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.

8924 lines
233 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include <stdio.h>
  8. #include <assert.h>
  9. #include <utlvector.h>
  10. #include <vstdlib/IKeyValuesSystem.h>
  11. #include <ctype.h> // isdigit()
  12. #include <materialsystem/imaterial.h>
  13. #include <vgui/IBorder.h>
  14. #include <vgui/IInput.h>
  15. #include <vgui/IPanel.h>
  16. #include <vgui/IScheme.h>
  17. #include <vgui/ISurface.h>
  18. #include <vgui/ISystem.h>
  19. #include <vgui/ILocalize.h>
  20. #include <vgui/IVGui.h>
  21. #include <KeyValues.h>
  22. #include <vgui/MouseCode.h>
  23. #include <vgui_controls/Panel.h>
  24. #include <vgui_controls/BuildGroup.h>
  25. #include <vgui_controls/Tooltip.h>
  26. #include <vgui_controls/PHandle.h>
  27. #include <vgui_controls/Controls.h>
  28. #include "vgui_controls/Menu.h"
  29. #include "vgui_controls/MenuItem.h"
  30. #include "UtlSortVector.h"
  31. #include "tier1/utldict.h"
  32. #include "tier1/utlbuffer.h"
  33. #include "mempool.h"
  34. #include "filesystem.h"
  35. #include "tier0/icommandline.h"
  36. #include "tier0/minidump.h"
  37. #include "tier0/vprof.h"
  38. // memdbgon must be the last include file in a .cpp file!!!
  39. #include <tier0/memdbgon.h>
  40. using namespace vgui;
  41. #define TRIPLE_PRESS_MSEC 300
  42. const char *g_PinCornerStrings [] =
  43. {
  44. "PIN_TOPLEFT",
  45. "PIN_TOPRIGHT",
  46. "PIN_BOTTOMLEFT",
  47. "PIN_BOTTOMRIGHT",
  48. "PIN_CENTER_TOP",
  49. "PIN_CENTER_RIGHT",
  50. "PIN_CENTER_BOTTOM",
  51. "PIN_CENTER_LEFT",
  52. };
  53. COMPILE_TIME_ASSERT( Panel::PIN_LAST == ARRAYSIZE( g_PinCornerStrings ) );
  54. extern int GetBuildModeDialogCount();
  55. static char *CopyString( const char *in )
  56. {
  57. if ( !in )
  58. return NULL;
  59. int len = strlen( in );
  60. char *n = new char[ len + 1 ];
  61. Q_strncpy( n, in, len + 1 );
  62. return n;
  63. }
  64. #ifdef STAGING_ONLY
  65. ConVar tf_strict_mouse_up_events( "tf_strict_mouse_up_events", "0", FCVAR_ARCHIVE, "Only allow Mouse-Release events to happens on panels we also Mouse-Downed in" );
  66. #endif
  67. // Temporary convar to help debug why the MvMVictoryMannUpPanel TabContainer is sometimes way off to the left.
  68. ConVar tf_debug_tabcontainer( "tf_debug_tabcontainer", "0", FCVAR_HIDDEN, "Spew TabContainer dimensions." );
  69. #if defined( VGUI_USEDRAGDROP )
  70. //-----------------------------------------------------------------------------
  71. // Purpose:
  72. //-----------------------------------------------------------------------------
  73. struct vgui::DragDrop_t
  74. {
  75. DragDrop_t() :
  76. m_bDragEnabled( false ),
  77. m_bShowDragHelper( true ),
  78. m_bDropEnabled( false ),
  79. m_bDragStarted( false ),
  80. m_nDragStartTolerance( 8 ),
  81. m_bDragging( false ),
  82. m_lDropHoverTime( 0 ),
  83. m_bDropMenuShown( false ),
  84. m_bPreventChaining( false )
  85. {
  86. m_nStartPos[ 0 ] = m_nStartPos[ 1 ] = 0;
  87. m_nLastPos[ 0 ] = m_nLastPos[ 1 ] = 0;
  88. }
  89. // Drag related data
  90. bool m_bDragEnabled;
  91. bool m_bShowDragHelper;
  92. bool m_bDragging;
  93. bool m_bDragStarted;
  94. // How many pixels the dragged box must move before showing the outline rect...
  95. int m_nDragStartTolerance;
  96. int m_nStartPos[ 2 ];
  97. int m_nLastPos[ 2 ];
  98. CUtlVector< KeyValues * > m_DragData;
  99. CUtlVector< PHandle > m_DragPanels;
  100. // Drop related data
  101. bool m_bDropEnabled;
  102. // A droppable panel can have a hover context menu, which will show up after m_flHoverContextTime of hovering
  103. float m_flHoverContextTime;
  104. PHandle m_hCurrentDrop;
  105. // Amount of time hovering over current drop target
  106. long m_lDropHoverTime;
  107. bool m_bDropMenuShown;
  108. DHANDLE< Menu > m_hDropContextMenu;
  109. // Misc data
  110. bool m_bPreventChaining;
  111. };
  112. //-----------------------------------------------------------------------------
  113. // Purpose: Helper for painting to the full screen...
  114. //-----------------------------------------------------------------------------
  115. class CDragDropHelperPanel : public Panel
  116. {
  117. DECLARE_CLASS_SIMPLE( CDragDropHelperPanel, Panel );
  118. public:
  119. CDragDropHelperPanel();
  120. virtual VPANEL IsWithinTraverse(int x, int y, bool traversePopups);
  121. virtual void PostChildPaint();
  122. void AddPanel( Panel *current );
  123. void RemovePanel( Panel *search );
  124. private:
  125. struct DragHelperPanel_t
  126. {
  127. PHandle m_hPanel;
  128. };
  129. CUtlVector< DragHelperPanel_t > m_PaintList;
  130. };
  131. vgui::DHANDLE< CDragDropHelperPanel > s_DragDropHelper;
  132. #endif
  133. #if defined( VGUI_USEKEYBINDINGMAPS )
  134. BoundKey_t::BoundKey_t():
  135. isbuiltin( true ),
  136. bindingname( 0 ),
  137. keycode( KEY_NONE ),
  138. modifiers( 0 )
  139. {
  140. }
  141. BoundKey_t::BoundKey_t( const BoundKey_t& src )
  142. {
  143. isbuiltin = src.isbuiltin;
  144. bindingname = isbuiltin ? src.bindingname : CopyString( src.bindingname );
  145. keycode = src.keycode;
  146. modifiers = src.modifiers;
  147. }
  148. BoundKey_t& BoundKey_t::operator =( const BoundKey_t& src )
  149. {
  150. if ( this == &src )
  151. return *this;
  152. isbuiltin = src.isbuiltin;
  153. bindingname = isbuiltin ? src.bindingname : CopyString( src.bindingname );
  154. keycode = src.keycode;
  155. modifiers = src.modifiers;
  156. return *this;
  157. }
  158. BoundKey_t::~BoundKey_t()
  159. {
  160. if ( !isbuiltin )
  161. {
  162. delete[] bindingname;
  163. }
  164. }
  165. KeyBindingMap_t::KeyBindingMap_t() :
  166. bindingname( 0 ),
  167. func( 0 ),
  168. helpstring( 0 ),
  169. docstring( 0 ),
  170. passive( false )
  171. {
  172. }
  173. KeyBindingMap_t::KeyBindingMap_t( const KeyBindingMap_t& src )
  174. {
  175. bindingname = src.bindingname;
  176. helpstring = src.helpstring;
  177. docstring = src.docstring;
  178. func = src.func;
  179. passive = src.passive;
  180. }
  181. KeyBindingMap_t::~KeyBindingMap_t()
  182. {
  183. }
  184. class CKeyBindingsMgr
  185. {
  186. public:
  187. CKeyBindingsMgr() :
  188. m_Bindings( 0, 0, KeyBindingContextHandleLessFunc ),
  189. m_nKeyBindingContexts( 0 )
  190. {
  191. }
  192. struct KBContext_t
  193. {
  194. KBContext_t() :
  195. m_KeyBindingsFile( UTL_INVAL_SYMBOL ),
  196. m_KeyBindingsPathID( UTL_INVAL_SYMBOL )
  197. {
  198. m_Handle = INVALID_KEYBINDINGCONTEXT_HANDLE;
  199. }
  200. KBContext_t( const KBContext_t& src )
  201. {
  202. m_Handle = src.m_Handle;
  203. m_KeyBindingsFile = src.m_KeyBindingsFile;
  204. m_KeyBindingsPathID = src.m_KeyBindingsPathID;
  205. int c = src.m_Panels.Count();
  206. for ( int i = 0; i < c; ++i )
  207. {
  208. m_Panels.AddToTail( src.m_Panels[ i ] );
  209. }
  210. }
  211. KeyBindingContextHandle_t m_Handle;
  212. CUtlSymbol m_KeyBindingsFile;
  213. CUtlSymbol m_KeyBindingsPathID;
  214. CUtlVector< Panel * > m_Panels;
  215. };
  216. static bool KeyBindingContextHandleLessFunc( const KBContext_t& lhs, const KBContext_t& rhs )
  217. {
  218. return lhs.m_Handle < rhs.m_Handle;
  219. }
  220. KeyBindingContextHandle_t CreateContext( char const *filename, char const *pathID )
  221. {
  222. KBContext_t entry;
  223. entry.m_Handle = (KeyBindingContextHandle_t)++m_nKeyBindingContexts;
  224. entry.m_KeyBindingsFile = filename;
  225. if ( pathID )
  226. {
  227. entry.m_KeyBindingsPathID = pathID;
  228. }
  229. else
  230. {
  231. entry.m_KeyBindingsPathID = UTL_INVAL_SYMBOL;
  232. }
  233. m_Bindings.Insert( entry );
  234. return entry.m_Handle;
  235. }
  236. void AddPanelToContext( KeyBindingContextHandle_t handle, Panel *panel )
  237. {
  238. if ( !panel->GetName() || !panel->GetName()[ 0 ] )
  239. {
  240. Warning( "Can't add Keybindings Context for unnamed panels\n" );
  241. return;
  242. }
  243. KBContext_t *entry = Find( handle );
  244. Assert( entry );
  245. if ( entry )
  246. {
  247. int idx = entry->m_Panels.Find( panel );
  248. if ( idx == entry->m_Panels.InvalidIndex() )
  249. {
  250. entry->m_Panels.AddToTail( panel );
  251. }
  252. }
  253. }
  254. void OnPanelDeleted( KeyBindingContextHandle_t handle, Panel *panel )
  255. {
  256. KBContext_t *kb = Find( handle );
  257. if ( kb )
  258. {
  259. kb->m_Panels.FindAndRemove( panel );
  260. }
  261. }
  262. KBContext_t *Find( KeyBindingContextHandle_t handle )
  263. {
  264. KBContext_t search;
  265. search.m_Handle = handle;
  266. int idx = m_Bindings.Find( search );
  267. if ( idx == m_Bindings.InvalidIndex() )
  268. {
  269. return NULL;
  270. }
  271. return &m_Bindings[ idx ];
  272. }
  273. char const *GetKeyBindingsFile( KeyBindingContextHandle_t handle )
  274. {
  275. KBContext_t *kb = Find( handle );
  276. if ( kb )
  277. {
  278. return kb->m_KeyBindingsFile.String();
  279. }
  280. Assert( 0 );
  281. return "";
  282. }
  283. char const *GetKeyBindingsFilePathID( KeyBindingContextHandle_t handle )
  284. {
  285. KBContext_t *kb = Find( handle );
  286. if ( kb )
  287. {
  288. return kb->m_KeyBindingsPathID.String();
  289. }
  290. Assert( 0 );
  291. return NULL;
  292. }
  293. int GetPanelsWithKeyBindingsCount( KeyBindingContextHandle_t handle )
  294. {
  295. KBContext_t *kb = Find( handle );
  296. if ( kb )
  297. {
  298. return kb->m_Panels.Count();
  299. }
  300. Assert( 0 );
  301. return 0;
  302. }
  303. //-----------------------------------------------------------------------------
  304. // Purpose: static method
  305. // Input : index -
  306. // Output : Panel
  307. //-----------------------------------------------------------------------------
  308. Panel *GetPanelWithKeyBindings( KeyBindingContextHandle_t handle, int index )
  309. {
  310. KBContext_t *kb = Find( handle );
  311. if ( kb )
  312. {
  313. Assert( index >= 0 && index < kb->m_Panels.Count() );
  314. return kb->m_Panels[ index ];
  315. }
  316. Assert( 0 );
  317. return 0;
  318. }
  319. CUtlRBTree< KBContext_t, int > m_Bindings;
  320. int m_nKeyBindingContexts;
  321. };
  322. static CKeyBindingsMgr g_KBMgr;
  323. //-----------------------------------------------------------------------------
  324. // Purpose: Static method to allocate a context
  325. // Input : -
  326. // Output : KeyBindingContextHandle_t
  327. //-----------------------------------------------------------------------------
  328. KeyBindingContextHandle_t Panel::CreateKeyBindingsContext( char const *filename, char const *pathID /*=0*/ )
  329. {
  330. return g_KBMgr.CreateContext( filename, pathID );
  331. }
  332. COMPILE_TIME_ASSERT( ( MOUSE_MIDDLE - MOUSE_LEFT ) == 2 );
  333. Panel* Panel::m_sMousePressedPanels[] = { NULL, NULL, NULL };
  334. //-----------------------------------------------------------------------------
  335. // Purpose: static method
  336. // Input : -
  337. // Output : int
  338. //-----------------------------------------------------------------------------
  339. int Panel::GetPanelsWithKeyBindingsCount( KeyBindingContextHandle_t handle )
  340. {
  341. return g_KBMgr.GetPanelsWithKeyBindingsCount( handle );
  342. }
  343. //-----------------------------------------------------------------------------
  344. // Purpose: static method
  345. // Input : index -
  346. // Output : Panel
  347. //-----------------------------------------------------------------------------
  348. Panel *Panel::GetPanelWithKeyBindings( KeyBindingContextHandle_t handle, int index )
  349. {
  350. return g_KBMgr.GetPanelWithKeyBindings( handle, index );
  351. }
  352. //-----------------------------------------------------------------------------
  353. // Returns the number of keybindings
  354. //-----------------------------------------------------------------------------
  355. int Panel::GetKeyMappingCount( )
  356. {
  357. int nCount = 0;
  358. PanelKeyBindingMap *map = GetKBMap();
  359. while ( map )
  360. {
  361. nCount += map->entries.Count();
  362. map = map->baseMap;
  363. }
  364. return nCount;
  365. }
  366. //-----------------------------------------------------------------------------
  367. // Purpose: static method. Reverts key bindings for all registered panels (panels with keybindings actually
  368. // loaded from file
  369. // Input : -
  370. //-----------------------------------------------------------------------------
  371. void Panel::RevertKeyBindings( KeyBindingContextHandle_t handle )
  372. {
  373. int c = GetPanelsWithKeyBindingsCount( handle );
  374. for ( int i = 0; i < c; ++i )
  375. {
  376. Panel *kbPanel = GetPanelWithKeyBindings( handle, i );
  377. Assert( kbPanel );
  378. kbPanel->RevertKeyBindingsToDefault();
  379. }
  380. }
  381. static void BufPrint( CUtlBuffer& buf, int level, char const *fmt, ... )
  382. {
  383. char string[ 2048 ];
  384. va_list argptr;
  385. va_start( argptr, fmt );
  386. _vsnprintf( string, sizeof( string ) - 1, fmt, argptr );
  387. va_end( argptr );
  388. string[ sizeof( string ) - 1 ] = 0;
  389. while ( --level >= 0 )
  390. {
  391. buf.Printf( " " );
  392. }
  393. buf.Printf( "%s", string );
  394. }
  395. //-----------------------------------------------------------------------------
  396. // Purpose:
  397. // Input : handle -
  398. //-----------------------------------------------------------------------------
  399. void Panel::SaveKeyBindings( KeyBindingContextHandle_t handle )
  400. {
  401. char const *filename = g_KBMgr.GetKeyBindingsFile( handle );
  402. char const *pathID = g_KBMgr.GetKeyBindingsFilePathID( handle );
  403. SaveKeyBindingsToFile( handle, filename, pathID );
  404. }
  405. //-----------------------------------------------------------------------------
  406. // Purpose: static method. Saves key binding files out for all keybindings
  407. // Input : -
  408. //-----------------------------------------------------------------------------
  409. void Panel::SaveKeyBindingsToFile( KeyBindingContextHandle_t handle, char const *filename, char const *pathID /*= 0*/ )
  410. {
  411. CUtlBuffer buf( 0, 0, CUtlBuffer::TEXT_BUFFER );
  412. BufPrint( buf, 0, "keybindings\n" );
  413. BufPrint( buf, 0, "{\n" );
  414. int c = GetPanelsWithKeyBindingsCount( handle );
  415. for ( int i = 0; i < c; ++i )
  416. {
  417. Panel *kbPanel = GetPanelWithKeyBindings( handle, i );
  418. Assert( kbPanel );
  419. if ( !kbPanel )
  420. continue;
  421. Assert( kbPanel->GetName() );
  422. Assert( kbPanel->GetName()[ 0 ] );
  423. if ( !kbPanel->GetName() || !kbPanel->GetName()[ 0 ] )
  424. continue;
  425. BufPrint( buf, 1, "\"%s\"\n", kbPanel->GetName() );
  426. BufPrint( buf, 1, "{\n" );
  427. kbPanel->SaveKeyBindingsToBuffer( 2, buf );
  428. BufPrint( buf, 1, "}\n" );
  429. }
  430. BufPrint( buf, 0, "}\n" );
  431. if ( g_pFullFileSystem->FileExists( filename, pathID ) &&
  432. !g_pFullFileSystem->IsFileWritable( filename, pathID ) )
  433. {
  434. Warning( "Panel::SaveKeyBindings '%s' is read-only!!!\n", filename );
  435. }
  436. FileHandle_t h = g_pFullFileSystem->Open( filename, "wb", pathID );
  437. if ( FILESYSTEM_INVALID_HANDLE != h )
  438. {
  439. g_pFullFileSystem->Write( buf.Base(), buf.TellPut(), h );
  440. g_pFullFileSystem->Close( h );
  441. }
  442. }
  443. //-----------------------------------------------------------------------------
  444. // Purpose:
  445. // Input : handle -
  446. // *panelOfInterest -
  447. //-----------------------------------------------------------------------------
  448. void Panel::LoadKeyBindingsForOnePanel( KeyBindingContextHandle_t handle, Panel *panelOfInterest )
  449. {
  450. if ( !panelOfInterest )
  451. return;
  452. if ( !panelOfInterest->GetName() )
  453. return;
  454. if ( !panelOfInterest->GetName()[ 0 ] )
  455. return;
  456. char const *filename = g_KBMgr.GetKeyBindingsFile( handle );
  457. char const *pathID = g_KBMgr.GetKeyBindingsFilePathID( handle );
  458. KeyValues *kv = new KeyValues( "keybindings" );
  459. if ( kv->LoadFromFile( g_pFullFileSystem, filename, pathID ) )
  460. {
  461. int c = GetPanelsWithKeyBindingsCount( handle );
  462. for ( int i = 0; i < c; ++i )
  463. {
  464. Panel *kbPanel = GetPanelWithKeyBindings( handle, i );
  465. Assert( kbPanel );
  466. char const *panelName = kbPanel->GetName();
  467. if ( !panelName )
  468. {
  469. continue;
  470. }
  471. if ( Q_stricmp( panelOfInterest->GetName(), panelName ) )
  472. continue;
  473. KeyValues *subKey = kv->FindKey( panelName, false );
  474. if ( !subKey )
  475. {
  476. Warning( "Panel::ReloadKeyBindings: Can't find entry for panel '%s'\n", panelName );
  477. continue;
  478. }
  479. kbPanel->ParseKeyBindings( subKey );
  480. }
  481. }
  482. kv->deleteThis();
  483. }
  484. //-----------------------------------------------------------------------------
  485. // Purpose: static method. Loads all key bindings again
  486. // Input : -
  487. //-----------------------------------------------------------------------------
  488. void Panel::ReloadKeyBindings( KeyBindingContextHandle_t handle )
  489. {
  490. char const *filename = g_KBMgr.GetKeyBindingsFile( handle );
  491. char const *pathID = g_KBMgr.GetKeyBindingsFilePathID( handle );
  492. KeyValues *kv = new KeyValues( "keybindings" );
  493. if ( kv->LoadFromFile( g_pFullFileSystem, filename, pathID ) )
  494. {
  495. int c = GetPanelsWithKeyBindingsCount( handle );
  496. for ( int i = 0; i < c; ++i )
  497. {
  498. Panel *kbPanel = GetPanelWithKeyBindings( handle, i );
  499. Assert( kbPanel );
  500. char const *panelName = kbPanel->GetName();
  501. if ( !panelName )
  502. {
  503. continue;
  504. }
  505. KeyValues *subKey = kv->FindKey( panelName, false );
  506. if ( !subKey )
  507. {
  508. Warning( "Panel::ReloadKeyBindings: Can't find entry for panel '%s'\n", panelName );
  509. continue;
  510. }
  511. kbPanel->ParseKeyBindings( subKey );
  512. }
  513. }
  514. kv->deleteThis();
  515. }
  516. #endif // VGUI_USEKEYBINDINGMAPS
  517. DECLARE_BUILD_FACTORY( Panel );
  518. //-----------------------------------------------------------------------------
  519. // Purpose: Constructor
  520. //-----------------------------------------------------------------------------
  521. Panel::Panel()
  522. {
  523. Init(0, 0, 64, 24);
  524. }
  525. //-----------------------------------------------------------------------------
  526. // Purpose: Constructor
  527. //-----------------------------------------------------------------------------
  528. Panel::Panel(Panel *parent)
  529. {
  530. Init(0, 0, 64, 24);
  531. SetParent(parent);
  532. }
  533. //-----------------------------------------------------------------------------
  534. // Purpose: Constructor
  535. //-----------------------------------------------------------------------------
  536. Panel::Panel(Panel *parent, const char *panelName)
  537. {
  538. Init(0, 0, 64, 24);
  539. SetName(panelName);
  540. SetParent(parent);
  541. SetBuildModeEditable(true);
  542. }
  543. //-----------------------------------------------------------------------------
  544. // Purpose: Constructor
  545. //-----------------------------------------------------------------------------
  546. Panel::Panel( Panel *parent, const char *panelName, HScheme scheme )
  547. {
  548. Init(0, 0, 64, 24);
  549. SetName(panelName);
  550. SetParent(parent);
  551. SetBuildModeEditable(true);
  552. SetScheme( scheme );
  553. }
  554. //-----------------------------------------------------------------------------
  555. // Purpose: Setup
  556. //-----------------------------------------------------------------------------
  557. void Panel::Init( int x, int y, int wide, int tall )
  558. {
  559. _panelName = NULL;
  560. _tooltipText = NULL;
  561. _pinToSibling = NULL;
  562. m_hMouseEventHandler = NULL;
  563. _pinCornerToSibling = PIN_TOPLEFT;
  564. _pinToSiblingCorner = PIN_TOPLEFT;
  565. // get ourselves an internal panel
  566. _vpanel = ivgui()->AllocPanel();
  567. ipanel()->Init(_vpanel, this);
  568. SetPos(x, y);
  569. SetSize(wide, tall);
  570. _flags.SetFlag( NEEDS_LAYOUT | NEEDS_SCHEME_UPDATE | NEEDS_DEFAULT_SETTINGS_APPLIED );
  571. _flags.SetFlag( AUTODELETE_ENABLED | PAINT_BORDER_ENABLED | PAINT_BACKGROUND_ENABLED | PAINT_ENABLED );
  572. #if defined( VGUI_USEKEYBINDINGMAPS )
  573. _flags.SetFlag( ALLOW_CHAIN_KEYBINDING_TO_PARENT );
  574. #endif
  575. m_nPinDeltaX = m_nPinDeltaY = 0;
  576. m_nResizeDeltaX = m_nResizeDeltaY = 0;
  577. _autoResizeDirection = AUTORESIZE_NO;
  578. _pinCorner = PIN_TOPLEFT;
  579. _cursor = dc_arrow;
  580. _border = NULL;
  581. _buildGroup = UTLHANDLE_INVALID;
  582. _tabPosition = 0;
  583. m_iScheme = 0;
  584. m_bIsSilent = false;
  585. m_bParentNeedsCursorMoveEvents = false;
  586. _buildModeFlags = 0; // not editable or deletable in buildmode dialog by default
  587. m_pTooltips = NULL;
  588. m_bToolTipOverridden = false;
  589. m_flAlpha = 255.0f;
  590. m_nPaintBackgroundType = 0;
  591. //=============================================================================
  592. // HPE_BEGIN:
  593. // [tj] Default to rounding all corners (for draw style 2)
  594. //=============================================================================
  595. m_roundedCorners = PANEL_ROUND_CORNER_ALL;
  596. //=============================================================================
  597. // HPE_END
  598. //=============================================================================
  599. m_nBgTextureId1 = -1;
  600. m_nBgTextureId2 = -1;
  601. m_nBgTextureId3 = -1;
  602. m_nBgTextureId4 = -1;
  603. #if defined( VGUI_USEDRAGDROP )
  604. m_pDragDrop = new DragDrop_t;
  605. #endif
  606. m_lLastDoublePressTime = 0L;
  607. #if defined( VGUI_USEKEYBINDINGMAPS )
  608. m_hKeyBindingsContext = INVALID_KEYBINDINGCONTEXT_HANDLE;
  609. #endif
  610. REGISTER_COLOR_AS_OVERRIDABLE( _fgColor, "fgcolor_override" );
  611. REGISTER_COLOR_AS_OVERRIDABLE( _bgColor, "bgcolor_override" );
  612. m_bIsConsoleStylePanel = false;
  613. m_NavUp = NULL;
  614. m_NavDown = NULL;
  615. m_NavLeft = NULL;
  616. m_NavRight = NULL;
  617. m_NavToRelay = NULL;
  618. m_NavActivate = NULL;
  619. m_NavBack = NULL;
  620. m_sNavUpName = NULL;
  621. m_sNavDownName = NULL;
  622. m_sNavLeftName = NULL;
  623. m_sNavRightName = NULL;
  624. m_sNavToRelayName = NULL;
  625. m_sNavActivateName = NULL;
  626. m_sNavBackName = NULL;
  627. m_PassUnhandledInput = true;
  628. m_LastNavDirection = ND_NONE;
  629. m_bWorldPositionCurrentFrame = false;
  630. m_bForceStereoRenderToFrameBuffer = false;
  631. }
  632. //-----------------------------------------------------------------------------
  633. // Purpose: Destructor
  634. //-----------------------------------------------------------------------------
  635. Panel::~Panel()
  636. {
  637. // @note Tom Bui: only cleanup if we've created it
  638. if ( !m_bToolTipOverridden )
  639. {
  640. if ( m_pTooltips )
  641. {
  642. delete m_pTooltips;
  643. }
  644. }
  645. #if defined( VGUI_USEKEYBINDINGMAPS )
  646. if ( IsValidKeyBindingsContext() )
  647. {
  648. g_KBMgr.OnPanelDeleted( m_hKeyBindingsContext, this );
  649. }
  650. #endif // VGUI_USEKEYBINDINGMAPS
  651. #if defined( VGUI_USEDRAGDROP )
  652. if ( m_pDragDrop->m_bDragging )
  653. {
  654. OnFinishDragging( false, (MouseCode)-1 );
  655. }
  656. #endif // VGUI_USEDRAGDROP
  657. _flags.ClearFlag( AUTODELETE_ENABLED );
  658. _flags.SetFlag( MARKED_FOR_DELETION );
  659. // remove panel from any list
  660. SetParent((VPANEL)NULL);
  661. // Stop our children from pointing at us, and delete them if possible
  662. while (ipanel()->GetChildCount(GetVPanel()))
  663. {
  664. VPANEL child = ipanel()->GetChild(GetVPanel(), 0);
  665. if (ipanel()->IsAutoDeleteSet(child))
  666. {
  667. ipanel()->DeletePanel(child);
  668. }
  669. else
  670. {
  671. ipanel()->SetParent(child, NULL);
  672. }
  673. }
  674. // delete VPanel
  675. ivgui()->FreePanel(_vpanel);
  676. // free our name
  677. delete [] _panelName;
  678. if ( _tooltipText && _tooltipText[0] )
  679. {
  680. delete [] _tooltipText;
  681. }
  682. delete [] _pinToSibling;
  683. _vpanel = NULL;
  684. #if defined( VGUI_USEDRAGDROP )
  685. delete m_pDragDrop;
  686. #endif // VGUI_USEDRAGDROP
  687. #if defined( VGUI_PANEL_VERIFY_DELETES )
  688. // Zero out our vtbl pointer. This should hopefully help us catch bad guys using
  689. // this panel after it has been deleted.
  690. uintp *panel_vtbl = (uintp *)this;
  691. *panel_vtbl = NULL;
  692. #endif
  693. }
  694. //-----------------------------------------------------------------------------
  695. // Purpose: fully construct this panel so its ready for use right now (i.e fonts loaded, colors set, default label text set, ...)
  696. //-----------------------------------------------------------------------------
  697. void Panel::MakeReadyForUse()
  698. {
  699. // PerformApplySchemeSettings();
  700. UpdateSiblingPin();
  701. surface()->SolveTraverse( GetVPanel(), true );
  702. }
  703. //-----------------------------------------------------------------------------
  704. // Purpose:
  705. //-----------------------------------------------------------------------------
  706. void Panel::SetName( const char *panelName )
  707. {
  708. // No change?
  709. if ( _panelName &&
  710. panelName &&
  711. !Q_strcmp( _panelName, panelName ) )
  712. {
  713. return;
  714. }
  715. if (_panelName)
  716. {
  717. delete [] _panelName;
  718. _panelName = NULL;
  719. }
  720. if (panelName)
  721. {
  722. int len = Q_strlen(panelName) + 1;
  723. _panelName = new char[ len ];
  724. Q_strncpy( _panelName, panelName, len );
  725. }
  726. }
  727. //-----------------------------------------------------------------------------
  728. // Purpose: returns the given name of the panel
  729. //-----------------------------------------------------------------------------
  730. const char *Panel::GetName()
  731. {
  732. if (_panelName)
  733. return _panelName;
  734. return "";
  735. }
  736. //-----------------------------------------------------------------------------
  737. // Purpose: returns the name of the module that this instance of panel was compiled into
  738. //-----------------------------------------------------------------------------
  739. const char *Panel::GetModuleName()
  740. {
  741. return vgui::GetControlsModuleName();
  742. }
  743. //-----------------------------------------------------------------------------
  744. // Purpose: returns the classname of the panel (as specified in the panelmaps)
  745. //-----------------------------------------------------------------------------
  746. const char *Panel::GetClassName()
  747. {
  748. // loop up the panel map name
  749. PanelMessageMap *panelMap = GetMessageMap();
  750. if ( panelMap )
  751. {
  752. return panelMap->pfnClassName();
  753. }
  754. return "Panel";
  755. }
  756. //-----------------------------------------------------------------------------
  757. // Purpose:
  758. //-----------------------------------------------------------------------------
  759. void Panel::SetPos(int x, int y)
  760. {
  761. if ( !HushAsserts() )
  762. {
  763. Assert( abs(x) < 32768 && abs(y) < 32768 );
  764. }
  765. ipanel()->SetPos(GetVPanel(), x, y);
  766. }
  767. //-----------------------------------------------------------------------------
  768. // Purpose:
  769. //-----------------------------------------------------------------------------
  770. void Panel::GetPos(int &x, int &y)
  771. {
  772. ipanel()->GetPos(GetVPanel(), x, y);
  773. }
  774. //-----------------------------------------------------------------------------
  775. // Purpose:
  776. //-----------------------------------------------------------------------------
  777. int Panel::GetXPos()
  778. {
  779. int x,y;
  780. GetPos( x, y );
  781. return x;
  782. }
  783. //-----------------------------------------------------------------------------
  784. // Purpose:
  785. //-----------------------------------------------------------------------------
  786. int Panel::GetYPos()
  787. {
  788. int x,y;
  789. GetPos( x, y );
  790. return y;
  791. }
  792. //-----------------------------------------------------------------------------
  793. // Purpose:
  794. //-----------------------------------------------------------------------------
  795. void Panel::SetSize(int wide, int tall)
  796. {
  797. tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "%s - %s", __FUNCTION__, GetName() );
  798. Assert( abs(wide) < 32768 && abs(tall) < 32768 );
  799. ipanel()->SetSize(GetVPanel(), wide, tall);
  800. }
  801. //-----------------------------------------------------------------------------
  802. // Purpose:
  803. //-----------------------------------------------------------------------------
  804. void Panel::GetSize(int &wide, int &tall)
  805. {
  806. ipanel()->GetSize(GetVPanel(), wide, tall);
  807. }
  808. //-----------------------------------------------------------------------------
  809. // Purpose:
  810. //-----------------------------------------------------------------------------
  811. void Panel::SetBounds(int x, int y, int wide, int tall)
  812. {
  813. SetPos(x,y);
  814. SetSize(wide,tall);
  815. }
  816. //-----------------------------------------------------------------------------
  817. // Purpose:
  818. //-----------------------------------------------------------------------------
  819. void Panel::GetBounds(int &x, int &y, int &wide, int &tall)
  820. {
  821. GetPos(x, y);
  822. GetSize(wide, tall);
  823. }
  824. //-----------------------------------------------------------------------------
  825. // Purpose: returns safe handle to parent
  826. //-----------------------------------------------------------------------------
  827. VPANEL Panel::GetVParent()
  828. {
  829. if ( ipanel() )
  830. {
  831. return ipanel()->GetParent(GetVPanel());
  832. }
  833. return 0;
  834. }
  835. //-----------------------------------------------------------------------------
  836. // Purpose: returns a pointer to a controls version of a Panel pointer
  837. //-----------------------------------------------------------------------------
  838. Panel *Panel::GetParent()
  839. {
  840. // get the parent and convert it to a Panel *
  841. // this is OK, the hierarchy is guaranteed to be all from the same module, except for the root node
  842. // the root node always returns NULL when a GetParent() is done so everything is OK
  843. if ( ipanel() )
  844. {
  845. VPANEL parent = ipanel()->GetParent(GetVPanel());
  846. if (parent)
  847. {
  848. Panel *pParent = ipanel()->GetPanel(parent, GetControlsModuleName());
  849. Assert(!pParent || !strcmp(pParent->GetModuleName(), GetControlsModuleName()));
  850. return pParent;
  851. }
  852. }
  853. return NULL;
  854. }
  855. //-----------------------------------------------------------------------------
  856. // Purpose: Screen size change notification handler
  857. //-----------------------------------------------------------------------------
  858. void Panel::OnScreenSizeChanged(int nOldWide, int nOldTall)
  859. {
  860. // post to all children
  861. for (int i = 0; i < ipanel()->GetChildCount(GetVPanel()); i++)
  862. {
  863. VPANEL child = ipanel()->GetChild(GetVPanel(), i);
  864. PostMessage(child, new KeyValues("OnScreenSizeChanged", "oldwide", nOldWide, "oldtall", nOldTall), NULL);
  865. }
  866. // make any currently fullsize window stay fullsize
  867. int x, y, wide, tall;
  868. GetBounds(x, y, wide, tall);
  869. int screenWide, screenTall;
  870. surface()->GetScreenSize(screenWide, screenTall);
  871. if (x == 0 && y == 0 && nOldWide == wide && tall == nOldTall)
  872. {
  873. // fullsize
  874. surface()->GetScreenSize(wide, tall);
  875. SetBounds(0, 0, wide, tall);
  876. }
  877. // panel needs to re-get it's scheme settings
  878. _flags.SetFlag( NEEDS_SCHEME_UPDATE );
  879. // invalidate our settings
  880. InvalidateLayout();
  881. }
  882. //-----------------------------------------------------------------------------
  883. // Purpose:
  884. //-----------------------------------------------------------------------------
  885. void Panel::SetVisible(bool state)
  886. {
  887. ipanel()->SetVisible(GetVPanel(), state);
  888. }
  889. //-----------------------------------------------------------------------------
  890. // Purpose:
  891. //-----------------------------------------------------------------------------
  892. bool Panel::IsVisible()
  893. {
  894. if (ipanel())
  895. {
  896. return ipanel()->IsVisible(GetVPanel());
  897. }
  898. return false;
  899. }
  900. //-----------------------------------------------------------------------------
  901. // Purpose:
  902. //-----------------------------------------------------------------------------
  903. void Panel::SetEnabled(bool state)
  904. {
  905. if (state != ipanel()->IsEnabled( GetVPanel()))
  906. {
  907. ipanel()->SetEnabled(GetVPanel(), state);
  908. InvalidateLayout(false);
  909. Repaint();
  910. }
  911. }
  912. //-----------------------------------------------------------------------------
  913. // Purpose:
  914. //-----------------------------------------------------------------------------
  915. bool Panel::IsEnabled()
  916. {
  917. return ipanel()->IsEnabled(GetVPanel());
  918. }
  919. //-----------------------------------------------------------------------------
  920. // Purpose:
  921. //-----------------------------------------------------------------------------
  922. bool Panel::IsPopup()
  923. {
  924. return ipanel()->IsPopup(GetVPanel());
  925. }
  926. //-----------------------------------------------------------------------------
  927. // Purpose:
  928. //-----------------------------------------------------------------------------
  929. void Panel::Repaint()
  930. {
  931. _flags.SetFlag( NEEDS_REPAINT );
  932. if (surface())
  933. {
  934. surface()->Invalidate(GetVPanel());
  935. }
  936. }
  937. //-----------------------------------------------------------------------------
  938. // Purpose:
  939. //-----------------------------------------------------------------------------
  940. void Panel::Think()
  941. {
  942. if (IsVisible())
  943. {
  944. // update any tooltips
  945. if (m_pTooltips)
  946. {
  947. m_pTooltips->PerformLayout();
  948. }
  949. if ( _flags.IsFlagSet( NEEDS_LAYOUT ) )
  950. {
  951. InternalPerformLayout();
  952. }
  953. }
  954. OnThink();
  955. }
  956. void Panel::OnChildSettingsApplied( KeyValues *pInResourceData, Panel *pChild )
  957. {
  958. tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "%s - %s", __FUNCTION__, GetName() );
  959. Panel* pParent = GetParent();
  960. if( pParent )
  961. {
  962. pParent->OnChildSettingsApplied( pInResourceData, pChild );
  963. }
  964. }
  965. //-----------------------------------------------------------------------------
  966. // Purpose:
  967. //-----------------------------------------------------------------------------
  968. void Panel::PaintTraverse( bool repaint, bool allowForce )
  969. {
  970. if ( m_bWorldPositionCurrentFrame )
  971. {
  972. surface()->SolveTraverse( GetVPanel() );
  973. }
  974. if ( !IsVisible() )
  975. {
  976. return;
  977. }
  978. float oldAlphaMultiplier = surface()->DrawGetAlphaMultiplier();
  979. float newAlphaMultiplier = oldAlphaMultiplier * m_flAlpha * 1.0f/255.0f;
  980. if ( IsXbox() && !newAlphaMultiplier )
  981. {
  982. // xbox optimization not suitable for pc
  983. // xbox panels are compliant and can early out and not traverse their children
  984. // when they have no opacity
  985. return;
  986. }
  987. if ( !repaint &&
  988. allowForce &&
  989. _flags.IsFlagSet( NEEDS_REPAINT ) )
  990. {
  991. repaint = true;
  992. _flags.ClearFlag( NEEDS_REPAINT );
  993. }
  994. VPANEL vpanel = GetVPanel();
  995. bool bPushedViewport = false;
  996. if( GetForceStereoRenderToFrameBuffer() )
  997. {
  998. CMatRenderContextPtr pRenderContext( materials );
  999. if( pRenderContext->GetRenderTarget() )
  1000. {
  1001. surface()->PushFullscreenViewport();
  1002. bPushedViewport = true;
  1003. }
  1004. }
  1005. int clipRect[4];
  1006. ipanel()->GetClipRect( vpanel, clipRect[0], clipRect[1], clipRect[2], clipRect[3] );
  1007. if ( ( clipRect[2] <= clipRect[0] ) || ( clipRect[3] <= clipRect[1] ) )
  1008. {
  1009. repaint = false;
  1010. }
  1011. // set global alpha
  1012. surface()->DrawSetAlphaMultiplier( newAlphaMultiplier );
  1013. bool bBorderPaintFirst = _border ? _border->PaintFirst() : false;
  1014. // draw the border first if requested to
  1015. if ( bBorderPaintFirst && repaint && _flags.IsFlagSet( PAINT_BORDER_ENABLED ) && ( _border != null ) )
  1016. {
  1017. // Paint the border over the background with no inset
  1018. surface()->PushMakeCurrent( vpanel, false );
  1019. PaintBorder();
  1020. surface()->PopMakeCurrent( vpanel );
  1021. }
  1022. if ( repaint )
  1023. {
  1024. // draw the background with no inset
  1025. if ( _flags.IsFlagSet( PAINT_BACKGROUND_ENABLED ) )
  1026. {
  1027. surface()->PushMakeCurrent( vpanel, false );
  1028. PaintBackground();
  1029. surface()->PopMakeCurrent( vpanel );
  1030. }
  1031. // draw the front of the panel with the inset
  1032. if ( _flags.IsFlagSet( PAINT_ENABLED ) )
  1033. {
  1034. surface()->PushMakeCurrent( vpanel, true );
  1035. Paint();
  1036. surface()->PopMakeCurrent( vpanel );
  1037. }
  1038. }
  1039. // traverse and paint all our children
  1040. CUtlVector< VPANEL > &children = ipanel()->GetChildren( vpanel );
  1041. int childCount = children.Count();
  1042. for (int i = 0; i < childCount; i++)
  1043. {
  1044. VPANEL child = children[ i ];
  1045. bool bVisible = ipanel()->IsVisible( child );
  1046. if ( surface()->ShouldPaintChildPanel( child ) )
  1047. {
  1048. if ( bVisible )
  1049. {
  1050. ipanel()->PaintTraverse( child, repaint, allowForce );
  1051. }
  1052. }
  1053. else
  1054. {
  1055. // Invalidate the child panel so that it gets redrawn
  1056. surface()->Invalidate( child );
  1057. // keep traversing the tree, just don't allow anyone to paint after here
  1058. if ( bVisible )
  1059. {
  1060. ipanel()->PaintTraverse( child, false, false );
  1061. }
  1062. }
  1063. }
  1064. // draw the border last
  1065. if ( repaint )
  1066. {
  1067. if ( !bBorderPaintFirst && _flags.IsFlagSet( PAINT_BORDER_ENABLED ) && ( _border != null ) )
  1068. {
  1069. // Paint the border over the background with no inset
  1070. surface()->PushMakeCurrent( vpanel, false );
  1071. PaintBorder();
  1072. surface()->PopMakeCurrent( vpanel );
  1073. }
  1074. #ifdef _DEBUG
  1075. // IsBuildGroupEnabled recurses up all the parents and ends up being very expensive as it wanders all over memory
  1076. if ( GetBuildModeDialogCount() && IsBuildGroupEnabled() ) //&& HasFocus() )
  1077. {
  1078. // outline all selected panels
  1079. // outline all selected panels
  1080. CUtlVector<PHandle> *controlGroup = _buildGroup->GetControlGroup();
  1081. for (int i=0; i < controlGroup->Size(); ++i)
  1082. {
  1083. surface()->PushMakeCurrent( ((*controlGroup)[i].Get())->GetVPanel(), false );
  1084. ((*controlGroup)[i].Get())->PaintBuildOverlay();
  1085. surface()->PopMakeCurrent( ((*controlGroup)[i].Get())->GetVPanel() );
  1086. }
  1087. _buildGroup->DrawRulers();
  1088. }
  1089. #endif
  1090. // All of our children have painted, etc, now allow painting in top of them
  1091. if ( _flags.IsFlagSet( POST_CHILD_PAINT_ENABLED ) )
  1092. {
  1093. surface()->PushMakeCurrent( vpanel, false );
  1094. PostChildPaint();
  1095. surface()->PopMakeCurrent( vpanel );
  1096. }
  1097. }
  1098. surface()->DrawSetAlphaMultiplier( oldAlphaMultiplier );
  1099. surface()->SwapBuffers( vpanel );
  1100. if( bPushedViewport )
  1101. {
  1102. surface()->PopFullscreenViewport();
  1103. }
  1104. }
  1105. //-----------------------------------------------------------------------------
  1106. // Purpose:
  1107. //-----------------------------------------------------------------------------
  1108. void Panel::PaintBorder()
  1109. {
  1110. _border->Paint(GetVPanel());
  1111. }
  1112. //-----------------------------------------------------------------------------
  1113. // Purpose:
  1114. //-----------------------------------------------------------------------------
  1115. void Panel::PaintBackground()
  1116. {
  1117. int wide, tall;
  1118. GetSize( wide, tall );
  1119. if ( m_SkipChild.Get() && m_SkipChild->IsVisible() )
  1120. {
  1121. if ( GetPaintBackgroundType() == 2 )
  1122. {
  1123. int cornerWide, cornerTall;
  1124. GetCornerTextureSize( cornerWide, cornerTall );
  1125. Color col = GetBgColor();
  1126. DrawHollowBox( 0, 0, wide, tall, col, 1.0f );
  1127. wide -= 2 * cornerWide;
  1128. tall -= 2 * cornerTall;
  1129. FillRectSkippingPanel( GetBgColor(), cornerWide, cornerTall, wide, tall, m_SkipChild.Get() );
  1130. }
  1131. else
  1132. {
  1133. FillRectSkippingPanel( GetBgColor(), 0, 0, wide, tall, m_SkipChild.Get() );
  1134. }
  1135. }
  1136. else
  1137. {
  1138. Color col = GetBgColor();
  1139. switch ( m_nPaintBackgroundType )
  1140. {
  1141. default:
  1142. case 0:
  1143. {
  1144. surface()->DrawSetColor(col);
  1145. surface()->DrawFilledRect(0, 0, wide, tall);
  1146. }
  1147. break;
  1148. case 1:
  1149. {
  1150. DrawTexturedBox( 0, 0, wide, tall, col, 1.0f );
  1151. }
  1152. break;
  1153. case 2:
  1154. {
  1155. DrawBox( 0, 0, wide, tall, col, 1.0f );
  1156. }
  1157. break;
  1158. case 3:
  1159. {
  1160. DrawBoxFade( 0, 0, wide, tall, col, 1.0f, 255, 0, true );
  1161. }
  1162. break;
  1163. }
  1164. }
  1165. }
  1166. //-----------------------------------------------------------------------------
  1167. // Purpose:
  1168. //-----------------------------------------------------------------------------
  1169. void Panel::Paint()
  1170. {
  1171. // empty on purpose
  1172. // PaintBackground is painted and default behavior is for Paint to do nothing
  1173. }
  1174. //-----------------------------------------------------------------------------
  1175. // Purpose:
  1176. //-----------------------------------------------------------------------------
  1177. void Panel::PostChildPaint()
  1178. {
  1179. // Empty on purpose
  1180. // This is called if _postChildPaintEnabled is true and allows painting to
  1181. // continue on the surface after all of the panel's children have painted
  1182. // themselves. Allows drawing an overlay on top of the children, etc.
  1183. }
  1184. //-----------------------------------------------------------------------------
  1185. // Purpose: Draws a black rectangle around the panel.
  1186. //-----------------------------------------------------------------------------
  1187. void Panel::PaintBuildOverlay()
  1188. {
  1189. int wide,tall;
  1190. GetSize(wide,tall);
  1191. surface()->DrawSetColor(0, 0, 0, 255);
  1192. surface()->DrawFilledRect(0,0,wide,2); //top
  1193. surface()->DrawFilledRect(0,tall-2,wide,tall); //bottom
  1194. surface()->DrawFilledRect(0,2,2,tall-2); //left
  1195. surface()->DrawFilledRect(wide-2,2,wide,tall-2); //right
  1196. }
  1197. //-----------------------------------------------------------------------------
  1198. // Purpose: Returns true if the panel's draw code will fully cover it's area
  1199. //-----------------------------------------------------------------------------
  1200. bool Panel::IsOpaque()
  1201. {
  1202. // FIXME: Add code to account for the 'SkipChild' functionality in Frame
  1203. if ( IsVisible() && _flags.IsFlagSet( PAINT_BACKGROUND_ENABLED ) && ( _bgColor[3] == 255 ) )
  1204. return true;
  1205. return false;
  1206. }
  1207. //-----------------------------------------------------------------------------
  1208. // Purpose: returns true if the settings are aligned to the right of the screen
  1209. //-----------------------------------------------------------------------------
  1210. bool Panel::IsRightAligned()
  1211. {
  1212. return (_buildModeFlags & BUILDMODE_SAVE_XPOS_RIGHTALIGNED);
  1213. }
  1214. //-----------------------------------------------------------------------------
  1215. // Purpose: returns true if the settings are aligned to the bottom of the screen
  1216. //-----------------------------------------------------------------------------
  1217. bool Panel::IsBottomAligned()
  1218. {
  1219. return (_buildModeFlags & BUILDMODE_SAVE_YPOS_BOTTOMALIGNED);
  1220. }
  1221. //-----------------------------------------------------------------------------
  1222. // Purpose: sets the parent
  1223. //-----------------------------------------------------------------------------
  1224. void Panel::SetParent(Panel *newParent)
  1225. {
  1226. // Assert that the parent is from the same module as the child
  1227. // FIXME: !!! work out how to handle this properly!
  1228. // Assert(!newParent || !strcmp(newParent->GetModuleName(), GetControlsModuleName()));
  1229. Panel* pCurrentParent = GetParent();
  1230. if ( pCurrentParent )
  1231. {
  1232. pCurrentParent->m_dictChidlren.Remove( GetName() );
  1233. }
  1234. if (newParent)
  1235. {
  1236. SetParent(newParent->GetVPanel());
  1237. }
  1238. else
  1239. {
  1240. SetParent((VPANEL)NULL);
  1241. }
  1242. }
  1243. //-----------------------------------------------------------------------------
  1244. // Purpose:
  1245. //-----------------------------------------------------------------------------
  1246. void Panel::SetParent(VPANEL newParent)
  1247. {
  1248. if (newParent)
  1249. {
  1250. ipanel()->SetParent(GetVPanel(), newParent);
  1251. }
  1252. else
  1253. {
  1254. ipanel()->SetParent(GetVPanel(), NULL);
  1255. }
  1256. if (GetVParent() && !IsPopup())
  1257. {
  1258. SetProportional(ipanel()->IsProportional(GetVParent()));
  1259. // most of the time KBInput == parents kbinput
  1260. if (ipanel()->IsKeyBoardInputEnabled(GetVParent()) != IsKeyBoardInputEnabled())
  1261. {
  1262. SetKeyBoardInputEnabled(ipanel()->IsKeyBoardInputEnabled(GetVParent()));
  1263. }
  1264. if (ipanel()->IsMouseInputEnabled(GetVParent()) != IsMouseInputEnabled())
  1265. {
  1266. SetMouseInputEnabled(ipanel()->IsMouseInputEnabled(GetVParent()));
  1267. }
  1268. }
  1269. UpdateSiblingPin();
  1270. }
  1271. //-----------------------------------------------------------------------------
  1272. // Purpose:
  1273. //-----------------------------------------------------------------------------
  1274. void Panel::OnChildAdded(VPANEL child)
  1275. {
  1276. Assert( !_flags.IsFlagSet( IN_PERFORM_LAYOUT ) );
  1277. Panel *pChild = ipanel()->GetPanel(child, GetControlsModuleName());
  1278. if ( pChild )
  1279. {
  1280. auto idx = m_dictChidlren.Insert( pChild->GetName() );
  1281. m_dictChidlren[ idx ].Set( child );
  1282. }
  1283. }
  1284. //-----------------------------------------------------------------------------
  1285. // Purpose: default message handler
  1286. //-----------------------------------------------------------------------------
  1287. void Panel::OnSizeChanged(int newWide, int newTall)
  1288. {
  1289. InvalidateLayout(); // our size changed so force us to layout again
  1290. }
  1291. //-----------------------------------------------------------------------------
  1292. // Purpose: sets Z ordering - lower numbers are always behind higher z's
  1293. //-----------------------------------------------------------------------------
  1294. void Panel::SetZPos(int z)
  1295. {
  1296. ipanel()->SetZPos(GetVPanel(), z);
  1297. }
  1298. //-----------------------------------------------------------------------------
  1299. // Purpose: sets Z ordering - lower numbers are always behind higher z's
  1300. //-----------------------------------------------------------------------------
  1301. int Panel::GetZPos() const
  1302. {
  1303. return ( ipanel()->GetZPos( GetVPanel() ) );
  1304. }
  1305. //-----------------------------------------------------------------------------
  1306. // Purpose: sets alpha modifier for panel and all child panels [0..255]
  1307. //-----------------------------------------------------------------------------
  1308. void Panel::SetAlpha(int alpha)
  1309. {
  1310. m_flAlpha = alpha;
  1311. }
  1312. //-----------------------------------------------------------------------------
  1313. // Purpose: data accessor
  1314. //-----------------------------------------------------------------------------
  1315. int Panel::GetAlpha()
  1316. {
  1317. return (int)m_flAlpha;
  1318. }
  1319. //-----------------------------------------------------------------------------
  1320. // Purpose: Moves the panel to the front of the z-order
  1321. //-----------------------------------------------------------------------------
  1322. void Panel::MoveToFront(void)
  1323. {
  1324. // FIXME: only use ipanel() as per src branch?
  1325. if (IsPopup())
  1326. {
  1327. surface()->BringToFront(GetVPanel());
  1328. }
  1329. else
  1330. {
  1331. ipanel()->MoveToFront(GetVPanel());
  1332. }
  1333. }
  1334. //-----------------------------------------------------------------------------
  1335. // Purpose: Iterates up the hierarchy looking for a particular parent
  1336. //-----------------------------------------------------------------------------
  1337. bool Panel::HasParent(VPANEL potentialParent)
  1338. {
  1339. if (!potentialParent)
  1340. return false;
  1341. return ipanel()->HasParent(GetVPanel(), potentialParent);
  1342. }
  1343. //-----------------------------------------------------------------------------
  1344. // Purpose: Finds the index of a child panel by string name
  1345. // Output : int - -1 if no panel of that name is found
  1346. //-----------------------------------------------------------------------------
  1347. int Panel::FindChildIndexByName(const char *childName)
  1348. {
  1349. for (int i = 0; i < GetChildCount(); i++)
  1350. {
  1351. Panel *pChild = GetChild(i);
  1352. if (!pChild)
  1353. continue;
  1354. if (!stricmp(pChild->GetName(), childName))
  1355. {
  1356. return i;
  1357. }
  1358. }
  1359. return -1;
  1360. }
  1361. //-----------------------------------------------------------------------------
  1362. // Purpose: Finds a child panel by string name
  1363. // Output : Panel * - NULL if no panel of that name is found
  1364. //-----------------------------------------------------------------------------
  1365. Panel *Panel::FindChildByName(const char *childName, bool recurseDown)
  1366. {
  1367. tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "%s - %s finding %s", __FUNCTION__, GetName(), childName );
  1368. auto idx = m_dictChidlren.Find( childName );
  1369. if ( idx != m_dictChidlren.InvalidIndex() )
  1370. {
  1371. Panel *pCachedChild = ipanel()->GetPanel( m_dictChidlren[ idx ], GetControlsModuleName() );
  1372. if ( !pCachedChild )
  1373. {
  1374. m_dictChidlren.Remove( childName );
  1375. }
  1376. else
  1377. {
  1378. return pCachedChild;
  1379. }
  1380. }
  1381. for (int i = 0; i < GetChildCount(); i++)
  1382. {
  1383. Panel *pChild = GetChild(i);
  1384. if (!pChild)
  1385. continue;
  1386. if (!V_stricmp(pChild->GetName(), childName))
  1387. {
  1388. idx = m_dictChidlren.Insert( childName );
  1389. m_dictChidlren[ idx ].Set( pChild->GetVPanel() );
  1390. return pChild;
  1391. }
  1392. if (recurseDown)
  1393. {
  1394. Panel *panel = pChild->FindChildByName(childName, recurseDown);
  1395. if ( panel )
  1396. {
  1397. return panel;
  1398. }
  1399. }
  1400. }
  1401. m_dictChidlren.Insert( childName ); // Defaults the handle to INVALID_PANEL
  1402. return NULL;
  1403. }
  1404. //-----------------------------------------------------------------------------
  1405. // Purpose: Finds a sibling panel by name
  1406. //-----------------------------------------------------------------------------
  1407. Panel *Panel::FindSiblingByName(const char *siblingName)
  1408. {
  1409. if ( !GetVParent() )
  1410. return NULL;
  1411. int siblingCount = ipanel()->GetChildCount(GetVParent());
  1412. for (int i = 0; i < siblingCount; i++)
  1413. {
  1414. VPANEL sibling = ipanel()->GetChild(GetVParent(), i);
  1415. Panel *panel = ipanel()->GetPanel(sibling, GetControlsModuleName());
  1416. if (!stricmp(panel->GetName(), siblingName))
  1417. {
  1418. return panel;
  1419. }
  1420. }
  1421. return NULL;
  1422. }
  1423. //-----------------------------------------------------------------------------
  1424. // Purpose: Dispatches immediately a message to the parent
  1425. //-----------------------------------------------------------------------------
  1426. void Panel::CallParentFunction(KeyValues *message)
  1427. {
  1428. if (GetVParent())
  1429. {
  1430. ipanel()->SendMessage(GetVParent(), message, GetVPanel());
  1431. }
  1432. if (message)
  1433. {
  1434. message->deleteThis();
  1435. }
  1436. }
  1437. //-----------------------------------------------------------------------------
  1438. // Purpose: if set to true, panel automatically frees itself when parent is deleted
  1439. //-----------------------------------------------------------------------------
  1440. void Panel::SetAutoDelete( bool state )
  1441. {
  1442. _flags.SetFlag( AUTODELETE_ENABLED, state );
  1443. }
  1444. //-----------------------------------------------------------------------------
  1445. // Purpose:
  1446. //-----------------------------------------------------------------------------
  1447. bool Panel::IsAutoDeleteSet()
  1448. {
  1449. return _flags.IsFlagSet( AUTODELETE_ENABLED );
  1450. }
  1451. //-----------------------------------------------------------------------------
  1452. // Purpose: Just calls 'delete this'
  1453. //-----------------------------------------------------------------------------
  1454. void Panel::DeletePanel()
  1455. {
  1456. // Avoid re-entrancy
  1457. _flags.SetFlag( MARKED_FOR_DELETION );
  1458. _flags.ClearFlag( AUTODELETE_ENABLED );
  1459. delete this;
  1460. }
  1461. //-----------------------------------------------------------------------------
  1462. // Purpose: data accessor
  1463. //-----------------------------------------------------------------------------
  1464. HScheme Panel::GetScheme()
  1465. {
  1466. if (m_iScheme)
  1467. {
  1468. return m_iScheme; // return our internal scheme
  1469. }
  1470. if (GetVParent()) // recurse down the heirarchy
  1471. {
  1472. return ipanel()->GetScheme(GetVParent());
  1473. }
  1474. return scheme()->GetDefaultScheme();
  1475. }
  1476. //-----------------------------------------------------------------------------
  1477. // Purpose: set the scheme to render this panel with by name
  1478. //-----------------------------------------------------------------------------
  1479. void Panel::SetScheme(const char *tag)
  1480. {
  1481. if (strlen(tag) > 0 && scheme()->GetScheme(tag)) // check the scheme exists
  1482. {
  1483. SetScheme(scheme()->GetScheme(tag));
  1484. }
  1485. }
  1486. //-----------------------------------------------------------------------------
  1487. // Purpose: set the scheme to render this panel with
  1488. //-----------------------------------------------------------------------------
  1489. void Panel::SetScheme(HScheme scheme)
  1490. {
  1491. if (scheme != m_iScheme)
  1492. {
  1493. m_iScheme = scheme;
  1494. // This will cause the new scheme to be applied at a later point
  1495. // InvalidateLayout( false, true );
  1496. }
  1497. }
  1498. //-----------------------------------------------------------------------------
  1499. // Purpose: returns the char of this panels hotkey
  1500. //-----------------------------------------------------------------------------
  1501. Panel *Panel::HasHotkey(wchar_t key)
  1502. {
  1503. return NULL;
  1504. }
  1505. #if defined( VGUI_USEDRAGDROP )
  1506. static vgui::PHandle g_DragDropCapture;
  1507. #endif // VGUI_USEDRAGDROP
  1508. void Panel::InternalCursorMoved(int x, int y)
  1509. {
  1510. #if defined( VGUI_USEDRAGDROP )
  1511. if ( g_DragDropCapture.Get() )
  1512. {
  1513. bool started = g_DragDropCapture->GetDragDropInfo()->m_bDragStarted;
  1514. g_DragDropCapture->OnContinueDragging();
  1515. if ( started )
  1516. {
  1517. bool isEscapeKeyDown = input()->IsKeyDown( KEY_ESCAPE );
  1518. if ( isEscapeKeyDown )
  1519. {
  1520. g_DragDropCapture->OnFinishDragging( true, (MouseCode)-1, true );
  1521. }
  1522. return;
  1523. }
  1524. }
  1525. #endif // VGUI_USEDRAGDROP
  1526. if ( !ShouldHandleInputMessage() )
  1527. return;
  1528. if ( IsCursorNone() )
  1529. return;
  1530. if ( !IsMouseInputEnabled() )
  1531. {
  1532. return;
  1533. }
  1534. if (IsBuildGroupEnabled())
  1535. {
  1536. if ( _buildGroup->CursorMoved(x, y, this) )
  1537. {
  1538. return;
  1539. }
  1540. }
  1541. if (m_pTooltips)
  1542. {
  1543. if ( _tooltipText )
  1544. {
  1545. m_pTooltips->SetText( _tooltipText );
  1546. }
  1547. m_pTooltips->ShowTooltip(this);
  1548. }
  1549. ScreenToLocal(x, y);
  1550. OnCursorMoved(x, y);
  1551. }
  1552. void Panel::InternalCursorEntered()
  1553. {
  1554. if (IsCursorNone() || !IsMouseInputEnabled())
  1555. return;
  1556. if (IsBuildGroupEnabled())
  1557. return;
  1558. if (m_pTooltips)
  1559. {
  1560. m_pTooltips->ResetDelay();
  1561. if ( _tooltipText )
  1562. {
  1563. m_pTooltips->SetText( _tooltipText );
  1564. }
  1565. m_pTooltips->ShowTooltip(this);
  1566. }
  1567. OnCursorEntered();
  1568. }
  1569. void Panel::InternalCursorExited()
  1570. {
  1571. if (IsCursorNone() || !IsMouseInputEnabled())
  1572. return;
  1573. if (IsBuildGroupEnabled())
  1574. return;
  1575. if (m_pTooltips)
  1576. {
  1577. m_pTooltips->HideTooltip();
  1578. }
  1579. OnCursorExited();
  1580. }
  1581. bool Panel::IsChildOfSurfaceModalPanel()
  1582. {
  1583. VPANEL appModalPanel = input()->GetAppModalSurface();
  1584. if ( !appModalPanel )
  1585. return true;
  1586. if ( ipanel()->HasParent( GetVPanel(), appModalPanel ) )
  1587. return true;
  1588. return false;
  1589. }
  1590. //-----------------------------------------------------------------------------
  1591. // Purpose:
  1592. // Input : -
  1593. // Output : Returns true on success, false on failure.
  1594. //-----------------------------------------------------------------------------
  1595. bool Panel::IsChildOfModalSubTree()
  1596. {
  1597. VPANEL subTree = input()->GetModalSubTree();
  1598. if ( !subTree )
  1599. return true;
  1600. if ( HasParent( subTree ) )
  1601. return true;
  1602. return false;
  1603. }
  1604. //-----------------------------------------------------------------------------
  1605. // Purpose: Checks to see if message is being subverted due to modal subtree logic
  1606. // Input : -
  1607. // Output : Returns true on success, false on failure.
  1608. //-----------------------------------------------------------------------------
  1609. static bool ShouldHandleInputMessage( VPANEL p )
  1610. {
  1611. // If there is not modal subtree, then always handle the msg
  1612. if ( !input()->GetModalSubTree() )
  1613. return true;
  1614. // What state are we in?
  1615. bool bChildOfModal = false;
  1616. VPANEL subTree = input()->GetModalSubTree();
  1617. if ( !subTree )
  1618. {
  1619. bChildOfModal = true;
  1620. }
  1621. else if ( ipanel()->HasParent( p, subTree ) )
  1622. {
  1623. bChildOfModal = true;
  1624. }
  1625. if ( input()->ShouldModalSubTreeReceiveMessages() )
  1626. return bChildOfModal;
  1627. return !bChildOfModal;
  1628. }
  1629. bool Panel::ShouldHandleInputMessage()
  1630. {
  1631. return ::ShouldHandleInputMessage( GetVPanel() );
  1632. }
  1633. void Panel::InternalMousePressed(int code)
  1634. {
  1635. long curtime = system()->GetTimeMillis();
  1636. if ( IsTriplePressAllowed() )
  1637. {
  1638. long elapsed = curtime - m_lLastDoublePressTime;
  1639. if ( elapsed < TRIPLE_PRESS_MSEC )
  1640. {
  1641. InternalMouseTriplePressed( code );
  1642. return;
  1643. }
  1644. }
  1645. // The menu system passively watches for mouse released messages so it
  1646. // can clear any open menus if the release is somewhere other than on a menu
  1647. Menu::OnInternalMousePressed( this, (MouseCode)code );
  1648. if ( !ShouldHandleInputMessage() )
  1649. return;
  1650. if ( IsCursorNone() )
  1651. return;
  1652. if ( !IsMouseInputEnabled())
  1653. {
  1654. #if defined( VGUI_USEDRAGDROP )
  1655. DragDropStartDragging();
  1656. #endif
  1657. return;
  1658. }
  1659. if (IsBuildGroupEnabled())
  1660. {
  1661. if ( _buildGroup->MousePressed((MouseCode)code, this) )
  1662. {
  1663. return;
  1664. }
  1665. }
  1666. #ifdef STAGING_ONLY
  1667. // If holding CTRL + ALT, invalidate layout. For debugging purposes
  1668. if ( ( vgui::input()->IsKeyDown(KEY_LCONTROL) || vgui::input()->IsKeyDown(KEY_RCONTROL) )
  1669. && ( vgui::input()->IsKeyDown(KEY_LALT) || vgui::input()->IsKeyDown(KEY_RALT) ) )
  1670. {
  1671. InvalidateLayout( true, true );
  1672. }
  1673. #endif
  1674. #ifdef STAGING_ONLY
  1675. const char *pGameDir = CommandLine()->ParmValue( "-game", "hl2" );
  1676. if ( !V_stricmp( pGameDir, "tf" ) )
  1677. {
  1678. if ( code >= MOUSE_LEFT && code <= MOUSE_MIDDLE )
  1679. {
  1680. m_sMousePressedPanels[ code - MOUSE_LEFT ] = this;
  1681. }
  1682. }
  1683. #endif
  1684. Panel *pMouseHandler = m_hMouseEventHandler.Get();
  1685. if ( pMouseHandler )
  1686. {
  1687. pMouseHandler->OnMousePressed( (MouseCode)code );
  1688. }
  1689. else
  1690. {
  1691. OnMousePressed( (MouseCode)code );
  1692. }
  1693. #if defined( VGUI_USEDRAGDROP )
  1694. DragDropStartDragging();
  1695. #endif
  1696. }
  1697. void Panel::InternalMouseDoublePressed(int code)
  1698. {
  1699. m_lLastDoublePressTime = system()->GetTimeMillis();
  1700. if ( !ShouldHandleInputMessage() )
  1701. return;
  1702. if ( IsCursorNone() )
  1703. return;
  1704. if ( !IsMouseInputEnabled())
  1705. {
  1706. return;
  1707. }
  1708. if (IsBuildGroupEnabled())
  1709. {
  1710. if ( _buildGroup->MouseDoublePressed((MouseCode)code, this) )
  1711. {
  1712. return;
  1713. }
  1714. }
  1715. Panel *pMouseHandler = m_hMouseEventHandler.Get();
  1716. if ( pMouseHandler )
  1717. {
  1718. pMouseHandler->OnMouseDoublePressed( (MouseCode)code );
  1719. }
  1720. else
  1721. {
  1722. OnMouseDoublePressed( (MouseCode)code );
  1723. }
  1724. }
  1725. #if defined( VGUI_USEDRAGDROP )
  1726. void Panel::SetStartDragWhenMouseExitsPanel( bool state )
  1727. {
  1728. _flags.SetFlag( DRAG_REQUIRES_PANEL_EXIT, state );
  1729. }
  1730. bool Panel::IsStartDragWhenMouseExitsPanel() const
  1731. {
  1732. return _flags.IsFlagSet( DRAG_REQUIRES_PANEL_EXIT );
  1733. }
  1734. #endif // VGUI_USEDRAGDROP
  1735. void Panel::SetTriplePressAllowed( bool state )
  1736. {
  1737. _flags.SetFlag( TRIPLE_PRESS_ALLOWED, state );
  1738. }
  1739. bool Panel::IsTriplePressAllowed() const
  1740. {
  1741. return _flags.IsFlagSet( TRIPLE_PRESS_ALLOWED );
  1742. }
  1743. void Panel::InternalMouseTriplePressed( int code )
  1744. {
  1745. Assert( IsTriplePressAllowed() );
  1746. m_lLastDoublePressTime = 0L;
  1747. if ( !ShouldHandleInputMessage() )
  1748. return;
  1749. if ( IsCursorNone() )
  1750. return;
  1751. if ( !IsMouseInputEnabled())
  1752. {
  1753. #if defined( VGUI_USEDRAGDROP )
  1754. DragDropStartDragging();
  1755. #endif
  1756. return;
  1757. }
  1758. if (IsBuildGroupEnabled())
  1759. {
  1760. return;
  1761. }
  1762. OnMouseTriplePressed((MouseCode)code);
  1763. #if defined( VGUI_USEDRAGDROP )
  1764. DragDropStartDragging();
  1765. #endif
  1766. }
  1767. void Panel::InternalMouseReleased(int code)
  1768. {
  1769. #if defined( VGUI_USEDRAGDROP )
  1770. if ( g_DragDropCapture.Get() )
  1771. {
  1772. bool started = g_DragDropCapture->GetDragDropInfo()->m_bDragStarted;
  1773. g_DragDropCapture->OnFinishDragging( true, (MouseCode)code );
  1774. if ( started )
  1775. {
  1776. return;
  1777. }
  1778. }
  1779. #endif
  1780. if ( !ShouldHandleInputMessage() )
  1781. return;
  1782. if ( IsCursorNone() )
  1783. return;
  1784. if ( !IsMouseInputEnabled())
  1785. {
  1786. return;
  1787. }
  1788. if (IsBuildGroupEnabled())
  1789. {
  1790. if ( _buildGroup->MouseReleased((MouseCode)code, this) )
  1791. {
  1792. return;
  1793. }
  1794. }
  1795. #ifdef STAGING_ONLY
  1796. const char *pGameDir = CommandLine()->ParmValue( "-game", "hl2" );
  1797. if ( tf_strict_mouse_up_events.GetBool() && !V_stricmp( pGameDir, "tf" ) )
  1798. {
  1799. // Only allow mouse release events to go to panels that we also
  1800. // first clicked into
  1801. if ( code >= MOUSE_LEFT && code <= MOUSE_MIDDLE )
  1802. {
  1803. const int nIndex = code - MOUSE_LEFT;
  1804. Panel* pPressedPanel = m_sMousePressedPanels[ nIndex ];
  1805. m_sMousePressedPanels[ nIndex ] = NULL; // Clear out pressed panel
  1806. if ( pPressedPanel != this )
  1807. {
  1808. OnMouseMismatchedRelease( (MouseCode)code, pPressedPanel );
  1809. return;
  1810. }
  1811. }
  1812. }
  1813. #endif
  1814. OnMouseReleased((MouseCode)code);
  1815. }
  1816. void Panel::InternalMouseWheeled(int delta)
  1817. {
  1818. if (IsBuildGroupEnabled() || !IsMouseInputEnabled())
  1819. {
  1820. return;
  1821. }
  1822. if ( !ShouldHandleInputMessage() )
  1823. return;
  1824. OnMouseWheeled(delta);
  1825. }
  1826. void Panel::InternalKeyCodePressed(int code)
  1827. {
  1828. if ( !ShouldHandleInputMessage() )
  1829. return;
  1830. if (IsKeyBoardInputEnabled())
  1831. {
  1832. OnKeyCodePressed((KeyCode)code);
  1833. }
  1834. else
  1835. {
  1836. CallParentFunction(new KeyValues("KeyCodePressed", "code", code));
  1837. }
  1838. }
  1839. #if defined( VGUI_USEKEYBINDINGMAPS )
  1840. //-----------------------------------------------------------------------------
  1841. // Purpose:
  1842. // Input : *bindingName -
  1843. // keycode -
  1844. // modifiers -
  1845. //-----------------------------------------------------------------------------
  1846. void Panel::AddKeyBinding( char const *bindingName, int keycode, int modifiers )
  1847. {
  1848. PanelKeyBindingMap *map = LookupMapForBinding( bindingName );
  1849. if ( !map )
  1850. {
  1851. Assert( 0 );
  1852. return;
  1853. }
  1854. BoundKey_t kb;
  1855. kb.isbuiltin = false;
  1856. kb.bindingname = CopyString( bindingName );
  1857. kb.keycode = keycode;
  1858. kb.modifiers = modifiers;
  1859. map->boundkeys.AddToTail( kb );
  1860. }
  1861. KeyBindingMap_t *Panel::LookupBinding( char const *bindingName )
  1862. {
  1863. PanelKeyBindingMap *map = GetKBMap();
  1864. while( map )
  1865. {
  1866. int c = map->entries.Count();
  1867. for( int i = 0; i < c ; ++i )
  1868. {
  1869. KeyBindingMap_t *binding = &map->entries[ i ];
  1870. if ( !Q_stricmp( binding->bindingname, bindingName ) )
  1871. return binding;
  1872. }
  1873. map = map->baseMap;
  1874. }
  1875. return NULL;
  1876. }
  1877. PanelKeyBindingMap *Panel::LookupMapForBinding( char const *bindingName )
  1878. {
  1879. PanelKeyBindingMap *map = GetKBMap();
  1880. while( map )
  1881. {
  1882. int c = map->entries.Count();
  1883. for( int i = 0; i < c ; ++i )
  1884. {
  1885. KeyBindingMap_t *binding = &map->entries[ i ];
  1886. if ( !Q_stricmp( binding->bindingname, bindingName ) )
  1887. return map;
  1888. }
  1889. map = map->baseMap;
  1890. }
  1891. return NULL;
  1892. }
  1893. KeyBindingMap_t *Panel::LookupBindingByKeyCode( KeyCode code, int modifiers )
  1894. {
  1895. PanelKeyBindingMap *map = GetKBMap();
  1896. while( map )
  1897. {
  1898. int c = map->boundkeys.Count();
  1899. for( int i = 0; i < c ; ++i )
  1900. {
  1901. BoundKey_t *kb = &map->boundkeys[ i ];
  1902. if ( kb->keycode == code && kb->modifiers == modifiers )
  1903. {
  1904. KeyBindingMap_t *binding = LookupBinding( kb->bindingname );
  1905. Assert( binding );
  1906. if ( binding )
  1907. {
  1908. return binding;
  1909. }
  1910. }
  1911. }
  1912. map = map->baseMap;
  1913. }
  1914. return NULL;
  1915. }
  1916. BoundKey_t *Panel::LookupDefaultKey( char const *bindingName )
  1917. {
  1918. PanelKeyBindingMap *map = GetKBMap();
  1919. while( map )
  1920. {
  1921. int c = map->defaultkeys.Count();
  1922. for( int i = 0; i < c ; ++i )
  1923. {
  1924. BoundKey_t *kb = &map->defaultkeys[ i ];
  1925. if ( !Q_stricmp( kb->bindingname, bindingName ) )
  1926. {
  1927. return kb;
  1928. }
  1929. }
  1930. map = map->baseMap;
  1931. }
  1932. return NULL;
  1933. }
  1934. void Panel::LookupBoundKeys( char const *bindingName, CUtlVector< BoundKey_t * >& list )
  1935. {
  1936. PanelKeyBindingMap *map = GetKBMap();
  1937. while( map )
  1938. {
  1939. int c = map->boundkeys.Count();
  1940. for( int i = 0; i < c ; ++i )
  1941. {
  1942. BoundKey_t *kb = &map->boundkeys[ i ];
  1943. if ( !Q_stricmp( kb->bindingname, bindingName ) )
  1944. {
  1945. list.AddToTail( kb );
  1946. }
  1947. }
  1948. map = map->baseMap;
  1949. }
  1950. }
  1951. void Panel::RevertKeyBindingsToDefault()
  1952. {
  1953. PanelKeyBindingMap *map = GetKBMap();
  1954. while( map )
  1955. {
  1956. map->boundkeys.RemoveAll();
  1957. map->boundkeys = map->defaultkeys;
  1958. map = map->baseMap;
  1959. }
  1960. }
  1961. void Panel::RemoveAllKeyBindings()
  1962. {
  1963. PanelKeyBindingMap *map = GetKBMap();
  1964. while( map )
  1965. {
  1966. map->boundkeys.RemoveAll();
  1967. map = map->baseMap;
  1968. }
  1969. }
  1970. //-----------------------------------------------------------------------------
  1971. // Purpose:
  1972. // Input : -
  1973. //-----------------------------------------------------------------------------
  1974. void Panel::ReloadKeyBindings()
  1975. {
  1976. RevertKeyBindingsToDefault();
  1977. LoadKeyBindingsForOnePanel( GetKeyBindingsContext(), this );
  1978. }
  1979. #define MAKE_STRING( x ) #x
  1980. #define KEY_NAME( str, disp ) { KEY_##str, MAKE_STRING( KEY_##str ), disp }
  1981. struct KeyNames_t
  1982. {
  1983. KeyCode code;
  1984. char const *string;
  1985. char const *displaystring;
  1986. };
  1987. static KeyNames_t g_KeyNames[] =
  1988. {
  1989. KEY_NAME( NONE, "None" ),
  1990. KEY_NAME( 0, "0" ),
  1991. KEY_NAME( 1, "1" ),
  1992. KEY_NAME( 2, "2" ),
  1993. KEY_NAME( 3, "3" ),
  1994. KEY_NAME( 4, "4" ),
  1995. KEY_NAME( 5, "5" ),
  1996. KEY_NAME( 6, "6" ),
  1997. KEY_NAME( 7, "7" ),
  1998. KEY_NAME( 8, "8" ),
  1999. KEY_NAME( 9, "9" ),
  2000. KEY_NAME( A, "A" ),
  2001. KEY_NAME( B, "B" ),
  2002. KEY_NAME( C, "C" ),
  2003. KEY_NAME( D, "D" ),
  2004. KEY_NAME( E, "E" ),
  2005. KEY_NAME( F, "F" ),
  2006. KEY_NAME( G, "G" ),
  2007. KEY_NAME( H, "H" ),
  2008. KEY_NAME( I, "I" ),
  2009. KEY_NAME( J, "J" ),
  2010. KEY_NAME( K, "K" ),
  2011. KEY_NAME( L, "L" ),
  2012. KEY_NAME( M, "M" ),
  2013. KEY_NAME( N, "N" ),
  2014. KEY_NAME( O, "O" ),
  2015. KEY_NAME( P, "P" ),
  2016. KEY_NAME( Q, "Q" ),
  2017. KEY_NAME( R, "R" ),
  2018. KEY_NAME( S, "S" ),
  2019. KEY_NAME( T, "T" ),
  2020. KEY_NAME( U, "U" ),
  2021. KEY_NAME( V, "V" ),
  2022. KEY_NAME( W, "W" ),
  2023. KEY_NAME( X, "X" ),
  2024. KEY_NAME( Y, "Y" ),
  2025. KEY_NAME( Z, "Z" ),
  2026. KEY_NAME( PAD_0, "Key Pad 0" ),
  2027. KEY_NAME( PAD_1, "Key Pad 1" ),
  2028. KEY_NAME( PAD_2, "Key Pad 2" ),
  2029. KEY_NAME( PAD_3, "Key Pad 3" ),
  2030. KEY_NAME( PAD_4, "Key Pad 4" ),
  2031. KEY_NAME( PAD_5, "Key Pad 5" ),
  2032. KEY_NAME( PAD_6, "Key Pad 6" ),
  2033. KEY_NAME( PAD_7, "Key Pad 7" ),
  2034. KEY_NAME( PAD_8, "Key Pad 8" ),
  2035. KEY_NAME( PAD_9, "Key Pad 9" ),
  2036. KEY_NAME( PAD_DIVIDE, "Key Pad /" ),
  2037. KEY_NAME( PAD_MULTIPLY, "Key Pad *" ),
  2038. KEY_NAME( PAD_MINUS, "Key Pad -" ),
  2039. KEY_NAME( PAD_PLUS, "Key Pad +" ),
  2040. KEY_NAME( PAD_ENTER, "Key Pad Enter" ),
  2041. KEY_NAME( PAD_DECIMAL, "Key Pad ." ),
  2042. KEY_NAME( LBRACKET, "[" ),
  2043. KEY_NAME( RBRACKET, "]" ),
  2044. KEY_NAME( SEMICOLON, "," ),
  2045. KEY_NAME( APOSTROPHE, "'" ),
  2046. KEY_NAME( BACKQUOTE, "`" ),
  2047. KEY_NAME( COMMA, "," ),
  2048. KEY_NAME( PERIOD, "." ),
  2049. KEY_NAME( SLASH, "/" ),
  2050. KEY_NAME( BACKSLASH, "\\" ),
  2051. KEY_NAME( MINUS, "-" ),
  2052. KEY_NAME( EQUAL, "=" ),
  2053. KEY_NAME( ENTER, "Enter" ),
  2054. KEY_NAME( SPACE, "Space" ),
  2055. KEY_NAME( BACKSPACE, "Backspace" ),
  2056. KEY_NAME( TAB, "Tab" ),
  2057. KEY_NAME( CAPSLOCK, "Caps Lock" ),
  2058. KEY_NAME( NUMLOCK, "Num Lock" ),
  2059. KEY_NAME( ESCAPE, "Escape" ),
  2060. KEY_NAME( SCROLLLOCK, "Scroll Lock" ),
  2061. KEY_NAME( INSERT, "Ins" ),
  2062. KEY_NAME( DELETE, "Del" ),
  2063. KEY_NAME( HOME, "Home" ),
  2064. KEY_NAME( END, "End" ),
  2065. KEY_NAME( PAGEUP, "PgUp" ),
  2066. KEY_NAME( PAGEDOWN, "PgDn" ),
  2067. KEY_NAME( BREAK, "Break" ),
  2068. KEY_NAME( LSHIFT, "Shift" ),
  2069. KEY_NAME( RSHIFT, "Shift" ),
  2070. KEY_NAME( LALT, "Alt" ),
  2071. KEY_NAME( RALT, "Alt" ),
  2072. KEY_NAME( LCONTROL, "Ctrl" ),
  2073. KEY_NAME( RCONTROL, "Ctrl" ),
  2074. KEY_NAME( LWIN, "Windows" ),
  2075. KEY_NAME( RWIN, "Windows" ),
  2076. KEY_NAME( APP, "App" ),
  2077. KEY_NAME( UP, "Up" ),
  2078. KEY_NAME( LEFT, "Left" ),
  2079. KEY_NAME( DOWN, "Down" ),
  2080. KEY_NAME( RIGHT, "Right" ),
  2081. KEY_NAME( F1, "F1" ),
  2082. KEY_NAME( F2, "F2" ),
  2083. KEY_NAME( F3, "F3" ),
  2084. KEY_NAME( F4, "F4" ),
  2085. KEY_NAME( F5, "F5" ),
  2086. KEY_NAME( F6, "F6" ),
  2087. KEY_NAME( F7, "F7" ),
  2088. KEY_NAME( F8, "F8" ),
  2089. KEY_NAME( F9, "F9" ),
  2090. KEY_NAME( F10, "F10" ),
  2091. KEY_NAME( F11, "F11" ),
  2092. KEY_NAME( F12, "F12" ),
  2093. KEY_NAME( CAPSLOCKTOGGLE, "Caps Lock Toggle" ),
  2094. KEY_NAME( NUMLOCKTOGGLE, "Num Lock Toggle" ),
  2095. KEY_NAME( SCROLLLOCKTOGGLE, "Scroll Lock Toggle" ),
  2096. };
  2097. char const *Panel::KeyCodeToString( KeyCode code )
  2098. {
  2099. int c = ARRAYSIZE( g_KeyNames );
  2100. for ( int i = 0; i < c ; ++i )
  2101. {
  2102. if ( g_KeyNames[ i ].code == code )
  2103. return g_KeyNames[ i ].string;
  2104. }
  2105. return "";
  2106. }
  2107. wchar_t const *Panel::KeyCodeToDisplayString( KeyCode code )
  2108. {
  2109. int c = ARRAYSIZE( g_KeyNames );
  2110. for ( int i = 0; i < c ; ++i )
  2111. {
  2112. if ( g_KeyNames[ i ].code == code )
  2113. {
  2114. char const *str = g_KeyNames[ i ].displaystring;
  2115. wchar_t *wstr = g_pVGuiLocalize->Find( str );
  2116. if ( wstr )
  2117. {
  2118. return wstr;
  2119. }
  2120. static wchar_t buf[ 64 ];
  2121. g_pVGuiLocalize->ConvertANSIToUnicode( str, buf, sizeof( buf ) );
  2122. return buf;
  2123. }
  2124. }
  2125. return L"";
  2126. }
  2127. static void AddModifierToString( char const *modifiername, char *buf, size_t bufsize )
  2128. {
  2129. char add[ 32 ];
  2130. if ( Q_strlen( buf ) > 0 )
  2131. {
  2132. Q_snprintf( add, sizeof( add ), "+%s", modifiername );
  2133. }
  2134. else
  2135. {
  2136. Q_strncpy( add, modifiername, sizeof( add ) );
  2137. }
  2138. Q_strncat( buf, add, bufsize, COPY_ALL_CHARACTERS );
  2139. }
  2140. wchar_t const *Panel::KeyCodeModifiersToDisplayString( KeyCode code, int modifiers )
  2141. {
  2142. char sz[ 256 ];
  2143. sz[ 0 ] = 0;
  2144. if ( modifiers & MODIFIER_SHIFT )
  2145. {
  2146. AddModifierToString( "Shift", sz, sizeof( sz ) );
  2147. }
  2148. if ( modifiers & MODIFIER_CONTROL )
  2149. {
  2150. AddModifierToString( "Ctrl", sz, sizeof( sz ) );
  2151. }
  2152. if ( modifiers & MODIFIER_ALT )
  2153. {
  2154. AddModifierToString( "Alt", sz, sizeof( sz ) );
  2155. }
  2156. if ( Q_strlen( sz ) > 0 )
  2157. {
  2158. Q_strncat( sz, "+", sizeof( sz ), COPY_ALL_CHARACTERS );
  2159. }
  2160. static wchar_t unicode[ 256 ];
  2161. V_swprintf_safe( unicode, L"%S%s", sz, Panel::KeyCodeToDisplayString( (KeyCode)code ) );
  2162. return unicode;
  2163. }
  2164. KeyCode Panel::StringToKeyCode( char const *str )
  2165. {
  2166. int c = ARRAYSIZE( g_KeyNames );
  2167. for ( int i = 0; i < c ; ++i )
  2168. {
  2169. if ( !Q_stricmp( str, g_KeyNames[ i ].string ) )
  2170. return g_KeyNames[ i ].code;
  2171. }
  2172. return KEY_NONE;
  2173. }
  2174. static void WriteKeyBindingToBuffer( CUtlBuffer& buf, int level, const BoundKey_t& binding )
  2175. {
  2176. BufPrint( buf, level, "\"keycode\"\t\"%s\"\n", Panel::KeyCodeToString( (KeyCode)binding.keycode ) );
  2177. if ( binding.modifiers & MODIFIER_SHIFT )
  2178. {
  2179. BufPrint( buf, level, "\"shift\"\t\"1\"\n" );
  2180. }
  2181. if ( binding.modifiers & MODIFIER_CONTROL )
  2182. {
  2183. BufPrint( buf, level, "\"ctrl\"\t\"1\"\n" );
  2184. }
  2185. if ( binding.modifiers & MODIFIER_ALT )
  2186. {
  2187. BufPrint( buf, level, "\"alt\"\t\"1\"\n" );
  2188. }
  2189. }
  2190. //-----------------------------------------------------------------------------
  2191. // Purpose:
  2192. // Input : *filename -
  2193. // *pathID -
  2194. //-----------------------------------------------------------------------------
  2195. void Panel::SaveKeyBindingsToBuffer( int level, CUtlBuffer& buf )
  2196. {
  2197. Assert( IsValidKeyBindingsContext() );
  2198. Assert( buf.IsText() );
  2199. PanelKeyBindingMap *map = GetKBMap();
  2200. while( map )
  2201. {
  2202. int c = map->boundkeys.Count();
  2203. for( int i = 0; i < c ; ++i )
  2204. {
  2205. const BoundKey_t& binding = map->boundkeys[ i ];
  2206. // Spew to file
  2207. BufPrint( buf, level, "\"%s\"\n", binding.bindingname );
  2208. BufPrint( buf, level, "{\n" );
  2209. WriteKeyBindingToBuffer( buf, level + 1, binding );
  2210. BufPrint( buf, level, "}\n" );
  2211. }
  2212. map = map->baseMap;
  2213. }
  2214. }
  2215. bool Panel::ParseKeyBindings( KeyValues *kv )
  2216. {
  2217. Assert( IsValidKeyBindingsContext() );
  2218. if ( !IsValidKeyBindingsContext() )
  2219. return false;
  2220. // To have KB the panel must have a name
  2221. Assert( GetName() && GetName()[ 0 ] );
  2222. if ( !GetName() || !GetName()[ 0 ] )
  2223. return false;
  2224. bool success = false;
  2225. g_KBMgr.AddPanelToContext( GetKeyBindingsContext(), this );
  2226. RemoveAllKeyBindings();
  2227. // Walk through bindings
  2228. for ( KeyValues *binding = kv->GetFirstSubKey(); binding != NULL; binding = binding->GetNextKey() )
  2229. {
  2230. char const *bindingName = binding->GetName();
  2231. if ( !bindingName || !bindingName[ 0 ] )
  2232. continue;
  2233. KeyBindingMap_t *b = LookupBinding( bindingName );
  2234. if ( b )
  2235. {
  2236. success = true;
  2237. const char *keycode = binding->GetString( "keycode", "" );
  2238. int modifiers = 0;
  2239. if ( binding->GetInt( "shift", 0 ) != 0 )
  2240. {
  2241. modifiers |= MODIFIER_SHIFT;
  2242. }
  2243. if ( binding->GetInt( "ctrl", 0 ) != 0 )
  2244. {
  2245. modifiers |= MODIFIER_CONTROL;
  2246. }
  2247. if ( binding->GetInt( "alt", 0 ) != 0 )
  2248. {
  2249. modifiers |= MODIFIER_ALT;
  2250. }
  2251. KeyBindingMap_t *bound = LookupBindingByKeyCode( StringToKeyCode( keycode ), modifiers );
  2252. if ( !bound )
  2253. {
  2254. AddKeyBinding( bindingName, StringToKeyCode( keycode ), modifiers );
  2255. }
  2256. }
  2257. else
  2258. {
  2259. Warning( "KeyBinding for panel '%s' contained unknown binding '%s'\n", GetName() ? GetName() : "???", bindingName );
  2260. }
  2261. }
  2262. // Now for each binding which is currently "unbound" to any key, use the default binding
  2263. PanelKeyBindingMap *map = GetKBMap();
  2264. while( map )
  2265. {
  2266. int c = map->entries.Count();
  2267. for( int i = 0; i < c ; ++i )
  2268. {
  2269. KeyBindingMap_t *binding = &map->entries[ i ];
  2270. // See if there is a bound key
  2271. CUtlVector< BoundKey_t * > list;
  2272. LookupBoundKeys( binding->bindingname, list );
  2273. if ( list.Count() == 0 )
  2274. {
  2275. // Assign the default binding to this key
  2276. BoundKey_t *defaultKey = LookupDefaultKey( binding->bindingname );
  2277. if ( defaultKey )
  2278. {
  2279. KeyBindingMap_t *alreadyBound = LookupBindingByKeyCode( (KeyCode)defaultKey->keycode, defaultKey->modifiers );
  2280. if ( alreadyBound )
  2281. {
  2282. Warning( "No binding for '%s', defautl key already bound to '%s'\n", binding->bindingname, alreadyBound->bindingname );
  2283. }
  2284. else
  2285. {
  2286. AddKeyBinding( defaultKey->bindingname, defaultKey->keycode, defaultKey->modifiers );
  2287. }
  2288. }
  2289. }
  2290. }
  2291. map = map->baseMap;
  2292. }
  2293. return success;
  2294. }
  2295. //-----------------------------------------------------------------------------
  2296. // Purpose:
  2297. // Input : handle -
  2298. // Output : Returns true on success, false on failure.
  2299. //-----------------------------------------------------------------------------
  2300. void Panel::SetKeyBindingsContext( KeyBindingContextHandle_t handle )
  2301. {
  2302. Assert( !IsValidKeyBindingsContext() || handle == GetKeyBindingsContext() );
  2303. g_KBMgr.AddPanelToContext( handle, this );
  2304. m_hKeyBindingsContext = handle;
  2305. }
  2306. //-----------------------------------------------------------------------------
  2307. // Purpose:
  2308. // Input : -
  2309. // Output : KeyBindingContextHandle_t
  2310. //-----------------------------------------------------------------------------
  2311. KeyBindingContextHandle_t Panel::GetKeyBindingsContext() const
  2312. {
  2313. return m_hKeyBindingsContext;
  2314. }
  2315. //-----------------------------------------------------------------------------
  2316. // Purpose:
  2317. // Input : -
  2318. // Output : Returns true on success, false on failure.
  2319. //-----------------------------------------------------------------------------
  2320. bool Panel::IsValidKeyBindingsContext() const
  2321. {
  2322. return GetKeyBindingsContext() != INVALID_KEYBINDINGCONTEXT_HANDLE;
  2323. }
  2324. char const *Panel::GetKeyBindingsFile() const
  2325. {
  2326. Assert( IsValidKeyBindingsContext() );
  2327. return g_KBMgr.GetKeyBindingsFile( GetKeyBindingsContext() );
  2328. }
  2329. char const *Panel::GetKeyBindingsFilePathID() const
  2330. {
  2331. Assert( IsValidKeyBindingsContext() );
  2332. return g_KBMgr.GetKeyBindingsFilePathID( GetKeyBindingsContext() );
  2333. }
  2334. void Panel::EditKeyBindings()
  2335. {
  2336. Assert( 0 );
  2337. }
  2338. //-----------------------------------------------------------------------------
  2339. // Purpose: Set this to false to disallow IsKeyRebound chaining to GetParent() Panels...
  2340. // Input : state -
  2341. //-----------------------------------------------------------------------------
  2342. void Panel::SetAllowKeyBindingChainToParent( bool state )
  2343. {
  2344. _flags.SetFlag( ALLOW_CHAIN_KEYBINDING_TO_PARENT, state );
  2345. }
  2346. //-----------------------------------------------------------------------------
  2347. // Purpose:
  2348. // Input : -
  2349. // Output : Returns true on success, false on failure.
  2350. //-----------------------------------------------------------------------------
  2351. bool Panel::IsKeyBindingChainToParentAllowed() const
  2352. {
  2353. return _flags.IsFlagSet( ALLOW_CHAIN_KEYBINDING_TO_PARENT );
  2354. }
  2355. bool Panel::IsKeyOverridden( KeyCode code, int modifiers )
  2356. {
  2357. // By default assume all keys should pass through binding system
  2358. return false;
  2359. }
  2360. bool Panel::IsKeyRebound( KeyCode code, int modifiers )
  2361. {
  2362. if ( IsKeyBoardInputEnabled() )
  2363. {
  2364. KeyBindingMap_t* binding = LookupBindingByKeyCode( code, modifiers );
  2365. // Only dispatch if we're part of the current modal subtree
  2366. if ( binding && IsChildOfSurfaceModalPanel() )
  2367. {
  2368. // Found match, post message to panel
  2369. if ( binding->func )
  2370. {
  2371. // dispatch the func
  2372. (this->*binding->func)();
  2373. }
  2374. else
  2375. {
  2376. Assert( 0 );
  2377. }
  2378. if ( !binding->passive )
  2379. {
  2380. // Exit this function...
  2381. return true;
  2382. }
  2383. }
  2384. }
  2385. // Chain to parent
  2386. Panel* pParent = GetParent();
  2387. if ( IsKeyBindingChainToParentAllowed() && pParent && !IsKeyOverridden( code, modifiers ) )
  2388. return pParent->IsKeyRebound( code, modifiers );
  2389. // No suitable binding found
  2390. return false;
  2391. }
  2392. static bool s_bSuppressRebindChecks = false;
  2393. #endif // VGUI_USEKEYBINDINGMAPS
  2394. void Panel::InternalKeyCodeTyped( int code )
  2395. {
  2396. if ( !ShouldHandleInputMessage() )
  2397. {
  2398. input()->OnKeyCodeUnhandled( code );
  2399. return;
  2400. }
  2401. if (IsKeyBoardInputEnabled())
  2402. {
  2403. bool shift = (input()->IsKeyDown(KEY_LSHIFT) || input()->IsKeyDown(KEY_RSHIFT));
  2404. bool ctrl = (input()->IsKeyDown(KEY_LCONTROL) || input()->IsKeyDown(KEY_RCONTROL));
  2405. bool alt = (input()->IsKeyDown(KEY_LALT) || input()->IsKeyDown(KEY_RALT));
  2406. int modifiers = 0;
  2407. if ( shift )
  2408. {
  2409. modifiers |= MODIFIER_SHIFT;
  2410. }
  2411. if ( ctrl )
  2412. {
  2413. modifiers |= MODIFIER_CONTROL;
  2414. }
  2415. if ( alt )
  2416. {
  2417. modifiers |= MODIFIER_ALT;
  2418. }
  2419. // Things in build mode don't have accelerators
  2420. if (IsBuildGroupEnabled())
  2421. {
  2422. _buildGroup->KeyCodeTyped((KeyCode)code, this);
  2423. return;
  2424. }
  2425. if ( !s_bSuppressRebindChecks && IsKeyRebound( (KeyCode)code, modifiers ) )
  2426. {
  2427. return;
  2428. }
  2429. bool oldVal = s_bSuppressRebindChecks;
  2430. s_bSuppressRebindChecks = true;
  2431. OnKeyCodeTyped((KeyCode)code);
  2432. s_bSuppressRebindChecks = oldVal;
  2433. }
  2434. else
  2435. {
  2436. if ( GetVPanel() == surface()->GetEmbeddedPanel() )
  2437. {
  2438. input()->OnKeyCodeUnhandled( code );
  2439. }
  2440. CallParentFunction(new KeyValues("KeyCodeTyped", "code", code));
  2441. }
  2442. }
  2443. void Panel::InternalKeyTyped(int unichar)
  2444. {
  2445. if ( !ShouldHandleInputMessage() )
  2446. return;
  2447. if (IsKeyBoardInputEnabled())
  2448. {
  2449. if ( IsBuildGroupEnabled() )
  2450. {
  2451. if ( _buildGroup->KeyTyped( (wchar_t)unichar, this ) )
  2452. {
  2453. return;
  2454. }
  2455. }
  2456. OnKeyTyped((wchar_t)unichar);
  2457. }
  2458. else
  2459. {
  2460. CallParentFunction(new KeyValues("KeyTyped", "unichar", unichar));
  2461. }
  2462. }
  2463. void Panel::InternalKeyCodeReleased(int code)
  2464. {
  2465. if ( !ShouldHandleInputMessage() )
  2466. return;
  2467. if (IsKeyBoardInputEnabled())
  2468. {
  2469. if (IsBuildGroupEnabled())
  2470. {
  2471. if ( _buildGroup->KeyCodeReleased((KeyCode)code, this) )
  2472. {
  2473. return;
  2474. }
  2475. }
  2476. OnKeyCodeReleased((KeyCode)code);
  2477. }
  2478. else
  2479. {
  2480. CallParentFunction(new KeyValues("KeyCodeReleased", "code", code));
  2481. }
  2482. }
  2483. void Panel::InternalKeyFocusTicked()
  2484. {
  2485. if (IsBuildGroupEnabled())
  2486. return;
  2487. OnKeyFocusTicked();
  2488. }
  2489. void Panel::InternalMouseFocusTicked()
  2490. {
  2491. if (IsBuildGroupEnabled())
  2492. {
  2493. // must repaint so the numbers will be accurate
  2494. if (_buildGroup->HasRulersOn())
  2495. {
  2496. PaintTraverse(true);
  2497. }
  2498. return;
  2499. }
  2500. // update cursor
  2501. InternalSetCursor();
  2502. OnMouseFocusTicked();
  2503. }
  2504. void Panel::InternalSetCursor()
  2505. {
  2506. bool visible = IsVisible();
  2507. if (visible)
  2508. {
  2509. #if defined( VGUI_USEDRAGDROP )
  2510. // Drag drop is overriding cursor?
  2511. if ( m_pDragDrop->m_bDragging ||
  2512. g_DragDropCapture.Get() != NULL )
  2513. return;
  2514. #endif
  2515. // chain up and make sure all our parents are also visible
  2516. VPANEL p = GetVParent();
  2517. while (p)
  2518. {
  2519. visible &= ipanel()->IsVisible(p);
  2520. p = ipanel()->GetParent(p);
  2521. }
  2522. // only change the cursor if this panel is visible, and if its part of the main VGUI tree
  2523. if (visible && HasParent(surface()->GetEmbeddedPanel()))
  2524. {
  2525. HCursor cursor = GetCursor();
  2526. if (IsBuildGroupEnabled())
  2527. {
  2528. cursor = _buildGroup->GetCursor(this);
  2529. }
  2530. if (input()->GetCursorOveride())
  2531. {
  2532. cursor = input()->GetCursorOveride();
  2533. }
  2534. surface()->SetCursor(cursor);
  2535. }
  2536. }
  2537. }
  2538. //-----------------------------------------------------------------------------
  2539. // Purpose: Called every frame the panel is visible, designed to be overridden
  2540. //-----------------------------------------------------------------------------
  2541. void Panel::OnThink()
  2542. {
  2543. #if defined( VGUI_USEDRAGDROP )
  2544. if ( IsPC() &&
  2545. m_pDragDrop->m_bDragEnabled &&
  2546. m_pDragDrop->m_bDragging &&
  2547. m_pDragDrop->m_bDragStarted )
  2548. {
  2549. bool isEscapeKeyDown = input()->IsKeyDown( KEY_ESCAPE );
  2550. if ( isEscapeKeyDown )
  2551. {
  2552. OnContinueDragging();
  2553. OnFinishDragging( true, (MouseCode)-1, true );
  2554. return;
  2555. }
  2556. if ( m_pDragDrop->m_hCurrentDrop != 0 )
  2557. {
  2558. if ( !input()->IsMouseDown( MOUSE_LEFT ) )
  2559. {
  2560. OnContinueDragging();
  2561. OnFinishDragging( true, (MouseCode)-1 );
  2562. return;
  2563. }
  2564. // allow the cursor to change based upon things like changing keystate, etc.
  2565. surface()->SetCursor( m_pDragDrop->m_hCurrentDrop->GetDropCursor( m_pDragDrop->m_DragData ) );
  2566. if ( !m_pDragDrop->m_bDropMenuShown )
  2567. {
  2568. // See if the hover time has gotten larger
  2569. float hoverSeconds = ( system()->GetTimeMillis() - m_pDragDrop->m_lDropHoverTime ) * 0.001f;
  2570. DragDrop_t *dropInfo = m_pDragDrop->m_hCurrentDrop->GetDragDropInfo();
  2571. if ( dropInfo->m_flHoverContextTime != 0.0f )
  2572. {
  2573. if ( hoverSeconds >= dropInfo->m_flHoverContextTime )
  2574. {
  2575. m_pDragDrop->m_bDropMenuShown = true;
  2576. CUtlVector< KeyValues * > data;
  2577. GetDragData( data );
  2578. int x, y;
  2579. input()->GetCursorPos( x, y );
  2580. if ( m_pDragDrop->m_hDropContextMenu.Get() )
  2581. {
  2582. delete m_pDragDrop->m_hDropContextMenu.Get();
  2583. }
  2584. Menu *menu = new Menu( m_pDragDrop->m_hCurrentDrop.Get(), "DropContext" );
  2585. bool useMenu = m_pDragDrop->m_hCurrentDrop->GetDropContextMenu( menu, data );
  2586. if ( useMenu )
  2587. {
  2588. m_pDragDrop->m_hDropContextMenu = menu;
  2589. menu->SetPos( x, y );
  2590. menu->SetVisible( true );
  2591. menu->MakePopup();
  2592. surface()->MovePopupToFront( menu->GetVPanel() );
  2593. if ( menu->GetItemCount() > 0 )
  2594. {
  2595. int id = menu->GetMenuID( 0 );
  2596. menu->SetCurrentlyHighlightedItem( id );
  2597. MenuItem *item = menu->GetMenuItem( id );
  2598. item->SetArmed( true );
  2599. }
  2600. }
  2601. else
  2602. {
  2603. delete menu;
  2604. }
  2605. m_pDragDrop->m_hCurrentDrop->OnDropContextHoverShow( data );
  2606. }
  2607. }
  2608. }
  2609. }
  2610. }
  2611. #endif
  2612. }
  2613. // input messages handlers (designed for override)
  2614. void Panel::OnCursorMoved(int x, int y)
  2615. {
  2616. if( ParentNeedsCursorMoveEvents() )
  2617. {
  2618. // figure out x and y in parent space
  2619. int thisX, thisY;
  2620. ipanel()->GetPos( GetVPanel(), thisX, thisY );
  2621. CallParentFunction( new KeyValues( "OnCursorMoved", "x", x + thisX, "y", y + thisY ) );
  2622. }
  2623. }
  2624. void Panel::OnCursorEntered()
  2625. {
  2626. }
  2627. void Panel::OnCursorExited()
  2628. {
  2629. }
  2630. void Panel::OnMousePressed(MouseCode code)
  2631. {
  2632. }
  2633. void Panel::OnMouseDoublePressed(MouseCode code)
  2634. {
  2635. }
  2636. void Panel::OnMouseTriplePressed(MouseCode code)
  2637. {
  2638. }
  2639. void Panel::OnMouseReleased(MouseCode code)
  2640. {
  2641. }
  2642. void Panel::OnMouseMismatchedRelease( MouseCode code, Panel* pPressedPanel )
  2643. {
  2644. }
  2645. void Panel::OnMouseWheeled(int delta)
  2646. {
  2647. CallParentFunction(new KeyValues("MouseWheeled", "delta", delta));
  2648. }
  2649. // base implementation forwards Key messages to the Panel's parent - override to 'swallow' the input
  2650. void Panel::OnKeyCodePressed(KeyCode code)
  2651. {
  2652. static ConVarRef vgui_nav_lock( "vgui_nav_lock" );
  2653. bool handled = false;
  2654. switch( GetBaseButtonCode( code ) )
  2655. {
  2656. case KEY_XBUTTON_UP:
  2657. case KEY_XSTICK1_UP:
  2658. case KEY_XSTICK2_UP:
  2659. case KEY_UP:
  2660. case STEAMCONTROLLER_DPAD_UP:
  2661. if ( ( !vgui_nav_lock.IsValid() || vgui_nav_lock.GetInt() == 0 ) && NavigateUp() )
  2662. {
  2663. vgui_nav_lock.SetValue( 1 );
  2664. vgui::surface()->PlaySound( "UI/menu_focus.wav" );
  2665. handled = true;
  2666. }
  2667. break;
  2668. case KEY_XBUTTON_DOWN:
  2669. case KEY_XSTICK1_DOWN:
  2670. case KEY_XSTICK2_DOWN:
  2671. case KEY_DOWN:
  2672. case STEAMCONTROLLER_DPAD_DOWN:
  2673. if ( ( !vgui_nav_lock.IsValid() || vgui_nav_lock.GetInt() == 0 ) && NavigateDown() )
  2674. {
  2675. vgui_nav_lock.SetValue( 1 );
  2676. vgui::surface()->PlaySound( "UI/menu_focus.wav" );
  2677. handled = true;
  2678. }
  2679. break;
  2680. case KEY_XBUTTON_LEFT:
  2681. case KEY_XSTICK1_LEFT:
  2682. case KEY_XSTICK2_LEFT:
  2683. case KEY_LEFT:
  2684. case STEAMCONTROLLER_DPAD_LEFT:
  2685. if ( ( !vgui_nav_lock.IsValid() || vgui_nav_lock.GetInt() == 0 ) && NavigateLeft() )
  2686. {
  2687. vgui_nav_lock.SetValue( 1 );
  2688. vgui::surface()->PlaySound( "UI/menu_focus.wav" );
  2689. handled = true;
  2690. }
  2691. break;
  2692. case KEY_XBUTTON_RIGHT:
  2693. case KEY_XSTICK1_RIGHT:
  2694. case KEY_XSTICK2_RIGHT:
  2695. case KEY_RIGHT:
  2696. case STEAMCONTROLLER_DPAD_RIGHT:
  2697. if ( ( !vgui_nav_lock.IsValid() || vgui_nav_lock.GetInt() == 0 ) && NavigateRight() )
  2698. {
  2699. vgui_nav_lock.SetValue( 1 );
  2700. vgui::surface()->PlaySound( "UI/menu_focus.wav" );
  2701. handled = true;
  2702. }
  2703. break;
  2704. case KEY_XBUTTON_B:
  2705. case STEAMCONTROLLER_B:
  2706. if ( ( !vgui_nav_lock.IsValid() || vgui_nav_lock.GetInt() == 0 ) && NavigateBack() )
  2707. {
  2708. vgui_nav_lock.SetValue( 1 );
  2709. vgui::surface()->PlaySound( "UI/menu_focus.wav" );
  2710. handled = true;
  2711. }
  2712. break;
  2713. }
  2714. if( !handled && !m_PassUnhandledInput )
  2715. return;
  2716. CallParentFunction(new KeyValues("KeyCodePressed", "code", code));
  2717. }
  2718. void Panel::OnKeyCodeTyped(KeyCode keycode)
  2719. {
  2720. vgui::KeyCode code = GetBaseButtonCode( keycode );
  2721. // handle focus change
  2722. if ( IsX360() || IsConsoleStylePanel() )
  2723. {
  2724. // eat these typed codes, will get handled in OnKeyCodePressed
  2725. switch ( code )
  2726. {
  2727. case KEY_XBUTTON_UP:
  2728. case KEY_XSTICK1_UP:
  2729. case KEY_XSTICK2_UP:
  2730. case KEY_XBUTTON_DOWN:
  2731. case KEY_XSTICK1_DOWN:
  2732. case KEY_XSTICK2_DOWN:
  2733. case KEY_XBUTTON_LEFT:
  2734. case KEY_XSTICK1_LEFT:
  2735. case KEY_XSTICK2_LEFT:
  2736. case KEY_XBUTTON_RIGHT:
  2737. case KEY_XSTICK1_RIGHT:
  2738. case KEY_XSTICK2_RIGHT:
  2739. case KEY_XBUTTON_A:
  2740. case KEY_XBUTTON_B:
  2741. case KEY_XBUTTON_X:
  2742. case KEY_XBUTTON_Y:
  2743. case KEY_XBUTTON_LEFT_SHOULDER:
  2744. case KEY_XBUTTON_RIGHT_SHOULDER:
  2745. case KEY_XBUTTON_BACK:
  2746. case KEY_XBUTTON_START:
  2747. case KEY_XBUTTON_STICK1:
  2748. case KEY_XBUTTON_STICK2:
  2749. case KEY_XBUTTON_LTRIGGER:
  2750. case KEY_XBUTTON_RTRIGGER:
  2751. case STEAMCONTROLLER_A:
  2752. case STEAMCONTROLLER_B:
  2753. case KEY_UP:
  2754. case KEY_DOWN:
  2755. case KEY_LEFT:
  2756. case KEY_RIGHT:
  2757. case STEAMCONTROLLER_DPAD_UP:
  2758. case STEAMCONTROLLER_DPAD_DOWN:
  2759. case STEAMCONTROLLER_DPAD_LEFT:
  2760. case STEAMCONTROLLER_DPAD_RIGHT:
  2761. return;
  2762. }
  2763. // legacy handling - need to re-enable for older apps?
  2764. /*
  2765. if ( code == KEY_XSTICK1_RIGHT || code == KEY_XBUTTON_RIGHT )
  2766. {
  2767. RequestFocusNext();
  2768. return;
  2769. }
  2770. else if ( code == KEY_XSTICK1_LEFT || code == KEY_XBUTTON_LEFT )
  2771. {
  2772. RequestFocusPrev();
  2773. return;
  2774. }
  2775. */
  2776. }
  2777. if (code == KEY_TAB)
  2778. {
  2779. bool bShiftDown = input()->IsKeyDown(KEY_LSHIFT) || input()->IsKeyDown(KEY_RSHIFT);
  2780. if ( IsConsoleStylePanel() )
  2781. {
  2782. if ( bShiftDown )
  2783. {
  2784. NavigateUp();
  2785. }
  2786. else
  2787. {
  2788. NavigateDown();
  2789. }
  2790. }
  2791. else
  2792. {
  2793. // if shift is down goto previous tab position, otherwise goto next
  2794. if ( bShiftDown )
  2795. {
  2796. RequestFocusPrev();
  2797. }
  2798. else
  2799. {
  2800. RequestFocusNext();
  2801. }
  2802. }
  2803. }
  2804. else
  2805. {
  2806. // forward up
  2807. if ( GetVPanel() == surface()->GetEmbeddedPanel() )
  2808. {
  2809. input()->OnKeyCodeUnhandled( keycode );
  2810. }
  2811. CallParentFunction(new KeyValues("KeyCodeTyped", "code", keycode));
  2812. }
  2813. }
  2814. void Panel::OnKeyTyped(wchar_t unichar)
  2815. {
  2816. CallParentFunction(new KeyValues("KeyTyped", "unichar", unichar));
  2817. }
  2818. void Panel::OnKeyCodeReleased(KeyCode code)
  2819. {
  2820. CallParentFunction(new KeyValues("KeyCodeReleased", "code", code));
  2821. }
  2822. void Panel::OnKeyFocusTicked()
  2823. {
  2824. CallParentFunction(new KeyValues("KeyFocusTicked"));
  2825. }
  2826. void Panel::OnMouseFocusTicked()
  2827. {
  2828. CallParentFunction(new KeyValues("OnMouseFocusTicked"));
  2829. }
  2830. bool Panel::IsWithin(int x,int y)
  2831. {
  2832. // check against our clip rect
  2833. int clipRect[4];
  2834. ipanel()->GetClipRect(GetVPanel(), clipRect[0], clipRect[1], clipRect[2], clipRect[3]);
  2835. if (x < clipRect[0])
  2836. {
  2837. return false;
  2838. }
  2839. if (y < clipRect[1])
  2840. {
  2841. return false;
  2842. }
  2843. if (x >= clipRect[2])
  2844. {
  2845. return false;
  2846. }
  2847. if (y >= clipRect[3])
  2848. {
  2849. return false;
  2850. }
  2851. return true;
  2852. }
  2853. //-----------------------------------------------------------------------------
  2854. // Purpose: determines which is the topmost panel under the coordinates (x, y)
  2855. //-----------------------------------------------------------------------------
  2856. VPANEL Panel::IsWithinTraverse(int x, int y, bool traversePopups)
  2857. {
  2858. // if this one is not visible, its children won't be either
  2859. // also if it doesn't want mouse input its children can't get it either
  2860. if (!IsVisible() || !IsMouseInputEnabled())
  2861. return NULL;
  2862. if (traversePopups)
  2863. {
  2864. // check popups first
  2865. int i;
  2866. CUtlVector< VPANEL > &children = ipanel()->GetChildren( GetVPanel() );
  2867. int childCount = children.Count();
  2868. for (i = childCount - 1; i >= 0; i--)
  2869. {
  2870. VPANEL panel = children[ i ];
  2871. if (ipanel()->IsPopup(panel))
  2872. {
  2873. panel = ipanel()->IsWithinTraverse(panel, x, y, true);
  2874. if (panel != null)
  2875. {
  2876. return panel;
  2877. }
  2878. }
  2879. }
  2880. // check children recursive, if you find one, just return first one
  2881. // this checks in backwards order so the last child drawn for this panel is chosen which
  2882. // coincides to how it would be visibly displayed
  2883. for (i = childCount - 1; i >= 0; i--)
  2884. {
  2885. VPANEL panel = children[ i ];
  2886. // we've already checked popups so ignore
  2887. if (!ipanel()->IsPopup(panel))
  2888. {
  2889. panel = ipanel()->IsWithinTraverse(panel, x, y, true);
  2890. if (panel != 0)
  2891. {
  2892. return panel;
  2893. }
  2894. }
  2895. }
  2896. // check ourself
  2897. if ( !IsMouseInputDisabledForThisPanel() && IsWithin(x, y) )
  2898. {
  2899. return GetVPanel();
  2900. }
  2901. }
  2902. else
  2903. {
  2904. // since we're not checking popups, it must be within us, so we can check ourself first
  2905. if (IsWithin(x, y))
  2906. {
  2907. // check children recursive, if you find one, just return first one
  2908. // this checks in backwards order so the last child drawn for this panel is chosen which
  2909. // coincides to how it would be visibly displayed
  2910. CUtlVector< VPANEL > &children = ipanel()->GetChildren( GetVPanel() );
  2911. int childCount = children.Count();
  2912. for (int i = childCount - 1; i >= 0; i--)
  2913. {
  2914. VPANEL panel = children[ i ];
  2915. // ignore popups
  2916. if (!ipanel()->IsPopup(panel))
  2917. {
  2918. panel = ipanel()->IsWithinTraverse(panel, x, y, false);
  2919. if (panel != 0)
  2920. {
  2921. return panel;
  2922. }
  2923. }
  2924. }
  2925. // not a child, must be us
  2926. if ( !IsMouseInputDisabledForThisPanel() )
  2927. return GetVPanel();
  2928. }
  2929. }
  2930. return NULL;
  2931. }
  2932. void Panel::LocalToScreen(int& x,int& y)
  2933. {
  2934. int px, py;
  2935. ipanel()->GetAbsPos(GetVPanel(), px, py);
  2936. x = x + px;
  2937. y = y + py;
  2938. }
  2939. void Panel::ScreenToLocal(int& x,int& y)
  2940. {
  2941. int px, py;
  2942. ipanel()->GetAbsPos(GetVPanel(), px, py);
  2943. x = x - px;
  2944. y = y - py;
  2945. }
  2946. void Panel::ParentLocalToScreen(int &x, int &y)
  2947. {
  2948. int px, py;
  2949. ipanel()->GetAbsPos(GetVParent(), px, py);
  2950. x = x + px;
  2951. y = y + py;
  2952. }
  2953. void Panel::MakePopup(bool showTaskbarIcon,bool disabled)
  2954. {
  2955. surface()->CreatePopup(GetVPanel(), false, showTaskbarIcon,disabled);
  2956. }
  2957. void Panel::SetCursor(HCursor cursor)
  2958. {
  2959. _cursor = cursor;
  2960. }
  2961. HCursor Panel::GetCursor()
  2962. {
  2963. return _cursor;
  2964. }
  2965. void Panel::SetCursorAlwaysVisible( bool visible )
  2966. {
  2967. surface()->SetCursorAlwaysVisible( visible );
  2968. }
  2969. void Panel::SetMinimumSize(int wide,int tall)
  2970. {
  2971. ipanel()->SetMinimumSize(GetVPanel(), wide, tall);
  2972. }
  2973. void Panel::GetMinimumSize(int& wide,int &tall)
  2974. {
  2975. ipanel()->GetMinimumSize(GetVPanel(), wide, tall);
  2976. }
  2977. bool Panel::IsBuildModeEditable()
  2978. {
  2979. return true;
  2980. }
  2981. void Panel::SetBuildModeEditable(bool state)
  2982. {
  2983. if (state)
  2984. {
  2985. _buildModeFlags |= BUILDMODE_EDITABLE;
  2986. }
  2987. else
  2988. {
  2989. _buildModeFlags &= ~BUILDMODE_EDITABLE;
  2990. }
  2991. }
  2992. //-----------------------------------------------------------------------------
  2993. // Purpose: data accessor
  2994. //-----------------------------------------------------------------------------
  2995. bool Panel::IsBuildModeDeletable()
  2996. {
  2997. return (_buildModeFlags & BUILDMODE_DELETABLE);
  2998. }
  2999. //-----------------------------------------------------------------------------
  3000. // Purpose: data accessor
  3001. //-----------------------------------------------------------------------------
  3002. void Panel::SetBuildModeDeletable(bool state)
  3003. {
  3004. if (state)
  3005. {
  3006. _buildModeFlags |= BUILDMODE_DELETABLE;
  3007. }
  3008. else
  3009. {
  3010. _buildModeFlags &= ~BUILDMODE_DELETABLE;
  3011. }
  3012. }
  3013. //-----------------------------------------------------------------------------
  3014. // Purpose:
  3015. //-----------------------------------------------------------------------------
  3016. bool Panel::IsBuildModeActive()
  3017. {
  3018. return _buildGroup ? _buildGroup->IsEnabled() : false;
  3019. }
  3020. //-----------------------------------------------------------------------------
  3021. // Purpose:
  3022. //-----------------------------------------------------------------------------
  3023. void Panel::GetClipRect(int& x0,int& y0,int& x1,int& y1)
  3024. {
  3025. ipanel()->GetClipRect(GetVPanel(), x0, y0, x1, y1);
  3026. }
  3027. //-----------------------------------------------------------------------------
  3028. // Purpose:
  3029. //-----------------------------------------------------------------------------
  3030. int Panel::GetChildCount()
  3031. {
  3032. if (ipanel())
  3033. {
  3034. return ipanel()->GetChildCount(GetVPanel());
  3035. }
  3036. return 0;
  3037. }
  3038. //-----------------------------------------------------------------------------
  3039. // Purpose: returns a child by the specified index
  3040. //-----------------------------------------------------------------------------
  3041. Panel *Panel::GetChild(int index)
  3042. {
  3043. // get the child and cast it to a panel
  3044. // this assumes that the child is from the same module as the this (precondition)
  3045. return ipanel()->GetPanel(ipanel()->GetChild(GetVPanel(), index), GetControlsModuleName());
  3046. }
  3047. CUtlVector< VPANEL > &Panel::GetChildren()
  3048. {
  3049. return ipanel()->GetChildren(GetVPanel());
  3050. }
  3051. //-----------------------------------------------------------------------------
  3052. // Purpose: moves the key focus back
  3053. //-----------------------------------------------------------------------------
  3054. bool Panel::RequestFocusPrev(VPANEL panel)
  3055. {
  3056. // chain to parent
  3057. if (GetVParent())
  3058. {
  3059. return ipanel()->RequestFocusPrev(GetVParent(), GetVPanel());
  3060. }
  3061. return false;
  3062. }
  3063. //-----------------------------------------------------------------------------
  3064. // Purpose:
  3065. //-----------------------------------------------------------------------------
  3066. bool Panel::RequestFocusNext(VPANEL panel)
  3067. {
  3068. // chain to parent
  3069. if (GetVParent())
  3070. {
  3071. return ipanel()->RequestFocusNext(GetVParent(), GetVPanel());
  3072. }
  3073. return false;
  3074. }
  3075. //-----------------------------------------------------------------------------
  3076. // Purpose: Sets the panel to have the current sub focus
  3077. // Input : direction - the direction in which focus travelled to arrive at this panel; forward = 1, back = -1
  3078. //-----------------------------------------------------------------------------
  3079. void Panel::RequestFocus(int direction)
  3080. {
  3081. // NOTE: This doesn't make any sense if we don't have keyboard input enabled
  3082. // NOTE: Well, maybe it does if you have a steam controller...
  3083. // Assert( ( IsX360() || IsConsoleStylePanel() ) || IsKeyBoardInputEnabled() );
  3084. // ivgui()->DPrintf2("RequestFocus(%s, %s)\n", GetName(), GetClassName());
  3085. OnRequestFocus(GetVPanel(), NULL);
  3086. }
  3087. //-----------------------------------------------------------------------------
  3088. // Purpose: Called after a panel requests focus to fix up the whole chain
  3089. //-----------------------------------------------------------------------------
  3090. void Panel::OnRequestFocus(VPANEL subFocus, VPANEL defaultPanel)
  3091. {
  3092. CallParentFunction(new KeyValues("OnRequestFocus", "subFocus", subFocus, "defaultPanel", defaultPanel));
  3093. }
  3094. //-----------------------------------------------------------------------------
  3095. // Purpose:
  3096. //-----------------------------------------------------------------------------
  3097. VPANEL Panel::GetCurrentKeyFocus()
  3098. {
  3099. return NULL;
  3100. }
  3101. //-----------------------------------------------------------------------------
  3102. // Purpose: returns true if the panel has focus
  3103. //-----------------------------------------------------------------------------
  3104. bool Panel::HasFocus()
  3105. {
  3106. if (input()->GetFocus() == GetVPanel())
  3107. {
  3108. return true;
  3109. }
  3110. return false;
  3111. }
  3112. //-----------------------------------------------------------------------------
  3113. // Purpose:
  3114. //-----------------------------------------------------------------------------
  3115. void Panel::SetTabPosition(int position)
  3116. {
  3117. _tabPosition = position;
  3118. }
  3119. //-----------------------------------------------------------------------------
  3120. // Purpose:
  3121. //-----------------------------------------------------------------------------
  3122. int Panel::GetTabPosition()
  3123. {
  3124. return _tabPosition;
  3125. }
  3126. //-----------------------------------------------------------------------------
  3127. // Purpose:
  3128. //-----------------------------------------------------------------------------
  3129. void Panel::InternalFocusChanged(bool lost)
  3130. {
  3131. /*
  3132. //if focus is gained tell the focusNavGroup about it so its current can be correct
  3133. if( (!lost) && (_focusNavGroup!=null) )
  3134. {
  3135. _focusNavGroup->setCurrentPanel(this);
  3136. }
  3137. */
  3138. }
  3139. //-----------------------------------------------------------------------------
  3140. // Purpose: Called when a panel loses it's mouse capture
  3141. //-----------------------------------------------------------------------------
  3142. void Panel::OnMouseCaptureLost()
  3143. {
  3144. if (m_pTooltips)
  3145. {
  3146. m_pTooltips->ResetDelay();
  3147. }
  3148. }
  3149. //-----------------------------------------------------------------------------
  3150. // Purpose:
  3151. //-----------------------------------------------------------------------------
  3152. void Panel::AddActionSignalTarget(Panel *messageTarget)
  3153. {
  3154. HPanel target = ivgui()->PanelToHandle(messageTarget->GetVPanel());
  3155. if (!_actionSignalTargetDar.HasElement(target))
  3156. {
  3157. _actionSignalTargetDar.AddElement(target);
  3158. }
  3159. }
  3160. //-----------------------------------------------------------------------------
  3161. // Purpose:
  3162. //-----------------------------------------------------------------------------
  3163. void Panel::AddActionSignalTarget(VPANEL messageTarget)
  3164. {
  3165. HPanel target = ivgui()->PanelToHandle(messageTarget);
  3166. if (!_actionSignalTargetDar.HasElement(target))
  3167. {
  3168. _actionSignalTargetDar.AddElement(target);
  3169. }
  3170. }
  3171. //-----------------------------------------------------------------------------
  3172. // Purpose:
  3173. //-----------------------------------------------------------------------------
  3174. void Panel::RemoveActionSignalTarget(Panel *oldTarget)
  3175. {
  3176. _actionSignalTargetDar.RemoveElement(ivgui()->PanelToHandle(oldTarget->GetVPanel()));
  3177. }
  3178. //-----------------------------------------------------------------------------
  3179. // Purpose: Sends a message to all the panels that have requested action signals
  3180. //-----------------------------------------------------------------------------
  3181. void Panel::PostActionSignal( KeyValues *message )
  3182. {
  3183. if ( m_bIsSilent != true )
  3184. {
  3185. // add who it was from the message
  3186. message->SetPtr("panel", this);
  3187. int i;
  3188. for (i = _actionSignalTargetDar.GetCount() - 1; i > 0; i--)
  3189. {
  3190. VPANEL panel = ivgui()->HandleToPanel(_actionSignalTargetDar[i]);
  3191. if (panel)
  3192. {
  3193. ivgui()->PostMessage(panel, message->MakeCopy(), GetVPanel());
  3194. }
  3195. }
  3196. // do this so we can save on one MakeCopy() call
  3197. if (i == 0)
  3198. {
  3199. VPANEL panel = ivgui()->HandleToPanel(_actionSignalTargetDar[i]);
  3200. if (panel)
  3201. {
  3202. ivgui()->PostMessage(panel, message, GetVPanel());
  3203. return;
  3204. }
  3205. }
  3206. }
  3207. message->deleteThis();
  3208. }
  3209. void Panel::SetBorder(IBorder *border)
  3210. {
  3211. tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "%s - %s", __FUNCTION__, GetName() );
  3212. _border = border;
  3213. if (border)
  3214. {
  3215. int x, y, x2, y2;
  3216. border->GetInset(x, y, x2, y2);
  3217. ipanel()->SetInset(GetVPanel(), x, y, x2, y2);
  3218. // update our background type based on the bord
  3219. SetPaintBackgroundType(border->GetBackgroundType());
  3220. }
  3221. else
  3222. {
  3223. ipanel()->SetInset(GetVPanel(), 0, 0, 0, 0);
  3224. }
  3225. }
  3226. IBorder *Panel::GetBorder()
  3227. {
  3228. return _border;
  3229. }
  3230. void Panel::SetPaintBorderEnabled(bool state)
  3231. {
  3232. _flags.SetFlag( PAINT_BORDER_ENABLED, state );
  3233. }
  3234. void Panel::SetPaintBackgroundEnabled(bool state)
  3235. {
  3236. _flags.SetFlag( PAINT_BACKGROUND_ENABLED, state );
  3237. }
  3238. void Panel::SetPaintBackgroundType( int type )
  3239. {
  3240. // HACK only 0 through 2 supported for now
  3241. m_nPaintBackgroundType = clamp( type, 0, 2 );
  3242. }
  3243. void Panel::SetPaintEnabled(bool state)
  3244. {
  3245. _flags.SetFlag( PAINT_ENABLED, state );
  3246. }
  3247. void Panel::SetPostChildPaintEnabled(bool state)
  3248. {
  3249. _flags.SetFlag( POST_CHILD_PAINT_ENABLED, state );
  3250. }
  3251. void Panel::GetInset(int& left,int& top,int& right,int& bottom)
  3252. {
  3253. ipanel()->GetInset(GetVPanel(), left, top, right, bottom);
  3254. }
  3255. void Panel::GetPaintSize(int& wide,int& tall)
  3256. {
  3257. GetSize(wide, tall);
  3258. if (_border != null)
  3259. {
  3260. int left,top,right,bottom;
  3261. _border->GetInset(left,top,right,bottom);
  3262. wide -= (left+right);
  3263. tall -= (top+bottom);
  3264. }
  3265. }
  3266. int Panel::GetWide()
  3267. {
  3268. int wide, tall;
  3269. ipanel()->GetSize(GetVPanel(), wide, tall);
  3270. return wide;
  3271. }
  3272. void Panel::SetWide(int wide)
  3273. {
  3274. ipanel()->SetSize(GetVPanel(), wide, GetTall());
  3275. }
  3276. int Panel::GetTall()
  3277. {
  3278. int wide, tall;
  3279. ipanel()->GetSize(GetVPanel(), wide, tall);
  3280. return tall;
  3281. }
  3282. void Panel::SetTall(int tall)
  3283. {
  3284. ipanel()->SetSize(GetVPanel(), GetWide(), tall);
  3285. }
  3286. void Panel::SetBuildGroup(BuildGroup* buildGroup)
  3287. {
  3288. //TODO: remove from old group
  3289. Assert(buildGroup != NULL);
  3290. _buildGroup = buildGroup;
  3291. _buildGroup->PanelAdded(this);
  3292. }
  3293. bool Panel::IsBuildGroupEnabled()
  3294. {
  3295. if ( !_buildGroup.IsValid() )
  3296. return false;
  3297. bool enabled = _buildGroup->IsEnabled();
  3298. if ( enabled )
  3299. return enabled;
  3300. if ( GetParent() && GetParent()->IsBuildGroupEnabled() )
  3301. return true;
  3302. return false;
  3303. }
  3304. void Panel::SetBgColor(Color color)
  3305. {
  3306. _bgColor = color;
  3307. }
  3308. void Panel::SetFgColor(Color color)
  3309. {
  3310. _fgColor = color;
  3311. }
  3312. Color Panel::GetBgColor()
  3313. {
  3314. return _bgColor;
  3315. }
  3316. Color Panel::GetFgColor()
  3317. {
  3318. return _fgColor;
  3319. }
  3320. void Panel::InternalPerformLayout()
  3321. {
  3322. // Don't layout if we're still waiting for our scheme to be applied.
  3323. // At worst, it leads to crashes, at best it does work that we'll redo as soon as the scheme has been applied.
  3324. if ( _flags.IsFlagSet( NEEDS_SCHEME_UPDATE ) )
  3325. return;
  3326. _flags.SetFlag( IN_PERFORM_LAYOUT );
  3327. // make sure the scheme has been applied
  3328. _flags.ClearFlag( NEEDS_LAYOUT );
  3329. PerformLayout();
  3330. _flags.ClearFlag( IN_PERFORM_LAYOUT );
  3331. }
  3332. void Panel::PerformLayout()
  3333. {
  3334. // this should be overridden to relayout controls
  3335. }
  3336. void Panel::InvalidateLayout( bool layoutNow, bool reloadScheme )
  3337. {
  3338. _flags.SetFlag( NEEDS_LAYOUT );
  3339. if (reloadScheme)
  3340. {
  3341. // make all our children reload the scheme
  3342. _flags.SetFlag( NEEDS_SCHEME_UPDATE );
  3343. for (int i = 0; i < GetChildCount(); i++)
  3344. {
  3345. vgui::Panel* panel = GetChild(i);
  3346. if( panel )
  3347. {
  3348. panel->InvalidateLayout(layoutNow, true);
  3349. }
  3350. }
  3351. PerformApplySchemeSettings();
  3352. }
  3353. if (layoutNow)
  3354. {
  3355. InternalPerformLayout();
  3356. Repaint();
  3357. }
  3358. }
  3359. bool Panel::IsCursorNone()
  3360. {
  3361. HCursor cursor = GetCursor();
  3362. if (!cursor)
  3363. {
  3364. return true;
  3365. }
  3366. return false;
  3367. }
  3368. //-----------------------------------------------------------------------------
  3369. // Purpose: returns true if the cursor is currently over the panel
  3370. // Output : Returns true on success, false on failure.
  3371. //-----------------------------------------------------------------------------
  3372. bool Panel::IsCursorOver(void)
  3373. {
  3374. int x, y;
  3375. input()->GetCursorPos(x, y);
  3376. return IsWithin(x, y);
  3377. }
  3378. //-----------------------------------------------------------------------------
  3379. // Purpose: Called when a panel receives a command message from another panel
  3380. //-----------------------------------------------------------------------------
  3381. void Panel::OnCommand(const char *command)
  3382. {
  3383. if ( !Q_stricmp( "performlayout", command ) )
  3384. {
  3385. InvalidateLayout();
  3386. }
  3387. else if ( !Q_stricmp( "reloadscheme", command ) )
  3388. {
  3389. InvalidateLayout( false, true );
  3390. }
  3391. else
  3392. {
  3393. // if noone else caught this, pass along to the listeners
  3394. // (this is useful for generic dialogs - otherwise, commands just get ignored)
  3395. KeyValues *msg = new KeyValues( command );
  3396. PostActionSignal( msg );
  3397. }
  3398. }
  3399. //-----------------------------------------------------------------------------
  3400. // Purpose: panel gained focus message
  3401. //-----------------------------------------------------------------------------
  3402. void Panel::OnSetFocus()
  3403. {
  3404. Repaint();
  3405. }
  3406. //-----------------------------------------------------------------------------
  3407. // Purpose: panel lost focus message
  3408. //-----------------------------------------------------------------------------
  3409. void Panel::OnKillFocus()
  3410. {
  3411. Repaint();
  3412. }
  3413. //-----------------------------------------------------------------------------
  3414. // Purpose: Sets the object up to be deleted next frame
  3415. //-----------------------------------------------------------------------------
  3416. void Panel::MarkForDeletion()
  3417. {
  3418. if ( _flags.IsFlagSet( MARKED_FOR_DELETION ) )
  3419. return;
  3420. _flags.SetFlag( MARKED_FOR_DELETION );
  3421. _flags.ClearFlag( AUTODELETE_ENABLED );
  3422. if (ivgui()->IsRunning())
  3423. {
  3424. ivgui()->MarkPanelForDeletion(GetVPanel());
  3425. }
  3426. // direct delete is never safe because even if ivgui is shutdown we manually do RunFrame()
  3427. // and we can enter here in a think traverse and then delete from underneath ourselves
  3428. /*else
  3429. {
  3430. delete this;
  3431. }*/
  3432. }
  3433. //-----------------------------------------------------------------------------
  3434. // Purpose: return true if this object require a perform layout
  3435. //-----------------------------------------------------------------------------
  3436. bool Panel::IsLayoutInvalid()
  3437. {
  3438. return _flags.IsFlagSet( NEEDS_LAYOUT );
  3439. }
  3440. //-----------------------------------------------------------------------------
  3441. // Sets the pin corner + resize mode for resizing panels
  3442. //-----------------------------------------------------------------------------
  3443. void Panel::SetAutoResize( PinCorner_e pinCorner, AutoResize_e resizeDir,
  3444. int nPinOffsetX, int nPinOffsetY, int nUnpinnedCornerOffsetX, int nUnpinnedCornerOffsetY )
  3445. {
  3446. _pinCorner = pinCorner;
  3447. _autoResizeDirection = resizeDir;
  3448. m_nPinDeltaX = nPinOffsetX;
  3449. m_nPinDeltaY = nPinOffsetY;
  3450. m_nResizeDeltaX = nUnpinnedCornerOffsetX;
  3451. m_nResizeDeltaY = nUnpinnedCornerOffsetY;
  3452. }
  3453. //-----------------------------------------------------------------------------
  3454. // Sets the pin corner for non-resizing panels
  3455. //-----------------------------------------------------------------------------
  3456. void Panel::SetPinCorner( PinCorner_e pinCorner, int nOffsetX, int nOffsetY )
  3457. {
  3458. _pinCorner = pinCorner;
  3459. _autoResizeDirection = AUTORESIZE_NO;
  3460. m_nPinDeltaX = nOffsetX;
  3461. m_nPinDeltaY = nOffsetY;
  3462. m_nResizeDeltaX = 0;
  3463. m_nResizeDeltaY = 0;
  3464. }
  3465. //-----------------------------------------------------------------------------
  3466. // Purpose: data accessor
  3467. //-----------------------------------------------------------------------------
  3468. Panel::PinCorner_e Panel::GetPinCorner()
  3469. {
  3470. return (PinCorner_e)_pinCorner;
  3471. }
  3472. //-----------------------------------------------------------------------------
  3473. // Gets the relative offset of the control from the pin corner
  3474. //-----------------------------------------------------------------------------
  3475. void Panel::GetPinOffset( int &dx, int &dy )
  3476. {
  3477. dx = m_nPinDeltaX;
  3478. dy = m_nPinDeltaY;
  3479. }
  3480. //-----------------------------------------------------------------------------
  3481. // Purpose: data accessor
  3482. //-----------------------------------------------------------------------------
  3483. Panel::AutoResize_e Panel::GetAutoResize()
  3484. {
  3485. return (AutoResize_e)_autoResizeDirection;
  3486. }
  3487. //-----------------------------------------------------------------------------
  3488. // Gets the relative offset of the control from the pin corner
  3489. //-----------------------------------------------------------------------------
  3490. void Panel::GetResizeOffset( int &dx, int &dy )
  3491. {
  3492. dx = m_nResizeDeltaX;
  3493. dy = m_nResizeDeltaY;
  3494. }
  3495. //-----------------------------------------------------------------------------
  3496. // Tells this panel that it should pin itself to the corner of a specified sibling panel
  3497. //-----------------------------------------------------------------------------
  3498. void Panel::PinToSibling( const char *pszSibling, PinCorner_e pinOurCorner, PinCorner_e pinSibling )
  3499. {
  3500. _pinCornerToSibling = pinOurCorner;
  3501. _pinToSiblingCorner = pinSibling;
  3502. if ( m_pinSibling.Get() && _pinToSibling && pszSibling && !Q_strcmp( _pinToSibling, pszSibling ) )
  3503. return;
  3504. if (_pinToSibling)
  3505. {
  3506. delete [] _pinToSibling;
  3507. _pinToSibling = NULL;
  3508. }
  3509. if (pszSibling)
  3510. {
  3511. int len = Q_strlen(pszSibling) + 1;
  3512. _pinToSibling = new char[ len ];
  3513. Q_strncpy( _pinToSibling, pszSibling, len );
  3514. }
  3515. m_pinSibling = NULL;
  3516. UpdateSiblingPin();
  3517. }
  3518. //-----------------------------------------------------------------------------
  3519. // Purpose:
  3520. //-----------------------------------------------------------------------------
  3521. void Panel::UpdateSiblingPin( void )
  3522. {
  3523. if ( !_pinToSibling )
  3524. {
  3525. ipanel()->SetSiblingPin(GetVPanel(), NULL);
  3526. return;
  3527. }
  3528. if ( !m_pinSibling.Get() )
  3529. {
  3530. // Resolve our sibling now
  3531. m_pinSibling = FindSiblingByName( _pinToSibling );
  3532. }
  3533. if ( m_pinSibling.Get() )
  3534. {
  3535. ipanel()->SetSiblingPin( GetVPanel(), m_pinSibling->GetVPanel(), _pinCornerToSibling, _pinToSiblingCorner );
  3536. }
  3537. else
  3538. {
  3539. ipanel()->SetSiblingPin(GetVPanel(), NULL);
  3540. }
  3541. }
  3542. //-----------------------------------------------------------------------------
  3543. // Purpose:
  3544. //-----------------------------------------------------------------------------
  3545. void Panel::ApplySchemeSettings(IScheme *pScheme)
  3546. {
  3547. // get colors
  3548. SetFgColor(GetSchemeColor("Panel.FgColor", pScheme));
  3549. SetBgColor(GetSchemeColor("Panel.BgColor", pScheme));
  3550. #if defined( VGUI_USEDRAGDROP )
  3551. m_clrDragFrame = pScheme->GetColor("DragDrop.DragFrame", Color(255, 255, 255, 192));
  3552. m_clrDropFrame = pScheme->GetColor("DragDrop.DropFrame", Color(150, 255, 150, 255));
  3553. m_infoFont = pScheme->GetFont( "DefaultVerySmall" );
  3554. #endif
  3555. // mark us as no longer needing scheme settings applied
  3556. _flags.ClearFlag( NEEDS_SCHEME_UPDATE );
  3557. if ( IsBuildGroupEnabled() )
  3558. {
  3559. _buildGroup->ApplySchemeSettings(pScheme);
  3560. return;
  3561. }
  3562. }
  3563. //-----------------------------------------------------------------------------
  3564. // Purpose: Checks to see if the panel needs it's scheme info setup
  3565. //-----------------------------------------------------------------------------
  3566. void Panel::PerformApplySchemeSettings()
  3567. {
  3568. if ( _flags.IsFlagSet( NEEDS_DEFAULT_SETTINGS_APPLIED ) )
  3569. {
  3570. InternalInitDefaultValues( GetAnimMap() );
  3571. }
  3572. if ( _flags.IsFlagSet( NEEDS_SCHEME_UPDATE ) )
  3573. {
  3574. VPROF( "ApplySchemeSettings" );
  3575. IScheme *pScheme = scheme()->GetIScheme( GetScheme() );
  3576. AssertOnce( pScheme );
  3577. if ( pScheme ) // this should NEVER be null, but if it is bad things would happen in ApplySchemeSettings...
  3578. {
  3579. ApplySchemeSettings( pScheme );
  3580. //_needsSchemeUpdate = false;
  3581. ApplyOverridableColors();
  3582. UpdateSiblingPin();
  3583. }
  3584. }
  3585. }
  3586. //-----------------------------------------------------------------------------
  3587. // Purpose: Loads panel details related to autoresize from the resource info
  3588. //-----------------------------------------------------------------------------
  3589. #if defined( _DEBUG )
  3590. static Panel *lastWarningParent = 0;
  3591. #endif
  3592. void Panel::ApplyAutoResizeSettings(KeyValues *inResourceData)
  3593. {
  3594. tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "%s - %s", __FUNCTION__, GetName() );
  3595. int x, y;
  3596. GetPos(x, y);
  3597. int wide, tall;
  3598. GetSize( wide, tall );
  3599. AutoResize_e autoResize = (AutoResize_e)inResourceData->GetInt( "AutoResize", AUTORESIZE_NO );
  3600. PinCorner_e pinCorner = (PinCorner_e)inResourceData->GetInt( "PinCorner", PIN_TOPLEFT );
  3601. // By default, measure unpinned corner for the offset
  3602. int pw = wide, pt = tall;
  3603. if ( GetParent() )
  3604. {
  3605. GetParent()->GetSize( pw, pt );
  3606. #if defined( _DEBUG )
  3607. if ( pw == 64 && pt == 24 )
  3608. {
  3609. if ( GetParent() != lastWarningParent )
  3610. {
  3611. lastWarningParent = GetParent();
  3612. Warning( "Resize parent (panel(%s) -> parent(%s)) not sized yet!!!\n", GetName(), GetParent()->GetName() );
  3613. }
  3614. }
  3615. #endif
  3616. }
  3617. int nPinnedCornerOffsetX = 0, nPinnedCornerOffsetY = 0;
  3618. int nUnpinnedCornerOffsetX = 0, nUnpinnedCornerOffsetY = 0;
  3619. switch( pinCorner )
  3620. {
  3621. case PIN_TOPLEFT:
  3622. nPinnedCornerOffsetX = x;
  3623. nPinnedCornerOffsetY = y;
  3624. nUnpinnedCornerOffsetX = (x + wide) - pw;
  3625. nUnpinnedCornerOffsetY = (y + tall) - pt;
  3626. break;
  3627. case PIN_TOPRIGHT:
  3628. nPinnedCornerOffsetX = (x + wide) - pw;
  3629. nPinnedCornerOffsetY = y;
  3630. nUnpinnedCornerOffsetX = x;
  3631. nUnpinnedCornerOffsetY = (y + tall) - pt;
  3632. break;
  3633. case PIN_BOTTOMLEFT:
  3634. nPinnedCornerOffsetX = x;
  3635. nPinnedCornerOffsetY = (y + tall) - pt;
  3636. nUnpinnedCornerOffsetX = (x + wide) - pw;
  3637. nUnpinnedCornerOffsetY = y;
  3638. break;
  3639. case PIN_BOTTOMRIGHT:
  3640. nPinnedCornerOffsetX = (x + wide) - pw;
  3641. nPinnedCornerOffsetY = (y + tall) - pt;
  3642. nUnpinnedCornerOffsetX = x;
  3643. nUnpinnedCornerOffsetY = y;
  3644. break;
  3645. }
  3646. // Allow specific overrides in the resource file
  3647. if ( IsProportional() )
  3648. {
  3649. if ( inResourceData->FindKey( "PinnedCornerOffsetX" ) )
  3650. {
  3651. nPinnedCornerOffsetX = scheme()->GetProportionalScaledValueEx( GetScheme(), inResourceData->GetInt( "PinnedCornerOffsetX" ) );
  3652. }
  3653. if ( inResourceData->FindKey( "PinnedCornerOffsetY" ) )
  3654. {
  3655. nPinnedCornerOffsetY = scheme()->GetProportionalScaledValueEx( GetScheme(), inResourceData->GetInt( "PinnedCornerOffsetY" ) );
  3656. }
  3657. if ( inResourceData->FindKey( "UnpinnedCornerOffsetX" ) )
  3658. {
  3659. nUnpinnedCornerOffsetX = scheme()->GetProportionalScaledValueEx( GetScheme(), inResourceData->GetInt( "UnpinnedCornerOffsetX" ) );
  3660. }
  3661. if ( inResourceData->FindKey( "UnpinnedCornerOffsetY" ) )
  3662. {
  3663. nUnpinnedCornerOffsetY = scheme()->GetProportionalScaledValueEx( GetScheme(), inResourceData->GetInt( "UnpinnedCornerOffsetY" ) );
  3664. }
  3665. }
  3666. else
  3667. {
  3668. nPinnedCornerOffsetX = inResourceData->GetInt( "PinnedCornerOffsetX", nPinnedCornerOffsetX );
  3669. nPinnedCornerOffsetY = inResourceData->GetInt( "PinnedCornerOffsetY", nPinnedCornerOffsetY );
  3670. nUnpinnedCornerOffsetX = inResourceData->GetInt( "UnpinnedCornerOffsetX", nUnpinnedCornerOffsetX );
  3671. nUnpinnedCornerOffsetY = inResourceData->GetInt( "UnpinnedCornerOffsetY", nUnpinnedCornerOffsetY );
  3672. }
  3673. if ( autoResize == AUTORESIZE_NO )
  3674. {
  3675. nUnpinnedCornerOffsetX = nUnpinnedCornerOffsetY = 0;
  3676. }
  3677. SetAutoResize( pinCorner, autoResize, nPinnedCornerOffsetX, nPinnedCornerOffsetY, nUnpinnedCornerOffsetX, nUnpinnedCornerOffsetY );
  3678. }
  3679. ConVar panel_test_title_safe( "panel_test_title_safe", "0", FCVAR_CHEAT, "Test vgui panel positioning with title safe indentation" );
  3680. Panel::PinCorner_e GetPinCornerFromString( const char* pszCornerName )
  3681. {
  3682. if ( pszCornerName == NULL )
  3683. {
  3684. return Panel::PIN_TOPLEFT;
  3685. }
  3686. // Optimize for all the old entries of a single digit
  3687. if ( strlen( pszCornerName ) == 1 )
  3688. {
  3689. return (Panel::PinCorner_e)atoi( pszCornerName );
  3690. }
  3691. for( int i=0; i<ARRAYSIZE( g_PinCornerStrings ); ++i )
  3692. {
  3693. if ( !Q_stricmp( g_PinCornerStrings[i], pszCornerName ) )
  3694. {
  3695. return (Panel::PinCorner_e)i;
  3696. }
  3697. }
  3698. return Panel::PIN_TOPLEFT;
  3699. }
  3700. //-----------------------------------------------------------------------------
  3701. // Purpose: Loads panel details from the resource info
  3702. //-----------------------------------------------------------------------------
  3703. void Panel::ApplySettings(KeyValues *inResourceData)
  3704. {
  3705. tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "%s - %s", __FUNCTION__, GetName() );
  3706. // First restore to default values
  3707. if ( _flags.IsFlagSet( NEEDS_DEFAULT_SETTINGS_APPLIED ) )
  3708. {
  3709. InternalInitDefaultValues( GetAnimMap() );
  3710. }
  3711. // Let PanelAnimationVars auto-retrieve settings (we restore defaults above
  3712. // since a script might be missing certain values)
  3713. InternalApplySettings( GetAnimMap(), inResourceData );
  3714. // clear any alignment flags
  3715. _buildModeFlags &= ~( BUILDMODE_SAVE_XPOS_RIGHTALIGNED
  3716. | BUILDMODE_SAVE_XPOS_CENTERALIGNED
  3717. | BUILDMODE_SAVE_YPOS_BOTTOMALIGNED
  3718. | BUILDMODE_SAVE_YPOS_CENTERALIGNED
  3719. | BUILDMODE_SAVE_WIDE_FULL
  3720. | BUILDMODE_SAVE_TALL_FULL
  3721. | BUILDMODE_SAVE_PROPORTIONAL_TO_PARENT
  3722. | BUILDMODE_SAVE_WIDE_PROPORTIONAL
  3723. | BUILDMODE_SAVE_TALL_PROPORTIONAL
  3724. | BUILDMODE_SAVE_XPOS_PROPORTIONAL_SELF
  3725. | BUILDMODE_SAVE_YPOS_PROPORTIONAL_SELF
  3726. | BUILDMODE_SAVE_WIDE_PROPORTIONAL_TALL
  3727. | BUILDMODE_SAVE_TALL_PROPORTIONAL_WIDE
  3728. | BUILDMODE_SAVE_XPOS_PROPORTIONAL_PARENT
  3729. | BUILDMODE_SAVE_YPOS_PROPORTIONAL_PARENT
  3730. | BUILDMODE_SAVE_WIDE_PROPORTIONAL_SELF
  3731. | BUILDMODE_SAVE_TALL_PROPORTIONAL_SELF );
  3732. // get the position
  3733. int alignScreenWide, alignScreenTall; // screen dimensions used for pinning in splitscreen
  3734. surface()->GetScreenSize( alignScreenWide, alignScreenTall );
  3735. int screenWide = alignScreenWide;
  3736. int screenTall = alignScreenTall;
  3737. // temporarily remove the override to get the fullscreen dimensions
  3738. if ( surface()->IsScreenSizeOverrideActive() )
  3739. {
  3740. surface()->ForceScreenSizeOverride( false, 0, 0 );
  3741. surface()->GetScreenSize( screenWide, screenTall );
  3742. // restore the override
  3743. surface()->ForceScreenSizeOverride( true, alignScreenWide, alignScreenTall );
  3744. }
  3745. int parentX = 0;
  3746. int parentY = 0;
  3747. // flag to cause windows to get screenWide and screenTall from their parents,
  3748. // this allows children windows to use fill and right/bottom alignment even
  3749. // if their parent does not use the full screen.
  3750. if ( inResourceData->GetInt( "proportionalToParent", 0 ) == 1 )
  3751. {
  3752. _buildModeFlags |= BUILDMODE_SAVE_PROPORTIONAL_TO_PARENT;
  3753. if ( GetParent() != NULL )
  3754. {
  3755. GetParent()->GetBounds( parentX, parentY, alignScreenWide, alignScreenTall );
  3756. }
  3757. }
  3758. // size
  3759. int wide = ComputeWide( this, _buildModeFlags, inResourceData, alignScreenWide, alignScreenTall, false );
  3760. int tall = ComputeTall( this, _buildModeFlags, inResourceData, alignScreenWide, alignScreenTall, false );
  3761. int x, y;
  3762. GetPos(x, y);
  3763. const char *xstr = inResourceData->GetString( "xpos", NULL );
  3764. const char *ystr = inResourceData->GetString( "ypos", NULL );
  3765. _buildModeFlags |= ComputePos( this, xstr, x, wide, alignScreenWide, true, OP_SET );
  3766. _buildModeFlags |= ComputePos( this, ystr, y, tall, alignScreenTall, false, OP_SET );
  3767. bool bUsesTitleSafeArea = false;
  3768. int titleSafeWide = 0;
  3769. int titleSafeTall = 0;
  3770. Rect_t excludeEdgeFromTitleSafe; // if a side is set to != 0, don't title safe relative to that edge
  3771. excludeEdgeFromTitleSafe.x = 0;
  3772. excludeEdgeFromTitleSafe.y = 0;
  3773. excludeEdgeFromTitleSafe.width = 0;
  3774. excludeEdgeFromTitleSafe.height = 0;
  3775. if ( IsX360() || panel_test_title_safe.GetBool() )
  3776. {
  3777. // "usetitlesafe" "1" - required inner 90%
  3778. // "usetitlesafe" "2" - suggested inner 85%
  3779. int iUseTitleSafeValue = 0;
  3780. if ( inResourceData->FindKey( "usetitlesafe" ) )
  3781. {
  3782. iUseTitleSafeValue = inResourceData->GetInt( "usetitlesafe" );
  3783. bUsesTitleSafeArea = ( iUseTitleSafeValue > 0 );
  3784. }
  3785. if( bUsesTitleSafeArea )
  3786. {
  3787. titleSafeWide = screenWide * ( iUseTitleSafeValue == 1 ? 0.05f : 0.075f );
  3788. titleSafeTall = screenTall * ( iUseTitleSafeValue == 1 ? 0.05f : 0.075f );
  3789. // Don't title safe internal boundaries for split screen viewports
  3790. int splitX = 0;
  3791. int splitY = 0;
  3792. vgui::surface()->OffsetAbsPos( splitX, splitY );
  3793. bool bHorizontalSplit = ( alignScreenTall != screenTall );
  3794. bool bVerticalSplit = ( alignScreenWide != screenWide );
  3795. if ( bHorizontalSplit )
  3796. {
  3797. // top or bottom?
  3798. if ( splitY != parentY )
  3799. {
  3800. excludeEdgeFromTitleSafe.y = 1;
  3801. }
  3802. else
  3803. {
  3804. excludeEdgeFromTitleSafe.height = 1;
  3805. }
  3806. }
  3807. if ( bVerticalSplit )
  3808. {
  3809. // left or right
  3810. if ( splitX != parentX )
  3811. {
  3812. excludeEdgeFromTitleSafe.x = 1;
  3813. }
  3814. else
  3815. {
  3816. excludeEdgeFromTitleSafe.width = 1;
  3817. }
  3818. }
  3819. if ( _buildModeFlags & BUILDMODE_SAVE_XPOS_RIGHTALIGNED )
  3820. {
  3821. if ( !excludeEdgeFromTitleSafe.width )
  3822. {
  3823. x -= titleSafeWide; // right edge
  3824. }
  3825. }
  3826. else if (_buildModeFlags & BUILDMODE_SAVE_XPOS_CENTERALIGNED)
  3827. {
  3828. }
  3829. else if ( !excludeEdgeFromTitleSafe.x )
  3830. {
  3831. x += titleSafeWide; // left edge
  3832. }
  3833. if ( _buildModeFlags & BUILDMODE_SAVE_YPOS_BOTTOMALIGNED )
  3834. {
  3835. if ( !excludeEdgeFromTitleSafe.height )
  3836. {
  3837. y -= titleSafeTall; // bottom edge
  3838. }
  3839. }
  3840. else if (_buildModeFlags & BUILDMODE_SAVE_YPOS_CENTERALIGNED)
  3841. {
  3842. }
  3843. else if ( !excludeEdgeFromTitleSafe.y )
  3844. {
  3845. y += titleSafeTall; // top edge
  3846. }
  3847. }
  3848. }
  3849. SetNavUp( inResourceData->GetString("navUp") );
  3850. SetNavDown( inResourceData->GetString("navDown") );
  3851. SetNavLeft( inResourceData->GetString("navLeft") );
  3852. SetNavRight( inResourceData->GetString("navRight") );
  3853. SetNavToRelay( inResourceData->GetString("navToRelay") );
  3854. SetNavActivate( inResourceData->GetString("navActivate") );
  3855. SetNavBack( inResourceData->GetString("navBack") );
  3856. SetPos(x, y);
  3857. if (inResourceData->FindKey( "zpos" ))
  3858. {
  3859. SetZPos( inResourceData->GetInt( "zpos" ) );
  3860. }
  3861. if( bUsesTitleSafeArea )
  3862. {
  3863. if ( _buildModeFlags & BUILDMODE_SAVE_WIDE_FULL )
  3864. {
  3865. if ( !excludeEdgeFromTitleSafe.x )
  3866. wide -= titleSafeWide;
  3867. if ( !excludeEdgeFromTitleSafe.width )
  3868. wide -= titleSafeWide;
  3869. }
  3870. if ( _buildModeFlags & BUILDMODE_SAVE_TALL_FULL )
  3871. {
  3872. if ( !excludeEdgeFromTitleSafe.y )
  3873. tall -= titleSafeTall;
  3874. if ( !excludeEdgeFromTitleSafe.height )
  3875. tall -= titleSafeTall;
  3876. }
  3877. }
  3878. SetSize( wide, tall );
  3879. // NOTE: This has to happen after pos + size is set
  3880. ApplyAutoResizeSettings( inResourceData );
  3881. // only get colors if we're ignoring the scheme
  3882. if (inResourceData->GetInt("IgnoreScheme", 0))
  3883. {
  3884. PerformApplySchemeSettings();
  3885. }
  3886. // state
  3887. int state = inResourceData->GetInt("visible", 1);
  3888. if (state == 0)
  3889. {
  3890. SetVisible(false);
  3891. }
  3892. else if (state == 1)
  3893. {
  3894. SetVisible(true);
  3895. }
  3896. SetEnabled( inResourceData->GetInt("enabled", true) );
  3897. bool bMouseEnabled = inResourceData->GetInt( "mouseinputenabled", true );
  3898. if ( !bMouseEnabled )
  3899. {
  3900. SetMouseInputEnabled( false );
  3901. }
  3902. // tab order
  3903. SetTabPosition(inResourceData->GetInt("tabPosition", 0));
  3904. const char *tooltip = inResourceData->GetString("tooltiptext", NULL);
  3905. if (tooltip && *tooltip)
  3906. {
  3907. GetTooltip()->SetText(tooltip);
  3908. }
  3909. // paint background?
  3910. int nPaintBackground = inResourceData->GetInt("paintbackground", -1);
  3911. if (nPaintBackground >= 0)
  3912. {
  3913. SetPaintBackgroundEnabled( nPaintBackground != 0 );
  3914. }
  3915. // paint border?
  3916. int nPaintBorder = inResourceData->GetInt("paintborder", -1);
  3917. if (nPaintBorder >= 0)
  3918. {
  3919. SetPaintBorderEnabled( nPaintBorder != 0 );
  3920. }
  3921. // border?
  3922. const char *pBorder = inResourceData->GetString( "border", "" );
  3923. if ( *pBorder )
  3924. {
  3925. IScheme *pScheme = scheme()->GetIScheme( GetScheme() );
  3926. SetBorder( pScheme->GetBorder( pBorder ) );
  3927. }
  3928. // check to see if we have a new name assigned
  3929. const char *newName = inResourceData->GetString("fieldName", NULL);
  3930. if ( newName )
  3931. {
  3932. // Only slam the name if the new one differs...
  3933. SetName(newName);
  3934. }
  3935. tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "%s - %s: Action signal", __FUNCTION__, GetName() );
  3936. // Automatically add an action signal target if one is specified. This allows for
  3937. // nested child buttons to add their distant parents as action signal targets.
  3938. int nActionSignalLevel = inResourceData->GetInt( "actionsignallevel", -1 );
  3939. if ( nActionSignalLevel != -1 )
  3940. {
  3941. Panel *pActionSignalTarget = this;
  3942. while( nActionSignalLevel-- )
  3943. {
  3944. pActionSignalTarget = pActionSignalTarget->GetParent();
  3945. }
  3946. AddActionSignalTarget( pActionSignalTarget );
  3947. }
  3948. // check to see if we need to render to the frame buffer even if
  3949. // stereo mode is trying to render all of the ui to a render target
  3950. m_bForceStereoRenderToFrameBuffer = inResourceData->GetBool( "ForceStereoRenderToFrameBuffer", false );
  3951. //=============================================================================
  3952. // HPE_BEGIN:
  3953. // [pfreese] Support for reading rounded corner flags
  3954. //=============================================================================
  3955. int roundedCorners = inResourceData->GetInt( "RoundedCorners", -1 );
  3956. if ( roundedCorners >= 0 )
  3957. {
  3958. m_roundedCorners = roundedCorners;
  3959. }
  3960. //=============================================================================
  3961. // HPE_END
  3962. //=============================================================================
  3963. tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "%s - %s: Pin Sibling", __FUNCTION__, GetName() );
  3964. const char *pszSiblingName = inResourceData->GetString("pin_to_sibling", NULL);
  3965. PinCorner_e pinOurCornerToSibling = GetPinCornerFromString( inResourceData->GetString( "pin_corner_to_sibling", NULL ) );
  3966. PinCorner_e pinSiblingCorner = GetPinCornerFromString( inResourceData->GetString( "pin_to_sibling_corner", NULL ) );
  3967. PinToSibling( pszSiblingName, pinOurCornerToSibling, pinSiblingCorner );
  3968. tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "%s - %s: Color overrides", __FUNCTION__, GetName() );
  3969. // Allow overriding of colors. Used mostly by HUD elements, where scheme color usage is often undesired.
  3970. IScheme *pScheme = vgui::scheme()->GetIScheme( GetScheme() );
  3971. for ( int i = 0; i < m_OverridableColorEntries.Count(); i++ )
  3972. {
  3973. // Need to ensure the key exists, so we don't overwrite existing colors when it's not set.
  3974. if ( inResourceData->FindKey( m_OverridableColorEntries[i].m_pszScriptName, false ) )
  3975. {
  3976. // Get the color as a string - test whether it is an actual color or a reference to a scheme color
  3977. const char *pColorStr = inResourceData->GetString( m_OverridableColorEntries[i].m_pszScriptName );
  3978. Color &clrDest = m_OverridableColorEntries[i].m_colFromScript;
  3979. if ( pColorStr[0] == '.' || isdigit( pColorStr[0] ) )
  3980. {
  3981. float r = 0.0f, g = 0.0f, b = 0.0f, a = 0.0f;
  3982. sscanf( pColorStr, "%f %f %f %f", &r, &g, &b, &a );
  3983. clrDest[0] = (unsigned char)r;
  3984. clrDest[1] = (unsigned char)g;
  3985. clrDest[2] = (unsigned char)b;
  3986. clrDest[3] = (unsigned char)a;
  3987. }
  3988. else
  3989. {
  3990. // First character wasn't a digit or a decimal - do a scheme color lookup
  3991. clrDest = pScheme->GetColor( pColorStr, Color( 255, 255, 255, 255 ) );
  3992. }
  3993. (*m_OverridableColorEntries[i].m_pColor) = m_OverridableColorEntries[i].m_colFromScript;
  3994. m_OverridableColorEntries[i].m_bOverridden = true;
  3995. }
  3996. }
  3997. tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "%s - %s: Keyboard enabled", __FUNCTION__, GetName() );
  3998. const char *pKeyboardInputEnabled = inResourceData->GetString( "keyboardinputenabled", NULL );
  3999. if ( pKeyboardInputEnabled && pKeyboardInputEnabled[0] )
  4000. {
  4001. SetKeyBoardInputEnabled( atoi( pKeyboardInputEnabled ) );
  4002. }
  4003. OnChildSettingsApplied( inResourceData, this );
  4004. }
  4005. //-----------------------------------------------------------------------------
  4006. // Purpose: Saves out a resource description of this panel
  4007. //-----------------------------------------------------------------------------
  4008. void Panel::GetSettings( KeyValues *outResourceData )
  4009. {
  4010. // control class name (so it can be recreated later if needed)
  4011. outResourceData->SetString( "ControlName", GetClassName() );
  4012. // name
  4013. outResourceData->SetString( "fieldName", _panelName );
  4014. // positioning
  4015. int screenWide, screenTall;
  4016. surface()->GetScreenSize(screenWide, screenTall);
  4017. int x, y;
  4018. GetPos( x, y );
  4019. if ( IsProportional() )
  4020. {
  4021. x = scheme()->GetProportionalNormalizedValueEx( GetScheme(), x );
  4022. y = scheme()->GetProportionalNormalizedValueEx( GetScheme(), y );
  4023. }
  4024. // correct for alignment
  4025. if (_buildModeFlags & BUILDMODE_SAVE_XPOS_RIGHTALIGNED)
  4026. {
  4027. x = screenWide - x;
  4028. char xstr[32];
  4029. Q_snprintf(xstr, sizeof( xstr ), "r%d", x);
  4030. outResourceData->SetString( "xpos", xstr );
  4031. }
  4032. else if (_buildModeFlags & BUILDMODE_SAVE_XPOS_CENTERALIGNED)
  4033. {
  4034. x = (screenWide / 2) + x;
  4035. char xstr[32];
  4036. Q_snprintf(xstr, sizeof( xstr ), "c%d", x);
  4037. outResourceData->SetString( "xpos", xstr );
  4038. }
  4039. else
  4040. {
  4041. outResourceData->SetInt( "xpos", x );
  4042. }
  4043. if (_buildModeFlags & BUILDMODE_SAVE_YPOS_BOTTOMALIGNED)
  4044. {
  4045. y = screenTall - y;
  4046. char ystr[32];
  4047. Q_snprintf(ystr, sizeof( ystr ), "r%d", y);
  4048. outResourceData->SetString( "ypos", ystr );
  4049. }
  4050. else if (_buildModeFlags & BUILDMODE_SAVE_YPOS_CENTERALIGNED)
  4051. {
  4052. y = (screenTall / 2) + y;
  4053. char ystr[32];
  4054. Q_snprintf(ystr, sizeof( ystr ), "c%d", y);
  4055. outResourceData->SetString( "ypos", ystr );
  4056. }
  4057. else
  4058. {
  4059. outResourceData->SetInt( "ypos", y );
  4060. }
  4061. if (m_pTooltips)
  4062. {
  4063. if (strlen(m_pTooltips->GetText()) > 0)
  4064. {
  4065. outResourceData->SetString("tooltiptext", m_pTooltips->GetText());
  4066. }
  4067. }
  4068. int wide, tall;
  4069. GetSize( wide, tall );
  4070. if ( IsProportional() )
  4071. {
  4072. wide = scheme()->GetProportionalNormalizedValueEx( GetScheme(), wide );
  4073. tall = scheme()->GetProportionalNormalizedValueEx( GetScheme(), tall );
  4074. }
  4075. int z = ipanel()->GetZPos(GetVPanel());
  4076. if (z)
  4077. {
  4078. outResourceData->SetInt("zpos", z);
  4079. }
  4080. // Correct for alignment
  4081. if (_buildModeFlags & BUILDMODE_SAVE_WIDE_FULL )
  4082. {
  4083. wide = screenWide - wide;
  4084. char wstr[32];
  4085. Q_snprintf(wstr, sizeof( wstr ), "f%d", wide);
  4086. outResourceData->SetString( "wide", wstr );
  4087. }
  4088. else
  4089. {
  4090. outResourceData->SetInt( "wide", wide );
  4091. }
  4092. outResourceData->SetInt( "tall", tall );
  4093. outResourceData->SetInt("AutoResize", GetAutoResize());
  4094. outResourceData->SetInt("PinCorner", GetPinCorner());
  4095. //=============================================================================
  4096. // HPE_BEGIN:
  4097. // [pfreese] Support for writing out rounded corner flags
  4098. //=============================================================================
  4099. outResourceData->SetInt("RoundedCorners", m_roundedCorners);
  4100. //=============================================================================
  4101. // HPE_END
  4102. //=============================================================================
  4103. outResourceData->SetString( "pin_to_sibling", _pinToSibling );
  4104. outResourceData->SetInt("pin_corner_to_sibling", _pinCornerToSibling );
  4105. outResourceData->SetInt("pin_to_sibling_corner", _pinToSiblingCorner );
  4106. // state
  4107. outResourceData->SetInt( "visible", IsVisible() );
  4108. outResourceData->SetInt( "enabled", IsEnabled() );
  4109. outResourceData->SetInt( "tabPosition", GetTabPosition() );
  4110. for ( int i = 0; i < m_OverridableColorEntries.Count(); i++ )
  4111. {
  4112. if ( m_OverridableColorEntries[i].m_bOverridden )
  4113. {
  4114. outResourceData->SetColor( m_OverridableColorEntries[i].m_pszScriptName, m_OverridableColorEntries[i].m_colFromScript );
  4115. }
  4116. }
  4117. }
  4118. //-----------------------------------------------------------------------------
  4119. // Purpose: After applying settings, apply overridable colors.
  4120. // Done post apply settings, so that baseclass settings don't stomp
  4121. // the script specified override colors.
  4122. //-----------------------------------------------------------------------------
  4123. void Panel::ApplyOverridableColors( void )
  4124. {
  4125. for ( int i = 0; i < m_OverridableColorEntries.Count(); i++ )
  4126. {
  4127. if ( m_OverridableColorEntries[i].m_bOverridden )
  4128. {
  4129. (*m_OverridableColorEntries[i].m_pColor) = m_OverridableColorEntries[i].m_colFromScript;
  4130. }
  4131. }
  4132. }
  4133. //-----------------------------------------------------------------------------
  4134. // Purpose:
  4135. //-----------------------------------------------------------------------------
  4136. void Panel::SetOverridableColor( Color *pColor, const Color &newColor )
  4137. {
  4138. for ( int i = 0; i < m_OverridableColorEntries.Count(); i++ )
  4139. {
  4140. if ( m_OverridableColorEntries[i].m_bOverridden )
  4141. {
  4142. if ( m_OverridableColorEntries[i].m_pColor == pColor )
  4143. return;
  4144. }
  4145. }
  4146. // Didn't find it, or it's not been overridden.
  4147. *pColor = newColor;
  4148. }
  4149. //-----------------------------------------------------------------------------
  4150. // Purpose:
  4151. //-----------------------------------------------------------------------------
  4152. Color Panel::GetSchemeColor(const char *keyName, IScheme *pScheme)
  4153. {
  4154. return pScheme->GetColor(keyName, Color(255, 255, 255, 255));
  4155. }
  4156. //-----------------------------------------------------------------------------
  4157. // Purpose:
  4158. //-----------------------------------------------------------------------------
  4159. Color Panel::GetSchemeColor(const char *keyName, Color defaultColor, IScheme *pScheme)
  4160. {
  4161. return pScheme->GetColor(keyName, defaultColor);
  4162. }
  4163. //-----------------------------------------------------------------------------
  4164. // Purpose: Returns a string description of the panel fields for use in the UI
  4165. //-----------------------------------------------------------------------------
  4166. const char *Panel::GetDescription( void )
  4167. {
  4168. static const char *panelDescription = "string fieldName, int xpos, int ypos, int wide, int tall, bool visible, bool enabled, int tabPosition, corner pinCorner, autoresize autoResize, string tooltiptext";
  4169. return panelDescription;
  4170. }
  4171. //-----------------------------------------------------------------------------
  4172. // Purpose: user configuration settings
  4173. // this is used for any control details the user wants saved between sessions
  4174. // eg. dialog positions, last directory opened, list column width
  4175. //-----------------------------------------------------------------------------
  4176. void Panel::ApplyUserConfigSettings(KeyValues *userConfig)
  4177. {
  4178. }
  4179. //-----------------------------------------------------------------------------
  4180. // Purpose: returns user config settings for this control
  4181. //-----------------------------------------------------------------------------
  4182. void Panel::GetUserConfigSettings(KeyValues *userConfig)
  4183. {
  4184. }
  4185. //-----------------------------------------------------------------------------
  4186. // Purpose: optimization, return true if this control has any user config settings
  4187. //-----------------------------------------------------------------------------
  4188. bool Panel::HasUserConfigSettings()
  4189. {
  4190. return false;
  4191. }
  4192. //-----------------------------------------------------------------------------
  4193. // Purpose:
  4194. //-----------------------------------------------------------------------------
  4195. void Panel::InternalInvalidateLayout()
  4196. {
  4197. InvalidateLayout(false, false);
  4198. }
  4199. //-----------------------------------------------------------------------------
  4200. // Purpose: called whenever the panel moves
  4201. //-----------------------------------------------------------------------------
  4202. void Panel::OnMove()
  4203. {
  4204. }
  4205. //-----------------------------------------------------------------------------
  4206. // Purpose:
  4207. //-----------------------------------------------------------------------------
  4208. void Panel::InternalMove()
  4209. {
  4210. OnMove();
  4211. for(int i=0;i<GetChildCount();i++)
  4212. {
  4213. // recursively apply to all children
  4214. GetChild(i)->OnMove();
  4215. }
  4216. }
  4217. //-----------------------------------------------------------------------------
  4218. // Purpose: empty function
  4219. //-----------------------------------------------------------------------------
  4220. void Panel::OnTick()
  4221. {
  4222. }
  4223. //-----------------------------------------------------------------------------
  4224. // Purpose: versioning
  4225. //-----------------------------------------------------------------------------
  4226. void *Panel::QueryInterface(EInterfaceID id)
  4227. {
  4228. if (id == ICLIENTPANEL_STANDARD_INTERFACE)
  4229. {
  4230. return this;
  4231. }
  4232. return NULL;
  4233. }
  4234. //-----------------------------------------------------------------------------
  4235. // Purpose: Map all the base messages to functions
  4236. // ordering from most -> least used improves speed
  4237. //-----------------------------------------------------------------------------
  4238. MessageMapItem_t Panel::m_MessageMap[] =
  4239. {
  4240. MAP_MESSAGE_INT( Panel, "RequestFocus", RequestFocus, "direction" )
  4241. };
  4242. // IMPLEMENT_PANELMAP( Panel, NULL )
  4243. PanelMap_t Panel::m_PanelMap = { Panel::m_MessageMap, ARRAYSIZE(Panel::m_MessageMap), "Panel", NULL };
  4244. PanelMap_t *Panel::GetPanelMap( void ) { return &m_PanelMap; }
  4245. //-----------------------------------------------------------------------------
  4246. // Purpose: !! Soon to replace existing prepare panel map
  4247. //-----------------------------------------------------------------------------
  4248. void PreparePanelMessageMap(PanelMessageMap *panelMap)
  4249. {
  4250. // iterate through the class hierarchy message maps
  4251. while ( panelMap != NULL && !panelMap->processed )
  4252. {
  4253. // hash message map strings into symbols
  4254. for (int i = 0; i < panelMap->entries.Count(); i++)
  4255. {
  4256. MessageMapItem_t *item = &panelMap->entries[i];
  4257. if (item->name)
  4258. {
  4259. item->nameSymbol = KeyValuesSystem()->GetSymbolForString(item->name);
  4260. }
  4261. else
  4262. {
  4263. item->nameSymbol = INVALID_KEY_SYMBOL;
  4264. }
  4265. if (item->firstParamName)
  4266. {
  4267. item->firstParamSymbol = KeyValuesSystem()->GetSymbolForString(item->firstParamName);
  4268. }
  4269. else
  4270. {
  4271. item->firstParamSymbol = INVALID_KEY_SYMBOL;
  4272. }
  4273. if (item->secondParamName)
  4274. {
  4275. item->secondParamSymbol = KeyValuesSystem()->GetSymbolForString(item->secondParamName);
  4276. }
  4277. else
  4278. {
  4279. item->secondParamSymbol = INVALID_KEY_SYMBOL;
  4280. }
  4281. }
  4282. panelMap->processed = true;
  4283. panelMap = panelMap->baseMap;
  4284. }
  4285. }
  4286. //-----------------------------------------------------------------------------
  4287. // Purpose: Handles a message
  4288. // Dispatches the message to a set of message maps
  4289. //-----------------------------------------------------------------------------
  4290. void Panel::OnMessage(const KeyValues *params, VPANEL ifromPanel)
  4291. {
  4292. PanelMessageMap *panelMap = GetMessageMap();
  4293. bool bFound = false;
  4294. int iMessageName = params->GetNameSymbol();
  4295. if ( !panelMap->processed )
  4296. {
  4297. PreparePanelMessageMap( panelMap );
  4298. }
  4299. // iterate through the class hierarchy message maps
  4300. for ( ; panelMap != NULL && !bFound; panelMap = panelMap->baseMap )
  4301. {
  4302. #if defined( _DEBUG )
  4303. // char const *className = panelMap->pfnClassName();
  4304. // NOTE_UNUSED( className );
  4305. #endif
  4306. // iterate all the entries in the panel map
  4307. for ( int i = 0; i < panelMap->entries.Count(); i++ )
  4308. {
  4309. MessageMapItem_t *pMap = &panelMap->entries[i];
  4310. if (iMessageName == pMap->nameSymbol)
  4311. {
  4312. bFound = true;
  4313. switch (pMap->numParams)
  4314. {
  4315. case 0:
  4316. {
  4317. (this->*(pMap->func))();
  4318. break;
  4319. }
  4320. case 1:
  4321. {
  4322. KeyValues *param1 = params->FindKey(pMap->firstParamSymbol);
  4323. if (!param1)
  4324. {
  4325. param1 = const_cast<KeyValues *>(params);
  4326. }
  4327. switch ( pMap->firstParamType )
  4328. {
  4329. case DATATYPE_INT:
  4330. typedef void (Panel::*MessageFunc_Int_t)(int);
  4331. (this->*((MessageFunc_Int_t)pMap->func))( param1->GetInt() );
  4332. break;
  4333. case DATATYPE_UINT64:
  4334. typedef void (Panel::*MessageFunc_Uin64_t)(uint64);
  4335. (this->*((MessageFunc_Uin64_t)pMap->func))( param1->GetUint64() );
  4336. break;
  4337. case DATATYPE_PTR:
  4338. typedef void (Panel::*MessageFunc_Ptr_t)( void * );
  4339. (this->*((MessageFunc_Ptr_t)pMap->func))( param1->GetPtr() );
  4340. break;
  4341. case DATATYPE_HANDLE:
  4342. {
  4343. typedef void (Panel::*MessageFunc_VPANEL_t)( VPANEL );
  4344. VPANEL vpanel = ivgui()->HandleToPanel( param1->GetInt() );
  4345. (this->*((MessageFunc_VPANEL_t)pMap->func))( vpanel );
  4346. }
  4347. break;
  4348. case DATATYPE_FLOAT:
  4349. typedef void (Panel::*MessageFunc_Float_t)( float );
  4350. (this->*((MessageFunc_Float_t)pMap->func))( param1->GetFloat() );
  4351. break;
  4352. case DATATYPE_CONSTCHARPTR:
  4353. typedef void (Panel::*MessageFunc_CharPtr_t)( const char * );
  4354. (this->*((MessageFunc_CharPtr_t)pMap->func))( param1->GetString() );
  4355. break;
  4356. case DATATYPE_CONSTWCHARPTR:
  4357. typedef void (Panel::*MessageFunc_WCharPtr_t)( const wchar_t * );
  4358. (this->*((MessageFunc_WCharPtr_t)pMap->func))( param1->GetWString() );
  4359. break;
  4360. case DATATYPE_KEYVALUES:
  4361. typedef void (Panel::*MessageFunc_KeyValues_t)(KeyValues *);
  4362. if ( pMap->firstParamName )
  4363. {
  4364. (this->*((MessageFunc_KeyValues_t)pMap->func))( (KeyValues *)param1->GetPtr() );
  4365. }
  4366. else
  4367. {
  4368. // no param set, so pass in the whole thing
  4369. (this->*((MessageFunc_KeyValues_t)pMap->func))( const_cast<KeyValues *>(params) );
  4370. }
  4371. break;
  4372. default:
  4373. Assert(!("No handler for vgui message function"));
  4374. break;
  4375. }
  4376. break;
  4377. }
  4378. case 2:
  4379. {
  4380. KeyValues *param1 = params->FindKey(pMap->firstParamSymbol);
  4381. if (!param1)
  4382. {
  4383. param1 = const_cast<KeyValues *>(params);
  4384. }
  4385. KeyValues *param2 = params->FindKey(pMap->secondParamSymbol);
  4386. if (!param2)
  4387. {
  4388. param2 = const_cast<KeyValues *>(params);
  4389. }
  4390. if ( (DATATYPE_INT == pMap->firstParamType) && (DATATYPE_INT == pMap->secondParamType) )
  4391. {
  4392. typedef void (Panel::*MessageFunc_IntInt_t)(int, int);
  4393. (this->*((MessageFunc_IntInt_t)pMap->func))( param1->GetInt(), param2->GetInt() );
  4394. }
  4395. else if ( (DATATYPE_PTR == pMap->firstParamType) && (DATATYPE_INT == pMap->secondParamType) )
  4396. {
  4397. typedef void (Panel::*MessageFunc_PtrInt_t)(void *, int);
  4398. (this->*((MessageFunc_PtrInt_t)pMap->func))( param1->GetPtr(), param2->GetInt() );
  4399. }
  4400. else if ( (DATATYPE_CONSTCHARPTR == pMap->firstParamType) && (DATATYPE_INT == pMap->secondParamType) )
  4401. {
  4402. typedef void (Panel::*MessageFunc_ConstCharPtrInt_t)(const char *, int);
  4403. (this->*((MessageFunc_ConstCharPtrInt_t)pMap->func))( param1->GetString(), param2->GetInt() );
  4404. }
  4405. else if ( (DATATYPE_CONSTCHARPTR == pMap->firstParamType) && (DATATYPE_CONSTCHARPTR == pMap->secondParamType) )
  4406. {
  4407. typedef void (Panel::*MessageFunc_ConstCharPtrConstCharPtr_t)(const char *, const char *);
  4408. (this->*((MessageFunc_ConstCharPtrConstCharPtr_t)pMap->func))( param1->GetString(), param2->GetString() );
  4409. }
  4410. else if ( (DATATYPE_INT == pMap->firstParamType) && (DATATYPE_CONSTCHARPTR == pMap->secondParamType) )
  4411. {
  4412. typedef void (Panel::*MessageFunc_IntConstCharPtr_t)(int, const char *);
  4413. (this->*((MessageFunc_IntConstCharPtr_t)pMap->func))( param1->GetInt(), param2->GetString() );
  4414. }
  4415. else if ( (DATATYPE_PTR == pMap->firstParamType) && (DATATYPE_CONSTCHARPTR == pMap->secondParamType) )
  4416. {
  4417. typedef void (Panel::*MessageFunc_PtrConstCharPtr_t)(void *, const char *);
  4418. (this->*((MessageFunc_PtrConstCharPtr_t)pMap->func))( param1->GetPtr(), param2->GetString() );
  4419. }
  4420. else if ( (DATATYPE_PTR == pMap->firstParamType) && (DATATYPE_CONSTWCHARPTR == pMap->secondParamType) )
  4421. {
  4422. typedef void (Panel::*MessageFunc_PtrConstCharPtr_t)(void *, const wchar_t *);
  4423. (this->*((MessageFunc_PtrConstCharPtr_t)pMap->func))( param1->GetPtr(), param2->GetWString() );
  4424. }
  4425. else if ( (DATATYPE_HANDLE == pMap->firstParamType) && (DATATYPE_CONSTCHARPTR == pMap->secondParamType) )
  4426. {
  4427. typedef void (Panel::*MessageFunc_HandleConstCharPtr_t)(VPANEL, const char *);
  4428. VPANEL vp = ivgui()->HandleToPanel( param1->GetInt() );
  4429. (this->*((MessageFunc_HandleConstCharPtr_t)pMap->func))( vp, param2->GetString() );
  4430. }
  4431. else if ( (DATATYPE_HANDLE == pMap->firstParamType) && (DATATYPE_CONSTWCHARPTR == pMap->secondParamType) )
  4432. {
  4433. typedef void (Panel::*MessageFunc_HandleConstCharPtr_t)(VPANEL, const wchar_t *);
  4434. VPANEL vp = ivgui()->HandleToPanel( param1->GetInt() );
  4435. (this->*((MessageFunc_HandleConstCharPtr_t)pMap->func))( vp, param2->GetWString() );
  4436. }
  4437. else
  4438. {
  4439. // the message isn't handled
  4440. ivgui()->DPrintf( "Message '%s', sent to '%s', has invalid parameter types\n", params->GetName(), GetName() );
  4441. }
  4442. break;
  4443. }
  4444. default:
  4445. Assert(!("Invalid number of parameters"));
  4446. break;
  4447. }
  4448. // break the loop
  4449. bFound = true;
  4450. break;
  4451. }
  4452. }
  4453. }
  4454. if (!bFound)
  4455. {
  4456. OnOldMessage(const_cast<KeyValues *>(params), ifromPanel);
  4457. }
  4458. }
  4459. void Panel::OnOldMessage(KeyValues *params, VPANEL ifromPanel)
  4460. {
  4461. bool bFound = false;
  4462. // message map dispatch
  4463. int iMessageName = params->GetNameSymbol();
  4464. PanelMap_t *panelMap = GetPanelMap();
  4465. if ( !panelMap->processed )
  4466. {
  4467. PreparePanelMap( panelMap );
  4468. }
  4469. // iterate through the class hierarchy message maps
  4470. for ( ; panelMap != NULL && !bFound; panelMap = panelMap->baseMap )
  4471. {
  4472. MessageMapItem_t *pMessageMap = panelMap->dataDesc;
  4473. for ( int i = 0; i < panelMap->dataNumFields; i++ )
  4474. {
  4475. if (iMessageName == pMessageMap[i].nameSymbol)
  4476. {
  4477. // call the mapped function
  4478. switch ( pMessageMap[i].numParams )
  4479. {
  4480. case 2:
  4481. if ( (DATATYPE_INT == pMessageMap[i].firstParamType) && (DATATYPE_INT == pMessageMap[i].secondParamType) )
  4482. {
  4483. typedef void (Panel::*MessageFunc_IntInt_t)(int, int);
  4484. (this->*((MessageFunc_IntInt_t)pMessageMap[i].func))( params->GetInt(pMessageMap[i].firstParamName), params->GetInt(pMessageMap[i].secondParamName) );
  4485. }
  4486. else if ( (DATATYPE_PTR == pMessageMap[i].firstParamType) && (DATATYPE_INT == pMessageMap[i].secondParamType) )
  4487. {
  4488. typedef void (Panel::*MessageFunc_PtrInt_t)(void *, int);
  4489. (this->*((MessageFunc_PtrInt_t)pMessageMap[i].func))( params->GetPtr(pMessageMap[i].firstParamName), params->GetInt(pMessageMap[i].secondParamName) );
  4490. }
  4491. else if ( (DATATYPE_CONSTCHARPTR == pMessageMap[i].firstParamType) && (DATATYPE_INT == pMessageMap[i].secondParamType) )
  4492. {
  4493. typedef void (Panel::*MessageFunc_ConstCharPtrInt_t)(const char *, int);
  4494. (this->*((MessageFunc_ConstCharPtrInt_t)pMessageMap[i].func))( params->GetString(pMessageMap[i].firstParamName), params->GetInt(pMessageMap[i].secondParamName) );
  4495. }
  4496. else if ( (DATATYPE_CONSTCHARPTR == pMessageMap[i].firstParamType) && (DATATYPE_CONSTCHARPTR == pMessageMap[i].secondParamType) )
  4497. {
  4498. typedef void (Panel::*MessageFunc_ConstCharPtrConstCharPtr_t)(const char *, const char *);
  4499. (this->*((MessageFunc_ConstCharPtrConstCharPtr_t)pMessageMap[i].func))( params->GetString(pMessageMap[i].firstParamName), params->GetString(pMessageMap[i].secondParamName) );
  4500. }
  4501. else if ( (DATATYPE_INT == pMessageMap[i].firstParamType) && (DATATYPE_CONSTCHARPTR == pMessageMap[i].secondParamType) )
  4502. {
  4503. typedef void (Panel::*MessageFunc_IntConstCharPtr_t)(int, const char *);
  4504. (this->*((MessageFunc_IntConstCharPtr_t)pMessageMap[i].func))( params->GetInt(pMessageMap[i].firstParamName), params->GetString(pMessageMap[i].secondParamName) );
  4505. }
  4506. else if ( (DATATYPE_PTR == pMessageMap[i].firstParamType) && (DATATYPE_CONSTCHARPTR == pMessageMap[i].secondParamType) )
  4507. {
  4508. typedef void (Panel::*MessageFunc_PtrConstCharPtr_t)(void *, const char *);
  4509. (this->*((MessageFunc_PtrConstCharPtr_t)pMessageMap[i].func))( params->GetPtr(pMessageMap[i].firstParamName), params->GetString(pMessageMap[i].secondParamName) );
  4510. }
  4511. else if ( (DATATYPE_PTR == pMessageMap[i].firstParamType) && (DATATYPE_CONSTWCHARPTR == pMessageMap[i].secondParamType) )
  4512. {
  4513. typedef void (Panel::*MessageFunc_PtrConstCharPtr_t)(void *, const wchar_t *);
  4514. (this->*((MessageFunc_PtrConstCharPtr_t)pMessageMap[i].func))( params->GetPtr(pMessageMap[i].firstParamName), params->GetWString(pMessageMap[i].secondParamName) );
  4515. }
  4516. else if ( (DATATYPE_HANDLE == pMessageMap[i].firstParamType) && (DATATYPE_CONSTCHARPTR ==pMessageMap[i].secondParamType) )
  4517. {
  4518. typedef void (Panel::*MessageFunc_HandleConstCharPtr_t)(VPANEL, const char *);
  4519. VPANEL vp = ivgui()->HandleToPanel( params->GetInt( pMessageMap[i].firstParamName ) );
  4520. (this->*((MessageFunc_HandleConstCharPtr_t)pMessageMap[i].func))( vp, params->GetString(pMessageMap[i].secondParamName) );
  4521. }
  4522. else if ( (DATATYPE_HANDLE == pMessageMap[i].firstParamType) && (DATATYPE_CONSTWCHARPTR == pMessageMap[i].secondParamType) )
  4523. {
  4524. typedef void (Panel::*MessageFunc_HandleConstCharPtr_t)(VPANEL, const wchar_t *);
  4525. VPANEL vp = ivgui()->HandleToPanel( params->GetInt( pMessageMap[i].firstParamName ) );
  4526. (this->*((MessageFunc_HandleConstCharPtr_t)pMessageMap[i].func))( vp, params->GetWString(pMessageMap[i].secondParamName) );
  4527. }
  4528. else
  4529. {
  4530. // the message isn't handled
  4531. ivgui()->DPrintf( "Message '%s', sent to '%s', has invalid parameter types\n", params->GetName(), GetName() );
  4532. }
  4533. break;
  4534. case 1:
  4535. switch ( pMessageMap[i].firstParamType )
  4536. {
  4537. case DATATYPE_BOOL:
  4538. typedef void (Panel::*MessageFunc_Bool_t)(bool);
  4539. (this->*((MessageFunc_Bool_t)pMessageMap[i].func))( (bool)params->GetInt(pMessageMap[i].firstParamName) );
  4540. break;
  4541. case DATATYPE_CONSTCHARPTR:
  4542. typedef void (Panel::*MessageFunc_ConstCharPtr_t)(const char *);
  4543. (this->*((MessageFunc_ConstCharPtr_t)pMessageMap[i].func))( (const char *)params->GetString(pMessageMap[i].firstParamName) );
  4544. break;
  4545. case DATATYPE_CONSTWCHARPTR:
  4546. typedef void (Panel::*MessageFunc_ConstCharPtr_t)(const char *);
  4547. (this->*((MessageFunc_ConstCharPtr_t)pMessageMap[i].func))( (const char *)params->GetWString(pMessageMap[i].firstParamName) );
  4548. break;
  4549. case DATATYPE_INT:
  4550. typedef void (Panel::*MessageFunc_Int_t)(int);
  4551. (this->*((MessageFunc_Int_t)pMessageMap[i].func))( params->GetInt(pMessageMap[i].firstParamName) );
  4552. break;
  4553. case DATATYPE_FLOAT:
  4554. typedef void (Panel::*MessageFunc_Float_t)(float);
  4555. (this->*((MessageFunc_Float_t)pMessageMap[i].func))( params->GetFloat(pMessageMap[i].firstParamName) );
  4556. break;
  4557. case DATATYPE_PTR:
  4558. typedef void (Panel::*MessageFunc_Ptr_t)(void *);
  4559. (this->*((MessageFunc_Ptr_t)pMessageMap[i].func))( (void *)params->GetPtr(pMessageMap[i].firstParamName) );
  4560. break;
  4561. case DATATYPE_HANDLE:
  4562. {
  4563. typedef void (Panel::*MessageFunc_Ptr_t)(void *);
  4564. VPANEL vp = ivgui()->HandleToPanel( params->GetInt( pMessageMap[i].firstParamName ) );
  4565. Panel *panel = ipanel()->GetPanel( vp, GetModuleName() );
  4566. (this->*((MessageFunc_Ptr_t)pMessageMap[i].func))( (void *)panel );
  4567. }
  4568. break;
  4569. case DATATYPE_KEYVALUES:
  4570. typedef void (Panel::*MessageFunc_KeyValues_t)(KeyValues *);
  4571. if ( pMessageMap[i].firstParamName )
  4572. {
  4573. (this->*((MessageFunc_KeyValues_t)pMessageMap[i].func))( (KeyValues *)params->GetPtr(pMessageMap[i].firstParamName) );
  4574. }
  4575. else
  4576. {
  4577. (this->*((MessageFunc_KeyValues_t)pMessageMap[i].func))( params );
  4578. }
  4579. break;
  4580. default:
  4581. // the message isn't handled
  4582. ivgui()->DPrintf( "Message '%s', sent to '%s', has an invalid parameter type\n", params->GetName(), GetName() );
  4583. break;
  4584. }
  4585. break;
  4586. default:
  4587. (this->*(pMessageMap[i].func))();
  4588. break;
  4589. };
  4590. // break the loop
  4591. bFound = true;
  4592. break;
  4593. }
  4594. }
  4595. }
  4596. // message not handled
  4597. // debug code
  4598. if ( !bFound )
  4599. {
  4600. static int s_bDebugMessages = -1;
  4601. if ( s_bDebugMessages == -1 )
  4602. {
  4603. s_bDebugMessages = CommandLine()->FindParm( "-vguimessages" ) ? 1 : 0;
  4604. }
  4605. if ( s_bDebugMessages == 1 )
  4606. {
  4607. ivgui()->DPrintf( "Message '%s' not handled by panel '%s'\n", params->GetName(), GetName() );
  4608. }
  4609. }
  4610. }
  4611. //-----------------------------------------------------------------------------
  4612. // Purpose: Safe call to get info from child panel by name
  4613. //-----------------------------------------------------------------------------
  4614. bool Panel::RequestInfoFromChild(const char *childName, KeyValues *outputData)
  4615. {
  4616. Panel *panel = FindChildByName(childName);
  4617. if (panel)
  4618. {
  4619. return panel->RequestInfo(outputData);
  4620. }
  4621. return false;
  4622. }
  4623. //-----------------------------------------------------------------------------
  4624. // Purpose: Posts a message
  4625. //-----------------------------------------------------------------------------
  4626. void Panel::PostMessage(Panel *target, KeyValues *message, float delay)
  4627. {
  4628. ivgui()->PostMessage(target->GetVPanel(), message, GetVPanel(), delay);
  4629. }
  4630. void Panel::PostMessage(VPANEL target, KeyValues *message, float delaySeconds)
  4631. {
  4632. ivgui()->PostMessage(target, message, GetVPanel(), delaySeconds);
  4633. }
  4634. void Panel::PostMessageToAllSiblings( KeyValues *msg, float delaySeconds /*= 0.0f*/ )
  4635. {
  4636. VPANEL parent = GetVParent();
  4637. if ( parent )
  4638. {
  4639. VPANEL vpanel = GetVPanel();
  4640. CUtlVector< VPANEL > &children = ipanel()->GetChildren( parent );
  4641. int nChildCount = children.Count();
  4642. for ( int i = 0; i < nChildCount; ++i )
  4643. {
  4644. VPANEL sibling = children[ i ];
  4645. if ( sibling == vpanel )
  4646. continue;
  4647. if ( sibling )
  4648. {
  4649. PostMessage( sibling, msg->MakeCopy(), delaySeconds );
  4650. }
  4651. }
  4652. }
  4653. msg->deleteThis();
  4654. }
  4655. //-----------------------------------------------------------------------------
  4656. // Purpose: Safe call to post a message to a child by name
  4657. //-----------------------------------------------------------------------------
  4658. void Panel::PostMessageToChild(const char *childName, KeyValues *message)
  4659. {
  4660. Panel *panel = FindChildByName(childName);
  4661. if (panel)
  4662. {
  4663. ivgui()->PostMessage(panel->GetVPanel(), message, GetVPanel());
  4664. }
  4665. else
  4666. {
  4667. message->deleteThis();
  4668. }
  4669. }
  4670. //-----------------------------------------------------------------------------
  4671. // Purpose: Requests some information from the panel
  4672. // Look through the message map for the handler
  4673. //-----------------------------------------------------------------------------
  4674. bool Panel::RequestInfo( KeyValues *outputData )
  4675. {
  4676. if ( InternalRequestInfo( GetAnimMap(), outputData ) )
  4677. {
  4678. return true;
  4679. }
  4680. if (GetVParent())
  4681. {
  4682. return ipanel()->RequestInfo(GetVParent(), outputData);
  4683. }
  4684. return false;
  4685. }
  4686. //-----------------------------------------------------------------------------
  4687. // Purpose: sets a specified value in the control - inverse of RequestInfo
  4688. //-----------------------------------------------------------------------------
  4689. bool Panel::SetInfo(KeyValues *inputData)
  4690. {
  4691. if ( InternalSetInfo( GetAnimMap(), inputData ) )
  4692. {
  4693. return true;
  4694. }
  4695. // doesn't chain to parent
  4696. return false;
  4697. }
  4698. //-----------------------------------------------------------------------------
  4699. // Purpose: change the panel's silent mode; if silent, the panel will not post
  4700. // any action signals
  4701. //-----------------------------------------------------------------------------
  4702. void Panel::SetSilentMode( bool bSilent )
  4703. {
  4704. m_bIsSilent = bSilent;
  4705. }
  4706. //-----------------------------------------------------------------------------
  4707. // Purpose: mouse events will be send to handler panel instead of this panel
  4708. //-----------------------------------------------------------------------------
  4709. void Panel::InstallMouseHandler( Panel *pHandler )
  4710. {
  4711. m_hMouseEventHandler = pHandler;
  4712. }
  4713. //-----------------------------------------------------------------------------
  4714. // Purpose: Prepares the hierarchy panel maps for use (with message maps etc)
  4715. //-----------------------------------------------------------------------------
  4716. void Panel::PreparePanelMap( PanelMap_t *panelMap )
  4717. {
  4718. // iterate through the class hierarchy message maps
  4719. while ( panelMap != NULL && !panelMap->processed )
  4720. {
  4721. // fixup cross-dll boundary panel maps
  4722. if ( panelMap->baseMap == (PanelMap_t*)0x00000001 )
  4723. {
  4724. panelMap->baseMap = &Panel::m_PanelMap;
  4725. }
  4726. // hash message map strings into symbols
  4727. for (int i = 0; i < panelMap->dataNumFields; i++)
  4728. {
  4729. MessageMapItem_t *item = &panelMap->dataDesc[i];
  4730. if (item->name)
  4731. {
  4732. item->nameSymbol = KeyValuesSystem()->GetSymbolForString(item->name);
  4733. }
  4734. else
  4735. {
  4736. item->nameSymbol = INVALID_KEY_SYMBOL;
  4737. }
  4738. if (item->firstParamName)
  4739. {
  4740. item->firstParamSymbol = KeyValuesSystem()->GetSymbolForString(item->firstParamName);
  4741. }
  4742. else
  4743. {
  4744. item->firstParamSymbol = INVALID_KEY_SYMBOL;
  4745. }
  4746. if (item->secondParamName)
  4747. {
  4748. item->secondParamSymbol = KeyValuesSystem()->GetSymbolForString(item->secondParamName);
  4749. }
  4750. else
  4751. {
  4752. item->secondParamSymbol = INVALID_KEY_SYMBOL;
  4753. }
  4754. }
  4755. panelMap->processed = true;
  4756. panelMap = panelMap->baseMap;
  4757. }
  4758. }
  4759. //-----------------------------------------------------------------------------
  4760. // Purpose: Called to delete the panel
  4761. //-----------------------------------------------------------------------------
  4762. void Panel::OnDelete()
  4763. {
  4764. #ifdef WIN32
  4765. Assert( IsX360() || ( IsPC() && _heapchk() == _HEAPOK ) );
  4766. #endif
  4767. delete this;
  4768. #ifdef WIN32
  4769. Assert( IsX360() || ( IsPC() && _heapchk() == _HEAPOK ) );
  4770. #endif
  4771. }
  4772. //-----------------------------------------------------------------------------
  4773. // Purpose: Panel handle implementation
  4774. // Returns a pointer to a valid panel, NULL if the panel has been deleted
  4775. //-----------------------------------------------------------------------------
  4776. Panel *PHandle::Get()
  4777. {
  4778. if (m_iPanelID != INVALID_PANEL)
  4779. {
  4780. VPANEL panel = ivgui()->HandleToPanel(m_iPanelID);
  4781. if (panel)
  4782. {
  4783. Panel *vguiPanel = ipanel()->GetPanel(panel, GetControlsModuleName());
  4784. return vguiPanel;
  4785. }
  4786. }
  4787. return NULL;
  4788. }
  4789. //-----------------------------------------------------------------------------
  4790. // Purpose: sets the smart pointer
  4791. //-----------------------------------------------------------------------------
  4792. Panel *PHandle::Set(Panel *pent)
  4793. {
  4794. if (pent)
  4795. {
  4796. m_iPanelID = ivgui()->PanelToHandle(pent->GetVPanel());
  4797. }
  4798. else
  4799. {
  4800. m_iPanelID = INVALID_PANEL;
  4801. }
  4802. return pent;
  4803. }
  4804. Panel *PHandle::Set( HPanel hPanel )
  4805. {
  4806. m_iPanelID = hPanel;
  4807. return Get();
  4808. }
  4809. //-----------------------------------------------------------------------------
  4810. // Purpose: Returns a handle to a valid panel, NULL if the panel has been deleted
  4811. //-----------------------------------------------------------------------------
  4812. VPANEL VPanelHandle::Get()
  4813. {
  4814. if (m_iPanelID != INVALID_PANEL)
  4815. {
  4816. if (ivgui())
  4817. {
  4818. return ivgui()->HandleToPanel(m_iPanelID);
  4819. }
  4820. }
  4821. return NULL;
  4822. }
  4823. //-----------------------------------------------------------------------------
  4824. // Purpose: sets the smart pointer
  4825. //-----------------------------------------------------------------------------
  4826. VPANEL VPanelHandle::Set(VPANEL pent)
  4827. {
  4828. if (pent)
  4829. {
  4830. m_iPanelID = ivgui()->PanelToHandle(pent);
  4831. }
  4832. else
  4833. {
  4834. m_iPanelID = INVALID_PANEL;
  4835. }
  4836. return pent;
  4837. }
  4838. //-----------------------------------------------------------------------------
  4839. // Purpose: returns a pointer to the tooltip object associated with the panel
  4840. //-----------------------------------------------------------------------------
  4841. BaseTooltip *Panel::GetTooltip()
  4842. {
  4843. if (!m_pTooltips)
  4844. {
  4845. m_pTooltips = new TextTooltip(this, NULL);
  4846. m_bToolTipOverridden = false;
  4847. if ( IsConsoleStylePanel() )
  4848. {
  4849. m_pTooltips->SetEnabled( false );
  4850. }
  4851. }
  4852. return m_pTooltips;
  4853. }
  4854. //-----------------------------------------------------------------------------
  4855. // Purpose:
  4856. //-----------------------------------------------------------------------------
  4857. void Panel::SetTooltip( BaseTooltip *pToolTip, const char *pszText )
  4858. {
  4859. if ( !m_bToolTipOverridden )
  4860. {
  4861. // Remove the one we made, we're being overridden.
  4862. delete m_pTooltips;
  4863. }
  4864. m_pTooltips = pToolTip;
  4865. m_bToolTipOverridden = true;
  4866. if ( _tooltipText )
  4867. {
  4868. delete [] _tooltipText;
  4869. _tooltipText = NULL;
  4870. }
  4871. if ( pszText )
  4872. {
  4873. int len = Q_strlen(pszText) + 1;
  4874. _tooltipText = new char[ len ];
  4875. Q_strncpy( _tooltipText, pszText, len );
  4876. }
  4877. }
  4878. //-----------------------------------------------------------------------------
  4879. const char *Panel::GetEffectiveTooltipText() const
  4880. {
  4881. if ( _tooltipText )
  4882. {
  4883. return _tooltipText;
  4884. }
  4885. if ( m_pTooltips )
  4886. {
  4887. const char *result = m_pTooltips->GetText();
  4888. if ( result )
  4889. {
  4890. return result;
  4891. }
  4892. }
  4893. return "";
  4894. }
  4895. //-----------------------------------------------------------------------------
  4896. // Purpose: sets the proportional flag on this panel and all it's children
  4897. //-----------------------------------------------------------------------------
  4898. void Panel::SetProportional(bool state)
  4899. {
  4900. // only do something if the state changes
  4901. if( state != _flags.IsFlagSet( IS_PROPORTIONAL ) )
  4902. {
  4903. _flags.SetFlag( IS_PROPORTIONAL, state );
  4904. for(int i=0;i<GetChildCount();i++)
  4905. {
  4906. // recursively apply to all children
  4907. GetChild(i)->SetProportional( IsProportional() );
  4908. }
  4909. }
  4910. InvalidateLayout();
  4911. }
  4912. void Panel::SetKeyBoardInputEnabled( bool state )
  4913. {
  4914. ipanel()->SetKeyBoardInputEnabled( GetVPanel(), state );
  4915. for ( int i = 0; i < GetChildCount(); i++ )
  4916. {
  4917. Panel *child = GetChild( i );
  4918. if ( !child )
  4919. {
  4920. continue;
  4921. }
  4922. child->SetKeyBoardInputEnabled( state );
  4923. }
  4924. // If turning off keyboard input enable, then make sure
  4925. // this panel is not the current key focus of a parent panel
  4926. if ( !state )
  4927. {
  4928. Panel *pParent = GetParent();
  4929. if ( pParent )
  4930. {
  4931. if ( pParent->GetCurrentKeyFocus() == GetVPanel() )
  4932. {
  4933. pParent->RequestFocusNext();
  4934. }
  4935. }
  4936. }
  4937. }
  4938. void Panel::SetMouseInputEnabled( bool state )
  4939. {
  4940. ipanel()->SetMouseInputEnabled( GetVPanel(), state );
  4941. /* for(int i=0;i<GetChildCount();i++)
  4942. {
  4943. GetChild(i)->SetMouseInput(state);
  4944. }*/
  4945. vgui::surface()->CalculateMouseVisible();
  4946. }
  4947. bool Panel::IsKeyBoardInputEnabled()
  4948. {
  4949. return ipanel()->IsKeyBoardInputEnabled( GetVPanel() );
  4950. }
  4951. bool Panel::IsMouseInputEnabled()
  4952. {
  4953. return ipanel()->IsMouseInputEnabled( GetVPanel() );
  4954. }
  4955. class CFloatProperty : public vgui::IPanelAnimationPropertyConverter
  4956. {
  4957. public:
  4958. virtual void GetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry )
  4959. {
  4960. void *data = ( void * )( (*entry->m_pfnLookup)( panel ) );
  4961. kv->SetFloat( entry->name(), *(float *)data );
  4962. }
  4963. virtual void SetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry )
  4964. {
  4965. void *data = ( void * )( (*entry->m_pfnLookup)( panel ) );
  4966. *(float *)data = kv->GetFloat( entry->name() );
  4967. }
  4968. virtual void InitFromDefault( Panel *panel, PanelAnimationMapEntry *entry )
  4969. {
  4970. void *data = ( void * )( (*entry->m_pfnLookup)( panel ) );
  4971. *(float *)data = atof( entry->defaultvalue() );
  4972. }
  4973. };
  4974. class CProportionalFloatProperty : public vgui::IPanelAnimationPropertyConverter
  4975. {
  4976. public:
  4977. virtual void GetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry )
  4978. {
  4979. void *data = ( void * )( (*entry->m_pfnLookup)( panel ) );
  4980. float f = *(float *)data;
  4981. f = scheme()->GetProportionalNormalizedValueEx( panel->GetScheme(), f );
  4982. kv->SetFloat( entry->name(), f );
  4983. }
  4984. virtual void SetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry )
  4985. {
  4986. void *data = ( void * )( (*entry->m_pfnLookup)( panel ) );
  4987. float f = kv->GetFloat( entry->name() );
  4988. f = scheme()->GetProportionalScaledValueEx( panel->GetScheme(), f );
  4989. *(float *)data = f;
  4990. }
  4991. virtual void InitFromDefault( Panel *panel, PanelAnimationMapEntry *entry )
  4992. {
  4993. void *data = ( void * )( (*entry->m_pfnLookup)( panel ) );
  4994. float f = atof( entry->defaultvalue() );
  4995. f = scheme()->GetProportionalScaledValueEx( panel->GetScheme(), f );
  4996. *(float *)data = f;
  4997. }
  4998. };
  4999. class CIntProperty : public vgui::IPanelAnimationPropertyConverter
  5000. {
  5001. public:
  5002. virtual void GetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry )
  5003. {
  5004. void *data = ( void * )( (*entry->m_pfnLookup)( panel ) );
  5005. kv->SetInt( entry->name(), *(int *)data );
  5006. }
  5007. virtual void SetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry )
  5008. {
  5009. void *data = ( void * )( (*entry->m_pfnLookup)( panel ) );
  5010. *(int *)data = kv->GetInt( entry->name() );
  5011. }
  5012. virtual void InitFromDefault( Panel *panel, PanelAnimationMapEntry *entry )
  5013. {
  5014. void *data = ( void * )( (*entry->m_pfnLookup)( panel ) );
  5015. *(int *)data = atoi( entry->defaultvalue() );
  5016. }
  5017. };
  5018. class CProportionalIntProperty : public vgui::IPanelAnimationPropertyConverter
  5019. {
  5020. public:
  5021. virtual void GetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry )
  5022. {
  5023. void *data = ( void * )( (*entry->m_pfnLookup)( panel ) );
  5024. int i = *(int *)data;
  5025. i = scheme()->GetProportionalNormalizedValueEx( panel->GetScheme(), i );
  5026. kv->SetInt( entry->name(), i );
  5027. }
  5028. virtual void SetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry )
  5029. {
  5030. void *data = ( void * )( (*entry->m_pfnLookup)( panel ) );
  5031. int i = kv->GetInt( entry->name() );
  5032. i = scheme()->GetProportionalScaledValueEx( panel->GetScheme(), i );
  5033. *(int *)data = i;
  5034. }
  5035. virtual void InitFromDefault( Panel *panel, PanelAnimationMapEntry *entry )
  5036. {
  5037. void *data = ( void * )( (*entry->m_pfnLookup)( panel ) );
  5038. int i = atoi( entry->defaultvalue() );
  5039. i = scheme()->GetProportionalScaledValueEx( panel->GetScheme(), i );
  5040. *(int *)data = i;
  5041. }
  5042. };
  5043. class CProportionalIntWithScreenspacePropertyX : public vgui::IPanelAnimationPropertyConverter
  5044. {
  5045. public:
  5046. int ExtractValue( Panel *pPanel, const char *pszKey )
  5047. {
  5048. int nPos = 0;
  5049. ComputePos( pPanel, pszKey, nPos, GetPanelDimension( pPanel ), GetScreenSize( pPanel ), true, OP_ADD );
  5050. return nPos;
  5051. }
  5052. virtual int GetScreenSize( Panel *pPanel ) const
  5053. {
  5054. int nParentWide, nParentTall;
  5055. if (pPanel->IsProportional() && pPanel->GetParent())
  5056. {
  5057. nParentWide = pPanel->GetParent()->GetWide();
  5058. nParentTall = pPanel->GetParent()->GetTall();
  5059. }
  5060. else
  5061. {
  5062. surface()->GetScreenSize(nParentWide, nParentTall);
  5063. }
  5064. return nParentWide;
  5065. }
  5066. virtual int GetPanelDimension( Panel *pPanel ) const
  5067. {
  5068. return pPanel->GetWide();
  5069. }
  5070. virtual void GetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry )
  5071. {
  5072. // Won't work with this, don't use it.
  5073. Assert(0);
  5074. }
  5075. virtual void SetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry )
  5076. {
  5077. void *data = ( void * )( (*entry->m_pfnLookup)( panel ) );
  5078. *(int *)data = ExtractValue( panel, kv->GetString( entry->name() ) );
  5079. }
  5080. virtual void InitFromDefault( Panel *panel, PanelAnimationMapEntry *entry )
  5081. {
  5082. void *data = ( void * )( (*entry->m_pfnLookup)( panel ) );
  5083. *(int *)data = ExtractValue( panel, entry->defaultvalue() );
  5084. }
  5085. };
  5086. class CProportionalIntWithScreenspacePropertyY : public CProportionalIntWithScreenspacePropertyX
  5087. {
  5088. public:
  5089. virtual int GetScreenSize( Panel *pPanel ) const OVERRIDE
  5090. {
  5091. int nParentWide, nParentTall;
  5092. if (pPanel->IsProportional() && pPanel->GetParent())
  5093. {
  5094. nParentWide = pPanel->GetParent()->GetWide();
  5095. nParentTall = pPanel->GetParent()->GetTall();
  5096. }
  5097. else
  5098. {
  5099. surface()->GetScreenSize(nParentWide, nParentTall);
  5100. }
  5101. return nParentTall;
  5102. }
  5103. virtual int GetPanelDimension(Panel *pPanel) const OVERRIDE
  5104. {
  5105. return pPanel->GetTall();
  5106. }
  5107. };
  5108. class CProportionalWidthProperty : public vgui::IPanelAnimationPropertyConverter
  5109. {
  5110. public:
  5111. int ExtractValue(Panel *pPanel, const char *pszKey)
  5112. {
  5113. if ( pszKey && ( pszKey[0] == 'o' || pszKey[0] == 'O' ) )
  5114. {
  5115. // We don't handle sizes based on the other dimension in this case
  5116. Assert( 0 );
  5117. return 0;
  5118. }
  5119. int nParentWide, nParentTall;
  5120. if ( pPanel->IsProportional() && pPanel->GetParent() )
  5121. {
  5122. nParentWide = pPanel->GetParent()->GetWide();
  5123. nParentTall = pPanel->GetParent()->GetTall();
  5124. }
  5125. else
  5126. {
  5127. surface()->GetScreenSize( nParentWide, nParentTall );
  5128. }
  5129. unsigned int nBuildFlags = 0;
  5130. return Compute( pPanel, nBuildFlags, pszKey, nParentWide, nParentTall, false );
  5131. }
  5132. virtual void GetData(Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry)
  5133. {
  5134. // Won't work with this, don't use it.
  5135. Assert(0);
  5136. }
  5137. virtual void SetData(Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry)
  5138. {
  5139. void *data = (void *)((*entry->m_pfnLookup)(panel));
  5140. *(int *)data = ExtractValue(panel, kv->GetString(entry->name()));
  5141. }
  5142. virtual void InitFromDefault(Panel *panel, PanelAnimationMapEntry *entry)
  5143. {
  5144. void *data = (void *)((*entry->m_pfnLookup)(panel));
  5145. *(int *)data = ExtractValue(panel, entry->defaultvalue());
  5146. }
  5147. private:
  5148. virtual int Compute( Panel* pPanel, unsigned int& nBuildFlags, const char *pszKey, int nParentWide, int nParentTall, bool bComputingOther )
  5149. {
  5150. KeyValuesAD kv( "temp" );
  5151. kv->SetString( "wide", pszKey );
  5152. return ComputeWide( pPanel, nBuildFlags, kv, nParentWide, nParentTall, false );
  5153. }
  5154. };
  5155. class CProportionalHeightProperty : public CProportionalWidthProperty
  5156. {
  5157. private:
  5158. virtual int Compute(Panel* pPanel, unsigned int& nBuildFlags, const char *pszKey, int nParentWide, int nParentTall, bool bComputingOther) OVERRIDE
  5159. {
  5160. KeyValuesAD kv( "temp" );
  5161. kv->SetString( "tall", pszKey );
  5162. return ComputeTall(pPanel, nBuildFlags, kv, nParentWide, nParentTall, false);
  5163. }
  5164. };
  5165. class CColorProperty : public vgui::IPanelAnimationPropertyConverter
  5166. {
  5167. public:
  5168. virtual void GetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry )
  5169. {
  5170. void *data = ( void * )( (*entry->m_pfnLookup)( panel ) );
  5171. kv->SetColor( entry->name(), *(Color *)data );
  5172. }
  5173. virtual void SetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry )
  5174. {
  5175. vgui::IScheme *scheme = vgui::scheme()->GetIScheme( panel->GetScheme() );
  5176. Assert( scheme );
  5177. if ( scheme )
  5178. {
  5179. void *data = ( void * )( (*entry->m_pfnLookup)( panel ) );
  5180. char const *colorName = kv->GetString( entry->name() );
  5181. if ( !colorName || !colorName[0] )
  5182. {
  5183. *(Color *)data = kv->GetColor( entry->name() );
  5184. }
  5185. else
  5186. {
  5187. *(Color *)data = scheme->GetColor( colorName, Color( 0, 0, 0, 0 ) );
  5188. }
  5189. }
  5190. }
  5191. virtual void InitFromDefault( Panel *panel, PanelAnimationMapEntry *entry )
  5192. {
  5193. vgui::IScheme *scheme = vgui::scheme()->GetIScheme( panel->GetScheme() );
  5194. Assert( scheme );
  5195. if ( scheme )
  5196. {
  5197. void *data = ( void * )( (*entry->m_pfnLookup)( panel ) );
  5198. *(Color *)data = scheme->GetColor( entry->defaultvalue(), Color( 0, 0, 0, 0 ) );
  5199. }
  5200. }
  5201. };
  5202. class CBoolProperty : public vgui::IPanelAnimationPropertyConverter
  5203. {
  5204. public:
  5205. virtual void GetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry )
  5206. {
  5207. void *data = ( void * )( (*entry->m_pfnLookup)( panel ) );
  5208. kv->SetInt( entry->name(), *(bool *)data ? 1 : 0 );
  5209. }
  5210. virtual void SetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry )
  5211. {
  5212. void *data = ( void * )( (*entry->m_pfnLookup)( panel ) );
  5213. *(bool *)data = kv->GetInt( entry->name() ) ? true : false;
  5214. }
  5215. virtual void InitFromDefault( Panel *panel, PanelAnimationMapEntry *entry )
  5216. {
  5217. void *data = ( void * )( (*entry->m_pfnLookup)( panel ) );
  5218. bool b = false;
  5219. if ( !stricmp( entry->defaultvalue(), "true" )||
  5220. atoi( entry->defaultvalue() )!= 0 )
  5221. {
  5222. b = true;
  5223. }
  5224. *(bool *)data = b;
  5225. }
  5226. };
  5227. class CStringProperty : public vgui::IPanelAnimationPropertyConverter
  5228. {
  5229. public:
  5230. virtual void GetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry )
  5231. {
  5232. void *data = ( void * )( (*entry->m_pfnLookup)( panel ) );
  5233. kv->SetString( entry->name(), (char *)data );
  5234. }
  5235. virtual void SetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry )
  5236. {
  5237. void *data = ( void * )( (*entry->m_pfnLookup)( panel ) );
  5238. strcpy( (char *)data, kv->GetString( entry->name() ) );
  5239. }
  5240. virtual void InitFromDefault( Panel *panel, PanelAnimationMapEntry *entry )
  5241. {
  5242. void *data = ( void * )( (*entry->m_pfnLookup)( panel ) );
  5243. strcpy( ( char * )data, entry->defaultvalue() );
  5244. }
  5245. };
  5246. class CHFontProperty : public vgui::IPanelAnimationPropertyConverter
  5247. {
  5248. public:
  5249. virtual void GetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry )
  5250. {
  5251. vgui::IScheme *scheme = vgui::scheme()->GetIScheme( panel->GetScheme() );
  5252. Assert( scheme );
  5253. if ( scheme )
  5254. {
  5255. void *data = ( void * )( (*entry->m_pfnLookup)( panel ) );
  5256. char const *fontName = scheme->GetFontName( *(HFont *)data );
  5257. kv->SetString( entry->name(), fontName );
  5258. }
  5259. }
  5260. virtual void SetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry )
  5261. {
  5262. vgui::IScheme *scheme = vgui::scheme()->GetIScheme( panel->GetScheme() );
  5263. Assert( scheme );
  5264. if ( scheme )
  5265. {
  5266. void *data = ( void * )( (*entry->m_pfnLookup)( panel ) );
  5267. char const *fontName = kv->GetString( entry->name() );
  5268. *(HFont *)data = scheme->GetFont( fontName, panel->IsProportional() );
  5269. }
  5270. }
  5271. virtual void InitFromDefault( Panel *panel, PanelAnimationMapEntry *entry )
  5272. {
  5273. vgui::IScheme *scheme = vgui::scheme()->GetIScheme( panel->GetScheme() );
  5274. Assert( scheme );
  5275. if ( scheme )
  5276. {
  5277. void *data = ( void * )( (*entry->m_pfnLookup)( panel ) );
  5278. *(HFont *)data = scheme->GetFont( entry->defaultvalue(), panel->IsProportional() );
  5279. }
  5280. }
  5281. };
  5282. class CTextureIdProperty : public vgui::IPanelAnimationPropertyConverter
  5283. {
  5284. public:
  5285. virtual void GetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry )
  5286. {
  5287. void *data = ( void * )( (*entry->m_pfnLookup)( panel ) );
  5288. int currentId = *(int *)data;
  5289. // lookup texture name for id
  5290. char texturename[ 512 ];
  5291. if ( currentId != -1 &&
  5292. surface()->DrawGetTextureFile( currentId, texturename, sizeof( texturename ) ) )
  5293. {
  5294. kv->SetString( entry->name(), texturename );
  5295. }
  5296. else
  5297. {
  5298. kv->SetString( entry->name(), "" );
  5299. }
  5300. }
  5301. virtual void SetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry )
  5302. {
  5303. void *data = ( void * )( (*entry->m_pfnLookup)( panel ) );
  5304. int currentId = -1;
  5305. char const *texturename = kv->GetString( entry->name() );
  5306. if ( texturename && texturename[ 0 ] )
  5307. {
  5308. currentId = surface()->DrawGetTextureId( texturename );
  5309. if ( currentId == -1 )
  5310. {
  5311. currentId = surface()->CreateNewTextureID();
  5312. }
  5313. surface()->DrawSetTextureFile( currentId, texturename, false, true );
  5314. }
  5315. *(int *)data = currentId;
  5316. }
  5317. virtual void InitFromDefault( Panel *panel, PanelAnimationMapEntry *entry )
  5318. {
  5319. void *data = ( void * )( (*entry->m_pfnLookup)( panel ) );
  5320. int currentId = -1;
  5321. char const *texturename = entry->defaultvalue();
  5322. if ( texturename && texturename[ 0 ] )
  5323. {
  5324. currentId = surface()->DrawGetTextureId( texturename );
  5325. if ( currentId == -1 )
  5326. {
  5327. currentId = surface()->CreateNewTextureID();
  5328. }
  5329. surface()->DrawSetTextureFile( currentId, texturename, false, true );
  5330. }
  5331. *(int *)data = currentId;
  5332. }
  5333. };
  5334. static CFloatProperty floatconverter;
  5335. static CProportionalFloatProperty p_floatconverter;
  5336. static CIntProperty intconverter;
  5337. static CProportionalIntProperty p_intconverter;
  5338. static CProportionalIntWithScreenspacePropertyX p_screenspace_intconverter_X;
  5339. static CProportionalIntWithScreenspacePropertyY p_screenspace_intconverter_Y;
  5340. static CColorProperty colorconverter;
  5341. static CBoolProperty boolconverter;
  5342. static CStringProperty stringconverter;
  5343. static CHFontProperty fontconverter;
  5344. static CTextureIdProperty textureidconverter;
  5345. static CProportionalWidthProperty proportional_width_converter;
  5346. static CProportionalHeightProperty proportional_height_converter;
  5347. //static CProportionalXPosProperty xposconverter;
  5348. //static CProportionalYPosProperty yposconverter;
  5349. static CUtlDict< IPanelAnimationPropertyConverter *, int > g_AnimationPropertyConverters;
  5350. static IPanelAnimationPropertyConverter *FindConverter( char const *typeName )
  5351. {
  5352. int lookup = g_AnimationPropertyConverters.Find( typeName );
  5353. if ( lookup == g_AnimationPropertyConverters.InvalidIndex() )
  5354. return NULL;
  5355. IPanelAnimationPropertyConverter *converter = g_AnimationPropertyConverters[ lookup ];
  5356. return converter;
  5357. }
  5358. void Panel::AddPropertyConverter( char const *typeName, IPanelAnimationPropertyConverter *converter )
  5359. {
  5360. int lookup = g_AnimationPropertyConverters.Find( typeName );
  5361. if ( lookup != g_AnimationPropertyConverters.InvalidIndex() )
  5362. {
  5363. Msg( "Already have converter for type %s, ignoring...\n", typeName );
  5364. return;
  5365. }
  5366. g_AnimationPropertyConverters.Insert( typeName, converter );
  5367. }
  5368. //-----------------------------------------------------------------------------
  5369. // Purpose: Static method to initialize all needed converters
  5370. //-----------------------------------------------------------------------------
  5371. void Panel::InitPropertyConverters( void )
  5372. {
  5373. static bool initialized = false;
  5374. if ( initialized )
  5375. return;
  5376. initialized = true;
  5377. AddPropertyConverter( "float", &floatconverter );
  5378. AddPropertyConverter( "int", &intconverter );
  5379. AddPropertyConverter( "Color", &colorconverter );
  5380. //AddPropertyConverter( "vgui::Color", &colorconverter );
  5381. AddPropertyConverter( "bool", &boolconverter );
  5382. AddPropertyConverter( "char", &stringconverter );
  5383. AddPropertyConverter( "string", &stringconverter );
  5384. AddPropertyConverter( "HFont", &fontconverter );
  5385. AddPropertyConverter( "vgui::HFont", &fontconverter );
  5386. // This is an aliased type for proportional float
  5387. AddPropertyConverter( "proportional_float", &p_floatconverter );
  5388. AddPropertyConverter( "proportional_int", &p_intconverter );
  5389. AddPropertyConverter( "proportional_xpos", &p_screenspace_intconverter_X );
  5390. AddPropertyConverter( "proportional_ypos", &p_screenspace_intconverter_Y );
  5391. AddPropertyConverter( "proportional_width", &proportional_width_converter );
  5392. AddPropertyConverter( "proportional_height", &proportional_height_converter );
  5393. AddPropertyConverter( "textureid", &textureidconverter );
  5394. }
  5395. bool Panel::InternalRequestInfo( PanelAnimationMap *map, KeyValues *outputData )
  5396. {
  5397. if ( !map )
  5398. return false;
  5399. Assert( outputData );
  5400. char const *name = outputData->GetName();
  5401. PanelAnimationMapEntry *e = FindPanelAnimationEntry( name, map );
  5402. if ( e )
  5403. {
  5404. IPanelAnimationPropertyConverter *converter = FindConverter( e->type() );
  5405. if ( converter )
  5406. {
  5407. converter->GetData( this, outputData, e );
  5408. return true;
  5409. }
  5410. }
  5411. return false;
  5412. }
  5413. bool Panel::InternalSetInfo( PanelAnimationMap *map, KeyValues *inputData )
  5414. {
  5415. if ( !map )
  5416. return false;
  5417. Assert( inputData );
  5418. char const *name = inputData->GetName();
  5419. PanelAnimationMapEntry *e = FindPanelAnimationEntry( name, map );
  5420. if ( e )
  5421. {
  5422. IPanelAnimationPropertyConverter *converter = FindConverter( e->type() );
  5423. if ( converter )
  5424. {
  5425. converter->SetData( this, inputData, e );
  5426. return true;
  5427. }
  5428. }
  5429. return false;
  5430. }
  5431. PanelAnimationMapEntry *Panel::FindPanelAnimationEntry( char const *scriptname, PanelAnimationMap *map )
  5432. {
  5433. if ( !map )
  5434. return NULL;
  5435. Assert( scriptname );
  5436. // Look through mapping for entry
  5437. int c = map->entries.Count();
  5438. for ( int i = 0; i < c; i++ )
  5439. {
  5440. PanelAnimationMapEntry *e = &map->entries[ i ];
  5441. if ( !stricmp( e->name(), scriptname ) )
  5442. {
  5443. return e;
  5444. }
  5445. }
  5446. // Recurse
  5447. if ( map->baseMap )
  5448. {
  5449. return FindPanelAnimationEntry( scriptname, map->baseMap );
  5450. }
  5451. return NULL;
  5452. }
  5453. // Recursively invoke settings for PanelAnimationVars
  5454. void Panel::InternalApplySettings( PanelAnimationMap *map, KeyValues *inResourceData)
  5455. {
  5456. tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "%s - %s", __FUNCTION__, GetName() );
  5457. // Loop through keys
  5458. KeyValues *kv;
  5459. for ( kv = inResourceData->GetFirstSubKey(); kv; kv = kv->GetNextKey() )
  5460. {
  5461. char const *varname = kv->GetName();
  5462. PanelAnimationMapEntry *entry = FindPanelAnimationEntry( varname, GetAnimMap() );
  5463. if ( entry )
  5464. {
  5465. // Set value to value from script
  5466. IPanelAnimationPropertyConverter *converter = FindConverter( entry->type() );
  5467. if ( converter )
  5468. {
  5469. converter->SetData( this, inResourceData, entry );
  5470. }
  5471. }
  5472. }
  5473. }
  5474. //-----------------------------------------------------------------------------
  5475. // Purpose: sets the default values of all CPanelAnimationVars
  5476. //-----------------------------------------------------------------------------
  5477. void Panel::InternalInitDefaultValues( PanelAnimationMap *map )
  5478. {
  5479. _flags.ClearFlag( NEEDS_DEFAULT_SETTINGS_APPLIED );
  5480. // Look through mapping for entry
  5481. int c = map->entries.Count();
  5482. for ( int i = 0; i < c; i++ )
  5483. {
  5484. PanelAnimationMapEntry *e = &map->entries[ i ];
  5485. Assert( e );
  5486. IPanelAnimationPropertyConverter *converter = FindConverter( e->type() );
  5487. if ( !converter )
  5488. continue;
  5489. converter->InitFromDefault( this, e );
  5490. }
  5491. if ( map->baseMap )
  5492. {
  5493. InternalInitDefaultValues( map->baseMap );
  5494. }
  5495. }
  5496. //-----------------------------------------------------------------------------
  5497. // Purpose:
  5498. // Input : -
  5499. //-----------------------------------------------------------------------------
  5500. int Panel::GetPaintBackgroundType()
  5501. {
  5502. return m_nPaintBackgroundType;
  5503. }
  5504. //-----------------------------------------------------------------------------
  5505. // Purpose:
  5506. // Input : w -
  5507. // h -
  5508. //-----------------------------------------------------------------------------
  5509. void Panel::GetCornerTextureSize( int& w, int& h )
  5510. {
  5511. if ( m_nBgTextureId1 == -1 )
  5512. {
  5513. w = h = 0;
  5514. return;
  5515. }
  5516. surface()->DrawGetTextureSize(m_nBgTextureId1, w, h);
  5517. }
  5518. //-----------------------------------------------------------------------------
  5519. // Purpose: draws a selection box
  5520. //-----------------------------------------------------------------------------
  5521. void Panel::DrawBox(int x, int y, int wide, int tall, Color color, float normalizedAlpha, bool hollow /*=false*/ )
  5522. {
  5523. if ( m_nBgTextureId1 == -1 ||
  5524. m_nBgTextureId2 == -1 ||
  5525. m_nBgTextureId3 == -1 ||
  5526. m_nBgTextureId4 == -1 )
  5527. {
  5528. return;
  5529. }
  5530. color[3] *= normalizedAlpha;
  5531. // work out our bounds
  5532. int cornerWide, cornerTall;
  5533. GetCornerTextureSize( cornerWide, cornerTall );
  5534. // draw the background in the areas not occupied by the corners
  5535. // draw it in three horizontal strips
  5536. surface()->DrawSetColor(color);
  5537. surface()->DrawFilledRect(x + cornerWide, y, x + wide - cornerWide, y + cornerTall);
  5538. if ( !hollow )
  5539. {
  5540. surface()->DrawFilledRect(x, y + cornerTall, x + wide, y + tall - cornerTall);
  5541. }
  5542. else
  5543. {
  5544. surface()->DrawFilledRect(x, y + cornerTall, x + cornerWide, y + tall - cornerTall);
  5545. surface()->DrawFilledRect(x + wide - cornerWide, y + cornerTall, x + wide, y + tall - cornerTall);
  5546. }
  5547. surface()->DrawFilledRect(x + cornerWide, y + tall - cornerTall, x + wide - cornerWide, y + tall);
  5548. // draw the corners
  5549. //=============================================================================
  5550. // HPE_BEGIN:
  5551. // [tj] We now check each individual corner and decide whether to draw it straight or rounded
  5552. //=============================================================================
  5553. //TOP-LEFT
  5554. if (ShouldDrawTopLeftCornerRounded())
  5555. {
  5556. surface()->DrawSetTexture(m_nBgTextureId1);
  5557. surface()->DrawTexturedRect(x, y, x + cornerWide, y + cornerTall);
  5558. }
  5559. else
  5560. {
  5561. surface()->DrawFilledRect(x, y, x + cornerWide, y + cornerTall);
  5562. }
  5563. //TOP-RIGHT
  5564. if (ShouldDrawTopRightCornerRounded())
  5565. {
  5566. surface()->DrawSetTexture(m_nBgTextureId2);
  5567. surface()->DrawTexturedRect(x + wide - cornerWide, y, x + wide, y + cornerTall);
  5568. }
  5569. else
  5570. {
  5571. surface()->DrawFilledRect(x + wide - cornerWide, y, x + wide, y + cornerTall);
  5572. }
  5573. //BOTTOM-LEFT
  5574. if (ShouldDrawBottomLeftCornerRounded())
  5575. {
  5576. surface()->DrawSetTexture(m_nBgTextureId4);
  5577. surface()->DrawTexturedRect(x + 0, y + tall - cornerTall, x + cornerWide, y + tall);
  5578. }
  5579. else
  5580. {
  5581. surface()->DrawFilledRect(x + 0, y + tall - cornerTall, x + cornerWide, y + tall);
  5582. }
  5583. //BOTTOM-RIGHT
  5584. if (ShouldDrawBottomRightCornerRounded())
  5585. {
  5586. surface()->DrawSetTexture(m_nBgTextureId3);
  5587. surface()->DrawTexturedRect(x + wide - cornerWide, y + tall - cornerTall, x + wide, y + tall);
  5588. }
  5589. else
  5590. {
  5591. surface()->DrawFilledRect(x + wide - cornerWide, y + tall - cornerTall, x + wide, y + tall);
  5592. }
  5593. //=============================================================================
  5594. // HPE_END
  5595. //=============================================================================
  5596. }
  5597. void Panel::DrawBoxFade(int x, int y, int wide, int tall, Color color, float normalizedAlpha, unsigned int alpha0, unsigned int alpha1, bool bHorizontal, bool hollow /*=false*/ )
  5598. {
  5599. if ( m_nBgTextureId1 == -1 ||
  5600. m_nBgTextureId2 == -1 ||
  5601. m_nBgTextureId3 == -1 ||
  5602. m_nBgTextureId4 == -1 ||
  5603. surface()->DrawGetAlphaMultiplier() == 0 )
  5604. {
  5605. return;
  5606. }
  5607. color[3] *= normalizedAlpha;
  5608. // work out our bounds
  5609. int cornerWide, cornerTall;
  5610. GetCornerTextureSize( cornerWide, cornerTall );
  5611. if ( !bHorizontal )
  5612. {
  5613. // draw the background in the areas not occupied by the corners
  5614. // draw it in three horizontal strips
  5615. surface()->DrawSetColor(color);
  5616. surface()->DrawFilledRectFade(x + cornerWide, y, x + wide - cornerWide, y + cornerTall, alpha0, alpha0, bHorizontal );
  5617. if ( !hollow )
  5618. {
  5619. surface()->DrawFilledRectFade(x, y + cornerTall, x + wide, y + tall - cornerTall, alpha0, alpha1, bHorizontal);
  5620. }
  5621. else
  5622. {
  5623. surface()->DrawFilledRectFade(x, y + cornerTall, x + cornerWide, y + tall - cornerTall, alpha0, alpha1, bHorizontal);
  5624. surface()->DrawFilledRectFade(x + wide - cornerWide, y + cornerTall, x + wide, y + tall - cornerTall, alpha0, alpha1, bHorizontal);
  5625. }
  5626. surface()->DrawFilledRectFade(x + cornerWide, y + tall - cornerTall, x + wide - cornerWide, y + tall, alpha1, alpha1, bHorizontal);
  5627. }
  5628. else
  5629. {
  5630. // draw the background in the areas not occupied by the corners
  5631. // draw it in three horizontal strips
  5632. surface()->DrawSetColor(color);
  5633. surface()->DrawFilledRectFade(x, y + cornerTall, x + cornerWide, y + tall - cornerTall, alpha0, alpha0, bHorizontal );
  5634. if ( !hollow )
  5635. {
  5636. surface()->DrawFilledRectFade(x + cornerWide, y, x + wide - cornerWide, y + tall, alpha0, alpha1, bHorizontal);
  5637. }
  5638. else
  5639. {
  5640. // FIXME: Hollow horz version not implemented
  5641. //surface()->DrawFilledRectFade(x, y + cornerTall, x + cornerWide, y + tall - cornerTall, alpha0, alpha1, bHorizontal);
  5642. //surface()->DrawFilledRectFade(x + wide - cornerWide, y + cornerTall, x + wide, y + tall - cornerTall, alpha0, alpha1, bHorizontal);
  5643. }
  5644. surface()->DrawFilledRectFade(x + wide - cornerWide, y + cornerTall, x + wide, y + tall - cornerTall, alpha1, alpha1, bHorizontal);
  5645. }
  5646. float fOldAlpha = color[ 3 ];
  5647. int iAlpha0 = fOldAlpha * ( static_cast<float>( alpha0 ) / 255.0f );
  5648. int iAlpha1 = fOldAlpha * ( static_cast<float>( alpha1 ) / 255.0f );
  5649. // draw the corners
  5650. if ( !bHorizontal )
  5651. {
  5652. color[ 3 ] = iAlpha0;
  5653. surface()->DrawSetColor( color );
  5654. surface()->DrawSetTexture(m_nBgTextureId1);
  5655. surface()->DrawTexturedRect(x, y, x + cornerWide, y + cornerTall);
  5656. surface()->DrawSetTexture(m_nBgTextureId2);
  5657. surface()->DrawTexturedRect(x + wide - cornerWide, y, x + wide, y + cornerTall);
  5658. color[ 3 ] = iAlpha1;
  5659. surface()->DrawSetColor( color );
  5660. surface()->DrawSetTexture(m_nBgTextureId3);
  5661. surface()->DrawTexturedRect(x + wide - cornerWide, y + tall - cornerTall, x + wide, y + tall);
  5662. surface()->DrawSetTexture(m_nBgTextureId4);
  5663. surface()->DrawTexturedRect(x + 0, y + tall - cornerTall, x + cornerWide, y + tall);
  5664. }
  5665. else
  5666. {
  5667. color[ 3 ] = iAlpha0;
  5668. surface()->DrawSetColor( color );
  5669. surface()->DrawSetTexture(m_nBgTextureId1);
  5670. surface()->DrawTexturedRect(x, y, x + cornerWide, y + cornerTall);
  5671. surface()->DrawSetTexture(m_nBgTextureId4);
  5672. surface()->DrawTexturedRect(x + 0, y + tall - cornerTall, x + cornerWide, y + tall);
  5673. color[ 3 ] = iAlpha1;
  5674. surface()->DrawSetColor( color );
  5675. surface()->DrawSetTexture(m_nBgTextureId2);
  5676. surface()->DrawTexturedRect(x + wide - cornerWide, y, x + wide, y + cornerTall);
  5677. surface()->DrawSetTexture(m_nBgTextureId3);
  5678. surface()->DrawTexturedRect(x + wide - cornerWide, y + tall - cornerTall, x + wide, y + tall);
  5679. }
  5680. }
  5681. //-----------------------------------------------------------------------------
  5682. // Purpose:
  5683. // Input : x -
  5684. // y -
  5685. // wide -
  5686. // tall -
  5687. // color -
  5688. // normalizedAlpha -
  5689. //-----------------------------------------------------------------------------
  5690. void Panel::DrawHollowBox(int x, int y, int wide, int tall, Color color, float normalizedAlpha )
  5691. {
  5692. DrawBox( x, y, wide, tall, color, normalizedAlpha, true );
  5693. }
  5694. //=============================================================================
  5695. // HPE_BEGIN:
  5696. // [menglish] Draws a hollow box similar to the already existing draw hollow box function, but takes the indents as params
  5697. //=============================================================================
  5698. void Panel::DrawHollowBox( int x, int y, int wide, int tall, Color color, float normalizedAlpha, int cornerWide, int cornerTall )
  5699. {
  5700. if ( m_nBgTextureId1 == -1 ||
  5701. m_nBgTextureId2 == -1 ||
  5702. m_nBgTextureId3 == -1 ||
  5703. m_nBgTextureId4 == -1 )
  5704. {
  5705. return;
  5706. }
  5707. color[3] *= normalizedAlpha;
  5708. // draw the background in the areas not occupied by the corners
  5709. // draw it in three horizontal strips
  5710. surface()->DrawSetColor(color);
  5711. surface()->DrawFilledRect(x + cornerWide, y, x + wide - cornerWide, y + cornerTall);
  5712. surface()->DrawFilledRect(x, y + cornerTall, x + cornerWide, y + tall - cornerTall);
  5713. surface()->DrawFilledRect(x + wide - cornerWide, y + cornerTall, x + wide, y + tall - cornerTall);
  5714. surface()->DrawFilledRect(x + cornerWide, y + tall - cornerTall, x + wide - cornerWide, y + tall);
  5715. // draw the corners
  5716. surface()->DrawSetTexture(m_nBgTextureId1);
  5717. surface()->DrawTexturedRect(x, y, x + cornerWide, y + cornerTall);
  5718. surface()->DrawSetTexture(m_nBgTextureId2);
  5719. surface()->DrawTexturedRect(x + wide - cornerWide, y, x + wide, y + cornerTall);
  5720. surface()->DrawSetTexture(m_nBgTextureId3);
  5721. surface()->DrawTexturedRect(x + wide - cornerWide, y + tall - cornerTall, x + wide, y + tall);
  5722. surface()->DrawSetTexture(m_nBgTextureId4);
  5723. surface()->DrawTexturedRect(x + 0, y + tall - cornerTall, x + cornerWide, y + tall);
  5724. }
  5725. //=============================================================================
  5726. // HPE_END
  5727. //=============================================================================
  5728. //-----------------------------------------------------------------------------
  5729. // Purpose: draws a selection box
  5730. //-----------------------------------------------------------------------------
  5731. void Panel::DrawTexturedBox(int x, int y, int wide, int tall, Color color, float normalizedAlpha )
  5732. {
  5733. if ( m_nBgTextureId1 == -1 )
  5734. return;
  5735. color[3] *= normalizedAlpha;
  5736. surface()->DrawSetColor( color );
  5737. surface()->DrawSetTexture(m_nBgTextureId1);
  5738. surface()->DrawTexturedRect(x, y, x + wide, y + tall);
  5739. }
  5740. //-----------------------------------------------------------------------------
  5741. // Purpose: Marks this panel as draggable (note that children will chain to their parents to see if any parent is draggable)
  5742. // Input : enabled -
  5743. //-----------------------------------------------------------------------------
  5744. void Panel::SetDragEnabled( bool enabled )
  5745. {
  5746. #if defined( VGUI_USEDRAGDROP )
  5747. // If turning it off, quit dragging if mid-drag
  5748. if ( !enabled &&
  5749. m_pDragDrop->m_bDragging )
  5750. {
  5751. OnFinishDragging( false, (MouseCode)-1 );
  5752. }
  5753. m_pDragDrop->m_bDragEnabled = enabled;
  5754. #endif
  5755. }
  5756. //-----------------------------------------------------------------------------
  5757. // Purpose:
  5758. // Input : -
  5759. // Output : Returns true on success, false on failure.
  5760. //-----------------------------------------------------------------------------
  5761. bool Panel::IsDragEnabled() const
  5762. {
  5763. #if defined( VGUI_USEDRAGDROP )
  5764. return m_pDragDrop->m_bDragEnabled;
  5765. #endif
  5766. return false;
  5767. }
  5768. void Panel::SetShowDragHelper( bool enabled )
  5769. {
  5770. #if defined( VGUI_USEDRAGDROP )
  5771. m_pDragDrop->m_bShowDragHelper = enabled;
  5772. #endif
  5773. }
  5774. // Use this to prevent chaining up from a parent which can mess with mouse functionality if you don't want to chain up from a child panel to the best
  5775. // draggable parent.
  5776. void Panel::SetBlockDragChaining( bool block )
  5777. {
  5778. #if defined( VGUI_USEDRAGDROP )
  5779. m_pDragDrop->m_bPreventChaining = block;
  5780. #endif
  5781. }
  5782. //-----------------------------------------------------------------------------
  5783. // Purpose:
  5784. // Input : -
  5785. // Output : Returns true on success, false on failure.
  5786. //-----------------------------------------------------------------------------
  5787. bool Panel::IsBlockingDragChaining() const
  5788. {
  5789. #if defined( VGUI_USEDRAGDROP )
  5790. return m_pDragDrop->m_bPreventChaining;
  5791. #endif
  5792. return true;
  5793. }
  5794. //-----------------------------------------------------------------------------
  5795. // accessors for m_nDragStartTolerance
  5796. //-----------------------------------------------------------------------------
  5797. int Panel::GetDragStartTolerance() const
  5798. {
  5799. #if defined( VGUI_USEDRAGDROP )
  5800. return m_pDragDrop->m_nDragStartTolerance;
  5801. #endif
  5802. return 0;
  5803. }
  5804. void Panel::SetDragSTartTolerance( int nTolerance )
  5805. {
  5806. #if defined( VGUI_USEDRAGDROP )
  5807. m_pDragDrop->m_nDragStartTolerance = nTolerance;
  5808. #endif
  5809. }
  5810. //-----------------------------------------------------------------------------
  5811. // Purpose: Marks this panel as droppable ( note that children will chain to their parents to see if any parent is droppable)
  5812. // Input : enabled -
  5813. //-----------------------------------------------------------------------------
  5814. void Panel::SetDropEnabled( bool enabled, float flHoverContextTime /* = 0.0f */ )
  5815. {
  5816. #if defined( VGUI_USEDRAGDROP )
  5817. m_pDragDrop->m_bDropEnabled = enabled;
  5818. m_pDragDrop->m_flHoverContextTime = flHoverContextTime;
  5819. #endif
  5820. }
  5821. //-----------------------------------------------------------------------------
  5822. // Purpose:
  5823. // Input : -
  5824. // Output : Returns true on success, false on failure.
  5825. //-----------------------------------------------------------------------------
  5826. bool Panel::IsDropEnabled() const
  5827. {
  5828. #if defined( VGUI_USEDRAGDROP )
  5829. return m_pDragDrop->m_bDropEnabled;
  5830. #endif
  5831. return false;
  5832. }
  5833. //-----------------------------------------------------------------------------
  5834. // Purpose: Chains up to any parent
  5835. // 1) marked DropEnabled; and
  5836. // 2) willing to accept the drop payload
  5837. // Input : -
  5838. // Output : Panel
  5839. //-----------------------------------------------------------------------------
  5840. Panel *Panel::GetDropTarget( CUtlVector< KeyValues * >& msglist )
  5841. {
  5842. #if defined( VGUI_USEDRAGDROP )
  5843. // Found one
  5844. if ( m_pDragDrop->m_bDropEnabled &&
  5845. IsDroppable( msglist ) )
  5846. {
  5847. return this;
  5848. }
  5849. // Chain up
  5850. if ( GetParent() )
  5851. {
  5852. return GetParent()->GetDropTarget( msglist );
  5853. }
  5854. #endif
  5855. // No luck
  5856. return NULL;
  5857. }
  5858. //-----------------------------------------------------------------------------
  5859. // Purpose: Chains up to first parent marked DragEnabled
  5860. // Input : -
  5861. // Output : Panel
  5862. //-----------------------------------------------------------------------------
  5863. Panel *Panel::GetDragPanel()
  5864. {
  5865. #if defined( VGUI_USEDRAGDROP )
  5866. // If we encounter a blocker, stop chaining
  5867. if ( m_pDragDrop->m_bPreventChaining )
  5868. return NULL;
  5869. if ( m_pDragDrop->m_bDragEnabled )
  5870. return this;
  5871. // Chain up
  5872. if ( GetParent() )
  5873. {
  5874. return GetParent()->GetDragPanel();
  5875. }
  5876. #endif
  5877. // No luck
  5878. return NULL;
  5879. }
  5880. //-----------------------------------------------------------------------------
  5881. // Purpose:
  5882. // Input : -
  5883. //-----------------------------------------------------------------------------
  5884. void Panel::OnStartDragging()
  5885. {
  5886. #if defined( VGUI_USEDRAGDROP )
  5887. // Only left mouse initiates drag/drop.
  5888. // FIXME: Revisit?
  5889. if ( !input()->IsMouseDown( MOUSE_LEFT ) )
  5890. return;
  5891. if ( !m_pDragDrop->m_bDragEnabled )
  5892. return;
  5893. if ( m_pDragDrop->m_bDragging )
  5894. return;
  5895. g_DragDropCapture = this;
  5896. m_pDragDrop->m_bDragStarted = false;
  5897. m_pDragDrop->m_bDragging = true;
  5898. input()->GetCursorPos( m_pDragDrop->m_nStartPos[ 0 ], m_pDragDrop->m_nStartPos[ 1 ] );
  5899. m_pDragDrop->m_nLastPos[ 0 ] = m_pDragDrop->m_nStartPos[ 0 ];
  5900. m_pDragDrop->m_nLastPos[ 1 ] = m_pDragDrop->m_nStartPos[ 1 ];
  5901. OnContinueDragging();
  5902. #endif
  5903. }
  5904. //-----------------------------------------------------------------------------
  5905. // Purpose: Called if drag drop is started but not dropped on top of droppable panel...
  5906. // Input : -
  5907. //-----------------------------------------------------------------------------
  5908. void Panel::OnDragFailed( CUtlVector< KeyValues * >& msglist )
  5909. {
  5910. }
  5911. //-----------------------------------------------------------------------------
  5912. // Purpose:
  5913. // Input : -
  5914. //-----------------------------------------------------------------------------
  5915. void Panel::OnFinishDragging( bool mousereleased, MouseCode code, bool abort /*= false*/ )
  5916. {
  5917. #if defined( VGUI_USEDRAGDROP )
  5918. g_DragDropCapture = NULL;
  5919. if ( !m_pDragDrop->m_bDragEnabled )
  5920. return;
  5921. Assert( m_pDragDrop->m_bDragging );
  5922. if ( !m_pDragDrop->m_bDragging )
  5923. return;
  5924. int x, y;
  5925. input()->GetCursorPos( x, y );
  5926. m_pDragDrop->m_nLastPos[ 0 ] = x;
  5927. m_pDragDrop->m_nLastPos[ 1 ] = y;
  5928. if ( s_DragDropHelper.Get() )
  5929. {
  5930. s_DragDropHelper->RemovePanel( this );
  5931. }
  5932. m_pDragDrop->m_bDragging = false;
  5933. CUtlVector< KeyValues * >& data = m_pDragDrop->m_DragData;
  5934. int nData = data.Count();
  5935. Panel *target = NULL;
  5936. bool shouldDrop = false;
  5937. if ( m_pDragDrop->m_bDragStarted )
  5938. {
  5939. char cmd[ 256 ];
  5940. Q_strncpy( cmd, "default", sizeof( cmd ) );
  5941. if ( mousereleased &&
  5942. m_pDragDrop->m_hCurrentDrop != 0 &&
  5943. m_pDragDrop->m_hDropContextMenu.Get() )
  5944. {
  5945. Menu *menu = m_pDragDrop->m_hDropContextMenu;
  5946. VPANEL hover = menu->IsWithinTraverse( x, y, false );
  5947. if ( hover )
  5948. {
  5949. Panel *pHover = ipanel()->GetPanel( hover, GetModuleName() );
  5950. if ( pHover )
  5951. {
  5952. // Figure out if it's a menu item...
  5953. int c = menu->GetItemCount();
  5954. for ( int i = 0; i < c; ++i )
  5955. {
  5956. int id = menu->GetMenuID( i );
  5957. MenuItem *item = menu->GetMenuItem( id );
  5958. if ( item == pHover )
  5959. {
  5960. KeyValues *command = item->GetCommand();
  5961. if ( command )
  5962. {
  5963. char const *p = command->GetString( "command", "" );
  5964. if ( p && p[ 0 ] )
  5965. {
  5966. Q_strncpy( cmd, p, sizeof( cmd ) );
  5967. }
  5968. }
  5969. }
  5970. }
  5971. }
  5972. }
  5973. delete menu;
  5974. m_pDragDrop->m_hDropContextMenu = NULL;
  5975. }
  5976. for ( int i = 0 ; i < nData; ++i )
  5977. {
  5978. KeyValues *msg = data[ i ];
  5979. msg->SetString( "command", cmd );
  5980. msg->SetInt( "screenx", x );
  5981. msg->SetInt( "screeny", y );
  5982. }
  5983. target = m_pDragDrop->m_hCurrentDrop.Get();
  5984. if ( target && !abort )
  5985. {
  5986. int localmousex = x, localmousey = y;
  5987. // Convert screen space coordintes to coordinates relative to drop window
  5988. target->ScreenToLocal( localmousex, localmousey );
  5989. for ( int i = 0 ; i < nData; ++i )
  5990. {
  5991. KeyValues *msg = data[ i ];
  5992. msg->SetInt( "x", localmousex );
  5993. msg->SetInt( "y", localmousey );
  5994. }
  5995. shouldDrop = true;
  5996. }
  5997. if ( !shouldDrop )
  5998. {
  5999. OnDragFailed( data );
  6000. }
  6001. }
  6002. m_pDragDrop->m_bDragStarted = false;
  6003. m_pDragDrop->m_DragPanels.RemoveAll();
  6004. m_pDragDrop->m_hCurrentDrop = NULL;
  6005. // Copy data ptrs out of data because OnPanelDropped might cause this panel to be deleted
  6006. // and our this ptr will be hosed...
  6007. CUtlVector< KeyValues * > temp;
  6008. for ( int i = 0 ; i < nData; ++i )
  6009. {
  6010. temp.AddToTail( data[ i ] );
  6011. }
  6012. data.RemoveAll();
  6013. if ( shouldDrop && target )
  6014. {
  6015. target->OnPanelDropped( temp );
  6016. }
  6017. for ( int i = 0 ; i < nData; ++i )
  6018. {
  6019. temp[ i ]->deleteThis();
  6020. }
  6021. #endif
  6022. }
  6023. void Panel::OnDropContextHoverShow( CUtlVector< KeyValues * >& msglist )
  6024. {
  6025. }
  6026. void Panel::OnDropContextHoverHide( CUtlVector< KeyValues * >& msglist )
  6027. {
  6028. }
  6029. //-----------------------------------------------------------------------------
  6030. // Purpose:
  6031. // Input : *msg -
  6032. // Output : Returns true on success, false on failure.
  6033. //-----------------------------------------------------------------------------
  6034. bool Panel::IsDroppable( CUtlVector< KeyValues * >& msglist )
  6035. {
  6036. return false;
  6037. }
  6038. //-----------------------------------------------------------------------------
  6039. // Purpose:
  6040. // Input : startx -
  6041. // starty -
  6042. // mx -
  6043. // my -
  6044. // Output : Returns true on success, false on failure.
  6045. //-----------------------------------------------------------------------------
  6046. bool Panel::CanStartDragging( int startx, int starty, int mx, int my )
  6047. {
  6048. #if defined( VGUI_USEDRAGDROP )
  6049. if ( IsStartDragWhenMouseExitsPanel() )
  6050. {
  6051. ScreenToLocal( mx, my );
  6052. if ( mx < 0 || my < 0 )
  6053. return true;
  6054. if ( mx > GetWide() || my > GetTall() )
  6055. return true;
  6056. return false;
  6057. }
  6058. int deltax = abs( mx - startx );
  6059. int deltay = abs( my - starty );
  6060. if ( deltax > m_pDragDrop->m_nDragStartTolerance ||
  6061. deltay > m_pDragDrop->m_nDragStartTolerance )
  6062. {
  6063. return true;
  6064. }
  6065. #endif
  6066. return false;
  6067. }
  6068. HCursor Panel::GetDropCursor( CUtlVector< KeyValues * >& msglist )
  6069. {
  6070. return dc_arrow;
  6071. }
  6072. bool IsSelfDroppable( CUtlVector< KeyValues * > &dragData )
  6073. {
  6074. if ( dragData.Count() == 0 )
  6075. return false;
  6076. KeyValues *pKeyValues( dragData[ 0 ] );
  6077. if ( !pKeyValues )
  6078. return false;
  6079. return pKeyValues->GetInt( "selfDroppable" ) != 0;
  6080. }
  6081. //-----------------------------------------------------------------------------
  6082. // Purpose:
  6083. // Input : -
  6084. //-----------------------------------------------------------------------------
  6085. void Panel::OnContinueDragging()
  6086. {
  6087. #if defined( VGUI_USEDRAGDROP )
  6088. if ( !m_pDragDrop->m_bDragEnabled )
  6089. return;
  6090. if ( !m_pDragDrop->m_bDragging )
  6091. return;
  6092. int x, y;
  6093. input()->GetCursorPos( x, y );
  6094. // Update last position
  6095. m_pDragDrop->m_nLastPos[ 0 ] = x;
  6096. m_pDragDrop->m_nLastPos[ 1 ] = y;
  6097. if ( !m_pDragDrop->m_bDragStarted )
  6098. {
  6099. if ( CanStartDragging( m_pDragDrop->m_nStartPos[ 0 ], m_pDragDrop->m_nStartPos[ 1 ], x, y ) )
  6100. {
  6101. m_pDragDrop->m_bDragStarted = true;
  6102. CreateDragData();
  6103. }
  6104. else
  6105. {
  6106. return;
  6107. }
  6108. }
  6109. if ( !s_DragDropHelper.Get() && m_pDragDrop->m_bShowDragHelper )
  6110. {
  6111. s_DragDropHelper = new CDragDropHelperPanel();
  6112. s_DragDropHelper->SetKeyBoardInputEnabled( false );
  6113. s_DragDropHelper->SetMouseInputEnabled( false );
  6114. Assert( s_DragDropHelper.Get() );
  6115. }
  6116. if ( !s_DragDropHelper.Get() )
  6117. return;
  6118. s_DragDropHelper->AddPanel( this );
  6119. Assert( m_pDragDrop->m_DragData.Count() );
  6120. vgui::PHandle oldDrop = m_pDragDrop->m_hCurrentDrop;
  6121. // See what's under that
  6122. m_pDragDrop->m_hCurrentDrop = NULL;
  6123. // Search under mouse pos...
  6124. Panel *dropTarget = FindDropTargetPanel();
  6125. if ( dropTarget )
  6126. {
  6127. dropTarget = dropTarget->GetDropTarget( m_pDragDrop->m_DragData );
  6128. }
  6129. // it's not okay until we find a droppable panel
  6130. surface()->SetCursor( dc_no );
  6131. if ( dropTarget )
  6132. {
  6133. if ( dropTarget != this || IsSelfDroppable( m_pDragDrop->m_DragData ) )
  6134. {
  6135. m_pDragDrop->m_hCurrentDrop = dropTarget;
  6136. surface()->SetCursor( dropTarget->GetDropCursor( m_pDragDrop->m_DragData ) );
  6137. }
  6138. }
  6139. if ( m_pDragDrop->m_hCurrentDrop.Get() != oldDrop.Get() )
  6140. {
  6141. if ( oldDrop.Get() )
  6142. {
  6143. oldDrop->OnPanelExitedDroppablePanel( m_pDragDrop->m_DragData );
  6144. }
  6145. if ( m_pDragDrop->m_hCurrentDrop.Get() )
  6146. {
  6147. m_pDragDrop->m_hCurrentDrop->OnPanelEnteredDroppablePanel( m_pDragDrop->m_DragData );
  6148. m_pDragDrop->m_hCurrentDrop->OnDropContextHoverHide( m_pDragDrop->m_DragData );
  6149. // Reset hover time
  6150. m_pDragDrop->m_lDropHoverTime = system()->GetTimeMillis();
  6151. m_pDragDrop->m_bDropMenuShown = false;
  6152. }
  6153. // Discard any stale context menu...
  6154. if ( m_pDragDrop->m_hDropContextMenu.Get() )
  6155. {
  6156. delete m_pDragDrop->m_hDropContextMenu.Get();
  6157. }
  6158. }
  6159. if ( m_pDragDrop->m_hCurrentDrop != 0 &&
  6160. m_pDragDrop->m_hDropContextMenu.Get() )
  6161. {
  6162. Menu *menu = m_pDragDrop->m_hDropContextMenu;
  6163. VPANEL hover = menu->IsWithinTraverse( x, y, false );
  6164. if ( hover )
  6165. {
  6166. Panel *pHover = ipanel()->GetPanel( hover, GetModuleName() );
  6167. if ( pHover )
  6168. {
  6169. // Figure out if it's a menu item...
  6170. int c = menu->GetItemCount();
  6171. for ( int i = 0; i < c; ++i )
  6172. {
  6173. int id = menu->GetMenuID( i );
  6174. MenuItem *item = menu->GetMenuItem( id );
  6175. if ( item == pHover )
  6176. {
  6177. menu->SetCurrentlyHighlightedItem( id );
  6178. }
  6179. }
  6180. }
  6181. }
  6182. else
  6183. {
  6184. menu->ClearCurrentlyHighlightedItem();
  6185. }
  6186. }
  6187. #endif
  6188. }
  6189. #if defined( VGUI_USEDRAGDROP )
  6190. //-----------------------------------------------------------------------------
  6191. // Purpose:
  6192. // Input : -
  6193. // Output : DragDrop_t
  6194. //-----------------------------------------------------------------------------
  6195. DragDrop_t *Panel::GetDragDropInfo()
  6196. {
  6197. Assert( m_pDragDrop );
  6198. return m_pDragDrop;
  6199. }
  6200. #endif
  6201. void Panel::OnGetAdditionalDragPanels( CUtlVector< Panel * >& dragabbles )
  6202. {
  6203. // Nothing here
  6204. }
  6205. //-----------------------------------------------------------------------------
  6206. // Purpose: Virtual method to allow panels to add to the default values
  6207. // Input : *msg -
  6208. //-----------------------------------------------------------------------------
  6209. void Panel::OnCreateDragData( KeyValues *msg )
  6210. {
  6211. // These values are filled in for you:
  6212. // "panel" ptr to panel being dropped
  6213. // "screenx", "screeny" - drop cursor pos in screen space
  6214. // "x", "y" - drop coordinates relative to this window (the window being dropped upon)
  6215. }
  6216. // Called if m_flHoverContextTime was non-zero, allows droppee to preview the drop data and show an appropriate menu
  6217. bool Panel::GetDropContextMenu( Menu *menu, CUtlVector< KeyValues * >& msglist )
  6218. {
  6219. return false;
  6220. }
  6221. void Panel::CreateDragData()
  6222. {
  6223. #if defined( VGUI_USEDRAGDROP )
  6224. int i, c;
  6225. if ( m_pDragDrop->m_DragData.Count() )
  6226. {
  6227. return;
  6228. }
  6229. PHandle h;
  6230. h = this;
  6231. m_pDragDrop->m_DragPanels.AddToTail( h );
  6232. CUtlVector< Panel * > temp;
  6233. OnGetAdditionalDragPanels( temp );
  6234. c = temp.Count();
  6235. for ( i = 0; i < c; ++i )
  6236. {
  6237. h = temp[ i ];
  6238. m_pDragDrop->m_DragPanels.AddToTail( h );
  6239. }
  6240. c = m_pDragDrop->m_DragPanels.Count();
  6241. for ( i = 0 ; i < c; ++i )
  6242. {
  6243. Panel *sibling = m_pDragDrop->m_DragPanels[ i ].Get();
  6244. if ( !sibling )
  6245. {
  6246. continue;
  6247. }
  6248. KeyValues *msg = new KeyValues( "DragDrop" );
  6249. msg->SetPtr( "panel", sibling );
  6250. sibling->OnCreateDragData( msg );
  6251. m_pDragDrop->m_DragData.AddToTail( msg );
  6252. }
  6253. #endif
  6254. }
  6255. //-----------------------------------------------------------------------------
  6256. // Purpose:
  6257. // Input : -
  6258. // Output : KeyValues
  6259. //-----------------------------------------------------------------------------
  6260. void Panel::GetDragData( CUtlVector< KeyValues * >& list )
  6261. {
  6262. #if defined( VGUI_USEDRAGDROP )
  6263. int i, c;
  6264. list.RemoveAll();
  6265. c = m_pDragDrop->m_DragData.Count();
  6266. for ( i = 0 ; i < c; ++i )
  6267. {
  6268. list.AddToTail( m_pDragDrop->m_DragData[ i ] );
  6269. }
  6270. #endif
  6271. }
  6272. #if defined( VGUI_USEDRAGDROP )
  6273. CDragDropHelperPanel::CDragDropHelperPanel() : BaseClass( NULL, "DragDropHelper" )
  6274. {
  6275. SetVisible( true );
  6276. SetPaintEnabled( false );
  6277. SetPaintBackgroundEnabled( false );
  6278. SetMouseInputEnabled( false );
  6279. SetKeyBoardInputEnabled( false );
  6280. // SetCursor( dc_none );
  6281. ipanel()->SetTopmostPopup( GetVPanel(), true );
  6282. int w, h;
  6283. surface()->GetScreenSize( w, h );
  6284. SetBounds( 0, 0, w, h );
  6285. SetPostChildPaintEnabled( true );
  6286. MakePopup( false );
  6287. }
  6288. VPANEL CDragDropHelperPanel::IsWithinTraverse(int x, int y, bool traversePopups)
  6289. {
  6290. return (VPANEL)0;
  6291. }
  6292. void CDragDropHelperPanel::PostChildPaint()
  6293. {
  6294. int c = m_PaintList.Count();
  6295. for ( int i = c - 1; i >= 0 ; --i )
  6296. {
  6297. DragHelperPanel_t& data = m_PaintList[ i ];
  6298. Panel *panel = data.m_hPanel.Get();
  6299. if ( !panel )
  6300. {
  6301. m_PaintList.Remove( i );
  6302. continue;
  6303. }
  6304. Panel *dropPanel = panel->GetDragDropInfo()->m_hCurrentDrop.Get();
  6305. if ( panel )
  6306. {
  6307. if ( !dropPanel )
  6308. {
  6309. panel->OnDraggablePanelPaint();
  6310. }
  6311. else
  6312. {
  6313. CUtlVector< Panel * > temp;
  6314. CUtlVector< PHandle >& dragData = panel->GetDragDropInfo()->m_DragPanels;
  6315. CUtlVector< KeyValues * >& msglist = panel->GetDragDropInfo()->m_DragData;
  6316. int j, nDragData;
  6317. nDragData = dragData.Count();
  6318. for ( j = 0; j < nDragData; ++j )
  6319. {
  6320. Panel *pPanel = dragData[ j ].Get();
  6321. if ( pPanel )
  6322. {
  6323. temp.AddToTail( pPanel );
  6324. }
  6325. }
  6326. dropPanel->OnDroppablePanelPaint( msglist, temp );
  6327. }
  6328. }
  6329. }
  6330. if ( c == 0 )
  6331. {
  6332. MarkForDeletion();
  6333. }
  6334. }
  6335. void CDragDropHelperPanel::AddPanel( Panel *current )
  6336. {
  6337. if ( !current )
  6338. return;
  6339. Menu *hover = current->GetDragDropInfo()->m_hDropContextMenu.Get();
  6340. surface()->MovePopupToFront( GetVPanel() );
  6341. if ( hover && hover->IsPopup() )
  6342. {
  6343. surface()->MovePopupToFront( hover->GetVPanel() );
  6344. }
  6345. int c = m_PaintList.Count();
  6346. for ( int i = 0; i < c; ++i )
  6347. {
  6348. if ( m_PaintList[ i ].m_hPanel.Get() == current )
  6349. return;
  6350. }
  6351. DragHelperPanel_t data;
  6352. data.m_hPanel = current;
  6353. m_PaintList.AddToTail( data );
  6354. }
  6355. //-----------------------------------------------------------------------------
  6356. // Purpose:
  6357. // Input : *search -
  6358. //-----------------------------------------------------------------------------
  6359. void CDragDropHelperPanel::RemovePanel( Panel *search )
  6360. {
  6361. int c = m_PaintList.Count();
  6362. for ( int i = c - 1 ; i >= 0; --i )
  6363. {
  6364. if ( m_PaintList[ i ].m_hPanel.Get() == search )
  6365. {
  6366. m_PaintList.Remove( i );
  6367. return;
  6368. }
  6369. }
  6370. }
  6371. #endif
  6372. //-----------------------------------------------------------------------------
  6373. // Purpose: Enumerates panels under mouse x,y
  6374. // Input : panelList -
  6375. // x -
  6376. // y -
  6377. // check -
  6378. //-----------------------------------------------------------------------------
  6379. void Panel::FindDropTargetPanel_R( CUtlVector< VPANEL >& panelList, int x, int y, VPANEL check )
  6380. {
  6381. #if defined( VGUI_USEDRAGDROP )
  6382. if ( !ipanel()->IsFullyVisible( check ) )
  6383. return;
  6384. if ( ::ShouldHandleInputMessage( check ) && ipanel()->IsWithinTraverse( check, x, y, false ) )
  6385. {
  6386. panelList.AddToTail( check );
  6387. }
  6388. CUtlVector< VPANEL > &children = ipanel()->GetChildren( check );
  6389. int childCount = children.Count();
  6390. for ( int i = 0; i < childCount; i++ )
  6391. {
  6392. VPANEL child = children[ i ];
  6393. FindDropTargetPanel_R( panelList, x, y, child );
  6394. }
  6395. #endif
  6396. }
  6397. //-----------------------------------------------------------------------------
  6398. // Purpose:
  6399. // Input : -
  6400. // Output : Panel
  6401. //-----------------------------------------------------------------------------
  6402. Panel *Panel::FindDropTargetPanel()
  6403. {
  6404. #if defined( VGUI_USEDRAGDROP )
  6405. if ( !s_DragDropHelper.Get() )
  6406. return NULL;
  6407. CUtlVector< VPANEL > hits;
  6408. int x, y;
  6409. input()->GetCursorPos( x, y );
  6410. VPANEL embedded = surface()->GetEmbeddedPanel();
  6411. VPANEL helper = s_DragDropHelper.Get()->GetVPanel();
  6412. if ( surface()->IsCursorVisible() && surface()->IsWithin(x, y) )
  6413. {
  6414. // faster version of code below
  6415. // checks through each popup in order, top to bottom windows
  6416. int c = surface()->GetPopupCount();
  6417. for (int i = c - 1; i >= 0 && hits.Count() == 0; i--)
  6418. {
  6419. VPANEL popup = surface()->GetPopup(i);
  6420. if ( popup == embedded )
  6421. continue;
  6422. // Don't return helper panel!!!
  6423. if ( popup == helper )
  6424. continue;
  6425. if ( !ipanel()->IsFullyVisible( popup ) )
  6426. continue;
  6427. FindDropTargetPanel_R( hits, x, y, popup );
  6428. }
  6429. // Check embedded
  6430. if ( !hits.Count() )
  6431. {
  6432. FindDropTargetPanel_R( hits, x, y, embedded );
  6433. }
  6434. }
  6435. // Nothing under mouse...
  6436. if ( !hits.Count() )
  6437. return NULL;
  6438. // Return topmost panel under mouse, if it's visible to this .dll
  6439. Panel *panel = NULL;
  6440. int nCount = hits.Count();
  6441. while ( --nCount >= 0 )
  6442. {
  6443. panel = ipanel()->GetPanel( hits[ nCount ], GetModuleName() );
  6444. if ( panel )
  6445. return panel;
  6446. }
  6447. #endif
  6448. return NULL;
  6449. }
  6450. //-----------------------------------------------------------------------------
  6451. // Purpose: Mouse is on draggable panel and has started moving, but is not over a droppable panel yet
  6452. // Input : -
  6453. //-----------------------------------------------------------------------------
  6454. void Panel::OnDraggablePanelPaint()
  6455. {
  6456. #if defined( VGUI_USEDRAGDROP )
  6457. int sw, sh;
  6458. GetSize( sw, sh );
  6459. int x, y;
  6460. input()->GetCursorPos( x, y );
  6461. int w, h;
  6462. w = min( sw, 80 );
  6463. h = min( sh, 80 );
  6464. x -= ( w >> 1 );
  6465. y -= ( h >> 1 );
  6466. surface()->DrawSetColor( m_clrDragFrame );
  6467. surface()->DrawOutlinedRect( x, y, x + w, y + h );
  6468. if ( m_pDragDrop->m_DragPanels.Count() > 1 )
  6469. {
  6470. surface()->DrawSetTextColor( m_clrDragFrame );
  6471. surface()->DrawSetTextFont( m_infoFont );
  6472. surface()->DrawSetTextPos( x + 5, y + 2 );
  6473. wchar_t sz[ 64 ];
  6474. V_swprintf_safe( sz, L"[ %i ]", m_pDragDrop->m_DragPanels.Count() );
  6475. surface()->DrawPrintText( sz, wcslen( sz ) );
  6476. }
  6477. #endif
  6478. }
  6479. //-----------------------------------------------------------------------------
  6480. // Purpose: Mouse is now over a droppable panel
  6481. // Input : *dragPanel -
  6482. //-----------------------------------------------------------------------------
  6483. void Panel::OnDroppablePanelPaint( CUtlVector< KeyValues * >& msglist, CUtlVector< Panel * >& dragPanels )
  6484. {
  6485. #if defined( VGUI_USEDRAGDROP )
  6486. if ( !dragPanels.Count() )
  6487. return;
  6488. // Convert this panel's bounds to screen space
  6489. int w, h;
  6490. GetSize( w, h );
  6491. int x, y;
  6492. x = y = 0;
  6493. LocalToScreen( x, y );
  6494. surface()->DrawSetColor( m_clrDropFrame );
  6495. // Draw 2 pixel frame
  6496. surface()->DrawOutlinedRect( x, y, x + w, y + h );
  6497. surface()->DrawOutlinedRect( x+1, y+1, x + w-1, y + h-1 );
  6498. #endif
  6499. }
  6500. //-----------------------------------------------------------------------------
  6501. // Purpose:
  6502. // Input : -
  6503. // Output : Color
  6504. //-----------------------------------------------------------------------------
  6505. Color Panel::GetDropFrameColor()
  6506. {
  6507. #if defined( VGUI_USEDRAGDROP )
  6508. return m_clrDropFrame;
  6509. #endif
  6510. return Color(0, 0, 0, 0);
  6511. }
  6512. //-----------------------------------------------------------------------------
  6513. // Purpose:
  6514. // Input : -
  6515. // Output : Color
  6516. //-----------------------------------------------------------------------------
  6517. Color Panel::GetDragFrameColor()
  6518. {
  6519. #if defined( VGUI_USEDRAGDROP )
  6520. return m_clrDragFrame;
  6521. #endif
  6522. return Color(0, 0, 0, 0);
  6523. }
  6524. //-----------------------------------------------------------------------------
  6525. // Purpose:
  6526. // Input : *data -
  6527. //-----------------------------------------------------------------------------
  6528. void Panel::OnPanelDropped( CUtlVector< KeyValues * >& data )
  6529. {
  6530. // Empty. Derived classes would implement handlers here
  6531. }
  6532. //-----------------------------------------------------------------------------
  6533. // called on droptarget when draggable panel enters droptarget
  6534. //-----------------------------------------------------------------------------
  6535. void Panel::OnPanelEnteredDroppablePanel( CUtlVector< KeyValues * >& msglist )
  6536. {
  6537. // Empty. Derived classes would implement handlers here
  6538. }
  6539. //-----------------------------------------------------------------------------
  6540. // called on droptarget when draggable panel exits droptarget
  6541. //-----------------------------------------------------------------------------
  6542. void Panel::OnPanelExitedDroppablePanel ( CUtlVector< KeyValues * >& msglist )
  6543. {
  6544. // Empty. Derived classes would implement handlers here
  6545. }
  6546. //-----------------------------------------------------------------------------
  6547. // Purpose:
  6548. // Input : -
  6549. //-----------------------------------------------------------------------------
  6550. void Panel::DragDropStartDragging()
  6551. {
  6552. #if defined( VGUI_USEDRAGDROP )
  6553. // We somehow missed a mouse release, cancel the previous drag
  6554. if ( g_DragDropCapture.Get() )
  6555. {
  6556. if ( HasParent( g_DragDropCapture.Get()->GetVPanel() ) )
  6557. return;
  6558. bool started = g_DragDropCapture->GetDragDropInfo()->m_bDragStarted;
  6559. g_DragDropCapture->OnFinishDragging( true, (MouseCode)-1 );
  6560. if ( started )
  6561. {
  6562. return;
  6563. }
  6564. }
  6565. // Find actual target panel
  6566. Panel *panel = GetDragPanel();
  6567. if ( !panel )
  6568. return;
  6569. DragDrop_t *data = panel->GetDragDropInfo();
  6570. if ( !data )
  6571. return;
  6572. if ( !panel->IsDragEnabled() )
  6573. return;
  6574. if ( data->m_bDragging )
  6575. return;
  6576. panel->OnStartDragging();
  6577. #endif
  6578. }
  6579. //-----------------------------------------------------------------------------
  6580. // Purpose:
  6581. // Input : -
  6582. // Output : Returns true on success, false on failure.
  6583. //-----------------------------------------------------------------------------
  6584. bool Panel::IsBeingDragged()
  6585. {
  6586. #if defined( VGUI_USEDRAGDROP )
  6587. if ( !g_DragDropCapture.Get() )
  6588. return false;
  6589. if ( g_DragDropCapture.Get() == this )
  6590. return true;
  6591. // If we encounter a blocker, stop chaining
  6592. if ( m_pDragDrop->m_bPreventChaining )
  6593. return false;
  6594. // Chain up
  6595. if ( GetParent() )
  6596. {
  6597. return GetParent()->IsBeingDragged();
  6598. }
  6599. #endif
  6600. // No luck
  6601. return false;
  6602. }
  6603. struct srect_t
  6604. {
  6605. int x0, y0;
  6606. int x1, y1;
  6607. bool IsDegenerate()
  6608. {
  6609. if ( x1 - x0 <= 0 )
  6610. return true;
  6611. if ( y1 - y0 <= 0 )
  6612. return true;
  6613. return false;
  6614. }
  6615. };
  6616. // Draws a filled rect of specified bounds, but omits the bounds of the skip panel from those bounds
  6617. void Panel::FillRectSkippingPanel( const Color &clr, int x, int y, int w, int h, Panel *skipPanel )
  6618. {
  6619. int sx = 0, sy = 0, sw, sh;
  6620. skipPanel->GetSize( sw, sh );
  6621. skipPanel->LocalToScreen( sx, sy );
  6622. ScreenToLocal( sx, sy );
  6623. surface()->DrawSetColor( clr );
  6624. srect_t r1;
  6625. r1.x0 = x;
  6626. r1.y0 = y;
  6627. r1.x1 = x + w;
  6628. r1.y1 = y + h;
  6629. srect_t r2;
  6630. r2.x0 = sx;
  6631. r2.y0 = sy;
  6632. r2.x1 = sx + sw;
  6633. r2.y1 = sy + sh;
  6634. int topy = r1.y0;
  6635. int bottomy = r1.y1;
  6636. // We'll descend vertically and draw:
  6637. // 1 a possible bar across the top
  6638. // 2 a possible bar across the bottom
  6639. // 3 possible left bar
  6640. // 4 possible right bar
  6641. // Room at top?
  6642. if ( r2.y0 > r1.y0 )
  6643. {
  6644. topy = r2.y0;
  6645. surface()->DrawFilledRect( r1.x0, r1.y0, r1.x1, topy );
  6646. }
  6647. // Room at bottom?
  6648. if ( r2.y1 < r1.y1 )
  6649. {
  6650. bottomy = r2.y1;
  6651. surface()->DrawFilledRect( r1.x0, bottomy, r1.x1, r1.y1 );
  6652. }
  6653. // Room on left side?
  6654. if ( r2.x0 > r1.x0 )
  6655. {
  6656. int left = r2.x0;
  6657. surface()->DrawFilledRect( r1.x0, topy, left, bottomy );
  6658. }
  6659. // Room on right side
  6660. if ( r2.x1 < r1.x1 )
  6661. {
  6662. int right = r2.x1;
  6663. surface()->DrawFilledRect( right, topy, r1.x1, bottomy );
  6664. }
  6665. }
  6666. //-----------------------------------------------------------------------------
  6667. // Purpose:
  6668. // Input : *child -
  6669. //-----------------------------------------------------------------------------
  6670. void Panel::SetSkipChildDuringPainting( Panel *child )
  6671. {
  6672. m_SkipChild = child;
  6673. }
  6674. HPanel Panel::ToHandle() const
  6675. {
  6676. return ivgui()->PanelToHandle( _vpanel );
  6677. }
  6678. //-----------------------------------------------------------------------------
  6679. // Purpose:
  6680. //-----------------------------------------------------------------------------
  6681. Panel* Panel::NavigateUp()
  6682. {
  6683. Panel *target = GetNavUp();
  6684. if ( target )
  6685. {
  6686. NavigateFrom();
  6687. target->m_LastNavDirection = ND_UP;
  6688. target->NavigateTo();
  6689. }
  6690. return target;
  6691. }
  6692. //-----------------------------------------------------------------------------
  6693. // Purpose:
  6694. //-----------------------------------------------------------------------------
  6695. Panel* Panel::NavigateDown()
  6696. {
  6697. Panel *target = GetNavDown();
  6698. if ( target )
  6699. {
  6700. NavigateFrom();
  6701. target->m_LastNavDirection = ND_DOWN;
  6702. target->NavigateTo();
  6703. }
  6704. return target;
  6705. }
  6706. //-----------------------------------------------------------------------------
  6707. // Purpose:
  6708. //-----------------------------------------------------------------------------
  6709. Panel* Panel::NavigateLeft()
  6710. {
  6711. Panel *target = GetNavLeft();
  6712. if ( target )
  6713. {
  6714. NavigateFrom();
  6715. target->m_LastNavDirection = ND_LEFT;
  6716. target->NavigateTo();
  6717. }
  6718. return target;
  6719. }
  6720. //-----------------------------------------------------------------------------
  6721. // Purpose:
  6722. //-----------------------------------------------------------------------------
  6723. Panel* Panel::NavigateRight()
  6724. {
  6725. Panel *target = GetNavRight();
  6726. if ( target )
  6727. {
  6728. NavigateFrom();
  6729. target->m_LastNavDirection = ND_RIGHT;
  6730. target->NavigateTo();
  6731. }
  6732. return target;
  6733. }
  6734. Panel* Panel::NavigateActivate()
  6735. {
  6736. Panel *target = GetNavActivate();
  6737. if ( target )
  6738. {
  6739. NavigateFrom();
  6740. target->m_LastNavDirection = ND_NONE;
  6741. target->NavigateTo();
  6742. }
  6743. return target;
  6744. }
  6745. Panel* Panel::NavigateBack()
  6746. {
  6747. Panel *target = GetNavBack();
  6748. if ( target )
  6749. {
  6750. NavigateFrom();
  6751. target->m_LastNavDirection = ND_NONE;
  6752. target->NavigateTo();
  6753. }
  6754. return target;
  6755. }
  6756. //-----------------------------------------------------------------------------
  6757. // Purpose:
  6758. //-----------------------------------------------------------------------------
  6759. void Panel::NavigateTo()
  6760. {
  6761. if ( IsX360() )
  6762. {
  6763. RequestFocus( 0 );
  6764. }
  6765. CallParentFunction( new KeyValues( "OnNavigateTo", "panelName", GetName() ) );
  6766. Panel *target = GetNavToRelay();
  6767. if ( target )
  6768. {
  6769. NavigateFrom();
  6770. target->m_LastNavDirection = ND_NONE;
  6771. NavigateToChild( target );
  6772. }
  6773. }
  6774. //-----------------------------------------------------------------------------
  6775. // Purpose:
  6776. //-----------------------------------------------------------------------------
  6777. void Panel::NavigateFrom()
  6778. {
  6779. for ( int i = 0; i < GetChildCount(); ++i )
  6780. {
  6781. Panel* currentNav = GetChild(i);
  6782. if ( currentNav != 0 )
  6783. {
  6784. currentNav->NavigateFrom();
  6785. }
  6786. }
  6787. CallParentFunction( new KeyValues( "OnNavigateFrom", "panelName", GetName() ) );
  6788. if ( m_pTooltips )
  6789. {
  6790. m_pTooltips->HideTooltip();
  6791. }
  6792. m_LastNavDirection = ND_NONE;
  6793. }
  6794. void Panel::NavigateToChild( Panel *pNavigateTo )
  6795. {
  6796. for( int i = 0; i != GetChildCount(); ++i )
  6797. {
  6798. vgui::Panel *pChild = GetChild(i);
  6799. if( pChild )
  6800. pChild->NavigateFrom();
  6801. }
  6802. pNavigateTo->NavigateTo();
  6803. }
  6804. //-----------------------------------------------------------------------------
  6805. // Purpose:
  6806. //-----------------------------------------------------------------------------
  6807. Panel* Panel::SetNavUp( Panel* navUp )
  6808. {
  6809. Panel* lastNav = m_NavUp;
  6810. m_NavUp = navUp;
  6811. if( navUp )
  6812. m_sNavUpName = navUp->GetName();
  6813. else
  6814. m_sNavUpName.Clear();
  6815. return lastNav;
  6816. }
  6817. //-----------------------------------------------------------------------------
  6818. // Purpose:
  6819. //-----------------------------------------------------------------------------
  6820. Panel* Panel::SetNavDown( Panel* navDown )
  6821. {
  6822. Panel* lastNav = m_NavDown;
  6823. m_NavDown = navDown;
  6824. if( navDown )
  6825. m_sNavDownName = navDown->GetName();
  6826. else
  6827. m_sNavDownName.Clear();
  6828. return lastNav;
  6829. }
  6830. //-----------------------------------------------------------------------------
  6831. // Purpose:
  6832. //-----------------------------------------------------------------------------
  6833. Panel* Panel::SetNavLeft( Panel* navLeft )
  6834. {
  6835. Panel* lastNav = m_NavLeft;
  6836. m_NavLeft = navLeft;
  6837. if( navLeft )
  6838. m_sNavLeftName = navLeft->GetName();
  6839. else
  6840. m_sNavLeftName.Clear();
  6841. return lastNav;
  6842. }
  6843. //-----------------------------------------------------------------------------
  6844. // Purpose:
  6845. //-----------------------------------------------------------------------------
  6846. Panel* Panel::SetNavRight( Panel* navRight )
  6847. {
  6848. Panel* lastNav = m_NavRight;
  6849. m_NavRight = navRight;
  6850. if( navRight )
  6851. m_sNavRightName = navRight->GetName();
  6852. else
  6853. m_sNavRightName.Clear();
  6854. return lastNav;
  6855. }
  6856. Panel* Panel::SetNavToRelay( Panel* navToRelay )
  6857. {
  6858. Panel* lastNav = m_NavToRelay;
  6859. m_NavToRelay = navToRelay;
  6860. return lastNav;
  6861. }
  6862. Panel* Panel::SetNavActivate( Panel* navActivate )
  6863. {
  6864. Panel* lastNav = m_NavActivate;
  6865. m_NavActivate = navActivate;
  6866. return lastNav;
  6867. }
  6868. Panel* Panel::SetNavBack( Panel* navBack )
  6869. {
  6870. Panel* lastNav = m_NavBack;
  6871. m_NavBack = navBack;
  6872. return lastNav;
  6873. }
  6874. //-----------------------------------------------------------------------------
  6875. // Purpose:
  6876. //-----------------------------------------------------------------------------
  6877. Panel::NAV_DIRECTION Panel::GetLastNavDirection()
  6878. {
  6879. return m_LastNavDirection;
  6880. }
  6881. //-----------------------------------------------------------------------------
  6882. // Purpose:
  6883. //-----------------------------------------------------------------------------
  6884. void Panel::OnNavigateTo( const char* panelName )
  6885. {
  6886. }
  6887. //-----------------------------------------------------------------------------
  6888. // Purpose:
  6889. //-----------------------------------------------------------------------------
  6890. void Panel::OnNavigateFrom( const char* panelName )
  6891. {
  6892. }
  6893. //-----------------------------------------------------------------------------
  6894. // Purpose:
  6895. //-----------------------------------------------------------------------------
  6896. void Panel::SetNavUp( const char* controlName )
  6897. {
  6898. if ( controlName && 0 < Q_strlen( controlName ) && GetParent() != 0 )
  6899. {
  6900. m_NavUp = NULL;
  6901. m_sNavUpName = controlName;
  6902. }
  6903. }
  6904. //-----------------------------------------------------------------------------
  6905. // Purpose:
  6906. //-----------------------------------------------------------------------------
  6907. void Panel::SetNavDown( const char* controlName )
  6908. {
  6909. if ( controlName && 0 < Q_strlen( controlName ) && GetParent() != 0 )
  6910. {
  6911. m_NavDown = NULL;
  6912. m_sNavDownName = controlName;
  6913. }
  6914. }
  6915. //-----------------------------------------------------------------------------
  6916. // Purpose:
  6917. //-----------------------------------------------------------------------------
  6918. void Panel::SetNavLeft( const char* controlName )
  6919. {
  6920. if ( controlName && 0 < Q_strlen( controlName ) && GetParent() != 0 )
  6921. {
  6922. m_NavLeft = NULL;
  6923. m_sNavLeftName = controlName;
  6924. }
  6925. }
  6926. //-----------------------------------------------------------------------------
  6927. // Purpose:
  6928. //-----------------------------------------------------------------------------
  6929. void Panel::SetNavRight( const char* controlName )
  6930. {
  6931. if ( controlName && 0 < Q_strlen( controlName ) && GetParent() != 0 )
  6932. {
  6933. m_NavRight = NULL;
  6934. m_sNavRightName = controlName;
  6935. }
  6936. }
  6937. void Panel::SetNavToRelay( const char* controlName )
  6938. {
  6939. if ( controlName && 0 < Q_strlen( controlName ) && GetParent() != 0 )
  6940. {
  6941. m_NavToRelay = NULL;
  6942. m_sNavToRelayName = controlName;
  6943. }
  6944. }
  6945. void Panel::SetNavActivate( const char* controlName )
  6946. {
  6947. if ( controlName && 0 < Q_strlen( controlName ) && GetParent() != 0 )
  6948. {
  6949. m_NavActivate = NULL;
  6950. m_sNavActivateName = controlName;
  6951. }
  6952. }
  6953. void Panel::SetNavBack( const char* controlName )
  6954. {
  6955. if ( controlName && 0 < Q_strlen( controlName ) && GetParent() != 0 )
  6956. {
  6957. m_NavBack = NULL;
  6958. m_sNavBackName = controlName;
  6959. }
  6960. }
  6961. //-----------------------------------------------------------------------------
  6962. // Purpose:
  6963. //-----------------------------------------------------------------------------
  6964. vgui::Panel* Panel::GetNavUp( Panel *first )
  6965. {
  6966. if ( !m_NavUp && m_sNavUpName.Length() > 0 )
  6967. {
  6968. Panel *pParent = GetParent();
  6969. const char *pName = m_sNavUpName.String();
  6970. while ( pParent && pName[ 0 ] == '<' )
  6971. {
  6972. pParent = pParent->GetParent();
  6973. pName++;
  6974. }
  6975. if ( !pParent )
  6976. {
  6977. return NULL;
  6978. }
  6979. Panel *foundPanel = pParent->FindChildByName( pName, true );
  6980. if ( foundPanel != 0 )
  6981. {
  6982. m_NavUp = foundPanel;
  6983. }
  6984. }
  6985. vgui::Panel* nextPanel = m_NavUp;
  6986. if( m_NavUp && m_NavUp != first && !m_NavUp->IsVisible() )
  6987. {
  6988. Panel *firstPanel = first == NULL ? this : first;
  6989. nextPanel = nextPanel->GetNavUp( firstPanel );
  6990. }
  6991. return nextPanel;
  6992. }
  6993. vgui::Panel* Panel::GetNavDown( Panel *first )
  6994. {
  6995. if ( !m_NavDown && m_sNavDownName.Length() > 0 )
  6996. {
  6997. Panel *pParent = GetParent();
  6998. const char *pName = m_sNavDownName.String();
  6999. while ( pParent && pName[ 0 ] == '<' )
  7000. {
  7001. pParent = pParent->GetParent();
  7002. pName++;
  7003. }
  7004. if ( !pParent )
  7005. {
  7006. return NULL;
  7007. }
  7008. Panel* foundPanel = pParent->FindChildByName( pName, true );
  7009. if ( foundPanel != 0 )
  7010. {
  7011. m_NavDown = foundPanel->GetPanel();
  7012. }
  7013. }
  7014. vgui::Panel* nextPanel = m_NavDown;
  7015. if( m_NavDown && m_NavDown != first && !m_NavDown->IsVisible() )
  7016. {
  7017. Panel *firstPanel = first == NULL ? this : first;
  7018. nextPanel = nextPanel->GetNavDown( firstPanel );
  7019. }
  7020. return nextPanel;
  7021. }
  7022. vgui::Panel* Panel::GetNavLeft( Panel *first )
  7023. {
  7024. if ( !m_NavLeft && m_sNavLeftName.Length() > 0 )
  7025. {
  7026. Panel *pParent = GetParent();
  7027. const char *pName = m_sNavLeftName.String();
  7028. while ( pParent && pName[ 0 ] == '<' )
  7029. {
  7030. pParent = pParent->GetParent();
  7031. pName++;
  7032. }
  7033. if ( !pParent )
  7034. {
  7035. return NULL;
  7036. }
  7037. Panel* foundPanel = pParent->FindChildByName( pName, true );
  7038. if ( foundPanel != 0 )
  7039. {
  7040. m_NavLeft = foundPanel->GetPanel();
  7041. }
  7042. }
  7043. vgui::Panel* nextPanel = m_NavLeft;
  7044. if( m_NavLeft && m_NavLeft != first && !m_NavLeft->IsVisible() )
  7045. {
  7046. Panel *firstPanel = first == NULL ? this : first;
  7047. nextPanel = nextPanel->GetNavLeft( firstPanel );
  7048. }
  7049. return nextPanel;
  7050. }
  7051. vgui::Panel* Panel::GetNavRight( Panel *first )
  7052. {
  7053. if ( !m_NavRight && m_sNavRightName.Length() > 0 )
  7054. {
  7055. Panel *pParent = GetParent();
  7056. const char *pName = m_sNavRightName.String();
  7057. while ( pParent && pName[ 0 ] == '<' )
  7058. {
  7059. pParent = pParent->GetParent();
  7060. pName++;
  7061. }
  7062. if ( !pParent )
  7063. {
  7064. return NULL;
  7065. }
  7066. Panel* foundPanel = pParent->FindChildByName( pName, true );
  7067. if ( foundPanel != 0 )
  7068. {
  7069. m_NavRight = foundPanel->GetPanel();
  7070. }
  7071. }
  7072. vgui::Panel* nextPanel = m_NavRight;
  7073. if( m_NavRight && m_NavRight != first && !m_NavRight->IsVisible() )
  7074. {
  7075. Panel *firstPanel = first == NULL ? this : first;
  7076. nextPanel = nextPanel->GetNavRight( firstPanel );
  7077. }
  7078. return nextPanel;
  7079. }
  7080. vgui::Panel* Panel::GetNavToRelay( Panel *first )
  7081. {
  7082. if ( !m_NavToRelay && m_sNavToRelayName.Length() > 0 )
  7083. {
  7084. Panel *pParent = this;
  7085. const char *pName = m_sNavToRelayName.String();
  7086. while ( pParent && pName[ 0 ] == '<' )
  7087. {
  7088. pParent = pParent->GetParent();
  7089. pName++;
  7090. }
  7091. if ( !pParent )
  7092. {
  7093. return NULL;
  7094. }
  7095. Panel* foundPanel = pParent->FindChildByName( pName, true );
  7096. if ( foundPanel != 0 )
  7097. {
  7098. m_NavToRelay = foundPanel->GetPanel();
  7099. }
  7100. }
  7101. vgui::Panel* nextPanel = m_NavToRelay;
  7102. if ( m_NavToRelay && m_NavToRelay != first && !m_NavToRelay->IsVisible() )
  7103. {
  7104. Panel *firstPanel = first == NULL ? this : first;
  7105. nextPanel = nextPanel->GetNavToRelay( firstPanel );
  7106. }
  7107. return nextPanel;
  7108. }
  7109. vgui::Panel* Panel::GetNavActivate( Panel *first )
  7110. {
  7111. if ( !m_NavActivate && m_sNavActivateName.Length() > 0 )
  7112. {
  7113. Panel *pParent = GetParent();
  7114. const char *pName = m_sNavActivateName.String();
  7115. while ( pParent && pName[ 0 ] == '<' )
  7116. {
  7117. pParent = pParent->GetParent();
  7118. pName++;
  7119. }
  7120. if ( !pParent )
  7121. {
  7122. return NULL;
  7123. }
  7124. Panel* foundPanel = pParent->FindChildByName( pName, true );
  7125. if ( foundPanel != 0 )
  7126. {
  7127. m_NavActivate = foundPanel->GetPanel();
  7128. }
  7129. }
  7130. vgui::Panel* nextPanel = m_NavActivate;
  7131. if ( m_NavActivate && m_NavActivate != first && !m_NavActivate->IsVisible() )
  7132. {
  7133. Panel *firstPanel = first == NULL ? this : first;
  7134. nextPanel = nextPanel->GetNavActivate( firstPanel );
  7135. }
  7136. return nextPanel;
  7137. }
  7138. vgui::Panel* Panel::GetNavBack( Panel *first )
  7139. {
  7140. if ( !m_NavBack && m_sNavBackName.Length() > 0 )
  7141. {
  7142. Panel *pParent = GetParent();
  7143. const char *pName = m_sNavBackName.String();
  7144. while ( pParent && pName[ 0 ] == '<' )
  7145. {
  7146. pParent = pParent->GetParent();
  7147. pName++;
  7148. }
  7149. if ( !pParent )
  7150. {
  7151. return NULL;
  7152. }
  7153. Panel *foundPanel = pParent->FindChildByName( pName );
  7154. if ( foundPanel )
  7155. {
  7156. m_NavBack = foundPanel;
  7157. }
  7158. }
  7159. vgui::Panel* nextPanel = m_NavBack;
  7160. if ( m_NavBack && m_NavBack != first && !m_NavBack->IsVisible() )
  7161. {
  7162. Panel *firstPanel = first == NULL ? this : first;
  7163. nextPanel = nextPanel->GetNavBack( firstPanel );
  7164. }
  7165. return nextPanel;
  7166. }
  7167. vgui::Panel* Panel::GetNavUpPanel()
  7168. {
  7169. return m_NavUp;
  7170. }
  7171. vgui::Panel* Panel::GetNavDownPanel()
  7172. {
  7173. return m_NavDown;
  7174. }
  7175. vgui::Panel* Panel::GetNavLeftPanel()
  7176. {
  7177. return m_NavLeft;
  7178. }
  7179. vgui::Panel* Panel::GetNavRightPanel()
  7180. {
  7181. return m_NavRight;
  7182. }
  7183. vgui::Panel* Panel::GetNavToRelayPanel()
  7184. {
  7185. return m_NavToRelay;
  7186. }
  7187. vgui::Panel* Panel::GetNavActivatePanel()
  7188. {
  7189. return m_NavActivate;
  7190. }
  7191. vgui::Panel* Panel::GetNavBackPanel()
  7192. {
  7193. return m_NavBack;
  7194. }
  7195. void Panel::SetConsoleStylePanel( bool bConsoleStyle )
  7196. {
  7197. m_bIsConsoleStylePanel = bConsoleStyle;
  7198. }
  7199. bool Panel::IsConsoleStylePanel() const
  7200. {
  7201. return m_bIsConsoleStylePanel;
  7202. }
  7203. //-----------------------------------------------------------------------------
  7204. // Purpose: Utility class for handling message map allocation
  7205. //-----------------------------------------------------------------------------
  7206. class CPanelMessageMapDictionary
  7207. {
  7208. public:
  7209. CPanelMessageMapDictionary() : m_PanelMessageMapPool( sizeof(PanelMessageMap), 32, CUtlMemoryPool::GROW_FAST, "CPanelMessageMapDictionary::m_PanelMessageMapPool" )
  7210. {
  7211. m_MessageMaps.RemoveAll();
  7212. }
  7213. PanelMessageMap *FindOrAddPanelMessageMap( char const *className );
  7214. PanelMessageMap *FindPanelMessageMap( char const *className );
  7215. private:
  7216. struct PanelMessageMapDictionaryEntry
  7217. {
  7218. PanelMessageMap *map;
  7219. };
  7220. char const *StripNamespace( char const *className );
  7221. CUtlDict< PanelMessageMapDictionaryEntry, int > m_MessageMaps;
  7222. CUtlMemoryPool m_PanelMessageMapPool;
  7223. };
  7224. char const *CPanelMessageMapDictionary::StripNamespace( char const *className )
  7225. {
  7226. if ( !strnicmp( className, "vgui::", 6 ) )
  7227. {
  7228. return className + 6;
  7229. }
  7230. return className;
  7231. }
  7232. //-----------------------------------------------------------------------------
  7233. // Purpose: Find but don't add mapping
  7234. //-----------------------------------------------------------------------------
  7235. PanelMessageMap *CPanelMessageMapDictionary::FindPanelMessageMap( char const *className )
  7236. {
  7237. int lookup = m_MessageMaps.Find( StripNamespace( className ) );
  7238. if ( lookup != m_MessageMaps.InvalidIndex() )
  7239. {
  7240. return m_MessageMaps[ lookup ].map;
  7241. }
  7242. return NULL;
  7243. }
  7244. #include <tier0/memdbgoff.h>
  7245. //-----------------------------------------------------------------------------
  7246. // Purpose:
  7247. //-----------------------------------------------------------------------------
  7248. PanelMessageMap *CPanelMessageMapDictionary::FindOrAddPanelMessageMap( char const *className )
  7249. {
  7250. PanelMessageMap *map = FindPanelMessageMap( className );
  7251. if ( map )
  7252. return map;
  7253. PanelMessageMapDictionaryEntry entry;
  7254. // use the alloc in place method of new
  7255. entry.map = new (m_PanelMessageMapPool.Alloc(sizeof(PanelMessageMap))) PanelMessageMap;
  7256. Construct(entry.map);
  7257. m_MessageMaps.Insert( StripNamespace( className ), entry );
  7258. return entry.map;
  7259. }
  7260. #include <tier0/memdbgon.h>
  7261. #if defined( VGUI_USEKEYBINDINGMAPS )
  7262. //-----------------------------------------------------------------------------
  7263. // Purpose: Utility class for handling keybinding map allocation
  7264. //-----------------------------------------------------------------------------
  7265. class CPanelKeyBindingMapDictionary
  7266. {
  7267. public:
  7268. CPanelKeyBindingMapDictionary() : m_PanelKeyBindingMapPool( sizeof(PanelKeyBindingMap), 32, CUtlMemoryPool::GROW_FAST, "CPanelKeyBindingMapDictionary::m_PanelKeyBindingMapPool" )
  7269. {
  7270. m_MessageMaps.RemoveAll();
  7271. }
  7272. PanelKeyBindingMap *FindOrAddPanelKeyBindingMap( char const *className );
  7273. PanelKeyBindingMap *FindPanelKeyBindingMap( char const *className );
  7274. private:
  7275. struct PanelKeyBindingMapDictionaryEntry
  7276. {
  7277. PanelKeyBindingMap *map;
  7278. };
  7279. char const *StripNamespace( char const *className );
  7280. CUtlDict< PanelKeyBindingMapDictionaryEntry, int > m_MessageMaps;
  7281. CUtlMemoryPool m_PanelKeyBindingMapPool;
  7282. };
  7283. char const *CPanelKeyBindingMapDictionary::StripNamespace( char const *className )
  7284. {
  7285. if ( !strnicmp( className, "vgui::", 6 ) )
  7286. {
  7287. return className + 6;
  7288. }
  7289. return className;
  7290. }
  7291. //-----------------------------------------------------------------------------
  7292. // Purpose: Find but don't add mapping
  7293. //-----------------------------------------------------------------------------
  7294. PanelKeyBindingMap *CPanelKeyBindingMapDictionary::FindPanelKeyBindingMap( char const *className )
  7295. {
  7296. int lookup = m_MessageMaps.Find( StripNamespace( className ) );
  7297. if ( lookup != m_MessageMaps.InvalidIndex() )
  7298. {
  7299. return m_MessageMaps[ lookup ].map;
  7300. }
  7301. return NULL;
  7302. }
  7303. #include <tier0/memdbgoff.h>
  7304. //-----------------------------------------------------------------------------
  7305. // Purpose:
  7306. //-----------------------------------------------------------------------------
  7307. PanelKeyBindingMap *CPanelKeyBindingMapDictionary::FindOrAddPanelKeyBindingMap( char const *className )
  7308. {
  7309. PanelKeyBindingMap *map = FindPanelKeyBindingMap( className );
  7310. if ( map )
  7311. return map;
  7312. PanelKeyBindingMapDictionaryEntry entry;
  7313. // use the alloc in place method of new
  7314. entry.map = new (m_PanelKeyBindingMapPool.Alloc(sizeof(PanelKeyBindingMap))) PanelKeyBindingMap;
  7315. Construct(entry.map);
  7316. m_MessageMaps.Insert( StripNamespace( className ), entry );
  7317. return entry.map;
  7318. }
  7319. #include <tier0/memdbgon.h>
  7320. CPanelKeyBindingMapDictionary& GetPanelKeyBindingMapDictionary()
  7321. {
  7322. static CPanelKeyBindingMapDictionary dictionary;
  7323. return dictionary;
  7324. }
  7325. #endif // VGUI_USEKEYBINDINGMAPS
  7326. CPanelMessageMapDictionary& GetPanelMessageMapDictionary()
  7327. {
  7328. static CPanelMessageMapDictionary dictionary;
  7329. return dictionary;
  7330. }
  7331. namespace vgui
  7332. {
  7333. //-----------------------------------------------------------------------------
  7334. // Purpose:
  7335. //-----------------------------------------------------------------------------
  7336. PanelMessageMap *FindOrAddPanelMessageMap( char const *className )
  7337. {
  7338. return GetPanelMessageMapDictionary().FindOrAddPanelMessageMap( className );
  7339. }
  7340. //-----------------------------------------------------------------------------
  7341. // Purpose: Find but don't add mapping
  7342. //-----------------------------------------------------------------------------
  7343. PanelMessageMap *FindPanelMessageMap( char const *className )
  7344. {
  7345. return GetPanelMessageMapDictionary().FindPanelMessageMap( className );
  7346. }
  7347. #if defined( VGUI_USEKEYBINDINGMAPS )
  7348. CPanelKeyBindingMapDictionary& GetPanelKeyBindingMapDictionary()
  7349. {
  7350. static CPanelKeyBindingMapDictionary dictionary;
  7351. return dictionary;
  7352. }
  7353. //-----------------------------------------------------------------------------
  7354. // Purpose:
  7355. //-----------------------------------------------------------------------------
  7356. PanelKeyBindingMap *FindOrAddPanelKeyBindingMap( char const *className )
  7357. {
  7358. return GetPanelKeyBindingMapDictionary().FindOrAddPanelKeyBindingMap( className );
  7359. }
  7360. //-----------------------------------------------------------------------------
  7361. // Purpose: Find but don't add mapping
  7362. //-----------------------------------------------------------------------------
  7363. PanelKeyBindingMap *FindPanelKeyBindingMap( char const *className )
  7364. {
  7365. return GetPanelKeyBindingMapDictionary().FindPanelKeyBindingMap( className );
  7366. }
  7367. #endif // VGUI_USEKEYBINDINGMAPS
  7368. SortedPanel_t::SortedPanel_t( Panel *panel )
  7369. {
  7370. pPanel = panel; pButton = dynamic_cast< Button* >( panel );
  7371. }
  7372. void VguiPanelGetSortedChildPanelList( Panel *pParentPanel, void *pSortedPanels )
  7373. {
  7374. CUtlSortVector< SortedPanel_t, CSortedPanelYLess > *pList = reinterpret_cast< CUtlSortVector< SortedPanel_t, CSortedPanelYLess >* >( pSortedPanels );
  7375. for ( int i = 0; i < pParentPanel->GetChildCount(); i++ )
  7376. {
  7377. // perform auto-layout on the child panel
  7378. Panel *pPanel = pParentPanel->GetChild( i );
  7379. if ( !pPanel || !pPanel->IsVisible() )
  7380. continue;
  7381. pList->Insert( SortedPanel_t( static_cast< Panel* >( pPanel ) ) );
  7382. }
  7383. }
  7384. void VguiPanelGetSortedChildButtonList( Panel *pParentPanel, void *pSortedPanels, char *pchFilter /*= NULL*/, int nFilterType /*= 0*/ )
  7385. {
  7386. CUtlSortVector< SortedPanel_t, CSortedPanelYLess > *pList = reinterpret_cast< CUtlSortVector< SortedPanel_t, CSortedPanelYLess >* >( pSortedPanels );
  7387. for ( int i = 0; i < pParentPanel->GetChildCount(); i++ )
  7388. {
  7389. // perform auto-layout on the child panel
  7390. Button *pPanel = dynamic_cast< Button* >( pParentPanel->GetChild( i ) );
  7391. if ( !pPanel || !pPanel->IsVisible() )
  7392. continue;
  7393. if ( pchFilter && pchFilter[ 0 ] != '\0' )
  7394. {
  7395. char szBuff[ 128 ];
  7396. pPanel->GetText( szBuff, sizeof( szBuff ) );
  7397. // Prefix
  7398. if ( nFilterType == 0 )
  7399. {
  7400. if ( !StringHasPrefix( szBuff, pchFilter ) )
  7401. {
  7402. continue;
  7403. }
  7404. }
  7405. // Substring
  7406. else if ( nFilterType == 1 )
  7407. {
  7408. if ( V_strstr( szBuff, pchFilter ) == NULL )
  7409. {
  7410. continue;
  7411. }
  7412. }
  7413. }
  7414. pList->Insert( SortedPanel_t( pPanel ) );
  7415. }
  7416. }
  7417. int VguiPanelNavigateSortedChildButtonList( void *pSortedPanels, int nDir )
  7418. {
  7419. CUtlSortVector< SortedPanel_t, CSortedPanelYLess > *pList = reinterpret_cast< CUtlSortVector< SortedPanel_t, CSortedPanelYLess >* >( pSortedPanels );
  7420. if ( pList->Count() <= 0 )
  7421. return -1;
  7422. if ( nDir != 0 )
  7423. {
  7424. int nArmed = -1;
  7425. for ( int i = 0; i < pList->Count(); i++ )
  7426. {
  7427. if ( (*pList)[ i ].pButton->IsArmed() )
  7428. {
  7429. nArmed = i;
  7430. break;
  7431. }
  7432. }
  7433. if ( nArmed == -1 )
  7434. {
  7435. (*pList)[ 0 ].pButton->SetArmed( true );
  7436. return 0;
  7437. }
  7438. else
  7439. {
  7440. int nNewArmed = clamp( nArmed + nDir, 0, pList->Count() - 1 );
  7441. if ( nNewArmed != nArmed )
  7442. {
  7443. (*pList)[ nArmed ].pButton->SetArmed( false );
  7444. }
  7445. (*pList)[ nNewArmed ].pButton->RequestFocus();
  7446. (*pList)[ nNewArmed ].pButton->SetArmed( true );
  7447. return nNewArmed;
  7448. }
  7449. }
  7450. return -1;
  7451. }
  7452. int ComputeWide(Panel* pPanel, unsigned int& nBuildFlags, KeyValues *inResourceData, int nParentWide, int nParentTall, bool bComputingOther)
  7453. {
  7454. int wide = pPanel->GetWide();
  7455. const char *wstr = inResourceData->GetString("wide", NULL);
  7456. if (wstr)
  7457. {
  7458. if (wstr[0] == 'f' || wstr[0] == 'F')
  7459. {
  7460. nBuildFlags |= Panel::BUILDMODE_SAVE_WIDE_FULL;
  7461. wstr++;
  7462. }
  7463. else
  7464. {
  7465. if (wstr[0] == 'o' || wstr[0] == 'O')
  7466. {
  7467. wstr++;
  7468. if (bComputingOther)
  7469. {
  7470. Warning("Wide and Tall of panel %s are set to be each other!\n", pPanel->GetName());
  7471. return 0;
  7472. }
  7473. nBuildFlags |= Panel::BUILDMODE_SAVE_WIDE_PROPORTIONAL_TALL;
  7474. wide = ComputeTall(pPanel, nBuildFlags, inResourceData, nParentWide, nParentTall, true);
  7475. if (pPanel->IsProportional())
  7476. {
  7477. wide = scheme()->GetProportionalNormalizedValue(wide);
  7478. }
  7479. }
  7480. else if (wstr[0] == 'p' || wstr[0] == 'P')
  7481. {
  7482. nBuildFlags |= Panel::BUILDMODE_SAVE_WIDE_PROPORTIONAL;
  7483. wstr++;
  7484. }
  7485. else if (wstr[0] == 's' || wstr[0] == 'S')
  7486. {
  7487. nBuildFlags |= Panel::BUILDMODE_SAVE_WIDE_PROPORTIONAL_SELF;
  7488. wstr++;
  7489. }
  7490. }
  7491. float flWide = atof(wstr);
  7492. if (!(nBuildFlags & Panel::BUILDMODE_SAVE_WIDE_PROPORTIONAL_TALL))
  7493. {
  7494. wide = atoi(wstr);
  7495. }
  7496. if (nBuildFlags & Panel::BUILDMODE_SAVE_WIDE_PROPORTIONAL_TALL)
  7497. {
  7498. wide = scheme()->GetProportionalScaledValueEx(pPanel->GetScheme(), wide);
  7499. wide *= flWide;
  7500. }
  7501. else if (nBuildFlags & Panel::BUILDMODE_SAVE_WIDE_PROPORTIONAL)
  7502. {
  7503. wide = scheme()->GetProportionalScaledValueEx(pPanel->GetScheme(), wide);
  7504. wide = nParentWide - wide;
  7505. wide *= flWide;
  7506. }
  7507. else if (nBuildFlags & Panel::BUILDMODE_SAVE_WIDE_PROPORTIONAL_SELF)
  7508. {
  7509. wide = pPanel->GetWide() * flWide;
  7510. }
  7511. else
  7512. {
  7513. if (pPanel->IsProportional())
  7514. {
  7515. // scale the width up to our screen co-ords
  7516. wide = scheme()->GetProportionalScaledValueEx(pPanel->GetScheme(), wide);
  7517. }
  7518. // now correct the alignment
  7519. if (nBuildFlags & Panel::BUILDMODE_SAVE_WIDE_FULL)
  7520. {
  7521. wide = nParentWide - wide;
  7522. }
  7523. }
  7524. }
  7525. return wide;
  7526. }
  7527. int ComputeTall(Panel* pPanel, unsigned int& nBuildFlags, KeyValues *inResourceData, int nParentWide, int nParentTall, bool bComputingOther)
  7528. {
  7529. int tall = pPanel->GetTall();
  7530. // allow tall to be use the "fill" option, set to the height of the parent/screen
  7531. const char *tstr = inResourceData->GetString("tall", NULL);
  7532. if (tstr)
  7533. {
  7534. if (tstr[0] == 'f' || tstr[0] == 'F')
  7535. {
  7536. nBuildFlags |= Panel::BUILDMODE_SAVE_TALL_FULL;
  7537. tstr++;
  7538. }
  7539. else
  7540. {
  7541. if (tstr[0] == 'o' || tstr[0] == 'O')
  7542. {
  7543. tstr++;
  7544. if (bComputingOther)
  7545. {
  7546. Warning("Wide and Tall of panel %s are set to be each other!\n", pPanel->GetName());
  7547. return 0;
  7548. }
  7549. nBuildFlags |= Panel::BUILDMODE_SAVE_TALL_PROPORTIONAL_WIDE;
  7550. tall = ComputeWide(pPanel, nBuildFlags, inResourceData, nParentWide, nParentTall, true);
  7551. if (pPanel->IsProportional())
  7552. {
  7553. tall = scheme()->GetProportionalNormalizedValue(tall);
  7554. }
  7555. }
  7556. else if (tstr[0] == 'p' || tstr[0] == 'P')
  7557. {
  7558. nBuildFlags |= Panel::BUILDMODE_SAVE_TALL_PROPORTIONAL;
  7559. tstr++;
  7560. }
  7561. else if (tstr[0] == 's' || tstr[0] == 'S')
  7562. {
  7563. nBuildFlags |= Panel::BUILDMODE_SAVE_TALL_PROPORTIONAL_SELF;
  7564. tstr++;
  7565. }
  7566. }
  7567. float flTall = atof(tstr);
  7568. if (!(nBuildFlags & Panel::BUILDMODE_SAVE_TALL_PROPORTIONAL_WIDE))
  7569. {
  7570. tall = atoi(tstr);
  7571. }
  7572. if (nBuildFlags & Panel::BUILDMODE_SAVE_TALL_PROPORTIONAL_WIDE)
  7573. {
  7574. tall = scheme()->GetProportionalScaledValueEx(pPanel->GetScheme(), tall);
  7575. tall *= flTall;
  7576. }
  7577. else if (nBuildFlags & Panel::BUILDMODE_SAVE_TALL_PROPORTIONAL)
  7578. {
  7579. // scale the height up to our screen co-ords
  7580. tall = scheme()->GetProportionalScaledValueEx(pPanel->GetScheme(), tall);
  7581. tall = nParentTall - tall;
  7582. tall *= flTall;
  7583. }
  7584. else if(nBuildFlags & Panel::BUILDMODE_SAVE_TALL_PROPORTIONAL_SELF)
  7585. {
  7586. tall = pPanel->GetTall() * flTall;
  7587. }
  7588. else
  7589. {
  7590. if (pPanel->IsProportional())
  7591. {
  7592. // scale the height up to our screen co-ords
  7593. tall = scheme()->GetProportionalScaledValueEx(pPanel->GetScheme(), tall);
  7594. }
  7595. // now correct the alignment
  7596. if (nBuildFlags & Panel::BUILDMODE_SAVE_TALL_FULL)
  7597. {
  7598. tall = nParentTall - tall;
  7599. }
  7600. }
  7601. }
  7602. return tall;
  7603. }
  7604. int ComputePos( Panel* pPanel, const char *pszInput, int &nPos, const int& nSize, const int& nParentSize, const bool& bX, EOperator eOp)
  7605. {
  7606. const int nFlagRightAlign = bX ? Panel::BUILDMODE_SAVE_XPOS_RIGHTALIGNED : Panel::BUILDMODE_SAVE_YPOS_BOTTOMALIGNED;
  7607. const int nFlagCenterAlign = bX ? Panel::BUILDMODE_SAVE_XPOS_CENTERALIGNED : Panel::BUILDMODE_SAVE_YPOS_CENTERALIGNED;
  7608. const int nFlagProportionalSelf = bX ? Panel::BUILDMODE_SAVE_XPOS_PROPORTIONAL_SELF : Panel::BUILDMODE_SAVE_YPOS_PROPORTIONAL_SELF;
  7609. const int nFlagProportionalParent = bX ? Panel::BUILDMODE_SAVE_XPOS_PROPORTIONAL_PARENT : Panel::BUILDMODE_SAVE_YPOS_PROPORTIONAL_PARENT;
  7610. int nFlags = 0;
  7611. int nPosDelta = 0;
  7612. if (pszInput)
  7613. {
  7614. // look for alignment flags
  7615. if (pszInput[0] == 'r' || pszInput[0] == 'R')
  7616. {
  7617. nFlags |= nFlagRightAlign;
  7618. pszInput++;
  7619. }
  7620. else if (pszInput[0] == 'c' || pszInput[0] == 'C')
  7621. {
  7622. nFlags |= nFlagCenterAlign;
  7623. pszInput++;
  7624. }
  7625. if (pszInput[0] == 's' || pszInput[0] == 'S')
  7626. {
  7627. nFlags |= nFlagProportionalSelf;
  7628. pszInput++;
  7629. }
  7630. else if (pszInput[0] == 'p' || pszInput[0] == 'P')
  7631. {
  7632. nFlags |= nFlagProportionalParent;
  7633. pszInput++;
  7634. }
  7635. // get the value
  7636. int nNewPos = atoi(pszInput);
  7637. float flPos = atof(pszInput);
  7638. float flProportion = 1.f;
  7639. // scale the x up to our screen co-ords
  7640. if ( pPanel->IsProportional() )
  7641. {
  7642. int nOldPos = nNewPos;
  7643. nNewPos = scheme()->GetProportionalScaledValueEx( pPanel->GetScheme(), nNewPos );
  7644. flProportion = (float)nNewPos / (float)nOldPos;
  7645. }
  7646. if (nFlags & nFlagProportionalSelf)
  7647. {
  7648. nPosDelta = nSize * flPos;
  7649. }
  7650. else if (nFlags & nFlagProportionalParent)
  7651. {
  7652. nPosDelta = nParentSize * flPos;
  7653. }
  7654. else
  7655. {
  7656. nPosDelta = nNewPos;
  7657. }
  7658. // now correct the alignment
  7659. if (nFlags & nFlagRightAlign)
  7660. {
  7661. nNewPos = nParentSize - nPosDelta;
  7662. }
  7663. else if (nFlags & nFlagCenterAlign)
  7664. {
  7665. nNewPos = (nParentSize / 2) + nPosDelta;
  7666. }
  7667. else
  7668. {
  7669. nNewPos = nPosDelta;
  7670. }
  7671. switch (eOp)
  7672. {
  7673. case OP_ADD:
  7674. nPos += nNewPos;
  7675. break;
  7676. case OP_SUB:
  7677. nPos -= nNewPos;
  7678. break;
  7679. case OP_SET:
  7680. nPos = nNewPos;
  7681. break;
  7682. }
  7683. // Jump the sign if it's there
  7684. if (pszInput[0] == '-' || pszInput[0] == '+')
  7685. pszInput++;
  7686. // Go past the number
  7687. while (V_isdigit(pszInput[0]) || pszInput[0] == '.')
  7688. pszInput++;
  7689. // Peep if there's an operator
  7690. if (pszInput && pszInput[0])
  7691. {
  7692. // Recurse!
  7693. switch (pszInput[0])
  7694. {
  7695. case '+':
  7696. ComputePos( pPanel, ++pszInput, nPos, nSize, nParentSize, bX, OP_ADD);
  7697. break;
  7698. case '-':
  7699. ComputePos( pPanel, ++pszInput, nPos, nSize, nParentSize, bX, OP_SUB);
  7700. break;
  7701. }
  7702. }
  7703. }
  7704. if (tf_debug_tabcontainer.GetBool() && !Q_stricmp("TabContainer", pPanel->GetName()))
  7705. {
  7706. Msg("TabContainer nFlags:%x nPos:%d nParentSize:%d nPosDelta:%d nSize:%d GetParent:%p (%s) pszInput:'%s'\n",
  7707. nFlags, nPos, nParentSize, nPosDelta, nSize, pPanel->GetParent(), pPanel->GetParent() ? pPanel->GetParent()->GetName() : "??",
  7708. pszInput ? pszInput : "??");
  7709. }
  7710. return nFlags;
  7711. }
  7712. }