package org.eclipse.uml2.diagram.sequence.edit.policies; import java.util.LinkedList; import java.util.List; import org.eclipse.draw2d.ColorConstants; import org.eclipse.draw2d.Cursors; import org.eclipse.draw2d.FigureUtilities; import org.eclipse.draw2d.Graphics; import org.eclipse.draw2d.IFigure; import org.eclipse.draw2d.Polygon; import org.eclipse.draw2d.PositionConstants; import org.eclipse.draw2d.geometry.Point; import org.eclipse.draw2d.geometry.PointList; import org.eclipse.draw2d.geometry.PrecisionRectangle; import org.eclipse.draw2d.geometry.Rectangle; import org.eclipse.gef.Request; import org.eclipse.gef.handles.RelativeHandleLocator; import org.eclipse.gef.handles.ResizableHandleKit; import org.eclipse.gef.handles.ResizeHandle; import org.eclipse.gef.requests.ChangeBoundsRequest; import org.eclipse.gmf.runtime.diagram.ui.editparts.GraphicalEditPart; import org.eclipse.swt.graphics.Image; import org.eclipse.uml2.diagram.sequence.part.UMLDiagramEditorPlugin; public class TieFrameEditPolicy extends SDResizableShapeEditPolicy { @Override protected List<?> createSelectionHandles() { setResizeDirections(PositionConstants.NSEW); List<Object> result = new LinkedList<Object>(); addResizeCornerHandles((GraphicalEditPart)getHost(), result); return result; } private void addResizeCornerHandles(GraphicalEditPart part, List<Object> output) { ResizableHandleKit.addMoveHandle((GraphicalEditPart)getHost(), output); output.add(createExpandFrameHandle(part, PositionConstants.EAST)); ResizableHandleKit.addHandle(part, output, PositionConstants.EAST); ResizableHandleKit.addHandle(part, output, PositionConstants.SOUTH_EAST); ResizableHandleKit.addHandle(part, output, PositionConstants.SOUTH); ResizableHandleKit.addHandle(part, output, PositionConstants.SOUTH_WEST); output.add(createExpandFrameHandle(part, PositionConstants.WEST)); ResizableHandleKit.addHandle(part, output, PositionConstants.WEST); ResizableHandleKit.addHandle(part, output, PositionConstants.NORTH_WEST); ResizableHandleKit.addHandle(part, output, PositionConstants.NORTH); ResizableHandleKit.addHandle(part, output, PositionConstants.NORTH_EAST); } @Override protected IFigure createDragSourceFeedbackFigure() { Rectangle bounds = getInitialFeedbackBounds(); StretchHorizontallyRectangle feedback = new StretchHorizontallyRectangle(bounds); FigureUtilities.makeGhostShape(feedback); feedback.setLineStyle(Graphics.LINE_DOT); feedback.setForegroundColor(ColorConstants.white); addFeedback(feedback); return feedback; } protected void showChangeBoundsFeedback(ChangeBoundsRequest request) { if (request instanceof TieFrameRequest) { StretchHorizontallyRectangle feedback = (StretchHorizontallyRectangle) getDragSourceFeedbackFigure(); PrecisionRectangle rect = new PrecisionRectangle(getInitialFeedbackBounds().getCopy()); getHostFigure().translateToAbsolute(rect); feedback.translateToRelative(rect); feedback.setBounds(rect); Point location = request.getLocation().getCopy(); feedback.translateToRelative(location); switch (request.getResizeDirection()) { case PositionConstants.WEST : feedback.setLeftCorner(location); break; case PositionConstants.EAST : feedback.setRightCorner(location); break; // default : // super.showChangeBoundsFeedback(request); } } else { super.showChangeBoundsFeedback(request); } } public void showSourceFeedback(Request request) { if (request instanceof TieFrameRequest) { showChangeBoundsFeedback((TieFrameRequest)request); } else { super.showSourceFeedback(request); } } public void eraseSourceFeedback(Request request) { if (request instanceof TieFrameRequest) { eraseChangeBoundsFeedback((TieFrameRequest)request); } else { super.eraseSourceFeedback(request); } } @Override public boolean understandsRequest(Request request) { if (request instanceof TieFrameRequest) { return true; } return super.understandsRequest(request); } private ResizeHandle createExpandFrameHandle(GraphicalEditPart owner, int direction) { //ResizeHandle handle = new TieFrameHandle(owner, direction, 3); ResizeHandle handle = new TieFrameImageHandle(owner, direction, 3); handle.setCursor(Cursors.ARROW); handle.setDragTracker(new ExpandFrameDragTracker(owner, direction, handle)); return handle; } static class StretchHorizontallyRectangle extends Polygon { StretchHorizontallyRectangle (Rectangle rectangle) { setBounds(rectangle); } public void setLeftCorner(Point location) { setPoint(location.getTranslated(0, BIT_HEIGHT) , 1); setPoint(location.getTranslated(0, - BIT_HEIGHT) , 2); } public void setRightCorner(Point location) { setPoint(location.getTranslated(0, - BIT_HEIGHT) , 5); setPoint(location.getTranslated(0, BIT_HEIGHT) , 6); } public void setBounds(Rectangle rectangle) { PointList points = new PointList(9); rectangle = rectangle.getResized(-1, -1); points.setSize(9); points.setPoint(rectangle.getBottomLeft(), 0); points.setPoint(rectangle.getTopLeft(), 1); points.setPoint(rectangle.getTopLeft(), 2); points.setPoint(rectangle.getTopLeft(), 3); points.setPoint(rectangle.getTopRight(), 4); points.setPoint(rectangle.getTopRight(), 5); points.setPoint(rectangle.getTopRight(), 6); points.setPoint(rectangle.getBottomRight(), 7); points.setPoint(rectangle.getBottomLeft(), 8); setPoints(points); } static final int BIT_HEIGHT = 5; } private static class TieFrameImageHandle extends ResizeHandle { public TieFrameImageHandle(GraphicalEditPart owner, int direction, int shift) { super(owner, new GdeRelativeHandleLocator(owner.getFigure(), direction, shift), Cursors.getDirectionalCursor(direction)); assert direction == PositionConstants.EAST || direction == PositionConstants.WEST; myResizeDirection = direction; } protected void init() { Rectangle imageBounds = new Rectangle(getHandleImage().getBounds()); imageBounds.expand(imageBounds.width, 0); setPreferredSize( imageBounds.getSize()); } public void paintFigure(Graphics g) { Rectangle r = getBounds().getCopy(); r.shrink(1, 1); final int shiftFactor = (myResizeDirection == PositionConstants.EAST) ? 1 : -1; g.setForegroundColor(getFillColor()); g.setLineWidth(1); g.setLineStyle(Graphics.LINE_DOT); g.drawLine(r.getCenter(), r.getCenter().translate(shiftFactor * r.width/4, 0)); if (myResizeDirection == PositionConstants.EAST) { r.x += r.width/4*3; } g.drawImage(UMLDiagramEditorPlugin.getInstance().getBundledImage("icons/shape-anchor.gif"), r.x , r.y); } private static Image getHandleImage() { return UMLDiagramEditorPlugin.getInstance().getBundledImage("icons/shape-anchor.gif"); } private final int myResizeDirection; } private static class GdeRelativeHandleLocator extends RelativeHandleLocator { protected int myLocation; private int myShift; public GdeRelativeHandleLocator(IFigure reference, int location, int shift) { super(reference, location); myLocation = location; myShift = shift; } public void relocate(IFigure target) { super.relocate(target); target.getBounds().x += getXGuide(myLocation) * myShift; target.getBounds().y += getYGuide(myLocation) * myShift; } private static int getXGuide(int dir) { switch (dir & PositionConstants.EAST_WEST) { case PositionConstants.WEST: return -1; case PositionConstants.EAST: return 1; default: return 0; } } private static int getYGuide(int dir) { switch (dir & PositionConstants.NORTH_SOUTH) { case PositionConstants.NORTH: return -1; case PositionConstants.SOUTH: return 1; default: return 0; } } } }