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.

589 lines
14 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. //=============================================================================
  4. // Valve includes
  5. #include "tier1/KeyValues.h"
  6. #include "vgui/MouseCode.h"
  7. #include "vgui/IInput.h"
  8. #include "vgui/IScheme.h"
  9. #include "vgui/ISurface.h"
  10. #include "vgui_controls/EditablePanel.h"
  11. #include "vgui_controls/ScrollBar.h"
  12. #include "vgui_controls/Label.h"
  13. #include "vgui_controls/Button.h"
  14. #include "vgui_controls/Controls.h"
  15. // Local includes
  16. #include "dualpanellist.h"
  17. // Last include
  18. #include "tier0/memdbgon.h"
  19. //=============================================================================
  20. //
  21. //=============================================================================
  22. CDualPanelList::CDualPanelList( vgui::Panel *pParent, char const *pszPanelName )
  23. : vgui::Panel( pParent, pszPanelName )
  24. , m_pScrollBar( NULL )
  25. {
  26. SetBounds( 0, 0, 100, 100 );
  27. if ( false )
  28. {
  29. m_pScrollBar = new vgui::ScrollBar( this, "CDualPanelListVScroll", true );
  30. m_pScrollBar->AddActionSignalTarget( this );
  31. }
  32. m_pPanelEmbedded = new vgui::EditablePanel( this, "PanelListEmbedded" );
  33. m_pPanelEmbedded->SetBounds( 0, 0, 20, 20 );
  34. m_pPanelEmbedded->SetPaintBackgroundEnabled( false );
  35. m_pPanelEmbedded->SetPaintBorderEnabled( false );
  36. m_iFirstColumnWidth = 100; // default width
  37. m_nNumColumns = 1; // 1 column by default
  38. if ( false && IsProportional() )
  39. {
  40. m_iDefaultHeight = vgui::scheme()->GetProportionalScaledValueEx( GetScheme(), DEFAULT_HEIGHT );
  41. m_iPanelBuffer = vgui::scheme()->GetProportionalScaledValueEx( GetScheme(), PANELBUFFER );
  42. }
  43. else
  44. {
  45. m_iDefaultHeight = DEFAULT_HEIGHT;
  46. m_iPanelBuffer = PANELBUFFER;
  47. }
  48. }
  49. //-----------------------------------------------------------------------------
  50. //
  51. //-----------------------------------------------------------------------------
  52. CDualPanelList::~CDualPanelList()
  53. {
  54. // free data from table
  55. DeleteAllItems();
  56. }
  57. //-----------------------------------------------------------------------------
  58. //
  59. //-----------------------------------------------------------------------------
  60. void CDualPanelList::SetVerticalBufferPixels( int buffer )
  61. {
  62. m_iPanelBuffer = buffer;
  63. InvalidateLayout();
  64. }
  65. //-----------------------------------------------------------------------------
  66. //
  67. //-----------------------------------------------------------------------------
  68. int CDualPanelList::ComputeVPixelsNeeded()
  69. {
  70. int iCurrentItem = 0;
  71. int iLargestH = 0;
  72. int nPixels = 0;
  73. for ( int i = 0; i < m_SortedItems.Count(); i++ )
  74. {
  75. Panel *pPanel = m_DataItems[ m_SortedItems[i] ].panel;
  76. if ( !pPanel || !pPanel->IsVisible() )
  77. continue;
  78. if ( pPanel->IsLayoutInvalid() )
  79. {
  80. pPanel->InvalidateLayout( true );
  81. }
  82. int iCurrentColumn = iCurrentItem % m_nNumColumns;
  83. int w, h;
  84. pPanel->GetSize( w, h );
  85. if ( iLargestH < h )
  86. iLargestH = h;
  87. if ( iCurrentColumn == 0 )
  88. nPixels += m_iPanelBuffer; // add in buffer. between rows.
  89. if ( iCurrentColumn >= m_nNumColumns - 1 )
  90. {
  91. nPixels += iLargestH;
  92. iLargestH = 0;
  93. }
  94. iCurrentItem++;
  95. }
  96. // Add in remaining largest height
  97. nPixels += iLargestH;
  98. nPixels += m_iPanelBuffer; // add in buffer below last item
  99. /*
  100. nPixels = 0;
  101. for ( int i = 0; i < m_SortedItems.Count(); ++i )
  102. {
  103. Panel *pPanel = m_DataItems[ m_SortedItems[i] ].panel;
  104. if ( !pPanel )
  105. continue;
  106. int nWide = 0;
  107. int nHeight = 0;
  108. pPanel->GetSize( nWide, nHeight );
  109. nPixels += nHeight;
  110. }
  111. */
  112. return nPixels;
  113. }
  114. //-----------------------------------------------------------------------------
  115. //
  116. //-----------------------------------------------------------------------------
  117. vgui::Panel *CDualPanelList::GetCellRenderer( int row )
  118. {
  119. if ( !m_SortedItems.IsValidIndex(row) )
  120. return NULL;
  121. Panel *panel = m_DataItems[ m_SortedItems[row] ].panel;
  122. return panel;
  123. }
  124. //-----------------------------------------------------------------------------
  125. //
  126. //-----------------------------------------------------------------------------
  127. int CDualPanelList::AddItem( vgui::Panel *labelPanel, vgui::Panel *panel)
  128. {
  129. Assert(panel);
  130. if ( labelPanel )
  131. {
  132. labelPanel->SetParent( m_pPanelEmbedded );
  133. }
  134. panel->SetParent( m_pPanelEmbedded );
  135. int itemID = m_DataItems.AddToTail();
  136. CDataItem &newitem = m_DataItems[itemID];
  137. newitem.labelPanel = labelPanel;
  138. newitem.panel = panel;
  139. m_SortedItems.AddToTail(itemID);
  140. InvalidateLayout();
  141. return itemID;
  142. }
  143. //-----------------------------------------------------------------------------
  144. //
  145. //-----------------------------------------------------------------------------
  146. int CDualPanelList::GetItemCount() const
  147. {
  148. return m_DataItems.Count();
  149. }
  150. //-----------------------------------------------------------------------------
  151. //
  152. //-----------------------------------------------------------------------------
  153. int CDualPanelList::GetItemIDFromRow( int nRow ) const
  154. {
  155. if ( nRow < 0 || nRow >= GetItemCount() )
  156. return m_DataItems.InvalidIndex();
  157. return m_SortedItems[ nRow ];
  158. }
  159. //-----------------------------------------------------------------------------
  160. //
  161. //-----------------------------------------------------------------------------
  162. int CDualPanelList::FirstItem() const
  163. {
  164. return m_DataItems.Head();
  165. }
  166. //-----------------------------------------------------------------------------
  167. //
  168. //-----------------------------------------------------------------------------
  169. int CDualPanelList::NextItem( int nItemID ) const
  170. {
  171. return m_DataItems.Next( nItemID );
  172. }
  173. //-----------------------------------------------------------------------------
  174. //
  175. //-----------------------------------------------------------------------------
  176. int CDualPanelList::InvalidItemID() const
  177. {
  178. return m_DataItems.InvalidIndex();
  179. }
  180. //-----------------------------------------------------------------------------
  181. //
  182. //-----------------------------------------------------------------------------
  183. vgui::Panel *CDualPanelList::GetItemLabel(int nItemID)
  184. {
  185. if ( !m_DataItems.IsValidIndex( nItemID ) )
  186. return NULL;
  187. return m_DataItems[nItemID].labelPanel;
  188. }
  189. //-----------------------------------------------------------------------------
  190. //
  191. //-----------------------------------------------------------------------------
  192. vgui::Panel *CDualPanelList::GetItemPanel( int nItemID )
  193. {
  194. if ( !m_DataItems.IsValidIndex( nItemID ) )
  195. return NULL;
  196. return m_DataItems[nItemID].panel;
  197. }
  198. //-----------------------------------------------------------------------------
  199. //
  200. //-----------------------------------------------------------------------------
  201. bool CDualPanelList::IsItemVisible( int nItemID ) const
  202. {
  203. if ( !m_DataItems.IsValidIndex( nItemID ) )
  204. return true;
  205. return m_DataItems[nItemID].IsVisible();
  206. }
  207. //-----------------------------------------------------------------------------
  208. //
  209. //-----------------------------------------------------------------------------
  210. void CDualPanelList::SetItemVisible( int nItemID, bool bVisible )
  211. {
  212. if ( !m_DataItems.IsValidIndex( nItemID ) )
  213. return;
  214. m_DataItems[nItemID].SetVisible( bVisible );
  215. InvalidateLayout();
  216. }
  217. //-----------------------------------------------------------------------------
  218. //
  219. //-----------------------------------------------------------------------------
  220. void CDualPanelList::RemoveItem( int nItemID )
  221. {
  222. if ( !m_DataItems.IsValidIndex( nItemID ) )
  223. return;
  224. CDataItem &item = m_DataItems[nItemID];
  225. if ( item.panel )
  226. {
  227. item.panel->MarkForDeletion();
  228. }
  229. if ( item.labelPanel )
  230. {
  231. item.labelPanel->MarkForDeletion();
  232. }
  233. m_DataItems.Remove( nItemID );
  234. m_SortedItems.FindAndRemove( nItemID );
  235. InvalidateLayout();
  236. }
  237. //-----------------------------------------------------------------------------
  238. //
  239. //-----------------------------------------------------------------------------
  240. void CDualPanelList::DeleteAllItems()
  241. {
  242. FOR_EACH_LL( m_DataItems, i )
  243. {
  244. if ( m_DataItems[i].panel )
  245. {
  246. delete m_DataItems[i].panel;
  247. }
  248. }
  249. m_DataItems.RemoveAll();
  250. m_SortedItems.RemoveAll();
  251. InvalidateLayout();
  252. }
  253. //-----------------------------------------------------------------------------
  254. //
  255. //-----------------------------------------------------------------------------
  256. void CDualPanelList::RemoveAll()
  257. {
  258. m_DataItems.RemoveAll();
  259. m_SortedItems.RemoveAll();
  260. // m_pScrollBar->SetValue( 0 );
  261. InvalidateLayout();
  262. }
  263. //-----------------------------------------------------------------------------
  264. //
  265. //-----------------------------------------------------------------------------
  266. void CDualPanelList::OnSizeChanged( int nWide, int nTall )
  267. {
  268. BaseClass::OnSizeChanged( nWide, nTall );
  269. InvalidateLayout();
  270. Repaint();
  271. }
  272. //-----------------------------------------------------------------------------
  273. //
  274. //-----------------------------------------------------------------------------
  275. void CDualPanelList::PerformLayout()
  276. {
  277. int nWide, nTall;
  278. GetSize( nWide, nTall );
  279. int vpixels = ComputeVPixelsNeeded();
  280. int top = 0;
  281. if ( m_pScrollBar )
  282. {
  283. m_pScrollBar->SetRange( 0, vpixels );
  284. m_pScrollBar->SetRangeWindow( nTall );
  285. m_pScrollBar->SetButtonPressedScrollValue( nTall / 4 ); // standard height of labels/buttons etc.
  286. m_pScrollBar->SetPos( nWide - m_pScrollBar->GetWide() - 2, 0 );
  287. m_pScrollBar->SetSize( m_pScrollBar->GetWide(), nTall - 2 );
  288. top = m_pScrollBar->GetValue();
  289. }
  290. m_pPanelEmbedded->SetPos( 1, -top );
  291. if ( m_pScrollBar )
  292. {
  293. m_pPanelEmbedded->SetSize( nWide - m_pScrollBar->GetWide() - 2, vpixels );
  294. }
  295. else
  296. {
  297. m_pPanelEmbedded->SetSize( nWide - 2, vpixels );
  298. }
  299. SetSize( nWide, vpixels );
  300. /*
  301. bool bScrollbarVisible = true;
  302. // If we're supposed to automatically hide the scrollbar when unnecessary, check it now
  303. if ( m_bAutoHideScrollbar )
  304. {
  305. bScrollbarVisible = (m_pPanelEmbedded->GetTall() > nTall);
  306. }
  307. m_pScrollBar->SetVisible( bScrollbarVisible );
  308. */
  309. // Now lay out the controls on the embedded panel
  310. int y = 0;
  311. int h = 0;
  312. int totalh = 0;
  313. int xpos = m_iFirstColumnWidth + m_iPanelBuffer;
  314. int iColumnWidth = ( nWide - xpos - 12 ) / m_nNumColumns;
  315. if ( m_pScrollBar )
  316. {
  317. iColumnWidth = ( nWide - xpos - m_pScrollBar->GetWide() - 12 ) / m_nNumColumns;
  318. }
  319. for ( int i = 0; i < m_SortedItems.Count(); i++ )
  320. {
  321. CDataItem &item = m_DataItems[ m_SortedItems[i] ];
  322. if ( !item.IsVisible() )
  323. continue;
  324. int iCurrentColumn = i % m_nNumColumns;
  325. // add in a little buffer between panels
  326. if ( iCurrentColumn == 0 )
  327. y += m_iPanelBuffer;
  328. if ( h < item.panel->GetTall() )
  329. h = item.panel->GetTall();
  330. if ( item.labelPanel )
  331. {
  332. item.labelPanel->SetBounds( 0, y, m_iFirstColumnWidth, item.panel->GetTall() );
  333. }
  334. item.panel->SetBounds( xpos + iCurrentColumn * iColumnWidth, y, iColumnWidth, item.panel->GetTall() );
  335. if ( iCurrentColumn >= m_nNumColumns - 1 )
  336. {
  337. y += h;
  338. totalh += h;
  339. h = 0;
  340. }
  341. }
  342. }
  343. //-----------------------------------------------------------------------------
  344. //
  345. //-----------------------------------------------------------------------------
  346. void CDualPanelList::ApplySchemeSettings( vgui::IScheme *pScheme )
  347. {
  348. BaseClass::ApplySchemeSettings( pScheme );
  349. SetBorder( pScheme->GetBorder( "ButtonDepressedBorder" ) );
  350. SetBgColor( GetSchemeColor( "ListPanel.BgColor", GetBgColor(), pScheme ) );
  351. }
  352. //-----------------------------------------------------------------------------
  353. //
  354. //-----------------------------------------------------------------------------
  355. void CDualPanelList::OnSliderMoved( int /* nPosition */ )
  356. {
  357. InvalidateLayout();
  358. Repaint();
  359. }
  360. /*
  361. //-----------------------------------------------------------------------------
  362. //
  363. //-----------------------------------------------------------------------------
  364. void CDualPanelList::MoveScrollBarToTop()
  365. {
  366. m_pScrollBar->SetValue( 0 );
  367. }
  368. */
  369. //-----------------------------------------------------------------------------
  370. //
  371. //-----------------------------------------------------------------------------
  372. void CDualPanelList::SetFirstColumnWidth( int nWidth )
  373. {
  374. m_iFirstColumnWidth = nWidth;
  375. }
  376. //-----------------------------------------------------------------------------
  377. //
  378. //-----------------------------------------------------------------------------
  379. int CDualPanelList::GetFirstColumnWidth()
  380. {
  381. return m_iFirstColumnWidth;
  382. }
  383. //-----------------------------------------------------------------------------
  384. //
  385. //-----------------------------------------------------------------------------
  386. void CDualPanelList::SetNumColumns( int nNumColumns )
  387. {
  388. m_nNumColumns = nNumColumns;
  389. }
  390. //-----------------------------------------------------------------------------
  391. //
  392. //-----------------------------------------------------------------------------
  393. int CDualPanelList::GetNumColumns()
  394. {
  395. return m_nNumColumns;
  396. }
  397. //-----------------------------------------------------------------------------
  398. //
  399. //-----------------------------------------------------------------------------
  400. void CDualPanelList::OnMouseWheeled( int nDelta )
  401. {
  402. if ( !m_pScrollBar )
  403. return;
  404. int nVal = m_pScrollBar->GetValue();
  405. nVal -= ( nDelta * DEFAULT_HEIGHT );
  406. m_pScrollBar->SetValue( nVal );
  407. }
  408. //-----------------------------------------------------------------------------
  409. //
  410. //-----------------------------------------------------------------------------
  411. void CDualPanelList::SetSelectedPanel( vgui::Panel *pPanel )
  412. {
  413. if ( pPanel != m_hSelectedItem )
  414. {
  415. // notify the panels of the selection change
  416. if ( m_hSelectedItem )
  417. {
  418. PostMessage( m_hSelectedItem.Get(), new KeyValues( "PanelSelected", "state", 0 ) );
  419. }
  420. if ( pPanel )
  421. {
  422. PostMessage( pPanel, new KeyValues( "PanelSelected", "state", 1 ) );
  423. }
  424. m_hSelectedItem = pPanel;
  425. }
  426. }
  427. //-----------------------------------------------------------------------------
  428. //
  429. //-----------------------------------------------------------------------------
  430. vgui::Panel *CDualPanelList::GetSelectedPanel()
  431. {
  432. return m_hSelectedItem;
  433. }
  434. //-----------------------------------------------------------------------------
  435. //
  436. //-----------------------------------------------------------------------------
  437. void CDualPanelList::ScrollToItem( int nItemNumber )
  438. {
  439. if ( !m_pScrollBar || !m_pScrollBar->IsVisible() )
  440. return;
  441. CDataItem& item = m_DataItems[ m_SortedItems[ nItemNumber ] ];
  442. if ( !item.panel )
  443. return;
  444. int x, y;
  445. item.panel->GetPos( x, y );
  446. int lx, ly;
  447. lx = x;
  448. ly = y;
  449. m_pPanelEmbedded->LocalToScreen( lx, ly );
  450. ScreenToLocal( lx, ly );
  451. int h = item.panel->GetTall();
  452. if ( ly >= 0 && ly + h < GetTall() )
  453. return;
  454. m_pScrollBar->SetValue( y );
  455. InvalidateLayout();
  456. }