xxtbg / fseye

Automatically exported from code.google.com/p/fseye
Apache License 2.0
0 stars 0 forks source link

Create plugin architecture and manager #25

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
Ideas:

1) Provide an interface to implement which accepts an FsEye WatchModel instance 
and returns a Control or Form instance which can be shown by FsEye. Perhaps the 
plugin itself will be held by FsEye as a singleton and have configuration 
properties like context menu text (I am envisioning plugins being invoked via 
right-click context menu on a watch node) and modal vs. non-modal display.

2) Have a plugin manager where you can enable or disable plugins. Plugins can 
be enabled by default and picked up by FsEye by putting them in a "plugins" 
directory relative to the FsEye dll (make sure to recursively traverse 
sub-directories in case plugin developers want to deploy multiple files 
together).

Original issue reported on code.google.com by stephen....@gmail.com on 11 Jun 2012 at 5:39

GoogleCodeExporter commented 9 years ago
I'm considering display to work something like this:
1) right-click valued node
2) hover over "Send to" which has a sub-menu
3) choose sub-menu option, which is split into two parts: "new" and "existing" 
plugin instances. Something like:
   New PropertyGrid
   New Eye
   ----------
   PropertyGrid: existing name 1
   PropertyGrid: existing name 2
   Eye: existing name 1

maybe the "existing" nodes should themselves have sub-menus
4) Based on selection, will send the watch value to a TAB within the left hand 
side of a SPLIT PANEL. Selecting an existing panel instance will simply update 
said existing instance. Closing all plugin instance will make the right hand 
split panel disappear.

Original comment by stephen....@gmail.com on 17 Jun 2012 at 2:28

GoogleCodeExporter commented 9 years ago
Currently pursuing the above display description.

Original comment by stephen....@gmail.com on 4 Jul 2012 at 7:31

GoogleCodeExporter commented 9 years ago
Not sure if this is what you are getting at, but I would love to be able to 
register plugins for custom data types that allow them to be visualized in 
different ways.  For example, suppose we have some datatype representing a 
tabular data structure, I would like to be able to see some custom viewer for 
it in fseye.  I would also like to be able to invoke a menu option to insert a 
visualization of that embedded in the FsEye window (as a separate area).  I 
envisage using the whole of one of my screens as an FsEye workspace that 
contains my current bindings plus any visualized versions of them

Original comment by Howard.M...@gmail.com on 11 Jul 2012 at 1:00

GoogleCodeExporter commented 9 years ago
Added "todo.txt" to the project tracking work to be done on this issue since it 
is big and the comments here are not really good for tracking issue sub-tasks.

http://code.google.com/p/fseye/source/browse/trunk/FsEye/todo.txt

Original comment by stephen....@gmail.com on 14 Jul 2012 at 11:12

GoogleCodeExporter commented 9 years ago
I spoke with Howard out-of-band and one of the good suggestions he made is to 
allow plugins to only be available for certain types. I suggested that we could 
add an AcceptedTypes property to the IPlugin interface which returned a list of 
types supported by the plugin (with an empty list indicating all types 
accepted). But since then I've rethought that and decided giving full control 
to the plugin author via either of the two interface methods would be better / 
more flexible:

(* Returns true or false depending on whether an instance of the given type is 
watchable: if false, then FsEye will not allow creating a watch for a value of 
the given type. *)
IPlugin.IsWatchable : Type -> bool

or

(* Returns true or false depending on whether the given instance and its type 
(which we may need if  the instance is null) is watchable: if false, then FsEye 
will not allow creating a watch for a value of the given type. *)
IPlugin.IsWatchable : obj -> Type -> bool

Howard, if you are monitoring this thread, I'd be interested in whether you see 
much value in the second option. I think it may be useful if e.g. you have some 
mutable object which is a watchable type, but may not be watchable if the 
object is in a given state (i.e. incompletely initialized).

Original comment by stephen....@gmail.com on 14 Jul 2012 at 11:23

GoogleCodeExporter commented 9 years ago
Hi Stephen

