Introduction Chapter 1 Chapter 2 Chapter 3 Chapter 4 Chapter 5 Chapter 6 CLOS Intro
Allegro CL version 8.0

Chapter 5: Create the Coefficients Dialog

  1. Start Allegro CL if you exited in Chapter 4. Open the gui-builder-tutorial project we left in Chapter 4. (If you have restarted Allegro CL, a dialog may appear asking if you want to open that project, along with any other projects recently worked on. If not, use File | Open Project and choose the file gui-builder-tutorial.lpr in your tutorial project directory, which is C:\Program Files\allegro-projects\gui-builder-tutorial\ or allegro-projects/gui-builder-tutorial/ on Linux if you used the defaults. The Recent menu may also provide a way to open the project.) You should now be where you stopped at the end of Chapter 4.
  2. In this chapter, you will create a Coefficients dialog similar to this one:

ch5-1-coef.bmp (199878 bytes)

  1. Click on the New Form button on the Standard toolbar (or choose File | New Form). Select dialog from the list and click OK. This defines the new form as an instance of dialog.
  2. Reshape the new form to be roughly the same size as the illustration in Step 2.
  3. Inspect the new form (double-clicking on it will expose the Inspector window with the new form inspected).
  4. In the inspector, change (where necessary) the minimize-button to nil, maximize-button to nil, name to :coefficient-dialog, resizable to nil, child-p to nil, and title to Coefficients.
  5. In the Project Manager dialog, select the coefficient-dialog and click on the View Selected Code button.
  6. In the editor buffer, enter the following defclass.
(defclass coefficient-dialog (dialog)
    ())
  1. Evaluate the coefficient-dialog defclass. (Once again, we have create a new subclass of dialog that we will specialize for our application without affecting other instances of the class dialog.)
  2. Save the buffer to coeffiicient-dialog.cl to your tutorial directory using the Save button or File | Save.
  3. In the coefficient-dialog inspector, change class to coefficient-dialog.
  4. On the Coefficients form, sketch in a static-text control. The icon for static-text is a capital A.
  5. Inspect the new static-text and change name to :a-text and value to ~A:.
  6. Reshape the static-text sizing handles so that they closely surround the text. Reposition the control so that it sits in the upper left part of the form. See the illustration in Step 2. (This control provides a label for the editable text widget displaying 200 in the picture).
  7. Now sketch in an editable-text control on the right-hand side of the static-text. The icon for editable-text looks like ab|.
  8. Inspect the new editable-text control and change the name to :a-coefficient-text.
  9. Reshape and reposition a-coefficient-text next to the static-text control (see the illustration after step 2).

Want more control over repositioning components vertically?

You need to turn off the grid and component alignment options.

  1. Select Tools | Options. The Options dialog will appear.
  2. Choose the Form tab.
  3. Clear the check boxes on Snap to Grid and Snap to Components.
  4. Click on Apply to apply the changes.
  5. Leave the Options dialog open while you make the adjustments you want to the controls on the Coefficients dialog. Drag everything to the location that satisfies you.
  6. Re-select Snap to Grid and Snap to Components before clicking OK to close the Options dialog and moving on to the next step. You'll need them again later.

If you only clear Snap to Grid you will still have trouble getting an alignment of vertical centers because these components are so similarly sized that they "stick" to the nearby edges of neighboring components. Clear both the Snap to Grid and Snap to Components options to make this exercise easier.

These two options comprise a feature called sticky alignment.

  1. Now sketch in an up-down-control next to the a-coefficient-text on the right-hand side.

up-down-icon.bmp (33102 bytes)

  1. Drag the new up-down-control so that it overlaps the right edge of the editable-text.

If done properly, the up-down-control will attach itself to the editable-text control. You will be able to tell because the up-down-control will reposition and resize itself to match the editable-text. It will also accompany the editable-text if you drag it around on the form.

  1. Inspect the new up-down-control. Verify that its buddy-widget is :a-coefficient-text. Change its name to :a-coefficient-control, range to (1 1000), and value to 1.

The buddy-widget property helps unify these two controls and keep their functions connected.

Note that it is a read-only property of the up-down-control. You must change it graphically (using the mouse and the IDE); the inspector wouldn’t know how to reposition the controls if you changed it textually (by typing into the value location in the Inspector).

  1. Click on the Save All button on the standard toolbar or choose File | Save All.
  2. Set focus to the Coefficients form and click Run | Run Form.

