Home page Home page Home page Home page
Pixel Header R1 C1 Pixel
Pixel Header R2 C1 Pixel
Pixel Header R3 C1 Pixel
By Sprezz | Tuesday, 17 April 2018 16:35 | 2 Comments

So OpenInsight X has finally arrived resplendent in all its glory! After a gruelling beta cycle Revelation Software announced yesterday the formal release of OpenInsight 10.0.1.

We've been working with the software internally for quite some time and it has been a pleasure to see it flesh out and come to life. So many small but important details are taken care of. The main executable is now digitally signed - so no more scary warnings when launching the program. The long term goal of developing a tool that's good enough to develop a tool has finally been achieved - no more random executables! These are all of the exe files in the product - not a formdes.exe in sight. Finally form designer is written in OpenInsight itself. This is testimony both to the power and flexibility now delivered in the shipping product.

The first impression on logging in is that of an uncluttered clean interface

Gone is the busy VB3 style front end, replaced with a simple set of choices. Do you want to create something new or open something? If you're just beginning development you're going to want to create an application. As that's such an unusual thing to do it isn't included in the standard "New" dialog. Rather there's an item specially for it on the File/New menu.

The dialog is familiar but as we opted to use the new stronger security during installation our passwords have to conform to the default rules.

There's a lot to look at but in the first instance we're just going to take a flying visit to the form designer. First though let's add some existing tables into the mix. To do this we'll need to turn on the Database Panel.

and now we've done that we can choose to "Add files"

and add in our PROFILES table to give us something to play with

Apply the changes and then a  keystroke shortcut (Ctrl-Alt-D) to toggle the database panel off. All panels have keystroke shortcuts to toggle on and off.

So now let's launch the form designer

for a data bound form.

Just a couple of things to note here. By default the form designer DOESN'T add a menu to the form. This is consistent with good practice in an MDI application. Instead it offers to place OK and Cancel buttons on the form. As with 9.4 the form designer chooses the most suitable control type to place on the form but allows overriding if required.

All the usual suspects and a date/time picker too! Pressing OK generates a default form and opens the form designer.

The first thing that is apparent is that OI X makes intelligent choices for control width! The screen straight out of the box is visually appealing! The screen is now split up into four main areas (The menu and TCL are omnipresent). These areas are the Toolbar at the left, the main design screen in the middle, the properties and events at the right and the status line at the bottom. By default the screen features a grid and snap to grid is set. These options can easily be overridden from the Settings/IDE Settings menu option :-

Note also that right clicking on the screen image provides a context sensitive options menu from which you can override some of these preferences.

As you move from control to control the property panel changes to reflect the properties specific to that control type - so an edit line has a whole different set of properties to a check box.

Similarly an edit line has a whole different set of events to a check box.

But what is really impressive is what happens when you select more than one control of different types :-

The property panel now only shows COMMON properties between the two controls.

As with 9.4 it is possible to add quick events and/or scripts to a control but there has been some significant changes in ease of use for quick events. Let's illustrate this by adding a popup to the options for the user id prompt.

So firstly we add a quickevent to the OPTIONS event on the USERID edit line.

Note a couple of new additions.

Does the quick event have priority? In existing OI, quick events occur at the end of the event chain. So for example, if we are putting on a READ quick event, the system will look for a script, execute it if present, if required execute the actual READ then execute the quick event. This means that the READ quick event is always POST READ. By setting priority, the quick event will be executed before the script and actual READ event. This means that for the first time we can use commuter modules for everything and never actually have to cut a script. In 9.4 sometimes you had to used scripts to get in before the system logic. No more!
Note also the "Finalize" section. When the quick event has completed what should be done (if anything) to wrap up. In the case here where we've returned a row id into the key prompt we obviously would like to read the row. Now we no longer have to cut code to make this possible.

Moving on to linking to this options event - we add a hyperlink control to replace the user Id static.

and we set the tooltip property

and we add a quick event to the CLICK event of the hyperlink control. 

Clicking the button opens the dialog from where we can check that we want a quick event or check that we want a script.

We want a CLICK quick event so we select that

and rather than "General" we want to do something else. Dropping down the combo box we see a number of events, the newest one being "Trigger Options" - i.e. cause the OPTIONS event to be triggered for the control we were just on.

Choosing this leads to what I can only describe as a touch of genius

