1 /*
2 * Copyright (c) 2003, Joe English
3 *
4 * Default implementation for themed elements.
5 *
6 */
7
8 #include "tkInt.h"
9 #include "ttkTheme.h"
10 #include "ttkWidget.h"
11
12 #define DEFAULT_BORDERWIDTH "2"
13 #define DEFAULT_ARROW_SIZE "15"
14 #define MIN_THUMB_SIZE 10
15
16 /*----------------------------------------------------------------------
17 * +++ Null element. Does nothing; used as a stub.
18 * Null element methods, option table and element spec are public,
19 * and may be used in other engines.
20 */
21
22 /* public */ Ttk_ElementOptionSpec TtkNullElementOptions[] = { { NULL, 0, 0, NULL } };
23
24 /* public */ void
TtkNullElementSize(void * clientData,void * elementRecord,Tk_Window tkwin,int * widthPtr,int * heightPtr,Ttk_Padding * paddingPtr)25 TtkNullElementSize(
26 void *clientData, void *elementRecord, Tk_Window tkwin,
27 int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
28 {
29 }
30
31 /* public */ void
TtkNullElementDraw(void * clientData,void * elementRecord,Tk_Window tkwin,Drawable d,Ttk_Box b,unsigned int state)32 TtkNullElementDraw(
33 void *clientData, void *elementRecord, Tk_Window tkwin,
34 Drawable d, Ttk_Box b, unsigned int state)
35 {
36 }
37
38 /* public */ Ttk_ElementSpec ttkNullElementSpec = {
39 TK_STYLE_VERSION_2,
40 sizeof(NullElement),
41 TtkNullElementOptions,
42 TtkNullElementSize,
43 TtkNullElementDraw
44 };
45
46 /*----------------------------------------------------------------------
47 * +++ Background and fill elements.
48 *
49 * The fill element fills its parcel with the background color.
50 * The background element ignores the parcel, and fills the entire window.
51 *
52 * Ttk_GetLayout() automatically includes a background element.
53 */
54
55 typedef struct {
56 Tcl_Obj *backgroundObj;
57 } BackgroundElement;
58
59 static Ttk_ElementOptionSpec BackgroundElementOptions[] = {
60 { "-background", TK_OPTION_BORDER,
61 Tk_Offset(BackgroundElement,backgroundObj), DEFAULT_BACKGROUND },
62 { NULL, 0, 0, NULL }
63 };
64
FillElementDraw(void * clientData,void * elementRecord,Tk_Window tkwin,Drawable d,Ttk_Box b,unsigned int state)65 static void FillElementDraw(
66 void *clientData, void *elementRecord, Tk_Window tkwin,
67 Drawable d, Ttk_Box b, unsigned int state)
68 {
69 BackgroundElement *bg = elementRecord;
70 Tk_3DBorder backgroundPtr = Tk_Get3DBorderFromObj(tkwin,bg->backgroundObj);
71
72 XFillRectangle(Tk_Display(tkwin), d,
73 Tk_3DBorderGC(tkwin, backgroundPtr, TK_3D_FLAT_GC),
74 b.x, b.y, b.width, b.height);
75 }
76
BackgroundElementDraw(void * clientData,void * elementRecord,Tk_Window tkwin,Drawable d,Ttk_Box b,unsigned int state)77 static void BackgroundElementDraw(
78 void *clientData, void *elementRecord, Tk_Window tkwin,
79 Drawable d, Ttk_Box b, unsigned int state)
80 {
81 FillElementDraw(
82 clientData, elementRecord, tkwin,
83 d, Ttk_WinBox(tkwin), state);
84 }
85
86 static Ttk_ElementSpec FillElementSpec = {
87 TK_STYLE_VERSION_2,
88 sizeof(BackgroundElement),
89 BackgroundElementOptions,
90 TtkNullElementSize,
91 FillElementDraw
92 };
93
94 static Ttk_ElementSpec BackgroundElementSpec = {
95 TK_STYLE_VERSION_2,
96 sizeof(BackgroundElement),
97 BackgroundElementOptions,
98 TtkNullElementSize,
99 BackgroundElementDraw
100 };
101
102 /*----------------------------------------------------------------------
103 * +++ Border element.
104 */
105
106 typedef struct {
107 Tcl_Obj *borderObj;
108 Tcl_Obj *borderWidthObj;
109 Tcl_Obj *reliefObj;
110 } BorderElement;
111
112 static Ttk_ElementOptionSpec BorderElementOptions[] = {
113 { "-background", TK_OPTION_BORDER,
114 Tk_Offset(BorderElement,borderObj), DEFAULT_BACKGROUND },
115 { "-borderwidth", TK_OPTION_PIXELS,
116 Tk_Offset(BorderElement,borderWidthObj), DEFAULT_BORDERWIDTH },
117 { "-relief", TK_OPTION_RELIEF,
118 Tk_Offset(BorderElement,reliefObj), "flat" },
119 { NULL, 0, 0, NULL }
120 };
121
BorderElementSize(void * clientData,void * elementRecord,Tk_Window tkwin,int * widthPtr,int * heightPtr,Ttk_Padding * paddingPtr)122 static void BorderElementSize(
123 void *clientData, void *elementRecord, Tk_Window tkwin,
124 int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
125 {
126 BorderElement *bd = elementRecord;
127 int borderWidth = 0;
128 Tcl_GetIntFromObj(NULL, bd->borderWidthObj, &borderWidth);
129 *paddingPtr = Ttk_UniformPadding((short)borderWidth);
130 }
131
BorderElementDraw(void * clientData,void * elementRecord,Tk_Window tkwin,Drawable d,Ttk_Box b,unsigned int state)132 static void BorderElementDraw(
133 void *clientData, void *elementRecord, Tk_Window tkwin,
134 Drawable d, Ttk_Box b, unsigned int state)
135 {
136 BorderElement *bd = elementRecord;
137 Tk_3DBorder border = NULL;
138 int borderWidth = 1, relief = TK_RELIEF_FLAT;
139
140 border = Tk_Get3DBorderFromObj(tkwin, bd->borderObj);
141 Tcl_GetIntFromObj(NULL, bd->borderWidthObj, &borderWidth);
142 Tk_GetReliefFromObj(NULL, bd->reliefObj, &relief);
143
144 if (border && borderWidth > 0 && relief != TK_RELIEF_FLAT) {
145 Tk_Draw3DRectangle(tkwin, d, border,
146 b.x, b.y, b.width, b.height, borderWidth,relief);
147 }
148 }
149
150 static Ttk_ElementSpec BorderElementSpec = {
151 TK_STYLE_VERSION_2,
152 sizeof(BorderElement),
153 BorderElementOptions,
154 BorderElementSize,
155 BorderElementDraw
156 };
157
158 /*----------------------------------------------------------------------
159 * +++ Field element.
160 * Used for editable fields.
161 */
162 typedef struct {
163 Tcl_Obj *borderObj;
164 Tcl_Obj *borderWidthObj;
165 } FieldElement;
166
167 static Ttk_ElementOptionSpec FieldElementOptions[] = {
168 { "-fieldbackground", TK_OPTION_BORDER,
169 Tk_Offset(FieldElement,borderObj), "white" },
170 { "-borderwidth", TK_OPTION_PIXELS,
171 Tk_Offset(FieldElement,borderWidthObj), "2" },
172 { NULL, 0, 0, NULL }
173 };
174
FieldElementSize(void * clientData,void * elementRecord,Tk_Window tkwin,int * widthPtr,int * heightPtr,Ttk_Padding * paddingPtr)175 static void FieldElementSize(
176 void *clientData, void *elementRecord, Tk_Window tkwin,
177 int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
178 {
179 FieldElement *field = elementRecord;
180 int borderWidth = 2;
181 Tk_GetPixelsFromObj(NULL, tkwin, field->borderWidthObj, &borderWidth);
182 *paddingPtr = Ttk_UniformPadding((short)borderWidth);
183 }
184
FieldElementDraw(void * clientData,void * elementRecord,Tk_Window tkwin,Drawable d,Ttk_Box b,unsigned int state)185 static void FieldElementDraw(
186 void *clientData, void *elementRecord, Tk_Window tkwin,
187 Drawable d, Ttk_Box b, unsigned int state)
188 {
189 FieldElement *field = elementRecord;
190 Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, field->borderObj);
191 int borderWidth = 2;
192
193 Tk_GetPixelsFromObj(NULL, tkwin, field->borderWidthObj, &borderWidth);
194 Tk_Fill3DRectangle(tkwin, d, border,
195 b.x, b.y, b.width, b.height, borderWidth, TK_RELIEF_SUNKEN);
196 }
197
198 static Ttk_ElementSpec FieldElementSpec = {
199 TK_STYLE_VERSION_2,
200 sizeof(FieldElement),
201 FieldElementOptions,
202 FieldElementSize,
203 FieldElementDraw
204 };
205
206 /*
207 *----------------------------------------------------------------------
208 * +++ Padding element.
209 *
210 * This element has no visual representation, only geometry.
211 * It adds a (possibly non-uniform) internal border.
212 * In addition, if "-shiftrelief" is specified,
213 * adds additional pixels to shift child elements "in" or "out"
214 * depending on the -relief.
215 */
216
217 typedef struct {
218 Tcl_Obj *paddingObj;
219 Tcl_Obj *reliefObj;
220 Tcl_Obj *shiftreliefObj;
221 } PaddingElement;
222
223 static Ttk_ElementOptionSpec PaddingElementOptions[] = {
224 { "-padding", TK_OPTION_STRING,
225 Tk_Offset(PaddingElement,paddingObj), "0" },
226 { "-relief", TK_OPTION_RELIEF,
227 Tk_Offset(PaddingElement,reliefObj), "flat" },
228 { "-shiftrelief", TK_OPTION_INT,
229 Tk_Offset(PaddingElement,shiftreliefObj), "0" },
230 { NULL, 0, 0, NULL }
231 };
232
PaddingElementSize(void * clientData,void * elementRecord,Tk_Window tkwin,int * widthPtr,int * heightPtr,Ttk_Padding * paddingPtr)233 static void PaddingElementSize(
234 void *clientData, void *elementRecord, Tk_Window tkwin,
235 int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
236 {
237 PaddingElement *padding = elementRecord;
238 int shiftRelief = 0;
239 int relief = TK_RELIEF_FLAT;
240 Ttk_Padding pad;
241
242 Tk_GetReliefFromObj(NULL, padding->reliefObj, &relief);
243 Tcl_GetIntFromObj(NULL, padding->shiftreliefObj, &shiftRelief);
244 Ttk_GetPaddingFromObj(NULL,tkwin,padding->paddingObj,&pad);
245 *paddingPtr = Ttk_RelievePadding(pad, relief, shiftRelief);
246 }
247
248 static Ttk_ElementSpec PaddingElementSpec = {
249 TK_STYLE_VERSION_2,
250 sizeof(PaddingElement),
251 PaddingElementOptions,
252 PaddingElementSize,
253 TtkNullElementDraw
254 };
255
256 /*----------------------------------------------------------------------
257 * +++ Focus ring element.
258 * Draws a dashed focus ring, if the widget has keyboard focus.
259 */
260 typedef struct {
261 Tcl_Obj *focusColorObj;
262 Tcl_Obj *focusThicknessObj;
263 } FocusElement;
264
265 /*
266 * DrawFocusRing --
267 * Draw a dotted rectangle to indicate focus.
268 */
DrawFocusRing(Tk_Window tkwin,Drawable d,Tcl_Obj * colorObj,Ttk_Box b)269 static void DrawFocusRing(
270 Tk_Window tkwin, Drawable d, Tcl_Obj *colorObj, Ttk_Box b)
271 {
272 XColor *color = Tk_GetColorFromObj(tkwin, colorObj);
273 unsigned long mask = 0UL;
274 XGCValues gcvalues;
275 GC gc;
276
277 gcvalues.foreground = color->pixel;
278 gcvalues.line_style = LineOnOffDash;
279 gcvalues.line_width = 1;
280 gcvalues.dashes = 1;
281 gcvalues.dash_offset = 1;
282 mask = GCForeground | GCLineStyle | GCDashList | GCDashOffset | GCLineWidth;
283
284 gc = Tk_GetGC(tkwin, mask, &gcvalues);
285 XDrawRectangle(Tk_Display(tkwin), d, gc, b.x, b.y, b.width-1, b.height-1);
286 Tk_FreeGC(Tk_Display(tkwin), gc);
287 }
288
289 static Ttk_ElementOptionSpec FocusElementOptions[] = {
290 { "-focuscolor",TK_OPTION_COLOR,
291 Tk_Offset(FocusElement,focusColorObj), "black" },
292 { "-focusthickness",TK_OPTION_PIXELS,
293 Tk_Offset(FocusElement,focusThicknessObj), "1" },
294 { NULL, 0, 0, NULL }
295 };
296
FocusElementSize(void * clientData,void * elementRecord,Tk_Window tkwin,int * widthPtr,int * heightPtr,Ttk_Padding * paddingPtr)297 static void FocusElementSize(
298 void *clientData, void *elementRecord, Tk_Window tkwin,
299 int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
300 {
301 FocusElement *focus = elementRecord;
302 int focusThickness = 0;
303
304 Tcl_GetIntFromObj(NULL, focus->focusThicknessObj, &focusThickness);
305 *paddingPtr = Ttk_UniformPadding((short)focusThickness);
306 }
307
FocusElementDraw(void * clientData,void * elementRecord,Tk_Window tkwin,Drawable d,Ttk_Box b,unsigned int state)308 static void FocusElementDraw(
309 void *clientData, void *elementRecord, Tk_Window tkwin,
310 Drawable d, Ttk_Box b, unsigned int state)
311 {
312 FocusElement *focus = elementRecord;
313 int focusThickness = 0;
314
315 if (state & TTK_STATE_FOCUS) {
316 Tcl_GetIntFromObj(NULL,focus->focusThicknessObj,&focusThickness);
317 DrawFocusRing(tkwin, d, focus->focusColorObj, b);
318 }
319 }
320
321 static Ttk_ElementSpec FocusElementSpec = {
322 TK_STYLE_VERSION_2,
323 sizeof(FocusElement),
324 FocusElementOptions,
325 FocusElementSize,
326 FocusElementDraw
327 };
328
329 /*----------------------------------------------------------------------
330 * +++ Separator element.
331 * Just draws a horizontal or vertical bar.
332 * Three elements are defined: horizontal, vertical, and general;
333 * the general separator checks the "-orient" option.
334 */
335
336 typedef struct {
337 Tcl_Obj *orientObj;
338 Tcl_Obj *borderObj;
339 } SeparatorElement;
340
341 static Ttk_ElementOptionSpec SeparatorElementOptions[] = {
342 { "-orient", TK_OPTION_ANY,
343 Tk_Offset(SeparatorElement, orientObj), "horizontal" },
344 { "-background", TK_OPTION_BORDER,
345 Tk_Offset(SeparatorElement,borderObj), DEFAULT_BACKGROUND },
346 { NULL, 0, 0, NULL }
347 };
348
SeparatorElementSize(void * clientData,void * elementRecord,Tk_Window tkwin,int * widthPtr,int * heightPtr,Ttk_Padding * paddingPtr)349 static void SeparatorElementSize(
350 void *clientData, void *elementRecord, Tk_Window tkwin,
351 int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
352 {
353 *widthPtr = *heightPtr = 2;
354 }
355
HorizontalSeparatorElementDraw(void * clientData,void * elementRecord,Tk_Window tkwin,Drawable d,Ttk_Box b,unsigned int state)356 static void HorizontalSeparatorElementDraw(
357 void *clientData, void *elementRecord, Tk_Window tkwin,
358 Drawable d, Ttk_Box b, unsigned int state)
359 {
360 SeparatorElement *separator = elementRecord;
361 Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, separator->borderObj);
362 GC lightGC = Tk_3DBorderGC(tkwin, border, TK_3D_LIGHT_GC);
363 GC darkGC = Tk_3DBorderGC(tkwin, border, TK_3D_DARK_GC);
364
365 XDrawLine(Tk_Display(tkwin), d, darkGC, b.x, b.y, b.x + b.width, b.y);
366 XDrawLine(Tk_Display(tkwin), d, lightGC, b.x, b.y+1, b.x + b.width, b.y+1);
367 }
368
VerticalSeparatorElementDraw(void * clientData,void * elementRecord,Tk_Window tkwin,Drawable d,Ttk_Box b,unsigned int state)369 static void VerticalSeparatorElementDraw(
370 void *clientData, void *elementRecord, Tk_Window tkwin,
371 Drawable d, Ttk_Box b, unsigned int state)
372 {
373 SeparatorElement *separator = elementRecord;
374 Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, separator->borderObj);
375 GC lightGC = Tk_3DBorderGC(tkwin, border, TK_3D_LIGHT_GC);
376 GC darkGC = Tk_3DBorderGC(tkwin, border, TK_3D_DARK_GC);
377
378 XDrawLine(Tk_Display(tkwin), d, darkGC, b.x, b.y, b.x, b.y + b.height);
379 XDrawLine(Tk_Display(tkwin), d, lightGC, b.x+1, b.y, b.x+1, b.y+b.height);
380 }
381
GeneralSeparatorElementDraw(void * clientData,void * elementRecord,Tk_Window tkwin,Drawable d,Ttk_Box b,unsigned int state)382 static void GeneralSeparatorElementDraw(
383 void *clientData, void *elementRecord, Tk_Window tkwin,
384 Drawable d, Ttk_Box b, unsigned int state)
385 {
386 SeparatorElement *separator = elementRecord;
387 int orient;
388 Ttk_GetOrientFromObj(NULL, separator->orientObj, &orient);
389 switch (orient) {
390 case TTK_ORIENT_HORIZONTAL:
391 HorizontalSeparatorElementDraw(
392 clientData, elementRecord, tkwin, d, b, state);
393 break;
394 case TTK_ORIENT_VERTICAL:
395 VerticalSeparatorElementDraw(
396 clientData, elementRecord, tkwin, d, b, state);
397 break;
398 }
399 }
400
401 static Ttk_ElementSpec HorizontalSeparatorElementSpec = {
402 TK_STYLE_VERSION_2,
403 sizeof(SeparatorElement),
404 SeparatorElementOptions,
405 SeparatorElementSize,
406 HorizontalSeparatorElementDraw
407 };
408
409 static Ttk_ElementSpec VerticalSeparatorElementSpec = {
410 TK_STYLE_VERSION_2,
411 sizeof(SeparatorElement),
412 SeparatorElementOptions,
413 SeparatorElementSize,
414 HorizontalSeparatorElementDraw
415 };
416
417 static Ttk_ElementSpec SeparatorElementSpec = {
418 TK_STYLE_VERSION_2,
419 sizeof(SeparatorElement),
420 SeparatorElementOptions,
421 SeparatorElementSize,
422 GeneralSeparatorElementDraw
423 };
424
425 /*----------------------------------------------------------------------
426 * +++ Sizegrip: lower-right corner grip handle for resizing window.
427 */
428
429 typedef struct {
430 Tcl_Obj *backgroundObj;
431 } SizegripElement;
432
433 static Ttk_ElementOptionSpec SizegripOptions[] = {
434 { "-background", TK_OPTION_BORDER,
435 Tk_Offset(SizegripElement,backgroundObj), DEFAULT_BACKGROUND },
436 {0,0,0,0}
437 };
438
SizegripSize(void * clientData,void * elementRecord,Tk_Window tkwin,int * widthPtr,int * heightPtr,Ttk_Padding * paddingPtr)439 static void SizegripSize(
440 void *clientData, void *elementRecord, Tk_Window tkwin,
441 int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
442 {
443 int gripCount = 3, gripSpace = 2, gripThickness = 3;
444 *widthPtr = *heightPtr = gripCount * (gripSpace + gripThickness);
445 }
446
SizegripDraw(void * clientData,void * elementRecord,Tk_Window tkwin,Drawable d,Ttk_Box b,Ttk_State state)447 static void SizegripDraw(
448 void *clientData, void *elementRecord, Tk_Window tkwin,
449 Drawable d, Ttk_Box b, Ttk_State state)
450 {
451 SizegripElement *grip = elementRecord;
452 int gripCount = 3, gripSpace = 2;
453 Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, grip->backgroundObj);
454 GC lightGC = Tk_3DBorderGC(tkwin, border, TK_3D_LIGHT_GC);
455 GC darkGC = Tk_3DBorderGC(tkwin, border, TK_3D_DARK_GC);
456 int x1 = b.x + b.width-1, y1 = b.y + b.height-1, x2 = x1, y2 = y1;
457
458 while (gripCount--) {
459 x1 -= gripSpace; y2 -= gripSpace;
460 XDrawLine(Tk_Display(tkwin), d, darkGC, x1,y1, x2,y2); --x1; --y2;
461 XDrawLine(Tk_Display(tkwin), d, darkGC, x1,y1, x2,y2); --x1; --y2;
462 XDrawLine(Tk_Display(tkwin), d, lightGC, x1,y1, x2,y2); --x1; --y2;
463 }
464 }
465
466 static Ttk_ElementSpec SizegripElementSpec = {
467 TK_STYLE_VERSION_2,
468 sizeof(SizegripElement),
469 SizegripOptions,
470 SizegripSize,
471 SizegripDraw
472 };
473
474 /*----------------------------------------------------------------------
475 * +++ Indicator element.
476 *
477 * Draws the on/off indicator for checkbuttons and radiobuttons.
478 *
479 * Draws a 3-D square (or diamond), raised if off, sunken if on.
480 *
481 * This is actually a regression from Tk 8.5 back to the ugly old Motif
482 * style; use "altTheme" for the newer, nicer version.
483 */
484
485 typedef struct {
486 Tcl_Obj *backgroundObj;
487 Tcl_Obj *reliefObj;
488 Tcl_Obj *colorObj;
489 Tcl_Obj *diameterObj;
490 Tcl_Obj *marginObj;
491 Tcl_Obj *borderWidthObj;
492 } IndicatorElement;
493
494 static Ttk_ElementOptionSpec IndicatorElementOptions[] = {
495 { "-background", TK_OPTION_BORDER,
496 Tk_Offset(IndicatorElement,backgroundObj), DEFAULT_BACKGROUND },
497 { "-indicatorcolor", TK_OPTION_BORDER,
498 Tk_Offset(IndicatorElement,colorObj), DEFAULT_BACKGROUND },
499 { "-indicatorrelief", TK_OPTION_RELIEF,
500 Tk_Offset(IndicatorElement,reliefObj), "raised" },
501 { "-indicatordiameter", TK_OPTION_PIXELS,
502 Tk_Offset(IndicatorElement,diameterObj), "12" },
503 { "-indicatormargin", TK_OPTION_STRING,
504 Tk_Offset(IndicatorElement,marginObj), "0 2 4 2" },
505 { "-borderwidth", TK_OPTION_PIXELS,
506 Tk_Offset(IndicatorElement,borderWidthObj), DEFAULT_BORDERWIDTH },
507 { NULL, 0, 0, NULL }
508 };
509
510 /*
511 * Checkbutton indicators (default): 3-D square.
512 */
SquareIndicatorElementSize(void * clientData,void * elementRecord,Tk_Window tkwin,int * widthPtr,int * heightPtr,Ttk_Padding * paddingPtr)513 static void SquareIndicatorElementSize(
514 void *clientData, void *elementRecord, Tk_Window tkwin,
515 int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
516 {
517 IndicatorElement *indicator = elementRecord;
518 Ttk_Padding margins;
519 int diameter = 0;
520 Ttk_GetPaddingFromObj(NULL, tkwin, indicator->marginObj, &margins);
521 Tk_GetPixelsFromObj(NULL, tkwin, indicator->diameterObj, &diameter);
522 *widthPtr = diameter + Ttk_PaddingWidth(margins);
523 *heightPtr = diameter + Ttk_PaddingHeight(margins);
524 }
525
SquareIndicatorElementDraw(void * clientData,void * elementRecord,Tk_Window tkwin,Drawable d,Ttk_Box b,unsigned int state)526 static void SquareIndicatorElementDraw(
527 void *clientData, void *elementRecord, Tk_Window tkwin,
528 Drawable d, Ttk_Box b, unsigned int state)
529 {
530 IndicatorElement *indicator = elementRecord;
531 Tk_3DBorder border = 0, interior = 0;
532 int relief = TK_RELIEF_RAISED;
533 Ttk_Padding padding;
534 int borderWidth = 2;
535 int diameter;
536
537 interior = Tk_Get3DBorderFromObj(tkwin, indicator->colorObj);
538 border = Tk_Get3DBorderFromObj(tkwin, indicator->backgroundObj);
539 Tcl_GetIntFromObj(NULL,indicator->borderWidthObj,&borderWidth);
540 Tk_GetReliefFromObj(NULL,indicator->reliefObj,&relief);
541 Ttk_GetPaddingFromObj(NULL,tkwin,indicator->marginObj,&padding);
542
543 b = Ttk_PadBox(b, padding);
544
545 diameter = b.width < b.height ? b.width : b.height;
546 Tk_Fill3DRectangle(tkwin, d, interior, b.x, b.y,
547 diameter, diameter,borderWidth, TK_RELIEF_FLAT);
548 Tk_Draw3DRectangle(tkwin, d, border, b.x, b.y,
549 diameter, diameter, borderWidth, relief);
550 }
551
552 /*
553 * Radiobutton indicators: 3-D diamond.
554 */
DiamondIndicatorElementSize(void * clientData,void * elementRecord,Tk_Window tkwin,int * widthPtr,int * heightPtr,Ttk_Padding * paddingPtr)555 static void DiamondIndicatorElementSize(
556 void *clientData, void *elementRecord, Tk_Window tkwin,
557 int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
558 {
559 IndicatorElement *indicator = elementRecord;
560 Ttk_Padding margins;
561 int diameter = 0;
562 Ttk_GetPaddingFromObj(NULL, tkwin, indicator->marginObj, &margins);
563 Tk_GetPixelsFromObj(NULL, tkwin, indicator->diameterObj, &diameter);
564 *widthPtr = diameter + 3 + Ttk_PaddingWidth(margins);
565 *heightPtr = diameter + 3 + Ttk_PaddingHeight(margins);
566 }
567
DiamondIndicatorElementDraw(void * clientData,void * elementRecord,Tk_Window tkwin,Drawable d,Ttk_Box b,unsigned int state)568 static void DiamondIndicatorElementDraw(
569 void *clientData, void *elementRecord, Tk_Window tkwin,
570 Drawable d, Ttk_Box b, unsigned int state)
571 {
572 IndicatorElement *indicator = elementRecord;
573 Tk_3DBorder border = 0, interior = 0;
574 int borderWidth = 2;
575 int relief = TK_RELIEF_RAISED;
576 int diameter, radius;
577 XPoint points[4];
578 Ttk_Padding padding;
579
580 interior = Tk_Get3DBorderFromObj(tkwin, indicator->colorObj);
581 border = Tk_Get3DBorderFromObj(tkwin, indicator->backgroundObj);
582 Tcl_GetIntFromObj(NULL,indicator->borderWidthObj,&borderWidth);
583 Tk_GetReliefFromObj(NULL,indicator->reliefObj,&relief);
584 Ttk_GetPaddingFromObj(NULL,tkwin,indicator->marginObj,&padding);
585
586 b = Ttk_PadBox(b, padding);
587
588 diameter = b.width < b.height ? b.width : b.height;
589 radius = diameter / 2;
590
591 points[0].x = b.x;
592 points[0].y = b.y + radius;
593 points[1].x = b.x + radius;
594 points[1].y = b.y + 2*radius;
595 points[2].x = b.x + 2*radius;
596 points[2].y = b.y + radius;
597 points[3].x = b.x + radius;
598 points[3].y = b.y;
599
600 Tk_Fill3DPolygon(tkwin,d,interior,points,4,borderWidth,TK_RELIEF_FLAT);
601 Tk_Draw3DPolygon(tkwin,d,border,points,4,borderWidth,relief);
602 }
603
604 static Ttk_ElementSpec CheckbuttonIndicatorElementSpec = {
605 TK_STYLE_VERSION_2,
606 sizeof(IndicatorElement),
607 IndicatorElementOptions,
608 SquareIndicatorElementSize,
609 SquareIndicatorElementDraw
610 };
611
612 static Ttk_ElementSpec RadiobuttonIndicatorElementSpec = {
613 TK_STYLE_VERSION_2,
614 sizeof(IndicatorElement),
615 IndicatorElementOptions,
616 DiamondIndicatorElementSize,
617 DiamondIndicatorElementDraw
618 };
619
620 /*
621 *----------------------------------------------------------------------
622 * +++ Menubutton indicators.
623 *
624 * These aren't functional like radio/check indicators,
625 * they're just affordability indicators.
626 *
627 * Standard Tk sets the indicator size to 4.0 mm by 1.7 mm.
628 * I have no idea where these numbers came from.
629 */
630
631 typedef struct {
632 Tcl_Obj *backgroundObj;
633 Tcl_Obj *widthObj;
634 Tcl_Obj *heightObj;
635 Tcl_Obj *borderWidthObj;
636 Tcl_Obj *reliefObj;
637 Tcl_Obj *marginObj;
638 } MenuIndicatorElement;
639
640 static Ttk_ElementOptionSpec MenuIndicatorElementOptions[] = {
641 { "-background", TK_OPTION_BORDER,
642 Tk_Offset(MenuIndicatorElement,backgroundObj), DEFAULT_BACKGROUND },
643 { "-indicatorwidth", TK_OPTION_PIXELS,
644 Tk_Offset(MenuIndicatorElement,widthObj), "4.0m" },
645 { "-indicatorheight", TK_OPTION_PIXELS,
646 Tk_Offset(MenuIndicatorElement,heightObj), "1.7m" },
647 { "-borderwidth", TK_OPTION_PIXELS,
648 Tk_Offset(MenuIndicatorElement,borderWidthObj), DEFAULT_BORDERWIDTH },
649 { "-indicatorrelief", TK_OPTION_RELIEF,
650 Tk_Offset(MenuIndicatorElement,reliefObj),"raised" },
651 { "-indicatormargin", TK_OPTION_STRING,
652 Tk_Offset(MenuIndicatorElement,marginObj), "5 0" },
653 { NULL, 0, 0, NULL }
654 };
655
MenuIndicatorElementSize(void * clientData,void * elementRecord,Tk_Window tkwin,int * widthPtr,int * heightPtr,Ttk_Padding * paddingPtr)656 static void MenuIndicatorElementSize(
657 void *clientData, void *elementRecord, Tk_Window tkwin,
658 int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
659 {
660 MenuIndicatorElement *mi = elementRecord;
661 Ttk_Padding margins;
662 Tk_GetPixelsFromObj(NULL, tkwin, mi->widthObj, widthPtr);
663 Tk_GetPixelsFromObj(NULL, tkwin, mi->heightObj, heightPtr);
664 Ttk_GetPaddingFromObj(NULL,tkwin,mi->marginObj, &margins);
665 *widthPtr += Ttk_PaddingWidth(margins);
666 *heightPtr += Ttk_PaddingHeight(margins);
667 }
668
MenuIndicatorElementDraw(void * clientData,void * elementRecord,Tk_Window tkwin,Drawable d,Ttk_Box b,unsigned int state)669 static void MenuIndicatorElementDraw(
670 void *clientData, void *elementRecord, Tk_Window tkwin,
671 Drawable d, Ttk_Box b, unsigned int state)
672 {
673 MenuIndicatorElement *mi = elementRecord;
674 Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, mi->backgroundObj);
675 Ttk_Padding margins;
676 int borderWidth = 2;
677
678 Ttk_GetPaddingFromObj(NULL,tkwin,mi->marginObj,&margins);
679 b = Ttk_PadBox(b, margins);
680 Tk_GetPixelsFromObj(NULL, tkwin, mi->borderWidthObj, &borderWidth);
681 Tk_Fill3DRectangle(tkwin, d, border, b.x, b.y, b.width, b.height,
682 borderWidth, TK_RELIEF_RAISED);
683 }
684
685 static Ttk_ElementSpec MenuIndicatorElementSpec = {
686 TK_STYLE_VERSION_2,
687 sizeof(MenuIndicatorElement),
688 MenuIndicatorElementOptions,
689 MenuIndicatorElementSize,
690 MenuIndicatorElementDraw
691 };
692
693 /*----------------------------------------------------------------------
694 * +++ Arrow elements.
695 *
696 * Draws a solid triangle inside a box.
697 * clientData is an enum ArrowDirection pointer.
698 */
699
700 static int ArrowElements[] = { ARROW_UP, ARROW_DOWN, ARROW_LEFT, ARROW_RIGHT };
701 typedef struct {
702 Tcl_Obj *borderObj;
703 Tcl_Obj *borderWidthObj;
704 Tcl_Obj *reliefObj;
705 Tcl_Obj *sizeObj;
706 Tcl_Obj *colorObj;
707 } ArrowElement;
708
709 static Ttk_ElementOptionSpec ArrowElementOptions[] = {
710 { "-background", TK_OPTION_BORDER,
711 Tk_Offset(ArrowElement,borderObj), DEFAULT_BACKGROUND },
712 { "-relief",TK_OPTION_RELIEF,
713 Tk_Offset(ArrowElement,reliefObj),"raised"},
714 { "-borderwidth", TK_OPTION_PIXELS,
715 Tk_Offset(ArrowElement,borderWidthObj), "1" },
716 { "-arrowcolor",TK_OPTION_COLOR,
717 Tk_Offset(ArrowElement,colorObj),"black"},
718 { "-arrowsize", TK_OPTION_PIXELS,
719 Tk_Offset(ArrowElement,sizeObj), "14" },
720 { NULL, 0, 0, NULL }
721 };
722
723 static Ttk_Padding ArrowMargins = { 3,3,3,3 };
724
ArrowElementSize(void * clientData,void * elementRecord,Tk_Window tkwin,int * widthPtr,int * heightPtr,Ttk_Padding * paddingPtr)725 static void ArrowElementSize(
726 void *clientData, void *elementRecord, Tk_Window tkwin,
727 int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
728 {
729 ArrowElement *arrow = elementRecord;
730 int direction = *(int *)clientData;
731 int width = 14;
732
733 Tk_GetPixelsFromObj(NULL, tkwin, arrow->sizeObj, &width);
734 width -= Ttk_PaddingWidth(ArrowMargins);
735 TtkArrowSize(width/2, direction, widthPtr, heightPtr);
736 *widthPtr += Ttk_PaddingWidth(ArrowMargins);
737 *heightPtr += Ttk_PaddingWidth(ArrowMargins);
738 }
739
ArrowElementDraw(void * clientData,void * elementRecord,Tk_Window tkwin,Drawable d,Ttk_Box b,unsigned int state)740 static void ArrowElementDraw(
741 void *clientData, void *elementRecord, Tk_Window tkwin,
742 Drawable d, Ttk_Box b, unsigned int state)
743 {
744 int direction = *(int *)clientData;
745 ArrowElement *arrow = elementRecord;
746 Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, arrow->borderObj);
747 XColor *arrowColor = Tk_GetColorFromObj(tkwin, arrow->colorObj);
748 int relief = TK_RELIEF_RAISED;
749 int borderWidth = 1;
750
751 Tk_GetReliefFromObj(NULL, arrow->reliefObj, &relief);
752
753 Tk_Fill3DRectangle(
754 tkwin, d, border, b.x, b.y, b.width, b.height, borderWidth, relief);
755
756 TtkFillArrow(Tk_Display(tkwin), d, Tk_GCForColor(arrowColor, d),
757 Ttk_PadBox(b, ArrowMargins), direction);
758 }
759
760 static Ttk_ElementSpec ArrowElementSpec = {
761 TK_STYLE_VERSION_2,
762 sizeof(ArrowElement),
763 ArrowElementOptions,
764 ArrowElementSize,
765 ArrowElementDraw
766 };
767
768 /*----------------------------------------------------------------------
769 * +++ Trough element.
770 *
771 * Used in scrollbars and scales in place of "border".
772 */
773
774 typedef struct {
775 Tcl_Obj *colorObj;
776 Tcl_Obj *borderWidthObj;
777 Tcl_Obj *reliefObj;
778 } TroughElement;
779
780 static Ttk_ElementOptionSpec TroughElementOptions[] = {
781 { "-borderwidth", TK_OPTION_PIXELS,
782 Tk_Offset(TroughElement,borderWidthObj), DEFAULT_BORDERWIDTH },
783 { "-troughcolor", TK_OPTION_BORDER,
784 Tk_Offset(TroughElement,colorObj), DEFAULT_BACKGROUND },
785 { "-troughrelief",TK_OPTION_RELIEF,
786 Tk_Offset(TroughElement,reliefObj), "sunken" },
787 { NULL, 0, 0, NULL }
788 };
789
TroughElementSize(void * clientData,void * elementRecord,Tk_Window tkwin,int * widthPtr,int * heightPtr,Ttk_Padding * paddingPtr)790 static void TroughElementSize(
791 void *clientData, void *elementRecord, Tk_Window tkwin,
792 int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
793 {
794 TroughElement *troughPtr = elementRecord;
795 int borderWidth = 2;
796
797 Tk_GetPixelsFromObj(NULL, tkwin, troughPtr->borderWidthObj, &borderWidth);
798 *paddingPtr = Ttk_UniformPadding((short)borderWidth);
799 }
800
TroughElementDraw(void * clientData,void * elementRecord,Tk_Window tkwin,Drawable d,Ttk_Box b,unsigned int state)801 static void TroughElementDraw(
802 void *clientData, void *elementRecord, Tk_Window tkwin,
803 Drawable d, Ttk_Box b, unsigned int state)
804 {
805 TroughElement *troughPtr = elementRecord;
806 Tk_3DBorder border = NULL;
807 int borderWidth = 2, relief = TK_RELIEF_SUNKEN;
808
809 border = Tk_Get3DBorderFromObj(tkwin, troughPtr->colorObj);
810 Tk_GetReliefFromObj(NULL, troughPtr->reliefObj, &relief);
811 Tk_GetPixelsFromObj(NULL, tkwin, troughPtr->borderWidthObj, &borderWidth);
812
813 Tk_Fill3DRectangle(tkwin, d, border, b.x, b.y, b.width, b.height,
814 borderWidth, relief);
815 }
816
817 static Ttk_ElementSpec TroughElementSpec = {
818 TK_STYLE_VERSION_2,
819 sizeof(TroughElement),
820 TroughElementOptions,
821 TroughElementSize,
822 TroughElementDraw
823 };
824
825 /*
826 *----------------------------------------------------------------------
827 * +++ Thumb element.
828 *
829 * Used in scrollbars.
830 */
831
832 typedef struct {
833 Tcl_Obj *orientObj;
834 Tcl_Obj *thicknessObj;
835 Tcl_Obj *reliefObj;
836 Tcl_Obj *borderObj;
837 Tcl_Obj *borderWidthObj;
838 } ThumbElement;
839
840 static Ttk_ElementOptionSpec ThumbElementOptions[] = {
841 { "-orient", TK_OPTION_ANY,
842 Tk_Offset(ThumbElement, orientObj), "horizontal" },
843 { "-width", TK_OPTION_PIXELS,
844 Tk_Offset(ThumbElement,thicknessObj), DEFAULT_ARROW_SIZE },
845 { "-relief", TK_OPTION_RELIEF,
846 Tk_Offset(ThumbElement,reliefObj), "raised" },
847 { "-background", TK_OPTION_BORDER,
848 Tk_Offset(ThumbElement,borderObj), DEFAULT_BACKGROUND },
849 { "-borderwidth", TK_OPTION_PIXELS,
850 Tk_Offset(ThumbElement,borderWidthObj), DEFAULT_BORDERWIDTH },
851 { NULL, 0, 0, NULL }
852 };
853
ThumbElementSize(void * clientData,void * elementRecord,Tk_Window tkwin,int * widthPtr,int * heightPtr,Ttk_Padding * paddingPtr)854 static void ThumbElementSize(
855 void *clientData, void *elementRecord, Tk_Window tkwin,
856 int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
857 {
858 ThumbElement *thumb = elementRecord;
859 int orient, thickness;
860
861 Tk_GetPixelsFromObj(NULL, tkwin, thumb->thicknessObj, &thickness);
862 Ttk_GetOrientFromObj(NULL, thumb->orientObj, &orient);
863
864 if (orient == TTK_ORIENT_VERTICAL) {
865 *widthPtr = thickness;
866 *heightPtr = MIN_THUMB_SIZE;
867 } else {
868 *widthPtr = MIN_THUMB_SIZE;
869 *heightPtr = thickness;
870 }
871 }
872
ThumbElementDraw(void * clientData,void * elementRecord,Tk_Window tkwin,Drawable d,Ttk_Box b,unsigned int state)873 static void ThumbElementDraw(
874 void *clientData, void *elementRecord, Tk_Window tkwin,
875 Drawable d, Ttk_Box b, unsigned int state)
876 {
877 ThumbElement *thumb = elementRecord;
878 Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, thumb->borderObj);
879 int borderWidth = 2, relief = TK_RELIEF_RAISED;
880
881 Tk_GetPixelsFromObj(NULL, tkwin, thumb->borderWidthObj, &borderWidth);
882 Tk_GetReliefFromObj(NULL, thumb->reliefObj, &relief);
883 Tk_Fill3DRectangle(tkwin, d, border, b.x, b.y, b.width, b.height,
884 borderWidth, relief);
885 }
886
887 static Ttk_ElementSpec ThumbElementSpec = {
888 TK_STYLE_VERSION_2,
889 sizeof(ThumbElement),
890 ThumbElementOptions,
891 ThumbElementSize,
892 ThumbElementDraw
893 };
894
895 /*
896 *----------------------------------------------------------------------
897 * +++ Slider element.
898 *
899 * This is the moving part of the scale widget. Drawn as a raised box.
900 */
901
902 typedef struct {
903 Tcl_Obj *orientObj; /* orientation of overall slider */
904 Tcl_Obj *lengthObj; /* slider length */
905 Tcl_Obj *thicknessObj; /* slider thickness */
906 Tcl_Obj *reliefObj; /* the relief for this object */
907 Tcl_Obj *borderObj; /* the background color */
908 Tcl_Obj *borderWidthObj; /* the size of the border */
909 } SliderElement;
910
911 static Ttk_ElementOptionSpec SliderElementOptions[] = {
912 { "-sliderlength", TK_OPTION_PIXELS, Tk_Offset(SliderElement,lengthObj),
913 "30" },
914 { "-sliderthickness",TK_OPTION_PIXELS,Tk_Offset(SliderElement,thicknessObj),
915 "15" },
916 { "-sliderrelief", TK_OPTION_RELIEF, Tk_Offset(SliderElement,reliefObj),
917 "raised" },
918 { "-borderwidth", TK_OPTION_PIXELS, Tk_Offset(SliderElement,borderWidthObj),
919 DEFAULT_BORDERWIDTH },
920 { "-background", TK_OPTION_BORDER, Tk_Offset(SliderElement,borderObj),
921 DEFAULT_BACKGROUND },
922 { "-orient", TK_OPTION_ANY, Tk_Offset(SliderElement,orientObj),
923 "horizontal" },
924 { NULL, 0, 0, NULL }
925 };
926
SliderElementSize(void * clientData,void * elementRecord,Tk_Window tkwin,int * widthPtr,int * heightPtr,Ttk_Padding * paddingPtr)927 static void SliderElementSize(
928 void *clientData, void *elementRecord, Tk_Window tkwin,
929 int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
930 {
931 SliderElement *slider = elementRecord;
932 int orient, length, thickness;
933
934 Ttk_GetOrientFromObj(NULL, slider->orientObj, &orient);
935 Tk_GetPixelsFromObj(NULL, tkwin, slider->lengthObj, &length);
936 Tk_GetPixelsFromObj(NULL, tkwin, slider->thicknessObj, &thickness);
937
938 switch (orient) {
939 case TTK_ORIENT_VERTICAL:
940 *widthPtr = thickness;
941 *heightPtr = length;
942 break;
943
944 case TTK_ORIENT_HORIZONTAL:
945 *widthPtr = length;
946 *heightPtr = thickness;
947 break;
948 }
949 }
950
SliderElementDraw(void * clientData,void * elementRecord,Tk_Window tkwin,Drawable d,Ttk_Box b,unsigned int state)951 static void SliderElementDraw(
952 void *clientData, void *elementRecord, Tk_Window tkwin,
953 Drawable d, Ttk_Box b, unsigned int state)
954 {
955 SliderElement *slider = elementRecord;
956 Tk_3DBorder border = NULL;
957 int relief = TK_RELIEF_RAISED, borderWidth = 2, orient;
958
959 border = Tk_Get3DBorderFromObj(tkwin, slider->borderObj);
960 Ttk_GetOrientFromObj(NULL, slider->orientObj, &orient);
961 Tk_GetPixelsFromObj(NULL, tkwin, slider->borderWidthObj, &borderWidth);
962 Tk_GetReliefFromObj(NULL, slider->reliefObj, &relief);
963
964 Tk_Fill3DRectangle(tkwin, d, border,
965 b.x, b.y, b.width, b.height,
966 borderWidth, relief);
967
968 if (relief != TK_RELIEF_FLAT) {
969 if (orient == TTK_ORIENT_HORIZONTAL) {
970 if (b.width > 4) {
971 b.x += b.width/2;
972 XDrawLine(Tk_Display(tkwin), d,
973 Tk_3DBorderGC(tkwin, border, TK_3D_DARK_GC),
974 b.x-1, b.y+borderWidth, b.x-1, b.y+b.height-borderWidth);
975 XDrawLine(Tk_Display(tkwin), d,
976 Tk_3DBorderGC(tkwin, border, TK_3D_LIGHT_GC),
977 b.x, b.y+borderWidth, b.x, b.y+b.height-borderWidth);
978 }
979 } else {
980 if (b.height > 4) {
981 b.y += b.height/2;
982 XDrawLine(Tk_Display(tkwin), d,
983 Tk_3DBorderGC(tkwin, border, TK_3D_DARK_GC),
984 b.x+borderWidth, b.y-1, b.x+b.width-borderWidth, b.y-1);
985 XDrawLine(Tk_Display(tkwin), d,
986 Tk_3DBorderGC(tkwin, border, TK_3D_LIGHT_GC),
987 b.x+borderWidth, b.y, b.x+b.width-borderWidth, b.y);
988 }
989 }
990 }
991 }
992
993 static Ttk_ElementSpec SliderElementSpec = {
994 TK_STYLE_VERSION_2,
995 sizeof(SliderElement),
996 SliderElementOptions,
997 SliderElementSize,
998 SliderElementDraw
999 };
1000
1001 /*------------------------------------------------------------------------
1002 * +++ Progress bar element:
1003 * Draws the moving part of the progress bar.
1004 *
1005 * -thickness specifies the size along the short axis of the bar.
1006 * -length specifies the default size along the long axis;
1007 * the bar will be this long in indeterminate mode.
1008 */
1009
1010 #define DEFAULT_PBAR_THICKNESS "15"
1011 #define DEFAULT_PBAR_LENGTH "30"
1012
1013 typedef struct {
1014 Tcl_Obj *orientObj; /* widget orientation */
1015 Tcl_Obj *thicknessObj; /* the height/width of the bar */
1016 Tcl_Obj *lengthObj; /* default width/height of the bar */
1017 Tcl_Obj *reliefObj; /* border relief for this object */
1018 Tcl_Obj *borderObj; /* background color */
1019 Tcl_Obj *borderWidthObj; /* thickness of the border */
1020 } PbarElement;
1021
1022 static Ttk_ElementOptionSpec PbarElementOptions[] = {
1023 { "-orient", TK_OPTION_ANY, Tk_Offset(PbarElement,orientObj),
1024 "horizontal" },
1025 { "-thickness", TK_OPTION_PIXELS, Tk_Offset(PbarElement,thicknessObj),
1026 DEFAULT_PBAR_THICKNESS },
1027 { "-barsize", TK_OPTION_PIXELS, Tk_Offset(PbarElement,lengthObj),
1028 DEFAULT_PBAR_LENGTH },
1029 { "-pbarrelief", TK_OPTION_RELIEF, Tk_Offset(PbarElement,reliefObj),
1030 "raised" },
1031 { "-borderwidth", TK_OPTION_PIXELS, Tk_Offset(PbarElement,borderWidthObj),
1032 DEFAULT_BORDERWIDTH },
1033 { "-background", TK_OPTION_BORDER, Tk_Offset(PbarElement,borderObj),
1034 DEFAULT_BACKGROUND },
1035 { NULL, 0, 0, NULL }
1036 };
1037
PbarElementSize(void * clientData,void * elementRecord,Tk_Window tkwin,int * widthPtr,int * heightPtr,Ttk_Padding * paddingPtr)1038 static void PbarElementSize(
1039 void *clientData, void *elementRecord, Tk_Window tkwin,
1040 int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
1041 {
1042 PbarElement *pbar = elementRecord;
1043 int orient, thickness = 15, length = 30, borderWidth = 2;
1044
1045 Ttk_GetOrientFromObj(NULL, pbar->orientObj, &orient);
1046 Tk_GetPixelsFromObj(NULL, tkwin, pbar->thicknessObj, &thickness);
1047 Tk_GetPixelsFromObj(NULL, tkwin, pbar->lengthObj, &length);
1048 Tk_GetPixelsFromObj(NULL, tkwin, pbar->borderWidthObj, &borderWidth);
1049
1050 switch (orient) {
1051 case TTK_ORIENT_HORIZONTAL:
1052 *widthPtr = length + 2 * borderWidth;
1053 *heightPtr = thickness + 2 * borderWidth;
1054 break;
1055 case TTK_ORIENT_VERTICAL:
1056 *widthPtr = thickness + 2 * borderWidth;
1057 *heightPtr = length + 2 * borderWidth;
1058 break;
1059 }
1060 }
1061
PbarElementDraw(void * clientData,void * elementRecord,Tk_Window tkwin,Drawable d,Ttk_Box b,Ttk_State state)1062 static void PbarElementDraw(
1063 void *clientData, void *elementRecord, Tk_Window tkwin,
1064 Drawable d, Ttk_Box b, Ttk_State state)
1065 {
1066 PbarElement *pbar = elementRecord;
1067 Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, pbar->borderObj);
1068 int relief = TK_RELIEF_RAISED, borderWidth = 2;
1069
1070 Tk_GetPixelsFromObj(NULL, tkwin, pbar->borderWidthObj, &borderWidth);
1071 Tk_GetReliefFromObj(NULL, pbar->reliefObj, &relief);
1072
1073 Tk_Fill3DRectangle(tkwin, d, border,
1074 b.x, b.y, b.width, b.height,
1075 borderWidth, relief);
1076 }
1077
1078 static Ttk_ElementSpec PbarElementSpec = {
1079 TK_STYLE_VERSION_2,
1080 sizeof(PbarElement),
1081 PbarElementOptions,
1082 PbarElementSize,
1083 PbarElementDraw
1084 };
1085
1086 /*------------------------------------------------------------------------
1087 * +++ Notebook tabs and client area.
1088 */
1089
1090 typedef struct {
1091 Tcl_Obj *borderWidthObj;
1092 Tcl_Obj *backgroundObj;
1093 } TabElement;
1094
1095 static Ttk_ElementOptionSpec TabElementOptions[] = {
1096 { "-borderwidth", TK_OPTION_PIXELS,
1097 Tk_Offset(TabElement,borderWidthObj),"1" },
1098 { "-background", TK_OPTION_BORDER,
1099 Tk_Offset(TabElement,backgroundObj), DEFAULT_BACKGROUND },
1100 {0,0,0,0}
1101 };
1102
TabElementSize(void * clientData,void * elementRecord,Tk_Window tkwin,int * widthPtr,int * heightPtr,Ttk_Padding * paddingPtr)1103 static void TabElementSize(
1104 void *clientData, void *elementRecord, Tk_Window tkwin,
1105 int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
1106 {
1107 TabElement *tab = elementRecord;
1108 int borderWidth = 1;
1109 Tk_GetPixelsFromObj(0, tkwin, tab->borderWidthObj, &borderWidth);
1110 paddingPtr->top = paddingPtr->left = paddingPtr->right = borderWidth;
1111 paddingPtr->bottom = 0;
1112 }
1113
TabElementDraw(void * clientData,void * elementRecord,Tk_Window tkwin,Drawable d,Ttk_Box b,unsigned int state)1114 static void TabElementDraw(
1115 void *clientData, void *elementRecord, Tk_Window tkwin,
1116 Drawable d, Ttk_Box b, unsigned int state)
1117 {
1118 TabElement *tab = elementRecord;
1119 Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, tab->backgroundObj);
1120 int borderWidth = 1;
1121 int cut = 2;
1122 XPoint pts[6];
1123 int n = 0;
1124
1125 Tcl_GetIntFromObj(NULL, tab->borderWidthObj, &borderWidth);
1126
1127 if (state & TTK_STATE_SELECTED) {
1128 /*
1129 * Draw slightly outside of the allocated parcel,
1130 * to overwrite the client area border.
1131 */
1132 b.height += borderWidth;
1133 }
1134
1135 pts[n].x = b.x; pts[n].y = b.y + b.height - 1; ++n;
1136 pts[n].x = b.x; pts[n].y = b.y + cut; ++n;
1137 pts[n].x = b.x + cut; pts[n].y = b.y; ++n;
1138 pts[n].x = b.x + b.width-1-cut; pts[n].y = b.y; ++n;
1139 pts[n].x = b.x + b.width-1; pts[n].y = b.y + cut; ++n;
1140 pts[n].x = b.x + b.width-1; pts[n].y = b.y + b.height; ++n;
1141
1142 XFillPolygon(Tk_Display(tkwin), d,
1143 Tk_3DBorderGC(tkwin, border, TK_3D_FLAT_GC),
1144 pts, 6, Convex, CoordModeOrigin);
1145
1146 #ifndef _WIN32
1147 /*
1148 * Account for whether XDrawLines draws endpoints by platform
1149 */
1150 --pts[5].y;
1151 #endif
1152
1153 while (borderWidth--) {
1154 XDrawLines(Tk_Display(tkwin), d,
1155 Tk_3DBorderGC(tkwin, border, TK_3D_LIGHT_GC),
1156 pts, 4, CoordModeOrigin);
1157 XDrawLines(Tk_Display(tkwin), d,
1158 Tk_3DBorderGC(tkwin, border, TK_3D_DARK_GC),
1159 pts+3, 3, CoordModeOrigin);
1160 ++pts[0].x; ++pts[1].x; ++pts[2].x; --pts[4].x; --pts[5].x;
1161 ++pts[2].y; ++pts[3].y;
1162 }
1163
1164 }
1165
1166 static Ttk_ElementSpec TabElementSpec = {
1167 TK_STYLE_VERSION_2,
1168 sizeof(TabElement),
1169 TabElementOptions,
1170 TabElementSize,
1171 TabElementDraw
1172 };
1173
1174 /*
1175 * Client area element:
1176 * Uses same resources as tab element.
1177 */
1178 typedef TabElement ClientElement;
1179 #define ClientElementOptions TabElementOptions
1180
ClientElementDraw(void * clientData,void * elementRecord,Tk_Window tkwin,Drawable d,Ttk_Box b,unsigned int state)1181 static void ClientElementDraw(
1182 void *clientData, void *elementRecord, Tk_Window tkwin,
1183 Drawable d, Ttk_Box b, unsigned int state)
1184 {
1185 ClientElement *ce = elementRecord;
1186 Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, ce->backgroundObj);
1187 int borderWidth = 1;
1188
1189 Tcl_GetIntFromObj(NULL, ce->borderWidthObj, &borderWidth);
1190
1191 Tk_Fill3DRectangle(tkwin, d, border,
1192 b.x, b.y, b.width, b.height, borderWidth,TK_RELIEF_RAISED);
1193 }
1194
ClientElementSize(void * clientData,void * elementRecord,Tk_Window tkwin,int * widthPtr,int * heightPtr,Ttk_Padding * paddingPtr)1195 static void ClientElementSize(
1196 void *clientData, void *elementRecord, Tk_Window tkwin,
1197 int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
1198 {
1199 ClientElement *ce = elementRecord;
1200 int borderWidth = 1;
1201 Tk_GetPixelsFromObj(0, tkwin, ce->borderWidthObj, &borderWidth);
1202 *paddingPtr = Ttk_UniformPadding((short)borderWidth);
1203 }
1204
1205 static Ttk_ElementSpec ClientElementSpec = {
1206 TK_STYLE_VERSION_2,
1207 sizeof(ClientElement),
1208 ClientElementOptions,
1209 ClientElementSize,
1210 ClientElementDraw
1211 };
1212
1213 /*----------------------------------------------------------------------
1214 * TtkElements_Init --
1215 * Register default element implementations.
1216 */
1217
1218 MODULE_SCOPE
TtkElements_Init(Tcl_Interp * interp)1219 void TtkElements_Init(Tcl_Interp *interp)
1220 {
1221 Ttk_Theme theme = Ttk_GetDefaultTheme(interp);
1222
1223 /*
1224 * Elements:
1225 */
1226 Ttk_RegisterElement(interp, theme, "background",
1227 &BackgroundElementSpec,NULL);
1228
1229 Ttk_RegisterElement(interp, theme, "fill", &FillElementSpec, NULL);
1230 Ttk_RegisterElement(interp, theme, "border", &BorderElementSpec, NULL);
1231 Ttk_RegisterElement(interp, theme, "field", &FieldElementSpec, NULL);
1232 Ttk_RegisterElement(interp, theme, "focus", &FocusElementSpec, NULL);
1233
1234 Ttk_RegisterElement(interp, theme, "padding", &PaddingElementSpec, NULL);
1235
1236 Ttk_RegisterElement(interp, theme, "Checkbutton.indicator",
1237 &CheckbuttonIndicatorElementSpec, NULL);
1238 Ttk_RegisterElement(interp, theme, "Radiobutton.indicator",
1239 &RadiobuttonIndicatorElementSpec, NULL);
1240 Ttk_RegisterElement(interp, theme, "Menubutton.indicator",
1241 &MenuIndicatorElementSpec, NULL);
1242
1243 Ttk_RegisterElement(interp, theme, "indicator", &ttkNullElementSpec,NULL);
1244
1245 Ttk_RegisterElement(interp, theme, "uparrow",
1246 &ArrowElementSpec, &ArrowElements[0]);
1247 Ttk_RegisterElement(interp, theme, "downarrow",
1248 &ArrowElementSpec, &ArrowElements[1]);
1249 Ttk_RegisterElement(interp, theme, "leftarrow",
1250 &ArrowElementSpec, &ArrowElements[2]);
1251 Ttk_RegisterElement(interp, theme, "rightarrow",
1252 &ArrowElementSpec, &ArrowElements[3]);
1253 Ttk_RegisterElement(interp, theme, "arrow",
1254 &ArrowElementSpec, &ArrowElements[0]);
1255
1256 Ttk_RegisterElement(interp, theme, "trough", &TroughElementSpec, NULL);
1257 Ttk_RegisterElement(interp, theme, "thumb", &ThumbElementSpec, NULL);
1258 Ttk_RegisterElement(interp, theme, "slider", &SliderElementSpec, NULL);
1259 Ttk_RegisterElement(interp, theme, "pbar", &PbarElementSpec, NULL);
1260
1261 Ttk_RegisterElement(interp, theme, "separator",
1262 &SeparatorElementSpec, NULL);
1263 Ttk_RegisterElement(interp, theme, "hseparator",
1264 &HorizontalSeparatorElementSpec, NULL);
1265 Ttk_RegisterElement(interp, theme, "vseparator",
1266 &VerticalSeparatorElementSpec, NULL);
1267
1268 Ttk_RegisterElement(interp, theme, "sizegrip", &SizegripElementSpec, NULL);
1269
1270 Ttk_RegisterElement(interp, theme, "tab", &TabElementSpec, NULL);
1271 Ttk_RegisterElement(interp, theme, "client", &ClientElementSpec, NULL);
1272
1273 /*
1274 * Register "default" as a user-loadable theme (for now):
1275 */
1276 Tcl_PkgProvideEx(interp, "ttk::theme::default", TTK_VERSION, NULL);
1277 }
1278
1279 /*EOF*/
1280