diff options
Diffstat (limited to 'plugins/org.eclipse.etrice.ui.common.base/src/org/eclipse/etrice/ui/common/base/editor/DiagramEditorBase.java')
-rw-r--r-- | plugins/org.eclipse.etrice.ui.common.base/src/org/eclipse/etrice/ui/common/base/editor/DiagramEditorBase.java | 306 |
1 files changed, 306 insertions, 0 deletions
diff --git a/plugins/org.eclipse.etrice.ui.common.base/src/org/eclipse/etrice/ui/common/base/editor/DiagramEditorBase.java b/plugins/org.eclipse.etrice.ui.common.base/src/org/eclipse/etrice/ui/common/base/editor/DiagramEditorBase.java new file mode 100644 index 000000000..5465a5dba --- /dev/null +++ b/plugins/org.eclipse.etrice.ui.common.base/src/org/eclipse/etrice/ui/common/base/editor/DiagramEditorBase.java @@ -0,0 +1,306 @@ +/******************************************************************************* + * Copyright (c) 2014 protos software gmbh (http://www.protos.de). + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * CONTRIBUTORS: + * Henrik Rentz-Reichert (initial contribution) + * + *******************************************************************************/ + +package org.eclipse.etrice.ui.common.base.editor; + +import java.io.IOException; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.MultiStatus; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.core.runtime.Status; +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.EStructuralFeature.Setting; +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.emf.ecore.resource.ResourceSet; +import org.eclipse.emf.ecore.util.EcoreUtil; +import org.eclipse.etrice.core.fsm.fSM.ModelComponent; +import org.eclipse.etrice.core.fsm.ui.FSMUiModule; +import org.eclipse.etrice.ui.common.base.UIBaseActivator; +import org.eclipse.graphiti.mm.pictograms.Diagram; +import org.eclipse.graphiti.services.Graphiti; +import org.eclipse.graphiti.ui.editor.DiagramBehavior; +import org.eclipse.graphiti.ui.editor.DiagramEditor; +import org.eclipse.graphiti.ui.editor.EditorInputAdapter; +import org.eclipse.graphiti.ui.editor.IDiagramEditorInput; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.dialogs.TrayDialog; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.IEditorSite; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.PlatformUI; +import org.eclipse.xtext.diagnostics.Severity; +import org.eclipse.xtext.resource.XtextResource; +import org.eclipse.xtext.serializer.ISerializer; +import org.eclipse.xtext.ui.editor.XtextEditor; +import org.eclipse.xtext.util.CancelIndicator; +import org.eclipse.xtext.util.concurrent.IUnitOfWork; +import org.eclipse.xtext.validation.CheckMode; +import org.eclipse.xtext.validation.IResourceValidator; +import org.eclipse.xtext.validation.Issue; + +import com.google.inject.Inject; +import com.google.inject.Injector; + +/** + * @author Henrik Rentz-Reichert + * + */ +public abstract class DiagramEditorBase extends DiagramEditor implements IInputUriHolder { + + @Inject + protected IResourceValidator resourceValidator; + + protected ModificationTrackingEnabler mte = new ModificationTrackingEnabler(); + protected URI inputUri; + protected Object textEditorClass; + + private SaveOnFocusLostListener saveOnFocusListener; + + private SuperClassListener superClassListener; + + public DiagramEditorBase() { + Injector injector = FSMUiModule.getInjector(); + injector.injectMembers(this); + + TrayDialog.setDialogHelpAvailable(false); + } + + @Override + protected DiagramBehavior createDiagramBehavior() { + return new CustomDiagramBehavior(this); + } + + @Override + public void init(IEditorSite site, IEditorInput input) throws PartInitException { + IEditorInput newInput = EditorInputAdapter.adaptToDiagramEditorInput(input); + if (newInput instanceof IDiagramEditorInput) + this.inputUri = ((IDiagramEditorInput) newInput).getUri(); + + super.init(site, input); + } + + @Override + public void initializeGraphicalViewer() { + super.initializeGraphicalViewer(); + + ResourceSet resourceSet = getEditingDomain().getResourceSet(); + Map<EObject, Collection<Setting>> result = EcoreUtil.UnresolvedProxyCrossReferencer.find(resourceSet); + if (!result.isEmpty()) + System.err.println("ERROR in diagram viewer: could not resolve all proxies!"); + + mte.setTarget(getEditingDomain()); + } + + @Override + public void doSave(final IProgressMonitor monitor) { + ResourceSet rs = getEditingDomain().getResourceSet(); + for (Resource res : rs.getResources()) { + if (res instanceof XtextResource) { + if (!res.isLoaded()) { + try { + res.load(Collections.EMPTY_MAP); + } catch (IOException e) { + MessageDialog.openError(Display.getDefault().getActiveShell(), "ERROR", "Internal error: couldn't load referenced resource "+res.getURI()); + return; + } + } + if (res.isModified()) { + + XtextResource xres = (XtextResource) res; + ISerializer serializer = xres.getSerializer(); + + if (xres.getContents().isEmpty()) { + MessageDialog.openError(Display.getDefault().getActiveShell(), "ERROR", "Internal error: part of textual model is empty, can't save"); + return; + } + + // HOWTO: call serializer to validate the concrete syntax + // this throws an exception which is caught further up the stack + // and a dialog will be displayed + serializer.serialize(xres.getContents().get(0)); + + List<Issue> result = resourceValidator.validate(res, CheckMode.NORMAL_AND_FAST, new CancelIndicator() { + public boolean isCanceled() { + return monitor.isCanceled(); + } + }); + if (!result.isEmpty()) { + boolean error = false; + MultiStatus ms = new MultiStatus(UIBaseActivator.PLUGIN_ID, Status.ERROR, "validation errors during diagram save", null); + for (Issue issue : result) { + if (issue.isSyntaxError() || issue.getSeverity()==Severity.ERROR) { + ms.add(new Status(Status.ERROR, UIBaseActivator.PLUGIN_ID, issue.getMessage())); + error = true; + } + } + if (error) { + MessageDialog.openError(Display.getDefault().getActiveShell(), "ERROR", "Internal error: model is invalid, can't save"); + UIBaseActivator.getDefault().getLog().log(ms); + return; + } + } + } + } + } + super.doSave(monitor); + } + + /* (non-Javadoc) + * @see org.eclipse.graphiti.ui.editor.DiagramEditor#setFocus() + */ + @Override + public void setFocus() { + super.setFocus(); + + boolean dirtyAlready = isDirty(); + + // inside this call auto refresh will happen if (and turn the editor dirty) + super.setFocus(); + + if(superClassListener.isChangeInSuperClass()) + superClassChanged(); + + if (!dirtyAlready && isDirty()) + doSave(null); + } + + public ModelComponent getModelComponent() { + Diagram diagram = getDiagramTypeProvider().getDiagram(); + EObject bo = Graphiti.getLinkService().getBusinessObjectForLinkedPictogramElement(diagram); + if (bo instanceof ModelComponent) + return (ModelComponent) bo; + + return null; + } + + @Override + public void dispose() { + mte.unsetTarget(getEditingDomain()); + + getSite().getPage().removePartListener(saveOnFocusListener); + PlatformUI.getWorkbench().getActiveWorkbenchWindow().getPartService().removePartListener(superClassListener); + superClassListener.dispose(); + + super.dispose(); + } + + @Override + public void createPartControl(Composite parent) { + super.createPartControl(parent); + + saveOnFocusListener = new SaveOnFocusLostListener(this); + getSite().getPage().addPartListener(saveOnFocusListener); + + superClassListener = new SuperClassListener(this, textEditorClass); + PlatformUI.getWorkbench().getActiveWorkbenchWindow().getPartService().addPartListener(superClassListener); + + /* we have to save here whether changes have been done or not to get rid of the dirty state + * CAUTION: save in + * init(IEditorSite site, IEditorInput input) + * or + * setInput(IEditorInput input) + * did not work correctly + */ + // if (AutoUpdateFeature.isLastDoneChanges()) + doSave(new NullProgressMonitor()); + } + + /** + * Check whether the given diagram editor manages a super class + * @param editor + * @return + */ + protected boolean registerSuperClassListener(DiagramEditorBase editor) { + if (!(this.getClass().equals(editor.getClass()) && this.getModelComponent()!=null)) + return false; + + ModelComponent editorSc = editor.getModelComponent(); + if (editorSc!=null) { + URI editorResURI = toCurrentPlatformURI(editorSc.eResource().getURI()); + + ModelComponent base = getModelComponent(); + while((base = base.getBase()) != null){ + URI baseResURI = toCurrentPlatformURI(base.eResource().getURI()); + if(editorResURI.equals(baseResURI)) + if(editorSc.getComponentName().equals(base.getComponentName())) + return true; + } + } + + return false; + } + + /** + * Check whether the given room editor has a super class + * @param editor + * @return + */ + protected boolean registerSuperClassListener(XtextEditor editor) { + if (!((Class<?>)textEditorClass).isInstance(editor)) + return false; + if (this.getModelComponent()==null) + return false; + + return editor.getDocument().readOnly(new IUnitOfWork<Boolean, XtextResource>(){ + + @Override + public Boolean exec(XtextResource resource) throws Exception { + + URI editorResURI = toCurrentPlatformURI(resource.getURI()); + URI thisScResURI = toCurrentPlatformURI(getModelComponent().eResource().getURI()); + + // ignore if in same file (handled by graphiti) + if(thisScResURI.equals(editorResURI)) + return false; + + ModelComponent base = getModelComponent(); + while((base = base.getBase()) != null){ + URI baseResURI = toCurrentPlatformURI(base.eResource().getURI()); + if(editorResURI.equals(baseResURI)) + return true; + } + + return false; + } + }); + } + + private URI toCurrentPlatformURI(URI uri) { + if(uri.isPlatform()) + return uri; + else if(uri.isFile()){ + final IPath rootPath = ResourcesPlugin.getWorkspace().getRoot().getLocation(); + String rootString = rootPath.toFile().toString(); + String fileString = uri.toFileString(); + if(fileString.startsWith(rootString)) + return URI.createPlatformResourceURI(fileString.replace(rootString, ""), false); + } + return null; + } + + protected abstract void superClassChanged(); + + public URI getInputUri() { + return inputUri; + } + +} |