The CHT Blogger

Thanks for your interest in The Clarion Handy Tools, an awesome collection of productivity enhancements for Clarion developers. These tools consist of an ever-expanding set of Clarion Templates and OOP Classes that extend or complement the normal functionality of the Clarion Application Development System from SoftVelocity.

Saturday, August 8, 2009

New Template, HandyFieldAutoCompleteControl

The Clarion Handy Tools Template called HandyFieldAutoCompleteControl is a control template that autocompletes a form field from values already available in another file.

In the example provided - HNDDROPDOWN.APP - we're autocompleting a "State Name" field from a file called hndstatesnew.tps. By simply typing 3 or 4 letters into this field a dropdown appears which displays the closest matches for the typed value. By continuing to type beyond 4 characters a matching value is brought into the autocomplete control.

Alternatively, with the down arrow key, users can scroll down into the dropdown control to select one of the values that appears there.

Adding to the autocomplete file: If you type a unique value and press CtrlEnter, the entered value is added to the autocomplete source file.

Deleting from the autocomplete file: If you bring an existing value from the autocomplete file into the autocomplete entry control and press CtrlDelete you are able to delete a value from the autocomplete source file.


autocomplete.gif



To watch a short video of the HandyFieldAutoCompleteControl Template in action, click here HandyFieldAutoCompleteControl Template Demo

Cheers...

Gus Creces
The Clarion Handy Tools Page
Visit Website

Thursday, August 6, 2009

Build 13C1.00 New Features Review Part 5

I had a user request to provide a "display-tape" facility to CHT's calculator with the opportunity to print the tape output.
I did that and had it working quite some time ago, with the intent to release with Build 13C1.00. In the meantime I was scanning, one day, through some Xara Graphics and spotted a calculator layout that I really liked.

As a result of finding that graphic, I've re-written the "display-tape" calculator - procedure HandyCalcTape() in HNDCALC.INC/.CLW. The outcome is the calculator below. This is a separate procedure entirely from procedure HandyCalc() which you have now.


calc.gif



Since this calculator is built around a graphic, those of you who provide applications for non-English users, will need to contact me with a list of symbols that you want to replace the English based symbols currently displaying on the interface. I'll whip up a separate graphic based on your non-English symbol list and include it with the toolkit in the /images/ directory. Inserting that graphic is easily enough to do by setting a property in the class or on our template.

To see the calculator in action click this link: CHT HandyCalcTape.

Cheers...

Gus Creces
The Clarion Handy Tools Page
Visit Website

Tuesday, August 4, 2009

CHT Build 13C1.00 New Features Review

ClientServerBrowseListBox Template


The previous three CHT Build 13C1.00 New Features Review parts dealt primarily with server side template changes with brief references to the Client side where server changes impact the client application. A new feature on the ClientServerBrowseListBox template described in this Part 4 posting, affects only the client. To find the feature, open the ClientServerBrowseListBox template dialog as in the image below.


aug_09_007.gif




The fields listed in this dialog may be manually entered, but usually they are simply imported from work already completed on the matching VIEW created in your server by the HandyJDODataAdapter + ClientServerDataBuilder template combination. If you need a checkbox in your list box to display a boolean on/off condition a new control on the ClientServerBrowseListBox template's "Hot Fields" dialog (see image below) lets you implement a checkbox icon without coding on your Client Server Listbox browse.


aug_09_008.gif



Check the "Display Checkbox" switch on this "Hot Fields" dialog and you're done - however, don't forget to set the icons switch for the matching column in your listbox design.

ClientServerBrowseListBox_XCL Template


Client-Side Cancelled-Insert Deletion



In my CHT Build 13C1.00 New Features Review Part 3 posting, I discussed deleting cancelled-insert records either from the server side with "Garbage Collection" or from from the client side. In the image displayed below, on the "Form Procedure" dialog of the ClientServerBrowseListBox_XCL template, there is an optional (OPT) configuration which when completed is used to signal to the template that it should handle cancelled inserts by deleting the record inserted and then cancelled. Insert the SysID of your table record here to trigger client-side cancelled-insert deletion. Or leave the field blank if you plan to implement server-side "Garbage Collection" for this view (see image below).