The quick event sets the SYSTEM FOCUS property to the control we were just on (@PREV - the PREVIOUS property of the current control) then finalizes by sending an OPTIONS event to the control currently having focus.

Running the window we see that the User Id: static is now a hyperlink

and hovering over it with the mouse changes the appearance and displays a tooltip

actually clicking the hyperlink sets the system focus to the USERID edit line and sends an OPTIONS event. The popup displays

a value is chosen

 and the USERID populates and a READ event is issued

No code required at all for such a comprehensive set of actions.

Moving onto the Toolbox section of the screen.

All of our old favourites are there along with a number of new control types.
The attention to detail is just phenomenal. Take as a simple example what is described as the "Up-Down Control". Let's add one into our screen and put it alongside an edit line.

Go into the properties of the up-down control and set a range to operate on and a "BUDDY" control - the edit line to associate with. Set the AUTOUPDATEBUDDY property to True

and now when you're in the entry form, scrolling the arrows will update the edit line and changing the edit line will update the scroll position! Again - no coding.

This short overview hasn't even begun to scratch the surface of what's changed in OI X but hopefully it will have whetted your appetite to get in there and play!
By Sprezz | Wednesday, 28 March 2018 12:09 | 0 Comments
We recently had the pleasure of working with one of our favourite sorts of client - the type who are enthusiastic about their speciality field and who have trained themselves to program - to allow themselves to write MOST of the system they need to service their enthusiasm. Every now and again, they call us in to do some of the heavy lifting for them.

This particular time the client had an issue with a multi page form. Under most circumstances the data displayed correctly but under - as yet undetermined circumstances - the data display would become corrupt. Data would appear in edit fields that belonged in other edit fields and existing data would be overwritten by seemingly unrelated data.

Approaching the issue logically, we installed break points to ensure that what was read from disk was correct and sure enough @Record and the ATRECORD and RECORD properties all contained what they should. It was only when a certain field was filled in that the data became corrupt. Through much testing we were able to determine which field had to be filled in to cause the corruption but it still made no sense. To illustrate using the AVERY_LABELS table (the client's data is commercially sensitive so we can't use screenshots from their system). In the example below the Cross Reference column references another row in the AVERY_LABELS table and extracts the product description.

So the above is what we expected to see. The below is more like what we were seeing - data that SHOULD have been there ("Removable Laser..." in Cross Ref Product Desc) wasn't - being replaced with the contents of the field above. Data was missing ("Label" in Product Type) and data was incorrect ("6464" in Template Family).

Painstakingly we played with entering data into the client screen - all 6 pages of it - until the error manifested itself when we entered data into a prompt that provided the key for a symbolic to xlate off. We turned on engine logging to see if some event was being triggered that would explain the corruption, but there was nothing other than standard engine flow. On a hunch we went to the system monitor and typed the equivalent of

LIST 100 AVERY_LABELS PRODUCT_DESC XREF_DESC SEQUENCE and were rewarded with something like

which was NOT what we would have expected to see. So we decided that the XREF_DESC formula must have been to blame in some way. Looking at it, it SEEMED to be straightforward enough :-

Until we looked REALLY closely... the column is called PRODUCT_DESC not PRODUCT_DESCS$. When we changed the spelling to the correct one - AVERY_LABELS$PRODUCT_DESC$ everything was right with the world again - the screen displayed correctly and the LIST statement produced

So - what went wrong? To understand this we need to be familiar with how the Window processor actually works with the data from @Record.

A major change in OI over AREV is that when the system WRITEs the current screen contents to disk, it does not simply write the contents of @Record onto disk as in AREV, rather it takes the current row from disk and updates ONLY those columns that feature in the current Window. THEN it writes the row back. This allows the user to have multiple windows open updating separate sections of the same current row.

To do this the Window processor has to maintain its own pseudo @Record, just containing the contents of the current screen. To illustrate using the pseudo code for a READ and populate operation

pseudoRecord = ""
for loopPtr = 1 to controlCount
  control = controlList< loopPtr >
  dictColumn = get_Property( control , "COLUMN")
  pseudoRecord := xlate( dataTable, @Id, dictColumn, "X") : @Fm
pseudoRecord[-1, 1] = ""
for loopPtr = 1 to controlCount
  control = controlList< loopPtr >
  call set_Property( control, "DEPFROP", pseudoRecord< loopPtr >)

