Next: Tracker objects
Up: Function and Class
Previous: Remote connection objects
The following objects are used to implement the user interface modules
in VMD, including the text interface, the 2D mouse interface, the GUI
interface, and (eventually) the 3D interface.
Items which have a specific section listed for them are
explained in detail in that section.
Table 6.6: VMD
user interface objects.

This is a base class for all the objects used in VMD
to peform actions
(commands) on the molecules or program state. Each time a request is to
be made to do some command (i.e. rotate the current scene, load a new
molecule, change a color, etc), an instance of a class derived from
Command
is created, and given to a CommandQueue
object. The
queue will then call virtual routines within Command
to perform
the action it knows how to do. There are a large number of relatively
small classes derived from Command
, each one used to perform a
particular type of action. These objects are all in the files with names
starting with 'Cmd', for example CmdDisplay.h and .C.
Each class derived from Command
has these characteristics and abilities:
- A unique integer code, which must be one of the items in the
enumeration Cmdtype located at the top of the Command.h file.
The code for the particular subclass of Command
is passed to
the Command
constuctor, and available via the gettype()
function.
- The data necessary to perform the required action. This data must
be given to the object via the constructor when it is created.
- A textual equivalent of the command. This is created after the
object is instantiated, based on the particular data given to that
instance. This string is used to echo commands to the console or to
a file.
- The ability to perform the command itself. The virtual function
execute() is used to request the Command
object to do its
stuff.
The basic philosophy behind the use of Command
is that each action
that the user may possibly request to do should be encapsulated within
a class derived from Command
. Each subclass should know also how
to create a text equivalent of the command. User interface objects in
VMD
(those derived from UIObject
must use these Command
's
to do the actions requested by the user, by creating new Command
instances and giving them to a CommandQueue
object to execute.
- Command::(Cmdtype, int)
The first argument specifies the type code for the command, while the
second argument is the ID of the user interface object which created
this Command
instance (see section 6.6.7).
There is one large enumeration Cmdtype in Command
, which contains
a set of unique ID's for each derived class of Command
. This is done
as an enumeration here so that other objects in the program (notably
UIObject
s) .. can be written with explicit codes to allow them to
check what type of command they may be working with. When a new Command
object is being written, a new value must be added to this list.
- Cmdtype mytype -- unique code for this derived class.
- int textExists -- whether or not the text equivalent of this
command has been created yet. This only needs to be done at most once,
and sometimes not at all (if commands are not being logged to a file or
the screen, for example).
- int hasTextCmd -- whether or not this command even HAS a text
equivalent ... some commands do not, for example Event's.
- char cmdtextbuf[256] -- character buffer to hold the text
equivalent string. This can be at most 256 characters.
- ostrstream *cmdText -- character stream used to format the
text equivalent.
- virtual int do_execute(void) -- the `heart' of each class
derived from Command
. This function performs the required task
(if possible), and returns TRUE if successful, FALSE if there is an error.
When errors occur, messages should be printed to msgErr in this
function, and preferrably NOT within the lower-level objects (i.e. the
Molecule
or DisplayDevice
objects).
- virtual void create_text(void) -- formats the text equivalent
of the command, writing the text to the cmdText stream.
Whenever an action is to be performed,
you create a new instance of the particular Command
derivative with
a `new' operation:
Command* cmd = new CmdTranslate(x, y, z, 0);
Then, the command is queued, by adding it to a CommandQueue
object,
by appending it to the queue:
commandQueue->append(cmd);
When doing this in a UIObject
, there is a member function
addcommand(Command *) to do this more easily.
Once queued, the command will be executed during the main event loop in VMD
,
and then the instance will be deleted after it is done executing. Do NOT
queue a static Command
object, it must have been created using new.
(But see the description of the runcommand function in
CommandQueue
, section 6.6.2.)
The following
`checklist' should be followed when creating a new type of command:
- Identify the `type' of command ... to affect the display, the
molecules, the on-screen forms, or whatever. There are several Cmd*
files, find one where it belongs, or create a new one of the form
CmdXXXX.h and .C
- Create a text equivalent of the commands. Text commands in VMD
\
consist of one or more words separated by whitespace, and terminated
by a newline. The first word of the command should be an `identifying'
word to indicate the general type of action to be performed, and the
other words should be arguments to describe exactly what action to do
in the general category.
- Put a new code in the Cmdtype enumeration in Command.h
- Create the class definition in CmdXXXX.h. The only functions that
are needed are the constructor/destructor, and the virtual functions
do_execute and create_text. If the command does not have
a text equivalent, you do not need to provide a version of the latter.
- Put the member functions in the file CmdXXXX.C. The easiest thing
to do is to follow the patters in the Cmd*.C files.
- All commands must be understood by the text parser ( UIText
).
The parser reads in new commands, looks at the first word, and calls
a text callback function to process that command. If the new command
is just a variant of another existing command (i.e. the first word of this
new command is the same as some existing command), then it should be put
in an existing Cmd* file, and the function 'text_cmd_WWWW' at the top
of the respective .C file (where WWWW is the first word of the command)
should be updated to understand the new command. Add code to look for
the proper strings, to create a new instance of the new command, and to
add it to the given CommandQueue
. If this command contains instead
a new word for the VMD
vocabulary, go on the next step, otherwise the
next step can be skipped.
- For commands which contain a new starting word, so that they are
placed in new files CmdXXXX.h and .C, two things must be done to allow
VMD
to be aware of the text versions of these commands and to be able
to execute them:
- At the beginning of CmdXXX.h and .C, a new function
`text_cmd_WWWW(int argc, char **argv, CommandQueue *cq, int id)'
must be defined and written. This routine must know how to examine
the text command (as provided in token form in argc and argv) and
create instances of the proper Command
object to be added to
the command queue. Other Cmd* files contain examples.
- In the file UIText.C, there is a section where all the words
that are at the beginning of VMD
commands are `registered', with
the callback function to call when that word is seen. Add a line
similar to the others in this section, to register the new word and
to specify the new function `text_cmd_WWWW'.
- If other user interfaces (other than the text interface) are to
have the ability to execute this same command, add this ability to them
as well.
- Finally, update the on-line help file vmd_help.html, and
the User's Guide.
The printing of error message is right now very uneven. Some commands do
so in the do_execute routine, others leave it to the objects being
operated upon to do the error message printing. It would be best if all
error messages were printed (if possible) in do_execute routines,
with the underlying objects just returning error codes to allow
do_execute to tell what is going wrong.

CommandQueue
maintains a queue of Command
's, and will
go through this queue and execute them when requested. The queue is
first-in first-out. This object also has the ability to log commands
to a file.
There is one global instance of this class in VMD
, called commandQueue.
It is used by all the user interface objects ( UIObject
classes).
Each time a new action is requested by the user or some other part of
VMD
, a new Command
instance is created and added to the
CommandQueue
. Within the main event loop of VMD
, after each
UIObject
is checked for new events, the commands in the queue are
all executed until the queue is empty (since the execution of one command
may result in the queuing of a new command, this process continues until
the queue is empty). Each time the queue is checked, the following
occurs:
- The next Command
instance at the top of the queue is
fetched to be executed.
- If commands are being logged to a file, the text representation
of the command is written to that file.
- The command itself is executed, and the return code (success of
the command) is stored.
- After it is executed, each UIObject
active at that time
(which are stored in the UIList
object) are informed about the
command, and are given both the pointer to the command, and it's
success flag. This is done so that user interfaces can update their
visual display or internal state to reflect the fact that something
has changed. In this way, even though a single user interface
component may do some action, ALL user interface's can know when
to update their state to reflect the changes in the program.
- After this, the Command
instance is deleted. There is
one routine which does this differently, `runcommand' (see below).
- ResizeArray<Command *> cmdlist -- the queue of commands.
- int loggingCmds -- flag indicating whether commands are
being logged to a file.
- FILE *logfile -- pointer to the FILE strcture for the output
log file, if one is being used.
- UIList *uil -- the list of user interface objects to inform
when a command is executed.
- int do_execute(Command *) -- executes the given command,
echoing it to the log file if necessary and informing all the
UIObject
s. This will NOT delete the Command
; this routine
is called by other routines in CommandQueue
.
- void delete_current(void) -- deletes the command which
is at the top of the queue, and moves all the other commands up. This
is called by `execute' after the command has been run.
- int logging(void) -- return TRUE if logging of commands
is turned on.
- void log_on(char *) -- turns on logging of commands, to the
given file.
- void log_off(void) -- turns off logging, closes the open
log file if necessary.
- int num(void) -- return number of commands in the queue.
- int append(Command *) -- puts the given command instance
at the end of the queue. This will not execute it; commands are not
executed until one of the following three routines are called. This
returns TRUE if the command could be added.
- int execute(UIList *UIL = NULL) -- executes just the first
command in the queue, by calling do_execute and then
delete_command. If a particular UIList
is given, that will
be used, otherwise the internal one will be used. This will definitel
delete the command when it is done. Returns the success code of the
command, or FALSE if not command is available.
- void execute_all(UIList *UIL = NULL) -- just calls
execute until the queue is empty.
- int runcommand(Command *) -- this routine executes the
given command, but without adding it to the queue. It should
be used when you definitely know that a command should be done
immediately, and can be done out-of-order with respect to the other
commands which might be in the queue. When the command is done,
it is deleted. This returns the success code of the command.
When objects other than UIObject
s wish to execute a command, they
should use the global object commandQueue, and append the
command:
commandQueue->append(new CmdReshape());
This command will not actually be run until the main event loop in VMD
\
is run. If a command needs to be executed immediately, use runcommand:
int success = commandQueue->runcommand(new CmdReshape());
When UIObject
s are adding commands, there are special funcions
in UIObject
to make this faster, `addcommand' and `runcommand'.
Each UIObject
is given a pointer to a CommandQueue
object,
and so the `addcommand' routine will take a command and add it to that
queue. For example, in UIText
there might be:
addcommand(new TextEvent("text command", id()));
Most commands have as their last argument an id code for the UIObject
which created them. This is that so UIObject
s can tell, when they
are told that the command has executed, who started it all.
There should be a version of runcommand that allows for executing a
command without 'new'ing it. At least, there should be an argument
to runcommand to allow this possibility.

The Mouse
class provides all the capabilities to provide a 2D
pointer for a particular DisplayDevice
. Mouse
will use
virtual functions with DisplayDevice
to determine when a mouse
button has been pressed, and where it is located. Based on this, the
Mouse
will rotate, translate, or scale the objects in the current
Scene
. It can also be used to `pick' items, by clicking one
of the mouse buttons while the cursor is positioned over the item.
Finally, it is used to activate and choose from a pop up menu.
Mouse
is derived from UIObject
, and is one of the main
user interface methods in VMD
(along with the text console, the GUI,
the 3D pointers, and any external command input programs).
It is assumed the Mouse
has three buttons, left, middle, and
right. The right button is always used to active the pop-up menu, while
the other two are used to apply transformations to the current
Scene
. The left and middle buttons are also used to select
items. For some things, you can only click on them (press button +
release) for something useful to happen. For other things, you can
select them (press button), pull them (move the mouse while the
button is held down), and release. The Mouse
will issue commands
to do the button presses, mouse motion, and button releases associated
with picking objects.
The Mouse
is always in one of several modes, which are
changed by various means (text commands, pop-up menu options, or
keyboard shortcuts). These modes are:
- Rotation mode: When held down, the left button will
rotate things about the X or Y axis as the mouse is moved, in a
`virtual trackball' method. The middle button is used to rotate
about the Z axis (perpendicular to the screen).
- Translation mode: The left button will move the objects
in the X-Y plane; the middle button will move things in the Z
direction (toward or away from the viewer).
- Scaling mode: The left button, when held down and the mouse
moved left-right, will enlarge or shrink the scene. The middle button
will do the same thing, but with a larger scaling factor (so the
left is for fine tuning, the middle is for coarse-grain scaling).
- Light mode: This acts just like rotation mode, but instead
of rotating all the displayed objects, the mouse will only rotate the
position of one of the light sources. When setting this mode, you also
select which light to rotate (0 ... 3).
- Pick mode: While the mouse can be used to select certain
items while it is in the other modes, there are certain special
pick-and-drag operations in VMD
which can only be done if the
pointer is put in a special picking mode. By default there
are five picking modes, which are numbered 0 ... N-1, in this order:
query, select atom, select bond, select angle, or select dihedral.
Picking on an object when in a non-picking mode does not allow you
move the mouse around any while the item is selected; in that case,
when the button is pressed, if an item is selected it acts just as
if the button were immediately released. But if the mouse is in a
special picking mode, then when the button is pressed and an item is
selected, you can move the mouse around while the button is held down
and have extra actions be taken during the motion. For example, there
are special modes which are used to add perturbative forces to atoms; to
to do this, the mouse must be placed in the atom-tug mode. When setting
the mouse into a pick mode, you also must select which mode it is to
be.
Note that clicking on an item with the left button while the mouse is NOT
in a pick mode is equivalent to clicking-and-releasing the button with
the mouse in the atom select mode. Clicking on an item with the middle
button in these same situations is the same as using the left button, but
instead the picking operation is done as if the mouse were in the bond
selection mode.
The Mouse
is also used to provide a customizable pop-up menu when
the third button is pressed. This menu contains selectable items,
separators, and submenus. There are several `standard' selections in the
popup menu, and there are text commands available which allow the user
to add their own submenus and pop-up menu items. Thus, the user can
customize their own user interface. There are Command
objects
which call routines within the Mouse
object to add these items.
The entire definition of the pop-up menu is contained within a member
object PopupMenu
. When the third button is pressed, the definition
of this pop-up menu is given to the DisplayDevice
specified in the
constructor of Mouse
(via virtual functions there for handling
pop-up menus), and the virtual function ni DisplayDevice
which activates
the pop-up menu is called to allow an item to be selected.
Finally, the Mouse
contains the ability to check the keyboard for
special events as well as the 2D pointing device. The Mouse
maintains
a list of user-customizable keyboard shortcuts, which associate a
specific keypress (i.e. 'A' or 'r') with a text command. When that key is
pressed while the Mouse
is in the graphics display window, the
associated text command is executed as if the entire command had been entered
at the console prompt.
There is one global instance of the Mouse
class, mouse. It
is created after the global UIList
, DisplayDevice
, and
CommandQueue
objects are created. Note that if a `default'
DisplayDevice
is created, the Mouse
will not be able to check
for events, determine a pointer position, etc, and so will do nothing.
- Mouse::(UIList *, CommandQueue *, DisplayDevice *)
The first argument is the UIList
with which this object should
register itself; the second is the CommandQueue
object which this
class should use when creating new Command
s to be executed, and
the third argument is the DisplayDevice
which this class should
be a 2D pointer for. The DisplayDevice
must provide all the
device-specific information for the Mouse
, such as the X,Y
location of the pointer, the state of the mouse buttons, and the
ability to post and activate a pop-up menu.
The MoveMode enumeration lists the possible mouse modes. These are:
- ROTATION.
- TRANSLATION.
- SCALING.
- LIGHT.
- PICKING.
- DisplayDevice *dispDev -- display to use for device-specific
functionality, such as checking for events, determining the pointer
position, etc.
- MoveMode moveMode -- current mode the mouse is in.
- int activePickMode -- if the current mode is PICKING,
this variable indicates which pick mode is active.
- int pickInProgress -- if this is zero, no picking operation is
currently in progress (which means that it is NOT that case that a
mouse button has been pressed and selected something, with the mouse button
still left down). If something is currently being selected with the mouse
and the button is still down, this flag indicates which button is being
used. In fact, pickInProgress = pick-button + 1.
- int moveObj -- if the current mode is LIGHT, this
variable indicates which light to rotate.
- int currX, currY, oldX, oldY -- current and previous positions
of the pointer, measured in pixels from the lower-left corner of the
global display screen.
- float transInc, rotInc, scaleInc -- the amount of change to
apply each time a translation, rotation, or scaling operation is requested.
- float xRotVel, yRotVel, zRotVel -- current angular velocity
of the scene; when the system has angular velocity, even if no event is
generated by the Mouse
, the current scene will be rotated by the
angular velocity amount.
- PopupMenu *mouseMenu -- the object which contains the definition
of the pop-up menu which is activated when the third button is pressed.
- NameList<NameList<char *> *> userMenuList -- a list of
NameList
objects which hold the definitions of user menus. Each name
in userMenuList is the title of a submenu to be added to the main
pop-up menu, with an associated list of names which define the submenu.
This is used to store the user-defined pop-up menu commands.
- <NameList<char *> *mainUserMenu -- this is the one
user-controlled menu which is always added to the main menu. The user can
add two types of items to the main menu:
- Single commands, which are put into the mainUsermenu list.
- Submenu commands, which are put into a new submenu with a specified
name that is added to the main menu. This allows for grouping of related
commands under a separate submenu in the main menu.
- NameList<char *> userKeys -- in a manner very similar to adding
new menu items, the user can assocate keyboard shortcuts (or hotkeys)
with a specified text command. This list stores the keystrokes, and
the text commands associated with those keystrokes.
- int mouse_moved(int b1Down, int b2Down) -- performs the
necessary action when the mouse is moved while a button is pressed. The
arguments indicate which buttons are currently down.
- void create_popup_menu(void) -- goes through the definitions
of the pop-up menu, and creates a PopupMenu
object to store this
data in the proper order and format.
- void create_key_commands(void) -- creates the initial
list of keyboard shortcuts; this is only done when the Mouse
is
initialized.
- void stop_rotation(void) -- sets the current angular velocity
to zero.
- int x(void) -- returns the current x position of the
Mouse
, as measured from the lower-left corner. This just calls a
similar (but virtual) function in DisplayDevice
.
- int y(void) -- as as x(), but for the vertical position.
- int button_down(int) -- returns the current state of the
given button.
- int move_mode(MoveMode, int = 0) -- sets the current mouse
mode. If the new mode is PICKING or LIGHT, the second argument
must be given to indicate which picking mode or light. Otherwise, the
second argument is ignored.
- MoveMode curr_move_mode(void) -- returns current mode.
- char *move_mode_name(MoveMode) -- returns a string describing
the specified mode.
- int curr_pick_mode(void) -- returns current picking mode, or
-1 if the current mouse mode is not PICKING.
- int picking(void) -- returns TRUE if somthing is being
pickied, or FALSE otherwise.
- int create_user_menu(char *label) -- indicates that a new
user-customizable submenu should be added to the main menu, with the
given label. The new menu will be initially empty.
- int add_user_menu_item(char *text, char *txtcmd) -- adds
a new user menu item to the main user submenu ... the name in the menu will
be `text', and the command executed when that menu option is
chosen is `txtcmd'.
- int add_user_menu_separator(void) -- puts in a separator at the current end of the main user submenu.
- int add_user_submenu_item(char *submenu, char *text, char *txtcmd) -- adds the command `txtcmd' to the submenu `submenu', under the
name of `text' in that submenu.
- int add_user_submenu_separator(char *submenu) -- adds a
separator to the end of the given submenu.
- int add_user_key_command(char, const char *) -- adds a new
keyboard shortcut (or replaces a previous one), for the given key.
- virtual void reset(void) -- resets the user interface to the
initial state it was in when it was created.
- virtual int act_on_command(int, Commmand *, int) -- this is
called each time a Command
is executed that the Mouse
has
expressed interest in hearing about. This will be when a mouse event
occurs, such as a mouse button press.
- virtual int check_event(void) -- calls the necessary routines
in DisplayDevice
to determine if a button has been pressed. If not,
then any angular velocity is used to rotate the current scene.
Once it is created and given the proper CommandQueue
, UIList
,
and DisplayDevice
, Mouse
only needs to have its virtual
function check_event() called regularly. This is done in the main
event loop of VMD
, when the UIList
is told to have all its
UIObject
s check for events.
The Command
objects which have the word `user' as their first word
control the customization of the pop-up menu and keyboard shortcuts.
When a new DisplayDevice
is eventually developed to use X-Windows
and OpenGL, there will also need to be included routines there to post
and activate the pop-up menu and for all the virtual functions in
DisplayDevice
which the Mouse
uses. If this is done successfully
then Mouse
should be completely device-independent. It may be
necessary (or preferred) to convert to the use of a pull-down menu in
the X-Windows case.

PopupMenu
is used by the Mouse
class, and perhaps other
components. A PopupMenu
contains a list of elements, which are used
to create a menu of commands. There are two types of elements, `normal'
elements which consist of a name and an associated text command, and
`special' elements which modify the appearance or behavior of the menu.
Each element has these characteristics:
- Name (as it appears in the menu).
- Text command to execute when the item is selected (may be null).
- Return code: this is an integer code which is returned by the
windowing system when the item is picked. It is assigned by
PopupMenu
, and for all regular menu items, it is greater than 0.
There are several ``special'' return codes, which indicate the menu
item is not a normal menu . These special return codes include:
- MENU_CODE_SUBMENU: the menu item contains a submenu.
- MENU_CODE_SEP: the menu item is really a separator.
- MENU_CODE_NONE: the menu item cannot be selected, it just
exists to display text.
- A submenu object, if any (only if the return code indicates the
element contains a submenu).
- Flags to indicate if the menu item should be displayed, or if
it should be disabled (greyed out) if possible.
A PopupMenu
relies on a specific windowing system to provide the methods
for creating, posting, and activating a menu. It contains a list of
pop-up items, each item containing the
characteristics listed above. A menu is a list of these, and has a name
associated with the total list as well as with each item.
- PopupMenu::(char *)
The argument is the name of the menu. If this menu is used as a submenu
in another menu, this name will appear in the parent menu as the name of
the submenu.
The PopupCodes enumeration lists the possible ``special'' return codes
for the menu items. Items in a menu with a return code greater than zero
are items which when selected result in some command being executed. Items
in a menu with one of the following return codes (which are all
)
are special menu items:
- MENU_CODE_NONE: Indicates the item does not do anything, it
is just a label or a placeholder.
- MENU_CODE_SEP: The item is a separator, which means that
a separating line should be drawn (if possible) between the items preceing
and following this item.
- MENU_CODE_SUBMENU: The item contains a submenu, so it does
not do any action itself, but provides access to a lower level of items.
- long menuID -- this may be used to store the ID of any
window-library-specific menu structure. It is a public variable
which is not used for any other reason by PopupMenu
.
- int menuExists -- another public variable which may be used
by the winding library if necessary, to indicate the presence of a
menu structure.
- static int nextReturnCode -- the next return code to assign
to an item. This must be unique, and greater than zero. It is static
so that all items across all the PopupMenu
instances can get
unique return codes.
- ResizeArray<PopupMenuItem *> menuItems -- the list of the
menu items in the menu. Each PopupMenuItem
object contains the name
and information for a single item, be it a regular item, a separator, or
a submenu.
- char *menuName -- the name of this menu.
- char *name(void) -- return the name of this menu.
- int items(void) -- return the number of items in this menu.
- PopupMenuItem *menu_item(int) -- return the Nth item, or NULL
if N is not in range.
- PopupMenuItem *menu_item(char *) -- return the first
menu item with the given name (label), or NULL if not found.
- PopupMenuItem *find_item(int, PopupMenu * = NULL) -- given a
specific return code as the first argument, this searches the menu specified
in the second argument until the first item with that return code is found.
This returns the item object if found, or NULL if not found or the given
return code is
. The second argument is used to allow for
recursive searching of submenus, and should not be specified by the user
when calling this function.
- int add_item(char *name, char *cmd, int disp, int mark, int
onoff=0) -- This adds a new item to the end of the current menu. The item
will appear in the menu with the given name, and will have the given string
`cmd' be associated with this item. The return code of the new item is
returned. The other flags in the argument specify the following:
- int disp: whether to display the item or not (it can be turned
on/off later by routines in PopupMenuItem
).
- int mark: whether to put a check box by the object or not.
- int onoff: if mark is TRUE, then the check mark can either be
shown as an empty box (onoff=FALSE), or as a checked box (onoff=TRUE). If
mark is FALSE, this is ignored.
- int add_submenu(PopupMenu *, int disp, int mark, int onoff=0)
-- Adds a submenu to the end of the menu. The submenu must have been
created previously. The name of the submenu is used as the name shown in
the current menu. The other arguments are as described for add_item.
Returns success.
- int add_separator(void) -- adds a separator to the end of the
menu. Returns success.
- int delete_item(int) -- delete the Nth item from the menu.
Returns success.
- PopupMenuItem *activate(DisplayDevice *) -- requests the the
menu be given to the specified DisplayDevice
to be activated by
the windowing system. Virtual functions in DisplayDevice
are used to
create the menu, and to get the user's choice from the menu. This returns
a pointer to the PopupMenuItem
object for the item selected, or NULL
if no item is selected.
PopupMenu
objects are used in the following way:
- A PopupMenu
instance is created, that is initially empty.
- The user calls PopupMenu->add_item to add commands, until the
menu is defined. This will return integer ``return codes''
for the items added, which must be remembered by the caller.
- If there is a hierarchy of menus, first create submenus just as
regular menus are created, and then create the parent menu by using the
same method and using the add_submenu routine to attach the submenus
to the parent menu.
- When the menu is defined, and it is to be used, the menu creator
should call PopupMenu->activate(), which returns either a pointer
to a PopupMenuItem
, or NULL if nothing was selected. The
caller can use this item to determine the return code and the text command.
See the source code of the Mouse
class for an example of the use of
PopupMenu
.
Currently there is no support for doing things like greying out of a menu
item, or attaching keyboard shortcuts to menu items. These might be nice
in the future.

This class is used by the PopupMenu
class to hold the data for each
item in the menu. There are several different types of menu items, each
different item has a separate constructor in this class. To create a new
item of a particular type, a new PopupMenuItem
instance is created,
using the relevant constructor. The different types of items are described
below.
- PopupMenuItem::(int rc, char *name, char *cmd)
Creates a new text command menu item. This item will appear in the
menu with the given name, and will have the specified text command
associated with it. The first argument specified the return code which
this menu item should have.
- PopupMenuItem::(PopupMenu *menu)
Creates a new submenu menu item. This item will appear in the menu
with the name of the specified submenu. When displayed and activated, the
specified submenu will be shown as cascading from the parent menu.
- PopupMenuItem::(void)
Creates a new separator menu item. This will be displayed as a line
of some sort between the previous and following menu item.
- int returnCode -- the return code of this item.
- char *textCmd -- the text command string associated with this
item. When this menu item is selected by the user, the Mouse
object
will get this string and request it to be executed as if it had been
typed at the console.
- char *itemName -- the name of the item, as it should appear in
the menu.
- PopupMenu *subMenu -- if this is a submenu item, this is the
pointer to the submenu. Otherwise, this is NULL.
- int showItem -- whether or not the item should be displayed.
- int showCheck -- whether or not a check box should be shown with
the item.
- int checkItem -- whether or not a check mark should be shown
with the item.
- int is_separator(void) -- return whether this item is a
separator item or not.
- int is_submenu(void) -- return whether this item is a submenu
item or not.
- int return_code(void) -- return the return code of this item.
- int showing(void) -- return whether the item is being displayed.
- int show_check(void) -- return whether a check box is to be
shown with the item.
- int checked(void) -- return whether a check mark is to be shown
with the item.
- char *text_command(void) -- return the text command string
associated with this item.
- char *name(void) -- the name of the item.
- PopupMenu *sub_menu(void) -- the submenu for this item, or NULL
if not present.
- void return_code(int nc) -- change the return code to the given
value.
- void showing(int yn) -- change the displayed status.
- void show_check(int yn) -- change whether to display a check
box.
- void checked(int yn) -- change whether to display a check mark.
The main place where this class is used is in PopupMenu
, and also
in Mouse
. When an item is added to a menu, a new PopupMenuItem
instance is created, of the requested type. The flags specified in the
functions in PopupMenu
for how to display the item (on/off, checked,
etc) are set by calling the proper functions in the newly created item
instance. Finally, when an item is selected by the user, the pointer to
the item is returned to the Mouse
object, which uses that item to
find the text command to execute (if any).
No provision is made here for `greyed-out' items, just for whether an item
is to be displayed or not. It might be nice to have greyed-out items in the
future.

VMD
contains several user interface components, where each component (a
UIObject
subclass) can separately issue requested (via Command
ojects) to have particular actions completed. The UIList
class is used
to maintain the entire collection of these user interface components. There
is one global instance of this class, uiList; all user interface
components which are active during a VMD
run must register themselves with
this list.
UIList
is used for two main purposes:
- To provide the names and pointers for all the UIObject
's in the
program to other parts of the program that need them.
- To perform global operations on all the UIObject
's, such as
checking for events, resetting the interfaces, and informing the interfaces
when a Command
is executed.
When a new UIObject
is created, it must register itself with
the proper UIList
. This is done by specifying a pointer to a
UIList
in the constructor of all subclasses of UIObject
. At
present, there is no way to `unregister' from the UIList
, it is
assumed all UIObject
's will be used for the duration of the program.
- ResizeArray<UIObject *> uilist -- the list of user interface
components which this list is managing.
- int num(void) -- return the number of UIObject
s in the
list.
- UIObject *item(char *) -- return the first interface object
which has the given name, or NULL if none found.
- UIObject *item(int) -- returns the Nth user interface object.
- int register_UI(UIObject *) -- adds a new user interface
object to the current list, and returns its index.
- void reset_UI(void) -- calls the reset() routine for
all registered UIObject
s.
- void init_UI(void) -- calls the init() routine for
all registered UIObject
s.
- void update_UI(void) -- calls the update() routine for
all registered UIObject
s.
- void check_event_UI(void) -- calls the check_event()
routine for all registered UIObject
s. This will cause them to
see if any events are pending, and if so new Command
objects will
be put in the command queue.
- void act_on_command(Command *) -- this is called after a
Command
has been executed, in order to inform all the user interface
components about the possible change. Each Command
has a unique code,
and each UIObject
will make a note of which command's they are
interested in. This routine will call the act_on_command routine
for each UIObject
which has expressed interest in the command.
A global instance of this class is created at the very beginning of the
program, before any UIObject
's are created. It is initially empty,
but each time a new UIObject
is started, the global instance is
specified in the UIObject
constructor and that UIObject
will
register itself with the list.
This object is used primarily in the main event loop of VMD
to cause
all the interface components to check for events, and in the
CommandQueue
object to inform components when an action occurs. It
is also used by parts of the program that need a list of the names of
UIObject
's.

UIObject
is the base class for each object in VMD
which provides
some form of user interface. There is a UIObject
subclass for dealing
with the text console, for the 2D pointer interface (the Mouse
), and
for the 3D user interface (currently in development). Also, each of the
different GUI forms which appear on the screen are a separate UIObject
.
VMD
contains many different UIObject
, each for the most part
independent of the others. A UIObject
has the ability to get input
from the user on what that would like to do, and convert these into particular
commands to do that action. These commands (embodied by different subclasses
of the Command
object) are put in a queue for execution. Each
UIObject
must also present some form of visual representation of the
state of VMD
to the user, which changes as different actions are performed.
As commands are executed, each UIObject
must be informed of what the
action was, in order to update its display. No user interface component is
capable of executing ALL the commands available in VMD
, however, and
conversely no user interface component is interested in hearing about all the
different possible actions in VMD
.
Each UIObject
has the following characteristics:
The main UIObject
s in VMD
are all created in the routine
VMDinitUI, in the file Global.C.
- UIObject::(char *, UIList *, CommandQueue *)
The arguments are the name of the object, the UIList
with which this
should register, and the CommandQueue
which this should use to queue
Command
objects for execution.
- char *name -- the name of the object; this is public so that
it can be accessed by other objects in VMD
.
- int myID -- the ID code for this object, as returned by the
UIList
.
- int uiOn -- whether this object is active; if not, it will not
check for events from the user.
- int maxCmds -- the total number of commands which this object
can possibly be interested in.
- char *doCmd -- an array of flags which are used to indicate if
a command is wanted or not.
- UIList *uiL -- the UIList
object that this object
registered with.
- CommandQueue *cmdQueue -- the CommandQueue
that this
object should use to queue and execute commands.
- virtual int is_menu(void) -- return whether this object is
an on-screen menu form, or another type.
- virtual int is_on(void) -- return whether the object is
currently active.
- virtual void On(void) -- turn on the UIObject
.
- virtual void Off(void) -- turn off the UIObject
.
- virtual void move(int, int) -- moves the UIObject
the the
given X,Y position on the screen, where X and Y are in pixels measured from
the lower-left corner of the display. This may not be applicable to all
UIObject
's, if not is is ignorned.
- virtual void where(int &, int &) -- return the position of the
UIObject
, if applicable.
- virtual void init(void) -- initialize the user interface. This
is called once at the beginning of VMD
, after all the UIObject
s have
been created.
- virtual void reset(void) -- resets the user interface object,
forcing an update of all the informative displays, etc.
- virtual void update(void) -- updates the display, for example
for some visual items which much change each time the scene is redrawn.
This is called in the main loop of VMD
after all queued Command
s
have been executed, before the scene is actually rendered.
- virtual int act_on_command(int, Command *, int) -- this is
called after a command is executed, and it is seen that this UIObject
is interested in that command. The first argument is the command code,
the second the Command
itself, and the third is the success of the
command. This routine should check what the code is, and based on that
update any visual or other such representation of the program to reflect the
change caused by execution of the given command. Returns TRUE if this
UIObject
actually did something due to this command being executed.
- virtual int check_event(void) -- checks whatever external
interface is necessary to see if a new command from the user has been
entered. If so, this routine creates a new Command
object, and
adds it to the queue.
To create a new UIObject
, you must do the following:
- In the constructor for the new class, call the routine
command_wanted to indicate the commands you are interested in.
- Provide versions of at least the routines init, reset, update,
act_on_command, and check_event.
- Add code to the VMDinitUI routine to have the UIObject
created at startup.

The particular UIObject
which is responsible for getting text commands
from the user, parsing them, and executing them. Each time it is requested
to do so, this object will check to see if the user has entered a line of
text at the VMD
prompt, and if so, this will read in the command,
break it up into the individual words, and determine what action is being
requested.
Every action in VMD
which the user can request to have performed has a
corresponding Command
object associated with it, and a text command
representation.
Each text command consists of N separate words separated by
whitespace, with the first word in the command used to distinguish between
different types of commands. The UIList
maintains a list of these
initial words, and with each word there is an associated callback
function which is called when a text command is read in and the first word
is found in the list.
This object can also be directed to read commands from a file, and to echo
text commands to the console.
UIText
is able to use the Tcl library, if available, to parse the
text commands and to provide sophisticated interpreted script capabilities
such as control loops, variable substitution, if-then-else constructs, and
user-defined subroutines and functions. If Tcl is not available, this
object will still function, but only the basic VMD
commands will be
understood.
- UIText::(UIList *, CommandQueue *)
The arguments are the UIList
object to register with, and the
CommandQueue
object to use for queuing and executing Command
objects.
- NameList<TextCallback *> textProcessors -- a list of all the
words which this object understands as the first word in a specific command,
and the callback function to call when a command with the starting word is
entered. TextCallback is a typedef for the callback function, as
defined in the file Command.h.
- int needPrompt -- whether or not the prompt needs to be
printed the next time it is possible to do so.
- Stack<FILE *> input_files -- a stack containing the FILE
structures for the files to read commands from. When a new file is opened
for reading, the currently open file is pushed down on the stack and the
new file is put at the top of the stack. When the end of the file is
reached, the stack is popped and reading from the new top file is resumed.
In this way files may be read in a nested fashion. When the stack is
empty, input is read from standard input.
- int doEcho -- flag to indicate if text commands should be
echoed back to the console after they have been entered (even if from a
file or from the console).
- Inform txtMsgEcho -- the Inform
object to use for
echoing commands.
- Timer mytimer -- the Timer
object is used to measure how
long to wait before reading the next message, if the user has requested a
waiting period between commands.
- float delay -- the amount of time to wait (in seconds) before
attempting to read the next command. Once the waiting period is over, this
is set to zero.
- int num_commands(void) -- the number of words which this
object understands as the first word in a command.
- char *word(int) -- the Nth word that this object understands
as the first word in a command.
- void add_command(char *, TextCallback *) -- adds a new word
to the UIText
vocabulary, and registers the given function as the
callback for that word. If the word is already known, this does nothing.
- int process_command(int argc, char **argv) -- given a tokenized
text command (one that has been broken up into `argc' individual words, with
the words in the `argv' array), this routine checks the first word to see
if it is understood, and calls the proper callback function or prints an
error message.
- void read_from_file(char *) -- instructs this object to read
text commands from the given file until the end-of-file is reached.
- void wait(float) -- instructs this object to wait for the given
number of seconds before attempting to read in the next text command.
- int echo(void) -- returns the current echoing status.
- void echo(int yn) -- turns on/off echoing of text commands.
- virtual int check_event(void) -- checks to see if a text
command has been entered at the console or is available from a file. If so,
this reads in the string, and queues a `TextEvent' command (which is a
subclass of Command
) containing the string.
- virtual int act_on_command(int, Command *, int) -- called
after a text event command is executed. This will take the text command
string in the text event, break it into tokens, and if the first word
is understood this will call the proper callback function. If this first
word is not understood, or the callback function returns an error code,
this will print an error message.
In the constructor for this object, first the code for the `TextEvent'
command is registered as a command this object is interested in, and then
all the words this object can understand (with their callback functions)
are added to the object's internal list. Each time a new word is added
to the VMD
vocabulary, a new line must be added in this section to add
the callback function (see the discussion of Command
, section
6.6.1). The callback functions themselves should be declared in
the Cmd*.h files, and defined in the Cmd*.C files.
When a text command is actually to be executed, is it broken into an argc,
argv tokenized format, and given to the process_command routine. This
searches for the first word in the internal list of known words, and calls
the callback function with the argc, argv pair, and also the
CommandQueue
object to use for queuing new commands as well as the ID
of this UIObject
.
In the case where Tcl is being used, there is a slightly different order to
these events. After a string is read, it is given to the Tcl evaluation
routine, which checks it for special Tcl commands or for VMD
commands.
When VMD
commands are seen, Tcl will tokenize the command itself and call
a particular Tcl-tailored callback function. This callback function is
registered with Tcl for every word in the VMD
vocabulary. In this Tcl
callback function, the first word is checked, and the regular text callback
function is called.
The reading of commands from files should be converted from the stdio
style I/O to the use of the streams library.
Next: Tracker objects
Up: Function and Class
Previous: Remote connection objects
Andrew Dalke
Wed May 15 02:25:03 CDT 1996