/*--------------------------------------------------------------------------- -- JAWAA 2.0 -- Copyright information: Susan H. Rodger, Pretesh Patel, Ayonike Akingbade, Diana Jackson Computer Science Department Duke University August 2002 Supported by National Science Foundation DUE-9752583. Copyright (c) 2002 All rights reserved. Redistribution and use in source and binary forms are permitted provided that the above copyright notice and this paragraph are duplicated in all such forms and that any documentation, advertising materials, and other materials related to such distribution and use acknowledge that the software was developed by the author. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIEs WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. ---------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------- File: nameoffile.java Package: JAWAA Version 2.0 Author: Pretesh Patel, Ayonike Akingbade, Diana Jackson Date: August 2002 Description of Contents: --------------------------------------------------------------------------*/ package jawaa.extras.arrow; import jawaa.util.*; import jawaa.object.JawaaObject; import java.awt.*; import jawaa.extras.PositionListener; /** * This object is graphically an arrow that is primarily used with * linked lists in the jawaa package. The basic objective of the * arrow is to remember two points and draw an arrow from one to the * other. A graphical arrow is defined to be a line connecting the * two points in question and an arrow head oriented in the same * direction as the vector from point 1 to point 2. * * In the future this object will be made even smarter by making it * cognizent of objects that are in its way. The future enhancement * will allow the arrow to determine the best path to follow from one * object to another instead of blindly drawing an arrow from one point * to another. * * @author Pretesh Patel **/ public class SmartArrow extends JawaaObject implements PositionListener { public SmartArrow(ArrowMonger p1, ArrowMonger p2, Color c) { myColor = c; myBegin= p1; myEnd = p2; p1.addArrowListener(this); p2.addArrowListener(this); myInitial = p1.getArrowConnection(this); myFinal = p2.getArrowPoint(this); } public SmartArrow(ArrowMonger p1, ArrowMonger p2, Color c, int arrowheads) { myColor = c; myBegin= p1; myEnd = p2; p1.addArrowListener(this); p2.addArrowListener(this); myInitial = p1.getArrowConnection(this); myFinal = p2.getArrowPoint(this); myHeads = arrowheads; } public SmartArrow(ArrowMonger p1, Color c) { myColor = c; myBegin = p1; p1.addArrowListener(this); myInitial = p1.getArrowConnection(this); proxy = new Point(myInitial.x + 10, myInitial.y); } public void setName(String s) { myName = s; } public String getName() { return myName; } public void pointMoved() { myFinal = myEnd.getArrowPoint(this); myInitial = myBegin.getArrowConnection(this); } public void setInitial(ArrowMonger p) { myBegin = p; myInitial = p.getArrowConnection(this); p.addArrowListener(this); } public void setFinal(ArrowMonger p) { myFinal = p.getArrowPoint(this); myEnd = p; p.addArrowListener(this); } public void setColor(Color c) { myColor = c; } public void setColor(String s) { myColor = ColorFactory.getColor(s); } public Color getColor() { return myColor; } public void paint(Graphics g) { paintLine(g); paintArrow(g); } public void paintLine(Graphics g) { g.setColor(myColor); if(myFinal != null) g.drawLine(myInitial.x, myInitial.y, myFinal.x, myFinal.y); else g.drawLine(myInitial.x, myInitial.y, myInitial.x+10, myInitial.y); } public void paintArrow(Graphics g) { Point above = aboveLine(myInitial, myFinal); Point below = belowLine(myInitial, myFinal); if (myHeads == 0) { } else { if(myFinal != null) proxy = myFinal; else proxy = new Point(myInitial.x + 10, myInitial.y); g.setColor(myColor); g.drawLine(proxy.x, proxy.y, above.x, above.y); g.drawLine(proxy.x, proxy.y, below.x, below.y); if(myHeads == 2) { above = aboveLine(myFinal, myInitial); below = belowLine(myFinal, myInitial); proxy = myInitial; g.drawLine(proxy.x, proxy.y, above.x, above.y); g.drawLine(proxy.x, proxy.y, below.x, below.y); } } } /** * @returns the angle the arrow line makes with the horizontal */ private double calcLineAngle(Point init, Point end) { if(myFinal != null) proxy = end; else proxy = new Point(init.x + 10, init.y); int y = proxy.y - init.y; int x = proxy.x - init.x; double angle; if((x == 0) && (y>=0)) angle = (3*Math.PI/2); else if((x == 0) && (y <=0)) angle = (Math.PI/2); else if((x < 0) && (y <= 0)) angle = Math.PI - Math.atan((double)y/(double)x); else if((x < 0) && (y >= 0)) angle = Math.PI + Math.abs(Math.atan((double)y/(double)x)); else if(y > 0) angle = 2*Math.PI - Math.atan((double)y/(double)x); else angle = -1* Math.atan((double)y/(double)x); return angle; } /** * @returns the Point of the arrowhead line below the arrow line **/ private Point belowLine(Point init, Point end) { if(end != null) proxy = end; else proxy = new Point(init.x + 10, init.y); double angle = calcLineAngle(init, end) + (Math.PI + Math.PI/4); double y_offset = Math.sin(angle)*-5; double x_offset = Math.cos(angle)*5; Point offset = new Point((int)Math.rint(x_offset), (int)Math.rint(y_offset)); Point p = new Point(proxy.x+offset.x, proxy.y+offset.y); return p; } /** * @returns the Point of the arrowhead line above the arrow line */ private Point aboveLine(Point init, Point end) { Point proxy; if(end != null) proxy = end; else proxy = new Point(init.x+10, init.y); double angle = (Math.PI - Math.PI/4 + calcLineAngle(init,end)); double y_offset = Math.sin(angle)*-5; double x_offset = Math.cos(angle)*5; Point offset = new Point((int)Math.rint(x_offset), (int)Math.rint(y_offset)); Point p = new Point(proxy.x+offset.x, proxy.y+offset.y); return p; } public Point getArrowStart() { return myBegin.getArrowConnection(); } public Point getArrowEnd() { if(myEnd != null) return myEnd.getArrowPoint(); else return new Point(myInitial.x+10, myInitial.y); } public ArrowMonger getNext() { return myEnd; } public ArrowMonger getPrevious() { return myBegin; } public void destroy() { myBegin.removeArrowListener(this); myEnd.removeArrowListener(this); } public Point getPathLocation(int count, int slices) { double percent = (double)count/(double)slices; int x = (int)Math.rint(percent*(myFinal.x-myInitial.x) + (double)myInitial.x); int y = (int)Math.rint(percent*(myFinal.y-myInitial.y) + (double)myInitial.y); return new Point(x,y); } private int myHeads = 1; private Point myInitial; private Point myFinal; private Color myColor; private final int arrowLength = 5; //length lines in arrow head private Point proxy; private ArrowMonger myBegin; private ArrowMonger myEnd; public static final int INITIAL = 0; public static final int FINAL = 1; private String myName; }