⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 modelcontroller.cpp

📁 A Model-View-Controller Framework that integrates with the MFC Doc/View architecture.
💻 CPP
字号:
#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;
			}
		}
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -