Tag Archives: Commuter Module

What’s “this”?

As I’m sure many of you will know, when you’re working with object oriented languages like C++, JavaScript and VB , the compiler provides you with a keyword (e.g. ‘this’ or ‘Me’) that you can use as a reference to the specific instance of an object under which the code is currently executing.  This provides a neat and easy way to access details about the current context when responding to events and methods, and generally improves the clarity of the code.

However, a ‘this/Me’ construct is not something we’ve really had in OpenInsight, because when we write our event handling code the system explicitly passes the name of the current object as the first argument called “CtrlEntID”, so in our event scripts we can use that instead.  Obviously this works well enough, but over the years I’ve found some situations where it would be nice to go a little further:

  • In many of the OpenInsight training courses I’ve run, one of the most common questions I get asked from new students is: “what is the equivalent of ‘this’, or “where is the ‘Me’ keyword”?   Having some sort of “this/me” construct in Basic+ would make learning the system much easier for them, and the name “CtrlEntID” hardly seems slick!
  • With the trend away from using event scripts and moving code into commuter modules the name “CtrlEntID” is no longer enforced – it can be named anything the author of the commuter module wishes, leading to a possible loss of clarity (for example in my own commuter modules I always use the variable name “Object” in place of “CtrlEntID”, but that’s just my convention, and is something subsequent code maintainers must adopt).
  • As code becomes deeper and more nested passing the “CtrlEntID” variable to each subsequent procedure as an argument becomes more of a chore, and I’ve seen global variables used in place of this which can lead to code that is difficult to maintain.

Of course, we do have the “@Window” system variable, which contains the name of the parent WINDOW instance for the currently executing context, so we’re nearly there, but unfortunately that’s not the same as ‘this/Me’ unless you’re responding to a WINDOW event.

So, with the release of version 10.0.8 we’ve now gone the whole way and added a new system variable called:

@Self

When an event is triggered this variable contains the full name of the control instance under which the event code is executing, just like @Window contains the name of the parent WINDOW instance.

E.g:

// Using CtrlEntID
Name = Get_Property( CtrlEntID, "TEXT" )

// Using @Self
Name = Get_Property( @Self, "TEXT" )

We’ve also included two more system variable names as synonyms for @Self as well:

@This
@Me

You may use these in place of @Self if you’re more inclined to use names that are familiar from another language (@Self was chosen because it is already referenced in OpenInsight as a pseudo-variable name when defining QuickEvents).

Hopefully, moving forward, this small addition may help to maintain a cleaner code-base and make teaching new students a little easier.

 

OpenInsight 10 and QuickEvent Processing

OpenInsight 10 introduced a couple of changes to how QuickEvents are processed that you may or may not be aware of, so in this post we’ll take a look at them so you can see how they work.

1) QuickEvent arguments are now passed by reference

In previous versions of OpenInsight, arguments passed to QuickEvents were duplicated and passed as copies, which meant that if you altered them in your Commuter Module you wouldn’t see the changes in the calling routine.  As QuickEvents are normally the last item processed in the event chain this is not something you might actually notice, unless perhaps you were using the Forward_Event() procedure from an Event Script.

Event arguments in version 10 are now passed by reference, which means a calling routine will see any changes you make to them.  This is an important point to bear in mind now that it’s possible to alter the order in which QuickEvents are executed in the event chain (see the “Has Priority” flag section below), so be careful when using those arguments in your Commuter Modules.

2) The new “Has Priority” flag

Under normal circumstances QuickEvents are always the last handlers processed in the event chain which normally looks something like this:

  1. Control-specific Event Script
  2. Promoted Events
  3. “System” Promoted Events
  4. QuickEvent

For most purposes this works fine, but there are occasions when you might need to step in front of the system code to do some pre-processing on events such as READ and WRITE, and unfortunately this usually involves writing an Event Script (or a Promoted Event perhaps) to contain your pre-system code like so:

E.g.  Sample pre-WRITE Event Script

Function WRITE( CtrlEntID, CtrlClassID )

   $Insert Logical
   WriteOK = TRUE$

   // Check if we can save the record - if not then WriteOK will be 
   // Set to FALSE$ which will stop the event chain
   GoSub CheckOKToWrite
 
Return WriteOK

However, this removes one of the main advantages of using Commuter Modules in the first place: i.e. the ability to keep all of your code in one place. To alleviate this you could just place your pre-WRITE code in your Commuter Module and call it directly :

Function WRITE( CtrlEntID, CtrlClassID )

   $Insert Logical

   // (Assume Commuter Module ID is the same name as the form with an 
   // "_EVENTS" suffix)
   CommID  = @window[1,"*"] : "_EVENTS"
   WriteOK = Function( @CommID( CtrlEntID, "PREWRITE" ) )
 
Return WriteOK

But then you’re still having to create the Event Script, so you still have a fragment that you need to track.

With version 10 we added a new flag to the QuickEvent handler called “Has Priority”:

QuickEvent definition showing the "Has Priority" flag set

“Has Priority” QuickEvent

If you set this to True the event chain is changed to this instead:

  1. Control-specific Event Script
  2. QuickEvent
  3. Promoted Events
  4. “System” Promoted Events

Which means that you can place something like a WRITE event handler in the Commuter Module, do your pre-processing, and return TRUE$ to allow the system to continue the chain, or use Forward_Event() if you need to do some post processing as well.

Points to note:

  • If you call Set_EventStatus( TRUE$ ) in your Commuter Module QuickEvent handler the event chain is stopped.
  • If you return FALSE$ (“0”) from your Commuter Module QuickEvent handler (and it has to be “0”, not null) the event chain is stopped.

Hopefully this removes the need for Event Scripts for writing pre-system events and should help to keep your applications a little more streamlined and organized, and preserve the benefits of using Commuter Modules.