/* DiagramPanel class for Y hang applet */ /* Simeon Warner - 20May96 */ import java.awt.*; public class DiagramPanel extends Canvas { final boolean _debug_ = false; Dimension mySize; //Stuff for grabbing and shifting an anchor or knot final int gotNothing = 0, gotLeft = 1, gotRight = 2, gotKnot = 3; int gotSomething = gotNothing ; //double-buffering private Image image2; private Graphics g2; Simulation simulation; DiagramPanel() { // nothing; } public void init(Simulation s) { simulation = s; repaint(); /* this.size() doesn't work here */ //mySize=this.size(); /* Hence, it is not possible to create the second image space */ //image2 = createImage(mySize.width,mySize.height); //g2=image2.getGraphics(); this.setBackground(Color.gray); this.repaint(); } public boolean handleEvent(Event evt) { switch (evt.id) { case Event.MOUSE_DOWN: // see about picking up an anchor if (onAnchor(evt.x, evt.y, simulation.xLeft, simulation.yLeft)) { gotSomething = gotLeft; } else { if (onAnchor(evt.x, evt.y, simulation.xRight, simulation.yRight)) { gotSomething = gotRight; } else { if (onAnchor(evt.x, evt.y, simulation.xKnot, simulation.yKnot)) { gotSomething = gotKnot; } else { gotSomething = gotNothing; } } //stop simulation if we have picked something up if (gotSomething != gotNothing) simulation.suspend(); } return true; case Event.MOUSE_DRAG: /* drop item if we move outside the drawing area! */ if ((evt.x<1) || (evt.x>(mySize.width-1)) || (evt.y<1) || (evt.y>(mySize.height-1))) { gotSomething=gotNothing; simulation.checkSlack(); simulation.resume(); } else { switch (gotSomething) { case gotLeft: simulation.xLeft=evt.x; simulation.yLeft=evt.y; break; case gotRight: simulation.setRight(evt.x,evt.y); break; case gotKnot: simulation.setKnot(evt.x, evt.y); break; case gotNothing: break; default: System.out.println("Program error - bad case in Event.MOUSE_DRAG."); } } repaint(); return true; case Event.MOUSE_UP: switch (gotSomething) { case gotLeft: case gotRight: case gotKnot: simulation.checkSlack(); simulation.resume(); break; case gotNothing: break; default: System.out.println("Program error - bad case in Event.MOUSE_UP."); } gotSomething = gotNothing; return true; case Event.MOUSE_MOVE: // do nothing return true; default: if (_debug_) System.out.println("Event not handled (" + evt.id + ")."); return false; } } private boolean onAnchor(int x1, int y1, int x2, int y2) { int aRadiusSqd = simulation.aradius*simulation.aradius; if (((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)) <= aRadiusSqd) return true; else return false; } public void update(Graphics g) { paint(g); } public void paint(Graphics g) { int xl,yl,xr,yr,xk,yk,r,d; boolean stable,slackLeft,slackRight; String sl,sr; float w,fl,fr,al,ar,tmp; /* If the second image doesn't exist then we must now create it, the size method will now give sensible answers so we may also set the default positions based on panel size. It would be nicer to put this bit of code elsewhere */ if (g2 == null) paintSetup(); /* grab data from the simulation */ /* this could (and maybe should) be done using synchronized methods of simulation */ synchronized(simulation) { xl=simulation.xLeft; yl=simulation.yLeft; xr=simulation.xRight; yr=simulation.yRight; xk=simulation.xKnot; yk=simulation.yKnot; r=(int)simulation.aradius; d=r+r; stable=simulation.stable; slackLeft=simulation.slackLeft; slackRight=simulation.slackRight; } w=simulation.getWeight(); /* now lets paint a picture to the second buffer (g2) and then copy */ g2.setColor(this.getBackground()); mySize=this.size(); g2.fillRect(0,0,mySize.width,mySize.height); g2.setColor(Color.blue); g2.fillOval(xl-r, yl-r, d, d); g2.fillOval(xr-r, yr-r, d, d); g2.drawLine(xl,yl,xk,yk); g2.drawLine(xk,yk,xr,yr); g2.drawLine(xk,yk,xk,mySize.height); /* Annotate */ if (yk<=mySize.height) { g2.drawLine(xk,mySize.height,xk+r,mySize.height-r); g2.drawLine(xk,mySize.height,xk-r,mySize.height-r); g2.drawString(String.valueOf(w),xk+r,mySize.height-r); } if ( (((xk-xr)*(xk-xl))>0) || (((xk-xl)*(yl-yr))<((xr-xl)*(yl-yk))) || (!stable) ) { fl=Float.NaN; fr=Float.NaN; } else { if ((xk==xr) && (xk==xl) ) { if (slackLeft) { fl=Float.NaN; fr=w; } else if (slackRight) { fl=w; fr=Float.NaN; } else { fl=w/(float)2.0; fr=fl; } } else if (xk==xr) { fr=w; fl=(float)0.0; if (slackLeft) fl=Float.NaN; } else if (xk==xl) { fr=(float)0.0; fl=w; if (slackRight) fr=Float.NaN; } else { al=(float)(Math.atan2(yk-yl,xl-xk)-Math.PI/2.0); ar=(float)(Math.PI/2.0-Math.atan2(yk-yr,xr-xk)); if ((float)Math.abs(tmp=(float)Math.sin(Math.PI-al-ar))<(float)0.02) { fl=Float.POSITIVE_INFINITY; fr=Float.POSITIVE_INFINITY; } else if (tmp<(float)0.0) { fl=Float.NaN; fr=Float.NaN; } else { fl=w/tmp*(float)Math.sin(ar); fr=w/tmp*(float)Math.sin(al); } } } if (Float.isInfinite(fl)) sl="!!!"; else if (Float.isNaN(fl)) sl="?"; else sl=String.valueOf((int)fl); if (Float.isInfinite(fr)) sr="!!!"; else if (Float.isNaN(fr)) sr="?"; else sr=String.valueOf((int)fr); g2.drawString(sl,xl+r,yl-r); g2.drawString(sr,xr+r,yr-r); /* Copy image to live version */ g.drawImage(image2,0,0,this); } private void paintSetup() { int min; mySize=this.size(); /* Set initial positions of anchors and knot */ if (mySize.width