updates for 0.9.3
[debian/openrocket] / src / net / sf / openrocket / gui / plot / PlotDialog.java
1 package net.sf.openrocket.gui.plot;
2
3 import java.awt.Color;
4 import java.awt.Window;
5 import java.awt.event.ActionEvent;
6 import java.awt.event.ActionListener;
7 import java.util.List;
8
9 import javax.swing.BorderFactory;
10 import javax.swing.JButton;
11 import javax.swing.JDialog;
12 import javax.swing.JPanel;
13
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;
20
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;
32
33 public class PlotDialog extends JDialog {
34         
35         private PlotDialog(Window parent, Simulation simulation, PlotConfiguration config) {
36                 super(parent, "Flight data plot");
37                 this.setModalityType(ModalityType.DOCUMENT_MODAL);
38                 
39                 
40                 // Fill the auto-selections
41                 FlightDataBranch branch = simulation.getSimulatedData().getBranch(0);
42                 PlotConfiguration filled = config.fillAutoAxes(branch);
43                 List<Axis> axes = filled.getAllAxes();
44
45
46                 // Create the data series for both axes
47                 XYSeriesCollection[] data = new XYSeriesCollection[2];
48                 data[0] = new XYSeriesCollection();
49                 data[1] = new XYSeriesCollection();
50                 
51                 
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.");
57                 }
58                 List<Double> x = branch.get(domainType);
59                 
60                 
61                 // Get plot length (ignore trailing NaN's)
62                 int typeCount = filled.getTypeCount();
63                 int dataLength = 0;
64                 for (int i=0; i<typeCount; i++) {
65                         FlightDataBranch.Type type = filled.getType(i);
66                         List<Double> y = branch.get(type);
67                         
68                         for (int j = dataLength; j < y.size(); j++) {
69                                 if (!Double.isNaN(y.get(j)) && !Double.isInfinite(y.get(j)))
70                                         dataLength = j;
71                         }
72                 }
73                 dataLength = Math.min(dataLength, x.size());
74                 
75                 
76                 // Create the XYSeries objects from the flight data and store into the collections
77                 String[] axisLabel = new String[2];
78                 for (int i = 0; i < typeCount; i++) {
79                         // Get info
80                         FlightDataBranch.Type type = filled.getType(i);
81                         Unit unit = filled.getUnit(i);
82                         int axis = filled.getAxis(i);
83                         String name = getLabel(type, unit);
84                         
85                         // Store data in provided units
86                         List<Double> y = branch.get(type);
87                         XYSeries series = new XYSeries(name, false, true);
88                         for (int j=0; j < dataLength; j++) {
89                                 series.add(domainUnit.toUnit(x.get(j)), unit.toUnit(y.get(j)));
90                         }
91                         data[axis].addSeries(series);
92
93                         // Update axis label
94                         if (axisLabel[axis] == null)
95                                 axisLabel[axis] = type.getName();
96                         else
97                                 axisLabel[axis] += "; " + type.getName();
98                 }
99                 
100                 
101                 // Create the chart using the factory to get all default settings
102         JFreeChart chart = ChartFactory.createXYLineChart(
103             "Simulated flight",
104             null, 
105             null, 
106             null,
107             PlotOrientation.VERTICAL,
108             true,
109             true,
110             false
111         );
112                 
113         chart.addSubtitle(new TextTitle(config.getName()));
114         
115                 // Add the data and formatting to the plot
116                 XYPlot plot = chart.getXYPlot();
117                 int axisno = 0;
118                 for (int i=0; i<2; i++) {
119                         // Check whether axis has any data
120                         if (data[i].getSeriesCount() > 0) {
121                                 // Create and set axis
122                                 double min = axes.get(i).getMinValue();
123                                 double max = axes.get(i).getMaxValue();
124                                 NumberAxis axis = new PresetNumberAxis(min, max);
125                                 axis.setLabel(axisLabel[i]);
126 //                              axis.setRange(axes.get(i).getMinValue(), axes.get(i).getMaxValue());
127                                 plot.setRangeAxis(axisno, axis);
128                                 
129                                 // Add data and map to the axis
130                                 plot.setDataset(axisno, data[i]);
131                                 plot.setRenderer(axisno, new StandardXYItemRenderer());
132                                 plot.mapDatasetToRangeAxis(axisno, axisno);
133                                 axisno++;
134                         }
135                 }
136                 
137                 plot.getDomainAxis().setLabel(getLabel(domainType,domainUnit));
138                 plot.addDomainMarker(new ValueMarker(0));
139                 plot.addRangeMarker(new ValueMarker(0));
140                 
141                 
142                 // Create the dialog
143                 
144                 JPanel panel = new JPanel(new MigLayout("fill"));
145                 this.add(panel);
146                 
147                 ChartPanel chartPanel = new ChartPanel(chart,
148                                 false, // properties
149                                 true,  // save
150                                 false, // print
151                                 true,  // zoom
152                                 true); // tooltips
153                 chartPanel.setMouseWheelEnabled(true);
154                 chartPanel.setEnforceFileExtensions(true);
155                 chartPanel.setInitialDelay(500);
156                 
157                 chartPanel.setBorder(BorderFactory.createLineBorder(Color.GRAY, 1));
158                 
159                 panel.add(chartPanel, "grow, wrap 20lp");
160
161                 JButton button = new JButton("Close");
162                 button.addActionListener(new ActionListener() {
163                         @Override
164                         public void actionPerformed(ActionEvent e) {
165                                 PlotDialog.this.dispose();
166                         }
167                 });
168                 panel.add(button, "right");
169
170                 this.setLocationByPlatform(true);
171                 this.pack();
172                 GUIUtil.installEscapeCloseOperation(this);
173                 GUIUtil.setDefaultButton(button);
174         }
175         
176         
177         private String getLabel(FlightDataBranch.Type type, Unit unit) {
178                 String name = type.getName();
179                 if (unit != null  &&  !UnitGroup.UNITS_NONE.contains(unit)  &&
180                                 !UnitGroup.UNITS_COEFFICIENT.contains(unit) && unit.getUnit().length() > 0)
181                         name += " ("+unit.getUnit() + ")";
182                 return name;
183         }
184         
185
186         
187         private class PresetNumberAxis extends NumberAxis {
188                 private final double min;
189                 private final double max;
190                 
191                 public PresetNumberAxis(double min, double max) {
192                         this.min = min;
193                         this.max = max;
194                         autoAdjustRange();
195                 }
196                 
197                 @Override
198                 protected void autoAdjustRange() {
199                         this.setRange(min, max);
200                 }
201         }
202         
203         
204         /**
205          * Static method that shows a plot with the specified parameters.
206          * 
207          * @param parent                the parent window, which will be blocked.
208          * @param simulation    the simulation to plot.
209          * @param config                the configuration of the plot.
210          */
211         public static void showPlot(Window parent, Simulation simulation, PlotConfiguration config) {
212                 new PlotDialog(parent, simulation, config).setVisible(true);
213         }
214         
215 }