X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/d90895ac118ad4546eed7ee4c358a3fe644a1ad7..8f79ece33306d91be746a694f3893906bba67465:/src/os2/treectrl.cpp diff --git a/src/os2/treectrl.cpp b/src/os2/treectrl.cpp index 8671b38c71..edd074f652 100644 --- a/src/os2/treectrl.cpp +++ b/src/os2/treectrl.cpp @@ -1,207 +1,296 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: treectrl.cpp -// Purpose: wxTreeCtrl. See also Robert's generic wxTreeCtrl. -// Author: David Webster -// Modified by: -// Created: 10/17/99 +// Name: src/os2/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) David +// Copyright: (c) Julian Smart // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// +// ============================================================================ +// declarations +// ============================================================================ + +// ---------------------------------------------------------------------------- +// headers +// ---------------------------------------------------------------------------- + // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" -#include "wx/window.h" -#include "wx/os2/private.h" +#ifdef __BORLANDC__ + #pragma hdrstop +#endif + +#if wxUSE_TREECTRL -#include "wx/log.h" -#include "wx/dynarray.h" -#include "wx/imaglist.h" #include "wx/treectrl.h" -#include "wx/settings.h" -// Bug in headers, sometimes -#ifndef TVIS_FOCUSED - #define TVIS_FOCUSED 0x0001 +#ifndef WX_PRECOMP + #include "wx/dynarray.h" + #include "wx/log.h" + #include "wx/app.h" + #include "wx/settings.h" #endif +#include "wx/os2/private.h" + +#include "wx/imaglist.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 // ---------------------------------------------------------------------------- -struct wxTreeViewItem// ??? : public TV_ITEM +typedef struct _MYRECORD +{ + RECORDCORE m_vRecord; + ULONG m_ulItemId; + ULONG m_ulUserData; +} MYRECORD, *PMYRECORD; + +struct wxTreeViewItem : public MYRECORD { - wxTreeViewItem(const wxTreeItemId& item, // the item handle - UINT mask_, // fields which are valid - UINT stateMask_ = 0) // for TVIF_STATE only + wxTreeViewItem(const wxTreeItemId& rItem) { - // hItem member is always valid - mask = mask_; // | TVIF_HANDLE; - stateMask = stateMask_; - hItem = /*(HTREEITEM)*/ (WXHTREEITEM) item; + m_ulItemId = (ULONG)rItem.m_pItem; } - // OS/2 subs - UINT mask; - UINT stateMask; - WXHTREEITEM hItem; -}; +}; // end of STRUCT wxTreeViewItem -// a class which encapsulates the tree traversal logic: it vists all (unless -// OnVisit() returns FALSE) items under the given one -class wxTreeTraversal +class wxTreeItemInternalData { public: - wxTreeTraversal(const wxTreeCtrl *tree) + + 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) { - m_tree = tree; + 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 + - // 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& root, bool recursively = TRUE); - // override this function to do whatever is needed for each item, return - // FALSE to stop traversing - virtual bool OnVisit(const wxTreeItemId& item) = 0; +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() const { return m_tree; } + const wxTreeCtrl* GetTree(void) const { return m_pTree; } private: - bool Traverse(const wxTreeItemId& root, bool recursively); + bool Traverse( const wxTreeItemId& rRoot + ,bool bRecursively + ); - const wxTreeCtrl *m_tree; -}; + const wxTreeCtrl* m_pTree; + wxDECLARE_NO_COPY_CLASS(wxTreeTraversal); +}; // end of CLASS wxTreeTraversal -// internal class for getting the selected items +// +// Internal class for getting the selected items +// class TraverseSelections : public wxTreeTraversal { public: - TraverseSelections(const wxTreeCtrl *tree, - wxArrayTreeItemIds& selections) - : wxTreeTraversal(tree), m_selections(selections) - { - m_selections.Empty(); - - DoTraverse(tree->GetRootItem()); - } + TraverseSelections( const wxTreeCtrl* pTree + ,wxArrayTreeItemIds& raSelections + ) + : wxTreeTraversal(pTree) + , m_aSelections(raSelections) + { + m_aSelections.Empty(); + DoTraverse(pTree->GetRootItem()); + } - virtual bool OnVisit(const wxTreeItemId& item) + virtual bool OnVisit(const wxTreeItemId& rItem) { - if ( GetTree()->IsItemChecked(item) ) + // + // Can't visit a virtual node. + // + if ((GetTree()->GetRootItem() == rItem) && (GetTree()->GetWindowStyle() & wxTR_HIDE_ROOT)) { - m_selections.Add(item); + return true; } - - return TRUE; - } - -private: - wxArrayTreeItemIds& m_selections; -}; - -// internal class for counting tree items -class TraverseCounter : public wxTreeTraversal -{ -public: - TraverseCounter(const wxTreeCtrl *tree, - const wxTreeItemId& root, - bool recursively) - : wxTreeTraversal(tree) + PMYRECORD pRecord = FindOS2TreeRecordByID( (HWND)GetTree()->GetHWND() + ,rItem.m_pItem + ); + if (pRecord->m_vRecord.flRecordAttr & CRA_SELECTED) { - m_count = 0; - - DoTraverse(root, recursively); + m_aSelections.Add(rItem); } - - virtual bool OnVisit(const wxTreeItemId& item) - { - m_count++; - - return TRUE; + return true; } - size_t GetCount() const { return m_count; } + size_t GetCount(void) const { return m_aSelections.GetCount(); } private: - size_t m_count; -}; + wxArrayTreeItemIds& m_aSelections; +}; // end of CLASS TraverseSelections -// ---------------------------------------------------------------------------- -// This class is needed for support of different images: the Win32 common -// control natively supports only 2 images (the normal one and another for the -// selected state). We wish to provide support for 2 more of them for folder -// items (i.e. those which have children): for expanded state and for expanded -// selected state. For this we use this structure to store the additional items -// images. // -// There is only one problem with this: when we retrieve the item's data, we -// don't know whether we get a pointer to wxTreeItemData or -// wxTreeItemIndirectData. So we have to maintain a list of all items which -// have indirect data inside the listctrl itself. -// ---------------------------------------------------------------------------- -class wxTreeItemIndirectData +// Internal class for counting tree items +// +class TraverseCounter : public wxTreeTraversal { public: - // ctor associates this data with the item and the real item data becomes - // available through our GetData() method - wxTreeItemIndirectData(wxTreeCtrl *tree, const wxTreeItemId& item) + TraverseCounter( const wxTreeCtrl* pTree + ,const wxTreeItemId& rRoot + ,bool bRecursively + ) + : wxTreeTraversal(pTree) { - for ( size_t n = 0; n < WXSIZEOF(m_images); n++ ) - { - m_images[n] = -1; - } - - // save the old data - m_data = tree->GetItemData(item); - - // and set ourselves as the new one - tree->SetIndirectItemData(item, this); + m_nCount = 0; + DoTraverse(rRoot, bRecursively); } - // dtor deletes the associated data as well - ~wxTreeItemIndirectData() { delete m_data; } - - // accessors - // get the real data associated with the item - wxTreeItemData *GetData() const { return m_data; } - // change it - void SetData(wxTreeItemData *data) { m_data = data; } + virtual bool OnVisit(const wxTreeItemId& WXUNUSED(rItem)) + { + m_nCount++; + return true; + } - // do we have such image? - bool HasImage(wxTreeItemIcon which) const { return m_images[which] != -1; } - // get image - int GetImage(wxTreeItemIcon which) const { return m_images[which]; } - // change it - void SetImage(int image, wxTreeItemIcon which) { m_images[which] = image; } + size_t GetCount(void) const { return m_nCount; } private: - // all the images associated with the item - int m_images[wxTreeItemIcon_Max]; - - wxTreeItemData *m_data; -}; + size_t m_nCount; +}; // end of CLASS TraverseCounter // ---------------------------------------------------------------------------- -// macros +// wxWin macros // ---------------------------------------------------------------------------- -#if !USE_SHARED_LIBRARY - IMPLEMENT_DYNAMIC_CLASS(wxTreeCtrl, wxControl) -#endif +IMPLEMENT_DYNAMIC_CLASS(wxTreeCtrl, wxControl) // ---------------------------------------------------------------------------- -// variables +// constants // ---------------------------------------------------------------------------- -// handy table for sending events -static const wxEventType g_events[2][2] = +// 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 @@ -211,1479 +300,1773 @@ static const wxEventType g_events[2][2] = // tree traversal // ---------------------------------------------------------------------------- -bool wxTreeTraversal::DoTraverse(const wxTreeItemId& root, bool recursively) -{ - if ( !OnVisit(root) ) - return FALSE; - - return Traverse(root, recursively); -} - -bool wxTreeTraversal::Traverse(const wxTreeItemId& root, bool recursively) -{ - long cookie; - wxTreeItemId child = m_tree->GetFirstChild(root, cookie); - while ( child.IsOk() ) +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 ( recursively && !Traverse(child, TRUE) ) - return FALSE; - - if ( !OnVisit(child) ) - return FALSE; - - child = m_tree->GetNextChild(root, cookie); + // + // Depth first traversal + // + if (bRecursively && !Traverse(vChild, true)) + return false; + if (!OnVisit(vChild)) + return false; + vChild = m_pTree->GetNextChild( rRoot + ,lCookie + ); } - - return TRUE; -} + return true; +} // end of wxTreeTraversal::Traverse // ---------------------------------------------------------------------------- // construction and destruction // ---------------------------------------------------------------------------- -void wxTreeCtrl::Init() -{ - m_imageListNormal = NULL; - m_imageListState = NULL; - m_textCtrl = NULL; -} +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; -bool wxTreeCtrl::Create(wxWindow *parent, - wxWindowID id, - const wxPoint& pos, - const wxSize& size, - long style, - const wxValidator& validator, - const wxString& name) -{ Init(); + if (!CreateControl( pParent + ,vId + ,rPos + ,rSize + ,lStyle + ,rValidator + ,rsName + )) + return false; - if ( !CreateControl(parent, id, pos, size, style, validator, name) ) - return FALSE; -// TODO: -/* - DWORD wstyle = WS_VISIBLE | WS_CHILD | WS_TABSTOP | - TVS_HASLINES | TVS_SHOWSELALWAYS; - - if ( m_windowStyle & wxTR_HAS_BUTTONS ) - wstyle |= TVS_HASBUTTONS; - - if ( m_windowStyle & wxTR_EDIT_LABELS ) - wstyle |= TVS_EDITLABELS; + DWORD dwStyle = WS_VISIBLE | WS_TABSTOP; - if ( m_windowStyle & wxTR_LINES_AT_ROOT ) - wstyle |= TVS_LINESATROOT; - - if ( m_windowStyle & wxTR_MULTIPLE ) - wstyle |= TVS_CHECKBOXES; + if (m_windowStyle & wxCLIP_SIBLINGS) + dwStyle |= WS_CLIPSIBLINGS; // Create the tree control. - if ( !OS2CreateControl(WC_TREEVIEW, wstyle) ) - return FALSE; -*/ - SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_WINDOW)); + 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()); - - // VZ: this is some experimental code which may be used to get the - // TVS_CHECKBOXES style functionality for comctl32.dll < 4.71. - // AFAIK, the standard DLL does about the same thing anyhow. -#if 0 - if ( m_windowStyle & wxTR_MULTIPLE ) + 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) { - wxBitmap bmp; - - // create the DC compatible with the current screen - HDC hdcMem = CreateCompatibleDC(NULL); - - // create a mono bitmap of the standard size - int x = GetSystemMetrics(SM_CXMENUCHECK); - int y = GetSystemMetrics(SM_CYMENUCHECK); - wxImageList imagelistCheckboxes(x, y, FALSE, 2); - HBITMAP hbmpCheck = CreateBitmap(x, y, // bitmap size - 1, // # of color planes - 1, // # bits needed for one pixel - 0); // array containing colour data - SelectObject(hdcMem, hbmpCheck); - - // then draw a check mark into it - RECT rect = { 0, 0, x, y }; - if ( !::DrawFrameControl(hdcMem, &rect, - DFC_BUTTON, - DFCS_BUTTONCHECK | DFCS_CHECKED) ) - { - wxLogLastError(wxT("DrawFrameControl(check)")); - } - - bmp.SetHBITMAP((WXHBITMAP)hbmpCheck); - imagelistCheckboxes.Add(bmp); - - if ( !::DrawFrameControl(hdcMem, &rect, - DFC_BUTTON, - DFCS_BUTTONCHECK) ) + for (wxNode* pNode = m_vAttrs.Next(); pNode; pNode = m_vAttrs.Next()) { - wxLogLastError(wxT("DrawFrameControl(uncheck)")); + delete (wxTreeItemAttr *)pNode->Data(); } - - bmp.SetHBITMAP((WXHBITMAP)hbmpCheck); - imagelistCheckboxes.Add(bmp); - - // clean up - ::DeleteDC(hdcMem); - - // set the imagelist - SetStateImageList(&imagelistCheckboxes); + m_bHasAnyAttr = false; } -#endif // 0 - - SetSize(pos.x, pos.y, size.x, size.y); - - return TRUE; -} - -wxTreeCtrl::~wxTreeCtrl() -{ DeleteTextCtrl(); - // delete user data to prevent memory leaks -// DeleteAllItems(); -} + // + // 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 - -bool wxTreeCtrl::DoGetItem(wxTreeViewItem* tvItem) const +// +// 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 { -// TODO: -/* - if ( !TreeView_GetItem(GetHwnd(), tvItem) ) - { - wxLogLastError("TreeView_GetItem"); + PMYRECORD pRecord = FindOS2TreeRecordByID( GetHWND() + ,pTvItem->m_ulItemId + ); - return FALSE; + if (!pRecord) + { + wxLogLastError(wxT("Item not obtained")); + return false; } -*/ - return TRUE; -} - -void wxTreeCtrl::DoSetItem(wxTreeViewItem* tvItem) -{ -// TODO: -/* - if ( TreeView_SetItem(GetHwnd(), tvItem) == -1 ) + 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("TreeView_SetItem"); + wxLogLastError(wxT("CM_INVALIDATERECORD")); } -*/ -} +} // end of wxTreeCtrl::DoSetItem -size_t wxTreeCtrl::GetCount() const +unsigned int wxTreeCtrl::GetCount () const { -// return (size_t)TreeView_GetCount(GetHwnd()); - return 0; -} + CNRINFO vCnrInfo; + + ::WinSendMsg( GetHWND() + ,CM_QUERYCNRINFO + ,MPFROMP(&vCnrInfo) + ,(MPARAM)(USHORT)sizeof(CNRINFO) + ); + + return (unsigned int)vCnrInfo.cRecords; +} // end of wxTreeCtrl::GetCount -unsigned int wxTreeCtrl::GetIndent() const +unsigned int wxTreeCtrl::GetIndent () const { -// return TreeView_GetIndent(GetHwnd()); - return 0; -} + 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 indent) +void wxTreeCtrl::SetIndent ( + unsigned int uIndent +) { -// TreeView_SetIndent(GetHwnd(), indent); -} + 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 +wxImageList* wxTreeCtrl::GetImageList () const { - return m_imageListNormal; -} + return m_pImageListNormal; +} // end of wxTreeCtrl::GetImageList -wxImageList *wxTreeCtrl::GetStateImageList() const +wxImageList* wxTreeCtrl::GetStateImageList () const { - return m_imageListNormal; -} + 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 +// compatibility only +// +void wxTreeCtrl::SetAnyImageList ( + wxImageList* WXUNUSED(pImageList) +, int WXUNUSED(nWhich) +) +{ +} // end of wxTreeCtrl::SetAnyImageList -void wxTreeCtrl::SetAnyImageList(wxImageList *imageList, int which) +void wxTreeCtrl::SetImageList ( + wxImageList* WXUNUSED(pImageList) +) { - // no error return -// TODO: -/* - TreeView_SetImageList(GetHwnd(), - imageList ? imageList->GetHIMAGELIST() : 0, - which); -*/ -} + if (m_bOwnsImageListNormal) + delete m_pImageListNormal; + m_bOwnsImageListNormal = false; +} // end of wxTreeCtrl::SetImageList -void wxTreeCtrl::SetImageList(wxImageList *imageList) +void wxTreeCtrl::SetStateImageList ( + wxImageList* WXUNUSED(pImageList) +) { -// SetAnyImageList(m_imageListNormal = imageList, TVSIL_NORMAL); -} + if (m_bOwnsImageListState) + delete m_pImageListState; + m_bOwnsImageListState = false; +} // end of wxTreeCtrl::SetStateImageList -void wxTreeCtrl::SetStateImageList(wxImageList *imageList) +void wxTreeCtrl::AssignImageList ( + wxImageList* WXUNUSED(pImageList) +) { -// SetAnyImageList(m_imageListState = imageList, TVSIL_STATE); -} + m_bOwnsImageListNormal = true; +} // end of wxTreeCtrl::AssignImageList -size_t wxTreeCtrl::GetChildrenCount(const wxTreeItemId& item, - bool recursively) const +void wxTreeCtrl::AssignStateImageList ( + wxImageList* WXUNUSED(pImageList) +) { - TraverseCounter counter(this, item, recursively); + m_bOwnsImageListState = true; +} // end of wxTreeCtrl::AssignStateImageList - return counter.GetCount() - 1; -} +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& item) const +wxString wxTreeCtrl::GetItemText ( + const wxTreeItemId& rItem +) const { - wxChar buf[512]; // the size is arbitrary... -// TODO: -/* - wxTreeViewItem tvItem(item, TVIF_TEXT); - tvItem.pszText = buf; - tvItem.cchTextMax = WXSIZEOF(buf); - if ( !DoGetItem(&tvItem) ) + 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 - buf[0] = wxT('\0'); + // + // Don't return some garbage which was on stack, but an empty string + // + zBuf[0] = wxT('\0'); } -*/ - return wxString(buf); -} + else + strcpy(zBuf, vTvItem.m_vRecord.pszTree); + return wxString(zBuf); +} // end of wxTreeCtrl::GetItemText -void wxTreeCtrl::SetItemText(const wxTreeItemId& item, const wxString& text) +void wxTreeCtrl::SetItemText ( + const wxTreeItemId& rItem +, const wxString& rsText +) { -// TODO: -/* - wxTreeViewItem tvItem(item, TVIF_TEXT); - tvItem.pszText = (wxChar *)text.c_str(); // conversion is ok - DoSetItem(&tvItem); -*/ -} + wxTreeViewItem vTvItem(rItem); -int wxTreeCtrl::DoGetItemImageFromData(const wxTreeItemId& item, - wxTreeItemIcon which) const -{ -// TODO: -/* - wxTreeViewItem tvItem(item, TVIF_PARAM); - if ( !DoGetItem(&tvItem) ) - { - return -1; - } - return ((wxTreeItemIndirectData *)tvItem.lParam)->GetImage(which); -*/ - return -1; -} + vTvItem.m_vRecord.pszTree = (wxChar *)rsText.c_str(); // conversion is ok + DoSetItem(&vTvItem); +} // end of wxTreeCtrl::SetItemText -void wxTreeCtrl::DoSetItemImageFromData(const wxTreeItemId& item, - int image, - wxTreeItemIcon which) const -{ -// TODO: -/* - wxTreeViewItem tvItem(item, TVIF_PARAM); - if ( !DoGetItem(&tvItem) ) +// +// 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) { - return; - } - - wxTreeItemIndirectData *data = ((wxTreeItemIndirectData *)tvItem.lParam); + case wxTreeItemIcon_Normal: + if (vCnrInfo.hbmCollapsed == NULLHANDLE) + return (int)::WinGetSysBitmap(HWND_DESKTOP, SBMP_TREEPLUS); + return vCnrInfo.hbmCollapsed; - data->SetImage(image, which); - // make sure that we have selected images as well - if ( which == wxTreeItemIcon_Normal && - !data->HasImage(wxTreeItemIcon_Selected) ) - { - data->SetImage(image, wxTreeItemIcon_Selected); - } + case wxTreeItemIcon_Expanded: + if (vCnrInfo.hbmExpanded == NULLHANDLE) + return (int)::WinGetSysBitmap(HWND_DESKTOP, SBMP_TREEMINUS); + return vCnrInfo.hbmExpanded; - if ( which == wxTreeItemIcon_Expanded && - !data->HasImage(wxTreeItemIcon_SelectedExpanded) ) - { - data->SetImage(image, wxTreeItemIcon_SelectedExpanded); + default: + return vCnrInfo.hbmCollapsed; } -*/ } -void wxTreeCtrl::DoSetItemImages(const wxTreeItemId& item, - int image, - int imageSel) -{ -// TODO: -/* - wxTreeViewItem tvItem(item, TVIF_IMAGE | TVIF_SELECTEDIMAGE); - tvItem.iSelectedImage = imageSel; - tvItem.iImage = image; - DoSetItem(&tvItem); -*/ -} - -int wxTreeCtrl::GetItemImage(const wxTreeItemId& item, - wxTreeItemIcon which) const -{ - if ( HasIndirectData(item) ) +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(item, which); + return DoGetItemImageFromData( rItem + ,nWhich + ); } - UINT mask; - switch ( which ) + 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: -// mask = TVIF_IMAGE; - break; + if (vCnrInfo.hbmCollapsed == NULLHANDLE) + return (int)::WinGetSysBitmap(HWND_DESKTOP, SBMP_TREEPLUS); + return vCnrInfo.hbmCollapsed; - case wxTreeItemIcon_Selected: -// mask = TVIF_SELECTEDIMAGE; - break; 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; } - - wxTreeViewItem tvItem(item, mask); - DoGetItem(&tvItem); - -// return mask == TVIF_IMAGE ? tvItem.iImage : tvItem.iSelectedImage; - return FALSE; } -void wxTreeCtrl::SetItemImage(const wxTreeItemId& item, int image, - wxTreeItemIcon which) +void wxTreeCtrl::SetItemImage ( + const wxTreeItemId& WXUNUSED(rItem) +, int nImage +, wxTreeItemIcon nWhich +) { - int imageNormal, imageSel; - switch ( which ) - { - default: - wxFAIL_MSG( wxT("unknown tree item image type") ); + CNRINFO vCnrInfo; + ::WinSendMsg( GetHWND() + ,CM_QUERYCNRINFO + ,MPFROMP(&vCnrInfo) + ,(MPARAM)(USHORT)sizeof(CNRINFO) + ); + switch (nWhich) + { case wxTreeItemIcon_Normal: - imageNormal = image; - imageSel = GetItemSelectedImage(item); - break; - - case wxTreeItemIcon_Selected: - imageNormal = GetItemImage(item); - imageSel = image; + vCnrInfo.hbmCollapsed = (HBITMAP)nImage; break; case wxTreeItemIcon_Expanded: - case wxTreeItemIcon_SelectedExpanded: - if ( !HasIndirectData(item) ) - { - // we need to get the old images first, because after we create - // the wxTreeItemIndirectData GetItemXXXImage() will use it to - // get the images - imageNormal = GetItemImage(item); - imageSel = GetItemSelectedImage(item); - - // if it doesn't have it yet, add it - wxTreeItemIndirectData *data = new - wxTreeItemIndirectData(this, item); - - // copy the data to the new location - data->SetImage(imageNormal, wxTreeItemIcon_Normal); - data->SetImage(imageSel, wxTreeItemIcon_Selected); - } - - DoSetItemImageFromData(item, image, which); - - // reset the normal/selected images because we won't use them any - // more - now they're stored inside the indirect data -// imageSel = I_IMAGECALLBACK; + vCnrInfo.hbmExpanded = (HBITMAP)nImage; break; - } - // NB: at least in version 5.00.0518.9 of comctl32.dll we need to always - // change both normal and selected image - otherwise the change simply - // doesn't take place! - DoSetItemImages(item, imageNormal, imageSel); -} + 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& item) const +wxTreeItemData* wxTreeCtrl::GetItemData ( + const wxTreeItemId& rItem +) const { -// TODO: -/* - wxTreeViewItem tvItem(item, TVIF_PARAM); - if ( !DoGetItem(&tvItem) ) + wxTreeViewItem vTvItem(rItem); + + if (!DoGetItem(&vTvItem)) { return NULL; } - if ( HasIndirectData(item) ) - { - return ((wxTreeItemIndirectData *)tvItem.lParam)->GetData(); - } - else - { - return (wxTreeItemData *)tvItem.lParam; - } -*/ - return 0; -} + return (wxTreeItemData *)vTvItem.m_ulUserData; +} // end of wxTreeCtrl::GetItemData -void wxTreeCtrl::SetItemData(const wxTreeItemId& item, wxTreeItemData *data) +void wxTreeCtrl::SetItemData ( + const wxTreeItemId& rItem +, wxTreeItemData* pData +) { -// TODO: -/* - wxTreeViewItem tvItem(item, TVIF_PARAM); - - if ( HasIndirectData(item) ) - { - if ( DoGetItem(&tvItem) ) - { - ((wxTreeItemIndirectData *)tvItem.lParam)->SetData(data); - } - else - { - wxFAIL_MSG( wxT("failed to change tree items data") ); - } - } - else + // + // first, associate this piece of data with this item + if (pData) { - tvItem.lParam = (MPARAM)data; - DoSetItem(&tvItem); + pData->SetId(rItem); } -*/ -} -void wxTreeCtrl::SetIndirectItemData(const wxTreeItemId& item, - wxTreeItemIndirectData *data) -{ - // this should never happen because it's unnecessary and will probably lead - // to crash too because the code elsewhere supposes that the pointer the - // wxTreeItemIndirectData has is a real wxItemData and not - // wxTreeItemIndirectData as well - wxASSERT_MSG( !HasIndirectData(item), wxT("setting indirect data twice?") ); + wxTreeViewItem vTvItem(rItem); - SetItemData(item, (wxTreeItemData *)data); + vTvItem.m_ulUserData = (ULONG)pData; + DoSetItem(&vTvItem); +} // end of wxTreeCtrl::SetItemData - m_itemsWithIndirectData.Add(item); -} +// 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& item) const +bool wxTreeCtrl::HasIndirectData ( + const wxTreeItemId& WXUNUSED(rItem) +) const { - return m_itemsWithIndirectData.Index(item) != wxNOT_FOUND; -} + return false; +} // end of wxTreeCtrl::HasIndirectData -void wxTreeCtrl::SetItemHasChildren(const wxTreeItemId& item, bool has) +// Irreleveant under OS/2 --- item either has child records or it doesn't. +void wxTreeCtrl::SetItemHasChildren ( + const wxTreeItemId& WXUNUSED(rItem) +, bool WXUNUSED(bHas) +) { -// TODO: -/* - wxTreeViewItem tvItem(item, TVIF_CHILDREN); - tvItem.cChildren = (int)has; - DoSetItem(&tvItem); -*/ -} +} // end of wxTreeCtrl::SetItemHasChildren -void wxTreeCtrl::SetItemBold(const wxTreeItemId& item, bool bold) +// Irreleveant under OS/2 --- function of the font in PM +void wxTreeCtrl::SetItemBold ( + const wxTreeItemId& WXUNUSED(rItem) +, bool WXUNUSED(bBold) +) { -// TODO: -/* - wxTreeViewItem tvItem(item, TVIF_STATE, TVIS_BOLD); - tvItem.state = bold ? TVIS_BOLD : 0; - DoSetItem(&tvItem); -*/ -} +} // end of wxTreeCtrl::SetItemBold -void wxTreeCtrl::SetItemDropHighlight(const wxTreeItemId& item, bool highlight) +void wxTreeCtrl::SetItemDropHighlight ( + const wxTreeItemId& rItem +, bool bHighlight +) { -// TODO: -/* - wxTreeViewItem tvItem(item, TVIF_STATE, TVIS_DROPHILITED); - tvItem.state = highlight ? TVIS_DROPHILITED : 0; - DoSetItem(&tvItem); -*/ -} + wxTreeViewItem vTvItem(rItem); -// ---------------------------------------------------------------------------- -// Item status -// ---------------------------------------------------------------------------- + ::WinSendMsg( GetHWND() + ,CM_SETRECORDEMPHASIS + ,MPFROMP(&vTvItem) + ,MPFROM2SHORT(bHighlight, CRA_SELECTED) + ); + DoSetItem(&vTvItem); +} // end of wxTreeCtrl::SetItemDropHighlight -bool wxTreeCtrl::IsVisible(const wxTreeItemId& item) const +void wxTreeCtrl::RefreshItem ( + const wxTreeItemId& rItem +) { - // Bug in Gnu-Win32 headers, so don't use the macro TreeView_GetItemRect -// TODO: -/* - RECT rect; - return SendMessage(GetHwnd(), TVM_GETITEMRECT, FALSE, (LPARAM)&rect) != 0; -*/ - return FALSE; -} + wxTreeViewItem vTvItem(rItem); -bool wxTreeCtrl::ItemHasChildren(const wxTreeItemId& item) const + // + // 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 { -// TODO: -/* - wxTreeViewItem tvItem(item, TVIF_CHILDREN); - DoGetItem(&tvItem); + long lId = (long)rItem.m_pItem; + wxTreeItemAttr* pAttr = (wxTreeItemAttr *)m_vAttrs.Get(lId); - return tvItem.cChildren != 0; -*/ - return FALSE; -} + if (!pAttr) + { + return wxNullColour; + } + return pAttr->GetTextColour(); +} // end of wxTreeCtrl::GetItemTextColour -bool wxTreeCtrl::IsExpanded(const wxTreeItemId& item) const +wxColour wxTreeCtrl::GetItemBackgroundColour ( + const wxTreeItemId& rItem +) const { - // probably not a good idea to put it here - //wxASSERT( ItemHasChildren(item) ); + long lId = (long)rItem.m_pItem; + wxTreeItemAttr* pAttr = (wxTreeItemAttr *)m_vAttrs.Get(lId); -// TODO: -/* - wxTreeViewItem tvItem(item, TVIF_STATE, TVIS_EXPANDED); - DoGetItem(&tvItem); - - return (tvItem.state & TVIS_EXPANDED) != 0; -*/ - return FALSE; -} + if (!pAttr) + { + return wxNullColour; + } + return pAttr->GetBackgroundColour(); +} // end of wxTreeCtrl::GetItemBackgroundColour -bool wxTreeCtrl::IsSelected(const wxTreeItemId& item) const +wxFont wxTreeCtrl::GetItemFont ( + const wxTreeItemId& rItem +) const { -// TODO: -/* - wxTreeViewItem tvItem(item, TVIF_STATE, TVIS_SELECTED); - DoGetItem(&tvItem); + long lId = (long)rItem.m_pItem; + wxTreeItemAttr* pAttr = (wxTreeItemAttr *)m_vAttrs.Get(lId); - return (tvItem.state & TVIS_SELECTED) != 0; -*/ - return FALSE; -} + if (!pAttr) + { + return wxNullFont; + } + return pAttr->GetFont(); +} // end of wxTreeCtrl::GetItemFont -bool wxTreeCtrl::IsBold(const wxTreeItemId& item) const +void wxTreeCtrl::SetItemTextColour ( + const wxTreeItemId& rItem +, const wxColour& rCol +) { -// TODO: -/* - wxTreeViewItem tvItem(item, TVIF_STATE, TVIS_BOLD); - DoGetItem(&tvItem); + m_bHasAnyAttr = true; - return (tvItem.state & TVIS_BOLD) != 0; -*/ - return FALSE; -} + long lId = (long)rItem.m_pItem; + wxTreeItemAttr* pAttr = (wxTreeItemAttr *)m_vAttrs.Get(lId); -// ---------------------------------------------------------------------------- -// navigation -// ---------------------------------------------------------------------------- + if (!pAttr) + { + pAttr = new wxTreeItemAttr; + m_vAttrs.Put(lId, (wxObject *)pAttr); + } + pAttr->SetTextColour(rCol); + RefreshItem(rItem); +} // end of wxTreeCtrl::SetItemTextColour -wxTreeItemId wxTreeCtrl::GetRootItem() const +void wxTreeCtrl::SetItemBackgroundColour ( + const wxTreeItemId& rItem +, const wxColour& rCol +) { -// return wxTreeItemId((WXHTREEITEM) TreeView_GetRoot(GetHwnd())); - return 0; -} + m_bHasAnyAttr = true; -wxTreeItemId wxTreeCtrl::GetSelection() const -{ - wxCHECK_MSG( !(m_windowStyle & wxTR_MULTIPLE), (WXHTREEITEM)0, - wxT("this only works with single selection controls") ); + long lId = (long)rItem.m_pItem; + wxTreeItemAttr* pAttr = (wxTreeItemAttr *)m_vAttrs.Get(lId); -// return wxTreeItemId((WXHTREEITEM) TreeView_GetSelection(GetHwnd())); - return 0; -} + if (!pAttr) + { + pAttr = new wxTreeItemAttr; + m_vAttrs.Put(lId, (wxObject *)pAttr); + } + pAttr->SetBackgroundColour(rCol); + RefreshItem(rItem); +} // end of wxTreeCtrl::SetItemBackgroundColour -wxTreeItemId wxTreeCtrl::GetParent(const wxTreeItemId& item) const +void wxTreeCtrl::SetItemFont ( + const wxTreeItemId& rItem +, const wxFont& rFont +) { -// return wxTreeItemId((WXHTREEITEM) TreeView_GetParent(GetHwnd(), (HTREEITEM) (WXHTREEITEM) item)); - return 0; -} + m_bHasAnyAttr = true; -wxTreeItemId wxTreeCtrl::GetFirstChild(const wxTreeItemId& item, - long& _cookie) const -{ -// TODO: -/* - // remember the last child returned in 'cookie' - _cookie = (long)TreeView_GetChild(GetHwnd(), (HTREEITEM) (WXHTREEITEM)item); + long lId = (long)rItem.m_pItem; + wxTreeItemAttr* pAttr = (wxTreeItemAttr *)m_vAttrs.Get(lId); - return wxTreeItemId((WXHTREEITEM)_cookie); -*/ - return 0; -} + if (!pAttr) + { + pAttr = new wxTreeItemAttr; + m_vAttrs.Put(lId, (wxObject *)pAttr); + } + pAttr->SetFont(rFont); + RefreshItem(rItem); +} // end of wxTreeCtrl::SetItemFont -wxTreeItemId wxTreeCtrl::GetNextChild(const wxTreeItemId& WXUNUSED(item), - long& _cookie) const +// ---------------------------------------------------------------------------- +// Item status +// ---------------------------------------------------------------------------- + +bool wxTreeCtrl::IsVisible ( + const wxTreeItemId& rItem +) const { - wxTreeItemId l = 0; //wxTreeItemId((WXHTREEITEM)TreeView_GetNextSibling(GetHwnd(), -// (HTREEITEM)(WXHTREEITEM)_cookie)); - _cookie = (long)l; + // 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.Contains(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 - return l; -} +// ---------------------------------------------------------------------------- +// navigation +// ---------------------------------------------------------------------------- -wxTreeItemId wxTreeCtrl::GetLastChild(const wxTreeItemId& item) const +wxTreeItemId wxTreeCtrl::GetRootItem () const { - // can this be done more efficiently? - long cookie; + PMYRECORD pRecord = NULL; - wxTreeItemId childLast, - child = GetFirstChild(item, cookie); - while ( child.IsOk() ) - { - childLast = child; - child = GetNextChild(item, cookie); - } + pRecord = (PMYRECORD)PVOIDFROMMR(::WinSendMsg( GetHWND() + ,CM_QUERYRECORD + ,MPFROMP(pRecord) + ,MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER) + )); - return childLast; -} + if (!pRecord) + return wxTreeItemId(-1L); + return wxTreeItemId((long)pRecord->m_ulItemId); +} // end of wxTreeCtrl::GetRootItem -wxTreeItemId wxTreeCtrl::GetNextSibling(const wxTreeItemId& item) const +wxTreeItemId wxTreeCtrl::GetSelection () const { -// return wxTreeItemId((WXHTREEITEM) TreeView_GetNextSibling(GetHwnd(), (HTREEITEM) (WXHTREEITEM) item)); - return 0; -} + wxCHECK_MSG( !(m_windowStyle & wxTR_MULTIPLE), (long)(WXHTREEITEM)0, + wxT("this only works with single selection controls") ); -wxTreeItemId wxTreeCtrl::GetPrevSibling(const wxTreeItemId& item) const -{ -// return wxTreeItemId((WXHTREEITEM) TreeView_GetPrevSibling(GetHwnd(), (HTREEITEM) (WXHTREEITEM) item)); - return 0; -} + 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::GetFirstVisibleItem() const +wxTreeItemId wxTreeCtrl::GetNextVisible ( + const wxTreeItemId& rItem +) const { -// return wxTreeItemId((WXHTREEITEM) TreeView_GetFirstVisible(GetHwnd())); - return 0; -} + wxASSERT_MSG(IsVisible(rItem), wxT("The item you call GetNextVisible() for must be visible itself!")); -wxTreeItemId wxTreeCtrl::GetNextVisible(const wxTreeItemId& item) const -{ - wxASSERT_MSG( IsVisible(item), wxT("The item you call GetNextVisible() " - "for must be visible itself!")); + PMYRECORD pRecord = FindOS2TreeRecordByID ( GetHWND() + ,rItem.m_pItem + ); -// return wxTreeItemId((WXHTREEITEM) TreeView_GetNextVisible(GetHwnd(), (HTREEITEM) (WXHTREEITEM) item)); - return 0; -} + 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& item) const +wxTreeItemId wxTreeCtrl::GetPrevVisible ( + const wxTreeItemId& rItem +) const { - wxASSERT_MSG( IsVisible(item), wxT("The item you call GetPrevVisible() " - "for must be visible itself!")); + wxASSERT_MSG( IsVisible(rItem), wxT("The item you call GetPrevVisible() for must be visible itself!")); -// return wxTreeItemId((WXHTREEITEM) TreeView_GetPrevVisible(GetHwnd(), (HTREEITEM) (WXHTREEITEM) item)); - return 0; -} + 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 +// 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& item) const +bool wxTreeCtrl::IsItemChecked ( + const wxTreeItemId& rItem +) const { - // receive the desired information. -// TODO: -/* - wxTreeViewItem tvItem(item, TVIF_STATE, TVIS_STATEIMAGEMASK); - DoGetItem(&tvItem); + wxTreeViewItem vTvItem(rItem); - // state image indices are 1 based - return ((tvItem.state >> 12) - 1) == 1; -*/ - return FALSE; -} + DoGetItem(&vTvItem); + return (vTvItem.m_vRecord.flRecordAttr & CRA_SELECTED); +} // end of wxTreeCtrl::IsItemChecked -void wxTreeCtrl::SetItemCheck(const wxTreeItemId& item, bool check) +void wxTreeCtrl::SetItemCheck ( + const wxTreeItemId& rItem +, bool bCheck +) { - // receive the desired information. -// TODO: -/* - wxTreeViewItem tvItem(item, TVIF_STATE, TVIS_STATEIMAGEMASK); + wxTreeViewItem vTvItem(rItem); - // state images are one-based - tvItem.state = (check ? 2 : 1) << 12; + DoGetItem(&vTvItem); + ::WinSendMsg( GetHWND() + ,CM_SETRECORDEMPHASIS + ,MPFROMP(&vTvItem) + ,MPFROM2SHORT(TRUE, CRA_SELECTED) + ); + DoSetItem(&vTvItem); +} // end of wxTreeCtrl::SetItemCheck - DoSetItem(&tvItem); -*/ -} - -size_t wxTreeCtrl::GetSelections(wxArrayTreeItemIds& selections) const +size_t wxTreeCtrl::GetSelections ( + wxArrayTreeItemIds& raSelections +) const { - TraverseSelections selector(this, selections); - - return selections.GetCount(); -} + TraverseSelections vSelector( this + ,raSelections + ); + return vSelector.GetCount(); +} // end of wxTreeCtrl::GetSelections // ---------------------------------------------------------------------------- // Usual operations // ---------------------------------------------------------------------------- -wxTreeItemId wxTreeCtrl::DoInsertItem(const wxTreeItemId& parent, - wxTreeItemId hInsertAfter, - const wxString& text, - int image, int selectedImage, - wxTreeItemData *data) -{ -// TODO: -/* - TV_INSERTSTRUCT tvIns; - tvIns.hParent = (HTREEITEM) (WXHTREEITEM)parent; - tvIns.hInsertAfter = (HTREEITEM) (WXHTREEITEM) hInsertAfter; - - // this is how we insert the item as the first child: supply a NULL - // hInsertAfter - if ( !tvIns.hInsertAfter ) - { - tvIns.hInsertAfter = TVI_FIRST; - } - - UINT mask = 0; - if ( !text.IsEmpty() ) +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) { - mask |= TVIF_TEXT; - tvIns.item.pszText = (wxChar *)text.c_str(); // cast is ok - } - - if ( image != -1 ) - { - mask |= TVIF_IMAGE; - tvIns.item.iImage = image; - - if ( selectedImage == -1 ) - { - // take the same image for selected icon if not specified - selectedImage = image; - } - } - - if ( selectedImage != -1 ) - { - mask |= TVIF_SELECTEDIMAGE; - tvIns.item.iSelectedImage = selectedImage; + if (vInsertAfter.m_pItem == -1) + vInsert.pRecordOrder = (PRECORDCORE)CMA_END; + else + vInsert.pRecordOrder = (PRECORDCORE)CMA_FIRST; + vInsert.pRecordParent = NULL; } - - if ( data != NULL ) + else { - mask |= TVIF_PARAM; - tvIns.item.lParam = (LPARAM)data; + 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; } - - tvIns.item.mask = mask; - - HTREEITEM id = (HTREEITEM) TreeView_InsertItem(GetHwnd(), &tvIns); - if ( id == 0 ) + 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) { - wxLogLastError("TreeView_InsertItem"); + pRecord->m_ulUserData = (ULONG)pData; } - - if ( data != NULL ) + ::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 Win32 tree item handle - data->SetId((WXHTREEITEM)id); + // + // Associate the application tree item with PM tree item handle + // + pData->SetId((long)pRecord->m_ulItemId); } - - return wxTreeItemId((WXHTREEITEM)id); -*/ - return 0; -} - -// for compatibility only -wxTreeItemId wxTreeCtrl::InsertItem(const wxTreeItemId& parent, - const wxString& text, - int image, int selImage, - long insertAfter) -{ - return DoInsertItem(parent, (WXHTREEITEM)insertAfter, text, - image, selImage, NULL); -} - -wxTreeItemId wxTreeCtrl::AddRoot(const wxString& text, - int image, int selectedImage, - wxTreeItemData *data) -{ - return DoInsertItem(wxTreeItemId((WXHTREEITEM) 0), (WXHTREEITEM) 0, - text, image, selectedImage, data); -} - -wxTreeItemId wxTreeCtrl::PrependItem(const wxTreeItemId& parent, - const wxString& text, - int image, int selectedImage, - wxTreeItemData *data) -{ -// TODO: -/* - return DoInsertItem(parent, (WXHTREEITEM) TVI_FIRST, - text, image, selectedImage, data); -*/ - return 0; -} - -wxTreeItemId wxTreeCtrl::InsertItem(const wxTreeItemId& parent, - const wxTreeItemId& idPrevious, - const wxString& text, - int image, int selectedImage, - wxTreeItemData *data) -{ - return DoInsertItem(parent, idPrevious, text, image, selectedImage, data); -} - -wxTreeItemId wxTreeCtrl::AppendItem(const wxTreeItemId& parent, - const wxString& text, - int image, int selectedImage, - wxTreeItemData *data) -{ -// TODO: -/* - return DoInsertItem(parent, (WXHTREEITEM) TVI_LAST, - text, image, selectedImage, data); -*/ - return 0; -} - -void wxTreeCtrl::Delete(const wxTreeItemId& item) -{ -// TODO: -/* - if ( !TreeView_DeleteItem(GetHwnd(), (HTREEITEM)(WXHTREEITEM)item) ) + return wxTreeItemId((long)pRecord->m_ulItemId); +} + +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) { - wxLogLastError("TreeView_DeleteItem"); + delete (wxTreeItemAttr *)m_vAttrs.Delete((long)rItem.m_pItem); } -*/ -} + vEvent.SetEventType(vEventType); + HandleWindowEvent(vEvent); +} // end of wxTreeCtrl::Delete // delete all children (but don't delete the item itself) -void wxTreeCtrl::DeleteChildren(const wxTreeItemId& item) +void wxTreeCtrl::DeleteChildren ( + const wxTreeItemId& rItem +) { - long cookie; + long lCookie; + wxArrayLong aChildren; + wxTreeItemId vChild = GetFirstChild( rItem + ,lCookie + ); - wxArrayLong children; - wxTreeItemId child = GetFirstChild(item, cookie); - while ( child.IsOk() ) + while (vChild.IsOk()) { - children.Add((long)(WXHTREEITEM)child); - - child = GetNextChild(item, cookie); + aChildren.Add((long)(WXHTREEITEM)vChild); + vChild = GetNextChild( rItem + ,lCookie + ); } - size_t nCount = children.Count(); -// TODO: -/* - for ( size_t n = 0; n < nCount; n++ ) - { - if ( !TreeView_DeleteItem(GetHwnd(), (HTREEITEM)children[n]) ) - { - wxLogLastError("TreeView_DeleteItem"); - } - } -*/ -} + size_t nCount = aChildren.Count(); -void wxTreeCtrl::DeleteAllItems() -{ -// TODO: -/* - if ( !TreeView_DeleteAllItems(GetHwnd()) ) + for (size_t n = 0; n < nCount; n++) { - wxLogLastError("TreeView_DeleteAllItems"); + Delete(aChildren[n]); } -*/ -} - -void wxTreeCtrl::DoExpand(const wxTreeItemId& item, int flag) -{ -// TODO: -/* - wxASSERT_MSG( flag == TVE_COLLAPSE || - flag == (TVE_COLLAPSE | TVE_COLLAPSERESET) || - flag == TVE_EXPAND || - flag == TVE_TOGGLE, - wxT("Unknown flag in wxTreeCtrl::DoExpand") ); - - // TreeView_Expand doesn't send TVN_ITEMEXPAND(ING) messages, so we must - // emulate them. This behaviour has changed slightly with comctl32.dll - // v 4.70 - now it does send them but only the first time. To maintain - // compatible behaviour and also in order to not have surprises with the - // future versions, don't rely on this and still do everything ourselves. - // To avoid that the messages be sent twice when the item is expanded for - // the first time we must clear TVIS_EXPANDEDONCE style manually. - - wxTreeViewItem tvItem(item, TVIF_STATE, TVIS_EXPANDEDONCE); - tvItem.state = 0; - DoSetItem(&tvItem); - - if ( TreeView_Expand(GetHwnd(), (HTREEITEM) (WXHTREEITEM) item, flag) != 0 ) +} // 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) { - wxTreeEvent event(wxEVT_NULL, m_windowId); - event.m_item = item; + case wxTREE_EXPAND_EXPAND: + ::WinSendMsg( GetHWND() + ,CM_EXPANDTREE + ,MPFROMP(pRecord) + ,NULL + ); + break; - bool isExpanded = IsExpanded(item); + case wxTREE_EXPAND_COLLAPSE: + ::WinSendMsg( GetHWND() + ,CM_COLLAPSETREE + ,MPFROMP(pRecord) + ,NULL + ); + break; - event.SetEventObject(this); + case wxTREE_EXPAND_COLLAPSE_RESET: + ::WinSendMsg( GetHWND() + ,CM_COLLAPSETREE + ,MPFROMP(pRecord) + ,NULL + ); + DeleteChildren(rItem); + break; - // FIXME return value of {EXPAND|COLLAPS}ING event handler is discarded - event.SetEventType(g_events[isExpanded][TRUE]); - GetEventHandler()->ProcessEvent(event); + 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; - event.SetEventType(g_events[isExpanded][FALSE]); - GetEventHandler()->ProcessEvent(event); } - //else: change didn't took place, so do nothing at all -*/ -} - -void wxTreeCtrl::Expand(const wxTreeItemId& item) -{ -// DoExpand(item, TVE_EXPAND); -} +} // end of wxTreeCtrl::DoExpand -void wxTreeCtrl::Collapse(const wxTreeItemId& item) +void wxTreeCtrl::Expand ( + const wxTreeItemId& rItem +) { -// DoExpand(item, TVE_COLLAPSE); -} + DoExpand( rItem + ,wxTREE_EXPAND_EXPAND + ); +} // end of wxTreeCtrl::Expand -void wxTreeCtrl::CollapseAndReset(const wxTreeItemId& item) +void wxTreeCtrl::Collapse ( + const wxTreeItemId& rItem +) { -// DoExpand(item, TVE_COLLAPSE | TVE_COLLAPSERESET); -} + DoExpand( rItem + ,wxTREE_EXPAND_COLLAPSE + ); +} // end of wxTreeCtrl::Collapse -void wxTreeCtrl::Toggle(const wxTreeItemId& item) +void wxTreeCtrl::CollapseAndReset ( + const wxTreeItemId& rItem +) { -// DoExpand(item, TVE_TOGGLE); -} + DoExpand( rItem + ,wxTREE_EXPAND_COLLAPSE_RESET + ); +} // end of wxTreeCtrl::CollapseAndReset -void wxTreeCtrl::ExpandItem(const wxTreeItemId& item, int action) +void wxTreeCtrl::Toggle ( + const wxTreeItemId& rItem +) { -// DoExpand(item, action); -} + DoExpand( rItem + ,wxTREE_EXPAND_TOGGLE + ); +} // end of wxTreeCtrl::Toggle -void wxTreeCtrl::Unselect() +void wxTreeCtrl::Unselect () { - wxASSERT_MSG( !(m_windowStyle & wxTR_MULTIPLE), wxT("doesn't make sense") ); + wxASSERT_MSG( !(m_windowStyle & wxTR_MULTIPLE), + wxT("doesn't make sense, may be you want UnselectAll()?") ); - // just remove the selection -// SelectItem(wxTreeItemId((WXHTREEITEM) 0)); -} + // + // Just remove the selection + // + SelectItem(wxTreeItemId((long)0)); +} // end of wxTreeCtrl::Unselect -void wxTreeCtrl::UnselectAll() +void wxTreeCtrl::UnselectAll () { - if ( m_windowStyle & wxTR_MULTIPLE ) + if (m_windowStyle & wxTR_MULTIPLE) { - wxArrayTreeItemIds selections; - size_t count = GetSelections(selections); - for ( size_t n = 0; n < count; n++ ) + wxArrayTreeItemIds aSelections; + size_t nCount = GetSelections(aSelections); + + for (size_t n = 0; n < nCount; n++) { - SetItemCheck(selections[n], FALSE); + SetItemCheck( aSelections[n] + ,false + ); } } else { - // just remove the selection + // + // Just remove the selection + // Unselect(); } -} - -void wxTreeCtrl::SelectItem(const wxTreeItemId& item) -{ - if ( m_windowStyle & wxTR_MULTIPLE ) - { - // selecting the item means checking it - SetItemCheck(item); - } - else - { - // inspite of the docs (MSDN Jan 99 edition), we don't seem to receive - // the notification from the control (i.e. TVN_SELCHANG{ED|ING}), so - // send them ourselves - - wxTreeEvent event(wxEVT_NULL, m_windowId); - event.m_item = item; - event.SetEventObject(this); - - event.SetEventType(wxEVT_COMMAND_TREE_SEL_CHANGING); -// TODO: -/* - if ( !GetEventHandler()->ProcessEvent(event) || event.IsAllowed() ) - { - if ( !TreeView_SelectItem(GetHwnd(), (HTREEITEM) (WXHTREEITEM) item) ) - { - wxLogLastError("TreeView_SelectItem"); - } - else - { - event.SetEventType(wxEVT_COMMAND_TREE_SEL_CHANGED); - (void)GetEventHandler()->ProcessEvent(event); - } - } - //else: program vetoed the change -*/ - } -} - -void wxTreeCtrl::EnsureVisible(const wxTreeItemId& item) -{ - // no error return -// TreeView_EnsureVisible(GetHwnd(), (HTREEITEM) (WXHTREEITEM) item); -} - -void wxTreeCtrl::ScrollTo(const wxTreeItemId& item) -{ -// TODO: -/* - if ( !TreeView_SelectSetFirstVisible(GetHwnd(), (HTREEITEM) (WXHTREEITEM) item) ) - { - wxLogLastError("TreeView_SelectSetFirstVisible"); - } -*/ -} - -wxTextCtrl* wxTreeCtrl::GetEditControl() const -{ - return m_textCtrl; -} - -void wxTreeCtrl::DeleteTextCtrl() -{ - if ( m_textCtrl ) - { - m_textCtrl->UnsubclassWin(); - m_textCtrl->SetHWND(0); - delete m_textCtrl; - m_textCtrl = NULL; - } -} - -wxTextCtrl* wxTreeCtrl::EditLabel(const wxTreeItemId& item, - wxClassInfo* textControlClass) -{ - wxASSERT( textControlClass->IsKindOf(CLASSINFO(wxTextCtrl)) ); - -// TODO: -/* - HWND hWnd = (HWND) TreeView_EditLabel(GetHwnd(), (HTREEITEM) (WXHTREEITEM) item); - - // this is not an error - the TVN_BEGINLABELEDIT handler might have - // returned FALSE - if ( !hWnd ) - { - return NULL; - } - - DeleteTextCtrl(); - - m_textCtrl = (wxTextCtrl *)textControlClass->CreateObject(); - m_textCtrl->SetHWND((WXHWND)hWnd); - m_textCtrl->SubclassWin((WXHWND)hWnd); -*/ - return m_textCtrl; -} +} // 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& item, bool discardChanges) -{ -// TreeView_EndEditLabelNow(GetHwnd(), discardChanges); - - DeleteTextCtrl(); -} - -wxTreeItemId wxTreeCtrl::HitTest(const wxPoint& point, int& flags) -{ -// TODO: -/* - TV_HITTESTINFO hitTestInfo; - hitTestInfo.pt.x = (int)point.x; - hitTestInfo.pt.y = (int)point.y; - - TreeView_HitTest(GetHwnd(), &hitTestInfo); - - flags = 0; - - // avoid repetition - #define TRANSLATE_FLAG(flag) if ( hitTestInfo.flags & TVHT_##flag ) \ - flags |= wxTREE_HITTEST_##flag - - TRANSLATE_FLAG(ABOVE); - TRANSLATE_FLAG(BELOW); - TRANSLATE_FLAG(NOWHERE); - TRANSLATE_FLAG(ONITEMBUTTON); - TRANSLATE_FLAG(ONITEMICON); - TRANSLATE_FLAG(ONITEMINDENT); - TRANSLATE_FLAG(ONITEMLABEL); - TRANSLATE_FLAG(ONITEMRIGHT); - TRANSLATE_FLAG(ONITEMSTATEICON); - TRANSLATE_FLAG(TOLEFT); - TRANSLATE_FLAG(TORIGHT); - - #undef TRANSLATE_FLAG - - return wxTreeItemId((WXHTREEITEM) hitTestInfo.hItem); -*/ - return 0; -} - -bool wxTreeCtrl::GetBoundingRect(const wxTreeItemId& item, - wxRect& rect, - bool textOnly) const -{ -// TODO: -/* - RECT rc; - if ( TreeView_GetItemRect(GetHwnd(), (HTREEITEM)(WXHTREEITEM)item, - &rc, textOnly) ) - { - rect = wxRect(wxPoint(rc.left, rc.top), wxPoint(rc.right, rc.bottom)); - - return TRUE; - } +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 - { - // couldn't retrieve rect: for example, item isn't visible - return FALSE; - } -*/ - return FALSE; -} + 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 // ---------------------------------------------------------------------------- -static int TreeView_CompareCallback(wxTreeItemData *pItem1, - wxTreeItemData *pItem2, - wxTreeCtrl *tree) +SHORT EXPENTRY InternalDataCompareTreeFunc ( + PMYRECORD p1 +, PMYRECORD p2 +, PVOID pStorage +) { - wxCHECK_MSG( pItem1 && pItem2, 0, + wxCHECK_MSG( p1 && p2, 0, wxT("sorting tree without data doesn't make sense") ); - return tree->OnCompareItems(pItem1->GetId(), pItem2->GetId()); -} + wxTreeCtrl* pTree = (wxTreeCtrl*)pStorage; -int wxTreeCtrl::OnCompareItems(const wxTreeItemId& item1, - const wxTreeItemId& item2) + 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(item1), GetItemText(item2)); -} + return wxStrcmp( GetItemText(rItem1) + ,GetItemText(rItem2) + ); +} // end of wxTreeCtrl::OnCompareItems -void wxTreeCtrl::SortChildren(const wxTreeItemId& item) +void wxTreeCtrl::SortChildren ( + const wxTreeItemId& rItem +) { - // rely on the fact that TreeView_SortChildren does the same thing as our - // default behaviour, i.e. sorts items alphabetically and so call it - // directly if we're not in derived class (much more efficient!) -// TODO: -/* - if ( GetClassInfo() == CLASSINFO(wxTreeCtrl) ) - { - TreeView_SortChildren(GetHwnd(), (HTREEITEM)(WXHTREEITEM)item, 0); - } - else - { - TV_SORTCB tvSort; - tvSort.hParent = (HTREEITEM)(WXHTREEITEM)item; - tvSort.lpfnCompare = (PFNTVCOMPARE)TreeView_CompareCallback; - tvSort.lParam = (LPARAM)this; - TreeView_SortChildrenCB(GetHwnd(), &tvSort, 0); - } -*/ -} + ::WinSendMsg( GetHWND() + ,CM_SORTRECORD + ,(PFN)InternalDataCompareTreeFunc + ,NULL + ); +} // end of wxTreeCtrl::SortChildren // ---------------------------------------------------------------------------- // implementation // ---------------------------------------------------------------------------- -bool wxTreeCtrl::OS2Command(WXUINT cmd, WXWORD id) +bool wxTreeCtrl::OS2Command ( + WXUINT uCmd +, WXWORD wId +) { -// TODO: -/* - if ( cmd == EN_UPDATE ) + if (uCmd == CN_ENDEDIT) { - wxCommandEvent event(wxEVT_COMMAND_TEXT_UPDATED, id); - event.SetEventObject( this ); - ProcessCommand(event); + wxCommandEvent vEvent( wxEVT_COMMAND_TEXT_UPDATED + ,wId + ); + + vEvent.SetEventObject( this ); + ProcessCommand(vEvent); + return true; } - else if ( cmd == EN_KILLFOCUS ) + else if (uCmd == CN_KILLFOCUS) { - wxCommandEvent event(wxEVT_KILL_FOCUS, id); - event.SetEventObject( this ); - ProcessCommand(event); + wxCommandEvent vEvent( wxEVT_KILL_FOCUS + ,wId + ); + vEvent.SetEventObject( this ); + ProcessCommand(vEvent); + return true; } else - { - // nothing done - return FALSE; - } - - // command processed - return TRUE; -*/ - return FALSE; -} + return false; +} // end of wxTreeCtrl::OS2Command -// process WM_NOTIFY Windows message -bool wxTreeCtrl::OS2OnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) -{ -// TODO: -/* - wxTreeEvent event(wxEVT_NULL, m_windowId); - wxEventType eventType = wxEVT_NULL; - NMHDR *hdr = (NMHDR *)lParam; - - switch ( hdr->code ) - { - case NM_RCLICK: - { - if ( wxControl::MSWOnNotify(idCtrl, lParam, result) ) - return TRUE; - - TV_HITTESTINFO tvhti; - ::GetCursorPos(&(tvhti.pt)); - ::ScreenToClient(GetHwnd(),&(tvhti.pt)); - if ( TreeView_HitTest(GetHwnd(),&tvhti) ) - { - if( tvhti.flags & TVHT_ONITEM ) - { - event.m_item = (WXHTREEITEM) tvhti.hItem; - eventType=wxEVT_COMMAND_TREE_ITEM_RIGHT_CLICK; - } - } - break; - } - - case TVN_BEGINDRAG: - eventType = wxEVT_COMMAND_TREE_BEGIN_DRAG; - // fall through - - case TVN_BEGINRDRAG: - { - if ( eventType == wxEVT_NULL ) - eventType = wxEVT_COMMAND_TREE_BEGIN_RDRAG; - //else: left drag, already set above - - NM_TREEVIEW *tv = (NM_TREEVIEW *)lParam; - - event.m_item = (WXHTREEITEM) tv->itemNew.hItem; - event.m_pointDrag = wxPoint(tv->ptDrag.x, tv->ptDrag.y); - break; - } - - case TVN_BEGINLABELEDIT: - { - eventType = wxEVT_COMMAND_TREE_BEGIN_LABEL_EDIT; - TV_DISPINFO *info = (TV_DISPINFO *)lParam; - - event.m_item = (WXHTREEITEM) info->item.hItem; - event.m_label = info->item.pszText; - break; - } - - case TVN_DELETEITEM: - { - eventType = wxEVT_COMMAND_TREE_DELETE_ITEM; - NM_TREEVIEW *tv = (NM_TREEVIEW *)lParam; - - event.m_item = (WXHTREEITEM) tv->itemOld.hItem; - break; - } - - case TVN_ENDLABELEDIT: - { - eventType = wxEVT_COMMAND_TREE_END_LABEL_EDIT; - TV_DISPINFO *info = (TV_DISPINFO *)lParam; - - event.m_item = (WXHTREEITEM)info->item.hItem; - event.m_label = info->item.pszText; - break; - } - - case TVN_GETDISPINFO: - eventType = wxEVT_COMMAND_TREE_GET_INFO; - // fall through - - case TVN_SETDISPINFO: - { - if ( eventType == wxEVT_NULL ) - eventType = wxEVT_COMMAND_TREE_SET_INFO; - //else: get, already set above - - TV_DISPINFO *info = (TV_DISPINFO *)lParam; - - event.m_item = (WXHTREEITEM) info->item.hItem; - break; - } - - case TVN_ITEMEXPANDING: - event.m_code = FALSE; - // fall through - - case TVN_ITEMEXPANDED: - { - NM_TREEVIEW* tv = (NM_TREEVIEW*)lParam; - - bool expand = FALSE; - switch ( tv->action ) - { - case TVE_EXPAND: - expand = TRUE; - break; - - case TVE_COLLAPSE: - expand = FALSE; - break; - - default: - wxLogDebug(wxT("unexpected code %d in TVN_ITEMEXPAND " - "message"), tv->action); - } - - bool ing = ((int)hdr->code == TVN_ITEMEXPANDING); - eventType = g_events[expand][ing]; - - event.m_item = (WXHTREEITEM) tv->itemNew.hItem; - break; - } - - case TVN_KEYDOWN: - { - eventType = wxEVT_COMMAND_TREE_KEY_DOWN; - TV_KEYDOWN *info = (TV_KEYDOWN *)lParam; - - event.m_code = wxCharCodeMSWToWX(info->wVKey); - - // a separate event for this case - if ( info->wVKey == VK_SPACE || info->wVKey == VK_RETURN ) - { - wxTreeEvent event2(wxEVT_COMMAND_TREE_ITEM_ACTIVATED, - m_windowId); - event2.SetEventObject(this); - - GetEventHandler()->ProcessEvent(event2); - } - break; - } - - case TVN_SELCHANGED: - eventType = wxEVT_COMMAND_TREE_SEL_CHANGED; - // fall through - - case TVN_SELCHANGING: - { - if ( eventType == wxEVT_NULL ) - eventType = wxEVT_COMMAND_TREE_SEL_CHANGING; - //else: already set above - - NM_TREEVIEW* tv = (NM_TREEVIEW *)lParam; - - event.m_item = (WXHTREEITEM) tv->itemNew.hItem; - event.m_itemOld = (WXHTREEITEM) tv->itemOld.hItem; - break; - } - - default: - return wxControl::MSWOnNotify(idCtrl, lParam, result); - } - - event.SetEventObject(this); - event.SetEventType(eventType); - - bool processed = GetEventHandler()->ProcessEvent(event); - - // post processing - switch ( hdr->code ) +// +// 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 TVN_DELETEITEM: - { - // NB: we might process this message using wxWindows event - // tables, but due to overhead of wxWin event system we - // prefer to do it here ourself (otherwise deleting a tree - // with many items is just too slow) - NM_TREEVIEW* tv = (NM_TREEVIEW *)lParam; - - wxTreeItemId item = event.m_item; - if ( HasIndirectData(item) ) - { - wxTreeItemIndirectData *data = (wxTreeItemIndirectData *) - tv->itemOld.lParam; - delete data; // can't be NULL here - - m_itemsWithIndirectData.Remove(item); - } - else - { - wxTreeItemData *data = (wxTreeItemData *)tv->itemOld.lParam; - delete data; // may be NULL, ok - } - - processed = TRUE; // Make sure we don't get called twice - } - break; - - case TVN_BEGINLABELEDIT: - // return TRUE to cancel label editing - *result = !event.IsAllowed(); - break; - - case TVN_ENDLABELEDIT: - // return TRUE to set the label to the new string - *result = event.IsAllowed(); - - // ensure that we don't have the text ctrl which is going to be - // deleted any more - DeleteTextCtrl(); - break; - - case TVN_SELCHANGING: - case TVN_ITEMEXPANDING: - // return TRUE to prevent the action from happening - *result = !event.IsAllowed(); - break; - - case TVN_GETDISPINFO: - // NB: so far the user can't set the image himself anyhow, so do it - // anyway - but this may change later - if ( 1 // !processed && ) + case WM_CONTROL: + switch(SHORT2FROMMP(wParam)) { - wxTreeItemId item = event.m_item; - TV_DISPINFO *info = (TV_DISPINFO *)lParam; - if ( info->item.mask & TVIF_IMAGE ) - { - info->item.iImage = - DoGetItemImageFromData - ( - item, - IsExpanded(item) ? wxTreeItemIcon_Expanded - : wxTreeItemIcon_Normal - ); - } - if ( info->item.mask & TVIF_SELECTEDIMAGE ) - { - info->item.iSelectedImage = - DoGetItemImageFromData - ( - item, - IsExpanded(item) ? wxTreeItemIcon_SelectedExpanded - : wxTreeItemIcon_Selected - ); - } + 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 = HandleWindowEvent(vEvent); break; - - //default: - // for the other messages the return value is ignored and there is - // nothing special to do } - - return processed; -*/ - return FALSE; -} - -// ---------------------------------------------------------------------------- -// Tree event -// ---------------------------------------------------------------------------- - -IMPLEMENT_DYNAMIC_CLASS(wxTreeEvent, wxNotifyEvent) - -wxTreeEvent::wxTreeEvent(wxEventType commandType, int id) - : wxNotifyEvent(commandType, id) -{ - m_code = 0; - m_itemOld = 0; -} - + if (!bProcessed) + mRc = wxControl::OS2WindowProc( uMsg + ,wParam + ,lParam + ); + return mRc; +} // end of wxTreeCtrl::OS2WindowProc + +#endif // wxUSE_TREECTRL