Making the most of the Tk option database

Unix Insider –

Modern scripting languages have come a long way toward achieving portability in the last couple of years. Even portable tools, though, benefit from platform-specific instruction.

The Tk option database is portable in the sense that it's documented identically for Mac OS, Unix, Windows, and the other operating systems for which Tk is available. However, you're likely to make different use of its functions on different platforms. Mac OS, Unix, and Windows all customize application instances by assigning values to resources or properties. The Tk option database is a child of the particular scheme that the X Window system defines, which is widely available on Unix hosts. In this system of X resources, you can, for example, code

<font face="Courier">foreground red</font>
, which means characters will appear in red.

X resources has a reputation for being inscrutably complex, mostly because it makes simple ideas very flexible in an unsystematic way. For example, you can assign

<font face="Courier">foreground red</font>
in at least a half dozen modes so that it will apply only in a specific application, only for a specific user, only for a particular invocation of an application, and so on. The Tk option database's interface was derived from that complex set of interfaces.

One aspect of the Tk is taken from

<font face="Courier">.Xdefaults</font>
, a configuration file located in a Unix
<font face="Courier">$HOME</font>
directory, as is
<font face="Courier">.mailrc</font>
or
<font face="Courier">.login</font>
. Its syntax is a simple list of resource assignments, one on each line. A very small
<font face="Courier">.Xdefaults</font>
file might look like:

Using the Tk option database:

Read the whole series!

  • Part 1. Individualize your apps
  • Part 2. Making the most out of the option database
  • Part 3. Options for the Tk option database
  • <font face="Courier">
    
      *fontMenu*background: green
    
        *foreground: black
    
    </font>

    We mentioned in our previous column that Tk under Unix is, among other things, a well-behaved X application. Therefore, Tk launched from Unix can be trusted to read

    <font face="Courier">.Xdefaults</font>
    . From within Tk, you can programmatically inspect the pertinent resources assigned there. The
    <font face="Courier">[option get]</font>
    subcommand does this:

    <font face="Courier">
    
            # Assume .Xdefaults has the content listed above.
    
        set value [option get . foreground ""]
    
        puts "'value' now holds the value 'black':  $value."
    
    </font>

    Moving beyond Unix

    Most readers of this column probably use Windows systems from time to time. Windows has no standard for interpretation of

    <font face="Courier">.Xdefaults</font>
    ; however, Tk supports the
    <font face="Courier">[option readfile]</font>
    subcommand on all platforms. That gives Windows a portable way to specify a resource configuration, as in:

    <font face="Courier">
    
        set filename [file join $env(HOME) .Xdefaults]
    
        option readfile $filename
    
    </font>

    Because Tk has already read

    <font face="Courier">$HOME/.Xdefaults</font>
    , execution of that fragment under Unix is redundant. On Windows, though, those lines read
    <font face="Courier">C:\.Xdefaults</font>
    and make the same initializations a Unix host would have read.

    That illustrates why we're careful when we write about "portability."

    <font face="Courier">.Xdefaults</font>
    is naturally meaningful on one OS, but not another. How should a portable language process a file that doesn't exist on most platforms? Tk's answer to that question has two parts. First, Tk behaves as a normal X application under Unix. Default actions are what a Unix user expects there. Second, the
    <font face="Courier">option</font>
    command provides a cross-platform layer that enables you to write option-database code that is simultaneously portable and maintainable. You can choose to configure and use
    <font face="Courier">.Xdefaults</font>
    in a portable way, and Tk does its part to make that possible.

    Full complement of subcommands

    A different subcommand,

    <font face="Courier">[option add]</font>
    , gives still another slant on portability. Suppose we drop
    <font face="Courier">.Xdefaults</font>
    entirely. Under Unix it's certainly possible to launch an X-based application with no
    <font face="Courier">.Xdefaults</font>
    ; the options database would simply be empty. Such an application could still be configured, though. Tk applications on any platform can interpret

    <font face="Courier">
    
        *fontMenu*background: green
    
    		 *foreground: black    
    
    </font>

    as Tk source code to give the same result as our

    <font face="Courier">.Xdefaults</font>
    example.

    Let's summarize all this in terms of source-code architecture. Suppose we want to set the font of all our entry widgets to

    <font face="Courier">times 12 bold</font>
    . We might write:

    <font face="Courier">
    
        entry $widget -font {times 12 bold} ...
    
    </font>

    for each entry we create. The redundancy of repeating the font specification in several places makes maintenance fragile.

    One approach we often take in our development work to combat this problem is to create an "entry factor":

    <font face="Courier">
    
        proc make_entry {widget ...} {
    
            set font {times 12 bold}
    
    		 entry $widget -font $font ...
    
        }
    
    </font>

    We can also go in an even more declarative direction and initialize the source code with:

    <font face="Courier">
    
        option add *Entry.font {times 12 bold}
    
    </font>

    Finally, we can externalize the declaration entirely, by using

    <font face="Courier">option readfile</font>
    and a separate file with contents:

    <font face="Courier">
    
        *Entry*font: times 12 bold
    
    </font>

    Each of those four choices is entirely portable. Decide among them by considering the overall architecture of your application. If you're dashing off a tiny prototype, coding the font specification inline each time you need it -- as the first choice above does - is probably quickest. If you have several applications, each in use by several people, and you need uniformity of appearance across applications and users, even

    <font face="Courier">option readfile</font>
    won't exhaust the option database's capabilities.

    As we explained previously, you have several supplementary ways to set resources with Unix OSs. Until then, have fun making your GUIs more consistent and maintainable with the option database.

    Resources

  • "Individualize Your Apps," Cameron Laird and Allen Flick. The first part in this series: http://www.itworld.com/AppDev/1243/UIR000602regex/
  • Options and Tk: A Beginner's Guide: http://www.cs.man.ac.uk/~fellowsd/tcl/option-tutorial.html
  • The X Window User HOWTO: The X Resources: http://www.linuxdoc.org/HOWTO/XWindow-User-HOWTO-8.html
  • Using Configuration Files to Customize Your Windows Environment: http://www.unix.digital.com/faqs/publications/base_doc/DOCUMENTATION/V40D_HTML/AQ917BTE/DOCU_012.HTM
  • XRDB(1) manual page: http://www.xfree86.org/4.0/xrdb.1.html
  • Past Regular Expressions columns: http://www.itworld.com/Comp/2378/UIRRegularExpressions/
  • This story, "Making the most of the Tk option database" was originally published by ITworld.

    Copyright © 2001 IDG Communications, Inc.

      
    Shop Tech Products at Amazon