From 1691e44b69fa89917a194e113ed30b37303c0efa Mon Sep 17 00:00:00 2001 From: kruland2607 Date: Sun, 1 Apr 2012 03:27:45 +0000 Subject: [PATCH] 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. git-svn-id: https://openrocket.svn.sourceforge.net/svnroot/openrocket/trunk@495 180e2498-e6e9-4542-8430-84ac67f01cd8 --- core/resources/l10n/messages.properties | 2 + .../database/BodyTubePresetDao.java | 50 --------- .../database/ComponentPresetDao.java | 33 ++++++ core/src/net/sf/openrocket/database/Daos.java | 2 +- .../net/sf/openrocket/database/DaosImpl.java | 6 +- .../file/preset/ColumnDefinition.java | 46 ++++++++ .../file/preset/PresetCSVReader.java | 71 +++++++++++++ .../gui/adaptors/BodyTubePresetModel.java | 6 +- .../gui/configdialog/BodyTubeConfig.java | 27 ++++- .../preset/ComponentPresetChooserDialog.java | 96 +++++++++++++++++ .../sf/openrocket/preset/ComponentPreset.java | 100 +++++++++++------- .../net/sf/openrocket/preset/TypedKey.java | 91 ++++++++++++++++ .../openrocket/preset/TypedPropertyMap.java | 80 ++++++++++++++ .../rocketcomponent/BodyComponent.java | 9 +- .../openrocket/rocketcomponent/BodyTube.java | 18 ++-- .../rocketcomponent/ExternalComponent.java | 37 ++++--- .../rocketcomponent/RocketComponent.java | 7 +- .../rocketcomponent/SymmetricComponent.java | 12 ++- 18 files changed, 561 insertions(+), 132 deletions(-) delete mode 100644 core/src/net/sf/openrocket/database/BodyTubePresetDao.java create mode 100644 core/src/net/sf/openrocket/database/ComponentPresetDao.java create mode 100644 core/src/net/sf/openrocket/file/preset/ColumnDefinition.java create mode 100644 core/src/net/sf/openrocket/file/preset/PresetCSVReader.java create mode 100644 core/src/net/sf/openrocket/gui/dialogs/preset/ComponentPresetChooserDialog.java create mode 100644 core/src/net/sf/openrocket/preset/TypedKey.java create mode 100644 core/src/net/sf/openrocket/preset/TypedPropertyMap.java diff --git a/core/resources/l10n/messages.properties b/core/resources/l10n/messages.properties index f20e1640..5f057a9b 100644 --- a/core/resources/l10n/messages.properties +++ b/core/resources/l10n/messages.properties @@ -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 diff --git a/core/src/net/sf/openrocket/database/BodyTubePresetDao.java b/core/src/net/sf/openrocket/database/BodyTubePresetDao.java deleted file mode 100644 index 733c7bcd..00000000 --- a/core/src/net/sf/openrocket/database/BodyTubePresetDao.java +++ /dev/null @@ -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 templates = new ArrayList(); - - // 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 listAll() { - return templates; - } - -} diff --git a/core/src/net/sf/openrocket/database/ComponentPresetDao.java b/core/src/net/sf/openrocket/database/ComponentPresetDao.java new file mode 100644 index 00000000..d76e71df --- /dev/null +++ b/core/src/net/sf/openrocket/database/ComponentPresetDao.java @@ -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 templates = new ArrayList(); + + // 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 list = parser.parse(); + for( ComponentPreset preset : list ) { + templates.add(preset); + } + } + + public List listAll() { + return templates; + } + +} diff --git a/core/src/net/sf/openrocket/database/Daos.java b/core/src/net/sf/openrocket/database/Daos.java index 210a186a..f19839e7 100644 --- a/core/src/net/sf/openrocket/database/Daos.java +++ b/core/src/net/sf/openrocket/database/Daos.java @@ -2,6 +2,6 @@ package net.sf.openrocket.database; public interface Daos { - public BodyTubePresetDao getBodyTubePresetDao(); + public ComponentPresetDao getBodyTubePresetDao(); } diff --git a/core/src/net/sf/openrocket/database/DaosImpl.java b/core/src/net/sf/openrocket/database/DaosImpl.java index c1fc44d8..fde42185 100644 --- a/core/src/net/sf/openrocket/database/DaosImpl.java +++ b/core/src/net/sf/openrocket/database/DaosImpl.java @@ -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; } diff --git a/core/src/net/sf/openrocket/file/preset/ColumnDefinition.java b/core/src/net/sf/openrocket/file/preset/ColumnDefinition.java new file mode 100644 index 00000000..3e62286b --- /dev/null +++ b/core/src/net/sf/openrocket/file/preset/ColumnDefinition.java @@ -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); + } + } + + + +} diff --git a/core/src/net/sf/openrocket/file/preset/PresetCSVReader.java b/core/src/net/sf/openrocket/file/preset/PresetCSVReader.java new file mode 100644 index 00000000..928639ec --- /dev/null +++ b/core/src/net/sf/openrocket/file/preset/PresetCSVReader.java @@ -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 parse() throws IOException { + + List templates = new ArrayList(); + + 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; + } + +} diff --git a/core/src/net/sf/openrocket/gui/adaptors/BodyTubePresetModel.java b/core/src/net/sf/openrocket/gui/adaptors/BodyTubePresetModel.java index 1f46062a..08850b8f 100644 --- a/core/src/net/sf/openrocket/gui/adaptors/BodyTubePresetModel.java +++ b/core/src/net/sf/openrocket/gui/adaptors/BodyTubePresetModel.java @@ -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(); } } diff --git a/core/src/net/sf/openrocket/gui/configdialog/BodyTubeConfig.java b/core/src/net/sf/openrocket/gui/configdialog/BodyTubeConfig.java index b026a455..bfeed944 100644 --- a/core/src/net/sf/openrocket/gui/configdialog/BodyTubeConfig.java +++ b/core/src/net/sf/openrocket/gui/configdialog/BodyTubeConfig.java @@ -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. diff --git a/core/src/net/sf/openrocket/gui/dialogs/preset/ComponentPresetChooserDialog.java b/core/src/net/sf/openrocket/gui/dialogs/preset/ComponentPresetChooserDialog.java new file mode 100644 index 00000000..23640217 --- /dev/null +++ b/core/src/net/sf/openrocket/gui/dialogs/preset/ComponentPresetChooserDialog.java @@ -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 null if the selection has been aborted. + * + * @return the selected motor, or null 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); + } + } + +} diff --git a/core/src/net/sf/openrocket/preset/ComponentPreset.java b/core/src/net/sf/openrocket/preset/ComponentPreset.java index cf24bb1b..504c72b4 100644 --- a/core/src/net/sf/openrocket/preset/ComponentPreset.java +++ b/core/src/net/sf/openrocket/preset/ComponentPreset.java @@ -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 */ -public class ComponentPreset { - - - private final String manufacturer; - private final String partNo; - private final String partDescription; - private final RocketComponent prototype; - - - public ComponentPreset(String manufacturer, String partNo, String partDescription, RocketComponent prototype) { - this.manufacturer = manufacturer; - this.partNo = partNo; - this.partDescription = partDescription; - this.prototype = prototype.copy(); - - 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"); - } +public class ComponentPreset extends TypedPropertyMap { + + // TODO - Implement clone. + // Implement "freezing" so the object cannot be modified. + + public enum Type { + BodyTube, + NoseCone + } + public final static TypedKey LENGTH = new TypedKey("Length", Double.class); + public final static TypedKey INNER_DIAMETER = new TypedKey("InnerDiameter", Double.class); + public final static TypedKey OUTER_DIAMETER = new TypedKey("OuterDiameter", Double.class); + public final static TypedKey MATERIAL = new TypedKey("Material", Material.class); + public final static TypedKey FINISH = new TypedKey("Finish",Finish.class); + public final static TypedKey THICKNESS = new TypedKey("Thickness", Double.class); + public final static TypedKey FILLED = new TypedKey("Filled",Boolean.class); + public final static TypedKey MASS = new TypedKey("Mass", Double.class); + + public final static Map> keyMap = new HashMap>(); + 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); } + + private String manufacturer; + private String partNo; + private String partDescription; + private Type type; - /** - * Return the component class that this preset defines. - */ - public Class getComponentClass() { - return prototype.getClass(); + public ComponentPreset() { + } - /** - * 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; } + } diff --git a/core/src/net/sf/openrocket/preset/TypedKey.java b/core/src/net/sf/openrocket/preset/TypedKey.java new file mode 100644 index 00000000..0d558944 --- /dev/null +++ b/core/src/net/sf/openrocket/preset/TypedKey.java @@ -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 { + + private final String name; + private final Class type; + + public TypedKey(String name, Class type) { + this.name = name; + this.type = type; + } + + public String getName() { + return name; + } + + public Class 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; + } + +} diff --git a/core/src/net/sf/openrocket/preset/TypedPropertyMap.java b/core/src/net/sf/openrocket/preset/TypedPropertyMap.java new file mode 100644 index 00000000..48d5bb94 --- /dev/null +++ b/core/src/net/sf/openrocket/preset/TypedPropertyMap.java @@ -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, Object> delegate; + + public TypedPropertyMap() { + delegate = new LinkedHashMap,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 get(TypedKey key) { + return (T) delegate.get(key); + } + + @SuppressWarnings("unchecked") + public T put(TypedKey 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> keySet() { + return delegate.keySet(); + } + + public Collection values() { + return delegate.values(); + } + + public Set, Object>> entrySet() { + return delegate.entrySet(); + } + + @Override + public boolean equals(Object o) { + return delegate.equals(o); + } + + @Override + public int hashCode() { + return delegate.hashCode(); + } + +} diff --git a/core/src/net/sf/openrocket/rocketcomponent/BodyComponent.java b/core/src/net/sf/openrocket/rocketcomponent/BodyComponent.java index a102e87f..1fcefa20 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/BodyComponent.java +++ b/core/src/net/sf/openrocket/rocketcomponent/BodyComponent.java @@ -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); } diff --git a/core/src/net/sf/openrocket/rocketcomponent/BodyTube.java b/core/src/net/sf/openrocket/rocketcomponent/BodyTube.java index 07bae722..8485c3fe 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/BodyTube.java +++ b/core/src/net/sf/openrocket/rocketcomponent/BodyTube.java @@ -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); diff --git a/core/src/net/sf/openrocket/rocketcomponent/ExternalComponent.java b/core/src/net/sf/openrocket/rocketcomponent/ExternalComponent.java index 85bc39f1..f981cf76 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/ExternalComponent.java +++ b/core/src/net/sf/openrocket/rocketcomponent/ExternalComponent.java @@ -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); + */ } } diff --git a/core/src/net/sf/openrocket/rocketcomponent/RocketComponent.java b/core/src/net/sf/openrocket/rocketcomponent/RocketComponent.java index b1a57dbf..566b793d 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/RocketComponent.java +++ b/core/src/net/sf/openrocket/rocketcomponent/RocketComponent.java @@ -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 } diff --git a/core/src/net/sf/openrocket/rocketcomponent/SymmetricComponent.java b/core/src/net/sf/openrocket/rocketcomponent/SymmetricComponent.java index 5dc18354..d2add384 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/SymmetricComponent.java +++ b/core/src/net/sf/openrocket/rocketcomponent/SymmetricComponent.java @@ -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); } -- 2.47.2