In the original dictionary item the XLATE destination column was incorrectly spelt, so at compile time in the Table Builder the equate would NOT have been replaced with a column number, but with a blank. The Table Builder compiler before OI 10 does not include the error checking that the System Editor has. So the XREF_DESC formula was resolving to

   @Ans = Xlate("AVERY_LABELS", {CROSSREF}, "", "X")

which returns the entire row, not just an individual column. So instead of pseudoRecord containing

1 : @FM : 8 : @FM : 3 : @FM : Xlated 8  : @FM : 2 : @FM : 17 : @FM : 10 : @FM : 16

it contained

1 : @FM : 8 : @FM : 3 : @FM : Xlated 1 - 43  : @FM : 2 : @FM : 17 : @FM : 10 : @FM : 16

thereby pushing the subsequent SET_PROPERTY DEFPROP out of kilter.

Obvious with hindsight but not the easiest bug in the world to track down on a system written by someone else!
By apk | Wednesday, 7 March 2018 16:13 | 1 Comments
As we all know, computers are actually pretty dumb.  They can't count past 1.  On the other hand, they're very loyal.  They do exactly what they're told to do.  When you're debugging code, that's great.  Enter in the same set of data, step through the debugger, and it's guaranteed to always work the same way ever time.  Except for when it doesn't.  We've all experienced the frustration of finding something wrong during testing, but no matter what you do, when you step through the debugger, it doesn't happen.

Sure, we usually chalk this up to something with the message queue or interaction with another program that's being interfered with because the debugger now has focus.  But, sometimes, we know we're just fooling ourselves, and we start to wonder if maybe this machine has a mind of it's own.

Recently, we here at Sprezz Towers found ourselves with a machine where the only obvious conclusion was that the system had become sentient.  Before welcoming our new silicon overlords, we decided to give things a second look.  And a third.  Probably a fourth as well.

The problem was reasonably simple.  While attempting to calculate a shipping rate, we were receiving an on-screen message that the shipping rate could not be found.  We expected that because we were testing how the system responded to missing shipping rates.  This had been working for years before the modification we were testing.  And by years, I mean decades.  We don't know when the code was originally written because there's no date in the header, but there's a comment dated June 1993.  Yes, 25 years ago. The most recent comment regarding a change is from 2001.  The code has been recompiled since in the move from ARev to OI, but it's effectively unchanged for 17 years.

The change itself was relatively simple.  We added a set of date ranges to indicate when the shipping rate profile was active. For the overly technical readers, basically, we added three MV fields, HIST_START_DATE, HIST_END_DATE, HIST_ACTIVE.  The system is full of this type of code.  There's a routine that's been in use for 10 years:

validRange = checkDateRange( checkDate, startDates, endDates, activeFlags )

which just returns TRUE$ or FALSE$ indicating if the passed checkDate is inside a valid date range.  This isn't rocket science nor brain surgery.  And it was working fine.  The system displayed the invalid rate message when the date was invalid, and didn't display the message when the date was valid.  That wasn't the problem.  With one specific test case, the system was displaying a failure message we weren't expecting.  The error was related to the customer's configuration, and not the changed code.  It was a valid error, and the correct error was displaying on screen.  However, the wrong error text was being placed into the error log.

Setting a debug break point just before the shipping rate code, we stepped through the code and verified that all the error flags are being set correctly.  And they are.  Everything is working as expected.  Including logging the correct error text.

Going back to our opening premise, computers are dumb.  There are no UI threads or messages interfering here.  The error message bubbles through the system and is returned at the end of the process.  But we're clearly getting different results when stepping through the debugger as opposed to just running the code.  It's time to start thinking critically and logically about this and we start looking over all the code carefully.

When working with systems like this (RevG systems converted to ARev, then to OI), there are times where you feel a bit like you're practicing a programming version of anthropology.  You look at the code and how the style has changed and how variables are named and you can see the evolution of Rev coding styles and standards.  Generally, you can pinpoint about when this code was originally written, just on the use of CASE v IF/THEN statements or how things are capitalized.

As mentioned earlier, this code is old.  Even though the earliest comment date is 1993, we know the code is much older by the style and function.  It's been around since the origin of the system, a RevG application from 1982.  And as RevG code it uses RevG style syntax.  And RevG style calling parameters.  And RevG style error handling.