Insert Mode Cross-Priming Prefetches



When a newly inserted record needs to be cross-primed from another record in the same table or in a different table, your client needs to signal that to the server in
the form of a "FetchFilter" passed to the server. The server then uses this filter to fetch the matching record from the correct table and keep it in the data buffer(or in a history buffer) before a new table record is inserted. Please re-read my CHT Build 13C1.00 New Features Review Part 3 posting if you don't know how to
handle this situation on the server application. To configure the client form for server-side cross-priming and pre-fetching, complete the SYSID of an existing record available to your form's browse and in the update form record buffer. The existing record can be in the same table or in another, joined table as the case may be (see image below).


aug_10_006.gif



The generated code resulting from the cross-priming configuration discussed above is in the next image.




aug_09_011.gif



In an unprimed "RequestInsert()" the "Prefetch" filter component is left blank. In the above example, because the template cross-prime field has been completed, the "RequestInsert()" call includes a prefetch filter.

That completes Build 13C1.00 New Features Review Part 4.

Cheers...
Gus Creces
The Clarion Handy Tools Page
www.cwhandy.com
support@cwhandy.com
August 4, 2009

CHT Build 13C1.00 New Features Review

Background - HandyJDOAdapter Template



The HandyJDODataAdapter template is an existing CHT procedure template used to create CHT Client Server data packaging procedures. It creates procedures that hook into a CHT server application by attaching to the main server via a server VIEW created there with a server-plug-in template called ClientServerQueryBrancher_BIC. All remote web-client queries directed at a particular VIEW name are routed by the server through a HandyJDODataAdatpter procedure attached to a matching VIEW name. A server may have numerous versions of this data packaging procedure- as many as the data requirements of your application dictate - each servicing a different back end data view consisting of one or more data tables. So asking, "How many HandyJDODataAdapter procedures does my server require?", is a lot like asking, "How many browses does my application require?" Depends. It's basically up to you to decide.

Extra Generation Control Features HandyJDOAdaper Template



A new dialog called "Generate" has been added to the HandyJDODataAdapter template (see image below). It's purpose is to give you more control over the existing code-generation features of this template and to add some new features particularly useful with SQL back ends - situations where your server is serving data to a web client application from an SQL data base without directly exposing the data base to the web.


aug_07_001.gif



The "Generate" dialog has been added as indicated above, just below the existing "Files" dialog. See the next image for the details of the dialog itself.


aug_09_002.gif



No Generate SetUpdateRecord() Pre-fetch Code

Inside all HandyJDOAdapter procedures is an OOP method called SetUpdateRecord(). This method is used to fetch a record - or a set of records described in a Clarion View - before updating or deleting. Your client will send an unambiguous filter that describes exactly one recordset during an update or delete operation. This filter is usually something as simple as CUS:SysID = 1234. The fetching operation is called a "Pre-Fetch" because the fetch is accomplished - and required - before the actual update or delete operation can take place.

There are also times when a "Pre-Fetch" using SetUpdateRecord() is required even in an "INSERT" operation. Inserting a child record to an invoice header,for instance, may require you to pre-fetch the header record so that the ID of the header can be primed into the child record's join field. Or you may want the child record to contain data from a related record as, for example, the CHT Support Forum does, where a copy of your original posting is inserted into your REPLY.

Suffice to say, that how and when your pre-fetch is performed can depend significantly on your data design. This first dialog "No Generate SetUpdateRecord() Pre-fetch Code" stops generation of default pre-fetch code so as to allow you to insert case-specific code of your own design.

Generate SQL-Style Primary Table Fetch



