Tk Source Code

Check-in [5f774964]
Login
EuroTcl/OpenACS 11 - 12 JULY 2024, VIENNA

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Fix [527cb3cd5d]: Documentation of ttk states. user1/user2 are no longer misused for other (internal) purposes
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk | main
Files: files | file ages | folders
SHA3-256: 5f774964d2f357a0e9e4e6871a94a8e10097cb746126b7f64589006a7baf91bb
User & Date: jan.nijtmans 2024-05-20 17:16:58
Context
2024-05-20
17:51
merge release check-in: bff5b110 user: dgp tags: trunk, main
17:16
Fix [527cb3cd5d]: Documentation of ttk states. user1/user2 are no longer misused for other (internal) purposes check-in: 5f774964 user: jan.nijtmans tags: trunk, main
17:13
Fix [527cb3cd5d]: Documentation of ttk states. user1/user2 are no longer misused for other (internal) purposes check-in: 602822d2 user: jan.nijtmans tags: core-8-branch
2024-05-18
20:51
Merge-mark check-in: e9f6fed6 user: jan.nijtmans tags: trunk, main
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to generic/ttk/ttkClamTheme.c.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/*
 * Copyright © 2004 Joe English
 *
 * "clam" theme; inspired by the XFCE family of Gnome themes.
 */

#include "tkInt.h"
#include "ttkTheme.h"

/*
 * Under windows, the Tk-provided XDrawLine and XDrawArc have an
 * off-by-one error in the end point. This is especially apparent with this
 * theme. Defining this macro as true handles this case.
 */
#if defined(_WIN32) && !defined(WIN32_XDRAWLINE_HACK)







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/*
 * Copyright © 2004 Joe English
 *
 * "clam" theme; inspired by the XFCE family of Gnome themes.
 */

#include "tkInt.h"
#include "ttkThemeInt.h"

/*
 * Under windows, the Tk-provided XDrawLine and XDrawArc have an
 * off-by-one error in the end point. This is especially apparent with this
 * theme. Defining this macro as true handles this case.
 */
#if defined(_WIN32) && !defined(WIN32_XDRAWLINE_HACK)
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
    if (state & TTK_STATE_SELECTED) {
	delta = borderWidth;
    }

    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+delta,
		borderWidth, TK_RELIEF_FLAT);








|







1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
    if (state & TTK_STATE_SELECTED) {
	delta = borderWidth;
    }

    switch (nbTabsStickBit) {
	default:
	case TTK_STICK_S:
	    if (state & TTK_STATE_LAST) {		/* rightmost tab */
		--b.width;
	    }

	    Tk_Fill3DRectangle(tkwin, d, border,
		b.x+2, b.y+2, b.width-1, b.height-2+delta,
		borderWidth, TK_RELIEF_FLAT);

1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064

	    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);








|







1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064

	    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_LAST) {		/* 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);

1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086

	    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);








|







1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086

	    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_LAST) {		/* 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);

1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108

	    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);








|







1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108

	    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_LAST) {		/* 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);

Changes to generic/ttk/ttkDefaultTheme.c.

1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
    SliderElementDraw
};

/*------------------------------------------------------------------------
 * +++ Tree indicator element.
 */

#define TTK_STATE_OPEN TTK_STATE_USER1		/* XREF: treeview.c */
#define TTK_STATE_LEAF TTK_STATE_USER2

typedef struct {
    Tcl_Obj *colorObj;
    Tcl_Obj *marginObj;
    Tcl_Obj *sizeObj;
} TreeitemIndicator;

static const Ttk_ElementOptionSpec TreeitemIndicatorOptions[] = {







<
<
<







1204
1205
1206
1207
1208
1209
1210



1211
1212
1213
1214
1215
1216
1217
    SliderElementDraw
};

/*------------------------------------------------------------------------
 * +++ Tree indicator element.
 */




typedef struct {
    Tcl_Obj *colorObj;
    Tcl_Obj *marginObj;
    Tcl_Obj *sizeObj;
} TreeitemIndicator;

static const Ttk_ElementOptionSpec TreeitemIndicatorOptions[] = {

Changes to generic/ttk/ttkNotebook.c.

313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
    }
    for (i = 0; i < Ttk_NumberContent(nb->notebook.mgr); ++i) {
	Tab *tab = (Tab *)Ttk_ContentData(nb->notebook.mgr, i);
	if (tab->state == TAB_STATE_HIDDEN) {
	    continue;
	}
	if (index == i) {
	    state |= TTK_STATE_USER1;
	}
	break;
    }
    for (i = Ttk_NumberContent(nb->notebook.mgr) - 1; i >= 0; --i) {
	Tab *tab = (Tab *)Ttk_ContentData(nb->notebook.mgr, i);
	if (tab->state == TAB_STATE_HIDDEN) {
	    continue;
	}
	if (index == i) {
	    state |= TTK_STATE_USER2;
	}
	break;
    }
    if (itab->state == TAB_STATE_DISABLED) {
	state |= TTK_STATE_DISABLED;
    }








|









|







313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
    }
    for (i = 0; i < Ttk_NumberContent(nb->notebook.mgr); ++i) {
	Tab *tab = (Tab *)Ttk_ContentData(nb->notebook.mgr, i);
	if (tab->state == TAB_STATE_HIDDEN) {
	    continue;
	}
	if (index == i) {
	    state |= TTK_STATE_FIRST;
	}
	break;
    }
    for (i = Ttk_NumberContent(nb->notebook.mgr) - 1; i >= 0; --i) {
	Tab *tab = (Tab *)Ttk_ContentData(nb->notebook.mgr, i);
	if (tab->state == TAB_STATE_HIDDEN) {
	    continue;
	}
	if (index == i) {
	    state |= TTK_STATE_LAST;
	}
	break;
    }
    if (itab->state == TAB_STATE_DISABLED) {
	state |= TTK_STATE_DISABLED;
    }

