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