Top Up Prev Next Bottom Contents Index Search

5.2 Writing Tcl/Tk scripts for the TclScript star

Several of the domains in Ptolemy have a star called TclScript. This star provides the quickest and easiest path to a customized user interface. The icon can take any number of forms, including the following:

All of these icons refer to the same star, but each has been customized for a particular number of input and output ports. You should select the one you need on the basis of the number of input and output ports required. The left-most icon has an unspecified number of inputs and outputs (as indicated by the double arrows at its input and output ports).

The TclScript star has one parameter (settable state):


tcl_file
A string giving the full path name of a file containing a Tcl script
The Tcl script file specifies initialization commands, for example to open new windows on the screen, and may optionally define a procedure to be invoked by the star every time it runs. We begin with two examples that illustrate most of the key techniques needed to use this star:

Example 1: Consider the following simple schematic in the SDF domain:


The TkShowValues star is in the standard SDF star library. It displays whatever input values are supplied in a subpanel of the control panel for the system. Suppose we specify the following Tcl script for the TclScript star:


set s $ptkControlPanel.middle.button_$starID
if {! [winfo exists $s]} {
button $s -text "PUSH ME"
pack append $ptkControlPanel.middle $s {top}
bind $s <ButtonPress-1> "setOutputs_$starID 1.0"
bind $s <ButtonRelease-1> "setOutputs_$starID 0.0"
setOutputs_$starID 0.0
}
unset s
This script creates a pushbutton in the control panel. When the button is depressed, the star outputs the value 1.0. When the button is released, the star outputs value 0.0. The resulting control panel is shown below:

While the system is running, depressing the button labeled "PUSH ME" will cause the value displayed at the bottom to change from 0.0 to 1.0. Releasing the button will change the value back to 0.0. The lines in the Tcl script are explained below:

set s $ptkControlPanel.middle.button_$starID

This defines a Tcl variable "s" whose value is the name of the window to be used for the button. The first part of the name, $ptkControlPanel, is a global variable giving the name of the control panel window itself. This global variable has been set by pigi and can be used by any Tcl script. The second part, .middle, specifies that the button should appear in the subwindow named .middle of the control panel. The control panel, by default, has empty subwindows named .high, .middle, and .low. The last part, .button_$starID, gives a unique name to the button itself. The Tcl variable starID has been set by the TclScript star to a name that is guaranteed to be unique for each instance of the star. Using a unique name for the button permits multiple instances of the star in a schematic to create separate buttons in the control window without conflict.


if {! [winfo exists $s]} {
...
}
This conditionally checks to see whether or not the button already exists. If, for example, the system is being run a second time, then there is no need to create the button a second time. In fact, an attempt to do so will generate an error message. If the button does not already exist, then it is created by the following lines:


button $s -text "PUSH ME"
pack append $ptkControlPanel.middle $s {top}
The first of these defines the button, and the second packs it into the control panel (see the Tk documentation). The following Tcl statement binds a particular command to a mouse action, thus defining the response when the button is pushed:

bind $s <ButtonPress-1> "setOutputs_$starID 1.0"
When button number 1 of the mouse is pressed, the Tcl interpreter invokes a procedure named setOutputs_$starID with a single argument, 1.0 (passed as a string). This procedure has been defined by the TclScript star. It sets the value(s) of the outputs of the star. In this case, there is only one output, so there is only one argument. The next statement defines the action when the button is released:


bind $s <ButtonRelease-1> "setOutputs_$starID 0.0"
The next statement initializes the output of the star to value 0.0:


setOutputs_$starID 0.0
The last command unsets the variable s, since it is no longer needed:


unset s

As illustrated in the previous example, a number of procedures and global variables will have been defined for use by the Tcl script by the time it is sourced. These enable the script to modify the control panel, define unique window names, and set initial output values for the star. Much of the complexity in the above example is due to the need to use unique names for each star instance that sources this script. In the above example, the Tcl procedure for setting the output values has a name unique to this star. Moreover, the name of the button in the control panel has to be unique to handle the case when more than one TclScript star sources the same Tcl script. These unique names are constructed using a unique string defined by the star prior to sourcing the script. That string is made available to the Tcl script in the form of a global Tcl variable starID. The procedure used by the Tcl script to set output values is called
setOutputs_$starID. This procedure takes as many arguments as there are output ports. The argument list should contain a floating-point value for each output of the star.

In the above example, Tcl code is executed when the Tcl script is sourced. This occurs during the setup phase of the execution of the star. After the setup phase, no Tcl code will be executed unless the user pushes the "PUSH ME" button. The command

