
/**
 * PlotEditorDialog.java
 * This dialog is used to edit the properties of plots
 *
 * Created: August 10, 2006
 *
 * @author Nathan Stevens
 * @version 0.2 2/4/07
 */
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.event.*;

import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.event.ChartChangeEvent;
import org.jfree.chart.event.ChartChangeListener;
import org.jfree.chart.renderer.*;
import org.jfree.chart.renderer.xy.*;
import org.jfree.chart.title.LegendTitle;

class PlotEditorDialog extends JDialog implements ActionListener {
  private PlotDialog plotDialog = null;
  private JFreeChart chart = null;
  private XYPlot plot = null;
  private XYSeriesCollection dataset = null;
  private XYLineAndShapeRenderer renderer = null;
  private LegendTitle legend = null;
  
  private JCheckBox[] visCB = null; // whether to show the line
  private JTextField[] keyTF = null; // hold the name of the line
  private JButton[] colorB = null; // defines the line color
  private JComboBox[] sizeCoB = null; // defines the line size
  private JCheckBox colorCB = null; // whether to set all colors the same
  private JCheckBox sizeCB = null; // whether to set all lines to the same thickness
  private JButton allColorB = null; // defines the line color for all
  private JComboBox allSizeCoB = null; // defines the line size for all
  private JCheckBox grCB = null; // whether to show the grid
  private JCheckBox chCB = null; // whether to show the crosshair
  private JCheckBox lgCB = null; // whether to show the legend
  
  private int count = 0; // the number of series in the plot
  
