Fourth World Logo Fourth World Media Corporation
  Embassy Services Products Resources   About Fourth World Contact  
logo

Using and Making Plugins for Runtime Revolution

Richard Gaskin
Fourth World Media Corporation
ambassador@fourthworld.com

Copyright ©2004 Fourth World

This document may be distributed freely only in its complete, unmodified form, including this header and copyright information.

Abstract
The Runtime Revolution development environment can be easily extended through plugins written in Revolution's native scripting language, Transcript. This article describes how to use plugins, where to find more, and how to create your own.

Keywords: Runtime Revoluton, plugins, Transcript, libraries, scripting, utilities


Introduction

Runtime Revolution's Transcript scripting language has a simple yet powerful message inheritance scheme which is inherently extensible to minimize code redundancy and maximize reuse. This article describes how to use libraries, backScripts and frontScripts effectively to achieve those goals.

Revolution's Native Message Path

Runtime Revolution's object model is easy to learn and work with, while flexible enough to build nearly any user interface an application needs. Similar to how Visual Basic places controls on forms, in Revolution you place controls on cards. Where Revolution goes beyond most implementations of Basic is that it natively accommodates multiple screens, or cards, within a given window, allowing rapid development of wizards and multimedia apps easily.

Revolution goes even further to provide an object that acts as a container of control lists (cards), called a stack, which has its own script.

One of the most useful aspects of this object model is that the event messages that drive it are inherited by each object in the hierarchy. For example, when the user clicks on a button control a mouseUp message is generated which can be handled in the script of the button control. If there is no mouseUp handler in the control script the message is passed to the card, and if not handled there it's passed to the stack, and then to the Revolution engine where any default behavior may be invoked.

It's worth noting that a collection of controls can be placed inside of a group object, which by default only receive system messages in response to user events in objects contained within it. Groups can be nested, and scripts within a given group can be called by other groups within it.

A group can be made to receive card messages by setting the group's backgroundBehavior property. When this property is active such objects are often distinguished from other groups by referring to them as backgrounds. When receiving such messages, a background occupies a place between the card and the stack for compatibility with similar languages.

If any object in the message path has a handler for a given message, by default the message is not sent further down the path. You can override this default behavior by using the pass command to allow the message to continue through the native message path:

on mouseUp
  put "Hello World!" into field 1
  pass mouseUp
end mouseUp

Figure 1 illustrates the simplest form of the Transcript message path.

Runtime Revolution message path

Runtime Revolution message path

Figure 1: Native Transcript message path



Extending the Message Path

While the native message path is quite powerful, it has some limitations. For example, what if you wanted to use a library of handlers across multiple projects, or handle messages before even controls get them? Fortunately Transcript provides three different mechanisms for extending the message path: libraries, backScripts, and frontScripts.

Libraries

HyperCard first introduced libraries with the addition of the start using syntax:

start using "MyLibraryStack"

The start using command inserts the script of the specific stack object into the back of the message path. A script brought into use in this way can be removed with the stop using command:

stop using "MyLibraryStack"

Later this concept was expanded on by Oracle Media Objects with the addition of a libraryStack message, sent to the stack object immediately after it is brought into use, useful if the library needs to perform any initialization:

on libraryStack
  global gInited
  put true into gInited
end libraryStack

A releaseStack message is provided as a corollary to libraryStack, sent when a stack script is removed from the message path with stop using, useful for any housekeeping that may need to be done before the library is removed:

on releaseStack
  global gInited
  put empty into gInited
end libraryStack

Revolution supports all four of these constructs for libraries.

BackScripts

SuperCard introduced two alternatives for extending the message path, which are both fully supported and improved upon in Revolution: frontScripts and backScripts.

The advantage of backScripts over libraries is that you are not limited to using only stack scripts; the script of any object can be inserted into the message path with the insert script command:

insert script of button "ScriptUtilities: into back

Scripts inserted into the message path this way can be removed with the remove script command:

remove script of button "ScriptUtilities" from back

Note that unlike libraries, backScripts receive no notifying message when they are inserted or removed.

Where Revolution has improved on SuperCard's original implementation of backScripts is that a script can be edited in Revolution without first removing it from the message path, whereas in SuperCard the script must be removed and re-inserted to reflect any changes made while it was in the backScripts.

Also, in SuperCard the order of insertion is strictly enforced, such that a script inserted after another does not have direct access to the first script's handlers and must call them explicitly using the send command (see "Changing the Firing Order of Messages" below).

In Revolution all libraries and backscripts can freely call each others' handlers by name, with the order of insertion only coming into play in the event that two scripts contain handlers of the same name; in such cases libraries take precedence over backscripts, and scripts inserted first take precedence over scripts inserted later.

FrontScripts

FrontScripts are inserted into the front of the message path, before any other object gets a message. This can be useful for implementing logging features where you can write a record of user activity to a file, or for implementing plugin utilities where you might want the plugin to have access to messages like selectedObjectChanged in order to update itself.

Like backScripts, frontScripts are inserted and removed with the same commands:

insert script of button "MessageTraps: into front

remove script of button "MessageTraps" from front

Figure 2 shows the Transcript message path with all extensible scripting options.

Runtime Revolution message path

Figure 2: Transcript message path showing
frontScripts, libraries, and backScripts

Changing the Firing Order of Messages

While messages ordinarily travel only through the message path as shown in the figures above, you can invoke handlers in scripts of objects outside of the current message path with the send and call commands:

send "mouseUp" to button "Cancel"
call "CalculateTotals" of button "Total"

The difference between the send and call commands is that the send command changes the context so that object references are treated as relative to the object you send the message to, while the call command does not change the context and continues to treat object references relative to the original object.

Special Considerations

ScriptLimits

One thing to keep in mind when using libraries, backScripts, and frontScripts is the difference in the number of each of these allowed when running outside of the Revolution development environment, such as in a standalone or with a player. These limits are noted in the scriptLimits function, which (as of this writing) at runtime returns 10, 10, 50, 10 when running as a standalone, which corresponds to (in order):

• the number of executable statements permitted when changing a script (10)
• the number of statements permitted in a do command (10)
• the number of stacks permitted in the stacksInUse (50)
• the number of objects permitted in the frontScripts and backScripts (10)

These limits only apply when running outside of the Revolution development environment. When working in the Revolution development environment no such limits exist.

Purging Stacks

Revolution gives you the option of determining whether a stack will remain cached in memory or be purged when it is closed. This is determined by the destroyStack property, which is set to false by default. The name of this property refers only to the copy of the stack in memory; when true, a stack is purged from memory when closed.

You have to be careful if the stack containing scripts that extend the message path, either with the start using or insert script commands, has its destroyStack property set to true. As of this writing, as soon as you close the stack all of its scripts will be removed from memory with it, so they will no longer be present in the message path.