896 lines
23 KiB
C++
896 lines
23 KiB
C++
/*
|
|
** Command & Conquer Renegade(tm)
|
|
** Copyright 2025 Electronic Arts Inc.
|
|
**
|
|
** This program is free software: you can redistribute it and/or modify
|
|
** it under the terms of the GNU General Public License as published by
|
|
** the Free Software Foundation, either version 3 of the License, or
|
|
** (at your option) any later version.
|
|
**
|
|
** This program is distributed in the hope that it will be useful,
|
|
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
** GNU General Public License for more details.
|
|
**
|
|
** You should have received a copy of the GNU General Public License
|
|
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
/***********************************************************************************************
|
|
*** 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 ***
|
|
***********************************************************************************************
|
|
* *
|
|
* Project Name : LevelEdit *
|
|
* *
|
|
* $Archive:: /Commando/Code/Tools/LevelEdit/ConversationPage.cpp $*
|
|
* *
|
|
* Author:: Patrick Smith *
|
|
* *
|
|
* $Modtime:: 2/12/02 9:57a $*
|
|
* *
|
|
* $Revision:: 5 $*
|
|
* *
|
|
*---------------------------------------------------------------------------------------------*
|
|
* Functions: *
|
|
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
|
|
|
|
|
#include "stdafx.h"
|
|
|
|
#include "leveledit.h"
|
|
#include "conversationpage.h"
|
|
#include "nodemgr.h"
|
|
#include "node.h"
|
|
#include "icons.h"
|
|
#include "conversation.h"
|
|
#include "conversationmgr.h"
|
|
#include "editconversationdialog.h"
|
|
#include "conversationeditormgr.h"
|
|
|
|
|
|
#ifdef _DEBUG
|
|
#define new DEBUG_NEW
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Helper objects
|
|
//
|
|
///////////////////////////////////////////////////////////////////////
|
|
class TreeStateCaptureClass
|
|
{
|
|
public:
|
|
TreeStateCaptureClass (CTreeCtrl &tree_ctrl, HTREEITEM *item_handle, ConversationClass **conversation_ptr)
|
|
: ConversationID (0),
|
|
ConversationPtr (conversation_ptr),
|
|
ItemHandle (item_handle),
|
|
TreeCtrl (tree_ctrl)
|
|
{
|
|
if (conversation_ptr != NULL) {
|
|
ConversationID = (*conversation_ptr)->Get_ID ();
|
|
}
|
|
|
|
return ;
|
|
}
|
|
|
|
void Restore (void)
|
|
{
|
|
if (ItemHandle != NULL) {
|
|
(*ItemHandle) = NULL;
|
|
}
|
|
|
|
if (ConversationPtr != NULL) {
|
|
(*ConversationPtr) = NULL;
|
|
}
|
|
|
|
Find_Entry (TVI_ROOT);
|
|
|
|
//
|
|
// Ensure the item is visible
|
|
//
|
|
if (ItemHandle != NULL && (*ItemHandle) != NULL) {
|
|
TreeCtrl.SelectItem (*ItemHandle);
|
|
TreeCtrl.EnsureVisible (*ItemHandle);
|
|
}
|
|
|
|
return ;
|
|
}
|
|
|
|
bool Find_Entry (HTREEITEM parent_item)
|
|
{
|
|
bool retval = false;
|
|
|
|
//
|
|
// Loop over all the children of this tree item
|
|
//
|
|
for ( HTREEITEM child_item = TreeCtrl.GetNextItem (parent_item, TVGN_CHILD);
|
|
retval == false && child_item != NULL;
|
|
child_item = TreeCtrl.GetNextItem (child_item, TVGN_NEXT))
|
|
{
|
|
//
|
|
// Is this the conversation we are looking for?
|
|
//
|
|
ConversationClass *conversation = (ConversationClass *)TreeCtrl.GetItemData (child_item);
|
|
if (conversation != NULL && conversation->Get_ID () == ConversationID) {
|
|
|
|
if (ItemHandle != NULL) {
|
|
(*ItemHandle) = child_item;
|
|
}
|
|
|
|
if (ConversationPtr != NULL) {
|
|
(*ConversationPtr) = conversation;
|
|
}
|
|
|
|
retval = true;
|
|
break ;
|
|
}
|
|
|
|
//
|
|
// Recurse into this child (if necessary)
|
|
//
|
|
if (TreeCtrl.ItemHasChildren (child_item)) {
|
|
retval = Find_Entry (child_item);
|
|
}
|
|
}
|
|
|
|
return retval;
|
|
}
|
|
|
|
private:
|
|
int ConversationID;
|
|
CTreeCtrl & TreeCtrl;
|
|
HTREEITEM * ItemHandle;
|
|
ConversationClass ** ConversationPtr;
|
|
};
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Static member initialization
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
ConversationPageClass * ConversationPageClass::_TheInstance = NULL;
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Local constants
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
static const int TOOLBAR_HEIGHT = 36;
|
|
static const int TOOLBAR_V_SPACING = 5;
|
|
static const int TOOLBAR_V_BORDER = TOOLBAR_V_SPACING * 2;
|
|
static const int TOOLBAR_H_SPACING = 5;
|
|
static const int TOOLBAR_H_BORDER = TOOLBAR_H_SPACING * 2;
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// ConversationPageClass
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
ConversationPageClass::ConversationPageClass(CWnd* pParent /*=NULL*/) :
|
|
m_GlobalsRoot (NULL),
|
|
m_LevelsRoot (NULL),
|
|
CDialog(ConversationPageClass::IDD, pParent)
|
|
{
|
|
//{{AFX_DATA_INIT(ConversationPageClass)
|
|
// NOTE: the ClassWizard will add member initialization here
|
|
//}}AFX_DATA_INIT
|
|
Create (ConversationPageClass::IDD, pParent);
|
|
_TheInstance = this;
|
|
return ;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// ~ConversationPageClass
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
ConversationPageClass::~ConversationPageClass (void)
|
|
{
|
|
_TheInstance = NULL;
|
|
return ;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// DoDataExchange
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void
|
|
ConversationPageClass::DoDataExchange (CDataExchange *pDX)
|
|
{
|
|
CDialog::DoDataExchange(pDX);
|
|
//{{AFX_DATA_MAP(ConversationPageClass)
|
|
DDX_Control(pDX, IDC_CONVERSATION_TREE, m_TreeCtrl);
|
|
//}}AFX_DATA_MAP
|
|
return ;
|
|
}
|
|
|
|
|
|
BEGIN_MESSAGE_MAP(ConversationPageClass, CDialog)
|
|
//{{AFX_MSG_MAP(ConversationPageClass)
|
|
ON_NOTIFY(TVN_DELETEITEM, IDC_CONVERSATION_TREE, OnDeleteItemConversationTree)
|
|
ON_WM_SIZE()
|
|
ON_WM_DESTROY()
|
|
ON_NOTIFY(NM_DBLCLK, IDC_CONVERSATION_TREE, OnDblclkConversationTree)
|
|
ON_NOTIFY(TVN_ITEMEXPANDED, IDC_CONVERSATION_TREE, OnItemexpandedConversationTree)
|
|
ON_COMMAND(IDC_ADD, OnAdd)
|
|
ON_COMMAND(IDC_DELETE, OnDelete)
|
|
ON_COMMAND(IDC_EDIT, OnEdit)
|
|
ON_COMMAND(IDC_SWAP, OnSwap)
|
|
//}}AFX_MSG_MAP
|
|
END_MESSAGE_MAP()
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// OnSize
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void
|
|
ConversationPageClass::OnSize
|
|
(
|
|
UINT nType,
|
|
int cx,
|
|
int cy
|
|
)
|
|
{
|
|
// Allow the base class to process this message
|
|
CDialog::OnSize (nType, cx, cy);
|
|
|
|
if (::IsWindow (m_TreeCtrl) && (cx > 0) && (cy > 0)) {
|
|
|
|
// Get the bounding rectangle of the form window
|
|
CRect parentrect;
|
|
GetWindowRect (&parentrect);
|
|
|
|
// Get the bounding rectangle of the toolbar
|
|
CRect toolbar_rect;
|
|
m_Toolbar.GetWindowRect (&toolbar_rect);
|
|
ScreenToClient (&toolbar_rect);
|
|
|
|
// Move the toolbar so it is in its correct position
|
|
m_Toolbar.SetWindowPos (NULL,
|
|
TOOLBAR_H_SPACING,
|
|
(cy - TOOLBAR_V_SPACING) - toolbar_rect.Height (),
|
|
cx - TOOLBAR_H_BORDER,
|
|
toolbar_rect.Height (),
|
|
SWP_NOZORDER);
|
|
|
|
// Get the bounding rectnagle of the list ctrl
|
|
RECT list_rect;
|
|
m_TreeCtrl.GetWindowRect (&list_rect);
|
|
|
|
CRect client_rect = list_rect;
|
|
ScreenToClient (&client_rect);
|
|
int list_height = ((cy - TOOLBAR_V_BORDER) - toolbar_rect.Height ()) - client_rect.top;
|
|
|
|
// Resize the tab control to fill the entire contents of the client area
|
|
m_TreeCtrl.SetWindowPos ( NULL,
|
|
0,
|
|
0,
|
|
cx-((list_rect.left - parentrect.left) << 1),
|
|
list_height,
|
|
SWP_NOZORDER | SWP_NOMOVE);
|
|
}
|
|
|
|
return ;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// OnDestroy
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void
|
|
ConversationPageClass::OnDestroy (void)
|
|
{
|
|
// Free the state image list we associated with the control
|
|
CImageList *imagelist = m_TreeCtrl.GetImageList (TVSIL_STATE);
|
|
m_TreeCtrl.SetImageList (NULL, TVSIL_STATE);
|
|
SAFE_DELETE (imagelist);
|
|
|
|
// Remove the main image list we associated with the control
|
|
m_TreeCtrl.SetImageList (NULL, TVSIL_NORMAL);
|
|
m_TreeCtrl.DeleteAllItems ();
|
|
|
|
::RemoveProp (m_TreeCtrl, "TRANS_ACCS");
|
|
::RemoveProp (m_hWnd, "TRANS_ACCS");
|
|
|
|
// Allow the base class to process this message
|
|
CDialog::OnDestroy ();
|
|
return ;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// OnInitDialog
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
BOOL
|
|
ConversationPageClass::OnInitDialog (void)
|
|
{
|
|
CDialog::OnInitDialog ();
|
|
|
|
m_Toolbar.CreateEx (this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_ALIGN_TOP, CRect(0, 0, 0, 0), 101);
|
|
m_Toolbar.SetOwner (this);
|
|
m_Toolbar.LoadToolBar (IDR_CONVERSATION_TOOLBAR);
|
|
m_Toolbar.SetBarStyle (m_Toolbar.GetBarStyle () | CBRS_TOOLTIPS | CBRS_FLYBY);
|
|
|
|
//
|
|
// Size the toolbar
|
|
//
|
|
CRect parentrect;
|
|
GetWindowRect (&parentrect);
|
|
m_Toolbar.SetWindowPos (NULL, 0, 0, parentrect.Width () - TOOLBAR_H_BORDER, TOOLBAR_HEIGHT, SWP_NOZORDER | SWP_NOMOVE);
|
|
|
|
//
|
|
// Pass the general use imagelist onto the tree control
|
|
//
|
|
m_TreeCtrl.SetImageList (::Get_Global_Image_List (), TVSIL_NORMAL);
|
|
|
|
SetProp (m_TreeCtrl, "TRANS_ACCS", (HANDLE)1);
|
|
SetProp (m_hWnd, "TRANS_ACCS", (HANDLE)1);
|
|
|
|
Reload_Data ();
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// OnDeleteItemConversationTree
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void
|
|
ConversationPageClass::OnDeleteItemConversationTree
|
|
(
|
|
NMHDR * pNMHDR,
|
|
LRESULT *pResult
|
|
)
|
|
{
|
|
NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
|
|
(*pResult) = 0;
|
|
|
|
//
|
|
// Release our hold on the conversation object
|
|
//
|
|
ConversationClass *conversation = (ConversationClass *)pNMTreeView->itemOld.lParam;
|
|
REF_PTR_RELEASE (conversation);
|
|
m_TreeCtrl.SetItemData (pNMTreeView->itemOld.hItem, 0);
|
|
return ;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Insert_Entry
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void
|
|
ConversationPageClass::Insert_Entry (ConversationClass *conversation, bool sort_items)
|
|
{
|
|
//
|
|
// Determine which folder this conversation goes under
|
|
//
|
|
HTREEITEM parent_item = m_LevelsRoot;
|
|
if (conversation->Get_Category_ID () != ConversationMgrClass::CATEGORY_LEVEL) {
|
|
parent_item = m_GlobalsRoot;
|
|
}
|
|
|
|
//
|
|
// Insert this item into the tree
|
|
//
|
|
HTREEITEM tree_item = m_TreeCtrl.InsertItem (conversation->Get_Name (), DIALOGUE_ICON,
|
|
DIALOGUE_ICON, parent_item);
|
|
if (tree_item != NULL) {
|
|
|
|
//
|
|
// Lock a reference on the object
|
|
//
|
|
conversation->Add_Ref ();
|
|
|
|
//
|
|
// Associate the conversation with the entry in the tree
|
|
//
|
|
m_TreeCtrl.SetItemData (tree_item, (DWORD)conversation);
|
|
|
|
//
|
|
// Sort the items
|
|
//
|
|
if (sort_items) {
|
|
m_TreeCtrl.InvalidateRect (NULL, TRUE);
|
|
m_TreeCtrl.SortChildren (parent_item);
|
|
}
|
|
}
|
|
|
|
return ;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Reload_Data
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void
|
|
ConversationPageClass::Reload_Data (void)
|
|
{
|
|
Reset_Tree ();
|
|
|
|
//
|
|
// Add all the conversations to the tree
|
|
//
|
|
int count = ConversationMgrClass::Get_Conversation_Count ();
|
|
for (int index = 0; index < count; index ++) {
|
|
Insert_Entry (ConversationMgrClass::Peek_Conversation (index), false);
|
|
}
|
|
|
|
m_TreeCtrl.InvalidateRect (NULL, TRUE);
|
|
m_TreeCtrl.SortChildren (m_GlobalsRoot);
|
|
m_TreeCtrl.SortChildren (m_LevelsRoot);
|
|
return ;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Reset_Tree
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void
|
|
ConversationPageClass::Reset_Tree (void)
|
|
{
|
|
m_TreeCtrl.DeleteAllItems ();
|
|
|
|
//
|
|
// Insert the root nodes
|
|
//
|
|
|
|
m_GlobalsRoot = m_TreeCtrl.InsertItem ("Globals", FOLDER_ICON, FOLDER_ICON);
|
|
m_LevelsRoot = m_TreeCtrl.InsertItem ("Level Specific", FOLDER_ICON, FOLDER_ICON);
|
|
return ;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// OnDblclkConversationTree
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
void
|
|
ConversationPageClass::OnDblclkConversationTree
|
|
(
|
|
NMHDR * pNMHDR,
|
|
LRESULT * pResult
|
|
)
|
|
{
|
|
//
|
|
// Determine what client-coord location was double-clicked on
|
|
//
|
|
DWORD mouse_pos = ::GetMessagePos ();
|
|
POINT hit_point = { GET_X_LPARAM (mouse_pos), GET_Y_LPARAM (mouse_pos) };
|
|
m_TreeCtrl.ScreenToClient (&hit_point);
|
|
|
|
//
|
|
// Goto the node that was double-clicked on (if possible)
|
|
//
|
|
UINT flags = 0;
|
|
HTREEITEM tree_item = m_TreeCtrl.HitTest (hit_point, &flags);
|
|
if (tree_item != NULL && flags & TVHT_ONITEMLABEL) {
|
|
|
|
//
|
|
// Edit the entry the user double-clicked on
|
|
//
|
|
Edit_Entry (tree_item);
|
|
(*pResult) = 1;
|
|
|
|
} else {
|
|
(*pResult) = 0;
|
|
}
|
|
|
|
|
|
return ;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// OnItemexpandedConversationTree
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
void
|
|
ConversationPageClass::OnItemexpandedConversationTree
|
|
(
|
|
NMHDR * pNMHDR,
|
|
LRESULT * pResult
|
|
)
|
|
{
|
|
NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
|
|
|
|
//
|
|
// If this is a folder, then change its image based
|
|
// on its expanded state.
|
|
//
|
|
if (m_TreeCtrl.GetItemData (pNMTreeView->itemNew.hItem) == NULL) {
|
|
|
|
if (pNMTreeView->itemNew.state & TVIS_EXPANDED) {
|
|
m_TreeCtrl.SetItemImage (pNMTreeView->itemNew.hItem, OPEN_FOLDER_ICON, OPEN_FOLDER_ICON);
|
|
} else {
|
|
m_TreeCtrl.SetItemImage (pNMTreeView->itemNew.hItem, FOLDER_ICON, FOLDER_ICON);
|
|
}
|
|
|
|
}
|
|
|
|
(*pResult) = 0;
|
|
return ;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// OnAdd
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
void
|
|
ConversationPageClass::OnAdd (void)
|
|
{
|
|
HTREEITEM selected_item = m_TreeCtrl.GetSelectedItem ();
|
|
if (selected_item != NULL) {
|
|
|
|
//
|
|
// Determine if this is a global conversation
|
|
//
|
|
bool is_global = false;
|
|
bool can_edit = true;
|
|
bool check_in = false;
|
|
if ( selected_item == m_GlobalsRoot ||
|
|
m_TreeCtrl.GetParentItem (selected_item) == m_GlobalsRoot)
|
|
{
|
|
is_global = true;
|
|
|
|
//
|
|
// Check out the database
|
|
//
|
|
CWaitCursor wait_cursor;
|
|
check_in = ConversationEditorMgrClass::Check_Out ();
|
|
can_edit = check_in;
|
|
|
|
//
|
|
// Reload the tree
|
|
//
|
|
if (can_edit) {
|
|
Reload_Tree (&selected_item, NULL);
|
|
}
|
|
}
|
|
|
|
if (can_edit) {
|
|
|
|
//
|
|
// Show a dialog to the user that will allow them to edit this conversation
|
|
//
|
|
EditConversationDialogClass dialog;
|
|
if (dialog.DoModal () == IDOK) {
|
|
|
|
ConversationClass *conversation = dialog.Peek_Conversation ();
|
|
|
|
//
|
|
// Determine which folder to put this conversation under
|
|
//
|
|
if (is_global) {
|
|
conversation->Set_Category_ID (ConversationMgrClass::CATEGORY_GLOBAL);
|
|
} else {
|
|
conversation->Set_Category_ID (ConversationMgrClass::CATEGORY_LEVEL);
|
|
::Set_Modified ();
|
|
}
|
|
|
|
//
|
|
// Add the conversation to the manager
|
|
//
|
|
ConversationMgrClass::Add_Conversation (conversation);
|
|
|
|
//
|
|
// Add the conversation to the tree
|
|
//
|
|
Insert_Entry (conversation);
|
|
m_TreeCtrl.UpdateWindow ();
|
|
|
|
//
|
|
// Check in the global conversation database
|
|
//
|
|
if (check_in) {
|
|
CWaitCursor wait_cursor;
|
|
ConversationEditorMgrClass::Save_Global_Database ();
|
|
ConversationEditorMgrClass::Check_In ();
|
|
}
|
|
|
|
} else if (check_in) {
|
|
CWaitCursor wait_cursor;
|
|
ConversationEditorMgrClass::Undo_Check_Out ();
|
|
}
|
|
}
|
|
}
|
|
|
|
return ;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// OnDelete
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
void
|
|
ConversationPageClass::OnDelete (void)
|
|
{
|
|
HTREEITEM selected_item = m_TreeCtrl.GetSelectedItem ();
|
|
if (selected_item != NULL) {
|
|
|
|
//
|
|
// Get the conversation associated with the selected item
|
|
//
|
|
ConversationClass *conversation = NULL;
|
|
conversation = (ConversationClass *)m_TreeCtrl.GetItemData (selected_item);
|
|
if (conversation != NULL) {
|
|
|
|
//
|
|
// This "dirties" the level, so mark it as modified...
|
|
//
|
|
if (conversation->Get_Category_ID () == ConversationMgrClass::CATEGORY_LEVEL) {
|
|
::Set_Modified ();
|
|
}
|
|
|
|
//
|
|
// Check out the global conversation database (if necessary)
|
|
//
|
|
bool check_in = false;
|
|
bool can_edit = true;
|
|
if (conversation->Get_Category_ID () == ConversationMgrClass::CATEGORY_GLOBAL) {
|
|
CWaitCursor wait_cursor;
|
|
check_in = ConversationEditorMgrClass::Check_Out ();
|
|
can_edit = check_in;
|
|
|
|
//
|
|
// Reload the tree
|
|
//
|
|
if (can_edit) {
|
|
Reload_Tree (&selected_item, &conversation);
|
|
}
|
|
}
|
|
|
|
if (can_edit && selected_item != NULL && conversation != NULL) {
|
|
|
|
//
|
|
// Remove this conversation from the manager
|
|
//
|
|
ConversationMgrClass::Remove_Conversation (conversation);
|
|
|
|
//
|
|
// Remove this conversation from the tree
|
|
//
|
|
m_TreeCtrl.DeleteItem (selected_item);
|
|
m_TreeCtrl.UpdateWindow ();
|
|
|
|
//
|
|
// Check in the global conversation database
|
|
//
|
|
if (check_in) {
|
|
ConversationEditorMgrClass::Save_Global_Database ();
|
|
ConversationEditorMgrClass::Check_In ();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return ;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// OnEdit
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
void
|
|
ConversationPageClass::OnEdit (void)
|
|
{
|
|
HTREEITEM selected_item = m_TreeCtrl.GetSelectedItem ();
|
|
if (selected_item != NULL) {
|
|
|
|
//
|
|
// Edit the selected entry
|
|
//
|
|
Edit_Entry (selected_item);
|
|
}
|
|
|
|
return ;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Edit_Entry
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
void
|
|
ConversationPageClass::Edit_Entry (HTREEITEM tree_item)
|
|
{
|
|
if (tree_item != NULL) {
|
|
|
|
//
|
|
// Edit the conversation (if necessary)
|
|
//
|
|
ConversationClass *conversation = (ConversationClass *)m_TreeCtrl.GetItemData (tree_item);
|
|
if (conversation != NULL) {
|
|
|
|
//
|
|
// Check out the global conversation database (if necessary)
|
|
//
|
|
bool check_in = false;
|
|
bool can_edit = true;
|
|
if (conversation->Get_Category_ID () == ConversationMgrClass::CATEGORY_GLOBAL) {
|
|
CWaitCursor wait_cursor;
|
|
check_in = ConversationEditorMgrClass::Check_Out ();
|
|
can_edit = check_in;
|
|
|
|
//
|
|
// Reload the tree
|
|
//
|
|
if (can_edit) {
|
|
Reload_Tree (&tree_item, &conversation);
|
|
}
|
|
}
|
|
|
|
if (can_edit && tree_item != NULL && conversation != NULL) {
|
|
|
|
//
|
|
// Display a dialog to the user allowing them to edit the conversation
|
|
//
|
|
EditConversationDialogClass dialog;
|
|
dialog.Set_Conversation (conversation);
|
|
if (dialog.DoModal () == IDOK) {
|
|
m_TreeCtrl.SetItemText (tree_item, conversation->Get_Name ());
|
|
m_TreeCtrl.UpdateWindow ();
|
|
|
|
//
|
|
// This "dirties" the level, so mark it as modified...
|
|
//
|
|
if (conversation->Get_Category_ID () == ConversationMgrClass::CATEGORY_LEVEL) {
|
|
::Set_Modified ();
|
|
}
|
|
|
|
//
|
|
// Check in the global conversation database
|
|
//
|
|
if (check_in) {
|
|
CWaitCursor wait_cursor;
|
|
ConversationEditorMgrClass::Save_Global_Database ();
|
|
ConversationEditorMgrClass::Check_In ();
|
|
}
|
|
|
|
} else if (check_in) {
|
|
CWaitCursor wait_cursor;
|
|
ConversationEditorMgrClass::Undo_Check_Out ();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return ;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// OnSwap
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
void
|
|
ConversationPageClass::OnSwap (void)
|
|
{
|
|
HTREEITEM selected_item = m_TreeCtrl.GetSelectedItem ();
|
|
if (selected_item != NULL) {
|
|
|
|
//
|
|
// Get the conversation associated with the selected item
|
|
//
|
|
ConversationClass *conversation = NULL;
|
|
conversation = (ConversationClass *)m_TreeCtrl.GetItemData (selected_item);
|
|
if (conversation != NULL) {
|
|
|
|
//
|
|
// Check out the global conversation database
|
|
//
|
|
CWaitCursor wait_cursor;
|
|
if (ConversationEditorMgrClass::Check_Out ()) {
|
|
|
|
//
|
|
// Reload the tree
|
|
//
|
|
Reload_Tree (&selected_item, &conversation);
|
|
if (selected_item != NULL && conversation != NULL) {
|
|
|
|
//
|
|
// Remove the conversation from the system
|
|
//
|
|
ConversationMgrClass::Remove_Conversation (conversation);
|
|
|
|
//
|
|
// Swap categories
|
|
//
|
|
int category_id = conversation->Get_Category_ID ();
|
|
if (category_id == ConversationMgrClass::CATEGORY_LEVEL) {
|
|
conversation->Set_Category_ID (ConversationMgrClass::CATEGORY_GLOBAL);
|
|
} else {
|
|
conversation->Set_Category_ID (ConversationMgrClass::CATEGORY_LEVEL);
|
|
}
|
|
|
|
//
|
|
// Re-add the conversation to the manager and the UI
|
|
//
|
|
ConversationMgrClass::Add_Conversation (conversation);
|
|
Insert_Entry (conversation);
|
|
|
|
//
|
|
// Remove the old entry
|
|
//
|
|
m_TreeCtrl.DeleteItem (selected_item);
|
|
m_TreeCtrl.UpdateWindow ();
|
|
|
|
//
|
|
// This "dirties" the level, so mark it as modified...
|
|
//
|
|
::Set_Modified ();
|
|
|
|
//
|
|
// Checkin the global conversation database
|
|
//
|
|
ConversationEditorMgrClass::Save_Global_Database ();
|
|
ConversationEditorMgrClass::Check_In ();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return ;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Reload_Tree
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
void
|
|
ConversationPageClass::Reload_Tree (HTREEITEM *item_handle, ConversationClass **conversation_ptr)
|
|
{
|
|
m_TreeCtrl.SetRedraw (FALSE);
|
|
|
|
//
|
|
// Reload the database while capturing its state
|
|
//
|
|
TreeStateCaptureClass capture_obj (m_TreeCtrl, item_handle, conversation_ptr);
|
|
ConversationEditorMgrClass::Load_Global_Database ();
|
|
capture_obj.Restore ();
|
|
|
|
//
|
|
// Expand the two root folders by default
|
|
//
|
|
m_TreeCtrl.Expand (m_GlobalsRoot, TVE_EXPAND);
|
|
m_TreeCtrl.Expand (m_LevelsRoot, TVE_EXPAND);
|
|
|
|
m_TreeCtrl.SetRedraw (TRUE);
|
|
return ;
|
|
}
|
|
|