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

public class GraphCanvasBNeg extends Canvas implements MouseListener{
    protected static final Color bgcolor = Color.gray;
    
    protected Image im;
    protected Graphics buf;
    protected int LeftMargin;
    protected int TopSep;
    protected int BottomSep;
    protected int RightMargin;
    protected int VPos=0;
    protected String XLabel, YLabel, ZLabel, TITLE;
    protected String X1, X2, X3;
    protected String Y1, Y2, Y3;
    protected int NumPoints;
    protected double x[];
    protected double y[], y2[];
    protected double ymin, ymax;
    protected double xmin, xmax;
    protected int xx[], xpoint;
    protected int yy[], yy2[], yy2max, yy2min;
    protected double xRef, wire_radius;
    protected boolean Should_Plot_Zero_Line;
    protected boolean Should_Plot_Ref_Point;
    protected boolean IsDirectivity;
    protected boolean IsYRangeMinSet, IsYRangeMaxSet;
    protected boolean IsXRangeMinSet, IsXRangeMaxSet;
    protected boolean IsWZero, IsFocusOn, IsTopoOn;
    protected Font font0;
    protected Font font1;
    protected Font font2;
    protected Font font3;
    NewGuide_State state;
    
    public GraphCanvasBNeg(NewGuide_State state){
	super();
        this.state = state;
        
        LeftMargin = state.s40;
        TopSep = state.s40;
        BottomSep = state.s40;
        RightMargin = state.s40;
        
        font0 = new Font("SanSerif",Font.PLAIN,state.font10);
        font1 = new Font("SanSerif",Font.PLAIN,state.font11);
        font2 = new Font("SanSerif",Font.PLAIN,state.font12);
        font3 = new Font("SanSerif",Font.PLAIN,state.font13);
    
	setBackground(bgcolor);
	XLabel="x-axis";
	YLabel="y-axis";
	TITLE ="Unknown Title";
	Y1 = " ";
	Y2 = " ";
	Y3 = " ";
	X1 = " ";
	X2 = " ";
	X3 = " ";
	NumPoints = 1001;
	x = new double[NumPoints];
	y = new double[NumPoints];
	y2 = new double[NumPoints];
	xx = new int[NumPoints];
	yy = new int[NumPoints];
	yy2 = new int[NumPoints];
	for(int i=0;i<NumPoints;i++){
	    x[i]=i;
	    y[i]=0.0;
	}
	IsYRangeMinSet=false;
	IsYRangeMaxSet=false;
	IsXRangeMinSet=false;
	IsXRangeMaxSet=false;
	IsWZero = false;
	
	xRef = 0.0;
	wire_radius = 1.0e-5;
	
	Should_Plot_Zero_Line = false;
	Should_Plot_Ref_Point = false;
	IsDirectivity = true;
	IsFocusOn = false; IsTopoOn = false;
	//Listeners
	this.addMouseListener(this);
    }
     
public void paint(Graphics g){
    if(im == null){
	im = createImage(getSize().width,getSize().height);
	buf = im.getGraphics();
	drawGraph(buf);
    }
    drawGraph(buf);
    g.drawImage(im,0,0,null);
}

//Addition to reduce flicker new routine
public void update(Graphics g){		// added to avoid clearing
	paint(g);
}

public void drawGraph(Graphics g){
	FontMetrics fm = g.getFontMetrics();
	g.clearRect(0,0,getSize().width,getSize().height);
	
    	drawAxis(g);
	if(Should_Plot_Zero_Line){plotZeroLine(g);}
	
        drawTitle(g);
        plotPoints(g);
	plotRefPoint(g);
		
        g.setFont(font0);
        fm = g.getFontMetrics();

        if(IsTopoOn){
            if(!IsFocusOn){
                g.setColor(Color.yellow);
                g.drawString("Click to show Self Reactance",(getSize().width - fm.stringWidth("Click to see Radiation Resistance"))/2+state.s10,getSize().height - state.s2);	
            }
            else{
                g.setColor(Color.cyan);
                g.drawString("Click to hide Self Reactance",(getSize().width - fm.stringWidth("Click to hide Radiation Resistance"))/2+state.s10,getSize().height - state.s2);			
            }
        }
}

protected void ignition(){
    int height=getSize().height;
    int width=getSize().width;
    if(!IsYRangeMinSet){ymin = MaestroA.getMin(y);}
    if(!IsYRangeMaxSet){ymax = MaestroA.getMax(y);}
    if(!IsXRangeMaxSet){xmax = x[x.length-1];}
    if(!IsXRangeMinSet){xmin = x[0];}
    if(IsYRangeMinSet || IsYRangeMaxSet){
	MaestroA.confiner(y,ymax,ymin);
    }
    if(IsXRangeMinSet || IsXRangeMaxSet){
	MaestroA.confiner(x,xmax,xmin);
    }
    
    if(ymin==ymax){ymax=2*ymin+state.s1;}    
    xpoint = (int)MaestroA.mapper(10.0*wire_radius,(double)(width-RightMargin),(double)(LeftMargin),xmax,xmin);
    
    for(int i=0;i<xx.length;i++){
	if(y[i] == -1.0E-230){y[i] = ymin;}
	xx[i]= (int)MaestroA.mapper(x[i],(double)(width-RightMargin),(double)(LeftMargin),xmax,xmin);
	yy[i]= (int)MaestroA.mapper(y[i],(double)TopSep,(double)(height-BottomSep),ymax,ymin);
	yy2[i]= (int)MaestroA.mapper(y2[i],(double)TopSep,(double)(height-BottomSep),ymax,ymin);
    } 
    yy2max= (int)MaestroA.mapper(ymax,(double)TopSep,(double)(height-BottomSep),ymax,ymin);
    yy2min= (int)MaestroA.mapper(ymin,(double)TopSep,(double)(height-BottomSep),ymax,ymin);
    X1=""+MaestroA.rounder(x[0],3);
    X2=""+MaestroA.rounder(x[x.length-1],3);
    X3="|";
    Y1=""+MaestroA.rounder(ymin,3);
    if(ymax < 1.0e230){
	Y2=""+MaestroA.rounder(ymax,3);
    }
    else{
	Y2="\u221e";
    }
    Y3="_";
    
}

protected void plotZeroLine(Graphics g){
    if(ymin*ymax>0){return;}
    g.setFont(font1);
    FontMetrics fm = g.getFontMetrics();
    
    int yy;
    yy = (int)MaestroA.mapper(0.0,(double)TopSep,(double)(getSize().height-BottomSep),ymax,ymin);
    g.setColor(Color.red);
    g.drawLine(LeftMargin,yy,getSize().width-RightMargin,yy);
    g.setColor(Color.yellow);
    g.drawString("0",LeftMargin-2*fm.stringWidth("0"),yy+fm.getHeight()/3);
    //g.drawString("0",getSize().width - RightMargin + state.s5,yy+fm.getHeight()/3);
}

public synchronized void plotZeroLine(boolean Should_Plot_Zero_Line){
    this.Should_Plot_Zero_Line = Should_Plot_Zero_Line;
}

protected void plotRefPoint(Graphics g){
    
    int myX=0, myY=0, i;
    int yy, yyM1, yyM2;
    yy = (int)MaestroA.mapper(0.0,(double)TopSep,(double)(getSize().height-BottomSep),ymax,ymin);
    
    i = (int)((NumPoints-1)*(xRef-x[0])/(x[x.length-1]-x[0]));
    if(i<0) {i = 0;}
    if(i>=NumPoints){i=NumPoints-1;}
  
    if(i<NumPoints-1){
	
	yyM1 = (int)MaestroA.mapper(y[i],(double)TopSep,(double)(getSize().height-BottomSep),ymax,ymin);
	yyM2 = (int)MaestroA.mapper(y[i+1],(double)TopSep,(double)(getSize().height-BottomSep),ymax,ymin);
    }
    else{
	yyM1 = (int)MaestroA.mapper(y[i],(double)TopSep,(double)(getSize().height-BottomSep),ymax,ymin);
	yyM2 = yyM1;
    }
   
    myX = (int)MaestroA.mapper(xRef,(double)(getSize().width-RightMargin),(double)(LeftMargin),xmax,xmin);
    {
	myY = (int)MaestroA.mapper(y[i],(double)TopSep,(double)(getSize().height-BottomSep),ymax,ymin);
    }
    
    g.setColor(Color.white);
    g.drawLine(myX,myY,myX,yy);

    Graphics2D g2d = (Graphics2D)g;
    g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
    
    if((yyM1<=yy2max && yyM2<=yy2max ) || (yyM1>=yy2min && yyM2>=yy2min )){
    
    }
    else
    {
	g.setColor(Color.red);
	MaestroG.fillCircle(myX,myY,state.s6,g);
	g.setColor(Color.white);
	MaestroG.drawCircle(myX,myY,state.s6,g);
    }
    
    g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_OFF);
    
}

