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.

1440 lines
38 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include <ctype.h>
  8. #include <stdio.h>
  9. #include <utlvector.h>
  10. #include <vgui/IInput.h>
  11. #include <vgui/ILocalize.h>
  12. #include <vgui/ISurface.h>
  13. #include <vgui/ISystem.h>
  14. #include <vgui/KeyCode.h>
  15. #include <KeyValues.h>
  16. #include <vgui/MouseCode.h>
  17. #include <vgui_controls/BuildModeDialog.h>
  18. #include <vgui_controls/Label.h>
  19. #include <vgui_controls/TextEntry.h>
  20. #include <vgui_controls/Button.h>
  21. #include <vgui_controls/CheckButton.h>
  22. #include <vgui_controls/RadioButton.h>
  23. #include <vgui_controls/MenuButton.h>
  24. #include <vgui_controls/ComboBox.h>
  25. #include <vgui_controls/BuildGroup.h>
  26. #include <vgui_controls/MessageBox.h>
  27. #include <vgui_controls/Menu.h>
  28. #include <vgui_controls/Divider.h>
  29. #include <vgui_controls/PanelListPanel.h>
  30. // memdbgon must be the last include file in a .cpp file!!!
  31. #include <tier0/memdbgon.h>
  32. using namespace vgui;
  33. struct PanelItem_t
  34. {
  35. PanelItem_t() : m_EditLabel(NULL) {}
  36. Panel *m_EditLabel;
  37. TextEntry *m_EditPanel;
  38. ComboBox *m_pCombo;
  39. Button *m_EditButton;
  40. char m_szName[64];
  41. int m_iType;
  42. };
  43. class CSmallTextEntry : public TextEntry
  44. {
  45. DECLARE_CLASS_SIMPLE( CSmallTextEntry, TextEntry );
  46. public:
  47. CSmallTextEntry( Panel *parent, char const *panelName ) :
  48. BaseClass( parent, panelName )
  49. {
  50. }
  51. virtual void ApplySchemeSettings( IScheme *scheme )
  52. {
  53. BaseClass::ApplySchemeSettings( scheme );
  54. SetFont( scheme->GetFont( "DefaultVerySmall" ) );
  55. }
  56. };
  57. //-----------------------------------------------------------------------------
  58. // Purpose: Holds a list of all the edit fields for the currently selected panel
  59. //-----------------------------------------------------------------------------
  60. class BuildModeDialog::PanelList
  61. {
  62. public:
  63. CUtlVector<PanelItem_t> m_PanelList;
  64. void AddItem( Panel *label, TextEntry *edit, ComboBox *combo, Button *button, const char *name, int type )
  65. {
  66. PanelItem_t item;
  67. item.m_EditLabel = label;
  68. item.m_EditPanel = edit;
  69. Q_strncpy(item.m_szName, name, sizeof(item.m_szName));
  70. item.m_iType = type;
  71. item.m_pCombo = combo;
  72. item.m_EditButton = button;
  73. m_PanelList.AddToTail( item );
  74. }
  75. void RemoveAll( void )
  76. {
  77. for ( int i = 0; i < m_PanelList.Size(); i++ )
  78. {
  79. PanelItem_t *item = &m_PanelList[i];
  80. delete item->m_EditLabel;
  81. delete item->m_EditPanel;
  82. delete item->m_EditButton;
  83. }
  84. m_PanelList.RemoveAll();
  85. m_pControls->RemoveAll();
  86. }
  87. KeyValues *m_pResourceData;
  88. PanelListPanel *m_pControls;
  89. };
  90. //-----------------------------------------------------------------------------
  91. // Purpose: Dialog for adding localized strings
  92. //-----------------------------------------------------------------------------
  93. class BuildModeLocalizedStringEditDialog : public Frame
  94. {
  95. DECLARE_CLASS_SIMPLE(BuildModeLocalizedStringEditDialog, Frame);
  96. public:
  97. #pragma warning( disable : 4355 )
  98. BuildModeLocalizedStringEditDialog() : Frame(this, NULL)
  99. {
  100. m_pTokenEntry = new TextEntry(this, NULL);
  101. m_pValueEntry = new TextEntry(this, NULL);
  102. m_pFileCombo = new ComboBox(this, NULL, 12, false);
  103. m_pOKButton = new Button(this, NULL, "OK");
  104. m_pCancelButton = new Button(this, NULL, "Cancel");
  105. m_pCancelButton->SetCommand("Close");
  106. m_pOKButton->SetCommand("OK");
  107. // add the files to the combo
  108. for (int i = 0; i < g_pVGuiLocalize->GetLocalizationFileCount(); i++)
  109. {
  110. m_pFileCombo->AddItem(g_pVGuiLocalize->GetLocalizationFileName(i), NULL);
  111. }
  112. }
  113. #pragma warning( default : 4355 )
  114. virtual void DoModal(const char *token)
  115. {
  116. input()->SetAppModalSurface(GetVPanel());
  117. // setup data
  118. m_pTokenEntry->SetText(token);
  119. // lookup the value
  120. StringIndex_t val = g_pVGuiLocalize->FindIndex(token);
  121. if (val != INVALID_LOCALIZE_STRING_INDEX)
  122. {
  123. m_pValueEntry->SetText(g_pVGuiLocalize->GetValueByIndex(val));
  124. // set the place in the file combo
  125. m_pFileCombo->SetText(g_pVGuiLocalize->GetFileNameByIndex(val));
  126. }
  127. else
  128. {
  129. m_pValueEntry->SetText("");
  130. }
  131. }
  132. private:
  133. virtual void PerformLayout()
  134. {
  135. }
  136. virtual void OnClose()
  137. {
  138. input()->SetAppModalSurface(NULL);
  139. BaseClass::OnClose();
  140. //PostActionSignal(new KeyValues("Command"
  141. }
  142. virtual void OnCommand(const char *command)
  143. {
  144. if (!stricmp(command, "OK"))
  145. {
  146. //!! apply changes
  147. }
  148. else
  149. {
  150. BaseClass::OnCommand(command);
  151. }
  152. }
  153. vgui::TextEntry *m_pTokenEntry;
  154. vgui::TextEntry *m_pValueEntry;
  155. vgui::ComboBox *m_pFileCombo;
  156. vgui::Button *m_pOKButton;
  157. vgui::Button *m_pCancelButton;
  158. };
  159. class CBuildModeDialogMgr
  160. {
  161. public:
  162. void Add( BuildModeDialog *pDlg );
  163. void Remove( BuildModeDialog *pDlg );
  164. int Count() const;
  165. private:
  166. CUtlVector< BuildModeDialog * > m_vecBuildDialogs;
  167. };
  168. static CBuildModeDialogMgr g_BuildModeDialogMgr;
  169. void CBuildModeDialogMgr::Add( BuildModeDialog *pDlg )
  170. {
  171. if ( m_vecBuildDialogs.Find( pDlg ) == m_vecBuildDialogs.InvalidIndex() )
  172. {
  173. m_vecBuildDialogs.AddToTail( pDlg );
  174. }
  175. }
  176. void CBuildModeDialogMgr::Remove( BuildModeDialog *pDlg )
  177. {
  178. m_vecBuildDialogs.FindAndRemove( pDlg );
  179. }
  180. int CBuildModeDialogMgr::Count() const
  181. {
  182. return m_vecBuildDialogs.Count();
  183. }
  184. int GetBuildModeDialogCount()
  185. {
  186. return g_BuildModeDialogMgr.Count();
  187. }
  188. //-----------------------------------------------------------------------------
  189. // Purpose: Constructor
  190. //-----------------------------------------------------------------------------
  191. BuildModeDialog::BuildModeDialog(BuildGroup *buildGroup) : Frame(buildGroup->GetContextPanel(), "BuildModeDialog")
  192. {
  193. SetMinimumSize(300, 256);
  194. SetSize(300, 420);
  195. m_pCurrentPanel = NULL;
  196. m_pEditableParents = NULL;
  197. m_pEditableChildren = NULL;
  198. m_pNextChild = NULL;
  199. m_pPrevChild = NULL;
  200. m_pBuildGroup = buildGroup;
  201. _undoSettings = NULL;
  202. _copySettings = NULL;
  203. _autoUpdate = false;
  204. MakePopup();
  205. SetTitle("VGUI Build Mode Editor", true);
  206. CreateControls();
  207. LoadUserConfig("BuildModeDialog");
  208. g_BuildModeDialogMgr.Add( this );
  209. }
  210. //-----------------------------------------------------------------------------
  211. // Purpose: Destructor
  212. //-----------------------------------------------------------------------------
  213. BuildModeDialog::~BuildModeDialog()
  214. {
  215. g_BuildModeDialogMgr.Remove( this );
  216. m_pPanelList->m_pResourceData->deleteThis();
  217. m_pPanelList->m_pControls->DeleteAllItems();
  218. if (_undoSettings)
  219. _undoSettings->deleteThis();
  220. if (_copySettings)
  221. _copySettings->deleteThis();
  222. }
  223. //-----------------------------------------------------------------------------
  224. // Purpose: makes sure build mode has been shut down properly
  225. //-----------------------------------------------------------------------------
  226. void BuildModeDialog::OnClose()
  227. {
  228. if (m_pBuildGroup->IsEnabled())
  229. {
  230. m_pBuildGroup->SetEnabled(false);
  231. }
  232. else
  233. {
  234. BaseClass::OnClose();
  235. MarkForDeletion();
  236. }
  237. }
  238. class CBuildModeNavCombo : public ComboBox
  239. {
  240. DECLARE_CLASS_SIMPLE( CBuildModeNavCombo, ComboBox );
  241. public:
  242. CBuildModeNavCombo(Panel *parent, const char *panelName, int numLines, bool allowEdit, bool getParents, Panel *context ) :
  243. BaseClass( parent, panelName, numLines, allowEdit ),
  244. m_bParents( getParents )
  245. {
  246. m_hContext = context;
  247. }
  248. virtual void OnShowMenu(Menu *menu)
  249. {
  250. menu->DeleteAllItems();
  251. if ( !m_hContext.Get() )
  252. return;
  253. if ( m_bParents )
  254. {
  255. Panel *p = m_hContext->GetParent();
  256. while ( p )
  257. {
  258. EditablePanel *ep = dynamic_cast < EditablePanel * >( p );
  259. if ( ep && ep->GetBuildGroup() )
  260. {
  261. KeyValues *kv = new KeyValues( "Panel" );
  262. kv->SetPtr( "ptr", p );
  263. char const *text = ep->GetName() ? ep->GetName() : "unnamed";
  264. menu->AddMenuItem( text, new KeyValues("SetText", "text", text), GetParent(), kv );
  265. }
  266. p = p->GetParent();
  267. }
  268. }
  269. else
  270. {
  271. int i;
  272. int c = m_hContext->GetChildCount();
  273. for ( i = 0; i < c; ++i )
  274. {
  275. EditablePanel *ep = dynamic_cast < EditablePanel * >( m_hContext->GetChild( i ) );
  276. if ( ep && ep->IsVisible() && ep->GetBuildGroup() )
  277. {
  278. KeyValues *kv = new KeyValues( "Panel" );
  279. kv->SetPtr( "ptr", ep );
  280. char const *text = ep->GetName() ? ep->GetName() : "unnamed";
  281. menu->AddMenuItem( text, new KeyValues("SetText", "text", text), GetParent(), kv );
  282. }
  283. }
  284. }
  285. }
  286. private:
  287. bool m_bParents;
  288. vgui::PHandle m_hContext;
  289. };
  290. //-----------------------------------------------------------------------------
  291. // Purpose: Creates the build mode editing controls
  292. //-----------------------------------------------------------------------------
  293. void BuildModeDialog::CreateControls()
  294. {
  295. int i;
  296. m_pPanelList = new PanelList;
  297. m_pPanelList->m_pResourceData = new KeyValues( "BuildDialog" );
  298. m_pPanelList->m_pControls = new PanelListPanel(this, "BuildModeControls");
  299. // file to edit combo box is first
  300. m_pFileSelectionCombo = new ComboBox(this, "FileSelectionCombo", 10, false);
  301. for ( i = 0; i < m_pBuildGroup->GetRegisteredControlSettingsFileCount(); i++)
  302. {
  303. m_pFileSelectionCombo->AddItem(m_pBuildGroup->GetRegisteredControlSettingsFileByIndex(i), NULL);
  304. }
  305. if (m_pFileSelectionCombo->GetItemCount() < 2)
  306. {
  307. m_pFileSelectionCombo->SetEnabled(false);
  308. }
  309. int buttonH = 18;
  310. // status info at top of dialog
  311. m_pStatusLabel = new Label(this, "StatusLabel", "[nothing currently selected]");
  312. m_pStatusLabel->SetTextColorState(Label::CS_DULL);
  313. m_pStatusLabel->SetTall( buttonH );
  314. m_pDivider = new Divider(this, "Divider");
  315. // drop-down combo box for adding new controls
  316. m_pAddNewControlCombo = new ComboBox(this, NULL, 30, false);
  317. m_pAddNewControlCombo->SetSize(116, buttonH);
  318. m_pAddNewControlCombo->SetOpenDirection(Menu::DOWN);
  319. m_pEditableParents = new CBuildModeNavCombo( this, NULL, 15, false, true, m_pBuildGroup->GetContextPanel() );
  320. m_pEditableParents->SetSize(116, buttonH);
  321. m_pEditableParents->SetOpenDirection(Menu::DOWN);
  322. m_pEditableChildren = new CBuildModeNavCombo( this, NULL, 15, false, false, m_pBuildGroup->GetContextPanel() );
  323. m_pEditableChildren->SetSize(116, buttonH);
  324. m_pEditableChildren->SetOpenDirection(Menu::DOWN);
  325. m_pNextChild = new Button( this, "NextChild", "Next", this );
  326. m_pNextChild->SetCommand( new KeyValues( "OnChangeChild", "direction", 1 ) );
  327. m_pPrevChild = new Button( this, "PrevChild", "Prev", this );
  328. m_pPrevChild->SetCommand( new KeyValues( "OnChangeChild", "direction", -1 ) );
  329. // controls that can be added
  330. // this list comes from controls EditablePanel can create by name.
  331. int defaultItem = m_pAddNewControlCombo->AddItem("None", NULL);
  332. CUtlVector< char const * > names;
  333. CBuildFactoryHelper::GetFactoryNames( names );
  334. // Sort the names
  335. CUtlRBTree< char const *, int > sorted( 0, 0, StringLessThan );
  336. for ( i = 0; i < names.Count(); ++i )
  337. {
  338. sorted.Insert( names[ i ] );
  339. }
  340. for ( i = sorted.FirstInorder(); i != sorted.InvalidIndex(); i = sorted.NextInorder( i ) )
  341. {
  342. m_pAddNewControlCombo->AddItem( sorted[ i ], NULL );
  343. }
  344. m_pAddNewControlCombo->ActivateItem(defaultItem);
  345. m_pExitButton = new Button(this, "ExitButton", "&Exit");
  346. m_pExitButton->SetSize(64, buttonH);
  347. m_pSaveButton = new Button(this, "SaveButton", "&Save");
  348. m_pSaveButton->SetSize(64, buttonH);
  349. m_pApplyButton = new Button(this, "ApplyButton", "&Apply");
  350. m_pApplyButton->SetSize(64, buttonH);
  351. m_pReloadLocalization = new Button( this, "Localization", "&Reload Localization" );
  352. m_pReloadLocalization->SetSize( 100, buttonH );
  353. m_pExitButton->SetCommand("Exit");
  354. m_pSaveButton->SetCommand("Save");
  355. m_pApplyButton->SetCommand("Apply");
  356. m_pReloadLocalization->SetCommand( new KeyValues( "ReloadLocalization" ) );
  357. m_pDeleteButton = new Button(this, "DeletePanelButton", "Delete");
  358. m_pDeleteButton->SetSize(64, buttonH);
  359. m_pDeleteButton->SetCommand("DeletePanel");
  360. m_pVarsButton = new MenuButton(this, "VarsButton", "Variables");
  361. m_pVarsButton->SetSize(72, buttonH);
  362. m_pVarsButton->SetOpenDirection(Menu::UP);
  363. // iterate the vars
  364. KeyValues *vars = m_pBuildGroup->GetDialogVariables();
  365. if (vars && vars->GetFirstSubKey())
  366. {
  367. // create the menu
  368. m_pVarsButton->SetEnabled(true);
  369. Menu *menu = new Menu(m_pVarsButton, "VarsMenu");
  370. // set all the variables to be copied to the clipboard when selected
  371. for (KeyValues *kv = vars->GetFirstSubKey(); kv != NULL; kv = kv->GetNextKey())
  372. {
  373. char buf[32];
  374. _snprintf(buf, sizeof(buf), "%%%s%%", kv->GetName());
  375. menu->AddMenuItem(kv->GetName(), new KeyValues("SetClipboardText", "text", buf), this);
  376. }
  377. m_pVarsButton->SetMenu(menu);
  378. }
  379. else
  380. {
  381. // no variables
  382. m_pVarsButton->SetEnabled(false);
  383. }
  384. m_pApplyButton->SetTabPosition(1);
  385. m_pPanelList->m_pControls->SetTabPosition(2);
  386. m_pVarsButton->SetTabPosition(3);
  387. m_pDeleteButton->SetTabPosition(4);
  388. m_pAddNewControlCombo->SetTabPosition(5);
  389. m_pSaveButton->SetTabPosition(6);
  390. m_pExitButton->SetTabPosition(7);
  391. m_pEditableParents->SetTabPosition( 8 );
  392. m_pEditableChildren->SetTabPosition( 9 );
  393. m_pPrevChild->SetTabPosition( 10 );
  394. m_pNextChild->SetTabPosition( 11 );
  395. m_pReloadLocalization->SetTabPosition( 12 );
  396. }
  397. void BuildModeDialog::ApplySchemeSettings( IScheme *pScheme )
  398. {
  399. BaseClass::ApplySchemeSettings( pScheme );
  400. HFont font = pScheme->GetFont( "DefaultVerySmall" );
  401. m_pStatusLabel->SetFont( font );
  402. m_pReloadLocalization->SetFont( font );
  403. m_pExitButton->SetFont( font );
  404. m_pSaveButton->SetFont( font );
  405. m_pApplyButton->SetFont( font );
  406. m_pAddNewControlCombo->SetFont( font );
  407. m_pEditableParents->SetFont( font );
  408. m_pEditableChildren->SetFont( font );
  409. m_pDeleteButton->SetFont( font );
  410. m_pVarsButton->SetFont( font );
  411. m_pPrevChild->SetFont( font );
  412. m_pNextChild->SetFont( font );
  413. }
  414. //-----------------------------------------------------------------------------
  415. // Purpose: lays out controls
  416. //-----------------------------------------------------------------------------
  417. void BuildModeDialog::PerformLayout()
  418. {
  419. BaseClass::PerformLayout();
  420. // layout parameters
  421. const int BORDER_GAP = 16, YGAP_SMALL = 4, YGAP_LARGE = 8, TITLE_HEIGHT = 24, BOTTOM_CONTROLS_HEIGHT = 145, XGAP = 6;
  422. int wide, tall;
  423. GetSize(wide, tall);
  424. int xpos = BORDER_GAP;
  425. int ypos = BORDER_GAP + TITLE_HEIGHT;
  426. // controls from top down
  427. // selection combo
  428. m_pFileSelectionCombo->SetBounds(xpos, ypos, wide - (BORDER_GAP * 2), m_pStatusLabel->GetTall());
  429. ypos += (m_pStatusLabel->GetTall() + YGAP_SMALL);
  430. // status
  431. m_pStatusLabel->SetBounds(xpos, ypos, wide - (BORDER_GAP * 2), m_pStatusLabel->GetTall());
  432. ypos += (m_pStatusLabel->GetTall() + YGAP_SMALL);
  433. // center control
  434. m_pPanelList->m_pControls->SetPos(xpos, ypos);
  435. m_pPanelList->m_pControls->SetSize(wide - (BORDER_GAP * 2), tall - (ypos + BOTTOM_CONTROLS_HEIGHT));
  436. // controls from bottom-right
  437. ypos = tall - BORDER_GAP;
  438. xpos = BORDER_GAP + m_pVarsButton->GetWide() + m_pDeleteButton->GetWide() + m_pAddNewControlCombo->GetWide() + (XGAP * 2);
  439. // bottom row of buttons
  440. ypos -= m_pApplyButton->GetTall();
  441. xpos -= m_pApplyButton->GetWide();
  442. m_pApplyButton->SetPos(xpos, ypos);
  443. xpos -= m_pExitButton->GetWide();
  444. xpos -= XGAP;
  445. m_pExitButton->SetPos(xpos, ypos);
  446. xpos -= m_pSaveButton->GetWide();
  447. xpos -= XGAP;
  448. m_pSaveButton->SetPos(xpos, ypos);
  449. // divider
  450. xpos = BORDER_GAP;
  451. ypos -= (YGAP_LARGE + m_pDivider->GetTall());
  452. m_pDivider->SetBounds(xpos, ypos, wide - (xpos + BORDER_GAP), 2);
  453. ypos -= (YGAP_LARGE + m_pVarsButton->GetTall());
  454. xpos = BORDER_GAP;
  455. m_pEditableParents->SetPos( xpos, ypos );
  456. m_pEditableChildren->SetPos( xpos + 150, ypos );
  457. ypos -= (YGAP_LARGE + 18 );
  458. xpos = BORDER_GAP;
  459. m_pReloadLocalization->SetPos( xpos, ypos );
  460. xpos += ( XGAP ) + m_pReloadLocalization->GetWide();
  461. m_pPrevChild->SetPos( xpos, ypos );
  462. m_pPrevChild->SetSize( 64, m_pReloadLocalization->GetTall() );
  463. xpos += ( XGAP ) + m_pPrevChild->GetWide();
  464. m_pNextChild->SetPos( xpos, ypos );
  465. m_pNextChild->SetSize( 64, m_pReloadLocalization->GetTall() );
  466. ypos -= (YGAP_LARGE + m_pVarsButton->GetTall());
  467. xpos = BORDER_GAP;
  468. // edit buttons
  469. m_pVarsButton->SetPos(xpos, ypos);
  470. xpos += (XGAP + m_pVarsButton->GetWide());
  471. m_pDeleteButton->SetPos(xpos, ypos);
  472. xpos += (XGAP + m_pDeleteButton->GetWide());
  473. m_pAddNewControlCombo->SetPos(xpos, ypos);
  474. }
  475. //-----------------------------------------------------------------------------
  476. // Purpose: Deletes all the controls from the panel
  477. //-----------------------------------------------------------------------------
  478. void BuildModeDialog::RemoveAllControls( void )
  479. {
  480. // free the array
  481. m_pPanelList->RemoveAll();
  482. }
  483. //-----------------------------------------------------------------------------
  484. // Purpose: simple helper function to get a token from a string
  485. // Input : char **string - pointer to the string pointer, which will be incremented
  486. // Output : const char * - pointer to the token
  487. //-----------------------------------------------------------------------------
  488. const char *ParseTokenFromString( const char **string )
  489. {
  490. static char buf[128];
  491. buf[0] = 0;
  492. // find the first alnum character
  493. const char *tok = *string;
  494. while ( !V_isalnum(*tok) && *tok != 0 )
  495. {
  496. tok++;
  497. }
  498. // read in all the alnum characters
  499. int pos = 0;
  500. while ( V_isalnum(tok[pos]) )
  501. {
  502. buf[pos] = tok[pos];
  503. pos++;
  504. }
  505. // null terminate the token
  506. buf[pos] = 0;
  507. // update the main string pointer
  508. *string = &(tok[pos]);
  509. // return a pointer to the static buffer
  510. return buf;
  511. }
  512. void BuildModeDialog::OnTextKillFocus()
  513. {
  514. if ( !m_pCurrentPanel )
  515. return;
  516. ApplyDataToControls();
  517. }
  518. //-----------------------------------------------------------------------------
  519. // Purpose: sets up the current control to edit
  520. //-----------------------------------------------------------------------------
  521. void BuildModeDialog::SetActiveControl(Panel *controlToEdit)
  522. {
  523. if (m_pCurrentPanel == controlToEdit)
  524. {
  525. // it's already set, so just update the property data and quit
  526. if (m_pCurrentPanel)
  527. {
  528. UpdateControlData(m_pCurrentPanel);
  529. }
  530. return;
  531. }
  532. // reset the data
  533. m_pCurrentPanel = controlToEdit;
  534. RemoveAllControls();
  535. m_pPanelList->m_pControls->MoveScrollBarToTop();
  536. if (!m_pCurrentPanel)
  537. {
  538. m_pStatusLabel->SetText("[nothing currently selected]");
  539. m_pStatusLabel->SetTextColorState(Label::CS_DULL);
  540. RemoveAllControls();
  541. return;
  542. }
  543. // get the control description string
  544. const char *controlDesc = m_pCurrentPanel->GetDescription();
  545. // parse out the control description
  546. int tabPosition = 1;
  547. while (1)
  548. {
  549. const char *dataType = ParseTokenFromString(&controlDesc);
  550. // finish when we have no more tokens
  551. if (*dataType == 0)
  552. break;
  553. // default the data type to a string
  554. int datat = TYPE_STRING;
  555. if (!stricmp(dataType, "int"))
  556. {
  557. datat = TYPE_STRING; //!! just for now
  558. }
  559. else if (!stricmp(dataType, "alignment"))
  560. {
  561. datat = TYPE_ALIGNMENT;
  562. }
  563. else if (!stricmp(dataType, "autoresize"))
  564. {
  565. datat = TYPE_AUTORESIZE;
  566. }
  567. else if (!stricmp(dataType, "corner"))
  568. {
  569. datat = TYPE_CORNER;
  570. }
  571. else if (!stricmp(dataType, "localize"))
  572. {
  573. datat = TYPE_LOCALIZEDSTRING;
  574. }
  575. // get the field name
  576. const char *fieldName = ParseTokenFromString(&controlDesc);
  577. int itemHeight = 18;
  578. // build a control & label
  579. Label *label = new Label(this, NULL, fieldName);
  580. label->SetSize(96, itemHeight);
  581. label->SetContentAlignment(Label::a_east);
  582. TextEntry *edit = NULL;
  583. ComboBox *editCombo = NULL;
  584. Button *editButton = NULL;
  585. if (datat == TYPE_ALIGNMENT)
  586. {
  587. // drop-down combo box
  588. editCombo = new ComboBox(this, NULL, 9, false);
  589. editCombo->AddItem("north-west", NULL);
  590. editCombo->AddItem("north", NULL);
  591. editCombo->AddItem("north-east", NULL);
  592. editCombo->AddItem("west", NULL);
  593. editCombo->AddItem("center", NULL);
  594. editCombo->AddItem("east", NULL);
  595. editCombo->AddItem("south-west", NULL);
  596. editCombo->AddItem("south", NULL);
  597. editCombo->AddItem("south-east", NULL);
  598. edit = editCombo;
  599. }
  600. else if (datat == TYPE_AUTORESIZE)
  601. {
  602. // drop-down combo box
  603. editCombo = new ComboBox(this, NULL, 4, false);
  604. editCombo->AddItem( "0 - no auto-resize", NULL);
  605. editCombo->AddItem( "1 - resize right", NULL);
  606. editCombo->AddItem( "2 - resize down", NULL);
  607. editCombo->AddItem( "3 - down & right", NULL);
  608. edit = editCombo;
  609. }
  610. else if (datat == TYPE_CORNER)
  611. {
  612. // drop-down combo box
  613. editCombo = new ComboBox(this, NULL, 4, false);
  614. editCombo->AddItem("0 - top-left", NULL);
  615. editCombo->AddItem("1 - top-right", NULL);
  616. editCombo->AddItem("2 - bottom-left", NULL);
  617. editCombo->AddItem("3 - bottom-right", NULL);
  618. edit = editCombo;
  619. }
  620. else if (datat == TYPE_LOCALIZEDSTRING)
  621. {
  622. editButton = new Button(this, NULL, "...");
  623. editButton->SetParent(this);
  624. editButton->AddActionSignalTarget(this);
  625. editButton->SetTabPosition(tabPosition++);
  626. editButton->SetTall( itemHeight );
  627. label->SetAssociatedControl(editButton);
  628. }
  629. else
  630. {
  631. // normal string edit
  632. edit = new CSmallTextEntry(this, NULL);
  633. }
  634. if (edit)
  635. {
  636. edit->SetTall( itemHeight );
  637. edit->SetParent(this);
  638. edit->AddActionSignalTarget(this);
  639. edit->SetTabPosition(tabPosition++);
  640. label->SetAssociatedControl(edit);
  641. }
  642. HFont smallFont = scheme()->GetIScheme( GetScheme() )->GetFont( "DefaultVerySmall" );
  643. if ( label )
  644. {
  645. label->SetFont( smallFont );
  646. }
  647. if ( edit )
  648. {
  649. edit->SetFont( smallFont );
  650. }
  651. if ( editCombo )
  652. {
  653. editCombo->SetFont( smallFont );
  654. }
  655. if ( editButton )
  656. {
  657. editButton->SetFont( smallFont );
  658. }
  659. // add to our control list
  660. m_pPanelList->AddItem(label, edit, editCombo, editButton, fieldName, datat);
  661. if ( edit )
  662. {
  663. m_pPanelList->m_pControls->AddItem(label, edit);
  664. }
  665. else
  666. {
  667. m_pPanelList->m_pControls->AddItem(label, editButton);
  668. }
  669. }
  670. // check and see if the current panel is a Label
  671. // iterate through the class hierarchy
  672. if ( controlToEdit->IsBuildModeDeletable() )
  673. {
  674. m_pDeleteButton->SetEnabled(true);
  675. }
  676. else
  677. {
  678. m_pDeleteButton->SetEnabled(false);
  679. }
  680. // update the property data in the dialog
  681. UpdateControlData(m_pCurrentPanel);
  682. // set our title
  683. if ( m_pBuildGroup->GetResourceName() )
  684. {
  685. m_pFileSelectionCombo->SetText(m_pBuildGroup->GetResourceName());
  686. }
  687. else
  688. {
  689. m_pFileSelectionCombo->SetText("[ no resource file associated with dialog ]");
  690. }
  691. m_pApplyButton->SetEnabled(false);
  692. InvalidateLayout();
  693. Repaint();
  694. }
  695. //-----------------------------------------------------------------------------
  696. // Purpose: Updates the edit fields with information about the control
  697. //-----------------------------------------------------------------------------
  698. void BuildModeDialog::UpdateControlData(Panel *control)
  699. {
  700. KeyValues *dat = m_pPanelList->m_pResourceData->FindKey( control->GetName(), true );
  701. control->GetSettings( dat );
  702. // apply the settings to the edit panels
  703. for ( int i = 0; i < m_pPanelList->m_PanelList.Size(); i++ )
  704. {
  705. const char *name = m_pPanelList->m_PanelList[i].m_szName;
  706. const char *datstring = dat->GetString( name, "" );
  707. UpdateEditControl(m_pPanelList->m_PanelList[i], datstring);
  708. }
  709. char statusText[512];
  710. Q_snprintf(statusText, sizeof(statusText), "%s: \'%s\'", control->GetClassName(), control->GetName());
  711. m_pStatusLabel->SetText(statusText);
  712. m_pStatusLabel->SetTextColorState(Label::CS_NORMAL);
  713. }
  714. //-----------------------------------------------------------------------------
  715. // Purpose: Updates the data in a single edit control
  716. //-----------------------------------------------------------------------------
  717. void BuildModeDialog::UpdateEditControl(PanelItem_t &panelItem, const char *datstring)
  718. {
  719. switch (panelItem.m_iType)
  720. {
  721. case TYPE_AUTORESIZE:
  722. case TYPE_CORNER:
  723. {
  724. int dat = atoi(datstring);
  725. panelItem.m_pCombo->ActivateItemByRow(dat);
  726. }
  727. break;
  728. case TYPE_LOCALIZEDSTRING:
  729. {
  730. panelItem.m_EditButton->SetText(datstring);
  731. }
  732. break;
  733. default:
  734. {
  735. wchar_t unicode[512];
  736. g_pVGuiLocalize->ConvertANSIToUnicode(datstring, unicode, sizeof(unicode));
  737. panelItem.m_EditPanel->SetText(unicode);
  738. }
  739. break;
  740. }
  741. }
  742. //-----------------------------------------------------------------------------
  743. // Purpose: Called when one of the buttons is pressed
  744. //-----------------------------------------------------------------------------
  745. void BuildModeDialog::OnCommand(const char *command)
  746. {
  747. if (!stricmp(command, "Save"))
  748. {
  749. // apply the current data and save it to disk
  750. ApplyDataToControls();
  751. if (m_pBuildGroup->SaveControlSettings())
  752. {
  753. // disable save button until another change has been made
  754. m_pSaveButton->SetEnabled(false);
  755. }
  756. }
  757. else if (!stricmp(command, "Exit"))
  758. {
  759. // exit build mode
  760. ExitBuildMode();
  761. }
  762. else if (!stricmp(command, "Apply"))
  763. {
  764. // apply data to controls
  765. ApplyDataToControls();
  766. }
  767. else if (!stricmp(command, "DeletePanel"))
  768. {
  769. OnDeletePanel();
  770. }
  771. else if (!stricmp(command, "RevertToSaved"))
  772. {
  773. RevertToSaved();
  774. }
  775. else if (!stricmp(command, "ShowHelp"))
  776. {
  777. ShowHelp();
  778. }
  779. else
  780. {
  781. BaseClass::OnCommand(command);
  782. }
  783. }
  784. //-----------------------------------------------------------------------------
  785. // Purpose: Deletes a panel from the buildgroup
  786. //-----------------------------------------------------------------------------
  787. void BuildModeDialog::OnDeletePanel()
  788. {
  789. if (!m_pCurrentPanel->IsBuildModeEditable())
  790. {
  791. return;
  792. }
  793. m_pBuildGroup->RemoveSettings();
  794. SetActiveControl(m_pBuildGroup->GetCurrentPanel());
  795. _undoSettings->deleteThis();
  796. _undoSettings = NULL;
  797. m_pSaveButton->SetEnabled(true);
  798. }
  799. //-----------------------------------------------------------------------------
  800. // Purpose: Applies the current settings to the build controls
  801. //-----------------------------------------------------------------------------
  802. void BuildModeDialog::ApplyDataToControls()
  803. {
  804. // don't apply if the panel is not editable
  805. if ( !m_pCurrentPanel->IsBuildModeEditable())
  806. {
  807. UpdateControlData( m_pCurrentPanel );
  808. return; // return success, since we are behaving as expected.
  809. }
  810. char fieldName[512];
  811. if (m_pPanelList->m_PanelList[0].m_EditPanel)
  812. {
  813. m_pPanelList->m_PanelList[0].m_EditPanel->GetText(fieldName, sizeof(fieldName));
  814. }
  815. else
  816. {
  817. m_pPanelList->m_PanelList[0].m_EditButton->GetText(fieldName, sizeof(fieldName));
  818. }
  819. // check to see if any buildgroup panels have this name
  820. Panel *panel = m_pBuildGroup->FieldNameTaken(fieldName);
  821. if (panel)
  822. {
  823. if (panel != m_pCurrentPanel)// make sure name is taken by some other panel not this one
  824. {
  825. char messageString[255];
  826. Q_snprintf(messageString, sizeof( messageString ), "Fieldname is not unique: %s\nRename it and try again.", fieldName);
  827. MessageBox *errorBox = new MessageBox("Cannot Apply", messageString);
  828. errorBox->DoModal();
  829. UpdateControlData(m_pCurrentPanel);
  830. m_pApplyButton->SetEnabled(false);
  831. return;
  832. }
  833. }
  834. // create a section to store settings
  835. // m_pPanelList->m_pResourceData->getSection( m_pCurrentPanel->GetName(), true );
  836. KeyValues *dat = new KeyValues( m_pCurrentPanel->GetName() );
  837. // loop through the textedit filling in settings
  838. for ( int i = 0; i < m_pPanelList->m_PanelList.Size(); i++ )
  839. {
  840. const char *name = m_pPanelList->m_PanelList[i].m_szName;
  841. char buf[512];
  842. if (m_pPanelList->m_PanelList[i].m_EditPanel)
  843. {
  844. m_pPanelList->m_PanelList[i].m_EditPanel->GetText(buf, sizeof(buf));
  845. }
  846. else
  847. {
  848. m_pPanelList->m_PanelList[i].m_EditButton->GetText(buf, sizeof(buf));
  849. }
  850. switch (m_pPanelList->m_PanelList[i].m_iType)
  851. {
  852. case TYPE_CORNER:
  853. case TYPE_AUTORESIZE:
  854. // the integer value is assumed to be the first part of the string for these items
  855. dat->SetInt(name, atoi(buf));
  856. break;
  857. default:
  858. dat->SetString(name, buf);
  859. break;
  860. }
  861. }
  862. // dat is built, hand it back to the control
  863. m_pCurrentPanel->ApplySettings( dat );
  864. if ( m_pBuildGroup->GetContextPanel() )
  865. {
  866. m_pBuildGroup->GetContextPanel()->Repaint();
  867. }
  868. m_pApplyButton->SetEnabled(false);
  869. m_pSaveButton->SetEnabled(true);
  870. }
  871. //-----------------------------------------------------------------------------
  872. // Purpose: Store the settings of the current panel in a KeyValues
  873. //-----------------------------------------------------------------------------
  874. void BuildModeDialog::StoreUndoSettings()
  875. {
  876. // don't save if the planel is not editable
  877. if ( !m_pCurrentPanel->IsBuildModeEditable())
  878. {
  879. if (_undoSettings)
  880. _undoSettings->deleteThis();
  881. _undoSettings = NULL;
  882. return;
  883. }
  884. if (_undoSettings)
  885. {
  886. _undoSettings->deleteThis();
  887. _undoSettings = NULL;
  888. }
  889. _undoSettings = StoreSettings();
  890. }
  891. //-----------------------------------------------------------------------------
  892. // Purpose: Revert to the stored the settings of the current panel in a keyValues
  893. //-----------------------------------------------------------------------------
  894. void BuildModeDialog::DoUndo()
  895. {
  896. if ( _undoSettings )
  897. {
  898. m_pCurrentPanel->ApplySettings( _undoSettings );
  899. UpdateControlData(m_pCurrentPanel);
  900. _undoSettings->deleteThis();
  901. _undoSettings = NULL;
  902. }
  903. m_pSaveButton->SetEnabled(true);
  904. }
  905. //-----------------------------------------------------------------------------
  906. // Purpose: Copy the settings of the current panel into a keyValues
  907. //-----------------------------------------------------------------------------
  908. void BuildModeDialog::DoCopy()
  909. {
  910. if (_copySettings)
  911. {
  912. _copySettings->deleteThis();
  913. _copySettings = NULL;
  914. }
  915. _copySettings = StoreSettings();
  916. Q_strncpy (_copyClassName, m_pCurrentPanel->GetClassName(), sizeof( _copyClassName ) );
  917. }
  918. //-----------------------------------------------------------------------------
  919. // Purpose: Create a new Panel with the _copySettings applied
  920. //-----------------------------------------------------------------------------
  921. void BuildModeDialog::DoPaste()
  922. {
  923. // Make a new control located where you had the mouse
  924. int x, y;
  925. input()->GetCursorPos(x, y);
  926. m_pBuildGroup->GetContextPanel()->ScreenToLocal(x,y);
  927. Panel *newPanel = OnNewControl(_copyClassName, x, y);
  928. if (newPanel)
  929. {
  930. newPanel->ApplySettings(_copySettings);
  931. newPanel->SetPos(x, y);
  932. char name[255];
  933. m_pBuildGroup->GetNewFieldName(name, sizeof(name), newPanel);
  934. newPanel->SetName(name);
  935. }
  936. }
  937. //-----------------------------------------------------------------------------
  938. // Purpose: Store the settings of the current panel in a keyValues
  939. //-----------------------------------------------------------------------------
  940. KeyValues *BuildModeDialog::StoreSettings()
  941. {
  942. KeyValues *storedSettings;
  943. storedSettings = new KeyValues( m_pCurrentPanel->GetName() );
  944. // loop through the textedit filling in settings
  945. for ( int i = 0; i < m_pPanelList->m_PanelList.Size(); i++ )
  946. {
  947. const char *name = m_pPanelList->m_PanelList[i].m_szName;
  948. char buf[512];
  949. if (m_pPanelList->m_PanelList[i].m_EditPanel)
  950. {
  951. m_pPanelList->m_PanelList[i].m_EditPanel->GetText(buf, sizeof(buf));
  952. }
  953. else
  954. {
  955. m_pPanelList->m_PanelList[i].m_EditButton->GetText(buf, sizeof(buf));
  956. }
  957. switch (m_pPanelList->m_PanelList[i].m_iType)
  958. {
  959. case TYPE_CORNER:
  960. case TYPE_AUTORESIZE:
  961. // the integer value is assumed to be the first part of the string for these items
  962. storedSettings->SetInt(name, atoi(buf));
  963. break;
  964. default:
  965. storedSettings->SetString(name, buf);
  966. break;
  967. }
  968. }
  969. return storedSettings;
  970. }
  971. //-----------------------------------------------------------------------------
  972. // Purpose:
  973. //-----------------------------------------------------------------------------
  974. void BuildModeDialog::OnKeyCodeTyped(KeyCode code)
  975. {
  976. if (code == KEY_ENTER) // if someone hits return apply the changes
  977. {
  978. ApplyDataToControls();
  979. }
  980. else
  981. {
  982. Frame::OnKeyCodeTyped(code);
  983. }
  984. }
  985. //-----------------------------------------------------------------------------
  986. // Purpose: Checks to see if any text has changed
  987. //-----------------------------------------------------------------------------
  988. void BuildModeDialog::OnTextChanged( Panel *panel )
  989. {
  990. if (panel == m_pFileSelectionCombo)
  991. {
  992. // reload file if it's changed
  993. char newFile[512];
  994. m_pFileSelectionCombo->GetText(newFile, sizeof(newFile));
  995. if (stricmp(newFile, m_pBuildGroup->GetResourceName()) != 0)
  996. {
  997. // file has changed, reload
  998. SetActiveControl(NULL);
  999. m_pBuildGroup->ChangeControlSettingsFile(newFile);
  1000. }
  1001. return;
  1002. }
  1003. if (panel == m_pAddNewControlCombo)
  1004. {
  1005. char buf[40];
  1006. m_pAddNewControlCombo->GetText(buf, 40);
  1007. if (stricmp(buf, "None") != 0)
  1008. {
  1009. OnNewControl(buf);
  1010. // reset box back to None
  1011. m_pAddNewControlCombo->ActivateItemByRow( 0 );
  1012. }
  1013. }
  1014. if ( panel == m_pEditableChildren )
  1015. {
  1016. KeyValues *kv = m_pEditableChildren->GetActiveItemUserData();
  1017. if ( kv )
  1018. {
  1019. EditablePanel *ep = reinterpret_cast< EditablePanel * >( kv->GetPtr( "ptr" ) );
  1020. if ( ep )
  1021. {
  1022. ep->ActivateBuildMode();
  1023. }
  1024. }
  1025. }
  1026. if ( panel == m_pEditableParents )
  1027. {
  1028. KeyValues *kv = m_pEditableParents->GetActiveItemUserData();
  1029. if ( kv )
  1030. {
  1031. EditablePanel *ep = reinterpret_cast< EditablePanel * >( kv->GetPtr( "ptr" ) );
  1032. if ( ep )
  1033. {
  1034. ep->ActivateBuildMode();
  1035. }
  1036. }
  1037. }
  1038. if (m_pCurrentPanel && m_pCurrentPanel->IsBuildModeEditable())
  1039. {
  1040. m_pApplyButton->SetEnabled(true);
  1041. }
  1042. if (_autoUpdate)
  1043. {
  1044. ApplyDataToControls();
  1045. }
  1046. }
  1047. //-----------------------------------------------------------------------------
  1048. // Purpose:
  1049. //-----------------------------------------------------------------------------
  1050. void BuildModeDialog::ExitBuildMode( void )
  1051. {
  1052. // make sure rulers are off
  1053. if (m_pBuildGroup->HasRulersOn())
  1054. {
  1055. m_pBuildGroup->ToggleRulerDisplay();
  1056. }
  1057. m_pBuildGroup->SetEnabled(false);
  1058. }
  1059. //-----------------------------------------------------------------------------
  1060. // Purpose: Create a new control in the context panel
  1061. //-----------------------------------------------------------------------------
  1062. Panel *BuildModeDialog::OnNewControl( const char *name, int x, int y)
  1063. {
  1064. // returns NULL on failure
  1065. Panel *newPanel = m_pBuildGroup->NewControl(name, x, y);
  1066. if (newPanel)
  1067. {
  1068. // call mouse commands to simulate selecting the new
  1069. // panel. This will set everything up correctly in the buildGroup.
  1070. m_pBuildGroup->MousePressed(MOUSE_LEFT, newPanel);
  1071. m_pBuildGroup->MouseReleased(MOUSE_LEFT, newPanel);
  1072. }
  1073. m_pSaveButton->SetEnabled(true);
  1074. return newPanel;
  1075. }
  1076. //-----------------------------------------------------------------------------
  1077. // Purpose: enable the save button, useful when buildgroup needs to Activate it.
  1078. //-----------------------------------------------------------------------------
  1079. void BuildModeDialog::EnableSaveButton()
  1080. {
  1081. m_pSaveButton->SetEnabled(true);
  1082. }
  1083. //-----------------------------------------------------------------------------
  1084. // Purpose: Revert to the saved settings in the .res file
  1085. //-----------------------------------------------------------------------------
  1086. void BuildModeDialog::RevertToSaved()
  1087. {
  1088. // hide the dialog as reloading will destroy it
  1089. surface()->SetPanelVisible(this->GetVPanel(), false);
  1090. m_pBuildGroup->ReloadControlSettings();
  1091. }
  1092. //-----------------------------------------------------------------------------
  1093. // Purpose: Display some information about the editor
  1094. //-----------------------------------------------------------------------------
  1095. void BuildModeDialog::ShowHelp()
  1096. {
  1097. char helpText[]= "In the Build Mode Dialog Window:\n"
  1098. "Delete button - deletes the currently selected panel if it is deletable.\n"
  1099. "Apply button - applies changes to the Context Panel.\n"
  1100. "Save button - saves all settings to file. \n"
  1101. "Revert to saved- reloads the last saved file.\n"
  1102. "Auto Update - any changes apply instantly.\n"
  1103. "Typing Enter in any text field applies changes.\n"
  1104. "New Control menu - creates a new panel in the upper left corner.\n\n"
  1105. "In the Context Panel:\n"
  1106. "After selecting and moving a panel Ctrl-z will undo the move.\n"
  1107. "Shift clicking panels allows multiple panels to be selected into a group.\n"
  1108. "Ctrl-c copies the settings of the last selected panel.\n"
  1109. "Ctrl-v creates a new panel with the copied settings at the location of the mouse pointer.\n"
  1110. "Arrow keys slowly move panels, holding shift + arrow will slowly resize it.\n"
  1111. "Holding right mouse button down opens a dropdown panel creation menu.\n"
  1112. " Panel will be created where the menu was opened.\n"
  1113. "Delete key deletes the currently selected panel if it is deletable.\n"
  1114. " Does nothing to multiple selections.";
  1115. MessageBox *helpDlg = new MessageBox ("Build Mode Help", helpText, this);
  1116. helpDlg->AddActionSignalTarget(this);
  1117. helpDlg->DoModal();
  1118. }
  1119. void BuildModeDialog::ShutdownBuildMode()
  1120. {
  1121. m_pBuildGroup->SetEnabled(false);
  1122. }
  1123. void BuildModeDialog::OnPanelMoved()
  1124. {
  1125. m_pApplyButton->SetEnabled(true);
  1126. }
  1127. //-----------------------------------------------------------------------------
  1128. // Purpose: message handles thats sets the text in the clipboard
  1129. //-----------------------------------------------------------------------------
  1130. void BuildModeDialog::OnSetClipboardText(const char *text)
  1131. {
  1132. system()->SetClipboardText(text, strlen(text));
  1133. }
  1134. void BuildModeDialog::OnCreateNewControl( char const *text )
  1135. {
  1136. if ( !Q_stricmp( text, "None" ) )
  1137. return;
  1138. OnNewControl( text, m_nClick[ 0 ], m_nClick[ 1 ] );
  1139. }
  1140. void BuildModeDialog::OnShowNewControlMenu()
  1141. {
  1142. if ( !m_pBuildGroup )
  1143. return;
  1144. int i;
  1145. input()->GetCursorPos( m_nClick[ 0 ], m_nClick[ 1 ] );
  1146. m_pBuildGroup->GetContextPanel()->ScreenToLocal( m_nClick[ 0 ], m_nClick[ 1 ] );
  1147. if ( m_hContextMenu )
  1148. delete m_hContextMenu.Get();
  1149. m_hContextMenu = new Menu( this, "NewControls" );
  1150. // Show popup menu
  1151. m_hContextMenu->AddMenuItem( "None", "None", new KeyValues( "CreateNewControl", "text", "None" ), this );
  1152. CUtlVector< char const * > names;
  1153. CBuildFactoryHelper::GetFactoryNames( names );
  1154. // Sort the names
  1155. CUtlRBTree< char const *, int > sorted( 0, 0, StringLessThan );
  1156. for ( i = 0; i < names.Count(); ++i )
  1157. {
  1158. sorted.Insert( names[ i ] );
  1159. }
  1160. for ( i = sorted.FirstInorder(); i != sorted.InvalidIndex(); i = sorted.NextInorder( i ) )
  1161. {
  1162. m_hContextMenu->AddMenuItem( sorted[ i ], sorted[ i ], new KeyValues( "CreateNewControl", "text", sorted[ i ] ), this );
  1163. }
  1164. Menu::PlaceContextMenu( this, m_hContextMenu );
  1165. }
  1166. void BuildModeDialog::OnReloadLocalization()
  1167. {
  1168. // reload localization files
  1169. g_pVGuiLocalize->ReloadLocalizationFiles( );
  1170. }
  1171. bool BuildModeDialog::IsBuildGroupEnabled()
  1172. {
  1173. // Don't ever edit the actual build dialog!!!
  1174. return false;
  1175. }
  1176. void BuildModeDialog::OnChangeChild( int direction )
  1177. {
  1178. Assert( direction == 1 || direction == -1 );
  1179. if ( !m_pBuildGroup )
  1180. return;
  1181. Panel *current = m_pCurrentPanel;
  1182. Panel *context = m_pBuildGroup->GetContextPanel();
  1183. if ( !current || current == context )
  1184. {
  1185. current = NULL;
  1186. if ( context->GetChildCount() > 0 )
  1187. {
  1188. current = context->GetChild( 0 );
  1189. }
  1190. }
  1191. else
  1192. {
  1193. int i;
  1194. // Move in direction requested
  1195. int children = context->GetChildCount();
  1196. for ( i = 0; i < children; ++i )
  1197. {
  1198. Panel *child = context->GetChild( i );
  1199. if ( child == current )
  1200. {
  1201. break;
  1202. }
  1203. }
  1204. if ( i < children )
  1205. {
  1206. for ( int offset = 1; offset < children; ++offset )
  1207. {
  1208. int test = ( i + ( direction * offset ) ) % children;
  1209. if ( test < 0 )
  1210. test += children;
  1211. if ( test == i )
  1212. continue;
  1213. Panel *check = context->GetChild( test );
  1214. BuildModeDialog *bm = dynamic_cast< BuildModeDialog * >( check );
  1215. if ( bm )
  1216. continue;
  1217. current = check;
  1218. break;
  1219. }
  1220. }
  1221. }
  1222. if ( !current )
  1223. {
  1224. return;
  1225. }
  1226. SetActiveControl( current );
  1227. }