www.gibmonks.com

  Previous section   Next section

Practical Programming in Tcl & Tk, Third Edition
By Brent B. Welch

Table of Contents
Chapter 46.  Writing a Tk Widget in C


Specifying Widget Attributes

Several of the fields in the Clock structure are attributes that can be set when the widget is created or reconfigured with the configure operation. The Tk_ConfigureWidget procedure is designed to help you manage the default values, their resource names, and their class names. It works by associating a widget option with an offset into the widget data structure. When you use a command line argument to change an option, Tk_ConfigureWidget reaches into your widget structure and changes the value for you. Several types are supported, such as colors and fonts, and Tk_ConfigureWidget handles all the memory allocation used to store the values. Example 46-9 shows the Tk_ConfigSpec type used to represent information about each attribute:

Example 46-9 The Tk_ConfigSpec typedef.
typedef struct Tk_ConfigSpec {
   int type;
   char *name;
   char *dbName;
   char *dbClass;
   char *defValue;
   int offset;
   int specflags;
   Tk_CustomOption *customPtr;
} Tk_ConfigSpec;

The initial field is a type, such as TK_CONFIG_BORDER. Colors and borders will be explained shortly. The next field is the command-line flag for the attribute, (e.g., -background). Then comes the resource name and the class name. The default value is next, (e.g., light blue). The offset of a structure member is next, and the Tk_Offset macro is used to compute this offset. The specflags field is a bitmask of flags. The two used in this example are TK_CONFIG_COLOR_ONLY and TK_CONFIG_MONO_ONLY, which restrict the application of the configuration setting to color and monochrome displays, respectively. You can define additional flags and pass them into Tk_ConfigureWidget if you have a family of widgets that share most, but not all, of their attributes. The tkButton.c file in the Tk sources has an example of this. The customPtr is used if you have a TK_CONFIG_CUSTOM type, which is explained in detail in the manual page for Tk_ConfigureWidget. Example 46-10 shows the Tk_ConfigSpec specification of widget attributes for the clock widget.

Example 46-10 Configuration specs for the clock widget.
static Tk_ConfigSpec configSpecs[] = {
   {TK_CONFIG_BORDER, "-background", "background",
      "Background", "light blue",
      Tk_Offset(Clock, background), TK_CONFIG_COLOR_ONLY},
   {TK_CONFIG_BORDER, "-background", "background",
      "Background", "white", Tk_Offset(Clock, background),
      TK_CONFIG_MONO_ONLY},
   {TK_CONFIG_SYNONYM, "-bg", "background", (char *) NULL,
      (char *) NULL, 0, 0},
   {TK_CONFIG_SYNONYM, "-bd", "borderWidth", (char *) NULL,
      (char *) NULL, 0, 0},
   {TK_CONFIG_PIXELS, "-borderwidth", "borderWidth",
      "BorderWidth","2", Tk_Offset(Clock, borderWidth), 0},
   {TK_CONFIG_RELIEF, "-relief", "relief", "Relief",
      "ridge", Tk_Offset(Clock, relief), 0},
   {TK_CONFIG_COLOR, "-foreground", "foreground",
      "Foreground", "black", Tk_Offset(Clock, foreground),
      0},
   {TK_CONFIG_SYNONYM, "-fg", "foreground", (char *) NULL,
      (char *) NULL, 0, 0},
   {TK_CONFIG_COLOR, "-highlightcolor", "highlightColor",
      "HighlightColor", "red", Tk_Offset(Clock, highlight),
      TK_CONFIG_COLOR_ONLY},
   {TK_CONFIG_COLOR, "-highlightcolor", "highlightColor",
       "HighlightColor", "black",
      Tk_Offset(Clock, highlight),TK_CONFIG_MONO_ONLY},
   {TK_CONFIG_COLOR, "-highlightbackground",
      "highlightBackground", "HighlightBackground",
      "light blue", Tk_Offset(Clock, highlightBg),
      TK_CONFIG_COLOR_ONLY},
   {TK_CONFIG_COLOR, "-highlightbackground",
      "highlightBackground", "HighlightBackground",
      "black", Tk_Offset(Clock, highlightBg),
      TK_CONFIG_MONO_ONLY},
   {TK_CONFIG_PIXELS, "-highlightthickness",
      "highlightThickness","HighlightThickness",
      "2", Tk_Offset(Clock, highlightWidth), 0},
   {TK_CONFIG_PIXELS, "-padx", "padX", "Pad",
      "2", Tk_Offset(Clock, padX), 0},
   {TK_CONFIG_PIXELS, "-pady", "padY", "Pad",
      "2", Tk_Offset(Clock, padY), 0},
   {TK_CONFIG_STRING, "-format", "format", "Format",
      "%H:%M:%S", Tk_Offset(Clock, format), 0},
   {TK_CONFIG_FONT, "-font", "font", "Font",
      "Courier 18",
       Tk_Offset(Clock, tkfont), 0},
   {TK_CONFIG_END, (char *) NULL, (char *) NULL,
       (char *) NULL, (char *) NULL, 0, 0}
};

