import ifi.plot.BoundingBox;
import ifi.plot.PlotableFunction;

import java.awt.*;
import java.util.Vector;

/*
 * PlotWindows can be used to manage several PlotArea's. It is alslo
 * possible to add labels and a title. The slabel and title are shared
 * by all PlotArea's.
 *
 * This class contains severeal methods which are identical to the
 * ones provided by PlotArea. These methods calls the corresponding
 * function of the active plot area.
 */

public class PlotWindow extends Panel{
  // Data members

  private Label title;
  private Label xlabel;
  private Label ylabel[];
  private int num_areas;

  private PlotArea plotarea[];
  private int active_plotarea;

  // Can be used by the init function.
  private static GridBagConstraints gbc = new GridBagConstraints();
  private GridBagLayout g;

  /*
   * Creates a new PlotWindow. The default window contains one plotarea.
   */

  public PlotWindow(){
    init(1, null);
  }

  /*
   * Creates a new PlotWindow with several plot areas. Each plot area
   * has equal weight (i.e they have the same size).
   */

  public PlotWindow(int no_areas){
    init(no_areas, null);
  }

  /*
   * Creates a new PlotWindow with several plot areas. Each plot
   * has specified weights (i.e their relative sizes are equal to the
   * weights).
   */

  public PlotWindow(int no_areas, double weights[]){
    init(no_areas, weights);
  }

  /*
   * Init plot window.
   */

  void init(int no_areas, double weights[]){
    // We use a GridBagLayout so that we can control the relative
    // sizes of the plot areas, and the sizes required by the title
    // and the labels.
    g = new GridBagLayout();
    setLayout(g);

    // Allocate the plotarea array and the y-label array.
    plotarea = new PlotArea[no_areas];
    ylabel = new Label[no_areas];

    // Set the current active area to be the upper area.
    active_plotarea = 0;

    // Add each area to the grid layout
    gbc.gridx = 1;
    gbc.weightx = 1.0;
    gbc.fill = GridBagConstraints.BOTH;

    for(int i = 0 ; i < no_areas; i++){
      // Create a PlotArea object and store in plotarea array.
      plotarea[i] = new PlotArea();

      // Add plotarea to this PlotWindow
      gbc.gridy = i + 1;

      if(weights != null)
	gbc.weighty = weights[i];
      else
	gbc.weighty = 1.0;

      g.setConstraints(plotarea[i], gbc);
      add(plotarea[i]);
    }

    gbc.weightx = 0.0;
    gbc.weighty = 0.0;

    // Tell the layout manager that the layout of this panel
    // needs to be updated.
    doLayout();

    // Tell awt that this panel needs to be redrawn.
    validate();
  }

  /*
   * Set a title for the active plot. The title is shown centered
   * above the plot area.
   */
  public void setTitle(String s){
    if(title == null){
      title = new Label(s);
      title.setAlignment(Label.CENTER);
      gbc.gridx = 1; gbc.gridy = 0;
      
      g.setConstraints(title, gbc);
      add(title);
    }else
      title.setText(s);

    // Tell awt that this panel needs to be redrawn.
    validate();
  }

  /*
   * Set the label for the x-axis. The label is shown centered
   * below the plot area.
   */
  public void setXLabel(String s){
    if(xlabel == null){
      xlabel = new Label(s);
      xlabel.setAlignment(Label.CENTER);
      gbc.gridx = 1; gbc.gridy = plotarea.length + 1;
      gbc.fill = GridBagConstraints.HORIZONTAL;
      
      g.setConstraints(xlabel, gbc);
      add(xlabel);
    }else
      xlabel.setText(s);

    // Tell awt that this panel needs to be redrawn.
    validate();
  }

  /*
   * Set the label for the y-axis. The label is shown centered
   * to the left of the plot area.
   */
  public void setYLabel(String s){
    if(ylabel[active_plotarea] == null){
      ylabel[active_plotarea] = new Label(s);
      ylabel[active_plotarea].setAlignment(Label.CENTER);
      gbc.gridx = 0; gbc.gridy = active_plotarea + 1;
      gbc.fill = GridBagConstraints.VERTICAL;
      
      g.setConstraints(ylabel[active_plotarea], gbc);
      add(ylabel[active_plotarea]);
    }else
      ylabel[active_plotarea].setText(s);

    // Tell awt that this panel needs to be redrawn.
    validate();
  }

  /*
   * Set the active plot area
   */
  public void setActivePlotArea(int i){
    if((i >= 0) && (i < plotarea.length)) active_plotarea = i;
  }

  /*
   * Add a function to the collection of functions to be plotted.
   */
  public void addFunction(PlotableFunction f){
    plotarea[active_plotarea].addFunction(f);
  }

  /*
   * Remove a function from the collection of functions to be plotted.
   * If this is the last function in the set, all information abound
   * bounds and tickmarks will be deleted.
   */
  public void removeFunction(PlotableFunction f){
    plotarea[active_plotarea].removeFunction(f);
  }

  /*
   * Emty the collection of functions to be plotted.
   * All information abound bounds and tickmarks are also deleted
   */
  public void removeAllFunctions(){
    //for(int i = 0; i < plotarea.length; i++)
    //  if(plotarea[i] != null) plotarea[i].removeAllFunctions();
    plotarea[active_plotarea].removeAllFunctions();
  }

  /*
   * Calculate the bounds of the active plotarea.
   */
  public void calculateBounds(){
    plotarea[active_plotarea].calculateBounds();
  }

  /*
   * Use a fixed bounding box for the active plotarea.
   */
  public void setBoundingBox(BoundingBox b){
    plotarea[active_plotarea].setBoundingBox(b);
  }

  /*
   * Force a redraw of all functions.
   */
  public void updatePlot(){
    for(int i = 0; i < plotarea.length; i++)
      if(plotarea[i] != null) plotarea[i].updatePlot();
  }
} //class PlotWindow
