1 package net.sf.openrocket.gui;
3 import java.awt.event.ActionEvent;
4 import java.awt.event.ActionListener;
6 import javax.swing.BorderFactory;
7 import javax.swing.ButtonGroup;
8 import javax.swing.JCheckBox;
9 import javax.swing.JFrame;
10 import javax.swing.JLabel;
11 import javax.swing.JOptionPane;
12 import javax.swing.JPanel;
13 import javax.swing.JRadioButton;
14 import javax.swing.JSpinner;
15 import javax.swing.SpinnerNumberModel;
16 import javax.swing.event.ChangeEvent;
17 import javax.swing.event.ChangeListener;
19 import net.miginfocom.swing.MigLayout;
20 import net.sf.openrocket.document.OpenRocketDocument;
21 import net.sf.openrocket.document.Simulation;
22 import net.sf.openrocket.document.StorageOptions;
23 import net.sf.openrocket.file.RocketSaver;
24 import net.sf.openrocket.file.openrocket.OpenRocketSaver;
25 import net.sf.openrocket.simulation.FlightData;
26 import net.sf.openrocket.simulation.FlightDataBranch;
28 public class StorageOptionChooser extends JPanel {
30 public static final double DEFAULT_SAVE_TIME_SKIP = 0.20;
32 private final OpenRocketDocument document;
34 private JRadioButton allButton;
35 private JRadioButton someButton;
36 private JRadioButton noneButton;
38 private JSpinner timeSpinner;
40 private JCheckBox compressButton;
42 private JLabel estimateLabel;
45 private boolean artificialEvent = false;
47 public StorageOptionChooser(OpenRocketDocument doc, StorageOptions opts) {
48 super(new MigLayout());
53 ChangeListener changeUpdater = new ChangeListener() {
55 public void stateChanged(ChangeEvent e) {
59 ActionListener actionUpdater = new ActionListener() {
61 public void actionPerformed(ActionEvent e) {
67 ButtonGroup buttonGroup = new ButtonGroup();
70 this.add(new JLabel("Simulated data to store:"), "spanx, wrap unrel");
72 allButton = new JRadioButton("All simulated data");
73 allButton.setToolTipText("<html>Store all simulated data.<br>" +
74 "This can result in very large files!");
75 buttonGroup.add(allButton);
76 allButton.addActionListener(actionUpdater);
77 this.add(allButton, "spanx, wrap rel");
80 someButton = new JRadioButton("Every");
81 tip = "<html>Store plottable values approximately this far apart.<br>" +
82 "Larger values result in smaller files.";
83 someButton.setToolTipText(tip);
84 buttonGroup.add(someButton);
85 someButton.addActionListener(actionUpdater);
86 this.add(someButton, "");
88 timeSpinner = new JSpinner(new SpinnerNumberModel(0.0, 0.0, 5.0, 0.1));
89 timeSpinner.setToolTipText(tip);
90 timeSpinner.addChangeListener(new ChangeListener() {
92 public void stateChanged(ChangeEvent e) {
95 someButton.setSelected(true);
98 this.add(timeSpinner, "wmin 55lp");
99 timeSpinner.addChangeListener(changeUpdater);
101 JLabel label = new JLabel("seconds");
102 label.setToolTipText(tip);
103 this.add(label, "wrap rel");
106 noneButton = new JRadioButton("Only primary figures");
107 noneButton.setToolTipText("<html>Store only the values shown in the summary table.<br>" +
108 "This results in the smallest files.");
109 buttonGroup.add(noneButton);
110 noneButton.addActionListener(actionUpdater);
111 this.add(noneButton, "spanx, wrap 20lp");
115 compressButton = new JCheckBox("Compress file");
116 compressButton.setToolTipText("Using compression reduces the file size significantly.");
117 compressButton.addActionListener(actionUpdater);
118 this.add(compressButton, "spanx, wrap para");
121 // Estimate is updated in loadOptions(opts)
122 estimateLabel = new JLabel("");
123 estimateLabel.setToolTipText("An estimate on how large the resulting file would " +
124 "be with the present options.");
125 this.add(estimateLabel, "spanx");
128 this.setBorder(BorderFactory.createCompoundBorder(
129 BorderFactory.createEmptyBorder(0, 10, 0, 0),
130 BorderFactory.createTitledBorder("Save options")));
136 public void loadOptions(StorageOptions opts) {
139 // Data storage radio button
140 t = opts.getSimulationTimeSkip();
141 if (t == StorageOptions.SIMULATION_DATA_ALL) {
142 allButton.setSelected(true);
143 t = DEFAULT_SAVE_TIME_SKIP;
144 } else if (t == StorageOptions.SIMULATION_DATA_NONE) {
145 noneButton.setSelected(true);
146 t = DEFAULT_SAVE_TIME_SKIP;
148 someButton.setSelected(true);
152 artificialEvent = true;
153 timeSpinner.setValue(t);
154 artificialEvent = false;
156 // Compression checkbox
157 compressButton.setSelected(opts.isCompressionEnabled());
163 public void storeOptions(StorageOptions opts) {
166 if (allButton.isSelected()) {
167 t = StorageOptions.SIMULATION_DATA_ALL;
168 } else if (noneButton.isSelected()) {
169 t = StorageOptions.SIMULATION_DATA_NONE;
171 t = (Double)timeSpinner.getValue();
174 opts.setSimulationTimeSkip(t);
176 opts.setCompressionEnabled(compressButton.isSelected());
178 opts.setExplicitlySet(true);
183 // TODO: MEDIUM: The estimation method always uses OpenRocketSaver!
184 private static final RocketSaver ROCKET_SAVER = new OpenRocketSaver();
186 private void updateEstimate() {
187 StorageOptions opts = new StorageOptions();
190 long size = ROCKET_SAVER.estimateFileSize(document, opts);
191 size = Math.max((size+512)/1024, 1);
196 formatted = (size/1000) + " MB";
197 } else if (size >= 1000){
198 formatted = (size/1000) + "." + ((size/100)%10) + " MB";
199 } else if (size >= 100) {
200 formatted = ((size/10)*10) + " kB";
202 formatted = size + " kB";
205 estimateLabel.setText("Estimated file size: " + formatted);
211 * Asks the user the storage options using a modal dialog window if the document
212 * contains simulated data and the user has not explicitly set how to store the data.
214 * @param document the document to check.
215 * @param parent the parent frame for the dialog.
216 * @return <code>true</code> to continue, <code>false</code> if the user cancelled.
218 public static boolean verifyStorageOptions(OpenRocketDocument document, JFrame parent) {
219 StorageOptions options = document.getDefaultStorageOptions();
221 if (options.isExplicitlySet()) {
222 // User has explicitly set the values, save as is
227 boolean hasData = false;
230 for (Simulation s: document.getSimulations()) {
231 if (s.getStatus() == Simulation.Status.NOT_SIMULATED ||
232 s.getStatus() == Simulation.Status.EXTERNAL)
235 FlightData data = s.getSimulatedData();
239 for (int i=0; i < data.getBranchCount(); i++) {
240 FlightDataBranch branch = data.getBranch(i);
243 if (branch.getLength() > 0) {
245 break simulationLoop;
252 // No data to store, do not ask only about compression
257 StorageOptionChooser chooser = new StorageOptionChooser(document, options);
259 if (JOptionPane.showConfirmDialog(parent, chooser, "Save options",
260 JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE) !=
261 JOptionPane.OK_OPTION) {
266 chooser.storeOptions(options);