]> git.saurik.com Git - wxWidgets.git/blobdiff - src/msw/treectrl.cpp
Cured some Motif bugs
[wxWidgets.git] / src / msw / treectrl.cpp
index 42dd352347710e1b9859aaea4150c941228a140e..11547d87e62d273e02f0ade3f89a1c41efa766ea 100644 (file)
 #endif
 
 #ifndef WX_PRECOMP
-    #include "wx.h"
+    #include "wx/wx.h"
 #endif
 
 #if defined(__WIN95__)
 
 #include "wx/log.h"
+#include "wx/dynarray.h"
 #include "wx/imaglist.h"
+#include "wx/msw/treectrl.h"
 
 #include "wx/msw/private.h"
 
-#ifndef __GNUWIN32__
+#ifdef __GNUWIN32__
+#include "wx/msw/gnuwin32/extra.h"
+#endif
+
+#if (defined(__WIN95__) && !defined(__GNUWIN32__)) || defined(__TWIN32__)
     #include <commctrl.h>
 #endif
 
@@ -54,7 +60,9 @@
 #undef GetNextSibling
 #endif
 
-#include "wx/msw/treectrl.h"
+#ifdef GetClassInfo
+#undef GetClassInfo
+#endif
 
 // Bug in headers, sometimes
 #ifndef TVIS_FOCUSED
@@ -254,6 +262,31 @@ void wxTreeCtrl::SetStateImageList(wxImageList *imageList)
     SetAnyImageList(m_imageListState = imageList, TVSIL_STATE);
 }
 
+size_t wxTreeCtrl::GetChildrenCount(const wxTreeItemId& item, bool recursively)
+{
+    long cookie;
+
+    size_t result = 0;
+
+    wxArrayLong children;
+    wxTreeItemId child = GetFirstChild(item, cookie);
+    while ( child.IsOk() )
+    {
+        if ( recursively )
+        {
+            // recursive call
+            result += GetChildrenCount(child, TRUE);
+        }
+
+        // add the child to the result in any case
+        result++;
+
+        child = GetNextChild(item, cookie);
+    }
+
+    return result;
+}
+
 // ----------------------------------------------------------------------------
 // Item access
 // ----------------------------------------------------------------------------
@@ -421,12 +454,29 @@ wxTreeItemId wxTreeCtrl::GetFirstChild(const wxTreeItemId& item,
 wxTreeItemId wxTreeCtrl::GetNextChild(const wxTreeItemId& WXUNUSED(item),
                                       long& _cookie) const
 {
-    wxTreeItemId l=wxTreeItemId((WXHTREEITEM) TreeView_GetNextSibling(wxhWnd,
-                (HTREEITEM) (WXHTREEITEM)_cookie));
-    _cookie=(long)l;
+    wxTreeItemId l = wxTreeItemId((WXHTREEITEM)TreeView_GetNextSibling(wxhWnd,
+                                   (HTREEITEM)(WXHTREEITEM)_cookie));
+    _cookie = (long)l;
+
     return l;
 }
 
+wxTreeItemId wxTreeCtrl::GetLastChild(const wxTreeItemId& item) const
+{
+    // can this be done more efficiently?
+    long cookie;
+
+    wxTreeItemId childLast,
+    child = GetFirstChild(item, cookie);
+    while ( child.IsOk() )
+    {
+        childLast = child;
+        child = GetNextChild(item, cookie);
+    }
+
+    return childLast;
+}
+
 wxTreeItemId wxTreeCtrl::GetNextSibling(const wxTreeItemId& item) const
 {
     return wxTreeItemId((WXHTREEITEM) TreeView_GetNextSibling(wxhWnd, (HTREEITEM) (WXHTREEITEM) item));
@@ -572,6 +622,30 @@ void wxTreeCtrl::Delete(const wxTreeItemId& item)
     }
 }
 
