diff options
author | hobbs <hobbs> | 2006-10-31 01:42:25 (GMT) |
---|---|---|
committer | hobbs <hobbs> | 2006-10-31 01:42:25 (GMT) |
commit | 397a2c9832bf618f26be267501cf49ab06a562ec (patch) | |
tree | 61d5e957eccfcba57b0dd27ebc73db085385834e /win/ttkWinTheme.c | |
parent | 18d330543869e240c2bd12fc9fbb8d5027f5cad6 (diff) | |
download | tk-397a2c9832bf618f26be267501cf49ab06a562ec.zip tk-397a2c9832bf618f26be267501cf49ab06a562ec.tar.gz tk-397a2c9832bf618f26be267501cf49ab06a562ec.tar.bz2 |
* doc/ttk_Geometry.3, doc/ttk_Theme.3, doc/ttk_button.n:
* doc/ttk_checkbutton.n, doc/ttk_combobox.n, doc/ttk_dialog.n:
* doc/ttk_entry.n, doc/ttk_frame.n, doc/ttk_image.n:
* doc/ttk_intro.n, doc/ttk_label.n, doc/ttk_labelframe.n:
* doc/ttk_menubutton.n, doc/ttk_notebook.n, doc/ttk_panedwindow.n:
* doc/ttk_progressbar.n, doc/ttk_radiobutton.n, doc/ttk_scrollbar.n:
* doc/ttk_separator.n, doc/ttk_sizegrip.n, doc/ttk_style.n:
* doc/ttk_treeview.n, doc/ttk_widget.n,:
* generic/ttk/ttk.decls, generic/ttk/ttkBlink.c:
* generic/ttk/ttkButton.c, generic/ttk/ttkCache.c:
* generic/ttk/ttkClamTheme.c, generic/ttk/ttkClassicTheme.c:
* generic/ttk/ttkDecls.h, generic/ttk/ttkDefaultTheme.c:
* generic/ttk/ttkElements.c, generic/ttk/ttkEntry.c:
* generic/ttk/ttkFrame.c, generic/ttk/ttkImage.c:
* generic/ttk/ttkInit.c, generic/ttk/ttkLabel.c:
* generic/ttk/ttkLayout.c, generic/ttk/ttkManager.c:
* generic/ttk/ttkManager.h, generic/ttk/ttkNotebook.c:
* generic/ttk/ttkPanedwindow.c, generic/ttk/ttkProgress.c:
* generic/ttk/ttkScale.c, generic/ttk/ttkScroll.c:
* generic/ttk/ttkScrollbar.c, generic/ttk/ttkSeparator.c:
* generic/ttk/ttkSquare.c, generic/ttk/ttkState.c:
* generic/ttk/ttkStubInit.c, generic/ttk/ttkStubLib.c:
* generic/ttk/ttkTagSet.c, generic/ttk/ttkTheme.c:
* generic/ttk/ttkTheme.h, generic/ttk/ttkThemeInt.h:
* generic/ttk/ttkTrace.c, generic/ttk/ttkTrack.c:
* generic/ttk/ttkTreeview.c, generic/ttk/ttkWidget.c:
* generic/ttk/ttkWidget.h:
* library/demos/ttk_demo.tcl, library/demos/ttk_iconlib.tcl:
* library/demos/ttk_repeater.tcl:
* library/ttk/altTheme.tcl, library/ttk/aquaTheme.tcl:
* library/ttk/button.tcl, library/ttk/clamTheme.tcl:
* library/ttk/classicTheme.tcl, library/ttk/combobox.tcl:
* library/ttk/cursors.tcl, library/ttk/defaults.tcl:
* library/ttk/dialog.tcl, library/ttk/entry.tcl:
* library/ttk/fonts.tcl, library/ttk/icons.tcl:
* library/ttk/keynav.tcl, library/ttk/menubutton.tcl:
* library/ttk/notebook.tcl, library/ttk/panedwindow.tcl:
* library/ttk/progress.tcl, library/ttk/scale.tcl:
* library/ttk/scrollbar.tcl, library/ttk/sizegrip.tcl:
* library/ttk/treeview.tcl, library/ttk/ttk.tcl:
* library/ttk/utils.tcl, library/ttk/winTheme.tcl:
* library/ttk/xpTheme.tcl:
* macosx/ttkMacOSXTheme.c:
* tests/ttk/all.tcl, tests/ttk/bwidget.test, tests/ttk/combobox.test:
* tests/ttk/entry.test, tests/ttk/image.test:
* tests/ttk/labelframe.test, tests/ttk/layout.test:
* tests/ttk/misc.test, tests/ttk/notebook.test:
* tests/ttk/panedwindow.test, tests/ttk/progressbar.test:
* tests/ttk/scrollbar.test, tests/ttk/treetags.test:
* tests/ttk/treeview.test, tests/ttk/ttk.test, tests/ttk/validate.test:
* win/ttkWinMonitor.c, win/ttkWinTheme.c, win/ttkWinXPTheme.c:
First import of Ttk themed Tk widgets as branched from tile 0.7.8
* generic/tkInt.h, generic/tkWindow.c: add Ttk_Init call, copy
tk classic widgets to ::tk namespace.
* library/tk.tcl: add source of ttk/ttk.tcl, define $::ttk::library.
* unix/Makefile.in, win/Makefile.in: add Ttk build bits
* win/configure, win/configure.in: check for uxtheme.h (XP theme).
Diffstat (limited to 'win/ttkWinTheme.c')
-rw-r--r-- | win/ttkWinTheme.c | 730 |
1 files changed, 730 insertions, 0 deletions
diff --git a/win/ttkWinTheme.c b/win/ttkWinTheme.c new file mode 100644 index 0000000..eb3a9eb --- /dev/null +++ b/win/ttkWinTheme.c @@ -0,0 +1,730 @@ +/* winTheme.c - Copyright (C) 2004 Pat Thoyts <patthoyts@users.sf.net> + * + * $Id: ttkWinTheme.c,v 1.1 2006/10/31 01:42:28 hobbs Exp $ + */ + +#ifdef _MSC_VER +#define WIN32_LEAN_AND_MEAN +#endif + +#include <windows.h> + +#include <tk.h> +#include <tkWinInt.h> + +#ifndef DFCS_HOT /* Windows 98/Me, Windows 200/XP only */ +#define DFCS_HOT 0 +#endif + +#include "ttk/ttkTheme.h" + +/* + * BoxToRect -- + * Helper routine. Converts a Ttk_Box to a Win32 RECT. + */ +static RECT BoxToRect(Ttk_Box b) +{ + RECT rc; + rc.top = b.y; + rc.left = b.x; + rc.bottom = b.y + b.height; + rc.right = b.x + b.width; + return rc; +} + +/* + * ReliefToEdge -- + * Convert a Tk "relief" value into an Windows "edge" value. + * NB: Caller must check for RELIEF_FLAT and RELIEF_SOLID, + * which must be handled specially. + * + * Passing the BF_FLAT flag to DrawEdge() yields something similar + * to TK_RELIEF_SOLID. TK_RELIEF_FLAT can be implemented by not + * drawing anything. + */ +static unsigned int ReliefToEdge(int relief) +{ + switch (relief) { + case TK_RELIEF_RAISED: return EDGE_RAISED; + case TK_RELIEF_SUNKEN: return EDGE_SUNKEN; + case TK_RELIEF_RIDGE: return EDGE_BUMP; + case TK_RELIEF_GROOVE: return EDGE_ETCHED; + case TK_RELIEF_SOLID: return BDR_RAISEDOUTER; + default: + case TK_RELIEF_FLAT: return BDR_RAISEDOUTER; + } +} + +/* ---------------------------------------------------------------------- */ + +static Ttk_StateTable checkbutton_statemap[] = +{ + { DFCS_CHECKED|DFCS_INACTIVE, TTK_STATE_SELECTED|TTK_STATE_DISABLED, 0 }, + { DFCS_CHECKED|DFCS_PUSHED, TTK_STATE_SELECTED|TTK_STATE_PRESSED, 0 }, + { DFCS_CHECKED, TTK_STATE_SELECTED, 0 }, + { DFCS_INACTIVE, TTK_STATE_DISABLED, TTK_STATE_SELECTED }, + { DFCS_PUSHED, TTK_STATE_PRESSED, TTK_STATE_SELECTED}, + { 0, 0, 0 } +}; + +static Ttk_StateTable pushbutton_statemap[] = +{ + { DFCS_INACTIVE, TTK_STATE_DISABLED, 0 }, + { DFCS_PUSHED, TTK_STATE_PRESSED, 0 }, + { DFCS_HOT, TTK_STATE_ACTIVE, 0 }, + { 0, 0, 0 } +}; + +static Ttk_StateTable arrow_statemap[] = +{ + { DFCS_INACTIVE, TTK_STATE_DISABLED, 0 }, + { DFCS_PUSHED | DFCS_FLAT, TTK_STATE_PRESSED, 0 }, + { 0, 0, 0 } +}; + +/*------------------------------------------------------------------------ + * +++ FrameControlElement -- + * General-purpose element for things drawn with DrawFrameControl + */ +typedef struct +{ + const char *name; /* element name */ + int classId; /* class id for DrawFrameControl */ + int partId; /* part id for DrawFrameControl */ + int cxId; /* system metric id for size in x */ + int cyId; /* system metric id for size in y */ + Ttk_StateTable *stateMap; /* map Tk states to Win32 flags */ + Ttk_Padding padding; /* additional placement padding */ +} FrameControlElementData; + +static FrameControlElementData FrameControlElements[] = +{ + { "Checkbutton.indicator", + DFC_BUTTON, DFCS_BUTTONCHECK, SM_CYMENUCHECK, SM_CYMENUCHECK, + checkbutton_statemap, {0,0,4,0} }, + { "Radiobutton.indicator", + DFC_BUTTON, DFCS_BUTTONRADIO, SM_CYMENUCHECK, SM_CYMENUCHECK, + checkbutton_statemap, {0,0,4,0} }, + { "uparrow", + DFC_SCROLL, DFCS_SCROLLUP, SM_CXVSCROLL, SM_CYVSCROLL, + arrow_statemap, {0,0,0,0} }, + { "downarrow", + DFC_SCROLL, DFCS_SCROLLDOWN, SM_CXVSCROLL, SM_CYVSCROLL, + arrow_statemap, {0,0,0,0} }, + { "leftarrow", + DFC_SCROLL, DFCS_SCROLLLEFT, SM_CXHSCROLL, SM_CYHSCROLL, + arrow_statemap, {0,0,0,0} }, + { "rightarrow", + DFC_SCROLL, DFCS_SCROLLRIGHT, SM_CXHSCROLL, SM_CYHSCROLL, + arrow_statemap, {0,0,0,0} }, + { "sizegrip", + DFC_SCROLL, DFCS_SCROLLSIZEGRIP, SM_CXVSCROLL, SM_CYHSCROLL, + arrow_statemap, {0,0,0,0} }, + + { 0,0,0,0,0,0, {0,0,0,0} } +}; + +/* ---------------------------------------------------------------------- */ + +static void FrameControlElementGeometry( + void *clientData, void *elementRecord, Tk_Window tkwin, + int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) +{ + FrameControlElementData *elementData = clientData; + *widthPtr = GetSystemMetrics(elementData->cxId); + *heightPtr = GetSystemMetrics(elementData->cyId); + *paddingPtr = elementData->padding; +} + +static void FrameControlElementDraw( + void *clientData, void *elementRecord, Tk_Window tkwin, + Drawable d, Ttk_Box b, unsigned int state) +{ + FrameControlElementData *elementData = clientData; + RECT rc = BoxToRect(b); + 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 Ttk_ElementSpec FrameControlElementSpec = +{ + TK_STYLE_VERSION_2, + sizeof(NullElement), + NullElementOptions, + FrameControlElementGeometry, + FrameControlElementDraw +}; + +/*---------------------------------------------------------------------- + * +++ Border element implementation. + */ + +typedef struct { + Tcl_Obj *reliefObj; +} BorderElement; + +static Ttk_ElementOptionSpec BorderElementOptions[] = { + { "-relief",TK_OPTION_RELIEF,Tk_Offset(BorderElement,reliefObj), "flat" }, + {NULL} +}; + +static void BorderElementGeometry( + void *clientData, void *elementRecord, Tk_Window tkwin, + int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) +{ + paddingPtr->left = paddingPtr->right = GetSystemMetrics(SM_CXEDGE); + paddingPtr->top = paddingPtr->bottom = GetSystemMetrics(SM_CYEDGE); +} + +static void BorderElementDraw( + void *clientData, void *elementRecord, Tk_Window tkwin, + Drawable d, Ttk_Box b, unsigned int state) +{ + BorderElement *border = elementRecord; + RECT rc = BoxToRect(b); + int relief = TK_RELIEF_FLAT; + TkWinDCState dcState; + HDC hdc; + + Tk_GetReliefFromObj(NULL, border->reliefObj, &relief); + + if (relief != TK_RELIEF_FLAT) { + UINT xFlags = (relief == TK_RELIEF_SOLID) ? BF_FLAT : 0; + hdc = TkWinGetDrawableDC(Tk_Display(tkwin), d, &dcState); + DrawEdge(hdc, &rc, ReliefToEdge(relief), BF_RECT | xFlags); + TkWinReleaseDrawableDC(d, hdc, &dcState); + } +} + +static Ttk_ElementSpec BorderElementSpec = +{ + TK_STYLE_VERSION_2, + sizeof(BorderElement), + BorderElementOptions, + BorderElementGeometry, + BorderElementDraw +}; + +/* + * Entry field borders: + * Sunken border; also fill with window color. + */ + +typedef struct +{ + Tcl_Obj *backgroundObj; +} FieldElement; + +static Ttk_ElementOptionSpec FieldElementOptions[] = +{ + { "-fieldbackground", TK_OPTION_BORDER, + Tk_Offset(FieldElement,backgroundObj), "white" }, + {NULL} +}; + +static void +FieldElementGeometry( + void *clientData, void *elementRecord, Tk_Window tkwin, + int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) +{ + paddingPtr->left = paddingPtr->right = GetSystemMetrics(SM_CXEDGE); + paddingPtr->top = paddingPtr->bottom = GetSystemMetrics(SM_CYEDGE); +} + +static void +FieldElementDraw( + void *clientData, void *elementRecord, Tk_Window tkwin, + Drawable d, Ttk_Box b, unsigned int state) +{ + FieldElement *field = elementRecord; + Tk_3DBorder bg = Tk_Get3DBorderFromObj(tkwin, field->backgroundObj); + RECT rc = BoxToRect(b); + TkWinDCState dcState; + HDC hdc; + + Tk_Fill3DRectangle( + tkwin, d, bg, b.x, b.y, b.width, b.height, 0, TK_RELIEF_FLAT); + + hdc = TkWinGetDrawableDC(Tk_Display(tkwin), d, &dcState); + DrawEdge(hdc, &rc, EDGE_SUNKEN, BF_RECT); + TkWinReleaseDrawableDC(d, hdc, &dcState); +} + +static Ttk_ElementSpec FieldElementSpec = +{ + TK_STYLE_VERSION_2, + sizeof(FieldElement), + FieldElementOptions, + FieldElementGeometry, + FieldElementDraw +}; + +/*------------------------------------------------------------------------ + * +++ Button borders. + * Drawn with DrawFrameControl instead of DrawEdge; + * Also draw default indicator and focus ring. + */ +typedef struct { + Tcl_Obj *reliefObj; + Tcl_Obj *highlightColorObj; + Tcl_Obj *defaultStateObj; +} ButtonBorderElement; + +static Ttk_ElementOptionSpec ButtonBorderElementOptions[] = { + { "-relief",TK_OPTION_RELIEF, + Tk_Offset(ButtonBorderElement,reliefObj), "flat" }, + { "-highlightcolor",TK_OPTION_COLOR, + Tk_Offset(ButtonBorderElement,highlightColorObj), "black" }, + { "-default", TK_OPTION_ANY, + Tk_Offset(ButtonBorderElement,defaultStateObj), "disabled" }, + {NULL} +}; + +static void ButtonBorderElementGeometry( + void *clientData, void *elementRecord, Tk_Window tkwin, + int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) +{ + ButtonBorderElement *bd = elementRecord; + int relief = TK_RELIEF_RAISED; + int defaultState = TTK_BUTTON_DEFAULT_DISABLED; + short int cx, cy; + + Tk_GetReliefFromObj(NULL, bd->reliefObj, &relief); + Ttk_GetButtonDefaultStateFromObj(NULL, bd->defaultStateObj, &defaultState); + cx = GetSystemMetrics(SM_CXEDGE); + cy = GetSystemMetrics(SM_CYEDGE); + + /* Space for default indicator: + */ + if (defaultState != TTK_BUTTON_DEFAULT_DISABLED) { + ++cx; ++cy; + } + + /* Space for focus ring: + */ + cx += 2; + cy += 2; + + *paddingPtr = Ttk_MakePadding(cx,cy,cx,cy); +} + +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 Ttk_ElementSpec ButtonBorderElementSpec = +{ + TK_STYLE_VERSION_2, + sizeof(ButtonBorderElement), + ButtonBorderElementOptions, + ButtonBorderElementGeometry, + ButtonBorderElementDraw +}; + +/*------------------------------------------------------------------------ + * +++ Focus element. + * Draw dashed focus rectangle. + */ + +static void FocusElementGeometry( + void *clientData, void *elementRecord, Tk_Window tkwin, + int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) +{ + *paddingPtr = Ttk_UniformPadding(1); +} + +static void FocusElementDraw( + void *clientData, void *elementRecord, Tk_Window tkwin, + Drawable d, Ttk_Box b, unsigned int state) +{ + if (state & TTK_STATE_FOCUS) { + RECT rc = BoxToRect(b); + TkWinDCState dcState; + HDC hdc = TkWinGetDrawableDC(Tk_Display(tkwin), d, &dcState); + DrawFocusRect(hdc, &rc); + TkWinReleaseDrawableDC(d, hdc, &dcState); + } +} + +static Ttk_ElementSpec FocusElementSpec = +{ + TK_STYLE_VERSION_2, + sizeof(NullElement), + NullElementOptions, + FocusElementGeometry, + FocusElementDraw +}; + +/* FillFocusElement -- + * Draws a focus ring filled with the selection color + */ + +typedef struct { + Tcl_Obj *fillColorObj; +} FillFocusElement; + +static Ttk_ElementOptionSpec FillFocusElementOptions[] = { + { "-focusfill", TK_OPTION_COLOR, + Tk_Offset(FillFocusElement,fillColorObj), "white" }, + { NULL } +}; + + /* @@@ FIX THIS */ +static void FillFocusElementDraw( + void *clientData, void *elementRecord, Tk_Window tkwin, + Drawable d, Ttk_Box b, unsigned int state) +{ + FillFocusElement *focus = elementRecord; + if (state & TTK_STATE_FOCUS) { + RECT rc = BoxToRect(b); + TkWinDCState dcState; + XColor *fillColor = Tk_GetColorFromObj(tkwin, focus->fillColorObj); + GC gc = Tk_GCForColor(fillColor, d); + HDC hdc; + + XFillRectangle(Tk_Display(tkwin),d,gc, b.x,b.y,b.width,b.height); + hdc = TkWinGetDrawableDC(Tk_Display(tkwin), d, &dcState); + DrawFocusRect(hdc, &rc); + TkWinReleaseDrawableDC(d, hdc, &dcState); + } +} + +/* + * ComboboxFocusElement -- + * Read-only comboboxes have a filled focus ring, editable ones do not. + */ +static void ComboboxFocusElementDraw( + void *clientData, void *elementRecord, Tk_Window tkwin, + Drawable d, Ttk_Box b, unsigned int state) +{ + if (state & TTK_STATE_READONLY) { + FillFocusElementDraw(clientData, elementRecord, tkwin, d, b, state); + } +} + +static Ttk_ElementSpec ComboboxFocusElementSpec = +{ + TK_STYLE_VERSION_2, + sizeof(FillFocusElement), + FillFocusElementOptions, + FocusElementGeometry, + ComboboxFocusElementDraw +}; + +/*---------------------------------------------------------------------- + * +++ Scrollbar trough element. + * + * The native windows scrollbar is drawn using a pattern brush giving a + * stippled appearance when the trough might otherwise be invisible. + * We can deal with this here. + */ + +typedef struct { /* clientData for Trough element */ + HBRUSH PatternBrush; + HBITMAP PatternBitmap; +} TroughClientData; + +static const WORD Pattern[] = { + 0x5555, 0xaaaa, 0x5555, 0xaaaa, 0x5555, 0xaaaa, 0x5555, 0xaaaa +}; + +static void TroughClientDataDeleteProc(void *clientData) +{ + TroughClientData *cd = clientData; + DeleteObject(cd->PatternBrush); + DeleteObject(cd->PatternBitmap); + ckfree(clientData); +} + +static TroughClientData *TroughClientDataInit(Tcl_Interp *interp) +{ + TroughClientData *cd = (TroughClientData*)ckalloc(sizeof(*cd)); + cd->PatternBitmap = CreateBitmap(8, 8, 1, 1, Pattern); + cd->PatternBrush = CreatePatternBrush(cd->PatternBitmap); + Ttk_RegisterCleanup(interp, cd, TroughClientDataDeleteProc); + return cd; +} + +static void TroughElementDraw( + void *clientData, void *elementRecord, Tk_Window tkwin, + Drawable d, Ttk_Box b, unsigned int state) +{ + TroughClientData *cd = clientData; + TkWinDCState dcState; + HDC hdc = TkWinGetDrawableDC(Tk_Display(tkwin), d, &dcState); + HBRUSH hbr; + COLORREF bk, oldbk, oldtxt; + + hbr = SelectObject(hdc, GetSysColorBrush(COLOR_SCROLLBAR)); + bk = GetSysColor(COLOR_3DHIGHLIGHT); + oldtxt = SetTextColor(hdc, GetSysColor(COLOR_3DFACE)); + oldbk = SetBkColor(hdc, bk); + + /* WAS: if (bk (COLOR_3DHIGHLIGHT) == GetSysColor(COLOR_WINDOW)) ... */ + if (GetSysColor(COLOR_SCROLLBAR) == GetSysColor(COLOR_BTNFACE)) { + /* Draw using the pattern brush */ + SelectObject(hdc, cd->PatternBrush); + } + + PatBlt(hdc, b.x, b.y, b.width, b.height, PATCOPY); + SetBkColor(hdc, oldbk); + SetTextColor(hdc, oldtxt); + SelectObject(hdc, hbr); + TkWinReleaseDrawableDC(d, hdc, &dcState); +} + +static Ttk_ElementSpec TroughElementSpec = +{ + TK_STYLE_VERSION_2, + sizeof(NullElement), + NullElementOptions, + NullElementGeometry, + TroughElementDraw +}; + +/*------------------------------------------------------------------------ + * +++ Thumb element. + */ + +typedef struct +{ + Tcl_Obj *orientObj; +} ThumbElement; + +static Ttk_ElementOptionSpec ThumbElementOptions[] = +{ + { "-orient", TK_OPTION_ANY,Tk_Offset(ThumbElement,orientObj),"horizontal"}, + { NULL } +}; + +static void ThumbElementGeometry( + void *clientData, void *elementRecord, Tk_Window tkwin, + int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) +{ + ThumbElement *thumbPtr = elementRecord; + int orient; + + Ttk_GetOrientFromObj(NULL, thumbPtr->orientObj, &orient); + if (orient == TTK_ORIENT_HORIZONTAL) { + *widthPtr = GetSystemMetrics(SM_CXHTHUMB); + *heightPtr = GetSystemMetrics(SM_CYHSCROLL); + } else { + *widthPtr = GetSystemMetrics(SM_CXVSCROLL); + *heightPtr = GetSystemMetrics(SM_CYVTHUMB); + } +} + +static void ThumbElementDraw( + void *clientData, void *elementRecord, Tk_Window tkwin, + Drawable d, Ttk_Box b, unsigned int state) +{ + RECT rc = BoxToRect(b); + TkWinDCState dcState; + HDC hdc; + + /* Windows doesn't show a thumb when the scrollbar is disabled */ + if (state & TTK_STATE_DISABLED) + return; + + hdc = TkWinGetDrawableDC(Tk_Display(tkwin), d, &dcState); + DrawEdge(hdc, &rc, EDGE_RAISED, BF_RECT | BF_MIDDLE); + TkWinReleaseDrawableDC(d, hdc, &dcState); +} + +static Ttk_ElementSpec ThumbElementSpec = +{ + TK_STYLE_VERSION_2, + sizeof(ThumbElement), + ThumbElementOptions, + ThumbElementGeometry, + ThumbElementDraw +}; + +/* ---------------------------------------------------------------------- + * The slider element is the shaped thumb used in the slider widget. + * Windows likes to call this a trackbar. + */ + +typedef struct +{ + Tcl_Obj *orientObj; /* orientation of the slider widget */ +} SliderElement; + +static Ttk_ElementOptionSpec SliderElementOptions[] = +{ + { "-orient", TK_OPTION_ANY, Tk_Offset(SliderElement,orientObj), + "horizontal" }, + { NULL } +}; + +static void SliderElementGeometry( + void *clientData, void *elementRecord, Tk_Window tkwin, + int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) +{ + SliderElement *slider = elementRecord; + int orient; + + Ttk_GetOrientFromObj(NULL, slider->orientObj, &orient); + if (orient == TTK_ORIENT_HORIZONTAL) { + *widthPtr = (GetSystemMetrics(SM_CXHTHUMB) / 2) | 1; + *heightPtr = GetSystemMetrics(SM_CYHSCROLL); + } else { + *widthPtr = GetSystemMetrics(SM_CXVSCROLL); + *heightPtr = (GetSystemMetrics(SM_CYVTHUMB) / 2) | 1; + } +} + +static void SliderElementDraw( + void *clientData, void *elementRecord, Tk_Window tkwin, + Drawable d, Ttk_Box b, unsigned int state) +{ + RECT rc = BoxToRect(b); + TkWinDCState dcState; + HDC hdc; + + hdc = TkWinGetDrawableDC(Tk_Display(tkwin), d, &dcState); + DrawEdge(hdc, &rc, EDGE_RAISED, BF_RECT | BF_MIDDLE); + TkWinReleaseDrawableDC(d, hdc, &dcState); +} + +static Ttk_ElementSpec SliderElementSpec = +{ + TK_STYLE_VERSION_2, + sizeof(SliderElement), + SliderElementOptions, + SliderElementGeometry, + SliderElementDraw +}; + +/*------------------------------------------------------------------------ + * +++ Notebook elements. + */ + +static void ClientElementGeometry( + void *clientData, void *elementRecord, Tk_Window tkwin, + int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) +{ + paddingPtr->left = paddingPtr->right = GetSystemMetrics(SM_CXEDGE); + paddingPtr->top = paddingPtr->bottom = GetSystemMetrics(SM_CYEDGE); +} + +static void ClientElementDraw( + void *clientData, void *elementRecord, Tk_Window tkwin, + Drawable d, Ttk_Box b, unsigned int state) +{ + RECT rc = BoxToRect(b); + TkWinDCState dcState; + HDC hdc = TkWinGetDrawableDC(Tk_Display(tkwin), d, &dcState); + DrawEdge(hdc, &rc, EDGE_RAISED, BF_RECT | BF_SOFT); + TkWinReleaseDrawableDC(d, hdc, &dcState); +} + +static Ttk_ElementSpec ClientElementSpec = +{ + TK_STYLE_VERSION_2, + sizeof(NullElement), + NullElementOptions, + ClientElementGeometry, + ClientElementDraw +}; + +/*------------------------------------------------------------------------ + * +++ Layouts. + */ + +TTK_BEGIN_LAYOUT(ButtonLayout) + TTK_GROUP("Button.border", TTK_FILL_BOTH, + TTK_GROUP("Button.padding", TTK_FILL_BOTH, + TTK_NODE("Button.label", TTK_FILL_BOTH))) +TTK_END_LAYOUT + +TTK_BEGIN_LAYOUT(ComboboxLayout) + TTK_GROUP("Combobox.field", TTK_FILL_BOTH, + TTK_NODE("Combobox.downarrow", TTK_PACK_RIGHT|TTK_FILL_Y) + TTK_GROUP("Combobox.padding", TTK_PACK_LEFT|TTK_EXPAND|TTK_FILL_BOTH, + TTK_GROUP("Combobox.focus", TTK_PACK_LEFT|TTK_EXPAND|TTK_FILL_BOTH, + TTK_NODE("Combobox.textarea", TTK_FILL_BOTH)))) +TTK_END_LAYOUT + + +/* ---------------------------------------------------------------------- */ + +int WinTheme_Init(Tcl_Interp *interp, HWND hwnd) +{ + Ttk_Theme themePtr, parentPtr; + FrameControlElementData *fce = FrameControlElements; + + parentPtr = Ttk_GetTheme(interp, "alt"); + themePtr = Ttk_CreateTheme(interp, "winnative", parentPtr); + if (!themePtr) { + return TCL_ERROR; + } + + Ttk_RegisterElementSpec(themePtr, "border", &BorderElementSpec, NULL); + Ttk_RegisterElementSpec(themePtr, "Button.border", + &ButtonBorderElementSpec, NULL); + Ttk_RegisterElementSpec(themePtr, "field", &FieldElementSpec, NULL); + Ttk_RegisterElementSpec(themePtr, "focus", &FocusElementSpec, NULL); + Ttk_RegisterElementSpec(themePtr, "Combobox.focus", + &ComboboxFocusElementSpec, NULL); + Ttk_RegisterElementSpec(themePtr, "thumb", &ThumbElementSpec, NULL); + Ttk_RegisterElementSpec(themePtr, "slider", &SliderElementSpec, NULL); + Ttk_RegisterElementSpec(themePtr, "Scrollbar.trough", &TroughElementSpec, + TroughClientDataInit(interp)); + + Ttk_RegisterElementSpec(themePtr, "client", &ClientElementSpec, NULL); + + for (fce = FrameControlElements; fce->name != 0; ++fce) { + Ttk_RegisterElementSpec(themePtr, fce->name, + &FrameControlElementSpec, fce); + } + + Ttk_RegisterLayout(themePtr, "TButton", ButtonLayout); + Ttk_RegisterLayout(themePtr, "TCombobox", ComboboxLayout); + + Tcl_PkgProvide(interp, "ttk::theme::winnative", TTK_VERSION); + return TCL_OK; +} + |