Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian W. Damus2014-06-18 15:57:18 +0000
committerChristian W. Damus2014-07-24 20:15:37 +0000
commitdfde88b139d345b628415dda0769aa87dd7733c6 (patch)
tree6eea3b88d5bbf1f5979a37770dd836407b68a50b /tests/junit/plugins/junit
parent660eb9df792ce11992342dfa712e659811d1da11 (diff)
downloadorg.eclipse.papyrus-dfde88b139d345b628415dda0769aa87dd7733c6.tar.gz
org.eclipse.papyrus-dfde88b139d345b628415dda0769aa87dd7733c6.tar.xz
org.eclipse.papyrus-dfde88b139d345b628415dda0769aa87dd7733c6.zip
437217: [Editors] In-place reloading of model resources in the editors
https://bugs.eclipse.org/bugs/show_bug.cgi?id=437217 In situ editor reloading. Introduces an IReloadableEditor adapter protocol with an implementation in the CoreMultiDiagramEditor that implements internal destruction of the ServicesRegistry and nested editors. Some refactoring of the initialization and disposal code in the editor class hierarchy and dependencies facilitates reuse of init/dispose code in the reload scenario. The re-loading of an editor is deferred until it is next activated, unless it is already the active editor (can happen when "Save All" is invoked). Editor re-load notifications to dependent views like Model Explorer and Outline. A new listener protocol informs dependents before and after reload so that they may properly dispose of obsolete state and re-initialize when the editor is reloaded. Also ensure that an editor is only reloaded once when some resource that it depends on has changed, not once for each resource. State restoration tokens. Re-load listeners can insert tokens into the re-load event that capture state to be restored after the re-load. Listeners retrieve and apply these tokens after the editor re-loads itself. Current state restoration includes: - tree node expansion and selection state in the Model Explorer view - diagram outline view: which presentation (tree or overview thumbnail) is active - which workbench part is active, such that the correct selection is reflected in views such as Model Explorer, Outline, and Properties - current active diagram in the re-loaded editor - edit-part selections in all diagrams - selection (columns and rows, not individual cells) in table editors - palettes in each diagram (or palette pages when the Palette View is open): * active tool * pinnable stack tool selection * drawer expansion state * drawer scroll position The Palette View support incidentally fixes loss of palette state when switching between Papyrus editors, caused by the PapyrusPaletteSynchronizer. JUnit regression tests for various aspects of editor re-load. Includes a fix for an NPE in the Validation View's content provider that occurs in several tests when an editor is closed or re-loaded. Also support for tests that need to load more than one test-fixture model and/or open more than one editor. Change-Id: Ic0f654ab138d3e091f81f1e9159bcca80d6bb0a5
Diffstat (limited to 'tests/junit/plugins/junit')
-rw-r--r--tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/META-INF/MANIFEST.MF8
-rw-r--r--tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/matchers/DiagramMatchers.java104
-rw-r--r--tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/Duck.java2
-rw-r--r--tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/rules/AbstractModelFixture.java46
-rw-r--r--tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/rules/JavaResource.java4
-rw-r--r--tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/rules/PapyrusEditorFixture.java507
-rw-r--r--tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/rules/PluginResource.java4
-rw-r--r--tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/rules/ShowView.java74
8 files changed, 684 insertions, 65 deletions
diff --git a/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/META-INF/MANIFEST.MF b/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/META-INF/MANIFEST.MF
index ae8017b314c..58e9c06e0d5 100644
--- a/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/META-INF/MANIFEST.MF
+++ b/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/META-INF/MANIFEST.MF
@@ -18,8 +18,12 @@ Require-Bundle: org.eclipse.ui,
org.eclipse.papyrus.infra.tools;bundle-version="1.0.0",
org.eclipse.papyrus.infra.emf;bundle-version="1.0.0",
com.google.guava;bundle-version="11.0.0",
- org.eclipse.papyrus.infra.nattable.model;bundle-version="1.0.0"
-Export-Package: org.eclipse.papyrus.junit.utils,
+ org.eclipse.papyrus.infra.nattable.model;bundle-version="1.0.0",
+ org.eclipse.e4.ui.workbench;bundle-version="1.1.0",
+ org.eclipse.e4.ui.model.workbench;bundle-version="1.1.0",
+ org.eclipse.e4.core.contexts;bundle-version="1.3.0"
+Export-Package: org.eclipse.papyrus.junit.matchers,
+ org.eclipse.papyrus.junit.utils,
org.eclipse.papyrus.junit.utils.classification,
org.eclipse.papyrus.junit.utils.resources,
org.eclipse.papyrus.junit.utils.rules,
diff --git a/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/matchers/DiagramMatchers.java b/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/matchers/DiagramMatchers.java
new file mode 100644
index 00000000000..b78720e078a
--- /dev/null
+++ b/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/matchers/DiagramMatchers.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2014 CEA 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:
+ * Christian W. Damus (CEA) - Initial API and implementation
+ *
+ */
+package org.eclipse.papyrus.junit.matchers;
+
+import org.eclipse.gef.EditPart;
+import org.eclipse.gef.EditPartViewer;
+import org.eclipse.gef.palette.PaletteDrawer;
+import org.eclipse.gef.ui.palette.PaletteViewer;
+import org.hamcrest.BaseMatcher;
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+
+
+/**
+ * Hamcrest matchers for assertions on GMF diagrams.
+ */
+public class DiagramMatchers {
+
+ private DiagramMatchers() {
+ super();
+ }
+
+ /**
+ * Match an edit part that is selected in its viewer.
+ */
+ public static Matcher<EditPart> editPartSelected() {
+ return EditPartSelected.INSTANCE;
+ }
+
+ /**
+ * Match a drawer that is expanded in the specified {@code viewer}.
+ */
+ public static Matcher<PaletteDrawer> expandedIn(PaletteViewer viewer) {
+ return new DrawerExpansion(viewer, true);
+ }
+
+ /**
+ * Match a drawer that is collapsed (closed) in the specified {@code viewer}.
+ */
+ public static Matcher<PaletteDrawer> collapsedIn(PaletteViewer viewer) {
+ return new DrawerExpansion(viewer, false);
+ }
+
+ //
+ // Nested types
+ //
+
+ static class EditPartSelected extends BaseMatcher<EditPart> {
+
+ private static final EditPartSelected INSTANCE = new EditPartSelected();
+
+ private EditPartSelected() {
+ super();
+ }
+
+ public void describeTo(Description description) {
+ description.appendText("edit-part is selected");
+ }
+
+ public boolean matches(Object item) {
+ return (item instanceof EditPart) && isSelected((EditPart)item);
+ }
+
+ boolean isSelected(EditPart editPart) {
+ EditPartViewer viewer = editPart.getViewer();
+ return (viewer != null) && viewer.getSelectedEditParts().contains(editPart);
+ }
+ }
+
+ static class DrawerExpansion extends BaseMatcher<PaletteDrawer> {
+
+ private final PaletteViewer viewer;
+
+ private final boolean expanded;
+
+ DrawerExpansion(PaletteViewer viewer, boolean expanded) {
+ this.viewer = viewer;
+ this.expanded = expanded;
+ }
+
+ public void describeTo(Description description) {
+ description.appendText("drawer is ");
+ description.appendText(expanded ? "expanded" : "collapsed");
+ }
+
+ public boolean matches(Object item) {
+ return (item instanceof PaletteDrawer) && (isExpanded((PaletteDrawer)item) == expanded);
+ }
+
+ boolean isExpanded(PaletteDrawer drawer) {
+ return viewer.isExpanded(drawer);
+ }
+ }
+}
diff --git a/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/Duck.java b/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/Duck.java
index b7a253b003b..1abd00dea18 100644
--- a/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/Duck.java
+++ b/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/Duck.java
@@ -159,7 +159,7 @@ public class Duck {
Method[] scope = target.getClass().getMethods();
for(int i = 0; (result == null) && (i < scope.length); i++) {
Method next = scope[i];
- if(next.getName().equals(methodName) && (returning == null) && match(next, signature)) {
+ if(next.getName().equals(methodName) && matchReturn(next.getReturnType(), returning) && match(next, signature)) {
result = next;
}
}
diff --git a/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/rules/AbstractModelFixture.java b/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/rules/AbstractModelFixture.java
index 231adc4f384..5d0da4a751d 100644
--- a/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/rules/AbstractModelFixture.java
+++ b/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/rules/AbstractModelFixture.java
@@ -24,6 +24,7 @@ import java.net.URL;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.LinkedList;
+import java.util.List;
import java.util.Queue;
import java.util.Set;
@@ -55,6 +56,7 @@ import org.osgi.framework.FrameworkUtil;
import com.google.common.base.Predicates;
import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
import com.google.common.io.ByteStreams;
@@ -87,6 +89,8 @@ public abstract class AbstractModelFixture<T extends EditingDomain> extends Test
private Class<?> testClass;
+ private Iterable<URI> initialResourceURIs;
+
public AbstractModelFixture() {
super();
}
@@ -146,15 +150,44 @@ public abstract class AbstractModelFixture<T extends EditingDomain> extends Test
@Override
protected void starting(Description description) {
domain = createEditingDomain();
- model = (Package)initModelResource(description).getContents().get(0);
+ model = (Package)Iterables.getFirst(initModelResources(description), null).getContents().get(0);
+
+ // We have finished initializing
+ initialResourceURIs = null;
}
- protected Resource initModelResource(Description description) {
- Annotation resourceAnnotation = getResourceAnnotation(description);
- ResourceKind kind = ResourceKind.getResourceKind(resourceAnnotation);
+ protected Iterable<Resource> initModelResources(Description description) {
+ List<Resource> result;
+
+ // Don't initialize the resources more than once (subclasses such as PapyrusEditorFixture can repeat this)
+ if(initialResourceURIs == null) {
+ Annotation resourceAnnotation = getResourceAnnotation(description);
+ ResourceKind kind = ResourceKind.getResourceKind(resourceAnnotation);
+
+ final String[] paths = kind.getResourcePaths(resourceAnnotation);
+ result = Lists.newArrayListWithCapacity(paths.length);
+
+ for(String path : paths) {
+ result.add(initModelResource(new Path(path), kind));
+ }
+
+ List<URI> uris = Lists.newArrayListWithCapacity(result.size());
+ for(Resource next : result) {
+ uris.add(next.getURI());
+ }
+ initialResourceURIs = uris;
+ } else {
+ ResourceSet rset = getResourceSet();
+ result = Lists.newArrayList();
+ for(URI next : initialResourceURIs) {
+ result.add(rset.getResource(next, true));
+ }
+ }
- IPath resourcePath = new Path(kind.getResourcePath(resourceAnnotation));
+ return result;
+ }
+ private Resource initModelResource(IPath resourcePath, ResourceKind kind) {
String targetResourceName = "model";
if(isDIModel(resourcePath)) {
// We will be initializing all three resources, and they have cross-references, so must not change
@@ -309,6 +342,7 @@ public abstract class AbstractModelFixture<T extends EditingDomain> extends Test
protected void finished(Description description) {
final ResourceSet resourceSet = getResourceSet();
+ initialResourceURIs = null;
model = null;
if(domain instanceof TransactionalEditingDomain) {
@@ -359,7 +393,7 @@ public abstract class AbstractModelFixture<T extends EditingDomain> extends Test
return (resourceAnnotation instanceof JavaResource) ? JAVA : (resourceAnnotation instanceof PluginResource) ? BUNDLE : null;
}
- String getResourcePath(Annotation resourceAnnotation) {
+ String[] getResourcePaths(Annotation resourceAnnotation) {
switch(this) {
case JAVA:
return ((JavaResource)resourceAnnotation).value();
diff --git a/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/rules/JavaResource.java b/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/rules/JavaResource.java
index d9aa6b14340..23d870281ba 100644
--- a/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/rules/JavaResource.java
+++ b/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/rules/JavaResource.java
@@ -19,7 +19,7 @@ import java.lang.annotation.Target;
/**
- * Annotation indicating the classpath-relative path to a resource from which to load the test model of an {@link AbstractModelFixture}.
+ * Annotation indicating the classpath-relative path to one or more resources from which to load the test model of an {@link AbstractModelFixture}.
*
* @see AbstractModelFixture
* @see PluginResource
@@ -28,5 +28,5 @@ import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
public @interface JavaResource {
- String value();
+ String[] value();
}
diff --git a/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/rules/PapyrusEditorFixture.java b/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/rules/PapyrusEditorFixture.java
index c0f21173585..de24d1c0d43 100644
--- a/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/rules/PapyrusEditorFixture.java
+++ b/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/rules/PapyrusEditorFixture.java
@@ -17,26 +17,44 @@ import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.fail;
+import java.util.Collection;
import java.util.Iterator;
+import java.util.List;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
+import org.eclipse.e4.ui.model.application.ui.MUIElement;
+import org.eclipse.e4.ui.model.application.ui.advanced.MPlaceholder;
+import org.eclipse.e4.ui.model.application.ui.basic.MPart;
+import org.eclipse.e4.ui.model.application.ui.basic.MPartSashContainerElement;
+import org.eclipse.e4.ui.model.application.ui.basic.MPartStack;
+import org.eclipse.e4.ui.model.application.ui.basic.MStackElement;
+import org.eclipse.e4.ui.workbench.modeling.EModelService;
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.gef.EditPart;
import org.eclipse.gef.GraphicalEditPart;
+import org.eclipse.gef.ui.palette.PaletteViewer;
import org.eclipse.gmf.runtime.diagram.ui.editparts.DiagramEditPart;
+import org.eclipse.gmf.runtime.diagram.ui.parts.DiagramEditor;
+import org.eclipse.gmf.runtime.diagram.ui.parts.DiagramEditorWithFlyOutPalette;
import org.eclipse.gmf.runtime.diagram.ui.parts.IDiagramWorkbenchPart;
-import org.eclipse.gmf.runtime.notation.Diagram;
import org.eclipse.gmf.runtime.notation.View;
+import org.eclipse.papyrus.editor.PapyrusMultiDiagramEditor;
import org.eclipse.papyrus.infra.core.editor.IMultiDiagramEditor;
import org.eclipse.papyrus.infra.core.resource.ModelSet;
import org.eclipse.papyrus.infra.core.resource.sasheditor.DiModel;
import org.eclipse.papyrus.infra.core.sasheditor.contentprovider.IPageManager;
+import org.eclipse.papyrus.infra.core.sasheditor.editor.IComponentPage;
+import org.eclipse.papyrus.infra.core.sasheditor.editor.IEditorPage;
+import org.eclipse.papyrus.infra.core.sasheditor.editor.IPageVisitor;
+import org.eclipse.papyrus.infra.core.sasheditor.editor.ISashWindowsContainer;
import org.eclipse.papyrus.infra.core.services.ServiceException;
import org.eclipse.papyrus.infra.core.services.ServicesRegistry;
import org.eclipse.papyrus.infra.core.utils.AdapterUtils;
@@ -48,14 +66,18 @@ import org.eclipse.papyrus.views.modelexplorer.ModelExplorerPageBookView;
import org.eclipse.papyrus.views.modelexplorer.ModelExplorerView;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IEditorReference;
import org.eclipse.ui.IPartListener;
+import org.eclipse.ui.ISaveablePart;
import org.eclipse.ui.IViewPart;
+import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.part.IPage;
+import org.eclipse.uml2.uml.NamedElement;
import org.eclipse.uml2.uml.Package;
import org.eclipse.uml2.uml.UMLPackage;
import org.junit.runner.Description;
@@ -63,7 +85,10 @@ import org.osgi.framework.Bundle;
import org.osgi.framework.FrameworkUtil;
import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
+import com.google.common.collect.Iterators;
+import com.google.common.collect.Lists;
/**
@@ -72,14 +97,20 @@ import com.google.common.collect.Iterables;
*/
public class PapyrusEditorFixture extends AbstractModelFixture<TransactionalEditingDomain> {
+ private final Collection<IEditorPart> editorsToClose = Lists.newArrayList();
+
private IMultiDiagramEditor editor;
+ private DiagramEditorWithFlyOutPalette activeDiagramEditor;
+
private ModelExplorerView modelExplorer;
private Class<?> testClass;
private Description testDescription;
+ private Collection<IViewPart> viewsToClose;
+
public PapyrusEditorFixture() {
super();
}
@@ -88,12 +119,29 @@ public class PapyrusEditorFixture extends AbstractModelFixture<TransactionalEdit
return editor;
}
+ public IMultiDiagramEditor getEditor(String path) {
+ IMultiDiagramEditor result = null;
+
+ final String fileName = new Path(path).lastSegment();
+ for(IEditorReference next : getWorkbenchPage().getEditorReferences()) {
+ if(PapyrusMultiDiagramEditor.EDITOR_ID.equals(next.getId()) && fileName.equals(next.getName())) {
+ result = (IMultiDiagramEditor)next.getEditor(true);
+ }
+ }
+
+ return result;
+ }
+
@Override
protected void starting(Description description) {
testClass = description.getTestClass();
testDescription = description;
- open(description);
+ if(hasRequiredViews()) {
+ openRequiredViews();
+ }
+
+ openAll(description);
super.starting(description);
}
@@ -101,12 +149,34 @@ public class PapyrusEditorFixture extends AbstractModelFixture<TransactionalEdit
@Override
protected void finished(Description description) {
try {
- if(editor != null) {
- close(editor);
- editor = null;
+ Exception exception = null;
+
+ for(IEditorPart editor : ImmutableList.copyOf(editorsToClose)) {
+ try {
+ close(editor);
+ } catch (Exception e) {
+ if(exception == null) {
+ exception = e;
+ }
+ }
+ }
+
+ if(exception != null) {
+ exception.printStackTrace();
+ fail("Failed to close an editor: " + exception.getLocalizedMessage());
}
} finally {
- super.finished(description);
+ editorsToClose.clear();
+ editor = null;
+ activeDiagramEditor = null;
+
+ try {
+ if(hasRequiredViews()) {
+ closeRequiredViews();
+ }
+ } finally {
+ super.finished(description);
+ }
}
}
@@ -115,15 +185,23 @@ public class PapyrusEditorFixture extends AbstractModelFixture<TransactionalEdit
TransactionalEditingDomain result = null;
if(editor != null) {
- try {
- result = getServiceRegistry().getService(TransactionalEditingDomain.class);
- } catch (ServiceException e) {
- e.printStackTrace();
- fail("Failed to get editing domain from Papyrus editor: " + e.getLocalizedMessage());
- }
+ result = getEditingDomain(editor);
}
+
return result;
+ }
+
+ public TransactionalEditingDomain getEditingDomain(IMultiDiagramEditor editor) {
+ TransactionalEditingDomain result = null;
+ try {
+ result = getServiceRegistry(editor).getService(TransactionalEditingDomain.class);
+ } catch (ServiceException e) {
+ e.printStackTrace();
+ fail("Failed to get editing domain from Papyrus editor: " + e.getLocalizedMessage());
+ }
+
+ return result;
}
@Override
@@ -133,11 +211,14 @@ public class PapyrusEditorFixture extends AbstractModelFixture<TransactionalEdit
}
protected IMultiDiagramEditor open(final IFile modelFile) {
+ final boolean firstEditor = editorsToClose.isEmpty();
+
Display.getDefault().syncExec(new Runnable() {
public void run() {
try {
editor = EditorUtils.openPapyrusEditor(modelFile);
+ editorsToClose.add(editor);
} catch (Exception e) {
e.printStackTrace();
fail("Failed to open Papyrus editor: " + e.getLocalizedMessage());
@@ -145,45 +226,63 @@ public class PapyrusEditorFixture extends AbstractModelFixture<TransactionalEdit
}
});
- final IWorkbenchPage page = editor.getSite().getPage();
- page.addPartListener(new IPartListener() {
+ if(firstEditor && !editorsToClose.isEmpty()) {
+ final IWorkbenchPage page = editor.getSite().getPage();
+ page.addPartListener(new IPartListener() {
+
+ public void partClosed(IWorkbenchPart part) {
+ editorsToClose.remove(part);
+
+ if(part == editor) {
+ editor = null;
+ }
- public void partClosed(IWorkbenchPart part) {
- if(part == editor) {
- editor = null;
+ if(editorsToClose.isEmpty()) {
+ page.removePartListener(this);
+ }
}
- page.removePartListener(this);
- }
- public void partOpened(IWorkbenchPart part) {
- // Pass
- }
+ public void partOpened(IWorkbenchPart part) {
+ // Pass
+ }
- public void partDeactivated(IWorkbenchPart part) {
- // Pass
- }
+ public void partDeactivated(IWorkbenchPart part) {
+ // Pass
+ }
- public void partBroughtToTop(IWorkbenchPart part) {
- // Pass
- }
+ public void partBroughtToTop(IWorkbenchPart part) {
+ // Pass
+ }
- public void partActivated(IWorkbenchPart part) {
- // Pass
- }
- });
+ public void partActivated(IWorkbenchPart part) {
+ // Pass
+ }
+ });
+ }
flushDisplayEvents();
return editor;
}
- protected IMultiDiagramEditor open(Description description) {
- IFile papyrusModel = getProject().getFile(initModelResource(description).getURI().trimFileExtension().appendFileExtension(DiModel.DI_FILE_EXTENSION));
+ protected IMultiDiagramEditor openOne(Description description) {
+ IFile papyrusModel = getProject().getFile(Iterables.getOnlyElement(initModelResources(description)).getURI().trimFileExtension().appendFileExtension(DiModel.DI_FILE_EXTENSION));
return open(papyrusModel);
}
+ protected Iterable<IMultiDiagramEditor> openAll(Description description) {
+ List<IMultiDiagramEditor> result = Lists.newArrayList();
+
+ for(Resource resource : initModelResources(description)) {
+ IFile papyrusModel = getProject().getFile(resource.getURI().trimFileExtension().appendFileExtension(DiModel.DI_FILE_EXTENSION));
+ result.add(open(papyrusModel));
+ }
+
+ return result;
+ }
+
public IMultiDiagramEditor open() {
- return open(testDescription);
+ return openOne(testDescription);
}
public IMultiDiagramEditor open(String resourcePath) {
@@ -206,7 +305,12 @@ public class PapyrusEditorFixture extends AbstractModelFixture<TransactionalEdit
}
public void activate(IWorkbenchPart part) {
- part.getSite().getPage().activate(part);
+ IWorkbenchPage page = part.getSite().getPage();
+
+ if(page.getActivePart() != part) {
+ page.activate(part);
+ flushDisplayEvents();
+ }
}
public void close() {
@@ -226,11 +330,9 @@ public class PapyrusEditorFixture extends AbstractModelFixture<TransactionalEdit
Display.getDefault().syncExec(new Runnable() {
public void run() {
- IWorkbenchWindow activeWorkbenchWindow = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
-
ModelExplorerPageBookView view;
try {
- view = (ModelExplorerPageBookView)activeWorkbenchWindow.getActivePage().showView(AbstractEditorTest.MODELEXPLORER_VIEW_ID);
+ view = (ModelExplorerPageBookView)getWorkbenchPage().showView(AbstractEditorTest.MODELEXPLORER_VIEW_ID);
} catch (PartInitException e) {
e.printStackTrace();
return;
@@ -246,13 +348,30 @@ public class PapyrusEditorFixture extends AbstractModelFixture<TransactionalEdit
return modelExplorer;
}
+ protected final IWorkbenchPage getWorkbenchPage() {
+ IWorkbench bench = PlatformUI.getWorkbench();
+ IWorkbenchWindow window = bench.getActiveWorkbenchWindow();
+ if(window == null) {
+ window = bench.getWorkbenchWindows()[0];
+ }
+ return window.getActivePage();
+ }
+
public ServicesRegistry getServiceRegistry() {
+ return getServiceRegistry(editor);
+ }
+
+ public ServicesRegistry getServiceRegistry(IMultiDiagramEditor editor) {
return editor.getServicesRegistry();
}
public ModelSet getModelSet() {
+ return getModelSet(editor);
+ }
+
+ public ModelSet getModelSet(IMultiDiagramEditor editor) {
try {
- return getServiceRegistry().getService(ModelSet.class);
+ return getServiceRegistry(editor).getService(ModelSet.class);
} catch (ServiceException e) {
e.printStackTrace();
fail("Failed to get model set from Papyrus editor: " + e.getLocalizedMessage());
@@ -262,9 +381,14 @@ public class PapyrusEditorFixture extends AbstractModelFixture<TransactionalEdit
@Override
public Package getModel() {
+ return getModel(editor);
+ }
+
+ public Package getModel(IMultiDiagramEditor editor) {
Package result = null;
- UmlModel uml = (UmlModel)getModelSet().getModel(UmlModel.MODEL_ID);
+ ModelSet modelSet = getModelSet(editor);
+ UmlModel uml = (UmlModel)modelSet.getModel(UmlModel.MODEL_ID);
assertThat("No UML model present in resource set", uml.getResource(), notNullValue());
result = (Package)EcoreUtil.getObjectByType(uml.getResource().getContents(), UMLPackage.Literals.PACKAGE);
@@ -274,8 +398,12 @@ public class PapyrusEditorFixture extends AbstractModelFixture<TransactionalEdit
}
public IPageManager getPageManager() {
+ return getPageManager(editor);
+ }
+
+ public IPageManager getPageManager(IMultiDiagramEditor editor) {
try {
- return getServiceRegistry().getService(IPageManager.class);
+ return getServiceRegistry(editor).getService(IPageManager.class);
} catch (ServiceException e) {
e.printStackTrace();
fail("Failed to get page manager from Papyrus editor: " + e.getLocalizedMessage());
@@ -284,20 +412,67 @@ public class PapyrusEditorFixture extends AbstractModelFixture<TransactionalEdit
}
public PapyrusEditorFixture activateDiagram(String name) {
- for(Diagram diagram : Iterables.filter(getPageManager().allPages(), Diagram.class)) {
- if(name.equals(diagram.getName())) {
- getPageManager().selectPage(diagram);
- break;
+ return activateDiagram(editor, name);
+ }
+
+ public PapyrusEditorFixture activateDiagram(IMultiDiagramEditor editor, final String name) {
+ activate(editor);
+
+ final ISashWindowsContainer sashContainer = AdapterUtils.adapt(editor, ISashWindowsContainer.class, null);
+ final org.eclipse.papyrus.infra.core.sasheditor.editor.IPage[] select = { null };
+
+ sashContainer.visit(new IPageVisitor() {
+
+ public void accept(IEditorPage page) {
+ if(name.equals(page.getPageTitle()) && (page.getIEditorPart() instanceof DiagramEditorWithFlyOutPalette)) {
+ select[0] = page;
+ activeDiagramEditor = (DiagramEditorWithFlyOutPalette)page.getIEditorPart();
+ }
+ }
+
+ public void accept(IComponentPage page) {
+ // Pass
}
+ });
+
+ if(select[0] != null) {
+ sashContainer.selectPage(select[0]);
+ flushDisplayEvents();
}
return this;
}
+ public DiagramEditorWithFlyOutPalette getActiveDiagramEditor() {
+ DiagramEditorWithFlyOutPalette result = activeDiagramEditor;
+
+ if(result == null) {
+ IEditorPart activeEditor = getWorkbenchPage().getActiveEditor();
+ if(activeEditor instanceof IMultiDiagramEditor) {
+ activeEditor = ((IMultiDiagramEditor)activeEditor).getActiveEditor();
+ if(activeEditor instanceof DiagramEditorWithFlyOutPalette) {
+ result = (DiagramEditorWithFlyOutPalette)activeEditor;
+ }
+ }
+ }
+
+ assertThat("No diagram active", result, notNullValue());
+
+ return result;
+ }
+
public EditPart findEditPart(EObject modelElement) {
- IEditorPart activeEditor = getEditor().getActiveEditor();
- assertThat("No diagram active", activeEditor, instanceOf(IDiagramWorkbenchPart.class));
- DiagramEditPart diagram = ((IDiagramWorkbenchPart)activeEditor).getDiagramEditPart();
+ return findEditPart(getActiveDiagramEditor(), modelElement);
+ }
+
+ public EditPart findEditPart(IMultiDiagramEditor editor, EObject modelElement) {
+ IEditorPart activeEditor = editor.getActiveEditor();
+ assertThat("No diagram active", activeEditor, instanceOf(DiagramEditor.class));
+ return findEditPart((DiagramEditor)activeEditor, modelElement);
+ }
+
+ public EditPart findEditPart(IDiagramWorkbenchPart editor, EObject modelElement) {
+ DiagramEditPart diagram = editor.getDiagramEditPart();
return findEditPart(diagram, modelElement);
}
@@ -326,6 +501,49 @@ public class PapyrusEditorFixture extends AbstractModelFixture<TransactionalEdit
return result;
}
+ public EditPart findEditPart(String name, Class<? extends NamedElement> type) {
+ return findEditPart(getActiveDiagramEditor(), name, type);
+ }
+
+ public EditPart findEditPart(IMultiDiagramEditor editor, String name, Class<? extends NamedElement> type) {
+ IEditorPart activeEditor = editor.getActiveEditor();
+ assertThat("No diagram active", activeEditor, instanceOf(DiagramEditor.class));
+ return findEditPart((DiagramEditor)activeEditor, name, type);
+ }
+
+ public EditPart findEditPart(IDiagramWorkbenchPart editor, String name, Class<? extends NamedElement> type) {
+ EditPart result = null;
+
+ for(Iterator<View> views = Iterators.filter(editor.getDiagram().eAllContents(), View.class); views.hasNext();) {
+ View next = views.next();
+ EObject element = next.getElement();
+ if(type.isInstance(element) && name.equals(type.cast(element).getName())) {
+ result = (EditPart)editor.getDiagramGraphicalViewer().getEditPartRegistry().get(next);
+ break;
+ }
+ }
+
+ return result;
+ }
+
+ public void select(EditPart editPart) {
+ editPart.getViewer().getSelectionManager().appendSelection(editPart);
+ }
+
+ public PaletteViewer getPalette() {
+ return getPalette(getActiveDiagramEditor());
+ }
+
+ public PaletteViewer getPalette(IMultiDiagramEditor editor) {
+ IEditorPart activeEditor = editor.getActiveEditor();
+ assertThat("No diagram active", activeEditor, instanceOf(DiagramEditor.class));
+ return getPalette((DiagramEditor)activeEditor);
+ }
+
+ public PaletteViewer getPalette(IDiagramWorkbenchPart editor) {
+ return editor.getDiagramEditPart().getViewer().getEditDomain().getPaletteViewer();
+ }
+
public void flushDisplayEvents() {
for(;;) {
try {
@@ -342,12 +560,12 @@ public class PapyrusEditorFixture extends AbstractModelFixture<TransactionalEdit
public IViewPart getView(String id, boolean open) {
IViewPart result = null;
- IWorkbenchWindow activeWorkbenchWindow = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+ IWorkbenchPage wbPage = getWorkbenchPage();
try {
- result = activeWorkbenchWindow.getActivePage().findView(id);
+ result = wbPage.findView(id);
if((result == null) && open) {
- result = activeWorkbenchWindow.getActivePage().showView(id);
+ result = wbPage.showView(id);
}
if(result != null) {
@@ -363,4 +581,189 @@ public class PapyrusEditorFixture extends AbstractModelFixture<TransactionalEdit
return result;
}
+
+ public void save(ISaveablePart part) {
+ if(part.isDirty()) {
+ try {
+ part.doSave(new NullProgressMonitor());
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail("Failed to save editor/view: " + e.getLocalizedMessage());
+ } finally {
+ // Must flush display events because some steps (e.g. dependent editor reload)
+ // are done asynchronously in a UI job
+ flushDisplayEvents();
+ }
+ }
+ }
+
+ public void saveAll() {
+ try {
+ IWorkbenchPage page = editor.getSite().getPage();
+ page.saveAllEditors(false);
+ } finally {
+ // Must flush display events because some steps (e.g. dependent editor reload)
+ // are done asynchronously in a UI job
+ flushDisplayEvents();
+ }
+ }
+
+ public void splitEditorArea(IEditorPart editorToMove, boolean splitHorizontally) {
+ MPart editorPart = (MPart)editorToMove.getSite().getService(MPart.class);
+ EModelService modelService = editorPart.getContext().get(EModelService.class);
+ MPartStack oldStack = (MPartStack)modelService.getContainer(editorPart);
+ MPartStack newStack = modelService.createModelElement(MPartStack.class);
+ modelService.insert(newStack, oldStack, splitHorizontally ? EModelService.RIGHT_OF : EModelService.BELOW, 0.5f);
+ newStack.getChildren().add(editorPart);
+
+ activate(editorToMove);
+ }
+
+ public List<IWorkbenchPart> getPartStack(IWorkbenchPart part) {
+ List<IWorkbenchPart> result;
+
+ MPart mpart = (MPart)part.getSite().getService(MPart.class);
+ EModelService modelService = mpart.getContext().get(EModelService.class);
+ MPartStack stack = (MPartStack)modelService.getContainer(mpart);
+
+ result = Lists.newArrayListWithCapacity(stack.getChildren().size());
+ for(MPart next : Iterables.filter(stack.getChildren(), MPart.class)) {
+ IWorkbenchPart wbPart = next.getContext().get(IWorkbenchPart.class);
+ if(wbPart != null) {
+ result.add(wbPart);
+ }
+ }
+
+ return result;
+ }
+
+ protected final boolean hasRequiredViews() {
+ return getRequiredViews() != null;
+ }
+
+ protected final ShowView getRequiredViews() {
+ ShowView result = testDescription.getAnnotation(ShowView.class);
+
+ if(result == null) {
+ for(Class<?> clazz = testClass; (result == null) && (clazz != null) && (clazz != Object.class); clazz = clazz.getSuperclass()) {
+ result = clazz.getAnnotation(ShowView.class);
+ }
+ }
+
+ return result;
+ }
+
+ protected void openRequiredViews() {
+ IWorkbenchPage page = getWorkbenchPage();
+
+ for(ShowViewDescriptor next : ShowViewDescriptor.getDescriptors(getRequiredViews())) {
+ IViewPart part = page.findView(next.viewID());
+ if(part == null) {
+ // Must open it
+ try {
+ part = page.showView(next.viewID());
+ movePartRelativeTo(part, next.relativeTo(), next.location());
+
+ if(viewsToClose == null) {
+ viewsToClose = Lists.newArrayListWithExpectedSize(1);
+ }
+ viewsToClose.add(part);
+ } catch (PartInitException e) {
+ e.printStackTrace();
+ fail("Failed to open required view: " + e.getLocalizedMessage());
+ }
+ }
+ }
+
+ flushDisplayEvents();
+ }
+
+ private void movePartRelativeTo(IWorkbenchPart part, String relativeTo, int where) {
+ MPart mPart = (MPart)part.getSite().getService(MPart.class);
+ EModelService modelService = mPart.getContext().get(EModelService.class);
+ MUIElement relativePart = modelService.find(relativeTo, modelService.getTopLevelWindowFor(mPart));
+ if(relativePart instanceof MPartSashContainerElement) {
+ MStackElement toMove = mPart;
+ MPlaceholder placeHolder = mPart.getCurSharedRef();
+ if(placeHolder != null) {
+ toMove = placeHolder;
+ }
+
+ if(where < 0) {
+ // Add it to the relative part's containing stack
+ if(relativePart instanceof MPart) {
+ MPart relativeMPart = (MPart)relativePart;
+ if(relativeMPart.getCurSharedRef() != null) {
+ // This is where the part is stacked
+ relativePart = relativeMPart.getCurSharedRef();
+ }
+ }
+ relativePart.getParent().getChildren().add(toMove);
+ } else {
+ // Insert it next to the relative part
+ MPartStack newStack = modelService.createModelElement(MPartStack.class);
+ newStack.getChildren().add(toMove);
+ modelService.insert(newStack, (MPartSashContainerElement)relativePart, where, 0.3f);
+ }
+ }
+ }
+
+ protected void closeRequiredViews() {
+ // Only close the Palette view if we opened it
+ if(viewsToClose != null) {
+ for(IViewPart closeMe : viewsToClose) {
+ closeMe.getSite().getPage().hideView(closeMe);
+ }
+ viewsToClose = null;
+ flushDisplayEvents();
+ }
+ }
+
+ private static final class ShowViewDescriptor {
+
+ private static final String DEFAULT_RELATIVE_TO = "org.eclipse.ui.editorss"; //$NON-NLS-1$
+
+ private static final ShowView.Location DEFAULT_LOCATION_EDITORS = ShowView.Location.RIGHT;
+
+ private static final ShowView.Location DEFAULT_LOCATION_VIEW = ShowView.Location.STACKED;
+
+ private final String viewID;
+
+ private final String relativeTo;
+
+ private final ShowView.Location location;
+
+ private ShowViewDescriptor(ShowView annotation, int index) {
+ this.viewID = annotation.value()[index];
+
+ String[] relativeTo = annotation.relativeTo();
+ this.relativeTo = (relativeTo.length == 0) ? null : (relativeTo.length == 1) ? relativeTo[0] : relativeTo[index];
+
+ ShowView.Location[] location = annotation.location();
+ this.location = (location.length == 0) ? null : (location.length == 1) ? location[0] : location[index];
+ }
+
+ static Iterable<ShowViewDescriptor> getDescriptors(final ShowView annotation) {
+ ImmutableList.Builder<ShowViewDescriptor> result = ImmutableList.builder();
+
+ String[] ids = annotation.value();
+ for(int i = 0; i < ids.length; i++) {
+ result.add(new ShowViewDescriptor(annotation, i));
+ }
+
+ return result.build();
+ }
+
+ String viewID() {
+ return viewID;
+ }
+
+ String relativeTo() {
+ return (relativeTo != null) ? relativeTo : DEFAULT_RELATIVE_TO;
+ }
+
+ int location() {
+ return ((location != null) ? location : (relativeTo == null) ? DEFAULT_LOCATION_EDITORS : DEFAULT_LOCATION_VIEW).toModelServiceLocation();
+ }
+ }
}
diff --git a/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/rules/PluginResource.java b/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/rules/PluginResource.java
index dc1e7e6eacd..aba01b2b74e 100644
--- a/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/rules/PluginResource.java
+++ b/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/rules/PluginResource.java
@@ -19,7 +19,7 @@ import java.lang.annotation.Target;
/**
- * Annotation indicating the bundle-relative path to a resource from which to load the test model of an {@link AbstractModelFixture}.
+ * Annotation indicating the bundle-relative path to one or more resources from which to load the test model of an {@link AbstractModelFixture}.
*
* @see AbstractModelFixture
* @see JavaResource
@@ -28,5 +28,5 @@ import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
public @interface PluginResource {
- String value();
+ String[] value();
}
diff --git a/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/rules/ShowView.java b/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/rules/ShowView.java
new file mode 100644
index 00000000000..103db0b1d37
--- /dev/null
+++ b/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/rules/ShowView.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2014 CEA 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:
+ * Christian W. Damus (CEA) - Initial API and implementation
+ *
+ */
+package org.eclipse.papyrus.junit.utils.rules;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import org.eclipse.e4.ui.workbench.modeling.EModelService;
+
+
+/**
+ * An annotation on tests using the {@link PapyrusEditorFixture} that need the palette view to be open before initializing the
+ * test (which generally entails opening one or more editors).
+ */
+@Target({ ElementType.METHOD, ElementType.TYPE })
+@Retention(RetentionPolicy.RUNTIME)
+public @interface ShowView {
+
+ /** The IDs of the views to show before the editor is opened. */
+ String[] value();
+
+ /**
+ * The IDs of workbench parts relative to which the views specified by the annotation are to be shown. If unspecified,
+ * the default is the workbench's editor area. If exactly part ID is specified, it is used for all views. Otherwise, a
+ * corresponding value is required for each view ID to be shown.
+ */
+ String[] relativeTo() default {};
+
+ /**
+ * The relative locations of the views to show. If unspecified, the default is {@link Location#STACKED} when the {@linkplain #relativeTo()
+ * relative part} is a view, otherwise {@link Location#RIGHT} when the relative part is the editor area.
+ * If exactly one value is specified, it is used for all views. Otherwise, a corresponding value is
+ * required for each view ID.
+ */
+ Location[] location() default {};
+
+ /**
+ * Enumeration of locations in which to open a view relative to some other workbench part.
+ */
+ enum Location {
+ /** Stacked with the relative part. */
+ STACKED(-1),
+ /** To the left of the relative part. */
+ LEFT(EModelService.LEFT_OF),
+ /** To the right of the relative part. */
+ RIGHT(EModelService.RIGHT_OF),
+ /** Above the relative part. */
+ ABOVE(EModelService.ABOVE),
+ /** Below the relative part. */
+ BELOW(EModelService.BELOW);
+
+ private final int modelServiceLocation;
+
+ private Location(int modelServiceLocation) {
+ this.modelServiceLocation = modelServiceLocation;
+ }
+
+ public int toModelServiceLocation() {
+ return modelServiceLocation;
+ }
+ }
+}

Back to the top