/*
 * InterPlot.java
 * Code: Jan Humble
 */

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

public class InterPlot extends Applet implements Runnable{

    int dY, dX;
    int canvasSizeX = 320;
    int canvasSizeY = 300;
    
    Color color;        

    boolean toggleAnimation = true;
    
    AnimCanvas animCanvas;
    InputPanel inputPanel;
    
    
    Plot plot;
    Thread drawThread;
    int time = 0;

   
    public void init(){
	// Get the drawing area of the applet 
	dY=getSize().height; dX=getSize().width;
	
	color = Color.blue;
       
	plot = new Plot(canvasSizeX, canvasSizeY, color);
  

	inputPanel = new InputPanel(this);

	
	setLayout(new BorderLayout());
	animCanvas = new AnimCanvas(this);
	add("West", animCanvas);
	add("Center", inputPanel);

    }
    
  
    
    public void start() { 
	if (toggleAnimation && drawThread == null){ 
	    drawThread = new Thread(this); 
	    drawThread.start(); 
	} 
    } 

   
    public void stop() { 
	drawThread = null; 
    } 
   

    public void run() { 
	
	while (toggleAnimation && drawThread != null) { 

	    
	    
	    // Use sleep to pause between movements 
	    try { 
		
		Thread.sleep((int)(100)); 
		
	    } catch (InterruptedException e) {}
	    
	    plot.move(time); 
	    animCanvas.repaint(); 
	    time++;
	} 
	
    } 
    

   
 
  
}



class AnimCanvas extends Canvas {
    
    Image offscreen;     // background graphics buffer
    InterPlot plotApplet;
    
    int dX, dY;
    
    AnimCanvas(InterPlot plotApplet) {
	this.plotApplet = plotApplet;
	
	dX = plotApplet.canvasSizeX;
	dY = plotApplet.canvasSizeY;

	setSize(dX, dY);
	
	setBackground(Color.white);
    }
    
    
    public void update (Graphics g){
	
	// Update using double buffering
	
	Dimension d = this.getSize();
	
	if (offscreen == null)
	    offscreen = this.createImage(d.width, d.height);
	
	// Draw to background buffer
	g = offscreen.getGraphics();
	paint(g);
	
	// draw from background buffer to screen buffer
	g = this.getGraphics();
	g.drawImage(offscreen, 0, 0, this);
	
    }
    
    public void paint(Graphics g) {
	
 
	
	// Clear screen
	g.setColor(Color.white);
	g.fillRect(0, 0, dX, dY);
	  
	// Draw plot and plot info
	plotApplet.plot.draw(g);
	plotApplet.plot.frameInfo(plotApplet.time, g);
	
    }
    
    
}


class InputPanel extends Panel implements ActionListener {

    InterPlot plotApplet;
    
    Button startButton;
    Button stopButton;
    Button ampButton;
    TextField ampField;
    
    InputPanel(InterPlot plotApplet) {
	
	this.plotApplet = plotApplet;
   	
	this.setLayout(new GridLayout(8,1));
	this.setBackground( Color.white);
	
	startButton = new Button("Start");
	stopButton = new Button("Stop");
	ampButton = new Button("New Amp");
	ampField = new TextField();
	

	startButton.addActionListener(this);
	stopButton.addActionListener(this); 
	ampButton.addActionListener(this); 
       

	add(startButton);
	add(stopButton);
	add(ampButton);
	add(ampField);


	
    } 
    
    public void actionPerformed(ActionEvent ev) {
	if (ev.getActionCommand().equals("Start")) {
            plotApplet.toggleAnimation = true;
	    startButton.setEnabled(false);
            stopButton.setEnabled(true);
	    plotApplet.drawThread = new Thread(plotApplet);
	    plotApplet.drawThread.start();
	    
        } else if (ev.getActionCommand().equals("Stop")) {
	    plotApplet.toggleAnimation = false;
	    startButton.setEnabled(true);
            stopButton.setEnabled(false);

        } else if (ev.getActionCommand().equals("New Amp")) {
	    
	    double newAmp = Double.valueOf(ampField.getText()).doubleValue();
	    plotApplet.plot.maxAmplitud = newAmp;


	    
	    
        }
	


    }
    
    
}


/* ------------------------------------------------ */
/* Inherited Plot classes                           */
/* Each contains its own function and label         */
/* ------------------------------------------------ */


class Plot extends BasePlot {

   
    double amplitud, maxAmplitud;
  

    // Constructor

    Plot(int dX, int dY, Color color) {
	
	super(dX, dY, color);
	this.label = "y = amplitud(time) * sin(x)";
	this.amplitud = dY/4;
	this.maxAmplitud = dY/4;
    }
    
    
    double f(double x) 
    {
	int phase = dX / 2;
	return dY/2 - Math.sin((x - phase)/16) * amplitud;
    }
    
    public void move(int time)
    {
	amplitud = maxAmplitud * Math.cos(time*0.02);
    }
    
    
    public void frameInfo(int time, Graphics g)
    {
	String amp_str = Double.toString(amplitud);

	g.setColor(Color.black);
	g.setFont(new Font("Helvetica", Font.PLAIN, 10));
	g.drawString("amplitud = " + 
		     amp_str.substring(0, Math.min(6, amp_str.length())), 
		     dX-100, dY-40);
	g.drawString("time = " + Integer.toString(time), dX-100, dY-20);
       	
    }
               
}



