1 package net.sf.openrocket.gui.plot;
3 import java.awt.event.ActionEvent;
4 import java.awt.event.ActionListener;
5 import java.awt.event.ItemEvent;
6 import java.awt.event.ItemListener;
7 import java.util.Arrays;
9 import javax.swing.JButton;
10 import javax.swing.JComboBox;
11 import javax.swing.JLabel;
12 import javax.swing.JOptionPane;
13 import javax.swing.JPanel;
14 import javax.swing.JScrollPane;
15 import javax.swing.SwingUtilities;
17 import net.miginfocom.swing.MigLayout;
18 import net.sf.openrocket.document.Simulation;
19 import net.sf.openrocket.gui.ResizeLabel;
20 import net.sf.openrocket.gui.UnitSelector;
21 import net.sf.openrocket.simulation.FlightDataBranch;
22 import net.sf.openrocket.simulation.FlightDataBranch.Type;
23 import net.sf.openrocket.unit.Unit;
25 public class PlotPanel extends JPanel {
27 // TODO: LOW: Should these be somewhere else?
28 public static final int AUTO = -1;
29 public static final int LEFT = 0;
30 public static final int RIGHT = 1;
32 public static final String AUTO_NAME = "Auto";
33 public static final String LEFT_NAME = "Left";
34 public static final String RIGHT_NAME = "Right";
36 private static final String CUSTOM = "Custom";
38 /** The "Custom" configuration - not to be used for anything other than the title. */
39 private static final PlotConfiguration CUSTOM_CONFIGURATION;
41 CUSTOM_CONFIGURATION = new PlotConfiguration(CUSTOM);
44 /** The array of presets for the combo box. */
45 private static final PlotConfiguration[] PRESET_ARRAY;
47 PRESET_ARRAY = Arrays.copyOf(PlotConfiguration.DEFAULT_CONFIGURATIONS,
48 PlotConfiguration.DEFAULT_CONFIGURATIONS.length + 1);
49 PRESET_ARRAY[PRESET_ARRAY.length-1] = CUSTOM_CONFIGURATION;
54 /** The current default configuration, set each time a plot is made. */
55 private static PlotConfiguration defaultConfiguration =
56 PlotConfiguration.DEFAULT_CONFIGURATIONS[0].resetUnits();
59 private final Simulation simulation;
60 private final FlightDataBranch.Type[] types;
61 private PlotConfiguration configuration;
64 private JComboBox configurationSelector;
66 private JComboBox domainTypeSelector;
67 private UnitSelector domainUnitSelector;
69 private JPanel typeSelectorPanel;
72 private int modifying = 0;
75 public PlotPanel(final Simulation simulation) {
76 super(new MigLayout("fill"));
78 this.simulation = simulation;
79 if (simulation.getSimulatedData() == null ||
80 simulation.getSimulatedData().getBranchCount()==0) {
81 throw new IllegalArgumentException("Simulation contains no data.");
83 FlightDataBranch branch = simulation.getSimulatedData().getBranch(0);
84 types = branch.getTypes();
86 // TODO: LOW: Revert to custom if data type is not available.
87 configuration = defaultConfiguration.clone();
92 // Setup the combo box
93 configurationSelector = new JComboBox(PRESET_ARRAY);
94 for (PlotConfiguration config: PRESET_ARRAY) {
95 if (config.getName().equals(configuration.getName())) {
96 configurationSelector.setSelectedItem(config);
99 configurationSelector.addItemListener(new ItemListener() {
101 public void itemStateChanged(ItemEvent e) {
104 PlotConfiguration conf = (PlotConfiguration)configurationSelector.getSelectedItem();
105 if (conf == CUSTOM_CONFIGURATION)
108 configuration = conf.clone().resetUnits();
113 this.add(new JLabel("Preset plot configurations: "), "spanx, split");
114 this.add(configurationSelector,"growx, wrap 30lp");
118 this.add(new JLabel("X axis type:"), "spanx, split");
119 domainTypeSelector = new JComboBox(types);
120 domainTypeSelector.setSelectedItem(configuration.getDomainAxisType());
121 domainTypeSelector.addItemListener(new ItemListener() {
123 public void itemStateChanged(ItemEvent e) {
126 FlightDataBranch.Type type = (Type) domainTypeSelector.getSelectedItem();
127 configuration.setDomainAxisType(type);
128 domainUnitSelector.setUnitGroup(type.getUnitGroup());
129 domainUnitSelector.setSelectedUnit(configuration.getDomainAxisUnit());
133 this.add(domainTypeSelector, "gapright para");
136 this.add(new JLabel("Unit:"));
137 domainUnitSelector = new UnitSelector(configuration.getDomainAxisType().getUnitGroup());
138 domainUnitSelector.setSelectedUnit(configuration.getDomainAxisUnit());
139 domainUnitSelector.addItemListener(new ItemListener() {
141 public void itemStateChanged(ItemEvent e) {
144 configuration.setDomainAxisUnit(domainUnitSelector.getSelectedUnit());
147 this.add(domainUnitSelector, "width 40lp, gapright para");
150 ResizeLabel desc = new ResizeLabel("<html><p>The data will be plotted in time order " +
151 "even if the X axis type is not time.", -2);
152 this.add(desc, "width :0px:, growx, wrap para");
156 this.add(new JLabel("Y axis types:"), "spanx, wrap rel");
158 typeSelectorPanel = new JPanel(new MigLayout("gapy rel"));
159 JScrollPane scroll = new JScrollPane(typeSelectorPanel);
160 this.add(scroll, "spanx, height :0:, grow, wrap para");
163 JButton button = new JButton("New Y axis plot type");
164 button.addActionListener(new ActionListener() {
166 public void actionPerformed(ActionEvent e) {
167 if (configuration.getTypeCount() >= 15) {
168 JOptionPane.showMessageDialog(PlotPanel.this,
169 "A maximum of 15 plots is allowed.", "Cannot add plot",
170 JOptionPane.ERROR_MESSAGE);
174 // Select new type smartly
175 FlightDataBranch.Type type = null;
176 for (FlightDataBranch.Type t:
177 simulation.getSimulatedData().getBranch(0).getTypes()) {
179 boolean used = false;
180 if (configuration.getDomainAxisType().equals(t)) {
183 for (int i=0; i < configuration.getTypeCount(); i++) {
184 if (configuration.getType(i).equals(t)) {
197 type = simulation.getSimulatedData().getBranch(0).getTypes()[0];
201 configuration.addPlotDataType(type);
206 this.add(button, "spanx, split");
208 this.add(new JPanel(), "growx");
210 button = new JButton("Plot flight");
211 button.addActionListener(new ActionListener() {
213 public void actionPerformed(ActionEvent e) {
214 defaultConfiguration = configuration.clone();
215 PlotDialog.showPlot(SwingUtilities.getWindowAncestor(PlotPanel.this),
216 simulation, configuration);
219 this.add(button, "right");
226 private void setToCustom() {
227 configuration.setName(CUSTOM);
228 configurationSelector.setSelectedItem(CUSTOM_CONFIGURATION);
232 private void updatePlots() {
233 domainTypeSelector.setSelectedItem(configuration.getDomainAxisType());
234 domainUnitSelector.setUnitGroup(configuration.getDomainAxisType().getUnitGroup());
235 domainUnitSelector.setSelectedUnit(configuration.getDomainAxisUnit());
237 typeSelectorPanel.removeAll();
238 for (int i=0; i < configuration.getTypeCount(); i++) {
239 FlightDataBranch.Type type = configuration.getType(i);
240 Unit unit = configuration.getUnit(i);
241 int axis = configuration.getAxis(i);
243 typeSelectorPanel.add(new PlotTypeSelector(i, type, unit, axis), "wrap");
246 typeSelectorPanel.repaint();
253 * A JPanel which configures a single plot of a PlotConfiguration.
255 private class PlotTypeSelector extends JPanel {
256 private final String[] POSITIONS = { AUTO_NAME, LEFT_NAME, RIGHT_NAME };
258 private final int index;
259 private JComboBox typeSelector;
260 private UnitSelector unitSelector;
261 private JComboBox axisSelector;
264 public PlotTypeSelector(int index, FlightDataBranch.Type type) {
265 this (index, type, null, -1);
268 public PlotTypeSelector(int plotIndex, FlightDataBranch.Type type, Unit unit, int position) {
269 super(new MigLayout(""));
271 this.index = plotIndex;
273 typeSelector = new JComboBox(types);
274 typeSelector.setSelectedItem(type);
275 typeSelector.addItemListener(new ItemListener() {
277 public void itemStateChanged(ItemEvent e) {
280 FlightDataBranch.Type type = (Type) typeSelector.getSelectedItem();
281 configuration.setPlotDataType(index, type);
282 unitSelector.setUnitGroup(type.getUnitGroup());
283 unitSelector.setSelectedUnit(configuration.getUnit(index));
287 this.add(typeSelector, "gapright para");
289 this.add(new JLabel("Unit:"));
290 unitSelector = new UnitSelector(type.getUnitGroup());
292 unitSelector.setSelectedUnit(unit);
293 unitSelector.addItemListener(new ItemListener() {
295 public void itemStateChanged(ItemEvent e) {
298 Unit unit = (Unit) unitSelector.getSelectedUnit();
299 configuration.setPlotDataUnit(index, unit);
302 this.add(unitSelector, "width 40lp, gapright para");
304 this.add(new JLabel("Axis:"));
305 axisSelector = new JComboBox(POSITIONS);
306 if (position == LEFT)
307 axisSelector.setSelectedIndex(1);
308 else if (position == RIGHT)
309 axisSelector.setSelectedIndex(2);
311 axisSelector.setSelectedIndex(0);
312 axisSelector.addItemListener(new ItemListener() {
314 public void itemStateChanged(ItemEvent e) {
317 int axis = axisSelector.getSelectedIndex() - 1;
318 configuration.setPlotDataAxis(index, axis);
321 this.add(axisSelector, "gapright para");
324 JButton button = new JButton("Remove");
325 button.addActionListener(new ActionListener() {
327 public void actionPerformed(ActionEvent e) {
328 configuration.removePlotDataType(index);