SOFA 2.0 Editor - GUI Repository Designer for Eclipse

NEWS

2007-06-10

SOFA 2.0 repository editor v. 1.3.0 released. Changes »

2007-02-10

SOFA 2.0 repository editor v. 1.0.149 released.

2006-10-21

Work on the plug-in is started. History »

MANUALS

Compiling and installation

User's manual

Usage scenarios

Developer's manual

UML diagrams

Java docs

Author MaViNes (c)

ARTICLES

OSGI Framework

Eclipse plugin basics

RCP basics

SWT draw basics

jFace tips

SWT Linux/Windows differences

Author MaViNes (c)

<< Previous | Table of contents | Next >>

Chapter 3 Plugging into the workbench

Activator

The Activator file is indicated in the manifest under the Bundle-Activator property. This file should extend org.eclipse.ui.plugin.AbstractUIPlugin. This class must define public static final String PLUGIN_ID which is the unique plug-in identifier in the current workbench context. The Activator should also implement start() and stop() methods which is necessary to make plug-in accessible from the Eclipse platform and there should be two static methods - getDefault() which should return the reference to the current plug-in activator and getImageDescriptor(String path) which should return descriptor for an image by the given path. All other methos can be called from the super class.

The Activator class can be used within the plug-in to receive plug-in related path to resources or image descriptor. It also can stop the plug-in using the stop() method. But this can only happened if user will use Configuration Manager to disable the plug-in.

Editor contribution


plugin.xml reference:
<editor class="org.objectweb.dsrg.sofa.repository.plugin.editors.MultiPageEditor"
         contributorClass="org.objectweb.dsrg.sofa.repository.plugin.editors.MultiPageEditorContributor"
         default="true"
         extensions="xml"
         icon="icons/small.gif"
         id="org.objectweb.dsrg.sofa.repository.plugin.editors.MultiPageEditor"
         name="Repository Project">
         
      </editor>

The editor must implement IEditorPart. We actively use only one editor in the plug-in. This is the MultiPageEditor. In our case the editor extends MultiPageEditorPart implements IResourceChangeListener which gives possibility of multiple pages for one document. The extension is declared so, that the editor opens all files which have the .xml extension. The editor is set to be default editor for xml files. The unique identifier of the editor is the same as its package path. The multi page editor must implement the init() method, which is called when the editor is initialized, the doSave() method, doSaveAs() method, isDirty() method which is called to check if there is something to save. The main method to be implemented is createPages(). This method is used when some file is open for editing. It should create all pages which are defined to be created for such a file type. Pages can be created of a very different kind. This can be properties pages, draw/graphic editing pages, text editor pages and others.

It is possible to contribute to the new multi page editor. For example, add some buttons as a toolbar to the top of the editor. For this reason the MiultiPageEditorContributor is used. It is located in the same package as the MultiPageEditor class. We do not use much contributions to the editor, it just implements all editor related actions like undo, redo, copy, paste etc. The contributor class extends the org.eclipse.ui.part.MultiPageEditorActionBarContributor class. But there are other possible contributions in the org.eclipse.ui.part package.

View contribution


plugin.xml reference:
<view
            allowMultiple="false"
            category="org.objectweb.dsrg.sofa.repository.plugin"
            class="org.objectweb.dsrg.sofa.repository.plugin.views.PropertiesView"
            icon="icons/pview.gif"
            id="org.objectweb.dsrg.sofa.repository.plugin.views.PropertiesView"
            name="Properties View">
      </view>

Each view in the Eclipse plug-in must extend org.eclipse.ui.part.ViewPart. In the plug-n we use 5 views. All of them are in the org.objectweb.dsrg.sofa.repository.plugin.views package. The main method in the view is createPageControl(Composite parent). This method is used to create all UI layouts which will be visible on the view. It is possible to create any GUI on the view part. It is even possible to create edit-like pane on it. We use this trick several times in order to use views instead of editors. Eclipse provides only one shared editor placeholder for all projects. And we required flexible parts layout in the workbench. That is why we should use views instead of editors. According to the Eclipse's specification it is possible to create the editor part only in center of the workbench, and all views should surround the editor. And views can be created in any part of the workbench. So, it is much more comfortable.

The syntax of the xml contribution says, that it is forbidden to open more than one instance of a view (this is valid for all 5 views used), it also assigns icon to a view (icons differ for each view), the id of each view is the same as its full package name (but it can be different, but it must be unique within the plug-in). And the name of a view is assigned in the xml contribution, not from the view itself. The view can be opened from the Window->Open view->other->SOFA 2.0. And then the name of the view to be open is listed there. That is why it is useful to name views outside of according classes.

Wizard contribution


plugin.xml reference:
<wizard
            canFinishEarly="true"
            category="org.objectweb.dsrg.sofa.repository.plugin"
            class="org.objectweb.dsrg.sofa.repository.plugin.wizards.NCushionInterfaceTypeWizard"
            hasPages="true"
            icon="icons/newi.gif"
            id="plugin.core.wizard3"
            name="New ITF"/>

Any wizard manager in the project should extend at least org.eclipse.jface.wizard.Wizard class in order to be identified as wizard manager. There are more complicated wizards to be extended (like new project wizard, new file wizard, etc) but we use primitive wizard class because we need totally different functionality. There are 8 wizard managers in the project. The are located in the org.objectweb.dsrg.sofa.repository.plugin.wizards package. They are used to create new frame, new architecture, new subcomponent, new frame from the architecture centric view, new cushion frame, new cushion architecture, new cushion interface type, and the new cushion project. All of them extends the Wizard class. There are 3 methods here to be implemented. These are addPages(), canFinish(), performFinish(). Those methods should be sub classed in order for the wizard manager to work properly. But the canFinish() is called only once - when wizard is created. To check if finish can be really performed, it is required to implement another method, directly in the class which represents wizard page. Please note, that after the finish is performed, the wizard manager itself is not disposed and all gathered data can be taken from it. So, there is no need to implement actions which should be done according to the wizard's results directly in the wizard manager class (until there is a real need for that).