+// delete all children (but don't delete the item itself)
+void wxTreeCtrl::DeleteChildren(const wxTreeItemId& item)
+{
+    long cookie;
+
+    wxArrayLong children;
+    wxTreeItemId child = GetFirstChild(item, cookie);
+    while ( child.IsOk() )
+    {
+        children.Add((long)(WXHTREEITEM)child);
+
+        child = GetNextChild(item, cookie);
+    }
+
+    size_t nCount = children.Count();
+    for ( size_t n = 0; n < nCount; n++ )
+    {
+        if ( !TreeView_DeleteItem(wxhWnd, (HTREEITEM)children[n]) )
+        {
+            wxLogLastError("TreeView_DeleteItem");
+        }
+    }
+}
+
 void wxTreeCtrl::DeleteAllItems()
 {
     if ( !TreeView_DeleteAllItems(wxhWnd) )
@@ -736,6 +810,36 @@ wxTreeItemId wxTreeCtrl::HitTest(const wxPoint& point, int& flags)
     return wxTreeItemId((WXHTREEITEM) hitTestInfo.hItem);
 }
 
+bool wxTreeCtrl::GetBoundingRect(const wxTreeItemId& item,
+                                 wxRect& rect,
+                                 bool textOnly) const
+{
+    RECT rc;
+    if ( TreeView_GetItemRect(wxhWnd, (HTREEITEM)(WXHTREEITEM)item,
+                              &rc, textOnly) )
+    {
+        rect = wxRect(wxPoint(rc.left, rc.top), wxPoint(rc.right, rc.bottom));
+
+        return TRUE;
+    }
+    else
+    {
+        // couldn't retrieve rect: for example, item isn't visible
+        return FALSE;
+    }
+}
+
+// ----------------------------------------------------------------------------
+// sorting stuff
+// ----------------------------------------------------------------------------
+
+static int CALLBACK TreeView_CompareCallback(wxTreeItemData *pItem1,
+                                             wxTreeItemData *pItem2,
+                                             wxTreeCtrl *tree)
+{
+    return tree->OnCompareItems(pItem1->GetId(), pItem2->GetId());
+}
+
 int wxTreeCtrl::OnCompareItems(const wxTreeItemId& item1,
                                const wxTreeItemId& item2)
 {
@@ -745,34 +849,22 @@ int wxTreeCtrl::OnCompareItems(const wxTreeItemId& item1,
 void wxTreeCtrl::SortChildren(const wxTreeItemId& item)
 {
     // rely on the fact that TreeView_SortChildren does the same thing as our
-    // default behaviour, i.e. sorts items alphabetically
-    if ( wxIS_KIND_OF(this, wxTreeCtrl) )
+    // default behaviour, i.e. sorts items alphabetically and so call it
+    // directly if we're not in derived class (much more efficient!)
+    if ( GetClassInfo() == CLASSINFO(wxTreeCtrl) )
     {
-        TreeView_SortChildren(wxhWnd, (HTREEITEM) (WXHTREEITEM) item, 0);
+        TreeView_SortChildren(wxhWnd, (HTREEITEM)(WXHTREEITEM)item, 0);
     }
     else
     {
-        // TODO: use TreeView_SortChildrenCB
-        wxFAIL_MSG("wxTreeCtrl::SortChildren not implemented");
+        TV_SORTCB tvSort;
+        tvSort.hParent = (HTREEITEM)(WXHTREEITEM)item;
+        tvSort.lpfnCompare = (PFNTVCOMPARE)TreeView_CompareCallback;
+        tvSort.lParam = (LPARAM)this;
+        TreeView_SortChildrenCB(wxhWnd, &tvSort, 0 /* reserved */);
     }
 }
 
-size_t wxTreeCtrl::GetChildrenCount(const wxTreeItemId& item, bool recursively)
-{
-    // TODO
-    wxFAIL_MSG("wxTreeCtrl::GetChildrenCount not implemented");
-
-    return 0;
-}
-
-// delete all children (but don't delete the item itself)
-// NB: this won't send wxEVT_COMMAND_TREE_ITEM_DELETED events
-void wxTreeCtrl::DeleteChildren(const wxTreeItemId& item)
-{
-    // TODO
-    wxFAIL_MSG("wxTreeCtrl::DeleteChildren not implemented");
-}
-
 // ----------------------------------------------------------------------------
 // implementation
 // ----------------------------------------------------------------------------
@@ -907,6 +999,16 @@ bool wxTreeCtrl::MSWNotify(WXWPARAM wParam, WXLPARAM lParam, WXLPARAM *result)
                 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;
             }