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.

479 lines
11 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "tabwindow.h"
  8. #include "ChoreoWidgetDrawHelper.h"
  9. #include "hlfaceposer.h"
  10. //-----------------------------------------------------------------------------
  11. // Purpose: Constructor
  12. // Input : *parent -
  13. // x -
  14. // y -
  15. // w -
  16. // h -
  17. // id -
  18. // style -
  19. //-----------------------------------------------------------------------------
  20. CTabWindow::CTabWindow( mxWindow *parent, int x, int y, int w, int h, int id /*= 0*/, int style /*=0*/ )
  21. : mxWindow( parent, x, y, w, h, "", style )
  22. {
  23. setId( id );
  24. m_nSelected = -1;
  25. m_nRowHeight = 20;
  26. m_nRowsRequired = 1;
  27. m_nTabWidth = 80;
  28. m_nPixelDelta = 3;
  29. m_bInverted = false;
  30. m_bRightJustify = false;
  31. SetColor( COLOR_BG, GetSysColor( COLOR_BTNFACE ) );
  32. SetColor( COLOR_FG, GetSysColor( COLOR_INACTIVECAPTION ) );
  33. SetColor( COLOR_FG_SELECTED, GetSysColor( COLOR_ACTIVECAPTION ) );
  34. SetColor( COLOR_HILITE, GetSysColor( COLOR_3DSHADOW ) );
  35. SetColor( COLOR_HILITE_SELECTED, GetSysColor( COLOR_3DHILIGHT ) );
  36. SetColor( COLOR_TEXT, GetSysColor( COLOR_CAPTIONTEXT ) );
  37. SetColor( COLOR_TEXT_SELECTED, GetSysColor( COLOR_INACTIVECAPTIONTEXT ) );
  38. FacePoser_AddWindowStyle( this, WS_CLIPCHILDREN | WS_CLIPSIBLINGS );
  39. }
  40. //-----------------------------------------------------------------------------
  41. // Purpose:
  42. // Output : CTabWindow::~CTabWindow
  43. //-----------------------------------------------------------------------------
  44. CTabWindow::~CTabWindow ( void )
  45. {
  46. removeAll();
  47. }
  48. //-----------------------------------------------------------------------------
  49. // Purpose:
  50. // Input : index -
  51. // clr -
  52. //-----------------------------------------------------------------------------
  53. void CTabWindow::SetColor( int index, COLORREF clr )
  54. {
  55. if ( index < 0 || index >= NUM_COLORS )
  56. return;
  57. m_Colors[ index ] = clr;
  58. }
  59. void CTabWindow::SetInverted( bool invert )
  60. {
  61. m_bInverted = invert;
  62. RecomputeLayout( w2() );
  63. }
  64. void CTabWindow::SetRightJustify( bool rightjustify )
  65. {
  66. m_bRightJustify = true;
  67. RecomputeLayout( w2() );
  68. }
  69. //-----------------------------------------------------------------------------
  70. // Purpose: Tabs are sized to string content
  71. // Input : rcClient -
  72. // tabRect -
  73. // tabNum -
  74. //-----------------------------------------------------------------------------
  75. void CTabWindow::GetTabRect( const RECT& rcClient, RECT& tabRect, int tabNum )
  76. {
  77. tabRect = m_Items[ tabNum ].rect;
  78. }
  79. //-----------------------------------------------------------------------------
  80. // Purpose:
  81. // Input : drawHelper -
  82. // rcClient -
  83. // tabnum -
  84. // selected -
  85. //-----------------------------------------------------------------------------
  86. void CTabWindow::DrawTab( CChoreoWidgetDrawHelper& drawHelper, RECT& rcClient, int tabnum, bool selected )
  87. {
  88. RECT rcTab;
  89. if ( tabnum < 0 || tabnum >= m_Items.Size() )
  90. return;
  91. GetTabRect( rcClient, rcTab, tabnum );
  92. COLORREF fgcolor = m_Colors[ selected ? COLOR_FG_SELECTED : COLOR_FG ];
  93. COLORREF hilightcolor = m_Colors[ selected ? COLOR_HILITE_SELECTED : COLOR_HILITE ];
  94. COLORREF text = m_Colors[ selected ? COLOR_TEXT_SELECTED : COLOR_TEXT ];
  95. // Create a trapezoid/paralleogram
  96. POINT region[4];
  97. int cPoints = 4;
  98. OffsetRect( &rcTab, 0, m_bInverted ? 1 : -1 );
  99. if ( m_bInverted )
  100. {
  101. region[ 0 ].x = rcTab.left - m_nPixelDelta;
  102. region[ 0 ].y = rcTab.top;
  103. region[ 1 ].x = rcTab.right + m_nPixelDelta;
  104. region[ 1 ].y = rcTab.top;
  105. region[ 2 ].x = rcTab.right - m_nPixelDelta;
  106. region[ 2 ].y = rcTab.bottom;
  107. region[ 3 ].x = rcTab.left + m_nPixelDelta;
  108. region[ 3 ].y = rcTab.bottom;
  109. }
  110. else
  111. {
  112. region[ 0 ].x = rcTab.left + m_nPixelDelta;
  113. region[ 0 ].y = rcTab.top;
  114. region[ 1 ].x = rcTab.right - m_nPixelDelta;
  115. region[ 1 ].y = rcTab.top;
  116. region[ 2 ].x = rcTab.right + m_nPixelDelta;
  117. region[ 2 ].y = rcTab.bottom;
  118. region[ 3 ].x = rcTab.left - m_nPixelDelta;
  119. region[ 3 ].y = rcTab.bottom;
  120. }
  121. HDC dc = drawHelper.GrabDC();
  122. HRGN rgn = CreatePolygonRgn( region, cPoints, ALTERNATE );
  123. int oldPF = SetPolyFillMode( dc, ALTERNATE );
  124. HBRUSH brBg = CreateSolidBrush( fgcolor );
  125. HBRUSH brBorder = CreateSolidBrush( hilightcolor );
  126. //HBRUSH brInset = CreateSolidBrush( fgcolor );
  127. FillRgn( dc, rgn, brBg );
  128. FrameRgn( dc, rgn, brBorder, 1, 1 );
  129. SetPolyFillMode( dc, oldPF );
  130. DeleteObject( rgn );
  131. DeleteObject( brBg );
  132. DeleteObject( brBorder );
  133. //DeleteObject( brInset );
  134. // Position label
  135. InflateRect( &rcTab, -5, 0 );
  136. OffsetRect( &rcTab, 2, 0 );
  137. // Draw label
  138. drawHelper.DrawColoredText( "Arial", 9, FW_NORMAL, text, rcTab, "%s%s", getPrefix( tabnum ), getLabel( tabnum ) );
  139. }
  140. //-----------------------------------------------------------------------------
  141. // Purpose:
  142. //-----------------------------------------------------------------------------
  143. void CTabWindow::redraw( void )
  144. {
  145. CChoreoWidgetDrawHelper drawHelper( this, m_Colors[ COLOR_BG ] );
  146. int liney = m_bInverted ? 1 : h2() - 2;
  147. drawHelper.DrawColoredLine( m_Colors[ COLOR_HILITE ], PS_SOLID, 1, 0, liney, w(), liney );
  148. RECT rc;
  149. drawHelper.GetClientRect( rc );
  150. // Draw non-selected first
  151. for ( int i = 0 ; i < m_Items.Size(); i++ )
  152. {
  153. if ( i == m_nSelected )
  154. continue;
  155. DrawTab( drawHelper, rc, i );
  156. }
  157. // Draw selected last, so that it appears to pop to top of z order
  158. if ( m_nSelected >= 0 && m_nSelected < m_Items.Size() )
  159. {
  160. DrawTab( drawHelper, rc, m_nSelected, true );
  161. }
  162. }
  163. //-----------------------------------------------------------------------------
  164. // Purpose:
  165. // Input : mx -
  166. // my -
  167. // Output : int
  168. //-----------------------------------------------------------------------------
  169. int CTabWindow::GetItemUnderMouse( int mx, int my )
  170. {
  171. RECT rcClient;
  172. GetClientRect( (HWND)getHandle(), &rcClient );
  173. for ( int i = 0; i < m_Items.Size() ; i++ )
  174. {
  175. RECT rcTab;
  176. GetTabRect( rcClient, rcTab, i );
  177. if ( mx < rcTab.left ||
  178. mx > rcTab.right ||
  179. my < rcTab.top ||
  180. my > rcTab.bottom )
  181. {
  182. continue;
  183. }
  184. return i;
  185. }
  186. return -1;
  187. }
  188. //-----------------------------------------------------------------------------
  189. // Purpose:
  190. // Input : *event -
  191. // Output : int CTabWindow::handleEvent
  192. //-----------------------------------------------------------------------------
  193. int CTabWindow::handleEvent (mxEvent *event)
  194. {
  195. int iret = 0;
  196. switch ( event->event )
  197. {
  198. case mxEvent::MouseDown:
  199. {
  200. int item = GetItemUnderMouse( (short)event->x, (short)event->y );
  201. if ( item != -1 )
  202. {
  203. m_nSelected = item;
  204. redraw();
  205. // Send CBN_SELCHANGE WM_COMMAND message to parent
  206. HWND parent = (HWND)( getParent() ? getParent()->getHandle() : NULL );
  207. if ( parent )
  208. {
  209. LPARAM lp;
  210. WPARAM wp;
  211. wp = MAKEWPARAM( getId(), CBN_SELCHANGE );
  212. lp = (long)getHandle();
  213. PostMessage( parent, WM_COMMAND, wp, lp );
  214. }
  215. iret = 1;
  216. }
  217. if ( event->buttons & mxEvent::MouseRightButton )
  218. {
  219. ShowRightClickMenu( (short)event->x, (short)event->y );
  220. iret = 1;
  221. }
  222. }
  223. break;
  224. case mxEvent::Size:
  225. {
  226. RecomputeLayout( w2() );
  227. }
  228. break;
  229. }
  230. return iret;
  231. }
  232. //-----------------------------------------------------------------------------
  233. // Purpose: Add string to table
  234. // Input : *item -
  235. //-----------------------------------------------------------------------------
  236. void CTabWindow::add( const char *item )
  237. {
  238. m_Items.AddToTail();
  239. CETItem *p = &m_Items[ m_Items.Size() - 1 ];
  240. Assert( p );
  241. Q_memset( &p->rect, 0, sizeof( p->rect) );
  242. strcpy( p->m_szString, item );
  243. p->m_szPrefix[ 0 ] = 0;
  244. m_nSelected = min( m_nSelected, m_Items.Size() - 1 );
  245. m_nSelected = max( m_nSelected, 0 );
  246. RecomputeLayout( w2() );
  247. redraw();
  248. }
  249. void CTabWindow::setPrefix( int item, char const *prefix )
  250. {
  251. if ( item < 0 || item >= m_Items.Size() )
  252. return;
  253. Q_strncpy( m_Items[ item ].m_szPrefix, prefix, sizeof( m_Items[ item ].m_szPrefix ) );
  254. // RecomputeLayout( w2() );
  255. }
  256. //-----------------------------------------------------------------------------
  257. // Purpose: Change selected item
  258. // Input : index -
  259. //-----------------------------------------------------------------------------
  260. void CTabWindow::select( int index )
  261. {
  262. if ( index < 0 || index >= m_Items.Size() )
  263. return;
  264. m_nSelected = index;
  265. redraw();
  266. }
  267. //-----------------------------------------------------------------------------
  268. // Purpose: Remove a string
  269. // Input : index -
  270. //-----------------------------------------------------------------------------
  271. void CTabWindow::remove( int index )
  272. {
  273. if ( index < 0 || index >= m_Items.Size() )
  274. return;
  275. m_Items.Remove( index );
  276. m_nSelected = min( m_nSelected, m_Items.Size() - 1 );
  277. m_nSelected = max( m_nSelected, 0 );
  278. RecomputeLayout( w2() );
  279. redraw();
  280. }
  281. //-----------------------------------------------------------------------------
  282. // Purpose: Clear out everything
  283. //-----------------------------------------------------------------------------
  284. void CTabWindow::removeAll()
  285. {
  286. m_nSelected = -1;
  287. m_Items.RemoveAll();
  288. RecomputeLayout( w2() );
  289. redraw();
  290. }
  291. //-----------------------------------------------------------------------------
  292. // Purpose:
  293. // Output : int
  294. //-----------------------------------------------------------------------------
  295. int CTabWindow::getItemCount () const
  296. {
  297. return m_Items.Size();
  298. }
  299. //-----------------------------------------------------------------------------
  300. // Purpose:
  301. // Output : int
  302. //-----------------------------------------------------------------------------
  303. int CTabWindow::getSelectedIndex () const
  304. {
  305. // Convert based on override index
  306. return m_nSelected;
  307. }
  308. char const *CTabWindow::getLabel( int item )
  309. {
  310. if ( item < 0 || item >= m_Items.Count() )
  311. return "";
  312. return m_Items[ item ].m_szString;
  313. }
  314. char const *CTabWindow::getPrefix( int item )
  315. {
  316. if ( item < 0 || item >= m_Items.Count() )
  317. return "";
  318. return m_Items[ item ].m_szPrefix;
  319. }
  320. void CTabWindow::SetRowHeight( int rowheight )
  321. {
  322. m_nRowHeight = rowheight;
  323. RecomputeLayout( w2() );
  324. redraw();
  325. }
  326. int CTabWindow::GetBestHeight( int width )
  327. {
  328. return RecomputeLayout( width, false ) * m_nRowHeight;
  329. }
  330. int CTabWindow::RecomputeLayout( int windowWidth, bool dolayout /*=true*/ )
  331. {
  332. // Draw non-selected first
  333. int curedge = m_nPixelDelta + 1;
  334. int curtop = 0;
  335. if ( m_bRightJustify )
  336. {
  337. curedge = windowWidth - ( m_nPixelDelta + 1 ) - 5;
  338. }
  339. int startedge = curedge;
  340. int currentrow = 0;
  341. for ( int i = 0 ; i < m_Items.Size(); i++ )
  342. {
  343. CETItem *p = &m_Items[ i ];
  344. RECT rc;
  345. int textwidth = CChoreoWidgetDrawHelper::CalcTextWidth( "Arial", 9, FW_NORMAL, "%s%s", p->m_szPrefix, p->m_szString ) + 15;
  346. if ( !m_bRightJustify )
  347. {
  348. // Starting column
  349. if ( curedge + textwidth > windowWidth )
  350. {
  351. curedge = startedge;
  352. curtop += m_nRowHeight;
  353. currentrow++;
  354. }
  355. rc.left = curedge;
  356. rc.right = curedge + textwidth;
  357. rc.top = curtop + 2;
  358. rc.bottom = curtop + m_nRowHeight;
  359. curedge += textwidth;
  360. p->rect = rc;
  361. }
  362. else
  363. {
  364. // Starting column
  365. if ( curedge - textwidth < 0 )
  366. {
  367. curedge = startedge;
  368. curtop += m_nRowHeight;
  369. currentrow++;
  370. }
  371. rc.left = curedge - textwidth;
  372. rc.right = curedge;
  373. rc.top = curtop;
  374. rc.bottom = curtop + m_nRowHeight - 2;
  375. curedge -= textwidth;
  376. }
  377. if ( dolayout )
  378. {
  379. p->rect = rc;
  380. }
  381. }
  382. if ( dolayout )
  383. {
  384. m_nRowsRequired = currentrow + 1;
  385. }
  386. return currentrow + 1;
  387. }