blob: 4620cafa8e4fd4a155b4f3e23cd9f1cbe90575d6 [file] [log] [blame]
/******************************************************************************
* Copyright (c) 2002, 2007 IBM Corporation 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:
* IBM Corporation - initial API and implementation
****************************************************************************/
package org.eclipse.gmf.tests.runtime.diagram.ui.util;
import java.util.List;
import java.util.ListIterator;
import junit.framework.Assert;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Status;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.emf.transaction.util.TransactionUtil;
import org.eclipse.emf.workspace.AbstractEMFOperation;
import org.eclipse.gef.Request;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.commands.CommandStack;
import org.eclipse.gef.requests.CreateConnectionRequest;
import org.eclipse.gef.requests.CreateRequest;
import org.eclipse.gmf.runtime.common.core.util.Log;
import org.eclipse.gmf.runtime.diagram.core.DiagramEditingDomainFactory;
import org.eclipse.gmf.runtime.diagram.core.preferences.PreferencesHint;
import org.eclipse.gmf.runtime.diagram.core.util.ViewUtil;
import org.eclipse.gmf.runtime.diagram.ui.OffscreenEditPartFactory;
import org.eclipse.gmf.runtime.diagram.ui.editparts.ConnectionEditPart;
import org.eclipse.gmf.runtime.diagram.ui.editparts.DiagramEditPart;
import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart;
import org.eclipse.gmf.runtime.diagram.ui.editparts.ShapeEditPart;
import org.eclipse.gmf.runtime.diagram.ui.parts.IDiagramWorkbenchPart;
import org.eclipse.gmf.runtime.diagram.ui.requests.RequestConstants;
import org.eclipse.gmf.runtime.diagram.ui.resources.editor.ide.util.IDEEditorUtil;
import org.eclipse.gmf.runtime.emf.type.core.IElementType;
import org.eclipse.gmf.runtime.notation.Diagram;
import org.eclipse.gmf.runtime.notation.Edge;
import org.eclipse.gmf.runtime.notation.View;
import org.eclipse.gmf.tests.runtime.diagram.ui.AbstractTestBase;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.ide.IDE;
import org.eclipse.ui.part.EditorPart;
/**
* @author choang
*
* Most fixture should extend fromthis Abstract class. The only things that are left to do is to implement the following
* abstract methods
* 1. createProject,createDiagram,craeteShapesAndConnectors
* 2. Implement you test class which should extend from org.junit.org or @see org.eclipse.gmf.tests.runtime.diagram.ui.AbstractTestBase
*
*/
public abstract class AbstractPresentationTestFixture
extends Assert
implements IPresentationTestFixture {
private IProject project = null;
private IDiagramWorkbenchPart diagramWorkbenchPart = null;
private IFile diagramFile = null;
private TransactionalEditingDomain editingDomain;
private Resource resource;
private Diagram diagram;
private DiagramEditPart diagramEditPart;
private Edge connectorView = null;
// connector view for the test fixture
/**
* Temporary shell to be used when creating the diagram editpart.
*/
private Shell tempShell;
/** verbose flag. */
private static boolean _verbose = Boolean.getBoolean(AbstractTestBase.SYSPROP_VERBOSE);
/**
* Returns the diagramFile.
* @return IFile
*/
public IFile getDiagramFile() {
return diagramFile;
}
/**
* Enable verbose mode. If enabled, {@link junit.framework.Assert#fail(java.lang.String)}
* will print the supplied string; otherwise the string is ignored.
*
* Verbose mode can also be enabled using the {@link AbstractTestBase#SYSPROP_VERBOSE} system property.
* @param enabled boolean flag
*/
protected final void enableVerbose( boolean enabled ) {
_verbose = enabled;
}
/** Return the verbose mode. */
public final boolean isVerbose() {
return _verbose;
}
/** Calls <code>System.out.println(msg)</code> if in verbose mode. */
public static final void println( Object msg ) {
if ( _verbose ) {
System.out.println(msg);
}
}
/** Calls <code>System.out.print(msg)</code> if in verbose mode. */
public static final void print( Object msg ) {
if ( _verbose ) {
System.out.print(msg);
}
}
/**
* Returns the editor.
* @return IDiagramWorkbenchPart
*/
public IDiagramWorkbenchPart getDiagramWorkbenchPart() {
if (diagramWorkbenchPart == null) {
assertTrue(
"It appears that the diagram needs to be opened for this test. Call openDiagram().", false); //$NON-NLS-1$
}
return diagramWorkbenchPart;
}
/**
* Returns the project.
* @return IProject
*/
public IProject getProject() {
return project;
}
/**
* Sets the diagramFile.
* @param diagramFile The diagramFile to set
*/
protected void setDiagramFile(IFile diagramFile) {
this.diagramFile = diagramFile;
}
/**
* Method getCommandStack.
* @return CommandStack Command stack for the diagram edit domain
*/
public CommandStack getCommandStack() {
return getDiagramEditPart().getDiagramEditDomain().getDiagramCommandStack();
}
/**
* Sets the diagramWorkbenchPart.
* @param diagramWorkbenchPart The editorPart to set
*/
public void setDiagramWorkbenchPart(IDiagramWorkbenchPart diagramWorkbenchPart) {
this.diagramWorkbenchPart = diagramWorkbenchPart;
}
/**
* Sets the project.
* @param project The project to set
*/
protected void setProject(IProject project) {
this.project = project;
}
/**
*
* Setup up the data for a test. It will create the project,diagram and then opent the diagram
* and then create the test shapes and connectors on the diagram for the tests.
*/
public void setup() throws Exception {
createProject();
createDiagram();
createResource();
createDiagramEditPart();
flushEventQueue(); // so that all editor related events are fired
createShapesAndConnectors();
}
/**
* Will delete the project that was used for the test and removed all the resources in it.
*/
public final void tearDown() throws Exception {
if (tempShell != null) {
tempShell.dispose();
tempShell = null;
}
// flushEventQueue();
boolean diagramClosed = false;
Throwable cde = null; // close diagram exception
Throwable pde = null; //project delete exception
try {
try {
diagramClosed = closeDiagram();
}
catch( Throwable cdt ) {
cde = cdt;
}
try {
if (project != null)
project.delete(true, true, null);
}
catch( Throwable pdt ) {
pde = pdt;
}
}
finally {
// erasing all the data
setDiagramWorkbenchPart(null);
// unload resource
if (getResource() != null) {
getResource().unload();
setResource(null);
}
setDiagramFile(null);
setProject(null);
setConnectorView(null);
flushEventQueue();
if ( !diagramClosed ) {
Log.error( TestsPlugin.getDefault(), IStatus.ERROR, "FAILED TO CLOSE DIAGRAM", cde);//$NON-NLS-1$
}
if ( pde != null ) {
Log.error( TestsPlugin.getDefault(), IStatus.ERROR, "FAILED TO DELETE PROJECT", pde);//$NON-NLS-1$
}
}
}
/**
* Returns the connectorView.
* Maybe null if there is no connector view for this test
* @return IConnectorView
*/
public Edge getConnectorView() {
// maybe null if there is no connector view for this test
return connectorView;
}
/**
* Sets the connectorView.
* @param connectorView The connectorView to set
*/
protected void setConnectorView(Edge connectorView) {
this.connectorView = connectorView;
}
/** Clears the diaplay's event queue. */
public void flushEventQueue() {
Display display = Display.getCurrent();
while (display.readAndDispatch()) {
// empty block
}
}
public void openDiagram() throws Exception {
if (getDiagramFile() == null) {
createDiagram();
}
assertTrue("creation of diagram failed", getDiagramFile() != null); //$NON-NLS-1$
IWorkbenchPage page =
PlatformUI.getWorkbench()
.getActiveWorkbenchWindow()
.getActivePage();
IDEEditorUtil.openDiagram(getDiagramFile(), page.getWorkbenchWindow(),
false, new NullProgressMonitor());
setDiagramWorkbenchPart((IDiagramWorkbenchPart)IDE.openEditor(page, getDiagramFile(), true));
setDiagramEditPart(getDiagramWorkbenchPart().getDiagramEditPart());
setDiagram(getDiagramEditPart().getDiagramView());
setResource(getDiagram().eResource());
}
public boolean closeDiagram() {
boolean closed = true;
if (diagramWorkbenchPart != null // only close if it was opened
&& diagramWorkbenchPart instanceof IEditorPart) {
IWorkbenchPage page =
getDiagramWorkbenchPart().getSite().getPage();
closed = page.closeEditor((IEditorPart)getDiagramWorkbenchPart(), false);
setDiagramWorkbenchPart(null);
}
return closed;
}
protected boolean isDirty() {
return ((EditorPart) getDiagramWorkbenchPart()).isDirty();
}
/**
* @param diagram The diagram to set.
*/
public void setDiagram(Diagram diagram) {
this.diagram = diagram;
}
/**
* @param diagramEditPart The diagramEditPart to set.
*/
public void setDiagramEditPart(DiagramEditPart diagramEditPart) {
this.diagramEditPart = diagramEditPart;
}
public Diagram getDiagram() {
return diagram;
}
public DiagramEditPart getDiagramEditPart() {
return diagramEditPart;
}
/**
* Implement to setup the project for the tests.
*/
protected abstract void createProject() throws Exception;
/**
* Implement to create the diagram and the diagram file for which
* the test should run under. Please set the diagramFile variable.
*/
protected abstract void createDiagram() throws Exception;
/**
* Creates the editing domain and resource and adds the diagram to
* that resource.
*/
protected void createResource() {
if (getResource() == null) {
IFile file = getDiagramFile();
if (file != null) {
String filePath = file.getLocation().toOSString();
setResource(getEditingDomain().loadResource(filePath));
} else {
setResource(getEditingDomain()
.createResource("null:/org.eclipse.gmf.tests.runtime.diagram.ui")); //$NON-NLS-1$
}
if (getDiagram() != null) {
AbstractEMFOperation operation = new AbstractEMFOperation(
getEditingDomain(), "AbstractPresentationTestFixture setup") { //$NON-NLS-1$
protected IStatus doExecute(IProgressMonitor monitor,
IAdaptable info)
throws ExecutionException {
getResource().getContents().add(getDiagram());
return Status.OK_STATUS;
};
};
try {
operation.execute(new NullProgressMonitor(), null);
} catch (ExecutionException ie) {
fail("createResource failed: " + ie.getLocalizedMessage()); //$NON-NLS-1$
}
}
}
}
/**
* Creates and sets the diagram editpart using the offscreen rendering
* capabilities.
*/
protected void createDiagramEditPart()
throws Exception
{
if (getDiagramEditPart() == null) {
setDiagramEditPart(OffscreenEditPartFactory.getInstance()
.createDiagramEditPart(getDiagram(), getTempShell()));
}
}
public ShapeEditPart createShapeUsingTool(IElementType elementType,
Point location, IGraphicalEditPart containerEP) {
return createShapeUsingTool(elementType, location, null, containerEP);
}
/**
* Creates a new shape using the request created by the
* <code>CreationTool</code>.
*
* @param elementType
* the type of the shape/element to be created
* @param location
* the location for the new shape
* @return the new shape's editpart
*/
public ShapeEditPart createShapeUsingTool(IElementType elementType,
Point location, Dimension size, IGraphicalEditPart containerEP) {
CreateRequest request = getCreationRequest(elementType);
request.setLocation(location);
if (size != null) {
request.setSize(size);
}
Command cmd = containerEP.getCommand(request);
int previousNumChildren = containerEP.getChildren().size();
getCommandStack().execute(cmd);
assertEquals(previousNumChildren + 1, containerEP.getChildren().size());
Object newView = ((IAdaptable) ((List) request.getNewObject()).get(0)).getAdapter(View.class);
assertNotNull(newView);
assertTrue(!ViewUtil.isTransient((View)newView));
EObject element = ((View)newView).getElement();
getCommandStack().undo();
assertEquals(previousNumChildren, containerEP.getChildren().size());
getCommandStack().redo();
assertEquals(previousNumChildren + 1, containerEP.getChildren().size());
IGraphicalEditPart newShape = null;
if (element != null) {
List children = containerEP.getChildren();
ListIterator li = children.listIterator();
while (li.hasNext()) {
IGraphicalEditPart gep = (IGraphicalEditPart) li.next();
if (gep.getNotationView() != null
&& element.equals(gep.getNotationView().getElement())) {
newShape = gep;
}
}
}
else {
newShape = (ShapeEditPart) getDiagramEditPart()
.getViewer().getEditPartRegistry().get(newView);
assertNotNull(newShape);
}
assertTrue(newShape != null && newShape instanceof ShapeEditPart);
return (ShapeEditPart)newShape;
}
/**
* Given an <code>IElementType</code>, gets the creation request that can be used to
* retrieve the command to creation the element for the type.
*
* @param elementType
* @return
*/
public CreateRequest getCreationRequest(IElementType elementType) {
class CreationTool
extends org.eclipse.gmf.runtime.diagram.ui.tools.CreationTool {
public CreationTool(IElementType theElementType) {
super(theElementType);
}
/** Make public. */
public Request createTargetRequest() {
return super.createTargetRequest();
}
protected PreferencesHint getPreferencesHint() {
return PreferencesHint.USE_DEFAULTS;
}
}
CreationTool tool = new CreationTool(elementType);
CreateRequest request = (CreateRequest) tool.createTargetRequest();
return request;
}
/**
* Creates a new shape using the request created by the
* <code>CreationTool</code>.
*
* @param elementType
* the type of the shape/element to be created
* @param location
* the location for the new shape
* @return the new shape's editpart
*/
public ShapeEditPart createShapeUsingTool(IElementType elementType,
Point location) {
return createShapeUsingTool(elementType, location, getDiagramEditPart());
}
/**
* Creates a new shape using the request created by the
* <code>CreationTool</code>.
*
* @param elementType
* the type of the shape/element to be created
* @param location
* the location for the new shape
* @return the new shape's editpart
*/
public ShapeEditPart createShapeUsingTool(IElementType elementType,
Point location, Dimension size) {
return createShapeUsingTool(elementType, location, size, getDiagramEditPart());
}
/**
* Creates a new connector using the request created by the
* <code>ConnectionCreationTool</code>.
*
* @param sourceEditPart
* the new connector's source
* @param targetEditPart
* the new connector's target
* @param elementType
* the type of the connector/relationship to be created
* @return the new connector's editpart
*/
public ConnectionEditPart createConnectorUsingTool(
final IGraphicalEditPart sourceEditPart,
final IGraphicalEditPart targetEditPart, IElementType elementType) {
class ConnectorCreationTool
extends
org.eclipse.gmf.runtime.diagram.ui.tools.ConnectionCreationTool {
public ConnectorCreationTool(IElementType theElementType) {
super(theElementType);
}
/** Make public. */
public Request createTargetRequest() {
return super.createTargetRequest();
}
protected PreferencesHint getPreferencesHint() {
return PreferencesHint.USE_DEFAULTS;
}
}
ConnectorCreationTool tool = new ConnectorCreationTool(elementType);
CreateConnectionRequest request = (CreateConnectionRequest) tool
.createTargetRequest();
request.setTargetEditPart(sourceEditPart);
request.setType(RequestConstants.REQ_CONNECTION_START);
sourceEditPart.getCommand(request);
request.setSourceEditPart(sourceEditPart);
request.setTargetEditPart(targetEditPart);
request.setType(RequestConstants.REQ_CONNECTION_END);
Command cmd = targetEditPart.getCommand(request);
int previousNumConnectors = getDiagramEditPart().getConnections().size();
getCommandStack().execute(cmd);
assertEquals(previousNumConnectors + 1, getDiagramEditPart()
.getConnections().size());
getCommandStack().undo();
assertEquals(previousNumConnectors, getDiagramEditPart()
.getConnections().size());
getCommandStack().redo();
assertEquals(previousNumConnectors + 1, getDiagramEditPart()
.getConnections().size());
Object newView = ((IAdaptable) request.getNewObject())
.getAdapter(View.class);
assertNotNull(newView);
ConnectionEditPart newConnector = (ConnectionEditPart) getDiagramEditPart()
.getViewer().getEditPartRegistry().get(newView);
assertNotNull(newConnector);
return newConnector;
}
/**
* Implement this to creates the shapes and the connectors for the tests.
* Will set the connect view if there is one needed for the test.
*/
protected abstract void createShapesAndConnectors() throws Exception;
public TransactionalEditingDomain getEditingDomain() {
if (editingDomain == null) {
if (getDiagram() != null) {
editingDomain = TransactionUtil.getEditingDomain(getDiagram());
} else {
editingDomain = DiagramEditingDomainFactory.getInstance()
.createEditingDomain();
}
}
return editingDomain;
}
protected Resource getResource() {
return resource;
}
protected void setResource(Resource resource) {
this.resource = resource;
}
/**
* Lazily creates a new shell.
* @return
*/
private Shell getTempShell() {
if (tempShell == null) {
tempShell = new Shell();
}
return tempShell;
}
}