/**
 * TransGraphCanvas2.java
 * Graphs specific for the transmission lines
 */

import java.awt.*;
import java.awt.event.*;
import java.applet.*;
import java.lang.*;


public class TransGraphCanvas2 extends Canvas implements ComponentListener{
    //private static final Color bgcolor = Color.gray;
    //private static final Color bgcolor = new Color(216,216,191); // kaki
    private static final Color bgcolor = new Color(206,206,206); // gray
    //private static final Color bgcolor = new Color(255,255,255);// white
    //private static final Color bgcolor = new Color(216,216,216);// gray
    private double tempmax;
    private double tempVss;
    private double tempIss;
    private double tempPss;
    
          
    private double ymax, ymin, xmax, xmin;
    private boolean IsYRangeMaxSet, IsYRangeMinSet, IsXRangeMaxSet, IsXRangeMinSet; 
    //private int LeftMargin=30, RightMargin=35, TopMargin=20, BottomMargin=20;
    private int LeftMargin=138, RightMargin=35, TopMargin=20, BottomMargin=20;
    private int WIDTH, HEIGHT, newshift;
    private String X1, X2, Y1, Y2, Y3, Y4, YMAX, YVss, YIss, YPss, TITLE;
    private Image im;
    private Graphics buf;
    private int VPos = 0;
    private static final Font TitleFont = TheFonts.serif12;
    private static final Font LabelFont = TheFonts.serif12;
    private static final Font LabelFont2 = TheFonts.sanSerif11;
    private double[] x, y;
    private double xpos, xposref, VScale, IScale, PScale, ValueMax, Vss, Iss, Pss, VScaleFlag, IScaleFlag, PScaleFlag;
    private int[] xx, yy;
    private int[] xx_old, yy_old;
    private double tempmax2;
    private int N, Flag;
    private boolean IsTraceOn, IsCleanUpOn, IsDynamic, IsStepOn, IsPulse;
    public TransGraphCanvas2(){
	super();
	N = 501;
	newshift = 0;
	xpos = 0.0;
	xposref = 0.0;
	setBackground(bgcolor);
	xmax = 1.0;
	xmin = 0.0;
	ymax = 2.0;
	ymin = -2.0;
	X1 = "l"; // lower case "L", not a "one"
	X2 = "0";
	Y1 = "Vss";
	Y2 = "  ";
	TITLE = "  ";
	IsYRangeMaxSet = false;
	IsYRangeMinSet = false;
	IsXRangeMaxSet = false;
	IsXRangeMinSet = false;
	IsTraceOn = false;
	IsCleanUpOn = false;
	IsDynamic = false;
	IsStepOn = true;
	IsPulse = false;
	VScaleFlag = 1.0;
	IScaleFlag = 1.0;
	PScaleFlag = 1.0;
	Vss = 0.0;
	Iss = 0.0;
	Pss = 0.0;
	ValueMax = 1.0;
	
	try{
	    x = new double[N];
	    y = new double[N];
	    xx = new int[N];
	    yy = 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;
	}
	
	//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 clear(){
	this.getGraphics().clearRect(0,0,getSize().width,getSize().height);
	repaint();
    }
    
    //public void fix(){
	//this.getGraphics().clearRect(100,100,getSize().width-100,getSize().height-100);
	//repaint();
    //}
    
    public void drawGraph(Graphics g){
	if(!IsDynamic){
	    g.clearRect(0,0,getSize().width-1,getSize().height-1);
	}
        
	drawAxis(g);
	labelDetect();
	
	drawZeroLine(g);
	drawPoints(g,1);
        drawLabels(g);
        drawRef(g);
        drawAxis(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+newshift,(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);
	}
        
        // This is a trick to get perfectly vertical fronts for the step and 
        // pulse functions.  Not good for gradually variable signals 
        
        for(int i = 0; i < xx.length-1; i++){
            if(yy[i] != yy[i+1]){
                xx[i+1]=xx[i];
            }
        }
    }
    
    private void drawPoints(Graphics g, int tipo){
	switch(tipo){
	    case 1:
		if(IsTraceOn){
		    g.setColor(Color.green);
		    g.drawPolyline(xx,yy,xx.length);
		    g.setColor(Color.black);
		    g.drawPolyline(xx_old,yy_old,xx_old.length);
		}
		else{
		    g.setColor(Color.black);
		    //g.drawPolyline(xx,yy,xx.length);
		    for(int i=0;i<N-1;i++){
			g.drawLine(xx[i],yy[i],xx[i+1],yy[i+1]);
		    }
		}
		break;
	    case 2:
		g.setColor(bgcolor);
		g.drawPolyline(xx_old,yy_old,xx_old.length);
		break;
	}
    }
       
