Version 1.2
Copyright © 2010 - 2011 Lars Vogel
01.09.2011
| Revision History | |||
|---|---|---|---|
| Revision 0.1 | 03.06.2010 | Lars Vogel |
Separated from Eclipse RCP tutorial |
| Revision 0.2 - 1.2 | 04.11.2010 - 01.09.2011 | Lars Vogel |
bug fixes and enhancements |
Table of Contents
Eclipse uses editors and views to maintain data. An editor typically requires that the user explicitly select "save" to apply the changes to the data while a view typically changes the data immediately.
All editors are opened in the same area. Via the perspective you can configure if the editor area is visible or not.
The following steps are required to create and use an editor within an RCP application.
Make the editor area visible in your perspective
Create an IEditorInput class
Define an extension for the "org.eclipse.ui.editors" extension point
Implement the class for the editor, this class must implement IEditorPart
IEditorInput serves as the model for the editor and is supposed to be a light-weight representation of the model. Eclipse will buffer IEditorInput objects therefore this object should be relatively small.
For example the Eclipse IDE uses IEditorInput objects to identify files without handling with the complete file. small.
Based on the equals() method of the IEditorInput the system will determine if the corresponding editor is already open or if a new editor must be opened.
The editor is defined via the extension point "org.eclipse.ui.editors". The class which implement the editor must implement the interface "IEditorPart". In most cases it extends the abstract class "EditorPart".
The editor receives the IEditorSite and the IEditorInput in the init() method. It must set the input via the setInput() method and the side via the setSite() method.
init() is called before createPartControl() therefore you can use the input during your UI creation (which happens in createPartControl()).
By default the Editor will use the tooltip and title from the EditorInput.
Typically the EditorInput is only a light-weight representation of the real object. Therefore you may want to change the title and tooltip in your Editor. Use setPartName() to set the title of the Editor. To set the tooltip you have to override the method getTitleToolTip() (despite the Javadoc description). See Bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=107772 for details.
In an editor the method isDirty() is used to inform the workbench if the content of the editor is changed. For inform the workbench that the dirty property of the editor has changed you fired an event.
firePropertyChange(IEditorPart.PROP.DIRTY);
You can open an Editor via the current active page. For this you need the EditorInput object and the ID for the editor which is defined in the "org.eclipse.ui.editors" extension point.
page.openEditor(new YourEditorInput(), ID_OF_THE_EDITOR);
To get the page you can use:
// If you are in a view getViewSite().getPage(); // If you are in an command HandlerUtil.getActiveWorkbenchWindow(event).getActivePage(); // Somewhere else PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
This tutorial assumes what you have basic understanding of development for the Eclipse platform. Please see Eclipse 4 RCP Tutorial or Eclipse Plug-in Tutorial if you need any basic information.
This tutorials describes the creation of an editor. It also shows how an editor can interact with a view. We will create a view which shows several persons.
Create a new RCP project "de.vogella.rcp.editor.example". Use the "RCP application with a view" as a template. Create the package "de.vogella.rcp.editor.example.model" and create the following classes in this package.
package de.vogella.rcp.editor.example.model; public class Person { private static int counter = 0; private int id; private String firstName; private String lastName; public Person(String firstName, String lastName) { id = counter++; this.firstName = firstName; this.lastName = lastName; } public int getId() { return id; } public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } @Override public String toString() { return firstName + " " + lastName; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((firstName == null) ? 0 : firstName.hashCode()); result = prime * result + ((lastName == null) ? 0 : lastName.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Person other = (Person) obj; if (firstName == null) { if (other.firstName != null) return false; } else if (!firstName.equals(other.firstName)) return false; if (lastName == null) { if (other.lastName != null) return false; } else if (!lastName.equals(other.lastName)) return false; return true; } }
The following class will serve as a data model content provider.
package de.vogella.rcp.editor.example.model; import java.util.ArrayList; import java.util.List; public class MyModel { private static MyModel model; private List<Person> persons = new ArrayList<Person>(); private MyModel() { Person person = new Person("Hans", "Nase"); persons.add(person); person = new Person("Jim", "Knopf"); persons.add(person); } public static MyModel getInstance() { if (model == null) { model = new MyModel(); } return model; } public List<Person> getPersons() { return persons; } public Person getPersonById(int id) { for (Person person : persons) { if (person.getId() == id) { System.out.println("returned"); return person; } } return null; } }
Make the editor area visible by changing your Perspective.java.
package de.vogella.rcp.editor.example; import org.eclipse.ui.IPageLayout; public class Perspective implements IPerspectiveFactory { public void createInitialLayout(IPageLayout layout) { // layout.setEditorAreaVisible(false); layout.setFixed(true); } }
Create the following new class "MyPersonEditorInput" which implements IEditorInput.
package de.vogella.rcp.editor.example.editor; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.ui.IEditorInput; import org.eclipse.ui.IPersistableElement; public class MyPersonEditorInput implements IEditorInput { private final int id; public MyPersonEditorInput(int id) { this.id = id; } public int getId() { return id; } @Override public boolean exists() { return true; } @Override public ImageDescriptor getImageDescriptor() { return null; } @Override public String getName() { return String.valueOf(id); } @Override public IPersistableElement getPersistable() { return null; } @Override public String getToolTipText() { return "Displays a person"; } @Override public Object getAdapter(Class adapter) { return null; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + id; return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; MyPersonEditorInput other = (MyPersonEditorInput) obj; if (id != other.id) return false; return true; } }
Go to plugin.xml and add the extension "org.eclipse.ui.editors".

Do not use a template. Use the ID "de.vogella.rcp.editor.example.editor.personeditor", any name you want and the class "de.vogella.rcp.editor.example.editor.MyPersonEditor".

Click on the class hyperlink to create the class. Make sure the variable "ID" matches the ID of the editor extension.
package de.vogella.rcp.editor.example.editor; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Text; import org.eclipse.ui.IEditorInput; import org.eclipse.ui.IEditorSite; import org.eclipse.ui.PartInitException; import org.eclipse.ui.part.EditorPart; import de.vogella.rcp.editor.example.model.MyModel; import de.vogella.rcp.editor.example.model.Person; public class MyPersonEditor extends EditorPart { public static final String ID = "de.vogella.rcp.editor.example.editor.personeditor"; private Person person; private MyPersonEditorInput input; // Will be called before createPartControl @Override public void init(IEditorSite site, IEditorInput input) throws PartInitException { if (!(input instanceof MyPersonEditorInput)) { throw new RuntimeException("Wrong input"); } MyPersonEditorInput new_name = (MyPersonEditorInput) input; this.input = (MyPersonEditorInput) input; setSite(site); setInput(input); person = MyModel.getInstance().getPersonById(this.input.getId()); setPartName("Person ID: " + person.getId()); } @Override public void createPartControl(Composite parent) { GridLayout layout = new GridLayout(); layout.numColumns = 2; parent.setLayout(layout); Label label1 = new Label(parent, SWT.NONE); label1.setText("First Name"); Text text = new Text(parent, SWT.BORDER); text.setText(person.getFirstName()); text.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false)); new Label(parent, SWT.NONE).setText("Last Name"); Text lastName = new Text(parent, SWT.BORDER); lastName.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false)); lastName.setText(person.getLastName()); } @Override public void doSave(IProgressMonitor monitor) { // person.getAddress().setCountry(text2.getText()); } @Override public void doSaveAs() { } @Override public boolean isDirty() { return false; } @Override public boolean isSaveAsAllowed() { return false; } @Override public void setFocus() { } }
Create a command "de.vogella.rcp.editor.example.openEditor" with the default handler "de.vogella.rcp.editor.example.handler.CallEditor".

Create the following class "de.vogella.rcp.intro.editor.handler.CallEditor".
package de.vogella.rcp.editor.example.handler; import org.eclipse.core.commands.AbstractHandler; import org.eclipse.core.commands.ExecutionEvent; import org.eclipse.core.commands.ExecutionException; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.PartInitException; import org.eclipse.ui.handlers.HandlerUtil; import de.vogella.rcp.editor.example.View; import de.vogella.rcp.editor.example.editor.MyPersonEditor; import de.vogella.rcp.editor.example.editor.MyPersonEditorInput; import de.vogella.rcp.editor.example.model.Person; public class CallEditor extends AbstractHandler { @Override public Object execute(ExecutionEvent event) throws ExecutionException { System.out.println("called"); // Get the view IWorkbenchWindow window = HandlerUtil.getActiveWorkbenchWindow(event); IWorkbenchPage page = window.getActivePage(); View view = (View) page.findView(View.ID); // Get the selection ISelection selection = view.getSite().getSelectionProvider() .getSelection(); if (selection != null && selection instanceof IStructuredSelection) { Object obj = ((IStructuredSelection) selection).getFirstElement(); // If we had a selection lets open the editor if (obj != null) { Person person = (Person) obj; MyPersonEditorInput input = new MyPersonEditorInput(person.getId()); try { page.openEditor(input, MyPersonEditor.ID); } catch (PartInitException e) { throw new RuntimeException(e); } } } return null; } }
We will change the class "View" to use JFace Viewers and add a double-click listener to call the command. The view makes his viewer available as selection provider via the following line:" getSite().setSelectionProvider(viewer);". This make is possible for the command which opens the editor to get the selection of the view. All workbench parts have a site, which can be accessed via the method getSite(). A site is a Facade which allows access to other parts of the workbench, e.g. the shell, the workbench window, etc. Whenever possible use the site to access Workbench objects.
package de.vogella.rcp.editor.example; import org.eclipse.jface.viewers.ArrayContentProvider; import org.eclipse.jface.viewers.DoubleClickEvent; import org.eclipse.jface.viewers.IDoubleClickListener; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.viewers.ListViewer; import org.eclipse.swt.widgets.Composite; import org.eclipse.ui.handlers.IHandlerService; import org.eclipse.ui.part.ViewPart; import de.vogella.rcp.editor.example.model.MyModel; import de.vogella.rcp.editor.example.model.Person; public class View extends ViewPart { public static final String ID = "de.vogella.rcp.editor.example.view"; private ListViewer viewer; public void createPartControl(Composite parent) { viewer = new ListViewer(parent); viewer.setContentProvider(ArrayContentProvider.getInstance()); viewer.setLabelProvider(new LabelProvider() { @Override public String getText(Object element) { Person p = (Person) element; return p.getFirstName() + " " + p.getLastName(); }; }); viewer.setInput(MyModel.getInstance().getPersons()); getSite().setSelectionProvider(viewer); hookDoubleClickCommand(); } private void hookDoubleClickCommand() { viewer.addDoubleClickListener(new IDoubleClickListener() { public void doubleClick(DoubleClickEvent event) { IHandlerService handlerService = (IHandlerService) getSite() .getService(IHandlerService.class); try { handlerService.executeCommand("de.vogella.rcp.editor.example.openEditor", null); } catch (Exception ex) { throw new RuntimeException("de.vogella.rcp.editor.example.openEditor not found"); } } }); } public void setFocus() { viewer.getControl().setFocus(); } }
Run the application. If you double-click on an item in the view, the editor should opened.

To participate in the global save command, set the isDirty property in your editor and call firePropertyChange(IEditorPart.PROP_DIRTY); to notify the workbench. I leave this as an exercise to the reader.
Before posting questions, please see the vogella FAQ. If you have questions or find an error in this article please use the www.vogella.com Google Group. I have created a short list how to create good questions which might also help you.
vogella Training Android and Eclipse Training from the vogella team
Android Tutorial Introduction to Android Programming
GWT Tutorial Program in Java and compile to JavaScript and HTML
Eclipse RCP Tutorial Create native applications in Java
JUnit Tutorial Test your application
Git Tutorial Put everything you have under distributed version control system