Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

765 lines
19 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //===========================================================================//
  7. #include <vgui/IScheme.h>
  8. #include <vgui/Cursor.h>
  9. #include <vgui/IInput.h>
  10. #include <vgui_controls/Splitter.h>
  11. #include "tier1/KeyValues.h"
  12. #include <limits.h>
  13. // memdbgon must be the last include file in a .cpp file!!!
  14. #include "tier0/memdbgon.h"
  15. using namespace vgui;
  16. enum
  17. {
  18. SPLITTER_HANDLE_WIDTH = 4
  19. };
  20. //-----------------------------------------------------------------------------
  21. // Splitter handle
  22. //-----------------------------------------------------------------------------
  23. namespace vgui
  24. {
  25. class SplitterHandle : public Panel
  26. {
  27. DECLARE_CLASS_SIMPLE( SplitterHandle, Panel );
  28. public:
  29. SplitterHandle( Splitter *parent, const char *name, SplitterMode_t mode, int nIndex );
  30. ~SplitterHandle();
  31. virtual void ApplySchemeSettings( IScheme *pScheme );
  32. virtual void OnMousePressed( MouseCode code );
  33. virtual void OnMouseReleased( MouseCode code );
  34. virtual void OnCursorMoved( int x, int y );
  35. virtual void OnMouseDoublePressed( MouseCode code );
  36. private:
  37. SplitterMode_t m_nMode;
  38. int m_nIndex;
  39. bool m_bDragging;
  40. };
  41. } // end namespace vgui
  42. //-----------------------------------------------------------------------------
  43. // Purpose: Constructor
  44. //-----------------------------------------------------------------------------
  45. SplitterHandle::SplitterHandle( Splitter *parent, const char *name, SplitterMode_t mode, int nIndex ) : BaseClass( parent, name )
  46. {
  47. int w, h;
  48. parent->GetSize( w, h );
  49. if ( mode == SPLITTER_MODE_HORIZONTAL )
  50. {
  51. SetSize( w, SPLITTER_HANDLE_WIDTH );
  52. SetCursor( dc_sizens );
  53. }
  54. else
  55. {
  56. SetSize( SPLITTER_HANDLE_WIDTH, h );
  57. SetCursor( dc_sizewe );
  58. }
  59. SetVisible( true );
  60. SetPaintBackgroundEnabled( false );
  61. SetPaintEnabled( false );
  62. SetPaintBorderEnabled( true );
  63. m_bDragging = false;
  64. m_nIndex = nIndex;
  65. m_nMode = mode;
  66. }
  67. //-----------------------------------------------------------------------------
  68. // Purpose: Destructor
  69. //-----------------------------------------------------------------------------
  70. SplitterHandle::~SplitterHandle()
  71. {
  72. }
  73. //-----------------------------------------------------------------------------
  74. // Scheme settings
  75. //-----------------------------------------------------------------------------
  76. void SplitterHandle::ApplySchemeSettings(IScheme *pScheme)
  77. {
  78. // Cache off background color stored in SetSplitterColor
  79. Color c = GetBgColor();
  80. SetBorder(pScheme->GetBorder("ButtonDepressedBorder"));
  81. BaseClass::ApplySchemeSettings(pScheme);
  82. SetBgColor( c );
  83. }
  84. //-----------------------------------------------------------------------------
  85. // Capture mouse when dragging
  86. //-----------------------------------------------------------------------------
  87. void SplitterHandle::OnMousePressed(MouseCode code)
  88. {
  89. if ( !m_bDragging )
  90. {
  91. input()->SetMouseCapture(GetVPanel());
  92. m_bDragging = true;
  93. }
  94. }
  95. //-----------------------------------------------------------------------------
  96. // Release mouse capture when finished dragging
  97. //-----------------------------------------------------------------------------
  98. void SplitterHandle::OnMouseReleased(MouseCode code)
  99. {
  100. if ( m_bDragging )
  101. {
  102. input()->SetMouseCapture(NULL);
  103. m_bDragging = false;
  104. }
  105. }
  106. //-----------------------------------------------------------------------------
  107. // While dragging, update the splitter position
  108. //-----------------------------------------------------------------------------
  109. void SplitterHandle::OnCursorMoved(int x, int y)
  110. {
  111. if (m_bDragging)
  112. {
  113. input()->GetCursorPos( x, y );
  114. Splitter *pSplitter = assert_cast<Splitter*>( GetParent() );
  115. pSplitter->ScreenToLocal( x,y );
  116. pSplitter->SetSplitterPosition( m_nIndex, (m_nMode == SPLITTER_MODE_HORIZONTAL) ? y : x );
  117. }
  118. }
  119. //-----------------------------------------------------------------------------
  120. // Double-click: make both panels on either side of the splitter equal size
  121. //-----------------------------------------------------------------------------
  122. void SplitterHandle::OnMouseDoublePressed( MouseCode code )
  123. {
  124. Splitter *pSplitter = assert_cast<Splitter*>( GetParent() );
  125. pSplitter->EvenlyRespaceSplitters();
  126. }
  127. //-----------------------------------------------------------------------------
  128. // Returns a panel that chains user configs
  129. //-----------------------------------------------------------------------------
  130. namespace vgui
  131. {
  132. class SplitterChildPanel : public EditablePanel
  133. {
  134. DECLARE_CLASS_SIMPLE( SplitterChildPanel, EditablePanel );
  135. public:
  136. SplitterChildPanel( Panel *parent, const char *panelName ) : BaseClass( parent, panelName )
  137. {
  138. SetPaintBackgroundEnabled( false );
  139. SetPaintEnabled( false );
  140. SetPaintBorderEnabled( false );
  141. }
  142. virtual ~SplitterChildPanel() {}
  143. // Children may have user config settings
  144. bool HasUserConfigSettings()
  145. {
  146. return true;
  147. }
  148. };
  149. } // end namespace vgui
  150. //-----------------------------------------------------------------------------
  151. //
  152. // Splitter panel
  153. //
  154. //-----------------------------------------------------------------------------
  155. vgui::Panel *Splitter_V_Factory()
  156. {
  157. return new Splitter( NULL, NULL, SPLITTER_MODE_VERTICAL, 1 );
  158. }
  159. vgui::Panel *Splitter_H_Factory()
  160. {
  161. return new Splitter( NULL, NULL, SPLITTER_MODE_HORIZONTAL, 1 );
  162. }
  163. //-----------------------------------------------------------------------------
  164. // Purpose: Constructor
  165. //-----------------------------------------------------------------------------
  166. Splitter::Splitter( Panel *parent, const char *name, SplitterMode_t mode, int nCount ) : BaseClass( parent, name )
  167. {
  168. Assert( nCount >= 1 );
  169. m_Mode = mode;
  170. SetPaintBackgroundEnabled( false );
  171. SetPaintEnabled( false );
  172. SetPaintBorderEnabled( false );
  173. RecreateSplitters( nCount );
  174. EvenlyRespaceSplitters();
  175. }
  176. //-----------------------------------------------------------------------------
  177. // Purpose: Destructor
  178. //-----------------------------------------------------------------------------
  179. Splitter::~Splitter()
  180. {
  181. m_Splitters.RemoveAll();
  182. }
  183. void Splitter::RecreateSplitters( int nCount )
  184. {
  185. int i;
  186. int c = m_Splitters.Count();
  187. for ( i = 0; i < c; ++i )
  188. {
  189. delete m_Splitters[ i ].m_pPanel;
  190. delete m_Splitters[ i ].m_pHandle;
  191. }
  192. m_Splitters.RemoveAll();
  193. for ( i = 0; i < (nCount + 1); ++i )
  194. {
  195. char pBuffer[512];
  196. Q_snprintf( pBuffer, sizeof(pBuffer), "child%d", i );
  197. int nIndex = m_Splitters.AddToTail( );
  198. SplitterChildPanel *pEditablePanel = new SplitterChildPanel( this, pBuffer );
  199. m_Splitters[nIndex].m_pPanel = pEditablePanel;
  200. m_Splitters[nIndex].m_bLocked = false;
  201. m_Splitters[nIndex].m_nLockedSize = 0;
  202. }
  203. // We do this in 2 loops so that the first N children are actual child panels
  204. for ( i = 0; i < nCount; ++i )
  205. {
  206. SplitterHandle *pHandle = new SplitterHandle( this, "SplitterHandle", m_Mode, i );
  207. m_Splitters[i].m_pHandle = pHandle;
  208. pHandle->MoveToFront();
  209. }
  210. m_Splitters[nCount].m_pHandle = NULL;
  211. }
  212. //-----------------------------------------------------------------------------
  213. // Sets the splitter color
  214. //-----------------------------------------------------------------------------
  215. void Splitter::SetSplitterColor( Color c )
  216. {
  217. int nCount = m_Splitters.Count() - 1;
  218. if ( c.a() != 0 )
  219. {
  220. for ( int i = 0; i < nCount; ++i )
  221. {
  222. m_Splitters[i].m_pHandle->SetBgColor( c );
  223. m_Splitters[i].m_pHandle->SetPaintBackgroundEnabled( true );
  224. }
  225. }
  226. else
  227. {
  228. for ( int i = 0; i < nCount; ++i )
  229. {
  230. m_Splitters[i].m_pHandle->SetPaintBackgroundEnabled( false );
  231. }
  232. }
  233. }
  234. //-----------------------------------------------------------------------------
  235. // Enables borders on the splitters
  236. //-----------------------------------------------------------------------------
  237. void Splitter::EnableBorders( bool bEnable )
  238. {
  239. int nCount = m_Splitters.Count() - 1;
  240. for ( int i = 0; i < nCount; ++i )
  241. {
  242. m_Splitters[i].m_pHandle->SetPaintBorderEnabled( bEnable );
  243. }
  244. }
  245. //-----------------------------------------------------------------------------
  246. // controls splitters
  247. //-----------------------------------------------------------------------------
  248. int Splitter::GetSplitterCount() const
  249. {
  250. return m_Splitters.Count() - 1;
  251. }
  252. //-----------------------------------------------------------------------------
  253. // controls splitters
  254. //-----------------------------------------------------------------------------
  255. int Splitter::GetSubPanelCount() const
  256. {
  257. return m_Splitters.Count();
  258. }
  259. //-----------------------------------------------------------------------------
  260. // Purpose: Applies resouce settings
  261. //-----------------------------------------------------------------------------
  262. void Splitter::ApplySettings(KeyValues *inResourceData)
  263. {
  264. BaseClass::ApplySettings(inResourceData);
  265. // Look for splitter positions
  266. int nSplitterCount = GetSplitterCount();
  267. for ( int i = 0; i < nSplitterCount; ++i )
  268. {
  269. char pBuffer[512];
  270. Q_snprintf( pBuffer, sizeof(pBuffer), "splitter%d", i );
  271. int nSplitterPos = inResourceData->GetInt( pBuffer , -1 );
  272. if ( nSplitterPos >= 0 )
  273. {
  274. SetSplitterPosition( i, nSplitterPos );
  275. }
  276. }
  277. }
  278. //-----------------------------------------------------------------------------
  279. // Purpose:
  280. //-----------------------------------------------------------------------------
  281. int Splitter::GetPosRange()
  282. {
  283. int w, h;
  284. GetSize( w, h );
  285. int nPosRange = (m_Mode == SPLITTER_MODE_HORIZONTAL) ? h : w;
  286. return nPosRange;
  287. }
  288. //-----------------------------------------------------------------------------
  289. // Locks the size of a particular child in pixels.
  290. //-----------------------------------------------------------------------------
  291. void Splitter::LockChildSize( int nChildIndex, int nSize )
  292. {
  293. Assert( nChildIndex < m_Splitters.Count() );
  294. SplitterInfo_t &info = m_Splitters[nChildIndex];
  295. nSize += SPLITTER_HANDLE_WIDTH;
  296. if ( !info.m_bLocked || (info.m_nLockedSize != nSize) )
  297. {
  298. float flPrevPos = (nChildIndex > 0) ? m_Splitters[nChildIndex-1].m_flPos : 0.0f;
  299. float flOldSize = info.m_flPos - flPrevPos;
  300. float flDelta = nSize - flOldSize;
  301. int nCount = m_Splitters.Count();
  302. for ( int i = nChildIndex; i < nCount-1; ++i )
  303. {
  304. m_Splitters[i].m_flPos += flDelta;
  305. }
  306. m_Splitters[nCount-1].m_flPos = GetPosRange();
  307. info.m_bLocked = true;
  308. info.m_nLockedSize = nSize;
  309. InvalidateLayout();
  310. }
  311. }
  312. void Splitter::UnlockChildSize( int nChildIndex )
  313. {
  314. Assert( nChildIndex < m_Splitters.Count() );
  315. SplitterInfo_t &info = m_Splitters[nChildIndex];
  316. if ( info.m_bLocked )
  317. {
  318. info.m_bLocked = false;
  319. float flPrevPos = (nChildIndex > 0) ? m_Splitters[nChildIndex-1].m_flPos : 0.0f;
  320. float flBelowSize = GetPosRange() - flPrevPos;
  321. int nLockedSize = ComputeLockedSize( nChildIndex + 1 );
  322. int nUnlockedCount = 1;
  323. int nCount = m_Splitters.Count();
  324. for ( int i = nChildIndex + 1; i < nCount; ++i )
  325. {
  326. if ( !m_Splitters[i].m_bLocked )
  327. {
  328. ++nUnlockedCount;
  329. }
  330. }
  331. float flUnlockedSize = ( flBelowSize - nLockedSize ) / nUnlockedCount;
  332. for ( int i = nChildIndex; i < nCount; ++i )
  333. {
  334. if ( !m_Splitters[i].m_bLocked )
  335. {
  336. m_Splitters[i].m_flPos = flPrevPos + flUnlockedSize;
  337. }
  338. else
  339. {
  340. m_Splitters[i].m_flPos = flPrevPos + m_Splitters[i].m_nLockedSize;
  341. }
  342. flPrevPos = m_Splitters[i].m_flPos;
  343. }
  344. InvalidateLayout();
  345. }
  346. }
  347. //-----------------------------------------------------------------------------
  348. // Called when size changes
  349. //-----------------------------------------------------------------------------
  350. void Splitter::OnSizeChanged( int newWide, int newTall )
  351. {
  352. BaseClass::OnSizeChanged( newWide, newTall );
  353. // Don't resize if it's degenerate and won't show up anyway...
  354. if ( newTall <= 0 || newWide <= 0 )
  355. return;
  356. int nLockedSize = 0;
  357. float flUnlockedSize = 0.0f;
  358. int nCount = m_Splitters.Count();
  359. float flLastPos = 0.0f;
  360. int nUnlockedCount = 0;
  361. for ( int i = 0; i < nCount; ++i )
  362. {
  363. SplitterInfo_t &info = m_Splitters[i];
  364. if ( info.m_bLocked )
  365. {
  366. nLockedSize += info.m_nLockedSize;
  367. }
  368. else
  369. {
  370. ++nUnlockedCount;
  371. flUnlockedSize += info.m_flPos - flLastPos;
  372. }
  373. flLastPos = info.m_flPos;
  374. }
  375. int nNewTotalSize = (m_Mode == SPLITTER_MODE_HORIZONTAL) ? newTall : newWide;
  376. int nNewUnlockedSize = nNewTotalSize - nLockedSize;
  377. if ( nNewUnlockedSize < nUnlockedCount * SPLITTER_HANDLE_WIDTH )
  378. {
  379. nNewUnlockedSize = nUnlockedCount * SPLITTER_HANDLE_WIDTH;
  380. }
  381. float flRatio = nNewUnlockedSize / flUnlockedSize;
  382. float flLastPrevPos = 0.0f;
  383. flLastPos = 0.0f;
  384. for ( int i = 0; i < nCount - 1; ++i )
  385. {
  386. SplitterInfo_t &info = m_Splitters[i];
  387. if ( info.m_bLocked )
  388. {
  389. flLastPrevPos = info.m_flPos;
  390. info.m_flPos = flLastPos + info.m_nLockedSize;
  391. }
  392. else
  393. {
  394. float flNewSize = info.m_flPos - flLastPrevPos;
  395. flNewSize *= flRatio;
  396. flLastPrevPos = info.m_flPos;
  397. info.m_flPos = flLastPos + flNewSize;
  398. }
  399. flLastPos = info.m_flPos;
  400. }
  401. // Clamp the bottom to 1.0
  402. m_Splitters[nCount-1].m_flPos = nNewTotalSize;
  403. }
  404. //-----------------------------------------------------------------------------
  405. // Splitter position
  406. //-----------------------------------------------------------------------------
  407. int Splitter::GetSplitterPosition( int nIndex )
  408. {
  409. return (int)( m_Splitters[nIndex].m_flPos + 0.5f );
  410. }
  411. void Splitter::SetSplitterPosition( int nIndex, int nPos )
  412. {
  413. int nPosRange = GetPosRange();
  414. if ( nPosRange == 0 )
  415. return;
  416. // If we're locked to a sibling, move the previous sibling first
  417. while ( ( nIndex >= 0 ) && m_Splitters[nIndex].m_bLocked )
  418. {
  419. nPos -= m_Splitters[nIndex].m_nLockedSize;
  420. --nIndex;
  421. }
  422. if ( nIndex < 0 )
  423. return;
  424. // Clamp to the valid positional range
  425. int i;
  426. int nMinPos = 0;
  427. for ( i = 0; i < nIndex; ++i )
  428. {
  429. if ( !m_Splitters[i].m_bLocked )
  430. {
  431. nMinPos += SPLITTER_HANDLE_WIDTH;
  432. }
  433. else
  434. {
  435. nMinPos += m_Splitters[i].m_nLockedSize;
  436. }
  437. }
  438. int nMaxPos = nPosRange - SPLITTER_HANDLE_WIDTH;
  439. int c = GetSplitterCount();
  440. for ( i = nIndex + 1; i < c; ++i )
  441. {
  442. if ( !m_Splitters[i].m_bLocked )
  443. {
  444. nMaxPos -= SPLITTER_HANDLE_WIDTH;
  445. }
  446. else
  447. {
  448. nMaxPos -= m_Splitters[i].m_nLockedSize;
  449. }
  450. }
  451. nPos = clamp( nPos, nMinPos, nMaxPos );
  452. m_Splitters[nIndex].m_flPos = nPos;
  453. int p = nPos;
  454. for ( i = nIndex - 1 ; i >= 0; --i )
  455. {
  456. int nMinPrevPos;
  457. int nMaxPrevPos;
  458. if ( !m_Splitters[i+1].m_bLocked )
  459. {
  460. nMinPrevPos = -INT_MAX;
  461. nMaxPrevPos = nPos - SPLITTER_HANDLE_WIDTH;
  462. }
  463. else
  464. {
  465. nMinPrevPos = nMaxPrevPos = p - m_Splitters[i+1].m_nLockedSize;
  466. }
  467. int nCurPos = GetSplitterPosition( i );
  468. if ( nMaxPrevPos < nCurPos || nMinPrevPos > nCurPos )
  469. {
  470. m_Splitters[ i ].m_flPos = nMaxPrevPos;
  471. p = nMaxPrevPos;
  472. }
  473. else
  474. {
  475. p = m_Splitters[ i ].m_flPos;
  476. }
  477. }
  478. for ( i = nIndex + 1 ; i < c; ++i )
  479. {
  480. int nMinNextPos;
  481. int nMaxNextPos;
  482. if ( !m_Splitters[i].m_bLocked )
  483. {
  484. nMinNextPos = nPos + SPLITTER_HANDLE_WIDTH;
  485. nMaxNextPos = INT_MAX;
  486. }
  487. else
  488. {
  489. nMinNextPos = nMaxNextPos = nPos + m_Splitters[i].m_nLockedSize;
  490. }
  491. int nCurPos = GetSplitterPosition( i );
  492. if ( nMinNextPos > nCurPos || nMaxNextPos < nCurPos )
  493. {
  494. m_Splitters[ i ].m_flPos = nMinNextPos;
  495. nPos = nMinNextPos;
  496. }
  497. else
  498. {
  499. nPos = m_Splitters[ i ].m_flPos;
  500. }
  501. }
  502. InvalidateLayout();
  503. }
  504. //-----------------------------------------------------------------------------
  505. // Computes the locked size
  506. //-----------------------------------------------------------------------------
  507. int Splitter::ComputeLockedSize( int nStartingIndex )
  508. {
  509. int nLockedSize = 0;
  510. int nCount = m_Splitters.Count();
  511. for ( int i = nStartingIndex; i < nCount; ++i )
  512. {
  513. if ( m_Splitters[i].m_bLocked )
  514. {
  515. nLockedSize += m_Splitters[i].m_nLockedSize;
  516. }
  517. }
  518. return nLockedSize;
  519. }
  520. //-----------------------------------------------------------------------------
  521. // Evenly respaces all the splitters
  522. //-----------------------------------------------------------------------------
  523. void Splitter::EvenlyRespaceSplitters( )
  524. {
  525. int nSplitterCount = GetSubPanelCount();
  526. if ( nSplitterCount == 0 )
  527. return;
  528. int nLockedSize = ComputeLockedSize( 0 );
  529. float flUnlockedSize = (float)( GetPosRange() - nLockedSize );
  530. float flDPos = flUnlockedSize / (float)nSplitterCount;
  531. if ( flDPos < SPLITTER_HANDLE_WIDTH )
  532. {
  533. flDPos = SPLITTER_HANDLE_WIDTH;
  534. }
  535. float flPos = 0.0f;
  536. for ( int i = 0; i < nSplitterCount; ++i )
  537. {
  538. if ( !m_Splitters[i].m_bLocked )
  539. {
  540. flPos += flDPos;
  541. }
  542. else
  543. {
  544. flPos += m_Splitters[i].m_nLockedSize;
  545. }
  546. m_Splitters[i].m_flPos = flPos;
  547. }
  548. InvalidateLayout();
  549. }
  550. void Splitter::RespaceSplitters( float *flFractions )
  551. {
  552. int nSplitterCount = GetSubPanelCount();
  553. if ( nSplitterCount == 0 )
  554. return;
  555. float flPos = 0.0f;
  556. int nPosRange = GetPosRange();
  557. for ( int i = 0; i < nSplitterCount; ++i )
  558. {
  559. flPos += flFractions[i];
  560. m_Splitters[i].m_flPos = flPos * nPosRange;
  561. }
  562. Assert( flPos == 1.0f );
  563. InvalidateLayout();
  564. }
  565. //-----------------------------------------------------------------------------
  566. // Purpose: sets user settings
  567. //-----------------------------------------------------------------------------
  568. void Splitter::ApplyUserConfigSettings(KeyValues *userConfig)
  569. {
  570. BaseClass::ApplyUserConfigSettings( userConfig );
  571. // read the splitter sizes
  572. int c = m_Splitters.Count();
  573. float *pFractions = (float*)_alloca( c * sizeof(float) );
  574. float flTotalSize = 0.0f;
  575. for ( int i = 0; i < c; i++ )
  576. {
  577. char name[128];
  578. _snprintf(name, sizeof(name), "%d_splitter_pos", i);
  579. pFractions[i] = userConfig->GetFloat( name, flTotalSize + SPLITTER_HANDLE_WIDTH + 1 );
  580. flTotalSize = pFractions[i];
  581. }
  582. if ( flTotalSize != 0.0f )
  583. {
  584. int nPosRange = GetPosRange();
  585. for ( int i = 0; i < c; ++i )
  586. {
  587. pFractions[i] /= flTotalSize;
  588. m_Splitters[i].m_flPos = pFractions[i] * nPosRange;
  589. }
  590. }
  591. }
  592. //-----------------------------------------------------------------------------
  593. // Purpose: returns user config settings for this control
  594. //-----------------------------------------------------------------------------
  595. void Splitter::GetUserConfigSettings(KeyValues *userConfig)
  596. {
  597. BaseClass::GetUserConfigSettings( userConfig );
  598. // save which columns are hidden
  599. int c = m_Splitters.Count();
  600. for ( int i = 0 ; i < c; i++ )
  601. {
  602. char name[128];
  603. _snprintf(name, sizeof(name), "%d_splitter_pos", i);
  604. userConfig->SetFloat( name, m_Splitters[i].m_flPos );
  605. }
  606. }
  607. //-----------------------------------------------------------------------------
  608. // Called to perform layout
  609. //-----------------------------------------------------------------------------
  610. void Splitter::PerformLayout( )
  611. {
  612. BaseClass::PerformLayout();
  613. int nSplitterCount = GetSubPanelCount();
  614. if ( nSplitterCount == 0 )
  615. return;
  616. int w, h;
  617. GetSize( w, h );
  618. int nLastPos = 0;
  619. for ( int i = 0; i < nSplitterCount; ++i )
  620. {
  621. Panel *pChild = m_Splitters[i].m_pPanel;
  622. SplitterHandle *pHandle = m_Splitters[i].m_pHandle;
  623. int nSplitterPos = (int)( m_Splitters[i].m_flPos + 0.5f );
  624. if ( m_Mode == SPLITTER_MODE_HORIZONTAL )
  625. {
  626. pChild->SetPos( 0, nLastPos );
  627. pChild->SetSize( w, nSplitterPos - nLastPos );
  628. if ( pHandle )
  629. {
  630. pHandle->SetPos( 0, nSplitterPos );
  631. pHandle->SetSize( w, SPLITTER_HANDLE_WIDTH );
  632. }
  633. }
  634. else
  635. {
  636. pChild->SetPos( nLastPos, 0 );
  637. pChild->SetSize( nSplitterPos - nLastPos, h );
  638. if ( pHandle )
  639. {
  640. pHandle->SetPos( nSplitterPos, 0 );
  641. pHandle->SetSize( SPLITTER_HANDLE_WIDTH, h );
  642. }
  643. }
  644. nLastPos = nSplitterPos + SPLITTER_HANDLE_WIDTH;
  645. }
  646. }
  647. //-----------------------------------------------------------------------------
  648. // Purpose:
  649. //-----------------------------------------------------------------------------
  650. void Splitter::GetSettings( KeyValues *outResourceData )
  651. {
  652. BaseClass::GetSettings( outResourceData );
  653. }