diff options
-rw-r--r-- | doc/ttk_notebook.n | 41 | ||||
-rw-r--r-- | generic/ttk/ttkClamTheme.c | 125 | ||||
-rw-r--r-- | generic/ttk/ttkElements.c | 148 | ||||
-rw-r--r-- | generic/ttk/ttkNotebook.c | 9 | ||||
-rw-r--r-- | win/ttkWinTheme.c | 159 | ||||
-rw-r--r-- | win/ttkWinXPTheme.c | 111 |
6 files changed, 548 insertions, 45 deletions
diff --git a/doc/ttk_notebook.n b/doc/ttk_notebook.n index 869e4bf..84b6495 100644 --- a/doc/ttk_notebook.n +++ b/doc/ttk_notebook.n @@ -230,7 +230,15 @@ are: .br \fB\-tabmargins\fP \fIpadding\fP .br -\fB\-tabposition\fP \fIside\fP +\fB\-tabposition\fP \fIposition\fP +.RS +Specifies the position of the tab row or column as a string of length +1 or 2. The first character indicates the side as \fBn\fP, \fBs\fP, +\fBw\fP, or \fBe\fP, while the second character (if present) is the +sticky bit (specified as \fBw\fP, \fBe\fP, \fBn\fP, or \fBs\fP) within +the tab position. The default position is \fBn\fP for the \fBaqua\fP +theme and \fBnw\fP for all the other built-in themes. +.RE .br .PP \fBTNotebook.Tab\fP styling options configurable with \fBttk::style\fP @@ -247,12 +255,43 @@ are: Defines how much the tab grows in size. Usually used with the \fBselected\fP dynamic state. \fB\-tabmargins\fP should be set appropriately so that there is room for the tab growth. +For example, the Ttk library file \fBvistaTheme.tcl\fP contains +the lines +.CS +ttk::style configure TNotebook -tabmargins {2 2 2 0} +ttk::style map TNotebook.Tab -expand {selected {2 2 2 2}} +.CE +which are valid for the default value \fBnw\fP of the \fB\-tabposition\fP +style option. For a \fBttk::notebook\fP style \fBnbStyle\fP defined by +.CS +set nbStyle SW.TNotebook +ttk::style configure $nbStyle -tabposition sw +.CE +you will have to adapt the above settings as follows: +.CS +ttk::style configure $nbStyle -tabmargins {2 0 2 2} +ttk::style map $nbStyle.Tab -expand {selected {2 2 2 2}} +.CE .RE \fB\-font\fP \fIfont\fP .br \fB\-foreground\fP \fIcolor\fP .br \fB\-padding\fP \fIpadding\fP +.RS +Some themes (e.g., \fBclam\fP) use a different \fIpadding\fP for the +selected tab. For example, the Ttk library file \fBclamTheme.tcl\fP +contains the lines +.CS +ttk::style configure TNotebook.Tab \\ + -padding {4.5p 1.5p 4.5p 1.5p} +ttk::style map TNotebook.Tab \\ + -padding {selected {4.5p 3p 4.5p 1.5p}} +.CE +which are valid for the default value \fBnw\fP of the \fB\-tabposition\fP +style option. Again, for a different tab position you will have to adapt +the above settings accordingly. +.RE .PP Some options are only available for specific themes. .PP diff --git a/generic/ttk/ttkClamTheme.c b/generic/ttk/ttkClamTheme.c index f6cd38c..70d1938 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,22 @@ static void TabElementSize( (void)widthPtr; (void)heightPtr; - paddingPtr->top = paddingPtr->left = paddingPtr->right = borderWidth; - paddingPtr->bottom = 0; + *paddingPtr = Ttk_UniformPadding((short)borderWidth); + 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( @@ -981,35 +997,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); + + 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; + } - x1 = b.x, x2 = b.x + b.width; - y1 = b.y, y2 = b.y + b.height; + 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..5e8351e 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,22 @@ 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); + 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( @@ -1622,51 +1638,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..7bb3683 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)) { diff --git a/win/ttkWinTheme.c b/win/ttkWinTheme.c index d526bfe..0c1c651 100644 --- a/win/ttkWinTheme.c +++ b/win/ttkWinTheme.c @@ -725,6 +725,164 @@ 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); + 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( + 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; + + 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: + 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 +972,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..03bbc48 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,76 @@ static void TabElementDraw( { ElementData *elementData = (ElementData *)clientData; int partId = elementData->info->partId; + int isSelected = (state & TTK_STATE_SELECTED); + int stateId = Ttk_StateTableLookup(elementData->info->statemap, state); + + /* + * Correct the members of b if needed + */ + switch (nbTabsStickBit) { + default: + case TTK_STICK_S: + break; + case TTK_STICK_N: + b.y -= isSelected ? 0 : 1; b.height -= isSelected ? 1 : 0; + break; + case TTK_STICK_E: + b.width -= isSelected ? 1 : 0; + break; + case TTK_STICK_W: + b.x -= isSelected ? 3 : 4; b.width += isSelected ? 1 : 2; + 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); + + if (nbTabsStickBit == TTK_STICK_S) { + if (state & TTK_STATE_USER1) { + partId = TABP_TABITEMLEFTEDGE; + } + + /* + * Draw the border and fill into rc + */ + elementData->procs->DrawThemeBackground( + elementData->hTheme, elementData->hDC, partId, stateId, &rc, NULL); + } else { + /* + * Draw the fill but no border into rc + */ + RECT rc2 = rc; + --rc2.top; --rc2.left; ++rc2.bottom; ++rc2.right; + elementData->procs->DrawThemeBackground( + elementData->hTheme, elementData->hDC, partId, stateId, &rc2, &rc); + } + + /* + * 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; + } + FreeElementData(elementData); } @@ -746,7 +845,7 @@ static const Ttk_ElementSpec TabElementSpec = TK_STYLE_VERSION_2, sizeof(NullElement), TtkNullElementOptions, - GenericElementSize, + TabElementSize, TabElementDraw }; |