/*
 *  The org.opensourcephysics.controls package defines the framework for building
 *  user interface controls for the book Simulations in Physics.
 *  Copyright (c) 2003  H. Gould, J. Tobochnik, and W. Christian.
 *
 * Modified version of OSPControl, by Max Perkins and Dr. J. Hasbun
 *
 */

/* This class was modified by Max Perkins and Dr. J. Hasbun in February 2004.
 * inputScrollPane and messsageScrollPane (in the constructor) were resized.
 *
 * Max Perkins was sponsored by the NASA Space Grant Consortium through Dr. Ben de Mayo 
 * of the Physics Department at the State University of West Georgia.
 */

package org.opensourcephysics.jahasbun.QE.controls;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.text.NumberFormat;
import org.opensourcephysics.controls.*;
import org.opensourcephysics.display.DrawingFrame;

/**
 *  A Control class for arbitray objects.
 *
 *  The user inteface contains an input text area and a message area.
 *  Custom bottons can be added.
 *
 * @author       Wolfgang Christian
 * @version 1.0
 */
public class EOSPControl extends EControlFrame implements Control {
  protected Object    model;
  private JScrollPane inputScrollPane;  
  private JScrollPane messageScrollPane;
  ParsableTextArea    inputTextArea;
  JTextArea           messageTextArea;
  JPanel              buttonPanel;
  JLabel              clearLabel;
  NumberFormat numberFormat = NumberFormat.getInstance();
  

  /**
   *  Constructs an OSPControl.
   *
   * @param  _model
   */
  public EOSPControl(Object _model) {
    super("OSP Control");
    model = _model;
    Font   labelFont  = new Font("Dialog", Font.BOLD, 12);
    JLabel inputLabel = new JLabel("Enter your input below", SwingConstants.CENTER);
    inputLabel.setFont(labelFont);
    JLabel messageLabel = new JLabel("Messages", SwingConstants.CENTER);
    messageLabel.setFont(labelFont);
    inputTextArea   = new ParsableTextArea();
    messageTextArea = new JTextArea(5, 5);
    inputScrollPane   = new JScrollPane(inputTextArea);
    messageScrollPane = new JScrollPane(messageTextArea);
    Container cp         = getContentPane();
    JPanel    northPanel = new JPanel(new BorderLayout());
    northPanel.add(inputLabel, BorderLayout.NORTH);
    northPanel.add(inputScrollPane, BorderLayout.CENTER);
    buttonPanel = new JPanel();    
    JPanel bottomPanel = new JPanel(new BorderLayout());                    
    bottomPanel.add(buttonPanel, BorderLayout.NORTH);    
    bottomPanel.add(messageLabel, BorderLayout.SOUTH);
    northPanel.add(bottomPanel, BorderLayout.SOUTH);                
    cp.add(northPanel, BorderLayout.NORTH);
    cp.add(messageScrollPane, BorderLayout.CENTER);        
    JPanel southPanel = new JPanel(new BorderLayout());
    southPanel.addMouseListener(new ClearMouseAdapter());
    clearLabel = new JLabel(" clear");
    clearLabel.setFont(new Font(clearLabel.getFont().getFamily(), Font.PLAIN, 9));
    clearLabel.setForeground(Color.black);
    southPanel.add(clearLabel, BorderLayout.WEST);
    cp.add(southPanel, BorderLayout.SOUTH);            
    messageTextArea.setEditable(false);
    
    //inputScrollPane.setPreferredSize(new Dimension(250,200));
    //messageScrollPane.setPreferredSize(new Dimension(250,50));
    inputScrollPane.setPreferredSize(new Dimension(210,175));     // had to be resized
    messageScrollPane.setPreferredSize(new Dimension(210,200));   // had to be resized
    
    Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
    setLocation( (d.width - getSize().width) / 2,(d.height - getSize().height) / 2); // center the frame    
    init();
  }

  /**
   * Sets the dimensions of the input scroll pane to (x, y)
   *
   * Added by Dr. J. Hasbun and Max Perkins
   */
  public void setInputScrollPaneSize(int x, int y) {
    inputScrollPane.setPreferredSize(new Dimension(x, y));
  }
 
  /** 
   * Sets the dimensions of the message scroll panel to (x, y)
   *
   * Added by Dr. J. Hasbun and Max Perkins
   */
  public void setMessageScrollPaneSize(int x, int y) {
      messageScrollPane.setPreferredSize(new Dimension(x, y));
  }
  
  /**
   * Sets the dimensions of the button panel to (x, y)
   *
   * Added by Dr. J. Hasbun and Max Perkins
   */
  public void setButtonPanelSize(int x, int y) {      
      buttonPanel.setPreferredSize(new Dimension(x, y));
  }
  
  /**
   * Initializes this control after all objects have been created.
   *
   * Override this method and change the default close operation if this control is used with an applet.
   */
  protected void init(){
    validate();
    pack();
    setVisible(true);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  }

  /**
   *  Creates a string representation of the control parameters.
   *
   * @return    the control parameters
   */
  public String toString() {
    return inputTextArea.getText();
  }

  /**
   *  Adds an initial value of a parameter to the input display.
   *
   * @param  par  the parameter name
   * @param  val  the initial parameter value
   */
  public void setValue(String par, Object val) {
    inputTextArea.setValue(par, val.toString());
  }

