[#24556] Combine sim settings & plot/export dialogs

This commit is contained in:
SiboVG 2024-02-19 17:00:38 +01:00
parent 921124e337
commit addd81b799
7 changed files with 506 additions and 482 deletions

View File

@ -452,9 +452,10 @@ simedtdlg.but.delete = Delete
simedtdlg.title.Editsim = Edit simulation
simedtdlg.title.MultiSimEdit = Multi-simulation edit
simedtdlg.title.MultiSimEdit.ttip = <html>You are editing the following simulations:<br>
simedtdlg.lbl.Simname = Simulation name:
simedtdlg.lbl.Simname = Name:
simedtdlg.tab.Launchcond = Launch conditions
simedtdlg.tab.Simopt = Simulation options
simedtdlg.tab.Settings = Settings
simedtdlg.tab.Plotdata = Plot data
simedtdlg.tab.CustomExpressions = Custom expressions
simedtdlg.tab.Exportdata = Export data
@ -534,6 +535,10 @@ simedtdlg.IntensityDesc.High = High
simedtdlg.IntensityDesc.Veryhigh = Very high
simedtdlg.IntensityDesc.Extreme = Extreme
! SimulationConfigDialog
SimulationConfigDialog.tab.plotDis.ttip = Plotting not supported for multi-simulation editing
SimulationConfigDialog.tab.expDis.ttip = Exporting not supported for multi-simulation editing
SimulationExtension.airstart.name.alt = Air-start ({alt})
SimulationExtension.airstart.name.altvel = Air-start ({alt}, {vel})
SimulationExtension.javacode.name = Java code

View File

@ -321,7 +321,7 @@ simedtdlg.but.savedefault = Save as default
simedtdlg.but.add = Add
simedtdlg.but.delete = Delete
simedtdlg.title.Editsim = Edit simulation
simedtdlg.lbl.Simname = Simulation name:
simedtdlg.lbl.Simname = Name:
simedtdlg.tab.Launchcond = Launch conditions
simedtdlg.tab.Simopt = Simulation options
simedtdlg.tab.Plotdata = Plot data

View File

@ -45,6 +45,7 @@ import javax.swing.table.DefaultTableCellRenderer;
import net.sf.openrocket.arch.SystemInfo;
import net.sf.openrocket.gui.components.CsvOptionPanel;
import net.sf.openrocket.gui.simulation.SimulationConfigDialog;
import net.sf.openrocket.gui.util.ColorConversion;
import net.sf.openrocket.gui.util.FileHelper;
import net.sf.openrocket.gui.util.GUIUtil;
@ -57,7 +58,6 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import net.miginfocom.swing.MigLayout;
import net.sf.openrocket.logging.Warning;
import net.sf.openrocket.logging.WarningSet;
import net.sf.openrocket.document.OpenRocketDocument;
import net.sf.openrocket.document.Simulation;
@ -72,7 +72,6 @@ import net.sf.openrocket.gui.adaptors.ColumnTableModel;
import net.sf.openrocket.gui.adaptors.ColumnTableRowSorter;
import net.sf.openrocket.gui.adaptors.ValueColumn;
import net.sf.openrocket.gui.components.StyledLabel;
import net.sf.openrocket.gui.simulation.SimulationEditDialog;
import net.sf.openrocket.gui.simulation.SimulationRunDialog;
import net.sf.openrocket.gui.simulation.SimulationWarningDialog;
import net.sf.openrocket.gui.util.Icons;
@ -888,9 +887,11 @@ public class SimulationPanel extends JPanel {
}
private void openDialog(boolean plotMode, boolean isNewSimulation, final Simulation... sims) {
SimulationEditDialog d = new SimulationEditDialog(SwingUtilities.getWindowAncestor(this), document, isNewSimulation, sims);
SimulationConfigDialog d = new SimulationConfigDialog(SwingUtilities.getWindowAncestor(this), document, isNewSimulation, sims);
if (plotMode) {
d.setPlotMode();
d.switchToPlotTab();
} else {
d.switchToSettingsTab();
}
d.setVisible(true);
fireMaintainSelection();

View File

@ -0,0 +1,456 @@
package net.sf.openrocket.gui.simulation;
import net.miginfocom.swing.MigLayout;
import net.sf.openrocket.document.OpenRocketDocument;
import net.sf.openrocket.document.Simulation;
import net.sf.openrocket.document.events.DocumentChangeEvent;
import net.sf.openrocket.gui.components.ConfigurationComboBox;
import net.sf.openrocket.gui.components.StyledLabel;
import net.sf.openrocket.gui.util.GUIUtil;
import net.sf.openrocket.gui.util.UITheme;
import net.sf.openrocket.gui.widgets.SelectColorButton;
import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.rocketcomponent.FlightConfiguration;
import net.sf.openrocket.rocketcomponent.FlightConfigurationId;
import net.sf.openrocket.rocketcomponent.Rocket;
import net.sf.openrocket.simulation.extension.SimulationExtension;
import net.sf.openrocket.startup.Application;
import net.sf.openrocket.startup.Preferences;
import net.sf.openrocket.util.StateChangeListener;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import javax.swing.JTextField;
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 java.awt.Color;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.util.ArrayList;
import java.util.EventObject;
import java.util.List;
public class SimulationConfigDialog extends JDialog {
private static final long serialVersionUID = -1068127685642912715L;
private final Window parentWindow;
private final Simulation[] simulationList;
private final OpenRocketDocument document;
private final JTabbedPane tabbedPane;
private JButton okButton;
private JButton cancelButton;
private static final Translator trans = Application.getTranslator();
private static final Preferences preferences = Application.getPreferences();
private final WindowListener applyChangesToSimsListener;
private final Simulation initialSim; // A copy of the first selected simulation before it was modified
private final boolean initialIsSaved; // Whether the document was saved before the dialog was opened
private boolean isModified = false; // Whether the simulation has been modified
private final boolean isNewSimulation; // Whether you are editing a new simulation, or an existing one
private static final int SETTINGS_IDX = 0;
private static final int PLOT_IDX = 1;
private static final int EXPORT_IDX = 2;
private final SimulationPlotPanel plotTab;
private final SimulationExportPanel exportTab;
private static Color multiCompEditColor;
static {
initColors();
}
public SimulationConfigDialog(Window parent, final OpenRocketDocument document, boolean isNewSimulation, Simulation... sims) {
super(parent, sims.length == 1 ? trans.get("simedtdlg.title.Editsim") : trans.get("simedtdlg.title.MultiSimEdit"),
JDialog.ModalityType.DOCUMENT_MODAL);
this.document = document;
this.parentWindow = parent;
this.simulationList = sims;
this.initialSim = simulationList[0].clone();
this.initialIsSaved = document.isSaved();
this.isNewSimulation = isNewSimulation;
simulationList[0].addChangeListener(new StateChangeListener() {
@Override
public void stateChanged(EventObject e) {
isModified = true;
setTitle("* " + getTitle()); // Add component changed indicator to the title
simulationList[0].removeChangeListener(this);
}
});
final JPanel contentPanel = new JPanel(new MigLayout("fill"));
// ======== Top panel ========
addTopPanel(document, contentPanel);
// ======== Tabbed pane ========
this.tabbedPane = new JTabbedPane();
//// Simulation Settings
final SimulationSettingsPanel settingsTab = new SimulationSettingsPanel(document, simulationList[0]);
tabbedPane.addTab(trans.get("simedtdlg.tab.Settings"), settingsTab);
//// Plot data
this.plotTab = new SimulationPlotPanel(simulationList[0]);
tabbedPane.addTab(trans.get("simedtdlg.tab.Plotdata"), plotTab);
if (isMultiCompEdit()) {
tabbedPane.setEnabledAt(PLOT_IDX, false);
tabbedPane.setToolTipTextAt(PLOT_IDX, trans.get("SimulationConfigDialog.tab.plotDis.ttip"));
}
//// Export data
this.exportTab = new SimulationExportPanel(simulationList[0]);
tabbedPane.addTab(trans.get("simedtdlg.tab.Exportdata"), exportTab);
if (isMultiCompEdit()) {
tabbedPane.setEnabledAt(EXPORT_IDX, false);
tabbedPane.setToolTipTextAt(EXPORT_IDX, trans.get("SimulationConfigDialog.tab.expDis.ttip"));
}
contentPanel.add(tabbedPane, "grow, wrap");
// ======== Bottom panel ========
addBottomPanel(contentPanel);
tabbedPane.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
if (okButton == null) {
return;
}
int selectedIndex = tabbedPane.getSelectedIndex();
switch (selectedIndex) {
case SETTINGS_IDX:
okButton.setText(trans.get("dlg.but.ok"));
cancelButton.setText(trans.get("dlg.but.cancel"));
SimulationConfigDialog.this.revalidate();
break;
case PLOT_IDX:
okButton.setText(trans.get("SimulationEditDialog.btn.plot"));
cancelButton.setText(trans.get("dlg.but.close"));
SimulationConfigDialog.this.revalidate();
break;
case EXPORT_IDX:
okButton.setText(trans.get("SimulationEditDialog.btn.export"));
cancelButton.setText(trans.get("dlg.but.close"));
SimulationConfigDialog.this.revalidate();
break;
}
}
});
this.add(contentPanel);
this.validate();
this.pack();
this.setLocationByPlatform(true);
this.applyChangesToSimsListener = new WindowAdapter() {
@Override
public void windowClosed(WindowEvent e) {
copyChangesToAllSims();
}
};
this.addWindowListener(applyChangesToSimsListener);
GUIUtil.setDisposableDialogOptions(this, null);
}
private static void initColors() {
updateColors();
UITheme.Theme.addUIThemeChangeListener(SimulationConfigDialog::updateColors);
}
private static void updateColors() {
multiCompEditColor = GUIUtil.getUITheme().getMultiCompEditColor();
}
public void switchToSettingsTab() {
tabbedPane.setSelectedIndex(SETTINGS_IDX);
}
public void switchToPlotTab() {
tabbedPane.setSelectedIndex(PLOT_IDX);
}
public void switchToExportTab() {
tabbedPane.setSelectedIndex(EXPORT_IDX);
}
private void addTopPanel(OpenRocketDocument document, JPanel contentPanel) {
JPanel topPanel = new JPanel(new MigLayout("fill, ins 0"));
//// Name:
topPanel.add(new JLabel(trans.get("simedtdlg.lbl.Simname") + " "), "growx 0, gapright para");
final JTextField field = new JTextField(simulationList[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;
simulationList[0].setName(name);
}
});
topPanel.add(field, "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"));
topPanel.add(label, "growx 0, gapright para");
final Rocket rkt = document.getRocket();
final FlightConfiguration config = rkt.getFlightConfiguration(simulationList[0].getFlightConfigurationId());
final ConfigurationComboBox configComboBox = new ConfigurationComboBox(rkt, false);
configComboBox.setSelectedItem(config);
//// Select the motor configuration to use.
configComboBox.setToolTipText(trans.get("simedtdlg.combo.ttip.Flightcfg"));
configComboBox.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
FlightConfiguration config = (FlightConfiguration)configComboBox.getSelectedItem();
FlightConfigurationId id = config.getId();
simulationList[0].setFlightConfigurationId( id );
}
});
topPanel.add(configComboBox, "span");
topPanel.add(new JPanel(), "growx, wrap");
contentPanel.add(topPanel, "growx, wrap");
}
private void addBottomPanel(JPanel contentPanel) {
final JPanel bottomPanel = new JPanel(new MigLayout("fill, ins 0"));
//// Multi-simulation edit
if (isMultiCompEdit()) {
StyledLabel multiSimEditLabel = new StyledLabel("", -1, StyledLabel.Style.BOLD);
multiSimEditLabel.setFontColor(multiCompEditColor);
multiSimEditLabel.setText(trans.get("simedtdlg.title.MultiSimEdit"));
StringBuilder components = new StringBuilder(trans.get("simedtdlg.title.MultiSimEdit.ttip"));
for (int i = 0; i < simulationList.length; i++) {
if (i < simulationList.length - 1) {
components.append(simulationList[i].getName()).append(", ");
} else {
components.append(simulationList[i].getName());
}
}
multiSimEditLabel.setToolTipText(components.toString());
bottomPanel.add(multiSimEditLabel, "align left");
}
//// Run simulation button
// TODO: disable when sim is up to date?
/*JButton button = new SelectColorButton(trans.get("SimulationEditDialog.btn.simulateAndPlot"));
if (!isSingleEdit()) {
button.setText(trans.get("SimulationEditDialog.btn.simulate"));
}
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
copyChangesToAllSims();
SimulationRunDialog dialog = SimulationRunDialog.runSimulations(parentWindow, SimulationEditDialog.this.document, simulationList);
if (allowsPlotMode() && dialog.isAllSimulationsSuccessful()) {
refreshView();
setPlotMode();
}
}
});
simEditPanel.add(button, "align right, gapright 10lp, tag ok");*/
//// Cancel button
this.cancelButton = new SelectColorButton(trans.get("dlg.but.cancel"));
this.cancelButton.setToolTipText(trans.get("SimulationEditDialog.btn.Cancel.ttip"));
this.cancelButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (tabbedPane.getSelectedIndex() == SETTINGS_IDX) {
cancelSimEdit();
} else {
// Normal close action
closeDialog();
}
// TODO: include plot/export undo?
}
});
bottomPanel.add(this.cancelButton, "split 2, tag ok");
//// Ok button
this.okButton = new SelectColorButton(trans.get("dlg.but.ok"));
this.okButton.setToolTipText(trans.get("SimulationEditDialog.btn.OK.ttip"));
this.okButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
copyChangesToAllSims();
// Run outdated simulations
Simulation[] outdatedSims = getOutdatedSimulations();
if (outdatedSims.length > 0) {
new SimulationRunDialog(SimulationConfigDialog.this.parentWindow, document, outdatedSims).setVisible(true);
}
int tabIdx = tabbedPane.getSelectedIndex();
if (tabIdx == PLOT_IDX) {
JDialog plot = plotTab.doPlot(SimulationConfigDialog.this.parentWindow);
if (plot != null) {
plot.setVisible(true);
}
closeDialog();
return;
} else if (tabIdx == EXPORT_IDX) {
if (exportTab.doExport()) {
closeDialog();
}
return;
}
closeDialog();
}
});
bottomPanel.add(this.okButton, "tag ok");
contentPanel.add(bottomPanel, "growx, wrap");
}
private void copyChangesToAllSims() {
if (isMultiCompEdit()) {
for (int i = 1; i < simulationList.length; i++) {
simulationList[i].getOptions().copyConditionsFrom(simulationList[0].getOptions());
simulationList[i].getSimulationExtensions().clear();
for (SimulationExtension c : simulationList[0].getSimulationExtensions()) {
simulationList[i].getSimulationExtensions().add(c.clone());
}
}
}
}
private Simulation[] getOutdatedSimulations() {
List<Simulation> outdated = new ArrayList<>();
for (Simulation sim : simulationList) {
if (!Simulation.isStatusUpToDate(sim.getStatus())) {
outdated.add(sim);
}
}
return outdated.toArray(new Simulation[0]);
}
private boolean isMultiCompEdit() {
return simulationList.length > 1;
}
private void closeDialog() {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
SimulationConfigDialog.this.removeWindowListener(applyChangesToSimsListener);
SimulationConfigDialog.this.dispose();
}
});
}
private JPanel createCancelOperationContent() {
JPanel panel = new JPanel(new MigLayout());
String msg = isNewSimulation ? trans.get("SimulationEditDialog.CancelOperation.msg.undoAdd") :
trans.get("SimulationEditDialog.CancelOperation.msg.discardChanges");
JLabel msgLabel = new JLabel(msg);
JCheckBox dontAskAgain = new JCheckBox(trans.get("SimulationEditDialog.CancelOperation.checkbox.dontAskAgain"));
dontAskAgain.setSelected(false);
dontAskAgain.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
preferences.setShowDiscardSimulationConfirmation(false);
}
// Unselected state should be not be possible and thus not be handled
}
});
panel.add(msgLabel, "left, wrap");
panel.add(dontAskAgain, "left, gaptop para");
return panel;
}
private void cancelSimEdit() {
// Don't do anything on cancel if you are editing an existing simulation, and it is not modified
if (!isNewSimulation && !isModified) {
closeDialog();
return;
}
// Apply the cancel operation if set to auto discard in preferences
if (!preferences.isShowDiscardSimulationConfirmation()) {
discardChanges();
return;
}
// Yes/No dialog: Are you sure you want to discard your changes?
JPanel msg = createCancelOperationContent();
int resultYesNo = JOptionPane.showConfirmDialog(SimulationConfigDialog.this, msg,
trans.get("SimulationEditDialog.CancelOperation.title"), JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE);
if (resultYesNo == JOptionPane.YES_OPTION) {
discardChanges();
}
}
private void discardChanges() {
if (isNewSimulation) {
document.removeSimulation(simulationList[0]);
} else {
undoSimulationChanges();
}
document.setSaved(this.initialIsSaved); // Restore the saved state of the document
document.fireDocumentChangeEvent(new DocumentChangeEvent(this));
closeDialog();
}
private void undoSimulationChanges() {
if (simulationList == null || simulationList.length == 0) {
return;
}
simulationList[0].loadFrom(initialSim);
}
}