public synchronized void plotRefPoint(boolean Should_Plot_Ref_Point){
    this.Should_Plot_Ref_Point = Should_Plot_Ref_Point;
}

protected void plotPoints(Graphics g){
    ignition();
    Graphics2D g2d = (Graphics2D)g;
    g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
    
      if(IsFocusOn){
	//g.drawPolyline(xx,yy2,xx.length);
	for(int i=1;i<NumPoints-1;i++){
	    //if(xx[i] < xpoint){g.setColor(Color.black);}
	    //else
	    {g.setColor(Color.green);} 
	    g.drawLine(xx[i],yy2[i],xx[i+1],yy2[i+1]);
	}
      }
      
	//g.drawPolyline(xx,yy,xx.length);
	for(int i=1;i<NumPoints-1;i++){
	    if((yy[i]<=yy2max && yy[i+1]<=yy2max )){
		g.setColor(bgcolor);
	    }
	    else if((yy[i]>=yy2min && yy[i+1]>=yy2min )){
		g.setColor(Color.white);
	    }
	    else{
		//if(xx[i] < xpoint){g.setColor(Color.black);}
		//else
		{g.setColor(Color.green);} 
		g.setColor(Color.cyan);
	    }
	    g.drawLine(xx[i],yy[i],xx[i+1],yy[i+1]);
	}
    
    g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_OFF);
    
}

