Progress
Language Tutorial
for Windows


Putting the Progress Programming Model to Work

Just when you were progressing nicely, your managers at All Around Sports stop by to see you. They’re not too familiar with computers, and they have a request to make: “Can you show us an object interface? It doesn’t have to work, we’re just curious.”

You go back and review the template that shows the parts of a Progress procedure. You’ve learned about frames since the last time you used the template, and know that you’ll need to use a defined frame to organize your field-level widgets more precisely. So, the old first step, define widgets, breaks down into two new steps: define field-level widgets and define frames.

The new coding template has the following sections:

  1. Define field-level widgets.
  2. Define frames.
  3. Define triggers.
  4. Display widgets.
  5. Enable widgets.
  6. Block execution.
  7. Disable user interface (end the procedure).

Sometimes traditional programming is called top-down programming, because you define larger structures first and then define smaller and smaller components. In some ways, you can think of event-driven programming as bottom-up programming, because you define the smaller components before you define the larger components. The template above illustrates this by placing field-level widgets before frames. If you reversed the order, the code would not compile—Progress needs to define the small components before it can construct a larger containing component.

Similarly, when you rely on default frames, Progress cannot interpret triggers that reference the frames until the main code block compiles. Therefore, when you first learned about triggers, they came after your DISPLAY and ENABLE statements. More properly, triggers should come before the main code block, as shown in the coding template above. Since you will almost always use defined frames, you won’t run into any conflicts.

It’s time to put this template to work.

Envisioning an Interface

You decide that creating the main interface of the sales and inventory application is enough to satisfy the curiosity of your bosses. What should that first screen consist of? You make a short list:

Figure 3–4 shows the interface you’ll try to create.

Figure 3–4: A Simple Interface

Now that you’ve envisioned the interface, you can start coding the sections of the procedure to make it a reality.

Defining Field-level Widgets

You create the following code to define all of your field-level widgets. All of this code can be found in the file lt-03-07.p.:

/*1*/  DEFINE RECTANGLE rct-Border SIZE-CHARS 40 BY 7 NO-FILL 
         EDGE-CHARS 1.

/*2*/  DEFINE VARIABLE Name1 AS CHARACTER FORMAT "x(19)"
         INITIAL "A L L   A R O U N D" VIEW-AS TEXT.
       DEFINE VARIABLE Name2 AS CHARACTER FORMAT "x(19)" 
         INITIAL "    S P O R T S    " VIEW-AS TEXT.

/*3*/  DEFINE VARIABLE Username AS CHARACTER FORMAT "x(3)" 
         LABEL "Initials".

/*4*/  DEFINE BUTTON btn-Cust LABEL "Customers".
       DEFINE BUTTON btn-Order LABEL "Order Entry". 
       DEFINE BUTTON btn-Inv LABEL "Inventory".

/*5*/  DEFINE BUTTON btn-Exit LABEL "Exit". 

These notes explain how field-level widgets serve various functions in this application:

  1. Use the rectangle widget to create a large (SIZE-CHARS 40 BY 7) empty (NO-FILL) box with a one-character wide edge (EDGE-CHARS). The box makes the application title stand out.
  2. Create two variables to hold the application title. The FORMAT "x(19)" option specifies how many characters of display space Progress should allow the text widgets to occupy. The default is 8. You define these variables as text widgets because you are using the values as a title. The variables are read-only text.
  3. Create another variable to hold the initials of the user. Here, you need a fill-in field, but you don’t have to specify it as such because fill-in field is the default.
  4. Create three buttons that launch various functions of a sales and inventory application.
  5. Create the Exit button.
NOTE: Keep in mind that you can access online help information about a Progress keyword by highlighting the keyword and pressing the HELP key function (F1).

Define Frames

Your next step is to organize your widgets into frames. While you typically need only one frame per interface, here you use two because you don’t want the buttons to appear until the user has entered valid initials in the fill-in field. Here is the code:

With the DEFINE FRAME statement, you list the widgets you want contained in each frame. In the first frame, you want precise placement of each widget. The AT phrase allows you to place a widget at a specific ROW and COLUMN within the frame, not the window. Here, you place the title variables inside the rectangle widget and you place the fill-in field below the rectangle. In the second frame, the default spacing works fine, so you don’t need to use the AT phrase.

Define Triggers

You only need one trigger for now. When the user chooses any of the function buttons, you want to display the message “Sorry, that function is not yet implemented.” Here is the code:

ON CHOOSE OF btn-Cust, btn-Order, btn-Inv
DO:
  HIDE MESSAGE NO-PAUSE.
  MESSAGE "Sorry, that function is not yet implemented.".
END.  

As you can see, one ON statement can apply to many widgets. It can also apply to many events. The HIDE MESSAGE NO-PAUSE statement clears the default message area without pausing. It’s a good habit to always use this statement before sending a new message.

