#include "stdafx.h"
#include "ModelController.h"
#include "CmdTargetController.h"
#include "CmdMsgHandler.h"
#include "ModelEvents.h"
#include "DocEvents.h"
#include "UndoRedoMgr.h"
#include "UndoRedoHandler.h"
#include "ControlledDocument.h"
#include "DocController.h"
namespace localNS
{
HANDLE HITEM_ROOT = (HANDLE)0xFFFFFFFF;
// Message Handlers ///////////////////////////////////////////////////////////////
class OnRemoveSelectedHandler : public SbjCore::Mvc::CmdMsgHandler
{
SbjCore::Mvc::Model::Controller* pTheCtrlr;
public:
OnRemoveSelectedHandler()
{
}
void SetCtrlr(SbjCore::Mvc::Model::Controller* p)
{
pTheCtrlr = p;
}
private:
virtual bool OnHandleCmd(UINT nID)
{
nID;
bool bRslt = false;
ASSERT(pTheCtrlr != NULL);
if (pTheCtrlr != NULL)
{
SbjCore::Mvc::Model::ItemHandles selItems;
pTheCtrlr->GetSelectedItems(selItems);
for (SbjCore::Mvc::Model::ItemHandlesIter iter = selItems.begin(); iter != selItems.end(); iter++)
{
HANDLE hItem = *iter;
pTheCtrlr->RemoveChild(hItem);
}
selItems.clear();
bRslt = true;
}
return bRslt;
}
virtual bool OnHandleCmdUI(CCmdUI* pCmdUI)
{
bool bRslt = true;
ASSERT(pTheCtrlr != NULL);
if (pTheCtrlr != NULL)
{
SbjCore::Mvc::Model::ItemHandles selItems;
int nCount = pTheCtrlr->GetSelectedItems(selItems);
pCmdUI->Enable(nCount > 0);
}
return bRslt;
};
};
class OnUndoHandler : public SbjCore::Mvc::CmdMsgHandler
{
virtual bool OnHandleCmd(UINT nID)
{
nID;
bool bRslt = false;
SbjCore::Mvc::Model::Controller* pCtrlr = dynamic_cast<SbjCore::Mvc::Model::Controller*>(GetController());
SbjCore::UndoRedo::Manager* pMgr = pCtrlr->GetUndoRedoMgr();
if (pMgr != NULL)
{
CMFCRibbonUndoButton* pUndoBtn = pMgr->GetUndoButton();
if (pUndoBtn != NULL)
{
int nActionNumber = pUndoBtn->GetActionNumber();
int nCount = (nActionNumber > 0) ? nActionNumber : 1;
pCtrlr->GetUndoRedoMgr()->Undo(nCount);
bRslt = true;
}
else
{
pCtrlr->GetUndoRedoMgr()->Undo(1);
bRslt = true;
}
}
return bRslt;
}
virtual bool OnHandleCmdUI(CCmdUI* pCmdUI)
{
bool bRslt = false;
bool bEnable = false;
SbjCore::Mvc::Model::Controller* pCtrlr = dynamic_cast<SbjCore::Mvc::Model::Controller*>(GetController());
SbjCore::UndoRedo::Manager* pMgr = pCtrlr->GetUndoRedoMgr();
if (pMgr != NULL)
{
bEnable = pMgr->EnableUndo();
bRslt = true;
}
pCmdUI->Enable(bEnable);
return bRslt;
}
};
class OnRedoHandler : public SbjCore::Mvc::CmdMsgHandler
{
virtual bool OnHandleCmd(UINT nID)
{
nID;
bool bRslt = false;
SbjCore::Mvc::Model::Controller* pCtrlr = dynamic_cast<SbjCore::Mvc::Model::Controller*>(GetController());
SbjCore::UndoRedo::Manager* pMgr = pCtrlr->GetUndoRedoMgr();
if (pMgr != NULL)
{
CMFCRibbonUndoButton* pUndoBtn = pMgr->GetRedoButton();
if (pUndoBtn != NULL)
{
int nActionNumber = pUndoBtn->GetActionNumber();
int nCount = (nActionNumber > 0) ? nActionNumber : 1;
pCtrlr->GetUndoRedoMgr()->Redo(nCount);
bRslt = true;
}
else
{
pCtrlr->GetUndoRedoMgr()->Redo(1);
bRslt = true;
}
}
return bRslt;
}
virtual bool OnHandleCmdUI(CCmdUI* pCmdUI)
{
bool bRslt = false;
bool bEnable = false;
SbjCore::Mvc::Model::Controller* pCtrlr = dynamic_cast<SbjCore::Mvc::Model::Controller*>(GetController());
SbjCore::UndoRedo::Manager* pMgr = pCtrlr->GetUndoRedoMgr();
if (pMgr != NULL)
{
bEnable = pMgr->EnableRedo();
bRslt = true;
}
pCmdUI->Enable(bEnable);
return bRslt;
}
};
}
///////////////////////////////////////////////////////////////////////
namespace SbjCore
{
namespace Mvc
{
namespace Model
{
struct ControllerImpl
{
Controller* pTheCtrlr;
UndoRedo::Manager theUndoRedoMgr;
ItemHandles theSelectionList;
localNS::OnRemoveSelectedHandler theOnRemoveSelectedHandler;
localNS::OnUndoHandler theOnUndoHandler;
localNS::OnRedoHandler theOnRedoHandler;
ControllerImpl() :
pTheCtrlr(NULL)
{
}
virtual ~ControllerImpl()
{
ClearSelectedItems();
}
void SetCtrlr(Controller* p)
{
pTheCtrlr = p;
}
int GetSelectedItems( ItemHandles& selItems )
{
selItems = theSelectionList;
return selItems.size();
}
void SetSelectedItems( const ItemHandles& selItems )
{
ClearSelectedItems();
theSelectionList = selItems;
SbjCore::Mvc::Model::Events::SelItemsChanged event(pTheCtrlr, theSelectionList);
}
void ClearSelectedItems()
{
theSelectionList.clear();
}
};
/////////////////////////////////////////////////////////
IMPLEMENT_DYNAMIC(Controller, t_Base)
Controller::Controller() :
m_pImpl(new ControllerImpl)
{
m_pImpl->SetCtrlr(this);
m_pImpl->theOnRemoveSelectedHandler.SetCtrlr(this);
AddHandler(ID_SBJCORE_CTX_DELETE, &m_pImpl->theOnRemoveSelectedHandler);
AddHandler(ID_EDIT_UNDO, &m_pImpl->theOnUndoHandler);
AddHandler(ID_EDIT_REDO, &m_pImpl->theOnRedoHandler);
}
Controller::~Controller()
{
try
{
delete m_pImpl;
}
catch(...)
{
ASSERT(FALSE);
}
}
HANDLE Controller::GetItemRoot()
{
return localNS::HITEM_ROOT;
}
int Controller::GetSelectedItems( ItemHandles& selItems ) const
{
return m_pImpl->GetSelectedItems(selItems);
}
void Controller::SetSelectedItems( const ItemHandles& selItems )
{
m_pImpl->SetSelectedItems(selItems);
}
void Controller::ClearSelectedItems()
{
m_pImpl->ClearSelectedItems();
}
bool Controller::InsertChild(
const HANDLE hChild,
const HANDLE hParent,
const HANDLE hAfter /*= NULL*/,
bool bAddToUndoRedo /*= true*/)
{
Events::ItemInsert eventItemInserting(Events::EVID_ITEM_INSERTING, this, hChild, hParent, hAfter);
bool bRslt = OnInsertChild(hChild, hParent, hAfter);
if (bRslt)
{
if (bAddToUndoRedo)
{
class UndoRedoHandler : public SbjCore::UndoRedo::Handler
{
CString sActionName;
Controller* pTheCtrlr;
const HANDLE hChild;
const HANDLE hParent;
const HANDLE hAfter;
public:
UndoRedoHandler(Controller* p,
const HANDLE hC,
const HANDLE hP,
const HANDLE hA) :
sActionName(_T("Insert")),
pTheCtrlr(p),
hChild(hC),
hParent(hP),
hAfter(hA)
{
}
virtual bool OnHandleUndo()
{
return pTheCtrlr->RemoveChild(hChild, false);
}
virtual bool OnHandleRedo()
{
return pTheCtrlr->InsertChild(hChild, hParent, hAfter, false);
}
virtual LPCTSTR OnGetHandlerName() const
{
return sActionName;
}
};
UndoRedoHandler* pUndoRedoHandler = new UndoRedoHandler(this, hChild, hParent, hAfter);
m_pImpl->theUndoRedoMgr.Push(pUndoRedoHandler);
}
Events::ItemInsert eventItemInserted(Events::EVID_ITEM_INSERTED, this, hChild, hParent, hAfter);
Doc::Events::DocModified eventDocModified(true);
}
return bRslt;
}
bool Controller::RemoveChild(
const HANDLE hChild,
bool bAddToUndoRedo /*= true*/)
{
HANDLE hTheParent = GetParentItem(hChild);;
Model::Events::ItemRemove eventItemRemoving(Model::Events::EVID_ITEM_REMOVING, this, hChild);
bool bRslt = OnRemoveChild(hChild);
if (bRslt)
{
if (bAddToUndoRedo)
{
class UndoRedoHandler : public SbjCore::UndoRedo::Handler
{
CString sActionName;
Controller* pTheCtrlr;
const HANDLE hChild;
const HANDLE hParent;
public:
UndoRedoHandler(Controller* p,
const HANDLE hC,
const HANDLE hP) :
sActionName(_T("Remove")),
pTheCtrlr(p),
hChild(hC),
hParent(hP)
{
}
virtual bool OnHandleUndo()
{
return pTheCtrlr->InsertChild(hChild, hParent, NULL, false);
}
virtual bool OnHandleRedo()
{
return pTheCtrlr->RemoveChild(hChild, false);
}
virtual LPCTSTR OnGetHandlerName() const
{
return sActionName;
}
};
UndoRedoHandler* pUndoRedoHandler = new UndoRedoHandler(this, hChild, hTheParent);
m_pImpl->theUndoRedoMgr.Push(pUndoRedoHandler);
}
Model::Events::ItemRemove eventItemRemoved(Model::Events::EVID_ITEM_REMOVED, this, hChild);
Doc::Events::DocModified eventDocModified(true);
}
return bRslt;
}
_variant_t Controller::GetItemAttrValue(
const HANDLE hItem,
const CString& sAttrName) const
{
return OnGetItemAttrValue(hItem, sAttrName);
}
bool Controller::SetItemAttrValue(
const HANDLE hItem,
const CString& sAttrName,
const _variant_t& val,
bool bAddToUndoRedo /*= false*/,
bool bFireEvents /*= false*/)
{
_variant_t vAfter = val;
_variant_t vBefore;
if (bAddToUndoRedo)
{
vBefore = GetItemAttrValue(hItem, sAttrName);
}
bool bRslt = OnSetItemAttrValue(hItem, sAttrName, val);
if (bRslt)
{
if (bAddToUndoRedo)
{
class UndoRedoHandler : public SbjCore::UndoRedo::Handler
{
CString sActionName;
Controller* pTheCtrlr;
const HANDLE hItem;
CString sAttrName;
_variant_t vBefore;
_variant_t vAfter;
public:
UndoRedoHandler(
Controller* p,
const HANDLE h,
CString a,
_variant_t vB,
_variant_t vA) :
pTheCtrlr(p),
hItem(h),
sAttrName(a),
vBefore(vB),
vAfter(vA)
{
CString s(pTheCtrlr->CookAttrName(sAttrName));
sActionName.Format(_T("%s change"), s);
}
virtual bool OnHandleUndo()
{
return pTheCtrlr->SetItemAttrValue(hItem, sAttrName, vBefore, false, true);
}
virtual bool OnHandleRedo()
{
return pTheCtrlr->SetItemAttrValue(hItem, sAttrName, vAfter, false, true);
}
virtual LPCTSTR OnGetHandlerName() const
{
return sActionName;
}
};
UndoRedoHandler* pUndoRedoHandler = new UndoRedoHandler(this, hItem, sAttrName, vBefore, vAfter);
m_pImpl->theUndoRedoMgr.Push(pUndoRedoHandler);
}
if (bFireEvents)
{
Model::Events::ItemChange eventItemChanged(Model::Events::EVID_ITEM_CHANGED, this, hItem, sAttrName);
Doc::Events::DocModified eventDocModified(true);
}
}
return bRslt;
}
CString Controller::CookAttrName(const CString& sAttrName) const
{
return OnCookAttrName(sAttrName);
}
CString Controller::OnCookAttrName(const CString& sAttrName) const
{
CString s;
int nIndex = 0;
while (sAttrName.GetAt(nIndex) != NULL)
{
CString sTemp(sAttrName.GetAt(nIndex));
if (0 == nIndex)
{
s = sTemp.MakeUpper();
}
else if (_istupper(sAttrName.GetAt(nIndex)))
{
if (!_istupper(sAttrName.GetAt(nIndex - 1)))
{
s += " ";
}
s += sTemp;
}
else
{
s += sTemp;
}
nIndex++;
}
return s;
}
CString Controller::AssureUniqueItemAttrValue(
const HANDLE hItem,
const CString& sAttrName,
const _variant_t& val) const
{
return OnAssureUniqueItemAttrValue(hItem, sAttrName, val);
}
SbjCore::UndoRedo::Manager* Controller::GetUndoRedoMgr() const
{
return &m_pImpl->theUndoRedoMgr;
}
CString Controller::GetItemTypeName( HANDLE hItem ) const
{
return OnGetItemTypeName(hItem);
}
int Controller::GetItemChildren(HANDLE hItem, SbjCore::Mvc::Model::ItemHandles& items) const
{
return OnGetItemChildren(hItem, items);
}
int Controller::GetItemAttrNames( HANDLE hItem, SbjCore::Mvc::Model::ItemAttrNames& attrNames ) const
{
return OnGetItemAttrNames(hItem, attrNames);
}
CString Controller::GetItemAttrName( HANDLE hItem, int nAttrIndex ) const
{
CString sAttrName;
SbjCore::Mvc::Model::ItemAttrNames attrNames;
int nCount = GetItemAttrNames(hItem, attrNames);
if (nCount > nAttrIndex)
{
sAttrName = attrNames[nAttrIndex];
}
return sAttrName;
}
HANDLE Controller::CreateItem( LPCTSTR lpszItemType )
{
return OnCreateItem(lpszItemType);
}
HANDLE Controller::GetParentItem( const HANDLE hItem ) const
{
return OnGetParentItem(hItem);
}
Controller* GetCurController()
{
SbjCore::Mvc::Model::Controller* pModelCtrlr = NULL;
CFrameWnd* pFrame = dynamic_cast<CFrameWnd*>(AfxGetMainWnd());
if (pFrame != NULL)
{
SbjCore::Mvc::Doc::ControlledDocument* pDoc = dynamic_cast<SbjCore::Mvc::Doc::ControlledDocument*>(pFrame->GetActiveDocument());
if (pDoc != NULL)
{
pModelCtrlr = dynamic_cast<SbjCore::Mvc::Model::Controller*>(pDoc->GetDocController());
}
}
return pModelCtrlr;
}
}
}
}