Merge pull request #1976 from SiboVG/issue-1973

[#1973] Don't mark all simulations out-of-date on flight config change
This commit is contained in:
Sibo Van Gool 2023-01-20 00:58:00 +01:00 committed by GitHub
commit ad676d9f5d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 147 additions and 66 deletions

View File

@ -75,7 +75,7 @@ public class Simulation implements ChangeSource, Cloneable {
private String name = ""; private String name = "";
private Status status = Status.NOT_SIMULATED; private Status status;
/** The conditions to use */ /** The conditions to use */
// TODO: HIGH: Change to use actual conditions class?? // TODO: HIGH: Change to use actual conditions class??
@ -98,7 +98,7 @@ public class Simulation implements ChangeSource, Cloneable {
private SimulationOptions simulatedConditions = null; private SimulationOptions simulatedConditions = null;
private String simulatedConfigurationDescription = null; private String simulatedConfigurationDescription = null;
private FlightData simulatedData = null; private FlightData simulatedData = null;
private int simulatedRocketID = -1; private int simulatedConfigurationID = -1;
/** /**
@ -147,7 +147,8 @@ public class Simulation implements ChangeSource, Cloneable {
this.options = options; this.options = options;
this.setFlightConfigurationId( rocket.getSelectedConfiguration().getFlightConfigurationID()); final FlightConfiguration config = rocket.getSelectedConfiguration();
this.setFlightConfigurationId(config.getFlightConfigurationID());
options.addChangeListener(new ConditionListener()); options.addChangeListener(new ConditionListener());
@ -160,7 +161,7 @@ public class Simulation implements ChangeSource, Cloneable {
simulatedData = data; simulatedData = data;
if (this.status == Status.LOADED) { if (this.status == Status.LOADED) {
simulatedConditions = options.clone(); simulatedConditions = options.clone();
simulatedRocketID = rocket.getModID(); simulatedConfigurationID = config.getModID();
} }
} }
@ -308,8 +309,10 @@ public class Simulation implements ChangeSource, Cloneable {
*/ */
public Status getStatus() { public Status getStatus() {
mutex.verify(); mutex.verify();
final FlightConfiguration config = rocket.getFlightConfiguration(this.getId()).clone();
if (isStatusUpToDate(status)) { if (isStatusUpToDate(status)) {
if (rocket.getFunctionalModID() != simulatedRocketID || !options.equals(simulatedConditions)) { if (config.getModID() != simulatedConfigurationID || !options.equals(simulatedConditions)) {
status = Status.OUTDATED; status = Status.OUTDATED;
} }
} }
@ -320,8 +323,6 @@ public class Simulation implements ChangeSource, Cloneable {
status = Status.CANT_RUN; status = Status.CANT_RUN;
return status; return status;
} }
FlightConfiguration config = rocket.getFlightConfiguration( this.getId()).clone();
//Make sure this simulation has motors. //Make sure this simulation has motors.
if ( ! config.hasMotors() ){ if ( ! config.hasMotors() ){
@ -338,7 +339,13 @@ public class Simulation implements ChangeSource, Cloneable {
public static boolean isStatusUpToDate(Status status) { public static boolean isStatusUpToDate(Status status) {
return status == Status.UPTODATE || status == Status.LOADED || status == Status.EXTERNAL; return status == Status.UPTODATE || status == Status.LOADED || status == Status.EXTERNAL;
} }
/**
* Syncs the modID with its flight configuration.
*/
public void syncModID() {
this.simulatedConfigurationID = getActiveConfiguration().getModID();
}
/** /**
@ -392,7 +399,7 @@ public class Simulation implements ChangeSource, Cloneable {
// Set simulated info after simulation // Set simulated info after simulation
simulatedConditions = options.clone(); simulatedConditions = options.clone();
simulatedConfigurationDescription = descriptor.format( this.rocket, getId()); simulatedConfigurationDescription = descriptor.format( this.rocket, getId());
simulatedRocketID = rocket.getFunctionalModID(); simulatedConfigurationID = getActiveConfiguration().getModID();
status = Status.UPTODATE; status = Status.UPTODATE;
fireChangeEvent(); fireChangeEvent();
@ -492,7 +499,7 @@ public class Simulation implements ChangeSource, Cloneable {
copy.simulatedConditions = null; copy.simulatedConditions = null;
copy.simulatedConfigurationDescription = null; copy.simulatedConfigurationDescription = null;
copy.simulatedData = null; copy.simulatedData = null;
copy.simulatedRocketID = -1; copy.simulatedConfigurationID = -1;
return copy; return copy;

View File

@ -4,6 +4,7 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.List; import java.util.List;
import net.sf.openrocket.rocketcomponent.ComponentChangeEvent;
import net.sf.openrocket.rocketcomponent.FlightConfiguration; import net.sf.openrocket.rocketcomponent.FlightConfiguration;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -62,6 +63,7 @@ public class OpenRocketLoader extends AbstractRocketLoader {
// Deduce suitable time skip // Deduce suitable time skip
double timeSkip = StorageOptions.SIMULATION_DATA_NONE; double timeSkip = StorageOptions.SIMULATION_DATA_NONE;
for (Simulation s : doc.getSimulations()) { for (Simulation s : doc.getSimulations()) {
s.syncModID(); // The config's modID can be out of sync with the simulation's after the whole loading process
if (s.getStatus() == Simulation.Status.EXTERNAL || if (s.getStatus() == Simulation.Status.EXTERNAL ||
s.getStatus() == Simulation.Status.NOT_SIMULATED) s.getStatus() == Simulation.Status.NOT_SIMULATED)
continue; continue;

View File

@ -160,8 +160,6 @@ public class FlightConfiguration implements FlightConfigurableParameter<FlightCo
*/ */
public void clearStage(final int stageNumber) { public void clearStage(final int stageNumber) {
_setStageActive( stageNumber, false ); _setStageActive( stageNumber, false );
updateMotors();
updateActiveInstances();
} }
/** /**
@ -175,8 +173,6 @@ public class FlightConfiguration implements FlightConfigurableParameter<FlightCo
for (int i = stageNumber; i < rocket.getStageCount(); i++) { for (int i = stageNumber; i < rocket.getStageCount(); i++) {
_setStageActive(i, false, false); _setStageActive(i, false, false);
} }
updateMotors();
updateActiveInstances();
} }
/** /**
@ -188,8 +184,6 @@ public class FlightConfiguration implements FlightConfigurableParameter<FlightCo
for (int i = 0; i < stageNumber; i++) { for (int i = 0; i < stageNumber; i++) {
_setStageActive(i, false, false); _setStageActive(i, false, false);
} }
updateMotors();
updateActiveInstances();
} }
/** /**
@ -215,8 +209,6 @@ public class FlightConfiguration implements FlightConfigurableParameter<FlightCo
for (int i=0; i <= stage.getStageNumber(); i++) { for (int i=0; i <= stage.getStageNumber(); i++) {
_setStageActive(i, true); _setStageActive(i, true);
} }
updateMotors();
updateActiveInstances();
} }
/** /**
@ -227,8 +219,6 @@ public class FlightConfiguration implements FlightConfigurableParameter<FlightCo
public void setOnlyStage(final int stageNumber) { public void setOnlyStage(final int stageNumber) {
_setAllStages(false); _setAllStages(false);
_setStageActive(stageNumber, true, false); _setStageActive(stageNumber, true, false);
updateMotors();
updateActiveInstances();
} }
/** /**
@ -540,6 +530,13 @@ public class FlightConfiguration implements FlightConfigurableParameter<FlightCo
updateMotors(); updateMotors();
updateActiveInstances(); updateActiveInstances();
} }
/**
* Update the configuration's modID, thus staging it in need to update.
*/
public void updateModID() {
this.modID++;
}
private void updateStages() { private void updateStages() {
Map<Integer, FlightConfiguration.StageFlags> stagesBackup = new HashMap<>(this.stages); Map<Integer, FlightConfiguration.StageFlags> stagesBackup = new HashMap<>(this.stages);
@ -908,13 +905,7 @@ public class FlightConfiguration implements FlightConfigurableParameter<FlightCo
@Override @Override
public int getModID() { public int getModID() {
// TODO: this doesn't seem consistent... return modID;
int id = modID;
// for (MotorInstance motor : motors.values()) {
// id += motor.getModID();
// }
id += rocket.getModID();
return id;
} }
public void setName(final String newName) { public void setName(final String newName) {

View File

@ -485,17 +485,40 @@ public class Rocket extends ComponentAssembly {
listenerList.remove(l); listenerList.remove(l);
log.trace("Removed ComponentChangeListener " + l + ", current number of listeners is " + listenerList.size()); log.trace("Removed ComponentChangeListener " + l + ", current number of listeners is " + listenerList.size());
} }
@Override /**
protected void fireComponentChangeEvent(ComponentChangeEvent cce) { * Fires a ComponentChangeEvent of the given type. The source of the event is set to
if( ! this.eventsEnabled ){ * this rocket.
*
* @param type Type of event
* @param ids IDs of the flight configurations to update, or null to update all.
* @see #fireComponentChangeEvent(ComponentChangeEvent)
*/
public void fireComponentChangeEvent(int type, final FlightConfigurationId[] ids) {
fireComponentChangeEvent(new ComponentChangeEvent(this, type), ids);
}
/**
* Fires a ComponentChangeEvent of the given type. The source of the event is set to
* this rocket.
*
* @param type Type of event
* @param id ID of the flight configurations to update, or null to update all.
* @see #fireComponentChangeEvent(ComponentChangeEvent)
*/
public void fireComponentChangeEvent(int type, FlightConfigurationId id) {
fireComponentChangeEvent(type, new FlightConfigurationId[]{ id });
}
protected void fireComponentChangeEvent(ComponentChangeEvent cce, final FlightConfigurationId[] ids) {
if (!this.eventsEnabled) {
return; return;
} }
mutex.lock("fireComponentChangeEvent"); mutex.lock("fireComponentChangeEvent");
try { try {
checkState(); checkState();
// Update modification ID's only for normal (not undo/redo) events // Update modification ID's only for normal (not undo/redo) events
if (!cce.isUndoChange()) { if (!cce.isUndoChange()) {
modID = UniqueID.next(); modID = UniqueID.next();
@ -505,32 +528,39 @@ public class Rocket extends ComponentAssembly {
aeroModID = modID; aeroModID = modID;
if (cce.isTreeChange()) if (cce.isTreeChange())
treeModID = modID; treeModID = modID;
if (cce.isFunctionalChange()) if (cce.isFunctionalChange()) {
functionalModID = modID; functionalModID = modID;
updateConfigurationsModID(ids);
}
} }
// Check whether frozen // Check whether frozen
if (freezeList != null) { if (freezeList != null) {
log.debug("Rocket is in frozen state, adding event " + cce + " info freeze list"); log.debug("Rocket is in frozen state, adding event " + cce + " info freeze list");
freezeList.add(cce); freezeList.add(cce);
return; return;
} }
// Notify all components first // Notify all components first
Iterator<RocketComponent> iterator = this.iterator(true); Iterator<RocketComponent> iterator = this.iterator(true);
while (iterator.hasNext()) { while (iterator.hasNext()) {
RocketComponent next = iterator.next(); RocketComponent next = iterator.next();
next.componentChanged(cce); next.componentChanged(cce);
} }
updateConfigurations(); updateConfigurations(ids);
notifyAllListeners(cce); notifyAllListeners(cce);
} finally { } finally {
mutex.unlock("fireComponentChangeEvent"); mutex.unlock("fireComponentChangeEvent");
} }
} }
@Override
protected void fireComponentChangeEvent(ComponentChangeEvent cce) {
fireComponentChangeEvent(cce, null);
}
@Override @Override
public void update(){ public void update(){
updateStageNumbers(); updateStageNumbers();
@ -555,11 +585,51 @@ public class Rocket extends ComponentAssembly {
trackStage(stage); trackStage(stage);
} }
} }
private void updateConfigurations(){ /**
for( FlightConfiguration config : configSet ){ * Update the modIDs of the supplied flight configurations.
config.update(); * @param ids IDs of the flight configurations to update, or null to update all.
*/
private void updateConfigurationsModID(FlightConfigurationId[] ids) {
if (ids == null) {
for (FlightConfiguration config : configSet) {
config.updateModID();
}
return;
} }
for (FlightConfiguration config : configSet) {
for (FlightConfigurationId id : ids) {
if (config.getId().equals(id)) {
config.updateModID();
break;
}
}
}
}
/**
* Update the flight configurations.
* @param ids IDs of the flight configurations to update, or null to update all.
*/
private void updateConfigurations(FlightConfigurationId[] ids) {
if (ids == null) {
for (FlightConfiguration config : configSet) {
config.update();
}
return;
}
for (FlightConfiguration config : configSet) {
for (FlightConfigurationId id : ids) {
if (config.getId().equals(id)) {
config.update();
break;
}
}
}
}
private void updateConfigurations() {
updateConfigurations(null);
} }
@ -696,8 +766,8 @@ public class Rocket extends ComponentAssembly {
} }
// Get current configuration: // Get current configuration:
this.configSet.reset( fcid); this.configSet.reset(fcid);
fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE); fireComponentChangeEvent(ComponentChangeEvent.NONFUNCTIONAL_CHANGE);
} }

View File

@ -33,8 +33,7 @@ import net.sf.openrocket.util.WorldCoordinate;
*/ */
public class SimulationStatus implements Monitorable { public class SimulationStatus implements Monitorable {
private static final Logger log = LoggerFactory.getLogger(SimulationStatus.class);
private SimulationConditions simulationConditions; private SimulationConditions simulationConditions;
private FlightConfiguration configuration; private FlightConfiguration configuration;
private FlightDataBranch flightData; private FlightDataBranch flightData;

View File

@ -96,8 +96,10 @@ public class StageSelector extends JPanel implements StateChangeListener {
setEnabled(true); setEnabled(true);
putValue(SHORT_DESCRIPTION, trans.get("RocketPanel.btn.Stages.Toggle.ttip")); putValue(SHORT_DESCRIPTION, trans.get("RocketPanel.btn.Stages.Toggle.ttip"));
} }
rocket.getSelectedConfiguration().toggleStage(stage.getStageNumber()); FlightConfiguration config = rocket.getSelectedConfiguration();
rocket.fireComponentChangeEvent(ComponentChangeEvent.AEROMASS_CHANGE | ComponentChangeEvent.MOTOR_CHANGE ); config.toggleStage(stage.getStageNumber());
rocket.fireComponentChangeEvent(ComponentChangeEvent.AEROMASS_CHANGE | ComponentChangeEvent.MOTOR_CHANGE,
config.getFlightConfigurationID());
} }
} }

