You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

672 lines
12 KiB
C++

// XTPCoreTreeItem.cpp: implementation of the CXTPCoreTreeItem class.
//
// This file is a part of the XTREME CONTROLS MFC class library.
// (c)1998-2012 Codejock Software, All Rights Reserved.
//
// THIS SOURCE FILE IS THE PROPERTY OF CODEJOCK SOFTWARE AND IS NOT TO BE
// RE-DISTRIBUTED BY ANY MEANS WHATSOEVER WITHOUT THE EXPRESSED WRITTEN
// CONSENT OF CODEJOCK SOFTWARE.
//
// THIS SOURCE CODE CAN ONLY BE USED UNDER THE TERMS AND CONDITIONS OUTLINED
// IN THE XTREME TOOLKIT PRO LICENSE AGREEMENT. CODEJOCK SOFTWARE GRANTS TO
// YOU (ONE SOFTWARE DEVELOPER) THE LIMITED RIGHT TO USE THIS SOFTWARE ON A
// SINGLE COMPUTER.
//
// CONTACT INFORMATION:
// support@codejock.com
// http://www.codejock.com
//
/////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "Common/XTPPropExchange.h"
#include "Common/XTPImageManager.h"
#include "Common/XTPMarkupRender.h"
#include "XTPCoreTreeItem.h"
#include "XTPCoreTreeControl.h"
#include "XTPCoreTreePaintManager.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
IMPLEMENT_SERIAL(CXTPCoreTreeItem, CObject, VERSIONABLE_SCHEMA | _XTP_SCHEMA_CURRENT);
//////////////////////////////////////////////////////////////////////
// CXTPCoreTreeItem
CXTPCoreTreeItem::CXTPCoreTreeItem()
{
m_pChildren = NULL;
m_pNextItem = NULL;
m_pPrevItem = NULL;
m_pParentItems = NULL;
m_pControl = NULL;
m_rcItem.SetRectEmpty();
m_bLabel = FALSE;
m_bHasCheckBox = FALSE;
m_bExpanded = FALSE;
m_bEnabled = TRUE;
m_nChecked = 0;
m_nIconId = -1;
m_dwData = 0;
m_dwRef = 1;
m_pMarkupUIElement = NULL;
}
CXTPCoreTreeItem::~CXTPCoreTreeItem()
{
SAFE_DELETE(m_pChildren);
XTPMarkupReleaseElement(m_pMarkupUIElement);
}
void CXTPCoreTreeItem::DoPropExchange(CXTPPropExchange* pPX)
{
PX_String(pPX, _T("Caption"), m_strCaption, _T(""));
PX_Int(pPX, _T("IconIndex"), m_nIconId, -1);
PX_Bool(pPX, _T("Enabled"), m_bEnabled, TRUE);
PX_Bool(pPX, _T("IsLabel"), m_bLabel, FALSE);
PX_Bool(pPX, _T("HasCheckBox"), m_bHasCheckBox, FALSE);
PX_Int(pPX, _T("Checked"), m_nChecked, 0);
ULONGLONG dwData = m_dwData;
PX_UI8(pPX, _T("Data"), dwData, 0);
if (pPX->IsLoading())
{
m_dwData = (DWORD_PTR)dwData;
}
}
DWORD CXTPCoreTreeItem::AddRef()
{
return InterlockedIncrement(&m_dwRef);
}
DWORD CXTPCoreTreeItem::Release()
{
if (m_dwRef == 0)
return 0;
LONG lResult = InterlockedDecrement(&m_dwRef);
if (lResult == 0)
{
delete this;
}
return lResult;
}
void CXTPCoreTreeItem::SetCaption(LPCTSTR lpszCaption)
{
CString strCaption(lpszCaption);
if (m_strCaption != strCaption)
{
m_strCaption = strCaption;
XTPMarkupReleaseElement(m_pMarkupUIElement);
if (m_pControl && m_pControl->GetMarkupContext())
{
m_pMarkupUIElement = XTPMarkupParseText(m_pControl->GetMarkupContext(), lpszCaption);
}
Invalidate();
}
}
CSize CXTPCoreTreeItem::CalcSize(CDC* /*pDC*/, int /*nWidth*/) const
{
int nHeight = m_pControl->GetPaintManager()->GetItemHeight();
return CSize(0, nHeight);
}
void CXTPCoreTreeItem::SetRect(CRect rc)
{
m_rcItem = rc;
}
BOOL CXTPCoreTreeItem::HasChildren() const
{
return m_pChildren && m_pChildren->GetCount() != 0;
}
CXTPCoreTreeItems* CXTPCoreTreeItem::GetChildren() const
{
if (!m_pChildren)
{
m_pChildren = new CXTPCoreTreeItems();
ASSERT(m_pControl);
m_pChildren->m_pControl = m_pControl;
m_pChildren->m_pOwnerItem = (CXTPCoreTreeItem*)this;
}
return m_pChildren;
}
void CXTPCoreTreeItem::Draw(CDC* pDC)
{
m_pControl->GetPaintManager()->DrawItem(pDC, this);
}
void CXTPCoreTreeItem::SetExpanded(BOOL bExpanded)
{
if (m_bExpanded != bExpanded)
{
m_bExpanded = bExpanded;
if (m_pControl && HasChildren())
m_pControl->RecalcLayout();
}
}
void CXTPCoreTreeItem::SetEnabled(BOOL bEnabled)
{
m_bEnabled = bEnabled;
Invalidate();
}
void CXTPCoreTreeItem::Invalidate()
{
if (m_rcItem.IsRectEmpty())
return;
if (m_pControl)
{
CRect rcItem(m_rcItem);
rcItem.OffsetRect(0, -m_pControl->GetScrollOffset());
m_pControl->RedrawControl(rcItem);
}
}
BOOL CXTPCoreTreeItem::IsExpanded() const
{
return m_bExpanded;
}
BOOL CXTPCoreTreeItem::IsSelected() const
{
return m_pControl->GetFocusedItem() == this;
}
CXTPCoreTreeItem* CXTPCoreTreeItem::GetNextSiblingItem() const
{
return m_pNextItem;
}
CXTPCoreTreeItem* CXTPCoreTreeItem::GetPrevSiblingItem() const
{
return m_pPrevItem;
}
CXTPCoreTreeItem* CXTPCoreTreeItem::GetParentItem() const
{
return m_pParentItems->m_pOwnerItem;
}
CXTPCoreTreeItem* CXTPCoreTreeItem::GetFirstChildItem() const
{
if (m_pChildren)
{
return m_pChildren->GetFirstItem();
}
return NULL;
}
CRect CXTPCoreTreeItem::GetRect() const
{
return m_rcItem;
}
CRect CXTPCoreTreeItem::GetScreenRect() const
{
CRect rcItem = m_rcItem;
if (m_pControl) rcItem.OffsetRect(0, -m_pControl->GetScrollOffset());
return rcItem;
}
CXTPImageManagerIcon* CXTPCoreTreeItem::GetImage() const
{
if (m_nIconId == -1)
return NULL;
return m_pControl->GetImageManager()->GetImage(m_nIconId);
}
CRect CXTPCoreTreeItem::GetButtonRect() const
{
CXTPCoreTreePaintManager* pPaintManager = m_pControl->GetPaintManager();
if (!pPaintManager->m_bShowButtons)
{
return CRect(0, 0, 0, 0);
}
CRect rc(m_rcItem);
rc.right = rc.left + pPaintManager->GetItemHeight();
return rc;
}
CRect CXTPCoreTreeItem::GetCheckboxRect() const
{
if (!IsCheckboxVisible())
return CRect(0, 0, 0, 0);
CXTPCoreTreePaintManager* pPaintManager = m_pControl->GetPaintManager();
int nHeight = pPaintManager->GetItemHeight();
CRect rc(m_rcItem);
if (pPaintManager->m_bShowButtons)
{
rc.left += nHeight;
}
rc.right = rc.left + nHeight;
return rc;
}
BOOL CXTPCoreTreeItem::IsParent(CXTPCoreTreeItem* pItem) const
{
while (pItem != NULL)
{
if (pItem == (CXTPCoreTreeItem*)this)
return TRUE;
pItem = pItem->GetParentItem();
}
return FALSE;
}
void CXTPCoreTreeItem::Remove()
{
m_pParentItems->RemoveItem(this);
}
BOOL CXTPCoreTreeItem::PrepareDrag (COleDataSource& srcItem)
{
HGLOBAL hGlobal = CacheGlobalData();
if (!hGlobal)
return FALSE;
srcItem.CacheGlobalData (CXTPCoreTreeControl::GetClipboardFormat(), hGlobal);
return TRUE;
}
HGLOBAL CXTPCoreTreeItem::CacheGlobalData()
{
try
{
CSharedFile sharedFile;
CArchive ar (&sharedFile, CArchive::store);
CRuntimeClass* pClass = GetRuntimeClass ();
ASSERT (pClass != NULL);
ar.WriteClass (pClass);
CXTPPropExchangeArchive px(ar);
DoPropExchange(&px);
ar.Close();
return sharedFile.Detach();
}
catch (COleException* pEx)
{
TRACE(_T("CXTPTaskPanelItem::PrepareDrag. OLE exception: %x\r\n"),
pEx->m_sc);
pEx->Delete ();
}
catch (CArchiveException* pEx)
{
TRACE(_T("CXTPTaskPanelItem::PrepareDrag. Archive exception\r\n"));
pEx->Delete ();
}
return NULL;
}
CXTPCoreTreeItem* CXTPCoreTreeItem::CreateFromOleFile(CFile* pFile)
{
ASSERT (pFile != NULL);
CXTPCoreTreeItem* pItem = NULL;
try
{
CArchive ar (pFile, CArchive::load);
CRuntimeClass* pClass = ar.ReadClass ();
if (pClass != NULL)
{
pItem = (CXTPCoreTreeItem*) pClass->CreateObject();
if (pItem != NULL)
{
CXTPPropExchangeArchive px(ar);
pItem->DoPropExchange(&px);
}
}
ar.Close ();
return pItem;
}
catch (COleException* pEx)
{
TRACE(_T("CXTPTaskPanelItem::CreateFromOleData. OLE exception: %x\r\n"),
pEx->m_sc);
pEx->Delete ();
}
catch (CArchiveException* pEx)
{
TRACE(_T("CXTPTaskPanelItem::CreateFromOleData. Archive exception\r\n"));
pEx->Delete ();
}
catch (CNotSupportedException *pEx)
{
TRACE(_T("CXTPTaskPanelItem::CreateFromOleData. \"Not Supported\" exception\r\n"));
pEx->Delete ();
}
if (pItem != NULL)
{
delete pItem;
}
return NULL;
}
CXTPCoreTreeItem* CXTPCoreTreeItem::CreateFromOleData(COleDataObject* pDataObject)
{
ASSERT (pDataObject != NULL);
if (!pDataObject)
return NULL;
CFile* pFile = pDataObject->GetFileData(CXTPCoreTreeControl::GetClipboardFormat());
if (!pFile)
return NULL;
CXTPCoreTreeItem* pItem = CreateFromOleFile(pFile);
delete pFile;
return pItem;
}
//////////////////////////////////////////////////////////////////////////
// CXTPCoreTreeItems
CXTPCoreTreeItems::CXTPCoreTreeItems()
{
m_pFirstItem = NULL;
m_pLastItem = NULL;
m_nCount = 0;
m_pControl = NULL;
m_pOwnerItem = NULL;
}
CXTPCoreTreeItems::~CXTPCoreTreeItems()
{
m_pControl = NULL;
RemoveAll();
}
void CXTPCoreTreeItems::RemoveAll()
{
for (CXTPCoreTreeItem* pItem = m_pFirstItem; pItem != NULL;)
{
CXTPCoreTreeItem* pNextItem = pItem->m_pNextItem;
if (m_pControl)
{
m_pControl->OnItemRemoved(pItem);
}
pItem->m_pControl = NULL;
pItem->m_pParentItems = NULL;
SAFE_RELEASE(pItem);
pItem = pNextItem;
}
m_pFirstItem = m_pLastItem = NULL;
m_nCount = 0;
if (m_pControl)
{
m_pControl->RecalcLayout();
}
}
void CXTPCoreTreeItems::RemoveItem(CXTPCoreTreeItem* pItem)
{
if (!pItem || pItem->m_pParentItems != this)
return;
if (pItem->m_pPrevItem)
{
pItem->m_pPrevItem->m_pNextItem = pItem->m_pNextItem;
}
if (pItem->m_pNextItem)
{
pItem->m_pNextItem->m_pPrevItem = pItem->m_pPrevItem;
}
if (m_pLastItem == pItem)
{
m_pLastItem = pItem->m_pPrevItem;
}
if (m_pFirstItem == pItem)
{
m_pFirstItem = pItem->m_pNextItem;
}
m_nCount--;
if (m_pControl)
{
m_pControl->OnItemRemoved(pItem);
}
pItem->m_pControl = NULL;
pItem->m_pParentItems = NULL;
SAFE_RELEASE(pItem);
if (m_pControl)
{
m_pControl->RecalcLayout();
}
}
CXTPCoreTreeItem* CXTPCoreTreeItems::AddItem(LPCTSTR lpszCaption)
{
CXTPCoreTreeItem* pItem = new CXTPCoreTreeItem();
AddItemAfter(pItem, m_pLastItem);
pItem->SetCaption(lpszCaption);
return pItem;
}
CXTPCoreTreeItem* CXTPCoreTreeItems::AddItemAfter(CXTPCoreTreeItem* pItem, CXTPCoreTreeItem* pPrevItem)
{
if (!pItem)
return NULL;
ASSERT(pItem->m_pParentItems == NULL);
if (pPrevItem == NULL)
pPrevItem = m_pLastItem;
CXTPCoreTreeItem* pNextItem = pPrevItem ? pPrevItem->m_pNextItem : NULL;
if (pPrevItem)
{
pPrevItem->m_pNextItem = pItem;
}
if (pNextItem)
{
pNextItem->m_pPrevItem = pItem;
}
pItem->m_pPrevItem = pPrevItem;
pItem->m_pNextItem = pNextItem;
if (m_pLastItem == pPrevItem)
{
m_pLastItem = pItem;
}
if (m_pFirstItem == NULL)
{
m_pFirstItem = pItem;
}
ASSERT(m_pControl);
pItem->m_pControl = m_pControl;
pItem->m_pParentItems = this;
m_nCount++;
m_pControl->RecalcLayout();
return pItem;
}
CXTPCoreTreeItem* CXTPCoreTreeItems::AddItemBefore(CXTPCoreTreeItem* pItem, CXTPCoreTreeItem* pNextItem)
{
if (!pItem)
return NULL;
ASSERT(pItem->m_pParentItems == NULL);
if (pNextItem == NULL)
pNextItem = m_pFirstItem;
CXTPCoreTreeItem* pPrevItem = pNextItem ? pNextItem->m_pPrevItem : NULL;
if (pPrevItem)
{
pPrevItem->m_pNextItem = pItem;
}
if (pNextItem)
{
pNextItem->m_pPrevItem = pItem;
}
pItem->m_pPrevItem = pPrevItem;
pItem->m_pNextItem = pNextItem;
if (m_pLastItem == NULL)
{
m_pLastItem = pItem;
}
if (m_pFirstItem == pNextItem)
{
m_pFirstItem = pItem;
}
ASSERT(m_pControl);
pItem->m_pControl = m_pControl;
pItem->m_pParentItems = this;
m_nCount++;
m_pControl->RecalcLayout();
return pItem;
}
void CXTPCoreTreeItems::MoveItemAfter(CXTPCoreTreeItem* pItem, CXTPCoreTreeItem* pPrevItem)
{
ASSERT(pItem->GetParentItems());
pItem->AddRef();
pItem->Remove();
AddItemAfter(pItem, pPrevItem);
}
void CXTPCoreTreeItems::MoveItemBefore(CXTPCoreTreeItem* pItem, CXTPCoreTreeItem* pPrevItem)
{
ASSERT(pItem->GetParentItems());
pItem->AddRef();
pItem->Remove();
AddItemBefore(pItem, pPrevItem);
}
POSITION CXTPCoreTreeItems::GetHeadPosition() const
{
return (POSITION)m_pFirstItem;
}
CXTPCoreTreeItem* CXTPCoreTreeItems::GetNext(POSITION& rPosition) const
{
CXTPCoreTreeItem* pItem = (CXTPCoreTreeItem*)rPosition;
rPosition = (POSITION)pItem->m_pNextItem;
return pItem;
}
CXTPCoreTreeItem* CXTPCoreTreeItems::GetNextItem(const CXTPCoreTreeItem* pItem) const
{
if (!pItem)
return NULL;
return pItem->m_pNextItem;
}
CXTPCoreTreeItem* CXTPCoreTreeItems::GetPrevItem(const CXTPCoreTreeItem* pItem) const
{
if (!pItem)
return NULL;
return pItem->m_pPrevItem;
}