# Writing TkGoodStuff Clients

## Table of Contents (this document)

- General Information
- Basic Client Interface

- TKGButton
- TKGMakeButton
- TKGLabelBox
- TKGGrid
- Adding to the Popup Menu
- TKGPeriodic

- Other Utilities

- TKGDialog
- TKGDeclare
- SetImage
- DEBUG

## General Information

Clients are housed in files with the extension ".tcl". They might do anything at all, though what they in fact mainly do is to produce buttons or displays and to run and to schedule tasks. Clients can be very complex (like the Jots client, which is a notecard manager), or very simple.

There is a commented example of a very simple button-producing client called "Example" in the file tcl/Example.tcl in the tkgoodstuff library directory. You might start with it.

This document is not as complete as it should be, but I think it's at least mostly correct, and hopefully it's better than nothing. Still, your best bet may be to look at the actual code for various clients.

## Basic Client Interface

Let's assume you are writing a client named "Foo". Your Foo.tcl file is "sourced" by tkgoodstuff when it reads the configuration file (or when Foo is added in the preferences manager). If you have defined a procedure "FooDoOnLoad", it is called then, as is "FooDeclare", if it exists ("FooDeclare" is called also when Foo is added in the preferences manager). "FooDeclare" should contain all your calls to TKGDeclare (for declaring preferences items). TKGDeclare is described below.

When the panel is being drawn (or redrawn following, e.g., a screen-edge move), the procedure "FooCreateWindow" is called if it exists. Ordinarily "FooCreateWindow" will make a call to TKGMakeButton or TKGLabelBox to produce a button or display window in the panel at the appropriate place. After all panels have been drawn, the procedure "FooStart", if it exists, will be called. During a screenedge move, the procedure "FooSuspend" will be called, if it exists, the client window will be ungridded, and then when the panel is redrawn "FooCreateWindow" and "FooStart" will be called.

### TKGButton

A "tkgbutton" is a button with either text, an icon, or both on its face. This command can be used either to create a button (but see TKGMakeButton) or to configure an existing button. If TKGButton is used to create a button, the button is not placed in the tkgoodstuff panel until TKGGrid is invoked. 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 (most also take "modified" forms; see the "-mode" switch for more about this):

- -pathname pathname
  This switch is used when creating the button (but see also TKGMakeButton, which is the easier way to make a TKGButton for inclusion in the tkgoodstuff panel). The value must be a tk pathname.
- -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.
- -font (standard font specifier)
  The button will display text (if any) using this font.
- -exec command
  The button, when pressed, will lauch the indicated unix command. Regular Tcl substitution is performed on the command string at execution.
- -command command
  The button, when pressed, will perform the indicated tcl command. Regular Tcl substitution is performed on the command string at execution.
- -menu menu
  The button will be a tkgmenubutton, and produce the indicated menu. No "exec" or "command" will be performed.
- -iconside left, right, top, bottom, or background
  This sets the side of the button taken by the icon, when your button has both an icon and text ("top" by default). If "background", then the text is written over the icon.
- -staydown 1 or 0
  If 1 (which is the 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.
- -usebutton2 1 or 0
  If 1 (which is the default), mouse button 2 will execute the button's unix command, if any, whether the button is up or down, and whether or not the unix command is already running.
- -windowname name
  This affects what happens when you press an already-depressed unix command button if you are running tkgoodstuff as an fvwm module. By default you move to the next window that is named by the name of the unix command of the button. But this switch allows you to look for an alternative window name (for instance, the program tkman names its window "TkMan", netscape "Netscape" and so on).
- -font font
  The font to use for text on the button
- -ignore 1 or 0
  If 1 (0 is the default), we will ignore the global iconsonly and labelsonly variables.
- -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 also the "mode" switch). This is useful to call manually primarily when you pack a child window in a button (as in the Load client) and want to set its colors.
- -foreground color
  -background color
  -activeforeground color
  -activebackground color
  These set the colors for the button.
- -padding (any number)
  The number of pixels of empty space to put around icons and labels in buttons.
- -mode mode
  Switches the button to the indicated mode. Each mode for a button is associated with values for text, image, exec, command, font, staydown, windowname, and four colors: foreground, background, activeforeground, and activebackground. Switching modes is the way to change a button's appearance and/or function dramatically with a simple command. 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.

To set values for a mode, use modified switches like the following:

         TKGButton Talk -foreground(notalk) red \
             -exec(notalk) {mesg y}

(Unmodified switches set the values for the current 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 current mode in BarBar-params(mode). Mode-sensitive parameters are stored as follows: e.g., the text is stored in BarBar-params(text,normal) (supposing the button is in the normal mode, as it is by default). (In fact this is the "textvariable" for the button; setting it changes the button text directly.) There are no "unmodified" parameters for mode-sensitive parameters. For instance BarBar-params(text) does not exist.

TKGButton is a wrapper around the widget commands "tkgbutton" and "tkgmenubutton"(part of libtkg).

### TKGMakeButton

    TKGMakeButton name . . .

Creates the indicated button, assigns it an approriate pathname, and packs it into the tkgoodstuff panel (at the position appropriate to the current stacking context). If the name is "Foo", the pathname is stored in the variable Foo-params(pathname). Takes the same arguments as TKGButton (which it calls, in fact), except that it is silly to give a "-pathname" switch to TKGMakeButton.

### TKGLabelBox

Creates a "label box" is a window with text on its face. The arguments are as follows:

    TKGLabelBox name [-label "label text"]

(The square braces indicate that the argument is optional. If no label text is supplied, you get an empty frame, which is what Clock and Load use.)

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 text is a text string that will be displayed in the window. The window containing (just) this text has the pathname BarBar_window.label.msg. The textvariable for the label is BarBar-lbparams(text)

### TKGGrid

    TKGGrid pathname

Packs the indicated window into the current tkgoodstuff panel (at the position appropriate to the current stacking context).

### 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.

### TKGPeriodic

You can schedule a Tcl command for periodic execution as follows:

    TKGPeriodic name period offset command

- The name is an arbitrary name.
- The period is the interval (in seconds) between executions of the periodic command.
- The offset is the delay (in seconds) between invocation of the TKGPeriodic_command and the first execution of this periodic command.
- The command is the command to execute at theat interval after that offset.

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 and other periodic processes. If you have to do something time-consuming, you should exec a shell script in the background with bgexec (see the BLT documentation) and trace the bgexec variable to get its output (for an example see Ical_fetch in Ical.tcl).

To cancel a scheduled periodic command, use:

    TKGPeriodicCancel name

This will cancel any command that was scheduled by the same name with TKGPeriodic.

## 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.

### TKGNotice

    TKGNotice "Notice text."

Posts a simple notice dialog with a dismiss button.

### TKGError

    TKGError "Error text." ?exit?

Posts an error dialog with a dismiss button, a stack-trace button, and a preferences manager button. If "exit" is present, tkgoodstuff will be suspended and will exit when dismissed.

### 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.

### TKGDeclare

    TKGDeclare variable value [-typelist {type1 type2 ...}] \
            [-vartype boolean/radio/optionMenu/text/entry] \
            [-textsize WxH] \
            [-radiolist {{"Label 1" value1} {"Label 2" value2} ...}\
            [-optionlist {value1 value2 ...}]\
            [-label "Preferences Manager Label text"] \
            [-help "Preferences Manager Help text"]

This command sets the indicated variable to value unless the variable already has a value (due, e.g., to the user's preferences settings), 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 the preferences manager.) The other switches govern how the variable is treated in the preferences manager.

### 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.