View File

@ -2,6 +2,7 @@ package net.sf.openrocket.gui.main;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.awt.event.MouseEvent; import java.awt.event.MouseEvent;
import java.util.Collections;
import java.util.EventObject; import java.util.EventObject;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
@ -156,8 +157,9 @@ public class FlightConfigurationPanel extends JPanel implements StateChangeListe
* @param duplicate if True, then duplicate configuration operation, if False then create a new configuration * @param duplicate if True, then duplicate configuration operation, if False then create a new configuration
*/ */
private void newOrDuplicateConfigAction(boolean duplicate) { private void newOrDuplicateConfigAction(boolean duplicate) {
addOrDuplicateConfiguration(duplicate); Map<FlightConfigurationId, FlightConfiguration> newConfigs = addOrDuplicateConfiguration(duplicate);
configurationChanged(ComponentChangeEvent.MOTOR_CHANGE); FlightConfigurationId[] ids = newConfigs.keySet().toArray(new FlightConfigurationId[0]);
configurationChanged(ComponentChangeEvent.MOTOR_CHANGE, ids);
stateChanged(null); stateChanged(null);
if (!duplicate) { if (!duplicate) {
switch (tabs.getSelectedIndex()) { switch (tabs.getSelectedIndex()) {
@ -179,14 +181,16 @@ public class FlightConfigurationPanel extends JPanel implements StateChangeListe
* either create or duplicate configuration * either create or duplicate configuration
* set new configuration as current * set new configuration as current
* create simulation for new configuration * create simulation for new configuration
*
* @return the new/duplicated configurations
*/ */
private void addOrDuplicateConfiguration(boolean duplicate) { private Map<FlightConfigurationId, FlightConfiguration> addOrDuplicateConfiguration(boolean duplicate) {
final Map<FlightConfigurationId, FlightConfiguration> newConfigs = new LinkedHashMap<>(); final Map<FlightConfigurationId, FlightConfiguration> newConfigs = new LinkedHashMap<>();
// create or duplicate configuration // create or duplicate configuration
if (duplicate) { if (duplicate) {
List<FlightConfigurationId> oldIds = getSelectedConfigurationIds(); List<FlightConfigurationId> oldIds = getSelectedConfigurationIds();
if (oldIds == null || oldIds.size() == 0) return; if (oldIds == null || oldIds.size() == 0) return Collections.emptyMap();
for (FlightConfigurationId oldId : oldIds) { for (FlightConfigurationId oldId : oldIds) {
final FlightConfiguration oldConfig = rocket.getFlightConfiguration(oldId); final FlightConfiguration oldConfig = rocket.getFlightConfiguration(oldId);
@ -210,7 +214,7 @@ public class FlightConfigurationPanel extends JPanel implements StateChangeListe
} }
OpenRocketDocument doc = BasicFrame.findDocument(rocket); OpenRocketDocument doc = BasicFrame.findDocument(rocket);
if (doc == null) return; if (doc == null) return Collections.emptyMap();
for (Map.Entry<FlightConfigurationId, FlightConfiguration> config : newConfigs.entrySet()) { for (Map.Entry<FlightConfigurationId, FlightConfiguration> config : newConfigs.entrySet()) {
// associate configuration with Id and select it // associate configuration with Id and select it
@ -226,6 +230,7 @@ public class FlightConfigurationPanel extends JPanel implements StateChangeListe
// Reset to first selected flight config // Reset to first selected flight config
rocket.setSelectedConfiguration((FlightConfigurationId) newConfigs.keySet().toArray()[0]); rocket.setSelectedConfiguration((FlightConfigurationId) newConfigs.keySet().toArray()[0]);
return newConfigs;
} }
private void renameConfigurationAction() { private void renameConfigurationAction() {
@ -273,10 +278,14 @@ public class FlightConfigurationPanel extends JPanel implements StateChangeListe
return duplicateConfigAction; return duplicateConfigAction;
} }
private void configurationChanged(int cce, FlightConfigurationId[] ids) {
motorConfigurationPanel.fireTableDataChanged(cce, ids);
recoveryConfigurationPanel.fireTableDataChanged(cce, ids);
separationConfigurationPanel.fireTableDataChanged(cce, ids);
}
private void configurationChanged(int cce) { private void configurationChanged(int cce) {
motorConfigurationPanel.fireTableDataChanged(cce); configurationChanged(cce, null);
recoveryConfigurationPanel.fireTableDataChanged(cce);
separationConfigurationPanel.fireTableDataChanged(cce);
} }
private void updateButtonState() { private void updateButtonState() {

View File

@ -64,11 +64,12 @@ public abstract class FlightConfigurablePanel<T extends FlightConfigurableCompon
/** /**
* Update the data in the table, with component change event type {cce} * Update the data in the table, with component change event type {cce}
* @param cce index of the ComponentChangeEvent to use (e.g. ComponentChangeEvent.NONFUNCTIONAL_CHANGE) * @param cce index of the ComponentChangeEvent to use (e.g. ComponentChangeEvent.NONFUNCTIONAL_CHANGE)
* @param ids: the IDs of the flight configurations that are affected by the change
*/ */
public void fireTableDataChanged(int cce) { public void fireTableDataChanged(int cce, FlightConfigurationId[] ids) {
int selectedRow = table.getSelectedRow(); int selectedRow = table.getSelectedRow();
int selectedColumn = table.getSelectedColumn(); int selectedColumn = table.getSelectedColumn();
this.rocket.fireComponentChangeEvent(cce); this.rocket.fireComponentChangeEvent(cce, ids);
((AbstractTableModel)table.getModel()).fireTableDataChanged(); ((AbstractTableModel)table.getModel()).fireTableDataChanged();
restoreSelection(selectedRow,selectedColumn); restoreSelection(selectedRow,selectedColumn);
updateButtonState(); updateButtonState();

View File

@ -330,7 +330,7 @@ public class MotorConfigurationPanel extends FlightConfigurablePanel<MotorMount>
} }
if (update) { if (update) {
fireTableDataChanged(ComponentChangeEvent.MOTOR_CHANGE); fireTableDataChanged(ComponentChangeEvent.MOTOR_CHANGE, fcIds.toArray(new FlightConfigurationId[0]));
} else { } else {
table.requestFocusInWindow(); table.requestFocusInWindow();
} }
@ -349,7 +349,7 @@ public class MotorConfigurationPanel extends FlightConfigurablePanel<MotorMount>
} }
} }
fireTableDataChanged(ComponentChangeEvent.MOTOR_CHANGE); fireTableDataChanged(ComponentChangeEvent.MOTOR_CHANGE, fcIds.toArray(new FlightConfigurationId[0]));
} }
private void selectIgnition() { private void selectIgnition() {
@ -396,7 +396,7 @@ public class MotorConfigurationPanel extends FlightConfigurablePanel<MotorMount>
} }
if (update) { if (update) {
fireTableDataChanged(ComponentChangeEvent.MOTOR_CHANGE); fireTableDataChanged(ComponentChangeEvent.MOTOR_CHANGE, fcIds.toArray(new FlightConfigurationId[0]));
} else { } else {
table.requestFocusInWindow(); table.requestFocusInWindow();
} }
@ -426,7 +426,7 @@ public class MotorConfigurationPanel extends FlightConfigurablePanel<MotorMount>
} }
if (update) { if (update) {
fireTableDataChanged(ComponentChangeEvent.MOTOR_CHANGE); fireTableDataChanged(ComponentChangeEvent.MOTOR_CHANGE, fcIds.toArray(new FlightConfigurationId[0]));
} else { } else {
table.requestFocusInWindow(); table.requestFocusInWindow();
} }

View File

@ -209,7 +209,7 @@ public class RecoveryConfigurationPanel extends FlightConfigurablePanel<Recovery
} }
if (update) { if (update) {
fireTableDataChanged(ComponentChangeEvent.AERODYNAMIC_CHANGE); fireTableDataChanged(ComponentChangeEvent.AERODYNAMIC_CHANGE, fcIds.toArray(new FlightConfigurationId[0]));
} else { } else {
table.requestFocusInWindow(); table.requestFocusInWindow();
} }
@ -235,7 +235,7 @@ public class RecoveryConfigurationPanel extends FlightConfigurablePanel<Recovery
} }
} }
if (update) { if (update) {
fireTableDataChanged(ComponentChangeEvent.AERODYNAMIC_CHANGE); fireTableDataChanged(ComponentChangeEvent.AERODYNAMIC_CHANGE, fcIds.toArray(new FlightConfigurationId[0]));
} else { } else {
table.requestFocusInWindow(); table.requestFocusInWindow();
} }

View File

@ -219,7 +219,7 @@ public class SeparationConfigurationPanel extends FlightConfigurablePanel<AxialS
} }
if (update) { if (update) {
fireTableDataChanged(ComponentChangeEvent.AEROMASS_CHANGE); fireTableDataChanged(ComponentChangeEvent.AEROMASS_CHANGE, fcIds.toArray(new FlightConfigurationId[0]));
} else { } else {
table.requestFocusInWindow(); table.requestFocusInWindow();
} }
@ -245,7 +245,7 @@ public class SeparationConfigurationPanel extends FlightConfigurablePanel<AxialS
} }
if (update) { if (update) {
fireTableDataChanged(ComponentChangeEvent.AEROMASS_CHANGE); fireTableDataChanged(ComponentChangeEvent.AEROMASS_CHANGE, fcIds.toArray(new FlightConfigurationId[0]));
} else { } else {
table.requestFocusInWindow(); table.requestFocusInWindow();
} }