diff --git a/ChangeLog b/ChangeLog
index 3503ef69f..3f0411c66 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,8 @@
-2022-02-06 Sibo Van Gool
+2023-11-16 Sibo Van Gool
+
+ * Released version 23.09. See Release Notes for changes.
+
+2023-02-06 Sibo Van Gool
* Released version 22.02. See Release Notes of 22.02.beta.01, 22.02.beta.02, 22.02.beta.03, 22.02.beta.04,
22.02.beta.05, and 22.02.RC.01 for changes.
diff --git a/ReleaseNotes.md b/ReleaseNotes.md
index 3a3816b5f..c1ecdc267 100644
--- a/ReleaseNotes.md
+++ b/ReleaseNotes.md
@@ -15,7 +15,7 @@ Release Notes
-OpenRocket 23.09
+OpenRocket 23.09 (2023-11-16)
------------------------
You can find a visual overview of what's new for this release on [our website](https://openrocket.info//downloads.html?vers=23.09#whats-new).
diff --git a/core/src/net/sf/openrocket/simulation/SimulationOptions.java b/core/src/net/sf/openrocket/simulation/SimulationOptions.java
index d11759332..f26f0146d 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
@@ -146,6 +146,9 @@ public class SimulationOptions implements ChangeSource, Cloneable {
if (MathUtil.equals(this.windAverage, windAverage))
return;
this.windAverage = MathUtil.max(windAverage, 0);
+ if (MathUtil.equals(this.windAverage, 0)) {
+ setWindTurbulenceIntensity(0);
+ }
fireChangeEvent();
}
@@ -161,34 +164,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 +298,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/core/src/net/sf/openrocket/unit/UnitGroup.java b/core/src/net/sf/openrocket/unit/UnitGroup.java
index 090b5ec49..c79272a64 100644
--- a/core/src/net/sf/openrocket/unit/UnitGroup.java
+++ b/core/src/net/sf/openrocket/unit/UnitGroup.java
@@ -291,6 +291,7 @@ public class UnitGroup {
UNITS_ROUGHNESS = new UnitGroup();
UNITS_ROUGHNESS.addUnit(new GeneralUnit(0.000001, MICRO + "m"));
UNITS_ROUGHNESS.addUnit(new GeneralUnit(0.0000254, "mil"));
+ UNITS_ROUGHNESS.addUnit(new GeneralUnit(0.0254, "in"));
UNITS_ROUGHNESS.addUnit(new GeneralUnit(1, "m"));
diff --git a/core/test/net/sf/openrocket/simulation/FlightEventsTest.java b/core/test/net/sf/openrocket/simulation/FlightEventsTest.java
index 4c4d55bab..442edb574 100644
--- a/core/test/net/sf/openrocket/simulation/FlightEventsTest.java
+++ b/core/test/net/sf/openrocket/simulation/FlightEventsTest.java
@@ -32,6 +32,10 @@ public class FlightEventsTest extends BaseTestCase {
@Test
public void testSingleStage() throws SimulationException {
final Rocket rocket = TestRockets.makeEstesAlphaIII();
+ final AxialStage stage = rocket.getStage(0);
+ final InnerTube motorMountTube = (InnerTube) stage.getChild(1).getChild(2);
+ final Parachute parachute = (Parachute) stage.getChild(1).getChild(3);
+
final Simulation sim = new Simulation(rocket);
sim.getOptions().setISAAtmosphere(true);
sim.getOptions().setTimeStep(0.05);
@@ -43,41 +47,21 @@ public class FlightEventsTest extends BaseTestCase {
final int branchCount = sim.getSimulatedData().getBranchCount();
assertEquals(" Single stage simulation invalid branch count ", 1, branchCount);
- final FlightEvent.Type[] expectedEventTypes = {FlightEvent.Type.LAUNCH, FlightEvent.Type.IGNITION, FlightEvent.Type.LIFTOFF,
- FlightEvent.Type.LAUNCHROD, FlightEvent.Type.BURNOUT, FlightEvent.Type.EJECTION_CHARGE, FlightEvent.Type.RECOVERY_DEVICE_DEPLOYMENT,
- FlightEvent.Type.APOGEE, FlightEvent.Type.GROUND_HIT, FlightEvent.Type.SIMULATION_END};
- final double[] expectedEventTimes = {0.0, 0.0, 0.1275, 0.13, 2.0, 2.0, 2.001, 2.48338}; // Ground hit time is too variable, so don't include it
- final AxialStage stage = rocket.getStage(0);
- final InnerTube motorMountTube = (InnerTube) stage.getChild(1).getChild(2);
- final Parachute parachute = (Parachute) stage.getChild(1).getChild(3);
- final RocketComponent[] expectedSources = {rocket, motorMountTube, null, null, motorMountTube,
- stage, parachute, rocket, null, null};
-
- // Test event count
- FlightDataBranch branch = sim.getSimulatedData().getBranch(0);
- List eventList = branch.getEvents();
- List eventTypes = eventList.stream().map(FlightEvent::getType).collect(Collectors.toList());
- assertEquals(" Single stage simulation invalid number of events ", expectedEventTypes.length, eventTypes.size());
-
- // Test that all expected events are present, and in the right order
- for (int i = 0; i < expectedEventTypes.length; i++) {
- assertSame(" Flight type " + expectedEventTypes[i] + " not found in single stage simulation ",
- expectedEventTypes[i], eventTypes.get(i));
- }
-
- // Test that the event times are correct
- for (int i = 0; i < expectedEventTimes.length; i++) {
- assertEquals(" Flight type " + expectedEventTypes[i] + " has wrong time ",
- expectedEventTimes[i], eventList.get(i).getTime(), EPSILON);
-
- }
-
- // Test that the event sources are correct
- for (int i = 0; i < expectedSources.length; i++) {
- assertEquals(" Flight type " + expectedEventTypes[i] + " has wrong source ",
- expectedSources[i], eventList.get(i).getSource());
- }
- }
+ final FlightEvent[] expectedEvents = new FlightEvent[] {
+ new FlightEvent(FlightEvent.Type.LAUNCH, 0.0, rocket),
+ new FlightEvent(FlightEvent.Type.IGNITION, 0.0, motorMountTube),
+ new FlightEvent(FlightEvent.Type.LIFTOFF, 0.1275, null),
+ new FlightEvent(FlightEvent.Type.LAUNCHROD, 0.13, null),
+ new FlightEvent(FlightEvent.Type.BURNOUT, 2.0, motorMountTube),
+ new FlightEvent(FlightEvent.Type.EJECTION_CHARGE, 2.0, stage),
+ new FlightEvent(FlightEvent.Type.RECOVERY_DEVICE_DEPLOYMENT, 2.001, parachute),
+ new FlightEvent(FlightEvent.Type.APOGEE, 2.48338, rocket),
+ new FlightEvent(FlightEvent.Type.GROUND_HIT, 1200, null),
+ new FlightEvent(FlightEvent.Type.SIMULATION_END, 1200, null)
+ };
+
+ checkEvents(expectedEvents, sim, 0);
+ }
/**
* Tests for a multi-stage design.
@@ -156,29 +140,34 @@ public class FlightEventsTest extends BaseTestCase {
throw new IllegalStateException("Invalid branch number " + b);
}
- // Test event count
- final FlightDataBranch branch = sim.getSimulatedData().getBranch(b);
- final FlightEvent[] events = branch.getEvents().toArray(new FlightEvent[0]);
- assertEquals(" Multi-stage simulation, branch " + b + " invalid number of events ", expectedEvents.length, events.length);
+ checkEvents(expectedEvents, sim, b);
+ }
+ }
- // Test that all expected events are present, in the right order, at the right time, from the right sources
- for (int i = 0; i < events.length; i++) {
- final FlightEvent expected = expectedEvents[i];
- final FlightEvent actual = events[i];
- assertSame("Branch " + b + " FlightEvent " + i + " type " + expected.getType() + " not found; FlightEvent " + actual.getType() + " found instead",
- expected.getType(), actual.getType());
+ private void checkEvents(FlightEvent[] expectedEvents, Simulation sim, int branchNo) {
- if (1200 != expected.getTime()) {
- // Tumbling can have a very large time error, so implement a more course epsilon (otherwise unit tests just keep failing...)
- double epsilon = actual.getType() == FlightEvent.Type.TUMBLE || actual.getType() == FlightEvent.Type.APOGEE ? 0.05 : EPSILON;
- assertEquals("Branch " + b + " FlightEvent " + i + " type " + expected.getType() + " has wrong time ",
- expected.getTime(), actual.getTime(), epsilon);
- }
+ FlightEvent[] actualEvents = sim.getSimulatedData().getBranch(branchNo).getEvents().toArray(new FlightEvent[0]);
+
+ // Test event count
+ assertEquals("Branch " + branchNo + " invalid number of events ", expectedEvents.length, actualEvents.length);
- // Test that the event sources are correct
- assertEquals("Branch " + b + " FlightEvent " + i + " type " + expected.getType() + " has wrong source ",
- expected.getSource(), actual.getSource());
- }
- }
- }
+ // Test that all expected events are present, in the right order, at the right time, from the right sources
+ for (int i = 0; i < actualEvents.length; i++) {
+ final FlightEvent expected = expectedEvents[i];
+ final FlightEvent actual = actualEvents[i];
+ assertSame("Branch " + branchNo + " FlightEvent " + i + " type " + expected.getType() + " not found; FlightEvent " + actual.getType() + " found instead",
+ expected.getType(), actual.getType());
+
+ if (1200 != expected.getTime()) {
+ // event times that are dependent on simulation step time shouldn't be held to tighter bounds than that
+ double epsilon = actual.getType() == FlightEvent.Type.TUMBLE || actual.getType() == FlightEvent.Type.APOGEE ? sim.getOptions().getTimeStep() : EPSILON;
+ assertEquals("Branch " + branchNo + " FlightEvent " + i + " type " + expected.getType() + " has wrong time ",
+ expected.getTime(), actual.getTime(), epsilon);
+ }
+
+ // Test that the event sources are correct
+ assertEquals("Branch " + branchNo + " FlightEvent " + i + " type " + expected.getType() + " has wrong source ",
+ expected.getSource(), actual.getSource());
+ }
+ }
}
diff --git a/swing/src/net/sf/openrocket/gui/dialogs/ComponentAnalysisDialog.java b/swing/src/net/sf/openrocket/gui/dialogs/ComponentAnalysisDialog.java
index 8e52d97f6..320c4b43a 100644
--- a/swing/src/net/sf/openrocket/gui/dialogs/ComponentAnalysisDialog.java
+++ b/swing/src/net/sf/openrocket/gui/dialogs/ComponentAnalysisDialog.java
@@ -49,6 +49,7 @@ import net.sf.openrocket.gui.adaptors.Column;
import net.sf.openrocket.gui.adaptors.ColumnTable;
import net.sf.openrocket.gui.adaptors.ColumnTableModel;
import net.sf.openrocket.gui.adaptors.DoubleModel;
+import net.sf.openrocket.gui.components.EditableSpinner;
import net.sf.openrocket.gui.components.BasicSlider;
import net.sf.openrocket.gui.components.ConfigurationComboBox;
import net.sf.openrocket.gui.components.StageSelector;
@@ -113,7 +114,7 @@ public class ComponentAnalysisDialog extends JDialog implements StateChangeListe
JTable table;
- JPanel panel = new JPanel(new MigLayout("fill", "[120lp][70lp][]"));
+ JPanel panel = new JPanel(new MigLayout("fill", "[120lp][70lp][50lp][]"));
add(panel);
rkt = rocketPanel.getDocument().getRocket();
@@ -134,7 +135,9 @@ public class ComponentAnalysisDialog extends JDialog implements StateChangeListe
//// Wind direction:
panel.add(new JLabel(trans.get("componentanalysisdlg.lbl.winddir")));
- panel.add(new UnitSelector(theta, true), "width 50lp!");
+ EditableSpinner spinner = new EditableSpinner(theta.getSpinnerModel());
+ panel.add(spinner, "growx");
+ panel.add(new UnitSelector(theta));
BasicSlider slider = new BasicSlider(theta.getSliderModel(0, 2 * Math.PI));
panel.add(slider, "growx, split 2");
//// Worst button
@@ -165,17 +168,20 @@ public class ComponentAnalysisDialog extends JDialog implements StateChangeListe
////Angle of attack:
panel.add(new JLabel(trans.get("componentanalysisdlg.lbl.angleofattack")));
- panel.add(new UnitSelector(aoa, true), "width 50lp!");
+ panel.add(new EditableSpinner(aoa.getSpinnerModel()), "growx");
+ panel.add(new UnitSelector(aoa));
panel.add(new BasicSlider(aoa.getSliderModel(0, Math.PI)), "growx, wrap");
//// Mach number:
panel.add(new JLabel(trans.get("componentanalysisdlg.lbl.machnumber")));
- panel.add(new UnitSelector(mach, true), "width 50lp!");
+ panel.add(new EditableSpinner(mach.getSpinnerModel()));
+ panel.add(new UnitSelector(mach));
panel.add(new BasicSlider(mach.getSliderModel(0, 3)), "growx, wrap");
//// Roll rate:
panel.add(new JLabel(trans.get("componentanalysisdlg.lbl.rollrate")));
- panel.add(new UnitSelector(roll, true), "width 50lp!");
+ panel.add(new EditableSpinner(roll.getSpinnerModel()), "growx");
+ panel.add(new UnitSelector(roll));
panel.add(new BasicSlider(roll.getSliderModel(-20 * 2 * Math.PI, 20 * 2 * Math.PI)),
"growx, wrap");
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..030c8f058 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,411 @@ 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);
+
+ DoubleModel windSpeedAverage = new DoubleModel(target, "WindSpeedAverage", UnitGroup.UNITS_WINDSPEED, 0);
+
+ spin = new JSpinner(windSpeedAverage.getSpinnerModel());
+ spin.setEditor(new SpinnerEditor(spin));
+ spin.setToolTipText(tip);
+ sub.add(spin, "growx");
+
+ unit = new UnitSelector(windSpeedAverage);
+ unit.setToolTipText(tip);
+ sub.add(unit, "growx");
+ slider = new BasicSlider(windSpeedAverage.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);
+
+ DoubleModel windSpeedDeviation = new DoubleModel(target, "WindSpeedDeviation", UnitGroup.UNITS_WINDSPEED, 0);
+ DoubleModel m2 = new DoubleModel(target, "WindSpeedAverage", 0.25, UnitGroup.UNITS_COEFFICIENT, 0);
+
+ spin = new JSpinner(windSpeedDeviation.getSpinnerModel());
+ spin.setEditor(new SpinnerEditor(spin));
+ spin.setToolTipText(tip);
+ addEasterEgg(spin, parent);
+ sub.add(spin, "growx");
+
+ unit = new UnitSelector(windSpeedDeviation);
+ unit.setToolTipText(tip);
+ sub.add(unit, "growx");
+ slider = new BasicSlider(windSpeedDeviation.getSliderModel(new DoubleModel(0), m2));
+ slider.setToolTipText(tip);
+ sub.add(slider, "w 75lp, wrap");
+
+ windSpeedAverage.addChangeListener(new ChangeListener() {
+ @Override
+ public void stateChanged(ChangeEvent e) {
+ windSpeedDeviation.stateChanged(e);
+ }
+ });
+
+
+ // 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);
+
+ DoubleModel windTurbulenceIntensity = new DoubleModel(target, "WindTurbulenceIntensity", UnitGroup.UNITS_RELATIVE, 0);
+
+ spin = new JSpinner(windTurbulenceIntensity.getSpinnerModel());
+ spin.setEditor(new SpinnerEditor(spin));
+ spin.setToolTipText(tip);
+ sub.add(spin, "growx");
+
+ unit = new UnitSelector(windTurbulenceIntensity);
+ unit.setToolTipText(tip);
+ sub.add(unit, "growx");
+
+ final JLabel intensityLabel = new JLabel(
+ getIntensityDescription(target.getWindTurbulenceIntensity()));
+ intensityLabel.setToolTipText(tip);
+ sub.add(intensityLabel, "w 75lp, wrap");
+ windTurbulenceIntensity.addChangeListener(new ChangeListener() {
+ @Override
+ public void stateChanged(ChangeEvent e) {
+ intensityLabel.setText(
+ getIntensityDescription(target.getWindTurbulenceIntensity()));
+ windSpeedDeviation.stateChanged(e);
+ }
+ });
+ windSpeedDeviation.addChangeListener(new ChangeListener() {
+ @Override
+ public void stateChanged(ChangeEvent e) {
+ windTurbulenceIntensity.stateChanged(e);
+ }
+ });
+
+ // 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, "growx");
+
+ 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 +506,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 = "|";