Files
wxWidgets/src/os2/treectrl.cpp
Włodzimierz Skiba a6fb8636e5 Old API deprecated. Source cleaning.
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@31319 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
2005-01-11 21:17:16 +00:00

2141 lines
67 KiB
C++

/////////////////////////////////////////////////////////////////////////////
// Name: src/msw/treectrl.cpp
// Purpose: wxTreeCtrl
// Author: Julian Smart
// Modified by: Vadim Zeitlin to be less MSW-specific on 10.10.98
// Created: 1997
// RCS-ID: $Id$
// Copyright: (c) Julian Smart
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
// ============================================================================
// declarations
// ============================================================================
// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------
#ifdef __GNUG__
#pragma implementation "treectrl.h"
#endif
// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#if wxUSE_TREECTRL
#include "wx/os2/private.h"
#include "wx/app.h"
#include "wx/log.h"
#include "wx/dynarray.h"
#include "wx/imaglist.h"
#include "wx/settings.h"
#include "wx/os2/treectrl.h"
// a macro to hide the ugliness of nested casts
#define HITEM(item) (HTREEITEM)(WXHTREEITEM)(item)
// the native control doesn't support multiple selections under MSW and we
// have 2 ways to emulate them: either using TVS_CHECKBOXES style and let
// checkboxes be the selection status (checked == selected) or by really
// emulating everything, i.e. intercepting mouse and key events &c. The first
// approach is much easier but doesn't work with comctl32.dll < 4.71 and also
// looks quite ugly.
#define wxUSE_CHECKBOXES_IN_MULTI_SEL_TREE 0
// ----------------------------------------------------------------------------
// private functions
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
// private classes
// ----------------------------------------------------------------------------
typedef struct _MYRECORD
{
RECORDCORE m_vRecord;
ULONG m_ulItemId;
ULONG m_ulUserData;
} MYRECORD, *PMYRECORD;
struct wxTreeViewItem : public MYRECORD
{
wxTreeViewItem(const wxTreeItemId& rItem)
{
m_ulItemId = (ULONG)rItem.m_pItem;
}
}; // end of STRUCT wxTreeViewItem
class wxTreeItemInternalData
{
public:
wxTreeItemInternalData() {}
~wxTreeItemInternalData()
{
if(m_pAttr)
{
delete m_pAttr;
m_pAttr = NULL;
}
}
wxTreeItemAttr* m_pAttr;
WXLPARAM m_lParam; // user data
#if defined(C_CM_COS232)
PMYRECORD m_pMyRecord; // so we can set the m_ulUserData to 0 when this is deleted
#endif
}; // end of CLASS wxTreeItemInternalData
void BumpTreeRecordIds (
HWND hWnd
, PMYRECORD pRecord
)
{
while(pRecord)
{
pRecord = (PMYRECORD)PVOIDFROMMR(::WinSendMsg( hWnd
,CM_QUERYRECORD
,MPFROMP(pRecord)
,MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER)
));
if (pRecord)
pRecord->m_ulItemId++;
}
} // end of BumpTreeRecordIds
PMYRECORD FindOS2TreeRecordByID (
HWND hWnd
, long lItemId
)
{
PMYRECORD pRecord = NULL;
CNRINFO vCnrInfo;
unsigned long i;
if (!::WinSendMsg( hWnd
,CM_QUERYCNRINFO
,MPFROMP(&vCnrInfo)
,(MPARAM)(USHORT)sizeof(CNRINFO)
))
return NULL;
for (i = 0; i < vCnrInfo.cRecords; i++)
{
if (i == 0)
pRecord = (PMYRECORD)PVOIDFROMMR(::WinSendMsg( hWnd
,CM_QUERYRECORD
,MPFROMP(pRecord)
,MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER)
));
else
pRecord = (PMYRECORD)PVOIDFROMMR(::WinSendMsg( hWnd
,CM_QUERYRECORD
,MPFROMP(pRecord)
,MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER)
));
if (!pRecord)
return NULL;
if (pRecord->m_ulItemId == (ULONG)lItemId)
break;
}
return pRecord;
} // end of FindOS2ListRecordByID
class wxTreeTraversal
{
public:
wxTreeTraversal(const wxTreeCtrl* pTree)
{
m_pTree = pTree;
}
//
// Do traverse the tree: visit all items (recursively by default) under the
// given one; return true if all items were traversed or false if the
// traversal was aborted because OnVisit returned false
//
bool DoTraverse( const wxTreeItemId& rRoot
,bool bRecursively = true
);
//
// Override this function to do whatever is needed for each item, return
// false to stop traversing
//
virtual bool OnVisit(const wxTreeItemId& rItem) = 0;
protected:
const wxTreeCtrl* GetTree(void) const { return m_pTree; }
private:
bool Traverse( const wxTreeItemId& rRoot
,bool bRecursively
);
const wxTreeCtrl* m_pTree;
DECLARE_NO_COPY_CLASS(wxTreeTraversal)
}; // end of CLASS wxTreeTraversal
//
// Internal class for getting the selected items
//
class TraverseSelections : public wxTreeTraversal
{
public:
TraverseSelections( const wxTreeCtrl* pTree
,wxArrayTreeItemIds& raSelections
)
: wxTreeTraversal(pTree)
, m_aSelections(raSelections)
{
m_aSelections.Empty();
DoTraverse(pTree->GetRootItem());
}
virtual bool OnVisit(const wxTreeItemId& rItem)
{
//
// Can't visit a virtual node.
//
if ((GetTree()->GetRootItem() == rItem) && (GetTree()->GetWindowStyle() & wxTR_HIDE_ROOT))
{
return true;
}
PMYRECORD pRecord = FindOS2TreeRecordByID( GetTree()->GetHWND()
,rItem.m_pItem
);
if (pRecord->m_vRecord.flRecordAttr & CRA_SELECTED)
{
m_aSelections.Add(rItem);
}
return true;
}
size_t GetCount(void) const { return m_aSelections.GetCount(); }
private:
wxArrayTreeItemIds& m_aSelections;
}; // end of CLASS TraverseSelections
//
// Internal class for counting tree items
//
class TraverseCounter : public wxTreeTraversal
{
public:
TraverseCounter( const wxTreeCtrl* pTree
,const wxTreeItemId& rRoot
,bool bRecursively
)
: wxTreeTraversal(pTree)
{
m_nCount = 0;
DoTraverse(rRoot, bRecursively);
}
virtual bool OnVisit(const wxTreeItemId& WXUNUSED(rItem))
{
m_nCount++;
return true;
}
size_t GetCount(void) const { return m_nCount; }
private:
size_t m_nCount;
}; // end of CLASS TraverseCounter
// ----------------------------------------------------------------------------
// wxWin macros
// ----------------------------------------------------------------------------
IMPLEMENT_DYNAMIC_CLASS(wxTreeCtrl, wxControl)
// ----------------------------------------------------------------------------
// constants
// ----------------------------------------------------------------------------
// indices in gs_expandEvents table below
enum
{
IDX_COLLAPSE,
IDX_EXPAND,
IDX_WHAT_MAX
};
enum
{
IDX_DONE,
IDX_DOING,
IDX_HOW_MAX
};
// handy table for sending events - it has to be initialized during run-time
// now so can't be const any more
static /* const */ wxEventType gs_expandEvents[IDX_WHAT_MAX][IDX_HOW_MAX];
/*
but logically it's a const table with the following entries:
=
{
{ wxEVT_COMMAND_TREE_ITEM_COLLAPSED, wxEVT_COMMAND_TREE_ITEM_COLLAPSING },
{ wxEVT_COMMAND_TREE_ITEM_EXPANDED, wxEVT_COMMAND_TREE_ITEM_EXPANDING }
};
*/
// ============================================================================
// implementation
// ============================================================================
// ----------------------------------------------------------------------------
// tree traversal
// ----------------------------------------------------------------------------
bool wxTreeTraversal::DoTraverse (
const wxTreeItemId& rRoot
, bool bRecursively
)
{
if (!OnVisit(rRoot))
return false;
return Traverse( rRoot
,bRecursively
);
} // end of wxTreeTraversal::DoTraverse
bool wxTreeTraversal::Traverse (
const wxTreeItemId& rRoot
, bool bRecursively
)
{
long lCookie;
wxTreeItemId vChild = m_pTree->GetFirstChild( rRoot
,lCookie
);
while (vChild.IsOk())
{
//
// Depth first traversal
//
if (bRecursively && !Traverse(vChild, true))
return false;
if (!OnVisit(vChild))
return false;
vChild = m_pTree->GetNextChild( rRoot
,lCookie
);
}
return true;
} // end of wxTreeTraversal::Traverse
// ----------------------------------------------------------------------------
// construction and destruction
// ----------------------------------------------------------------------------
void wxTreeCtrl::Init ()
{
m_pImageListNormal = NULL;
m_pImageListState = NULL;
m_bOwnsImageListNormal = false;
m_bOwnsImageListState = false;
m_bHasAnyAttr = false;
m_pDragImage = NULL;
//
// Initialize the global array of events now as it can't be done statically
// with the wxEVT_XXX values being allocated during run-time only
//
gs_expandEvents[IDX_COLLAPSE][IDX_DONE] = wxEVT_COMMAND_TREE_ITEM_COLLAPSED;
gs_expandEvents[IDX_COLLAPSE][IDX_DOING] = wxEVT_COMMAND_TREE_ITEM_COLLAPSING;
gs_expandEvents[IDX_EXPAND][IDX_DONE] = wxEVT_COMMAND_TREE_ITEM_EXPANDED;
gs_expandEvents[IDX_EXPAND][IDX_DOING] = wxEVT_COMMAND_TREE_ITEM_EXPANDING;
} // end of wxTreeCtrl::Init
bool wxTreeCtrl::Create (
wxWindow* pParent
, wxWindowID vId
, const wxPoint& rPos
, const wxSize& rSize
, long lStyle
, const wxValidator& rValidator
, const wxString& rsName
)
{
CNRINFO vCnrInfo;
Init();
if (!CreateControl( pParent
,vId
,rPos
,rSize
,lStyle
,rValidator
,rsName
))
return false;
DWORD dwStyle = WS_VISIBLE | WS_TABSTOP;
if (m_windowStyle & wxCLIP_SIBLINGS)
dwStyle |= WS_CLIPSIBLINGS;
// Create the tree control.
if (!OS2CreateControl( "CONTAINER"
,dwStyle
))
return false;
//
// Now set the display attributes to show a TREE/ICON view of the
// OS/2 Container
//
if (!::WinSendMsg( GetHWND()
,CM_QUERYCNRINFO
,MPFROMP(&vCnrInfo)
,(MPARAM)(USHORT)sizeof(CNRINFO)
))
vCnrInfo.flWindowAttr = CV_TREE|CV_ICON;
vCnrInfo.flWindowAttr |= CA_DRAWBITMAP;
if (m_windowStyle & wxTR_NO_LINES)
vCnrInfo.flWindowAttr |= CA_TREELINE;
::WinSendMsg( GetHWND()
,CM_SETCNRINFO
,MPFROMP(&vCnrInfo)
,(MPARAM)CMA_FLWINDOWATTR
);
SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
SetForegroundColour(wxWindow::GetParent()->GetForegroundColour());
SetFont(*wxSMALL_FONT);
SetXComp(0);
SetYComp(0);
SetSize( rPos.x
,rPos.y
,rSize.x
,rSize.y
);
return true;
} // end of wxTreeCtrl::Create
wxTreeCtrl::~wxTreeCtrl ()
{
//
// Delete any attributes
//
if (m_bHasAnyAttr)
{
for (wxNode* pNode = m_vAttrs.Next(); pNode; pNode = m_vAttrs.Next())
{
delete (wxTreeItemAttr *)pNode->Data();
}
m_bHasAnyAttr = false;
}
DeleteTextCtrl();
//
// Delete user data to prevent memory leaks
// also deletes hidden root node storage.
//
DeleteAllItems();
if (m_bOwnsImageListNormal)
delete m_pImageListNormal;
if (m_bOwnsImageListState)
delete m_pImageListState;
} // end of wxTreeCtrl::~wxTreeCtrl
// ----------------------------------------------------------------------------
// accessors
// ----------------------------------------------------------------------------
//
// simple wrappers which add error checking in debug mode. These methods
// assume the items are properly filled out already. If not, you get errors
//
bool wxTreeCtrl::DoGetItem (
wxTreeViewItem* pTvItem
) const
{
PMYRECORD pRecord = FindOS2TreeRecordByID( GetHWND()
,pTvItem->m_ulItemId
);
if (!pRecord)
{
wxLogLastError(wxT("Item not obtained"));
return false;
}
return true;
} // end of wxTreeCtrl::DoGetItem
void wxTreeCtrl::DoSetItem (
wxTreeViewItem* pTvItem
)
{
//
// Just invalidate the record to redisplay it
//
if (!::WinSendMsg( GetHWND()
,CM_INVALIDATERECORD
,MPFROMP(pTvItem)
,MPFROM2SHORT(1, CMA_ERASE | CMA_REPOSITION | CMA_TEXTCHANGED)
));
{
wxLogLastError(wxT("CM_INVALIDATERECORD"));
}
} // end of wxTreeCtrl::DoSetItem
size_t wxTreeCtrl::GetCount () const
{
CNRINFO vCnrInfo;
::WinSendMsg( GetHWND()
,CM_QUERYCNRINFO
,MPFROMP(&vCnrInfo)
,(MPARAM)(USHORT)sizeof(CNRINFO)
);
return (size_t)vCnrInfo.cRecords;
} // end of wxTreeCtrl::GetCount
unsigned int wxTreeCtrl::GetIndent () const
{
CNRINFO vCnrInfo;
::WinSendMsg( GetHWND()
,CM_QUERYCNRINFO
,MPFROMP(&vCnrInfo)
,(MPARAM)(USHORT)sizeof(CNRINFO)
);
return (unsigned int)vCnrInfo.cxTreeIndent;
} // end of wxTreeCtrl::GetIndent
void wxTreeCtrl::SetIndent (
unsigned int uIndent
)
{
CNRINFO vCnrInfo;
::WinSendMsg( GetHWND()
,CM_QUERYCNRINFO
,MPFROMP(&vCnrInfo)
,(MPARAM)(USHORT)sizeof(CNRINFO)
);
vCnrInfo.cxTreeIndent = (LONG)uIndent;
::WinSendMsg( GetHWND()
,CM_SETCNRINFO
,MPFROMP(&vCnrInfo)
,(MPARAM)CMA_CXTREEINDENT
);
} // end of wxTreeCtrl::SetIndent
wxImageList* wxTreeCtrl::GetImageList () const
{
return m_pImageListNormal;
} // end of wxTreeCtrl::GetImageList
#if WXWIN_COMPATIBILITY_2_4
wxImageList* wxTreeCtrl::GetImageList(int nVal) const
{
return GetImageList();
}
void wxTreeCtrl::SetImageList(wxImageList* pImageList, int nVal)
{
SetImageList(pImageList);
}
int wxTreeCtrl::GetItemSelectedImage(const wxTreeItemId& rItem) const
{
return GetItemImage(rItem, wxTreeItemIcon_Selected);
}
void wxTreeCtrl::SetItemSelectedImage(const wxTreeItemId& rItem, int nImage)
{
SetItemImage(rItem, nImage, wxTreeItemIcon_Selected);
}
#endif // WXWIN_COMPATIBILITY_2_4
wxImageList* wxTreeCtrl::GetStateImageList () const
{
return m_pImageListNormal;
} // end of wxTreeCtrl::GetStateImageList
//
// The SETS of imagelists really do nothing under OS2 as a RECORDCORE
// struct has the icon imbedded in it that it uses for the icon being
// displayed via the TREEITEMDESC member. Provided for interface
// compatability only
//
void wxTreeCtrl::SetAnyImageList (
wxImageList* WXUNUSED(pImageList)
, int WXUNUSED(nWhich)
)
{
} // end of wxTreeCtrl::SetAnyImageList
void wxTreeCtrl::SetImageList (
wxImageList* WXUNUSED(pImageList)
)
{
if (m_bOwnsImageListNormal)
delete m_pImageListNormal;
m_bOwnsImageListNormal = false;
} // end of wxTreeCtrl::SetImageList
void wxTreeCtrl::SetStateImageList (
wxImageList* WXUNUSED(pImageList)
)
{
if (m_bOwnsImageListState)
delete m_pImageListState;
m_bOwnsImageListState = false;
} // end of wxTreeCtrl::SetStateImageList
void wxTreeCtrl::AssignImageList (
wxImageList* WXUNUSED(pImageList)
)
{
m_bOwnsImageListNormal = true;
} // end of wxTreeCtrl::AssignImageList
void wxTreeCtrl::AssignStateImageList (
wxImageList* WXUNUSED(pImageList)
)
{
m_bOwnsImageListState = true;
} // end of wxTreeCtrl::AssignStateImageList
size_t wxTreeCtrl::GetChildrenCount (
const wxTreeItemId& rItem
, bool bRecursively
) const
{
TraverseCounter vCounter( this
,rItem
,bRecursively
);
return vCounter.GetCount() - 1;
} // end of wxTreeCtrl::GetChildrenCount
// ----------------------------------------------------------------------------
// control colours
// ----------------------------------------------------------------------------
bool wxTreeCtrl::SetBackgroundColour (
const wxColour& rColour
)
{
ULONG ulColor = wxColourToRGB(rColour);
if ( !wxWindowBase::SetBackgroundColour(rColour) )
return false;
::WinSetPresParam( GetHWND()
,PP_BACKGROUNDCOLOR
,sizeof(ULONG)
,&ulColor
);
return true;
} // end of wxTreeCtrl::SetBackgroundColour
bool wxTreeCtrl::SetForegroundColour (
const wxColour& rColour
)
{
ULONG ulColor = wxColourToRGB(rColour);
if (!wxWindowBase::SetForegroundColour(rColour))
return false;
::WinSetPresParam( GetHWND()
,PP_FOREGROUNDCOLOR
,sizeof(ULONG)
,&ulColor
);
return true;
} // end of wxTreeCtrl::SetForegroundColour
// ----------------------------------------------------------------------------
// Item access
// ----------------------------------------------------------------------------
wxString wxTreeCtrl::GetItemText (
const wxTreeItemId& rItem
) const
{
wxChar zBuf[512]; // the size is arbitrary...
wxTreeViewItem vTvItem(rItem);
if (!DoGetItem(&vTvItem))
{
//
// Don't return some garbage which was on stack, but an empty string
//
zBuf[0] = wxT('\0');
}
else
strcpy(zBuf, vTvItem.m_vRecord.pszTree);
return wxString(zBuf);
} // end of wxTreeCtrl::GetItemText
void wxTreeCtrl::SetItemText (
const wxTreeItemId& rItem
, const wxString& rsText
)
{
wxTreeViewItem vTvItem(rItem);
vTvItem.m_vRecord.pszTree = (wxChar *)rsText.c_str(); // conversion is ok
DoSetItem(&vTvItem);
} // end of wxTreeCtrl::SetItemText
//
// These functions under OS/2 PM are not needed. OS/2 containers in tree view
// provide for storing a custom expanded and collapsed icons and selected
// and non selected icons, natively. For instance, by default, a disk display
// will display a tree list of folder icons with "+" icons (collapsed) beside
// those folder which contain child members. Double clicking a folder changes
// the closed folder icon to an open folder icon with hatched selection
// highlighting indicating an ICON view container of the folder is open
// elsewhere on the desktop. So the below is not really needed, but we will
// simply return the appropriate icon requested out of OS/2's native PM
// data structures.
//
int wxTreeCtrl::DoGetItemImageFromData (
const wxTreeItemId& WXUNUSED(rItem)
, wxTreeItemIcon nWhich
) const
{
//
// Image handles stored in CNRINFO.
//
CNRINFO vCnrInfo;
::WinSendMsg( GetHWND()
,CM_QUERYCNRINFO
,MPFROMP(&vCnrInfo)
,(MPARAM)(USHORT)sizeof(CNRINFO)
);
//
// We really only have two to chose from. If not custom (set in CNRINFO
// then return the handle to system bitmap). OS/2 automatically provides
// in_use and selected bitmaps/icons
//
switch(nWhich)
{
case wxTreeItemIcon_Normal:
if (vCnrInfo.hbmCollapsed == NULLHANDLE)
return (int)::WinGetSysBitmap(HWND_DESKTOP, SBMP_TREEPLUS);
return vCnrInfo.hbmCollapsed;
case wxTreeItemIcon_Expanded:
if (vCnrInfo.hbmExpanded == NULLHANDLE)
return (int)::WinGetSysBitmap(HWND_DESKTOP, SBMP_TREEMINUS);
return vCnrInfo.hbmExpanded;
default:
return vCnrInfo.hbmCollapsed;
}
}
void wxTreeCtrl::DoSetItemImageFromData (
const wxTreeItemId& WXUNUSED(rItem)
, int nImage
, wxTreeItemIcon nWhich
) const
{
//
// Image handles stored in CNRINFO.
//
CNRINFO vCnrInfo;
::WinSendMsg( GetHWND()
,CM_QUERYCNRINFO
,MPFROMP(&vCnrInfo)
,(MPARAM)(USHORT)sizeof(CNRINFO)
);
if (nWhich == wxTreeItemIcon_Normal)
vCnrInfo.hbmCollapsed = (HBITMAP)nImage;
if (nWhich == wxTreeItemIcon_Expanded)
vCnrInfo.hbmExpanded = (HBITMAP)nImage;
::WinSendMsg( GetHWND()
,CM_SETCNRINFO
,MPFROMP(&vCnrInfo)
,(MPARAM)CMA_TREEBITMAP
);
} // end of wxTreeCtrl::DoSetItemImageFromData
// Useless for OS/2
void wxTreeCtrl::DoSetItemImages (
const wxTreeItemId& rItem
, int nImage
, int nImageSel
)
{
} // end of wxTreeCtrl::DoSetItemImages
int wxTreeCtrl::GetItemImage (
const wxTreeItemId& rItem
, wxTreeItemIcon nWhich
) const
{
if (HasIndirectData(rItem))
{
return DoGetItemImageFromData( rItem
,nWhich
);
}
CNRINFO vCnrInfo;
::WinSendMsg( GetHWND()
,CM_QUERYCNRINFO
,MPFROMP(&vCnrInfo)
,(MPARAM)(USHORT)sizeof(CNRINFO)
);
switch (nWhich)
{
default:
wxFAIL_MSG( wxT("unknown tree item image type") );
case wxTreeItemIcon_Normal:
if (vCnrInfo.hbmCollapsed == NULLHANDLE)
return (int)::WinGetSysBitmap(HWND_DESKTOP, SBMP_TREEPLUS);
return vCnrInfo.hbmCollapsed;
case wxTreeItemIcon_Expanded:
if (vCnrInfo.hbmExpanded == NULLHANDLE)
return (int)::WinGetSysBitmap(HWND_DESKTOP, SBMP_TREEMINUS);
return vCnrInfo.hbmExpanded;
case wxTreeItemIcon_Selected:
case wxTreeItemIcon_SelectedExpanded:
return -1;
}
}
void wxTreeCtrl::SetItemImage (
const wxTreeItemId& WXUNUSED(rItem)
, int nImage
, wxTreeItemIcon nWhich
)
{
CNRINFO vCnrInfo;
::WinSendMsg( GetHWND()
,CM_QUERYCNRINFO
,MPFROMP(&vCnrInfo)
,(MPARAM)(USHORT)sizeof(CNRINFO)
);
switch (nWhich)
{
case wxTreeItemIcon_Normal:
vCnrInfo.hbmCollapsed = (HBITMAP)nImage;
break;
case wxTreeItemIcon_Expanded:
vCnrInfo.hbmExpanded = (HBITMAP)nImage;
break;
default:
wxFAIL_MSG( wxT("unknown tree item image type") );
}
::WinSendMsg( GetHWND()
,CM_SETCNRINFO
,MPFROMP(&vCnrInfo)
,(MPARAM)CMA_TREEBITMAP
);
} // end of wxTreeCtrl::SetItemImage
wxTreeItemData* wxTreeCtrl::GetItemData (
const wxTreeItemId& rItem
) const
{
wxTreeViewItem vTvItem(rItem);
if (!DoGetItem(&vTvItem))
{
return NULL;
}
return (wxTreeItemData *)vTvItem.m_ulUserData;
} // end of wxTreeCtrl::GetItemData
void wxTreeCtrl::SetItemData (
const wxTreeItemId& rItem
, wxTreeItemData* pData
)
{
//
// first, associate this piece of data with this item
if (pData)
{
pData->SetId(rItem);
}
wxTreeViewItem vTvItem(rItem);
vTvItem.m_ulUserData = (ULONG)pData;
DoSetItem(&vTvItem);
} // end of wxTreeCtrl::SetItemData
// The following two do nothing under OS/2
void wxTreeCtrl::SetIndirectItemData (
const wxTreeItemId& WXUNUSED(rItem)
, wxTreeItemIndirectData* WXUNUSED(pData)
)
{
} // end of wxTreeCtrl::SetIndirectItemData
bool wxTreeCtrl::HasIndirectData (
const wxTreeItemId& WXUNUSED(rItem)
) const
{
return false;
} // end of wxTreeCtrl::HasIndirectData
// Irreleveant under OS/2 --- item either has child records or it doesn't.
void wxTreeCtrl::SetItemHasChildren (
const wxTreeItemId& WXUNUSED(rItem)
, bool WXUNUSED(bHas)
)
{
} // end of wxTreeCtrl::SetItemHasChildren
// Irreleveant under OS/2 --- function of the font in PM
void wxTreeCtrl::SetItemBold (
const wxTreeItemId& WXUNUSED(rItem)
, bool WXUNUSED(bBold)
)
{
} // end of wxTreeCtrl::SetItemBold
void wxTreeCtrl::SetItemDropHighlight (
const wxTreeItemId& rItem
, bool bHighlight
)
{
wxTreeViewItem vTvItem(rItem);
::WinSendMsg( GetHWND()
,CM_SETRECORDEMPHASIS
,MPFROMP(&vTvItem)
,MPFROM2SHORT(bHighlight, CRA_SELECTED)
);
DoSetItem(&vTvItem);
} // end of wxTreeCtrl::SetItemDropHighlight
void wxTreeCtrl::RefreshItem (
const wxTreeItemId& rItem
)
{
wxTreeViewItem vTvItem(rItem);
//
// This just does a record invalidate causing it to be re-displayed
//
DoSetItem(&vTvItem);
} // end of wxTreeCtrl::RefreshItem
wxColour wxTreeCtrl::GetItemTextColour (
const wxTreeItemId& rItem
) const
{
long lId = (long)rItem.m_pItem;
wxTreeItemAttr* pAttr = (wxTreeItemAttr *)m_vAttrs.Get(lId);
if (!pAttr)
{
return wxNullColour;
}
return pAttr->GetTextColour();
} // end of wxTreeCtrl::GetItemTextColour
wxColour wxTreeCtrl::GetItemBackgroundColour (
const wxTreeItemId& rItem
) const
{
long lId = (long)rItem.m_pItem;
wxTreeItemAttr* pAttr = (wxTreeItemAttr *)m_vAttrs.Get(lId);
if (!pAttr)
{
return wxNullColour;
}
return pAttr->GetBackgroundColour();
} // end of wxTreeCtrl::GetItemBackgroundColour
wxFont wxTreeCtrl::GetItemFont (
const wxTreeItemId& rItem
) const
{
long lId = (long)rItem.m_pItem;
wxTreeItemAttr* pAttr = (wxTreeItemAttr *)m_vAttrs.Get(lId);
if (!pAttr)
{
return wxNullFont;
}
return pAttr->GetFont();
} // end of wxTreeCtrl::GetItemFont
void wxTreeCtrl::SetItemTextColour (
const wxTreeItemId& rItem
, const wxColour& rCol
)
{
m_bHasAnyAttr = true;
long lId = (long)rItem.m_pItem;
wxTreeItemAttr* pAttr = (wxTreeItemAttr *)m_vAttrs.Get(lId);
if (!pAttr)
{
pAttr = new wxTreeItemAttr;
m_vAttrs.Put(lId, (wxObject *)pAttr);
}
pAttr->SetTextColour(rCol);
RefreshItem(rItem);
} // end of wxTreeCtrl::SetItemTextColour
void wxTreeCtrl::SetItemBackgroundColour (
const wxTreeItemId& rItem
, const wxColour& rCol
)
{
m_bHasAnyAttr = true;
long lId = (long)rItem.m_pItem;
wxTreeItemAttr* pAttr = (wxTreeItemAttr *)m_vAttrs.Get(lId);
if (!pAttr)
{
pAttr = new wxTreeItemAttr;
m_vAttrs.Put(lId, (wxObject *)pAttr);
}
pAttr->SetBackgroundColour(rCol);
RefreshItem(rItem);
} // end of wxTreeCtrl::SetItemBackgroundColour
void wxTreeCtrl::SetItemFont (
const wxTreeItemId& rItem
, const wxFont& rFont
)
{
m_bHasAnyAttr = true;
long lId = (long)rItem.m_pItem;
wxTreeItemAttr* pAttr = (wxTreeItemAttr *)m_vAttrs.Get(lId);
if (!pAttr)
{
pAttr = new wxTreeItemAttr;
m_vAttrs.Put(lId, (wxObject *)pAttr);
}
pAttr->SetFont(rFont);
RefreshItem(rItem);
} // end of wxTreeCtrl::SetItemFont
// ----------------------------------------------------------------------------
// Item status
// ----------------------------------------------------------------------------
bool wxTreeCtrl::IsVisible (
const wxTreeItemId& rItem
) const
{
// Bug in Gnu-Win32 headers, so don't use the macro TreeView_GetItemRect
RECTL vRectRecord;
RECTL vRectContainer;
wxRect vWxRectRecord;
wxRect vWxRectContainer;
PMYRECORD pRecord = FindOS2TreeRecordByID ( GetHWND()
,rItem.m_pItem
);
QUERYRECORDRECT vQuery;
vQuery.cb = sizeof(QUERYRECORDRECT);
vQuery.pRecord = (PRECORDCORE)pRecord;
vQuery.fRightSplitWindow = FALSE;
vQuery.fsExtent = CMA_TREEICON;
::WinSendMsg( GetHWND()
,CM_QUERYVIEWPORTRECT
,MPFROMP(&vRectContainer)
,MPFROM2SHORT(CMA_WINDOW, FALSE)
);
::WinSendMsg( GetHWND()
,CM_QUERYRECORDRECT
,MPFROMP(&vRectRecord)
,MPFROMP(&vQuery)
);
vWxRectRecord.SetLeft(vRectRecord.xLeft);
vWxRectRecord.SetTop(vRectRecord.yTop);
vWxRectRecord.SetRight(vRectRecord.xRight);
vWxRectRecord.SetBottom(vRectRecord.yBottom);
vWxRectContainer.SetLeft(vRectContainer.xLeft);
vWxRectContainer.SetTop(vRectContainer.yTop);
vWxRectContainer.SetRight(vRectContainer.xRight);
vWxRectContainer.SetBottom(vRectContainer.yBottom);
return (vWxRectContainer.Inside(wxPoint(vWxRectRecord.x, vWxRectRecord.y)));
} // end of wxTreeCtrl::IsVisible
bool wxTreeCtrl::ItemHasChildren (
const wxTreeItemId& rItem
) const
{
wxTreeViewItem vTvItem(rItem);
DoGetItem(&vTvItem);
//
// A tree record with children will have one of these attributes
//
return (vTvItem.m_vRecord.flRecordAttr & CRA_EXPANDED ||
vTvItem.m_vRecord.flRecordAttr & CRA_COLLAPSED) != 0;
}
bool wxTreeCtrl::IsExpanded (
const wxTreeItemId& rItem
) const
{
wxTreeViewItem vTvItem(rItem);
DoGetItem(&vTvItem);
return (vTvItem.m_vRecord.flRecordAttr & CRA_EXPANDED) != 0;
} // end of wxTreeCtrl::IsExpanded
bool wxTreeCtrl::IsSelected (
const wxTreeItemId& rItem
) const
{
wxTreeViewItem vTvItem(rItem);
DoGetItem(&vTvItem);
return (vTvItem.m_vRecord.flRecordAttr & CRA_SELECTED) != 0;
} // end of wxTreeCtrl::IsSelected
// Not supported
bool wxTreeCtrl::IsBold (
const wxTreeItemId& rItem
) const
{
return false;
} // end of wxTreeCtrl::IsBold
// ----------------------------------------------------------------------------
// navigation
// ----------------------------------------------------------------------------
wxTreeItemId wxTreeCtrl::GetRootItem () const
{
PMYRECORD pRecord = NULL;
pRecord = (PMYRECORD)PVOIDFROMMR(::WinSendMsg( GetHWND()
,CM_QUERYRECORD
,MPFROMP(pRecord)
,MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER)
));
if (!pRecord)
return wxTreeItemId(-1L);
return wxTreeItemId((long)pRecord->m_ulItemId);
} // end of wxTreeCtrl::GetRootItem
wxTreeItemId wxTreeCtrl::GetSelection () const
{
wxCHECK_MSG( !(m_windowStyle & wxTR_MULTIPLE), (long)(WXHTREEITEM)0,
wxT("this only works with single selection controls") );
PMYRECORD pRecord = NULL;
pRecord = (PMYRECORD)PVOIDFROMMR(::WinSendMsg( GetHWND()
,CM_QUERYRECORDEMPHASIS
,MPARAM(CMA_FIRST)
,MPARAM(CRA_SELECTED)
));
if (!pRecord)
return wxTreeItemId(-1L);
return wxTreeItemId((long)pRecord->m_ulItemId);
} // end of wxTreeCtrl::GetSelection
wxTreeItemId wxTreeCtrl::GetItemParent (
const wxTreeItemId& rItem
) const
{
PMYRECORD pRecord = FindOS2TreeRecordByID ( GetHWND()
,rItem.m_pItem
);
if (!pRecord)
return wxTreeItemId(-1L);
pRecord = (PMYRECORD)PVOIDFROMMR(::WinSendMsg( GetHWND()
,CM_QUERYRECORD
,MPFROMP(pRecord)
,MPFROM2SHORT(CMA_PARENT, CMA_ITEMORDER)
));
if (!pRecord)
return wxTreeItemId(-1L);
return wxTreeItemId((long)pRecord->m_ulItemId);
} // end of wxTreeCtrl::GetItemParent
wxTreeItemId wxTreeCtrl::GetFirstChild (
const wxTreeItemId& rItem
, long& rCookie
) const
{
PMYRECORD pRecord = FindOS2TreeRecordByID ( GetHWND()
,rItem.m_pItem
);
if (!pRecord)
return wxTreeItemId(-1L);
pRecord = (PMYRECORD)PVOIDFROMMR(::WinSendMsg( GetHWND()
,CM_QUERYRECORD
,MPFROMP(pRecord)
,MPFROM2SHORT(CMA_FIRSTCHILD, CMA_ITEMORDER)
));
if (!pRecord)
return wxTreeItemId(-1L);
//
// Remember the last child returned in 'cookie'
//
rCookie = (long)pRecord->m_ulItemId;
return wxTreeItemId(rCookie);
} // end of wxTreeCtrl::GetFirstChild
wxTreeItemId wxTreeCtrl::GetNextChild (
const wxTreeItemId& WXUNUSED(rItem)
, long& rCookie
) const
{
PMYRECORD pRecord = FindOS2TreeRecordByID ( GetHWND()
,rCookie
);
if (!pRecord)
return wxTreeItemId(-1L);
pRecord = (PMYRECORD)PVOIDFROMMR(::WinSendMsg( GetHWND()
,CM_QUERYRECORD
,MPFROMP(pRecord)
,MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER)
));
if (!pRecord)
return wxTreeItemId(-1L);
rCookie = (long)pRecord->m_ulItemId;
return wxTreeItemId(rCookie);
} // end of wxTreeCtrl::GetNextChild
wxTreeItemId wxTreeCtrl::GetLastChild (
const wxTreeItemId& rItem
) const
{
PMYRECORD pRecord = FindOS2TreeRecordByID ( GetHWND()
,rItem.m_pItem
);
if (!pRecord)
return wxTreeItemId(-1L);
pRecord = (PMYRECORD)PVOIDFROMMR(::WinSendMsg( GetHWND()
,CM_QUERYRECORD
,MPFROMP(pRecord)
,MPFROM2SHORT(CMA_LASTCHILD, CMA_ITEMORDER)
));
if (!pRecord)
return wxTreeItemId(-1L);
return wxTreeItemId((long)pRecord->m_ulItemId);
} // end of wxTreeCtrl::GetLastChild
wxTreeItemId wxTreeCtrl::GetNextSibling (
const wxTreeItemId& rItem
) const
{
PMYRECORD pRecord = FindOS2TreeRecordByID ( GetHWND()
,rItem.m_pItem
);
if (!pRecord)
return wxTreeItemId(-1L);
pRecord = (PMYRECORD)PVOIDFROMMR(::WinSendMsg( GetHWND()
,CM_QUERYRECORD
,MPFROMP(pRecord)
,MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER)
));
if (!pRecord)
return wxTreeItemId(-1L);
return wxTreeItemId((long)pRecord->m_ulItemId);
} // end of wxTreeCtrl::GetNextSibling
wxTreeItemId wxTreeCtrl::GetPrevSibling (
const wxTreeItemId& rItem
) const
{
PMYRECORD pRecord = FindOS2TreeRecordByID ( GetHWND()
,rItem.m_pItem
);
if (!pRecord)
return wxTreeItemId(-1L);
pRecord = (PMYRECORD)PVOIDFROMMR(::WinSendMsg( GetHWND()
,CM_QUERYRECORD
,MPFROMP(pRecord)
,MPFROM2SHORT(CMA_PREV, CMA_ITEMORDER)
));
if (!pRecord)
return wxTreeItemId(-1L);
return wxTreeItemId((long)pRecord->m_ulItemId);
} // end of wxTreeCtrl::GetPrevSibling
wxTreeItemId wxTreeCtrl::GetFirstVisibleItem () const
{
PMYRECORD pRecord = (PMYRECORD)PVOIDFROMMR(::WinSendMsg( GetHWND()
,CM_QUERYRECORD
,MPFROMP(pRecord)
,MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER)
));
if (!pRecord)
return wxTreeItemId(-1L);
if (IsVisible(wxTreeItemId((long)pRecord->m_ulItemId)))
return wxTreeItemId((long)pRecord->m_ulItemId);
while(pRecord)
{
pRecord = (PMYRECORD)PVOIDFROMMR(::WinSendMsg( GetHWND()
,CM_QUERYRECORD
,MPFROMP(pRecord)
,MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER)
));
if (!pRecord)
return wxTreeItemId(-1L);
if (IsVisible(wxTreeItemId((long)pRecord->m_ulItemId)))
return wxTreeItemId((long)pRecord->m_ulItemId);
}
return wxTreeItemId(-1L);
} // end of wxTreeCtrl::GetFirstVisibleItem
wxTreeItemId wxTreeCtrl::GetNextVisible (
const wxTreeItemId& rItem
) const
{
wxASSERT_MSG(IsVisible(rItem), wxT("The item you call GetNextVisible() for must be visible itself!"));
PMYRECORD pRecord = FindOS2TreeRecordByID ( GetHWND()
,rItem.m_pItem
);
if (!pRecord)
return wxTreeItemId(-1L);
while(pRecord)
{
pRecord = (PMYRECORD)PVOIDFROMMR(::WinSendMsg( GetHWND()
,CM_QUERYRECORD
,MPFROMP(pRecord)
,MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER)
));
if (!pRecord)
return wxTreeItemId(-1L);
if (IsVisible(wxTreeItemId((long)pRecord->m_ulItemId)))
return wxTreeItemId((long)pRecord->m_ulItemId);
}
return wxTreeItemId(-1L);
} // end of wxTreeCtrl::GetNextVisible
wxTreeItemId wxTreeCtrl::GetPrevVisible (
const wxTreeItemId& rItem
) const
{
wxASSERT_MSG( IsVisible(rItem), wxT("The item you call GetPrevVisible() for must be visible itself!"));
PMYRECORD pRecord = FindOS2TreeRecordByID ( GetHWND()
,rItem.m_pItem
);
if (!pRecord)
return wxTreeItemId(-1L);
while(pRecord)
{
pRecord = (PMYRECORD)PVOIDFROMMR(::WinSendMsg( GetHWND()
,CM_QUERYRECORD
,MPFROMP(pRecord)
,MPFROM2SHORT(CMA_PREV, CMA_ITEMORDER)
));
if (!pRecord)
return wxTreeItemId(-1L);
if (IsVisible(wxTreeItemId((long)pRecord->m_ulItemId)))
return wxTreeItemId((long)pRecord->m_ulItemId);
}
return wxTreeItemId(-1L);
} // end of wxTreeCtrl::GetPrevVisible
// ----------------------------------------------------------------------------
// multiple selections emulation -- under OS/2 checked tree items is not
// supported, but multisel is. So we'll just check for selections here.
// ----------------------------------------------------------------------------
bool wxTreeCtrl::IsItemChecked (
const wxTreeItemId& rItem
) const
{
wxTreeViewItem vTvItem(rItem);
DoGetItem(&vTvItem);
return (vTvItem.m_vRecord.flRecordAttr & CRA_SELECTED);
} // end of wxTreeCtrl::IsItemChecked
void wxTreeCtrl::SetItemCheck (
const wxTreeItemId& rItem
, bool bCheck
)
{
wxTreeViewItem vTvItem(rItem);
DoGetItem(&vTvItem);
::WinSendMsg( GetHWND()
,CM_SETRECORDEMPHASIS
,MPFROMP(&vTvItem)
,MPFROM2SHORT(TRUE, CRA_SELECTED)
);
DoSetItem(&vTvItem);
} // end of wxTreeCtrl::SetItemCheck
size_t wxTreeCtrl::GetSelections (
wxArrayTreeItemIds& raSelections
) const
{
TraverseSelections vSelector( this
,raSelections
);
return vSelector.GetCount();
} // end of wxTreeCtrl::GetSelections
// ----------------------------------------------------------------------------
// Usual operations
// ----------------------------------------------------------------------------
wxTreeItemId wxTreeCtrl::DoInsertItem (
const wxTreeItemId& rParent
, wxTreeItemId vInsertAfter
, const wxString& rsText
, int nImage
, int selectedImage
, wxTreeItemData* pData
)
{
PMYRECORD pRecordAfter = FindOS2TreeRecordByID( GetHWND()
,vInsertAfter.m_pItem
);
PMYRECORD pRecordParent = FindOS2TreeRecordByID( GetHWND()
,rParent.m_pItem
);
PMYRECORD pRecord = (PMYRECORD)::WinSendMsg( GetHWND()
,CM_ALLOCRECORD
,MPFROMLONG(sizeof(MYRECORD) - sizeof(RECORDCORE))
,MPFROMLONG(1)
);
RECORDINSERT vInsert;
vInsert.cb = sizeof(RECORDINSERT);
if (rParent.m_pItem == 0L)
{
if (vInsertAfter.m_pItem == -1)
vInsert.pRecordOrder = (PRECORDCORE)CMA_END;
else
vInsert.pRecordOrder = (PRECORDCORE)CMA_FIRST;
vInsert.pRecordParent = NULL;
}
else
{
if (vInsertAfter.m_pItem == 0)
vInsert.pRecordOrder = (PRECORDCORE)CMA_FIRST;
else if (vInsertAfter.m_pItem == -1)
vInsert.pRecordOrder = (PRECORDCORE)CMA_END;
else
vInsert.pRecordOrder = (PRECORDCORE)pRecordAfter;
vInsert.pRecordParent = (PRECORDCORE)pRecordParent;
}
vInsert.fInvalidateRecord = TRUE;
vInsert.zOrder = CMA_TOP;
vInsert.cRecordsInsert = 1;
pRecord->m_vRecord.pszTree = (wxChar*)rsText.c_str();
pRecord->m_vRecord.hbmBitmap = nImage;
pRecord->m_ulItemId = pRecordAfter->m_ulItemId + 1;
if (pData != NULL)
{
pRecord->m_ulUserData = (ULONG)pData;
}
::WinSendMsg( GetHWND()
,CM_INSERTRECORD
,MPFROMP(pRecord)
,MPFROMP(&vInsert)
);
//
// OS/2 must mannually bump the index's of following records
//
BumpTreeRecordIds( GetHWND()
,pRecord
);
if (pData != NULL)
{
//
// Associate the application tree item with PM tree item handle
//
pData->SetId((long)pRecord->m_ulItemId);
}
return wxTreeItemId((long)pRecord->m_ulItemId);
}
#if WXWIN_COMPATIBILITY_2_4
// for compatibility only
wxTreeItemId wxTreeCtrl::InsertItem (
const wxTreeItemId& rParent
, const wxString& rsText
, int nImage
, int nSelImage
, long lInsertAfter
)
{
return DoInsertItem( rParent
,wxTreeItemId(lInsertAfter)
,rsText
,nImage
,nSelImage
,NULL
);
} // end of wxTreeCtrl::InsertItem
#endif // WXWIN_COMPATIBILITY_2_4
wxTreeItemId wxTreeCtrl::AddRoot (
const wxString& rsText
, int nImage
, int nSelectedImage
, wxTreeItemData* pData)
{
return DoInsertItem( wxTreeItemId((long)0)
,wxTreeItemId((long)-1)
,rsText
,nImage
,nSelectedImage
,pData
);
} // end of wxTreeCtrl::AddRoot
wxTreeItemId wxTreeCtrl::PrependItem (
const wxTreeItemId& rParent
, const wxString& rsText
, int nImage
, int nSelectedImage
, wxTreeItemData* pData
)
{
return DoInsertItem( rParent
,wxTreeItemId((long)0)
,rsText
,nImage
,nSelectedImage
,pData
);
} // end of wxTreeCtrl::PrependItem
wxTreeItemId wxTreeCtrl::InsertItem (
const wxTreeItemId& rParent
, const wxTreeItemId& rIdPrevious
, const wxString& rsText
, int nImage
, int nSelectedImage
, wxTreeItemData* pData
)
{
return DoInsertItem( rParent
,rIdPrevious
,rsText
,nImage
,nSelectedImage
,pData
);
} // end of wxTreeCtrl::InsertItem
wxTreeItemId wxTreeCtrl::InsertItem (
const wxTreeItemId& rParent
, size_t nIndex
, const wxString& rsText
, int nImage
, int nSelectedImage
, wxTreeItemData* pData
)
{
return DoInsertItem( rParent
,wxTreeItemId((long)nIndex)
,rsText
,nImage
,nSelectedImage
,pData
);
} // end of wxTreeCtrl::InsertItem
wxTreeItemId wxTreeCtrl::AppendItem (
const wxTreeItemId& rParent
, const wxString& rsText
, int nImage
, int nSelectedImage
, wxTreeItemData* pData
)
{
return DoInsertItem( rParent
,wxTreeItemId((long)-1)
,rsText
,nImage
,nSelectedImage
,pData
);
} // end of wxTreeCtrl::AppendItem
void wxTreeCtrl::Delete (
const wxTreeItemId& rItem
)
{
//
// OS/2 does not generate DELETEITEM events so do it here
//
wxEventType vEventType = wxEVT_NULL;
wxTreeEvent vEvent( wxEVT_NULL
,m_windowId
);
PMYRECORD pRecord = FindOS2TreeRecordByID( GetHWND()
,rItem.m_pItem
);
vEvent.SetEventObject(this);
::WinSendMsg( GetHWND()
,CM_REMOVERECORD
,MPFROMP(pRecord)
,(MPARAM)(CMA_FREE | CMA_INVALIDATE)
);
vEvent.m_item = rItem.m_pItem;
if (m_bHasAnyAttr)
{
delete (wxTreeItemAttr *)m_vAttrs.Delete((long)rItem.m_pItem);
}
vEvent.SetEventType(vEventType);
GetEventHandler()->ProcessEvent(vEvent);
} // end of wxTreeCtrl::Delete
// delete all children (but don't delete the item itself)
void wxTreeCtrl::DeleteChildren (
const wxTreeItemId& rItem
)
{
long lCookie;
wxArrayLong aChildren;
wxTreeItemId vChild = GetFirstChild( rItem
,lCookie
);
while (vChild.IsOk())
{
aChildren.Add((long)(WXHTREEITEM)vChild);
vChild = GetNextChild( rItem
,lCookie
);
}
size_t nCount = aChildren.Count();
for (size_t n = 0; n < nCount; n++)
{
Delete(aChildren[n]);
}
} // end of wxTreeCtrl::DeleteChildren
void wxTreeCtrl::DeleteAllItems ()
{
::WinSendMsg( GetHWND()
,CM_REMOVERECORD
,NULL // Remove all
,(MPARAM)(CMA_FREE | CMA_INVALIDATE)
);
} // end of wxTreeCtrl::DeleteAllItems
void wxTreeCtrl::DoExpand (
const wxTreeItemId& rItem
, int nFlag
)
{
PMYRECORD pRecord = FindOS2TreeRecordByID( GetHWND()
,rItem.m_pItem
);
switch(nFlag)
{
case wxTREE_EXPAND_EXPAND:
::WinSendMsg( GetHWND()
,CM_EXPANDTREE
,MPFROMP(pRecord)
,NULL
);
break;
case wxTREE_EXPAND_COLLAPSE:
::WinSendMsg( GetHWND()
,CM_COLLAPSETREE
,MPFROMP(pRecord)
,NULL
);
break;
case wxTREE_EXPAND_COLLAPSE_RESET:
::WinSendMsg( GetHWND()
,CM_COLLAPSETREE
,MPFROMP(pRecord)
,NULL
);
DeleteChildren(rItem);
break;
case wxTREE_EXPAND_TOGGLE:
if (pRecord->m_vRecord.flRecordAttr & CRA_COLLAPSED)
::WinSendMsg( GetHWND()
,CM_EXPANDTREE
,MPFROMP(pRecord)
,NULL
);
else if (pRecord->m_vRecord.flRecordAttr & CRA_EXPANDED)
::WinSendMsg( GetHWND()
,CM_COLLAPSETREE
,MPFROMP(pRecord)
,NULL
);
break;
}
} // end of wxTreeCtrl::DoExpand
void wxTreeCtrl::Expand (
const wxTreeItemId& rItem
)
{
DoExpand( rItem
,wxTREE_EXPAND_EXPAND
);
} // end of wxTreeCtrl::Expand
void wxTreeCtrl::Collapse (
const wxTreeItemId& rItem
)
{
DoExpand( rItem
,wxTREE_EXPAND_COLLAPSE
);
} // end of wxTreeCtrl::Collapse
void wxTreeCtrl::CollapseAndReset (
const wxTreeItemId& rItem
)
{
DoExpand( rItem
,wxTREE_EXPAND_COLLAPSE_RESET
);
} // end of wxTreeCtrl::CollapseAndReset
void wxTreeCtrl::Toggle (
const wxTreeItemId& rItem
)
{
DoExpand( rItem
,wxTREE_EXPAND_TOGGLE
);
} // end of wxTreeCtrl::Toggle
#if WXWIN_COMPATIBILITY_2_4
void wxTreeCtrl::ExpandItem (
const wxTreeItemId& rItem
, int nAction
)
{
DoExpand( rItem
,nAction
);
} // end of wxTreeCtrl::ExpandItem
#endif // WXWIN_COMPATIBILITY_2_4
void wxTreeCtrl::Unselect ()
{
wxASSERT_MSG( !(m_windowStyle & wxTR_MULTIPLE),
wxT("doesn't make sense, may be you want UnselectAll()?") );
//
// Just remove the selection
//
SelectItem(wxTreeItemId((long)0));
} // end of wxTreeCtrl::Unselect
void wxTreeCtrl::UnselectAll ()
{
if (m_windowStyle & wxTR_MULTIPLE)
{
wxArrayTreeItemIds aSelections;
size_t nCount = GetSelections(aSelections);
for (size_t n = 0; n < nCount; n++)
{
SetItemCheck( aSelections[n]
,false
);
}
}
else
{
//
// Just remove the selection
//
Unselect();
}
} // end of wxTreeCtrl::UnselectAll
void wxTreeCtrl::SelectItem (
const wxTreeItemId& rItem
)
{
SetItemCheck(rItem);
} // end of wxTreeCtrl::SelectItem
void wxTreeCtrl::EnsureVisible (
const wxTreeItemId& rItem
)
{
wxTreeViewItem vTvItem(rItem);
DoGetItem(&vTvItem);
if (!::WinSendMsg( GetHWND()
,CM_INVALIDATERECORD
,MPFROMP(&vTvItem)
,MPFROM2SHORT(1, CMA_ERASE | CMA_REPOSITION | CMA_TEXTCHANGED)
));
} // end of wxTreeCtrl::EnsureVisible
void wxTreeCtrl::ScrollTo (
const wxTreeItemId& rItem
)
{
wxTreeViewItem vTvItem(rItem);
DoGetItem(&vTvItem);
if (!::WinSendMsg( GetHWND()
,CM_INVALIDATERECORD
,MPFROMP(&vTvItem)
,MPFROM2SHORT(1, CMA_ERASE | CMA_REPOSITION | CMA_TEXTCHANGED)
));
}
wxTextCtrl* wxTreeCtrl::EditLabel (
const wxTreeItemId& rItem
, wxClassInfo* WXUNUSED(pTextControlClass)
)
{
CNREDITDATA vEdit;
PMYRECORD pRecord = FindOS2TreeRecordByID( GetHWND()
,rItem.m_pItem
);
vEdit.cb = sizeof(CNREDITDATA);
vEdit.hwndCnr = GetHWND();
vEdit.pRecord = &pRecord->m_vRecord;
vEdit.pFieldInfo = NULL;
vEdit.ppszText = NULL;
vEdit.cbText = 0;
vEdit.id = 0;
::WinSendMsg( GetHWND()
,CM_OPENEDIT
,MPFROMP(&vEdit)
,(MPARAM)0
);
return NULL;
} // end of wxTreeCtrl::EditLabel
// End label editing, optionally cancelling the edit
void wxTreeCtrl::EndEditLabel (
const wxTreeItemId& WXUNUSED(rItem)
, bool WXUNUSED(bDiscardChanges)
)
{
::WinSendMsg( GetHWND()
,CM_CLOSEEDIT
,(MPARAM)0
,(MPARAM)0
);
} // end of wxTreeCtrl::EndEditLabel
wxTreeItemId wxTreeCtrl::HitTest (
const wxPoint& rPoint
, int& WXUNUSED(rFlags)
)
{
PMYRECORD pRecord = NULL;
QUERYRECFROMRECT vQueryRect;
RECTL vRect;
long lHeight;
//
// Get height for OS/2 point conversion
//
::WinSendMsg( GetHWND()
,CM_QUERYVIEWPORTRECT
,MPFROMP(&vRect)
,MPFROM2SHORT(CMA_WINDOW, TRUE)
);
lHeight = vRect.yTop - vRect.yBottom;
//
// For now just try and get a record in the general vicinity and forget
// the flag
//
vRect.xLeft = rPoint.x - 2;
vRect.xRight = rPoint.x + 2;
vRect.yTop = (lHeight - rPoint.y) + 2;
vRect.yBottom = (lHeight - rPoint.y) - 2;
vQueryRect.cb = sizeof(QUERYRECFROMRECT);
vQueryRect.rect = vRect;
vQueryRect.fsSearch = CMA_PARTIAL;
pRecord = (PMYRECORD)::WinSendMsg( GetHWND()
,CM_QUERYRECORDFROMRECT
,(MPARAM)CMA_FIRST
,MPFROMP(&vQueryRect)
);
if (!pRecord)
return -1L;
return wxTreeItemId((long)pRecord->m_ulItemId);
} // end of wxTreeCtrl::HitTest
bool wxTreeCtrl::GetBoundingRect (
const wxTreeItemId& rItem
, wxRect& rRect
, bool bTextOnly
) const
{
RECTL vRectRecord;
PMYRECORD pRecord = FindOS2TreeRecordByID ( GetHWND()
,rItem.m_pItem
);
QUERYRECORDRECT vQuery;
vQuery.cb = sizeof(QUERYRECORDRECT);
vQuery.pRecord = (PRECORDCORE)pRecord;
vQuery.fRightSplitWindow = FALSE;
if (bTextOnly)
vQuery.fsExtent = CMA_TEXT;
else
vQuery.fsExtent = CMA_TREEICON | CMA_TEXT;
if (!::WinSendMsg( GetHWND()
,CM_QUERYRECORDRECT
,MPFROMP(&vRectRecord)
,MPFROMP(&vQuery)
))
return false;
rRect.SetLeft(vRectRecord.xLeft);
rRect.SetTop(vRectRecord.yTop);
rRect.SetRight(vRectRecord.xRight);
rRect.SetBottom(vRectRecord.yBottom);
return true;
} // end of wxTreeCtrl::GetBoundingRect
// ----------------------------------------------------------------------------
// sorting stuff
// ----------------------------------------------------------------------------
SHORT EXPENTRY InternalDataCompareTreeFunc (
PMYRECORD p1
, PMYRECORD p2
, PVOID pStorage
)
{
wxCHECK_MSG( p1 && p2, 0,
wxT("sorting tree without data doesn't make sense") );
wxTreeCtrl* pTree = (wxTreeCtrl*)pStorage;
return pTree->OnCompareItems( p1->m_ulItemId
,p2->m_ulItemId
);
} // end of wxTreeSortHelper::Compare
int wxTreeCtrl::OnCompareItems (
const wxTreeItemId& rItem1
, const wxTreeItemId& rItem2
)
{
return wxStrcmp( GetItemText(rItem1)
,GetItemText(rItem2)
);
} // end of wxTreeCtrl::OnCompareItems
void wxTreeCtrl::SortChildren (
const wxTreeItemId& rItem
)
{
::WinSendMsg( GetHWND()
,CM_SORTRECORD
,(PFN)InternalDataCompareTreeFunc
,NULL
);
} // end of wxTreeCtrl::SortChildren
// ----------------------------------------------------------------------------
// implementation
// ----------------------------------------------------------------------------
bool wxTreeCtrl::OS2Command (
WXUINT uCmd
, WXWORD wId
)
{
if (uCmd == CN_ENDEDIT)
{
wxCommandEvent vEvent( wxEVT_COMMAND_TEXT_UPDATED
,wId
);
vEvent.SetEventObject( this );
ProcessCommand(vEvent);
return true;
}
else if (uCmd == CN_KILLFOCUS)
{
wxCommandEvent vEvent( wxEVT_KILL_FOCUS
,wId
);
vEvent.SetEventObject( this );
ProcessCommand(vEvent);
return true;
}
else
return false;
} // end of wxTreeCtrl::OS2Command
//
// TODO: Fully implement direct manipulation when I figure it out
//
MRESULT wxTreeCtrl::OS2WindowProc (
WXUINT uMsg
, WXWPARAM wParam
, WXLPARAM lParam
)
{
bool bProcessed = false;
MRESULT mRc = 0;
wxTreeEvent vEvent( wxEVT_NULL
,m_windowId
);
wxEventType vEventType = wxEVT_NULL;
PCNRDRAGINIT pDragInit = NULL;
PCNREDITDATA pEditData = NULL;
PNOTIFYRECORDENTER pNotifyEnter = NULL;
vEvent.SetEventObject(this);
switch (uMsg)
{
case WM_CONTROL:
switch(SHORT2FROMMP(wParam))
{
case CN_INITDRAG:
pDragInit = (PCNRDRAGINIT)lParam;
if (pDragInit)
{
PMYRECORD pRecord = (PMYRECORD)pDragInit->pRecord;
vEventType = wxEVT_COMMAND_TREE_BEGIN_DRAG;
vEvent.m_item = pRecord->m_ulItemId;
vEvent.m_pointDrag.x = pDragInit->x;
vEvent.m_pointDrag.y = pDragInit->y;
}
break;
case CN_BEGINEDIT:
pEditData = (PCNREDITDATA)lParam;
if (pEditData)
{
PMYRECORD pRecord = (PMYRECORD)pEditData->pRecord;
vEventType = wxEVT_COMMAND_TREE_BEGIN_LABEL_EDIT;
vEvent.m_item = pRecord->m_ulItemId;
vEvent.m_label = pRecord->m_vRecord.pszTree;
vEvent.m_editCancelled = false;
}
break;
case CN_ENDEDIT:
pEditData = (PCNREDITDATA)lParam;
if (pEditData)
{
PMYRECORD pRecord = (PMYRECORD)pEditData->pRecord;
vEventType = wxEVT_COMMAND_TREE_END_LABEL_EDIT;
vEvent.m_item = pRecord->m_ulItemId;
vEvent.m_label = pRecord->m_vRecord.pszTree;
if (pRecord->m_vRecord.pszTree == NULL)
{
vEvent.m_editCancelled = true;
}
else
{
vEvent.m_editCancelled = false;
}
}
break;
case CN_EXPANDTREE:
{
PMYRECORD pRecord = (PMYRECORD)lParam;
vEventType = gs_expandEvents[IDX_EXPAND][IDX_DONE];
vEvent.m_item = pRecord->m_ulItemId;
}
break;
}
vEvent.SetEventType(vEventType);
bProcessed = GetEventHandler()->ProcessEvent(vEvent);
break;
}
if (!bProcessed)
mRc = wxControl::OS2WindowProc( uMsg
,wParam
,lParam
);
return mRc;
} // end of wxTreeCtrl::OS2WindowProc
#if WXWIN_COMPATIBILITY_2_2
wxTreeItemId wxTreeCtrl::GetParent(const wxTreeItemId& item) const
{
return GetItemParent( item );
}
#endif // WXWIN_COMPATIBILITY_2_2
#endif // wxUSE_TREECTRL