The clients written so far use a simple set of "client interface"
commands and standards. There is no reason a client has to do this
however, so long as it doesn't mess up the features of tkgoodstuff
that other clients rely on (such as window-naming and keeping track of
stacking stuff). If you want to do something different, your best bet
is to dig into the reasonably readable tkgoodstuff script itself.
Send me questions if you like.
Basic Client Interface
Let's assume you are writing a client named "Foo".
Your Foo.tcl file is sourced by the main tkgoodstuff program as it
executes the procedure "Client" invoked in the configuration file (it
is sourced uplevel 1 in that procedure, which is equivalent to
sourcing it at top level). Variables that you set outside of any
procedures are global.
tkgoodstuff insists that your client (assuming it is to be invoked by
"Client Foo") in the configuration file) have a procedure called
"create-Foo-window". This procedure is called (among a
sequence of such calls for all clients and user-defined buttons,
labels, and stacks) after the configuration file has been fully
sourced. You can do whatever you want in this procedure, but it is
called at just the right time to pack a window in the requested
position in the user's panel.
Two client-called procedures are provided for producing windows in the
panel: TKGButton and create-label-box.
TKGButton
A "TKGButton" is a button with either text, an icon, or both on
its face. The syntax is as follows:
TKGButton name argumentsThe name is an arbitrary name for the window (containing only characters suitable for variables). The other arguments are all optional:
create-label-box name label [ labelvarlist ](The square braces indicate that the argument is optional.)
The name is an arbitrary name for the window (containing only characters suitable for variables). If the name is "BarBar", the pathname of the created window will be stored in the global variable BarBar_window.
The label is a text string that will be displayed as the last (bottom) label in the window (others might be requested with the labelvarlist argument). The window containing (just) this text has the pathname BarBar_window.plate.barbar-main-label.msg.
The labelvarlist, if specified, is a list of
(all-lowercase) variables. For each variable (in order from the top
of the window) a label is created in the window with the text that is
the value of that variable. If the variable "foobar" is in the list,
the window containing (just) the text assigned to it has the pathname
BarBar_window.plate.foobar.msg.
StartStack
The StartStack command creates a frame (which may have a ridge border
and a special color), into which new tkgoodstuff elements (stacks,
buttons, labels, etc.) will be packed in a certain direction (either
from the top or from the left). Don't confuse this with the
"SubStack" configuration file command---SubStack tells tkgoodstuff
where in the process of packing all the windows it should execute
StartStack.
None of the provided clients uses StartStack and FinishStack, but
there's no reason not to---why not have a client with a group of
buttons and/or labels? You would invoke it within your
create-Foo-window procedure.
StartStack is invoked as follows:
Startstack [ orientation ] [ borderwidth ] [ color ]All of the arguments are optional.
The orientation can be either "vertical" (the default) or "horizontal".
The borderwidth can be any number (0 is the default), and
the color can be any standard color specification.
The pathname of the current stack always resides in the global
variable TKG_stackprefix, and its orientation (coded as "top" or
"left") is in the global variable CurrentSide.
FinishStack
The FinishStack command closes the current stack frame,
packs it into its parent stack frame, which now becomes the current stack.
Adding to the Popup Menu
Two commands are provided for adding to the popup menu:
TKGPopupAddClient clientnameSuppose your clientname is FooBar. Then, this command generates a cascade menu entry labelled "FOOBAR:", and a corresponding (empty) menu with the pathname .tkgpopup.foobar, which is the menu to which you should add items in your client code.
You should try not to do anything periodically in this way that will
take a lot of time to finish processing (e.g., don't have a
periodically-called procedure wait for something before returning),
since this will screw up the user interface
responsiveness. If you have to do something time-consuming, you might
exec a shell script in the background and look periodically for its
output in a file (for examples see Ical_list_items and Ical_fetch
in Ical.tcl). (I don't want to do the async things in a separate wish
process with "send"---which would be easy enough to do---both because
of the system resource usage and because I dread the complaints and
questions about X security. I know there are extensions to Tcl which
let us spawn processes, but I want to stick with the basics.)
Other Utilities
TKGDialog
TKGDialog name [ -wmtitle string ] [ -title string ] \ [-image imagefilename] [-message string] [-text string] \ [-titlebg color] [-titlefg color] [-bitmapfg color] \ [-buttons buttonlist] [-nodismiss]All the options in brackets are optional. This command pops up a dialog box with pathname ".name". The -wmtitle string is what will be put in the window manager title bar. The -title string is put in the dialog box title frame (up top, in a large font). The icon from the file named by the -imagefilename identifier is also put in the title frame. The -message string is put in a framed message widget under the title frame, if any. The -text widget is put in a scrollable text widget under the title frame, if any (and message frame, if any). The color options are as follows: -titlebg is the background of the title frame; -titlefg is the foreground of the title string; and -bitmapfg is the foreground color of the icon (if it is a bitmap; otherwise this switch does nothing). The button list is a list of button items, where a button item is a list of three items: a (lowercase) name for the button (the button's pathname will be ".name.buttons.buttonname"), a string of text to put on the button, and the command that the button will execute when pressed (usually this should include "destroy .name"). Unless you include the argument "-nodismiss", there will also be a button labelled "Dismiss" which destroys the dialog. The buttons are placed at the bottom of the dialog, left to right in the order of your list, with the default "Dismiss" button at the right.
ColorConfig pathname foregroundcolor backgroundcolorThis command sets the foreground and background colors of the window whose pathname you indicate, as well as the colors of its descendants, to the colors you name. Using "-" in place of the name of a color leaves that feature unchanged.
RecursiveBind pathname sequence commandThis command binds the sequence to the indicated command in the window whose pathname you indicate as well as in all of its descendants.
setifunset variable valueThis command sets the indicated variable to value unless the variable already has a value, in which case that value is retained. (This is how a client should set those of its global variable that you want users to be able to set in their configuration files.)
SetImage name filnameThis command creates an image named name, reading it from the file filename, and returns the image type (e.g., "bitmap", "photo").
DEBUG stringThis command writes the string to the internal log, and, if TKGLogging is 1, also to the log file. Sep 14, 1995. Mark Crimmins markcrim@umich.edu