Progress
Language Tutorial
for Windows


Defining Widgets

This section discusses the basic 4GL syntax that you use to define widgets. First, you’ll learn how to represent a database field or a variable as a data widget. Next, you’ll learn how to define buttons and rectangles. Finally, you’ll see how to use a frame to arrange your widgets inside a window.

Defining Data Representations

Recall that Progress represents database fields and variables in an interface as a data widget. The widget and the field or variable are separate. You can think of a data widget as a suit of clothes that a database field or variable can put on or change out of as the need arises. In other words, in one part of your application you might represent a particular field or variable as a fill-in field, while in another part you might use an editor widget.

Before describing how you dress up a field or variable as a widget, you need to understand the syntax for defining variables. This is a partial syntax.

SYNTAX
DEFINE VARIABLE variable-name AS datatype
  [ INITIAL constant ]
  [ LABEL string ] 

The following table describes the components:

Component
Description
variable-name 
A name you supply to uniquely identify the variable. The variable name must begin with an alphabetic character (A–Z, a–z).
datatype 
Describes the type of data stored in the variable.
The tutorial thoroughly covers data types in later chapters. As you have already seen, the CHARACTER data type indicates text data, INTEGER indicates integer data, and LOGICAL indicates TRUE/FALSE or YES/NO data.
INITIAL constant
Specifies a constant value assigned to the variable at definition time.
LABEL string
Specifies a label that Progress uses when it displays the widget. If you do not specify a label, the variable name is the default label.

So, the DEFINE VARIABLE statement defines a variable and allows you to define the default data representation for that variable. The Progress language element for specifying data widgets is the VIEW-AS phrase. This is the general syntax.

SYNTAX
VIEW-AS widget-type [ options ] 

The following table describes the elements of the VIEW-AS phrase:

Component
Description
widget-type
Specify the Progress keyword that indicates the appropriate data representation. The keywords are:

FILL-IN
TEXT
SELECTION-LIST
COMBO-BOX
RADIO-SET
TOGGLE-BOX
EDITOR
SLIDER
options
Specific widgets have options that let you define functional and display characteristics.

Note that VIEW-AS is a phrase, not a statement. This means that VIEW-AS can be attached to certain Progress statements to expand the function of the statement. When you attach the VIEW-AS phrase to a DEFINE VARIABLE statement, you are defining the default data representation of the variable as shown in this brief code example:

DEFINE VARIABLE Field1 AS CHARACTER VIEW-AS TEXT. 

Whenever Progress displays Field1, it displays the variable as a text widget. (Text widgets are typically used for labels and reports.) If you do not use a VIEW-AS phrase in the DEFINE VARIABLE statement, Progress displays the variable as a fill-in field.

You don’t have to stick with the default data representation, however. You can override the default widget for a variable or a database field by attaching the VIEW-AS phrase to a run-time screen output statement, like this DISPLAY statement shows:

DISPLAY Field1 VIEW-AS FILL-IN. 

Examine the code below, and load it into the Procedure Editor if you like:

lt-03-03.p
DEFINE VARIABLE Field1 AS CHARACTER INITIAL "Hello!" VIEW-AS TEXT.

DISPLAY SKIP(3) Field1 VIEW-AS FILL-IN
  WITH SIDE-LABELS NO-BOX CENTERED THREE-D.

ENABLE Field1.

WAIT-FOR RETURN OF Field1. 

NOTE: The THREE-D option is relevant only on a Windows client; it is ignored by a character client.

When you run the lt-03-03.p procedure, you see a fill-in field because the VIEW-AS phrase on the DISPLAY statement overrides the default VIEW-AS phrase of the DEFINE VARIABLE statement.

Defining Buttons

Button and rectangle widgets differ from data representations in that they are exclusively user interface components and are not related to database fields or variables. The button allows the user to execute a function directly and the rectangle is an interface decoration.

This is a partial syntax for the DEFINE BUTTON statement.

SYNTAX
DEFINE BUTTON button-name LABEL string 

Typically, you associate a button with a trigger in your code. The button then becomes a tool that lets a user explicitly execute a trigger.

Follow these steps for a demonstration of buttons and triggers:

  1. Open lt-03-04.p.
  2. Choose Compile Run. The interface, shown below, contains two buttons, Display Data and Exit:
  3. Choose the Display Data button. The trigger executes on the CHOOSE event of the button widget, and displays Field1 as a text widget.
  4. Choose Exit to end the procedure.
  5. Press SPACEBAR to return to the Procedure Editor.

Here is the code that created the display:

lt-03-04.p
    DEFINE VARIABLE Field1 AS CHARACTER INITIAL "Hello!" VIEW-AS TEXT.
    DEFINE BUTTON btn-Exit LABEL "Exit".
    DEFINE BUTTON btn-Data LABEL "Display Data".

    ENABLE SKIP(2) btn-Data SKIP(2) btn-Exit SKIP(2)
        WITH SIDE-LABELS NO-BOX THREE-D.

    ON CHOOSE OF btn-Data
    DO:
        DISPLAY Field1.
    END.

/*1*/  WAIT-FOR CHOOSE OF btn-Exit. 

The Exit button does not have a trigger associated with it. That’s because the procedure uses the CHOOSE event of btn-Exit to signal the unblocking response. Since this is a default response, the procedure doesn’t require a trigger and a programmed response.

Defining Rectangles

The basic syntax for defining a rectangle lets you decide the size of the rectangle, whether it’s filled or empty, and how wide the edge is.

This is a partial syntax for the DEFINE RECTANGLE statement.

SYNTAX
DEFINE RECTANGLE rectangle-name SIZE width BY height
  [ NO-FILL ]
  [ EDGE-CHARS width ] 

The steps below use the same code as the last exercise, modified to use a DEFINE RECTANGLE statement:

  1. Open lt-03-05.p.
  2. Choose Compile Run. The interface, shown below, contains two buttons:
    Display Rectangle and Exit:
  3. Choose the Display Rectangle button. The rectangle appears.
  4. Choose Exit to end the procedure.
  5. Press SPACEBAR to return to the Procedure Editor.

Here is the code that created the display:

lt-03-05.p
/*1*/  DEFINE RECTANGLE Rect1 SIZE-CHARS 12 BY 8 NO-FILL EDGE-CHARS 2.
    DEFINE BUTTON btn-Exit LABEL "Exit".
    DEFINE BUTTON btn-Rect LABEL "Display Rectangle".

    ENABLE SKIP(1) btn-Rect SKIP(1) btn-Exit SKIP(1)
        WITH SIDE-LABELS NO-BOX THREE-D.

    ON CHOOSE OF btn-Rect
    DO:
        DISPLAY Rect1 WITH NO-BOX.
    END.

    WAIT-FOR CHOOSE OF btn-Exit.  

As shown at point 1, the size of the rectangle is 12 columns (width) by 8 rows (height). The NO-FILL option makes the rectangle empty. The EDGE-CHARS option specifies a border that’s two characters wide. The trigger executes on the CHOOSE event of the btn-Rect widget, and displays a rectangle.

Defining Frames

A frame is a container for widgets. Frames allow you to organize data, action, and graphic widgets. Data, action, and graphic widgets that can be placed in a frame (or dialog box) are called field-level widgets.

You cannot place widgets in a window unless they are first contained in a frame widget. (One exception: menu bars go directly into the window.) If you don’t specify a frame, Progress creates one for you. This frame is called the default frame.

Follow these steps for a demonstration of the default frame:

  1. Open lt-03-06.p.
  2. Choose Compile Run. The interface you see is the same “Hello Progress World!” interface, except that a graphic border surrounds the fill-in fields. The graphic border shows the area of the default frame follows:
  3. Move input focus to Field3 and press RETURN to end the procedure.
  4. Press SPACEBAR to return to the Procedure Editor.

Here is the code that created the display:

