/* ** AreaEditor - a program for editing SMAUG and ROM area files. ** Author: Nick Gammon ** http://www.gammon.com.au/ ** See Copyright Notice at the end of AreaEditor.h */ // AreaEditorView.cpp : implementation of the CAreaEditorView class // #include "stdafx.h" #include "AreaEditor.h" #include "MainFrm.h" #include "AreaEditorDoc.h" #include "AreaEditorView.h" #include "BlankView.h" #include "AreaView.h" #include "MobileView.h" #include "ObjectView.h" #include "RoomView.h" #include "ResetView.h" #include "ShopView.h" #include "RepairView.h" #include "HelpView.h" #include "FindDlg.h" #include "resource.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif #define WM_USER_PUT_FOCUS_BACK (WM_USER + 1003) ///////////////////////////////////////////////////////////////////////////// // CAreaEditorView IMPLEMENT_DYNCREATE(CAreaEditorView, CTreeView) BEGIN_MESSAGE_MAP(CAreaEditorView, CTreeView) ON_WM_CONTEXTMENU() //{{AFX_MSG_MAP(CAreaEditorView) ON_NOTIFY_REFLECT(TVN_ITEMEXPANDING, OnItemexpanding) ON_NOTIFY_REFLECT(TVN_SELCHANGED, OnSelchanged) ON_NOTIFY_REFLECT(TVN_SELCHANGING, OnSelchanging) ON_NOTIFY_REFLECT(TVN_KEYDOWN, OnKeydown) ON_COMMAND(ID_AREA_DELETE_ITEM, OnAreaDeleteItem) ON_UPDATE_COMMAND_UI(ID_AREA_DELETE_ITEM, OnUpdateAreaDeleteItem) ON_COMMAND(ID_AREA_ADD_ITEM, OnAreaAddItem) ON_UPDATE_COMMAND_UI(ID_AREA_ADD_ITEM, OnUpdateAreaAddItem) ON_COMMAND(ID_AREA_FIND, OnAreaFind) ON_COMMAND(ID_AREA_FIND_NEXT, OnAreaFindNext) ON_UPDATE_COMMAND_UI(ID_AREA_FIND_NEXT, OnUpdateAreaFindNext) ON_WM_CONTEXTMENU() ON_NOTIFY_REFLECT(NM_RCLICK, OnRclick) ON_UPDATE_COMMAND_UI(ID_AREA_DUPLICATE_ITEM, OnUpdateAreaDuplicateItem) ON_COMMAND(ID_AREA_DUPLICATE_ITEM, OnAreaDuplicateItem) ON_COMMAND(ID_FILE_PRINT, OnFilePrint) ON_COMMAND(ID_VIEW_REFRESH, OnViewRefresh) ON_COMMAND(ID_AREA_CHECKALLAREAS, OnAreaCheckallareas) //}}AFX_MSG_MAP // Standard printing commands ON_COMMAND(ID_FILE_PRINT, CTreeView::OnFilePrint) ON_COMMAND(ID_FILE_PRINT_DIRECT, CTreeView::OnFilePrint) ON_COMMAND(ID_FILE_PRINT_PREVIEW, CTreeView::OnFilePrintPreview) END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CAreaEditorView construction/destruction CAreaEditorView::CAreaEditorView() { m_pSplitterWindow = NULL; m_hdlTreeArea = NULL; // TODO: add construction code here } CAreaEditorView::~CAreaEditorView() { } BOOL CAreaEditorView::PreCreateWindow(CREATESTRUCT& cs) { if (!CTreeView::PreCreateWindow (cs)) return FALSE; cs.style |= TVS_HASLINES | TVS_LINESATROOT | TVS_HASBUTTONS | TVS_SHOWSELALWAYS | TVS_DISABLEDRAGDROP; return true; } ///////////////////////////////////////////////////////////////////////////// // CAreaEditorView drawing void CAreaEditorView::OnDraw(CDC* pDC) { CAreaEditorDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); // TODO: add draw code for native data here } // This is for adding a new item (mob, object, whatever) to a nominated branch HTREEITEM CAreaEditorView::AddTreeItem (CMUDitem * pItem, const HTREEITEM hdlBranch, const HTREEITEM hInsertAfter) { CAreaEditorDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); HTREEITEM hdlNewItem; hdlNewItem = GetTreeCtrl().InsertItem(pItem->Summary (), hdlBranch, hInsertAfter); GetTreeCtrl().SetItemData (hdlNewItem, (DWORD) pItem); pItem->m_hdlTreeItem = hdlNewItem; pItem->m_pTreeCtrl = &GetTreeCtrl(); return hdlNewItem; } void CAreaEditorView::OnInitialUpdate() { CTreeView::OnInitialUpdate(); CAreaEditorDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); pDoc->m_leftview = this; Refresh (); } ///////////////////////////////////////////////////////////////////////////// // CAreaEditorView printing BOOL CAreaEditorView::OnPreparePrinting(CPrintInfo* pInfo) { // default preparation return DoPreparePrinting(pInfo); } void CAreaEditorView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) { // TODO: add extra initialization before printing } void CAreaEditorView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) { // TODO: add cleanup after printing } ///////////////////////////////////////////////////////////////////////////// // CAreaEditorView diagnostics #ifdef _DEBUG void CAreaEditorView::AssertValid() const { CTreeView::AssertValid(); } void CAreaEditorView::Dump(CDumpContext& dc) const { CTreeView::Dump(dc); } CAreaEditorDoc* CAreaEditorView::GetDocument() // non-debug version is inline { ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CAreaEditorDoc))); return (CAreaEditorDoc*)m_pDocument; } #endif //_DEBUG ///////////////////////////////////////////////////////////////////////////// // CAreaEditorView message handlers void CAreaEditorView::OnItemexpanding(NMHDR* pNMHDR, LRESULT* pResult) { NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR; // TODO: Add your control notification handler code here *pResult = 0; } void CAreaEditorView::OnSelchanged(NMHDR* pNMHDR, LRESULT* pResult) { CAreaEditorDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR; HTREEITEM hdlItem = pNMTreeView->itemNew.hItem; *pResult = 0; m_pSplitterWindow->SetActivePane(0, 0); // make sure info view pane is not active m_pSplitterWindow->DeleteView (0, 1); // delete RH column CMUDitem * pItem = (CMUDitem *) GetTreeCtrl().GetItemData (hdlItem); if (pItem) { // add back the second splitter pane - the area name view if (!m_pSplitterWindow->CreateView(0, 1, pItem->m_pViewClass, CSize(0, 0), NULL)) return; pItem->ChangeRHview (this, (CView *) m_pSplitterWindow->GetPane(0,1)); } else // <no field> { // add the second splitter pane - a blank view in column 1 if (!m_pSplitterWindow->CreateView(0, 1, RUNTIME_CLASS(CBlankView), CSize(0, 0), NULL)) return; } // end of not being in any interesting tree item // force data to be copied from member variables to window CView * pView = (CView *) m_pSplitterWindow->GetPane(0,1); pView->UpdateData (FALSE); // force splitter to redraw new pane m_pSplitterWindow->RecalcLayout (); pView = (CView *) m_pSplitterWindow->GetPane(0,0); pView->SetFocus (); // keep focus on LH window for now } void CAreaEditorView::OnSelchanging(NMHDR* pNMHDR, LRESULT* pResult) { CAreaEditorDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); *pResult = 0; // good update // if we are in middle of deleting a tree item, don't bother syntax checking it if (pDoc->m_bDoingDelete) return; NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR; // update previous view in RH window CView * pView = (CView *) m_pSplitterWindow->GetPane(0,1); if (pView->UpdateData (TRUE)) return; // updated OK else { *pResult = 1; // bad update // *post* a message putting the focus back on the naughty control PostMessage (WM_USER_PUT_FOCUS_BACK, 0, (UINT) pView->GetFocus ()); } } void CAreaEditorView::OnKeydown(NMHDR* pNMHDR, LRESULT* pResult) { TV_KEYDOWN* pTVKeyDown = (TV_KEYDOWN*)pNMHDR; // TODO: Add your control notification handler code here *pResult = 0; } void CAreaEditorView::OnActivateView(BOOL bActivate, CView* pActivateView, CView* pDeactiveView) { CAreaEditorDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); if (bActivate) { pDoc->m_active_view = this; Frame.FixUpTitleBar (pDoc); } else { pDoc->m_active_view = NULL; } CTreeView::OnActivateView(bActivate, pActivateView, pDeactiveView); } void CAreaEditorView::OnAreaDeleteItem() { // find which item is currently selected HTREEITEM hdlItem = GetItem (); if (!hdlItem) return; // get the CMUDitem from that item, if any CMUDitem * pItem = (CMUDitem *) GetTreeCtrl().GetItemData (hdlItem); if (!pItem) return; // can't delete if we can't update (sadly) CView * pView = (CView *) m_pSplitterWindow->GetPane(0,1); if (!pView->UpdateData (TRUE)) return; // ask if they want to delete it if (::AfxMessageBox (CFormat ("OK to delete %s %s?", pItem->Type (), (LPCTSTR) pItem->Summary ()), MB_ICONQUESTION | MB_YESNO) != IDYES) return; pItem->Delete (); } void CAreaEditorView::OnUpdateAreaDeleteItem(CCmdUI* pCmdUI) { CMUDitem * pItem; // find which item is currently selected HTREEITEM hdlItem = GetItem (); // get the CMUDitem from that item, if any if (hdlItem) pItem = (CMUDitem *) GetTreeCtrl().GetItemData (hdlItem); if (hdlItem && pItem) pCmdUI->SetText (CFormat ("&Remove %s\tDel", pItem->Type ())); pCmdUI->Enable ((hdlItem != NULL) && // must have a selection (pItem != NULL) && // must be an item and not a header (hdlItem != m_hdlTreeArea)); // can't delete the area itself } void CAreaEditorView::OnAreaAddItem () { CAreaEditorDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); // find which item is currently selected HTREEITEM hdlItem = GetItem (); // no selected item - cannot add another one like it! if (!hdlItem) return; // cannot add anything other than an area and helps if we don't have an area if ((hdlItem != m_hdlTreeArea) && (hdlItem != m_hdlTreeHelps) && !pDoc->m_Area) return; // ================== new AREA ================================================ if (hdlItem == m_hdlTreeArea) { if (pDoc->m_Area) return; // cannot add a second area pDoc->m_Area = new CArea (RUNTIME_CLASS(CAreaView), pDoc); pDoc->m_Area->strAreaName = "area name"; pDoc->m_Area->obj_low_vnum = 9900; pDoc->m_Area->mob_low_vnum = 9900; pDoc->m_Area->room_low_vnum = 9900; pDoc->m_Area->obj_hi_vnum = 9950; pDoc->m_Area->mob_hi_vnum = 9950; pDoc->m_Area->room_hi_vnum = 9950; GetTreeCtrl().SetItemData (m_hdlTreeArea, (DWORD) pDoc->m_Area); pDoc->m_Area->m_hdlTreeItem = m_hdlTreeArea; pDoc->m_Area->m_pTreeCtrl = &GetTreeCtrl(); GetTreeCtrl().Select (m_hdlTreeHelps, TVGN_CARET); // select away from area GetTreeCtrl().Select (m_hdlTreeArea, TVGN_CARET); // reselect to display it pDoc->SetModifiedFlag (); } // end of area being selected // ================== new MOBILE ================================================ else if (hdlItem == m_hdlTreeMobiles) pDoc->AddMobile (this, true); // ================== new OBJECT ================================================ else if (hdlItem == m_hdlTreeObjects) pDoc->AddObject (this, true); // ================== new ROOM ================================================ else if (hdlItem == m_hdlTreeRooms) pDoc->AddRoom (this, true); // ================== new RESET ================================================ else if (hdlItem == m_hdlTreeResets) { CReset * reset = new CReset (RUNTIME_CLASS(CResetView), pDoc); pDoc->m_ResetList.AddHead (reset); // and add it to our list HTREEITEM hdlResetItem = AddTreeItem (reset, m_hdlTreeResets, TVI_FIRST); GetTreeCtrl().Select (hdlResetItem, TVGN_CARET); // select it pDoc->SetModifiedFlag (); } // end of new reset // ================== new SHOP ================================================ else if (hdlItem == m_hdlTreeShops) { CShop * shop = new CShop (RUNTIME_CLASS(CShopView), pDoc); pDoc->m_ShopList.AddTail (shop); // and add it to our list HTREEITEM hdlShopItem = AddTreeItem (shop, m_hdlTreeShops); GetTreeCtrl().Select (hdlShopItem, TVGN_CARET); // select it pDoc->SetModifiedFlag (); } // end of new shop // ================== new REPAIR ================================================ else if (hdlItem == m_hdlTreeRepairs) { CRepair * repair = new CRepair (RUNTIME_CLASS(CRepairView), pDoc); pDoc->m_RepairList.AddTail (repair); // and add it to our list HTREEITEM hdlRepairItem = AddTreeItem (repair, m_hdlTreeRepairs); GetTreeCtrl().Select (hdlRepairItem, TVGN_CARET); // select it pDoc->SetModifiedFlag (); } // end of new repair // ================== new HELP ================================================ else if (hdlItem == m_hdlTreeHelps) { CHelp * help = new CHelp (RUNTIME_CLASS(CHelpView), pDoc); pDoc->m_HelpList.AddTail (help); // and add it to our list HTREEITEM hdlHelpItem = AddTreeItem (help, m_hdlTreeHelps); GetTreeCtrl().Select (hdlHelpItem, TVGN_CARET); // select it pDoc->SetModifiedFlag (); } // end of new help else { // not a major heading - minor things (eg. mobs) handle their own adding CMUDitem * pItem = (CMUDitem *) GetTreeCtrl().GetItemData (hdlItem); // no item - give up if (!pItem) return; // cannot add - give up if (!pItem->CanAdd ()) return; pItem->Add (this); // add the new item } // end of not being a major heading } // end of CAreaEditorView::OnAreaAddItem void CAreaEditorView::OnUpdateAreaAddItem(CCmdUI* pCmdUI) { CAreaEditorDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); // find which item is currently selected HTREEITEM hdlItem = GetItem (); // set menu text CString strAddType; if (hdlItem == m_hdlTreeArea) strAddType = "area"; else if (hdlItem == m_hdlTreeMobiles) strAddType = "mobile"; else if (hdlItem == m_hdlTreeObjects) strAddType = "object"; else if (hdlItem == m_hdlTreeRooms) strAddType = "room"; else if (hdlItem == m_hdlTreeResets) strAddType = "reset"; else if (hdlItem == m_hdlTreeShops) strAddType = "shop"; else if (hdlItem == m_hdlTreeRepairs) strAddType = "repair"; else if (hdlItem == m_hdlTreeHelps) strAddType = "help"; else { // not a major heading - minor things (eg. mobs) handle their own adding CMUDitem * pItem = (CMUDitem *) GetTreeCtrl().GetItemData (hdlItem); // no item - give up if (pItem || pItem->CanAdd ()) strAddType = pItem->AddDescription (); // add the new item } // end of not being a major heading if (strAddType.IsEmpty ()) pCmdUI->SetText ("Cannot &Add\tCtrl+A"); else pCmdUI->SetText ("&Add " + strAddType + "\tCtrl+A"); // no selected item - cannot add another one like it! if (!hdlItem) { pCmdUI->Enable (false); return; } // cannot add a second area if ((hdlItem == m_hdlTreeArea) && pDoc->m_Area) { pCmdUI->Enable (false); return; } // cannot add anything other than an area and helps if we don't have an area if ((hdlItem != m_hdlTreeArea) && (hdlItem != m_hdlTreeHelps) && !pDoc->m_Area) { pCmdUI->Enable (false); return; } // can add most other things CMUDitem * pItem = (CMUDitem *) GetTreeCtrl().GetItemData (hdlItem); // no item - we can probably add - it will be an area header if (!pItem) { pCmdUI->Enable (true); return; } // let them know if we can add to it pCmdUI->Enable (pItem->CanAdd ()); } // find does the dialog box, and then just calls "find next" void CAreaEditorView::OnAreaFind() { CAreaEditorDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); CFindDlg dlg; if (!App.m_strFindText.IsEmpty ()) dlg.m_strFindText = App.m_strFindText.GetTail (); // default find text dlg.m_bMatchCase = App.m_bMatchCase; // default case dlg.m_iFindType = App.m_iFindType; // default find type dlg.m_bAllAreas = App.m_bAllAreas; // default all areas if (dlg.DoModal () != IDOK) return; // remember find text, if it wasn't the same as last time if (App.m_strFindText.IsEmpty () || App.m_strFindText.GetTail () != dlg.m_strFindText) App.m_strFindText.AddTail (dlg.m_strFindText); // save find text App.m_bMatchCase = dlg.m_bMatchCase ; // save case App.m_iFindType = dlg.m_iFindType; // default find type App.m_bAllAreas = dlg.m_bAllAreas; // default all areas OnAreaFindNext (); } // find next finds the next item *after* this one, matching the specified text void CAreaEditorView::OnAreaFindNext() { // start off with current document CAreaEditorDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); // start off with current tree control CTreeCtrl * pTreeCtrl = & GetTreeCtrl (); // find which item is currently selected HTREEITEM hdlItem = GetItem (); // none selected - start at root if (!hdlItem) hdlItem = pTreeCtrl->GetNextItem (NULL, TVGN_ROOT); if (!hdlItem) return; // no root? strange // remember where we started, for wrap around HTREEITEM hdlStartPoint = hdlItem; CString strWanted = App.m_strFindText.GetTail (); CString strFound; // if not case-sensitive, make upper case if (!App.m_bMatchCase || (App.m_iFindType == eFindVnum)) strWanted.MakeUpper (); // save some work later by fixing vnum field if (App.m_iFindType == eFindVnum) { strWanted.TrimLeft (); strWanted.TrimRight (); // vnum can be M1234 for mob 1234 CString strRestOfVnum = strWanted.Mid (1); strRestOfVnum.TrimLeft (); strWanted = strWanted [0]; // first character strWanted += strRestOfVnum; // rest with leading spaces removed } while (true) { // first look for children of the current item if (pTreeCtrl->ItemHasChildren (hdlItem)) hdlItem = pTreeCtrl->GetChildItem (hdlItem); else { while (true) { HTREEITEM hdlCurrentItem = hdlItem; // next look for siblings of the current item hdlItem = pTreeCtrl->GetNextItem (hdlItem, TVGN_NEXT); if (hdlItem) break; // found one - exit loop // no siblings - get parent - and then next sibling if (!hdlItem) { hdlItem = pTreeCtrl->GetParentItem (hdlCurrentItem); if (!hdlItem) break; // no parent - must be at end of tree control } // end of no getting parent } // end of finding a sibling somewhere } // end of tree control - start at root (wrap around), or change areas if (!hdlItem) { if (App.m_bAllAreas) { POSITION docPos; // find this area for (docPos = App.m_pDocTemplate->GetFirstDocPosition(); docPos != NULL; ) { CAreaEditorDoc * pThisDoc = (CAreaEditorDoc *) App.m_pDocTemplate->GetNextDoc(docPos); if (pThisDoc == pDoc) break; } // end of doing each document // now, docPos should be the position of the next area, or NULL if this was // the last one if (!docPos) // wrap to first area docPos = App.m_pDocTemplate->GetFirstDocPosition(); if (!docPos) return; // no areas? very strange // now get next area pDoc = (CAreaEditorDoc *) App.m_pDocTemplate->GetNextDoc(docPos); // get new tree control pTreeCtrl = & pDoc->m_leftview->GetTreeCtrl (); } // end of all areas wanted hdlItem = pTreeCtrl->GetNextItem (NULL, TVGN_ROOT); } if (hdlItem == hdlStartPoint) break; // stop when we reach starting point again // find associated MUD item, if any CMUDitem * pItem = (CMUDitem *) pTreeCtrl->GetItemData (hdlItem); if (!pItem) continue; // ignore those without it // do the appropriate sort of search if (pItem->Search (strWanted, App.m_iFindType, App.m_bMatchCase)) { pItem->GoTo (); // go to this item // pTreeCtrl->Select (hdlItem, TVGN_CARET); return; } // end of found wanted string } // end of looking for an item CString strNotFoundType; switch (App.m_iFindType) { case eFindSummary: strNotFoundType = " in item summaries"; break; case eFindDetail: strNotFoundType = " in item detail"; break; case eFindProgram: strNotFoundType = " in MUD programs"; break; case eFindVnum: switch (toupper (App.m_strFindText.GetTail () [0])) { case 'M': strNotFoundType = " (mob vnum)"; break; case 'R': strNotFoundType = " (room vnum)"; break; case 'O': strNotFoundType = " (object vnum)"; break; default: strNotFoundType = " in item vnums"; break; } // end of switching on 1st char of vnum break; } // end of switch ::AfxMessageBox (CFormat ("Could not find \"%s\"%s.", (LPCTSTR) App.m_strFindText.GetTail (), (LPCTSTR) strNotFoundType), MB_ICONINFORMATION); } void CAreaEditorView::OnUpdateAreaFindNext(CCmdUI* pCmdUI) { CAreaEditorDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); pCmdUI->Enable (!App.m_strFindText.IsEmpty ()); } void CAreaEditorView::OnContextMenu(CWnd*, CPoint point) { // CG: This block was added by the Pop-up Menu component { if (point.x == -1 && point.y == -1){ //keystroke invocation CRect rect; GetClientRect(rect); ClientToScreen(rect); point = rect.TopLeft(); point.Offset(5, 5); } CMenu menu; VERIFY(menu.LoadMenu(CG_IDR_POPUP_AREA_EDITOR_VIEW)); CMenu* pPopup = menu.GetSubMenu(0); ASSERT(pPopup != NULL); CWnd* pWndPopupOwner = this; while (pWndPopupOwner->GetStyle() & WS_CHILD) pWndPopupOwner = pWndPopupOwner->GetParent(); pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y, pWndPopupOwner); } } void CAreaEditorView::OnRclick(NMHDR* pNMHDR, LRESULT* pResult) { CPoint pt; GetCursorPos (&pt); HTREEITEM hdlDropItem = GetTreeCtrl().GetDropHilightItem( ); if (hdlDropItem) if (GetTreeCtrl().Select (hdlDropItem, TVGN_CARET)) OnContextMenu (this, pt); *pResult = 1; } // return the selected item HTREEITEM CAreaEditorView::GetItem (void) const { return GetTreeCtrl().GetNextItem (NULL, TVGN_CARET); } void CAreaEditorView::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint) { CAreaEditorDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); CString strOldTitle; CString strNewTitle = "Untitled area"; // use area name for window name, otherwise document name, otherwise "untitled" /* if (pDoc->m_Area && !pDoc->m_Area->strAreaName.IsEmpty ()) strNewTitle = pDoc->m_Area->strAreaName; else */ // Show full pathname to area document in title if (!pDoc->GetPathName ().IsEmpty ()) strNewTitle = pDoc->GetPathName (); GetParentFrame ()->GetWindowText (strOldTitle); // amend title if necessary (avoid flicker) if (strOldTitle != strNewTitle) GetParentFrame ()->SetWindowText (strNewTitle); } void CAreaEditorView::OnUpdateAreaDuplicateItem(CCmdUI* pCmdUI) { CAreaEditorDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); // find which item is currently selected HTREEITEM hdlItem = GetItem (); // no selected item - cannot duplicate it! if (!hdlItem) { pCmdUI->Enable (false); pCmdUI->SetText ("Cannot &Duplicate\tCtrl+D"); return; } // can duplicate most other things CMUDitem * pItem = (CMUDitem *) GetTreeCtrl().GetItemData (hdlItem); // no item - we can't duplicate it if (!pItem) { pCmdUI->Enable (false); pCmdUI->SetText ("Cannot &Duplicate\tCtrl+D"); return; } // let them know if we can add to it pCmdUI->Enable (pItem->CanDuplicate ()); pCmdUI->SetText (CFormat ("&Duplicate %s\tCtrl+D", pItem->Type ())); } void CAreaEditorView::OnAreaDuplicateItem() { CAreaEditorDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); // find which item is currently selected HTREEITEM hdlItem = GetItem (); // no selected item - cannot add another one like it! if (!hdlItem) return; CMUDitem * pItem = (CMUDitem *) GetTreeCtrl().GetItemData (hdlItem); // no item - give up if (!pItem) return; // cannot duplicate - give up if (!pItem->CanDuplicate ()) return; pItem->Duplicate (this); // duplicate the item } BOOL CAreaEditorView::PreTranslateMessage(MSG* pMsg) { if (pMsg->message == WM_USER_PUT_FOCUS_BACK) { CView * pView = (CView *) m_pSplitterWindow->GetPane(0,1); pView->PostMessage (WM_SETFOCUS, 0, 0); CWnd * pNewFocusWindow = (CWnd *) pMsg->lParam; pNewFocusWindow->SetFocus (); return TRUE; // message was handled } return CTreeView::PreTranslateMessage(pMsg); } void CAreaEditorView::Refresh (void) { CTreeView::OnInitialUpdate(); CAreaEditorDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); SetStatusMsg ("Initialising view"); if (m_hdlTreeArea) GetTreeCtrl().Select (m_hdlTreeArea, TVGN_CARET); CWaitCursor wait; GetTreeCtrl().DeleteAllItems (); m_hdlTreeArea = GetTreeCtrl().InsertItem("Area"); m_hdlTreeHelps = GetTreeCtrl().InsertItem("Helps"); m_hdlTreeMobiles = GetTreeCtrl().InsertItem("Mobiles"); // m_hdlTreeMudprogs = GetTreeCtrl().InsertItem("Mudprogs"); m_hdlTreeObjects = GetTreeCtrl().InsertItem("Objects"); // m_hdlTreeObjprogs = GetTreeCtrl().InsertItem("Objprogs"); m_hdlTreeResets = GetTreeCtrl().InsertItem("Resets"); m_hdlTreeRooms = GetTreeCtrl().InsertItem("Rooms"); m_hdlTreeShops = GetTreeCtrl().InsertItem("Shops"); m_hdlTreeRepairs = GetTreeCtrl().InsertItem("Repairs"); if (pDoc->m_Area) { GetTreeCtrl().SetItemData (m_hdlTreeArea, (DWORD) pDoc->m_Area); pDoc->m_Area->m_hdlTreeItem = m_hdlTreeArea; pDoc->m_Area->m_pTreeCtrl = &GetTreeCtrl(); } // ======================================================================== SetStatusMsg ("Setting up mobiles"); // add the mobiles list CMobile * mob; HTREEITEM hdlMobItem; for (POSITION mobPos = pDoc->m_MobList.GetHeadPosition (); mobPos; ) { mob = pDoc->m_MobList.GetNext (mobPos); hdlMobItem = AddTreeItem (mob, m_hdlTreeMobiles); // add programs to the mobile for (POSITION progPos = mob->programlist.GetHeadPosition (); progPos; ) AddTreeItem (mob->programlist.GetNext (progPos), hdlMobItem); } // end of adding each mob // ======================================================================== SetStatusMsg ("Setting up objects"); // add the objects list CMUDObject * obj; HTREEITEM hdlObjItem; for (POSITION objPos = pDoc->m_ObjectList.GetHeadPosition (); objPos; ) { obj = pDoc->m_ObjectList.GetNext (objPos); hdlObjItem = AddTreeItem (obj, m_hdlTreeObjects); // add extra descriptions to the object for (POSITION extraPos = obj->extralist.GetHeadPosition (); extraPos; ) AddTreeItem (obj->extralist.GetNext (extraPos), hdlObjItem); // add affects to the object for (POSITION affectPos = obj->affectlist.GetHeadPosition (); affectPos; ) AddTreeItem (obj->affectlist.GetNext (affectPos), hdlObjItem); // add programs to the object for (POSITION progPos = obj->programlist.GetHeadPosition (); progPos; ) AddTreeItem (obj->programlist.GetNext (progPos), hdlObjItem); } // end of adding each object // ======================================================================== SetStatusMsg ("Setting up rooms"); // add the rooms list CRoom * room; HTREEITEM hdlRoomItem; for (POSITION roomPos = pDoc->m_RoomList.GetHeadPosition (); roomPos; ) { room = pDoc->m_RoomList.GetNext (roomPos); hdlRoomItem = AddTreeItem (room, m_hdlTreeRooms); // add extra descriptions to the room for (POSITION extraPos = room->extralist.GetHeadPosition (); extraPos; ) AddTreeItem (room->extralist.GetNext (extraPos), hdlRoomItem); // add exits to the room for (POSITION exitPos = room->exitlist.GetHeadPosition (); exitPos; ) AddTreeItem (room->exitlist.GetNext (exitPos), hdlRoomItem); // add programs to the object for (POSITION progPos = room->programlist.GetHeadPosition (); progPos; ) AddTreeItem (room->programlist.GetNext (progPos), hdlRoomItem); } // end of adding each room // ======================================================================== SetStatusMsg ("Setting up resets"); // add the resets list for (POSITION resetPos = pDoc->m_ResetList.GetHeadPosition (); resetPos; ) AddTreeItem (pDoc->m_ResetList.GetNext (resetPos), m_hdlTreeResets); // ======================================================================== SetStatusMsg ("Setting up shops"); // add the shops list for (POSITION shopPos = pDoc->m_ShopList.GetHeadPosition (); shopPos; ) AddTreeItem (pDoc->m_ShopList.GetNext (shopPos), m_hdlTreeShops); // ======================================================================== SetStatusMsg ("Setting up repairs"); // add the repairs list for (POSITION repairPos = pDoc->m_RepairList.GetHeadPosition (); repairPos; ) AddTreeItem (pDoc->m_RepairList.GetNext (repairPos), m_hdlTreeRepairs); // ======================================================================== SetStatusMsg ("Setting up helps"); // add the helps list for (POSITION helpPos = pDoc->m_HelpList.GetHeadPosition (); helpPos; ) AddTreeItem (pDoc->m_HelpList.GetNext (helpPos), m_hdlTreeHelps); // ======================================================================== // select "area" node GetTreeCtrl().Select (m_hdlTreeArea, TVGN_CARET); SetStatusMsg ("For Help, press F1"); GetTreeCtrl().Select (m_hdlTreeArea, TVGN_CARET); } // end of CAreaEditorView::Refresh void CAreaEditorView::OnViewRefresh() { Refresh (); } void CAreaEditorView::OnAreaCheckallareas() { CheckAreas (NULL); }