/******************************************************************************* * Copyright (c) 2011 Red Hat, Inc. * All rights reserved. * This program is 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: * Red Hat, Inc. - initial API and implementation ******************************************************************************/ package org.eclipse.bpmn2.modeler.core.utils; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import org.eclipse.bpmn2.EventDefinition; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.ecore.EObject; import org.eclipse.graphiti.mm.GraphicsAlgorithmContainer; import org.eclipse.graphiti.mm.algorithms.Ellipse; import org.eclipse.graphiti.mm.algorithms.GraphicsAlgorithm; import org.eclipse.graphiti.mm.algorithms.Image; import org.eclipse.graphiti.mm.algorithms.Polygon; import org.eclipse.graphiti.mm.algorithms.Polyline; import org.eclipse.graphiti.mm.algorithms.Rectangle; import org.eclipse.graphiti.mm.algorithms.styles.Point; import org.eclipse.graphiti.mm.pictograms.ContainerShape; import org.eclipse.graphiti.mm.pictograms.PictogramElement; import org.eclipse.graphiti.mm.pictograms.Shape; import org.eclipse.graphiti.services.Graphiti; import org.eclipse.graphiti.services.IGaService; import org.eclipse.graphiti.services.IPeService; public class GraphicsUtil { private static final IGaService gaService = Graphiti.getGaService(); private static final IPeService peService = Graphiti.getPeService(); // TODO move all size properties to separate interface public static int DATA_WIDTH = 36; public static int DATA_HEIGHT = 50; public static class Envelope { public Rectangle rect; public Polyline line; } public static class Asterisk { public Polyline horizontal; public Polyline vertical; public Polyline diagonalDesc; public Polyline diagonalAsc; } public static class Compensation { public Polygon arrow1; public Polygon arrow2; } public static class Cross { public Polyline vertical; public Polyline horizontal; } public static class MultiInstance { public Polyline line1; public Polyline line2; public Polyline line3; } public static class Loop { public Polyline circle; public Polyline arrow; } public static class Expand { public Rectangle rect; public Polyline horizontal; public Polyline vertical; } /* GATEWAY */ private static final String DELETABLE_PROPERTY = "deletable"; public static final int GATEWAY_RADIUS = 25; public static final int GATEWAY_TEXT_AREA = 15; private static final int[] GATEWAY = { 0, GATEWAY_RADIUS, GATEWAY_RADIUS, 0, 2 * GATEWAY_RADIUS, GATEWAY_RADIUS, GATEWAY_RADIUS, 2 * GATEWAY_RADIUS }; public static Polygon createGateway(Shape container) { return gaService.createPolygon(container, GATEWAY); } public static Polygon createGatewayPentagon(ContainerShape container) { Shape pentagonShape = peService.createShape(container, false); Polygon pentagon = gaService.createPolygon(pentagonShape, new int[] { GATEWAY_RADIUS, 18, GATEWAY_RADIUS + 8, GATEWAY_RADIUS - 2, GATEWAY_RADIUS + 5, GATEWAY_RADIUS + 7, GATEWAY_RADIUS - 5, GATEWAY_RADIUS + 7, GATEWAY_RADIUS - 8, GATEWAY_RADIUS - 2 }); peService.setPropertyValue(pentagonShape, DELETABLE_PROPERTY, "true"); return pentagon; } public static Ellipse createGatewayInnerCircle(ContainerShape container) { Shape ellipseShape = peService.createShape(container, false); Ellipse ellipse = gaService.createEllipse(ellipseShape); gaService.setLocationAndSize(ellipse, 14, 14, 23, 23); ellipse.setFilled(false); ellipse.setLineWidth(1); peService.setPropertyValue(ellipseShape, DELETABLE_PROPERTY, "true"); return ellipse; } public static Ellipse createGatewayOuterCircle(ContainerShape container) { Shape ellipseShape = peService.createShape(container, false); Ellipse ellipse = gaService.createEllipse(ellipseShape); gaService.setLocationAndSize(ellipse, 12, 12, 27, 27); ellipse.setFilled(false); ellipse.setLineWidth(1); peService.setPropertyValue(ellipseShape, DELETABLE_PROPERTY, "true"); return ellipse; } public static Cross createGatewayCross(ContainerShape container) { Shape verticalShape = peService.createShape(container, false); Polyline verticalLine = gaService.createPolyline(verticalShape, new int[] { 24, 7, 24, 43 }); verticalLine.setLineWidth(3); peService.setPropertyValue(verticalShape, DELETABLE_PROPERTY, "false"); Shape horizontalShape = peService.createShape(container, false); Polyline horizontalLine = gaService.createPolyline(horizontalShape, new int[] { 7, 24, 43, 24 }); horizontalLine.setLineWidth(3); peService.setPropertyValue(horizontalShape, DELETABLE_PROPERTY, "false"); Cross cross = new Cross(); cross.vertical = verticalLine; cross.horizontal = horizontalLine; return cross; } public static Polygon createEventGatewayParallelCross(ContainerShape container) { Shape crossShape = peService.createShape(container, false); int n1 = 14; int n2 = 22; int n3 = 28; int n4 = 36; Collection<Point> points = new ArrayList<Point>(); points.add(gaService.createPoint(n1, n2)); points.add(gaService.createPoint(n2, n2)); points.add(gaService.createPoint(n2, n1)); points.add(gaService.createPoint(n3, n1)); points.add(gaService.createPoint(n3, n2)); points.add(gaService.createPoint(n4, n2)); points.add(gaService.createPoint(n4, n3)); points.add(gaService.createPoint(n3, n3)); points.add(gaService.createPoint(n3, n4)); points.add(gaService.createPoint(n2, n4)); points.add(gaService.createPoint(n2, n3)); points.add(gaService.createPoint(n1, n3)); Polygon cross = gaService.createPolygon(crossShape, points); cross.setFilled(false); cross.setLineWidth(1); peService.setPropertyValue(crossShape, DELETABLE_PROPERTY, "true"); return cross; } public static Asterisk createGatewayAsterisk(ContainerShape container) { IPeService service = Graphiti.getPeService(); Shape verticalShape = service.createShape(container, false); Polyline vertical = gaService.createPolyline(verticalShape, new int[] { 23, 8, 23, 42 }); vertical.setLineWidth(5); peService.setPropertyValue(verticalShape, DELETABLE_PROPERTY, "true"); Shape horizontalShape = service.createShape(container, false); Polyline horizontal = gaService.createPolyline(horizontalShape, new int[] { 8, 24, 42, 24 }); horizontal.setLineWidth(5); peService.setPropertyValue(horizontalShape, DELETABLE_PROPERTY, "true"); Shape diagonalDescShape = service.createShape(container, false); Polyline diagonalDesc = gaService.createPolyline(diagonalDescShape, new int[] { 13, 14, 37, 37 }); diagonalDesc.setLineWidth(4); peService.setPropertyValue(diagonalDescShape, DELETABLE_PROPERTY, "true"); Shape diagonalAscShape = service.createShape(container, false); Polyline diagonalAsc = gaService.createPolyline(diagonalAscShape, new int[] { 37, 14, 13, 37 }); diagonalAsc.setLineWidth(4); peService.setPropertyValue(diagonalAscShape, DELETABLE_PROPERTY, "true"); Asterisk a = new Asterisk(); a.horizontal = horizontal; a.vertical = vertical; a.diagonalDesc = diagonalDesc; a.diagonalAsc = diagonalAsc; return a; } public static void clearGateway(PictogramElement element) { Iterator<PictogramElement> iterator = peService.getAllContainedPictogramElements(element).iterator(); while (iterator.hasNext()) { PictogramElement childElement = iterator.next(); boolean deletable = Boolean.parseBoolean(peService.getPropertyValue(childElement, DELETABLE_PROPERTY)); if (deletable) { peService.deletePictogramElement(childElement); } } } /* EVENT */ public static final int EVENT_SIZE = 36; public static final int EVENT_TEXT_AREA = 15; public static Ellipse createEventShape(Shape container) { Ellipse ellipse = gaService.createEllipse(container); gaService.setLocationAndSize(ellipse, 0, 0, EVENT_SIZE, EVENT_SIZE); return ellipse; } public static Envelope createEventEnvelope(Shape shape) { return createEnvelope(shape, 9, 9, 18, 18); } public static Polygon createEventPentagon(Shape shape) { int r = EVENT_SIZE / 2; return gaService.createPolygon(shape, new int[] { r, 7, r + 10, r - 4, r + 7, r + 10, r - 7, r + 10, r - 10, r - 4 }); } public static Ellipse createIntermediateEventCircle(Ellipse ellipse) { Ellipse circle = gaService.createEllipse(ellipse); gaService.setLocationAndSize(circle, 4, 4, EVENT_SIZE - 8, EVENT_SIZE - 8); circle.setLineWidth(1); circle.setFilled(false); return circle; } public static Image createEventImage(Shape shape, String imageId) { Image image = gaService.createImage(shape, imageId); gaService.setLocationAndSize(image, 8, 8, 20, 20); return image; } public static Polygon createEventSignal(Shape shape) { Polygon polygon = gaService.createPolygon(shape, new int[] { 16, 4, 28, 26, 7, 26 }); polygon.setLineWidth(1); return polygon; } public static Polygon createEventEscalation(Shape shape) { int r = EVENT_SIZE / 2; int[] points = { r, 8, r + 8, r + 9, r, r + 2, r - 8, r + 9 }; Polygon polygon = gaService.createPolygon(shape, points); polygon.setLineWidth(1); return polygon; } public static Compensation createEventCompensation(Shape shape) { Rectangle rect = gaService.createInvisibleRectangle(shape); int w = 22; int h = 18; gaService.setLocationAndSize(rect, 5, 9, w, h); int _w = w / 2; int _h = h / 2; int[] pontsArrow1 = { _w, 0, _w, h, 0, _h }; Polygon arrow1 = gaService.createPolygon(rect, pontsArrow1); int[] pontsArrow2 = { w, 0, w, h, w / 2, _h }; Polygon arrow2 = gaService.createPolygon(rect, pontsArrow2); Compensation compensation = new Compensation(); compensation.arrow1 = arrow1; compensation.arrow2 = arrow2; return compensation; } public static Polygon createEventLink(Shape shape) { int r = EVENT_SIZE / 2; int[] points = { 32, r, 23, r + 11, 23, r + 6, 5, r + 6, 5, r - 6, 23, r - 6, 23, r - 11 }; Polygon polygon = gaService.createPolygon(shape, points); polygon.setLineWidth(1); return polygon; } public static Polygon createEventError(Shape shape) { int r = EVENT_SIZE / 2; int[] points = { r + 4, r, r + 10, r - 10, r + 7, r + 10, r - 4, r, r - 10, r + 10, r - 7, r - 10 }; Polygon polygon = gaService.createPolygon(shape, points); polygon.setLineWidth(1); return polygon; } public static Polygon createEventCancel(Shape shape) { int r = EVENT_SIZE / 2; int a = 9; int b = 12; int c = 4; int[] points = { r, r - c, r + a, r - b, r + b, r - a, r + c, r, r + b, r + a, r + a, r + b, r, r + c, r - a, r + b, r - b, r + a, r - c, r, r - b, r - a, r - a, r - b }; Polygon polygon = gaService.createPolygon(shape, points); polygon.setLineWidth(1); return polygon; } public static Ellipse createEventTerminate(Shape terminateShape) { Ellipse ellipse = gaService.createEllipse(terminateShape); gaService.setLocationAndSize(ellipse, 6, 6, EVENT_SIZE - 12, EVENT_SIZE - 12); ellipse.setLineWidth(1); ellipse.setFilled(true); return ellipse; } public static Polygon createEventParallelMultiple(Shape shape) { int r = EVENT_SIZE / 2; int a = 3; int b = 11; int[] points = { r - a, r - b, r + a, r - b, r + a, r - a, r + b, r - a, r + b, r + a, r + a, r + a, r + a, r + b, r - a, r + b, r - a, r + a, r - b, r + a, r - b, r - a, r - a, r - a }; Polygon cross = gaService.createPolygon(shape, points); cross.setFilled(false); cross.setLineWidth(1); return cross; } public static boolean clearEvent(ContainerShape shape) { boolean cleared = false; Iterator<PictogramElement> iterator = peService.getAllContainedPictogramElements(shape).iterator(); while (iterator.hasNext()) { PictogramElement element = iterator.next(); if (element.getLink() == null) { continue; } EList<EObject> objects = element.getLink().getBusinessObjects(); if (!objects.isEmpty() && objects.size() > 1) { return false; } if (objects.get(0) != null && objects.get(0) instanceof EventDefinition) { peService.deletePictogramElement(element); cleared = true; } } return cleared; } /* OTHER */ public static Envelope createEnvelope(GraphicsAlgorithmContainer gaContainer, int x, int y, int w, int h) { Rectangle rect = gaService.createRectangle(gaContainer); gaService.setLocationAndSize(rect, x, y, w, h); rect.setFilled(false); Polyline line = gaService.createPolyline(rect, new int[] { 0, 0, w / 2, h / 2, w, 0 }); Envelope envelope = new Envelope(); envelope.rect = rect; envelope.line = line; return envelope; } public static Polygon createDataArrow(Polygon p) { int[] points = { 4, 8, 14, 8, 14, 4, 18, 10, 14, 16, 14, 12, 4, 12 }; Polygon arrow = gaService.createPolygon(p, points); arrow.setLineWidth(1); return arrow; } // ACTIVITY public static final int TASK_DEFAULT_WIDTH = 110; public static final int TASK_DEFAULT_HEIGHT = 50; public static final int TASK_IMAGE_SIZE = 16; public static final int SUB_PROCEESS_DEFAULT_WIDTH = 300; public static final int SUB_PROCESS_DEFAULT_HEIGHT = 300; public static final int MARKER_WIDTH = 10; public static final int MARKER_HEIGHT = 10; public static final String ACTIVITY_MARKER_CONTAINER = "activity.marker.container"; public static final String ACTIVITY_MARKER_COMPENSATE = "activity.marker.compensate"; public static final String ACTIVITY_MARKER_LOOP_CHARACTERISTIC = "activity.marker.loop.characteristic"; public static final String ACTIVITY_MARKER_AD_HOC = "activity.marker.adhoc"; public static final String ACTIVITY_MARKER_EXPAND = "activity.marker.expand"; public static Compensation createActivityMarkerCompensate(ContainerShape markerContainer) { GraphicsAlgorithmContainer algorithmContainer = createActivityMarkerGaContainer(markerContainer, ACTIVITY_MARKER_COMPENSATE); return createCompensation(algorithmContainer, MARKER_WIDTH, MARKER_HEIGHT); } public static Loop createActivityMarkerStandardLoop(ContainerShape markerContainer) { GraphicsAlgorithmContainer algorithmContainer = createActivityMarkerGaContainer(markerContainer, ACTIVITY_MARKER_LOOP_CHARACTERISTIC); int[] xy = { 8, 10, 10, 5, 5, 0, 0, 5, 3, 10 }; int[] bend = { 0, 0, 3, 4, 4, 4, 4, 3, 3, 0 }; Polyline circle = gaService.createPolyline(algorithmContainer, xy, bend); Loop loop = new Loop(); loop.circle = circle; loop.arrow = gaService.createPolyline(algorithmContainer, new int[] { 5, 5, 5, 10, 0, 10 }); return loop; } public static MultiInstance createActivityMarkerMultiParallel(ContainerShape markerContainer) { GraphicsAlgorithmContainer algorithmContainer = createActivityMarkerGaContainer(markerContainer, ACTIVITY_MARKER_LOOP_CHARACTERISTIC); MultiInstance multiInstance = new MultiInstance(); multiInstance.line1 = gaService.createPolyline(algorithmContainer, new int[] { 2, 0, 2, MARKER_HEIGHT }); multiInstance.line2 = gaService.createPolyline(algorithmContainer, new int[] { 5, 0, 5, MARKER_HEIGHT }); multiInstance.line3 = gaService.createPolyline(algorithmContainer, new int[] { 8, 0, 8, MARKER_HEIGHT }); return multiInstance; } public static MultiInstance createActivityMarkerMultiSequential(ContainerShape markerContainer) { GraphicsAlgorithmContainer algorithmContainer = createActivityMarkerGaContainer(markerContainer, ACTIVITY_MARKER_LOOP_CHARACTERISTIC); MultiInstance multiInstance = new MultiInstance(); multiInstance.line1 = gaService.createPolyline(algorithmContainer, new int[] { 0, 2, MARKER_WIDTH, 2 }); multiInstance.line2 = gaService.createPolyline(algorithmContainer, new int[] { 0, 5, MARKER_WIDTH, 5 }); multiInstance.line3 = gaService.createPolyline(algorithmContainer, new int[] { 0, 8, MARKER_WIDTH, 8 }); return multiInstance; } public static Polyline createActivityMarkerAdHoc(ContainerShape markerContainer) { GraphicsAlgorithmContainer algorithmContainer = createActivityMarkerGaContainer(markerContainer, ACTIVITY_MARKER_AD_HOC); int[] xy = { 0, 8, 3, 2, 7, 8, 10, 2 }; int[] bend = { 0, 3, 3, 3, 3, 3, 3, 0 }; return gaService.createPolyline(algorithmContainer, xy, bend); } public static Expand createActivityMarkerExpand(ContainerShape markerContainer) { GraphicsAlgorithmContainer algorithmContainer = createActivityMarkerGaContainer(markerContainer, ACTIVITY_MARKER_EXPAND); Rectangle rect = gaService.createRectangle(algorithmContainer); rect.setFilled(false); gaService.setLocationAndSize(rect, 0, 0, 10, 10); Expand expand = new Expand(); expand.rect = rect; expand.horizontal = gaService.createPolyline(algorithmContainer, new int[] { 0, 5, 10, 5 }); expand.vertical = gaService.createPolyline(algorithmContainer, new int[] { 5, 0, 5, 10 }); return expand; } public static void clearActivityMarker(ContainerShape markerContainer, String property) { int totalWidth = 0; int parentW = ((ContainerShape) markerContainer.eContainer()).getGraphicsAlgorithm().getWidth(); int lastX = -1; Iterator<Shape> iterator = peService.getAllContainedShapes(markerContainer).iterator(); while (iterator.hasNext()) { Shape shape = iterator.next(); String value = peService.getPropertyValue(shape, property); GraphicsAlgorithm ga = shape.getGraphicsAlgorithm(); if (value != null && new Boolean(value)) { lastX = ga.getX(); peService.deletePictogramElement(shape); } else { totalWidth += ga.getWidth(); if (lastX != -1) { gaService.setLocation(ga, lastX, ga.getY(), true); lastX = ga.getX() + ga.getWidth(); } } } totalWidth = totalWidth == 0 ? 10 : totalWidth; GraphicsAlgorithm ga = markerContainer.getGraphicsAlgorithm(); gaService.setLocationAndSize(ga, (parentW / 2) - (totalWidth / 2), ga.getY(), totalWidth, MARKER_HEIGHT); } private static GraphicsAlgorithmContainer createActivityMarkerGaContainer(ContainerShape markerContainer, String property) { GraphicsAlgorithm ga = markerContainer.getGraphicsAlgorithm(); int totalWidth = MARKER_WIDTH; int parentW = ((ContainerShape) markerContainer.eContainer()).getGraphicsAlgorithm().getWidth(); int lastX = 0; Iterator<Shape> iterator = peService.getAllContainedShapes(markerContainer).iterator(); while (iterator.hasNext()) { Shape containedShape = (Shape) iterator.next(); GraphicsAlgorithm containedGa = containedShape.getGraphicsAlgorithm(); totalWidth += containedGa.getWidth(); lastX = containedGa.getX() + containedGa.getWidth(); } gaService.setLocationAndSize(ga, (parentW / 2) - (totalWidth / 2), ga.getY(), totalWidth, MARKER_HEIGHT); Shape shape = peService.createShape(markerContainer, false); peService.setPropertyValue(shape, property, Boolean.toString(true)); Rectangle invisibleRect = gaService.createInvisibleRectangle(shape); gaService.setLocationAndSize(invisibleRect, lastX, 0, MARKER_WIDTH, MARKER_HEIGHT); return invisibleRect; } private static Compensation createCompensation(GraphicsAlgorithmContainer container, int w, int h) { int[] xy = { 0, h / 2, w / 2, 0, w / 2, h }; Polygon arrow1 = gaService.createPolygon(container, xy); arrow1.setFilled(false); xy = new int[] { w / 2, h / 2, w, 0, w, h }; Polygon arrow2 = gaService.createPolygon(container, xy); arrow2.setFilled(false); Compensation compensation = new Compensation(); compensation.arrow1 = arrow1; compensation.arrow2 = arrow2; return compensation; } }