/**
 * TransGraphCanvas2.java
 * Graphs specific for the transmission lines
 */
/* A Java class for
 * LossyWide.java
 * Electromagnetic Transmission Line Applet
 * Applet without Smith Chart - Prepared by Umberto Ravaioli 
 * for 6th edition of Fundamentals of Applied Electromagnetics Book
 * May 2009 - All Rights Reserved
 */ 

import java.awt.*;
import java.awt.geom.*;
import java.awt.image.*;
import java.net.*;
import java.awt.event.*;
import java.lang.*;

public class TransGraphCanvas2 extends Canvas implements ComponentListener{
    
    private static final Color bgcolor = new Color(246,246,246); 
    //private static final Color bgcolor = new Color(236,236,221); 
    private static final Color maroon = new Color(185,50,50);
       
    private double ymax, ymin, xmax, xmin;
    private boolean IsYRangeMaxSet, IsYRangeMinSet, IsXRangeMaxSet, IsXRangeMinSet; 
    //private int LeftMargin=30, RightMargin=30, TopMargin=20, BottomMargin=20;
    private int LeftMargin=65, RightMargin=35, TopMargin=20, BottomMargin=20;
    private int WIDTH, HEIGHT;
    private String X1, X2, Y1, Y2, Y3, Y4, TITLE, UNITS, LABELY, VALUE;
    private Image im;
    private Graphics buf;
    private int VPos = 0;
    private int Flag;
    //private static final Font TitleFontSe = new Font("Serif",Font.PLAIN,13);
    //private static final Font LabelFont = new Font("SanSerif",Font.PLAIN,11);
    //private static final Font LabelFontIT2 = new Font("Serif",Font.ITALIC,16);
    //private static final Font LabelFontITsmall = new Font("Serif",Font.ITALIC,13);
    public static  Font TitleFontSe;
    public static  Font LabelFont;
    public static  Font LabelFontIT2;
    public static  Font LabelFontITsmall;
    private double[] x, y, ySWP, ySWPmin;
    protected double xpos, xposref;
    protected int tx1;
    private int[] xx, yy, yySWP, yySWPmin;
    private int[] xx_old, yy_old;
    private int N;
    private int lab_flag = 1;
    private boolean IsTraceOn, IsCleanUpOn, IsDynamic, IsBackDark, IsEnvelope;
    public TransGraphCanvas2(){
	super();
	N = 301;
	tx1 = getSize().width - RightMargin;
	xpos = 0.0;
	xposref = 0.0;
	Flag = 0;
	setBackground(bgcolor);
	xmax = 1.0;
	xmin = 0.0;
	ymax = 2.0;
	ymin = -2.0;
	X1 = "l";
	X2 = "0";
	Y1 = "  ";
	Y2 = "  ";
	TITLE = "  ";
	UNITS = "  ";
	LABELY = "   ";
	VALUE = "   ";
	
	IsBackDark = false;
	
	IsYRangeMaxSet = false;
	IsYRangeMinSet = false;
	IsXRangeMaxSet = false;
	IsXRangeMinSet = false;
	IsTraceOn = false;
	IsCleanUpOn = false;
	IsDynamic = false;
        IsEnvelope = true;
	try{
	    x = new double[N];
	    y = new double[N];
            ySWP = new double[N];
            ySWPmin = new double[N];
            xx = new int[N];
	    yy = new int[N];
            yySWP = new int[N];
            yySWPmin = new int[N];
            
	    xx_old = new int[N];
	    yy_old = new int[N];
	}
	catch(Exception e){e.printStackTrace();}
	for(int i = 0; i < x.length; i++){
	    x[i] = (double)i;
	    y[i] = 0.0;
            ySWP[i] = 0.0;
            ySWPmin[i] = 0.0;
        }
	//Listeners
	this.addComponentListener(this);
    }
    
    public void paint(Graphics g){
	if(im == null){
	    im = createImage(getSize().width,getSize().height);
	    buf = im.getGraphics();
	    drawGraph(buf);
	}
	else{
	 drawGraph(buf);
	}
	g.drawImage(im,0,0,null);
    }
    
