From fb835826dd21c44784539b40e590866ffb89bd93 Mon Sep 17 00:00:00 2001 From: jenglish Date: Mon, 18 Dec 2006 19:33:10 +0000 Subject: Big batch of ttk::treeview improvements: Added column '-stretch' and '-minwidth' options. Improved column drag and resize behavior. Added horizontal scrolling [#1518650]. Row height and child indent specifiable on Treeview style. Decreased default row height, no default -padding. Use correct heading height [#1163349]. Apply tag settings to tree item as well as to data columns [NOTE: 'tag configure' still buggy]. Fix off-by-one condition when moving nodes forward [#1618142] Prevent overscroll ([#1173434]) Treeview style settings specified separately in each theme. Added disclosure triangle element in aqua theme. --- ChangeLog | 19 ++ doc/ttk_treeview.n | 23 +- generic/ttk/ttkScroll.c | 8 +- generic/ttk/ttkTreeview.c | 558 +++++++++++++++++++++++++++++++------------ library/ttk/altTheme.tcl | 17 +- library/ttk/aquaTheme.tcl | 13 +- library/ttk/clamTheme.tcl | 19 +- library/ttk/classicTheme.tcl | 14 +- library/ttk/defaults.tcl | 18 +- library/ttk/treeview.tcl | 47 +--- library/ttk/winTheme.tcl | 16 +- library/ttk/xpTheme.tcl | 16 +- macosx/ttkMacOSXTheme.c | 59 ++++- 13 files changed, 615 insertions(+), 212 deletions(-) diff --git a/ChangeLog b/ChangeLog index eb859a4..d382692 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,22 @@ +2006-12-18 Joe English + + * generic/ttk/ttkTreeview.c, library/ttk/treeview.tcl, doc/treeview.n: + Added column '-stretch' and '-minwidth' options. + Improved column drag and resize behavior. + Added horizontal scrolling [#1518650]. + Row height and child indent specifiable on Treeview style. + Decreased default row height, no default -padding. + Use correct heading height [#1163349]. + Apply tag settings to tree item as well as to data columns + [NOTE: 'tag configure' still buggy]. + Fix off-by-one condition when moving nodes forward [#1618142] + * generic/ttk/ttkScroll.c(TtkScrollTo): Prevent overscroll ([#1173434]) + * library/ttk/altTheme.tcl, library/ttk/aquaTheme.tcl, + library/ttk/clamTheme.tcl, library/ttk/classicTheme.tcl, + library/ttk/defaults.tcl, library/ttk/winTheme.tcl + library/ttk/xpTheme.tcl: Per-theme treeview settings. + * macosx/ttkMacOSXTheme.c: Added disclosure triangle element. + 2006-12-17 Joe English * library/ttk/combobox.tcl, generic/ttk/ttkEntry.c, diff --git a/doc/ttk_treeview.n b/doc/ttk_treeview.n index 0770c7c..63c354d 100644 --- a/doc/ttk_treeview.n +++ b/doc/ttk_treeview.n @@ -4,7 +4,7 @@ '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" -'\" RCS: @(#) $Id: ttk_treeview.n,v 1.3 2006/12/13 23:04:33 hobbs Exp $ +'\" RCS: @(#) $Id: ttk_treeview.n,v 1.4 2006/12/18 19:33:13 jenglish Exp $ '\" .so man.macros .TH ttk_treeview n 8.5 Tk "Tk Themed Widget" @@ -41,12 +41,12 @@ and control the appearance of the item. .\" .PP .\" @@@HERE: describe selection, focus item .PP -Treeview widgets support vertical scrolling with the -standard \fB-yscrollcommand\fR option and \fByview\fR widget command. -They probably ought to support horizontal scrolling as well. +Treeview widgets support horizontal and vertical scrolling with the +standard \fB-[xy]scrollcommand\fR options +and \fB[xyview\fR widget commands. .SO \-class \-cursor \-takefocus \-style -\-yscrollcommand +\-xscrollcommand \-yscrollcommand .SE .SH "WIDGET-SPECIFIC OPTIONS" @@ -141,6 +141,16 @@ with respect to the cell. One of \fBn\fR, \fBne\fR, \fBe\fR, \fBse\fR, \fBs\fR, \fBsw\fR, \fBw\fR, \fBnw\fR, or \fBcenter\fR. .TP +\fB-minwidth\fR +The minimum width of the column in pixels. +The treeview widget will not make the column any smaller than +\fB-minwidth\fR when the widget is resized or the user drags a +column separator. +.TP +\fB-stretch\fR +Specifies whether or not the column's width should be adjusted +when the widget is resized. +.TP \fB-width \fIw\fR The width of the column in pixels. Default is something reasonable, probably 200 or so. @@ -331,6 +341,9 @@ returns a dictionary of the option settings for \fItagName\fR. See \fBTAG OPTIONS\fR for the list of available options. .RE .TP +\fIpathName \fBxview \fIargs\fR +Standard command for horizontal scrolling; see \fIwidget(n)\fR. +.TP \fIpathName \fByview \fIargs\fR Standard command for vertical scrolling; see \fIttk_widget(n)\fR. diff --git a/generic/ttk/ttkScroll.c b/generic/ttk/ttkScroll.c index a7fa1f4..ab1f1e7 100644 --- a/generic/ttk/ttkScroll.c +++ b/generic/ttk/ttkScroll.c @@ -1,4 +1,4 @@ -/* $Id: ttkScroll.c,v 1.4 2006/11/13 00:22:40 jenglish Exp $ +/* $Id: ttkScroll.c,v 1.5 2006/12/18 19:33:13 jenglish Exp $ * * Copyright 2004, Joe English * @@ -144,6 +144,12 @@ void TtkScrolled(ScrollHandle h, int first, int last, int total) total = 1; } + if (last > total) { + first -= (last - total); + if (first < 0) first = 0; + last = total; + } + if (s->first != first || s->last != last || s->total != total || (h->flags & SCROLL_UPDATE_REQUIRED)) { diff --git a/generic/ttk/ttkTreeview.c b/generic/ttk/ttkTreeview.c index 53f1b33..25f5942 100644 --- a/generic/ttk/ttkTreeview.c +++ b/generic/ttk/ttkTreeview.c @@ -1,23 +1,23 @@ -/* - * $Id: ttkTreeview.c,v 1.8 2006/12/14 19:51:04 jenglish Exp $ +/* $Id: ttkTreeview.c,v 1.9 2006/12/18 19:33:13 jenglish Exp $ * Copyright (c) 2004, Joe English * * ttk::treeview widget implementation. */ +#include + #include #include #include "ttkTheme.h" #include "ttkWidget.h" #define DEF_TREE_ROWS "10" -#define DEF_TREE_PADDING "4" #define DEF_COLWIDTH "200" +#define DEF_MINWIDTH "20" -static const int ROWHEIGHT = 24; -static const int HEADINGHEIGHT = 24; -static const int INDENT = 24; -static const int HALO = 4; /* separator */ +static const int DEFAULT_ROWHEIGHT = 20; +static const int DEFAULT_INDENT = 20; +static const int HALO = 4; /* separator */ #define TTK_STATE_OPEN TTK_STATE_USER1 #define TTK_STATE_LEAF TTK_STATE_USER2 @@ -172,7 +172,7 @@ typedef struct { Tcl_Obj *imageObj; /* taken from item */ Tcl_Obj *anchorObj; /* from column */ Tcl_Obj *backgroundObj; /* remainder from tag */ - Tcl_Obj *foregroundObj; + Tcl_Obj *foregroundObj; Tcl_Obj *fontObj; } DisplayItem; @@ -185,12 +185,12 @@ static Tk_OptionSpec TagOptionSpecs[] = NULL, Tk_Offset(DisplayItem,imageObj), -1, TK_OPTION_NULL_OK,0,0 }, {TK_OPTION_ANCHOR, "-anchor", "anchor", "Anchor", - NULL, Tk_Offset(DisplayItem,anchorObj), -1, + NULL, Tk_Offset(DisplayItem,anchorObj), -1, TK_OPTION_NULL_OK, 0, GEOMETRY_CHANGED}, - {TK_OPTION_COLOR, "-background", "windowColor", "WindowColor", + {TK_OPTION_COLOR, "-background", "windowColor", "WindowColor", NULL, Tk_Offset(DisplayItem,backgroundObj), -1, TK_OPTION_NULL_OK,0,0 }, - {TK_OPTION_COLOR, "-foreground", "textColor", "TextColor", + {TK_OPTION_COLOR, "-foreground", "textColor", "TextColor", NULL, Tk_Offset(DisplayItem,foregroundObj), -1, TK_OPTION_NULL_OK,0,0 }, {TK_OPTION_FONT, "-font", "font", "Font", @@ -200,8 +200,6 @@ static Tk_OptionSpec TagOptionSpecs[] = {TK_OPTION_END, 0,0,0, NULL, -1,-1, 0,0,0} }; - - /*------------------------------------------------------------------------ * +++ Columns. * @@ -211,6 +209,8 @@ static Tk_OptionSpec TagOptionSpecs[] = */ typedef struct { int width; /* Column width, in pixels */ + int minWidth; /* Minimum column width, in pixels */ + int stretch; /* Should column stretch while resizing? */ Tcl_Obj *idObj; /* Column identifier, from -columns option */ Tcl_Obj *anchorObj; /* -anchor for cell data */ @@ -232,6 +232,8 @@ typedef struct { static void InitColumn(TreeColumn *column) { column->width = 200; + column->minWidth = 20; + column->stretch = 1; column->idObj = 0; column->anchorObj = 0; @@ -245,7 +247,7 @@ static void InitColumn(TreeColumn *column) column->data = 0; } -static void FreeColumn(TreeColumn *column) /* @@@ rename */ +static void FreeColumn(TreeColumn *column) { if (column->idObj) { Tcl_DecrRefCount(column->idObj); } if (column->anchorObj) { Tcl_DecrRefCount(column->anchorObj); } @@ -264,6 +266,12 @@ static Tk_OptionSpec ColumnOptionSpecs[] = {TK_OPTION_INT, "-width", "width", "Width", DEF_COLWIDTH, -1, Tk_Offset(TreeColumn,width), 0,0,GEOMETRY_CHANGED }, + {TK_OPTION_INT, "-minwidth", "minWidth", "MinWidth", + DEF_MINWIDTH, -1, Tk_Offset(TreeColumn,minWidth), + 0,0,0 }, + {TK_OPTION_BOOLEAN, "-stretch", "stretch", "Stretch", + "1", -1, Tk_Offset(TreeColumn,stretch), + 0,0,0 }, {TK_OPTION_ANCHOR, "-anchor", "anchor", "Anchor", "w", Tk_Offset(TreeColumn,anchorObj), -1, 0,0,0 }, @@ -340,6 +348,8 @@ static int GetEnumSetFromObj( * Dependencies: * columns, columnNames: -columns * displayColumns: -columns, -displaycolumns + * headingHeight: [layout] + * rowHeight, indent: style */ typedef struct { @@ -359,6 +369,10 @@ typedef struct Ttk_Layout headingLayout; Ttk_Layout rowLayout; + int headingHeight; /* Space for headings */ + int rowHeight; /* Height of each item */ + int indent; /* #pixels horizontal offset for child items */ + /* Tree data: */ Tcl_HashTable items; /* Map: item name -> item */ @@ -381,6 +395,8 @@ typedef struct Tcl_Obj *showObj; /* -show list */ Tcl_Obj *selectModeObj; /* -selectmode option */ + Scrollable xscroll; + ScrollHandle xscrollHandle; Scrollable yscroll; ScrollHandle yscrollHandle; @@ -394,6 +410,7 @@ typedef struct int nDisplayColumns; /* #display columns */ Ttk_Box headingArea; /* Display area for column headings */ Ttk_Box treeArea; /* Display area for tree */ + int slack; /* Slack space (see Resizing section) */ } TreePart; @@ -432,9 +449,12 @@ static Tk_OptionSpec TreeviewOptionSpecs[] = DEF_TREE_ROWS, Tk_Offset(Treeview,tree.heightObj), -1, 0,0,GEOMETRY_CHANGED}, {TK_OPTION_STRING, "-padding", "padding", "Pad", - DEF_TREE_PADDING, Tk_Offset(Treeview,tree.paddingObj), -1, + NULL, Tk_Offset(Treeview,tree.paddingObj), -1, TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED }, + {TK_OPTION_STRING, "-xscrollcommand", "xScrollCommand", "ScrollCommand", + NULL, -1, Tk_Offset(Treeview, tree.xscroll.scrollCmd), + TK_OPTION_NULL_OK, 0, SCROLLCMD_CHANGED}, {TK_OPTION_STRING, "-yscrollcommand", "yScrollCommand", "ScrollCommand", NULL, -1, Tk_Offset(Treeview, tree.yscroll.scrollCmd), TK_OPTION_NULL_OK, 0, SCROLLCMD_CHANGED}, @@ -734,6 +754,174 @@ static int TreeviewInitDisplayColumns(Tcl_Interp *interp, Treeview *tv) } /*------------------------------------------------------------------------ + * +++ Resizing. + * Invariants: TreeWidth(tree) + slack = available space + */ + +#define FirstColumn(tv) ((tv->tree.showFlags&SHOW_TREE) ? 0 : 1) + +/* + TreeWidth -- + * Compute the requested tree width from the sum of visible column widths. + */ +static int TreeWidth(Treeview *tv) +{ + int i = FirstColumn(tv); + int width = 0; + + while (i < tv->tree.nDisplayColumns) { + width += tv->tree.displayColumns[i++]->width; + } + return width; +} + +static int SLACKINVARIANT(Treeview *tv) { + return (TreeWidth(tv) + tv->tree.slack == tv->tree.treeArea.width) ; +} + +/* + RecomputeSlack -- + */ +static void RecomputeSlack(Treeview *tv) +{ + tv->tree.slack = tv->tree.treeArea.width - TreeWidth(tv); +} + +/* + PickupSlack/DepositSlack -- + * When resizing columns, distribute extra space to 'slack' first, + * and only adjust column widths if 'slack' goes to zero. + * That is, don't bother changing column widths if the tree + * is already scrolled or short. + */ +static int PickupSlack(Treeview *tv, int extra) +{ + int newSlack = tv->tree.slack + extra; + + if ( (newSlack < 0 && 0 <= tv->tree.slack) + || (newSlack > 0 && 0 >= tv->tree.slack)) + { + tv->tree.slack = 0; + return newSlack; + } else { + tv->tree.slack = newSlack; + return 0; + } +} + +static void DepositSlack(Treeview *tv, int extra) +{ + tv->tree.slack += extra; +} + +/* + Stretch -- + * Adjust width of column by N pixels, down to minimum width. + * Returns: #pixels actually moved. + */ +static int Stretch(TreeColumn *c, int n) +{ + int newWidth = n + c->width; + if (newWidth < c->minWidth) { + n = c->minWidth - c->width; + c->width = c->minWidth; + } else { + c->width = newWidth; + } + return n; +} + +/* + ShoveLeft -- + * Adjust width of (stretchable) columns to the left by N pixels. + * Returns: leftover slack. + */ +static int ShoveLeft(Treeview *tv, int i, int n) +{ + int first = FirstColumn(tv); + while (n != 0 && i >= first) { + TreeColumn *c = tv->tree.displayColumns[i]; + if (c->stretch) { + n -= Stretch(c, n); + } + --i; + } + return n; +} + +/* + ShoveRight -- + * Adjust width of (stretchable) columns to the right by N pixels. + * Returns: leftover slack. + */ +static int ShoveRight(Treeview *tv, int i, int n) +{ + while (n != 0 && i < tv->tree.nDisplayColumns) { + TreeColumn *c = tv->tree.displayColumns[i]; + if (c->stretch) { + n -= Stretch(c, n); + } + ++i; + } + return n; +} + +/* + DistributeWidth -- + * Distribute n pixels evenly across all stretchable display columns. + * Returns: leftover slack. + * Notes: + * The "((++w % m) < r)" term is there so that the remainder r = n % m + * is distributed round-robin. + */ +static int DistributeWidth(Treeview *tv, int n) +{ + int w = TreeWidth(tv); + int m = 0; + int i, d, r; + + for (i = FirstColumn(tv); i < tv->tree.nDisplayColumns; ++i) { + if (tv->tree.displayColumns[i]->stretch) { + ++m; + } + } + if (m == 0) { + return n; + } + + d = n / m; + r = n % m; + if (r < 0) { r += m; --d; } + + for (i = FirstColumn(tv); i < tv->tree.nDisplayColumns; ++i) { + TreeColumn *c = tv->tree.displayColumns[i]; + if (c->stretch) { + n -= Stretch(c, d + ((++w % m) < r)); + } + } + return n; +} + +/* + ResizeColumns -- + * Recompute column widths based on available width. + * Pick up slack first; + * Distribute the remainder evenly across stretchable columns; + * If any is still left over due to minwidth constraints, shove left. + */ +static void ResizeColumns(Treeview *tv, int newWidth) +{ + int delta = newWidth - (TreeWidth(tv) + tv->tree.slack); + DepositSlack(tv, + ShoveLeft(tv, tv->tree.nDisplayColumns - 1, + DistributeWidth(tv, PickupSlack(tv, delta)))); +} + +/* + DragColumn -- + * Move the separator to the right of specified column, + * adjusting other column widths as necessary. + */ +static void DragColumn(Treeview *tv, int i, int delta) +{ + TreeColumn *c = tv->tree.displayColumns[i]; + int dl = delta - ShoveLeft(tv, i-1, delta - Stretch(c, delta)); + int dr = ShoveRight(tv, i+1, PickupSlack(tv, -dl)); + DepositSlack(tv, dr); +} + +/*------------------------------------------------------------------------ * +++ Event handlers. */ @@ -758,7 +946,7 @@ static void TreeviewBindEventProc(void *clientData, XEvent *event) * Figure out where to deliver the event. */ - switch (event->type) + switch (event->type) { case KeyPress: case KeyRelease: @@ -823,6 +1011,8 @@ static int TreeviewInitialize(Tcl_Interp *interp, void *recordPtr) = tv->tree.headingLayout = tv->tree.rowLayout = 0; + tv->tree.headingHeight = tv->tree.rowHeight = DEFAULT_ROWHEIGHT; + tv->tree.indent = DEFAULT_INDENT; Tcl_InitHashTable(&tv->tree.columnNames, TCL_STRING_KEYS); tv->tree.nColumns = tv->tree.nDisplayColumns = 0; @@ -853,7 +1043,13 @@ static int TreeviewInitialize(Tcl_Interp *interp, void *recordPtr) /* Scroll handles: */ - tv->tree.yscrollHandle = TtkCreateScrollHandle(&tv->core, &tv->tree.yscroll); + tv->tree.xscrollHandle = TtkCreateScrollHandle(&tv->core,&tv->tree.xscroll); + tv->tree.yscrollHandle = TtkCreateScrollHandle(&tv->core,&tv->tree.yscroll); + + /* Size parameters: + */ + tv->tree.treeArea = tv->tree.headingArea = Ttk_MakeBox(0,0,0,0); + tv->tree.slack = 0; return TCL_OK; } @@ -880,6 +1076,7 @@ static void TreeviewCleanup(void *recordPtr) foreachHashEntry(&tv->tree.items, FreeItemCB); Tcl_DeleteHashTable(&tv->tree.items); + TtkFreeScrollHandle(tv->tree.xscrollHandle); TtkFreeScrollHandle(tv->tree.yscrollHandle); } @@ -905,9 +1102,9 @@ TreeviewConfigure(Tcl_Interp *interp, void *recordPtr, int mask) return TCL_ERROR; } if (mask & SCROLLCMD_CHANGED) { + TtkScrollbarUpdateRequired(tv->tree.xscrollHandle); TtkScrollbarUpdateRequired(tv->tree.yscrollHandle); } - if ( (mask & SHOW_CHANGED) && GetEnumSetFromObj( interp,tv->tree.showObj,showStrings,&showFlags) != TCL_OK) @@ -920,6 +1117,10 @@ TreeviewConfigure(Tcl_Interp *interp, void *recordPtr, int mask) } tv->tree.showFlags = showFlags; + + if (mask & (SHOW_CHANGED | DCOLUMNS_CHANGED)) { + RecomputeSlack(tv); + } return TCL_OK; } @@ -949,7 +1150,7 @@ static int ConfigureItem( /* Validate -image option. */ if (item->imageObj) { - Ttk_ImageSpec *imageSpec = + Ttk_ImageSpec *imageSpec = TtkGetImageSpec(interp, tv->core.tkwin, item->imageObj); if (!imageSpec) { goto error; @@ -1023,11 +1224,16 @@ static int ConfigureColumn( * but only if the widget is currently unmapped, in order to prevent * geometry jumping during interactive column resize. */ - if (mask & GEOMETRY_CHANGED && !Tk_IsMapped(tv->core.tkwin)) { - TtkResizeWidget(&tv->core); + if (mask & GEOMETRY_CHANGED) { + if (!Tk_IsMapped(tv->core.tkwin)) { + TtkResizeWidget(&tv->core); + } + RecomputeSlack(tv); } TtkRedisplayWidget(&tv->core); + assert(SLACKINVARIANT(tv)); + Tk_FreeSavedOptions(&savedOptions); return TCL_OK; @@ -1081,77 +1287,44 @@ error: */ /* + CountRows -- - * Count the number of viewable items. + * Returns the number of viewable rows rooted at item */ static int CountRows(TreeItem *item) { - int height = 1; + int rows = 1; if (item->state & TTK_STATE_OPEN) { TreeItem *child = item->children; while (child) { - height += CountRows(child); + rows += CountRows(child); child = child->next; } } - return height; -} - -/* + TreeWidth -- - * Compute the requested tree width from the sum of visible column widths. - */ -static int TreeWidth(Treeview *tv) -{ - int i = (tv->tree.showFlags&SHOW_TREE) ? 0 : 1; - int width = 0; - - while (i < tv->tree.nDisplayColumns) { - width += tv->tree.displayColumns[i++]->width; - } - return width; -} - -/* + PlaceColumns - - * Adjust final column width to fill available space. - * @@@ NB: still not right -- see paned.c for correct algorithm - */ -static void PlaceColumns(Treeview *tv, int availableWidth) -{ -# define MIN_WIDTH 24 - int colno = (tv->tree.showFlags & SHOW_TREE) ? 0 : 1; - TreeColumn *column = tv->tree.displayColumns[colno]; - - while (++colno < tv->tree.nDisplayColumns) { - availableWidth -= column->width; - column = tv->tree.displayColumns[colno]; - } - column->width = availableWidth; - if (column->width < MIN_WIDTH) { - column->width = MIN_WIDTH; - } + return rows; } /* + IdentifyRow -- * Recursive search for item at specified y position. - * Main work routine for IdentifyItem(() + * Main work routine for IdentifyItem() */ static TreeItem *IdentifyRow( - TreeItem *item, /* where to start search */ + Treeview *tv, /* Widget record */ + TreeItem *item, /* Where to start search */ Ttk_Box *bp, /* Scan position */ - int y) /* target y coordinate */ + int y) /* Target y coordinate */ { while (item) { - int next_ypos = bp->y + ROWHEIGHT; + int next_ypos = bp->y + tv->tree.rowHeight; if (bp->y <= y && y <= next_ypos) { - bp->height = ROWHEIGHT; + bp->height = tv->tree.rowHeight; return item; } bp->y = next_ypos; if (item->state & TTK_STATE_OPEN) { - TreeItem *subitem = IdentifyRow(item->children, bp, y); + TreeItem *subitem = IdentifyRow(tv, item->children, bp, y); if (subitem) { - bp->x += INDENT; - bp->width -= INDENT; + bp->x += tv->tree.indent; + bp->width -= tv->tree.indent; return subitem; } } @@ -1166,12 +1339,13 @@ static TreeItem *IdentifyRow( */ static TreeItem *IdentifyItem(Treeview *tv, int y, Ttk_Box *itemPos) { + int rowHeight = tv->tree.rowHeight; *itemPos = Ttk_MakeBox( - tv->tree.treeArea.x, - tv->tree.treeArea.y - tv->tree.yscroll.first * ROWHEIGHT, - tv->tree.column0.width, - ROWHEIGHT); - return IdentifyRow(tv->tree.root->children, itemPos, y); + tv->tree.treeArea.x, + tv->tree.treeArea.y - tv->tree.yscroll.first * rowHeight, + tv->tree.column0.width, + rowHeight); + return IdentifyRow(tv, tv->tree.root->children, itemPos, y); } /* + IdentifyDisplayColumn -- @@ -1180,7 +1354,7 @@ static TreeItem *IdentifyItem(Treeview *tv, int y, Ttk_Box *itemPos) */ static int IdentifyDisplayColumn(Treeview *tv, int x, int *x1) { - int colno = (tv->tree.showFlags & SHOW_TREE) ? 0 : 1; + int colno = FirstColumn(tv); int xpos = tv->tree.treeArea.x; while (colno < tv->tree.nDisplayColumns) { @@ -1197,36 +1371,19 @@ static int IdentifyDisplayColumn(Treeview *tv, int x, int *x1) return -1; } -/* + SubtreeHeight -- - * Returns the height of the visible subtree rooted at item. - */ -#define ItemHeight(item) (ROWHEIGHT) /* TBFIXED */ -static int SubtreeHeight(TreeItem *item) -{ - int height = ItemHeight(item); - if (item->state & TTK_STATE_OPEN) { - TreeItem *child = item->children; - while (child) { - height += SubtreeHeight(child); - child = child->next; - } - } - return height; -} - -/* + ItemYPosition -- - * Returns Y position of specified item relative to root of tree, +/* + ItemRow -- + * Returns row number of specified item relative to root, * -1 if item is not viewable. */ -static int ItemYPosition(Treeview *tv, TreeItem *p) +static int ItemRow(Treeview *tv, TreeItem *p) { TreeItem *root = tv->tree.root; - int ypos = 0; + int rowNumber = 0; for (;;) { if (p->prev) { p = p->prev; - ypos += SubtreeHeight(p); + rowNumber += CountRows(p); } else { p = p->parent; if (!(p && (p->state & TTK_STATE_OPEN))) { @@ -1234,9 +1391,9 @@ static int ItemYPosition(Treeview *tv, TreeItem *p) return -1; } if (p == root) { - return ypos; + return rowNumber; } - ypos += ItemHeight(p); + ++rowNumber; } } } @@ -1275,11 +1432,13 @@ static Ttk_Layout TreeviewGetLayout( { Treeview *tv = recordPtr; Ttk_Layout treeLayout = TtkWidgetGetLayout(interp, themePtr, recordPtr); + Tcl_Obj *objPtr; + int unused; if (!( - treeLayout + treeLayout && GetSublayout(interp, themePtr, treeLayout, ".Item", - tv->tree.itemOptionTable, &tv->tree.itemLayout) + tv->tree.tagOptionTable, &tv->tree.itemLayout) && GetSublayout(interp, themePtr, treeLayout, ".Cell", tv->tree.tagOptionTable, &tv->tree.cellLayout) /*@@@HERE*/ && GetSublayout(interp, themePtr, treeLayout, ".Heading", @@ -1290,6 +1449,23 @@ static Ttk_Layout TreeviewGetLayout( return 0; } + /* Compute heading height. + */ + Ttk_RebindSublayout(tv->tree.headingLayout, &tv->tree.column0); + Ttk_LayoutSize(tv->tree.headingLayout, 0, &unused, &tv->tree.headingHeight); + + /* Get item height, indent from style: + * @@@ TODO: sanity-check. + */ + tv->tree.rowHeight = DEFAULT_ROWHEIGHT; + tv->tree.indent = DEFAULT_INDENT; + if ((objPtr = Ttk_QueryOption(treeLayout, "-rowheight", 0))) { + (void)Tcl_GetIntFromObj(NULL, objPtr, &tv->tree.rowHeight); + } + if ((objPtr = Ttk_QueryOption(treeLayout, "-indent", 0))) { + (void)Tcl_GetIntFromObj(NULL, objPtr, &tv->tree.indent); + } + return treeLayout; } @@ -1304,51 +1480,59 @@ static Ttk_Layout TreeviewGetLayout( static void TreeviewDoLayout(void *clientData) { Treeview *tv = clientData; - unsigned showFlags = tv->tree.showFlags; Ttk_LayoutNode *clientNode = Ttk_LayoutFindNode(tv->core.layout, "client"); + int visibleRows; + + assert(SLACKINVARIANT(tv)); Ttk_PlaceLayout(tv->core.layout,tv->core.state,Ttk_WinBox(tv->core.tkwin)); tv->tree.treeArea = clientNode ? Ttk_LayoutNodeInternalParcel(tv->core.layout,clientNode) : Ttk_WinBox(tv->core.tkwin) ; - PlaceColumns(tv, tv->tree.treeArea.width); + ResizeColumns(tv, tv->tree.treeArea.width); + assert(SLACKINVARIANT(tv)); - if (showFlags & SHOW_HEADINGS) { + TtkScrolled(tv->tree.xscrollHandle, + tv->tree.xscroll.first, + tv->tree.xscroll.first + tv->tree.treeArea.width, + TreeWidth(tv)); + + tv->tree.treeArea.x -= tv->tree.xscroll.first; + if (tv->tree.showFlags & SHOW_HEADINGS) { tv->tree.headingArea = Ttk_PackBox( - &tv->tree.treeArea, 1, HEADINGHEIGHT, TTK_SIDE_TOP); + &tv->tree.treeArea, 1, tv->tree.headingHeight, TTK_SIDE_TOP); } else { tv->tree.headingArea = Ttk_MakeBox(0,0,0,0); } + visibleRows = tv->tree.treeArea.height / tv->tree.rowHeight; tv->tree.root->state |= TTK_STATE_OPEN; TtkScrolled(tv->tree.yscrollHandle, tv->tree.yscroll.first, - tv->tree.yscroll.first + (tv->tree.treeArea.height / ROWHEIGHT), + tv->tree.yscroll.first + visibleRows, CountRows(tv->tree.root) - 1); + } /* + TreeviewSize -- * SizeProc() widget hook. Size is determined by * -height option and column widths. - * - * <>: Ought to compute extra width and height - * by checking the padding of TTK_OPTION_BORDER elements - * in the layout. In the meantime, just add some extra for slop. */ static int TreeviewSize(void *clientData, int *widthPtr, int *heightPtr) { Treeview *tv = clientData; - int nRows; - int slop = 12; /* NOTE-SLOP */ + int nRows, padHeight, padWidth; - Tk_GetPixelsFromObj(NULL,tv->core.tkwin, tv->tree.heightObj, &nRows); + Ttk_LayoutSize(tv->core.layout, tv->core.state, &padWidth, &padHeight); + Tcl_GetIntFromObj(NULL, tv->tree.heightObj, &nRows); - *widthPtr = TreeWidth(tv) + slop; - *heightPtr = slop + ROWHEIGHT * nRows; + *widthPtr = padWidth + TreeWidth(tv); + *heightPtr = padHeight + tv->tree.rowHeight * nRows; - if (tv->tree.showFlags & SHOW_HEADINGS) - *heightPtr += HEADINGHEIGHT; + if (tv->tree.showFlags & SHOW_HEADINGS) { + *heightPtr += tv->tree.headingHeight; + } return 1; } @@ -1372,7 +1556,7 @@ static Ttk_State ItemState(Treeview *tv, TreeItem *item) */ static void DrawHeadings(Treeview *tv, Drawable d, Ttk_Box b) { - int i = (tv->tree.showFlags & SHOW_TREE) ? 0 : 1; + int i = FirstColumn(tv); int x = 0; while (i < tv->tree.nDisplayColumns) { @@ -1397,7 +1581,7 @@ static void PrepareItem(Treeview *tv, TreeItem *item, DisplayItem *displayItem) memset(displayItem, 0, sizeof(*displayItem)); - if ( item->tagsObj + if ( item->tagsObj && Tcl_ListObjGetElements(NULL, item->tagsObj, &objc, &objv) == TCL_OK) { int i, j; @@ -1426,7 +1610,7 @@ static void DrawCells( Ttk_Layout layout = tv->tree.cellLayout; Ttk_State state = ItemState(tv, item); Ttk_Padding cellPadding = {4, 0, 4, 0}; - int height = ROWHEIGHT; + int rowHeight = tv->tree.rowHeight; int nValues = 0; Tcl_Obj **values = 0; int i; @@ -1443,7 +1627,7 @@ static void DrawCells( for (i = 1; i < tv->tree.nDisplayColumns; ++i) { TreeColumn *column = tv->tree.displayColumns[i]; Ttk_Box parcel = Ttk_PadBox( - Ttk_MakeBox(b.x+x, b.y+y, column->width, height), cellPadding); + Ttk_MakeBox(b.x+x, b.y+y, column->width, rowHeight), cellPadding); displayItem->textObj = column->data; displayItem->anchorObj = column->anchorObj; @@ -1455,17 +1639,15 @@ static void DrawCells( /* + DrawItem -- * Draw an item (row background, tree label, and cells). - * at the specified x, y position. */ static void DrawItem( Treeview *tv, TreeItem *item, Drawable d, Ttk_Box b, int depth, int row) { - Ttk_Layout layout = tv->tree.itemLayout; Ttk_State state = ItemState(tv, item); DisplayItem displayItem; - int height = ROWHEIGHT; - int x = depth * INDENT; - int y = (row - tv->tree.yscroll.first) * ROWHEIGHT; + int rowHeight = tv->tree.rowHeight; + int x = depth * tv->tree.indent; + int y = (row - tv->tree.yscroll.first) * tv->tree.rowHeight; if (row % 2) state |= TTK_STATE_ALTERNATE; @@ -1474,7 +1656,7 @@ static void DrawItem( /* Draw row background: */ { - Ttk_Box rowBox = Ttk_MakeBox(b.x, b.y+y, TreeWidth(tv), height); + Ttk_Box rowBox = Ttk_MakeBox(b.x, b.y+y, TreeWidth(tv), rowHeight); DisplayLayout(tv->tree.rowLayout, &displayItem, state, rowBox, d); } @@ -1482,8 +1664,11 @@ static void DrawItem( */ if (tv->tree.showFlags & SHOW_TREE) { int colwidth = tv->tree.column0.width; - Ttk_Box parcel = Ttk_MakeBox(b.x + x, b.y + y, colwidth - x, height); - DisplayLayout(layout, item, state, parcel, d); + Ttk_Box parcel = Ttk_MakeBox(b.x + x, b.y + y, colwidth - x, rowHeight); + displayItem.textObj = item->textObj; + displayItem.imageObj = item->imageObj; + displayItem.anchorObj = 0; + DisplayLayout(tv->tree.itemLayout, &displayItem, state, parcel, d); x = colwidth; } else { x = 0; @@ -1553,24 +1738,22 @@ static void TreeviewDisplay(void *clientData, Drawable d) */ /* + InsertPosition -- - * Locate the previous sibling for [$tree insert] and [$tree move]. + * Locate the previous sibling for [$tree insert]. * * Returns a pointer to the item just before the specified index, * or 0 if the item is to be inserted at the beginning. */ static TreeItem *InsertPosition(TreeItem *parent, int index) { - TreeItem *sibling = parent->children; - if (sibling) { - while (index > 0 && sibling->next) { - sibling = sibling->next; - --index; - } - if (index <= 0) { - sibling = sibling->prev; - } /* else -- $index > #children, insert at end. */ + TreeItem *prev = 0, *next = parent->children; + + while (next != 0 && index > 0) { + --index; + prev = next; + next = prev->next; } - return sibling; + + return prev; } /* + EndPosition -- @@ -1892,7 +2075,7 @@ static int TreeviewBBoxCommand( Treeview *tv = recordPtr; TreeItem *item = 0; TreeColumn *column = 0; - int ypos; + int row; Ttk_Box bbox; if (objc < 3 || objc > 4) { @@ -1909,22 +2092,21 @@ static int TreeviewBBoxCommand( } /* Compute bounding box of item: - * ALTERNATE: (RowNumber(tv, item) - tv->tree.yscroll.first) * ROWHEIGHT; */ - ypos = ItemYPosition(tv, item) - (ROWHEIGHT * tv->tree.yscroll.first); - if (ypos < 0 || ypos > tv->tree.treeArea.height) { + row = ItemRow(tv, item); + if (row < tv->tree.yscroll.first || row > tv->tree.yscroll.last) { /* not viewable, or off-screen */ return TCL_OK; } bbox = tv->tree.treeArea; - bbox.y += ypos; - bbox.height = ROWHEIGHT; + bbox.y += (row - tv->tree.yscroll.first) * tv->tree.rowHeight; + bbox.height = tv->tree.rowHeight; /* If column has been specified, compute bounding box of cell */ if (column) { - int xpos = 0, i = (tv->tree.showFlags & SHOW_TREE) ? 0 : 1; + int xpos = 0, i = FirstColumn(tv); while (i < tv->tree.nDisplayColumns) { if (tv->tree.displayColumns[i] == column) { break; @@ -1943,7 +2125,7 @@ static int TreeviewBBoxCommand( * @@@ this may or may not be the right thing.) */ if (column == &tv->tree.column0) { - int indent = INDENT * ItemDepth(item); + int indent = tv->tree.indent * ItemDepth(item); bbox.x += indent; bbox.width -= indent; } @@ -2001,8 +2183,11 @@ static int TreeviewHorribleIdentify( detail = dcolbuf; } else if (item) { Ttk_Layout layout = tv->tree.itemLayout; + DisplayItem displayItem; Ttk_LayoutNode *element; - Ttk_RebindSublayout(layout, item); + + PrepareItem(tv, item, &displayItem); /*@@@ FIX: -text, etc*/ + Ttk_RebindSublayout(layout, &displayItem); Ttk_PlaceLayout(layout, ItemState(tv,item), itemBox); element = Ttk_LayoutIdentify(layout, x, y); @@ -2464,16 +2649,27 @@ static int TreeviewMoveCommand( if (!strcmp(Tcl_GetString(objv[4]), "end")) { sibling = EndPosition(parent); } else { + TreeItem *p; int index; - if (Tcl_GetIntFromObj(interp, objv[4], &index) != TCL_OK) + + if (Tcl_GetIntFromObj(interp, objv[4], &index) != TCL_OK) { return TCL_ERROR; - sibling = InsertPosition(parent, index); + } + + sibling = 0; + for (p = parent->children; p != NULL && index > 0; p = p->next) { + if (p != item) { + --index; + } /* else -- moving node forward, count index+1 nodes */ + sibling = p; + } } /* Check ancestry: */ - if (!AncestryCheck(interp, tv, item, parent)) + if (!AncestryCheck(interp, tv, item, parent)) { return TCL_ERROR; + } /* Moving an item after itself is a no-op: */ @@ -2494,6 +2690,13 @@ static int TreeviewMoveCommand( * +++ Widget commands -- scrolling */ +static int TreeviewXViewCommand( + Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], void *recordPtr) +{ + Treeview *tv = recordPtr; + return TtkScrollviewCommand(interp, objc, objv, tv->tree.xscrollHandle); +} + static int TreeviewYViewCommand( Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], void *recordPtr) { @@ -2544,6 +2747,52 @@ static int TreeviewSeeCommand( } /*------------------------------------------------------------------------ + * +++ Widget commands -- interactive column resize + */ + +/* + $tree drag $column $newX -- + * Set right edge of display column $column to x position $X + */ +static int TreeviewDragCommand( + Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], void *recordPtr) +{ + Treeview *tv = recordPtr; + int left = tv->tree.treeArea.x; + int i = FirstColumn(tv); + TreeColumn *column; + int newx; + + if (objc != 4) { + Tcl_WrongNumArgs(interp, 2, objv, "column xposition"); + return TCL_ERROR; + } + + if ( (column = FindColumn(interp, tv, objv[2])) == 0 + || Tcl_GetIntFromObj(interp, objv[3], &newx) != TCL_OK) + { + return TCL_ERROR; + } + + for (;i < tv->tree.nDisplayColumns; ++i) { + TreeColumn *c = tv->tree.displayColumns[i]; + int right = left + c->width; + if (c == column) { + DragColumn(tv, i, newx - right); + assert(SLACKINVARIANT(tv)); + TtkRedisplayWidget(&tv->core); + return TCL_OK; + } + left = right; + } + + Tcl_ResetResult(interp); + Tcl_AppendResult(interp, + "column ", Tcl_GetString(objv[2]), " is not displayed", + NULL); + return TCL_ERROR; +} + +/*------------------------------------------------------------------------ * +++ Widget commands -- focus and selection */ @@ -2755,6 +3004,7 @@ static WidgetCommandSpec TreeviewCommands[] = { "configure", TtkWidgetConfigureCommand }, { "delete", TreeviewDeleteCommand }, { "detach", TreeviewDetachCommand }, + { "drag", TreeviewDragCommand }, { "exists", TreeviewExistsCommand }, { "focus", TreeviewFocusCommand }, { "heading", TreeviewHeadingCommand }, @@ -2772,6 +3022,7 @@ static WidgetCommandSpec TreeviewCommands[] = { "set", TreeviewSetCommand }, { "state", TtkWidgetStateCommand }, { "tag", TreeviewTagCommand }, + { "xview", TreeviewXViewCommand }, { "yview", TreeviewYViewCommand }, { NULL, NULL } }; @@ -2816,14 +3067,15 @@ TTK_END_LAYOUT TTK_BEGIN_LAYOUT(CellLayout) TTK_GROUP("Treedata.padding", TTK_FILL_BOTH, - TTK_NODE("Treeitem.label", TTK_FILL_BOTH)) + TTK_NODE("Treeitem.text", TTK_FILL_BOTH)) TTK_END_LAYOUT TTK_BEGIN_LAYOUT(HeadingLayout) TTK_NODE("Treeheading.cell", TTK_FILL_BOTH) TTK_GROUP("Treeheading.border", TTK_FILL_BOTH, - TTK_NODE("Treeheading.image", TTK_PACK_RIGHT) - TTK_NODE("Treeheading.text", TTK_FILL_X)) + TTK_GROUP("Treeheading.padding", TTK_FILL_BOTH, + TTK_NODE("Treeheading.image", TTK_PACK_RIGHT) + TTK_NODE("Treeheading.text", TTK_FILL_X))) TTK_END_LAYOUT TTK_BEGIN_LAYOUT(RowLayout) diff --git a/library/ttk/altTheme.tcl b/library/ttk/altTheme.tcl index b1bbc65..62a0607 100644 --- a/library/ttk/altTheme.tcl +++ b/library/ttk/altTheme.tcl @@ -1,5 +1,5 @@ # -# $Id: altTheme.tcl,v 1.2 2006/11/24 18:04:14 jenglish Exp $ +# $Id: altTheme.tcl,v 1.3 2006/12/18 19:33:14 jenglish Exp $ # # Ttk widget set: Alternate theme # @@ -9,6 +9,7 @@ namespace eval ttk::theme::alt { variable colors array set colors { -frame "#d9d9d9" + -window "#ffffff" -darker "#c3c3c3" -activebg "#ececec" -disabledfg "#a3a3a3" @@ -77,6 +78,20 @@ namespace eval ttk::theme::alt { -expand [list selected {2 2 1 0}] \ ; + # Treeview: + style configure Heading -font TkHeadingFont -relief raised + style configure Row -background $colors(-window) + style configure Cell -background $colors(-window) + style map Row \ + -background [list selected $colors(-selectbg)] \ + -foreground [list selected $colors(-selectfg)] ; + style map Cell \ + -background [list selected $colors(-selectbg)] \ + -foreground [list selected $colors(-selectfg)] ; + style map Item \ + -background [list selected $colors(-selectbg)] \ + -foreground [list selected $colors(-selectfg)] ; + style configure TScale \ -groovewidth 4 -troughrelief sunken \ -sliderwidth raised -borderwidth 2 diff --git a/library/ttk/aquaTheme.tcl b/library/ttk/aquaTheme.tcl index 4b4ad5e..f0f63aa 100644 --- a/library/ttk/aquaTheme.tcl +++ b/library/ttk/aquaTheme.tcl @@ -1,5 +1,5 @@ # -# $Id: aquaTheme.tcl,v 1.1 2006/10/31 01:42:26 hobbs Exp $ +# $Id: aquaTheme.tcl,v 1.2 2006/12/18 19:33:14 jenglish Exp $ # # Ttk widget set: Aqua theme (OSX native look and feel) # @@ -38,6 +38,16 @@ namespace eval ttk { style configure TNotebook -tabposition n -padding {20 12} style configure TNotebook.Tab -padding {10 2 10 2} + # Treeview: + style configure Treeview -rowheight 18 + style configure Heading -font TkHeadingFont + style map Row -background [list \ + {selected background} "#c3c3c3" selected SystemHighlight] ; + style map Cell -foreground [list \ + {selected background} "#000000" selected SystemHighlightText] ; + style map Item -foreground [list \ + {selected background} "#000000" selected SystemHighlightText] ; + # Enable animation for ttk::progressbar widget: style configure TProgressbar -period 100 -maxphase 255 @@ -56,5 +66,6 @@ namespace eval ttk { # style configure TLabelframe \ -labeloutside true -labelmargins {14 0 14 4} + } } diff --git a/library/ttk/clamTheme.tcl b/library/ttk/clamTheme.tcl index 9061006..930ec97 100644 --- a/library/ttk/clamTheme.tcl +++ b/library/ttk/clamTheme.tcl @@ -1,5 +1,5 @@ # -# $Id: clamTheme.tcl,v 1.3 2006/12/13 17:06:32 jenglish Exp $ +# $Id: clamTheme.tcl,v 1.4 2006/12/18 19:33:14 jenglish Exp $ # # "Clam" theme. # @@ -10,8 +10,8 @@ namespace eval ttk::theme::clam { variable colors array set colors { -disabledfg "#999999" - -frame "#dcdad5" + -window "#ffffff" -dark "#cfcdc8" -darker "#bab5ab" -darkest "#9e9a91" @@ -111,6 +111,21 @@ namespace eval ttk::theme::clam { -lightcolor [list selected $colors(-lighter) {} $colors(-dark)] \ ; + # Treeview: + ttk::style configure Heading \ + -font TkHeadingFont -relief raised -padding {3} + ttk::style configure Row -background $colors(-window) + ttk::style configure Cell -background $colors(-window) + ttk::style map Row \ + -background [list selected $colors(-selectbg)] \ + -foreground [list selected $colors(-selectfg)] ; + ttk::style map Cell \ + -background [list selected $colors(-selectbg)] \ + -foreground [list selected $colors(-selectfg)] ; + ttk::style map Item \ + -background [list selected $colors(-selectbg)] \ + -foreground [list selected $colors(-selectfg)] ; + ttk::style configure TLabelframe \ -labeloutside true -labelmargins {0 0 0 4} \ -borderwidth 2 -relief raised diff --git a/library/ttk/classicTheme.tcl b/library/ttk/classicTheme.tcl index 5e29787..2061b4e 100644 --- a/library/ttk/classicTheme.tcl +++ b/library/ttk/classicTheme.tcl @@ -1,5 +1,5 @@ # -# $Id: classicTheme.tcl,v 1.2 2006/11/24 18:04:14 jenglish Exp $ +# $Id: classicTheme.tcl,v 1.3 2006/12/18 19:33:14 jenglish Exp $ # # "classic" Tk theme. # @@ -10,6 +10,7 @@ namespace eval ttk::theme::classic { variable colors; array set colors { -frame "#d9d9d9" + -window "#ffffff" -activebg "#ececec" -troughbg "#c3c3c3" -selectbg "#c3c3c3" @@ -84,6 +85,17 @@ namespace eval ttk::theme::classic { -background $colors(-troughbg) style map TNotebook.Tab -background [list selected $colors(-frame)] + # Treeview: + ttk::style configure Heading -font TkHeadingFont -relief raised + ttk::style configure Row -background $colors(-window) + ttk::style configure Cell -background $colors(-window) + ttk::style map Row \ + -background [list selected $colors(-selectbg)] \ + -foreground [list selected $colors(-selectfg)] ; + ttk::style map Cell \ + -background [list selected $colors(-selectbg)] \ + -foreground [list selected $colors(-selectfg)] ; + # # Toolbar buttons: # diff --git a/library/ttk/defaults.tcl b/library/ttk/defaults.tcl index 0869fd3..d076d8e 100644 --- a/library/ttk/defaults.tcl +++ b/library/ttk/defaults.tcl @@ -1,5 +1,5 @@ # -# $Id: defaults.tcl,v 1.3 2006/12/13 17:06:32 jenglish Exp $ +# $Id: defaults.tcl,v 1.4 2006/12/18 19:33:14 jenglish Exp $ # # Settings for default theme. # @@ -8,6 +8,7 @@ namespace eval ttk::theme::default { variable colors array set colors { -frame "#d9d9d9" + -window "#ffffff" -activebg "#ececec" -selectbg "#4a6984" -selectfg "#ffffff" @@ -80,6 +81,21 @@ namespace eval ttk::theme::default { ttk::style map TNotebook.Tab \ -background [list selected $colors(-frame)] + # Treeview. + # + ttk::style configure Heading -font TkHeadingFont -relief raised + ttk::style configure Row -background $colors(-window) + ttk::style configure Cell -background $colors(-window) + ttk::style map Row \ + -background [list selected $colors(-selectbg)] \ + -foreground [list selected $colors(-selectfg)] ; + ttk::style map Cell \ + -background [list selected $colors(-selectbg)] \ + -foreground [list selected $colors(-selectfg)] ; + ttk::style map Item \ + -background [list selected $colors(-selectbg)] \ + -foreground [list selected $colors(-selectfg)] ; + # # Toolbar buttons: # diff --git a/library/ttk/treeview.tcl b/library/ttk/treeview.tcl index 265f34c..3ccb746 100644 --- a/library/ttk/treeview.tcl +++ b/library/ttk/treeview.tcl @@ -1,7 +1,6 @@ +# $Id: treeview.tcl,v 1.2 2006/12/18 19:33:14 jenglish Exp $ # -# $Id: treeview.tcl,v 1.1 2006/10/31 01:42:27 hobbs Exp $ -# -# Ttk widget set -- bindings for Treeview widget. +# ttk::treeview widget bindings and utilities. # namespace eval ttk::treeview { @@ -18,9 +17,7 @@ namespace eval ttk::treeview { set State(pressX) 0 # For pressMode == "resize" - set State(minWidth) 24 set State(resizeColumn) #0 - set State(resizeWidth) 0 # For pressmode == "heading" set State(heading) {} @@ -217,24 +214,15 @@ proc ttk::treeview::Release {w x y} { ### Interactive column resizing. # -# @@@ needs work. -# proc ttk::treeview::resize.press {w x column} { variable State - set State(pressMode) "resize" - set State(pressX) $x set State(resizeColumn) $column - set State(resizeWidth) [$w column $column -width] } proc ttk::treeview::resize.drag {w x} { variable State - set newWidth [expr {$State(resizeWidth) + $x - $State(pressX)}] - if {$newWidth < $State(minWidth)} { - set newWidth $State(minWidth) - } - $w column $State(resizeColumn) -width $newWidth + $w drag $State(resizeColumn) $x } proc ttk::treeview::resize.release {w x} { @@ -391,33 +379,4 @@ proc ttk::treeview::BrowseTo {w item} { $w selection set [list $item] } -### Style settings for selected built-in themes. -# -# Do this here instead of in the theme definitions since the details are -# likely to change; it's better to keep this all in one place for now. -# -namespace eval ::ttk::treeview { - variable theme - namespace import -force ::ttk::style - foreach theme [style theme names] { - style theme settings $theme { - style map Item -foreground [list selected "#FFFFFF"] - style configure Row -background "#EEEEEE" - style configure Heading -relief raised -font TkHeadingFont - style configure Item -justify left - style map Heading -relief { - pressed sunken - } - style map Row -background { - selected #4a6984 - focus #ccccff - alternate #FFFFFF - } - style map Cell -foreground { - selected #FFFFFF - } - } - } -} - #*EOF* diff --git a/library/ttk/winTheme.tcl b/library/ttk/winTheme.tcl index 9678b10..34a6bc3 100644 --- a/library/ttk/winTheme.tcl +++ b/library/ttk/winTheme.tcl @@ -1,5 +1,5 @@ # -# $Id: winTheme.tcl,v 1.2 2006/11/24 18:04:14 jenglish Exp $ +# $Id: winTheme.tcl,v 1.3 2006/12/18 19:33:14 jenglish Exp $ # # Ttk widget set: Windows Native theme # @@ -57,6 +57,20 @@ namespace eval ttk { style configure TNotebook.Tab -padding {3 1} -borderwidth 1 style map TNotebook.Tab -expand [list selected {2 2 2 0}] + # Treeview: + style configure Heading -font TkHeadingFont -relief raised + style configure Row -background SystemWindow + style configure Cell -background SystemWindow + style map Row \ + -background [list selected SystemHighlight] \ + -foreground [list selected SystemHighlightText] ; + style map Cell \ + -background [list selected SystemHighlight] \ + -foreground [list selected SystemHighlightText] ; + style map Item \ + -background [list selected SystemHighlight] \ + -foreground [list selected SystemHighlightText] ; + style configure TProgressbar -borderwidth 0 -background SystemHighlight } } diff --git a/library/ttk/xpTheme.tcl b/library/ttk/xpTheme.tcl index 9bb8b8b..5320b85 100644 --- a/library/ttk/xpTheme.tcl +++ b/library/ttk/xpTheme.tcl @@ -1,5 +1,5 @@ # -# $Id: xpTheme.tcl,v 1.2 2006/11/24 18:04:14 jenglish Exp $ +# $Id: xpTheme.tcl,v 1.3 2006/12/18 19:33:14 jenglish Exp $ # # Ttk widget set: XP Native theme # @@ -30,6 +30,20 @@ namespace eval ttk { style map TNotebook.Tab \ -expand [list selected {2 2 2 2}] + # Treeview: + style configure Heading -font TkHeadingFont + style configure Row -background SystemWindow + style configure Cell -background SystemWindow + style map Row \ + -background [list selected SystemHighlight] \ + -foreground [list selected SystemHighlightText] ; + style map Cell \ + -background [list selected SystemHighlight] \ + -foreground [list selected SystemHighlightText] ; + style map Item \ + -background [list selected SystemHighlight] \ + -foreground [list selected SystemHighlightText] ; + style configure TLabelframe -foreground "#0046d5" # OR: -padding {3 3 3 6}, which some apps seem to use. diff --git a/macosx/ttkMacOSXTheme.c b/macosx/ttkMacOSXTheme.c index 7cd46ae..47dca7b 100644 --- a/macosx/ttkMacOSXTheme.c +++ b/macosx/ttkMacOSXTheme.c @@ -1,5 +1,5 @@ /* - * $Id: ttkMacOSXTheme.c,v 1.3 2006/11/03 03:06:22 das Exp $ + * $Id: ttkMacOSXTheme.c,v 1.4 2006/12/18 19:33:14 jenglish Exp $ * * Tk theme engine for Mac OSX, using the Appearance Manager API. * @@ -46,6 +46,13 @@ Rect BoxToRect(Ttk_Box b) return rect; } +/* DontErase -- + * No-op ThemeEraseProc, can be passed to DrawThemeButton &c. + */ +static void DontErase( + const Rect *bounds, UInt32 eraseData, SInt16 depth, Boolean isColorDev) +{ } + #define BEGIN_DRAWING(d) { \ CGrafPtr saveWorld; GDHandle saveDevice; \ GetGWorld(&saveWorld, &saveDevice); \ @@ -94,6 +101,7 @@ static ThemeButtonParms RadioButtonParms = { kThemeRadioButton, kThemeMetricRadioButtonHeight }, BevelButtonParms = { kThemeBevelButton, NoThemeMetric }, PopupButtonParms = { kThemePopupButton, NoThemeMetric }, + DisclosureParms = { kThemeDisclosureButton, kThemeMetricDisclosureTriangleHeight }, ListHeaderParms = { kThemeListHeaderButton, kThemeMetricListHeaderHeight }; static Ttk_StateTable ButtonValueTable[] = { @@ -866,6 +874,53 @@ static Ttk_ElementSpec TreeHeaderElementSpec = 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; + GetThemeMetric(kThemeMetricDisclosureTriangleWidth, &s); *widthPtr = s; + GetThemeMetric(kThemeMetricDisclosureTriangleHeight, &s); *heightPtr = s; +} + +static void DisclosureElementDraw( + void *clientData, void *elementRecord, Tk_Window tkwin, + Drawable d, Ttk_Box b, Ttk_State state) +{ + Rect bounds = BoxToRect(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) + DrawThemeButton(&bounds, kThemeDisclosureTriangle, &info, + NULL/*prevInfo*/,DontErase,NULL/*labelProc*/,0/*userData*/); + END_DRAWING +} + +static Ttk_ElementSpec DisclosureElementSpec = +{ + TK_STYLE_VERSION_2, + sizeof(NullElement), + TtkNullElementOptions, + DisclosureElementSize, + DisclosureElementDraw +}; + /*---------------------------------------------------------------------- * +++ Widget layouts. */ @@ -944,6 +999,8 @@ static int AquaTheme_Init(Tcl_Interp *interp) &ButtonElementSpec, &BevelButtonParms); Ttk_RegisterElementSpec(themePtr, "Menubutton.button", &ButtonElementSpec, &PopupButtonParms); + Ttk_RegisterElementSpec(themePtr, "Treeitem.indicator", + &DisclosureElementSpec, &DisclosureParms); Ttk_RegisterElementSpec(themePtr, "Treeheading.cell", &TreeHeaderElementSpec, &ListHeaderParms); -- cgit v0.12