/*****************************************************************************
* Copyright (c) 2009 Atos Origin.
*
*
* 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:
* Atos Origin - Initial API and implementation
*
*****************************************************************************/
package org.eclipse.papyrus.uml.diagram.activity.helper;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.draw2d.AbstractPointListShape;
import org.eclipse.draw2d.Polygon;
import org.eclipse.draw2d.PolylineShape;
import org.eclipse.draw2d.PositionConstants;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.gef.editparts.AbstractGraphicalEditPart;
import org.eclipse.gmf.runtime.draw2d.ui.mapmode.IMapMode;
import org.eclipse.gmf.runtime.notation.Bounds;
import org.eclipse.gmf.runtime.notation.Shape;
/**
* The ActivityFigureDrawer helps drawing representations for activity diagram
* out of a Polyline figure
*/
public class ActivityFigureDrawer {
/**
* The template for drawing a triangle figure
*/
private static final List<Point> TRIANGLE_FIGURE = new ArrayList<Point>(3);
static {
TRIANGLE_FIGURE.add(new Point(0, 5));
TRIANGLE_FIGURE.add(new Point(5, 5));
TRIANGLE_FIGURE.add(new Point(3, 0));
}
/**
* The template size point for translating a pin arrow figure
*/
private static final Point TRIANGLE_FIGURE_SIZE = new Point(5, 5);
/**
* The template for drawing a rake figure
*/
private static final List<Point> RAKE_FIGURE = new ArrayList<Point>(8);
static {
RAKE_FIGURE.add(new Point(0, 10));
RAKE_FIGURE.add(new Point(0, 4));
RAKE_FIGURE.add(new Point(5, 4));
RAKE_FIGURE.add(new Point(5, 0));
RAKE_FIGURE.add(new Point(5, 10));
RAKE_FIGURE.add(new Point(5, 4));
RAKE_FIGURE.add(new Point(10, 4));
RAKE_FIGURE.add(new Point(10, 10));
}
/**
* The template point for translating a rake figure
*/
private static final Point RAKE_FIGURE_TRANSLATION = new Point(-16, -12);
/**
* The template for drawing an pin arrow figure turned right
*/
private static final List<Point> RIGHT_PIN_ARROW_FIGURE = new ArrayList<Point>(8);
static {
RIGHT_PIN_ARROW_FIGURE.add(new Point(4, 2));
RIGHT_PIN_ARROW_FIGURE.add(new Point(7, 4));
RIGHT_PIN_ARROW_FIGURE.add(new Point(1, 4));
RIGHT_PIN_ARROW_FIGURE.add(new Point(7, 4));
RIGHT_PIN_ARROW_FIGURE.add(new Point(4, 6));
}
/**
* The template for drawing a pin arrow figure turned left
*/
private static final List<Point> LEFT_PIN_ARROW_FIGURE = new ArrayList<Point>(8);
static {
LEFT_PIN_ARROW_FIGURE.add(new Point(4, 2));
LEFT_PIN_ARROW_FIGURE.add(new Point(1, 4));
LEFT_PIN_ARROW_FIGURE.add(new Point(7, 4));
LEFT_PIN_ARROW_FIGURE.add(new Point(1, 4));
LEFT_PIN_ARROW_FIGURE.add(new Point(4, 6));
}
/**
* The template for drawing a pin arrow figure turned up
*/
private static final List<Point> UP_PIN_ARROW_FIGURE = new ArrayList<Point>(8);
static {
UP_PIN_ARROW_FIGURE.add(new Point(2, 4));
UP_PIN_ARROW_FIGURE.add(new Point(4, 1));
UP_PIN_ARROW_FIGURE.add(new Point(4, 7));
UP_PIN_ARROW_FIGURE.add(new Point(4, 1));
UP_PIN_ARROW_FIGURE.add(new Point(6, 4));
}
/**
* The template for drawing a pin arrow figure turned down
*/
private static final List<Point> DOWN_PIN_ARROW_FIGURE = new ArrayList<Point>(8);
static {
DOWN_PIN_ARROW_FIGURE.add(new Point(2, 4));
DOWN_PIN_ARROW_FIGURE.add(new Point(4, 7));
DOWN_PIN_ARROW_FIGURE.add(new Point(4, 1));
DOWN_PIN_ARROW_FIGURE.add(new Point(4, 7));
DOWN_PIN_ARROW_FIGURE.add(new Point(6, 4));
}
/**
* The template size point for translating a pin arrow figure
*/
private static final Point PIN_ARROW_FIGURE_SIZE = new Point(8, 8);
/**
* Get the direction opposite to the parameter one
*
* @param direction
* {@link PositionConstants#NORTH}, {@link PositionConstants#EAST}, {@link PositionConstants#SOUTH} or {@link PositionConstants#WEST}
* @return the direction at the opposite or {@link PositionConstants#NONE}
*/
public static int getOppositeDirection(int direction) {
switch(direction) {
case PositionConstants.NORTH:
return PositionConstants.SOUTH;
case PositionConstants.EAST:
return PositionConstants.WEST;
case PositionConstants.SOUTH:
return PositionConstants.NORTH;
case PositionConstants.WEST:
return PositionConstants.EAST;
default:
return PositionConstants.NONE;
}
}
/**
* Draw the triangle or refresh it
*
* @param triangle
* figure which contains the triangle
* @param iMapMode
* the map mode to translate points
* @param parentDimension
* the dimension of the parent
*/
public static void redrawTriangle(Polygon triangle, IMapMode iMapMode, Dimension parentDimension) {
triangle.removeAllPoints();
double xScale = parentDimension.preciseWidth() / TRIANGLE_FIGURE_SIZE.x;
double yScale = parentDimension.preciseHeight() / TRIANGLE_FIGURE_SIZE.y;
for(Point refPoint : TRIANGLE_FIGURE) {
Point translatedPoint = new Point(refPoint).scale(xScale, yScale);
iMapMode.DPtoLP(translatedPoint);
triangle.addPoint(translatedPoint);
}
}
/**
* Draw the rake or refresh it
*
* @param rake
* figure which contains the rake
* @param iMapMode
* the map mode to translate points
* @param parentDimension
* the dimension of the parent
*/
public static void redrawRake(AbstractPointListShape rake, IMapMode iMapMode, Dimension parentDimension) {
rake.removeAllPoints();
Point translationPoint = new Point();
if(!(rake instanceof PolylineShape)) {
// do not translate for PolylineShape since bounds will be adapted
new Point(RAKE_FIGURE_TRANSLATION);
translationPoint.translate(parentDimension);
}
for(Point refPoint : RAKE_FIGURE) {
Point translatedPoint = new Point(refPoint).translate(translationPoint);
iMapMode.DPtoLP(translatedPoint);
rake.addPoint(translatedPoint);
}
if(rake instanceof PolylineShape) {
// adapt bounds for PolylineShape
Point loc = rake.getParent().getBounds().getLocation().getCopy().translate(parentDimension).translate(RAKE_FIGURE_TRANSLATION);
Rectangle b = new Rectangle(loc, new Dimension(-RAKE_FIGURE_TRANSLATION.x, -RAKE_FIGURE_TRANSLATION.y));
((PolylineShape)rake).setBounds(b);
}
}
/**
* Draw the pin arrow or refresh it
*
* @param arrow
* figure which contains the arrow
* @param iMapMode
* the map mode to translate points
* @param parentDimension
* the dimension of the parent
* @param direction
* the direction to which the arrow is directed : {@link PositionConstants#SOUTH}, {@link PositionConstants#NORTH},
* {@link PositionConstants#EAST}, {@link PositionConstants#WEST}
*/
public static void redrawPinArrow(AbstractPointListShape arrow, IMapMode iMapMode, Dimension parentDimension, int direction) {
arrow.removeAllPoints();
List<Point> template;
switch(direction) {
case PositionConstants.NORTH:
template = UP_PIN_ARROW_FIGURE;
break;
case PositionConstants.SOUTH:
template = DOWN_PIN_ARROW_FIGURE;
break;
case PositionConstants.WEST:
template = LEFT_PIN_ARROW_FIGURE;
break;
case PositionConstants.EAST:
default:
template = RIGHT_PIN_ARROW_FIGURE;
break;
}
double xScale = parentDimension.preciseWidth() / PIN_ARROW_FIGURE_SIZE.x;
double yScale = parentDimension.preciseHeight() / PIN_ARROW_FIGURE_SIZE.y;
for(Point refPoint : template) {
Point translatedPoint = new Point(refPoint).scale(xScale, yScale);
iMapMode.DPtoLP(translatedPoint);
arrow.addPoint(translatedPoint);
}
if(arrow instanceof PolylineShape) {
// adapt bounds for PolylineShape
((PolylineShape)arrow).setBounds(arrow.getParent().getBounds());
}
}
/**
* Undraw the polyline figure
*
* @param figure
* figure to undraw
*/
public static void undrawFigure(AbstractPointListShape figure) {
figure.removeAllPoints();
}
/**
* Get the size of the edit part node
*
* @param editPart
* edit part
* @param dimensionChangeEvent
* the change dimension event or null
* @return the node size
*/
public static Dimension getNodeSize(AbstractGraphicalEditPart editPart, Notification dimensionChangeEvent) {
Bounds bounds = null;
// if a bounds change is notified, size may have changed, otherwise, get
// size from model
// shape
if(dimensionChangeEvent != null && dimensionChangeEvent.getNotifier() instanceof Bounds) {
bounds = (Bounds)dimensionChangeEvent.getNotifier();
} else if(editPart.getModel() instanceof Shape) {
Shape shape = (Shape)editPart.getModel();
if(shape.getLayoutConstraint() instanceof Bounds) {
bounds = (Bounds)shape.getLayoutConstraint();
}
}
Dimension size = null;
if(bounds != null) {
size = new Dimension(bounds.getWidth(), bounds.getHeight());
}
if(size == null || size.isEmpty()) {
// recover the exact size from the figure
Dimension preferredSize = editPart.getFigure().getPreferredSize(size.width, size.height);
if(size.width <= 0) {
size.width = preferredSize.width;
}
if(size.height <= 0) {
size.height = preferredSize.height;
}
}
return size;
}
}