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.
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.
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.
optionClear, optionAdd, optionGet, and optionReadfile are the standard Tk resource handling methods. For complete details, read the Tk::option manpage. Briefly:
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.
$b3->optionGet('foreground', ' Frog'); $b3->optionGet('foreground', ref $b3);
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;
In addition to the option* methods, Perl/Tk provides the following subroutines to manage the option database, fully described in the Tk::CmdLine manpage.
Copyright © 2002 O'Reilly & Associates. All rights reserved.