In the previous issue of Universal Thread Magazine we presented the TierAdapter Framework and gave a brief summary of its history and some of its basic features. In this second issue of the series about the framework, we review the Demo application, the way it works and the main features it provides, so in the future issues we can explain how to implement a solution.
Remember that you can download the complete TierAdapter and demo application, including source code, from the framework's main page at SourceForge, in two versions: 2.19 for VFP8; and 2.21, equivalent to the previous one, but optimized for some of the new features of VFP 9.
Installing and starting the demo
The package you download from SourceForge can be installed by simply creating a new folder and decompressing the .zip file provided into it. Two subfolders will be created, one called "Comun", which containes the framework, and another one called "Demo" which contains the application we are going to analyze. If you look into the Demo folder, you will see a number of .ini files that contain information related to the location and the way of accessing the database. Let's remember that the database on which the Demo is based is Northwind (both the one in SQL Server and the one that comes with VFP), and the database with system data located at Demo\Data\taSystem.dbc which contains the definition of users, groups, main menu for the demo, etc., which we will analyze in more detail later on.
These .ini files are referred to in doGeneral.prg and doSystem.prg (both within the folder Demo\DataTier), which are instances of the business tier of each application, pointing to the corresponding data source.
The reference is established as follows:
In doGeneral.prg, the property "cIniFileName" indicates the name of the file that will be used.
cIniFileName = "doGeneral.ini"
Next, let's take a look at the contents of the file "doGeneral.ini", configured to connect to different data sources.
Northwind in SQL Server
[Backend] cAccessType=ADO cDataBaseName= cStringConnection=DRIVER=SQL SERVER;SERVER=(local);DATABASE=Northwind;UID=;PWD=;trusted_connection=yes cBackEndEngine=SQLOLEDB
Northwind in VFP
[Backend] cAccessType=NATIVE cDataBaseName=C:\PROGRAM FILES\MICROSOFT VISUAL FOXPRO 9\SAMPLES\NORTHWIND\Northwind.Dbc cStringConnection= cBackEndEngine=
Check that doGeneral.Ini contains the data required to establish a conection with the database to be used. Once this has been established, from the VFP command window, go to the folder "Demo", and there, type:
Do source\main.prg
to start the Demo.
The different execution modes
TierAdapter can run in two different modes: Development and Production. The corresponding mode is determined automatically once the application is started. At this moment, the correct value is stored to the property lDebugMode, according to the following criteria:
_SCREEN.oApp.lDebugMode = Version( 2 ) > 0 And File( "debug.ini" )
In development mode, the startup screen is omitted, as well as the Login screen; the user is automatically logged in as "Admin (Develop)". In this mode, there is an additional menu, "{TierAdapter Developer}", which we will analyze a little later. Finally, the development environment is restored once the application stops executing.
In Production mode, we have a welcome screen and the user authentication, as we will see later.
Note: You can easily change to Production mode, by renaming the file debug.ini provided with the Demo.
Startup screen
This screen is based on the class "msSplashScreen" contained in "msSplashScreen.vcx", which should be subclassed for specialization in each application. The referrence to the subclass is found in the properties cSplashClass and cSplashClassLibrary of the application object (which we shall see in more detail soon). Next, we see how these properties are configured in DemoApp.prg (subclass of msApp.prg).
cSplashClass = "DemoSplashScreen" cSplashClassLibrary = "source\DemoSplashScreen.vcx"
In the following figure we see the general look of this form.
Figure 1: Startup form
Login screen
The login window lets us identify as users of the system. The framework's security system lets us define users and user groups in the system, and assign them access privileges to the different menu items. The rights are cumulative, that is, if a user belongs to more than one group, he accumulates the privileges of both; it is also possible to add individual rights. It should be noted that any user who has administrator privileges has unrestricted access to all the options in the system. Internally, passwords are saved encrypted; they are also protected by a field of "checksum" type, to avoid the manipulation of this data from outside the system.
Once the user name and password have been validated, the framework constructs the application menu, according to the corresponding access rights.
Figure 2: Login screen
You can test access in the Demo with the different users we have already created. For all of them, the password is empty. If you want to see a list of existing users, click on the "..." button located on the right of the TextBox where the username is entered.
The main system menu
The main menu of the Demo consists of several submenus. The first one (from left to right) is the "Tools" menu. This submenu is part of the framework; through it, among others, we can close the user session (logout) to restart (login) with a different name, and we can re-show the toolbar in case we closed it accidentally. You can see its design by opening "taMenu" from the tab "Other" in the project "taDemo".
Figure 3: Main system menu in "Production" mode
The next two submenus of "Demo" are "Tables" and "Security". These are menus for the application itself, and are constructured dynamically when it starts, after user login, and on the basis of his access privileges. The information required for this is stored in the tables "Access.dbf" and "UserAccess.dbf".
The last two submenus of the "Demo" are "Window" and "Help". These complement the main menu, making it possible to cycle through the open windows, cascading them, accessing help, etc. You can see their design in detail, opening "taTrailerMenu" from the tab "Other" of the "taDemo" project.
As we had already indicated, if we start the Demo in development mode, we will have one additional submenu: the submenu {TierAdapter Developer}.
Figure 4: Main system menu in "Development" mode
Located between the submenus "Security" and "Windows", it allows us to execute some script, cancel or suspend execution, start the debugger, and other features which are useful for the developer. You can see the details of its design by opening "taDevelopTools" from the tab "Other" in project "taDemo".
All the submenus we named can be redesigned or eliminated; in this case, it is the responsibility of the developer to maintain the basic functionality required for the correct working of the application. In case you want to design your own menus, you can do it; then, you have to indicate the name of your menus in the properties cToolsMenu, cDeveloperMenu and cTrailerMenu. We will now see how these properties are set in msApp.prg:
cToolsMenu = "taMenu.mpr" cDeveloperMenu = "taDevelopTools.mpr" cTrailerMenu = "taTrailerMenu.mpr"
The object "taPickOne"
This object was designed with the purpose of allowing the user to select a record from a table associated with the object, through its code or the first letters of its description. For example, let's see the form "Orders":
Figure5: The object taPickOne
We have the basic information for an order. Immediately underneath the Order ID, we see information about the client. In the Northwind database, the client data is found in table Customer, which has a unique customer ID (CustomerID) and a descriptive name (CompanyName). With this, we have excellent conditions for using the taPickOne object.
In case we don't exactly remember the client code, but we do know the first few letters of his name, we can type this in the right part of the taPickOne object. Let's see in the following image, how the object would react if we type a letter "B", followed by Enter:
Figure 6: The taPickOne selection list
As we can see, the object takes care of going to the table and showing us a list of those clients whose CompanyName starts with "B". All we have to do is move within the list and select the desired client. Once selected, the object will bring us all his data and fill out the code on its left part.
Additional features of the taPickOne
If we don't remember the exact client code, nor the starting letters of his name, taPickOne gives us yet another possibility, which consists of right-clicking on it. In the following image, we can see what happens:
Figure 7: The taPickOne context menu
As we can see, a small context menu is opened, which offers us three options. The first is to access the client form (assuming one has already been selected), and completing the data. The second is to go to the client selector, where we can refine the search according to the parameters which it gives us, and, once one is selected, its data is returned so that it can be completed in the taPickOne. The third option allows us to close this context menu without executing any of the previously described options.
The xMenu function
The xMenu function (see xMenu.prg) allows us to easily create a context menu, passing, as a parameter, a list of options separated by colons. These functions will show us the menu and give us, as a return value, the number of the selected option. We have already seen the xMenu in action in the previous image (Figure 7), when we saw the additional features of the taPickOne. Let's now see the code with which it was invoked, and how to process the integer value which is returned in the variable lnOption.
Local lnOption As Integer lnOption = xMenu( "\<Form;\<Search") Do Case Case lnOption = 1 Do Form Customer Case lnOption = 2 Do Form CustomersSelector Otherwise * Exit. EndCase
The DatePicker and DateTimePicker objects
These objects, as you can guess from their names, allow us to easily type a date or a datetime, with additional help from a calendar. Let's see the object in action:
Figure 8: The object DateTimePicker in action
As we can see, we have the possibility of moving from month to month, through the calendar, and we see the current date, date(), highlighted (in red) and with a circle with a grey background, the day we have selected (in the previous image, both are the same, namely, day 10).
We have to note that this object is developed 100% in VFP code, and that we have downloaded it from one of the many sites of VFP code exchanges which exists on the Internet, simply adjusting some of its features to integrate them into the framework. Unfortunately it didn't say who the authors were, but we hereby wish to thank them.
The FastEdit object
This object, based on the base class CommandButton, has the task of putting a record, that was in No Edit state (for example, using the F7 key or the corresponding button) into the Edit state, without using the Open (F3) button, which would force us to repeat the entire selection process. Let's see how cmdFastEdit looks in the product form; I invite you to open a record from any product both ways, to appreciate the function of this object.
Figure 9: The FastEdit object
List of errors
In the previous issue, when we listed the features of the toolbar buttons, we indicated that the action carried out by the button "Close" was precisely to "close the form", but, after reading it again, we decide to reformulate this definition, since we consider that its behaviour would be better described as "putting the form into a wait state", since what is actually closed is the Edit state of the current record.
Conclusion
The idea of this second note about the TierAdapter was to show you in detail the main visible features which the framework gives us, with the idea that in the future issues, we will write in more detail about their implementation. We encourage those who are interested to review the source code, both of the Demo application and of the framework itself.
An interesting note is that, for example, the Product form that you saw in the previous image, which is totally functional, doesn't have a single line of code. You don't believe it? Well, while you check it, we will say "good-bye", until the next issue, where we will see the inside of the framework.
See you later!