|Issue 65 February 12 2009|
Meet your new friend, Behaviors
The other day I started working on a new desktop application in Revolution. Usually I'm happy to have the native operating system appearance for my software. But this application is a complement to an existing Web application and I needed to mimic the look-and-feel of the website, down to pixel precision. The website contains numerous non-standard, custom option menus that look something like this:
So I set out to create a custom control that provided the same appearance by assembling various Revolution objects. Here is what I ended up with:
All of these controls were contained in a group, as follows:
So far, so good. But now that I had the controls grouped together, I had to script all of the user interactions that I would normally get "for free" had I used Revolution's built-in Option menu. Once I had the basics of the control in place, I started using it in the application. The first card I had to work on required five instances of this custom menu control. Of course, as I continued putting the application together, I had to go back to my custom control's script to fix bugs or add new functionality. Now, on a normal day I would have grown weary of changing the group script in one of the custom controls and then copying and pasting the changes into the other four instances. Each time a change was made I would have repeated this same exercise over and over again. But this was no ordinary day. No, this was a special day because I was using the developer preview release of Revolution 3.5, which introduces a new feature called Behaviors, or "parent scripts." Rather than copying and pasting my code between the five groups each time a change was made, I simply updated the script of a single button and the behavior of all five of my custom controls was instantly -- if not magically -- updated.
Introducing parentScript Behaviors
Notice how the "ParentScript" button script receives the message right after the field control. The field appears to have it's own personal backscript, right? Yes, but it is even better than just having a private backscript. What is really cool is that the script in the "ParentScript" button thinks it is the script of the field control.The Importance of 'me'
Let's look at what this case of "flexible" identity means to us developers. Normally, the keyword 'me' refers to the object that contains the currently running handler. If I have a script in a field with the line:
put the text of me
Then 'me' refers to the field the script is in. But in the context of a parent script 'me' refers to the control the parent script is attached to, not the object where the script actually resides. So while writing "put the text of me" in a button would normally return the text of the button, when that button is the parentScript of a field, that same code would return the text of the field. In practice this means you can use the 'me' keyword throughout your parent scripts and the code will always refer to whatever object you attach it to.
Because of how 'me' is resolved in parent scripts you'll find it easy to migrate your existing handlers. You can simply copy and paste code that once resided in a field or group into a button and it will more than likely work if you used 'me' references throughout. I was able to convert one such script in under 10 minutes.
Without parent scripts you would have to copy the script into each field that required numeric input or add a closeField handler somewhere in the message path (frontScript, group, card, stack, library or backScript) that determined whether or not the control receiving the closeField message required numeric input.
Neither solution is optimal:
But with parent scripts you simply create a single button (mine is named "Number Formatter") and add the closeField handler to it. Once you assign the button as the parentScript of a field, that field will automatically start converting any input into a number.
Here's another example. Mac OS X and Windows operate very similarly, but have some important differences in their user interface requirements. One of the most annoying is that the position of the "OK" and "Cancel" buttons is swapped. While Revolution handles most interface differences for you automatically, it won't touch your custom modal dialogs (which are usually implemented as substacks). If you want to have a nice, cross-platform application then you either have to pick one or the other way of handling these buttons (upsetting the nitpickers on the other platform, or possibly leading to the wrong button being clicked by accident), or you have to code a solution that automatically arranges the buttons properly. Not a problem if you have only one custom dialog, but how about if you have several? It becomes a headache for the same reasons listed above.
The solution is a parent script that arranges controls based on platform:
With the introduction of parent scripts Revolution 3.5 will change the way that behaviors are shared in Revolution. Not only can you easily create and reuse behaviors in your own applications, but this opens the door for 3rd party developers to create and share useful custom controls with the Revolution community.