diff --git a/core/resources/l10n/messages.properties b/core/resources/l10n/messages.properties
index 8d6457153..f15466ed8 100644
--- a/core/resources/l10n/messages.properties
+++ b/core/resources/l10n/messages.properties
@@ -1361,6 +1361,15 @@ RecoveryDevice.DeployEvent.CURRENT_STAGE_SEPARATION = Current stage separation
RecoveryDevice.DeployEvent.LOWER_STAGE_SEPARATION = Lower stage separation
RecoveryDevice.DeployEvent.NEVER = Never
+RecoveryDevice.DeployEvent.short.LAUNCH = Launch
+RecoveryDevice.DeployEvent.short.EJECTION = Ejection charge
+RecoveryDevice.DeployEvent.short.APOGEE = Apogee
+RecoveryDevice.DeployEvent.short.ALTITUDE = Altitude
+RecoveryDevice.DeployEvent.short.CURRENT_STAGE_SEPARATION = Current stage separation
+RecoveryDevice.DeployEvent.short.LOWER_STAGE_SEPARATION = Lower stage separation
+RecoveryDevice.DeployEvent.short.NEVER = Never
+
+
! FlightEvent
FlightEvent.Type.LAUNCH = Launch
FlightEvent.Type.IGNITION = Motor ignition
@@ -1828,7 +1837,21 @@ MotorConfigurationPanel.btn.selectIgnition = Select ignition
MotorConfigurationPanel.btn.resetIgnition = Reset ignition
MotorConfigurationTableModel.table.ignition.default = Default ({0})
+RecoveryConfigurationPanel.table.deployment.default = Default ({0})
+SeparationConfigurationPanel.table.separation.default = Default ({0})
+IgnitionSelectionDialog.opt.title = Which flight configurations are affected:
+IgnitionSelectionDialog.opt.default = Change the default ignition event for this motor
+IgnitionSelectionDialog.opt.override = Override for the {0} flight configuration only
+
+DeploymentSelectionDialog.opt.title = Which flight configurations are affected:
+DeploymentSelectionDialog.opt.default = Change the default deployment event for this recovery device
+DeploymentSelectionDialog.opt.override = Override for the {0} flight configuration only
+
+SeparationSelectionDialog.lbl.separation = Stage separation at:
+SeparationSelectionDialog.opt.title = Which flight configurations are affected:
+SeparationSelectionDialog.opt.default = Change the default separation event for this stage
+SeparationSelectionDialog.opt.override = Override for the {0} flight configuration only
MotorConfigurationPanel.description = Select the motors and motor ignition events of your rocket.
Motor mounts: Select which components function as motor mounts.
Motor configurations: Select the motor and ignition event for each motor mount.
diff --git a/core/src/net/sf/openrocket/appearance/defaults/ResourceDecalImage.java b/core/src/net/sf/openrocket/appearance/defaults/ResourceDecalImage.java
index bea3b8d76..1110cd6d0 100644
--- a/core/src/net/sf/openrocket/appearance/defaults/ResourceDecalImage.java
+++ b/core/src/net/sf/openrocket/appearance/defaults/ResourceDecalImage.java
@@ -4,9 +4,9 @@ import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
-import java.util.EventListener;
import net.sf.openrocket.appearance.DecalImage;
+import net.sf.openrocket.util.StateChangeListener;
class ResourceDecalImage implements DecalImage {
@@ -38,12 +38,12 @@ class ResourceDecalImage implements DecalImage {
}
@Override
- public void addChangeListener(EventListener listener) {
+ public void addChangeListener(StateChangeListener listener) {
//Unimplemented, this can not change
}
@Override
- public void removeChangeListener(EventListener listener) {
+ public void removeChangeListener(StateChangeListener listener) {
//Unimplemented, this can not change
}
diff --git a/core/src/net/sf/openrocket/file/GeneralRocketSaver.java b/core/src/net/sf/openrocket/file/GeneralRocketSaver.java
index 61644ac53..877435ab2 100644
--- a/core/src/net/sf/openrocket/file/GeneralRocketSaver.java
+++ b/core/src/net/sf/openrocket/file/GeneralRocketSaver.java
@@ -24,13 +24,13 @@ import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.util.MathUtil;
public class GeneralRocketSaver {
-
+
/**
* Interface which can be implemented by the caller to receive progress information.
*
*/
public interface SavingProgress {
-
+
/**
* Inform the callback of the current progress.
* It is guaranteed that the value will be an integer between 0 and 100 representing
@@ -40,10 +40,10 @@ public class GeneralRocketSaver {
*
* @param progress int value between 0 and 100 representing percent complete.
*/
- public void setProgress( int progress );
-
+ public void setProgress(int progress);
+
}
-
+
/**
* Save the document to the specified file using the default storage options.
*
@@ -54,7 +54,7 @@ public class GeneralRocketSaver {
public final void save(File dest, OpenRocketDocument document) throws IOException {
save(dest, document, document.getDefaultStorageOptions());
}
-
+
/**
* Save the document to the specified file using the given storage options.
*
@@ -64,9 +64,9 @@ public class GeneralRocketSaver {
* @throws IOException in case of an I/O error.
*/
public final void save(File dest, OpenRocketDocument document, StorageOptions options) throws IOException {
- save( dest, document, options, null );
+ save(dest, document, options, null);
}
-
+
/**
* Save the document to a file with default StorageOptions and a SavingProgress callback object.
*
@@ -75,10 +75,10 @@ public class GeneralRocketSaver {
* @param progress a SavingProgress object used to provide progress information
* @throws IOException in case of an I/O error.
*/
- public final void save(File dest, OpenRocketDocument doc, SavingProgress progress ) throws IOException {
- save( dest, doc, doc.getDefaultStorageOptions(), progress );
+ public final void save(File dest, OpenRocketDocument doc, SavingProgress progress) throws IOException {
+ save(dest, doc, doc.getDefaultStorageOptions(), progress);
}
-
+
/**
* Save the document to a file with the given StorageOptions and a SavingProgress callback object.
*
@@ -88,40 +88,40 @@ public class GeneralRocketSaver {
* @param progress a SavingProgress object used to provide progress information
* @throws IOException in case of an I/O error.
*/
- public final void save(File dest, OpenRocketDocument doc, StorageOptions opts, SavingProgress progress ) throws IOException {
-
+ public final void save(File dest, OpenRocketDocument doc, StorageOptions opts, SavingProgress progress) throws IOException {
+
// This method is the core operational method. It saves the document into a new (hopefully unique)
// file, then if the save is successful, it will copy the file over the old one.
// Write to a temporary file in the same directory as the specified file.
- File temporaryNewFile = File.createTempFile("ORSave", ".tmp", dest.getParentFile() );
+ File temporaryNewFile = File.createTempFile("ORSave", ".tmp", dest.getParentFile());
- OutputStream s = new BufferedOutputStream( new FileOutputStream(temporaryNewFile));
+ OutputStream s = new BufferedOutputStream(new FileOutputStream(temporaryNewFile));
- if ( progress != null ) {
+ if (progress != null) {
long estimatedSize = this.estimateFileSize(doc, opts);
- s = new ProgressOutputStream( s, estimatedSize, progress );
+ s = new ProgressOutputStream(s, estimatedSize, progress);
}
try {
save(dest.getName(), s, doc, opts);
} finally {
s.close();
}
-
+
// Move the temporary new file over the specified file.
boolean destExists = dest.exists();
- File oldBackupFile = new File( dest.getParentFile(), dest.getName() + "-bak");
+ File oldBackupFile = new File(dest.getParentFile(), dest.getName() + "-bak");
- if ( destExists ) {
+ if (destExists) {
dest.renameTo(oldBackupFile);
}
// since we created the temporary new file in the same directory as the dest file,
// it is on the same filesystem, so File.renameTo will work just fine.
boolean success = temporaryNewFile.renameTo(dest);
- if ( success ) {
- if ( destExists ) {
+ if (success) {
+ if (destExists) {
oldBackupFile.delete();
}
}
@@ -137,138 +137,138 @@ public class GeneralRocketSaver {
* @return the estimated number of bytes the storage would take.
*/
public long estimateFileSize(OpenRocketDocument doc, StorageOptions options) {
- if ( options.getFileType() == StorageOptions.FileType.ROCKSIM ) {
+ if (options.getFileType() == StorageOptions.FileType.ROCKSIM) {
return new RocksimSaver().estimateFileSize(doc, options);
} else {
- return new OpenRocketSaver().estimateFileSize(doc,options);
+ return new OpenRocketSaver().estimateFileSize(doc, options);
}
}
-
- private void save(String fileName, OutputStream output, OpenRocketDocument document, StorageOptions options) throws IOException {
-
+
+ private void save(String fileName, OutputStream output, OpenRocketDocument document, StorageOptions options) throws IOException {
+
// For now, we don't save decal inforamtion in ROCKSIM files, so don't do anything
// which follows.
// TODO - add support for decals in ROCKSIM files?
- if ( options.getFileType() == FileType.ROCKSIM ) {
+ if (options.getFileType() == FileType.ROCKSIM) {
saveInternal(output, document, options);
output.close();
return;
}
-
+
Set usedDecals = new TreeSet();
// Look for all decals used in the rocket.
- for( RocketComponent c : document.getRocket() ) {
- if ( c.getAppearance() == null ) {
+ for (RocketComponent c : document.getRocket()) {
+ if (c.getAppearance() == null) {
continue;
}
Appearance ap = c.getAppearance();
- if ( ap.getTexture() == null ) {
+ if (ap.getTexture() == null) {
continue;
}
-
+
Decal decal = ap.getTexture();
-
+
usedDecals.add(decal.getImage());
}
-
- saveAllPartsZipFile(fileName, output, document, options, usedDecals);
+
+ saveAllPartsZipFile(output, document, options, usedDecals);
}
- public void saveAllPartsZipFile(String fileName, OutputStream output, OpenRocketDocument document, StorageOptions options, Set decals) throws IOException {
+ public void saveAllPartsZipFile(OutputStream output, OpenRocketDocument document, StorageOptions options, Set decals) throws IOException {
// Open a zip stream to write to.
ZipOutputStream zos = new ZipOutputStream(output);
zos.setLevel(9);
// big try block to close the zos.
try {
-
-
- ZipEntry mainFile = new ZipEntry(fileName);
+
+
+ ZipEntry mainFile = new ZipEntry("rocket.ork");
zos.putNextEntry(mainFile);
- saveInternal(zos,document,options);
+ saveInternal(zos, document, options);
zos.closeEntry();
-
+
// Now we write out all the decal images files.
-
- for( DecalImage image : decals ) {
-
+
+ for (DecalImage image : decals) {
+
String name = image.getName();
ZipEntry decal = new ZipEntry(name);
zos.putNextEntry(decal);
-
+
InputStream is = image.getBytes();
int bytesRead = 0;
byte[] buffer = new byte[2048];
- while( (bytesRead = is.read(buffer)) > 0 ) {
+ while ((bytesRead = is.read(buffer)) > 0) {
zos.write(buffer, 0, bytesRead);
}
zos.closeEntry();
}
-
+
zos.flush();
} finally {
zos.close();
}
-
-
+
+
}
-
+
// package scope for testing.
-
+
private void saveInternal(OutputStream output, OpenRocketDocument document, StorageOptions options)
throws IOException {
-
- if ( options.getFileType() == StorageOptions.FileType.ROCKSIM ) {
+
+ if (options.getFileType() == StorageOptions.FileType.ROCKSIM) {
new RocksimSaver().save(output, document, options);
} else {
new OpenRocketSaver().save(output, document, options);
}
}
-
+
private static class ProgressOutputStream extends FilterOutputStream {
-
+
private long estimatedSize;
private long bytesWritten = 0;
private SavingProgress progressCallback;
-
- ProgressOutputStream( OutputStream ostream, long estimatedSize, SavingProgress progressCallback ) {
+
+ ProgressOutputStream(OutputStream ostream, long estimatedSize, SavingProgress progressCallback) {
super(ostream);
this.estimatedSize = estimatedSize;
this.progressCallback = progressCallback;
}
-
+
@Override
public void write(int b) throws IOException {
super.write(b);
bytesWritten++;
updateProgress();
}
-
+
@Override
public void write(byte[] b) throws IOException {
super.write(b);
bytesWritten += b.length;
updateProgress();
}
-
+
@Override
public void write(byte[] b, int off, int len) throws IOException {
super.write(b, off, len);
bytesWritten += len;
updateProgress();
}
-
+
private void updateProgress() {
if (progressCallback != null) {
int p = 50;
- if ( estimatedSize > 0 ) {
- p = (int) Math.floor( bytesWritten * 100.0 / estimatedSize );
+ if (estimatedSize > 0) {
+ p = (int) Math.floor(bytesWritten * 100.0 / estimatedSize);
p = MathUtil.clamp(p, 0, 100);
}
progressCallback.setProgress(p);
}
}
-
+
}
}
diff --git a/core/src/net/sf/openrocket/file/RocketSaver.java b/core/src/net/sf/openrocket/file/RocketSaver.java
index 30b13cd62..b731c7f75 100644
--- a/core/src/net/sf/openrocket/file/RocketSaver.java
+++ b/core/src/net/sf/openrocket/file/RocketSaver.java
@@ -40,22 +40,4 @@ public abstract class RocketSaver {
* @return the estimated number of bytes the storage would take.
*/
public abstract long estimateFileSize(OpenRocketDocument doc, StorageOptions options);
-
- public static String escapeXML(String s) {
-
- s = s.replace("&", "&");
- s = s.replace("<", "<");
- s = s.replace(">", ">");
- s = s.replace("\"",""");
- s = s.replace("'", "'");
-
- for (int i=0; i < s.length(); i++) {
- char n = s.charAt(i);
- if (((n < 32) && (n != 9) && (n != 10) && (n != 13)) || (n == 127)) {
- s = s.substring(0,i) + "" + ((int)n) + ";" + s.substring(i+1);
- }
- }
-
- return s;
- }
}
diff --git a/core/src/net/sf/openrocket/file/openrocket/OpenRocketSaver.java b/core/src/net/sf/openrocket/file/openrocket/OpenRocketSaver.java
index 3c9b01c86..479341684 100644
--- a/core/src/net/sf/openrocket/file/openrocket/OpenRocketSaver.java
+++ b/core/src/net/sf/openrocket/file/openrocket/OpenRocketSaver.java
@@ -354,7 +354,7 @@ public class OpenRocketSaver extends RocketSaver {
writeln("");
indent++;
- writeln("" + escapeXML(simulation.getName()) + "");
+ writeln("" + TextUtil.escapeXML(simulation.getName()) + "");
// TODO: MEDIUM: Other simulators/calculators
writeln("RK4Simulator");
@@ -392,7 +392,7 @@ public class OpenRocketSaver extends RocketSaver {
for (String s : simulation.getSimulationListeners()) {
- writeElement("listener", escapeXML(s));
+ writeElement("listener", TextUtil.escapeXML(s));
}
// Write basic simulation data
@@ -423,7 +423,7 @@ public class OpenRocketSaver extends RocketSaver {
indent++;
for (Warning w : data.getWarningSet()) {
- writeElement("warning", escapeXML(w.toString()));
+ writeElement("warning", TextUtil.escapeXML(w.toString()));
}
// Check whether to store data
@@ -471,7 +471,7 @@ public class OpenRocketSaver extends RocketSaver {
// Build the tag
StringBuilder sb = new StringBuilder();
sb.append(" 0)
sb.append(",");
- sb.append(escapeXML(types[i].getName()));
+ sb.append(TextUtil.escapeXML(types[i].getName()));
}
sb.append("\">");
writeln(sb.toString());
diff --git a/core/src/net/sf/openrocket/file/openrocket/importt/DeploymentConfigurationHandler.java b/core/src/net/sf/openrocket/file/openrocket/importt/DeploymentConfigurationHandler.java
index 3c5863bef..e40992bbb 100644
--- a/core/src/net/sf/openrocket/file/openrocket/importt/DeploymentConfigurationHandler.java
+++ b/core/src/net/sf/openrocket/file/openrocket/importt/DeploymentConfigurationHandler.java
@@ -15,49 +15,66 @@ import net.sf.openrocket.rocketcomponent.RecoveryDevice;
import org.xml.sax.SAXException;
class DeploymentConfigurationHandler extends AbstractElementHandler {
+
private final RecoveryDevice recoveryDevice;
- private DeploymentConfiguration config;
-
- public DeploymentConfigurationHandler( RecoveryDevice recoveryDevice, DocumentLoadingContext context ) {
- this.recoveryDevice = recoveryDevice;
- config = new DeploymentConfiguration();
+
+ private DeployEvent event = null;
+ private double delay = Double.NaN;
+ private double altitude = Double.NaN;
+
+ public DeploymentConfigurationHandler(RecoveryDevice component, DocumentLoadingContext context) {
+ this.recoveryDevice = component;
}
-
+
+ public DeploymentConfiguration getConfiguration(DeploymentConfiguration def) {
+ DeploymentConfiguration config = def.clone();
+ if (event != null) {
+ config.setDeployEvent(event);
+ }
+ if (!Double.isNaN(delay)) {
+ config.setDeployDelay(delay);
+ }
+ if (!Double.isNaN(altitude)) {
+ config.setDeployAltitude(altitude);
+ }
+ return config;
+ }
+
@Override
public ElementHandler openElement(String element, HashMap attributes, WarningSet warnings)
throws SAXException {
return PlainTextHandler.INSTANCE;
}
-
+
@Override
public void closeElement(String element, HashMap attributes, String content,
WarningSet warnings) throws SAXException {
content = content.trim();
- if ( "deployevent".equals(element) ) {
- DeployEvent type = (DeployEvent) DocumentConfig.findEnum(content, DeployEvent.class);
- if ( type == null ) {
+ if ("deployevent".equals(element)) {
+ event = (DeployEvent) DocumentConfig.findEnum(content, DeployEvent.class);
+ if (event == null) {
warnings.add(Warning.FILE_INVALID_PARAMETER);
return;
}
- config.setDeployEvent( type );
return;
- } else if ( "deployaltitude".equals(element) ) {
- config.setDeployAltitude( Double.parseDouble(content));
+ } else if ("deploydelay".equals(element)) {
+ delay = parseDouble(content, warnings, Warning.FILE_INVALID_PARAMETER);
return;
- } else if ( "deploydelay".equals(element) ) {
- config.setDeployDelay( Double.parseDouble(content));
+ } else if ("deployaltitude".equals(element)) {
+ altitude = parseDouble(content, warnings, Warning.FILE_INVALID_PARAMETER);
return;
}
super.closeElement(element, attributes, content, warnings);
-
+
}
-
+
@Override
public void endHandler(String element, HashMap attributes, String content, WarningSet warnings) throws SAXException {
String configId = attributes.get("configid");
- recoveryDevice.setFlightConfiguration(configId, config);
+ DeploymentConfiguration def = recoveryDevice.getDeploymentConfiguration().getDefault();
+ recoveryDevice.getDeploymentConfiguration().set(configId, getConfiguration(def));
}
}
\ No newline at end of file
diff --git a/core/src/net/sf/openrocket/file/openrocket/importt/DocumentConfig.java b/core/src/net/sf/openrocket/file/openrocket/importt/DocumentConfig.java
index dbf897a5c..dc14486d0 100644
--- a/core/src/net/sf/openrocket/file/openrocket/importt/DocumentConfig.java
+++ b/core/src/net/sf/openrocket/file/openrocket/importt/DocumentConfig.java
@@ -10,6 +10,7 @@ import net.sf.openrocket.rocketcomponent.BodyComponent;
import net.sf.openrocket.rocketcomponent.BodyTube;
import net.sf.openrocket.rocketcomponent.Bulkhead;
import net.sf.openrocket.rocketcomponent.CenteringRing;
+import net.sf.openrocket.rocketcomponent.DeploymentConfiguration;
import net.sf.openrocket.rocketcomponent.DeploymentConfiguration.DeployEvent;
import net.sf.openrocket.rocketcomponent.EllipticalFinSet;
import net.sf.openrocket.rocketcomponent.EngineBlock;
@@ -47,7 +48,7 @@ import net.sf.openrocket.util.Reflection;
class DocumentConfig {
/* Remember to update OpenRocketSaver as well! */
- public static final String[] SUPPORTED_VERSIONS = { "1.0", "1.1", "1.2", "1.3", "1.4", "1.5", "1.6"};
+ public static final String[] SUPPORTED_VERSIONS = { "1.0", "1.1", "1.2", "1.3", "1.4", "1.5", "1.6" };
/**
* Divisor used in converting an integer version to the point-represented version.
@@ -327,12 +328,15 @@ class DocumentConfig {
"auto",
Reflection.findMethod(RecoveryDevice.class, "setCDAutomatic", boolean.class)));
setters.put("RecoveryDevice:deployevent", new EnumSetter(
- Reflection.findMethod(RecoveryDevice.class, "setDefaultDeployEvent", DeployEvent.class),
+ Reflection.findMethod(RecoveryDevice.class, "getDeploymentConfiguration"),
+ Reflection.findMethod(DeploymentConfiguration.class, "setDeployEvent", DeployEvent.class),
DeployEvent.class));
setters.put("RecoveryDevice:deployaltitude", new DoubleSetter(
- Reflection.findMethod(RecoveryDevice.class, "setDefaultDeployAltitude", double.class)));
+ Reflection.findMethod(RecoveryDevice.class, "getDeploymentConfiguration"),
+ Reflection.findMethod(DeploymentConfiguration.class, "setDeployAltitude", double.class)));
setters.put("RecoveryDevice:deploydelay", new DoubleSetter(
- Reflection.findMethod(RecoveryDevice.class, "setDefaultDeployDelay", double.class)));
+ Reflection.findMethod(RecoveryDevice.class, "getDeploymentConfiguration"),
+ Reflection.findMethod(DeploymentConfiguration.class, "setDeployDelay", double.class)));
setters.put("RecoveryDevice:material", new MaterialSetter(
Reflection.findMethod(RecoveryDevice.class, "setMaterial", Material.class),
Material.Type.SURFACE));
@@ -368,10 +372,12 @@ class DocumentConfig {
// Stage
setters.put("Stage:separationevent", new EnumSetter(
- Reflection.findMethod(Stage.class, "setDefaultSeparationEvent", StageSeparationConfiguration.SeparationEvent.class),
+ Reflection.findMethod(Stage.class, "getStageSeparationConfiguration"),
+ Reflection.findMethod(StageSeparationConfiguration.class, "setSeparationEvent", StageSeparationConfiguration.SeparationEvent.class),
StageSeparationConfiguration.SeparationEvent.class));
setters.put("Stage:separationdelay", new DoubleSetter(
- Reflection.findMethod(Stage.class, "setDefaultSeparationDelay", double.class)));
+ Reflection.findMethod(Stage.class, "getStageSeparationConfiguration"),
+ Reflection.findMethod(StageSeparationConfiguration.class, "setSeparationDelay", double.class)));
}
diff --git a/core/src/net/sf/openrocket/file/openrocket/importt/DoubleSetter.java b/core/src/net/sf/openrocket/file/openrocket/importt/DoubleSetter.java
index a7a50b9b2..9fdd3e9f3 100644
--- a/core/src/net/sf/openrocket/file/openrocket/importt/DoubleSetter.java
+++ b/core/src/net/sf/openrocket/file/openrocket/importt/DoubleSetter.java
@@ -4,12 +4,15 @@ import java.util.HashMap;
import net.sf.openrocket.aerodynamics.Warning;
import net.sf.openrocket.aerodynamics.WarningSet;
+import net.sf.openrocket.rocketcomponent.FlightConfiguration;
import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.util.Reflection;
+import net.sf.openrocket.util.Reflection.Method;
//// DoubleSetter - sets a double value or (alternatively) if a specific string is encountered
//// calls a setXXX(boolean) method.
class DoubleSetter implements Setter {
+ private final Reflection.Method configGetter;
private final Reflection.Method setMethod;
private final String specialString;
private final Reflection.Method specialMethod;
@@ -21,6 +24,7 @@ class DoubleSetter implements Setter {
*/
public DoubleSetter(Reflection.Method set) {
this.setMethod = set;
+ this.configGetter = null;
this.specialString = null;
this.specialMethod = null;
this.multiplier = 1.0;
@@ -33,6 +37,7 @@ class DoubleSetter implements Setter {
*/
public DoubleSetter(Reflection.Method set, double mul) {
this.setMethod = set;
+ this.configGetter = null;
this.specialString = null;
this.specialMethod = null;
this.multiplier = mul;
@@ -49,12 +54,27 @@ class DoubleSetter implements Setter {
public DoubleSetter(Reflection.Method set, String special,
Reflection.Method specialMethod) {
this.setMethod = set;
+ this.configGetter = null;
this.specialString = special;
this.specialMethod = specialMethod;
this.multiplier = 1.0;
}
+ /**
+ * Set a double value of the default configuration of a FlightConfiguration object.
+ *
+ * @param configGetter getter method for the FlightConfiguration object
+ * @param setter setter method for the configuration object
+ */
+ public DoubleSetter(Method configGetter, Method setter) {
+ this.setMethod = setter;
+ this.configGetter = configGetter;
+ this.specialString = null;
+ this.specialMethod = null;
+ this.multiplier = 1.0;
+ }
+
@Override
public void set(RocketComponent c, String s, HashMap attributes,
WarningSet warnings) {
@@ -70,7 +90,14 @@ class DoubleSetter implements Setter {
// Normal case
try {
double d = Double.parseDouble(s);
- setMethod.invoke(c, d * multiplier);
+
+ if (configGetter == null) {
+ setMethod.invoke(c, d * multiplier);
+ } else {
+ FlightConfiguration> config = (FlightConfiguration>) configGetter.invoke(c);
+ Object obj = config.getDefault();
+ setMethod.invoke(obj, d * multiplier);
+ }
} catch (NumberFormatException e) {
warnings.add(Warning.FILE_INVALID_PARAMETER);
}
diff --git a/core/src/net/sf/openrocket/file/openrocket/importt/EnumSetter.java b/core/src/net/sf/openrocket/file/openrocket/importt/EnumSetter.java
index 8b93becbd..55ceaac34 100644
--- a/core/src/net/sf/openrocket/file/openrocket/importt/EnumSetter.java
+++ b/core/src/net/sf/openrocket/file/openrocket/importt/EnumSetter.java
@@ -4,16 +4,24 @@ import java.util.HashMap;
import net.sf.openrocket.aerodynamics.Warning;
import net.sf.openrocket.aerodynamics.WarningSet;
+import net.sf.openrocket.rocketcomponent.FlightConfiguration;
import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.util.Reflection;
+import net.sf.openrocket.util.Reflection.Method;
//// EnumSetter - sets a generic enum type
class EnumSetter> implements Setter {
+ private final Reflection.Method configurationGetter;
private final Reflection.Method setter;
private final Class enumClass;
- public EnumSetter(Reflection.Method set, Class enumClass) {
- this.setter = set;
+ public EnumSetter(Reflection.Method setter, Class enumClass) {
+ this(null, setter, enumClass);
+ }
+
+ public EnumSetter(Method configurationGetter, Method setter, Class enumClass) {
+ this.configurationGetter = configurationGetter;
+ this.setter = setter;
this.enumClass = enumClass;
}
@@ -27,6 +35,12 @@ class EnumSetter> implements Setter {
return;
}
- setter.invoke(c, setEnum);
+ if (configurationGetter == null) {
+ setter.invoke(c, setEnum);
+ } else {
+ FlightConfiguration> config = (FlightConfiguration>) configurationGetter.invoke(c);
+ Object obj = config.getDefault();
+ setter.invoke(obj, setEnum);
+ }
}
}
\ No newline at end of file
diff --git a/core/src/net/sf/openrocket/file/openrocket/importt/IgnitionConfigurationHandler.java b/core/src/net/sf/openrocket/file/openrocket/importt/IgnitionConfigurationHandler.java
index 8ec701c5c..ee02dbc07 100644
--- a/core/src/net/sf/openrocket/file/openrocket/importt/IgnitionConfigurationHandler.java
+++ b/core/src/net/sf/openrocket/file/openrocket/importt/IgnitionConfigurationHandler.java
@@ -9,21 +9,19 @@ import net.sf.openrocket.file.DocumentLoadingContext;
import net.sf.openrocket.file.simplesax.AbstractElementHandler;
import net.sf.openrocket.file.simplesax.ElementHandler;
import net.sf.openrocket.file.simplesax.PlainTextHandler;
-import net.sf.openrocket.rocketcomponent.MotorConfiguration;
+import net.sf.openrocket.rocketcomponent.IgnitionConfiguration;
+import net.sf.openrocket.rocketcomponent.IgnitionConfiguration.IgnitionEvent;
import org.xml.sax.SAXException;
class IgnitionConfigurationHandler extends AbstractElementHandler {
- /** File version where latest digest format was introduced */
- private static final int MOTOR_DIGEST_VERSION = 104;
-
- private final DocumentLoadingContext context;
private Double ignitionDelay = null;
- private MotorConfiguration.IgnitionEvent ignitionEvent = null;
+ private IgnitionEvent ignitionEvent = null;
+
public IgnitionConfigurationHandler(DocumentLoadingContext context) {
- this.context = context;
+
}
@@ -34,13 +32,17 @@ class IgnitionConfigurationHandler extends AbstractElementHandler {
}
- public Double getIgnitionDelay() {
- return ignitionDelay;
+ public IgnitionConfiguration getConfiguration(IgnitionConfiguration def) {
+ IgnitionConfiguration config = def.clone();
+ if (ignitionEvent != null) {
+ config.setIgnitionEvent(ignitionEvent);
+ }
+ if (ignitionDelay != null) {
+ config.setIgnitionDelay(ignitionDelay);
+ }
+ return config;
}
- public MotorConfiguration.IgnitionEvent getIgnitionEvent() {
- return ignitionEvent;
- }
@Override
public void closeElement(String element, HashMap attributes,
@@ -50,7 +52,7 @@ class IgnitionConfigurationHandler extends AbstractElementHandler {
if (element.equals("ignitionevent")) {
- for (MotorConfiguration.IgnitionEvent e : MotorConfiguration.IgnitionEvent.values()) {
+ for (IgnitionEvent e : IgnitionEvent.values()) {
if (e.name().toLowerCase(Locale.ENGLISH).replaceAll("_", "").equals(content)) {
ignitionEvent = e;
break;
diff --git a/core/src/net/sf/openrocket/file/openrocket/importt/MotorMountHandler.java b/core/src/net/sf/openrocket/file/openrocket/importt/MotorMountHandler.java
index 8efec835c..e723edab1 100644
--- a/core/src/net/sf/openrocket/file/openrocket/importt/MotorMountHandler.java
+++ b/core/src/net/sf/openrocket/file/openrocket/importt/MotorMountHandler.java
@@ -9,7 +9,6 @@ import net.sf.openrocket.file.DocumentLoadingContext;
import net.sf.openrocket.file.simplesax.AbstractElementHandler;
import net.sf.openrocket.file.simplesax.ElementHandler;
import net.sf.openrocket.file.simplesax.PlainTextHandler;
-import net.sf.openrocket.motor.Motor;
import net.sf.openrocket.rocketcomponent.IgnitionConfiguration;
import net.sf.openrocket.rocketcomponent.MotorConfiguration;
import net.sf.openrocket.rocketcomponent.MotorMount;
@@ -65,9 +64,11 @@ class MotorMountHandler extends AbstractElementHandler {
return;
}
- Motor motor = motorHandler.getMotor(warnings);
- mount.setMotor(id, motor);
- mount.setMotorDelay(id, motorHandler.getDelay(warnings));
+ MotorConfiguration config = new MotorConfiguration();
+ config.setMotor(motorHandler.getMotor(warnings));
+ config.setEjectionDelay(motorHandler.getDelay(warnings));
+ mount.getMotorConfiguration().set(id, config);
+
return;
}
@@ -77,9 +78,9 @@ class MotorMountHandler extends AbstractElementHandler {
warnings.add(Warning.fromString("Illegal motor specification, ignoring."));
return;
}
- MotorConfiguration motorConfig = mount.getFlightConfiguration(id);
- motorConfig.setIgnitionEvent(ignitionConfigHandler.getIgnitionEvent());
- motorConfig.setIgnitionDelay(ignitionConfigHandler.getIgnitionDelay());
+
+ IgnitionConfiguration def = mount.getIgnitionConfiguration().getDefault();
+ mount.getIgnitionConfiguration().set(id, ignitionConfigHandler.getConfiguration(def));
return;
}
@@ -95,7 +96,7 @@ class MotorMountHandler extends AbstractElementHandler {
warnings.add(Warning.fromString("Unknown ignition event type '" + content + "', ignoring."));
return;
}
- mount.setDefaultIgnitionEvent(event);
+ mount.getIgnitionConfiguration().getDefault().setIgnitionEvent(event);
return;
}
@@ -107,7 +108,7 @@ class MotorMountHandler extends AbstractElementHandler {
warnings.add(Warning.fromString("Illegal ignition delay specified, ignoring."));
return;
}
- mount.setDefaultIgnitionDelay(d);
+ mount.getIgnitionConfiguration().getDefault().setIgnitionDelay(d);
return;
}
diff --git a/core/src/net/sf/openrocket/file/openrocket/importt/StageSeparationConfigurationHandler.java b/core/src/net/sf/openrocket/file/openrocket/importt/StageSeparationConfigurationHandler.java
index 0b3c42393..a349c91df 100644
--- a/core/src/net/sf/openrocket/file/openrocket/importt/StageSeparationConfigurationHandler.java
+++ b/core/src/net/sf/openrocket/file/openrocket/importt/StageSeparationConfigurationHandler.java
@@ -16,45 +16,59 @@ import org.xml.sax.SAXException;
class StageSeparationConfigurationHandler extends AbstractElementHandler {
private final Stage stage;
- private StageSeparationConfiguration config;
-
- public StageSeparationConfigurationHandler( Stage stage, DocumentLoadingContext context ) {
+
+ private SeparationEvent event = null;
+ private double delay = Double.NaN;
+
+ public StageSeparationConfigurationHandler(Stage stage, DocumentLoadingContext context) {
this.stage = stage;
- config = new StageSeparationConfiguration();
}
-
+
+
+ public StageSeparationConfiguration getConfiguration(StageSeparationConfiguration def) {
+ StageSeparationConfiguration config = def.clone();
+ if (event != null) {
+ config.setSeparationEvent(event);
+ }
+ if (!Double.isNaN(delay)) {
+ config.setSeparationDelay(delay);
+ }
+ return config;
+ }
+
+
@Override
public ElementHandler openElement(String element, HashMap attributes, WarningSet warnings)
throws SAXException {
return PlainTextHandler.INSTANCE;
}
-
+
@Override
public void closeElement(String element, HashMap attributes, String content,
WarningSet warnings) throws SAXException {
content = content.trim();
- if ( "separationevent".equals(element) ) {
- SeparationEvent type = (SeparationEvent) DocumentConfig.findEnum(content, SeparationEvent.class);
- if ( type == null ) {
+ if ("separationevent".equals(element)) {
+ event = (SeparationEvent) DocumentConfig.findEnum(content, SeparationEvent.class);
+ if (event == null) {
warnings.add(Warning.FILE_INVALID_PARAMETER);
return;
}
- config.setSeparationEvent( type );
return;
- } else if ( "separationdelay".equals(element) ) {
- config.setSeparationDelay( Double.parseDouble(content));
+ } else if ("separationdelay".equals(element)) {
+ delay = parseDouble(content, warnings, Warning.FILE_INVALID_PARAMETER);
return;
}
super.closeElement(element, attributes, content, warnings);
-
+
}
-
+
@Override
public void endHandler(String element, HashMap attributes, String content, WarningSet warnings) throws SAXException {
String configId = attributes.get("configid");
- stage.setFlightConfiguration(configId, config);
+ StageSeparationConfiguration def = stage.getStageSeparationConfiguration().getDefault();
+ stage.getStageSeparationConfiguration().set(configId, getConfiguration(def));
}
}
\ No newline at end of file
diff --git a/core/src/net/sf/openrocket/file/openrocket/savers/RecoveryDeviceSaver.java b/core/src/net/sf/openrocket/file/openrocket/savers/RecoveryDeviceSaver.java
index cfc16275a..e4f06442d 100644
--- a/core/src/net/sf/openrocket/file/openrocket/savers/RecoveryDeviceSaver.java
+++ b/core/src/net/sf/openrocket/file/openrocket/savers/RecoveryDeviceSaver.java
@@ -10,48 +10,49 @@ import net.sf.openrocket.rocketcomponent.Rocket;
public class RecoveryDeviceSaver extends MassObjectSaver {
-
+
@Override
protected void addParams(net.sf.openrocket.rocketcomponent.RocketComponent c, List elements) {
super.addParams(c, elements);
-
+
RecoveryDevice dev = (RecoveryDevice) c;
-
+
if (dev.isCDAutomatic())
elements.add("auto");
else
elements.add("" + dev.getCD() + "");
-
- DeploymentConfiguration defaultConfig = dev.getDefaultFlightConfiguration();
- elements.addAll( deploymentConfiguration(defaultConfig, false));
elements.add(materialParam(dev.getMaterial()));
-
+
+ // NOTE: Default config must be BEFORE overridden config for proper backward compatibility later on
+ DeploymentConfiguration defaultConfig = dev.getDeploymentConfiguration().getDefault();
+ elements.addAll(deploymentConfiguration(defaultConfig, false));
+
Rocket rocket = c.getRocket();
// Note - getFlightConfigurationIDs returns at least one element. The first element
// is null and means "default".
String[] configs = rocket.getFlightConfigurationIDs();
- if ( configs.length > 1 ) {
-
- for( String id : configs ) {
- if ( id == null ) {
+ if (configs.length > 1) {
+
+ for (String id : configs) {
+ if (id == null) {
continue;
}
- DeploymentConfiguration config = dev.getFlightConfiguration(id);
- if ( config == null ) {
+ if (dev.getDeploymentConfiguration().isDefault(id)) {
continue;
}
+ DeploymentConfiguration config = dev.getDeploymentConfiguration().get(id);
elements.add("");
- elements.addAll( deploymentConfiguration(config, true) );
+ elements.addAll(deploymentConfiguration(config, true));
elements.add("");
}
}
}
-
- private List deploymentConfiguration( DeploymentConfiguration config, boolean indent ) {
+
+ private List deploymentConfiguration(DeploymentConfiguration config, boolean indent) {
List elements = new ArrayList(3);
- elements.add((indent?" ": "") + "" + config.getDeployEvent().name().toLowerCase(Locale.ENGLISH).replace("_", "") + "");
- elements.add((indent?" ": "") + "" + config.getDeployAltitude() + "");
- elements.add((indent?" ": "") + "" + config.getDeployDelay() + "");
+ elements.add((indent ? " " : "") + "" + config.getDeployEvent().name().toLowerCase(Locale.ENGLISH).replace("_", "") + "");
+ elements.add((indent ? " " : "") + "" + config.getDeployAltitude() + "");
+ elements.add((indent ? " " : "") + "" + config.getDeployDelay() + "");
return elements;
}
diff --git a/core/src/net/sf/openrocket/file/openrocket/savers/RocketComponentSaver.java b/core/src/net/sf/openrocket/file/openrocket/savers/RocketComponentSaver.java
index adda3e115..7df686e5a 100644
--- a/core/src/net/sf/openrocket/file/openrocket/savers/RocketComponentSaver.java
+++ b/core/src/net/sf/openrocket/file/openrocket/savers/RocketComponentSaver.java
@@ -8,13 +8,13 @@ import java.util.Locale;
import net.sf.openrocket.appearance.Appearance;
import net.sf.openrocket.appearance.Decal;
import net.sf.openrocket.appearance.Decal.EdgeMode;
-import net.sf.openrocket.file.RocketSaver;
import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.material.Material;
import net.sf.openrocket.motor.Motor;
import net.sf.openrocket.motor.ThrustCurveMotor;
import net.sf.openrocket.preset.ComponentPreset;
import net.sf.openrocket.rocketcomponent.ComponentAssembly;
+import net.sf.openrocket.rocketcomponent.IgnitionConfiguration;
import net.sf.openrocket.rocketcomponent.MotorConfiguration;
import net.sf.openrocket.rocketcomponent.MotorMount;
import net.sf.openrocket.rocketcomponent.Rocket;
@@ -24,6 +24,7 @@ import net.sf.openrocket.util.BugException;
import net.sf.openrocket.util.Color;
import net.sf.openrocket.util.Coordinate;
import net.sf.openrocket.util.LineStyle;
+import net.sf.openrocket.util.TextUtil;
public class RocketComponentSaver {
private static final Translator trans = Application.getTranslator();
@@ -33,7 +34,7 @@ public class RocketComponentSaver {
}
protected void addParams(net.sf.openrocket.rocketcomponent.RocketComponent c, List elements) {
- elements.add("" + RocketSaver.escapeXML(c.getName()) + "");
+ elements.add("" + TextUtil.escapeXML(c.getName()) + "");
ComponentPreset preset = c.getPresetComponent();
if (preset != null) {
@@ -104,7 +105,7 @@ public class RocketComponentSaver {
// Comment
if (c.getComment().length() > 0) {
- elements.add("" + RocketSaver.escapeXML(c.getComment()) + "");
+ elements.add("" + TextUtil.escapeXML(c.getComment()) + "");
}
}
@@ -136,7 +137,7 @@ public class RocketComponentSaver {
String baseName = trans.getBaseText("material", mat.getName());
- return str + " density=\"" + mat.getDensity() + "\">" + RocketSaver.escapeXML(baseName) + "" + tag + ">";
+ return str + " density=\"" + mat.getDensity() + "\">" + TextUtil.escapeXML(baseName) + "" + tag + ">";
}
@@ -148,11 +149,15 @@ public class RocketComponentSaver {
elements.add("");
+ // NOTE: Default config must be BEFORE overridden config for proper backward compatibility later on
+ elements.add(" "
+ + mount.getIgnitionConfiguration().getDefault().getIgnitionEvent().name().toLowerCase(Locale.ENGLISH).replace("_", "")
+ + "");
+ elements.add(" " + mount.getIgnitionConfiguration().getDefault().getIgnitionDelay() + "");
+ elements.add(" " + mount.getMotorOverhang() + "");
+
for (String id : motorConfigIDs) {
- MotorConfiguration motorConfig = mount.getFlightConfiguration(id);
- if (motorConfig == null) {
- continue;
- }
+ MotorConfiguration motorConfig = mount.getMotorConfiguration().get(id);
Motor motor = motorConfig.getMotor();
// Nothing is stored if no motor loaded
if (motor == null)
@@ -164,11 +169,11 @@ public class RocketComponentSaver {
}
if (motor instanceof ThrustCurveMotor) {
ThrustCurveMotor m = (ThrustCurveMotor) motor;
- elements.add(" " + RocketSaver.escapeXML(m.getManufacturer().getSimpleName()) +
+ elements.add(" " + TextUtil.escapeXML(m.getManufacturer().getSimpleName()) +
"");
elements.add(" " + m.getDigest() + "");
}
- elements.add(" " + RocketSaver.escapeXML(motor.getDesignation()) + "");
+ elements.add(" " + TextUtil.escapeXML(motor.getDesignation()) + "");
elements.add(" " + motor.getDiameter() + "");
elements.add(" " + motor.getLength() + "");
@@ -181,27 +186,16 @@ public class RocketComponentSaver {
elements.add(" ");
- if (motorConfig.getIgnitionEvent() != null || motorConfig.getIgnitionDelay() != null) {
+ if (!mount.getIgnitionConfiguration().isDefault(id)) {
+ IgnitionConfiguration ignition = mount.getIgnitionConfiguration().get(id);
elements.add(" ");
-
- if (motorConfig.getIgnitionEvent() != null) {
- elements.add(" " + motorConfig.getIgnitionEvent().name().toLowerCase(Locale.ENGLISH).replace("_", "") + "");
- }
- if (motorConfig.getIgnitionDelay() != null) {
- elements.add(" " + motorConfig.getIgnitionDelay() + "");
- }
-
+ elements.add(" " + ignition.getIgnitionEvent().name().toLowerCase(Locale.ENGLISH).replace("_", "") + "");
+ elements.add(" " + ignition.getIgnitionDelay() + "");
elements.add(" ");
}
}
- elements.add(" "
- + mount.getDefaultIgnitionEvent().name().toLowerCase(Locale.ENGLISH).replace("_", "")
- + "");
- elements.add(" " + mount.getDefaultIgnitionDelay() + "");
- elements.add(" " + mount.getMotorOverhang() + "");
-
elements.add("");
return elements;
diff --git a/core/src/net/sf/openrocket/file/openrocket/savers/RocketSaver.java b/core/src/net/sf/openrocket/file/openrocket/savers/RocketSaver.java
index 3a58bed5d..257e072c1 100644
--- a/core/src/net/sf/openrocket/file/openrocket/savers/RocketSaver.java
+++ b/core/src/net/sf/openrocket/file/openrocket/savers/RocketSaver.java
@@ -29,12 +29,12 @@ public class RocketSaver extends RocketComponentSaver {
if (rocket.getDesigner().length() > 0) {
elements.add(""
- + net.sf.openrocket.file.RocketSaver.escapeXML(rocket.getDesigner())
+ + net.sf.openrocket.util.TextUtil.escapeXML(rocket.getDesigner())
+ "");
}
if (rocket.getRevision().length() > 0) {
elements.add(""
- + net.sf.openrocket.file.RocketSaver.escapeXML(rocket.getRevision())
+ + net.sf.openrocket.util.TextUtil.escapeXML(rocket.getRevision())
+ "");
}
@@ -52,7 +52,7 @@ public class RocketSaver extends RocketComponentSaver {
if (rocket.getFlightConfigurationName(id) == "") {
str += "/>";
} else {
- str += ">" + net.sf.openrocket.file.RocketSaver.escapeXML(rocket.getFlightConfigurationName(id))
+ str += ">" + net.sf.openrocket.util.TextUtil.escapeXML(rocket.getFlightConfigurationName(id))
+ "";
}
elements.add(str);
diff --git a/core/src/net/sf/openrocket/file/openrocket/savers/StageSaver.java b/core/src/net/sf/openrocket/file/openrocket/savers/StageSaver.java
index 33bdd4986..fb875379f 100644
--- a/core/src/net/sf/openrocket/file/openrocket/savers/StageSaver.java
+++ b/core/src/net/sf/openrocket/file/openrocket/savers/StageSaver.java
@@ -10,56 +10,57 @@ import net.sf.openrocket.rocketcomponent.Stage;
import net.sf.openrocket.rocketcomponent.StageSeparationConfiguration;
public class StageSaver extends ComponentAssemblySaver {
-
+
private static final StageSaver instance = new StageSaver();
-
+
public static ArrayList getElements(net.sf.openrocket.rocketcomponent.RocketComponent c) {
ArrayList list = new ArrayList();
-
+
list.add("");
instance.addParams(c, list);
list.add("");
-
+
return list;
}
-
+
@Override
protected void addParams(RocketComponent c, List elements) {
super.addParams(c, elements);
Stage stage = (Stage) c;
-
+
if (stage.getStageNumber() > 0) {
- elements.addAll( separationConfig( stage.getDefaultFlightConfiguration(), false));
-
+ // NOTE: Default config must be BEFORE overridden config for proper backward compatibility later on
+ elements.addAll(separationConfig(stage.getStageSeparationConfiguration().getDefault(), false));
+
Rocket rocket = stage.getRocket();
// Note - getFlightConfigurationIDs returns at least one element. The first element
// is null and means "default".
String[] configs = rocket.getFlightConfigurationIDs();
- if ( configs.length > 1 ) {
-
- for( String id : configs ) {
- if ( id == null ) {
+ if (configs.length > 1) {
+
+ for (String id : configs) {
+ if (id == null) {
continue;
}
- StageSeparationConfiguration config = stage.getFlightConfiguration(id);
- if ( config == null ) {
+ if (stage.getStageSeparationConfiguration().isDefault(id)) {
continue;
}
+ StageSeparationConfiguration config = stage.getStageSeparationConfiguration().get(id);
elements.add("");
- elements.addAll( separationConfig(config, true) );
+ elements.addAll(separationConfig(config, true));
elements.add("");
}
}
}
}
-
- private List separationConfig( StageSeparationConfiguration config, boolean indent ) {
+
+ private List separationConfig(StageSeparationConfiguration config, boolean indent) {
List elements = new ArrayList(2);
- elements.add((indent?" ":"")+ ""
+ elements.add((indent ? " " : "") + ""
+ config.getSeparationEvent().name().toLowerCase(Locale.ENGLISH).replace("_", "")
+ "");
- elements.add((indent?" ":"")+ "" + config.getSeparationDelay() + "");
+ elements.add((indent ? " " : "") + "" + config.getSeparationDelay() + "");
return elements;
-
+
}
}
diff --git a/core/src/net/sf/openrocket/file/simplesax/AbstractElementHandler.java b/core/src/net/sf/openrocket/file/simplesax/AbstractElementHandler.java
index 208f68c01..3085d2ffe 100644
--- a/core/src/net/sf/openrocket/file/simplesax/AbstractElementHandler.java
+++ b/core/src/net/sf/openrocket/file/simplesax/AbstractElementHandler.java
@@ -51,4 +51,21 @@ public abstract class AbstractElementHandler implements ElementHandler {
// No-op
}
+
+ /**
+ * Helper method for parsing a double value safely.
+ *
+ * @param str the string to parse
+ * @param warnings the warning set
+ * @param warn the warning to add if the value fails to parse
+ * @return the double value, or NaN if an error occurred
+ */
+ protected double parseDouble(String str, WarningSet warnings, Warning warn) {
+ try {
+ return Double.parseDouble(str);
+ } catch (NumberFormatException e) {
+ warnings.add(warn);
+ return Double.NaN;
+ }
+ }
}
diff --git a/core/src/net/sf/openrocket/gui/adaptors/BasicEnumModel.java b/core/src/net/sf/openrocket/gui/adaptors/BasicEnumModel.java
deleted file mode 100644
index 37b512645..000000000
--- a/core/src/net/sf/openrocket/gui/adaptors/BasicEnumModel.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package net.sf.openrocket.gui.adaptors;
-
-import javax.swing.AbstractListModel;
-import javax.swing.ComboBoxModel;
-
-
-public class BasicEnumModel> extends AbstractListModel implements ComboBoxModel {
-
- private final String nullText;
-
- private final Enum[] values;
- private Enum currentValue = null;
-
- public BasicEnumModel( Class extends Enum> clazz ) {
- this(clazz, null);
- }
-
- @SuppressWarnings("unchecked")
- public BasicEnumModel(Class extends Enum> clazz, String nullText) {
- this.values = clazz.getEnumConstants();
- this.nullText = nullText;
- }
-
- @Override
- public void setSelectedItem(Object anItem) {
- currentValue = (Enum) anItem;
- }
-
- @Override
- public Object getSelectedItem() {
- if (currentValue==null)
- return nullText;
- return currentValue;
- }
-
- @Override
- public Object getElementAt(int index) {
- if (values[index] == null)
- return nullText;
- return values[index];
- }
-
- @Override
- public int getSize() {
- return values.length;
- }
-
-}
diff --git a/core/src/net/sf/openrocket/gui/configdialog/MotorConfig.java b/core/src/net/sf/openrocket/gui/configdialog/MotorConfig.java
index 15dbf881b..2974e768f 100644
--- a/core/src/net/sf/openrocket/gui/configdialog/MotorConfig.java
+++ b/core/src/net/sf/openrocket/gui/configdialog/MotorConfig.java
@@ -144,7 +144,7 @@ public class MotorConfig extends JPanel {
//// plus
panel.add(new JLabel(trans.get("MotorCfg.lbl.plus")), "gap indent, skip 1, span, split");
- dm = new DoubleModel(ignitionConfig, "Delay", 0);
+ dm = new DoubleModel(ignitionConfig, "IgnitionDelay", 0);
spin = new JSpinner(dm.getSpinnerModel());
spin.setEditor(new SpinnerEditor(spin, 3));
panel.add(spin, "gap rel rel");
diff --git a/core/src/net/sf/openrocket/gui/configdialog/StageConfig.java b/core/src/net/sf/openrocket/gui/configdialog/StageConfig.java
index c7e76e875..08e6a57b9 100644
--- a/core/src/net/sf/openrocket/gui/configdialog/StageConfig.java
+++ b/core/src/net/sf/openrocket/gui/configdialog/StageConfig.java
@@ -40,13 +40,14 @@ public class StageConfig extends RocketComponentConfig {
// Select separation event
panel.add(new StyledLabel(trans.get("separation.lbl.title"), Style.BOLD), "spanx, wrap rel");
- JComboBox combo = new JComboBox(new EnumModel(stage, "DefaultSeparationEvent"));
+ StageSeparationConfiguration config = stage.getStageSeparationConfiguration().getDefault();
+ JComboBox combo = new JComboBox(new EnumModel(config, "SeparationEvent"));
panel.add(combo, "");
// ... and delay
panel.add(new JLabel(trans.get("separation.lbl.plus")), "");
- DoubleModel dm = new DoubleModel(stage, "DefaultSeparationDelay", 0);
+ DoubleModel dm = new DoubleModel(config, "SeparationDelay", 0);
JSpinner spin = new JSpinner(dm.getSpinnerModel());
spin.setEditor(new SpinnerEditor(spin));
panel.add(spin, "width 45");
diff --git a/core/src/net/sf/openrocket/gui/customexpression/OperatorSelector.java b/core/src/net/sf/openrocket/gui/customexpression/OperatorSelector.java
index 4a66d15ee..a4daa254c 100644
--- a/core/src/net/sf/openrocket/gui/customexpression/OperatorSelector.java
+++ b/core/src/net/sf/openrocket/gui/customexpression/OperatorSelector.java
@@ -26,13 +26,12 @@ import net.miginfocom.swing.MigLayout;
import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.logging.LogHelper;
import net.sf.openrocket.startup.Application;
-import net.sf.openrocket.util.TextUtil;
public class OperatorSelector extends JDialog {
private static final Translator trans = Application.getTranslator();
private static final LogHelper log = Application.getLogger();
-
+
@SuppressWarnings("unused")
private final Window parentWindow;
@@ -40,7 +39,7 @@ public class OperatorSelector extends JDialog {
private final OperatorTableModel tableModel;
private final ExpressionBuilderDialog parentBuilder;
- public OperatorSelector(Window parent, final ExpressionBuilderDialog parentBuilder){
+ public OperatorSelector(Window parent, final ExpressionBuilderDialog parentBuilder) {
super(parent, trans.get("CustomOperatorSelector.title"), JDialog.ModalityType.DOCUMENT_MODAL);
@@ -57,19 +56,19 @@ public class OperatorSelector extends JDialog {
table.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
int width = table.getColumnModel().getTotalColumnWidth();
- table.getColumnModel().getColumn(0).setPreferredWidth( (int) (.1 * width));
- table.getColumnModel().getColumn(1).setPreferredWidth( (int) (.9 * width));
+ table.getColumnModel().getColumn(0).setPreferredWidth((int) (.1 * width));
+ table.getColumnModel().getColumn(1).setPreferredWidth((int) (.9 * width));
table.setAutoCreateRowSorter(true);
- table.addMouseMotionListener(new MouseMotionAdapter(){
+ table.addMouseMotionListener(new MouseMotionAdapter() {
@Override
- public void mouseMoved(MouseEvent e){
+ public void mouseMoved(MouseEvent e) {
Point p = e.getPoint();
int row = table.rowAtPoint(p);
int col = table.columnAtPoint(p);
- if (col == 1 && row > -1){
+ if (col == 1 && row > -1) {
String description = String.valueOf(table.getValueAt(row, 1));
- description = TextUtil.wrap(description, 60);
+ description = wrap(description, 60);
table.setToolTipText(description);
} else {
table.setToolTipText(null);
@@ -77,29 +76,37 @@ public class OperatorSelector extends JDialog {
}
});
- table.addMouseListener(new MouseListener(){
+ table.addMouseListener(new MouseListener() {
@Override
- public void mouseClicked(MouseEvent e){
- if (e.getClickCount() == 2){
+ public void mouseClicked(MouseEvent e) {
+ if (e.getClickCount() == 2) {
log.debug("Selected operator by double clicking.");
selectOperator();
}
}
+
@Override
- public void mouseEntered(MouseEvent e) {}
+ public void mouseEntered(MouseEvent e) {
+ }
+
@Override
- public void mouseExited(MouseEvent e) {}
+ public void mouseExited(MouseEvent e) {
+ }
+
@Override
- public void mousePressed(MouseEvent e) {}
+ public void mousePressed(MouseEvent e) {
+ }
+
@Override
- public void mouseReleased(MouseEvent e) {}
- } );
+ public void mouseReleased(MouseEvent e) {
+ }
+ });
InputMap inputMap = table.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
ActionMap actionMap = table.getActionMap();
KeyStroke enter = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0);
inputMap.put(enter, "select");
- actionMap.put("select", new AbstractAction(){
+ actionMap.put("select", new AbstractAction() {
@Override
public void actionPerformed(ActionEvent arg0) {
log.debug("Selected operator by enter key");
@@ -110,16 +117,16 @@ public class OperatorSelector extends JDialog {
JScrollPane scrollPane = new JScrollPane(table);
table.setFillsViewportHeight(true);
table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
- @Override
- public void valueChanged(ListSelectionEvent e){
- if (table.getSelectedRowCount() == 1){
- insertButton.setEnabled(true);
- }
- else {
- insertButton.setEnabled(false);
- }
+ @Override
+ public void valueChanged(ListSelectionEvent e) {
+ if (table.getSelectedRowCount() == 1) {
+ insertButton.setEnabled(true);
}
- });
+ else {
+ insertButton.setEnabled(false);
+ }
+ }
+ });
mainPanel.add(scrollPane, "wrap, push, grow");
@@ -142,17 +149,32 @@ public class OperatorSelector extends JDialog {
});
insertButton.setEnabled(false); // disabled by default, only enable when a variable selected
mainPanel.add(insertButton, "right, width :100:200, wrap");
-
+
this.add(mainPanel);
this.validate();
this.pack();
- this.setLocationByPlatform(true);
+ this.setLocationByPlatform(true);
}
- private void selectOperator(){
+ private void selectOperator() {
int row = table.getSelectedRow();
String str = table.getValueAt(row, 0).toString();
parentBuilder.pasteIntoExpression(str);
OperatorSelector.this.dispose();
}
+
+
+ /*
+ * Returns a word-wrapped version of given input string using HTML syntax, wrapped to len characters.
+ */
+ private String wrap(String in, int len) {
+ in = in.trim();
+ if (in.length() < len)
+ return in;
+ if (in.substring(0, len).contains("\n"))
+ return in.substring(0, in.indexOf("\n")).trim() + "\n\n" + wrap(in.substring(in.indexOf("\n") + 1), len);
+ int place = Math.max(Math.max(in.lastIndexOf(" ", len), in.lastIndexOf("\t", len)), in.lastIndexOf("-", len));
+ return "" + in.substring(0, place).trim() + "
" + wrap(in.substring(place), len);
+ }
+
}
diff --git a/core/src/net/sf/openrocket/gui/dialogs/flightconfiguration/DeploymentSelectionDialog.java b/core/src/net/sf/openrocket/gui/dialogs/flightconfiguration/DeploymentSelectionDialog.java
new file mode 100644
index 000000000..41d03cb8b
--- /dev/null
+++ b/core/src/net/sf/openrocket/gui/dialogs/flightconfiguration/DeploymentSelectionDialog.java
@@ -0,0 +1,147 @@
+package net.sf.openrocket.gui.dialogs.flightconfiguration;
+
+import java.awt.Dialog;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+import javax.swing.ButtonGroup;
+import javax.swing.JButton;
+import javax.swing.JComboBox;
+import javax.swing.JDialog;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JRadioButton;
+import javax.swing.JSlider;
+import javax.swing.JSpinner;
+
+import net.miginfocom.swing.MigLayout;
+import net.sf.openrocket.gui.SpinnerEditor;
+import net.sf.openrocket.gui.adaptors.DoubleModel;
+import net.sf.openrocket.gui.adaptors.EnumModel;
+import net.sf.openrocket.gui.components.BasicSlider;
+import net.sf.openrocket.gui.components.UnitSelector;
+import net.sf.openrocket.gui.util.GUIUtil;
+import net.sf.openrocket.l10n.Translator;
+import net.sf.openrocket.rocketcomponent.DeploymentConfiguration;
+import net.sf.openrocket.rocketcomponent.DeploymentConfiguration.DeployEvent;
+import net.sf.openrocket.rocketcomponent.RecoveryDevice;
+import net.sf.openrocket.rocketcomponent.Rocket;
+import net.sf.openrocket.startup.Application;
+import net.sf.openrocket.unit.UnitGroup;
+
+public class DeploymentSelectionDialog extends JDialog {
+
+ private static final Translator trans = Application.getTranslator();
+
+ private final DeploymentConfiguration newConfiguration;
+
+ private final JLabel altText;
+ private final JSpinner altSpinner;
+ private final UnitSelector altUnit;
+ private final JSlider altSlider;
+
+ DeploymentSelectionDialog(JDialog parent, final Rocket rocket, final RecoveryDevice component) {
+ super(parent, trans.get("edtmotorconfdlg.title.Selectdeploymentconf"), Dialog.ModalityType.APPLICATION_MODAL);
+
+ final String id = rocket.getDefaultConfiguration().getFlightConfigurationID();
+
+ newConfiguration = component.getDeploymentConfiguration().get(id).clone();
+
+ JPanel panel = new JPanel(new MigLayout("fill"));
+
+ panel.add(new JLabel(trans.get("DeploymentSelectionDialog.opt.title")), "span, wrap rel");
+ final JRadioButton defaultButton = new JRadioButton(trans.get("DeploymentSelectionDialog.opt.default"), true);
+ panel.add(defaultButton, "span, gapleft para, wrap rel");
+ String str = trans.get("DeploymentSelectionDialog.opt.override");
+ str = str.replace("{0}", rocket.getFlightConfigurationNameOrDescription(id));
+ final JRadioButton overrideButton = new JRadioButton(str, false);
+ panel.add(overrideButton, "span, gapleft para, wrap para");
+
+ ButtonGroup buttonGroup = new ButtonGroup();
+ buttonGroup.add(defaultButton);
+ buttonGroup.add(overrideButton);
+
+
+ //// Deployment
+ //// Deploys at:
+ panel.add(new JLabel(trans.get("ParachuteCfg.lbl.Deploysat")), "");
+
+ final JComboBox event = new JComboBox(new EnumModel(newConfiguration, "DeployEvent"));
+ panel.add(event, "spanx 3, growx, wrap");
+
+ // ... and delay
+ //// plus
+ panel.add(new JLabel(trans.get("ParachuteCfg.lbl.plusdelay")), "right");
+
+ final DoubleModel delay = new DoubleModel(newConfiguration, "DeployDelay", UnitGroup.UNITS_SHORT_TIME, 0);
+ final JSpinner delaySpinner = new JSpinner(delay.getSpinnerModel());
+ delaySpinner.setEditor(new SpinnerEditor(delaySpinner, 3));
+ panel.add(delaySpinner, "spanx, split");
+
+ //// seconds
+ panel.add(new JLabel(trans.get("ParachuteCfg.lbl.seconds")), "wrap paragraph");
+
+ // Altitude:
+ altText = new JLabel(trans.get("ParachuteCfg.lbl.Altitude"));
+ panel.add(altText);
+
+ final DoubleModel alt = new DoubleModel(newConfiguration, "DeployAltitude", UnitGroup.UNITS_DISTANCE, 0);
+
+ altSpinner = new JSpinner(alt.getSpinnerModel());
+ altSpinner.setEditor(new SpinnerEditor(altSpinner));
+ panel.add(altSpinner, "growx");
+ altUnit = new UnitSelector(alt);
+ panel.add(altUnit, "growx");
+ altSlider = new BasicSlider(alt.getSliderModel(100, 1000));
+ panel.add(altSlider, "w 100lp, wrap");
+
+ event.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ updateState();
+ }
+ });
+ updateState();
+
+ panel.add(new JPanel(), "span, split, growx");
+
+ JButton okButton = new JButton(trans.get("button.ok"));
+ okButton.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ if (defaultButton.isSelected()) {
+ component.getDeploymentConfiguration().setDefault(newConfiguration);
+ } else {
+ component.getDeploymentConfiguration().set(id, newConfiguration);
+ }
+ DeploymentSelectionDialog.this.setVisible(false);
+ }
+ });
+
+ panel.add(okButton, "sizegroup btn");
+
+ JButton cancel = new JButton(trans.get("button.cancel"));
+ cancel.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ DeploymentSelectionDialog.this.setVisible(false);
+ }
+ });
+
+ panel.add(cancel, "sizegroup btn");
+
+ this.setContentPane(panel);
+ GUIUtil.setDisposableDialogOptions(this, okButton);
+ }
+
+
+ private void updateState() {
+ boolean enabled = (newConfiguration.getDeployEvent() == DeployEvent.ALTITUDE);
+ altText.setEnabled(enabled);
+ altSpinner.setEnabled(enabled);
+ altUnit.setEnabled(enabled);
+ altSlider.setEnabled(enabled);
+ }
+
+
+}
diff --git a/core/src/net/sf/openrocket/gui/dialogs/flightconfiguration/FlightConfigurationDialog.java b/core/src/net/sf/openrocket/gui/dialogs/flightconfiguration/FlightConfigurationDialog.java
index 41191f070..4cc28bdeb 100644
--- a/core/src/net/sf/openrocket/gui/dialogs/flightconfiguration/FlightConfigurationDialog.java
+++ b/core/src/net/sf/openrocket/gui/dialogs/flightconfiguration/FlightConfigurationDialog.java
@@ -16,6 +16,7 @@ import javax.swing.JTabbedPane;
import net.miginfocom.swing.MigLayout;
import net.sf.openrocket.document.OpenRocketDocument;
+import net.sf.openrocket.gui.adaptors.FlightConfigurationModel;
import net.sf.openrocket.gui.main.BasicFrame;
import net.sf.openrocket.gui.util.GUIUtil;
import net.sf.openrocket.l10n.Translator;
@@ -23,9 +24,13 @@ import net.sf.openrocket.rocketcomponent.Rocket;
import net.sf.openrocket.rocketvisitors.CopyFlightConfigurationVisitor;
import net.sf.openrocket.startup.Application;
+/**
+ * Dialog for configuring all flight-configuration specific properties.
+ * Content of individual tabs are in separate classes.
+ */
public class FlightConfigurationDialog extends JDialog {
- static final Translator trans = Application.getTranslator();
+ private static final Translator trans = Application.getTranslator();
private final Rocket rocket;
@@ -58,7 +63,7 @@ public class FlightConfigurationDialog extends JDialog {
JLabel label = new JLabel("Selected Configuration:");
panel.add(label);
- flightConfigurationModel = new FlightConfigurationModel(this, rocket.getDefaultConfiguration());
+ flightConfigurationModel = new FlightConfigurationModel(rocket.getDefaultConfiguration());
JComboBox configSelector = new JComboBox(flightConfigurationModel);
panel.add(configSelector, "gapright para");
@@ -78,7 +83,7 @@ public class FlightConfigurationDialog extends JDialog {
renameConfButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
- new RenameConfigDialog(rocket, FlightConfigurationDialog.this).setVisible(true);
+ new RenameConfigDialog(FlightConfigurationDialog.this, rocket).setVisible(true);
}
});
panel.add(renameConfButton);
@@ -111,7 +116,6 @@ public class FlightConfigurationDialog extends JDialog {
//// Motor tabs
motorConfigurationPanel = new MotorConfigurationPanel(this, rocket);
tabs.add(trans.get("edtmotorconfdlg.lbl.Motortab"), motorConfigurationPanel);
-
//// Recovery tab
recoveryConfigurationPanel = new RecoveryConfigurationPanel(this, rocket);
tabs.add(trans.get("edtmotorconfdlg.lbl.Recoverytab"), recoveryConfigurationPanel);
@@ -122,6 +126,7 @@ public class FlightConfigurationDialog extends JDialog {
tabs.add(trans.get("edtmotorconfdlg.lbl.Stagetab"), separationConfigurationPanel);
}
+
//// Close button
JButton close = new JButton(trans.get("dlg.but.close"));
close.addActionListener(new ActionListener() {
@@ -168,7 +173,6 @@ public class FlightConfigurationDialog extends JDialog {
currentID = rocket.newFlightConfigurationID();
rocket.getDefaultConfiguration().setFlightConfigurationID(currentID);
motorConfigurationPanel.fireTableDataChanged();
- flightConfigurationModel.fireContentsUpdated();
recoveryConfigurationPanel.fireTableDataChanged();
separationConfigurationPanel.fireTableDataChanged();
updateButtonState();
@@ -185,7 +189,6 @@ public class FlightConfigurationDialog extends JDialog {
// Copy the name.
this.changeConfigurationName(oldName);
motorConfigurationPanel.fireTableDataChanged();
- flightConfigurationModel.fireContentsUpdated();
recoveryConfigurationPanel.fireTableDataChanged();
separationConfigurationPanel.fireTableDataChanged();
updateButtonState();
@@ -193,7 +196,6 @@ public class FlightConfigurationDialog extends JDialog {
public void changeConfigurationName(String newName) {
rocket.setFlightConfigurationName(currentID, newName);
- flightConfigurationModel.fireContentsUpdated();
}
public void removeConfiguration() {
@@ -202,7 +204,6 @@ public class FlightConfigurationDialog extends JDialog {
rocket.removeFlightConfigurationID(currentID);
rocket.getDefaultConfiguration().setFlightConfigurationID(null);
motorConfigurationPanel.fireTableDataChanged();
- flightConfigurationModel.fireContentsUpdated();
recoveryConfigurationPanel.fireTableDataChanged();
separationConfigurationPanel.fireTableDataChanged();
updateButtonState();
@@ -212,7 +213,6 @@ public class FlightConfigurationDialog extends JDialog {
* Call this from other panels when a change might cause the names of the configurations to change.
*/
public void fireContentsUpdated() {
- flightConfigurationModel.fireContentsUpdated();
}
private void updateButtonState() {
diff --git a/core/src/net/sf/openrocket/gui/dialogs/flightconfiguration/FlightConfigurationModel.java b/core/src/net/sf/openrocket/gui/dialogs/flightconfiguration/FlightConfigurationModel.java
deleted file mode 100644
index cb2bd7a94..000000000
--- a/core/src/net/sf/openrocket/gui/dialogs/flightconfiguration/FlightConfigurationModel.java
+++ /dev/null
@@ -1,98 +0,0 @@
-package net.sf.openrocket.gui.dialogs.flightconfiguration;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import javax.swing.DefaultComboBoxModel;
-
-import net.sf.openrocket.rocketcomponent.Configuration;
-import net.sf.openrocket.rocketcomponent.Rocket;
-
-public class FlightConfigurationModel extends DefaultComboBoxModel {
-
- private final Configuration config;
- private final Rocket rocket;
-
- private Map map = new HashMap();
-
- private final FlightConfigurationDialog flightConfigurationDialog;
-
- public FlightConfigurationModel(FlightConfigurationDialog flightConfigurationDialog, Configuration config) {
- this.flightConfigurationDialog = flightConfigurationDialog;
- this.config = config;
- this.rocket = config.getRocket();
- }
-
- void fireContentsUpdated() {
- fireContentsChanged(this, 0, rocket.getFlightConfigurationIDs().length);
- }
-
- @Override
- public Object getElementAt(int index) {
- String[] ids = rocket.getFlightConfigurationIDs();
- if (index < 0 || index >= ids.length)
- return null;
-
- return get(ids[index]);
- }
-
- @Override
- public int getSize() {
- return rocket.getFlightConfigurationIDs().length;
- }
-
- @Override
- public Object getSelectedItem() {
- return get(config.getFlightConfigurationID());
- }
-
- @Override
- public void setSelectedItem(Object item) {
- if (item == null) {
- // Clear selection - huh?
- return;
- }
- if (!(item instanceof ID)) {
- throw new IllegalArgumentException("MotorConfigurationModel item="+item);
- }
-
- ID idObject = (ID) item;
- flightConfigurationDialog.selectConfiguration(idObject.getID());
- }
-
- /*
- * The ID class is an adapter, that contains the actual configuration ID,
- * but gives the configuration description as its String representation.
- * The get(id) method retrieves ID objects and caches them for reuse.
- */
-
- private ID get(String id) {
- ID idObject = map.get(id);
- if (idObject != null)
- return idObject;
-
- idObject = new ID(id);
- map.put(id, idObject);
- return idObject;
- }
-
-
- private class ID {
- private final String id;
-
- public ID(String id) {
- this.id = id;
- }
-
- public String getID() {
- return id;
- }
-
- @Override
- public String toString() {
- return rocket.getFlightConfigurationNameOrDescription(id);
- }
- }
-
-}
-
diff --git a/core/src/net/sf/openrocket/gui/dialogs/flightconfiguration/IgnitionSelectionDialog.java b/core/src/net/sf/openrocket/gui/dialogs/flightconfiguration/IgnitionSelectionDialog.java
new file mode 100644
index 000000000..c0fd12e45
--- /dev/null
+++ b/core/src/net/sf/openrocket/gui/dialogs/flightconfiguration/IgnitionSelectionDialog.java
@@ -0,0 +1,107 @@
+package net.sf.openrocket.gui.dialogs.flightconfiguration;
+
+import java.awt.Dialog;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+import javax.swing.ButtonGroup;
+import javax.swing.JButton;
+import javax.swing.JComboBox;
+import javax.swing.JDialog;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JRadioButton;
+import javax.swing.JSpinner;
+
+import net.miginfocom.swing.MigLayout;
+import net.sf.openrocket.gui.SpinnerEditor;
+import net.sf.openrocket.gui.adaptors.DoubleModel;
+import net.sf.openrocket.gui.adaptors.EnumModel;
+import net.sf.openrocket.gui.util.GUIUtil;
+import net.sf.openrocket.l10n.Translator;
+import net.sf.openrocket.rocketcomponent.IgnitionConfiguration;
+import net.sf.openrocket.rocketcomponent.IgnitionConfiguration.IgnitionEvent;
+import net.sf.openrocket.rocketcomponent.MotorMount;
+import net.sf.openrocket.rocketcomponent.Rocket;
+import net.sf.openrocket.startup.Application;
+import net.sf.openrocket.unit.UnitGroup;
+
+public class IgnitionSelectionDialog extends JDialog {
+
+ private static final Translator trans = Application.getTranslator();
+
+
+ private IgnitionConfiguration newConfiguration;
+
+ IgnitionSelectionDialog(JDialog parent, final Rocket rocket, final MotorMount component) {
+ super(parent, trans.get("edtmotorconfdlg.title.Selectignitionconf"), Dialog.ModalityType.APPLICATION_MODAL);
+ final String id = rocket.getDefaultConfiguration().getFlightConfigurationID();
+
+ newConfiguration = component.getIgnitionConfiguration().get(id).clone();
+
+ JPanel panel = new JPanel(new MigLayout("fill"));
+
+ panel.add(new JLabel(trans.get("IgnitionSelectionDialog.opt.title")), "span, wrap rel");
+ final JRadioButton defaultButton = new JRadioButton(trans.get("IgnitionSelectionDialog.opt.default"), true);
+ panel.add(defaultButton, "span, gapleft para, wrap rel");
+ String str = trans.get("IgnitionSelectionDialog.opt.override");
+ str = str.replace("{0}", rocket.getFlightConfigurationNameOrDescription(id));
+ final JRadioButton overrideButton = new JRadioButton(str, false);
+ panel.add(overrideButton, "span, gapleft para, wrap para");
+
+ ButtonGroup buttonGroup = new ButtonGroup();
+ buttonGroup.add(defaultButton);
+ buttonGroup.add(overrideButton);
+
+ // Select ignition event
+ //// Ignition at:
+ panel.add(new JLabel(trans.get("MotorCfg.lbl.Ignitionat")), "");
+
+ final JComboBox event = new JComboBox(new EnumModel(newConfiguration, "IgnitionEvent"));
+ panel.add(event, "growx, wrap");
+
+ // ... and delay
+ //// plus
+ panel.add(new JLabel(trans.get("MotorCfg.lbl.plus")), "gap indent, skip 1, span, split");
+
+ DoubleModel delay = new DoubleModel(newConfiguration, "IgnitionDelay", UnitGroup.UNITS_SHORT_TIME, 0);
+ JSpinner spin = new JSpinner(delay.getSpinnerModel());
+ spin.setEditor(new SpinnerEditor(spin, 3));
+ panel.add(spin, "gap rel rel");
+
+ //// seconds
+ panel.add(new JLabel(trans.get("MotorCfg.lbl.seconds")), "wrap unrel");
+
+
+ panel.add(new JPanel(), "span, split, growx");
+
+ JButton okButton = new JButton(trans.get("button.ok"));
+ okButton.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ if (defaultButton.isSelected()) {
+ component.getIgnitionConfiguration().setDefault(newConfiguration);
+ } else {
+ component.getIgnitionConfiguration().set(id, newConfiguration);
+ }
+ IgnitionSelectionDialog.this.setVisible(false);
+ }
+ });
+
+ panel.add(okButton, "sizegroup btn");
+
+ JButton cancel = new JButton(trans.get("button.cancel"));
+ cancel.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ IgnitionSelectionDialog.this.setVisible(false);
+ }
+ });
+
+ panel.add(cancel, "sizegroup btn");
+
+ this.setContentPane(panel);
+
+ GUIUtil.setDisposableDialogOptions(this, okButton);
+ }
+}
diff --git a/core/src/net/sf/openrocket/gui/dialogs/flightconfiguration/MotorConfigurationPanel.java b/core/src/net/sf/openrocket/gui/dialogs/flightconfiguration/MotorConfigurationPanel.java
index 5308d06b9..4ce43ffc6 100644
--- a/core/src/net/sf/openrocket/gui/dialogs/flightconfiguration/MotorConfigurationPanel.java
+++ b/core/src/net/sf/openrocket/gui/dialogs/flightconfiguration/MotorConfigurationPanel.java
@@ -22,6 +22,7 @@ import net.sf.openrocket.gui.dialogs.motor.MotorChooserDialog;
import net.sf.openrocket.gui.util.GUIUtil;
import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.motor.Motor;
+import net.sf.openrocket.rocketcomponent.MotorConfiguration;
import net.sf.openrocket.rocketcomponent.MotorMount;
import net.sf.openrocket.rocketcomponent.Rocket;
import net.sf.openrocket.rocketcomponent.RocketComponent;
@@ -87,6 +88,7 @@ public class MotorConfigurationPanel extends JPanel {
public void mouseClicked(MouseEvent e) {
updateButtonState();
if (e.getClickCount() == 2) {
+ // FIXME: Double-click on ignition column should select ignition
// Double-click edits motor
selectMotor();
}
@@ -177,23 +179,27 @@ public class MotorConfigurationPanel extends JPanel {
}
private void selectMotor() {
- String currentID = rocket.getDefaultConfiguration().getFlightConfigurationID();
- MotorMount currentMount = getCurrentMount();
- if (currentID == null || currentMount == null)
+ String id = rocket.getDefaultConfiguration().getFlightConfigurationID();
+ MotorMount mount = getCurrentMount();
+ if (id == null || mount == null)
return;
+ MotorConfiguration config = mount.getMotorConfiguration().get(id);
+
MotorChooserDialog dialog = new MotorChooserDialog(
- currentMount.getMotor(currentID),
- currentMount.getMotorDelay(currentID),
- currentMount.getMotorMountDiameter(),
+ config.getMotor(),
+ config.getEjectionDelay(),
+ mount.getMotorMountDiameter(),
flightConfigurationDialog);
dialog.setVisible(true);
Motor m = dialog.getSelectedMotor();
double d = dialog.getSelectedDelay();
if (m != null) {
- currentMount.setMotor(currentID, m);
- currentMount.setMotorDelay(currentID, d);
+ config = new MotorConfiguration();
+ config.setMotor(m);
+ config.setEjectionDelay(d);
+ mount.getMotorConfiguration().set(id, config);
}
flightConfigurationDialog.fireContentsUpdated();
@@ -202,12 +208,12 @@ public class MotorConfigurationPanel extends JPanel {
}
private void removeMotor() {
- String currentID = rocket.getDefaultConfiguration().getFlightConfigurationID();
- MotorMount currentMount = getCurrentMount();
- if (currentID == null || currentMount == null)
+ String id = rocket.getDefaultConfiguration().getFlightConfigurationID();
+ MotorMount mount = getCurrentMount();
+ if (id == null || mount == null)
return;
- currentMount.setMotor(currentID, null);
+ mount.getMotorConfiguration().resetDefault(id);
flightConfigurationDialog.fireContentsUpdated();
configurationTableModel.fireTableDataChanged();
@@ -220,7 +226,7 @@ public class MotorConfigurationPanel extends JPanel {
if (currentID == null || currentMount == null)
return;
- SelectIgnitionConfigDialog dialog = new SelectIgnitionConfigDialog(
+ IgnitionSelectionDialog dialog = new IgnitionSelectionDialog(
this.flightConfigurationDialog,
rocket,
currentMount);
diff --git a/core/src/net/sf/openrocket/gui/dialogs/flightconfiguration/MotorConfigurationTableModel.java b/core/src/net/sf/openrocket/gui/dialogs/flightconfiguration/MotorConfigurationTableModel.java
index 10919d939..ce900e72f 100644
--- a/core/src/net/sf/openrocket/gui/dialogs/flightconfiguration/MotorConfigurationTableModel.java
+++ b/core/src/net/sf/openrocket/gui/dialogs/flightconfiguration/MotorConfigurationTableModel.java
@@ -19,12 +19,12 @@ import net.sf.openrocket.util.Coordinate;
*/
class MotorConfigurationTableModel extends AbstractTableModel {
- private Translator trans = Application.getTranslator();
+ private static final Translator trans = Application.getTranslator();
- private final static String NONE = FlightConfigurationDialog.trans.get("edtmotorconfdlg.tbl.None");
- private final static String MOTOR_MOUNT = FlightConfigurationDialog.trans.get("edtmotorconfdlg.tbl.Mountheader");
- private final static String MOTOR = FlightConfigurationDialog.trans.get("edtmotorconfdlg.tbl.Motorheader");
- private final static String IGNITION = FlightConfigurationDialog.trans.get("edtmotorconfdlg.tbl.Ignitionheader");
+ private static final String NONE = trans.get("edtmotorconfdlg.tbl.None");
+ private static final String MOTOR_MOUNT = trans.get("edtmotorconfdlg.tbl.Mountheader");
+ private static final String MOTOR = trans.get("edtmotorconfdlg.tbl.Motorheader");
+ private static final String IGNITION = trans.get("edtmotorconfdlg.tbl.Ignitionheader");
private final Rocket rocket;
@@ -63,13 +63,14 @@ class MotorConfigurationTableModel extends AbstractTableModel {
}
case 1: {
MotorMount mount = findMount(row);
- String currentID = rocket.getDefaultConfiguration().getFlightConfigurationID();
- Motor motor = mount.getMotor(currentID);
+ String id = rocket.getDefaultConfiguration().getFlightConfigurationID();
+ MotorConfiguration config = mount.getMotorConfiguration().get(id);
+ Motor motor = config.getMotor();
if (motor == null)
return NONE;
- String str = motor.getDesignation(mount.getMotorDelay(currentID));
+ String str = motor.getDesignation(config.getEjectionDelay());
int count = getMountMultiplicity(mount);
if (count > 1) {
str = "" + count + Chars.TIMES + " " + str;
@@ -124,26 +125,16 @@ class MotorConfigurationTableModel extends AbstractTableModel {
private String getIgnitionEventString(int row) {
- String currentID = rocket.getDefaultConfiguration().getFlightConfigurationID();
+ String id = rocket.getDefaultConfiguration().getFlightConfigurationID();
MotorMount mount = findMount(row);
- MotorConfiguration motorConfig = mount.getFlightConfiguration(currentID);
- if (motorConfig == null) {
- return NONE;
- }
+ IgnitionConfiguration ignitionConfig = mount.getIgnitionConfiguration().get(id);
- IgnitionConfiguration.IgnitionEvent ignition = motorConfig.getIgnitionEvent();
- Double ignitionDelay = motorConfig.getIgnitionDelay();
- boolean isDefault = (ignition == null);
+ IgnitionConfiguration.IgnitionEvent ignitionEvent = ignitionConfig.getIgnitionEvent();
+ Double ignitionDelay = ignitionConfig.getIgnitionDelay();
+ boolean isDefault = mount.getIgnitionConfiguration().isDefault(id);
- if (ignition == null) {
- ignition = mount.getDefaultIgnitionEvent();
- }
- if (ignitionDelay == null) {
- ignitionDelay = mount.getDefaultIgnitionDelay();
- }
-
- String str = trans.get("MotorMount.IgnitionEvent.short." + ignition.name());
- if (ignitionDelay > 0) {
+ String str = trans.get("MotorMount.IgnitionEvent.short." + ignitionEvent.name());
+ if (ignitionDelay > 0.001) {
str = str + " + " + UnitGroup.UNITS_SHORT_TIME.toStringUnit(ignitionDelay);
}
if (isDefault) {
diff --git a/core/src/net/sf/openrocket/gui/dialogs/flightconfiguration/RecoveryConfigurationPanel.java b/core/src/net/sf/openrocket/gui/dialogs/flightconfiguration/RecoveryConfigurationPanel.java
index c313da3e5..939ca1029 100644
--- a/core/src/net/sf/openrocket/gui/dialogs/flightconfiguration/RecoveryConfigurationPanel.java
+++ b/core/src/net/sf/openrocket/gui/dialogs/flightconfiguration/RecoveryConfigurationPanel.java
@@ -15,60 +15,57 @@ import javax.swing.ListSelectionModel;
import javax.swing.table.AbstractTableModel;
import net.miginfocom.swing.MigLayout;
+import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.rocketcomponent.DeploymentConfiguration;
+import net.sf.openrocket.rocketcomponent.DeploymentConfiguration.DeployEvent;
import net.sf.openrocket.rocketcomponent.RecoveryDevice;
import net.sf.openrocket.rocketcomponent.Rocket;
import net.sf.openrocket.rocketcomponent.RocketComponent;
+import net.sf.openrocket.startup.Application;
+import net.sf.openrocket.unit.UnitGroup;
public class RecoveryConfigurationPanel extends JPanel {
-
+
+ private Translator trans = Application.getTranslator();
+
+
private final FlightConfigurationDialog flightConfigurationDialog;
private final Rocket rocket;
private final RecoveryTableModel recoveryTableModel;
+ private final JTable recoveryTable;
private final JButton selectDeploymentButton;
private final JButton resetDeploymentButton;
- private RecoveryDevice selectedComponent;
-
- RecoveryConfigurationPanel( FlightConfigurationDialog flightConfigurationDialog, Rocket rocket ) {
- super( new MigLayout("fill") );
+
+ RecoveryConfigurationPanel(FlightConfigurationDialog flightConfigurationDialog, Rocket rocket) {
+ super(new MigLayout("fill"));
this.flightConfigurationDialog = flightConfigurationDialog;
this.rocket = rocket;
-
+
//// Recovery selection
recoveryTableModel = new RecoveryTableModel();
- JTable table = new JTable( recoveryTableModel );
- table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
- table.setRowSelectionAllowed(true);
- table.addMouseListener(new MouseAdapter() {
+ recoveryTable = new JTable(recoveryTableModel);
+ recoveryTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+ recoveryTable.setRowSelectionAllowed(true);
+ recoveryTable.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
JTable table = (JTable) e.getComponent();
- int row = table.getSelectedRow();
-
- if ( row >= 0 ) {
- selectedComponent = findRecoveryDevice(row);
- } else {
- selectedComponent = null;
- }
-
- if (e.getClickCount() == 1) {
- // Single click updates selection
- updateButtonState();
- } else if (e.getClickCount() == 2) {
+ updateButtonState();
+
+ if (e.getClickCount() == 2) {
// Double-click edits
selectDeployment();
}
-
}
});
-
- JScrollPane scroll = new JScrollPane(table);
+
+ JScrollPane scroll = new JScrollPane(recoveryTable);
this.add(scroll, "span, grow, wrap");
-
+
//// Select deployment
- selectDeploymentButton = new JButton(FlightConfigurationDialog.trans.get("edtmotorconfdlg.but.Selectdeployment"));
+ selectDeploymentButton = new JButton(trans.get("edtmotorconfdlg.but.Selectdeployment"));
selectDeploymentButton.setEnabled(false);
selectDeploymentButton.addActionListener(new ActionListener() {
@Override
@@ -77,9 +74,9 @@ public class RecoveryConfigurationPanel extends JPanel {
}
});
this.add(selectDeploymentButton, "skip, split, sizegroup button");
-
+
//// Reset deployment
- resetDeploymentButton = new JButton(FlightConfigurationDialog.trans.get("edtmotorconfdlg.but.Resetdeployment"));
+ resetDeploymentButton = new JButton(trans.get("edtmotorconfdlg.but.Resetdeployment"));
resetDeploymentButton.setEnabled(false);
resetDeploymentButton.addActionListener(new ActionListener() {
@Override
@@ -87,100 +84,127 @@ public class RecoveryConfigurationPanel extends JPanel {
resetDeployment();
}
});
- this.add(resetDeploymentButton,"sizegroup button, wrap");
-
+ this.add(resetDeploymentButton, "sizegroup button, wrap");
}
public void fireTableDataChanged() {
- selectedComponent = null;
recoveryTableModel.fireTableDataChanged();
updateButtonState();
}
private void selectDeployment() {
- JDialog d = new SelectDeploymentConfigDialog( flightConfigurationDialog, rocket, selectedComponent );
+ RecoveryDevice c = getSelectedComponent();
+ if (c == null) {
+ return;
+ }
+ JDialog d = new DeploymentSelectionDialog(flightConfigurationDialog, rocket, c);
d.setVisible(true);
fireTableDataChanged();
}
private void resetDeployment() {
- selectedComponent.setFlightConfiguration(rocket.getDefaultConfiguration().getFlightConfigurationID(), null);
+ RecoveryDevice c = getSelectedComponent();
+ if (c == null) {
+ return;
+ }
+ String id = rocket.getDefaultConfiguration().getFlightConfigurationID();
+ c.getDeploymentConfiguration().resetDefault(id);
fireTableDataChanged();
}
public void updateButtonState() {
- boolean componentSelected = selectedComponent != null;
- boolean isDefaulted = true;
- if ( componentSelected ) {
- isDefaulted = selectedComponent.getFlightConfiguration(rocket.getDefaultConfiguration().getFlightConfigurationID()) == null;
- }
+ boolean componentSelected = getSelectedComponent() != null;
selectDeploymentButton.setEnabled(componentSelected);
- resetDeploymentButton.setEnabled(componentSelected & ! isDefaulted);
+ resetDeploymentButton.setEnabled(componentSelected);
}
- private RecoveryDevice findRecoveryDevice( int count ) {
+
+ private RecoveryDevice getSelectedComponent() {
+ int row = recoveryTable.getSelectedRow();
+ return findRecoveryDevice(row);
+ }
+
+ private RecoveryDevice findRecoveryDevice(int count) {
RecoveryDevice d = null;
Iterator it = rocket.iterator();
- while( it.hasNext() && count >= 0 ) {
+ while (it.hasNext() && count >= 0) {
RocketComponent c = it.next();
- if ( c instanceof RecoveryDevice ) {
+ if (c instanceof RecoveryDevice) {
d = (RecoveryDevice) c;
count--;
}
}
return d;
}
-
+
+
+
private class RecoveryTableModel extends AbstractTableModel {
-
+
@Override
public int getRowCount() {
int count = 0;
Iterator it = rocket.iterator();
- while( it.hasNext() ) {
+ while (it.hasNext()) {
RocketComponent c = it.next();
- if ( c instanceof RecoveryDevice ) {
- count ++;
+ if (c instanceof RecoveryDevice) {
+ count++;
}
}
return count;
}
-
+
@Override
public int getColumnCount() {
return 2;
}
-
+
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
- RecoveryDevice d = RecoveryConfigurationPanel.this.findRecoveryDevice(rowIndex);
- switch ( columnIndex ) {
+ RecoveryDevice d = findRecoveryDevice(rowIndex);
+ switch (columnIndex) {
case 0:
return d.getName();
case 1:
- DeploymentConfiguration deployConfig = d.getFlightConfiguration(rocket.getDefaultConfiguration().getFlightConfigurationID());
- if ( deployConfig == null ) {
- return "[" + d.getDefaultFlightConfiguration().toString() + "]";
- } else {
- return deployConfig.toString();
+ String id = rocket.getDefaultConfiguration().getFlightConfigurationID();
+ DeploymentConfiguration config = d.getDeploymentConfiguration().get(id);
+ boolean isDefault = d.getDeploymentConfiguration().isDefault(id);
+
+ String str;
+
+ str = trans.get("RecoveryDevice.DeployEvent.short." + config.getDeployEvent().name());
+ if (config.getDeployEvent() == DeployEvent.ALTITUDE) {
+ str += " " + UnitGroup.UNITS_DISTANCE.toStringUnit(config.getDeployAltitude());
}
+ if (config.getDeployDelay() > 0.001) {
+ str += " + " + UnitGroup.UNITS_SHORT_TIME.toStringUnit(config.getDeployDelay());
+ }
+
+
+ if (isDefault) {
+ String def = trans.get("table.deployment.default");
+ str = def.replace("{0}", str);
+ }
+ return str;
+
+ default:
+ throw new IndexOutOfBoundsException("columnIndex=" + columnIndex);
}
- return null;
}
-
+
@Override
public String getColumnName(int column) {
- switch ( column ) {
+ switch (column) {
case 0:
- return FlightConfigurationDialog.trans.get("edtmotorconfdlg.tbl.Recoveryheader");
+ return trans.get("edtmotorconfdlg.tbl.Recoveryheader");
case 1:
- return FlightConfigurationDialog.trans.get("edtmotorconfdlg.tbl.Deploymentheader");
+ return trans.get("edtmotorconfdlg.tbl.Deploymentheader");
default:
return "";
}
}
-
+
}
-
+
}
diff --git a/core/src/net/sf/openrocket/gui/dialogs/flightconfiguration/RenameConfigDialog.java b/core/src/net/sf/openrocket/gui/dialogs/flightconfiguration/RenameConfigDialog.java
index 16b56e0f9..df2845118 100644
--- a/core/src/net/sf/openrocket/gui/dialogs/flightconfiguration/RenameConfigDialog.java
+++ b/core/src/net/sf/openrocket/gui/dialogs/flightconfiguration/RenameConfigDialog.java
@@ -10,23 +10,27 @@ import javax.swing.JPanel;
import javax.swing.JTextArea;
import net.miginfocom.swing.MigLayout;
+import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.rocketcomponent.Configuration;
import net.sf.openrocket.rocketcomponent.Rocket;
+import net.sf.openrocket.startup.Application;
public class RenameConfigDialog extends JDialog {
- RenameConfigDialog( final Rocket rocket, final FlightConfigurationDialog parent ) {
- super(parent, FlightConfigurationDialog.trans.get("edtmotorconfdlg.title.Renameconf"),Dialog.ModalityType.APPLICATION_MODAL);
+ private static final Translator trans = Application.getTranslator();
+
+ RenameConfigDialog(final FlightConfigurationDialog parent, final Rocket rocket) {
+ super(parent, trans.get("edtmotorconfdlg.title.Renameconf"), Dialog.ModalityType.APPLICATION_MODAL);
final Configuration config = rocket.getDefaultConfiguration();
JPanel panel = new JPanel(new MigLayout("fill"));
- final JTextArea textbox = new JTextArea( config.getFlightConfigurationDescription() );
+ final JTextArea textbox = new JTextArea(config.getFlightConfigurationDescription());
panel.add(textbox, "span, w 200lp, wrap");
JButton okButton = new JButton("Ok");
- okButton.addActionListener( new ActionListener() {
-
+ okButton.addActionListener(new ActionListener() {
+
@Override
public void actionPerformed(ActionEvent e) {
parent.changeConfigurationName(textbox.getText());
@@ -35,11 +39,11 @@ public class RenameConfigDialog extends JDialog {
});
- panel.add( okButton );
+ panel.add(okButton);
JButton defaultButton = new JButton("Reset to default");
- defaultButton.addActionListener( new ActionListener() {
-
+ defaultButton.addActionListener(new ActionListener() {
+
@Override
public void actionPerformed(ActionEvent e) {
parent.changeConfigurationName(null);
@@ -48,11 +52,11 @@ public class RenameConfigDialog extends JDialog {
});
- panel.add( defaultButton );
+ panel.add(defaultButton);
JButton cancel = new JButton("Cancel");
- cancel.addActionListener( new ActionListener() {
-
+ cancel.addActionListener(new ActionListener() {
+
@Override
public void actionPerformed(ActionEvent e) {
RenameConfigDialog.this.setVisible(false);
@@ -60,13 +64,13 @@ public class RenameConfigDialog extends JDialog {
});
- panel.add( cancel );
-
+ panel.add(cancel);
+
this.setContentPane(panel);
this.validate();
this.pack();
this.setLocationByPlatform(true);
-
+
}
-
+
}
diff --git a/core/src/net/sf/openrocket/gui/dialogs/flightconfiguration/SelectDeploymentConfigDialog.java b/core/src/net/sf/openrocket/gui/dialogs/flightconfiguration/SelectDeploymentConfigDialog.java
deleted file mode 100644
index cb754c156..000000000
--- a/core/src/net/sf/openrocket/gui/dialogs/flightconfiguration/SelectDeploymentConfigDialog.java
+++ /dev/null
@@ -1,145 +0,0 @@
-package net.sf.openrocket.gui.dialogs.flightconfiguration;
-
-import java.awt.Dialog;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-
-import javax.swing.JButton;
-import javax.swing.JComboBox;
-import javax.swing.JDialog;
-import javax.swing.JLabel;
-import javax.swing.JPanel;
-import javax.swing.JSpinner;
-
-import net.miginfocom.swing.MigLayout;
-import net.sf.openrocket.gui.SpinnerEditor;
-import net.sf.openrocket.gui.adaptors.BasicEnumModel;
-import net.sf.openrocket.gui.adaptors.DoubleModel;
-import net.sf.openrocket.gui.components.BasicSlider;
-import net.sf.openrocket.gui.components.UnitSelector;
-import net.sf.openrocket.rocketcomponent.DeploymentConfiguration;
-import net.sf.openrocket.rocketcomponent.DeploymentConfiguration.DeployEvent;
-import net.sf.openrocket.rocketcomponent.RecoveryDevice;
-import net.sf.openrocket.rocketcomponent.Rocket;
-import net.sf.openrocket.unit.UnitGroup;
-
-public class SelectDeploymentConfigDialog extends JDialog {
-
- DeploymentConfiguration newConfiguration;
-
-
- SelectDeploymentConfigDialog( JDialog parent, final Rocket rocket, final RecoveryDevice component ) {
- super(parent, FlightConfigurationDialog.trans.get("edtmotorconfdlg.title.Selectdeploymentconf"),Dialog.ModalityType.APPLICATION_MODAL);
-
- final String configId = rocket.getDefaultConfiguration().getFlightConfigurationID();
-
- newConfiguration = component.getFlightConfiguration(configId);
- if ( newConfiguration == null ) {
- newConfiguration = component.getDefaultFlightConfiguration().clone();
- } else {
- // Clone the existing so cancel works. When the user selects OK, this configuration
- // is put back in there.
- newConfiguration = newConfiguration.clone();
- }
-
- JPanel panel = new JPanel(new MigLayout("fill"));
-
- //// Deployment
- //// Deploys at:
- panel.add(new JLabel(FlightConfigurationDialog.trans.get("ParachuteCfg.lbl.Deploysat")), "");
-
- final JComboBox event = new JComboBox(new BasicEnumModel(DeployEvent.class));
- event.setSelectedItem( newConfiguration.getDeployEvent() );
- panel.add(event, "spanx 3, growx, wrap");
-
- // ... and delay
- //// plus
- panel.add(new JLabel(FlightConfigurationDialog.trans.get("ParachuteCfg.lbl.plusdelay")), "right");
-
- final DoubleModel delay = new DoubleModel(newConfiguration.getDeployDelay(), UnitGroup.UNITS_NONE, 0);
- final JSpinner delaySpinner = new JSpinner( delay.getSpinnerModel() );
- delaySpinner.setEditor(new SpinnerEditor(delaySpinner,3));
- panel.add(delaySpinner, "spanx, split");
-
- //// seconds
- panel.add(new JLabel(FlightConfigurationDialog.trans.get("ParachuteCfg.lbl.seconds")), "wrap paragraph");
-
- // Altitude:
- JLabel label = new JLabel(FlightConfigurationDialog.trans.get("ParachuteCfg.lbl.Altitude"));
- panel.add(label);
-
- final DoubleModel alt = new DoubleModel(newConfiguration.getDeployAltitude(), UnitGroup.UNITS_DISTANCE, 0);
-
- final JSpinner altSpinner = new JSpinner(alt.getSpinnerModel());
- altSpinner.setEditor(new SpinnerEditor(altSpinner));
- panel.add(altSpinner, "growx");
- UnitSelector unit = new UnitSelector(alt);
- panel.add(unit, "growx");
- BasicSlider slider = new BasicSlider(alt.getSliderModel(100, 1000));
- panel.add(slider, "w 100lp, wrap");
-
- event.addActionListener( new ActionListener() {
-
- @Override
- public void actionPerformed(ActionEvent e) {
- if ( event.getSelectedItem() == DeployEvent.ALTITUDE ) {
- altSpinner.setEnabled(true);
- } else {
- altSpinner.setEnabled(false);
- }
-
- }
-
- });
-
- // Set the value of the combo box at the end to take advantage of the action listener above.
- event.setSelectedItem( newConfiguration.getDeployEvent() );
-
- JButton okButton = new JButton(FlightConfigurationDialog.trans.get("button.ok"));
- okButton.addActionListener( new ActionListener() {
-
- @Override
- public void actionPerformed(ActionEvent e) {
-
- //// extract deployment type;
- DeployEvent deployEvent = (DeployEvent) event.getSelectedItem();
- newConfiguration.setDeployEvent(deployEvent);
-
- //// extract deployment time;
- double deployDelay = delay.getValue();
- newConfiguration.setDeployDelay(deployDelay);
-
- //// extract altitude;
- double deployAltitude = alt.getValue();
- newConfiguration.setDeployAltitude(deployAltitude);
-
- component.setFlightConfiguration(configId, newConfiguration);
-
- SelectDeploymentConfigDialog.this.setVisible(false);
- }
-
- });
-
- panel.add( okButton );
-
- JButton cancel = new JButton(FlightConfigurationDialog.trans.get("button.cancel"));
- cancel.addActionListener( new ActionListener() {
-
- @Override
- public void actionPerformed(ActionEvent e) {
- SelectDeploymentConfigDialog.this.setVisible(false);
- }
-
- });
-
- panel.add( cancel );
-
- this.setContentPane(panel);
- this.validate();
- this.pack();
- this.setLocationByPlatform(true);
-
- }
-
-
-}
diff --git a/core/src/net/sf/openrocket/gui/dialogs/flightconfiguration/SelectIgnitionConfigDialog.java b/core/src/net/sf/openrocket/gui/dialogs/flightconfiguration/SelectIgnitionConfigDialog.java
deleted file mode 100644
index 94a4e23cd..000000000
--- a/core/src/net/sf/openrocket/gui/dialogs/flightconfiguration/SelectIgnitionConfigDialog.java
+++ /dev/null
@@ -1,116 +0,0 @@
-package net.sf.openrocket.gui.dialogs.flightconfiguration;
-
-import java.awt.Dialog;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-
-import javax.swing.JButton;
-import javax.swing.JComboBox;
-import javax.swing.JDialog;
-import javax.swing.JLabel;
-import javax.swing.JPanel;
-import javax.swing.JSpinner;
-
-import net.miginfocom.swing.MigLayout;
-import net.sf.openrocket.gui.SpinnerEditor;
-import net.sf.openrocket.gui.adaptors.BasicEnumModel;
-import net.sf.openrocket.gui.adaptors.DoubleModel;
-import net.sf.openrocket.rocketcomponent.IgnitionConfiguration;
-import net.sf.openrocket.rocketcomponent.IgnitionConfiguration.IgnitionEvent;
-import net.sf.openrocket.rocketcomponent.MotorConfiguration;
-import net.sf.openrocket.rocketcomponent.MotorMount;
-import net.sf.openrocket.rocketcomponent.Rocket;
-import net.sf.openrocket.unit.UnitGroup;
-
-public class SelectIgnitionConfigDialog extends JDialog {
-
- MotorConfiguration newConfiguration;
-
- SelectIgnitionConfigDialog(JDialog parent, final Rocket rocket, final MotorMount component) {
- super(parent, FlightConfigurationDialog.trans.get("edtmotorconfdlg.title.Selectignitionconf"), Dialog.ModalityType.APPLICATION_MODAL);
- final String configId = rocket.getDefaultConfiguration().getFlightConfigurationID();
-
- newConfiguration = component.getFlightConfiguration(configId);
- if (newConfiguration == null) {
- newConfiguration = component.getDefaultFlightConfiguration().clone();
- } else {
- // Clone the existing so cancel works. When the user selects OK, this configuration
- // is put back in there.
- newConfiguration = newConfiguration.clone();
- }
- // MotorConfiguration is a little wierd. It is possible for the MotorConfiguration
- // to be non-null (for example, a motor is selected) but the ignition spec is null
- // (ignition is not overridden). In order to accomodate this, we need to test
- // for IgnitionEvent and copy from the default config.
- if (newConfiguration.getIgnitionEvent() == null) {
- MotorConfiguration oldConfig = component.getDefaultFlightConfiguration();
- newConfiguration.setIgnitionDelay(oldConfig.getIgnitionDelay());
- newConfiguration.setIgnitionEvent(oldConfig.getIgnitionEvent());
- }
-
- JPanel panel = new JPanel(new MigLayout("fill"));
-
- // Select ignition event
- //// Ignition at:
- panel.add(new JLabel(FlightConfigurationDialog.trans.get("MotorCfg.lbl.Ignitionat")), "");
-
- final JComboBox event = new JComboBox(new BasicEnumModel(IgnitionConfiguration.IgnitionEvent.class));
- event.setSelectedItem(newConfiguration.getIgnitionEvent());
- panel.add(event, "growx, wrap");
-
- // ... and delay
- //// plus
- panel.add(new JLabel(FlightConfigurationDialog.trans.get("MotorCfg.lbl.plus")), "gap indent, skip 1, span, split");
-
- Double delayValue = newConfiguration.getIgnitionDelay();
- final DoubleModel delay = new DoubleModel((delayValue == null ? 0 : delayValue.doubleValue()), UnitGroup.UNITS_NONE, 0d);
- JSpinner spin = new JSpinner(delay.getSpinnerModel());
- spin.setEditor(new SpinnerEditor(spin, 3));
- panel.add(spin, "gap rel rel");
-
- //// seconds
- panel.add(new JLabel(FlightConfigurationDialog.trans.get("MotorCfg.lbl.seconds")), "wrap unrel");
-
- JButton okButton = new JButton(FlightConfigurationDialog.trans.get("button.ok"));
- okButton.addActionListener(new ActionListener() {
-
- @Override
- public void actionPerformed(ActionEvent e) {
-
- //// extract ignition event type;
- IgnitionConfiguration.IgnitionEvent ignitionEvent = (IgnitionConfiguration.IgnitionEvent) event.getSelectedItem();
- newConfiguration.setIgnitionEvent(ignitionEvent);
-
- //// extract ignition delay time;
- double ignitionDelay = delay.getValue();
- newConfiguration.setIgnitionDelay(ignitionDelay);
-
-
- component.setFlightConfiguration(configId, newConfiguration);
-
- SelectIgnitionConfigDialog.this.setVisible(false);
- }
-
- });
-
- panel.add(okButton);
-
- JButton cancel = new JButton(FlightConfigurationDialog.trans.get("button.cancel"));
- cancel.addActionListener(new ActionListener() {
-
- @Override
- public void actionPerformed(ActionEvent e) {
- SelectIgnitionConfigDialog.this.setVisible(false);
- }
-
- });
-
- panel.add(cancel);
-
- this.setContentPane(panel);
- this.validate();
- this.pack();
- this.setLocationByPlatform(true);
-
- }
-}
diff --git a/core/src/net/sf/openrocket/gui/dialogs/flightconfiguration/SelectSeparationConfigDialog.java b/core/src/net/sf/openrocket/gui/dialogs/flightconfiguration/SelectSeparationConfigDialog.java
deleted file mode 100644
index 1d761aa2c..000000000
--- a/core/src/net/sf/openrocket/gui/dialogs/flightconfiguration/SelectSeparationConfigDialog.java
+++ /dev/null
@@ -1,107 +0,0 @@
-package net.sf.openrocket.gui.dialogs.flightconfiguration;
-
-import java.awt.Dialog;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-
-import javax.swing.JButton;
-import javax.swing.JComboBox;
-import javax.swing.JDialog;
-import javax.swing.JLabel;
-import javax.swing.JPanel;
-import javax.swing.JSpinner;
-
-import net.miginfocom.swing.MigLayout;
-import net.sf.openrocket.gui.SpinnerEditor;
-import net.sf.openrocket.gui.adaptors.BasicEnumModel;
-import net.sf.openrocket.gui.adaptors.DoubleModel;
-import net.sf.openrocket.gui.components.StyledLabel;
-import net.sf.openrocket.gui.components.StyledLabel.Style;
-import net.sf.openrocket.rocketcomponent.Rocket;
-import net.sf.openrocket.rocketcomponent.Stage;
-import net.sf.openrocket.rocketcomponent.StageSeparationConfiguration;
-import net.sf.openrocket.rocketcomponent.StageSeparationConfiguration.SeparationEvent;
-import net.sf.openrocket.unit.UnitGroup;
-
-public class SelectSeparationConfigDialog extends JDialog {
-
- StageSeparationConfiguration newConfiguration;
-
- SelectSeparationConfigDialog( JDialog parent, final Rocket rocket, final Stage component ) {
- super(parent, FlightConfigurationDialog.trans.get("edtmotorconfdlg.title.Selectseparationconf"),Dialog.ModalityType.APPLICATION_MODAL);
- final String configId = rocket.getDefaultConfiguration().getFlightConfigurationID();
-
- newConfiguration = component.getFlightConfiguration(configId);
- if ( newConfiguration == null ) {
- newConfiguration = component.getDefaultFlightConfiguration().clone();
- } else {
- // Clone the existing so cancel works. When the user selects OK, this configuration
- // is put back in there.
- newConfiguration = newConfiguration.clone();
- }
-
- JPanel panel = new JPanel(new MigLayout("fill"));
-
- // Select separation event
- panel.add(new StyledLabel(FlightConfigurationDialog.trans.get("StageConfig.separation.lbl.title"), Style.BOLD), "spanx, wrap rel");
-
- final JComboBox event = new JComboBox(new BasicEnumModel(SeparationEvent.class));
- event.setSelectedItem( newConfiguration.getSeparationEvent() );
- panel.add(event, "");
-
- // ... and delay
- panel.add(new JLabel(FlightConfigurationDialog.trans.get("StageConfig.separation.lbl.plus")), "");
-
- final DoubleModel delay = new DoubleModel(newConfiguration.getSeparationDelay(), UnitGroup.UNITS_NONE, 0);
- JSpinner spin = new JSpinner(delay.getSpinnerModel());
- spin.setEditor(new SpinnerEditor(spin));
- panel.add(spin, "width 45");
-
- //// seconds
- panel.add(new JLabel(FlightConfigurationDialog.trans.get("StageConfig.separation.lbl.seconds")), "wrap unrel");
-
-
- JButton okButton = new JButton(FlightConfigurationDialog.trans.get("button.ok"));
- okButton.addActionListener( new ActionListener() {
-
- @Override
- public void actionPerformed(ActionEvent e) {
-
- //// extract event type;
- SeparationEvent eventType = (SeparationEvent) event.getSelectedItem();
- newConfiguration.setSeparationEvent(eventType);
-
- //// extract delay time;
- double separationDelay = delay.getValue();
- newConfiguration.setSeparationDelay(separationDelay);
-
- component.setFlightConfiguration(configId, newConfiguration);
-
- SelectSeparationConfigDialog.this.setVisible(false);
- }
-
- });
-
- panel.add( okButton );
-
- JButton cancel = new JButton(FlightConfigurationDialog.trans.get("button.cancel"));
- cancel.addActionListener( new ActionListener() {
-
- @Override
- public void actionPerformed(ActionEvent e) {
- SelectSeparationConfigDialog.this.setVisible(false);
- }
-
- });
-
- panel.add( cancel );
-
- this.setContentPane(panel);
- this.validate();
- this.pack();
- this.setLocationByPlatform(true);
-
- }
-
-
-}
diff --git a/core/src/net/sf/openrocket/gui/dialogs/flightconfiguration/SeparationConfigurationPanel.java b/core/src/net/sf/openrocket/gui/dialogs/flightconfiguration/SeparationConfigurationPanel.java
index 4312e1e21..05be8b880 100644
--- a/core/src/net/sf/openrocket/gui/dialogs/flightconfiguration/SeparationConfigurationPanel.java
+++ b/core/src/net/sf/openrocket/gui/dialogs/flightconfiguration/SeparationConfigurationPanel.java
@@ -15,78 +15,74 @@ import javax.swing.ListSelectionModel;
import javax.swing.table.AbstractTableModel;
import net.miginfocom.swing.MigLayout;
+import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.rocketcomponent.Rocket;
import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.rocketcomponent.Stage;
import net.sf.openrocket.rocketcomponent.StageSeparationConfiguration;
+import net.sf.openrocket.rocketcomponent.StageSeparationConfiguration.SeparationEvent;
+import net.sf.openrocket.startup.Application;
public class SeparationConfigurationPanel extends JPanel {
-
+
+ private static final Translator trans = Application.getTranslator();
+
private final FlightConfigurationDialog flightConfigurationDialog;
private final Rocket rocket;
private final Stage[] stages;
-
+
+ private final JTable separationTable;
private final SeparationTableModel separationTableModel;
private final JButton selectSeparationButton;
private final JButton resetDeploymentButton;
-
- private Stage selectedComponent;
-
- SeparationConfigurationPanel( FlightConfigurationDialog flightConfigurationDialog, Rocket rocket ) {
- super( new MigLayout("fill") );
+
+
+ SeparationConfigurationPanel(FlightConfigurationDialog flightConfigurationDialog, Rocket rocket) {
+ super(new MigLayout("fill"));
this.flightConfigurationDialog = flightConfigurationDialog;
this.rocket = rocket;
-
- int stageCount = rocket.getStageCount() -1;
+
+
+ int stageCount = rocket.getStageCount() - 1;
stages = new Stage[stageCount];
Iterator it = rocket.iterator();
{
int stageIndex = -1;
- while( it.hasNext() ) {
+ while (it.hasNext()) {
RocketComponent c = it.next();
- if ( c instanceof Stage ) {
- if ( stageIndex >= 0 ){
+ if (c instanceof Stage) {
+ if (stageIndex >= 0) {
stages[stageIndex] = (Stage) c;
}
stageIndex++;
}
}
}
-
+
//// Recovery selection
separationTableModel = new SeparationTableModel();
- JTable table = new JTable( separationTableModel );
- table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
- table.setRowSelectionAllowed(true);
- table.addMouseListener(new MouseAdapter() {
+ separationTable = new JTable(separationTableModel);
+ separationTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+ separationTable.setRowSelectionAllowed(true);
+ separationTable.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
- JTable table = (JTable) e.getComponent();
- int row = table.getSelectedRow();
- int column = table.getSelectedColumn();
-
- if ( row >= 0 ) {
- selectedComponent = stages[row];
- } else {
- selectedComponent = null;
- }
-
if (e.getClickCount() == 1) {
+ // FIXME: Listen to selection change, not clicks
// Single click updates selection
updateButtonState();
} else if (e.getClickCount() == 2) {
// Double-click edits
selectDeployment();
}
-
}
});
-
- JScrollPane scroll = new JScrollPane(table);
+
+ JScrollPane scroll = new JScrollPane(separationTable);
this.add(scroll, "span, grow, wrap");
-
+
//// Select deployment
- selectSeparationButton = new JButton(FlightConfigurationDialog.trans.get("edtmotorconfdlg.but.Selectseparation"));
+ selectSeparationButton = new JButton(trans.get("edtmotorconfdlg.but.Selectseparation"));
selectSeparationButton.setEnabled(false);
selectSeparationButton.addActionListener(new ActionListener() {
@Override
@@ -95,9 +91,9 @@ public class SeparationConfigurationPanel extends JPanel {
}
});
this.add(selectSeparationButton, "skip, split, sizegroup button");
-
+
//// Reset deployment
- resetDeploymentButton = new JButton(FlightConfigurationDialog.trans.get("edtmotorconfdlg.but.Resetseparation"));
+ resetDeploymentButton = new JButton(trans.get("edtmotorconfdlg.but.Resetseparation"));
resetDeploymentButton.setEnabled(false);
resetDeploymentButton.addActionListener(new ActionListener() {
@Override
@@ -105,79 +101,100 @@ public class SeparationConfigurationPanel extends JPanel {
resetDeployment();
}
});
- this.add(resetDeploymentButton,"sizegroup button, wrap");
-
+ this.add(resetDeploymentButton, "sizegroup button, wrap");
+
}
-
+
public void fireTableDataChanged() {
- selectedComponent = null;
separationTableModel.fireTableDataChanged();
updateButtonState();
}
-
+
+ private Stage getSelectedStage() {
+ int row = separationTable.getSelectedRow();
+ if (row >= 0 && row < stages.length) {
+ return stages[row];
+ }
+ return null;
+ }
+
private void selectDeployment() {
- JDialog d = new SelectSeparationConfigDialog( flightConfigurationDialog, rocket, selectedComponent );
+ Stage stage = getSelectedStage();
+ if (stage == null) {
+ return;
+ }
+ JDialog d = new SeparationSelectionDialog(flightConfigurationDialog, rocket, stage);
d.setVisible(true);
fireTableDataChanged();
}
-
+
private void resetDeployment() {
- selectedComponent.setFlightConfiguration(rocket.getDefaultConfiguration().getFlightConfigurationID(), null);
+ Stage stage = getSelectedStage();
+ if (stage == null) {
+ return;
+ }
+ String id = rocket.getDefaultConfiguration().getFlightConfigurationID();
+ stage.getStageSeparationConfiguration().resetDefault(id);
fireTableDataChanged();
}
-
+
public void updateButtonState() {
- boolean componentSelected = selectedComponent != null;
- boolean isDefaulted = true;
- if ( componentSelected ) {
- isDefaulted = selectedComponent.getFlightConfiguration(rocket.getDefaultConfiguration().getFlightConfigurationID()) == null;
- }
+ boolean componentSelected = getSelectedStage() != null;
selectSeparationButton.setEnabled(componentSelected);
- resetDeploymentButton.setEnabled(componentSelected & ! isDefaulted);
+ resetDeploymentButton.setEnabled(componentSelected);
}
-
+
private class SeparationTableModel extends AbstractTableModel {
-
+
@Override
public int getRowCount() {
return stages.length;
}
-
+
@Override
public int getColumnCount() {
return 2;
}
-
+
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
Stage d = SeparationConfigurationPanel.this.stages[rowIndex];
- switch ( columnIndex ) {
+ switch (columnIndex) {
case 0:
return d.getName();
case 1:
- StageSeparationConfiguration separationConfig = d.getFlightConfiguration(rocket.getDefaultConfiguration().getFlightConfigurationID());
- if ( separationConfig == null ) {
- return "[" + d.getDefaultFlightConfiguration().toString() + "]";
+ String id = rocket.getDefaultConfiguration().getFlightConfigurationID();
+ StageSeparationConfiguration separationConfig = d.getStageSeparationConfiguration().get(id);
+
+ SeparationEvent event = separationConfig.getSeparationEvent();
+ String str = event.toString();
+
+ if (d.getStageSeparationConfiguration().isDefault(id)) {
+ str = trans.get("SeparationConfigurationPanel.table.separation.default");
+ str = str.replace("{0}", event.toString());
} else {
- return separationConfig.toString();
+ str = event.toString();
}
+ return str;
+
+ default:
+ throw new IndexOutOfBoundsException("column=" + columnIndex);
}
-
- return null;
+
}
-
+
@Override
public String getColumnName(int column) {
- switch ( column ) {
+ switch (column) {
case 0:
- return FlightConfigurationDialog.trans.get("edtmotorconfdlg.tbl.Stageheader");
+ return trans.get("edtmotorconfdlg.tbl.Stageheader");
case 1:
- return FlightConfigurationDialog.trans.get("edtmotorconfdlg.tbl.Separationheader");
+ return trans.get("edtmotorconfdlg.tbl.Separationheader");
default:
return "";
}
}
-
+
}
-
+
}
diff --git a/core/src/net/sf/openrocket/gui/dialogs/flightconfiguration/SeparationSelectionDialog.java b/core/src/net/sf/openrocket/gui/dialogs/flightconfiguration/SeparationSelectionDialog.java
new file mode 100644
index 000000000..daf6afddb
--- /dev/null
+++ b/core/src/net/sf/openrocket/gui/dialogs/flightconfiguration/SeparationSelectionDialog.java
@@ -0,0 +1,91 @@
+package net.sf.openrocket.gui.dialogs.flightconfiguration;
+
+import java.awt.Dialog;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+import javax.swing.JButton;
+import javax.swing.JComboBox;
+import javax.swing.JDialog;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JSpinner;
+
+import net.miginfocom.swing.MigLayout;
+import net.sf.openrocket.gui.SpinnerEditor;
+import net.sf.openrocket.gui.adaptors.DoubleModel;
+import net.sf.openrocket.gui.adaptors.EnumModel;
+import net.sf.openrocket.gui.util.GUIUtil;
+import net.sf.openrocket.l10n.Translator;
+import net.sf.openrocket.rocketcomponent.Rocket;
+import net.sf.openrocket.rocketcomponent.Stage;
+import net.sf.openrocket.rocketcomponent.StageSeparationConfiguration;
+import net.sf.openrocket.rocketcomponent.StageSeparationConfiguration.SeparationEvent;
+import net.sf.openrocket.startup.Application;
+import net.sf.openrocket.unit.UnitGroup;
+
+public class SeparationSelectionDialog extends JDialog {
+
+ private static final Translator trans = Application.getTranslator();
+
+ private StageSeparationConfiguration newConfiguration;
+
+ SeparationSelectionDialog(JDialog parent, final Rocket rocket, final Stage component) {
+ super(parent, trans.get("edtmotorconfdlg.title.Selectseparationconf"), Dialog.ModalityType.APPLICATION_MODAL);
+ final String id = rocket.getDefaultConfiguration().getFlightConfigurationID();
+
+ newConfiguration = component.getStageSeparationConfiguration().get(id).clone();
+
+
+ JPanel panel = new JPanel(new MigLayout("fill"));
+
+ // FIXME: Edit Default or override option
+
+ // Select separation event
+ panel.add(new JLabel(trans.get("SeparationSelectionDialog.lbl.separation")), "");
+
+ final JComboBox event = new JComboBox(new EnumModel(newConfiguration, "SeparationEvent"));
+ event.setSelectedItem(newConfiguration.getSeparationEvent());
+ panel.add(event, "wrap rel");
+
+ // ... and delay
+ panel.add(new JLabel(trans.get("StageConfig.separation.lbl.plus")), "alignx 100%");
+
+ final DoubleModel delay = new DoubleModel(newConfiguration, "SeparationDelay", UnitGroup.UNITS_SHORT_TIME, 0);
+ JSpinner spin = new JSpinner(delay.getSpinnerModel());
+ spin.setEditor(new SpinnerEditor(spin, 3));
+ panel.add(spin, "span, split");
+
+ //// seconds
+ panel.add(new JLabel(trans.get("StageConfig.separation.lbl.seconds")), "wrap para");
+
+
+ panel.add(new JPanel(), "span, split, growx");
+
+ JButton okButton = new JButton(trans.get("button.ok"));
+ okButton.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ component.getStageSeparationConfiguration().set(id, newConfiguration);
+ SeparationSelectionDialog.this.setVisible(false);
+ }
+ });
+
+ panel.add(okButton, "sizegroup btn");
+
+ JButton cancel = new JButton(trans.get("button.cancel"));
+ cancel.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ SeparationSelectionDialog.this.setVisible(false);
+ }
+ });
+
+ panel.add(cancel, "sizegroup btn");
+
+ this.setContentPane(panel);
+
+ GUIUtil.setDisposableDialogOptions(this, okButton);
+ }
+
+}
diff --git a/core/src/net/sf/openrocket/gui/dialogs/optimization/SimulationModifierTree.java b/core/src/net/sf/openrocket/gui/dialogs/optimization/SimulationModifierTree.java
index 663c79b83..c18c98060 100644
--- a/core/src/net/sf/openrocket/gui/dialogs/optimization/SimulationModifierTree.java
+++ b/core/src/net/sf/openrocket/gui/dialogs/optimization/SimulationModifierTree.java
@@ -119,8 +119,8 @@ public class SimulationModifierTree extends BasicTree {
}
-
-
+
+
public class ComponentModifierTreeRenderer extends DefaultTreeCellRenderer {
private Font componentFont;
private Font stringFont;
@@ -142,7 +142,7 @@ public class SimulationModifierTree extends BasicTree {
makeFonts();
}
-
+
// Customize based on line type
Object object = ((DefaultMutableTreeNode) value).getUserObject();
@@ -150,7 +150,7 @@ public class SimulationModifierTree extends BasicTree {
// Set icon (for rocket components, null for others)
setIcon(ComponentIcons.getSmallIcon(object.getClass()));
-
+
// Set text color/style
if (object instanceof RocketComponent) {
setForeground(Color.GRAY);
@@ -160,7 +160,7 @@ public class SimulationModifierTree extends BasicTree {
RocketComponent c = (RocketComponent) object;
String comment = c.getComment().trim();
if (comment.length() > 0) {
- comment = TextUtil.htmlEncode(comment);
+ comment = TextUtil.escapeXML(comment);
comment = "" + comment.replace("\n", "
");
this.setToolTipText(comment);
} else {
diff --git a/core/src/net/sf/openrocket/gui/main/componenttree/ComponentTreeRenderer.java b/core/src/net/sf/openrocket/gui/main/componenttree/ComponentTreeRenderer.java
index 6fe9fe1d9..de9982b58 100644
--- a/core/src/net/sf/openrocket/gui/main/componenttree/ComponentTreeRenderer.java
+++ b/core/src/net/sf/openrocket/gui/main/componenttree/ComponentTreeRenderer.java
@@ -48,7 +48,7 @@ public class ComponentTreeRenderer extends DefaultTreeCellRenderer {
String comment = c.getComment().trim();
if (comment.length() > 0) {
- comment = TextUtil.htmlEncode(comment);
+ comment = TextUtil.escapeXML(comment);
comment = comment.replace("\n", "
");
sb.append("
").append(comment);
}
diff --git a/core/src/net/sf/openrocket/optimization/services/DefaultSimulationModifierService.java b/core/src/net/sf/openrocket/optimization/services/DefaultSimulationModifierService.java
index 9a1f2405f..a04a3c1b1 100644
--- a/core/src/net/sf/openrocket/optimization/services/DefaultSimulationModifierService.java
+++ b/core/src/net/sf/openrocket/optimization/services/DefaultSimulationModifierService.java
@@ -14,7 +14,6 @@ import net.sf.openrocket.optimization.general.OptimizationException;
import net.sf.openrocket.optimization.rocketoptimization.SimulationModifier;
import net.sf.openrocket.optimization.rocketoptimization.modifiers.GenericComponentModifier;
import net.sf.openrocket.rocketcomponent.BodyTube;
-import net.sf.openrocket.rocketcomponent.DeploymentConfiguration.DeployEvent;
import net.sf.openrocket.rocketcomponent.EllipticalFinSet;
import net.sf.openrocket.rocketcomponent.FinSet;
import net.sf.openrocket.rocketcomponent.FreeformFinSet;
@@ -24,7 +23,6 @@ import net.sf.openrocket.rocketcomponent.MassComponent;
import net.sf.openrocket.rocketcomponent.MotorMount;
import net.sf.openrocket.rocketcomponent.NoseCone;
import net.sf.openrocket.rocketcomponent.Parachute;
-import net.sf.openrocket.rocketcomponent.RecoveryDevice;
import net.sf.openrocket.rocketcomponent.Rocket;
import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.rocketcomponent.Streamer;
@@ -243,29 +241,31 @@ public class DefaultSimulationModifierService implements SimulationModifierServi
}
+ // FIXME: Reimplement for flight-configuration controlled modifiers
+
// Recovery device deployment altitude and delay
- if (c instanceof RecoveryDevice) {
- RecoveryDevice device = (RecoveryDevice) c;
-
- SimulationModifier mod = new GenericComponentModifier(
- trans.get("optimization.modifier.recoverydevice.deployDelay"),
- trans.get("optimization.modifier.recoverydevice.deployDelay.desc"),
- c, UnitGroup.UNITS_SHORT_TIME,
- 1.0, c.getClass(), c.getID(), "DefaultDeployDelay");
- mod.setMinValue(0);
- mod.setMaxValue(10);
- modifiers.add(mod);
-
- if (device.getDefaultDeployEvent() == DeployEvent.ALTITUDE) {
- mod = new GenericComponentModifier(
- trans.get("optimization.modifier.recoverydevice.deployAltitude"),
- trans.get("optimization.modifier.recoverydevice.deployAltitude.desc"),
- c, UnitGroup.UNITS_DISTANCE,
- 1.0, c.getClass(), c.getID(), "DefaultDeployAltitude");
- setDefaultMinMax(mod, simulation);
- modifiers.add(mod);
- }
- }
+ // if (c instanceof RecoveryDevice) {
+ // RecoveryDevice device = (RecoveryDevice) c;
+ //
+ // SimulationModifier mod = new GenericComponentModifier(
+ // trans.get("optimization.modifier.recoverydevice.deployDelay"),
+ // trans.get("optimization.modifier.recoverydevice.deployDelay.desc"),
+ // c, UnitGroup.UNITS_SHORT_TIME,
+ // 1.0, c.getClass(), c.getID(), "DefaultDeployDelay");
+ // mod.setMinValue(0);
+ // mod.setMaxValue(10);
+ // modifiers.add(mod);
+ //
+ // if (device.getDefaultDeployEvent() == DeployEvent.ALTITUDE) {
+ // mod = new GenericComponentModifier(
+ // trans.get("optimization.modifier.recoverydevice.deployAltitude"),
+ // trans.get("optimization.modifier.recoverydevice.deployAltitude.desc"),
+ // c, UnitGroup.UNITS_DISTANCE,
+ // 1.0, c.getClass(), c.getID(), "DefaultDeployAltitude");
+ // setDefaultMinMax(mod, simulation);
+ // modifiers.add(mod);
+ // }
+ // }
// Conditional shape parameter of Transition
diff --git a/core/src/net/sf/openrocket/rocketcomponent/BodyTube.java b/core/src/net/sf/openrocket/rocketcomponent/BodyTube.java
index c983b80d7..ccfc387f8 100644
--- a/core/src/net/sf/openrocket/rocketcomponent/BodyTube.java
+++ b/core/src/net/sf/openrocket/rocketcomponent/BodyTube.java
@@ -38,7 +38,7 @@ public class BodyTube extends SymmetricComponent implements MotorMount, Coaxial
this.outerRadius = DEFAULT_RADIUS;
this.autoRadius = true;
- this.motorConfigurations = new FlightConfigurationImpl(this, ComponentChangeEvent.MOTOR_CHANGE, new MotorConfiguration());
+ this.motorConfigurations = new MotorFlightConfigurationImpl(this, ComponentChangeEvent.MOTOR_CHANGE, MotorConfiguration.NO_MOTORS);
this.ignitionConfigurations = new FlightConfigurationImpl(this, ComponentChangeEvent.EVENT_CHANGE, new IgnitionConfiguration());
}
diff --git a/core/src/net/sf/openrocket/rocketcomponent/IgnitionConfiguration.java b/core/src/net/sf/openrocket/rocketcomponent/IgnitionConfiguration.java
index 9dda39175..984c18059 100644
--- a/core/src/net/sf/openrocket/rocketcomponent/IgnitionConfiguration.java
+++ b/core/src/net/sf/openrocket/rocketcomponent/IgnitionConfiguration.java
@@ -9,7 +9,7 @@ import net.sf.openrocket.util.StateChangeListener;
public class IgnitionConfiguration implements FlightConfigurableParameter {
- public static enum IgnitionEvent {
+ public enum IgnitionEvent {
//// Automatic (launch or ejection charge)
AUTOMATIC("MotorMount.IgnitionEvent.AUTOMATIC") {
@Override
@@ -104,11 +104,11 @@ public class IgnitionConfiguration implements FlightConfigurableParameter(this, ComponentChangeEvent.MOTOR_CHANGE, new MotorConfiguration());
+ this.motorConfigurations = new MotorFlightConfigurationImpl(this, ComponentChangeEvent.MOTOR_CHANGE, MotorConfiguration.NO_MOTORS);
this.ignitionConfigurations = new FlightConfigurationImpl(this, ComponentChangeEvent.EVENT_CHANGE, new IgnitionConfiguration());
}
diff --git a/core/src/net/sf/openrocket/rocketcomponent/MotorConfiguration.java b/core/src/net/sf/openrocket/rocketcomponent/MotorConfiguration.java
index 1e22a9fca..b04e82ca3 100644
--- a/core/src/net/sf/openrocket/rocketcomponent/MotorConfiguration.java
+++ b/core/src/net/sf/openrocket/rocketcomponent/MotorConfiguration.java
@@ -15,6 +15,19 @@ import net.sf.openrocket.util.Utils;
*/
public class MotorConfiguration implements FlightConfigurableParameter {
+ /** Immutable configuration with no motor and zero delay. */
+ public static final MotorConfiguration NO_MOTORS = new MotorConfiguration() {
+ @Override
+ public void setMotor(Motor motor) {
+ throw new UnsupportedOperationException("Trying to modify immutable no-motors configuration");
+ };
+
+ @Override
+ public void setEjectionDelay(double delay) {
+ throw new UnsupportedOperationException("Trying to modify immutable no-motors configuration");
+ };
+ };
+
private final List listeners = new ArrayList();
private Motor motor;
diff --git a/core/src/net/sf/openrocket/rocketcomponent/MotorFlightConfigurationImpl.java b/core/src/net/sf/openrocket/rocketcomponent/MotorFlightConfigurationImpl.java
new file mode 100644
index 000000000..8be3a841a
--- /dev/null
+++ b/core/src/net/sf/openrocket/rocketcomponent/MotorFlightConfigurationImpl.java
@@ -0,0 +1,18 @@
+package net.sf.openrocket.rocketcomponent;
+
+/**
+ * FlightConfiguration implementation that prevents changing the default value.
+ * This is used for motors, where the default value is always no motor.
+ */
+public class MotorFlightConfigurationImpl> extends FlightConfigurationImpl {
+
+ public MotorFlightConfigurationImpl(RocketComponent component, int eventType, E defaultValue) {
+ super(component, eventType, defaultValue);
+ }
+
+ @Override
+ public void setDefault(E value) {
+ throw new UnsupportedOperationException("Cannot change default value of motor configuration");
+ }
+
+}
diff --git a/core/src/net/sf/openrocket/simulation/BasicEventSimulationEngine.java b/core/src/net/sf/openrocket/simulation/BasicEventSimulationEngine.java
index cfd569196..e8aeaff3b 100644
--- a/core/src/net/sf/openrocket/simulation/BasicEventSimulationEngine.java
+++ b/core/src/net/sf/openrocket/simulation/BasicEventSimulationEngine.java
@@ -243,7 +243,7 @@ public class BasicEventSimulationEngine implements SimulationEngine {
Coordinate position = positions[i];
MotorId id = new MotorId(component.getID(), i + 1);
motors.addMotor(id, motor.getInstance(), motorConfig.getEjectionDelay(), mount,
- ignitionConfig.getIgnitionEvent(), ignitionConfig.getDelay(), position);
+ ignitionConfig.getIgnitionEvent(), ignitionConfig.getIgnitionDelay(), position);
}
}
}
diff --git a/core/src/net/sf/openrocket/util/Reflection.java b/core/src/net/sf/openrocket/util/Reflection.java
index b3c66f62b..a5e39d282 100644
--- a/core/src/net/sf/openrocket/util/Reflection.java
+++ b/core/src/net/sf/openrocket/util/Reflection.java
@@ -2,14 +2,13 @@ package net.sf.openrocket.util;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
+import java.util.Arrays;
import net.sf.openrocket.rocketcomponent.RocketComponent;
public class Reflection {
- private static final String ROCKETCOMPONENT_PACKAGE = "net.sf.openrocket.rocketcomponent";
-
/**
* Simple wrapper class that converts the Method.invoke() exceptions into suitable
* RuntimeExceptions.
@@ -88,25 +87,24 @@ public class Reflection {
}
-
+
/**
- * Find a method from the rocket component classes.
+ * Find a method from a class.
* Throws an exception if method not found.
*/
- public static Reflection.Method findMethod(
- Class extends RocketComponent> componentClass,
- String method, Class>... params) {
- Reflection.Method m = findMethod(ROCKETCOMPONENT_PACKAGE, componentClass,
- "", method, params);
- if (m == null) {
- throw new BugException("Could not find method for componentClass="
- + componentClass + " method=" + method);
+ public static Reflection.Method findMethod(Class> c, String method, Class>... params) {
+
+ java.lang.reflect.Method m;
+ try {
+ m = c.getMethod(method, params);
+ return new Reflection.Method(m);
+ } catch (NoSuchMethodException e) {
+ throw new BugException("Could not find method " + method + "(" + Arrays.toString(params) + ") from class " + c);
}
- return m;
}
-
+
public static Reflection.Method findMethod(String pack, RocketComponent component,
String method, Class>... params) {
return findMethod(pack, component.getClass(), "", method, params);
diff --git a/core/src/net/sf/openrocket/util/TextUtil.java b/core/src/net/sf/openrocket/util/TextUtil.java
index a3d6b1ee8..41d7a2692 100644
--- a/core/src/net/sf/openrocket/util/TextUtil.java
+++ b/core/src/net/sf/openrocket/util/TextUtil.java
@@ -42,9 +42,9 @@ public class TextUtil {
}
/**
- * Return a string of the double value with suitable precision (5 digits).
- * The string is the shortest representation of the value including the
- * required precision.
+ * Return a string of the double value with suitable precision for storage.
+ * The string is the shortest representation of the value including at least
+ * 5 digits of precision.
*
* @param d the value to present.
* @return a representation with suitable precision.
@@ -172,26 +172,42 @@ public class TextUtil {
return sb.toString();
}
-
- public static String htmlEncode(String s) {
- s = s.replace("&", "&");
- s = s.replace("\"", """);
- s = s.replace("<", "<");
- s = s.replace(">", ">");
- return s;
- }
-
- /*
- * Returns a word-wrapped version of given input string using HTML syntax, wrapped to len characters.
+ /**
+ * Escape a string as XML or HTML. Encodes the following characters:
+ *
+ * - less than, greater than
+ *
- quotation mark, apostrophe
+ *
- ampersand
+ *
- all control characters except newline, carriage return and tab
+ *
+ *
+ * The result is both valid XML and HTML 2.0. The majority of characters are left unchanged.
*/
- public static String wrap(String in, int len) {
- in = in.trim();
- if (in.length() < len)
- return in;
- if (in.substring(0, len).contains("\n"))
- return in.substring(0, in.indexOf("\n")).trim() + "\n\n" + wrap(in.substring(in.indexOf("\n") + 1), len);
- int place = Math.max(Math.max(in.lastIndexOf(" ", len), in.lastIndexOf("\t", len)), in.lastIndexOf("-", len));
- return "" + in.substring(0, place).trim() + "
" + wrap(in.substring(place), len);
+ public static String escapeXML(String s) {
+ StringBuilder sb = new StringBuilder(s.length());
+
+ for (int i = 0; i < s.length(); i++) {
+ char c = s.charAt(i);
+
+ if (c == '&') {
+ sb.append("&");
+ } else if (c == '<') {
+ sb.append("<");
+ } else if (c == '>') {
+ sb.append(">");
+ } else if (c == '"') {
+ sb.append(""");
+ } else if (((c < 32) && (c != '\t') && (c != '\n') && (c != '\r')) || (c == '\'') || (c == 127)) {
+ // ' is not used since it's not standard HTML, use numerical escape instead
+ sb.append("").append((int) c).append(';');
+ } else {
+ sb.append(c);
+ }
+ }
+
+ return sb.toString();
}
+
+
}
diff --git a/core/test/net/sf/openrocket/util/TextUtilTest.java b/core/test/net/sf/openrocket/util/TextUtilTest.java
index a408b3c38..e3b2558a3 100644
--- a/core/test/net/sf/openrocket/util/TextUtilTest.java
+++ b/core/test/net/sf/openrocket/util/TextUtilTest.java
@@ -278,4 +278,15 @@ public class TextUtilTest {
}
}
+
+ @Test
+ public void testEscapeXML() {
+ assertEquals("", TextUtil.escapeXML(""));
+ assertEquals("foo&bar", TextUtil.escapeXML("foo&bar"));
+ assertEquals("<html>&", TextUtil.escapeXML("&"));
+ assertEquals(""'", TextUtil.escapeXML("\"'"));
+ assertEquals("foo\n\r\tbar", TextUtil.escapeXML("foo\n\r\tbar"));
+ assertEquals("foobar", TextUtil.escapeXML("foo" + ((char) 0) + ((char) 1) + ((char) 31) + ((char) 127) + "bar"));
+ }
+
}