Reimplement ComponentPreset to be a bag of typed parameters. This provides greater flexibility.

Added PresetCSVReader which reads Components from CSV files based on the headers defined in the file.
Added placeholder for a Table dialog containing the ComponentPresets.
This commit is contained in:
Kevin Ruland 2012-04-01 03:27:45 +00:00
parent 35d96f3d53
commit 6f465cd0a2
18 changed files with 562 additions and 133 deletions

View File

@ -124,6 +124,8 @@ PrintDialog.error.preview.title = Unable to open preview
PrintDialog.error.preview.desc1 = Unable to open PDF preview.
PrintDialog.error.preview.desc2 = Please use the "Save as PDF" option instead.
! Component Preset Chooser Dialog
CompPresetChooser.title = Choose component preset
!PrintSettingsDialog
PrintSettingsDialog.title = Print settings

View File

@ -1,50 +0,0 @@
package net.sf.openrocket.database;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import net.sf.openrocket.preset.ComponentPreset;
import net.sf.openrocket.rocketcomponent.BodyTube;
import au.com.bytecode.opencsv.CSVReader;
public class BodyTubePresetDao {
private final List<ComponentPreset> templates = new ArrayList<ComponentPreset>();
// Package scope constructor to control creation pattern.
BodyTubePresetDao() {}
void initialize() throws IOException {
InputStream is = BodyTubePresetDao.class.getResourceAsStream("/datafiles/bodytubepresets.csv");
InputStreamReader r = new InputStreamReader(is);
// Create the CSV reader. Use comma separator and double-quote escaping. Skip first line.
CSVReader reader = new CSVReader(r,',','"',1);
String[] line;
while( (line = reader.readNext()) != null ) {
String manu = line[0];
String prod = line[1];
// inner diameter in centimeters
String idString = line[2];
double innerRadius = Double.parseDouble(idString) /100.0/2.0;
// outer diameter in centimeters
String odString = line[3];
double outerRadius = Double.parseDouble(odString) /100.0/2.0;
// length in centimeters
String maxLength = line[4];
double length = Double.parseDouble(maxLength) /100.0;
BodyTube bt = new BodyTube(length, outerRadius, outerRadius - innerRadius );
ComponentPreset preset = new ComponentPreset( manu, prod, "", bt );
templates.add(preset);
}
}
public List<ComponentPreset> listAll() {
return templates;
}
}

View File

@ -0,0 +1,33 @@
package net.sf.openrocket.database;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import net.sf.openrocket.file.preset.PresetCSVReader;
import net.sf.openrocket.preset.ComponentPreset;
public class ComponentPresetDao {
private final List<ComponentPreset> templates = new ArrayList<ComponentPreset>();
// Package scope constructor to control creation pattern.
ComponentPresetDao() {}
void initialize() throws IOException {
InputStream is = ComponentPresetDao.class.getResourceAsStream("/datafiles/bodytubepresets.csv");
PresetCSVReader parser = new PresetCSVReader(is);
List<ComponentPreset> list = parser.parse();
for( ComponentPreset preset : list ) {
templates.add(preset);
}
}
public List<ComponentPreset> listAll() {
return templates;
}
}

View File

@ -2,6 +2,6 @@ package net.sf.openrocket.database;
public interface Daos {
public BodyTubePresetDao getBodyTubePresetDao();
public ComponentPresetDao getBodyTubePresetDao();
}

View File

