diff --git a/core/resources/l10n/messages.properties b/core/resources/l10n/messages.properties index 4e03dcac9..3fb752cca 100644 --- a/core/resources/l10n/messages.properties +++ b/core/resources/l10n/messages.properties @@ -366,6 +366,10 @@ pref.dlg.lbl.Temperature = Temperature: pref.dlg.lbl.Momentofinertia = Moment of inertia: pref.dlg.lbl.Pressure = Pressure: pref.dlg.lbl.Stability = Stability: +pref.dlg.lbl.SecondaryStability = Secondary Stability: +pref.dlg.lbl.SecondaryStability.ttip = Select the stability unit that will be displayed alongside the main stability unit in the design view. +pref.dlg.checkbox.DisplaySecondaryStability = Display secondary stability unit +pref.dlg.checkbox.DisplaySecondaryStability.ttip = If checked, a secondary stability unit will be displayed in the rocket design view. pref.dlg.lbl.FlightTime = Flight time: pref.dlg.lbl.effect1 = The effects will take place the next time you open a window. pref.dlg.lbl.Checkingupdates = Checking for updates\u2026 diff --git a/core/src/net/sf/openrocket/startup/Preferences.java b/core/src/net/sf/openrocket/startup/Preferences.java index 52508731f..0c78ed70b 100644 --- a/core/src/net/sf/openrocket/startup/Preferences.java +++ b/core/src/net/sf/openrocket/startup/Preferences.java @@ -44,6 +44,10 @@ public abstract class Preferences implements ChangeSource { public static final String USER_THRUST_CURVES_KEY = "UserThrustCurves"; public static final String DEFAULT_MACH_NUMBER = "DefaultMachNumber"; + + // Preferences related to units + public static final String DISPLAY_SECONDARY_STABILITY = "DisplaySecondaryStability"; + // Preferences related to data export public static final String EXPORT_FIELD_SEPARATOR = "ExportFieldSeparator"; public static final String EXPORT_DECIMAL_PLACES = "ExportDecimalPlaces"; @@ -201,6 +205,27 @@ public abstract class Preferences implements ChangeSource { } + /* + * *********************** Unit Preferences ******************************************* + */ + + /** + * Return whether to display a secondary stability unit in the rocket design view. + * @return true if the secondary unit should be displayed, false if not. + */ + public final boolean isDisplaySecondaryStability() { + return this.getBoolean(DISPLAY_SECONDARY_STABILITY, true); + } + + /** + * Set whether to display a secondary stability unit in the rocket design view. + * @param check if true, display the secondary unit, if false not. + */ + public final void setDisplaySecondaryStability(boolean check) { + this.putBoolean(DISPLAY_SECONDARY_STABILITY, check); + } + + /* * ****************************************************************************************** */ diff --git a/core/src/net/sf/openrocket/unit/UnitGroup.java b/core/src/net/sf/openrocket/unit/UnitGroup.java index 03dcf38d1..eb5621687 100644 --- a/core/src/net/sf/openrocket/unit/UnitGroup.java +++ b/core/src/net/sf/openrocket/unit/UnitGroup.java @@ -39,6 +39,8 @@ public class UnitGroup { public static final UnitGroup UNITS_AREA; public static final UnitGroup UNITS_STABILITY; + public static final UnitGroup UNITS_SECONDARY_STABILITY; + /** * This unit group contains only the caliber unit that never scales the originating "SI" value. * It can be used in cases where the originating value is already in calibers to obtains the correct unit. @@ -162,12 +164,10 @@ public class UnitGroup { UNITS_STABILITY = new UnitGroup(); - UNITS_STABILITY.addUnit(new GeneralUnit(0.001, "mm")); - UNITS_STABILITY.addUnit(new GeneralUnit(0.01, "cm")); - UNITS_STABILITY.addUnit(new GeneralUnit(1, "m")); - UNITS_STABILITY.addUnit(new GeneralUnit(0.0254, "in")); - UNITS_STABILITY.addUnit(new CaliberUnit((Rocket) null)); - UNITS_STABILITY.addUnit(new PercentageOfLengthUnit((Rocket) null)); + UNITS_SECONDARY_STABILITY = new UnitGroup(); + addStabilityUnits(UNITS_STABILITY); + addStabilityUnits(UNITS_SECONDARY_STABILITY); + UNITS_STABILITY_CALIBERS = new UnitGroup(); UNITS_STABILITY_CALIBERS.addUnit(new GeneralUnit(1, "cal")); @@ -310,6 +310,7 @@ public class UnitGroup { map.put("ACCELERATION", UNITS_ACCELERATION); map.put("AREA", UNITS_AREA); map.put("STABILITY", UNITS_STABILITY); + map.put("SECONDARY_STABILITY", UNITS_SECONDARY_STABILITY); map.put("MASS", UNITS_MASS); map.put("INERTIA", UNITS_INERTIA); map.put("ANGLE", UNITS_ANGLE); @@ -366,6 +367,7 @@ public class UnitGroup { UNITS_DISTANCE.setDefaultUnit("m"); UNITS_AREA.setDefaultUnit("cm" + SQUARED); UNITS_STABILITY.setDefaultUnit("cal"); + UNITS_SECONDARY_STABILITY.setDefaultUnit("%"); UNITS_VELOCITY.setDefaultUnit("m/s"); UNITS_ACCELERATION.setDefaultUnit("m/s" + SQUARED); UNITS_MASS.setDefaultUnit("g"); @@ -392,6 +394,7 @@ public class UnitGroup { UNITS_DISTANCE.setDefaultUnit("ft"); UNITS_AREA.setDefaultUnit("in" + SQUARED); UNITS_STABILITY.setDefaultUnit("cal"); + UNITS_SECONDARY_STABILITY.setDefaultUnit("%"); UNITS_VELOCITY.setDefaultUnit("ft/s"); UNITS_ACCELERATION.setDefaultUnit("ft/s" + SQUARED); UNITS_MASS.setDefaultUnit("oz"); @@ -425,6 +428,7 @@ public class UnitGroup { UNITS_ALL_LENGTHS.setDefaultUnit(2); UNITS_AREA.setDefaultUnit(1); UNITS_STABILITY.setDefaultUnit(4); + UNITS_SECONDARY_STABILITY.setDefaultUnit(5); UNITS_STABILITY_CALIBERS.setDefaultUnit(0); UNITS_VELOCITY.setDefaultUnit(0); UNITS_WINDSPEED.setDefaultUnit(0); @@ -448,6 +452,15 @@ public class UnitGroup { UNITS_COEFFICIENT.setDefaultUnit(0); UNITS_FREQUENCY.setDefaultUnit(1); } + + private static void addStabilityUnits(UnitGroup stabilityUnit) { + stabilityUnit.addUnit(new GeneralUnit(0.001, "mm")); + stabilityUnit.addUnit(new GeneralUnit(0.01, "cm")); + stabilityUnit.addUnit(new GeneralUnit(1, "m")); + stabilityUnit.addUnit(new GeneralUnit(0.0254, "in")); + stabilityUnit.addUnit(new CaliberUnit((Rocket) null)); + stabilityUnit.addUnit(new PercentageOfLengthUnit((Rocket) null)); + } /** @@ -457,7 +470,17 @@ public class UnitGroup { * @return the unit group */ public static StabilityUnitGroup stabilityUnits(Rocket rocket) { - return new StabilityUnitGroup(rocket); + return new StabilityUnitGroup(UnitGroup.UNITS_STABILITY, rocket); + } + + /** + * Return a UnitGroup for secondary stability units based on the rocket. + * + * @param rocket the rocket from which to calculate the caliber + * @return the unit group + */ + public static StabilityUnitGroup secondaryStabilityUnits(Rocket rocket) { + return new StabilityUnitGroup(UnitGroup.UNITS_SECONDARY_STABILITY, rocket); } @@ -468,7 +491,17 @@ public class UnitGroup { * @return the unit group */ public static StabilityUnitGroup stabilityUnits(FlightConfiguration config) { - return new StabilityUnitGroup(config); + return new StabilityUnitGroup(UnitGroup.UNITS_STABILITY, config); + } + + /** + * Return a UnitGroup for stability units based on the rocket configuration. + * + * @param config the rocket configuration from which to calculate the caliber + * @return the unit group + */ + public static StabilityUnitGroup secondaryStabilityUnits(FlightConfiguration config) { + return new StabilityUnitGroup(UnitGroup.UNITS_SECONDARY_STABILITY, config); } @@ -479,7 +512,17 @@ public class UnitGroup { * @return the unit group */ public static UnitGroup stabilityUnits(double reference) { - return new StabilityUnitGroup(reference); + return new StabilityUnitGroup(UnitGroup.UNITS_STABILITY, reference); + } + + /** + * Return a UnitGroup for secondary stability units based on a constant caliber. + * + * @param reference the constant reference length + * @return the unit group + */ + public static UnitGroup secondaryStabilityUnits(double reference) { + return new StabilityUnitGroup(UnitGroup.UNITS_SECONDARY_STABILITY, reference); } @@ -719,19 +762,25 @@ public class UnitGroup { */ public static class StabilityUnitGroup extends UnitGroup { private final PercentageOfLengthUnit percentageOfLengthUnit; + private final UnitGroup stabilityUnit; - public StabilityUnitGroup(double ref) { this(new CaliberUnit(ref), new PercentageOfLengthUnit(ref)); } - - public StabilityUnitGroup(Rocket rocket) { - this(new CaliberUnit(rocket), new PercentageOfLengthUnit(rocket)); + public StabilityUnitGroup(UnitGroup stabilityUnit, double ref) { + this(stabilityUnit, new CaliberUnit(ref), new PercentageOfLengthUnit(ref)); } - public StabilityUnitGroup(FlightConfiguration config) { this(new CaliberUnit(config), new PercentageOfLengthUnit(config)); } + public StabilityUnitGroup(UnitGroup stabilityUnit, Rocket rocket) { + this(stabilityUnit, new CaliberUnit(rocket), new PercentageOfLengthUnit(rocket)); + } - private StabilityUnitGroup(CaliberUnit caliberUnit, PercentageOfLengthUnit percentageOfLengthUnit) { + public StabilityUnitGroup(UnitGroup stabilityUnit, FlightConfiguration config) { + this(stabilityUnit, new CaliberUnit(config), new PercentageOfLengthUnit(config)); + } + + private StabilityUnitGroup(UnitGroup stabilityUnit, CaliberUnit caliberUnit, PercentageOfLengthUnit percentageOfLengthUnit) { this.percentageOfLengthUnit = percentageOfLengthUnit; - this.units.addAll(UnitGroup.UNITS_STABILITY.units); - this.defaultUnit = UnitGroup.UNITS_STABILITY.defaultUnit; + this.stabilityUnit = stabilityUnit; + this.units.addAll(stabilityUnit.units); + this.defaultUnit = stabilityUnit.defaultUnit; for (int i = 0; i < units.size(); i++) { if (units.get(i) instanceof CaliberUnit) { units.set(i, caliberUnit); @@ -746,7 +795,7 @@ public class UnitGroup { @Override public void setDefaultUnit(int n) { super.setDefaultUnit(n); - UNITS_STABILITY.setDefaultUnit(n); + this.stabilityUnit.setDefaultUnit(n); } /** diff --git a/swing/src/net/sf/openrocket/gui/dialogs/preferences/UnitsPreferencesPanel.java b/swing/src/net/sf/openrocket/gui/dialogs/preferences/UnitsPreferencesPanel.java index 013e1ada2..bb32755b0 100644 --- a/swing/src/net/sf/openrocket/gui/dialogs/preferences/UnitsPreferencesPanel.java +++ b/swing/src/net/sf/openrocket/gui/dialogs/preferences/UnitsPreferencesPanel.java @@ -3,8 +3,11 @@ package net.sf.openrocket.gui.dialogs.preferences; import java.awt.LayoutManager; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; import javax.swing.JButton; +import javax.swing.JCheckBox; import javax.swing.JComboBox; import javax.swing.JDialog; import javax.swing.JLabel; @@ -77,9 +80,33 @@ public class UnitsPreferencesPanel extends PreferencesPanel { //// Stability: leftPanel.add(new JLabel(trans.get("pref.dlg.lbl.Stability"))); - combo = new JComboBox(new DefaultUnitSelector(UnitGroup.UNITS_STABILITY)); + combo = new JComboBox<>(new DefaultUnitSelector(UnitGroup.UNITS_STABILITY)); leftPanel.add(combo, "sizegroup boxes, wrap"); + //// Secondary stability: + final JLabel labelSecStab = new JLabel(trans.get("pref.dlg.lbl.SecondaryStability")); + labelSecStab.setToolTipText(trans.get("pref.dlg.lbl.SecondaryStability.ttip")); + labelSecStab.setEnabled(preferences.isDisplaySecondaryStability()); + leftPanel.add(labelSecStab); + final JComboBox comboSecStab = new JComboBox<>(new DefaultUnitSelector(UnitGroup.UNITS_SECONDARY_STABILITY)); + comboSecStab.setToolTipText(trans.get("pref.dlg.lbl.SecondaryStability.ttip")); + comboSecStab.setEnabled(preferences.isDisplaySecondaryStability()); + leftPanel.add(comboSecStab, "sizegroup boxes, wrap"); + + //// Display secondary stability unit: + JCheckBox displaySecondary = new JCheckBox(trans.get("pref.dlg.checkbox.DisplaySecondaryStability")); + displaySecondary.setToolTipText(trans.get("pref.dlg.checkbox.DisplaySecondaryStability.ttip")); + displaySecondary.setSelected(preferences.isDisplaySecondaryStability()); + displaySecondary.addItemListener(new ItemListener() { + @Override + public void itemStateChanged(ItemEvent e) { + preferences.setDisplaySecondaryStability(e.getStateChange() == ItemEvent.SELECTED); + labelSecStab.setEnabled(e.getStateChange() == ItemEvent.SELECTED); + comboSecStab.setEnabled(e.getStateChange() == ItemEvent.SELECTED); + } + }); + leftPanel.add(displaySecondary, "spanx, wrap"); + // -------------- RIGHT PANEL @@ -133,8 +160,8 @@ public class UnitsPreferencesPanel extends PreferencesPanel { combo = new JComboBox(new DefaultUnitSelector(UnitGroup.UNITS_WINDSPEED)); rightPanel.add(combo, "sizegroup boxes, wrap"); - this.add(leftPanel); - this.add(rightPanel, "wrap para"); + this.add(leftPanel, "top"); + this.add(rightPanel, "top, wrap para"); //// Default metric button diff --git a/swing/src/net/sf/openrocket/gui/figureelements/RocketInfo.java b/swing/src/net/sf/openrocket/gui/figureelements/RocketInfo.java index 118ddfbf1..be07743a3 100644 --- a/swing/src/net/sf/openrocket/gui/figureelements/RocketInfo.java +++ b/swing/src/net/sf/openrocket/gui/figureelements/RocketInfo.java @@ -11,6 +11,7 @@ import java.awt.Rectangle; import java.awt.font.GlyphVector; import java.awt.geom.Rectangle2D; +import net.sf.openrocket.gui.util.SwingPreferences; import net.sf.openrocket.logging.Warning; import net.sf.openrocket.logging.WarningSet; import net.sf.openrocket.l10n.Translator; @@ -31,6 +32,7 @@ import net.sf.openrocket.util.MathUtil; public class RocketInfo implements FigureElement { private static final Translator trans = Application.getTranslator(); + private static final SwingPreferences preferences = (SwingPreferences) Application.getPreferences(); // Margin around the figure edges, pixels private static final int MARGIN = 8; @@ -42,6 +44,7 @@ public class RocketInfo implements FigureElement { private final Caret cgCaret = new CGCaret(0,0); private UnitGroup.StabilityUnitGroup stabilityUnits; + private UnitGroup.StabilityUnitGroup secondaryStabilityUnits; private FlightConfiguration configuration; private double cg = 0, cp = 0; @@ -66,6 +69,7 @@ public class RocketInfo implements FigureElement { public RocketInfo(FlightConfiguration configuration) { this.configuration = configuration; this.stabilityUnits = UnitGroup.stabilityUnits(configuration); + this.secondaryStabilityUnits = UnitGroup.secondaryStabilityUnits(configuration); } @@ -284,16 +288,21 @@ public class RocketInfo implements FigureElement { * @return the current stability margin in the currently selected stability unit and in percentage */ public String getStabilityCombined() { - Unit defaultUnit = stabilityUnits.getDefaultUnit(); - String stability = getStability(); + Unit stabilityUnit = stabilityUnits.getDefaultUnit(); + Unit secondaryStabilityUnit = secondaryStabilityUnits.getDefaultUnit(); - if (Double.isNaN(getStabilityValue()) || defaultUnit == stabilityUnits.getPercentageOfLengthUnit()) { - return stability; + String stabilityStr = getStability(); + + // Don't display secondary units if the stability is NaN, or if the secondary unit is the same as the primary unit, + // or if it is disabled in the preferences + if (Double.isNaN(getStabilityValue()) || secondaryStabilityUnit.equals(stabilityUnit) || + !preferences.isDisplaySecondaryStability()) { + return stabilityStr; } - String stabilityPercentage = getStabilityPercentage(); + String secondaryStabilityStr = getSecondaryStability(); - return stability + " (" + stabilityPercentage + ")"; + return stabilityStr + " / " + secondaryStabilityStr; } /** @@ -305,11 +314,11 @@ public class RocketInfo implements FigureElement { } /** - * Get the stability in the percentage length unit. - * @return the current stability margin in the percentage length unit + * Get the stability in the secondary stability unit. + * @return the current stability margin in the secondary stability unit */ - private String getStabilityPercentage() { - return stabilityUnits.getPercentageOfLengthUnit().toStringUnit(getStabilityValue()); + private String getSecondaryStability() { + return secondaryStabilityUnits.getDefaultUnit().toStringUnit(getStabilityValue()); } private double getStabilityValue() { @@ -508,5 +517,6 @@ public class RocketInfo implements FigureElement { public void setCurrentConfig(FlightConfiguration newConfig) { this.configuration = newConfig; this.stabilityUnits = UnitGroup.stabilityUnits(newConfig); + this.secondaryStabilityUnits = UnitGroup.secondaryStabilityUnits(newConfig); } }