//RectWaveGuideCanvas.java

import java.awt.*;
import java.awt.event.*;

public class RectWaveGuideCanvas extends Canvas implements MouseListener{
    private static final Color bgcolor = Color.white;
    private static final Color medium1Color = Color.yellow;
    private static final Color medium2Color = Color.cyan;
    private int LeftMargin, RightMargin, TopMargin, BottomMargin;
    private Font labfont;
    private Font textfont;
    private Font symbolfont;
    private Font symbolfont2;
    
    private double a_to_b_ratio, frequency, a, b, epsilon_r, mu_r, phase_velocity, phase_velocity0;
    //private static final double epsilon0 = 8.8541878176E-12; //Units: F/m
    // Approximate epsilon for phase velocity 3 x 10^8 m/s
    private static final double epsilon0 = 8.841941286E-12; 
    private static final double mu0 = 1.25663706144E-6; //Units H/m
    
    private Image im;
    private Graphics buf;
    private String stmp;
    private double temp;
    private boolean IsFocusOn;
    
    RectWaveGuide_State state;
    
    public RectWaveGuideCanvas(RectWaveGuide_State state){
	super();
	IsFocusOn = false;
        this.state = state;
        
	setBackground(bgcolor);
	//Listeners
	this.addMouseListener(this);
        LeftMargin = state.s10; 
        RightMargin = state.s10; 
        TopMargin = state.s10; 
        BottomMargin = state.s10;
        labfont = new Font("SanSerif",Font.PLAIN,state.font10);
        textfont = new Font("SanSerif",Font.PLAIN,state.font10);
        symbolfont = new Font("Serif",Font.PLAIN,state.font12);
        symbolfont2 = new Font("Serif",Font.PLAIN,state.font14);
        
	a_to_b_ratio = 2.22;
	frequency = 10.0E9;
	mu_r = 1.0;
	epsilon_r = 1.0;
	a = 0.02;
	b =a/a_to_b_ratio;
    }

    public void drawCanvas(Graphics g){
	g.clearRect(0,0,getSize().width,getSize().height);
	g.setColor(Color.black);
	
 	if(IsFocusOn){drawBackLabels(g);}
	drawAxis(g);
	drawGuide(g);
    }
    
    private void drawAxis(Graphics g){
        
        Graphics2D g2d = (Graphics2D)g;
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);

        double theta = Math.PI/6.0;
	int ArrowPos1, ArrowPos2;
	int Lsize = state.s30;
        
	g.setColor(Color.gray);
	//Vertical axis
	g.drawLine(LeftMargin,getSize().height-BottomMargin,LeftMargin,getSize().height-BottomMargin-Lsize);
	//MaestroG.drawArrow(LeftMargin,getSize().height-BottomMargin-Lsize,5,g);
        drawArrowScaled( LeftMargin,getSize().height-BottomMargin-Lsize, 1,state.sfactor, g);
	//Horizontal axis
	g.drawLine(LeftMargin,getSize().height-BottomMargin,LeftMargin+Lsize,getSize().height-BottomMargin);
	//Draw up arrow
	//MaestroG.drawArrow(LeftMargin+Lsize,getSize().height-BottomMargin,7,g);
	drawArrowScaled( LeftMargin+Lsize,getSize().height-BottomMargin, 3,state.sfactor, g);
	
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
	//Third axis
		int tipz = -state.s10;
		int verticz = getSize().height-BottomMargin-(int)(Lsize*Math.sin(theta));
		int horizz = LeftMargin+(int)(Lsize*Math.cos(theta));
		g.drawLine(LeftMargin,getSize().height-BottomMargin,horizz - tipz,verticz + tipz);
		   
		//draw oblique arrow head
		Polygon pz = new Polygon();
		pz.addPoint(horizz - tipz,verticz + tipz);
		pz.addPoint(horizz - (tipz + state.s4),verticz +(tipz + state.s6));
		pz.addPoint(horizz - (tipz + state.s7),verticz + (tipz + state.s2));
		g.drawPolygon(pz);
		g.fillPolygon(pz);
	
