summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog12
-rw-r--r--doc/ttk_image.n31
-rw-r--r--generic/ttk/ttkButton.c127
-rw-r--r--generic/ttk/ttkImage.c300
-rw-r--r--generic/ttk/ttkLabel.c75
-rw-r--r--generic/ttk/ttkNotebook.c4
-rw-r--r--generic/ttk/ttkTheme.h11
-rw-r--r--generic/ttk/ttkTreeview.c12
-rw-r--r--generic/ttk/ttkWidget.h9
-rw-r--r--tests/ttk/image.test27
10 files changed, 302 insertions, 306 deletions
diff --git a/ChangeLog b/ChangeLog
index 9008fde..a6717b2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2006-12-09 Joe English <jenglish@users.sourceforge.net>
+
+ * generic/ttk/ttkButton.c, generic/ttk/ttkImage.c,
+ generic/ttk/ttkLabel.c, generic/ttk/ttkWidget.h,
+ generic/ttk/ttkTheme.h, generic/ttk/ttkNotebook.c,
+ generic/ttk/ttkTreeview.c, doc/ttk_image.n:
+ Merged duplicate functionality between image element factory,
+ image element, and -image option processing. Image element
+ factory now takes an imageSpec argument instead of a separate
+ image name and -map option.
+ * tests/ttk/image.test(image-1.1): Can catch this error earlier now.
+
2006-12-06 Kevin Kenny <kennykb@acm.org>
* unix/configure.in: Further changes to avoid attempting to link
diff --git a/doc/ttk_image.n b/doc/ttk_image.n
index bcda678..30c6698 100644
--- a/doc/ttk_image.n
+++ b/doc/ttk_image.n
@@ -1,6 +1,6 @@
'\"
'\" Copyright (c) 2004 Joe English
-'\" $Id: ttk_image.n,v 1.3 2006/11/16 13:25:11 dkf Exp $
+'\" $Id: ttk_image.n,v 1.4 2006/12/09 20:53:35 jenglish Exp $
'\"
.so man.macros
.TH ttk_image n 8.5 Tk "Tk Themed Widget"
@@ -8,12 +8,17 @@
.SH NAME
ttk_image \- Define an element based on an image
.SH SYNOPSIS
-\fBttk::style create element \fIname\fR \fBimage\fR \fIimageName\fR ?\fIoptions\fR?
+\fBttk::style element create \fIname\fR \fBimage\fR \fIimageSpec\fR ?\fIoptions\fR?
.BE
.SH DESCRIPTION
The \fIimage\fR element factory creates a new element
in the current theme whose visual appearance is determined
-by a Tk image.
+by Tk images.
+\fIimageSpec\fP is a list of one or more elements.
+The first element is the default image name.
+The rest of the list is a sequence of \fIstatespec / value\fR
+pairs specifying other images to use when the element is
+in a particular state or combination of states.
.SH OPTIONS
Valid \fIoptions\fR are:
.TP
@@ -26,16 +31,6 @@ See \fBIMAGE STRETCHING\fR, below.
Specifies a minimum height for the element.
If less than zero, the base image's height is used as a default.
.TP
-\fB-map { \fIstatespec\fR \fIimage\fR.. }
-Specifies auxilliary images to use in different states.
-Each \fIstatespec\fR is a list of state names optionally
-prefixed by an exclamation point, as in \fBttk::style map\fR.
-Each \fIimageName\fR is the name of a Tk image
-defined with \fBimage create ...\fR.
-When the element is displayed, each \fIstatespec\fR is
-tested in order, and the \fIimage\fR corresponding to
-the first matching \fIstatespec\fR is used.
-If none match, the base \fIimageName\fR is used.
.TP
\fB-padding\fR \fIpadding\fR
Specifies the element's interior padding. Defaults to
@@ -62,10 +57,12 @@ left and right edges (which may be tiled vertically),
and the central area (which may be tiled in both directions).
.SH "EXAMPLE"
.CS
-set button(normal) [image create photo -file button.png]
-set button(pressed) [image create photo -file button-pressed.png]
-ttk::style element create Button.button \fBimage\fR $button(normal) \e
- -border {2 4} -map [list pressed $button(pressed)] -sticky nswe
+set img1 [image create photo -file button.png]
+set img2 [image create photo -file button-pressed.png]
+set img3 [image create photo -file button-active.png]
+style element create Button.button image \e
+ [list $img1 pressed $img2 active $img3] \e
+ -border {2 4} -sticky we
.CE
.SH "SEE ALSO"
image(n), photo(n)
diff --git a/generic/ttk/ttkButton.c b/generic/ttk/ttkButton.c
index e69c5c2..033279f 100644
--- a/generic/ttk/ttkButton.c
+++ b/generic/ttk/ttkButton.c
@@ -1,8 +1,7 @@
-/* $Id: ttkButton.c,v 1.2 2006/11/03 03:06:22 das Exp $
+/* $Id: ttkButton.c,v 1.3 2006/12/09 20:53:35 jenglish Exp $
* Copyright (c) 2003, Joe English
*
- * Ttk widget set: label, button, checkbutton, radiobutton, and
- * menubutton widgets.
+ * label, button, checkbutton, radiobutton, and menubutton widgets.
*/
#include <string.h>
@@ -29,7 +28,7 @@ typedef struct
Tcl_Obj *widthObj;
Ttk_TraceHandle *textVariableTrace;
- Tk_Image *images;
+ Ttk_ImageSpec *imageSpec;
/*
* Image element resources:
@@ -119,106 +118,12 @@ static void TextVariableChanged(void *clientData, const char *value)
TtkResizeWidget(&basePtr->core);
}
-/*
- * Tk_ImageChangedProc for -image option:
- */
-static void CoreImageChangedProc(ClientData clientData,
- int x, int y, int width, int height, int imageWidth, int imageHeight)
-{
- WidgetCore *corePtr = (WidgetCore *)clientData;
- TtkRedisplayWidget(corePtr);
-}
-
-/* TtkGetImageList --
- * ConfigureProc utility routine for handling -image option.
- * Verifies that -image is a valid image specification,
- * registers image-changed callbacks for each image (via Tk_GetImage).
- *
- * The -image option is a multi-element list; the first element
- * is the name of the default image to use, the remainder of the
- * list is a sequence of statespec/imagename options as per
- * [style map].
- *
- * Returns: TCL_OK if image specification is valid and sets *imageListPtr
- * to a NULL-terminated list of Tk_Images; otherwise TCL_ERROR
- * and leaves an error message in the interpreter result.
- */
-int TtkGetImageList(
- Tcl_Interp *interp,
- WidgetCore *corePtr,
- Tcl_Obj *imageOption,
- Tk_Image **imageListPtr)
-{
- int i, mapCount, imageCount;
- Tcl_Obj **mapList;
- Tk_Image *images;
-
- if (Tcl_ListObjGetElements(interp,
- imageOption, &mapCount, &mapList) != TCL_OK)
- {
- return TCL_ERROR;
- }
-
- if (mapCount == 0) {
- *imageListPtr = 0;
- return TCL_OK;
- }
-
- if ((mapCount % 2) != 1) {
- Tcl_SetResult(interp,
- "-image value must contain an odd number of elements", TCL_STATIC);
- return TCL_ERROR;
- }
-
- /* Verify state specifications:
- */
- for (i = 1; i < mapCount -1; i += 2) {
- Ttk_StateSpec spec;
- if (Ttk_GetStateSpecFromObj(interp, mapList[i], &spec) != TCL_OK)
- return TCL_ERROR;
- }
-
- /* Get images:
- */
- imageCount = (mapCount + 1) / 2;
- images = (Tk_Image*)ckalloc((imageCount+1) * sizeof(Tk_Image));
-
- for (i = 0; i < imageCount; ++i) {
- const char *imageName = Tcl_GetString(mapList[i * 2]);
- images[i] = Tk_GetImage(interp, corePtr->tkwin,
- imageName, CoreImageChangedProc, corePtr);
-
- if (!images[i]) {
- while (i--)
- Tk_FreeImage(images[i]);
- ckfree((ClientData)images);
- return TCL_ERROR;
- }
- }
- images[i] = NULL; /* Add null terminator */
-
- *imageListPtr = images;
- return TCL_OK;
-}
-
-/*
- * TtkFreeImageList --
- * Release an image list obtained by TtkGetImageList.
- */
-void TtkFreeImageList(Tk_Image *imageList)
-{
- Tk_Image *p;
- for (p = imageList; *p; ++p)
- Tk_FreeImage(*p);
- ckfree((ClientData)imageList);
-}
-
static int
BaseInitialize(Tcl_Interp *interp, void *recordPtr)
{
Base *basePtr = recordPtr;
basePtr->base.textVariableTrace = 0;
- basePtr->base.images = NULL;
+ basePtr->base.imageSpec = NULL;
return TCL_OK;
}
@@ -228,8 +133,8 @@ BaseCleanup(void *recordPtr)
Base *basePtr = recordPtr;
if (basePtr->base.textVariableTrace)
Ttk_UntraceVariable(basePtr->base.textVariableTrace);
- if (basePtr->base.images)
- TtkFreeImageList(basePtr->base.images);
+ if (basePtr->base.imageSpec)
+ TtkFreeImageSpec(basePtr->base.imageSpec);
}
static int BaseConfigure(Tcl_Interp *interp, void *recordPtr, int mask)
@@ -237,22 +142,24 @@ static int BaseConfigure(Tcl_Interp *interp, void *recordPtr, int mask)
Base *basePtr = recordPtr;
Tcl_Obj *textVarName = basePtr->base.textVariableObj;
Ttk_TraceHandle *vt = 0;
- Tk_Image *images = NULL;
+ Ttk_ImageSpec *imageSpec = NULL;
if (textVarName != NULL && *Tcl_GetString(textVarName) != '\0') {
vt = Ttk_TraceVariable(interp,textVarName,TextVariableChanged,basePtr);
if (!vt) return TCL_ERROR;
}
- if (basePtr->base.imageObj && TtkGetImageList(interp,
- &basePtr->core, basePtr->base.imageObj, &images) != TCL_OK)
- {
- goto error;
+ if (basePtr->base.imageObj) {
+ imageSpec = TtkGetImageSpec(
+ interp, basePtr->core.tkwin, basePtr->base.imageObj);
+ if (!imageSpec) {
+ goto error;
+ }
}
if (TtkCoreConfigure(interp, recordPtr, mask) != TCL_OK) {
error:
- if (images) TtkFreeImageList(images);
+ if (imageSpec) TtkFreeImageSpec(imageSpec);
if (vt) Ttk_UntraceVariable(vt);
return TCL_ERROR;
}
@@ -262,10 +169,10 @@ error:
}
basePtr->base.textVariableTrace = vt;
- if (basePtr->base.images) {
- TtkFreeImageList(basePtr->base.images);
+ if (basePtr->base.imageSpec) {
+ TtkFreeImageSpec(basePtr->base.imageSpec);
}
- basePtr->base.images = images;
+ basePtr->base.imageSpec = imageSpec;
if (mask & STATE_CHANGED) {
TtkCheckStateOption(&basePtr->core, basePtr->base.stateObj);
diff --git a/generic/ttk/ttkImage.c b/generic/ttk/ttkImage.c
index 4d80f48..7f0a2af 100644
--- a/generic/ttk/ttkImage.c
+++ b/generic/ttk/ttkImage.c
@@ -1,9 +1,13 @@
-/* $Id: ttkImage.c,v 1.3 2006/11/27 06:53:55 jenglish Exp $
- * Ttk widget set -- image element factory.
+/* $Id: ttkImage.c,v 1.4 2006/12/09 20:53:35 jenglish Exp $
+ * Image specifications and image element factory.
*
* Copyright (C) 2004 Pat Thoyts <patthoyts@users.sf.net>
* Copyright (C) 2004 Joe English
*
+ * An imageSpec is a multi-element list; the first element
+ * is the name of the default image to use, the remainder of the
+ * list is a sequence of statespec/imagename options as per
+ * [style map].
*/
#include <string.h>
@@ -13,6 +17,127 @@
#define MIN(a,b) ((a) < (b) ? (a) : (b))
/*------------------------------------------------------------------------
+ * +++ ImageSpec management.
+ */
+
+struct TtkImageSpec {
+ Tk_Image baseImage; /* Base image to use */
+ int mapCount; /* #state-specific overrides */
+ Ttk_StateSpec *states; /* array[mapCount] of states ... */
+ Tk_Image *images; /* ... per-state images to use */
+};
+
+/* NullImageChanged --
+ * Do-nothing Tk_ImageChangedProc.
+ */
+static void NullImageChanged(ClientData clientData,
+ int x, int y, int width, int height, int imageWidth, int imageHeight)
+{ /* No-op */ }
+
+/* TtkGetImageSpec --
+ * Constructs a Ttk_ImageSpec * from a Tcl_Obj *.
+ * Result must be released using TtkFreeImageSpec.
+ *
+ * TODO: Need a variant of this that takes a user-specified ImageChanged proc
+ */
+Ttk_ImageSpec *
+TtkGetImageSpec(Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *objPtr)
+{
+ Ttk_ImageSpec *imageSpec = 0;
+ int i = 0, n = 0, objc;
+ Tcl_Obj **objv;
+
+ imageSpec = (Ttk_ImageSpec *)ckalloc(sizeof(*imageSpec));
+ imageSpec->baseImage = 0;
+ imageSpec->mapCount = 0;
+ imageSpec->states = 0;
+ imageSpec->images = 0;
+
+ if (Tcl_ListObjGetElements(interp, objPtr, &objc, &objv) != TCL_OK) {
+ goto error;
+ }
+
+ if ((objc % 2) != 1) {
+ if (interp) {
+ Tcl_SetResult(interp,
+ "image specification must contain an odd number of elements",
+ TCL_STATIC);
+ }
+ goto error;
+ }
+
+ n = (objc - 1) / 2;
+ imageSpec->states = (Ttk_StateSpec*)ckalloc(n * sizeof(Ttk_StateSpec));
+ imageSpec->images = (Tk_Image*)ckalloc(n * sizeof(Tk_Image *));
+
+ /* Get base image:
+ */
+ imageSpec->baseImage = Tk_GetImage(
+ interp, tkwin, Tcl_GetString(objv[0]), NullImageChanged, NULL);
+ if (!imageSpec->baseImage) {
+ goto error;
+ }
+
+ /* Extract state and image specifications:
+ */
+ for (i = 0; i < n; ++i) {
+ Tcl_Obj *stateSpec = objv[2*i + 1];
+ const char *imageName = Tcl_GetString(objv[2*i + 2]);
+ Ttk_StateSpec state;
+
+ if (Ttk_GetStateSpecFromObj(interp, stateSpec, &state) != TCL_OK) {
+ goto error;
+ }
+ imageSpec->states[i] = state;
+
+ imageSpec->images[i] = Tk_GetImage(
+ interp, tkwin, imageName, NullImageChanged, NULL);
+ if (imageSpec->images[i] == NULL) {
+ goto error;
+ }
+ imageSpec->mapCount = i+1;
+ }
+
+ return imageSpec;
+
+error:
+ TtkFreeImageSpec(imageSpec);
+ return NULL;
+}
+
+/* TtkFreeImageSpec --
+ * Dispose of an image specification.
+ */
+void TtkFreeImageSpec(Ttk_ImageSpec *imageSpec)
+{
+ int i;
+
+ for (i=0; i < imageSpec->mapCount; ++i) {
+ Tk_FreeImage(imageSpec->images[i]);
+ }
+
+ if (imageSpec->baseImage) { Tk_FreeImage(imageSpec->baseImage); }
+ if (imageSpec->states) { ckfree((ClientData)imageSpec->states); }
+ if (imageSpec->images) { ckfree((ClientData)imageSpec->images); }
+
+ ckfree((ClientData)imageSpec);
+}
+
+/* TtkSelectImage --
+ * Return a state-specific image from an ImageSpec
+ */
+Tk_Image TtkSelectImage(Ttk_ImageSpec *imageSpec, Ttk_State state)
+{
+ int i;
+ for (i = 0; i < imageSpec->mapCount; ++i) {
+ if (Ttk_StateMatches(state, imageSpec->states+i)) {
+ return imageSpec->images[i];
+ }
+ }
+ return imageSpec->baseImage;
+}
+
+/*------------------------------------------------------------------------
* +++ Drawing utilities.
*/
@@ -92,59 +217,35 @@ static void Ttk_Tile(
*/
typedef struct { /* ClientData for image elements */
- Ttk_ResourceCache cache; /* Resource cache for images */
- Tcl_Obj *baseImage; /* Name of default image */
- Ttk_StateMap imageMap; /* State-based lookup table for images */
- Tcl_Obj *stickyObj; /* Stickiness specification, NWSE */
- Tcl_Obj *borderObj; /* Border specification */
- Tcl_Obj *paddingObj; /* Padding specification */
+ Ttk_ImageSpec *imageSpec; /* Image(s) to use */
int minWidth; /* Minimum width; overrides image width */
int minHeight; /* Minimum width; overrides image width */
- unsigned sticky;
+ Ttk_Sticky sticky; /* -stickiness specification */
Ttk_Padding border; /* Fixed border region */
Ttk_Padding padding; /* Internal padding */
+
+#if TILE_07_COMPAT
+ Ttk_ResourceCache cache; /* Resource cache for images */
+ Ttk_StateMap imageMap; /* State-based lookup table for images */
+#endif
} ImageData;
static void FreeImageData(void *clientData)
{
ImageData *imageData = clientData;
- Tcl_DecrRefCount(imageData->baseImage);
+ if (imageData->imageSpec) { TtkFreeImageSpec(imageData->imageSpec); }
+#if TILE_07_COMPAT
if (imageData->imageMap) { Tcl_DecrRefCount(imageData->imageMap); }
- if (imageData->stickyObj) { Tcl_DecrRefCount(imageData->stickyObj); }
- if (imageData->borderObj) { Tcl_DecrRefCount(imageData->borderObj); }
- if (imageData->paddingObj) { Tcl_DecrRefCount(imageData->paddingObj); }
+#endif
ckfree(clientData);
}
-static Tk_OptionSpec ImageOptionSpecs[] =
-{
- { TK_OPTION_STRING, "-sticky", "sticky", "Sticky",
- "nswe", Tk_Offset(ImageData,stickyObj), -1,
- 0,0,0 },
- { TK_OPTION_STRING, "-border", "border", "Border",
- "0", Tk_Offset(ImageData,borderObj), -1,
- 0,0,0 },
- { TK_OPTION_STRING, "-padding", "padding", "Padding",
- NULL, Tk_Offset(ImageData,paddingObj), -1,
- TK_OPTION_NULL_OK,0,0 },
- { TK_OPTION_STRING, "-map", "map", "Map",
- "", Tk_Offset(ImageData,imageMap), -1,
- 0,0,0 },
- { TK_OPTION_INT, "-width", "width", "Width",
- "-1", -1, Tk_Offset(ImageData, minWidth),
- 0, 0, 0},
- { TK_OPTION_INT, "-height", "height", "Height",
- "-1", -1, Tk_Offset(ImageData, minHeight),
- 0, 0, 0},
- { TK_OPTION_END }
-};
-
-static void ImageElementGeometry(
+static void ImageElementSize(
void *clientData, void *elementRecord, Tk_Window tkwin,
int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
{
ImageData *imageData = clientData;
- Tk_Image image = Ttk_UseImage(imageData->cache,tkwin,imageData->baseImage);
+ Tk_Image image = imageData->imageSpec->baseImage;
if (image) {
Tk_SizeOfImage(image, widthPtr, heightPtr);
@@ -166,18 +267,23 @@ static void ImageElementDraw(
Drawable d, Ttk_Box b, unsigned int state)
{
ImageData *imageData = clientData;
- Tcl_Obj *imageObj = 0;
- Tk_Image image;
+ Tk_Image image = 0;
int imgWidth, imgHeight;
Ttk_Box src, dst;
+#if TILE_07_COMPAT
if (imageData->imageMap) {
- imageObj = Ttk_StateMapLookup(NULL, imageData->imageMap, state);
+ Tcl_Obj *imageObj = Ttk_StateMapLookup(NULL,imageData->imageMap,state);
+ if (imageObj) {
+ image = Ttk_UseImage(imageData->cache, tkwin, imageObj);
+ }
}
- if (!imageObj) {
- imageObj = imageData->baseImage;
+ if (!image) {
+ image = TtkSelectImage(imageData->imageSpec, state);
}
- image = Ttk_UseImage(imageData->cache, tkwin, imageObj);
+#else
+ image = TtkSelectImage(imageData->imageSpec, state);
+#endif
if (!image) {
return;
@@ -195,7 +301,7 @@ static Ttk_ElementSpec ImageElementSpec =
TK_STYLE_VERSION_2,
sizeof(NullElement),
TtkNullElementOptions,
- ImageElementGeometry,
+ ImageElementSize,
ImageElementDraw
};
@@ -210,58 +316,85 @@ Ttk_CreateImageElement(
const char *elementName,
int objc, Tcl_Obj *CONST objv[])
{
- Tk_OptionTable imageOptionTable =
- Tk_CreateOptionTable(interp, ImageOptionSpecs);
- ImageData *imageData;
+ const char *optionStrings[] =
+ { "-border","-height","-padding","-sticky","-width",NULL };
+ enum { O_BORDER, O_HEIGHT, O_PADDING, O_STICKY, O_WIDTH };
- imageData = (ImageData*)ckalloc(sizeof(*imageData));
+ Ttk_ImageSpec *imageSpec = 0;
+ ImageData *imageData = 0;
+ int padding_specified = 0;
+ int i;
if (objc <= 0) {
Tcl_AppendResult(interp, "Must supply a base image", NULL);
return TCL_ERROR;
}
- imageData->cache = Ttk_GetResourceCache(interp);
- imageData->imageMap = imageData->stickyObj
- = imageData->borderObj = imageData->paddingObj = 0;
- imageData->minWidth = imageData->minHeight = -1;
- imageData->sticky = TTK_FILL_BOTH; /* ??? Is this sensible */
- imageData->border = imageData->padding = Ttk_UniformPadding(0);
-
- /* Can't use Tk_InitOptions() here, since we don't have a Tk_Window
- */
- if (TCL_OK != Tk_SetOptions(interp, (ClientData)imageData,
- imageOptionTable, objc-1, objv+1,
- NULL/*tkwin*/, NULL/*savedOptions*/, NULL/*mask*/))
- {
- ckfree((ClientData)imageData);
+ imageSpec = TtkGetImageSpec(interp, Tk_MainWindow(interp), objv[0]);
+ if (!imageSpec) {
return TCL_ERROR;
}
- imageData->baseImage = Tcl_DuplicateObj(objv[0]);
-
- if (imageData->borderObj && Ttk_GetBorderFromObj(
- interp, imageData->borderObj, &imageData->border) != TCL_OK)
- {
- goto error;
- }
+ imageData = (ImageData*)ckalloc(sizeof(*imageData));
+ imageData->imageSpec = imageSpec;
+ imageData->minWidth = imageData->minHeight = -1;
+ imageData->sticky = TTK_FILL_BOTH;
+ imageData->border = imageData->padding = Ttk_UniformPadding(0);
+#if TILE_07_COMPAT
+ imageData->cache = Ttk_GetResourceCache(interp);
+ imageData->imageMap = 0;
+#endif
- imageData->padding = imageData->border;
+ for (i = 1; i < objc; i += 2) {
+ int option;
- if (imageData->paddingObj && Ttk_GetBorderFromObj(
- interp, imageData->paddingObj, &imageData->padding) != TCL_OK)
- {
- goto error;
- }
+ if (i == objc - 1) {
+ Tcl_AppendResult(interp,
+ "Value for ", Tcl_GetString(objv[i]), " missing",
+ NULL);
+ goto error;
+ }
- if (imageData->stickyObj && Ttk_GetStickyFromObj(
- interp, imageData->stickyObj, &imageData->sticky) != TCL_OK)
- {
- goto error;
+#if TILE_07_COMPAT
+ if (!strcmp("-map", Tcl_GetString(objv[i]))) {
+ imageData->imageMap = objv[i+1];
+ Tcl_IncrRefCount(imageData->imageMap);
+ continue;
+ }
+#endif
+
+ if (Tcl_GetIndexFromObj(interp, objv[i], optionStrings,
+ "option", 0, &option) != TCL_OK) { goto error; }
+
+ switch (option) {
+ case O_BORDER:
+ if (Ttk_GetBorderFromObj(interp, objv[i+1], &imageData->border)
+ != TCL_OK) { goto error; }
+ if (!padding_specified) {
+ imageData->padding = imageData->border;
+ }
+ break;
+ case O_PADDING:
+ if (Ttk_GetBorderFromObj(interp, objv[i+1], &imageData->padding)
+ != TCL_OK) { goto error; }
+ padding_specified = 1;
+ break;
+ case O_WIDTH:
+ if (Tcl_GetIntFromObj(interp, objv[i+1], &imageData->minWidth)
+ != TCL_OK) { goto error; }
+ break;
+ case O_HEIGHT:
+ if (Tcl_GetIntFromObj(interp, objv[i+1], &imageData->minHeight)
+ != TCL_OK) { goto error; }
+ break;
+ case O_STICKY:
+ if (Ttk_GetStickyFromObj(interp, objv[i+1], &imageData->sticky)
+ != TCL_OK) { goto error; }
+ }
}
- if (!Ttk_RegisterElement(interp, theme,
- elementName, &ImageElementSpec, imageData))
+ if (!Ttk_RegisterElement(interp, theme, elementName, &ImageElementSpec,
+ imageData))
{
goto error;
}
@@ -278,7 +411,8 @@ error:
MODULE_SCOPE int Ttk_ImageInit(Tcl_Interp *);
int Ttk_ImageInit(Tcl_Interp *interp)
{
- return Ttk_RegisterElementFactory(interp, "image", Ttk_CreateImageElement, NULL);
+ return Ttk_RegisterElementFactory(interp, "image",
+ Ttk_CreateImageElement, NULL);
}
/*EOF*/
diff --git a/generic/ttk/ttkLabel.c b/generic/ttk/ttkLabel.c
index 4d90722..e03fea4 100644
--- a/generic/ttk/ttkLabel.c
+++ b/generic/ttk/ttkLabel.c
@@ -1,6 +1,6 @@
-/* $Id: ttkLabel.c,v 1.2 2006/11/03 03:06:22 das Exp $
+/* $Id: ttkLabel.c,v 1.3 2006/12/09 20:53:35 jenglish Exp $
*
- * Ttk widget set: text, image, and label elements.
+ * text, image, and label elements.
*
* The label element combines text and image elements,
* with layout determined by the "-compound" option.
@@ -263,14 +263,13 @@ MODULE_SCOPE Ttk_ElementSpec ttkImageTextElementSpec;
typedef struct
{
Tcl_Obj *imageObj;
-
Tcl_Obj *stippleObj; /* For TTK_STATE_DISABLED */
Tcl_Obj *backgroundObj; /* " " */
+ Ttk_ImageSpec *imageSpec;
Tk_Image tkimg;
int width;
int height;
- int doStipple;
} ImageElement;
/* ===> NB: Keep in sync with label element option table. <===
@@ -286,13 +285,6 @@ static Ttk_ElementOptionSpec ImageElementOptions[] =
{NULL}
};
-/* NullImageChanged --
- * No-op Tk_ImageChangedProc for Tk_GetImage.
- */
-static void NullImageChanged(ClientData clientData,
- int x, int y, int width, int height, int imageWidth, int imageHeight)
-{ }
-
/*
* ImageSetup() --
* Look up the Tk_Image from the image element's imageObj resource.
@@ -306,51 +298,19 @@ static void NullImageChanged(ClientData clientData,
static int ImageSetup(
ImageElement *image, Tk_Window tkwin, Tcl_Interp *interp, Ttk_State state)
{
- const char *imageName;
- Tcl_Obj *imageObj = image->imageObj;
- Tcl_Obj **mapList = NULL;
- int i, mapCnt = 0;
-
- if (!imageObj) /* No -image option specified */
- return 0;
-
- if (Tcl_ListObjGetElements(interp,imageObj,&mapCnt,&mapList) == TCL_ERROR)
- return 0;
- if (mapCnt == 0) /* -image is an empty list */
+ if (!image->imageObj) {
return 0;
-
- /* Only enable disabled-stippling if there's no state map:
- * @@@ Possibly: Don't do disabled-stippling at all;
- * @@@ it's ugly and out of fashion.
- */
- image->doStipple = mapCnt == 1;
-
- /* Locate which image to use based on current state:
- */
- imageObj = mapList[0];
- for (i = 1; i < mapCnt - 1; i += 2) {
- Ttk_StateSpec stateSpec;
-
- if (Ttk_GetStateSpecFromObj(interp,mapList[i],&stateSpec) != TCL_OK) {
- /* shouldn't happen, but can */
- break;
- }
-
- if (Ttk_StateMatches(state, &stateSpec)) {
- imageObj = mapList[i+1];
- break;
- }
}
-
- imageName = Tcl_GetString(imageObj);
- if (!imageName || !*imageName) /* Empty string. */
+ image->imageSpec = TtkGetImageSpec(NULL, tkwin, image->imageObj);
+ if (!image->imageSpec) {
return 0;
-
- image->tkimg = Tk_GetImage(interp, tkwin, imageName, NullImageChanged, 0);
- if (!image->tkimg) /* No such image */
+ }
+ image->tkimg = TtkSelectImage(image->imageSpec, state);
+ if (!image->tkimg) {
+ TtkFreeImageSpec(image->imageSpec);
return 0;
-
+ }
Tk_SizeOfImage(image->tkimg, &image->width, &image->height);
return 1;
@@ -358,7 +318,7 @@ static int ImageSetup(
static void ImageCleanup(ImageElement *image)
{
- Tk_FreeImage(image->tkimg);
+ TtkFreeImageSpec(image->imageSpec);
}
/*
@@ -402,8 +362,15 @@ static void ImageDraw(
Tk_RedrawImage(image->tkimg, 0,0, width, height, d, b.x, b.y);
- if (image->doStipple && (state & TTK_STATE_DISABLED)) {
- StippleOver(image, tkwin, d, b.x,b.y);
+ /* If we're disabled there's no state-specific 'disabled' image,
+ * stipple the image.
+ * @@@ Possibly: Don't do disabled-stippling at all;
+ * @@@ it's ugly and out of fashion.
+ */
+ if (state & TTK_STATE_DISABLED) {
+ if (TtkSelectImage(image->imageSpec, 0ul) == image->tkimg) {
+ StippleOver(image, tkwin, d, b.x,b.y);
+ }
}
}
diff --git a/generic/ttk/ttkNotebook.c b/generic/ttk/ttkNotebook.c
index c801bfe..4e8caf9 100644
--- a/generic/ttk/ttkNotebook.c
+++ b/generic/ttk/ttkNotebook.c
@@ -1,4 +1,4 @@
-/* $Id: ttkNotebook.c,v 1.2 2006/11/03 03:06:22 das Exp $
+/* $Id: ttkNotebook.c,v 1.3 2006/12/09 20:53:35 jenglish Exp $
* Copyright (c) 2004, Joe English
*
* NOTE-ACTIVE: activeTabIndex is not always correct (it's
@@ -638,7 +638,7 @@ static int TabConfigured(
Tk_Window tkwin = mgr->masterWindow;
/* Check options:
- * @@@ TODO: validate -image option with TtkGetImageList()
+ * @@@ TODO: validate -image option.
*/
if (Ttk_GetStickyFromObj(interp, tab->stickyObj, &sticky) != TCL_OK) {
return TCL_ERROR;
diff --git a/generic/ttk/ttkTheme.h b/generic/ttk/ttkTheme.h
index 513701d..27f1e5b 100644
--- a/generic/ttk/ttkTheme.h
+++ b/generic/ttk/ttkTheme.h
@@ -4,7 +4,7 @@
*
* Copyright (c) 2003 Joe English. Freely redistributable.
*
- * $Id: ttkTheme.h,v 1.4 2006/12/01 15:05:28 jenglish Exp $
+ * $Id: ttkTheme.h,v 1.5 2006/12/09 20:53:35 jenglish Exp $
*/
#ifndef _TTKTHEME
@@ -364,6 +364,15 @@ MODULE_SCOPE Tk_Image Ttk_UseImage(Ttk_ResourceCache, Tk_Window, Tcl_Obj *);
MODULE_SCOPE void Ttk_RegisterNamedColor(Ttk_ResourceCache, const char *, XColor *);
/*------------------------------------------------------------------------
+ * +++ Image specifications.
+ */
+
+typedef struct TtkImageSpec Ttk_ImageSpec;
+extern Ttk_ImageSpec *TtkGetImageSpec(Tcl_Interp *, Tk_Window, Tcl_Obj *);
+extern void TtkFreeImageSpec(Ttk_ImageSpec *);
+extern Tk_Image TtkSelectImage(Ttk_ImageSpec *, Ttk_State);
+
+/*------------------------------------------------------------------------
* +++ Miscellaneous enumerations.
* Other stuff that element implementations need to know about.
*/
diff --git a/generic/ttk/ttkTreeview.c b/generic/ttk/ttkTreeview.c
index 70b328e..6990c8f 100644
--- a/generic/ttk/ttkTreeview.c
+++ b/generic/ttk/ttkTreeview.c
@@ -1,5 +1,5 @@
/*
- * $Id: ttkTreeview.c,v 1.5 2006/11/27 06:53:55 jenglish Exp $
+ * $Id: ttkTreeview.c,v 1.6 2006/12/09 20:53:35 jenglish Exp $
* Copyright (c) 2004, Joe English
*
* ttk::treeview widget implementation.
@@ -949,14 +949,14 @@ static int ConfigureItem(
}
/* Validate -image option.
- * @@@ TODO: keep images array around
*/
if (item->imageObj) {
- Tk_Image *images = NULL;
- if (TtkGetImageList(interp, &tv->core, item->imageObj, &images) != TCL_OK)
+ Ttk_ImageSpec *imageSpec =
+ TtkGetImageSpec(interp, tv->core.tkwin, item->imageObj);
+ if (!imageSpec) {
goto error;
- if (images)
- TtkFreeImageList(images);
+ }
+ TtkFreeImageSpec(imageSpec); /* @@@TODO: Keep this around */
}
/* Keep TTK_STATE_OPEN flag in sync with item->openObj.
diff --git a/generic/ttk/ttkWidget.h b/generic/ttk/ttkWidget.h
index 0a0f10f..9312040 100644
--- a/generic/ttk/ttkWidget.h
+++ b/generic/ttk/ttkWidget.h
@@ -1,4 +1,4 @@
-/* $Id: ttkWidget.h,v 1.2 2006/11/03 03:06:22 das Exp $
+/* $Id: ttkWidget.h,v 1.3 2006/12/09 20:53:35 jenglish Exp $
* Copyright (c) 2003, Joe English
*
* Helper routines for widget implementations.
@@ -170,13 +170,6 @@ MODULE_SCOPE void Ttk_UntraceVariable(Ttk_TraceHandle *);
MODULE_SCOPE int Ttk_FireTrace(Ttk_TraceHandle *);
/*
- * Utility routines for managing -image option:
- */
-MODULE_SCOPE int TtkGetImageList(
- Tcl_Interp *, WidgetCore *, Tcl_Obj *imageOption, Tk_Image **imageListPtr);
-MODULE_SCOPE void TtkFreeImageList(Tk_Image *);
-
-/*
* Virtual events:
*/
MODULE_SCOPE void TtkSendVirtualEvent(Tk_Window tgtWin, const char *eventName);
diff --git a/tests/ttk/image.test b/tests/ttk/image.test
index b1f66bd..e9c1248 100644
--- a/tests/ttk/image.test
+++ b/tests/ttk/image.test
@@ -1,37 +1,14 @@
#
-# $Id: image.test,v 1.1 2006/10/31 01:42:27 hobbs Exp $
+# $Id: image.test,v 1.2 2006/12/09 20:53:35 jenglish Exp $
#
package require Tk 8.5
package require tcltest ; namespace import -force tcltest::*
loadTestedCommands
-# catch background errors:
-#
-if {[info procs bgerror] == "bgerror"} { rename bgerror {} }
-array set BGerror { caught 0 message {} }
-proc bgerror {message} {
- variable BGerror
- set BGerror(caught) 1
- set BGerror(message) $message
-}
-proc caughtbgerror {} {
- variable BGerror
- if {!$BGerror(caught)} {
- error "No bgerror caught"
- }
- set BGerror(caught) 0
- return $BGerror(message)
-}
-
test image-1.1 "Bad image element" -body {
ttk::style element create BadImage image badimage
- ttk::style layout BadImage { BadImage }
- ttk::label .l -style BadImage
- pack .l ; update
- destroy .l
- caughtbgerror
-} -result {image "badimage" doesn't exist}
+} -returnCodes error -result {image "badimage" doesn't exist}
test image-1.2 "Duplicate element" -setup {
image create photo test.element -width 10 -height 10