/******************************************************************************* * <copyright> * * Copyright (c) 2005, 2011 SAP AG. * 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: * SAP AG - initial API, implementation and documentation * mgorning - Bug 355968 - Only ChopboxAnchors should compute the reference point as the center of its GA * * </copyright> * *******************************************************************************/ package org.eclipse.graphiti.ui.internal.util.draw2d; import org.eclipse.draw2d.ChopboxAnchor; import org.eclipse.draw2d.IFigure; import org.eclipse.draw2d.geometry.Point; import org.eclipse.draw2d.geometry.Rectangle; import org.eclipse.graphiti.mm.pictograms.AdvancedAnchor; import org.eclipse.graphiti.ui.internal.services.impl.GefService; /** * The purpose of this class is to fix bugs in the {@link ChopboxAnchor} by * overwriting the erroneous methods. * * @noinstantiate This class is not intended to be instantiated by clients. * @noextend This class is not intended to be subclassed by clients. */ public class ChopboxAnchorFixed extends ChopboxAnchor { private AdvancedAnchor advancedAnchor = null; public ChopboxAnchorFixed(IFigure figure, AdvancedAnchor advancedAnchor) { super(figure); this.advancedAnchor = advancedAnchor; } /** * CHANGED: if the reference is in the center of the figure, the result was * not correct. This method has to be kept in sync with * {@link GefService#getChopboxLocationOnBox(Point, Rectangle)}. */ @Override public Point getLocation(Point reference) { if (getAdvancedAnchor() != null && getAdvancedAnchor().isUseAnchorLocationAsConnectionEndpoint()) { Rectangle box = getBox(); Rectangle r = Rectangle.SINGLETON; r.setBounds(box); getOwner().translateToAbsolute(r); // consider zoom etc. Point point = new Point(r.x(), r.y()); return point; } Rectangle r = Rectangle.SINGLETON; r.setBounds(getBox()); r.translate(-1, -1); r.resize(1, 1); getOwner().translateToAbsolute(r); float centerX = r.x + 0.5f * r.width; float centerY = r.y + 0.5f * r.height; // CHANGED: returning the center in case of a divide-by-zero is not a // good result // if (r.isEmpty() || (reference.x == (int)centerX && reference.y == // (int)centerY)) // return new Point((int)centerX, (int)centerY); //This avoids // divide-by-zero float dx = reference.x - centerX; float dy = reference.y - centerY; // r.width, r.height, dx, and dy are guaranteed to be non-zero. // CHANGED: in case of "nearly zero" (divide-by-zero or // rounding-problems) would happen. // Instead return a point on the border of the figure. // Doesn't matter which one, because it is directly in the center, so // take top-middle. float max = Math.max(Math.abs(dx) / r.width, Math.abs(dy) / r.height); if (max <= 0.001f) { return new Point((int) centerX, r.y); } float scale = 0.5f / max; dx *= scale; dy *= scale; centerX += dx; centerY += dy; return new Point(Math.round(centerX), Math.round(centerY)); } protected AdvancedAnchor getAdvancedAnchor() { return this.advancedAnchor; } }