/* ========================
* JSynoptic : a free Synoptic editor
* ========================
*
* Project Info: http://jsynoptic.sourceforge.net/index.html
*
* This program is free software; you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Foundation;
* either version 2.1 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* (C) Copyright 2001-2003, by :
* Corporate:
* Astrium SAS
* EADS CRC
* Individual:
* Nicolas Brodu
*
* $Id: StandardPlotShape.java,v 1.20 2008/09/29 10:27:46 ogor Exp $
*
* Changes
* -------
* 25-Sep-2003 : Initial public release (NB);
*
*/
package jsynoptic.plugins.jfreechart;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.geom.Rectangle2D;
import java.util.ResourceBundle;
import java.util.Vector;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import javax.swing.JTextField;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;
import javax.swing.undo.CompoundEdit;
import jsynoptic.base.ContextualActionProvider;
import jsynoptic.ui.JSynoptic;
import jsynoptic.ui.LongAction;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.plot.PlotRenderingInfo;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.ui.ChartPropertyEditPanel;
import simtools.data.DataInfo;
import simtools.data.DataSource;
import simtools.data.DataSourceCollection;
import simtools.shapes.AbstractShape;
import simtools.shapes.AxisLabelFormatter;
import simtools.ui.ActionCheckBox;
import simtools.ui.ColorMapper;
import simtools.ui.DynamicColorChooser;
import simtools.ui.NumberField;
import simtools.ui.ResourceFinder;
/**
* @author nbrodu
*
* To change the template for this generated type comment go to
* Window - Preferences - Java - Code Generation - Code and Comments
*/
public class StandardPlotShape extends ChartShape implements ContextualActionProvider {
static final long serialVersionUID = 4663313906061456914L;
public static ResourceBundle resources = ResourceFinder.get(StandardPlotShape.class);
public StandardPlotShape(JFreeChart chart) {
this(chart,0,0,400,300);
}
public StandardPlotShape(JFreeChart chart, int ox, int oy, int width, int height) {
super(chart, ox, oy, width, height);
XYPlot plot = chart.getXYPlot();
NumberAxis axis = new NumberAxis();
//CyclicNumberAxis axis = new CyclicNumberAxis(0, 100);
plot.setDomainAxis(axis);
axis.setAutoRange(true);
//axis.setAutoRangeIncludesZero(false);
ValueAxis vaxis = plot.getRangeAxis();
axis.setAutoRange(true);
if (vaxis instanceof NumberAxis) {((NumberAxis)vaxis).setAutoRangeIncludesZero(false);}
plot.setRenderer(new JSynopticStandardXYItemRenderer());
//plot.setRenderer(new CyclicXYItemRenderer());
plot.setRangeCrosshairLockedOnData(false);
plot.setDomainCrosshairLockedOnData(false);
}
/* (non-Javadoc)
* @see jsynoptic.base.ContextualActionProvider#getActions(double, double, java.lang.Object, int)
*/
public String[] getActions(double x, double y, Object o, int context) {
if (context==MOUSE_OVER_CONTEXT) {
return new String[] {"mouseover"};
}
if (context==MOUSE_OUT_CONTEXT) {
return new String[] {"mouseout"};
}
if (context==MOUSE_PRESSED_CONTEXT) {
return null;
}
if (context==EDITOR_CONTEXT) {
}
Vector v = new Vector();
v.add(resources.getString("Properties..."));
XYPlot plot = (XYPlot)chart.getXYPlot();
SourceXYDataset dst = (SourceXYDataset)plot.getDataset();
SourceXYDataset dst2 = (SourceXYDataset)plot.getSecondaryDataset(0);
if (o instanceof DataSource) {
v.add(resources.getString("setX"));
if (dst.getSources().size() != 0) {
v.add(resources.getString("addY"));
v.add(resources.getString("setSecX"));
plot.getSecondaryDatasetCount();
if (dst2!=null && dst2.getSources().size() != 0)
v.add(resources.getString("addSecY"));
}
}
else if (o instanceof DataSourceCollection) {
v.add(resources.getString("setXY1Yn"));
if (dst.getSources().size() != 0) {
v.add(resources.getString("addY1Yn"));
v.add(resources.getString("setSecXY1Yn"));
plot.getSecondaryDatasetCount();
if (dst2!=null && dst2.getSources().size() != 0)
v.add(resources.getString("addSecY1Yn"));
}
}
//NB Alex : primary and secondary refer to datasets, not to axes
//Datasets are defined by X source linked to domain axis
// -> TO DO : allow to display the axis where we want ;)
// -> TO DO : allow to display two range axis based on the same domain data...
// ----------> the first solution seems to create a secondary data set with X primary source duplicated, without axis
// ----------> find a way to do it properly... or don't do it if it's not necessary.
// ----------> the second one is not to display an axis if the data source is already linked with one displayed...
// ----------> by this way the user has to select again his X source for the secondary dataset, but we don't create axis
// ----------> as it is already there... it might be better.
if (v.size()==0) {
JSynoptic.setStatus(resources.getString("noSource"));
}
// v.add(resources.getString("SetXUnits"));
return (String[])v.toArray(new String[v.size()]);
}
/* (non-Javadoc)
* @see jsynoptic.base.ContextualActionProvider#doAction(double, double, java.lang.Object, java.lang.String)
*/
public boolean doAction(double x, double y, Object o, String action, CompoundEdit undoableEdit) {
if (action.equals("mouseover")) {
if (chartRenderingInfo==null) return false;
XYPlot plot = (XYPlot)chart.getXYPlot();
PlotRenderingInfo info = chartRenderingInfo.getPlotInfo();
Rectangle2D dataArea = info.getDataArea();
if (dataArea.contains(x, y)) {
plot.setRangeCrosshairVisible(true);
plot.setDomainCrosshairVisible(true);
String msg = "";
// set the crosshair value for the horizontal axis...
ValueAxis da = plot.getDomainAxis();
if (da != null) {
double hvalue = da.translateJava2DToValue(x, info.getDataArea(),plot.getDomainAxisEdge());
plot.setDomainCrosshairValue(hvalue,false);
String label = da.getLabel();
if ((label!=null) && (!label.equals(""))) msg += label;
else msg+= resources.getString("X");
msg += "=" + AxisLabelFormatter.labelFormat(hvalue);
}
// set the crosshair value for the vertical axis...
ValueAxis ra = plot.getRangeAxis();
if (ra != null) {
double vvalue = ra.translateJava2DToValue(y, info.getDataArea(),plot.getRangeAxisEdge());
plot.setRangeCrosshairValue(vvalue,false);
if (!msg.equals("")) msg+=" ";
String label = ra.getLabel();
if ((label!=null) && (!label.equals(""))) msg += label;
else msg+= resources.getString("Y");
msg += "=" + AxisLabelFormatter.labelFormat(vvalue);
}
notifyChange(dataArea.getBounds());
if (!msg.equals("")) JSynoptic.setStatus(msg);
} else {
plot.setRangeCrosshairVisible(false);
plot.setDomainCrosshairVisible(false);
}
}
if (action.equals("mouseout")) {
XYPlot plot = (XYPlot)chart.getXYPlot();
plot.setRangeCrosshairVisible(false);
plot.setDomainCrosshairVisible(false);
JSynoptic.setStatus("");
}
if (action.equals(resources.getString("Properties..."))) {
new LongAction(LongAction.LONG_ACTION_SHAPE, null, this) {
protected void doAction() {
ChartPropertyEditPanel panel = new ChartPropertyEditPanel(chart);
JTabbedPane tab = findTab(panel);
PlotPanel plotPanel = null;
if (tab!=null) tab.add(plotPanel = new PlotPanel(),0);
int result = JOptionPane.showConfirmDialog(null, panel,
resources.getString("ChartProperties"), JOptionPane.OK_CANCEL_OPTION,
JOptionPane.PLAIN_MESSAGE);
if (result == JOptionPane.OK_OPTION) {
panel.updateChartProperties(chart);
if (plotPanel!=null) plotPanel.updateChartProperties();
}
notifyChange();
}
}.start();
return true;
}
//for DataSource Collection ----> dirty duplication...
if (action.equals(resources.getString("setXY1Yn"))) {
try {
XYPlot plot = chart.getXYPlot();
SourceXYDataset dst = (SourceXYDataset)plot.getDataset();
dst.setDataSourceCollection((DataSourceCollection)o);
chart.setTitle(dst.getName());
plot.getDomainAxis().setLabel(dst.getXLabel(0));
notifyChange();
} catch (ClassCastException cce) {
JSynoptic.setStatus(resources.getString("ErrorWhileSettingDataSourceCollection"));
}
}
if (action.equals(resources.getString("addY1Yn"))) {
try {
XYPlot plot = chart.getXYPlot();
SourceXYDataset dst = (SourceXYDataset)plot.getDataset();
dst.addDataSourceCollection((DataSourceCollection)o);
notifyChange();
} catch (ClassCastException cce) {
JSynoptic.setStatus(resources.getString("ErrorWhileSettingDataSourceCollection"));
}
}
if (action.equals(resources.getString("setSecXY1Yn"))) {
try {
XYPlot plot = chart.getXYPlot();
SourceXYDataset dst2 = (SourceXYDataset)plot.getSecondaryDataset(0);
//If not any previous Secondary Dataset was found
if (dst2==null) {
//we build a new one
dst2 = new SourceXYDataset();
//and link it
plot.setSecondaryDataset(0,dst2);
}
dst2.setDataSourceCollection((DataSourceCollection)o);
//If we got no secondary domain axis
if (plot.getSecondaryDomainAxis(0)==null) {
//we build a new one
NumberAxis axis = new NumberAxis();
axis.setAutoRange(true);
//and link it
plot.setSecondaryDomainAxis(0,axis);
}
//If we got no secondary range axis
if (plot.getSecondaryRangeAxis(0)==null) {
//We build a new one
NumberAxis axis = new NumberAxis();
axis.setAutoRange(true);
//and link it
plot.setSecondaryRangeAxis(0,axis);
}
//We reset the title
chart.setTitle(chart.getTitle().getText() + " and " + dst2.getName());
//We set Xlabel
plot.getSecondaryDomainAxis(0).setLabel(dst2.getXLabel(0));
//If necessary we set the renderer
if (plot.getSecondaryRenderer(0)==null) {
plot.setSecondaryRenderer(0,new JSynopticStandardXYItemRenderer(2));
}
//We map the secondary dataset to secondary domain axis
plot.mapSecondaryDatasetToDomainAxis(0,new Integer(0));
//We map the secondary dataset to secondary range axis
plot.mapSecondaryDatasetToRangeAxis(0,new Integer(0));
notifyChange();
} catch (ClassCastException cce) {
JSynoptic.setStatus(resources.getString("ErrorWhileSettingXDataSource"));
}
}
if (action.equals(resources.getString("addSecY1Yn"))) {
try {
XYPlot plot = chart.getXYPlot();
SourceXYDataset dst2 = (SourceXYDataset)plot.getSecondaryDataset(0);
dst2.addYSource((DataSource)o);
//If we got no secondary range axis
if (plot.getSecondaryRangeAxis(0)==null) {
//We build a new one
NumberAxis axis = new NumberAxis();
axis.setAutoRange(true);
//and link it
plot.setSecondaryRangeAxis(0,axis);
}
//We map the secondary dataset to secondary range axis
plot.mapSecondaryDatasetToRangeAxis(0,new Integer(0));
notifyChange();
} catch (ClassCastException cce) {
JSynoptic.setStatus(resources.getString("ErrorWhileAddingYDataSource"));
}
}
//for DataSource ----> dirty duplication...
if (action.equals(resources.getString("setX"))) {
try {
XYPlot plot = chart.getXYPlot();
SourceXYDataset dst = (SourceXYDataset)plot.getDataset();
dst.setXSource((DataSource)o);
plot.getDomainAxis().setLabel(dst.getXLabel(0));
notifyChange();
} catch (ClassCastException cce) {
JSynoptic.setStatus(resources.getString("ErrorWhileSettingXDataSource"));
}
}
if (action.equals(resources.getString("addY"))) {
try {
XYPlot plot = chart.getXYPlot();
SourceXYDataset dst = (SourceXYDataset)plot.getDataset();
dst.addYSource((DataSource)o);
notifyChange();
} catch (ClassCastException cce) {
JSynoptic.setStatus(resources.getString("ErrorWhileAddingYDataSource"));
}
}
if (action.equals(resources.getString("setSecX"))) {
try {
XYPlot plot = chart.getXYPlot();
SourceXYDataset dst2 = (SourceXYDataset)plot.getSecondaryDataset(0);
//If not any previous Secondary Dataset was found
if (dst2==null) {
//we build a new one
dst2 = new SourceXYDataset();
//and link it
plot.setSecondaryDataset(0,dst2);
}
dst2.setXSource((DataSource)o);
//If we got no axis
if (plot.getSecondaryDomainAxis(0)==null) {
//we build a new one
NumberAxis axis = new NumberAxis();
axis.setAutoRange(true);
//and link it
plot.setSecondaryDomainAxis(0,axis);
}
//We set the label
plot.getSecondaryDomainAxis(0).setLabel(dst2.getXLabel(0));
//If necessary we set the renderer
if (plot.getSecondaryRenderer(0)==null) {
plot.setSecondaryRenderer(0,new JSynopticStandardXYItemRenderer(2));
}
//We map the secondary dataset to secondary domain axis
plot.mapSecondaryDatasetToDomainAxis(0,new Integer(0));
notifyChange();
} catch (ClassCastException cce) {
JSynoptic.setStatus(resources.getString("ErrorWhileSettingXDataSource"));
}
}
if (action.equals(resources.getString("addSecY"))) {
try {
XYPlot plot = chart.getXYPlot();
SourceXYDataset dst2 = (SourceXYDataset)plot.getSecondaryDataset(0);
dst2.addYSource((DataSource)o);
//If we got no axis
if (plot.getSecondaryRangeAxis(0)==null) {
//We build a new one
NumberAxis axis = new NumberAxis();
axis.setAutoRange(true);
//and link it
plot.setSecondaryRangeAxis(0,axis);
}
//We map the secondary dataset to secondary range axis
plot.mapSecondaryDatasetToRangeAxis(0,new Integer(0));
notifyChange();
} catch (ClassCastException cce) {
JSynoptic.setStatus(resources.getString("ErrorWhileAddingYDataSource"));
}
}
return true;
}
/* (non-Javadoc)
* @see jsynoptic.base.ContextualActionProvider#canDoAction(double, double, java.lang.Object, java.lang.String, int)
*/
public boolean canDoAction(double x, double y, Object o, String action, int context) {
return true;
}
static protected class CbxEntry {
public int datasetIndex;
public String name;
public Color color;
public DataSource source;
public ColorMapper mapper;
public CbxEntry(int datasetIndex, String name, Color c, DataSource ds, ColorMapper cm) {
this.name = name;
this.datasetIndex=datasetIndex;
color = c;
source = ds;
mapper = cm;
}
public String toString() {
return name;
}
}
public class PlotPanel extends JPanel {
// primary X variables
ActionCheckBox pcbautox,pcbfixedautox;
NumberField pnffixedautox,ptfpxmin,ptfpxmax;
JLabel plpxmin, plpxmax;
// secondary X variables
ActionCheckBox scbautox,scbfixedautox;
NumberField snffixedautox,stfpxmin,stfpxmax;
JLabel slpxmin, slpxmax;
JTextField tfTitle;
Color noCurveColor;
// primary Y variables
ActionCheckBox pcbautoy,pcbfixedautoy;
NumberField pnffixedautoy,ptfpymin,ptfpymax;
JLabel plpymin, plpymax;
JComboBox pcbxcurves;
JButton pcurvecolor, pcurvedelete;
CbxEntry pactiveEntry;
JTextField pcbxeditortf;
boolean peditLocked;
// secondary Y variables
ActionCheckBox scbautoy,scbfixedautoy;
NumberField snffixedautoy,stfpymin,stfpymax;
JLabel slpymin, slpymax;
JComboBox scbxcurves;
JButton scurvecolor, scurvedelete;
CbxEntry sactiveEntry;
JTextField scbxeditortf;
boolean seditLocked;
public PlotPanel() {
// setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
setLayout(new BorderLayout());
JPanel panel;
Box section;
Box content = Box.createVerticalBox();
setName(resources.getString("PlotProperties"));
XYPlot plot = chart.getXYPlot();
// Create the title section
section=Box.createHorizontalBox();
section.add(new JLabel(resources.getString("PlotTitle:")));
section.add(tfTitle = new JTextField());
tfTitle.setText(chart.getTitle().getText());
content.add(section);
// X axis section
section = new Box(BoxLayout.Y_AXIS);
section.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(),resources.getString("XAxis")));
panel = new JPanel();
panel.setLayout(new FlowLayout(FlowLayout.LEFT));
panel.add(pcbautox = new ActionCheckBox(resources.getString("Auto-update"), plot.getDomainAxis().isAutoRange()) {
public void actionPerformed(ActionEvent e) {
pcbfixedautox.setEnabled(isSelected());
pcbfixedautox.apply();
plpxmin.setEnabled(!isSelected());
plpxmax.setEnabled(!isSelected());
ptfpxmin.setEnabled(!isSelected());
ptfpxmax.setEnabled(!isSelected());
}
});
double autorange = plot.getDomainAxis().getFixedAutoRange();
panel.add(pcbfixedautox = new ActionCheckBox(resources.getString("FixedRange"),autorange!=0) {
public void actionPerformed(ActionEvent e) {
pnffixedautox.setEnabled(isSelected() && isEnabled());
}
});
panel.add(pnffixedautox = new NumberField(autorange,10));
section.add(panel);
panel = new JPanel();
panel.setLayout(new FlowLayout(FlowLayout.LEFT));
panel.add(plpxmin = new JLabel(resources.getString("minLabel")));
panel.add(ptfpxmin = new NumberField(10));
ptfpxmin.setValue(plot.getDomainAxis().getLowerBound());
panel.add(plpxmax = new JLabel(resources.getString("maxLabel")));
panel.add(ptfpxmax = new NumberField(10));
ptfpxmax.setValue(plot.getDomainAxis().getUpperBound());
section.add(panel);
pcbautox.apply();
content.add(section);
// X secondary axis section
if (plot.getSecondaryDomainAxis(0) != null) {
section = new Box(BoxLayout.Y_AXIS);
section.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(),resources.getString("SecondaryXAxis")));
panel = new JPanel();
panel.setLayout(new FlowLayout(FlowLayout.LEFT));
panel.add(scbautox = new ActionCheckBox(resources.getString("Auto-update"), plot.getSecondaryDomainAxis(0).isAutoRange()) {
public void actionPerformed(ActionEvent e) {
scbfixedautox.setEnabled(isSelected());
scbfixedautox.apply();
slpxmin.setEnabled(!isSelected());
slpxmax.setEnabled(!isSelected());
stfpxmin.setEnabled(!isSelected());
stfpxmax.setEnabled(!isSelected());
}
});
autorange = plot.getSecondaryDomainAxis(0).getFixedAutoRange();
panel.add(scbfixedautox = new ActionCheckBox(resources.getString("FixedRange"),autorange!=0) {
public void actionPerformed(ActionEvent e) {
snffixedautox.setEnabled(isSelected() && isEnabled());
}
});
panel.add(snffixedautox = new NumberField(autorange,10));
section.add(panel);
panel = new JPanel();
panel.setLayout(new FlowLayout(FlowLayout.LEFT));
panel.add(slpxmin = new JLabel(resources.getString("minLabel")));
panel.add(stfpxmin = new NumberField(10));
stfpxmin.setValue(plot.getSecondaryDomainAxis(0).getLowerBound());
panel.add(slpxmax = new JLabel(resources.getString("maxLabel")));
panel.add(stfpxmax = new NumberField(10));
stfpxmax.setValue(plot.getSecondaryDomainAxis(0).getUpperBound());
section.add(panel);
scbautox.apply();
content.add(section);
}
// Now handle Y axis
section = new Box(BoxLayout.Y_AXIS);
section.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(),resources.getString("YAxis")));
panel = new JPanel();
panel.setLayout(new FlowLayout(FlowLayout.LEFT));
panel.add(pcbautoy = new ActionCheckBox(resources.getString("Auto-update"), plot.getRangeAxis().isAutoRange()) {
public void actionPerformed(ActionEvent e) {
pcbfixedautoy.setEnabled(isSelected());
pcbfixedautoy.apply();
plpymin.setEnabled(!isSelected());
plpymax.setEnabled(!isSelected());
ptfpymin.setEnabled(!isSelected());
ptfpymax.setEnabled(!isSelected());
}
});
autorange = plot.getRangeAxis().getFixedAutoRange();
panel.add(pcbfixedautoy = new ActionCheckBox(resources.getString("FixedRange"),autorange!=0) {
public void actionPerformed(ActionEvent e) {
pnffixedautoy.setEnabled(isSelected() && isEnabled());
}
});
panel.add(pnffixedautoy = new NumberField(autorange,8));
panel.add(plpymin = new JLabel(resources.getString("minLabel")));
panel.add(ptfpymin = new NumberField(8));
ptfpymin.setValue(plot.getRangeAxis().getLowerBound());
panel.add(plpymax = new JLabel(resources.getString("maxLabel")));
panel.add(ptfpymax = new NumberField(8));
ptfpymax.setValue(plot.getRangeAxis().getUpperBound());
section.add(panel);
pcbautoy.apply();
section.add(panel);
Box box = Box.createHorizontalBox();
box.add(new JLabel(resources.getString("Curves:")));
box.add(pcbxcurves = new JComboBox());
box.add(pcurvecolor = new JButton(" "));
box.add(pcurvedelete = new JButton(resources.getString("Delete")));
section.add(box);
content.add(section);
pcbxcurves.setEditable(true);
noCurveColor = pcurvecolor.getBackground();
pcurvecolor.setFocusPainted(false);
SourceXYDataset dst = (SourceXYDataset)plot.getDataset();
int n = dst.getSeriesCount();
JSynopticXYItemRenderer renderer = (JSynopticXYItemRenderer)plot.getRenderer();
for (int i=0; i<n; ++i) {
DataSource ds = renderer.getDataSource(i);
if (ds==null) {
ds = dst.getYSource(i); // take the datasource associated with this curve by default
DataSource linked = DataInfo.getLinkedSource(ds); // and follow link if necessary
if (linked!=null) ds = linked;
}
pcbxcurves.addItem(new CbxEntry(i,dst.getSeriesName(i),(Color)renderer.getSeriesPaint(i),ds,renderer.getColorMapper(i)));
}
pcbxeditortf = (JTextField)pcbxcurves.getEditor().getEditorComponent();
pupdateForEntry(pcbxcurves.getSelectedItem());
pcbxcurves.addPopupMenuListener(new PopupMenuListener() {
public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
peditLocked = true;
}
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
peditLocked = false;
}
public void popupMenuCanceled(PopupMenuEvent e) {
peditLocked = false;
}
});
pcbxcurves.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange()==ItemEvent.DESELECTED) pactiveEntry = null;
else pupdateForEntry(e.getItem());
}
});
pcbxeditortf.getDocument().addDocumentListener(new DocumentListener() {
public void insertUpdate(DocumentEvent e) {
updateName();
}
public void removeUpdate(DocumentEvent e) {
updateName();
}
public void changedUpdate(DocumentEvent e) {
updateName();
}
public void updateName() {
if ((peditLocked) || (pactiveEntry == null)) return;
pactiveEntry.name = pcbxeditortf.getText();
}
});
pcurvecolor.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (pactiveEntry==null) return;
DynamicColorChooser dialog = new DynamicColorChooser(
null, resources.getString("ChooseAColor"),null ,pactiveEntry.color,pactiveEntry.source,pactiveEntry.mapper);
dialog.pack();
dialog.setVisible(true);
if (dialog.isOk()){
pactiveEntry.color = dialog.getColor();
pactiveEntry.source = dialog.getSource();
pactiveEntry.mapper = dialog.getMapper();
pupdateForEntry(pactiveEntry);
}
}
});
pcurvedelete.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (pactiveEntry==null) return;
pcbxcurves.removeItem(pactiveEntry);
}
});
// Now handle Secondary Y axis
if (plot.getSecondaryRangeAxis(0) != null) {
section = new Box(BoxLayout.Y_AXIS);
section.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(),resources.getString("SecondaryYAxis")));
panel = new JPanel();
panel.setLayout(new FlowLayout(FlowLayout.LEFT));
panel.add(scbautoy = new ActionCheckBox(resources.getString("Auto-update"), plot.getSecondaryRangeAxis(0).isAutoRange()) {
public void actionPerformed(ActionEvent e) {
scbfixedautoy.setEnabled(isSelected());
scbfixedautoy.apply();
slpymin.setEnabled(!isSelected());
slpymax.setEnabled(!isSelected());
stfpymin.setEnabled(!isSelected());
stfpymax.setEnabled(!isSelected());
}
});
autorange = plot.getSecondaryRangeAxis(0).getFixedAutoRange();
panel.add(scbfixedautoy = new ActionCheckBox(resources.getString("FixedRange"),autorange!=0) {
public void actionPerformed(ActionEvent e) {
snffixedautoy.setEnabled(isSelected() && isEnabled());
}
});
panel.add(snffixedautoy = new NumberField(autorange,8));
panel.add(slpymin = new JLabel(resources.getString("minLabel")));
panel.add(stfpymin = new NumberField(8));
stfpymin.setValue(plot.getSecondaryRangeAxis(0).getLowerBound());
panel.add(slpymax = new JLabel(resources.getString("maxLabel")));
panel.add(stfpymax = new NumberField(8));
stfpymax.setValue(plot.getSecondaryRangeAxis(0).getUpperBound());
section.add(panel);
scbautoy.apply();
section.add(panel);
box = Box.createHorizontalBox();
box.add(new JLabel(resources.getString("Curves:")));
box.add(scbxcurves = new JComboBox());
box.add(scurvecolor = new JButton(" "));
box.add(scurvedelete = new JButton(resources.getString("Delete")));
section.add(box);
content.add(section);
scbxcurves.setEditable(true);
//noCurveColor = scurvecolor.getBackground();
scurvecolor.setFocusPainted(false);
dst = (SourceXYDataset)plot.getSecondaryDataset(0);
n = dst.getSeriesCount();
renderer = (JSynopticXYItemRenderer)plot.getSecondaryRenderer(0);
for (int i=0; i<n; ++i) {
DataSource ds = renderer.getDataSource(i);
if (ds==null) {
ds = dst.getYSource(i); // take the datasource associated with this curve by default
DataSource linked = DataInfo.getLinkedSource(ds); // and follow link if necessary
if (linked!=null) ds = linked;
}
scbxcurves.addItem(new CbxEntry(i,dst.getSeriesName(i),(Color)renderer.getSeriesPaint(i),ds,renderer.getColorMapper(i)));
}
scbxeditortf = (JTextField)scbxcurves.getEditor().getEditorComponent();
supdateForEntry(scbxcurves.getSelectedItem());
scbxcurves.addPopupMenuListener(new PopupMenuListener() {
public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
seditLocked = true;
}
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
seditLocked = false;
}
public void popupMenuCanceled(PopupMenuEvent e) {
seditLocked = false;
}
});
scbxcurves.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange()==ItemEvent.DESELECTED) sactiveEntry = null;
else supdateForEntry(e.getItem());
}
});
scbxeditortf.getDocument().addDocumentListener(new DocumentListener() {
public void insertUpdate(DocumentEvent e) {
updateName();
}
public void removeUpdate(DocumentEvent e) {
updateName();
}
public void changedUpdate(DocumentEvent e) {
updateName();
}
public void updateName() {
if ((seditLocked) || (sactiveEntry == null)) return;
sactiveEntry.name = scbxeditortf.getText();
}
});
scurvecolor.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (sactiveEntry==null) return;
DynamicColorChooser dialog = new DynamicColorChooser(
null, resources.getString("ChooseAColor"),null ,pactiveEntry.color,pactiveEntry.source,pactiveEntry.mapper);
dialog.pack();
dialog.setVisible(true);
if (dialog.isOk()){
pactiveEntry.color = dialog.getColor();
pactiveEntry.source = dialog.getSource();
pactiveEntry.mapper = dialog.getMapper();
pupdateForEntry(pactiveEntry);
}
}
});
scurvedelete.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (sactiveEntry==null) return;
scbxcurves.removeItem(sactiveEntry);
}
});
} // End secondary axis section
add(content, BorderLayout.NORTH);
}
protected void pupdateForEntry(Object o) {
if (o instanceof CbxEntry) pactiveEntry = (CbxEntry)o;
else pactiveEntry = null;
if (pactiveEntry == null) return;
pcurvecolor.setBackground(pactiveEntry.color);
}
protected void supdateForEntry(Object o) {
if (o instanceof CbxEntry) sactiveEntry = (CbxEntry)o;
else sactiveEntry = null;
if (sactiveEntry == null) return;
scurvecolor.setBackground(sactiveEntry.color);
}
protected void updateChartProperties() {
//Primary X update
ValueAxis xaxis = chart.getXYPlot().getDomainAxis();
xaxis.setAutoRange(pcbautox.isSelected());
if (pnffixedautox.isEnabled()) xaxis.setFixedAutoRange(pnffixedautox.getDoubleValue());
if (ptfpxmin.isEnabled() && ptfpxmax.isEnabled()) xaxis.setRange(ptfpxmin.getDoubleValue(), ptfpxmax.getDoubleValue());
//Secondary X update
ValueAxis sxaxis = chart.getXYPlot().getSecondaryDomainAxis(0);
if (sxaxis!=null) {
sxaxis.setAutoRange(scbautox.isSelected());
if (snffixedautox.isEnabled()) sxaxis.setFixedAutoRange(snffixedautox.getDoubleValue());
if (stfpxmin.isEnabled() && stfpxmax.isEnabled()) sxaxis.setRange(stfpxmin.getDoubleValue(), stfpxmax.getDoubleValue());
}
ValueAxis yaxis = chart.getXYPlot().getRangeAxis();
yaxis.setAutoRange(pcbautoy.isSelected());
if (pnffixedautoy.isEnabled()) yaxis.setFixedAutoRange(pnffixedautoy.getDoubleValue());
if (ptfpymin.isEnabled() && ptfpymax.isEnabled()) yaxis.setRange(ptfpymin.getDoubleValue(), ptfpymax.getDoubleValue());
chart.setTitle(tfTitle.getText());
XYPlot plot = chart.getXYPlot();
// Primary Y update
SourceXYDataset dst = (SourceXYDataset)plot.getDataset();
int n = dst.getSeriesCount();
// If some curves were deleted, remove them
if (n != pcbxcurves.getItemCount()) {
boolean[] toKeep = new boolean[n]; // boolean are initialized to false by JVM
for (int i=0; i<pcbxcurves.getItemCount(); ++i)
toKeep[((CbxEntry)pcbxcurves.getItemAt(i)).datasetIndex] = true;
JSynopticXYItemRenderer renderer = (JSynopticXYItemRenderer)plot.getRenderer();
// Now we can remove the deleted curves, and update the existing ones
// Start from the end, to remove the entries and keep the index OK
for (int i=n-1; i>=0; i--) {
if (!toKeep[i]) {
if (i>0) dst.removeXSource(i);
else dst.removeYSource(i);
renderer.removeColorMapper(i);
renderer.removeDataSource(i);
}
}
}
// Now we match the data set and the list
for (int i=0; i<pcbxcurves.getItemCount(); ++i) {
CbxEntry e = (CbxEntry)pcbxcurves.getItemAt(i);
dst.setName(i,e.name);
JSynopticXYItemRenderer renderer = (JSynopticXYItemRenderer)plot.getRenderer();
renderer.setSeriesPaint(i,e.color);
renderer.setDataSource(i, e.source);
renderer.setColorMapper(i, e.mapper);
}
// Secondary Y update
if (plot.getSecondaryRangeAxis(0) != null) {
ValueAxis syaxis = plot.getSecondaryRangeAxis(0);
if (syaxis!=null) {
syaxis.setAutoRange(scbautoy.isSelected());
if (snffixedautoy.isEnabled()) syaxis.setFixedAutoRange(snffixedautoy.getDoubleValue());
if (stfpymin.isEnabled() && stfpymax.isEnabled()) syaxis.setRange(stfpymin.getDoubleValue(), stfpymax.getDoubleValue());
}
dst = (SourceXYDataset)plot.getSecondaryDataset(0);
n = dst.getSeriesCount();
// If some curves were deleted, remove them
if (n != scbxcurves.getItemCount()) {
boolean[] toKeep = new boolean[n]; // boolean are initialized to false by JVM
for (int i=0; i<scbxcurves.getItemCount(); ++i)
toKeep[((CbxEntry)scbxcurves.getItemAt(i)).datasetIndex] = true;
JSynopticXYItemRenderer renderer = (JSynopticXYItemRenderer)plot.getSecondaryRenderer(0);
// Now we can remove the deleted curves, and update the existing ones
// Start from the end, to remove the entries and keep the index OK
for (int i=n-1; i>=0; i--) {
if (!toKeep[i]) {
if (i>0) dst.removeXSource(i);
else dst.removeYSource(i);
renderer.removeColorMapper(i);
renderer.removeDataSource(i);
}
}
}
// Now we match the data set and the list
for (int i=0; i<scbxcurves.getItemCount(); ++i) {
CbxEntry e = (CbxEntry)scbxcurves.getItemAt(i);
dst.setName(i,e.name);
JSynopticXYItemRenderer renderer = (JSynopticXYItemRenderer)plot.getSecondaryRenderer(0);
renderer.setSeriesPaint(i,e.color);
renderer.setDataSource(i, e.source);
renderer.setColorMapper(i, e.mapper);
}
}
}
}
/* (non-Javadoc)
* @see simtools.shapes.AbstractShape#cloneShape()
*/
protected AbstractShape cloneShape() {
ChartShape cs = (ChartShape)super.cloneShape();
SourceXYDataset dst = (SourceXYDataset)chart.getXYPlot().getDataset();
cs.chart.getXYPlot().setDataset(dst.cloneSet());
cs.chart.getXYPlot().setRenderer(((JSynopticXYItemRenderer)chart.getXYPlot().getRenderer()).cloneRenderer());
JSynopticXYItemRenderer secrenderer = (JSynopticXYItemRenderer)chart.getXYPlot().getSecondaryRenderer(0);
if (secrenderer!=null) cs.chart.getXYPlot().setSecondaryRenderer(0,secrenderer.cloneRenderer());
return cs;
}
}