/*
 * TideHeight.java
 * Contains the code for the creation of the user interface of Earthguide's
 * Java based Tide Calendar.
 */

//package tideCalendar;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.awt.font.*;
import java.io.*;
import java.util.GregorianCalendar;
import java.util.LinkedList;
import java.util.ListIterator;
import java.util.Timer;
import java.util.TimerTask;
/**
 * TideHeight is a class whose purpose is to create the user interface for
 * the scrolling view of the tide.  For the implementation of the calendar
 * view, see <code>CalendarFrame.java</code>
 *
 * @author  Tim Bollman
 * @author  Earthguide
 * @version 2.5 06-20-05
 */
public class TideHeight extends JPanel
{
   /* Global variables*/
   //The Image at the top of the Window
   private ImageIcon titleImage=Shared.loadImage("new_banner.jpg", 9800, this);
   // Stores the data for the phases of the moon
   private Moon myMoon = new Moon();
   //What time scale is currently active in the tide view window.  The
   //three possible values are WEEK, MONTH, and YEAR (0,1,2)
   private byte currentMode = Shared.WEEK;
   // Stores the data that is given to the user about the height of the line
   // at a given point on the screen.  The default size is 600, but that size
   // changes based on the currentMode
   private float[] featuredLine = new float[600];
   // Stores the height of the tide as used in the graphing function at a given
   // point on the screen.  The default size is 600, but that size changes
   // based on the currentMode
   private LinkedList ylocation[] = {new LinkedList(),new LinkedList()}; 
   // Stores the time of the tide as used in the graphing function at a given
   // point on the screen.  The default size is 600, but that size changes
   // based on the currentMode
   private LinkedList xlocation[] = {new LinkedList(),new LinkedList()};
   // A variable used to ensure that the tide-line will be redrawn in
   // certain useful circumstances.
   private boolean rebuild[] = {false,false};
   // A Queue that is used to to store the ImageIcons of the moons.  The
   // ImageIcon's description is the relative percentage of fullness of the
   // moon
   private MoonQueue moonList = new MoonQueue(9, myMoon);
   // A PopupFactory to create the popups used in this file
   private PopupFactory factory = PopupFactory.getSharedInstance();
   // The actual panel that contains the Tide wave.
   private JPanel wave;
   // The labels that report to the user what lines are currently being drawn
   // on the screen
   private JLabel lineLabel[];
   // The popup that is used to make all of the popups used in this file
   private Popup popup;
   // Tells the program if it is currently running in simulation mode
   private byte simulating = OFF;
   // Tells the program to pause the simulation for a second while data is changed.
   private boolean simPaused = false;
   // the generic boolean and button for whether or not the first option 
   // in a time mode is selected
   private boolean option1 = false;
   private OptionButton opButton1;
   // the generic boolean and button for whether or not the second option
   // in a time mode is selected
   private boolean option2 = false;
   private OptionButton opButton2;
   // the generic boolean and button for whether or not the second option
   // in a time mode is selected
   private boolean option3 = false;
   private OptionButton opButton3;
   private Rectangle simulationRect = new Rectangle(X_OFFSET,Y_OFFSET+HEADER_HEIGHT,WAVE_WIDTH,WAVE_HEIGHT-HEADER_HEIGHT);
   // The Global Timer which is used to schedule the simulation TimerTask.
   private Timer timer;
   //Stores the last day that was accessed for the given tideLines
   private int[] lastDay = {-100,-100};
   
