X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2Fnet%2Fsf%2Fopenrocket%2Frocketcomponent%2FRocketComponent.java;h=a945d7b2dd9ecf5a38d063c9a971a93f84216f79;hb=4e356b38bfc24fc25a2fcf0ddbf0dee3a72d5f41;hp=335a22311252e533098d12ad07cacb679a1d9f49;hpb=720d4935bc6bec453e6478ad5227356c626610a2;p=debian%2Fopenrocket diff --git a/src/net/sf/openrocket/rocketcomponent/RocketComponent.java b/src/net/sf/openrocket/rocketcomponent/RocketComponent.java index 335a2231..a945d7b2 100644 --- a/src/net/sf/openrocket/rocketcomponent/RocketComponent.java +++ b/src/net/sf/openrocket/rocketcomponent/RocketComponent.java @@ -13,6 +13,7 @@ import java.util.UUID; import javax.swing.event.ChangeListener; +import net.sf.openrocket.util.BugException; import net.sf.openrocket.util.ChangeSource; import net.sf.openrocket.util.Coordinate; import net.sf.openrocket.util.LineStyle; @@ -307,7 +308,7 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, try { clone = (RocketComponent)this.clone(); } catch (CloneNotSupportedException e) { - throw new RuntimeException("CloneNotSupportedException encountered, " + + throw new BugException("CloneNotSupportedException encountered, " + "report a bug!",e); } @@ -316,10 +317,11 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, clone.children = new ArrayList(); // Add copied children to the structure without firing events. - for (RocketComponent c: this.children) { - RocketComponent copy = c.copy(); - clone.children.add(copy); - copy.parent = clone; + for (RocketComponent child: this.children) { + RocketComponent childCopy = child.copy(); + // Don't use add method since it fires events + clone.children.add(childCopy); + childCopy.parent = clone; } return clone; @@ -777,7 +779,7 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, break; default: - throw new RuntimeException("Unknown relative positioning type of component"+ + throw new BugException("Unknown relative positioning type of component"+ component+": "+component.relativePosition); } @@ -1079,6 +1081,10 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, RocketComponent stage = this; while (!(stage instanceof Stage)) { stage = stage.parent; + if (stage == null || stage.parent == null) { + throw new IllegalStateException("getStageNumber() could not find parent " + + "stage."); + } } return stage.parent.getChildPosition(stage); } @@ -1107,6 +1113,21 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, if (parent == null) return null; int pos = parent.getChildPosition(this); + if (pos < 0) { + StringBuffer sb = new StringBuffer(); + sb.append("Inconsistent internal state: "); + sb.append("this=").append(this).append('[') + .append(System.identityHashCode(this)).append(']'); + sb.append(" parent.children=["); + for (int i=0; i < parent.children.size(); i++) { + RocketComponent c = parent.children.get(i); + sb.append(c).append('[').append(System.identityHashCode(c)).append(']'); + if (i < parent.children.size()-1) + sb.append(", "); + } + sb.append(']'); + throw new IllegalStateException(sb.toString()); + } assert(pos >= 0); if (pos == 0) return parent; @@ -1155,12 +1176,15 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, /** * Removes a ComponentChangeListener from the rocket tree. The listener is removed from * the root component, which must be of type Rocket (which overrides this method). + * Does nothing if the root component is not a Rocket. (The asymmetry is so + * that listeners can always be removed just in case.) * * @param l Listener to remove - * @throws IllegalStateException - if the root component is not a Rocket */ public void removeComponentChangeListener(ComponentChangeListener l) { - getRocket().removeComponentChangeListener(l); + if (parent != null) { + getRoot().removeComponentChangeListener(l); + } } @@ -1180,12 +1204,15 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, /** * Removes a ChangeListener from the rocket tree. This is identical to * removeComponentChangeListener() except it uses a ChangeListener. + * Does nothing if the root component is not a Rocket. (The asymmetry is so + * that listeners can always be removed just in case.) * * @param l Listener to remove - * @throws IllegalStateException - if the root component is not a Rocket */ public void removeChangeListener(ChangeListener l) { - getRocket().removeChangeListener(l); + if (this.parent != null) { + getRoot().removeChangeListener(l); + } } @@ -1402,16 +1429,23 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, /** * Loads the RocketComponent fields from the given component. This method is meant - * for use with the undo/redo mechanism. - * + * for in-place replacement of a component. It is used with the undo/redo + * mechanism and when converting a finset into a freeform fin set. + * This component must not have a parent, otherwise this method will fail. + *

* The fields are copied by reference, and the supplied component must not be used * after the call, as it is in an undefined state. * * TODO: MEDIUM: Make general to copy all private/protected fields... */ protected void copyFrom(RocketComponent src) { + + if (this.parent != null) { + throw new UnsupportedOperationException("copyFrom called for non-root component " + + this); + } + // Set parents and children - this.parent = null; this.children = src.children; src.children = new ArrayList();