	g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
        
	//Draw labels for axes
	g.setFont(new Font("SanSerif",Font.PLAIN,state.font12));
	FontMetrics fm = g.getFontMetrics();
	g.drawString("x",LeftMargin-fm.stringWidth("x")/2,getSize().height-BottomMargin-Lsize-state.s10);
	g.drawString("y",LeftMargin+Lsize+10+fm.stringWidth("y"),
		getSize().height-BottomMargin+fm.getHeight()/3);
	g.drawString("z",LeftMargin+(int)(Lsize*Math.cos(theta))+state.s15,getSize().height-BottomMargin-(int)(Lsize*Math.sin(theta))-state.s7);
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_OFF);
    }
    
    private void drawGuide(Graphics g){
	Graphics2D g2d = (Graphics2D)g;
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
        
	int x1, y1, x2, y2;
	//Color MetalColor = Color.lightGray;
	//Color MetalColor2 = new Color(235,235,235);
	//Color MetalColor3 = new Color(225,225,225);
	//Color MetalColor4 = new Color(185,185,185);
	//Color MetalColor5 = new Color(200,200,200);
	//Color MetalColor6 = new Color(150,150,150);
        Color MetalColor2 = new Color(190,140,80);  // Darkest Copper
	Color MetalColor5 = new Color(250,220,180); // Light Copper
	Color MetalColor3 = new Color(210,170,110); // Dark Copper
	Color MetalColor4 = new Color(240,210,170); // Less Light Copper
	Color MetalColor = new Color(255,240,210); // Lightest Copper
	Color MetalColor6 = new Color(220,200,150);  //
        
        double theta = Math.PI/6.0;
	int GuideHeight = getSize().height/2;
	int GuideWidth =  (int)(GuideHeight/a_to_b_ratio);
	int GuideThickness = state.s4;
	int GuideDepth = state.s70;
	int GuideXPos = 17*getSize().width/60;
	int GuideYPos = getSize().height - 3 * BottomMargin - GuideHeight;
	int xPoints[] = new int[4];
	int yPoints[] = new int[4];
	int xPoints2[] = new int[4];
	int yPoints2[] = new int[4];
	
        //External rectangle (front face)
	g.setColor(MetalColor);
	g.fillRect(GuideXPos,GuideYPos,GuideWidth,GuideHeight);
	// border
        g.setColor(MetalColor3);
	g.drawRect(GuideXPos,GuideYPos,GuideWidth,GuideHeight);
	
        //Internal rectangle - dark
	g.setColor(MetalColor2);
	g.fillRect(GuideXPos+GuideThickness, GuideYPos+GuideThickness,GuideWidth-2*GuideThickness,GuideHeight-2*GuideThickness);
	
        // Internal bottom - lighter color
	xPoints2[0] = GuideXPos+GuideThickness;
	xPoints2[1] = GuideXPos + GuideWidth-GuideThickness;
	xPoints2[2] = GuideXPos + GuideWidth-GuideThickness;
	
	yPoints2[0] = GuideYPos - GuideThickness + GuideHeight;
	yPoints2[1] = GuideYPos - GuideThickness + GuideHeight;
	yPoints2[2] = GuideYPos-GuideThickness+GuideHeight-(int)((GuideWidth-2*GuideThickness)*Math.tan(theta));
	
	g.setColor(MetalColor4);
	g.fillPolygon(xPoints2,yPoints2,3);

	g.setColor(MetalColor2);
	g.drawRect(GuideXPos+GuideThickness, GuideYPos+GuideThickness,GuideWidth-2*GuideThickness,GuideHeight-2*GuideThickness);
	//======================================================================
	//Polygons
	//Top side external wall
	
	xPoints[0] = GuideXPos;
	xPoints[1] = GuideXPos + (int)(GuideDepth*Math.cos(theta));
	xPoints[2] = GuideXPos + GuideWidth + (int)(GuideDepth*Math.cos(theta));
	xPoints[3] = GuideXPos + GuideWidth;
	
	yPoints[0] = GuideYPos;
	yPoints[1] = GuideYPos - (int)(GuideDepth*Math.sin(theta));
	yPoints[2] = yPoints[1];
	yPoints[3] = yPoints[0];
	
	g.setColor(MetalColor5);
	g.fillPolygon(xPoints,yPoints,4);
	
	//Right side external wall
	xPoints[0] = GuideXPos + GuideWidth+1;
	xPoints[1] = GuideXPos + +GuideWidth + (int)(GuideDepth*Math.cos(theta));
	xPoints[2] = xPoints[1];
	xPoints[3] = xPoints[0];
	
	yPoints[0] = GuideYPos;
	yPoints[1] = GuideYPos - (int)(GuideDepth*Math.sin(theta));
	yPoints[2] = yPoints[1] + GuideHeight;
	yPoints[3] = yPoints[0] + GuideHeight;
	
	g.setColor(MetalColor3);
	g.fillPolygon(xPoints,yPoints,4);
	
	//lines
	g.setColor(MetalColor6);
	//Top Left
	g.drawLine(GuideXPos,GuideYPos,GuideXPos+(int)(GuideDepth*Math.cos(theta)),GuideYPos-(int)(GuideDepth*Math.sin(theta)));
	//Top Right
	g.setColor(MetalColor3);
        g.drawLine(GuideXPos+GuideWidth,GuideYPos,GuideXPos+GuideWidth+(int)(GuideDepth*Math.cos(theta)),GuideYPos-(int)(GuideDepth*Math.sin(theta)));
	//Bottom Right
	g.drawLine(GuideXPos+GuideWidth,GuideYPos+GuideHeight,GuideXPos+GuideWidth+(int)(GuideDepth*Math.cos(theta)),GuideYPos+GuideHeight-(int)(GuideDepth*Math.sin(theta)));
	//Bottom Left, and Internal
	g.drawLine(GuideXPos+GuideThickness,GuideYPos+GuideHeight-GuideThickness,
	   GuideXPos+GuideThickness+(int)(GuideWidth-2*GuideThickness),
	   GuideYPos-GuideThickness+GuideHeight-(int)((GuideWidth-2*GuideThickness)*Math.tan(theta)));
	g.setColor(Color.red);
	//draw arrows and labels around the waveguide
	//vertical line
	g.drawLine(GuideXPos-LeftMargin,GuideYPos+10,GuideXPos-LeftMargin,GuideYPos+GuideHeight-state.s10);
	//up arrow
	//MaestroG.drawArrow(GuideXPos-LeftMargin,GuideYPos+10+GuideThickness,5,g);
        drawArrowScaled( GuideXPos-LeftMargin,GuideYPos+state.s10+GuideThickness, 1,state.sfactor, g);
	
	//draw down arrow
	//MaestroG.drawArrow(GuideXPos-LeftMargin,GuideYPos+GuideHeight-10-GuideThickness,6,g);
	drawArrowScaled( GuideXPos-LeftMargin,GuideYPos+GuideHeight-state.s10-GuideThickness, 2,state.sfactor, g);
	
        g.setFont(new Font("SanSerif",Font.BOLD,state.font12));
        g.drawString("a",GuideXPos-2*LeftMargin,GuideYPos+GuideHeight/2+state.s4);
        
	g.drawLine(GuideXPos-state.s15,GuideYPos+GuideThickness,GuideXPos-state.s5,GuideYPos+GuideThickness);
	g.drawLine(GuideXPos-state.s15,GuideYPos+GuideHeight-GuideThickness,GuideXPos-state.s5,GuideYPos+GuideHeight-GuideThickness);
	g.drawLine(GuideXPos+GuideThickness,GuideYPos+GuideHeight+state.s5,
		   GuideXPos+GuideThickness,GuideYPos+GuideHeight+state.s15);
	g.drawLine(GuideXPos+GuideWidth-GuideThickness,GuideYPos+GuideHeight+state.s5,
		   GuideXPos+GuideWidth-GuideThickness,GuideYPos+GuideHeight+state.s15);
	
	if(a_to_b_ratio < 2.5){
	    //horizontal line
	    g.drawLine(GuideXPos+state.s10,GuideYPos+GuideHeight+BottomMargin,GuideXPos+GuideWidth-state.s10,GuideYPos+GuideHeight+BottomMargin);
	    //draw right arrow
	    //MaestroG.drawArrow(GuideXPos+GuideWidth-state.s10-GuideThickness,GuideYPos+GuideHeight+BottomMargin,7,g);
            drawArrowScaled( GuideXPos+GuideWidth-state.s10-GuideThickness,GuideYPos+GuideHeight+BottomMargin, 3,state.sfactor, g);
	
	    //draw left arrow
	    //MaestroG.drawArrow(GuideXPos+state.s10+GuideThickness,GuideYPos+GuideHeight+BottomMargin,8,g);
            drawArrowScaled( GuideXPos+state.s10+GuideThickness,GuideYPos+GuideHeight+BottomMargin, 4,state.sfactor, g);
            
	    g.drawString("b",GuideXPos+GuideWidth/2-state.s3,GuideYPos+GuideHeight+2*BottomMargin+state.s4);
	}
	else{
	    //horizontal line
	    g.drawLine(GuideXPos-state.s10,GuideYPos+GuideHeight+BottomMargin,GuideXPos+GuideWidth+state.s10,GuideYPos+GuideHeight+BottomMargin);
	    //draw right arrow
	    //MaestroG.drawArrow(GuideXPos+GuideWidth+state.s5,GuideYPos+GuideHeight+BottomMargin,8,g);
            drawArrowScaled( GuideXPos+GuideWidth+state.s5,GuideYPos+GuideHeight+BottomMargin, 4,state.sfactor, g);
            
	    //draw left arrow
	    //MaestroG.drawArrow(GuideXPos-state.s5,GuideYPos+GuideHeight+BottomMargin,7,g);	
	    drawArrowScaled( GuideXPos-state.s5,GuideYPos+GuideHeight+BottomMargin, 3,state.sfactor, g);
            
            g.drawString("b",GuideXPos+GuideWidth/2-state.s3,GuideYPos+GuideHeight+2*BottomMargin+state.s7); 
	}
        
        g.setFont(new Font("SanSerif",Font.PLAIN,state.font12));
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
        
	g.setColor(Color.black);
	int x =state.s130;
	int y = state.s58;
	
	g.drawString("    a = "+MaestroA.rounder(a,5)+" [ m ]",x,y);	
	y= state.s75;
	g.drawString("    b = "+MaestroA.rounder(a/a_to_b_ratio,5)+" [ m ]",x,y);	
	x = state.s180;
	y = state.s15;
	
        double f_normalized;
	if(frequency < 1.0E3){
		    f_normalized = frequency;
		    MaestroG.subscripterSer5("","f",""," =  "+MaestroA.rounder(f_normalized,3)+" Hz",g,state.font12,x,y);	
		}
		else if(frequency < 1.0E6 && frequency >= 1.0E3  ){
		    f_normalized = frequency/1.0E3;
		    MaestroG.subscripterSer5("","f",""," =  "+MaestroA.rounder(f_normalized,3)+" kHz",g,state.font12,x,y);	
		}
		else if(frequency < 1.0E9 && frequency >= 1.0E6 ){
		    f_normalized = frequency/1.0E6;
		    MaestroG.subscripterSer5("","f",""," =  "+MaestroA.rounder(f_normalized,3)+" MHz",g,state.font12,x,y);	
		}
		else if(frequency < 1.0E12 && frequency >= 1.0E9 ){
		    f_normalized = frequency/1.0E9;
		    MaestroG.subscripterSer5("","f",""," =  "+MaestroA.rounder(f_normalized,3)+" GHz",g,state.font12,x,y);	
		}
		else if(frequency < 1.0E15 && frequency >= 1.0E12 ){
		    f_normalized = frequency/1.0E12;
		    MaestroG.subscripterSer5("","f",""," =  "+MaestroA.rounder(f_normalized,3)+" THz",g,state.font12,x,y);	
		}
		else{
		    f_normalized = frequency/1.0E12;
		    MaestroG.subscripterSer5("","f",""," =  "+MaestroA.rounder(f_normalized,3)+" THz",g,state.font12,x,y);	
		}
		
		g.setFont(symbolfont2);
		MaestroG.subscripterSer2("\u03b5","r"," = "+MaestroA.rounder(epsilon_r,4),g,state.font12,state.s5,state.s45);
		MaestroG.subscripterSer2("\u03bc","r"," = "+MaestroA.rounder(mu_r,4),g,state.font12,state.s3,state.s60);
		g.setFont(textfont);
		
		phase_velocity = 1.0/Math.sqrt(epsilon0*mu0*epsilon_r*mu_r);
		phase_velocity0 = 1.0/Math.sqrt(epsilon0*mu0);
		
		if(frequency<1.0E3){
		    MaestroG.superscripterk("| k |"," = "+MaestroA.rounder(2.0*Math.PI*frequency/phase_velocity,9)+" [ m","-1"," ]",g,state.font12,state.s5,state.s15);
		}
		else if(frequency<1.0E6 && frequency>=1.0E3){
		    MaestroG.superscripterk("| k |"," = "+MaestroA.rounder(2.0*Math.PI*frequency/phase_velocity,6)+" [ m","-1"," ]",g,state.font12,state.s5,state.s15);
		}
		else if(frequency<1.0E9 && frequency>=1.0E6){
		    MaestroG.superscripterk("| k |"," = "+MaestroA.rounder(2.0*Math.PI*frequency/phase_velocity,5)+" [ m","-1"," ]",g,state.font12,state.s5,state.s15);
		}
		else if(frequency<30.0E9 && frequency>=1.0E9){
		    MaestroG.superscripterk("| k |"," = "+MaestroA.rounder(2.0*Math.PI*frequency/phase_velocity,4)+" [ m","-1"," ]",g,state.font12,state.s5,state.s15);
		}
		else if(frequency<3.0E12 && frequency>= 30.0E9){
		    MaestroG.superscripterk("| k |"," = "+MaestroA.rounder(2.0*Math.PI*frequency/phase_velocity/1.0E3,4)+" [ mm","-1"," ]",g,state.font12,state.s5,state.s15);
		}
		else if(frequency<3.0E15 && frequency>= 3.0E12){
		    MaestroG.superscripterk("| k |"," = "+MaestroA.rounder(2.0*Math.PI*frequency/phase_velocity/1.0E6,4)+" [ \u03bcm","-1"," ]",g,state.font12,state.s5,state.s15);
		}
		else if(frequency>= 3.0E15){
		    MaestroG.superscripterk("| k |"," = "+MaestroA.rounder(2.0*Math.PI*frequency/phase_velocity/1.0E9,4)+" [ nm","-1"," ]",g,state.font12,state.s5,state.s15);
		}
		g.setFont(textfont);
		
		if(frequency == 0.0){
		    MaestroG.subscripter("    ",""," =      ",g,state.font12,state.s5,state.s30);
		    g.setFont(symbolfont2);
		    g.drawString("  \u221e",state.s30,state.s30);
		    g.setFont(labfont);
		}
		else if(frequency < 1.0E3){
		    temp = phase_velocity/frequency/1.0E6;
		    MaestroG.subscripter("    ",""," = "+MaestroA.rounder(temp,3)+" [ 1,000 km ]",g,state.font12,state.s5,state.s30);
		}
		else if(frequency < 1.0E6 && frequency >= 1.0E3){
		    temp = phase_velocity/frequency/1.0E3;
		    MaestroG.subscripter("    ",""," = "+MaestroA.rounder(temp,4)+" [ km ]",g,state.font12,state.s5,state.s30);
		}
		else if(frequency < 1.0E9 && frequency >= 1.0E6){
		    MaestroG.subscripter("    ",""," = "+MaestroA.rounder(phase_velocity/frequency,3)+" [ m ]",g,state.font12,state.s5,state.s30);
		}
		else if(frequency <30.0E9 && frequency>= 1.0E9){
		    MaestroG.subscripter("    ",""," = "+MaestroA.rounder(phase_velocity/frequency,6)+" [ m ]",g,state.font12,state.s5,state.s30);
		}
		else if(frequency<3.0E12 && frequency>= 30.0E9){
		    temp = phase_velocity/frequency*1.0E3;
		    MaestroG.subscripter("    ",""," = "+MaestroA.rounder(temp,4)+" [ mm ]",g,state.font12,state.s5,state.s30);
		}
		else if(frequency < 3.0E15 &&frequency>=3.0E12 ){
		    temp = phase_velocity/frequency*1.0E6;
		    MaestroG.subscripter("    ",""," = "+MaestroA.rounder(temp,4)+" [ \u03bc m ]",g,state.font12,state.s5,state.s30);
		}
		else if(frequency>=3.0E15 ){
		    temp = phase_velocity/frequency*1.0E9;
		    MaestroG.subscripter("    ",""," = "+MaestroA.rounder(temp,4)+" [ nm ]",g,state.font12,state.s5,state.s30);
		}
                if(epsilon_r == 1.0 && mu_r == 1.0){
                    MaestroG.subscripterSer("\u03bb","0","",g,state.font12,state.s6,state.s30);
                }
                else{
                    g.setFont(symbolfont2);
                    g.drawString("\u03bb",state.s10,state.s30);
                    g.setFont(textfont);
                }
    }
    
    public void drawArrowScaled(int x, int y, int tipo, double sfactor, Graphics g){
	Graphics2D g2d = (Graphics2D)g;
        double s;
        s = sfactor;
        
        switch (tipo){
	   
          case 1://ArrowUpSmooth
               g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
        
                g.drawLine(x,y-1,x,y+(int)(s*5));
		//draw oblique arrow head
		Polygon pH = new Polygon();
		pH.addPoint(x-(int)(s*2), y-(int)(s*2));
		pH.addPoint(x+(int)(s*2), y-(int)(s*2));
		pH.addPoint(x,y-(int)(s*8));
		g.drawPolygon(pH);
		g.fillPolygon(pH);
                
                g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_OFF);
        
          break;
          
          case 2://ArrowDownSmooth
               g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
        
                g.drawLine(x,y+1,x,y-(int)(s*5));
		//draw oblique arrow head
		Polygon pJ = new Polygon();
		pJ.addPoint(x-(int)(s*2), y+(int)(s*2));
		pJ.addPoint(x+(int)(s*2), y+(int)(s*2));
		pJ.addPoint(x,y+(int)(s*8));
		g.drawPolygon(pJ);
		g.fillPolygon(pJ);
                
                g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_OFF);
	   break;
           
           case 3://ArrowRightSmooth
               g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
        
                g.drawLine(x+1,y,x-(int)(s*5),y);
		//draw oblique arrow head
		Polygon pK = new Polygon();
		pK.addPoint(x+(int)(s*2), y-(int)(s*2));
		pK.addPoint(x+(int)(s*2), y+(int)(s*2));
		pK.addPoint(x+(int)(s*8),y);
		g.drawPolygon(pK);
		g.fillPolygon(pK);
                
                g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_OFF);
	   
	   break;
           
           case 4://ArrowLeftSmooth
               g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
        
                g.drawLine(x-1,y,x+(int)(s*5),y);
		//draw oblique arrow head
		Polygon pL = new Polygon();
		pL.addPoint(x-(int)(s*2), y-(int)(s*2));
		pL.addPoint(x-(int)(s*2), y+(int)(s*2));
		pL.addPoint(x-(int)(s*8),y);
		g.drawPolygon(pL);
		g.fillPolygon(pL);
                
                g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_OFF);
 
	   break;
           
           case 5://ArrowOblique 45 degrees pointing NE
                g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
        
		//draw oblique arrow head
		Polygon pM = new Polygon();
                
                pM.addPoint(x+(int)(s*6),y-(int)(s*6)); // longer arrow
		pM.addPoint(x+(int)(s*1),y-(int)(s*3));
		pM.addPoint(x+(int)(s*2),y+(int)(s*1));
		
                g.drawPolygon(pM);
		g.fillPolygon(pM);
                
                g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_OFF);
                 
           break;
           
           case 6://ArrowOblique 45 degrees pointing SW
                g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
        
		//draw oblique arrow head
		Polygon pN = new Polygon();
                
                pN.addPoint(x-(int)(s*6),y+(int)(s*6)); 
		pN.addPoint(x-(int)(s*1),y+(int)(s*3));
		pN.addPoint(x-(int)(s*2),y-(int)(s*2));
		
                g.drawPolygon(pN);
		g.fillPolygon(pN);
                
                g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_OFF);
                 
           break;
           
           case 7://Larger ArrowRightSmooth
               g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
        
                Polygon pR = new Polygon();
		pR.addPoint(x, y-(int)(s*3));
		pR.addPoint(x, y+(int)(s*3));
		pR.addPoint(x+(int)(s*7),y);
		g.drawPolygon(pR);
		g.fillPolygon(pR);
                
                g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_OFF);
	   
	   break;
           
           case 8://Larger ArrowLeftSmooth
               g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
        
                Polygon pS = new Polygon();
		pS.addPoint(x, y-(int)(s*3));
		pS.addPoint(x, y+(int)(s*3));
		pS.addPoint(x-(int)(s*7),y);
		g.drawPolygon(pS);
		g.fillPolygon(pS);
                
                g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_OFF);
 
	   break;
           
           case 9://ArrowUpSmooth
               g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
        
                Polygon pU = new Polygon();
		pU.addPoint(x-(int)(s*3), y);
		pU.addPoint(x+(int)(s*3), y);
		pU.addPoint(x,y-(int)(s*7));
		g.drawPolygon(pU);
		g.fillPolygon(pU);
                
                g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_OFF);
        
          break;
          
          case 10://ArrowDownSmooth
               g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
        
                Polygon pD = new Polygon();
                pD.addPoint(x-(int)(s*3), y);
		pD.addPoint(x+(int)(s*3), y);
		pD.addPoint(x,y+(int)(s*7));
		g.drawPolygon(pD);
		g.fillPolygon(pD);
                
                g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_OFF);
	   break;
	}		
    }

    
    public synchronized void setRatio(double a_to_b_ratio){
	this.a_to_b_ratio = a_to_b_ratio;
	repaint();
    }
    
    public synchronized void setFrequency(double frequency){
	this.frequency = frequency;
    }
    
    public synchronized void setWidth(double width){
	this.a = width;
    }
    
    public synchronized void setEpsilon(double epsilon){
	this.epsilon_r = epsilon;
	
    }
    
    public synchronized void setMu(double mu){
	this.mu_r = mu;
    }
    
    
    private void drawLabels(Graphics g){
	
    }
    
    private void drawBackLabels(Graphics g){
	
    }
    
    private void drawMedium(Graphics g){
	
    }
    
    private void drawWaves(Graphics g){
	
    }
    
    public void paint(Graphics g){
	    if(im == null){
		im = createImage(getSize().width,getSize().height);
		buf = im.getGraphics();
		drawCanvas(buf);
	    }
	    else{
		drawCanvas(buf);
	    }
	    g.drawImage(im,0,0,null);
    }
    
    
    public void update(Graphics g){
	paint(g);
    }
    
    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){}
}
