613-518-1166 info@zimdatabases.com

ZIM Development Center (DC) for Zim 7

Program Organization and Event Driven Applications

< All Topics

Program Organization and Event Driven Applications

Older Program Organization

With older versions of Zim, all windows were modal. Once a window was opened, all user interface events occurred within and applied to that window until another window was opened or until the initial window was closed. As a result, a typical Zim program was written to manage a single window and looked like this:

Procedure TypicalProgram ( )
%% Start
window open MyWindow  % open the window
form open dMyDisplay   % open form/display
form set exit …   % set exit and/or transmit keys
% other processing such as initializing the forms
form display

%% Middle
while
form input
% code here would react to different user interface
events. E.g.,
case
when $transmitkey = “Escape”
break
when $transmitkey = CtrlF4
break
when …
endcase
endwhile

%% End – other clean-up code here
window close MyWindow
EndProcedure

As illustrated, the code can be broken down into three major sections. In the “Start” section, the window and form or display is opened and initialized. The “Middle” section is composed of a loop that gets the next user interface event (using FORM INPUT) and then acting on that event. Finally, the “End” section closes the window and does any other clean up before the program is completed.

Impact of Event Driven Applications

In event-driven applications, several windows can be open at any time and the user can select the window with which they wish to interact. The older organization for programs does not handle this situation because the “Middle” section assumes that each user interface event is targeted at the window opened in the “Start” section. As a result, the organization that is best suited to event driven applications is to create a single program that contains an event loop and have separate programs to manage each window. Programs that manage a window are organised as servers to respond to a particular event and then to exit immediately.

Organization for Event Driven Applications

If our application has three windows that can be opened (MyWindow, ThatWindow, and AnotherWindow), then the event loop program looks like this (we have also replaced FORM INPUT with pGetAction since pGetAction can be used in both the event driven and application driven cases):

Procedure EventLoop () \
local(vlStatus, vlAction, vlTargetWindow, vlCurrWindow)

while
pGetAction (vlStatus, vlCurrWindow, vlAction, vlTargetWindow)

%% Dispatch action to appropriate window
case
when vlTargetWindow = “MyWindow”
HandleMyWindow (vlStatus, vlAction)
when vlTargetWindow = “ThatWindow”
HandleThatWindow (vlStatus, vlAction)
when vlTargetWindow = “AnotherWindow”
HandleAnotherWindow (vlStatus, vlAction)
endcase
let vlCurrWindow = vlTargetWindow
endwhile

EndProcedure

After each call to pGetAction, the appropriate window management program is called. Now getting the next event/action is centralized in one program which dispatches the actions to the appropriate window management program.

Note: There is a problem with this event loop program. As written, it does not handle getting the first window open nor does it provide any means to stop the application. We resolve this problem in the next section.

A window management program for MyWindow can be organised as follows:

Procedure HandleMyWindow (out vlStatus, in vlAction)
on error
let vlStatus = “ERROR”
return
endon

let vlStatus = “OK”

%% This code corresponds to Start section above
if $IsWinOpen (“MyWindow”) = $false
window open MyWindow  % open the window
form open dMyDisplay  % open form/display
form set exit …   % set exit and/or transmit keys
% other processing such as initializing the forms
form display
endif

%% Exit action contains code from End section above
case
when vlAction = “Exit”
%% other clean-up code here
window close MyWindow

%%Other cases correspond to code from Middle section
when …
endcase
EndProcedure

Handling State Information

Typically, while a window is open, the application needs to maintain state information about the window. For example, if the window is designed for data entry, you need to keep track of whether you are in “add” mode (that is data being entered is for new database records) or “change” mode (you are editing existing data). You also need to keep track of any changes that have been made. In the older program organization, this state information was usually stored in local variables. In the new organization, this does not work since the application enters and exits the window management program for each user interface event. Thus, it is usual practice to create structures (i.e. forms intended for data storage rather than display) to hold any state information.

More General Action Dispatching

As written, our event loop needs to know, in advance, which windows can be open. This makes this code very application specific and it also means it must be changed when another window is added to the application.

We also need to resolve the problem of how the event loop starts and how it ends. Applications typically have a main window — that is, the window that first appears when the application begins. We’ll assume that MyWindow is the main window of this application.

The following code resolves this problem as well as dealing with the issue of how the application begins and ends.

Procedure EventLoop () \
local(vlStatus, vlAction, vlTargetWindow)

%% Launch the main application window.
HandleMyWindow (vlStatus, “ENTERWINDOW”)

let vlAction = “”

while
%% Make sure main app window is still open.
%% If not, then exit the loop and clean up.
if $IsWinOpen (“MyWindow”) = $false
break
endif

%% Event loop exits when main window is no longer open.
pGetAction (vlStatus, vCurrProcess.WindowName, \      vlAction, vlTargetWindow)
%% pDispatchAction makes the event loop independent
%% of window names.
pDispatchAction (vlStatus, vlAction, “”, 0, \
vlTargetWindow)
endwhile
EndProcedure

The changes in the event loop program are

  • Before the actual loop begins, HandleMyWindow is called with the action “ENTERWINDOW”. This has the effect of opening MyWindow
  • Inside the event loop, a check is made that the main window is still open. If it is not open, the event loop is terminated.
  • Instead of dispatching the action to specific windows and specific window management programs, this version of the event loop uses pDispatchAction to dispatch the action to the appropriate program.

The window management program is as follows:

Procedure HandleMyWindow (out vlStatus, in vlAction)
on error
let vlStatus = “ERROR”
return
endon

let vlStatus = “OK”

if $IsWinOpen (“MyWindow”) = $false
window open MyWindow % open the window
form open dMyDisplay % open form/display
form set exit … % set exit and/or transmit keys
% other processing such as initializing the forms
form display
%% Register the window with the process manager.
pRegisterProcess (vlStatus, “Main Window”, \
MyWindow”, “”, “App’n Window.”, “HandleMyWindow”, \
cChildClass, $NULL, stMyWindow.stProcessId)
endif

case
when vlAction = “Exit”
%% other clean-up code here
window close MyWindow
pUnRegisterProcess (vlStatus, \
stMyWindow.stProcessId, “”)

%% Remove this window from the process list.
when …
endcase
EndProcedure

The major changes here are as follows:

  • When the window is opened, a call is made to pRegisterProcess. This makes the Framework aware of this window and the name of the program (HandleMyWindow) that manages it. pRegisterProcess also assigns a process id to this window and returns it in stMyWindow.stProcessId (stMyWindow is the name of the state structure we use in this program).
  • When the window is closed, a call is made to pUnRegisterProcess to remove the window from the process list.
Was this article helpful?
0 out Of 5 Stars
5 Stars 0%
4 Stars 0%
3 Stars 0%
2 Stars 0%
1 Stars 0%
How can we improve this article?

Submit a Comment

Your email address will not be published. Required fields are marked *

Table of Contents