Run Form versus Run Project

Run | Run Project (or the Run Project button) invokes the project init function. This creates and displays the window associated with the main (Doodler) form only. Other windows must be created and displayed programmatically. Run | Run Project will not display the window we are working on since it is not the main form.

Run | Run Form works here because it creates and displays the window associated with the selected form whether or not it is the main form.

Another difference, not specifically relevant in this case, is that projects are run in a new thread, different from the IDE thread (IDE GUI) while forms are run in the IDE thread. (Display the Process Browser with View | Processes and update it while running a project to see this.)

  1. When you are satisfied that the up-down-control and the editable-text are working (clicking on the up-down-control arrows should change the value in the editable-text) on the Coefficients dialog, click the Stop button (or choose Run | Stop).
  2. Drag-select the static-text control for the A coefficient, the editable-text, and the up-down-control on the coefficient-dialog form. All three controls should be selected now. To drag-select, place the cursor just above and to the left of the static-text control, depress the left mouse button and drag the cursor to just below and to the right of the up-down-control. Release the mouse button. All controls should be selected, as indicated by white squares in their corners, as shown in this illustration:

ch5-ds.bmp (304182 bytes)

Selecting More Than One Object

When multiple controls are group-selected, the selection handles for each control will appear hollow and light colored rather than solid and dark colored. This indicates that the controls can be moved as a group but not resized.

  1. Copy the selected controls using the Edit | Copy command.
  2. Paste the controls using the Edit | Paste command.

The pasted controls appear to the right and below the controls being copied.

  1. Leave the pasted controls selected. Move them as a group into alignment with the original group of controls. Refer to the illustration in Step 2 for the position of the B coefficient control. Horizontal alignment marks will begin appearing to guide you when you get close.

Turn sticky alignment back on (see step 17) if you don't have alignment guides and want to see them. Although you have a group of controls already selected; it will still come on right away and assist you during this step.

  1. Inspect the pasted static-text control. Change its name to :b-text and its value to "~B:".
  2. Inspect the newly pasted editable-text control. Change the name to :b-coefficient-text.
  3. Inspect the newly pasted up-down-control. Change the name to :b-coefficient-control. Verify that the buddy-widget is :b-coefficient-text.
  4. Click on the Save All button to save your changes.
  5. Set focus on the Coefficients form and choose the Run | Run Form command.
  6. Verify that the up-down-controls are working for both the A and B coefficients.
  7. Stop the running Coefficients dialog using the Stop button or choosing Run | Stop.
  8. Repeat the previous pasting and editing process to create the controls for the C coefficient. See the illustration in Step 2 for reference.
  9. Sketch a group-box enclosing all the controls on the Coefficients form.

gb-icon.bmp (25758 bytes)

  1. Inspect the new group-box and change its name to :coefficient-box and clear its title.
  2. Click on the Save All button to save your changes.
  3. Set focus to the Coefficients form and click Run | Run Form.
  4. Verify that all the up-down-controls are working, then stop the running dialog.

If the controls aren't changing numbers in the editable-text boxes, confirm that each has its partnering editable-text control name showing as the buddy-widget value in the Inspect window.

Add Button Controls to the Coefficients Dialog

  1. In the Coefficients form, sketch a default-button in the lower-left corner.
  2. Inspect the new button and change its name to :ok-button and title to ~OK.
  3. Sketch in a cancel-button on the right side of the OK button. Align the top edge with the OK button.
  4. Inspect the cancel-button and change its name to :cancel-button and its title to ~Cancel (its title starts as Cancel, without the leading tilde).
  5. Sketch a button on the right side of the Cancel Button. Align the top edge with the other two buttons.
  6. Inspect the new button and change its name to :test-button and its title to ~Test.
  7. Click on the Save All button to save your changes.

Activate the Test Button

The Test button allows users to test-draw a curve and make adjustments without leaving the Coefficients dialog.

  1. In the inspector of the test-button, click on the Events tab.
  2. In the test-button inspector, click on the on-change event and then, click on the Extended Editor button (the one with the three dots).
  3. In the coefficient-dialog buffer (which should be visible), edit the skeleton code for the on-change function coefficients-dialog-test-button-on-change to match the following:
