package Current.canvases.Rational; import java.applet.Applet; import java.awt.event.*; import java.awt.*; import java.awt.geom.*; import Current.gui.*; import Current.basic.*; import Current.manage.*; public class RationalCanvas extends DBCanvas implements MouseListener, KeyListener, FocusListener { Manager M; IntegerSelector I; ListenSquare[] L=new ListenSquare[7]; ListenSquare[][] Y=new ListenSquare[3][3]; int mode; int P1,Q1,P2,Q2; Complex Z; //added by pat FontMetrics fm; Rectangle2D.Double[] bounds=new Rectangle2D.Double[4]; // this holds the currently selected integer (selected==-1 => not selected) int selected=-1; public RationalCanvas(Manager M) { this.M=M; Z=new Complex(); M.addListener(this); I=new IntegerSelector(2,90,30,16,5,1,25,1); L[1]=new ListenSquare(2,70,35,16,Color.white); L[1].on=1; L[2]=new ListenSquare(42,72,12,12,Color.white); L[2].on=1; mode=1; //farey to start P1=2;Q1=3; P2=2;Q2=3; for(int i=0;i<=2;++i) { for(int j=0;j<=2;++j) { Y[i][j]=new ListenSquare(2+18*i,110+18*j,18,18,Color.white); Y[i][j].on=1; }} L[3]=new ListenSquare(2,170,14,14,Color.white); L[4]=new ListenSquare(2,188,14,14,Color.white); L[3].on=1; L[4].on=0; setFont(new Font("sanserif",Font.PLAIN,10)); fm=getFontMetrics(getFont()); addMouseListener(this); addKeyListener(this); addFocusListener(this); } public void paint(Graphics gfx) { Graphics2D g=(Graphics2D) gfx; g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); Dimension D=getSize(); g.setColor(new Color(100,0,100)); g.fillRect(0,0,D.width,D.height); I.render(g,new Color(80,130,250),Color.white,Color.white); L[1].render(g,new Color(80,130,250)); g.setColor(Color.black); g.setFont(new Font("sanserif",Font.PLAIN,10)); if(mode==0) g.drawString("k/2^n",6,83); if(mode==1) g.drawString("p/q",6,82); g.setColor(Color.white); g.drawString("grid",20,181); g.drawString("track",20,199); drawX(g); drawY(g); for(int i=0;i<3;++i) { for(int j=0;j<3;++j) { Y[i][j].render(g,new Color(80,130,250)); } } Y[1][1].render(g,new Color(0,0,255)); L[2].infoRender(g); L[3].render(g,new Color(80,130,250)); L[4].render(g,new Color(80,130,250)); g.setColor(Color.white); g.drawRect(0,0,D.width-1,D.height-1); } public void mouseEntered(MouseEvent e) {} public void mouseExited(MouseEvent e) {} public void mouseClicked(MouseEvent e) { e.consume(); Point X=new Point(); X.x=e.getX(); X.y=e.getY(); I.modify(X); if(L[1].inside(X)==1) mode=1-mode; if(L[2].inside(X)==1) document(); if(L[3].inside(X)==1) { L[3].on=1-L[3].on; M.GM.draw= !M.GM.draw; M.spaceChanged(); } if(L[4].inside(X)==1) { L[4].on=1-L[4].on; } for(int i=0;i<3;++i) { for(int j=0;j<3;++j) { if(Y[i][j].inside(X)==1) {Z=M.getZ();getApproximation(i,j);} }} // added by pat for (int i=0; i<4; i++) { if (bounds[i].contains(e.getX(),e.getY())) { if (i!=selected) selected=i; else selected=-1; repaint(); return; } } selected=-1; repaint(); } public void mousePressed(MouseEvent e) {} public void mouseReleased(MouseEvent e) {} public void drawX(Graphics2D g) { g.setColor(new Color(255,80,255)); g.fillRect(1,1,58,32); g.setColor(Color.black); g.drawRect(1,1,57,32); g.drawLine(5,16,54,16); Integer PP1=new Integer(P1); Integer QQ1=new Integer(Q1); // added by pat Rectangle2D rect; rect=fm.getStringBounds(PP1.toString(),getGraphics()); bounds[0]=new Rectangle2D.Double(rect.getX()+3, rect.getY()+12, getWidth()-6, rect.getHeight()); if (selected==0) { g.setColor(Color.white); g.fill(bounds[0]); g.setColor(Color.black); } g.drawString(PP1.toString(),3,12); // added by pat rect=fm.getStringBounds(QQ1.toString(),getGraphics()); bounds[1]=new Rectangle2D.Double(rect.getX()+3, rect.getY()+28, getWidth()-6, rect.getHeight()); if (selected==1) { g.setColor(Color.white); g.fill(bounds[1]); g.setColor(Color.black); } g.drawString(QQ1.toString(),3,28); } public void drawY(Graphics2D g) { g.setColor(new Color(255,80,255)); g.fillRect(1,1+34,58,32); g.setColor(Color.black); g.drawRect(1,1+34,57,32); g.drawLine(5,16+34,54,16+34); Integer PP2=new Integer(P2); Integer QQ2=new Integer(Q2); // added by pat Rectangle2D rect; rect=fm.getStringBounds(PP2.toString(),getGraphics()); bounds[2]=new Rectangle2D.Double(rect.getX()+3, rect.getY()+12+34, getWidth()-6, rect.getHeight()); if (selected==2) { g.setColor(Color.white); g.fill(bounds[2]); g.setColor(Color.black); } g.drawString(PP2.toString(),3,12+34); rect=fm.getStringBounds(QQ2.toString(),getGraphics()); bounds[3]=new Rectangle2D.Double(rect.getX()+3, rect.getY()+28+34, getWidth()-6, rect.getHeight()); if (selected==3) { g.setColor(Color.white); g.fill(bounds[3]); g.setColor(Color.black); } g.drawString(QQ2.toString(),3,28+34); } public void getApproximation(int i,int j) { if(mode==0) getDyadicApproximation(i,j); if(mode==1) getFareyApproximation(i,j); } public void getDyadicApproximation(int i, int j) { DyadicRational X=DyadicRational.approximate(Z.x,I.val); DyadicRational Y=DyadicRational.approximate(Z.y,I.val); DyadicRational dX=new DyadicRational(1,I.val); DyadicRational dY=new DyadicRational(1,I.val); if(i==0) X=DyadicRational.minus(X,dX); if(i==2) X=DyadicRational.plus(X,dX); if(j==2) Y=DyadicRational.minus(Y,dY); if(j==0) Y=DyadicRational.plus(Y,dY); X=DyadicRational.confine(X); Y=DyadicRational.confine(Y); P1=X.n; Q1=(int)(Math.pow(2,X.d)); P2=Y.n; Q2=(int)(Math.pow(2,Y.d)); speak(); } public void getFareyApproximation(int i,int j) { FareyRational X=new FareyRational(0,1); FareyRational Y=new FareyRational(0,1); if(i==0) X=FareyRational.approximateDn(Z.x,I.val); if(i==1) X=FareyRational.approximate(Z.x,I.val); if(i==2) X=FareyRational.approximateUp(Z.x,I.val); if(j==2) Y=FareyRational.approximateDn(Z.y,I.val); if(j==1) Y=FareyRational.approximate(Z.y,I.val); if(j==0) Y=FareyRational.approximateUp(Z.y,I.val); P1=X.p; Q1=X.q; P2=Y.p; Q2=Y.q; speak(); } public void document() { M.mcbSend(new HelpDocument("RationalCanvas.html")); } public void keyPressed(KeyEvent e) { L[4].on=0; } public void keyReleased(KeyEvent e) { //System.out.println("KeyReleased="+e.paramString()); } public void keyTyped(KeyEvent e) { if (e.getKeyChar()==KeyEvent.VK_TAB) { selected=(selected+1)%4; repaint(); return; } if (selected!=-1) { if (e.getKeyChar()==KeyEvent.VK_ENTER) { selected=-1; repaint(); return; } int x=0; switch (selected) { case 0: x=P1; break; case 1: x=Q1; break; case 2: x=P2; break; case 3: x=Q2; break; } int temp=x; if (e.getKeyChar()==KeyEvent.VK_BACK_SPACE) { temp=temp/10; } if (e.getKeyChar()==KeyEvent.VK_DELETE) { temp=0; } int ch=(int)(e.getKeyChar()-'0'); if ((ch>=0)&&(ch<10)){ temp=10*temp+ch; } //System.out.println("x="+x+" temp="+temp); if (x!=temp) { x=temp; switch (selected) { case 0: P1=x; break; case 1: Q1=x; break; case 2: P2=x; break; case 3: Q2=x; break; } speak(); repaint(); } } } public void mcbReceive(Parameter p) { Complex Y=p.getZ(); if(L[4].on==1) { if((Z.x!=Y.x)||(Z.y!=Y.y)) {Z=Y;getApproximation(1,1);} repaint(); } } /** This was added by pat to enable other classes to learn about the new * rational triangle. */ public void speak(){ //System.out.println("speaking"); M.mcbSend(RationalTriangle.fromMcbRational(P1,Q1,P2,Q2)); Complex old=M.getZ(); Z=new Complex(1.0*P1/Q1,1.0*P2/Q2); if ( (old.x!=Z.x)||(old.y!=Z.y)) { //System.out.println("speaking2"); M.setParameter(Z); } } public void focusGained(java.awt.event.FocusEvent focusEvent) { } public void focusLost(java.awt.event.FocusEvent focusEvent) { if (selected!=-1) { selected=-1; repaint(); } } public void mcbCleanup() { M.remove(this); } public Dimension getPreferredSize() { return new Dimension(60,206); } }