InstancesPage.cpp 32 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319
  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. /***********************************************************************************************
  19. *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
  20. ***********************************************************************************************
  21. * *
  22. * Project Name : LevelEdit *
  23. * *
  24. * $Archive:: /Commando/Code/Tools/LevelEdit/InstancesPage.cpp $*
  25. * *
  26. * Author:: Patrick Smith *
  27. * *
  28. * $Modtime:: 5/11/01 9:25a $*
  29. * *
  30. * $Revision:: 14 $*
  31. * *
  32. *---------------------------------------------------------------------------------------------*
  33. * Functions: *
  34. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  35. #include "stdafx.h"
  36. #include "leveledit.h"
  37. #include "instancespage.h"
  38. #include "nodemgr.h"
  39. #include "node.h"
  40. #include "utils.h"
  41. #include "cameramgr.h"
  42. #include "gotoobjectdialog.h"
  43. #include "sceneeditor.h"
  44. #include "icons.h"
  45. #include "nodecategories.h"
  46. #include "definition.h"
  47. #include "definitionfactory.h"
  48. #include "definitionfactorymgr.h"
  49. #include "preset.h"
  50. #ifdef _DEBUG
  51. #define new DEBUG_NEW
  52. #undef THIS_FILE
  53. static char THIS_FILE[] = __FILE__;
  54. #endif
  55. ///////////////////////////////////////////////////////////////////////
  56. // Local prototypes
  57. ///////////////////////////////////////////////////////////////////////
  58. int CALLBACK InstancesListSortCallback (LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort);
  59. #ifndef ListView_SetCheckState
  60. #define ListView_SetCheckState(hwndLV, i, fCheck) \
  61. ListView_SetItemState(hwndLV, i, \
  62. INDEXTOSTATEIMAGEMASK((fCheck)+1), LVIS_STATEIMAGEMASK)
  63. #endif
  64. #ifndef ListView_SetOverlay
  65. #define ListView_SetOverlay(hwndLV, i, overlay) \
  66. ListView_SetItemState(hwndLV, i, \
  67. INDEXTOOVERLAYMASK(overlay), LVIS_OVERLAYMASK)
  68. #endif
  69. ///////////////////////////////////////////////////////////////////////
  70. // Local structures
  71. ///////////////////////////////////////////////////////////////////////
  72. typedef enum
  73. {
  74. TYPE_NAVIGATOR,
  75. TYPE_FACTORY,
  76. TYPE_NODE,
  77. } ITEM_TYPE;
  78. typedef struct
  79. {
  80. ITEM_TYPE type;
  81. StringClass name;
  82. union
  83. {
  84. uint32 class_id;
  85. NodeClass * node;
  86. };
  87. } ITEM_DATA;
  88. /////////////////////////////////////////////////////////////////////////////
  89. // Local constants
  90. /////////////////////////////////////////////////////////////////////////////
  91. const int TOOLBAR_HEIGHT = 36;
  92. const int TOOLBAR_V_SPACING = 5;
  93. const int TOOLBAR_V_BORDER = TOOLBAR_V_SPACING * 2;
  94. const int TOOLBAR_H_SPACING = 5;
  95. const int TOOLBAR_H_BORDER = TOOLBAR_H_SPACING * 2;
  96. //const int COLUMN_CHECK = 0;
  97. //const int COLUMN_PLUS = 1;
  98. const int COLUMN_NAME = 0;
  99. /////////////////////////////////////////////////////////////////////////////
  100. //
  101. // InstancesPageClass
  102. //
  103. /////////////////////////////////////////////////////////////////////////////
  104. InstancesPageClass::InstancesPageClass (CWnd *parent_wnd)
  105. : m_ClassID (0),
  106. CDialog(InstancesPageClass::IDD)
  107. {
  108. //{{AFX_DATA_INIT(InstancesPageClass)
  109. //}}AFX_DATA_INIT
  110. Create (InstancesPageClass::IDD, parent_wnd);
  111. return ;
  112. }
  113. /////////////////////////////////////////////////////////////////////////////
  114. //
  115. // ~InstancesPageClass
  116. //
  117. /////////////////////////////////////////////////////////////////////////////
  118. InstancesPageClass::~InstancesPageClass (void)
  119. {
  120. return ;
  121. }
  122. /////////////////////////////////////////////////////////////////////////////
  123. //
  124. // DoDataExchange
  125. //
  126. /////////////////////////////////////////////////////////////////////////////
  127. void
  128. InstancesPageClass::DoDataExchange (CDataExchange* pDX)
  129. {
  130. CDialog::DoDataExchange(pDX);
  131. //{{AFX_DATA_MAP(InstancesPageClass)
  132. DDX_Control(pDX, IDC_INSTANCE_LIST, m_ListCtrl);
  133. //}}AFX_DATA_MAP
  134. return ;
  135. }
  136. BEGIN_MESSAGE_MAP(InstancesPageClass, CDialog)
  137. //{{AFX_MSG_MAP(InstancesPageClass)
  138. ON_WM_SIZE()
  139. ON_WM_DESTROY()
  140. ON_COMMAND(IDC_EDIT, OnEdit)
  141. ON_COMMAND(IDC_GOTO, OnGoto)
  142. ON_COMMAND(IDC_SHOWALL, OnShowAll)
  143. ON_COMMAND(IDC_SELECT, OnSelect)
  144. ON_COMMAND(IDC_DELETE, OnDelete)
  145. ON_NOTIFY(LVN_DELETEITEM, IDC_INSTANCE_LIST, OnDeleteitemInstanceList)
  146. ON_NOTIFY(NM_DBLCLK, IDC_INSTANCE_LIST, OnDblclkInstanceList)
  147. ON_NOTIFY(LVN_ITEMCHANGED, IDC_INSTANCE_LIST, OnItemchangedInstanceList)
  148. //}}AFX_MSG_MAP
  149. END_MESSAGE_MAP()
  150. #ifdef _DEBUG
  151. void InstancesPageClass::AssertValid() const
  152. {
  153. CDialog::AssertValid();
  154. }
  155. void InstancesPageClass::Dump(CDumpContext& dc) const
  156. {
  157. CDialog::Dump(dc);
  158. }
  159. #endif //_DEBUG
  160. /////////////////////////////////////////////////////////////////////////////
  161. //
  162. // OnSize
  163. //
  164. /////////////////////////////////////////////////////////////////////////////
  165. void
  166. InstancesPageClass::OnSize
  167. (
  168. UINT nType,
  169. int cx,
  170. int cy
  171. )
  172. {
  173. // Allow the base class to process this message
  174. CDialog::OnSize (nType, cx, cy);
  175. if (::IsWindow (m_ListCtrl) && (cx > 0) && (cy > 0)) {
  176. // Get the bounding rectangle of the form window
  177. CRect parentrect;
  178. GetWindowRect (&parentrect);
  179. // Get the bounding rectangle of the toolbar
  180. CRect toolbar_rect;
  181. m_Toolbar.GetWindowRect (&toolbar_rect);
  182. ScreenToClient (&toolbar_rect);
  183. // Move the toolbar so it is in its correct position
  184. m_Toolbar.SetWindowPos (NULL,
  185. TOOLBAR_H_SPACING,
  186. (cy - TOOLBAR_V_SPACING) - toolbar_rect.Height (),
  187. cx - TOOLBAR_H_BORDER,
  188. toolbar_rect.Height (),
  189. SWP_NOZORDER);
  190. // Get the bounding rectnagle of the list ctrl
  191. RECT list_rect;
  192. m_ListCtrl.GetWindowRect (&list_rect);
  193. CRect client_rect = list_rect;
  194. ScreenToClient (&client_rect);
  195. int list_height = ((cy - TOOLBAR_V_BORDER) - toolbar_rect.Height ()) - client_rect.top;
  196. // Resize the tab control to fill the entire contents of the client area
  197. m_ListCtrl.SetWindowPos ( NULL,
  198. 0,
  199. 0,
  200. cx-((list_rect.left - parentrect.left) << 1),
  201. list_height,
  202. SWP_NOZORDER | SWP_NOMOVE);
  203. }
  204. return ;
  205. }
  206. /////////////////////////////////////////////////////////////////////////////
  207. //
  208. // OnDestroy
  209. //
  210. /////////////////////////////////////////////////////////////////////////////
  211. void
  212. InstancesPageClass::OnDestroy (void)
  213. {
  214. //
  215. // Free the state image list we associated with the control
  216. //
  217. CImageList *imagelist = m_ListCtrl.GetImageList (LVSIL_STATE);
  218. m_ListCtrl.SetImageList (NULL, LVSIL_STATE);
  219. SAFE_DELETE (imagelist);
  220. //
  221. // Remove the main image list we associated with the control
  222. //
  223. m_ListCtrl.SetImageList (NULL, LVSIL_SMALL);
  224. m_ListCtrl.DeleteAllItems ();
  225. ::RemoveProp (m_ListCtrl, "TRANS_ACCS");
  226. ::RemoveProp (m_hWnd, "TRANS_ACCS");
  227. CDialog::OnDestroy ();
  228. return ;
  229. }
  230. /////////////////////////////////////////////////////////////////////////////
  231. //
  232. // OnEdit
  233. //
  234. /////////////////////////////////////////////////////////////////////////////
  235. void
  236. InstancesPageClass::OnEdit (void)
  237. {
  238. // Show the settings dialog for the currently selected item
  239. NodeClass *node = Get_Item_Node (m_ListCtrl.GetNextItem (-1, LVNI_ALL | LVNI_SELECTED));
  240. if (node != NULL) {
  241. node->Show_Settings_Dialog ();
  242. }
  243. return ;
  244. }
  245. /////////////////////////////////////////////////////////////////////////////
  246. //
  247. // OnGoto
  248. //
  249. /////////////////////////////////////////////////////////////////////////////
  250. void
  251. InstancesPageClass::OnGoto (void)
  252. {
  253. NodeClass *selected_node = NULL;
  254. //
  255. // Try to find the first selected node (if any)
  256. //
  257. int index = m_ListCtrl.GetNextItem (-1, LVNI_SELECTED | LVNI_ALL);
  258. if (index >= 0) {
  259. selected_node = Get_Item_Node (index);
  260. }
  261. //
  262. // Show the 'goto' dialog...
  263. //
  264. GotoObjectDialogClass dialog (selected_node);
  265. dialog.DoModal ();
  266. return ;
  267. }
  268. /////////////////////////////////////////////////////////////////////////////
  269. //
  270. // OnShowAll
  271. //
  272. /////////////////////////////////////////////////////////////////////////////
  273. void
  274. InstancesPageClass::OnShowAll (void)
  275. {
  276. //
  277. // Show all the nodes
  278. //
  279. for ( NodeClass *node = NodeMgrClass::Get_First ();
  280. node != NULL;
  281. node = NodeMgrClass::Get_Next (node))
  282. {
  283. node->Hide (false);
  284. }
  285. //
  286. // Fixup the UI
  287. //
  288. for (int index = 0; index < m_ListCtrl.GetItemCount (); index ++) {
  289. ITEM_DATA *item_data = (ITEM_DATA *)m_ListCtrl.GetItemData (index);
  290. if (item_data != NULL && item_data->type != TYPE_NAVIGATOR) {
  291. ListView_SetCheckState (m_ListCtrl, index, true);
  292. }
  293. }
  294. //
  295. // Make sure the main view is updated
  296. //
  297. ::Refresh_Main_View ();
  298. return ;
  299. }
  300. ////////////////////////////////////////////////////////////////////////////
  301. //
  302. // WindowProc
  303. //
  304. ////////////////////////////////////////////////////////////////////////////
  305. LRESULT
  306. InstancesPageClass::WindowProc
  307. (
  308. UINT message,
  309. WPARAM wParam,
  310. LPARAM lParam
  311. )
  312. {
  313. //
  314. // Is this the message we are expecting?
  315. //
  316. if (message == WM_USER+102) {
  317. int index = (int)lParam;
  318. //
  319. // Should we toggle the checkmark for this entry?
  320. //
  321. ITEM_DATA *item_data = (ITEM_DATA *)m_ListCtrl.GetItemData (index);
  322. if (item_data != NULL && item_data->type != TYPE_NAVIGATOR) {
  323. //
  324. // Either hide or show the selected nodes
  325. //
  326. bool hidden = (ListView_GetCheckState (m_ListCtrl, index) == false);
  327. Hide_Nodes (index, !hidden);
  328. ListView_SetCheckState (m_ListCtrl, index, hidden);
  329. }
  330. }
  331. return CDialog::WindowProc(message, wParam, lParam);
  332. }
  333. ////////////////////////////////////////////////////////////////////////////
  334. //
  335. // CheckBoxSubclassProc
  336. //
  337. ////////////////////////////////////////////////////////////////////////////
  338. LRESULT CALLBACK
  339. CheckBoxSubclassProc
  340. (
  341. HWND hwnd,
  342. UINT message,
  343. WPARAM wparam,
  344. LPARAM lparam
  345. )
  346. {
  347. WNDPROC pold_proc = (WNDPROC)::GetProp (hwnd, "OLDPROC");
  348. if (message == WM_LBUTTONUP) {
  349. //
  350. // Find out where the user clicked
  351. //
  352. LVHITTESTINFO hittest = { 0 };
  353. hittest.pt.x = LOWORD (lparam);
  354. hittest.pt.y = HIWORD (lparam);
  355. ::SendMessage (hwnd, LVM_HITTEST, 0, (LPARAM)&hittest);
  356. //
  357. // Did the user click one of the checkboxes?
  358. //
  359. if (hittest.flags & LVHT_ONITEMSTATEICON) {
  360. //
  361. // Notify the instances page that the user wants to toggle the checkbox
  362. //
  363. ::PostMessage (::GetParent (hwnd), WM_USER+102, 0, (LPARAM)hittest.iItem);
  364. }
  365. } else if (message == WM_DESTROY) {
  366. ::SetWindowLong (hwnd, GWL_WNDPROC, (LONG)pold_proc);
  367. ::RemoveProp (hwnd, "OLDPROC");
  368. }
  369. if (pold_proc != NULL) {
  370. return ::CallWindowProc (pold_proc, hwnd, message, wparam, lparam);
  371. } else {
  372. return ::DefWindowProc (hwnd, message, wparam, lparam);
  373. }
  374. }
  375. ////////////////////////////////////////////////////////////////////////////
  376. //
  377. // OnDblclkInstanceList
  378. //
  379. ////////////////////////////////////////////////////////////////////////////
  380. void
  381. InstancesPageClass::OnDblclkInstanceList
  382. (
  383. NMHDR * pNMHDR,
  384. LRESULT* pResult
  385. )
  386. {
  387. // Determine what client-coord location was double-clicked on
  388. DWORD mouse_pos = ::GetMessagePos ();
  389. POINT hit_point = { GET_X_LPARAM (mouse_pos), GET_Y_LPARAM (mouse_pos) };
  390. m_ListCtrl.ScreenToClient (&hit_point);
  391. // Goto the node that was double-clicked on (if possible)
  392. UINT flags = 0;
  393. int index = m_ListCtrl.HitTest (hit_point, &flags);
  394. if ((index >= 0) && ((flags & LVHT_ONITEMLABEL) || (flags & LVHT_ONITEMICON))) {
  395. ITEM_DATA *item_data = (ITEM_DATA *)m_ListCtrl.GetItemData (index);
  396. if (item_data != NULL) {
  397. if (item_data->type == TYPE_NAVIGATOR) {
  398. //
  399. // Determine which class id we should display
  400. //
  401. int class_id = 0;
  402. if (m_ClassIDStack.Count () > 0) {
  403. class_id = m_ClassIDStack[m_ClassIDStack.Count ()-1];
  404. m_ClassIDStack.Delete (m_ClassIDStack.Count ()-1);
  405. }
  406. Populate_List (class_id);
  407. } else if (item_data->type == TYPE_FACTORY) {
  408. //
  409. // Fill the list with children of the given class id
  410. //
  411. m_ClassIDStack.Add (m_ClassID);
  412. Populate_List (item_data->class_id);
  413. } else {
  414. NodeClass *node = Get_Item_Node (index);
  415. if (node != NULL) {
  416. //
  417. // If this node is a terrain, then display the subojects,
  418. // otherwise snap the camera to the node
  419. //
  420. if (node->Get_Sub_Node_Count () > 0) {
  421. m_ClassIDStack.Add (m_ClassID);
  422. Populate_List (node);
  423. } else {
  424. ::Get_Camera_Mgr ()->Goto_Node (node);
  425. }
  426. }
  427. }
  428. }
  429. }
  430. (*pResult) = 0;
  431. return ;
  432. }
  433. ////////////////////////////////////////////////////////////////////////////
  434. //
  435. // OnSelect
  436. //
  437. ////////////////////////////////////////////////////////////////////////////
  438. void
  439. InstancesPageClass::OnSelect (void)
  440. {
  441. //
  442. // Clear all selected nodes
  443. //
  444. ::Get_Scene_Editor ()->Set_Selection (NULL);
  445. //
  446. // Toggle the selection state of all the nodes in the selection set
  447. //
  448. int index = -1;
  449. while ((index = m_ListCtrl.GetNextItem (index, LVNI_ALL | LVNI_SELECTED)) >= 0) {
  450. NodeClass *node = Get_Item_Node (index);
  451. if (node != NULL) {
  452. ::Get_Scene_Editor ()->Toggle_Selection (node);
  453. }
  454. }
  455. ::Refresh_Main_View ();
  456. return ;
  457. }
  458. ////////////////////////////////////////////////////////////////////////////
  459. //
  460. // OnDelete
  461. //
  462. ////////////////////////////////////////////////////////////////////////////
  463. void
  464. InstancesPageClass::OnDelete (void)
  465. {
  466. CString message = "Are you sure you wish to delete the selected node(s)?";
  467. CString title;
  468. title.LoadString (IDS_DELETE_CONFIRM_TITLE);
  469. //
  470. // Ask the user if they really want to delete the selected item
  471. //
  472. if (MessageBox (message, title, MB_ICONEXCLAMATION | MB_YESNO) == IDYES) {
  473. //
  474. // Build a list of all the nodes we need to delete
  475. //
  476. DynamicVectorClass<NodeClass *> delete_list;
  477. int index = -1;
  478. while ((index = m_ListCtrl.GetNextItem (index, LVNI_ALL | LVNI_SELECTED)) >= 0) {
  479. NodeClass *node = Get_Item_Node (index);
  480. if (node != NULL) {
  481. delete_list.Add (node);
  482. }
  483. }
  484. //
  485. // Delete all the selected nodes
  486. //
  487. for (index = 0; index < delete_list.Count (); index ++) {
  488. ::Get_Scene_Editor ()->Delete_Node (delete_list[index]);
  489. }
  490. ::Refresh_Main_View ();
  491. }
  492. return ;
  493. }
  494. ////////////////////////////////////////////////////////////////////////////
  495. //
  496. // OnInitDialog
  497. //
  498. ////////////////////////////////////////////////////////////////////////////
  499. BOOL
  500. InstancesPageClass::OnInitDialog (void)
  501. {
  502. CDialog::OnInitDialog ();
  503. m_Toolbar.CreateEx (this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_ALIGN_TOP, CRect(0, 0, 0, 0), 101);
  504. m_Toolbar.SetOwner (this);
  505. m_Toolbar.LoadToolBar (IDR_INSTANCES_TOOLBAR);
  506. m_Toolbar.SetBarStyle (m_Toolbar.GetBarStyle () | CBRS_TOOLTIPS | CBRS_FLYBY);
  507. //
  508. // Configure the toolbar
  509. //
  510. CRect parentrect;
  511. GetWindowRect (&parentrect);
  512. m_Toolbar.SetWindowPos (NULL, 0, 0, parentrect.Width () - TOOLBAR_H_BORDER, TOOLBAR_HEIGHT, SWP_NOZORDER | SWP_NOMOVE);
  513. m_Toolbar.Enable_Button (IDC_DELETE, false);
  514. m_Toolbar.Enable_Button (IDC_SELECT, false);
  515. m_Toolbar.Enable_Button (IDC_EDIT, false);
  516. //
  517. // Configure the list control's extended styles
  518. //
  519. //m_ListCtrl.SetExtendedStyle (m_ListCtrl.GetExtendedStyle () | LVS_EX_SUBITEMIMAGES | LVS_EX_FULLROWSELECT);
  520. //
  521. // Create a state imagelist for the list control to use for checkboxes
  522. //
  523. CImageList *imagelist = new CImageList;
  524. imagelist->Create (MAKEINTRESOURCE (IDB_CHECKBOX_STATES1), 13, 0, RGB (255, 0, 255));
  525. m_ListCtrl.SetImageList (imagelist, LVSIL_STATE);
  526. //
  527. // Setup the columns of the list control
  528. //
  529. CRect client_rect;
  530. m_ListCtrl.GetClientRect (&client_rect);
  531. m_ListCtrl.InsertColumn (COLUMN_NAME, "Name");
  532. m_ListCtrl.SetColumnWidth (COLUMN_NAME, client_rect.Width () - 5);
  533. //
  534. // Pass the general use imagelist onto the list control
  535. //
  536. m_ListCtrl.SetImageList (::Get_Global_Image_List (), LVSIL_SMALL);
  537. //
  538. // Subclass the list control so we can handle the checkstates
  539. //
  540. LONG oldproc = ::SetWindowLong (m_ListCtrl, GWL_WNDPROC, (LONG)CheckBoxSubclassProc);
  541. ::SetProp (m_ListCtrl, "OLDPROC", (HANDLE)oldproc);
  542. //
  543. // Populate the list control
  544. //
  545. Reset_List ();
  546. SetProp (m_ListCtrl, "TRANS_ACCS", (HANDLE)1);
  547. SetProp (m_hWnd, "TRANS_ACCS", (HANDLE)1);
  548. return TRUE;
  549. }
  550. /////////////////////////////////////////////////////////////////////////////
  551. //
  552. // Insert_Factory
  553. //
  554. /////////////////////////////////////////////////////////////////////////////
  555. void
  556. InstancesPageClass::Insert_Factory (LPCTSTR name, int class_id)
  557. {
  558. //
  559. // Add an entry to the list control for the factory
  560. //
  561. int index = m_ListCtrl.InsertItem (0xFF, name, FOLDER_ICON);
  562. if (index >= 0) {
  563. //
  564. // Set the text and the icon for this entry
  565. //
  566. //m_ListCtrl.SetItem (index, COLUMN_NAME, LVIF_TEXT | LVIF_IMAGE, name, FOLDER_ICON, 0, 0, 0);
  567. //
  568. // Allocate a new wrapper if we need to
  569. //
  570. ITEM_DATA *item_data = (ITEM_DATA *)m_ListCtrl.GetItemData (index);
  571. if (item_data == NULL) {
  572. item_data = new ITEM_DATA;
  573. }
  574. //
  575. // Set a flag in the wrapper so we know what kind of data
  576. // this list item contains.
  577. //
  578. item_data->type = TYPE_FACTORY;
  579. item_data->class_id = class_id;
  580. item_data->name = name;
  581. m_ListCtrl.SetItemData (index, (DWORD)item_data);
  582. m_ListCtrl.SetCheck (index, TRUE);
  583. }
  584. return ;
  585. }
  586. /////////////////////////////////////////////////////////////////////////////
  587. //
  588. // Insert_Node
  589. //
  590. /////////////////////////////////////////////////////////////////////////////
  591. void
  592. InstancesPageClass::Insert_Node (NodeClass *node)
  593. {
  594. //
  595. // Add an entry to the list control for the node
  596. //
  597. int index = m_ListCtrl.InsertItem (0xFF, node->Get_Name (), node->Get_Icon_Index ());
  598. if (index >= 0) {
  599. //
  600. // Set the text and the icon for this entry
  601. //
  602. //m_ListCtrl.SetItem (index, COLUMN_NAME, LVIF_TEXT | LVIF_IMAGE, node->Get_Name (), node->Get_Icon_Index (), 0, 0, 0);
  603. //
  604. // Allocate a new wrapper if we need to
  605. //
  606. ITEM_DATA *item_data = (ITEM_DATA *)m_ListCtrl.GetItemData (index);
  607. if (item_data == NULL) {
  608. item_data = new ITEM_DATA;
  609. }
  610. //
  611. // Set a flag in the wrapper so we know what kind of data
  612. // this list item contains.
  613. //
  614. SAFE_ADD_REF (node);
  615. item_data->type = TYPE_NODE;
  616. item_data->node = node;
  617. item_data->name = node->Get_Name ();
  618. m_ListCtrl.SetItemData (index, (DWORD)item_data);
  619. ListView_SetCheckState (m_ListCtrl, index, (node->Is_Hidden () == false));
  620. }
  621. return ;
  622. }
  623. /////////////////////////////////////////////////////////////////////////////
  624. //
  625. // Insert_Navigator
  626. //
  627. /////////////////////////////////////////////////////////////////////////////
  628. void
  629. InstancesPageClass::Insert_Navigator (void)
  630. {
  631. //
  632. // Add an entry to the list control for the navigator
  633. //
  634. int index = m_ListCtrl.InsertItem (0xFF, "..", NAVIGATOR_ICON);
  635. if (index >= 0) {
  636. //
  637. // Set the text and the icon for this entry
  638. //
  639. //m_ListCtrl.SetItem (index, COLUMN_NAME, LVIF_TEXT | LVIF_IMAGE, "..", NAVIGATOR_ICON, 0, 0, 0);
  640. //
  641. // Allocate a new wrapper if we need to
  642. //
  643. ITEM_DATA *item_data = (ITEM_DATA *)m_ListCtrl.GetItemData (index);
  644. if (item_data == NULL) {
  645. item_data = new ITEM_DATA;
  646. }
  647. //
  648. // Set a flag in the wrapper so we know what kind of data
  649. // this list item contains.
  650. //
  651. item_data->type = TYPE_NAVIGATOR;
  652. item_data->node = NULL;
  653. item_data->name = "..";
  654. m_ListCtrl.SetItemData (index, (DWORD)item_data);
  655. }
  656. return ;
  657. }
  658. ////////////////////////////////////////////////////////////////////////////
  659. //
  660. // Add_Node
  661. //
  662. ////////////////////////////////////////////////////////////////////////////
  663. void
  664. InstancesPageClass::Add_Node (NodeClass *node)
  665. {
  666. WWASSERT (node != NULL);
  667. PresetClass *preset = node->Get_Preset ();
  668. if (preset != NULL) {
  669. DefinitionClass *definition = preset->Get_Definition ();
  670. WWASSERT (definition != NULL);
  671. if (definition != NULL) {
  672. //
  673. // Should the node be inserted into the current view?
  674. //
  675. if (definition->Get_Class_ID () == m_ClassID) {
  676. m_ListCtrl.SetRedraw (FALSE);
  677. Insert_Node (node);
  678. m_ListCtrl.SortItems (InstancesListSortCallback, 0L);
  679. m_ListCtrl.SetRedraw (TRUE);
  680. }
  681. }
  682. }
  683. Update_Overlays ();
  684. return ;
  685. }
  686. ////////////////////////////////////////////////////////////////////////////
  687. //
  688. // Remove_Node
  689. //
  690. ////////////////////////////////////////////////////////////////////////////
  691. void
  692. InstancesPageClass::Remove_Node (NodeClass *node)
  693. {
  694. WWASSERT (node != NULL);
  695. //
  696. // Attempt to find this node in the current view
  697. //
  698. for (int index = 0; index < m_ListCtrl.GetItemCount (); index ++) {
  699. NodeClass *curr_node = Get_Item_Node (index);
  700. //
  701. // If this is the node we are looking for, then remove it from
  702. // the view.
  703. //
  704. if (curr_node == node) {
  705. m_ListCtrl.DeleteItem (index);
  706. break;
  707. }
  708. }
  709. Update_Overlays ();
  710. return ;
  711. }
  712. /////////////////////////////////////////////////////////////////////////////
  713. //
  714. // Get_Item_Node
  715. //
  716. /////////////////////////////////////////////////////////////////////////////
  717. NodeClass *
  718. InstancesPageClass::Get_Item_Node (int index)
  719. {
  720. NodeClass *node = NULL;
  721. //
  722. // If this item represents a node, then return the node
  723. // pointer to the caller.
  724. //
  725. ITEM_DATA *item_data = (ITEM_DATA *)m_ListCtrl.GetItemData (index);
  726. if ((item_data != NULL) && (item_data->type == TYPE_NODE)) {
  727. node = item_data->node;
  728. }
  729. return node;
  730. }
  731. ////////////////////////////////////////////////////////////////////////////
  732. //
  733. // Set_Node_Check
  734. //
  735. ////////////////////////////////////////////////////////////////////////////
  736. void
  737. InstancesPageClass::Set_Node_Check
  738. (
  739. int index,
  740. bool onoff
  741. )
  742. {
  743. // First off, show/hide the node
  744. /*NodeClass *node = Get_Item_Node (index);
  745. if (node != NULL) {
  746. node->Hide (!onoff);
  747. }*/
  748. // Update the UI for this node
  749. //ListView_SetCheckState (m_ListCtrl, index, onoff);
  750. return ;
  751. }
  752. ////////////////////////////////////////////////////////////////////////////
  753. //
  754. // Reset_List
  755. //
  756. ////////////////////////////////////////////////////////////////////////////
  757. void
  758. InstancesPageClass::Reset_List (void)
  759. {
  760. m_ClassIDStack.Delete_All ();
  761. Populate_List ((uint32)0);
  762. return ;
  763. }
  764. ////////////////////////////////////////////////////////////////////////////
  765. //
  766. // Populate_List
  767. //
  768. ////////////////////////////////////////////////////////////////////////////
  769. void
  770. InstancesPageClass::Populate_List (uint32 class_id)
  771. {
  772. m_ListCtrl.SetRedraw (FALSE);
  773. m_ListCtrl.DeleteAllItems ();
  774. if (class_id == 0) {
  775. //
  776. // Add all the node categories to the list control
  777. //
  778. for (int index = 0; index < PRESET_CATEGORY_COUNT; index ++) {
  779. Insert_Factory (PRESET_CATEGORIES[index].name, PRESET_CATEGORIES[index].clsid);
  780. }
  781. } else {
  782. Insert_Navigator ();
  783. //
  784. // Fill all the node instances into the list control
  785. //
  786. for ( NodeClass *node = NodeMgrClass::Find_First (class_id);
  787. node != NULL;
  788. node = NodeMgrClass::Find_Next (node, class_id))
  789. {
  790. //
  791. // Add this node to the list control
  792. //
  793. Insert_Node (node);
  794. }
  795. //
  796. // Fill all the factory instances into the list control
  797. //
  798. for ( DefinitionFactoryClass *factory = DefinitionFactoryMgrClass::Get_First (class_id);
  799. factory != NULL;
  800. factory = DefinitionFactoryMgrClass::Get_Next (factory, class_id))
  801. {
  802. //
  803. // Add this node to the list control
  804. //
  805. if (factory->Get_Class_ID () != class_id) {
  806. Insert_Factory (factory->Get_Name (), factory->Get_Class_ID ());
  807. }
  808. }
  809. //
  810. // Sort all the items
  811. //
  812. m_ListCtrl.SortItems (InstancesListSortCallback, 0L);
  813. }
  814. m_ListCtrl.SetRedraw (TRUE);
  815. //
  816. // Save this class ID for later
  817. //
  818. m_ClassID = class_id;
  819. //
  820. // Make sure the toolbar is up to date
  821. //
  822. Update_Overlays ();
  823. Update_Button_States ();
  824. return ;
  825. }
  826. ////////////////////////////////////////////////////////////////////////////
  827. //
  828. // Populate_List
  829. //
  830. ////////////////////////////////////////////////////////////////////////////
  831. void
  832. InstancesPageClass::Populate_List (NodeClass *node)
  833. {
  834. m_ListCtrl.SetRedraw (FALSE);
  835. m_ListCtrl.DeleteAllItems ();
  836. if (node != NULL) {
  837. Insert_Navigator ();
  838. //
  839. // Add all the sub-nodes to the list control
  840. //
  841. for (int index = 0; index < node->Get_Sub_Node_Count (); index ++) {
  842. NodeClass *sub_node = node->Get_Sub_Node (index);
  843. if (sub_node != NULL) {
  844. //
  845. // Add this node to the list control
  846. //
  847. Insert_Node (sub_node);
  848. }
  849. }
  850. }
  851. //
  852. // Sort all the items
  853. //
  854. m_ListCtrl.SortItems (InstancesListSortCallback, 0L);
  855. m_ListCtrl.SetRedraw (TRUE);
  856. //
  857. // Make sure the toolbar is up to date
  858. //
  859. Update_Overlays ();
  860. Update_Button_States ();
  861. return ;
  862. }
  863. ////////////////////////////////////////////////////////////////////////////
  864. //
  865. // OnDeleteitemInstanceList
  866. //
  867. ////////////////////////////////////////////////////////////////////////////
  868. void
  869. InstancesPageClass::OnDeleteitemInstanceList
  870. (
  871. NMHDR * pNMHDR,
  872. LRESULT * pResult
  873. )
  874. {
  875. NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
  876. (*pResult) = 0;
  877. // Get the node associated with this entry
  878. NodeClass *node = Get_Item_Node (pNMListView->iItem);
  879. MEMBER_RELEASE (node);
  880. // Free the item data structure associated with this entry
  881. ITEM_DATA *item_data = (ITEM_DATA *)m_ListCtrl.GetItemData (pNMListView->iItem);
  882. SAFE_DELETE (item_data);
  883. m_ListCtrl.SetItemData (pNMListView->iItem, 0L);
  884. return ;
  885. }
  886. ////////////////////////////////////////////////////////////////////////////
  887. //
  888. // InstancesListSortCallback
  889. //
  890. ////////////////////////////////////////////////////////////////////////////
  891. int CALLBACK
  892. InstancesListSortCallback
  893. (
  894. LPARAM lParam1,
  895. LPARAM lParam2,
  896. LPARAM lParamSort
  897. )
  898. {
  899. int retval = 0;
  900. ITEM_DATA *item_data1 = (ITEM_DATA *)lParam1;
  901. ITEM_DATA *item_data2 = (ITEM_DATA *)lParam2;
  902. if (item_data1 != NULL && item_data2 != NULL) {
  903. //
  904. // Do the types match?
  905. //
  906. if (item_data1->type == item_data2->type) {
  907. //
  908. // Do a simple name comparison
  909. //
  910. retval = ::lstrcmpi (item_data1->name, item_data2->name);
  911. } else {
  912. //
  913. // Sort based on type
  914. //
  915. retval = (item_data1->type - item_data2->type);
  916. }
  917. }
  918. return retval;
  919. }
  920. ////////////////////////////////////////////////////////////////////////////
  921. //
  922. // OnItemchangedInstanceList
  923. //
  924. ////////////////////////////////////////////////////////////////////////////
  925. void
  926. InstancesPageClass::OnItemchangedInstanceList
  927. (
  928. NMHDR * pNMHDR,
  929. LRESULT* pResult
  930. )
  931. {
  932. NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
  933. *pResult = 0;
  934. if (pNMListView->uChanged & LVIF_STATE) {
  935. //
  936. // Did the selection set change?
  937. //
  938. if (pNMListView->uNewState & LVIS_SELECTED || pNMListView->uOldState & LVIS_SELECTED) {
  939. Update_Button_States ();
  940. }
  941. }
  942. return ;
  943. }
  944. ////////////////////////////////////////////////////////////////////////////
  945. //
  946. // Update_Button_States
  947. //
  948. ////////////////////////////////////////////////////////////////////////////
  949. void
  950. InstancesPageClass::Update_Button_States (void)
  951. {
  952. //
  953. // Determine if there are any nodes in the current selection set.
  954. //
  955. bool enable = false;
  956. int index = -1;
  957. while (!enable && (index = m_ListCtrl.GetNextItem (index, LVNI_ALL | LVNI_SELECTED)) >= 0) {
  958. enable |= (Get_Item_Node (index) != NULL);
  959. }
  960. //
  961. // Enable or disable the edit button depending on
  962. // whether the selected item is a category or a node
  963. //
  964. m_Toolbar.Enable_Button (IDC_DELETE, enable);
  965. m_Toolbar.Enable_Button (IDC_EDIT, enable);
  966. m_Toolbar.Enable_Button (IDC_SELECT, enable);
  967. return ;
  968. }
  969. ////////////////////////////////////////////////////////////////////////////
  970. //
  971. // Hide_Node
  972. //
  973. ////////////////////////////////////////////////////////////////////////////
  974. void
  975. InstancesPageClass::Hide_Node (NodeClass *node, uint32 class_id, bool hide)
  976. {
  977. PresetClass *preset = node->Get_Preset ();
  978. if (preset != NULL) {
  979. DefinitionClass *definition = preset->Get_Definition ();
  980. if (definition != NULL) {
  981. //
  982. // Did this node come from the selected factory?
  983. //
  984. uint32 curr_class_id = definition->Get_Class_ID ();
  985. uint32 superclass_id = ::SuperClassID_From_ClassID (curr_class_id);
  986. if (curr_class_id == class_id || superclass_id == class_id) {
  987. //
  988. // Change this node's display state
  989. //
  990. node->Hide (hide);
  991. }
  992. }
  993. }
  994. //
  995. // Now, check all this nodes children
  996. //
  997. for (int index = 0; index < node->Get_Sub_Node_Count (); index ++) {
  998. NodeClass *sub_node = node->Get_Sub_Node (index);
  999. if (sub_node != NULL) {
  1000. Hide_Node (sub_node, class_id, hide);
  1001. }
  1002. }
  1003. return ;
  1004. }
  1005. ////////////////////////////////////////////////////////////////////////////
  1006. //
  1007. // Hide_Nodes
  1008. //
  1009. ////////////////////////////////////////////////////////////////////////////
  1010. void
  1011. InstancesPageClass::Hide_Nodes (int index, bool hide)
  1012. {
  1013. ITEM_DATA *item_data = (ITEM_DATA *)m_ListCtrl.GetItemData (index);
  1014. if (item_data != NULL) {
  1015. if (item_data->type == TYPE_FACTORY) {
  1016. //
  1017. // Loop over all the nodes in the world
  1018. //
  1019. for ( NodeClass *node = NodeMgrClass::Get_First ();
  1020. node != NULL;
  1021. node = NodeMgrClass::Get_Next (node))
  1022. {
  1023. //
  1024. // Hide this node (if necessary)
  1025. //
  1026. Hide_Node (node, item_data->class_id, hide);
  1027. }
  1028. } else if (item_data->type == TYPE_NODE) {
  1029. //
  1030. // Change this node's display state
  1031. //
  1032. item_data->node->Hide (hide);
  1033. }
  1034. }
  1035. //
  1036. // Make sure the main view is updated
  1037. //
  1038. ::Refresh_Main_View ();
  1039. return ;
  1040. }
  1041. /////////////////////////////////////////////////////////////////////////////
  1042. //
  1043. // Update_Overlays
  1044. //
  1045. /////////////////////////////////////////////////////////////////////////////
  1046. void
  1047. InstancesPageClass::Update_Overlays (void)
  1048. {
  1049. //
  1050. // Loop over all the entries in the current view
  1051. //
  1052. for (int index = 0; index < m_ListCtrl.GetItemCount (); index ++) {
  1053. //
  1054. // Get information about this entry
  1055. //
  1056. ITEM_DATA *item_data = (ITEM_DATA *)m_ListCtrl.GetItemData (index);
  1057. if (item_data != NULL) {
  1058. bool needs_overlay = false;
  1059. //
  1060. // Check to see if this entry has any sub-entries
  1061. //
  1062. if (item_data->type == TYPE_FACTORY) {
  1063. needs_overlay = Does_Factory_Have_Children (item_data->class_id);
  1064. } else if (item_data->type == TYPE_NODE && (item_data->node->Get_Sub_Node_Count () > 0)) {
  1065. needs_overlay = true;
  1066. }
  1067. //
  1068. // Set the appropriate overlay
  1069. //
  1070. ListView_SetOverlay (m_ListCtrl, index, needs_overlay ? 1 : 0);
  1071. }
  1072. }
  1073. return ;
  1074. }
  1075. /////////////////////////////////////////////////////////////////////////////
  1076. //
  1077. // Does_Factory_Have_Children
  1078. //
  1079. /////////////////////////////////////////////////////////////////////////////
  1080. bool
  1081. InstancesPageClass::Does_Factory_Have_Children (uint32 factory_id)
  1082. {
  1083. bool retval = false;
  1084. //
  1085. // Check to see if there are any instances of this factory
  1086. // in the world
  1087. //
  1088. for ( NodeClass *node = NodeMgrClass::Get_First ();
  1089. node != NULL && retval == false;
  1090. node = NodeMgrClass::Get_Next (node))
  1091. {
  1092. PresetClass *preset = node->Get_Preset ();
  1093. if (preset != NULL) {
  1094. DefinitionClass *definition = preset->Get_Definition ();
  1095. if (definition != NULL) {
  1096. //
  1097. // Did this node come from the specified factory?
  1098. //
  1099. uint32 class_id = definition->Get_Class_ID ();
  1100. uint32 superclass_id = ::SuperClassID_From_ClassID (class_id);
  1101. if (class_id == factory_id || superclass_id == factory_id) {
  1102. retval = true;
  1103. }
  1104. }
  1105. }
  1106. }
  1107. //
  1108. // Check to see if this factory has any sub-factories
  1109. //
  1110. if (retval == false) {
  1111. DefinitionFactoryClass *factory = DefinitionFactoryMgrClass::Get_First (factory_id);
  1112. if (factory != NULL && factory->Get_Class_ID () != factory_id) {
  1113. retval = true;
  1114. }
  1115. }
  1116. return retval;
  1117. }