The syntax of the xml contribution says, that it is allowed for the wizard to be finished before all steps are passed thru (this means, not only the Next> button is available in the middle of the wizard, but also the Finish button is active if all needed data is already gathered). Also it is indicated, that the wizard has pages (this is obvious, each wizard should have pages). The id of the wizard is assigned, now it differs from the qualified class name in the package, but it is still unique. The name is assigned outside of the wizard class, in the contribution details. This is mainly done because it is possible to open wizard using the New->Other->SOFA projects option. And the wizard class is inactive then.

Wizard pages

Each wizard should have pages. It is possible to add many pages to one wizard and it is possible to decide which page to display next dependably on the gathered data. Each wizard page should extend the org.eclipse.jface.wizard.WizardPage class. This class provides the createControl() method which is intended to be overridden. This method allows creating GUI of the page. It is possible to create any valid GUI. But it is not recommended to create editors on wizard pages.

Also it is useful to implement change listener to check if all proper data is gathered. The canFinish() method from the wizard manager is performed only once per wizard lifecycle. So, it is important to track all changes via custom listener.

In the project all wizard pages are kept in the same packages as wizard managers.

Action contributions


plugin.xml reference:

[For actions which implements IObjectActionDelegate interface]
<action
               class="org.objectweb.dsrg.sofa.repository.plugin.popup.actions.CommitAction"
               icon="icons/start.gif"
               id="org.objectweb.dsrg.sofa.repository.plugin.newAction"
               label="commit"
               menubarPath="org.objectweb.dsrg.sofa.repository.plugin.menu1/group1"/>

[For actions which implements IWorkbenchWindowActionDelegate]

<action
               label="&Save all changes to repository server"
               icon="icons/saveall.gif"
               class="org.objectweb.dsrg.sofa.repository.plugin.actions.RepositoryAction"
               tooltip="Save all changes to repository server"
               toolbarPath="sampleGroup"
               id="org.objectweb.dsrg.sofa.repository.plugin.actions.RepositoryAction">
         </action>

There are two possibilities for actions to be declared - implement IObjectActionDelegate, this is interface for an object action that is contributed into a popup menu for a view or editor. It extends IActionDelegate and adds an initialization method for connecting the delegate to the part it should work with. The other way is to implement IWorkbenchWindowActionDelegate. This is interface for an action that is contributed into the workbench window menu or tool bar. It extends IActionDelegate and adds an initialization method for connecting the delegate to the workbench window it should work with.

In the project we use both types of actions. Instances of the first type are kept in the org.objectweb.dsrg.sofa.repository.plugin.popup.actions package and the other one is in the org.objectweb.dsrg.sofa.repository.plugin.actions package. The first type of actions is used for contribution to the context menus and the second type is used for contributions to the main application menu and the main tool bar.

For the first XML snippet (actions which implements IObjectActionDelegate interface) the syntax of the XML contribution says, that the action is triggered when a pop-up menu invoked. The action is assigned to the menu1/group1 action group. Also the action has assigned icon, and label. Label here acts as a name. It is visible to user when s/he is going to click a pup-up menu point. The full syntax (not introduced here, please refer to the original plugin.xml file) says, that the title of the group is SOFA repository and it is shown between other menu choices when the popup menu is triggered over the Package Explorer.

For the second XML snipped (actions which implements IWorkbenchWindowActionDelegate interface) the syntax of the XML contribution says, that the action is triggered when a button on the main toolbar is clicked, or an option from the main application menu is selected. We do not contribute to the main application menu in the plug-in, but we put the button on the main toolbar to save all changes on the repository part. The contribution defines tool-tip text and icon for the button. These are main changes here.

Perspective contribution


plugin.xml reference:
<perspective
     class="org.objectweb.dsrg.sofa.repository.plugin.perspectives.PerspectivesFactory1"
            fixed="true"
            icon="icons/perspective.gif"
            id="Sperspective1"
            name= "SOFA 2.0">
         <description/>
      </perspective> 

A perspective is a visual container for a set of views and editors (parts). These parts exist wholly within the perspective and are not shared. A perspective is like a page within a book. It exists within a window along with any number of other perspectives and, like a page within a book, only one perspective is visible at any time. In the project we use one perspective, which is stored in the org.objectweb.dsrg.sofa.repository.plugin.perspectives package. This perspectives defines placeholders for views used in the plug-in. It allocates placeholders for 2 views and ties other 5 views to the perspective view. So, when the perspective is opened there are 5 visible views on it and it is also possible to add other 2 views on predefined placeholders. There is also predefined place for an instance of the multi page editor which is used in the cushion projects. When the editor is invoked, its placed on the predefined place.

To be able to layout views and editors properly a perspective class realization should implement IPerspectiveFactory interface.

This layout is performed in the perspective factory, a Java class associated with the perspective type. When the perspective is initialized, it consists of an editor area with no additional views. The perspective factory may add new views, using the editor area as the initial point of reference.

The size and position of each view is controlled by the perspective factory. These attributes should be defined in a reasonable manner, such that the user can resize or move a view if they desire it. The syntax of the XML contribution says that perspective has fixed layout (fixed="true"), and there is assigned icon and name for it. The id is differs from the qualified package name, but still it is unique. Also it is possible to add perspective description to the contribution, but now the appropriate tag () is empty.



<< Previous | Table of contents | Next >>

Learn More