When you check, and set ON the "No Generate SetUpdateRecord Pre-fetch Code" switch mentioned above, the second switch, "Generate SQL-Style Primary Table Fetch" becomes enabled. This generates a simple fetch on the Primary Table in your procedure's data view based on the "FetchFilter" being passed up from your client. With this switch set, you don't need to write the SQL-style fetch code yourself, if what's generated applies to your design. The code generated looks as follows and, as already stated, applies only to the Primary table in your view.


aug_10_001.gif



By juggling your view layout, you can often achieve the end result you want in order to pre-fetch the data record you want without writing any code. However, you must decide whether the code created by the template is what you want or need. If not, leave "Generate SQL-Style Primary Table Fetch" unchecked and write more complex pre-fetch code that better fulfills your design. These switches give you the option of doing that.

No Generate TakeWebUpdateRecord() HTTPInsert Code



Also inside your HandyJDOAdapter procedure is an OOP method called TakeWebUpdateRecord(). This method is used to actually perform record INSERT, UPDATE and DELETE operations at the command of your web client. This specific switch lets you turn OFF code generation of the INSERT code normally produced by our template. That provides you with the opportunity to craft your own insert code based on specific requirements that our template has not forseen or generic insert code just won't handle. The image below, illustrates some hand-embedded code in a server I recently created. The main bit of knowledge you need to have that is CHT server specific is the return value after a successful insert.


aug_10_002.gif



There are three requirements after a successful insert. These are: 1) Call xServer.SetCurrentQuery() with the filter statement that your CHT server will use to refetch this new record just created. This is a simple, unambiguous "FetchFilter" used to recall this newly inserted record. 2) Set the procedure returnvalue to HPROP:WebCycleToEdit. The server uses this value to literally switch itself into update mode and return the data to your web client app now operating in update mode. In other words, the record is pre-inserted and returned to your web-client primed to the extent your insert requires and the client form procedure completes the record. 3) The procedure return error code is set to HND_MESSAGE_BRWSVR_CYCLE_EDIT This is really not an error code, just a signal to the main server code that it should go into edit mode using the record just inserted.

What If The Client Cancels An Insert Operation?



While we're on the topic of web-client record insertion, since records are pre-inserted by the server - for obvious reasons - what happens if the web-client operator decides to cancel record insertion? There are two ways to handle this. They can be used exclusively by implementing one or the other, or they can be used together. Each server back end data packaging procedure built with HandyJDOAdapter is always populated with another template called ClientServerDataBuilder.
This template describes the tables, the view and the fields to be operated on by the procedure. It provides among other things a dialog called "Garbage Collection" (see image below). Here you can describe a background operation that purges incomplete records on a time scale determined by you. The purging operation requires a few specific fields that signal to the server that a record has been abandonded without having being completed.


aug_10_003.gif



If you don't want to avail yourself of this "Garbage Collection" facility - implemented on the server end - you can simply configure the client applicaton to delete the pre-inserted record if the user cancels out of insert mode without completing and saving the record. That's a more traditional, Clarion-like behaviour to handle housekeeping of cancelled inserts (see image below).


aug_10_004.gif



No-Generate Query Keyword File Fetches



A built-in capability of all CHT Back-end data packaging procedures created with HandyJDODataAdapter is the ability to dynamically switch in or out, query keywords from the application's configuration file. For example, you might have a server that serves both English and French users who are operating browses that allow them to construct native language queries using CHT's query builder or QueryParsingFilterControl. With a signal from the client indicating French or English, your data procedure can, in real time, read and BIND the approrpriate set of Query Keywords from it's configuration file and thus be able to interpret both sets of queries from either French or English clients. The switch "No-Generate Query Keyword File Fetches" turns off this dynamic query keyword capability in favor of the query keywords that you've pre-configured on our template. Doing so generates less code - that you probably aren't using anyway - and eliminates the requirement to complete the "Server Variables File" dialog on our ClientServerDataBuilder template (see next image). In fact, this "Server Variables File" dialog becomes disabled when "No Generate Query Keyword File Fetches" is checked.


