|
//------------------------------------------------------------------------------
// $Workfile: TreeItemController.cpp $
// $Header: /SbjDev/SbjCore/TreeItemController.cpp 6 11/12/08 2:22p Steve $
//
// Copyright � 2008 SbjCat
// All rights reserved.
//
//
// *** Authors ***
// Steve Johnson
//
// $Revision: 6 $
//
//-----------------------------------------------------------------------------
#include "StdAfx.h"
#include "TreeItemController.h"
#include "resource.h"
#include "TreeController.h"
#include "ItemDisplayModel.h"
#include "NotifyMsgHandler.h"
#include "CtrlUtils.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
namespace localNS
{
// Message Handlers //////////////////////////////////////////////////////////////////////////
class BeginLabelEditHandler : public SbjCore::Mvc::NotifyMsgHandler
{
virtual bool OnHandleNotify(NMHDR* pNMHDR, LRESULT* pResult)
{
pNMHDR;
bool bRslt = true;
*pResult = 1;
SbjCore::Mvc::TreeView::ItemController* pItem = dynamic_cast<SbjCore::Mvc::TreeView::ItemController*>(GetController());
if (pItem->CanEdit())
{
*pResult = 0;
}
return bRslt;
}
};
//////////////////////////////////////////////////////////////////////////////
class EndLabelEditHandler : public SbjCore::Mvc::NotifyMsgHandler
{
virtual bool OnHandleNotify(NMHDR* pNMHDR, LRESULT* pResult)
{
bool bRslt = true;
SbjCore::Mvc::TreeView::ItemController* pItem = dynamic_cast<SbjCore::Mvc::TreeView::ItemController*>(GetController());
TV_DISPINFO* pTVDispInfo = (TV_DISPINFO*)pNMHDR;
*pResult = 0;
if ((pTVDispInfo->item.mask != 0) && (pTVDispInfo->item.pszText != NULL))
{
if (pTVDispInfo->item.pszText[0] != NULL)
{
CString sNewName(pTVDispInfo->item.pszText);
HTREEITEM htiParent = TVI_ROOT;
SbjCore::Mvc::TreeView::ItemController* pParent = pItem->GetParentItem();
if (pParent != NULL)
{
htiParent = pItem->GetParentItem()->GetHandle();
}
const SbjCore::Mvc::TreeView::Controller* pCtrlr = dynamic_cast<const SbjCore::Mvc::TreeView::Controller*>(pItem->GetTreeController());
if (pCtrlr->NameExists(sNewName, htiParent))
{
CString s;
s.Format(_T("%s exists,\nplease rename"), sNewName);
AfxMessageBox(s);
pItem->EditLabel();
}
else
{
pItem->UpdateItemText(sNewName);
*pResult = 1;
}
}
}
return bRslt;
}
};
}
//////////////////////////////////////////////////////////////////////////////
namespace SbjCore
{
namespace Mvc
{
namespace TreeView
{
struct ItemControllerImpl
{
HTREEITEM hti;
HTREEITEM hItemAfter;
HANDLE hItem;
Utils::Ctrl::TVItem tvi;
TCHAR szItemText[256];
const ItemDisplayModel *pIDM;
const Controller *pTheTreeCtrlr;
localNS::BeginLabelEditHandler theBeginItemLabelEditHandler;
localNS::EndLabelEditHandler theEndItemLabelEditHandler;
ItemControllerImpl() :
hti(NULL),
hItemAfter(TVI_LAST),
hItem(NULL),
pIDM(NULL),
pTheTreeCtrlr(NULL)
{
}
virtual ~ItemControllerImpl()
{
}
void Init(ItemController *p)
{
if (pIDM != NULL)
{
tvi.SetItemText(p->SaveItemText(pIDM->GetItemText()));
tvi.SetImage(pTheTreeCtrlr->ImageIndexFromResID(pIDM->GetImageResID()));
tvi.SetSelectedImage(pTheTreeCtrlr->ImageIndexFromResID(pIDM->GetSelectedImageResID()));
}
tvi.SetParam((LPARAM)p);
}
void UpdateTreeCtrl(ItemController *p, Utils::Ctrl::TVItem *pItem)
{
CTreeCtrl *pTreeCtrl = pTheTreeCtrlr->GetTreeCtrl();
ASSERT(hti != NULL);
pItem->SetHandle(hti);
pItem->SetParam((LPARAM)p);
pTreeCtrl->SetItem((TVITEM*)pItem);
}
};
//////////////////////////////////////////////////////////////////////////////
// ItemController
IMPLEMENT_DYNCREATE(ItemController, WndController)
ItemController::ItemController() :
m_pImpl(new ItemControllerImpl)
{
AddHandler(TVN_BEGINLABELEDIT, &m_pImpl->theBeginItemLabelEditHandler);
AddHandler(TVN_ENDLABELEDIT, &m_pImpl->theEndItemLabelEditHandler);
}
ItemController::~ItemController()
{
try
{
delete m_pImpl;
}
catch (...)
{
ASSERT(FALSE);
}
}
void ItemController::InsertAfter( const HTREEITEM hti )
{
m_pImpl->hItemAfter = hti;
}
HTREEITEM ItemController::InsertAfter() const
{
return m_pImpl->hItemAfter;
}
void TreeView::ItemController::Create(const SbjCore::Mvc::Model::Controller* pModelCtrlr, const SbjCore::Mvc::TreeView::Controller* pTreeController, HANDLE hItem )
{
pModelCtrlr;
SetTreeController(pTreeController);
SetModelItemHandle(hItem);
}
void ItemController::SetTreeController( const SbjCore::Mvc::TreeView::Controller* p )
{
m_pImpl->pTheTreeCtrlr = p;
}
const SbjCore::Mvc::TreeView::Controller* ItemController::GetTreeController() const
{
return m_pImpl->pTheTreeCtrlr;
}
void ItemController::SetModelItemHandle( const HANDLE h )
{
m_pImpl->hItem = h;
}
HANDLE ItemController::GetModelItemHandle() const
{
return m_pImpl->hItem;
}
const ItemDisplayModel *ItemController::GetItemDisplayModel() const
{
return m_pImpl->pIDM;
}
void ItemController::SetItemDisplayModel(const ItemDisplayModel *pIDM)
{
m_pImpl->pIDM = pIDM;
m_pImpl->Init(this);
}
ItemController* ItemController::GetParentItem() const
{
return m_pImpl->pTheTreeCtrlr->GetParentItem(this);
}
bool ItemController::IsChildOf(ItemController* pItem)
{
bool bRslt = false;
ItemController* pParent = GetParentItem();
while (pParent != NULL)
{
if (pParent == pItem)
{
bRslt = true;
break;
}
pParent = pParent->GetParentItem();
}
return bRslt;
}
TVITEMEX& ItemController::GetTVItem() const
{
return m_pImpl->tvi;
}
void ItemController::SetHandle(const HTREEITEM hti)
{
m_pImpl->hti = hti;
}
HTREEITEM ItemController::GetHandle() const
{
return m_pImpl->hti;
}
LPTSTR ItemController::SaveItemText(LPCTSTR lpszItemText)
{
LPTSTR lpszReturn = LPSTR_TEXTCALLBACK;
if (lpszItemText != LPSTR_TEXTCALLBACK)
{
_tcscpy_s(m_pImpl->szItemText, 255, lpszItemText);
lpszReturn = (LPTSTR)&m_pImpl->szItemText;
}
return lpszReturn;
}
bool ItemController::CanAcceptChildren()
{
return true; // override to prevent
}
bool ItemController::CanEdit()
{
return true; // override to prevent
}
bool ItemController::CanDelete()
{
return true; // override to prevent
}
void ItemController::OnInserted()
{
// do nothing
}
void ItemController::EditLabel()
{
CTreeCtrl *pTree = m_pImpl->pTheTreeCtrlr->GetTreeCtrl();
HTREEITEM hti = pTree->GetSelectedItem();
while (NULL == pTree->EditLabel(hti)); // first time fails
}
void ItemController::UpdateItemText(LPCTSTR lpszItemText)
{
Utils::Ctrl::TVItem tvi;
tvi.SetItemText(SaveItemText(lpszItemText));
m_pImpl->UpdateTreeCtrl(this, &tvi);
}
void ItemController::UpdateImage(long nImage)
{
Utils::Ctrl::TVItem tvi;
tvi.SetImage(m_pImpl->pTheTreeCtrlr->ImageIndexFromResID(nImage));
m_pImpl->UpdateTreeCtrl(this, &tvi);
}
void ItemController::UpdateSelectedImage(long nImage)
{
Utils::Ctrl::TVItem tvi;
tvi.SetSelectedImage(m_pImpl->pTheTreeCtrlr->ImageIndexFromResID(nImage));
m_pImpl->UpdateTreeCtrl(this, &tvi);
}
void ItemController::UpdateState(UINT nState, UINT nStateMask)
{
//1.21.2004 SBJ - prevents deselect
// if (nState)
{
Utils::Ctrl::TVItem tvi;
tvi.SetState(nState, nStateMask);
m_pImpl->UpdateTreeCtrl(this, &tvi);
}
}
void ItemController::UpdateOverlayImage(UINT nIndex)
{
if (nIndex)
{
Utils::Ctrl::TVItem tvi;
tvi.SetOverlayIndex(nIndex);
m_pImpl->UpdateTreeCtrl(this, &tvi);
}
}
void ItemController::UpdateStateImage(UINT nIndex)
{
if (nIndex)
{
Utils::Ctrl::TVItem tvi;
tvi.SetStateImageIndex(nIndex);
m_pImpl->UpdateTreeCtrl(this, &tvi);
}
}
void ItemController::UpdateChildren(long nCount)
{
Utils::Ctrl::TVItem tvi;
tvi.SetChildren(nCount);
m_pImpl->UpdateTreeCtrl(this, &tvi);
}
void ItemController::DeselectItem()
{
UpdateState(0, TVIS_SELECTED);
}
BOOL ItemController::IsSelected()
{
return IsState(TVIS_SELECTED);
}
BOOL ItemController::IsCut()
{
return IsState(TVIS_CUT);
}
BOOL ItemController::IsDropHilited()
{
return IsState(TVIS_DROPHILITED);
}
BOOL ItemController::IsBold()
{
return IsState(TVIS_BOLD);
}
BOOL ItemController::IsExpanded()
{
return IsState(TVIS_EXPANDED);
}
BOOL ItemController::IsExpandedOnce()
{
return IsState(TVIS_EXPANDEDONCE);
}
BOOL ItemController::IsExpandPartial()
{
return IsState(TVIS_EXPANDPARTIAL);
}
BOOL ItemController::IsState(UINT nState)
{
return (BOOL)GetState(nState);
}
UINT ItemController::GetOverlayImage() const
{
CTreeCtrl *pTreeCtrl = m_pImpl->pTheTreeCtrlr->GetTreeCtrl();
Utils::Ctrl::TVItem tvi;
tvi.mask = TVIF_STATE | TVIF_HANDLE;
tvi.hItem = m_pImpl->hti;
tvi.stateMask = TVIS_OVERLAYMASK;
pTreeCtrl->GetItem((TVITEM*)&tvi);
return OVERLAYMASKTOINDEX(tvi.state & TVIS_OVERLAYMASK);
}
UINT ItemController::GetStateImage() const
{
CTreeCtrl *pTreeCtrl = m_pImpl->pTheTreeCtrlr->GetTreeCtrl();
Utils::Ctrl::TVItem tvi;
tvi.mask = TVIF_STATE | TVIF_HANDLE;
tvi.hItem = m_pImpl->hti;
tvi.stateMask = TVIS_STATEIMAGEMASK;
pTreeCtrl->GetItem((TVITEM*)&tvi);
return STATEIMAGEMASKTOINDEX(tvi.state & TVIS_STATEIMAGEMASK);
}
UINT ItemController::GetState(UINT nState) const
{
CTreeCtrl *pTreeCtrl = m_pImpl->pTheTreeCtrlr->GetTreeCtrl();
Utils::Ctrl::TVItem tvi;
tvi.mask = TVIF_STATE | TVIF_HANDLE;
tvi.hItem = m_pImpl->hti;
tvi.stateMask = nState;
pTreeCtrl->GetItem((TVITEM*)&tvi);
return (tvi.state & nState);
}
Utils::Menu::ItemRange ItemController::OnPrepareCtxMenu( CMenu& ctxMenu )
{
Utils::Menu::ItemRange menuItems;
menuItems.nFirst = (int)ctxMenu.GetMenuItemCount()-1;
menuItems.nLast = menuItems.nFirst;
if (CanEdit() || CanDelete())
{
if (Utils::Menu::InsertSeparator(ctxMenu, menuItems.nLast))
{
menuItems.nLast++;
}
CTreeCtrl* pTree = m_pImpl->pTheTreeCtrlr->GetTreeCtrl();
DWORD dwStyle = pTree->GetStyle();
bool bCanEdit = ((dwStyle & TVS_EDITLABELS) == TVS_EDITLABELS) && CanEdit();
if (bCanEdit)
{
(void)ctxMenu.InsertMenu(++menuItems.nLast, MF_BYPOSITION, ID_SBJCORE_CTX_RENAME, _T("Rena&me"));
}
if (CanDelete())
{
(void)ctxMenu.InsertMenu(++menuItems.nLast, MF_BYPOSITION, ID_SBJCORE_CTX_DELETE, _T("&Delete\t Del"));
}
}
return menuItems;
}
}
}
}
//*** Modification History ***
// $Log: /SbjDev/SbjCore/TreeItemController.cpp $
//
// 6 11/12/08 2:22p Steve
// Finished Generalization of Model v2.0.1
//
// 5 10/14/08 1:12p Steve
// Implemented Deletes
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
Real name is Steve Johnson. Programming since 1979. Started on a Heathkit Micro with a DEC LSI-11 and UCSD Pascal. Moved to PCs & DOS as soon as Turbo Pascal became available. Did some Assembly, ISR, TSR etc. All this while working for a Manufacturing Co. for 8 years. Had my own solo Co. doing barcode labeling software for 4 years (terrible business man, all I wanted to do was code). Since then working for various software companies. Moved to Windows around the time of 3.1 with Borland C then C++. Then on to VC++ and MFC, and just about anything I could get my hands on or had to learn for my job, and been at it ever since. Of course recently I've been playing with .NET, ASP, C#, WPF etc.