Add error & warning dialog for RASAero exporting
This commit is contained in:
parent
c5a2fc44df
commit
9667466fdb
@ -89,7 +89,12 @@ BasicFrame.dlg.title = Design not saved
|
||||
BasicFrame.StageName.Sustainer = Sustainer
|
||||
BasicFrame.WarningDialog.txt1 = The following problems were encountered while opening
|
||||
BasicFrame.WarningDialog.txt2 = Some design features may not have been loaded correctly.
|
||||
BasicFrame.WarningDialog.saving.txt1 = The following problems were encountered while saving
|
||||
BasicFrame.WarningDialog.saving.txt2 = Some design features may not have exported correctly.
|
||||
BasicFrame.WarningDialog.title = Warnings while opening file
|
||||
BasicFrame.WarningDialog.saving.title = Warnings while opening file
|
||||
BasicFrame.ErrorWarningDialog.txt1 = <html>Please <b>correct the errors</b>.</html>
|
||||
BasicFrame.ErrorWarningDialog.saving.title = Errors/Warnings while saving file
|
||||
|
||||
|
||||
! General error messages used in multiple contexts
|
||||
|
@ -21,12 +21,16 @@ import net.sf.openrocket.document.StorageOptions.FileType;
|
||||
import net.sf.openrocket.file.openrocket.OpenRocketSaver;
|
||||
import net.sf.openrocket.file.rasaero.export.RASAeroSaver;
|
||||
import net.sf.openrocket.file.rocksim.export.RockSimSaver;
|
||||
import net.sf.openrocket.logging.ErrorSet;
|
||||
import net.sf.openrocket.logging.WarningSet;
|
||||
import net.sf.openrocket.rocketcomponent.InsideColorComponent;
|
||||
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
||||
import net.sf.openrocket.util.DecalNotFoundException;
|
||||
import net.sf.openrocket.util.MathUtil;
|
||||
|
||||
public class GeneralRocketSaver {
|
||||
protected final WarningSet warnings = new WarningSet();
|
||||
protected final ErrorSet errors = new ErrorSet();
|
||||
|
||||
/**
|
||||
* Interface which can be implemented by the caller to receive progress information.
|
||||
@ -234,16 +238,34 @@ public class GeneralRocketSaver {
|
||||
|
||||
private void saveInternal(OutputStream output, OpenRocketDocument document, StorageOptions options)
|
||||
throws IOException {
|
||||
|
||||
warnings.clear();
|
||||
errors.clear();
|
||||
|
||||
if (options.getFileType() == FileType.ROCKSIM) {
|
||||
new RockSimSaver().save(output, document, options);
|
||||
new RockSimSaver().save(output, document, options, warnings, errors);
|
||||
} else if (options.getFileType() == FileType.RASAERO) {
|
||||
new RASAeroSaver().save(output, document, options);
|
||||
new RASAeroSaver().save(output, document, options, warnings, errors);
|
||||
} else {
|
||||
new OpenRocketSaver().save(output, document, options);
|
||||
new OpenRocketSaver().save(output, document, options, warnings, errors);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return a list of warnings generated during the saving process.
|
||||
* @return a list of warnings generated during the saving process
|
||||
*/
|
||||
public WarningSet getWarnings() {
|
||||
return warnings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a list of errors generated during the saving process.
|
||||
* @return a list of errors generated during the saving process
|
||||
*/
|
||||
public ErrorSet getErrors() {
|
||||
return errors;
|
||||
}
|
||||
|
||||
private static class ProgressOutputStream extends FilterOutputStream {
|
||||
|
||||
private final long estimatedSize;
|
||||
|
@ -3,23 +3,24 @@ package net.sf.openrocket.file;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import net.sf.openrocket.logging.ErrorSet;
|
||||
import net.sf.openrocket.logging.WarningSet;
|
||||
import net.sf.openrocket.document.OpenRocketDocument;
|
||||
import net.sf.openrocket.document.StorageOptions;
|
||||
|
||||
|
||||
public abstract class RocketSaver {
|
||||
protected final WarningSet warnings = new WarningSet();
|
||||
|
||||
/**
|
||||
* Save the document to the specified output stream using the default storage options.
|
||||
*
|
||||
* @param dest the destination stream.
|
||||
* @param doc the document to save.
|
||||
* @param warnings list to store save warnings to
|
||||
* @param errors list to store save errors to
|
||||
* @throws IOException in case of an I/O error.
|
||||
*/
|
||||
public final void save(OutputStream dest, OpenRocketDocument doc) throws IOException {
|
||||
save(dest, doc, doc.getDefaultStorageOptions());
|
||||
public final void save(OutputStream dest, OpenRocketDocument doc, WarningSet warnings, ErrorSet errors) throws IOException {
|
||||
save(dest, doc, doc.getDefaultStorageOptions(), warnings, errors);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -28,9 +29,11 @@ public abstract class RocketSaver {
|
||||
* @param dest the destination stream.
|
||||
* @param doc the document to save.
|
||||
* @param options the storage options.
|
||||
* @param warnings list to store save warnings to
|
||||
* @param errors list to store save errors to
|
||||
* @throws IOException in case of an I/O error.
|
||||
*/
|
||||
public abstract void save(OutputStream dest, OpenRocketDocument doc, StorageOptions options) throws IOException;
|
||||
public abstract void save(OutputStream dest, OpenRocketDocument doc, StorageOptions options, WarningSet warnings, ErrorSet errors) throws IOException;
|
||||
|
||||
/**
|
||||
* Provide an estimate of the file size when saving the document with the
|
||||
|
@ -8,6 +8,8 @@ import java.io.Writer;
|
||||
import java.util.*;
|
||||
|
||||
import net.sf.openrocket.file.openrocket.savers.PhotoStudioSaver;
|
||||
import net.sf.openrocket.logging.ErrorSet;
|
||||
import net.sf.openrocket.logging.WarningSet;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@ -60,7 +62,7 @@ public class OpenRocketSaver extends RocketSaver {
|
||||
private Writer dest;
|
||||
|
||||
@Override
|
||||
public void save(OutputStream output, OpenRocketDocument document, StorageOptions options) throws IOException {
|
||||
public void save(OutputStream output, OpenRocketDocument document, StorageOptions options, WarningSet warnings, ErrorSet errors) throws IOException {
|
||||
|
||||
log.info("Saving .ork file");
|
||||
|
||||
|
@ -2,6 +2,8 @@ package net.sf.openrocket.file.rasaero.export;
|
||||
|
||||
import net.sf.openrocket.file.rasaero.CustomDoubleAdapter;
|
||||
import net.sf.openrocket.file.rasaero.RASAeroCommonConstants;
|
||||
import net.sf.openrocket.logging.ErrorSet;
|
||||
import net.sf.openrocket.logging.WarningSet;
|
||||
import net.sf.openrocket.rocketcomponent.AxialStage;
|
||||
import net.sf.openrocket.rocketcomponent.BodyTube;
|
||||
import net.sf.openrocket.rocketcomponent.NoseCone;
|
||||
@ -43,16 +45,24 @@ public class BasePartDTO {
|
||||
|
||||
@XmlTransient
|
||||
private final RocketComponent component;
|
||||
@XmlTransient
|
||||
private final WarningSet warnings;
|
||||
@XmlTransient
|
||||
private final ErrorSet errors;
|
||||
|
||||
/**
|
||||
* We need a default no-args constructor.
|
||||
*/
|
||||
public BasePartDTO() {
|
||||
this.component = null;
|
||||
this.warnings = null;
|
||||
this.errors = null;
|
||||
}
|
||||
|
||||
protected BasePartDTO(RocketComponent component) throws RASAeroExportException {
|
||||
protected BasePartDTO(RocketComponent component, WarningSet warnings, ErrorSet errors) throws RASAeroExportException {
|
||||
this.component = component;
|
||||
this.warnings = warnings;
|
||||
this.errors = errors;
|
||||
|
||||
if (component instanceof BodyTube) {
|
||||
setPartType(RASAeroCommonConstants.BODY_TUBE);
|
||||
|
@ -2,6 +2,8 @@ package net.sf.openrocket.file.rasaero.export;
|
||||
|
||||
import net.sf.openrocket.file.rasaero.CustomDoubleAdapter;
|
||||
import net.sf.openrocket.file.rasaero.RASAeroCommonConstants;
|
||||
import net.sf.openrocket.logging.ErrorSet;
|
||||
import net.sf.openrocket.logging.WarningSet;
|
||||
import net.sf.openrocket.rocketcomponent.BodyTube;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
@ -9,6 +11,7 @@ import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlElementRef;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
import javax.xml.bind.annotation.XmlTransient;
|
||||
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
|
||||
|
||||
import net.sf.openrocket.file.rasaero.export.RASAeroSaver.RASAeroExportException;
|
||||
@ -49,14 +52,25 @@ public class BodyTubeDTO extends BasePartDTO implements BodyTubeDTOAdapter {
|
||||
@XmlElementRef(name = RASAeroCommonConstants.FIN, type = FinDTO.class)
|
||||
private FinDTO fin;
|
||||
|
||||
|
||||
@XmlTransient
|
||||
private final WarningSet warnings;
|
||||
@XmlTransient
|
||||
private final ErrorSet errors;
|
||||
|
||||
/**
|
||||
* We need a default no-args constructor.
|
||||
*/
|
||||
public BodyTubeDTO() { }
|
||||
public BodyTubeDTO() {
|
||||
this.warnings = null;
|
||||
this.errors = null;
|
||||
}
|
||||
|
||||
public BodyTubeDTO(BodyTube bodyTube) throws RASAeroExportException {
|
||||
super(bodyTube);
|
||||
applyBodyTubeSettings(bodyTube);
|
||||
public BodyTubeDTO(BodyTube bodyTube, WarningSet warnings, ErrorSet errors) throws RASAeroExportException {
|
||||
super(bodyTube, warnings, errors);
|
||||
this.warnings = warnings;
|
||||
this.errors = errors;
|
||||
applyBodyTubeSettings(bodyTube, warnings, errors);
|
||||
}
|
||||
|
||||
public Double getLaunchLugDiameter() {
|
||||
|
@ -1,6 +1,8 @@
|
||||
package net.sf.openrocket.file.rasaero.export;
|
||||
|
||||
import net.sf.openrocket.file.rasaero.RASAeroCommonConstants;
|
||||
import net.sf.openrocket.logging.ErrorSet;
|
||||
import net.sf.openrocket.logging.WarningSet;
|
||||
import net.sf.openrocket.rocketcomponent.BodyTube;
|
||||
import net.sf.openrocket.rocketcomponent.LaunchLug;
|
||||
import net.sf.openrocket.rocketcomponent.RailButton;
|
||||
@ -10,17 +12,17 @@ import net.sf.openrocket.util.MathUtil;
|
||||
import net.sf.openrocket.file.rasaero.export.RASAeroSaver.RASAeroExportException;
|
||||
|
||||
public interface BodyTubeDTOAdapter {
|
||||
default void applyBodyTubeSettings(BodyTube bodyTube) throws RASAeroExportException {
|
||||
default void applyBodyTubeSettings(BodyTube bodyTube, WarningSet warnings, ErrorSet errors) throws RASAeroExportException {
|
||||
for (RocketComponent child : bodyTube.getChildren()) {
|
||||
if (child instanceof TrapezoidFinSet) {
|
||||
setFin(new FinDTO((TrapezoidFinSet) child));
|
||||
} else if (child instanceof LaunchLug) {
|
||||
if (!MathUtil.equals(getRailGuideDiameter(), 0) || !MathUtil.equals(getRailGuideHeight(), 0)) { // only one check on diameter or length should be sufficient, but just to be safe
|
||||
//TODO: warning.add(String.format("Already added a rail button, ignoring launch lug '%s'", child.getName());
|
||||
warnings.add(String.format("Already added a rail button, ignoring launch lug '%s'", child.getName()));
|
||||
continue;
|
||||
}
|
||||
if (!MathUtil.equals(getLaunchShoeArea(), 0)) {
|
||||
//TODO: warning.add(String.format("Already added a launch shoe, ignoring launch lug '%s'", child.getName());
|
||||
warnings.add(String.format("Already added a launch shoe, ignoring launch lug '%s'", child.getName()));
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -29,17 +31,18 @@ public interface BodyTubeDTOAdapter {
|
||||
if (lug.getInstanceCount() == 2) {
|
||||
setLaunchLugLength(lug.getLength() * RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH);
|
||||
} else {
|
||||
//TODO:warnings.add(String.format("Instance count of '%s' not set to 2, defaulting to 2 and adjusting
|
||||
// launch lug length accordingly.", lug.getName()")
|
||||
warnings.add(String.format(
|
||||
"Instance count of '%s' not set to 2, defaulting to 2 and adjusting launch lug length accordingly.",
|
||||
lug.getName()));
|
||||
setLaunchLugLength(lug.getLength() * lug.getInstanceCount() / 2 * RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH);
|
||||
}
|
||||
} else if (child instanceof RailButton) {
|
||||
if (!MathUtil.equals(getLaunchLugDiameter(), 0) || !MathUtil.equals(getLaunchLugLength(), 0)) { // only one check on diameter or length should be sufficient, but just to be safe
|
||||
// TODO: warning.add(String.format("Already added a launch lug, ignoring rail button '%s'", child.getName()));
|
||||
warnings.add(String.format("Already added a launch lug, ignoring rail button '%s'", child.getName()));
|
||||
continue;
|
||||
}
|
||||
if (!MathUtil.equals(getLaunchShoeArea(), 0)) {
|
||||
// TODO: warning.add(String.format("Already added a launch shoe, ignoring rail button '%s'", child.getName()));
|
||||
warnings.add(String.format("Already added a launch shoe, ignoring rail button '%s'", child.getName()));
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -48,10 +51,11 @@ public interface BodyTubeDTOAdapter {
|
||||
setRailGuideHeight(button.getTotalHeight() * RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH);
|
||||
|
||||
if (button.getInstanceCount() != 2) {
|
||||
//TODO: warnings.add(String.format("Instance count of '%s' equals %d, defaulting to 2", button.getName(), button.getInstanceCount()));
|
||||
warnings.add(String.format("Instance count of '%s' equals %d, defaulting to 2",
|
||||
button.getName(), button.getInstanceCount()));
|
||||
}
|
||||
} else {
|
||||
// TODO: warnings.add(String.format("Unsupported component '%s', ignoring.", child.getComponentName()));
|
||||
warnings.add(String.format("Unsupported component '%s', ignoring.", child.getComponentName()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,8 @@ package net.sf.openrocket.file.rasaero.export;
|
||||
|
||||
import net.sf.openrocket.file.rasaero.CustomDoubleAdapter;
|
||||
import net.sf.openrocket.file.rasaero.RASAeroCommonConstants;
|
||||
import net.sf.openrocket.logging.ErrorSet;
|
||||
import net.sf.openrocket.logging.WarningSet;
|
||||
import net.sf.openrocket.rocketcomponent.AxialStage;
|
||||
import net.sf.openrocket.rocketcomponent.BodyTube;
|
||||
import net.sf.openrocket.rocketcomponent.NoseCone;
|
||||
@ -13,6 +15,7 @@ import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlElementRef;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
import javax.xml.bind.annotation.XmlTransient;
|
||||
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
|
||||
|
||||
import net.sf.openrocket.file.rasaero.export.RASAeroSaver.RASAeroExportException;
|
||||
@ -74,12 +77,28 @@ public class BoosterDTO implements BodyTubeDTOAdapter {
|
||||
private FinDTO fin;
|
||||
|
||||
|
||||
@XmlTransient
|
||||
private final RocketComponent component;
|
||||
@XmlTransient
|
||||
private final WarningSet warnings;
|
||||
@XmlTransient
|
||||
private final ErrorSet errors;
|
||||
|
||||
|
||||
/**
|
||||
* We need a default, no-args constructor.
|
||||
*/
|
||||
public BoosterDTO() { }
|
||||
public BoosterDTO() {
|
||||
this.component = null;
|
||||
this.warnings = null;
|
||||
this.errors = null;
|
||||
}
|
||||
|
||||
protected BoosterDTO(Rocket rocket, AxialStage stage, WarningSet warnings, ErrorSet errors) throws RASAeroExportException {
|
||||
this.component = stage;
|
||||
this.warnings = warnings;
|
||||
this.errors = errors;
|
||||
|
||||
protected BoosterDTO(Rocket rocket, AxialStage stage) throws RASAeroExportException {
|
||||
int stageNr = rocket.getChildPosition(stage); // Use this instead of stage.getStageNumber() in case there are parallel stages in the design
|
||||
if (stageNr != 1 && stageNr != 2) {
|
||||
throw new RASAeroExportException(String.format("Invalid stage number '%d' for booster stage '%s'", stageNr, stage.getName()));
|
||||
@ -129,7 +148,7 @@ public class BoosterDTO implements BodyTubeDTOAdapter {
|
||||
firstTube = (BodyTube) stage.getChild(0);
|
||||
}
|
||||
|
||||
applyBodyTubeSettings(firstTube);
|
||||
applyBodyTubeSettings(firstTube, warnings, errors);
|
||||
|
||||
TrapezoidFinSet finSet = getFinSetFromBodyTube(firstTube);
|
||||
if (finSet == null) {
|
||||
@ -144,6 +163,8 @@ public class BoosterDTO implements BodyTubeDTOAdapter {
|
||||
setDiameter(firstTube.getOuterRadius() * 2 * RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH);
|
||||
setLocation(firstChild.getAxialOffset(AxialMethod.ABSOLUTE) * RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH);
|
||||
setColor(RASAeroCommonConstants.OPENROCKET_TO_RASAERO_COLOR(firstTube.getColor()));
|
||||
|
||||
// TODO: parse children for body tubes , transtitions etc.
|
||||
}
|
||||
|
||||
private TrapezoidFinSet getFinSetFromBodyTube(BodyTube bodyTube) {
|
||||
@ -168,6 +189,10 @@ public class BoosterDTO implements BodyTubeDTOAdapter {
|
||||
}
|
||||
|
||||
public void setLength(Double length) {
|
||||
if (MathUtil.equals(length, 0)) {
|
||||
errors.add(String.format("Length of '%s' must be greater than 0", component.getName()));
|
||||
return;
|
||||
}
|
||||
this.length = length;
|
||||
}
|
||||
|
||||
@ -175,7 +200,10 @@ public class BoosterDTO implements BodyTubeDTOAdapter {
|
||||
return diameter;
|
||||
}
|
||||
|
||||
public void setDiameter(Double diameter) {
|
||||
public void setDiameter(Double diameter) throws RASAeroExportException {
|
||||
if (MathUtil.equals(diameter, 0)) {
|
||||
throw new RASAeroExportException(String.format("Diameter of '%s' must be greater than 0", component.getName()));
|
||||
}
|
||||
this.diameter = diameter;
|
||||
}
|
||||
|
||||
@ -183,7 +211,10 @@ public class BoosterDTO implements BodyTubeDTOAdapter {
|
||||
return insideDiameter;
|
||||
}
|
||||
|
||||
public void setInsideDiameter(Double insideDiameter) {
|
||||
public void setInsideDiameter(Double insideDiameter) throws RASAeroExportException {
|
||||
if (MathUtil.equals(insideDiameter, 0)) {
|
||||
throw new RASAeroExportException(String.format("Inside diameter of '%s' must be greater than 0", component.getName()));
|
||||
}
|
||||
this.insideDiameter = insideDiameter;
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,8 @@ package net.sf.openrocket.file.rasaero.export;
|
||||
|
||||
import net.sf.openrocket.file.rasaero.CustomDoubleAdapter;
|
||||
import net.sf.openrocket.file.rasaero.RASAeroCommonConstants;
|
||||
import net.sf.openrocket.logging.ErrorSet;
|
||||
import net.sf.openrocket.logging.WarningSet;
|
||||
import net.sf.openrocket.rocketcomponent.NoseCone;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
@ -31,8 +33,8 @@ public class NoseConeDTO extends BasePartDTO {
|
||||
public NoseConeDTO() {
|
||||
}
|
||||
|
||||
public NoseConeDTO(NoseCone noseCone) throws RASAeroExportException {
|
||||
super(noseCone);
|
||||
public NoseConeDTO(NoseCone noseCone, WarningSet warnings, ErrorSet errors) throws RASAeroExportException {
|
||||
super(noseCone, warnings, errors);
|
||||
|
||||
NoseConeShapeSettings shapeSettings =
|
||||
RASAeroCommonConstants.OPENROCKET_TO_RASAERO_SHAPE(noseCone.getShapeType(), noseCone.getShapeParameter());
|
||||
|
@ -3,12 +3,13 @@ package net.sf.openrocket.file.rasaero.export;
|
||||
import net.sf.openrocket.document.OpenRocketDocument;
|
||||
import net.sf.openrocket.document.StorageOptions;
|
||||
import net.sf.openrocket.file.RocketSaver;
|
||||
import net.sf.openrocket.logging.ErrorSet;
|
||||
import net.sf.openrocket.logging.WarningSet;
|
||||
import net.sf.openrocket.rocketcomponent.Rocket;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.xml.bind.JAXBContext;
|
||||
import javax.xml.bind.JAXBException;
|
||||
import javax.xml.bind.Marshaller;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.IOException;
|
||||
@ -35,7 +36,7 @@ public class RASAeroSaver extends RocketSaver {
|
||||
* @param doc the OR design
|
||||
* @return RASAero-compliant XML
|
||||
*/
|
||||
public String marshalToRASAero(OpenRocketDocument doc) {
|
||||
public String marshalToRASAero(OpenRocketDocument doc, WarningSet warnings, ErrorSet errors) {
|
||||
try {
|
||||
JAXBContext binder = JAXBContext.newInstance(RASAeroDocumentDTO.class);
|
||||
Marshaller marshaller = binder.createMarshaller();
|
||||
@ -43,10 +44,10 @@ public class RASAeroSaver extends RocketSaver {
|
||||
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
|
||||
StringWriter sw = new StringWriter();
|
||||
|
||||
marshaller.marshal(toRASAeroDocumentDTO(doc), sw);
|
||||
marshaller.marshal(toRASAeroDocumentDTO(doc, warnings, errors), sw);
|
||||
return sw.toString();
|
||||
} catch (RASAeroExportException e) {
|
||||
throw new RuntimeException(e);
|
||||
errors.add(e.getMessage());
|
||||
} catch (Exception e) {
|
||||
log.error("Could not marshall a design to RASAero format. " + e.getMessage());
|
||||
}
|
||||
@ -55,28 +56,30 @@ public class RASAeroSaver extends RocketSaver {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(OutputStream dest, OpenRocketDocument doc, StorageOptions options) throws IOException {
|
||||
public void save(OutputStream dest, OpenRocketDocument doc, StorageOptions options, WarningSet warnings, ErrorSet errors) throws IOException {
|
||||
log.info("Saving .CDX1 file");
|
||||
|
||||
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(dest, StandardCharsets.UTF_8));
|
||||
writer.write(marshalToRASAero(doc));
|
||||
writer.write(marshalToRASAero(doc, warnings, errors));
|
||||
writer.flush();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long estimateFileSize(OpenRocketDocument doc, StorageOptions options) {
|
||||
return marshalToRASAero(doc).length();
|
||||
return marshalToRASAero(doc, new WarningSet(), new ErrorSet()).length();
|
||||
}
|
||||
|
||||
/**
|
||||
* Root conversion method. It iterates over all subcomponents.
|
||||
*
|
||||
* @param doc the OR design
|
||||
* @param warnings list to add export warnings to
|
||||
* @param errors list to add export errors to
|
||||
* @return a corresponding RASAero representation
|
||||
*/
|
||||
private RASAeroDocumentDTO toRASAeroDocumentDTO(OpenRocketDocument doc) throws RASAeroExportException {
|
||||
private RASAeroDocumentDTO toRASAeroDocumentDTO(OpenRocketDocument doc, WarningSet warnings, ErrorSet errors) throws RASAeroExportException {
|
||||
RASAeroDocumentDTO rad = new RASAeroDocumentDTO();
|
||||
rad.setDesign(toRocketDesignDTO(doc.getRocket()));
|
||||
rad.setDesign(toRocketDesignDTO(doc.getRocket(), warnings, errors));
|
||||
|
||||
return rad;
|
||||
}
|
||||
@ -86,8 +89,7 @@ public class RASAeroSaver extends RocketSaver {
|
||||
* @param rocket the OR rocket to export the components from
|
||||
* @return the RASAero rocket design
|
||||
*/
|
||||
private RocketDesignDTO toRocketDesignDTO(Rocket rocket) throws RASAeroExportException {
|
||||
RocketDesignDTO result = new RocketDesignDTO(rocket);
|
||||
return result;
|
||||
private RocketDesignDTO toRocketDesignDTO(Rocket rocket, WarningSet warnings, ErrorSet errors) throws RASAeroExportException {
|
||||
return new RocketDesignDTO(rocket, warnings, errors);
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,8 @@ package net.sf.openrocket.file.rasaero.export;
|
||||
import net.sf.openrocket.file.rasaero.CustomBooleanAdapter;
|
||||
import net.sf.openrocket.file.rasaero.CustomDoubleAdapter;
|
||||
import net.sf.openrocket.file.rasaero.RASAeroCommonConstants;
|
||||
import net.sf.openrocket.logging.ErrorSet;
|
||||
import net.sf.openrocket.logging.WarningSet;
|
||||
import net.sf.openrocket.rocketcomponent.AxialStage;
|
||||
import net.sf.openrocket.rocketcomponent.BodyTube;
|
||||
import net.sf.openrocket.rocketcomponent.NoseCone;
|
||||
@ -65,10 +67,10 @@ public class RocketDesignDTO {
|
||||
@XmlElement(name = RASAeroCommonConstants.COMMENTS)
|
||||
private String comments = "";
|
||||
|
||||
public RocketDesignDTO(Rocket rocket) throws RASAeroExportException {
|
||||
public RocketDesignDTO(Rocket rocket, WarningSet warnings, ErrorSet errors) throws RASAeroExportException {
|
||||
setComments(rocket.getComment());
|
||||
if (rocket.getChildCount() > 3) {
|
||||
throw new RASAeroExportException("Rocket should have no more then 3 stages (excl. boosters) in total");
|
||||
warnings.add("Rocket should have no more then 3 stages (excl. boosters) in total.\nIgnoring other stages.");
|
||||
}
|
||||
setUseBooster1(rocket.getStageCount() >= 2);
|
||||
setUseBooster2(rocket.getStageCount() == 3);
|
||||
@ -77,30 +79,40 @@ public class RocketDesignDTO {
|
||||
|
||||
// Export components from sustainer
|
||||
for (int i = 0; i < sustainer.getChildCount(); i++) {
|
||||
RocketComponent component = sustainer.getChild(i);
|
||||
if (i == 0 && !(component instanceof NoseCone)) {
|
||||
throw new RASAeroExportException("First component of the sustainer must be a nose cone");
|
||||
} else if (i == 1 && !(component instanceof BodyTube)) {
|
||||
throw new RASAeroExportException("Second component of the sustainer must be a body tube");
|
||||
}
|
||||
if (component instanceof BodyTube) {
|
||||
addExternalPart(new BodyTubeDTO((BodyTube) component));
|
||||
} else if (component instanceof NoseCone) {
|
||||
if (i != 0) {
|
||||
throw new RASAeroExportException("A nose cone can only be the first component of the rocket");
|
||||
try {
|
||||
RocketComponent component = sustainer.getChild(i);
|
||||
if (i == 0 && !(component instanceof NoseCone)) {
|
||||
errors.add("First component of the sustainer must be a nose cone");
|
||||
return;
|
||||
} else if (i == 1 && !(component instanceof BodyTube)) {
|
||||
errors.add("Second component of the sustainer must be a body tube");
|
||||
return;
|
||||
}
|
||||
addExternalPart(new NoseConeDTO((NoseCone) component));
|
||||
// Set the global surface finish to that of the first nose cone
|
||||
setSurface(RASAeroCommonConstants.OPENROCKET_TO_RASAERO_SURFACE(((NoseCone) component).getFinish()));
|
||||
}
|
||||
else if (component instanceof Transition) {
|
||||
addExternalPart(new TransitionDTO((Transition) component));
|
||||
if (component instanceof BodyTube) {
|
||||
addExternalPart(new BodyTubeDTO((BodyTube) component, warnings, errors));
|
||||
} else if (component instanceof NoseCone) {
|
||||
if (i != 0) {
|
||||
errors.add("A nose cone can only be the first component of the rocket");
|
||||
return;
|
||||
}
|
||||
addExternalPart(new NoseConeDTO((NoseCone) component, warnings, errors));
|
||||
// Set the global surface finish to that of the first nose cone
|
||||
setSurface(RASAeroCommonConstants.OPENROCKET_TO_RASAERO_SURFACE(((NoseCone) component).getFinish()));
|
||||
} else if (component instanceof Transition) {
|
||||
addExternalPart(new TransitionDTO((Transition) component, warnings, errors));
|
||||
}
|
||||
} catch (RASAeroExportException e) {
|
||||
errors.add(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// Export components from other stages
|
||||
for (int i = 1; i < rocket.getChildCount(); i++) {
|
||||
addBooster(new BoosterDTO(rocket, (AxialStage) rocket.getChild(i)));
|
||||
for (int i = 1; i < Math.min(rocket.getChildCount(), 3); i++) {
|
||||
try {
|
||||
addBooster(new BoosterDTO(rocket, (AxialStage) rocket.getChild(i), warnings, errors));
|
||||
} catch (RASAeroExportException e) {
|
||||
errors.add(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,8 @@ package net.sf.openrocket.file.rasaero.export;
|
||||
|
||||
import net.sf.openrocket.file.rasaero.CustomDoubleAdapter;
|
||||
import net.sf.openrocket.file.rasaero.RASAeroCommonConstants;
|
||||
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
||||
import net.sf.openrocket.logging.ErrorSet;
|
||||
import net.sf.openrocket.logging.WarningSet;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
@ -31,8 +32,8 @@ public class TransitionDTO extends BasePartDTO {
|
||||
public TransitionDTO() {
|
||||
}
|
||||
|
||||
public TransitionDTO(Transition transition) throws RASAeroExportException {
|
||||
super(transition);
|
||||
public TransitionDTO(Transition transition, WarningSet warnings, ErrorSet errors) throws RASAeroExportException {
|
||||
super(transition, warnings, errors);
|
||||
|
||||
if (!transition.getShapeType().equals(Transition.Shape.CONICAL)) {
|
||||
throw new RASAeroExportException("RASAero only supports conical transitions");
|
||||
|
@ -10,6 +10,8 @@ import java.nio.charset.StandardCharsets;
|
||||
import javax.xml.bind.JAXBContext;
|
||||
import javax.xml.bind.Marshaller;
|
||||
|
||||
import net.sf.openrocket.logging.ErrorSet;
|
||||
import net.sf.openrocket.logging.WarningSet;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@ -58,7 +60,7 @@ public class RockSimSaver extends RocketSaver {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(OutputStream dest, OpenRocketDocument doc, StorageOptions options) throws IOException {
|
||||
public void save(OutputStream dest, OpenRocketDocument doc, StorageOptions options, WarningSet warnings, ErrorSet errors) throws IOException {
|
||||
log.info("Saving .rkt file");
|
||||
|
||||
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(dest, StandardCharsets.UTF_8));
|
||||
|
@ -11,6 +11,8 @@ import net.sf.openrocket.document.OpenRocketDocument;
|
||||
import net.sf.openrocket.document.OpenRocketDocumentFactory;
|
||||
import net.sf.openrocket.document.Simulation;
|
||||
import net.sf.openrocket.file.openrocket.OpenRocketSaver;
|
||||
import net.sf.openrocket.logging.ErrorSet;
|
||||
import net.sf.openrocket.logging.WarningSet;
|
||||
import net.sf.openrocket.material.Material;
|
||||
import net.sf.openrocket.material.Material.Type;
|
||||
import net.sf.openrocket.motor.Manufacturer;
|
||||
@ -1830,7 +1832,7 @@ public class TestRockets {
|
||||
OpenRocketSaver saver = new OpenRocketSaver();
|
||||
try {
|
||||
FileOutputStream str = new FileOutputStream(filename);
|
||||
saver.save(str, doc, null);
|
||||
saver.save(str, doc, null, new WarningSet(), new ErrorSet());
|
||||
}
|
||||
catch (Exception e) {
|
||||
System.err.println("exception " + e);
|
||||
|
@ -29,6 +29,8 @@ import net.sf.openrocket.file.RocketLoadException;
|
||||
import net.sf.openrocket.file.motor.GeneralMotorLoader;
|
||||
import net.sf.openrocket.l10n.DebugTranslator;
|
||||
import net.sf.openrocket.l10n.Translator;
|
||||
import net.sf.openrocket.logging.ErrorSet;
|
||||
import net.sf.openrocket.logging.WarningSet;
|
||||
import net.sf.openrocket.motor.Manufacturer;
|
||||
import net.sf.openrocket.motor.Motor;
|
||||
import net.sf.openrocket.motor.ThrustCurveMotor;
|
||||
@ -363,7 +365,7 @@ public class OpenRocketSaverTest {
|
||||
try {
|
||||
file = File.createTempFile( TMP_DIR.getName(), ".ork");
|
||||
out = new FileOutputStream(file);
|
||||
this.saver.save(out, rocketDoc, options);
|
||||
this.saver.save(out, rocketDoc, options, new WarningSet(), new ErrorSet());
|
||||
} catch (FileNotFoundException e) {
|
||||
fail("FileNotFound saving temp file in: " + TMP_DIR.getName() + ": " + e.getMessage());
|
||||
} catch (IOException e) {
|
||||
|
128
swing/src/net/sf/openrocket/gui/dialogs/ErrorWarningDialog.java
Normal file
128
swing/src/net/sf/openrocket/gui/dialogs/ErrorWarningDialog.java
Normal file
@ -0,0 +1,128 @@
|
||||
package net.sf.openrocket.gui.dialogs;
|
||||
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import net.sf.openrocket.gui.components.StyledLabel;
|
||||
import net.sf.openrocket.logging.Error;
|
||||
import net.sf.openrocket.logging.ErrorSet;
|
||||
import net.sf.openrocket.logging.Warning;
|
||||
import net.sf.openrocket.logging.WarningSet;
|
||||
|
||||
import javax.swing.DefaultListCellRenderer;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JSeparator;
|
||||
import javax.swing.JViewport;
|
||||
import javax.swing.ListSelectionModel;
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
|
||||
/**
|
||||
* A message dialog displaying errors and warnings.
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public abstract class ErrorWarningDialog {
|
||||
public static void showErrorsAndWarnings(Component parent, Object message, String title, ErrorSet errors, WarningSet warnings) {
|
||||
JPanel content = new JPanel(new MigLayout("ins 0, fillx"));
|
||||
|
||||
StyledLabel label = new StyledLabel("Errors");
|
||||
label.setFontColor(net.sf.openrocket.util.Color.DARK_RED.toAWTColor());
|
||||
content.add(label, "wrap, gaptop 15lp");
|
||||
|
||||
Error[] e = errors.toArray(new Error[0]);
|
||||
final JList<Error> errorList = new JList<>(e);
|
||||
errorList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
||||
errorList.setCellRenderer(new ErrorListCellRenderer());
|
||||
JScrollPane errorPane = new JScrollPane(errorList);
|
||||
content.add(errorPane, "wrap, growx");
|
||||
|
||||
// Deselect items if clicked on blank region
|
||||
errorList.addMouseListener(new MouseAdapter() {
|
||||
@Override
|
||||
public void mousePressed(MouseEvent e) {
|
||||
int selectedIndex = errorList.locationToIndex(e.getPoint());
|
||||
if (selectedIndex < 0 || !errorList.getCellBounds(0, errorList.getLastVisibleIndex()).contains(e.getPoint())) {
|
||||
errorList.clearSelection();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
content.add(new JSeparator(JSeparator.HORIZONTAL), "wrap");
|
||||
|
||||
content.add(new JLabel("Warnings:"), "wrap");
|
||||
|
||||
Warning[] w = warnings.toArray(new Warning[0]);
|
||||
final JList<Warning> warningList = new JList<>(w);
|
||||
warningList.setCellRenderer(new WarningListCellRenderer());
|
||||
JScrollPane warningPane = new JScrollPane(warningList);
|
||||
content.add(warningPane, "wrap, growx");
|
||||
|
||||
// Deselect items if clicked on blank region
|
||||
warningList.addMouseListener(new MouseAdapter() {
|
||||
@Override
|
||||
public void mousePressed(MouseEvent e) {
|
||||
int selectedIndex = warningList.locationToIndex(e.getPoint());
|
||||
if (selectedIndex < 0 || !warningList.getCellBounds(0, warningList.getLastVisibleIndex()).contains(e.getPoint())) {
|
||||
warningList.clearSelection();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
JOptionPane.showMessageDialog(parent, new Object[] { message, content },
|
||||
title, JOptionPane.WARNING_MESSAGE);
|
||||
|
||||
}
|
||||
|
||||
private static class ErrorListCellRenderer extends DefaultListCellRenderer {
|
||||
@Override
|
||||
public Component getListCellRendererComponent(JList<?> list, Object value, int index,
|
||||
boolean isSelected, boolean cellHasFocus) {
|
||||
JLabel label = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
|
||||
|
||||
// Alternating row colors
|
||||
if (!isSelected) {
|
||||
if (index % 2 == 0) {
|
||||
label.setBackground(Color.WHITE);
|
||||
} else {
|
||||
label.setBackground(new Color(245, 245, 245));
|
||||
}
|
||||
}
|
||||
// Text color
|
||||
if (isSelected) {
|
||||
label.setForeground(Color.WHITE);
|
||||
} else {
|
||||
label.setForeground(net.sf.openrocket.util.Color.DARK_RED.toAWTColor());
|
||||
}
|
||||
return label;
|
||||
}
|
||||
}
|
||||
|
||||
private static class WarningListCellRenderer extends DefaultListCellRenderer {
|
||||
@Override
|
||||
public Component getListCellRendererComponent(JList<?> list, Object value, int index,
|
||||
boolean isSelected, boolean cellHasFocus) {
|
||||
JLabel label = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
|
||||
|
||||
// Alternating row colors
|
||||
if (!isSelected) {
|
||||
if (index % 2 == 0) {
|
||||
label.setBackground(Color.WHITE);
|
||||
} else {
|
||||
label.setBackground(new Color(245, 245, 245));
|
||||
}
|
||||
}
|
||||
// Text color
|
||||
if (isSelected) {
|
||||
label.setForeground(Color.WHITE);
|
||||
} else {
|
||||
label.setForeground(Color.BLACK);
|
||||
}
|
||||
return label;
|
||||
}
|
||||
}
|
||||
}
|
@ -11,7 +11,7 @@ import net.sf.openrocket.logging.Warning;
|
||||
import net.sf.openrocket.logging.WarningSet;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public class WarningDialog extends JDialog {
|
||||
public abstract class WarningDialog {
|
||||
|
||||
public static void showWarnings(Component parent, Object message, String title, WarningSet warnings) {
|
||||
|
||||
|
@ -49,6 +49,8 @@ import javax.swing.tree.DefaultTreeSelectionModel;
|
||||
import javax.swing.tree.TreePath;
|
||||
import javax.swing.tree.TreeSelectionModel;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import net.sf.openrocket.gui.dialogs.ErrorWarningDialog;
|
||||
import net.sf.openrocket.logging.ErrorSet;
|
||||
import net.sf.openrocket.logging.WarningSet;
|
||||
import net.sf.openrocket.appearance.DecalImage;
|
||||
import net.sf.openrocket.arch.SystemInfo;
|
||||
@ -1466,8 +1468,33 @@ public class BasicFrame extends JFrame {
|
||||
private boolean saveRASAeroFile(File file, StorageOptions options) {
|
||||
try {
|
||||
ROCKET_SAVER.save(file, document, options);
|
||||
|
||||
WarningSet warnings = ROCKET_SAVER.getWarnings();
|
||||
ErrorSet errors = ROCKET_SAVER.getErrors();
|
||||
|
||||
if (errors.isEmpty()) {
|
||||
WarningDialog.showWarnings(this,
|
||||
new Object[]{
|
||||
// // The following problems were encountered while saving
|
||||
trans.get("BasicFrame.WarningDialog.saving.txt1") + " '" + file.getName() + "'.",
|
||||
// // Some design features may not have been exported correctly.
|
||||
trans.get("BasicFrame.WarningDialog.saving.txt2")
|
||||
},
|
||||
// // Warnings while opening file
|
||||
trans.get("BasicFrame.WarningDialog.saving.title"), warnings);
|
||||
} else {
|
||||
ErrorWarningDialog.showErrorsAndWarnings(this,
|
||||
new Object[]{
|
||||
// // The following problems were encountered while saving
|
||||
trans.get("BasicFrame.WarningDialog.saving.txt1") + " '" + file.getName() + "'.",
|
||||
// // Please correct the errors.
|
||||
trans.get("BasicFrame.ErrorWarningDialog.txt1")
|
||||
},
|
||||
// // Errors/Warnings while saving file
|
||||
trans.get("BasicFrame.ErrorWarningDialog.saving.title"), errors, warnings);
|
||||
}
|
||||
// Do not update the save state of the document.
|
||||
return true;
|
||||
return errors.isEmpty();
|
||||
} catch (IOException e) {
|
||||
return false;
|
||||
} catch (DecalNotFoundException decex) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user