git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@31319 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
2141 lines
67 KiB
C++
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
|