(defun coefficient-dialog-test-button-on-change
    (widget new-value old-value)
   (declare 
     (ignore-if-unused widget new-value old-value))
   (when new-value
     (test-curve (parent widget)))
   (not new-value))
  1. Evaluate the coefficient-dialog-test-button-on-change function.
  2. Add the test-curve method to the same buffer.
(defmethod test-curve 
    ((dialog coefficient-dialog))
   (let* ((curve 
            (make-instance 'cycloidal-curve
              :a-coefficient 
              (value
               (find-component 
                 :a-coefficient-control
                 dialog))
              :b-coefficient 
              (value
               (find-component 
                 :b-coefficient-control
                 dialog))
              :c-coefficient 
              (value 
               (find-component 
                 :c-coefficient-control
                 dialog))))
          (curve-dialog (owner dialog))
          (doodler (owner curve-dialog)))
      (draw-curve (frame-child doodler) curve)))
  1. Evaluate the test-curve method.
  2. Save the coefficient-dialog buffer.
  3. In the coefficient-dialog buffer, click inside the cycloidal-curve text. Then, click Tools | Browse Class
  4. You should see the class browser dialog displayed with the information about the class cycloidal-curve.
  5. In the Class Browser dialog, click on the Direct Slots icon in the toolbar (the one with three horizonatl lines) and display the information.

ch5-2-clabr.bmp (574254 bytes)

We are following the convention of naming the accessor the same as the slot; slots shown here have the same names as their accessor functions.

Using the Class Browser

Use the Class Browser to quickly look up slots and methods of a class.

Click on the Methods tab now and you’ll see a list of the methods (including the accessors) for cycloidal-curve.

Displaying the Coefficients Dialog from the Curves Dialog

  1. In the General tab of the Project Manager dialog, select curve-dialog and click on the View Selected Code button.
  2. In the curve-dialog buffer, modify the curve-dialog class to add a slot to store the coefficient-dialog. It should match the following:
(defclass curve-dialog (dialog)
  ((curve-coefficient-dialog
    :initform nil
    :accessor curve-coefficient-dialog)))
  1. Now add the following close :before method to the same buffer.
(defmethod close :before ((dialog curve-dialog) &key)
  (let ((coefficient-dialog
           (curve-coefficient-dialog dialog)))
    (when (and (windowp coefficient-dialog)
                coefficient-dialog)
      (close coefficient-dialog))
    (setf (curve-coefficient-dialog dialog) nil)))

Since the curve-dialog creates the coefficient-dialog, it must also close it. The dialog must be explicitly closed since it is a pop-up window.

  1. Click on the Save All button on the standard toolbar to save your changes.
  2. Click Tools | Compile Project to compile your changes.
  3. In the Project Manager dialog, select doodler and click on the View Selected Code button.
  4. In the doodler buffer, add the user-close method.
(defmethod user-close ((window doodler))
  (let ((modal-dialog (modal-window)))
    (if* modal-dialog then
      (beep window)
      (pop-up-message-dialog window "Doodler"
        (format nil "~
         Close the ~a modal dialog before closing ~
         the Doodler."
         (title modal-dialog))
         warning-icon 
         "~OK")
       else
       (call-next-method))))

Since the Coefficients dialog is displayed modally, you cannot close the Doodler when the coefficient-dialog is displayed. Therefore, you must customize the user-close method for doodlers to prevent your users from closing the Doodler while the Coefficients dialog is displayed.

Activating the Add Button

  1. In the Project Manager, select curve-dialog and click on the View Selected Form button.
  2. In the curve-dialog form, inspect the Add button.
  3. In the Add button inspector on the Events tab, select the on-change event. Click on the Extended Editor button (the one with the three dots).
  4. In the curve-dialog buffer, change the on-change function (curve-dialog-add-button-on-change) to match the following:
(defun curve-dialog-add-button-on-change 
    (widget new-value old-value)
  (declare 
    (ignore-if-unused widget new-value old-value))
  (when new-value
     (add-curve (parent widget)))
  (not new-value))
  1. Now add the following add-curve, get-coefficient-dialog, and show-coefficient-dialog methods to the same buffer.
