Editoren in Eclipse RCP
In Eclipse RCP-Anwendungen werden Dokumente, die vom Benutzer geöffnet, bearbeitet und wieder gespeichert werden können, mit Editoren abgebildet. Dies bedingt weder eine Datei im Dateisystem noch dass es sich dabei um einen Texteditor handeln muss - die Texteditoren der Eclipse IDE sind lediglich eine spezielle Variante eines Editors. Ein Editor könnte beispielsweise eine Eingabemaske oder eine Grafik zum Gegenstand haben. Die Daten könnten in einer Datenbank persistiert werden. Dies obliegt dem Entwickler bei der Implementierung des Editors.
Alle Editoren werden im Editierbereich der Anwendung geöffnet. Diesen Bereich teilen sich alle Perspektiven, er kann lediglich ein- und ausgeblendet werden:
EditorInput
Ein EditorInput-Objekt beschreibt eine Referenz auf die Daten, die der Editor bearbeitet. Bei einer Datei im Dateisystem würde das EditorInput-Objekt den Dateinamen beinhalten, bei einem Datenbankobjekt den Primärschlüssel. Für dieses Objekt ist das Interface IEditorInput zu implementieren:
Für einen Editor, dem ein Datenbank-Objekt SomeObject zugrunde liegt, könnte das Editor-Input-Objekt folgendermaßen implementiert werden:
/**
* SomeEditorInput beschreibt eine Referenz auf SomeObject
*/
public class SomeEditorInput implements IEditorInput {
// Minimale Informationen, mit der das zu bearbeitende Objekt beschrieben
// und referenziert werden kann
private int id;
public SomeEditorInput(int id) {
super();
this.id = id;
}
public ImageDescriptor getImageDescriptor() {
return Activator.getImageDescriptor("/icons/someicon.png");
}
public String getName() {
// Text für den Benutzer, wird initial im Reiter des Editors angezeigt
return "Some Document " + id;
}
public String getToolTipText() {
return getName();
}
public IPersistableElement getPersistable() {
// getPersistable muss nur implementiert werden, wenn das Editor-Inputobjekt
// über mehrere Anwendungssessions hinweg gelten soll, z.B. wenn eine
// "Zuletzt geöffnete Dokumente"-Liste verwendet wird.
return null;
}
public boolean exists() {
// Ggf. prüfen ob Objekt noch existiert und false zurückgeben wenn nicht.
// Vor allem relevant im Zusammenspiel mit getPersistable.
return true;
}
public Object getAdapter(Class adapterTarget) {
// Editor-Input-Objekte können optional adaptierbar gestaltet werden
return null;
}
// equals und hashCode müssen implementiert werden, damit nur ein
// Editor für dasselbe Dokumente geöffnet werden kann
public int hashCode() {
return id;
}
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null || getClass() != obj.getClass())
return false;
return (someObjectId == ((SomeEditorInput) obj).id)
}
}
Editor
Editoren werden der Workbench über den Extension Point org.eclipse.ui.editors bekannt gegeben:
<extension point="org.eclipse.ui.editors">
<editor
id="com.example.SomeEditorPart"
class="com.example.SomeEditorPart"
name="Some Object Editor">
</editor>
</extension>
Hier ist die implementierende Klasse für den Editor anzugeben. Diese muss von EditorPart erben:
Der Editor ist so zu implementieren, dass die Daten anhand des EditorInput-Objektes geladen werden und entsprechend angezeigt werden. Beispielsweise:
public class SomeEditorPart extends EditorPart {
public void init(IEditorSite site, IEditorInput input) throws PartInitException {
// Sobald der Editor erzeugt wird, wird die init-Methode aufgerufen.
// EditorPart verlangt, dass man die hereingereichte EditorSite und das
// EditorInput-Objekt setzt. In dieser Methode könnte man auch
// Nicht-UI bezogene Initialisierungen erledigen.
setSite(site);
setInput(input);
// Sicherstellen, das das Input-Objekt vom erwarteten Typ ist
Assert.isTrue(input instanceof SomeEditorInput,
"Input object needs to be SomeEditorInput!");
}
public void createPartControl(Composite parent) {
// Analog zu ViewParts sind in createPartControl die UI-Inhalte des
// Editors zu erzeugen
// ...
// Titel des Editors kann gesetzt werden mit:
setPartName(/* ... */);
}
public void setFocus() {
// setFocus sollte in Editoren unbedingt implementiert werden und dem
// ersten Control den Eingabefokus geben
}
public boolean isDirty() {
// Die Workbench erledigt das Handling des Speichern und die
// Anzeige des aktuellen Änderungsstatus des Editors. Dazu muss isDirty
// Auskunft darüber geben, ob der Editor ungespeicherte Änderungen enthält
// (= dirty ist). Dies ist gemäß der Inhalte des Editors herauszufinden und
// zurückzugeben.
return /* ... */;
}
private void setDirty(boolean dirty) {
this.dirty = dirty;
firePropertyChange(IEditorPart.PROP_DIRTY);
}
public void doSave(IProgressMonitor monitor) {
// doSave wird aufgerufen, sobald der Benutzer den Speichern-Command
// auslöst und sollte die Änderungen des Editors persistieren.
}
public void doSaveAs() {
throw new UnsupportedOperationException();
}
public boolean isSaveAsAllowed() {
return false;
}
// TIPP: getEditorInput überschreiben und ein konkretisiertes
// EditorInput-Objekt zurückliefern
public SomeEditorInput getEditorInput() {
return (SomeEditorInput) super.getEditorInput();
}
}
Speichern der Editor-Inhalte
Die Methode isDirty ist so zu implementieren, dass sie jederzeit Auskunft darüber gibt, ob ein Editor ungespeicherte Änderungen enthält. Damit dieser Status korrekt angezeigt werden kann, muss eine Benachrichtung erfolgen, sobald sich dieser dirty-Status ändert. Dies kann z.B. im Zusammenspiel mit den bearbeitenden UI-Elementen erfolgen:
public class SomeEditorPart extends EditorPart {
private boolean dirty;
public void createPartControl(Composite parent) {
// ...
someTextField.addModifyListener(new ModifyListener() {
public void modifyText(ModifyEvent e) {
setDirty(true);
}
});
}
public boolean isDirty() {
return dirty;
}
public void setDirty(boolean dirty) {
this.dirty = dirty;
firePropertyChange(IEditorPart.PROP_DIRTY);
}
}
Die Workbench erledigt dabei auch die Sicherheitsabfragen, sobald der Benutzer einen Editor mit ungespeicherten Änderungen schließen möchte:
Das Speichern wird über den Command org.eclipse.ui.file.save ausgelöst. Durch den Standard-Handler für den save-Command wird die Methode doSave des Editors aufgerufen.
Editoren öffnen, Workbench APIs für Editoren
Um einen Editor zu öffnen, rufen Sie openEditor() auf der Workbench-Page mit dem Editor-Input-Objekt und der Editor-ID auf:
// Der Zugriff auf Workbench-Page ist situationsabhängig
// Variante 1) in Views / Editoren
page = getSite().getPage();
// Variante 2) in Command-Handlern
page = HandlerUtil.getActiveWorkbenchWindow(event).getActivePage();
// Variante 3) globaler Zugriff
page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
// Editor öffnen:
page.openEditor(new SomeEditorInput(someId), SOME_EDITOR_ID);
Weitere Methoden für das Handling von Editoren finden Sie ebenfalls auf der Workbench-Page:
// Alle Editoren schließen, optional mit Bestätigung bei ungespeicherten Änderungen
page.closeAllEditors(true);
// Editoren suchen
IEditorReference[] editorRefs = page.findEditors(someEditorInput, TestEditor.EDITOR_ID,
IWorkbenchPage.MATCH_INPUT | IWorkbenchPage.MATCH_ID)
// Alle Editoren
IEditorReference[] editorRefs = page.getEditorReferences();
// Editoren schließen, optional mit Bestätigung bei ungespeicherten Änderungen
page.closeEditors(editorRefs);



Sehr gutes Tutorial.
Vielen Dank!