SIMPOL Documentation

Chapter 26. Using the SIMPOL Application Framework

This chapter will describe the general design of the SIMPOL Application Framework. The appframework.sml library provides a complete application framework that uses databaseforms.sml, formlib.sml, db1util.sml, uisyshelp.sml, and other libraries to allow the quick and easy creation of powerful database-oriented applications. It implements an application and appwindow data type, which together with various functions and helper types, assists the programmer to produce a reliable database-oriented application with very little effort. Typically a program based on the framework will create its own application object type that includes the application object from the framework, and which is type-tagged as application. To see the code for this in detail, look at the chapters in the Quickstart Guide that cover the Address Book and Ordering System samples. These samples are also included as part of the distribution, so all the source code is there to exploit.

The Design of the Application Framework

The basic premise behind the application framework is that most applications that work with a database will have numerous aspects in common. These include:

  • Displaying forms

  • Switching forms

  • Managing data sources

  • Managing tables

  • Creating, locking, unlocking, modifying, and deleting of records

  • Placing the cursor in the first viable control on a form when entering data-entry

  • Testing to see if a record has been modified, and prompting the user to save or discard it

  • Browsing through records

To that end, the application framework provided with SIMPOL does an excellent job. It contains a basic application type, that can be used as is, or which can be embedded into a more sophisticated application type. The appwindow type provides the necessary management for the one or more windows used by the application, provides a container for the database tables used by the window, and various services for setting the current table, record, index, etc. for the window.

This library includes the formlib.sml, and therefore has all of the features of that library including all of the lower level included libraries. This includes all of the dataform1, printform1, and DOM type families, plus most of the important functions for lists, formatting types as strings, and the support libraries for the UI and the file system. In this section we will specifically discuss the features specific to the appframework.sml.

Table 26.1. The Functions in the Application Framework
Function nameDescription
checkneedsave()Checks to see if the record has been modified. If it has, it prompts the user to save or discard and handles the result. After calling this function, the programmer must check the return value. If it is .true, they can continue whatever they are doing that would lose the current unsaved changes, otherwise they should abort the operation.
clearstatusbar()This clears the status bar after a specified delay (has a default value).
closewindow()This function is intended to be attached to the onvisibilitychange event of the embedded wxwindow object in an appwindow type. To handle the closing of the final window the programmer creates an event handler for the onexitrequest event of the application. If defined, it will be called from this function if the user is attempting to close the last visible window. Return .false to prevent the window closing.
defer()This function is typically called from any menu item or tool bar item event handler, in order to ensure that any changed data in the current control with focus has been written to the underlying field. The defer mechanism is necessary since menu and tool bar events take place before the onlostfocus event of a form control. Without the defer mechanism, the call to save changes to a record would fail to record any changes to the control that currently has focus. By using defer, the focus is cleared and the onlostfocus event is called to write the data while the defer() function in a separate thread waits a very short period and then re-calls the original function.
deleterecord()This function is designed to be assigned to both menu items and tool bar items as the onselect event handler. It expects the application object to be passed (or the derived application object as long as it is tagged application). It can also be called directly passing the appwindow object as the first argument. It will handle locking and deletion of the current record on the form, and will call the ondelete event handler if it has been assigned. This function is particularly tuned to cope with both auto-locking and explicit locking systems. It will use the status bar, if available, when telling the user if a record is unable to be locked, which is very important since in an auto-locking environment, when the dialog window vanishes it automatically attempts to place focus back on the form, which then tries to lock the record, leading to an uninterruptible cycle that will only frustrate the users.
duplicaterecord()This function is designed to be assigned to both menu items and tool bar items as the onselect event handler. It expects the application object to be passed (or the derived application object as long as it is tagged application). It can also be called directly passing the appwindow object as the first argument. It creates a new record and copies the current record into it. To make changes for unique indexes, assign a handler function to the onchangerecord event and test the record to see if it has been stored. If not, then it is a new record that has been duplicated.
findfirstfocusablecontrol()This function does exactly what it says. It retrieves the first focusable control on a form. This would be used in conjunction with placing the user in data-entry, in order to set focus to the first appropriate control in the tab order.
getappwindowfromwindow()Use this function to return the appwindow object from a wxwindow object. This situation occurs when a menu event takes place, since the object passed to the function is of type wxmenuitem, and not appwindow. This function needs to be paired with the next one.
getmenuitemwindow()With this function it is possible to retrieve the wxwindow object from a wxmenuitem object. When a menu event occurs, the object that causes the event is an item in the menu, so that is the type passed as the initial parameter to the function. Together with the previous function you can retrieve both the wxwindow and the appwindow objects.
gettableformatstrings()Use this function to retrieve an array of the field display format strings for a table that is part of the appwindow ring of tables. The array is in the order of the fields in the database table.
gettablesarray()Retrieves an array of tbinfo objects, one for each table opened in the appwindow's ring of tables. These objects are not specific to a parent object and can be used for transferring a set of tables from one component to another, so that both sections use the exact same set of objects. That is important so that any record objects selected are compatible to each other.
lookup()Call this function to look up a value in a database table against a specific index and if found, to return the record. If no matching record is found, then the return value is .nul.
modifyrecord()This function is designed to be assigned to both menu items and tool bar items as the onselect event handler. It expects the application object to be passed (or the derived application object as long as it is tagged application). It can also be called directly passing the appwindow object as the first argument. It will lock and modify the record that is currently displayed in the form. It will also place the user into data-entry in the first focusable control on the form.
newrecord()This function is designed to be assigned to both menu items and tool bar items as the onselect event handler. It expects the application object to be passed (or the derived application object as long as it is tagged application). It can also be called directly passing the appwindow object as the first argument. It will create a new record for the master table of the currently displayed form. It will also place the user into data-entry in the first focusable control on the form.
saverecord()This function is designed to be assigned to both menu items and tool bar items as the onselect event handler. It expects the application object to be passed (or the derived application object as long as it is tagged application). It can also be called directly passing the appwindow object as the first argument. It will save the record correctly and reset various state flags. It is important that this function be used for saving the record if the program is calling either the newrecord() or modifyrecord() functions..