bind $s <ButtonPress-1> "setOutputs_$starID 1.0" defines a Tcl command to be executed asynchronously. Notice that the command is enclosed in quotation marks, not braces. Tcl aficionados will recognize that this is necessary to ensure that the starID variable is evaluated when the command binding occurs (when the script is sourced), rather than when the command is executed. There is no guarantee that the variable will be set when the command is executed.

In the above example, no Tcl code is executed when the star fires. The following example shows how to define Tcl code to be executed each time the star fires, and also how to read the inputs of the star from Tcl.

Example 2: Consider the following schematic in the SDF domain:


Suppose we specify the following Tcl script for the TclScript star:


proc goTcl_$starID {starID} {
set inputVals [grabInputs_$starID]
set xin [lindex $inputVals 0]
set yin [lindex $inputVals 1]
setOutputs_$starID [expr $xin+$yin]
}
Unlike the previous example, this script does not define any code that runs when the script is sourced, during the setup phase of execution of the star. Instead, it simply defines a procedure with a name unique to the instance of the star. This procedure reads two input values, adds them, and writes the result to the output. Although this would be a very costly way to accomplish addition in Ptolemy, this example nonetheless illustrates an important point. If a Tcl script sourced by a TclScript star defines a procedure called goTcl_$starID, then that procedure will be invoked every time the star fires. The single argument passed to the procedure when it is called is the starID. In this example, the procedure uses grabInputs_$starID, defined by the TclScript star, to read the inputs. The current input values are returned by this procedure as a list, so the Tcl command lindex is used to index into the list. The final line adds the two inputs and sends the result to the output.

As shown in the previous example, if the Tcl script defines the optional Tcl procedure goTcl_$starID, then that procedure will be invoked every time the star fires. It takes one argument (the starID) and returns nothing. This procedure, therefore, allows for synchronous communication between the Ptolemy simulation and the Tcl code (it is synchronized to the firing of the star). If no goTcl_$starID procedure is defined, then communication is asynchronous (Tcl commands are invoked at arbitrary times, as specified when the script is read). For asynchronous operation, typically X events are bound to Tcl/Tk commands that read or write data to the star.

The inputs to the star can be of any type. The print() method of the particle is used to construct a string passed to Tcl. Although it is not illustrated in the above examples, asynchronous reads of the star inputs are also allowed.

Below is a summary of the Tcl procedures used when executing a TclScript star:

grabInputs_$starID
A procedure that returns the current values of the inputs of the star corresponding to the given starID. This procedure is defined by the TclScript star if and only if the instance of the star has at least one input port.
setOutputs_$starID
A procedure that takes one argument for each output of the TclScript star. The value becomes the new output value for the star. This procedure is defined by the TclScript star if and only if the instance of the star has at least one output port.
goTcl_$starID If this procedure is defined in the Tcl script associated with an instance of the TclScript star, then it will be invoked every time the star fires.
wrapupTcl_$starID
If this procedure is defined in the Tcl script associated with an instance of the TclScript star, then it will be invoked every time the wrapup method of the star is invoked. In other words, it will be invoked when a simulation stops.
destructorTcl_$starID
If this procedure is defined in the Tcl script associated with an instance of the TclScript star, then it will be invoked when the destructor for the star is invoked. This can be used to destroy windows or to unset variables that will no longer be needed.
In addition to the starID global variable, the TclScript star makes other information available to the Tcl script. The mechanism used is to define an array with a name equal to the value of the starID variable. Tcl arrays are indexed by strings. Thus, not only is starID a global variable, but so is $starID. The value of the former is a unique string, while the value of the latter is an array. One of the entries in this array gives the number of inputs that are connected to the star. The value of the expression [set ${starID}(numInputs)] is an integer giving the number of inputs. The Tcl command "set", when given only one argument, returns the value of the variable whose name is given by that argument. The array entries are summarized below:

$starID This evaluates to a string that is different for every instance of the TclScript star. The starID global variable is set by the TclScript star.
[set ${starID}(numInputs)]
This evaluates to the number of inputs that are connected to the star.
[set ${starID}(numOutputs)]
This evaluates to the number of outputs that are connected to the star.
[set ${starID}(tcl_file)]
This evaluates to the name of the file containing the Tcl script associated with the star.
[set ${starID}(fullName)]
This evaluates to the full name of the star (which is of the form universe.galaxy.galaxy.star).


Top Up Prev Next Bottom Contents Index Search

Copyright © 1990-1997, University of California. All rights reserved.