  public PlotEditorDialog(PlotDialog plotDialog,  ChartPanel chartPanel) {
    super(plotDialog, "Plot Editor", false);
    
    // get the chart objects
    chart = chartPanel.getChart();
    plot = (XYPlot)chart.getPlot();
    dataset = (XYSeriesCollection)plot.getDataset();
    renderer = (XYLineAndShapeRenderer)plot.getRenderer();
    legend = chart.getLegend();
    
    count = dataset.getSeriesCount();
    visCB = new JCheckBox[count];
    keyTF = new JTextField[count];
    colorB = new JButton[count];
    sizeCoB = new JComboBox[count];
    
    // set the layout
    getContentPane().setLayout(new BorderLayout());
    
    // some gui stuff
    JPanel panel;
    JLabel label;
    JButton button;
    
    // add the panel that hold the button to edit
    JPanel mainPanel = new JPanel();
    mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
    
    // add an editor panel for each series
    String[] size = {"1.0", "1.5", "2.0", "2.5", "3.0"};
    String default_size = "" + plotDialog.line_size;
    
    for(int i = 0; i < count; i++) {
      Color color = (Color)renderer.getSeriesPaint(i);
      
      panel = new JPanel();
      panel.setLayout(new FlowLayout(FlowLayout.LEFT, 2,2));
      
      visCB[i] = new JCheckBox();
      visCB[i].setSelected(true);
      panel.add(visCB[i]);
      
      String key = (String)dataset.getSeriesKey(i);
      keyTF[i] = new JTextField(key, 12);
      keyTF[i].setActionCommand("update_" + i);
      keyTF[i].addActionListener(this);
      panel.add(keyTF[i]);
      
      colorB[i] = new JButton(" ");
      colorB[i].setBackground(color);
      colorB[i].setActionCommand("color_" + i);
      colorB[i].addActionListener(this);
      panel.add(colorB[i]);
      
      sizeCoB[i] = new JComboBox(size);
      sizeCoB[i].setSelectedItem(default_size);
      sizeCoB[i].setEditable(true);
      panel.add(sizeCoB[i]);
      
      button = new JButton("Update");
      button.setActionCommand("update_" + i);
      button.addActionListener(this);
      panel.add(button);
      
      mainPanel.add(panel);
    }
    
    // add the panel that allows updating the colors for all 
    panel = new JPanel();
    //panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));
    panel.setLayout(new FlowLayout(FlowLayout.LEFT, 2,2));
     
    colorCB = new JCheckBox("Colors");
    colorCB.setSelected(true);
    panel.add(colorCB);
    
    sizeCB = new JCheckBox("Lines");
    sizeCB.setSelected(true);
    panel.add(sizeCB);
    
    panel.add(Box.createRigidArea(new Dimension(30,0)));
    
    allColorB = new JButton(" ");
    allColorB.setBackground(Color.black);
    allColorB.setActionCommand("color_all");
    allColorB.addActionListener(this);
    panel.add(allColorB);
    
    allSizeCoB = new JComboBox(size);
    allSizeCoB.setSelectedItem(default_size);
    allSizeCoB.setEditable(true);
    panel.add(allSizeCoB);
    
    button = new JButton("Update");
    button.setActionCommand("update_all");
    button.addActionListener(this);
    panel.add(button);
    
    mainPanel.add(panel);
    
    // add the main panel to the scroll pane
    JScrollPane scrollPane = new JScrollPane(mainPanel);
    //scrollPane.setPreferredSize(new Dimension(300, 200));
		add(scrollPane, "Center");
    
    // add the button panel
    JPanel buttonPanel = new JPanel();
    buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.X_AXIS));
    Border border = BorderFactory.createRaisedBevelBorder();
    buttonPanel.setBorder(border);
    
    chCB = new JCheckBox("Crosshair");
    chCB.setSelected(plotDialog.crosshair);
    chCB.setActionCommand("crosshair");
		chCB.addActionListener(this);
    buttonPanel.add(chCB);
    
    grCB = new JCheckBox("Grid");
    grCB.setSelected(true);
    grCB.setActionCommand("grid");
		grCB.addActionListener(this);
    buttonPanel.add(grCB);
    
    lgCB = new JCheckBox("Legend");
    lgCB.setSelected(true);
    lgCB.setActionCommand("legend");
		lgCB.addActionListener(this);
    buttonPanel.add(lgCB);
    
    buttonPanel.add(Box.createHorizontalGlue());
    
    button = new JButton("Close");
    button.setActionCommand("close");
		button.addActionListener(this);
    buttonPanel.add(button);
    
    getContentPane().add(buttonPanel, "South");
  }
  
  // Method to handel action events
  public void actionPerformed(ActionEvent ae) {
		String cmd = ae.getActionCommand();
		
		if(cmd.equals("close")) {
			setVisible(false);
		}
    else if(cmd.equals("color_all")) {
			updateAllColor();
		}
    else if(cmd.indexOf("color") != -1) {
      updateColor(cmd);
    }
    else if(cmd.equals("update_all")) {
      updateAllPlot();
    }
    else if(cmd.indexOf("update") != -1) {
      updatePlot(cmd);
    }
    else if(cmd.equals("crosshair")) {
      updateCrosshair();
    }
    else if(cmd.equals("grid")) {
      updateGrid();
    }
    else if(cmd.equals("legend")) {
      updateLegend();
    }
    else {
      System.err.println("Action Command not handeled in class PlotEditorDialog ...");
      System.err.println(cmd);
    }
	}
  
  // Method to update the color
  private void updateColor(String cmd) {
    int index = getSeriesIndex(cmd);
    Color newColor = JColorChooser.showDialog(
                     this,"Choose Line Color", colorB[index].getBackground());
    
    if (newColor != null) {
      colorB[index].setBackground(newColor);
    }
  }
  
  // Method to update the color of all lines
  private void updateAllColor() {
    Color newColor = JColorChooser.showDialog(
    this,"Choose Line Color", allColorB.getBackground());
    
    if (newColor != null) {
      allColorB.setBackground(newColor);
    }
  }
  
  // Method to update a plot
  private void updatePlot(String cmd) {
    int index = getSeriesIndex(cmd);
    updatePlot(index);
  }
  
   // Method to update all plots with color and/or lines
  private void updateAllPlot() {
    Color color = allColorB.getBackground();
    BasicStroke stroke = null;
    
    try {
      String s = (String)allSizeCoB.getSelectedItem();
      float size = Float.parseFloat(s);
      stroke = new BasicStroke(size);
    }
    catch(NumberFormatException nfe) { }
    
    for(int i = 0; i < count; i++) {
      boolean visible = visCB[i].isSelected();
      renderer.setSeriesVisible(i, new Boolean(visible));
      
      // update the name
      XYSeries series = dataset.getSeries(i);
      series.setKey(keyTF[i].getText());
      
      // update the line color
      if(colorCB.isSelected()) {
        renderer.setSeriesPaint(i, color);
      }
      
      // update the line size
       if(sizeCB.isSelected()) {
         renderer.setSeriesStroke(i, stroke);
       }
    }
  }
  
  // Method to update a particular series
  private void updatePlot(int index) {
    // update visibility
    boolean visible = visCB[index].isSelected();
    renderer.setSeriesVisible(index, new Boolean(visible));
    
    // update the name
    XYSeries series = dataset.getSeries(index);
    series.setKey(keyTF[index].getText());
    
    // update the line color
    Color color = colorB[index].getBackground();
    renderer.setSeriesPaint(index, color);
    
    // update the line size
    try {
      String s = (String)sizeCoB[index].getSelectedItem();
      float size = Float.parseFloat(s);
      BasicStroke stroke = new BasicStroke(size);
      renderer.setSeriesStroke(index, stroke);
    }
    catch(NumberFormatException nfe) { }
  }
  
  // Method to set the crosshair visible or not
  private void updateCrosshair() {
    boolean crosshair = chCB.isSelected();
    plot.setDomainCrosshairVisible(crosshair);
    plot.setRangeCrosshairVisible(crosshair);
  }
  
  // Method to set the item labels visible or not
  private void updateGrid() {
    boolean grid = grCB.isSelected();
    plot.setDomainGridlinesVisible(grid);
    plot.setRangeGridlinesVisible(grid);
  }
  
  // Method to remove the legend
  private void updateLegend() {
    boolean show = lgCB.isSelected();
    if(!show) {
      chart.removeLegend();
    }
    else {
      chart.addLegend(legend);
    }
  }
  
  //Method to return the series index
  private int getSeriesIndex(String cmd) {
    int index = 0;
    try {
      String[] sa = cmd.split("_");
      index = Integer.parseInt(sa[1]);
    }
    catch(NumberFormatException nfe) {}
    
    return index;
  }
} //--end class PlotEditor Dialog
