Преглед изворни кода

#153 Remove dithering connection anchors when resizing

andreas muelder пре 7 година
родитељ
комит
5f4cd3fc8b

+ 2 - 1
plugins/org.yakindu.base.xtext.utils.gmf/META-INF/MANIFEST.MF

@@ -12,7 +12,8 @@ Require-Bundle: org.eclipse.core.runtime,
  org.eclipse.gmf.runtime.diagram.ui.resources.editor.ide,
  org.eclipse.xtext.ui.shared
 Bundle-RequiredExecutionEnvironment: JavaSE-1.8
-Export-Package: org.yakindu.base.xtext.utils.gmf.directedit,
+Export-Package: org.yakindu.base.xtext.utils.gmf.commands,
+ org.yakindu.base.xtext.utils.gmf.directedit,
  org.yakindu.base.xtext.utils.gmf.experimental,
  org.yakindu.base.xtext.utils.gmf.figures,
  org.yakindu.base.xtext.utils.gmf.resource,

+ 127 - 35
plugins/org.yakindu.base.xtext.utils.gmf/src/org/yakindu/base/xtext/utils/gmf/commands/AdjustIdentityAnchorCommand.java

@@ -16,90 +16,182 @@ import org.eclipse.core.commands.ExecutionException;
 import org.eclipse.core.runtime.IAdaptable;
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.draw2d.IFigure;
+import org.eclipse.draw2d.PositionConstants;
 import org.eclipse.draw2d.geometry.Dimension;
+import org.eclipse.draw2d.geometry.Point;
 import org.eclipse.draw2d.geometry.PrecisionPoint;
-import org.eclipse.emf.common.util.EList;
+import org.eclipse.draw2d.geometry.Rectangle;
 import org.eclipse.emf.transaction.TransactionalEditingDomain;
 import org.eclipse.gef.EditPart;
+import org.eclipse.gef.handles.HandleBounds;
 import org.eclipse.gef.requests.ChangeBoundsRequest;
 import org.eclipse.gmf.runtime.common.core.command.CommandResult;
+import org.eclipse.gmf.runtime.diagram.ui.editparts.DiagramRootEditPart;
 import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart;
 import org.eclipse.gmf.runtime.draw2d.ui.figures.BaseSlidableAnchor;
 import org.eclipse.gmf.runtime.emf.commands.core.command.AbstractTransactionalCommand;
+import org.eclipse.gmf.runtime.gef.ui.figures.SlidableAnchor;
 import org.eclipse.gmf.runtime.notation.Anchor;
 import org.eclipse.gmf.runtime.notation.Edge;
 import org.eclipse.gmf.runtime.notation.IdentityAnchor;