I definitely think that an interface that takes an instance of an object is the 
way to go.  It's the most flexible because it allows a plugin to become 
available based on any characteristics of a value.  The only downside is that 
it could be slower if you have a large number of plugins, but I don't expect 
that will be a bit deal.

As a concrete example of the value, I am working on a F# type provider for R, 
which we plan to Open Source shortly.  This allows you to call arbitrary 
functionality in R, but the value coming back from the function is always of 
the same .NET type.  Through option (2), we could make different plugins 
available depending on arbitrary characteristics such as the class of the 
object in R.

Also, I feel that it is valuable to allow a plugin to return a tri-state value 
- Enabled, Disabled, and Hidden.  If it is Disabled, the plugin would be 
present on the menu but disabled.  If Hidden, the menu item would not be 
present.  For a plugin that works for a large proportion of values, being 
Disabled is fine.  But suppose I write a plugin that only works for a small 
proportion of values, it would be better to hide if it the value is not 
supported.  

For example, I might have a plugin that sends a value to Excel, but I can only 
support it one very specific types.  It is better to not show it than to have a 
disabled "Send to Excel".  As another example, I might write a plugin that can 
convert an F# Quotation into F# code and spit it out into my F# script file.  
This would only be supported for quotations and so should be hidden for other 
types.

As you can probably see from my examples, I envision this mechanism being used 
for more than just "adding a watch".  I would be like to be able to incorporate 
arbitrary functionality that a user might want to invoke.  So perhaps a more 
general term (IsSupported?) would make more  sense than IsWatchable.

I can imagine enhancements such as allowing the plugin to derive the text for 
the menu item from the value, but I think that is unnecessary for now.

Original comment by Howard.M...@gmail.com on 16 Jul 2012 at 12:57

GoogleCodeExporter commented 9 years ago
Howard: heads-up, I've release FsEye 2.0.0-beta1! You can find the download at 
https://code.google.com/p/fseye/downloads/list and reference the documentation 
at https://code.google.com/p/fseye/wiki/FsEye2Beta.

I did go with the more flexible IsWatchable: (obj * Type) -> bool interface 
member, thanks for the feedback.

Your F# type provider for R sounds interesting, I look forward to taking a look 
at it!

Your other suggestions are great too, and my first reaction was "let's go for 
it!". But upon further reflection I have some hesitations, but I certainly am 
not closing the door on anything yet. I say try out the beta1 release and see 
how well it works for your use-cases in practice.

To enumerate my thoughts:

1) Expanding the generality of plugins beyond just "adding a watch". I worry 
about the increased complexity for both plugin authors and users. e.g. some 
plugins expose GUI controls, some don't. But I believe the IWatchViewer 
interface is certainly still flexible enough for your use cases (you can do 
anything you want in the IWatchViewer.Watch implementation). Indeed, if you 
have something like "Send to Excel", I think it could be nice to have a GUI 
watch control displayed which could be used to display information, allow 
configuration, show progress, etc..

2) I understand your motivation for wanting to allow plugin authors to return a 
tri-state value to indicate the availability of the Send To command. But again 
I worry about increased complexity for plugin authors and confusion for users. 
In case, I believe the UX best practice is to only hide menu items when they 
never make sense for static nodes (e.g. "Non-public" and "Rest" non-valued 
nodes) - but for dynamic nodes, that may or may not have functionality 
available based on their state, I think disabling the menu item is least 
surprising to the user. However, I would consider empowering the user to make 
this choice: i.e. add a setting (see issue 22) to either hide / or disable 
plugin commands that are unavailable based on the context.

But again, let's see how this all works out in practice, and take it from there.

Thanks!

Original comment by stephen....@gmail.com on 20 Jul 2012 at 1:14

GoogleCodeExporter commented 9 years ago
Thanks - very exciting.  I probably won't be able to try it out until next 
week, but I will let you know as soon as I have feedback.

Original comment by Howard.M...@gmail.com on 20 Jul 2012 at 1:49

GoogleCodeExporter commented 9 years ago
Marking this issue "Fixed" for 2.0.0 beta1 release in favor of having new 
plugin related features requests or bug reports logged as new issues against 
the release.

Original comment by stephen....@gmail.com on 21 Jul 2012 at 3:07