    private void drawAxis(Graphics g){
	VPos = getSize().height - BottomMargin;
	WIDTH = getSize().width - LeftMargin +newshift-RightMargin;
	HEIGHT = VPos - TopMargin;
	g.setColor(Color.black);
	g.drawLine(LeftMargin+newshift-5,VPos,getSize().width-RightMargin+5,VPos);
	g.drawLine(LeftMargin+newshift,TopMargin,LeftMargin+newshift,VPos+5);
	g.drawLine(getSize().width-RightMargin,TopMargin,getSize().width-RightMargin,VPos+5);
        
        // mid-point tick marks
        g.drawLine(LeftMargin+newshift-5,TopMargin+(VPos-TopMargin)/2,LeftMargin+newshift,
                                         TopMargin+(VPos-TopMargin)/2);
        g.drawLine(getSize().width-RightMargin,TopMargin+(VPos-TopMargin)/2,
                   getSize().width-RightMargin+5,TopMargin+(VPos-TopMargin)/2);
        
	//g.drawLine(LeftMargin+newshift,VPos,LeftMargin+newshift-20,VPos);
    }
    
    public void drawRef(Graphics g){
	  
	  if(!IsDynamic){
	    xposref = xpos;
	  } 
   	  if(xposref <=xmax && xposref >= xmin){
		int tx1, ty1, tx2, ty2;
		int txfix;
		tx1 = (int)MaestroA.mapper(xposref,(double)LeftMargin+newshift,(double)(getSize().width-RightMargin),xmax,xmin);
		txfix = (int)MaestroA.mapper(0.0,(double)LeftMargin+newshift,(double)(getSize().width-RightMargin),xmax,xmin);
		ty1 = TopMargin;
		tx2 = tx1;
		ty2 = getSize().height-BottomMargin;
		//if(xposref == 0.0){
		//    g.setColor(bgcolor);
		//}
		//else{		    
		//    g.setColor(Color.white);		    
		//}
		g.setColor(Color.white);
		g.drawLine(tx1,ty1,tx2,ty2);
		g.setColor(Color.black);
		g.drawLine(txfix,ty1,txfix,ty2);
		
          }
    }	
    
    private void labelDetect(){
    
	tempmax=0.0;
	tempVss=0.0;
	tempIss=0.0;
	tempPss=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;
	}
	//--------------------------------------------------------
	
	if(ValueMax>=1.0 && ValueMax<1.0E3 || ValueMax==0.0){
	    tempmax2 = ValueMax;
	    tempVss = Vss;
	    tempIss = Iss;
	    tempPss = Pss;
	}
	else if(ValueMax<1.0E6 && ValueMax>=1.0e3){
	    tempmax2 = ValueMax*1.0E-3;
	    tempVss = Vss*1.0E-3;
	    tempIss = Iss*1.0E-3;
	    tempPss = Pss*1.0E-3;
	}
	else if(ValueMax>=1.0e6){
	    tempmax2 = ValueMax*1.0E-6;
	    tempVss = Vss*1.0E-6;
	    tempIss = Iss*1.0E-6;
	    tempPss = Pss*1.0E-6;
	}
	else if(ValueMax<1.0 && ValueMax>=1.0e-3){
	    tempmax2 = ValueMax*1.0E3;
	    tempVss = Vss*1.0E3;
	    tempIss = Iss*1.0E3;
	    tempPss = Pss*1.0E3;
	}
	else if(ValueMax<1.0E-3 && ValueMax>=1.0e-6){
	    tempmax2 = ValueMax*1.0E6;
	    tempVss = Vss*1.0E6;
	    tempIss = Iss*1.0E6;
	    tempPss = Pss*1.0E6;
	}
	else if(ValueMax<1.0E-6 && ValueMax>=1.0e-9){
	    tempmax2 = ValueMax*1.0E9;
	    tempVss = Vss*1.0E9;
	    tempIss = Iss*1.0E9;
	    tempPss = Pss*1.0E9;
	}
	else if(ValueMax<1.0E-9 && ValueMax>=1.0E-12){
	    tempmax2 = ValueMax*1.0E12;
	    tempVss = Vss*1.0E12;
	    tempIss = Iss*1.0E12;
	    tempPss = Pss*1.0E12;
	}
	else if(ValueMax<1.0E-12 && ValueMax>=1.0E-15){
	    tempmax2 = ValueMax*1.0E15;
	    tempVss = Vss*1.0E15;
	    tempIss = Iss*1.0E15;
	    tempPss = Pss*1.0E15;
	}
	else if(ValueMax<1.0E-15){
	    tempmax2 = ValueMax*1.0E18;
	    tempVss = Vss*1.0E18;
	    tempIss = Iss*1.0E18;
	    tempPss = Pss*1.0E18;
	}
	
