]> git.saurik.com Git - wxWidgets.git/blobdiff - src/msw/treectrl.cpp
Style listbox now shows current style
[wxWidgets.git] / src / msw / treectrl.cpp
index 932ae78390c8fec95e81371a87e1847adc711ee0..8a7ce1352577325c7e7165d7d094980877b2c32c 100644 (file)
@@ -29,6 +29,8 @@
 #include "wx/treectrl.h"
 
 #ifndef WX_PRECOMP
 #include "wx/treectrl.h"
 
 #ifndef WX_PRECOMP
+    #include "wx/msw/wrapcctl.h" // include <commctrl.h> "properly"
+    #include "wx/msw/missing.h"
     #include "wx/dynarray.h"
     #include "wx/log.h"
     #include "wx/app.h"
     #include "wx/dynarray.h"
     #include "wx/log.h"
     #include "wx/app.h"
 
 #include "wx/msw/private.h"
 
 
 #include "wx/msw/private.h"
 
-// include <commctrl.h> "properly"
-#include "wx/msw/wrapcctl.h"
-
-#include "wx/msw/missing.h"
-
 // Set this to 1 to be _absolutely_ sure that repainting will work for all
 // comctl32.dll versions
 #define wxUSE_COMCTL32_SAFELY 0
 // Set this to 1 to be _absolutely_ sure that repainting will work for all
 // comctl32.dll versions
 #define wxUSE_COMCTL32_SAFELY 0
