Commit abd12e4d authored by Vitaliy Margolen's avatar Vitaliy Margolen Committed by Alexandre Julliard

Fix handling of minimum tab width.

Add more tests to test it.
parent e18f8abe
......@@ -142,13 +142,18 @@ typedef struct
#define BUTTON_SPACINGX 3
#define BUTTON_SPACINGY 3
#define FLAT_BTN_SPACINGX 8
#define DEFAULT_TAB_WIDTH 96
#define DEFAULT_MIN_TAB_WIDTH 54
#define DEFAULT_TAB_WIDTH_FIXED 96
#define DEFAULT_PADDING_X 6
#define EXTRA_ICON_PADDING 3
#define TAB_GetInfoPtr(hwnd) ((TAB_INFO *)GetWindowLongPtrW(hwnd,0))
/* Since items are variable sized, cannot directly access them */
#define TAB_GetItem(info,i) \
((TAB_ITEM*)((LPBYTE)info->items + (i) * TAB_ITEM_SIZE(info)))
#define GET_DEFAULT_MIN_TAB_WIDTH(infoPtr) (DEFAULT_MIN_TAB_WIDTH - (DEFAULT_PADDING_X - (infoPtr)->uHItemPadding) * 2)
/******************************************************************************
* Hot-tracking timer constants
*/
......@@ -1163,23 +1168,43 @@ static void TAB_SetItemBounds (TAB_INFO *infoPtr)
/* Set the leftmost position of the tab. */
curr->rect.left = curItemLeftPos;
if ((lStyle & TCS_FIXEDWIDTH) || !curr->pszText)
if (lStyle & TCS_FIXEDWIDTH)
{
curr->rect.right = curr->rect.left +
max(infoPtr->tabWidth, icon_width);
}
else
else if (!curr->pszText)
{
int num = 2;
/* If no text use minimum tab width including padding. */
if (infoPtr->tabMinWidth < 0)
curr->rect.right = curr->rect.left + GET_DEFAULT_MIN_TAB_WIDTH(infoPtr);
else
{
curr->rect.right = curr->rect.left + infoPtr->tabMinWidth;
/* Add extra padding if icon is present */
if (infoPtr->himl && infoPtr->tabMinWidth > 0 && infoPtr->tabMinWidth < DEFAULT_MIN_TAB_WIDTH
&& infoPtr->uHItemPadding > 1)
curr->rect.right += EXTRA_ICON_PADDING * (infoPtr->uHItemPadding-1);
}
}
else
{
int tabwidth;
/* Calculate how wide the tab is depending on the text it contains */
GetTextExtentPoint32W(hdc, curr->pszText,
lstrlenW(curr->pszText), &size);
curr->rect.right = curr->rect.left + size.cx + icon_width +
num * infoPtr->uHItemPadding;
TRACE("for <%s>, l,r=%ld,%ld, num=%d\n",
debugstr_w(curr->pszText), curr->rect.left, curr->rect.right, num);
tabwidth = size.cx + icon_width + 2 * infoPtr->uHItemPadding;
if (infoPtr->tabMinWidth < 0)
tabwidth = max(tabwidth, GET_DEFAULT_MIN_TAB_WIDTH(infoPtr));
else
tabwidth = max(tabwidth, infoPtr->tabMinWidth);
curr->rect.right = curr->rect.left + tabwidth;
TRACE("for <%s>, l,r=%ld,%ld\n",
debugstr_w(curr->pszText), curr->rect.left, curr->rect.right);
}
/*
......@@ -2648,7 +2673,7 @@ TAB_SetItemSize (TAB_INFO *infoPtr, LPARAM lParam)
/* UNDOCUMENTED: If requested Width or Height is 0 this means that program wants to use auto size. */
if (lStyle & TCS_FIXEDWIDTH && (infoPtr->tabWidth != (INT)LOWORD(lParam)))
{
infoPtr->tabWidth = max((INT)LOWORD(lParam), infoPtr->tabMinWidth);
infoPtr->tabWidth = (INT)LOWORD(lParam);
bNeedPaint = TRUE;
}
......@@ -2680,8 +2705,9 @@ static inline LRESULT TAB_SetMinTabWidth (TAB_INFO *infoPtr, INT cx)
if (infoPtr) {
oldcx = infoPtr->tabMinWidth;
infoPtr->tabMinWidth = (cx==-1)?DEFAULT_TAB_WIDTH:cx;
infoPtr->tabMinWidth = cx;
}
TAB_SetItemBounds(infoPtr);
return oldcx;
}
......@@ -3041,8 +3067,10 @@ static LRESULT TAB_Create (HWND hwnd, WPARAM wParam, LPARAM lParam)
infoPtr->uVItemPadding;
/* Initialize the width of a tab. */
infoPtr->tabWidth = DEFAULT_TAB_WIDTH;
infoPtr->tabMinWidth = 0;
if (dwStyle & TCS_FIXEDWIDTH)
infoPtr->tabWidth = DEFAULT_TAB_WIDTH_FIXED;
infoPtr->tabMinWidth = -1;
TRACE("tabH=%d, tabW=%d\n", infoPtr->tabHeight, infoPtr->tabWidth);
......
......@@ -23,24 +23,37 @@
#include "wine/test.h"
#undef VISIBLE
#define DEFAULT_MIN_TAB_WIDTH 54
#define TAB_DEFAULT_WIDTH 96
#define TAB_PADDING_X 2
#define TAB_PADDING_Y 2
#ifdef VISIBLE
#define WAIT Sleep (1000)
#define REDRAW(hwnd) RedrawWindow (hwnd, NULL, 0, RDW_UPDATENOW)
#define trace_tab(str) trace(str)
#else
#define WAIT
#define REDRAW(hwnd)
#define trace_tab(str)
#endif
#define TAB_PADDING_X 6
#define EXTRA_ICON_PADDING 3
#define TabWidthPadded(padd_x, num) (DEFAULT_MIN_TAB_WIDTH - (TAB_PADDING_X - (padd_x)) * num)
#define TabCheckSetSize(hwnd, SetWidth, SetHeight, ExpWidth, ExpHeight, Msg)\
SendMessage (hwnd, TCM_SETITEMSIZE, 0,\
(LPARAM) MAKELPARAM((SetWidth >= 0) ? SetWidth:0, (SetHeight >= 0) ? SetHeight:0));\
if (winetest_interactive) RedrawWindow (hwnd, NULL, 0, RDW_UPDATENOW);\
CheckSize(hwnd, ExpWidth, ExpHeight, Msg);
#define CheckSize(hwnd,width,height,msg)\
SendMessage (hwnd, TCM_GETITEMRECT, 0, (LPARAM) &rTab);\
if ((width >= 0) && (height < 0))\
ok (width == rTab.right - rTab.left, "%s: Expected width [%d] got [%ld]\n",\
msg, (int)width, rTab.right - rTab.left);\
else if ((height >= 0) && (width < 0))\
ok (height == rTab.bottom - rTab.top, "%s: Expected height [%d] got [%ld]\n",\
msg, (int)height, rTab.bottom - rTab.top);\
else\
ok ((width == rTab.right - rTab.left) &&\
(height == rTab.bottom - rTab.top ),\
"%s: Expected [%d,%d] got [%ld,%ld]\n", msg, (int)width, (int)height,\
rTab.right - rTab.left, rTab.bottom - rTab.top);
static HFONT hFont = 0;
static HWND
create_tabcontrol (DWORD style)
create_tabcontrol (DWORD style, DWORD mask)
{
HWND handle;
TCITEM tcNewTab;
......@@ -53,10 +66,11 @@ create_tabcontrol (DWORD style)
NULL, NULL, NULL, 0);
assert (handle);
SetWindowLong(handle, GWL_STYLE, WS_CLIPSIBLINGS | WS_CLIPCHILDREN | TCS_FOCUSNEVER | style);
SendMessage (handle, WM_SETFONT, 0, (LPARAM) hFont);
tcNewTab.mask = TCIF_TEXT | TCIF_IMAGE;
tcNewTab.mask = mask;
tcNewTab.pszText = "Tab 1";
tcNewTab.iImage = 0;
SendMessage (handle, TCM_INSERTITEM, 0, (LPARAM) &tcNewTab);
......@@ -67,131 +81,166 @@ create_tabcontrol (DWORD style)
tcNewTab.iImage = 2;
SendMessage (handle, TCM_INSERTITEM, 2, (LPARAM) &tcNewTab);
#ifdef VISIBLE
ShowWindow (handle, SW_SHOW);
#endif
REDRAW(handle);
WAIT;
if (winetest_interactive)
{
ShowWindow (handle, SW_SHOW);
RedrawWindow (handle, NULL, 0, RDW_UPDATENOW);
Sleep (1000);
}
return handle;
}
static void CheckSize(HWND hwnd, INT width, INT height)
{
RECT rTab, r1;
r1.left=r1.top=r1.right=r1.bottom=0;
SendMessage (hwnd, TCM_GETITEMRECT, 0, (LPARAM) &rTab);
SendMessage (hwnd, TCM_ADJUSTRECT, FALSE, (LPARAM) &r1);
/* trace ("Got (%ld,%ld)-(%ld,%ld)\n", rTab.left, rTab.top, rTab.right, rTab.bottom); */
trace (" (%ld,%ld)-(%ld,%ld)\n", r1.left, r1.top, r1.right, r1.bottom);
if ((width >= 0) && (height < 0))
ok (width == rTab.right - rTab.left, "Expected [%d] got [%ld]\n", width, rTab.right - rTab.left);
else if ((height >= 0) && (width < 0))
ok (height == rTab.bottom - rTab.top, "Expected [%d] got [%ld]\n", height, rTab.bottom - rTab.top);
else
ok ((width == rTab.right - rTab.left) &&
(height == rTab.bottom - rTab.top ),
"Expected [%d,%d] got [%ld,%ld]\n", width, height, rTab.right - rTab.left, rTab.bottom - rTab.top);
}
static void TabCheckSetSize(HWND hwnd, INT SetWidth, INT SetHeight, INT ExpWidth, INT ExpHeight)
{
SendMessage (hwnd, TCM_SETITEMSIZE, 0,
(LPARAM) MAKELPARAM((SetWidth >= 0) ? SetWidth:0, (SetHeight >= 0) ? SetHeight:0));
REDRAW(hwnd);
CheckSize(hwnd, ExpWidth, ExpHeight);
WAIT;
}
START_TEST(tab)
static void test_tab(INT nMinTabWidth)
{
HWND hwTab;
RECT rTab;
HIMAGELIST himl = ImageList_Create(21, 21, ILC_COLOR, 3, 4);
SIZE size;
HDC hdc;
HFONT hOldFont;
INT i;
hwTab = create_tabcontrol(TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE);
SendMessage(hwTab, TCM_SETMINTABWIDTH, 0, nMinTabWidth);
hdc = GetDC(hwTab);
hOldFont = SelectObject(hdc, (HFONT)SendMessage(hwTab, WM_GETFONT, 0, 0));
GetTextExtentPoint32A(hdc, "Tab 1", strlen("Tab 1"), &size);
trace("Tab1 text size: size.cx=%ld size.cy=%ld\n", size.cx, size.cy);
SelectObject(hdc, hOldFont);
ReleaseDC(hwTab, hdc);
trace (" TCS_FIXEDWIDTH tabs no icon...\n");
CheckSize(hwTab, TAB_DEFAULT_WIDTH, -1, "default width");
TabCheckSetSize(hwTab, 50, 20, 50, 20, "set size");
TabCheckSetSize(hwTab, 0, 1, 0, 1, "min size");
InitCommonControls();
SendMessage(hwTab, TCM_SETIMAGELIST, 0, (LPARAM)himl);
trace (" TCS_FIXEDWIDTH tabs with icon...\n");
TabCheckSetSize(hwTab, 50, 30, 50, 30, "set size > icon");
TabCheckSetSize(hwTab, 20, 20, 25, 20, "set size < icon");
TabCheckSetSize(hwTab, 0, 1, 25, 1, "min size");
DestroyWindow (hwTab);
hwTab = create_tabcontrol(TCS_FIXEDWIDTH);
hwTab = create_tabcontrol(TCS_FIXEDWIDTH | TCS_BUTTONS, TCIF_TEXT|TCIF_IMAGE);
SendMessage(hwTab, TCM_SETMINTABWIDTH, 0, nMinTabWidth);
trace_tab ("Testing TCS_FIXEDWIDTH tabs no icon...\n");
trace_tab (" default width...\n");
CheckSize(hwTab, TAB_DEFAULT_WIDTH, -1);
trace_tab (" set size...\n");
TabCheckSetSize(hwTab, 50, 20, 50, 20);
WAIT;
trace_tab (" min size...\n");
TabCheckSetSize(hwTab, 0, 1, 0, 1);
WAIT;
trace (" TCS_FIXEDWIDTH buttons no icon...\n");
CheckSize(hwTab, TAB_DEFAULT_WIDTH, -1, "default width");
TabCheckSetSize(hwTab, 20, 20, 20, 20, "set size 1");
TabCheckSetSize(hwTab, 10, 50, 10, 50, "set size 2");
TabCheckSetSize(hwTab, 0, 1, 0, 1, "min size");
SendMessage(hwTab, TCM_SETIMAGELIST, 0, (LPARAM)himl);
trace_tab ("Testing TCS_FIXEDWIDTH tabs with icon...\n");
trace_tab (" set size > icon...\n");
TabCheckSetSize(hwTab, 50, 30, 50, 30);
trace_tab (" set size < icon...\n");
TabCheckSetSize(hwTab, 20, 20, 25, 20);
trace_tab (" min size...\n");
TabCheckSetSize(hwTab, 0, 1, 25, 1);
trace (" TCS_FIXEDWIDTH buttons with icon...\n");
TabCheckSetSize(hwTab, 50, 30, 50, 30, "set size > icon");
TabCheckSetSize(hwTab, 20, 20, 25, 20, "set size < icon");
TabCheckSetSize(hwTab, 0, 1, 25, 1, "min size");
SendMessage(hwTab, TCM_SETPADDING, 0, MAKELPARAM(4,4));
TabCheckSetSize(hwTab, 0, 1, 25, 1, "set padding, min size");
DestroyWindow (hwTab);
trace_tab ("Testing TCS_FIXEDWIDTH buttons no icon...\n");
hwTab = create_tabcontrol(TCS_FIXEDWIDTH | TCS_BUTTONS);
hwTab = create_tabcontrol(TCS_FIXEDWIDTH | TCS_BOTTOM, TCIF_TEXT|TCIF_IMAGE);
SendMessage(hwTab, TCM_SETMINTABWIDTH, 0, nMinTabWidth);
trace (" TCS_FIXEDWIDTH | TCS_BOTTOM tabs...\n");
CheckSize(hwTab, TAB_DEFAULT_WIDTH, -1, "no icon, default width");
trace_tab (" default width...\n");
CheckSize(hwTab, TAB_DEFAULT_WIDTH, -1);
trace_tab (" set size 1...\n");
TabCheckSetSize(hwTab, 20, 20, 20, 20);
trace_tab (" set size 2...\n");
TabCheckSetSize(hwTab, 10, 50, 10, 50);
trace_tab (" min size...\n");
TabCheckSetSize(hwTab, 0, 1, 0, 1);
TabCheckSetSize(hwTab, 20, 20, 20, 20, "no icon, set size 1");
TabCheckSetSize(hwTab, 10, 50, 10, 50, "no icon, set size 2");
TabCheckSetSize(hwTab, 0, 1, 0, 1, "no icon, min size");
SendMessage(hwTab, TCM_SETIMAGELIST, 0, (LPARAM)himl);
trace_tab ("Testing TCS_FIXEDWIDTH buttons with icon...\n");
trace_tab (" set size > icon...\n");
TabCheckSetSize(hwTab, 50, 30, 50, 30);
trace_tab (" set size < icon...\n");
TabCheckSetSize(hwTab, 20, 20, 25, 20);
trace_tab (" min size...\n");
TabCheckSetSize(hwTab, 0, 1, 25, 1);
trace_tab (" Add padding...\n");
TabCheckSetSize(hwTab, 50, 30, 50, 30, "with icon, set size > icon");
TabCheckSetSize(hwTab, 20, 20, 25, 20, "with icon, set size < icon");
TabCheckSetSize(hwTab, 0, 1, 25, 1, "with icon, min size");
SendMessage(hwTab, TCM_SETPADDING, 0, MAKELPARAM(4,4));
trace_tab (" min size...\n");
TabCheckSetSize(hwTab, 0, 1, 25, 1);
TabCheckSetSize(hwTab, 0, 1, 25, 1, "set padding, min size");
DestroyWindow (hwTab);
hwTab = create_tabcontrol(TCS_FIXEDWIDTH | TCS_BOTTOM);
trace_tab ("Testing TCS_FIXEDWIDTH | TCS_BOTTOM tabs no icon...\n");
hwTab = create_tabcontrol(0, TCIF_TEXT|TCIF_IMAGE);
SendMessage(hwTab, TCM_SETMINTABWIDTH, 0, nMinTabWidth);
trace_tab (" default width...\n");
CheckSize(hwTab, TAB_DEFAULT_WIDTH, -1);
trace_tab (" set size 1...\n");
TabCheckSetSize(hwTab, 20, 20, 20, 20);
trace_tab (" set size 2...\n");
TabCheckSetSize(hwTab, 10, 50, 10, 50);
trace_tab (" min size...\n");
TabCheckSetSize(hwTab, 0, 1, 0, 1);
trace (" non fixed width, with text...\n");
CheckSize(hwTab, max(size.cx +TAB_PADDING_X*2, (nMinTabWidth < 0) ? DEFAULT_MIN_TAB_WIDTH : nMinTabWidth), -1,
"no icon, default width");
for (i=0; i<8; i++)
{
INT nTabWidth = (nMinTabWidth < 0) ? TabWidthPadded(i, 2) : nMinTabWidth;
SendMessage(hwTab, TCM_SETIMAGELIST, 0, (LPARAM)himl);
trace_tab ("Testing TCS_FIXEDWIDTH | TCS_BOTTOM tabs with icon...\n");
trace_tab (" set size > icon...\n");
TabCheckSetSize(hwTab, 50, 30, 50, 30);
trace_tab (" set size < icon...\n");
TabCheckSetSize(hwTab, 20, 20, 25, 20);
trace_tab (" min size...\n");
TabCheckSetSize(hwTab, 0, 1, 25, 1);
trace_tab (" Add padding...\n");
SendMessage(hwTab, TCM_SETPADDING, 0, MAKELPARAM(4,4));
trace_tab (" min size...\n");
TabCheckSetSize(hwTab, 0, 1, 25, 1);
SendMessage(hwTab, TCM_SETIMAGELIST, 0, 0);
SendMessage(hwTab, TCM_SETPADDING, 0, MAKELPARAM(i,i));
TabCheckSetSize(hwTab, 50, 20, max(size.cx + i*2, nTabWidth), 20, "no icon, set size");
TabCheckSetSize(hwTab, 0, 1, max(size.cx + i*2, nTabWidth), 1, "no icon, min size");
SendMessage(hwTab, TCM_SETIMAGELIST, 0, (LPARAM)himl);
nTabWidth = (nMinTabWidth < 0) ? TabWidthPadded(i, 3) : nMinTabWidth;
TabCheckSetSize(hwTab, 50, 30, max(size.cx + 21 + i*3, nTabWidth), 30, "with icon, set size > icon");
TabCheckSetSize(hwTab, 20, 20, max(size.cx + 21 + i*3, nTabWidth), 20, "with icon, set size < icon");
TabCheckSetSize(hwTab, 0, 1, max(size.cx + 21 + i*3, nTabWidth), 1, "with icon, min size");
}
DestroyWindow (hwTab);
hwTab = create_tabcontrol(0, TCIF_IMAGE);
SendMessage(hwTab, TCM_SETMINTABWIDTH, 0, nMinTabWidth);
trace (" non fixed width, no text...\n");
CheckSize(hwTab, (nMinTabWidth < 0) ? DEFAULT_MIN_TAB_WIDTH : nMinTabWidth, -1, "no icon, default width");
for (i=0; i<8; i++)
{
INT nTabWidth = (nMinTabWidth < 0) ? TabWidthPadded(i, 2) : nMinTabWidth;
SendMessage(hwTab, TCM_SETIMAGELIST, 0, 0);
SendMessage(hwTab, TCM_SETPADDING, 0, MAKELPARAM(i,i));
TabCheckSetSize(hwTab, 50, 20, nTabWidth, 20, "no icon, set size");
TabCheckSetSize(hwTab, 0, 1, nTabWidth, 1, "no icon, min size");
SendMessage(hwTab, TCM_SETIMAGELIST, 0, (LPARAM)himl);
if (i > 1 && nMinTabWidth > 0 && nMinTabWidth < DEFAULT_MIN_TAB_WIDTH)
nTabWidth += EXTRA_ICON_PADDING *(i-1);
TabCheckSetSize(hwTab, 50, 30, nTabWidth, 30, "with icon, set size > icon");
TabCheckSetSize(hwTab, 20, 20, nTabWidth, 20, "with icon, set size < icon");
TabCheckSetSize(hwTab, 0, 1, nTabWidth, 1, "with icon, min size");
}
DestroyWindow (hwTab);
ImageList_Destroy(himl);
DeleteObject(hFont);
}
START_TEST(tab)
{
LOGFONTA logfont;
lstrcpyA(logfont.lfFaceName, "Arial");
memset(&logfont, 0, sizeof(logfont));
logfont.lfHeight = -12;
logfont.lfWeight = FW_NORMAL;
logfont.lfCharSet = ANSI_CHARSET;
hFont = CreateFontIndirectA(&logfont);
InitCommonControls();
trace ("Testing with default MinWidth\n");
test_tab(-1);
trace ("Testing with MinWidth set to -3\n");
test_tab(-3);
trace ("Testing with MinWidth set to 24\n");
test_tab(24);
trace ("Testing with MinWidth set to 54\n");
test_tab(54);
trace ("Testing with MinWidth set to 94\n");
test_tab(94);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment