Common Desktop Environment: Application Builder User's Guide

Creating and Editing Messages

This section describes the Message Editor and explains how to create and edit message dialog boxes.

Message Editor

The Message Editor is used to create various types of messages to be displayed at appropriate times in the compiled application. It is shown in Figure 5-1 and then described. See "To Create a Message Dialog Box " and "To Edit a Message " for instructions on its use.

Figure 5-1 Message Editor

Graphic

Messages

Lists all messages for the current project. The module name precedes the message name in the list.

Module menu

Specifies the module for which you wish to add a new message. The module name precedes the message name in the Messages list.

Add Message

Adds a new message to the Messages list and to the current project. The message is for the module selected in the module option menu.

Delete Message

Deletes the selected message.

Name

Specifies the instance name of the current message object. Messages are given names such as "message," "message2," "message3," by default.

Dialog Title

Specifies the title that will appear at the top of the message dialog box.

Type

Specifies the type of message to be created. The choices are Error, Information, Working, Question, and Warning. The message type appears above the message text pane. The appropriate message icon appears in the message dialog box in the compiled applications.

Message text pane

A text pane for entering the text of the message. Press Return when you want the text to start a new line. The label above the text pane varies, depending on what type of message you have chosen.

Button check boxes

Specifes which buttons will be included at the bottom of the message dialog box. Each message type has a different set of buttons specified by default; these default choices can be changed. Actions associated with the Action1, Action2, Action3, and Cancel buttons are set in the Connections Editor. See "To Create a Message Dialog Box " for detailed instructions.

Default Button menu

Specifies the default button for the selected message dialog.

Connections

Displays the Connections Editor for specifying what functions to call for each of the Action buttons and the Cancel button.

Help Text

Displays the Help Editor, in which you write help text to be displayed when the Help button is clicked in the message dialog box.

Show Dialog

A push button for displaying the selected message in a message dialog box that looks like the actual dialog box in the compiled application. Click one of the buttons other than Help to dismiss the dialog box.

See "Property Editor: Common Buttons " for descriptions of the buttons at the bottom of the editor.

To Create a Message Dialog Box

See "Message Editor" for descriptions of each of the fields in the editor. See "To Connect a Non-Modal Message to a Function " for a discussion of how to connect messages to the functions that cause them to be displayed, with examples.

  1. Choose Messages from the Editors menu of the App Builder primary window to display the Message Editor.

  2. Choose the module to which you want to add a message in the option menu below the Messages list.

  3. Click Add Message.

    A unique name ("message," "message2," and so on, depending on how many messages are in the current module) will be displayed in the Name field. The module name and the message name will be added to the Messages list.

  4. Modify the Name if you wish.

    This is the name used to identify the message internally--in the Connections Editor, for instance. This name is not displayed in the compiled message dialog box.

  5. Type a title for the message dialog in the Dialog Title field.

    This will appear in the title bar of the compiled message dialog box.

  6. Choose a message type from the Type menu.

    The icon for the message type will be displayed in the Type menu and the message type (Error, Information, Working, Question, or Warning) will be displayed above the message text pane (to the right of the Type menu).

  7. Type the message text in the message text pane, pressing Return when you want a new line to start in the compiled message.

  8. Specify which buttons will appear in the message dialog box by clicking the check boxes below the message text pane and typing the labels you want on the Action1, Action2, and Action3 buttons.

    Each of the message types includes a default set of buttons that you can modify:

    • Error: Action2 (Retry), Cancel, Help.

    • Information: Action1 (OK), Help.

    • Working: Action1 (Close), Action2 (Stop), Help.

    • Question: Action1 (Yes), Action2 (No), Help.

    • Warning: Action2 (Continue), Cancel, Help.

  9. Choose a default button from the Default Button menu.

    This is the button that will have an extra border when the message dialog box is displayed. This is the button that will be activated if Return is pressed. Each of the message types has a default Default Button that you can modify:

    • Error: Action2

    • Information: Action1

    • Working: Action1

    • Question: Action1

    • Warning: Action2

  10. Click the Help Text button and create help text, as appropriate.

    See "To Create Help" for instructions.

  11. Click OK or Apply to apply the changes.

    The Message Editor will be dismissed if you click OK.

To Edit a Message

  1. Choose Messages from the Editors menu of the App Builder primary window to display the Message Editor.

  2. Select the message you want to edit in the Messages list.

  3. Edit the message, as appropriate.

    • To delete a message, click Delete Message.

    • To modify the dialog box title, click in the Dialog Title text field and type the new label.

    • To change the message type, choose a different Type icon.

    • To modify the message text, click in the message text pane and type the appropriate changes.

    • To change the available buttons, select the check boxes and type new button labels, if appropriate.

    • To change the default button, choose another from the Default Button menu.

    • To modify help text, click Help Text, make the changes in the Help Editor, and click OK in the Help Editor.

  4. Click OK or Apply to apply the changes.

    The Message Editor will be dismissed if you click OK.

