From fe2ec559ed6b54e2b693f74ca0dcfabb9776e6c0 Mon Sep 17 00:00:00 2001 From: csaba Date: Sun, 5 Nov 2023 15:24:15 +0000 Subject: Attempt to fix the bug [eedd2e078d] (ttk::notebook looks bad when tabs are positioned on edges other than the top). --- generic/ttk/ttkClamTheme.c | 110 ++++++++++++++++++++++++------ generic/ttk/ttkElements.c | 133 ++++++++++++++++++++++++++++++------ generic/ttk/ttkNotebook.c | 15 ++++- win/ttkWinTheme.c | 163 +++++++++++++++++++++++++++++++++++++++++++++ win/ttkWinXPTheme.c | 107 ++++++++++++++++++++++++++++- 5 files changed, 484 insertions(+), 44 deletions(-) diff --git a/generic/ttk/ttkClamTheme.c b/generic/ttk/ttkClamTheme.c index f6cd38c..971bdc0 100644 --- a/generic/ttk/ttkClamTheme.c +++ b/generic/ttk/ttkClamTheme.c @@ -959,6 +959,8 @@ static const Ttk_ElementOptionSpec NotebookElementOptions[] = { { NULL, TK_OPTION_BOOLEAN, 0, NULL } }; +extern Ttk_PositionSpec nbTabsStickBit; /* see ttkNotebook.c */ + static void TabElementSize( void *dummy, void *elementRecord, Tk_Window tkwin, int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) @@ -970,8 +972,7 @@ static void TabElementSize( (void)widthPtr; (void)heightPtr; - paddingPtr->top = paddingPtr->left = paddingPtr->right = borderWidth; - paddingPtr->bottom = 0; + *paddingPtr = Ttk_UniformPadding((short)borderWidth); } static void TabElementDraw( @@ -981,35 +982,106 @@ static void TabElementDraw( NotebookElement *tab = (NotebookElement *)elementRecord; Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, tab->backgroundObj); Display *display = Tk_Display(tkwin); - int borderWidth = 2, dh = 0; - int x1,y1,x2,y2; + int borderWidth = 2, delta = 0; + int x1, y1, x2, y2; GC gc; const int w = WIN32_XDRAWLINE_HACK; (void)dummy; if (state & TTK_STATE_SELECTED) { - dh = borderWidth; + delta = borderWidth; } - if (state & TTK_STATE_USER2) { /* Rightmost tab */ - --b.width; - } + switch (nbTabsStickBit) { + default: + case TTK_STICK_S: + if (state & TTK_STATE_USER2) { /* rightmost tab */ + --b.width; + } - Tk_Fill3DRectangle(tkwin, d, border, - b.x+2, b.y+2, b.width-1, b.height-2+dh, borderWidth, TK_RELIEF_FLAT); + Tk_Fill3DRectangle(tkwin, d, border, + b.x+2, b.y+2, b.width-1, b.height-2+delta, + borderWidth, TK_RELIEF_FLAT); + + x1 = b.x; y1 = b.y; /* top left */ + x2 = b.x + b.width; y2 = b.y + b.height-1; /* bottom right */ + + gc = Ttk_GCForColor(tkwin, tab->borderColorObj, d); + XDrawLine(display, d, gc, x1, y1+1, x1, y2+1+w); + XDrawLine(display, d, gc, x2, y1+1, x2, y2+1+w); + XDrawLine(display, d, gc, x1+1, y1, x2-1+w, y1); - x1 = b.x, x2 = b.x + b.width; - y1 = b.y, y2 = b.y + b.height; + gc = Ttk_GCForColor(tkwin, tab->lightColorObj, d); + XDrawLine(display, d, gc, x1+1, y1+1, x1+1, y2+delta+w); + XDrawLine(display, d, gc, x1+1, y1+1, x2-1+w, y1+1); + break; + + case TTK_STICK_N: + if (state & TTK_STATE_USER2) { /* rightmost tab */ + --b.width; + } + + Tk_Fill3DRectangle(tkwin, d, border, + b.x+2, b.y-delta, b.width-1, b.height-2+delta, + borderWidth, TK_RELIEF_FLAT); + x1 = b.x; y1 = b.y + b.height-1; /* bottom left */ + x2 = b.x + b.width; y2 = b.y; /* top right */ - gc=Ttk_GCForColor(tkwin,tab->borderColorObj,d); - XDrawLine(display,d,gc, x1,y1+1, x1,y2+w); - XDrawLine(display,d,gc, x2,y1+1, x2,y2+w); - XDrawLine(display,d,gc, x1+1,y1, x2-1+w,y1); + gc = Ttk_GCForColor(tkwin, tab->borderColorObj, d); + XDrawLine(display, d, gc, x1, y1-1, x1, y2-1-w); + XDrawLine(display, d, gc, x2, y1-1, x2, y2-1-w); + XDrawLine(display, d, gc, x1+1, y1, x2-1+w, y1); - gc=Ttk_GCForColor(tkwin,tab->lightColorObj,d); - XDrawLine(display,d,gc, x1+1,y1+1, x1+1,y2-1+dh+w); - XDrawLine(display,d,gc, x1+1,y1+1, x2-1+w,y1+1); + gc = Ttk_GCForColor(tkwin, tab->lightColorObj, d); + XDrawLine(display, d, gc, x1+1, y1-1, x1+1, y2-delta-w); + XDrawLine(display, d, gc, x1+1, y1-1, x2-1+w, y1-1); + break; + + case TTK_STICK_E: + if (state & TTK_STATE_USER2) { /* bottommost tab */ + --b.height; + } + + Tk_Fill3DRectangle(tkwin, d, border, + b.x+2, b.y+2, b.width-2+delta, b.height-1, + borderWidth, TK_RELIEF_FLAT); + + x1 = b.x; y1 = b.y; /* top left */ + x2 = b.x + b.width-1; y2 = b.y + b.height; /* bottom right */ + + gc = Ttk_GCForColor(tkwin, tab->borderColorObj, d); + XDrawLine(display, d, gc, x1, y1+1, x1, y2-1+w); + XDrawLine(display, d, gc, x1+1, y1, x2+1+w, y1); + XDrawLine(display, d, gc, x1+1, y2, x2+1+w, y2); + + gc = Ttk_GCForColor(tkwin, tab->lightColorObj, d); + XDrawLine(display, d, gc, x1+1, y1+1, x1+1, y2-1+w); + XDrawLine(display, d, gc, x1+1, y1+1, x2+delta+w, y1+1); + break; + + case TTK_STICK_W: + if (state & TTK_STATE_USER2) { /* bottommost tab */ + --b.height; + } + + Tk_Fill3DRectangle(tkwin, d, border, + b.x-delta, b.y+2, b.width-2+delta, b.height-1, + borderWidth, TK_RELIEF_FLAT); + + x1 = b.x + b.width-1; y1 = b.y; /* top right */ + x2 = b.x; y2 = b.y + b.height; /* bottom left */ + + gc = Ttk_GCForColor(tkwin, tab->borderColorObj, d); + XDrawLine(display, d, gc, x1, y1+1, x1, y2-1+w); + XDrawLine(display, d, gc, x1-1, y1, x2-1-w, y1); + XDrawLine(display, d, gc, x1-1, y2, x2-1-w, y2); + + gc = Ttk_GCForColor(tkwin, tab->lightColorObj, d); + XDrawLine(display, d, gc, x1-1, y1+1, x1-1, y2-1+w); + XDrawLine(display, d, gc, x1-1, y1+1, x2-delta-w, y1+1); + break; + } } static const Ttk_ElementSpec TabElementSpec = diff --git a/generic/ttk/ttkElements.c b/generic/ttk/ttkElements.c index bc53bac..908f9c2 100644 --- a/generic/ttk/ttkElements.c +++ b/generic/ttk/ttkElements.c @@ -1601,6 +1601,8 @@ static const Ttk_ElementOptionSpec TabElementOptions[] = { {0,TK_OPTION_BOOLEAN,0,0} }; +extern Ttk_PositionSpec nbTabsStickBit; /* see ttkNotebook.c */ + static void TabElementSize( void *dummy, void *elementRecord, Tk_Window tkwin, int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) @@ -1612,8 +1614,7 @@ static void TabElementSize( (void)heightPtr; Tk_GetPixelsFromObj(0, tkwin, tab->borderWidthObj, &borderWidth); - paddingPtr->top = paddingPtr->left = paddingPtr->right = borderWidth; - paddingPtr->bottom = 0; + *paddingPtr = Ttk_UniformPadding((short)borderWidth); } static void TabElementDraw( @@ -1622,51 +1623,145 @@ static void TabElementDraw( { TabElement *tab = (TabElement *)elementRecord; Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, tab->backgroundObj); - int borderWidth = 1, highlight = 0; + int highlight = 0; + XColor *hlColor = NULL; XPoint pts[6]; - int n = 0; double scalingLevel = TkScalingLevel(tkwin); int cut = round(2 * scalingLevel); Display *disp = Tk_Display(tkwin); + int borderWidth = 1; (void)dummy; - Tcl_GetIntFromObj(NULL, tab->borderWidthObj, &borderWidth); - if (state & TTK_STATE_SELECTED) { /* * Draw slightly outside of the allocated parcel, * to overwrite the client area border. */ - b.height += borderWidth; + switch (nbTabsStickBit) { + default: + case TTK_STICK_S: + b.height += 1; + break; + case TTK_STICK_N: + b.height += 1; b.y -= 1; + break; + case TTK_STICK_E: + b.width += 1; + break; + case TTK_STICK_W: + b.width += 1; b.x -= 1; + break; + } Tcl_GetBooleanFromObj(NULL, tab->highlightObj, &highlight); + if (highlight) { + hlColor = Tk_GetColorFromObj(tkwin, tab->highlightColorObj); + } } - pts[n].x = b.x; pts[n].y = b.y + b.height - 1; ++n; - pts[n].x = b.x; pts[n].y = b.y + cut; ++n; - pts[n].x = b.x + cut; pts[n].y = b.y; ++n; - pts[n].x = b.x + b.width-1-cut; pts[n].y = b.y; ++n; - pts[n].x = b.x + b.width-1; pts[n].y = b.y + cut; ++n; - pts[n].x = b.x + b.width-1; pts[n].y = b.y + b.height; ++n; + switch (nbTabsStickBit) { + default: + case TTK_STICK_S: + pts[0].x = b.x; pts[0].y = b.y + b.height-1; + pts[1].x = b.x; pts[1].y = b.y + cut; + pts[2].x = b.x + cut; pts[2].y = b.y; + pts[3].x = b.x + b.width-1 - cut; pts[3].y = b.y; + pts[4].x = b.x + b.width-1; pts[4].y = b.y + cut; + pts[5].x = b.x + b.width-1; pts[5].y = b.y + b.height; + break; + case TTK_STICK_N: + pts[0].x = b.x; pts[0].y = b.y; + pts[1].x = b.x; pts[1].y = b.y + b.height-1 - cut; + pts[2].x = b.x + cut; pts[2].y = b.y + b.height-1; + pts[3].x = b.x + b.width-1 - cut; pts[3].y = b.y + b.height-1; + pts[4].x = b.x + b.width-1; pts[4].y = b.y + b.height-1 - cut; + pts[5].x = b.x + b.width-1; pts[5].y = b.y-1; + break; + case TTK_STICK_E: + pts[0].x = b.x + b.width-1; pts[0].y = b.y; + pts[1].x = b.x + cut; pts[1].y = b.y; + pts[2].x = b.x; pts[2].y = b.y + cut; + pts[3].x = b.x; pts[3].y = b.y + b.height-1 - cut; + pts[4].x = b.x + cut; pts[4].y = b.y + b.height-1; + pts[5].x = b.x + b.width; pts[5].y = b.y + b.height-1; + break; + case TTK_STICK_W: + pts[0].x = b.x; pts[0].y = b.y; + pts[1].x = b.x + b.width-1 - cut; pts[1].y = b.y; + pts[2].x = b.x + b.width-1; pts[2].y = b.y + cut; + pts[3].x = b.x + b.width-1; pts[3].y = b.y + b.height-1 - cut; + pts[4].x = b.x + b.width-1 - cut; pts[4].y = b.y + b.height-1; + pts[5].x = b.x-1; pts[5].y = b.y + b.height-1; + break; + } XFillPolygon(disp, d, Tk_3DBorderGC(tkwin, border, TK_3D_FLAT_GC), pts, 6, Convex, CoordModeOrigin); - pts[5].y -= 1 - WIN32_XDRAWLINE_HACK; + switch (nbTabsStickBit) { + default: + case TTK_STICK_S: + pts[5].y -= 1 - WIN32_XDRAWLINE_HACK; + break; + case TTK_STICK_N: + pts[5].y += 1 - WIN32_XDRAWLINE_HACK; + break; + case TTK_STICK_E: + pts[5].x -= 1 - WIN32_XDRAWLINE_HACK; + break; + case TTK_STICK_W: + pts[5].x += 1 - WIN32_XDRAWLINE_HACK; + break; + } + Tcl_GetIntFromObj(NULL, tab->borderWidthObj, &borderWidth); while (borderWidth--) { XDrawLines(disp, d, Tk_3DBorderGC(tkwin, border, TK_3D_LIGHT_GC), pts, 4, CoordModeOrigin); XDrawLines(disp, d, Tk_3DBorderGC(tkwin, border, TK_3D_DARK_GC), pts+3, 3, CoordModeOrigin); - ++pts[0].x; ++pts[1].x; ++pts[2].x; --pts[4].x; --pts[5].x; - ++pts[2].y; ++pts[3].y; + + switch (nbTabsStickBit) { + default: + case TTK_STICK_S: + ++pts[0].x; ++pts[1].x; ++pts[2].y; + ++pts[3].y; --pts[4].x; --pts[5].x; + break; + case TTK_STICK_N: + ++pts[0].x; ++pts[1].x; --pts[2].y; + --pts[3].y; --pts[4].x; --pts[5].x; + break; + case TTK_STICK_E: + ++pts[0].y; ++pts[1].y; ++pts[2].x; + ++pts[3].x; --pts[4].y; --pts[5].y; + break; + case TTK_STICK_W: + ++pts[0].y; ++pts[1].y; --pts[2].x; + --pts[3].x; --pts[4].y; --pts[5].y; + break; + } } if (highlight) { - XColor *hlColor = Tk_GetColorFromObj(tkwin, tab->highlightColorObj); - XFillRectangle(disp, d, Tk_GCForColor(hlColor, d), - b.x + cut, b.y, b.width - 2*cut, cut); + switch (nbTabsStickBit) { + default: + case TTK_STICK_S: + XFillRectangle(disp, d, Tk_GCForColor(hlColor, d), + b.x + cut, b.y, b.width - 2*cut, cut); + break; + case TTK_STICK_N: + XFillRectangle(disp, d, Tk_GCForColor(hlColor, d), + b.x + cut, b.y + b.height - cut, b.width - 2*cut, cut); + break; + case TTK_STICK_E: + XFillRectangle(disp, d, Tk_GCForColor(hlColor, d), + b.x, b.y + cut, cut, b.height - 2*cut); + break; + case TTK_STICK_W: + XFillRectangle(disp, d, Tk_GCForColor(hlColor, d), + b.x + b.width - cut, b.y + cut, cut, b.height - 2*cut); + break; + } } } diff --git a/generic/ttk/ttkNotebook.c b/generic/ttk/ttkNotebook.c index c373587..8417820 100644 --- a/generic/ttk/ttkNotebook.c +++ b/generic/ttk/ttkNotebook.c @@ -135,6 +135,11 @@ typedef struct Ttk_Padding padding; /* External padding */ } NotebookStyle; +/* Global variable to be set from within NotebookStyleOptions() to one + * of the values TTK_STICK_S, TTK_STICK_N, TTK_STICK_E, or TTK_STICK_W: + */ +Ttk_PositionSpec nbTabsStickBit; + static void NotebookStyleOptions(Notebook *nb, NotebookStyle *nbstyle) { Tcl_Obj *objPtr; @@ -159,6 +164,10 @@ static void NotebookStyleOptions(Notebook *nb, NotebookStyle *nbstyle) TtkGetLabelAnchorFromObj(NULL, objPtr, &nbstyle->tabPlacement); } + /* Save the stick bit in the global variable nbTabsStickBit + */ + nbTabsStickBit = (nbstyle->tabPlacement & 0x0f); + /* Compute tabOrient as function of tabPlacement: */ if (nbstyle->tabPlacement & (TTK_PACK_LEFT|TTK_PACK_RIGHT)) { @@ -1415,9 +1424,9 @@ TTK_END_LAYOUT TTK_BEGIN_LAYOUT(TabLayout) TTK_GROUP("Notebook.tab", TTK_FILL_BOTH, - TTK_GROUP("Notebook.padding", TTK_PACK_TOP|TTK_FILL_BOTH, - TTK_GROUP("Notebook.focus", TTK_PACK_TOP|TTK_FILL_BOTH, - TTK_NODE("Notebook.label", TTK_PACK_TOP)))) + TTK_GROUP("Notebook.padding", TTK_FILL_BOTH, + TTK_GROUP("Notebook.focus", TTK_FILL_BOTH, + TTK_NODE("Notebook.label", TTK_FILL_BOTH)))) TTK_END_LAYOUT /*------------------------------------------------------------------------ diff --git a/win/ttkWinTheme.c b/win/ttkWinTheme.c index d526bfe..7f5450f 100644 --- a/win/ttkWinTheme.c +++ b/win/ttkWinTheme.c @@ -725,6 +725,168 @@ static const Ttk_ElementSpec SliderElementSpec = { * +++ Notebook elements. */ +typedef struct { + Tcl_Obj *borderWidthObj; + Tcl_Obj *backgroundObj; +} TabElement; + +static const Ttk_ElementOptionSpec TabElementOptions[] = { + { "-borderwidth", TK_OPTION_PIXELS, + offsetof(TabElement,borderWidthObj), "1" }, + { "-background", TK_OPTION_BORDER, + offsetof(TabElement,backgroundObj), DEFAULT_BACKGROUND }, + {0,TK_OPTION_BOOLEAN,0,0} +}; + +extern Ttk_PositionSpec nbTabsStickBit; /* see ttkNotebook.c */ + +static void TabElementSize( + TCL_UNUSED(void *), + void *elementRecord, + Tk_Window tkwin, + TCL_UNUSED(void *), + TCL_UNUSED(void *), + Ttk_Padding *paddingPtr) +{ + TabElement *tab = (TabElement *)elementRecord; + int borderWidth = 1; + + Tk_GetPixelsFromObj(0, tkwin, tab->borderWidthObj, &borderWidth); + *paddingPtr = Ttk_UniformPadding((short)borderWidth); +} + +static void TabElementDraw( + TCL_UNUSED(void *), + void *elementRecord, + Tk_Window tkwin, + Drawable d, + Ttk_Box b, + unsigned int state) +{ + TabElement *tab = (TabElement *)elementRecord; + Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, tab->backgroundObj); + XPoint pts[6]; + double scalingLevel = TkScalingLevel(tkwin); + int cut = round(2 * scalingLevel); + Display *disp = Tk_Display(tkwin); + int borderWidth = 1; + + /* + * Correct the coordinates of b if needed. + */ + switch (nbTabsStickBit) { + default: + case TTK_STICK_S: + break; + case TTK_STICK_N: + b.y -= 2; + break; + case TTK_STICK_E: + b.x += 2; + break; + case TTK_STICK_W: + b.x -= 2; + break; + } + + if (state & TTK_STATE_SELECTED) { + /* + * Draw slightly outside of the allocated parcel, + * to overwrite the client area border. + */ + switch (nbTabsStickBit) { + default: + case TTK_STICK_S: + b.height += 2; + break; + case TTK_STICK_N: + b.height += 2; b.y -= 2; + break; + case TTK_STICK_E: + b.width += 2; + break; + case TTK_STICK_W: + b.width += 2; b.x -= 2; + break; + } + } + + switch (nbTabsStickBit) { + default: + case TTK_STICK_S: + pts[0].x = b.x; pts[0].y = b.y + b.height-1; + pts[1].x = b.x; pts[1].y = b.y + cut; + pts[2].x = b.x + cut; pts[2].y = b.y; + pts[3].x = b.x + b.width-1 - cut; pts[3].y = b.y; + pts[4].x = b.x + b.width-1; pts[4].y = b.y + cut; + pts[5].x = b.x + b.width-1; pts[5].y = b.y + b.height; + break; + case TTK_STICK_N: + pts[0].x = b.x; pts[0].y = b.y; + pts[1].x = b.x; pts[1].y = b.y + b.height-1 - cut; + pts[2].x = b.x + cut; pts[2].y = b.y + b.height-1; + pts[3].x = b.x + b.width-1 - cut; pts[3].y = b.y + b.height-1; + pts[4].x = b.x + b.width-1; pts[4].y = b.y + b.height-1 - cut; + pts[5].x = b.x + b.width-1; pts[5].y = b.y-1; + break; + case TTK_STICK_E: + pts[0].x = b.x + b.width-1; pts[0].y = b.y; + pts[1].x = b.x + cut; pts[1].y = b.y; + pts[2].x = b.x; pts[2].y = b.y + cut; + pts[3].x = b.x; pts[3].y = b.y + b.height-1 - cut; + pts[4].x = b.x + cut; pts[4].y = b.y + b.height-1; + pts[5].x = b.x + b.width; pts[5].y = b.y + b.height-1; + break; + case TTK_STICK_W: + pts[0].x = b.x; pts[0].y = b.y; + pts[1].x = b.x + b.width-1 - cut; pts[1].y = b.y; + pts[2].x = b.x + b.width-1; pts[2].y = b.y + cut; + pts[3].x = b.x + b.width-1; pts[3].y = b.y + b.height-1 - cut; + pts[4].x = b.x + b.width-1 - cut; pts[4].y = b.y + b.height-1; + pts[5].x = b.x-1; pts[5].y = b.y + b.height-1; + break; + } + + XFillPolygon(disp, d, Tk_3DBorderGC(tkwin, border, TK_3D_FLAT_GC), + pts, 6, Convex, CoordModeOrigin); + + Tcl_GetIntFromObj(NULL, tab->borderWidthObj, &borderWidth); + while (borderWidth--) { + XDrawLines(disp, d, Tk_3DBorderGC(tkwin, border, TK_3D_LIGHT_GC), + pts, 4, CoordModeOrigin); + XDrawLines(disp, d, Tk_3DBorderGC(tkwin, border, TK_3D_DARK_GC), + pts+3, 3, CoordModeOrigin); + + switch (nbTabsStickBit) { + default: + case TTK_STICK_S: + ++pts[0].x; ++pts[1].x; ++pts[2].y; + ++pts[3].y; --pts[4].x; --pts[5].x; + break; + case TTK_STICK_N: + ++pts[0].x; ++pts[1].x; --pts[2].y; + --pts[3].y; --pts[4].x; --pts[5].x; + break; + case TTK_STICK_E: + ++pts[0].y; ++pts[1].y; ++pts[2].x; + ++pts[3].x; --pts[4].y; --pts[5].y; + break; + case TTK_STICK_W: + ++pts[0].y; ++pts[1].y; --pts[2].x; + --pts[3].x; --pts[4].y; --pts[5].y; + break; + } + } +} + +static const Ttk_ElementSpec TabElementSpec = { + TK_STYLE_VERSION_2, + sizeof(TabElement), + TabElementOptions, + TabElementSize, + TabElementDraw +}; + static void ClientElementSize( TCL_UNUSED(void *), TCL_UNUSED(void *), @@ -814,6 +976,7 @@ int TtkWinTheme_Init( Ttk_RegisterElementSpec(themePtr, "Scrollbar.trough", &TroughElementSpec, TroughClientDataInit(interp)); + Ttk_RegisterElementSpec(themePtr, "tab", &TabElementSpec, NULL); Ttk_RegisterElementSpec(themePtr, "client", &ClientElementSpec, NULL); for (fce = FrameControlElements; fce->name != 0; ++fce) { diff --git a/win/ttkWinXPTheme.c b/win/ttkWinXPTheme.c index 1ad3bfc..a4b53fc 100644 --- a/win/ttkWinXPTheme.c +++ b/win/ttkWinXPTheme.c @@ -27,6 +27,10 @@ typedef HRESULT (STDAPICALLTYPE CloseThemeDataProc)(HTHEME hTheme); typedef HRESULT (STDAPICALLTYPE DrawThemeBackgroundProc)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, const RECT *pRect, OPTIONAL const RECT *pClipRect); +typedef HRESULT (STDAPICALLTYPE DrawThemeEdgeProc)(HTHEME hTheme, + HDC hdc, int iPartId, int iStateId, const RECT *pDestRect, + unsigned int uEdge, unsigned int uFlags, + OPTIONAL RECT *pContentRect); typedef HRESULT (STDAPICALLTYPE GetThemePartSizeProc)(HTHEME,HDC, int iPartId, int iStateId, RECT *prc, enum THEMESIZE eSize, SIZE *psz); @@ -48,6 +52,7 @@ typedef struct GetThemePartSizeProc *GetThemePartSize; GetThemeSysSizeProc *GetThemeSysSize; DrawThemeBackgroundProc *DrawThemeBackground; + DrawThemeEdgeProc *DrawThemeEdge; DrawThemeTextProc *DrawThemeText; GetThemeTextExtentProc *GetThemeTextExtent; IsThemeActiveProc *IsThemeActive; @@ -101,6 +106,7 @@ LoadXPThemeProcs(HINSTANCE *phlib) && LOADPROC(GetThemePartSize) && LOADPROC(GetThemeSysSize) && LOADPROC(DrawThemeBackground) + && LOADPROC(DrawThemeEdge) && LOADPROC(GetThemeTextExtent) && LOADPROC(DrawThemeText) && LOADPROC(IsThemeActive) @@ -719,6 +725,38 @@ static const Ttk_ElementSpec PbarElementSpec = * The TIS_* and TILES_* definitions are identical, so * we can use the same statemap no matter what the partId. */ + +extern Ttk_PositionSpec nbTabsStickBit; /* see ttkNotebook.c */ + +static void TabElementSize( + void *clientData, + void *elementRecord, + Tk_Window tkwin, + int *widthPtr, + int *heightPtr, + Ttk_Padding *paddingPtr) +{ + GenericElementSize(clientData, elementRecord, tkwin, + widthPtr, heightPtr, paddingPtr); + + *paddingPtr = Ttk_UniformPadding(3); + switch (nbTabsStickBit) { + default: + case TTK_STICK_S: + paddingPtr->bottom = 0; + break; + case TTK_STICK_N: + paddingPtr->top = 0; + break; + case TTK_STICK_E: + paddingPtr->right = 0; + break; + case TTK_STICK_W: + paddingPtr->left = 0; + break; + } +} + static void TabElementDraw( void *clientData, TCL_UNUSED(void *), @@ -729,15 +767,78 @@ static void TabElementDraw( { ElementData *elementData = (ElementData *)clientData; int partId = elementData->info->partId; + int stateId = Ttk_StateTableLookup(elementData->info->statemap, state); + + /* + * Correct the coordinates of b if needed + */ + switch (nbTabsStickBit) { + default: + case TTK_STICK_S: + break; + case TTK_STICK_N: + b.y -= 4; + break; + case TTK_STICK_E: + b.x += 3; + break; + case TTK_STICK_W: + b.x -= 5; + break; + } + RECT rc = BoxToRect(b); if (!InitElementData(elementData, tkwin, d)) return; + if (state & TTK_STATE_USER1) partId = TABP_TABITEMLEFTEDGE; elementData->procs->DrawThemeBackground( - elementData->hTheme, elementData->hDC, partId, - Ttk_StateTableLookup(elementData->info->statemap, state), &rc, NULL); + elementData->hTheme, elementData->hDC, partId, stateId, &rc, NULL); + + if (nbTabsStickBit != TTK_STICK_S) { + /* + * Erase the border + */ + elementData->procs->DrawThemeEdge( + elementData->hTheme, elementData->hDC, partId, stateId, &rc, + BDR_RAISEDINNER, BF_MONO|BF_RECT, NULL); + } + + if (state & TTK_STATE_SELECTED) { + /* + * Draw a flat border at 3 edges + */ + switch (nbTabsStickBit) { + default: + case TTK_STICK_S: + break; + case TTK_STICK_N: + elementData->procs->DrawThemeEdge( + elementData->hTheme, elementData->hDC, partId, stateId, &rc, + BDR_RAISEDINNER, BF_FLAT|BF_LEFT|BF_RIGHT|BF_BOTTOM, NULL); + break; + case TTK_STICK_E: + elementData->procs->DrawThemeEdge( + elementData->hTheme, elementData->hDC, partId, stateId, &rc, + BDR_RAISEDINNER, BF_FLAT|BF_LEFT|BF_TOP|BF_BOTTOM, NULL); + break; + case TTK_STICK_W: + elementData->procs->DrawThemeEdge( + elementData->hTheme, elementData->hDC, partId, stateId, &rc, + BDR_RAISEDINNER, BF_FLAT|BF_TOP|BF_RIGHT|BF_BOTTOM, NULL); + break; + } + } else if (nbTabsStickBit != TTK_STICK_S) { + /* + * Draw a flat border at all 4 edges + */ + elementData->procs->DrawThemeEdge( + elementData->hTheme, elementData->hDC, partId, stateId, &rc, + BDR_RAISEDINNER, BF_FLAT|BF_RECT, NULL); + } + FreeElementData(elementData); } @@ -746,7 +847,7 @@ static const Ttk_ElementSpec TabElementSpec = TK_STYLE_VERSION_2, sizeof(NullElement), TtkNullElementOptions, - GenericElementSize, + TabElementSize, TabElementDraw }; -- cgit v0.12