[#1956] Fix issue in multi-comp edit during undo operation
At least I hope this fixes it; it was a weird bug and hard to replicate...
This commit is contained in:
parent
ac03080588
commit
e8638b25cf
@ -241,6 +241,7 @@ public class AxialStage extends ComponentAssembly implements FlightConfigurableC
|
|||||||
@Override
|
@Override
|
||||||
public void clearConfigListeners() {
|
public void clearConfigListeners() {
|
||||||
super.clearConfigListeners();
|
super.clearConfigListeners();
|
||||||
|
// StageSeparationConfiguration also has config listeners, so clear them as well
|
||||||
StageSeparationConfiguration thisConfig = getSeparationConfiguration();
|
StageSeparationConfiguration thisConfig = getSeparationConfiguration();
|
||||||
thisConfig.clearConfigListeners();
|
thisConfig.clearConfigListeners();
|
||||||
}
|
}
|
||||||
|
@ -549,6 +549,7 @@ public class BodyTube extends SymmetricComponent implements BoxBounded, MotorMou
|
|||||||
@Override
|
@Override
|
||||||
public void clearConfigListeners() {
|
public void clearConfigListeners() {
|
||||||
super.clearConfigListeners();
|
super.clearConfigListeners();
|
||||||
|
// The motor config also has listeners, so clear them as well
|
||||||
getDefaultMotorConfig().clearConfigListeners();
|
getDefaultMotorConfig().clearConfigListeners();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -482,6 +482,7 @@ public class InnerTube extends ThicknessRingComponent implements AxialPositionab
|
|||||||
@Override
|
@Override
|
||||||
public void clearConfigListeners() {
|
public void clearConfigListeners() {
|
||||||
super.clearConfigListeners();
|
super.clearConfigListeners();
|
||||||
|
// The motor config also has listeners, so clear them as well
|
||||||
getDefaultMotorConfig().clearConfigListeners();
|
getDefaultMotorConfig().clearConfigListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,14 +1,9 @@
|
|||||||
package net.sf.openrocket.rocketcomponent;
|
package net.sf.openrocket.rocketcomponent;
|
||||||
|
|
||||||
import net.sf.openrocket.appearance.Appearance;
|
|
||||||
import net.sf.openrocket.appearance.Decal;
|
|
||||||
import net.sf.openrocket.l10n.Translator;
|
import net.sf.openrocket.l10n.Translator;
|
||||||
import net.sf.openrocket.preset.ComponentPreset;
|
import net.sf.openrocket.preset.ComponentPreset;
|
||||||
import net.sf.openrocket.preset.ComponentPreset.Type;
|
import net.sf.openrocket.preset.ComponentPreset.Type;
|
||||||
import net.sf.openrocket.startup.Application;
|
import net.sf.openrocket.startup.Application;
|
||||||
import net.sf.openrocket.util.StateChangeListener;
|
|
||||||
|
|
||||||
import java.util.EventObject;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rocket nose cones of various types. Implemented as a transition with the
|
* Rocket nose cones of various types. Implemented as a transition with the
|
||||||
@ -205,7 +200,7 @@ public class NoseCone extends Transition implements InsideColorComponent {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean previousByPass = getBypassComponentChangeEvent();
|
boolean previousByPass = isBypassComponentChangeEvent();
|
||||||
setBypassChangeEvent(true);
|
setBypassChangeEvent(true);
|
||||||
if (flipped) {
|
if (flipped) {
|
||||||
setForeRadius(getAftRadiusNoAutomatic());
|
setForeRadius(getAftRadiusNoAutomatic());
|
||||||
|
@ -177,6 +177,7 @@ public abstract class RecoveryDevice extends MassObject implements FlightConfigu
|
|||||||
@Override
|
@Override
|
||||||
public void clearConfigListeners() {
|
public void clearConfigListeners() {
|
||||||
super.clearConfigListeners();
|
super.clearConfigListeners();
|
||||||
|
// The DeploymentConfiguration also has listeners, so clear them as well
|
||||||
DeploymentConfiguration thisConfig = getDeploymentConfigurations().getDefault();
|
DeploymentConfiguration thisConfig = getDeploymentConfigurations().getDefault();
|
||||||
thisConfig.clearConfigListeners();
|
thisConfig.clearConfigListeners();
|
||||||
}
|
}
|
||||||
|
@ -448,6 +448,7 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
|
|||||||
}
|
}
|
||||||
// Make sure the config listeners aren't cloned
|
// Make sure the config listeners aren't cloned
|
||||||
clone.configListeners = new LinkedList<>();
|
clone.configListeners = new LinkedList<>();
|
||||||
|
clone.bypassComponentChangeEvent = false;
|
||||||
return clone;
|
return clone;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -603,7 +604,7 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
|
|||||||
for (RocketComponent listener : configListeners) {
|
for (RocketComponent listener : configListeners) {
|
||||||
listener.setBypassChangeEvent(false);
|
listener.setBypassChangeEvent(false);
|
||||||
listener.setMassOverridden(o);
|
listener.setMassOverridden(o);
|
||||||
listener.setBypassChangeEvent(false);
|
listener.setBypassChangeEvent(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (massOverridden == o) {
|
if (massOverridden == o) {
|
||||||
@ -2277,7 +2278,11 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
|
|||||||
this.bypassComponentChangeEvent = newValue;
|
this.bypassComponentChangeEvent = newValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean getBypassComponentChangeEvent() {
|
/**
|
||||||
|
* Returns whether the current component if ignoring ComponentChangeEvents.
|
||||||
|
* @return true if the component is ignoring ComponentChangeEvents.
|
||||||
|
*/
|
||||||
|
public boolean isBypassComponentChangeEvent() {
|
||||||
return this.bypassComponentChangeEvent;
|
return this.bypassComponentChangeEvent;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2287,7 +2292,18 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
|
|||||||
* @return true if listener was successfully added, false if not
|
* @return true if listener was successfully added, false if not
|
||||||
*/
|
*/
|
||||||
public boolean addConfigListener(RocketComponent listener) {
|
public boolean addConfigListener(RocketComponent listener) {
|
||||||
if (listener == null || configListeners.contains(listener) || listener == this) {
|
if (isBypassComponentChangeEvent()) {
|
||||||
|
// This is a precaution. If you are multi-comp editing and the current component is bypassing events,
|
||||||
|
// the editing will be REALLY weird, see GitHub issue #1956.
|
||||||
|
throw new IllegalStateException("Cannot add config listener while bypassing events");
|
||||||
|
}
|
||||||
|
if (listener == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (listener.getConfigListeners().size() > 0) {
|
||||||
|
throw new IllegalArgumentException("Listener already has config listeners");
|
||||||
|
}
|
||||||
|
if (configListeners.contains(listener) || listener == this) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
configListeners.add(listener);
|
configListeners.add(listener);
|
||||||
@ -2555,6 +2571,7 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
|
|||||||
this.displayOrder_side = src.displayOrder_side;
|
this.displayOrder_side = src.displayOrder_side;
|
||||||
this.displayOrder_back = src.displayOrder_back;
|
this.displayOrder_back = src.displayOrder_back;
|
||||||
this.configListeners = new LinkedList<>();
|
this.configListeners = new LinkedList<>();
|
||||||
|
this.bypassComponentChangeEvent = false;
|
||||||
if (this instanceof InsideColorComponent && src instanceof InsideColorComponent) {
|
if (this instanceof InsideColorComponent && src instanceof InsideColorComponent) {
|
||||||
InsideColorComponentHandler icch = new InsideColorComponentHandler(this);
|
InsideColorComponentHandler icch = new InsideColorComponentHandler(this);
|
||||||
icch.copyFrom(((InsideColorComponent) src).getInsideColorComponentHandler());
|
icch.copyFrom(((InsideColorComponent) src).getInsideColorComponentHandler());
|
||||||
|
@ -105,6 +105,7 @@ public class DesignPanel extends JSplitPane {
|
|||||||
// Double-click
|
// Double-click
|
||||||
if ((e.getButton() == MouseEvent.BUTTON1) && (e.getClickCount() == 2) && !ComponentConfigDialog.isDialogVisible()) {
|
if ((e.getButton() == MouseEvent.BUTTON1) && (e.getClickCount() == 2) && !ComponentConfigDialog.isDialogVisible()) {
|
||||||
RocketComponent component = (RocketComponent) selPath.getLastPathComponent();
|
RocketComponent component = (RocketComponent) selPath.getLastPathComponent();
|
||||||
|
component.clearConfigListeners();
|
||||||
|
|
||||||
// Multi-component edit if shift/meta key is pressed
|
// Multi-component edit if shift/meta key is pressed
|
||||||
if ((e.isShiftDown() || e.isMetaDown()) && tree.getSelectionPaths() != null) {
|
if ((e.isShiftDown() || e.isMetaDown()) && tree.getSelectionPaths() != null) {
|
||||||
|
@ -985,6 +985,7 @@ public class RocketActions {
|
|||||||
ComponentConfigDialog.disposeDialog();
|
ComponentConfigDialog.disposeDialog();
|
||||||
|
|
||||||
RocketComponent component = components.get(0);
|
RocketComponent component = components.get(0);
|
||||||
|
component.clearConfigListeners();
|
||||||
if (components.size() > 1) {
|
if (components.size() > 1) {
|
||||||
for (int i = 1; i < components.size(); i++) {
|
for (int i = 1; i < components.size(); i++) {
|
||||||
RocketComponent listener = components.get(i);
|
RocketComponent listener = components.get(i);
|
||||||
|
@ -636,6 +636,7 @@ public class RocketPanel extends JPanel implements TreeSelectionListener, Change
|
|||||||
if (event.isShiftDown() || event.isMetaDown()) {
|
if (event.isShiftDown() || event.isMetaDown()) {
|
||||||
List<TreePath> paths = new ArrayList<>(Arrays.asList(selectionModel.getSelectionPaths()));
|
List<TreePath> paths = new ArrayList<>(Arrays.asList(selectionModel.getSelectionPaths()));
|
||||||
RocketComponent component = selectedComponents.get(selectedComponents.size() - 1);
|
RocketComponent component = selectedComponents.get(selectedComponents.size() - 1);
|
||||||
|
component.clearConfigListeners();
|
||||||
|
|
||||||
// Make sure the clicked component is selected
|
// Make sure the clicked component is selected
|
||||||
for (RocketComponent c : clicked) {
|
for (RocketComponent c : clicked) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user