/* 
 * SpectralTest.java 1.0 2003-09-17
 *
 * © 2003 Jouni Smed
 *
 * This software is provided for educational and non-commercial use only.
 *
 */

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

public class SpectralTest extends Applet
  {
  public static final int MODULUS = 317;      
  public static final int MULTIPLIER = 3;     
  public static final int INCREMENT = 7;      
  public static final int SEED = 1;          

  private static int modulus = MODULUS;
  private static int multiplier = MULTIPLIER;
  private static int increment = INCREMENT;
  private static int seed = SEED;

  private SpectralView spectralView = new SpectralView();
  private TextField modulusField =
        new TextField(Integer.toString(modulus));
  private TextField multiplierField =
        new TextField(Integer.toString(multiplier));
  private TextField incrementField =
        new TextField(Integer.toString(increment));
  private Checkbox lineCheckbox =
        new Checkbox("Lines", true);
  private Button generateButton = new Button("Generate");

  private Vector numbers;


  public void init()
    {
    spectralView.setBackground(Color.white);
    generateButton.addActionListener(new ActionListener()
      {
      public void actionPerformed(ActionEvent e)
        {
        if (updateParameters())
          {
          generateNumbers();
          spectralView.repaint();
          }
        }
      } );
    lineCheckbox.addItemListener(new ItemListener()
      {
      public void itemStateChanged(ItemEvent e)
        {
        spectralView.repaint();
        }
      } );
    Panel parameterPanel = new Panel();
    parameterPanel.add(new Label("Modulus:", Label.RIGHT));
    parameterPanel.add(modulusField);
    parameterPanel.add(new Label("Multiplier:", Label.RIGHT));
    parameterPanel.add(multiplierField);
    parameterPanel.add(new Label("Increment:", Label.RIGHT));
    parameterPanel.add(incrementField);
    parameterPanel.add(new Label("  "));
    parameterPanel.add(lineCheckbox);
    parameterPanel.add(generateButton);

    this.setLayout(new BorderLayout());
    this.add(spectralView, BorderLayout.CENTER);
    this.add(parameterPanel, BorderLayout.SOUTH);
    }


  public void start()
    {
    generateNumbers();
    repaint();
    }


  public void paint(Graphics g)
    {
    spectralView.repaint();
    }


  private boolean updateParameters()
    {
    try
      {
      modulus = Integer.parseInt(modulusField.getText());
      multiplier = Integer.parseInt(multiplierField.getText());
      increment = Integer.parseInt(incrementField.getText());
      return true;
      }
    catch (NumberFormatException e)
      {
      Toolkit.getDefaultToolkit().beep();
      showStatus("Bad parameter number.");
      return false;
      }
    }


  private void generateNumbers()
    {
    numbers = new Vector(modulus);
    for (int i = 0; i < modulus; i++)
      {
      showStatus("Generating number " + i + " out of " + modulus);
      numbers.add(new Integer(randomInt()));
      }
    showStatus("Done.");
    }


  private class SpectralView extends Panel
    {
    public void paint(Graphics g)
      {
      if (numbers != null)
        {
        int previousX = 0;
        int previousY = 0;
        boolean first = true;
        Iterator it = numbers.iterator();
        int previousNumber = ((Integer)it.next()).intValue();;
        while (it.hasNext())
          {
          int number = ((Integer)it.next()).intValue();
          int x = (number * this.getSize().width / modulus);
          int y = this.getSize().height -
                  (previousNumber * this.getSize().height / modulus);
          if (!first && lineCheckbox.getState())
            {
            g.setColor(Color.gray.brighter());
            g.drawLine(previousX, previousY, x, y);
            }
          g.setColor(Color.red);
          g.fillRect(x - 2, y -2 , 5, 5);
          previousNumber = number;
          previousX = x;
          previousY = y;
          first = false;
          }
        }
      }
    }


  private static int previousValue = SEED;

  public static int randomInt()
    {
    int result = (multiplier * previousValue + increment) % modulus;
    previousValue = result;
    return result;
    }
  }