|Title||Dialog programming (part 1)—Getting started|
|Authors|| James Hassell, StataCorp
Jean Marie Linhart, StataCorp
|Date||August 2003; minor revisions July 2011|
This FAQ is intended to be a supplement for the documentation rather than a substitute. We strongly recommend reading the online help on dialog programming, which contains information that will not be covered here.
Stata dialog programs allow you to define the appearance of a dialog box, specify how the controls of the dialog box interact with the user, and specify the ultimate action that is to be taken (such as running a Stata command) when the user clicks the OK or Submit button.
A dialog-box program is stored in a file ending in .dlg. A .dlg file consists of seven parts, although some of them are optional.
------------------------- dialogboxname.dlg ------------------------- VERSION 12 Part 1: version number POSITION ... Part 2: set size of dialog box DEFINE ... Part 3, optional: common definitions LIST ... DIALOG ... Part 4: dialog definitions BEGIN Dialog controls END repeat DIALOG ... BEGIN ... END as necessary to add dialog tabs SCRIPT ... Part 5, optional: i-action definitions BEGIN ... usually done as scripts ... END PROGRAM ... ... but sometimes as programs BEGIN ... END OK ... Part 6: u-action & helper button definitions CANCEL ... SUBMIT ... HELP ... RESET ... COPY ... PROGRAM command Part 7: u-action definition BEGIN ... END ------------------------- dialogboxname.dlg -------------------------
Using the template above, we can create a dialog for one of Stata's most used commands, generate. The first thing we should do is decide on a name for our new dialog. We will save the file as mygenerate.dlg, as there is already a built-in dialog named generate. Always avoid using names that are already in use.
Click here to download this version of mygenerate.dlg.
Once you have downloaded it, save mygenerate.dlg in your Stata adopath, most preferably your PERSONAL directory. If you are unfamiliar with the PERSONAL directory, please see the following FAQ: Where is my personal ado directory.
Once you have saved it correctly, mygenerate can be called from the Stata command line by typing db mygenerate.
------------------------- mygenerate.dlg ------------------------- VERSION 12 POSITION . . 410 250 DIALOG main, label("generate - Generate a new variable") tabtitle("Main") BEGIN TEXT tx_gen 10 10 120 ., label("Generate variable:") EDIT ed_gen 10 +20 120 ., error("Generate variable") TEXT tx_exp 10 +25 390 ., label("Contents:") EXP ex_exp 10 +20 390 ., label("Create ...") /// error("Contents") END OK ok1, label("OK") CANCEL can1, label("Cancel") SUBMIT sub1, label("Submit") HELP hlp1, view("help generate") RESET res1 COPY copy1 PROGRAM command BEGIN put "generate " require main.ed_gen put main.ed_gen " " put "= " require main.ex_exp put main.ex_exp END ------------------------- mygenerate.dlg -------------------------
The following screen image is produced by the code above:
Now let's break down the code above and analyze the purpose of each line.
- VERSION 12
The version statement is required so that Stata knows how to interpret the code that follows.
- POSITION . . 410 250
This line defines the position and size of the dialog box. In this case, the two dots are interpreted as the default position. The width is defined to be 410 pixels, and the height is defined to be 250 pixels.
- DIALOG main, label("generate - Generate a new variable") tabtitle("Main")
This line defines the main dialog tab. This tab does not necessarily have to be named "main", but that is our preferred name for the first tab here at StataCorp. In this case, the first tab is not displayed as a visible tab. Tabs are only displayed if more than one dialog is defined for a dialog box. The label option of the first dialog tab defines the overall dialog title and is displayed in the title bar of the dialog window.
This line marks the beginning of a dialog tab's input control section.
- TEXT tx_gen 10 10 120 ., label("Generate variable:")
This line defines a TEXT control named tx_gen. TEXT controls are essentially just labels used to convey some information to the user. The numbers following the name will determine the placement of this control on the dialog. The basic form at is X coordinate, Y coordinate, width, and height. This control will be placed 10 pixels right of the left border and 10 pixels below the top of this dialog. It will have a width of 120 pixels. The dot instructs Stata to use the control's default height. As you might expect, the label determines what is displayed.
- EDIT ed_gen 10 +20 120 ., error("Generate variable")
This line defines an EDIT control named ed_gen. EDIT controls are used to provide the user with an area in which to enter information. Just as with the TEXT control above, the numbers that follow the name provide information about where to place the control on the dialog. The error option is used to specify the text to be displayed when an error box is displayed. For instance, in the programming section of this dialog box, we can require that ed_gen not be left blank. In the event it is left blank, the error option determines what error message is displayed.
The line above has one other important feature. Instead of using an absolute point to define the location of the y coordinate, a relative position is used. +20 indicates that the control will be drawn 20 pixels below the control that was previously defined.
- TEXT tx_exp 10 +25 390 ., label("Contents:")
This is another TEXT control, similar to the first one used.
- EXP ex_exp 10 +20 390 ., label("Create ...") /// error("Contents")
This line defines a special control called EXP, which stands for expression builder. An EXP, or expression builder control, has an edit control and a button that is used to launch Stata’s Expression Builder. The user can type directly into the edit portion or use the expression builder.
The label option is used to determine the text displayed on the button, and the error option is used to define the text associated with error messages. Also notice the "///" located at the end of the first line. The "///" is a special type of comment that comments out the end-of-line character. By using this special comment, long commands can be defined while maintaining code that is easy to read.
This line marks the end of a dialog tab's input control section.
Notice that all of the controls in the section above have unique names. These names must be unique, as with any programming language. It is ultimately up to the dialog programmer to name dialog controls; however, we recommend that you use a meaningful naming scheme. For instance, we can immediately tell that the control named tx_gen is associated with a TEXT control and that ed_gen is associated with an EDIT control. Furthermore, we can easily determine that they are both associated with the new generate variable. See some of our preferred name prefixes and their associated controls below.
tx_ TEXT ed_ EDIT ck_ CHECKBOX rb_ RADIO cb_ COMBOBOX ex_ EXP gb_ GROUPBOX - OK ok1, label("OK") - CANCEL can1, label("Cancel") - SUBMIT sub1, label("Submit") - HELP hlp1, view("help generate") - RESET res1 - COPY copy1
The section above adds the u-action and helper buttons to the bottom of the dialog box. This syntax should be self-explanatory and will require little modification. The one exception is the name of the help file, which should obviously direct help to the appropriate place.
- PROGRAM command
The line above marks the beginning of the u-action definitions or program. This section controls behavior when the OK or Submit button is clicked.
This line marks the official beginning of the command program.
- put "generate "
The line above starts building the return string, which is important because it contains the actual command Stata will execute when OK or Submit is clicked. Notice the extra space following the word generate. It is important because it will separate this part of the return string from the next part.
- require main.ed_gen
The require command is very useful because it lets the dialog programmer assert that a control not be left blank and, therefore, avoid circumstances where the dialog generates an invalid Stata command or u-action. It is much more desirable to inform the user that he or she has not entered all of the required information within the context of the dialog system. The less-than-desirable alternative would be to let the user submit an invalid command to Stata.
The second part of the require command is the control. Notice that "main." has been prepended to the control's name. Recall that the DIALOG command can be used multiple times within a single dialog box. Doing so will produce a dialog box with multiple dialog tabs. Since it is possible to have multiple dialog tabs on a single dialog box, controls with identical names can exist on different tabs. Now it should be clear why ed_gen must be fully qualified with the name of the dialog to which it belongs. Those familiar with object-oriented programming will find this notation to be quite familiar.
The text above indicates that using require causes an error box to be displayed when the user presses the OK or Submit button without filling in main.ed_gen. The error box will contain the text defined in the error option for that control. If the error option is not defined, the label option will be used.
- put main.ed_gen " "
Here, we are continuing to build the return string by adding the contents of the edit control ed_gen and padding the string with a blank. Remember, the ultimate goal of the dialog box is to issue a valid command to Stata. This is simply a continuation of that process.
- put "= "
This line adds the equal sign and a space to the return string. This is significant, because it is required syntax for the generate command being constructed.
- require main.ex_exp
Just as above, this line asserts that a control has not been left blank.
- put main.ex_exp
This line completes the return string by adding the final argument to the generate command.
As you might expect, this line is used to terminate the PROGRAM block.
We have now successfully created a simple dialog called mygenerate. In the next section, we will discuss adding more functionality to mygenerate.