aug_10_005.gif



That concludes "Build 13C1.00 Feature Review Part 3" describing changes on the HandyJDODataAdapter template and how they impact other parts of your server/client systems.

Cheers...
Gus Creces
The Clarion Handy Tools Page
www.cwhandy.com
support@cwhandy.com
August 4, 2009

Monday, August 3, 2009

CHT Build 13C1.00 New Features Review

Client Server Hardware Key Login



Normally I do this the other way around, releasing the new build and then reviewing the features. This time, I'll review some of the key new features this week and then
with any luck, I'll be finished the final touchup on Build 13C1.00 before week's end August 7th.

I've had the opportunity this summer to work on a project that required the software to be locked to the hardware on which it is installed. Since this is also client-server software, requiring a login and download of stock market and money market data for display, I was able to use a standard CHT Client Server with some strategic changes to achieve a login-style data connection to an MSSQL server as well as a software-locked-to-hardware condition. These strategic changes are now reflected in Build 13C1.00 templates.

This is not to say that hardware key login could not be achieved without these latest template changes. Obviously, before a template can be written that generates code, somebody has to write the code that's going to be generated first. After writing and testing and re-writing the concept, I was able to abstract the requirements considerably in order to have the template help CHT developers achieve a Hardware Key Login.

Normally a CHT server login requires three pieces of information. I normally use Last Name, Email Address and a Login ID. There's nothing that says you actually need to use those specific bits of information, at least not the Last Name and Email Address, these fields and keys can be juggled on the template interace to use something else which is appropriate. The Login ID, on the other hand is more rigid concept and harder to work around since it is assumed to be numeric and unique.

For this login the customer wanted to use a USERNAME and PASSWORD only for the user to fill in at login time. But he wanted the software to "lock itself to the hardware on which it was installed". That means, once installed, and run on a given computer, it will not connect to the back end using any other computer even though it' s copied or installed there, and the USERNAME and PASSWORD are known. This prevents users in an office setting from buying one license of the software and sharing it amongst themselves in the office.

The concept is flexible enough that if the user wants some time later to move the software to another machine, he can contact the vendor and the hardware key can be purged from the customer's data record, allowing the software to be installed successfully and locked to a different machine.

In the background the application creates a HARDWARE KEY, a unique piece of data consisting of something which is unique to the machine on which it is running. You can use a combination of things such as the hard disk serial number or the primary MAC address or you can simply have the installer generate a GUID which is written into the registry and encrypted. This HARDWARE KEY is used as the third piece of login data along with USERNAME and PASSWORD instead of a LOGINID.

The first time the user logs in, the login is achieved by USERNAME and PASSWORD only because the hardware key field in the data base is blank. During the first login, that hardware key - which is passed up with each login - is written into the data base and left there. After that, subsequent logins are achieved via the hardware
key in combination with the USER NAME and PASSWORD. The same user running the software on a different piece of hardware is not allowed to log in since the hardware key generated on that machine is different than the one now stored in the data base against his other credentials.

Hardware Key-Style Login Specifics



Once you decide that a hardware key-style login is what you want, a lot of the work is done for you by the templates. Your back-end tables require aslightly different combination of fields than normal, but not all that much. You need a string(100) hardware key field in place of the usual numeric login ID field. Our back-end table also contains UserName and Password fields. This is not strictly necessary, as you could use any two other fields, for example, last name and email address as long as these two fields, used in combination, provide a unique key value that results in the ability to make an unambiguous fetch on the data base.

Since our example is an SQL implementation, our data table does not actually have any keys other than the standard SYSID. Our clarion dictionary, of course, declares a unqique key on the hardware key field and on the combination UserName+Password fields, but these key declarations are only there for the Clarion file drivers will generate the correct SQL SELECT. These keys are not actually required to be in the data base table declarion.

Initially, let's take a look at a new button on the "File" dialog of the BrowserServerInitializationControls template, called "Implement Hardware Key-Style Login" (see image below).

