From fellowsd@cs.man.ac.uk Wed Nov 19 15:25:19 CST 1997
Article: 75427 of comp.lang.tcl
Path: uuneo.neosoft.com!ultraneo.neosoft.com!news-out.internetmci.com!newsfeed.internetmci.com!205.252.116.205!howland.erols.net!recycled.news.erols.com!nntp.news.xara.net!xara.net!peer.news.nildram.co.uk!pavilion!peernews.ftech.net!159.170.4.40.MISMATCH!news.smsuk.smed.com!yama.mcc.ac.uk!cs.man.ac.uk!fellowsd
From: fellowsd@cs.man.ac.uk (Donal K. Fellows)
Newsgroups: comp.lang.tcl
Subject: Re: Tutorial material needed [Was: Re: length of string in pixels]
Date: 11 Nov 1997 12:54:20 GMT
Organization: Dept of Computer Science, University of Manchester, U.K.
Lines: 263
Message-ID: <649khs$5gf$1@m1.cs.man.ac.uk>
References: <345F70C2.64B5BAEF@awinc.com> <345FB73B.52F2E819@awinc.com> <34631DA1.23F1CEB8@neovision.com> <6473a3$19l$2@srv38s4u.cas.org>
NNTP-Posting-Host: r8h.cs.man.ac.uk
Xref: uuneo.neosoft.com comp.lang.tcl:75427

In article <6473a3$19l$2@srv38s4u.cas.org>,  <lvirden@cas.org> wrote:
> According to Marc Graham  <marc@neovision.com>:
>> No one has ever gotten "option get" to work correctly!  No one
>> understands name and class in the Xdb!
> 
> Okay Tk experts.  There is the claim.  Surely one of you folk who are
> using option get could take some time to write up a tutorial explaining
> how to use option get not only to manage application writer options but
> also Tk core options?

Happy to take up the challenge.
---
0. The Underlying Hierarchy

The widget hierarchy is really a forest (multi-rooted tree) with each
application being one tree.  The branches of the tree are the widgets,
and the leaves of the tree are the options of the widgets.

1. Basic Option Specification Use

To specify an option to a widget using the option database, you need
to specify the pathname of the widget whose option you want to set,
the option which is going to be set, and the value you want to set it
to.  The option database is a collection of these.

If the application is called spong, and you have a widget called
.foo.bar, then you can set the cursor for that widget to be a watch
(or semantic equivalent on non-Unix platforms) using a resource
database entry of:

  spong.foo.bar.cursor: watch
  ^^^^^^^^^^^^^ ^^^^^^  ^^^^^
       path     option  value

There are several ways of making this entry into the resource database
(under unix/X):
   a) Placing the entry in your ~/.Xdefaults file which Tk reads in
      when it starts up. [*]  This is a system-wide file.
   b) Using xrdb to enter it into the system-wide resource database,
      which Tk reads when it starts up. [*]
   c) Using [option add spong.foo.bar.cursor watch]  This is
      specific to the particular app. that performed the operation.
   d) Placing the entry in a file somewhere and using [option readfile]
      to load it in.  This is probably the easiest technique for
      application writers.  This is specific to the particular
      app. that performed the operation, but it is especially useful
      for loading the defaults for an application.

You can always find out the name of a window using [winfo name $win]
though this is mostly only useful when examining . [**]

The name of an option is either listed in the manual page where the
widget is described, or in the options(n) manual page.  It is usually
the same as the -option name, except with the second and all
subsequent words within the name capitalised.  Thus, -borderwidth has
the option name borderWidth

2. Widget Classes

Each widget has a class as well as a name.  Classes are distinguished
>from  names by starting with a capital letter, and they are useful for
when you want to set the options of a collection of similar windows.

The class of most widgets is fixed, but for frames and toplevels, you
can set it to be something new.  I strongly recommend doing this for
toplevels, and particularly those where you will be creating then with
more than one name, as it lets you separate different kinds of windows
(particularly non-modal dialog boxes) from each other.  The use of
programmer-defined classes for frames is mostly less useful, but can
come into its own in highly complex widget hierarchies, and is crucial
to supporting megawidgets correctly in the option database.

When specifying the class of a widget (via the -class option, which
cannot be specified via the resource mechanism) you should take care
not to use the class of any of the normal widgets (like Button,
Scrollbar, Text, etc.) to prevent confusion, if nothing else.

The resource entry:
  spong.foo.Button.cursor: watch
tells all the buttons that are children of .foo in the application
called spong to have a watch cursor.

You can always find out the class of window using [winfo class $win]

3. Application Classes

Applications also have a class, which starts out as a capitalised
version of the name of .  This can be probed in the obvious way.

The name and class of . is rarely of any use to the application
writer, and should probably be left to users as a way for them to use
when adding their own resource specifications.

4. Option Classes

Each option, in addition to its name, has a class so that related
options can be referred to by a single entry in the database.  The
class of an option is usually the same as the name of the option,
except with the first letter capitalised as well.  Note that this is
not always true (particularly for less common options,) and that you
should look up the option in the appropriate manual page if you are
not sure.

e.g.  To set all the background-related options for .foo.bar, you
could use a database entry like this:

  spong.foo.bar.Background: white

5. Wildcards in Paths

