//CircuitCanvas.java
/* A Java class for
 * SingleStub.java
 * Electromagnetic Transmission Line Applet
 * Applet without Smith Chart - Prepared by Umberto Ravaioli 
 * for 6th edition of Fundamentals of Applied Electromagnetics Book
 * June 2009 - All Rights Reserved
 */   

import java.awt.*;
import java.awt.event.*;
import java.awt.geom.Arc2D;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
import java.awt.geom.Ellipse2D;

public class CircuitCanvas extends Canvas implements MouseListener{
	private int x[], y[];
	private StateVars state;
	private Image im;
	private Graphics buf;
	private double frequency, wavelength, epsilon_r;
	
	private static final Font labfont = TheFonts.sanSerif10;
	private static final Font symbolfont = TheFonts.symbol12;
	
	//private static final Color bgcolor = new Color(24,188,185);
	private static final Color bgcolor = Color.gray;
	private static final Color ccolor1 = new Color(50,204,153);
	private boolean IsFocusOn;
	
        public CircuitCanvas(StateVars state){
		super();
		this.state = state;
		setBackground(bgcolor);
		x = new int[5];
		y = new int[6];
		this.addMouseListener(this);
		IsFocusOn = false;
	}

	public void update(Graphics g){
		paint(g);
	}

	public void paint(Graphics g){
		if(im == null){
			im = createImage(getSize().width,getSize().height);
			buf = im.getGraphics();
			drawCircuit(buf);
		}
		else{
			drawCircuit(buf);
		}
		g.drawImage(im,0,0,null);
	}
	
	public void drawCircuit(Graphics g){
		//Draw the background
		g.setColor(bgcolor.darker());
		//g.fillRect(0,getSize().height-2,getSize().width,2);
		//g.fillRect(getSize().width-2,0,2,getSize().height);
		//g.setColor(bgcolor.brighter());
		//g.fillRect(0,0,2,getSize().height-1);
		//g.fillRect(0,0,getSize().width-2,2);
		

		//set the arrays
		x[0] = state.s20;
		x[4] = getSize().width-state.s20;
		x[2] = x[0] + state.s50;
		x[3] = x[4] - state.s20;
		x[1] = (x[0]+x[2])/2;

		y[4] = state.s25;
		y[0] = getSize().height-state.s115;
		y[2] = (y[4]+y[0])/2;
		y[3] = (y[4]+y[2])/2;
		y[1] = (y[0]+y[2])/2;
		y[5] = getSize().height;

		g.clearRect(0,0,getSize().width-1,getSize().height-1);
		
		//Reference
		drawRef(g);
		
		//Wires
		drawWire(x[0],y[4],x[4],y[4],1,g);
		drawWire(x[0],y[0],x[4],y[0],1,g);
		drawWire(x[0],y[4]+1,x[0],y[0]-1,2,g);
		drawWire(x[4],y[4]+1,x[4],y[0]-1,2,g);
                    
                Graphics2D g2d = (Graphics2D)g;
                g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);

		//Horizontal axis
		drawAxis(g);
		drawAxis(g);
                
		//ZL
		draw3DRect(x[4],y[2],state.s18,y[1]-y[3],ccolor1,g);
		g.setColor(Color.black);
                g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
		MaestroG.subscripter("Z","L","",g,state.font11,x[4]-state.s5,y[2]+state.s2);
                //Zg
		draw3DRect(x[1],y[4],x[2]-x[0]-state.s20,state.s18,ccolor1,g);	
		g.setColor(Color.black);
                g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
		MaestroG.subscripter("Z","g","",g,state.font11,x[1]-state.s5,y[4]+state.s2);
                
		//Vg
		drawCircle(x[0],y[2],state.s12,ccolor1,g);
                
		g.setColor(Color.black);
		MaestroG.subscripter("V","g","",g,state.font11,x[0]-state.s6,y[2]+state.s1);
                
		//Connections
		drawConnect(x[2],y[4],g);
		drawConnect(x[2],y[0],g);
		drawConnect(x[3],y[4],g);
		drawConnect(x[3],y[0],g);

		//Draw parameter strings
		//if(IsFocusOn){drawStrings(g);
		drawStrings(g);
		                
