diff --git a/core/resources/l10n/messages.properties b/core/resources/l10n/messages.properties index 1c68f3fd2..902ced7c1 100644 --- a/core/resources/l10n/messages.properties +++ b/core/resources/l10n/messages.properties @@ -220,6 +220,7 @@ MaterialModel.title.Defcustmat = Define custom material pref.dlg.but.add = Add pref.dlg.but.reset = Reset pref.dlg.but.checknow = Check now +pref.dlg.but.openlast = Open last design file on startup pref.dlg.but.defaultmetric = Default metric pref.dlg.but.defaultimperial = Default imperial pref.dlg.title.Preferences = Preferences @@ -486,7 +487,7 @@ ExpressionBuilderDialog.led.ttip.Name = Name must not have already been used ExpressionBuilderDialog.led.ttip.Symbol = Symbol must not have already been used ExpressionBuilderDialog.led.ttip.Expression = Expression must use only known symbols and operators ExpressionBuilderDialog.CopyToOtherSimulations = Copy to other simulations -ExpressionBuilderDialog.CopyToOtherSimulations.ttip = Make a copy of this expression in other simulations in this document.
Will not overwrite or modify any existing expressions in other simulations. +ExpressionBuilderDialog.CopyToOtherSimulations.ttip = Make a copy of this expression in other simulations in this document.
Will not overwrite or modify any existing expressions in other simulations. ! Custom expression variable selector CustomVariableSelector.title = Variable Selector @@ -520,7 +521,7 @@ Operator.htan = Hyperbolic tangent Operator.log10 = Base 10 logarithm Operator.round = Round to nearest integer value Operator.random = Random number between zero and given value -Operator.expm1 = The same as exp(x)-1, but more accurate for small x +Operator.expm1 = The same as exp(x)-1, but more accurate for small x Operator.mean = The arithmetic mean of a given range Operator.min = The minimum value in a given range Operator.max = The maximum value in a given range @@ -1106,7 +1107,7 @@ main.menu.analyze.componentAnalysis.desc = Analyze the rocket components separat main.menu.analyze.optimization = Rocket optimization main.menu.analyze.optimization.desc = General rocket design optimization main.menu.analyze.customExpressions = Custom expressions -main.menu.analyze.customExpressions.desc = Define new flight data types by writing custom mathematical expressions +main.menu.analyze.customExpressions.desc = Define new flight data types by writing custom mathematical expressions main.menu.help = Help main.menu.help.desc = Information about OpenRocket diff --git a/core/src/net/sf/openrocket/gui/dialogs/preferences/PreferencesDialog.java b/core/src/net/sf/openrocket/gui/dialogs/preferences/PreferencesDialog.java index a3d963ee9..82cf33d9a 100644 --- a/core/src/net/sf/openrocket/gui/dialogs/preferences/PreferencesDialog.java +++ b/core/src/net/sf/openrocket/gui/dialogs/preferences/PreferencesDialog.java @@ -53,21 +53,21 @@ import net.sf.openrocket.util.Utils; public class PreferencesDialog extends JDialog { private static final LogHelper log = Application.getLogger(); - + private final List unitSelectors = new ArrayList(); - + private File defaultDirectory = null; private static final Translator trans = Application.getTranslator(); - + private PreferencesDialog(Window parent) { //// Preferences super(parent, trans.get("pref.dlg.title.Preferences"), Dialog.ModalityType.APPLICATION_MODAL); - + JPanel panel = new JPanel(new MigLayout("fill, gap unrel", "[grow]", "[grow][]")); - + JTabbedPane tabbedPane = new JTabbedPane(); panel.add(tabbedPane, "grow, wrap"); - + //// Units and Default units tabbedPane.addTab(trans.get("pref.dlg.tab.Units"), null, unitsPane(), trans.get("pref.dlg.tab.Defaultunits")); @@ -77,7 +77,7 @@ public class PreferencesDialog extends JDialog { //// Options and Miscellaneous options tabbedPane.addTab(trans.get("pref.dlg.tab.Options"), null, optionsPane(), trans.get("pref.dlg.tab.Miscellaneousoptions")); - + //// Close button JButton close = new JButton(trans.get("dlg.but.close")); close.addActionListener(new ActionListener() { @@ -88,25 +88,25 @@ public class PreferencesDialog extends JDialog { } }); panel.add(close, "span, right, tag close"); - + this.setContentPane(panel); pack(); this.setLocationRelativeTo(null); - + this.addWindowListener(new WindowAdapter() { @Override public void windowClosed(WindowEvent e) { ((SwingPreferences) Application.getPreferences()).storeDefaultUnits(); } }); - + GUIUtil.setDisposableDialogOptions(this, close); } - - + + private JPanel optionsPane() { JPanel panel = new JPanel(new MigLayout("fillx, ins 30lp n n n")); - + //// Language selector Locale userLocale = null; @@ -120,7 +120,7 @@ public class PreferencesDialog extends JDialog { } Collections.sort(locales); locales.add(0, new Named(null, trans.get("languages.default"))); - + final JComboBox languageCombo = new JComboBox(locales.toArray()); for (int i = 0; i < locales.size(); i++) { if (Utils.equals(userLocale, locales.get(i).get())) { @@ -138,9 +138,9 @@ public class PreferencesDialog extends JDialog { }); panel.add(new JLabel(trans.get("lbl.language")), "gapright para"); panel.add(languageCombo, "wrap rel, growx, sg combos"); - + panel.add(new StyledLabel(trans.get("PreferencesDialog.lbl.languageEffect"), -3, Style.ITALIC), "span, wrap para*2"); - + //// Position to insert new body components: panel.add(new JLabel(trans.get("pref.dlg.lbl.Positiontoinsert")), "gapright para"); @@ -151,7 +151,7 @@ public class PreferencesDialog extends JDialog { trans.get("pref.dlg.PrefChoiseSelector1"), trans.get("pref.dlg.PrefChoiseSelector2"), trans.get("pref.dlg.PrefChoiseSelector3"))), "wrap para, growx, sg combos"); - + //// Confirm deletion of simulations: panel.add(new JLabel(trans.get("pref.dlg.lbl.Confirmdeletion"))); panel.add(new JComboBox(new PrefBooleanSelector(Preferences.CONFIRM_DELETE_SIMULATION, @@ -159,7 +159,7 @@ public class PreferencesDialog extends JDialog { //// Confirm trans.get("pref.dlg.PrefBooleanSelector1"), trans.get("pref.dlg.PrefBooleanSelector2"), true)), "wrap 40lp, growx, sg combos"); - + //// User-defined thrust curves: panel.add(new JLabel(trans.get("pref.dlg.lbl.User-definedthrust")), "spanx, wrap"); final JTextField field = new JTextField(); @@ -177,17 +177,17 @@ public class PreferencesDialog extends JDialog { public void removeUpdate(DocumentEvent e) { changed(); } - + @Override public void insertUpdate(DocumentEvent e) { changed(); } - + @Override public void changedUpdate(DocumentEvent e) { changed(); } - + private void changed() { String text = field.getText(); List list = new ArrayList(); @@ -201,7 +201,7 @@ public class PreferencesDialog extends JDialog { } }); panel.add(field, "w 100px, gapright unrel, spanx, growx, split"); - + //// Add button JButton button = new JButton(trans.get("pref.dlg.but.add")); button.addActionListener(new ActionListener() { @@ -228,7 +228,7 @@ public class PreferencesDialog extends JDialog { if (defaultDirectory != null) { chooser.setCurrentDirectory(defaultDirectory); } - + //// Add int returnVal = chooser.showDialog(PreferencesDialog.this, trans.get("pref.dlg.Add")); if (returnVal == JFileChooser.APPROVE_OPTION) { @@ -244,10 +244,10 @@ public class PreferencesDialog extends JDialog { } }); panel.add(button, "gapright unrel"); - + //// Reset button button = new JButton(trans.get("pref.dlg.but.reset")); - + button.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { @@ -257,12 +257,12 @@ public class PreferencesDialog extends JDialog { } }); panel.add(button, "wrap"); - + //// 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. DescriptionArea desc = new DescriptionArea(trans.get("pref.dlg.DescriptionArea.Adddirectories"), 3, -3, false); desc.setBackground(getBackground()); panel.add(desc, "spanx, growx, wrap 40lp"); - + //// Check for software updates at startup @@ -276,7 +276,7 @@ public class PreferencesDialog extends JDialog { } }); panel.add(softwareUpdateBox); - + //// Check now button button = new JButton(trans.get("pref.dlg.but.checknow")); //// Check for software updates now @@ -288,127 +288,137 @@ public class PreferencesDialog extends JDialog { } }); panel.add(button, "right, wrap"); - - return panel; + + final JCheckBox autoOpenDesignFile = new JCheckBox(trans.get("pref.dlg.but.openlast")); + autoOpenDesignFile.setSelected(Application.getPreferences().isAutoOpenLastDesignOnStartupEnabled()); + autoOpenDesignFile.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + Application.getPreferences().setAutoOpenLastDesignOnStartup(autoOpenDesignFile.isSelected()); + } + }); + panel.add(autoOpenDesignFile); + + return panel; } - + private JPanel unitsPane() { JPanel panel = new JPanel(new MigLayout("", "[][]40lp[][]")); JComboBox combo; - + //// Select your preferred units: panel.add(new JLabel(trans.get("pref.dlg.lbl.Selectprefunits")), "span, wrap paragraph"); - + //// Rocket dimensions: panel.add(new JLabel(trans.get("pref.dlg.lbl.Rocketdimensions"))); combo = new JComboBox(new DefaultUnitSelector(UnitGroup.UNITS_LENGTH)); panel.add(combo, "sizegroup boxes"); - + //// Line density: panel.add(new JLabel(trans.get("pref.dlg.lbl.Linedensity"))); combo = new JComboBox(new DefaultUnitSelector(UnitGroup.UNITS_DENSITY_LINE)); panel.add(combo, "sizegroup boxes, wrap"); - + //// Motor dimensions: panel.add(new JLabel(trans.get("pref.dlg.lbl.Motordimensions"))); combo = new JComboBox(new DefaultUnitSelector(UnitGroup.UNITS_MOTOR_DIMENSIONS)); panel.add(combo, "sizegroup boxes"); - + //// Surface density: panel.add(new JLabel(trans.get("pref.dlg.lbl.Surfacedensity"))); combo = new JComboBox(new DefaultUnitSelector(UnitGroup.UNITS_DENSITY_SURFACE)); panel.add(combo, "sizegroup boxes, wrap"); - + //// Distance: panel.add(new JLabel(trans.get("pref.dlg.lbl.Distance"))); combo = new JComboBox(new DefaultUnitSelector(UnitGroup.UNITS_DISTANCE)); panel.add(combo, "sizegroup boxes"); - + //// Bulk density:: panel.add(new JLabel(trans.get("pref.dlg.lbl.Bulkdensity"))); combo = new JComboBox(new DefaultUnitSelector(UnitGroup.UNITS_DENSITY_BULK)); panel.add(combo, "sizegroup boxes, wrap"); - + //// Velocity: panel.add(new JLabel(trans.get("pref.dlg.lbl.Velocity"))); combo = new JComboBox(new DefaultUnitSelector(UnitGroup.UNITS_VELOCITY)); panel.add(combo, "sizegroup boxes"); - + //// Surface roughness: panel.add(new JLabel(trans.get("pref.dlg.lbl.Surfaceroughness"))); combo = new JComboBox(new DefaultUnitSelector(UnitGroup.UNITS_ROUGHNESS)); panel.add(combo, "sizegroup boxes, wrap"); - + //// Acceleration: panel.add(new JLabel(trans.get("pref.dlg.lbl.Acceleration"))); combo = new JComboBox(new DefaultUnitSelector(UnitGroup.UNITS_ACCELERATION)); panel.add(combo, "sizegroup boxes"); - + //// Area: panel.add(new JLabel(trans.get("pref.dlg.lbl.Area"))); combo = new JComboBox(new DefaultUnitSelector(UnitGroup.UNITS_AREA)); panel.add(combo, "sizegroup boxes, wrap"); - + //// Mass: panel.add(new JLabel(trans.get("pref.dlg.lbl.Mass"))); combo = new JComboBox(new DefaultUnitSelector(UnitGroup.UNITS_MASS)); panel.add(combo, "sizegroup boxes"); - + //// Angle: panel.add(new JLabel(trans.get("pref.dlg.lbl.Angle"))); combo = new JComboBox(new DefaultUnitSelector(UnitGroup.UNITS_ANGLE)); panel.add(combo, "sizegroup boxes, wrap"); - + //// Force: panel.add(new JLabel(trans.get("pref.dlg.lbl.Force"))); combo = new JComboBox(new DefaultUnitSelector(UnitGroup.UNITS_FORCE)); panel.add(combo, "sizegroup boxes"); - + //// Roll rate: panel.add(new JLabel(trans.get("pref.dlg.lbl.Rollrate"))); combo = new JComboBox(new DefaultUnitSelector(UnitGroup.UNITS_ROLL)); panel.add(combo, "sizegroup boxes, wrap"); - + //// Total impulse: panel.add(new JLabel(trans.get("pref.dlg.lbl.Totalimpulse"))); combo = new JComboBox(new DefaultUnitSelector(UnitGroup.UNITS_IMPULSE)); panel.add(combo, "sizegroup boxes"); - + //// Temperature: panel.add(new JLabel(trans.get("pref.dlg.lbl.Temperature"))); combo = new JComboBox(new DefaultUnitSelector(UnitGroup.UNITS_TEMPERATURE)); panel.add(combo, "sizegroup boxes, wrap"); - + //// Moment of inertia: panel.add(new JLabel(trans.get("pref.dlg.lbl.Momentofinertia"))); combo = new JComboBox(new DefaultUnitSelector(UnitGroup.UNITS_INERTIA)); panel.add(combo, "sizegroup boxes"); - + //// Pressure: panel.add(new JLabel(trans.get("pref.dlg.lbl.Pressure"))); combo = new JComboBox(new DefaultUnitSelector(UnitGroup.UNITS_PRESSURE)); panel.add(combo, "sizegroup boxes, wrap"); - + //// Stability: panel.add(new JLabel(trans.get("pref.dlg.lbl.Stability"))); combo = new JComboBox(new DefaultUnitSelector(UnitGroup.UNITS_STABILITY)); panel.add(combo, "sizegroup boxes"); - + //// Windspeed: panel.add(new JLabel(trans.get("pref.dlg.lbl.Windspeed"))); combo = new JComboBox(new DefaultUnitSelector(UnitGroup.UNITS_WINDSPEED)); panel.add(combo, "sizegroup boxes, wrap para"); - + @@ -423,7 +433,7 @@ public class PreferencesDialog extends JDialog { } }); panel.add(button, "spanx, split 2, grow"); - + //// Default imperial button button = new JButton(trans.get("pref.dlg.but.defaultimperial")); button.addActionListener(new ActionListener() { @@ -435,34 +445,34 @@ public class PreferencesDialog extends JDialog { } }); panel.add(button, "grow, wrap para"); - + //// The effects will take place the next time you open a window. panel.add(new StyledLabel( trans.get("pref.dlg.lbl.effect1"), -2, Style.ITALIC), "spanx, wrap"); - + return panel; } - - + + private class DefaultUnitSelector extends AbstractListModel implements ComboBoxModel { - + private final UnitGroup group; - + public DefaultUnitSelector(UnitGroup group) { this.group = group; unitSelectors.add(this); } - + @Override public Object getSelectedItem() { return group.getDefaultUnit(); } - + @Override public void setSelectedItem(Object item) { if (item == null) { @@ -474,39 +484,39 @@ public class PreferencesDialog extends JDialog { } group.setDefaultUnit(group.getUnitIndex((Unit) item)); } - + @Override public Object getElementAt(int index) { return group.getUnit(index); } - + @Override public int getSize() { return group.getUnitCount(); } - - + + public void fireChange() { this.fireContentsChanged(this, 0, this.getSize()); } } - - + + private class PrefChoiseSelector extends AbstractListModel implements ComboBoxModel { private final String preference; private final String[] descriptions; - + public PrefChoiseSelector(String preference, String... descriptions) { this.preference = preference; this.descriptions = descriptions; } - + @Override public Object getSelectedItem() { return descriptions[Application.getPreferences().getChoice(preference, descriptions.length, 0)]; } - + @Override public void setSelectedItem(Object item) { if (item == null) { @@ -524,27 +534,27 @@ public class PreferencesDialog extends JDialog { if (index >= descriptions.length) { throw new IllegalArgumentException("Illegal argument " + item); } - + Application.getPreferences().putChoice(preference, index); } - + @Override public Object getElementAt(int index) { return descriptions[index]; } - + @Override public int getSize() { return descriptions.length; } } - - + + private class PrefBooleanSelector extends AbstractListModel implements ComboBoxModel { private final String preference; private final String trueDesc, falseDesc; private final boolean def; - + public PrefBooleanSelector(String preference, String falseDescription, String trueDescription, boolean defaultState) { this.preference = preference; @@ -552,7 +562,7 @@ public class PreferencesDialog extends JDialog { this.falseDesc = falseDescription; this.def = defaultState; } - + @Override public Object getSelectedItem() { if (Application.getPreferences().getBoolean(preference, def)) { @@ -561,7 +571,7 @@ public class PreferencesDialog extends JDialog { return falseDesc; } } - + @Override public void setSelectedItem(Object item) { if (item == null) { @@ -571,7 +581,7 @@ public class PreferencesDialog extends JDialog { if (!(item instanceof String)) { throw new IllegalArgumentException("Illegal argument " + item); } - + if (trueDesc.equals(item)) { Application.getPreferences().putBoolean(preference, true); } else if (falseDesc.equals(item)) { @@ -580,44 +590,44 @@ public class PreferencesDialog extends JDialog { throw new IllegalArgumentException("Illegal argument " + item); } } - + @Override public Object getElementAt(int index) { switch (index) { case 0: return def ? trueDesc : falseDesc; - + case 1: return def ? falseDesc : trueDesc; - + default: throw new IndexOutOfBoundsException("Boolean asked for index=" + index); } } - + @Override public int getSize() { return 2; } } - - + + private void checkForUpdates() { final UpdateInfoRetriever retriever = new UpdateInfoRetriever(); retriever.start(); - + // Progress dialog final JDialog dialog = new JDialog(this, ModalityType.APPLICATION_MODAL); JPanel panel = new JPanel(new MigLayout()); - + //// Checking for updates... panel.add(new JLabel(trans.get("pref.dlg.lbl.Checkingupdates")), "wrap"); - + JProgressBar bar = new JProgressBar(); bar.setIndeterminate(true); panel.add(bar, "growx, wrap para"); - + //// Cancel button JButton cancel = new JButton(trans.get("dlg.but.cancel")); cancel.addActionListener(new ActionListener() { @@ -628,14 +638,14 @@ public class PreferencesDialog extends JDialog { }); panel.add(cancel, "right"); dialog.add(panel); - + GUIUtil.setDisposableDialogOptions(dialog, cancel); - + // Timer to monitor progress final Timer timer = new Timer(100, null); final long startTime = System.currentTimeMillis(); - + ActionListener listener = new ActionListener() { @Override public void actionPerformed(ActionEvent e) { @@ -647,11 +657,11 @@ public class PreferencesDialog extends JDialog { }; timer.addActionListener(listener); timer.start(); - + // Wait for action dialog.setVisible(true); - + // Check result UpdateInfo info = retriever.getUpdateInfo(); @@ -678,14 +688,14 @@ public class PreferencesDialog extends JDialog { Application.getPreferences().putString(SwingPreferences.LAST_UPDATE, info.getLatestVersion()); } } - + } - - + + //////// Singleton implementation //////// - + private static PreferencesDialog dialog = null; - + public static void showPreferences(Window parent) { if (dialog != null) { dialog.dispose(); @@ -693,6 +703,6 @@ public class PreferencesDialog extends JDialog { dialog = new PreferencesDialog(parent); dialog.setVisible(true); } - + } diff --git a/core/src/net/sf/openrocket/gui/main/BasicFrame.java b/core/src/net/sf/openrocket/gui/main/BasicFrame.java index bdfcbd4a0..b804905ca 100644 --- a/core/src/net/sf/openrocket/gui/main/BasicFrame.java +++ b/core/src/net/sf/openrocket/gui/main/BasicFrame.java @@ -1058,7 +1058,7 @@ public class BasicFrame extends JFrame { log.info("Closing window because it is replaceable"); closeAction(); } - + } /** * Open a file based on a URL. diff --git a/core/src/net/sf/openrocket/gui/main/MRUDesignFile.java b/core/src/net/sf/openrocket/gui/main/MRUDesignFile.java index f32d23e88..e010986b7 100644 --- a/core/src/net/sf/openrocket/gui/main/MRUDesignFile.java +++ b/core/src/net/sf/openrocket/gui/main/MRUDesignFile.java @@ -56,6 +56,20 @@ public class MRUDesignFile { return mruFileList; } + /** + * Get the last edited design file. + * + * @return an absolute file name, or null + */ + public String getLastEditedDesignFile() { + if (!mruFileList.isEmpty()) { + return mruFileList.get(0); + } + else { + return null; + } + } + /** * Set the most-recently-used list to the given parameter and fire change events. * diff --git a/core/src/net/sf/openrocket/startup/Preferences.java b/core/src/net/sf/openrocket/startup/Preferences.java index 73a29cc2f..46e1239d0 100644 --- a/core/src/net/sf/openrocket/startup/Preferences.java +++ b/core/src/net/sf/openrocket/startup/Preferences.java @@ -22,7 +22,7 @@ import net.sf.openrocket.util.MathUtil; import net.sf.openrocket.util.UniqueID; public abstract class Preferences { - + /* * Well known string keys to preferences. * There are other strings out there in the source as well. @@ -37,39 +37,40 @@ public abstract class Preferences { public static final String EXPORT_EVENT_COMMENTS = "ExportEventComments"; public static final String EXPORT_COMMENT_CHARACTER = "ExportCommentCharacter"; public static final String USER_LOCAL = "locale"; - + public static final String PLOT_SHOW_POINTS = "ShowPlotPoints"; - + private static final String CHECK_UPDATES = "CheckUpdates"; public static final String LAST_UPDATE = "LastUpdateVersion"; - + public static final String MOTOR_DIAMETER_FILTER = "MotorDiameterMatch"; public static final String MOTOR_HIDE_SIMILAR = "MotorHideSimilar"; - + // Node names public static final String PREFERRED_THRUST_CURVE_MOTOR_NODE = "preferredThrustCurveMotors"; - - /* - * ****************************************************************************************** - * - * Abstract methods which must be implemented by any derived class. - */ + private static final String AUTO_OPEN_LAST_DESIGN = "AUTO_OPEN_LAST_DESIGN"; + + /* + * ****************************************************************************************** + * + * Abstract methods which must be implemented by any derived class. + */ public abstract boolean getBoolean(String key, boolean defaultValue); - + public abstract void putBoolean(String key, boolean value); - + public abstract int getInt(String key, int defaultValue); - + public abstract void putInt(String key, int value); - + public abstract double getDouble(String key, double defaultValue); - + public abstract void putDouble(String key, double value); - + public abstract String getString(String key, String defaultValue); - + public abstract void putString(String key, String value); - + /** * Directory represents a way to collect multiple keys together. Implementors may * choose to concatenate the directory with the key using some special character. @@ -79,28 +80,44 @@ public abstract class Preferences { * @return */ public abstract String getString(String directory, String key, String defaultValue); - + public abstract void putString(String directory, String key, String value); - + /* * ****************************************************************************************** */ public final boolean getCheckUpdates() { return this.getBoolean(CHECK_UPDATES, BuildProperties.getDefaultCheckUpdates()); } - + public final void setCheckUpdates(boolean check) { this.putBoolean(CHECK_UPDATES, check); } - + public final double getDefaultMach() { // TODO: HIGH: implement custom default mach number return 0.3; } - + + /** + * Enable/Disable the auto-opening of the last edited design file on startup. + */ + public final void setAutoOpenLastDesignOnStartup(boolean enabled) { + this.putBoolean(AUTO_OPEN_LAST_DESIGN, enabled); + } + + /** + * Answer if the auto-opening of the last edited design file on startup is enabled. + * + * @return true if the application should automatically open the last edited design file on startup. + */ + public final boolean isAutoOpenLastDesignOnStartupEnabled() { + return this.getBoolean(AUTO_OPEN_LAST_DESIGN, false); + } + /** * Return the OpenRocket unique ID. - * + * * @return a random ID string that stays constant between OpenRocket executions */ public final String getUniqueID() { @@ -111,12 +128,12 @@ public abstract class Preferences { } return id; } - + /** - * Returns a limited-range integer value from the preferences. If the value - * in the preferences is negative or greater than max, then the default value + * Returns a limited-range integer value from the preferences. If the value + * in the preferences is negative or greater than max, then the default value * is returned. - * + * * @param key The preference to retrieve. * @param max Maximum allowed value for the choice. * @param def Default value. @@ -128,20 +145,20 @@ public abstract class Preferences { return def; return v; } - + /** * Helper method that puts an integer choice value into the preferences. - * + * * @param key the preference key. * @param value the value to store. */ public final void putChoice(String key, int value) { this.putInt(key, value); } - + /** * Retrieve an enum value from the user preferences. - * + * * @param the enum type * @param key the key * @param def the default value, cannot be null @@ -151,22 +168,22 @@ public abstract class Preferences { if (def == null) { throw new BugException("Default value cannot be null"); } - + String value = getString(key, null); if (value == null) { return def; } - + try { return Enum.valueOf(def.getDeclaringClass(), value); } catch (IllegalArgumentException e) { return def; } } - + /** * Store an enum value to the user preferences. - * + * * @param key the key * @param value the value to store, or null to remove the value */ @@ -177,12 +194,12 @@ public abstract class Preferences { putString(key, value.name()); } } - + public Color getDefaultColor(Class c) { String color = get("componentColors", c, DEFAULT_COLORS); if (color == null) return Color.BLACK; - + Color clr = parseColor(color); if (clr != null) { return clr; @@ -190,14 +207,14 @@ public abstract class Preferences { return Color.BLACK; } } - + public final void setDefaultColor(Class c, Color color) { if (color == null) return; putString("componentColors", c.getSimpleName(), stringifyColor(color)); } - - + + /** * Retrieve a Line style for the given component. * @param c @@ -211,7 +228,7 @@ public abstract class Preferences { return LineStyle.SOLID; } } - + /** * Set a default line style for the given component. * @param c @@ -223,7 +240,7 @@ public abstract class Preferences { return; putString("componentStyle", c.getSimpleName(), style.name()); } - + /** * Get the default material type for the given component. * @param componentClass @@ -233,7 +250,7 @@ public abstract class Preferences { public Material getDefaultComponentMaterial( Class componentClass, Material.Type type) { - + String material = get("componentMaterials", componentClass, null); if (material != null) { try { @@ -243,7 +260,7 @@ public abstract class Preferences { } catch (IllegalArgumentException ignore) { } } - + switch (type) { case LINE: return DefaultMaterialHolder.DEFAULT_LINE_MATERIAL; @@ -254,7 +271,7 @@ public abstract class Preferences { } throw new IllegalArgumentException("Unknown material type: " + type); } - + /** * Set the default material for a component type. * @param componentClass @@ -262,11 +279,11 @@ public abstract class Preferences { */ public void setDefaultComponentMaterial( Class componentClass, Material material) { - + putString("componentMaterials", componentClass.getSimpleName(), material == null ? null : material.toStorableString()); } - + /** * get a net.sf.openrocket.util.Color object for the given key. * @param key @@ -280,7 +297,7 @@ public abstract class Preferences { } return c; } - + /** * set a net.sf.openrocket.util.Color preference value for the given key. * @param key @@ -289,7 +306,7 @@ public abstract class Preferences { public final void putColor(String key, Color value) { putString(key, stringifyColor(value)); } - + /** * Helper function to convert a string representation into a net.sf.openrocket.util.Color object. * @param color @@ -299,7 +316,7 @@ public abstract class Preferences { if (color == null) { return null; } - + String[] rgb = color.split(","); if (rgb.length == 3) { try { @@ -312,7 +329,7 @@ public abstract class Preferences { } return null; } - + /** * Helper function to convert a net.sf.openrocket.util.Color object into a * String before storing in a preference. @@ -323,13 +340,13 @@ public abstract class Preferences { String string = color.getRed() + "," + color.getGreen() + "," + color.getBlue(); return string; } - + /** * Special helper function which allows for a map of default values. - * + * * First getString(directory,componentClass.getSimpleName(), null) is invoked, * if the returned value is null, the defaultMap is consulted for a value. - * + * * @param directory * @param componentClass * @param defaultMap @@ -338,7 +355,7 @@ public abstract class Preferences { protected String get(String directory, Class componentClass, Map, String> defaultMap) { - + // Search preferences Class c = componentClass; while (c != null && RocketComponent.class.isAssignableFrom(c)) { @@ -347,10 +364,10 @@ public abstract class Preferences { return value; c = c.getSuperclass(); } - + if (defaultMap == null) return null; - + // Search defaults c = componentClass; while (RocketComponent.class.isAssignableFrom(c)) { @@ -359,20 +376,20 @@ public abstract class Preferences { return value; c = c.getSuperclass(); } - + return null; } - + public abstract void addUserMaterial(Material m); - + public abstract Set getUserMaterials(); - + public abstract void removeUserMaterial(Material m); - + public abstract void setComponentFavorite(ComponentPreset preset, ComponentPreset.Type type, boolean favorite); - + public abstract Set getComponentFavorites(ComponentPreset.Type type); - + /* * Map of default line styles */ @@ -382,7 +399,7 @@ public abstract class Preferences { DEFAULT_LINE_STYLES.put(RocketComponent.class, LineStyle.SOLID.name()); DEFAULT_LINE_STYLES.put(MassObject.class, LineStyle.DASHED.name()); } - + /* * Within a holder class so they will load only when needed. */ @@ -391,7 +408,7 @@ public abstract class Preferences { private static final Material DEFAULT_SURFACE_MATERIAL = Databases.findMaterial(Material.Type.SURFACE, "Ripstop nylon"); private static final Material DEFAULT_BULK_MATERIAL = Databases.findMaterial(Material.Type.BULK, "Cardboard"); } - + private static final HashMap, String> DEFAULT_COLORS = new HashMap, String>(); static { @@ -402,7 +419,7 @@ public abstract class Preferences { DEFAULT_COLORS.put(MassObject.class, "0,0,0"); DEFAULT_COLORS.put(RecoveryDevice.class, "255,0,0"); } - - - + + + } diff --git a/core/src/net/sf/openrocket/startup/Startup2.java b/core/src/net/sf/openrocket/startup/Startup2.java index 6b7b49cdf..82bc0d3c1 100644 --- a/core/src/net/sf/openrocket/startup/Startup2.java +++ b/core/src/net/sf/openrocket/startup/Startup2.java @@ -17,6 +17,7 @@ import net.sf.openrocket.database.ComponentPresetDatabase; import net.sf.openrocket.database.Databases; import net.sf.openrocket.gui.dialogs.UpdateInfoDialog; import net.sf.openrocket.gui.main.BasicFrame; +import net.sf.openrocket.gui.main.MRUDesignFile; import net.sf.openrocket.gui.main.Splash; import net.sf.openrocket.gui.main.SwingExceptionHandler; import net.sf.openrocket.gui.util.GUIUtil; @@ -27,38 +28,38 @@ import net.sf.openrocket.util.BuildProperties; /** * The second class in the OpenRocket startup sequence. This class can assume the * Application class to be properly set up, and can use any classes safely. - * + * * @author Sampo Niskanen */ public class Startup2 { private static final LogHelper log = Application.getLogger(); - + private static final String THRUSTCURVE_DIRECTORY = "datafiles/thrustcurves/"; - + /** * Run when starting up OpenRocket after Application has been set up. - * + * * @param args command line arguments */ static void runMain(final String[] args) throws Exception { - + log.info("Starting up OpenRocket version " + BuildProperties.getVersion()); - + // Check that we're not running headless log.info("Checking for graphics head"); checkHead(); - + // Check that we're running a good version of a JRE log.info("Checking JRE compatibility"); VersionHelper.checkVersion(); VersionHelper.checkOpenJDK(); - + // If running on a MAC set up OSX UI Elements. if ( SystemInfo.getPlatform() == Platform.MAC_OS ){ OSXStartup.setupOSX(); } - + // Run the actual startup method in the EDT since it can use progress dialogs etc. log.info("Moving startup to EDT"); SwingUtilities.invokeAndWait(new Runnable() { @@ -67,22 +68,22 @@ public class Startup2 { runInEDT(args); } }); - + log.info("Startup complete"); } - - + + /** * Run in the EDT when starting up OpenRocket. - * + * * @param args command line arguments */ private static void runInEDT(String[] args) { - + // Initialize the splash screen with version info log.info("Initializing the splash screen"); Splash.init(); - + // Must be done after localization is initialized ComponentPresetDatabase componentPresetDao = new ComponentPresetDatabase(true) { @@ -93,21 +94,21 @@ public class Startup2 { try { presetLoader.await(); } catch ( InterruptedException iex) { - + } } - + }; Application.setComponentPresetDao( componentPresetDao ); componentPresetDao.startLoading(); - + // Setup the uncaught exception handler log.info("Registering exception handler"); SwingExceptionHandler exceptionHandler = new SwingExceptionHandler(); Application.setExceptionHandler(exceptionHandler); exceptionHandler.registerExceptionHandler(); - + // Start update info fetching final UpdateInfoRetriever updateInfo; if ( Application.getPreferences().getCheckUpdates()) { @@ -118,37 +119,54 @@ public class Startup2 { log.info("Update check disabled"); updateInfo = null; } - + // Set the best available look-and-feel log.info("Setting best LAF"); GUIUtil.setBestLAF(); - + // Set tooltip delay time. Tooltips are used in MotorChooserDialog extensively. ToolTipManager.sharedInstance().setDismissDelay(30000); - + // Load defaults ((SwingPreferences) Application.getPreferences()).loadDefaultUnits(); - + // Load motors etc. log.info("Loading databases"); - + loadMotor(); - + Databases.fakeMethod(); - + // Starting action (load files or open new document) log.info("Opening main application window"); if (!handleCommandLine(args)) { - BasicFrame.newAction(); - } - + if (!Application.getPreferences().isAutoOpenLastDesignOnStartupEnabled()) { + BasicFrame.newAction(); + } + else { + String lastFile = MRUDesignFile.getInstance().getLastEditedDesignFile(); + if (lastFile != null) { + if (!BasicFrame.open(new File(lastFile), null)) { + MRUDesignFile.getInstance().removeFile(lastFile); + BasicFrame.newAction(); + } + else { + MRUDesignFile.getInstance().addFile(lastFile); + } + } + else { + BasicFrame.newAction(); + } + } + } + // Check whether update info has been fetched or whether it needs more time log.info("Checking update status"); checkUpdateStatus(updateInfo); - + } - + /** * this method is useful for the python bindings. */ @@ -157,12 +175,12 @@ public class Startup2 { motorLoader.startLoading(); Application.setMotorSetDatabase(motorLoader); } - + /** * Check that the JRE is not running headless. */ private static void checkHead() { - + if (GraphicsEnvironment.isHeadless()) { log.error("Application is headless."); System.err.println(); @@ -171,36 +189,36 @@ public class Startup2 { System.err.println(); System.exit(1); } - + } - - + + private static void checkUpdateStatus(final UpdateInfoRetriever updateInfo) { if (updateInfo == null) return; - + int delay = 1000; if (!updateInfo.isRunning()) delay = 100; - + final Timer timer = new Timer(delay, null); - + ActionListener listener = new ActionListener() { private int count = 5; - + @Override public void actionPerformed(ActionEvent e) { if (!updateInfo.isRunning()) { timer.stop(); - + String current = BuildProperties.getVersion(); String last = Application.getPreferences().getString(Preferences.LAST_UPDATE, ""); - + UpdateInfo info = updateInfo.getUpdateInfo(); if (info != null && info.getLatestVersion() != null && !current.equals(info.getLatestVersion()) && !last.equals(info.getLatestVersion())) { - + UpdateInfoDialog infoDialog = new UpdateInfoDialog(info); infoDialog.setVisible(true); if (infoDialog.isReminderSelected()) { @@ -218,18 +236,18 @@ public class Startup2 { timer.addActionListener(listener); timer.start(); } - + /** * Handles arguments passed from the command line. This may be used either * when starting the first instance of OpenRocket or later when OpenRocket is * executed again while running. - * + * * @param args the command-line arguments. * @return whether a new frame was opened or similar user desired action was * performed as a result. */ private static boolean handleCommandLine(String[] args) { - + // Check command-line for files boolean opened = false; for (String file : args) { @@ -239,5 +257,5 @@ public class Startup2 { } return opened; } - + }