Counter Strike : Global Offensive Source Code
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.

573 lines
16 KiB

  1. //========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "vgui/MouseCode.h"
  8. #include "vgui/IInput.h"
  9. #include "vgui/IScheme.h"
  10. #include "vgui/ISurface.h"
  11. #include "vgui_controls/EditablePanel.h"
  12. #include "vgui_controls/ScrollBar.h"
  13. #include "vgui_controls/Label.h"
  14. #include "vgui_controls/Button.h"
  15. #include "vgui_controls/Controls.h"
  16. #include "vgui_controls/PanelListPanel.h"
  17. #include "keyvalues.h"
  18. // memdbgon must be the last include file in a .cpp file!!!
  19. #include "tier0/memdbgon.h"
  20. using namespace vgui;
  21. //-----------------------------------------------------------------------------
  22. // Purpose: Constructor
  23. //-----------------------------------------------------------------------------
  24. PanelListPanel::PanelListPanel( vgui::Panel *parent, char const *panelName ) : Panel( parent, panelName )
  25. {
  26. SetBounds( 0, 0, 100, 100 );
  27. m_vbar = new ScrollBar(this, "PanelListPanelVScroll", true);
  28. m_vbar->SetVisible(false);
  29. m_vbar->AddActionSignalTarget( this );
  30. m_pPanelEmbedded = new EditablePanel(this, "PanelListEmbedded");
  31. m_pPanelEmbedded->SetBounds(0, 0, 20, 20);
  32. m_pPanelEmbedded->SetPaintBackgroundEnabled( false );
  33. m_pPanelEmbedded->SetPaintBorderEnabled(false);
  34. m_iFirstColumnWidth = 100; // default width
  35. m_iNumColumns = 1; // 1 column by default
  36. m_bShowScrollBar = true;
  37. m_bAllowMouseWheel = true;
  38. m_bOverrideChildPanelWidth = true;
  39. if ( IsProportional() )
  40. {
  41. m_iDefaultHeight = scheme()->GetProportionalScaledValueEx( GetScheme(), DEFAULT_HEIGHT );
  42. m_iPanelBuffer = scheme()->GetProportionalScaledValueEx( GetScheme(), PANELBUFFER );
  43. }
  44. else
  45. {
  46. m_iDefaultHeight = DEFAULT_HEIGHT;
  47. m_iPanelBuffer = PANELBUFFER;
  48. }
  49. }
  50. //-----------------------------------------------------------------------------
  51. // Purpose: Destructor
  52. //-----------------------------------------------------------------------------
  53. PanelListPanel::~PanelListPanel()
  54. {
  55. // free data from table
  56. DeleteAllItems();
  57. }
  58. void PanelListPanel::SetVerticalBufferPixels( int buffer )
  59. {
  60. m_iPanelBuffer = buffer;
  61. InvalidateLayout();
  62. }
  63. //-----------------------------------------------------------------------------
  64. // Purpose: counts the total vertical pixels
  65. //-----------------------------------------------------------------------------
  66. int PanelListPanel::ComputeVPixelsNeeded()
  67. {
  68. int iCurrentItem = 0;
  69. int iLargestH = 0;
  70. int pixels = 0;
  71. for ( int i = 0; i < m_SortedItems.Count(); i++ )
  72. {
  73. Panel *panel = m_DataItems[ m_SortedItems[i] ].panel;
  74. if ( !panel )
  75. continue;
  76. // Skip hidden items
  77. if ( !panel->IsVisible() )
  78. continue;
  79. int iCurrentColumn = iCurrentItem % m_iNumColumns;
  80. int w, h;
  81. panel->GetSize( w, h );
  82. if ( iLargestH < h )
  83. iLargestH = h;
  84. if ( iCurrentColumn == 0 )
  85. pixels += m_iPanelBuffer; // add in buffer. between rows.
  86. if ( iCurrentColumn >= m_iNumColumns - 1 )
  87. {
  88. pixels += iLargestH;
  89. iLargestH = 0;
  90. }
  91. iCurrentItem++;
  92. }
  93. // Add in remaining largest height
  94. pixels += iLargestH;
  95. pixels += m_iPanelBuffer; // add in buffer below last item
  96. return pixels;
  97. }
  98. //-----------------------------------------------------------------------------
  99. // Purpose: Returns the panel to use to render a cell
  100. //-----------------------------------------------------------------------------
  101. Panel *PanelListPanel::GetCellRenderer( int row )
  102. {
  103. if ( !m_SortedItems.IsValidIndex(row) )
  104. return NULL;
  105. Panel *panel = m_DataItems[ m_SortedItems[row] ].panel;
  106. return panel;
  107. }
  108. //-----------------------------------------------------------------------------
  109. // Purpose: adds an item to the view
  110. // data->GetName() is used to uniquely identify an item
  111. // data sub items are matched against column header name to be used in the table
  112. //-----------------------------------------------------------------------------
  113. int PanelListPanel::AddItem( Panel *labelPanel, Panel *panel)
  114. {
  115. Assert(panel);
  116. if ( labelPanel )
  117. {
  118. labelPanel->SetParent( m_pPanelEmbedded );
  119. }
  120. panel->SetParent( m_pPanelEmbedded );
  121. panel->SetVisible( true );
  122. int itemID = m_DataItems.AddToTail();
  123. DATAITEM &newitem = m_DataItems[itemID];
  124. newitem.labelPanel = labelPanel;
  125. newitem.panel = panel;
  126. m_SortedItems.AddToTail(itemID);
  127. InvalidateLayout();
  128. return itemID;
  129. }
  130. //-----------------------------------------------------------------------------
  131. // Purpose: iteration accessor
  132. //-----------------------------------------------------------------------------
  133. int PanelListPanel::GetItemCount() const
  134. {
  135. return m_DataItems.Count();
  136. }
  137. int PanelListPanel::GetItemIDFromRow( int nRow ) const
  138. {
  139. if ( nRow < 0 || nRow >= GetItemCount() )
  140. return m_DataItems.InvalidIndex();
  141. return m_SortedItems[ nRow ];
  142. }
  143. //-----------------------------------------------------------------------------
  144. // Purpose: Returns the number of visible item panels
  145. //-----------------------------------------------------------------------------
  146. int PanelListPanel::GetVisibleItemCount()
  147. {
  148. int iTotal = 0;
  149. for ( int i = 0 ; i < GetItemCount() ; ++i )
  150. {
  151. Panel *panel = GetItemPanel( i );
  152. if (panel && panel->IsVisible())
  153. iTotal++;
  154. }
  155. return iTotal;
  156. }
  157. //-----------------------------------------------------------------------------
  158. // Iteration. Use these until they return InvalidItemID to iterate all the items.
  159. //-----------------------------------------------------------------------------
  160. int PanelListPanel::FirstItem() const
  161. {
  162. return m_DataItems.Head();
  163. }
  164. int PanelListPanel::NextItem( int nItemID ) const
  165. {
  166. return m_DataItems.Next( nItemID );
  167. }
  168. int PanelListPanel::InvalidItemID() const
  169. {
  170. return m_DataItems.InvalidIndex( );
  171. }
  172. //-----------------------------------------------------------------------------
  173. // Purpose: returns label panel for this itemID
  174. //-----------------------------------------------------------------------------
  175. Panel *PanelListPanel::GetItemLabel(int itemID)
  176. {
  177. if ( !m_DataItems.IsValidIndex(itemID) )
  178. return NULL;
  179. return m_DataItems[itemID].labelPanel;
  180. }
  181. //-----------------------------------------------------------------------------
  182. // Purpose: returns label panel for this itemID
  183. //-----------------------------------------------------------------------------
  184. Panel *PanelListPanel::GetItemPanel(int itemID)
  185. {
  186. if ( !m_DataItems.IsValidIndex(itemID) )
  187. return NULL;
  188. return m_DataItems[itemID].panel;
  189. }
  190. //-----------------------------------------------------------------------------
  191. // Purpose:
  192. //-----------------------------------------------------------------------------
  193. void PanelListPanel::RemoveItem(int itemID)
  194. {
  195. if ( !m_DataItems.IsValidIndex(itemID) )
  196. return;
  197. DATAITEM &item = m_DataItems[itemID];
  198. if ( item.panel )
  199. {
  200. item.panel->MarkForDeletion();
  201. }
  202. if ( item.labelPanel )
  203. {
  204. item.labelPanel->MarkForDeletion();
  205. }
  206. m_DataItems.Remove(itemID);
  207. m_SortedItems.FindAndRemove(itemID);
  208. InvalidateLayout();
  209. }
  210. //-----------------------------------------------------------------------------
  211. // Purpose: clears and deletes all the memory used by the data items
  212. //-----------------------------------------------------------------------------
  213. void PanelListPanel::DeleteAllItems()
  214. {
  215. FOR_EACH_LL( m_DataItems, i )
  216. {
  217. if ( m_DataItems[i].panel )
  218. {
  219. delete m_DataItems[i].panel;
  220. }
  221. }
  222. m_DataItems.RemoveAll();
  223. m_SortedItems.RemoveAll();
  224. InvalidateLayout();
  225. }
  226. //-----------------------------------------------------------------------------
  227. // Purpose: clears and deletes all the memory used by the data items
  228. //-----------------------------------------------------------------------------
  229. void PanelListPanel::RemoveAll()
  230. {
  231. m_DataItems.RemoveAll();
  232. m_SortedItems.RemoveAll();
  233. // move the scrollbar to the top of the list
  234. m_vbar->SetValue(0);
  235. InvalidateLayout();
  236. }
  237. //-----------------------------------------------------------------------------
  238. // Purpose:
  239. //-----------------------------------------------------------------------------
  240. void PanelListPanel::OnSizeChanged(int wide, int tall)
  241. {
  242. BaseClass::OnSizeChanged(wide, tall);
  243. InvalidateLayout();
  244. Repaint();
  245. }
  246. //-----------------------------------------------------------------------------
  247. // Purpose: relayouts out the panel after any internal changes
  248. //-----------------------------------------------------------------------------
  249. void PanelListPanel::PerformLayout()
  250. {
  251. int wide, tall;
  252. GetSize( wide, tall );
  253. int vpixels = ComputeVPixelsNeeded();
  254. m_vbar->SetVisible( GetShowScrollbar() );
  255. m_vbar->SetRange( 0, vpixels );
  256. m_vbar->SetRangeWindow( tall );
  257. m_vbar->SetButtonPressedScrollValue( tall / 4 ); // standard height of labels/buttons etc.
  258. m_vbar->SetPos( wide - m_vbar->GetWide() - 2, 0 );
  259. m_vbar->SetSize( m_vbar->GetWide(), tall - 2 );
  260. int top = m_vbar->GetValue();
  261. m_pPanelEmbedded->SetPos( 1, -top );
  262. m_pPanelEmbedded->SetSize( wide - m_vbar->GetWide() - 2, vpixels );
  263. int sliderPos = m_vbar->GetValue();
  264. // Now lay out the controls on the embedded panel
  265. int y = 0;
  266. int h = 0;
  267. int totalh = 0;
  268. int xpos = m_iFirstColumnWidth + m_iPanelBuffer;
  269. int iColumnWidth = ( wide - xpos - m_vbar->GetWide() - 12 ) / m_iNumColumns;
  270. for ( int i = 0; i < m_SortedItems.Count(); i++ )
  271. {
  272. DATAITEM &item = m_DataItems[ m_SortedItems[i] ];
  273. if ( !item.panel || !item.panel->IsVisible() )
  274. continue;
  275. int iCurrentColumn = i % m_iNumColumns;
  276. // add in a little buffer between panels
  277. if ( iCurrentColumn == 0 )
  278. y += m_iPanelBuffer;
  279. if ( h < item.panel->GetTall() )
  280. h = item.panel->GetTall();
  281. if (totalh >= sliderPos)
  282. {
  283. if ( item.labelPanel )
  284. {
  285. item.labelPanel->SetBounds( 0, y, m_iFirstColumnWidth, item.panel->GetTall() );
  286. }
  287. item.panel->SetBounds(xpos + iCurrentColumn * iColumnWidth, y,
  288. m_bOverrideChildPanelWidth ? iColumnWidth : item.panel->GetWide(), item.panel->GetTall() );
  289. }
  290. if ( iCurrentColumn >= m_iNumColumns - 1 )
  291. {
  292. y += h;
  293. totalh += h;
  294. h = 0;
  295. }
  296. }
  297. }
  298. //-----------------------------------------------------------------------------
  299. // Purpose: scheme settings
  300. //-----------------------------------------------------------------------------
  301. void PanelListPanel::ApplySchemeSettings(IScheme *pScheme)
  302. {
  303. BaseClass::ApplySchemeSettings(pScheme);
  304. SetBorder(pScheme->GetBorder("ButtonDepressedBorder"));
  305. SetBgColor(GetSchemeColor("ListPanel.BgColor", GetBgColor(), pScheme));
  306. }
  307. //-----------------------------------------------------------------------------
  308. // Purpose:
  309. //-----------------------------------------------------------------------------
  310. void PanelListPanel::OnSliderMoved( int position )
  311. {
  312. InvalidateLayout();
  313. Repaint();
  314. }
  315. //-----------------------------------------------------------------------------
  316. // Purpose:
  317. //-----------------------------------------------------------------------------
  318. void PanelListPanel::MoveScrollBarToTop()
  319. {
  320. m_vbar->SetValue(0);
  321. }
  322. //-----------------------------------------------------------------------------
  323. // Purpose:
  324. //-----------------------------------------------------------------------------
  325. void PanelListPanel::SetFirstColumnWidth( int width )
  326. {
  327. m_iFirstColumnWidth = width;
  328. }
  329. //-----------------------------------------------------------------------------
  330. // Purpose: data accessor
  331. //-----------------------------------------------------------------------------
  332. int PanelListPanel::GetFirstColumnWidth()
  333. {
  334. return m_iFirstColumnWidth;
  335. }
  336. void PanelListPanel::SetNumColumns( int iNumColumns )
  337. {
  338. m_iNumColumns = iNumColumns;
  339. }
  340. int PanelListPanel::GetNumColumns( void )
  341. {
  342. return m_iNumColumns;
  343. }
  344. //-----------------------------------------------------------------------------
  345. // Purpose: moves the scrollbar with the mousewheel
  346. //-----------------------------------------------------------------------------
  347. void PanelListPanel::OnMouseWheeled(int delta)
  348. {
  349. if (!m_bAllowMouseWheel)
  350. return;
  351. int val = m_vbar->GetValue();
  352. val -= (delta * DEFAULT_HEIGHT);
  353. m_vbar->SetValue(val);
  354. }
  355. //-----------------------------------------------------------------------------
  356. // Purpose: selection handler
  357. //-----------------------------------------------------------------------------
  358. void PanelListPanel::SetSelectedPanel( Panel *panel )
  359. {
  360. if ( panel != m_hSelectedItem )
  361. {
  362. // notify the panels of the selection change
  363. if ( m_hSelectedItem )
  364. {
  365. PostMessage( m_hSelectedItem.Get(), new KeyValues("PanelSelected", "state", 0) );
  366. }
  367. if ( panel )
  368. {
  369. PostMessage( panel, new KeyValues("PanelSelected", "state", 1) );
  370. }
  371. m_hSelectedItem = panel;
  372. }
  373. }
  374. //-----------------------------------------------------------------------------
  375. // Purpose: data accessor
  376. //-----------------------------------------------------------------------------
  377. Panel *PanelListPanel::GetSelectedPanel()
  378. {
  379. return m_hSelectedItem;
  380. }
  381. //-----------------------------------------------------------------------------
  382. // Purpose:
  383. //-----------------------------------------------------------------------------
  384. void PanelListPanel::ScrollToItem( int itemNumber )
  385. {
  386. if (!m_vbar->IsVisible())
  387. {
  388. return;
  389. }
  390. DATAITEM& item = m_DataItems[ m_SortedItems[ itemNumber ] ];
  391. if ( !item.panel )
  392. return;
  393. int x, y;
  394. item.panel->GetPos( x, y );
  395. int lx, ly;
  396. lx = x;
  397. ly = y;
  398. m_pPanelEmbedded->LocalToScreen( lx, ly );
  399. ScreenToLocal( lx, ly );
  400. int h = item.panel->GetTall();
  401. if ( ly >= 0 && ly + h < GetTall() )
  402. return;
  403. m_vbar->SetValue( y );
  404. InvalidateLayout();
  405. }
  406. void PanelListPanel::ApplySettings( KeyValues *inResourceData )
  407. {
  408. BaseClass::ApplySettings( inResourceData );
  409. SetShowScrollBar(inResourceData->GetBool("showScrollBar", true));
  410. AllowMouseWheel(inResourceData->GetBool("allowMouseWheel", true));
  411. OverrideChildPanelWidth(inResourceData->GetBool("setChildPanelWidth", true));
  412. }
  413. //-----------------------------------------------------------------------------
  414. // Purpose:
  415. //-----------------------------------------------------------------------------
  416. void PanelListPanel::GetSettings( KeyValues *outResourceData )
  417. {
  418. BaseClass::GetSettings( outResourceData );
  419. outResourceData->SetBool("showScrollBar", m_bShowScrollBar);
  420. outResourceData->SetBool("allowMouseWheel", m_bShowScrollBar);
  421. outResourceData->SetBool("overrideChildPanelWidth", m_bOverrideChildPanelWidth);
  422. }
  423. //-----------------------------------------------------------------------------
  424. // Purpose:
  425. //-----------------------------------------------------------------------------
  426. const char *PanelListPanel::GetDescription()
  427. {
  428. static char buf[1024];
  429. Q_snprintf(buf, sizeof(buf), "%s, bool showScrollBar, bool allowMouseWheel, bool overrideChildPanelWidth", BaseClass::GetDescription());
  430. return buf;
  431. }
  432. //-----------------------------------------------------------------------------
  433. // Purpose:
  434. //-----------------------------------------------------------------------------
  435. void PanelListPanel::SetShowScrollBar( bool bShow )
  436. {
  437. m_bShowScrollBar = bShow;
  438. }
  439. //-----------------------------------------------------------------------------
  440. // Purpose:
  441. //-----------------------------------------------------------------------------
  442. void PanelListPanel::AllowMouseWheel( bool bAllow )
  443. {
  444. m_bAllowMouseWheel = bAllow;
  445. }
  446. //-----------------------------------------------------------------------------
  447. // Purpose:
  448. //-----------------------------------------------------------------------------
  449. void PanelListPanel::OverrideChildPanelWidth( bool bOverride )
  450. {
  451. m_bOverrideChildPanelWidth = bOverride;
  452. }
  453. void PanelListPanel::SetItemVisible( int nItemID, bool bVisible )
  454. {
  455. if ( !m_DataItems.IsValidIndex(nItemID) )
  456. return;
  457. m_DataItems[nItemID].panel->SetVisible( bVisible );
  458. InvalidateLayout();
  459. }
  460. bool PanelListPanel::IsItemVisible( int nItemID ) const
  461. {
  462. if ( !m_DataItems.IsValidIndex(nItemID) )
  463. return false;
  464. return m_DataItems[nItemID].panel->IsVisible();
  465. }
  466. void PanelListPanel::HideAllItems()
  467. {
  468. FOR_EACH_LL( m_DataItems, i )
  469. {
  470. if ( m_DataItems[i].panel )
  471. {
  472. m_DataItems[i].panel->SetVisible( false );
  473. }
  474. }
  475. InvalidateLayout();
  476. }