Book HomeMastering Perl/TkSearch this book

16.2. Using the Option Database

The option database is populated by several mechanisms. We already know Tk::CmdLine::SetArguments sets standard X11 options prior to MainWindow creation. Unix users should be familiar with the .Xdefaults file, a simple text file that can contain resource entries and is one of the files Tk::CmdLine::SetArguments reads during MainWindow initialization. Perl/Tk programs can load resources from other files as well by calling Tk::CmdLine::LoadResources or optionReadfile. Or, Tk::CmdLine::SetResources and optionAdd can add individual resources to the option database. For the location of other resources files, please read the manpage for Tk::CmdLine.

Here are some sample resource entries:

*font                         : 12x24
frog*Foreground               : blue
frog.button1.Background       : orange
frog.b3.foreground            : green
frog*Label*cursor             : gobbler 

Note that the resource pattern is to the left of the colon, and its value to the right. The pattern can be general (such as the first entry, which changes the default font for every X and Tk application) or specific (such as the fourth entry, which changes only the foreground color of the widget named b3 of the application frog).

A resource pattern identifies an option and one or more widgets in the window hierarchy. Tk generates the hierarchy automatically, assigning string pathnames to each widget. In Chapter 13, "Miscellaneous Perl/Tk Methods", we learned that Tcl/Tk programmers are required to do this manually. In Perl/Tk, we seldom need to refer to widget pathnames; rather, we use object references. If we need to see a widget's pathname, we use the PathName method. Pathnames are composed of words (components) separated by pathname separators (.), analogous to the forward slash in Unix pathnames or the backslash in Win32. For example, the pathname .frame.text.button might represent the Button created from these commands:

$mw->Frame;
$t = $mw->Text;
$b = $t->Button;

