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.

720 lines
19 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include <vgui/IVGui.h>
  8. #include <keyvalues.h>
  9. #include <vgui_controls/BuildGroup.h>
  10. #include <vgui_controls/Button.h>
  11. #include <vgui_controls/Controls.h>
  12. #include <vgui_controls/WizardPanel.h>
  13. #include <vgui_controls/WizardSubPanel.h>
  14. // memdbgon must be the last include file in a .cpp file!!!
  15. #include <tier0/memdbgon.h>
  16. using namespace vgui;
  17. //-----------------------------------------------------------------------------
  18. // Purpose: Constructor
  19. //-----------------------------------------------------------------------------
  20. WizardPanel::WizardPanel(Panel *parent, const char *panelName) : Frame(parent, panelName)
  21. {
  22. _currentSubPanel = NULL;
  23. _currentData = new KeyValues("WizardData");
  24. _showButtons = true;
  25. SetSizeable(false);
  26. CreateButtons();
  27. }
  28. //-----------------------------------------------------------------------------
  29. // Purpose: Destructor
  30. //-----------------------------------------------------------------------------
  31. WizardPanel::~WizardPanel()
  32. {
  33. if (_currentData)
  34. {
  35. _currentData->deleteThis();
  36. }
  37. }
  38. //-----------------------------------------------------------------------------
  39. // Purpose:
  40. //-----------------------------------------------------------------------------
  41. void WizardPanel::PerformLayout()
  42. {
  43. BaseClass::PerformLayout();
  44. // resize the sub panel to fit in the Client area
  45. int x, y, wide, tall;
  46. GetClientArea(x, y, wide, tall);
  47. if (_currentSubPanel && _currentSubPanel->isNonWizardPanel())
  48. {
  49. // just have the subpanel cover the full size
  50. _currentSubPanel->SetBounds(x, y, wide, tall);
  51. _cancelButton->SetVisible(false);
  52. _prevButton->SetVisible(false);
  53. _nextButton->SetVisible(false);
  54. _finishButton->SetVisible(false);
  55. }
  56. else
  57. {
  58. // make room for the buttons at bottom
  59. if (_currentSubPanel)
  60. {
  61. if( _showButtons )
  62. {
  63. _currentSubPanel->SetBounds(x, y, wide, tall - 35);
  64. }
  65. else
  66. {
  67. _currentSubPanel->SetBounds(x, y, wide, tall);
  68. }
  69. }
  70. // align the buttons to the right hand side
  71. GetSize(wide, tall);
  72. int bwide, btall;
  73. _cancelButton->GetSize(bwide, btall);
  74. x = wide - (20 + bwide);
  75. y = tall - (12 + btall);
  76. _cancelButton->SetPos(x, y);
  77. x -= (20 + bwide);
  78. // only display one of the next or finish buttons (and only if both are visible)
  79. if ( _showButtons )
  80. {
  81. if (_finishButton->IsEnabled() )
  82. {
  83. _nextButton->SetVisible(false);
  84. _finishButton->SetVisible(true);
  85. _finishButton->SetPos(x, y);
  86. }
  87. else
  88. {
  89. _nextButton->SetVisible(true);
  90. _finishButton->SetVisible(false);
  91. _nextButton->SetPos(x, y);
  92. }
  93. }
  94. x -= (1 + bwide);
  95. _prevButton->SetPos(x, y);
  96. ResetDefaultButton();
  97. }
  98. }
  99. //-----------------------------------------------------------------------------
  100. // Purpose: if we don't show buttons then let the sub panel occupy the whole screen
  101. //-----------------------------------------------------------------------------
  102. void WizardPanel::GetClientArea(int &x, int &y, int &wide, int &tall)
  103. {
  104. if( _showButtons )
  105. {
  106. BaseClass::GetClientArea( x, y, wide, tall );
  107. }
  108. else
  109. {
  110. x = 0;
  111. y = 0;
  112. GetSize( wide, tall );
  113. }
  114. }
  115. //-----------------------------------------------------------------------------
  116. // Purpose:
  117. //-----------------------------------------------------------------------------
  118. void WizardPanel::ApplySchemeSettings(IScheme *pScheme)
  119. {
  120. BaseClass::ApplySchemeSettings(pScheme);
  121. }
  122. //-----------------------------------------------------------------------------
  123. // Purpose:
  124. //-----------------------------------------------------------------------------
  125. void WizardPanel::Run(WizardSubPanel *startPanel)
  126. {
  127. // skip over sub panels if they don't want to be displayed
  128. startPanel = FindNextValidSubPanel(startPanel);
  129. // show it
  130. ActivateNextSubPanel(startPanel);
  131. // make sure we're set up and Run the first panel
  132. Activate();
  133. }
  134. //-----------------------------------------------------------------------------
  135. // Purpose:
  136. //-----------------------------------------------------------------------------
  137. void WizardPanel::ActivateBuildMode()
  138. {
  139. // no subpanel, no build mode
  140. if (!_currentSubPanel)
  141. return;
  142. _currentSubPanel->ActivateBuildMode();
  143. }
  144. //-----------------------------------------------------------------------------
  145. // Purpose:
  146. //-----------------------------------------------------------------------------
  147. void WizardPanel::ResetDefaultButton()
  148. {
  149. // work out which is the default button
  150. if (_nextButton->IsEnabled())
  151. {
  152. _nextButton->SetAsDefaultButton(true);
  153. }
  154. else if (_finishButton->IsEnabled())
  155. {
  156. _finishButton->SetAsDefaultButton(true);
  157. }
  158. else if (_prevButton->IsEnabled())
  159. {
  160. _prevButton->SetAsDefaultButton(true);
  161. }
  162. /* Don't ever set the cancel button as the default, as it is too easy for users to quit the wizard without realizing
  163. else if (_cancelButton->IsEnabled())
  164. {
  165. _cancelButton->SetAsDefaultButton(true);
  166. }
  167. */
  168. // reset them all (this may not be necessary)
  169. _nextButton->InvalidateLayout();
  170. _prevButton->InvalidateLayout();
  171. _cancelButton->InvalidateLayout();
  172. _finishButton->InvalidateLayout();
  173. Repaint();
  174. }
  175. //-----------------------------------------------------------------------------
  176. // Purpose:
  177. //-----------------------------------------------------------------------------
  178. void WizardPanel::ResetKeyFocus()
  179. {
  180. // set the focus on the default
  181. FocusNavGroup &navGroup = GetFocusNavGroup();
  182. Panel *def = navGroup.GetDefaultPanel();
  183. if (def)
  184. {
  185. if (def->IsEnabled() && def->IsVisible())
  186. {
  187. def->RequestFocus();
  188. }
  189. else
  190. {
  191. def->RequestFocusNext();
  192. }
  193. }
  194. ResetDefaultButton();
  195. }
  196. //-----------------------------------------------------------------------------
  197. // Purpose:
  198. //-----------------------------------------------------------------------------
  199. void WizardPanel::CreateButtons()
  200. {
  201. _prevButton = new Button(this, "PrevButton", "");
  202. _nextButton = new Button(this, "NextButton", "");
  203. _cancelButton = new Button(this, "CancelButton", "");
  204. _finishButton = new Button(this, "FinishButton", "");
  205. _prevButton->SetCommand(new KeyValues("PrevButton"));
  206. _nextButton->SetCommand(new KeyValues("NextButton"));
  207. _cancelButton->SetCommand(new KeyValues("CancelButton"));
  208. _finishButton->SetCommand(new KeyValues("FinishButton"));
  209. SetNextButtonText(NULL);
  210. SetPrevButtonText(NULL);
  211. SetFinishButtonText(NULL);
  212. SetCancelButtonText(NULL);
  213. _prevButton->SetSize(82, 24);
  214. _nextButton->SetSize(82, 24);
  215. _cancelButton->SetSize(82, 24);
  216. _finishButton->SetSize(82, 24);
  217. }
  218. //-----------------------------------------------------------------------------
  219. // Purpose: clears all previous history
  220. //-----------------------------------------------------------------------------
  221. void WizardPanel::ResetHistory()
  222. {
  223. _subPanelStack.RemoveAll();
  224. }
  225. //-----------------------------------------------------------------------------
  226. // Purpose:
  227. //-----------------------------------------------------------------------------
  228. void WizardPanel::ActivateNextSubPanel(WizardSubPanel *subPanel)
  229. {
  230. // get rid of previous panel
  231. WizardSubPanel *prevPanel = _currentSubPanel;
  232. if (prevPanel && prevPanel->ShouldDisplayPanel())
  233. {
  234. // hide
  235. prevPanel->SetVisible(false);
  236. // push onto history stack
  237. _subPanelStack.AddElement(_currentSubPanel);
  238. }
  239. // reenable all buttons, returning them to their default state
  240. _prevButton->SetEnabled(true);
  241. _nextButton->SetEnabled(true);
  242. _cancelButton->SetEnabled(true);
  243. _finishButton->SetEnabled(true);
  244. if ( _showButtons )
  245. {
  246. _prevButton->SetVisible(true);
  247. _cancelButton->SetVisible(true);
  248. }
  249. // set up new subpanel
  250. _currentSubPanel = subPanel;
  251. _currentSubPanel->SetParent(this);
  252. _currentSubPanel->SetVisible(true);
  253. _currentSubPanel->SetWizardPanel(this);
  254. _currentSubPanel->OnDisplayAsNext();
  255. _currentSubPanel->OnDisplay();
  256. _currentSubPanel->InvalidateLayout(false);
  257. SETUP_PANEL( _currentSubPanel );
  258. int wide, tall;
  259. if ( _currentSubPanel->GetDesiredSize(wide, tall) )
  260. {
  261. SetSize(wide, tall);
  262. }
  263. if (!prevPanel)
  264. {
  265. // no previous panel, so disable the back button
  266. _prevButton->SetEnabled(false);
  267. }
  268. _currentSubPanel->RequestFocus();
  269. RecalculateTabOrdering();
  270. InvalidateLayout(false);
  271. Repaint();
  272. }
  273. //-----------------------------------------------------------------------------
  274. // Purpose: Pops the last panel off the stack and runs it
  275. //-----------------------------------------------------------------------------
  276. void WizardPanel::ActivatePrevSubPanel()
  277. {
  278. _currentSubPanel->SetVisible(false);
  279. WizardSubPanel *prevPanel = NULL;
  280. if (_subPanelStack.GetCount())
  281. {
  282. // check to see if we need to jump back to a previous sub panel
  283. WizardSubPanel *searchPanel = _currentSubPanel->GetPrevSubPanel();
  284. if (searchPanel && _subPanelStack.HasElement(searchPanel))
  285. {
  286. // keep poping the stack till we find it
  287. while (_subPanelStack.GetCount() && prevPanel != searchPanel)
  288. {
  289. prevPanel = _subPanelStack[_subPanelStack.GetCount() - 1];
  290. _subPanelStack.RemoveElementAt(_subPanelStack.GetCount() - 1);
  291. }
  292. }
  293. else
  294. {
  295. // just get the last one
  296. prevPanel = _subPanelStack[_subPanelStack.GetCount() - 1];
  297. _subPanelStack.RemoveElementAt(_subPanelStack.GetCount() - 1);
  298. }
  299. }
  300. if (!prevPanel)
  301. {
  302. ivgui()->DPrintf2("Error: WizardPanel::ActivatePrevSubPanel(): no previous panel to go back to\n");
  303. return;
  304. }
  305. // hide old panel
  306. _currentSubPanel->SetVisible(false);
  307. // reenable all buttons, returning them to their default state
  308. _prevButton->SetEnabled(true);
  309. _nextButton->SetEnabled(true);
  310. _cancelButton->SetEnabled(true);
  311. _finishButton->SetEnabled(true);
  312. // Activate new panel
  313. _currentSubPanel = prevPanel;
  314. _currentSubPanel->RequestFocus();
  315. _currentSubPanel->SetWizardPanel(this);
  316. _currentSubPanel->OnDisplayAsPrev();
  317. _currentSubPanel->OnDisplay();
  318. _currentSubPanel->InvalidateLayout(false);
  319. SETUP_PANEL( _currentSubPanel );
  320. int wide, tall;
  321. if ( _currentSubPanel->GetDesiredSize(wide, tall) )
  322. {
  323. SetSize(wide, tall);
  324. }
  325. // show the previous panel, but don't Activate it (since it should show just what it was previously)
  326. _currentSubPanel->SetVisible(true);
  327. if (!_subPanelStack.GetCount())
  328. {
  329. // no previous panel, so disable the back button
  330. _prevButton->SetEnabled(false);
  331. }
  332. RecalculateTabOrdering();
  333. InvalidateLayout(false);
  334. Repaint();
  335. }
  336. //-----------------------------------------------------------------------------
  337. // Purpose: Sets up the new tab ordering
  338. //-----------------------------------------------------------------------------
  339. void WizardPanel::RecalculateTabOrdering()
  340. {
  341. if (_currentSubPanel)
  342. {
  343. _currentSubPanel->SetTabPosition(1);
  344. }
  345. _prevButton->SetTabPosition(2);
  346. _nextButton->SetTabPosition(3);
  347. _finishButton->SetTabPosition(4);
  348. _cancelButton->SetTabPosition(5);
  349. }
  350. //-----------------------------------------------------------------------------
  351. // Purpose:
  352. //-----------------------------------------------------------------------------
  353. void WizardPanel::SetNextButtonEnabled(bool state)
  354. {
  355. if (_nextButton->IsEnabled() != state)
  356. {
  357. _nextButton->SetEnabled(state);
  358. InvalidateLayout(false);
  359. }
  360. }
  361. //-----------------------------------------------------------------------------
  362. // Purpose:
  363. //-----------------------------------------------------------------------------
  364. void WizardPanel::SetPrevButtonEnabled(bool state)
  365. {
  366. if (_prevButton->IsEnabled() != state)
  367. {
  368. _prevButton->SetEnabled(state);
  369. InvalidateLayout(false);
  370. }
  371. }
  372. //-----------------------------------------------------------------------------
  373. // Purpose:
  374. //-----------------------------------------------------------------------------
  375. void WizardPanel::SetFinishButtonEnabled(bool state)
  376. {
  377. if (_finishButton->IsEnabled() != state)
  378. {
  379. _finishButton->SetEnabled(state);
  380. InvalidateLayout(false);
  381. }
  382. }
  383. //-----------------------------------------------------------------------------
  384. // Purpose:
  385. //-----------------------------------------------------------------------------
  386. void WizardPanel::SetCancelButtonEnabled(bool state)
  387. {
  388. if (_cancelButton->IsEnabled() != state)
  389. {
  390. _cancelButton->SetEnabled(state);
  391. InvalidateLayout(false);
  392. }
  393. }
  394. //-----------------------------------------------------------------------------
  395. // Purpose:
  396. //-----------------------------------------------------------------------------
  397. void WizardPanel::SetNextButtonVisible(bool state)
  398. {
  399. _nextButton->SetVisible(state);
  400. }
  401. //-----------------------------------------------------------------------------
  402. // Purpose:
  403. //-----------------------------------------------------------------------------
  404. void WizardPanel::SetPrevButtonVisible(bool state)
  405. {
  406. _prevButton->SetVisible(state);
  407. }
  408. //-----------------------------------------------------------------------------
  409. // Purpose:
  410. //-----------------------------------------------------------------------------
  411. void WizardPanel::SetFinishButtonVisible(bool state)
  412. {
  413. _finishButton->SetVisible(state);
  414. }
  415. //-----------------------------------------------------------------------------
  416. // Purpose:
  417. //-----------------------------------------------------------------------------
  418. void WizardPanel::SetCancelButtonVisible(bool state)
  419. {
  420. _cancelButton->SetVisible(state);
  421. }
  422. //-----------------------------------------------------------------------------
  423. // Purpose:
  424. //-----------------------------------------------------------------------------
  425. void WizardPanel::SetNextButtonText(const char *text)
  426. {
  427. if (text)
  428. {
  429. _nextButton->SetText(text);
  430. }
  431. else
  432. {
  433. _nextButton->SetText("#WizardPanel_Next");
  434. }
  435. }
  436. //-----------------------------------------------------------------------------
  437. // Purpose:
  438. //-----------------------------------------------------------------------------
  439. void WizardPanel::SetPrevButtonText(const char *text)
  440. {
  441. if (text)
  442. {
  443. _prevButton->SetText(text);
  444. }
  445. else
  446. {
  447. _prevButton->SetText("#WizardPanel_Back");
  448. }
  449. }
  450. //-----------------------------------------------------------------------------
  451. // Purpose:
  452. //-----------------------------------------------------------------------------
  453. void WizardPanel::SetFinishButtonText(const char *text)
  454. {
  455. if (text)
  456. {
  457. _finishButton->SetText(text);
  458. }
  459. else
  460. {
  461. _finishButton->SetText("#WizardPanel_Finish");
  462. }
  463. }
  464. //-----------------------------------------------------------------------------
  465. // Purpose:
  466. //-----------------------------------------------------------------------------
  467. void WizardPanel::SetCancelButtonText(const char *text)
  468. {
  469. if (text)
  470. {
  471. _cancelButton->SetText(text);
  472. }
  473. else
  474. {
  475. _cancelButton->SetText("#WizardPanel_Cancel");
  476. }
  477. }
  478. //-----------------------------------------------------------------------------
  479. // Purpose: Finds the next panel that wants to be shown
  480. //-----------------------------------------------------------------------------
  481. WizardSubPanel *WizardPanel::FindNextValidSubPanel(WizardSubPanel *currentPanel)
  482. {
  483. // skip over sub panels if they don't want to be displayed
  484. while (currentPanel)
  485. {
  486. currentPanel->SetWizardPanel(this);
  487. if (currentPanel->ShouldDisplayPanel())
  488. break;
  489. // ok the panel wants to be skipped, so skip ahead
  490. currentPanel = currentPanel->GetNextSubPanel();
  491. }
  492. return currentPanel;
  493. }
  494. //-----------------------------------------------------------------------------
  495. // Purpose: Advances to the next panel
  496. //-----------------------------------------------------------------------------
  497. void WizardPanel::OnNextButton()
  498. {
  499. if (_currentSubPanel)
  500. {
  501. bool shouldAdvance = _currentSubPanel->OnNextButton();
  502. if (shouldAdvance)
  503. {
  504. WizardSubPanel *nextPanel = FindNextValidSubPanel(_currentSubPanel->GetNextSubPanel());
  505. if (nextPanel)
  506. {
  507. KeyValues *kv = new KeyValues("ActivateNextSubPanel");
  508. kv->SetPtr("panel", nextPanel);
  509. ivgui()->PostMessage(GetVPanel(), kv, GetVPanel());
  510. }
  511. }
  512. }
  513. }
  514. //-----------------------------------------------------------------------------
  515. // Purpose: Retreats to the previous panel
  516. //-----------------------------------------------------------------------------
  517. void WizardPanel::OnPrevButton()
  518. {
  519. bool shouldRetreat = true;
  520. if (_currentSubPanel)
  521. {
  522. shouldRetreat = _currentSubPanel->OnPrevButton();
  523. }
  524. if (shouldRetreat)
  525. {
  526. ActivatePrevSubPanel();
  527. }
  528. }
  529. //-----------------------------------------------------------------------------
  530. // Purpose:
  531. //-----------------------------------------------------------------------------
  532. void WizardPanel::OnFinishButton()
  533. {
  534. if (_currentSubPanel && _currentSubPanel->OnFinishButton())
  535. {
  536. // hide ourselves away
  537. BaseClass::OnClose();
  538. // automatically delete ourselves if marked to do so
  539. if (IsAutoDeleteSet())
  540. {
  541. MarkForDeletion();
  542. }
  543. }
  544. }
  545. //-----------------------------------------------------------------------------
  546. // Purpose:
  547. //-----------------------------------------------------------------------------
  548. void WizardPanel::OnCancelButton()
  549. {
  550. if (_currentSubPanel && _currentSubPanel->OnCancelButton())
  551. {
  552. // hide ourselves away
  553. BaseClass::OnClose();
  554. if (IsAutoDeleteSet())
  555. {
  556. MarkForDeletion();
  557. }
  558. }
  559. }
  560. //-----------------------------------------------------------------------------
  561. // Purpose: command handler for catching escape key presses
  562. //-----------------------------------------------------------------------------
  563. void WizardPanel::OnCommand(const char *command)
  564. {
  565. if (!stricmp(command, "Cancel"))
  566. {
  567. if (_cancelButton->IsEnabled())
  568. {
  569. _cancelButton->DoClick();
  570. }
  571. }
  572. else
  573. {
  574. BaseClass::OnCommand(command);
  575. }
  576. }
  577. //-----------------------------------------------------------------------------
  578. // Purpose: Maps close button to cancel button
  579. //-----------------------------------------------------------------------------
  580. void WizardPanel::OnClose()
  581. {
  582. if (_cancelButton->IsEnabled())
  583. {
  584. _cancelButton->DoClick();
  585. }
  586. else if (_finishButton->IsEnabled())
  587. {
  588. _finishButton->DoClick();
  589. }
  590. // don't chain back
  591. }
  592. //-----------------------------------------------------------------------------
  593. // Purpose:
  594. //-----------------------------------------------------------------------------
  595. KeyValues *WizardPanel::GetWizardData()
  596. {
  597. return _currentData;
  598. }
  599. //-----------------------------------------------------------------------------
  600. // Purpose: whether to show the next,prev,finish and cancel buttons
  601. //-----------------------------------------------------------------------------
  602. void WizardPanel::ShowButtons(bool state)
  603. {
  604. _showButtons = state; // hide the wizard panel buttons
  605. SetNextButtonVisible( state );
  606. SetPrevButtonVisible( state );
  607. SetFinishButtonVisible( state );
  608. SetCancelButtonVisible( state );
  609. }
  610. //-----------------------------------------------------------------------------
  611. // Purpose: filters close buttons
  612. //-----------------------------------------------------------------------------
  613. void WizardPanel::OnCloseFrameButtonPressed()
  614. {
  615. // only allow close if the cancel button is enabled
  616. if (_cancelButton->IsEnabled())
  617. {
  618. BaseClass::OnCloseFrameButtonPressed();
  619. }
  620. }
  621. //-----------------------------------------------------------------------------
  622. // Purpose: returns a page by name
  623. //-----------------------------------------------------------------------------
  624. WizardSubPanel *WizardPanel::GetSubPanelByName(const char *pageName)
  625. {
  626. return dynamic_cast<WizardSubPanel *>(FindChildByName(pageName));
  627. }