From 932e5ce705443196ef1b9e4b05c8794d85822622 Mon Sep 17 00:00:00 2001 From: treectrl Date: Mon, 4 Dec 2006 00:20:38 +0000 Subject: Theme-related changes to support tile-aware treectrl. --- generic/tkTreeCtrl.c | 58 ++++- generic/tkTreeTheme.c | 609 +++++++++++++++++++++++++++++++++++++++++++++++++- library/treectrl.tcl | 15 +- 3 files changed, 665 insertions(+), 17 deletions(-) diff --git a/generic/tkTreeCtrl.c b/generic/tkTreeCtrl.c index b2f2611..d36f50f 100644 --- a/generic/tkTreeCtrl.c +++ b/generic/tkTreeCtrl.c @@ -7,10 +7,12 @@ * Copyright (c) 2002-2003 Christian Krone * Copyright (c) 2003-2005 ActiveState, a division of Sophos * - * RCS: @(#) $Id: tkTreeCtrl.c,v 1.91 2006/12/02 21:21:16 treectrl Exp $ + * RCS: @(#) $Id: tkTreeCtrl.c,v 1.92 2006/12/04 00:21:29 treectrl Exp $ */ #include "tkTreeCtrl.h" +#include "tclInt.h" /* TclGetIntForIndex */ + #ifdef WIN32 #include #endif @@ -85,7 +87,7 @@ static Tk_OptionSpec optionSpecs[] = { {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth", DEF_LISTBOX_BORDER_WIDTH, Tk_Offset(TreeCtrl, borderWidthObj), Tk_Offset(TreeCtrl, borderWidth), - 0, (ClientData) NULL, TREE_CONF_RELAYOUT}, + 0, (ClientData) NULL, TREE_CONF_BORDERS | TREE_CONF_RELAYOUT}, {TK_OPTION_COLOR, "-buttoncolor", "buttonColor", "ButtonColor", "#808080", -1, Tk_Offset(TreeCtrl, buttonColor), 0, (ClientData) NULL, TREE_CONF_BUTTON | TREE_CONF_REDISPLAY}, @@ -149,7 +151,7 @@ static Tk_OptionSpec optionSpecs[] = { "HighlightThickness", DEF_LISTBOX_HIGHLIGHT_WIDTH, Tk_Offset(TreeCtrl, highlightWidthObj), Tk_Offset(TreeCtrl, highlightWidth), - 0, (ClientData) NULL, TREE_CONF_RELAYOUT}, + 0, (ClientData) NULL, TREE_CONF_BORDERS | TREE_CONF_RELAYOUT}, {TK_OPTION_PIXELS, "-indent", "indent", "Indent", "19", Tk_Offset(TreeCtrl, indentObj), Tk_Offset(TreeCtrl, indent), @@ -411,7 +413,11 @@ TreeObjCmd( TreeDInfo_Init(tree); Tk_CreateEventHandler(tree->tkwin, +#ifdef USE_TTK + ExposureMask|StructureNotifyMask|FocusChangeMask|ActivateMask|VirtualEventMask, +#else ExposureMask|StructureNotifyMask|FocusChangeMask|ActivateMask, +#endif TreeEventProc, (ClientData) tree); /* Must do this on Unix because Tk_GCForColor() uses @@ -1511,9 +1517,18 @@ badWrap: tree->useIndent = MAX(tree->indent, ButtonMaxWidth(tree)); - if (tree->highlightWidth < 0) - tree->highlightWidth = 0; - tree->inset = tree->highlightWidth + tree->borderWidth; + if (createFlag) + mask |= TREE_CONF_BORDERS; + + if (mask & TREE_CONF_BORDERS) { + if (tree->highlightWidth < 0) + tree->highlightWidth = 0; + if (TreeTheme_SetBorders(tree) != TCL_OK) { + tree->inset.left = tree->inset.top = + tree->inset.right = tree->inset.bottom = + tree->highlightWidth + tree->borderWidth; + } + } if (oldShowRoot != tree->showRoot) { TreeItem_InvalidateHeight(tree, tree->root); @@ -1657,6 +1672,16 @@ TreeEventProc( Tcl_EventuallyFree((ClientData) tree, TreeDestroy); } break; +#ifdef USE_TTK + case VirtualEvent: + if (!strcmp("ThemeChanged", ((XVirtualEvent *)(eventPtr))->name)) { + TreeTheme_ThemeChanged(tree); + tree->widthOfColumns = -1; + tree->widthOfColumnsLeft = tree->widthOfColumnsRight = -1; + Tree_RelayoutWindow(tree); + } + break; +#endif } } @@ -1923,11 +1948,12 @@ TreeComputeGeometry( TreeCtrl *tree /* Widget info. */ ) { - if (TreeTheme_ComputeGeometry(tree) != TCL_OK) { - Tk_SetInternalBorder(tree->tkwin, tree->inset); - Tk_GeometryRequest(tree->tkwin, tree->width + tree->inset * 2, - tree->height + tree->inset * 2); - } + Tk_SetInternalBorderEx(tree->tkwin, + tree->inset.left, tree->inset.right, + tree->inset.top, tree->inset.bottom); + Tk_GeometryRequest(tree->tkwin, + tree->width + tree->inset.left + tree->inset.right, + tree->height + tree->inset.top + tree->inset.bottom); } /* @@ -4122,6 +4148,8 @@ LoupeCmd( return TCL_OK; } +#ifndef USE_TTK + /* *-------------------------------------------------------------- * @@ -4190,6 +4218,8 @@ Tree_TheWorldHasChanged( RecomputeWidgets(winPtr); } +#endif /* !USE_TTK */ + /* * In order to find treectrl.tcl during initialization, the following script * is invoked. @@ -4225,7 +4255,11 @@ Treectrl_Init( Tcl_Interp *interp /* Interpreter the package is loading into. */ ) { - static /*CONST*/ char *tcl_version = "8.4"; +#ifdef USE_TTK + static CONST char *tcl_version = "8.5"; +#else + static CONST char *tcl_version = "8.4"; +#endif #ifdef USE_TCL_STUBS if (Tcl_InitStubs(interp, tcl_version, 0) == NULL) { diff --git a/generic/tkTreeTheme.c b/generic/tkTreeTheme.c index cde4b71..b573c11 100644 --- a/generic/tkTreeTheme.c +++ b/generic/tkTreeTheme.c @@ -5,7 +5,7 @@ * * Copyright (c) 2006 Tim Baker * - * RCS: @(#) $Id: tkTreeTheme.c,v 1.17 2006/12/02 21:39:32 treectrl Exp $ + * RCS: @(#) $Id: tkTreeTheme.c,v 1.18 2006/12/04 00:20:38 treectrl Exp $ */ #ifdef WIN32 @@ -13,12 +13,17 @@ #endif #include "tkTreeCtrl.h" +#ifdef USE_TTK +#include "ttk/ttkTheme.h" +#include "ttk/ttk-extra.h" +#endif /* These must agree with tkTreeColumn.c */ #define COLUMN_STATE_NORMAL 0 #define COLUMN_STATE_ACTIVE 1 #define COLUMN_STATE_PRESSED 2 +#ifndef USE_TTK #ifdef WIN32 #include "tkWinInt.h" @@ -553,11 +558,27 @@ int TreeTheme_GetArrowSize(TreeCtrl *tree, Drawable drawable, int up, int *width return TCL_OK; } -int TreeTheme_ComputeGeometry(TreeCtrl *tree) +int TreeTheme_SetBorders(TreeCtrl *tree) { return TCL_ERROR; } +int +TreeTheme_DrawBorders( + TreeCtrl *tree, + Drawable drawable + ) +{ + return TCL_ERROR; +} + +void +TreeTheme_Relayout( + TreeCtrl *tree + ) +{ +} + #if !defined(WM_THEMECHANGED) #define WM_THEMECHANGED 0x031A #endif @@ -928,11 +949,28 @@ int TreeTheme_GetArrowSize(TreeCtrl *tree, Drawable drawable, int up, int *width } -int TreeTheme_ComputeGeometry(TreeCtrl *tree) +int TreeTheme_SetBorders(TreeCtrl *tree) +{ + return TCL_ERROR; +} + +int +TreeTheme_DrawBorders( + TreeCtrl *tree, + Drawable drawable + ) { return TCL_ERROR; } + +void +TreeTheme_Relayout( + TreeCtrl *tree + ) +{ +} + void TreeTheme_ThemeChanged(TreeCtrl *tree) { } @@ -985,11 +1023,28 @@ int TreeTheme_GetArrowSize(TreeCtrl *tree, Drawable drawable, int up, int *width } -int TreeTheme_ComputeGeometry(TreeCtrl *tree) +int TreeTheme_SetBorders(TreeCtrl *tree) +{ + return TCL_ERROR; +} + +int +TreeTheme_DrawBorders( + TreeCtrl *tree, + Drawable drawable + ) { return TCL_ERROR; } + +void +TreeTheme_Relayout( + TreeCtrl *tree + ) +{ +} + void TreeTheme_ThemeChanged(TreeCtrl *tree) { } @@ -1011,3 +1066,549 @@ int TreeTheme_InitInterp(Tcl_Interp *interp) #endif /* !WIN32 && !MAC_OSX_TK */ +#else /* !USE_TTK */ + +typedef struct TreeThemeData_ +{ + Ttk_Layout layout; + Ttk_Layout buttonLayout; + Ttk_Layout headingLayout; + Tk_OptionTable buttonOptionTable; + Tk_OptionTable headingOptionTable; + Ttk_Box clientBox; + int buttonWidth[2], buttonHeight[2]; + Ttk_Padding buttonPadding[2]; +} TreeThemeData_; + +int TreeTheme_DrawHeaderItem(TreeCtrl *tree, Drawable drawable, int state, int arrow, int x, int y, int width, int height) +{ + TreeThemeData themeData = tree->themeData; + Ttk_Layout layout = themeData->headingLayout; + Ttk_State ttk_state = 0; + Ttk_Box box; + + if (layout == NULL) + return TCL_ERROR; + + box = Ttk_MakeBox(x, y, width, height); + + switch (state) + { + case COLUMN_STATE_ACTIVE: ttk_state = TTK_STATE_ACTIVE; break; + case COLUMN_STATE_PRESSED: ttk_state = TTK_STATE_PRESSED; break; + } + + eTtk_RebindSublayout(layout, NULL); /* !!! rebind to column */ + eTtk_PlaceLayout(layout, ttk_state, box); + eTtk_DrawLayout(layout, ttk_state, drawable); + + return TCL_OK; +} + +int TreeTheme_GetHeaderContentMargins(TreeCtrl *tree, int state, int arrow, int bounds[4]) +{ + return TCL_ERROR; +} + +int TreeTheme_DrawHeaderArrow(TreeCtrl *tree, Drawable drawable, int up, int x, int y, int width, int height) +{ + return TCL_ERROR; +} + +/* From ttkTreeview.c */ +#define TTK_STATE_OPEN TTK_STATE_USER1 + +int TreeTheme_DrawButton(TreeCtrl *tree, Drawable drawable, int open, int x, int y, int width, int height) +{ + TreeThemeData themeData = tree->themeData; + Ttk_Layout layout = themeData->buttonLayout; + Ttk_State ttk_state = 0; + Ttk_Box box; + Ttk_Padding padding; + + if (layout == NULL) + return TCL_ERROR; + + open = open ? 1 : 0; + padding = themeData->buttonPadding[open]; + x -= padding.left; + y -= padding.top; + width = themeData->buttonWidth[open]; + height = themeData->buttonHeight[open]; + box = Ttk_MakeBox(x, y, width, height); + + ttk_state = open ? TTK_STATE_OPEN : 0; + + eTtk_RebindSublayout(layout, NULL); /* !!! rebind to item */ + eTtk_PlaceLayout(layout, ttk_state, box); + eTtk_DrawLayout(layout, ttk_state, drawable); + + return TCL_OK; +} + +int TreeTheme_GetButtonSize(TreeCtrl *tree, Drawable drawable, int open, int *widthPtr, int *heightPtr) +{ + TreeThemeData themeData = tree->themeData; + Ttk_Padding padding; + + if (themeData->buttonLayout == NULL) + return TCL_ERROR; + + open = open ? 1 : 0; + padding = themeData->buttonPadding[open]; + *widthPtr = themeData->buttonWidth[open] - padding.left - padding.right; + *heightPtr = themeData->buttonHeight[open] - padding.top - padding.bottom; + return TCL_OK; +} + +int TreeTheme_GetArrowSize(TreeCtrl *tree, Drawable drawable, int up, int *widthPtr, int *heightPtr) +{ + return TCL_ERROR; +} + +int TreeTheme_SetBorders(TreeCtrl *tree) +{ + TreeThemeData themeData = tree->themeData; + Tk_Window tkwin = tree->tkwin; + Ttk_Box clientBox = themeData->clientBox; + + tree->inset.left = clientBox.x; + tree->inset.top = clientBox.y; + tree->inset.right = Tk_Width(tkwin) - (clientBox.x + clientBox.width); + tree->inset.bottom = Tk_Height(tkwin) - (clientBox.y + clientBox.height); + + return TCL_OK; +} + +/* + * This routine is a big hack so that the "field" element (of the TreeCtrl + * layout) doesn't erase the entire background of the window. This routine + * draws each edge of the layout into a pixmap and copies the pixmap to the + * window. + */ +int +TreeTheme_DrawBorders( + TreeCtrl *tree, + Drawable drawable + ) +{ + TreeThemeData themeData = tree->themeData; + Tk_Window tkwin = tree->tkwin; + Ttk_Box winBox = Ttk_WinBox(tree->tkwin); + Ttk_State state = 0; /* ??? */ + int left, top, right, bottom; + Drawable pixmapLR = None, pixmapTB = None; + + left = tree->inset.left; + top = tree->inset.top; + right = tree->inset.right; + bottom = tree->inset.bottom; + + /* If the Ttk layout doesn't specify any borders or padding, then + * draw nothing. */ + if (left < 1 && top < 1 && right < 1 && bottom < 1) + return TCL_OK; + + if (left > 0 || top > 0) + eTtk_PlaceLayout(themeData->layout, state, winBox); + + if (left > 0 || right > 0) { + pixmapLR = Tk_GetPixmap(tree->display, Tk_WindowId(tkwin), + MAX(left, right), Tk_Height(tkwin), Tk_Depth(tkwin)); + } + + if (top > 0 || bottom > 0) { + pixmapTB = Tk_GetPixmap(tree->display, Tk_WindowId(tkwin), + Tk_Width(tkwin), MAX(top, bottom), Tk_Depth(tkwin)); + } + + DebugDrawBorder(tree, 0, left, top, right, bottom); + + if (left > 0) { + eTtk_DrawLayout(themeData->layout, state, pixmapLR); + XCopyArea(tree->display, pixmapLR, drawable, + tree->copyGC, 0, 0, + left, Tk_Height(tkwin), + 0, 0); + } + + if (top > 0) { + eTtk_DrawLayout(themeData->layout, state, pixmapTB); + XCopyArea(tree->display, pixmapTB, drawable, + tree->copyGC, 0, 0, + Tk_Width(tkwin), top, + 0, 0); + } + + if (right > 0) { + winBox.x -= winBox.width - right; + eTtk_PlaceLayout(themeData->layout, state, winBox); + + eTtk_DrawLayout(themeData->layout, state, pixmapLR); + XCopyArea(tree->display, pixmapLR, drawable, + tree->copyGC, 0, 0, + right, Tk_Height(tkwin), + Tree_BorderRight(tree), 0); + } + + if (bottom > 0) { + winBox.x = 0; + winBox.y -= winBox.height - bottom; + eTtk_PlaceLayout(themeData->layout, state, winBox); + + eTtk_DrawLayout(themeData->layout, state, pixmapTB); + XCopyArea(tree->display, pixmapTB, drawable, + tree->copyGC, 0, 0, + Tk_Width(tkwin), bottom, + 0, Tree_BorderBottom(tree)); + } + + if (pixmapLR != None) + Tk_FreePixmap(tree->display, pixmapLR); + if (pixmapTB != None) + Tk_FreePixmap(tree->display, pixmapTB); + + return TCL_OK; +} + +static Tk_OptionSpec NullOptionSpecs[] = +{ + {TK_OPTION_END, 0,0,0, NULL, -1,-1, 0,0,0} +}; + +/* from ttkTreeview.c */ +static Ttk_Layout +GetSublayout( + Tcl_Interp *interp, + Ttk_Theme themePtr, + Ttk_Layout parentLayout, + const char *layoutName, + Tk_OptionTable optionTable, + Ttk_Layout *layoutPtr) +{ + Ttk_Layout newLayout = eTtk_CreateSublayout( + interp, themePtr, parentLayout, layoutName, optionTable); + + if (newLayout) { + if (*layoutPtr) + eTtk_FreeLayout(*layoutPtr); + *layoutPtr = newLayout; + } + return newLayout; +} + +Ttk_Layout +TreeCtrlGetLayout( + Tcl_Interp *interp, + Ttk_Theme themePtr, + void *recordPtr + ) +{ + TreeCtrl *tree = recordPtr; + TreeThemeData themeData = tree->themeData; + Ttk_Layout treeLayout, newLayout; + + if (themeData->headingOptionTable == NULL) + themeData->headingOptionTable = Tk_CreateOptionTable(interp, NullOptionSpecs); + if (themeData->buttonOptionTable == NULL) + themeData->buttonOptionTable = Tk_CreateOptionTable(interp, NullOptionSpecs); + + /* Create a new layout record based on widget -style or class */ + treeLayout = eTtk_CreateLayout(interp, themePtr, "TreeCtrl", tree, + tree->optionTable, tree->tkwin); + + /* Create a sublayout for drawing the column headers. The sublayout is + * called "TreeCtrl.TreeCtrlHeading" by default. The actual layout specification + * was defined by Ttk_RegisterLayout("TreeCtrlHeading") below. */ + newLayout = GetSublayout(interp, themePtr, treeLayout, + ".TreeCtrlHeading", themeData->headingOptionTable, + &themeData->headingLayout); + if (newLayout == NULL) + return NULL; + + newLayout = GetSublayout(interp, themePtr, treeLayout, + ".TreeCtrlButton", themeData->buttonOptionTable, + &themeData->buttonLayout); + if (newLayout == NULL) + return NULL; + + return treeLayout; +} + +void +TreeCtrlDoLayout( + void *recordPtr + ) +{ + TreeCtrl *tree = recordPtr; + TreeThemeData themeData = tree->themeData; + Ttk_LayoutNode *node; + Ttk_Box winBox = Ttk_WinBox(tree->tkwin); + Ttk_State state = 0; /* ??? */ + + eTtk_PlaceLayout(themeData->layout, state, winBox); + node = eTtk_LayoutFindNode(themeData->layout, "client"); + if (node != NULL) + themeData->clientBox = eTtk_LayoutNodeInternalParcel(themeData->layout, node); + else + themeData->clientBox = winBox; + + /* Size of opened and closed buttons. */ + eTtk_LayoutSize(themeData->buttonLayout, TTK_STATE_OPEN, + &themeData->buttonWidth[1], &themeData->buttonHeight[1]); + eTtk_LayoutSize(themeData->buttonLayout, 0, + &themeData->buttonWidth[0], &themeData->buttonHeight[0]); + + node = eTtk_LayoutFindNode(themeData->buttonLayout, "indicator"); + if (node != NULL) { + Ttk_Box box1, box2; + + box1 = Ttk_MakeBox(0, 0, themeData->buttonWidth[1], themeData->buttonHeight[1]); + eTtk_PlaceLayout(themeData->buttonLayout, TTK_STATE_OPEN, box1); + box2 = eTtk_LayoutNodeInternalParcel(themeData->buttonLayout, node); + themeData->buttonPadding[1] = Ttk_MakePadding(box2.x, box2.y, + (box1.x + box1.width) - (box2.x + box2.width), + (box1.y + box1.height) - (box2.y + box2.height)); + + box1 = Ttk_MakeBox(0, 0, themeData->buttonWidth[0], themeData->buttonHeight[0]); + eTtk_PlaceLayout(themeData->buttonLayout, 0, box1); + box2 = eTtk_LayoutNodeInternalParcel(themeData->buttonLayout, node); + themeData->buttonPadding[0] = Ttk_MakePadding(box2.x, box2.y, + (box1.x + box1.width) - (box2.x + box2.width), + (box1.y + box1.height) - (box2.y + box2.height)); + + } else { + themeData->buttonPadding[1] = Ttk_MakePadding(0,0,0,0); + themeData->buttonPadding[0] = Ttk_MakePadding(0,0,0,0); + } +} + +void +TreeTheme_Relayout( + TreeCtrl *tree + ) +{ + TreeThemeData themeData = tree->themeData; + Ttk_Theme themePtr = Ttk_GetCurrentTheme(tree->interp); + Ttk_Layout newLayout = TreeCtrlGetLayout(tree->interp, themePtr, tree); + + if (newLayout) { + if (themeData->layout) { + eTtk_FreeLayout(themeData->layout); + } + themeData->layout = newLayout; + TreeCtrlDoLayout(tree); + } +} + +/* HeaderElement is used for Treeheading.cell. The platform-specific code + * will draw the native heading. */ +typedef struct +{ + Tcl_Obj *backgroundObj; +} HeaderElement; + +static Ttk_ElementOptionSpec HeaderElementOptions[] = +{ + { "-background", TK_OPTION_COLOR, + Tk_Offset(HeaderElement, backgroundObj), DEFAULT_BACKGROUND }, + {NULL} +}; + +static void HeaderElementDraw( + void *clientData, void *elementRecord, Tk_Window tkwin, + Drawable d, Ttk_Box b, Ttk_State state) +{ + HeaderElement *e = elementRecord; + XColor *color = Tk_GetColorFromObj(tkwin, e->backgroundObj); + GC gc = Tk_GCForColor(color, d); + XFillRectangle(Tk_Display(tkwin), d, gc, + b.x, b.y, b.width, b.height); +} + +static Ttk_ElementSpec HeaderElementSpec = +{ + TK_STYLE_VERSION_2, + sizeof(HeaderElement), + HeaderElementOptions, + Ttk_NullElementGeometry, + HeaderElementDraw +}; + +/* Default button element (aka Treeitem.indicator). */ +typedef struct +{ + Tcl_Obj *backgroundObj; + Tcl_Obj *colorObj; + Tcl_Obj *sizeObj; + Tcl_Obj *thicknessObj; +} TreeitemIndicator; + +static Ttk_ElementOptionSpec TreeitemIndicatorOptions[] = +{ + { "-buttonbackground", TK_OPTION_COLOR, + Tk_Offset(TreeitemIndicator, backgroundObj), "white" }, + { "-buttoncolor", TK_OPTION_COLOR, + Tk_Offset(TreeitemIndicator, colorObj), "#808080" }, + { "-buttonsize", TK_OPTION_PIXELS, + Tk_Offset(TreeitemIndicator, sizeObj), "9" }, + { "-buttonthickness", TK_OPTION_PIXELS, + Tk_Offset(TreeitemIndicator, thicknessObj), "1" }, + {NULL} +}; + +static void TreeitemIndicatorSize( + void *clientData, void *elementRecord, Tk_Window tkwin, + int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) +{ + TreeitemIndicator *indicator = elementRecord; + int size = 0; + + Tk_GetPixelsFromObj(NULL, tkwin, indicator->sizeObj, &size); + + *widthPtr = *heightPtr = size; + *paddingPtr = Ttk_MakePadding(0,0,0,0); +} + +static void TreeitemIndicatorDraw( + void *clientData, void *elementRecord, Tk_Window tkwin, + Drawable d, Ttk_Box b, Ttk_State state) +{ + TreeitemIndicator *indicator = elementRecord; + int w1, lineLeft, lineTop, buttonLeft, buttonTop, buttonThickness, buttonSize; + XColor *bgColor = Tk_GetColorFromObj(tkwin, indicator->backgroundObj); + XColor *buttonColor = Tk_GetColorFromObj(tkwin, indicator->colorObj); + XGCValues gcValues; + unsigned long gcMask; + GC buttonGC; + Ttk_Padding padding = Ttk_MakePadding(0,0,0,0); + + b = Ttk_PadBox(b, padding); + + Tk_GetPixelsFromObj(NULL, tkwin, indicator->sizeObj, &buttonSize); + Tk_GetPixelsFromObj(NULL, tkwin, indicator->thicknessObj, &buttonThickness); + + w1 = buttonThickness / 2; + + /* Left edge of vertical line */ + /* Make sure this matches TreeItem_DrawLines() */ + lineLeft = b.x + (b.width - buttonThickness) / 2; + + /* Top edge of horizontal line */ + /* Make sure this matches TreeItem_DrawLines() */ + lineTop = b.y + (b.height - buttonThickness) / 2; + + buttonLeft = b.x; + buttonTop = b.y; + + /* Erase button background */ + XFillRectangle(Tk_Display(tkwin), d, + Tk_GCForColor(bgColor, d), + buttonLeft + buttonThickness, + buttonTop + buttonThickness, + buttonSize - buttonThickness, + buttonSize - buttonThickness); + + gcValues.foreground = buttonColor->pixel; + gcValues.line_width = buttonThickness; + gcMask = GCForeground | GCLineWidth; + buttonGC = Tk_GetGC(tkwin, gcMask, &gcValues); + + /* Draw button outline */ + XDrawRectangle(Tk_Display(tkwin), d, buttonGC, + buttonLeft + w1, + buttonTop + w1, + buttonSize - buttonThickness, + buttonSize - buttonThickness); + + /* Horizontal '-' */ + XFillRectangle(Tk_Display(tkwin), d, buttonGC, + buttonLeft + buttonThickness * 2, + lineTop, + buttonSize - buttonThickness * 4, + buttonThickness); + + if (!(state & TTK_STATE_OPEN)) { + /* Finish '+' */ + XFillRectangle(Tk_Display(tkwin), d, buttonGC, + lineLeft, + buttonTop + buttonThickness * 2, + buttonThickness, + buttonSize - buttonThickness * 4); + } + + Tk_FreeGC(Tk_Display(tkwin), buttonGC); +} + +static Ttk_ElementSpec TreeitemIndicatorElementSpec = +{ + TK_STYLE_VERSION_2, + sizeof(TreeitemIndicator), + TreeitemIndicatorOptions, + TreeitemIndicatorSize, + TreeitemIndicatorDraw +}; + +TTK_BEGIN_LAYOUT(HeadingLayout) + TTK_NODE("Treeheading.cell", TTK_FILL_BOTH) + TTK_NODE("Treeheading.border", TTK_FILL_BOTH) +TTK_END_LAYOUT + +TTK_BEGIN_LAYOUT(ButtonLayout) + TTK_NODE("Treeitem.indicator", TTK_PACK_LEFT) +TTK_END_LAYOUT + +TTK_BEGIN_LAYOUT(TreeCtrlLayout) + TTK_GROUP("TreeCtrl.field", TTK_FILL_BOTH|TTK_BORDER, + TTK_GROUP("TreeCtrl.padding", TTK_FILL_BOTH, + TTK_NODE("TreeCtrl.client", TTK_FILL_BOTH))) +TTK_END_LAYOUT + +void TreeTheme_ThemeChanged(TreeCtrl *tree) +{ +} + +int TreeTheme_Init(TreeCtrl *tree) +{ + tree->themeData = (TreeThemeData) ckalloc(sizeof(TreeThemeData_)); + memset(tree->themeData, '\0', sizeof(TreeThemeData_)); + + return TCL_OK; +} + +int TreeTheme_Free(TreeCtrl *tree) +{ + TreeThemeData themeData = tree->themeData; + + if (themeData != NULL) { + if (themeData->layout != NULL) + eTtk_FreeLayout(themeData->layout); + if (themeData->buttonLayout != NULL) + eTtk_FreeLayout(themeData->buttonLayout); + if (themeData->headingLayout != NULL) + eTtk_FreeLayout(themeData->headingLayout); + ckfree((char *) themeData); + } + return TCL_OK; +} + +int TreeTheme_InitInterp(Tcl_Interp *interp) +{ + Ttk_Theme theme = Ttk_GetDefaultTheme(interp); + + Ttk_RegisterLayout(theme, "TreeCtrl", TreeCtrlLayout); + + /* Problem: what if Treeview also defines this? */ + Ttk_RegisterElement(interp, theme, "Treeheading.cell", &HeaderElementSpec, 0); + + /* Problem: what if Treeview also defines this? */ + Ttk_RegisterElement(interp, theme, "Treeitem.indicator", &TreeitemIndicatorElementSpec, 0); + + Ttk_RegisterLayout(theme, "TreeCtrlHeading", HeadingLayout); + Ttk_RegisterLayout(theme, "TreeCtrlButton", ButtonLayout); + + return TCL_OK; +} + +#endif /* USE_TTK */ + diff --git a/library/treectrl.tcl b/library/treectrl.tcl index 84be0e9..4ff06a4 100644 --- a/library/treectrl.tcl +++ b/library/treectrl.tcl @@ -1,4 +1,4 @@ -# RCS: @(#) $Id: treectrl.tcl,v 1.37 2006/11/21 02:00:54 treectrl Exp $ +# RCS: @(#) $Id: treectrl.tcl,v 1.38 2006/12/04 00:22:29 treectrl Exp $ bind TreeCtrl { TreeCtrl::CursorCheck %W %x %y @@ -1494,3 +1494,16 @@ proc ::TreeCtrl::PercentsCmd {T char object event detail charMap} { } return } + +namespace eval TreeCtrl { +catch { + foreach theme [ttk::style theme names] { + ttk::style theme settings $theme { + ttk::style configure TreeCtrlHeading -relief raised -font TkHeadingFont + ttk::style map TreeCtrlHeading -relief { + pressed sunken + } + } + } +} +} -- cgit v0.12