From 94c2c1ef38e40fd12a6393650a40fc997fa40b34 Mon Sep 17 00:00:00 2001 From: SiboVG Date: Wed, 15 Nov 2023 04:41:31 +0100 Subject: [PATCH] Major refactor of simulation options UI --- .../simulation/SimulationOptions.java | 32 +- .../SimulationOptionsInterface.java | 77 ++ .../sf/openrocket/startup/Preferences.java | 4 +- .../preferences/LaunchPreferencesPanel.java | 468 +--------- .../simulation/SimulationConditionsPanel.java | 818 +++++++++--------- .../openrocket/gui/util/SwingPreferences.java | 3 +- 6 files changed, 511 insertions(+), 891 deletions(-) create mode 100644 core/src/net/sf/openrocket/simulation/SimulationOptionsInterface.java diff --git a/core/src/net/sf/openrocket/simulation/SimulationOptions.java b/core/src/net/sf/openrocket/simulation/SimulationOptions.java index d11759332..dfcee63c3 100644 --- a/core/src/net/sf/openrocket/simulation/SimulationOptions.java +++ b/core/src/net/sf/openrocket/simulation/SimulationOptions.java @@ -32,7 +32,7 @@ import net.sf.openrocket.util.WorldCoordinate; * * @author Sampo Niskanen */ -public class SimulationOptions implements ChangeSource, Cloneable { +public class SimulationOptions implements ChangeSource, Cloneable, SimulationOptionsInterface { @SuppressWarnings("unused") private static final Logger log = LoggerFactory.getLogger(SimulationOptions.class); @@ -71,7 +71,7 @@ public class SimulationOptions implements ChangeSource, Cloneable { private double launchLongitude = preferences.getLaunchLongitude(); private GeodeticComputationStrategy geodeticComputation = GeodeticComputationStrategy.SPHERICAL; - private boolean useISA = preferences.getISAAtmosphere(); + private boolean useISA = preferences.isISAAtmosphere(); private double launchTemperature = preferences.getLaunchTemperature(); // In Kelvin private double launchPressure = preferences.getLaunchPressure(); // In Pascal @@ -161,34 +161,17 @@ public class SimulationOptions implements ChangeSource, Cloneable { setWindTurbulenceIntensity(windDeviation / windAverage); } - - /** - * Return the wind turbulence intensity (standard deviation / average). - * - * @return the turbulence intensity - */ + public double getWindTurbulenceIntensity() { return windTurbulence; } - - /** - * Set the wind standard deviation to match the given turbulence intensity. - * - * @param intensity the turbulence intensity - */ + public void setWindTurbulenceIntensity(double intensity) { // Does not check equality so that setWindSpeedDeviation can be sure of event firing this.windTurbulence = intensity; fireChangeEvent(); } - - - /** - * Set the wind direction - * - * @param direction the wind direction - */ - + public void setWindDirection(double direction) { direction = MathUtil.reduce2Pi(direction); if (launchIntoWind) { @@ -312,11 +295,12 @@ public class SimulationOptions implements ChangeSource, Cloneable { fireChangeEvent(); } - + + /** * Returns an atmospheric model corresponding to the launch conditions. The * atmospheric models may be shared between different calls. - * + * * @return an AtmosphericModel object. */ private AtmosphericModel getAtmosphericModel() { diff --git a/core/src/net/sf/openrocket/simulation/SimulationOptionsInterface.java b/core/src/net/sf/openrocket/simulation/SimulationOptionsInterface.java new file mode 100644 index 000000000..418c9dad5 --- /dev/null +++ b/core/src/net/sf/openrocket/simulation/SimulationOptionsInterface.java @@ -0,0 +1,77 @@ +package net.sf.openrocket.simulation; + +import net.sf.openrocket.util.ChangeSource; +import net.sf.openrocket.util.GeodeticComputationStrategy; + +public interface SimulationOptionsInterface extends ChangeSource { + double getLaunchRodLength(); + + void setLaunchRodLength(double launchRodLength); + + boolean getLaunchIntoWind(); + + void setLaunchIntoWind(boolean i); + + double getLaunchRodAngle(); + + void setLaunchRodAngle(double launchRodAngle); + + double getLaunchRodDirection(); + + void setLaunchRodDirection(double launchRodDirection); + + double getWindSpeedAverage(); + + void setWindSpeedAverage(double windAverage); + + double getWindSpeedDeviation(); + + void setWindSpeedDeviation(double windDeviation); + + /** + * Return the wind turbulence intensity (standard deviation / average). + * + * @return the turbulence intensity + */ + double getWindTurbulenceIntensity(); + + /** + * Set the wind standard deviation to match the given turbulence intensity. + * + * @param intensity the turbulence intensity + */ + void setWindTurbulenceIntensity(double intensity); + + void setWindDirection(double direction); + + double getWindDirection(); + + double getLaunchAltitude(); + + void setLaunchAltitude(double altitude); + + double getLaunchLatitude(); + + void setLaunchLatitude(double launchLatitude); + + double getLaunchLongitude(); + + void setLaunchLongitude(double launchLongitude); + + GeodeticComputationStrategy getGeodeticComputation(); + + void setGeodeticComputation(GeodeticComputationStrategy geodeticComputation); + + boolean isISAAtmosphere(); + + void setISAAtmosphere(boolean isa); + + double getLaunchTemperature(); + + void setLaunchTemperature(double launchTemperature); + + double getLaunchPressure(); + + void setLaunchPressure(double launchPressure); + +} diff --git a/core/src/net/sf/openrocket/startup/Preferences.java b/core/src/net/sf/openrocket/startup/Preferences.java index 7f46a85a5..2c0011832 100644 --- a/core/src/net/sf/openrocket/startup/Preferences.java +++ b/core/src/net/sf/openrocket/startup/Preferences.java @@ -428,7 +428,7 @@ public abstract class Preferences implements ChangeSource { this.putDouble(LAUNCH_ALTITUDE, altitude); // Update the launch temperature and pressure if using ISA - if (getISAAtmosphere()) { + if (isISAAtmosphere()) { setLaunchTemperature(ISA_ATMOSPHERIC_MODEL.getConditions(getLaunchAltitude()).getTemperature()); setLaunchPressure(ISA_ATMOSPHERIC_MODEL.getConditions(getLaunchAltitude()).getPressure()); } @@ -518,7 +518,7 @@ public abstract class Preferences implements ChangeSource { } - public boolean getISAAtmosphere() { + public boolean isISAAtmosphere() { return this.getBoolean(LAUNCH_USE_ISA, true); } diff --git a/swing/src/net/sf/openrocket/gui/dialogs/preferences/LaunchPreferencesPanel.java b/swing/src/net/sf/openrocket/gui/dialogs/preferences/LaunchPreferencesPanel.java index 50b5d97f7..0443c1b8a 100644 --- a/swing/src/net/sf/openrocket/gui/dialogs/preferences/LaunchPreferencesPanel.java +++ b/swing/src/net/sf/openrocket/gui/dialogs/preferences/LaunchPreferencesPanel.java @@ -2,35 +2,13 @@ package net.sf.openrocket.gui.dialogs.preferences; import java.awt.Color; import java.awt.LayoutManager; -import java.awt.event.KeyAdapter; -import java.awt.event.KeyEvent; -import java.util.EventObject; - -import javax.swing.BorderFactory; -import javax.swing.JCheckBox; import javax.swing.JDialog; -import javax.swing.JLabel; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JSpinner; -import javax.swing.JTextField; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; import net.miginfocom.swing.MigLayout; -import net.sf.openrocket.gui.SpinnerEditor; -import net.sf.openrocket.gui.adaptors.BooleanModel; -import net.sf.openrocket.gui.adaptors.DoubleModel; -import net.sf.openrocket.gui.components.BasicSlider; import net.sf.openrocket.gui.components.StyledLabel; -import net.sf.openrocket.gui.components.UnitSelector; +import net.sf.openrocket.gui.simulation.SimulationConditionsPanel; import net.sf.openrocket.gui.util.GUIUtil; import net.sf.openrocket.gui.util.UITheme; -import net.sf.openrocket.models.atmosphere.ExtendedISAModel; -import net.sf.openrocket.simulation.SimulationOptions; -import net.sf.openrocket.unit.UnitGroup; -import net.sf.openrocket.util.Chars; -import net.sf.openrocket.util.StateChangeListener; public class LaunchPreferencesPanel extends PreferencesPanel { private static Color darkWarningColor; @@ -55,406 +33,8 @@ public class LaunchPreferencesPanel extends PreferencesPanel { warning.setToolTipText(trans.get("pref.dlg.lbl.launchWarning.ttip")); add(warning, "spanx, growx 0, gapbottom para, wrap"); - JPanel sub; - String tip; - UnitSelector unit; - BasicSlider slider; - DoubleModel m; - DoubleModel temperatureModel; - DoubleModel pressureModel; - JSpinner spin; - - // Wind settings: Average wind speed, turbulence intensity, std. - // deviation, and direction - sub = new JPanel(new MigLayout("fill, gap rel unrel", - "[grow][65lp!][30lp!][75lp!]", "")); - // Wind - sub.setBorder(BorderFactory.createTitledBorder(trans - .get("simedtdlg.lbl.Wind"))); - this.add(sub, "growx, split 2, aligny 0, flowy, gapright para"); - - // Wind average - // Average windspeed: - JLabel label = new JLabel(trans.get("simedtdlg.lbl.Averwindspeed")); - // The average windspeed relative to the ground. - tip = trans.get("simedtdlg.lbl.ttip.Averwindspeed"); - label.setToolTipText(tip); - sub.add(label); - - m = new DoubleModel(preferences, "WindSpeedAverage", - UnitGroup.UNITS_WINDSPEED, 0); - - spin = new JSpinner(m.getSpinnerModel()); - spin.setEditor(new SpinnerEditor(spin)); - spin.setToolTipText(tip); - addEasterEgg(spin); - sub.add(spin, "w 65lp!"); - - unit = new UnitSelector(m); - unit.setToolTipText(tip); - sub.add(unit, "growx"); - slider = new BasicSlider(m.getSliderModel(0, 10.0)); - slider.setToolTipText(tip); - sub.add(slider, "w 75lp, wrap"); - - // Wind std. deviation - // // Standard deviation: - label = new JLabel(trans.get("simedtdlg.lbl.Stddeviation")); - // // The standard deviation of the windspeed.
- // // The windspeed is within twice the standard deviation from the - // average for 95% of the time. - tip = trans.get("simedtdlg.lbl.ttip.Stddeviation"); - label.setToolTipText(tip); - sub.add(label); - - m = new DoubleModel(preferences, "WindSpeedDeviation", - UnitGroup.UNITS_WINDSPEED, 0); - DoubleModel m2 = new DoubleModel(preferences, "WindSpeedAverage", 0.25, - UnitGroup.UNITS_COEFFICIENT, 0); - - spin = new JSpinner(m.getSpinnerModel()); - spin.setEditor(new SpinnerEditor(spin)); - spin.setToolTipText(tip); - sub.add(spin, "w 65lp!"); - - unit = new UnitSelector(m); - unit.setToolTipText(tip); - sub.add(unit, "growx"); - slider = new BasicSlider(m.getSliderModel(new DoubleModel(0), m2)); - slider.setToolTipText(tip); - sub.add(slider, "w 75lp, wrap"); - - - // Wind turbulence intensity - // // Turbulence intensity: - label = new JLabel(trans.get("simedtdlg.lbl.Turbulenceintensity")); - // // The turbulence intensity is the standard deviation divided - // by the average windspeed.
- // // Typical values range from - // // to - tip = trans.get("simedtdlg.lbl.ttip.Turbulenceintensity1") - + trans.get("simedtdlg.lbl.ttip.Turbulenceintensity2") + " " - + UnitGroup.UNITS_RELATIVE.getDefaultUnit().toStringUnit(0.05) - + " " + trans.get("simedtdlg.lbl.ttip.Turbulenceintensity3") - + " " - + UnitGroup.UNITS_RELATIVE.getDefaultUnit().toStringUnit(0.20) - + "."; - label.setToolTipText(tip); - sub.add(label); - - m = new DoubleModel(preferences, "WindTurbulenceIntensity", - UnitGroup.UNITS_RELATIVE, 0); - - spin = new JSpinner(m.getSpinnerModel()); - spin.setEditor(new SpinnerEditor(spin)); - spin.setToolTipText(tip); - sub.add(spin, "w 65lp!"); - - unit = new UnitSelector(m); - unit.setToolTipText(tip); - sub.add(unit, "growx"); - - final JLabel intensityLabel = new JLabel( - getIntensityDescription(preferences - .getWindTurbulenceIntensity())); - intensityLabel.setToolTipText(tip); - sub.add(intensityLabel, "w 75lp, wrap"); - m.addChangeListener(new ChangeListener() { - @Override - public void stateChanged(ChangeEvent e) { - intensityLabel.setText(getIntensityDescription(preferences - .getWindTurbulenceIntensity())); - } - }); - - // Wind Direction: - label = new JLabel(trans.get("simedtdlg.lbl.Winddirection")); - // // Direction of the wind. 0 is north - tip = trans.get("simedtdlg.lbl.ttip.Winddirection"); - label.setToolTipText(tip); - sub.add(label); - - m = new DoubleModel(preferences, "WindDirection", 1.0, - UnitGroup.UNITS_ANGLE, 0, 2 * Math.PI); - - spin = new JSpinner(m.getSpinnerModel()); - spin.setEditor(new SpinnerEditor(spin)); - spin.setToolTipText(tip); - sub.add(spin, "w 65lp!"); - - unit = new UnitSelector(m); - unit.setToolTipText(tip); - sub.add(unit, "growx"); - slider = new BasicSlider(m.getSliderModel(0, 2 * Math.PI)); - slider.setToolTipText(tip); - sub.add(slider, "w 75lp, wrap"); - - // // Temperature and pressure - sub = new JPanel(new MigLayout("fill, gap rel unrel", - "[grow][75lp!][35lp!][75lp!]", "")); - // // Atmospheric preferences - sub.setBorder(BorderFactory.createTitledBorder(trans - .get("simedtdlg.border.Atmoscond"))); - this.add(sub, "growx, aligny 0, gapright para"); - - BooleanModel isa = new BooleanModel(preferences, "ISAAtmosphere"); - JCheckBox check = new JCheckBox(isa); - // // Use International Standard Atmosphere - check.setText(trans.get("simedtdlg.checkbox.InterStdAtmosphere")); - // // Select to use the International Standard Atmosphere model. - // //
This model has a temperature of - // // and a pressure of - // // at sea level. - check.setToolTipText(trans - .get("simedtdlg.checkbox.ttip.InterStdAtmosphere1") - + " " - + UnitGroup.UNITS_TEMPERATURE - .toStringUnit(ExtendedISAModel.STANDARD_TEMPERATURE) - + " " - + trans.get("simedtdlg.checkbox.ttip.InterStdAtmosphere2") - + " " - + UnitGroup.UNITS_PRESSURE - .toStringUnit(ExtendedISAModel.STANDARD_PRESSURE) - + " " - + trans.get("simedtdlg.checkbox.ttip.InterStdAtmosphere3")); - sub.add(check, "spanx, wrap unrel"); - - // Temperature: - label = new JLabel(trans.get("simedtdlg.lbl.Temperature")); - // // The temperature at the launch site. - tip = trans.get("simedtdlg.lbl.ttip.Temperature"); - label.setToolTipText(tip); - isa.addEnableComponent(label, false); - sub.add(label); - - temperatureModel = new DoubleModel(preferences, "LaunchTemperature", - UnitGroup.UNITS_TEMPERATURE, 0); - - spin = new JSpinner(temperatureModel.getSpinnerModel()); - spin.setEditor(new SpinnerEditor(spin)); - spin.setToolTipText(tip); - isa.addEnableComponent(spin, false); - sub.add(spin, "growx"); - - unit = new UnitSelector(temperatureModel); - unit.setToolTipText(tip); - isa.addEnableComponent(unit, false); - sub.add(unit, "growx"); - slider = new BasicSlider(temperatureModel.getSliderModel(253.15, 308.15)); // -20 ... - // 35 - slider.setToolTipText(tip); - isa.addEnableComponent(slider, false); - sub.add(slider, "w 75lp, wrap"); - - // Pressure: - label = new JLabel(trans.get("simedtdlg.lbl.Pressure")); - // // The atmospheric pressure at the launch site. - tip = trans.get("simedtdlg.lbl.ttip.Pressure"); - label.setToolTipText(tip); - isa.addEnableComponent(label, false); - sub.add(label); - - pressureModel = new DoubleModel(preferences, "LaunchPressure", - UnitGroup.UNITS_PRESSURE, 0); - - spin = new JSpinner(pressureModel.getSpinnerModel()); - spin.setEditor(new SpinnerEditor(spin)); - spin.setToolTipText(tip); - isa.addEnableComponent(spin, false); - sub.add(spin, "growx"); - - unit = new UnitSelector(pressureModel); - unit.setToolTipText(tip); - isa.addEnableComponent(unit, false); - sub.add(unit, "growx"); - slider = new BasicSlider(pressureModel.getSliderModel(0.950e5, 1.050e5)); - slider.setToolTipText(tip); - isa.addEnableComponent(slider, false); - sub.add(slider, "w 75lp, wrap"); - - isa.addChangeListener(new StateChangeListener() { - @Override - public void stateChanged(EventObject e) { - temperatureModel.stateChanged(e); - pressureModel.stateChanged(e); - } - }); - - - // // Launch site preferences - sub = new JPanel(new MigLayout("fill, gap rel unrel", - "[grow][65lp!][30lp!][75lp!]", "")); - // // Launch site - sub.setBorder(BorderFactory.createTitledBorder(trans - .get("simedtdlg.lbl.Launchsite"))); - this.add(sub, "growx, split 2, aligny 0, flowy"); - - // Latitude: - label = new JLabel(trans.get("simedtdlg.lbl.Latitude")); - // // The launch site latitude affects the gravitational pull of - // Earth.
- // // Positive values are on the Northern hemisphere, negative values on - // the Southern hemisphere. - tip = trans.get("simedtdlg.lbl.ttip.Latitude"); - label.setToolTipText(tip); - sub.add(label); - - m = new DoubleModel(preferences, "LaunchLatitude", - UnitGroup.UNITS_NONE, -90, 90); - - spin = new JSpinner(m.getSpinnerModel()); - spin.setEditor(new SpinnerEditor(spin)); - spin.setToolTipText(tip); - sub.add(spin, "growx"); - - label = new JLabel(Chars.DEGREE + " " + trans.get("CompassRose.lbl.north")); - label.setToolTipText(tip); - sub.add(label, "growx"); - slider = new BasicSlider(m.getSliderModel(-90, 90)); - slider.setToolTipText(tip); - sub.add(slider, "w 75lp, wrap"); - - // Longitude: - label = new JLabel(trans.get("simedtdlg.lbl.Longitude")); - tip = trans.get("simedtdlg.lbl.ttip.Longitude"); - label.setToolTipText(tip); - sub.add(label); - - m = new DoubleModel(preferences, "LaunchLongitude", - UnitGroup.UNITS_NONE, -180, 180); - - spin = new JSpinner(m.getSpinnerModel()); - spin.setEditor(new SpinnerEditor(spin)); - spin.setToolTipText(tip); - sub.add(spin, "growx"); - - label = new JLabel(Chars.DEGREE + " " + trans.get("CompassRose.lbl.east")); - label.setToolTipText(tip); - sub.add(label, "growx"); - slider = new BasicSlider(m.getSliderModel(-180, 180)); - slider.setToolTipText(tip); - sub.add(slider, "w 75lp, wrap"); - - // Altitude: - label = new JLabel(trans.get("simedtdlg.lbl.Altitude")); - // // The launch altitude above mean sea level.
- // // This affects the position of the rocket in the atmospheric model. - tip = trans.get("simedtdlg.lbl.ttip.Altitude"); - label.setToolTipText(tip); - sub.add(label); - - m = new DoubleModel(preferences, "LaunchAltitude", - UnitGroup.UNITS_DISTANCE, 0); - - spin = new JSpinner(m.getSpinnerModel()); - spin.setEditor(new SpinnerEditor(spin)); - spin.setToolTipText(tip); - sub.add(spin, "growx"); - - unit = new UnitSelector(m); - unit.setToolTipText(tip); - sub.add(unit, "growx"); - slider = new BasicSlider(m.getSliderModel(0, 250, 1000)); - slider.setToolTipText(tip); - sub.add(slider, "w 75lp, wrap"); - - // // Launch rod - sub = new JPanel(new MigLayout("fill, gap rel unrel", - "[grow][65lp!][30lp!][75lp!]", "")); - // // Launch rod - sub.setBorder(BorderFactory.createTitledBorder(trans - .get("simedtdlg.border.Launchrod"))); - this.add(sub, "growx, aligny 0, wrap"); - - // Length: - label = new JLabel(trans.get("simedtdlg.lbl.Length")); - // // The length of the launch rod. - tip = trans.get("simedtdlg.lbl.ttip.Length"); - label.setToolTipText(tip); - sub.add(label); - - m = new DoubleModel(preferences, "LaunchRodLength", - UnitGroup.UNITS_LENGTH, 0); - - spin = new JSpinner(m.getSpinnerModel()); - spin.setEditor(new SpinnerEditor(spin)); - spin.setToolTipText(tip); - sub.add(spin, "growx"); - - unit = new UnitSelector(m); - unit.setToolTipText(tip); - sub.add(unit, "growx"); - slider = new BasicSlider(m.getSliderModel(0, 1, 5)); - slider.setToolTipText(tip); - sub.add(slider, "w 75lp, wrap"); - - // Keep launch rod parallel to the wind. - - BooleanModel intoWind = new BooleanModel(preferences, "LaunchIntoWind"); - JCheckBox checkWind = new JCheckBox(intoWind); - // // Use International Standard Atmosphere - checkWind.setText(trans.get("simedtdlg.checkbox.Intowind")); - checkWind.setToolTipText(trans.get("simedtdlg.checkbox.ttip.Intowind1") - + trans.get("simedtdlg.checkbox.ttip.Intowind2") - + trans.get("simedtdlg.checkbox.ttip.Intowind3") - + trans.get("simedtdlg.checkbox.ttip.Intowind4")); - sub.add(checkWind, "spanx, wrap unrel"); - - // Angle: - label = new JLabel(trans.get("simedtdlg.lbl.Angle")); - // // The angle of the launch rod from vertical. - tip = trans.get("simedtdlg.lbl.ttip.Angle"); - label.setToolTipText(tip); - sub.add(label); - - m = new DoubleModel(preferences, "LaunchRodAngle", - UnitGroup.UNITS_ANGLE, -SimulationOptions.MAX_LAUNCH_ROD_ANGLE, - SimulationOptions.MAX_LAUNCH_ROD_ANGLE); - - spin = new JSpinner(m.getSpinnerModel()); - spin.setEditor(new SpinnerEditor(spin)); - spin.setToolTipText(tip); - sub.add(spin, "growx"); - - unit = new UnitSelector(m); - unit.setToolTipText(tip); - sub.add(unit, "growx"); - slider = new BasicSlider(m.getSliderModel( - -SimulationOptions.MAX_LAUNCH_ROD_ANGLE, 0, - SimulationOptions.MAX_LAUNCH_ROD_ANGLE)); - slider.setToolTipText(tip); - sub.add(slider, "w 75lp, wrap"); - - // Direction: - JLabel directionLabel = new JLabel(trans.get("simedtdlg.lbl.Direction")); - // // Direction of the launch rod. - tip = trans.get("simedtdlg.lbl.ttip.Direction1") - + UnitGroup.UNITS_ANGLE.toStringUnit(0) + " " - + trans.get("simedtdlg.lbl.ttip.Direction2") + " " - + UnitGroup.UNITS_ANGLE.toStringUnit(2 * Math.PI) + " " - + trans.get("simedtdlg.lbl.ttip.Direction3"); - directionLabel.setToolTipText(tip); - sub.add(directionLabel); - - m = new DoubleModel(preferences, "LaunchRodDirection", 1.0, - UnitGroup.UNITS_ANGLE, 0, 2 * Math.PI); - - JSpinner directionSpin = new JSpinner(m.getSpinnerModel()); - directionSpin.setEditor(new SpinnerEditor(directionSpin)); - directionSpin.setToolTipText(tip); - sub.add(directionSpin, "growx"); - - unit = new UnitSelector(m); - unit.setToolTipText(tip); - sub.add(unit, "growx"); - BasicSlider directionSlider = new BasicSlider(m.getSliderModel(0, - 2 * Math.PI)); - directionSlider.setToolTipText(tip); - sub.add(directionSlider, "w 75lp, wrap"); - intoWind.addEnableComponent(directionLabel, false); - intoWind.addEnableComponent(directionSpin, false); - intoWind.addEnableComponent(unit, false); - intoWind.addEnableComponent(directionSlider, false); + // Simulation conditions + SimulationConditionsPanel.addSimulationConditionsPanel(this, preferences); } @@ -467,46 +47,4 @@ public class LaunchPreferencesPanel extends PreferencesPanel { darkWarningColor = GUIUtil.getUITheme().getDarkWarningColor(); } - private String getIntensityDescription(double i) { - if (i < 0.001) - // // None - return trans.get("simedtdlg.IntensityDesc.None"); - if (i < 0.05) - // // Very low - return trans.get("simedtdlg.IntensityDesc.Verylow"); - if (i < 0.10) - // // Low - return trans.get("simedtdlg.IntensityDesc.Low"); - if (i < 0.15) - // // Medium - return trans.get("simedtdlg.IntensityDesc.Medium"); - if (i < 0.20) - // // High - return trans.get("simedtdlg.IntensityDesc.High"); - if (i < 0.25) - // // Very high - return trans.get("simedtdlg.IntensityDesc.Veryhigh"); - // // Extreme - return trans.get("simedtdlg.IntensityDesc.Extreme"); - } - - /** - * Shh, don't tell anyone about this easter-egg. (displays a fun quote when the text of the spinner equals 42) - * @param spinner the magic spinner! - */ - private void addEasterEgg(JSpinner spinner) { - JTextField textField = ((JSpinner.DefaultEditor) spinner.getEditor()).getTextField(); - textField.addKeyListener(new KeyAdapter() { - @Override - public void keyTyped(KeyEvent e) { - String text = textField.getText() + e.getKeyChar(); - if (text.equals("42")) { - JOptionPane.showMessageDialog(LaunchPreferencesPanel.this, - "The answer to the ultimate question of life, the universe, and everything.", - "42", JOptionPane.INFORMATION_MESSAGE); - } - } - }); - } - } diff --git a/swing/src/net/sf/openrocket/gui/simulation/SimulationConditionsPanel.java b/swing/src/net/sf/openrocket/gui/simulation/SimulationConditionsPanel.java index 9d11d2010..7c1252657 100644 --- a/swing/src/net/sf/openrocket/gui/simulation/SimulationConditionsPanel.java +++ b/swing/src/net/sf/openrocket/gui/simulation/SimulationConditionsPanel.java @@ -1,15 +1,20 @@ package net.sf.openrocket.gui.simulation; +import java.awt.Component; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; import java.util.EventObject; import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JLabel; +import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JSpinner; +import javax.swing.JTextField; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; @@ -24,6 +29,7 @@ import net.sf.openrocket.l10n.Translator; import net.sf.openrocket.models.atmosphere.ExtendedISAModel; import net.sf.openrocket.simulation.DefaultSimulationOptionFactory; import net.sf.openrocket.simulation.SimulationOptions; +import net.sf.openrocket.simulation.SimulationOptionsInterface; import net.sf.openrocket.startup.Application; import net.sf.openrocket.unit.UnitGroup; import net.sf.openrocket.util.Chars; @@ -38,405 +44,11 @@ public class SimulationConditionsPanel extends JPanel { super(new MigLayout("fill")); final SimulationOptions conditions = simulation.getOptions(); - - JPanel sub; - String tip; - UnitSelector unit; - BasicSlider slider; - DoubleModel m; - JSpinner spin; - DoubleModel temperatureModel; - DoubleModel pressureModel; - - //// Wind settings: Average wind speed, turbulence intensity, std. deviation, and direction - sub = new JPanel(new MigLayout("fill, gap rel unrel", - "[grow][65lp!][30lp!][75lp!]", "")); - //// Wind - sub.setBorder(BorderFactory.createTitledBorder(trans.get("simedtdlg.lbl.Wind"))); - this.add(sub, "growx, split 2, aligny 0, flowy, gapright para"); - - - // Wind average - //// Average windspeed: - JLabel label = new JLabel(trans.get("simedtdlg.lbl.Averwindspeed")); - //// The average windspeed relative to the ground. - tip = trans.get("simedtdlg.lbl.ttip.Averwindspeed"); - label.setToolTipText(tip); - sub.add(label); - - m = new DoubleModel(conditions, "WindSpeedAverage", UnitGroup.UNITS_WINDSPEED, 0); - - spin = new JSpinner(m.getSpinnerModel()); - spin.setEditor(new SpinnerEditor(spin)); - spin.setToolTipText(tip); - sub.add(spin, "w 65lp!"); - - unit = new UnitSelector(m); - unit.setToolTipText(tip); - sub.add(unit, "growx"); - slider = new BasicSlider(m.getSliderModel(0, 10.0)); - slider.setToolTipText(tip); - sub.add(slider, "w 75lp, wrap"); - - - - // Wind std. deviation - //// Standard deviation: - label = new JLabel(trans.get("simedtdlg.lbl.Stddeviation")); - //// The standard deviation of the windspeed.
- //// The windspeed is within twice the standard deviation from the average for 95% of the time. - tip = trans.get("simedtdlg.lbl.ttip.Stddeviation"); - label.setToolTipText(tip); - sub.add(label); - - m = new DoubleModel(conditions, "WindSpeedDeviation", UnitGroup.UNITS_WINDSPEED, 0); - DoubleModel m2 = new DoubleModel(conditions, "WindSpeedAverage", 0.25, - UnitGroup.UNITS_COEFFICIENT, 0); - - spin = new JSpinner(m.getSpinnerModel()); - spin.setEditor(new SpinnerEditor(spin)); - spin.setToolTipText(tip); - sub.add(spin, "w 65lp!"); - - unit = new UnitSelector(m); - unit.setToolTipText(tip); - sub.add(unit, "growx"); - slider = new BasicSlider(m.getSliderModel(new DoubleModel(0), m2)); - slider.setToolTipText(tip); - sub.add(slider, "w 75lp, wrap"); - - - - - - // Wind turbulence intensity - //// Turbulence intensity: - label = new JLabel(trans.get("simedtdlg.lbl.Turbulenceintensity")); - //// The turbulence intensity is the standard deviation divided by the average windspeed.
- //// Typical values range from - //// to - tip = trans.get("simedtdlg.lbl.ttip.Turbulenceintensity1") + - trans.get("simedtdlg.lbl.ttip.Turbulenceintensity2") + " " + - UnitGroup.UNITS_RELATIVE.getDefaultUnit().toStringUnit(0.05) + - " " + trans.get("simedtdlg.lbl.ttip.Turbulenceintensity3") + " " + - UnitGroup.UNITS_RELATIVE.getDefaultUnit().toStringUnit(0.20) + "."; - label.setToolTipText(tip); - sub.add(label); - - m = new DoubleModel(conditions, "WindTurbulenceIntensity", UnitGroup.UNITS_RELATIVE, 0); - - spin = new JSpinner(m.getSpinnerModel()); - spin.setEditor(new SpinnerEditor(spin)); - spin.setToolTipText(tip); - sub.add(spin, "w 65lp!"); - - unit = new UnitSelector(m); - unit.setToolTipText(tip); - sub.add(unit, "growx"); - - final JLabel intensityLabel = new JLabel( - getIntensityDescription(conditions.getWindTurbulenceIntensity())); - intensityLabel.setToolTipText(tip); - sub.add(intensityLabel, "w 75lp, wrap"); - m.addChangeListener(new ChangeListener() { - @Override - public void stateChanged(ChangeEvent e) { - intensityLabel.setText( - getIntensityDescription(conditions.getWindTurbulenceIntensity())); - } - }); - - // Wind Direction: - label = new JLabel(trans.get("simedtdlg.lbl.Winddirection")); - //// Direction of the wind. 0 is north - tip = trans.get("simedtdlg.lbl.ttip.Winddirection"); - label.setToolTipText(tip); - sub.add(label); - - m = new DoubleModel(conditions, "WindDirection", 1.0, UnitGroup.UNITS_ANGLE, - 0, 2*Math.PI); - - spin = new JSpinner(m.getSpinnerModel()); - spin.setEditor(new SpinnerEditor(spin)); - spin.setToolTipText(tip); - sub.add(spin, "w 65lp!"); - - unit = new UnitSelector(m); - unit.setToolTipText(tip); - sub.add(unit, "growx"); - slider = new BasicSlider(m.getSliderModel(0, 2*Math.PI)); - slider.setToolTipText(tip); - sub.add(slider, "w 75lp, wrap"); - - - - - //// Temperature and pressure - sub = new JPanel(new MigLayout("fill, gap rel unrel", - "[grow][75lp!][35lp!][75lp!]", "")); - //// Atmospheric conditions - sub.setBorder(BorderFactory.createTitledBorder(trans.get("simedtdlg.border.Atmoscond"))); - this.add(sub, "growx, aligny 0, gapright para"); - - - BooleanModel isa = new BooleanModel(conditions, "ISAAtmosphere"); - JCheckBox check = new JCheckBox(isa); - //// Use International Standard Atmosphere - check.setText(trans.get("simedtdlg.checkbox.InterStdAtmosphere")); - //// Select to use the International Standard Atmosphere model. - ////
This model has a temperature of - //// and a pressure of - //// at sea level. - check.setToolTipText(trans.get("simedtdlg.checkbox.ttip.InterStdAtmosphere1") + " " + - UnitGroup.UNITS_TEMPERATURE.toStringUnit(ExtendedISAModel.STANDARD_TEMPERATURE) + - " " + trans.get("simedtdlg.checkbox.ttip.InterStdAtmosphere2") + " " + - UnitGroup.UNITS_PRESSURE.toStringUnit(ExtendedISAModel.STANDARD_PRESSURE) + - " " + trans.get("simedtdlg.checkbox.ttip.InterStdAtmosphere3")); - sub.add(check, "spanx, wrap unrel"); - - // Temperature: - label = new JLabel(trans.get("simedtdlg.lbl.Temperature")); - //// The temperature at the launch site. - tip = trans.get("simedtdlg.lbl.ttip.Temperature"); - label.setToolTipText(tip); - isa.addEnableComponent(label, false); - sub.add(label); - temperatureModel = new DoubleModel(conditions, "LaunchTemperature", UnitGroup.UNITS_TEMPERATURE, 0); - - spin = new JSpinner(temperatureModel.getSpinnerModel()); - spin.setEditor(new SpinnerEditor(spin)); - spin.setToolTipText(tip); - isa.addEnableComponent(spin, false); - sub.add(spin, "growx"); - - unit = new UnitSelector(temperatureModel); - unit.setToolTipText(tip); - isa.addEnableComponent(unit, false); - sub.add(unit, "growx"); - slider = new BasicSlider(temperatureModel.getSliderModel(253.15, 308.15)); // -20 ... 35 - slider.setToolTipText(tip); - isa.addEnableComponent(slider, false); - sub.add(slider, "w 75lp, wrap"); - - - - // Pressure: - label = new JLabel(trans.get("simedtdlg.lbl.Pressure")); - //// The atmospheric pressure at the launch site. - tip = trans.get("simedtdlg.lbl.ttip.Pressure"); - label.setToolTipText(tip); - isa.addEnableComponent(label, false); - sub.add(label); - - pressureModel = new DoubleModel(conditions, "LaunchPressure", UnitGroup.UNITS_PRESSURE, 0); - - spin = new JSpinner(pressureModel.getSpinnerModel()); - spin.setEditor(new SpinnerEditor(spin)); - spin.setToolTipText(tip); - isa.addEnableComponent(spin, false); - sub.add(spin, "growx"); - - unit = new UnitSelector(pressureModel); - unit.setToolTipText(tip); - isa.addEnableComponent(unit, false); - sub.add(unit, "growx"); - slider = new BasicSlider(pressureModel.getSliderModel(0.950e5, 1.050e5)); - slider.setToolTipText(tip); - isa.addEnableComponent(slider, false); - sub.add(slider, "w 75lp, wrap"); + // Simulation conditions settings + addSimulationConditionsPanel(this, conditions); - isa.addChangeListener(new StateChangeListener() { - @Override - public void stateChanged(EventObject e) { - temperatureModel.stateChanged(e); - pressureModel.stateChanged(e); - } - }); - - - - //// Launch site conditions - sub = new JPanel(new MigLayout("fill, gap rel unrel", - "[grow][65lp!][30lp!][75lp!]", "")); - //// Launch site - sub.setBorder(BorderFactory.createTitledBorder(trans.get("simedtdlg.lbl.Launchsite"))); - this.add(sub, "growx, split 2, aligny 0, flowy"); - - - // Latitude: - label = new JLabel(trans.get("simedtdlg.lbl.Latitude")); - //// The launch site latitude affects the gravitational pull of Earth.
- //// Positive values are on the Northern hemisphere, negative values on the Southern hemisphere. - tip = trans.get("simedtdlg.lbl.ttip.Latitude"); - label.setToolTipText(tip); - sub.add(label); - - m = new DoubleModel(conditions, "LaunchLatitude", UnitGroup.UNITS_NONE, -90, 90); - - spin = new JSpinner(m.getSpinnerModel()); - spin.setEditor(new SpinnerEditor(spin)); - spin.setToolTipText(tip); - sub.add(spin, "w 65lp!"); - - label = new JLabel(Chars.DEGREE + " N"); - label.setToolTipText(tip); - sub.add(label, "growx"); - slider = new BasicSlider(m.getSliderModel(-90, 90)); - slider.setToolTipText(tip); - sub.add(slider, "w 75lp, wrap"); - - - // Longitude: - label = new JLabel(trans.get("simedtdlg.lbl.Longitude")); - tip = trans.get("simedtdlg.lbl.ttip.Longitude"); - label.setToolTipText(tip); - sub.add(label); - - m = new DoubleModel(conditions, "LaunchLongitude", UnitGroup.UNITS_NONE, -180, 180); - - spin = new JSpinner(m.getSpinnerModel()); - spin.setEditor(new SpinnerEditor(spin)); - spin.setToolTipText(tip); - sub.add(spin, "w 65lp!"); - - label = new JLabel(Chars.DEGREE + " E"); - label.setToolTipText(tip); - sub.add(label, "growx"); - slider = new BasicSlider(m.getSliderModel(-180, 180)); - slider.setToolTipText(tip); - sub.add(slider, "w 75lp, wrap"); - - - // Altitude: - label = new JLabel(trans.get("simedtdlg.lbl.Altitude")); - //// The launch altitude above mean sea level.
- //// This affects the position of the rocket in the atmospheric model. - tip = trans.get("simedtdlg.lbl.ttip.Altitude"); - label.setToolTipText(tip); - sub.add(label); - - m = new DoubleModel(conditions, "LaunchAltitude", UnitGroup.UNITS_DISTANCE, 0); - - spin = new JSpinner(m.getSpinnerModel()); - spin.setEditor(new SpinnerEditor(spin)); - spin.setToolTipText(tip); - sub.add(spin, "w 65lp!"); - - unit = new UnitSelector(m); - unit.setToolTipText(tip); - sub.add(unit, "growx"); - slider = new BasicSlider(m.getSliderModel(0, 250, 1000)); - slider.setToolTipText(tip); - sub.add(slider, "w 75lp, wrap"); - - - - - - //// Launch rod - sub = new JPanel(new MigLayout("fill, gap rel unrel", - "[grow][65lp!][30lp!][75lp!]", "")); - //// Launch rod - sub.setBorder(BorderFactory.createTitledBorder(trans.get("simedtdlg.border.Launchrod"))); - this.add(sub, "growx, aligny 0, wrap"); - - - // Length: - label = new JLabel(trans.get("simedtdlg.lbl.Length")); - //// The length of the launch rod. - tip = trans.get("simedtdlg.lbl.ttip.Length"); - label.setToolTipText(tip); - sub.add(label); - - m = new DoubleModel(conditions, "LaunchRodLength", UnitGroup.UNITS_LENGTH, 0); - - spin = new JSpinner(m.getSpinnerModel()); - spin.setEditor(new SpinnerEditor(spin)); - spin.setToolTipText(tip); - sub.add(spin, "w 65lp!"); - - unit = new UnitSelector(m); - unit.setToolTipText(tip); - sub.add(unit, "growx"); - slider = new BasicSlider(m.getSliderModel(0, 1, 5)); - slider.setToolTipText(tip); - sub.add(slider, "w 75lp, wrap"); - - // Keep launch rod parallel to the wind. - - BooleanModel intoWind = new BooleanModel(conditions, "LaunchIntoWind"); - JCheckBox checkWind = new JCheckBox(intoWind); - //// Use International Standard Atmosphere - checkWind.setText(trans.get("simedtdlg.checkbox.Intowind")); - checkWind.setToolTipText( - trans.get("simedtdlg.checkbox.ttip.Intowind1") + - trans.get("simedtdlg.checkbox.ttip.Intowind2") + - trans.get("simedtdlg.checkbox.ttip.Intowind3") + - trans.get("simedtdlg.checkbox.ttip.Intowind4")); - sub.add(checkWind, "spanx, wrap unrel"); - - - // Angle: - label = new JLabel(trans.get("simedtdlg.lbl.Angle")); - //// The angle of the launch rod from vertical. - tip = trans.get("simedtdlg.lbl.ttip.Angle"); - label.setToolTipText(tip); - sub.add(label); - - m = new DoubleModel(conditions, "LaunchRodAngle", UnitGroup.UNITS_ANGLE, - -SimulationOptions.MAX_LAUNCH_ROD_ANGLE, SimulationOptions.MAX_LAUNCH_ROD_ANGLE); - - spin = new JSpinner(m.getSpinnerModel()); - spin.setEditor(new SpinnerEditor(spin)); - spin.setToolTipText(tip); - sub.add(spin, "w 65lp!"); - - unit = new UnitSelector(m); - unit.setToolTipText(tip); - sub.add(unit, "growx"); - slider = new BasicSlider(m.getSliderModel(-SimulationOptions.MAX_LAUNCH_ROD_ANGLE, 0, - SimulationOptions.MAX_LAUNCH_ROD_ANGLE)); - slider.setToolTipText(tip); - sub.add(slider, "w 75lp, wrap"); - - - - // Direction: - JLabel directionLabel = new JLabel(trans.get("simedtdlg.lbl.Direction")); - //// Direction of the launch rod. - tip = trans.get("simedtdlg.lbl.ttip.Direction1") + - UnitGroup.UNITS_ANGLE.toStringUnit(0) + - " " + trans.get("simedtdlg.lbl.ttip.Direction2") + " " + - UnitGroup.UNITS_ANGLE.toStringUnit(2*Math.PI) + - " " + trans.get("simedtdlg.lbl.ttip.Direction3"); - directionLabel.setToolTipText(tip); - sub.add(directionLabel); - - m = new DoubleModel(conditions, "LaunchRodDirection", 1.0, UnitGroup.UNITS_ANGLE, - 0, 2*Math.PI); - - JSpinner directionSpin = new JSpinner(m.getSpinnerModel()); - directionSpin.setEditor(new SpinnerEditor(directionSpin)); - directionSpin.setToolTipText(tip); - sub.add(directionSpin, "w 65lp!"); - - unit = new UnitSelector(m); - unit.setToolTipText(tip); - sub.add(unit, "growx"); - BasicSlider directionSlider = new BasicSlider(m.getSliderModel(0, 2*Math.PI)); - directionSlider.setToolTipText(tip); - sub.add(directionSlider, "w 75lp, wrap"); - intoWind.addEnableComponent(directionLabel, false); - intoWind.addEnableComponent(directionSpin, false); - intoWind.addEnableComponent(unit, false); - intoWind.addEnableComponent(directionSlider, false); - - - - - JButton restoreDefaults = new SelectColorButton(trans.get("simedtdlg.but.resettodefault")); restoreDefaults.addActionListener(new ActionListener() { @@ -468,8 +80,398 @@ public class SimulationConditionsPanel extends JPanel { this.add(saveDefaults, "gapbottom para, gapright para, right"); } - - private String getIntensityDescription(double i) { + + /** + * Adds the simulation conditions panel to the parent panel. + * @param parent The parent panel. + * @param target The object containing the simulation conditions setters/getters. + */ + public static void addSimulationConditionsPanel(JPanel parent, SimulationOptionsInterface target) { + JPanel sub; + DoubleModel pressureModel; + DoubleModel m; + JSpinner spin; + DoubleModel temperatureModel; + String tip; + BasicSlider slider; + UnitSelector unit; + + //// Wind settings: Average wind speed, turbulence intensity, std. deviation, and direction + sub = new JPanel(new MigLayout("fill, gap rel unrel", + "[grow][75lp!][30lp!][75lp!]", "")); + //// Wind + sub.setBorder(BorderFactory.createTitledBorder(trans.get("simedtdlg.lbl.Wind"))); + parent.add(sub, "growx, split 2, aligny 0, flowy, gapright para"); + + + // Wind average + //// Average windspeed: + JLabel label = new JLabel(trans.get("simedtdlg.lbl.Averwindspeed")); + //// The average windspeed relative to the ground. + tip = trans.get("simedtdlg.lbl.ttip.Averwindspeed"); + label.setToolTipText(tip); + sub.add(label); + + m = new DoubleModel(target, "WindSpeedAverage", UnitGroup.UNITS_WINDSPEED, 0); + + spin = new JSpinner(m.getSpinnerModel()); + spin.setEditor(new SpinnerEditor(spin)); + spin.setToolTipText(tip); + sub.add(spin, "w 65lp!"); + + unit = new UnitSelector(m); + unit.setToolTipText(tip); + sub.add(unit, "growx"); + slider = new BasicSlider(m.getSliderModel(0, 10.0)); + slider.setToolTipText(tip); + sub.add(slider, "w 75lp, wrap"); + + + // Wind std. deviation + //// Standard deviation: + label = new JLabel(trans.get("simedtdlg.lbl.Stddeviation")); + //// The standard deviation of the windspeed.
+ //// The windspeed is within twice the standard deviation from the average for 95% of the time. + tip = trans.get("simedtdlg.lbl.ttip.Stddeviation"); + label.setToolTipText(tip); + sub.add(label); + + m = new DoubleModel(target, "WindSpeedDeviation", UnitGroup.UNITS_WINDSPEED, 0); + DoubleModel m2 = new DoubleModel(target, "WindSpeedAverage", 0.25, + UnitGroup.UNITS_COEFFICIENT, 0); + + spin = new JSpinner(m.getSpinnerModel()); + spin.setEditor(new SpinnerEditor(spin)); + spin.setToolTipText(tip); + addEasterEgg(spin, parent); + sub.add(spin, "w 65lp!"); + + unit = new UnitSelector(m); + unit.setToolTipText(tip); + sub.add(unit, "growx"); + slider = new BasicSlider(m.getSliderModel(new DoubleModel(0), m2)); + slider.setToolTipText(tip); + sub.add(slider, "w 75lp, wrap"); + + + // Wind turbulence intensity + //// Turbulence intensity: + label = new JLabel(trans.get("simedtdlg.lbl.Turbulenceintensity")); + //// The turbulence intensity is the standard deviation divided by the average windspeed.
+ //// Typical values range from + //// to + tip = trans.get("simedtdlg.lbl.ttip.Turbulenceintensity1") + + trans.get("simedtdlg.lbl.ttip.Turbulenceintensity2") + " " + + UnitGroup.UNITS_RELATIVE.getDefaultUnit().toStringUnit(0.05) + + " " + trans.get("simedtdlg.lbl.ttip.Turbulenceintensity3") + " " + + UnitGroup.UNITS_RELATIVE.getDefaultUnit().toStringUnit(0.20) + "."; + label.setToolTipText(tip); + sub.add(label); + + m = new DoubleModel(target, "WindTurbulenceIntensity", UnitGroup.UNITS_RELATIVE, 0); + + spin = new JSpinner(m.getSpinnerModel()); + spin.setEditor(new SpinnerEditor(spin)); + spin.setToolTipText(tip); + sub.add(spin, "w 65lp!"); + + unit = new UnitSelector(m); + unit.setToolTipText(tip); + sub.add(unit, "growx"); + + final JLabel intensityLabel = new JLabel( + getIntensityDescription(target.getWindTurbulenceIntensity())); + intensityLabel.setToolTipText(tip); + sub.add(intensityLabel, "w 75lp, wrap"); + m.addChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + intensityLabel.setText( + getIntensityDescription(target.getWindTurbulenceIntensity())); + } + }); + + // Wind Direction: + label = new JLabel(trans.get("simedtdlg.lbl.Winddirection")); + //// Direction of the wind. 0 is north + tip = trans.get("simedtdlg.lbl.ttip.Winddirection"); + label.setToolTipText(tip); + sub.add(label); + + m = new DoubleModel(target, "WindDirection", 1.0, UnitGroup.UNITS_ANGLE, + 0, 2*Math.PI); + + spin = new JSpinner(m.getSpinnerModel()); + spin.setEditor(new SpinnerEditor(spin)); + spin.setToolTipText(tip); + sub.add(spin, "w 65lp!"); + + unit = new UnitSelector(m); + unit.setToolTipText(tip); + sub.add(unit, "growx"); + slider = new BasicSlider(m.getSliderModel(0, 2*Math.PI)); + slider.setToolTipText(tip); + sub.add(slider, "w 75lp, wrap"); + + + //// Temperature and pressure + sub = new JPanel(new MigLayout("fill, gap rel unrel", + "[grow][85lp!][35lp!][75lp!]", "")); + //// Atmospheric conditions + sub.setBorder(BorderFactory.createTitledBorder(trans.get("simedtdlg.border.Atmoscond"))); + parent.add(sub, "growx, aligny 0, gapright para"); + + + BooleanModel isa = new BooleanModel(target, "ISAAtmosphere"); + JCheckBox check = new JCheckBox(isa); + //// Use International Standard Atmosphere + check.setText(trans.get("simedtdlg.checkbox.InterStdAtmosphere")); + //// Select to use the International Standard Atmosphere model. + ////
This model has a temperature of + //// and a pressure of + //// at sea level. + check.setToolTipText(trans.get("simedtdlg.checkbox.ttip.InterStdAtmosphere1") + " " + + UnitGroup.UNITS_TEMPERATURE.toStringUnit(ExtendedISAModel.STANDARD_TEMPERATURE) + + " " + trans.get("simedtdlg.checkbox.ttip.InterStdAtmosphere2") + " " + + UnitGroup.UNITS_PRESSURE.toStringUnit(ExtendedISAModel.STANDARD_PRESSURE) + + " " + trans.get("simedtdlg.checkbox.ttip.InterStdAtmosphere3")); + sub.add(check, "spanx, wrap unrel"); + + // Temperature: + label = new JLabel(trans.get("simedtdlg.lbl.Temperature")); + //// The temperature at the launch site. + tip = trans.get("simedtdlg.lbl.ttip.Temperature"); + label.setToolTipText(tip); + isa.addEnableComponent(label, false); + sub.add(label); + + temperatureModel = new DoubleModel(target, "LaunchTemperature", UnitGroup.UNITS_TEMPERATURE, 0); + + spin = new JSpinner(temperatureModel.getSpinnerModel()); + spin.setEditor(new SpinnerEditor(spin)); + spin.setToolTipText(tip); + isa.addEnableComponent(spin, false); + sub.add(spin, "growx"); + + unit = new UnitSelector(temperatureModel); + unit.setToolTipText(tip); + isa.addEnableComponent(unit, false); + sub.add(unit, "growx"); + slider = new BasicSlider(temperatureModel.getSliderModel(253.15, 308.15)); // -20 ... 35 + slider.setToolTipText(tip); + isa.addEnableComponent(slider, false); + sub.add(slider, "w 75lp, wrap"); + + + // Pressure: + label = new JLabel(trans.get("simedtdlg.lbl.Pressure")); + //// The atmospheric pressure at the launch site. + tip = trans.get("simedtdlg.lbl.ttip.Pressure"); + label.setToolTipText(tip); + isa.addEnableComponent(label, false); + sub.add(label); + + pressureModel = new DoubleModel(target, "LaunchPressure", UnitGroup.UNITS_PRESSURE, 0); + + spin = new JSpinner(pressureModel.getSpinnerModel()); + spin.setEditor(new SpinnerEditor(spin)); + spin.setToolTipText(tip); + isa.addEnableComponent(spin, false); + sub.add(spin, "growx"); + + unit = new UnitSelector(pressureModel); + unit.setToolTipText(tip); + isa.addEnableComponent(unit, false); + sub.add(unit, "growx"); + slider = new BasicSlider(pressureModel.getSliderModel(0.950e5, 1.050e5)); + slider.setToolTipText(tip); + isa.addEnableComponent(slider, false); + sub.add(slider, "w 75lp, wrap"); + + + isa.addChangeListener(new StateChangeListener() { + @Override + public void stateChanged(EventObject e) { + temperatureModel.stateChanged(e); + pressureModel.stateChanged(e); + } + }); + + + //// Launch site conditions + sub = new JPanel(new MigLayout("fill, gap rel unrel", + "[grow][65lp!][30lp!][75lp!]", "")); + //// Launch site + sub.setBorder(BorderFactory.createTitledBorder(trans.get("simedtdlg.lbl.Launchsite"))); + parent.add(sub, "growx, split 2, aligny 0, flowy"); + + + // Latitude: + label = new JLabel(trans.get("simedtdlg.lbl.Latitude")); + //// The launch site latitude affects the gravitational pull of Earth.
+ //// Positive values are on the Northern hemisphere, negative values on the Southern hemisphere. + tip = trans.get("simedtdlg.lbl.ttip.Latitude"); + label.setToolTipText(tip); + sub.add(label); + + m = new DoubleModel(target, "LaunchLatitude", UnitGroup.UNITS_NONE, -90, 90); + + spin = new JSpinner(m.getSpinnerModel()); + spin.setEditor(new SpinnerEditor(spin)); + spin.setToolTipText(tip); + sub.add(spin, "w 65lp!"); + + label = new JLabel(Chars.DEGREE + " N"); + label.setToolTipText(tip); + sub.add(label, "growx"); + slider = new BasicSlider(m.getSliderModel(-90, 90)); + slider.setToolTipText(tip); + sub.add(slider, "w 75lp, wrap"); + + + // Longitude: + label = new JLabel(trans.get("simedtdlg.lbl.Longitude")); + tip = trans.get("simedtdlg.lbl.ttip.Longitude"); + label.setToolTipText(tip); + sub.add(label); + + m = new DoubleModel(target, "LaunchLongitude", UnitGroup.UNITS_NONE, -180, 180); + + spin = new JSpinner(m.getSpinnerModel()); + spin.setEditor(new SpinnerEditor(spin)); + spin.setToolTipText(tip); + sub.add(spin, "w 65lp!"); + + label = new JLabel(Chars.DEGREE + " E"); + label.setToolTipText(tip); + sub.add(label, "growx"); + slider = new BasicSlider(m.getSliderModel(-180, 180)); + slider.setToolTipText(tip); + sub.add(slider, "w 75lp, wrap"); + + + // Altitude: + label = new JLabel(trans.get("simedtdlg.lbl.Altitude")); + //// The launch altitude above mean sea level.
+ //// This affects the position of the rocket in the atmospheric model. + tip = trans.get("simedtdlg.lbl.ttip.Altitude"); + label.setToolTipText(tip); + sub.add(label); + + m = new DoubleModel(target, "LaunchAltitude", UnitGroup.UNITS_DISTANCE, 0); + + spin = new JSpinner(m.getSpinnerModel()); + spin.setEditor(new SpinnerEditor(spin)); + spin.setToolTipText(tip); + sub.add(spin, "w 65lp!"); + + unit = new UnitSelector(m); + unit.setToolTipText(tip); + sub.add(unit, "growx"); + slider = new BasicSlider(m.getSliderModel(0, 250, 1000)); + slider.setToolTipText(tip); + sub.add(slider, "w 75lp, wrap"); + + + //// Launch rod + sub = new JPanel(new MigLayout("fill, gap rel unrel", + "[grow][75lp!][30lp!][75lp!]", "")); + //// Launch rod + sub.setBorder(BorderFactory.createTitledBorder(trans.get("simedtdlg.border.Launchrod"))); + parent.add(sub, "growx, aligny 0, wrap"); + + + // Length: + label = new JLabel(trans.get("simedtdlg.lbl.Length")); + //// The length of the launch rod. + tip = trans.get("simedtdlg.lbl.ttip.Length"); + label.setToolTipText(tip); + sub.add(label); + + m = new DoubleModel(target, "LaunchRodLength", UnitGroup.UNITS_LENGTH, 0); + + spin = new JSpinner(m.getSpinnerModel()); + spin.setEditor(new SpinnerEditor(spin)); + spin.setToolTipText(tip); + sub.add(spin, "growx"); + + unit = new UnitSelector(m); + unit.setToolTipText(tip); + sub.add(unit, "growx"); + slider = new BasicSlider(m.getSliderModel(0, 1, 5)); + slider.setToolTipText(tip); + sub.add(slider, "w 75lp, wrap"); + + // Keep launch rod parallel to the wind. + + BooleanModel intoWind = new BooleanModel(target, "LaunchIntoWind"); + JCheckBox checkWind = new JCheckBox(intoWind); + //// Use International Standard Atmosphere + checkWind.setText(trans.get("simedtdlg.checkbox.Intowind")); + checkWind.setToolTipText( + trans.get("simedtdlg.checkbox.ttip.Intowind1") + + trans.get("simedtdlg.checkbox.ttip.Intowind2") + + trans.get("simedtdlg.checkbox.ttip.Intowind3") + + trans.get("simedtdlg.checkbox.ttip.Intowind4")); + sub.add(checkWind, "spanx, wrap unrel"); + + + // Angle: + label = new JLabel(trans.get("simedtdlg.lbl.Angle")); + //// The angle of the launch rod from vertical. + tip = trans.get("simedtdlg.lbl.ttip.Angle"); + label.setToolTipText(tip); + sub.add(label); + + m = new DoubleModel(target, "LaunchRodAngle", UnitGroup.UNITS_ANGLE, + -SimulationOptions.MAX_LAUNCH_ROD_ANGLE, SimulationOptions.MAX_LAUNCH_ROD_ANGLE); + + spin = new JSpinner(m.getSpinnerModel()); + spin.setEditor(new SpinnerEditor(spin)); + spin.setToolTipText(tip); + sub.add(spin, "growx"); + + unit = new UnitSelector(m); + unit.setToolTipText(tip); + sub.add(unit, "growx"); + slider = new BasicSlider(m.getSliderModel(-SimulationOptions.MAX_LAUNCH_ROD_ANGLE, 0, + SimulationOptions.MAX_LAUNCH_ROD_ANGLE)); + slider.setToolTipText(tip); + sub.add(slider, "w 75lp, wrap"); + + + // Direction: + JLabel directionLabel = new JLabel(trans.get("simedtdlg.lbl.Direction")); + //// Direction of the launch rod. + tip = trans.get("simedtdlg.lbl.ttip.Direction1") + + UnitGroup.UNITS_ANGLE.toStringUnit(0) + + " " + trans.get("simedtdlg.lbl.ttip.Direction2") + " " + + UnitGroup.UNITS_ANGLE.toStringUnit(2*Math.PI) + + " " + trans.get("simedtdlg.lbl.ttip.Direction3"); + directionLabel.setToolTipText(tip); + sub.add(directionLabel); + + m = new DoubleModel(target, "LaunchRodDirection", 1.0, UnitGroup.UNITS_ANGLE, + 0, 2*Math.PI); + + JSpinner directionSpin = new JSpinner(m.getSpinnerModel()); + directionSpin.setEditor(new SpinnerEditor(directionSpin)); + directionSpin.setToolTipText(tip); + sub.add(directionSpin, "growx"); + + unit = new UnitSelector(m); + unit.setToolTipText(tip); + sub.add(unit, "growx"); + BasicSlider directionSlider = new BasicSlider(m.getSliderModel(0, 2*Math.PI)); + directionSlider.setToolTipText(tip); + sub.add(directionSlider, "w 75lp, wrap"); + intoWind.addEnableComponent(directionLabel, false); + intoWind.addEnableComponent(directionSpin, false); + intoWind.addEnableComponent(unit, false); + intoWind.addEnableComponent(directionSlider, false); + } + + private static String getIntensityDescription(double i) { if (i < 0.001) //// None return trans.get("simedtdlg.IntensityDesc.None"); @@ -491,5 +493,23 @@ public class SimulationConditionsPanel extends JPanel { //// Extreme return trans.get("simedtdlg.IntensityDesc.Extreme"); } - + + /** + * Shh, don't tell anyone about this easter-egg. (displays a fun quote when the text of the spinner equals 42) + * @param spinner the magic spinner! + */ + private static void addEasterEgg(JSpinner spinner, Component parent) { + JTextField textField = ((JSpinner.DefaultEditor) spinner.getEditor()).getTextField(); + textField.addKeyListener(new KeyAdapter() { + @Override + public void keyTyped(KeyEvent e) { + String text = textField.getText() + e.getKeyChar(); + if (text.equals("42")) { + JOptionPane.showMessageDialog(parent, + "The answer to the ultimate question of life, the universe, and everything.", + "42", JOptionPane.INFORMATION_MESSAGE); + } + } + }); + } } diff --git a/swing/src/net/sf/openrocket/gui/util/SwingPreferences.java b/swing/src/net/sf/openrocket/gui/util/SwingPreferences.java index e544fcd8d..44bdd5736 100644 --- a/swing/src/net/sf/openrocket/gui/util/SwingPreferences.java +++ b/swing/src/net/sf/openrocket/gui/util/SwingPreferences.java @@ -32,6 +32,7 @@ import net.sf.openrocket.rocketcomponent.RailButton; import net.sf.openrocket.rocketcomponent.RecoveryDevice; import net.sf.openrocket.rocketcomponent.RocketComponent; import net.sf.openrocket.rocketcomponent.TubeFinSet; +import net.sf.openrocket.simulation.SimulationOptionsInterface; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -50,7 +51,7 @@ import net.sf.openrocket.util.BugException; import net.sf.openrocket.util.BuildProperties; -public class SwingPreferences extends net.sf.openrocket.startup.Preferences { +public class SwingPreferences extends net.sf.openrocket.startup.Preferences implements SimulationOptionsInterface { private static final Logger log = LoggerFactory.getLogger(SwingPreferences.class); private static final String SPLIT_CHARACTER = "|";