Ahh..error handling.  I could write a whole new post on inconsistencies in error handling, and whether FALSE$ means success or failure as we move from system to system (and programming epochs).  But in this case, it wasn't how the status was returned.  It was how the status was checked.  Most of us probably forget now, because OpenInsight (in it's modern form) is 25 years old, but in the ARev days, we didn't have get_status() and set_status().  We had status().  And we had...well, that was pretty much it.  There was @FILE.ERROR, but that always seemed too embedded with LH and the filing system to piggy-back on for your own use.

This code used status().  And it used get_status() and set_status() as well.  Needless to say, it was a complicated mess.  But, status() was the key and the source of our error.

It turns out, that when stepping through the debugger, when you return from a subroutine or function call, the contents of status() is cleared.  During normal execution, the system found a value in status(), and jumped into the error routine related to a failed shipping rate call.  However, stepping through the debugger, status()was set to 0, and the system continued on.  Here it checked get_status() for additional errors, and we received the warning about the mis-configured client.

The OI programming documentation says

Be aware, however, that between the time you set the value of Status() and next check it, some other procedure might have set its own value.

This is not related to the Get_Status and Set_Status functions.

While we expect this when calling multiple functions and routines, we didn't expect it to be cleared by the debugger when popping back on the return stack.

The lesson to be learned here is just because your old ARev code recompiles in OI, doesn't mean it's still working.  ARev is ARev and OI is OI, and while they might be very similar and compatible, they're not the same thing.  Something to keep in mind for those hoping to just ARev/32 their way into OpenInsight.  It's not all just cut and paste.
By Sprezz | Thursday, 16 November 2017 17:52 | 0 Comments
Sometimes it doesn't matter how esoteric your knowledge of the internals of the product are - the only way to get to the bottom of an obscure mystery can just be Elbow Grease.

Recently we were contacted by a client with a predicament. He was (finally) converting his client's Rev G system to OpenInsight and he'd run into a snag. Every time he quick painted a form to deal with a specific table, the form was created with no problem. But the moment he reopened the form and tried to look at the properties of specific controls, the controls were no longer data-bound. And to add insult to injury, the columns they had been associated with no longer appeared in the dropdown of selectable columns ; they were still in the dictionary, but not selectable from within the form designer dialog.

Our first thought was that the column names might have retained their Rev G periods. But that wasn't the case. "OK", we queried, "are they in %FIELDS%?". Predictably they were. And anticipating this question the client had already forced a rebuild by clearing the dictionary and copying everything back in.

"Can you check the SYSREPOSWINEXE? Are the columns showing there?". At this point the client indicated that the rows seemed to be corrupted and that the columns weren't showing there. So we suggested REPOSITORY DELETE the EXE and recompiling.

Still no joy.

"OK - check SYSREPOSWINS, SYSREPOSWINEXES and SYSOBJ for GFEs". None. So we decided to try and establish the root cause. Essentially if the design process is removing the column from the control, it's an indicator that the designer hasn't found the column in the dictionary. But we have established that it IS there, so let's start an LH log and see why the read is failing.

Shortly thereafter armed with an LH log, we took a good look at the relevant section and quickly established that the designer was using a TEMP table, not the actual table. Without bothering to test further we simply instructed the client to stop using a TEMP table, as this was likely the cause. The client remonstrated that they WEREN'T using a TEMP table, so at this point we asked for the dictionary and SYSREPOSWIN row to test for ourselves. We ran with the actual table and to our surprise, the LH log showed that regardless of what we told the form designer, a temp table was created and populated with all of the dictionary items from the actual table. And to make matters worse, the columns that wouldn't show up were present both in the temp table AND in the %FIELDS% of the temp table.

Employing Occam's Razor, we then quick painted a form with just two controls, the key prompt and one of the disappearing columns. It quick painted fine BUT the moment we tried to modify the disappearing column's control properties, it was unbound from the data table. All we could gather from that, was that the initial quick paint uses a different column list than the form designer column selection dialog.

Working on the hunch that something in the form read process was removing the column, we then copied all but the two columns needed by our test form into a separate dictionary, and developed a program to copy in a dictionary item, REPOSITORY ACCESS the form, REPOSITORY COMPILE the form, then ACCESS it again to see at what point the column was blanked down. (There were over 700 dictionary items so doing this manually would have been too tedious). To our consternation the column was never blanked down, BUT the moment we entered the form designer it was immediately removed.

