Developer's Guide: Plugin Objects

Export Filters | Plugins | User Interface

## Plugin Objects

Plugin objects provide a way to define new types of objects. Plugin objects can define how the user interacts with them and they can be saved to and loaded from sk files. The design of plugin objects takes the problem of loading files containing plugin objects that a particular Skencil installation doesn't know about into account.

An example of a plugin object is the regular polygon object that comes with Skencil.

### Design Philosophy

The idea behind plugin objects is that they're groups of builtin objects with some special attributes and behavior on top of that.

What a plugin object looks like is completely defined by the children. This is the key to being able to load drawings with unknown plugin objects. Because the children are builtin objects Skencil can display and print them without problems by treating them more or less as ordinary groups.

### Saving and Loading a Plugin Object

A plugin object is saved as a special compound object together with all its children. When Skencil reads an sk file with a plugin object that it doesn't know about it can still treat is like a normal group and since all drawing is done by the children it can still display and print it.

Skencil is actually a bit smarter than that. It doesn't turn unknown plugin objects into normal groups, it turns them into an UnknownPlugin object that remembers which class the object belongs to and what parameters were used. As long as the object isn't changed it is saved as a plugin object again.

### Configuration Variables

For plugin object configuration, Skencil uses the following variables:

`type`

  The type must be `PluginCompound`. This identifier is defined in the globals() dictionary.

`class_name`

  A string containing the name of a Python class defined in the module. See below for the interface this class has to provide.

  Skencil uses the class_name to distinguish different plugin types and should therefore be unique. A future version of Skencil will probably use a different name for that purpose.

`menu_text`

  The text to display in the menu as a string. In the 0.6.x, this text is used for the entry in the Edit->Create menu.

`standard_messages` (optional)

  A boolean indicating whether the messages in the plugin are standard messages that are defined in Skencil's message catalogs. For third-party plugins this should be omitted.

`parameters` (optional)

  A tuple of tuples describing the parameters of the object. This information is used to create a dialog that allows the user to set the parameters for new objects and modify those of existing objects.

  See below for more detail.

`factory` (optional)

  The name of a function that is to be called by the user interface code instead of the class to create a new object. The sk import filter always calls the class directly.

`uses_selection` (optional)

  If this boolean is true, the factory, if defined, or the class will be called with a list of objects as the only parameter. These objects are the ones currently selected.

  When omitted, it defaults to 0.

`custom_dialog` (optional)

  The name of a dialog class that is to be used instead of the dialog automatically built from the parameters information.

### Implementation of a Plugin Object

Many plugin objects have some parameters that the user can set and modify and that have to be saved and read in again.

For the user interface part, there are two mechanism to deal with parameters. They can either be defined by the `parameters` configuration variable in which case Skencil automatically builds a dialog from the description or the plugin can implement a custom dialog and tell Skencil to use it with the `custom_dialog` configuration variable.

The `parameters` variable has to be sequence of pentuples each of which defines one parameter. The pentuple has the form

`(name, type, default, range, label)`

where label is text suitable for a label in the dialog box. name is the internal name for that property. The constructor of the plugin object must accept a keyword argument name. Also, the plugin object must have a method Capname to read the current value of that property and a method `SetParameters` accepting a dictionary of parameters and returning undo information. Capname is a `Capitalized' version of the lowercase name (if name is `the_parameter', Capname is `TheParameter')

type describes the type of the parameter, default is the initial value and range describes the valid values.

Supported types:

type | range
--- | ---
int | (MIN, MAX) | the minimal and maximal value. MIN and/or MAX may be None indicating no limit (apart from the builtin limits).
float | (MIN, MAX) | same as for int
length | (MIN, MAX) | A length in pt. The user can change the unit.
text | ignored | A text string (the range should be None for now)

Saving of plugin objects works a little differently for sk-files than for other, non-native file formats.

Export filters for non-native file formats treat plugin objects just like groups. That means you don't have to do anything special, but it also means that any extra information associated with the plugin-object will be lost.

Saving to an sk-file is done by the `SaveToFile` method which is called with an `SKSaver` instance, customarily called `file`. `SKSaver` is defined by the sksvaver plugin. The plugin-object is expected to first call `file.BeginPluginCompound` with appropriate arguments, then to call each child's SaveToFile method with `file` as the only argument and finally `file.EndPluginCompound` with no arguments.

`BeginPluginCompound` has the following syntax:

`BeginPluginCompound(plugin_name [, arg1, ...] [, kwarg1 = value1, ...])`

  Start a plugin compound object in the sk file. plugin_name has to be the same as the configuration variable class_name.

  All remaining arguments, whether positional or keyword arguments, should be builtin python types. They're written to the file as is. The keywords if used must be names of parameters if the configuration variable parameters is used.

  When the file is read in again the plugin class is called with these arguments to create the instance.

### The class `PluginCompound`

To make implementation easier, Skencil provides a base class for plugin objects. `PluginCompound` has a default implementation of `SetParameters` which assumes that the parameters are instance variables that have the same name as the parameters.

Furthermore, it has an implementation of `SaveToFile` that has to be extended by the derived class. All the derived class has to do in its implementation of `SaveToFile` is to call the inherited method with the same arguments as the SKSaver method `BeginPluginCompound` except the class name. The class name is expected to be in a (class-)attribute called `class_name`.

For examples see the regular polygon and the LCD-text objects in `Plugin/Objects`.

Export Filters | Plugins | User Interface