1 package net.sf.openrocket.gui.plot;
4 import java.awt.Window;
5 import java.awt.event.ActionEvent;
6 import java.awt.event.ActionListener;
9 import javax.swing.BorderFactory;
10 import javax.swing.JButton;
11 import javax.swing.JDialog;
12 import javax.swing.JPanel;
14 import net.miginfocom.swing.MigLayout;
15 import net.sf.openrocket.document.Simulation;
16 import net.sf.openrocket.simulation.FlightDataBranch;
17 import net.sf.openrocket.unit.Unit;
18 import net.sf.openrocket.unit.UnitGroup;
19 import net.sf.openrocket.util.GUIUtil;
21 import org.jfree.chart.ChartFactory;
22 import org.jfree.chart.ChartPanel;
23 import org.jfree.chart.JFreeChart;
24 import org.jfree.chart.axis.NumberAxis;
25 import org.jfree.chart.plot.PlotOrientation;
26 import org.jfree.chart.plot.ValueMarker;
27 import org.jfree.chart.plot.XYPlot;
28 import org.jfree.chart.renderer.xy.StandardXYItemRenderer;
29 import org.jfree.chart.title.TextTitle;
30 import org.jfree.data.xy.XYSeries;
31 import org.jfree.data.xy.XYSeriesCollection;
33 public class PlotDialog extends JDialog {
35 private PlotDialog(Window parent, Simulation simulation, PlotConfiguration config) {
36 super(parent, "Flight data plot");
37 this.setModalityType(ModalityType.DOCUMENT_MODAL);
40 // Fill the auto-selections
41 FlightDataBranch branch = simulation.getSimulatedData().getBranch(0);
42 PlotConfiguration filled = config.fillAutoAxes(branch);
43 List<Axis> axes = filled.getAllAxes();
46 // Create the data series for both axes
47 XYSeriesCollection[] data = new XYSeriesCollection[2];
48 data[0] = new XYSeriesCollection();
49 data[1] = new XYSeriesCollection();
52 // Get the domain axis type
53 final FlightDataBranch.Type domainType = filled.getDomainAxisType();
54 final Unit domainUnit = filled.getDomainAxisUnit();
55 if (domainType == null) {
56 throw new IllegalArgumentException("Domain axis type not specified.");
58 List<Double> x = branch.get(domainType);
61 // Create the XYSeries objects from the flight data and store into the collections
62 int length = filled.getTypeCount();
63 String[] axisLabel = new String[2];
64 for (int i = 0; i < length; i++) {
66 FlightDataBranch.Type type = filled.getType(i);
67 Unit unit = filled.getUnit(i);
68 int axis = filled.getAxis(i);
69 String name = getLabel(type, unit);
71 // Store data in provided units
72 List<Double> y = branch.get(type);
73 XYSeries series = new XYSeries(name, false, true);
74 for (int j=0; j<x.size(); j++) {
75 series.add(domainUnit.toUnit(x.get(j)), unit.toUnit(y.get(j)));
77 data[axis].addSeries(series);
80 if (axisLabel[axis] == null)
81 axisLabel[axis] = type.getName();
83 axisLabel[axis] += "; " + type.getName();
87 // Create the chart using the factory to get all default settings
88 JFreeChart chart = ChartFactory.createXYLineChart(
93 PlotOrientation.VERTICAL,
99 chart.addSubtitle(new TextTitle(config.getName()));
101 // Add the data and formatting to the plot
102 XYPlot plot = chart.getXYPlot();
104 for (int i=0; i<2; i++) {
105 // Check whether axis has any data
106 if (data[i].getSeriesCount() > 0) {
107 // Create and set axis
108 double min = axes.get(i).getMinValue();
109 double max = axes.get(i).getMaxValue();
110 NumberAxis axis = new PresetNumberAxis(min, max);
111 axis.setLabel(axisLabel[i]);
112 // axis.setRange(axes.get(i).getMinValue(), axes.get(i).getMaxValue());
113 plot.setRangeAxis(axisno, axis);
115 // Add data and map to the axis
116 plot.setDataset(axisno, data[i]);
117 plot.setRenderer(axisno, new StandardXYItemRenderer());
118 plot.mapDatasetToRangeAxis(axisno, axisno);
123 plot.getDomainAxis().setLabel(getLabel(domainType,domainUnit));
124 plot.addDomainMarker(new ValueMarker(0));
125 plot.addRangeMarker(new ValueMarker(0));
130 JPanel panel = new JPanel(new MigLayout("fill"));
133 ChartPanel chartPanel = new ChartPanel(chart,
139 chartPanel.setMouseWheelEnabled(true);
140 chartPanel.setEnforceFileExtensions(true);
141 chartPanel.setInitialDelay(500);
143 chartPanel.setBorder(BorderFactory.createLineBorder(Color.GRAY, 1));
145 panel.add(chartPanel, "grow, wrap 20lp");
147 JButton button = new JButton("Close");
148 button.addActionListener(new ActionListener() {
150 public void actionPerformed(ActionEvent e) {
151 PlotDialog.this.dispose();
154 panel.add(button, "right");
156 this.setLocationByPlatform(true);
158 GUIUtil.installEscapeCloseOperation(this);
159 GUIUtil.setDefaultButton(button);
163 private String getLabel(FlightDataBranch.Type type, Unit unit) {
164 String name = type.getName();
165 if (unit != null && !UnitGroup.UNITS_NONE.contains(unit) &&
166 !UnitGroup.UNITS_COEFFICIENT.contains(unit) && unit.getUnit().length() > 0)
167 name += " ("+unit.getUnit() + ")";
173 private class PresetNumberAxis extends NumberAxis {
174 private final double min;
175 private final double max;
177 public PresetNumberAxis(double min, double max) {
184 protected void autoAdjustRange() {
185 this.setRange(min, max);
191 * Static method that shows a plot with the specified parameters.
193 * @param parent the parent window, which will be blocked.
194 * @param simulation the simulation to plot.
195 * @param config the configuration of the plot.
197 public static void showPlot(Window parent, Simulation simulation, PlotConfiguration config) {
198 new PlotDialog(parent, simulation, config).setVisible(true);