Photo by nasrulekram
This week’s Uncle Pete’s corner covers the use of the Open Source Default Manager Class. This is an introductory into the Open Source Initiative for anyone that hasn’t worked with projects from other developers before, as well as show some uses for the default manager class.
What is the Open Source Initiative
I am not going to bored you with a lot of details, you can read my original post when I started the initiative here. The short version is:
- I have developed quite a bit of foundation code that I use in most of my projects
- It took me 18 months and several projects to do it
- I was a 3rd party vendor back in the day with clarion products and never want to be a 3rd party vendor again!
- Over the years many great developers have contributed to my knowledge and success. If you use my open source code and it makes your products and life a little better than I have paid it forward!
- If it convinces you that I would be a valueable asset to your project, even better!
Download the Open Source Demo Application
You can download bits and pieces of the Open Source code by going to the articles that cover those specific classes, however the best way is to download the Open Source Demo Application which include all of the open source code in one project file along with a few other tidbits and examples, you will find examples and demo from many of my other articles as well.
The download file is a zip file made by the Project backup function in WinDev, if you haven’t used this function it is a handy way to make a copy of your entire project. You can use the restore function to restore the zip file you just downloaded.
The first window of the restore wizard just lets you know what you are about to do
On the next screen, point to the zip file you just downloaded.
And on the 3rd where you would like the project to be located at. Note: Be source to create a subdirectory under your projects directory, the project restores in the directory provide here so you don’t want it to be in the parent of your projects folder.
And finally you are done! The Project is restored and can be opened in the IDE.
Running the Open Source Demo Application
Now that you have downloaded and restored the project, go ahead and open it in the IDE, it comes complete with some sample data so you can play with it and experiment with the code. When you start working with the open source code, this application will provide samples of them being used. Documentation is provide for both the application and each of the class, from with in the project you can get to it from the Project Explorer pane in the document folder
This folder is a physical directory under the project directory that you restored the project into so you can also get to the documentation outside of the project via file explorer
Using code bricks
The open source project includes a code brick file with several code bricks to make it easier to work with classes. If you have not used code bricks yet I encourage you to investigate them and start using them, but that is the subject for a future article. Unfortunately pcSoft has not given us an easy way to use multiple code bricks files or to merge them. If you have your own code bricks, the easier way I have found to merge them is to open two copies of the idea, and point each copy to a different code brick file and then copy and paste the code for each brick, not pretty but until someone, you know who you are ;-), writes a utility it is what it is. For now just point the IDE to the code brick file included with the open source project, from the tools menu select options and then General options of WinDev
And then the directories tab from the options window
Select the Bricks of Code and click on the ellispe
Select the CodeBricks directory that is under the project directory where you restored the Open Source project.
The code bricks pane does not immediately refresh so you need to close the IDE and reopen it so the new code brick file will be used.
Importing the default class into one of the WD example apps
Now that you have the open source project restored and code bricks configured, its time to actually begin using some of the code. Since WinDev gives you the ability to copy and paste between projects, an easy way is to leave one copy of the IDE open with the Open Source project in it, and then open your project in another copy of the IDE.
So in a second copy of the IDE, open the CRM example.
Reading the documentation that comes with the Open Source project (you will read the documentation right? ) you will find out that the Default Manager class uses the SystemLog class (in fact almost all of the classes do) and that means that you will need to add to tables to your analysis (DefaultManager and SystemLog) and the class file for each.
So open the Analysis for the CRM project, then switch to the copy of the IDE that has the Open Source project open, and switch to its analysis. Highlight the DefaultManger and the SystemLog files and press Ctrl-C
Now switch back to the IDE with the CRM open, and press Ctrl-V to paste the two file definition into the CRM analysis. THAT WAS EASY!!!!
If you don’t like my file and file names no problem you can change them to what ever you like, the classes have properties that allow you to override the file and field names used. The Open Source project has the files defined as HyperFile SQL Classic files, but you can change their connection and use them with any database WX supports. You might of course need to create the tables in your particular backend database, of course.
The next step is to import the classes into the project. If you use the SCM and add the Open Source Project to your SCM then you could use the share features it provides, but again that is a topic for another article. For now you will just use the import class function. In the Project explorer pane, right click on Classes and select Import a class.
Navigate to the folder you restored the Open Source Project to and select both the DefaultManager and SystemLog Class Files.
The next screen wants to know if you want to copy the files into this project folder or share the files from their current location. The answer to this question depends on if you are using the SCM, if you intend to make any changes to the Open Source code, and a matter of preference, so it is outside the scope of this article. For now choose copy the file into the project directory.
Reading the documentation (yes I am going to continue to harp on this) , you will learn that the next step is to enable and configure the class with a few lines of code in the project code. So open the project code via the Project -> Project Code menu option.
This is another opportunity to “cheat”, since you have the Open Source project open, you can copy the code from its project code. Go ahead and do that for the SystemLog class, by switch over to that copy of the IDE, opening the Project code and you will see two lines of code for the class
Copy those lines and paste them into the CRM project code
From the documentation (you have noticed a theme right ?), you know that the UserIdVariable property wants to know what global varibable hold the ID of the currently logged in user, which for the Open Source project was Glo.UserId. For the CRM project it is gnUser, so change that line of code to the appropriate value
No its time to add the default manager to the project, but this time you are going to use the supplied code brick. There are two ways to use the code brick, you can drag it from the Code Brick pane and drop it in the project code where needed, or even easier, use the short cut of the code brick. If you look at the code brick pane you will notice that each brick has a short cut defined, and that the short cut you want is DMSetup
So right under the code that you added for system log start typing the shortcut, DMSetup. Once you have typed a few characters intellisense will find the code brick.
Once it does you can press F5 to use that brick. This will popup a window with some prompts for you to provide the system settings you want. As you provide the appropriate values notice that the Inserted code section reflects the changes.
Once completed and you press the green check mark, the code is insert into the project code.
Some example uses of the default manager class
Now that the classes are configured for the project they can be used. For the first example you are going to replace the existing code in the Login_Win of the CRM project that is making registry calls with Default Manager calls instead. So open the Login_Win Window and in the Initialization code you will see they are using registry calls to retrieve some values from the registry.
These can be replaced with GetDefault method calls to the default manager. And of course there is a code brick to assist with making the call. So comment out the line fetching nUser from the registry and then below it start typing DMGet, the shortcut for the code brick, and when it is available select it.
And fill out the appropriate values. You want the result placed in nUser. The default type will be Registry, you found that out by reading the documentation (right?) . The default name is User. And you can make the default value 0.
And when you click the green check box the code is inserted.
So what did you just do? The default type of Registry, told the class that you want the value stored in the registry (making it machine specific) and to store it in the key location specified when you configured the class in the project code. The name of the default is its unique identifier so that you can retrieve the default when needed. The value stored for the default anme will placed into the result, unless an existing default entry is not found, in which case the default value supplied (0) will be returned, and a default entry will be made.
The same thing can be done for the retrieval of the value for CheckBox1, and will you are done the initialization code will look like this
IF you look at the code for Button1, please tell me that you know your buttons something a little more descriptive than that, you will see where they are storing the values in the registry.
The code for making sure the registry key exist can be removed, the class is managing all of that for you. And the RegistrySetValue lines will become SaveDefault method calls. So under under the first one, start typing DMSave, the short cut for the Save default code brick, and select it when it becomes available.
And fill in the appropriate values. You will notice that their code is always storing a 1 in User. I believe this is just so that the demo always defaults the the user they have setup to be used. I find this type of coding very common in the example applications, and you need to be very careful when using any of their code in a production project.
The values that seem appropriate to me, are the Default Type is once again Registry, the Default Name is user. And the value you want to store is gnUser which contains the User ID of the user that just logged in. This will store the value in the registry with the name that can be found by the GetDefault code you created above. Go ahead and do the other two values save lines and when you are done it should look something like this
A little cleaner than the original code but nothing earth shattering for certain. The real power of the Default Manager class comes when you start using the other default types, which are stored in the database file you created earlier. Looking in the documentation (yes I said it again), you will see there are 3 additional types available.
These settings are stored in a database table and are keyed to the logged in users id. This is a great method of storing “User Preference” type settings.
These settings are stored in a database table, but are not keyed to a user id, meaning all users of the system will share the default. Handy for storing “Company Preference” type settings.
These settings are stored in a database table and are keyed on both the userid and the current window. This is useful for storing default parameters for Report prompt windows, etc.
The advantage to store the defaults in the database is that the defaults can “follow” a user from workstation to work station.
I have found that many of the items that in the past I would have had to add a new table to database to store something I can now use the default manager to store it, which turns a half day project into a 15 minutes project.
A few examples uses from one of my production applications
I allow a user to set their preference for whether reports go direct to the print or go through print preview first. So once the user is logged on I retrieve their preference with this line:
Glo.PrintPreview = DM.GetDefault(DefaultManager.UserGlobal,"Glo.PrintPreview",True)
and when ever they change it I store the new default with this line
And now no matter which workstation the user logs into their preference for Print Preview is remembered. This is an example of a User Global default.
For the browses that use the browse form manager with the Peek-a-boo interface, I use the default manger to remember, if the user prefers to have the Peek-a-boo open all the time, or just when editing. So when the browse is first initilized I use this line to tell the class its initial state
BFM.PeekABooState = DM.GetDefault(DefaultManager.UserWindow,"PeekABooState",False)
and when the window is closed, I store its current state as the users preference with this line.
No the window remembers the users preference for the Peek-a-Boo state for this specific window. This is an example of a UserWindow default.
1099 Alignment Parameters
This example show the true power of the default manager and how I use it to increase my productivity. We were having trouble with the 1099 alignment at my bank client this year, so I decided to quit tweaking the report every year and instead give them the ability to set the X and Y coordinates for each field. This resulted in 23 new fields on the prompt screen
In the past I would have create a database table called something original like Ten99Settings (can’t start a table name with a number!) with 23 fields plus a unique id so I could retrieve the record. In the best of conditions that would at least take an hour or two by the time you create the file in the analysis, code the retrieve and save logic, do a full release of the application because of the database changes. At my bank client it would be best case scenario a two week project, because we would have to go through change request, DBA review, planned and schedule database upgrades, a few meetings and plenty of other nonsense that comes with working with corporate america.
Instead I used the newest feature of the default manger, the ability to store binary data (thanks to Pragma for the suggestion), to store a structure containing all 23 fields as a default. No database change, just a screen change so, shorter change request process, no DBA review, not long drawn out upgrade and testing phase. My life is good!!!
So the code for this little miracle that gave me half a month of my life back? The initilazation of the window contains the following code
PrintAlignmentStructure is structure PayersNameAddressX is int PayersNameAddressY is int PayersFederalIDX is int PayersFederalIDY is int RecipientIDX is int RecipientIDY is int RecipientNameX is int RecipientNameY is int StreetAddressX is int StreetAddressY is int CityStateZipX is int CityStateZipY is int CorrectedX is int CorrectedY is int RentalX is int RentalY is int OtherIncomeX is int OtherIncomeY is int NonEmployeeCompX is int NonEmployeeCompY is int LegalFeesX is int LegalFeesY is int SpacerHeight is int END PrintAlignmentSettings is PrintAlignmentStructure PrintAlignmentSettings.PayersNameAddressX = 13 PrintAlignmentSettings.PayersNameAddressY = 19 PrintAlignmentSettings.PayersFederalIDX = 13 PrintAlignmentSettings.PayersFederalIDY = 54 PrintAlignmentSettings.RecipientIDX = 52 PrintAlignmentSettings.RecipientIDY = 54 PrintAlignmentSettings.RecipientNameX = 13 PrintAlignmentSettings.RecipientNameY = 65 PrintAlignmentSettings.StreetAddressX = 13 PrintAlignmentSettings.StreetAddressY = 80 PrintAlignmentSettings.CityStateZipX = 13 PrintAlignmentSettings.CityStateZipY = 92 PrintAlignmentSettings.CorrectedX = 77 PrintAlignmentSettings.CorrectedY = 4 PrintAlignmentSettings.RentalX = 98 PrintAlignmentSettings.RentalY = 21 PrintAlignmentSettings.OtherIncomeX = 98 PrintAlignmentSettings.OtherIncomeY = 43 PrintAlignmentSettings.NonEmployeeCompX = 98 PrintAlignmentSettings.NonEmployeeCompY = 66 PrintAlignmentSettings.LegalFeesX = 126 PrintAlignmentSettings.LegalFeesY = 106 PrintAlignmentSettings.SpacerHeight = 38 PrintAlignmentSettings = DM.GetDefault(DefaultManager.WindowGlobal,"PrintAlignmentSettings",PrintAlignmentSettings)
It may look long but there isn’t a lot of “real” code there. The first half is defining the structure to hold the values, the same as I would have had to define a file had I went the traditional route. Next is setting the values to the defaults based on my testing, so that all they have to do is small adjustments to get it perfect for their printer and forms. And then finally is the same call to GetDefault that you have seen several times now. The class sees that this is a complex data type and will store it as binary data. If there is already a default entry it will be retrieved and its values used, and if not the default values I specified will be stored and used.
The only other code is when the run the report I store the defaults so that any changes they made to the settings are saved with this line
This is an example of a WindowGlobal default, all users will have the same default values. And as you can see this turned what would have been a time sink project into a really quick and easy task.
I hope this article has inspired you to grab the Open Source Project and start playing with it, and also got the creative juices flowing for different ways the default manager might make your development life a little easier. Just remember the key to open source is sharing, so if you come up with a unqiue use, or expand the class or have a suggestion be sure to place a comment on the article related to that class, so that we can all benefit as a community.
Be sure to go over to wxLive.us and watch the Uncle Pete’s corner, webinar that is the companion to this article.
Uncle Pete’s Corner is weekly webinar on all things WX every Friday 7:15 AM CST (5:15 PST), to watch the recorded version of this webinar, many other WX related webinars or to watch future ones live go to wxLive.us