/* * Created on 28-Feb-2004 * @author Michael Camacho (and whoever wrote the first bit!) * @author Edwin Chung 16 Mar 2007: modified the constructor and several other * functions so that DataLayer objects can be created outside the GUI */ package pipe.views; import pipe.constants.GUIConstants; import pipe.controllers.PetriNetController; import uk.ac.imperial.pipe.models.petrinet.ArcPoint; import java.awt.Container; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.RenderingHints; import java.awt.geom.Ellipse2D; import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; import java.awt.geom.RectangularShape; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; /** * This class represents each point on the arc path graphically. * It's old code so the Bezier maths etc. needs to be addressed */ @SuppressWarnings("serial") public class ArcPathPoint extends AbstractPetriNetViewComponent<ArcPoint> { /** * Boolean value determining if the arc is straight or a curve */ public static final boolean STRAIGHT = false; private static final int SIZE_OFFSET = 1; /** * Size of the point */ private static final int SIZE = 3; /** * Underlying point model */ private final ArcPoint model; /** * Control used for Bezier curve */ private final Point2D.Double control1 = new Point2D.Double(); /** * Control used for Bezier curve */ private final Point2D.Double control = new Point2D.Double(); /** * Path point belongs to */ private ArcPath arcPath; /** * Sets copyPastable to false because we cant copy paste individual arc points */ private void setup() { copyPasteable = false; } public void setPointLocation(double x, double y) { setBounds((int) x - SIZE, (int) y - SIZE, 2 * SIZE + SIZE_OFFSET, 2 * SIZE + SIZE_OFFSET); } /** * Constructor * @param point on the arc * @param arcPath path of the arc * @param petriNetController Petri net controller * @param parent container */ public ArcPathPoint(ArcPoint point, ArcPath arcPath, PetriNetController petriNetController, Container parent) { super("", point, petriNetController, parent); setup(); model = point; setPointLocation(model.getPoint()); this.arcPath = arcPath; model.addPropertyChangeListener(new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent propertyChangeEvent) { if (propertyChangeEvent.getPropertyName().equals(ArcPoint.UPDATE_LOCATION_CHANGE_MESSAGE)) { Point2D point = (Point2D) propertyChangeEvent.getNewValue(); setPointLocation(point.getX(), point.getY()); } } }); } public final void setPointLocation(Point2D point) { setPointLocation(point.getX(), point.getY()); } public Point2D getPoint() { return model.getPoint(); } public boolean isCurved() { return model.isCurved(); } public void setVisibilityLock(boolean lock) { arcPath.setPointVisibilityLock(lock); } public double getAngle(Point2D.Double p2) { double angle; if (model.getPoint().getY() <= p2.y) { angle = Math.atan((model.getPoint().getX() - p2.x) / (p2.y - model.getPoint().getY())); } else { angle = Math.atan((model.getPoint().getX() - p2.x) / (p2.y - model.getPoint().getY())) + Math.PI; } // Needed to eliminate an exception on Windows if (model.getPoint().equals(p2)) { angle = 0; } return angle; } public Point2D.Double getMidPoint(ArcPathPoint target) { return new Point2D.Double((target.model.getPoint().getX() + model.getPoint().getX()) / 2, (target.model.getPoint().getY() + model.getPoint().getY()) / 2); } public Point2D.Double getControl1() { return control1; } public void setControl1(Point2D.Double p) { control1.x = p.x; control1.y = p.y; } public Point2D.Double getControl() { return control; } public void setControl(Point2D.Double p) { control.x = p.x; control.y = p.y; } public void setControl1(double _x, double _y) { control1.x = _x; control1.y = _y; } public void setControl2(double _x, double _y) { control.x = _x; control.y = _y; } @Override public void addToContainer(Container container) { // Nothing needed } @Override public String getName() { return this.getArcPath().getArc().getModel().getName() + " - Point " + this.getIndex(); } public int getIndex() { for (int i = 0; i < arcPath.getNumPoints(); i++) { if (arcPath.getPathPoint(i) == this) { return i; } } return -1; } public ArcPath getArcPath() { return arcPath; } @Override public int hashCode() { int result = super.hashCode(); result = 31 * result + model.hashCode(); return result; } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } if (!super.equals(o)) { return false; } ArcPathPoint pathPoint = (ArcPathPoint) o; if (!model.equals(pathPoint.model)) { return false; } return true; } /** * Performs a delete only if there are more than two points left after deleting this one */ @Override public void componentSpecificDelete() { if (isDeleteable()) { if (getArcPath().getArc().isSelected()) { return; } kill(); } } @Override public void paintComponent(Graphics g) { super.paintComponent(g); if (!ignoreSelection) { Graphics2D g2 = (Graphics2D) g; g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_NORMALIZE); RectangularShape shape; if (model.isCurved()) { shape = new Ellipse2D.Double(0, 0, 2 * SIZE, 2 * SIZE); } else { shape = new Rectangle2D.Double(0, 0, 2 * SIZE, 2 * SIZE); } if (isSelected()) { g2.setPaint(GUIConstants.SELECTION_FILL_COLOUR); g2.fill(shape); g2.setPaint(GUIConstants.SELECTION_LINE_COLOUR); g2.draw(shape); } else { g2.setPaint(GUIConstants.ELEMENT_FILL_COLOUR); g2.fill(shape); g2.setPaint(GUIConstants.ELEMENT_LINE_COLOUR); g2.draw(shape); } } } public boolean isDeleteable() { int i = getIndex(); return i > 0 && i != arcPath.getNumPoints() - 1; } public void kill() { // called internally by ArcPoint and parent ArcPath super.removeFromContainer(); } }