At this point all fingers were pointing to the form designer as the culprit, so we had to take a peek inside to see what it was up to. In the absence of source code, the only way to do this was to run an oeprofile.log and dissect that.

The profile log showed that during the loading process, the form designer called DICT_MFS_BUILD, which in turn called COMPILE.PROTECT for a number of dictionary items that was less than the total dictionary items in the table. So in another wild goose chase, we wrote a program to emulate this behaviour and see which dictionary items were failing to compile. Naturally this failed to produce the results we needed.

At this point we were pulling our hair out with frustration, so we just populated the dictionary with only the columns needed for the original data entry form the client had provided. The form worked and the columns remained intact in the controls. So we copied in the rest of the dictionary items and again the columns were removed from the errant controls. It was time to abandon abstruse investigative techniques and just go back to plain old gumshoeing.

It was obvious that at least ONE of the columns in the dictionary was causing the issue but which one? The only way to investigate would be to copy the dictionary items in one by one, go into the form designer, check if the control had had the column removed and if so the last dictionary item copied in was our culprit. The idea of doing this for over 700 columns frankly sucked. Enter our old friend - 'binary chop'.

We wrote a program that selected the temporary dictionary in sorted order , and then copied in the first 360 or so columns. We went into the form designer and sure enough, the affected controls had their columns removed. So we modified the program to do the first 180. Same problem. First 90. Same problem. First 45. The controls kept their columns. First 72. Same problem. First 58. The controls kept their columns. First 65. Same problem. First 61. The controls kept their columns. First 63. Same Problem. First 62. The controls kept their columns.

Ladies and Gentlemen we have a winner! Dictionary item 63 looks to be the culprit. But one final check. We copied in ALL dictionary items apart from that one and the form remained intact. It was the sole dictionary item responsible. We called the client and asked them to confirm. Delightedly they did...

Finally it was time to see WHY this dictionary item was such bad news. Opening it in the table builder showed no obvious reason, but reading it then dropping to the debugger so it could be examined properly gave the game away. There was object code on attribute 20. It was still a Rev G format dictionary item and for reasons best known to C++ this confused the form designer.

Armed with this knowledge we could easily inspect the table and others for dictionary items with code on attribute 20 - and to save ourselves the hassle of writing a program we just used a simple RLIST statement


Note that we could have opted to create a new dict item in SYSDICT pointing to column 20 and  query on that but as the AVERY_LABELS table already had a dictionary item pointing at column 20 we used that instead in combination with the RLIST "USING AltDict" syntax.

Now if only we'd gone down the simple route at the beginning. Still it's hard to beat the adrenaline boost you get when you finally get there!

By Sprezz | Friday, 20 May 2016 16:00 | 2 Comments
In what has been one of the most exciting announcements since the trailers for OI 10, Revelation Software have just released UD 4.7.2 and Whilst the small incremental release number might make this seem insignificant it actually marks one of the biggest changes in linear hash since the Universal Driver was released.

For some time now we have been aware of issues with "enterprise" sites where under certain ill-defined circumstances, the network would crawl to a halt and frustrated users would sit helpless until the system eventually recovered. Under certain extreme conditions the system would never recover and the only solution would be to reboot the server with possible ensuing data corruption. After such halts linear hash files would be seen to have "exploded". Growing in size from tens of megabytes to tens of gigabytes.

The suspicion has long been that some form of alpha corruption led to a massive resizing exercise and that this in turn led to the network slowdown.

With the help of a large UK client Revelation staff have finally been able to track this error down and to finally fix it! And while they were under the hood they've made a whole slew of other changes that make fine tuning an enterprise system so much easier!

VSS has been made more reliable.

Resizing has been made programmatically controllable. So a site that experiences peak transaction volumes at specific times can now tell the UD not to do any resizing until it is appropriate to do so. The underlying filing system naturally copes well with this and when the resizing is re-enabled  it can catch up with the necessary tasks.

Size-locking has been revisited and fixed. We have an unpublished blog article about how size-locking was broken in later releases of OI - which made it very difficult to control whether files expanded/contracted or not. This has now been fixed and even better enhanced so that it works with the hidden volume/share feature of the UD so the client no longer needs physical access to the file to set the size-lock.

The UD can now reliably be shut down even if clients are not responding. This fixes an issue where the UD would refuse to close and the server would have to be rebooted to force closure.

