// A real-time simulation
//
/** NOTE: The simulation information for this applet have been taken from
          ???, Hartmut Bossel, Springer-Verlag, Stuttgart, 1994*/
// (c) Tomaz Sesek, January 1996

import java.applet.Applet;
import java.awt.*;

public class Simulation extends Applet implements Runnable{
   Thread jaz;
   Component board, paramCtrl;

   public void init() {
      setLayout(new GridLayout(0, 2, 5, 5));
      add(board = new CurvePanel());
      add(paramCtrl = new ParameterControl((CurvePanel)board));
      }

   /** Enable as thread */
   public void start() {
      jaz = new Thread(this);
      jaz.start();
      }
   public void stop() {
      jaz.stop();
      }
   public void run() {
      while (true) {
         try {
            Thread.currentThread().sleep(500);
            } 
            catch (InterruptedException e){}
         }
      }
   }

class CurvePanel extends Panel {
   Graphics backGC;
   Image backBuffer;

   int paramVal[] = new int[4];

   public CurvePanel() {
      setBackground(Color.black);
      for (int i=0;i<paramVal.length;i++) {
         paramVal[i] = 20;
         }

      /**  Create double buffer if enough memory available  */
      try
        {
          backBuffer = createImage(size().width, size().height);
          backGC = backBuffer.getGraphics();
        }
      catch (Exception e) backBuffer=null;
      }

   public void setValue(int index, int value) {
      /** if a parameter is changed, update value and redraw graph */
      if (index < paramVal.length) {
         paramVal[index] = value;
         repaint();
         }
         else {
         // throw exception
         } 
      }

   public void drawCurve(Graphics g) {
      /**  Draw Curve  */
      double x, y, yRate;
      int t, yCoord, xCoord;

      x = (double)( paramVal[0] - 40 ) / 20;
      y = (double)( paramVal[1] - 40 ) / 20;
      yCoord = (int)Math.round(size().height/2 - y * 15);
      xCoord = (int)Math.round(size().height/2 - x * 15);
      t = 0;
      g.setColor(Color.green);
      g.drawLine(0, size().height/2, 301, size().height/2);

      while (t<300) {
        for (int i=1;i<=5;i++) {
           yRate = (double)( paramVal[2] - 40 ) / 20 *x + (double)( paramVal[3] - 40 ) / 20 *y;
           x = x + y * 0.05;
           y = y + yRate * 0.05;
           }
        t = t + 7;

        g.setColor(Color.yellow);
        g.drawLine(t - 7, yCoord, t, (int)Math.round(size().height/2 - y * 15));
        yCoord = (int)Math.round(size().height/2 - y * 15);

        g.setColor(Color.blue);
        g.drawLine(t - 7, xCoord, t, (int)Math.round(size().height/2 - x * 15));
        xCoord = (int)Math.round(size().height/2 - x * 15);
        if ( (y > 200) | (y < -200) ) t = 300;
        }
      }

   public void paint(Graphics g) {
      if (backBuffer!=null) {
         drawCurve(backGC);
         g.drawImage(backBuffer, 0, 0, this);
         }
       /**  otherwise just paint onto the screen => flashes possible */
       else {
         drawCurve(g);
         }      
      }
   }

/** Parameter Control scrollbars determine the values of 4 parameters to curves  */
class ParameterControl extends Panel {
   Scrollbar param[] = new Scrollbar[4];

   public ParameterControl(CurvePanel graph) {
      setLayout(new GridLayout(1,0,0,0));
      for (int i=0;i<param.length;i++) {
         add(param[i] = new ParameterBar(graph, i, Scrollbar.VERTICAL, 10*(i+1), 1, 1, 80));
         }
      }
   }

/** Parameter Scrollbar determines the value of a parameter (index)  */
class ParameterBar extends Scrollbar {
   CurvePanel graph;	// pointer to the target graph
   int index;		// index of the parameter

   public ParameterBar(CurvePanel graph, int index, int orientation,
                       int value, int visible,
                       int minimum, int maximum) {

      super(orientation, value, visible, minimum, maximum);
      this.graph = graph;
      this.index = index;
      setLineIncrement(1);
      setPageIncrement(1);
      }

   public boolean handleEvent(Event evt) {
      super.handleEvent(evt);
      setLineIncrement(1);
      setPageIncrement(1);

      /** if the value of the scrollbar is chanegd, pass it to the graph */
      switch (evt.id) {
         case Event.SCROLL_ABSOLUTE :
         case Event.SCROLL_LINE_DOWN :
         case Event.SCROLL_LINE_UP :
         case Event.SCROLL_PAGE_DOWN :
         case Event.SCROLL_PAGE_UP :
  	    graph.setValue(index, getValue());
            break;
         }
      return true;
      }
   }