Changes to generic/ttk/ttkState.c.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16



17


18
19
20
21
22
23
24

25
26

27
28
29
30
31
32
33

34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57

58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
/*
 * Tk widget state utilities.
 *
 * Copyright © 2003 Joe English.  Freely redistributable.
 *
 */

#include "tkInt.h"
#include "ttkTheme.h"

/*
 * Table of state names.  Must be kept in sync with TTK_STATE_*
 * #defines in ttkTheme.h.
 */
static const char *const stateNames[] =
{



    "active",		/* Mouse cursor is over widget or element */


    "disabled",		/* Widget is disabled */
    "focus",		/* Widget has keyboard focus */
    "pressed",		/* Pressed or "armed" */
    "selected",		/* "on", "true", "current", etc. */
    "background",	/* Top-level window lost focus (Mac,Win "inactive") */
    "alternate",	/* Widget-specific alternate display style */
    "invalid",		/* Bad value */

    "readonly",		/* Editing/modification disabled */
    "hover",		/* Mouse cursor is over widget */

    "user6",		/* User-definable state */
    "user5",		/* User-definable state */
    "user4",		/* User-definable state */
    "user3",		/* User-definable state */
    "user2",		/* User-definable state */
    "user1",		/* User-definable state */
    NULL

};

/*------------------------------------------------------------------------
 * +++ StateSpec object type:
 *
 * The string representation consists of a list of state names,
 * each optionally prefixed by an exclamation point (!).
 *
 * The internal representation uses the upper half of the longValue
 * to store the on bits and the lower half to store the off bits.
 * If we ever get more than 16 states, this will need to be reconsidered...
 */

static int  StateSpecSetFromAny(Tcl_Interp *interp, Tcl_Obj *obj);
/* static void StateSpecFreeIntRep(Tcl_Obj *); */
#define StateSpecFreeIntRep 0		/* not needed */
static void StateSpecDupIntRep(Tcl_Obj *, Tcl_Obj *);
static void StateSpecUpdateString(Tcl_Obj *);

static const
TkObjType StateSpecObjType =
{
    {"StateSpec",
    StateSpecFreeIntRep,

    StateSpecDupIntRep,
    StateSpecUpdateString,
    StateSpecSetFromAny,
    TCL_OBJTYPE_V0},
    0
};

static void StateSpecDupIntRep(Tcl_Obj *srcPtr, Tcl_Obj *copyPtr)
{
    copyPtr->internalRep.longValue = srcPtr->internalRep.longValue;
    copyPtr->typePtr = &StateSpecObjType.objType;
}