+import org.eclipse.gmf.runtime.notation.NotationFactory;
 import org.eclipse.gmf.runtime.notation.View;
 
 /**
- * EXPERIMENTAL !!
  * 
  * Recalculates the {@link IdentityAnchor}s to recalculate connection anchors
  * when a node is resized
  * 
- * @author andreas muelder - Initial contribution and API
+ * Parts are copied from Sirius ShiftEdgeIdentityAnchorOperation
  * 
  */
 public class AdjustIdentityAnchorCommand extends AbstractTransactionalCommand {
 
+	final private static char TERMINAL_START_CHAR = '(';
+	final private static char TERMINAL_DELIMITER_CHAR = ',';
+	final private static char TERMINAL_END_CHAR = ')';
+
+	private final static PrecisionPoint DEFAULT_POINT = new PrecisionPoint(0.5d, 0.5d);
+
 	private ChangeBoundsRequest request;
-	private List<IGraphicalEditPart> editParts;
 
-	@SuppressWarnings("unchecked")
+	private Dimension futureSize;
+
+	private PrecisionPoint delta;
+
 	public AdjustIdentityAnchorCommand(TransactionalEditingDomain domain, ChangeBoundsRequest request) {
 		super(domain, "Adjusting anchors", null);
 		this.request = request;
-		editParts = request.getEditParts();
 
 	}
 
 	@Override
 	protected CommandResult doExecuteWithResult(IProgressMonitor monitor, IAdaptable info) throws ExecutionException {
-		for (EditPart editPart : editParts) {
+		@SuppressWarnings("unchecked")
+		List<IGraphicalEditPart> editParts = request.getEditParts();
+		for (IGraphicalEditPart editPart : editParts) {
 			adjustAnchors(editPart);
 		}
 		return CommandResult.newOKCommandResult();
 	}
 
 	@SuppressWarnings("unchecked")
-	private void adjustAnchors(EditPart editPart) {
+	protected void adjustAnchors(IGraphicalEditPart editPart) {
 		if (editPart instanceof IGraphicalEditPart) {
 			View view = ((IGraphicalEditPart) editPart).getNotationView();
-			EList<Edge> targetEdges = view.getTargetEdges();
+			List<Edge> targetEdges = view.getTargetEdges();
 			for (Edge edge : targetEdges) {
-				Anchor targetAnchor = edge.getTargetAnchor();
-				if (targetAnchor instanceof IdentityAnchor) {
-					PrecisionPoint anchorPoint = BaseSlidableAnchor.parseTerminalString(((IdentityAnchor) targetAnchor)
-							.getId());
-					IFigure figure = ((IGraphicalEditPart) editPart).getFigure();
-					Dimension sizeBefore = figure.getBounds().getSize();
-					float widthFactor = (float) (sizeBefore.width() + request.getSizeDelta().width())
-							/ (float) sizeBefore.width();
-					float heightFactor = (float) (sizeBefore.height() + request.getSizeDelta().height())
-							/ (float) sizeBefore.height();
-					PrecisionPoint newPoint = new PrecisionPoint(anchorPoint.preciseX() / widthFactor,
-							anchorPoint.preciseY() / heightFactor);
-					((IdentityAnchor) targetAnchor).setId(composeTerminalString(newPoint));
-				}
+				handleEdge(edge, editPart, false);
+			}
+			List<Edge> sourceEdges = view.getSourceEdges();
+			for (Edge edge : sourceEdges) {
+				handleEdge(edge, editPart, true);
 			}
 		}
+	}
 
+	private void handleEdge(Edge edge, EditPart editPart, boolean sourceAnchor) {
+		Anchor anchorToModify;
+		if (sourceAnchor) {
+			anchorToModify = edge.getSourceAnchor();
+		} else {
+			anchorToModify = edge.getTargetAnchor();
+		}
+		String terminalString = composeTerminalString(DEFAULT_POINT);
+		if (anchorToModify instanceof IdentityAnchor) {
+			terminalString = ((IdentityAnchor) anchorToModify).getId();
+		}
+		PrecisionPoint anchorPoint = BaseSlidableAnchor.parseTerminalString(terminalString);
+		PrecisionPoint newPoint = computeNewAnchor(anchorPoint, editPart);
+		String newTerminalString = new SlidableAnchor(null, newPoint).getTerminal();
+		if (anchorToModify instanceof IdentityAnchor) {
+			((IdentityAnchor) anchorToModify).setId(newTerminalString);
+		} else if (anchorToModify == null) {
+			// Create a new one
+			IdentityAnchor newAnchor = NotationFactory.eINSTANCE.createIdentityAnchor();
+			newAnchor.setId(newTerminalString);
+			if (sourceAnchor) {
+				edge.setSourceAnchor(newAnchor);
+			} else {
+				edge.setTargetAnchor(newAnchor);
+			}
+		}
 	}
 
-	// Copied from BaseSlideableAnchor
-	final private static char TERMINAL_START_CHAR = '(';
-	final private static char TERMINAL_DELIMITER_CHAR = ',';
-	final private static char TERMINAL_END_CHAR = ')';
+	protected double getScale(EditPart part) {
+		double scale = 1.0;
+		if (part.getRoot() instanceof DiagramRootEditPart) {
+			DiagramRootEditPart rootEditPart = (DiagramRootEditPart) part.getRoot();
+			scale = rootEditPart.getZoomManager().getZoom();
+		}
+		return scale;
+	}
+
+	private PrecisionPoint computeNewAnchor(PrecisionPoint currentAnchorPoint, EditPart editPart) {
+
+		double scale = getScale(editPart);
+		IFigure figure = ((IGraphicalEditPart) editPart).getFigure();
+		Rectangle bounds = figure.getBounds();
+		if (figure instanceof HandleBounds) {
+			bounds = ((HandleBounds) figure).getHandleBounds();
+		}
+
+		Point currentRelativePoint = getAnchorRelativePoint(currentAnchorPoint, bounds);
+
+		if (futureSize != null && delta != null) {
+			// In case of border node, the real location is computed earlier
+			// (according to BorderItemLocator). The corresponding futureSize
+			// and delta are used instead of the request data.
+			return new PrecisionPoint(((double) (currentRelativePoint.x - delta.x)) / futureSize.width,
+					((double) (currentRelativePoint.y - delta.y)) / futureSize.height);
+		} else {
+
+			double logicalWidthDelta = request.getSizeDelta().width / scale;
+			double logicalHeightDelta = request.getSizeDelta().height / scale;
+
+			int direction = request.getResizeDirection();
+
+			double newRelativeX = computeNewXRelativeLocation(direction, currentRelativePoint, logicalWidthDelta);
+			double newRelativeY = computeNewYRelativeLocation(direction, currentRelativePoint, logicalHeightDelta);
+
+			return new PrecisionPoint(newRelativeX / (bounds.width() + logicalWidthDelta),
+					newRelativeY / (bounds.height() + logicalHeightDelta));
+		}
+	}
+
+	protected Point getAnchorRelativePoint(PrecisionPoint currentAnchorPoint, Rectangle bounds) {
+		return new PrecisionPoint(bounds.width() * currentAnchorPoint.preciseX(),
+				bounds.height() * currentAnchorPoint.preciseY());
+	}
+
+	private double computeNewXRelativeLocation(int direction, Point currentRelativePoint, double logicalWidthDelta) {
+
+		if (direction == PositionConstants.NORTH_WEST || direction == PositionConstants.WEST
+				|| direction == PositionConstants.SOUTH_WEST) {
+			return currentRelativePoint.preciseX() + logicalWidthDelta;
+		} else {
+
+			return currentRelativePoint.preciseX();
+		}
+	}
+
+	protected double computeNewYRelativeLocation(int direction, Point currentRelativePoint, double logicalHeightDelta) {
+
+		if (direction == PositionConstants.NORTH_WEST || direction == PositionConstants.NORTH
+				|| direction == PositionConstants.NORTH_EAST) {
+			return currentRelativePoint.preciseY() + logicalHeightDelta;
+		} else {
+			return currentRelativePoint.preciseY();
+		}
+	}
 
 	protected String composeTerminalString(PrecisionPoint p) {
 		StringBuffer s = new StringBuffer(24);
-		s.append(TERMINAL_START_CHAR); // 1 char
-		s.append(p.preciseX()); // 10 chars
-		s.append(TERMINAL_DELIMITER_CHAR); // 1 char
-		s.append(p.preciseY()); // 10 chars
-		s.append(TERMINAL_END_CHAR); // 1 char
-		return s.toString(); // 24 chars max (+1 for safety, i.e. for string
-								// termination)
+		s.append(TERMINAL_START_CHAR);
+		s.append(p.preciseX());
+		s.append(TERMINAL_DELIMITER_CHAR);
+		s.append(p.preciseY());
+		s.append(TERMINAL_END_CHAR);
+		return s.toString();
 	}
-
 }

+ 95 - 78
plugins/org.yakindu.sct.ui.editor/src/org/yakindu/sct/ui/editor/editparts/RegionCompartmentEditPart.java

@@ -1,78 +1,95 @@
-/**
- * Copyright (c) 2010 committers of YAKINDU 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:
- * 	committers of YAKINDU - initial API and implementation
- * 
- */
-package org.yakindu.sct.ui.editor.editparts;
-
-import org.eclipse.draw2d.IFigure;
-import org.eclipse.draw2d.LayoutAnimator;
-import org.eclipse.gef.EditPolicy;
-import org.eclipse.gmf.runtime.diagram.core.preferences.PreferencesHint;
-import org.eclipse.gmf.runtime.diagram.ui.editparts.ShapeCompartmentEditPart;
-import org.eclipse.gmf.runtime.diagram.ui.editpolicies.DragDropEditPolicy;
-import org.eclipse.gmf.runtime.diagram.ui.editpolicies.EditPolicyRoles;
-import org.eclipse.gmf.runtime.diagram.ui.editpolicies.ResizableEditPolicyEx;
-import org.eclipse.gmf.runtime.diagram.ui.editpolicies.XYLayoutEditPolicy;
-import org.eclipse.gmf.runtime.diagram.ui.figures.ResizableCompartmentFigure;
-import org.eclipse.gmf.runtime.diagram.ui.figures.ShapeCompartmentFigure;
-import org.eclipse.gmf.runtime.notation.View;
-import org.yakindu.sct.ui.editor.DiagramActivator;
-import org.yakindu.sct.ui.editor.policies.CompartmentCreationEditPolicy;
-import org.yakindu.sct.ui.editor.policies.RegionCompartmentCanonicalEditPolicy;
-
-/**
- * @author muelder
- * @author muehlbrandt
- */
-public class RegionCompartmentEditPart extends ShapeCompartmentEditPart {
-
-	public RegionCompartmentEditPart(View view) {
-		super(view);
-	}
-
-	@Override
-	protected void createDefaultEditPolicies() {
-		super.createDefaultEditPolicies();
-		installEditPolicy(EditPolicyRoles.CREATION_ROLE, new CompartmentCreationEditPolicy());
-		installEditPolicy(EditPolicyRoles.CANONICAL_ROLE, new RegionCompartmentCanonicalEditPolicy());
-		installEditPolicy(EditPolicyRoles.DRAG_DROP_ROLE, new DragDropEditPolicy());
-		installEditPolicy(EditPolicy.LAYOUT_ROLE, new XYLayoutEditPolicy());
-		// Removes the collapse expand handler
-		installEditPolicy(EditPolicy.PRIMARY_DRAG_ROLE, new ResizableEditPolicyEx());
-		installEditPolicy(EditPolicyRoles.SNAP_FEEDBACK_ROLE, new SimpleSnapFeedbackPolicy());
-	}
-
-	@Override
-	public PreferencesHint getDiagramPreferencesHint() {
-		return DiagramActivator.DIAGRAM_PREFERENCES_HINT;
-	}
-
-	@Override
-	protected IFigure createFigure() {
-		ShapeCompartmentFigure figure = new ShapeCompartmentFigure(getCompartmentName(), getMapMode());
-		figure.getContentPane().setLayoutManager(getLayoutManager());
-		figure.getContentPane().addLayoutListener(LayoutAnimator.getDefault());
-		figure.setBorder(null);
-		figure.setFitContents(true);
-		figure.setToolTip((String) null);
-		return figure;
-	}
-
-	@Override
-	public boolean isSelectable() {
-		return false;
-	}
-
-	@Override
-	protected void refreshVisuals() {
-		super.refreshVisuals();
-		((ResizableCompartmentFigure) getFigure()).getScrollPane().setScrollBarVisibility(
-				org.eclipse.draw2d.ScrollPane.NEVER);
-	}
-}
+/**
+ * Copyright (c) 2010 committers of YAKINDU 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:
+ * 	committers of YAKINDU - initial API and implementation
+ * 
+ */
+package org.yakindu.sct.ui.editor.editparts;
+
+import org.eclipse.draw2d.IFigure;
+import org.eclipse.draw2d.LayoutAnimator;
+import org.eclipse.emf.transaction.util.TransactionUtil;
+import org.eclipse.gef.EditPolicy;
+import org.eclipse.gef.commands.Command;
+import org.eclipse.gef.commands.CompoundCommand;
+import org.eclipse.gef.requests.ChangeBoundsRequest;
+import org.eclipse.gmf.runtime.diagram.core.preferences.PreferencesHint;
+import org.eclipse.gmf.runtime.diagram.ui.commands.ICommandProxy;
+import org.eclipse.gmf.runtime.diagram.ui.editparts.ShapeCompartmentEditPart;
+import org.eclipse.gmf.runtime.diagram.ui.editpolicies.DragDropEditPolicy;
+import org.eclipse.gmf.runtime.diagram.ui.editpolicies.EditPolicyRoles;
+import org.eclipse.gmf.runtime.diagram.ui.editpolicies.ResizableEditPolicyEx;
+import org.eclipse.gmf.runtime.diagram.ui.editpolicies.XYLayoutEditPolicy;
+import org.eclipse.gmf.runtime.diagram.ui.figures.ResizableCompartmentFigure;
+import org.eclipse.gmf.runtime.diagram.ui.figures.ShapeCompartmentFigure;
+import org.eclipse.gmf.runtime.notation.View;
+import org.yakindu.base.xtext.utils.gmf.commands.AdjustIdentityAnchorCommand;
+import org.yakindu.sct.ui.editor.DiagramActivator;
+import org.yakindu.sct.ui.editor.policies.CompartmentCreationEditPolicy;
+import org.yakindu.sct.ui.editor.policies.RegionCompartmentCanonicalEditPolicy;
+
+/**
+ * @author muelder
+ * @author muehlbrandt
+ */
+public class RegionCompartmentEditPart extends ShapeCompartmentEditPart {
+
+	public RegionCompartmentEditPart(View view) {
+		super(view);
+	}
+
+	@Override
+	protected void createDefaultEditPolicies() {
+		super.createDefaultEditPolicies();
+		installEditPolicy(EditPolicyRoles.CREATION_ROLE, new CompartmentCreationEditPolicy());
+		installEditPolicy(EditPolicyRoles.CANONICAL_ROLE, new RegionCompartmentCanonicalEditPolicy());
+		installEditPolicy(EditPolicyRoles.DRAG_DROP_ROLE, new DragDropEditPolicy());
+		installEditPolicy(EditPolicy.LAYOUT_ROLE, new XYLayoutEditPolicy() {
+			@Override
+			protected Command getResizeChildrenCommand(ChangeBoundsRequest request) {
+				//Remove dithering connection anchors 
+				CompoundCommand result = new CompoundCommand();
+				result.add(super.getResizeChildrenCommand(request));
+				AdjustIdentityAnchorCommand command = new AdjustIdentityAnchorCommand(
+						TransactionUtil.getEditingDomain(resolveSemanticElement()), request);
+				result.add(new ICommandProxy(command));
+				return result;
+			}
+		});
+		// Removes the collapse expand handler
+		installEditPolicy(EditPolicy.PRIMARY_DRAG_ROLE, new ResizableEditPolicyEx());
+		installEditPolicy(EditPolicyRoles.SNAP_FEEDBACK_ROLE, new SimpleSnapFeedbackPolicy());
+	}
+
+	@Override
+	public PreferencesHint getDiagramPreferencesHint() {
+		return DiagramActivator.DIAGRAM_PREFERENCES_HINT;
+	}
+
+	@Override
+	protected IFigure createFigure() {
+		ShapeCompartmentFigure figure = new ShapeCompartmentFigure(getCompartmentName(), getMapMode());
+		figure.getContentPane().setLayoutManager(getLayoutManager());
+		figure.getContentPane().addLayoutListener(LayoutAnimator.getDefault());
+		figure.setBorder(null);
+		figure.setFitContents(true);
+		figure.setToolTip((String) null);
+		return figure;
+	}
+
+	@Override
+	public boolean isSelectable() {
+		return false;
+	}
+
+	@Override
+	protected void refreshVisuals() {
+		super.refreshVisuals();
+		((ResizableCompartmentFigure) getFigure()).getScrollPane()
+				.setScrollBarVisibility(org.eclipse.draw2d.ScrollPane.NEVER);
+	}
+}