]> git.gag.com Git - debian/openrocket/commitdiff
Reimplement ComponentPreset to be a bag of typed parameters. This provides greater...
authorkruland2607 <kruland2607@180e2498-e6e9-4542-8430-84ac67f01cd8>
Sun, 1 Apr 2012 03:27:45 +0000 (03:27 +0000)
committerkruland2607 <kruland2607@180e2498-e6e9-4542-8430-84ac67f01cd8>
Sun, 1 Apr 2012 03:27:45 +0000 (03:27 +0000)
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

18 files changed:
core/resources/l10n/messages.properties
core/src/net/sf/openrocket/database/BodyTubePresetDao.java [deleted file]
core/src/net/sf/openrocket/database/ComponentPresetDao.java [new file with mode: 0644]
core/src/net/sf/openrocket/database/Daos.java
core/src/net/sf/openrocket/database/DaosImpl.java
core/src/net/sf/openrocket/file/preset/ColumnDefinition.java [new file with mode: 0644]
core/src/net/sf/openrocket/file/preset/PresetCSVReader.java [new file with mode: 0644]
core/src/net/sf/openrocket/gui/adaptors/BodyTubePresetModel.java
core/src/net/sf/openrocket/gui/configdialog/BodyTubeConfig.java
core/src/net/sf/openrocket/gui/dialogs/preset/ComponentPresetChooserDialog.java [new file with mode: 0644]
core/src/net/sf/openrocket/preset/ComponentPreset.java
core/src/net/sf/openrocket/preset/TypedKey.java [new file with mode: 0644]
core/src/net/sf/openrocket/preset/TypedPropertyMap.java [new file with mode: 0644]
core/src/net/sf/openrocket/rocketcomponent/BodyComponent.java
core/src/net/sf/openrocket/rocketcomponent/BodyTube.java
core/src/net/sf/openrocket/rocketcomponent/ExternalComponent.java
core/src/net/sf/openrocket/rocketcomponent/RocketComponent.java
core/src/net/sf/openrocket/rocketcomponent/SymmetricComponent.java

index f20e16407b24fb658c25ecf73c15e4535ec88761..5f057a9bbc6da8f1912ce8b82a7cd63dd275afdf 100644 (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
diff --git a/core/src/net/sf/openrocket/database/BodyTubePresetDao.java b/core/src/net/sf/openrocket/database/BodyTubePresetDao.java
deleted file mode 100644 (file)
index 733c7bc..0000000
+++ /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<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;
-       }
-       
-}
diff --git a/core/src/net/sf/openrocket/database/ComponentPresetDao.java b/core/src/net/sf/openrocket/database/ComponentPresetDao.java
new file mode 100644 (file)
index 0000000..d76e71d
--- /dev/null
@@ -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;
+       }
+       
+}
index 210a186a5fa2777f85ec41d950fce80b4fa49766..f19839e7184dab54c6c8c267cc8eda56027a7105 100644 (file)
@@ -2,6 +2,6 @@ package net.sf.openrocket.database;
 
 public interface Daos {
 
-       public BodyTubePresetDao getBodyTubePresetDao();
+       public ComponentPresetDao getBodyTubePresetDao();
        
 }
index c1fc44d817c4ea897a2b0428058297e4b440c623..fde421855ce8f08b2eee863a44547d4b96af4c4d 100644 (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;
        }
 
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 (file)
index 0000000..3e62286
--- /dev/null
@@ -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 (file)
index 0000000..928639e
--- /dev/null
@@ -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;
+       }
+       
+}
index 1f46062ac1a85f9fda5f75426affe232fcdcd7bd..08850b8f0a53a7947bef2e218f8b5bab42b8eb7d 100644 (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();
                }
        }
        
index b026a45544876ca3c7eeb5e8a7983a234e9aacb5..bfeed94470ceb19f41d3012ec68769cc49cf5f8f 100644 (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.
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 (file)
index 0000000..2364021
--- /dev/null
@@ -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);
+               }
+       }
+       
+}
index cf24bb1bdc073167c0eba644da0fa5665d500e57..504c72b439de95ec5f834b7b3edcb34fc3d48af9 100644 (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 {
-
-
-       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<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 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);
        }
+       
+       private String manufacturer;
+       private String partNo;
+       private String partDescription;
+       private Type type;
 
-       /**
-        * Return the component class that this preset defines.
-        */
-       public Class<? extends RocketComponent> 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 (file)
index 0000000..0d55894
--- /dev/null
@@ -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;
+       }
+       
+}
diff --git a/core/src/net/sf/openrocket/preset/TypedPropertyMap.java b/core/src/net/sf/openrocket/preset/TypedPropertyMap.java
new file mode 100644 (file)
index 0000000..48d5bb9
--- /dev/null
@@ -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();
+       }
+       
+}
index a102e87f720871ae46f1341a3f3f05280bb6c858..1fcefa20e476ff6295f1746556b0170586e0408c 100644 (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);
        }
index 07bae72246209497bffc3440798e8b2d0dbed275..8485c3fefe54e61c6d6ae0df8956679b06b7a0ce 100644 (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);
                
index 85bc39f19fe88c639b11371aa8780308a5162194..f981cf7669610389039182c5e65c52876fe2b10f 100644 (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);
+                       */
                }
        }
 
index b1a57dbfc8e7445a75a8b30bd926f126b3bbc519..566b793deefa6334b13cf1f062d6cb3c18e46178 100644 (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
        }
        
index 5dc1835463e9ed3bf2ad72207c0835607e2b167c..d2add38449db1d3539a921893446a6c8cca8e951 100644 (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);
        }