CS551 - Self-Study Exercises

Exercise 7: Dialogs

Almost any graphical interface requires the ability to make supplementary windows appear and disappear from the screen in response to user actions, error situations, or state changes in the underlying software. This exercise explores how a simple dialog is created and activated/deactivated, and its effect on where user input is directed. It also introduces basic techniques for detecting when the position of a window might make it partially off-the-screen.

You should have read Chapter 13.1 - 13.3 in Nye and O'Reilly, Vol. 4, before starting this exercise.


  1. Make a copy of the codeview program (from the course directory), naming it dialogs. Add another button to the application, this one to invoke an InputFile mechanism. Mimic the Quit callback mechanism, but instead of exiting the application, print a message -- be sure this message does not end with an explicit newline character -- to file stderr indicating that pushing this button will cause a file input dialog window to appear (this will be implemented in the next steps).

    How does the behavior change if you print to stdout instead? Explain.

  2. Now modify the file mechanism so that a popup dialog appears whenever the button is pressed. The purpose of this dialog is so the user can specify an input file. It will prompt the user for a file name and provide buttons for either canceling or confirming the choice. Use the Athena dialog widget.

    Start by implementing the mechanism to pop up the dialog, but not to pop it back down. You will need to add the header files for both the Dialog widget class and X11's Shell.h file. Call the shell for your popup dshell and the dialog widget itself, input_dialog. Mimic the book's Example 3-6, but in the simplest possible way: all you will need to add are the lines to create dshell and input_dialog, plus a call to XtPopup in the callback for your button; no new resource settings are needed. At this point, don't worry about desensitizing the buttons, popping the dialog down, or positioning it. Compile and run your code in the foreground (so you can kill it with Control-C).

    What factors determined the size and placement of the popup?

    Why can't you continue interacting with the application?

    Try using XtGrabNone instead of XtGrabNonexclusive.

    How does that change the application's behavior?

    Traditionally, buttons in the main window are desensitized (dimmed) and the keyboard focus is "grabbed" by a dialog, whenever the user's response to a dialog are critical before the application can continue. This is a modal dialog. If the dialog provides supplementary information that the user might want to continue viewing, the keyboard focus is not grabbed and buttons are not dimmed; such a dialog is referred to as non-modal.

    If the function of your dialog is to change the file being viewed, should the dialog be modal or non-modal?

    Implement the correct modality in your program.

  3. Next, add a Done button to the Dialog widget, and give it a callback that pops down the transient shell. By means of the resource file only (no changes to your code), provide a more meaningful descriptive text and force the dialog widget to display a text input field. The same callback that pops down the dialog should also print (to stderr) the file name typed by the user.

  4. Most graphical interface platforms allow the user the option of cancelling a dialog via a Cancel button. Selecting this button causes the dialog to pop down, without registering (in this case, printing) the file name. Implement this button.

    Another difference between Done and Cancel is that cancelling a dialog will "ignore" any text editing the user has done.

    Right now, what controls the contents of the text input field the first time the dialog is popped up? For subsequent displaying of the dialog?

    Modify your program so that any previously assigned string value is restored whenever Cancel is selected instead of Done.

  5. Now add the code necessary to position the popup dialog in a more pleasing location. Simplify the technique shown in Example 3-6 in the text so that the top center of the popup window appears in the location where the button was pressed. Run this version.

    What happens if the user moves the application so it's in the lower right side of the screen, then clicks the cursor from a position low in the window?

    Fix this problem by adding code which checks to make sure that there is room to display the whole popup. If not, modify the position so that the whole popup is visible.

  6. Now observe what happens if you try to resize the main window vertically and/or horizontally. Your task is to make the application behave correctly when resized. Start by changing the outermost frame (window) from a Box to a Form. Adjust the resource(s) required so that the quit button is above the code box, not on top of it.

    What resource setting accomplished this?

  7. Now try the same approach with the second box, codes. Make it a Form and add the minimal number of constraints such that all module labels are (at least partly) visible. This time you will have to hard-code the resources settings by modifying the call to XtVaCreateManaged Widget.

    Why did the constraints have to be hard-coded rather than being in the defaults file?

  8. Note that the expansion no longer works properly. This is because Form sizes its children once, and then responds only to user resizing, not to the fact that children might resize themselves. Use the information on Form in Volume 5 to figure out which resource will make this feature work again.

    Which is it? Were you able to add it via the defaults file, or did it have to be hard-coded?