summaryrefslogtreecommitdiffstats
path: root/generic/ttk/ttkTagSet.c
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 /generic/ttk/ttkTagSet.c
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.
Diffstat (limited to 'generic/ttk/ttkTagSet.c')
-rw-r--r--generic/ttk/ttkTagSet.c191
1 files changed, 143 insertions, 48 deletions
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;
+ }
}