Recent Changes - Search:


Mod /

Styles

(:toc:)

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.

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.

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.

Target Patterns

A target is a specifier of the form:

   Class.winname/subwin@group

The elements (any of which may be empty) are:

ElementDescription
Classthe widget class (usually from [winfo class])
.winnamethe window name (from [winfo name] or gui '-id' attr)
/subwinwindow is a child of named window id.
@groupthe group name (from a gui '-gid' attr or [Tk::styles::setgroup])

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.

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 }

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 }

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 }
}

Configuration Actions

The most common configuration option is any valid option accepted by the widget configure subcommand. Examples are -bg and -fg.

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.

Expand Actions

The action name = is used to expand inline the value from a prior target.

  @grp1 { -bg red }
  @grp2 { = @grp1 -fg white }

- 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 }

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 }

Command Actions

A name begining with @ is an action command. These call special purpose functions Tcl procs.

Command Action Reference

Handlers for @ commands are defined in the Tcl namespace ::Tk::styles::StyleCmds. The defined functions are described below.

@bind - Key bindings

Set key bindings on the window.

@break - Terminate current style body

@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 }

@defgradients - Gradient definitions.

This is like @defimages except that the created images are gradients as defined by Winop.

@deficons - Icon Images definition table.

Like @defimages, but also forces images to a standard size.

@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} }

@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.

@@ 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.

@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> } 
        }
    }
}

@image - Sets the -image option.

The @image command sets the -image for the widget.

@matte - Produce a matte effect for a frame.

The @matte command sets up an embossed ridge for a frame.

@pack/place/grid - options for pack, place or grid.

@return - Terminate style.

Terminate style, including sub-styles.

@scheme - Set color scheme.

Setup a color scheme for all subwindows.

@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 }

@stylefile - Include a file as a sub-style.

Like @style but includes a file of style.

@tag - Setup Tags

Setup tags for text widget.

@tip - Tooltip

Set balloon text tip.

@@image - Set an image for option.

The option to set is in the first list element, and the remainder is handled as with @image.

@@font - Set a font for option.

The option to set is in the first list element, and the remainder is handled as with @font.

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 }

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 }
  }

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]

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.

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}}
}

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.

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.

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.

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.

Caveats

Note that styles allow running arbitrary Tcl code with the @eval option and thus are not completely separated from application logic.

Edit - History - Print - Recent Changes - Search
Page last modified on September 20, 2010, at 09:24 PM