/******************************************************************************* * Copyright (c) 2006-2012 * Software Technology Group, Dresden University of Technology * DevBoost GmbH, Berlin, Amtsgericht Charlottenburg, HRB 140026 * * 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: * Software Technology Group - TU Dresden, Germany; * DevBoost GmbH - Berlin, Germany * - initial API and implementation ******************************************************************************/ /* * @(#)ElbowLiner.java 1.1 2007-02-09 * * Copyright (c) 1996-2007 by the original authors of JHotDraw * and all its contributors. * All rights reserved. * * The copyright of this software is owned by the authors and * contributors of the JHotDraw project ("the copyright holders"). * You may not use, copy or modify this software, except in * accordance with the license agreement you entered into with * the copyright holders. For details see accompanying license terms. */ package org.jhotdraw.draw; import java.util.*; import java.awt.*; import java.awt.geom.*; import org.jhotdraw.geom.*; import org.jhotdraw.xml.DOMInput; import org.jhotdraw.xml.DOMOutput; import org.jhotdraw.xml.DOMStorable; /** * A Liner that constrains a connection to orthogonal lines. * * @author Werner Randelshofer * @version 1.1 2007-02-09 Added support for connections that connect to * the same Figure on both ends. * <br>1.0 2006-03-28 Created. */ public class ElbowLiner implements Liner, DOMStorable { private double shoulderSize; /** Creates a new instance. */ public ElbowLiner() { this(20); } public ElbowLiner(double slantSize) { this.shoulderSize = slantSize; } public Collection<Handle> createHandles(BezierPath path) { return null; } public void lineout(ConnectionFigure figure) { BezierPath path = ((LineConnectionFigure) figure).getBezierPath(); Connector start = figure.getStartConnector(); Connector end = figure.getEndConnector(); if (start == null || end == null || path == null) { return; } // Special treatment if the connection connects the same figure if (figure.getStartFigure() == figure.getEndFigure()) { // Ensure path has exactly four nodes while (path.size() < 5) { path.add(1, new BezierPath.Node(0,0)); } while (path.size() > 5) { path.remove(1); } Point2D.Double sp = start.findStart(figure); Point2D.Double ep = end.findEnd(figure); Rectangle2D.Double sb = start.getBounds(); Rectangle2D.Double eb = end.getBounds(); int soutcode = sb.outcode(sp); if (soutcode == 0) { soutcode = Geom.outcode(sb, eb); } int eoutcode = eb.outcode(ep); if (eoutcode == 0) { eoutcode = Geom.outcode(sb, eb); } path.get(0).moveTo(sp); path.get(path.size() - 1).moveTo(ep); switch (soutcode) { case Geom.OUT_TOP : eoutcode = Geom.OUT_LEFT; break; case Geom.OUT_RIGHT : eoutcode = Geom.OUT_TOP; break; case Geom.OUT_BOTTOM : eoutcode = Geom.OUT_RIGHT; break; case Geom.OUT_LEFT : eoutcode = Geom.OUT_BOTTOM; break; default : eoutcode = Geom.OUT_TOP; soutcode = Geom.OUT_RIGHT; break; } path.get(1).moveTo(sp.x + shoulderSize, sp.y); if ((soutcode & Geom.OUT_RIGHT) != 0) { path.get(1).moveTo(sp.x + shoulderSize, sp.y); } else if ((soutcode & Geom.OUT_LEFT) != 0) { path.get(1).moveTo(sp.x - shoulderSize, sp.y); } else if ((soutcode & Geom.OUT_BOTTOM) != 0) { path.get(1).moveTo(sp.x, sp.y + shoulderSize); } else { path.get(1).moveTo(sp.x, sp.y - shoulderSize); } if ((eoutcode & Geom.OUT_RIGHT) != 0) { path.get(3).moveTo(ep.x + shoulderSize, ep.y); } else if ((eoutcode & Geom.OUT_LEFT) != 0) { path.get(3).moveTo(ep.x - shoulderSize, ep.y); } else if ((eoutcode & Geom.OUT_BOTTOM) != 0) { path.get(3).moveTo(ep.x, ep.y + shoulderSize); } else { path.get(3).moveTo(ep.x, ep.y - shoulderSize); } switch (soutcode) { case Geom.OUT_RIGHT : path.get(2).moveTo(path.get(1).x[0], path.get(3).y[0]); break; case Geom.OUT_TOP : path.get(2).moveTo(path.get(1).y[0], path.get(3).x[0]); break; case Geom.OUT_LEFT : path.get(2).moveTo(path.get(1).x[0], path.get(3).y[0]); break; case Geom.OUT_BOTTOM : default : path.get(2).moveTo(path.get(1).y[0], path.get(3).x[0]); break; } } else { Point2D.Double sp = start.findStart(figure); Point2D.Double ep = end.findEnd(figure); path.clear(); path.add(new BezierPath.Node(sp.x,sp.y)); if (sp.x == ep.x || sp.y == ep.y) { path.add(new BezierPath.Node(ep.x,ep.y)); } else { Rectangle2D.Double sb = start.getBounds(); sb.x += 5d; sb.y += 5d; sb.width -= 10d; sb.height -= 10d; Rectangle2D.Double eb = end.getBounds(); eb.x += 5d; eb.y += 5d; eb.width -= 10d; eb.height -= 10d; int soutcode = sb.outcode(sp); if (soutcode == 0) { soutcode = Geom.outcode(sb, eb); } int eoutcode = eb.outcode(ep); if (eoutcode == 0) { eoutcode = Geom.outcode(eb, sb); } if ((soutcode & (Geom.OUT_TOP | Geom.OUT_BOTTOM)) != 0 && (eoutcode & (Geom.OUT_TOP | Geom.OUT_BOTTOM)) != 0) { path.add(new BezierPath.Node(sp.x, (sp.y + ep.y)/2)); path.add(new BezierPath.Node(ep.x, (sp.y + ep.y)/2)); } else if ((soutcode & (Geom.OUT_LEFT | Geom.OUT_RIGHT)) != 0 && (eoutcode & (Geom.OUT_LEFT | Geom.OUT_RIGHT)) != 0) { path.add(new BezierPath.Node((sp.x + ep.x)/2, sp.y)); path.add(new BezierPath.Node((sp.x + ep.x)/2, ep.y)); } else if (soutcode == Geom.OUT_BOTTOM && eoutcode == Geom.OUT_LEFT) { path.add(new BezierPath.Node(sp.x, ep.y)); } else { path.add(new BezierPath.Node(ep.x, sp.y)); } path.add(new BezierPath.Node(ep.x,ep.y)); } } // Ensure all path nodes are straight for (BezierPath.Node node : path) { node.setMask(BezierPath.C0_MASK); } path.invalidatePath(); } public void read(DOMInput in) { } public void write(DOMOutput out) { } public Liner clone() { try { return (Liner) super.clone(); } catch (CloneNotSupportedException ex) { InternalError error = new InternalError(ex.getMessage()); error.initCause(ex); throw error; } } }