    public void drawGraph(Graphics g){
	
	if(!IsDynamic){
	    g.clearRect(0,0,getSize().width-1,getSize().height-1);
	}
        
	drawAxis(g);
	labelDetect();
	drawLabels(g);
	drawZeroLine(g);
	drawPoints(g,1);
        drawAxis(g);
	drawRef(g);
	
    }
    
    private void ignition(){
	N = x.length;
	//Find the boundaries for data
    	if(!IsYRangeMaxSet){ ymax = MaestroA.getMax(y);}
	if(!IsYRangeMinSet){ ymin = MaestroA.getMin(y);}
	
	if(!IsXRangeMaxSet){ xmax = x[x.length-1];}
	if(!IsXRangeMinSet){ xmin = x[0]; }
	
	//Confine data
	MaestroA.confiner(x,xmax,xmin);
	MaestroA.confiner(y,ymax,ymin);
	if(ymax==0.0 && ymin==0.0){ymax=0.001;}
	
	//Reverse Mapping
	for(int i = 0; i < xx.length; i++){
	    xx[N-1-i] = (int)MaestroA.mapper(x[i],(double)LeftMargin+1,(double)(getSize().width-RightMargin),xmax,xmin);
	    yy[N-1-i] = (int)MaestroA.mapper(y[i],(double)TopMargin+1,(double)(getSize().height-BottomMargin)-1,ymax,ymin);
	    yySWP[N-1-i] = (int)MaestroA.mapper(ySWP[i],(double)TopMargin+1,(double)(getSize().height-BottomMargin)-1,ymax,ymin);
	    yySWPmin[N-1-i] = (int)MaestroA.mapper(ySWPmin[i],(double)TopMargin+1,(double)(getSize().height-BottomMargin)-1,ymax,ymin);
	    
            //yy_old[N-1-i]=yy[N-1-i];
	}
        
    }
    
    private void drawPoints(Graphics g, int tipo){
        Graphics2D g2d = (Graphics2D)g;
        //g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);

	switch(tipo){
	    case 1:
                    // draw envelope (top part is standing wave pattern)
                if(IsEnvelope){
                    g.setColor(Color.magenta);
                    g.drawPolyline(xx,yySWP,xx.length);
                    g.drawPolyline(xx,yySWPmin,xx.length);
                }
                if(IsTraceOn){
		    //g.setColor(Color.white);
                   
                    g.setColor(Color.lightGray);
                    g.setColor(new Color(220,220,220));
		    g.drawPolyline(xx_old,yy_old,xx_old.length);
                    
                    if(IsEnvelope){
                        g.setColor(Color.magenta);
                        g.drawPolyline(xx,yySWP,xx.length);
                        g.drawPolyline(xx,yySWPmin,xx.length);
                    }
                    
                    //g.setColor(Color.black);
		    g.setColor(Color.blue);
		    g.drawPolyline(xx,yy,xx.length);
                    drawZeroLine(g);
                    
                    
		}
		else{
                    // draw envelope
                    if(IsEnvelope){
                        g.setColor(Color.magenta);
                        g.drawPolyline(xx,yySWP,xx.length);
                        g.drawPolyline(xx,yySWPmin,xx.length);
                    }
                    // draw time dependent function
                    g.setColor(Color.blue);
		    g.drawPolyline(xx,yy,xx.length);
                    drawZeroLine(g);
		    //g.setColor(Color.red);
		    //MaestroG.drawCircle(tx1,yy[(int)(N*xposref/(xmax-xmin))],8,g);
		}
	                
		break;
	    case 2:
		g.setColor(bgcolor);
		g.drawPolyline(xx_old,yy_old,xx_old.length);
                drawZeroLine(g);
                
                
		break;
	}
    }
       
    private void drawAxis(Graphics g){
        
	VPos = getSize().height - BottomMargin;
	WIDTH = getSize().width - LeftMargin -RightMargin;
	HEIGHT = VPos - TopMargin;
	g.setColor(Color.black);
	
        g.drawLine(LeftMargin-5,VPos,getSize().width-RightMargin+5,VPos);
	g.drawLine(LeftMargin,TopMargin,LeftMargin,VPos+5);
	g.drawLine(getSize().width-RightMargin,TopMargin,getSize().width-RightMargin,VPos+5);
	g.drawLine(LeftMargin,TopMargin,LeftMargin-5,TopMargin);
        g.drawLine(getSize().width-RightMargin,TopMargin,getSize().width-RightMargin+5,TopMargin);
	
    }
    
