What's Inside a Style?

If all you want to do is use a style or create a new one with a few tweaks, you now know everything you need. If, however, you want to make more substantial changes, things start to get "interesting."

Elements

While each style controls a single type of widget, each widget is usually composed of smaller pieces, called elements. It's the job of the style author to construct the entire widget out of these smaller elements. What these elements are depends on the widget.

Here's an example of a button. It might have a border on the very outside. That's one element. Just inside that, there may be a focus ring. Normally, it's just the background color, but could be highlighted when a user tabs into the button. So that's a second element. Then there might be some spacing between that focus ring and the button's label. That spacing is a third element. Finally, the text label of the button itself is a forth element.

Possible elements of a button.
Possible elements of a button.

Why might the style author have divided it up that way? If you have one part of the widget that may be in a different location or a different color than another, it may be a good candidate for an element. Note that this is just one example of how a button could be constructed from elements. Different styles and themes could (and do) accomplish this in different ways.

Here is an example of a vertical scrollbar. It consists of a "trough" element, which contains other elements. These include the up and down arrow elements at either end and a "thumb" element in the middle (it might have additional elements, like borders).

Possible elements of a scrollbar.
Possible elements of a scrollbar.

Layout

Besides specifying which elements make up a widget, a style also defines how those elements are arranged within the widget. This is called their layout. Our button had a label element inside a spacing element, inside a focus ring element, inside a border element. Its logical layout is this:

border {
    focus {
        spacing {
            label
        }
    }
}

We can ask Tk for the layout of the TButton style:


#![allow(unused)]
fn main() {
println!( "{}", tbutton_style.layout()? );
// "Button.border -sticky nswe -border 1 -children {Button.focus -sticky nswe -children {Button.spacing -sticky nswe -children {Button.label -sticky nswe}}}"
}

If we clean this up and format it a bit, we get something with this structure:

Button.border -sticky nswe -border 1 -children {
    Button.focus -sticky nswe -children {
        Button.spacing -sticky nswe -children {
            Button.label -sticky nswe
        }
    }
}

This starts to make sense; we have four elements, named Button.border, Button.focus, Button.spacing, and Button.label. Each has different element options, such as children, sticky, and border that specify layout or sizes. Without getting into too much detail at this point, we can clearly see the nested layout based on the children and sticky attributes.

Styles uses a simplified version of Tk's pack geometry manager to specify element layout. This is detailed in the style reference manual page.

Element Options

Each of these elements has several different options. For example, a label element has a font and a foreground color. An element representing the thumb of a scrollbar may have one option to set its background color and another to provide the width of a border. These can be customized to adjust how the elements within the overall widget look.

You can determine what options are available for each element? Here's an example of checking what options are available for the label inside the button (which we know from the layout method is identified as Button.label):


#![allow(unused)]
fn main() {
let options = tk
    .element("Button.label")
    .element_options()?
    .iter()
    .fold( String::new(), |acc,opt| format!( "{} {}", acc, opt ));
println!( "{}", options ); // " -compound -space -text -font -foreground -underline -width -anchor -justify -wraplength -embossed -image -stipple -background"
}

In the following sections, we'll look at the not-entirely-straightforward way to work with element options.