protected void drawTitle(Graphics g){
    
    g.setFont(font2);
    FontMetrics fm = g.getFontMetrics();
    g.setColor(Color.white);
    
    int ylevel = getSize().height-state.s13;
    int xlevel = (getSize().width-fm.stringWidth(XLabel))/2-state.s10;
    int xshift = xlevel+ state.s3 + fm.stringWidth("Dipole Length    ");
    g.drawString(XLabel,xlevel,ylevel);
    
    g.setFont(new Font("Serif",Font.PLAIN,state.font14));
    g.drawString("[ \u03bb ]",xshift + state.s6,ylevel);
    
    g.setFont(font3);
    
    g.drawString(YLabel,LeftMargin-state.s33,getSize().height/2);
    g.drawString(ZLabel,LeftMargin-state.s26,getSize().height/2 + state.s4);
    g.setColor(Color.white);
    g.drawString(TITLE,(getSize().width-fm.stringWidth(TITLE))/2,TopSep/2);
    
    g.setFont(font1);
    g.setColor(Color.yellow);
    
    g.drawString(X1,LeftMargin - state.s6,ylevel);
    g.drawString(X2,getSize().width-RightMargin-fm.stringWidth(X2) + state.s9,ylevel);
    
    //g.drawString(X3,LeftMargin+(getSize().width-RightMargin-LeftMargin)/2,getSize().height-BottomSep+5);
    //g.drawString(X3,getSize().width-RightMargin,getSize().height-BottomSep+5);
    
    // horizontal tick marks.  Using fonts (above) DOES NOT WORK on Mac - Mac sucks!!!!!
    g.drawLine(LeftMargin+(getSize().width-RightMargin-LeftMargin)/2,getSize().height-BottomSep,
               LeftMargin+(getSize().width-RightMargin-LeftMargin)/2,getSize().height-BottomSep + state.s6);
    g.drawLine(getSize().width-RightMargin,getSize().height-BottomSep,
               getSize().width-RightMargin,getSize().height-BottomSep + state.s6);
    g.drawLine(LeftMargin - state.s6,getSize().height-BottomSep,LeftMargin,getSize().height-BottomSep);
    g.drawString(Y3,LeftMargin - state.s6,TopSep - state.s1);
    
    g.drawString(Y1,state.s3,getSize().height-BottomSep + state.s12);
    g.drawString(Y2, state.s5,TopSep - state.s4);

    
    if(!IsDirectivity){
	g.setColor(Color.white);
	g.setFont(new Font("SanSerif",Font.PLAIN, state.font12));
	g.drawString("[\u03a9]",LeftMargin-state.s23,getSize().height/2-state.s30);
	g.setFont(new Font("SanSerif",Font.PLAIN,state.font11));
	g.setColor(Color.black);
    }
    
    //g.setColor(Color.cyan);
    //g.drawLine(getSize().width - state.s60,state.s10,getSize().width - state.s45,state.s10);
    //MaestroG.subscripter("X","in","",g,state.font12,getSize().width - state.s40, state.s15);
    
    //if(IsFocusOn){
    //	g.setColor(Color.green);
    //	g.drawLine(getSize().width - state.s60,state.s28,getSize().width - state.s45,state.s28);
    //	MaestroG.subscripter("X","rad","",g,state.s12,getSize().width - state.s40, state.s33);
    //}
    
    g.setColor(Color.cyan);
    g.drawLine(getSize().width - state.s60,state.s7,getSize().width - state.s45,state.s7);
    MaestroG.subscripter("X","in","",g,state.font11,getSize().width - state.s40, state.s12);
    
    if(IsFocusOn){
	g.setColor(Color.green);
	g.drawLine(getSize().width - state.s60,state.s22,getSize().width - state.s45,state.s22);
	MaestroG.subscripter("X","rad","",g,state.font11,getSize().width - state.s40, state.s27);
    }
}

