refactored file package
[debian/openrocket] / src / net / sf / openrocket / gui / StorageOptionChooser.java
1 package net.sf.openrocket.gui;
2
3 import java.awt.event.ActionEvent;
4 import java.awt.event.ActionListener;
5
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;
18
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;
27
28 public class StorageOptionChooser extends JPanel {
29         
30         public static final double DEFAULT_SAVE_TIME_SKIP = 0.20;
31
32         private final OpenRocketDocument document;
33         
34         private JRadioButton allButton;
35         private JRadioButton someButton;
36         private JRadioButton noneButton;
37         
38         private JSpinner timeSpinner;
39         
40         private JCheckBox compressButton;
41         
42         private JLabel estimateLabel;
43         
44         
45         private boolean artificialEvent = false;
46         
47         public StorageOptionChooser(OpenRocketDocument doc, StorageOptions opts) {
48                 super(new MigLayout());
49                 
50                 this.document = doc;
51                 
52                 
53                 ChangeListener changeUpdater = new ChangeListener() {
54                         @Override
55                         public void stateChanged(ChangeEvent e) {
56                                 updateEstimate();
57                         }
58                 };
59                 ActionListener actionUpdater = new ActionListener() {
60                         @Override
61                         public void actionPerformed(ActionEvent e) {
62                                 updateEstimate();
63                         }
64                 };
65                 
66
67                 ButtonGroup buttonGroup = new ButtonGroup();
68                 String tip;
69                 
70                 this.add(new JLabel("Simulated data to store:"), "spanx, wrap unrel");
71
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");
78                 
79                 
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, "");
87                 
88                 timeSpinner = new JSpinner(new SpinnerNumberModel(0.0, 0.0, 5.0, 0.1));
89                 timeSpinner.setToolTipText(tip);
90                 timeSpinner.addChangeListener(new ChangeListener() {
91                         @Override
92                         public void stateChanged(ChangeEvent e) {
93                                 if (artificialEvent)
94                                         return;
95                                 someButton.setSelected(true);
96                         }
97                 });
98                 this.add(timeSpinner, "wmin 55lp");
99                 timeSpinner.addChangeListener(changeUpdater);
100                 
101                 JLabel label = new JLabel("seconds");
102                 label.setToolTipText(tip);
103                 this.add(label, "wrap rel");
104                 
105                 
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");
112                 
113                 
114                 
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");
119                 
120                 
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");
126                 
127                 
128                 this.setBorder(BorderFactory.createCompoundBorder(
129                                 BorderFactory.createEmptyBorder(0, 10, 0, 0),
130                                 BorderFactory.createTitledBorder("Save options")));
131                 
132                 loadOptions(opts);
133         }
134         
135         
136         public void loadOptions(StorageOptions opts) {
137                 double t;
138                 
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;
147                 } else {
148                         someButton.setSelected(true);
149                 }
150                 
151                 // Time skip spinner
152                 artificialEvent = true;
153                 timeSpinner.setValue(t);
154                 artificialEvent = false;
155                 
156                 // Compression checkbox
157                 compressButton.setSelected(opts.isCompressionEnabled());
158                 
159                 updateEstimate();
160         }
161         
162         
163         public void storeOptions(StorageOptions opts) {
164                 double t;
165                 
166                 if (allButton.isSelected()) {
167                         t = StorageOptions.SIMULATION_DATA_ALL;
168                 } else if (noneButton.isSelected()) {
169                         t = StorageOptions.SIMULATION_DATA_NONE;
170                 } else {
171                         t = (Double)timeSpinner.getValue();
172                 }
173                 
174                 opts.setSimulationTimeSkip(t);
175                 
176                 opts.setCompressionEnabled(compressButton.isSelected());
177                 
178                 opts.setExplicitlySet(true);
179         }
180         
181         
182         
183         // TODO: MEDIUM: The estimation method always uses OpenRocketSaver!
184         private static final RocketSaver ROCKET_SAVER = new OpenRocketSaver();
185         
186         private void updateEstimate() {
187                 StorageOptions opts = new StorageOptions();
188                 
189                 storeOptions(opts);
190                 long size = ROCKET_SAVER.estimateFileSize(document, opts);
191                 size = Math.max((size+512)/1024, 1);
192
193                 String formatted;
194                 
195                 if (size >= 10000) {
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";
201                 } else {
202                         formatted = size + " kB";
203                 }
204
205                 estimateLabel.setText("Estimated file size: " + formatted);
206         }
207         
208         
209         
210         /**
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.
213          * 
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.
217          */
218         public static boolean verifyStorageOptions(OpenRocketDocument document, JFrame parent) {
219                 StorageOptions options = document.getDefaultStorageOptions();
220                 
221                 if (options.isExplicitlySet()) {
222                         // User has explicitly set the values, save as is
223                         return true;
224                 }
225                 
226                 
227                 boolean hasData = false;
228                 
229                 simulationLoop:
230                         for (Simulation s: document.getSimulations()) {
231                                 if (s.getStatus() == Simulation.Status.NOT_SIMULATED ||
232                                                 s.getStatus() == Simulation.Status.EXTERNAL)
233                                         continue;
234                                 
235                                 FlightData data = s.getSimulatedData();
236                                 if (data == null)
237                                         continue;
238                                 
239                                 for (int i=0; i < data.getBranchCount(); i++) {
240                                         FlightDataBranch branch = data.getBranch(i);
241                                         if (branch == null)
242                                                 continue;
243                                         if (branch.getLength() > 0) {
244                                                 hasData = true;
245                                                 break simulationLoop;
246                                         }
247                                 }
248                         }
249                 
250
251                 if (!hasData) {
252                         // No data to store, do not ask only about compression
253                         return true;
254                 }
255                 
256                 
257                 StorageOptionChooser chooser = new StorageOptionChooser(document, options);
258                 
259                 if (JOptionPane.showConfirmDialog(parent, chooser, "Save options", 
260                                 JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE) !=
261                                         JOptionPane.OK_OPTION) {
262                         // User cancelled
263                         return false;
264                 }
265                 
266                 chooser.storeOptions(options);
267                 return true;
268         }
269         
270 }