A resource pattern is also composed of words separated by . and * characters. These words may be program names, class names, option names, or widget names (a widget's name is the leaf portion of its pathname; if the pathname is .a.b.c, the leaf portion is c).

The characters . and * are used to provide tight and loose pattern match bindings. The . is the tight binding operator, separating adjacent pathname components. The * is the loose binding operator, separating any number of pathname components, including none. That's why the *font resource changes the font for any X or Tk program.

If you want a resource to apply to a particular program (or instance of a program), prepend the program name as the first component of the pattern. In the previous example, the second through fifth resources apply only to the program "frog". frog is in quotes because there are various ways to name a program frog. First, the program's filename can be frog or frog.ext (extensions are thrown away). Or, use the -name command-line option and name any old program frog.

A program's class name is its name with the first character capitalized or the value of the -class command-line option. Thus, if you have several frog-related programs, named, say, tree-frog and sand-frog, they could all be of class Frog and share resource entries, each of whose first component is Frog. Resource entries beginning with Frog are distinct from those beginning with frog.

Let's use the following program as an example. We create the MainWindow and disable its propagate feature, so it doesn't shrink-wrap itself around the widgets inside it. This lets us see its background color. Somewhere early on in this process, Tk::CmdLine::SetArguments is called to initialize the option database with command-line option/values. We print @ARGV so we can see what's left in the array after the call to MainWindow.

The Label's purpose is simply to show us the application's class and name, which affect how option database lookups work.

Now for the three Buttons, each designed for a special purpose. The first has a hardcoded background color, so it should remain yellow no matter what background-related resources are in the option database. The second button has no attributes set, so its background can be set from the option database. Finally, the third button has explicity set its name using the Name option. A widget's name can be changed only during widget creation; the name cannot be reconfigured afterwards. If the Name option is omitted, Tk automatically generates the name.

Lastly, we loop through all the widgets (ignoring Labels) and configure the Button's text to show its full pathname. It's the pathname we're interested in when creating resource entries.

my $mw = MainWindow->new;
$mw->packPropagate(0);

print "ARGV=@ARGV.\n";

my $l1 = $mw->Label(-text =>
    "Application class/name is\n'" . $mw->class . '/' . $mw->name . "'");
$l1->pack;
my $b1 = $mw->Button(-background => 'yellow')->pack;
my $b2 = $mw->Button->pack;
my $b3 = $mw->Button('Name' => 'B3')->pack;

foreach ($mw->children) {
    next if ref $_ eq 'Tk::Label';
    $_->configure(-text => "'" . $_->PathName . "'");
}

Let's assume the preceding code is saved in a file named frog. This means that the program's name is frog and its class is Frog.

For our test runs, we'll use the same resource entries that we saw before, which we've stored in our .Xdefaults file.

*font                         : 12x24
frog*Foreground               : blue
frog.button1.Background       : orange
frog.b3.foreground            : green
frog*Label*cursor             : gobbler 

This file always resides in our home directory. Tk uses the value of the environment variable $HOME to locate the .Xdefaults file. Under Unix, the variable is always defined, but not so for you Win32 users, where the concept of a home directory doesn't exist. Nevertheless, you can define an MS-DOS HOME environment variable pointing to any directory you choose and store your .Xdefaults file there. If you want the .Xdefaults file on your desktop, use this command:

set HOME=c:\windows\desktop

Alternatively, you can create a batch (.bat) file, which might look like this:

set HOME=C:\Program Files\PerlApps
perl "C:\Program Files\PerlApps\fontviewer.pl"

This allows you to keep various resource files lying about.

Now run the program with the following command-line arguments and note the output. It shows us that Tk::CmdLine::SetArguments has indeed processed the -geometry option and left the unknown option in @ARGV for us to handle. Figure 16-1 displays the window.

 [bug@Pandy atk]$ frog -geometry -0-0 -unknown-arg 123
ARGV=-unknown-arg 123. 
Figure 16-1

Figure 16-1. frog application with a huge font

It's immediately clear that the font is huge. That's due to a loose binding *font : 12x24 resource. This turns out to be a very unpleasant resource, as it trashes nearly every graphical application. Fortunately for us, we can still tell that the program's class and name are Frog and frog, respectively.

Although you can't tell from the grayscale image, the first Button (.button) has a yellow background with blue lettering. Indeed, the loose binding frog*Foreground : blue resource ensures that any widget attribute of class Foreground is set to blue, unless otherwise overridden.

The second Button (.button1) has an orange background and, again, a blue foreground.

The third Button (.b3) has the standard gray background with green lettering when inactive. In the figure, the Button is active, thus its background is blue and foreground is black. It's blue because a Button's -activebackground option is of class Foreground.

Let's remove the loose font resource binding by commenting it out. The option database comment character is the exclamation point.

!*font                         : 12x24
frog*Foreground                : blue
frog.button1.Background        : orange
frog.b3.foreground             : green
frog*Label*cursor              : gobbler 

Figure 16-2 shows the result. First, the font is back to the Tk default. We've also left the pointer hanging over the Label and, as per the option database, the cursor has changed to a gobbler.

Figure 16-2

Figure 16-2. frog with normal fonts again

What do we do if we want to change the options on some Buttons but not others? From what we've covered, we know that all Button widgets nominally belong to the class Tk::Button, unless we do something to change it. If we want to group all Buttons with the text Ok on them, we can put them in the 'OkButton' class:

$mw->Button(-text => 'Ok', -class => 'OkButton');

Even if you create a Button with the text Cancel, as long as the -class option uses OkButton, it belongs to the proper class.

16.2.1. Manipulating Resources with option* Methods

optionClear, optionAdd, optionGet, and optionReadfile are the standard Tk resource handling methods. For complete details, read the Tk::option manpage. Briefly:

$widget->optionClear
Clears the option database. The next time a resource is added to or removed from the database, .Xdefaults is reloaded automatically.

$widget->optionAdd(pattern => value ?, priority?)
Adds the specified resource to the option database, with a priority of priority (0-100). These are the recommended symbolic values:

widgetDefault (20)
Used for default values hardcoded into widgets.

startupFile (40)
Used for options specified in application-specific startup files.

userDefault (60)
Used for options specified in the .Xdefaults file.

interactive (80)
Used for options specified interactively after the application starts running. This is the default priority.

If an option database lookup results in multiple pattern matches, the one with the highest priority wins. If there are multiple matches at the same priority, the latest resource entered in the option database wins.

$widget->optionGet(name, class)
Returns a widget's option value given the specified name and class. name might be a configuration option like background, and class might be an application's class name or widget class, such as Tk::Button. This method is for looking up option database values only; it is not an analog of cget. In the context of the program frog, these commands both return green:

$b3->optionGet('foreground', ' Frog');
$b3->optionGet('foreground', ref $b3); 
$widget->optionReadfile(pathName ?, priority?)
Loads the resources from file pathName at the given priority.

Be aware that Perl/Tk widgets can have hierarchical class names (Tk::A::B), but that the internal Tk class is always the leaf part (B). The internal Tk class is used as the identifier for option database lookups, as the following code demonstrates:

package Tk::Foo::Bar;
use base qw/Tk::Label/;
Construct Tk::Widget 'FooBar';

package main;
$mw = MainWindow->new;
$mw->optionAdd("*FooBar.background", "red"); # does not work
$mw->optionAdd("*Bar.foreground", "blue");      # works
$f = $mw->FooBar(-text => "foobar")->pack;
warn $f->Class;

16.2.2. Manipulating Resources with Tk::CmdLine Subroutines

In addition to the option* methods, Perl/Tk provides the following subroutines to manage the option database, fully described in the Tk::CmdLine manpage.

Tk::CmdLine::SetArguments([args])
Parses the command-line-formatted option/value pairs in the array args and adds them to the option database. The array @ARGV is used by default. Perl/Tk implicitly calls this subroutine as it creates the first MainWindow.

Tk::CmdLine::cget([option])
Returns the value of an option initialized by Tk::CmdLine::SetArguments. The only valid options are -class, -name, -screen, and -title. You might use this command to determine an application's class, which then might map to a particular resource file to load via Tk::CmdLine::LoadResources. The default option is -class.

Tk::CmdLine::SetResources(resource [, priority])
Sets one or more resources. If resource is a scalar, it's interpreted as a resource pattern/value string. If resource is an array reference, its elements may be pattern/value strings or yet another reference to an array of two elements, the first being the pattern and the second the pattern's value. The priority defaults to userDefault.

Tk::CmdLine::LoadResources
Loads resources from one or more files into the option database. This subroutine accepts four options, though none are required. Typically, you would use -file => pathName and perhaps -priority => priority. The -symbol option specifies the name of an environment variable that contains a colon-separated list of directory and/or file patterns. The -echo option expects a file handle reference (default is \*STDOUT). For every resource file loaded, its filename is written to this file handle. Refer to the Tk::CmdLine manpage for details.



Library Navigation Links

Copyright © 2002 O'Reilly & Associates. All rights reserved.