ConversationPage.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896
  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/ConversationPage.cpp $*
  25. * *
  26. * Author:: Patrick Smith *
  27. * *
  28. * $Modtime:: 2/12/02 9:57a $*
  29. * *
  30. * $Revision:: 5 $*
  31. * *
  32. *---------------------------------------------------------------------------------------------*
  33. * Functions: *
  34. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  35. #include "stdafx.h"
  36. #include "leveledit.h"
  37. #include "conversationpage.h"
  38. #include "nodemgr.h"
  39. #include "node.h"
  40. #include "icons.h"
  41. #include "conversation.h"
  42. #include "conversationmgr.h"
  43. #include "editconversationdialog.h"
  44. #include "conversationeditormgr.h"
  45. #ifdef _DEBUG
  46. #define new DEBUG_NEW
  47. #undef THIS_FILE
  48. static char THIS_FILE[] = __FILE__;
  49. #endif
  50. ///////////////////////////////////////////////////////////////////////
  51. //
  52. // Helper objects
  53. //
  54. ///////////////////////////////////////////////////////////////////////
  55. class TreeStateCaptureClass
  56. {
  57. public:
  58. TreeStateCaptureClass (CTreeCtrl &tree_ctrl, HTREEITEM *item_handle, ConversationClass **conversation_ptr)
  59. : ConversationID (0),
  60. ConversationPtr (conversation_ptr),
  61. ItemHandle (item_handle),
  62. TreeCtrl (tree_ctrl)
  63. {
  64. if (conversation_ptr != NULL) {
  65. ConversationID = (*conversation_ptr)->Get_ID ();
  66. }
  67. return ;
  68. }
  69. void Restore (void)
  70. {
  71. if (ItemHandle != NULL) {
  72. (*ItemHandle) = NULL;
  73. }
  74. if (ConversationPtr != NULL) {
  75. (*ConversationPtr) = NULL;
  76. }
  77. Find_Entry (TVI_ROOT);
  78. //
  79. // Ensure the item is visible
  80. //
  81. if (ItemHandle != NULL && (*ItemHandle) != NULL) {
  82. TreeCtrl.SelectItem (*ItemHandle);
  83. TreeCtrl.EnsureVisible (*ItemHandle);
  84. }
  85. return ;
  86. }
  87. bool Find_Entry (HTREEITEM parent_item)
  88. {
  89. bool retval = false;
  90. //
  91. // Loop over all the children of this tree item
  92. //
  93. for ( HTREEITEM child_item = TreeCtrl.GetNextItem (parent_item, TVGN_CHILD);
  94. retval == false && child_item != NULL;
  95. child_item = TreeCtrl.GetNextItem (child_item, TVGN_NEXT))
  96. {
  97. //
  98. // Is this the conversation we are looking for?
  99. //
  100. ConversationClass *conversation = (ConversationClass *)TreeCtrl.GetItemData (child_item);
  101. if (conversation != NULL && conversation->Get_ID () == ConversationID) {
  102. if (ItemHandle != NULL) {
  103. (*ItemHandle) = child_item;
  104. }
  105. if (ConversationPtr != NULL) {
  106. (*ConversationPtr) = conversation;
  107. }
  108. retval = true;
  109. break ;
  110. }
  111. //
  112. // Recurse into this child (if necessary)
  113. //
  114. if (TreeCtrl.ItemHasChildren (child_item)) {
  115. retval = Find_Entry (child_item);
  116. }
  117. }
  118. return retval;
  119. }
  120. private:
  121. int ConversationID;
  122. CTreeCtrl & TreeCtrl;
  123. HTREEITEM * ItemHandle;
  124. ConversationClass ** ConversationPtr;
  125. };
  126. /////////////////////////////////////////////////////////////////////////////
  127. // Static member initialization
  128. /////////////////////////////////////////////////////////////////////////////
  129. ConversationPageClass * ConversationPageClass::_TheInstance = NULL;
  130. /////////////////////////////////////////////////////////////////////////////
  131. // Local constants
  132. /////////////////////////////////////////////////////////////////////////////
  133. static const int TOOLBAR_HEIGHT = 36;
  134. static const int TOOLBAR_V_SPACING = 5;
  135. static const int TOOLBAR_V_BORDER = TOOLBAR_V_SPACING * 2;
  136. static const int TOOLBAR_H_SPACING = 5;
  137. static const int TOOLBAR_H_BORDER = TOOLBAR_H_SPACING * 2;
  138. /////////////////////////////////////////////////////////////////////////////
  139. //
  140. // ConversationPageClass
  141. //
  142. /////////////////////////////////////////////////////////////////////////////
  143. ConversationPageClass::ConversationPageClass(CWnd* pParent /*=NULL*/) :
  144. m_GlobalsRoot (NULL),
  145. m_LevelsRoot (NULL),
  146. CDialog(ConversationPageClass::IDD, pParent)
  147. {
  148. //{{AFX_DATA_INIT(ConversationPageClass)
  149. // NOTE: the ClassWizard will add member initialization here
  150. //}}AFX_DATA_INIT
  151. Create (ConversationPageClass::IDD, pParent);
  152. _TheInstance = this;
  153. return ;
  154. }
  155. /////////////////////////////////////////////////////////////////////////////
  156. //
  157. // ~ConversationPageClass
  158. //
  159. /////////////////////////////////////////////////////////////////////////////
  160. ConversationPageClass::~ConversationPageClass (void)
  161. {
  162. _TheInstance = NULL;
  163. return ;
  164. }
  165. /////////////////////////////////////////////////////////////////////////////
  166. //
  167. // DoDataExchange
  168. //
  169. /////////////////////////////////////////////////////////////////////////////
  170. void
  171. ConversationPageClass::DoDataExchange (CDataExchange *pDX)
  172. {
  173. CDialog::DoDataExchange(pDX);
  174. //{{AFX_DATA_MAP(ConversationPageClass)
  175. DDX_Control(pDX, IDC_CONVERSATION_TREE, m_TreeCtrl);
  176. //}}AFX_DATA_MAP
  177. return ;
  178. }
  179. BEGIN_MESSAGE_MAP(ConversationPageClass, CDialog)
  180. //{{AFX_MSG_MAP(ConversationPageClass)
  181. ON_NOTIFY(TVN_DELETEITEM, IDC_CONVERSATION_TREE, OnDeleteItemConversationTree)
  182. ON_WM_SIZE()
  183. ON_WM_DESTROY()
  184. ON_NOTIFY(NM_DBLCLK, IDC_CONVERSATION_TREE, OnDblclkConversationTree)
  185. ON_NOTIFY(TVN_ITEMEXPANDED, IDC_CONVERSATION_TREE, OnItemexpandedConversationTree)
  186. ON_COMMAND(IDC_ADD, OnAdd)
  187. ON_COMMAND(IDC_DELETE, OnDelete)
  188. ON_COMMAND(IDC_EDIT, OnEdit)
  189. ON_COMMAND(IDC_SWAP, OnSwap)
  190. //}}AFX_MSG_MAP
  191. END_MESSAGE_MAP()
  192. /////////////////////////////////////////////////////////////////////////////
  193. //
  194. // OnSize
  195. //
  196. /////////////////////////////////////////////////////////////////////////////
  197. void
  198. ConversationPageClass::OnSize
  199. (
  200. UINT nType,
  201. int cx,
  202. int cy
  203. )
  204. {
  205. // Allow the base class to process this message
  206. CDialog::OnSize (nType, cx, cy);
  207. if (::IsWindow (m_TreeCtrl) && (cx > 0) && (cy > 0)) {
  208. // Get the bounding rectangle of the form window
  209. CRect parentrect;
  210. GetWindowRect (&parentrect);
  211. // Get the bounding rectangle of the toolbar
  212. CRect toolbar_rect;
  213. m_Toolbar.GetWindowRect (&toolbar_rect);
  214. ScreenToClient (&toolbar_rect);
  215. // Move the toolbar so it is in its correct position
  216. m_Toolbar.SetWindowPos (NULL,
  217. TOOLBAR_H_SPACING,
  218. (cy - TOOLBAR_V_SPACING) - toolbar_rect.Height (),
  219. cx - TOOLBAR_H_BORDER,
  220. toolbar_rect.Height (),
  221. SWP_NOZORDER);
  222. // Get the bounding rectnagle of the list ctrl
  223. RECT list_rect;
  224. m_TreeCtrl.GetWindowRect (&list_rect);
  225. CRect client_rect = list_rect;
  226. ScreenToClient (&client_rect);
  227. int list_height = ((cy - TOOLBAR_V_BORDER) - toolbar_rect.Height ()) - client_rect.top;
  228. // Resize the tab control to fill the entire contents of the client area
  229. m_TreeCtrl.SetWindowPos ( NULL,
  230. 0,
  231. 0,
  232. cx-((list_rect.left - parentrect.left) << 1),
  233. list_height,
  234. SWP_NOZORDER | SWP_NOMOVE);
  235. }
  236. return ;
  237. }
  238. /////////////////////////////////////////////////////////////////////////////
  239. //
  240. // OnDestroy
  241. //
  242. /////////////////////////////////////////////////////////////////////////////
  243. void
  244. ConversationPageClass::OnDestroy (void)
  245. {
  246. // Free the state image list we associated with the control
  247. CImageList *imagelist = m_TreeCtrl.GetImageList (TVSIL_STATE);
  248. m_TreeCtrl.SetImageList (NULL, TVSIL_STATE);
  249. SAFE_DELETE (imagelist);
  250. // Remove the main image list we associated with the control
  251. m_TreeCtrl.SetImageList (NULL, TVSIL_NORMAL);
  252. m_TreeCtrl.DeleteAllItems ();
  253. ::RemoveProp (m_TreeCtrl, "TRANS_ACCS");
  254. ::RemoveProp (m_hWnd, "TRANS_ACCS");
  255. // Allow the base class to process this message
  256. CDialog::OnDestroy ();
  257. return ;
  258. }
  259. ////////////////////////////////////////////////////////////////////////////
  260. //
  261. // OnInitDialog
  262. //
  263. ////////////////////////////////////////////////////////////////////////////
  264. BOOL
  265. ConversationPageClass::OnInitDialog (void)
  266. {
  267. CDialog::OnInitDialog ();
  268. m_Toolbar.CreateEx (this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_ALIGN_TOP, CRect(0, 0, 0, 0), 101);
  269. m_Toolbar.SetOwner (this);
  270. m_Toolbar.LoadToolBar (IDR_CONVERSATION_TOOLBAR);
  271. m_Toolbar.SetBarStyle (m_Toolbar.GetBarStyle () | CBRS_TOOLTIPS | CBRS_FLYBY);
  272. //
  273. // Size the toolbar
  274. //
  275. CRect parentrect;
  276. GetWindowRect (&parentrect);
  277. m_Toolbar.SetWindowPos (NULL, 0, 0, parentrect.Width () - TOOLBAR_H_BORDER, TOOLBAR_HEIGHT, SWP_NOZORDER | SWP_NOMOVE);
  278. //
  279. // Pass the general use imagelist onto the tree control
  280. //
  281. m_TreeCtrl.SetImageList (::Get_Global_Image_List (), TVSIL_NORMAL);
  282. SetProp (m_TreeCtrl, "TRANS_ACCS", (HANDLE)1);
  283. SetProp (m_hWnd, "TRANS_ACCS", (HANDLE)1);
  284. Reload_Data ();
  285. return TRUE;
  286. }
  287. /////////////////////////////////////////////////////////////////////////////
  288. //
  289. // OnDeleteItemConversationTree
  290. //
  291. /////////////////////////////////////////////////////////////////////////////
  292. void
  293. ConversationPageClass::OnDeleteItemConversationTree
  294. (
  295. NMHDR * pNMHDR,
  296. LRESULT *pResult
  297. )
  298. {
  299. NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
  300. (*pResult) = 0;
  301. //
  302. // Release our hold on the conversation object
  303. //
  304. ConversationClass *conversation = (ConversationClass *)pNMTreeView->itemOld.lParam;
  305. REF_PTR_RELEASE (conversation);
  306. m_TreeCtrl.SetItemData (pNMTreeView->itemOld.hItem, 0);
  307. return ;
  308. }
  309. /////////////////////////////////////////////////////////////////////////////
  310. //
  311. // Insert_Entry
  312. //
  313. /////////////////////////////////////////////////////////////////////////////
  314. void
  315. ConversationPageClass::Insert_Entry (ConversationClass *conversation, bool sort_items)
  316. {
  317. //
  318. // Determine which folder this conversation goes under
  319. //
  320. HTREEITEM parent_item = m_LevelsRoot;
  321. if (conversation->Get_Category_ID () != ConversationMgrClass::CATEGORY_LEVEL) {
  322. parent_item = m_GlobalsRoot;
  323. }
  324. //
  325. // Insert this item into the tree
  326. //
  327. HTREEITEM tree_item = m_TreeCtrl.InsertItem (conversation->Get_Name (), DIALOGUE_ICON,
  328. DIALOGUE_ICON, parent_item);
  329. if (tree_item != NULL) {
  330. //
  331. // Lock a reference on the object
  332. //
  333. conversation->Add_Ref ();
  334. //
  335. // Associate the conversation with the entry in the tree
  336. //
  337. m_TreeCtrl.SetItemData (tree_item, (DWORD)conversation);
  338. //
  339. // Sort the items
  340. //
  341. if (sort_items) {
  342. m_TreeCtrl.InvalidateRect (NULL, TRUE);
  343. m_TreeCtrl.SortChildren (parent_item);
  344. }
  345. }
  346. return ;
  347. }
  348. /////////////////////////////////////////////////////////////////////////////
  349. //
  350. // Reload_Data
  351. //
  352. /////////////////////////////////////////////////////////////////////////////
  353. void
  354. ConversationPageClass::Reload_Data (void)
  355. {
  356. Reset_Tree ();
  357. //
  358. // Add all the conversations to the tree
  359. //
  360. int count = ConversationMgrClass::Get_Conversation_Count ();
  361. for (int index = 0; index < count; index ++) {
  362. Insert_Entry (ConversationMgrClass::Peek_Conversation (index), false);
  363. }
  364. m_TreeCtrl.InvalidateRect (NULL, TRUE);
  365. m_TreeCtrl.SortChildren (m_GlobalsRoot);
  366. m_TreeCtrl.SortChildren (m_LevelsRoot);
  367. return ;
  368. }
  369. /////////////////////////////////////////////////////////////////////////////
  370. //
  371. // Reset_Tree
  372. //
  373. /////////////////////////////////////////////////////////////////////////////
  374. void
  375. ConversationPageClass::Reset_Tree (void)
  376. {
  377. m_TreeCtrl.DeleteAllItems ();
  378. //
  379. // Insert the root nodes
  380. //
  381. m_GlobalsRoot = m_TreeCtrl.InsertItem ("Globals", FOLDER_ICON, FOLDER_ICON);
  382. m_LevelsRoot = m_TreeCtrl.InsertItem ("Level Specific", FOLDER_ICON, FOLDER_ICON);
  383. return ;
  384. }
  385. ////////////////////////////////////////////////////////////////////////////
  386. //
  387. // OnDblclkConversationTree
  388. //
  389. ////////////////////////////////////////////////////////////////////////////
  390. void
  391. ConversationPageClass::OnDblclkConversationTree
  392. (
  393. NMHDR * pNMHDR,
  394. LRESULT * pResult
  395. )
  396. {
  397. //
  398. // Determine what client-coord location was double-clicked on
  399. //
  400. DWORD mouse_pos = ::GetMessagePos ();
  401. POINT hit_point = { GET_X_LPARAM (mouse_pos), GET_Y_LPARAM (mouse_pos) };
  402. m_TreeCtrl.ScreenToClient (&hit_point);
  403. //
  404. // Goto the node that was double-clicked on (if possible)
  405. //
  406. UINT flags = 0;
  407. HTREEITEM tree_item = m_TreeCtrl.HitTest (hit_point, &flags);
  408. if (tree_item != NULL && flags & TVHT_ONITEMLABEL) {
  409. //
  410. // Edit the entry the user double-clicked on
  411. //
  412. Edit_Entry (tree_item);
  413. (*pResult) = 1;
  414. } else {
  415. (*pResult) = 0;
  416. }
  417. return ;
  418. }
  419. ////////////////////////////////////////////////////////////////////////////
  420. //
  421. // OnItemexpandedConversationTree
  422. //
  423. ////////////////////////////////////////////////////////////////////////////
  424. void
  425. ConversationPageClass::OnItemexpandedConversationTree
  426. (
  427. NMHDR * pNMHDR,
  428. LRESULT * pResult
  429. )
  430. {
  431. NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
  432. //
  433. // If this is a folder, then change its image based
  434. // on its expanded state.
  435. //
  436. if (m_TreeCtrl.GetItemData (pNMTreeView->itemNew.hItem) == NULL) {
  437. if (pNMTreeView->itemNew.state & TVIS_EXPANDED) {
  438. m_TreeCtrl.SetItemImage (pNMTreeView->itemNew.hItem, OPEN_FOLDER_ICON, OPEN_FOLDER_ICON);
  439. } else {
  440. m_TreeCtrl.SetItemImage (pNMTreeView->itemNew.hItem, FOLDER_ICON, FOLDER_ICON);
  441. }
  442. }
  443. (*pResult) = 0;
  444. return ;
  445. }
  446. ////////////////////////////////////////////////////////////////////////////
  447. //
  448. // OnAdd
  449. //
  450. ////////////////////////////////////////////////////////////////////////////
  451. void
  452. ConversationPageClass::OnAdd (void)
  453. {
  454. HTREEITEM selected_item = m_TreeCtrl.GetSelectedItem ();
  455. if (selected_item != NULL) {
  456. //
  457. // Determine if this is a global conversation
  458. //
  459. bool is_global = false;
  460. bool can_edit = true;
  461. bool check_in = false;
  462. if ( selected_item == m_GlobalsRoot ||
  463. m_TreeCtrl.GetParentItem (selected_item) == m_GlobalsRoot)
  464. {
  465. is_global = true;
  466. //
  467. // Check out the database
  468. //
  469. CWaitCursor wait_cursor;
  470. check_in = ConversationEditorMgrClass::Check_Out ();
  471. can_edit = check_in;
  472. //
  473. // Reload the tree
  474. //
  475. if (can_edit) {
  476. Reload_Tree (&selected_item, NULL);
  477. }
  478. }
  479. if (can_edit) {
  480. //
  481. // Show a dialog to the user that will allow them to edit this conversation
  482. //
  483. EditConversationDialogClass dialog;
  484. if (dialog.DoModal () == IDOK) {
  485. ConversationClass *conversation = dialog.Peek_Conversation ();
  486. //
  487. // Determine which folder to put this conversation under
  488. //
  489. if (is_global) {
  490. conversation->Set_Category_ID (ConversationMgrClass::CATEGORY_GLOBAL);
  491. } else {
  492. conversation->Set_Category_ID (ConversationMgrClass::CATEGORY_LEVEL);
  493. ::Set_Modified ();
  494. }
  495. //
  496. // Add the conversation to the manager
  497. //
  498. ConversationMgrClass::Add_Conversation (conversation);
  499. //
  500. // Add the conversation to the tree
  501. //
  502. Insert_Entry (conversation);
  503. m_TreeCtrl.UpdateWindow ();
  504. //
  505. // Check in the global conversation database
  506. //
  507. if (check_in) {
  508. CWaitCursor wait_cursor;
  509. ConversationEditorMgrClass::Save_Global_Database ();
  510. ConversationEditorMgrClass::Check_In ();
  511. }
  512. } else if (check_in) {
  513. CWaitCursor wait_cursor;
  514. ConversationEditorMgrClass::Undo_Check_Out ();
  515. }
  516. }
  517. }
  518. return ;
  519. }
  520. ////////////////////////////////////////////////////////////////////////////
  521. //
  522. // OnDelete
  523. //
  524. ////////////////////////////////////////////////////////////////////////////
  525. void
  526. ConversationPageClass::OnDelete (void)
  527. {
  528. HTREEITEM selected_item = m_TreeCtrl.GetSelectedItem ();
  529. if (selected_item != NULL) {
  530. //
  531. // Get the conversation associated with the selected item
  532. //
  533. ConversationClass *conversation = NULL;
  534. conversation = (ConversationClass *)m_TreeCtrl.GetItemData (selected_item);
  535. if (conversation != NULL) {
  536. //
  537. // This "dirties" the level, so mark it as modified...
  538. //
  539. if (conversation->Get_Category_ID () == ConversationMgrClass::CATEGORY_LEVEL) {
  540. ::Set_Modified ();
  541. }
  542. //
  543. // Check out the global conversation database (if necessary)
  544. //
  545. bool check_in = false;
  546. bool can_edit = true;
  547. if (conversation->Get_Category_ID () == ConversationMgrClass::CATEGORY_GLOBAL) {
  548. CWaitCursor wait_cursor;
  549. check_in = ConversationEditorMgrClass::Check_Out ();
  550. can_edit = check_in;
  551. //
  552. // Reload the tree
  553. //
  554. if (can_edit) {
  555. Reload_Tree (&selected_item, &conversation);
  556. }
  557. }
  558. if (can_edit && selected_item != NULL && conversation != NULL) {
  559. //
  560. // Remove this conversation from the manager
  561. //
  562. ConversationMgrClass::Remove_Conversation (conversation);
  563. //
  564. // Remove this conversation from the tree
  565. //
  566. m_TreeCtrl.DeleteItem (selected_item);
  567. m_TreeCtrl.UpdateWindow ();
  568. //
  569. // Check in the global conversation database
  570. //
  571. if (check_in) {
  572. ConversationEditorMgrClass::Save_Global_Database ();
  573. ConversationEditorMgrClass::Check_In ();
  574. }
  575. }
  576. }
  577. }
  578. return ;
  579. }
  580. ////////////////////////////////////////////////////////////////////////////
  581. //
  582. // OnEdit
  583. //
  584. ////////////////////////////////////////////////////////////////////////////
  585. void
  586. ConversationPageClass::OnEdit (void)
  587. {
  588. HTREEITEM selected_item = m_TreeCtrl.GetSelectedItem ();
  589. if (selected_item != NULL) {
  590. //
  591. // Edit the selected entry
  592. //
  593. Edit_Entry (selected_item);
  594. }
  595. return ;
  596. }
  597. ////////////////////////////////////////////////////////////////////////////
  598. //
  599. // Edit_Entry
  600. //
  601. ////////////////////////////////////////////////////////////////////////////
  602. void
  603. ConversationPageClass::Edit_Entry (HTREEITEM tree_item)
  604. {
  605. if (tree_item != NULL) {
  606. //
  607. // Edit the conversation (if necessary)
  608. //
  609. ConversationClass *conversation = (ConversationClass *)m_TreeCtrl.GetItemData (tree_item);
  610. if (conversation != NULL) {
  611. //
  612. // Check out the global conversation database (if necessary)
  613. //
  614. bool check_in = false;
  615. bool can_edit = true;
  616. if (conversation->Get_Category_ID () == ConversationMgrClass::CATEGORY_GLOBAL) {
  617. CWaitCursor wait_cursor;
  618. check_in = ConversationEditorMgrClass::Check_Out ();
  619. can_edit = check_in;
  620. //
  621. // Reload the tree
  622. //
  623. if (can_edit) {
  624. Reload_Tree (&tree_item, &conversation);
  625. }
  626. }
  627. if (can_edit && tree_item != NULL && conversation != NULL) {
  628. //
  629. // Display a dialog to the user allowing them to edit the conversation
  630. //
  631. EditConversationDialogClass dialog;
  632. dialog.Set_Conversation (conversation);
  633. if (dialog.DoModal () == IDOK) {
  634. m_TreeCtrl.SetItemText (tree_item, conversation->Get_Name ());
  635. m_TreeCtrl.UpdateWindow ();
  636. //
  637. // This "dirties" the level, so mark it as modified...
  638. //
  639. if (conversation->Get_Category_ID () == ConversationMgrClass::CATEGORY_LEVEL) {
  640. ::Set_Modified ();
  641. }
  642. //
  643. // Check in the global conversation database
  644. //
  645. if (check_in) {
  646. CWaitCursor wait_cursor;
  647. ConversationEditorMgrClass::Save_Global_Database ();
  648. ConversationEditorMgrClass::Check_In ();
  649. }
  650. } else if (check_in) {
  651. CWaitCursor wait_cursor;
  652. ConversationEditorMgrClass::Undo_Check_Out ();
  653. }
  654. }
  655. }
  656. }
  657. return ;
  658. }
  659. ////////////////////////////////////////////////////////////////////////////
  660. //
  661. // OnSwap
  662. //
  663. ////////////////////////////////////////////////////////////////////////////
  664. void
  665. ConversationPageClass::OnSwap (void)
  666. {
  667. HTREEITEM selected_item = m_TreeCtrl.GetSelectedItem ();
  668. if (selected_item != NULL) {
  669. //
  670. // Get the conversation associated with the selected item
  671. //
  672. ConversationClass *conversation = NULL;
  673. conversation = (ConversationClass *)m_TreeCtrl.GetItemData (selected_item);
  674. if (conversation != NULL) {
  675. //
  676. // Check out the global conversation database
  677. //
  678. CWaitCursor wait_cursor;
  679. if (ConversationEditorMgrClass::Check_Out ()) {
  680. //
  681. // Reload the tree
  682. //
  683. Reload_Tree (&selected_item, &conversation);
  684. if (selected_item != NULL && conversation != NULL) {
  685. //
  686. // Remove the conversation from the system
  687. //
  688. ConversationMgrClass::Remove_Conversation (conversation);
  689. //
  690. // Swap categories
  691. //
  692. int category_id = conversation->Get_Category_ID ();
  693. if (category_id == ConversationMgrClass::CATEGORY_LEVEL) {
  694. conversation->Set_Category_ID (ConversationMgrClass::CATEGORY_GLOBAL);
  695. } else {
  696. conversation->Set_Category_ID (ConversationMgrClass::CATEGORY_LEVEL);
  697. }
  698. //
  699. // Re-add the conversation to the manager and the UI
  700. //
  701. ConversationMgrClass::Add_Conversation (conversation);
  702. Insert_Entry (conversation);
  703. //
  704. // Remove the old entry
  705. //
  706. m_TreeCtrl.DeleteItem (selected_item);
  707. m_TreeCtrl.UpdateWindow ();
  708. //
  709. // This "dirties" the level, so mark it as modified...
  710. //
  711. ::Set_Modified ();
  712. //
  713. // Checkin the global conversation database
  714. //
  715. ConversationEditorMgrClass::Save_Global_Database ();
  716. ConversationEditorMgrClass::Check_In ();
  717. }
  718. }
  719. }
  720. }
  721. return ;
  722. }
  723. ////////////////////////////////////////////////////////////////////////////
  724. //
  725. // Reload_Tree
  726. //
  727. ////////////////////////////////////////////////////////////////////////////
  728. void
  729. ConversationPageClass::Reload_Tree (HTREEITEM *item_handle, ConversationClass **conversation_ptr)
  730. {
  731. m_TreeCtrl.SetRedraw (FALSE);
  732. //
  733. // Reload the database while capturing its state
  734. //
  735. TreeStateCaptureClass capture_obj (m_TreeCtrl, item_handle, conversation_ptr);
  736. ConversationEditorMgrClass::Load_Global_Database ();
  737. capture_obj.Restore ();
  738. //
  739. // Expand the two root folders by default
  740. //
  741. m_TreeCtrl.Expand (m_GlobalsRoot, TVE_EXPAND);
  742. m_TreeCtrl.Expand (m_LevelsRoot, TVE_EXPAND);
  743. m_TreeCtrl.SetRedraw (TRUE);
  744. return ;
  745. }