protected void drawAxis(Graphics g){
    VPos = getSize().height-BottomSep;
    g.setColor(Color.white);
    //Vertical Axis
    g.drawLine(LeftMargin,TopSep-state.s1,LeftMargin,getSize().height-BottomSep);
    //g.drawLine(LeftMargin,TopSep/2,LeftMargin,getSize().height-BottomSep);
    //MaestroG.drawArrow(LeftMargin,TopSep/2,1,g);
    
    //Horizontal Axis
    g.drawLine(LeftMargin,VPos,getSize().width-RightMargin+state.s10,VPos);
    //MaestroG.drawArrow(getSize().width-RightMargin+10,VPos,7,g);
    MaestroG.drawArrowScaled(getSize().width-RightMargin+state.s10,VPos,3,state.sfactor,g);
}

public final synchronized void setXLabel(String XLabel){
    this.XLabel=XLabel;
}

public final synchronized void setYLabel(String YLabel){
    this.YLabel=YLabel;
} 

public final synchronized void setTitle(String TITLE){
    this.TITLE = TITLE;
}

public void setWZero(boolean IsWZero){
    this.IsWZero = IsWZero;
}

public final synchronized void setLabels(String TITLE, String YLabel, String XLabel, String ZLabel){
    this.TITLE=TITLE;
    this.YLabel = YLabel;
    this.XLabel = XLabel;
    this.ZLabel = ZLabel;
}
 
public void plot(double[] xdata, double[] ydata, double[] y2data, boolean IsDirectivity){
    this.IsDirectivity = IsDirectivity;
    if(NumPoints != xdata.length){
	NumPoints = xdata.length;
	x = new double[NumPoints];
	y = new double[NumPoints];
	xx = new int[NumPoints];
	yy = new int[NumPoints];
	yy2 = new int[NumPoints];
    }
    for(int i = 0; i < NumPoints; i++){
	x[i] = xdata[i];
	y[i] = ydata[i];
	y2[i] = y2data[i];
    }
    repaint();
}

public void setYRange(double ymax, double ymin){
    IsYRangeMaxSet=true;
    IsYRangeMinSet=true;
    this.ymax=ymax;
    this.ymin=ymin;
}

public void setYRangeMin(double ymin){
    IsYRangeMinSet=true;
    this.ymin=ymin;
}

public void setYRangeMax(double ymax){
    IsYRangeMaxSet=true;
    this.ymax=ymax;
}

public void setWireRadius(double wire_radius){
    this.wire_radius=wire_radius;
}

public void setAuto(){
    IsYRangeMaxSet=false;
    IsYRangeMinSet=false;
    IsXRangeMaxSet=false;
    IsXRangeMinSet=false;
}

public synchronized void setRefPoint(double xRef){
    this.xRef = xRef;
}

public void mouseClicked(MouseEvent evt){
	if(IsFocusOn){
	    IsFocusOn = false;
	    repaint();
	}
	
	else{
	    IsFocusOn = true;
	    repaint();
	}
}
    
public void mouseEntered(MouseEvent evt){
	IsTopoOn = true;
	repaint();
}
public void mouseExited(MouseEvent evt){
	IsTopoOn = false;
	repaint();
}
public void mousePressed(MouseEvent evt){}
public void mouseReleased(MouseEvent evt){}



}