diff options
author | csaba <csaba> | 2023-11-05 15:24:15 (GMT) |
---|---|---|
committer | csaba <csaba> | 2023-11-05 15:24:15 (GMT) |
commit | fe2ec559ed6b54e2b693f74ca0dcfabb9776e6c0 (patch) | |
tree | 795f688becdb1ab5b7efe53296ab01fff4a82002 /win | |
parent | 7b562ef10e88fa07f7439e279490e20eaf528944 (diff) | |
download | tk-fe2ec559ed6b54e2b693f74ca0dcfabb9776e6c0.zip tk-fe2ec559ed6b54e2b693f74ca0dcfabb9776e6c0.tar.gz tk-fe2ec559ed6b54e2b693f74ca0dcfabb9776e6c0.tar.bz2 |
Attempt to fix the bug [eedd2e078d] (ttk::notebook looks bad when tabs are positioned on edges other than the top).
Diffstat (limited to 'win')
-rw-r--r-- | win/ttkWinTheme.c | 163 | ||||
-rw-r--r-- | win/ttkWinXPTheme.c | 107 |
2 files changed, 267 insertions, 3 deletions
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 }; |