static int StateSpecSetFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr)
{
    int status;
    Tcl_Size i, objc;











|
<

|
<
>
>
>
|
>
>
|
|
|
<
<
<
|
>
|
<
>
|
|
|
|
|
|
<
>








|

|



<
<







<
>









|







1
2
3
4
5
6
7
8
9
10
11
12

13
14

15
16
17
18
19
20
21
22
23



24
25
26

27
28
29
30
31
32
33

34
35
36
37
38
39
40
41
42
43
44
45
46
47
48


49
50
51
52
53
54
55

56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
/*
 * Tk widget state utilities.
 *
 * Copyright © 2003 Joe English.  Freely redistributable.
 *
 */

#include "tkInt.h"
#include "ttkTheme.h"

/*
 * Table of state names.

 */
static const struct {

    char name[12];
    int value;
} stateNames[] = {
    {"active", TTK_STATE_ACTIVE},		/* Mouse cursor is over widget or element */
    {"alternate", TTK_STATE_ALTERNATE},	/* Widget-specific alternate display style */
    {"background", TTK_STATE_BACKGROUND},	/* Top-level window lost focus (Mac,Win "inactive") */
    {"disabled", TTK_STATE_DISABLED},		/* Widget is disabled */
    {"focus", TTK_STATE_FOCUS},		/* Widget has keyboard focus */
    {"hover", TTK_STATE_HOVER},		/* Mouse cursor is over widget */



    {"invalid", TTK_STATE_INVALID},		/* Bad value */
    {"pressed", TTK_STATE_PRESSED},		/* Pressed or "armed" */
    {"readonly", TTK_STATE_READONLY},		/* Editing/modification disabled */

    {"selected", TTK_STATE_SELECTED},		/* "on", "true", "current", etc. */
    {"user1", TTK_STATE_USER1},		/* User-definable state */
    {"user2", TTK_STATE_USER2},		/* User-definable state */
    {"user3", TTK_STATE_USER3},		/* User-definable state */
    {"user4", TTK_STATE_USER4},		/* User-definable state */
    {"user5", TTK_STATE_USER5},		/* User-definable state */
    {"user6", TTK_STATE_USER6},		/* User-definable state */

    {"", 0}
};

/*------------------------------------------------------------------------
 * +++ StateSpec object type:
 *
 * The string representation consists of a list of state names,
 * each optionally prefixed by an exclamation point (!).
 *
 * The internal representation uses the upper half of the wideValue
 * to store the on bits and the lower half to store the off bits.
 * If we ever get more than 32 states, this will need to be reconsidered...
 */

static int  StateSpecSetFromAny(Tcl_Interp *interp, Tcl_Obj *obj);


static void StateSpecDupIntRep(Tcl_Obj *, Tcl_Obj *);
static void StateSpecUpdateString(Tcl_Obj *);

static const
TkObjType StateSpecObjType =
{
    {"StateSpec",

    0,
    StateSpecDupIntRep,
    StateSpecUpdateString,
    StateSpecSetFromAny,
    TCL_OBJTYPE_V0},
    0
};

static void StateSpecDupIntRep(Tcl_Obj *srcPtr, Tcl_Obj *copyPtr)
{
    copyPtr->internalRep.wideValue = srcPtr->internalRep.wideValue;
    copyPtr->typePtr = &StateSpecObjType.objType;
}

static int StateSpecSetFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr)
{
    int status;
    Tcl_Size i, objc;
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140

141
142
143
144
145
146
147
148
	if (*stateName == '!') {
	    ++stateName;
	    on = 0;
	} else {
	    on = 1;
	}

	for (j = 0; stateNames[j] != 0; ++j) {
	    if (strcmp(stateName, stateNames[j]) == 0)
		break;
	}

    	if (stateNames[j] == 0) {
	    if (interp) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"Invalid state name %s", stateName));
		Tcl_SetErrorCode(interp, "TTK", "VALUE", "STATE", NULL);
	    }
	    return TCL_ERROR;
	}

	if (on) {
	    onbits |= (1<<j);
	} else {
	    offbits |= (1<<j);
	}
    }

    /* Invalidate old intrep:
     */
    if (objPtr->typePtr && objPtr->typePtr->freeIntRepProc) {
	objPtr->typePtr->freeIntRepProc(objPtr);
    }

    objPtr->typePtr = &StateSpecObjType.objType;
    objPtr->internalRep.longValue = (onbits << 16) | offbits;

    return TCL_OK;
}

static void StateSpecUpdateString(Tcl_Obj *objPtr)
{
    unsigned int onbits = (objPtr->internalRep.longValue & 0xFFFF0000) >> 16;
    unsigned int offbits = objPtr->internalRep.longValue & 0x0000FFFF;
    unsigned int mask = onbits | offbits;
    Tcl_DString result;
    int i;
    int len;

    Tcl_DStringInit(&result);

    for (i=0; stateNames[i] != NULL; ++i) {
	if (mask & (1<<i)) {
	    if (offbits & (1<<i))
		Tcl_DStringAppend(&result, "!", 1);

	    Tcl_DStringAppend(&result, stateNames[i], TCL_INDEX_NONE);
	    Tcl_DStringAppend(&result, " ", 1);
	}
    }

    len = Tcl_DStringLength(&result);
    if (len) {
	/* 'len' includes extra trailing ' ' */







|
|



|









|

|










|






|
|







|
|
|

>
|







85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
	if (*stateName == '!') {
	    ++stateName;
	    on = 0;
	} else {
	    on = 1;
	}

	for (j = 0; stateNames[j].value; ++j) {
	    if (strcmp(stateName, stateNames[j].name) == 0)
		break;
	}

    	if (stateNames[j].value == 0) {
	    if (interp) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"Invalid state name %s", stateName));
		Tcl_SetErrorCode(interp, "TTK", "VALUE", "STATE", NULL);
	    }
	    return TCL_ERROR;
	}

	if (on) {
	    onbits |= stateNames[j].value;
	} else {
	    offbits |= stateNames[j].value;
	}
    }

    /* Invalidate old intrep:
     */
    if (objPtr->typePtr && objPtr->typePtr->freeIntRepProc) {
	objPtr->typePtr->freeIntRepProc(objPtr);
    }

    objPtr->typePtr = &StateSpecObjType.objType;
    objPtr->internalRep.wideValue = ((Tcl_WideInt)onbits << 32) | offbits;

    return TCL_OK;
}