@ -3,16 +3,16 @@ package net.sf.openrocket.database;
public class DaosImpl implements Daos {
private BodyTubePresetDao bodyTubePresetDao;
private ComponentPresetDao bodyTubePresetDao;
public DaosImpl() throws Exception {
bodyTubePresetDao = new BodyTubePresetDao();
bodyTubePresetDao = new ComponentPresetDao();
bodyTubePresetDao.initialize();
}
@Override
public BodyTubePresetDao getBodyTubePresetDao() {
public ComponentPresetDao getBodyTubePresetDao() {
return bodyTubePresetDao;
}

View File

@ -0,0 +1,46 @@
package net.sf.openrocket.file.preset;
import net.sf.openrocket.preset.ComponentPreset;
import net.sf.openrocket.preset.TypedKey;
public interface ColumnDefinition {
public void setProperty( ComponentPreset preset, String value );
public static class Manufactuer implements ColumnDefinition {
@Override
public void setProperty( ComponentPreset preset, String value ) {
preset.setManufacturer(value);
}
}
public static class PartNumber implements ColumnDefinition {
@Override
public void setProperty( ComponentPreset preset, String value ) {
preset.setPartNo(value);
}
}
public static class Type implements ColumnDefinition {
@Override
public void setProperty( ComponentPreset preset, String value ) {
ComponentPreset.Type t = ComponentPreset.Type.valueOf(value);
if ( t == null ) {
throw new RuntimeException("Invalid ComponentPreset Type: " + value);
}
preset.setType(t);
}
}
public static class Parameter implements ColumnDefinition {
TypedKey key;
public Parameter( TypedKey key ) {
this.key = key;
}
@Override
public void setProperty( ComponentPreset preset, String value ) {
Object o = key.parseFromString(value);
preset.put(key, o);
}
}
}

View File

@ -0,0 +1,71 @@
package net.sf.openrocket.file.preset;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import net.sf.openrocket.preset.ComponentPreset;
import net.sf.openrocket.preset.TypedKey;
import net.sf.openrocket.rocketcomponent.BodyTube;
import au.com.bytecode.opencsv.CSVReader;
public class PresetCSVReader {
private InputStream is;
private ColumnDefinition[] columns;
public PresetCSVReader( InputStream is ) {
this.is = is;
}
public List<ComponentPreset> parse() throws IOException {
List<ComponentPreset> templates = new ArrayList<ComponentPreset>();
InputStreamReader r = new InputStreamReader(is);
// Create the CSV reader. Use comma separator and double-quote escaping.
CSVReader reader = new CSVReader(r,',','"');
String[] headers = reader.readNext();
if (headers == null || headers.length == 0) {
return templates;
}
columns = new ColumnDefinition[headers.length];
for( int i = 0; i< headers.length; i++ ) {
String h = headers[i];
if( "Manufacturer".equals(h) ) {
columns[i] = new ColumnDefinition.Manufactuer();
} else if ( "PartNumber".equals(h) ) {
columns[i] = new ColumnDefinition.PartNumber();
} else if ( "Type".equals(h) ) {
columns[i] = new ColumnDefinition.Type();
} else {
TypedKey key = ComponentPreset.keyMap.get(h);
if ( key == null ) {
throw new RuntimeException("Invalid parameter key " + h + " in file");
}
columns[i] = new ColumnDefinition.Parameter( key );
}
}
String[] line;
while( (line = reader.readNext()) != null ) {
ComponentPreset preset = new ComponentPreset();
for( int i = 0; i< headers.length; i++ ) {
if ( i > line.length ) {
break;
}
String value = line[i];
columns[i].setProperty(preset, value);
}
templates.add(preset);
}
return templates;
}
}

View File

@ -43,6 +43,8 @@ public class BodyTubePresetModel extends AbstractListModel implements ComboBoxMo
}
@Override
public boolean equals(Object obj) {
// I don't know why the default equals generated by Eclipse does not work.
// instead of relying on bt.equals(other.bt), we have to compare the hashcodes of those objects.
if (this == obj)
return true;
if (obj == null)
@ -53,9 +55,9 @@ public class BodyTubePresetModel extends AbstractListModel implements ComboBoxMo
if (bt == null) {
if (other.bt != null)
return false;
} else if (!bt.equals(other.bt))
} else if (other.bt == null)
return false;
return true;
return bt.hashCode() == other.bt.hashCode();
}
}

View File

@ -1,11 +1,16 @@
package net.sf.openrocket.gui.configdialog;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.SwingUtilities;
import net.miginfocom.swing.MigLayout;
import net.sf.openrocket.document.OpenRocketDocument;
@ -15,8 +20,10 @@ import net.sf.openrocket.gui.adaptors.BooleanModel;
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.gui.dialogs.preset.ComponentPresetChooserDialog;
import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.material.Material;
import net.sf.openrocket.preset.ComponentPreset;
import net.sf.openrocket.rocketcomponent.BodyTube;
import net.sf.openrocket.rocketcomponent.ComponentChangeEvent;
import net.sf.openrocket.rocketcomponent.ComponentChangeListener;
@ -40,7 +47,21 @@ public class BodyTubeConfig extends RocketComponentConfig {
//// Body tube template
panel.add( new JLabel(trans.get("BodyTubecfg.lbl.Bodytubepreset")) );
presetComboBox = new JComboBox(new BodyTubePresetModel(component));
panel.add(presetComboBox, "wrap");
panel.add(presetComboBox);
{
JButton opendialog = new JButton("o");
opendialog.addActionListener(
new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
ComponentPresetChooserDialog dialog = new ComponentPresetChooserDialog(SwingUtilities.getWindowAncestor(BodyTubeConfig.this));
dialog.setVisible(true);
ComponentPreset preset = dialog.getSelectedComponentPreset();
}
});
panel.add( opendialog, "wrap" );
}
//// Body tube length
panel.add(new JLabel(trans.get("BodyTubecfg.lbl.Bodytubelength")));
@ -152,8 +173,8 @@ public class BodyTubeConfig extends RocketComponentConfig {
private void adjustPresetState() {
BodyTube bt = (BodyTube) component;
if ( bt.getPresetComponent() != null ) {
BodyTube btPreset = (BodyTube) bt.getPresetComponent().getPrototype();
maxLength.setValue( btPreset.getLength() );
ComponentPreset btPreset = bt.getPresetComponent();
maxLength.setValue( btPreset.get(ComponentPreset.LENGTH) );
} else {
// here we should be able to force the preset combo box to display empty.
// We set the selected index to -1 (undefined), then force a repaint.

View File

@ -0,0 +1,96 @@
package net.sf.openrocket.gui.dialogs.preset;
import java.awt.Dialog;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JPanel;
import net.miginfocom.swing.MigLayout;
import net.sf.openrocket.gui.util.GUIUtil;
import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.preset.ComponentPreset;
import net.sf.openrocket.startup.Application;
public class ComponentPresetChooserDialog extends JDialog {
// private final ThrustCurveMotorSelectionPanel selectionPanel;
private boolean okClicked = false;
private static final Translator trans = Application.getTranslator();
public ComponentPresetChooserDialog(Window owner) {
super(owner, trans.get("CompPresetChooser.title"), Dialog.ModalityType.APPLICATION_MODAL);
JPanel panel = new JPanel(new MigLayout("fill"));
//selectionPanel = new ThrustCurveMotorSelectionPanel((ThrustCurveMotor) current, delay, diameter);
//panel.add(selectionPanel, "grow, wrap para");
// OK / Cancel buttons
JButton okButton = new JButton(trans.get("dlg.but.ok"));
okButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
close(true);
}
});
panel.add(okButton, "tag ok, spanx, split");
//// Cancel button
JButton cancelButton = new JButton(trans.get("dlg.but.cancel"));
cancelButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
close(false);
}
});
panel.add(cancelButton, "tag cancel");
this.add(panel);
this.setModal(true);
this.pack();
this.setLocationByPlatform(true);
GUIUtil.setDisposableDialogOptions(this, okButton);
//JComponent focus = selectionPanel.getDefaultFocus();
//if (focus != null) {
// focus.grabFocus();
//}
// Set the closeable dialog after all initialization
//selectionPanel.setCloseableDialog(this);
}
/**
* Return the motor selected by this chooser dialog, or <code>null</code> if the selection has been aborted.
*
* @return the selected motor, or <code>null</code> if no motor has been selected or the selection was canceled.
*/
public ComponentPreset getSelectedComponentPreset() {
if (!okClicked)
return null;
//return selectionPanel.getSelectedMotor();
return null;
}
public void close(boolean ok) {
okClicked = ok;
this.setVisible(false);
ComponentPreset preset = getSelectedComponentPreset();
if (okClicked && preset != null) {
//selectionPanel.selectedMotor(selected);
}
}
}

View File

