[PATCH 2/3] Fix TVS_SINGLEEXPAND notifications order

Nikolay Sivov nsivov at codeweavers.com
Mon Jul 26 06:49:09 CDT 2010


---
 dlls/comctl32/tests/treeview.c |   29 ++++++++++
 dlls/comctl32/treeview.c       |  117 +++++++++++++++++++++------------------
 2 files changed, 92 insertions(+), 54 deletions(-)

diff --git a/dlls/comctl32/tests/treeview.c b/dlls/comctl32/tests/treeview.c
index d3de85f..d1ca581 100644
--- a/dlls/comctl32/tests/treeview.c
+++ b/dlls/comctl32/tests/treeview.c
@@ -192,6 +192,15 @@ static const struct message parent_expand_seq[] = {
     { 0 }
 };
 
+static const struct message parent_singleexpand_seq[] = {
+    { WM_NOTIFY, sent|id, 0, 0, TVN_SELCHANGINGA },
+    { WM_NOTIFY, sent|id, 0, 0, TVN_SELCHANGEDA },
+    { WM_NOTIFY, sent|id, 0, 0, TVN_SINGLEEXPAND },
+    { WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDINGA },
+    { WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDEDA },
+    { 0 }
+};
+
 static const struct message empty_seq[] = {
     { 0 }
 };
@@ -1231,6 +1240,25 @@ static void test_expandedimage(void)
     DestroyWindow(hTree);
 }
 
