Refactor doc material loading to OpenRocketDocument

This commit is contained in:
SiboVG 2024-08-07 15:41:04 +02:00
parent 65116fcb58
commit 0d5952cfa3
2 changed files with 148 additions and 147 deletions

View File

@ -4,6 +4,7 @@ import java.io.File;
import java.util.*; import java.util.*;
import info.openrocket.core.file.wavefrontobj.export.OBJExportOptions; import info.openrocket.core.file.wavefrontobj.export.OBJExportOptions;
import info.openrocket.core.material.Material;
import info.openrocket.core.preferences.ApplicationPreferences; import info.openrocket.core.preferences.ApplicationPreferences;
import info.openrocket.core.preferences.DocumentPreferences; import info.openrocket.core.preferences.DocumentPreferences;
import info.openrocket.core.rocketcomponent.*; import info.openrocket.core.rocketcomponent.*;
@ -33,7 +34,7 @@ import info.openrocket.core.util.ArrayList;
* - Simulation instances * - Simulation instances
* - the stored file and file save information * - the stored file and file save information
* - undo/redo information * - undo/redo information
* *
* @author Sampo Niskanen <sampo.niskanen@iki.fi> * @author Sampo Niskanen <sampo.niskanen@iki.fi>
*/ */
public class OpenRocketDocument implements ComponentChangeListener, StateChangeListener { public class OpenRocketDocument implements ComponentChangeListener, StateChangeListener {
@ -46,65 +47,65 @@ public class OpenRocketDocument implements ComponentChangeListener, StateChangeL
*/ */
public static final int UNDO_LEVELS = 50; public static final int UNDO_LEVELS = 50;
/** /**
* The margin of the undo levels. After the number of undo levels exceeds * The margin of the undo levels. After the number of undo levels exceeds
* UNDO_LEVELS by this amount the undo is purged to that length. * UNDO_LEVELS by this amount the undo is purged to that length.
*/ */
public static final int UNDO_MARGIN = 10; public static final int UNDO_MARGIN = 10;
public static final String SIMULATION_NAME_PREFIX = "Simulation "; public static final String SIMULATION_NAME_PREFIX = "Simulation ";
/** Whether an undo error has already been reported to the user */ /** Whether an undo error has already been reported to the user */
private static boolean undoErrorReported = false; private static boolean undoErrorReported = false;
private final Rocket rocket; private final Rocket rocket;
private final ArrayList<Simulation> simulations = new ArrayList<Simulation>(); private final ArrayList<Simulation> simulations = new ArrayList<Simulation>();
private final ArrayList<CustomExpression> customExpressions = new ArrayList<CustomExpression>(); private final ArrayList<CustomExpression> customExpressions = new ArrayList<CustomExpression>();
// The Photo Settings will be saved in the core module as a map of key values with corresponding content // The Photo Settings will be saved in the core module as a map of key values with corresponding content
private Map<String, String> photoSettings = new HashMap<>(); private Map<String, String> photoSettings = new HashMap<>();
/* /*
* The undo/redo variables and mechanism are documented in doc/undo-redo-flow.* * The undo/redo variables and mechanism are documented in doc/undo-redo-flow.*
*/ */
/** /**
* The undo history of the rocket. Whenever a new undo position is created while the * The undo history of the rocket. Whenever a new undo position is created while the
* rocket is in "dirty" state, the rocket is copied here. * rocket is in "dirty" state, the rocket is copied here.
*/ */
private final LinkedList<Rocket> undoHistory = new LinkedList<Rocket>(); private final LinkedList<Rocket> undoHistory = new LinkedList<Rocket>();
private final LinkedList<String> undoDescription = new LinkedList<String>(); private final LinkedList<String> undoDescription = new LinkedList<String>();
/** /**
* The position in the undoHistory we are currently at. If modifications have been * The position in the undoHistory we are currently at. If modifications have been
* made to the rocket, the rocket is in "dirty" state and this points to the previous * made to the rocket, the rocket is in "dirty" state and this points to the previous
* "clean" state. * "clean" state.
*/ */
private int undoPosition = -1; // Illegal position, init in constructor private int undoPosition = -1; // Illegal position, init in constructor
/** /**
* The description of the next action that modifies this rocket. * The description of the next action that modifies this rocket.
*/ */
private String nextDescription = null; private String nextDescription = null;
private String storedDescription = null; private String storedDescription = null;
private final ArrayList<UndoRedoListener> undoRedoListeners = new ArrayList<UndoRedoListener>(2); private final ArrayList<UndoRedoListener> undoRedoListeners = new ArrayList<UndoRedoListener>(2);
private File file = null; private File file = null;
private int modID = -1; private int modID = -1;
private int savedID = -1; private int savedID = -1;
private final StorageOptions storageOptions = new StorageOptions(); private final StorageOptions storageOptions = new StorageOptions();
private final OBJExportOptions objOptions; private final OBJExportOptions objOptions;
private final DecalRegistry decalRegistry = new DecalRegistry(); private final DecalRegistry decalRegistry = new DecalRegistry();
private final List<DocumentChangeListener> listeners = new ArrayList<DocumentChangeListener>(); private final List<DocumentChangeListener> listeners = new ArrayList<DocumentChangeListener>();
/** /**
* main constructor, enable events in the rocket * main constructor, enable events in the rocket
* and initializes the document * and initializes the document
* @param rocket the rocket to be used in the document * @param rocket the rocket to be used in the document
*/ */
OpenRocketDocument(Rocket rocket) { OpenRocketDocument(Rocket rocket) {
@ -113,7 +114,7 @@ public class OpenRocketDocument implements ComponentChangeListener, StateChangeL
rocket.enableEvents(); rocket.enableEvents();
init(); init();
} }
/** /**
* initializes the document, clearing the undo cache and * initializes the document, clearing the undo cache and
* setting itself as a listener for changes in the rocket * setting itself as a listener for changes in the rocket
@ -122,7 +123,7 @@ public class OpenRocketDocument implements ComponentChangeListener, StateChangeL
clearUndo(); clearUndo();
rocket.addComponentChangeListener(this); rocket.addComponentChangeListener(this);
} }
/** /**
* adds a customExpression into the list * adds a customExpression into the list
* @param expression the expression to be added * @param expression the expression to be added
@ -130,10 +131,10 @@ public class OpenRocketDocument implements ComponentChangeListener, StateChangeL
public void addCustomExpression(CustomExpression expression) { public void addCustomExpression(CustomExpression expression) {
if (customExpressions.contains(expression)) { if (customExpressions.contains(expression)) {
log.info(Markers.USER_MARKER, "Could not add custom expression " + expression.getName() + " to document as document already has a matching expression."); log.info(Markers.USER_MARKER, "Could not add custom expression " + expression.getName() + " to document as document already has a matching expression.");
} }
customExpressions.add(expression); customExpressions.add(expression);
} }
/** /**
* Removes custom expression from the document * Removes custom expression from the document
* @param expression * @param expression
@ -141,44 +142,44 @@ public class OpenRocketDocument implements ComponentChangeListener, StateChangeL
public void removeCustomExpression(CustomExpression expression) { public void removeCustomExpression(CustomExpression expression) {
customExpressions.remove(expression); customExpressions.remove(expression);
} }
//TODO:LOW:this leaves the object custom expression exposed, is it supposed to be like that? //TODO:LOW:this leaves the object custom expression exposed, is it supposed to be like that?
/** /**
* *
* @return * @return
*/ */
public List<CustomExpression> getCustomExpressions() { public List<CustomExpression> getCustomExpressions() {
return customExpressions; return customExpressions;
} }
/** /**
* @returns a set of all the flight data types defined or available in any way in the rocket document * @returns a set of all the flight data types defined or available in any way in the rocket document
*/ */
public Set<FlightDataType> getFlightDataTypes() { public Set<FlightDataType> getFlightDataTypes() {
Set<FlightDataType> allTypes = new LinkedHashSet<FlightDataType>(); Set<FlightDataType> allTypes = new LinkedHashSet<FlightDataType>();
// built in // built in
Collections.addAll(allTypes, FlightDataType.ALL_TYPES); Collections.addAll(allTypes, FlightDataType.ALL_TYPES);
// custom expressions // custom expressions
for (CustomExpression exp : customExpressions) { for (CustomExpression exp : customExpressions) {
allTypes.add(exp.getType()); allTypes.add(exp.getType());
} }
// simulation listeners // simulation listeners
for (Simulation sim : simulations) { for (Simulation sim : simulations) {
for (SimulationExtension c : sim.getSimulationExtensions()) { for (SimulationExtension c : sim.getSimulationExtensions()) {
allTypes.addAll(c.getFlightDataTypes()); allTypes.addAll(c.getFlightDataTypes());
} }
} }
// imported data // imported data
/// not implemented yet /// not implemented yet
return allTypes; return allTypes;
} }
/** /**
* gets the rocket in the document * gets the rocket in the document
* @return the rocket in the document * @return the rocket in the document
@ -186,7 +187,7 @@ public class OpenRocketDocument implements ComponentChangeListener, StateChangeL
public Rocket getRocket() { public Rocket getRocket() {
return rocket; return rocket;
} }
/** /**
* returns the selected configuration from the rocket * returns the selected configuration from the rocket
* @return selected configuration from the rocket * @return selected configuration from the rocket
@ -194,7 +195,7 @@ public class OpenRocketDocument implements ComponentChangeListener, StateChangeL
public FlightConfiguration getSelectedConfiguration() { public FlightConfiguration getSelectedConfiguration() {
return rocket.getSelectedConfiguration(); return rocket.getSelectedConfiguration();
} }
/** /**
* returns the File handler object for the document * returns the File handler object for the document
* @return the File handler object for the document * @return the File handler object for the document
@ -220,7 +221,7 @@ public class OpenRocketDocument implements ComponentChangeListener, StateChangeL
} }
return file; return file;
} }
/** /**
* set the file handler object for the document * set the file handler object for the document
* @param file the new file handler object * @param file the new file handler object
@ -228,7 +229,7 @@ public class OpenRocketDocument implements ComponentChangeListener, StateChangeL
public void setFile(File file) { public void setFile(File file) {
this.file = file; this.file = file;
} }
/** /**
* returns if the current rocket is saved * returns if the current rocket is saved
* @return if the current rocket is saved * @return if the current rocket is saved
@ -236,7 +237,7 @@ public class OpenRocketDocument implements ComponentChangeListener, StateChangeL
public boolean isSaved() { public boolean isSaved() {
return rocket.getModID() + modID == savedID; return rocket.getModID() + modID == savedID;
} }
/** /**
* sets the current rocket as saved, and none if false is given * sets the current rocket as saved, and none if false is given
* @param saved if the current rocket or none will be set to save * @param saved if the current rocket or none will be set to save
@ -247,7 +248,7 @@ public class OpenRocketDocument implements ComponentChangeListener, StateChangeL
else else
this.savedID = rocket.getModID() + modID; this.savedID = rocket.getModID() + modID;
} }
/** /**
* Retrieve the default storage options for this document. * Retrieve the default storage options for this document.
* *
@ -261,25 +262,25 @@ public class OpenRocketDocument implements ComponentChangeListener, StateChangeL
return objOptions; return objOptions;
} }
/** /**
* returns the decal list used in the document * returns the decal list used in the document
* @return the decal list registered in the document * @return the decal list registered in the document
*/ */
public Collection<DecalImage> getDecalList() { public Collection<DecalImage> getDecalList() {
return decalRegistry.getDecalList(); return decalRegistry.getDecalList();
} }
/** /**
* returns the number of times the given decal was used * returns the number of times the given decal was used
* @param img the decal to be counted * @param img the decal to be counted
* @return the number of times * @return the number of times
*/ */
public int countDecalUsage(DecalImage img) { public int countDecalUsage(DecalImage img) {
int count = 0; int count = 0;
Iterator<RocketComponent> it = rocket.iterator(); Iterator<RocketComponent> it = rocket.iterator();
while (it.hasNext()) { while (it.hasNext()) {
RocketComponent c = it.next(); RocketComponent c = it.next();
@ -290,7 +291,7 @@ public class OpenRocketDocument implements ComponentChangeListener, StateChangeL
} }
return count; return count;
} }
//TODO: LOW: move this method to rocketComponent, Appearance and decal //TODO: LOW: move this method to rocketComponent, Appearance and decal
//I see 3 layers of object accessed, seems unsafe //I see 3 layers of object accessed, seems unsafe
/** /**
@ -333,7 +334,7 @@ public class OpenRocketDocument implements ComponentChangeListener, StateChangeL
} }
return false; return false;
} }
/** /**
* gets a unique identification for the given decal * gets a unique identification for the given decal
* @param img the decal to be made unique * @param img the decal to be made unique
@ -345,7 +346,7 @@ public class OpenRocketDocument implements ComponentChangeListener, StateChangeL
} }
return decalRegistry.makeUniqueImage(img); return decalRegistry.makeUniqueImage(img);
} }
/** /**
* gets the decal image from an attachment * gets the decal image from an attachment
* @param a the attachment * @param a the attachment
@ -354,7 +355,7 @@ public class OpenRocketDocument implements ComponentChangeListener, StateChangeL
public DecalImage getDecalImage(Attachment a) { public DecalImage getDecalImage(Attachment a) {
return decalRegistry.getDecalImage(a); return decalRegistry.getDecalImage(a);
} }
/** /**
* gets a list of simulations in the document * gets a list of simulations in the document
* @return the simulations in the document * @return the simulations in the document
@ -362,7 +363,7 @@ public class OpenRocketDocument implements ComponentChangeListener, StateChangeL
public List<Simulation> getSimulations() { public List<Simulation> getSimulations() {
return simulations.clone(); return simulations.clone();
} }
/** /**
* gets the number of simulations in the document * gets the number of simulations in the document
* @return the number of simulations in the document * @return the number of simulations in the document
@ -370,7 +371,7 @@ public class OpenRocketDocument implements ComponentChangeListener, StateChangeL
public int getSimulationCount() { public int getSimulationCount() {
return simulations.size(); return simulations.size();
} }
/** /**
* the the Nth simulation from the document * the the Nth simulation from the document
* @param n simulation index * @param n simulation index
@ -379,7 +380,7 @@ public class OpenRocketDocument implements ComponentChangeListener, StateChangeL
public Simulation getSimulation(int n) { public Simulation getSimulation(int n) {
return simulations.get(n); return simulations.get(n);
} }
/** /**
* gets the index of the given simulation * gets the index of the given simulation
* @param simulation the simulation being searched * @param simulation the simulation being searched
@ -388,7 +389,7 @@ public class OpenRocketDocument implements ComponentChangeListener, StateChangeL
public int getSimulationIndex(Simulation simulation) { public int getSimulationIndex(Simulation simulation) {
return simulations.indexOf(simulation); return simulations.indexOf(simulation);
} }
/** /**
* adds simulation into the document * adds simulation into the document
* fires document change event * fires document change event
@ -397,7 +398,7 @@ public class OpenRocketDocument implements ComponentChangeListener, StateChangeL
public void addSimulation(Simulation simulation) { public void addSimulation(Simulation simulation) {
addSimulation(simulation, simulations.size()); addSimulation(simulation, simulations.size());
} }
/** /**
* adds the simulation to the Nth index, overwriting if there is already one * adds the simulation to the Nth index, overwriting if there is already one
* fires change document event * fires change document event
@ -412,7 +413,7 @@ public class OpenRocketDocument implements ComponentChangeListener, StateChangeL
} }
fireDocumentChangeEvent(new SimulationChangeEvent(simulation)); fireDocumentChangeEvent(new SimulationChangeEvent(simulation));
} }
/** /**
* removes the specific simulation from the list * removes the specific simulation from the list
* @param simulation the simulation to be removed * @param simulation the simulation to be removed
@ -421,7 +422,7 @@ public class OpenRocketDocument implements ComponentChangeListener, StateChangeL
simulations.remove(simulation); simulations.remove(simulation);
fireDocumentChangeEvent(new SimulationChangeEvent(simulation)); fireDocumentChangeEvent(new SimulationChangeEvent(simulation));
} }
/** /**
* removes the Nth simulation from the document * removes the Nth simulation from the document
* fires document change event * fires document change event
@ -433,7 +434,7 @@ public class OpenRocketDocument implements ComponentChangeListener, StateChangeL
fireDocumentChangeEvent(new SimulationChangeEvent(simulation)); fireDocumentChangeEvent(new SimulationChangeEvent(simulation));
return simulation; return simulation;
} }
/** /**
* removes the flight configuration and simulation with the specific id * removes the flight configuration and simulation with the specific id
* @param configId * @param configId
@ -458,13 +459,13 @@ public class OpenRocketDocument implements ComponentChangeListener, StateChangeL
} }
} }
} }
/** /**
* Return a unique name suitable for the next simulation. The name begins * Return a unique name suitable for the next simulation. The name begins
* with {@link #SIMULATION_NAME_PREFIX} and has a unique number larger than any * with {@link #SIMULATION_NAME_PREFIX} and has a unique number larger than any
* previous simulation. * previous simulation.
* *
* @return the new name. * @return the new name.
*/ */
public String getNextSimulationName() { public String getNextSimulationName() {
@ -482,39 +483,39 @@ public class OpenRocketDocument implements ComponentChangeListener, StateChangeL
} }
return SIMULATION_NAME_PREFIX + (maxValue + 1); return SIMULATION_NAME_PREFIX + (maxValue + 1);
} }
/** /**
* Adds an undo point at this position. This method should be called *before* any * Adds an undo point at this position. This method should be called *before* any
* action that is to be undoable. All actions after the call will be undone by a * action that is to be undoable. All actions after the call will be undone by a
* single "Undo" action. * single "Undo" action.
* <p> * <p>
* The description should be a short, descriptive string of the actions that will * The description should be a short, descriptive string of the actions that will
* follow. This is shown to the user e.g. in the Edit-menu, for example * follow. This is shown to the user e.g. in the Edit-menu, for example
* "Undo (Modify body tube)". If the actions are not known (in general should not * "Undo (Modify body tube)". If the actions are not known (in general should not
* be the case!) description may be null. * be the case!) description may be null.
* <p> * <p>
* If this method is called successively without any change events occurring between the * If this method is called successively without any change events occurring between the
* calls, only the last call will have any effect. * calls, only the last call will have any effect.
* *
* @param description A short description of the following actions. * @param description A short description of the following actions.
*/ */
public void addUndoPosition(String description) { public void addUndoPosition(String description) {
checkDescription(description); checkDescription(description);
// Check whether modifications have been done since last call // Check whether modifications have been done since last call
if(isCheckNoModification(description)) if(isCheckNoModification(description))
return; return;
log.info("Adding undo position '" + description + "' to " + this + ", document is in unclean state"); log.info("Adding undo position '" + description + "' to " + this + ", document is in unclean state");
checkUndoPositionConsistency(); checkUndoPositionConsistency();
addStateToUndoHistory(description); addStateToUndoHistory(description);
maintainMaximumUndoSize(); maintainMaximumUndoSize();
} }
/** /**
* *
*/ */
private void maintainMaximumUndoSize() { private void maintainMaximumUndoSize() {
if (undoHistory.size() > UNDO_LEVELS + UNDO_MARGIN && undoPosition > UNDO_MARGIN) { if (undoHistory.size() > UNDO_LEVELS + UNDO_MARGIN && undoPosition > UNDO_MARGIN) {
@ -539,7 +540,7 @@ public class OpenRocketDocument implements ComponentChangeListener, StateChangeL
/** /**
* checks if there was or not modification, and logs * checks if there was or not modification, and logs
* *
* @param description the description to be used in the log * @param description the description to be used in the log
* @return if there was or not modification * @return if there was or not modification
*/ */
@ -552,11 +553,11 @@ public class OpenRocketDocument implements ComponentChangeListener, StateChangeL
} }
return false; return false;
} }
/** /**
* checks if the document already has a stored undo description * checks if the document already has a stored undo description
* logs if it has * logs if it has
* *
* @param description undo description to be logged * @param description undo description to be logged
*/ */
private void checkDescription(String description) { private void checkDescription(String description) {
@ -576,15 +577,15 @@ public class OpenRocketDocument implements ComponentChangeListener, StateChangeL
} }
removeRedoInfo(); removeRedoInfo();
} }
/** /**
* Start a time-limited undoable operation. After the operation {@link #stopUndo()} * Start a time-limited undoable operation. After the operation {@link #stopUndo()}
* must be called, which will restore the previous undo description into effect. * must be called, which will restore the previous undo description into effect.
* Only one level of start-stop undo descriptions is supported, i.e. start-stop * Only one level of start-stop undo descriptions is supported, i.e. start-stop
* undo cannot be nested, and no other undo operations may be called between * undo cannot be nested, and no other undo operations may be called between
* the start and stop calls. * the start and stop calls.
* *
* @param description Description of the following undoable operations. * @param description Description of the following undoable operations.
*/ */
public void startUndo(String description) { public void startUndo(String description) {
@ -597,7 +598,7 @@ public class OpenRocketDocument implements ComponentChangeListener, StateChangeL
addUndoPosition(description); addUndoPosition(description);
storedDescription = store; storedDescription = store;
} }
/** /**
* End the previous time-limited undoable operation. This must be called after * End the previous time-limited undoable operation. This must be called after
* {@link #startUndo(String)} has been called before any other undo operations are * {@link #startUndo(String)} has been called before any other undo operations are
@ -610,8 +611,8 @@ public class OpenRocketDocument implements ComponentChangeListener, StateChangeL
storedDescription = null; storedDescription = null;
addUndoPosition(stored); addUndoPosition(stored);
} }
/** /**
* Clear the undo history. * Clear the undo history.
*/ */
@ -619,18 +620,18 @@ public class OpenRocketDocument implements ComponentChangeListener, StateChangeL
//log.info("Clearing undo history of " + this); //log.info("Clearing undo history of " + this);
undoHistory.clear(); undoHistory.clear();
undoDescription.clear(); undoDescription.clear();
undoHistory.add(rocket.copyWithOriginalID()); undoHistory.add(rocket.copyWithOriginalID());
undoDescription.add(null); undoDescription.add(null);
undoPosition = 0; undoPosition = 0;
fireUndoRedoChangeEvent(); fireUndoRedoChangeEvent();
} }
@Override @Override
public void componentChanged(ComponentChangeEvent e) { public void componentChanged(ComponentChangeEvent e) {
if (!e.isUndoChange()) { if (!e.isUndoChange()) {
if (undoPosition < undoHistory.size() - 1) { if (undoPosition < undoHistory.size() - 1) {
log.info("Rocket changed while in undo history, removing redo information for " + this + log.info("Rocket changed while in undo history, removing redo information for " + this +
@ -640,7 +641,7 @@ public class OpenRocketDocument implements ComponentChangeListener, StateChangeL
removeRedoInfo(); removeRedoInfo();
setLatestDescription(); setLatestDescription();
} }
fireUndoRedoChangeEvent(); fireUndoRedoChangeEvent();
fireDocumentChangeEvent(new DocumentChangeEvent(e.getSource())); fireDocumentChangeEvent(new DocumentChangeEvent(e.getSource()));
} }
@ -667,8 +668,8 @@ public class OpenRocketDocument implements ComponentChangeListener, StateChangeL
undoDescription.removeLast(); undoDescription.removeLast();
} }
} }
/** /**
* Return whether undo action is available. * Return whether undo action is available.
* @return <code>true</code> if undo can be performed * @return <code>true</code> if undo can be performed
@ -676,10 +677,10 @@ public class OpenRocketDocument implements ComponentChangeListener, StateChangeL
public boolean isUndoAvailable() { public boolean isUndoAvailable() {
if (undoPosition > 0) if (undoPosition > 0)
return true; return true;
return !isCleanState(); return !isCleanState();
} }
/** /**
* Return the description of what action would be undone if undo is called. * Return the description of what action would be undone if undo is called.
* @return the description what would be undone, or <code>null</code> if description unavailable. * @return the description what would be undone, or <code>null</code> if description unavailable.
@ -687,15 +688,15 @@ public class OpenRocketDocument implements ComponentChangeListener, StateChangeL
public String getUndoDescription() { public String getUndoDescription() {
if (!isUndoAvailable()) if (!isUndoAvailable())
return null; return null;
if (isCleanState()) { if (isCleanState()) {
return undoDescription.get(undoPosition - 1); return undoDescription.get(undoPosition - 1);
} else { } else {
return undoDescription.get(undoPosition); return undoDescription.get(undoPosition);
} }
} }
/** /**
* Return whether redo action is available. * Return whether redo action is available.
* @return <code>true</code> if redo can be performed * @return <code>true</code> if redo can be performed
@ -703,7 +704,7 @@ public class OpenRocketDocument implements ComponentChangeListener, StateChangeL
public boolean isRedoAvailable() { public boolean isRedoAvailable() {
return undoPosition < undoHistory.size() - 1; return undoPosition < undoHistory.size() - 1;
} }
/** /**
* Return the description of what action would be redone if redo is called. * Return the description of what action would be redone if redo is called.
* @return the description of what would be redone, or <code>null</code> if description unavailable. * @return the description of what would be redone, or <code>null</code> if description unavailable.
@ -711,11 +712,11 @@ public class OpenRocketDocument implements ComponentChangeListener, StateChangeL
public String getRedoDescription() { public String getRedoDescription() {
if (!isRedoAvailable()) if (!isRedoAvailable())
return null; return null;
return undoDescription.get(undoPosition); return undoDescription.get(undoPosition);
} }
/** /**
* Perform undo operation on the rocket. * Perform undo operation on the rocket.
*/ */
@ -730,9 +731,9 @@ public class OpenRocketDocument implements ComponentChangeListener, StateChangeL
if (storedDescription != null) { if (storedDescription != null) {
logUndoError("undo() called with storedDescription=" + storedDescription); logUndoError("undo() called with storedDescription=" + storedDescription);
} }
// Update history position // Update history position
if (isCleanState()) { if (isCleanState()) {
// We are in a clean state, simply move backwards in history // We are in a clean state, simply move backwards in history
undoPosition--; undoPosition--;
@ -744,13 +745,13 @@ public class OpenRocketDocument implements ComponentChangeListener, StateChangeL
undoHistory.add(rocket.copyWithOriginalID()); undoHistory.add(rocket.copyWithOriginalID());
undoDescription.add(null); undoDescription.add(null);
} }
rocket.checkComponentStructure(); rocket.checkComponentStructure();
rocket.loadFrom(undoHistory.get(undoPosition)); rocket.loadFrom(undoHistory.get(undoPosition));
rocket.checkComponentStructure(); rocket.checkComponentStructure();
} }
/** /**
* Perform redo operation on the rocket. * Perform redo operation on the rocket.
*/ */
@ -765,20 +766,20 @@ public class OpenRocketDocument implements ComponentChangeListener, StateChangeL
if (storedDescription != null) { if (storedDescription != null) {
logUndoError("redo() called with storedDescription=" + storedDescription); logUndoError("redo() called with storedDescription=" + storedDescription);
} }
undoPosition++; undoPosition++;
rocket.loadFrom(undoHistory.get(undoPosition).copyWithOriginalID()); rocket.loadFrom(undoHistory.get(undoPosition).copyWithOriginalID());
} }
private boolean isCleanState() { private boolean isCleanState() {
return rocket.getModID() == undoHistory.get(undoPosition).getModID(); return rocket.getModID() == undoHistory.get(undoPosition).getModID();
} }
/** /**
* Log a non-fatal undo/redo error or inconsistency. Reports it to the user the first * Log a non-fatal undo/redo error or inconsistency. Reports it to the user the first
* time it occurs, but not on subsequent times. Logs automatically the undo system state. * time it occurs, but not on subsequent times. Logs automatically the undo system state.
*/ */
private void logUndoError(String error) { private void logUndoError(String error) {
@ -786,64 +787,64 @@ public class OpenRocketDocument implements ComponentChangeListener, StateChangeL
" undoHistory.size=" + undoHistory.size() + " isClean=" + isCleanState() + " undoHistory.size=" + undoHistory.size() + " isClean=" + isCleanState() +
" nextDescription=" + nextDescription + " storedDescription=" + storedDescription, " nextDescription=" + nextDescription + " storedDescription=" + storedDescription,
new Throwable()); new Throwable());
if (!undoErrorReported) { if (!undoErrorReported) {
undoErrorReported = true; undoErrorReported = true;
Application.getExceptionHandler().handleErrorCondition("Undo/Redo error: " + error); Application.getExceptionHandler().handleErrorCondition("Undo/Redo error: " + error);
} }
} }
/** /**
* Return a copy of this document. The rocket is copied with original ID's, the default * Return a copy of this document. The rocket is copied with original ID's, the default
* motor configuration ID is maintained and the simulations are copied to the new rocket. * motor configuration ID is maintained and the simulations are copied to the new rocket.
* No undo/redo information or file storage information is maintained. * No undo/redo information or file storage information is maintained.
* *
* This function is used from the Optimization routine to store alternatives of the same rocket. * This function is used from the Optimization routine to store alternatives of the same rocket.
* For now we can assume that the copy returned does not have any of the attachment factories in place. * For now we can assume that the copy returned does not have any of the attachment factories in place.
* *
* @return a copy of this document. * @return a copy of this document.
*/ */
public OpenRocketDocument copy() { public OpenRocketDocument copy() {
Rocket rocketCopy = rocket.copyWithOriginalID(); Rocket rocketCopy = rocket.copyWithOriginalID();
OpenRocketDocument documentCopy = OpenRocketDocumentFactory.createDocumentFromRocket(rocketCopy); OpenRocketDocument documentCopy = OpenRocketDocumentFactory.createDocumentFromRocket(rocketCopy);
for (Simulation s : simulations) { for (Simulation s : simulations) {
documentCopy.addSimulation(s.duplicateSimulation(rocketCopy)); documentCopy.addSimulation(s.duplicateSimulation(rocketCopy));
} }
return documentCopy; return documentCopy;
} }
/////// Listeners /////// Listeners
public void addUndoRedoListener(UndoRedoListener listener) { public void addUndoRedoListener(UndoRedoListener listener) {
undoRedoListeners.add(listener); undoRedoListeners.add(listener);
} }
public void removeUndoRedoListener(UndoRedoListener listener) { public void removeUndoRedoListener(UndoRedoListener listener) {
undoRedoListeners.remove(listener); undoRedoListeners.remove(listener);
} }
private void fireUndoRedoChangeEvent() { private void fireUndoRedoChangeEvent() {
UndoRedoListener[] array = undoRedoListeners.toArray(new UndoRedoListener[0]); UndoRedoListener[] array = undoRedoListeners.toArray(new UndoRedoListener[0]);
for (UndoRedoListener l : array) { for (UndoRedoListener l : array) {
l.setAllValues(); l.setAllValues();
} }
} }
public void addDocumentChangeListener(DocumentChangeListener listener) { public void addDocumentChangeListener(DocumentChangeListener listener) {
listeners.add(listener); listeners.add(listener);
} }
public void removeDocumentChangeListener(DocumentChangeListener listener) { public void removeDocumentChangeListener(DocumentChangeListener listener) {
listeners.remove(listener); listeners.remove(listener);
} }
public void fireDocumentChangeEvent(DocumentChangeEvent event) { public void fireDocumentChangeEvent(DocumentChangeEvent event) {
DocumentChangeListener[] array = listeners.toArray(new DocumentChangeListener[0]); DocumentChangeListener[] array = listeners.toArray(new DocumentChangeListener[0]);
for (DocumentChangeListener l : array) { for (DocumentChangeListener l : array) {
@ -857,16 +858,16 @@ public class OpenRocketDocument implements ComponentChangeListener, StateChangeL
l.documentSaving(event); l.documentSaving(event);
} }
} }
public String toSimulationDetail(){ public String toSimulationDetail(){
StringBuilder str = new StringBuilder(); StringBuilder str = new StringBuilder();
str.append(">> Dumping simulation list:\n"); str.append(">> Dumping simulation list:\n");
int simNum = 0; int simNum = 0;
for( Simulation s : this.simulations ){ for( Simulation s : this.simulations ){
str.append(String.format(" [%d] %s (%s) \n", simNum, s.getName(), s.getId().toShortKey() )); str.append(String.format(" [%d] %s (%s) \n", simNum, s.getName(), s.getId().toShortKey() ));
simNum++; simNum++;
} }
return str.toString(); return str.toString();
} }
@ -881,4 +882,21 @@ public class OpenRocketDocument implements ComponentChangeListener, StateChangeL
public DocumentPreferences getDocumentPreferences() { public DocumentPreferences getDocumentPreferences() {
return docPrefs; return docPrefs;
} }
/**
* Load all materials that are user-defined and document materials to the document material database.
*/
public void reloadDocumentMaterials() {
for (RocketComponent c : getRocket()) {
List<Material> materials = c.getAllMaterials();
if (materials == null) {
continue;
}
for (Material m : materials) {
if (m.isUserDefined() && m.isDocumentMaterial()) {
getDocumentPreferences().addMaterial(m);
}
}
}
}
} }

View File

@ -246,23 +246,6 @@ public class GeneralRocketLoader {
} }
} }
/**
* Load all materials that are user-defined and document materials to the document material database.
*/
private void loadMaterialsToDocument() {
for (RocketComponent c : doc.getRocket()) {
List<Material> materials = c.getAllMaterials();
if (materials == null) {
continue;
}
for (Material m : materials) {
if (m.isUserDefined() && m.isDocumentMaterial()) {
doc.getDocumentPreferences().addMaterial(m);
}
}
}
}
private void loadUsing(RocketLoader loader, InputStream source, String fileName) throws RocketLoadException { private void loadUsing(RocketLoader loader, InputStream source, String fileName) throws RocketLoadException {
warnings.clear(); warnings.clear();
DocumentLoadingContext context = new DocumentLoadingContext(); DocumentLoadingContext context = new DocumentLoadingContext();
@ -273,6 +256,6 @@ public class GeneralRocketLoader {
warnings.addAll(loader.getWarnings()); warnings.addAll(loader.getWarnings());
// Check for custom materials that need to be added to the document material database // Check for custom materials that need to be added to the document material database
loadMaterialsToDocument(); doc.reloadDocumentMaterials();
} }
} }