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