To make a part scriptable, changes must be made to the part and to the IDL that describes the part. A script extension object needs to be provided.
The script extension object is a subclass of an ODExtension object that provides most of the logic needed to associate an ODPart with an available scripting component. The script component is supplied by a language developer and provides the script language interpretation, debugging, and editing facilities. The script extension initiates and manages the interaction between the part and the script component. Most of the logic of the script extension class applies to all parts, but there are methods that must be customized to reflect the particular part for which it has been subclassed.
The script extension for your part is a class that inherits from the ODScriptExtension class. Several methods of this class must be overridden to reflect your part's specific characteristics.
For additional information on the methods mentioned in the following sections, see ODScriptExtension class in the OpenDoc Programming Reference.
For all parts, this routine must properly register the scriptable part and its class. The default behavior of this method registers the class of the associated part and that part object with the scripting component. Registration makes the object available for access from the user's scripts. This method provides a name for the part, by which it can be referenced in the scripts. The name for the part is how it is referenced from the scripting language. The script extension must assign this name, pass it to the script component, and preserve the association of the name with the part when the part is externalized and reloaded.
If scripting support for your part requires access to objects other than the associated part, or if script writers need to access classes other than the class of the part, then the overriding logic you provide must assure that those classes and objects are registered with an appropriate name for each such object.
In some cases, it is useful to provide an object that provides an interface for scripting and uses an OpenDoc part to provide the user interface. In this case it is possible for the register logic to identify this object to the script component. The script component accesses the surrogate part that in turn accesses the OpenDoc part. This method can be used to separate the scripting aspects of a part from the details of its implementation in the OpenDoc environment.
If the part is a container part, you must ensure that each contained part is registered. The part and the script extension object must provide the logic to request that any contained scriptable part be registered. The extension and the part must work together to ensure that the names assigned to all registered objects and contained parts are unique and are preserved when the application is saved to persistent storage.
This method is the converse of the Register method. This method removes specific objects from script accessibility. The default behavior of this method causes the part object to be deregistered with the scripting component. The object is no longer available for access by the user's scripts. When the Register method passes different objects to the script component, then DeRegister must be overridden to deregister the same set of objects that were registered. If the part is a container part, then each contained, scriptable part must have its DeRegister method invoked.
The default behavior of this method does not provide any specific component requirement identification flags. These flags are a combination of the component function flags that specify the functions that must be provided by a scripting component. The flag values used by scriptable parts are defined in scrcomp.xh. The default logic leaves the ScrCompFlags attribute and ScrCompFlagsMask attribute set as zeros permitting the part to be scripted by any script component. If your part has a requirement for specific support capabilities, these attributes should be set to the appropriate values in this routine. The ScrCompFlags should be set to reflect the capabilities that the script component must support (flag set on) or must not support (flag set off), and the ScrCompFlagsMask attribute should be set to reflect all the capability flags which should be tested.
For details on how these values are processed, see Component Access Interface.
To ensure that your Part provides the correct interface and behavior, the implementing code must support the script extension and invoke its methods at the proper times.
These two methods, that a part inherits from the ODObject parent of ODPart, must be modified to properly handle requests for kODScriptExtension. When the argument to these routines has this value, HasExtension should return kODTrue and AcquireExtension should ensure that the Part specific ODScriptExtension object is created, acquire a reference to that object, and return that reference to the caller.
When your part is externalized, you must ensure that the persistent information needed by the script extension is preserved. This can be done by invoking the ScriptExternalize method of the script extension during the Externalize or CloneInto logic of your part. This routine adds the script extension's persistent data to the storage unit for your part. This information includes the identifier of the script component that supports this part and the actual scripts that have been written by the user to support your part.
When you reinitialize your part from saved data in its storage unit, it is necessary to reinitialize the script extension from its saved information. This can be done by invoking the InitScriptFromStorage method of your script extension object. This results in reloading the scripts associated with your part, reaccessing the appropriate script component, and reestablishing the mapping between names and the objects of your part and its contained parts.
The following modifications are not overrides or additions to defined methods but are logic that may need to be added to your part's code at appropriate locations.
To initiate scripting for your part, some user action needs to be interpreted as a request for that action. The normal mechanism is to add an item to the Edit menu dropdown list to be interpreted by your part as a request to initiate scripting. When that menu item is selected by the user, your part should invoke the InitEditor method of the script extension. This method locates an appropriate script component, registers the part with that script component (by calling Register), and then requests the script component to bring up its script editor interface.
It is desirable to allow a user to request that all the scripting logic that is associated with your part be removed. A menu item in the Edit menu dropdown is the normal way to present this option. When it is selected, the EndScripting method of the ScriptExtension should be called. EndScripting deregisters the object and any contained objects, requests that the script component remove all information about the scripts attached to this object, and closes the script component (removes its interface).
If your part is a container part, it should keep the script extension object informed as contained parts are added or removed from your part. At the point where a new part has been included within your part, the script extension method, AddContainedPart should be called with a reference to the newly added part. When a part is removed from the set of contained parts, the script extension method, DropContainedPart, should be called with a reference to the part. These two methods ensure that the part is properly registered (or deregistered) with the script component for your part and any parts that contain your part.
Only methods, attributes, and events that are properly identified in the part's IDL will be visible to the script component. Each method defined by the part and available to the script writer needs to be identified as a scriptable method by providing an ODid modifier as part of the method's IDL. Any events which your Part recognizes and invokes need to be described using the ODevent modifier as described in ODevent (I). The other modifiers defined in Annotating the IDL provide additional support and description for a class which is to be scriptable. The script component reads the SOM Interface Repository that contains the compiled information from the IDL and uses that information to determine which methods, attributes, and events are part of the scripting interface for the class. Your part's script extension may register any SOM classes needed for scripting your part and may choose to register an object other than the ODPart as part of the scripting interface. Any class that is registered for script access needs to be appropriately annotated with the IDL modifiers and must be included in the OpenDoc Interface Repository file.
Any events which are raised by the objects you register with the script component should implement their methods in accordance with the interfaces defined for the ODEvent class as described in OpenDoc Event Notification. The script component can supply target code for such events that are defined by the application developer in the script code.
A script component is a separately packaged and installed set of code that provides a scripting language development and execution environment for OpenDoc parts that are enabled. The script component that is appropriate for a part is created and attached through the script extension object to that part. The script extension object uses the methods defined for the script component class to control the attachment, persistence, and interface for the script component. The script component provides the user interface for script editing, testing, and execution.
Component developers implement the script component for a language.