@@ -293,9 +290,9 @@ class wxTreeItemParam
 {
 public:
     wxTreeItemParam()
 {
 public:
     wxTreeItemParam()
-        : m_item(NULL),
-          m_data(NULL)
     {
     {
+        m_data = NULL;
+
         for ( size_t n = 0; n < WXSIZEOF(m_images); n++ )
         {
             m_images[n] = -1;
         for ( size_t n = 0; n < WXSIZEOF(m_images); n++ )
         {
             m_images[n] = -1;
@@ -451,16 +448,18 @@ public:
 
     virtual bool OnVisit(const wxTreeItemId& item)
     {
 
     virtual bool OnVisit(const wxTreeItemId& item)
     {
+        const wxTreeCtrl * const tree = GetTree();
+
         // can't visit a virtual node.
         // can't visit a virtual node.
-        if ( (GetTree()->GetRootItem() == item) && (GetTree()->GetWindowStyle() & wxTR_HIDE_ROOT))
+        if ( (tree->GetRootItem() == item) && tree->HasFlag(wxTR_HIDE_ROOT) )
         {
             return true;
         }
 
 #if wxUSE_CHECKBOXES_IN_MULTI_SEL_TREE
         {
             return true;
         }
 
 #if wxUSE_CHECKBOXES_IN_MULTI_SEL_TREE
-        if ( GetTree()->IsItemChecked(item) )
+        if ( tree->IsItemChecked(item) )
 #else
 #else
-        if ( ::IsItemSelected(GetHwndOf(GetTree()), HITEM(item)) )
+        if ( ::IsItemSelected(GetHwndOf(tree), HITEM(item)) )
 #endif
         {
             m_selections.Add(item);
 #endif
         {
             m_selections.Add(item);
@@ -933,6 +932,11 @@ bool wxTreeCtrl::SetForegroundColour(const wxColour &colour)
 // Item access
 // ----------------------------------------------------------------------------
 
 // Item access
 // ----------------------------------------------------------------------------
 
+bool wxTreeCtrl::IsHiddenRoot(const wxTreeItemId& item) const
+{
+    return HITEM(item) == TVI_ROOT && HasFlag(wxTR_HIDE_ROOT);
+}
+
 wxString wxTreeCtrl::GetItemText(const wxTreeItemId& item) const
 {
     wxCHECK_MSG( item.IsOk(), wxEmptyString, wxT("invalid tree item") );
 wxString wxTreeCtrl::GetItemText(const wxTreeItemId& item) const
 {
     wxCHECK_MSG( item.IsOk(), wxEmptyString, wxT("invalid tree item") );
@@ -982,7 +986,7 @@ int wxTreeCtrl::GetItemImage(const wxTreeItemId& item,
 {
     wxCHECK_MSG( item.IsOk(), -1, wxT("invalid tree item") );
 
 {
     wxCHECK_MSG( item.IsOk(), -1, wxT("invalid tree item") );
 
-    if ( (HITEM(item) == TVI_ROOT) && (m_windowStyle & wxTR_HIDE_ROOT) )
+    if ( IsHiddenRoot(item) )
     {
         // no images for hidden root item
         return -1;
     {
         // no images for hidden root item
         return -1;
@@ -1002,7 +1006,7 @@ void wxTreeCtrl::SetItemImage(const wxTreeItemId& item, int image,
                  wxT("invalid image index"));
 
 
                  wxT("invalid image index"));
 
 
-    if ( (HITEM(item) == TVI_ROOT) && (m_windowStyle & wxTR_HIDE_ROOT) )
+    if ( IsHiddenRoot(item) )
     {
         // no images for hidden root item
         return;
     {
         // no images for hidden root item
         return;
@@ -1013,6 +1017,8 @@ void wxTreeCtrl::SetItemImage(const wxTreeItemId& item, int image,
         return;
 
     data->SetImage(image, which);
         return;
 
     data->SetImage(image, which);
+
+    RefreshItem(item);
 }
 
 wxTreeItemParam *wxTreeCtrl::GetItemParam(const wxTreeItemId& item) const
 }
 
 wxTreeItemParam *wxTreeCtrl::GetItemParam(const wxTreeItemId& item) const
@@ -1562,7 +1568,7 @@ wxTreeItemId wxTreeCtrl::AddRoot(const wxString& text,
                                  wxTreeItemData *data)
 {
 
                                  wxTreeItemData *data)
 {
 
-    if ( m_windowStyle & wxTR_HIDE_ROOT )
+    if ( HasFlag(wxTR_HIDE_ROOT) )
     {
         // create a virtual root item, the parent for all the others
         wxTreeItemParam *param = new wxTreeItemParam;
     {
         // create a virtual root item, the parent for all the others
         wxTreeItemParam *param = new wxTreeItemParam;
@@ -1667,7 +1673,7 @@ void wxTreeCtrl::DoExpand(const wxTreeItemId& item, int flag)
                   wxT("Unknown flag in wxTreeCtrl::DoExpand") );
 
     // A hidden root can be neither expanded nor collapsed.
                   wxT("Unknown flag in wxTreeCtrl::DoExpand") );
 
     // A hidden root can be neither expanded nor collapsed.
-    wxCHECK_RET( !(m_windowStyle & wxTR_HIDE_ROOT) || (HITEM(item) != TVI_ROOT),
+    wxCHECK_RET( !IsHiddenRoot(item),
                  wxT("Can't expand/collapse hidden root node!") );
 
     // TreeView_Expand doesn't send TVN_ITEMEXPAND(ING) messages, so we must
                  wxT("Can't expand/collapse hidden root node!") );
 
     // TreeView_Expand doesn't send TVN_ITEMEXPAND(ING) messages, so we must
@@ -1684,16 +1690,12 @@ void wxTreeCtrl::DoExpand(const wxTreeItemId& item, int flag)
 
     if ( TreeView_Expand(GetHwnd(), HITEM(item), flag) != 0 )
     {
 
     if ( TreeView_Expand(GetHwnd(), HITEM(item), flag) != 0 )
     {
-        wxTreeEvent event(wxEVT_NULL, m_windowId);
-        event.m_item = item;
-        event.SetEventObject(this);
-
         // note that the {EXPAND|COLLAPS}ING event is sent by TreeView_Expand()
         // itself
         // note that the {EXPAND|COLLAPS}ING event is sent by TreeView_Expand()
         // itself
-        event.SetEventType(gs_expandEvents[IsExpanded(item) ? IDX_EXPAND
-                                                            : IDX_COLLAPSE]
-                                          [IDX_DONE]);
-
+        wxTreeEvent event(gs_expandEvents[IsExpanded(item) ? IDX_EXPAND
+                                                           : IDX_COLLAPSE]
+                                         [IDX_DONE],
+                           this, item);
         (void)GetEventHandler()->ProcessEvent(event);
     }
     //else: change didn't took place, so do nothing at all
         (void)GetEventHandler()->ProcessEvent(event);
     }
     //else: change didn't took place, so do nothing at all
@@ -1781,11 +1783,7 @@ void wxTreeCtrl::SelectItem(const wxTreeItemId& item, bool select)
         // the notification from the control (i.e. TVN_SELCHANG{ED|ING}), so
         // send them ourselves
 
         // 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);
+        wxTreeEvent event(wxEVT_COMMAND_TREE_SEL_CHANGING, this, item);
         if ( !GetEventHandler()->ProcessEvent(event) || event.IsAllowed() )
         {
             if ( !TreeView_SelectItem(GetHwnd(), HITEM(item)) )
         if ( !GetEventHandler()->ProcessEvent(event) || event.IsAllowed() )
         {
             if ( !TreeView_SelectItem(GetHwnd(), HITEM(item)) )
@@ -1804,6 +1802,8 @@ void wxTreeCtrl::SelectItem(const wxTreeItemId& item, bool select)
 
 void wxTreeCtrl::EnsureVisible(const wxTreeItemId& item)
 {
 
 void wxTreeCtrl::EnsureVisible(const wxTreeItemId& item)
 {
+    wxCHECK_RET( !IsHiddenRoot(item), _T("can't show hidden root item") );
+
     // no error return
     TreeView_EnsureVisible(GetHwnd(), HITEM(item));
 }
     // no error return
     TreeView_EnsureVisible(GetHwnd(), HITEM(item));
 }
@@ -1874,7 +1874,7 @@ void wxTreeCtrl::DoEndEditLabel(bool discardChanges)
     DeleteTextCtrl();
 }
 
     DeleteTextCtrl();
 }
 
-wxTreeItemId wxTreeCtrl::DoTreeHitTest(const wxPoint& point, int& flags)
+wxTreeItemId wxTreeCtrl::DoTreeHitTest(const wxPoint& point, int& flags) const
 {
     TV_HITTESTINFO hitTestInfo;
     hitTestInfo.pt.x = (int)point.x;
 {
     TV_HITTESTINFO hitTestInfo;
     hitTestInfo.pt.x = (int)point.x;
@@ -1991,6 +1991,20 @@ void wxTreeCtrl::SortChildren(const wxTreeItemId& item)
 // implementation
 // ----------------------------------------------------------------------------
 
 // implementation
 // ----------------------------------------------------------------------------
 
+bool wxTreeCtrl::MSWShouldPreProcessMessage(WXMSG* msg)
+{
+    if ( msg->message == WM_KEYDOWN )
+    {
+        if ( msg->wParam == VK_RETURN )
+        {
+            // we need VK_RETURN to generate wxEVT_COMMAND_TREE_ITEM_ACTIVATED
+            return false;
+        }
+    }
+
+    return wxTreeCtrlBase::MSWShouldPreProcessMessage(msg);
+}
+
 bool wxTreeCtrl::MSWCommand(WXUINT cmd, WXWORD id)
 {
     if ( cmd == EN_UPDATE )
 bool wxTreeCtrl::MSWCommand(WXUINT cmd, WXWORD id)
 {
     if ( cmd == EN_UPDATE )
@@ -2033,11 +2047,9 @@ WXLRESULT wxTreeCtrl::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lPara
         // Convert the screen point to a client point
         wxPoint MenuPoint = ScreenToClient(wxPoint(x, y));
 
         // Convert the screen point to a client point
         wxPoint MenuPoint = ScreenToClient(wxPoint(x, y));
 
-        wxTreeEvent event( wxEVT_COMMAND_TREE_ITEM_MENU, GetId() );
-
         // can't use GetSelection() here as it would assert in multiselect mode
         // can't use GetSelection() here as it would assert in multiselect mode
-        event.m_item = wxTreeItemId(TreeView_GetSelection(GetHwnd()));
-        event.SetEventObject( this );
+        wxTreeEvent event(wxEVT_COMMAND_TREE_ITEM_MENU, this,
+                          wxTreeItemId(TreeView_GetSelection(GetHwnd())));
 
         // Get the bounding rectangle for the item, including the non-text areas
         wxRect ItemRect;
 
         // Get the bounding rectangle for the item, including the non-text areas
         wxRect ItemRect;
@@ -2259,12 +2271,7 @@ WXLRESULT wxTreeCtrl::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lPara
                     m_dragImage = NULL;
 
                     // generate the drag end event
                     m_dragImage = NULL;
 
                     // generate the drag end event
-                    wxTreeEvent event(wxEVT_COMMAND_TREE_END_DRAG, m_windowId);
-
-                    event.m_item = htItem;
-                    event.m_pointDrag = wxPoint(x, y);
-                    event.SetEventObject(this);
-
+                    wxTreeEvent event(wxEVT_COMMAND_TREE_END_DRAG, this, htItem);
                     (void)GetEventHandler()->ProcessEvent(event);
 
                     // if we don't do it, the tree seems to think that 2 items
                     (void)GetEventHandler()->ProcessEvent(event);
 
                     // if we don't do it, the tree seems to think that 2 items
@@ -2443,7 +2450,7 @@ wxTreeCtrl::MSWDefWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
 // process WM_NOTIFY Windows message
 bool wxTreeCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result)
 {
 // process WM_NOTIFY Windows message
 bool wxTreeCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result)
 {
-    wxTreeEvent event(wxEVT_NULL, m_windowId);
+    wxTreeEvent event(wxEVT_NULL, this);
     wxEventType eventType = wxEVT_NULL;
     NMHDR *hdr = (NMHDR *)lParam;
 
     wxEventType eventType = wxEVT_NULL;
     NMHDR *hdr = (NMHDR *)lParam;
 
@@ -2618,16 +2625,13 @@ bool wxTreeCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result)
                 if ( !wxIsCtrlDown() && !wxIsShiftDown() && !isAltDown &&
                      ((info->wVKey == VK_SPACE) || (info->wVKey == VK_RETURN)) )
                 {
                 if ( !wxIsCtrlDown() && !wxIsShiftDown() && !isAltDown &&
                      ((info->wVKey == VK_SPACE) || (info->wVKey == VK_RETURN)) )
                 {
-                    wxTreeEvent event2(wxEVT_COMMAND_TREE_ITEM_ACTIVATED,
-                                       m_windowId);
-                    event2.SetEventObject(this);
-                    if ( !(GetWindowStyle() & wxTR_MULTIPLE) )
-                    {
-                        event2.m_item = GetSelection();
-                    }
-                    //else: don't know how to get it
+                   wxTreeItemId item;
+                   if ( !HasFlag(wxTR_MULTIPLE) )
+                       item = GetSelection();
 
 
-                    (void)GetEventHandler()->ProcessEvent(event2);
+                   wxTreeEvent event2(wxEVT_COMMAND_TREE_ITEM_ACTIVATED,
+                                        this, item);
+                   (void)GetEventHandler()->ProcessEvent(event2);
                 }
             }
             break;
                 }
             }
             break;
@@ -2693,9 +2697,15 @@ bool wxTreeCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result)
 
                             wxTreeItemAttr * const attr = it->second;
 
 
                             wxTreeItemAttr * const attr = it->second;
 
+                            wxTreeViewItem tvItem((void *)nmcd.dwItemSpec,
+                                                  TVIF_STATE, TVIS_DROPHILITED);
+                            DoGetItem(&tvItem);
+                            const UINT tvItemState = tvItem.state;
+
                             // selection colours should override ours,
                             // selection colours should override ours,
-                            // otherwise it is too confusing ot the user
-                            if ( !(nmcd.uItemState & CDIS_SELECTED) )
+                            // otherwise it is too confusing to the user
+                            if ( !(nmcd.uItemState & CDIS_SELECTED) &&
+                                 !(tvItemState & TVIS_DROPHILITED) )
                             {
                                 wxColour colBack;
                                 if ( attr->HasBackgroundColour() )
                             {
                                 wxColour colBack;
                                 if ( attr->HasBackgroundColour() )
@@ -2709,8 +2719,9 @@ bool wxTreeCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result)
                             // colour when we don't have focus (we can't keep
                             // it when we do, it would usually be unreadable on
                             // the almost inverted bg colour...)
                             // colour when we don't have focus (we can't keep
                             // it when we do, it would usually be unreadable on
                             // the almost inverted bg colour...)
-                            if ( !(nmcd.uItemState & CDIS_SELECTED) ||
-                                    FindFocus() != this )
+                            if ( ( !(nmcd.uItemState & CDIS_SELECTED) ||
+                                    FindFocus() != this ) &&
+                                 !(tvItemState & TVIS_DROPHILITED) )
                             {
                                 wxColour colText;
                                 if ( attr->HasTextColour() )
                             {
                                 wxColour colText;
                                 if ( attr->HasTextColour() )
@@ -2789,9 +2800,11 @@ bool wxTreeCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result)
             return wxControl::MSWOnNotify(idCtrl, lParam, result);
     }
 
             return wxControl::MSWOnNotify(idCtrl, lParam, result);
     }
 
-    event.SetEventObject(this);
     event.SetEventType(eventType);
 
     event.SetEventType(eventType);
 
+    if ( event.m_item.IsOk() )
+        event.SetClientObject(GetItemData(event.m_item));
+
     bool processed = GetEventHandler()->ProcessEvent(event);
 
     // post processing
     bool processed = GetEventHandler()->ProcessEvent(event);
 
     // post processing