/* * computeButtonDrawInfo -- * Fill in an appearance manager HIThemeButtonDrawInfo record. */ static inline HIThemeButtonDrawInfo computeButtonDrawInfo( ThemeButtonParams *params, Ttk_State state) { const HIThemeButtonDrawInfo info = { .version = 0, .state = Ttk_StateTableLookup(ThemeStateTable, state), .kind = params ? params->kind : 0, .value = Ttk_StateTableLookup(ButtonValueTable, state), .adornment = Ttk_StateTableLookup(ButtonAdornmentTable, state), }; return info; } static void ButtonElementSizeNoPadding( void *clientData, void *elementRecord, Tk_Window tkwin, int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) { ThemeButtonParams *params = clientData; if (params->heightMetric != NoThemeMetric) { SInt32 height; ChkErr(GetThemeMetric, params->heightMetric, &height); *heightPtr = height; } }
/* * computeButtonDrawInfo -- * Fill in an appearance manager ThemeButtonDrawInfo record. */ static ThemeButtonDrawInfo computeButtonDrawInfo( ThemeButtonParms *parms, Ttk_State state) { ThemeButtonDrawInfo info; info.state = Ttk_StateTableLookup(ThemeStateTable, state); info.value = Ttk_StateTableLookup(ButtonValueTable, state); info.adornment = Ttk_StateTableLookup(ButtonAdornmentTable, state); return info; }
static void TreeHeaderElementDraw( void *clientData, void *elementRecord, Tk_Window tkwin, Drawable d, Ttk_Box b, Ttk_State state) { ThemeButtonParams *params = clientData; CGRect bounds = BoxToRect(d, b); const HIThemeButtonDrawInfo info = { .version = 0, .state = Ttk_StateTableLookup(ThemeStateTable, state), .kind = params->kind, .value = Ttk_StateTableLookup(TreeHeaderValueTable, state), .adornment = Ttk_StateTableLookup(TreeHeaderAdornmentTable, state), }; BEGIN_DRAWING(d) ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, NULL); END_DRAWING } static Ttk_ElementSpec TreeHeaderElementSpec = { TK_STYLE_VERSION_2, sizeof(NullElement), TtkNullElementOptions, ButtonElementSizeNoPadding, TreeHeaderElementDraw }; /* * Disclosure triangle: */ #define TTK_TREEVIEW_STATE_OPEN TTK_STATE_USER1 #define TTK_TREEVIEW_STATE_LEAF TTK_STATE_USER2 static Ttk_StateTable DisclosureValueTable[] = { { kThemeDisclosureDown, TTK_TREEVIEW_STATE_OPEN, 0 }, { kThemeDisclosureRight, 0, 0 }, }; static void DisclosureElementSize( void *clientData, void *elementRecord, Tk_Window tkwin, int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) { SInt32 s; ChkErr(GetThemeMetric, kThemeMetricDisclosureTriangleWidth, &s); *widthPtr = s; ChkErr(GetThemeMetric, kThemeMetricDisclosureTriangleHeight, &s); *heightPtr = s; }
static void TreeHeaderElementDraw( void *clientData, void *elementRecord, Tk_Window tkwin, Drawable d, Ttk_Box b, Ttk_State state) { ThemeButtonParms *parms = clientData; Rect bounds = BoxToRect(d, b); ThemeButtonDrawInfo info; info.state = Ttk_StateTableLookup(ThemeStateTable, state); info.value = Ttk_StateTableLookup(ButtonValueTable, state); info.adornment = Ttk_StateTableLookup(TreeHeaderAdornmentTable, state); BEGIN_DRAWING(d) ChkErr(DrawThemeButton, &bounds, parms->kind, &info, NULL, NULL, NULL, 0); END_DRAWING }
static void PbarElementDraw( void *clientData, void *elementRecord, Tk_Window tkwin, Drawable d, Ttk_Box b, Ttk_State state) { PbarElement *pbar = elementRecord; int orientation = TTK_ORIENT_HORIZONTAL; double value = 0, maximum = 100; int phase = 0; ThemeTrackDrawInfo info; Ttk_GetOrientFromObj(NULL, pbar->orientObj, &orientation); Tcl_GetDoubleFromObj(NULL, pbar->valueObj, &value); Tcl_GetDoubleFromObj(NULL, pbar->maximumObj, &maximum); Tcl_GetIntFromObj(NULL, pbar->phaseObj, &phase); if (!strcmp("indeterminate", Tcl_GetString(pbar->modeObj)) && value) { info.kind = kThemeIndeterminateBar; } else { info.kind = kThemeProgressBar; } info.bounds = BoxToRect(d, b); info.min = 0; info.max = (int) maximum; /* @@@ See note above */ info.value = (int) value; info.attributes = orientation == TTK_ORIENT_HORIZONTAL ? kThemeTrackHorizontal : 0; info.attributes |= kThemeTrackShowThumb; info.enableState = Ttk_StateTableLookup(ThemeTrackEnableTable, state); info.trackInfo.progress.phase = phase; BEGIN_DRAWING(d) ChkErr(DrawThemeTrack, &info, NULL, NULL, 0); END_DRAWING }
static void ComboboxElementDraw( void *clientData, void *elementRecord, Tk_Window tkwin, Drawable d, Ttk_Box b, Ttk_State state) { CGRect bounds = BoxToRect(d, Ttk_PadBox(b, ComboboxMargins)); const HIThemeButtonDrawInfo info = { .version = 0, .state = Ttk_StateTableLookup(ThemeStateTable, state), .kind = kThemeComboBox, .value = Ttk_StateTableLookup(ButtonValueTable, state), .adornment = Ttk_StateTableLookup(ButtonAdornmentTable, state), }; BEGIN_DRAWING(d) ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, NULL); END_DRAWING } static Ttk_ElementSpec ComboboxElementSpec = { TK_STYLE_VERSION_2, sizeof(NullElement), TtkNullElementOptions, ComboboxElementSize, ComboboxElementDraw }; /*---------------------------------------------------------------------- * +++ Spinbuttons. * * From Apple HIG, part III, section "Controls", "The Stepper Control": * there should be 2 pixels of space between the stepper control * (AKA IncDecButton, AKA "little arrows") and the text field it modifies. */ static Ttk_Padding SpinbuttonMargins = {2,0,2,0}; static void SpinButtonElementSize( void *clientData, void *elementRecord, Tk_Window tkwin, int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) { SInt32 s; ChkErr(GetThemeMetric, kThemeMetricLittleArrowsWidth, &s); *widthPtr = s + Ttk_PaddingWidth(SpinbuttonMargins); ChkErr(GetThemeMetric, kThemeMetricLittleArrowsHeight, &s); *heightPtr = s + Ttk_PaddingHeight(SpinbuttonMargins); }
static void EntryElementDraw( void *clientData, void *elementRecord, Tk_Window tkwin, Drawable d, Ttk_Box b, Ttk_State state) { EntryElement *e = elementRecord; Tk_3DBorder backgroundPtr = Tk_Get3DBorderFromObj(tkwin,e->backgroundObj); Ttk_Box inner = Ttk_PadBox(b, Ttk_UniformPadding(3)); CGRect bounds = BoxToRect(d, inner); const HIThemeFrameDrawInfo info = { .version = 0, .kind = kHIThemeFrameTextFieldSquare, .state = Ttk_StateTableLookup(ThemeStateTable, state), .isFocused = state & TTK_STATE_FOCUS, }; /* * Erase w/background color: */ XFillRectangle(Tk_Display(tkwin), d, Tk_3DBorderGC(tkwin, backgroundPtr, TK_3D_FLAT_GC), inner.x,inner.y, inner.width, inner.height); BEGIN_DRAWING(d) ChkErr(HIThemeDrawFrame, &bounds, &info, dc.context, HIOrientation); /*if (state & TTK_STATE_FOCUS) { ChkErr(DrawThemeFocusRect, &bounds, 1); }*/ END_DRAWING } static Ttk_ElementSpec EntryElementSpec = { TK_STYLE_VERSION_2, sizeof(EntryElement), EntryElementOptions, EntryElementSize, EntryElementDraw }; /*---------------------------------------------------------------------- * +++ Combobox: * * NOTES: * kThemeMetricComboBoxLargeDisclosureWidth -> 17 * Padding and margins guesstimated by trial-and-error. */ static Ttk_Padding ComboboxPadding = { 2, 3, 17, 1 }; static Ttk_Padding ComboboxMargins = { 3, 3, 4, 4 }; static void ComboboxElementSize( void *clientData, void *elementRecord, Tk_Window tkwin, int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) { *widthPtr = 0; *heightPtr = 0; *paddingPtr = Ttk_AddPadding(ComboboxMargins, ComboboxPadding); }
static void DisclosureElementDraw( void *clientData, void *elementRecord, Tk_Window tkwin, Drawable d, Ttk_Box b, Ttk_State state) { if (!(state & TTK_TREEVIEW_STATE_LEAF)) { CGRect bounds = BoxToRect(d, b); const HIThemeButtonDrawInfo info = { .version = 0, .state = Ttk_StateTableLookup(ThemeStateTable, state), .kind = kThemeDisclosureTriangle, .value = Ttk_StateTableLookup(DisclosureValueTable, state), .adornment = kThemeAdornmentDrawIndicatorOnly, }; BEGIN_DRAWING(d) ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, NULL); END_DRAWING } }
static void GroupElementDraw( void *clientData, void *elementRecord, Tk_Window tkwin, Drawable d, Ttk_Box b, Ttk_State state) { Rect bounds = BoxToRect(d, b); ThemeDrawState drawState = Ttk_StateTableLookup(ThemeStateTable, state); BEGIN_DRAWING(d) ChkErr(DrawThemePrimaryGroup, &bounds, drawState); END_DRAWING }
static void DisclosureElementDraw( void *clientData, void *elementRecord, Tk_Window tkwin, Drawable d, Ttk_Box b, Ttk_State state) { Rect bounds = BoxToRect(d, b); ThemeButtonDrawInfo info; if (state & TTK_TREEVIEW_STATE_LEAF) { return; } info.state = Ttk_StateTableLookup(ThemeStateTable, state); info.value = Ttk_StateTableLookup(DisclosureValueTable, state); info.adornment = kThemeAdornmentDrawIndicatorOnly; BEGIN_DRAWING(d) ChkErr(DrawThemeButton, &bounds, kThemeDisclosureTriangle, &info, NULL, DontErase, NULL, 0); END_DRAWING }
static void SpinButtonElementDraw( void *clientData, void *elementRecord, Tk_Window tkwin, Drawable d, Ttk_Box b, Ttk_State state) { Rect bounds = BoxToRect(d, Ttk_PadBox(b, SpinbuttonMargins)); ThemeButtonDrawInfo info; /* @@@ can't currently distinguish PressedUp (== Pressed) from PressedDown; * ignore this bit for now [see #2219588] */ info.state = Ttk_StateTableLookup(ThemeStateTable, state & ~TTK_STATE_PRESSED); info.value = Ttk_StateTableLookup(ButtonValueTable, state); info.adornment = kThemeAdornmentNone; BEGIN_DRAWING(d) ChkErr(DrawThemeButton, &bounds, kThemeIncDecButton, &info, NULL, NULL, NULL, 0); END_DRAWING }
static void TabElementDraw( void *clientData, void *elementRecord, Tk_Window tkwin, Drawable d, Ttk_Box b, Ttk_State state) { Rect bounds = BoxToRect(d, b); ThemeTabStyle tabStyle = Ttk_StateTableLookup(TabStyleTable, state); bounds.bottom += TAB_OVERLAP; BEGIN_DRAWING(d) ChkErr(DrawThemeTab, &bounds, tabStyle, kThemeTabNorth, 0, 0); END_DRAWING }
static void FrameControlElementDraw( void *clientData, void *elementRecord, Tk_Window tkwin, Drawable d, Ttk_Box b, unsigned int state) { FrameControlElementData *elementData = clientData; RECT rc = BoxToRect(Ttk_PadBox(b, elementData->margins)); TkWinDCState dcState; HDC hdc = TkWinGetDrawableDC(Tk_Display(tkwin), d, &dcState); DrawFrameControl(hdc, &rc, elementData->classId, elementData->partId|Ttk_StateTableLookup(elementData->stateMap, state)); TkWinReleaseDrawableDC(d, hdc, &dcState); }
static void TabElementDraw( void *clientData, void *elementRecord, Tk_Window tkwin, Drawable d, Ttk_Box b, Ttk_State state) { CGRect bounds = BoxToRect(d, b); HIThemeTabDrawInfo info = { .version = 1, .style = Ttk_StateTableLookup(TabStyleTable, state), .direction = kThemeTabNorth, .size = kHIThemeTabSizeNormal, .adornment = Ttk_StateTableLookup(TabAdornmentTable, state), .kind = kHIThemeTabKindNormal, .position = Ttk_StateTableLookup(TabPositionTable, state), }; BEGIN_DRAWING(d) ChkErr(HIThemeDrawTab, &bounds, &info, dc.context, HIOrientation, NULL); END_DRAWING } static Ttk_ElementSpec TabElementSpec = { TK_STYLE_VERSION_2, sizeof(NullElement), TtkNullElementOptions, TabElementSize, TabElementDraw }; /* * Notebook panes: */ static void PaneElementSize( void *clientData, void *elementRecord, Tk_Window tkwin, int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) { *paddingPtr = Ttk_MakePadding(9, 5, 9, 9); }
static void SeparatorElementDraw( void *clientData, void *elementRecord, Tk_Window tkwin, Drawable d, Ttk_Box b, unsigned int state) { Rect bounds = BoxToRect(d, b); ThemeDrawState drawState = Ttk_StateTableLookup(ThemeStateTable, state); /* * DrawThemeSeparator only supports kThemeStateActive / kThemeStateInactive */ state &= TTK_STATE_BACKGROUND; BEGIN_DRAWING(d) ChkErr(DrawThemeSeparator, &bounds, drawState); END_DRAWING }
static void SizegripElementDraw( void *clientData, void *elementRecord, Tk_Window tkwin, Drawable d, Ttk_Box b, unsigned int state) { Rect bounds = BoxToRect(d, b); Point origin = {bounds.top, bounds.left}; /* Grow box only supports kThemeStateActive, kThemeStateInactive */ state &= TTK_STATE_BACKGROUND; BEGIN_DRAWING(d) ChkErr(DrawThemeStandaloneGrowBox, origin, sizegripGrowDirection, false, Ttk_StateTableLookup(ThemeStateTable, state)); END_DRAWING }
static void GroupElementDraw( void *clientData, void *elementRecord, Tk_Window tkwin, Drawable d, Ttk_Box b, Ttk_State state) { CGRect bounds = BoxToRect(d, b); const HIThemeGroupBoxDrawInfo info = { .version = 0, .state = Ttk_StateTableLookup(ThemeStateTable, state), .kind = kHIThemeGroupBoxKindPrimaryOpaque, }; BEGIN_DRAWING(d) ChkErr(HIThemeDrawGroupBox, &bounds, &info, dc.context, HIOrientation); END_DRAWING } static Ttk_ElementSpec GroupElementSpec = { TK_STYLE_VERSION_2, sizeof(NullElement), TtkNullElementOptions, GroupElementSize, GroupElementDraw }; /*---------------------------------------------------------------------- * +++ Entry element -- * 3 pixels padding for focus rectangle * 2 pixels padding for EditTextFrame */ typedef struct { Tcl_Obj *backgroundObj; } EntryElement; static Ttk_ElementOptionSpec EntryElementOptions[] = { { "-background", TK_OPTION_BORDER, Tk_Offset(EntryElement,backgroundObj), "white" }, {0} }; static void EntryElementSize( void *clientData, void *elementRecord, Tk_Window tkwin, int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) { *paddingPtr = Ttk_UniformPadding(5); }
static void PaneElementDraw( void *clientData, void *elementRecord, Tk_Window tkwin, Drawable d, Ttk_Box b, Ttk_State state) { CGRect bounds = BoxToRect(d, b); HIThemeTabPaneDrawInfo info = { .version = 1, .state = Ttk_StateTableLookup(ThemeStateTable, state), .direction = kThemeTabNorth, .size = kHIThemeTabSizeNormal, .kind = kHIThemeTabKindNormal, .adornment = kHIThemeTabPaneAdornmentNormal, }; bounds.origin.y -= kThemeMetricTabFrameOverlap; bounds.size.height += kThemeMetricTabFrameOverlap; BEGIN_DRAWING(d) ChkErr(HIThemeDrawTabPane, &bounds, &info, dc.context, HIOrientation); END_DRAWING } static Ttk_ElementSpec PaneElementSpec = { TK_STYLE_VERSION_2, sizeof(NullElement), TtkNullElementOptions, PaneElementSize, PaneElementDraw }; /* * Labelframe borders: * Use "primary group box ..." * Quoth DrawThemePrimaryGroup reference: * "The primary group box frame is drawn inside the specified * rectangle and is a maximum of 2 pixels thick." * * "Maximum of 2 pixels thick" is apparently a lie; * looks more like 4 to me with shading. */ static void GroupElementSize( void *clientData, void *elementRecord, Tk_Window tkwin, int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) { *paddingPtr = Ttk_UniformPadding(4); }
static void TrackElementDraw( void *clientData, void *elementRecord, Tk_Window tkwin, Drawable d, Ttk_Box b, Ttk_State state) { TrackElementData *data = clientData; TrackElement *elem = elementRecord; double from = 0, to = 100, value = 0; int orientation = TTK_ORIENT_HORIZONTAL; ThemeTrackDrawInfo info; Tcl_GetDoubleFromObj(NULL, elem->fromObj, &from); Tcl_GetDoubleFromObj(NULL, elem->toObj, &to); Tcl_GetDoubleFromObj(NULL, elem->valueObj, &value); Ttk_GetOrientFromObj(NULL, elem->orientObj, &orientation); /* @@@ BUG: min, max, and value should account for resolution: * @@@ if finer than 1.0, conversion to int breaks. */ info.kind = data->kind; info.bounds = BoxToRect(d, b); info.min = (int) from; /* @@@ */ info.max = (int) to; /* @@@ */ info.value = (int) value; /* @@@ */ info.attributes = orientation == TTK_ORIENT_HORIZONTAL ? kThemeTrackHorizontal : 0; info.attributes |= kThemeTrackShowThumb; info.enableState = Ttk_StateTableLookup(ThemeTrackEnableTable, state); switch (data->kind) { case kThemeProgressBar: info.trackInfo.progress.phase = 0; /* 1-4: animation phase */ break; case kThemeSlider: info.trackInfo.slider.pressState = 0; /* @@@ fill this in */ info.trackInfo.slider.thumbDir = kThemeThumbPlain; /* kThemeThumbUpward, kThemeThumbDownward, kThemeThumbPlain */ break; } BEGIN_DRAWING(d) ChkErr(DrawThemeTrack, &info, NULL, NULL, 0); END_DRAWING }
static void ButtonBorderElementDraw( void *clientData, void *elementRecord, Tk_Window tkwin, Drawable d, Ttk_Box b, unsigned int state) { ButtonBorderElement *bd = elementRecord; int relief = TK_RELIEF_FLAT; int defaultState = TTK_BUTTON_DEFAULT_DISABLED; TkWinDCState dcState; HDC hdc; RECT rc; Tk_GetReliefFromObj(NULL, bd->reliefObj, &relief); Ttk_GetButtonDefaultStateFromObj(NULL, bd->defaultStateObj, &defaultState); if (defaultState == TTK_BUTTON_DEFAULT_ACTIVE) { XColor *highlightColor = Tk_GetColorFromObj(tkwin, bd->highlightColorObj); GC gc = Tk_GCForColor(highlightColor, d); XDrawRectangle(Tk_Display(tkwin), d, gc, b.x,b.y,b.width-1,b.height-1); } if (defaultState != TTK_BUTTON_DEFAULT_DISABLED) { ++b.x; ++b.y; b.width -= 2; b.height -= 2; } hdc = TkWinGetDrawableDC(Tk_Display(tkwin), d, &dcState); rc = BoxToRect(b); DrawFrameControl(hdc, &rc, DFC_BUTTON, /* classId */ DFCS_BUTTONPUSH | Ttk_StateTableLookup(pushbutton_statemap, state)); /* Draw focus ring: */ if (state & TTK_STATE_FOCUS) { short int borderWidth = 3; /* @@@ Use GetSystemMetrics?*/ rc = BoxToRect(Ttk_PadBox(b, Ttk_UniformPadding(borderWidth))); DrawFocusRect(hdc, &rc); } TkWinReleaseDrawableDC(d, hdc, &dcState); }
static void EntryElementDraw( void *clientData, void *elementRecord, Tk_Window tkwin, Drawable d, Ttk_Box b, Ttk_State state) { EntryElement *e = elementRecord; Tk_3DBorder backgroundPtr = Tk_Get3DBorderFromObj(tkwin,e->backgroundObj); Ttk_Box inner = Ttk_PadBox(b, Ttk_UniformPadding(3)); Rect bounds = BoxToRect(d, inner); ThemeDrawState drawState = Ttk_StateTableLookup(ThemeStateTable, state); /* * Erase w/background color: */ XFillRectangle(Tk_Display(tkwin), d, Tk_3DBorderGC(tkwin, backgroundPtr, TK_3D_FLAT_GC), inner.x,inner.y, inner.width, inner.height); BEGIN_DRAWING(d) ChkErr(DrawThemeEditTextFrame, &bounds, drawState); if (state & TTK_STATE_FOCUS) { ChkErr(DrawThemeFocusRect, &bounds, 1); } END_DRAWING }
static void IndicatorElementDraw( void *clientData, void *elementRecord, Tk_Window tkwin, Drawable d, Ttk_Box b, unsigned int state) { IndicatorSpec *spec = clientData; IndicatorElement *indicator = elementRecord; Display *display = Tk_Display(tkwin); Ttk_Padding padding; XColor *fgColor, *frameColor, *shadeColor, *indicatorColor, *borderColor; int index, ix, iy; XGCValues gcValues; GC copyGC; unsigned long imgColors[8]; XImage *img; Ttk_GetPaddingFromObj(NULL, tkwin, indicator->marginObj, &padding); b = Ttk_PadBox(b, padding); if ( b.x < 0 || b.y < 0 || Tk_Width(tkwin) < b.x + spec->width || Tk_Height(tkwin) < b.y + spec->height) { /* Oops! not enough room to display the image. * Don't draw anything. */ return; } /* * Fill in imgColors palette: * * (SHOULD: take light and shade colors from the border object, * but Tk doesn't provide easy access to these in the public API.) */ fgColor = Tk_GetColorFromObj(tkwin, indicator->foregroundObj); frameColor = Tk_GetColorFromObj(tkwin, indicator->backgroundObj); shadeColor = Tk_GetColorFromObj(tkwin, indicator->shadeColorObj); indicatorColor = Tk_GetColorFromObj(tkwin, indicator->colorObj); borderColor = Tk_GetColorFromObj(tkwin, indicator->borderColorObj); imgColors[0 /*A*/] = shadeColor->pixel; imgColors[1 /*B*/] = indicatorColor->pixel; imgColors[2 /*C*/] = frameColor->pixel; imgColors[3 /*D*/] = indicatorColor->pixel; imgColors[4 /*E*/] = borderColor->pixel; imgColors[5 /*F*/] = frameColor->pixel; imgColors[6 /*G*/] = fgColor->pixel; imgColors[7 /*H*/] = fgColor->pixel; /* * Create a scratch buffer to store the image: */ img = XGetImage(display,d, 0, 0, (unsigned int)spec->width, (unsigned int)spec->height, AllPlanes, ZPixmap); if (img == NULL) return; /* * Create the image, painting it into an XImage one pixel at a time. */ index = Ttk_StateTableLookup(spec->map, state); for (iy=0 ; iy<spec->height ; iy++) { for (ix=0 ; ix<spec->width ; ix++) { XPutPixel(img, ix, iy, imgColors[spec->pixels[iy][index*spec->width+ix] - 'A'] ); } } /* * Copy onto our target drawable surface. */ memset(&gcValues, 0, sizeof(gcValues)); copyGC = Tk_GetGC(tkwin, 0, &gcValues); TkPutImage(NULL, 0, display, d, copyGC, img, 0, 0, b.x, b.y, spec->width, spec->height); /* * Tidy up. */ Tk_FreeGC(display, copyGC); XDestroyImage(img); }
static void PbarElementDraw( void *clientData, void *elementRecord, Tk_Window tkwin, Drawable d, Ttk_Box b, Ttk_State state) { PbarElement *pbar = elementRecord; int orientation = TTK_ORIENT_HORIZONTAL, phase = 0; double value = 0, maximum = 100, factor; Ttk_GetOrientFromObj(NULL, pbar->orientObj, &orientation); Tcl_GetDoubleFromObj(NULL, pbar->valueObj, &value); Tcl_GetDoubleFromObj(NULL, pbar->maximumObj, &maximum); Tcl_GetIntFromObj(NULL, pbar->phaseObj, &phase); factor = RangeToFactor(maximum); HIThemeTrackDrawInfo info = { .version = 0, .kind = (!strcmp("indeterminate", Tcl_GetString(pbar->modeObj)) && value) ? kThemeIndeterminateBar : kThemeProgressBar, .bounds = BoxToRect(d, b), .min = 0, .max = maximum * factor, .value = value * factor, .attributes = kThemeTrackShowThumb | (orientation == TTK_ORIENT_HORIZONTAL ? kThemeTrackHorizontal : 0), .enableState = Ttk_StateTableLookup(ThemeTrackEnableTable, state), .trackInfo.progress.phase = phase, }; BEGIN_DRAWING(d) ChkErr(HIThemeDrawTrack, &info, NULL, dc.context, HIOrientation); END_DRAWING } static Ttk_ElementSpec PbarElementSpec = { TK_STYLE_VERSION_2, sizeof(PbarElement), PbarElementOptions, PbarElementSize, PbarElementDraw }; /*---------------------------------------------------------------------- * +++ Separator element. * * DrawThemeSeparator() guesses the orientation of the line from * the width and height of the rectangle, so the same element can * can be used for horizontal, vertical, and general separators. */ static void SeparatorElementSize( void *clientData, void *elementRecord, Tk_Window tkwin, int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) { *widthPtr = *heightPtr = 1; } static void SeparatorElementDraw( void *clientData, void *elementRecord, Tk_Window tkwin, Drawable d, Ttk_Box b, unsigned int state) { CGRect bounds = BoxToRect(d, b); const HIThemeSeparatorDrawInfo info = { .version = 0, /* Separator only supports kThemeStateActive, kThemeStateInactive */ .state = Ttk_StateTableLookup(ThemeStateTable, state & TTK_STATE_BACKGROUND), }; BEGIN_DRAWING(d) ChkErr(HIThemeDrawSeparator, &bounds, &info, dc.context, HIOrientation); END_DRAWING } static Ttk_ElementSpec SeparatorElementSpec = { TK_STYLE_VERSION_2, sizeof(NullElement), TtkNullElementOptions, SeparatorElementSize, SeparatorElementDraw }; /*---------------------------------------------------------------------- * +++ Size grip element. */ static const ThemeGrowDirection sizegripGrowDirection = kThemeGrowRight|kThemeGrowDown; static void SizegripElementSize( void *clientData, void *elementRecord, Tk_Window tkwin, int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) { HIThemeGrowBoxDrawInfo info = { .version = 0, .state = kThemeStateActive, .kind = kHIThemeGrowBoxKindNormal, .direction = sizegripGrowDirection, .size = kHIThemeGrowBoxSizeNormal, }; CGRect bounds = CGRectZero; ChkErr(HIThemeGetGrowBoxBounds, &bounds.origin, &info, &bounds); *widthPtr = bounds.size.width; *heightPtr = bounds.size.height; } static void SizegripElementDraw( void *clientData, void *elementRecord, Tk_Window tkwin, Drawable d, Ttk_Box b, unsigned int state) { CGRect bounds = BoxToRect(d, b); HIThemeGrowBoxDrawInfo info = { .version = 0, /* Grow box only supports kThemeStateActive, kThemeStateInactive */ .state = Ttk_StateTableLookup(ThemeStateTable, state & TTK_STATE_BACKGROUND), .kind = kHIThemeGrowBoxKindNormal, .direction = sizegripGrowDirection, .size = kHIThemeGrowBoxSizeNormal, }; BEGIN_DRAWING(d) ChkErr(HIThemeDrawGrowBox, &bounds.origin, &info, dc.context, HIOrientation); END_DRAWING } static Ttk_ElementSpec SizegripElementSpec = { TK_STYLE_VERSION_2, sizeof(NullElement), TtkNullElementOptions, SizegripElementSize, SizegripElementDraw }; /*---------------------------------------------------------------------- * +++ Background and fill elements. * * This isn't quite right: In Aqua, the correct background for * a control depends on what kind of container it belongs to, * and the type of the top-level window. * * Also: patterned backgrounds should be aligned with the coordinate * system of the top-level window. If we're drawing into an * off-screen graphics port this leads to alignment glitches. */ static void FillElementDraw( void *clientData, void *elementRecord, Tk_Window tkwin, Drawable d, Ttk_Box b, Ttk_State state) { CGRect bounds = BoxToRect(d, b); ThemeBrush brush = (state & TTK_STATE_BACKGROUND) ? kThemeBrushModelessDialogBackgroundInactive : kThemeBrushModelessDialogBackgroundActive; BEGIN_DRAWING(d) ChkErr(HIThemeSetFill, brush, NULL, dc.context, HIOrientation); //QDSetPatternOrigin(PatternOrigin(tkwin, d)); CGContextFillRect(dc.context, bounds); END_DRAWING }
static void TrackElementDraw( void *clientData, void *elementRecord, Tk_Window tkwin, Drawable d, Ttk_Box b, Ttk_State state) { TrackElementData *data = clientData; TrackElement *elem = elementRecord; int orientation = TTK_ORIENT_HORIZONTAL; double from = 0, to = 100, value = 0, factor; Ttk_GetOrientFromObj(NULL, elem->orientObj, &orientation); Tcl_GetDoubleFromObj(NULL, elem->fromObj, &from); Tcl_GetDoubleFromObj(NULL, elem->toObj, &to); Tcl_GetDoubleFromObj(NULL, elem->valueObj, &value); factor = RangeToFactor(to - from); HIThemeTrackDrawInfo info = { .version = 0, .kind = data->kind, .bounds = BoxToRect(d, b), .min = from * factor, .max = to * factor, .value = value * factor, .attributes = kThemeTrackShowThumb | (orientation == TTK_ORIENT_HORIZONTAL ? kThemeTrackHorizontal : 0), .enableState = Ttk_StateTableLookup(ThemeTrackEnableTable, state), .trackInfo.progress.phase = 0, }; if (info.kind == kThemeSlider) { info.trackInfo.slider.pressState = state & TTK_STATE_PRESSED ? kThemeThumbPressed : 0; info.trackInfo.slider.thumbDir = kThemeThumbPlain; } BEGIN_DRAWING(d) ChkErr(HIThemeDrawTrack, &info, NULL, dc.context, HIOrientation); END_DRAWING } static Ttk_ElementSpec TrackElementSpec = { TK_STYLE_VERSION_2, sizeof(TrackElement), TrackElementOptions, TrackElementSize, TrackElementDraw }; /* * Slider element -- <<NOTE-TRACKS>> * Has geometry only. The Scale widget adjusts the position of this element, * and uses it for hit detection. In the Aqua theme, the slider is actually * drawn as part of the trough element. * * Also buggy: The geometry here is a Wild-Assed-Guess; I can't * figure out how to get the Appearance Manager to tell me the * slider size. */ static void SliderElementSize( void *clientData, void *elementRecord, Tk_Window tkwin, int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) { *widthPtr = *heightPtr = 24; } static Ttk_ElementSpec SliderElementSpec = { TK_STYLE_VERSION_2, sizeof(NullElement), TtkNullElementOptions, SliderElementSize, TtkNullElementDraw }; /*---------------------------------------------------------------------- * +++ Progress bar element (new): * * @@@ NOTE: According to an older revision of the Aqua reference docs, * @@@ the 'phase' field is between 0 and 4. Newer revisions say * @@@ that it can be any UInt8 value. */ typedef struct { Tcl_Obj *orientObj; /* horizontal / vertical */ Tcl_Obj *valueObj; /* current value */ Tcl_Obj *maximumObj; /* maximum value */ Tcl_Obj *phaseObj; /* animation phase */ Tcl_Obj *modeObj; /* progress bar mode */ } PbarElement; static Ttk_ElementOptionSpec PbarElementOptions[] = { { "-orient", TK_OPTION_STRING, Tk_Offset(PbarElement,orientObj), "horizontal" }, { "-value", TK_OPTION_DOUBLE, Tk_Offset(PbarElement,valueObj), "0" }, { "-maximum", TK_OPTION_DOUBLE, Tk_Offset(PbarElement,maximumObj), "100" }, { "-phase", TK_OPTION_INT, Tk_Offset(PbarElement,phaseObj), "0" }, { "-mode", TK_OPTION_STRING, Tk_Offset(PbarElement,modeObj), "determinate" }, {0,0,0,0} }; static void PbarElementSize( void *clientData, void *elementRecord, Tk_Window tkwin, int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) { SInt32 size = 24; /* @@@ Check HIG for correct default */ ChkErr(GetThemeMetric, kThemeMetricLargeProgressBarThickness, &size); *widthPtr = *heightPtr = size; }
static void SpinButtonElementDraw( void *clientData, void *elementRecord, Tk_Window tkwin, Drawable d, Ttk_Box b, Ttk_State state) { CGRect bounds = BoxToRect(d, Ttk_PadBox(b, SpinbuttonMargins)); /* @@@ can't currently distinguish PressedUp (== Pressed) from PressedDown; * ignore this bit for now [see #2219588] */ const HIThemeButtonDrawInfo info = { .version = 0, .state = Ttk_StateTableLookup(ThemeStateTable, state & ~TTK_STATE_PRESSED), .kind = kThemeIncDecButton, .value = Ttk_StateTableLookup(ButtonValueTable, state), .adornment = kThemeAdornmentNone, }; BEGIN_DRAWING(d) ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, NULL); END_DRAWING } static Ttk_ElementSpec SpinButtonElementSpec = { TK_STYLE_VERSION_2, sizeof(NullElement), TtkNullElementOptions, SpinButtonElementSize, SpinButtonElementDraw }; /*---------------------------------------------------------------------- * +++ DrawThemeTrack-based elements -- * Progress bars and scales. (See also: <<NOTE-TRACKS>>) */ static Ttk_StateTable ThemeTrackEnableTable[] = { { kThemeTrackDisabled, TTK_STATE_DISABLED, 0 }, { kThemeTrackInactive, TTK_STATE_BACKGROUND, 0 }, { kThemeTrackActive, 0, 0 } /* { kThemeTrackNothingToScroll, ?, ? }, */ }; typedef struct { /* TrackElement client data */ ThemeTrackKind kind; SInt32 thicknessMetric; } TrackElementData; static TrackElementData ScaleData = { kThemeSlider, kThemeMetricHSliderHeight }; typedef struct { Tcl_Obj *fromObj; /* minimum value */ Tcl_Obj *toObj; /* maximum value */ Tcl_Obj *valueObj; /* current value */ Tcl_Obj *orientObj; /* horizontal / vertical */ } TrackElement; static Ttk_ElementOptionSpec TrackElementOptions[] = { { "-from", TK_OPTION_DOUBLE, Tk_Offset(TrackElement,fromObj) }, { "-to", TK_OPTION_DOUBLE, Tk_Offset(TrackElement,toObj) }, { "-value", TK_OPTION_DOUBLE, Tk_Offset(TrackElement,valueObj) }, { "-orient", TK_OPTION_STRING, Tk_Offset(TrackElement,orientObj) }, {0,0,0} }; static void TrackElementSize( void *clientData, void *elementRecord, Tk_Window tkwin, int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) { TrackElementData *data = clientData; SInt32 size = 24; /* reasonable default ... */ ChkErr(GetThemeMetric, data->thicknessMetric, &size); *widthPtr = *heightPtr = size; }