package org.eclipse.uml2.diagram.sequence.edit.policies; import org.eclipse.draw2d.geometry.Point; import org.eclipse.gef.EditPart; import org.eclipse.gef.EditPolicy; import org.eclipse.gmf.runtime.diagram.ui.editparts.IBorderItemEditPart; import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart; import org.eclipse.gmf.runtime.diagram.ui.editpolicies.BorderItemSelectionEditPolicy; import org.eclipse.gmf.runtime.diagram.ui.editpolicies.ResizableShapeEditPolicy; import org.eclipse.gmf.runtime.diagram.ui.editpolicies.XYLayoutEditPolicy; import org.eclipse.gmf.runtime.notation.Bounds; import org.eclipse.gmf.runtime.notation.Node; import org.eclipse.gmf.runtime.notation.NotationPackage; import org.eclipse.gmf.runtime.notation.View; import org.eclipse.uml2.diagram.sequence.part.UMLVisualIDRegistry; public class SDXYLayoutEditPolicy extends XYLayoutEditPolicy implements OrderedLayoutEditPolicy { @Override protected EditPolicy createChildEditPolicy(EditPart child) { if (child instanceof IBorderItemEditPart) { return new BorderItemSelectionEditPolicy(); } EditPolicy result = super.createChildEditPolicy(child); if (result == null) { return new ResizableShapeEditPolicy(); } return result; } public AnchoredSibling findAnchoredSibling(Point relativeLocation) { AnchoredSibling result = findAnchorAbove(relativeLocation); if (result == null){ result = findAnchorBelow(relativeLocation); } return result; } private AnchoredSibling findAnchorAbove(Point relativeLocation) { View hostView = getHostImpl().getNotationView(); View result = null; int maxFoundPositionBefore = Integer.MIN_VALUE; for (Object next : hostView.getChildren()){ if (false == next instanceof Node){ continue; } Node nextChild = (Node)next; if (!isConsiderableNode(nextChild)){ continue; } if (false == nextChild.getLayoutConstraint() instanceof Bounds){ continue; } Bounds bounds = (Bounds) nextChild.getLayoutConstraint(); if (!bounds.eIsSet(NotationPackage.eINSTANCE.getLocation_Y())){ continue; } if (!bounds.eIsSet(NotationPackage.eINSTANCE.getSize_Height())){ continue; } int nextMaxY = bounds.getY() + bounds.getHeight(); if (nextMaxY > maxFoundPositionBefore && nextMaxY < relativeLocation.y){ maxFoundPositionBefore = nextMaxY; result = nextChild; } } return result == null ? null : new AnchoredSibling(result, false); } private AnchoredSibling findAnchorBelow(Point relativeLocation) { View hostView = getHostImpl().getNotationView(); View result = null; int minFoundPositionAfter = Integer.MAX_VALUE; for (Object next : hostView.getChildren()){ if (false == next instanceof Node){ continue; } Node nextChild = (Node)next; if (!isConsiderableNode(nextChild)){ continue; } if (false == nextChild.getLayoutConstraint() instanceof Bounds){ continue; } Bounds bounds = (Bounds) nextChild.getLayoutConstraint(); if (!bounds.eIsSet(NotationPackage.eINSTANCE.getLocation_Y())){ continue; } if (!bounds.eIsSet(NotationPackage.eINSTANCE.getSize_Height())){ continue; } int nextY = bounds.getY(); if (nextY < minFoundPositionAfter && nextY > relativeLocation.y){ minFoundPositionAfter = nextY; result = nextChild; } } return result == null ? null : new AnchoredSibling(result, true); } private IGraphicalEditPart getHostImpl(){ return (IGraphicalEditPart) getHost(); } private static boolean isConsiderableNode(Node node){ int vid = UMLVisualIDRegistry.getVisualID(node); if (vid == -1){ return false; } if (UMLVisualIDRegistry.isCompartmentVisualID(vid)){ return false; } //XXX: introduce generated method for labels in VIDRegistry if (vid > 5000){ return false; } return true; } }