lt-03-06.p
    DEFINE VARIABLE Field1 AS CHARACTER INITIAL "Hello".
    DEFINE VARIABLE Field2 AS CHARACTER INITIAL "Progress".
    DEFINE VARIABLE Field3 AS CHARACTER INITIAL "World!".

    DISPLAY SKIP(1) Field1 SKIP(1) Field2 SKIP(1) Field3 
/*1*/    WITH SIDE-LABELS CENTERED THREE-D.

    ENABLE Field1 Field2 Field3.

    ON ENTRY OF Field3
    DO:
      MESSAGE "Press Return in Field3 to exit the procedure.".
    END.

    WAIT-FOR RETURN OF Field3. 

In the code you saw earlier, the DISPLAY statement included the NO-BOX option, which suppressed the default frame border. Since the option is not included here, as shown at point 1, the border appears.

The DEFINE FRAME statement allows you to name a frame and list the field-level widgets it contains. You also have several options for controlling the arrangement of the widgets within the frame, such as the SKIP option, which you have already seen.

Here is a partial syntax.

SYNTAX
DEFINE FRAME frame-name
  form-item ...
    [
      WITH
        [ SIDE-LABELS ]
        [ NO-BOX ]
        [ CENTERED ]
    ] 

The following table describes the elements of the DEFINE FRAME statement:

Component
Description
form-item 
Form items can include database fields, variables that have been previously defined, buttons, rectangles, and SKIP options.
Frame phrase (WITH)
The options shown at the bottom of the syntax diagram make up what is called the frame phrase. The frame phrase, which begins with WITH, lets you specify options that affect the frame itself or all the widgets in the frame as a group.

The frame phrase has other important applications outside of the DEFINE FRAME statement. The frame phrase can be attached to statements that output data to the screen to:

This is a partial syntax for the frame phrase.

SYNTAX
WITH FRAME frame-name 
  [ SIDE-LABELS ]
  [ NO-BOX ]
  [ CENTERED ] 

In the following example, the DISPLAY statement uses a frame phrase to alter the characteristics of a default frame:

DISPLAY Field1 WITH SIDE-LABELS NO-BOX CENTERED. 

When you use a frame phrase without specifying a frame name, Progress applies the phrase to the default frame.

Defining Frame Families

A parent is a widget that contains or owns other widgets. In addition to parenting frames to windows, as described in the previous section, you can also parent frames to other frames. When you parent a frame to another frame, you create a  frame family. A frame that is parented by another frame is called a child frame and a frame that parents another frame is called a parent frame. Frames that are parented to the same frame, in the same generation, are called sibling frames.

By defining a frame family, you create a relationship among the descendant frames that is different from that of frames parented to the same window. For example, you can:

Child frames behave like field-level widgets of the parent frame. Child frames must be positioned physically within the parent frame. When you specify a location of a child frame, the options you specify are with respect to the parent frame, not the window. However, the field-level widgets of child frames are not controlled by the parent frame. You must explicitly display, enable, and disable field-level widgets of child frames.

To define a frame family, set the FRAME attribute of the child frame to the widget handle of the parent frame. As shown in this example, frame child1 is a child frame of frame parent1 and button btn-Exit is a field-level widget of frame child1:

DEFINE BUTTON btn-Exit LABEL "Exit".
DEFINE FRAME parent1 WITH TITLE "parent1" SIZE 40 BY 10
  AT ROW 3 COLUMN 3.
DEFINE FRAME child1 btn-Exit WITH TITLE "child1" SIZE 20 BY 5
  AT ROW 3 COLUMN 3.

FRAME child1:FRAME = FRAME parent1:HANDLE.

DISPLAY WITH FRAME parent1.
ENABLE ALL WITH FRAME parent1.
ENABLE ALL WITH FRAME child1.

WAIT-FOR CHOOSE OF btn-Exit. 

You can use frame families to create useful interactions among frames, but they do carry some restrictions that are important to remember. For example:


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