DesignBais Tip – The Art of Indirection

Almost all of us are familiar with selecting data in BASIC programs. The code looks something like this:
STMT = \SSELECT CUSTS\
STMT := \ WITH STATE "\ : STATE.CHOICE : \"\
STMT := \ AND WITH BAL > "0"\
STMT := \ BY NAME\
EXECUTE STMT CAPTURING OUT RTNLIST LIST
*… loop on the list and process records
In DesignBais, many of the selections we use are defined in a Selection Process. The results are then used for on form reports, dropdown lists, and other purposes. This interesting bit of indirection takes a moment to understand. We don’t build a form and write the selection code into the form – this is the way most BASIC programs are written. We do define selection processes, then we build our forms and call to selection processes from the forms.

Digression #2: This may remind a lot of people about the old Proc days before BASIC had an Execute or Perform statement. Back then, all selections needed to be performed outside of BASIC, and all we did in BASIC was loop through whatever list was passed to us. Many applications are still written with external selection routines, but few of us use a tool like the DesignBais Selection Process form to define so many of these in detail.

Digression #2 1/2: For anyone not familiar with Selection Processes, you don’t need to actually define the selections here, you can select all of your data the same way you do now in your apps. Personally I think it’s preferable to use the same selection code for your character interface and your graphical interfaces. A Selection Process is two tools in one: It’s a handy tool to define selection criteria in a GUI, and it’s a graphical way to define a consistent selection interface for your users. It allows for paging, refinement or narrowing down of the data selected, and it’s a nice way to allow multiple items to be selected where that’s valid. It’s not a required component but one of convenience. If you have extended needs which go beyond the capabilities of the Selection Process provided in DesignBais, there’s nothing wrong using your existing code to generate the data and defining your own standard dialogs for the user interface.

Another bit of indirection comes when you want to intercept an operation in order to add some other logic. For example, let’s say you have a set of MV Input fields and you want to set the header of the first field to popup a Selection dialog. To do this, simply put the name of the selection process in the Hdr Process for that field. It would look like SOMEFILE_SELECTION.NAME. Now let’s say you want to disable this selection process when you’re in inquiry mode – or a similar mode where you just don’t want the user to select items. (You may or may not want people doing a lookup for data for a field they can’t change – sometimes people want to do lookups even if they know they can’t change the current record.) Assuming you want to disable the header, here’s where we handle this indirectly. Rather than calling SOMEFILE_SELECTION.NAME directly, call to a program which catches the MV_HEADER event. Then in the event handler use this:
IF DBENQUIRY.MODE THEN RETURN ; * yes, Enquiry with an ‘E’
PROCESS.STACK = "SOMEFILE_SELECTION.NAME"
RETURN

If using inquiry mode, the code simply returns without taking action – thus disabling the function. Otherwise we perform exactly the same action that was originally hard-coded into the field Hdr Process. In this bit of indirection, we are capturing an event and then using Process.Stack to pass the event somewhere else for processing. In other enviroments this is called a Proxy – your program serves as a proxy to cause something else to occur, rather than the control on the form directly taking some hard-coded action.

Digression #3: Once you’ve used Process.Stack a few times you may start thinking of many uses for it in your app.
– It can launch dialogs more complex than the standard DBI.G.DIALOG.
– It can be used to swap forms imperceptably. If the user enters the ID for a person instead of a company in Customer Maintenance, you can swap the current form with one more suited for that specific type of data. When they save the data they go back to the normal Customer Maintenance form without ever really knowing they left. This could be preferable to creating a single form that handles all kinds of data.

Can a checkbox be disabled? No, not directly. However, you can use the technique described in another tip for radio buttons: hide the checkbox, and replace it with an image that won’t accept focus. As you see this doesn’t do exactly what you wanted but the exact same net effect is achieved by going at it indirectly.

Leave a Reply