Module: wine Branch: master Commit: 881c204c027d3d972c0d13531cd7dee0a5177db5 URL: http://source.winehq.org/git/wine.git/?a=commit;h=881c204c027d3d972c0d13531c...
Author: Jason Edmeades jason.edmeades@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); }