There is an alternative to the Tk_ConfigureWidget interface that understands Tcl_Obj values in the widget data structure. It uses a a similar type, Tk_OptionSpec, and Tk_ConfigureWidget is replaced by the Tk_SetOptions, Tk_GetOptionValue, and Tk_GetOptionInfo procedures. Example 46-11 shows the Tk_OptionSpec type.

Example 46-11 The Tk_OptionSpec typedef.
typedef struct Tk_OptionSpec {
   Tk_OptionType type;
   char *optionName;
   char *dbName;
   char *dbClass;
   char *defValue;
   int objOffset;
   int internalOffset;
   int flags;
   ClientData clientData;
   int typeMask;
} Tk_OptionSpec;

The Tk_OptionSpec has two offsets, one for normal values and one for Tcl_Obj values. You can use the second offset to set Tcl_Obj values directly from the command line configuration. The TK_CONFIG_PIXELS type uses both offsets. The pixel value is stored in an integer, and a Tcl_Obj is used to remember the exact string (e.g., 0.2cm) used to specify the screen distance. Most of the functionality of the specflags field of Tk_ConfigSpec (e.g., TK_CONFIG_MONO_ONLY) has been changed. The flags field accepts only TK_CONFIG_NULL_OK, and the rest of the features use the clientData field instead. For example, the color types uses clientData for their default on monochrome displays. The typeMask supports a general notion of grouping option values into sets. For example, the clock widget marks attributes that affect geometry and color into different sets. This lets the widget optimize its configuration procedure. Example 46-12 shows the Tk_OptionSpec specification of the clock widget attributes.

Example 46-12 The Tk_OptionSpec structure for the clock widget.
#define GEOMETRY_MASK 0X1
#define GRAPHICS_MASK 0X2

static Tk_OptionSpec optionSpecs[] = {
   {TK_OPTION_BORDER, "-background", "background",
      "Background", "light blue", -1,
      Tk_Offset(Clock, background), 0,
      (ClientData) "white", GRAPHICS_MASK},
   {TK_OPTION_SYNONYM, "-bg", "background", (char *) NULL,
      (char *) NULL, -1, 0,0, (ClientData)"-background", 0},
   {TK_OPTION_PIXELS, "-borderwidth", "borderWidth",
      "BorderWidth", "2", Tk_Offset(Clock, borderWidthPtr),
      Tk_Offset(Clock, borderWidth),
      0, 0, GEOMETRY_MASK},
   {TK_OPTION_SYNONYM, "-bd", "borderWidth", (char *) NULL,
      (char *) NULL, -1,0,0,(ClientData)"-borderwidth", 0},
   {TK_OPTION_RELIEF, "-relief", "relief", "Relief",
      "ridge", -1, Tk_Offset(Clock, relief), 0, 0, 0},
   {TK_OPTION_COLOR, "-foreground", "foreground",
      "Foreground", "black",-1, Tk_Offset(Clock, foreground),
      0, (ClientData) "black", GRAPHICS_MASK},
   {TK_OPTION_SYNONYM, "-fg", "foreground", (char *) NULL,
      (char *) NULL, -1, 0,0,(ClientData) "-foreground", 0},
   {TK_OPTION_COLOR, "-highlightcolor", "highlightColor",
      "HighlightColor", "red",-1, Tk_Offset(Clock, highlight),
      0, (ClientData) "black", GRAPHICS_MASK},
   {TK_OPTION_COLOR, "-highlightbackground",
      "highlightBackground", "HighlightBackground",
      "light blue",-1, Tk_Offset(Clock, highlightBg),
      0, (ClientData) "white", GRAPHICS_MASK},
   {TK_OPTION_PIXELS, "-highlightthickness",
      "highlightThickness","HighlightThickness",
      "2", Tk_Offset(Clock, highlightWidthPtr),
      Tk_Offset(Clock, highlightWidth), 0, 0,
      GEOMETRY_MASK},
   {TK_OPTION_PIXELS, "-padx", "padX", "Pad",
      "2", Tk_Offset(Clock, padXPtr),
      Tk_Offset(Clock, padX), 0, 0, GEOMETRY_MASK},
   {TK_OPTION_PIXELS, "-pady", "padY", "Pad",
      "2", Tk_Offset(Clock, padYPtr),
      Tk_Offset(Clock, padY), 0, 0, GEOMETRY_MASK},
   {TK_OPTION_STRING, "-format", "format", "Format",
      "%H:%M:%S",-1, Tk_Offset(Clock, format), 0, 0,
      GEOMETRY_MASK},
   {TK_OPTION_FONT, "-font", "font", "Font",
      "Courier 18",
      -1, Tk_Offset(Clock, tkfont), 0, 0,
      (GRAPHICS_MASK|GEOMETRY_MASK)},
   {TK_OPTION_END, (char *) NULL, (char *) NULL,
       (char *) NULL, (char *) NULL, -1, 0, 0, 0, 0}
};