    private void labelDetect(){
    
	double tempmax=0.0;
	if(ymax>=1.0 && ymax<1.0E3 || ymax==0.0){
	    tempmax = ymax;
	}
	else if(ymax<1.0E6 && ymax>=1.0e3){
	    tempmax = ymax*1.0E-3;
	}
	else if(ymax>=1.0e6){
	    tempmax = ymax*1.0E-6;
	}
	else if(ymax<1.0 && ymax>=1.0e-3){
	    tempmax = ymax*1.0E3;
	}
	else if(ymax<1.0E-3 && ymax>=1.0e-6){
	    tempmax = ymax*1.0E6;
	}
	else if(ymax<1.0E-6 && ymax>=1.0e-9){
	    tempmax = ymax*1.0E9;
	}
	else if(ymax<1.0E-9 && ymax>=1.0E-12){
	    tempmax = ymax*1.0E12;
	}
	else if(ymax<1.0E-12 && ymax>=1.0E-15){
	    tempmax = ymax*1.0E15;
	}
	else if(ymax<1.0E-15){
	    tempmax = ymax*1.0E18;
	}
	
	    Y1 = String.valueOf(MaestroA.rounder(tempmax,3))+" ";
	
	if(ymin==0.0){
	    Y2 = String.valueOf(MaestroA.rounder(ymin,3))+" ";
	}
	else{
	    Y2 = String.valueOf(MaestroA.rounder(-tempmax,3))+" ";
	}
	Y3 = "_";
	Y4 = "|";

    }
    
