/****************************************************************************** * Copyright (c) 2004, 2007 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.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.PrecisionRectangle; import org.eclipse.draw2d.geometry.Rectangle; import org.eclipse.emf.transaction.TransactionalEditingDomain; import org.eclipse.gef.commands.Command; import org.eclipse.gef.editparts.AbstractConnectionEditPart; import org.eclipse.gef.editpolicies.NonResizableEditPolicy; import org.eclipse.gef.requests.ChangeBoundsRequest; import org.eclipse.gmf.runtime.common.core.command.ICommand; import org.eclipse.gmf.runtime.diagram.ui.commands.ICommandProxy; import org.eclipse.gmf.runtime.diagram.ui.commands.SetBoundsCommand; import org.eclipse.gmf.runtime.diagram.ui.editparts.GraphicalEditPart; import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart; import org.eclipse.gmf.runtime.diagram.ui.internal.figures.LabelHelper; import org.eclipse.gmf.runtime.diagram.ui.l10n.DiagramUIMessages; import org.eclipse.gmf.runtime.draw2d.ui.geometry.PointListUtilities; import org.eclipse.gmf.runtime.emf.core.util.EObjectAdapter; import org.eclipse.gmf.runtime.notation.View; /** * Edit policy which supports * * @author jcorchis */ public class ResizableShapeLabelEditPolicy extends ResizableShapeEditPolicy { private Polyline tether = null; /** * Removes the tether from the feedback * * @see NonResizableEditPolicy#eraseChangeBoundsFeedback(ChangeBoundsRequest) */ protected void eraseChangeBoundsFeedback(ChangeBoundsRequest request) { super.eraseChangeBoundsFeedback(request); if (tether != null) removeFeedback(tether); tether = null; } /** * Add the tether to the feedback * * @see NonResizableEditPolicy#createDragSourceFeedbackFigure() */ protected IFigure createDragSourceFeedbackFigure() { IFigure feedback = super.createDragSourceFeedbackFigure(); tether = new Polyline(); tether.setLineStyle(Graphics.LINE_DASHDOT); tether.setForegroundColor(((IGraphicalEditPart) getHost().getParent()) .getFigure().getForegroundColor()); addFeedback(tether); return feedback; } protected Command getMoveCommand(ChangeBoundsRequest request) { Point refPoint = getReferencePoint(); // translate the feedback figure PrecisionRectangle rect = new PrecisionRectangle( getInitialFeedbackBounds().getCopy()); getHostFigure().translateToAbsolute(rect); rect.translate(request.getMoveDelta()); rect.resize(request.getSizeDelta()); getHostFigure().translateToRelative(rect); adjustRect(rect); Point normalPoint = LabelHelper.offsetFromRelativeCoordinate( getHostFigure(), rect, refPoint); TransactionalEditingDomain editingDomain = ((IGraphicalEditPart) getHost()) .getEditingDomain(); ICommand moveCommand = new SetBoundsCommand(editingDomain, DiagramUIMessages.MoveLabelCommand_Label_Location, new EObjectAdapter((View) getHost().getModel()), normalPoint); return new ICommandProxy(moveCommand); } /** * adjust the rectangle used for the move command; the default implementatin * assumes no behavior, clients can override this function to change * this behavior * * @param rect * Rect to adjust */ protected void adjustRect(PrecisionRectangle rect) { // do nothing } protected void showChangeBoundsFeedback(ChangeBoundsRequest request) { super.showChangeBoundsFeedback(request); IFigure p = getDragSourceFeedbackFigure(); Rectangle r = p.getBounds(); Point refPoint = getReferencePoint(); // translate the feedback figure PrecisionRectangle rect = new PrecisionRectangle( getInitialFeedbackBounds().getCopy()); getHostFigure().translateToAbsolute(rect); rect.translate(request.getMoveDelta()); rect.resize(request.getSizeDelta()); p.translateToRelative(rect); p.setBounds(rect); // translate the refPoint PrecisionRectangle ref = new PrecisionRectangle(new Rectangle( refPoint.x, refPoint.y, 0, 0)); getHostFigure().translateToAbsolute(ref); p.translateToRelative(ref); 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; tether.setStart(startPoint); tether.setEnd(ref.getLocation()); } /** * @param request * the resize request * @return the command contribution obtained from the parent */ protected Command getResizeCommand(ChangeBoundsRequest request) { PrecisionRectangle rect = new PrecisionRectangle( getInitialFeedbackBounds().getCopy()); getHostFigure().translateToAbsolute(rect); rect.translate(request.getMoveDelta()); rect.resize(request.getSizeDelta()); getHostFigure().translateToRelative(rect); View shapeView = (View) getHost().getModel(); TransactionalEditingDomain editingDomain = ((IGraphicalEditPart) getHost()) .getEditingDomain(); Point refPoint = getReferencePoint(); Point normalPoint = LabelHelper.offsetFromRelativeCoordinate( getHostFigure(), rect, refPoint); ICommand resizeCommand = new SetBoundsCommand(editingDomain, DiagramUIMessages.SetLocationCommand_Label_Resize, new EObjectAdapter(shapeView), new Rectangle(normalPoint, rect .getSize())); return new ICommandProxy(resizeCommand); } /** * Helper method to calculate the reference point on the middle of the * parent edge or the point given by the location of a node. * * @return the reference point */ private Point getReferencePoint() { if (getHost().getParent() instanceof AbstractConnectionEditPart) { PointList ptList = ((AbstractConnectionEditPart) getHost() .getParent()).getConnectionFigure().getPoints(); return PointListUtilities.calculatePointRelativeToLine(ptList, 0, 50, true); } else { return ((GraphicalEditPart) getHost().getParent()).getFigure() .getBounds().getLocation(); } } }