A new registry flag has been added called CreateFileFlags. The service expects that, if this registry entry exists, it has a DWORD value. If it’s not set, its default value is the value associated with:


So the developer can now ensure that writes are passed straight through to the disk and not cached. See the Microsoft documentation here.
Not forgetting the fact that the UD now supports encryption AND reestablishing dropped connections!

All of us at Sprezzatura salute Revelation for the mammoth efforts they invested into putting this right - along with grateful thanks to the UK client who made this possible.
By Sprezz | Tuesday, 3 May 2016 10:10 | 0 Comments
At the recent conference in Orlando I was given the opportunity to present a very early preview of the sample application that Sprezzatura will be providing for the final release of OpenInsight 10. To make the application simpler for new users to follow and understand how MV can be used to improve on SQL data structures the decision was made to convert an open source SQL bug tracking system (Bugzilla) to OpenInsight 10.

This article represents a distillation of the conference presentation without the rambling asides and with a little more depth given to some of the tools. If you were at the presentation then thank you for being there - but this isn't a PowerPoint of my talk! As you'll know the talk was just a live dem. (And we didn't hit the debugger once!).

To make the conversion easier pre-conference the decision was made to develop the application in 9.4 and then move it over. To keep this blog post focused I won't include the screen shots of the app that were demonstrated at conference but suffice to say that the data tables were populated with a small sample data set (500 clients, 8 products, 5000 bugs, 1-4 incidents per bug) and supporting windows were constructed to allow viewing of these.

An interesting thing to come out of the work undertaken during the conversion was to see just how tight OpenInsight security has been made. At one stage I found myself unable to log into my system to continue working as the system told me that my passwords were wrong. I was slightly taken aback by this as I was fairly sure that I'd remembered them correctly but rather than waste time asserting that I was in the right I decided to cheat. I installed a new copy of the pre-Alpha in a different subdirectory, logged in using the default passwords and set up my accounts and users again. Then I made a note of the system tables used to store the user details and copied those corresponding DOS LK and OV files over to my compromised system.

I was still unable to log in.

I queried this with Revelation and all was revealed. To stop this sort of backdoor entry from happening, passwords are encrypted using a salt value that is NOT stored with the password.This is a significant improvement over previous behaviour. I still remember being at a PC Trade Show with Release C of Revelation when an attendee came up and suggested to me that he could easily break into our password protected system. I scoffed. He TYPEd the ROS file containing all the system details and logged straight in. It's nice to see this sort of security hole well and truly closed!

Back to the product!

The first thing that strikes you about the product is how simplified and clean the interface appears.

As has been explained before - the above window is just an OpenInsight form designed using several of the new translucency features that make UI potentially so much more attractive in 10. Logging in takes you to the launch pad.

Gone are the myriad of tools and differing ways of opening an entity or creating a new one. Now if you want to create a new message, you simply File/New Entity/Message. Whereas if you want to create a new form you have to File/New Entity/Form. Popups on the other hand are created using File/New Entity/Popup... I think you get the idea! The only exceptions to this currently is for entities using the new improved system editor which have their own menu options.

Choosing the File/New Entity launches the Select Entity window from where you can choose the class and type of the entity you wish to create (or in the case of existing entities File/Open Entity). No more do we have to remember the correct tool to use for an entity. Choose the entity and the correct tool launches. (I know this was possible in the Application Manager but you had to know that - it wasn't intuitive). If you know that the entity you want doesn't use the new system editor then just clicking the New or Open folder image will launch the appropriate selection dialog.

The New Entity dialog contains all possible entities

Whereas the Open Entity dialog only shows entities you actually have - you can hardly open something you don't have now can you?!

Message Designer

The message designer has added a few new features which were the subject of a completely separate talk by David Hendershot, so rather than duplicate efforts I simply made reference to the ability of the designer to render simple HTML commands to improve message appearance...

Consistently throughout the product now when a designer is open, a property panel provides access to the properties of the selected control or entity. You'll see here that I've highlighted the icon property and the cursor property. You can change the cursor to be displayed at run time to a standard cursor or to custom ones of your own.

As stated above the HTML selection is limited in the message designer to those tags shown in the image below.


When QuickHelp was introduced we all hoped that this would remove the burden of creating proper HTML help for users. In AREV we were used to delivering a new system to the end user and training their power user in the use of the system so that THEY could document the system in a way that their colleagues could understand. Unfortunately Windows users are used to better help than plain text so QuickHelp never really took off.

OI 10 addresses this issue and makes QuickHelp editable HTML. So if I define a QuickHelp as follows :-

When I run the QuickHelp it remains editable

but if I set it to read-only the edit controls disappear.

Note also that if you're a real code jockey you can edit the HTML directly by clicking the HTML button at the end of the toolbar.

Form Designer

Where to start with the revised form designer? Well immediately it has to be said that so much has changed that the Form Designer was the subject of several sessions at conference, so my presentation simply highlighted some of the areas that I was most impressed by.

One of the most fundamental  internal changes made to the product has been the way it has been redesigned to be much more "object oriented". Entities have been designed to be reflective so the tool set can ask an entity what properties and methods it supports. No more hard coded lists. You may have noticed that with newer releases of the product, newer properties were not reflected in the form designer - you had to set them at run time. This added to the coding burden in a way that was entirely avoidable if the form designer had allowed access to them at design time. The issue was that the Form Designer had one list of properties and the Presentation Server had another. Keeping them in sync was an issue that was neglected.

With OI 10 all of this has changed. The form designer now exposes EVERY property that is settable meaning that less code has to be written at run time. The properties are exposed in the property panel - so selecting a control allows access to the properties associated with that control :-

If you have multiple controls selected, only the properties common to those controls are displayed in the property panel. So consider EDITFIELD properties and BITMAP properties

The BITMAP obviously has more "Appearance" properties. But if you select an EDITFIELD and a BITMAP together the property panel changes to just "Common Properties" and these common properties can be set by a single adjustment.

Worth noting is the improvement of support for images. Selecting the BITMAP control allows access to the bitmap property dialog where properties of the image in this context can be set. Note that some properties are of the image itself so cannot be set via this dialog.

The property panel also provides access to the events associated with a control via the Events tab

The Events Editor dialog is a work in progress but it has a logical flow that is easily understood. Clicking on an event launches the Events Editor. So clicking on the Click event for the BITMAP control displays an "options button".

and clicking that leads to the Events Editor

At first I was confused by this dialog as nothing was showing. But then I noticed the check boxes from which I can select whether I want a quick event or an event script - or both.

Checking the event script check box displays the event editor

and praise be! The event script finally defaults to 1! The amount of grief that the event script defaulting to 0 caused can now finally be avoided!

Checking the quick event check box displays a slightly familiar set of choices

So - if on the double click of the bitmap we decided that we wanted to send an "Options" event to the Clock No edit line we'd do the following...

Firstly select what we want to happen

Then we identify the control we want it to happen to

and finally we identify the event to be sent

So double clicking the bitmap will send an "Options" event to the Clock Number edit line. As for the "Options" event on the edit line - firstly we tell it we wish to execute a repository method against a chosen popup entity

Then we tell it that on return it should populate the current editfield.

So far all well and good - familiar territory. But then a stroke of genius...

How many times have you had to write code to launch a popup and then send a read event to the screen? No more - there's a new "Finalize" section for quick events. What should happen after the quick event has fired? A wrap up quick event as it were.

So with one simple addition creating screens just got a whole lot easier.

There are so many features of the new form designer to get excited about. For now I'll just leave you with a screen shot of some of the  new control types available to us.

An Aside

When I first started using the product I kept looking to the File menu for the "Most Recently Used" menu so I could return rapidly to wherever I was last working. I couldn't find it so queried this with Rev. Suffice to say that sometimes it's easy to miss what's under your nose! The start screen has the MRU embedded within it!

Even better - the open dialog remembers the tool you were working with last and reorders the open dialog to present you with the tool you were lasting with in a style reminiscent of an MRU. See how this open dialog differs from the initial open dialog presented in the article as since then I've worked with messages, quickhelp and forms!

Another nice touch is the tabbed interface showing you all of the entities that you have open allowing quick return to them.


 Remember reflection?

Well now that tools can simply ask what properties a control exposes the debugger has been re-engineered to take advantage of this! So now ALL properties are available for inspection from the debugger. It now shows all nested controls, all their properties, including UDPs and it has improved fonts so you can work in High DPI.

OpenInsight 10 is a landmark release for us developers and personally I can't wait to get developing real world applications with it. I'd actively encourage you to play with the Alpha available for download for Works members from here.

I look forward to interacting with you all on the Beta forum in due course!
Pixel Footer R1 C1 Pixel