2025-11-27 16:46:48 +09:00

1170 lines
22 KiB
C++

// ==========================================================================
// COXTreeSubItem & COXTreeItem
// ==========================================================================
// Version: 9.3
// This software along with its related components, documentation and files ("The Libraries")
// is © 1994-2007 The Code Project (1612916 Ontario Limited) and use of The Libraries is
// governed by a software license agreement ("Agreement"). Copies of the Agreement are
// available at The Code Project (www.codeproject.com), as part of the package you downloaded
// to obtain this file, or directly from our office. For a copy of the license governing
// this software, you may contact us at legalaffairs@codeproject.com, or by calling 416-849-8900.
// //////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "OXTreeItem.h"
#include "OXTreeCtrl.h"
#include <malloc.h>
#include "UTBStrOp.h"
#include "UTB64Bit.h"
COXTreeItem::COXTreeItem()
{
m_uEditMode=OXET_EDIT;
pxNext=pxPrev=pxFirstChild=pxParent=NULL;
m_bExpand=FALSE;
m_bExpandedOnce=FALSE;
dwStateEx=XTIS_VISIBLE;
memset(&m_tvi,0,sizeof(m_tvi));
m_tvi.mask = TVIF_HANDLE;
m_tvi.hItem = (HTREEITEM) this;
m_tvi.pszText=NULL;
m_nEllipsisFormat=DT_END_ELLIPSIS;
m_clr=::GetSysColor(COLOR_WINDOWTEXT);
m_clrBackground=::GetSysColor(COLOR_WINDOW);
}
COXTreeItem::~COXTreeItem()
{
Unlink();
DeleteChildren();
for(int i=0;i < m_Items.GetSize();i++)
delete m_Items[i];
if(m_tvi.pszText && m_tvi.pszText != LPSTR_TEXTCALLBACK)
delete [] m_tvi.pszText;
}
// Copy constructor
COXTreeItem& COXTreeItem::operator=( const COXTreeItem& xti )
{
if(this==&xti)
return *this;
if((HFONT)m_font)
m_font.DeleteObject();
if((HFONT)xti.m_font)
{
LOGFONT lf;
COXTreeItem* xtiCopy=(COXTreeItem*)&xti;
VERIFY(xtiCopy->m_font.GetLogFont(&lf));
VERIFY(m_font.CreateFontIndirect(&lf));
}
m_tvi.mask=xti.m_tvi.mask;
m_tvi.hItem=(HTREEITEM)this;
m_tvi.state=xti.m_tvi.state;
m_tvi.stateMask=xti.m_tvi.stateMask;
if(xti.m_tvi.pszText==LPSTR_TEXTCALLBACK)
{
if(m_tvi.pszText && m_tvi.pszText!=LPSTR_TEXTCALLBACK)
delete[] m_tvi.pszText;
m_tvi.pszText=LPSTR_TEXTCALLBACK;
}
else
{
// allocate space for new item text and copy string
size_t len = _tcslen(xti.m_tvi.pszText)+1;
TCHAR* pChar=new TCHAR[len];
UTBStr::tcscpy(pChar, len, xti.m_tvi.pszText);
if(m_tvi.pszText && m_tvi.pszText!=LPSTR_TEXTCALLBACK)
delete[] m_tvi.pszText;
m_tvi.pszText=pChar;
}
m_tvi.cchTextMax=xti.m_tvi.cchTextMax;
m_tvi.iImage=xti.m_tvi.iImage;
m_tvi.iSelectedImage=xti.m_tvi.iSelectedImage;
m_tvi.cChildren=xti.m_tvi.cChildren;
m_tvi.lParam=xti.m_tvi.lParam;
m_clr=xti.m_clr;
m_clrBackground = xti.m_clrBackground;
m_nEllipsisFormat=xti.m_nEllipsisFormat;
dwStateEx=xti.dwStateEx;
m_bExpand=xti.m_bExpand;
m_bExpandedOnce=xti.m_bExpandedOnce;
pxParent=xti.pxParent;
pxNext=xti.pxNext;
pxPrev=xti.pxPrev;
pxFirstChild=xti.pxFirstChild;
m_saTextEx.RemoveAll();
m_saTextEx.Append(xti.m_saTextEx);
m_uEditMode=xti.m_uEditMode;
int nIndex=0;
for(nIndex=0; nIndex<m_Items.GetSize(); nIndex++)
{
COXTreeSubItem* pSubItem=m_Items.GetAt(nIndex);
ASSERT(pSubItem!=NULL);
delete pSubItem;
}
m_Items.RemoveAll();
for(nIndex=0; nIndex<xti.m_Items.GetSize(); nIndex++)
{
COXTreeSubItem* pSubItem=xti.m_Items.GetAt(nIndex);
ASSERT(pSubItem!=NULL);
COXTreeSubItem* pNewSubItem=new COXTreeSubItem;
ASSERT(pNewSubItem!=NULL);
*pNewSubItem=*pSubItem;
m_Items.Add(pNewSubItem);
}
return *this;
}
// Copy constructor
COXTreeSubItem& COXTreeSubItem::operator=( const COXTreeSubItem& xtsi )
{
if(this==&xtsi)
return *this;
sItem=xtsi.sItem;
nCol=xtsi.nCol;
uFlags=xtsi.uFlags;
nImage=xtsi.nImage;
m_nEllipsisFormat=xtsi.m_nEllipsisFormat;
m_uEditMode=xtsi.m_uEditMode;
m_clr=xtsi.m_clr;
m_clrBackground = xtsi.m_clrBackground;
if((HFONT)m_font)
m_font.DeleteObject();
if((HFONT)xtsi.m_font)
{
LOGFONT lf;
COXTreeSubItem* xtsiCopy=(COXTreeSubItem*)&xtsi;
VERIFY(xtsiCopy->m_font.GetLogFont(&lf));
VERIFY(m_font.CreateFontIndirect(&lf));
}
m_saTextEx.RemoveAll();
m_saTextEx.Append(xtsi.m_saTextEx);
return *this;
}
void COXTreeItem::DeleteChildren()
{
COXTreeItem *xti = pxFirstChild;
while(xti)
{
xti->Unlink();
delete xti;
xti = pxFirstChild;
}
}
BOOL COXTreeItem::DeleteSubitem(int nCol)
{
if(nCol<=0 || nCol>=GetSubitemsCount())
return FALSE;
ASSERT(m_Items[nCol-1]!=NULL);
delete m_Items[nCol-1];
for(int nIndex=nCol; nIndex<GetSubitemsCount(); nIndex++)
{
ASSERT(m_Items[nIndex]!=NULL);
m_Items[nIndex]->nCol--;
m_Items[nIndex-1]=m_Items[nIndex];
}
m_Items.RemoveAt(GetSubitemsCount()-1);
return TRUE;
}
COXTreeItem* COXTreeItem::GetLastChild()
{
COXTreeItem *xti=pxFirstChild;
if(!xti)
return NULL;
while(xti->pxNext)
xti = xti->pxNext;
return xti;
}
void COXTreeItem::Unlink()
{
if(pxParent && pxParent->pxFirstChild == this)
{
pxParent->pxFirstChild = pxNext;
}
if(pxPrev)
{
pxPrev->pxNext = pxNext;
}
if(pxNext)
{
pxNext->pxPrev = pxPrev;
}
pxParent = pxPrev= pxNext=NULL;
}
void COXTreeItem::AddChild(COXTreeItem *pNewChild, COXTreeItem *pInsAfter)
{
ASSERT(!pNewChild->pxParent);
ASSERT(!pNewChild->pxNext);
ASSERT(!pNewChild->pxPrev);
pNewChild->pxParent=this;
if(!pxFirstChild)
{
pxFirstChild = pNewChild;
pNewChild->pxPrev = pNewChild->pxNext = NULL;
return;
}
if(pInsAfter && pInsAfter!=(COXTreeItem*)TVI_LAST)
{
if(pInsAfter == (COXTreeItem*) TVI_FIRST)
{
pNewChild->pxPrev = NULL;
pNewChild->pxNext = pxFirstChild;
if(pxFirstChild)
pxFirstChild->pxPrev = pNewChild;
pxFirstChild = pNewChild;
}
else
{
ASSERT(pInsAfter->pxParent==this);
pNewChild->pxNext=pInsAfter->pxNext;
pInsAfter->pxNext=pNewChild;
pNewChild->pxPrev=pInsAfter;
if(pNewChild->pxNext!=NULL)
pNewChild->pxNext->pxPrev=pNewChild;
}
}
else
{
pNewChild->pxPrev=GetLastChild();
pNewChild->pxNext = NULL;
GetLastChild()->pxNext = pNewChild;
}
}
int COXTreeItem::GetChildOffset(COXTreeItem *pChild,BOOL bCalcHidden)
{
UNREFERENCED_PARAMETER(pChild);
COXTreeItem * pxti = pxFirstChild;
int cnt=0;
while(pxti)
{
if(!pxti->IsHidden() || bCalcHidden)
cnt++;
pxti = pxti->pxNext;
}
ASSERT(cnt);
return cnt;
}
COXTreeItem::COXTreeItem(LPCTSTR lpszItem)
{
m_uEditMode=OXET_EDIT;
pxNext=pxPrev=pxFirstChild=pxParent=NULL;
m_bExpand=FALSE;
m_bExpandedOnce=FALSE;
dwStateEx=XTIS_VISIBLE;
memset(&m_tvi,0,sizeof(m_tvi));
if(lpszItem == LPSTR_TEXTCALLBACK)
m_tvi.pszText = (LPTSTR) lpszItem;
else
{
size_t len = _tcslen(lpszItem)+1;
m_tvi.pszText = new TCHAR[len];
UTBStr::tcscpy(m_tvi.pszText, len, lpszItem);
}
m_tvi.mask = TVIF_HANDLE | TVIF_TEXT;
m_tvi.hItem = (HTREEITEM) this;
m_tvi.iImage=-1;
m_tvi.iSelectedImage=-1;
m_nEllipsisFormat=DT_END_ELLIPSIS;
m_clr=::GetSysColor(COLOR_WINDOWTEXT);
m_clrBackground=::GetSysColor(COLOR_WINDOW);
}
BOOL COXTreeItem::IsHidden() const
{
return !(dwStateEx & XTIS_VISIBLE);
}
void COXTreeItem::RemoveChildrenFromCtrl(COXTreeCtrl *pCtrl)
{
// TRACE(_T("RemoveChildrenFromCtrl\n"));
COXTreeItem *xti=pxFirstChild;
while(xti)
{
int idx = pCtrl->GetItemIndexInternal(xti);
if(idx != -1)
{
xti->RemoveChildrenFromCtrl(pCtrl);
pCtrl->CListCtrl::DeleteItem(idx);
}
xti = xti->pxNext;
}
}
int COXTreeItem::AddChildrenToCtrl(COXTreeCtrl *pCtrl,int startPos)
{
// TRACE(_T("AddChildrenToCtrl\n"));
int pos = startPos;
if(IsHidden() || !IsExpanded())
return pos;
COXTreeItem *xti = pxFirstChild;
while(xti)
{
if(!xti->IsHidden())
{
pCtrl->SetItemAtPos(pos,xti);
pos ++;
pos = xti->AddChildrenToCtrl(pCtrl,pos);
}
xti = xti->pxNext;
}
return pos;
}
int COXTreeItem::GetSubitemsCount() const
{
return PtrToInt(m_Items.GetSize());
}
BOOL COXTreeItem::Expand(UINT nCode,COXTreeCtrl *pCtrl)
{
ASSERT(pCtrl!=NULL);
BOOL bWasVisible=IsVisible();
switch(nCode)
{
case TVE_TOGGLE:
m_bExpand = !m_bExpand;
break;
case TVE_COLLAPSE:
if(!m_bExpand)
{
TRACE(_T("COXTreeItem::Expand: the item is already in collapsed state!\n"));
return TRUE;
}
m_bExpand = FALSE;
break;
case TVE_EXPAND:
if(m_bExpand)
{
TRACE(_T("COXTreeItem::Expand: the item is already in expanded state!\n"));
return TRUE;
}
m_bExpand = TRUE;
break;
case TVE_COLLAPSERESET:
pCtrl->DeleteChildrenItems(this);
m_bExpand=FALSE;
m_bExpandedOnce=FALSE;
m_tvi.cChildren=0;
return TRUE;
default:
TRACE(_T("COXTreeItem::Expand: unexpected case found!\n"));
return FALSE;
}
if(m_bExpand)
m_bExpandedOnce=TRUE;
if(!bWasVisible && !m_bExpand)
return TRUE;
if(!IsVisible() && m_bExpand)
{
COXTreeItem* xtiParent=pxParent;
ASSERT(xtiParent!=NULL && xtiParent!=&pCtrl->m_xtiRoot);
xtiParent->Expand(TVE_EXPAND,pCtrl);
}
else
Exp(pCtrl);
return TRUE;
}
void COXTreeItem::Exp(COXTreeCtrl *pCtrl)
{
COXTreeItem *xti = pxFirstChild;
int pos = pCtrl->GetItemIndexInternal(this) + 1;
ASSERT(pos);
if(m_bExpand)
{
while(xti)
{
if(!xti->IsHidden())
{
pCtrl->SetItemAtPos(pos,xti);
pos ++;
pos = xti->AddChildrenToCtrl(pCtrl,pos);
}
xti=xti->pxNext;
}
}
else
{
while(xti)
{
int idx = pCtrl->GetItemIndexInternal(xti);
if(idx != -1)
{
xti->RemoveChildrenFromCtrl(pCtrl);
pCtrl->CListCtrl::DeleteItem(idx);
}
xti = xti->pxNext;
}
}
}
int COXTreeItem::GetItemLevel() const
{
int nLevel = 0;
COXTreeItem *xti = pxParent;
while(xti)
{
nLevel++;
xti = xti->pxParent;
}
return nLevel;
}
BOOL COXTreeItem::IsLastUnhidden() const
{
COXTreeItem *xti = pxNext;
while(xti)
{
if(!xti->IsHidden())
return FALSE;
xti=xti->pxNext;
}
return TRUE;
}
BOOL COXTreeItem::ItemHasChildren() const
{
return pxFirstChild != NULL;
}
COXTreeSubItem* COXTreeItem::GetSubItem(int nCol) const
{
ASSERT(nCol != -1 && nCol != 0);
for(int i=0;i < m_Items.GetSize();i++)
{
if(m_Items[i]->nCol == nCol)
return m_Items[i];
}
return NULL;
}
int COXTreeItem::GetItemImage(int nCol,BOOL bSelImg) const
{
if(nCol == 0)
return bSelImg ? m_tvi.iImage:m_tvi.iSelectedImage;
for(int i=0;i < m_Items.GetSize();i++)
{
if(m_Items[i]->nCol == nCol)
{
if(m_Items[i]->HasImage())
return m_Items[i]->nImage;
else
break;
}
}
return -1;
}
BOOL COXTreeSubItem::SetFont(CFont *pFont)
{
if(pFont)
{
if((HFONT)m_font!=NULL)
{
m_font.DeleteObject();
}
LOGFONT lf;
BOOL bRet = pFont->GetLogFont(&lf);
if(bRet)
{
bRet=m_font.CreateFontIndirect(&lf);
}
if(bRet)
uFlags |= OX_SUBITEM_FONT;
else
uFlags &= ~OX_SUBITEM_FONT;
return bRet;
}
else
{
uFlags &= ~OX_SUBITEM_FONT;
}
return TRUE;
}
BOOL COXTreeItem::SetSubItem(int nCol,UINT uMask,LPCTSTR lpszText,int nImage,
CFont * pFont,COLORREF clr, COLORREF clrBack)
{
if(nCol == -1 || nCol == 0)
{
ASSERT(FALSE);
return FALSE;
}
COXTreeSubItem *pSubItem = GetSubItem(nCol);
if(!pSubItem)
{
pSubItem = new COXTreeSubItem(nCol);
m_Items.Add(pSubItem);
}
ASSERT(pSubItem);
if(uMask & OX_SUBITEM_IMAGE)
{
pSubItem->nImage = nImage;
pSubItem->uFlags |= OX_SUBITEM_IMAGE;
}
if(uMask & OX_SUBITEM_TEXT)
{
pSubItem->sItem = lpszText;
pSubItem->uFlags |= OX_SUBITEM_TEXT;
}
if(uMask & OX_SUBITEM_FONT)
pSubItem->SetFont(pFont);
if(uMask & OX_SUBITEM_COLOR)
{
pSubItem->m_clr = clr;
pSubItem->uFlags |= OX_SUBITEM_COLOR;
}
if(uMask & OX_SUBITEM_BGCOLOR)
{
pSubItem->m_clrBackground = clrBack;
pSubItem->uFlags |= OX_SUBITEM_BGCOLOR;
}
return TRUE;
}
LPCTSTR COXTreeItem::GetSubItemText(int nCol) const
{
COXTreeSubItem *pSubItem = GetSubItem(nCol);
if(pSubItem)
return pSubItem->sItem;
else
return _T("");
}
int COXTreeItem::GetSubItemImage(int nCol) const
{
COXTreeSubItem *pSubItem = GetSubItem(nCol);
if(pSubItem)
return pSubItem->HasImage() ? pSubItem->nImage:-1;
else
return -1;
}
void COXTreeItem::SetHidden(BOOL bHide)
{
if(bHide)
dwStateEx &= ~XTIS_VISIBLE;
else
dwStateEx |= XTIS_VISIBLE;
}
COXTreeItem* COXTreeItem::GetNextInTree()
{
//get next item in the tree structure
if(pxFirstChild)
return pxFirstChild;
if(pxNext)
return pxNext;
COXTreeItem * xti = pxParent;
while(xti)
{
if(xti->pxNext)
return xti->pxNext;
xti = xti->pxParent;
}
return NULL;
}
COXTreeItem* COXTreeItem::GetPrevInTree()
{
//get prev item in the tree structure
if(pxPrev)
{
COXTreeItem* pItemTemp=pxPrev;
COXTreeItem* pLastChild;
while((pLastChild=pItemTemp->GetLastChild())!=NULL)
pItemTemp=pLastChild;
return pItemTemp;
}
// if there is no prev sibling, return parent
return pxParent;
}
BOOL COXTreeItem::IsVisible() const
{
// check visible
if(IsHidden())
return FALSE;
COXTreeItem *xtiParent = pxParent;
while(xtiParent)
{
if(xtiParent->IsHidden() || !xtiParent->IsExpanded())
return FALSE;
xtiParent=xtiParent->pxParent;
}
// otherwise it is visible
return TRUE;
}
BOOL COXTreeItem::NeedDrawButton() const
{
if(m_tvi.cChildren>0)
return TRUE;
COXTreeItem *xti = pxFirstChild;
while(xti)
{
if(!xti->IsHidden())
return TRUE;
xti = xti->pxNext;
}
return FALSE;
}
BOOL COXTreeItem::HasColor(int nCol) const
{
if(!nCol)
return (BOOL)(dwStateEx & XTIS_HASCOLOR);
COXTreeSubItem *pSubItem = GetSubItem(nCol);
if(!pSubItem)
return FALSE;
return pSubItem->HasColor();
}
BOOL COXTreeItem::HasBackColor(int nCol) const
{
if(!nCol)
return (BOOL)(dwStateEx & XTIS_HASBGCOLOR);
COXTreeSubItem *pSubItem = GetSubItem(nCol);
if(!pSubItem)
return FALSE;
return pSubItem->HasBackColor();
}
void COXTreeItem::SetColor(COLORREF clr)
{
m_clr = clr;
dwStateEx |= XTIS_HASCOLOR;
}
void COXTreeItem::SetBackColor(COLORREF clr)
{
m_clrBackground = clr;
dwStateEx |= XTIS_HASBGCOLOR;
}
void COXTreeSubItem::SetColor(COLORREF clr)
{
m_clr = clr;
uFlags |= OX_SUBITEM_COLOR;
}
void COXTreeSubItem::SetBackColor(COLORREF clr)
{
m_clrBackground = clr;
uFlags |= OX_SUBITEM_BGCOLOR;
}
COLORREF COXTreeItem::GetItemColor(int nCol) const
{
ASSERT(HasColor(nCol));
if(!nCol)
return m_clr;
COXTreeSubItem *pSubItem = GetSubItem(nCol);
if(!pSubItem)
{
ASSERT(FALSE);
return 0;
}
return pSubItem->m_clr;
}
COLORREF COXTreeItem::GetItemBackColor(int nCol) const
{
ASSERT(HasBackColor(nCol));
if(!nCol)
return m_clrBackground;
COXTreeSubItem *pSubItem = GetSubItem(nCol);
if(!pSubItem)
{
ASSERT(FALSE);
return 0;
}
return pSubItem->m_clrBackground;
}
void COXTreeItem::SetDrawEllipsis(UINT nEllipsisFormat, int nCol/*=0*/)
{
ASSERT(nEllipsisFormat==DT_END_ELLIPSIS || nEllipsisFormat==DT_PATH_ELLIPSIS ||
nEllipsisFormat==DT_WORD_ELLIPSIS);
if(nCol==0)
m_nEllipsisFormat = nEllipsisFormat;
else
{
COXTreeSubItem *pSubItem = GetSubItem(nCol);
ASSERT(pSubItem!=NULL);
pSubItem->SetDrawEllipsis(nEllipsisFormat);
}
}
void COXTreeSubItem::SetDrawEllipsis(UINT nEllipsisFormat)
{
ASSERT(nEllipsisFormat==DT_END_ELLIPSIS || nEllipsisFormat==DT_PATH_ELLIPSIS ||
nEllipsisFormat==DT_WORD_ELLIPSIS);
m_nEllipsisFormat = nEllipsisFormat;
}
UINT COXTreeItem::GetDrawEllipsis(int nCol/*=0*/) const
{
if(nCol==0)
return m_nEllipsisFormat;
else
{
COXTreeSubItem *pSubItem = GetSubItem(nCol);
if(pSubItem!=NULL)
return pSubItem->GetDrawEllipsis();
else
return DT_END_ELLIPSIS;
}
}
BOOL COXTreeItem::HasFont(int nCol) const
{
if(!nCol)
return (BOOL)(dwStateEx & XTIS_HASFONT);
COXTreeSubItem *pSubItem = GetSubItem(nCol);
if(!pSubItem)
return FALSE;
return pSubItem->HasFont();
}
BOOL COXTreeItem::SetFont(int nCol, CFont* pFont)
{
if(nCol == 0)
{
if(pFont==NULL)
{
dwStateEx &= ~XTIS_HASFONT;
return TRUE;
}
LOGFONT lf;
if(!pFont->GetLogFont(&lf))
{
return FALSE;
}
if((HFONT)m_font!=NULL)
{
m_font.DeleteObject();
}
if(m_font.CreateFontIndirect(&lf))
{
dwStateEx |= XTIS_HASFONT;
return TRUE;
}
return FALSE;
}
else
{
COXTreeSubItem *pSubItem = GetSubItem(nCol);
if(!pSubItem)
return FALSE;
return pSubItem->SetFont(pFont);
}
}
CFont* COXTreeItem::GetItemFont(int nCol)
{
if(!HasFont(nCol))
return NULL;
if(!nCol)
{
return &m_font;
}
else
{
COXTreeSubItem *pSubItem = GetSubItem(nCol);
if(!pSubItem)
return NULL;
return &(pSubItem->m_font);
}
}
void COXTreeItem::SetDisabled(BOOL bDisable)
{
if(bDisable)
dwStateEx |= XTIS_DISABLED;
else
dwStateEx &= ~XTIS_DISABLED;
}
BOOL COXTreeItem::IsDisabled() const
{
return (dwStateEx & XTIS_DISABLED);
}
BOOL COXTreeItem::SetSubItemText(LPCTSTR lpszText,int nCol)
{
if(nCol <= 0)
{
// column must be > 0
ASSERT(FALSE);
return FALSE;
}
return SetSubItem(nCol,OX_SUBITEM_TEXT,lpszText);
}
void COXTreeItem::SetEditMode(UINT uMode,CStringArray& saTextEx,int nCol)
{
if(nCol == 0)
{
//set main item
switch(uMode)
{
case OXET_EDIT:
case OXET_NOEDIT:
case OXET_COMBO:
case OXET_CALENDAR:
m_uEditMode = uMode;
break;
default:
// Undefined edit mode found!
ASSERT(FALSE);
break;
}
m_saTextEx.RemoveAll();
for(int i=0;i < saTextEx.GetSize();i++)
m_saTextEx.SetAtGrow(i,saTextEx[i]);
}
else
{
COXTreeSubItem *pSubItem = GetSubItem(nCol);
ASSERT(pSubItem);
if(pSubItem)
pSubItem->SetEditMode(uMode,saTextEx);
}
}
void COXTreeSubItem::SetEditMode(UINT uMode,CStringArray& saTextEx)
{
switch(uMode)
{
case OXET_EDIT:
case OXET_NOEDIT:
case OXET_COMBO:
case OXET_CALENDAR:
m_uEditMode = uMode;
break;
default:
// Undefined edit mode found!
ASSERT(FALSE);
break;
}
m_saTextEx.RemoveAll();
for(int i=0;i < saTextEx.GetSize();i++)
m_saTextEx.SetAtGrow(i,saTextEx[i]);
}
UINT COXTreeItem::GetEditMode(int nCol) const
{
if(nCol == 0)
return m_uEditMode;
COXTreeSubItem *pSubItem = GetSubItem(nCol);
ASSERT(pSubItem);
if(pSubItem)
return pSubItem->GetEditMode();
return 0;
}
UINT COXTreeSubItem::GetEditMode() const
{
return m_uEditMode;
}
CStringArray& COXTreeSubItem::GetTextEx()
{
return m_saTextEx;
}
CStringArray& COXTreeItem::GetTextEx(int nCol)
{
if(nCol == 0)
return m_saTextEx;
COXTreeSubItem *pSubItem = GetSubItem(nCol);
ASSERT(pSubItem);
return pSubItem->GetTextEx();
}
void COXTreeItem::SetTextEx(CStringArray& saText,int nCol)
{
if(nCol == 0)
{
m_saTextEx.RemoveAll();
for(int i=0;i < saText.GetSize();i++)
m_saTextEx.SetAtGrow(i,saText[i]);
}
else
{
COXTreeSubItem *pSubItem = GetSubItem(nCol);
ASSERT(pSubItem);
pSubItem->SetTextEx(saText);
}
}
void COXTreeSubItem::SetTextEx(CStringArray& saText)
{
m_saTextEx.RemoveAll();
for(int i=0;i < saText.GetSize();i++)
m_saTextEx.SetAtGrow(i,saText[i]);
}
COXTreeItem* COXTreeItem::FindItemToInsertAfter(LPCTSTR lpszItem,
BOOL bAscending/*=TRUE*/) const
{
ASSERT(this);
CString sItemText=lpszItem;
if(sItemText.IsEmpty())
{
return bAscending ? NULL : (COXTreeItem*)TVI_FIRST;
}
int nKoef=bAscending ? 1 : -1;
COXTreeItem* pInsertAfter=NULL;
COXTreeItem* xti=pxFirstChild;
CString sTextToCompare;
CString sClosest=sItemText;
BOOL bFirstTime=TRUE;
while(xti)
{
if (m_tvi.pszText)
{
sTextToCompare=xti->m_tvi.pszText;
int result=sItemText.Collate(sTextToCompare)*nKoef;
if(result>0)
{
result=sClosest.Collate(sTextToCompare)*nKoef;
if(result<0 || bFirstTime)
{
bFirstTime=FALSE;
pInsertAfter=xti;
sClosest=sTextToCompare;
}
}
}
xti = xti->pxNext;
}
return pInsertAfter==NULL ? (COXTreeItem*)TVI_FIRST : pInsertAfter;
}
UINT COXTreeItem::GetChildrenCount() const
{
UINT result=0;
COXTreeItem* xti=pxFirstChild;
while(xti)
{
result++;
xti = xti->pxNext;
}
return result;
}
BOOL COXTreeItem::SortChildren(int nCol/*=0*/,
BOOL bOnlyChildren/*=TRUE*/,
BOOL bAscending/*=TRUE*/,
PFNTVCOMPARE lpfnCompare/*=NULL*/,
LPARAM lParam/*=NULL*/)
{
if(!ItemHasChildren())
{
return TRUE;
}
BOOL bNotDone = TRUE;
while (bNotDone)
{
bNotDone = FALSE;
COXTreeItem* xti=pxFirstChild;
BOOL bFirstChild=TRUE;
while(xti && xti->pxNext)
{
BOOL bResult;
if(lpfnCompare==NULL)
{
bResult=Compare(xti,nCol,bAscending);
}
else
{
bResult=lpfnCompare(xti->m_tvi.lParam,xti->pxNext->m_tvi.lParam,lParam)*
(bAscending ? 1 : -1)>0 ? TRUE : FALSE;
}
bNotDone|=bResult;
if(bResult)
{
Swap(xti);
if(bFirstChild)
{
pxFirstChild=xti->pxPrev;
}
xti=xti->pxPrev;
}
xti=xti->pxNext;
bFirstChild=FALSE;
}
}
if(!bOnlyChildren)
{
COXTreeItem* xti=pxFirstChild;
while(xti)
{
if(xti->ItemHasChildren())
{
xti->SortChildren(nCol,bOnlyChildren,bAscending,
lpfnCompare,lParam);
}
xti=xti->pxNext;
}
}
return TRUE;
}
BOOL COXTreeItem::Compare(COXTreeItem* xti, int nCol/*=0*/, BOOL bAscending/*=TRUE*/)
{
COXTreeItem* xtiNext=xti->pxNext;
if(xtiNext==NULL || xti->m_tvi.pszText == LPSTR_TEXTCALLBACK || xtiNext->m_tvi.pszText == LPSTR_TEXTCALLBACK)
{
return FALSE;
}
CString sText=nCol==0 ? xti->m_tvi.pszText : xti->GetSubItemText(nCol);
CString sTextToCompare=nCol==0 ? xtiNext->m_tvi.pszText :
xtiNext->GetSubItemText(nCol);
int nKoef=bAscending ? 1 : -1;
return sText.Collate(sTextToCompare)*nKoef>0;
}
void COXTreeItem::Swap(COXTreeItem* xti)
{
COXTreeItem* xtiNext=xti->pxNext;
if(xtiNext==NULL)
{
return;
}
COXTreeItem* xtiTemp=xti->pxPrev;
if(xti->pxPrev)
{
xti->pxPrev->pxNext=xti->pxNext;
}
if(xtiNext->pxNext)
{
xtiNext->pxNext->pxPrev=xti;
}
xti->pxPrev=xtiNext;
xti->pxNext=xtiNext->pxNext;
xtiNext->pxPrev=xtiTemp;
xtiNext->pxNext=xti;
}
COXTreeItem* COXTreeItem::CopyChild(COXTreeItem* pChildToCopy,
COXTreeItem* pInsAfter/*=NULL*/,
BOOL bCopyDescendants/*=TRUE*/)
{
COXTreeItem* pNewChild=new COXTreeItem;
ASSERT(pNewChild!=NULL);
*pNewChild=*pChildToCopy;
pNewChild->pxParent=NULL;
pNewChild->pxNext=NULL;
pNewChild->pxPrev=NULL;
pNewChild->pxFirstChild=NULL;
AddChild(pNewChild,pInsAfter);
if(bCopyDescendants && pChildToCopy->pxFirstChild!=NULL)
{
pNewChild->pxFirstChild=pNewChild->CopyChild(pChildToCopy->pxFirstChild,
(COXTreeItem*)TVI_FIRST,bCopyDescendants);
ASSERT(pNewChild->pxFirstChild!=NULL);
pInsAfter=pNewChild->pxFirstChild;
COXTreeItem* pNextChild=pChildToCopy->pxFirstChild->pxNext;
while(pNextChild!=NULL)
{
pInsAfter=pNewChild->CopyChild(pNextChild,pInsAfter,bCopyDescendants);
ASSERT(pInsAfter!=NULL);
pNextChild=pNextChild->pxNext;
}
}
return pNewChild;
}
BOOL COXTreeItem::IsAnyParentCollapsed()
{
// Walk up the parent tree and return FALSE if a collapsed parent if found
COXTreeItem* pParent = pxParent;
while (pParent != NULL)
{
if (!pParent->IsExpanded())
return TRUE;
pParent = pParent->pxParent;
}
return FALSE;
}