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.l10n.Translator;
26 import net.sf.openrocket.simulation.FlightData;
27 import net.sf.openrocket.simulation.FlightDataBranch;
28 import net.sf.openrocket.startup.Application;
30 public class StorageOptionChooser extends JPanel {
32 public static final double DEFAULT_SAVE_TIME_SKIP = 0.20;
34 private final OpenRocketDocument document;
36 private JRadioButton allButton;
37 private JRadioButton someButton;
38 private JRadioButton noneButton;
40 private JSpinner timeSpinner;
42 private JCheckBox compressButton;
44 private JLabel estimateLabel;
47 private boolean artificialEvent = false;
48 private static final Translator trans = Application.getTranslator();
50 public StorageOptionChooser(OpenRocketDocument doc, StorageOptions opts) {
51 super(new MigLayout());
56 ChangeListener changeUpdater = new ChangeListener() {
58 public void stateChanged(ChangeEvent e) {
62 ActionListener actionUpdater = new ActionListener() {
64 public void actionPerformed(ActionEvent e) {
70 ButtonGroup buttonGroup = new ButtonGroup();
73 //// Simulated data to store:
74 this.add(new JLabel(trans.get("StorageOptChooser.lbl.Simdatatostore")), "spanx, wrap unrel");
76 //// All simulated data
77 allButton = new JRadioButton(trans.get("StorageOptChooser.rdbut.Allsimdata"));
78 //// <html>Store all simulated data.<br>
79 //// This can result in very large files!
80 allButton.setToolTipText(trans.get("StorageOptChooser.lbl.longA1") +
81 trans.get("StorageOptChooser.lbl.longA2"));
82 buttonGroup.add(allButton);
83 allButton.addActionListener(actionUpdater);
84 this.add(allButton, "spanx, wrap rel");
87 someButton = new JRadioButton(trans.get("StorageOptChooser.rdbut.Every"));
88 //// <html>Store plottable values approximately this far apart.<br>"
89 //// Larger values result in smaller files.
90 tip = trans.get("StorageOptChooser.lbl.longB1") +
91 trans.get("StorageOptChooser.lbl.longB2");
92 someButton.setToolTipText(tip);
93 buttonGroup.add(someButton);
94 someButton.addActionListener(actionUpdater);
95 this.add(someButton, "");
97 timeSpinner = new JSpinner(new SpinnerNumberModel(0.0, 0.0, 5.0, 0.1));
98 timeSpinner.setToolTipText(tip);
99 timeSpinner.addChangeListener(new ChangeListener() {
101 public void stateChanged(ChangeEvent e) {
104 someButton.setSelected(true);
107 this.add(timeSpinner, "wmin 55lp");
108 timeSpinner.addChangeListener(changeUpdater);
111 JLabel label = new JLabel(trans.get("StorageOptChooser.lbl.seconds"));
112 label.setToolTipText(tip);
113 this.add(label, "wrap rel");
115 //// Only primary figures
116 noneButton = new JRadioButton(trans.get("StorageOptChooser.rdbut.Onlyprimfig"));
117 //// <html>Store only the values shown in the summary table.<br>
118 //// This results in the smallest files.
119 noneButton.setToolTipText(trans.get("StorageOptChooser.lbl.longC1") +
120 trans.get("StorageOptChooser.lbl.longC2"));
121 buttonGroup.add(noneButton);
122 noneButton.addActionListener(actionUpdater);
123 this.add(noneButton, "spanx, wrap 20lp");
127 compressButton = new JCheckBox(trans.get("StorageOptChooser.checkbox.Compfile"));
128 //// Using compression reduces the file size significantly.
129 compressButton.setToolTipText(trans.get("StorageOptChooser.lbl.UsingComp"));
130 compressButton.addActionListener(actionUpdater);
131 this.add(compressButton, "spanx, wrap para");
134 // Estimate is updated in loadOptions(opts)
135 estimateLabel = new JLabel("");
136 //// An estimate on how large the resulting file would
137 //// be with the present options.
138 estimateLabel.setToolTipText(trans.get("StorageOptChooser.lbl.longD1"));
139 this.add(estimateLabel, "spanx");
142 this.setBorder(BorderFactory.createCompoundBorder(
143 BorderFactory.createEmptyBorder(0, 10, 0, 0),
145 BorderFactory.createTitledBorder(trans.get("StorageOptChooser.ttip.Saveopt"))));
151 public void loadOptions(StorageOptions opts) {
154 // Data storage radio button
155 t = opts.getSimulationTimeSkip();
156 if (t == StorageOptions.SIMULATION_DATA_ALL) {
157 allButton.setSelected(true);
158 t = DEFAULT_SAVE_TIME_SKIP;
159 } else if (t == StorageOptions.SIMULATION_DATA_NONE) {
160 noneButton.setSelected(true);
161 t = DEFAULT_SAVE_TIME_SKIP;
163 someButton.setSelected(true);
167 artificialEvent = true;
168 timeSpinner.setValue(t);
169 artificialEvent = false;
171 // Compression checkbox
172 compressButton.setSelected(opts.isCompressionEnabled());
178 public void storeOptions(StorageOptions opts) {
181 if (allButton.isSelected()) {
182 t = StorageOptions.SIMULATION_DATA_ALL;
183 } else if (noneButton.isSelected()) {
184 t = StorageOptions.SIMULATION_DATA_NONE;
186 t = (Double)timeSpinner.getValue();
189 opts.setSimulationTimeSkip(t);
191 opts.setCompressionEnabled(compressButton.isSelected());
193 opts.setExplicitlySet(true);
198 // TODO: MEDIUM: The estimation method always uses OpenRocketSaver!
199 private static final RocketSaver ROCKET_SAVER = new OpenRocketSaver();
201 private void updateEstimate() {
202 StorageOptions opts = new StorageOptions();
205 long size = ROCKET_SAVER.estimateFileSize(document, opts);
206 size = Math.max((size+512)/1024, 1);
211 formatted = (size/1000) + " MB";
212 } else if (size >= 1000){
213 formatted = (size/1000) + "." + ((size/100)%10) + " MB";
214 } else if (size >= 100) {
215 formatted = ((size/10)*10) + " kB";
217 formatted = size + " kB";
220 //// Estimated file size:
221 estimateLabel.setText(trans.get("StorageOptChooser.lbl.Estfilesize") + " " + formatted);
227 * Asks the user the storage options using a modal dialog window if the document
228 * contains simulated data and the user has not explicitly set how to store the data.
230 * @param document the document to check.
231 * @param parent the parent frame for the dialog.
232 * @return <code>true</code> to continue, <code>false</code> if the user cancelled.
234 public static boolean verifyStorageOptions(OpenRocketDocument document, JFrame parent) {
235 StorageOptions options = document.getDefaultStorageOptions();
237 if (options.isExplicitlySet()) {
238 // User has explicitly set the values, save as is
243 boolean hasData = false;
246 for (Simulation s: document.getSimulations()) {
247 if (s.getStatus() == Simulation.Status.NOT_SIMULATED ||
248 s.getStatus() == Simulation.Status.EXTERNAL)
251 FlightData data = s.getSimulatedData();
255 for (int i=0; i < data.getBranchCount(); i++) {
256 FlightDataBranch branch = data.getBranch(i);
259 if (branch.getLength() > 0) {
261 break simulationLoop;
268 // No data to store, do not ask only about compression
273 StorageOptionChooser chooser = new StorageOptionChooser(document, options);
276 if (JOptionPane.showConfirmDialog(parent, chooser, trans.get("StorageOptChooser.lbl.Saveopt"),
277 JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE) !=
278 JOptionPane.OK_OPTION) {
283 chooser.storeOptions(options);