To Connect a Non-Modal Message to a Function

See "Example: Writing Code for Messages" for a discussion of how to connect a message to the function that causes it to be displayed, with examples. In particular, read that section to see how to attach a modal (blocking) message to a function.

  1. Display the Connections Editor by clicking Connections in the Message Editor or by choosing Connections from the Editors menu of the App Builder primary window.

    If you select a message in the Message Editor and click Connections, the selected message will be selected in the Source list of the Connections Editor. You can skip the next two steps.

  2. Display messages in the Source list by choosing Message from the Source menu.

  3. Select a message in the Source list.

  4. Choose Call Function as the Action Type.

    This activates the When menu on the Source side of the Connections Editor.

  5. Choose a When item (Action1, Action2, Action3, or Cancel Activated, depending on which buttons were checked in the Message Editor).

  6. Type the name of the Function to be called when the selected button is selected.

    When code is generated, this function is created in <module_name>_stubs.c. You will have to substitute appropriate code before running make.

  7. Click Connect to create the connection.

    The connection will be displayed in the View list at the bottom of the Connections Editor.

  8. Repeat the previous three steps for each button except Help.

  9. Click Cancel to dismiss the Connections Editor.

Example: Writing Code for Messages

Once you have created a message as described in "To Create a Message Dialog Box ", you must determine when and how it should be displayed. Usually messages are displayed after a certain piece of logic has been executed. For example, if a user types digits in a text field that is designed to accept a name, you will want to post an error message informing the user that digits are not valid.

Message boxes in Motif can be displayed in one of two ways: modally or non-modally (equivalently, blocking or non-blocking). The App Builder code generator (dtcodegen) supplies two routines, corresponding to the two modes of display. They are found in dtb_utils.c and are named:

If you want to display a particular message modally, use dtb_show_modal_message(). If you want to display a particular message non-modally, use dtb_show_message().

One of the key differences in the way these two types of of messages are handled is in how the application determines which button was pressed by the user in the message dialog box. For non-modal messages callbacks are added to each button via the Connections Editor. When the user clicks a button the corresponding callback is called. Since modal dialogs are blocking, the button callbacks are not called. Instead, the value is returned by dtb_show_modal_message(), which indicates which button is pressed by the user.

To Write Code for Modal Messages

If a message is to be displayed modally, use dtb_show_modal_message(). This routine returns a value which indicates which message box button the user has pressed. The value is an enum that is defined in dtb_utils.h:

/*
 * Returns answer value for modal MessageBox
 */ 
typedef enum {
        DTB_ANSWER_NONE,
        DTB_ANSWER_ACTION1,
        DTB_ANSWER_ACTION2,
        DTB_ANSWER_ACTION3,
        DTB_ANSWER_CANCEL,
        DTB_ANSWER_HELP
} DTB_MODAL_ANSWER;

You can then examine the return value (for example via a switch statement) and execute the appropriate piece of code.

Here's an example of displaying a message modally. Say that you have created a simple application, named foo. The project is named foo.bip and consists of one module, foo.bil. The module foo.bil consists of a main window, control pane, and two text fields, one for the user to enter a person's first name and the other to enter the last name. If the user types digits, an error message will be posted, informing the user that digits are not allowed, and giving the user a couple of options. The user can start over, which means the text entered will be erased, or the user can continue, which means that the text entered will be left intact, giving the user discretion as to how to modify the text.

A call-function connection is made for both text fields, which will be called each time the user types something. The function for the first text field will check if the character typed is a digit. If so, it will post the error message modally:

void 
verify_first_nameCB(
     Widget widget,
     XtPointer clientData,
     XtPointer callData 
)
{
     /*** DTB_USER_CODE_START vvv Add C variables and code below vvv ***/
     char                *text = (char *)NULL;
     int                 textlen = 0;
     DTB_MODAL_ANSWER    answer = DTB_ANSWER_NONE;    
     DtbFooMainwindowInfo instance = (DtbFooMainwindowInfo) clientData;
     /*** DTB_USER_CODE_END   ^^^ Add C variables and code above ^^^ ***/

     /*** DTB_USER_CODE_START vvv Add C code below vvv ***/
     text = XmTextFieldGetString(widget);
     if ((text != NULL) && (*text != NULL))
     { 
        textlen = strlen(text);
        if (isdigit(text[textlen-1]))
        {
             dtb_foo_message_initialize(&dtb_foo_message);
             answer  dtb_show_modal_message(instance->textfield,
                        &dtb_foo_message, NULL, NULL, NULL);
             switch (answer)
             {
                 case DTB_ANSWER_ACTION1:        /* Start Over */
                     XmTextFieldSetString(widget, "");
                     break;

                 case DTB_ANSWER_ACTION2: /* Continue */
                     break;
             }
        }
     }

      /*** DTB_USER_CODE_END   ^^^ Add C code above ^^^ ***/ 
}

