Commit 26186c40 authored by Eyrak Paen-Rochlitz's avatar Eyrak Paen-Rochlitz
Browse files

[ui.structure] Handle external port/binding positions for update/resize

- minimum resize is restricted to external port locations
- external ports retain their positions along the structure class edge
when resized or updated
- inherited binding bendpoints are updated during resize to keep
positions relative to base class
parent 9baa9ca4
......@@ -34,6 +34,14 @@ import org.eclipse.graphiti.services.IPeService;
public class DiagramUtil {
public static enum Border {
NONE,
TOP,
BOTTOM,
LEFT,
RIGHT
}
public static boolean isSupported(Object obj){
return obj instanceof StructureClass
|| obj instanceof ActorContainerRef
......@@ -75,4 +83,38 @@ public class DiagramUtil {
return null;
}
/**
* Given an element and its container, calculates the nearest border relative to the element's boundaries.
*/
public static Border getNearestBorder(PosAndSize element, PosAndSize container) {
int left = Math.abs(element.getX());
int right = Math.abs(container.getW() - element.getX());
int top = Math.abs(element.getY());
int bottom = Math.abs(container.getH() - element.getY());
int min = left;
Border border = Border.LEFT;
if (right < min) {
border = Border.RIGHT;
min = right;
}
if (top < min) {
border = Border.TOP;
min = top;
}
if (bottom < min) {
border = Border.BOTTOM;
}
return border;
}
/**
* Given an element and its container, calculates the nearest border relative to the element's boundaries.
* Takes the position and size values from the GraphicsAlgorithm objects.
*/
public static Border getNearestBorder(GraphicsAlgorithm element, GraphicsAlgorithm container) {
PosAndSize posContainer = getPosAndSize(container);
PosAndSize pos = getPosAndSize(element);
return getNearestBorder(pos, posContainer);
}
}
......@@ -19,8 +19,6 @@ import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.etrice.core.room.ActorClass;
import org.eclipse.etrice.core.room.InterfaceItem;
import org.eclipse.etrice.core.room.Port;
import org.eclipse.etrice.core.room.RoomPackage;
import org.eclipse.etrice.core.room.StructureClass;
import org.eclipse.etrice.core.room.util.RoomHelpers;
import org.eclipse.etrice.ui.commands.RoomOpeningHelper;
......@@ -29,6 +27,7 @@ import org.eclipse.etrice.ui.common.base.support.BaseToolBehaviorProvider;
import org.eclipse.etrice.ui.common.base.support.CantRemoveFeature;
import org.eclipse.etrice.ui.common.base.support.DeleteWithoutConfirmFeature;
import org.eclipse.etrice.ui.common.commands.ChangeDiagramInputJob;
import org.eclipse.etrice.ui.structure.support.DiagramUtil.Border;
import org.eclipse.graphiti.dt.IDiagramTypeProvider;
import org.eclipse.graphiti.features.IAddFeature;
import org.eclipse.graphiti.features.IDeleteFeature;
......@@ -54,8 +53,11 @@ import org.eclipse.graphiti.features.impl.AbstractLayoutFeature;
import org.eclipse.graphiti.features.impl.DefaultResizeShapeFeature;
import org.eclipse.graphiti.mm.algorithms.GraphicsAlgorithm;
import org.eclipse.graphiti.mm.algorithms.Rectangle;
import org.eclipse.graphiti.mm.algorithms.styles.Point;
import org.eclipse.graphiti.mm.pictograms.Connection;
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.PictogramElement;
import org.eclipse.graphiti.mm.pictograms.Shape;
import org.eclipse.graphiti.platform.IPlatformImageConstants;
......@@ -372,19 +374,37 @@ public class StructureClassSupport {
int xmax = 0;
int ymax = 0;
ContainerShape containerShape = (ContainerShape)context.getShape();
GraphicsAlgorithm containerGa = containerShape.getGraphicsAlgorithm();
if ((containerGa == null) || (containerGa.getGraphicsAlgorithmChildren().size() != 2))
return false;
GraphicsAlgorithm containerVisibleGa = containerGa.getGraphicsAlgorithmChildren().get(0);
StructureClass sc = (StructureClass) getBusinessObjectForPictogramElement(containerShape);
for (Shape childShape : containerShape.getChildren()) {
Object childBo = getBusinessObjectForPictogramElement(childShape);
if (!isInherited(sc, childBo) && isOnInterface(sc, childBo))
continue;
GraphicsAlgorithm ga = childShape.getGraphicsAlgorithm();
int x = ga.getX()+ga.getWidth()-ActorContainerRefSupport.MARGIN;
int y = ga.getY()+ga.getHeight()-ActorContainerRefSupport.MARGIN;
if (x>xmax)
xmax = x;
if (y>ymax)
ymax = y;
if (isOnInterface(sc, childBo)) {
Border border = DiagramUtil.getNearestBorder(ga, containerVisibleGa);
switch (border) {
case TOP:
case BOTTOM:
if (x > xmax) xmax = x;
break;
case LEFT:
case RIGHT:
if (y > ymax) ymax = y;
break;
default:
break;
}
}
else {
if (x>xmax)
xmax = x;
if (y>ymax)
ymax = y;
}
}
if (width>0 && width<xmax)
return false;
......@@ -402,53 +422,49 @@ public class StructureClassSupport {
if (containerShape.getGraphicsAlgorithm()!=null) {
GraphicsAlgorithm containerGa = containerShape.getGraphicsAlgorithm();
if (containerGa.getGraphicsAlgorithmChildren().size()==2) {
// scale interface item coordinates
// we refer to the visible rectangle which defines the border of our structure class
// since the margin is not scaled
GraphicsAlgorithm ga = containerGa.getGraphicsAlgorithmChildren().get(0);
double sx = (context.getWidth()-2*MARGIN)/(double)ga.getWidth();
double sy = (context.getHeight()-2*MARGIN)/(double)ga.getHeight();
GraphicsAlgorithm visibleGa = containerGa.getGraphicsAlgorithmChildren().get(0);
int newX = (context.getWidth()-2*MARGIN);
int newY = (context.getHeight()-2*MARGIN);
for (Shape childShape : containerShape.getChildren()) {
Object childBo = getBusinessObjectForPictogramElement(childShape);
if (!isInherited(sc, childBo) && isOnInterface(sc, childBo)) {
ga = childShape.getGraphicsAlgorithm();
ga.setX((int) (ga.getX()*sx));
ga.setY((int) (ga.getY()*sy));
if (isOnInterface(sc, childBo)) {
GraphicsAlgorithm ga = childShape.getGraphicsAlgorithm();
Border border = DiagramUtil.getNearestBorder(ga, visibleGa);
switch (border) {
case RIGHT:
ga.setX(newX);
break;
case BOTTOM:
ga.setY(newY);
break;
default:
break;
}
}
}
}
}
super.resizeShape(context);
}
private boolean isInherited(StructureClass sc, Object childBo) {
if (EObject.class.isInstance(childBo) && RoomPackage.eINSTANCE.getActorClass().isInstance(sc)) {
RoomHelpers helpers = SupportUtil.getInstance().getRoomHelpers();
ActorClass acOfChild = helpers.getActorClass((EObject)childBo);
ActorClass acLocal = (ActorClass)sc;
if (!acOfChild.equals(acLocal) && helpers.isKindOf(acLocal, acOfChild)) {
return true;
if ((context.getDirection() & IResizeShapeContext.DIRECTION_NORTH_WEST) != 0) {
int offsetX = context.getX() - containerGa.getX();
int offsetY = context.getY() - containerGa.getY();
for (Connection c : getDiagram().getConnections()) {
FreeFormConnection conn = (FreeFormConnection)c;
for (Point bp : conn.getBendpoints()) {
bp.setX(bp.getX()+offsetX);
bp.setY(bp.getY()+offsetY);
}
}
}
}
return false;
super.resizeShape(context);
}
private boolean isOnInterface(StructureClass sc, Object childBo) {
boolean onInterface = false;
if (childBo instanceof InterfaceItem) {
// in general InterfaceItem sit on the interface...
onInterface = true;
// ...with the exception of internal end ports
if (childBo instanceof Port) {
if (sc instanceof ActorClass) {
if (((ActorClass) sc).getInternalPorts().contains(childBo))
onInterface = false;
}
}
}
return onInterface;
RoomHelpers helpers = SupportUtil.getInstance().getRoomHelpers();
return (childBo instanceof InterfaceItem) && (helpers.getInterfaceItems(sc, true).contains(childBo));
}
}
......
......@@ -26,9 +26,12 @@ import org.eclipse.etrice.core.room.ActorContainerRef;
import org.eclipse.etrice.core.room.Binding;
import org.eclipse.etrice.core.room.InterfaceItem;
import org.eclipse.etrice.core.room.LayerConnection;
import org.eclipse.etrice.core.room.Port;
import org.eclipse.etrice.core.room.StructureClass;
import org.eclipse.etrice.ui.structure.DiagramAccess;
import org.eclipse.etrice.ui.structure.support.DiagramUtil;
import org.eclipse.etrice.ui.structure.support.DiagramUtil.Border;
import org.eclipse.etrice.ui.structure.support.SupportUtil;
import org.eclipse.graphiti.mm.algorithms.GraphicsAlgorithm;
import org.eclipse.graphiti.mm.algorithms.Text;
import org.eclipse.graphiti.mm.algorithms.styles.Point;
......@@ -48,8 +51,18 @@ public class SuperDiagramPositionProvider implements IPositionProvider {
PosAndSize posInv;
}
private class ElementPosition {
final PosAndSize pos;
final Border border;
ElementPosition(PosAndSize pos, Border border) {
this.pos = pos;
this.border = border;
}
}
private PosAndSize posInvSuper;
private HashMap<String, PosAndSize> obj2pos;
private HashMap<String, ElementPosition> obj2pos;
private HashMap<String, Pos> obj2text;
private HashMap<String, ArrayList<Pos>> obj2bendpoints;
private Parent parent;
......@@ -57,7 +70,7 @@ public class SuperDiagramPositionProvider implements IPositionProvider {
private SuperDiagramPositionProvider(){ }
public SuperDiagramPositionProvider(StructureClass sc) {
obj2pos = new HashMap<String, PosAndSize>();
obj2pos = new HashMap<String, ElementPosition>();
obj2text = new HashMap<String, Pos>();
obj2bendpoints = new HashMap<String, ArrayList<Pos>>();
......@@ -103,14 +116,38 @@ public class SuperDiagramPositionProvider implements IPositionProvider {
@Override
public PosAndSize getPosition(EObject bo) {
PosAndSize pos = obj2pos.get(getKey(bo));
return pos;
ElementPosition elem = obj2pos.get(getKey(bo));
if (elem == null)
return null;
int x = elem.pos.getX();
int y = elem.pos.getY();
int w = elem.pos.getW();
int h = elem.pos.getH();
switch (elem.border) {
case BOTTOM:
if (parent.posInv.getH() > posInvSuper.getH())
y = elem.pos.getY() + (parent.posInv.getH() - posInvSuper.getH());
break;
case RIGHT:
if (parent.posInv.getW() > posInvSuper.getW())
x = elem.pos.getX()+(parent.posInv.getW() - posInvSuper.getW());
break;
case NONE:
case TOP:
case LEFT:
default:
break;
}
return new PosAndSize(x,y,w,h);
}
@Override
public Pos getConnectionText(EObject obj) {
Pos pos = obj2text.get(getKey(obj));
return pos;
Pos p = obj2text.get(getKey(obj));
int offsetX = parent.posInv.getX() - posInvSuper.getX();
int offsetY = parent.posInv.getY() - posInvSuper.getY();
return new Pos((p.getX() + offsetX), (p.getY() + offsetY));
}
@Override
......@@ -149,8 +186,7 @@ public class SuperDiagramPositionProvider implements IPositionProvider {
if (obj instanceof ActorContainerRef || obj instanceof InterfaceItem) {
PosAndSize objInv = DiagramUtil.getPosAndSize(shape.getGraphicsAlgorithm());
obj2pos.put(getKey(obj), objInv);
Border border = Border.NONE;
// refs interface items
if (obj instanceof ActorContainerRef){
for(Shape child : ((ContainerShape)shape).getChildren()){
......@@ -158,9 +194,17 @@ public class SuperDiagramPositionProvider implements IPositionProvider {
if(!(childBo instanceof InterfaceItem))
continue;
PosAndSize ifInv = DiagramUtil.getPosAndSize(child.getGraphicsAlgorithm());
obj2pos.put(getKey(obj)+getKey(childBo), ifInv);
obj2pos.put(getKey(obj)+getKey(childBo), new ElementPosition(ifInv, Border.NONE));
}
} else if (obj instanceof InterfaceItem) {
if (obj instanceof Port) {
Port p = (Port)obj;
if (!SupportUtil.getInstance().getRoomHelpers().isInternal(p)) {
border = DiagramUtil.getNearestBorder(objInv, posInvSuper);
}
}
}
obj2pos.put(getKey(obj), new ElementPosition(objInv, border));
}
}
......@@ -194,7 +238,7 @@ public class SuperDiagramPositionProvider implements IPositionProvider {
}
}
private String getKey(EObject bo){
// short path
if(bo instanceof StructureClass)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment