1/* 2 * ttkMacOSXTheme.c -- 3 * 4 * Tk theme engine for Mac OSX, using the Appearance Manager API. 5 * 6 * Copyright (c) 2004 Joe English 7 * Copyright (c) 2005 Neil Madden 8 * Copyright (c) 2006-2009 Daniel A. Steffen <das@users.sourceforge.net> 9 * Copyright 2008-2009, Apple Inc. 10 * Copyright 2009 Kevin Walzer/WordTech Communications LLC. 11 * 12 * See the file "license.terms" for information on usage and redistribution 13 * of this file, and for a DISCLAIMER OF ALL WARRANTIES. 14 * 15 * See also: 16 * 17 * <URL: http://developer.apple.com/documentation/Carbon/Reference/ 18 * Appearance_Manager/appearance_manager/APIIndex.html > 19 * 20 * Notes: 21 * "Active" means different things in Mac and Tk terminology -- 22 * On Aqua, widgets are "Active" if they belong to the foreground window, 23 * "Inactive" if they are in a background window. 24 * Tk uses the term "active" to mean that the mouse cursor 25 * is over a widget; aka "hover", "prelight", or "hot-tracked". 26 * Aqua doesn't use this kind of feedback. 27 * 28 * The QuickDraw/Carbon coordinate system is relative to the 29 * top-level window, not to the Tk_Window. BoxToRect() 30 * accounts for this. 31 * 32 * RCS: @(#) $Id$ 33 */ 34 35#include "tkMacOSXPrivate.h" 36#include "ttk/ttkTheme.h" 37 38/* 39 * Use this version in the core: 40 */ 41#define BEGIN_DRAWING(d) { \ 42 TkMacOSXDrawingContext dc; \ 43 if (!TkMacOSXSetupDrawingContext((d), NULL, 1, &dc)) {return;} 44#define END_DRAWING \ 45 TkMacOSXRestoreDrawingContext(&dc); } 46 47#define HIOrientation kHIThemeOrientationNormal 48 49#ifdef __LP64__ 50#define RangeToFactor(maximum) (((double) (INT_MAX >> 1)) / (maximum)) 51#else 52#define RangeToFactor(maximum) (((double) (LONG_MAX >> 1)) / (maximum)) 53#endif /* __LP64__ */ 54 55/*---------------------------------------------------------------------- 56 * +++ Utilities. 57 */ 58 59/* 60 * BoxToRect -- 61 * Convert a Ttk_Box in Tk coordinates relative to the given Drawable 62 * to a native Rect relative to the containing port. 63 */ 64static inline CGRect BoxToRect(Drawable d, Ttk_Box b) 65{ 66 MacDrawable *md = (MacDrawable*)d; 67 CGRect rect; 68 69 rect.origin.y = b.y + md->yOff; 70 rect.origin.x = b.x + md->xOff; 71 rect.size.height = b.height; 72 rect.size.width = b.width; 73 74 return rect; 75} 76 77/* 78 * Table mapping Tk states to Appearance manager ThemeStates 79 */ 80 81static Ttk_StateTable ThemeStateTable[] = { 82 {kThemeStateUnavailable, TTK_STATE_DISABLED, 0}, 83 {kThemeStatePressed, TTK_STATE_PRESSED, 0}, 84 {kThemeStateInactive, TTK_STATE_BACKGROUND, 0}, 85 {kThemeStateActive, 0, 0} 86/* Others: Not sure what these are supposed to mean. 87 Up/Down have something to do with "little arrow" increment controls... 88 Dunno what a "Rollover" is. 89 NEM: Rollover is TTK_STATE_ACTIVE... but we don't handle that yet, by the 90 looks of things 91 {kThemeStateRollover, 0, 0}, 92 {kThemeStateUnavailableInactive, 0, 0} 93 {kThemeStatePressedUp, 0, 0}, 94 {kThemeStatePressedDown, 0, 0} 95*/ 96}; 97 98/*---------------------------------------------------------------------- 99 * +++ Button element: Used for elements drawn with DrawThemeButton. 100 */ 101 102/* 103 * Extra margins to account for drop shadow. 104 */ 105static Ttk_Padding ButtonMargins = {2,2,2,2}; 106 107#define NoThemeMetric 0xFFFFFFFF 108 109typedef struct { 110 ThemeButtonKind kind; 111 ThemeMetric heightMetric; 112} ThemeButtonParams; 113 114static ThemeButtonParams 115 PushButtonParams = { kThemePushButton, kThemeMetricPushButtonHeight }, 116 CheckBoxParams = { kThemeCheckBox, kThemeMetricCheckBoxHeight }, 117 RadioButtonParams = { kThemeRadioButton, kThemeMetricRadioButtonHeight }, 118 BevelButtonParams = { kThemeBevelButton, NoThemeMetric }, 119 PopupButtonParams = { kThemePopupButton, kThemeMetricPopupButtonHeight }, 120 DisclosureParams = { kThemeDisclosureButton, kThemeMetricDisclosureTriangleHeight }, 121 ListHeaderParams = { kThemeListHeaderButton, kThemeMetricListHeaderHeight }; 122 123static Ttk_StateTable ButtonValueTable[] = { 124 { kThemeButtonMixed, TTK_STATE_ALTERNATE, 0 }, 125 { kThemeButtonOn, TTK_STATE_SELECTED, 0 }, 126 { kThemeButtonOff, 0, 0 } 127/* Others: kThemeDisclosureRight, kThemeDisclosureDown, kThemeDisclosureLeft */ 128}; 129 130static Ttk_StateTable ButtonAdornmentTable[] = { 131 { kThemeAdornmentDefault| kThemeAdornmentFocus, 132 TTK_STATE_ALTERNATE| TTK_STATE_FOCUS, 0 }, 133 { kThemeAdornmentDefault, TTK_STATE_ALTERNATE, 0 }, 134 { kThemeAdornmentFocus, TTK_STATE_FOCUS, 0 }, 135 { kThemeAdornmentNone, 0, 0 } 136}; 137 138/* 139 * computeButtonDrawInfo -- 140 * Fill in an appearance manager HIThemeButtonDrawInfo record. 141 */ 142static inline HIThemeButtonDrawInfo computeButtonDrawInfo( 143 ThemeButtonParams *params, Ttk_State state) 144{ 145 const HIThemeButtonDrawInfo info = { 146 .version = 0, 147 .state = Ttk_StateTableLookup(ThemeStateTable, state), 148 .kind = params ? params->kind : 0, 149 .value = Ttk_StateTableLookup(ButtonValueTable, state), 150 .adornment = Ttk_StateTableLookup(ButtonAdornmentTable, state), 151 }; 152 return info; 153} 154 155static void ButtonElementSizeNoPadding( 156 void *clientData, void *elementRecord, Tk_Window tkwin, 157 int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) 158{ 159 ThemeButtonParams *params = clientData; 160 161 if (params->heightMetric != NoThemeMetric) { 162 SInt32 height; 163 164 ChkErr(GetThemeMetric, params->heightMetric, &height); 165 *heightPtr = height; 166 } 167} 168 169static void ButtonElementSize( 170 void *clientData, void *elementRecord, Tk_Window tkwin, 171 int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) 172{ 173 ThemeButtonParams *params = clientData; 174 const HIThemeButtonDrawInfo info = computeButtonDrawInfo(params, 0); 175 static const CGRect scratchBounds = {{0, 0}, {100, 100}}; 176 CGRect contentBounds; 177 178 ButtonElementSizeNoPadding( 179 clientData, elementRecord, tkwin, 180 widthPtr, heightPtr, paddingPtr); 181 182 /* 183 * To compute internal padding, query the appearance manager 184 * for the content bounds of a dummy rectangle, then use 185 * the difference as the padding. 186 */ 187 ChkErr(HIThemeGetButtonContentBounds, 188 &scratchBounds, &info, &contentBounds); 189 190 paddingPtr->left = CGRectGetMinX(contentBounds); 191 paddingPtr->top = CGRectGetMinY(contentBounds); 192 paddingPtr->right = CGRectGetMaxX(scratchBounds) - CGRectGetMaxX(contentBounds) + 1; 193 paddingPtr->bottom = CGRectGetMaxY(scratchBounds) - CGRectGetMaxY(contentBounds); 194 195 /* 196 * Now add a little extra padding to account for drop shadows. 197 * @@@ SHOULD: call GetThemeButtonBackgroundBounds() instead. 198 */ 199 200 *paddingPtr = Ttk_AddPadding(*paddingPtr, ButtonMargins); 201 *widthPtr += Ttk_PaddingWidth(ButtonMargins); 202 *heightPtr += Ttk_PaddingHeight(ButtonMargins); 203} 204 205static void ButtonElementDraw( 206 void *clientData, void *elementRecord, Tk_Window tkwin, 207 Drawable d, Ttk_Box b, Ttk_State state) 208{ 209 ThemeButtonParams *params = clientData; 210 CGRect bounds = BoxToRect(d, Ttk_PadBox(b, ButtonMargins)); 211 const HIThemeButtonDrawInfo info = computeButtonDrawInfo(params, state); 212 213 BEGIN_DRAWING(d) 214 ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, NULL); 215 END_DRAWING 216} 217 218static Ttk_ElementSpec ButtonElementSpec = { 219 TK_STYLE_VERSION_2, 220 sizeof(NullElement), 221 TtkNullElementOptions, 222 ButtonElementSize, 223 ButtonElementDraw 224}; 225 226/*---------------------------------------------------------------------- 227 * +++ Notebook elements. 228 */ 229 230 231/* Tab position logic, c.f. ttkNotebook.c TabState() */ 232 233#define TTK_STATE_NOTEBOOK_FIRST TTK_STATE_USER1 234#define TTK_STATE_NOTEBOOK_LAST TTK_STATE_USER2 235static Ttk_StateTable TabStyleTable[] = { 236 { kThemeTabFrontInactive, TTK_STATE_SELECTED|TTK_STATE_BACKGROUND}, 237 { kThemeTabNonFrontInactive, TTK_STATE_BACKGROUND}, 238 { kThemeTabFrontUnavailable, TTK_STATE_DISABLED|TTK_STATE_SELECTED}, 239 { kThemeTabNonFrontUnavailable, TTK_STATE_DISABLED}, 240 { kThemeTabFront, TTK_STATE_SELECTED}, 241 { kThemeTabNonFrontPressed, TTK_STATE_PRESSED}, 242 { kThemeTabNonFront, 0} 243}; 244 245static Ttk_StateTable TabAdornmentTable[] = { 246 { kHIThemeTabAdornmentNone, 247 TTK_STATE_NOTEBOOK_FIRST|TTK_STATE_NOTEBOOK_LAST}, 248 {kHIThemeTabAdornmentTrailingSeparator, TTK_STATE_NOTEBOOK_FIRST}, 249 {kHIThemeTabAdornmentNone, TTK_STATE_NOTEBOOK_LAST}, 250 {kHIThemeTabAdornmentTrailingSeparator, 0 }, 251}; 252 253static Ttk_StateTable TabPositionTable[] = { 254 { kHIThemeTabPositionOnly, 255 TTK_STATE_NOTEBOOK_FIRST|TTK_STATE_NOTEBOOK_LAST}, 256 { kHIThemeTabPositionFirst, TTK_STATE_NOTEBOOK_FIRST}, 257 { kHIThemeTabPositionLast, TTK_STATE_NOTEBOOK_LAST}, 258 { kHIThemeTabPositionMiddle, 0 }, 259}; 260 261/* 262 * Apple XHIG Tab View Specifications: 263 * 264 * Control sizes: Tab views are available in regular, small, and mini sizes. 265 * The tab height is fixed for each size, but you control the size of the pane 266 * area. The tab heights for each size are listed below: 267 * - Regular size: 20 pixels. 268 * - Small: 17 pixels. 269 * - Mini: 15 pixels. 270 * 271 * Label spacing and fonts: The tab labels should be in a font that’s 272 * proportional to the size of the tab view control. In addition, the label 273 * should be placed so that there are equal margins of space before and after 274 * it. The guidelines below provide the specifications you should use for tab 275 * labels: 276 * - Regular size: System font. Center in tab, leaving 12 pixels on each side. 277 * - Small: Small system font. Center in tab, leaving 10 pixels on each side. 278 * - Mini: Mini system font. Center in tab, leaving 8 pixels on each side. 279 * 280 * Control spacing: Whether you decide to inset a tab view in a window or 281 * extend its edges to the window sides and bottom, you should place the top 282 * edge of the tab view 12 or 14 pixels below the bottom edge of the title bar 283 * (or toolbar, if there is one). If you choose to inset a tab view in a 284 * window, you should leave a margin of 20 pixels between the sides and bottom 285 * of the tab view and the sides and bottom of the window (although 16 pixels 286 * is also an acceptable margin-width). If you need to provide controls below 287 * the tab view, leave enough space below the tab view so the controls are 20 288 * pixels above the bottom edge of the window and 12 pixels between the tab 289 * view and the controls. 290 * If you choose to extend the tab view sides and bottom so that they meet the 291 * window sides and bottom, you should leave a margin of at least 20 pixels 292 * between the content in the tab view and the tab-view edges. 293 * 294 * <URL: http://developer.apple.com/documentation/userexperience/Conceptual/ 295 * AppleHIGuidelines/XHIGControls/XHIGControls.html#//apple_ref/doc/uid/ 296 * TP30000359-TPXREF116> 297 */ 298 299static const int TAB_HEIGHT = 10; 300static const int TAB_OVERLAP = 10; 301 302static void TabElementSize( 303 void *clientData, void *elementRecord, Tk_Window tkwin, 304 int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) 305{ 306 *heightPtr = TAB_HEIGHT + TAB_OVERLAP - 1; 307} 308 309static void TabElementDraw( 310 void *clientData, void *elementRecord, Tk_Window tkwin, 311 Drawable d, Ttk_Box b, Ttk_State state) 312{ 313 CGRect bounds = BoxToRect(d, b); 314 HIThemeTabDrawInfo info = { 315 .version = 1, 316 .style = Ttk_StateTableLookup(TabStyleTable, state), 317 .direction = kThemeTabNorth, 318 .size = kHIThemeTabSizeNormal, 319 .adornment = Ttk_StateTableLookup(TabAdornmentTable, state), 320 .kind = kHIThemeTabKindNormal, 321 .position = Ttk_StateTableLookup(TabPositionTable, state), 322 }; 323 324 bounds.size.height += TAB_OVERLAP; 325 BEGIN_DRAWING(d) 326 ChkErr(HIThemeDrawTab, &bounds, &info, dc.context, HIOrientation, NULL); 327 END_DRAWING 328} 329 330static Ttk_ElementSpec TabElementSpec = { 331 TK_STYLE_VERSION_2, 332 sizeof(NullElement), 333 TtkNullElementOptions, 334 TabElementSize, 335 TabElementDraw 336}; 337 338/* 339 * Notebook panes: 340 */ 341static void PaneElementSize( 342 void *clientData, void *elementRecord, Tk_Window tkwin, 343 int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) 344{ 345 *paddingPtr = Ttk_MakePadding(9, 5, 9, 9); 346} 347 348static void PaneElementDraw( 349 void *clientData, void *elementRecord, Tk_Window tkwin, 350 Drawable d, Ttk_Box b, Ttk_State state) 351{ 352 CGRect bounds = BoxToRect(d, b); 353 HIThemeTabPaneDrawInfo info = { 354 .version = 1, 355 .state = Ttk_StateTableLookup(ThemeStateTable, state), 356 .direction = kThemeTabNorth, 357 .size = kHIThemeTabSizeNormal, 358 .kind = kHIThemeTabKindNormal, 359 .adornment = kHIThemeTabPaneAdornmentNormal, 360 }; 361 362 bounds.origin.y -= TAB_OVERLAP; 363 bounds.size.height += TAB_OVERLAP; 364 BEGIN_DRAWING(d) 365 ChkErr(HIThemeDrawTabPane, &bounds, &info, dc.context, HIOrientation); 366 END_DRAWING 367} 368 369static Ttk_ElementSpec PaneElementSpec = { 370 TK_STYLE_VERSION_2, 371 sizeof(NullElement), 372 TtkNullElementOptions, 373 PaneElementSize, 374 PaneElementDraw 375}; 376 377/* 378 * Labelframe borders: 379 * Use "primary group box ..." 380 * Quoth DrawThemePrimaryGroup reference: 381 * "The primary group box frame is drawn inside the specified 382 * rectangle and is a maximum of 2 pixels thick." 383 * 384 * "Maximum of 2 pixels thick" is apparently a lie; 385 * looks more like 4 to me with shading. 386 */ 387static void GroupElementSize( 388 void *clientData, void *elementRecord, Tk_Window tkwin, 389 int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) 390{ 391 *paddingPtr = Ttk_UniformPadding(4); 392} 393 394static void GroupElementDraw( 395 void *clientData, void *elementRecord, Tk_Window tkwin, 396 Drawable d, Ttk_Box b, Ttk_State state) 397{ 398 CGRect bounds = BoxToRect(d, b); 399 const HIThemeGroupBoxDrawInfo info = { 400 .version = 0, 401 .state = Ttk_StateTableLookup(ThemeStateTable, state), 402 .kind = kHIThemeGroupBoxKindPrimaryOpaque, 403 }; 404 405 BEGIN_DRAWING(d) 406 ChkErr(HIThemeDrawGroupBox, &bounds, &info, dc.context, HIOrientation); 407 END_DRAWING 408} 409 410static Ttk_ElementSpec GroupElementSpec = { 411 TK_STYLE_VERSION_2, 412 sizeof(NullElement), 413 TtkNullElementOptions, 414 GroupElementSize, 415 GroupElementDraw 416}; 417 418/*---------------------------------------------------------------------- 419 * +++ Entry element -- 420 * 3 pixels padding for focus rectangle 421 * 2 pixels padding for EditTextFrame 422 */ 423 424typedef struct { 425 Tcl_Obj *backgroundObj; 426} EntryElement; 427 428static Ttk_ElementOptionSpec EntryElementOptions[] = { 429 { "-background", TK_OPTION_BORDER, 430 Tk_Offset(EntryElement,backgroundObj), "white" }, 431 {0} 432}; 433 434static void EntryElementSize( 435 void *clientData, void *elementRecord, Tk_Window tkwin, 436 int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) 437{ 438 *paddingPtr = Ttk_UniformPadding(5); 439} 440 441static void EntryElementDraw( 442 void *clientData, void *elementRecord, Tk_Window tkwin, 443 Drawable d, Ttk_Box b, Ttk_State state) 444{ 445 EntryElement *e = elementRecord; 446 Tk_3DBorder backgroundPtr = Tk_Get3DBorderFromObj(tkwin,e->backgroundObj); 447 Ttk_Box inner = Ttk_PadBox(b, Ttk_UniformPadding(3)); 448 CGRect bounds = BoxToRect(d, inner); 449 const HIThemeFrameDrawInfo info = { 450 .version = 0, 451 .kind = kHIThemeFrameTextFieldSquare, 452 .state = Ttk_StateTableLookup(ThemeStateTable, state), 453 .isFocused = state & TTK_STATE_FOCUS, 454 }; 455 456 /* 457 * Erase w/background color: 458 */ 459 XFillRectangle(Tk_Display(tkwin), d, 460 Tk_3DBorderGC(tkwin, backgroundPtr, TK_3D_FLAT_GC), 461 inner.x,inner.y, inner.width, inner.height); 462 463 BEGIN_DRAWING(d) 464 ChkErr(HIThemeDrawFrame, &bounds, &info, dc.context, HIOrientation); 465 /*if (state & TTK_STATE_FOCUS) { 466 ChkErr(DrawThemeFocusRect, &bounds, 1); 467 }*/ 468 END_DRAWING 469} 470 471static Ttk_ElementSpec EntryElementSpec = { 472 TK_STYLE_VERSION_2, 473 sizeof(EntryElement), 474 EntryElementOptions, 475 EntryElementSize, 476 EntryElementDraw 477}; 478 479/*---------------------------------------------------------------------- 480 * +++ Combobox: 481 * 482 * NOTES: 483 * kThemeMetricComboBoxLargeDisclosureWidth -> 17 484 * Padding and margins guesstimated by trial-and-error. 485 */ 486 487static Ttk_Padding ComboboxPadding = { 2, 3, 17, 1 }; 488static Ttk_Padding ComboboxMargins = { 3, 3, 4, 4 }; 489 490static void ComboboxElementSize( 491 void *clientData, void *elementRecord, Tk_Window tkwin, 492 int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) 493{ 494 *widthPtr = 0; 495 *heightPtr = 0; 496 *paddingPtr = Ttk_AddPadding(ComboboxMargins, ComboboxPadding); 497} 498 499static void ComboboxElementDraw( 500 void *clientData, void *elementRecord, Tk_Window tkwin, 501 Drawable d, Ttk_Box b, Ttk_State state) 502{ 503 CGRect bounds = BoxToRect(d, Ttk_PadBox(b, ComboboxMargins)); 504 const HIThemeButtonDrawInfo info = { 505 .version = 0, 506 .state = Ttk_StateTableLookup(ThemeStateTable, state), 507 .kind = kThemeComboBox, 508 .value = Ttk_StateTableLookup(ButtonValueTable, state), 509 .adornment = Ttk_StateTableLookup(ButtonAdornmentTable, state), 510 }; 511 512 BEGIN_DRAWING(d) 513 ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, NULL); 514 END_DRAWING 515} 516 517static Ttk_ElementSpec ComboboxElementSpec = { 518 TK_STYLE_VERSION_2, 519 sizeof(NullElement), 520 TtkNullElementOptions, 521 ComboboxElementSize, 522 ComboboxElementDraw 523}; 524 525/*---------------------------------------------------------------------- 526 * +++ Spinbuttons. 527 * 528 * From Apple HIG, part III, section "Controls", "The Stepper Control": 529 * there should be 2 pixels of space between the stepper control 530 * (AKA IncDecButton, AKA "little arrows") and the text field it modifies. 531 */ 532 533static Ttk_Padding SpinbuttonMargins = {2,0,2,0}; 534static void SpinButtonElementSize( 535 void *clientData, void *elementRecord, Tk_Window tkwin, 536 int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) 537{ 538 SInt32 s; 539 540 ChkErr(GetThemeMetric, kThemeMetricLittleArrowsWidth, &s); 541 *widthPtr = s + Ttk_PaddingWidth(SpinbuttonMargins); 542 ChkErr(GetThemeMetric, kThemeMetricLittleArrowsHeight, &s); 543 *heightPtr = s + Ttk_PaddingHeight(SpinbuttonMargins); 544} 545 546static void SpinButtonElementDraw( 547 void *clientData, void *elementRecord, Tk_Window tkwin, 548 Drawable d, Ttk_Box b, Ttk_State state) 549{ 550 CGRect bounds = BoxToRect(d, Ttk_PadBox(b, SpinbuttonMargins)); 551 /* @@@ can't currently distinguish PressedUp (== Pressed) from PressedDown; 552 * ignore this bit for now [see #2219588] 553 */ 554 const HIThemeButtonDrawInfo info = { 555 .version = 0, 556 .state = Ttk_StateTableLookup(ThemeStateTable, state & ~TTK_STATE_PRESSED), 557 .kind = kThemeIncDecButton, 558 .value = Ttk_StateTableLookup(ButtonValueTable, state), 559 .adornment = kThemeAdornmentNone, 560 }; 561 562 BEGIN_DRAWING(d) 563 ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, NULL); 564 END_DRAWING 565} 566 567static Ttk_ElementSpec SpinButtonElementSpec = { 568 TK_STYLE_VERSION_2, 569 sizeof(NullElement), 570 TtkNullElementOptions, 571 SpinButtonElementSize, 572 SpinButtonElementDraw 573}; 574 575 576/*---------------------------------------------------------------------- 577 * +++ DrawThemeTrack-based elements -- 578 * Progress bars and scales. (See also: <<NOTE-TRACKS>>) 579 */ 580 581static Ttk_StateTable ThemeTrackEnableTable[] = { 582 { kThemeTrackDisabled, TTK_STATE_DISABLED, 0 }, 583 { kThemeTrackInactive, TTK_STATE_BACKGROUND, 0 }, 584 { kThemeTrackActive, 0, 0 } 585 /* { kThemeTrackNothingToScroll, ?, ? }, */ 586}; 587 588typedef struct { /* TrackElement client data */ 589 ThemeTrackKind kind; 590 SInt32 thicknessMetric; 591} TrackElementData; 592 593static TrackElementData ScaleData = { 594 kThemeSlider, kThemeMetricHSliderHeight 595}; 596 597typedef struct { 598 Tcl_Obj *fromObj; /* minimum value */ 599 Tcl_Obj *toObj; /* maximum value */ 600 Tcl_Obj *valueObj; /* current value */ 601 Tcl_Obj *orientObj; /* horizontal / vertical */ 602} TrackElement; 603 604static Ttk_ElementOptionSpec TrackElementOptions[] = { 605 { "-from", TK_OPTION_DOUBLE, Tk_Offset(TrackElement,fromObj) }, 606 { "-to", TK_OPTION_DOUBLE, Tk_Offset(TrackElement,toObj) }, 607 { "-value", TK_OPTION_DOUBLE, Tk_Offset(TrackElement,valueObj) }, 608 { "-orient", TK_OPTION_STRING, Tk_Offset(TrackElement,orientObj) }, 609 {0,0,0} 610}; 611 612static void TrackElementSize( 613 void *clientData, void *elementRecord, Tk_Window tkwin, 614 int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) 615{ 616 TrackElementData *data = clientData; 617 SInt32 size = 24; /* reasonable default ... */ 618 619 ChkErr(GetThemeMetric, data->thicknessMetric, &size); 620 *widthPtr = *heightPtr = size; 621} 622 623static void TrackElementDraw( 624 void *clientData, void *elementRecord, Tk_Window tkwin, 625 Drawable d, Ttk_Box b, Ttk_State state) 626{ 627 TrackElementData *data = clientData; 628 TrackElement *elem = elementRecord; 629 int orientation = TTK_ORIENT_HORIZONTAL; 630 double from = 0, to = 100, value = 0, factor; 631 632 Ttk_GetOrientFromObj(NULL, elem->orientObj, &orientation); 633 Tcl_GetDoubleFromObj(NULL, elem->fromObj, &from); 634 Tcl_GetDoubleFromObj(NULL, elem->toObj, &to); 635 Tcl_GetDoubleFromObj(NULL, elem->valueObj, &value); 636 factor = RangeToFactor(to - from); 637 638 HIThemeTrackDrawInfo info = { 639 .version = 0, 640 .kind = data->kind, 641 .bounds = BoxToRect(d, b), 642 .min = from * factor, 643 .max = to * factor, 644 .value = value * factor, 645 .attributes = kThemeTrackShowThumb | 646 (orientation == TTK_ORIENT_HORIZONTAL ? 647 kThemeTrackHorizontal : 0), 648 .enableState = Ttk_StateTableLookup(ThemeTrackEnableTable, state), 649 .trackInfo.progress.phase = 0, 650 }; 651 652 if (info.kind == kThemeSlider) { 653 info.trackInfo.slider.pressState = state & TTK_STATE_PRESSED ? 654 kThemeThumbPressed : 0; 655 info.trackInfo.slider.thumbDir = kThemeThumbPlain; 656 } 657 658 BEGIN_DRAWING(d) 659 ChkErr(HIThemeDrawTrack, &info, NULL, dc.context, HIOrientation); 660 END_DRAWING 661} 662 663static Ttk_ElementSpec TrackElementSpec = { 664 TK_STYLE_VERSION_2, 665 sizeof(TrackElement), 666 TrackElementOptions, 667 TrackElementSize, 668 TrackElementDraw 669}; 670 671/* 672 * Slider element -- <<NOTE-TRACKS>> 673 * Has geometry only. The Scale widget adjusts the position of this element, 674 * and uses it for hit detection. In the Aqua theme, the slider is actually 675 * drawn as part of the trough element. 676 * 677 * Also buggy: The geometry here is a Wild-Assed-Guess; I can't 678 * figure out how to get the Appearance Manager to tell me the 679 * slider size. 680 */ 681static void SliderElementSize( 682 void *clientData, void *elementRecord, Tk_Window tkwin, 683 int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) 684{ 685 *widthPtr = *heightPtr = 24; 686} 687 688static Ttk_ElementSpec SliderElementSpec = { 689 TK_STYLE_VERSION_2, 690 sizeof(NullElement), 691 TtkNullElementOptions, 692 SliderElementSize, 693 TtkNullElementDraw 694}; 695 696/*---------------------------------------------------------------------- 697 * +++ Progress bar element (new): 698 * 699 * @@@ NOTE: According to an older revision of the Aqua reference docs, 700 * @@@ the 'phase' field is between 0 and 4. Newer revisions say 701 * @@@ that it can be any UInt8 value. 702 */ 703 704typedef struct { 705 Tcl_Obj *orientObj; /* horizontal / vertical */ 706 Tcl_Obj *valueObj; /* current value */ 707 Tcl_Obj *maximumObj; /* maximum value */ 708 Tcl_Obj *phaseObj; /* animation phase */ 709 Tcl_Obj *modeObj; /* progress bar mode */ 710} PbarElement; 711 712static Ttk_ElementOptionSpec PbarElementOptions[] = { 713 { "-orient", TK_OPTION_STRING, 714 Tk_Offset(PbarElement,orientObj), "horizontal" }, 715 { "-value", TK_OPTION_DOUBLE, 716 Tk_Offset(PbarElement,valueObj), "0" }, 717 { "-maximum", TK_OPTION_DOUBLE, 718 Tk_Offset(PbarElement,maximumObj), "100" }, 719 { "-phase", TK_OPTION_INT, 720 Tk_Offset(PbarElement,phaseObj), "0" }, 721 { "-mode", TK_OPTION_STRING, 722 Tk_Offset(PbarElement,modeObj), "determinate" }, 723 {0,0,0,0} 724}; 725 726static void PbarElementSize( 727 void *clientData, void *elementRecord, Tk_Window tkwin, 728 int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) 729{ 730 SInt32 size = 24; /* @@@ Check HIG for correct default */ 731 732 ChkErr(GetThemeMetric, kThemeMetricLargeProgressBarThickness, &size); 733 *widthPtr = *heightPtr = size; 734} 735 736static void PbarElementDraw( 737 void *clientData, void *elementRecord, Tk_Window tkwin, 738 Drawable d, Ttk_Box b, Ttk_State state) 739{ 740 PbarElement *pbar = elementRecord; 741 int orientation = TTK_ORIENT_HORIZONTAL, phase = 0; 742 double value = 0, maximum = 100, factor; 743 744 Ttk_GetOrientFromObj(NULL, pbar->orientObj, &orientation); 745 Tcl_GetDoubleFromObj(NULL, pbar->valueObj, &value); 746 Tcl_GetDoubleFromObj(NULL, pbar->maximumObj, &maximum); 747 Tcl_GetIntFromObj(NULL, pbar->phaseObj, &phase); 748 factor = RangeToFactor(maximum); 749 750 HIThemeTrackDrawInfo info = { 751 .version = 0, 752 .kind = (!strcmp("indeterminate", Tcl_GetString(pbar->modeObj)) && value) ? 753 kThemeIndeterminateBar : kThemeProgressBar, 754 .bounds = BoxToRect(d, b), 755 .min = 0, 756 .max = maximum * factor, 757 .value = value * factor, 758 .attributes = kThemeTrackShowThumb | 759 (orientation == TTK_ORIENT_HORIZONTAL ? 760 kThemeTrackHorizontal : 0), 761 .enableState = Ttk_StateTableLookup(ThemeTrackEnableTable, state), 762 .trackInfo.progress.phase = phase, 763 }; 764 765 BEGIN_DRAWING(d) 766 ChkErr(HIThemeDrawTrack, &info, NULL, dc.context, HIOrientation); 767 END_DRAWING 768} 769 770static Ttk_ElementSpec PbarElementSpec = { 771 TK_STYLE_VERSION_2, 772 sizeof(PbarElement), 773 PbarElementOptions, 774 PbarElementSize, 775 PbarElementDraw 776}; 777 778/*---------------------------------------------------------------------- 779 * +++ Separator element. 780 * 781 * DrawThemeSeparator() guesses the orientation of the line from 782 * the width and height of the rectangle, so the same element can 783 * can be used for horizontal, vertical, and general separators. 784 */ 785 786static void SeparatorElementSize( 787 void *clientData, void *elementRecord, Tk_Window tkwin, 788 int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) 789{ 790 *widthPtr = *heightPtr = 1; 791} 792 793static void SeparatorElementDraw( 794 void *clientData, void *elementRecord, Tk_Window tkwin, 795 Drawable d, Ttk_Box b, unsigned int state) 796{ 797 CGRect bounds = BoxToRect(d, b); 798 const HIThemeSeparatorDrawInfo info = { 799 .version = 0, 800 /* Separator only supports kThemeStateActive, kThemeStateInactive */ 801 .state = Ttk_StateTableLookup(ThemeStateTable, state & TTK_STATE_BACKGROUND), 802 }; 803 804 BEGIN_DRAWING(d) 805 ChkErr(HIThemeDrawSeparator, &bounds, &info, dc.context, HIOrientation); 806 END_DRAWING 807} 808 809static Ttk_ElementSpec SeparatorElementSpec = { 810 TK_STYLE_VERSION_2, 811 sizeof(NullElement), 812 TtkNullElementOptions, 813 SeparatorElementSize, 814 SeparatorElementDraw 815}; 816 817/*---------------------------------------------------------------------- 818 * +++ Size grip element. 819 */ 820static const ThemeGrowDirection sizegripGrowDirection 821 = kThemeGrowRight|kThemeGrowDown; 822 823static void SizegripElementSize( 824 void *clientData, void *elementRecord, Tk_Window tkwin, 825 int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) 826{ 827 HIThemeGrowBoxDrawInfo info = { 828 .version = 0, 829 .state = kThemeStateActive, 830 .kind = kHIThemeGrowBoxKindNormal, 831 .direction = sizegripGrowDirection, 832 .size = kHIThemeGrowBoxSizeNormal, 833 }; 834 CGRect bounds = CGRectZero; 835 836 ChkErr(HIThemeGetGrowBoxBounds, &bounds.origin, &info, &bounds); 837 *widthPtr = bounds.size.width; 838 *heightPtr = bounds.size.height; 839} 840 841static void SizegripElementDraw( 842 void *clientData, void *elementRecord, Tk_Window tkwin, 843 Drawable d, Ttk_Box b, unsigned int state) 844{ 845 CGRect bounds = BoxToRect(d, b); 846 HIThemeGrowBoxDrawInfo info = { 847 .version = 0, 848 /* Grow box only supports kThemeStateActive, kThemeStateInactive */ 849 .state = Ttk_StateTableLookup(ThemeStateTable, state & TTK_STATE_BACKGROUND), 850 .kind = kHIThemeGrowBoxKindNormal, 851 .direction = sizegripGrowDirection, 852 .size = kHIThemeGrowBoxSizeNormal, 853 }; 854 855 BEGIN_DRAWING(d) 856 ChkErr(HIThemeDrawGrowBox, &bounds.origin, &info, dc.context, HIOrientation); 857 END_DRAWING 858} 859 860static Ttk_ElementSpec SizegripElementSpec = { 861 TK_STYLE_VERSION_2, 862 sizeof(NullElement), 863 TtkNullElementOptions, 864 SizegripElementSize, 865 SizegripElementDraw 866}; 867 868/*---------------------------------------------------------------------- 869 * +++ Background and fill elements. 870 * 871 * This isn't quite right: In Aqua, the correct background for 872 * a control depends on what kind of container it belongs to, 873 * and the type of the top-level window. 874 * 875 * Also: patterned backgrounds should be aligned with the coordinate 876 * system of the top-level window. If we're drawing into an 877 * off-screen graphics port this leads to alignment glitches. 878 */ 879 880static void FillElementDraw( 881 void *clientData, void *elementRecord, Tk_Window tkwin, 882 Drawable d, Ttk_Box b, Ttk_State state) 883{ 884 CGRect bounds = BoxToRect(d, b); 885 ThemeBrush brush = (state & TTK_STATE_BACKGROUND) 886 ? kThemeBrushModelessDialogBackgroundInactive 887 : kThemeBrushModelessDialogBackgroundActive; 888 889 BEGIN_DRAWING(d) 890 ChkErr(HIThemeSetFill, brush, NULL, dc.context, HIOrientation); 891 //QDSetPatternOrigin(PatternOrigin(tkwin, d)); 892 CGContextFillRect(dc.context, bounds); 893 END_DRAWING 894} 895 896static void BackgroundElementDraw( 897 void *clientData, void *elementRecord, Tk_Window tkwin, 898 Drawable d, Ttk_Box b, unsigned int state) 899{ 900 FillElementDraw( 901 clientData, elementRecord, tkwin, 902 d, Ttk_WinBox(tkwin), state); 903} 904 905static Ttk_ElementSpec FillElementSpec = { 906 TK_STYLE_VERSION_2, 907 sizeof(NullElement), 908 TtkNullElementOptions, 909 TtkNullElementSize, 910 FillElementDraw 911}; 912 913static Ttk_ElementSpec BackgroundElementSpec = { 914 TK_STYLE_VERSION_2, 915 sizeof(NullElement), 916 TtkNullElementOptions, 917 TtkNullElementSize, 918 BackgroundElementDraw 919}; 920 921/*---------------------------------------------------------------------- 922 * +++ ToolbarBackground element -- toolbar style for frames. 923 * 924 * This is very similar to the normal background element, but uses a 925 * different ThemeBrush in order to get the lighter pinstripe effect 926 * used in toolbars. We use SetThemeBackground() rather than 927 * ApplyThemeBackground() in order to get the right style. 928 * 929 * <URL: http://developer.apple.com/documentation/Carbon/Reference/ 930 * Appearance_Manager/appearance_manager/constant_7.html#/ 931 * /apple_ref/doc/uid/TP30000243/C005321> 932 * 933 */ 934static void ToolbarBackgroundElementDraw( 935 void *clientData, void *elementRecord, Tk_Window tkwin, 936 Drawable d, Ttk_Box b, Ttk_State state) 937{ 938 ThemeBrush brush = kThemeBrushToolbarBackground; 939 CGRect bounds = BoxToRect(d, Ttk_WinBox(tkwin)); 940 941 BEGIN_DRAWING(d) 942 ChkErr(HIThemeSetFill, brush, NULL, dc.context, HIOrientation); 943 //QDSetPatternOrigin(PatternOrigin(tkwin, d)); 944 CGContextFillRect(dc.context, bounds); 945 END_DRAWING 946} 947 948static Ttk_ElementSpec ToolbarBackgroundElementSpec = { 949 TK_STYLE_VERSION_2, 950 sizeof(NullElement), 951 TtkNullElementOptions, 952 TtkNullElementSize, 953 ToolbarBackgroundElementDraw 954}; 955 956/*---------------------------------------------------------------------- 957 * +++ Treeview header 958 * Redefine the header to use a kThemeListHeaderButton. 959 */ 960 961#define TTK_TREEVIEW_STATE_SORTARROW TTK_STATE_USER1 962static Ttk_StateTable TreeHeaderValueTable[] = { 963 { kThemeButtonOn, TTK_STATE_ALTERNATE}, 964 { kThemeButtonOn, TTK_STATE_SELECTED}, 965 { kThemeButtonOff, 0} 966}; 967static Ttk_StateTable TreeHeaderAdornmentTable[] = { 968 { kThemeAdornmentHeaderButtonSortUp, 969 TTK_STATE_ALTERNATE|TTK_TREEVIEW_STATE_SORTARROW}, 970 { kThemeAdornmentDefault, 971 TTK_STATE_SELECTED|TTK_TREEVIEW_STATE_SORTARROW}, 972 { kThemeAdornmentHeaderButtonNoSortArrow, TTK_STATE_ALTERNATE}, 973 { kThemeAdornmentHeaderButtonNoSortArrow, TTK_STATE_SELECTED}, 974 { kThemeAdornmentFocus, TTK_STATE_FOCUS}, 975 { kThemeAdornmentNone, 0} 976}; 977 978static void TreeHeaderElementDraw( 979 void *clientData, void *elementRecord, Tk_Window tkwin, 980 Drawable d, Ttk_Box b, Ttk_State state) 981{ 982 ThemeButtonParams *params = clientData; 983 CGRect bounds = BoxToRect(d, b); 984 const HIThemeButtonDrawInfo info = { 985 .version = 0, 986 .state = Ttk_StateTableLookup(ThemeStateTable, state), 987 .kind = params->kind, 988 .value = Ttk_StateTableLookup(TreeHeaderValueTable, state), 989 .adornment = Ttk_StateTableLookup(TreeHeaderAdornmentTable, state), 990 }; 991 992 BEGIN_DRAWING(d) 993 ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, NULL); 994 END_DRAWING 995} 996 997static Ttk_ElementSpec TreeHeaderElementSpec = { 998 TK_STYLE_VERSION_2, 999 sizeof(NullElement), 1000 TtkNullElementOptions, 1001 ButtonElementSizeNoPadding, 1002 TreeHeaderElementDraw 1003}; 1004 1005/* 1006 * Disclosure triangle: 1007 */ 1008#define TTK_TREEVIEW_STATE_OPEN TTK_STATE_USER1 1009#define TTK_TREEVIEW_STATE_LEAF TTK_STATE_USER2 1010static Ttk_StateTable DisclosureValueTable[] = { 1011 { kThemeDisclosureDown, TTK_TREEVIEW_STATE_OPEN, 0 }, 1012 { kThemeDisclosureRight, 0, 0 }, 1013}; 1014 1015static void DisclosureElementSize( 1016 void *clientData, void *elementRecord, Tk_Window tkwin, 1017 int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) 1018{ 1019 SInt32 s; 1020 1021 ChkErr(GetThemeMetric, kThemeMetricDisclosureTriangleWidth, &s); 1022 *widthPtr = s; 1023 ChkErr(GetThemeMetric, kThemeMetricDisclosureTriangleHeight, &s); 1024 *heightPtr = s; 1025} 1026 1027static void DisclosureElementDraw( 1028 void *clientData, void *elementRecord, Tk_Window tkwin, 1029 Drawable d, Ttk_Box b, Ttk_State state) 1030{ 1031 if (!(state & TTK_TREEVIEW_STATE_LEAF)) { 1032 CGRect bounds = BoxToRect(d, b); 1033 const HIThemeButtonDrawInfo info = { 1034 .version = 0, 1035 .state = Ttk_StateTableLookup(ThemeStateTable, state), 1036 .kind = kThemeDisclosureTriangle, 1037 .value = Ttk_StateTableLookup(DisclosureValueTable, state), 1038 .adornment = kThemeAdornmentDrawIndicatorOnly, 1039 }; 1040 1041 BEGIN_DRAWING(d) 1042 ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, NULL); 1043 END_DRAWING 1044 } 1045} 1046 1047static Ttk_ElementSpec DisclosureElementSpec = { 1048 TK_STYLE_VERSION_2, 1049 sizeof(NullElement), 1050 TtkNullElementOptions, 1051 DisclosureElementSize, 1052 DisclosureElementDraw 1053}; 1054 1055/*---------------------------------------------------------------------- 1056 * +++ Widget layouts. 1057 */ 1058 1059TTK_BEGIN_LAYOUT_TABLE(LayoutTable) 1060 1061TTK_LAYOUT("Toolbar", 1062 TTK_NODE("Toolbar.background", TTK_FILL_BOTH)) 1063 1064TTK_LAYOUT("TButton", 1065 TTK_GROUP("Button.button", TTK_FILL_BOTH, 1066 TTK_GROUP("Button.padding", TTK_FILL_BOTH, 1067 TTK_NODE("Button.label", TTK_FILL_BOTH)))) 1068 1069TTK_LAYOUT("TRadiobutton", 1070 TTK_GROUP("Radiobutton.button", TTK_FILL_BOTH, 1071 TTK_GROUP("Radiobutton.padding", TTK_FILL_BOTH, 1072 TTK_NODE("Radiobutton.label", TTK_PACK_LEFT)))) 1073 1074TTK_LAYOUT("TCheckbutton", 1075 TTK_GROUP("Checkbutton.button", TTK_FILL_BOTH, 1076 TTK_GROUP("Checkbutton.padding", TTK_FILL_BOTH, 1077 TTK_NODE("Checkbutton.label", TTK_PACK_LEFT)))) 1078 1079TTK_LAYOUT("TMenubutton", 1080 TTK_GROUP("Menubutton.button", TTK_FILL_BOTH, 1081 TTK_GROUP("Menubutton.padding", TTK_FILL_BOTH, 1082 TTK_NODE("Menubutton.label", TTK_PACK_LEFT)))) 1083 1084TTK_LAYOUT("TCombobox", 1085 TTK_GROUP("Combobox.button", TTK_PACK_TOP|TTK_FILL_X, 1086 TTK_GROUP("Combobox.padding", TTK_FILL_BOTH, 1087 TTK_NODE("Combobox.textarea", TTK_FILL_X)))) 1088 1089/* Notebook tabs -- no focus ring */ 1090TTK_LAYOUT("Tab", 1091 TTK_GROUP("Notebook.tab", TTK_FILL_BOTH, 1092 TTK_GROUP("Notebook.padding", TTK_EXPAND|TTK_FILL_BOTH, 1093 TTK_NODE("Notebook.label", TTK_EXPAND|TTK_FILL_BOTH)))) 1094 1095/* Progress bars -- track only */ 1096TTK_LAYOUT("TSpinbox", 1097 TTK_NODE("Spinbox.spinbutton", TTK_PACK_RIGHT|TTK_STICK_E) 1098 TTK_GROUP("Spinbox.field", TTK_EXPAND|TTK_FILL_X, 1099 TTK_NODE("Spinbox.textarea", TTK_EXPAND|TTK_FILL_X))) 1100 1101TTK_LAYOUT("TProgressbar", 1102 TTK_NODE("Progressbar.track", TTK_EXPAND|TTK_FILL_BOTH)) 1103 1104/* Tree heading -- no border, fixed height */ 1105TTK_LAYOUT("Heading", 1106 TTK_NODE("Treeheading.cell", TTK_FILL_X) 1107 TTK_NODE("Treeheading.image", TTK_PACK_RIGHT) 1108 TTK_NODE("Treeheading.text", 0)) 1109 1110/* Tree items -- omit focus ring */ 1111TTK_LAYOUT("Item", 1112 TTK_GROUP("Treeitem.padding", TTK_FILL_BOTH, 1113 TTK_NODE("Treeitem.indicator", TTK_PACK_LEFT) 1114 TTK_NODE("Treeitem.image", TTK_PACK_LEFT) 1115 TTK_NODE("Treeitem.text", TTK_PACK_LEFT))) 1116 1117TTK_END_LAYOUT_TABLE 1118 1119/*---------------------------------------------------------------------- 1120 * +++ Initialization. 1121 */ 1122 1123static int AquaTheme_Init(Tcl_Interp *interp) 1124{ 1125 Ttk_Theme themePtr = Ttk_CreateTheme(interp, "aqua", NULL); 1126 1127 if (!themePtr) { 1128 return TCL_ERROR; 1129 } 1130 1131 /* 1132 * Elements: 1133 */ 1134 Ttk_RegisterElementSpec(themePtr, "background", &BackgroundElementSpec, 0); 1135 Ttk_RegisterElementSpec(themePtr, "fill", &FillElementSpec, 0); 1136 Ttk_RegisterElementSpec(themePtr, "Toolbar.background", 1137 &ToolbarBackgroundElementSpec, 0); 1138 1139 Ttk_RegisterElementSpec(themePtr, "Button.button", 1140 &ButtonElementSpec, &PushButtonParams); 1141 Ttk_RegisterElementSpec(themePtr, "Checkbutton.button", 1142 &ButtonElementSpec, &CheckBoxParams); 1143 Ttk_RegisterElementSpec(themePtr, "Radiobutton.button", 1144 &ButtonElementSpec, &RadioButtonParams); 1145 Ttk_RegisterElementSpec(themePtr, "Toolbutton.border", 1146 &ButtonElementSpec, &BevelButtonParams); 1147 Ttk_RegisterElementSpec(themePtr, "Menubutton.button", 1148 &ButtonElementSpec, &PopupButtonParams); 1149 Ttk_RegisterElementSpec(themePtr, "Spinbox.spinbutton", 1150 &SpinButtonElementSpec, 0); 1151 Ttk_RegisterElementSpec(themePtr, "Combobox.button", 1152 &ComboboxElementSpec, 0); 1153 Ttk_RegisterElementSpec(themePtr, "Treeitem.indicator", 1154 &DisclosureElementSpec, &DisclosureParams); 1155 Ttk_RegisterElementSpec(themePtr, "Treeheading.cell", 1156 &TreeHeaderElementSpec, &ListHeaderParams); 1157 1158 Ttk_RegisterElementSpec(themePtr, "Notebook.tab", &TabElementSpec, 0); 1159 Ttk_RegisterElementSpec(themePtr, "Notebook.client", &PaneElementSpec, 0); 1160 1161 Ttk_RegisterElementSpec(themePtr, "Labelframe.border",&GroupElementSpec,0); 1162 Ttk_RegisterElementSpec(themePtr, "Entry.field",&EntryElementSpec,0); 1163 Ttk_RegisterElementSpec(themePtr, "Spinbox.field",&EntryElementSpec,0); 1164 1165 Ttk_RegisterElementSpec(themePtr, "separator",&SeparatorElementSpec,0); 1166 Ttk_RegisterElementSpec(themePtr, "hseparator",&SeparatorElementSpec,0); 1167 Ttk_RegisterElementSpec(themePtr, "vseparator",&SeparatorElementSpec,0); 1168 1169 Ttk_RegisterElementSpec(themePtr, "sizegrip",&SizegripElementSpec,0); 1170 1171 /* 1172 * <<NOTE-TRACKS>> 1173 * The Progressbar widget adjusts the size of the pbar element. 1174 * In the Aqua theme, the appearance manager computes the bar geometry; 1175 * we do all the drawing in the ".track" element and leave the .pbar out. 1176 */ 1177 Ttk_RegisterElementSpec(themePtr,"Scale.trough", 1178 &TrackElementSpec, &ScaleData); 1179 Ttk_RegisterElementSpec(themePtr,"Scale.slider",&SliderElementSpec,0); 1180 Ttk_RegisterElementSpec(themePtr,"Progressbar.track", &PbarElementSpec, 0); 1181 1182 /* 1183 * Layouts: 1184 */ 1185 Ttk_RegisterLayouts(themePtr, LayoutTable); 1186 1187 Tcl_PkgProvide(interp, "ttk::theme::aqua", TTK_VERSION); 1188 return TCL_OK; 1189} 1190 1191MODULE_SCOPE 1192int Ttk_MacOSXPlatformInit(Tcl_Interp *interp) 1193{ 1194 return AquaTheme_Init(interp); 1195} 1196 1197/* 1198 * Local Variables: 1199 * mode: c 1200 * c-basic-offset: 4 1201 * fill-column: 79 1202 * coding: utf-8 1203 * End: 1204 */ 1205 1206