static void StateSpecUpdateString(Tcl_Obj *objPtr)
{
    unsigned int onbits = objPtr->internalRep.wideValue >> 32;
    unsigned int offbits = objPtr->internalRep.wideValue & 0xFFFFFFFFLL;
    unsigned int mask = onbits | offbits;
    Tcl_DString result;
    int i;
    int len;

    Tcl_DStringInit(&result);

    for (i=0; stateNames[i].value; ++i) {
	if (mask & stateNames[i].value) {
	    if (offbits & stateNames[i].value) {
		Tcl_DStringAppend(&result, "!", 1);
	    }
	    Tcl_DStringAppend(&result, stateNames[i].name, TCL_INDEX_NONE);
	    Tcl_DStringAppend(&result, " ", 1);
	}
    }

    len = Tcl_DStringLength(&result);
    if (len) {
	/* 'len' includes extra trailing ' ' */
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193

Tcl_Obj *Ttk_NewStateSpecObj(unsigned int onbits, unsigned int offbits)
{
    Tcl_Obj *objPtr = Tcl_NewObj();

    Tcl_InvalidateStringRep(objPtr);
    objPtr->typePtr = &StateSpecObjType.objType;
    objPtr->internalRep.longValue = (onbits << 16) | offbits;

    return objPtr;
}

int Ttk_GetStateSpecFromObj(
    Tcl_Interp *interp,
    Tcl_Obj *objPtr,
    Ttk_StateSpec *spec)
{
    if (objPtr->typePtr != &StateSpecObjType.objType) {
	int status = StateSpecSetFromAny(interp, objPtr);
	if (status != TCL_OK)
	    return status;
    }

    spec->onbits = (objPtr->internalRep.longValue & 0xFFFF0000) >> 16;
    spec->offbits = objPtr->internalRep.longValue & 0x0000FFFF;
    return TCL_OK;
}


/*
 * Tk_StateMapLookup --
 *







|















|
|







162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193

Tcl_Obj *Ttk_NewStateSpecObj(unsigned int onbits, unsigned int offbits)
{
    Tcl_Obj *objPtr = Tcl_NewObj();

    Tcl_InvalidateStringRep(objPtr);
    objPtr->typePtr = &StateSpecObjType.objType;
    objPtr->internalRep.wideValue = ((Tcl_WideInt)onbits << 32) | offbits;

    return objPtr;
}

int Ttk_GetStateSpecFromObj(
    Tcl_Interp *interp,
    Tcl_Obj *objPtr,
    Ttk_StateSpec *spec)
{
    if (objPtr->typePtr != &StateSpecObjType.objType) {
	int status = StateSpecSetFromAny(interp, objPtr);
	if (status != TCL_OK)
	    return status;
    }

    spec->onbits = objPtr->internalRep.wideValue >> 32;
    spec->offbits = objPtr->internalRep.wideValue & 0xFFFFFFFFLL;
    return TCL_OK;
}


/*
 * Tk_StateMapLookup --
 *

Changes to generic/ttk/ttkThemeInt.h.

1
2
3
4
5
6
7
8
9
10









11
12
13
14
15
16
17
/*
 * Theme engine: private definitions.
 *
 * Copyright © 2004 Joe English.  Freely redistributable.
 */

#ifndef _TTKTHEMEINT
#define _TTKTHEMEINT

#include "ttkTheme.h"










typedef struct Ttk_TemplateNode_ Ttk_TemplateNode, *Ttk_LayoutTemplate;

MODULE_SCOPE Ttk_ElementClass *Ttk_GetElement(Ttk_Theme, const char *name);
MODULE_SCOPE const char *Ttk_ElementClassName(Ttk_ElementClass *);

MODULE_SCOPE void Ttk_ElementSize(










>
>
>
>
>
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/*
 * Theme engine: private definitions.
 *
 * Copyright © 2004 Joe English.  Freely redistributable.
 */

#ifndef _TTKTHEMEINT
#define _TTKTHEMEINT

#include "ttkTheme.h"

/*------------------------------------------------------------------------
 * +++ Widget states (internal).
 */

#define TTK_STATE_OPEN		(1<<16)
#define TTK_STATE_LEAF		(1<<17)
#define TTK_STATE_FIRST		(1<<18)
#define TTK_STATE_LAST		(1<<19)

typedef struct Ttk_TemplateNode_ Ttk_TemplateNode, *Ttk_LayoutTemplate;

MODULE_SCOPE Ttk_ElementClass *Ttk_GetElement(Ttk_Theme, const char *name);
MODULE_SCOPE const char *Ttk_ElementClassName(Ttk_ElementClass *);

MODULE_SCOPE void Ttk_ElementSize(

Changes to generic/ttk/ttkTreeview.c.

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#define DEF_COLWIDTH		"200"
#define DEF_MINWIDTH		"20"

static const Tk_Anchor DEFAULT_IMAGEANCHOR = TK_ANCHOR_W;
static const int DEFAULT_INDENT 	= 20;
static const int HALO   		= 4;	/* heading separator */

#define TTK_STATE_OPEN TTK_STATE_USER1
#define TTK_STATE_LEAF TTK_STATE_USER2

#define STATE_CHANGED	 	(0x100)	/* item state option changed */

#define MAX(a,b) (((a) > (b)) ? (a) : (b))

/*------------------------------------------------------------------------
 * +++ Tree items.
 *







<
<
<







19
20
21
22
23
24
25



26
27
28
29
30
31
32
#define DEF_COLWIDTH		"200"
#define DEF_MINWIDTH		"20"

static const Tk_Anchor DEFAULT_IMAGEANCHOR = TK_ANCHOR_W;
static const int DEFAULT_INDENT 	= 20;
static const int HALO   		= 4;	/* heading separator */




#define STATE_CHANGED	 	(0x100)	/* item state option changed */

#define MAX(a,b) (((a) > (b)) ? (a) : (b))

/*------------------------------------------------------------------------
 * +++ Tree items.
 *

Changes to macosx/ttkMacOSXTheme.c.

26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
 *      "prelight", or "hot-tracked".  Aqua doesn't use this kind of feedback.
 *
 *      The QuickDraw/Carbon coordinate system is relative to the top-level
 *      window, not to the Tk_Window.  BoxToRect() accounts for this.
 */

#include "tkMacOSXPrivate.h"
#include "ttk/ttkTheme.h"
#include "ttkMacOSXTheme.h"
#include "tkColor.h"
#include <math.h>

MODULE_SCOPE NSColor *controlAccentColor(void) {
    static int accentPixel = -1;
    if (accentPixel == -1) {







|







26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
 *      "prelight", or "hot-tracked".  Aqua doesn't use this kind of feedback.
 *
 *      The QuickDraw/Carbon coordinate system is relative to the top-level
 *      window, not to the Tk_Window.  BoxToRect() accounts for this.
 */

#include "tkMacOSXPrivate.h"
#include "ttk/ttkThemeInt.h"
#include "ttkMacOSXTheme.h"
#include "tkColor.h"
#include <math.h>

MODULE_SCOPE NSColor *controlAccentColor(void) {
    static int accentPixel = -1;
    if (accentPixel == -1) {
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
     * Extend the bounds to one or both sides so the rounded part will be
     * clipped off if the right of the left tab, the left of the right tab,
     * and both sides of the middle tabs.
     */

    CGContextClipToRect(context, bounds);
    if (OSVersion < 110000 || !(state & TTK_STATE_SELECTED)) {
	if (!(state & TTK_STATE_FIRST_TAB)) {
	    bounds.origin.x -= 10;
	    bounds.size.width += 10;
	}
	if (!(state & TTK_STATE_LAST_TAB)) {
	    bounds.size.width += 10;
	}
    }
    /*
     * Fill the tab face with the appropriate color or gradient.  Use a solid
     * color if the tab is not selected, otherwise use the accent color with
     * highlights
     */

    if (!(state & TTK_STATE_SELECTED)) {
	DrawGrayButton(context, bounds, &tabDesign, state, tkwin);

        /*
         * Draw a separator line on the left side of the tab if it
         * not first.
         */

	if (!(state & TTK_STATE_FIRST_TAB)) {
	    CGContextSaveGState(context);
	    strokeColor = CGColorFromGray(darkTabSeparator);
	    CGContextSetStrokeColorWithColor(context, strokeColor);
	    CGContextBeginPath(context);
	    CGContextMoveToPoint(context, originalBounds.origin.x,
		originalBounds.origin.y + 1);
	    CGContextAddLineToPoint(context, originalBounds.origin.x,
		originalBounds.origin.y + originalBounds.size.height - 1);
	    CGContextStrokePath(context);
	    CGContextRestoreGState(context);
	}
    } else {

	/*
	 * This is the selected tab; paint it with the current accent color.
	 * If it is first, cover up the separator line drawn by the second one.
	 * (The selected tab is always drawn last.)
	 */

	if ((state & TTK_STATE_FIRST_TAB) && !(state & TTK_STATE_LAST_TAB)) {
	    bounds.size.width += 1;
	}
	if (!(state & TTK_STATE_BACKGROUND)) {
	    DrawAccentedButton(context, bounds, &tabDesign, 0, 0);
	} else {
	    DrawGrayButton(context, bounds, &tabDesign, state, tkwin);
	}







|



|

















|



















|







1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
     * Extend the bounds to one or both sides so the rounded part will be
     * clipped off if the right of the left tab, the left of the right tab,
     * and both sides of the middle tabs.
     */

    CGContextClipToRect(context, bounds);
    if (OSVersion < 110000 || !(state & TTK_STATE_SELECTED)) {
	if (!(state & TTK_STATE_FIRST)) {
	    bounds.origin.x -= 10;
	    bounds.size.width += 10;
	}
	if (!(state & TTK_STATE_LAST)) {
	    bounds.size.width += 10;
	}
    }
    /*
     * Fill the tab face with the appropriate color or gradient.  Use a solid
     * color if the tab is not selected, otherwise use the accent color with
     * highlights
     */

    if (!(state & TTK_STATE_SELECTED)) {
	DrawGrayButton(context, bounds, &tabDesign, state, tkwin);

        /*
         * Draw a separator line on the left side of the tab if it
         * not first.
         */

	if (!(state & TTK_STATE_FIRST)) {
	    CGContextSaveGState(context);
	    strokeColor = CGColorFromGray(darkTabSeparator);
	    CGContextSetStrokeColorWithColor(context, strokeColor);
	    CGContextBeginPath(context);
	    CGContextMoveToPoint(context, originalBounds.origin.x,
		originalBounds.origin.y + 1);
	    CGContextAddLineToPoint(context, originalBounds.origin.x,
		originalBounds.origin.y + originalBounds.size.height - 1);
	    CGContextStrokePath(context);
	    CGContextRestoreGState(context);
	}
    } else {

	/*
	 * This is the selected tab; paint it with the current accent color.
	 * If it is first, cover up the separator line drawn by the second one.
	 * (The selected tab is always drawn last.)
	 */

	if ((state & TTK_STATE_FIRST) && !(state & TTK_STATE_LAST)) {
	    bounds.size.width += 1;
	}
	if (!(state & TTK_STATE_BACKGROUND)) {
	    DrawAccentedButton(context, bounds, &tabDesign, 0, 0);
	} else {
	    DrawGrayButton(context, bounds, &tabDesign, state, tkwin);
	}
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
	CGRect clipRect = bounds;
	/*
	 * Draw a segment of a Group Box as a background for non-selected tabs.
	 * Clip the Group Box so that the segments fit together to form a long
	 * rounded rectangle behind the entire tab bar.
	 */

	if (!(state & TTK_STATE_FIRST_TAB)) {
	    clipRect.origin.x -= 5;
	    bounds.origin.x -= 5;
	    bounds.size.width += 5;
	}
	if (!(state & TTK_STATE_LAST_TAB)) {
	    clipRect.size.width += 5;
	    bounds.size.width += 5;
	}
	CGContextSaveGState(context);
	CGContextClipToRect(context, clipRect);
	DrawGroupBox(bounds, context, tkwin, 3, NO);
	CGContextRestoreGState(context);







|




|







1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
	CGRect clipRect = bounds;
	/*
	 * Draw a segment of a Group Box as a background for non-selected tabs.
	 * Clip the Group Box so that the segments fit together to form a long
	 * rounded rectangle behind the entire tab bar.
	 */

	if (!(state & TTK_STATE_FIRST)) {
	    clipRect.origin.x -= 5;
	    bounds.origin.x -= 5;
	    bounds.size.width += 5;
	}
	if (!(state & TTK_STATE_LAST)) {
	    clipRect.size.width += 5;
	    bounds.size.width += 5;
	}
	CGContextSaveGState(context);
	CGContextClipToRect(context, clipRect);
	DrawGroupBox(bounds, context, tkwin, 3, NO);
	CGContextRestoreGState(context);
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
    {kThemeTabFrontUnavailable, TTK_STATE_DISABLED | TTK_STATE_SELECTED, 0},
    {kThemeTabNonFrontUnavailable, TTK_STATE_DISABLED, 0},
    {kThemeTabFront, TTK_STATE_SELECTED, 0},
    {kThemeTabNonFrontPressed, TTK_STATE_PRESSED, 0},
    {kThemeTabNonFront, 0, 0}
};
static const Ttk_StateTable TabAdornmentTable[] = {
    {kHIThemeTabAdornmentNone, TTK_STATE_FIRST_TAB | TTK_STATE_LAST_TAB, 0},
    {kHIThemeTabAdornmentTrailingSeparator, TTK_STATE_FIRST_TAB, 0},
    {kHIThemeTabAdornmentNone, TTK_STATE_LAST_TAB, 0},
    {kHIThemeTabAdornmentTrailingSeparator, 0, 0},
};
static const Ttk_StateTable TabPositionTable[] = {
    {kHIThemeTabPositionOnly, TTK_STATE_FIRST_TAB | TTK_STATE_LAST_TAB, 0},
    {kHIThemeTabPositionFirst, TTK_STATE_FIRST_TAB, 0},
    {kHIThemeTabPositionLast, TTK_STATE_LAST_TAB, 0},
    {kHIThemeTabPositionMiddle, 0, 0},
};

/*
 * Apple XHIG Tab View Specifications:
 *
 * Control sizes: Tab views are available in regular, small, and mini sizes.







|
|
|



|
|
|







1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
    {kThemeTabFrontUnavailable, TTK_STATE_DISABLED | TTK_STATE_SELECTED, 0},
    {kThemeTabNonFrontUnavailable, TTK_STATE_DISABLED, 0},
    {kThemeTabFront, TTK_STATE_SELECTED, 0},
    {kThemeTabNonFrontPressed, TTK_STATE_PRESSED, 0},
    {kThemeTabNonFront, 0, 0}
};
static const Ttk_StateTable TabAdornmentTable[] = {
    {kHIThemeTabAdornmentNone, TTK_STATE_FIRST | TTK_STATE_LAST, 0},
    {kHIThemeTabAdornmentTrailingSeparator, TTK_STATE_FIRST, 0},
    {kHIThemeTabAdornmentNone, TTK_STATE_LAST, 0},
    {kHIThemeTabAdornmentTrailingSeparator, 0, 0},
};
static const Ttk_StateTable TabPositionTable[] = {
    {kHIThemeTabPositionOnly, TTK_STATE_FIRST | TTK_STATE_LAST, 0},
    {kHIThemeTabPositionFirst, TTK_STATE_FIRST, 0},
    {kHIThemeTabPositionLast, TTK_STATE_LAST, 0},
    {kHIThemeTabPositionMiddle, 0, 0},
};

/*
 * Apple XHIG Tab View Specifications:
 *
 * Control sizes: Tab views are available in regular, small, and mini sizes.
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
    TreeHeaderElementDraw
};

/*----------------------------------------------------------------------
 * +++ Disclosure triangles --
 */

#define TTK_TREEVIEW_STATE_OPEN         TTK_STATE_USER1
#define TTK_TREEVIEW_STATE_LEAF         TTK_STATE_USER2
static const Ttk_StateTable DisclosureValueTable[] = {
    {kThemeDisclosureDown, TTK_TREEVIEW_STATE_OPEN, 0},
    {kThemeDisclosureRight, 0, 0},
};
static void DisclosureElementSize(
    TCL_UNUSED(void *),    /* clientData */
    TCL_UNUSED(void *),    /* elementRecord */
    TCL_UNUSED(Tk_Window), /* tkwin */
    int *minWidth,







<
<

|







3317
3318
3319
3320
3321
3322
3323


3324
3325
3326
3327
3328
3329
3330
3331
3332
    TreeHeaderElementDraw
};

/*----------------------------------------------------------------------
 * +++ Disclosure triangles --
 */



static const Ttk_StateTable DisclosureValueTable[] = {
    {kThemeDisclosureDown, TTK_STATE_OPEN, 0},
    {kThemeDisclosureRight, 0, 0},
};
static void DisclosureElementSize(
    TCL_UNUSED(void *),    /* clientData */
    TCL_UNUSED(void *),    /* elementRecord */
    TCL_UNUSED(Tk_Window), /* tkwin */
    int *minWidth,
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
    TCL_UNUSED(void *),    /* clientData */
    TCL_UNUSED(void *),    /* elementRecord */
    Tk_Window tkwin,
    Drawable d,
    Ttk_Box b,
    Ttk_State state)
{
    if (!(state & TTK_TREEVIEW_STATE_LEAF)) {
	int triangleState = TkMacOSXInDarkMode(tkwin) ?
	    kThemeStateInactive : kThemeStateActive;
	CGRect bounds = BoxToRect(d, b);
	const HIThemeButtonDrawInfo info = {
	    .version = 0,
	    .state = triangleState,
	    .kind = kThemeDisclosureTriangle,
	    .value = Ttk_StateTableLookup(DisclosureValueTable, state),
	    .adornment = kThemeAdornmentDrawIndicatorOnly,
	};

	BEGIN_DRAWING(d)
	if ([NSApp macOSVersion] >= 110000) {
	    CGFloat rgba[4];
	    NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace];
	    NSColor *stroke = [[NSColor textColor]
		colorUsingColorSpace: deviceRGB];
	    [stroke getComponents: rgba];
	    if (state & TTK_TREEVIEW_STATE_OPEN) {
		DrawOpenDisclosure(dc.context, bounds, 2, 8, rgba);
	    } else {
		DrawClosedDisclosure(dc.context, bounds, 2, 12, rgba);
	    }
	} else {
	    ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation,
	    NULL);







|


















|







3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
    TCL_UNUSED(void *),    /* clientData */
    TCL_UNUSED(void *),    /* elementRecord */
    Tk_Window tkwin,
    Drawable d,
    Ttk_Box b,
    Ttk_State state)
{
    if (!(state & TTK_STATE_LEAF)) {
	int triangleState = TkMacOSXInDarkMode(tkwin) ?
	    kThemeStateInactive : kThemeStateActive;
	CGRect bounds = BoxToRect(d, b);
	const HIThemeButtonDrawInfo info = {
	    .version = 0,
	    .state = triangleState,
	    .kind = kThemeDisclosureTriangle,
	    .value = Ttk_StateTableLookup(DisclosureValueTable, state),
	    .adornment = kThemeAdornmentDrawIndicatorOnly,
	};

	BEGIN_DRAWING(d)
	if ([NSApp macOSVersion] >= 110000) {
	    CGFloat rgba[4];
	    NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace];
	    NSColor *stroke = [[NSColor textColor]
		colorUsingColorSpace: deviceRGB];
	    [stroke getComponents: rgba];
	    if (state & TTK_STATE_OPEN) {
		DrawOpenDisclosure(dc.context, bounds, 2, 8, rgba);
	    } else {
		DrawClosedDisclosure(dc.context, bounds, 2, 12, rgba);
	    }
	} else {
	    ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation,
	    NULL);

Changes to macosx/ttkMacOSXTheme.h.

34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49

#define RangeToFactor(max) ((double) (1073741824.0) / (max < 1.0 ? 1.0 : max))

/*
 * Meanings of Ttk states represented by User1 and User2.
 */

#define TTK_STATE_FIRST_TAB     TTK_STATE_USER1
#define TTK_STATE_LAST_TAB      TTK_STATE_USER2
#define TTK_STATE_IS_ACCENTED   TTK_STATE_USER2
#define TTK_TREEVIEW_STATE_SORTARROW    TTK_STATE_USER1

/*
 * Colors and gradients used when drawing buttons.
 */








<
<







34
35
36
37
38
39
40


41
42
43
44
45
46
47

#define RangeToFactor(max) ((double) (1073741824.0) / (max < 1.0 ? 1.0 : max))

/*
 * Meanings of Ttk states represented by User1 and User2.
 */



#define TTK_STATE_IS_ACCENTED   TTK_STATE_USER2
#define TTK_TREEVIEW_STATE_SORTARROW    TTK_STATE_USER1

/*
 * Colors and gradients used when drawing buttons.
 */

Changes to win/ttkWinXPTheme.c.

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
 *  	shellcc/platform/commctls/userex/refentry.asp >
 */

#include "tkWinInt.h"
#include <windows.h>
#include <uxtheme.h>
#include <vssym32.h>
#include "ttk/ttkTheme.h"

typedef HTHEME  (STDAPICALLTYPE OpenThemeDataProc)(HWND hwnd,
		 LPCWSTR pszClassList);
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);







|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
 *  	shellcc/platform/commctls/userex/refentry.asp >
 */

#include "tkWinInt.h"
#include <windows.h>
#include <uxtheme.h>
#include <vssym32.h>
#include "ttk/ttkThemeInt.h"

typedef HTHEME  (STDAPICALLTYPE OpenThemeDataProc)(HWND hwnd,
		 LPCWSTR pszClassList);
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);
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878

/*----------------------------------------------------------------------
 * +++  Tree indicator element.
 *
 *	Generic element, but don't display at all if TTK_STATE_LEAF (=USER2) set
 */

#define TTK_STATE_OPEN TTK_STATE_USER1
#define TTK_STATE_LEAF TTK_STATE_USER2

static const Ttk_StateTable header_statemap[] =
{
    { HIS_PRESSED, 	TTK_STATE_PRESSED, 0 },
    { HIS_HOT,  	TTK_STATE_ACTIVE, 0 },
    { HIS_NORMAL, 	0,0 },
};








<
<
<







862
863
864
865
866
867
868



869
870
871
872
873
874
875

/*----------------------------------------------------------------------
 * +++  Tree indicator element.
 *
 *	Generic element, but don't display at all if TTK_STATE_LEAF (=USER2) set
 */




static const Ttk_StateTable header_statemap[] =
{
    { HIS_PRESSED, 	TTK_STATE_PRESSED, 0 },
    { HIS_HOT,  	TTK_STATE_ACTIVE, 0 },
    { HIS_NORMAL, 	0,0 },
};