	YMAX =  String.valueOf(MaestroA.rounder(tempmax2,3))+" ";
	YVss =	String.valueOf(MaestroA.rounder(tempVss,3))+" ";
	YIss =	String.valueOf(MaestroA.rounder(tempIss,3))+" ";
	YPss =	String.valueOf(MaestroA.rounder(tempPss,3))+" ";
	
	//------------------------------------------------------
	
	if(ymin==0.0){
	    Y2 = String.valueOf(MaestroA.rounder(ymin,3))+" ";
	}
	else{
	    Y2 = String.valueOf(MaestroA.rounder(-tempmax2,3))+" ";
	}
	Y3 = "_";
	Y4 = "|";
	
	if(Flag == 1){
	    Y1 = "Vss = ";
	}
	else if(Flag == 2){
	    Y1 = " Iss = ";
	}
	else if(Flag == 3){
	    Y1 = "Pss = ";
	}
    }
    
    private void drawLabels(Graphics g){
	
        Graphics2D g2d = (Graphics2D)g;
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
        FontMetrics fm = g.getFontMetrics();
        String tmp;
	int bit;
	
	g.clearRect(0,0,LeftMargin-1+newshift,getSize().height-1);
	g.clearRect(0,0,getSize().width-1,TopMargin-1);
	
        g.setFont(TheFonts.italic16);
        fm = g.getFontMetrics();
	tmp = X1;
	MaestroG.subscripterSerIT(""+tmp,"","",g,16,getSize().width-RightMargin-fm.stringWidth(tmp)/2+3,VPos+17);
	
        g.setFont(LabelFont);
        fm = g.getFontMetrics();
        
        tmp = X2;
	g.drawString(tmp,LeftMargin+newshift-fm.stringWidth(tmp)/2+1,VPos+17);
        
	tmp = YMAX;
	g.drawString(tmp,LeftMargin+newshift-fm.stringWidth(tmp)-10,TopMargin+4);
	tmp = Y2;
	g.drawString(tmp,LeftMargin+newshift-fm.stringWidth(tmp)-10,VPos);
	g.setFont(LabelFont2);
	tmp = Y3;
	//g.drawString(tmp,LeftMargin+newshift-5,VPos-1);
	//g.drawString(tmp,LeftMargin+newshift-5, TopMargin);
	
	//g.drawString(tmp,getSize().width-RightMargin,VPos-1);
	//g.drawString(tmp,getSize().width-RightMargin, TopMargin);
	g.drawLine(getSize().width-RightMargin, TopMargin,getSize().width-RightMargin+5, TopMargin);
	g.drawLine(LeftMargin+newshift-5, TopMargin,LeftMargin+newshift, TopMargin);
	//g.drawString(tmp,LeftMargin-5,getSize().height/2-1);
	//g.drawString(tmp,getSize().width-RightMargin,getSize().height/2-1);
	
	
	g.setColor(Color.blue);
        //System.out.println(IsPulse+"    "+Flag);
	if(Flag == 1){
            
	    if(!IsPulse){ // Step Response
	    
		bit = (int)MaestroA.mapper(Vss,(double)TopMargin+1,(double)(getSize().height-BottomMargin)-1,ymax,ymin);
		
                // tick marks for steady state
                g.drawLine(LeftMargin,bit,LeftMargin-5,bit);
                g.drawLine(getSize().width-RightMargin,bit,getSize().width-RightMargin+5,bit);
		
                // type steady state value
                g.setFont(LabelFont);
		g.drawString(Y1+String.valueOf(MaestroA.rounder(tempVss,4)),LeftMargin+newshift-fm.stringWidth(tmp)-100,bit-1);
		
		g.setFont(LabelFont2);
	    }
	    else{ // Pulse Response
                 g.drawLine(LeftMargin,TopMargin+(VPos-TopMargin)/2,LeftMargin-5,getSize().height/2);
                 g.drawLine(getSize().width-RightMargin,TopMargin+(VPos-TopMargin)/2,
                            getSize().width-RightMargin+5,getSize().height/2);
	    }
	    
	}
	else if(Flag == 2){
	    if(!IsPulse){ // Step Response
		bit = (int)MaestroA.mapper(Iss,(double)TopMargin+1,(double)(getSize().height-BottomMargin)-1,ymax,ymin);
		
                // tick marks for steady state
		g.drawLine(LeftMargin,bit,LeftMargin-5,bit);
                g.drawLine(getSize().width-RightMargin,bit,getSize().width-RightMargin+5,bit);
                
                // type steady state value
                g.setFont(LabelFont);
                g.drawString(Y1+String.valueOf(MaestroA.rounder(tempIss,4)),LeftMargin+newshift-fm.stringWidth(tmp)-100,bit-1);
		
		g.setFont(LabelFont2);
	    }
	    
	    else{  // Pulse Response
		 g.drawLine(LeftMargin,TopMargin+(VPos-TopMargin)/2,LeftMargin-5,getSize().height/2);
                 g.drawLine(getSize().width-RightMargin,TopMargin+(VPos-TopMargin)/2,
                            getSize().width-RightMargin+5,getSize().height/2);
	    }
    	}
	else if(Flag == 3){
	
	    if(!IsPulse){ // Step Response
		    bit = (int)MaestroA.mapper(Pss,(double)TopMargin+1,(double)(getSize().height-BottomMargin)-1,ymax,ymin);
		    
                    //tick marks for steady state
                    g.drawLine(LeftMargin,bit,LeftMargin-5,bit);
                    g.drawLine(getSize().width-RightMargin,bit,getSize().width-RightMargin+5,bit);
		    
                    // type steady state value
                    g.setFont(LabelFont);
		    g.drawString(Y1+String.valueOf(MaestroA.rounder(tempPss,4)),LeftMargin+newshift-fm.stringWidth(tmp)-100,bit-1);
		    g.setFont(LabelFont2);
	    }
	    else{  // Pulse Response
		    g.drawLine(LeftMargin,TopMargin+(VPos-TopMargin)/2,LeftMargin-5,getSize().height/2);
                    g.drawLine(getSize().width-RightMargin,TopMargin+(VPos-TopMargin)/2,
                               getSize().width-RightMargin+5,getSize().height/2);
	    }
	}
	
	g.setColor(Color.black);
	tmp = Y4;
	//g.drawString(tmp,LeftMargin+newshift,VPos+4);
	//g.drawString(tmp,getSize().width-RightMargin-fm.stringWidth(tmp)/2+1,VPos+4);
	
	tmp = TITLE;
	g.setFont(TitleFont);
	g.drawString(tmp,LeftMargin+2+newshift,TopMargin-2);
    }
    
    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+newshift,myY,getSize().width-RightMargin-1,myY);
    }
    
    
    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 setFlag(int Flag){
	this.Flag = Flag;
    }
    
    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 setStep(boolean IsStepOn){
	this.IsStepOn = IsStepOn;
	this.clean_memory();
    }
    
    public synchronized void setDynamics(boolean IsDynamic){
	this.IsDynamic = IsDynamic;
    }
    
   //public void update(Graphics g){		// added to avoid clearing
   //	paint(g);
   // }

    public void update(Graphics g){
	if(!IsDynamic){
	    super.update(g);
	    return;
	}
	if(IsDynamic && IsTraceOn){
	    g.clipRect(LeftMargin+1+newshift,TopMargin+1,WIDTH-1,HEIGHT-1);
	}
	
	if(IsCleanUpOn){
	    
	    g.clearRect(LeftMargin+1+newshift,TopMargin+1,WIDTH-1,HEIGHT-1);
	    IsCleanUpOn = false;
	}
	
	if(!IsTraceOn){
	
	    drawPoints(g,2);//This cleans the previous graph
	    
	}
	drawPoints(g,1);//This draws the new graph
	
	drawZeroLine(g);
	drawRef(g);
        drawAxis(g);
	push();
    }
   
    
    public void plot(double xdata[], double ydata[]){
	N = xdata.length;
	x = new double[N];
	y = 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];
	}	
	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] = 0;
	}
    }
    
    
    
    
    public synchronized void setTitle(String TITLE){
	this.TITLE = TITLE;
    }
    
    public void setXpos(double xpos){
	this.xpos = xpos;   
    }
    
    public void setPulse(boolean IsPulse){
	this.IsPulse = IsPulse;
    }
    
    public void setScale(double VScale, double IScale, double PScale, double Vss, double Iss, double Pss, 
			 double VScaleFlag, double IScaleFlag, double PscaleFlag){
	this.VScale = VScale;
	this.IScale = IScale;  
	this.PScale = PScale;
	this.VScaleFlag = VScaleFlag;
	this.IScaleFlag = IScaleFlag;  
	this.PScaleFlag = PScaleFlag; 
	this.Vss = Vss;
	this.Iss = Iss;  
	this.Pss = Pss;
	//System.out.println(VScale+"  "+IScale+"   "+PScale+"   "+Vss+"   "+Iss+"   "+Pss);
    }
    
    public void setValueMax(double ValueMax){
	this.ValueMax = ValueMax;
    }
    
    public void componentHidden(ComponentEvent evt){/*cleanUp();*/}
    public void componentMoved(ComponentEvent evt){/*cleanUp();*/}
    public void componentResized(ComponentEvent evt){/*cleanUp();*/}
    public void componentShown(ComponentEvent evt){/*cleanUp();*/}
     
}
