]> git.saurik.com Git - wxWidgets.git/blobdiff - src/msw/treectrl.cpp
Swap client data pointers in wxRearrangeList too.
[wxWidgets.git] / src / msw / treectrl.cpp
index f90ba117d3b6856ad8facc0815733dafd1c83b10..58daae2cf1c7df3a57d1d05b1589074b986ce8a4 100644 (file)
@@ -750,6 +750,7 @@ void wxTreeCtrl::Init()
     m_focusLost = true;
     m_changingSelection = false;
     m_triggerStateImageClick = false;
+    m_mouseUpDeselect = false;
 
     // 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
@@ -1666,6 +1667,12 @@ void wxTreeCtrl::Delete(const wxTreeItemId& item)
             return;
         }
 
+        if ( item == m_htSelStart )
+            m_htSelStart.Unset();
+
+        if ( item == m_htClickedItem )
+            m_htClickedItem.Unset();
+
         if ( next.IsOk() )
         {
             wxTreeEvent changingEvent(wxEVT_COMMAND_TREE_SEL_CHANGING, this, next);
@@ -1720,6 +1727,10 @@ void wxTreeCtrl::DeleteAllItems()
     // unlock tree selections on vista for the duration of this call
     TreeItemUnlocker unlock_all;
 
+    // invalidate all the items we store as they're going to become invalid
+    m_htSelStart =
+    m_htClickedItem = wxTreeItemId();
+
     // delete the "virtual" root item.
     if ( GET_VIRTUAL_ROOT() )
     {
@@ -1872,6 +1883,39 @@ void wxTreeCtrl::UnselectAll()
     }
 }
 
+void wxTreeCtrl::DoSelectChildren(const wxTreeItemId& parent)
+{
+    DoUnselectAll();
+
+    wxTreeItemIdValue cookie;
+    wxTreeItemId child = GetFirstChild(parent, cookie);
+    while ( child.IsOk() )
+    {
+        DoSelectItem(child, true);
+        child = GetNextChild(child, cookie);
+    }
+}
+
+void wxTreeCtrl::SelectChildren(const wxTreeItemId& parent)
+{
+    wxCHECK_RET( HasFlag(wxTR_MULTIPLE),
+                 "this only works with multiple selection controls" );
+
+    HTREEITEM htFocus = (HTREEITEM)TreeView_GetSelection(GetHwnd());
+
+    wxTreeEvent changingEvent(wxEVT_COMMAND_TREE_SEL_CHANGING, this);
+    changingEvent.m_itemOld = htFocus;
+
+    if ( IsTreeEventAllowed(changingEvent) )
+    {
+        DoSelectChildren(parent);
+
+        wxTreeEvent changedEvent(wxEVT_COMMAND_TREE_SEL_CHANGED, this);
+        changedEvent.m_itemOld = htFocus;
+        (void)HandleTreeEvent(changedEvent);
+    }
+}
+
 void wxTreeCtrl::DoSelectItem(const wxTreeItemId& item, bool select)
 {
     TempSetter set(m_changingSelection);
@@ -1985,8 +2029,7 @@ void wxTreeCtrl::DeleteTextCtrl()
 
         m_textCtrl->UnsubclassWin();
         m_textCtrl->SetHWND(0);
-        delete m_textCtrl;
-        m_textCtrl = NULL;
+        wxDELETE(m_textCtrl);
 
         m_idEdited.Unset();
     }
