Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1037 lines
29 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include <vgui/IPanel.h>
  8. #include <vgui/ISurface.h>
  9. #include <vgui/ISystem.h>
  10. #include <vgui/ILocalize.h>
  11. #include <keyvalues.h>
  12. #include "vgui/IVGui.h"
  13. #include <vgui_controls/BuildGroup.h>
  14. #include <vgui_controls/BuildModeDialog.h>
  15. #include <vgui_controls/EditablePanel.h>
  16. // these includes are all for the virtual contruction factory Dialog::CreateControlByName()
  17. #include <vgui_controls/Button.h>
  18. #include <vgui_controls/Label.h>
  19. #include <vgui_controls/CheckButton.h>
  20. #include <vgui_controls/ComboBox.h>
  21. #include <vgui_controls/Menu.h>
  22. #include <vgui_controls/MenuItem.h>
  23. #include <vgui_controls/MessageBox.h>
  24. #include <vgui_controls/ProgressBar.h>
  25. #include <vgui_controls/RadioButton.h>
  26. #include <vgui_controls/ScrollBar.h>
  27. #include <vgui_controls/ToggleButton.h>
  28. #include <vgui_controls/ImagePanel.h>
  29. #include <vgui_controls/AnimatingImagePanel.h>
  30. #include <vgui_controls/Divider.h>
  31. #include <vgui_controls/URLLabel.h>
  32. #include <vgui_controls/RichText.h>
  33. #include <vgui_controls/BitmapImagePanel.h>
  34. // memdbgon must be the last include file in a .cpp file!!!
  35. #include <tier0/memdbgon.h>
  36. using namespace vgui;
  37. DECLARE_BUILD_FACTORY( EditablePanel );
  38. //-----------------------------------------------------------------------------
  39. // Purpose: Constructor
  40. //-----------------------------------------------------------------------------
  41. #pragma warning( disable : 4355 )
  42. EditablePanel::EditablePanel(Panel *parent, const char *panelName) : Panel(parent, panelName), m_NavGroup(this)
  43. {
  44. _buildGroup = new BuildGroup(this, this);
  45. m_pszConfigName = NULL;
  46. m_iConfigID = 0;
  47. m_pDialogVariables = NULL;
  48. // add ourselves to the build group
  49. _buildGroup->PanelAdded( this );
  50. }
  51. //-----------------------------------------------------------------------------
  52. // Purpose: Constructor
  53. //-----------------------------------------------------------------------------
  54. EditablePanel::EditablePanel(Panel *parent, const char *panelName, HScheme hScheme) : Panel(parent, panelName, hScheme), m_NavGroup(this)
  55. {
  56. _buildGroup = new BuildGroup(this, this);
  57. m_pszConfigName = NULL;
  58. m_iConfigID = 0;
  59. m_pDialogVariables = NULL;
  60. // add ourselves to the build group
  61. _buildGroup->PanelAdded( this );
  62. }
  63. #pragma warning( default : 4355 )
  64. //-----------------------------------------------------------------------------
  65. // Purpose: Destructor
  66. //-----------------------------------------------------------------------------
  67. EditablePanel::~EditablePanel()
  68. {
  69. SetBuildGroup( NULL );
  70. delete [] m_pszConfigName;
  71. delete _buildGroup;
  72. if (m_pDialogVariables)
  73. {
  74. m_pDialogVariables->deleteThis();
  75. }
  76. }
  77. //-----------------------------------------------------------------------------
  78. // Purpose: Called when a child is added to the panel.
  79. //-----------------------------------------------------------------------------
  80. void EditablePanel::OnChildAdded(VPANEL child)
  81. {
  82. BaseClass::OnChildAdded(child);
  83. // add only if we're in the same module
  84. Panel *panel = ipanel()->GetPanel(child, GetModuleName());
  85. if (panel)
  86. {
  87. panel->SetBuildGroup(_buildGroup);
  88. panel->AddActionSignalTarget(this);
  89. }
  90. }
  91. //-----------------------------------------------------------------------------
  92. // Purpose:
  93. //-----------------------------------------------------------------------------
  94. void EditablePanel::OnKeyCodeTyped(KeyCode code)
  95. {
  96. if (code == KEY_ENTER)
  97. {
  98. // check for a default button
  99. VPANEL panel = GetFocusNavGroup().GetCurrentDefaultButton();
  100. if (panel && ipanel()->IsVisible( panel ) && ipanel()->IsEnabled( panel ) && !IsConsoleStylePanel() )
  101. {
  102. // Activate the button
  103. PostMessage(panel, new KeyValues("Hotkey"));
  104. }
  105. else
  106. {
  107. BaseClass::OnKeyCodeTyped(code);
  108. }
  109. }
  110. else
  111. {
  112. BaseClass::OnKeyCodeTyped(code);
  113. }
  114. }
  115. //-----------------------------------------------------------------------------
  116. // Performs layout
  117. //-----------------------------------------------------------------------------
  118. void EditablePanel::PerformLayout()
  119. {
  120. BaseClass::PerformLayout( );
  121. int wide, tall;
  122. GetSize( wide, tall );
  123. for (int i = 0; i < GetChildCount(); i++)
  124. {
  125. // perform auto-layout on the child panel
  126. Panel *child = GetChild(i);
  127. if ( !child )
  128. continue;
  129. PinCorner_e pinCorner = child->GetPinCorner();
  130. AutoResize_e resize = child->GetAutoResize();
  131. if ( pinCorner == PIN_NO && resize == AUTORESIZE_NO )
  132. continue;
  133. int x, y, w, h;
  134. child->GetBounds( x, y, w, h );
  135. int px, py;
  136. child->GetPinOffset( px, py );
  137. int ox, oy;
  138. child->GetResizeOffset( ox, oy );
  139. int ex;
  140. int ey;
  141. bool bResizeHoriz = ( resize == AUTORESIZE_RIGHT || resize == AUTORESIZE_DOWNANDRIGHT );
  142. bool bResizeVert = ( resize == AUTORESIZE_DOWN || resize == AUTORESIZE_DOWNANDRIGHT );
  143. if ( pinCorner == PIN_TOPRIGHT || pinCorner == PIN_BOTTOMRIGHT )
  144. {
  145. // move along with the right edge
  146. ex = wide + px;
  147. x = bResizeHoriz ? ox : ex - w;
  148. }
  149. else
  150. {
  151. x = px;
  152. ex = bResizeHoriz ? wide + ox : px + w;
  153. }
  154. if ( pinCorner == PIN_BOTTOMLEFT || pinCorner == PIN_BOTTOMRIGHT )
  155. {
  156. // move along with the right edge
  157. ey = tall + py;
  158. y = bResizeVert ? oy : ey - h;
  159. }
  160. else
  161. {
  162. y = py;
  163. ey = bResizeVert ? tall + oy : py + h;
  164. }
  165. // Clamp..
  166. if ( ex < x )
  167. {
  168. ex = x;
  169. }
  170. if ( ey < y )
  171. {
  172. ey = y;
  173. }
  174. child->SetBounds( x, y, ex - x, ey - y );
  175. }
  176. }
  177. //-----------------------------------------------------------------------------
  178. // Purpose: Callback for when the panel size has been changed
  179. //-----------------------------------------------------------------------------
  180. void EditablePanel::OnSizeChanged(int wide, int tall)
  181. {
  182. BaseClass::OnSizeChanged(wide, tall);
  183. for (int i = 0; i < GetChildCount(); i++)
  184. {
  185. // perform auto-layout on the child panel
  186. Panel *child = GetChild(i);
  187. if ( !child )
  188. continue;
  189. if ( child->GetAutoResize() == AUTORESIZE_NO )
  190. continue;
  191. child->InvalidateLayout();
  192. }
  193. }
  194. //-----------------------------------------------------------------------------
  195. // Purpose:
  196. //-----------------------------------------------------------------------------
  197. void EditablePanel::OnCurrentDefaultButtonSet( VPANEL defaultButton )
  198. {
  199. m_NavGroup.SetCurrentDefaultButton( defaultButton, false );
  200. // forward the message up
  201. if (GetVParent())
  202. {
  203. KeyValues *msg = new KeyValues("CurrentDefaultButtonSet");
  204. msg->SetInt("button", ivgui()->PanelToHandle( defaultButton ) );
  205. PostMessage(GetVParent(), msg);
  206. }
  207. }
  208. //-----------------------------------------------------------------------------
  209. // Purpose:
  210. //-----------------------------------------------------------------------------
  211. void EditablePanel::OnDefaultButtonSet( VPANEL defaultButton )
  212. {
  213. Panel *panel = ipanel()->GetPanel( defaultButton, GetModuleName() );
  214. m_NavGroup.SetDefaultButton(panel);
  215. }
  216. //-----------------------------------------------------------------------------
  217. // Purpose:
  218. //-----------------------------------------------------------------------------
  219. void EditablePanel::OnFindDefaultButton()
  220. {
  221. if (m_NavGroup.GetDefaultButton())
  222. {
  223. m_NavGroup.SetCurrentDefaultButton(m_NavGroup.GetDefaultButton());
  224. }
  225. else
  226. {
  227. if (GetVParent())
  228. {
  229. PostMessage(GetVParent(), new KeyValues("FindDefaultButton"));
  230. }
  231. }
  232. }
  233. struct leaf_t
  234. {
  235. short x, y, wide, tall;
  236. unsigned char split; // 0 no split; 1 x-axis, 2 y-axis
  237. bool filled; // true if this is already filled
  238. short splitpos; // place of split
  239. leaf_t *left;
  240. leaf_t *right;
  241. };
  242. leaf_t g_Leaves[256];
  243. int g_iNextLeaf;
  244. inline leaf_t *AllocLeaf()
  245. {
  246. Assert(g_iNextLeaf < 255);
  247. return &g_Leaves[g_iNextLeaf++];
  248. }
  249. void AddSolidToTree(leaf_t *leaf, int x, int y, int wide, int tall)
  250. {
  251. // clip to this leaf
  252. if (x < leaf->x)
  253. {
  254. wide -= (leaf->x - x);
  255. if (wide < 1)
  256. return;
  257. x = leaf->x;
  258. }
  259. if (y < leaf->y)
  260. {
  261. tall -= (leaf->y - y);
  262. if (tall < 1)
  263. return;
  264. y = leaf->y;
  265. }
  266. if (x + wide > leaf->x + leaf->wide)
  267. {
  268. wide -= ((x + wide) - (leaf->x + leaf->wide));
  269. if (wide < 1)
  270. return;
  271. }
  272. if (y + tall > leaf->y + leaf->tall)
  273. {
  274. tall -= ((y + tall) - (leaf->y + leaf->tall));
  275. if (tall < 1)
  276. return;
  277. }
  278. // the rect should now be completely within the leaf
  279. if (leaf->split == 1)
  280. {
  281. // see if it is to the left or the right of the split
  282. if (x < leaf->splitpos)
  283. {
  284. // it's to the left
  285. AddSolidToTree(leaf->left, x, y, wide, tall);
  286. }
  287. else if (x + wide > leaf->splitpos)
  288. {
  289. // it's to the right
  290. AddSolidToTree(leaf->right, x, y, wide, tall);
  291. }
  292. }
  293. else if (leaf->split == 2)
  294. {
  295. // check y
  296. // see if it is to the left (above) or the right (below) of the split
  297. if (y < leaf->splitpos)
  298. {
  299. // it's above
  300. AddSolidToTree(leaf->left, x, y, wide, tall);
  301. }
  302. else if (y + tall > leaf->splitpos)
  303. {
  304. // it's below
  305. AddSolidToTree(leaf->right, x, y, wide, tall);
  306. }
  307. }
  308. else
  309. {
  310. // this leaf is unsplit, make the first split against the first edge we find
  311. if (x > leaf->x)
  312. {
  313. // split the left side of the rect
  314. leaf->split = 1;
  315. leaf->splitpos = (short)x;
  316. // create 2 new leaves
  317. leaf_t *left = AllocLeaf();
  318. leaf_t *right = AllocLeaf();
  319. memset(left, 0, sizeof(leaf_t));
  320. memset(right, 0, sizeof(leaf_t));
  321. leaf->left = left;
  322. leaf->right = right;
  323. left->x = leaf->x;
  324. left->y = leaf->y;
  325. left->wide = (short)(leaf->splitpos - leaf->x);
  326. left->tall = leaf->tall;
  327. right->x = leaf->splitpos;
  328. right->y = leaf->y;
  329. right->wide = (short)(leaf->wide - left->wide);
  330. right->tall = leaf->tall;
  331. // split the right leaf by the current rect
  332. AddSolidToTree(leaf->right, x, y, wide, tall);
  333. }
  334. else if (y > leaf->y)
  335. {
  336. // split the top edge
  337. leaf->split = 2;
  338. leaf->splitpos = (short)y;
  339. // create 2 new leaves (facing to the east)
  340. leaf_t *left = AllocLeaf();
  341. leaf_t *right = AllocLeaf();
  342. memset(left, 0, sizeof(leaf_t));
  343. memset(right, 0, sizeof(leaf_t));
  344. leaf->left = left;
  345. leaf->right = right;
  346. left->x = leaf->x;
  347. left->y = leaf->y;
  348. left->wide = leaf->wide;
  349. left->tall = (short)(y - leaf->y);
  350. right->x = leaf->x;
  351. right->y = leaf->splitpos;
  352. right->wide = leaf->wide;
  353. right->tall = (short)(leaf->tall + leaf->y - right->y);
  354. // split the right leaf by the current rect
  355. AddSolidToTree(leaf->right, x, y, wide, tall);
  356. }
  357. else if (x + wide < leaf->x + leaf->wide)
  358. {
  359. // split the right edge
  360. leaf->split = 1;
  361. leaf->splitpos = (short)(x + wide);
  362. // create 2 new leaves
  363. leaf_t *left = AllocLeaf();
  364. leaf_t *right = AllocLeaf();
  365. memset(left, 0, sizeof(leaf_t));
  366. memset(right, 0, sizeof(leaf_t));
  367. leaf->left = left;
  368. leaf->right = right;
  369. left->x = leaf->x;
  370. left->y = leaf->y;
  371. left->wide = (short)(leaf->splitpos - leaf->x);
  372. left->tall = leaf->tall;
  373. right->x = leaf->splitpos;
  374. right->y = leaf->y;
  375. right->wide = (short)(leaf->wide - left->wide);
  376. right->tall = leaf->tall;
  377. // split the left leaf by the current rect
  378. AddSolidToTree(leaf->left, x, y, wide, tall);
  379. }
  380. else if (y + tall < leaf->y + leaf->tall)
  381. {
  382. // split the bottom edge
  383. leaf->split = 2;
  384. leaf->splitpos = (short)(y + tall);
  385. // create 2 new leaves (facing to the east)
  386. leaf_t *left = AllocLeaf();
  387. leaf_t *right = AllocLeaf();
  388. memset(left, 0, sizeof(leaf_t));
  389. memset(right, 0, sizeof(leaf_t));
  390. leaf->left = left;
  391. leaf->right = right;
  392. left->x = leaf->x;
  393. left->y = leaf->y;
  394. left->wide = leaf->wide;
  395. left->tall = (short)(leaf->splitpos - leaf->y);
  396. right->x = leaf->x;
  397. right->y = leaf->splitpos;
  398. right->wide = leaf->wide;
  399. right->tall = (short)(leaf->tall - left->tall);
  400. // split the left leaf by the current rect
  401. AddSolidToTree(leaf->left, x, y, wide, tall);
  402. }
  403. else
  404. {
  405. // this is the exact same rect! don't draw this leaf
  406. leaf->filled = true;
  407. return;
  408. }
  409. }
  410. }
  411. //-----------------------------------------------------------------------------
  412. // Purpose: Fills the panel background, clipping if possible
  413. //-----------------------------------------------------------------------------
  414. void EditablePanel::PaintBackground()
  415. {
  416. BaseClass::PaintBackground();
  417. return;
  418. /*
  419. test code, using a screenspace bsp tree to reduce overdraw in vgui
  420. not yet fully functional
  421. // test: fill background with obnoxious color to show holes
  422. // surface()->DrawSetColor(Color(255, 0, 0, 255));
  423. // surface()->DrawFilledRect(0, 0, GetWide(), GetTall());
  424. // return;
  425. // reset the leaf memory
  426. g_iNextLeaf = 0;
  427. leaf_t *headNode = AllocLeaf();
  428. memset(headNode, 0, sizeof(leaf_t));
  429. headNode->wide = (short)GetWide();
  430. headNode->tall = (short)GetTall();
  431. // split the leaf by the first child
  432. for (int i = 0; i < GetChildCount(); i++)
  433. {
  434. Panel *child = GetChild(i);
  435. if (child->IsOpaque())
  436. {
  437. int x, y, wide, tall;
  438. child->GetBounds(x, y, wide, tall);
  439. // ignore small children
  440. if (wide + tall < 100)
  441. continue;
  442. AddSolidToTree(headNode, x, y, wide, tall);
  443. }
  444. }
  445. // walk the built tree, painting the background
  446. Color col = GetBgColor();
  447. surface()->DrawSetColor(col);
  448. for (i = 0; i < g_iNextLeaf; i++)
  449. {
  450. leaf_t *leaf = g_Leaves + i;
  451. if (leaf->splitpos || leaf->filled)
  452. continue;
  453. surface()->DrawFilledRect(leaf->x, leaf->y, leaf->x + leaf->wide, leaf->y + leaf->tall);
  454. }
  455. */
  456. }
  457. //-----------------------------------------------------------------------------
  458. // Purpose: Activates the build mode dialog for editing panels.
  459. //-----------------------------------------------------------------------------
  460. void EditablePanel::ActivateBuildMode()
  461. {
  462. _buildGroup->SetEnabled(true);
  463. }
  464. //-----------------------------------------------------------------------------
  465. // Purpose: Loads panel settings from a resource file.
  466. //-----------------------------------------------------------------------------
  467. void EditablePanel::LoadControlSettings(const char *resourceName, const char *pathID, KeyValues *pKeyValues, KeyValues *pConditions)
  468. {
  469. _buildGroup->LoadControlSettings(resourceName, pathID, pKeyValues, pConditions);
  470. ForceSubPanelsToUpdateWithNewDialogVariables();
  471. InvalidateLayout();
  472. }
  473. //-----------------------------------------------------------------------------
  474. // Purpose: registers a file in the list of control settings, so the vgui dialog can choose between them to edit
  475. //-----------------------------------------------------------------------------
  476. void EditablePanel::RegisterControlSettingsFile(const char *resourceName, const char *pathID)
  477. {
  478. _buildGroup->RegisterControlSettingsFile(resourceName, pathID);
  479. }
  480. //-----------------------------------------------------------------------------
  481. // Purpose: sets the name of this dialog so it can be saved in the user config area
  482. //-----------------------------------------------------------------------------
  483. void EditablePanel::LoadUserConfig(const char *configName, int dialogID)
  484. {
  485. KeyValues *data = system()->GetUserConfigFileData(configName, dialogID);
  486. delete [] m_pszConfigName;
  487. int len = Q_strlen(configName) + 1;
  488. m_pszConfigName = new char[ len ];
  489. Q_strncpy(m_pszConfigName, configName, len );
  490. m_iConfigID = dialogID;
  491. // apply our user config settings (this will recurse through our children)
  492. if (data)
  493. {
  494. ApplyUserConfigSettings(data);
  495. }
  496. }
  497. //-----------------------------------------------------------------------------
  498. // Purpose: saves all the settings to the document
  499. //-----------------------------------------------------------------------------
  500. void EditablePanel::SaveUserConfig()
  501. {
  502. if (m_pszConfigName)
  503. {
  504. KeyValues *data = system()->GetUserConfigFileData(m_pszConfigName, m_iConfigID);
  505. // get our user config settings (this will recurse through our children)
  506. if (data)
  507. {
  508. GetUserConfigSettings(data);
  509. }
  510. }
  511. }
  512. //-----------------------------------------------------------------------------
  513. // Purpose: combines both of the above, LoadControlSettings & LoadUserConfig
  514. //-----------------------------------------------------------------------------
  515. void EditablePanel::LoadControlSettingsAndUserConfig(const char *dialogResourceName, int dialogID)
  516. {
  517. LoadControlSettings(dialogResourceName);
  518. LoadUserConfig(dialogResourceName, dialogID);
  519. }
  520. //-----------------------------------------------------------------------------
  521. // Purpose: applies the user config settings to all the children
  522. //-----------------------------------------------------------------------------
  523. void EditablePanel::ApplyUserConfigSettings(KeyValues *userConfig)
  524. {
  525. for (int i = 0; i < GetChildCount(); i++)
  526. {
  527. Panel *child = GetChild(i);
  528. if (child->HasUserConfigSettings())
  529. {
  530. const char *name = child->GetName();
  531. if (name && *name)
  532. {
  533. child->ApplyUserConfigSettings(userConfig->FindKey(name, true));
  534. }
  535. }
  536. }
  537. }
  538. //-----------------------------------------------------------------------------
  539. // Purpose: gets all the children's user config settings
  540. //-----------------------------------------------------------------------------
  541. void EditablePanel::GetUserConfigSettings(KeyValues *userConfig)
  542. {
  543. for (int i = 0; i < GetChildCount(); i++)
  544. {
  545. Panel *child = GetChild(i);
  546. if (child->HasUserConfigSettings())
  547. {
  548. const char *name = child->GetName();
  549. if (name && *name)
  550. {
  551. child->GetUserConfigSettings(userConfig->FindKey(name, true));
  552. }
  553. }
  554. }
  555. }
  556. //-----------------------------------------------------------------------------
  557. // Purpose: Save user config settings
  558. //-----------------------------------------------------------------------------
  559. void EditablePanel::OnClose()
  560. {
  561. SaveUserConfig();
  562. }
  563. //-----------------------------------------------------------------------------
  564. // Purpose: Handle information requests
  565. //-----------------------------------------------------------------------------
  566. bool EditablePanel::RequestInfo(KeyValues *data)
  567. {
  568. if (!stricmp(data->GetName(), "BuildDialog"))
  569. {
  570. // a build dialog is being requested, give it one
  571. // a bit hacky, but this is a case where vgui.dll needs to reach out
  572. data->SetPtr("PanelPtr", new BuildModeDialog( (BuildGroup *)data->GetPtr("BuildGroupPtr")));
  573. return true;
  574. }
  575. else if (!stricmp(data->GetName(), "ControlFactory"))
  576. {
  577. Panel *newPanel = CreateControlByName(data->GetString("ControlName"));
  578. if (newPanel)
  579. {
  580. data->SetPtr("PanelPtr", newPanel);
  581. return true;
  582. }
  583. }
  584. return BaseClass::RequestInfo(data);
  585. }
  586. //-----------------------------------------------------------------------------
  587. // Purpose: Return the buildgroup that this panel is part of.
  588. // Input :
  589. // Output : BuildGroup
  590. //-----------------------------------------------------------------------------
  591. BuildGroup *EditablePanel::GetBuildGroup()
  592. {
  593. return _buildGroup;
  594. }
  595. //-----------------------------------------------------------------------------
  596. // Purpose: Return a pointer to the nav group
  597. // Output : FocusNavGroup
  598. //-----------------------------------------------------------------------------
  599. FocusNavGroup &EditablePanel::GetFocusNavGroup()
  600. {
  601. return m_NavGroup;
  602. }
  603. //-----------------------------------------------------------------------------
  604. // Purpose:
  605. //-----------------------------------------------------------------------------
  606. bool EditablePanel::RequestFocusNext(VPANEL panel)
  607. {
  608. bool bRet = m_NavGroup.RequestFocusNext(panel);
  609. if ( IsPC() && !bRet && IsConsoleStylePanel() )
  610. {
  611. NavigateDown();
  612. }
  613. return bRet;
  614. }
  615. //-----------------------------------------------------------------------------
  616. // Purpose:
  617. //-----------------------------------------------------------------------------
  618. bool EditablePanel::RequestFocusPrev(VPANEL panel)
  619. {
  620. bool bRet = m_NavGroup.RequestFocusPrev(panel);
  621. if ( IsPC() && !bRet && IsConsoleStylePanel() )
  622. {
  623. NavigateUp();
  624. }
  625. return bRet;
  626. }
  627. //-----------------------------------------------------------------------------
  628. // Purpose: Delegates focus to a sub panel
  629. // Input : direction - the direction in which focus travelled to arrive at this panel; forward = 1, back = -1
  630. //-----------------------------------------------------------------------------
  631. void EditablePanel::RequestFocus(int direction)
  632. {
  633. // we must be a sub panel for this to be called
  634. // delegate focus
  635. if (direction == 1)
  636. {
  637. RequestFocusNext(NULL);
  638. }
  639. else if (direction == -1)
  640. {
  641. RequestFocusPrev(NULL);
  642. }
  643. else
  644. {
  645. BaseClass::RequestFocus();
  646. }
  647. }
  648. //-----------------------------------------------------------------------------
  649. // Purpose: Pass the focus down onto the last used panel
  650. //-----------------------------------------------------------------------------
  651. void EditablePanel::OnSetFocus()
  652. {
  653. Panel *focus = m_NavGroup.GetCurrentFocus();
  654. if (focus && focus != this)
  655. {
  656. focus->RequestFocus();
  657. }
  658. else
  659. {
  660. focus = m_NavGroup.GetDefaultPanel();
  661. if (focus)
  662. {
  663. focus->RequestFocus();
  664. focus->OnSetFocus();
  665. }
  666. }
  667. BaseClass::OnSetFocus();
  668. }
  669. //-----------------------------------------------------------------------------
  670. // Purpose: Called when the resource file is loaded to set up the panel state
  671. // Input : *inResourceData -
  672. //-----------------------------------------------------------------------------
  673. void EditablePanel::ApplySettings(KeyValues *inResourceData)
  674. {
  675. BaseClass::ApplySettings(inResourceData);
  676. _buildGroup->ApplySettings(inResourceData);
  677. }
  678. //-----------------------------------------------------------------------------
  679. // Purpose: Update focus info for navigation
  680. //-----------------------------------------------------------------------------
  681. void EditablePanel::OnRequestFocus(VPANEL subFocus, VPANEL defaultPanel)
  682. {
  683. if (!ipanel()->IsPopup(subFocus))
  684. {
  685. defaultPanel = m_NavGroup.SetCurrentFocus(subFocus, defaultPanel);
  686. }
  687. BaseClass::OnRequestFocus(GetVPanel(), defaultPanel);
  688. }
  689. //-----------------------------------------------------------------------------
  690. // Purpose: Get the panel that currently has keyfocus
  691. //-----------------------------------------------------------------------------
  692. VPANEL EditablePanel::GetCurrentKeyFocus()
  693. {
  694. Panel *focus = m_NavGroup.GetCurrentFocus();
  695. if (focus == this)
  696. return NULL;
  697. if (focus)
  698. {
  699. if (focus->IsPopup())
  700. return BaseClass::GetCurrentKeyFocus();
  701. // chain down the editpanel hierarchy
  702. VPANEL subFocus = focus->GetCurrentKeyFocus();
  703. if (subFocus)
  704. return subFocus;
  705. // hit a leaf panel, return that
  706. return focus->GetVPanel();
  707. }
  708. return BaseClass::GetCurrentKeyFocus();
  709. }
  710. //-----------------------------------------------------------------------------
  711. // Purpose: Gets the panel with the specified hotkey
  712. //-----------------------------------------------------------------------------
  713. Panel *EditablePanel::HasHotkey(wchar_t key)
  714. {
  715. if( !IsVisible() || !IsEnabled()) // not visible, so can't respond to a hot key
  716. {
  717. return NULL;
  718. }
  719. for (int i = 0; i < GetChildCount(); i++)
  720. {
  721. Panel *hot = GetChild(i)->HasHotkey(key);
  722. if (hot && hot->IsVisible() && hot->IsEnabled())
  723. {
  724. return hot;
  725. }
  726. }
  727. return NULL;
  728. }
  729. //-----------------------------------------------------------------------------
  730. // Purpose: Shortcut function to setting enabled state of control
  731. //-----------------------------------------------------------------------------
  732. void EditablePanel::SetControlEnabled(const char *controlName, bool enabled)
  733. {
  734. Panel *control = FindChildByName(controlName);
  735. if (control)
  736. {
  737. control->SetEnabled(enabled);
  738. }
  739. }
  740. //-----------------------------------------------------------------------------
  741. // Purpose: Shortcut function to setting visibility state of control
  742. //-----------------------------------------------------------------------------
  743. void EditablePanel::SetControlVisible(const char *controlName, bool visible)
  744. {
  745. Panel *control = FindChildByName(controlName);
  746. if (control)
  747. {
  748. control->SetVisible(visible);
  749. }
  750. }
  751. //-----------------------------------------------------------------------------
  752. // Purpose: Shortcut function to set data in child controls
  753. //-----------------------------------------------------------------------------
  754. void EditablePanel::SetControlString(const char *controlName, const char *string)
  755. {
  756. Panel *control = FindChildByName(controlName);
  757. if (control)
  758. {
  759. if (string[0] == '#')
  760. {
  761. const wchar_t *wszText = g_pVGuiLocalize->Find(string);
  762. if (wszText)
  763. {
  764. PostMessage(control, new KeyValues("SetText", "text", wszText));
  765. }
  766. }
  767. else
  768. {
  769. PostMessage(control, new KeyValues("SetText", "text", string));
  770. }
  771. }
  772. }
  773. //-----------------------------------------------------------------------------
  774. // Purpose: Shortcut function to set data in child controls
  775. //-----------------------------------------------------------------------------
  776. void EditablePanel::SetControlString(const char *controlName, const wchar_t *string)
  777. {
  778. Panel *control = FindChildByName(controlName);
  779. if (control)
  780. {
  781. PostMessage(control, new KeyValues("SetText", "text", string));
  782. }
  783. }
  784. //-----------------------------------------------------------------------------
  785. // Purpose: Shortcut function to set data in child controls
  786. //-----------------------------------------------------------------------------
  787. void EditablePanel::SetControlInt(const char *controlName, int state)
  788. {
  789. Panel *control = FindChildByName(controlName);
  790. if (control)
  791. {
  792. PostMessage(control, new KeyValues("SetState", "state", state));
  793. }
  794. }
  795. //-----------------------------------------------------------------------------
  796. // Purpose: Shortcut function to get data in child controls
  797. //-----------------------------------------------------------------------------
  798. int EditablePanel::GetControlInt(const char *controlName, int defaultState)
  799. {
  800. Panel *control = FindChildByName(controlName);
  801. if (control)
  802. {
  803. KeyValues *data = new KeyValues("GetState");
  804. if (control->RequestInfo(data))
  805. {
  806. int state = data->GetInt("state", defaultState);
  807. data->deleteThis();
  808. return state;
  809. }
  810. }
  811. return defaultState;
  812. }
  813. //-----------------------------------------------------------------------------
  814. // Purpose: Shortcut function to get data in child controls
  815. //-----------------------------------------------------------------------------
  816. const char *EditablePanel::GetControlString(const char *controlName, const char *defaultString)
  817. {
  818. static char buf[512];
  819. GetControlString(controlName, buf, sizeof(buf) - 1, defaultString);
  820. return buf;
  821. }
  822. //-----------------------------------------------------------------------------
  823. // Purpose: Shortcut function to get data in child controls
  824. //-----------------------------------------------------------------------------
  825. void EditablePanel::GetControlString(const char *controlName, char *buf, int bufSize, const char *defaultString)
  826. {
  827. Panel *control = FindChildByName(controlName);
  828. KeyValues *data = new KeyValues("GetText");
  829. if (control && control->RequestInfo(data))
  830. {
  831. Q_strncpy(buf, data->GetString("text", defaultString), bufSize);
  832. }
  833. else
  834. {
  835. // no value found, copy in default text
  836. Q_strncpy(buf, defaultString, bufSize);
  837. }
  838. // ensure null termination of string
  839. buf[bufSize - 1] = 0;
  840. // free
  841. data->deleteThis();
  842. }
  843. //-----------------------------------------------------------------------------
  844. // Purpose: localization variables (used in constructing UI strings)
  845. //-----------------------------------------------------------------------------
  846. void EditablePanel::SetDialogVariable(const char *varName, const char *value)
  847. {
  848. GetDialogVariables()->SetString(varName, value);
  849. ForceSubPanelsToUpdateWithNewDialogVariables();
  850. }
  851. //-----------------------------------------------------------------------------
  852. // Purpose: localization variables (used in constructing UI strings)
  853. //-----------------------------------------------------------------------------
  854. void EditablePanel::SetDialogVariable(const char *varName, const wchar_t *value)
  855. {
  856. GetDialogVariables()->SetWString(varName, value);
  857. ForceSubPanelsToUpdateWithNewDialogVariables();
  858. }
  859. //-----------------------------------------------------------------------------
  860. // Purpose: localization variables (used in constructing UI strings)
  861. //-----------------------------------------------------------------------------
  862. void EditablePanel::SetDialogVariable(const char *varName, int value)
  863. {
  864. GetDialogVariables()->SetInt(varName, value);
  865. ForceSubPanelsToUpdateWithNewDialogVariables();
  866. }
  867. //-----------------------------------------------------------------------------
  868. // Purpose: localization variables (used in constructing UI strings)
  869. //-----------------------------------------------------------------------------
  870. void EditablePanel::SetDialogVariable(const char *varName, float value)
  871. {
  872. GetDialogVariables()->SetFloat(varName, value);
  873. ForceSubPanelsToUpdateWithNewDialogVariables();
  874. }
  875. //-----------------------------------------------------------------------------
  876. // Purpose: redraws child panels with new localization vars
  877. //-----------------------------------------------------------------------------
  878. void EditablePanel::ForceSubPanelsToUpdateWithNewDialogVariables()
  879. {
  880. if (m_pDialogVariables)
  881. {
  882. ipanel()->SendMessage(GetVPanel(), m_pDialogVariables, GetVPanel());
  883. for (int i = 0; i < ipanel()->GetChildCount(GetVPanel()); i++)
  884. {
  885. ipanel()->SendMessage(ipanel()->GetChild(GetVPanel(), i), m_pDialogVariables, GetVPanel());
  886. }
  887. }
  888. }
  889. //-----------------------------------------------------------------------------
  890. // Purpose: lazy creation of localization vars object
  891. //-----------------------------------------------------------------------------
  892. KeyValues *EditablePanel::GetDialogVariables()
  893. {
  894. if (m_pDialogVariables)
  895. return m_pDialogVariables;
  896. m_pDialogVariables = new KeyValues("DialogVariables");
  897. return m_pDialogVariables;
  898. }
  899. //-----------------------------------------------------------------------------
  900. // Purpose: Virtual factory for control creation
  901. //-----------------------------------------------------------------------------
  902. Panel *EditablePanel::CreateControlByName(const char *controlName)
  903. {
  904. Panel *fromFactory = CBuildFactoryHelper::InstancePanel( controlName );
  905. if ( fromFactory )
  906. {
  907. return fromFactory;
  908. }
  909. return NULL;
  910. }