		//Draw Stubs
		drawStub(state.stub1);
		drawStub(state.stub2);
	}

	private void drawGrid(int [] x,int [] y,Graphics g){
		g.setColor(Color.yellow);
		for(int i = 0 ; i< 5; i++){
			g.drawLine(x[0],y[i],x[4],y[i]);
			g.drawLine(x[i],y[0],x[i],y[4]);
		}
	}


	private void draw3DRect(int x, int y, int width, int height, Color c, Graphics g){
		g.setColor(c);
		g.fillRect(x-width/2,y-height/2,width,height);
		g.setColor(Color.white);
		g.drawLine(x-width/2,y-height/2,x+width/2,y-height/2);
		g.drawLine(x-width/2,y-height/2,x-width/2,y+height/2);
		g.setColor(Color.black);
		g.drawLine(x-width/2,y+height/2,x+width/2,y+height/2);
		g.drawLine(x+width/2,y-height/2,x+width/2,y+height/2);
	}
	
	private void drawRect(int x, int y, int width, int height, Color c, Graphics g){
		g.setColor(c);
		g.fillRect(x-width/2,y-height/2,width,height);
	}
	

	private void drawCircle(int x, int y, int radius, Color c, Graphics g){
		Graphics2D g2d = (Graphics2D)g;
                g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
                g.setColor(c);
		g.fillOval(x-radius,y-radius,2*radius,2*radius);
		g.setColor(Color.white);
		g.drawOval(x-radius,y-radius,2*radius,2*radius);
		g.setColor(Color.black);
		g.drawArc(x-radius-state.s1,y-radius-state.s1,2*radius+state.s2,2*radius+state.s2,30,-120);
		/*
		g.setColor(c.brighter());
		g.drawArc(x-radius,y-radius,2*radius,2*radius,60,120);
		*/
	}

	private void drawConnect(int x, int y, Graphics g){
            int tmp1, tmp2;
            tmp1 = state.s6;
            tmp2 = tmp1-state.s2;
            //drawRect(x,y,tmp1,tmp1,Color.white,g);
            //drawRect(x,y,tmp2,tmp2,Color.black,g);

            Graphics2D g2d = (Graphics2D)g;

            g2d.setStroke(new BasicStroke(2));
        
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
            
            g2d.setPaint(Color.black);
            g.fillOval(x-tmp1/2,y-tmp1/2,tmp1,tmp1);
            g2d.setPaint(Color.white);
            //g.fillOval(x-tmp2/2,y-tmp2/2,tmp2,tmp2);
            
            Arc2D.Double arc_zero = new Arc2D.Double((double)(x-tmp1/2),(double)(y-tmp1/2),
                    (double)tmp1,(double)tmp1,0,360,0);
            g2d.draw(arc_zero);
            
	
            g2d.setStroke(new BasicStroke(1));
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_OFF);
	}

	private void drawWire(int x1, int y1, int x2, int y2, int mode, Graphics g){
		g.setColor(Color.white);
		g.drawLine(x1,y1,x2,y2);
		if(mode==1){
			g.setColor(Color.black);
			g.drawLine(x1,y1+1,x2,y2+1);
		}
		else if(mode==2){
			g.setColor(Color.black);
			g.drawLine(x1+1,y1,x2+1,y2);
		}
	}

	public void drawStub(Stub stub){
	     if(stub.isEnable()){
		int tax1, tay1, tax2, tay2;
		int tbx1, tby1, tbx2, tby2;
		double maxstublength=0.5;
		double stubangle;
		int stublength;
		stubangle=0.5235;
		stublength = state.s40;
				
		tax1=(int)(x[3]-(stub.getPosition()/state.lineLength)*(x[3]-x[2]));
		tay1=y[4]+state.s2;
		tax2=(int)(tax1-stublength*stub.getLength()/maxstublength*Math.cos(stubangle));
		tay2=(int)(tay1+stublength*stub.getLength()/maxstublength*Math.sin(stubangle));
		
		tbx1=tax1;
		tby1=y[0];
		tbx2=tax2;
		tby2=(int)(tby1+stublength*stub.getLength()/maxstublength*Math.sin(stubangle));

		buf.setColor(Color.white);
		buf.drawLine(tax1,tay1,tax2,tay2);
		buf.drawLine(tbx1,tby1,tbx2,tby2);
		buf.setColor(Color.blue);
		buf.drawLine(tax1,tay1+state.s1,tax2,tay2+state.s1);
		buf.drawLine(tbx1,tby1+state.s1,tbx2,tby2+state.s1);
		if(!stub.isOpen()){
			buf.setColor(Color.white);
			buf.drawLine(tax2,tay2,tbx2,tby2);
			buf.setColor(Color.blue);
			buf.drawLine(tax2+state.s1,tay2,tbx2+state.s1,tby2);
		}
            }
	}

	public void drawRef(Graphics g){
	
            if(state.xpos <=state.lineLength && state.xpos >= 0.0){
		int tx1, ty1, tx2, ty2;
		tx1 = (int)(x[3] - (state.xpos/state.lineLength)*(x[3]-x[2]));
		ty1 = y[4]-state.s10;
		tx2 = tx1;
		ty2 = y[0]+state.s10;
		
		g.setColor(Color.green);
		//g.drawLine(tx1,ty1,tx2,ty2);
		MaestroG.drawArrow(tx1,ty1+state.s20,5,g);
		MaestroG.drawArrow(tx1,ty2-state.s20,6,g);
            }
	}	
        
	private void drawAxis(Graphics g){
		Graphics2D g2d = (Graphics2D)g;
                g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
                
                int ytmp;
		FontMetrics fm;
		ytmp=y[0] + state.s15;
		g.setColor(Color.gray.brighter());
		g.drawLine(x[4],ytmp,x[0],ytmp);
		g.drawLine(x[2],ytmp-state.s4,x[2],ytmp+state.s4);
		g.drawLine(x[3],ytmp-state.s4,x[3],ytmp+state.s4);
		//Arrowhead
		MaestroG.drawArrow(x[0],ytmp,8,g);
		g.setFont(TheFonts.bold12);
		fm = g.getFontMetrics();
                
                g.setColor(Color.white);
		g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
                //MaestroG.subscripterSerIT("l","","",g,state.font18,x[2],ytmp+fm.getHeight()+state.s10);
                MaestroG.subscripter("0","","",g,state.font15,x[3]-state.s3,ytmp+fm.getHeight()+state.s10);
                MaestroG.subscripterSS3("d","","",g,state.font16,x[0],ytmp+fm.getHeight()+state.s3);
                
		g.setColor(Color.black);
	}
	
	private void drawStrings(Graphics g){
                Graphics2D g2d = (Graphics2D)g;
                g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);

                String alpha, Ohm, lambda, infinity, Gamma, epsilon;
                FontMetrics fm;
                
                g.setFont(new Font("Sanserif",Font.PLAIN,state.font12));
		fm = g.getFontMetrics();
                
                alpha="\u03b1";
		lambda="\u03bb";
		Ohm="\u03a9";
		infinity="\u221e";
		Gamma="\u0393";
                epsilon="\u03b5";
		
                g.setColor(Color.white);
		String tempo;
		int ylevel = y[5]-state.s120-3*fm.getHeight()+fm.getHeight()/2;
		
		
                MaestroG.subscripterSanSym2("Z","0"," = "+state.getZ0()," "+Ohm,g,state.font12,x[2]+state.s40,ylevel);
                MaestroG.subscripterSanSym2("Z","0"," = "+state.getZ0()," "+Ohm,g,state.font12,x[2]+state.s40,ylevel);
		// write epsilon
		
		epsilon_r = state.epsilon_r;
		int x2 = x[2] + state.s40;
		int y2 = ylevel + state.s25;
		
		MaestroG.subscripterSymFirst2(epsilon,"r","",g,state.font14,x2,y2);
		MaestroG.subscripterSymFirst2(epsilon,"r","",g,state.font14,x2,y2);
                
                g.setFont(labfont);
		
		MaestroG.subscripter("  ","  "," =  "+MaestroA.rounder(epsilon_r,4),g,state.font12,x2,y2);
		MaestroG.subscripter("  ","  "," =  "+MaestroA.rounder(epsilon_r,4),g,state.font12,x2,y2);
                
		// write Load Impedance
		int x3 = x[2] + state.s40;
		int y3 = y[5] - 46*fm.getHeight()/10;
		int offsetto = 0;
                
		if(Complex.Real(state.getZL())==0.0&&Complex.Imaginary(state.getZL())<=-2.0E140){ 
		    MaestroG.subscripter("Z","L"," = ",g,state.font12,x3,y3);
		    MaestroG.subscripterSanSym2("","",""+infinity," "+Ohm,g,state.font12,x3+state.s30,y3);
                }
		else if(Complex.Real(state.getZL())==0.0&&Complex.Imaginary(state.getZL())==0.0){ 
		    MaestroG.subscripter("Z","L"," = ",g,state.font12,x3,y3);
                    MaestroG.subscripterSanSym2("","","0.0"," "+Ohm,g,12,x3+state.s30,y3);
                    MaestroG.subscripter("Z","L"," = ",g,state.font12,x3,y3);
                    MaestroG.subscripterSanSym2("","","0.0"," "+Ohm,g,12,x3+state.s30,y3);
                }
		else{
		    MaestroG.subscripter("Z","L"," = ",g,state.font12,x3,y3);
		    MaestroG.subscripterSanSym2("","",""+state.getZL().toString(Complex.CARTESIAN,2)," "+Ohm,g,state.font12,x3+state.s30,y3);
                    
                    MaestroG.subscripter("Z","L"," = ",g,state.font12,x3,y3);
		    MaestroG.subscripterSanSym2("","",""+state.getZL().toString(Complex.CARTESIAN,2)," "+Ohm,g,state.font12,x3+state.s30,y3);
		}
		
		g.setColor(Color.yellow);
		if(state.IsOpen){
		    g.drawString("OPEN CIRCUIT STUB",getSize().width/2-fm.stringWidth("OPEN CIRCUIT STUB")/2,state.s15);
                    g.drawString("OPEN CIRCUIT STUB",getSize().width/2-fm.stringWidth("OPEN CIRCUIT STUB")/2,state.s15);
		}
		else{
		    g.drawString("SHORT CIRCUIT STUB",getSize().width/2-fm.stringWidth("SHORT CIRCUIT STUB")/2,state.s15);
                    g.drawString("SHORT CIRCUIT STUB",getSize().width/2-fm.stringWidth("SHORT CIRCUIT STUB")/2,state.s15);
		}
		
		g.setColor(Color.white);
		
		// write frequency	
		int x0 = x3 + state.s7;
		int y0 = y3 + state.s23;
		double f_normalized;
		frequency = state.frequency;
	
		if(frequency < 1.0E3){
		    f_normalized = frequency;
		    g.drawString("    =  "+MaestroA.rounder(f_normalized,6)+" Hz",x0,y0);	
                    g.drawString("    =  "+MaestroA.rounder(f_normalized,6)+" Hz",x0,y0);	
		}
		else if(frequency < 1.0E6 && frequency >= 1.0E3  ){
		    f_normalized = frequency/1.0E3;
		    g.drawString("    =  "+MaestroA.rounder(f_normalized,6)+" kHz",x0,y0);	
                    g.drawString("    =  "+MaestroA.rounder(f_normalized,6)+" kHz",x0,y0);	
		}
		else if(frequency < 1.0E9 && frequency >= 1.0E6 ){
		    f_normalized = frequency/1.0E6;
		    g.drawString("    =  "+MaestroA.rounder(f_normalized,6)+" MHz",x0,y0);
                    g.drawString("    =  "+MaestroA.rounder(f_normalized,6)+" MHz",x0,y0);
		}
		else if(frequency < 1.0E12 && frequency >= 1.0E9 ){
		    f_normalized = frequency/1.0E9;
		    g.drawString("    =  "+MaestroA.rounder(f_normalized,6)+" GHz",x0,y0);	
                    g.drawString("    =  "+MaestroA.rounder(f_normalized,6)+" GHz",x0,y0);	
		}
		else if(frequency < 1.0E15 && frequency >=1.0E12 ){
		    f_normalized = frequency/1.0E12;
		    g.drawString("   =  "+MaestroA.rounder(f_normalized,6)+" THz",x0,y0);	
                    g.drawString("   =  "+MaestroA.rounder(f_normalized,6)+" THz",x0,y0);	
		}
		else{
		    f_normalized = frequency/1.0E12;
		    g.drawString("    =  "+MaestroA.rounder(f_normalized,6)+" THz",x0,y0);
                    g.drawString("    =  "+MaestroA.rounder(f_normalized,6)+" THz",x0,y0);
		}
		
		MaestroG.subscripterSerIT("f","","",g,state.font14,x0-state.s2,y0);
		MaestroG.subscripterSerIT("f","","",g,state.font14,x0-state.s2,y0);
                
		//wavelength
		
		wavelength = state.wavelength;
		int x1 = x3 + state.s5;
		int y1 = y3 + state.s46;
		double tempw = 0.0;
		
                MaestroG.subscripterSymFirst2(lambda,"","",g,state.font14,x1,y1);
		MaestroG.subscripterSymFirst2(lambda,"","",g,state.font14,x1,y1);
                
		g.setFont(labfont);

		if(state.frequency == 0.0){
		    MaestroG.subscripter("   ",""," =      m",g,state.font12,x1,y1);
		    g.setFont(symbolfont);
		    g.drawString("\u221e",x1+fm.stringWidth("          "),y1);
		    g.setFont(labfont);
                    
                    MaestroG.subscripter("   ",""," =      m",g,state.font12,x1,y1);
		    g.setFont(symbolfont);
		    g.drawString("\u221e",x1+fm.stringWidth("          "),y1);
		    g.setFont(labfont);
		}
		else if(wavelength >= 1.0E6 && state.frequency > 0.0){
		    tempw = wavelength/1.0E6;
		    MaestroG.subSymsup("   ",""," = "+MaestroA.rounder(tempw,3),"","x 10","3"," km",g,state.font12,x1,y1);
                    MaestroG.subSymsup("   ",""," = "+MaestroA.rounder(tempw,3),"","x 10","3"," km",g,state.font12,x1,y1);
		}
		else if(wavelength < 1.0E6 && wavelength >= 1.0E3){
		    tempw = wavelength/1.0E3;
		    MaestroG.subscripter("   ",""," =  "+MaestroA.rounder(tempw,4)+" km",g,state.font12,x1,y1);
                    MaestroG.subscripter("   ",""," =  "+MaestroA.rounder(tempw,4)+" km",g,state.font12,x1,y1);
		}
		else if(wavelength < 1.0E3 && wavelength >= 1.0E-1){
		    MaestroG.subscripter("   ",""," =  "+MaestroA.rounder(wavelength,4)+" m",g,state.font12,x1,y1);
                    MaestroG.subscripter("   ",""," =  "+MaestroA.rounder(wavelength,4)+" m",g,state.font12,x1,y1);
		}
		else if(wavelength <1.0E-1 && wavelength >= 1.0E-2){
		    tempw = wavelength*1.0E2;
		    MaestroG.subscripter("   ",""," =  "+MaestroA.rounder(tempw,4)+" cm",g,state.font12,x1,y1);
                    MaestroG.subscripter("   ",""," =  "+MaestroA.rounder(tempw,4)+" cm",g,state.font12,x1,y1);
		}
		else if(wavelength <1.0E2 && wavelength >= 1.0E-4){
		    tempw = wavelength*1.0E3;
		    MaestroG.subscripter("   ",""," =  "+MaestroA.rounder(tempw,4)+" mm",g,state.font12,x1,y1);
                    MaestroG.subscripter("   ",""," =  "+MaestroA.rounder(tempw,4)+" mm",g,state.font12,x1,y1);
		}
		else if(wavelength < 1.0E-4 && wavelength >=1.0E-6 ){
		    tempw = wavelength*1.0E6;
		    MaestroG.subscripter("   ",""," =  "+MaestroA.rounder(tempw,4)+" \u00b5 m",g,state.font12,x1,y1);
                    MaestroG.subscripter("   ",""," =  "+MaestroA.rounder(tempw,4)+" \u00b5 m",g,state.font12,x1,y1);
		}
		else if(wavelength < 1.0E-6 ){
		    tempw = wavelength*1.0E9;
		    MaestroG.subscripter("   ",""," =  "+MaestroA.rounder(tempw,4)+" nm",g,state.font12,x1,y1);
                    MaestroG.subscripter("   ",""," =  "+MaestroA.rounder(tempw,4)+" nm",g,state.font12,x1,y1);
		}
		
	}
	
	public void mouseClicked(MouseEvent evt){
	
	}
	public void mouseEntered(MouseEvent evt){
	    IsFocusOn = true;
	    repaint();
	}
	public void mouseExited(MouseEvent evt){
	    IsFocusOn = false;
	    repaint();
    	}
	public void mousePressed(MouseEvent evt){
	
	}
	public void mouseReleased(MouseEvent evt){
	
	}
    
}//End of CircuitCanvs