    private void drawLabels(Graphics g){
        Graphics2D g2d = (Graphics2D)g;
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
	
	g.setColor(Color.black);
        
        String tmp;
	FontMetrics fm;
        
	g.clearRect(0,0,LeftMargin-1,getSize().height-1);
	g.clearRect(0,0,getSize().width-1,TopMargin-1);
	
        g.setFont(LabelFontIT2);
        fm = g.getFontMetrics();
	tmp = X1;
	g.drawString(tmp,LeftMargin+3,getSize().height-3);
	
        g.setFont(LabelFont);
        fm = g.getFontMetrics();
	
        g.drawString("0.0",40,getSize().height/2);
        
	tmp = X2;
	g.drawString(tmp,getSize().width-RightMargin-fm.stringWidth(tmp)/2+1,VPos+fm.getHeight()+2);
	tmp = Y1;
	//g.drawString(tmp,LeftMargin-fm.stringWidth(tmp),TopMargin+fm.getHeight());
	g.drawString(tmp,LeftMargin-fm.stringWidth(tmp)-10,TopMargin);
	tmp = Y2;
	g.drawString(tmp,LeftMargin-fm.stringWidth(tmp)-10,VPos);
	
	//tmp = Y3;
        //g.drawString(tmp,LeftMargin-5,getSize().height/2-1);
	//g.drawString(tmp,LeftMargin-5,VPos-1);
	//g.drawString(tmp,LeftMargin-5, TopMargin);
	//g.drawString(tmp,getSize().width - RightMargin,VPos-1);
	//g.drawString(tmp,getSize().width - RightMargin,TopMargin);
	
	//tmp = Y4;
	//g.drawString(tmp,LeftMargin,VPos+4);
	//g.drawString(tmp,getSize().width-RightMargin-fm.stringWidth(tmp)/2+1,VPos+4);
	
        tmp = LABELY;
	g.setFont(LabelFontITsmall);
        //g.drawString(tmp,getSize().width-RightMargin-fm.stringWidth(tmp),TopMargin-5);
	
	//tmp = TITLE;
	//g.setFont(TitleFontSe);
	//g.drawString(tmp,10,getSize().height/3-25);
	
        //-------------------------------------------------------------------
        // New code for plot label with book's conventions
        //-------------------------------------------------------------------
        
        String alpha, Ohm, lambda, infinity, Gamma;
	    
	    alpha="\u03b1";
	    lambda="\u03bb";
	    Ohm="\u03a9";
	    infinity="\u221e";
	    Gamma="\uu0393";
	    
        int newx, newy;
        newx = 8; newy = 2*getSize().height/9;
        if(lab_flag == 1){
            MaestroG.subscripterIT2("v","","( d, t )",g,12,newx,newy);
            tmp = LABELY; 
            //MaestroG.subscripterSpecialSubSupSub("2 |V","o","+","| exp ("+alpha,"l",")","","",g,12,getSize().width-RightMargin-fm.stringWidth(tmp)-5,TopMargin-5);
            MaestroG.subscripterSpecialSubSupSub("2 |V","o","+","|","","","",
               "",g,12,getSize().width-RightMargin-fm.stringWidth(tmp)-5,TopMargin-5); 
        }
        else if(lab_flag == 2){
            MaestroG.subscripterIT2("i","","( d, t )",g,12,newx,newy);
            //MaestroG.subscripterSpecialSubSupSub("2 |V","o","+","| exp ("+alpha,"l",")/ Z","0","",g,12,getSize().width-RightMargin-fm.stringWidth(tmp)-5,TopMargin-5);
            MaestroG.subscripterSpecialSubSupSub("2 |V","o","+","|","","/ Z",
           "0","",g,12,getSize().width-RightMargin-fm.stringWidth(tmp)-5,TopMargin-5);
        }
        else if(lab_flag == 3){
            MaestroG.subscripterIT2("p","","( d, t )",g,11,newx,newy);
            //MaestroG.subscripterSpecialSubSupSub("|V","o","+","|\u00b2 exp (2 "+alpha,"l",")/ Z","0","",g,12,getSize().width-RightMargin-fm.stringWidth(tmp)-5,TopMargin-5);
            MaestroG.subscripterSpecialSubSupSub("|V","o","+","|\u00b2","",
              "/ Z","0","",g,12,getSize().width-RightMargin-fm.stringWidth(tmp)-5,TopMargin-5);
        }
	//------------------------------------------------------------------
        
        //System.out.println(lab_flag);
        
        g.setFont(TitleFontSe);
	tmp = UNITS;
	g.drawString(tmp,10,getSize().height/3);
	 
	tmp = VALUE;
        if (VALUE.trim().length() >= 4) {
        //System.out.println("2 VALUE = '"+VALUE+"'");
        //System.out.println("2 VALUE.substring(3,4) = "+VALUE.substring(3,4));
	//g.drawString(tmp,getSize().width/2-fm.stringWidth(tmp),TopMargin-5);
        if (VALUE.substring(3,4).equals("I")) 
            tmp = VALUE.substring(0,4)+"(d)"+VALUE.substring(4);
	g.drawString(tmp,4*getSize().width/10-200,TopMargin-7);
	}
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
        g.setColor(Color.green);
	MaestroG.fillCircle(4*getSize().width/10-210,TopMargin-12,6,g);
	g.setColor(Color.black);
	MaestroG.drawCircle(4*getSize().width/10-210,TopMargin-12,6,g);	
	g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_OFF);
	
    }
    
    private void drawZeroLine(Graphics g){
	int myY;
	myY = (int)MaestroA.mapper(0,(double)TopMargin,(double)VPos,ymax,ymin);
	g.setColor(Color.red);
	g.drawLine(LeftMargin+1,myY,getSize().width-RightMargin-1,myY);
    }
    
    public void drawRef(Graphics g){
	  
	  if(!IsDynamic){
	    xposref = xpos;
	  } 
   	  if(xposref <=xmax && xposref >= xmin){
		int ty1, tx2, ty2;
		tx1 = (int)MaestroA.mapper(xposref,(double)LeftMargin+1,(double)(getSize().width-RightMargin),xmax,xmin);
		ty1 = TopMargin;
		tx2 = tx1;
		ty2 = getSize().height-BottomMargin;
		if(xposref == 0.0){
		    g.setColor(Color.green);
		}
		else{		    
		    g.setColor(Color.green);		    
		}
		g.drawLine(tx1,ty1,tx2,ty2);
          }
    }	

    public synchronized void reset(){
	IsYRangeMaxSet = false;
	IsYRangeMinSet = false;
	IsXRangeMaxSet = false;
	IsXRangeMinSet = false;
	IsTraceOn = false;
	IsCleanUpOn = false;
    }
    
    public synchronized void cleanUp(){
	IsCleanUpOn=true;
    }
    
    public synchronized void setYRangeMax(double ymax){
	this.ymax = ymax;
	IsYRangeMaxSet = true;
    }
    
    public synchronized void setYRangeMin(double ymin){
	this.ymin = ymin;
	IsYRangeMinSet = true;
    }
    
    public synchronized void setXRangeMax(double xmax){
	this.xmax = xmax;
	IsXRangeMaxSet = true;
    }
    
    public synchronized void setXRangeMin(double xmin){
	this.xmin = xmin;
	IsXRangeMinSet = true;
    }
    
    public synchronized void setTrace(boolean IsTraceOn){
	this.IsTraceOn = IsTraceOn;
	this.clean_memory();
    }
    
    public synchronized void setDynamics(boolean IsDynamic){
	this.IsDynamic = IsDynamic;
    }
    

    public void update(Graphics g){
	if(!IsDynamic){
            paint(g);
	    //super.update(g);
	    //return;
	}
	if(IsDynamic && IsTraceOn){g.clipRect(LeftMargin+1,TopMargin+1,WIDTH-1,HEIGHT-1);}
	if(IsCleanUpOn){
	    //g.clearRect(0,0,getSize().width-1,getSize().height-1);
	    g.clearRect(LeftMargin+1,TopMargin+1,WIDTH-1,HEIGHT-1);
	    IsCleanUpOn = false;
	}
	drawZeroLine(g);
	if(!IsTraceOn){
	    drawPoints(g,2);//This cleans the previous graph
	}
	drawPoints(g,1);//This draws the new graph
	drawRef(g);

	push();
    }
    
    public void plot(double xdata[], double ydata[], double ySWPdata[], double ySWPmindata[]){
	N = xdata.length;
	x = new double[N];
	y = new double[N];
        ySWP = new double[N];
        ySWPmin = new double[N];
        xx = new int[N];
	yy = new int[N];
	for(int i = 0; i < N; i++){
	    x[i] = xdata[i];
	    y[i] = ydata[i];
            ySWP[i] = ySWPdata[i];
            ySWPmin[i] = ySWPmindata[i];
        }
	ignition();
	repaint();
    }
    
    private void push(){
	if(xx.length != xx_old.length){
	    xx_old = new int[xx.length];
	    yy_old = new int[xx.length];
	}
    
	for(int i = 0; i < xx.length; i++){
	    xx_old[i] = xx[i];
	    yy_old[i] = yy[i];
	}
    }
    
     private void clean_memory(){
	if(xx.length != xx_old.length){
	    xx_old = new int[xx.length];
	    yy_old = new int[xx.length];
	}
    
	for(int i = 0; i < xx.length; i++){
	    xx_old[i] = xx[i];
	    yy_old[i] = 1000;
	}
    }
    
    public synchronized void setTitle(String TITLE){
	this.TITLE = TITLE;
    }
    
    public synchronized void setUnits(String UNITS){
	this.UNITS = UNITS;
    }
    
    public synchronized void setLabelY(String LABELY){
	this.LABELY = LABELY;
    }
    
    public synchronized void setLabFlag(int number){
	this.lab_flag = number;
    }
    
    public synchronized void setValue(String VALUE){
	this.VALUE = VALUE;
    }

     public synchronized void setEnvelope(boolean IsEnvelope){
	this.IsEnvelope = IsEnvelope;
    }
     
    public void setXpos(double xpos){
	this.xpos = xpos;   
    }

    
    public synchronized void setFlag(int number){
	this.Flag = number;
    }
    
    public void componentHidden(ComponentEvent evt){/*cleanUp();*/}
    public void componentMoved(ComponentEvent evt){/*cleanUp();*/}
    public void componentResized(ComponentEvent evt){/*cleanUp();*/}
    public void componentShown(ComponentEvent evt){/*cleanUp();*/}
     
}
