1. Styles
Styles are used by Gui to abstract Tk
options ie. colors, fonts and images.
Hard-coded options are very convenient to use in small Tk applications.
However as program size increases
the quantity of code given over to managing such options
tends to grow unchecked.
This leads to excess complexity and in general creates a maintainence headache.
Styles avoid such problems by applying options implictly,
using pattern rules, and in a fault tolerant manner.
2. Example
Here's an example employing style (via
the Toplevel style sub-command):
package require Mod
set t [Toplevel new .demo%d]
Toplevel style $t {
.w* { -bd 2 -relief raised }
.win { -bg Black -fg White }
Entry { -bg Pink }
}
pack [Text new $t.win]
pack [Entry new $t.we1] -fill x
Defined options are
automatically apply to subwidgets at creation.
Moreover, these options are set
fault tolerantly with errors silently ignored.
During development time, you can optionally enable warnings.
3. Style Specification
In their simplest form
a style specification is defined as a Tcl list of pairs, eg.
TARGET ACTIONS TARGET ACTIONS ...
where TARGET is a pattern match, and
ACTIONS a list of configuration options.
4. Target Patterns
A target is a specifier of the form:
Class.winname/subwin@group
The elements (any of which may be empty) are:
| Element | Description |
| Class | the widget class (usually from [winfo class]) |
| .winname | the window name (from [winfo name] or gui '-id' attr) |
| /subwin | window is a child of named window id. |
| @group | the group name (from a gui '-gid' attr or [Tk::styles::setgroup]) |
4.1 Patterns
Any element may contain wildcards, eg:
.but* { -bd 1 -bg Green }
.fi*er* { -fg Red }
Text.f* { -bg Blue }
T*.[a-e]* { -font Courier }
In the above, the pattern .but* would match .button, .but1, etc.
Note 1: window names
(the tail portion of a widget path) are assumed to
be unique within a toplevel
Note 2: more than one TARGET can be matched.
This means later options can be used to override earlier ones.
4.2 Groups
A group is specified using a @. This will
match any gui element that used a -gid attribute
or any window that registered with [Tk::styles::setgroup],
eg.
Button@grp { -bg Red }
4.3 Sub-Windows
A sub-window is specified using a /. This will
match only gui elements that are a child of the named
id, eg.
Button/topframe { -bg red }
5. Actions
Actions are a list of name/value pairs with form:
{ name value name value ....}
Each name begins with a prefix char that is one of:
- : A widget configuration option.
* : A Tk database option.
@ : Cmd call in StyleCmds, eg @tip, @bind.
= : Expand actions from previously defined target.
Here's an example:
Toplevel style $x {
Text { -fg black -bg white *borderWidth 2 }
.defs { -bg white -fg black @tip "The main window" }
@mygrp { -font "Courier -19" = Text = .defs }
}
5.1 Configuration Actions
The most common configuration option is any valid option
accepted by the widget configure subcommand.
Examples are -bg and -fg.
5.2 DBoption Actions
A DB option is any
name begining with *, ie. as used in
[option set] command.
The option also tries to apply
a lower case -loweropt to the widget. eg:
Text { *borderWidth 2 }
This will be implemented as:
option add *APPATH...borderWidth 2
$w configure -borderwidth 2
Valid database options include any option
defined in fields 2 and 3 from a widgets configure subcommand. These options a affect a window
and all of it's descendants.
Note: database options should be used sparingly
because invalid options can break Tk widget creation. Styles
do attempt to detect
invalid options when used with -Wall.
However, the option still gets applied, valid or not.
Thus, the following style breaks virtually all subwidgets.
* { *background BadColor }
Note2: A side effect of using a database style option
is that it normalizes
[tk appname], removing dots, stars, etc.
5.3 Expand Actions
The action name = is used to expand inline
the value from a prior target.
@grp1 { -bg red }
@grp2 { = @grp1 -fg white }
5.4 - Action
The special action dash "-" is used
similar to the Tcl switch statement. It causes the following elements style to be substituted, eg.
Text -
Entry { -bg white }
5.5 The default Target
If the last target is the keyword default,
then it's actions are applied if and only if no other
targets were matched in the current style, eg.
Entry -
Text { -font Courier }
default { -font Helvetica }
5.6 Command Actions
A name begining with @ is an action command.
These call special purpose functions Tcl procs.
6. Command Action Reference
Handlers for @ commands are defined in the Tcl namespace ::Tk::styles::StyleCmds. The defined functions
are described below.
6.1 @bind - Key bindings
Set key bindings on the window.
6.2 @break - Terminate current style body
6.3 @deffonts - Font definitions table.
This command defines a set of named fonts for the toplevel.
These are dereferenced if a value starts with ^,
and are automatically applied to any option that ends with
of font or fonts, eg.
Toplevel { @deffonts {
main {Verdana,Comic,Courier -20}
other {Helvetica -16}
}}
Text { *font ^main }
Label { -font ^other }
6.4 @defgradients - Gradient definitions.
This is like @defimages except that
the created images are gradients as defined by Winop.
6.5 @deficons - Icon Images definition table.
Like @defimages, but also forces images to a standard size.
6.6 @defimages - Images definition table.
This command defines a set of named images for the toplevel
of the application.
These are dereferenced if a value starts with ^,
and automatically applied to any option whose
name ends image, images, icon and icons. eg.
Toplevel { @defimages {
open {openfolder.gif}
close {closefolder.gif}
}}
Button { *image ^open }
Label { -icon ^close }
TreeView { -icons {^close open} }
Wierdy { -showimg {@image ^close} }
6.7 @font - Sets the -font option.
Sets the -font option for the widget. This creates a named
font.
The first component of a font can be a comma separated list
of font family names.
The size can optionally start with a + and followed
by a number from 0-15. These will map to sizes from 4-100,
but may be scaled to fit larger or smaller displays.
A value of 4 generally represents a 12point font
on a 1024 wide display.
The rest can be any normal font option like 'bold,
or -slant italic.
6.8 @@ or @guiattr - GUI Attribute Definitions.
This provides a way for a style to set many of the
attributes for Gui elements, eg.
style {
.mywin {
@guiattr { -pad 0,0 -tip "Text input window" }
}
Tabset::tab {
@guiattr { -img greenball }
}
}
Attributes such as -conf,
-msg and -value
are ignored, because these are handled before window/item
creation.
6.9 @guiattrmap - GUI Attribute Maps.
This provides a way for a style to override groups
of stylistic
attributes in a Gui Toplevel or Menu.
Currently these are limited
to the following attributes: -icon -key -image -tip.
For example, the following sets up attributes
for the File menu.
style {
.file {
@guiattrmap {
-tip { Tab "Open a new file" }
-icon { Tab {fileopen filenew} New {filenew fileopen} Save filesave }
-key { Tab <Alt-t> Open <Alt-o> Close <Alt-w> Save <Alt-s> }
}
}
}
6.10 @image - Sets the -image option.
The @image command sets the -image for the widget.
6.11 @matte - Produce a matte effect for a frame.
The @matte command sets up an embossed ridge for a frame.
6.12 @pack/place/grid - options for pack, place or grid.
6.13 @return - Terminate style.
Terminate style, including sub-styles.
6.14 @scheme - Set color scheme.
Setup a color scheme for all subwindows.
6.15 @style - Apply a sub-style.
Sub-styles using @style are a powerful way to apply styles to just a subset
of a gui. eg:
Menu.top { -bd 1 @style {
.file { -bg blue }
}}
Button { -bg red }
6.16 @stylefile - Include a file as a sub-style.
Like @style but includes a file of style.
6.17 @tag - Setup Tags
Setup tags for text widget.
6.18 @tip - Tooltip
Set balloon text tip.
6.19 @@image - Set an image for option.
The option to set is in the first list element, and the
remainder is handled as with @image.
6.20 @@font - Set a font for option.
The option to set is in the first list element, and the
remainder is handled as with @font.
7. Comments
If any target or action name begins with a #, its
value is treated as a comment string.
eg.
# "The following is for text widgets"
Text { -bg 1 # "An action comment" }
#Button { -bg blue }
8. Sub-styles
For applications containing many gui sub-items,
style specifications can become
quite large and detailed. This may become a concern
as the entire style is traversed for each widget and
item created in a gui.
The @style and @stylefile
command can be used to decompose the style. eg:
style {
Canvas { -bg white @style {
@grp1 { -bg blue }
.rect*@grp2 { -bg red }
}}
Text { -bd 1 @style {
.stat* { -bd 3 -relief raised }
@tgrpa { -bd 2 }
}}
Entry { @stylefile entsty.sty }
}
9. Item Classes
For a widget the class is normally derived using
[winfo class]. But widgets such
as Menu and Text
support sub-elements.
In a gui layout
sub-elements are called an item and in a target
append 2 colons and the
element name, eg.
style {
Canvas::rectangle { -fill blue }
Text::text { -foreground blue }
Text::window::frame { -padx 4 }
}
Note that some items ( such as window::frame above)
automatically add sub-item styles.
However, thes can also
be applied manually using
[styles item], eg:
Canvas new .c
set id [Canvas create rectangle .c {0 0 100 100}]
styles item .c rectangle $id]
9.1 Item Classes and Targets
Normally, an item style will not match a target pattern
that gives just a window, but does not
contain a class. The only exception is a substyle
where some parent style has matched the class, eg:
style {
.mork { -bg green }
Canvas::rectangle { @style {
.mork { -fill blue }
@mindy { -fill pink }
}}
}
This prevents widget options from being applied
to items, or vice versa.
10. Styles Example
Toplevel style $x {
Text { -fg black -bg white }
.defs { -bg white -fg black }
@yourgrp -
@mygrp { -font "Courier -19" }
.datawin { = Text -cursor xterm }
.topframe { = .defs *background yellow @tip "This is a tip" }
.mainwin { -fg blue -bg red @tip "The main window" }
.awin { @font {-weight italic} @tip "A window" }
.mybut { -image {@image foo.gif} @bind {<Control-x> {%_ quit %W} } }
Button/topframe { -bg red }
Menu break
.but* { @@image {*image foo.gif} @@font {*font Courier -10}}
}
11. Caching
The @stylefile command automatically uses
caching so as to speed up style processing.
Even so, when
applying styles to 1000's of elements you may find
styles are not fast enough.
In these cases
styles can be extracted and cached locally by
the application using: [styles map $w -return 1].
See Gridtable.tcl in
Mod for an example.
12. Re-Styling
It is possible to reapply styles to all named elements in
a widget tree with
the 'styles reapply command.
All options are reapplied, but obviously
database options (those starting with *) will have no
effect on subwidgets.
13. XPM
Within Wize, XPM images are supported via the Img extension.
Styles extend this to support
XPM2. As defined in wikipedia, XPM version 2 strips away all of the C style
syntax, eg.
! XPM2
5 7 2 1
. c none
X c steelblue
XXXXX
.....
.....
XXXXX
.....
.....
XXXXX
Moreover, XPMs can further be collapsed in a style by embedding newlines in a
double quoted string!
style {
Toplevel {
@defimages {
vscrbar "! XPM2\n5 7 2 1\n. c none\nX c steelblue\nXXXXX\n.....\n.....\nXXXXX\n.....\n.....\nXXXXX"
}
}
}
Note that XPM2 is processed in Tcl to the standard XPM form
before being passed to Img.
13.1 Conditional Styles
There is no direct support for conditionals in a style.
Instead we can use a Gui with eval, eg.
{Toplevel +} {
eval {
switch -- $tcl_platform(platform) {
unix { return { include unix.gui } }
windows { return { include win.gui } }
default {
return {
style {
.txtwin { -bg LightBlue }
.input { -fg DarkGreen }
}
}
}
}
{Text - -id txtwin} {}
{Entry - -id input} {}
}
ie. an included .gui file could define a style section.
14. Caveats
Note that styles allow running arbitrary Tcl code with
the @eval option and thus are not completely separated from
application logic.
© 2008 Peter MacDonald