/****************************************************************************** * Copyright (c) 2004, 2005 IBM Corporation 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: * IBM Corporation - initial API and implementation ****************************************************************************/ package org.eclipse.gmf.runtime.diagram.ui.editpolicies; import org.eclipse.draw2d.FigureListener; import org.eclipse.draw2d.Graphics; import org.eclipse.draw2d.IFigure; import org.eclipse.draw2d.Polyline; import org.eclipse.draw2d.geometry.Point; import org.eclipse.draw2d.geometry.PointList; import org.eclipse.draw2d.geometry.Rectangle; import org.eclipse.gef.editparts.AbstractConnectionEditPart; import org.eclipse.gef.editparts.AbstractGraphicalEditPart; import org.eclipse.gmf.runtime.diagram.ui.editparts.GraphicalEditPart; import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart; import org.eclipse.gmf.runtime.draw2d.ui.figures.PolylineConnectionEx; import org.eclipse.gmf.runtime.draw2d.ui.geometry.PointListUtilities; import org.eclipse.gmf.runtime.gef.ui.internal.editpolicies.GraphicalEditPolicyEx; /** * An EditPolicy that tethers a shape to the connection to which it * applies. The default style for the tether is <code>Graphics.LINE_DASH</code> * * @author jcorchis */ public class TetherConnectionEditPolicy extends GraphicalEditPolicyEx { private Polyline tether; private OwnerMovedListener ownerMovedListener = new OwnerMovedListener(); /** * Returns the tether figure which is a <code>Polyline</code> with the * given style. * * @return the <code>Polyline</code> * @since 1.2 */ public Polyline getConnection() { if (tether == null) { tether = new PolylineConnectionEx(); tether.setLineStyle(Graphics.LINE_DASH); } return tether; } /** * Listens to the owner figure being moved so the tether position can be * updated when this occurs. */ private class OwnerMovedListener implements FigureListener { /** * @see org.eclipse.draw2d.FigureListener#figureMoved(org.eclipse.draw2d.IFigure) */ public void figureMoved(IFigure source) { refresh(); } } /** * Adds the tether upon activation */ public void activate() { super.activate(); addConnection(); ((IGraphicalEditPart) getHost()).getFigure().addFigureListener( ownerMovedListener); } /** * Removes the tether upon deactivation. */ public void deactivate() { ((IGraphicalEditPart) getHost()).getFigure().removeFigureListener( ownerMovedListener); removeConnection(); super.deactivate(); } /** * Removes the tether from the label. */ private void removeConnection() { if (getParentFigure().getChildren().contains(getConnection())) getParentFigure().remove(getConnection()); } /** * Adds the tether * */ private void addConnection() { if (!getParentFigure().getChildren().contains(getConnection())) getParentFigure().add(getConnection()); } /** * Updates the end-points of the tether based on the figure's position. */ public void refresh() { IFigure figure = ((GraphicalEditPart) getHost()).getFigure(); Rectangle r = figure.getBounds().getCopy(); PointList pl = new PointList(); Point refPoint = new Point(); if (getHost().getParent() instanceof AbstractConnectionEditPart) { AbstractConnectionEditPart connectionClassEP = (AbstractConnectionEditPart) getHost() .getParent(); pl = connectionClassEP.getConnectionFigure().getPoints(); refPoint = PointListUtilities.calculatePointRelativeToLine(pl, 0, 50, true); } else { refPoint = ((AbstractGraphicalEditPart)getHost().getParent()).getFigure().getBounds().getLocation(); } Point midTop = new Point(r.x + r.width / 2, r.y); Point midBottom = new Point(r.x + r.width / 2, r.y + r.height); Point midLeft = new Point(r.x, r.y + r.height / 2); Point midRight = new Point(r.x + r.width, r.y + r.height / 2); Point startPoint = midTop; int x = r.x + r.width / 2 - refPoint.x; int y = r.y + r.height / 2 - refPoint.y; if (y > 0 && y > x && y > -x) startPoint = midTop; else if (y < 0 && y < x && y < -x) startPoint = midBottom; else if (x < 0 && y > x && y < -x) startPoint = midRight; else startPoint = midLeft; getConnection().setStart(startPoint); getConnection().setEnd(refPoint); getConnection().setForegroundColor( ((AbstractGraphicalEditPart) getHost().getParent()).getFigure() .getForegroundColor()); } /** * Returns the layer that the tether will be added. * * @return the layer that the tether will be added */ private IFigure getParentFigure() { return getHostFigure().getParent(); } }