Table 46-1 lists the correspondence between the configuration type of the option and the type of the associated field in the widget data structure. The same types are supported by the Tk_ConfigSpec and Tk_OptionSpec types, with a few exceptions. The TK_CONFIG_ACTIVE_CURSOR configuration type corresponds to the TK_OPTION_CURSOR; both of these set the widgets cursor. The TK_CONFIG_MM and TK_CONFIG_CURSOR types are simply not supported by Tk_OptionSpec because they were not very useful. The TK_OPTION_STRING_TABLE replaces TK_CONFIG_CAP_STYLE and TK_CONFIG_JOIN_STYLE with a more general type that works with Tcl_GetIndexFromObj. In this case, the clientData is an array of strings that are passed to Tcl_GetIndexFromObj. The index value corresponds to the integer value returned from procedures like Tk_GetCapStyle.

Table 46-1. Configuration flags and corresponding C types.

TK_CONFIG_ACTIVE_CURSOR

TK_OPTION_CURSOR

Cursor

TK_CONFIG_ANCHOR

TK_OPTION_ANCHOR

Tk_Anchor

TK_CONFIG_BITMAP

TK_OPTION_BITMAP

Pixmap

TK_CONFIG_BOOLEAN

TK_OPTION_BOOLEAN

int (0 or 1)

TK_CONFIG_BORDER

TK_OPTION_BORDER

Tk_3DBorder *
TK_CONFIG_CAP_STYLEint (see Tk_GetCapStyle)

TK_CONFIG_COLOR

TK_OPTION_COLOR

XColor *

clientData is monochrome default.

TK_CONFIG_CURSORCursor
TK_CONFIG_CUSTOM 

TK_CONFIG_DOUBLE

TK_OPTION_DOUBLE

double

TK_CONFIG_END

TK_OPTION_END

(signals end of options)

TK_CONFIG_FONT

TK_OPTION_FONT

Tk_Font

TK_CONFIG_INT

TK_OPTION_INT

int
TK_CONFIG_JOIN_STYLEint (see Tk_GetJoinStyle)

TK_CONFIG_JUSTIFY

TK_OPTION_JUSTIFY

Tk_Justify
TK_CONFIG_MMdouble

TK_CONFIG_PIXELS

TK_OPTION_PIXELS

int

objOffset used for original value.

TK_CONFIG_RELIEF

TK_OPTION_RELIEF

int (see Tk_GetRelief)

TK_CONFIG_STRING

TK_OPTION_STRING

char *
TK_OPTION_STRING_TABLEThe clientData is an array of strings used with Tcl_GetIndexFromObj

TK_CONFIG_SYNONYM

TK_OPTION_SYNONYM

(alias for other option)

clientData is the name of another option.

TK_CONFIG_UIDTk_Uid

TK_CONFIG_WINDOW

TK_OPTION_WINDOW

Tk_Window


      Previous section   Next section
    Top