The need for perspectives

The virtual R Workbench of the biocep project uses Info Node as a flexible docking framework, giving the possibility the move parts of the user interface (called views) anywhere. However, views have be to moved manually each time to reconstruct the layout you are using, which to me is one major usability misfeature of the workbench. At the moment, workbench plugins add views by calling the createView method of the RGui interface, which adds the requested view next to the Working Directory view of the workbench.

As an example, if I add the view supplied by this tutorial, it appears as this:

createView.png

and unless your plugin uses tricks, that is the only place where the view can be added, and you have to move it around to compose the layout you want to use. This is fine if your plugin only defines one view, but if you define many views (such as the power editor plugin), then asking the user to arrange the views each time is not so great.

Typically, programs using flexible docking frameworks (most notably eclipse) also use perspectives as a way to save and load the layout of the user interface.

Perspectives for the power editor

I have added support for perspectives in the power editor so that the many views supplied by the power editor are arranged in a useful way when the plugin is started, which can be configured by the user. Here is the default layout:

perspectives.png

That is stored in this xml file in the pesrepectives directory of the Editor plugin

   1 <RootWindow>
   2   <WindowBar direction="Up" />
   3   <WindowBar direction="Right" />
   4   <WindowBar direction="Down" />
   5   <WindowBar direction="Left" />
   6   <SplitWindow horizontal="true" dividerLocation="0.2">
   7     <SplitWindow horizontal="false" dividerLocation="0.5407166">
   8       <TabWindow selected="0" direction="Up" tabAreaOrientation="Left">
   9         <JEditDockableView name="vfs.browser" title="File Browser" />
  10         <JEditDockableView name="projectviewer" title="Project Viewer" />
  11       </TabWindow>
  12       <TabWindow selected="0" direction="Up" tabAreaOrientation="Left">
  13         <JEditDockableView name="robjectexplorer" title="R Objects Explorer" />
  14       </TabWindow>
  15     </SplitWindow>
  16     <SplitWindow horizontal="true" dividerLocation="0.75">
  17       <SplitWindow horizontal="false" dividerLocation="0.7654723">
  18         <TabWindow selected="0" direction="Right" tabAreaOrientation="Up">
  19           <JEditView />
  20           <View title="R Console" urls="/opt/biocep/biocep.jar" class="org.kchine.rpf.gui.ConsolePanel" />
  21           <View title="Main Graphic Device" class="javax.swing.JPanel" />
  22         </TabWindow>
  23         <TabWindow selected="0" direction="Right" tabAreaOrientation="Down">
  24           <JEditDockableView name="console" title="Console" />
  25           <View title="Working Directory" class="javax.swing.JPanel" />
  26         </TabWindow>
  27       </SplitWindow>
  28       <SplitWindow horizontal="false" dividerLocation="0.66">
  29         <SplitWindow horizontal="false" dividerLocation="0.5124378">
  30           <TabWindow selected="0" direction="Down" tabAreaOrientation="Right">
  31             <JEditDockableView name="sidekick-tree" title="Sidekick" />
  32           </TabWindow>
  33           <TabWindow selected="0" direction="Down" tabAreaOrientation="Right">
  34             <JEditDockableView name="hypersearch-results" title="HyperSearch Results" />
  35           </TabWindow>
  36         </SplitWindow>
  37         <TabWindow selected="0" direction="Down" tabAreaOrientation="Right">
  38           <JEditDockableView name="error-list" title="Error List" />
  39         </TabWindow>
  40       </SplitWindow>
  41     </SplitWindow>
  42   </SplitWindow>
  43 </RootWindow>

Implementation of perspectives in the power editor

I have recently added support for perspectives in the power editor (this feature should really belong to the biocep project itself, but is not high priority to the author at the moment) by using XML. For example, the default layout that appears when the workbench is started

default.png

can be represented by this perspective

   1 <RootWindow>
   2   <SplitWindow horizontal="true" dividerLocation="0.2">
   3     <View title="R Console" 
   4       urls="/opt/biocep/biocep.jar" 
   5       class="org.kchine.rpf.gui.ConsolePanel" />
   6     <SplitWindow horizontal="false" dividerLocation="0.5407166">
   7       <View title="Main Graphic Device" class="javax.swing.JPanel" />
   8       <TabWindow selected="0" direction="Up" tabAreaOrientation="Up">
   9             <View title="Working Directory" class="javax.swing.JPanel" />
  10       </TabWindow>
  11     </SplitWindow>
  12   </SplitWindow>  
  13 </RootWindow>   
  14 
  15           

Basically, each node of the XML represents one info node window below the root window. Info Node defines a class for each type of window, see the api for the net.infonode.docking package. Theses are of particular interest:

  • RootWindow: top level container for docking windows
  • SplitWindow: A window with a split pane that contains two child windows
  • TabWindow: A docking window containing a tabbed panel
  • View: A docking window containing a component

The implementation of perspectives that is available in the Power Editor plugin relies on two classes for each docking window class, a class that is responsible for exporting the view to an XML node (called FooExporter if the docking window class is Foo), and a class that is responsible for reading the XML representation and recreate the window from it.

The implementation provides importer and exporter classes for all Info Nodes docking window classes, most importantly classes ViewExporter and ViewImporter that dumps the sufficient information about the view into XML and reads this information to recreate the view. Plugins are encouraged to create classes that inherit from View, say MyPluginView and create the classes MyPluginViewExporter and MyPluginViewImporter to handle the information that this view need to store sufficient information as attributes of the <MyPluginView> node

The exporter is the easiest to implement, all the MyPluginView class needs to do is extend the DefaultExporter class and use the setAttribute method somewhere in the constructor. As an example, the constructor for the JEditDockableViewExporter looks like this:

13   /**
14    * Constructor for the ViewExporter
15    *
16    * @param window The View to stream to XML
17    */
18   public JEditDockableViewExporter( JEditDockableView window){
19     super( window ) ;
20     setAttribute( "name", window.getName() ) ;
21     setAttribute( "title", window.getTitle() ) ;
22   }           
23   

... so that the <JEditDockableView> node will have the attributes title and name

To implement custom importers, the easiest way is to extend the ViewImporter class and define the newView method that takes no parameter and builds the view from the attributes, the DefaultImporter defines the getAttribute method that can be used to retrieve an attribute from the xml node. See the implementation of newView for the JEditDockableView class below:

28   /** 
29    * Creates the JEditDockableView
30    *
31    * @return the JEditDockableView for the &lt;JEditDockableView&gt; node
32    */      
33   @Override
34   public View newView( ) throws Exception {
35     return new JEditDockableView( name ) ;
36   }

Future

At the moment, this feature is implemented in the Power editor only, and even if it could be used outside of it by using some tricks, the best course of action is probably to add the feature into the biocep workbench itself so that all plugins can take advantage of it and potentially arrange views from other plugins as well. We can also imagine these features

  • user specific perspectives
  • restore the perspective of the previous session
  • plugin specific perspectives