11 - Eclipse Plugin Editors Tutorial

Working with Editors

Editors are used to create/modify workspace resources. As an Eclipse user you must have used editors all the time. Famous example of editor is the Java Editor. It provides many capabilities like Content assist, color coding and so on. There is no specific implementation of an editor because editors essentially cater to application specific behavior. 
Once the implementation model for an editor is determined, implementing the editor is much like programming a standalone JFace or SWT application. 

Workbench Editors


Although the implementation of a workbench editor will be specific to your plug-in and the content that you want to edit, the workbench provides a general structure for building an editor. Editors should implement org.eclipse.ui.IEditorPart interface. In Eclipse, Editors rests inside org.eclipse.ui.IEditorSite, which in turn rests in org.eclipse.ui.IWorkbenchPage.

         Eclipse Workbench_Editor.

Thankfully, Eclipse provides two important base implementations of IEditorPart interface namely EditorPart and MultiPageEditorPart (discussed next). Major difference between the two type of editors is that MultiPageEditorPart provides the functionality of displaying multiple pages on same editor in tabbed fashion – similar to what we see in plug-in manifest editor (Overview tab, extensions tab, dependency tab etc.)

EditorPart

This is the Abstract base implementation of all workbench editors. Subclasses must implement the following methods: • IEditorPart.init - to initialize editor when assigned its site • IWorkbenchPart.createPartControl - to create the editor's controls (SWT/JFace controls) • IWorkbenchPart.setFocus - to accept focus • IEditorPart.isDirty - to decide whether a significant change has occurred • IEditorPart.doSave - to save contents of editor • IEditorPart.doSaveAs - to save contents of editor • IEditorPart.isSaveAsAllowed - to control Save As

MultiPageEditorPart

A multi-page editor is an editor with multiple pages, each of which may contain an editor or an arbitrary SWT control. Subclasses must implement the following methods:

  • CreatePages - to create the required pages by calling one of the addPage methods (pages will be subclasses of EditorPart discussed above)
  • IEditorPart.doSave - to save contents of editor
  • IEditorPart.doSaveAs - to save contents of editor
  • IEditorPart.isSaveAsAllowed - to enable Save As
  • IEditorPart.gotoMarker - to scroll to a marker.

 

Creating Editor by using inbuilt editor template

In order to understand editor concepts we will use one of the templates available in eclipse itself. This template creates a multi-page editor. The editor has three pages: Edit where you enter text, Properties that allows you to change font of the result and Preview that shows sorted words from the Edit page using the font set in Properties. 

In order to create multi-page editor, open plug-in.xml file. Navigate to extensions tab and click on Add. Select “Extension Wizards” tab followed by Multi-page Editor as shown in figure below.

       Eclipse selecting multipage editor

Next, click on “Next” button and provide values as shown below:

        eclipse plugin options for multipage editor

Java Package Name: is the package in which editor class will be generated.

Editor Class Name: is the name of multi page editor class which will be generated after this wizard finishes

Editor Contributor Class: is an instance of org.eclipse.ui.IEditorActionBarContributor which manages the installation and removal of global menus, menu items, and toolbar buttons for one or more editors. The platform sends the some events to the contributor, indicating when an editor has become active or inactive, so that the contributor can install or remove menus and buttons as appropriate.

Editor Name: Human readable name of editor.

File Extension: This attribute specifies the file extensions with which we would like to associate this particular editor. 

Next, Click finish. Save the Plugin manifest file. We will first look how newly created editor looks like before reviewing the generated code. In order to view the editor in action launch eclipse runtime application. Create a new file from right click context menu as shown below:

     Eclipse file extentions for editors

Name the new file anything but keep the extension of the “.mpe” because this is the extension with which newly created editor is associated with. Once you have created the file – Sample Multi-Page editor will open up with three tabs namely <filename>.mpe, Properties and Preview. Play around with the editor before we get onto reviewing generated code.

       Eclipse plugin sample multipage editor

Let’s Review the generated code

Let’s start with plug-in manifest editor.

       Eclipse plugin manifest edtor

In order to create a new editor we need to extend org.eclipse.ui.editors extension point. Following are some of attributes (with brief description) which need special attention.

Extensions: every editor typically understands only special file extensions. For ex: XML editor understands only .xml extension. You can provide file extensions (comma separated) understood by editor. 

Command: We can specify command here to launch an external editor. For example: I may like to open XML SPY (external editor) when user clicks on xml file inside eclipse. 

Launcher: class that implements org.eclipse.ui.IEditorLauncher and is used to launch an external editor.

contributerClass: a class that implements org.eclipse.ui. IEditorActionBarContributor . This class us useful in adding actions to various parts of eclipse whenever editor is opened. We will discuss Contributor class in coming sections when we review its generated code. 

Default: If true, this editor will be used as the default editor for the file extension 

Filenames: if we want to open our editor for specific filenames

Let’s review com.myplugin.rmp.editors.MultiPageEditor class.

