From c53a7e4c05c42af9ee11eb8a0a81b2e75269b007 Mon Sep 17 00:00:00 2001 From: kruland2607 Date: Thu, 30 May 2013 15:46:47 -0500 Subject: [PATCH] Consolidated the SimulationEditDialog and SimulationPlotExportDialog into a single dialog which uses CardLayout to switch between contents. The new SimulationEditDialog is pretty smart about when it can support the plot view and continues to support multi-edit. Double-click in the SimulationPanel is a little smarter - it opens either the dialog in plot mode when appropriate. Fixed but in SimulationPanel where the status icon was not updated after running a simulation when plot button is pressed. --- .../openrocket/gui/main/SimulationPanel.java | 12 +- .../simulation/SimulationConditionsPanel.java | 441 ++++++++ .../gui/simulation/SimulationEditDialog.java | 1008 ++++------------- .../simulation/SimulationOptionsPanel.java | 294 +++++ .../SimulationPlotExportDialog.java | 105 -- 5 files changed, 941 insertions(+), 919 deletions(-) create mode 100644 core/src/net/sf/openrocket/gui/simulation/SimulationConditionsPanel.java create mode 100644 core/src/net/sf/openrocket/gui/simulation/SimulationOptionsPanel.java delete mode 100644 core/src/net/sf/openrocket/gui/simulation/SimulationPlotExportDialog.java diff --git a/core/src/net/sf/openrocket/gui/main/SimulationPanel.java b/core/src/net/sf/openrocket/gui/main/SimulationPanel.java index 558ca9ef6..bdb8c501d 100644 --- a/core/src/net/sf/openrocket/gui/main/SimulationPanel.java +++ b/core/src/net/sf/openrocket/gui/main/SimulationPanel.java @@ -36,7 +36,6 @@ import net.sf.openrocket.gui.adaptors.Column; import net.sf.openrocket.gui.adaptors.ColumnTableModel; import net.sf.openrocket.gui.components.StyledLabel; import net.sf.openrocket.gui.simulation.SimulationEditDialog; -import net.sf.openrocket.gui.simulation.SimulationPlotExportDialog; import net.sf.openrocket.gui.simulation.SimulationRunDialog; import net.sf.openrocket.gui.simulation.SimulationWarningDialog; import net.sf.openrocket.gui.util.Icons; @@ -233,10 +232,10 @@ public class SimulationPanel extends JPanel { SimulationPanel.this), document, sim).setVisible(true); } - new SimulationPlotExportDialog(SwingUtilities.getWindowAncestor(SimulationPanel.this), document, sim) - .setVisible(true); fireMaintainSelection(); + openDialog(sim); + } }); this.add(plotButton, "wrap para"); @@ -502,7 +501,6 @@ public class SimulationPanel extends JPanel { simulationTable.clearSelection(); simulationTable.addRowSelectionInterval(selected, selected); - // FIXME - do we want to check to open plot dialog? openDialog(document.getSimulations().get(selected)); } } else { @@ -563,7 +561,11 @@ public class SimulationPanel extends JPanel { } private void openDialog(final Simulation... sims) { - new SimulationEditDialog(SwingUtilities.getWindowAncestor(this), document, sims).setVisible(true); + SimulationEditDialog d = new SimulationEditDialog(SwingUtilities.getWindowAncestor(this), document, sims); + if (sims.length == 1 && sims[0].hasSimulationData()) { + d.setPlotMode(); + } + d.setVisible(true); fireMaintainSelection(); } diff --git a/core/src/net/sf/openrocket/gui/simulation/SimulationConditionsPanel.java b/core/src/net/sf/openrocket/gui/simulation/SimulationConditionsPanel.java new file mode 100644 index 000000000..2839704b1 --- /dev/null +++ b/core/src/net/sf/openrocket/gui/simulation/SimulationConditionsPanel.java @@ -0,0 +1,441 @@ +package net.sf.openrocket.gui.simulation; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.BorderFactory; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JSpinner; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; + +import net.miginfocom.swing.MigLayout; +import net.sf.openrocket.document.Simulation; +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.UnitSelector; +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.startup.Application; +import net.sf.openrocket.unit.UnitGroup; +import net.sf.openrocket.util.Chars; + +public class SimulationConditionsPanel extends JPanel { + private static final Translator trans = Application.getTranslator(); + + + SimulationConditionsPanel(final Simulation simulation) { + super(new MigLayout("fill")); + + final SimulationOptions conditions = simulation.getOptions(); + + JPanel sub; + String tip; + UnitSelector unit; + BasicSlider slider; + DoubleModel m; + JSpinner spin; + + //// Wind settings: Average wind speed, turbulence intensity, std. deviation + 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())); + } + }); + + + + + + //// Temperature and pressure + sub = new JPanel(new MigLayout("fill, gap rel unrel", + "[grow][65lp!][30lp!][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); + + m = new DoubleModel(conditions, "LaunchTemperature", UnitGroup.UNITS_TEMPERATURE, 0); + + spin = new JSpinner(m.getSpinnerModel()); + spin.setEditor(new SpinnerEditor(spin)); + spin.setToolTipText(tip); + isa.addEnableComponent(spin, false); + sub.add(spin, "w 65lp!"); + + unit = new UnitSelector(m); + unit.setToolTipText(tip); + isa.addEnableComponent(unit, false); + sub.add(unit, "growx"); + slider = new BasicSlider(m.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); + + m = new DoubleModel(conditions, "LaunchPressure", UnitGroup.UNITS_PRESSURE, 0); + + spin = new JSpinner(m.getSpinnerModel()); + spin.setEditor(new SpinnerEditor(spin)); + spin.setToolTipText(tip); + isa.addEnableComponent(spin, false); + sub.add(spin, "w 65lp!"); + + unit = new UnitSelector(m); + unit.setToolTipText(tip); + isa.addEnableComponent(unit, false); + sub.add(unit, "growx"); + slider = new BasicSlider(m.getSliderModel(0.950e5, 1.050e5)); + slider.setToolTipText(tip); + isa.addEnableComponent(slider, false); + sub.add(slider, "w 75lp, wrap"); + + + + + + //// 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"); + + + + // 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, + 0, 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(0, Math.PI / 9, + SimulationOptions.MAX_LAUNCH_ROD_ANGLE)); + slider.setToolTipText(tip); + sub.add(slider, "w 75lp, wrap"); + + + + // Direction: + label = new JLabel(trans.get("simedtdlg.lbl.Direction")); + //// Direction of the launch rod relative to the wind.
+ //// = towards the wind, + //// = downwind. + tip = trans.get("simedtdlg.lbl.ttip.Direction1") + + UnitGroup.UNITS_ANGLE.toStringUnit(0) + + " " + trans.get("simedtdlg.lbl.ttip.Direction2") + " " + + UnitGroup.UNITS_ANGLE.toStringUnit(Math.PI) + + " " + trans.get("simedtdlg.lbl.ttip.Direction3"); + label.setToolTipText(tip); + sub.add(label); + + m = new DoubleModel(conditions, "LaunchRodDirection", UnitGroup.UNITS_ANGLE, + -Math.PI, 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(-Math.PI, Math.PI)); + slider.setToolTipText(tip); + sub.add(slider, "w 75lp, wrap"); + + JButton restoreDefaults = new JButton(trans.get("simedtdlg.but.resettodefault")); + restoreDefaults.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + + DefaultSimulationOptionFactory f = Application.getInjector().getInstance(DefaultSimulationOptionFactory.class); + SimulationOptions defaults = f.getDefault(); + conditions.copyConditionsFrom(defaults); + + } + + }); + this.add(restoreDefaults, "span, split 3, skip, gapbottom para, gapright para, right"); + + JButton saveDefaults = new JButton(trans.get("simedtdlg.but.savedefault")); + saveDefaults.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + + DefaultSimulationOptionFactory f = Application.getInjector().getInstance(DefaultSimulationOptionFactory.class); + f.saveDefault(conditions); + + } + + }); + + this.add(saveDefaults, "gapbottom para, gapright para, right"); + + } + + 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"); + } + +} diff --git a/core/src/net/sf/openrocket/gui/simulation/SimulationEditDialog.java b/core/src/net/sf/openrocket/gui/simulation/SimulationEditDialog.java index 47634e048..9e16e1a02 100644 --- a/core/src/net/sf/openrocket/gui/simulation/SimulationEditDialog.java +++ b/core/src/net/sf/openrocket/gui/simulation/SimulationEditDialog.java @@ -1,59 +1,32 @@ package net.sf.openrocket.gui.simulation; -import java.awt.Component; +import java.awt.CardLayout; import java.awt.Window; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -import java.util.Arrays; -import javax.swing.AbstractListModel; -import javax.swing.BorderFactory; import javax.swing.JButton; -import javax.swing.JCheckBox; import javax.swing.JComboBox; import javax.swing.JDialog; import javax.swing.JLabel; -import javax.swing.JList; -import javax.swing.JOptionPane; import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.JSpinner; import javax.swing.JTabbedPane; import javax.swing.JTextField; -import javax.swing.ListCellRenderer; import javax.swing.SwingUtilities; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import net.miginfocom.swing.MigLayout; import net.sf.openrocket.document.OpenRocketDocument; import net.sf.openrocket.document.Simulation; -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.adaptors.EnumModel; import net.sf.openrocket.gui.adaptors.FlightConfigurationModel; -import net.sf.openrocket.gui.components.BasicSlider; -import net.sf.openrocket.gui.components.DescriptionArea; -import net.sf.openrocket.gui.components.UnitSelector; import net.sf.openrocket.gui.dialogs.flightconfiguration.FlightConfigurationDialog; import net.sf.openrocket.gui.util.GUIUtil; -import net.sf.openrocket.gui.util.Icons; import net.sf.openrocket.l10n.Translator; -import net.sf.openrocket.models.atmosphere.ExtendedISAModel; import net.sf.openrocket.rocketcomponent.Configuration; -import net.sf.openrocket.simulation.DefaultSimulationOptionFactory; -import net.sf.openrocket.simulation.RK4SimulationStepper; import net.sf.openrocket.simulation.SimulationOptions; -import net.sf.openrocket.simulation.listeners.SimulationListener; -import net.sf.openrocket.simulation.listeners.example.CSVSaveListener; import net.sf.openrocket.startup.Application; -import net.sf.openrocket.unit.UnitGroup; -import net.sf.openrocket.util.Chars; -import net.sf.openrocket.util.GeodeticComputationStrategy; public class SimulationEditDialog extends JDialog { @@ -65,6 +38,32 @@ public class SimulationEditDialog extends JDialog { private final Configuration configuration; private static final Translator trans = Application.getTranslator(); + JPanel cards; + private final static String EDITMODE = "EDIT"; + private final static String PLOTMODE = "PLOT"; + + private boolean isSingleEdit() { + return simulation.length == 1; + } + + private boolean allowsPlotMode() { + return simulation.length == 1 && simulation[0].hasSimulationData(); + } + + public void setEditMode() { + CardLayout cl = (CardLayout) (cards.getLayout()); + cl.show(cards, EDITMODE); + cards.validate(); + } + + public void setPlotMode() { + if (!allowsPlotMode()) { + return; + } + CardLayout cl = (CardLayout) (cards.getLayout()); + cl.show(cards, PLOTMODE); + cards.validate(); + } public SimulationEditDialog(Window parent, OpenRocketDocument document, Simulation... sims) { //// Edit simulation @@ -75,130 +74,200 @@ public class SimulationEditDialog extends JDialog { this.conditions = simulation[0].getOptions(); configuration = simulation[0].getConfiguration(); - JPanel mainPanel = new JPanel(new MigLayout("")); - - if (sims.length == 1) { - //// Simulation name: - mainPanel.add(new JLabel(trans.get("simedtdlg.lbl.Simname") + " "), "shrink"); - final JTextField field = new JTextField(simulation[0].getName()); - field.getDocument().addDocumentListener(new DocumentListener() { - @Override - public void changedUpdate(DocumentEvent e) { - setText(); - } - - @Override - public void insertUpdate(DocumentEvent e) { - setText(); - } - - @Override - public void removeUpdate(DocumentEvent e) { - setText(); - } - - private void setText() { - String name = field.getText(); - if (name == null || name.equals("")) - return; - //System.out.println("Setting name:" + name); - simulation[0].setName(name); + this.cards = new JPanel(new CardLayout()); + this.add(cards); + { + JPanel simEditPanel = new JPanel(new MigLayout("fill")); + + if (isSingleEdit()) { + //// Simulation name: + simEditPanel.add(new JLabel(trans.get("simedtdlg.lbl.Simname") + " "), "shrink"); + final JTextField field = new JTextField(simulation[0].getName()); + field.getDocument().addDocumentListener(new DocumentListener() { + @Override + public void changedUpdate(DocumentEvent e) { + setText(); + } - } - }); - mainPanel.add(field, "shrinky, growx, wrap"); + @Override + public void insertUpdate(DocumentEvent e) { + setText(); + } + + @Override + public void removeUpdate(DocumentEvent e) { + setText(); + } + + private void setText() { + String name = field.getText(); + if (name == null || name.equals("")) + return; + //System.out.println("Setting name:" + name); + simulation[0].setName(name); + + } + }); + simEditPanel.add(field, "shrinky, growx, wrap"); + + //// Flight selector + //// Flight configuration: + JLabel label = new JLabel(trans.get("simedtdlg.lbl.Flightcfg")); + //// Select the motor configuration to use. + label.setToolTipText(trans.get("simedtdlg.lbl.ttip.Flightcfg")); + simEditPanel.add(label, "shrink"); + + JComboBox combo = new JComboBox(new FlightConfigurationModel(configuration)); + //// Select the motor configuration to use. + combo.setToolTipText(trans.get("simedtdlg.combo.ttip.Flightcfg")); + combo.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + conditions.setMotorConfigurationID(configuration.getFlightConfigurationID()); + } + }); + simEditPanel.add(combo, "split 2, shrink"); + + //// Edit button + JButton button = new JButton(trans.get("simedtdlg.but.FlightcfgEdit")); + button.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + JDialog configDialog = new FlightConfigurationDialog(SimulationEditDialog.this.document.getRocket(), SwingUtilities.windowForComponent(SimulationEditDialog.this)); + configDialog.setVisible(true); + } + }); + simEditPanel.add(button, "shrink, wrap"); + } + JTabbedPane tabbedPane = new JTabbedPane(); - //// Flight selector - //// Flight configuration: - JLabel label = new JLabel(trans.get("simedtdlg.lbl.Flightcfg")); - //// Select the motor configuration to use. - label.setToolTipText(trans.get("simedtdlg.lbl.ttip.Flightcfg")); - mainPanel.add(label, "shrink"); + //// Launch conditions + tabbedPane.addTab(trans.get("simedtdlg.tab.Launchcond"), new SimulationConditionsPanel(simulation[0])); + //// Simulation options + tabbedPane.addTab(trans.get("simedtdlg.tab.Simopt"), new SimulationOptionsPanel(simulation[0])); - JComboBox combo = new JComboBox(new FlightConfigurationModel(configuration)); - //// Select the motor configuration to use. - combo.setToolTipText(trans.get("simedtdlg.combo.ttip.Flightcfg")); - combo.addActionListener(new ActionListener() { + tabbedPane.setSelectedIndex(0); + + simEditPanel.add(tabbedPane, "spanx, grow, wrap"); + + + //// Open Plot button + JButton button = new JButton("<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())); - } - }); - - - - - - //// Temperature and pressure - sub = new JPanel(new MigLayout("fill, gap rel unrel", - "[grow][65lp!][30lp!][75lp!]", "")); - //// Atmospheric conditions - sub.setBorder(BorderFactory.createTitledBorder(trans.get("simedtdlg.border.Atmoscond"))); - panel.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); - - m = new DoubleModel(conditions, "LaunchTemperature", UnitGroup.UNITS_TEMPERATURE, 0); - - spin = new JSpinner(m.getSpinnerModel()); - spin.setEditor(new SpinnerEditor(spin)); - spin.setToolTipText(tip); - isa.addEnableComponent(spin, false); - sub.add(spin, "w 65lp!"); - - unit = new UnitSelector(m); - unit.setToolTipText(tip); - isa.addEnableComponent(unit, false); - sub.add(unit, "growx"); - slider = new BasicSlider(m.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); - - m = new DoubleModel(conditions, "LaunchPressure", UnitGroup.UNITS_PRESSURE, 0); - - spin = new JSpinner(m.getSpinnerModel()); - spin.setEditor(new SpinnerEditor(spin)); - spin.setToolTipText(tip); - isa.addEnableComponent(spin, false); - sub.add(spin, "w 65lp!"); - - unit = new UnitSelector(m); - unit.setToolTipText(tip); - isa.addEnableComponent(unit, false); - sub.add(unit, "growx"); - slider = new BasicSlider(m.getSliderModel(0.950e5, 1.050e5)); - slider.setToolTipText(tip); - isa.addEnableComponent(slider, false); - sub.add(slider, "w 75lp, wrap"); - - - - - - //// 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"))); - panel.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"))); - panel.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"); - - - - // 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, - 0, 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(0, Math.PI / 9, - SimulationOptions.MAX_LAUNCH_ROD_ANGLE)); - slider.setToolTipText(tip); - sub.add(slider, "w 75lp, wrap"); - - - - // Direction: - label = new JLabel(trans.get("simedtdlg.lbl.Direction")); - //// Direction of the launch rod relative to the wind.
- //// = towards the wind, - //// = downwind. - tip = trans.get("simedtdlg.lbl.ttip.Direction1") + - UnitGroup.UNITS_ANGLE.toStringUnit(0) + - " " + trans.get("simedtdlg.lbl.ttip.Direction2") + " " + - UnitGroup.UNITS_ANGLE.toStringUnit(Math.PI) + - " " + trans.get("simedtdlg.lbl.ttip.Direction3"); - label.setToolTipText(tip); - sub.add(label); - - m = new DoubleModel(conditions, "LaunchRodDirection", UnitGroup.UNITS_ANGLE, - -Math.PI, 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(-Math.PI, Math.PI)); - slider.setToolTipText(tip); - sub.add(slider, "w 75lp, wrap"); - - JButton restoreDefaults = new JButton(trans.get("simedtdlg.but.resettodefault")); - restoreDefaults.addActionListener(new ActionListener() { - - @Override - public void actionPerformed(ActionEvent e) { - - DefaultSimulationOptionFactory f = Application.getInjector().getInstance(DefaultSimulationOptionFactory.class); - SimulationOptions defaults = f.getDefault(); - conditions.copyConditionsFrom(defaults); - - } - - }); - panel.add(restoreDefaults, "span, split 3, skip, gapbottom para, gapright para, right"); - - JButton saveDefaults = new JButton(trans.get("simedtdlg.but.savedefault")); - saveDefaults.addActionListener(new ActionListener() { - - @Override - public void actionPerformed(ActionEvent e) { - - DefaultSimulationOptionFactory f = Application.getInjector().getInstance(DefaultSimulationOptionFactory.class); - f.saveDefault(conditions); - - } - - }); - - panel.add(saveDefaults, "gapbottom para, gapright para, right"); - return panel; - } - - - 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"); - } - - - - private JPanel simulationOptionsTab() { - JPanel panel = new JPanel(new MigLayout("fill")); - JPanel sub, subsub; - String tip; - JLabel label; - DoubleModel m; - JSpinner spin; - UnitSelector unit; - BasicSlider slider; - - - //// Simulation options - sub = new JPanel(new MigLayout("fill, gap rel unrel", - "[grow][65lp!][30lp!][75lp!]", "")); - //// Simulator options - sub.setBorder(BorderFactory.createTitledBorder(trans.get("simedtdlg.border.Simopt"))); - panel.add(sub, "growx, growy, aligny 0"); - - - // Separate panel for computation methods, as they use a different layout - subsub = new JPanel(new MigLayout("insets 0, fill")); - - - //// Calculation method: - tip = trans.get("simedtdlg.lbl.ttip.Calcmethod"); - label = new JLabel(trans.get("simedtdlg.lbl.Calcmethod")); - label.setToolTipText(tip); - subsub.add(label, "gapright para"); - - //// Extended Barrowman - label = new JLabel(trans.get("simedtdlg.lbl.ExtBarrowman")); - label.setToolTipText(tip); - subsub.add(label, "growx, wrap para"); - - - // Simulation method - tip = trans.get("simedtdlg.lbl.ttip.Simmethod1") + - trans.get("simedtdlg.lbl.ttip.Simmethod2"); - label = new JLabel(trans.get("simedtdlg.lbl.Simmethod")); - label.setToolTipText(tip); - subsub.add(label, "gapright para"); - - label = new JLabel("6-DOF Runge-Kutta 4"); - label.setToolTipText(tip); - subsub.add(label, "growx, wrap para"); - - - //// Geodetic calculation method: - label = new JLabel(trans.get("simedtdlg.lbl.GeodeticMethod")); - label.setToolTipText(trans.get("simedtdlg.lbl.ttip.GeodeticMethodTip")); - subsub.add(label, "gapright para"); - - EnumModel gcsModel = new EnumModel(conditions, "GeodeticComputation"); - final JComboBox gcsCombo = new JComboBox(gcsModel); - ActionListener gcsTTipListener = new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - GeodeticComputationStrategy gcs = (GeodeticComputationStrategy) gcsCombo.getSelectedItem(); - gcsCombo.setToolTipText(gcs.getDescription()); - } - }; - gcsCombo.addActionListener(gcsTTipListener); - gcsTTipListener.actionPerformed(null); - subsub.add(gcsCombo, "growx, wrap para"); - - sub.add(subsub, "spanx, wrap para"); - - - //// Time step: - label = new JLabel(trans.get("simedtdlg.lbl.Timestep")); - tip = trans.get("simedtdlg.lbl.ttip.Timestep1") + - trans.get("simedtdlg.lbl.ttip.Timestep2") + " " + - UnitGroup.UNITS_TIME_STEP.toStringUnit(RK4SimulationStepper.RECOMMENDED_TIME_STEP) + - "."; - label.setToolTipText(tip); - sub.add(label); - - m = new DoubleModel(conditions, "TimeStep", UnitGroup.UNITS_TIME_STEP, 0, 1); - - spin = new JSpinner(m.getSpinnerModel()); - spin.setEditor(new SpinnerEditor(spin)); - spin.setToolTipText(tip); - sub.add(spin, "w 65lp!"); - //sub.add(spin, "nogrid"); - - unit = new UnitSelector(m); - unit.setToolTipText(tip); - sub.add(unit, "w 25"); - //sub.add(unit, "nogrid"); - slider = new BasicSlider(m.getSliderModel(0, 0.2)); - slider.setToolTipText(tip); - sub.add(slider, "w 75lp, wrap"); - //sub.add(slider,"wrap"); - - - - - //// Reset to default button - JButton button = new JButton(trans.get("simedtdlg.but.resettodefault")); - //// Reset the time step to its default value ( - button.setToolTipText(trans.get("simedtdlg.but.ttip.resettodefault") + - UnitGroup.UNITS_SHORT_TIME.toStringUnit(RK4SimulationStepper.RECOMMENDED_TIME_STEP) + - ")."); - button.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - conditions.setTimeStep(RK4SimulationStepper.RECOMMENDED_TIME_STEP); - conditions.setGeodeticComputation(GeodeticComputationStrategy.SPHERICAL); - } - }); - - sub.add(button, "align left"); - - - - - //// Simulation listeners - sub = new JPanel(new MigLayout("fill, gap 0 0")); - //// Simulator listeners - sub.setBorder(BorderFactory.createTitledBorder(trans.get("simedtdlg.border.Simlist"))); - panel.add(sub, "growx, growy"); - - - DescriptionArea desc = new DescriptionArea(5); - //// Simulation listeners is an advanced feature that allows user-written code to listen to and interact with the simulation. - //// For details on writing simulation listeners, see the OpenRocket technical documentation. - desc.setText(trans.get("simedtdlg.txt.longA1") + - trans.get("simedtdlg.txt.longA2")); - sub.add(desc, "aligny 0, growx, wrap para"); - - //// Current listeners: - label = new JLabel(trans.get("simedtdlg.lbl.Curlist")); - sub.add(label, "spanx, wrap rel"); - - final ListenerListModel listenerModel = new ListenerListModel(); - final JList list = new JList(listenerModel); - list.setCellRenderer(new ListenerCellRenderer()); - JScrollPane scroll = new JScrollPane(list); - // scroll.setPreferredSize(new Dimension(1,1)); - sub.add(scroll, "height 1px, grow, wrap rel"); - - //// Add button - button = new JButton(trans.get("simedtdlg.but.add")); - button.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - String previous = Application.getPreferences().getString("previousListenerName", ""); - String input = (String) JOptionPane.showInputDialog(SimulationEditDialog.this, - new Object[] { - //// Type the full Java class name of the simulation listener, for example: - "Type the full Java class name of the simulation listener, for example:", - "" + CSVSaveListener.class.getName() + "" }, - //// Add simulation listener - trans.get("simedtdlg.lbl.Addsimlist"), - JOptionPane.QUESTION_MESSAGE, - null, null, - previous - ); - if (input == null || input.equals("")) - return; - - Application.getPreferences().putString("previousListenerName", input); - simulation[0].getSimulationListeners().add(input); - listenerModel.fireContentsChanged(); - } - }); - sub.add(button, "split 2, sizegroup buttons, alignx 50%, gapright para"); - - //// Remove button - button = new JButton(trans.get("simedtdlg.but.remove")); - button.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - int[] selected = list.getSelectedIndices(); - Arrays.sort(selected); - for (int i = selected.length - 1; i >= 0; i--) { - simulation[0].getSimulationListeners().remove(selected[i]); - } - listenerModel.fireContentsChanged(); - } - }); - sub.add(button, "sizegroup buttons, alignx 50%"); - - - return panel; - } - - - private class ListenerListModel extends AbstractListModel { - @Override - public String getElementAt(int index) { - if (index < 0 || index >= getSize()) - return null; - return simulation[0].getSimulationListeners().get(index); - } - - @Override - public int getSize() { - return simulation[0].getSimulationListeners().size(); - } - - public void fireContentsChanged() { - super.fireContentsChanged(this, 0, getSize()); - } - } - - - - - - /** - * Return a panel stating that there is no data available, and that the user - * should run the simulation first. - */ - public static JPanel noDataPanel() { - JPanel panel = new JPanel(new MigLayout("fill")); - - // No data available - //// No flight data available. - panel.add(new JLabel(trans.get("simedtdlg.lbl.Noflightdata")), - "alignx 50%, aligny 100%, wrap para"); - //// Please run the simulation first. - panel.add(new JLabel(trans.get("simedtdlg.lbl.runsimfirst")), - "alignx 50%, aligny 0%, wrap"); - return panel; - } - - - - private class ListenerCellRenderer extends JLabel implements ListCellRenderer { - - @Override - public Component getListCellRendererComponent(JList list, Object value, - int index, boolean isSelected, boolean cellHasFocus) { - String s = value.toString(); - setText(s); - - // Attempt instantiating, catch any exceptions - Exception ex = null; - try { - Class c = Class.forName(s); - @SuppressWarnings("unused") - SimulationListener l = (SimulationListener) c.newInstance(); - } catch (Exception e) { - ex = e; - } - - if (ex == null) { - setIcon(Icons.SIMULATION_LISTENER_OK); - //// Listener instantiated successfully. - setToolTipText("Listener instantiated successfully."); - } else { - setIcon(Icons.SIMULATION_LISTENER_ERROR); - //// Unable to instantiate listener due to exception:
- setToolTipText("Unable to instantiate listener due to exception:
" + - ex.toString()); - } - - if (isSelected) { - setBackground(list.getSelectionBackground()); - setForeground(list.getSelectionForeground()); - } else { - setBackground(list.getBackground()); - setForeground(list.getForeground()); - } - setOpaque(true); - return this; - } - } } diff --git a/core/src/net/sf/openrocket/gui/simulation/SimulationOptionsPanel.java b/core/src/net/sf/openrocket/gui/simulation/SimulationOptionsPanel.java new file mode 100644 index 000000000..c7b0fe023 --- /dev/null +++ b/core/src/net/sf/openrocket/gui/simulation/SimulationOptionsPanel.java @@ -0,0 +1,294 @@ +package net.sf.openrocket.gui.simulation; + +import java.awt.Component; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.Arrays; + +import javax.swing.AbstractListModel; +import javax.swing.BorderFactory; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JSpinner; +import javax.swing.ListCellRenderer; +import javax.swing.SwingUtilities; + +import net.miginfocom.swing.MigLayout; +import net.sf.openrocket.document.Simulation; +import net.sf.openrocket.gui.SpinnerEditor; +import net.sf.openrocket.gui.adaptors.DoubleModel; +import net.sf.openrocket.gui.adaptors.EnumModel; +import net.sf.openrocket.gui.components.BasicSlider; +import net.sf.openrocket.gui.components.DescriptionArea; +import net.sf.openrocket.gui.components.UnitSelector; +import net.sf.openrocket.gui.util.Icons; +import net.sf.openrocket.l10n.Translator; +import net.sf.openrocket.simulation.RK4SimulationStepper; +import net.sf.openrocket.simulation.SimulationOptions; +import net.sf.openrocket.simulation.listeners.SimulationListener; +import net.sf.openrocket.simulation.listeners.example.CSVSaveListener; +import net.sf.openrocket.startup.Application; +import net.sf.openrocket.unit.UnitGroup; +import net.sf.openrocket.util.GeodeticComputationStrategy; + +class SimulationOptionsPanel extends JPanel { + + private static final Translator trans = Application.getTranslator(); + + final Simulation simulation; + + SimulationOptionsPanel(final Simulation simulation) { + super(new MigLayout("fill")); + this.simulation = simulation; + + final SimulationOptions conditions = simulation.getOptions(); + + JPanel sub, subsub; + String tip; + JLabel label; + DoubleModel m; + JSpinner spin; + UnitSelector unit; + BasicSlider slider; + + + //// Simulation options + sub = new JPanel(new MigLayout("fill, gap rel unrel", + "[grow][65lp!][30lp!][75lp!]", "")); + //// Simulator options + sub.setBorder(BorderFactory.createTitledBorder(trans.get("simedtdlg.border.Simopt"))); + this.add(sub, "growx, growy, aligny 0"); + + + // Separate panel for computation methods, as they use a different layout + subsub = new JPanel(new MigLayout("insets 0, fill")); + + + //// Calculation method: + tip = trans.get("simedtdlg.lbl.ttip.Calcmethod"); + label = new JLabel(trans.get("simedtdlg.lbl.Calcmethod")); + label.setToolTipText(tip); + subsub.add(label, "gapright para"); + + //// Extended Barrowman + label = new JLabel(trans.get("simedtdlg.lbl.ExtBarrowman")); + label.setToolTipText(tip); + subsub.add(label, "growx, wrap para"); + + + // Simulation method + tip = trans.get("simedtdlg.lbl.ttip.Simmethod1") + + trans.get("simedtdlg.lbl.ttip.Simmethod2"); + label = new JLabel(trans.get("simedtdlg.lbl.Simmethod")); + label.setToolTipText(tip); + subsub.add(label, "gapright para"); + + label = new JLabel("6-DOF Runge-Kutta 4"); + label.setToolTipText(tip); + subsub.add(label, "growx, wrap para"); + + + //// Geodetic calculation method: + label = new JLabel(trans.get("simedtdlg.lbl.GeodeticMethod")); + label.setToolTipText(trans.get("simedtdlg.lbl.ttip.GeodeticMethodTip")); + subsub.add(label, "gapright para"); + + EnumModel gcsModel = new EnumModel(conditions, "GeodeticComputation"); + final JComboBox gcsCombo = new JComboBox(gcsModel); + ActionListener gcsTTipListener = new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + GeodeticComputationStrategy gcs = (GeodeticComputationStrategy) gcsCombo.getSelectedItem(); + gcsCombo.setToolTipText(gcs.getDescription()); + } + }; + gcsCombo.addActionListener(gcsTTipListener); + gcsTTipListener.actionPerformed(null); + subsub.add(gcsCombo, "growx, wrap para"); + + sub.add(subsub, "spanx, wrap para"); + + + //// Time step: + label = new JLabel(trans.get("simedtdlg.lbl.Timestep")); + tip = trans.get("simedtdlg.lbl.ttip.Timestep1") + + trans.get("simedtdlg.lbl.ttip.Timestep2") + " " + + UnitGroup.UNITS_TIME_STEP.toStringUnit(RK4SimulationStepper.RECOMMENDED_TIME_STEP) + + "."; + label.setToolTipText(tip); + sub.add(label); + + m = new DoubleModel(conditions, "TimeStep", UnitGroup.UNITS_TIME_STEP, 0, 1); + + spin = new JSpinner(m.getSpinnerModel()); + spin.setEditor(new SpinnerEditor(spin)); + spin.setToolTipText(tip); + sub.add(spin, "w 65lp!"); + //sub.add(spin, "nogrid"); + + unit = new UnitSelector(m); + unit.setToolTipText(tip); + sub.add(unit, "w 25"); + //sub.add(unit, "nogrid"); + slider = new BasicSlider(m.getSliderModel(0, 0.2)); + slider.setToolTipText(tip); + sub.add(slider, "w 75lp, wrap"); + //sub.add(slider,"wrap"); + + + + + //// Reset to default button + JButton button = new JButton(trans.get("simedtdlg.but.resettodefault")); + //// Reset the time step to its default value ( + button.setToolTipText(trans.get("simedtdlg.but.ttip.resettodefault") + + UnitGroup.UNITS_SHORT_TIME.toStringUnit(RK4SimulationStepper.RECOMMENDED_TIME_STEP) + + ")."); + button.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + conditions.setTimeStep(RK4SimulationStepper.RECOMMENDED_TIME_STEP); + conditions.setGeodeticComputation(GeodeticComputationStrategy.SPHERICAL); + } + }); + + sub.add(button, "align left"); + + + + + //// Simulation listeners + sub = new JPanel(new MigLayout("fill, gap 0 0")); + //// Simulator listeners + sub.setBorder(BorderFactory.createTitledBorder(trans.get("simedtdlg.border.Simlist"))); + this.add(sub, "growx, growy"); + + + DescriptionArea desc = new DescriptionArea(5); + //// Simulation listeners is an advanced feature that allows user-written code to listen to and interact with the simulation. + //// For details on writing simulation listeners, see the OpenRocket technical documentation. + desc.setText(trans.get("simedtdlg.txt.longA1") + + trans.get("simedtdlg.txt.longA2")); + sub.add(desc, "aligny 0, growx, wrap para"); + + //// Current listeners: + label = new JLabel(trans.get("simedtdlg.lbl.Curlist")); + sub.add(label, "spanx, wrap rel"); + + final ListenerListModel listenerModel = new ListenerListModel(); + final JList list = new JList(listenerModel); + list.setCellRenderer(new ListenerCellRenderer()); + JScrollPane scroll = new JScrollPane(list); + // scroll.setPreferredSize(new Dimension(1,1)); + sub.add(scroll, "height 1px, grow, wrap rel"); + + //// Add button + button = new JButton(trans.get("simedtdlg.but.add")); + button.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + String previous = Application.getPreferences().getString("previousListenerName", ""); + String input = (String) JOptionPane.showInputDialog(SwingUtilities.getRoot(SimulationOptionsPanel.this), + new Object[] { + //// Type the full Java class name of the simulation listener, for example: + "Type the full Java class name of the simulation listener, for example:", + "" + CSVSaveListener.class.getName() + "" }, + //// Add simulation listener + trans.get("simedtdlg.lbl.Addsimlist"), + JOptionPane.QUESTION_MESSAGE, + null, null, + previous + ); + if (input == null || input.equals("")) + return; + + Application.getPreferences().putString("previousListenerName", input); + simulation.getSimulationListeners().add(input); + listenerModel.fireContentsChanged(); + } + }); + sub.add(button, "split 2, sizegroup buttons, alignx 50%, gapright para"); + + //// Remove button + button = new JButton(trans.get("simedtdlg.but.remove")); + button.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + int[] selected = list.getSelectedIndices(); + Arrays.sort(selected); + for (int i = selected.length - 1; i >= 0; i--) { + simulation.getSimulationListeners().remove(selected[i]); + } + listenerModel.fireContentsChanged(); + } + }); + sub.add(button, "sizegroup buttons, alignx 50%"); + + + } + + private class ListenerCellRenderer extends JLabel implements ListCellRenderer { + + @Override + public Component getListCellRendererComponent(JList list, Object value, + int index, boolean isSelected, boolean cellHasFocus) { + String s = value.toString(); + setText(s); + + // Attempt instantiating, catch any exceptions + Exception ex = null; + try { + Class c = Class.forName(s); + @SuppressWarnings("unused") + SimulationListener l = (SimulationListener) c.newInstance(); + } catch (Exception e) { + ex = e; + } + + if (ex == null) { + setIcon(Icons.SIMULATION_LISTENER_OK); + //// Listener instantiated successfully. + setToolTipText("Listener instantiated successfully."); + } else { + setIcon(Icons.SIMULATION_LISTENER_ERROR); + //// Unable to instantiate listener due to exception:
+ setToolTipText("Unable to instantiate listener due to exception:
" + + ex.toString()); + } + + if (isSelected) { + setBackground(list.getSelectionBackground()); + setForeground(list.getSelectionForeground()); + } else { + setBackground(list.getBackground()); + setForeground(list.getForeground()); + } + setOpaque(true); + return this; + } + } + + private class ListenerListModel extends AbstractListModel { + @Override + public String getElementAt(int index) { + if (index < 0 || index >= getSize()) + return null; + return simulation.getSimulationListeners().get(index); + } + + @Override + public int getSize() { + return simulation.getSimulationListeners().size(); + } + + public void fireContentsChanged() { + super.fireContentsChanged(this, 0, getSize()); + } + } + +} diff --git a/core/src/net/sf/openrocket/gui/simulation/SimulationPlotExportDialog.java b/core/src/net/sf/openrocket/gui/simulation/SimulationPlotExportDialog.java deleted file mode 100644 index d82ac605b..000000000 --- a/core/src/net/sf/openrocket/gui/simulation/SimulationPlotExportDialog.java +++ /dev/null @@ -1,105 +0,0 @@ -package net.sf.openrocket.gui.simulation; - -import java.awt.Window; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; - -import javax.swing.JButton; -import javax.swing.JDialog; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JTabbedPane; -import javax.swing.JTextField; - -import net.miginfocom.swing.MigLayout; -import net.sf.openrocket.document.OpenRocketDocument; -import net.sf.openrocket.document.Simulation; -import net.sf.openrocket.gui.util.GUIUtil; -import net.sf.openrocket.l10n.Translator; -import net.sf.openrocket.startup.Application; - -public class SimulationPlotExportDialog extends JDialog { - - private final Window parentWindow; - private final Simulation simulation; - private static final Translator trans = Application.getTranslator(); - - public SimulationPlotExportDialog(Window parent, final OpenRocketDocument document, Simulation s) { - //// Plot/Export simulation - super(parent, trans.get("simedtdlg.title.Editsim"), JDialog.ModalityType.DOCUMENT_MODAL); - this.parentWindow = parent; - this.simulation = s; - - JPanel mainPanel = new JPanel(new MigLayout("fill", "[grow]")); - - //// Simulation name: - mainPanel.add(new JLabel(trans.get("simedtdlg.lbl.Simname") + " "), "span, split 2, shrink"); - final JTextField field = new JTextField(simulation.getName()); - field.setEditable(false); - mainPanel.add(field, "shrinky, growx, wrap"); - - final JTabbedPane tabbedPane = new JTabbedPane(); - - //// Plot data - final SimulationPlotPanel plotTab = new SimulationPlotPanel(simulation); - tabbedPane.addTab(trans.get("simedtdlg.tab.Plotdata"), plotTab); - //// Export data - final SimulationExportPanel exportTab = new SimulationExportPanel(simulation); - tabbedPane.addTab(trans.get("simedtdlg.tab.Exportdata"), exportTab); - - mainPanel.add(tabbedPane, "grow, wrap"); - - JButton button = new JButton("<