+static void test_TVS_SINGLEEXPAND(void)
+{
+    HWND hTree;
+    BOOL ret;
+
+    hTree = create_treeview_control();
+    SetWindowLongA(hTree, GWL_STYLE, GetWindowLong(hTree, GWL_STYLE) | TVS_SINGLEEXPAND);
+    /* to avoid paiting related notifications */
+    ShowWindow(hTree, SW_HIDE);
+    fill_tree(hTree);
+
+    flush_sequences(sequences, NUM_MSG_SEQUENCES);
+    ret = SendMessageA(hTree, TVM_SELECTITEM, TVGN_CARET, (LPARAM)hRoot);
+    ok(ret, "got %d\n", ret);
+    ok_sequence(sequences, PARENT_SEQ_INDEX, parent_singleexpand_seq, "singleexpand notifications", FALSE);
+
+    DestroyWindow(hTree);
+}
+
 START_TEST(treeview)
 {
     HMODULE hComctl32;
@@ -1296,6 +1324,7 @@ START_TEST(treeview)
     test_treeview_classinfo();
     test_expandnotify();
     test_rect_retrieval_after_expand_with_select();
+    test_TVS_SINGLEEXPAND();
 
     if (!load_v6_module(&ctx_cookie, &hCtx))
     {
diff --git a/dlls/comctl32/treeview.c b/dlls/comctl32/treeview.c
index 8683b4a..3ee1639 100644
--- a/dlls/comctl32/treeview.c
+++ b/dlls/comctl32/treeview.c
@@ -3305,7 +3305,7 @@ TREEVIEW_Collapse(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *wineItem,
 
 static BOOL
 TREEVIEW_Expand(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *wineItem,
-		BOOL bExpandPartial, BOOL bUser)
+		BOOL partial, BOOL user)
 {
     LONG scrollDist;
     LONG orgNextTop = 0;
@@ -3313,7 +3313,7 @@ TREEVIEW_Expand(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *wineItem,
     TREEVIEW_ITEM *nextItem, *tmpItem;
     BOOL sendsNotifications;
 
-    TRACE("(%p, %p, partial=%d, %d\n", infoPtr, wineItem, bExpandPartial, bUser);
+    TRACE("(%p, %p, partial=%d, %d\n", infoPtr, wineItem, partial, user);
 
     if (wineItem->state & TVIS_EXPANDED)
        return TRUE;
@@ -3334,7 +3334,7 @@ TREEVIEW_Expand(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *wineItem,
 
     TRACE("TVE_EXPAND %p %s\n", wineItem, TREEVIEW_ItemName(wineItem));
 
-    sendsNotifications = bUser || ((wineItem->cChildren != 0) &&
+    sendsNotifications = user || ((wineItem->cChildren != 0) &&
                                     !(wineItem->state & TVIS_EXPANDEDONCE));
     if (sendsNotifications)
     {
@@ -3349,7 +3349,7 @@ TREEVIEW_Expand(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *wineItem,
 
     wineItem->state |= TVIS_EXPANDED;
 
-    if (bExpandPartial)
+    if (partial)
 	FIXME("TVE_EXPANDPARTIAL not implemented\n");
 
     if (ISVISIBLE(wineItem))
@@ -3415,6 +3415,58 @@ TREEVIEW_Expand(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *wineItem,
     return TRUE;
 }
 
+/* Handler for TVS_SINGLEEXPAND behaviour. Used on response
+   to mouse messages and TVM_SELECTITEM.
+
+   selection - previously selected item, used to collapse a part of a tree
+   item - new selected item
+*/
+static void TREEVIEW_SingleExpand(TREEVIEW_INFO *infoPtr,
+    HTREEITEM selection, HTREEITEM item)
+{
+    TREEVIEW_ITEM *SelItem;
+
+    if ((infoPtr->dwStyle & TVS_SINGLEEXPAND) == 0 || infoPtr->hwndEdit) return;
+
+    TREEVIEW_SendTreeviewNotify(infoPtr, TVN_SINGLEEXPAND, TVC_UNKNOWN, TVIF_HANDLE | TVIF_PARAM, item, 0);
+
+    /*
+     * Close the previous selection all the way to the root
+     * as long as the new selection is not a child
+     */
+    if(selection && (selection != item))
+    {
+        BOOL closeit = TRUE;
+        SelItem = item;
+
+        /* determine if the hitItem is a child of the currently selected item */
+        while(closeit && SelItem && TREEVIEW_ValidItem(infoPtr, SelItem) &&
+              (SelItem->parent != infoPtr->root))
+        {
+            closeit = (SelItem != selection);
+            SelItem = SelItem->parent;
+        }
+
+        if(closeit)
+        {
+            if(TREEVIEW_ValidItem(infoPtr, selection))
+                SelItem = selection;
+
+            while(SelItem && (SelItem != item) && TREEVIEW_ValidItem(infoPtr, SelItem) &&
+                  SelItem->parent != infoPtr->root)
+            {
+                TREEVIEW_Collapse(infoPtr, SelItem, FALSE, FALSE);
+                SelItem = SelItem->parent;
+            }
+        }
+    }
+
+    /*
+     * Expand the current item
+     */
+    TREEVIEW_Expand(infoPtr, item, FALSE, FALSE);
+}
+
 static BOOL
 TREEVIEW_Toggle(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *wineItem, BOOL bUser)
 {
@@ -4132,58 +4184,11 @@ TREEVIEW_LButtonDown(TREEVIEW_INFO *infoPtr, LPARAM lParam)
     }
     else if (ht.flags & (TVHT_ONITEMICON|TVHT_ONITEMLABEL)) /* select the item if the hit was inside of the icon or text */
     {
-        /*
-         * if we are TVS_SINGLEEXPAND then we want this single click to
-         * do a bunch of things.
-         */
-        if((infoPtr->dwStyle & TVS_SINGLEEXPAND) &&
-          (infoPtr->hwndEdit == 0))
-        {
-            TREEVIEW_ITEM *SelItem;
-
-            /*
-             * Send the notification
-             */
-            TREEVIEW_SendTreeviewNotify(infoPtr, TVN_SINGLEEXPAND, TVC_UNKNOWN, TVIF_HANDLE | TVIF_PARAM, ht.hItem, 0);
-
-            /*
-             * Close the previous selection all the way to the root
-             * as long as the new selection is not a child
-             */
-            if((infoPtr->selectedItem)
-                && (infoPtr->selectedItem != ht.hItem))
-            {
-                BOOL closeit = TRUE;
-                SelItem = ht.hItem;
-
-                /* determine if the hitItem is a child of the currently selected item */
-                while(closeit && SelItem && TREEVIEW_ValidItem(infoPtr, SelItem) && (SelItem != infoPtr->root))
-                {
-                    closeit = (SelItem != infoPtr->selectedItem);
-                    SelItem = SelItem->parent;
-                }
-
-                if(closeit)
-                {
-                    if(TREEVIEW_ValidItem(infoPtr, infoPtr->selectedItem))
-                        SelItem = infoPtr->selectedItem;
-
-                    while(SelItem && (SelItem != ht.hItem) && TREEVIEW_ValidItem(infoPtr, SelItem) && (SelItem != infoPtr->root))
-                    {
-                        TREEVIEW_Collapse(infoPtr, SelItem, FALSE, FALSE);
-                        SelItem = SelItem->parent;
-                    }
-                }
-            }
-
-            /*
-             * Expand the current item
-             */
-            TREEVIEW_Expand(infoPtr, ht.hItem, TVE_TOGGLE, FALSE);
-        }
+        TREEVIEW_ITEM *selection = infoPtr->selectedItem;
 
         /* Select the current item */
         TREEVIEW_DoSelectItem(infoPtr, TVGN_CARET, ht.hItem, TVC_BYMOUSE);
+        TREEVIEW_SingleExpand(infoPtr, selection, ht.hItem);
     }
     else if (ht.flags & TVHT_ONITEMSTATEICON)
     {
@@ -4415,7 +4420,9 @@ TREEVIEW_DoSelectItem(TREEVIEW_INFO *infoPtr, INT action, HTREEITEM newSelect,
 static LRESULT
 TREEVIEW_SelectItem(TREEVIEW_INFO *infoPtr, INT wParam, HTREEITEM item)
 {
-    if (item != NULL && !TREEVIEW_ValidItem(infoPtr, item))
+    TREEVIEW_ITEM *selection = infoPtr->selectedItem;
+
+    if (item && !TREEVIEW_ValidItem(infoPtr, item))
 	return FALSE;
 
     TRACE("%p (%s) %d\n", item, TREEVIEW_ItemName(item), wParam);
@@ -4423,6 +4430,8 @@ TREEVIEW_SelectItem(TREEVIEW_INFO *infoPtr, INT wParam, HTREEITEM item)
     if (!TREEVIEW_DoSelectItem(infoPtr, wParam, item, TVC_UNKNOWN))
 	return FALSE;
 
+    TREEVIEW_SingleExpand(infoPtr, selection, item);
+
     return TRUE;
 }
 
-- 
1.5.6.5



--------------080301030104080304080203--



More information about the wine-patches mailing list