@@ -2007,8 +2050,7 @@ wxTextCtrl *wxTreeCtrl::EditLabel(const wxTreeItemId& item,
     // returned false
     if ( !hWnd )
     {
-        delete m_textCtrl;
-        m_textCtrl = NULL;
+        wxDELETE(m_textCtrl);
         return NULL;
     }
 
@@ -2093,6 +2135,8 @@ void wxTreeCtrl::ClearFocusedItem()
 
 void wxTreeCtrl::SetFocusedItem(const wxTreeItemId& item)
 {
+    wxCHECK_RET( item.IsOk(), wxT("invalid tree item") );
+
     TempSetter set(m_changingSelection);
 
     ::SetFocus(GetHwnd(), HITEM(item));
@@ -2214,6 +2258,15 @@ bool wxTreeCtrl::MSWCommand(WXUINT cmd, WXWORD id_)
     return true;
 }
 
+bool wxTreeCtrl::MSWIsOnItem(unsigned flags) const
+{
+    unsigned mask = TVHT_ONITEM;
+    if ( HasFlag(wxTR_FULL_ROW_HIGHLIGHT) )
+        mask |= TVHT_ONITEMINDENT | TVHT_ONITEMRIGHT;
+
+    return (flags & mask) != 0;
+}
+
 bool wxTreeCtrl::MSWHandleSelectionKey(unsigned vkey)
 {
     const bool bCtrl = wxIsCtrlDown();
@@ -2715,7 +2768,7 @@ wxTreeCtrl::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
 
                 m_htClickedItem.Unset();
 
-                if ( !(tvht.flags & TVHT_ONITEM) )
+                if ( !MSWIsOnItem(tvht.flags) )
                 {
                     if ( tvht.flags & TVHT_ONITEMBUTTON )
                     {
@@ -2876,6 +2929,7 @@ wxTreeCtrl::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
                         else
                         {
                             SetFocusedItem(wxTreeItemId(htItem));
+                            m_mouseUpDeselect = true;
                         }
                     }
                     else // click on a single selected item
@@ -3025,16 +3079,13 @@ wxTreeCtrl::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
             case WM_LBUTTONUP:
                 if ( isMultiple )
                 {
-                    // deselect other items if multiple items selected
+                    // deselect other items if needed
                     if ( htItem )
                     {
-                        wxArrayTreeItemIds selections;
-                        size_t count = GetSelections(selections);
-
-                        if ( count > 1 &&
-                             !(wParam & MK_CONTROL) &&
-                             !(wParam & MK_SHIFT) )
+                        if ( m_mouseUpDeselect )
                         {
+                            m_mouseUpDeselect = false;
+
                             wxTreeEvent changingEvent(wxEVT_COMMAND_TREE_SEL_CHANGING,
                                                       this, htItem);
                             changingEvent.m_itemOld = htOldItem;
@@ -3068,10 +3119,7 @@ wxTreeCtrl::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
                         }
                     }
 
-                    if ( !m_dragStarted &&
-                         (tvht.flags & TVHT_ONITEMSTATEICON ||
-                          tvht.flags & TVHT_ONITEMICON ||
-                          tvht.flags & TVHT_ONITEM) )
+                    if ( !m_dragStarted && MSWIsOnItem(tvht.flags) )
                     {
                         processed = true;
                     }
@@ -3084,8 +3132,7 @@ wxTreeCtrl::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
                 if ( m_dragImage )
                 {
                     m_dragImage->EndDrag();
-                    delete m_dragImage;
-                    m_dragImage = NULL;
+                    wxDELETE(m_dragImage);
 
                     // generate the drag end event
                     wxTreeEvent event(wxEVT_COMMAND_TREE_END_DRAG,
@@ -3162,7 +3209,8 @@ wxTreeCtrl::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
             case VK_END:
             case VK_PRIOR:
             case VK_NEXT:
-                if ( !MSWHandleTreeKeyDownEvent(wParam, lParam) )
+                if ( !HandleKeyDown(wParam, lParam) &&
+                        !MSWHandleTreeKeyDownEvent(wParam, lParam) )
                 {
                     // use the key to update the selection if it was left
                     // unprocessed
@@ -3224,8 +3272,7 @@ wxTreeCtrl::MSWDefWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
             if ( m_dragImage )
             {
                 m_dragImage->EndDrag();
-                delete m_dragImage;
-                m_dragImage = NULL;
+                wxDELETE(m_dragImage);
 
                 // if we don't do it, the tree seems to think that 2 items
                 // are selected simultaneously which is quite weird
@@ -3653,7 +3700,7 @@ bool wxTreeCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result)
                 ::ScreenToClient(GetHwnd(), &tvhti.pt);
                 if ( TreeView_HitTest(GetHwnd(), &tvhti) )
                 {
-                    if ( tvhti.flags & TVHT_ONITEM )
+                    if ( MSWIsOnItem(tvhti.flags) )
                     {
                         event.m_item = tvhti.hItem;
                         eventType = (int)hdr->code == NM_DBLCLK