Merge commit '46077ef99f953486550547c15bd60dd02bab9241' into upstream
[debian/openrocket] / core / src / net / sf / openrocket / gui / dialogs / preferences / PreferencesDialog.java
1 package net.sf.openrocket.gui.dialogs.preferences;
2
3 import java.awt.Dialog;
4 import java.awt.Window;
5 import java.awt.event.ActionEvent;
6 import java.awt.event.ActionListener;
7 import java.awt.event.WindowAdapter;
8 import java.awt.event.WindowEvent;
9 import java.io.File;
10 import java.util.ArrayList;
11 import java.util.Collections;
12 import java.util.List;
13 import java.util.Locale;
14
15 import javax.swing.AbstractListModel;
16 import javax.swing.ComboBoxModel;
17 import javax.swing.JButton;
18 import javax.swing.JCheckBox;
19 import javax.swing.JComboBox;
20 import javax.swing.JDialog;
21 import javax.swing.JFileChooser;
22 import javax.swing.JLabel;
23 import javax.swing.JOptionPane;
24 import javax.swing.JPanel;
25 import javax.swing.JProgressBar;
26 import javax.swing.JTabbedPane;
27 import javax.swing.JTextField;
28 import javax.swing.Timer;
29 import javax.swing.event.DocumentEvent;
30 import javax.swing.event.DocumentListener;
31
32 import net.miginfocom.swing.MigLayout;
33 import net.sf.openrocket.communication.UpdateInfo;
34 import net.sf.openrocket.communication.UpdateInfoRetriever;
35 import net.sf.openrocket.gui.components.DescriptionArea;
36 import net.sf.openrocket.gui.components.StyledLabel;
37 import net.sf.openrocket.gui.components.StyledLabel.Style;
38 import net.sf.openrocket.gui.dialogs.UpdateInfoDialog;
39 import net.sf.openrocket.gui.util.GUIUtil;
40 import net.sf.openrocket.gui.util.SwingPreferences;
41 import net.sf.openrocket.gui.util.SimpleFileFilter;
42 import net.sf.openrocket.l10n.L10N;
43 import net.sf.openrocket.l10n.Translator;
44 import net.sf.openrocket.logging.LogHelper;
45 import net.sf.openrocket.startup.Application;
46 import net.sf.openrocket.startup.Preferences;
47 import net.sf.openrocket.unit.Unit;
48 import net.sf.openrocket.unit.UnitGroup;
49 import net.sf.openrocket.util.BuildProperties;
50 import net.sf.openrocket.util.Named;
51 import net.sf.openrocket.util.Utils;
52
53
54 public class PreferencesDialog extends JDialog {
55         private static final LogHelper log = Application.getLogger();
56         
57         private final List<DefaultUnitSelector> unitSelectors = new ArrayList<DefaultUnitSelector>();
58         
59         private File defaultDirectory = null;
60         private static final Translator trans = Application.getTranslator();
61         
62         private PreferencesDialog(Window parent) {
63                 //// Preferences
64                 super(parent, trans.get("pref.dlg.title.Preferences"), Dialog.ModalityType.APPLICATION_MODAL);
65                 
66                 JPanel panel = new JPanel(new MigLayout("fill, gap unrel", "[grow]", "[grow][]"));
67                 
68                 JTabbedPane tabbedPane = new JTabbedPane();
69                 panel.add(tabbedPane, "grow, wrap");
70                 
71                 //// Units and Default units
72                 tabbedPane.addTab(trans.get("pref.dlg.tab.Units"), null, unitsPane(),
73                                 trans.get("pref.dlg.tab.Defaultunits"));
74                 //// Materials and Custom materials
75                 tabbedPane.addTab(trans.get("pref.dlg.tab.Materials"), null, new MaterialEditPanel(),
76                                 trans.get("pref.dlg.tab.Custommaterials"));
77                 //// Options and Miscellaneous options
78                 tabbedPane.addTab(trans.get("pref.dlg.tab.Options"), null, optionsPane(),
79                                 trans.get("pref.dlg.tab.Miscellaneousoptions"));
80                 
81                 //// Close button
82                 JButton close = new JButton(trans.get("dlg.but.close"));
83                 close.addActionListener(new ActionListener() {
84                         @Override
85                         public void actionPerformed(ActionEvent arg0) {
86                                 PreferencesDialog.this.setVisible(false);
87                                 PreferencesDialog.this.dispose();
88                         }
89                 });
90                 panel.add(close, "span, right, tag close");
91                 
92                 this.setContentPane(panel);
93                 pack();
94                 this.setLocationRelativeTo(null);
95                 
96                 this.addWindowListener(new WindowAdapter() {
97                         @Override
98                         public void windowClosed(WindowEvent e) {
99                                 ((SwingPreferences) Application.getPreferences()).storeDefaultUnits();
100                         }
101                 });
102                 
103                 GUIUtil.setDisposableDialogOptions(this, close);
104         }
105         
106         
107         private JPanel optionsPane() {
108                 JPanel panel = new JPanel(new MigLayout("fillx, ins 30lp n n n"));
109                 
110
111                 //// Language selector
112                 Locale userLocale = null;
113                 {
114                         String locale = Application.getPreferences().getString("locale", null);
115                         userLocale = L10N.toLocale(locale);
116                 }
117                 List<Named<Locale>> locales = new ArrayList<Named<Locale>>();
118                 for (Locale l : SwingPreferences.getSupportedLocales()) {
119                         locales.add(new Named<Locale>(l, l.getDisplayLanguage()));
120                 }
121                 Collections.sort(locales);
122                 locales.add(0, new Named<Locale>(null, trans.get("languages.default")));
123                 
124                 final JComboBox languageCombo = new JComboBox(locales.toArray());
125                 for (int i = 0; i < locales.size(); i++) {
126                         if (Utils.equals(userLocale, locales.get(i).get())) {
127                                 languageCombo.setSelectedIndex(i);
128                         }
129                 }
130                 languageCombo.addActionListener(new ActionListener() {
131                         @Override
132                         @SuppressWarnings("unchecked")
133                         public void actionPerformed(ActionEvent e) {
134                                 Named<Locale> selection = (Named<Locale>) languageCombo.getSelectedItem();
135                                 Locale l = selection.get();
136                                 Application.getPreferences().putString(Preferences.USER_LOCAL, l == null ? null : l.toString());
137                         }
138                 });
139                 panel.add(new JLabel(trans.get("lbl.language")), "gapright para");
140                 panel.add(languageCombo, "wrap rel, growx, sg combos");
141                 
142                 panel.add(new StyledLabel(trans.get("PreferencesDialog.lbl.languageEffect"), -3, Style.ITALIC), "span, wrap para*2");
143                 
144
145                 //// Position to insert new body components:
146                 panel.add(new JLabel(trans.get("pref.dlg.lbl.Positiontoinsert")), "gapright para");
147                 panel.add(new JComboBox(new PrefChoiseSelector(Preferences.BODY_COMPONENT_INSERT_POSITION_KEY,
148                                 //// Always ask
149                                 //// Insert in middle
150                                 //// Add to end
151                                 trans.get("pref.dlg.PrefChoiseSelector1"),
152                                 trans.get("pref.dlg.PrefChoiseSelector2"),
153                                 trans.get("pref.dlg.PrefChoiseSelector3"))), "wrap para, growx, sg combos");
154                 
155                 //// Confirm deletion of simulations:
156                 panel.add(new JLabel(trans.get("pref.dlg.lbl.Confirmdeletion")));
157                 panel.add(new JComboBox(new PrefBooleanSelector(Preferences.CONFIRM_DELETE_SIMULATION,
158                                 //// Delete
159                                 //// Confirm
160                                 trans.get("pref.dlg.PrefBooleanSelector1"),
161                                 trans.get("pref.dlg.PrefBooleanSelector2"), true)), "wrap 40lp, growx, sg combos");
162                 
163                 //// User-defined thrust curves:
164                 panel.add(new JLabel(trans.get("pref.dlg.lbl.User-definedthrust")), "spanx, wrap");
165                 final JTextField field = new JTextField();
166                 List<File> files = ((SwingPreferences) Application.getPreferences()).getUserThrustCurveFiles();
167                 String str = "";
168                 for (File file : files) {
169                         if (str.length() > 0) {
170                                 str += ";";
171                         }
172                         str += file.getAbsolutePath();
173                 }
174                 field.setText(str);
175                 field.getDocument().addDocumentListener(new DocumentListener() {
176                         @Override
177                         public void removeUpdate(DocumentEvent e) {
178                                 changed();
179                         }
180                         
181                         @Override
182                         public void insertUpdate(DocumentEvent e) {
183                                 changed();
184                         }
185                         
186                         @Override
187                         public void changedUpdate(DocumentEvent e) {
188                                 changed();
189                         }
190                         
191                         private void changed() {
192                                 String text = field.getText();
193                                 List<File> list = new ArrayList<File>();
194                                 for (String s : text.split(";")) {
195                                         s = s.trim();
196                                         if (s.length() > 0) {
197                                                 list.add(new File(s));
198                                         }
199                                 }
200                                 ((SwingPreferences) Application.getPreferences()).setUserThrustCurveFiles(list);
201                         }
202                 });
203                 panel.add(field, "w 100px, gapright unrel, spanx, growx, split");
204                 
205                 //// Add button
206                 JButton button = new JButton(trans.get("pref.dlg.but.add"));
207                 button.addActionListener(new ActionListener() {
208                         @Override
209                         public void actionPerformed(ActionEvent e) {
210                                 JFileChooser chooser = new JFileChooser();
211                                 SimpleFileFilter filter =
212                                                 new SimpleFileFilter(
213                                                                 //// All thrust curve files (*.eng; *.rse; *.zip; directories)
214                                                                 trans.get("pref.dlg.Allthrustcurvefiles"),
215                                                                 true, "eng", "rse", "zip");
216                                 chooser.addChoosableFileFilter(filter);
217                                 //// RASP motor files (*.eng)
218                                 chooser.addChoosableFileFilter(new SimpleFileFilter(trans.get("pref.dlg.RASPfiles"),
219                                                 true, "eng"));
220                                 //// RockSim engine files (*.rse)
221                                 chooser.addChoosableFileFilter(new SimpleFileFilter(trans.get("pref.dlg.RockSimfiles"),
222                                                 true, "rse"));
223                                 //// ZIP archives (*.zip)
224                                 chooser.addChoosableFileFilter(new SimpleFileFilter(trans.get("pref.dlg.ZIParchives"),
225                                                 true, "zip"));
226                                 chooser.setFileFilter(filter);
227                                 chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
228                                 if (defaultDirectory != null) {
229                                         chooser.setCurrentDirectory(defaultDirectory);
230                                 }
231                                 
232                                 //// Add
233                                 int returnVal = chooser.showDialog(PreferencesDialog.this, trans.get("pref.dlg.Add"));
234                                 if (returnVal == JFileChooser.APPROVE_OPTION) {
235                                         log.user("Adding user thrust curve: " + chooser.getSelectedFile());
236                                         defaultDirectory = chooser.getCurrentDirectory();
237                                         String text = field.getText().trim();
238                                         if (text.length() > 0) {
239                                                 text += ";";
240                                         }
241                                         text += chooser.getSelectedFile().getAbsolutePath();
242                                         field.setText(text);
243                                 }
244                         }
245                 });
246                 panel.add(button, "gapright unrel");
247                 
248                 //// Reset button
249                 button = new JButton(trans.get("pref.dlg.but.reset"));
250                 
251                 button.addActionListener(new ActionListener() {
252                         @Override
253                         public void actionPerformed(ActionEvent e) {
254                                 // First one sets to the default, but does not un-set the pref
255                                 field.setText(((SwingPreferences)Application.getPreferences()).getDefaultUserThrustCurveFile().getAbsolutePath());
256                                 ((SwingPreferences) Application.getPreferences()).setUserThrustCurveFiles(null);
257                         }
258                 });
259                 panel.add(button, "wrap");
260                 
261                 //// Add directories, RASP motor files (*.eng), RockSim engine files (*.rse) or ZIP archives separated by a semicolon (;) to load external thrust curves.  Changes will take effect the next time you start OpenRocket.
262                 DescriptionArea desc = new DescriptionArea(trans.get("pref.dlg.DescriptionArea.Adddirectories"), 3, -3, false);
263                 desc.setBackground(getBackground());
264                 panel.add(desc, "spanx, growx, wrap 40lp");
265                 
266
267
268                 //// Check for software updates at startup
269                 final JCheckBox softwareUpdateBox =
270                                 new JCheckBox(trans.get("pref.dlg.checkbox.Checkupdates"));
271                 softwareUpdateBox.setSelected( Application.getPreferences().getCheckUpdates());
272                 softwareUpdateBox.addActionListener(new ActionListener() {
273                         @Override
274                         public void actionPerformed(ActionEvent e) {
275                                 Application.getPreferences().setCheckUpdates(softwareUpdateBox.isSelected());
276                         }
277                 });
278                 panel.add(softwareUpdateBox);
279                 
280                 //// Check now button
281                 button = new JButton(trans.get("pref.dlg.but.checknow"));
282                 //// Check for software updates now
283                 button.setToolTipText(trans.get("pref.dlg.ttip.Checkupdatesnow"));
284                 button.addActionListener(new ActionListener() {
285                         @Override
286                         public void actionPerformed(ActionEvent e) {
287                                 checkForUpdates();
288                         }
289                 });
290                 panel.add(button, "right, wrap");
291                 
292
293                 return panel;
294         }
295         
296         private JPanel unitsPane() {
297                 JPanel panel = new JPanel(new MigLayout("", "[][]40lp[][]"));
298                 JComboBox combo;
299                 
300                 //// Select your preferred units:
301                 panel.add(new JLabel(trans.get("pref.dlg.lbl.Selectprefunits")), "span, wrap paragraph");
302                 
303
304                 //// Rocket dimensions:
305                 panel.add(new JLabel(trans.get("pref.dlg.lbl.Rocketdimensions")));
306                 combo = new JComboBox(new DefaultUnitSelector(UnitGroup.UNITS_LENGTH));
307                 panel.add(combo, "sizegroup boxes");
308                 
309                 //// Line density:
310                 panel.add(new JLabel(trans.get("pref.dlg.lbl.Linedensity")));
311                 combo = new JComboBox(new DefaultUnitSelector(UnitGroup.UNITS_DENSITY_LINE));
312                 panel.add(combo, "sizegroup boxes, wrap");
313                 
314
315                 //// Motor dimensions:
316                 panel.add(new JLabel(trans.get("pref.dlg.lbl.Motordimensions")));
317                 combo = new JComboBox(new DefaultUnitSelector(UnitGroup.UNITS_MOTOR_DIMENSIONS));
318                 panel.add(combo, "sizegroup boxes");
319                 
320                 //// Surface density:
321                 panel.add(new JLabel(trans.get("pref.dlg.lbl.Surfacedensity")));
322                 combo = new JComboBox(new DefaultUnitSelector(UnitGroup.UNITS_DENSITY_SURFACE));
323                 panel.add(combo, "sizegroup boxes, wrap");
324                 
325
326                 //// Distance:
327                 panel.add(new JLabel(trans.get("pref.dlg.lbl.Distance")));
328                 combo = new JComboBox(new DefaultUnitSelector(UnitGroup.UNITS_DISTANCE));
329                 panel.add(combo, "sizegroup boxes");
330                 
331                 //// Bulk density::
332                 panel.add(new JLabel(trans.get("pref.dlg.lbl.Bulkdensity")));
333                 combo = new JComboBox(new DefaultUnitSelector(UnitGroup.UNITS_DENSITY_BULK));
334                 panel.add(combo, "sizegroup boxes, wrap");
335                 
336
337                 //// Velocity:
338                 panel.add(new JLabel(trans.get("pref.dlg.lbl.Velocity")));
339                 combo = new JComboBox(new DefaultUnitSelector(UnitGroup.UNITS_VELOCITY));
340                 panel.add(combo, "sizegroup boxes");
341                 
342                 //// Surface roughness:
343                 panel.add(new JLabel(trans.get("pref.dlg.lbl.Surfaceroughness")));
344                 combo = new JComboBox(new DefaultUnitSelector(UnitGroup.UNITS_ROUGHNESS));
345                 panel.add(combo, "sizegroup boxes, wrap");
346                 
347
348                 //// Acceleration:
349                 panel.add(new JLabel(trans.get("pref.dlg.lbl.Acceleration")));
350                 combo = new JComboBox(new DefaultUnitSelector(UnitGroup.UNITS_ACCELERATION));
351                 panel.add(combo, "sizegroup boxes");
352                 
353                 //// Area:
354                 panel.add(new JLabel(trans.get("pref.dlg.lbl.Area")));
355                 combo = new JComboBox(new DefaultUnitSelector(UnitGroup.UNITS_AREA));
356                 panel.add(combo, "sizegroup boxes, wrap");
357                 
358
359                 //// Mass:
360                 panel.add(new JLabel(trans.get("pref.dlg.lbl.Mass")));
361                 combo = new JComboBox(new DefaultUnitSelector(UnitGroup.UNITS_MASS));
362                 panel.add(combo, "sizegroup boxes");
363                 
364                 //// Angle:
365                 panel.add(new JLabel(trans.get("pref.dlg.lbl.Angle")));
366                 combo = new JComboBox(new DefaultUnitSelector(UnitGroup.UNITS_ANGLE));
367                 panel.add(combo, "sizegroup boxes, wrap");
368                 
369
370                 //// Force:
371                 panel.add(new JLabel(trans.get("pref.dlg.lbl.Force")));
372                 combo = new JComboBox(new DefaultUnitSelector(UnitGroup.UNITS_FORCE));
373                 panel.add(combo, "sizegroup boxes");
374                 
375                 //// Roll rate:
376                 panel.add(new JLabel(trans.get("pref.dlg.lbl.Rollrate")));
377                 combo = new JComboBox(new DefaultUnitSelector(UnitGroup.UNITS_ROLL));
378                 panel.add(combo, "sizegroup boxes, wrap");
379                 
380
381                 //// Total impulse:
382                 panel.add(new JLabel(trans.get("pref.dlg.lbl.Totalimpulse")));
383                 combo = new JComboBox(new DefaultUnitSelector(UnitGroup.UNITS_IMPULSE));
384                 panel.add(combo, "sizegroup boxes");
385                 
386                 //// Temperature:
387                 panel.add(new JLabel(trans.get("pref.dlg.lbl.Temperature")));
388                 combo = new JComboBox(new DefaultUnitSelector(UnitGroup.UNITS_TEMPERATURE));
389                 panel.add(combo, "sizegroup boxes, wrap");
390                 
391
392                 //// Moment of inertia:
393                 panel.add(new JLabel(trans.get("pref.dlg.lbl.Momentofinertia")));
394                 combo = new JComboBox(new DefaultUnitSelector(UnitGroup.UNITS_INERTIA));
395                 panel.add(combo, "sizegroup boxes");
396                 
397                 //// Pressure:
398                 panel.add(new JLabel(trans.get("pref.dlg.lbl.Pressure")));
399                 combo = new JComboBox(new DefaultUnitSelector(UnitGroup.UNITS_PRESSURE));
400                 panel.add(combo, "sizegroup boxes, wrap");
401                 
402
403                 //// Stability:
404                 panel.add(new JLabel(trans.get("pref.dlg.lbl.Stability")));
405                 combo = new JComboBox(new DefaultUnitSelector(UnitGroup.UNITS_STABILITY));
406                 panel.add(combo, "sizegroup boxes, wrap para");
407                 
408
409
410                 //// Default metric button
411                 JButton button = new JButton(trans.get("pref.dlg.but.defaultmetric"));
412                 button.addActionListener(new ActionListener() {
413                         @Override
414                         public void actionPerformed(ActionEvent e) {
415                                 UnitGroup.setDefaultMetricUnits();
416                                 for (DefaultUnitSelector s : unitSelectors)
417                                         s.fireChange();
418                         }
419                 });
420                 panel.add(button, "spanx, split 2, grow");
421                 
422                 //// Default imperial button
423                 button = new JButton(trans.get("pref.dlg.but.defaultimperial"));
424                 button.addActionListener(new ActionListener() {
425                         @Override
426                         public void actionPerformed(ActionEvent e) {
427                                 UnitGroup.setDefaultImperialUnits();
428                                 for (DefaultUnitSelector s : unitSelectors)
429                                         s.fireChange();
430                         }
431                 });
432                 panel.add(button, "grow, wrap para");
433                 
434                 //// The effects will take place the next time you open a window.
435                 panel.add(new StyledLabel(
436                                 trans.get("pref.dlg.lbl.effect1"), -2, Style.ITALIC),
437                                 "spanx, wrap");
438                 
439
440                 return panel;
441         }
442         
443         
444
445
446
447         private class DefaultUnitSelector extends AbstractListModel implements ComboBoxModel {
448                 
449                 private final UnitGroup group;
450                 
451                 public DefaultUnitSelector(UnitGroup group) {
452                         this.group = group;
453                         unitSelectors.add(this);
454                 }
455                 
456                 @Override
457                 public Object getSelectedItem() {
458                         return group.getDefaultUnit();
459                 }
460                 
461                 @Override
462                 public void setSelectedItem(Object item) {
463                         if (item == null) {
464                                 // Clear selection - huh?
465                                 return;
466                         }
467                         if (!(item instanceof Unit)) {
468                                 throw new IllegalArgumentException("Illegal argument " + item);
469                         }
470                         group.setDefaultUnit(group.getUnitIndex((Unit) item));
471                 }
472                 
473                 @Override
474                 public Object getElementAt(int index) {
475                         return group.getUnit(index);
476                 }
477                 
478                 @Override
479                 public int getSize() {
480                         return group.getUnitCount();
481                 }
482                 
483                 
484                 public void fireChange() {
485                         this.fireContentsChanged(this, 0, this.getSize());
486                 }
487         }
488         
489         
490
491         private class PrefChoiseSelector extends AbstractListModel implements ComboBoxModel {
492                 private final String preference;
493                 private final String[] descriptions;
494                 
495                 public PrefChoiseSelector(String preference, String... descriptions) {
496                         this.preference = preference;
497                         this.descriptions = descriptions;
498                 }
499                 
500                 @Override
501                 public Object getSelectedItem() {
502                         return descriptions[Application.getPreferences().getChoice(preference, descriptions.length, 0)];
503                 }
504                 
505                 @Override
506                 public void setSelectedItem(Object item) {
507                         if (item == null) {
508                                 // Clear selection - huh?
509                                 return;
510                         }
511                         if (!(item instanceof String)) {
512                                 throw new IllegalArgumentException("Illegal argument " + item);
513                         }
514                         int index;
515                         for (index = 0; index < descriptions.length; index++) {
516                                 if (((String) item).equalsIgnoreCase(descriptions[index]))
517                                         break;
518                         }
519                         if (index >= descriptions.length) {
520                                 throw new IllegalArgumentException("Illegal argument " + item);
521                         }
522                         
523                         Application.getPreferences().putChoice(preference, index);
524                 }
525                 
526                 @Override
527                 public Object getElementAt(int index) {
528                         return descriptions[index];
529                 }
530                 
531                 @Override
532                 public int getSize() {
533                         return descriptions.length;
534                 }
535         }
536         
537         
538         private class PrefBooleanSelector extends AbstractListModel implements ComboBoxModel {
539                 private final String preference;
540                 private final String trueDesc, falseDesc;
541                 private final boolean def;
542                 
543                 public PrefBooleanSelector(String preference, String falseDescription,
544                                 String trueDescription, boolean defaultState) {
545                         this.preference = preference;
546                         this.trueDesc = trueDescription;
547                         this.falseDesc = falseDescription;
548                         this.def = defaultState;
549                 }
550                 
551                 @Override
552                 public Object getSelectedItem() {
553                         if (Application.getPreferences().getBoolean(preference, def)) {
554                                 return trueDesc;
555                         } else {
556                                 return falseDesc;
557                         }
558                 }
559                 
560                 @Override
561                 public void setSelectedItem(Object item) {
562                         if (item == null) {
563                                 // Clear selection - huh?
564                                 return;
565                         }
566                         if (!(item instanceof String)) {
567                                 throw new IllegalArgumentException("Illegal argument " + item);
568                         }
569                         
570                         if (trueDesc.equals(item)) {
571                                 Application.getPreferences().putBoolean(preference, true);
572                         } else if (falseDesc.equals(item)) {
573                                 Application.getPreferences().putBoolean(preference, false);
574                         } else {
575                                 throw new IllegalArgumentException("Illegal argument " + item);
576                         }
577                 }
578                 
579                 @Override
580                 public Object getElementAt(int index) {
581                         switch (index) {
582                         case 0:
583                                 return def ? trueDesc : falseDesc;
584                                 
585                         case 1:
586                                 return def ? falseDesc : trueDesc;
587                                 
588                         default:
589                                 throw new IndexOutOfBoundsException("Boolean asked for index=" + index);
590                         }
591                 }
592                 
593                 @Override
594                 public int getSize() {
595                         return 2;
596                 }
597         }
598         
599         
600         private void checkForUpdates() {
601                 final UpdateInfoRetriever retriever = new UpdateInfoRetriever();
602                 retriever.start();
603                 
604
605                 // Progress dialog
606                 final JDialog dialog = new JDialog(this, ModalityType.APPLICATION_MODAL);
607                 JPanel panel = new JPanel(new MigLayout());
608                 
609                 //// Checking for updates...
610                 panel.add(new JLabel(trans.get("pref.dlg.lbl.Checkingupdates")), "wrap");
611                 
612                 JProgressBar bar = new JProgressBar();
613                 bar.setIndeterminate(true);
614                 panel.add(bar, "growx, wrap para");
615                 
616                 //// Cancel button
617                 JButton cancel = new JButton(trans.get("dlg.but.cancel"));
618                 cancel.addActionListener(new ActionListener() {
619                         @Override
620                         public void actionPerformed(ActionEvent e) {
621                                 dialog.dispose();
622                         }
623                 });
624                 panel.add(cancel, "right");
625                 dialog.add(panel);
626                 
627                 GUIUtil.setDisposableDialogOptions(dialog, cancel);
628                 
629
630                 // Timer to monitor progress
631                 final Timer timer = new Timer(100, null);
632                 final long startTime = System.currentTimeMillis();
633                 
634                 ActionListener listener = new ActionListener() {
635                         @Override
636                         public void actionPerformed(ActionEvent e) {
637                                 if (!retriever.isRunning() || startTime + 10000 < System.currentTimeMillis()) {
638                                         timer.stop();
639                                         dialog.dispose();
640                                 }
641                         }
642                 };
643                 timer.addActionListener(listener);
644                 timer.start();
645                 
646
647                 // Wait for action
648                 dialog.setVisible(true);
649                 
650
651                 // Check result
652                 UpdateInfo info = retriever.getUpdateInfo();
653                 if (info == null) {
654                         JOptionPane.showMessageDialog(this,
655                                         //// An error occurred while communicating with the server.
656                                         trans.get("pref.dlg.lbl.msg1"),
657                                         //// Unable to retrieve update information
658                                         trans.get("pref.dlg.lbl.msg2"), JOptionPane.WARNING_MESSAGE, null);
659                 } else if (info.getLatestVersion() == null ||
660                                 info.getLatestVersion().equals("") ||
661                                 BuildProperties.getVersion().equalsIgnoreCase(info.getLatestVersion())) {
662                         JOptionPane.showMessageDialog(this,
663                                         //// You are running the latest version of OpenRocket.
664                                         trans.get("pref.dlg.lbl.msg3"),
665                                         //// No updates available
666                                         trans.get("pref.dlg.lbl.msg4"), JOptionPane.INFORMATION_MESSAGE, null);
667                 } else {
668                         UpdateInfoDialog infoDialog = new UpdateInfoDialog(info);
669                         infoDialog.setVisible(true);
670                         if (infoDialog.isReminderSelected()) {
671                                 Application.getPreferences().putString(SwingPreferences.LAST_UPDATE, "");
672                         } else {
673                                 Application.getPreferences().putString(SwingPreferences.LAST_UPDATE, info.getLatestVersion());
674                         }
675                 }
676                 
677         }
678         
679         
680         ////////  Singleton implementation  ////////
681         
682         private static PreferencesDialog dialog = null;
683         
684         public static void showPreferences(Window parent) {
685                 if (dialog != null) {
686                         dialog.dispose();
687                 }
688                 dialog = new PreferencesDialog(parent);
689                 dialog.setVisible(true);
690         }
691         
692
693 }