next up previous contents
Next: Tracker objects Up: Function and Class Previous: Remote connection objects

User interface 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.

Command

 

Description

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:

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.

Constructors

Enumerations, lists or character name arrays

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.

Internal data structures

Nonvirtual member functions

Virtual member functions

Method of use

Using a Command object:

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

Developing a new class derived from Command:

The following `checklist' should be followed when creating a new type of command:
  1. 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

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

  3. Put a new code in the Cmdtype enumeration in Command.h

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

  5. Put the member functions in the file CmdXXXX.C. The easiest thing to do is to follow the patters in the Cmd*.C files.

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

  7. 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:
    1. 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.

    2. 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'.

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

  9. Finally, update the on-line help file vmd_help.html, and the User's Guide.

Suggestions for future changes/additions

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

 

Description

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:

Constructors

Internal data structures

Nonvirtual member functions

Method of use

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.

Suggestions for future changes/additions

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.

Mouse

 

Description

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:

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.

Constructors

Enumerations, lists or character name arrays

The MoveMode enumeration lists the possible mouse modes. These are:

Internal data structures

Nonvirtual member functions

Virtual member functions

Method of use

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.

Suggestions for future changes/additions

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

 

Description

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:

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.

Constructors

Enumerations, lists or character name arrays

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:

Internal data structures

Nonvirtual member functions

Method of use

PopupMenu objects are used in the following way:

See the source code of the Mouse class for an example of the use of PopupMenu .

Suggestions for future changes/additions

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.

PopupMenuItem

 

Description

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.

Constructors

Internal data structures

Nonvirtual member functions

Method of use

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

Suggestions for future changes/additions

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.

UIList

 

Description

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:

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.

Constructors

Internal data structures

Nonvirtual member functions

Method of use

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

 

Description

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.

Constructors

Internal data structures

Nonvirtual member functions

Virtual member functions

Method of use

To create a new UIObject , you must do the following:

UIText

 

Description

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.

Constructors

Internal data structures

Nonvirtual member functions

Virtual member functions

Method of use

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.

Suggestions for future changes/additions

The reading of commands from files should be converted from the stdio style I/O to the use of the streams library.



next up previous contents
Next: Tracker objects Up: Function and Class Previous: Remote connection objects



Andrew Dalke
Wed May 15 02:25:03 CDT 1996