summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjenglish <jenglish@flightlab.com>2008-05-23 20:20:05 (GMT)
committerjenglish <jenglish@flightlab.com>2008-05-23 20:20:05 (GMT)
commitee1814c0cdbcfe9807b18e2b2732c299789897a3 (patch)
tree38468a3e3f80fe6a337d7e5bef1503a0780d1797
parentc2ee900569916fac1b939549e153c9344dca8c0a (diff)
downloadtk-ee1814c0cdbcfe9807b18e2b2732c299789897a3.zip
tk-ee1814c0cdbcfe9807b18e2b2732c299789897a3.tar.gz
tk-ee1814c0cdbcfe9807b18e2b2732c299789897a3.tar.bz2
Batch of ttk::treeview enhancements:
+ Added [$tv identify region], [$tv identify element], and [$tv identify item] subcommands. + Simplified bindings. + Added [$tv tag has] subcommand. + Tag-related display improvements: setting a tag -background or -foreground no longer overrides selection feedback. + Don't need separate 'Item', 'Cell', and 'Row' style settings anymore, only the base "Treeview" style is used.
-rw-r--r--ChangeLog23
-rw-r--r--doc/ttk_treeview.n44
-rw-r--r--generic/ttk/ttkLayout.c23
-rw-r--r--generic/ttk/ttkTagSet.c191
-rw-r--r--generic/ttk/ttkTheme.c53
-rw-r--r--generic/ttk/ttkTheme.h7
-rw-r--r--generic/ttk/ttkThemeInt.h3
-rw-r--r--generic/ttk/ttkTreeview.c591
-rw-r--r--generic/ttk/ttkWidget.h33
-rw-r--r--library/ttk/altTheme.tcl13
-rw-r--r--library/ttk/aquaTheme.tcl10
-rw-r--r--library/ttk/clamTheme.tcl13
-rw-r--r--library/ttk/classicTheme.tcl10
-rw-r--r--library/ttk/defaults.tcl19
-rw-r--r--library/ttk/treeview.tcl53
-rw-r--r--library/ttk/winTheme.tcl13
-rw-r--r--library/ttk/xpTheme.tcl13
-rw-r--r--tests/ttk/treeview.test116
18 files changed, 782 insertions, 446 deletions
diff --git a/ChangeLog b/ChangeLog
index 513d8a0..d8aefff 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,28 @@
2008-05-23 Joe English <jenglish@users.sourceforge.net>
+ * doc/ttk_treeview.n, generic/ttk/ttkTreeview.c,
+ generic/ttk/ttkTagSet.c, generic/ttk/ttkLayout.c,
+ generic/ttk/ttkTheme.c, generic/ttk/ttkTheme.h,
+ generic/ttk/ttkThemeInt.h, generic/ttk/ttkWidget.h:
+
+ Added [$tv identify region], [$tv identify element],
+ and [$tv identify item] subcommands. Simplified
+ bindings. Added [$tv tag has] subcommand. Tag-related
+ display improvements; setting a tag -background or -foreground
+ no longer overrides selection feedback.
+
+
+ * library/ttk/altTheme.tcl, library/ttk/aquaTheme.tcl,
+ library/ttk/clamTheme.tcl, library/ttk/classicTheme.tcl,
+ library/ttk/defaults.tcl, library/ttk/treeview.tcl,
+ library/ttk/winTheme.tcl, library/ttk/xpTheme.tcl:
+
+ Don't need separate 'Item', 'Cell', and 'Row' style
+ settings anymore, only the base "Treeview" style is used.
+
+
+2008-05-23 Joe English <jenglish@users.sourceforge.net>
+
* generic/ttk/ttkLabel.c: Avoid passing width or height <= 0 to
Tk_RedrawImage, as this leads to a panic on Windows [Bug 1967576]
diff --git a/doc/ttk_treeview.n b/doc/ttk_treeview.n
index fbe84b1..e2ecc4c 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.17 2008/01/29 15:38:00 dkf Exp $
+'\" RCS: @(#) $Id: ttk_treeview.n,v 1.18 2008/05/23 20:20:05 jenglish Exp $
'\"
.so man.macros
.TH ttk::treeview n 8.5 Tk "Tk Themed Widget"
@@ -58,11 +58,8 @@ A list of column identifiers
specifying which data columns are displayed
and the order in which they appear,
or the string \fB#all\fP.
-.RS
-.PP
-If set to \fB#all\fP (the default), all columns are shown in the order
-given.
-.RE
+If set to \fB#all\fP (the default),
+all columns are shown in the order given.
.OP \-height height Height
Specifies the number of rows which should be visible.
Note:
@@ -104,7 +101,7 @@ Returns the bounding box (relative to the treeview widget's window)
of the specified \fIitem\fR
in the form \fIx y width height\fR.
If \fIcolumn\fR is specified, returns the bounding box of that cell.
-If the \fIitem\fR is not visible
+If the \fIitem\fR is not visible
(i.e., if it is a descendant of a closed item or is scrolled offscreen),
returns the empty list.
.TP
@@ -215,12 +212,35 @@ or the empty string if no such \fIcomponent\fR is present at that position.
The following subcommands are supported:
.RS
.TP
-\fIpathname \fBidentify row\fR \fIx y\fR
+\fIpathname \fBidentify region\fR \fI x y\fR
+.RS
+Returns one of:
+.IP heading
+Tree heading area;
+use [\fBpathname identify column \fIx y\fR]
+to determine the heading number.
+.IP separator
+Space between two column headings;
+[\fBpathname identify column \fIx y\fR]
+will return the display column identifier
+of the heading to left of the separator.
+.IP tree
+The tree area.
+.IP cell
+A data cell.
+.RE
+\fIpathname \fBidentify item\fR \fIx y\fR
Returns the item ID of the item at position \fIy\fR.
.TP
\fIpathname \fBidentify column\fR \fIx y\fR
Returns the data column identifier of the cell at position \fIx\fR.
The tree column has ID \fB#0\fR.
+.TP
+\fIpathname \fBidentify element\fR \fIx y\fR
+The element at position \fIx,y\fR.
+.TP
+\fIpathname \fBidentify row\fR \fIx y\fR
+Obsolescent synonym for \fIpathname \fBidentify item\fR.
.PP
See \fBCOLUMN IDENTIFIERS\fR for a discussion of display columns
and data columns.
@@ -310,7 +330,7 @@ Toggle the selection state of each item in \fIitemList\fR.
.TP
\fIpathname \fBset\fR \fIitem\fR ?\fIcolumn\fR? ?\fIvalue\fR?
With one argument, returns a dictionary of column/value pairs
-for the specified \fIitem\fR.
+for the specified \fIitem\fR.
With two arguments, returns the current value of the specified \fIcolumn\fR.
With three arguments, sets the value of column \fIcolumn\fR
in item \fIitem\fR to the specified \fIvalue\fR.
@@ -349,6 +369,12 @@ returns the value of that option
With no additional arguments,
returns a dictionary of the option settings for \fItagName\fR.
See \fBTAG OPTIONS\fR for the list of available options.
+.TP
+\fIpathName \fBtag has\fR \fItagName\fR ?\fIitem\fR?
+If \fIitem\fR is specified, returns 1 or 0
+depending on whether the specified item has the named tag.
+Otherwise, returns a list of all items which have
+the specified tag.
.RE
.TP
\fIpathName \fBxview \fIargs\fR
diff --git a/generic/ttk/ttkLayout.c b/generic/ttk/ttkLayout.c
index bfa10c4..c1e239a 100644
--- a/generic/ttk/ttkLayout.c
+++ b/generic/ttk/ttkLayout.c
@@ -5,7 +5,7 @@
*
* Copyright (c) 2003 Joe English. Freely redistributable.
*
- * $Id: ttkLayout.c,v 1.11 2007/12/13 15:26:26 dgp Exp $
+ * $Id: ttkLayout.c,v 1.12 2008/05/23 20:20:05 jenglish Exp $
*/
#include <string.h>
@@ -47,8 +47,6 @@ Ttk_NewBoxObj(Ttk_Box box)
return Tcl_NewListObj(4, result);
}
-
-
/*
* packTop, packBottom, packLeft, packRight --
* Carve out a parcel of the specified height (resp width)
@@ -768,7 +766,7 @@ void Ttk_RegisterLayouts(Ttk_Theme theme, Ttk_LayoutSpec spec)
}
}
-Tcl_Obj *Ttk_UnparseLayoutTemplate(Ttk_TemplateNode *node)
+Tcl_Obj *Ttk_UnparseLayoutTemplate(Ttk_TemplateNode *node)
{
Tcl_Obj *result = Tcl_NewListObj(0,0);
@@ -785,14 +783,14 @@ Tcl_Obj *Ttk_UnparseLayoutTemplate(Ttk_TemplateNode *node)
*/
if (flags & TTK_EXPAND) {
APPENDSTR("-expand");
- APPENDSTR("1");
+ APPENDSTR("1");
} else {
if (flags & _TTK_MASK_PACK) {
int side = 0;
unsigned sideFlags = flags & _TTK_MASK_PACK;
while ((sideFlags & TTK_PACK_LEFT) == 0) {
- ++side;
+ ++side;
sideFlags >>= 1;
}
APPENDSTR("-side");
@@ -891,7 +889,7 @@ Ttk_Layout Ttk_CreateLayout(
* Creates a new sublayout.
*
* Sublayouts are used to draw subparts of a compound widget.
- * They use the same Tk_Window, but a different option table
+ * They use the same Tk_Window, but a different option table
* and data record.
*/
Ttk_Layout
@@ -924,7 +922,7 @@ Ttk_CreateSublayout(
Tcl_DStringFree(&buf);
return TTKNewLayout(
- style, 0, optionTable, parentLayout->tkwin,
+ style, 0, optionTable, parentLayout->tkwin,
Ttk_InstantiateLayout(themePtr, layoutTemplate));
}
@@ -947,6 +945,15 @@ Tcl_Obj *Ttk_QueryOption(
layout->style,layout->recordPtr,layout->optionTable,optionName,state);
}
+/*
+ * Ttk_LayoutStyle --
+ * Extract Ttk_Style from Ttk_Layout.
+ */
+Ttk_Style Ttk_LayoutStyle(Ttk_Layout layout)
+{
+ return layout->style;
+}
+
/*------------------------------------------------------------------------
* +++ Size computation.
*/
diff --git a/generic/ttk/ttkTagSet.c b/generic/ttk/ttkTagSet.c
index 85624a2..d925a78 100644
--- a/generic/ttk/ttkTagSet.c
+++ b/generic/ttk/ttkTagSet.c
@@ -1,6 +1,6 @@
-/* $Id: ttkTagSet.c,v 1.3 2007/01/11 19:59:26 jenglish Exp $
+/* $Id: ttkTagSet.c,v 1.4 2008/05/23 20:20:05 jenglish Exp $
*
- * Ttk widget set: tag tables. Half-baked, work in progress.
+ * Tag tables. 3/4-baked, work in progress.
*
* Copyright (C) 2005, Joe English. Freely redistributable.
*/
@@ -16,12 +16,16 @@
* +++ Internal data structures.
*/
struct TtkTag {
- Tcl_Obj **tagRecord; /* ... hrmph. */
+ int priority; /* 1=>highest */
+ void *tagRecord;
};
struct TtkTagTable {
- Tk_OptionTable tagOptionTable; /* ... */
- int tagRecordSize; /* size of tag record */
+ Tk_Window tkwin; /* owner window */
+ Tk_OptionSpec *optionSpecs; /* ... */
+ Tk_OptionTable optionTable; /* ... */
+ int recordSize; /* size of tag record */
+ int nTags; /* #tags defined so far */
Tcl_HashTable tags; /* defined tags */
};
@@ -31,38 +35,34 @@ struct TtkTagTable {
static Ttk_Tag NewTag(Ttk_TagTable tagTable)
{
Ttk_Tag tag = (Ttk_Tag)ckalloc(sizeof(*tag));
- tag->tagRecord = (Tcl_Obj **)ckalloc(tagTable->tagRecordSize);
- memset(tag->tagRecord, 0, tagTable->tagRecordSize);
+ tag->tagRecord = ckalloc(tagTable->recordSize);
+ memset(tag->tagRecord, 0, tagTable->recordSize);
+ /* Don't need Tk_InitOptions() here, all defaults should be NULL. */
+ tag->priority = ++tagTable->nTags;
return tag;
}
-static void DeleteTag(Ttk_Tag tag, int nOptions)
+static void DeleteTag(Ttk_TagTable tagTable, Ttk_Tag tag)
{
- int i;
- for (i = 0; i < nOptions; ++i) {
- if (tag->tagRecord[i]) {
- Tcl_DecrRefCount(tag->tagRecord[i]);
- }
- }
- ckfree((void*)tag->tagRecord);
+ Tk_FreeConfigOptions(tag->tagRecord,tagTable->optionTable,tagTable->tkwin);
+ ckfree(tag->tagRecord);
ckfree((void*)tag);
}
-Tcl_Obj **Ttk_TagRecord(Ttk_Tag tag)
-{
- return tag->tagRecord;
-}
-
/*------------------------------------------------------------------------
* +++ Tag tables.
*/
Ttk_TagTable Ttk_CreateTagTable(
- Tk_OptionTable tagOptionTable, int tagRecordSize)
+ Tcl_Interp *interp, Tk_Window tkwin,
+ Tk_OptionSpec optionSpecs[], int recordSize)
{
Ttk_TagTable tagTable = (Ttk_TagTable)ckalloc(sizeof(*tagTable));
- tagTable->tagOptionTable = tagOptionTable;
- tagTable->tagRecordSize = tagRecordSize;
+ tagTable->tkwin = tkwin;
+ tagTable->optionSpecs = optionSpecs;
+ tagTable->optionTable = Tk_CreateOptionTable(interp, optionSpecs);
+ tagTable->recordSize = recordSize;
+ tagTable->nTags = 0;
Tcl_InitHashTable(&tagTable->tags, TCL_STRING_KEYS);
return tagTable;
}
@@ -71,11 +71,10 @@ void Ttk_DeleteTagTable(Ttk_TagTable tagTable)
{
Tcl_HashSearch search;
Tcl_HashEntry *entryPtr;
- int nOptions = tagTable->tagRecordSize / sizeof(Tcl_Obj *);
entryPtr = Tcl_FirstHashEntry(&tagTable->tags, &search);
while (entryPtr != NULL) {
- DeleteTag(Tcl_GetHashValue(entryPtr), nOptions);
+ DeleteTag(tagTable, Tcl_GetHashValue(entryPtr));
entryPtr = Tcl_NextHashEntry(&search);
}
@@ -100,48 +99,144 @@ Ttk_Tag Ttk_GetTagFromObj(Ttk_TagTable tagTable, Tcl_Obj *objPtr)
return Ttk_GetTag(tagTable, Tcl_GetString(objPtr));
}
-/* Ttk_GetTagListFromObj --
+/*------------------------------------------------------------------------
+ * +++ Tag sets.
+ */
+
+/* Ttk_GetTagSetFromObj --
* Extract an array of pointers to Ttk_Tags from a Tcl_Obj.
- * (suitable for passing to Tk_BindEvent).
+ * objPtr may be NULL, in which case a new empty tag set is returned.
*
- * Result must be passed to Ttk_FreeTagList().
+ * Returns NULL and leaves an error message in interp->result on error.
+ *
+ * Non-NULL results must be passed to Ttk_FreeTagSet().
*/
-extern int Ttk_GetTagListFromObj(
- Tcl_Interp *interp,
- Ttk_TagTable tagTable,
- Tcl_Obj *objPtr,
- int *nTags_rtn,
- void **taglist_rtn)
+Ttk_TagSet Ttk_GetTagSetFromObj(
+ Tcl_Interp *interp, Ttk_TagTable tagTable, Tcl_Obj *objPtr)
{
+ Ttk_TagSet tagset = (Ttk_TagSet)(ckalloc(sizeof *tagset));
Tcl_Obj **objv;
int i, objc;
- void **tags;
-
- *taglist_rtn = NULL; *nTags_rtn = 0;
if (objPtr == NULL) {
- return TCL_OK;
+ tagset->tags = NULL;
+ tagset->nTags = 0;
+ return tagset;
}
if (Tcl_ListObjGetElements(interp, objPtr, &objc, &objv) != TCL_OK) {
- return TCL_ERROR;
+ ckfree((ClientData)tagset);
+ return NULL;
}
- tags = (void**)ckalloc((objc+1) * sizeof(void*));
+ tagset->tags = (Ttk_Tag*)ckalloc((objc+1) * sizeof(Ttk_Tag));
for (i=0; i<objc; ++i) {
- tags[i] = Ttk_GetTagFromObj(tagTable, objv[i]);
+ tagset->tags[i] = Ttk_GetTagFromObj(tagTable, objv[i]);
}
- tags[i] = NULL;
+ tagset->tags[i] = NULL;
+ tagset->nTags = objc;
+
+ return tagset;
+}
+
+void Ttk_FreeTagSet(Ttk_TagSet tagset)
+{
+ ckfree((ClientData)tagset->tags);
+ ckfree((ClientData)tagset);
+}
+
+/* Ttk_TagSetContains -- test if tag set contains a tag.
+ */
+int Ttk_TagSetContains(Ttk_TagSet tagset, Ttk_Tag tag)
+{
+ int i;
+ for (i = 0; i < tagset->nTags; ++i) {
+ if (tagset->tags[i] == tag) {
+ return 1;
+ }
+ }
+ return 0;
+}
- *taglist_rtn = tags;
- *nTags_rtn = objc;
+/*------------------------------------------------------------------------
+ * +++ Utilities for widget commands.
+ */
+
+/* Ttk_EnumerateTagOptions -- implements [$w tag configure $tag]
+ */
+int Ttk_EnumerateTagOptions(
+ Tcl_Interp *interp, Ttk_TagTable tagTable, Ttk_Tag tag)
+{
+ return TtkEnumerateOptions(interp, tag->tagRecord,
+ tagTable->optionSpecs, tagTable->optionTable, tagTable->tkwin);
+}
+
+Tcl_Obj *Ttk_TagOptionValue(
+ Tcl_Interp *interp,
+ Ttk_TagTable tagTable,
+ Ttk_Tag tag,
+ Tcl_Obj *optionName)
+{
+ return Tk_GetOptionValue(interp,
+ tag->tagRecord, tagTable->optionTable, optionName, tagTable->tkwin);
+}
+
+/* Ttk_ConfigureTag -- implements [$w tag configure $tag -option value...]
+ */
+int Ttk_ConfigureTag(
+ Tcl_Interp *interp,
+ Ttk_TagTable tagTable,
+ Ttk_Tag tag,
+ int objc, Tcl_Obj *const objv[])
+{
+ return Tk_SetOptions(
+ interp, tag->tagRecord, tagTable->optionTable,
+ objc, objv, tagTable->tkwin, NULL/*savedOptions*/, NULL/*mask*/);
+}
+
+/*------------------------------------------------------------------------
+ * +++ Tag values.
+ */
- return TCL_OK;
+#define OBJ_AT(record, offset) (*(Tcl_Obj**)(((char*)record)+offset))
+
+void Ttk_TagSetValues(Ttk_TagTable tagTable, Ttk_TagSet tagSet, void *record)
+{
+ const int LOWEST_PRIORITY = 0x7FFFFFFF;
+ int i, j;
+
+ memset(record, 0, tagTable->recordSize);
+
+ for (i = 0; tagTable->optionSpecs[i].type != TK_OPTION_END; ++i) {
+ Tk_OptionSpec *optionSpec = tagTable->optionSpecs + i;
+ int offset = optionSpec->objOffset;
+ int prio = LOWEST_PRIORITY;
+
+ for (j = 0; j < tagSet->nTags; ++j) {
+ Ttk_Tag tag = tagSet->tags[j];
+ if (OBJ_AT(tag->tagRecord, offset) != 0 && tag->priority < prio) {
+ OBJ_AT(record, offset) = OBJ_AT(tag->tagRecord, offset);
+ prio = tag->priority;
+ }
+ }
+ }
}
-void Ttk_FreeTagList(void **taglist)
+void Ttk_TagSetApplyStyle(
+ Ttk_TagTable tagTable, Ttk_Style style, Ttk_State state, void *record)
{
- if (taglist)
- ckfree((ClientData)taglist);
+ Tk_OptionSpec *optionSpec = tagTable->optionSpecs;
+
+ while (optionSpec->type != TK_OPTION_END) {
+ int offset = optionSpec->objOffset;
+ const char *optionName = optionSpec->optionName;
+ Tcl_Obj *val = Ttk_StyleMap(style, optionName, state);
+ if (val) {
+ OBJ_AT(record, offset) = val;
+ } else if (OBJ_AT(record, offset) == 0) {
+ OBJ_AT(record, offset) = Ttk_StyleDefault(style, optionName);
+ }
+ ++optionSpec;
+ }
}
diff --git a/generic/ttk/ttkTheme.c b/generic/ttk/ttkTheme.c
index 3439ef0..45049b6 100644
--- a/generic/ttk/ttkTheme.c
+++ b/generic/ttk/ttkTheme.c
@@ -9,7 +9,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * $Id: ttkTheme.c,v 1.12 2008/04/27 22:41:12 dkf Exp $
+ * $Id: ttkTheme.c,v 1.13 2008/05/23 20:20:05 jenglish Exp $
*/
#include <stdlib.h>
@@ -85,34 +85,35 @@ static void FreeStyle(Style *stylePtr)
}
/*
- * LookupStateMap --
- * Look up dynamic resource settings in the in the specified style.
+ * Ttk_StyleMap --
+ * Look up state-specific option value from specified style.
*/
-
-static Ttk_StateMap LookupStateMap(Ttk_Style stylePtr, const char *optionName)
+Tcl_Obj *Ttk_StyleMap(Ttk_Style style, const char *optionName, Ttk_State state)
{
- while (stylePtr) {
+ while (style) {
Tcl_HashEntry *entryPtr =
- Tcl_FindHashEntry(&stylePtr->settingsTable, optionName);
- if (entryPtr)
- return (Ttk_StateMap)Tcl_GetHashValue(entryPtr);
- stylePtr = stylePtr->parentStyle;
+ Tcl_FindHashEntry(&style->settingsTable, optionName);
+ if (entryPtr) {
+ Ttk_StateMap stateMap = Tcl_GetHashValue(entryPtr);
+ return Ttk_StateMapLookup(NULL, stateMap, state);
+ }
+ style = style->parentStyle;
}
return 0;
}
/*
- * LookupDefault --
+ * Ttk_StyleDefault --
* Look up default resource setting the in the specified style.
*/
-static Tcl_Obj *LookupDefault(Ttk_Style stylePtr, const char *optionName)
+Tcl_Obj *Ttk_StyleDefault(Ttk_Style style, const char *optionName)
{
- while (stylePtr) {
+ while (style) {
Tcl_HashEntry *entryPtr =
- Tcl_FindHashEntry(&stylePtr->defaultsTable, optionName);
+ Tcl_FindHashEntry(&style->defaultsTable, optionName);
if (entryPtr)
return (Tcl_Obj *)Tcl_GetHashValue(entryPtr);
- stylePtr = stylePtr->parentStyle;
+ style= style->parentStyle;
}
return 0;
}
@@ -296,7 +297,6 @@ static void FreeElementImpl(ElementImpl *elementImpl)
ckfree((ClientData)elementImpl);
}
-
/*------------------------------------------------------------------------
* +++ Themes.
*/
@@ -993,15 +993,10 @@ int InitializeElementRecord(
Tcl_Obj **dest = (Tcl_Obj **)
(elementRecord + elementOption->offset);
const char *optionName = elementOption->optionName;
- Tcl_Obj *stateMap = LookupStateMap(style, optionName);
- Tcl_Obj *dynamicSetting = 0;
+ Tcl_Obj *dynamicSetting = Ttk_StyleMap(style, optionName, state);
Tcl_Obj *widgetValue = 0;
Tcl_Obj *elementDefault = element->defaultValues[i];
- if (stateMap) {
- dynamicSetting = Ttk_StateMapLookup(NULL, stateMap, state);
- }
-
if (optionMap[i]) {
widgetValue = *(Tcl_Obj **)
(widgetRecord + optionMap[i]->objOffset);
@@ -1012,7 +1007,7 @@ int InitializeElementRecord(
} else if (dynamicSetting) {
*dest = dynamicSetting;
} else {
- Tcl_Obj *styleDefault = LookupDefault(style, optionName);
+ Tcl_Obj *styleDefault = Ttk_StyleDefault(style, optionName);
*dest = styleDefault ? styleDefault : elementDefault;
}
@@ -1039,7 +1034,6 @@ Tcl_Obj *Ttk_QueryStyle(
const char *optionName, /* Option name */
Ttk_State state) /* Current state */
{
- Tcl_Obj *stateMap;
const Tk_OptionSpec *optionSpec;
Tcl_Obj *result;
@@ -1057,18 +1051,15 @@ Tcl_Obj *Ttk_QueryStyle(
/*
* Check dynamic settings:
*/
- stateMap = LookupStateMap(style, optionName);
- if (stateMap) {
- result = Ttk_StateMapLookup(NULL, stateMap, state);
- if (result) {
- return result;
- }
+ result = Ttk_StyleMap(style, optionName, state);
+ if (result) {
+ return result;
}
/*
* Use style default:
*/
- return LookupDefault(style, optionName);
+ return Ttk_StyleDefault(style, optionName);
}
/*
diff --git a/generic/ttk/ttkTheme.h b/generic/ttk/ttkTheme.h
index 5e7dc88..c5de39b 100644
--- a/generic/ttk/ttkTheme.h
+++ b/generic/ttk/ttkTheme.h
@@ -1,4 +1,4 @@
-/* $Id: ttkTheme.h,v 1.13 2007/12/13 15:26:26 dgp Exp $
+/* $Id: ttkTheme.h,v 1.14 2008/05/23 20:20:05 jenglish Exp $
* Copyright (c) 2003 Joe English. Freely redistributable.
*
* Declarations for Tk theme engine.
@@ -205,6 +205,7 @@ typedef struct Ttk_Theme_ *Ttk_Theme;
typedef struct Ttk_ElementImpl_ *Ttk_ElementImpl;
typedef struct Ttk_Layout_ *Ttk_Layout;
typedef struct Ttk_LayoutNode_ Ttk_LayoutNode;
+typedef struct Ttk_Style_ *Ttk_Style;
TTKAPI Ttk_Theme Ttk_GetTheme(Tcl_Interp *interp, const char *name);
TTKAPI Ttk_Theme Ttk_GetDefaultTheme(Tcl_Interp *interp);
@@ -341,6 +342,10 @@ MODULE_SCOPE void Ttk_ChangeElementState(Ttk_LayoutNode *,unsigned set,unsigned
MODULE_SCOPE Tcl_Obj *Ttk_QueryOption(Ttk_Layout, const char *, Ttk_State);
+TTKAPI Ttk_Style Ttk_LayoutStyle(Ttk_Layout);
+TTKAPI Tcl_Obj *Ttk_StyleDefault(Ttk_Style, const char *optionName);
+TTKAPI Tcl_Obj *Ttk_StyleMap(Ttk_Style, const char *optionName, Ttk_State);
+
/*------------------------------------------------------------------------
* +++ Resource cache.
* See resource.c for explanation.
diff --git a/generic/ttk/ttkThemeInt.h b/generic/ttk/ttkThemeInt.h
index a7c19aa..1f61b73 100644
--- a/generic/ttk/ttkThemeInt.h
+++ b/generic/ttk/ttkThemeInt.h
@@ -1,5 +1,5 @@
/*
- * $Id: ttkThemeInt.h,v 1.5 2007/12/13 15:26:26 dgp Exp $
+ * $Id: ttkThemeInt.h,v 1.6 2008/05/23 20:20:05 jenglish Exp $
*
* Theme engine: private definitions.
*
@@ -11,7 +11,6 @@
#include "ttkTheme.h"
-typedef struct Ttk_Style_ *Ttk_Style;
typedef struct Ttk_TemplateNode_ Ttk_TemplateNode, *Ttk_LayoutTemplate;
MODULE_SCOPE Ttk_ElementImpl Ttk_GetElement(Ttk_Theme theme, const char *name);
diff --git a/generic/ttk/ttkTreeview.c b/generic/ttk/ttkTreeview.c
index 95c9a99..ffe1351 100644
--- a/generic/ttk/ttkTreeview.c
+++ b/generic/ttk/ttkTreeview.c
@@ -1,4 +1,4 @@
-/* $Id: ttkTreeview.c,v 1.24 2008/04/27 22:41:12 dkf Exp $
+/* $Id: ttkTreeview.c,v 1.25 2008/05/23 20:20:05 jenglish Exp $
* Copyright (c) 2004, Joe English
*
* ttk::treeview widget implementation.
@@ -33,8 +33,7 @@ static const int HALO = 4; /* separator */
*/
typedef struct TreeItemRec TreeItem;
-struct TreeItemRec
-{
+struct TreeItemRec {
Tcl_HashEntry *entryPtr; /* Back-pointer to hash table entry */
TreeItem *parent; /* Parent item */
TreeItem *children; /* Linked list of child items */
@@ -50,16 +49,24 @@ struct TreeItemRec
Tcl_Obj *valuesObj;
Tcl_Obj *openObj;
Tcl_Obj *tagsObj;
+
+ /*
+ * Derived resources:
+ */
+ Ttk_TagSet tagset;
+ Ttk_ImageSpec *imagespec;
};
-static Tk_OptionSpec ItemOptionSpecs[] =
-{
+#define ITEM_OPTION_TAGS_CHANGED 0x100
+#define ITEM_OPTION_IMAGE_CHANGED 0x200
+
+static Tk_OptionSpec ItemOptionSpecs[] = {
{TK_OPTION_STRING, "-text", "text", "Text",
"", Tk_Offset(TreeItem,textObj), -1,
0,0,0 },
{TK_OPTION_STRING, "-image", "image", "Image",
NULL, Tk_Offset(TreeItem,imageObj), -1,
- TK_OPTION_NULL_OK,0,0 },
+ TK_OPTION_NULL_OK,0,ITEM_OPTION_IMAGE_CHANGED },
{TK_OPTION_STRING, "-values", "values", "Values",
NULL, Tk_Offset(TreeItem,valuesObj), -1,
TK_OPTION_NULL_OK,0,0 },
@@ -68,7 +75,7 @@ static Tk_OptionSpec ItemOptionSpecs[] =
0,0,0 },
{TK_OPTION_STRING, "-tags", "tags", "Tags",
NULL, Tk_Offset(TreeItem,tagsObj), -1,
- TK_OPTION_NULL_OK,0,0 },
+ TK_OPTION_NULL_OK,0,ITEM_OPTION_TAGS_CHANGED },
{TK_OPTION_END, 0,0,0, NULL, -1,-1, 0,0,0}
};
@@ -90,6 +97,9 @@ static TreeItem *NewItem(void)
item->openObj = NULL;
item->tagsObj = NULL;
+ item->tagset = NULL;
+ item->imagespec = NULL;
+
return item;
}
@@ -103,6 +113,10 @@ static void FreeItem(TreeItem *item)
if (item->valuesObj) { Tcl_DecrRefCount(item->valuesObj); }
if (item->openObj) { Tcl_DecrRefCount(item->openObj); }
if (item->tagsObj) { Tcl_DecrRefCount(item->tagsObj); }
+
+ if (item->tagset) { Ttk_FreeTagSet(item->tagset); }
+ if (item->imagespec) { TtkFreeImageSpec(item->imagespec); }
+
ckfree((ClientData)item);
}
@@ -168,14 +182,13 @@ static TreeItem *NextPreorder(TreeItem *item)
typedef struct {
Tcl_Obj *textObj; /* taken from item / data cell */
Tcl_Obj *imageObj; /* taken from item */
- Tcl_Obj *anchorObj; /* from column */
+ Tcl_Obj *anchorObj; /* from column <<NOTE-ANCHOR>> */
Tcl_Obj *backgroundObj; /* remainder from tag */
Tcl_Obj *foregroundObj;
Tcl_Obj *fontObj;
} DisplayItem;
-static Tk_OptionSpec TagOptionSpecs[] =
-{
+static Tk_OptionSpec TagOptionSpecs[] = {
{TK_OPTION_STRING, "-text", "text", "Text",
NULL, Tk_Offset(DisplayItem,textObj), -1,
TK_OPTION_NULL_OK,0,0 },
@@ -184,14 +197,14 @@ static Tk_OptionSpec TagOptionSpecs[] =
TK_OPTION_NULL_OK,0,0 },
{TK_OPTION_ANCHOR, "-anchor", "anchor", "Anchor",
NULL, Tk_Offset(DisplayItem,anchorObj), -1,
- TK_OPTION_NULL_OK, 0, GEOMETRY_CHANGED},
- {TK_OPTION_STRING, "-background", "windowColor", "WindowColor", /*SB:COLOR*/
+ TK_OPTION_NULL_OK, 0, GEOMETRY_CHANGED}, /* <<NOTE-ANCHOR>> */
+ {TK_OPTION_COLOR, "-background", "windowColor", "WindowColor",
NULL, Tk_Offset(DisplayItem,backgroundObj), -1,
TK_OPTION_NULL_OK,0,0 },
- {TK_OPTION_STRING, "-foreground", "textColor", "TextColor", /*SB:COLOR*/
+ {TK_OPTION_COLOR, "-foreground", "textColor", "TextColor",
NULL, Tk_Offset(DisplayItem,foregroundObj), -1,
TK_OPTION_NULL_OK,0,0 },
- {TK_OPTION_STRING, "-font", "font", "Font", /* SB:FONT */
+ {TK_OPTION_FONT, "-font", "font", "Font",
NULL, Tk_Offset(DisplayItem,fontObj), -1,
TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED },
@@ -211,7 +224,7 @@ typedef struct {
int stretch; /* Should column stretch while resizing? */
Tcl_Obj *idObj; /* Column identifier, from -columns option */
- Tcl_Obj *anchorObj; /* -anchor for cell data */
+ Tcl_Obj *anchorObj; /* -anchor for cell data <<NOTE-ANCHOR>> */
/* Column heading data:
*/
@@ -259,8 +272,7 @@ static void FreeColumn(TreeColumn *column)
/* Don't touch column->data, it's scratch storage */
}
-static Tk_OptionSpec ColumnOptionSpecs[] =
-{
+static Tk_OptionSpec ColumnOptionSpecs[] = {
{TK_OPTION_INT, "-width", "width", "Width",
DEF_COLWIDTH, -1, Tk_Offset(TreeColumn,width),
0,0,GEOMETRY_CHANGED },
@@ -271,7 +283,7 @@ static Tk_OptionSpec ColumnOptionSpecs[] =
"1", -1, Tk_Offset(TreeColumn,stretch),
0,0,0 },
{TK_OPTION_ANCHOR, "-anchor", "anchor", "Anchor",
- "w", Tk_Offset(TreeColumn,anchorObj), -1,
+ "w", Tk_Offset(TreeColumn,anchorObj), -1, /* <<NOTE-ANCHOR>> */
0,0,0 },
{TK_OPTION_STRING, "-id", "id", "ID",
NULL, Tk_Offset(TreeColumn,idObj), -1,
@@ -279,8 +291,7 @@ static Tk_OptionSpec ColumnOptionSpecs[] =
{TK_OPTION_END, 0,0,0, NULL, -1,-1, 0,0,0}
};
-static Tk_OptionSpec HeadingOptionSpecs[] =
-{
+static Tk_OptionSpec HeadingOptionSpecs[] = {
{TK_OPTION_STRING, "-text", "text", "Text",
"", Tk_Offset(TreeColumn,headingObj), -1,
0,0,0 },
@@ -349,8 +360,7 @@ static int GetEnumSetFromObj(
* headingHeight: [layout]
* rowHeight, indent: style
*/
-typedef struct
-{
+typedef struct {
/* Resources acquired at initialization-time:
*/
Tk_OptionTable itemOptionTable;
@@ -425,8 +435,7 @@ typedef struct {
static const char *SelectModeStrings[] = { "none", "browse", "extended", NULL };
-static Tk_OptionSpec TreeviewOptionSpecs[] =
-{
+static Tk_OptionSpec TreeviewOptionSpecs[] = {
WIDGET_TAKES_FOCUS,
{TK_OPTION_STRING, "-columns", "columns", "Columns",
@@ -887,14 +896,14 @@ static int DistributeWidth(Treeview *tv, int n)
/* + ResizeColumns --
* Recompute column widths based on available width.
- * Pick up slack first;
+ * 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,
+ DepositSlack(tv,
ShoveLeft(tv, tv->tree.nDisplayColumns - 1,
DistributeWidth(tv, PickupSlack(tv, delta))));
}
@@ -915,7 +924,7 @@ static void DragColumn(Treeview *tv, int i, int delta)
* +++ Event handlers.
*/
-static TreeItem *IdentifyItem(Treeview *tv,int y,Ttk_Box *itemPos); /*forward*/
+static TreeItem *IdentifyItem(Treeview *tv, int y); /*forward*/
static const unsigned int TreeviewBindEventMask =
KeyPressMask|KeyReleaseMask
@@ -928,14 +937,11 @@ static void TreeviewBindEventProc(void *clientData, XEvent *event)
{
Treeview *tv = clientData;
TreeItem *item = NULL;
- Ttk_Box unused;
- void *taglist;
- int nTags;
+ Ttk_TagSet tagset;
/*
* Figure out where to deliver the event.
*/
-
switch (event->type)
{
case KeyPress:
@@ -945,10 +951,10 @@ static void TreeviewBindEventProc(void *clientData, XEvent *event)
break;
case ButtonPress:
case ButtonRelease:
- item = IdentifyItem(tv, event->xbutton.y, &unused);
+ item = IdentifyItem(tv, event->xbutton.y);
break;
case MotionNotify:
- item = IdentifyItem(tv, event->xmotion.y, &unused);
+ item = IdentifyItem(tv, event->xmotion.y);
break;
default:
break;
@@ -958,18 +964,21 @@ static void TreeviewBindEventProc(void *clientData, XEvent *event)
return;
}
- /* ASSERT: Ttk_GetTagListFromObj returns TCL_OK. */
- Ttk_GetTagListFromObj(NULL, tv->tree.tagTable, item->tagsObj,
- &nTags, &taglist);
+ /* ASSERT: Ttk_GetTagSetFromObj succeeds.
+ * NB: must use a local copy of the tagset,
+ * in case a binding script stomps on -tags.
+ */
+ tagset = Ttk_GetTagSetFromObj(NULL, tv->tree.tagTable, item->tagsObj);
/*
* Fire binding:
*/
Tcl_Preserve(clientData);
- Tk_BindEvent(tv->tree.bindingTable, event, tv->core.tkwin, nTags, taglist);
+ Tk_BindEvent(tv->tree.bindingTable, event, tv->core.tkwin,
+ tagset->nTags, (void **)tagset->tags);
Tcl_Release(clientData);
- Ttk_FreeTagList(taglist);
+ Ttk_FreeTagSet(tagset);
}
/*------------------------------------------------------------------------
@@ -991,7 +1000,7 @@ static int TreeviewInitialize(Tcl_Interp *interp, void *recordPtr)
Tk_CreateOptionTable(interp, TagOptionSpecs);
tv->tree.tagTable = Ttk_CreateTagTable(
- tv->tree.tagOptionTable, sizeof(DisplayItem));
+ interp, tv->core.tkwin, TagOptionSpecs, sizeof(DisplayItem));
tv->tree.bindingTable = Tk_CreateBindingTable(interp);
Tk_CreateEventHandler(tv->core.tkwin,
TreeviewBindEventMask, TreeviewBindEventProc, tv);
@@ -1028,6 +1037,7 @@ static int TreeviewInitialize(Tcl_Interp *interp, void *recordPtr)
tv->tree.root = NewItem();
Tk_InitOptions(interp, (ClientData)tv->tree.root,
tv->tree.itemOptionTable, tv->core.tkwin);
+ tv->tree.root->tagset = Ttk_GetTagSetFromObj(NULL, tv->tree.tagTable, NULL);
tv->tree.root->entryPtr = Tcl_CreateHashEntry(&tv->tree.items, "", &unused);
Tcl_SetHashValue(tv->tree.root->entryPtr, tv->tree.root);
@@ -1122,9 +1132,12 @@ static int ConfigureItem(
int objc, Tcl_Obj *const objv[])
{
Tk_SavedOptions savedOptions;
+ unsigned mask;
+ Ttk_ImageSpec *newImageSpec = NULL;
+ Ttk_TagSet newTagSet = NULL;
if (Tk_SetOptions(interp, (ClientData)item, tv->tree.itemOptionTable,
- objc, objv, tv->core.tkwin,&savedOptions,0) != TCL_OK)
+ objc, objv, tv->core.tkwin,&savedOptions,&mask) != TCL_OK)
{
return TCL_ERROR;
}
@@ -1137,15 +1150,24 @@ static int ConfigureItem(
goto error;
}
- /* Validate -image option.
+ /* Check -image.
*/
- if (item->imageObj) {
- Ttk_ImageSpec *imageSpec =
- TtkGetImageSpec(interp, tv->core.tkwin, item->imageObj);
- if (!imageSpec) {
+ if ((mask & ITEM_OPTION_IMAGE_CHANGED) && item->imageObj) {
+ newImageSpec = TtkGetImageSpec(interp, tv->core.tkwin, item->imageObj);
+ if (!newImageSpec) {
+ goto error;
+ }
+ }
+
+ /* Check -tags.
+ * Side effect: may create new tags.
+ */
+ if (mask & ITEM_OPTION_TAGS_CHANGED) {
+ newTagSet = Ttk_GetTagSetFromObj(
+ interp, tv->tree.tagTable, item->tagsObj);
+ if (!newTagSet) {
goto error;
}
- TtkFreeImageSpec(imageSpec); /* @@@TODO: Keep this around */
}
/* Keep TTK_STATE_OPEN flag in sync with item->openObj.
@@ -1162,28 +1184,24 @@ static int ConfigureItem(
item->state &= ~TTK_STATE_OPEN;
}
- /* Make sure -tags is a valid list
- * (side effect: may create new tags)
- */
- if (item->tagsObj) {
- void *taglist;
- int nTags;
- if (Ttk_GetTagListFromObj(interp, tv->tree.tagTable, item->tagsObj,
- &nTags, &taglist) != TCL_OK)
- {
- goto error;
- }
- Ttk_FreeTagList(taglist);
- }
-
/* All OK.
*/
Tk_FreeSavedOptions(&savedOptions);
+ if (mask & ITEM_OPTION_TAGS_CHANGED) {
+ if (item->tagset) { Ttk_FreeTagSet(item->tagset); }
+ item->tagset = newTagSet;
+ }
+ if (mask & ITEM_OPTION_IMAGE_CHANGED) {
+ if (item->imagespec) { TtkFreeImageSpec(item->imagespec); }
+ item->imagespec = newImageSpec;
+ }
TtkRedisplayWidget(&tv->core);
return TCL_OK;
error:
Tk_RestoreSavedOptions(&savedOptions);
+ if (newTagSet) { Ttk_FreeTagSet(newTagSet); }
+ if (newImageSpec) { TtkFreeImageSpec(newImageSpec); }
return TCL_ERROR;
}
@@ -1300,21 +1318,18 @@ static int CountRows(TreeItem *item)
static TreeItem *IdentifyRow(
Treeview *tv, /* Widget record */
TreeItem *item, /* Where to start search */
- Ttk_Box *bp, /* Scan position */
+ int *ypos, /* Scan position */
int y) /* Target y coordinate */
{
while (item) {
- int next_ypos = bp->y + tv->tree.rowHeight;
- if (bp->y <= y && y <= next_ypos) {
- bp->height = tv->tree.rowHeight;
+ int next_ypos = *ypos + tv->tree.rowHeight;
+ if (*ypos <= y && y <= next_ypos) {
return item;
}
- bp->y = next_ypos;
+ *ypos = next_ypos;
if (item->state & TTK_STATE_OPEN) {
- TreeItem *subitem = IdentifyRow(tv, item->children, bp, y);
+ TreeItem *subitem = IdentifyRow(tv, item->children, ypos, y);
if (subitem) {
- bp->x += tv->tree.indent;
- bp->width -= tv->tree.indent;
return subitem;
}
}
@@ -1325,17 +1340,12 @@ static TreeItem *IdentifyRow(
/* + IdentifyItem --
* Locate the item at the specified y position, if any.
- * On return, *itemPos holds the parcel of the tree item.
*/
-static TreeItem *IdentifyItem(Treeview *tv, int y, Ttk_Box *itemPos)
+static TreeItem *IdentifyItem(Treeview *tv, int y)
{
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, tv->tree.root->children, itemPos, y);
+ int ypos = tv->tree.treeArea.y - tv->tree.yscroll.first * rowHeight;
+ return IdentifyRow(tv, tv->tree.root->children, &ypos, y);
}
/* + IdentifyDisplayColumn --
@@ -1361,6 +1371,51 @@ static int IdentifyDisplayColumn(Treeview *tv, int x, int *x1)
return -1;
}
+/* + RowNumber --
+ * Calculate which row the specified item appears on;
+ * returns -1 if the item is not viewable.
+ * Xref: DrawForest, IdentifyItem.
+ */
+static int RowNumber(Treeview *tv, TreeItem *item)
+{
+ TreeItem *p = tv->tree.root->children;
+ int n = 0;
+
+ while (p) {
+ if (p == item)
+ return n;
+
+ ++n;
+
+ /* Find next viewable item in preorder traversal order
+ */
+ if (p->children && (p->state & TTK_STATE_OPEN)) {
+ p = p->children;
+ } else {
+ while (!p->next && p && p->parent)
+ p = p->parent;
+ if (p)
+ p = p->next;
+ }
+ }
+
+ return -1;
+}
+
+/* + ItemDepth -- return the depth of a tree item.
+ * The depth of an item is equal to the number of proper ancestors,
+ * not counting the root node.
+ */
+static int ItemDepth(TreeItem *item)
+{
+ int depth = 0;
+ while (item->parent) {
+ ++depth;
+ item = item->parent;
+ }
+ return depth-1;
+}
+
/* + ItemRow --
* Returns row number of specified item relative to root,
* -1 if item is not viewable.
@@ -1388,6 +1443,93 @@ static int ItemRow(Treeview *tv, TreeItem *p)
}
}
+/* + BoundingBox --
+ * Compute the parcel of the specified column of the specified item,
+ * (or the entire item if column is NULL)
+ * Returns: 0 if item or column is not viewable, 1 otherwise.
+ */
+static int BoundingBox(
+ Treeview *tv, /* treeview widget */
+ TreeItem *item, /* desired item */
+ TreeColumn *column, /* desired column */
+ Ttk_Box *bbox_rtn) /* bounding box of item */
+{
+ int row = ItemRow(tv, item);
+ Ttk_Box bbox = tv->tree.treeArea;
+
+ if (row < tv->tree.yscroll.first || row > tv->tree.yscroll.last) {
+ /* not viewable, or off-screen */
+ return 0;
+ }
+
+ bbox.y += (row - tv->tree.yscroll.first) * tv->tree.rowHeight;
+ bbox.height = tv->tree.rowHeight;
+
+ if (column) {
+ int xpos = 0, i = FirstColumn(tv);
+ while (i < tv->tree.nDisplayColumns) {
+ if (tv->tree.displayColumns[i] == column) {
+ break;
+ }
+ xpos += tv->tree.displayColumns[i]->width;
+ ++i;
+ }
+ if (i == tv->tree.nDisplayColumns) { /* specified column unviewable */
+ return 0;
+ }
+ bbox.x += xpos;
+ bbox.width = column->width;
+
+ /* Account for indentation in tree column:
+ */
+ if (column == &tv->tree.column0) {
+ int indent = tv->tree.indent * ItemDepth(item);
+ bbox.x += indent;
+ bbox.width -= indent;
+ }
+ }
+ *bbox_rtn = bbox;
+ return 1;
+}
+
+/* + IdentifyRegion --
+ */
+
+typedef enum {
+ REGION_NOTHING = 0,
+ REGION_HEADING,
+ REGION_SEPARATOR,
+ REGION_TREE,
+ REGION_CELL
+} TreeRegion;
+
+static const char *regionStrings[] = {
+ "nothing", "heading", "separator", "tree", "cell", 0
+};
+
+static TreeRegion IdentifyRegion(Treeview *tv, int x, int y)
+{
+ int x1, colno = IdentifyDisplayColumn(tv, x, &x1);
+
+ if (Ttk_BoxContains(tv->tree.headingArea, x, y)) {
+ if (colno < 0) {
+ return REGION_NOTHING;
+ } else if (-HALO <= x1 - x && x1 - x <= HALO) {
+ return REGION_SEPARATOR;
+ } else {
+ return REGION_HEADING;
+ }
+ } else if (Ttk_BoxContains(tv->tree.treeArea,x,y)) {
+ TreeItem *item = IdentifyItem(tv, y);
+ if (item && colno > 0) {
+ return REGION_CELL;
+ } else if (item) {
+ return REGION_TREE;
+ }
+ }
+ return REGION_NOTHING;
+}
+
/*------------------------------------------------------------------------
* +++ Display routines.
*/
@@ -1560,34 +1702,16 @@ static void DrawHeadings(Treeview *tv, Drawable d, Ttk_Box b)
}
/* + PrepareItem --
- * Fill in a displayItem record from tag settings.
+ * Fill in a displayItem record.
*/
-static void PrepareItem(Treeview *tv, TreeItem *item, DisplayItem *displayItem)
+static void PrepareItem(
+ Treeview *tv, TreeItem *item, DisplayItem *displayItem)
{
- const int nOptions = sizeof(*displayItem)/sizeof(Tcl_Obj*);
- Tcl_Obj **dest = (Tcl_Obj**)displayItem;
- Tcl_Obj **objv = NULL;
- int objc = 0;
-
- memset(displayItem, 0, sizeof(*displayItem));
+ Ttk_Style style = Ttk_LayoutStyle(tv->core.layout);
+ Ttk_State state = ItemState(tv, item);
- if ( item->tagsObj
- && Tcl_ListObjGetElements(NULL, item->tagsObj, &objc, &objv) == TCL_OK)
- {
- int i, j;
- for (i=0; i<objc; ++i) {
- Ttk_Tag tag = Ttk_GetTagFromObj(tv->tree.tagTable, objv[i]);
- Tcl_Obj **tagRecord = Ttk_TagRecord(tag);
-
- if (tagRecord) {
- for (j=0; j<nOptions; ++j) {
- if (tagRecord[j] != 0) {
- dest[j] = tagRecord[j];
- }
- }
- }
- }
- }
+ Ttk_TagSetValues(tv->tree.tagTable, item->tagset, displayItem);
+ Ttk_TagSetApplyStyle(tv->tree.tagTable, style, state, displayItem);
}
/* + DrawCells --
@@ -1620,7 +1744,7 @@ static void DrawCells(
Ttk_MakeBox(b.x+x, b.y+y, column->width, rowHeight), cellPadding);
displayItem->textObj = column->data;
- displayItem->anchorObj = column->anchorObj;
+ displayItem->anchorObj = column->anchorObj; /* <<NOTE-ANCHOR>> */
DisplayLayout(layout, displayItem, state, parcel, d);
x += column->width;
@@ -1655,9 +1779,9 @@ 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, rowHeight);
- displayItem.textObj = item->textObj;
- displayItem.imageObj = item->imageObj;
- displayItem.anchorObj = 0;
+ if (item->textObj) { displayItem.textObj = item->textObj; }
+ if (item->imageObj) { displayItem.imageObj = item->imageObj; }
+ /* ??? displayItem.anchorObj = 0; <<NOTE-ANCHOR>> */
DisplayLayout(tv->tree.itemLayout, &displayItem, state, parcel, d);
x = colwidth;
} else {
@@ -1802,51 +1926,6 @@ static TreeItem *DeleteItems(TreeItem *item, TreeItem *delq)
return delq;
}
-/* + RowNumber --
- * Calculate which row the specified item appears on;
- * returns -1 if the item is not viewable.
- * Xref: DrawForest, IdentifyItem.
- */
-static int RowNumber(Treeview *tv, TreeItem *item)
-{
- TreeItem *p = tv->tree.root->children;
- int n = 0;
-
- while (p) {
- if (p == item)
- return n;
-
- ++n;
-
- /* Find next viewable item in preorder traversal order
- */
- if (p->children && (p->state & TTK_STATE_OPEN)) {
- p = p->children;
- } else {
- while (!p->next && p && p->parent)
- p = p->parent;
- if (p)
- p = p->next;
- }
- }
-
- return -1;
-}
-
-/* + ItemDepth -- return the depth of a tree item.
- * The depth of an item is equal to the number of proper ancestors,
- * not counting the root node.
- */
-static int ItemDepth(TreeItem *item)
-{
- int depth = 0;
- while (item->parent) {
- ++depth;
- item = item->parent;
- }
- return depth-1;
-}
-
/*------------------------------------------------------------------------
* +++ Widget commands -- item inquiry.
*/
@@ -2065,7 +2144,6 @@ static int TreeviewBBoxCommand(
Treeview *tv = recordPtr;
TreeItem *item = 0;
TreeColumn *column = 0;
- int row;
Ttk_Box bbox;
if (objc < 3 || objc > 4) {
@@ -2081,47 +2159,10 @@ static int TreeviewBBoxCommand(
return TCL_ERROR;
}
- /* Compute bounding box of item:
- */
- 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 += (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 = FirstColumn(tv);
- while (i < tv->tree.nDisplayColumns) {
- if (tv->tree.displayColumns[i] == column) {
- break;
- }
- xpos += tv->tree.displayColumns[i]->width;
- ++i;
- }
- if (i == tv->tree.nDisplayColumns) { /* specified column unviewable */
- return TCL_OK;
- }
- bbox.x += xpos;
- bbox.width = column->width;
-
- /* Special case for tree column -- account for indentation:
- * (@@@ NOTE: doesn't account for tree indicator or image;
- * @@@ this may or may not be the right thing.)
- */
- if (column == &tv->tree.column0) {
- int indent = tv->tree.indent * ItemDepth(item);
- bbox.x += indent;
- bbox.width -= indent;
- }
+ if (BoundingBox(tv, item, column, &bbox)) {
+ Tcl_SetObjResult(interp, Ttk_NewBoxObj(bbox));
}
- Tcl_SetObjResult(interp, Ttk_NewBoxObj(bbox));
return TCL_OK;
}
@@ -2166,16 +2207,17 @@ static int TreeviewHorribleIdentify(
}
detail = dcolbuf;
} else if (Ttk_BoxContains(tv->tree.treeArea,x,y)) {
- Ttk_Box itemBox;
- item = IdentifyItem(tv, y, &itemBox);
+ item = IdentifyItem(tv, y);
if (item && dColumnNumber > 0) {
what = "cell";
detail = dcolbuf;
} else if (item) {
Ttk_Layout layout = tv->tree.itemLayout;
+ Ttk_Box itemBox;
DisplayItem displayItem;
Ttk_LayoutNode *element;
+ BoundingBox(tv, item, NULL, &itemBox);
PrepareItem(tv, item, &displayItem); /*@@@ FIX: -text, etc*/
Ttk_RebindSublayout(layout, &displayItem);
Ttk_PlaceLayout(layout, ItemState(tv,item), itemBox);
@@ -2209,51 +2251,97 @@ done:
static int TreeviewIdentifyCommand(
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], void *recordPtr)
{
- static const char *componentStrings[] =
- { "row", "column", NULL };
- enum { I_ROW, I_COLUMN };
+ static const char *submethodStrings[] =
+ { "region", "item", "column", "row", "element", NULL };
+ enum { I_REGION, I_ITEM, I_COLUMN, I_ROW, I_ELEMENT };
Treeview *tv = recordPtr;
- int component, x, y;
+ int submethod;
+ int x, y;
+
+ TreeRegion region;
+ Ttk_Box bbox;
+ TreeItem *item;
+ TreeColumn *column = 0;
+ int colno, x1;
if (objc == 4) { /* Old form */
return TreeviewHorribleIdentify(interp, objc, objv, tv);
} else if (objc != 5) {
- Tcl_WrongNumArgs(interp, 2, objv, "component x y");
+ Tcl_WrongNumArgs(interp, 2, objv, "command x y");
return TCL_ERROR;
}
if ( Tcl_GetIndexFromObj(interp, objv[2],
- componentStrings, "component", TCL_EXACT, &component) != TCL_OK
+ submethodStrings, "command", TCL_EXACT, &submethod) != TCL_OK
|| Tcl_GetIntFromObj(interp, objv[3], &x) != TCL_OK
|| Tcl_GetIntFromObj(interp, objv[4], &y) != TCL_OK
) {
return TCL_ERROR;
}
- switch (component)
+ region = IdentifyRegion(tv, x, y);
+ item = IdentifyItem(tv, y);
+ colno = IdentifyDisplayColumn(tv, x, &x1);
+ column = (colno >= 0) ? tv->tree.displayColumns[colno] : NULL;
+
+ switch (submethod)
{
+ case I_REGION :
+ Tcl_SetObjResult(interp,Tcl_NewStringObj(regionStrings[region],-1));
+ break;
+
+ case I_ITEM :
case I_ROW :
- {
- Ttk_Box itemBox;
- TreeItem *item = IdentifyItem(tv, y, &itemBox);
if (item) {
Tcl_SetObjResult(interp, ItemID(tv, item));
}
break;
- }
case I_COLUMN :
- {
- int x1;
- int column = IdentifyDisplayColumn(tv, x, &x1);
-
- if (column >= 0) {
+ if (colno >= 0) {
char dcolbuf[16];
- sprintf(dcolbuf, "#%d", column);
+ sprintf(dcolbuf, "#%d", colno);
Tcl_SetObjResult(interp, Tcl_NewStringObj(dcolbuf, -1));
}
break;
+
+ case I_ELEMENT :
+ {
+ Ttk_Layout layout = 0;
+ DisplayItem displayItem;
+ Ttk_LayoutNode *element;
+
+ switch (region) {
+ case REGION_NOTHING:
+ layout = tv->core.layout;
+ return TCL_OK; /* @@@ NYI */
+ case REGION_HEADING:
+ case REGION_SEPARATOR:
+ layout = tv->tree.headingLayout;
+ return TCL_OK; /* @@@ NYI */
+ case REGION_TREE:
+ layout = tv->tree.itemLayout;
+ break;
+ case REGION_CELL:
+ layout = tv->tree.cellLayout;
+ break;
+ }
+
+ if (!BoundingBox(tv, item, column, &bbox)) {
+ return TCL_OK;
+ }
+
+ PrepareItem(tv, item, &displayItem); /*@@@ FIX: fill in -text,etc */
+ Ttk_RebindSublayout(layout, &displayItem);
+ Ttk_PlaceLayout(layout, ItemState(tv,item), bbox);
+ element = Ttk_LayoutIdentify(layout, x, y);
+
+ if (element) {
+ const char *elementName = Ttk_LayoutNodeName(element);
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(elementName, -1));
+ }
+ break;
}
}
return TCL_OK;
@@ -2501,6 +2589,7 @@ static int TreeviewInsertCommand(
newItem = NewItem();
Tk_InitOptions(
interp, (ClientData)newItem, tv->tree.itemOptionTable, tv->core.tkwin);
+ newItem->tagset = Ttk_GetTagSetFromObj(NULL, tv->tree.tagTable, NULL);
if (ConfigureItem(interp, tv, newItem, objc, objv) != TCL_OK) {
Tcl_DeleteHashEntry(entryPtr);
FreeItem(newItem);
@@ -2651,7 +2740,7 @@ static int TreeviewMoveCommand(
if (p != item) {
--index;
} /* else -- moving node forward, count index+1 nodes */
- sibling = p;
+ sibling = p;
}
}
@@ -2942,7 +3031,7 @@ static int TreeviewTagConfigureCommand(
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], void *recordPtr)
{
Treeview *tv = recordPtr;
- void *tagRecord;
+ Ttk_TagTable tagTable = tv->tree.tagTable;
Ttk_Tag tag;
if (objc < 4) {
@@ -2950,22 +3039,57 @@ static int TreeviewTagConfigureCommand(
return TCL_ERROR;
}
- tag = Ttk_GetTagFromObj(tv->tree.tagTable, objv[3]);
- tagRecord = Ttk_TagRecord(tag);
+ tag = Ttk_GetTagFromObj(tagTable, objv[3]);
if (objc == 4) {
- return TtkEnumerateOptions(interp, tagRecord, TagOptionSpecs,
- tv->tree.tagOptionTable, tv->core.tkwin);
+ return Ttk_EnumerateTagOptions(interp, tagTable, tag);
} else if (objc == 5) {
- return TtkGetOptionValue(interp, tagRecord, objv[4],
- tv->tree.tagOptionTable, tv->core.tkwin);
+ Tcl_Obj *result = Ttk_TagOptionValue(interp, tagTable, tag, objv[4]);
+ if (result) {
+ Tcl_SetObjResult(interp, result);
+ return TCL_OK;
+ } /* else */
+ return TCL_ERROR;
}
/* else */
TtkRedisplayWidget(&tv->core);
- return Tk_SetOptions(
- interp, tagRecord, tv->tree.tagOptionTable,
- objc - 4, objv + 4, tv->core.tkwin,
- NULL/*savedOptions*/, NULL/*mask*/);
+ return Ttk_ConfigureTag(interp, tagTable, tag, objc - 4, objv + 4);
+}
+
+/* + $tv tag has $tag ?$item?
+ */
+static int TreeviewTagHasCommand(
+ Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], void *recordPtr)
+{
+ Treeview *tv = recordPtr;
+
+ if (objc == 4) { /* Return list of all items with tag */
+ Ttk_Tag tag = Ttk_GetTagFromObj(tv->tree.tagTable, objv[3]);
+ TreeItem *item = tv->tree.root;
+ Tcl_Obj *result = Tcl_NewListObj(0,0);
+
+ while (item) {
+ if (Ttk_TagSetContains(item->tagset, tag)) {
+ Tcl_ListObjAppendElement(NULL, result, ItemID(tv, item));
+ }
+ item = NextPreorder(item);
+ }
+
+ Tcl_SetObjResult(interp, result);
+ return TCL_OK;
+ } else if (objc == 5) { /* Test if item has specified tag */
+ Ttk_Tag tag = Ttk_GetTagFromObj(tv->tree.tagTable, objv[3]);
+ TreeItem *item = FindItem(interp, tv, objv[4]);
+ if (!item) {
+ return TCL_ERROR;
+ }
+ Tcl_SetObjResult(interp,
+ Tcl_NewBooleanObj(Ttk_TagSetContains(item->tagset, tag)));
+ return TCL_OK;
+ } else {
+ Tcl_WrongNumArgs(interp, 3, objv, "tagName ?item?");
+ return TCL_ERROR;
+ }
}
/* + $tv tag option args...
@@ -2976,6 +3100,7 @@ static int TreeviewTagCommand(
static WidgetCommandSpec TreeviewTagCommands[] = {
{ "bind", TreeviewTagBindCommand },
{ "configure", TreeviewTagConfigureCommand },
+ { "has", TreeviewTagHasCommand },
{0,0}
};
return TtkWidgetEnsembleCommand(
@@ -2985,8 +3110,7 @@ static int TreeviewTagCommand(
/*------------------------------------------------------------------------
* +++ Widget commands record.
*/
-static WidgetCommandSpec TreeviewCommands[] =
-{
+static WidgetCommandSpec TreeviewCommands[] = {
{ "bbox", TreeviewBBoxCommand },
{ "children", TreeviewChildrenCommand },
{ "cget", TtkWidgetCgetCommand },
@@ -3021,8 +3145,7 @@ static WidgetCommandSpec TreeviewCommands[] =
* +++ Widget definition.
*/
-static WidgetSpec TreeviewWidgetSpec =
-{
+static WidgetSpec TreeviewWidgetSpec = {
"Treeview", /* className */
sizeof(Treeview), /* recordSize */
TreeviewOptionSpecs, /* optionSpecs */
@@ -3075,15 +3198,13 @@ TTK_END_LAYOUT_TABLE
* +++ Tree indicator element.
*/
-typedef struct
-{
+typedef struct {
Tcl_Obj *colorObj;
Tcl_Obj *sizeObj;
Tcl_Obj *marginsObj;
} TreeitemIndicator;
-static Ttk_ElementOptionSpec TreeitemIndicatorOptions[] =
-{
+static Ttk_ElementOptionSpec TreeitemIndicatorOptions[] = {
{ "-foreground", TK_OPTION_COLOR,
Tk_Offset(TreeitemIndicator,colorObj), DEFAULT_FOREGROUND },
{ "-indicatorsize", TK_OPTION_PIXELS,
@@ -3135,8 +3256,7 @@ static void TreeitemIndicatorDraw(
Tk_FreeGC(Tk_Display(tkwin), gc);
}
-static Ttk_ElementSpec TreeitemIndicatorElementSpec =
-{
+static Ttk_ElementSpec TreeitemIndicatorElementSpec = {
TK_STYLE_VERSION_2,
sizeof(TreeitemIndicator),
TreeitemIndicatorOptions,
@@ -3148,14 +3268,12 @@ static Ttk_ElementSpec TreeitemIndicatorElementSpec =
* +++ Row element.
*/
-typedef struct
-{
+typedef struct {
Tcl_Obj *backgroundObj;
Tcl_Obj *rowNumberObj;
} RowElement;
-static Ttk_ElementOptionSpec RowElementOptions[] =
-{
+static Ttk_ElementOptionSpec RowElementOptions[] = {
{ "-background", TK_OPTION_COLOR,
Tk_Offset(RowElement,backgroundObj), DEFAULT_BACKGROUND },
{ "-rownumber", TK_OPTION_INT,
@@ -3174,8 +3292,7 @@ static void RowElementDraw(
b.x, b.y, b.width, b.height);
}
-static Ttk_ElementSpec RowElementSpec =
-{
+static Ttk_ElementSpec RowElementSpec = {
TK_STYLE_VERSION_2,
sizeof(RowElement),
RowElementOptions,
diff --git a/generic/ttk/ttkWidget.h b/generic/ttk/ttkWidget.h
index 21cb1b3..c74711d 100644
--- a/generic/ttk/ttkWidget.h
+++ b/generic/ttk/ttkWidget.h
@@ -1,4 +1,4 @@
-/* $Id: ttkWidget.h,v 1.9 2008/01/06 22:33:14 jenglish Exp $
+/* $Id: ttkWidget.h,v 1.10 2008/05/23 20:20:05 jenglish Exp $
* Copyright (c) 2003, Joe English
* Helper routines for widget implementations.
*/
@@ -211,20 +211,39 @@ MODULE_SCOPE void TtkScrollbarUpdateRequired(ScrollHandle);
typedef struct TtkTag *Ttk_Tag;
typedef struct TtkTagTable *Ttk_TagTable;
+typedef struct TtkTagSet { /* TODO: make opaque */
+ Ttk_Tag *tags;
+ int nTags;
+} *Ttk_TagSet;
-MODULE_SCOPE Ttk_TagTable Ttk_CreateTagTable(Tk_OptionTable, int tagRecSize);
+MODULE_SCOPE Ttk_TagTable Ttk_CreateTagTable(
+ Tcl_Interp *, Tk_Window tkwin, Tk_OptionSpec[], int recordSize);
MODULE_SCOPE void Ttk_DeleteTagTable(Ttk_TagTable);
MODULE_SCOPE Ttk_Tag Ttk_GetTag(Ttk_TagTable, const char *tagName);
MODULE_SCOPE Ttk_Tag Ttk_GetTagFromObj(Ttk_TagTable, Tcl_Obj *);
-MODULE_SCOPE Tcl_Obj **Ttk_TagRecord(Ttk_Tag);
+MODULE_SCOPE Tcl_Obj *Ttk_TagOptionValue(
+ Tcl_Interp *, Ttk_TagTable, Ttk_Tag, Tcl_Obj *optionName);
-MODULE_SCOPE int Ttk_GetTagListFromObj(
- Tcl_Interp *interp, Ttk_TagTable, Tcl_Obj *objPtr,
- int *nTags_rtn, void **taglist_rtn);
+MODULE_SCOPE int Ttk_EnumerateTagOptions(
+ Tcl_Interp *, Ttk_TagTable, Ttk_Tag);
-MODULE_SCOPE void Ttk_FreeTagList(void **taglist);
+MODULE_SCOPE int Ttk_ConfigureTag(
+ Tcl_Interp *interp, Ttk_TagTable tagTable, Ttk_Tag tag,
+ int objc, Tcl_Obj *const objv[]);
+
+MODULE_SCOPE Ttk_TagSet Ttk_GetTagSetFromObj(
+ Tcl_Interp *interp, Ttk_TagTable, Tcl_Obj *objPtr);
+
+MODULE_SCOPE void Ttk_FreeTagSet(Ttk_TagSet);
+
+MODULE_SCOPE int Ttk_TagSetContains(Ttk_TagSet, Ttk_Tag tag);
+MODULE_SCOPE void Ttk_TagSetAdd(Ttk_TagSet, Ttk_Tag tag);
+MODULE_SCOPE void Ttk_TagSetRemove(Ttk_TagSet, Ttk_Tag tag);
+
+MODULE_SCOPE void Ttk_TagSetValues(Ttk_TagTable, Ttk_TagSet, void *record);
+MODULE_SCOPE void Ttk_TagSetApplyStyle(Ttk_TagTable,Ttk_Style,Ttk_State,void*);
/*
* Useful widget base classes:
diff --git a/library/ttk/altTheme.tcl b/library/ttk/altTheme.tcl
index c92e3d5..e604373 100644
--- a/library/ttk/altTheme.tcl
+++ b/library/ttk/altTheme.tcl
@@ -1,5 +1,5 @@
#
-# $Id: altTheme.tcl,v 1.6 2007/12/13 15:27:07 dgp Exp $
+# $Id: altTheme.tcl,v 1.7 2008/05/23 20:20:05 jenglish Exp $
#
# Ttk widget set: Alternate theme
#
@@ -80,15 +80,8 @@ namespace eval ttk::theme::alt {
# 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 \
+ ttk::style configure Treeview -background $colors(-window)
+ ttk::style map Treeview \
-background [list selected $colors(-selectbg)] \
-foreground [list selected $colors(-selectfg)] ;
diff --git a/library/ttk/aquaTheme.tcl b/library/ttk/aquaTheme.tcl
index bc6d4e9..ccb8bd3 100644
--- a/library/ttk/aquaTheme.tcl
+++ b/library/ttk/aquaTheme.tcl
@@ -1,5 +1,5 @@
#
-# $Id: aquaTheme.tcl,v 1.11 2007/12/13 15:27:08 dgp Exp $
+# $Id: aquaTheme.tcl,v 1.12 2008/05/23 20:20:06 jenglish Exp $
#
# Aqua theme (OSX native look and feel)
#
@@ -38,14 +38,10 @@ namespace eval ttk::theme::aqua {
ttk::style configure TCombobox -postoffset {5 -2 -10 0}
# Treeview:
- ttk::style configure Treeview -rowheight 18
ttk::style configure Heading -font TkHeadingFont
- ttk::style map Row -background [list \
+ ttk::style configure Treeview -rowheight 18 -background White
+ ttk::style map Treeview -background [list \
{selected background} "#c3c3c3" selected SystemHighlight] ;
- ttk::style map Cell -foreground [list \
- {selected background} "#000000" selected SystemHighlightText] ;
- ttk::style map Item -foreground [list \
- {selected background} "#000000" selected SystemHighlightText] ;
# Enable animation for ttk::progressbar widget:
ttk::style configure TProgressbar -period 100 -maxphase 255
diff --git a/library/ttk/clamTheme.tcl b/library/ttk/clamTheme.tcl
index c4c8184..799b6ae 100644
--- a/library/ttk/clamTheme.tcl
+++ b/library/ttk/clamTheme.tcl
@@ -1,5 +1,5 @@
#
-# $Id: clamTheme.tcl,v 1.6 2007/12/13 15:27:08 dgp Exp $
+# $Id: clamTheme.tcl,v 1.7 2008/05/23 20:20:06 jenglish Exp $
#
# "Clam" theme.
#
@@ -116,15 +116,8 @@ namespace eval ttk::theme::clam {
# 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 \
+ ttk::style configure Treeview -background $colors(-window)
+ ttk::style map Treeview \
-background [list selected $colors(-selectbg)] \
-foreground [list selected $colors(-selectfg)] ;
diff --git a/library/ttk/classicTheme.tcl b/library/ttk/classicTheme.tcl
index c96d7ff..48c3df8 100644
--- a/library/ttk/classicTheme.tcl
+++ b/library/ttk/classicTheme.tcl
@@ -1,5 +1,5 @@
#
-# $Id: classicTheme.tcl,v 1.6 2007/12/13 15:27:08 dgp Exp $
+# $Id: classicTheme.tcl,v 1.7 2008/05/23 20:20:06 jenglish Exp $
#
# "classic" Tk theme.
#
@@ -87,12 +87,8 @@ namespace eval ttk::theme::classic {
# 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 \
+ ttk::style configure Treeview -background $colors(-window)
+ ttk::style map Treeview \
-background [list selected $colors(-selectbg)] \
-foreground [list selected $colors(-selectfg)] ;
diff --git a/library/ttk/defaults.tcl b/library/ttk/defaults.tcl
index 500562d..dfb6654 100644
--- a/library/ttk/defaults.tcl
+++ b/library/ttk/defaults.tcl
@@ -1,5 +1,5 @@
#
-# $Id: defaults.tcl,v 1.6 2007/12/13 15:27:08 dgp Exp $
+# $Id: defaults.tcl,v 1.7 2008/05/23 20:20:06 jenglish Exp $
#
# Settings for default theme.
#
@@ -8,7 +8,9 @@ namespace eval ttk::theme::default {
variable colors
array set colors {
-frame "#d9d9d9"
+ -foreground "#000000"
-window "#ffffff"
+ -text "#000000"
-activebg "#ececec"
-selectbg "#4a6984"
-selectfg "#ffffff"
@@ -22,7 +24,7 @@ namespace eval ttk::theme::default {
ttk::style configure "." \
-borderwidth 1 \
-background $colors(-frame) \
- -foreground black \
+ -foreground $colors(-foreground) \
-troughcolor $colors(-darker) \
-font TkDefaultFont \
-selectborderwidth 1 \
@@ -85,15 +87,10 @@ namespace eval ttk::theme::default {
# 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 \
+ ttk::style configure Treeview \
+ -background $colors(-window) \
+ -foreground $colors(-text) ;
+ ttk::style map Treeview \
-background [list selected $colors(-selectbg)] \
-foreground [list selected $colors(-selectfg)] ;
diff --git a/library/ttk/treeview.tcl b/library/ttk/treeview.tcl
index d2a1015..608cdf2 100644
--- a/library/ttk/treeview.tcl
+++ b/library/ttk/treeview.tcl
@@ -1,4 +1,4 @@
-# $Id: treeview.tcl,v 1.5 2008/04/25 19:08:32 jenglish Exp $
+# $Id: treeview.tcl,v 1.6 2008/05/23 20:20:06 jenglish Exp $
#
# ttk::treeview widget bindings and utilities.
#
@@ -21,15 +21,6 @@ namespace eval ttk::treeview {
# For pressmode == "heading"
set State(heading) {}
-
- # Provide [lassign] if not already present
- # (@@@ TODO: check if this is still needed after horrible-identify purge)
- #
- if {![llength [info commands lassign]]} {
- proc lassign {vals args} {
- uplevel 1 [list foreach $args $vals break]
- }
- }
}
### Widget bindings.
@@ -118,10 +109,9 @@ proc ttk::treeview::Motion {w x y} {
set cursor {}
set activeHeading {}
- lassign [$w identify $x $y] what where detail
- switch -- $what {
+ switch -- [$w identify region $x $y] {
separator { set cursor $Cursors(hresize) }
- heading { set activeHeading $where }
+ heading { set activeHeading [$w identify column $x $y] }
}
if {[$w cget -cursor] ne $cursor} {
@@ -170,19 +160,20 @@ proc ttk::treeview::DoubleClick {w x y} {
## Press -- ButtonPress binding.
#
proc ttk::treeview::Press {w x y} {
- lassign [$w identify $x $y] what where detail
- focus $w ;# or: ClickToFocus?
-
- switch -- $what {
+ focus $w
+ switch -- [$w identify region $x $y] {
nothing { }
- heading { heading.press $w $where }
- separator { resize.press $w $x $where }
- cell -
- row -
- item { SelectOp $w $where choose }
- }
- if {$what eq "item" && [string match *indicator $detail]} {
- Toggle $w $where
+ heading { heading.press $w $x $y }
+ separator { resize.press $w $x $y }
+ tree -
+ cell {
+ set item [$w identify item $x $y]
+ SelectOp $w $item choose
+ switch -glob -- [$w identify element $x $y] {
+ *indicator -
+ *disclosure { Toggle $w $item }
+ }
+ }
}
}
@@ -208,10 +199,10 @@ proc ttk::treeview::Release {w x y} {
### Interactive column resizing.
#
-proc ttk::treeview::resize.press {w x column} {
+proc ttk::treeview::resize.press {w x y} {
variable State
set State(pressMode) "resize"
- set State(resizeColumn) $column
+ set State(resizeColumn) [$w identify column $x $y]
}
proc ttk::treeview::resize.drag {w x} {
@@ -226,8 +217,9 @@ proc ttk::treeview::resize.release {w x} {
### Heading activation.
#
-proc ttk::treeview::heading.press {w column} {
+proc ttk::treeview::heading.press {w x y} {
variable State
+ set column [$w identify column $x $y]
set State(pressMode) "heading"
set State(heading) $column
$w heading $column state pressed
@@ -235,8 +227,9 @@ proc ttk::treeview::heading.press {w column} {
proc ttk::treeview::heading.drag {w x y} {
variable State
- lassign [$w identify $x $y] what where detail
- if {$what eq "heading" && $where eq $State(heading)} {
+ if { [$w identify region $x $y] eq "heading"
+ && [$w identify column $x $y] eq $State(heading)
+ } {
$w heading $State(heading) state pressed
} else {
$w heading $State(heading) state !pressed
diff --git a/library/ttk/winTheme.tcl b/library/ttk/winTheme.tcl
index 20f45de..03ca6d2 100644
--- a/library/ttk/winTheme.tcl
+++ b/library/ttk/winTheme.tcl
@@ -1,5 +1,5 @@
#
-# $Id: winTheme.tcl,v 1.6 2007/12/13 15:27:08 dgp Exp $
+# $Id: winTheme.tcl,v 1.7 2008/05/23 20:20:06 jenglish Exp $
#
# Settings for 'winnative' theme.
#
@@ -59,15 +59,8 @@ namespace eval ttk::theme::winnative {
# Treeview:
ttk::style configure Heading -font TkHeadingFont -relief raised
- ttk::style configure Row -background SystemWindow
- ttk::style configure Cell -background SystemWindow
- ttk::style map Row \
- -background [list selected SystemHighlight] \
- -foreground [list selected SystemHighlightText] ;
- ttk::style map Cell \
- -background [list selected SystemHighlight] \
- -foreground [list selected SystemHighlightText] ;
- ttk::style map Item \
+ ttk::style configure Treeview -background SystemWindow
+ ttk::style map Treeview \
-background [list selected SystemHighlight] \
-foreground [list selected SystemHighlightText] ;
diff --git a/library/ttk/xpTheme.tcl b/library/ttk/xpTheme.tcl
index d85d415..691dcea 100644
--- a/library/ttk/xpTheme.tcl
+++ b/library/ttk/xpTheme.tcl
@@ -1,5 +1,5 @@
#
-# $Id: xpTheme.tcl,v 1.8 2008/05/15 23:41:08 patthoyts Exp $
+# $Id: xpTheme.tcl,v 1.9 2008/05/23 20:20:06 jenglish Exp $
#
# Settings for 'xpnative' theme
#
@@ -31,15 +31,8 @@ namespace eval ttk::theme::xpnative {
# Treeview:
ttk::style configure Heading -font TkHeadingFont
- ttk::style configure Row -background SystemWindow
- ttk::style configure Cell -background SystemWindow
- ttk::style map Row \
- -background [list selected SystemHighlight] \
- -foreground [list selected SystemHighlightText] ;
- ttk::style map Cell \
- -background [list selected SystemHighlight] \
- -foreground [list selected SystemHighlightText] ;
- ttk::style map Item \
+ ttk::style configure Treeview -background SystemWindow
+ ttk::style map Treeview \
-background [list selected SystemHighlight] \
-foreground [list selected SystemHighlightText] ;
diff --git a/tests/ttk/treeview.test b/tests/ttk/treeview.test
index d2b33a9..2a58444 100644
--- a/tests/ttk/treeview.test
+++ b/tests/ttk/treeview.test
@@ -1,5 +1,5 @@
#
-# $Id: treeview.test,v 1.3 2008/01/06 19:16:12 jenglish Exp $
+# $Id: treeview.test,v 1.4 2008/05/23 20:20:07 jenglish Exp $
#
# [7Jun2005] TO CHECK: [$tv see {}] -- shouldn't work (at least, shouldn't do
# what it currently does)
@@ -245,7 +245,7 @@ test treeview-3.15 "Consecutive duplicate entries in children list" -body {
} -result [list x1 x2 x3]
test treeview-3.16 "Insert child after self" -body {
- .tv move x2 newfirstone 1
+ .tv move x2 newfirstone 1
consistencyCheck .tv
.tv children newfirstone
} -result [list x1 x2 x3]
@@ -262,7 +262,6 @@ test treeview-3.18 "Insert last child after end" -body {
.tv children newfirstone
} -result [list x1 x2 x3]
-
test treeview-4.1 "opened - initial state" -body {
.tv item newnode -open
} -result 0
@@ -290,12 +289,12 @@ test treeview-5.3 "Heading" -body {
test treeview-5.4 "get cell" -body {
set l [list a b c]
.tv item newnode -values $l
- .tv set newnode 1
+ .tv set newnode 1
} -result b
test treeview-5.5 "set cell" -body {
.tv set newnode 1 XXX
- .tv item newnode -values
+ .tv item newnode -values
} -result [list a XXX c]
test treeview-5.6 "set illegal cell" -body {
@@ -408,11 +407,11 @@ test treeview-7.1 "move" -body {
test treeview-7.2 "illegal move" -body {
.tv move d d2 end
-} -returnCodes 1 -result "Cannot insert d as a descendant of d2"
+} -returnCodes 1 -result "Cannot insert d as a descendant of d2"
test treeview-7.3 "illegal move has no effect" -body {
consistencyCheck .tv
- .tv children d
+ .tv children d
} -result [list d3 d1 d2]
test treeview-7.4 "Replace children" -body {
@@ -474,8 +473,109 @@ test treeview-9.0 "scroll callback - empty tree" -body {
set ::scrolldata
} -result [list 0 1]
-### NEED: tests for focus item, selection
+### identify tests:
+#
+proc identify* {tv comps args} {
+ foreach {x y} $args {
+ foreach comp $comps {
+ lappend result [$tv identify $comp $x $y]
+ }
+ }
+ return $result
+}
+# get list of column IDs from list of display column ids.
+#
+proc columnids {tv dcols} {
+ set result [list]
+ foreach dcol $dcols {
+ if {[catch {
+ lappend result [$tv column $dcol -id]
+ }]} {
+ lappend result ERROR
+ }
+ }
+ return $result
+}
+
+test treeview-identify-setup "identify series - setup" -body {
+ destroy .tv
+ ttk::setTheme default
+ ttk::treeview .tv -columns [list A B C]
+ .tv insert {} end -id branch -text branch -open true
+ .tv insert branch end -id item1 -text item1
+ .tv insert branch end -id item2 -text item2
+ .tv insert branch end -id item3 -text item3
+
+ .tv column #0 -width 50 ;# 0-50
+ .tv column A -width 50 ;# 50-100
+ .tv column B -width 50 ;# 100-150
+ .tv column C -width 50 ;# 150-200 (plus slop for margins)
+
+ wm geometry . {} ; pack .tv ; update
+}
+
+test treeview-identify-1 "identify heading" -body {
+ .tv configure -show {headings tree}
+ update idletasks
+ identify* .tv {region column} 10 10
+} -result [list heading #0]
+
+test treeview-identify-2 "identify columns" -body {
+ .tv configure -displaycolumns #all
+ update idletasks
+ columnids .tv [identify* .tv column 25 10 75 10 125 10 175 10]
+} -result [list {} A B C]
+
+test treeview-identify-3 "reordered columns" -body {
+ .tv configure -displaycolumns {B A C}
+ update idletasks
+ columnids .tv [identify* .tv column 25 10 75 10 125 10 175 10]
+} -result [list {} B A C]
+
+test treeview-identify-4 "no tree column" -body {
+ .tv configure -displaycolumns #all -show {headings}
+ update idletasks
+ identify* .tv {region column} 25 10 75 10 125 10 175 10
+} -result [list heading #1 heading #2 heading #3 nothing {}]
+
+# Item height in default theme is 20px
+test treeview-identify-5 "vertical scan - no headings" -body {
+ .tv configure -displaycolumns #all -show {tree}
+ update idletasks
+ identify* .tv {region item} 25 10 25 30 25 50 25 70 25 90
+} -result [list tree branch tree item1 tree item2 tree item3 nothing {}]
+
+test treeview-identify-6 "vertical scan - with headings" -body {
+ .tv configure -displaycolumns #all -show {tree headings}
+ update idletasks
+ identify* .tv {region item} 25 10 25 30 25 50 25 70 25 90
+} -result [list heading {} tree branch tree item1 tree item2 tree item3]
+
+test treeview-identify-7 "vertical scan - headings, no tree" -body {
+ .tv configure -displaycolumns #all -show {headings}
+ update idletasks
+ identify* .tv {region item} 25 10 25 30 25 50 25 70 25 90
+} -result [list heading {} cell branch cell item1 cell item2 cell item3]
+
+# In default theme, -indent and -itemheight both 20px
+# Disclosure element name is "Treeitem.indicator"
+set disclosure "*.indicator"
+test treeview-identify-8 "identify element" -body {
+ .tv configure -show {tree}
+ .tv insert branch 0 -id branch2 -open true
+ .tv insert branch2 0 -id branch3 -open true
+ .tv insert branch3 0 -id leaf3
+ update idletasks;
+ identify* .tv {item element} 10 10 30 30 50 50
+} -match glob -result [list \
+ branch $disclosure branch2 $disclosure branch3 $disclosure]
+
+test treeview-identify-cleanup "identify - cleanup" -body {
+ destroy .tv
+}
+
+### NEED: tests for focus item, selection
### Misc. tests: