Rework simulation ui. Added support for default flight conditions.
Editing of flight conditions on multiple simulations. Changed exceptions generated in simulation to still produce data.
This commit is contained in:
parent
b1b2bc5abe
commit
f0ae25615e
@ -306,6 +306,7 @@ PreferencesDialog.lbl.languageEffect = The language will change the next time yo
|
||||
! Simulation edit dialog
|
||||
simedtdlg.but.runsimulation = Run simulation
|
||||
simedtdlg.but.resettodefault = Reset to default
|
||||
simedtdlg.but.savedefault = Save as default
|
||||
simedtdlg.but.add = Add
|
||||
simedtdlg.but.remove = Remove
|
||||
simedtdlg.title.Editsim = Edit simulation
|
||||
@ -438,12 +439,6 @@ SimuRunDlg.lbl.Altitude = Altitude:
|
||||
SimuRunDlg.lbl.Velocity = Velocity:
|
||||
SimuRunDlg.msg.Unabletosim = Unable to simulate:
|
||||
SimuRunDlg.msg.errorOccurred = An error occurred during the simulation:
|
||||
SimuRunDlg.msg.AnException1 = An exception occurred during the simulation:
|
||||
SimuRunDlg.msg.AnException2 = Please report this as a bug along with the details below.
|
||||
SimuRunDlg.msg.AssertionError1 = A computation error occurred during the simulation.
|
||||
SimuRunDlg.msg.AssertionError2 = Please report this as a bug along with the details below.
|
||||
SimuRunDlg.msg.unknownerror1 = An unknown error was encountered during the simulation.
|
||||
SimuRunDlg.msg.unknownerror2 = The program may be unstable, you should save all your designs and restart OpenRocket now!
|
||||
|
||||
|
||||
RK4SimulationStepper.error.valuesTooLarge = Simulation values exceeded limits. Try selecting a shorter time step.
|
||||
@ -468,7 +463,6 @@ SimExpPan.checkbox.Incflightevents = Include flight events
|
||||
SimExpPan.checkbox.ttip.Incflightevents = Include a comment line for every flight event.
|
||||
SimExpPan.lbl.Commentchar = Comment character:
|
||||
SimExpPan.lbl.ttip.Commentchar = The character(s) that mark a comment line.
|
||||
SimExpPan.but.Exporttofile = Export to file...
|
||||
SimExpPan.Fileexists.desc1 = File \"
|
||||
SimExpPan.Fileexists.desc2 = \" exists. Overwrite?
|
||||
SimExpPan.Fileexists.title = File exists
|
||||
@ -581,7 +575,6 @@ simplotpanel.lbl.Flightevents = Flight events:
|
||||
simplotpanel.but.All = All
|
||||
simplotpanel.but.None = None
|
||||
simplotpanel.but.NewYaxisplottype = New Y axis plot type
|
||||
simplotpanel.but.Plotflight = Plot flight
|
||||
simplotpanel.lbl.Axis = Axis:
|
||||
simplotpanel.but.ttip.Removethisplot = Remove this plot
|
||||
simplotpanel.Desc = The data will be plotted in time order even if the X axis type is not time.
|
||||
@ -1394,6 +1387,7 @@ FlightEvent.Type.GROUND_HIT = Ground hit
|
||||
FlightEvent.Type.SIMULATION_END = Simulation end
|
||||
FlightEvent.Type.ALTITUDE = Altitude change
|
||||
FlightEvent.Type.TUMBLE = Tumbling
|
||||
FlightEvent.Type.EXCEPTION = Exception
|
||||
|
||||
! ThrustCurveMotorColumns
|
||||
TCurveMotorCol.MANUFACTURER = Manufacturer
|
||||
|
@ -325,4 +325,7 @@ public abstract class Warning {
|
||||
|
||||
public static final Warning RECOVERY_LAUNCH_ROD =
|
||||
new Other(trans.get("Warning.RECOVERY_LAUNCH_ROD"));
|
||||
|
||||
public static final Warning SIMULATION_EXCEPTION =
|
||||
new Other("Exception during simulation");
|
||||
}
|
||||
|
@ -23,9 +23,6 @@ import javax.swing.ListSelectionModel;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.table.DefaultTableCellRenderer;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import net.sf.openrocket.aerodynamics.Warning;
|
||||
import net.sf.openrocket.aerodynamics.WarningSet;
|
||||
@ -38,6 +35,10 @@ import net.sf.openrocket.formatting.RocketDescriptor;
|
||||
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;
|
||||
import net.sf.openrocket.l10n.Translator;
|
||||
import net.sf.openrocket.rocketcomponent.ComponentChangeEvent;
|
||||
@ -48,6 +49,9 @@ import net.sf.openrocket.startup.Application;
|
||||
import net.sf.openrocket.startup.Preferences;
|
||||
import net.sf.openrocket.unit.UnitGroup;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class SimulationPanel extends JPanel {
|
||||
private static final Logger log = LoggerFactory.getLogger(SimulationPanel.class);
|
||||
private static final Translator trans = Application.getTranslator();
|
||||
@ -68,13 +72,14 @@ public class SimulationPanel extends JPanel {
|
||||
private final ColumnTableModel simulationTableModel;
|
||||
private final JTable simulationTable;
|
||||
|
||||
private final JButton editButton;
|
||||
private final JButton runButton;
|
||||
private final JButton deleteButton;
|
||||
private final JButton plotButton;
|
||||
|
||||
public SimulationPanel(OpenRocketDocument doc) {
|
||||
super(new MigLayout("fill", "[grow][][][][][][grow]"));
|
||||
|
||||
JButton button;
|
||||
|
||||
|
||||
this.document = doc;
|
||||
|
||||
|
||||
@ -82,51 +87,54 @@ public class SimulationPanel extends JPanel {
|
||||
//////// The simulation action buttons
|
||||
|
||||
//// New simulation button
|
||||
button = new JButton(trans.get("simpanel.but.newsimulation"));
|
||||
//// Add a new simulation
|
||||
button.setToolTipText(trans.get("simpanel.but.ttip.newsimulation"));
|
||||
button.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
Simulation sim = new Simulation(document.getRocket());
|
||||
sim.setName(document.getNextSimulationName());
|
||||
|
||||
int n = document.getSimulationCount();
|
||||
document.addSimulation(sim);
|
||||
simulationTableModel.fireTableDataChanged();
|
||||
simulationTable.clearSelection();
|
||||
simulationTable.addRowSelectionInterval(n, n);
|
||||
|
||||
openDialog(sim, SimulationEditDialog.EDIT);
|
||||
}
|
||||
});
|
||||
this.add(button, "skip 1, gapright para");
|
||||
{
|
||||
JButton button = new JButton(trans.get("simpanel.but.newsimulation"));
|
||||
//// Add a new simulation
|
||||
button.setToolTipText(trans.get("simpanel.but.ttip.newsimulation"));
|
||||
button.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
Simulation sim = new Simulation(document.getRocket());
|
||||
sim.setName(document.getNextSimulationName());
|
||||
|
||||
int n = document.getSimulationCount();
|
||||
document.addSimulation(sim);
|
||||
simulationTableModel.fireTableDataChanged();
|
||||
simulationTable.clearSelection();
|
||||
simulationTable.addRowSelectionInterval(n, n);
|
||||
|
||||
openDialog(sim);
|
||||
}
|
||||
});
|
||||
this.add(button, "skip 1, gapright para");
|
||||
}
|
||||
|
||||
//// Edit simulation button
|
||||
button = new JButton(trans.get("simpanel.but.editsimulation"));
|
||||
editButton = new JButton(trans.get("simpanel.but.editsimulation"));
|
||||
//// Edit the selected simulation
|
||||
button.setToolTipText(trans.get("simpanel.but.ttip.editsim"));
|
||||
button.addActionListener(new ActionListener() {
|
||||
editButton.setToolTipText(trans.get("simpanel.but.ttip.editsim"));
|
||||
editButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
int selected = simulationTable.getSelectedRow();
|
||||
if (selected < 0)
|
||||
return; // TODO: MEDIUM: "None selected" dialog
|
||||
int[] selection = simulationTable.getSelectedRows();
|
||||
if (selection.length == 0)
|
||||
return; // TODO: LOW: "None selected" dialog
|
||||
|
||||
selected = simulationTable.convertRowIndexToModel(selected);
|
||||
simulationTable.clearSelection();
|
||||
simulationTable.addRowSelectionInterval(selected, selected);
|
||||
|
||||
openDialog(document.getSimulations().get(selected), SimulationEditDialog.EDIT);
|
||||
Simulation[] sims = new Simulation[selection.length];
|
||||
for (int i = 0; i < selection.length; i++) {
|
||||
selection[i] = simulationTable.convertRowIndexToModel(selection[i]);
|
||||
sims[i] = document.getSimulation(selection[i]);
|
||||
}
|
||||
openDialog(sims);
|
||||
}
|
||||
});
|
||||
this.add(button, "gapright para");
|
||||
this.add(editButton, "gapright para");
|
||||
|
||||
//// Run simulations
|
||||
button = new JButton(trans.get("simpanel.but.runsimulations"));
|
||||
runButton = new JButton(trans.get("simpanel.but.runsimulations"));
|
||||
//// Re-run the selected simulations
|
||||
button.setToolTipText(trans.get("simpanel.but.ttip.runsimu"));
|
||||
button.addActionListener(new ActionListener() {
|
||||
runButton.setToolTipText(trans.get("simpanel.but.ttip.runsimu"));
|
||||
runButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
int[] selection = simulationTable.getSelectedRows();
|
||||
@ -146,13 +154,13 @@ public class SimulationPanel extends JPanel {
|
||||
fireMaintainSelection();
|
||||
}
|
||||
});
|
||||
this.add(button, "gapright para");
|
||||
this.add(runButton, "gapright para");
|
||||
|
||||
//// Delete simulations button
|
||||
button = new JButton(trans.get("simpanel.but.deletesimulations"));
|
||||
deleteButton = new JButton(trans.get("simpanel.but.deletesimulations"));
|
||||
//// Delete the selected simulations
|
||||
button.setToolTipText(trans.get("simpanel.but.ttip.deletesim"));
|
||||
button.addActionListener(new ActionListener() {
|
||||
deleteButton.setToolTipText(trans.get("simpanel.but.ttip.deletesim"));
|
||||
deleteButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
int[] selection = simulationTable.getSelectedRows();
|
||||
@ -201,12 +209,12 @@ public class SimulationPanel extends JPanel {
|
||||
simulationTableModel.fireTableDataChanged();
|
||||
}
|
||||
});
|
||||
this.add(button, "gapright para");
|
||||
this.add(deleteButton, "gapright para");
|
||||
|
||||
//// Plot / export button
|
||||
button = new JButton(trans.get("simpanel.but.plotexport"));
|
||||
plotButton = new JButton(trans.get("simpanel.but.plotexport"));
|
||||
// button = new JButton("Plot flight");
|
||||
button.addActionListener(new ActionListener() {
|
||||
plotButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
int selected = simulationTable.getSelectedRow();
|
||||
@ -217,10 +225,21 @@ public class SimulationPanel extends JPanel {
|
||||
simulationTable.clearSelection();
|
||||
simulationTable.addRowSelectionInterval(selected, selected);
|
||||
|
||||
openDialog(document.getSimulations().get(selected), SimulationEditDialog.PLOT);
|
||||
|
||||
Simulation sim = document.getSimulations().get(selected);
|
||||
|
||||
if (sim.getSimulatedData() == null || sim.getSimulatedData().getBranchCount() == 0) {
|
||||
new SimulationRunDialog(SwingUtilities.getWindowAncestor(
|
||||
SimulationPanel.this), document, sim).setVisible(true);
|
||||
}
|
||||
|
||||
new SimulationPlotExportDialog(SwingUtilities.getWindowAncestor(SimulationPanel.this), document, sim)
|
||||
.setVisible(true);
|
||||
fireMaintainSelection();
|
||||
|
||||
}
|
||||
});
|
||||
this.add(button, "wrap para");
|
||||
this.add(plotButton, "wrap para");
|
||||
|
||||
|
||||
|
||||
@ -474,13 +493,20 @@ public class SimulationPanel extends JPanel {
|
||||
int selected = simulationTable.getSelectedRow();
|
||||
if (selected < 0)
|
||||
return;
|
||||
|
||||
selected = simulationTable.convertRowIndexToModel(selected);
|
||||
simulationTable.clearSelection();
|
||||
simulationTable.addRowSelectionInterval(selected, selected);
|
||||
|
||||
openDialog(document.getSimulations().get(selected),
|
||||
SimulationEditDialog.DEFAULT);
|
||||
int column = simulationTable.columnAtPoint(e.getPoint());
|
||||
if (column == 0) {
|
||||
SimulationWarningDialog.showWarningDialog(SimulationPanel.this, document.getSimulations().get(selected));
|
||||
} else {
|
||||
simulationTable.clearSelection();
|
||||
simulationTable.addRowSelectionInterval(selected, selected);
|
||||
|
||||
// FIXME - do we want to check to open plot dialog?
|
||||
openDialog(document.getSimulations().get(selected));
|
||||
}
|
||||
} else {
|
||||
updateButtonStates();
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -509,17 +535,35 @@ public class SimulationPanel extends JPanel {
|
||||
JScrollPane scrollpane = new JScrollPane(simulationTable);
|
||||
this.add(scrollpane, "spanx, grow, wrap rel");
|
||||
|
||||
|
||||
updateButtonStates();
|
||||
}
|
||||
|
||||
private void updateButtonStates() {
|
||||
int[] selection = simulationTable.getSelectedRows();
|
||||
if (selection.length == 0) {
|
||||
editButton.setEnabled(false);
|
||||
runButton.setEnabled(false);
|
||||
deleteButton.setEnabled(false);
|
||||
plotButton.setEnabled(false);
|
||||
} else {
|
||||
if (selection.length > 1) {
|
||||
plotButton.setEnabled(false);
|
||||
} else {
|
||||
plotButton.setEnabled(true);
|
||||
}
|
||||
editButton.setEnabled(true);
|
||||
runButton.setEnabled(true);
|
||||
deleteButton.setEnabled(true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public ListSelectionModel getSimulationListSelectionModel() {
|
||||
return simulationTable.getSelectionModel();
|
||||
}
|
||||
|
||||
private void openDialog(final Simulation sim, int position) {
|
||||
new SimulationEditDialog(SwingUtilities.getWindowAncestor(this), document, sim, position)
|
||||
.setVisible(true);
|
||||
private void openDialog(final Simulation... sims) {
|
||||
new SimulationEditDialog(SwingUtilities.getWindowAncestor(this), document, sims).setVisible(true);
|
||||
fireMaintainSelection();
|
||||
}
|
||||
|
||||
|
@ -20,6 +20,7 @@ import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
import net.sf.openrocket.document.Simulation;
|
||||
import net.sf.openrocket.gui.simulation.SimulationPlotPanel;
|
||||
import net.sf.openrocket.simulation.FlightDataBranch;
|
||||
import net.sf.openrocket.simulation.FlightDataType;
|
||||
import net.sf.openrocket.simulation.FlightEvent;
|
||||
|
@ -7,8 +7,6 @@ import java.awt.event.InputEvent;
|
||||
import java.awt.event.ItemEvent;
|
||||
import java.awt.event.ItemListener;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JCheckBox;
|
||||
@ -40,7 +38,7 @@ public class SimulationPlotDialog extends JDialog {
|
||||
private SimulationPlotDialog(Window parent, Simulation simulation, PlotConfiguration config) {
|
||||
//// Flight data plot
|
||||
super(parent, simulation.getName());
|
||||
this.setModalityType(ModalityType.DOCUMENT_MODAL);
|
||||
this.setModalityType(ModalityType.MODELESS);
|
||||
|
||||
final boolean initialShowPoints = Application.getPreferences().getBoolean(Preferences.PLOT_SHOW_POINTS, false);
|
||||
|
||||
@ -113,8 +111,8 @@ public class SimulationPlotDialog extends JDialog {
|
||||
//// Add series selection box
|
||||
ArrayList<String> stages = new ArrayList<String>();
|
||||
stages.add("All");
|
||||
stages.addAll( Util.generateSeriesLabels(simulation));
|
||||
|
||||
stages.addAll(Util.generateSeriesLabels(simulation));
|
||||
|
||||
final JComboBox stageSelection = new JComboBox(stages.toArray(new String[0]));
|
||||
stageSelection.addItemListener(new ItemListener() {
|
||||
|
||||
@ -159,8 +157,8 @@ public class SimulationPlotDialog extends JDialog {
|
||||
* @param simulation the simulation to plot.
|
||||
* @param config the configuration of the plot.
|
||||
*/
|
||||
public static void showPlot(Window parent, Simulation simulation, PlotConfiguration config) {
|
||||
new SimulationPlotDialog(parent, simulation, config).setVisible(true);
|
||||
public static SimulationPlotDialog getPlot(Window parent, Simulation simulation, PlotConfiguration config) {
|
||||
return new SimulationPlotDialog(parent, simulation, config);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -4,7 +4,7 @@
|
||||
package net.sf.openrocket.gui.print;
|
||||
|
||||
import net.sf.openrocket.document.Simulation;
|
||||
import net.sf.openrocket.gui.main.SimulationWorker;
|
||||
import net.sf.openrocket.gui.simulation.SimulationWorker;
|
||||
import net.sf.openrocket.simulation.FlightData;
|
||||
|
||||
/**
|
||||
|
@ -54,8 +54,8 @@ import net.sf.openrocket.gui.figureelements.CGCaret;
|
||||
import net.sf.openrocket.gui.figureelements.CPCaret;
|
||||
import net.sf.openrocket.gui.figureelements.Caret;
|
||||
import net.sf.openrocket.gui.figureelements.RocketInfo;
|
||||
import net.sf.openrocket.gui.main.SimulationWorker;
|
||||
import net.sf.openrocket.gui.main.componenttree.ComponentTreeModel;
|
||||
import net.sf.openrocket.gui.simulation.SimulationWorker;
|
||||
import net.sf.openrocket.gui.util.SwingPreferences;
|
||||
import net.sf.openrocket.l10n.Translator;
|
||||
import net.sf.openrocket.masscalc.BasicMassCalculator;
|
||||
|
@ -1,13 +1,11 @@
|
||||
package net.sf.openrocket.gui.main;
|
||||
package net.sf.openrocket.gui.simulation;
|
||||
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Window;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.AbstractListModel;
|
||||
import javax.swing.BorderFactory;
|
||||
@ -40,139 +38,126 @@ 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.SimulationExportPanel;
|
||||
import net.sf.openrocket.gui.components.UnitSelector;
|
||||
import net.sf.openrocket.gui.dialogs.flightconfiguration.FlightConfigurationDialog;
|
||||
import net.sf.openrocket.gui.plot.Axis;
|
||||
import net.sf.openrocket.gui.plot.PlotConfiguration;
|
||||
import net.sf.openrocket.gui.plot.SimulationPlotPanel;
|
||||
import net.sf.openrocket.gui.scalefigure.RocketPanel;
|
||||
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.FlightData;
|
||||
import net.sf.openrocket.simulation.FlightDataBranch;
|
||||
import net.sf.openrocket.simulation.FlightDataType;
|
||||
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.Unit;
|
||||
import net.sf.openrocket.unit.UnitGroup;
|
||||
import net.sf.openrocket.util.Chars;
|
||||
import net.sf.openrocket.util.GeodeticComputationStrategy;
|
||||
|
||||
import org.jfree.chart.ChartFactory;
|
||||
import org.jfree.chart.ChartPanel;
|
||||
import org.jfree.chart.JFreeChart;
|
||||
import org.jfree.chart.axis.NumberAxis;
|
||||
import org.jfree.chart.plot.PlotOrientation;
|
||||
import org.jfree.chart.plot.ValueMarker;
|
||||
import org.jfree.chart.plot.XYPlot;
|
||||
import org.jfree.chart.renderer.xy.StandardXYItemRenderer;
|
||||
import org.jfree.data.xy.XYSeries;
|
||||
import org.jfree.data.xy.XYSeriesCollection;
|
||||
|
||||
|
||||
public class SimulationEditDialog extends JDialog {
|
||||
|
||||
public static final int DEFAULT = -1;
|
||||
public static final int EDIT = 1;
|
||||
public static final int PLOT = 2;
|
||||
|
||||
|
||||
private final Window parentWindow;
|
||||
private final Simulation simulation;
|
||||
private final Simulation[] simulation;
|
||||
private final OpenRocketDocument document;
|
||||
private final SimulationOptions conditions;
|
||||
private final Configuration configuration;
|
||||
private static final Translator trans = Application.getTranslator();
|
||||
|
||||
|
||||
public SimulationEditDialog(Window parent, OpenRocketDocument document, Simulation s) {
|
||||
this(parent, document, s, 0);
|
||||
}
|
||||
|
||||
public SimulationEditDialog(Window parent, OpenRocketDocument document, Simulation s, int tab) {
|
||||
public SimulationEditDialog(Window parent, OpenRocketDocument document, Simulation... sims) {
|
||||
//// Edit simulation
|
||||
super(parent, trans.get("simedtdlg.title.Editsim"), JDialog.ModalityType.DOCUMENT_MODAL);
|
||||
this.document = document;
|
||||
this.parentWindow = parent;
|
||||
this.simulation = s;
|
||||
this.conditions = simulation.getOptions();
|
||||
configuration = simulation.getConfiguration();
|
||||
this.simulation = sims;
|
||||
this.conditions = simulation[0].getOptions();
|
||||
configuration = simulation[0].getConfiguration();
|
||||
|
||||
JPanel mainPanel = new JPanel(new MigLayout("fill", "[grow, fill]"));
|
||||
JPanel mainPanel = new JPanel(new MigLayout(""));
|
||||
|
||||
//// Simulation name:
|
||||
mainPanel.add(new JLabel(trans.get("simedtdlg.lbl.Simname") + " "), "span, split 2, shrink");
|
||||
final JTextField field = new JTextField(simulation.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.setName(name);
|
||||
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();
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
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);
|
||||
|
||||
}
|
||||
});
|
||||
mainPanel.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"));
|
||||
mainPanel.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());
|
||||
}
|
||||
});
|
||||
mainPanel.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);
|
||||
}
|
||||
});
|
||||
mainPanel.add(button, "shrink, wrap");
|
||||
}
|
||||
JTabbedPane tabbedPane = new JTabbedPane();
|
||||
|
||||
//// Launch conditions
|
||||
tabbedPane.addTab(trans.get("simedtdlg.tab.Launchcond"), flightConditionsTab());
|
||||
//// Simulation options
|
||||
tabbedPane.addTab(trans.get("simedtdlg.tab.Simopt"), simulationOptionsTab());
|
||||
//// Plot data
|
||||
tabbedPane.addTab(trans.get("simedtdlg.tab.Plotdata"), plotTab());
|
||||
//// Export data
|
||||
tabbedPane.addTab(trans.get("simedtdlg.tab.Exportdata"), exportTab());
|
||||
|
||||
// Select the initial tab
|
||||
if (tab == EDIT) {
|
||||
tabbedPane.setSelectedIndex(0);
|
||||
} else if (tab == PLOT) {
|
||||
tabbedPane.setSelectedIndex(2);
|
||||
} else {
|
||||
FlightData data = s.getSimulatedData();
|
||||
if (data == null || data.getBranchCount() == 0)
|
||||
tabbedPane.setSelectedIndex(0);
|
||||
else
|
||||
tabbedPane.setSelectedIndex(2);
|
||||
}
|
||||
tabbedPane.setSelectedIndex(0);
|
||||
|
||||
mainPanel.add(tabbedPane, "spanx, grow, wrap");
|
||||
|
||||
|
||||
|
||||
// Buttons
|
||||
mainPanel.add(new JPanel(), "spanx, split, growx");
|
||||
|
||||
JButton button;
|
||||
//// Run simulation button
|
||||
button = new JButton(trans.get("simedtdlg.but.runsimulation"));
|
||||
JButton button = new JButton(trans.get("simedtdlg.but.runsimulation"));
|
||||
button.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
copyChangesToAllSims();
|
||||
SimulationEditDialog.this.dispose();
|
||||
SimulationRunDialog.runSimulations(parentWindow, SimulationEditDialog.this.document, simulation);
|
||||
}
|
||||
@ -184,12 +169,13 @@ public class SimulationEditDialog extends JDialog {
|
||||
close.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
copyChangesToAllSims();
|
||||
SimulationEditDialog.this.dispose();
|
||||
}
|
||||
});
|
||||
mainPanel.add(close, "");
|
||||
|
||||
|
||||
|
||||
this.add(mainPanel);
|
||||
this.validate();
|
||||
this.pack();
|
||||
@ -198,10 +184,19 @@ public class SimulationEditDialog extends JDialog {
|
||||
GUIUtil.setDisposableDialogOptions(this, button);
|
||||
}
|
||||
|
||||
private void copyChangesToAllSims() {
|
||||
if (simulation.length > 1) {
|
||||
for (int i = 1; i < simulation.length; i++) {
|
||||
simulation[i].getOptions().copyConditionsFrom(simulation[0].getOptions());
|
||||
simulation[i].getSimulationListeners().clear();
|
||||
simulation[i].getSimulationListeners().addAll(simulation[0].getSimulationListeners());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private JPanel flightConditionsTab() {
|
||||
JPanel panel = new JPanel(new MigLayout("fill"));
|
||||
JPanel sub;
|
||||
@ -211,35 +206,6 @@ public class SimulationEditDialog extends JDialog {
|
||||
DoubleModel m;
|
||||
JSpinner spin;
|
||||
|
||||
//// 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"));
|
||||
panel.add(label, "shrinkx, spanx, split 2");
|
||||
|
||||
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());
|
||||
}
|
||||
});
|
||||
panel.add(combo, "");
|
||||
|
||||
//// 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(document.getRocket(),SwingUtilities.windowForComponent(SimulationEditDialog.this));
|
||||
configDialog.show();
|
||||
}
|
||||
});
|
||||
panel.add(button, "wrap");
|
||||
|
||||
//// Wind settings: Average wind speed, turbulence intensity, std. deviation
|
||||
sub = new JPanel(new MigLayout("fill, gap rel unrel",
|
||||
"[grow][65lp!][30lp!][75lp!]", ""));
|
||||
@ -247,10 +213,10 @@ public class SimulationEditDialog extends JDialog {
|
||||
sub.setBorder(BorderFactory.createTitledBorder(trans.get("simedtdlg.lbl.Wind")));
|
||||
panel.add(sub, "growx, split 2, aligny 0, flowy, gapright para");
|
||||
|
||||
|
||||
|
||||
// Wind average
|
||||
//// Average windspeed:
|
||||
label = new JLabel(trans.get("simedtdlg.lbl.Averwindspeed"));
|
||||
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);
|
||||
@ -270,8 +236,8 @@ public class SimulationEditDialog extends JDialog {
|
||||
slider.setToolTipText(tip);
|
||||
sub.add(slider, "w 75lp, wrap");
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Wind std. deviation
|
||||
//// Standard deviation:
|
||||
label = new JLabel(trans.get("simedtdlg.lbl.Stddeviation"));
|
||||
@ -297,7 +263,7 @@ public class SimulationEditDialog extends JDialog {
|
||||
slider.setToolTipText(tip);
|
||||
sub.add(slider, "w 75lp, wrap");
|
||||
|
||||
|
||||
|
||||
// Wind turbulence intensity
|
||||
//// Turbulence intensity:
|
||||
label = new JLabel(trans.get("simedtdlg.lbl.Turbulenceintensity"));
|
||||
@ -335,10 +301,10 @@ public class SimulationEditDialog extends JDialog {
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//// Temperature and pressure
|
||||
sub = new JPanel(new MigLayout("fill, gap rel unrel",
|
||||
"[grow][65lp!][30lp!][75lp!]", ""));
|
||||
@ -346,7 +312,7 @@ public class SimulationEditDialog extends JDialog {
|
||||
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
|
||||
@ -387,8 +353,8 @@ public class SimulationEditDialog extends JDialog {
|
||||
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.
|
||||
@ -414,10 +380,10 @@ public class SimulationEditDialog extends JDialog {
|
||||
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!]", ""));
|
||||
@ -425,7 +391,7 @@ public class SimulationEditDialog extends JDialog {
|
||||
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"));
|
||||
//// <html>The launch site latitude affects the gravitational pull of Earth.<br>
|
||||
@ -448,7 +414,7 @@ public class SimulationEditDialog extends JDialog {
|
||||
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");
|
||||
@ -469,7 +435,7 @@ public class SimulationEditDialog extends JDialog {
|
||||
slider.setToolTipText(tip);
|
||||
sub.add(slider, "w 75lp, wrap");
|
||||
|
||||
|
||||
|
||||
// Altitude:
|
||||
label = new JLabel(trans.get("simedtdlg.lbl.Altitude"));
|
||||
//// <html>The launch altitude above mean sea level.<br>
|
||||
@ -492,10 +458,10 @@ public class SimulationEditDialog extends JDialog {
|
||||
slider.setToolTipText(tip);
|
||||
sub.add(slider, "w 75lp, wrap");
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//// Launch rod
|
||||
sub = new JPanel(new MigLayout("fill, gap rel unrel",
|
||||
"[grow][65lp!][30lp!][75lp!]", ""));
|
||||
@ -503,7 +469,7 @@ public class SimulationEditDialog extends JDialog {
|
||||
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.
|
||||
@ -525,8 +491,8 @@ public class SimulationEditDialog extends JDialog {
|
||||
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.
|
||||
@ -550,8 +516,8 @@ public class SimulationEditDialog extends JDialog {
|
||||
slider.setToolTipText(tip);
|
||||
sub.add(slider, "w 75lp, wrap");
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Direction:
|
||||
label = new JLabel(trans.get("simedtdlg.lbl.Direction"));
|
||||
//// <html>Direction of the launch rod relative to the wind.<br>
|
||||
@ -580,6 +546,35 @@ public class SimulationEditDialog extends JDialog {
|
||||
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;
|
||||
}
|
||||
|
||||
@ -608,7 +603,7 @@ public class SimulationEditDialog extends JDialog {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
private JPanel simulationOptionsTab() {
|
||||
JPanel panel = new JPanel(new MigLayout("fill"));
|
||||
JPanel sub, subsub;
|
||||
@ -619,7 +614,7 @@ public class SimulationEditDialog extends JDialog {
|
||||
UnitSelector unit;
|
||||
BasicSlider slider;
|
||||
|
||||
|
||||
|
||||
//// Simulation options
|
||||
sub = new JPanel(new MigLayout("fill, gap rel unrel",
|
||||
"[grow][65lp!][30lp!][75lp!]", ""));
|
||||
@ -627,11 +622,11 @@ public class SimulationEditDialog extends JDialog {
|
||||
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"));
|
||||
@ -643,7 +638,7 @@ public class SimulationEditDialog extends JDialog {
|
||||
label.setToolTipText(tip);
|
||||
subsub.add(label, "growx, wrap para");
|
||||
|
||||
|
||||
|
||||
// Simulation method
|
||||
tip = trans.get("simedtdlg.lbl.ttip.Simmethod1") +
|
||||
trans.get("simedtdlg.lbl.ttip.Simmethod2");
|
||||
@ -655,7 +650,7 @@ public class SimulationEditDialog extends JDialog {
|
||||
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"));
|
||||
@ -676,7 +671,7 @@ public class SimulationEditDialog extends JDialog {
|
||||
|
||||
sub.add(subsub, "spanx, wrap para");
|
||||
|
||||
|
||||
|
||||
//// Time step:
|
||||
label = new JLabel(trans.get("simedtdlg.lbl.Timestep"));
|
||||
tip = trans.get("simedtdlg.lbl.ttip.Timestep1") +
|
||||
@ -703,9 +698,9 @@ public class SimulationEditDialog extends JDialog {
|
||||
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 (
|
||||
@ -722,16 +717,16 @@ public class SimulationEditDialog extends JDialog {
|
||||
|
||||
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);
|
||||
//// <html><i>Simulation listeners</i> 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.
|
||||
@ -771,7 +766,7 @@ public class SimulationEditDialog extends JDialog {
|
||||
return;
|
||||
|
||||
Application.getPreferences().putString("previousListenerName", input);
|
||||
simulation.getSimulationListeners().add(input);
|
||||
simulation[0].getSimulationListeners().add(input);
|
||||
listenerModel.fireContentsChanged();
|
||||
}
|
||||
});
|
||||
@ -785,14 +780,14 @@ public class SimulationEditDialog extends JDialog {
|
||||
int[] selected = list.getSelectedIndices();
|
||||
Arrays.sort(selected);
|
||||
for (int i = selected.length - 1; i >= 0; i--) {
|
||||
simulation.getSimulationListeners().remove(selected[i]);
|
||||
simulation[0].getSimulationListeners().remove(selected[i]);
|
||||
}
|
||||
listenerModel.fireContentsChanged();
|
||||
}
|
||||
});
|
||||
sub.add(button, "sizegroup buttons, alignx 50%");
|
||||
|
||||
|
||||
|
||||
return panel;
|
||||
}
|
||||
|
||||
@ -802,12 +797,12 @@ public class SimulationEditDialog extends JDialog {
|
||||
public String getElementAt(int index) {
|
||||
if (index < 0 || index >= getSize())
|
||||
return null;
|
||||
return simulation.getSimulationListeners().get(index);
|
||||
return simulation[0].getSimulationListeners().get(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSize() {
|
||||
return simulation.getSimulationListeners().size();
|
||||
return simulation[0].getSimulationListeners().size();
|
||||
}
|
||||
|
||||
public void fireContentsChanged() {
|
||||
@ -816,40 +811,9 @@ public class SimulationEditDialog extends JDialog {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* A panel for plotting the previously calculated data.
|
||||
*/
|
||||
private JPanel plotTab() {
|
||||
|
||||
// Check that data exists
|
||||
if (simulation.getSimulatedData() == null ||
|
||||
simulation.getSimulatedData().getBranchCount() == 0) {
|
||||
return noDataPanel();
|
||||
}
|
||||
|
||||
return new SimulationPlotPanel(simulation);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* A panel for exporting the data.
|
||||
*/
|
||||
private JPanel exportTab() {
|
||||
FlightData data = simulation.getSimulatedData();
|
||||
|
||||
// Check that data exists
|
||||
if (data == null || data.getBranchCount() == 0 ||
|
||||
data.getBranch(0).getTypes().length == 0) {
|
||||
return noDataPanel();
|
||||
}
|
||||
|
||||
return new SimulationExportPanel(simulation);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return a panel stating that there is no data available, and that the user
|
||||
* should run the simulation first.
|
||||
@ -868,165 +832,7 @@ public class SimulationEditDialog extends JDialog {
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private void performPlot(PlotConfiguration config) {
|
||||
|
||||
// Fill the auto-selections
|
||||
FlightDataBranch branch = simulation.getSimulatedData().getBranch(0);
|
||||
PlotConfiguration filled = config.fillAutoAxes(branch);
|
||||
List<Axis> axes = filled.getAllAxes();
|
||||
|
||||
|
||||
// Create the data series for both axes
|
||||
XYSeriesCollection[] data = new XYSeriesCollection[2];
|
||||
data[0] = new XYSeriesCollection();
|
||||
data[1] = new XYSeriesCollection();
|
||||
|
||||
|
||||
// Get the domain axis type
|
||||
final FlightDataType domainType = filled.getDomainAxisType();
|
||||
final Unit domainUnit = filled.getDomainAxisUnit();
|
||||
if (domainType == null) {
|
||||
throw new IllegalArgumentException("Domain axis type not specified.");
|
||||
}
|
||||
List<Double> x = branch.get(domainType);
|
||||
|
||||
|
||||
// Create the XYSeries objects from the flight data and store into the collections
|
||||
int length = filled.getTypeCount();
|
||||
String[] axisLabel = new String[2];
|
||||
for (int i = 0; i < length; i++) {
|
||||
// Get info
|
||||
FlightDataType type = filled.getType(i);
|
||||
Unit unit = filled.getUnit(i);
|
||||
int axis = filled.getAxis(i);
|
||||
String name = getLabel(type, unit);
|
||||
|
||||
// Store data in provided units
|
||||
List<Double> y = branch.get(type);
|
||||
XYSeries series = new XYSeries(name, false, true);
|
||||
for (int j = 0; j < x.size(); j++) {
|
||||
series.add(domainUnit.toUnit(x.get(j)), unit.toUnit(y.get(j)));
|
||||
}
|
||||
data[axis].addSeries(series);
|
||||
|
||||
// Update axis label
|
||||
if (axisLabel[axis] == null)
|
||||
axisLabel[axis] = type.getName();
|
||||
else
|
||||
axisLabel[axis] += "; " + type.getName();
|
||||
}
|
||||
|
||||
|
||||
// Create the chart using the factory to get all default settings
|
||||
JFreeChart chart = ChartFactory.createXYLineChart(
|
||||
//// Simulated flight
|
||||
trans.get("simedtdlg.chart.Simflight"),
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
PlotOrientation.VERTICAL,
|
||||
true,
|
||||
true,
|
||||
false
|
||||
);
|
||||
|
||||
|
||||
// Add the data and formatting to the plot
|
||||
XYPlot plot = chart.getXYPlot();
|
||||
int axisno = 0;
|
||||
for (int i = 0; i < 2; i++) {
|
||||
// Check whether axis has any data
|
||||
if (data[i].getSeriesCount() > 0) {
|
||||
// Create and set axis
|
||||
double min = axes.get(i).getMinValue();
|
||||
double max = axes.get(i).getMaxValue();
|
||||
NumberAxis axis = new PresetNumberAxis(min, max);
|
||||
axis.setLabel(axisLabel[i]);
|
||||
// axis.setRange(axes.get(i).getMinValue(), axes.get(i).getMaxValue());
|
||||
plot.setRangeAxis(axisno, axis);
|
||||
|
||||
// Add data and map to the axis
|
||||
plot.setDataset(axisno, data[i]);
|
||||
plot.setRenderer(axisno, new StandardXYItemRenderer());
|
||||
plot.mapDatasetToRangeAxis(axisno, axisno);
|
||||
axisno++;
|
||||
}
|
||||
}
|
||||
|
||||
plot.getDomainAxis().setLabel(getLabel(domainType, domainUnit));
|
||||
plot.addDomainMarker(new ValueMarker(0));
|
||||
plot.addRangeMarker(new ValueMarker(0));
|
||||
|
||||
|
||||
// Create the dialog
|
||||
//// Simulation results
|
||||
final JDialog dialog = new JDialog(this, trans.get("simedtdlg.dlg.Simres"));
|
||||
dialog.setModalityType(ModalityType.DOCUMENT_MODAL);
|
||||
|
||||
JPanel panel = new JPanel(new MigLayout("fill"));
|
||||
dialog.add(panel);
|
||||
|
||||
ChartPanel chartPanel = new ChartPanel(chart,
|
||||
false, // properties
|
||||
true, // save
|
||||
false, // print
|
||||
true, // zoom
|
||||
true); // tooltips
|
||||
chartPanel.setMouseWheelEnabled(true);
|
||||
chartPanel.setEnforceFileExtensions(true);
|
||||
chartPanel.setInitialDelay(500);
|
||||
|
||||
chartPanel.setBorder(BorderFactory.createLineBorder(Color.GRAY, 1));
|
||||
|
||||
panel.add(chartPanel, "grow, wrap 20lp");
|
||||
|
||||
//// Close button
|
||||
JButton button = new JButton(trans.get("dlg.but.close"));
|
||||
button.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
dialog.setVisible(false);
|
||||
}
|
||||
});
|
||||
panel.add(button, "right");
|
||||
|
||||
dialog.setLocationByPlatform(true);
|
||||
dialog.pack();
|
||||
|
||||
GUIUtil.setDisposableDialogOptions(dialog, button);
|
||||
|
||||
dialog.setVisible(true);
|
||||
}
|
||||
|
||||
|
||||
private class PresetNumberAxis extends NumberAxis {
|
||||
private final double min;
|
||||
private final double max;
|
||||
|
||||
public PresetNumberAxis(double min, double max) {
|
||||
this.min = min;
|
||||
this.max = max;
|
||||
autoAdjustRange();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void autoAdjustRange() {
|
||||
this.setRange(min, max);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private String getLabel(FlightDataType type, Unit unit) {
|
||||
String name = type.getName();
|
||||
if (unit != null && !UnitGroup.UNITS_NONE.contains(unit) &&
|
||||
!UnitGroup.UNITS_COEFFICIENT.contains(unit) && unit.getUnit().length() > 0)
|
||||
name += " (" + unit.getUnit() + ")";
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private class ListenerCellRenderer extends JLabel implements ListCellRenderer {
|
||||
|
||||
@Override
|
@ -0,0 +1,436 @@
|
||||
package net.sf.openrocket.gui.simulation;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.io.File;
|
||||
import java.util.Arrays;
|
||||
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JFileChooser;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JTable;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.table.AbstractTableModel;
|
||||
import javax.swing.table.TableCellRenderer;
|
||||
import javax.swing.table.TableColumn;
|
||||
import javax.swing.table.TableColumnModel;
|
||||
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import net.sf.openrocket.document.Simulation;
|
||||
import net.sf.openrocket.gui.components.CsvOptionPanel;
|
||||
import net.sf.openrocket.gui.components.UnitCellEditor;
|
||||
import net.sf.openrocket.gui.util.FileHelper;
|
||||
import net.sf.openrocket.gui.util.GUIUtil;
|
||||
import net.sf.openrocket.gui.util.SaveCSVWorker;
|
||||
import net.sf.openrocket.gui.util.SwingPreferences;
|
||||
import net.sf.openrocket.l10n.Translator;
|
||||
import net.sf.openrocket.simulation.FlightData;
|
||||
import net.sf.openrocket.simulation.FlightDataBranch;
|
||||
import net.sf.openrocket.simulation.FlightDataType;
|
||||
import net.sf.openrocket.startup.Application;
|
||||
import net.sf.openrocket.unit.Unit;
|
||||
import net.sf.openrocket.unit.UnitGroup;
|
||||
|
||||
public class SimulationExportPanel extends JPanel {
|
||||
|
||||
private static final String SPACE = "SPACE";
|
||||
private static final String TAB = "TAB";
|
||||
private static final Translator trans = Application.getTranslator();
|
||||
|
||||
private static final int OPTION_SIMULATION_COMMENTS = 0;
|
||||
private static final int OPTION_FIELD_DESCRIPTIONS = 1;
|
||||
private static final int OPTION_FLIGHT_EVENTS = 2;
|
||||
|
||||
private final JTable table;
|
||||
private final SelectionTableModel tableModel;
|
||||
private final JLabel selectedCountLabel;
|
||||
|
||||
private final Simulation simulation;
|
||||
private final FlightDataBranch branch;
|
||||
|
||||
private final boolean[] selected;
|
||||
private final FlightDataType[] types;
|
||||
private final Unit[] units;
|
||||
|
||||
private final CsvOptionPanel csvOptions;
|
||||
|
||||
|
||||
public SimulationExportPanel(Simulation sim) {
|
||||
super(new MigLayout("fill, flowy"));
|
||||
|
||||
JPanel panel;
|
||||
JButton button;
|
||||
|
||||
|
||||
this.simulation = sim;
|
||||
|
||||
// TODO: MEDIUM: Only exports primary branch
|
||||
|
||||
final FlightData data = simulation.getSimulatedData();
|
||||
|
||||
// Check that data exists
|
||||
if (data == null || data.getBranchCount() == 0 ||
|
||||
data.getBranch(0).getTypes().length == 0) {
|
||||
throw new IllegalArgumentException("No data for panel");
|
||||
}
|
||||
|
||||
|
||||
// Create the data model
|
||||
branch = data.getBranch(0);
|
||||
|
||||
types = branch.getTypes();
|
||||
Arrays.sort(types);
|
||||
|
||||
selected = new boolean[types.length];
|
||||
units = new Unit[types.length];
|
||||
for (int i = 0; i < types.length; i++) {
|
||||
selected[i] = ((SwingPreferences) Application.getPreferences()).isExportSelected(types[i]);
|
||||
units[i] = types[i].getUnitGroup().getDefaultUnit();
|
||||
}
|
||||
|
||||
|
||||
//// Create the panel
|
||||
|
||||
|
||||
// Set up the variable selection table
|
||||
tableModel = new SelectionTableModel();
|
||||
table = new JTable(tableModel);
|
||||
table.setDefaultRenderer(Object.class,
|
||||
new SelectionBackgroundCellRenderer(table.getDefaultRenderer(Object.class)));
|
||||
table.setDefaultRenderer(Boolean.class,
|
||||
new SelectionBackgroundCellRenderer(table.getDefaultRenderer(Boolean.class)));
|
||||
table.setRowSelectionAllowed(false);
|
||||
table.setColumnSelectionAllowed(false);
|
||||
|
||||
table.setDefaultEditor(Unit.class, new UnitCellEditor() {
|
||||
@Override
|
||||
protected UnitGroup getUnitGroup(Unit value, int row, int column) {
|
||||
return types[row].getUnitGroup();
|
||||
}
|
||||
});
|
||||
|
||||
// Set column widths
|
||||
TableColumnModel columnModel = table.getColumnModel();
|
||||
TableColumn col = columnModel.getColumn(0);
|
||||
int w = table.getRowHeight();
|
||||
col.setMinWidth(w);
|
||||
col.setPreferredWidth(w);
|
||||
col.setMaxWidth(w);
|
||||
|
||||
col = columnModel.getColumn(1);
|
||||
col.setPreferredWidth(200);
|
||||
|
||||
col = columnModel.getColumn(2);
|
||||
col.setPreferredWidth(100);
|
||||
|
||||
table.addMouseListener(new GUIUtil.BooleanTableClickListener(table));
|
||||
|
||||
// Add table
|
||||
panel = new JPanel(new MigLayout("fill"));
|
||||
panel.setBorder(BorderFactory.createTitledBorder(trans.get("SimExpPan.border.Vartoexport")));
|
||||
|
||||
panel.add(new JScrollPane(table), "wmin 300lp, width 300lp, height 1, grow 100, wrap");
|
||||
|
||||
// Select all/none buttons
|
||||
button = new JButton(trans.get("SimExpPan.but.Selectall"));
|
||||
button.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
tableModel.selectAll();
|
||||
}
|
||||
});
|
||||
panel.add(button, "split 2, growx 1, sizegroup selectbutton");
|
||||
|
||||
button = new JButton(trans.get("SimExpPan.but.Selectnone"));
|
||||
button.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
tableModel.selectNone();
|
||||
}
|
||||
});
|
||||
panel.add(button, "growx 1, sizegroup selectbutton, wrap");
|
||||
|
||||
|
||||
selectedCountLabel = new JLabel();
|
||||
updateSelectedCount();
|
||||
panel.add(selectedCountLabel);
|
||||
|
||||
this.add(panel, "grow 100, wrap");
|
||||
|
||||
|
||||
// These need to be in the order of the OPTIONS_XXX indices
|
||||
csvOptions = new CsvOptionPanel(SimulationExportPanel.class,
|
||||
trans.get("SimExpPan.checkbox.Includesimudesc"),
|
||||
trans.get("SimExpPan.checkbox.ttip.Includesimudesc"),
|
||||
trans.get("SimExpPan.checkbox.Includefielddesc"),
|
||||
trans.get("SimExpPan.checkbox.ttip.Includefielddesc"),
|
||||
trans.get("SimExpPan.checkbox.Incflightevents"),
|
||||
trans.get("SimExpPan.checkbox.ttip.Incflightevents"));
|
||||
|
||||
this.add(csvOptions, "spany, split, growx 1");
|
||||
|
||||
|
||||
// Space-filling panel
|
||||
panel = new JPanel();
|
||||
this.add(panel, "width 1, height 1, grow 1");
|
||||
|
||||
/*
|
||||
// Export button
|
||||
button = new JButton(trans.get("SimExpPan.but.Exporttofile"));
|
||||
button.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
doExport();
|
||||
}
|
||||
});
|
||||
this.add(button, "gapbottom para, gapright para, right");
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
public boolean doExport() {
|
||||
JFileChooser chooser = new JFileChooser();
|
||||
chooser.setFileFilter(FileHelper.CSV_FILE_FILTER);
|
||||
chooser.setCurrentDirectory(((SwingPreferences) Application.getPreferences()).getDefaultDirectory());
|
||||
|
||||
if (chooser.showSaveDialog(this) != JFileChooser.APPROVE_OPTION)
|
||||
return false;
|
||||
|
||||
File file = chooser.getSelectedFile();
|
||||
if (file == null)
|
||||
return false;
|
||||
|
||||
file = FileHelper.ensureExtension(file, "csv");
|
||||
if (!FileHelper.confirmWrite(file, this)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
String commentChar = csvOptions.getCommentCharacter();
|
||||
String fieldSep = csvOptions.getFieldSeparator();
|
||||
boolean simulationComment = csvOptions.getSelectionOption(OPTION_SIMULATION_COMMENTS);
|
||||
boolean fieldComment = csvOptions.getSelectionOption(OPTION_FIELD_DESCRIPTIONS);
|
||||
boolean eventComment = csvOptions.getSelectionOption(OPTION_FLIGHT_EVENTS);
|
||||
csvOptions.storePreferences();
|
||||
|
||||
// Store preferences and export
|
||||
int n = 0;
|
||||
((SwingPreferences) Application.getPreferences()).setDefaultDirectory(chooser.getCurrentDirectory());
|
||||
for (int i = 0; i < selected.length; i++) {
|
||||
((SwingPreferences) Application.getPreferences()).setExportSelected(types[i], selected[i]);
|
||||
if (selected[i])
|
||||
n++;
|
||||
}
|
||||
|
||||
|
||||
FlightDataType[] fieldTypes = new FlightDataType[n];
|
||||
Unit[] fieldUnits = new Unit[n];
|
||||
int pos = 0;
|
||||
for (int i = 0; i < selected.length; i++) {
|
||||
if (selected[i]) {
|
||||
fieldTypes[pos] = types[i];
|
||||
fieldUnits[pos] = units[i];
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
|
||||
if (fieldSep.equals(SPACE)) {
|
||||
fieldSep = " ";
|
||||
} else if (fieldSep.equals(TAB)) {
|
||||
fieldSep = "\t";
|
||||
}
|
||||
|
||||
|
||||
SaveCSVWorker.export(file, simulation, branch, fieldTypes, fieldUnits, fieldSep,
|
||||
commentChar, simulationComment, fieldComment, eventComment,
|
||||
SwingUtilities.getWindowAncestor(this));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
private void updateSelectedCount() {
|
||||
int total = selected.length;
|
||||
int n = 0;
|
||||
String str;
|
||||
|
||||
for (int i = 0; i < selected.length; i++) {
|
||||
if (selected[i])
|
||||
n++;
|
||||
}
|
||||
|
||||
if (n == 1) {
|
||||
//// Exporting 1 variable out of
|
||||
str = trans.get("SimExpPan.ExportingVar.desc1") + " " + total + ".";
|
||||
} else {
|
||||
//// Exporting
|
||||
//// variables out of
|
||||
str = trans.get("SimExpPan.ExportingVar.desc2") + " " + n + " " +
|
||||
trans.get("SimExpPan.ExportingVar.desc3") + " " + total + ".";
|
||||
}
|
||||
|
||||
selectedCountLabel.setText(str);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* A table cell renderer that uses another renderer and sets the background and
|
||||
* foreground of the returned component based on the selection of the variable.
|
||||
*/
|
||||
private class SelectionBackgroundCellRenderer implements TableCellRenderer {
|
||||
|
||||
private final TableCellRenderer renderer;
|
||||
|
||||
public SelectionBackgroundCellRenderer(TableCellRenderer renderer) {
|
||||
this.renderer = renderer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getTableCellRendererComponent(JTable myTable, Object value,
|
||||
boolean isSelected, boolean hasFocus, int row, int column) {
|
||||
|
||||
Component component = renderer.getTableCellRendererComponent(myTable,
|
||||
value, isSelected, hasFocus, row, column);
|
||||
|
||||
if (selected[row]) {
|
||||
component.setBackground(myTable.getSelectionBackground());
|
||||
component.setForeground(myTable.getSelectionForeground());
|
||||
} else {
|
||||
component.setBackground(myTable.getBackground());
|
||||
component.setForeground(myTable.getForeground());
|
||||
}
|
||||
|
||||
return component;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The table model for the variable selection.
|
||||
*/
|
||||
private class SelectionTableModel extends AbstractTableModel {
|
||||
private static final int SELECTED = 0;
|
||||
private static final int NAME = 1;
|
||||
private static final int UNIT = 2;
|
||||
|
||||
@Override
|
||||
public int getColumnCount() {
|
||||
return 3;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRowCount() {
|
||||
return types.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getColumnName(int column) {
|
||||
switch (column) {
|
||||
case SELECTED:
|
||||
return "";
|
||||
case NAME:
|
||||
//// Variable
|
||||
return trans.get("SimExpPan.Col.Variable");
|
||||
case UNIT:
|
||||
//// Unit
|
||||
return trans.get("SimExpPan.Col.Unit");
|
||||
default:
|
||||
throw new IndexOutOfBoundsException("column=" + column);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getColumnClass(int column) {
|
||||
switch (column) {
|
||||
case SELECTED:
|
||||
return Boolean.class;
|
||||
case NAME:
|
||||
return FlightDataType.class;
|
||||
case UNIT:
|
||||
return Unit.class;
|
||||
default:
|
||||
throw new IndexOutOfBoundsException("column=" + column);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValueAt(int row, int column) {
|
||||
|
||||
switch (column) {
|
||||
case SELECTED:
|
||||
return selected[row];
|
||||
|
||||
case NAME:
|
||||
return types[row];
|
||||
|
||||
case UNIT:
|
||||
return units[row];
|
||||
|
||||
default:
|
||||
throw new IndexOutOfBoundsException("column=" + column);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValueAt(Object value, int row, int column) {
|
||||
|
||||
switch (column) {
|
||||
case SELECTED:
|
||||
selected[row] = (Boolean) value;
|
||||
this.fireTableRowsUpdated(row, row);
|
||||
updateSelectedCount();
|
||||
break;
|
||||
|
||||
case NAME:
|
||||
break;
|
||||
|
||||
case UNIT:
|
||||
units[row] = (Unit) value;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new IndexOutOfBoundsException("column=" + column);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCellEditable(int row, int column) {
|
||||
switch (column) {
|
||||
case SELECTED:
|
||||
return true;
|
||||
|
||||
case NAME:
|
||||
return false;
|
||||
|
||||
case UNIT:
|
||||
return types[row].getUnitGroup().getUnitCount() > 1;
|
||||
|
||||
default:
|
||||
throw new IndexOutOfBoundsException("column=" + column);
|
||||
}
|
||||
}
|
||||
|
||||
public void selectAll() {
|
||||
Arrays.fill(selected, true);
|
||||
updateSelectedCount();
|
||||
this.fireTableDataChanged();
|
||||
}
|
||||
|
||||
public void selectNone() {
|
||||
Arrays.fill(selected, false);
|
||||
updateSelectedCount();
|
||||
this.fireTableDataChanged();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,137 @@
|
||||
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.rocketcomponent.Configuration;
|
||||
import net.sf.openrocket.simulation.FlightData;
|
||||
import net.sf.openrocket.simulation.SimulationOptions;
|
||||
import net.sf.openrocket.startup.Application;
|
||||
|
||||
public class SimulationPlotExportDialog extends JDialog {
|
||||
|
||||
private final Window parentWindow;
|
||||
private final Simulation simulation;
|
||||
private final OpenRocketDocument document;
|
||||
private final SimulationOptions conditions;
|
||||
private final Configuration configuration;
|
||||
private static final Translator trans = Application.getTranslator();
|
||||
|
||||
public SimulationPlotExportDialog(Window parent, OpenRocketDocument document, Simulation s) {
|
||||
//// Plot/Export simulation
|
||||
super(parent, trans.get("simedtdlg.title.Editsim"), JDialog.ModalityType.DOCUMENT_MODAL);
|
||||
this.document = document;
|
||||
this.parentWindow = parent;
|
||||
this.simulation = s;
|
||||
this.conditions = simulation.getOptions();
|
||||
configuration = simulation.getConfiguration();
|
||||
|
||||
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 = plotTab();
|
||||
tabbedPane.addTab(trans.get("simedtdlg.tab.Plotdata"), plotTab);
|
||||
//// Export data
|
||||
final SimulationExportPanel exportTab = exportTab();
|
||||
tabbedPane.addTab(trans.get("simedtdlg.tab.Exportdata"), exportTab);
|
||||
|
||||
mainPanel.add(tabbedPane, "grow, wrap");
|
||||
|
||||
JButton ok = new JButton(trans.get("dlg.but.ok"));
|
||||
ok.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
|
||||
if (tabbedPane.getSelectedIndex() == 0) {
|
||||
JDialog plot = plotTab.doPlot();
|
||||
if (plot != null) {
|
||||
SimulationPlotExportDialog.this.dispose();
|
||||
plot.setVisible(true);
|
||||
}
|
||||
} else {
|
||||
if (exportTab.doExport()) {
|
||||
SimulationPlotExportDialog.this.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
mainPanel.add(ok, "tag ok, split 2");
|
||||
|
||||
//// Close button
|
||||
JButton close = new JButton(trans.get("dlg.but.close"));
|
||||
close.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
SimulationPlotExportDialog.this.dispose();
|
||||
}
|
||||
});
|
||||
mainPanel.add(close, "tag cancel");
|
||||
|
||||
|
||||
this.add(mainPanel);
|
||||
this.validate();
|
||||
this.pack();
|
||||
this.setLocationByPlatform(true);
|
||||
|
||||
GUIUtil.setDisposableDialogOptions(this, close);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A panel for plotting the previously calculated data.
|
||||
*/
|
||||
private SimulationPlotPanel plotTab() {
|
||||
|
||||
// Check that data exists
|
||||
// FIXME -
|
||||
/*
|
||||
if (simulation.getSimulatedData() == null ||
|
||||
simulation.getSimulatedData().getBranchCount() == 0) {
|
||||
return noDataPanel();
|
||||
}
|
||||
*/
|
||||
return new SimulationPlotPanel(simulation);
|
||||
}
|
||||
|
||||
/**
|
||||
* A panel for exporting the data.
|
||||
*/
|
||||
private SimulationExportPanel exportTab() {
|
||||
FlightData data = simulation.getSimulatedData();
|
||||
|
||||
// Check that data exists
|
||||
// FIXME -
|
||||
/*
|
||||
if (data == null || data.getBranchCount() == 0 ||
|
||||
data.getBranch(0).getTypes().length == 0) {
|
||||
return noDataPanel();
|
||||
}
|
||||
*/
|
||||
return new SimulationExportPanel(simulation);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
package net.sf.openrocket.gui.plot;
|
||||
package net.sf.openrocket.gui.simulation;
|
||||
|
||||
import java.awt.Window;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.ItemEvent;
|
||||
@ -10,6 +11,7 @@ import java.util.EnumSet;
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JDialog;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JPanel;
|
||||
@ -24,6 +26,8 @@ import net.miginfocom.swing.MigLayout;
|
||||
import net.sf.openrocket.document.Simulation;
|
||||
import net.sf.openrocket.gui.components.DescriptionArea;
|
||||
import net.sf.openrocket.gui.components.UnitSelector;
|
||||
import net.sf.openrocket.gui.plot.PlotConfiguration;
|
||||
import net.sf.openrocket.gui.plot.SimulationPlotDialog;
|
||||
import net.sf.openrocket.gui.util.GUIUtil;
|
||||
import net.sf.openrocket.gui.util.Icons;
|
||||
import net.sf.openrocket.l10n.Translator;
|
||||
@ -213,7 +217,7 @@ public class SimulationPlotPanel extends JPanel {
|
||||
col0.setPreferredWidth(w);
|
||||
col0.setMaxWidth(w);
|
||||
table.addMouseListener(new GUIUtil.BooleanTableClickListener(table));
|
||||
this.add(new JScrollPane(table), "height 10px, width 200lp, grow 1, wrap rel");
|
||||
this.add(new JScrollPane(table), "height 200px, width 200lp, grow 1, wrap rel");
|
||||
|
||||
|
||||
//// All + None buttons
|
||||
@ -294,6 +298,7 @@ public class SimulationPlotPanel extends JPanel {
|
||||
|
||||
this.add(new JPanel(), "growx");
|
||||
|
||||
/*
|
||||
//// Plot flight
|
||||
button = new JButton(trans.get("simplotpanel.but.Plotflight"));
|
||||
button.addActionListener(new ActionListener() {
|
||||
@ -312,10 +317,22 @@ public class SimulationPlotPanel extends JPanel {
|
||||
}
|
||||
});
|
||||
this.add(button, "right");
|
||||
|
||||
*/
|
||||
updatePlots();
|
||||
}
|
||||
|
||||
public JDialog doPlot() {
|
||||
if (configuration.getTypeCount() == 0) {
|
||||
JOptionPane.showMessageDialog(SimulationPlotPanel.this,
|
||||
trans.get("error.noPlotSelected"),
|
||||
trans.get("error.noPlotSelected.title"),
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
return null;
|
||||
}
|
||||
defaultConfiguration = configuration.clone();
|
||||
return SimulationPlotDialog.getPlot((Window) SwingUtilities.getRoot(SimulationPlotPanel.this),
|
||||
simulation, configuration);
|
||||
}
|
||||
|
||||
private void setConfiguration(PlotConfiguration conf) {
|
||||
|
@ -1,4 +1,4 @@
|
||||
package net.sf.openrocket.gui.main;
|
||||
package net.sf.openrocket.gui.simulation;
|
||||
|
||||
|
||||
import java.awt.Dialog;
|
@ -0,0 +1,32 @@
|
||||
package net.sf.openrocket.gui.simulation;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import javax.swing.JOptionPane;
|
||||
|
||||
import net.sf.openrocket.aerodynamics.Warning;
|
||||
import net.sf.openrocket.document.Simulation;
|
||||
import net.sf.openrocket.gui.dialogs.DetailDialog;
|
||||
import net.sf.openrocket.l10n.Translator;
|
||||
import net.sf.openrocket.startup.Application;
|
||||
|
||||
public class SimulationWarningDialog {
|
||||
|
||||
private static final Translator trans = Application.getTranslator();
|
||||
|
||||
public static void showWarningDialog(Component parent, Simulation simulation) {
|
||||
|
||||
if (simulation.getSimulatedWarnings().size() > 0) {
|
||||
ArrayList<String> messages = new ArrayList<String>();
|
||||
messages.add(trans.get("SimuRunDlg.msg.errorOccurred"));
|
||||
for (Warning m : simulation.getSimulatedWarnings()) {
|
||||
messages.add(m.toString());
|
||||
}
|
||||
DetailDialog.showDetailedMessageDialog(parent,
|
||||
messages.toArray(),
|
||||
null, simulation.getName(), JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package net.sf.openrocket.gui.main;
|
||||
package net.sf.openrocket.gui.simulation;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
@ -53,6 +53,7 @@ public abstract class SimulationWorker extends SwingWorker<FlightData, Simulatio
|
||||
|
||||
try {
|
||||
simulation.simulate(listeners);
|
||||
// FIXME - test for simulation warnings.
|
||||
} catch (Throwable e) {
|
||||
throwable = e;
|
||||
return null;
|
@ -42,9 +42,9 @@ public class BasicEventSimulationEngine implements SimulationEngine {
|
||||
private SimulationStepper landingStepper = new BasicLandingStepper();
|
||||
private SimulationStepper tumbleStepper = new BasicTumbleStepper();
|
||||
|
||||
// Constant holding 30 degress in radians. This is the AOA condition
|
||||
// Constant holding 10 degress in radians. This is the AOA condition
|
||||
// necessary to transistion to tumbling.
|
||||
private final static double AOA_TUMBLE_CONDITION = Math.PI / 3.0;
|
||||
private final static double AOA_TUMBLE_CONDITION = Math.PI / 9.0;
|
||||
|
||||
private SimulationStepper currentStepper;
|
||||
|
||||
@ -105,7 +105,7 @@ public class BasicEventSimulationEngine implements SimulationEngine {
|
||||
return flightData;
|
||||
}
|
||||
|
||||
private FlightDataBranch simulateLoop() throws SimulationException {
|
||||
private FlightDataBranch simulateLoop() {
|
||||
|
||||
// Initialize the simulation
|
||||
currentStepper = flightStepper;
|
||||
@ -222,7 +222,9 @@ public class BasicEventSimulationEngine implements SimulationEngine {
|
||||
|
||||
} catch (SimulationException e) {
|
||||
SimulationListenerHelper.fireEndSimulation(status, e);
|
||||
throw e;
|
||||
// Add FlightEvent for Abort.
|
||||
status.getFlightData().addEvent(new FlightEvent(FlightEvent.Type.EXCEPTION, status.getSimulationTime(), status.getConfiguration().getRocket(), e.getLocalizedMessage()));
|
||||
status.getWarnings().add(Warning.SIMULATION_EXCEPTION);
|
||||
}
|
||||
|
||||
return status.getFlightData();
|
||||
|
@ -13,7 +13,7 @@ public class BasicLandingStepper extends AbstractSimulationStepper {
|
||||
private static final double RECOVERY_TIME_STEP = 0.5;
|
||||
|
||||
@Override
|
||||
public SimulationStatus initialize(SimulationStatus status) throws SimulationException {
|
||||
public SimulationStatus initialize(SimulationStatus status) {
|
||||
return status;
|
||||
}
|
||||
|
||||
|
@ -12,7 +12,7 @@ public class BasicTumbleStepper extends AbstractSimulationStepper {
|
||||
private static final double RECOVERY_TIME_STEP = 0.5;
|
||||
|
||||
@Override
|
||||
public SimulationStatus initialize(SimulationStatus status) throws SimulationException {
|
||||
public SimulationStatus initialize(SimulationStatus status) {
|
||||
return new BasicTumbleStatus(status);
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,73 @@
|
||||
package net.sf.openrocket.simulation;
|
||||
|
||||
|
||||
import net.sf.openrocket.startup.Preferences;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
|
||||
public class DefaultSimulationOptionFactory {
|
||||
|
||||
@Inject
|
||||
private Preferences prefs;
|
||||
|
||||
public static final String SIMCONDITION_WIND_SPEED = "SimConditionWindSpeed";
|
||||
public static final String SIMCONDITION_WIND_STDDEV = "SimConditionWindStdDev";
|
||||
public static final String SIMCONDITION_WIND_TURB = "SimConditionWindTurb";
|
||||
public static final String SIMCONDITION_SITE_LAT = "SimConditionSiteLat";
|
||||
public static final String SIMCONDITION_SITE_LON = "SimConditionSiteLon";
|
||||
public static final String SIMCONDITION_SITE_ALT = "SimConditionSiteAlt";
|
||||
public static final String SIMCONDITION_ATMOS_STD = "SimConditionsAtmosStd";
|
||||
public static final String SIMCONDITION_ATMOS_TEMP = "SimConditionsAtmosTemp";
|
||||
public static final String SIMCONDITION_ATMOS_PRESSURE = "SimConditionsAtmosPres";
|
||||
public static final String SIMCONDITION_ROD_LENGTH = "SimConditionsRodLength";
|
||||
public static final String SIMCONDITION_ROD_ANGLE = "SimConditionsRodAngle";
|
||||
public static final String SIMCONDITION_ROD_DIRECTION = "SimConditionsRodDirection";
|
||||
|
||||
public DefaultSimulationOptionFactory(Preferences prefs) {
|
||||
this.prefs = prefs;
|
||||
}
|
||||
|
||||
public DefaultSimulationOptionFactory() {
|
||||
prefs = null;
|
||||
}
|
||||
|
||||
public SimulationOptions getDefault() {
|
||||
SimulationOptions defaults = new SimulationOptions(null);
|
||||
if (prefs != null) {
|
||||
|
||||
defaults.setWindSpeedAverage(prefs.getDouble(SIMCONDITION_WIND_SPEED, defaults.getWindSpeedAverage()));
|
||||
defaults.setWindSpeedDeviation(prefs.getDouble(SIMCONDITION_WIND_STDDEV, defaults.getWindSpeedDeviation()));
|
||||
defaults.setWindTurbulenceIntensity(prefs.getDouble(SIMCONDITION_WIND_TURB, defaults.getWindTurbulenceIntensity()));
|
||||
|
||||
defaults.setLaunchLatitude(prefs.getDouble(SIMCONDITION_SITE_LAT, defaults.getLaunchLatitude()));
|
||||
defaults.setLaunchLongitude(prefs.getDouble(SIMCONDITION_SITE_LON, defaults.getLaunchLongitude()));
|
||||
defaults.setLaunchAltitude(prefs.getDouble(SIMCONDITION_SITE_ALT, defaults.getLaunchAltitude()));
|
||||
|
||||
defaults.setISAAtmosphere(prefs.getBoolean(SIMCONDITION_ATMOS_STD, defaults.isISAAtmosphere()));
|
||||
defaults.setLaunchTemperature(prefs.getDouble(SIMCONDITION_ATMOS_TEMP, defaults.getLaunchTemperature()));
|
||||
|
||||
defaults.setLaunchRodLength(prefs.getDouble(SIMCONDITION_ROD_LENGTH, defaults.getLaunchRodLength()));
|
||||
defaults.setLaunchRodAngle(prefs.getDouble(SIMCONDITION_ROD_ANGLE, defaults.getLaunchRodAngle()));
|
||||
defaults.setLaunchRodDirection(prefs.getDouble(SIMCONDITION_ROD_DIRECTION, defaults.getLaunchRodDirection()));
|
||||
}
|
||||
return defaults;
|
||||
}
|
||||
|
||||
public void saveDefault(SimulationOptions newDefaults) {
|
||||
|
||||
prefs.putDouble(SIMCONDITION_WIND_SPEED, newDefaults.getWindSpeedAverage());
|
||||
prefs.putDouble(SIMCONDITION_WIND_STDDEV, newDefaults.getWindSpeedDeviation());
|
||||
prefs.putDouble(SIMCONDITION_WIND_TURB, newDefaults.getWindTurbulenceIntensity());
|
||||
|
||||
prefs.putDouble(SIMCONDITION_SITE_LAT, newDefaults.getLaunchLatitude());
|
||||
prefs.putDouble(SIMCONDITION_SITE_LON, newDefaults.getLaunchLongitude());
|
||||
prefs.putDouble(SIMCONDITION_SITE_ALT, newDefaults.getLaunchAltitude());
|
||||
|
||||
prefs.putBoolean(SIMCONDITION_ATMOS_STD, newDefaults.isISAAtmosphere());
|
||||
prefs.putDouble(SIMCONDITION_ATMOS_TEMP, newDefaults.getLaunchTemperature());
|
||||
|
||||
prefs.putDouble(SIMCONDITION_ROD_LENGTH, newDefaults.getLaunchRodLength());
|
||||
prefs.putDouble(SIMCONDITION_ROD_ANGLE, newDefaults.getLaunchRodAngle());
|
||||
prefs.putDouble(SIMCONDITION_ROD_DIRECTION, newDefaults.getLaunchRodDirection());
|
||||
}
|
||||
}
|
@ -77,7 +77,12 @@ public class FlightEvent implements Comparable<FlightEvent> {
|
||||
/**
|
||||
* The rocket begins to tumble.
|
||||
*/
|
||||
TUMBLE(trans.get("FlightEvent.Type.TUMBLE"));
|
||||
TUMBLE(trans.get("FlightEvent.Type.TUMBLE")),
|
||||
|
||||
/**
|
||||
* Simulation aborted
|
||||
*/
|
||||
EXCEPTION(trans.get("FlightEvent.Type.EXCEPTION"));
|
||||
|
||||
private final String name;
|
||||
|
||||
|
@ -452,6 +452,25 @@ public class SimulationOptions implements ChangeSource, Cloneable {
|
||||
fireChangeEvent();
|
||||
}
|
||||
|
||||
public void copyConditionsFrom(SimulationOptions src) {
|
||||
|
||||
this.launchAltitude = src.launchAltitude;
|
||||
this.launchLatitude = src.launchLatitude;
|
||||
this.launchLongitude = src.launchLongitude;
|
||||
this.launchPressure = src.launchPressure;
|
||||
this.launchRodAngle = src.launchRodAngle;
|
||||
this.launchRodDirection = src.launchRodDirection;
|
||||
this.launchRodLength = src.launchRodLength;
|
||||
this.launchTemperature = src.launchTemperature;
|
||||
this.maximumAngle = src.maximumAngle;
|
||||
this.timeStep = src.timeStep;
|
||||
this.windAverage = src.windAverage;
|
||||
this.windTurbulence = src.windTurbulence;
|
||||
this.calculateExtras = src.calculateExtras;
|
||||
this.randomSeed = src.randomSeed;
|
||||
|
||||
fireChangeEvent();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
|
@ -11,7 +11,7 @@ public interface SimulationStepper {
|
||||
* @param status the current simulation status.
|
||||
* @return a SimulationStatus suitable for simulating with this simulation stepper.
|
||||
*/
|
||||
public SimulationStatus initialize(SimulationStatus status) throws SimulationException;
|
||||
public SimulationStatus initialize(SimulationStatus status);
|
||||
|
||||
/**
|
||||
* Perform one simulation time step.
|
||||
|
Loading…
x
Reference in New Issue
Block a user