diff options
author | hobbs <hobbs> | 2010-08-26 02:06:08 (GMT) |
---|---|---|
committer | hobbs <hobbs> | 2010-08-26 02:06:08 (GMT) |
commit | b29adcfbfc2e03e058536524f1aa3378b948e7ed (patch) | |
tree | fa90e1e6d32590addfbb0a1599a40b1f7f99ea3b /generic/ttk/ttkTagSet.c | |
parent | 7dec1714e5d5efd6b7d095657c1434fa68af0f87 (diff) | |
download | tk-b29adcfbfc2e03e058536524f1aa3378b948e7ed.zip tk-b29adcfbfc2e03e058536524f1aa3378b948e7ed.tar.gz tk-b29adcfbfc2e03e058536524f1aa3378b948e7ed.tar.bz2 |
Major backport of 8.6 Ttk for 8.5.9. Most changes were only being
committed to head (8.6), although they could apply for 8.5 as well.
This re-sync makes future work easier to maintain and adds some
useful work for 8.5 users. Notable changes:
- Lots of code cleanup
- Some bug fixes never backported
- Addition of ttk::spinbox
- minor color changes
- Improved Vista/7 styling
- Move to tile version 0.8.6 (pseudo-package)
- ABI and API compatible (even $w identify)
- minor new features (extended $w identify)
Diffstat (limited to 'generic/ttk/ttkTagSet.c')
-rw-r--r-- | generic/ttk/ttkTagSet.c | 260 |
1 files changed, 210 insertions, 50 deletions
diff --git a/generic/ttk/ttkTagSet.c b/generic/ttk/ttkTagSet.c index 85624a2..fd4c538 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.3.4.1 2010/08/26 02:06:09 hobbs 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,53 +16,55 @@ * +++ Internal data structures. */ struct TtkTag { - Tcl_Obj **tagRecord; /* ... hrmph. */ + int priority; /* 1=>highest */ + const char *tagName; /* Back-pointer to hash table entry */ + void *tagRecord; /* User data */ }; 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 */ }; /*------------------------------------------------------------------------ * +++ Tags. */ -static Ttk_Tag NewTag(Ttk_TagTable tagTable) +static Ttk_Tag NewTag(Ttk_TagTable tagTable, const char *tagName) { 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; + tag->tagName = tagName; 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 +73,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); } @@ -90,7 +91,8 @@ Ttk_Tag Ttk_GetTag(Ttk_TagTable tagTable, const char *tagName) &tagTable->tags, tagName, &isNew); if (isNew) { - Tcl_SetHashValue(entryPtr, NewTag(tagTable)); + tagName = Tcl_GetHashKey(&tagTable->tags, entryPtr); + Tcl_SetHashValue(entryPtr, NewTag(tagTable,tagName)); } return Tcl_GetHashValue(entryPtr); } @@ -100,48 +102,206 @@ 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. + * + * Returns NULL and leaves an error message in interp->result on error. * - * Result must be passed to Ttk_FreeTagList(). + * 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]); + } + tagset->tags[i] = NULL; + tagset->nTags = objc; + + return tagset; +} + +/* Ttk_NewTagSetObj -- + * Construct a fresh Tcl_Obj * from a tag set. + */ +Tcl_Obj *Ttk_NewTagSetObj(Ttk_TagSet tagset) +{ + Tcl_Obj *result = Tcl_NewListObj(0,0); + int i; + + for (i = 0; i < tagset->nTags; ++i) { + Tcl_ListObjAppendElement( + NULL, result, Tcl_NewStringObj(tagset->tags[i]->tagName, -1)); } - tags[i] = NULL; + return result; +} - *taglist_rtn = tags; - *nTags_rtn = objc; +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; +} - return TCL_OK; +/* Ttk_TagSetAdd -- add a tag to a tag set. + * + * Returns: 0 if tagset already contained tag, + * 1 if tagset was modified. + */ +int Ttk_TagSetAdd(Ttk_TagSet tagset, Ttk_Tag tag) +{ + int i; + for (i = 0; i < tagset->nTags; ++i) { + if (tagset->tags[i] == tag) { + return 0; + } + } + tagset->tags = (void*)ckrealloc((void*)tagset->tags, + (tagset->nTags+1)*sizeof(tagset->tags[0])); + tagset->tags[tagset->nTags++] = tag; + return 1; } -void Ttk_FreeTagList(void **taglist) +/* Ttk_TagSetRemove -- remove a tag from a tag set. + * + * Returns: 0 if tagset did not contain tag, + * 1 if tagset was modified. + */ +int Ttk_TagSetRemove(Ttk_TagSet tagset, Ttk_Tag tag) { - if (taglist) - ckfree((ClientData)taglist); + int i = 0, j = 0; + while (i < tagset->nTags) { + if ((tagset->tags[j] = tagset->tags[i]) != tag) { + ++j; + } + ++i; + } + tagset->nTags = j; + return j != i; +} + +/*------------------------------------------------------------------------ + * +++ Utilities for widget commands. + */ + +/* Ttk_EnumerateTags -- implements [$w tag names] + */ +int Ttk_EnumerateTags( + Tcl_Interp *interp, Ttk_TagTable tagTable) +{ + return TtkEnumerateHashTable(interp, &tagTable->tags); +} + +/* 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); +} + +/* Ttk_TagOptionValue -- implements [$w tag configure $tag -option] + */ +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. + */ + +#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_TagSetApplyStyle( + Ttk_TagTable tagTable, Ttk_Style style, Ttk_State state, void *record) +{ + 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; + } } |