[Back to TkGoodStuff] Writing TkGoodStuff Clients

Writing TkGoodStuff Clients

Table of Contents (this document)

General Information

Clients are housed in files with the extension ".tcl". They might do anything at all, though what I envision clients mainly doing is producing buttons or displays and running and scheduling tasks.

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 arguments
The name is an arbitrary name for the window (containing only characters suitable for variables). The other arguments are all optional:
  • -image tkimage
    The value must be an already-created tk image. The button will display the image.
  • -text textstring
    The button will display the text indicated.
  • -unixcmd command
    The button, when pressed, will lauch the indicated unix command. Regular Tcl substitution is performed on the command string at execution.
  • -tclcmd command
    The button, when pressed, will perform the indicated tcl command. Regular Tcl substitution is performed on the command string at execution.
  • -imageside left, right, top, or bottom
    This sets the side of the button taken by the icon, when your button has both an icon and text. "top" by default.
  • -staydown 1 or 0
    If 1 (and by default), the button will stay down and inoperative after you press it until the launched unix command terminates. This is so you can see that you're already running that command. If 0, the button pops back up after launching the command, ready to launch the command again.
  • -state active or normal
    The button goes into the active state automatically when the mouse pointer enters, and into the normal state when it leaves. The state affects the button's colors (see the "mode" switch).
  • -mode mode
    Each mode for a button is associated with four colors: foreground, background, activeforeground, and activebackground. Switching modes is the way to change all the button's colors at once. By default a button is in the "normal" mode. For instance, Biff defines "nomail" and "newmail" modes, and Net defines "netup", "netdn", and "netwt" modes.
  • -foreground(mode) color
    -background(mode) color
    -activeforeground(mode) color
    -activebackground(mode) color
    These set the colors for that the button will have when it is in the indicated mode.
  • The parameters of the button are stored in a global array. If the name is "BarBar", the pathname of the created window will be stored in the global variable BarBar-params(window), the text is stored in BarBar-params(text) (in fact this is the "textvariable" for the button; setting it changes the button text directly), and so on.

    create-label-box

    A "label box" is a window with text on its face. The arguments are as follows:
    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

    adds a cascade menu entry in the main popup menu. It is invoked as follows:
    TKGPopupAddClient clientname
    Suppose 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.

    TKGPopupAdd

    adds an item to the main popup menu at the end of the client-added section. The arguments are any arguments that would come after ".menuname add" in a normal addition of an item to a menu.

    TKG_async_map

    tkgoodstuff maintains an internal counter (the global variable TKGcounter) that ticks off seconds (not very accurately, because of intervening processing) since program invocation. It also maintains a list of periodic tasks to accomplish, in the array TKG_async_map. Each element of the array (with any arbitrary name) is a list of three items:

    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

    ColorConfig pathname foregroundcolor backgroundcolor
    This 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

    RecursiveBind pathname sequence command
    This command binds the sequence to the indicated command in the window whose pathname you indicate as well as in all of its descendants.

    setifunset

    setifunset variable value
    This 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

    SetImage name filname
    This command creates an image named name, reading it from the file filename, and returns the image type (e.g., "bitmap", "photo").

    DEBUG

    DEBUG string
    This command writes the string to the internal log, and, if TKGLogging is 1, also to the log file.

    [Back to TkGoodStuff]

    Sep 14, 1995. Mark Crimmins markcrim@umich.edu