/** * Copyright (c) 2012 committers of YAKINDU and others. * 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: * committers of YAKINDU - initial API and implementation * */ package org.yakindu.sct.ui.editor.partitioning; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.Assert; import org.eclipse.emf.common.util.TreeIterator; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.ecore.util.EcoreUtil; import org.eclipse.emf.transaction.TransactionalEditingDomain; import org.eclipse.emf.workspace.util.WorkspaceSynchronizer; import org.eclipse.gmf.runtime.diagram.core.DiagramEditingDomainFactory; import org.eclipse.gmf.runtime.diagram.ui.parts.IDiagramEditorInput; import org.eclipse.gmf.runtime.notation.BooleanValueStyle; import org.eclipse.gmf.runtime.notation.Diagram; import org.eclipse.gmf.runtime.notation.NotationFactory; import org.eclipse.gmf.runtime.notation.NotationPackage; import org.eclipse.gmf.runtime.notation.Style; import org.eclipse.gmf.runtime.notation.View; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.ui.IEditorDescriptor; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.IEditorReference; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.PartInitException; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.part.FileEditorInput; import org.yakindu.sct.model.sgraph.CompositeElement; import org.yakindu.sct.model.sgraph.State; import org.yakindu.sct.model.sgraph.Statechart; import org.yakindu.sct.model.sgraph.resource.AbstractSCTResource; import org.yakindu.sct.ui.editor.editor.StatechartDiagramEditor; import org.yakindu.sct.ui.editor.utils.GMFNotationUtil; /** * * @author andreas muelder - Initial contribution and API * */ public class DiagramPartitioningUtil { /** GMFs notation {@link Style} id **/ public static final String INLINE_STYLE = "isInline"; private static final String DOMAIN_ID = "StatechartDomain"; private DiagramPartitioningUtil() { } /** * returns the style for diagram inlining * */ public static BooleanValueStyle getInlineStyle(View view) { BooleanValueStyle result = GMFNotationUtil.getBooleanValueStyle(view, INLINE_STYLE); return result; } /** * creates a new style for diagam inlining */ public static BooleanValueStyle createInlineStyle() { BooleanValueStyle result = NotationFactory.eINSTANCE.createBooleanValueStyle(); result.setName(INLINE_STYLE); result.setBooleanValue(true); return result; } /** * Returns the Shared Editing Domain that is used for all Editors acting on * the same {@link IResource} * * @return the {@link TransactionalEditingDomain} */ public static synchronized TransactionalEditingDomain getSharedDomain() { TransactionalEditingDomain editingDomain = TransactionalEditingDomain.Registry.INSTANCE .getEditingDomain(DOMAIN_ID); if (editingDomain == null) { editingDomain = DiagramEditingDomainFactory.getInstance().createEditingDomain(); editingDomain.setID(DOMAIN_ID); TransactionalEditingDomain.Registry.INSTANCE.add(DOMAIN_ID, editingDomain); new WorkspaceSynchronizer(editingDomain, new WorkspaceSynchronizer.Delegate() { public boolean handleResourceDeleted(Resource resource) { resource.unload(); return true; } public boolean handleResourceMoved(Resource resource, URI newURI) { resource.unload(); return true; } public boolean handleResourceChanged(Resource resource) { if (resource instanceof AbstractSCTResource) { // do not unload GMF resources as it might be the one // underlying the currently opened editor return true; } resource.unload(); try { resource.load(resource.getResourceSet().getLoadOptions()); } catch (IOException e) { e.printStackTrace(); } return true; } public void dispose() { // nothing to dispose (especially as I am shared) } }); } return editingDomain; } /** * Returns the {@link Diagram} that contains a given semantic element. */ public static Diagram getDiagramContaining(EObject element) { Assert.isNotNull(element); Resource eResource = element.eResource(); Collection<Diagram> objects = EcoreUtil.getObjectsByType(eResource.getContents(), NotationPackage.Literals.DIAGRAM); for (Diagram diagram : objects) { TreeIterator<EObject> eAllContents = diagram.eAllContents(); while (eAllContents.hasNext()) { EObject next = eAllContents.next(); if (next instanceof View) { if (EcoreUtil.equals(((View) next).getElement(), element)) { return ((View) next).getDiagram(); } } } } return null; } /** * Returns the Subdiagram for a given {@link State} or {@link Statechart} * */ public static Diagram getSubDiagram(CompositeElement element) { Assert.isNotNull(element); Resource eResource = element.eResource(); Collection<Diagram> objects = EcoreUtil.getObjectsByType(eResource.getContents(), NotationPackage.Literals.DIAGRAM); for (Diagram diagram : objects) { if (EcoreUtil.equals(diagram.getElement(), element)) return diagram; } return null; } /** * Opens the {@link StatechartDiagramEditor} for a fiven {@link IFile} * */ public static void openEditor(IFile file) { try { IEditorDescriptor desc = PlatformUI.getWorkbench().getEditorRegistry().getDefaultEditor(file.getName()); final IWorkbenchPage wbPage = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); wbPage.openEditor(new FileEditorInput(file), desc.getId()); } catch (PartInitException e) { e.printStackTrace(); } } /** * Opens a subdiagram for a given {@link Diagram} */ public static IEditorPart openEditor(Diagram diagramToOpen) { IFile file = WorkspaceSynchronizer.getFile(diagramToOpen.eResource()); try { IEditorDescriptor desc = PlatformUI.getWorkbench().getEditorRegistry().getDefaultEditor(file.getName()); final IWorkbenchPage wbPage = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); if (diagramToOpen.getElement() instanceof Statechart) { return wbPage.openEditor(new FileEditorInput(file), desc.getId()); } else if (diagramToOpen.getElement() instanceof State) { return wbPage.openEditor(new DiagramEditorInput(diagramToOpen), desc.getId()); } } catch (PartInitException e) { e.printStackTrace(); } return null; } /** * Forces the user to close all opened editors for subdiagrams that are * inlined. * * @return true if all editors were closed, false otherwise */ public static boolean closeSubdiagramEditors(State state) { Diagram diagram = DiagramPartitioningUtil.getSubDiagram(state); if (diagram == null) return true; IWorkbenchPage activePage = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); IEditorReference[] refs = activePage.getEditorReferences(); for (IEditorReference ref : refs) { try { if (ref.getEditorInput() instanceof IDiagramEditorInput) { IDiagramEditorInput diagramInput = (IDiagramEditorInput) ref.getEditorInput(); if (diagramInput.getDiagram().equals(diagram)) { boolean close = MessageDialog.openQuestion(activePage.getActivePart().getSite().getShell(), "Close subdiagram editor?", "The subdiagram is still open in another editor. Do you want to close it?"); if (close) { activePage.closeEditor(ref.getEditor(false), false); } return close; } } } catch (PartInitException e) { e.printStackTrace(); } } return true; } public static List<Diagram> getDiagramContainerHierachy(Diagram diagram) { Assert.isNotNull(diagram); List<Diagram> result = new ArrayList<Diagram>(); result.add(diagram); while (diagram.getElement() instanceof State) { diagram = DiagramPartitioningUtil.getDiagramContaining((State) diagram.getElement()); result.add(diagram); } Collections.reverse(result); return result; } public static List<Diagram> getSubDiagramHierachy(Diagram diagram) { Assert.isNotNull(diagram); List<Diagram> result = new ArrayList<Diagram>(); result.add(diagram); while (diagram.getElement() instanceof State) { diagram = DiagramPartitioningUtil.getSubDiagram((CompositeElement) diagram.getElement()); result.add(diagram); } Collections.reverse(result); return result; } }