Merge pull request #2308 from SiboVG/issue-2307

[#2307] Add dedicated undo actions + fix multi-comp editing for motors & recovery settings
This commit is contained in:
Sibo Van Gool 2023-09-02 00:20:21 +02:00 committed by GitHub
commit 9de395c4aa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 220 additions and 110 deletions

View File

@ -30,8 +30,7 @@ public abstract class RecoveryDevice extends MassObject implements FlightConfigu
private FlightConfigurableParameterSet<DeploymentConfiguration> deploymentConfigurations; private FlightConfigurableParameterSet<DeploymentConfiguration> deploymentConfigurations;
public RecoveryDevice() { public RecoveryDevice() {
this.deploymentConfigurations = this.deploymentConfigurations = new FlightConfigurableParameterSet<>( new DeploymentConfiguration());
new FlightConfigurableParameterSet<DeploymentConfiguration>( new DeploymentConfiguration());
defaultMaterial = (Material.Surface) Application.getPreferences().getDefaultComponentMaterial(RecoveryDevice.class, Material.Type.SURFACE); defaultMaterial = (Material.Surface) Application.getPreferences().getDefaultComponentMaterial(RecoveryDevice.class, Material.Type.SURFACE);
setMaterial(Application.getPreferences().getDefaultComponentMaterial(RecoveryDevice.class, Material.Type.SURFACE)); setMaterial(Application.getPreferences().getDefaultComponentMaterial(RecoveryDevice.class, Material.Type.SURFACE));
} }
@ -148,7 +147,7 @@ public abstract class RecoveryDevice extends MassObject implements FlightConfigu
@Override @Override
protected RocketComponent copyWithOriginalID() { protected RocketComponent copyWithOriginalID() {
RecoveryDevice copy = (RecoveryDevice) super.copyWithOriginalID(); RecoveryDevice copy = (RecoveryDevice) super.copyWithOriginalID();
copy.deploymentConfigurations = new FlightConfigurableParameterSet<DeploymentConfiguration>(deploymentConfigurations); copy.deploymentConfigurations = new FlightConfigurableParameterSet<>(deploymentConfigurations);
return copy; return copy;
} }

View File

@ -4,6 +4,7 @@ import java.awt.Dialog;
import java.awt.Window; import java.awt.Window;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.awt.event.ActionListener; import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import javax.swing.ButtonGroup; import javax.swing.ButtonGroup;
import javax.swing.JButton; import javax.swing.JButton;
@ -46,12 +47,12 @@ public class DeploymentSelectionDialog extends JDialog {
private final JSpinner altSpinner; private final JSpinner altSpinner;
private final UnitSelector altUnit; private final UnitSelector altUnit;
private final JSlider altSlider; private final JSlider altSlider;
private boolean isOverrideDefault;
public DeploymentSelectionDialog(Window parent, final Rocket rocket, final RecoveryDevice component) { public DeploymentSelectionDialog(Window parent, final Rocket rocket, final FlightConfigurationId id, final RecoveryDevice component) {
super(parent, trans.get("edtmotorconfdlg.title.Selectdeploymentconf"), Dialog.ModalityType.APPLICATION_MODAL); super(parent, trans.get("edtmotorconfdlg.title.Selectdeploymentconf"), Dialog.ModalityType.APPLICATION_MODAL);
final FlightConfigurationId id = rocket.getSelectedConfiguration().getFlightConfigurationID();
newConfiguration = component.getDeploymentConfigurations().get(id).clone(); newConfiguration = component.getDeploymentConfigurations().get(id).clone();
JPanel panel = new JPanel(new MigLayout("fill")); JPanel panel = new JPanel(new MigLayout("fill"));
@ -61,15 +62,16 @@ public class DeploymentSelectionDialog extends JDialog {
panel.add(defaultButton, "span, gapleft para, wrap rel"); panel.add(defaultButton, "span, gapleft para, wrap rel");
String str = trans.get("DeploymentSelectionDialog.opt.override"); String str = trans.get("DeploymentSelectionDialog.opt.override");
str = str.replace("{0}", descriptor.format(rocket, id)); str = str.replace("{0}", descriptor.format(rocket, id));
final JRadioButton overrideButton = new JRadioButton(str, false); final JRadioButton overrideButton = new JRadioButton(str);
overrideButton.addItemListener(e -> isOverrideDefault = e.getStateChange() == ItemEvent.SELECTED);
overrideButton.setSelected(false);
panel.add(overrideButton, "span, gapleft para, wrap para"); panel.add(overrideButton, "span, gapleft para, wrap para");
ButtonGroup buttonGroup = new ButtonGroup(); ButtonGroup buttonGroup = new ButtonGroup();
buttonGroup.add(defaultButton); buttonGroup.add(defaultButton);
buttonGroup.add(overrideButton); buttonGroup.add(overrideButton);
// Select the button based on current configuration. If the configuration is overridden // Select the button based on current configuration. If the configuration is overridden, the overrideButton is selected.
// The the overrideButton is selected.
boolean isOverridden = !component.getDeploymentConfigurations().isDefault(id); boolean isOverridden = !component.getDeploymentConfigurations().isDefault(id);
if (isOverridden) { if (isOverridden) {
overrideButton.setSelected(true); overrideButton.setSelected(true);
@ -79,7 +81,7 @@ public class DeploymentSelectionDialog extends JDialog {
//// Deploys at: //// Deploys at:
panel.add(new JLabel(trans.get("ParachuteCfg.lbl.Deploysat")), ""); panel.add(new JLabel(trans.get("ParachuteCfg.lbl.Deploysat")), "");
final JComboBox<DeployEvent> deployEvent = new JComboBox<DeployEvent>(new EnumModel<DeployEvent>(newConfiguration, "DeployEvent")); final JComboBox<DeployEvent> deployEvent = new JComboBox<DeployEvent>(new EnumModel<>(newConfiguration, "DeployEvent"));
if( (component.getStageNumber() + 1 ) == rocket.getStageCount() ){ if( (component.getStageNumber() + 1 ) == rocket.getStageCount() ){
// This is the bottom stage: Restrict deployment options. // This is the bottom stage: Restrict deployment options.
deployEvent.removeItem( DeployEvent.LOWER_STAGE_SEPARATION ); deployEvent.removeItem( DeployEvent.LOWER_STAGE_SEPARATION );
@ -149,6 +151,7 @@ public class DeploymentSelectionDialog extends JDialog {
this.setContentPane(panel); this.setContentPane(panel);
GUIUtil.setDisposableDialogOptions(this, okButton); GUIUtil.setDisposableDialogOptions(this, okButton);
GUIUtil.installEscapeCloseButtonOperation(this, okButton);
} }
private void updateState() { private void updateState() {
@ -158,6 +161,12 @@ public class DeploymentSelectionDialog extends JDialog {
altUnit.setEnabled(enabled); altUnit.setEnabled(enabled);
altSlider.setEnabled(enabled); altSlider.setEnabled(enabled);
} }
/**
* Returns true if this dialog was used to override the default configuration.
* @return true if this dialog was used to override the default configuration.
*/
public boolean isOverrideDefault() {
return isOverrideDefault;
}
} }

View File

@ -4,6 +4,7 @@ import java.awt.Dialog;
import java.awt.Window; import java.awt.Window;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.awt.event.ActionListener; import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.util.Iterator; import java.util.Iterator;
import javax.swing.ButtonGroup; import javax.swing.ButtonGroup;
@ -44,6 +45,8 @@ public class IgnitionSelectionDialog extends JDialog {
private IgnitionEvent startIgnitionEvent; private IgnitionEvent startIgnitionEvent;
private double startIgnitionDelay; private double startIgnitionDelay;
private boolean isOverrideDefault;
public IgnitionSelectionDialog(Window parent, final FlightConfigurationId curFCID, MotorMount _mount) { public IgnitionSelectionDialog(Window parent, final FlightConfigurationId curFCID, MotorMount _mount) {
super(parent, trans.get("edtmotorconfdlg.title.Selectignitionconf"), Dialog.ModalityType.APPLICATION_MODAL); super(parent, trans.get("edtmotorconfdlg.title.Selectignitionconf"), Dialog.ModalityType.APPLICATION_MODAL);
@ -62,15 +65,16 @@ public class IgnitionSelectionDialog extends JDialog {
Rocket rkt = ((RocketComponent)_mount).getRocket(); Rocket rkt = ((RocketComponent)_mount).getRocket();
str = str.replace("{0}", descriptor.format(rkt, curFCID)); str = str.replace("{0}", descriptor.format(rkt, curFCID));
final JRadioButton overrideButton = new JRadioButton(str, !isDefault); final JRadioButton overrideButton = new JRadioButton(str);
overrideButton.addItemListener(e -> isOverrideDefault = e.getStateChange() == ItemEvent.SELECTED);
overrideButton.setSelected(!isDefault);
panel.add(overrideButton, "span, gapleft para, wrap para"); panel.add(overrideButton, "span, gapleft para, wrap para");
ButtonGroup buttonGroup = new ButtonGroup(); ButtonGroup buttonGroup = new ButtonGroup();
buttonGroup.add(defaultButton); buttonGroup.add(defaultButton);
buttonGroup.add(overrideButton); buttonGroup.add(overrideButton);
// Select the button based on current configuration. If the configuration is overridden // Select the button based on current configuration. If the configuration is overridden the overrideButton is selected.
// The the overrideButton is selected.
boolean isOverridden = !isDefault; boolean isOverridden = !isDefault;
if (isOverridden) { if (isOverridden) {
overrideButton.setSelected(true); overrideButton.setSelected(true);
@ -114,18 +118,11 @@ public class IgnitionSelectionDialog extends JDialog {
// and change all remaining configs // and change all remaining configs
// this seems like odd behavior to me, but it matches the text on the UI dialog popup. -teyrana (equipoise@gmail.com) // this seems like odd behavior to me, but it matches the text on the UI dialog popup. -teyrana (equipoise@gmail.com)
Iterator<MotorConfiguration> iter = curMount.getMotorIterator(); Iterator<MotorConfiguration> iter = curMount.getMotorIterator();
while( iter.hasNext() ){ while(iter.hasNext() ) {
MotorConfiguration next = iter.next(); MotorConfiguration next = iter.next();
next.setIgnitionDelay( cid); next.setIgnitionDelay(cid);
next.setIgnitionEvent( cie); next.setIgnitionEvent(cie);
} }
// System.err.println("setting default motor ignition ("+defaultMotorInstance.getMotorID().toString()+") to: ");
// System.err.println(" event: "+defaultMotorInstance.getIgnitionEvent().name+" w/delay: "+defaultMotorInstance.getIgnitionDelay());
// }else {
// System.err.println("setting motor ignition to.... new values: ");
// //destMotorInstance.setIgnitionEvent((IgnitionEvent)eventBox.getSelectedItem());
// System.err.println(" "+curMotorInstance.getIgnitionEvent()+" w/ "+curMotorInstance.getIgnitionDelay());
} }
IgnitionSelectionDialog.this.setVisible(false); IgnitionSelectionDialog.this.setVisible(false);
} }
@ -150,5 +147,14 @@ public class IgnitionSelectionDialog extends JDialog {
this.setContentPane(panel); this.setContentPane(panel);
GUIUtil.setDisposableDialogOptions(this, okButton); GUIUtil.setDisposableDialogOptions(this, okButton);
GUIUtil.installEscapeCloseButtonOperation(this, okButton);
}
/**
* Returns true if this dialog was used to override the default configuration.
* @return true if this dialog was used to override the default configuration.
*/
public boolean isOverrideDefault() {
return isOverrideDefault;
} }
} }

View File

@ -4,6 +4,7 @@ import java.awt.Dialog;
import java.awt.Window; import java.awt.Window;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.awt.event.ActionListener; import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import javax.swing.ButtonGroup; import javax.swing.ButtonGroup;
import javax.swing.JButton; import javax.swing.JButton;
@ -38,11 +39,12 @@ public class SeparationSelectionDialog extends JDialog {
private RocketDescriptor descriptor = Application.getInjector().getInstance(RocketDescriptor.class); private RocketDescriptor descriptor = Application.getInjector().getInstance(RocketDescriptor.class);
private StageSeparationConfiguration newConfiguration; private StageSeparationConfiguration newConfiguration;
private boolean isOverrideDefault;
public SeparationSelectionDialog(Window parent, final Rocket rocket, final AxialStage stage) { public SeparationSelectionDialog(Window parent, final Rocket rocket, final AxialStage stage, FlightConfigurationId id) {
super(parent, trans.get("edtmotorconfdlg.title.Selectseparationconf"), Dialog.ModalityType.APPLICATION_MODAL); super(parent, trans.get("edtmotorconfdlg.title.Selectseparationconf"), Dialog.ModalityType.APPLICATION_MODAL);
final FlightConfigurationId id = rocket.getSelectedConfiguration().getFlightConfigurationID();
newConfiguration = stage.getSeparationConfigurations().get(id); newConfiguration = stage.getSeparationConfigurations().get(id);
if( stage.getSeparationConfigurations().isDefault( newConfiguration )){ if( stage.getSeparationConfigurations().isDefault( newConfiguration )){
newConfiguration = newConfiguration.clone(); newConfiguration = newConfiguration.clone();
@ -59,7 +61,9 @@ public class SeparationSelectionDialog extends JDialog {
panel.add(defaultButton, "span, gapleft para, wrap rel"); panel.add(defaultButton, "span, gapleft para, wrap rel");
String str = trans.get("SeparationSelectionDialog.opt.override"); String str = trans.get("SeparationSelectionDialog.opt.override");
str = str.replace("{0}", descriptor.format(rocket, id)); str = str.replace("{0}", descriptor.format(rocket, id));
final JRadioButton overrideButton = new JRadioButton(str, false); final JRadioButton overrideButton = new JRadioButton(str);
overrideButton.addItemListener(e -> isOverrideDefault = e.getStateChange() == ItemEvent.SELECTED);
overrideButton.setSelected(false);
panel.add(overrideButton, "span, gapleft para, wrap para"); panel.add(overrideButton, "span, gapleft para, wrap para");
ButtonGroup buttonGroup = new ButtonGroup(); ButtonGroup buttonGroup = new ButtonGroup();
@ -123,5 +127,14 @@ public class SeparationSelectionDialog extends JDialog {
this.setContentPane(panel); this.setContentPane(panel);
GUIUtil.setDisposableDialogOptions(this, okButton); GUIUtil.setDisposableDialogOptions(this, okButton);
GUIUtil.installEscapeCloseButtonOperation(this, okButton);
}
/**
* Returns true if this dialog was used to override the default configuration.
* @return true if this dialog was used to override the default configuration.
*/
public boolean isOverrideDefault() {
return isOverrideDefault;
} }
} }

View File

@ -88,15 +88,15 @@ public class FlightConfigurationPanel extends JPanel implements StateChangeListe
tabs = new JTabbedPane(); tabs = new JTabbedPane();
//// Motor tabs //// Motor tabs
motorConfigurationPanel = new MotorConfigurationPanel(this, rocket); motorConfigurationPanel = new MotorConfigurationPanel(this, document, rocket);
tabs.add(trans.get("edtmotorconfdlg.lbl.Motortab"), motorConfigurationPanel); tabs.add(trans.get("edtmotorconfdlg.lbl.Motortab"), motorConfigurationPanel);
//// Recovery tab //// Recovery tab
recoveryConfigurationPanel = new RecoveryConfigurationPanel(this, rocket); recoveryConfigurationPanel = new RecoveryConfigurationPanel(this, document, rocket);
tabs.add(trans.get("edtmotorconfdlg.lbl.Recoverytab"), recoveryConfigurationPanel); tabs.add(trans.get("edtmotorconfdlg.lbl.Recoverytab"), recoveryConfigurationPanel);
//// Stage tab //// Stage tab
separationConfigurationPanel = new SeparationConfigurationPanel(this, rocket); separationConfigurationPanel = new SeparationConfigurationPanel(this, document, rocket);
tabs.add(trans.get("edtmotorconfdlg.lbl.Stagetab"), separationConfigurationPanel); tabs.add(trans.get("edtmotorconfdlg.lbl.Stagetab"), separationConfigurationPanel);
//// New configuration //// New configuration
@ -237,12 +237,29 @@ public class FlightConfigurationPanel extends JPanel implements StateChangeListe
List<FlightConfigurationId> fcIds = getSelectedConfigurationIds(); List<FlightConfigurationId> fcIds = getSelectedConfigurationIds();
if (fcIds == null) return; if (fcIds == null) return;
FlightConfigurationId initFcId = fcIds.get(0); FlightConfigurationId initFcId = fcIds.get(0);
new RenameConfigDialog(SwingUtilities.getWindowAncestor(this), rocket, initFcId).setVisible(true); String initName = rocket.getFlightConfiguration(initFcId).getNameRaw();
document.addUndoPosition("Rename configuration(s)");
// Launch the rename dialog
RenameConfigDialog dialog = new RenameConfigDialog(SwingUtilities.getWindowAncestor(this), rocket, initFcId);
dialog.setVisible(true);
// Get the name of the (potentially renamed) config
String newName = rocket.getFlightConfiguration(initFcId).getNameRaw(); String newName = rocket.getFlightConfiguration(initFcId).getNameRaw();
boolean update = !newName.equals(initName);
for (int i = 1; i < fcIds.size(); i++) { for (int i = 1; i < fcIds.size(); i++) {
rocket.getFlightConfiguration(fcIds.get(i)).setName(newName); FlightConfiguration config = rocket.getFlightConfiguration(fcIds.get(i));
if (!config.getNameRaw().equals(newName)) {
update = true;
config.setName(newName);
}
}
if (update) {
configurationChanged(ComponentChangeEvent.NONFUNCTIONAL_CHANGE);
} }
configurationChanged(ComponentChangeEvent.NONFUNCTIONAL_CHANGE);
} }
private void removeConfigurationAction() { private void removeConfigurationAction() {
@ -250,6 +267,8 @@ public class FlightConfigurationPanel extends JPanel implements StateChangeListe
if (fcIds == null || fcIds.size() == 0) if (fcIds == null || fcIds.size() == 0)
return; return;
document.addUndoPosition("Remove configuration(s)");
for (FlightConfigurationId fcId : fcIds) { for (FlightConfigurationId fcId : fcIds) {
document.removeFlightConfigurationAndSimulations(fcId); document.removeFlightConfigurationAndSimulations(fcId);
} }

View File

@ -22,6 +22,7 @@ import javax.swing.event.ListSelectionListener;
import javax.swing.table.AbstractTableModel; import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer; import javax.swing.table.DefaultTableCellRenderer;
import net.sf.openrocket.document.OpenRocketDocument;
import net.sf.openrocket.gui.main.FlightConfigurationPanel; import net.sf.openrocket.gui.main.FlightConfigurationPanel;
import net.sf.openrocket.gui.util.SwingPreferences; import net.sf.openrocket.gui.util.SwingPreferences;
import net.sf.openrocket.util.ArrayList; import net.sf.openrocket.util.ArrayList;
@ -51,12 +52,14 @@ public abstract class FlightConfigurablePanel<T extends FlightConfigurableCompon
protected RocketDescriptor descriptor = Application.getInjector().getInstance(RocketDescriptor.class); protected RocketDescriptor descriptor = Application.getInjector().getInstance(RocketDescriptor.class);
protected final FlightConfigurationPanel flightConfigurationPanel; protected final FlightConfigurationPanel flightConfigurationPanel;
protected final OpenRocketDocument document;
protected final Rocket rocket; protected final Rocket rocket;
protected final JTable table; protected final JTable table;
public FlightConfigurablePanel(final FlightConfigurationPanel flightConfigurationPanel, Rocket rocket) { public FlightConfigurablePanel(final FlightConfigurationPanel flightConfigurationPanel, OpenRocketDocument document, Rocket rocket) {
super(new MigLayout("fill")); super(new MigLayout("fill"));
this.flightConfigurationPanel = flightConfigurationPanel; this.flightConfigurationPanel = flightConfigurationPanel;
this.document = document;
this.rocket = rocket; this.rocket = rocket;
table = doTableInitialization(); table = doTableInitialization();
@ -250,7 +253,10 @@ public abstract class FlightConfigurablePanel<T extends FlightConfigurableCompon
if (tableValue instanceof Pair) { if (tableValue instanceof Pair) {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
Pair<String, T> selectedComponent = (Pair<String, T>) tableValue; Pair<String, T> selectedComponent = (Pair<String, T>) tableValue;
components.add(selectedComponent.getV()); T comp = selectedComponent.getV();
if (!components.contains(comp)) {
components.add(comp);
}
} }
} }
} }
@ -289,11 +295,17 @@ public abstract class FlightConfigurablePanel<T extends FlightConfigurableCompon
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
Pair<FlightConfigurationId, T> selectedComponent = (Pair<FlightConfigurationId, T>) tableValue; Pair<FlightConfigurationId, T> selectedComponent = (Pair<FlightConfigurationId, T>) tableValue;
FlightConfigurationId fcid = selectedComponent.getU(); FlightConfigurationId fcid = selectedComponent.getU();
Ids.add(fcid); if (!Ids.contains(fcid)) {
Ids.add(fcid);
}
} else if (tableValue instanceof FlightConfigurationId) { } else if (tableValue instanceof FlightConfigurationId) {
Ids.add((FlightConfigurationId) tableValue); if (!Ids.contains(tableValue)) {
Ids.add((FlightConfigurationId) tableValue);
}
} else { } else {
Ids.add(FlightConfigurationId.ERROR_FCID); if (!Ids.contains(FlightConfigurationId.ERROR_FCID)) {
Ids.add(FlightConfigurationId.ERROR_FCID);
}
} }
} }

View File

@ -28,6 +28,7 @@ import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener; import javax.swing.event.TableModelListener;
import net.miginfocom.swing.MigLayout; import net.miginfocom.swing.MigLayout;
import net.sf.openrocket.document.OpenRocketDocument;
import net.sf.openrocket.gui.dialogs.flightconfiguration.IgnitionSelectionDialog; import net.sf.openrocket.gui.dialogs.flightconfiguration.IgnitionSelectionDialog;
import net.sf.openrocket.gui.dialogs.flightconfiguration.MotorMountConfigurationPanel; import net.sf.openrocket.gui.dialogs.flightconfiguration.MotorMountConfigurationPanel;
import net.sf.openrocket.gui.dialogs.motor.MotorChooserDialog; import net.sf.openrocket.gui.dialogs.motor.MotorChooserDialog;
@ -49,7 +50,7 @@ import net.sf.openrocket.util.Chars;
@SuppressWarnings("serial") @SuppressWarnings("serial")
public class MotorConfigurationPanel extends FlightConfigurablePanel<MotorMount> { public class MotorConfigurationPanel extends FlightConfigurablePanel<MotorMount> {
private static final String NONE = trans.get("edtmotorconfdlg.tbl.None"); private static final String NONE = trans.get("edtmotorconfdlg.tbl.None");
private final JButton selectMotorButton, deleteMotorButton, selectIgnitionButton, resetIgnitionButton; private final JButton selectMotorButton, deleteMotorButton, selectIgnitionButton, resetIgnitionButton;
@ -64,8 +65,8 @@ public class MotorConfigurationPanel extends FlightConfigurablePanel<MotorMount>
private final JPopupMenu popupMenuFull; // popup menu containing all the options private final JPopupMenu popupMenuFull; // popup menu containing all the options
public MotorConfigurationPanel(final FlightConfigurationPanel flightConfigurationPanel, Rocket rocket) { public MotorConfigurationPanel(final FlightConfigurationPanel flightConfigurationPanel, OpenRocketDocument document, Rocket rocket) {
super(flightConfigurationPanel, rocket); super(flightConfigurationPanel, document, rocket);
motorChooserDialog = new MotorChooserDialog(SwingUtilities.getWindowAncestor(flightConfigurationPanel)); motorChooserDialog = new MotorChooserDialog(SwingUtilities.getWindowAncestor(flightConfigurationPanel));
@ -306,6 +307,9 @@ public class MotorConfigurationPanel extends FlightConfigurablePanel<MotorMount>
double initDelay = initMount.getMotorConfig(initFcId).getEjectionDelay(); double initDelay = initMount.getMotorConfig(initFcId).getEjectionDelay();
document.addUndoPosition("Select motor");
// Open the motor chooser dialog
motorChooserDialog.setMotorMountAndConfig(initFcId, initMount); motorChooserDialog.setMotorMountAndConfig(initFcId, initMount);
motorChooserDialog.open(); motorChooserDialog.open();
@ -343,6 +347,8 @@ public class MotorConfigurationPanel extends FlightConfigurablePanel<MotorMount>
return; return;
} }
document.addUndoPosition("Delete motor(s)");
for (MotorMount mount : mounts) { for (MotorMount mount : mounts) {
for (FlightConfigurationId fcId : fcIds) { for (FlightConfigurationId fcId : fcIds) {
mount.setMotorConfig(null, fcId); mount.setMotorConfig(null, fcId);
@ -359,7 +365,6 @@ public class MotorConfigurationPanel extends FlightConfigurablePanel<MotorMount>
return; return;
} }
boolean update = false;
MotorMount initMount = mounts.get(0); MotorMount initMount = mounts.get(0);
FlightConfigurationId initFcId = fcIds.get(0); FlightConfigurationId initFcId = fcIds.get(0);
@ -367,31 +372,42 @@ public class MotorConfigurationPanel extends FlightConfigurablePanel<MotorMount>
IgnitionEvent initialIgnitionEvent = initConfig.getIgnitionEvent(); IgnitionEvent initialIgnitionEvent = initConfig.getIgnitionEvent();
double initialIgnitionDelay = initConfig.getIgnitionDelay(); double initialIgnitionDelay = initConfig.getIgnitionDelay();
document.addUndoPosition("Select ignition");
// this call also performs the update changes // this call also performs the update changes
IgnitionSelectionDialog ignitionDialog = new IgnitionSelectionDialog( IgnitionSelectionDialog ignitionDialog = new IgnitionSelectionDialog(
SwingUtilities.getWindowAncestor(this.flightConfigurationPanel), SwingUtilities.getWindowAncestor(this.flightConfigurationPanel),
initFcId, initFcId,
initMount); initMount);
ignitionDialog.setVisible(true); ignitionDialog.setVisible(true);
boolean isOverrideDefault = ignitionDialog.isOverrideDefault();
if (!initialIgnitionEvent.equals(initConfig.getIgnitionEvent()) || (initialIgnitionDelay != initConfig.getIgnitionDelay())) { boolean update = !initialIgnitionEvent.equals(initConfig.getIgnitionEvent()) ||
update = true; (initialIgnitionDelay != initConfig.getIgnitionDelay());
}
for (int i = 0; i < mounts.size(); i++) { for (MotorMount mount : mounts) {
for (int j = 0; j < fcIds.size(); j++) { for (FlightConfigurationId fcId : fcIds) {
if ((i == 0) && (j == 0)) break; if ((mount == initMount) && (fcId == initFcId))
continue;
MotorConfiguration config = mounts.get(i).getMotorConfig(fcIds.get(j)); MotorConfiguration currentConfig = mount.getMotorConfig(fcId);
initialIgnitionEvent = config.getIgnitionEvent();
initialIgnitionDelay = config.getIgnitionDelay();
config.setIgnitionEvent(initConfig.getIgnitionEvent()); // It could be that the current config is the default config, but the user has selected to override it.
config.setIgnitionDelay(initConfig.getIgnitionDelay()); if (isOverrideDefault && !mount.getMotorConfigurationSet().containsId(fcId)) {
mount.getMotorConfigurationSet().set(fcId, mount.getMotorConfigurationSet().getDefault().clone());
if (!initialIgnitionEvent.equals(config.getIgnitionEvent()) || (initialIgnitionDelay != config.getIgnitionDelay())) {
update = true;
} }
initialIgnitionEvent = currentConfig.getIgnitionEvent();
initialIgnitionDelay = currentConfig.getIgnitionDelay();
if (initialIgnitionEvent.equals(currentConfig.getIgnitionEvent()) && (initialIgnitionDelay != currentConfig.getIgnitionDelay())) {
continue;
}
update = true;
currentConfig.setIgnitionEvent(initConfig.getIgnitionEvent());
currentConfig.setIgnitionDelay(initConfig.getIgnitionDelay());
} }
} }
@ -410,6 +426,8 @@ public class MotorConfigurationPanel extends FlightConfigurablePanel<MotorMount>
return; return;
} }
document.addUndoPosition("Reset ignition");
boolean update = false; boolean update = false;
for (MotorMount mount : mounts) { for (MotorMount mount : mounts) {
for (FlightConfigurationId fcId : fcIds) { for (FlightConfigurationId fcId : fcIds) {

View File

@ -21,6 +21,7 @@ import javax.swing.SwingUtilities;
import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener; import javax.swing.event.ListSelectionListener;
import net.sf.openrocket.document.OpenRocketDocument;
import net.sf.openrocket.formatting.RocketDescriptor; import net.sf.openrocket.formatting.RocketDescriptor;
import net.sf.openrocket.gui.dialogs.flightconfiguration.DeploymentSelectionDialog; import net.sf.openrocket.gui.dialogs.flightconfiguration.DeploymentSelectionDialog;
import net.sf.openrocket.gui.main.FlightConfigurationPanel; import net.sf.openrocket.gui.main.FlightConfigurationPanel;
@ -42,8 +43,8 @@ public class RecoveryConfigurationPanel extends FlightConfigurablePanel<Recovery
private final JPopupMenu popupMenuFull; // popup menu containing all the options private final JPopupMenu popupMenuFull; // popup menu containing all the options
public RecoveryConfigurationPanel(FlightConfigurationPanel flightConfigurationPanel, Rocket rocket) { public RecoveryConfigurationPanel(FlightConfigurationPanel flightConfigurationPanel, OpenRocketDocument document, Rocket rocket) {
super(flightConfigurationPanel,rocket); super(flightConfigurationPanel, document, rocket);
JScrollPane scroll = new JScrollPane(table); JScrollPane scroll = new JScrollPane(table);
this.add(scroll, "span, grow, pushy, wrap"); this.add(scroll, "span, grow, pushy, wrap");
@ -171,40 +172,48 @@ public class RecoveryConfigurationPanel extends FlightConfigurablePanel<Recovery
return; return;
} }
boolean update = false; // Get the device and fcid that will be used in the config dialog
RecoveryDevice initDevice = devices.get(0); RecoveryDevice initDevice = devices.get(0);
FlightConfigurationId initFcId = fcIds.get(0); FlightConfigurationId initFcId = fcIds.get(0);
DeploymentConfiguration initialConfig = initDevice.getDeploymentConfigurations().get(initFcId).copy(initFcId); DeploymentConfiguration initialConfig = initDevice.getDeploymentConfigurations().get(initFcId).copy(initFcId);
JDialog d = new DeploymentSelectionDialog(SwingUtilities.getWindowAncestor(this), rocket, initDevice);
document.addUndoPosition("Select deployment");
// Open the configuration dialog
DeploymentSelectionDialog d = new DeploymentSelectionDialog(SwingUtilities.getWindowAncestor(this), rocket, initFcId, initDevice);
d.setVisible(true); d.setVisible(true);
if (!initialConfig.equals(initDevice.getDeploymentConfigurations().get(initFcId))) { final DeploymentConfiguration modifiedConfig = initDevice.getDeploymentConfigurations().get(initFcId);
update = true; boolean update = !initialConfig.equals(modifiedConfig);
}
double deployDelay = initDevice.getDeploymentConfigurations().get(initFcId).getDeployDelay(); double deployDelay = modifiedConfig.getDeployDelay();
double deployAltitude = initDevice.getDeploymentConfigurations().get(initFcId).getDeployAltitude(); double deployAltitude = modifiedConfig.getDeployAltitude();
DeployEvent deployEvent = initDevice.getDeploymentConfigurations().get(initFcId).getDeployEvent(); DeployEvent deployEvent = modifiedConfig.getDeployEvent();
boolean isOverrideDefault = d.isOverrideDefault();
for (int i = 0; i < devices.size(); i++) { for (RecoveryDevice device : devices) {
for (int j = 0; j < fcIds.size(); j++) { for (FlightConfigurationId fcId : fcIds) {
if ((i == 0) && (j == 0)) break; // Skip the config that was used for the config dialog (it has already been modified)
if ((device == initDevice) && (fcId == initFcId))
continue;
final RecoveryDevice device = devices.get(i); // It could be that the current config is the default config, but the user has selected to override it.
final FlightConfigurationId fcId = fcIds.get(j); if (isOverrideDefault && !device.getDeploymentConfigurations().containsId(fcId)) {
DeploymentConfiguration config = device.getDeploymentConfigurations().get(fcId).copy(fcId); device.getDeploymentConfigurations().set(fcId, device.getDeploymentConfigurations().getDefault().clone());
initialConfig = config.copy(fcId);
config.setDeployDelay(deployDelay);
config.setDeployAltitude(deployAltitude);
config.setDeployEvent(deployEvent);
device.getDeploymentConfigurations().set(fcId, config);
if (!initialConfig.equals(device.getDeploymentConfigurations().get(fcId))) {
update = true;
} }
DeploymentConfiguration currentConfig = device.getDeploymentConfigurations().get(fcId);
if (currentConfig.equals(modifiedConfig)) {
continue;
}
update = true;
currentConfig.setDeployDelay(deployDelay);
currentConfig.setDeployAltitude(deployAltitude);
currentConfig.setDeployEvent(deployEvent);
} }
} }
@ -223,6 +232,8 @@ public class RecoveryConfigurationPanel extends FlightConfigurablePanel<Recovery
return; return;
} }
document.addUndoPosition("Reset deployment");
boolean update = false; boolean update = false;
for (RecoveryDevice device : devices) { for (RecoveryDevice device : devices) {
for (FlightConfigurationId fcId : fcIds) { for (FlightConfigurationId fcId : fcIds) {

View File

@ -10,7 +10,6 @@ import java.util.List;
import javax.swing.AbstractAction; import javax.swing.AbstractAction;
import javax.swing.JButton; import javax.swing.JButton;
import javax.swing.JComponent; import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JLabel; import javax.swing.JLabel;
import javax.swing.JPopupMenu; import javax.swing.JPopupMenu;
import javax.swing.JScrollPane; import javax.swing.JScrollPane;
@ -21,6 +20,7 @@ import javax.swing.SwingUtilities;
import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener; import javax.swing.event.ListSelectionListener;
import net.sf.openrocket.document.OpenRocketDocument;
import net.sf.openrocket.formatting.RocketDescriptor; import net.sf.openrocket.formatting.RocketDescriptor;
import net.sf.openrocket.gui.dialogs.flightconfiguration.SeparationSelectionDialog; import net.sf.openrocket.gui.dialogs.flightconfiguration.SeparationSelectionDialog;
import net.sf.openrocket.gui.main.FlightConfigurationPanel; import net.sf.openrocket.gui.main.FlightConfigurationPanel;
@ -47,8 +47,8 @@ public class SeparationConfigurationPanel extends FlightConfigurablePanel<AxialS
private final JPopupMenu popupMenuFull; // popup menu containing all the options private final JPopupMenu popupMenuFull; // popup menu containing all the options
public SeparationConfigurationPanel(FlightConfigurationPanel flightConfigurationPanel, Rocket rocket) { public SeparationConfigurationPanel(FlightConfigurationPanel flightConfigurationPanel, OpenRocketDocument document, Rocket rocket) {
super(flightConfigurationPanel,rocket); super(flightConfigurationPanel, document, rocket);
JScrollPane scroll = new JScrollPane(table); JScrollPane scroll = new JScrollPane(table);
this.add(scroll, "span, grow, pushy, wrap"); this.add(scroll, "span, grow, pushy, wrap");
@ -180,45 +180,47 @@ public class SeparationConfigurationPanel extends FlightConfigurablePanel<AxialS
return; return;
} }
boolean update = false;
AxialStage initStage = stages.get(0); // Arbitrary choice of stage (all stages should have the same settings due to multi-comp editing) AxialStage initStage = stages.get(0); // Arbitrary choice of stage (all stages should have the same settings due to multi-comp editing)
FlightConfigurationId initFcId = rocket.getSelectedConfiguration().getId(); // The SeparationSelectionDialog should apply its separation settings to the selected configuration FlightConfigurationId initFcId = fcIds.get(0);
// Store the initial configuration so we can check later whether something changed // Store the initial configuration so we can check later whether something changed
StageSeparationConfiguration initialConfig = initStage.getSeparationConfigurations().get(initFcId).copy(initFcId); StageSeparationConfiguration initialConfig = initStage.getSeparationConfigurations().get(initFcId).copy(initFcId);
document.addUndoPosition("Select separation");
// Launch the separation config dialog // Launch the separation config dialog
JDialog d = new SeparationSelectionDialog(SwingUtilities.getWindowAncestor(this), rocket, initStage); SeparationSelectionDialog d = new SeparationSelectionDialog(SwingUtilities.getWindowAncestor(this), rocket, initStage, initFcId);
d.setVisible(true); d.setVisible(true);
if (!initialConfig.equals(initStage.getSeparationConfigurations().get(initFcId))) { final StageSeparationConfiguration modifiedConfig = initStage.getSeparationConfigurations().get(initFcId);
update = true; boolean update = !initialConfig.equals(modifiedConfig);
}
double separationDelay = initStage.getSeparationConfigurations().get(initFcId).getSeparationDelay(); double separationDelay = initStage.getSeparationConfigurations().get(initFcId).getSeparationDelay();
SeparationEvent separationEvent= initStage.getSeparationConfigurations().get(initFcId).getSeparationEvent(); SeparationEvent separationEvent= initStage.getSeparationConfigurations().get(initFcId).getSeparationEvent();
boolean isOverrideDefault = d.isOverrideDefault();
// Parse all stages anc flight configurations to check whether we need to update // Parse all stages and flight configurations to check whether we need to update
for (int i = 0; i < stages.size(); i++) { for (AxialStage stage : stages) {
for (int j = 0; j < fcIds.size(); j++) { for (FlightConfigurationId fcId : fcIds) {
if ((i == 0) && (j == 0)) break; if ((stage == initStage) && (fcId == initFcId))
continue;
final AxialStage stage = stages.get(i); // It could be that the current config is the default config, but the user has selected to override it.
final FlightConfigurationId fcId = fcIds.get(j); if (isOverrideDefault && !stage.getSeparationConfigurations().containsId(fcId)) {
StageSeparationConfiguration config = stage.getSeparationConfigurations().get(fcId); stage.getSeparationConfigurations().set(fcId, stage.getSeparationConfigurations().getDefault().clone());
initialConfig = config.copy(fcId);
if (stage.getSeparationConfigurations().isDefault(config)) {
config = config.copy(fcId);
} }
config.setSeparationDelay(separationDelay); StageSeparationConfiguration currentConfig = stage.getSeparationConfigurations().get(fcId);
config.setSeparationEvent(separationEvent);
stage.getSeparationConfigurations().set(fcId, config);
if (!initialConfig.equals(config)) { if (currentConfig.equals(modifiedConfig)) {
update = true; continue;
} }
update = true;
currentConfig.setSeparationDelay(separationDelay);
currentConfig.setSeparationEvent(separationEvent);
stage.getSeparationConfigurations().set(fcId, currentConfig);
} }
} }
@ -236,6 +238,8 @@ public class SeparationConfigurationPanel extends FlightConfigurablePanel<AxialS
return; return;
} }
document.addUndoPosition("Reset separation");
boolean update = false; boolean update = false;
for (AxialStage stage : stages) { for (AxialStage stage : stages) {
for (FlightConfigurationId fcId : fcIds) { for (FlightConfigurationId fcId : fcIds) {

View File

@ -165,6 +165,25 @@ public class GUIUtil {
installEscapeCloseOperation(dialog, null); installEscapeCloseOperation(dialog, null);
} }
public static void installEscapeCloseButtonOperation(final JDialog dialog, final JButton buttonToClick) {
Action triggerButtonAndClose = new AbstractAction() {
private static final long serialVersionUID = 9196153713666242274L;
@Override
public void actionPerformed(ActionEvent event) {
log.info(Markers.USER_MARKER, "Closing dialog " + dialog);
if (buttonToClick != null) {
buttonToClick.doClick(); // Programmatically "press" the button
}
dialog.dispatchEvent(new WindowEvent(dialog, WindowEvent.WINDOW_CLOSING));
}
};
installEscapeCloseOperation(dialog, triggerButtonAndClose);
}
/** /**
* Add the correct action to close a JDialog when the ESC key is pressed. * Add the correct action to close a JDialog when the ESC key is pressed.
* The dialog is closed by sending it a WINDOW_CLOSING event. * The dialog is closed by sending it a WINDOW_CLOSING event.