summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/ttk_notebook.n41
-rw-r--r--generic/ttk/ttkClamTheme.c125
-rw-r--r--generic/ttk/ttkElements.c148
-rw-r--r--generic/ttk/ttkNotebook.c9
-rw-r--r--win/ttkWinTheme.c159
-rw-r--r--win/ttkWinXPTheme.c111
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
};