Skip to content

Creating a Modal Popup Object

Here is the approach for designing and creating a modal task. First, you define the problem and design an interface to perform the task. Let's say that we need to know if it is proper to accept overtime hours. Our interface might look like the following:

Object Name:
    overtime
Function:
    ApproveOvertime
    returns Boolean
Return:      
    True if approved, False if denied

This is all we need to know to use this object in our program. The procedure initiating the modal task would look like the following:

Procedure Process_Hours number iTotalHours
    Boolean bResponse
    Number nOTHours

    If (iTotalHours > 40) Begin
        Get ApproveOvertime of oOvertime to bResponse
        If (bResponse) ;
            Move (iTotalHours - 40) to nOTHours  // hours approved
        Else ;
            Move 0 to nOTHours  // hours not approved
        Move 40 to iTotalHours
    End
    Send EnterHours iTotalHours nOTHours
End_Procedure

At this point, we only worry about the interface. We have an object named overtime that understands the message ApproveOvertime. It will perform a task and return a result. At this level, this is all we need to know. We do not even know if the task involves user interaction or not. This is the responsibility of the task object. That level of detail should be hidden from the rest of the program (it is encapsulated).

We will look at three completely different methods of handling the task. These are all valid and completely interchangeable.

Option 1: Non-user-interface - Return an answer based on existing data.

Object oOvertime is a cObject  // use a simple class
// Do not allow if employee.ot_type = "S" (salaried)
Function ApproveOvertime returns Boolean
    If (Employee.ot_type = "S") ;
        Function_Return False
    Else ;
        Function_Return True
End_Function
End_Object

Option 2: Pass the buck chain wait to another program which may or may not perform a UI task.

If it is a UI task, it will be modal since a chain waited program cannot interact with its parent program. This method is not necessarily recommended. It is included because this is a method that procedural DataFlex developers use all the time.

Object Overtime is a cObject
Function ApproveOvertime returns Boolean
    Chain_Wait "ot_pgm" export_files
    // use some time-honored procedural trick to figure out what happened
    // in the chain-waited program and return a status_value.
    Function_Return status_value
End_Function
End_Object

Option 3: Require user input - Create and use a modal popup object.

To do this, we must do the following:

  1. Make sure the object is a modal-popup object. This is simple—we should base the object on the ModalPanel or dbModalPanel class.
  2. Pop up the object. We send the message popup to do this.
  3. When finished with the object, send close_panel.
  4. Figure out what happened and return a status value.

You could do this as follows:

Object Overtime is a ModalPanel
    // we use this to track the return value
    Property Boolean pbOvertimeOk

    Set Label to "Allow Overtime?"
    Set Size to .. ..

    // note that modal panels will locate automatically
    // Let's assume that OT_is_Good and OT_is_Bad should complete the popup
    Procedure AcceptOk
        Set pbOvertimeOk to True   // mark this property as OK
        Send Close_Panel           // and close the panel
    End_Procedure

    Object oOTButton is a Button
        Set Location to .. ..
        Set Label to "OT is OK"
        Procedure OnClick
            Delegate Send AcceptOk  // we define this message
        End_Procedure
    End_Object

    Object oNoOTButton is a Button
        Set Location to .. ..
        Set Label to "No OT"
        Procedure OnClick
            Delegate Send Close_Panel  // this is understood by ModalPanel
        End_Procedure
    End_Object

    Function ApproveOvertime returns Integer
        Boolean bResponse
        Set pbOvertimeOk to False  // set a default value of no OT
        Send Popup                  // This may change pbOvertimeOk
        Get pbOvertimeOk to bResponse
        Function_Return bResponse
    End_Function
End_Object

This example presents the suggested structure for all modal pop-up objects. Please note the following:

  • If the object is modal (based on ModalPanel, dbModalPanel, or the property Modal_State is set to true), the object is invoked when it is sent the message popup.
  • Whenever possible, do not send the popup message from outside of the object. Instead, create a public message that performs the desired task. In this sample, our task was not to pop up a modal object; our task was to determine if overtime was allowed. An interface should reflect an object’s purpose, not its function.
  • A modal panel is closed by sending the message close_panel. This message is also sent automatically by other operations like clicking on the Close button in the panel’s upper right-hand corner.

The best way to determine what happened within a modal panel is to have object data (i.e., a property) which can be inspected after the popup is complete. In this sample, we created a status property which was initialized to 0 upon start-up and is only set to 1 if the Ok button is selected.

Finally, notice that this was designed starting with the interface. The object that started this (invoked the prompt) is not responsible for any of this. It simply asks an object a question through an agreed-upon interface. It has no idea how the response will be generated. It is asking a question of a black box.

If you design your interface first and then worry about implementation, everything becomes much easier.

See Also