Previous Tutorial: Creating a GEF Editor – Part 11: Creating Link Bendpoints
So, after managing to break my laptop’s screen last week I’ve been pretty down… but as the saying goes, the show must go on. Here goes a small tutorial that fixes something that is probably bothering you (It bothered me a lot): saving the model file. While eclipse does detect that the file has changed before closing the editor, having the possibility to check that the file can be saved (which also validates that the EMF) is very useful. And the solution is also pretty simple.
The GEF graphical editor already registers the SaveAction
when created. What is left to do is somehow tell it to enable and disable itself. Since all changes to the model (and therefore the file) are done using commands, the file must be saved if there was a change in the command stack since the last time the file was saved. Thankfully most of the work was already done for us and we need to do two small changes.
- First, the GEF editor is informed whenever there is a change in the
CommandStack
calling itscommandStackChanged
method (this occurs because theGraphicalEditor
is adds itself as a listener to theCommandStack
when it is initialized). When this happens, theisDirty
method of theGraphicalEditor
will returntrue
when called… but the problem is that theSaveAction
does not recalculate if it is enabled automatically, so we must tell it by firing a property change, in this case using thePROP_DIRTY
property of theGraphicalEditor
(this is of course done in thecommandStackChanged
). - Secondly, after the file is saved we must also save the location in the
CommandStack
.
So after all the talking, here is updated code of the OPMGraphicalEditor
(the relevant changes are in lines 61 and 93-100):
package com.vainolo.phd.opm.gef.editor; import java.io.IOException; import java.util.EventObject; import org.eclipse.core.resources.IFile; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.ecore.resource.ResourceSet; import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl; import org.eclipse.gef.DefaultEditDomain; import org.eclipse.gef.commands.CommandStack; import org.eclipse.gef.palette.PaletteRoot; import org.eclipse.gef.ui.parts.GraphicalEditorWithFlyoutPalette; import org.eclipse.ui.IEditorInput; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.IEditorSite; import org.eclipse.ui.IFileEditorInput; import org.eclipse.ui.PartInitException; import com.vainolo.phd.opm.gef.editor.part.OPMEditPartFactory; import com.vainolo.phd.opm.model.OPMPackage; import com.vainolo.phd.opm.model.OPMObjectProcessDiagram; public class OPMGraphicalEditor extends GraphicalEditorWithFlyoutPalette { private Resource opdResource; private OPMObjectProcessDiagram opd; public OPMGraphicalEditor() { setEditDomain(new DefaultEditDomain(this)); } @Override protected void initializeGraphicalViewer() { super.initializeGraphicalViewer(); getGraphicalViewer().setContents(opd); } @Override protected void configureGraphicalViewer() { super.configureGraphicalViewer(); getGraphicalViewer().setEditPartFactory(new OPMEditPartFactory()); } @Override protected PaletteRoot getPaletteRoot() { return new OPMGraphicalEditorPalette(); } /** * Save the model using the resource from which it was * opened, and mark the current location in the * {@link CommandStack}. */ @Override public void doSave(IProgressMonitor monitor) { if(opdResource == null) { return; } try { opdResource.save(null); getCommandStack().markSaveLocation(); } catch(IOException e) { // TODO do something smarter. e.printStackTrace(); opdResource = null; } } @Override public void init(IEditorSite site, IEditorInput input) throws PartInitException { super.init(site, input); loadInput(input); } private void loadInput(IEditorInput input) { OPMPackage.eINSTANCE.eClass(); // This initializes the OPMPackage singleton implementation. ResourceSet resourceSet = new ResourceSetImpl(); if(input instanceof IFileEditorInput) { IFileEditorInput fileInput = (IFileEditorInput) input; IFile file = fileInput.getFile(); opdResource = resourceSet.createResource(URI.createURI(file.getLocationURI().toString())); try { opdResource.load(null); opd = (OPMObjectProcessDiagram) opdResource.getContents().get(0); } catch(IOException e) { // TODO do something smarter. e.printStackTrace(); opdResource = null; } } } /** * Fire a {@link IEditorPart#PROP_DIRTY} property change and * call super implementation. */ @Override public void commandStackChanged(EventObject event) { firePropertyChange(PROP_DIRTY); super.commandStackChanged(event); } }
Fire up your editor, edit something and hit Save. Works great, right?
You can find the final project files here.
And a last reminder, if you like my tutorials please support my work by donating for the good cause of fixing my laptop (upper right corner of your screen).
Next Tutorial: Creating an OPM GEF Editor – Part 13: Adding Procedural Links