/* ****************************************************************************** * Copyright (c) 2006-2012 XMind Ltd. and others. * * This file is a part of XMind 3. XMind releases 3 and * above are dual-licensed under the Eclipse Public License (EPL), * which is available at http://www.eclipse.org/legal/epl-v10.html * and the GNU Lesser General Public License (LGPL), * which is available at http://www.gnu.org/licenses/lgpl.html * See http://www.xmind.net/license.html for details. * * Contributors: * XMind Ltd. - initial API and implementation *******************************************************************************/ package org.xmind.ui.internal.fishbone.decorations; import org.eclipse.draw2d.IFigure; import org.xmind.gef.draw2d.IAnchor; import org.xmind.gef.draw2d.geometry.Geometry; import org.xmind.gef.draw2d.geometry.PrecisionLine; import org.xmind.gef.draw2d.geometry.PrecisionPoint; import org.xmind.gef.draw2d.graphics.Path; import org.xmind.ui.decorations.AbstractBranchConnection; import org.xmind.ui.internal.fishbone.structures.ISubDirection; import org.xmind.ui.mindmap.IBranchPart; public class FishboneBranchConnection extends AbstractBranchConnection { private IBranchPart branch; private PrecisionPoint joint = null; public FishboneBranchConnection(IBranchPart branch, String id) { super(id); this.branch = branch; } protected boolean usesFill() { return false; } protected void route(IFigure figure, Path shape) { PrecisionPoint sp = getSourcePosition(figure); PrecisionPoint tp = getTargetPosition(figure); shape.moveTo(sp); if (joint != null) { shape.lineTo(joint); } shape.lineTo(tp); } protected void reroute(IFigure figure, PrecisionPoint sourcePos, PrecisionPoint targetPos, boolean validating) { IAnchor sa = getSourceAnchor(); IAnchor ta = getTargetAnchor(); if (sa != null && ta != null) { PrecisionPoint p1 = sa.getLocation(Geometry .getOppositePosition(getSourceOrientation()), 0); PrecisionPoint p2 = sa.getLocation(getSourceOrientation(), getSourceExpansion()); PrecisionPoint p3 = ta.getLocation(getTargetOrientation(), getTargetExpansion()); PrecisionPoint p4 = ta.getLocation(Geometry .getOppositePosition(getTargetOrientation()), 0); PrecisionPoint j = calcJoint(p1, p2, p3, p4); if (j == null) { if (p3.getDistance2(p2) > p4.getDistance2(p2)) { PrecisionPoint temp = p3; p3 = p4; p4 = temp; } j = calcJoint2(ta.getOwner(), p1, p2, p3, p4); } if (needsSourceLine(ta.getOwner())) { joint = j; sourcePos.setLocation(p2); targetPos.setLocation(calcTarget(ta.getOwner(), p3, p4)); } else { joint = null; sourcePos.setLocation(j); targetPos.setLocation(calcTarget(ta.getOwner(), p3, p4)); } } } private PrecisionPoint calcJoint2(IFigure child, PrecisionPoint p1, PrecisionPoint p2, PrecisionPoint p3, PrecisionPoint p4) { double angle = calcAngle(p1, p2, p3, p4); PrecisionPoint p6 = p3.getMoved(Math.toRadians(angle), 100); PrecisionPoint j = calcJoint(p1, p2, p3, p6); if (j == null) return p3; return j; } private double calcAngle(PrecisionPoint p1, PrecisionPoint p2, PrecisionPoint p3, PrecisionPoint p4) { if (Math.abs(p1.y - p2.y) < 2) { if (p1.x > p2.x) { if (p3.y < p1.y) return ISubDirection.NWR.getRotateAngle(); return ISubDirection.SWR.getRotateAngle(); } if (p3.y < p1.y) return ISubDirection.NER.getRotateAngle(); return ISubDirection.SER.getRotateAngle(); } return 0; } private PrecisionPoint calcJoint(PrecisionPoint p1, PrecisionPoint p2, PrecisionPoint p3, PrecisionPoint p4) { if (isParalell(p1, p2, p3, p4)) return null; PrecisionLine line1 = new PrecisionLine(p1, p2, PrecisionLine.LineType.Line); PrecisionLine line2 = new PrecisionLine(p4, p3, PrecisionLine.LineType.Line); return line1.intersect(line2); } private boolean isParalell(PrecisionPoint p1, PrecisionPoint p2, PrecisionPoint p3, PrecisionPoint p4) { double dx1 = p1.x - p2.x; double dy1 = p1.y - p2.y; double dx2 = p3.x - p4.x; double dy2 = p3.y - p4.y; if (Math.abs(dx1) < 2) return Math.abs(dx2) < 2; if (Math.abs(dy1) < 2) return Math.abs(dy2) < 2; double s1 = dy1 / dx1; double s2 = dy2 / dx2; return Math.abs(s1 / s2 - 1) < 0.01; } private PrecisionPoint calcTarget(IFigure child, PrecisionPoint p3, PrecisionPoint p4) { // if (child != null && child instanceof IDecoratedFigure) { // IDecoration decoration = ((IDecoratedFigure) child).getDecoration(); // if (decoration instanceof FishboneTopicDecoration) // return p4; // } return p3; } private boolean needsSourceLine(IFigure child) { return child == null || !isChild(child, branch.getFigure()); } private boolean isChild(IFigure figure, IFigure branchFigure) { IFigure parent = figure.getParent(); if (parent == branchFigure) return true; if (parent == null || parent == branchFigure.getParent()) return false; return isChild(parent, branchFigure); } public void invalidate() { joint = null; super.invalidate(); } }