blob: c53237bd112d19294270ad41501c840933b89954 [file] [log] [blame]
/**
* <copyright>
*
* Copyright (c) 2012 itemis 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:
* itemis - Initial API and implementation
*
* </copyright>
*/
package org.eclipse.sphinx.examples.hummingbird20.diagram.graphiti.features.add;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.graphiti.features.IFeatureProvider;
import org.eclipse.graphiti.features.context.IAddContext;
import org.eclipse.graphiti.features.impl.AbstractAddShapeFeature;
import org.eclipse.graphiti.mm.algorithms.GraphicsAlgorithm;
import org.eclipse.graphiti.mm.algorithms.Rectangle;
import org.eclipse.graphiti.mm.algorithms.Text;
import org.eclipse.graphiti.mm.algorithms.styles.Orientation;
import org.eclipse.graphiti.mm.pictograms.BoxRelativeAnchor;
import org.eclipse.graphiti.mm.pictograms.ContainerShape;
import org.eclipse.graphiti.mm.pictograms.Diagram;
import org.eclipse.graphiti.mm.pictograms.PictogramElement;
import org.eclipse.graphiti.mm.pictograms.PictogramLink;
import org.eclipse.graphiti.mm.pictograms.Shape;
import org.eclipse.graphiti.services.Graphiti;
import org.eclipse.graphiti.services.IGaService;
import org.eclipse.graphiti.services.IPeCreateService;
import org.eclipse.graphiti.util.ColorConstant;
import org.eclipse.graphiti.util.IColorConstant;
import org.eclipse.sphinx.examples.hummingbird20.typemodel.ComponentType;
import org.eclipse.sphinx.examples.hummingbird20.typemodel.Port;
import org.eclipse.sphinx.examples.hummingbird20.typemodel.TypeModel20Package;
import org.eclipse.sphinx.graphiti.workspace.ui.util.DiagramUtil;
public class AddPortFeature extends AbstractAddShapeFeature {
public static final int PORT_SIZE = 10;
public static final IColorConstant PORT_COLOR_TEXT_FOREGROUND = new ColorConstant(0, 0, 0);
public static final IColorConstant PORT_RECTANGLE_COLOR_FOREGROUND = new ColorConstant(98, 131, 167);
public static final IColorConstant PORT_RECTANGLE_COLOR_BACKGROUND = new ColorConstant(98, 14, 165);
public static final int PORT_CONTAINER_WIDTH_DEFAULT = 60;
public static final int PORT_CONTAINER_HEIGTH_DEFAULT = 20;
public AddPortFeature(IFeatureProvider fp) {
super(fp);
}
@Override
public boolean canAdd(IAddContext context) {
// Is it an add request for a Port ?
if (context.getNewObject() instanceof Port) {
// Is it an add request for adding the a Port to a diagram?
ContainerShape container = context.getTargetContainer();
PictogramLink link = container.getLink();
EList<EObject> bo = link.getBusinessObjects();
if (bo.get(0) instanceof ComponentType) {
return true;
}
// Added to handle extended Drag & Drop features
if (context.getProperty("container") instanceof ComponentType) {
return true;
}
}
return false;
}
@Override
public PictogramElement add(IAddContext context) {
Port portToAdd = (Port) context.getNewObject();
ContainerShape parentContainer = context.getTargetContainer();
PictogramLink link = parentContainer.getLink();
EObject parentBO = null;
PictogramElement newElement = null;
// Does the context come from Drag & Drop ? see: BasicGraphitiObjectTransferDropTargetListener
if (context.getProperty("container") != null) { //$NON-NLS-1$
parentBO = (EObject) context.getProperty("container"); //$NON-NLS-1$
String fragment = EcoreUtil.getURI(portToAdd).fragment();
if (DiagramUtil.getEObject(parentBO, fragment) != null) {
// the object already exist (Drag & Drop)
EList<Shape> children = context.getTargetContainer().getChildren();
for (Shape candidateShape : children) {
if (candidateShape.getLink().getBusinessObjects().get(0) != null) {
EObject candidateObject = candidateShape.getLink().getBusinessObjects().get(0);
if (EcoreUtil.equals(candidateObject, parentBO)) {
// Get eObject2 shape
newElement = createBoundPort((ContainerShape) candidateShape, 0, 0);
link(newElement, context.getNewObject());
break;
}
}
}
}
} else {
// Get the parent Business Object
parentBO = link.getBusinessObjects().get(0);
// Get the reference Id
EReference referenceId = TypeModel20Package.Literals.COMPONENT_TYPE__PORTS;
// Add object to BO resource
DiagramUtil.addObjectToBOResource(parentBO, referenceId, portToAdd);
if (!(context.getTargetContainer() instanceof Diagram)) {
newElement = createBoundPort(context.getTargetContainer(), context.getX(), context.getY());
link(newElement, context.getNewObject());
}
}
return newElement;
}
/**
* Create a port that is bound to an entity's boundary.
*
* @param container
* the container shape of the parent entity
* @param xpos
* the x position
* @param ypos
* the y position
* @return a new pictogram element for the port
*/
private PictogramElement createBoundPort(final ContainerShape container, final int xpos, final int ypos) {
int nodeWidth = container.getGraphicsAlgorithm().getWidth();
int nodeHeight = container.getGraphicsAlgorithm().getHeight();
float widthPercent = (float) (xpos - 2) / nodeWidth;
float heightPercent = (float) (ypos - 2) / nodeHeight;
float deltaY = heightPercent < 1.0f / 2.0f ? heightPercent : 1 - heightPercent;
float deltaX = widthPercent < 1.0f / 2.0f ? widthPercent : 1 - widthPercent;
if (deltaY < deltaX) {
heightPercent = Math.round(heightPercent);
} else {
widthPercent = Math.round(widthPercent);
}
IPeCreateService peCreateService = Graphiti.getPeCreateService();
BoxRelativeAnchor boxAnchor = peCreateService.createBoxRelativeAnchor(container);
boxAnchor.setRelativeWidth(widthPercent);
boxAnchor.setRelativeHeight(heightPercent);
boxAnchor.setActive(true);
IGaService gaService = Graphiti.getGaService();
// look for the actual rectangle that represents the parent entity
for (GraphicsAlgorithm ga : container.getGraphicsAlgorithm().getGraphicsAlgorithmChildren()) {
if (ga instanceof Rectangle) {
boxAnchor.setReferencedGraphicsAlgorithm(ga);
break;
}
}
Rectangle rectangleShape = gaService.createRectangle(boxAnchor);
gaService.setLocationAndSize(rectangleShape, -PORT_SIZE / 2, -PORT_SIZE / 2, PORT_SIZE, PORT_SIZE);
return boxAnchor;
}
/**
* Create a port that is bound to an entity's boundary.
*
* @param container
* the container shape of the parent entity
* @param xpos
* the x position
* @param ypos
* the y position
* @return a new pictogram element for the port
*/
private PictogramElement createBoundPortWithLabel(final ContainerShape container, final int xpos, final int ypos) {
// TODO : validate this method
int nodeWidth = container.getGraphicsAlgorithm().getWidth();
int nodeHeight = container.getGraphicsAlgorithm().getHeight();
float widthPercent = (float) (xpos - 2) / nodeWidth;
float heightPercent = (float) (ypos - 2) / nodeHeight;
float deltaY = heightPercent < 1.0f / 2.0f ? heightPercent : 1 - heightPercent;
float deltaX = widthPercent < 1.0f / 2.0f ? widthPercent : 1 - widthPercent;
if (deltaY < deltaX) {
heightPercent = Math.round(heightPercent);
} else {
widthPercent = Math.round(widthPercent);
}
IPeCreateService peCreateService = Graphiti.getPeCreateService();
BoxRelativeAnchor boxAnchor = peCreateService.createBoxRelativeAnchor(container);
boxAnchor.setRelativeWidth(widthPercent);
boxAnchor.setRelativeHeight(heightPercent);
boxAnchor.setActive(true);
IGaService gaService = Graphiti.getGaService();
// look for the actual rectangle that represents the parent entity
for (GraphicsAlgorithm ga : container.getGraphicsAlgorithm().getGraphicsAlgorithmChildren()) {
if (ga instanceof Rectangle) {
boxAnchor.setReferencedGraphicsAlgorithm(ga);
break;
}
}
// INVISIBLE RECTANGLE
Rectangle invisibleRectangle = gaService.createInvisibleRectangle(boxAnchor);
gaService.setLocationAndSize(invisibleRectangle, -PORT_SIZE / 2, -PORT_SIZE / 2, 6 * PORT_SIZE, PORT_SIZE);
// INTERNAL RECTANGLE
Rectangle internalRectangle = gaService.createRectangle(invisibleRectangle);
internalRectangle.setLineWidth(2);
gaService.setLocationAndSize(internalRectangle, 0, 0, PORT_SIZE, PORT_SIZE);
// TEXT SHAPE
Text text = gaService.createText(invisibleRectangle, "IN#"); //$NON-NLS-1$
gaService.setLocationAndSize(text, 2 * PORT_SIZE, 0, 5 * PORT_SIZE, PORT_SIZE);
text.setHorizontalAlignment(Orientation.ALIGNMENT_LEFT);
text.setFont(gaService.manageDefaultFont(getDiagram(), false, true));
return boxAnchor;
}
}