/* $Id: tkElements.c,v 1.31 2004/01/16 03:25:20 jenglish Exp $
*
* Copyright (c) 2003, Joe English
*
* Default implementation for themed elements.
*
* Implements the "classic" Motif-like Tk look.
* Also provides default fallback elements for other themes.
*
*/
#include <tcl.h>
#include <tk.h>
#include <string.h>
#include "tkTheme.h"
#define DEFAULT_SLIDER_LENGTH "30"
#define DEFAULT_ARROW_SIZE "15"
#define MIN_THUMB_SIZE 10
/*----------------------------------------------------------------------
* +++ Background element implementation.
*
* This element simply clears the entire widget area
* with the background color.
*
* It should be the first element drawn.
*/
typedef struct
{
Tcl_Obj *backgroundObj;
} BackgroundElement;
static TTK_ElementOptionSpec BackgroundElementOptions[] =
{
{ "-background", TK_OPTION_BORDER,
Tk_Offset(BackgroundElement,backgroundObj), DEFAULT_BACKGROUND },
{NULL}
};
static void
BackgroundElementGeometry(
void *clientData, void *elementRecord,
Tk_Window tkwin, int *widthPtr, int *heightPtr, TTK_Padding *paddingPtr)
{
/* Default zero is OK */
}
static void
BackgroundElementDraw(
void *clientData, void *elementRecord,
Tk_Window tkwin, Drawable d,
int x, int y, int width, int height,
unsigned int state)
{
BackgroundElement *bg = elementRecord;
Tk_3DBorder backgroundPtr = NULL;
/*
* Extract option values.
*/
if (bg->backgroundObj)
backgroundPtr = Tk_Get3DBorderFromObj(tkwin, bg->backgroundObj);
/*
* Draw stuff.
*/
if (backgroundPtr) {
XFillRectangle(Tk_Display(tkwin), d,
Tk_3DBorderGC(tkwin, backgroundPtr, TK_3D_FLAT_GC),
0,0,(unsigned)Tk_Width(tkwin), (unsigned)Tk_Height(tkwin));
}
}
static TTK_ElementSpec BackgroundElementSpec =
{
TK_STYLE_VERSION_2,
sizeof(BackgroundElement),
BackgroundElementOptions,
BackgroundElementGeometry,
BackgroundElementDraw
};
/*----------------------------------------------------------------------
* +++ Highlight element implementation.
* Draws the focus ring (if the widget has keyboard focus).
*/
typedef struct {
Tcl_Obj *highlightColorObj;
Tcl_Obj *highlightThicknessObj;
} HighlightElement;
static TTK_ElementOptionSpec HighlightElementOptions[] = {
{ "-highlightcolor",TK_OPTION_COLOR,
Tk_Offset(HighlightElement,highlightColorObj), "black" },
{ "-highlightthickness",TK_OPTION_PIXELS,
Tk_Offset(HighlightElement,highlightThicknessObj), "1" },
{NULL}
};
static void
HighlightElementGeometry(
void *clientData, void *elementRecord,
Tk_Window tkwin, int *widthPtr, int *heightPtr, TTK_Padding *paddingPtr)
{
HighlightElement *highlight = elementRecord;
int highlightThickness = 0;
Tcl_GetIntFromObj(NULL, highlight->highlightThicknessObj, &highlightThickness);
paddingPtr->left = paddingPtr->top
= paddingPtr->right = paddingPtr->bottom = highlightThickness;
}
static void
HighlightElementDraw(
void *clientData, void *elementRecord,
Tk_Window tkwin, Drawable d,
int x, int y, int width, int height,
unsigned int state)
{
HighlightElement *hl = elementRecord;
int highlightThickness = 0;
XColor *highlightColor = NULL;
if (state & TTK_STATE_FOCUS) {
Tcl_GetIntFromObj(NULL,hl->highlightThicknessObj,&highlightThickness);
highlightColor = Tk_GetColorFromObj(tkwin, hl->highlightColorObj);
if (highlightColor && highlightThickness > 0) {
GC gc = Tk_GCForColor(highlightColor, d);
Tk_DrawFocusHighlight(tkwin, gc, highlightThickness, d);
}
}
}
static TTK_ElementSpec HighlightElementSpec =
{
TK_STYLE_VERSION_2,
sizeof(HighlightElement),
HighlightElementOptions,
HighlightElementGeometry,
HighlightElementDraw
};
/*
*----------------------------------------------------------------------
* +++ Border element implementation.
*
* The standard border on X11 consists of (from outside-in):
*
* + focus indicator (controlled by -highlightcolor and -highlightthickness),
* + shaded border (controlled by -background, -borderwidth, and -relief)
*
* A "Pushable" border also adds 2 pixels of padding to shift child elements
* "in" or "out" depending on -relief.
*
* In addition, buttons may have an additional "default ring",
* controlled by the -default option. There is a separate
* Border element for Buttons than for everything else.
* everything else. While in principle it makes sense for
* checkbuttons and radio buttons to be the "default" element,
* we don't want to draw a default ring around them in this
* theme since it's rilly ugly.
*
*
*----------------------------------------------------------------------
*/
typedef struct
{
Tcl_Obj *borderObj;
Tcl_Obj *borderWidthObj;
Tcl_Obj *defaultStateObj;
Tcl_Obj *reliefObj;
} BorderElement;
static TTK_ElementOptionSpec BorderElementOptions[] =
{
{ "-background", TK_OPTION_BORDER, Tk_Offset(BorderElement,borderObj),
DEFAULT_BACKGROUND },
{ "-borderwidth", TK_OPTION_PIXELS, Tk_Offset(BorderElement,borderWidthObj),
DEFAULT_BORDERWIDTH },
{ "-default", TK_OPTION_ANY, Tk_Offset(BorderElement,defaultStateObj),
"disabled" },
{ "-relief", TK_OPTION_RELIEF, Tk_Offset(BorderElement,reliefObj),
"flat" },
{NULL}
};
static void
BorderElementGeometry(
void *clientData, void *elementRecord,
Tk_Window tkwin, int *widthPtr, int *heightPtr, TTK_Padding *paddingPtr)
{
BorderElement *bd = elementRecord;
int borderWidth = 0;
int relief = TK_RELIEF_FLAT;
Tcl_GetIntFromObj(NULL, bd->borderWidthObj, &borderWidth);
Tk_GetReliefFromObj(NULL, bd->reliefObj, &relief);
paddingPtr->left = paddingPtr->right = paddingPtr->top = paddingPtr->bottom
= borderWidth;
}
static void PushableBorderElementGeometry(
void *clientData, void *elementRecord,
Tk_Window tkwin, int *widthPtr, int *heightPtr, TTK_Padding *paddingPtr)
{
BorderElement *border = elementRecord;
int relief;
BorderElementGeometry(clientData, elementRecord, tkwin,
widthPtr, heightPtr, paddingPtr);
/* Distribute extra 2 pixels of padding according to current relief: */
Tk_GetReliefFromObj(NULL, border->reliefObj, &relief);
switch (relief)
{
case TK_RELIEF_RAISED:
paddingPtr->right += 2;
paddingPtr->bottom += 2;
break;
case TK_RELIEF_SUNKEN: /* shift */
paddingPtr->left += 2;
paddingPtr->top += 2;
break;
default:
paddingPtr->left += 1;
paddingPtr->top += 1;
paddingPtr->right += 1;
paddingPtr->bottom += 1;
break;
}
}
/*
* ButtonBorderElementGeometry --
* Same as PushableBorderElementGeometry(), but allocate extra space
* for the default ring.
*/
static void
ButtonBorderElementGeometry(
void *clientData, void *elementRecord,
Tk_Window tkwin, int *widthPtr, int *heightPtr, TTK_Padding *paddingPtr)
{
BorderElement *bd = elementRecord;
int defaultState = TK_BUTTON_DEFAULT_DISABLED;
PushableBorderElementGeometry(clientData, elementRecord, tkwin,
widthPtr, heightPtr, paddingPtr);
TkGetButtonDefaultStateFromObj(NULL, bd->defaultStateObj, &defaultState);
if (defaultState != TK_BUTTON_DEFAULT_DISABLED) {
paddingPtr->left += 5;
paddingPtr->right += 5;
paddingPtr->top += 5;
paddingPtr->bottom += 5;
}
}
/*
* BorderElementDraw --
* Draw default borders.
* See also ButtonBorderElementDraw, which handles the default ring.
*/
static void
BorderElementDraw(
void *clientData, void *elementRecord,
Tk_Window tkwin, Drawable d,
int x, int y, int width, int height,
unsigned int state)
{
BorderElement *bd = elementRecord;
Tk_3DBorder border = NULL;
int borderWidth = 1, relief = TK_RELIEF_FLAT;
int inset = 0;
/*
* Get option values.
*/
border = Tk_Get3DBorderFromObj(tkwin, bd->borderObj);
Tcl_GetIntFromObj(NULL, bd->borderWidthObj, &borderWidth);
Tk_GetReliefFromObj(NULL, bd->reliefObj, &relief);
/*
* 3-D shadow:
*/
if (border && borderWidth > 0 && relief != TK_RELIEF_FLAT) {
Tk_Draw3DRectangle(tkwin, d, border,
x+inset, y+inset, width - 2*inset, height - 2*inset,
borderWidth,relief);
}
}
/*
* ButtonBorderElementDraw --
* Same as BorderElementDraw, but has extra logic to deal with
* the default ring.
* (@@@ Note: still buggy: padding for default ring is drawn in
* the wrong color when the button is active. I'm not going to
* bother to fix this right now.)
*/
static void
ButtonBorderElementDraw(
void *clientData, void *elementRecord,
Tk_Window tkwin, Drawable d,
int x, int y, int width, int height,
unsigned int state)
{
BorderElement *bd = elementRecord;
Tk_3DBorder border = NULL;
int borderWidth = 1, relief = TK_RELIEF_FLAT;
int defaultState = TK_BUTTON_DEFAULT_DISABLED;
int inset = 0;
/*
* Get option values.
*/
border = Tk_Get3DBorderFromObj(tkwin, bd->borderObj);
Tcl_GetIntFromObj(NULL, bd->borderWidthObj, &borderWidth);
Tk_GetReliefFromObj(NULL, bd->reliefObj, &relief);
TkGetButtonDefaultStateFromObj(NULL, bd->defaultStateObj, &defaultState);
/*
* Default ring:
*/
switch (defaultState)
{
case TK_BUTTON_DEFAULT_DISABLED :
break;
case TK_BUTTON_DEFAULT_NORMAL :
inset += 5;
break;
case TK_BUTTON_DEFAULT_ACTIVE :
Tk_Draw3DRectangle(tkwin, d, border,
inset, inset, width - 2*inset, height - 2*inset,
2, TK_RELIEF_FLAT);
inset += 2;
Tk_Draw3DRectangle(tkwin, d, border,
inset, inset, width - 2*inset, height - 2*inset,
1, TK_RELIEF_SUNKEN);
++inset;
Tk_Draw3DRectangle(tkwin, d, border,
inset, inset, width - 2*inset, height - 2*inset,
2, TK_RELIEF_FLAT);
inset += 2;
break;
}
/*
* 3-D border:
*/
if (border && borderWidth > 0) {
Tk_Draw3DRectangle(tkwin, d, border,
x+inset, y+inset, width - 2*inset, height - 2*inset,
borderWidth,relief);
}
}
static TTK_ElementSpec BorderElementSpec =
{
TK_STYLE_VERSION_2,
sizeof(BorderElement),
BorderElementOptions,
BorderElementGeometry,
BorderElementDraw
};
static TTK_ElementSpec PushableBorderElementSpec =
{
TK_STYLE_VERSION_2,
sizeof(BorderElement),
BorderElementOptions,
PushableBorderElementGeometry,
BorderElementDraw
};
static TTK_ElementSpec ButtonBorderElementSpec =
{
TK_STYLE_VERSION_2,
sizeof(BorderElement),
BorderElementOptions,
ButtonBorderElementGeometry,
ButtonBorderElementDraw
};
/*
*----------------------------------------------------------------------
* +++ Padding element implementation.
*
* This element has no visual representation, only geometry.
* It adds a (possibly non-uniform) internal border.
*/
typedef struct
{
Tcl_Obj *paddingObj;
} PaddingElement;
static TTK_ElementOptionSpec PaddingElementOptions[] =
{
{ "-padding", TK_OPTION_STRING,
Tk_Offset(PaddingElement,paddingObj), "0" },
{NULL}
};
static void
PaddingElementGeometry(
void *clientData, void *elementRecord,
Tk_Window tkwin, int *widthPtr, int *heightPtr, TTK_Padding *paddingPtr)
{
PaddingElement *padding = elementRecord;
TTK_GetPaddingFromObj(NULL,tkwin,padding->paddingObj,paddingPtr);
}
static void
PaddingElementDraw(
void *clientData, void *elementRecord,
Tk_Window tkwin, Drawable d,
int x, int y, int width, int height,
unsigned int state)
{
/* No-op */
}
static TTK_ElementSpec PaddingElementSpec =
{
TK_STYLE_VERSION_2,
sizeof(PaddingElement),
PaddingElementOptions,
PaddingElementGeometry,
PaddingElementDraw
};
/*
*----------------------------------------------------------------------
* +++ Text element implementation.
*
* This element displays a textual label in the foreground color.
*
* Optionally underlines the mnemonic character if the -underline resource
* is present and >= 0.
*/
typedef struct
{
/*
* Element resources:
*/
Tcl_Obj *textObj;
Tcl_Obj *fontObj;
Tcl_Obj *foregroundObj;
Tcl_Obj *underlineObj;
Tcl_Obj *widthObj;
/*
* Computed resources:
*/
Tk_Font tkfont;
Tk_TextLayout textLayout;
int width;
int height;
} TextElement;
/* Text element options table.
* NB: Keep in sync with compound element option table.
*/
static TTK_ElementOptionSpec TextElementOptions[] =
{
{ "-text", TK_OPTION_STRING,
Tk_Offset(TextElement,textObj), "" },
{ "-font", TK_OPTION_FONT,
Tk_Offset(TextElement,fontObj), DEFAULT_FONT },
{ "-foreground", TK_OPTION_COLOR,
Tk_Offset(TextElement,foregroundObj), "black" },
{ "-underline", TK_OPTION_INT,
Tk_Offset(TextElement,underlineObj), "-1"},
{ "-width", TK_OPTION_INT,
Tk_Offset(TextElement,widthObj), "-1"},
{NULL}
};
static int TextSetup(TextElement *text, Tk_Window tkwin)
{
const char *string;
int nChars;
int justify = TK_JUSTIFY_LEFT;
text->width = text->height = 0;
if (!text->textObj || !text->fontObj)
return 0;
text->tkfont = Tk_GetFontFromObj(tkwin, text->fontObj);
if (!text->tkfont)
return 0;
string = Tcl_GetStringFromObj(text->textObj, &nChars);
/* @@@ POSSIBLY: just use Tk_MeasureChars() and font metrics?
* @@@ Do we really need to support multi-line text labels here?
*/
text->textLayout = Tk_ComputeTextLayout(
text->tkfont, string, nChars, 0, justify,
0/*flags*/, &text->width, &text->height);
return 1;
}
/*
* TextReqWidth -- compute the requested width of a text element.
*
* If -width is positive, use that as the width
* If -width is negative, use that as the minimum width
* If not specified or empty, use the natural size of the text
*/
static int TextReqWidth(TextElement *text)
{
int reqWidth;
if ( text->widthObj
&& Tcl_GetIntFromObj(NULL, text->widthObj, &reqWidth) == TCL_OK)
{
int avgWidth = Tk_TextWidth(text->tkfont, "0", 1);
if (reqWidth <= 0) {
int specWidth = avgWidth * -reqWidth;
if (specWidth > text->width)
return specWidth;
} else {
return avgWidth * reqWidth;
}
}
return text->width;
}
static void TextCleanup(TextElement *text)
{
Tk_FreeTextLayout(text->textLayout);
}
/*
* TextDraw --
* Draw a text element.
* Called by TextElementDraw() and CompoundElementDraw().
*/
static void TextDraw(TextElement *text, Tk_Window tkwin,
Drawable d, int x, int y, int width, int height)
{
int underline = -1;
unsigned long mask = 0;
XGCValues gcValues;
GC gc;
mask = 0;
getFontFromObj(tkwin, text->fontObj, &mask, &gcValues);
getForegroundFromObj(tkwin, text->foregroundObj, &mask, &gcValues);
gc = Tk_GetGC(tkwin, mask, &gcValues);
adjustAnchor(TK_ANCHOR_CENTER, &x,&y, width,height,
text->width,text->height);
Tk_DrawTextLayout(Tk_Display(tkwin), d, gc,
text->textLayout, x, y, 0/*firstChar*/, -1/*lastChar*/);
Tcl_GetIntFromObj(NULL, text->underlineObj, &underline);
if (underline >= 0)
Tk_UnderlineTextLayout(Tk_Display(tkwin), d, gc,
text->textLayout, x, y, underline);
Tk_FreeGC(Tk_Display(tkwin), gc);
}
static void
TextElementGeometry(
void *clientData, void *elementRecord,
Tk_Window tkwin, int *widthPtr, int *heightPtr, TTK_Padding *paddingPtr)
{
TextElement *text = elementRecord;
if (!TextSetup(text, tkwin))
return;
*heightPtr = text->height;
*widthPtr = text->width;
TextCleanup(text);
return;
}
static void
TextElementDraw(
ClientData clientData, void *elementRecord,
Tk_Window tkwin, Drawable d,
int x, int y, int width, int height,
unsigned int state)
{
TextElement *text = elementRecord;
if (!TextSetup(text, tkwin))
return;
TextDraw(text, tkwin, d, x, y, width, height);
TextCleanup(text);
}
static TTK_ElementSpec TextElementSpec =
{
TK_STYLE_VERSION_2,
sizeof(TextElement),
TextElementOptions,
TextElementGeometry,
TextElementDraw
};
/*
*----------------------------------------------------------------------
* +++ Image element implementation.
*
* Draws an image.
*
* The clientData parameter is a Tcl_Interp, which is needed for
* the call to Tk_GetImage().
*/
typedef struct
{
Tcl_Obj *imageObj;
Tk_Image tkimg;
int width;
int height;
} ImageElement;
static TTK_ElementOptionSpec ImageElementOptions[] =
{
{ "-image", TK_OPTION_STRING, Tk_Offset(ImageElement,imageObj), "" },
{NULL}
};
/*
* ImageSetup() --
* Look up the Tk_Image from the image element's imageObj resource.
* Caller must release the image with ImageCleanup().
*
* Returns:
* 1 if successful, 0 if there was an error (unreported)
* or the image resource was not specified.
*/
static int ImageSetup(ImageElement *image, Tk_Window tkwin, Tcl_Interp *interp)
{
const char *imageName;
if (!image->imageObj) /* No -image resource specified */
return 0;
imageName = Tcl_GetString(image->imageObj);
if (!imageName || !*imageName) /* Empty string. */
return 0;
image->tkimg = Tk_GetImage(interp, tkwin, imageName, 0, 0);
if (!image->tkimg) /* No such image */
return 0;
Tk_SizeOfImage(image->tkimg, &image->width, &image->height);
return 1;
}
static void ImageCleanup(ImageElement *image)
{
Tk_FreeImage(image->tkimg);
}
static void ImageDraw(ImageElement *image, Tk_Window tkwin, Drawable d,
int x, int y, int width, int height)
{
adjustAnchor(TK_ANCHOR_CENTER, &x,&y, width,height,
image->width,image->height);
Tk_RedrawImage(image->tkimg, 0, 0, image->width, image->height, d, x, y);
}
static void
ImageElementGeometry(
void *clientData, void *elementRecord,
Tk_Window tkwin, int *widthPtr, int *heightPtr, TTK_Padding *paddingPtr)
{
ImageElement *image = elementRecord;
Tcl_Interp *interp = clientData;
if (ImageSetup(image, tkwin, interp)) {
*widthPtr = image->width;
*heightPtr = image->height;
ImageCleanup(image);
}
}
static void
ImageElementDraw(
void *clientData, void *elementRecord,
Tk_Window tkwin, Drawable d,
int x, int y, int width, int height,
unsigned int state)
{
ImageElement *image = elementRecord;
Tcl_Interp *interp = clientData;
if (ImageSetup(image, tkwin, interp)) {
ImageDraw(image, tkwin, d, x, y, width, height);
ImageCleanup(image);
}
}
static TTK_ElementSpec ImageElementSpec =
{
TK_STYLE_VERSION_2,
sizeof(ImageElement),
ImageElementOptions,
ImageElementGeometry,
ImageElementDraw
};
/*------------------------------------------------------------------------
* +++ Compound element implementation.
*
* Displays an image and/or text, as determined by the -compound
* resource.
*
* The clientData parameter is a Tcl_Interp; this is needed for the
* image part.
*
* Differences from Tk 8.4 compound elements:
*
* This adds two new options for the -compound resource, "text"
* and "image". (This is useful for configuring toolbars to
* display icons, text and icons, or text only, as found in
* many browsers.)
*
* "-compound none" is supported, but I'd like to get rid of it;
* it makes the logic more complex, and the only benefit is
* backwards compatibility with Tk < 8.3.0 scripts.
*
* This adds a new resource, -space, for determining how much
* space to leave between the text and image; Tk 8.4 reuses the
* -padx or -pady option for this purpose.
*
* Tk 8.4 ignores -padx and -pady if -compound is set to "none".
* This element always includes padding.
*/
typedef struct
{
/*
* Element resources:
*/
Tcl_Obj *compoundObj;
Tcl_Obj *spaceObj;
Tcl_Obj *anchorObj;
TextElement text;
ImageElement image;
/*
* Computed values (see CompoundSetup)
*/
TkCompoundLayout layout;
int space;
int textWidth, textHeight;
int imageWidth, imageHeight;
int totalWidth, totalHeight;
} CompoundElement;
static TTK_ElementOptionSpec CompoundElementOptions[] =
{
{ "-compound", TK_OPTION_ANY,
Tk_Offset(CompoundElement,compoundObj), "none" },
{ "-anchor", TK_OPTION_ANCHOR,
Tk_Offset(CompoundElement,anchorObj), "center"},
{ "-space", TK_OPTION_PIXELS,
Tk_Offset(CompoundElement,spaceObj), "4" },
/* Text element part:
* NB: Keep in sync with TextElementOptions.
*/
{ "-text", TK_OPTION_STRING,
Tk_Offset(CompoundElement,text.textObj), "" },
{ "-font", TK_OPTION_FONT,
Tk_Offset(CompoundElement,text.fontObj), DEFAULT_FONT },
{ "-foreground", TK_OPTION_COLOR,
Tk_Offset(CompoundElement,text.foregroundObj), "black" },
{ "-underline", TK_OPTION_INT,
Tk_Offset(CompoundElement,text.underlineObj), "-1"},
{ "-width", TK_OPTION_INT,
Tk_Offset(CompoundElement,text.widthObj), ""},
/* Image element part:
* NB: Keep in sync with ImageElementOptions.
*/
{ "-image", TK_OPTION_STRING,
Tk_Offset(CompoundElement,image.imageObj), "" },
{NULL}
};
/*
* CompoundSetup --
* Fills in computed fields of the compound element.
*
* Calculate the text, image, and total width and height.
*/
#define MAX(a,b) ((a) > (b) ? a : b);
static void CompoundSetup(
CompoundElement *c, Tk_Window tkwin, Tcl_Interp *interp)
{
Tk_GetPixelsFromObj(NULL,tkwin,c->spaceObj,&c->space);
TkGetCompoundLayoutFromObj(NULL,c->compoundObj,(int*)&c->layout);
/*
* Deal with TK_COMPOUND_LAYOUT_NONE.
*/
if (c->layout == TK_COMPOUND_LAYOUT_NONE) {
if (ImageSetup(&c->image, tkwin, interp)) {
c->layout = TK_COMPOUND_LAYOUT_IMAGE;
} else {
c->layout = TK_COMPOUND_LAYOUT_TEXT;
}
} else if (c->layout != TK_COMPOUND_LAYOUT_TEXT) {
if (!ImageSetup(&c->image, tkwin, interp)) {
c->layout = TK_COMPOUND_LAYOUT_TEXT;
}
}
if (c->layout != TK_COMPOUND_LAYOUT_IMAGE)
TextSetup(&c->text, tkwin);
/*
* ASSERT:
* if c->layout != LAYOUT_IMAGE, then TextSetup() has been called
* if c->layout != LAYOUT_TEXT, then ImageSetup() has returned successfully
* c->layout != LAYOUT_NONE.
*/
switch (c->layout)
{
case TK_COMPOUND_LAYOUT_NONE:
Tcl_Panic("This can't happen");
break;
case TK_COMPOUND_LAYOUT_TEXT:
c->totalWidth = TextReqWidth(&c->text);
c->totalHeight = c->text.height;
break;
case TK_COMPOUND_LAYOUT_IMAGE:
c->totalWidth = c->image.width;
c->totalHeight = c->image.height;
break;
case TK_COMPOUND_LAYOUT_CENTER:
c->totalWidth = MAX(c->image.width, c->text.width);
c->totalHeight = MAX(c->image.height, c->text.height);
break;
case TK_COMPOUND_LAYOUT_TOP:
case TK_COMPOUND_LAYOUT_BOTTOM:
c->totalWidth = MAX(c->image.width, c->text.width);
c->totalHeight = c->image.height + c->text.height + c->space;
break;
case TK_COMPOUND_LAYOUT_LEFT:
case TK_COMPOUND_LAYOUT_RIGHT:
c->totalWidth = c->image.width + c->text.width + c->space;
c->totalHeight = MAX(c->image.height, c->text.height);
break;
}
}
static void CompoundCleanup(CompoundElement *c)
{
if (c->layout != TK_COMPOUND_LAYOUT_TEXT)
ImageCleanup(&c->image);
if (c->layout != TK_COMPOUND_LAYOUT_IMAGE)
TextCleanup(&c->text);
}
static void
CompoundElementGeometry(
void *clientData, void *elementRecord,
Tk_Window tkwin, int *widthPtr, int *heightPtr, TTK_Padding *paddingPtr)
{
CompoundElement *compound = elementRecord;
Tcl_Interp *interp = clientData;
CompoundSetup(compound, tkwin, interp);
*widthPtr = compound->totalWidth;
*heightPtr = compound->totalHeight;
CompoundCleanup(compound);
}
static void
CompoundElementDraw(
void *clientData, void *elementRecord,
Tk_Window tkwin, Drawable d,
int x, int y, int width, int height,
unsigned int state)
{
CompoundElement *c = elementRecord;
Tcl_Interp *interp = clientData;
Tk_Anchor anchor = TK_ANCHOR_CENTER;
CompoundSetup(c, tkwin, interp);
/*
* Adjust parcel:
*/
Tk_GetAnchorFromObj(NULL, c->anchorObj, &anchor);
adjustAnchor(anchor, &x, &y, width, height, c->totalWidth, c->totalHeight);
switch (c->layout)
{
case TK_COMPOUND_LAYOUT_NONE:
Tcl_Panic("This can't happen");
break;
case TK_COMPOUND_LAYOUT_TEXT:
TextDraw(&c->text,tkwin,d,x,y, c->totalWidth,c->totalHeight);
break;
case TK_COMPOUND_LAYOUT_IMAGE:
ImageDraw(&c->image,tkwin,d,x,y, c->totalWidth,c->totalHeight);
break;
case TK_COMPOUND_LAYOUT_CENTER:
ImageDraw(&c->image,tkwin,d,x,y, c->totalWidth,c->totalHeight);
TextDraw(&c->text,tkwin,d,x,y, c->totalWidth,c->totalHeight);
break;
case TK_COMPOUND_LAYOUT_TOP:
ImageDraw(&c->image,tkwin,d,x,y, c->totalWidth,c->image.height);
y += c->image.height + c->space;
TextDraw(&c->text,tkwin,d,x,y, c->totalWidth,c->text.height);
break;
case TK_COMPOUND_LAYOUT_BOTTOM:
TextDraw(&c->text,tkwin,d,x,y, c->totalWidth,c->text.height);
y += c->text.height + c->space;
ImageDraw(&c->image,tkwin,d,x,y, c->totalWidth,c->image.height);
break;
case TK_COMPOUND_LAYOUT_LEFT:
ImageDraw(&c->image,tkwin,d,x,y, c->image.width,c->totalHeight);
x += c->image.width + c->space;
TextDraw(&c->text,tkwin,d,x,y, c->text.width,c->totalHeight);
break;
case TK_COMPOUND_LAYOUT_RIGHT:
TextDraw(&c->text,tkwin,d,x,y, c->text.width,c->totalHeight);
x += c->text.width + c->space;
ImageDraw(&c->image,tkwin,d,x,y, c->image.width,c->totalHeight);
break;
}
CompoundCleanup(c);
}
static TTK_ElementSpec CompoundElementSpec =
{
TK_STYLE_VERSION_2,
sizeof(CompoundElement),
CompoundElementOptions,
CompoundElementGeometry,
CompoundElementDraw
};
/*
*----------------------------------------------------------------------
* +++ Indicator element implementation.
*
* Draws the on/off indicator for checkbuttons and radiobuttons.
*
* Draws a 3-D square (or diamond), raised if off, sunken if on.
*
* This is actually a regression from Tk 8.5 back to the ugly old Motif
* style; use "altTheme" for the newer, nicer version.
*/
typedef struct
{
Tcl_Obj *backgroundObj;
Tcl_Obj *reliefObj;
Tcl_Obj *colorObj;
Tcl_Obj *diameterObj;
Tcl_Obj *marginObj;
Tcl_Obj *borderWidthObj;
} IndicatorElement;
static TTK_ElementOptionSpec IndicatorElementOptions[] =
{
{ "-background", TK_OPTION_BORDER,
Tk_Offset(IndicatorElement,backgroundObj), DEFAULT_BACKGROUND },
{ "-indicatorcolor", TK_OPTION_BORDER,
Tk_Offset(IndicatorElement,colorObj), DEFAULT_BACKGROUND },
{ "-indicatorrelief", TK_OPTION_RELIEF,
Tk_Offset(IndicatorElement,reliefObj), "raised" },
{ "-indicatordiameter", TK_OPTION_PIXELS,
Tk_Offset(IndicatorElement,diameterObj), "12" },
{ "-indicatormargin", TK_OPTION_STRING,
Tk_Offset(IndicatorElement,marginObj), "0 2 4 2" },
{ "-borderwidth", TK_OPTION_PIXELS,
Tk_Offset(IndicatorElement,borderWidthObj), DEFAULT_BORDERWIDTH },
{NULL}
};
/*
* Checkbutton indicators (default): 3-D square.
*/
static void
SquareIndicatorElementGeometry(
void *clientData, void *elementRecord,
Tk_Window tkwin, int *widthPtr, int *heightPtr, TTK_Padding *paddingPtr)
{
IndicatorElement *indicator = elementRecord;
int diameter = 0;
TTK_GetPaddingFromObj(NULL, tkwin, indicator->marginObj, paddingPtr);
Tk_GetPixelsFromObj(NULL, tkwin, indicator->diameterObj, &diameter);
*widthPtr = *heightPtr = diameter;
}
static void
SquareIndicatorElementDraw(
void *clientData, void *elementRecord,
Tk_Window tkwin, Drawable d,
int x, int y, int width, int height,
unsigned int state)
{
IndicatorElement *indicator = elementRecord;
Tk_3DBorder border = 0, interior = 0;
int relief = TK_RELIEF_RAISED;
int borderWidth = 2;
int diameter;
interior = Tk_Get3DBorderFromObj(tkwin, indicator->colorObj);
if (indicator->backgroundObj)
border = Tk_Get3DBorderFromObj(tkwin, indicator->backgroundObj);
else
border = interior;
if (indicator->borderWidthObj)
Tcl_GetIntFromObj(NULL,indicator->borderWidthObj,&borderWidth);
if (indicator->marginObj) {
TTK_Padding margin;
TTK_GetPaddingFromObj(NULL,tkwin,indicator->marginObj,&margin);
adjustPadding(&margin, &x,&y,&width,&height);
}
Tk_GetReliefFromObj(NULL,indicator->reliefObj,&relief);
/*
* Ensure square, center in parcel:
*/
diameter = adjustAspect(&x,&y, &width, &height);
Tk_Fill3DRectangle(tkwin, d, interior, x, y,
diameter, diameter,borderWidth, TK_RELIEF_FLAT);
Tk_Draw3DRectangle(tkwin, d, border, x, y,
diameter, diameter, borderWidth, relief);
}
/*
* Radiobutton indicators: 3-D diamond.
*/
static void
DiamondIndicatorElementGeometry(
void *clientData, void *elementRecord,
Tk_Window tkwin, int *widthPtr, int *heightPtr, TTK_Padding *paddingPtr)
{
IndicatorElement *indicator = elementRecord;
int diameter = 0;
TTK_GetPaddingFromObj(NULL, tkwin, indicator->marginObj, paddingPtr);
Tk_GetPixelsFromObj(NULL, tkwin, indicator->diameterObj, &diameter);
*widthPtr = *heightPtr = diameter + 3;
}
static void
DiamondIndicatorElementDraw(
void *clientData, void *elementRecord,
Tk_Window tkwin, Drawable d,
int x, int y, int width, int height,
unsigned int state)
{
IndicatorElement *indicator = elementRecord;
Tk_3DBorder border = 0, interior = 0;
int borderWidth = 2;
int relief = TK_RELIEF_RAISED;
int diameter, radius;
XPoint points[4];
interior = Tk_Get3DBorderFromObj(tkwin, indicator->colorObj);
if (indicator->backgroundObj)
border = Tk_Get3DBorderFromObj(tkwin, indicator->backgroundObj);
else
border = interior;
if (indicator->borderWidthObj)
Tcl_GetIntFromObj(NULL,indicator->borderWidthObj,&borderWidth);
if (indicator->marginObj) {
TTK_Padding margin;
TTK_GetPaddingFromObj(NULL,tkwin,indicator->marginObj,&margin);
adjustPadding(&margin, &x,&y,&width,&height);
}
Tk_GetReliefFromObj(NULL,indicator->reliefObj,&relief);
/*
* Ensure square, center in parcel:
*/
diameter = adjustAspect(&x,&y, &width, &height);
radius = diameter / 2;
points[0].x = x;
points[0].y = y + radius;
points[1].x = x + radius;
points[1].y = y + 2*radius;
points[2].x = x + 2*radius;
points[2].y = y + radius;
points[3].x = x + radius;
points[3].y = y;
Tk_Fill3DPolygon(tkwin,d,interior,points,4,borderWidth,TK_RELIEF_FLAT);
Tk_Draw3DPolygon(tkwin,d,border,points,4,borderWidth,relief);
}
static TTK_ElementSpec IndicatorElementSpec =
{
TK_STYLE_VERSION_2,
sizeof(IndicatorElement),
IndicatorElementOptions,
SquareIndicatorElementGeometry,
SquareIndicatorElementDraw
};
static TTK_ElementSpec RadiobuttonIndicatorElementSpec =
{
TK_STYLE_VERSION_2,
sizeof(IndicatorElement),
IndicatorElementOptions,
DiamondIndicatorElementGeometry,
DiamondIndicatorElementDraw
};
/*
*----------------------------------------------------------------------
* +++ Arrow element(s)
*
* Draws a 3-D shaded triangle.
*
* clientData is an enum ArrowDirection pointer.
*/
enum { ARROW_UP, ARROW_DOWN, ARROW_LEFT, ARROW_RIGHT };
/* ClientData storage:
*
* OK, it looks kind of silly doing things this way, but it
* avoids casting pointers to integers.
*/
static int ArrowElements[] = { ARROW_UP, ARROW_DOWN, ARROW_LEFT, ARROW_RIGHT };
typedef struct
{
Tcl_Obj *sizeObj;
Tcl_Obj *borderObj;
Tcl_Obj *borderWidthObj;
Tcl_Obj *reliefObj;
} ArrowElement;
static TTK_ElementOptionSpec ArrowElementOptions[] =
{
{ "-width", TK_OPTION_PIXELS, Tk_Offset(ArrowElement,sizeObj),
DEFAULT_ARROW_SIZE },
{ "-background", TK_OPTION_BORDER, Tk_Offset(ArrowElement,borderObj),
DEFAULT_BACKGROUND },
{ "-borderwidth", TK_OPTION_PIXELS, Tk_Offset(ArrowElement,borderWidthObj),
DEFAULT_BORDERWIDTH },
{ "-relief", TK_OPTION_RELIEF, Tk_Offset(ArrowElement,reliefObj),"raised" },
{ NULL }
};
static void
ArrowElementGeometry(
void *clientData, void *elementRecord,
Tk_Window tkwin, int *widthPtr, int *heightPtr, TTK_Padding *paddingPtr)
{
ArrowElement *arrow = elementRecord;
int size = 12;
Tk_GetPixelsFromObj(NULL, tkwin, arrow->sizeObj, &size);
*widthPtr = *heightPtr = size;
}
static void
ArrowElementDraw(
void *clientData, void *elementRecord,
Tk_Window tkwin, Drawable d,
int x, int y, int width, int height,
unsigned int state)
{
int direction = *(int *)clientData;
ArrowElement *arrow = elementRecord;
Tk_3DBorder border;
int borderWidth;
int relief = TK_RELIEF_RAISED;
int size;
XPoint points[3];
Tk_GetPixelsFromObj(NULL, tkwin, arrow->borderWidthObj, &borderWidth);
border = Tk_Get3DBorderFromObj(tkwin, arrow->borderObj);
Tk_GetReliefFromObj(NULL, arrow->reliefObj, &relief);
size = adjustAspect(&x,&y,&width,&height);
/*
* @@@ There are off-by-one pixel errors in the way these are drawn;
* @@@ need to take a look at Tk_Fill3DPolygon and X11 to find the
* @@@ exact rules.
*/
switch (direction)
{
case ARROW_UP:
points[2].x = x; points[2].y = y + size;
points[1].x = x + size / 2; points[1].y = y;
points[0].x = x + size; points[0].y = y + size;
break;
case ARROW_DOWN:
points[0].x = x; points[0].y = y;
points[1].x = x + size / 2; points[1].y = y + size;
points[2].x = x + size; points[2].y = y;
break;
case ARROW_LEFT:
points[0].x = x; points[0].y = y + size / 2;
points[1].x = x + size; points[1].y = y + size;
points[2].x = x + size; points[2].y = y;
break;
case ARROW_RIGHT:
points[0].x = x + size; points[0].y = y + size / 2;
points[1].x = x; points[1].y = y;
points[2].x = x; points[2].y = y + size;
break;
}
Tk_Fill3DPolygon(tkwin, d, border, points, 3, borderWidth, relief);
}
static TTK_ElementSpec ArrowElementSpec =
{
TK_STYLE_VERSION_2,
sizeof(ArrowElement),
ArrowElementOptions,
ArrowElementGeometry,
ArrowElementDraw
};
/*
*----------------------------------------------------------------------
* +++ Trough element
*
* Used in scrollbars and scales in place of "border".
*/
typedef struct
{
Tcl_Obj *colorObj;
Tcl_Obj *borderWidthObj;
Tcl_Obj *reliefObj;
} TroughElement;
static TTK_ElementOptionSpec TroughElementOptions[] =
{
{ "-borderwidth", TK_OPTION_PIXELS,
Tk_Offset(TroughElement,borderWidthObj), DEFAULT_BORDERWIDTH },
{ "-troughcolor", TK_OPTION_BORDER,
Tk_Offset(TroughElement,colorObj), DEFAULT_BACKGROUND },
{ "-troughrelief",TK_OPTION_RELIEF,
Tk_Offset(TroughElement,reliefObj), "sunken" },
{ NULL }
};
static void
TroughElementGeometry(
void *clientData, void *elementRecord,
Tk_Window tkwin, int *widthPtr, int *heightPtr, TTK_Padding *paddingPtr)
{
TroughElement *troughPtr = elementRecord;
int borderWidth = 2;
Tk_GetPixelsFromObj(NULL, tkwin, troughPtr->borderWidthObj, &borderWidth);
paddingPtr->left = paddingPtr->right = paddingPtr->top = paddingPtr->bottom
= borderWidth;
}
static void
TroughElementDraw(
void *clientData, void *elementRecord,
Tk_Window tkwin, Drawable d,
int x, int y, int width, int height,
unsigned int state)
{
TroughElement *troughPtr = elementRecord;
Tk_3DBorder border = NULL;
int borderWidth = 2, relief = TK_RELIEF_SUNKEN;
border = Tk_Get3DBorderFromObj(tkwin, troughPtr->colorObj);
Tk_GetReliefFromObj(NULL, troughPtr->reliefObj, &relief);
Tk_GetPixelsFromObj(NULL, tkwin, troughPtr->borderWidthObj, &borderWidth);
Tk_Fill3DRectangle(tkwin, d, border, x, y, width, height,
borderWidth, relief);
}
static TTK_ElementSpec TroughElementSpec =
{
TK_STYLE_VERSION_2,
sizeof(TroughElement),
TroughElementOptions,
TroughElementGeometry,
TroughElementDraw
};
/*
*----------------------------------------------------------------------
* +++ Thumb element.
*
* Used in scrollbars.
*/
typedef struct
{
Tcl_Obj *sizeObj;
Tcl_Obj *reliefObj;
Tcl_Obj *borderObj;
Tcl_Obj *orientObj;
} ThumbElement;
static TTK_ElementOptionSpec ThumbElementOptions[] =
{
{ "-width", TK_OPTION_PIXELS, Tk_Offset(ThumbElement,sizeObj),
DEFAULT_ARROW_SIZE },
{ "-relief", TK_OPTION_RELIEF,
Tk_Offset(ThumbElement,reliefObj), "raised" },
{ "-background", TK_OPTION_BORDER,
Tk_Offset(ThumbElement,borderObj), DEFAULT_BACKGROUND },
{ "-orient", TK_OPTION_ANY,
Tk_Offset(ThumbElement, orientObj), "horizontal" },
{ NULL }
};
static void
ThumbElementGeometry(
void *clientData, void *elementRecord,
Tk_Window tkwin, int *widthPtr, int *heightPtr, TTK_Padding *paddingPtr)
{
ThumbElement *thumb = elementRecord;
int orient, size;
Tk_GetPixelsFromObj(NULL, tkwin, thumb->sizeObj, &size);
TTK_GetOrientationFromObj(NULL, thumb->orientObj, &orient);
if (orient == TTK_ORIENT_VERTICAL) {
*widthPtr = size;
*heightPtr = MIN_THUMB_SIZE;
} else {
*widthPtr = MIN_THUMB_SIZE;
*heightPtr = size;
}
}
static void
ThumbElementDraw(
void *clientData, void *elementRecord,
Tk_Window tkwin, Drawable d,
int x, int y, int width, int height,
unsigned int state)
{
ThumbElement *thumb = elementRecord;
Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, thumb->borderObj);
int borderWidth = 2;
int relief = TK_RELIEF_RAISED;
Tk_GetReliefFromObj(NULL, thumb->reliefObj, &relief);
Tk_Fill3DRectangle(tkwin, d, border, x, y, width, height,
borderWidth, relief);
}
static TTK_ElementSpec ThumbElementSpec =
{
TK_STYLE_VERSION_2,
sizeof(ThumbElement),
ThumbElementOptions,
ThumbElementGeometry,
ThumbElementDraw
};
/*
*----------------------------------------------------------------------
* +++ Slider element.
*
* This is the moving part of the scale widget. Drawn as a raised box.
*/
typedef struct
{
Tcl_Obj *orientObj; /* orientation of overall slider */
Tcl_Obj *lengthObj; /* the length of the slider (if a flat style) */
Tcl_Obj *widthObj; /* the width of the slider (height if horizontal) */
Tcl_Obj *reliefObj; /* the relief for this object */
Tcl_Obj *borderObj; /* the background color */
Tcl_Obj *borderWidthObj; /* the size of the border */
} SliderElement;
static TTK_ElementOptionSpec SliderElementOptions[] =
{
{ "-sliderlength", TK_OPTION_PIXELS, Tk_Offset(SliderElement,lengthObj),
DEFAULT_SLIDER_LENGTH },
{ "-width", TK_OPTION_PIXELS, Tk_Offset(SliderElement,widthObj),
"3" },
{ "-sliderrelief", TK_OPTION_RELIEF, Tk_Offset(SliderElement,reliefObj),
"raised" },
{ "-borderwidth", TK_OPTION_PIXELS, Tk_Offset(SliderElement,borderWidthObj),
DEFAULT_BORDERWIDTH },
{ "-background", TK_OPTION_BORDER, Tk_Offset(SliderElement,borderObj),
DEFAULT_BACKGROUND },
{ "-orient", TK_OPTION_ANY, Tk_Offset(SliderElement,orientObj),
"horizontal" },
{ NULL }
};
static void
SliderElementGeometry(
void *clientData, void *elementRecord,
Tk_Window tkwin, int *widthPtr, int *heightPtr, TTK_Padding *paddingPtr)
{
SliderElement *slider = elementRecord;
int borderWidth, sliderwidth, sliderlength, orient;
TTK_GetOrientationFromObj(NULL, slider->orientObj, &orient);
Tk_GetPixelsFromObj(NULL, tkwin, slider->borderWidthObj, &borderWidth);
Tk_GetPixelsFromObj(NULL, tkwin, slider->lengthObj, &sliderlength);
Tk_GetPixelsFromObj(NULL, tkwin, slider->widthObj, &sliderwidth);
switch (orient) {
case TTK_ORIENT_VERTICAL:
*widthPtr = sliderwidth;
*heightPtr = sliderlength;
break;
case TTK_ORIENT_HORIZONTAL:
*heightPtr = sliderwidth;
*widthPtr = sliderlength;
break;
}
}
static void
SliderElementDraw(
void *clientData, void *elementRecord,
Tk_Window tkwin, Drawable d,
int x, int y, int width, int height,
unsigned int state)
{
SliderElement *slider = elementRecord;
Tk_3DBorder border = NULL;
int relief, borderWidth, orient;
border = Tk_Get3DBorderFromObj(tkwin, slider->borderObj);
TTK_GetOrientationFromObj(NULL, slider->orientObj, &orient);
Tk_GetPixelsFromObj(NULL, tkwin, slider->borderWidthObj, &borderWidth);
Tk_GetReliefFromObj(NULL, slider->reliefObj, &relief);
Tk_Fill3DRectangle(tkwin, d, border,
x, y, width, height,
borderWidth, relief);
if (relief != TK_RELIEF_FLAT) {
if (orient == TTK_ORIENT_HORIZONTAL) {
if (width > 4) {
x += width/2;
XDrawLine(Tk_Display(tkwin), d,
Tk_3DBorderGC(tkwin, border, TK_3D_DARK_GC),
x-1, y+borderWidth, x-1, y+height-borderWidth);
XDrawLine(Tk_Display(tkwin), d,
Tk_3DBorderGC(tkwin, border, TK_3D_LIGHT_GC),
x, y+borderWidth, x, y+height-borderWidth);
}
} else {
if (height > 4) {
y += height/2;
XDrawLine(Tk_Display(tkwin), d,
Tk_3DBorderGC(tkwin, border, TK_3D_DARK_GC),
x+borderWidth, y-1, x+width-borderWidth, y-1);
XDrawLine(Tk_Display(tkwin), d,
Tk_3DBorderGC(tkwin, border, TK_3D_LIGHT_GC),
x+borderWidth, y, x+width-borderWidth, y);
}
}
}
}
static TTK_ElementSpec SliderElementSpec =
{
TK_STYLE_VERSION_2,
sizeof(SliderElement),
SliderElementOptions,
SliderElementGeometry,
SliderElementDraw
};
/*
*----------------------------------------------------------------------
* +++ Progress element:
*
* A progress bar.
* @@@ reuses most of the slider element
*/
static void
ProgressElementDraw(
void *clientData, void *elementRecord,
Tk_Window tkwin, Drawable d,
int x, int y, int width, int height,
unsigned int state)
{
SliderElement *slider = elementRecord;
Tk_3DBorder border = NULL;
int relief, borderWidth, orient;
border = Tk_Get3DBorderFromObj(tkwin, slider->borderObj);
TTK_GetOrientationFromObj(NULL, slider->orientObj, &orient);
Tk_GetPixelsFromObj(NULL, tkwin, slider->borderWidthObj, &borderWidth);
Tk_GetReliefFromObj(NULL, slider->reliefObj, &relief);
Tk_Fill3DRectangle(tkwin, d, border,
x, y, width, height,
borderWidth, relief);
}
static TTK_ElementSpec ProgressElementSpec =
{
TK_STYLE_VERSION_2,
sizeof(SliderElement),
SliderElementOptions,
SliderElementGeometry,
ProgressElementDraw
};
/*------------------------------------------------------------------------
* Layouts:
*/
TTK_BEGIN_LAYOUT(LabelLayout)
TTK_LAYOUT_DRAW("Label.background")
TTK_LAYOUT_INSIDE("Label.border",
TTK_LAYOUT_INSIDE("Label.padding",
TTK_LAYOUT_HFILL("Label.compound")))
TTK_END_LAYOUT
TTK_BEGIN_LAYOUT(ButtonLayout)
TTK_LAYOUT_DRAW("Button.background")
TTK_LAYOUT_INSIDE("Button.highlight",
TTK_LAYOUT_INSIDE("Button.border",
TTK_LAYOUT_INSIDE("Button.padding",
TTK_LAYOUT_HFILL("Button.compound"))))
TTK_END_LAYOUT
TTK_BEGIN_LAYOUT(CheckbuttonLayout)
TTK_LAYOUT_DRAW("Checkbutton.background")
TTK_LAYOUT_INSIDE("Checkbutton.highlight",
TTK_LAYOUT_INSIDE("Checkbutton.border",
TTK_LAYOUT_INSIDE("Checkbutton.padding",
TTK_LAYOUT_LEFT("Checkbutton.indicator")
TTK_LAYOUT_HFILL("Checkbutton.compound"))))
TTK_END_LAYOUT
TTK_BEGIN_LAYOUT(RadiobuttonLayout)
TTK_LAYOUT_DRAW("Radiobutton.background")
TTK_LAYOUT_INSIDE("Radiobutton.highlight",
TTK_LAYOUT_INSIDE("Radiobutton.border",
TTK_LAYOUT_INSIDE("Radiobutton.padding",
TTK_LAYOUT_LEFT("Radiobutton.indicator")
TTK_LAYOUT_HFILL("Radiobutton.compound"))))
TTK_END_LAYOUT
TTK_BEGIN_LAYOUT(VerticalScrollbarLayout)
TTK_LAYOUT_DRAW("Scrollbar.background")
TTK_LAYOUT_INSIDE("Scrollbar.trough",
TTK_LAYOUT_TOP("Scrollbar.uparrow")
TTK_LAYOUT_BOTTOM("Scrollbar.downarrow")
TTK_LAYOUT_VFILL("Scrollbar.thumb") )
TTK_END_LAYOUT
TTK_BEGIN_LAYOUT(HorizontalScrollbarLayout)
TTK_LAYOUT_DRAW("Scrollbar.background")
TTK_LAYOUT_INSIDE("Scrollbar.trough",
TTK_LAYOUT_LEFT("Scrollbar.leftarrow")
TTK_LAYOUT_RIGHT("Scrollbar.rightarrow")
TTK_LAYOUT_HFILL("Scrollbar.thumb") )
TTK_END_LAYOUT
TTK_BEGIN_LAYOUT(VerticalScaleLayout)
TTK_LAYOUT_DRAW("Scale.background")
TTK_LAYOUT_INSIDE("Scale.highlight",
TTK_LAYOUT_INSIDE("Scale.padding",
TTK_LAYOUT_INSIDE("Scale.trough",
TTK_LAYOUT_TOP("Scale.slider") )))
TTK_END_LAYOUT
TTK_BEGIN_LAYOUT(HorizontalScaleLayout)
TTK_LAYOUT_DRAW("Scale.background")
TTK_LAYOUT_INSIDE("Scale.highlight",
TTK_LAYOUT_INSIDE("Scale.padding",
TTK_LAYOUT_INSIDE("Scale.trough",
TTK_LAYOUT_LEFT("Scale.slider") )))
TTK_END_LAYOUT
TTK_BEGIN_LAYOUT(ProgressBarLayout)
TTK_LAYOUT_INSIDE("Progress.trough",
TTK_LAYOUT_TOP("Progress.bar"))
TTK_END_LAYOUT
/*----------------------------------------------------------------------
* RegisterElements --
*
* Register all elements and layouts defined in this package.
*/
void RegisterElements(Tcl_Interp *interp)
{
TTK_Theme themePtr = TTK_GetTheme(interp, NULL);
/*
* Elements:
*/
TTK_RegisterElementSpec(themePtr, "background",
&BackgroundElementSpec,NULL);
TTK_RegisterElementSpec(themePtr, "border", &BorderElementSpec, NULL);
TTK_RegisterElementSpec(themePtr, "Button.border",
&ButtonBorderElementSpec, NULL);
TTK_RegisterElementSpec(themePtr, "Checkbutton.border",
&PushableBorderElementSpec, NULL);
TTK_RegisterElementSpec(themePtr, "Radiobutton.border",
&PushableBorderElementSpec, NULL);
TTK_RegisterElementSpec(themePtr, "padding", &PaddingElementSpec, NULL);
TTK_RegisterElementSpec(themePtr, "text", &TextElementSpec, NULL);
TTK_RegisterElementSpec(themePtr, "image", &ImageElementSpec, interp);
TTK_RegisterElementSpec(themePtr, "compound", &CompoundElementSpec, interp);
TTK_RegisterElementSpec(themePtr, "indicator",&IndicatorElementSpec,NULL);
TTK_RegisterElementSpec(themePtr, "Radiobutton.indicator",
&RadiobuttonIndicatorElementSpec, NULL);
TTK_RegisterElementSpec(themePtr, "uparrow",
&ArrowElementSpec, &ArrowElements[0]);
TTK_RegisterElementSpec(themePtr, "downarrow",
&ArrowElementSpec, &ArrowElements[1]);
TTK_RegisterElementSpec(themePtr, "leftarrow",
&ArrowElementSpec, &ArrowElements[2]);
TTK_RegisterElementSpec(themePtr, "rightarrow",
&ArrowElementSpec, &ArrowElements[3]);
TTK_RegisterElementSpec(themePtr, "arrow",
&ArrowElementSpec, &ArrowElements[0]);
TTK_RegisterElementSpec(themePtr, "trough", &TroughElementSpec, NULL);
TTK_RegisterElementSpec(themePtr, "thumb", &ThumbElementSpec, NULL);
TTK_RegisterElementSpec(themePtr, "slider", &SliderElementSpec, NULL);
TTK_RegisterElementSpec(themePtr, "highlight", &HighlightElementSpec, NULL);
TTK_RegisterElementSpec(themePtr,"Progress.bar",&ProgressElementSpec,NULL);
/*
* Layouts:
*/
TTK_RegisterLayout(themePtr, "TLabel", LabelLayout);
TTK_RegisterLayout(themePtr, "TButton", ButtonLayout);
TTK_RegisterLayout(themePtr, "TCheckbutton", CheckbuttonLayout);
TTK_RegisterLayout(themePtr, "TRadiobutton", RadiobuttonLayout);
TTK_RegisterLayout(themePtr,
"Vertical.TScrollbar", VerticalScrollbarLayout);
TTK_RegisterLayout(themePtr,
"Horizontal.TScrollbar", HorizontalScrollbarLayout);
TTK_RegisterLayout(themePtr,
"Vertical.TScale", VerticalScaleLayout);
TTK_RegisterLayout(themePtr,
"Horizontal.TScale", HorizontalScaleLayout);
TTK_RegisterLayout(themePtr, "TProgress", ProgressBarLayout);
}
/*EOF*/