  /**
   *  Adds an initial boolean value of a parameter to the input display.
   *
   * @param  par  the parameter name
   * @param  val  the initial parameter value
   */
  public void setValue(String par, boolean val) {
    inputTextArea.setValue(par, String.valueOf(val));
  }

  /**
   *  Adds an initial value of a parameter to the input display.
   *
   * @param  par  the parameter name
   * @param  val  the initial parameter value
   */
  public void setValue(String par, double val) {
    inputTextArea.setValue(par, Double.toString(val));
  }

  /**
   *  Adds an initial value of a parameter to the input display.
   *
   * @param  par  the parameter name
   * @param  val  the initial parameter value
   */
  public void setValue(String par, int val) {
    inputTextArea.setValue(par, Integer.toString(val));
  }

  /**
   *  Reads a parameter value from the input display.
   *
   * @param  par
   * @return      double the value of of the parameter
   */
  public double getDouble(String par) {
    double val = 0;
    try {
      String str = inputTextArea.getValue(par);
      //val = Double.parseDouble(str);
      val = numberFormat.parse(str).doubleValue();
    } catch(VariableNotFoundException e) {
      println(e.getMessage());
    } catch(java.text.ParseException e) {
      println("Variable " + par + " is not a number");
    }
    return val;
  }

  /**
   *  Reads a parameter value from the input display.
   *
   * @param  par
   * @return      int the value of of the parameter
   */
  public int getInt(String par) {
    int val = (int) getDouble(par);
    return val;
  }

  /**
   *  Reads a parameter value from the input display.
   *
   * @param  par  the parameter name
   * @return      String the value of of the parameter
   */
  public String getString(String par) {
    try {
      String str = inputTextArea.getValue(par);
      return str;
    } catch(VariableNotFoundException e) {
      println(e.getMessage());
      return "";
    }
  }

  /**
   *  Reads a parameter value from the input display.
   *
   * @param  par  the parameter name
   * @return      the value of of the parameter
   */
  public boolean getBoolean(String par) {
    boolean val = false;
    try {
      String str = inputTextArea.getValue(par);
      str = str.toLowerCase().trim();
      if(str.equals("true")) {
        val = true;
      } else if(!str.equals("false")) {
        println("Error: Boolean variable must be true or false.");
      }
    } catch(VariableNotFoundException e) {
      println(e.getMessage());
    }
    return val;
  }

  /**
   *  Adds a custom button to the control's frame.
   *
   * @param  methodName  the name of the method; the method has no parameters
   * @param  text        the button's text label
   * @return             the custom button
   */
  public JButton addButton(String methodName, String text) {      
    return addButton(methodName, text, null);
  }

  /**
   *  Adds a custom button to the control's frame.
   *
   * @param  methodName   the name of the method; the method has no parameters
   * @param  text         the button's text label
   * @param  toolTipText  the button's tool tip text
   * @return              the custom button
   */
  public JButton addButton(String methodName, String text, String toolTipText) {    
    Font   labelFont  = new Font("Dialog", Font.BOLD, 12);
    JButton b = new JButton(text);
    b.setFont(labelFont);
    b.setToolTipText(toolTipText);
    
    Class[] parameters = {};
    try {
      final java.lang.reflect.Method m = model.getClass().getMethod(methodName, parameters);
      b.addActionListener(new ActionListener() {

        public void actionPerformed(ActionEvent e) {
          Object[] args = {};
          try {
            m.invoke(model, args);
          } catch(IllegalAccessException iae) {}
          catch(java.lang.reflect.InvocationTargetException ite) {}
        }
      });
      
      buttonPanel.add(b);
      validate();          
      pack();
    } catch(NoSuchMethodException nsme) {
      System.err.println("Error adding custom button " + text + ". The method " + methodName + "() does not exist.");
    }
    return b;
  }


  /**
   *  Prints a line of text in the message area.
   *
   * @param  s
   */
  public void println(String s) {
    messageTextArea.append(s + "\n");
  }

  /**
   *  Prints a blank line in the message area.
   */
  public void println() {
    messageTextArea.append("\n");
  }

  /**
   *  Prints text in the message area.
   *
   * @param  s
   */
  public void print(String s) {
    messageTextArea.append(s);
  }

  /**
   *  Remove all text from the message area.
   */
  public void clearMessages() {
    messageTextArea.setText("");
  }

  /**
   *  Remove all text from the data input area.
   */
  public void clearValues() {
    inputTextArea.setText("");
  }

  /**
   *  A signal that a method has completed. A message is printed in the message area.
   *
   * @param  message
   */
  public void calculationDone(String message) {
    // not implemented
    println(message);
  }

  private class ClearMouseAdapter extends java.awt.event.MouseAdapter {

    /**
     * Method mousePressed
     *
     * @param evt
     */
    public void mousePressed(java.awt.event.MouseEvent evt) {
      messageTextArea.setText("");
    }

    /**
     * Method mouseEntered
     *
     * @param evt
     */
    public void mouseEntered(java.awt.event.MouseEvent evt) {
      clearLabel.setFont(new Font(clearLabel.getFont().getFamily(), Font.BOLD, 10));
      clearLabel.setText(" click here to clear messages");
    }

    /**
     * Method mouseExited
     *
     * @param evt
     */
    public void mouseExited(java.awt.event.MouseEvent evt) {
      clearLabel.setFont(new Font(clearLabel.getFont().getFamily(), Font.PLAIN, 9));
      clearLabel.setText(" clear");
    }
  }

}