(defmethod add-curve ((dialog curve-dialog))
  (let* ((curve-list 
          (find-component :curve-list dialog))
         (default-curve (value curve-list))
         (curve (show-coefficient-dialog dialog
                 (if default-curve
                    (copy-object default-curve)
                    ;; else
                    (make-instance 
                      'cycloidal-curve)))))
    (when curve
      (setf (range curve-list)
            (append (range curve-list) 
                    (list curve))))))

(defmethod get-coefficient-dialog 
    ((dialog curve-dialog))
  (let ((coefficient-dialog 
         (curve-coefficient-dialog dialog)))
    (when (or (not coefficient-dialog)
              (not (windowp coefficient-dialog)))
      (setq coefficient-dialog
            (make-coefficient-dialog :owner dialog))
      (setf (curve-coefficient-dialog dialog)
             coefficient-dialog))
    coefficient-dialog))

(defmethod show-coefficient-dialog 
    ((dialog curve-dialog) 
     &optional (curve 
                (make-instance 'cycloidal-curve)))
  (let* ((coefficient-dialog 
          (get-coefficient-dialog dialog))
         (a-widget 
          (find-component :a-coefficient-control
            coefficient-dialog))
         (b-widget 
          (find-component :b-coefficient-control
            coefficient-dialog))
         (c-widget 
          (find-component :c-coefficient-control
            coefficient-dialog)))
    (move-window coefficient-dialog 
      (window-to-screen-units 
        dialog (make-position 10 10)))
    ;; initialize the value of the widgets
    (setf (value a-widget) (a-coefficient curve))
    (setf (value b-widget) (b-coefficient curve))
    (setf (value c-widget) (c-coefficient curve))
    ;; display the dialog as modal
    (when (pop-up-modal-dialog coefficient-dialog
            :stream (owner dialog))
    ;; if the user clicks on OK, change 
    ;; the new curve to
    ;; reflect the values shown in the dialog
      (setf (a-coefficient curve) (value a-widget))
      (setf (b-coefficient curve) (value b-widget))
      (setf (c-coefficient curve) (value c-widget))
      curve)))

add-curve initializes a new curve to the same values as the selected curve.

show-coefficient-dialog uses the pop-up-modal-dialog function to display the Coefficients dialog modally.

  1. In the curve-dialog buffer, select everything (Edit | Select All) and evaluate the selection (Tools | Incremental Evaluation).
  2. Click on the Save All button to save everything.
  3. Click the Run Project button to run the Doodler. Display the Curves dialog by clicking on the blue Curve button displaying a cycloid graph. In the Curves dialog, click on the Add button. Make sure that the Coefficients dialog is modal with respect all the other Doodler windows (meaning you cannot select another Doodler window until the Coefficients dialog is closed).
  4. When you are satisfied, click the Stop button or Run | Stop to stop running.

Activating the Edit Button

  1. In the Project Manager, select the curve-dialog and click on the View Selected Form button.
  2. Inspect the Edit button on the curve-dialog form. Switch to the Events tab if necessary.
  3. Select the on-change property. Click on the Editor button (the one with three dots). There is a default function -- return-t-from-pop-up-dialog -- already provided but it is not suitable for our purposes.)
  4. In the curve-dialog buffer, edit the on-change function (curve-dialog-edit-button-on-change) to match the following.
(defun curve-dialog-edit-button-on-change 
    (widget new-value old-value)
  (declare 
    (ignore-if-unused widget new-value old-value))
  (when new-value 
    (edit-curve (parent widget)))
  (not new-value))
  1. In the curve-dialog buffer, add the edit-curve method:
(defmethod edit-curve ((dialog curve-dialog))
  (let* ((curve-list (find-component :curve-list dialog))
         (curve (value curve-list))
         (range (range curve-list)))
    (when curve
      (when (show-coefficient-dialog dialog curve)
      ;; reset the range to force 
      ;; the scrolling list
      ;; to redisplay its curve information
        (setf (range curve-list) nil)
        (setf (range curve-list) range)))))
  1. Click on the Save All button on the standard toolbar to save your changes.
  2. Run the Doodler using the Run button or the Run | Run Project command.
  3. In the Doodler, click on the Curve button. In the Curves dialog, click on the Edit button. Notice that nothing happens.

Select the curve in the list box and click Edit again. This time the coefficients dialog will appear since you have selected a curve. When satisfied, click the Stop button to stop running the Doodler.

  1. In the curve-dialog buffer, enter the select-curve-warning method.
(defmethod select-curve-warning 
    ((dialog curve-dialog))
  (pop-up-message-dialog dialog "Doodler"
    "Select a curve first"
    warning-icon "~OK"))
  1. In the curve-dialog buffer, modify the edit-curve method to match the following.
(defmethod edit-curve ((dialog curve-dialog))
  (let* ((curve-list 
          (find-component :curve-list dialog))
         (curve (value curve-list))
         (range (range curve-list)))
    (if curve
       (when (show-coefficient-dialog dialog curve)
          ;; reset the range to force the 
          ;; scrolling list to redisplay
          ;; its curve information
          (setf (range curve-list) nil)
          (setf (range curve-list) range))
        ;; else
        (select-curve-warning dialog))))
  1. Select the whole curve-dialog buffer (Edit | Select All) and evaluate it (Tools | Incremental Evaluation). Then click on the Save All button to save your changes.
  2. Run the doodler using the Run button or Run | Run Project. In the Doodler window, click on the Curve button and then click on the Edit button. You’ll see a warning saying that you need to select a curve first. Click OK to accept the warning. Select a curve and try editing a curve.
  3. Your application will look something like this after adding, editing, and drawing the curves.

ch5-3-doodles.bmp (1191666 bytes)

When satisfied, click Run | Stop command to stop running the doodler.

Making the Delete Button Work

  1. In the Project Manager dialog, select curve-dialog and click on the View Selected Form button.
  2. Inspect the Delete button and select the Events tab.
  3. In the delete-button inspector, select the on-change event and click on the Extended Editor button (the one with three dots). The curve-dialog buffer will appear with some skeleton code in it.
  4. In the curve-dialog buffer, edit the on-change function (curve-dialog-delete-button-on-change) to match the following.
(defun curve-dialog-delete-button-on-change 
    (widget new-value old-value)
   (declare 
     (ignore-if-unused widget new-value old-value))
   (when new-value 
      (delete-curve (parent widget)))
   (not new-value))
  1. Now add the delete-curve method to the same buffer. Notice that the draw-all and select-curve-warning functions are reused here.
(defmethod delete-curve ((dialog curve-dialog))
  (let* ((curve-list 
          (find-component :curve-list dialog))
         (curve (value curve-list)))
    (if* curve then
       (setf (range curve-list)
             (remove curve (range curve-list)))
       (setf (value curve-list) nil)
             (erase-window (owner dialog))
       (draw-all dialog)
      else
       (select-curve-warning dialog))))
  1. Click on the Save All button on the Standard toolbar to save your changes.
  2. Click the Run button to run the Doodler. Add a few curves to the dialog using the Add button. Try using the Delete button to see how it works.
  3. When you are satisfied, click the Stop button to stop running the Doodler.

Handling a Double-Click

  1. In the Project Manager dialog, select the curve-dialog and click on the View Selected Form button.
  2. In the Curves form, inspect the curve-list, which is a single-item-list control.
  3. In the curve-list inspector, select the Events tab. Select the on-double-click event and click on the Extended Editor button (the one with the three dots).
  4. 98.    In the curve-dialog buffer, change the on-double-click function (curve-dialog-curve-list-on-double-click) to match the following:
(defun curve-dialog-curve-list-on-double-click 
    (dialog widget)
  (declare (ignore-if-unused dialog widget))
  (curve-list-double-click dialog widget)
  t) ;; Return t to accept the new value
  1. Now add the curve-list-double-click method to the same buffer:
(defmethod curve-list-double-click 
    ((dialog curve-dialog) widget)
  (declare (ignore widget))
  (edit-curve dialog))

    100. Click on the Save All button to save your changes.
    101. Run the Doodler using the Run button. Try double-clicking on a curve to edit it.
    102. When you are satisfied, click the Stop button to stop running the Doodler.
    103. Go on to Chapter 6. If you wish to, you can stop working on the tutorial now and return to it later. All the work you have done has been saved.

Copyright © 2001-2004 Franz Inc. All rights reserved.

Introduction Chapter 1 Chapter 2 Chapter 3 Chapter 4 Chapter 5 Chapter 6 CLOS Intro
Allegro CL version 8.0