-
Notifications
You must be signed in to change notification settings - Fork 9
Plugins
Plugins are dlls that contain types that implement two interfaces: IPlugin
and IWatchViewer
. IPlugin
s produce IWatchViewer
s from traditional FsEye tree view watches to provide alternative views of a watch value. Plugins are deployed either along side FsEye.dll or in the plugins
sub-folder (preferred) (FsEye automatically loads these upon start-up, though plugins may also be programmatically registered or removed).
FsEye includes two plugins out-of-the-box: FsEye.TreeView.Plugin.dll and FsEye.PropertyGrid.Plugin.dll. The former is simply the traditional FsEye TreeView
-based watch viewer wrapped as a plugin. The latter wraps the WinForms PropertyGrid
control.
Plugin watch viewers are displayed in tabs on the right-hand-side of a split panel (the "plugin panel") with the traditional FsEye watch viewer kept on the left-hand-side (the "main panel"). When no plugin watch tabs are open, the plugin panel is hidden. When a watch in the main panel is right-clicked, you will be presented with a context menu containing a Send To
menu item (which may be hidden or disable based on the context, such as whether the selected watch has its value loaded) which has the following organization
Send To -> PluginA -> New
-
PluginA 1
PluginA 2
-> PluginB -> New
-
PluginB 1
If we chose Send To -> PluginA -> New
we would send the selected watch to a new watch viewer instance for the given plugin.
If we chose Send To -> PluginA -> PluginA 1
we would send the selected watch to the existing watch viewer instance for PluginA (replacing or updating it according to the rules implemented by the plugin author).
The created or updated plugin watch viewer tab will receive receive focus.
Various options for closing plugin tabs are available by right-clicking a given tab. These are Close, Close Others, and Close All. Close Others will be disabled if there is only one tab. When all tabs are closed, the plugin panel will become hidden.
The following public classes have been renamed in FsEye 2.0.0 to reflect the growing breadth of functionality they now handle:
- WatchPanel -> EyePanel
- WatchForm -> EyeForm
The following types now expose a public property PluginManager
which is used to programmatically manipulate plugins: Eye
(the primary surface for manipulating FsEye within FSI), EyeForm
, and EyePanel
.
The PluginManager
object is responsible for managing plugins. As mentioned previously, plugin authors implement two interfaces, IPlugin
and IWatchViewer
. These interfaces are wrapped by two record types, ManagedPlugin
and ManagedWatchViewer
. The following are the definitions for these types (with some members removed for simplicity):
///Represents a plugin watch viewer being managed by the PluginManager
type ManagedWatchViewer =
{///The unique ID of the watch viewer instance
ID: string;
///The watch viewer instance which is being managed
WatchViewer: IWatchViewer;
///The owning ManagedPlugin
ManagedPlugin: ManagedPlugin;}
///Represents a plugin being managed by the PluginManager
and ManagedPlugin =
{///The plugin being managed
Plugin: IPlugin;
///The owning plugin manager
PluginManager: PluginManager;}
with
member ManagedWatchViewers : seq<ManagedWatchViewer>
end
///Manages FsEye watch viewer plugins
and PluginManager =
class
///Initialize and load any plugins in the "plugins" folder relative to the executing assembly
new : unit -> PluginManager
///Register the given plugin and return the managed plugin wrapping it. If a managed plugin wrapping a plugin of the same name exists,
///removes it (and all of its associated managed watch viewers).
member RegisterPlugin : plugin:IPlugin -> ManagedPlugin
///Remove the given managed plugin (and all of its managed watch viewers).
member RemoveManagedPlugin : mp:ManagedPlugin -> unit
///Remove the managed plugin (and all of its managed watch viewers) by name.
member RemoveManagedPlugin : name:string -> unit
///Remove the given managed watch viewer, disposing the watch viewer's Control.
member RemoveManagedWatchViewer : mwv:ManagedWatchViewer -> unit
///Remove the managed watch viewer by id, disposing the watch viewer's Control.
member RemoveManagedWatchViewer : id:string -> unit
///Create a new watch viewer for the given managed plugin, sending the given label, value and type.
///Returns the ManagedWatchViewer which wraps the created watch viewer.
member
SendTo : managedPlugin:ManagedPlugin * label:string * value:obj *
valueTy:System.Type -> ManagedWatchViewer
///Send the given label, value and type to the given, existing managed watch viewer.
member
SendTo : mwv:ManagedWatchViewer * label:string * value:obj *
valueTy:System.Type -> unit
member ManagedPlugins : seq<ManagedPlugin>
member ManagedWatchViewers : seq<ManagedWatchViewer>
member WatchAdded : IEvent<ManagedWatchViewer>
member WatchRemoved : IEvent<ManagedWatchViewer>
member WatchUpdated : IEvent<ManagedWatchViewer>
end
For API users interested in the IPlugin
and IWatchViewer
interfaces, see the section for plugin authors.
Note that adding, removing, and updating watches triggers the WatchAdded
, WatchRemoved
, and WatchUpdated
events of the plugin manager. The GUI plugin panel listens to these events to add, update (select), and remove the tabs it controls.
Plugin authors should be well versed in the documentation provided for all other types of users. The following are the definitions for the interfaces plugin authors are required to implement, they are found in the Swensen.FsEye namespace:
///Specifies a watch viewer interface, an instance which can add or update one or more watches with
///a custom watch viewer control
type IWatchViewer =
interface
///Add or update a watch with the given label, value, and type. Note: you can choose to
///disregard the label and type if desired, but will almost certainly need the value.
abstract member Watch : string * obj * System.Type -> unit
///The underlying watch viewer control. Exists as a property of IWatchViewer
///since you may or may not own the control (i.e. you cannot directly implement IWatchViewer on the control).
abstract member Control : System.Windows.Forms.Control
end
///Specificies a watch view plugin, capable of creating watch viewer instances
type IPlugin =
interface
///Create an instance of this plugin's watch viewer
abstract member CreateWatchViewer : unit -> IWatchViewer
///Returns true or false depending on whether the given instance and its type (which we may need if
///the instance is null) are watchable: if false, then FsEye will not allow creating a watch for a value
///of the given type. Plugin authors should be mindful of the performance impact this method may have.
abstract member IsWatchable : obj * System.Type -> bool
//The name of the plugin
abstract member Name : string
end
these should be implemented as class libraries (.dll assembly files) targeting .NET 2.0 or greater with processor AnyCPU or x86 platforms (FsEye.dll, FsEye.PropertyGrid.Plugin.dll, and FsEye.TreeView.Plugin.dll all target .NET 4.0 with processor AnyCPU platform).
PluginManager.RegisterPlugin
is a nice way to interactively develop and test plugins through FSI.
The out-of-the-box PropertyGrid
(FsEye.PropertyGrid.Plugin/PropertyGridPlugin.fs) and TreeView
(FsEye.TreeView.Plugin/TreeViewPlugin.fs) plugins may service as an implementation reference.
If you are developing a plugin, we'd be interested to hear about it! Eventually, we plan to have a "PluginGallery" wiki page to feature links to 3rd party FsEye plugins.