Initial commit
[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                 // 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++) {
65                         // Get info
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);
70                         
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)));
76                         }
77                         data[axis].addSeries(series);
78
79                         // Update axis label
80                         if (axisLabel[axis] == null)
81                                 axisLabel[axis] = type.getName();
82                         else
83                                 axisLabel[axis] += "; " + type.getName();
84                 }
85                 
86                 
87                 // Create the chart using the factory to get all default settings
88         JFreeChart chart = ChartFactory.createXYLineChart(
89             "Simulated flight",
90             null, 
91             null, 
92             null,
93             PlotOrientation.VERTICAL,
94             true,
95             true,
96             false
97         );
98                 
99         chart.addSubtitle(new TextTitle(config.getName()));
100         
101                 // Add the data and formatting to the plot
102                 XYPlot plot = chart.getXYPlot();
103                 int axisno = 0;
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);
114                                 
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);
119                                 axisno++;
120                         }
121                 }
122                 
123                 plot.getDomainAxis().setLabel(getLabel(domainType,domainUnit));
124                 plot.addDomainMarker(new ValueMarker(0));
125                 plot.addRangeMarker(new ValueMarker(0));
126                 
127                 
128                 // Create the dialog
129                 
130                 JPanel panel = new JPanel(new MigLayout("fill"));
131                 this.add(panel);
132                 
133                 ChartPanel chartPanel = new ChartPanel(chart,
134                                 false, // properties
135                                 true,  // save
136                                 false, // print
137                                 true,  // zoom
138                                 true); // tooltips
139                 chartPanel.setMouseWheelEnabled(true);
140                 chartPanel.setEnforceFileExtensions(true);
141                 chartPanel.setInitialDelay(500);
142                 
143                 chartPanel.setBorder(BorderFactory.createLineBorder(Color.GRAY, 1));
144                 
145                 panel.add(chartPanel, "grow, wrap 20lp");
146
147                 JButton button = new JButton("Close");
148                 button.addActionListener(new ActionListener() {
149                         @Override
150                         public void actionPerformed(ActionEvent e) {
151                                 PlotDialog.this.dispose();
152                         }
153                 });
154                 panel.add(button, "right");
155
156                 this.setLocationByPlatform(true);
157                 this.pack();
158                 GUIUtil.installEscapeCloseOperation(this);
159                 GUIUtil.setDefaultButton(button);
160         }
161         
162         
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() + ")";
168                 return name;
169         }
170         
171
172         
173         private class PresetNumberAxis extends NumberAxis {
174                 private final double min;
175                 private final double max;
176                 
177                 public PresetNumberAxis(double min, double max) {
178                         this.min = min;
179                         this.max = max;
180                         autoAdjustRange();
181                 }
182                 
183                 @Override
184                 protected void autoAdjustRange() {
185                         this.setRange(min, max);
186                 }
187         }
188         
189         
190         /**
191          * Static method that shows a plot with the specified parameters.
192          * 
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.
196          */
197         public static void showPlot(Window parent, Simulation simulation, PlotConfiguration config) {
198                 new PlotDialog(parent, simulation, config).setVisible(true);
199         }
200         
201 }