From 6f3f1ed67d3763594b0cd993aaa0e2b30c24deec Mon Sep 17 00:00:00 2001 From: SiboVG Date: Wed, 24 May 2023 00:49:12 +0200 Subject: [PATCH 1/5] [#2079] Display percentage length unit in stability info --- .../src/net/sf/openrocket/unit/UnitGroup.java | 16 +++++-- .../gui/figureelements/RocketInfo.java | 45 ++++++++++++++++--- .../sf/openrocket/gui/print/DesignReport.java | 2 +- 3 files changed, 52 insertions(+), 11 deletions(-) diff --git a/core/src/net/sf/openrocket/unit/UnitGroup.java b/core/src/net/sf/openrocket/unit/UnitGroup.java index 654410d70..03dcf38d1 100644 --- a/core/src/net/sf/openrocket/unit/UnitGroup.java +++ b/core/src/net/sf/openrocket/unit/UnitGroup.java @@ -456,7 +456,7 @@ public class UnitGroup { * @param rocket the rocket from which to calculate the caliber * @return the unit group */ - public static UnitGroup stabilityUnits(Rocket rocket) { + public static StabilityUnitGroup stabilityUnits(Rocket rocket) { return new StabilityUnitGroup(rocket); } @@ -467,7 +467,7 @@ public class UnitGroup { * @param config the rocket configuration from which to calculate the caliber * @return the unit group */ - public static UnitGroup stabilityUnits(FlightConfiguration config) { + public static StabilityUnitGroup stabilityUnits(FlightConfiguration config) { return new StabilityUnitGroup(config); } @@ -717,7 +717,8 @@ public class UnitGroup { * A private class that switches the CaliberUnit to a rocket-specific CaliberUnit. * All other methods are passed through to UNITS_STABILITY. */ - private static class StabilityUnitGroup extends UnitGroup { + public static class StabilityUnitGroup extends UnitGroup { + private final PercentageOfLengthUnit percentageOfLengthUnit; public StabilityUnitGroup(double ref) { this(new CaliberUnit(ref), new PercentageOfLengthUnit(ref)); } @@ -728,6 +729,7 @@ public class UnitGroup { public StabilityUnitGroup(FlightConfiguration config) { this(new CaliberUnit(config), new PercentageOfLengthUnit(config)); } private StabilityUnitGroup(CaliberUnit caliberUnit, PercentageOfLengthUnit percentageOfLengthUnit) { + this.percentageOfLengthUnit = percentageOfLengthUnit; this.units.addAll(UnitGroup.UNITS_STABILITY.units); this.defaultUnit = UnitGroup.UNITS_STABILITY.defaultUnit; for (int i = 0; i < units.size(); i++) { @@ -746,5 +748,13 @@ public class UnitGroup { super.setDefaultUnit(n); UNITS_STABILITY.setDefaultUnit(n); } + + /** + * Returns the percentage of length unit. (Stability in %) + * @return the percentage of length unit. + */ + public Unit getPercentageOfLengthUnit() { + return this.percentageOfLengthUnit; + } } } diff --git a/swing/src/net/sf/openrocket/gui/figureelements/RocketInfo.java b/swing/src/net/sf/openrocket/gui/figureelements/RocketInfo.java index 64c120c19..baf9b831a 100644 --- a/swing/src/net/sf/openrocket/gui/figureelements/RocketInfo.java +++ b/swing/src/net/sf/openrocket/gui/figureelements/RocketInfo.java @@ -41,7 +41,7 @@ public class RocketInfo implements FigureElement { private final Caret cpCaret = new CPCaret(0,0); private final Caret cgCaret = new CGCaret(0,0); - private UnitGroup stabilityUnits; + private UnitGroup.StabilityUnitGroup stabilityUnits; private FlightConfiguration configuration; private double cg = 0, cp = 0; @@ -201,7 +201,7 @@ public class RocketInfo implements FigureElement { GlyphVector cgValue = createText(getCg()); GlyphVector cpValue = createText(getCp()); - GlyphVector stabValue = createText(getStability()); + GlyphVector stabValue = createText(getStabilityCombined()); //// CG: GlyphVector cgText = createText(trans.get("RocketInfo.cgText")); @@ -276,16 +276,47 @@ public class RocketInfo implements FigureElement { public String getMassWithMotors(Unit u) { return u.toStringUnit(massWithMotors); } - + + /** - * Get the stability, in calibers. + * Get the stability in both the selected stability unit and in percentage, e.g. "2.4 cal (14.1 %)". + * If the current unit is already the percentage length unit, only use that. * - * @return the current stability margin + * @return the current stability margin in the currently selected stability unit and in percentage */ - public String getStability () { - return stabilityUnits.getDefaultUnit().toStringUnit(cp-cg); + public String getStabilityCombined() { + Unit defaultUnit = stabilityUnits.getDefaultUnit(); + String stability = getStability(); + + if (Double.isNaN(getStabilityValue()) || defaultUnit == stabilityUnits.getPercentageOfLengthUnit()) { + return stability; + } + + String stabilityPercentage = getStabilityPercentage(); + + return stability + " (" + stabilityPercentage + ")"; } + /** + * Get the stability in the currently selected unit. + * @return the current stability margin in the currently selected stability unit + */ + private String getStability() { + return stabilityUnits.getDefaultUnit().toStringUnit(getStabilityValue()); + } + + /** + * Get the stability in the percentage length unit. + * @return the current stability margin in the percentage length unit + */ + private String getStabilityPercentage() { + return stabilityUnits.getPercentageOfLengthUnit().toStringUnit(getStabilityValue()); + } + + private double getStabilityValue() { + return cp - cg; + } + /** * Get the center of pressure in default length units. * diff --git a/swing/src/net/sf/openrocket/gui/print/DesignReport.java b/swing/src/net/sf/openrocket/gui/print/DesignReport.java index cb281336e..4483ebb1d 100644 --- a/swing/src/net/sf/openrocket/gui/print/DesignReport.java +++ b/swing/src/net/sf/openrocket/gui/print/DesignReport.java @@ -256,7 +256,7 @@ public class DesignReport { canvas.showText(text.getMassWithMotors(UnitGroup.UNITS_MASS.getDefaultUnit())); canvas.newlineShowText(STABILITY); - canvas.showText(text.getStability()); + canvas.showText(text.getStabilityCombined()); canvas.newlineShowText(CG); canvas.showText(text.getCg()); From 57469e940ee42e2099ca99980c98df68291c29c6 Mon Sep 17 00:00:00 2001 From: SiboVG Date: Wed, 24 May 2023 01:51:54 +0200 Subject: [PATCH 2/5] Refactor --- .../gui/figureelements/RocketInfo.java | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/swing/src/net/sf/openrocket/gui/figureelements/RocketInfo.java b/swing/src/net/sf/openrocket/gui/figureelements/RocketInfo.java index baf9b831a..118ddfbf1 100644 --- a/swing/src/net/sf/openrocket/gui/figureelements/RocketInfo.java +++ b/swing/src/net/sf/openrocket/gui/figureelements/RocketInfo.java @@ -189,16 +189,6 @@ public class RocketInfo implements FigureElement { private void drawStabilityInfo() { - String at; - //// at M= - at = trans.get("RocketInfo.at")+UnitGroup.UNITS_COEFFICIENT.getDefaultUnit().toStringUnit(this.mach); - if (!Double.isNaN(aoa)) { - at += " "+ALPHA+"=" + UnitGroup.UNITS_ANGLE.getDefaultUnit().toStringUnit(aoa); - } - if (!Double.isNaN(theta)) { - at += " "+THETA+"=" + UnitGroup.UNITS_ANGLE.getDefaultUnit().toStringUnit(theta); - } - GlyphVector cgValue = createText(getCg()); GlyphVector cpValue = createText(getCp()); GlyphVector stabValue = createText(getStabilityCombined()); @@ -209,6 +199,15 @@ public class RocketInfo implements FigureElement { GlyphVector cpText = createText(trans.get("RocketInfo.cpText")); //// Stability: GlyphVector stabText = createText(trans.get("RocketInfo.stabText")); + + //// at M=... + String at = trans.get("RocketInfo.at")+UnitGroup.UNITS_COEFFICIENT.getDefaultUnit().toStringUnit(this.mach); + if (!Double.isNaN(aoa)) { + at += " "+ALPHA+"=" + UnitGroup.UNITS_ANGLE.getDefaultUnit().toStringUnit(aoa); + } + if (!Double.isNaN(theta)) { + at += " "+THETA+"=" + UnitGroup.UNITS_ANGLE.getDefaultUnit().toStringUnit(theta); + } GlyphVector atText = createSmallText(at); // GlyphVector visual bounds drops the spaces, so we'll add them From a7124ec5d7998f32585359b44091434791a2eca1 Mon Sep 17 00:00:00 2001 From: SiboVG Date: Mon, 29 May 2023 11:48:08 +0200 Subject: [PATCH 3/5] Refactor widgets in separate panels --- .../preferences/UnitsPreferencesPanel.java | 163 +++++++++--------- 1 file changed, 82 insertions(+), 81 deletions(-) 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 3b561e04f..013e1ada2 100644 --- a/swing/src/net/sf/openrocket/gui/dialogs/preferences/UnitsPreferencesPanel.java +++ b/swing/src/net/sf/openrocket/gui/dialogs/preferences/UnitsPreferencesPanel.java @@ -8,6 +8,7 @@ import javax.swing.JButton; import javax.swing.JComboBox; import javax.swing.JDialog; import javax.swing.JLabel; +import javax.swing.JPanel; import net.miginfocom.swing.MigLayout; import net.sf.openrocket.gui.components.StyledLabel; @@ -18,122 +19,122 @@ import net.sf.openrocket.gui.widgets.SelectColorButton; public class UnitsPreferencesPanel extends PreferencesPanel { public UnitsPreferencesPanel(JDialog parent) { - super(parent, new MigLayout("", "[][]40lp[][]")); + super(parent, new MigLayout("", "[]40lp[]")); JComboBox combo; + JPanel leftPanel = new JPanel(new MigLayout("ins 0")); + JPanel rightPanel = new JPanel(new MigLayout("ins 0")); //// Select your preferred units: this.add(new JLabel(trans.get("pref.dlg.lbl.Selectprefunits")), "span, wrap paragraph"); - + + + // -------------- LEFT PANEL //// Rocket dimensions: - this.add(new JLabel(trans.get("pref.dlg.lbl.Rocketdimensions"))); + leftPanel.add(new JLabel(trans.get("pref.dlg.lbl.Rocketdimensions"))); combo = new JComboBox(new DefaultUnitSelector(UnitGroup.UNITS_LENGTH)); - this.add(combo, "sizegroup boxes"); - - //// Line density: - this.add(new JLabel(trans.get("pref.dlg.lbl.Linedensity"))); - combo = new JComboBox(new DefaultUnitSelector(UnitGroup.UNITS_DENSITY_LINE)); - this.add(combo, "sizegroup boxes, wrap"); - + leftPanel.add(combo, "sizegroup boxes, wrap"); //// Motor dimensions: - this.add(new JLabel(trans.get("pref.dlg.lbl.Motordimensions"))); + leftPanel.add(new JLabel(trans.get("pref.dlg.lbl.Motordimensions"))); combo = new JComboBox(new DefaultUnitSelector(UnitGroup.UNITS_MOTOR_DIMENSIONS)); - this.add(combo, "sizegroup boxes"); - - //// Surface density: - this.add(new JLabel(trans.get("pref.dlg.lbl.Surfacedensity"))); - combo = new JComboBox(new DefaultUnitSelector(UnitGroup.UNITS_DENSITY_SURFACE)); - this.add(combo, "sizegroup boxes, wrap"); - + leftPanel.add(combo, "sizegroup boxes, wrap"); //// Distance: - this.add(new JLabel(trans.get("pref.dlg.lbl.Distance"))); + leftPanel.add(new JLabel(trans.get("pref.dlg.lbl.Distance"))); combo = new JComboBox(new DefaultUnitSelector(UnitGroup.UNITS_DISTANCE)); - this.add(combo, "sizegroup boxes"); - - //// Bulk density:: - this.add(new JLabel(trans.get("pref.dlg.lbl.Bulkdensity"))); - combo = new JComboBox(new DefaultUnitSelector(UnitGroup.UNITS_DENSITY_BULK)); - this.add(combo, "sizegroup boxes, wrap"); - + leftPanel.add(combo, "sizegroup boxes, wrap"); //// Velocity: - this.add(new JLabel(trans.get("pref.dlg.lbl.Velocity"))); + leftPanel.add(new JLabel(trans.get("pref.dlg.lbl.Velocity"))); combo = new JComboBox(new DefaultUnitSelector(UnitGroup.UNITS_VELOCITY)); - this.add(combo, "sizegroup boxes"); - - //// Surface roughness: - this.add(new JLabel(trans.get("pref.dlg.lbl.Surfaceroughness"))); - combo = new JComboBox(new DefaultUnitSelector(UnitGroup.UNITS_ROUGHNESS)); - this.add(combo, "sizegroup boxes, wrap"); - + leftPanel.add(combo, "sizegroup boxes, wrap"); //// Acceleration: - this.add(new JLabel(trans.get("pref.dlg.lbl.Acceleration"))); + leftPanel.add(new JLabel(trans.get("pref.dlg.lbl.Acceleration"))); combo = new JComboBox(new DefaultUnitSelector(UnitGroup.UNITS_ACCELERATION)); - this.add(combo, "sizegroup boxes"); - - //// Area: - this.add(new JLabel(trans.get("pref.dlg.lbl.Area"))); - combo = new JComboBox(new DefaultUnitSelector(UnitGroup.UNITS_AREA)); - this.add(combo, "sizegroup boxes, wrap"); - + leftPanel.add(combo, "sizegroup boxes, wrap"); //// Mass: - this.add(new JLabel(trans.get("pref.dlg.lbl.Mass"))); + leftPanel.add(new JLabel(trans.get("pref.dlg.lbl.Mass"))); combo = new JComboBox(new DefaultUnitSelector(UnitGroup.UNITS_MASS)); - this.add(combo, "sizegroup boxes"); - - //// Angle: - this.add(new JLabel(trans.get("pref.dlg.lbl.Angle"))); - combo = new JComboBox(new DefaultUnitSelector(UnitGroup.UNITS_ANGLE)); - this.add(combo, "sizegroup boxes, wrap"); - + leftPanel.add(combo, "sizegroup boxes, wrap"); //// Force: - this.add(new JLabel(trans.get("pref.dlg.lbl.Force"))); + leftPanel.add(new JLabel(trans.get("pref.dlg.lbl.Force"))); combo = new JComboBox(new DefaultUnitSelector(UnitGroup.UNITS_FORCE)); - this.add(combo, "sizegroup boxes"); - - //// Roll rate: - this.add(new JLabel(trans.get("pref.dlg.lbl.Rollrate"))); - combo = new JComboBox(new DefaultUnitSelector(UnitGroup.UNITS_ROLL)); - this.add(combo, "sizegroup boxes, wrap"); - + leftPanel.add(combo, "sizegroup boxes, wrap"); //// Total impulse: - this.add(new JLabel(trans.get("pref.dlg.lbl.Totalimpulse"))); + leftPanel.add(new JLabel(trans.get("pref.dlg.lbl.Totalimpulse"))); combo = new JComboBox(new DefaultUnitSelector(UnitGroup.UNITS_IMPULSE)); - this.add(combo, "sizegroup boxes"); - - //// Temperature: - this.add(new JLabel(trans.get("pref.dlg.lbl.Temperature"))); - combo = new JComboBox(new DefaultUnitSelector(UnitGroup.UNITS_TEMPERATURE)); - this.add(combo, "sizegroup boxes, wrap"); + leftPanel.add(combo, "sizegroup boxes, wrap"); //// Moment of inertia: - this.add(new JLabel(trans.get("pref.dlg.lbl.Momentofinertia"))); + leftPanel.add(new JLabel(trans.get("pref.dlg.lbl.Momentofinertia"))); combo = new JComboBox(new DefaultUnitSelector(UnitGroup.UNITS_INERTIA)); - this.add(combo, "sizegroup boxes"); - - //// Pressure: - this.add(new JLabel(trans.get("pref.dlg.lbl.Pressure"))); - combo = new JComboBox(new DefaultUnitSelector(UnitGroup.UNITS_PRESSURE)); - this.add(combo, "sizegroup boxes, wrap"); - + leftPanel.add(combo, "sizegroup boxes, wrap"); //// Stability: - this.add(new JLabel(trans.get("pref.dlg.lbl.Stability"))); + leftPanel.add(new JLabel(trans.get("pref.dlg.lbl.Stability"))); combo = new JComboBox(new DefaultUnitSelector(UnitGroup.UNITS_STABILITY)); - this.add(combo, "sizegroup boxes"); - + leftPanel.add(combo, "sizegroup boxes, wrap"); + + + // -------------- RIGHT PANEL + + //// Line density: + rightPanel.add(new JLabel(trans.get("pref.dlg.lbl.Linedensity"))); + combo = new JComboBox(new DefaultUnitSelector(UnitGroup.UNITS_DENSITY_LINE)); + rightPanel.add(combo, "sizegroup boxes, wrap"); + + //// Surface density: + rightPanel.add(new JLabel(trans.get("pref.dlg.lbl.Surfacedensity"))); + combo = new JComboBox(new DefaultUnitSelector(UnitGroup.UNITS_DENSITY_SURFACE)); + rightPanel.add(combo, "sizegroup boxes, wrap"); + + //// Bulk density:: + rightPanel.add(new JLabel(trans.get("pref.dlg.lbl.Bulkdensity"))); + combo = new JComboBox(new DefaultUnitSelector(UnitGroup.UNITS_DENSITY_BULK)); + rightPanel.add(combo, "sizegroup boxes, wrap"); + + //// Surface roughness: + rightPanel.add(new JLabel(trans.get("pref.dlg.lbl.Surfaceroughness"))); + combo = new JComboBox(new DefaultUnitSelector(UnitGroup.UNITS_ROUGHNESS)); + rightPanel.add(combo, "sizegroup boxes, wrap"); + + //// Area: + rightPanel.add(new JLabel(trans.get("pref.dlg.lbl.Area"))); + combo = new JComboBox(new DefaultUnitSelector(UnitGroup.UNITS_AREA)); + rightPanel.add(combo, "sizegroup boxes, wrap"); + + //// Angle: + rightPanel.add(new JLabel(trans.get("pref.dlg.lbl.Angle"))); + combo = new JComboBox(new DefaultUnitSelector(UnitGroup.UNITS_ANGLE)); + rightPanel.add(combo, "sizegroup boxes, wrap"); + + //// Roll rate: + rightPanel.add(new JLabel(trans.get("pref.dlg.lbl.Rollrate"))); + combo = new JComboBox(new DefaultUnitSelector(UnitGroup.UNITS_ROLL)); + rightPanel.add(combo, "sizegroup boxes, wrap"); + + //// Temperature: + rightPanel.add(new JLabel(trans.get("pref.dlg.lbl.Temperature"))); + combo = new JComboBox(new DefaultUnitSelector(UnitGroup.UNITS_TEMPERATURE)); + rightPanel.add(combo, "sizegroup boxes, wrap"); + + //// Pressure: + rightPanel.add(new JLabel(trans.get("pref.dlg.lbl.Pressure"))); + combo = new JComboBox(new DefaultUnitSelector(UnitGroup.UNITS_PRESSURE)); + rightPanel.add(combo, "sizegroup boxes, wrap"); + //// Windspeed: - this.add(new JLabel(trans.get("pref.dlg.lbl.Windspeed"))); + rightPanel.add(new JLabel(trans.get("pref.dlg.lbl.Windspeed"))); combo = new JComboBox(new DefaultUnitSelector(UnitGroup.UNITS_WINDSPEED)); - this.add(combo, "sizegroup boxes, wrap para"); - - + rightPanel.add(combo, "sizegroup boxes, wrap"); + + this.add(leftPanel); + this.add(rightPanel, "wrap para"); //// Default metric button @@ -165,7 +166,7 @@ public class UnitsPreferencesPanel extends PreferencesPanel { trans.get("pref.dlg.lbl.effect1"), -2, Style.ITALIC), "spanx, wrap"); - } + } public UnitsPreferencesPanel(LayoutManager layout) { super(layout); From b21b7569f50e6bdc023808e19981cae0a9a842c5 Mon Sep 17 00:00:00 2001 From: SiboVG Date: Mon, 29 May 2023 12:23:19 +0200 Subject: [PATCH 4/5] Refactor preference keys Yes, will break compatibility, but it's just one checkbox. Too bad. --- core/src/net/sf/openrocket/startup/Preferences.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/core/src/net/sf/openrocket/startup/Preferences.java b/core/src/net/sf/openrocket/startup/Preferences.java index 0830222ae..52508731f 100644 --- a/core/src/net/sf/openrocket/startup/Preferences.java +++ b/core/src/net/sf/openrocket/startup/Preferences.java @@ -79,10 +79,10 @@ public abstract class Preferences implements ChangeSource { private static final String OPEN_LEFTMOST_DESIGN_TAB = "OpenLeftmostDesignTab"; private static final String SHOW_DISCARD_CONFIRMATION = "IgnoreDiscardEditingWarning"; private static final String SHOW_DISCARD_SIMULATION_CONFIRMATION = "IgnoreDiscardSimulationEditingWarning"; - public static final String MARKER_STYLE_ICON = "MARKER_STYLE_ICON"; - private static final String SHOW_MARKERS = "SHOW_MARKERS"; - private static final String SHOW_RASAERO_FORMAT_WARNING = "SHOW_RASAERO_FORMAT_WARNING"; - private static final String SHOW_ROCKSIM_FORMAT_WARNING = "SHOW_ROCKSIM_FORMAT_WARNING"; + public static final String MARKER_STYLE_ICON = "MarkerStyleIcon"; + private static final String SHOW_MARKERS = "ShowMarkers"; + private static final String SHOW_RASAERO_FORMAT_WARNING = "ShowRASAeroFormatWarning"; + private static final String SHOW_ROCKSIM_FORMAT_WARNING = "ShowRockSimFormatWarning"; private static final String EXPORT_USER_DIRECTORIES = "ExportUserDirectories"; private static final String EXPORT_WINDOW_INFORMATION = "ExportWindowInformation"; From 5e717e443d697803c35da636e0c4fc079a88678e Mon Sep 17 00:00:00 2001 From: SiboVG Date: Mon, 29 May 2023 15:24:36 +0200 Subject: [PATCH 5/5] Add secondary stability unit in preferences --- core/resources/l10n/messages.properties | 4 + .../sf/openrocket/startup/Preferences.java | 25 ++++++ .../src/net/sf/openrocket/unit/UnitGroup.java | 85 +++++++++++++++---- .../preferences/UnitsPreferencesPanel.java | 33 ++++++- .../gui/figureelements/RocketInfo.java | 30 ++++--- 5 files changed, 146 insertions(+), 31 deletions(-) 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); } }