| /********************************************************************* |
| * Copyright (c) 2005, 2019 SAP SE |
| * |
| * This program and the accompanying materials are made |
| * available under the terms of the Eclipse Public License 2.0 |
| * which is available at https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * Contributors: |
| * SAP SE - initial API, implementation and documentation |
| * Bug 356218 - Added hasDoneChanges updates to update diagram feature and |
| * called features via editor command stack to check it |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| **********************************************************************/ |
| package org.eclipse.graphiti.tests.cases; |
| |
| import static org.easymock.EasyMock.createMock; |
| import static org.easymock.EasyMock.createNiceMock; |
| import static org.easymock.EasyMock.expect; |
| import static org.easymock.EasyMock.isA; |
| import static org.easymock.EasyMock.replay; |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertFalse; |
| import static org.junit.Assert.assertNotNull; |
| import static org.junit.Assert.assertTrue; |
| |
| import org.eclipse.emf.ecore.resource.impl.ResourceImpl; |
| import org.eclipse.graphiti.datatypes.ILocation; |
| import org.eclipse.graphiti.dt.IDiagramTypeProvider; |
| import org.eclipse.graphiti.features.IFeatureProvider; |
| import org.eclipse.graphiti.features.IReason; |
| import org.eclipse.graphiti.features.context.IUpdateContext; |
| import org.eclipse.graphiti.features.context.impl.AddBendpointContext; |
| import org.eclipse.graphiti.features.context.impl.AreaAnchorContext; |
| import org.eclipse.graphiti.features.context.impl.MoveBendpointContext; |
| import org.eclipse.graphiti.features.context.impl.MoveConnectionDecoratorContext; |
| import org.eclipse.graphiti.features.context.impl.MoveShapeContext; |
| import org.eclipse.graphiti.features.context.impl.ReconnectionContext; |
| import org.eclipse.graphiti.features.context.impl.RemoveBendpointContext; |
| import org.eclipse.graphiti.features.context.impl.RemoveContext; |
| import org.eclipse.graphiti.features.context.impl.ResizeShapeContext; |
| import org.eclipse.graphiti.features.context.impl.UpdateContext; |
| import org.eclipse.graphiti.features.impl.AbstractUpdateFeature; |
| import org.eclipse.graphiti.features.impl.DefaultAddBendpointFeature; |
| import org.eclipse.graphiti.features.impl.DefaultMoveAnchorFeature; |
| import org.eclipse.graphiti.features.impl.DefaultMoveBendpointFeature; |
| import org.eclipse.graphiti.features.impl.DefaultMoveConnectionDecoratorFeature; |
| import org.eclipse.graphiti.features.impl.DefaultMoveShapeFeature; |
| import org.eclipse.graphiti.features.impl.DefaultReconnectionFeature; |
| import org.eclipse.graphiti.features.impl.DefaultRemoveBendpointFeature; |
| import org.eclipse.graphiti.features.impl.DefaultRemoveFeature; |
| import org.eclipse.graphiti.features.impl.DefaultResizeShapeFeature; |
| import org.eclipse.graphiti.features.impl.DefaultUpdateDiagramFeature; |
| import org.eclipse.graphiti.features.impl.Reason; |
| import org.eclipse.graphiti.mm.pictograms.BoxRelativeAnchor; |
| import org.eclipse.graphiti.mm.pictograms.ChopboxAnchor; |
| import org.eclipse.graphiti.mm.pictograms.ConnectionDecorator; |
| import org.eclipse.graphiti.mm.pictograms.ContainerShape; |
| import org.eclipse.graphiti.mm.pictograms.Diagram; |
| import org.eclipse.graphiti.mm.pictograms.FreeFormConnection; |
| import org.eclipse.graphiti.mm.pictograms.Shape; |
| import org.eclipse.graphiti.platform.IDiagramBehavior; |
| import org.eclipse.graphiti.platform.IDiagramContainer; |
| import org.eclipse.graphiti.services.Graphiti; |
| import org.eclipse.graphiti.tests.reuse.GFAbstractTestCase; |
| import org.junit.After; |
| import org.junit.AfterClass; |
| import org.junit.Before; |
| import org.junit.BeforeClass; |
| import org.junit.Test; |
| |
| import junit.framework.Assert; |
| |
| public class DefaultFeaturesTest extends GFAbstractTestCase { |
| |
| // Fixture |
| private Diagram d; |
| private Shape s1; |
| private Shape s2; |
| private ChopboxAnchor a1; |
| private BoxRelativeAnchor a2; |
| private ContainerShape s3; |
| private FreeFormConnection c; |
| private ChopboxAnchor a3; |
| |
| private static IFeatureProvider fpMock; |
| |
| // Update feature instance used for DefaultUpdateDiagramFeature tests |
| private static AbstractUpdateFeatureExtension abstractUpdateFeature = new AbstractUpdateFeatureExtension(fpMock); |
| |
| @BeforeClass |
| public static void prepareClass() { |
| fpMock = createNiceMock(IFeatureProvider.class); |
| IDiagramTypeProvider dtpMock = createMock(IDiagramTypeProvider.class); |
| IDiagramBehavior editorBehaviorMock = createNiceMock(IDiagramBehavior.class); |
| IDiagramContainer diagramContainerMock = createNiceMock(IDiagramContainer.class); |
| expect(fpMock.getDiagramTypeProvider()).andReturn(dtpMock).anyTimes(); |
| expect(fpMock.getRemoveFeature(isA(RemoveContext.class))).andReturn(new DefaultRemoveFeature(fpMock)); |
| expect(dtpMock.getDiagramBehavior()).andReturn(editorBehaviorMock).anyTimes(); |
| expect(editorBehaviorMock.getDiagramContainer()).andReturn(diagramContainerMock).anyTimes(); |
| expect(fpMock.getUpdateFeature(isA(UpdateContext.class))).andReturn(abstractUpdateFeature).anyTimes(); |
| replay(fpMock, dtpMock, editorBehaviorMock, diagramContainerMock); |
| } |
| |
| @Before |
| public void initializeTest() { |
| d = Graphiti.getPeCreateService().createDiagram("tutorial", "test", true); |
| assertNotNull(d); |
| s1 = Graphiti.getPeCreateService().createShape(d, true); |
| s1.setGraphicsAlgorithm(Graphiti.getGaCreateService().createRectangle(d)); |
| assertNotNull(s1); |
| s2 = Graphiti.getPeCreateService().createShape(d, true); |
| s2.setGraphicsAlgorithm(Graphiti.getGaCreateService().createRectangle(d)); |
| s2.getGraphicsAlgorithm().setX(20); |
| assertNotNull(s2); |
| c = Graphiti.getPeCreateService().createFreeFormConnection(d); |
| assertNotNull(c); |
| a1 = Graphiti.getPeCreateService().createChopboxAnchor(s1); |
| assertNotNull(a1); |
| a2 = Graphiti.getPeCreateService().createBoxRelativeAnchor(s2); |
| a2.setRelativeHeight(0.5); |
| a2.setRelativeWidth(0.5); |
| a2.setGraphicsAlgorithm(Graphiti.getGaCreateService().createRectangle(d)); |
| assertNotNull(a2); |
| c.setStart(a1); |
| c.setEnd(a2); |
| s3 = Graphiti.getPeCreateService().createContainerShape(d, true); |
| s3.setGraphicsAlgorithm(Graphiti.getGaCreateService().createRectangle(d)); |
| s3.getGraphicsAlgorithm().setX(50); |
| a3 = Graphiti.getPeCreateService().createChopboxAnchor(s3); |
| ResourceImpl resource = new ResourceImpl(); |
| resource.getContents().add(d); |
| |
| } |
| |
| @Test |
| public void move() { |
| ILocation connectionMidpoint = Graphiti.getPeLayoutService().getConnectionMidpoint(c, 0.5); |
| Assert.assertEquals(10, connectionMidpoint.getX()); |
| Assert.assertEquals(0, connectionMidpoint.getY()); |
| |
| // Move while container remains the same |
| DefaultMoveShapeFeature moveFeature = new DefaultMoveShapeFeature(fpMock); |
| MoveShapeContext moveShapeContext = new MoveShapeContext(s1); |
| moveShapeContext.setX(10); |
| moveShapeContext.setY(0); |
| moveShapeContext.setSourceContainer(d); |
| moveShapeContext.setTargetContainer(d); |
| boolean canExecute = moveFeature.canExecute(moveShapeContext); |
| assertTrue(canExecute); |
| moveFeature.execute(moveShapeContext); |
| connectionMidpoint = Graphiti.getPeLayoutService().getConnectionMidpoint(c, 0.5); |
| Assert.assertEquals(15, connectionMidpoint.getX()); |
| Assert.assertEquals(0, connectionMidpoint.getY()); |
| |
| // Move to different target container |
| moveShapeContext.setX(50); |
| moveShapeContext.setY(0); |
| moveShapeContext.setSourceContainer(d); |
| moveShapeContext.setTargetContainer(s3); |
| // canExecute() would fail in default implementation, since source and |
| // target container differ |
| moveFeature.execute(moveShapeContext); |
| assertEquals(50, s1.getGraphicsAlgorithm().getX()); |
| assertEquals(s3, s1.getContainer()); |
| |
| } |
| |
| @Test |
| public void reconnect() { |
| DefaultReconnectionFeature reconnectionFeature = new DefaultReconnectionFeature(fpMock); |
| ReconnectionContext context = new ReconnectionContext(c, a2, a3, null); |
| assertTrue(reconnectionFeature.canExecute(context)); |
| assertTrue(reconnectionFeature.canReconnect(context)); |
| reconnectionFeature.execute(context); |
| assertEquals(a3, c.getEnd()); |
| } |
| |
| @Test |
| public void bendpoints() { |
| { |
| DefaultAddBendpointFeature addBendpointFeature = new DefaultAddBendpointFeature(fpMock); |
| AddBendpointContext context = new AddBendpointContext(c, 10, 0, 0); |
| assertTrue(addBendpointFeature.canExecute(context)); |
| assertTrue(addBendpointFeature.canAddBendpoint(context)); |
| addBendpointFeature.execute(context); |
| assertEquals(1, c.getBendpoints().size()); |
| } |
| |
| { |
| org.eclipse.graphiti.mm.algorithms.styles.Point point = c.getBendpoints().get(0); |
| DefaultMoveBendpointFeature moveBendpointFeature = new DefaultMoveBendpointFeature(fpMock); |
| MoveBendpointContext context = new MoveBendpointContext(point); |
| context.setConnection(c); |
| context.setLocation(10, 5); |
| assertTrue(moveBendpointFeature.canExecute(context)); |
| assertTrue(moveBendpointFeature.canMoveBendpoint(context)); |
| moveBendpointFeature.execute(context); |
| assertEquals(5, c.getBendpoints().get(0).getY()); |
| } |
| |
| { |
| DefaultRemoveBendpointFeature removeBendpointFeature = new DefaultRemoveBendpointFeature(fpMock); |
| RemoveBendpointContext context = new RemoveBendpointContext(c, c.getBendpoints().get(0)); |
| context.setBendpointIndex(0); |
| assertTrue(removeBendpointFeature.canExecute(context)); |
| assertTrue(removeBendpointFeature.canRemoveBendpoint(context)); |
| removeBendpointFeature.execute(context); |
| assertTrue(c.getBendpoints().isEmpty()); |
| } |
| } |
| |
| @Test |
| public void resize() { |
| DefaultResizeShapeFeature feature = new DefaultResizeShapeFeature(fpMock); |
| ResizeShapeContext context = new ResizeShapeContext(s3); |
| context.setSize(5, 5); |
| assertTrue(feature.canExecute(context)); |
| assertTrue(feature.canResizeShape(context)); |
| feature.execute(context); |
| assertEquals(5, s3.getGraphicsAlgorithm().getHeight()); |
| } |
| |
| @Test |
| public void remove() { |
| DefaultRemoveFeature feature = new DefaultRemoveFeature(fpMock); |
| RemoveContext context = new RemoveContext(s1); |
| assertTrue(feature.canExecute(context)); |
| assertTrue(feature.canRemove(context)); |
| feature.execute(context); |
| // Check if Shape got removed |
| assertFalse(d.getChildren().contains(s1)); |
| // Connection should be removed as well, since it is connected to the |
| // shape |
| assertTrue(d.getConnections().isEmpty()); |
| } |
| |
| @Test |
| public void moveAnchor() { |
| DefaultMoveAnchorFeature feature = new DefaultMoveAnchorFeature(fpMock); |
| s2.getGraphicsAlgorithm().setWidth(10); |
| s2.getGraphicsAlgorithm().setHeight(10); |
| AreaAnchorContext context = new AreaAnchorContext(a2); |
| context.setX(1); |
| context.setY(1); |
| assertTrue(feature.canExecute(context)); |
| assertTrue(feature.canMoveAnchor(context)); |
| feature.execute(context); |
| Assert.assertEquals(0.1, a2.getRelativeWidth()); |
| Assert.assertEquals(0.1, a2.getRelativeHeight()); |
| } |
| |
| @Test |
| public void moveConnectionDecorator() { |
| ConnectionDecorator dec = Graphiti.getPeCreateService().createConnectionDecorator(c, true, 0.5, true); |
| Graphiti.getGaCreateService().createDefaultText(d, dec, "TEST"); |
| DefaultMoveConnectionDecoratorFeature feature = new DefaultMoveConnectionDecoratorFeature(fpMock); |
| MoveConnectionDecoratorContext context = new MoveConnectionDecoratorContext(dec, 5, 5, true); |
| assertTrue(feature.canExecute(context)); |
| assertTrue(feature.canMoveConnectionDecorator(context)); |
| feature.execute(context); |
| Assert.assertEquals(dec.getGraphicsAlgorithm().getX(), 5); |
| |
| } |
| |
| @Test |
| public void updateDiagramNoChildren() throws Exception { |
| // Test for Bug 356218 - DefaultUpdateDiagramFeature correctly |
| // implements hasDoneChanges |
| Diagram diagram = Graphiti.getPeCreateService().createDiagram("dummy", "Test", true); |
| DefaultUpdateDiagramFeature feature = new DefaultUpdateDiagramFeature(fpMock); |
| UpdateContext context = new UpdateContext(diagram); |
| assertTrue(feature.canExecute(context)); |
| feature.execute(context); |
| assertFalse(feature.hasDoneChanges()); |
| } |
| |
| @Test |
| public void updateDiagramWithChildrenNegative() throws Exception { |
| // Test for Bug 356218 - DefaultUpdateDiagramFeature correctly |
| // implements hasDoneChanges |
| Diagram diagram = Graphiti.getPeCreateService().createDiagram("dummy", "Test", true); |
| ContainerShape containerShape = Graphiti.getPeCreateService().createContainerShape(diagram, true); |
| ((AbstractUpdateFeatureExtension) (fpMock.getUpdateFeature(new UpdateContext(containerShape)))).hasDoneChanges = false; |
| DefaultUpdateDiagramFeature feature = new DefaultUpdateDiagramFeature(fpMock); |
| UpdateContext context = new UpdateContext(diagram); |
| assertTrue(feature.canExecute(context)); |
| feature.execute(context); |
| assertFalse(feature.hasDoneChanges()); |
| } |
| |
| @Test |
| public void updateDiagramWithChildrenPositive() throws Exception { |
| // Test for Bug 356218 - DefaultUpdateDiagramFeature correctly |
| // implements hasDoneChanges |
| Diagram diagram = Graphiti.getPeCreateService().createDiagram("dummy", "Test", true); |
| ContainerShape containerShape = Graphiti.getPeCreateService().createContainerShape(diagram, true); |
| ((AbstractUpdateFeatureExtension) (fpMock.getUpdateFeature(new UpdateContext(containerShape)))).hasDoneChanges = true; |
| DefaultUpdateDiagramFeature feature = new DefaultUpdateDiagramFeature(fpMock); |
| UpdateContext context = new UpdateContext(diagram); |
| assertTrue(feature.canExecute(context)); |
| feature.execute(context); |
| assertTrue(feature.hasDoneChanges()); |
| } |
| |
| @After |
| public void uninitializeTest() { |
| |
| } |
| |
| @AfterClass |
| public static void afterClass() { |
| fpMock = null; |
| } |
| |
| /** |
| * |
| */ |
| private static final class AbstractUpdateFeatureExtension extends AbstractUpdateFeature { |
| |
| boolean hasDoneChanges = false; |
| |
| private AbstractUpdateFeatureExtension(IFeatureProvider fp) { |
| super(fp); |
| } |
| |
| public IReason updateNeeded(IUpdateContext context) { |
| return Reason.createTrueReason(); |
| } |
| |
| public boolean update(IUpdateContext context) { |
| return true; |
| } |
| |
| public boolean canUpdate(IUpdateContext context) { |
| return true; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see |
| * org.eclipse.graphiti.features.impl.AbstractFeature#hasDoneChanges() |
| */ |
| @Override |
| public boolean hasDoneChanges() { |
| return hasDoneChanges; |
| } |
| } |
| } |