aug_09_001.gif



Notice here that the first two fields of the file dialog are completed as usual with the user or customer table name and sysID key. The third field receives the HARDWARKEY unique key and the fourth field receives the unique compound key consisting of USERNAME and PASSWORD. Again this compound key could be any two values, for example Last Name and Email Address, which in combination can be used to obtain a unique value for login. In our implementation the USERNAME and PASSWORD are completed on the client application's login interface by the user. The hardware key is code-dervided by the client application.

The "Implement Hardware Key-Style Login" dialog explains these concepts again and requires only that you check the switch provided (see image below).

aug_09_002.gif



If your key field design matches these requirements your hardware key-style login implmentation is complete, on the server side at least. Checking the switch (above) to the ON setting causes our template to not generate the standard LastName, Email Address LoginID login and instead the code pictured below is generated into the Server.TakeLoginDetailsRequest() procedure (See image below).


aug_09_003.gif



I've heavily commented the generated code above so the implementation should be clear enough. The first time a user logs in with a USERNAME and PASSWORD,
the hardware key is not yet stored. The user is warned that he must initially install to the machine on which the software will be used. Initially the generated code attempts to retrieve the user account using the hardware key. This will fail under two conditions, either the user has never logged in before,and his hardware key is not yet stored, or the user is logging in with the correct user name and password from the wrong hardware. If the hardware key exists in the file, the user name and password provided are qualified against the account on file, and if these match, the login is permitted. If the hardware key is not found, the user's account is fetched using the unique combination USERNAME and PASSWORD and the hardware key provided is stored to that account and the login is permitted.

Hardware Key-Style Login (Client-Side)



On the client side, to accommodate hardware key-style login, we've provided a new method called "ThinClientHardwareKeyLogin()" (see image below).


aug_09_004.gif



Inside our client application all the necessary information to perform the hardware key-style login is collected and passed in the ThinClientHardwareKeyLogin() method - before the PARENT call. This makes it easy to debug any login problems on the client application side.

The following properties are completed here, only one of which is unique to this hardware key login. The properties initialized are as follows:
The first two properties - Encryption and Compression - are determined strictly by the client. The server does not have to be told about them in advance. Since the client communicates the encryption/compression states to the server during the transaction and the server responds in kind based on the state information provided in each communication. Encryption is not static, nor is it predictable, every single communication between client and server is uniquely encrypted.


SELF.SetUseEncryption(True) !We've turned encryption on.

SELF.SetUseCompression(True) !We've turned compression on.

SELF.RemoteUrl = CHTDataServerURL !This can be hard coded in the app or determined by app configuration.

SELF.RemotePort = CHTDataServerPort !This can be hard coded in the app or determined by app configuration.

SELF.LoginID = 0 !This property is not required to be set in a hardware key style login.

SELF.HardwareKey = MOD:HardwareKey !This new property (STRING 100) is provided with any static hardware-unique key you decide to derive in code.

SELF.LastName = UserName !This property value comes from a UserName field completed at login.

SELF.EmailAddress = Password !This property value comes from a Password field completed at login.



Note that there are no separate HNDCLIENT properties for USERNAME and PASSWORD. We're placing this information into the SELF.LastName and SELF.EmailAddress properties.

If you check in the server code, you'll see that the server is picking up the "lastname=xxx" tag from the client and passing it to the server's UserName data
field while the "emailaddress=xxx" tag is passed to the server's Password data field. In fact any two pieces of information that in combination provide a unique value can be used as the login, using these SELF.Lastname and SELF.EmailAddress properties. The server and client just need to understand ahead of time what combination of fields will be used.

That completes Hardware Key-Style Login. In the next posting, Build 13C1.00 Feature Review Part 3, I'll cover several new CHT Client Server features having to do with SQL implementations.

Cheers...
Gus Creces
The Clarion Handy Tools Page
www.cwhandy.com
support@cwhandy.com
August 3, 2009