@ -1,6 +1,10 @@
package net.sf.openrocket.preset;
import net.sf.openrocket.rocketcomponent.RocketComponent;
import java.util.HashMap;
import java.util.Map;
import net.sf.openrocket.material.Material;
import net.sf.openrocket.rocketcomponent.ExternalComponent.Finish;
/**
@ -11,63 +15,77 @@ import net.sf.openrocket.rocketcomponent.RocketComponent;
*
* @author Sampo Niskanen <sampo.niskanen@iki.fi>
*/
public class ComponentPreset {
public class ComponentPreset extends TypedPropertyMap {
// TODO - Implement clone.
// Implement "freezing" so the object cannot be modified.
private final String manufacturer;
private final String partNo;
private final String partDescription;
private final RocketComponent prototype;
public enum Type {
BodyTube,
NoseCone
}
public final static TypedKey<Double> LENGTH = new TypedKey<Double>("Length", Double.class);
public final static TypedKey<Double> INNER_DIAMETER = new TypedKey<Double>("InnerDiameter", Double.class);
public final static TypedKey<Double> OUTER_DIAMETER = new TypedKey<Double>("OuterDiameter", Double.class);
public final static TypedKey<Material> MATERIAL = new TypedKey<Material>("Material", Material.class);
public final static TypedKey<Finish> FINISH = new TypedKey<Finish>("Finish",Finish.class);
public final static TypedKey<Double> THICKNESS = new TypedKey<Double>("Thickness", Double.class);
public final static TypedKey<Boolean> FILLED = new TypedKey<Boolean>("Filled",Boolean.class);
public final static TypedKey<Double> MASS = new TypedKey<Double>("Mass", Double.class);
public ComponentPreset(String manufacturer, String partNo, String partDescription, RocketComponent prototype) {
this.manufacturer = manufacturer;
this.partNo = partNo;
this.partDescription = partDescription;
this.prototype = prototype.copy();
public final static Map<String,TypedKey<?>> keyMap = new HashMap<String,TypedKey<?>>();
static {
keyMap.put(LENGTH.getName(), LENGTH);
keyMap.put(INNER_DIAMETER.getName(), INNER_DIAMETER);
keyMap.put(OUTER_DIAMETER.getName(), OUTER_DIAMETER);
keyMap.put(MATERIAL.getName(), MATERIAL);
keyMap.put(FINISH.getName(), FINISH);
keyMap.put(THICKNESS.getName(), THICKNESS);
keyMap.put(FILLED.getName(), FILLED);
keyMap.put(MASS.getName(), MASS);
}
if (prototype.getParent() != null) {
throw new IllegalArgumentException("Prototype component cannot have a parent");
}
if (prototype.getChildCount() > 0) {
throw new IllegalArgumentException("Prototype component cannot have children");
}
private String manufacturer;
private String partNo;
private String partDescription;
private Type type;
public ComponentPreset() {
}
/**
* Return the component class that this preset defines.
*/
public Class<? extends RocketComponent> getComponentClass() {
return prototype.getClass();
}
/**
* Return the manufacturer of this preset component.
*/
public String getManufacturer() {
return manufacturer;
}
/**
* Return the part number. This is the part identifier (e.g. "BT-50").
*/
public void setManufacturer(String manufacturer) {
this.manufacturer = manufacturer;
}
public String getPartNo() {
return partNo;
}
/**
* Return the part description. This is a longer description of the component.
*/
public void setPartNo(String partNo) {
this.partNo = partNo;
}
public String getPartDescription() {
return partDescription;
}
/**
* Return a prototype component. This component may be modified freely.
*/
public RocketComponent getPrototype() {
return prototype.copy();
public void setPartDescription(String partDescription) {
this.partDescription = partDescription;
}
public Type getType() {
return type;
}
public void setType(Type type) {
this.type = type;
}
}

View File

@ -0,0 +1,91 @@
package net.sf.openrocket.preset;
import net.sf.openrocket.database.Databases;
import net.sf.openrocket.material.Material;
import net.sf.openrocket.rocketcomponent.ExternalComponent.Finish;
import net.sf.openrocket.startup.Application;
public class TypedKey<T> {
private final String name;
private final Class<T> type;
public TypedKey(String name, Class<T> type) {
this.name = name;
this.type = type;
}
public String getName() {
return name;
}
public Class<T> getType() {
return type;
}
public Object parseFromString( String value ) {
if ( type.equals(Boolean.class) ) {
return Boolean.parseBoolean(value);
}
if ( type.isAssignableFrom(Double.class) ) {
return Double.parseDouble(value);
}
if ( type.equals(String.class ) ) {
return value;
}
if ( type.equals(Finish.class) ) {
return Finish.valueOf(value);
}
if ( type.equals(Material.class) ) {
// need to translate the value first!
String translated_value = Application.getTranslator().get(value);
Material material;
material = Databases.findMaterial(Material.Type.BULK, translated_value);
if ( material != null ) {
return material;
}
material = Databases.findMaterial(Material.Type.LINE, translated_value);
if ( material != null ) {
return material;
}
material = Databases.findMaterial(Material.Type.SURFACE, translated_value);
if ( material != null ) {
return material;
}
throw new IllegalArgumentException("Invalid material " + value + " in component preset.");
}
throw new IllegalArgumentException("Inavlid type " + type.getName() + " for component preset parameter " + name);
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + ((type == null) ? 0 : type.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
TypedKey other = (TypedKey) obj;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
if (type == null) {
if (other.type != null)
return false;
} else if (!type.equals(other.type))
return false;
return true;
}
}

View File

@ -0,0 +1,80 @@
package net.sf.openrocket.preset;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
public class TypedPropertyMap {
private final Map<TypedKey<?>, Object> delegate;
public TypedPropertyMap() {
delegate = new LinkedHashMap<TypedKey<?>,Object>();
}
public int size() {
return delegate.size();
}
public boolean isEmpty() {
return delegate.isEmpty();
}
public boolean containsKey(Object key) {
return delegate.containsKey(key);
}
public boolean containsValue(Object value) {
return delegate.containsValue(value);
}
@SuppressWarnings("unchecked")
public <T> T get(TypedKey<T> key) {
return (T) delegate.get(key);
}
@SuppressWarnings("unchecked")
public <T> T put(TypedKey<T> key, T value) {
return (T) delegate.put(key, value);
}
public Object remove(Object key) {
return delegate.remove(key);
}
public void putAll(TypedPropertyMap other) {
if ( other == null ) {
return;
}
delegate.putAll(other.delegate);
}
public void clear() {
delegate.clear();
}
public Set<TypedKey<?>> keySet() {
return delegate.keySet();
}
public Collection<Object> values() {
return delegate.values();
}
public Set<Entry<TypedKey<?>, Object>> entrySet() {
return delegate.entrySet();
}
@Override
public boolean equals(Object o) {
return delegate.equals(o);
}
@Override
public int hashCode() {
return delegate.hashCode();
}
}

View File

@ -1,5 +1,7 @@
package net.sf.openrocket.rocketcomponent;
import net.sf.openrocket.preset.ComponentPreset;
/**
@ -49,9 +51,10 @@ public abstract class BodyComponent extends ExternalComponent {
@Override
protected void loadFromPreset(RocketComponent preset) {
BodyComponent c = (BodyComponent) preset;
this.setLength(c.getLength());
protected void loadFromPreset(ComponentPreset preset) {
if ( preset.containsKey(ComponentPreset.LENGTH) ) {
this.setLength(preset.get(ComponentPreset.LENGTH));
}
super.loadFromPreset(preset);
}

View File

@ -6,6 +6,7 @@ import java.util.HashMap;
import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.motor.Motor;
import net.sf.openrocket.preset.ComponentPreset;
import net.sf.openrocket.startup.Application;
import net.sf.openrocket.util.Coordinate;
import net.sf.openrocket.util.MathUtil;
@ -134,13 +135,18 @@ public class BodyTube extends SymmetricComponent implements MotorMount, Coaxial
@Override
protected void loadFromPreset(RocketComponent preset) {
super.loadFromPreset(preset);
BodyTube bt = (BodyTube) preset;
protected void loadFromPreset(ComponentPreset preset) {
this.autoRadius = false;
this.outerRadius = bt.getOuterRadius();
this.thickness = (bt.getOuterRadius() - bt.getInnerRadius());
this.length = bt.getLength();
if ( preset.containsKey(ComponentPreset.OUTER_DIAMETER) ) {
double outerDiameter = preset.get(ComponentPreset.OUTER_DIAMETER);
this.outerRadius = outerDiameter/2.0;
if ( preset.containsKey(ComponentPreset.INNER_DIAMETER) ) {
double innerDiameter = preset.get(ComponentPreset.INNER_DIAMETER);
this.thickness = (outerDiameter-innerDiameter) / 2.0;
}
}
super.loadFromPreset(preset);
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);

View File

@ -4,7 +4,7 @@ import java.util.List;
import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.material.Material;
import net.sf.openrocket.material.Material.Type;
import net.sf.openrocket.preset.ComponentPreset;
import net.sf.openrocket.startup.Application;
import net.sf.openrocket.unit.UnitGroup;
@ -129,27 +129,30 @@ public abstract class ExternalComponent extends RocketComponent {
@Override
protected void loadFromPreset(RocketComponent preset) {
protected void loadFromPreset(ComponentPreset preset) {
super.loadFromPreset(preset);
// Surface finish is left unchanged
ExternalComponent c = (ExternalComponent) preset;
Material mat = c.getMaterial();
if ( mat != null ) {
setMaterial(mat);
} else if (c.isMassOverridden()) {
double mass = c.getOverrideMass();
double volume = getComponentVolume();
double density;
if (volume > 0.00001) {
density = mass / volume;
} else {
density = 1000;
if ( preset.containsKey(ComponentPreset.MATERIAL ) ) {
Material mat = preset.get(ComponentPreset.MATERIAL);
if ( mat != null ) {
setMaterial(mat);
} /*
TODO -
else if (c.isMassOverridden()) {
double mass = c.getOverrideMass();
double volume = getComponentVolume();
double density;
if (volume > 0.00001) {
density = mass / volume;
} else {
density = 1000;
}
mat = Material.newMaterial(Type.BULK, mat.getName(), density, true);
setMaterial(mat);
}
mat = Material.newMaterial(Type.BULK, mat.getName(), density, true);
setMaterial(mat);
*/
}
}

View File

@ -688,10 +688,13 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
return;
}
// TODO - do we need to this compatibility check?
/*
if (preset.getComponentClass() != this.getClass()) {
throw new IllegalArgumentException("Attempting to load preset of type " + preset.getComponentClass()
+ " into component of type " + this.getClass());
}
*/
RocketComponent root = getRoot();
final Rocket rocket;
@ -706,7 +709,7 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
rocket.freeze();
}
loadFromPreset(preset.getPrototype());
loadFromPreset(preset);
this.presetComponent = preset;
fireComponentChangeEvent(ComponentChangeEvent.NONFUNCTIONAL_CHANGE);
@ -731,7 +734,7 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
*
* @param preset the preset to load from
*/
protected void loadFromPreset(RocketComponent preset) {
protected void loadFromPreset(ComponentPreset preset) {
// No-op
}

View File

@ -6,6 +6,7 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import net.sf.openrocket.preset.ComponentPreset;
import net.sf.openrocket.util.Coordinate;
import net.sf.openrocket.util.MathUtil;
@ -146,10 +147,13 @@ public abstract class SymmetricComponent extends BodyComponent implements Radial
@Override
protected void loadFromPreset(RocketComponent preset) {
SymmetricComponent c = (SymmetricComponent) preset;
this.setThickness(c.getThickness());
this.setFilled(c.isFilled());
protected void loadFromPreset(ComponentPreset preset) {
if ( preset.containsKey(ComponentPreset.THICKNESS) ) {
this.setThickness(preset.get(ComponentPreset.THICKNESS));
}
if ( preset.containsKey(ComponentPreset.FILLED)) {
this.setFilled(preset.get(ComponentPreset.FILLED));
}
super.loadFromPreset(preset);
}