Displaying, Enabling, and Blocking

Here is the code that displays, enables, and blocks the interface:

/*1*/  DISPLAY Name1 NO-LABEL Name2 NO-LABEL Username WITH FRAME Frame1.

/*2*/  ENABLE Username WITH FRAME Frame1.

/*3*/  WAIT-FOR RETURN OF Username.

/*4*/  DISABLE Username WITH FRAME Frame1.

/*5*/  ENABLE ALL WITH FRAME Frame2.

/*6*/  WAIT-FOR CHOOSE OF btn-exit. 

Here are descriptions of each step:

  1. The DISPLAY statement displays the title variables without labels (NO-LABEL). Next it displays the fill-in field. Finally, by using the frame phrase (WITH FRAME), you tell Progress to use a frame you’ve already defined.
  2. Only the fill-in field in the frame is meant to have user interaction, so you enable it.
  3. You block execution until the user presses RETURN in the fill-in field.
  4. When the user presses RETURN, the application executes the code that follows the WAIT-FOR statement. Here, you disable the fill-in field from receiving further input.
  5. This statement serves to more precisely illustrate the function of the DISPLAY statement. As you can see, you do not need a DISPLAY statement to make the buttons appear-enabling the buttons makes them appear. Basically, you use the DISPLAY statement with data widgets to display both the widget and the underlying value of the variable or database field that the widget represents. If you had skipped the DISPLAY statement for the first frame, the values of the text widgets, “All Around” and “Sports”, would not appear.
  6. The ALL keyword tells Progress to enable all the widgets in the defined frame.

  7. You establish the condition that signals the end of the application—when the user chooses the Exit button.

It’s time to put all your hard work together and view the results. Perform these steps:

  1. Open lt-03-07.p.
  2. Choose Compile Run.
  3. Type your initials in the fill-in field and press RETURN. A row of buttons appears.
  4. Choose one of the buttons. The “Sorry, that function is not yet implemented” message appears in the default message area.
  5. Choose Exit to end the procedure.
  6. Press SPACEBAR to return to the Procedure Editor.

The complete procedure is shown below:

lt-03-07.p
/**********  DEFINE FIELD-LEVEL WIDGETS  **********/
DEFINE RECTANGLE rct-Border SIZE-CHARS 40 BY 7 NO-FILL.
DEFINE VARIABLE Name1 AS CHARACTER FORMAT "x(19)"
    INITIAL "A L L   A R O U N D" VIEW-AS TEXT.
DEFINE VARIABLE Name2 AS CHARACTER FORMAT "x(19)" 
    INITIAL "    S P O R T S    " VIEW-AS TEXT.
DEFINE VARIABLE Username AS CHARACTER FORMAT "x(3)" LABEL "Initials".
DEFINE BUTTON btn-Cust LABEL "Customers".
DEFINE BUTTON btn-Order LABEL "Order Entry". 
DEFINE BUTTON btn-Inv LABEL "Inventory".
DEFINE BUTTON btn-Exit LABEL "Exit".

/**********  DEFINE FRAMES  **********/
DEFINE FRAME Frame1
    rct-Border AT ROW  2 COLUMN 21 
    Name1      AT ROW  4 COLUMN 31
    Name2      AT ROW  6 COLUMN 31
    Username   AT ROW 11 COLUMN 34
        WITH SIDE-LABELS NO-BOX THREE-D.    
           
DEFINE FRAME Frame2 
    btn-Cust btn-Order btn-Inv btn-Exit
        WITH NO-BOX AT ROW 13 COLUMN 21 THREE-D.
           
/**********  DEFINE TRIGGERS  **********/
ON CHOOSE OF btn-Cust, btn-Order, btn-Inv
DO:
    HIDE MESSAGE NO-PAUSE.
    MESSAGE "Sorry, that function is not yet implemented.".
END.  

/**********  MAIN LOGIC  **********/
DISPLAY Name1 NO-LABEL Name2 NO-LABEL Username WITH FRAME Frame1.
ENABLE Username WITH FRAME Frame1.
WAIT-FOR RETURN OF Username.
DISABLE Username WITH FRAME Frame1.ENABLE ALL WITH FRAME Frame2.
WAIT-FOR CHOOSE OF btn-Exit. 

Practice Problems

If you feel like you need some practice creating interfaces, complete the exercise below. The filename listed next to the problem contains a sample solution. You can load the file into the Procedure Editor.

Problem 3-1: lt-03-s1.p

The procedure you just worked with, lt-03-07.p, creates a complete interface that follows the Progress programming model. Using the same techniques, you should be able to duplicate the interface shown below.


Copyright © 2004 Progress Software Corporation
www.progress.com
Voice: (781) 280-4000
Fax: (781) 280-4095