Jason Edmeades : comctl32: toolbar: Implemented SetRows.

Alexandre Julliard julliard at wine.codeweavers.com
Tue Aug 28 07:50:14 CDT 2007


Module: wine
Branch: master
Commit: 881c204c027d3d972c0d13531cd7dee0a5177db5
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=881c204c027d3d972c0d13531cd7dee0a5177db5

Author: Jason Edmeades <jason.edmeades at googlemail.com>
Date:   Mon Aug 27 21:30:16 2007 +0100

comctl32: toolbar: Implemented SetRows.

---

 dlls/comctl32/tests/toolbar.c |   56 ++++++++++++++++++++++
 dlls/comctl32/toolbar.c       |  104 +++++++++++++++++++++++++++++++++++++----
 2 files changed, 150 insertions(+), 10 deletions(-)

diff --git a/dlls/comctl32/tests/toolbar.c b/dlls/comctl32/tests/toolbar.c
index b46ef0d..5e619ee 100644
--- a/dlls/comctl32/tests/toolbar.c
+++ b/dlls/comctl32/tests/toolbar.c
@@ -1032,6 +1032,61 @@ static void test_dispinfo(void)
     g_dwExpectedDispInfoMask = 0;
 }
 
+typedef struct
+{
+    int  nRows;
+    BOOL bLarger;
+    int  expectedRows;
+} tbrows_result_t;
+
+static tbrows_result_t tbrows_results[] =
+{
+    {1, TRUE,  1}, /* 0: Simple case 9 in a row */
+    {2, TRUE,  2}, /* 1: Another simple case 5 on one row, 4 on another*/
+    {3, FALSE, 3}, /* 2: 3 lines - should be 3 lines of 3 buttons */
+    {8, FALSE, 5}, /* 3: 8 lines - should be 5 lines of 2 buttons */
+    {8, TRUE,  9}, /* 4: 8 lines but grow - should be 9 lines */
+    {1, TRUE,  1}  /* 5: Back to simple case */
+};
+
+static void test_setrows(void)
+{
+    TBBUTTON buttons[9];
+    HWND hToolbar;
+    int i;
+
+    for (i=0; i<9; i++)
+        MakeButton(buttons+i, 1000+i, TBSTYLE_FLAT | TBSTYLE_CHECKGROUP, 0);
+
+    /* Test 1 - 9 buttons */
+    hToolbar = CreateToolbarEx(hMainWnd,
+        WS_VISIBLE | WS_CLIPCHILDREN | WS_CHILD | CCS_NORESIZE | CCS_NOPARENTALIGN
+        | CCS_NOMOVEY | CCS_TOP,
+        0,
+        0, NULL, (UINT)0,
+        buttons, sizeof(buttons)/sizeof(buttons[0]),
+        20, 20, 0, 0, sizeof(TBBUTTON));
+    ok(hToolbar != NULL, "Toolbar creation\n");
+    ok(SendMessageA(hToolbar, TB_AUTOSIZE, 0, 0) == 0, "TB_AUTOSIZE failed\n");
+
+    /* test setting rows to each of 1-10 with bLarger true and false */
+    for (i=0; i<(sizeof(tbrows_results) / sizeof(tbrows_result_t)); i++) {
+        RECT rc;
+        int rows;
+
+        memset(&rc, 0xCC, sizeof(rc));
+        SendMessageA(hToolbar, TB_SETROWS,
+                     MAKELONG(tbrows_results[i].nRows, tbrows_results[i].bLarger),
+                     (LONG) &rc);
+
+        rows = SendMessageA(hToolbar, TB_GETROWS, MAKELONG(0,0), MAKELONG(0,0));
+        ok(rows == tbrows_results[i].expectedRows,
+                   "[%d] Unexpected number of rows %d (expected %d)\n", i, rows,
+                   tbrows_results[i].expectedRows);
+    }
+
+    DestroyWindow(hToolbar);
+}
 
 START_TEST(toolbar)
 {
@@ -1066,6 +1121,7 @@ START_TEST(toolbar)
     test_getbuttoninfo();
     test_createtoolbarex();
     test_dispinfo();
+    test_setrows();
 
     PostQuitMessage(0);
     while(GetMessageA(&msg,0,0,0)) {
diff --git a/dlls/comctl32/toolbar.c b/dlls/comctl32/toolbar.c
index 275d3d5..8ca4e6b 100644
--- a/dlls/comctl32/toolbar.c
+++ b/dlls/comctl32/toolbar.c
@@ -44,7 +44,7 @@
  *     - TBN_GETOBJECT
  *     - TBN_SAVE
  *   - Button wrapping (under construction).
- *   - Fix TB_SETROWS.
+ *   - Fix TB_SETROWS and Separators.
  *   - iListGap custom draw support.
  *
  * Testing:
@@ -3637,10 +3637,7 @@ TOOLBAR_GetRows (HWND hwnd, WPARAM wParam, LPARAM lParam)
 {
     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
 
-    if (infoPtr->dwStyle & TBSTYLE_WRAPABLE)
-	return infoPtr->nRows;
-    else
-	return 1;
+    return infoPtr->nRows;
 }
 
 
@@ -4947,20 +4944,107 @@ TOOLBAR_SetRows (HWND hwnd, WPARAM wParam, LPARAM lParam)
 {
     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
     LPRECT lprc = (LPRECT)lParam;
+    int rows = LOWORD(wParam);
+    BOOL bLarger = HIWORD(wParam);
 
     TRACE("\n");
 
-    if (LOWORD(wParam) > 1) {
-	FIXME("multiple rows not supported!\n");
-    }
+    TRACE("Setting rows to %d (%d)\n", rows, bLarger);
 
-    if(infoPtr->nRows != LOWORD(wParam))
+    if(infoPtr->nRows != rows)
     {
-        infoPtr->nRows = LOWORD(wParam);
+        TBUTTON_INFO *btnPtr = infoPtr->buttons;
+        int curColumn = 0; /* Current column                      */
+        int curRow    = 0; /* Current row                         */
+        int hidden    = 0; /* Number of hidden buttons */
+        int seps      = 0; /* Number of separators     */
+        int idealWrap = 0; /* Ideal wrap point         */
+        int i;
+        BOOL wrap;
+
+        /*
+           Calculate new size and wrap points - Under windows, setrows will
+           change the dimensions if needed to show the number of requested
+           rows (if CCS_NORESIZE is set), or will take up the whole window
+           (if no CCS_NORESIZE).
+
+           Basic algorithum - If N buttons, and y rows requested, each row
+           contains N/y buttons.
+
+           FIXME: Handling of separators not obvious from testing results
+           FIXME: Take width of window into account?
+         */
+
+        /* Loop through the buttons one by one counting key items  */
+        for (i = 0; i < infoPtr->nNumButtons; i++ )
+        {
+            btnPtr[i].fsState &= ~TBSTATE_WRAP;
+            if (btnPtr[i].fsState & TBSTATE_HIDDEN)
+                hidden++;
+            else if (btnPtr[i].fsStyle & BTNS_SEP)
+                seps++;
+        }
+
+        /* FIXME: Separators make this quite complex */
+        if (seps) FIXME("Separators unhandled\n");
+
+        /* Round up so more per line, ie less rows */
+        idealWrap = (infoPtr->nNumButtons - hidden + (rows-1)) / rows;
+
+        /* Calculate ideal wrap point if we are allowed to grow, but cannot
+           achieve the requested number of rows. */
+        if (bLarger && idealWrap > 1)
+        {
+            int resRows = (infoPtr->nNumButtons + (idealWrap-1)) / idealWrap;
+            int moreRows = (infoPtr->nNumButtons + (idealWrap-2)) / (idealWrap-1);
+
+            if (resRows < rows && moreRows > rows)
+            {
+                idealWrap--;
+                TRACE("Changing idealWrap due to bLarger (now %d)\n", idealWrap);
+            }
+        }
+
+        curColumn = curRow = 0;
+        wrap = FALSE;
+        TRACE("Trying to wrap at %d (%d,%d,%d)\n", idealWrap,
+              infoPtr->nNumButtons, hidden, rows);
+
+        for (i = 0; i < infoPtr->nNumButtons; i++ )
+        {
+            if (btnPtr[i].fsState & TBSTATE_HIDDEN)
+                continue;
+
+            /* Step on, wrap if necessary or flag next to wrap */
+            if (!wrap) {
+                curColumn++;
+            } else {
+                wrap = FALSE;
+                curColumn = 1;
+                curRow++;
+            }
+
+            if (curColumn > (idealWrap-1)) {
+                wrap = TRUE;
+                btnPtr[i].fsState |= TBSTATE_WRAP;
+            }
+        }
+
+        TRACE("Result - %d rows\n", curRow + 1);
 
         /* recalculate toolbar */
         TOOLBAR_CalcToolbar (hwnd);
 
+        /* Resize if necessary (Only if NORESIZE is set - odd, but basically
+           if NORESIZE is NOT set, then the toolbar will always be resized to
+           take up the whole window. With it set, sizing needs to be manual. */
+        if (infoPtr->dwStyle & CCS_NORESIZE) {
+            SetWindowPos(hwnd, NULL, 0, 0,
+                         infoPtr->rcBound.right - infoPtr->rcBound.left,
+                         infoPtr->rcBound.bottom - infoPtr->rcBound.top,
+                         SWP_NOMOVE);
+        }
+
         /* repaint toolbar */
         InvalidateRect(hwnd, NULL, TRUE);
     }




More information about the wine-cvs mailing list