It quickly becomes very tedious to write the full path to a widget
whenever you want to specify an option using the database, and quite
often you want to refer to widgets that are at an uncertain depth.
By using the wildcard, *, for a section of the path, you can make a
database entry that refers to the options of many widgets at once.

This is particularly useful when used at the beginning of the path, as
it can also match any application name, so allowing for the case when
a user starts up the application twice and Tk is forced to choose a
different name for the app.

The following sets the background-related options for all buttons to
be white.  If used in a system-wide resource database, this will be
applied across all applications (and may well be recognised by non-Tk
applications.)  It is perfectly safe if used in the context of
something loaded into the application's database using [option add] or
[option readfile]

  *Button.Background: white

Obviously, you cannot use a wildcard for a particular option name
since there is no value that is universally accepted for all options,
and wildcards have no meaning in the context of values.

6. Option Priorities

Tk manages options according to their priority, taking the most
recently encountered option at the highest priority where something
can be found to match.  There are five primary priority levels.  From
lowest to highest, they are:

  widgetDefault
     The hard-coded default for the particular option.  It is only
     useful to set something at this level when you are writing a
     megawidget, as everything else overrides it.

  startupFile
     This level should be used by application writers when reading
     application-level option database entries.  More on this later.

  userDefault
     This level should be used by application writers when reading in
     per-user option database entries.  The system-wide options in the
     user's .Xdefaults file and attached to the user's display are
     loaded at this level.

  interactive
     This level should be used for all entries made because of user
     actions (e.g. because of what a user does in a configuration
     management dialog.)  This is the default level for the [option]
     command to work at.

  "programmed"
     This is not a conventional level, but rather the pseudo-level
     that all options that are specified as part of a widget configure
     subcommand are introduced at.  Anything introduced by this route
     will override all entries in the option database for the
     particular option and widget, though it will have no truly
     persistent effect, and if you destroyed and recreated the widget,
     the effects of this setting would be lost.

For more information, see the option(n) manual page.

7. Setting Up the Option Database

It is generally the case that it is a good thing that users should be
able to configure the way that their applications look.  Doing this
with Tk is relatively easy, provided an application defaults file is
used.  Otherwise, it can be very tricky.

When creating an application defaults file, you should make all
specifications of the look of a widget via that file.  Thus, things
like the border width, relief, cursor, foreground and background of
the widgets can be usefully defined via this route.  The easiest place
to create the file is in the same directory as the Tcl script that
loads the app-def file, so you can load it using a command like:

  option readfile [file join [file dirname [info script]] myapp.def] startup

If you then add another command to load a user's app-def file, like:

  catch {option readfile [file join ~ myapp.def] user}

it becomes easy for a user to override any of the settings in the
application's defaults.

8. Introducing Your Own Options

It is easy to add your own options to a widget.[***]  To do this, make
it so that every time you need to option the value, you perform an
[option get] command.  This requires three arguments:
   The pathname of the widget, so it knows where in the (virtual) tree
     to look for the option.  Note that the widget _must_ exist before
     you perform the lookup.  This can be real a P.I.T.A
   The name of the option.  You probably ought to make sure that this
     doesn't overlap with any of the standard option names, or the
     effects could well be undefined.
   The class of the option.  This can quite frequently be shared with
     a standard option, and usually ought to reflect the sort of value
     that can be used with the option.  Thus, if you accept fonts in
     that option value, you are recommended to use the class Font in
     the [option get] command.

It is acceptable to only read the option database once, when the
widget being used as the pathname is created.

9. Problems and Caveats

Some things cannot be specified by defaults files (notably the -class
option to some widgets) and some probably should not be specified by
defaults files (particularly those options that affect the behaviour
of the interface, like -command, -variable, -xscrollcommand, etc.) as
otherwise the interface can end up completely non-functional.  Often
those options are only usefully set in the context of part of the
application anyway.

Furthermore, some things cannot be specified by options (layout
options for pack and grid, or the items on a menu) even though it
would be useful to do so.  You can work around this, but it is not
especially easy.

To make things worse, some window/session managers (notably Mwm/CDE)
set "useful" options like *Background, which can make life rather
interesting.  I've had problems with debugging the interface of an
application from user reports because of this.

Note that there is no automatic update of existing widgets when the
database is modified.  If you want this, you will need to implement it
yourself.

There are probably more problems involved with the option database,
but that is all I can think of right now...  :^)

10. Copyright, etc.

Copyright (c) 1997 Donal K. Fellows.  Permission to distribute this
message via USENET is granted, but all commercial use is forbidden.
If you want to use this message commercially, please contact the
author.

[* This also occurs after an [option clear] operation.]
[** The linkage between the name of . and the value returned by
    [winfo name .] can be broken by the [tk appname] command. ]
[*** This is only from the point-of-view of the option database.
     Adding them from the PoV of the configure command is a business
     for megawidgets only. ]
---
Donal.
-- 
Donal K. Fellows   http://r8h.cs.man.ac.uk:8000/    Boing!  Boing!  Boing!
fellowsd@cs.man.ac.uk  Dept. Comp. Sci, Univ. Manchester, U.K. +44-161-275-6137
--
I have a really good anti-spam mail filter in use.  Don't bother spamming me...