To Write Code for Non-Modal Messages

If you want to post a non-modal message, use dtb_show_message(). Since this function is not modal and does not return a return value, callbacks for the message box buttons should be specified via the Connections Editor, as described in "To Connect a Non-Modal Message to a Function " . The buttons that are specified for the message box are displayed as When items for the message object in the Connections Editor.

Using the same example as above, make the last name text field display the error message non-modally if the user types a digit. As previously mentioned, first you'll need to make a couple of call-function connections for the two buttons in the message box, labelled "Start Over" and "Continue." When code is generated, add code to those routines to do the right thing. The start over routine will clear out the text field and the continue routine will do nothing, in this case.

void 
verify_last_nameCB(
    Widget widget,
     XtPointer clientData,
     XtPointer callData 
) 
{
    /*** DTB_USER_CODE_START vvv Add C variables and code below vvv ***/
    char               *text = (char *)NULL;
    int                 textlen = 0;    
    DtbFooMainwindowInfo instance = (DtbFooMainwindowInfo) clientData;

    /*** DTB_USER_CODE_END   ^^^ Add C variables and code above ^^^ ***/
    
    /*** DTB_USER_CODE_START vvv Add C code below vvv ***/

    text = XmTextFieldGetString(widget);
    if ((text != NULL) && (*text != NULL))
    {
         textlen = strlen(text);
         if (isdigit(text[textlen-1]))
         {
            dtb_foo_message_initialize(&dtb_foo_message);
            dtb_show_message(instance->textfield,
                        &dtb_foo_message, NULL, NULL);
         }
     }
      /*** DTB_USER_CODE_END  ^^^ Add C code above ^^^ ***/ 
}
void start_overCB(
     Widget widget,
     XtPointer clientData,
     XtPointer callData 
) 
{
    /*** DTB_USER_CODE_START vvv Add C variables and code below vvv ***/

    DtbFooMainwindowInfo instance = (DtbFooMainwindowInfo) clientData;      

   /*** DTB_USER_CODE_END   ^^^ Add C variables and code above ^^^ ***/
      
   /*** DTB_USER_CODE_START vvv Add C code below vvv ***/
      
   XmTextFieldSetString(dtb_foo_mainwindow.textfield2, "");  

   /*** DTB_USER_CODE_END   ^^^ Add C code above ^^^ ***/ 

}   

void continueCB(
    Widget widget,
    XtPointer clientData,
    XtPointer callData 
) 
{    

    /*** DTB_USER_CODE_START vvv Add C variables and code below vvv ***/
    /*** DTB_USER_CODE_END   ^^^ Add C variables and code above ^^^ ***/      

    /*** DTB_USER_CODE_START vvv Add C code below vvv ***/     
    /*** DTB_USER_CODE_END  ^^^ Add C code above ^^^ ***/ 
}

The two routines above, start_overCB() and continueCB(), are added as callbacks for the two buttons via the call to dtb_show_message(). Here is the code fragment that adds the callback (from dtb_utils.c):

/* Add Callbacks if necessary */

if (mbr->action1_callback != (XtCallbackProc) NULL)
     XtAddCallback(msg_dlg, XmNokCallback, mbr->action1_callback, NULL);     

if (mbr->cancel_callback != (XtCallbackProc) NULL)        

     XtAddCallback(msg_dlg, XmNcancelCallback, mbr->cancel_callback, NULL);    

if (mbr->action2_callback != (XtCallbackProc) NULL)     
{
     action_btn = dtb_MessageBoxGetActionButton(msg_dlg, DTB_ACTION2_BUTTON);
     if (action_btn != NULL)
             XtAddCallback(action_btn, XmNactivateCallback,
                           mbr->action2_callback, NULL);    
}     
if (mbr->action3_callback != (XtCallbackProc) NULL)     
{ 
     action_btn = dtb_MessageBoxGetActionButton(msg_dlg, DTB_ACTION3_BUTTON);     
if (action_btn != NULL)
     XtAddCallback(action_btn, XmNactivateCallback, mbr->action3_callback, NULL);    
}

The structure mbr contains all the necessary information for the message. The structure is filled in with the values specified in the Message Editor when the message object was created via the dtb_&_&_initialize() routine--in this example, dtb_foo_message_initialize().