   /**
    * Initializes the Continuous view for Earthguide's Tide Calendar.
    * 
    */
   public TideHeight()
   {
      super(new BorderLayout());
      //createMarks();
      add(createTitle(), BorderLayout.NORTH);
      addMouseListener(new MouseAdapter()
      {
	 public void mouseClicked(MouseEvent e)
	 {
	    popupCheck();
	 }
      });
      // create the moon line
      myMoon.moonReader("moonCharts/moonChart"+Shared.year);
      wave = new JPanel()
      {
	 public void paint(Graphics g)
	 {
	    //Calls parent to clear window
	    super.paint(g);
	    simPaused = true;
	    // Create the "window" that the Tide will be drawn in using a
	    // Graphics2D object.
	    Graphics2D G = (Graphics2D)g;
	    G.translate(X_OFFSET,Y_OFFSET);
	    /* The "Back" buttons*/
	    G.setFont(Format.MODE_SELECTED_FONT);
	    G.drawString("Continuous",0,383);
	    G.setColor(Format.CAL_LINECOLOR);
	    G.setFont(Format.MODE_UNSELECTED_FONT);
	    G.drawString("Calendar",WAVE_WIDTH-55,383);
	    //Main view screen
	    G.setColor(Format.VIEWSCREEN);
	    G.fillRoundRect(0,0,WAVE_WIDTH,WAVE_HEIGHT,15,15);
	    //Header
	    G.setColor(Format.VIEWSCREENHEAD);
	    G.fill(new RoundRectangle2D.Double(0,0,WAVE_WIDTH,
					       HEADER_HEIGHT,10, 10));
	    // Bottom of Header is flush with rest of viewscreen, not rounded.
	    G.fill(new Rectangle(0,2*HEADER_HEIGHT/3,
				 WAVE_WIDTH,HEADER_HEIGHT/3));
	    // Outline the view screen in gray
	    G.setColor(Format.SEPERATOR);
	    G.drawRoundRect(0,0,WAVE_WIDTH,WAVE_HEIGHT,15,15);
	    // differentiate between the Title and the view screen with a
	    //  gray line
	    G.drawLine(0,HEADER_HEIGHT,WAVE_WIDTH,HEADER_HEIGHT);
	    //Create the LLMT line in black
	    drawTickMarks(G);
	    // Tell the program where it is allowed to draw (the main view
	    // screen) through the use of a clip
	    G.clip(new Rectangle2D.Double(0,0,WAVE_WIDTH,WAVE_HEIGHT));
	    switch(currentMode)
	    {
	    case Shared.WEEK:
	       drawWeek(G);
	       G.setStroke(Format.THICKSTROKE);
	       break;
	    case Shared.MONTH:
	       drawMonth(G);
	       G.setStroke(Format.THICKSTROKE);
	       break;
	    case Shared.YEAR:
	       drawYear(G);
	       break;
	    }
	    //initialize the generalPath that stores the path of the tideLine
	    GeneralPath polyline;
	    if (Shared.parameterArray[1] != null)
	    {
	       G.setColor(Format.LINE2);
	       polyline = graphTide(1);
	       G.draw(polyline);
	    }
	    if (Shared.parameterArray[0] != null)
	    {
	       G.setColor(Format.LINE1);
	       polyline = graphTide(0);
	       G.draw(polyline);
	    }
	    /*
	    G.setStroke(new BasicStroke());
	    for (int i = 0; i < tideLocations.length;i++)
	    {
	       int x = (int)Math.round(tideLocations[i].x - Shared.offset*Shared.PIXELCONVERT);
	       int y = (int)Math.round(tideLocations[i].y);
	       if (x < 0)
		  continue;
	       if (x > 600)
		  break;
	       //System.out.println(tideLocations[i]);
	       G.setColor(Color.magenta);
	       G.drawLine(x-3,y,x+3,y);
	       G.drawLine(x,y-3,x,y+3);
	    }
	    */
	    G.setColor(Color.black);
	    simPaused = false;
         }
      };
      wave.setBackground(Format.MAIN);
      // Creates a Listener to monitor the movement of the mouse over the wave window.
      // This Listener will then add the height and location of the wave at that
      // point to the bottom of the screen
      wave.addMouseListener(new MouseAdapter()
      {
	 public void mouseClicked(MouseEvent e)
	 {
	    popupCheck();
	    if (currentMode != Shared.YEAR)
	    {//they could be attempting to click on a month selector
	       Point p = e.getPoint();
	       Rectangle inner;
	       int i=0;
	       Rectangle outer = new Rectangle(X_OFFSET,Y_OFFSET,WAVE_WIDTH,
					       HEADER_HEIGHT);
	       if (outer.contains(p)) //clicked outside the header
	       {
		  simPaused = true;
		  // point is within the header, so determine the month.
		  // Only need to check the first 11 months because if it is not
		  // in the first 11 months and it is within the header, it has
		  // to be in the last month.
		  Shared.offset = 0;
		  for (; i < 11; i++)
		  {
		     inner = new Rectangle(X_OFFSET+i*50,Y_OFFSET,50,30);
		     if (inner.contains(p))
			break;
		     Shared.offset += Shared.monthEnd[i]*24;
		  }
		  Shared.currentMonth = i;
		  Shared.currentDay = 1;
		  rebuild[0] = true;
		  rebuild[1] = true;
		  wave.paintImmediately(wave.getVisibleRect());
		  simPaused = false;
		  return;
	       }
	       outer = new Rectangle(X_OFFSET+WAVE_WIDTH-60,
				     Y_OFFSET+WAVE_HEIGHT,67,17);
	       if (outer.contains(p))
	       {
		  if (currentMode != Shared.WEEK)
		     modeChanger(Shared.WEEK);
		  else 
		  {// in week mode already, so end simulation and set
		   // the moons to refresh when we return from Calendar 
		   // View by clearing the queue.
		     if (option1)
			opButton1.doClick();
		  }
		  if (opButton1.isDeactivated())
		     opButton1.activate();
		  if (opButton2.isDeactivated())
		     opButton2.activate();
		  opButton1.setText("Auto-Scroll: Forward");
		  opButton2.setText("Auto-Scroll: Back");
		  opButton3.setText("Lunar Cycle");
		  Tides.changeToCalendar();
	       }
	    }
	 }
      });
      wave.addMouseMotionListener(new MouseMotionListener()
      {
	 private final Rectangle waveBounds = 
		     new Rectangle(X_OFFSET,Y_OFFSET+HEADER_HEIGHT, 
				   WAVE_WIDTH,WAVE_HEIGHT-HEADER_HEIGHT);
	 private final Rectangle headerBounds = 
		     new Rectangle(X_OFFSET,Y_OFFSET,WAVE_WIDTH,HEADER_HEIGHT);
	 private final Rectangle calBounds = 
		     new Rectangle(X_OFFSET+WAVE_WIDTH-60,
				   Y_OFFSET+WAVE_HEIGHT,67,17);
	 private final Rectangle contBounds =
		     new Rectangle (X_OFFSET-5,Y_OFFSET+WAVE_HEIGHT,90,17);
	 public void mouseMoved(MouseEvent e)
	 {
	    Point p = e.getPoint();
	    if (simulating == OFF)
	    {
	       if (waveBounds.contains(p))
	       {
		  float offset = (p.x - X_OFFSET)/Shared.PIXELCONVERT + Shared.offset;
		  wave.setToolTipText(Shared.parameterArray[0].getExtremas(offset));
	       }
	       else if (headerBounds.contains(p))
	       {
		  int x = (p.x - X_OFFSET)/50;
		  String month = Shared.monthList[x];
		  wave.setToolTipText("Jump to " + month);
	       }
	       else if (calBounds.contains(p))
	       {
		  wave.setToolTipText("Change to Calendar View");
	       }
	       else if (contBounds.contains(p))
	       {
		  wave.setToolTipText("Current View");
	       }
	       else
	       {
		  wave.setToolTipText(null);
	       }
	    }
	 }
	 public void mouseDragged(MouseEvent e)
	 {return;}
      });
      //Begin creation of the labels at the bottom the the screen
      add(wave, BorderLayout.CENTER);
      add(createBottom(), BorderLayout.SOUTH);
   }
   /**
    * Creates the Title Panel for the Tide Screen and returns it.
    *
    * @return the Title JPanel
    */
   private JPanel createTitle()
   {
      /* The actual Panel that stores the title*/
      JPanel titlePanel = new JPanel()
      {
	 public void paintComponent(Graphics g)
	 {
	    super.paintComponent(g);
	    titleImage.paintIcon(this, g, 0,0);
      	 }
      };
      titlePanel.setPreferredSize(new Dimension(Shared.FRAME_WIDTH,
						Shared.FRAME_HEIGHT/8));
      return titlePanel;
   }
   /**
    * Creates the options panel that appears on the bottom of the screen.
    *
    * @return the Panel that will appear on the bottom of the screen
    */
   private JPanel createBottom()
   {
      /* The panel that will contain the options.  It will be split up
       * into three options categories:
       * Left) Choosing which lines are being graphed
       * Center) Choosing the time mode that is drawn
       * Right) myriad options that the user can choose based on the time mode
       *
       * There will be a logical split of the Panels into 2 sections: Title and
       * buttons, which will create uniformity of space usage.
       */
      final JPanel bottomPanel = new JPanel(new GridBagLayout());
      // Constraints for the bottom panel that tell it how to place objects
      GridBagConstraints c = new GridBagConstraints();
      // Intermediary container
      JPanel container1;
      // Intermediary container
      JPanel container2;
      // Intermediary container
      JPanel container3;
      // Strings that describe formatting
      final String STDINTRO="<HTML><font color="
			    + Shared.colorString(Format.BOTTOMTEXT) + ">";
      final String SIZEINTRO="<HTML><font color="
			     + Shared.colorString(Format.BOTTOMTEXT) + ">";
      final String TITLEINTRO="<HTML><font color="
			      + Shared.colorString(Format.TITLE) + ">";
      final String END = "</font></HTML>";
      // Used for titles of the 3 sections
      JLabel myLabel;
      // Creates the two labels that store the lines the user can see
      lineLabel = new JLabel[2];
      // Sets the initial values of the two labels
      lineLabel[0] = new JLabel(SIZEINTRO+"None Selected"+END,
							 SwingConstants.LEFT);
      lineLabel[1] = new JLabel(SIZEINTRO+"None Selected"+END,
							 SwingConstants.LEFT);
      // The labels that will store the options availible to the user
      final JLabel optionLabel1 = new JLabel();
      final JLabel optionLabel2 = new JLabel();
      // The Buttons that are used in the center panel 
      final JButton mode1 = new JButton();
      final JButton mode2 = new JButton();
      final JButton mode3 = new JButton();
      // Reusable button
      JButton myButton;
      // Start function body
      bottomPanel.setPreferredSize(new Dimension(660,100));
      bottomPanel.setBackground(Format.BOTTOM);
      lineLabel[0].setFont(Format.BASICFONT);
      lineLabel[1].setFont(Format.BASICFONT);
      optionLabel1.setFont(Format.BASICFONT);
      optionLabel2.setFont(Format.BASICFONT);
      //Title Panel
      container1 = new JPanel(new FlowLayout(0,0,0));
      container1.setBackground(Format.BOTTOM);
      // Title 1
      myLabel = new JLabel(TITLEINTRO+"Location"+END, SwingConstants.LEFT);
      myLabel.setFont(Format.TITLEFONT);
      myLabel.setPreferredSize(new Dimension(210,30));
      myLabel.setMinimumSize(new Dimension(210,30));
      container1.add(myLabel);
      // Title 2
      myLabel = new JLabel(TITLEINTRO+"Time Window"+END, SwingConstants.LEFT);
      myLabel.setFont(Format.TITLEFONT);
      myLabel.setPreferredSize(new Dimension(210,30));
      myLabel.setMinimumSize(new Dimension(210,30));
      container1.add(myLabel);
      // Title 3
      myLabel = new JLabel(TITLEINTRO+"Options"+END, SwingConstants.LEFT);
      myLabel.setFont(Format.TITLEFONT);
      myLabel.setPreferredSize(new Dimension(150,30));
      myLabel.setMinimumSize(new Dimension(150,30));
      container1.add(myLabel);
      c.weighty = 1.0;
      c.gridwidth = GridBagConstraints.REMAINDER;
      c.ipadx = 0;
      c.ipady = 0;
      c.insets = new Insets(0,35,3,15);
      bottomPanel.add(container1, c);
      // Panel 1
      // Used as outermost container.  It contains the 3 panels
      container1 = new JPanel(new GridLayout(1,3));
      container1.setBackground(Format.BOTTOM);
      container1.setPreferredSize(new Dimension(660,70));
      container1.setMinimumSize(new Dimension(660,70));
      // Used as the middle container.  It is the 3 panels
      container2 = new JPanel(new GridLayout(2,1));
      container2.setBackground(Format.BOTTOM);
      // Used to contain portions of the Panels
      container3 = new JPanel(new FlowLayout(0,5,0));
      container3.setBackground(Format.BOTTOM);
      // Line 1
      if (Shared.parameterArray[0] != null)
      {
	 lineLabel[0].setText("<HTML><font color=#FFFFFF>" +
			    Shared.parameterArray[0].getLine() + 
			    "</font></HTML>");
      }
      lineLabel[0].setPreferredSize(new Dimension(165,30));
      // button that creates the popup to change the 1st line
      myButton = new JButton(TITLEINTRO+"1"+END);
      myButton.setFont(Format.TITLEFONT);
      myButton.setBackground(Format.BOTTOM);
      myButton.setBorder(Format.LOCBORDER);
      myButton.setPreferredSize(new Dimension(30,30));
      myButton.addActionListener(new ActionListener()
      {
	 public void actionPerformed(ActionEvent e)
	 {
	    final Component caller = (Component)e.getSource();
	    Point p = bottomPanel.getLocationOnScreen();
	    popupCheck();
	    caller.setBackground(Format.MODEBUTTON);
	    popup = new Popup(bottomPanel,createLinePane(0),
				       p.x+230,p.y+5)
	    {
	       public void hide()
	       {
		  caller.setBackground(Format.BOTTOM);
		  super.hide();
	       }
	    };
	    popup.show();
	 }
      });
      container3.add(myButton);
      container3.add(lineLabel[0]);
      container2.add(container3);
      // Line 2
      container3 = new JPanel(new FlowLayout(0,5,0));
      container3.setBackground(Format.BOTTOM);
      if (Shared.parameterArray[1] != null)
      {
	 lineLabel[1].setText("<HTML><font color=#FF0000>" +
			    Shared.parameterArray[1].getLine() + 
			    "</font></HTML>");
      }
      lineLabel[1].setPreferredSize(new Dimension(165,30));
      // button that creates the popup to change the second line
      myButton = new JButton(TITLEINTRO+"2"+END);
      myButton.setFont(Format.TITLEFONT);
      myButton.setBackground(Format.BOTTOM);
      myButton.setBorder(Format.LOCBORDER);
      myButton.setPreferredSize(new Dimension(30,30));
      myButton.addActionListener(new ActionListener()
      {
	 public void actionPerformed(ActionEvent e)
	 {
	    final Component caller = (Component)e.getSource();
	    Point p = bottomPanel.getLocationOnScreen();
	    popupCheck();
	    caller.setBackground(Format.MODEBUTTON);
	    popup = new Popup(bottomPanel,createLinePane(1),
				       p.x+230,p.y+5)
	    {
	       public void hide()
	       {
		  caller.setBackground(Format.BOTTOM);
		  super.hide();
	       }
	    };
	    popup.show();
	 }
      });
      container3.add(myButton);
      container3.add(lineLabel[1]);
      container2.add(container3);
      container1.add(container2);
      
      //Panel 2 (Center panel) 3 sections: Title, button panel, and empty space

      // Container1 stores the panel as a whole and container2 stores
      // the 3 buttons and the filler panel at the bottom
      container2 = new JPanel(new GridLayout(3,1));
      container2.setBackground(Format.BOTTOM);
      //Week button
      container3 = new JPanel(new FlowLayout(0,5,0));
      container3.setBackground(Format.BOTTOM);
      mode1.setBackground(Format.MODEBUTTON);
      mode1.setPreferredSize(new Dimension(15, 15));
      mode1.setBorder(Format.MODEBORDER);
      myLabel = new JLabel(STDINTRO+"One Week"+END);
      myLabel.setFont(Format.BASICFONT);
      myLabel.addMouseListener(new MouseAdapter()
      {
	 public void mouseClicked(MouseEvent e)
	 {
	    mode1.doClick();
	 }
      });
      mode1.addActionListener(new ActionListener()
      {
	 public void actionPerformed(ActionEvent e)
	 {
	    mode1.setBackground(Format.MODEBUTTON);
	    mode2.setBackground(Format.BOTTOM);
	    mode3.setBackground(Format.BOTTOM);
	    modeChanger(Shared.WEEK);
	    opButton1.setText("Auto-Scroll: Forward");
	    opButton2.setText("Auto-Scroll: Back");
	    opButton3.setText("Lunar Cycle");
	    if (opButton1.isDeactivated())
	       opButton1.activate();
	    if (opButton2.isDeactivated())
	       opButton2.activate();
	    if (opButton3.isDeactivated())
	       opButton3.activate();
	 }
      });
      container3.add(mode1);
      container3.add(myLabel);
      container2.add(container3);
      //Month button
      container3 = new JPanel(new FlowLayout(0,5,0));
      container3.setBackground(Format.BOTTOM);
      mode2.setBackground(Format.BOTTOM);
      mode2.setPreferredSize(new Dimension(15, 15));
      mode2.setBorder(Format.MODEBORDER);
      myLabel = new JLabel(STDINTRO+"One Month"+END);
      myLabel.setFont(Format.BASICFONT);
      myLabel.addMouseListener(new MouseAdapter()
      {
	 public void mouseClicked(MouseEvent e)
	 {
	    mode2.doClick();
	 }
      });
      mode2.addActionListener(new ActionListener()
      {
	 public void actionPerformed(ActionEvent e)
	 {
	    mode1.setBackground(Format.BOTTOM);
	    mode2.setBackground(Format.MODEBUTTON);
	    mode3.setBackground(Format.BOTTOM);
	    modeChanger(Shared.MONTH);
	    opButton1.setText("Auto-Scroll: Forward");
	    opButton2.setText("Auto-Scroll: Back");
	    opButton3.setText("Lunar Cycle");
	    if (opButton1.isDeactivated())
	       opButton1.activate();
	    if (opButton2.isDeactivated())
	       opButton2.activate();
	    if (opButton3.isDeactivated())
	       opButton3.activate();
	 }
      });
      container3.add(mode2);
      container3.add(myLabel);
      container2.add(container3);
      //Year button
      container3 = new JPanel(new FlowLayout(0,5,0));
      container3.setBackground(Format.BOTTOM);
      mode3.setBackground(Format.BOTTOM);
      mode3.setPreferredSize(new Dimension(15, 15));
      mode3.setBorder(Format.MODEBORDER);
      myLabel = new JLabel(STDINTRO+"One Year"+END);
      myLabel.setFont(Format.BASICFONT);
      myLabel.addMouseListener(new MouseAdapter()
      {
	 public void mouseClicked(MouseEvent e)
	 {
	    mode3.doClick();
	 }
      });
      mode3.addActionListener(new ActionListener()
      {
	 public void actionPerformed(ActionEvent e)
	 {
	    Shared.offset = 0;
	    mode1.setBackground(Format.BOTTOM);
	    mode2.setBackground(Format.BOTTOM);
	    mode3.setBackground(Format.MODEBUTTON);
	    modeChanger(Shared.YEAR);
	    if (!opButton1.isDeactivated())
	       opButton1.deactivate();
	    if (!opButton2.isDeactivated())
	       opButton2.deactivate();
	    if (!opButton3.isDeactivated())
	       opButton3.deactivate();
	 }
      });
      container3.add(mode3);
      container3.add(myLabel);
      container2.add(container3);
      container1.add(container2);
      //<<EDIT>panel 3 (Right panel) 3 sections?: title and 2 options
      // Container 1 stores the panel as a whole and container 2 stores the
      // option panels
      container2 = new JPanel(new GridLayout(3,1));
      container3 = new JPanel(new FlowLayout(0,5,0));
      container2.setBackground(Format.BOTTOM);
      container3.setBackground(Format.BOTTOM);
      //option 1
      //Preset to off.
      myLabel = new JLabel();
      opButton1 = new OptionButton();
      opButton1.setOnBackground(Format.OPTION_ON);
      opButton1.setOffBackground(Format.OPTION_OFF);
      opButton1.setBorder(Format.OPTIONBORDER);
      opButton1.setLabel(myLabel);
      opButton1.setTextColor(Format.BOTTOMTEXT);
      opButton1.setFont(Format.BASICFONT);
      opButton1.setText("Auto-Scroll: Forward");
      opButton1.setBackground(Format.OPTION_OFF);
      opButton1.setPreferredSize(new Dimension(15, 15));
      opButton1.addActionListener(new ActionListener()
      {
	 public void actionPerformed(ActionEvent e)
	 {
	    // Week or Month: Simulation
	    // Year: <<UNKNOWN>>
	    simPaused = true;
	    switch(currentMode)
	    {
	    case Shared.WEEK:
	    case Shared.MONTH:
	       if (option2)
		  opButton2.doClick();
	       if (!option1) //simulate
		  doSimulation();
	       else //stop simulation
	       {
		  endSimulation();
		  while(simulating != OFF);
	       }
	       break;
	    case Shared.YEAR:
	       break;
	    }
	    option1 = !option1;
	    opButton1.changeState();
	    simPaused = false;
	 }
      });
      container3.add(opButton1);
      container3.add(myLabel);
      container2.add(container3);
      //option 2
      //preset to off
      container3 = new JPanel(new FlowLayout(0,5,0));
      container3.setBackground(Format.BOTTOM);
      myLabel = new JLabel();
      opButton2 = new OptionButton();
      opButton2.setLabel(myLabel);
      opButton2.setOnBackground(Format.OPTION_ON);
      opButton2.setOffBackground(Format.OPTION_OFF);
      opButton2.setBorder(Format.OPTIONBORDER);
      opButton2.setTextColor(Format.BOTTOMTEXT);
      opButton2.setFont(Format.BASICFONT);
      opButton2.setText("Auto-Scroll: Back");
      opButton2.setBackground(Format.OPTION_OFF);
      opButton2.setPreferredSize(new Dimension(15, 15));
      opButton2.addActionListener(new ActionListener()
      {
	 public void actionPerformed(ActionEvent e)
	 {
	    simPaused = true;
	    switch (currentMode)
	    {
	    case Shared.WEEK:
	    case Shared.MONTH:
	        if (option1)
		  opButton1.doClick();
	       if (!option2) //simulate
		  doBackwardsSimulation();
	       else //stop simulation
	       {
		  endSimulation();
		  while(simulating != OFF);
	       }
	    case Shared.YEAR:
	       break;
	    }
	    option2 = !option2;
	    opButton2.changeState();
	    simPaused = false;
	 }
      });
      container3.add(opButton2);
      container3.add(myLabel);
      container2.add(container3);
      // option 3
      // preset to off
      container3 = new JPanel(new FlowLayout(0,5,0));
      container3.setBackground(Format.BOTTOM);
      myLabel = new JLabel();
      opButton3 = new OptionButton();
      opButton3.setLabel(myLabel);
      opButton3.setOnBackground(Format.OPTION_ON);
      opButton3.setOffBackground(Format.OPTION_OFF);
      opButton3.setBorder(Format.OPTIONBORDER);
      opButton3.setTextColor(Format.BOTTOMTEXT);
      opButton3.setFont(Format.BASICFONT);
      opButton3.setText("Lunar Cycle");
      opButton3.setBackground(Format.OPTION_OFF);
      opButton3.setPreferredSize(new Dimension(15, 15));
      opButton3.addActionListener(new ActionListener()
      {
	 public void actionPerformed(ActionEvent e)
	 {
	    opButton3.changeState();
	    option3 = !option3;
	    switch (currentMode)
	    {
	    case Shared.WEEK:
	    case Shared.MONTH:
	       wave.paintImmediately(wave.getVisibleRect());
	       break;
	    case Shared.YEAR:
	       break;
	    }
	 }
      });
      container3.add(opButton3);
      container3.add(myLabel);
      container2.add(container3);
      container1.add(container2);
      c.weighty = 2.0;
      c.ipadx = 0;
      c.ipady = 0;
      c.insets = new Insets(0,60,0,0);
      bottomPanel.add(container1, c);
      return bottomPanel;
   }
   /**
    * creates the Scrollable pane that is used in the popups for the line
    * selection buttons.
    *
    * @param num1 the line number that the button was pressed for.
    * @return the scrollable panel that will be put in the popup.
    */
   public JPanel createLinePane(final int num1)
   {
      /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
       * Used variables:
       * JPanel container1: the object which contains all of the line
       *       buttons.  It is added to scroller to ensure that it does not
       *       exceed the space alloted for it on the screen.
       * JScrollPane scroller: the Java object which adds scrollbars if needed
       *       based on the size of the object which contains it.
       * JPanel Container2: the container which contains scroller to ensure
       *       that the popup will be of the correct size.
       * JButton menuItem: the clickable lines that will be stored in the pane
       * int size: how large to make the container so that it will be the
       *       the minimum possible size for how many items are stored.
       * final byte LINEMOD: how many pixels to apply for each line of text
       *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
      // the line that the popup has not been called for
      final int num2 = num1^1; //sets num2 to be 1 or 0, whatever num1 is not
      // the strings that denote the RGB color that is used by this line
      final String COLOR1 = "<HTML><font color=" +
			Shared.colorString((num1==0)?Format.LINE1:Format.LINE2)
			      + ">";
      final String COLOR2 = "<HTML><font color=" +
			Shared.colorString((num2==0)?Format.LINE1:Format.LINE2)
			      + "2>";
      final String NONE = "<HTML><font color="
			  + Shared.colorString(Format.BOTTOMTEXT)
			  + ">";
      final String END = "</font></HTML>";
      // Java object which adds scrollbars if needed (based on the size of the
      // information stored versus the size of the viewing panel
      JScrollPane scroller;
      // Intermediary containers
      JPanel container1, container2;
      // Name of the lines that are already being drawn
      String line1 = null;
      String line2 = null;
      // The clickable items that will be stored in the pane
      JButton menuItem;
      // How large to make the viewing pane vertically
      int size = 0;
      // How many pixels each line of text uses
      final byte LINEMOD = 10;
      container1 = new JPanel();
      container1.setLayout(new BoxLayout(container1,BoxLayout.Y_AXIS));
      container1.setBackground(Format.BOTTOM);
      container2 = new JPanel(new FlowLayout(0,0,0));
      container2.setPreferredSize(new Dimension(370,90));//185
      container2.setBackground(Format.BOTTOM);
      // if the two respective lines exist, set the line strings to store the
      // location names of the lines
      if (Shared.parameterArray[num1] != null)
	    line1 = (Shared.parameterArray[num1].getLine()).toString();
      if (Shared.parameterArray[num2] != null)
	    line2 = (Shared.parameterArray[num2].getLine()).toString();
      for (int i = 0; i < Shared.lines.length; i++)
      {
	 // if this line is the one that is currently selected by the
	 // button that called this popup
	 if ((Shared.lines[i].toString()).equals(line1))
	 {
	    // set the button to be the color of the line
	    menuItem = new JButton(COLOR1+Shared.lines[i]+END);
	    // No action should be performed except to close popup
	    menuItem.addActionListener(new ActionListener()
	    {
	       public void actionPerformed(ActionEvent e)
	       {
		  popupCheck();
	       }
	    });
	 }
	 // if this line is the lines stored in the alternate button
	 else if ((Shared.lines[i].toString()).equals(line2))
	 {
	    // set the button to be the color of the line
	    menuItem = new JButton(COLOR2+Shared.lines[i]+END);
	    final int q = i;
	    // temporary storage for the names of the lines
	    final String lineA = line1;
	    final String lineB = line2;
	    // the action of this button is to swap the 2 lines
	    menuItem.addActionListener(new ActionListener()
	    {
	       public void actionPerformed(ActionEvent e)
	       {
		  Parameter temp = Shared.parameterArray[num1];
		  Shared.parameterArray[num1] = Shared.parameterArray[num2];
		  Shared.parameterArray[num2] = temp;
		  wave.paintImmediately(simulationRect);
		  lineLabel[num1].setText(COLOR1+lineB+END);
		  if (Shared.parameterArray[num2] == null)
		     lineLabel[num2].setText(NONE+"None Selected"+END);
		  else
		     lineLabel[num2].setText(COLOR2+lineA+END);
		  //close popup
		  popupCheck();
		  }
	    });
	 }
	 else //not a previously selected line
	 {
	    final int q = i;
	    menuItem = new JButton(NONE+Shared.lines[i]+END);
	    // action is to replace the selector line with the clicked line
	    menuItem.addActionListener(new ActionListener()
	    {
	       public void actionPerformed(ActionEvent E)
	       {
		  // used in case the lines are shorter than the current lines
		  float dis1, dis2 = Float.MAX_VALUE;
		  // change lines
		  Shared.parameterArray[num1] = 
			   Grapher.fileReader(Shared.lines[q]);
		  // Change text in linelabel
		  lineLabel[num1].setText(COLOR1+Shared.lines[q]+END);
		  // update view screen
		  wave.paintImmediately(simulationRect);
		  // remove popup from screen
		  popupCheck();
		  // check if we need to change the total distance
		  dis1 = Shared.parameterArray[num1].getTotalDistance();
		  if (Shared.parameterArray[num2] != null)
		     dis2 = Shared.parameterArray[num2].getTotalDistance();
		  Shared.totalDistance = (long)(Shared.PIXELCONVERT * 
					     ((dis1 < dis2)?dis1:dis2));
	       }
	    });
	 }
	 // removes border from button to make it look like a line of text
	 menuItem.setBackground(Format.BOTTOM);
	 menuItem.setBorderPainted(false);
	 menuItem.setMargin(new Insets(0,0,0,0)); 
	 menuItem.setPreferredSize(new Dimension(330,
				  ((menuItem.getText()).length()/30 + 1)*12));
	 menuItem.addMouseListener(new MouseAdapter()
	 {
	    public void mouseEntered(MouseEvent e)
	    {
	       JButton Caller = (JButton)e.getComponent();
	       Caller.setBackground(Format.CAL_MONTH1);//<<TEMP>>
	    }
	    public void mouseExited(MouseEvent e)
	    {
	       JButton Caller = (JButton)e.getComponent();
	       Caller.setBackground(Format.BOTTOM);
	    }
	 });
	 size += ((menuItem.getText()).length()/30 + 1)*LINEMOD;
	 container1.add(menuItem);
      }
      // Cancel button
      menuItem = new JButton("<HTML><font color=#00CCFF>" +
 			     "Cancel</font></HTML>");
      menuItem.setBackground(Format.BOTTOM);
      menuItem.setBorderPainted(false);
      menuItem.setMargin(new Insets(0,0,0,0)); 
      // no action, just removes popup from screen
      menuItem.addActionListener(new ActionListener()
      {
	 public void actionPerformed(ActionEvent e)
 	 {
	    popupCheck();
 	 }
      });
      menuItem.addMouseListener(new MouseAdapter()
      {
	 public void mouseEntered(MouseEvent e)
	 {
	    JButton Caller = (JButton)e.getComponent();
	    Caller.setBackground(Format.CAL_MONTH1);//<<TEMP>>
	 }
	 public void mouseExited(MouseEvent e)
	 {
	    JButton Caller = (JButton)e.getComponent();
	    Caller.setBackground(Format.BOTTOM);
	 }
      });
      size += ((menuItem.getText()).length()/30 + 1)*LINEMOD;
      container1.add(menuItem);
      // Clear button
      menuItem = new JButton("<HTML><font color=#00CCFF>" +
			     "Clear</font></HTML>");
      menuItem.setBackground(Format.BOTTOM);
      menuItem.setMargin(new Insets(0,0,0,0)); 
      menuItem.setBorderPainted(false);
      // Action depends on which button created popup.  If it was
      // the first line, clear both lines from the screen, if it was the second
      // line, then just clear out the contents of the second line.
      menuItem.addActionListener(new ActionListener()
      {
	 public void actionPerformed(ActionEvent e)
	 {
	    if (num1 == 0) //clear both the lines
	    {
	       Shared.parameterArray[0] = null;
	       lineLabel[0].setText(NONE+"None Selected"+END);
	    }
	    //else just clear the second line
	    Shared.parameterArray[1] = null;
	    lineLabel[1].setText(NONE+"None Selected"+END);
	    // Clear popup
	    popupCheck();
	    Shared.totalDistance = Long.MAX_VALUE;
	    wave.paintImmediately(simulationRect);
	 }
      });
      menuItem.addMouseListener(new MouseAdapter()
      {
	 public void mouseEntered(MouseEvent e)
	 {
	    JButton Caller = (JButton)e.getComponent();
	    Caller.setBackground(Format.CAL_MONTH1);//<<TEMP>>
	 }
	 public void mouseExited(MouseEvent e)
	 {
	    JButton Caller = (JButton)e.getComponent();
	    Caller.setBackground(Format.BOTTOM);
	 }
      });
      size += ((menuItem.getText()).length()/30 + 1)*LINEMOD;
      container1.add(menuItem);
      container1.setPreferredSize(new Dimension(330, size));
      scroller = new JScrollPane(container1);
      scroller.setPreferredSize(new Dimension(370,88));
      scroller.setViewportBorder(null);
      scroller.setBorder(null);
      scroller.setBackground(Format.BOTTOM);
      JPanel topRightContainer = new JPanel(new FlowLayout(0,0,0));
      JPanel header = new JPanel(new FlowLayout(0,1,1))
      {
	 public void paint(Graphics g)
	 {
	    g.setColor(Format.LINECOLOR);
	    g.drawLine(0,14,352,14);
	    g.drawLine(352,0,352,14);
	    g.setColor(Format.TITLE);
	    g.drawString("Tide Locations",150,11);
	 }
      };
      header.setPreferredSize(new Dimension(355,15));
      header.setBackground(Format.BOTTOM);
      JButton cancelButton = new JButton("<HTML><font color=#FFFFFF>X</font>");
      cancelButton.setPreferredSize(new Dimension(15,15));
      cancelButton.setMargin(new Insets(0,0,0,0));
      cancelButton.setBorder(null);
      cancelButton.setBackground(Format.BOTTOM);
      cancelButton.addActionListener(new ActionListener()
      {
	 public void actionPerformed(ActionEvent e)
	 {
	    popupCheck();
	 }
      });
      cancelButton.addMouseListener(new MouseAdapter()
      {
	 public void mouseEntered(MouseEvent e)
	 {
	    JButton Caller = (JButton)e.getComponent();
	    Caller.setText("<HTML><font color=#CCCCFF>X</font></HTML>");
	 }
	 public void mouseExited(MouseEvent e)
	 {
	    JButton Caller = (JButton)e.getComponent();
	    Caller.setText("<HTML><font color=#FFFFFF>X</font></HTML>");
	 }
      });
      topRightContainer.add(cancelButton);
      scroller.setCorner(JScrollPane.UPPER_RIGHT_CORNER, topRightContainer);
      scroller.setColumnHeaderView(header);
      container2.add(scroller);
      container2.setBorder(Format.STDBORDER);
      return container2;
   }
   /**
    * Changes the Time Scale being graphed to <code> newMode</code>
    *
    * @param newMode the Time mode that the viewing screen will be changed to.
    */
   private void modeChanger(byte newMode)
   {
      float newFactor = Shared.HrsToPxls[newMode];
      float oldFactor = Shared.PIXELCONVERT;
      if (oldFactor == newFactor)//no action should be taken
	 return;
      if (option1)
	 opButton1.doClick();
      if (option2)
	 opButton2.doClick();
      if (option3)
	 opButton3.doClick();
      Shared.totalDistance =(long)((Shared.totalDistance/oldFactor)*newFactor);
      if (moonList != null) moonList.clear();
      Shared.PIXELCONVERT = newFactor;
      currentMode = newMode;
      lastDay[0] = -100; lastDay[1] = -100;
      rebuild[0] = rebuild[1] = true;
      wave.paintImmediately(wave.getVisibleRect());
   }
   private void drawTickMarks(Graphics2D G)
   {
      // Give some Tick marks for the height of the tide
      //    -Every 5 tick marks should be "bolder" and have a number
      //    -MLLW (ft) is the name of the median line.
      G.setColor(Format.MEDIAN);
      //Goes through the positive tick marks.
      for (int i=2*WAVE_HEIGHT/3-WAVE_AMPLITUDE, j = 1;
	   i > HEADER_HEIGHT; i-= WAVE_AMPLITUDE,j++)
      {
	 if (j % 5 != 0)
	    G.drawLine(0,i,5,i);
	 else
	 {
	    G.drawLine(0,i,8,i);
	    G.drawString(Integer.toString(j),9,i+5);
	 }
      }
      // Draw the Mean Low Low Water indicator and a black line across
      // the "middle" of the viewscreen (actually about 2/3 way down)
      G.drawString("MLLW (ft)",2,2*WAVE_HEIGHT/3-2);
      G.drawLine(0, 2*WAVE_HEIGHT/3,
	         WAVE_WIDTH,2*WAVE_HEIGHT/3);
      //Goes through the negative Tick marks
      for (int i=2*WAVE_HEIGHT/3+WAVE_AMPLITUDE, j = 1;
	   i < WAVE_HEIGHT; i+= WAVE_AMPLITUDE,j++)
      {
	 if (j % 5 != 0)
	    G.drawLine(0,i,5,i);
	 else
	 {
	    G.drawLine(0,i,8,i);
	    G.drawString(Integer.toString(j),9,i+5);
	 }
      }
   }
   private void drawWeek(Graphics2D G)
   {
      // Draw the Months in the header of the viewscreen.
      G.setFont(Format.MONTH_SELECTOR_FONT);
      for (int i = 0; i < 12; i++)
      {
	 if (i != Shared.currentMonth)
	    G.setColor(Format.MONTH_HEADER);
	 else
	    G.setColor(Format.MONTH_HEADER_SELECTED);
	 G.drawString(Shared.monthShort[i], 13+i*50,
		      2*HEADER_HEIGHT/3);
      }
      // get the number of days that have passed since the 
      // beginning of the new year
      final int totalDays = (int)(Shared.offset/24);
      final int DAY_DISTANCE =  (int)(Shared.PIXELCONVERT*24);
      int xLoc = (int)Math.round((totalDays*24-Shared.offset)*Shared.PIXELCONVERT);
      //starting with the current day, draw in day seperators.
      for (int i=totalDays;i<9+totalDays;i++)
      {
	 if (Shared.beyondYear(i))
	    break;
	 ImageIcon moonPic;
	 //draw a day seperator
	 G.setColor(Format.SEPERATOR);
	 G.drawLine(xLoc,HEADER_HEIGHT,xLoc,WAVE_HEIGHT);
	 //tell the user what day it is
	 G.setColor(Format.DATETEXT);
	 FontRenderContext frc = G.getFontRenderContext();
	 TextLayout text = new TextLayout(Shared.toMonth(i),
					  Format.DATEFONT,frc);
	 Rectangle2D bounds = text.getBounds();
	 int buffer = (int)(DAY_DISTANCE - bounds.getWidth())/2;
	 text.draw(G, xLoc+buffer,WAVE_HEIGHT-70);
	 if (option3) //if the moon should be drawn
	 {
	       //get the pertinant moon
	       moonPic = (ImageIcon)moonList.getMoon(i);
	       //paint it on screen
	       moonPic.paintIcon(this, G, xLoc+22,HEADER_HEIGHT+40);
	       //if it is a full or new moon, tell the user.
	       String description = moonPic.getDescription();
	       if (description == "Full Moon" || description == "New Moon")
	       {
		  text = new TextLayout(description,Format.DATEFONT,frc);
		  bounds = text.getBounds();
		  buffer = (int)(DAY_DISTANCE - bounds.getWidth())/2;
		  text.draw(G, xLoc+buffer,HEADER_HEIGHT+35);
	       }
	 }
	 xLoc += DAY_DISTANCE;
      }
   }
   private void drawMonth(Graphics2D G)
   {
      G.setFont(Format.MONTH_SELECTOR_FONT);
      for (int i = 0; i < 12; i++)
      {
	 if (i != Shared.currentMonth)
	    G.setColor(Format.MONTH_HEADER);
	 else
	    G.setColor(Format.MONTH_HEADER_SELECTED);
	 G.drawString(Shared.monthShort[i], 13+i*50,
		      2*HEADER_HEIGHT/3);
      }
      // get the number of days that have passed since the 
      // beginning of the new year
      final int totalDays = (int)(Shared.offset/24/7)*7;
      final int DAY_DISTANCE =  (int)(Shared.PIXELCONVERT*24*7);
      int xLoc = (int)Math.round((totalDays*24-Shared.offset)*Shared.PIXELCONVERT);
      //starting with the current day, draw in day seperators.
      for (int i=totalDays;i<42+totalDays;i+=7)
      {
	 if (Shared.beyondYear(i))
	    break;
	 ImageIcon moonPic;
	 //draw a day seperator
	 G.setColor(Format.SEPERATOR);
	 G.drawLine(xLoc,HEADER_HEIGHT,xLoc,WAVE_HEIGHT);
	 //tell the user what day it is
	 G.setColor(Format.DATETEXT);
	 FontRenderContext frc = G.getFontRenderContext();
	 TextLayout text = new TextLayout(Shared.toMonth(i),
					  Format.DATEFONT,frc);
	 Rectangle2D bounds = text.getBounds();
	 int buffer = (int)(DAY_DISTANCE - bounds.getWidth())/2;
	 text.draw(G, xLoc+buffer,WAVE_HEIGHT-70);
	 if (option3) //if the moon should be drawn
	 {
	       //get the pertinant moon
	       moonPic = (ImageIcon)moonList.getMoon(i);
	       //paint it on screen
	       moonPic.paintIcon(this, G, xLoc+22,HEADER_HEIGHT+40);
	       //if it is a full or new moon, tell the user.
	       String description = moonPic.getDescription();
	       if (description == "Full Moon" || description == "New Moon")
		  G.drawString(description,xLoc+22,HEADER_HEIGHT+35);
	 }
	 xLoc += DAY_DISTANCE;
      }
   }
   private void drawYear(Graphics2D G)
   {
      double m = 0;
      G.setColor(Format.TITLE);
      G.setFont(Format.BASICFONT);
      G.drawString(Shared.year + " Full Year mode",10,2*HEADER_HEIGHT/3);
      G.setFont(Format.DATEFONT);
      int days = 0;
      int month = 0;
      while(month < 12)
      {
	 int i = (int)(days*Shared.PIXELCONVERT*24);
	 G.setColor(Format.SEPERATOR);
	 G.drawLine(i, HEADER_HEIGHT,i,WAVE_HEIGHT);
	 G.setColor(Format.DATETEXT);
	 G.drawString(Shared.monthShort[month],i+5,4*WAVE_HEIGHT/5);
	 days += Shared.monthEnd[month++];
      }
      int i = (int)(days*Shared.PIXELCONVERT*24);
      G.setColor(Format.SEPERATOR);
      G.drawLine(i, HEADER_HEIGHT,i,WAVE_HEIGHT);
   }
   /**
    * Graphs the tideLine
    */
   synchronized private GeneralPath graphTide(int lineNum)
   {
      int day = (int)(Shared.offset/24);
      GeneralPath polyline = null;
      ListIterator xLI, yLI;
      boolean first = true;
      switch (simulating)
      {
      case OFF:
	 if (day != lastDay[lineNum])
	 {
	    Grapher.graph(Shared.offset, Shared.parameterArray[lineNum],ylocation[lineNum], xlocation[lineNum], WAVE_WIDTH, 2*WAVE_HEIGHT/3, 0, WAVE_AMPLITUDE, Shared.PIXELCONVERT);
	    lastDay[lineNum] = day;
	 }
	 polyline = new GeneralPath(GeneralPath.WIND_EVEN_ODD,WAVE_WIDTH);
	 polyline.moveTo(((Integer)xlocation[lineNum].get(0)).intValue(),((Integer)ylocation[lineNum].get(0)).intValue());
	 xLI = xlocation[lineNum].listIterator(1);
	 yLI = ylocation[lineNum].listIterator(1);
	 while (xLI.hasNext() && yLI.hasNext())
	 {
	    int x = ((Integer)xLI.next()).intValue();
	    int y = ((Integer)yLI.next()).intValue();
	    polyline.lineTo(x,y);
	 }
	 break;
      case FORWARD:
	 int last=0;
	 if (!rebuild[lineNum])
	    last = ((Integer)xlocation[lineNum].getLast()).intValue();
	 else
	 {
	    rebuild[lineNum]=false;
	    xlocation[lineNum].clear();ylocation[lineNum].clear();
	 }
	 if (last < WAVE_WIDTH+10)
	 {
	    LinkedList xTemp = new LinkedList();
	    LinkedList yTemp = new LinkedList();
	    Grapher.graph(Shared.offset+(last-1)/Shared.PIXELCONVERT, Shared.parameterArray[lineNum],yTemp, xTemp, WAVE_WIDTH*2-last, 2*WAVE_HEIGHT/3, last, WAVE_AMPLITUDE, Shared.PIXELCONVERT);
	    xlocation[lineNum].addAll(xTemp);
	    ylocation[lineNum].addAll(yTemp);
	 }
	 polyline = new GeneralPath(GeneralPath.WIND_EVEN_ODD,WAVE_WIDTH);
	 xLI = xlocation[lineNum].listIterator(0);
	 yLI = ylocation[lineNum].listIterator(0);
	 while (xLI.hasNext() && yLI.hasNext())
	 {
	    //increment the x and y values that are 
	    int x = ((Integer)xLI.next()).intValue() - 1;
	    int y = ((Integer)yLI.next()).intValue();
	    if (x < 0)
	    {
	       xLI.remove();
	       yLI.remove();
	    }
	    else
	    {
	       xLI.set(new Integer(x));
	       if (x < WAVE_WIDTH)
	       {
		  if (first)
		  {
		     polyline.moveTo(x,y);
		     first = false;
		  }
		  else
		     polyline.lineTo(x,y);
	       }
	    }
	 }
	 break;
      case BACK:
	 int firstLoc = WAVE_WIDTH;
	 if (!rebuild[lineNum])
	    firstLoc = ((Integer)xlocation[lineNum].getFirst()).intValue();
	 else
	 {
	    rebuild[lineNum]=false;
	    xlocation[lineNum].clear();ylocation[lineNum].clear();
	 }
	 if (firstLoc > -10) 
	 {
	    LinkedList xTemp = new LinkedList();
	    LinkedList yTemp = new LinkedList();
	    Grapher.graph(Shared.offset-(WAVE_WIDTH+firstLoc)/Shared.PIXELCONVERT, Shared.parameterArray[lineNum],yTemp, xTemp, WAVE_WIDTH+firstLoc, 2*WAVE_HEIGHT/3, -WAVE_WIDTH, WAVE_AMPLITUDE, Shared.PIXELCONVERT);
	    xlocation[lineNum].addAll(0,xTemp);
	    ylocation[lineNum].addAll(0,yTemp);
	 }
	 polyline = new GeneralPath(GeneralPath.WIND_EVEN_ODD,WAVE_WIDTH);
	 xLI = xlocation[lineNum].listIterator(0);
	 yLI = ylocation[lineNum].listIterator(0);
	 while (xLI.hasNext() && yLI.hasNext())
	 {
	    //increment the x and y values that are 
	    int x = ((Integer)xLI.next()).intValue() +1;
	    int y = ((Integer)yLI.next()).intValue();
	    if (x > WAVE_WIDTH)
	    {
	       xLI.remove();
	       yLI.remove();
	    }
	    else
	    {
	       xLI.set(new Integer(x));
	       if (x >= 0)
	       {
		  if (first)
		  {
		     polyline.moveTo(x,y);
		     first = false;
		  }
		  else
		     polyline.lineTo(x,y);
	       }
	    }
	 }
	 break;
      }
      return polyline;
   }
   /**
    *  Checks if the popup exists.  If it does, it removes the popup.
    */
   private void popupCheck()
   {
      if (popup != null)
      {
	 popup.hide();
	 popup = null;
      }
   }

