Extending Plugins

Although plugins can be developed as stand alone modules they can also interact so that one plugin extends the functionality provided by another. To allow a plugin access to the functionality of a second the first plugin must include the second as a dependency.

For example, a plugin wishing to interact with the QuickSharp.Workspace plugin must specify a dependency like this:

public List<Plugin> GetDependencies()
{
    List<Plugin> deps = new List<Plugin>();
    deps.Add(new Plugin(
        QuickSharpPlugins.Workspace, "QuickSharp.Workspace", 1));

    return deps;
}

The QuickSharpPlugins helper class allows the workspace plugin ID to be specified conveniently; for a custom plugin the ID must be included directly.

Now that the dependency has been specified it is safe to access the types and methods defined by the Workspace plugin. Although the plugin namespace is now accessible, the entities defined within it may not be immediately available. Different components will require different techniques to gain access.

Accessing modules

Typically, a plugin will be implemented in a class named Module which is instantiated by the plugin loader to activate its functionality. Once the plugin has been activated the module will normally be discarded. A plugin module might contain public methods or properties that could be required elsewhere in the application. To make sure the module remains accessible a proxy class can be defined to contain a reference to the module object.

For example, the QuickSharp.BuildTools plugin contains a module proxy class and this provides access to the public members defined by the plugin module. To access them use the Module property of the proxy like this:

QuickSharp.BuildTools.ModuleProxy proxy =
    QuickSharp.BuildTools.ModuleProxy.GetInstance();

proxy.Module.UpdateBuildToolStatus();

This technique can be used to make any public members accessible to other plugins.

Accessing transient forms

Another proxy class technique allows the properties of a transient form to be accessed from another plugin. A transient form is a form that appears temporarily within an application. Examples are the application about box, the main options editor and the application update check form.

As these forms don't exist until they are invoked it is not possible for a plugin to directly interact with them as the plugin activation process will be long complete by the time these forms are invoked. To overcome this a form proxy class can be defined to allow code to be attached by the plugin when it is activated so that the form can call it when it is invoked.

For example, the QuickSharp.Core.UpdateCheckFormProxy includes a public event 'FormControlUpdate' which allows event handlers to be added by a plugin. When the UpdateCheckForm is invoked it raises the event passing its control collection to each of the event handlers attached to it. The code in these handlers now has access to the form's controls and can make any changes required to customize the form.

Accessing docked forms

If the plugin contributes a docked form to the application is will be registered with the application manager. This allows the form object to be accessed from another plugin; the following code demonstrates how to access the workspace:

ApplicationManager applicationManager =
    ApplicationManager.GetInstance();

WorkspaceForm workspace = applicationManager.GetDockedForm(
    QuickSharp.Workspace.Constants.DOCKED_FORM_KEY)
    as WorkspaceForm;

if (workspace != null)
{
    // access the workspace here...
}

Be sure to add the appropriate assembly references and a using directive for the QuickSharp.Workspace namespace.

This technique is applicable to all docked forms including the output window and the explorer view; change the form class and namespace references to the appropriate values.