The jcommand.tcl library is distributed as part of the jstools package.
This document describes jcommand.tcl version 1998.09.30.
(Currently, I don't think the library actually enforces any constraints on the procedure name, but the format above (app:cmd:cmnd) is what I use, and (1) I'm not completely certain I'm not assuming those kinds of names anywere and (2) I'm not completely certain I'll never assume those kinds of names in the future.)
The argument w is a window name, intended to identify the document the command is intended to apply to in multidocument applications. It's required even if your application only supports one toplevel window; you can just invoke your commands with `.' as the value of w and ignore it in your procedure definitions if that's the case. Sometimes you (the programmer) provide the value of w - for instance, when you define a menu of command procedures, you can specify the window they apply to. Sometimes the value of w is less constrained - for instance, users can invoke command procedures with keyboard accelerators, in which case the name of the widget the accelerator binding was invoked for is provided as w. Depending how complicated your user interface is, and what widgets keyboard accelerators are active in, this may mean that your command procedures need to translate widget names to document names.
The special argument keyword args should be included in case you want your command procedure to interact with the jbindtext.tcl and jbindentry.tcl libraries which support editor emulation. They call procedures with additional arguments (which your command procedures can generally ignore) after the widget name. For instance, the jedit application defines both Control-s in the emacs-normal map and slash (/) in the vi-command map as the command procedure jedit:cmd:find_forward, so that Emacs users and vi users can use their familiar keystrokes to search for text. (Actually, please include it even if you don't intend to make your command procedures available this way, since future versions of the library may require it.)
##################################################
# jdoc:cmd:save_as - save to a file
##################################################
j:command:register jdoc:cmd:save_as {Save As...}
proc jdoc:cmd:save_as { w args } {
j:tc:saveas $w
}
##################################################
# jdoc:cmd:quit - quit
##################################################
j:command:register jdoc:cmd:quit {Quit}
proc jdoc:cmd:quit { w args } {
if [j:confirm -text "Are you sure you want to quit?"] {
exit 0
}
}
(Notice that
jdoc:cmd:quit ignores its window argument.)
The following procedure would create a new `File' menubutton $mb with two menu entries which would invoke the above two prodedures on the window w:
proc jdoc:mkmenu:file { mb w } {
j:menu:menubutton $mb $mb.m {File}
pack $mb -side left
j:menu:commands $mb.m $w {
jdoc:cmd:save_as
jdoc:cmd:quit
}
By default (i.e. if there is no language database), the menubutton
will be labelled `File' and the menu entries will be labelled
`Save As...' and `Quit'. If you provide a language database,
though, you can also provide
Alt-key equivalents and other keyboard accelerators. For instance,
if the active language database contained
j:ldb:set_strings {
{jdoc:cmd:save_as \
{Sauvegarder comme...} 0 <Control-Key-s> {^S}}
{jdoc:cmd:quit {Quitter} 0 <Key-F3> {F3}}
{File Fichier 0}
}
then the labels would be in French (or my pathetic attempt at
it, anyway :-), and the first character of each label would be
underlined for
Alt-key menu traversal. The strings `^S' and `F3' will be displayed
to the left of the appropriate menu entries, but this by itself
isn't quite enough to define keyboard accelerators. However,
if the application executes the command
j:command:bind .t .t [j:command:list]
then keyboard accelerator bindings will be defined for all registered
commands. The accelerators will be active when widget
.t had the focus and they will also act on widget
.t (i.e., they will invoke command procedures with
.t appended as an argument).
The net result of this is that cmd will be included in the list that j:command:list returns, which provides a list of the valid user commands in the application, and that if defaultname is given, cmd is guaranteed to be a valid entry in the naturallanguage database, and will produce defaultname if there's no entry for cmd in a loaded database file.
See j:command:list for a discussion of exactly where in your code you should register commands.
You may need to be careful that all the commands in your application have been registered at the time you call j:command:list. If you autoload command procedures and include the j:command:register invocation in the library file where the procedure is defined, if the file hasn't been autoloaded when you invoke j:command:list, it won't be included in the result.
One way around this is to put all your j:command:register invocations in initialisation code called near the beginning of your application; however, this may increase the likelihood that you'll forget to register a new command you add.
Another alternative is to include a dummy procedure (that doesn't do anything) in each library file that contain command procedures, and call that in your initialisation code; that will force the file to be autoloaded (at the cost of slower startup time, which defeats some of the purpose of library files).
(Because the key is looked up using j:ldb:short, whereas strings in menus are typically looked up using j:ldb, it's easy, although not necessary, to have different strings displayed for the same command on buttons and in menus.)
The pathname b of the button created is returned.
The button will be at least eight characters wide, even if the text corresponding to key is shorter than that. This is intended to provide some visual consistency to buttons with short labels. (Of course, you should be aware when designing your layout that the length of the text displayed in a button will vary from language to language, so you can't count on predicting the width of the button created.)
The perhaps odd order of the arguments to j:command:button, with the argument to cmd preceding cmd itself, is intended to be consistent with the order of arguments to j:command:menuentries, where the list of commands is last because there may be many of them.
Each button will be labelled with the text corresponding to cmd in the naturallanguage database. The buttons will be created from right to left, and each button will be at least eight characters wide (for visual consistency). The button corresponding to the command default (if any) will be surrounded with a sunken rectangle.
If given, padx and pady specify the space to add around the edges of the group of buttons. The default is to add five pixels around the group of buttons. These options do not affect the spacing between buttons..
If -orient vertical is specified, the buttons will be laid out vertically (starting at the botton), rather than horizontally.
You may find j:default_button (in jtkutils.tcl) useful with j:command:buttonbar, since no bindings are automatically set up to invoke the default button.
The first example above is typical; if you use j:command:register to register the commands in your application, you can use j:command:list later to get a list of all of them. However, you can also specify a list of command procedures explicitly, as in the second example. You might want to do that, for instance, if your application has two windows and you want all the bindings in effect in one of them, but only a subset in the other.
* There should be a way to ask j:command:button to underline a character or display an accelerator.
* There should be a way to tell
j:command:button not to enforce a minimum width, and there should also be a
way to force an explicit width.