package net.sf.openrocket.rocketcomponent;
-import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import javax.swing.event.EventListenerList;
import net.sf.openrocket.gui.main.ExceptionHandler;
+import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.logging.LogHelper;
import net.sf.openrocket.motor.Motor;
import net.sf.openrocket.startup.Application;
+import net.sf.openrocket.util.ArrayList;
import net.sf.openrocket.util.Chars;
import net.sf.openrocket.util.Coordinate;
import net.sf.openrocket.util.MathUtil;
public class Rocket extends RocketComponent {
private static final LogHelper log = Application.getLogger();
+ private static final Translator trans = Application.getTranslator();
public static final double DEFAULT_REFERENCE_LENGTH = 0.01;
}
-
/**
* Return the non-negative modification ID of this rocket. The ID is changed
* every time any change occurs in the rocket. This can be used to check
* Make a deep copy of the Rocket structure. This method is exposed as public to allow
* for undo/redo system functionality.
*/
- @Override
@SuppressWarnings("unchecked")
+ @Override
public Rocket copyWithOriginalID() {
Rocket copy = (Rocket) super.copyWithOriginalID();
- copy.motorConfigurationIDs = (ArrayList<String>) this.motorConfigurationIDs.clone();
+ copy.motorConfigurationIDs = this.motorConfigurationIDs.clone();
copy.motorConfigurationNames =
(HashMap<String, String>) this.motorConfigurationNames.clone();
copy.resetListeners();
*/
@SuppressWarnings("unchecked")
public void loadFrom(Rocket r) {
- super.copyFrom(r);
+
+ // Store list of components to invalidate after event has been fired
+ List<RocketComponent> toInvalidate = this.copyFrom(r);
int type = ComponentChangeEvent.UNDO_CHANGE | ComponentChangeEvent.NONFUNCTIONAL_CHANGE;
if (this.massModID != r.massModID)
type |= ComponentChangeEvent.MASS_CHANGE;
if (this.aeroModID != r.aeroModID)
type |= ComponentChangeEvent.AERODYNAMIC_CHANGE;
- if (this.treeModID != r.treeModID)
- type |= ComponentChangeEvent.TREE_CHANGE;
+ // Loading a rocket is always a tree change since the component objects change
+ type |= ComponentChangeEvent.TREE_CHANGE;
this.modID = r.modID;
this.massModID = r.massModID;
this.refType = r.refType;
this.customReferenceLength = r.customReferenceLength;
- this.motorConfigurationIDs = (ArrayList<String>) r.motorConfigurationIDs.clone();
+ this.motorConfigurationIDs = r.motorConfigurationIDs.clone();
this.motorConfigurationNames =
(HashMap<String, String>) r.motorConfigurationNames.clone();
this.perfectFinish = r.perfectFinish;
if (!this.motorConfigurationIDs.contains(id))
defaultConfiguration.setMotorConfigurationID(null);
+ this.checkComponentStructure();
+
fireComponentChangeEvent(type);
+
+ // Invalidate obsolete components after event
+ for (RocketComponent c : toInvalidate) {
+ c.invalidate();
+ }
}
@Override
protected void fireComponentChangeEvent(ComponentChangeEvent e) {
- checkState();
-
- // Update modification ID's only for normal (not undo/redo) events
- if (!e.isUndoChange()) {
- modID = UniqueID.next();
- if (e.isMassChange())
- massModID = modID;
- if (e.isAerodynamicChange())
- aeroModID = modID;
- if (e.isTreeChange())
- treeModID = modID;
- if (e.getType() != ComponentChangeEvent.NONFUNCTIONAL_CHANGE)
- functionalModID = modID;
- }
-
- // Check whether frozen
- if (freezeList != null) {
- log.debug("Rocket is in frozen state, adding event " + e + " info freeze list");
- freezeList.add(e);
- return;
- }
-
- log.debug("Firing rocket change event " + e);
-
- // Notify all components first
- Iterator<RocketComponent> iterator = this.deepIterator(true);
- while (iterator.hasNext()) {
- iterator.next().componentChanged(e);
- }
-
- // Notify all listeners
- Object[] listeners = listenerList.getListenerList();
- for (int i = listeners.length - 2; i >= 0; i -= 2) {
- if (listeners[i] == ComponentChangeListener.class) {
- ((ComponentChangeListener) listeners[i + 1]).componentChanged(e);
- } else if (listeners[i] == ChangeListener.class) {
- ((ChangeListener) listeners[i + 1]).stateChanged(e);
+ mutex.lock("fireComponentChangeEvent");
+ try {
+ checkState();
+
+ // Update modification ID's only for normal (not undo/redo) events
+ if (!e.isUndoChange()) {
+ modID = UniqueID.next();
+ if (e.isMassChange())
+ massModID = modID;
+ if (e.isAerodynamicChange())
+ aeroModID = modID;
+ if (e.isTreeChange())
+ treeModID = modID;
+ if (e.getType() != ComponentChangeEvent.NONFUNCTIONAL_CHANGE)
+ functionalModID = modID;
+ }
+
+ // Check whether frozen
+ if (freezeList != null) {
+ log.debug("Rocket is in frozen state, adding event " + e + " info freeze list");
+ freezeList.add(e);
+ return;
+ }
+
+ log.debug("Firing rocket change event " + e);
+
+ // Notify all components first
+ Iterator<RocketComponent> iterator = this.iterator(true);
+ while (iterator.hasNext()) {
+ iterator.next().componentChanged(e);
+ }
+
+ // Notify all listeners
+ Object[] listeners = listenerList.getListenerList();
+ for (int i = listeners.length - 2; i >= 0; i -= 2) {
+ if (listeners[i] == ComponentChangeListener.class) {
+ ((ComponentChangeListener) listeners[i + 1]).componentChanged(e);
+ } else if (listeners[i] == ChangeListener.class) {
+ ((ChangeListener) listeners[i + 1]).stateChanged(e);
+ }
}
+ } finally {
+ mutex.unlock("fireComponentChangeEvent");
}
}
if (id == null)
return false;
- Iterator<RocketComponent> iterator = this.deepIterator();
+ Iterator<RocketComponent> iterator = this.iterator();
while (iterator.hasNext()) {
RocketComponent c = iterator.next();
List<List<String>> list = new ArrayList<List<String>>();
List<String> currentList = null;
- Iterator<RocketComponent> iterator = this.deepIterator();
+ Iterator<RocketComponent> iterator = this.iterator();
while (iterator.hasNext()) {
RocketComponent c = iterator.next();
}
if (motorCount == 0) {
- return "[No motors]";
+ //// [No motors]
+ return trans.get("Rocket.motorCount.Nomotor");
}
// Change multiple occurrences of a motor to n x motor
@Override
public String getComponentName() {
- return "Rocket";
+ //// Rocket
+ return trans.get("Rocket.compname.Rocket");
}
@Override
}
@Override
- public double getLongitudalUnitInertia() {
+ public double getLongitudinalUnitInertia() {
return 0;
}
public boolean isCompatible(Class<? extends RocketComponent> type) {
return (Stage.class.isAssignableFrom(type));
}
+
+ /**
+ * Accept a visitor to this Rocket in the component hierarchy.
+ *
+ * @param theVisitor the visitor that will be called back with a reference to this Rocket
+ */
+ @Override
+ public void accept(final ComponentVisitor theVisitor) {
+ theVisitor.visit(this);
+ }
}