View File

@ -1,476 +0,0 @@
package net.sf.openrocket.gui.simulation;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.util.EventObject;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import javax.swing.JTextField;
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.document.events.DocumentChangeEvent;
import net.sf.openrocket.gui.components.ConfigurationComboBox;
import net.sf.openrocket.gui.components.StyledLabel;
import net.sf.openrocket.gui.util.GUIUtil;
import net.sf.openrocket.gui.util.UITheme;
import net.sf.openrocket.gui.widgets.SelectColorButton;
import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.rocketcomponent.FlightConfiguration;
import net.sf.openrocket.rocketcomponent.FlightConfigurationId;
import net.sf.openrocket.rocketcomponent.Rocket;
import net.sf.openrocket.simulation.extension.SimulationExtension;
import net.sf.openrocket.startup.Application;
import net.sf.openrocket.startup.Preferences;
import net.sf.openrocket.util.StateChangeListener;
public class SimulationEditDialog extends JDialog {
private static final long serialVersionUID = -4468157685542912715L;
private final Window parentWindow;
private final Simulation[] simulationList;
private final OpenRocketDocument document;
private static final Translator trans = Application.getTranslator();
private static final Preferences preferences = Application.getPreferences();
JPanel cards;
private final static String EDITMODE = "EDIT";
private final static String PLOTMODE = "PLOT";
private final WindowListener applyChangesToSimsListener;
private final Simulation initialSim; // A copy of the first selected simulation before it was modified
private final boolean initialIsSaved; // Whether the document was saved before the dialog was opened
private boolean isModified = false; // Whether the simulation has been modified
private final boolean isNewSimulation; // Whether you are editing a new simulation, or an existing one
private static Color multiCompEditColor;
static {
initColors();
}
public SimulationEditDialog(Window parent, final OpenRocketDocument document, boolean isNewSimulation, Simulation... sims) {
//// Edit simulation
super(parent, sims.length == 1 ? trans.get("simedtdlg.title.Editsim") : trans.get("simedtdlg.title.MultiSimEdit"),
JDialog.ModalityType.DOCUMENT_MODAL);
this.document = document;
this.parentWindow = parent;
this.simulationList = sims;
this.initialSim = simulationList[0].clone();
this.initialIsSaved = document.isSaved();
this.isNewSimulation = isNewSimulation;
simulationList[0].addChangeListener(new StateChangeListener() {
@Override
public void stateChanged(EventObject e) {
isModified = true;
setTitle("* " + getTitle()); // Add component changed indicator to the title
simulationList[0].removeChangeListener(this);
}
});
this.cards = new JPanel(new CardLayout());
this.add(cards);
buildEditCard();
buildPlotCard();
this.validate();
this.pack();
this.setLocationByPlatform(true);
this.applyChangesToSimsListener = new WindowAdapter() {
@Override
public void windowClosed(WindowEvent e) {
copyChangesToAllSims();
}
};
this.addWindowListener(applyChangesToSimsListener);
GUIUtil.setDisposableDialogOptions(this, null);
}
private static void initColors() {
updateColors();
UITheme.Theme.addUIThemeChangeListener(SimulationEditDialog::updateColors);
}
private static void updateColors() {
multiCompEditColor = GUIUtil.getUITheme().getMultiCompEditColor();
}
private boolean isSingleEdit() {
return simulationList.length == 1;
}
private boolean allowsPlotMode() {
return simulationList.length == 1 && simulationList[0].hasSimulationData();
}
public void setEditMode() {
String baseTitle = simulationList.length == 1 ?
trans.get("simedtdlg.title.Editsim") : trans.get("simedtdlg.title.MultiSimEdit");
setTitle((isModified ? "* " : "") + baseTitle);
CardLayout cl = (CardLayout) (cards.getLayout());
cl.show(cards, EDITMODE);
cards.validate();
this.addWindowListener(applyChangesToSimsListener);
}
public void setPlotMode() {
if (!allowsPlotMode()) {
return;
}
this.removeWindowListener(applyChangesToSimsListener);
setTitle((isModified ? "* " : "") + trans.get("simplotpanel.title.Plotsim"));
CardLayout cl = (CardLayout) (cards.getLayout());
cl.show(cards, PLOTMODE);
cards.validate();
}
private void copyChangesToAllSims() {
if (simulationList.length > 1) {
for (int i = 1; i < simulationList.length; i++) {
simulationList[i].getOptions().copyConditionsFrom(simulationList[0].getOptions());
simulationList[i].getSimulationExtensions().clear();
for (SimulationExtension c : simulationList[0].getSimulationExtensions()) {
simulationList[i].getSimulationExtensions().add(c.clone());
}
}
}
}
private void refreshView() {
cards.removeAll();
buildEditCard();
buildPlotCard();
this.validate();
}
private void buildEditCard() {
JPanel simEditPanel = new JPanel(new MigLayout("fill, hidemode 1"));
if (isSingleEdit()) {
JPanel panel = new JPanel(new MigLayout("fill, ins 0"));
//// Simulation name:
panel.add(new JLabel(trans.get("simedtdlg.lbl.Simname") + " "), "growx 0, gapright para");
final JTextField field = new JTextField(simulationList[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;
simulationList[0].setName(name);
}
});
panel.add(field, "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"));
panel.add(label, "growx 0, gapright para");
final Rocket rkt = document.getRocket();
final FlightConfiguration config = rkt.getFlightConfiguration(simulationList[0].getFlightConfigurationId());
final ConfigurationComboBox configComboBox = new ConfigurationComboBox(rkt, false);
configComboBox.setSelectedItem(config);
//// Select the motor configuration to use.
configComboBox.setToolTipText(trans.get("simedtdlg.combo.ttip.Flightcfg"));
configComboBox.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
FlightConfiguration config = (FlightConfiguration)configComboBox.getSelectedItem();
FlightConfigurationId id = config.getId();
simulationList[0].setFlightConfigurationId( id );
}
});
panel.add(configComboBox, "span");
panel.add(new JPanel(), "growx, wrap");
simEditPanel.add(panel, "growx, wrap");
}
JTabbedPane tabbedPane = new JTabbedPane();
//// Launch conditions
tabbedPane.addTab(trans.get("simedtdlg.tab.Launchcond"), new SimulationConditionsPanel(simulationList[0]));
//// Simulation options
tabbedPane.addTab(trans.get("simedtdlg.tab.Simopt"), new SimulationOptionsPanel(document, simulationList[0]));
tabbedPane.setSelectedIndex(0);
simEditPanel.add(tabbedPane, "spanx, grow, wrap");
//// Open Plot button
JButton button = new SelectColorButton(trans.get("SimulationEditDialog.btn.plot") + " >>");
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
SimulationEditDialog.this.setPlotMode();
}
});
simEditPanel.add(button, "spanx, split 5, align left");
if (allowsPlotMode()) {
button.setVisible(true);
} else {
button.setVisible(false);
}
//// Multi-simulation edit
if (simulationList.length > 1) {
StyledLabel multiSimEditLabel = new StyledLabel("", -1, StyledLabel.Style.BOLD);
multiSimEditLabel.setFontColor(multiCompEditColor);
multiSimEditLabel.setText(trans.get("simedtdlg.title.MultiSimEdit"));
StringBuilder components = new StringBuilder(trans.get("simedtdlg.title.MultiSimEdit.ttip"));
for (int i = 0; i < simulationList.length; i++) {
if (i < simulationList.length - 1) {
components.append(simulationList[i].getName()).append(", ");
} else {
components.append(simulationList[i].getName());
}
}
multiSimEditLabel.setToolTipText(components.toString());
simEditPanel.add(multiSimEditLabel, "align left");
}
//// Run simulation button
button = new SelectColorButton(trans.get("SimulationEditDialog.btn.simulateAndPlot"));
if (!isSingleEdit()) {
button.setText(trans.get("SimulationEditDialog.btn.simulate"));
}
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
copyChangesToAllSims();
SimulationRunDialog dialog = SimulationRunDialog.runSimulations(parentWindow, SimulationEditDialog.this.document, simulationList);
if (allowsPlotMode() && dialog.isAllSimulationsSuccessful()) {
refreshView();
setPlotMode();
}
}
});
simEditPanel.add(button, "align right, gapright 10lp, tag ok");
//// Cancel button
JButton cancelButton = new SelectColorButton(trans.get("dlg.but.cancel"));
cancelButton.setToolTipText(trans.get("SimulationEditDialog.btn.Cancel.ttip"));
cancelButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// Don't do anything on cancel if you are editing an existing simulation, and it is not modified
if (!isNewSimulation && !isModified) {
SimulationEditDialog.this.removeWindowListener(applyChangesToSimsListener);
SimulationEditDialog.this.dispose();
return;
}
// Apply the cancel operation if set to auto discard in preferences
if (!preferences.isShowDiscardSimulationConfirmation()) {
discardChanges();
return;
}
// Yes/No dialog: Are you sure you want to discard your changes?
JPanel msg = createCancelOperationContent();
int resultYesNo = JOptionPane.showConfirmDialog(SimulationEditDialog.this, msg,
trans.get("SimulationEditDialog.CancelOperation.title"), JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE);
if (resultYesNo == JOptionPane.YES_OPTION) {
discardChanges();
}
}
});
simEditPanel.add(cancelButton, "tag ok");
//// Ok button
JButton okButton = new SelectColorButton(trans.get("dlg.but.ok"));
okButton.setToolTipText(trans.get("SimulationEditDialog.btn.OK.ttip"));
okButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
copyChangesToAllSims();
SimulationEditDialog.this.dispose();
}
});
simEditPanel.add(okButton, "tag ok");
cards.add(simEditPanel, EDITMODE);
}
private void buildPlotCard() {
if (allowsPlotMode()) {
JPanel plotExportPanel = new JPanel(new MigLayout("fill"));
//// Simulation name:
plotExportPanel.add(new JLabel(trans.get("simedtdlg.lbl.Simname") + " "), "span, split 2, shrink");
final JTextField field = new JTextField(simulationList[0].getName());
field.setEditable(false);
plotExportPanel.add(field, "shrinky, growx, wrap");
final JTabbedPane tabbedPane = new JTabbedPane();
//// Plot data
final SimulationPlotPanel plotTab = new SimulationPlotPanel(simulationList[0]);
tabbedPane.addTab(trans.get("simedtdlg.tab.Plotdata"), plotTab);
//// Export data
final SimulationExportPanel exportTab = new SimulationExportPanel(simulationList[0]);
tabbedPane.addTab(trans.get("simedtdlg.tab.Exportdata"), exportTab);
plotExportPanel.add(tabbedPane, "grow, wrap");
JButton button = new SelectColorButton("<< " + trans.get("SimulationEditDialog.btn.edit"));
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
SimulationEditDialog.this.setEditMode();
}
});
plotExportPanel.add(button, "spanx, split 3, align left");
final JButton ok = new SelectColorButton(trans.get("SimulationEditDialog.btn.plot"));
tabbedPane.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
int selectedIndex = tabbedPane.getSelectedIndex();
switch (selectedIndex) {
case 0:
ok.setText(trans.get("SimulationEditDialog.btn.plot"));
plotExportPanel.revalidate();
break;
case 1:
ok.setText(trans.get("SimulationEditDialog.btn.export"));
plotExportPanel.revalidate();
break;
}
}
});
ok.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// If the simulation is out of date, run the simulation.
if (!Simulation.isStatusUpToDate(simulationList[0].getStatus())) {
new SimulationRunDialog(SimulationEditDialog.this.parentWindow, document, simulationList[0]).setVisible(true);
}
if (tabbedPane.getSelectedIndex() == 0) {
JDialog plot = plotTab.doPlot(SimulationEditDialog.this.parentWindow);
if (plot != null) {
plot.setVisible(true);
}
} else {
if (exportTab.doExport()) {
SimulationEditDialog.this.dispose();
}
}
}
});
plotExportPanel.add(ok, "tag ok, split 2");
//// Close button
JButton close = new SelectColorButton(trans.get("dlg.but.close"));
close.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
SimulationEditDialog.this.dispose();
}
});
plotExportPanel.add(close, "tag cancel");
//plotExportPanel.validate();
cards.add(plotExportPanel, PLOTMODE);
}
}
private JPanel createCancelOperationContent() {
JPanel panel = new JPanel(new MigLayout());
String msg = isNewSimulation ? trans.get("SimulationEditDialog.CancelOperation.msg.undoAdd") :
trans.get("SimulationEditDialog.CancelOperation.msg.discardChanges");
JLabel msgLabel = new JLabel(msg);
JCheckBox dontAskAgain = new JCheckBox(trans.get("SimulationEditDialog.CancelOperation.checkbox.dontAskAgain"));
dontAskAgain.setSelected(false);
dontAskAgain.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
preferences.setShowDiscardSimulationConfirmation(false);
}
// Unselected state should be not be possible and thus not be handled
}
});
panel.add(msgLabel, "left, wrap");
panel.add(dontAskAgain, "left, gaptop para");
return panel;
}
private void discardChanges() {
if (isNewSimulation) {
document.removeSimulation(simulationList[0]);
} else {
undoSimulationChanges();
}
document.setSaved(this.initialIsSaved); // Restore the saved state of the document
document.fireDocumentChangeEvent(new DocumentChangeEvent(this));
SimulationEditDialog.this.removeWindowListener(applyChangesToSimsListener);
SimulationEditDialog.this.dispose();
}
private void undoSimulationChanges() {
if (simulationList == null || simulationList.length == 0) {
return;
}
simulationList[0].loadFrom(initialSim);
}
}

View File

@ -5,6 +5,7 @@ import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.io.Serial;
import java.util.Arrays;
import java.util.EnumSet;
@ -51,6 +52,7 @@ import net.sf.openrocket.gui.widgets.SelectColorButton;
* @author Sampo Niskanen <sampo.niskanen@iki.fi>
*/
public class SimulationPlotPanel extends JPanel {
@Serial
private static final long serialVersionUID = -2227129713185477998L;
private static final Translator trans = Application.getTranslator();

View File

@ -0,0 +1,36 @@
package net.sf.openrocket.gui.simulation;
import net.miginfocom.swing.MigLayout;
import net.sf.openrocket.document.OpenRocketDocument;
import net.sf.openrocket.document.Simulation;
import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.startup.Application;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import java.io.Serial;
public class SimulationSettingsPanel extends JPanel {
@Serial
private static final long serialVersionUID = -2114129713185477998L;
private static final Translator trans = Application.getTranslator();
public SimulationSettingsPanel(final OpenRocketDocument document, final Simulation simulation) {
super(new MigLayout("fill"));
JTabbedPane tabbedPane = new JTabbedPane();
//// Launch conditions
tabbedPane.addTab(trans.get("simedtdlg.tab.Launchcond"), new SimulationConditionsPanel(simulation));
//// Simulation options
tabbedPane.addTab(trans.get("simedtdlg.tab.Simopt"), new SimulationOptionsPanel(document, simulation));
tabbedPane.setSelectedIndex(0);
this.add(tabbedPane, "spanx, grow, wrap");
}
}