As discussed earlier that implementation of editor is much like programming a standalone JFace or SWT application. So we will not get into details of how to build an editor with help of SWT/JFACE. We will just concentrate on the lifecycle of editor. In Coming sections ill discuss various editor specific methods. We will discuss the order in which these method get called (in editor lifecycle) and what is the purpose of these methods. 

public MultiPageEditor() {
              super();
              ResourcesPlugin.getWorkspace().addResourceChangeListener(this);
}

Whenever user clicks on a “.mpe” file constructor of MultiPageEditor will be called. This class implements IResourceChangeListener (discussed in resource change tracking chapter). In editor constructor we are registering this instance of editor with the workspace so that editor is notified for any resource changes in the workspace. 

public void init(IEditorSite site, IEditorInput editorInput)
              throws PartInitException {
              if (!(editorInput instanceof IFileEditorInput))
                        throw new PartInitException("Invalid Input: Must be IFileEditorInput");
              super.init(site, editorInput);
}

Next in the editor lifecycle init method is called, we are overriding init method defined in EditorPart class. This method is the first method to be called when editor is created In this method we are verifying whether the editor input is acceptable (it should be instance of IFileEditorInput) otherwise throwing an exception. IEditorInput is a light weight descriptor of editor input, like a file name but more abstract. It is a object which can be queried to know more about the input which is coming to editor.

protected void createPages() {
              createPage0();
              createPage1();
              createPage2();
}

void createPage0() {
              try {
                        editor = new TextEditor();
                        int index = addPage(editor, getEditorInput());
                        setPageText(index, editor.getTitle());
              } catch (PartInitException e) {
                        ErrorDialog.openError(
                                  getSite().getShell(),
                                  "Error creating nested text editor",
                                  null,
                                  e.getStatus());
              }
}
...
...

Next in the editor lifecycle createPages() method is called, This method creates the pages of this multipage editor. Typically, this method simply calls more finely grained methods such as createPage0(To create eclipse plugin text editor), createPage1(To create composite) etc. So this method is used to create the GUI for our editor. Next, in createPage0() we are creating a new TextEditor. This is a inbuilt standard text editor for file resources (we could have created our own editor by extensing EditoPart Directly). addPage method is used to add a new page containing the given editor to this multipage editor. addPage returns the index where this page is added. Next setPageText is used to set the title for the page index. 

public boolean isSaveAsAllowed() {
    return true;
}

isSaveAsAllowed() returns whether the "Save As" operation is supported by this editor part. This method calculates whether save action should be disabled or enabled whenever editor is opened.

protected void pageChange(int newPageIndex) {
              super.pageChange(newPageIndex);
              if (newPageIndex == 2) {
                        sortWords();
              }
}

pageChange(int) method is called whenever user toggles the page tab on bottom of multi page editor. This method is used to calculate the contents of selected page. 

public void doSave(IProgressMonitor monitor) {
              getEditor(0).doSave(monitor);
}
public void doSaveAs() {
              IEditorPart editor = getEditor(0);
              editor.doSaveAs();
              setPageText(0, editor.getTitle());
              setInput(editor.getEditorInput());
}

doSave() and doSaveAs() methods are called whenever user clicks “Save” or “Save As” actions. We are using editor at index zero i.e. the Text Editor to save the file. On save, the editor should generate a property changed event (PROP_DIRTY). doSaveAs() is used to open a Save As dialog

public void gotoMarker(IMarker marker) {
              setActivePage(0);
              IDE.gotoMarker(getEditor(0), marker);
}

gotoMarker() sets the cursor and selection state for this editor as specified by the given marker. We will discuss about markers in chapters to follow. 

Note About Marking Editors Dirty

In above example we have not covered process to mark editors dirty so that Save and Save As buttons can be enabled. Whenever user makes some modification to editor file we can mark editor as dirty by calling firePropertyChange(IEditorPart.PROP_DIRTY). We can also use isDirty() method to see if editor is marked as dirty at any point in editor. 

Let’s review com.myplugin.rmp.editors.MultiPageEditorContributor class.

This class is responsible for Managing the installation/de-installation of global actions for multi-page editors. In our example editor, you will notice that “Editor Menu” action is displayed on top menu whenever editor is opened (as shown in figure below). This action is removed from workbench menu bar whenever multi page editor is closed.

     Eclipse editor menu on top menu.

The EditorActionBarContributor class implements the IEditorActionBarContributor interface, which caches the action bar and workbench page, and provides two new accessor methods.

getActionBars() : it returns the contributor's action bars provided to the contributor when it was initialized.

getPage(): it returns the contributor's workbench page provided to the contributor when it was initialized.

contributeToMenu(): Contributes to the given menu. In our example we are adding new “Editor &Menu” to the workbench menu.

contributeToToolBar(): Contributes to the given tool bar. 

The MultiPageEditorActionBarContributor class extends EditorActionBarContributor, providing a new method to override instead of the setActiveEditor(IEditorPart) method.

setActivePage(IEditorPart part): This method is called whenever the page changes. This method Sets the active page of the multipage editor to the given editor. If there is no active page, or if the active page does not have a corresponding editor, the argument is null.  

Like us on Facebook