   /**
    * Performs the simulation of the line progressing across the screen.
    */
   private void doSimulation()
   {
      simulating = FORWARD;
      timer = new Timer(true);
      TimerTask simulator = new TimerTask()
      {
	 public void run()
	 {
	    if (!simPaused)
	    {
	       int temp = (int)(Shared.offset/24);
	       Shared.offset += 1/Shared.PIXELCONVERT;
	       //if Offset > length, break;
	       if (temp < (int)(Shared.offset/24))
	       {
		  Shared.currentDay++;
		  if (Shared.currentDay > Shared.monthEnd[Shared.currentMonth])
		  {
		     Shared.currentDay=1;
		     Shared.currentMonth++;
		     wave.paintImmediately(X_OFFSET,Y_OFFSET,WAVE_WIDTH,HEADER_HEIGHT);
		  }
	       }
	       wave.paintImmediately(simulationRect);
	    }
	 }
      };
      timer.scheduleAtFixedRate(simulator, 0, 30);
   }
   private void doBackwardsSimulation()
   {
      simulating = BACK;
      timer = new Timer(true);
      TimerTask simulator = new TimerTask()
      {
	 public void run()
	 {
	    if (!simPaused)
	    {
	       int temp = (int)(Shared.offset/24);
	       if (Shared.offset - 1/Shared.PIXELCONVERT < 0)
	       {
		  opButton2.doClick();
		  return;
	       }
	       Shared.offset -= 1/Shared.PIXELCONVERT;
	       if (temp > (int)(Shared.offset/24))
	       {
		  Shared.currentDay--;
		  if (Shared.currentDay <= 0)
		  {
		     Shared.currentMonth--;
		     wave.paintImmediately(X_OFFSET,Y_OFFSET,WAVE_WIDTH,HEADER_HEIGHT);
		     if (Shared.currentMonth < 0)
		     {
			Shared.offset += 1/Shared.PIXELCONVERT;
			Shared.currentDay++;
			Shared.currentMonth++;
			opButton2.doClick();
		     }
		     Shared.currentDay = Shared.monthEnd[Shared.currentMonth];
		  }
	       }
	       wave.paintImmediately(simulationRect);
	    }
	 }
      };
      timer.scheduleAtFixedRate(simulator, 0, 30);
   }
   /**
    *  Ends the simulation.
    */
   private void endSimulation()
   {
      timer.cancel();
      simulating = OFF;
   }
   private static final int WAVE_HEIGHT = 370;
   private static final int WAVE_WIDTH = 600;
   private static final int HEADER_HEIGHT = 30;
   //X Offset for the Calendar Viewscreen
   private static final int X_OFFSET = (Shared.FRAME_WIDTH - WAVE_WIDTH)/2;
   //Y Offset for the Calendar Viewscreen
   private static final int Y_OFFSET =(17*Shared.FRAME_HEIGHT/24-WAVE_HEIGHT)/2;
   private static final int WAVE_AMPLITUDE = 16;
   private static final byte OFF = 0x00;
   private static final byte ON = 0x10;
   private static final byte FORWARD = 0x11;
   private static final byte BACK = 0x12;
}
