PresetListDialog.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681
  1. /*
  2. ** Command & Conquer Renegade(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. // PresetListDialog.cpp : implementation file
  19. //
  20. #include "stdafx.h"
  21. #include "leveledit.h"
  22. #include "PresetListDialog.h"
  23. #include "presetmgr.h"
  24. #include "definition.h"
  25. #include "definitionfactory.h"
  26. #include "definitionfactorymgr.h"
  27. #include "icons.h"
  28. #include "utils.h"
  29. #include "preset.h"
  30. #include "persistfactory.h"
  31. #ifdef _DEBUG
  32. #define new DEBUG_NEW
  33. #undef THIS_FILE
  34. static char THIS_FILE[] = __FILE__;
  35. #endif
  36. /////////////////////////////////////////////////////////////////////////////
  37. //
  38. // PresetListDialogClass
  39. //
  40. /////////////////////////////////////////////////////////////////////////////
  41. PresetListDialogClass::PresetListDialogClass (CWnd *pParent)
  42. : m_List (NULL),
  43. m_ClassID (0),
  44. m_RootClassID (0),
  45. m_EnableTypeSel (true),
  46. CDialog(PresetListDialogClass::IDD, pParent)
  47. {
  48. //{{AFX_DATA_INIT(PresetListDialogClass)
  49. // NOTE: the ClassWizard will add member initialization here
  50. //}}AFX_DATA_INIT
  51. return ;
  52. }
  53. /////////////////////////////////////////////////////////////////////////////
  54. //
  55. // DoDataExchange
  56. //
  57. /////////////////////////////////////////////////////////////////////////////
  58. void
  59. PresetListDialogClass::DoDataExchange (CDataExchange *pDX)
  60. {
  61. CDialog::DoDataExchange(pDX);
  62. //{{AFX_DATA_MAP(PresetListDialogClass)
  63. DDX_Control(pDX, IDC_TYPE_COMBO, m_ComboBox);
  64. DDX_Control(pDX, IDC_PRESET_TREE, m_PresetTreeCtrl);
  65. DDX_Control(pDX, IDC_PRESET_LIST, m_PresetListCtrl);
  66. //}}AFX_DATA_MAP
  67. return ;
  68. }
  69. BEGIN_MESSAGE_MAP(PresetListDialogClass, CDialog)
  70. //{{AFX_MSG_MAP(PresetListDialogClass)
  71. ON_BN_CLICKED(IDC_ADD, OnAdd)
  72. ON_BN_CLICKED(IDC_REMOVE, OnRemove)
  73. ON_NOTIFY(NM_DBLCLK, IDC_PRESET_LIST, OnDblclkPresetList)
  74. ON_NOTIFY(NM_DBLCLK, IDC_PRESET_TREE, OnDblclkPresetTree)
  75. ON_NOTIFY(LVN_ITEMCHANGED, IDC_PRESET_LIST, OnItemchangedPresetList)
  76. ON_NOTIFY(TVN_SELCHANGED, IDC_PRESET_TREE, OnSelchangedPresetTree)
  77. ON_WM_DESTROY()
  78. ON_CBN_SELENDOK(IDC_TYPE_COMBO, OnSelendokTypeCombo)
  79. ON_CBN_SELCHANGE(IDC_TYPE_COMBO, OnSelchangeTypeCombo)
  80. //}}AFX_MSG_MAP
  81. END_MESSAGE_MAP()
  82. /////////////////////////////////////////////////////////////////////////////
  83. //
  84. // OnInitDialog
  85. //
  86. /////////////////////////////////////////////////////////////////////////////
  87. BOOL
  88. PresetListDialogClass::OnInitDialog (void)
  89. {
  90. CDialog::OnInitDialog ();
  91. ASSERT (m_List != NULL);
  92. //
  93. // Configure the preset list control
  94. //
  95. m_PresetListCtrl.InsertColumn (0, "Name");
  96. m_PresetListCtrl.InsertColumn (1, "Type");
  97. //
  98. // Configure the type combobox
  99. //
  100. Generate_Type_List ();
  101. //
  102. // Add the previously selected presets to the list control
  103. //
  104. for (int index = 0; index < m_List->Count (); index ++) {
  105. //
  106. // Lookup this preset
  107. //
  108. int preset_id = (*m_List)[index];
  109. PresetClass *preset = PresetMgrClass::Find_Preset (preset_id);
  110. //
  111. // Add the preset to the list control
  112. //
  113. Add_Preset (preset);
  114. }
  115. //
  116. // Fill in the tree control
  117. //
  118. m_PresetTreeCtrl.SetImageList (::Get_Global_Image_List (), TVSIL_NORMAL);
  119. Populate_Preset_Tree ();
  120. //
  121. // Size the columns
  122. //
  123. CRect rect;
  124. m_PresetListCtrl.GetClientRect (&rect);
  125. m_PresetListCtrl.SetColumnWidth (0, rect.Width () * 2 / 3);
  126. m_PresetListCtrl.SetColumnWidth (1, (rect.Width () / 3) - 2);
  127. Update_Button_State ();
  128. return TRUE;
  129. }
  130. ////////////////////////////////////////////////////////////////////////////
  131. //
  132. // Update_Button_State
  133. //
  134. ////////////////////////////////////////////////////////////////////////////
  135. void
  136. PresetListDialogClass::Update_Button_State (void)
  137. {
  138. bool enable_add = false;
  139. bool enable_remove = (m_PresetListCtrl.GetNextItem (-1, LVNI_ALL | LVNI_SELECTED) >= 0);
  140. //
  141. // Should the add button be enabled?
  142. //
  143. HTREEITEM tree_item = m_PresetTreeCtrl.GetSelectedItem ();
  144. if (tree_item != NULL) {
  145. PresetClass *preset = (PresetClass *)m_PresetTreeCtrl.GetItemData (tree_item);
  146. if (preset != NULL) {
  147. enable_add = true;
  148. }
  149. }
  150. ::EnableWindow (::GetDlgItem (m_hWnd, IDC_ADD), enable_add);
  151. ::EnableWindow (::GetDlgItem (m_hWnd, IDC_REMOVE), enable_remove);
  152. return ;
  153. }
  154. ////////////////////////////////////////////////////////////////////////////
  155. //
  156. // Sort_Nodes
  157. //
  158. ////////////////////////////////////////////////////////////////////////////
  159. void
  160. PresetListDialogClass::Sort_Nodes (HTREEITEM root_item, bool recursive)
  161. {
  162. for ( HTREEITEM tree_item = m_PresetTreeCtrl.GetChildItem (root_item);
  163. tree_item != NULL;
  164. tree_item = m_PresetTreeCtrl.GetNextSiblingItem (tree_item))
  165. {
  166. //
  167. // Sort the children
  168. //
  169. m_PresetTreeCtrl.SortChildren (tree_item);
  170. //
  171. // Recurse through the hierarchy
  172. //
  173. if (recursive && m_PresetTreeCtrl.ItemHasChildren (tree_item)) {
  174. Sort_Nodes (tree_item, recursive);
  175. }
  176. }
  177. return ;
  178. }
  179. /////////////////////////////////////////////////////////////////////////////
  180. //
  181. // Add_Preset
  182. //
  183. /////////////////////////////////////////////////////////////////////////////
  184. void
  185. PresetListDialogClass::Add_Preset (PresetClass *preset)
  186. {
  187. if (preset != NULL && preset->Get_Definition () != NULL) {
  188. //
  189. // Insert this preset into the list control
  190. //
  191. int list_index = m_PresetListCtrl.InsertItem (0xFFF, preset->Get_Name ());
  192. if (list_index >= 0) {
  193. //
  194. // Set the entry's type name
  195. //
  196. int class_id = preset->Get_Definition ()->Get_Class_ID ();
  197. DefinitionFactoryClass *factory = DefinitionFactoryMgrClass::Find_Factory (class_id);
  198. if (factory != NULL) {
  199. LPCTSTR type_name = factory->Get_Name ();
  200. m_PresetListCtrl.SetItemText (list_index, 1, type_name);
  201. }
  202. //
  203. // Associate the preset ID with this list entry
  204. //
  205. m_PresetListCtrl.SetItemData (list_index, preset->Get_ID ());
  206. }
  207. }
  208. return ;
  209. }
  210. /////////////////////////////////////////////////////////////////////////////
  211. //
  212. // OnOK
  213. //
  214. /////////////////////////////////////////////////////////////////////////////
  215. void
  216. PresetListDialogClass::OnOK (void)
  217. {
  218. m_List->Delete_All ();
  219. int count = m_PresetListCtrl.GetItemCount ();
  220. for (int index = 0; index < count; index ++) {
  221. int preset_id = m_PresetListCtrl.GetItemData (index);
  222. m_List->Add (preset_id);
  223. }
  224. CDialog::OnOK ();
  225. return ;
  226. }
  227. /////////////////////////////////////////////////////////////////////////////
  228. //
  229. // OnAdd
  230. //
  231. /////////////////////////////////////////////////////////////////////////////
  232. void
  233. PresetListDialogClass::OnAdd (void)
  234. {
  235. HTREEITEM tree_item = m_PresetTreeCtrl.GetSelectedItem ();
  236. if (tree_item != NULL) {
  237. //
  238. // Add the preset from the currently selected tree item to the list
  239. //
  240. PresetClass *preset = (PresetClass *)m_PresetTreeCtrl.GetItemData (tree_item);
  241. if (preset != NULL) {
  242. Add_Preset (preset);
  243. }
  244. }
  245. return ;
  246. }
  247. /////////////////////////////////////////////////////////////////////////////
  248. //
  249. // OnRemove
  250. //
  251. /////////////////////////////////////////////////////////////////////////////
  252. void
  253. PresetListDialogClass::OnRemove (void)
  254. {
  255. int index = m_PresetListCtrl.GetNextItem (-1, LVNI_ALL | LVNI_SELECTED);
  256. if (index >= 0) {
  257. m_PresetListCtrl.DeleteItem (index);
  258. //
  259. // Select the previous entry in the list
  260. //
  261. int count = m_PresetListCtrl.GetItemCount ();
  262. if (count > 0) {
  263. if (index >= (count-1)) {
  264. index --;
  265. }
  266. index = max (index, 0);
  267. m_PresetListCtrl.SetItemState (index, LVNI_SELECTED, LVNI_SELECTED);
  268. }
  269. Update_Button_State ();
  270. }
  271. return ;
  272. }
  273. /////////////////////////////////////////////////////////////////////////////
  274. //
  275. // OnDblclkPresetList
  276. //
  277. /////////////////////////////////////////////////////////////////////////////
  278. void
  279. PresetListDialogClass::OnDblclkPresetList
  280. (
  281. NMHDR * pNMHDR,
  282. LRESULT * pResult
  283. )
  284. {
  285. (*pResult) = 0;
  286. OnRemove ();
  287. return ;
  288. }
  289. /////////////////////////////////////////////////////////////////////////////
  290. //
  291. // OnDblclkPresetTree
  292. //
  293. /////////////////////////////////////////////////////////////////////////////
  294. void
  295. PresetListDialogClass::OnDblclkPresetTree
  296. (
  297. NMHDR * pNMHDR,
  298. LRESULT * pResult
  299. )
  300. {
  301. (*pResult) = 0;
  302. OnAdd ();
  303. return ;
  304. }
  305. /////////////////////////////////////////////////////////////////////////////
  306. //
  307. // OnItemchangedPresetList
  308. //
  309. /////////////////////////////////////////////////////////////////////////////
  310. void
  311. PresetListDialogClass::OnItemchangedPresetList
  312. (
  313. NMHDR * pNMHDR,
  314. LRESULT * pResult
  315. )
  316. {
  317. (*pResult) = 0;
  318. Update_Button_State ();
  319. return ;
  320. }
  321. /////////////////////////////////////////////////////////////////////////////
  322. //
  323. // OnSelchangedPresetTree
  324. //
  325. /////////////////////////////////////////////////////////////////////////////
  326. void
  327. PresetListDialogClass::OnSelchangedPresetTree
  328. (
  329. NMHDR * pNMHDR,
  330. LRESULT * pResult
  331. )
  332. {
  333. (*pResult) = 0;
  334. Update_Button_State ();
  335. return ;
  336. }
  337. /////////////////////////////////////////////////////////////////////////////
  338. //
  339. // OnDestroy
  340. //
  341. /////////////////////////////////////////////////////////////////////////////
  342. void
  343. PresetListDialogClass::OnDestroy (void)
  344. {
  345. m_PresetTreeCtrl.SetImageList (NULL, TVSIL_NORMAL);
  346. CDialog::OnDestroy ();
  347. return ;
  348. }
  349. /////////////////////////////////////////////////////////////////////////////
  350. //
  351. // Generate_Type_List
  352. //
  353. /////////////////////////////////////////////////////////////////////////////
  354. void
  355. PresetListDialogClass::Generate_Type_List (void)
  356. {
  357. //
  358. // Configure the combo-box
  359. //
  360. m_ComboBox.SetImageList (::Get_Global_Image_List ());
  361. m_ComboBox.EnableWindow (m_EnableTypeSel);
  362. //
  363. // Build a tree of factories
  364. //
  365. FACTORY_TREE factory_tree;
  366. PresetMgrClass::Build_Factory_Tree (m_RootClassID, factory_tree);
  367. //
  368. // Default to game-objects if no other type is selected
  369. //
  370. if (m_ClassID == 0) {
  371. m_ClassID = CLASSID_GAME_OBJECTS;
  372. }
  373. //
  374. // Put these factories into the combobox
  375. //
  376. int index = 0;
  377. Add_Factories_To_Combo (factory_tree.Peek_Root (), 0, index);
  378. return ;
  379. }
  380. /////////////////////////////////////////////////////////////////////////////
  381. //
  382. // Add_Factories_To_Combo
  383. //
  384. /////////////////////////////////////////////////////////////////////////////
  385. void
  386. PresetListDialogClass::Add_Factories_To_Combo
  387. (
  388. NTreeLeafClass<uint32> *leaf,
  389. int indent,
  390. int & index
  391. )
  392. {
  393. do
  394. {
  395. uint32 class_id = leaf->Get_Value ();
  396. //
  397. // Add this factory to the combobox
  398. //
  399. COMBOBOXEXITEM item = { 0 };
  400. item.mask = CBEIF_IMAGE | CBEIF_INDENT | CBEIF_LPARAM | CBEIF_TEXT | CBEIF_SELECTEDIMAGE;
  401. item.pszText = (char *)::Get_Factory_Name (class_id);
  402. item.iImage = FOLDER_ICON;
  403. item.iSelectedImage = FOLDER_ICON;
  404. item.iIndent = indent;
  405. item.lParam = (long)class_id;
  406. item.iItem = index ++;
  407. int item_index = m_ComboBox.InsertItem (&item);
  408. //
  409. // Is this the factory we need to select?
  410. //
  411. if (class_id == m_ClassID) {
  412. m_ComboBox.SetCurSel (item_index);
  413. }
  414. //
  415. // Recurse if necessary
  416. //
  417. NTreeLeafClass<uint32> *child = leaf->Peek_Child ();
  418. if (child != NULL) {
  419. Add_Factories_To_Combo (child, indent + 1, index);
  420. }
  421. } while ((leaf = leaf->Peek_Next ()) != NULL);
  422. return ;
  423. }
  424. /////////////////////////////////////////////////////////////////////////////
  425. //
  426. // Populate_Preset_Tree
  427. //
  428. /////////////////////////////////////////////////////////////////////////////
  429. void
  430. PresetListDialogClass::Populate_Preset_Tree (void)
  431. {
  432. //
  433. // Start fresh
  434. //
  435. CWaitCursor wait_cursor;
  436. m_PresetTreeCtrl.DeleteAllItems ();
  437. //
  438. // Should we add any sub-factories to the tree?
  439. //
  440. if (DefinitionFactoryMgrClass::Find_Factory (m_ClassID) == NULL) {
  441. //
  442. // Generate the tree from its sub-factories
  443. //
  444. DefinitionFactoryClass *factory = NULL;
  445. for ( factory = DefinitionFactoryMgrClass::Get_First (m_ClassID);
  446. factory != NULL;
  447. factory = DefinitionFactoryMgrClass::Get_Next (factory, m_ClassID))
  448. {
  449. if (factory->Is_Displayed ()) {
  450. HTREEITEM folder_item = m_PresetTreeCtrl.InsertItem (factory->Get_Name (), FOLDER_ICON, FOLDER_ICON);
  451. //
  452. // Generate the tree of presets
  453. //
  454. PRESET_TREE preset_tree;
  455. PresetMgrClass::Build_Preset_Tree (factory->Get_Class_ID (), preset_tree);
  456. //
  457. // Populate the tree control
  458. //
  459. Fill_Tree (preset_tree.Peek_Root (), folder_item);
  460. }
  461. }
  462. } else {
  463. //
  464. // Generate the tree of presets
  465. //
  466. PRESET_TREE preset_tree;
  467. PresetMgrClass::Build_Preset_Tree (m_ClassID, preset_tree);
  468. //
  469. // Populate the tree control
  470. //
  471. Fill_Tree (preset_tree.Peek_Root (), TVI_ROOT);
  472. }
  473. return ;
  474. }
  475. /////////////////////////////////////////////////////////////////////////////
  476. //
  477. // Fill_Tree
  478. //
  479. /////////////////////////////////////////////////////////////////////////////
  480. void
  481. PresetListDialogClass::Fill_Tree (NTreeLeafClass<PresetClass *> *leaf, HTREEITEM parent_item)
  482. {
  483. //
  484. // Loop over all the presets
  485. //
  486. for ( ; leaf != NULL; leaf = leaf->Peek_Next ()) {
  487. PresetClass *preset = leaf->Get_Value ();
  488. ASSERT (preset != NULL);
  489. if (preset != NULL) {
  490. //
  491. // Insert the new preset into the tree
  492. //
  493. int icon = preset->Get_Icon_Index ();
  494. HTREEITEM new_item = m_PresetTreeCtrl.InsertItem (preset->Get_Name (), icon, icon, parent_item);
  495. if (new_item != NULL) {
  496. //
  497. // Associate the preset with its tree entry
  498. //
  499. m_PresetTreeCtrl.SetItemData (new_item, (LONG)preset);
  500. //
  501. // Recurse if necessary
  502. //
  503. NTreeLeafClass<PresetClass *> *child = leaf->Peek_Child ();
  504. if (child != NULL) {
  505. Fill_Tree (child, new_item);
  506. m_PresetTreeCtrl.SortChildren (parent_item);
  507. }
  508. }
  509. }
  510. }
  511. return ;
  512. }
  513. /*
  514. //
  515. // Add all the presets (by category) to the tree control
  516. //
  517. DefinitionFactoryClass *factory = NULL;
  518. for ( factory = DefinitionFactoryMgrClass::Get_First (m_ClassID);
  519. factory != NULL;
  520. factory = DefinitionFactoryMgrClass::Get_Next (factory, m_ClassID))
  521. {
  522. //
  523. // Add this folder to the tree ctrl
  524. //
  525. HTREEITEM folder_item = m_PresetTreeCtrl.InsertItem (factory->Get_Name (), FOLDER_ICON, FOLDER_ICON);
  526. //
  527. // Add all the folder contents to the tree ctrl
  528. //
  529. PresetClass *preset = NULL;
  530. uint32 factory_id = factory->Get_Class_ID ();
  531. for ( preset = PresetMgrClass::Get_First (factory_id, PresetMgrClass::ID_CLASS);
  532. preset != NULL;
  533. preset = PresetMgrClass::Get_Next (preset, factory_id, PresetMgrClass::ID_CLASS))
  534. {
  535. //
  536. // Add this preset to the tree ctrl
  537. //
  538. HTREEITEM preset_item = m_PresetTreeCtrl.InsertItem ( preset->Get_Name (),
  539. OBJECT_ICON,
  540. OBJECT_ICON,
  541. folder_item);
  542. m_PresetTreeCtrl.SetItemData (preset_item, (ULONG)preset);
  543. }
  544. }
  545. //
  546. // Sort the tree control
  547. //
  548. Sort_Nodes (TVI_ROOT, true);
  549. m_PresetTreeCtrl.SortChildren (TVI_ROOT);
  550. return ;
  551. }*/
  552. /////////////////////////////////////////////////////////////////////////////
  553. //
  554. // OnSelendokTypeCombo
  555. //
  556. /////////////////////////////////////////////////////////////////////////////
  557. void
  558. PresetListDialogClass::OnSelendokTypeCombo (void)
  559. {
  560. }
  561. void PresetListDialogClass::OnSelchangeTypeCombo()
  562. {
  563. //
  564. // Get the currently selected type from the combobox
  565. //
  566. int cur_sel = m_ComboBox.GetCurSel ();
  567. if (cur_sel >= 0) {
  568. //
  569. // Repopulate the tree control if the type changed
  570. //
  571. uint32 new_class_id = m_ComboBox.GetItemData (cur_sel);
  572. if (new_class_id != m_ClassID) {
  573. m_ClassID = new_class_id;
  574. Populate_Preset_Tree ();
  575. }
  576. }
  577. return ;
  578. }