package com.horstmann.violet.product.diagram.common.edge; import com.horstmann.violet.product.diagram.abstracts.edge.ShapeEdge; import com.horstmann.violet.product.diagram.property.BentStyleChoiceList; import com.horstmann.violet.product.diagram.property.LineStyleChoiceList; import com.horstmann.violet.product.diagram.property.choiceList.ChoiceList; import com.horstmann.violet.product.diagram.abstracts.Direction; import com.horstmann.violet.product.diagram.abstracts.edge.bentstyle.BentStyle; import java.awt.*; import java.awt.geom.GeneralPath; import java.awt.geom.Line2D; import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; import java.util.*; import java.util.List; /** * An edge that is composed of multiple line segments * * @author Adrian Bobrowski <adrian071993@gmail.com> * @date 21.02.2016 */ public abstract class LineEdge extends ShapeEdge { public LineEdge() { super(); lineStyleChoiceList = new LineStyleChoiceList(); bentStyleChoiceList = new BentStyleChoiceList(); setBentStyle(BentStyle.AUTO); setLineStyle(LineStyleChoiceList.SOLID); } protected LineEdge(LineEdge lineEdge) { this.bentStyleChoiceList = lineEdge.bentStyleChoiceList.clone(); this.lineStyleChoiceList = lineEdge.lineStyleChoiceList.clone(); this.selectedBentStyle = this.bentStyleChoiceList.getSelectedPos(); this.selectedLineStyle = this.lineStyleChoiceList.getSelectedPos(); } @Override protected void beforeReconstruction() { super.beforeReconstruction(); lineStyleChoiceList = new LineStyleChoiceList(); bentStyleChoiceList = new BentStyleChoiceList(); lineStyleChoiceList.setSelectedIndex(selectedLineStyle); bentStyleChoiceList.setSelectedIndex(selectedBentStyle); } @Override public void setTransitionPoints(Point2D[] transitionPoints) { super.setTransitionPoints(transitionPoints); if(null == transitionPoints || 0 == transitionPoints.length) { // setBentStyle(BentStyle.AUTO); } else { setBentStyle(BentStyle.FREE); } } @Override public boolean isTransitionPointsSupported() { return true; } /** * Draws the edge. * * @param graphics the graphics context */ public void draw(Graphics2D graphics) { updateContactPoints(); Color oldColor = graphics.getColor(); Stroke oldStroke = graphics.getStroke(); graphics.setColor(getBorderColor()); graphics.setStroke(getLineStyle()); graphics.draw(getPath()); graphics.setStroke(oldStroke); graphics.setColor(oldColor); } @Override public Shape getShape() { return getPath(); } protected GeneralPath getPath() { GeneralPath path = new GeneralPath(); path.moveTo(contactPoints[0].getX(), contactPoints[0].getY()); for (int i = 1; i < contactPoints.length; ++i) { path.lineTo(contactPoints[i].getX(), contactPoints[i].getY()); } return path; } protected void updateContactPoints() { Line2D connectionPoints = getConnectionPoints(); Point2D startingPoint = connectionPoints.getP1(); Point2D endingPoint = connectionPoints.getP2(); if (getStartNode().equals(getEndNode())) { Rectangle2D nodeBounds = getStartNode().getBounds(); Point2D nodeLocation = getStartNode().getLocationOnGraph(); contactPoints = new Point2D[5]; contactPoints[0] = new Point2D.Double(nodeLocation.getX() + nodeBounds.getWidth(), nodeLocation.getY() + nodeBounds.getHeight()/2); contactPoints[1] = new Point2D.Double(contactPoints[0].getX()+SELF_LOOP_GAP_X, contactPoints[0].getY()); contactPoints[2] = new Point2D.Double(contactPoints[1].getX(), nodeLocation.getY() + nodeBounds.getHeight() + SELF_LOOP_GAP_Y); contactPoints[3] = new Point2D.Double(contactPoints[0].getX()- nodeBounds.getWidth()/2, contactPoints[2].getY()); contactPoints[4] = new Point2D.Double(contactPoints[3].getX(), contactPoints[2].getY()-SELF_LOOP_GAP_Y); } else { List<Point2D> points = new ArrayList<Point2D>(); points.add(startingPoint); points.addAll(Arrays.asList(getTransitionPoints())); points.add(endingPoint); Point2D[] bentStylePointsAsArray = points.toArray(new Point2D[points.size()]); points = getBentStyle().getPath(bentStylePointsAsArray); contactPoints = new Point2D[points.size()]; points.toArray(contactPoints); } } /** * Gets the bentStyle property * * @return the bent style list */ public final ChoiceList getBentStyleChoiceList() { return bentStyleChoiceList; } /** * Sets the bentStyle property * * @param bentStyleChoiceList the bent style list */ public final void setBentStyleChoiceList(ChoiceList bentStyleChoiceList) { this.bentStyleChoiceList = (BentStyleChoiceList)bentStyleChoiceList; this.selectedBentStyle = this.bentStyleChoiceList.getSelectedPos(); } /** * Gets the line style property. * * @return the line style list */ public final ChoiceList getLineStyleChoiceList() { return lineStyleChoiceList; } /** * Sets the line style property. * * @param lineStyleChoiceList the line style list */ public final void setLineStyleChoiceList(ChoiceList lineStyleChoiceList) { this.lineStyleChoiceList = (LineStyleChoiceList)lineStyleChoiceList; this.selectedLineStyle = this.lineStyleChoiceList.getSelectedPos(); } /** * Gets the line style. * * @return the line style */ public final Stroke getLineStyle() { return lineStyleChoiceList.getSelectedValue(); } protected final void setLineStyle(Stroke stroke) { if(lineStyleChoiceList.setSelectedValue(stroke)) { this.selectedLineStyle = lineStyleChoiceList.getSelectedPos(); } } /** * Gets the bent style. * * @return the bent style */ public final BentStyle getBentStyle() { if (!bentStyleChoiceList.getSelectedValue().equals(BentStyleChoiceList.AUTO)) { return bentStyleChoiceList.getSelectedValue(); } Direction startDirection = getDirection(getStartNode()).getNearestCardinalDirection(); Direction endDirection = getDirection(getEndNode()).getNearestCardinalDirection(); if ((Direction.NORTH.equals(startDirection) || Direction.SOUTH.equals(startDirection)) && (Direction.NORTH.equals(endDirection) || Direction.SOUTH.equals(endDirection))) { return BentStyleChoiceList.VHV; } else if ((Direction.NORTH.equals(startDirection) || Direction.SOUTH.equals(startDirection)) && (Direction.EAST.equals(endDirection) || Direction.WEST.equals(endDirection))) { return BentStyleChoiceList.VH; } else if ((Direction.EAST.equals(startDirection) || Direction.WEST.equals(startDirection)) && (Direction.NORTH.equals(endDirection) || Direction.SOUTH.equals(endDirection))) { return BentStyleChoiceList.HV; } else if ((Direction.EAST.equals(startDirection) || Direction.WEST.equals(startDirection)) && (Direction.EAST.equals(endDirection) || Direction.WEST.equals(endDirection))) { return BentStyleChoiceList.HVH; } return BentStyleChoiceList.STRAIGHT; } protected final void setBentStyle(BentStyle bentStyle) { if(bentStyleChoiceList.setSelectedValue(bentStyle)) { this.selectedBentStyle = bentStyleChoiceList.getSelectedPos(); } } private transient LineStyleChoiceList lineStyleChoiceList; private transient BentStyleChoiceList bentStyleChoiceList; private int selectedBentStyle; private int selectedLineStyle; public static final int SELF_LOOP_GAP_X = 20; public static final int SELF_LOOP_GAP_Y = 22; }