next up previous contents
Next: CommandQueue Up: User interface objects Previous: User interface objects   Contents

Subsections


Command

Files: Command.h, Command.C, Cmd*.h, Cmd*.C
Derived from: none
Global instance (if any): none
Used in optional component: Part of main VMD code

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


next up previous contents
Next: CommandQueue Up: User interface objects Previous: User interface objects   Contents
vmd@ks.uiuc.edu