Component preset updates
authorplaa <plaa@180e2498-e6e9-4542-8430-84ac67f01cd8>
Mon, 18 Jun 2012 19:48:57 +0000 (19:48 +0000)
committerplaa <plaa@180e2498-e6e9-4542-8430-84ac67f01cd8>
Mon, 18 Jun 2012 19:48:57 +0000 (19:48 +0000)
git-svn-id: https://openrocket.svn.sourceforge.net/svnroot/openrocket/trunk@788 180e2498-e6e9-4542-8430-84ac67f01cd8

25 files changed:
core/resources/l10n/messages.properties
core/resources/pix/icons/copyright.txt
core/resources/pix/icons/star_gold.png [new file with mode: 0644]
core/resources/pix/icons/star_silver.png [new file with mode: 0644]
core/src/net/sf/openrocket/gui/adaptors/PresetModel.java
core/src/net/sf/openrocket/gui/components/StarCheckBox.java [new file with mode: 0644]
core/src/net/sf/openrocket/gui/configdialog/MassComponentConfig.java
core/src/net/sf/openrocket/gui/configdialog/RocketComponentConfig.java
core/src/net/sf/openrocket/gui/dialogs/preset/ComponentPresetChooserDialog.java
core/src/net/sf/openrocket/gui/dialogs/preset/ComponentPresetRowFilter.java
core/src/net/sf/openrocket/gui/dialogs/preset/ComponentPresetTable.java
core/src/net/sf/openrocket/gui/dialogs/preset/XTableColumnModel.java
core/src/net/sf/openrocket/gui/preset/PresetEditorDialog.java
core/src/net/sf/openrocket/gui/util/GUIUtil.java
core/src/net/sf/openrocket/gui/util/Icons.java
core/src/net/sf/openrocket/preset/ComponentPreset.java
core/src/net/sf/openrocket/rocketcomponent/MassComponent.java
core/src/net/sf/openrocket/unit/FractionalUnit.java
core/src/net/sf/openrocket/unit/UnitGroup.java
core/src/net/sf/openrocket/util/Chars.java
core/src/net/sf/openrocket/util/ExpressionParser.java
core/src/net/sf/openrocket/util/enums/EnumConversion.java [new file with mode: 0644]
core/src/net/sf/openrocket/util/enums/EnumName.java [new file with mode: 0644]
core/test/net/sf/openrocket/util/ExpressionParserTest.java
core/test/net/sf/openrocket/util/enums/TestEnumName.java [new file with mode: 0644]

index db2b58af2ec0c051bda7a46acff3c2de267629b0..0715bc7968fb823d3634ce75834294c6973fb87b 100644 (file)
@@ -807,6 +807,7 @@ LaunchLugCfg.tab.Generalprop = General properties
 
 ! MassComponentConfig
 MassComponentCfg.lbl.Mass = Mass:
+MassComponentCfg.lbl.Density = Approximate density:
 MassComponentCfg.lbl.Length = Length:
 MassComponentCfg.lbl.Diameter = Diameter:
 MassComponentCfg.lbl.PosRelativeto = Position relative to:
@@ -1644,13 +1645,13 @@ CustomFinImport.error.badimage = Could not deduce fin shape from image.
 CustomFinImport.description = The image will be converted internally to black and white image (black for the fin), so make sure you use a solid dark color for the fin, and white or a light color for the background. The fin must be touching the bottom of the image, which is the base of the fin.
 
 
-PresetModel.lbl.select = Select preset:
+PresetModel.lbl.select = Select preset
 PresetModel.lbl.database = From database...
 
 
 ! Component Preset Chooser Dialog
 ComponentPresetChooserDialog.title = Choose component preset
-ComponentPresetChooserDialog.filter.label = Filter:
+ComponentPresetChooserDialog.filter.label = Filter by text:
 ComponentPresetChooserDialog.checkbox.filterAftDiameter = Match aft diameter
 ComponentPresetChooserDialog.checkbox.filterForeDiameter = Match fore diameter
 ComponentPresetChooserDialog.menu.sortAsc = Sort Ascending
index 809fdd681fa4a849d84fd8baf7c43bb925a1d65a..b1fc04ea6b876554751874ce33e9e69a98b39c94 100644 (file)
@@ -38,3 +38,5 @@ help-log.png
 help-about.png
 help-bug.png
 help-tours.png
+star_silver.png
+star_gold.png (modified from star_silver.png)
diff --git a/core/resources/pix/icons/star_gold.png b/core/resources/pix/icons/star_gold.png
new file mode 100644 (file)
index 0000000..686aa93
Binary files /dev/null and b/core/resources/pix/icons/star_gold.png differ
diff --git a/core/resources/pix/icons/star_silver.png b/core/resources/pix/icons/star_silver.png
new file mode 100644 (file)
index 0000000..30245ee
Binary files /dev/null and b/core/resources/pix/icons/star_silver.png differ
index 9f148063a7a027a57c31dcf28bcca633480ec5a3..4dca6f568e40bf9a0e2aa5c61da83d17c3e7805b 100644 (file)
@@ -17,21 +17,22 @@ import net.sf.openrocket.rocketcomponent.ComponentChangeEvent;
 import net.sf.openrocket.rocketcomponent.ComponentChangeListener;
 import net.sf.openrocket.rocketcomponent.RocketComponent;
 import net.sf.openrocket.startup.Application;
+import net.sf.openrocket.util.BugException;
 
 public class PresetModel extends AbstractListModel implements ComboBoxModel, ComponentChangeListener, DatabaseListener<ComponentPreset> {
-
+       
        private static final LogHelper log = Application.getLogger();
        private static final Translator trans = Application.getTranslator();
-
-       private static final String NONE_SELECTED = "";
+       
+       private static final String NONE_SELECTED = trans.get("lbl.select");
        private static final String SELECT_DATABASE = trans.get("lbl.database");
-
+       
        private final Component parent;
        private final RocketComponent component;
        private ComponentPreset previousPreset;
-
+       
        private List<ComponentPreset> presets;
-
+       
        public PresetModel(Component parent, RocketComponent component) {
                this.parent = parent;
                presets = Application.getComponentPresetDao().listForType(component.getPresetType(), true);
@@ -39,12 +40,12 @@ public class PresetModel extends AbstractListModel implements ComboBoxModel, Com
                previousPreset = component.getPresetComponent();
                component.addComponentChangeListener(this);
        }
-
+       
        @Override
        public int getSize() {
                return presets.size() + 2;
        }
-
+       
        @Override
        public Object getElementAt(int index) {
                if (index == 0) {
@@ -55,26 +56,27 @@ public class PresetModel extends AbstractListModel implements ComboBoxModel, Com
                }
                return presets.get(index - 1);
        }
-
+       
        @Override
        public void setSelectedItem(Object item) {
                log.user("User selected preset item '" + item + "' for component " + component);
-
+               
                if (item == null) {
                        // FIXME:  What to do?
+                       throw new BugException("item is null");
                } else if (item.equals(NONE_SELECTED)) {
                        component.clearPreset();
                } else if (item.equals(SELECT_DATABASE)) {
-                       SwingUtilities.invokeLater( new Runnable() {
+                       SwingUtilities.invokeLater(new Runnable() {
                                @Override
                                public void run() {
-                                       ComponentPresetChooserDialog dialog = 
-                                                       new ComponentPresetChooserDialog( SwingUtilities.getWindowAncestor(PresetModel.this.parent),
-                                                                       PresetModel.this.component);
+                                       ComponentPresetChooserDialog dialog =
+                                                       new ComponentPresetChooserDialog(SwingUtilities.getWindowAncestor(parent), component);
                                        dialog.setVisible(true);
                                        ComponentPreset preset = dialog.getSelectedComponentPreset();
-                                       setSelectedItem(preset);
-
+                                       if (preset != null) {
+                                               setSelectedItem(preset);
+                                       }
                                }
                        });
                } else {
@@ -82,7 +84,7 @@ public class PresetModel extends AbstractListModel implements ComboBoxModel, Com
                        component.loadPreset((ComponentPreset) item);
                }
        }
-
+       
        @Override
        public Object getSelectedItem() {
                ComponentPreset preset = component.getPresetComponent();
@@ -92,7 +94,7 @@ public class PresetModel extends AbstractListModel implements ComboBoxModel, Com
                        return preset;
                }
        }
-
+       
        @Override
        public void componentChanged(ComponentChangeEvent e) {
                if (previousPreset != component.getPresetComponent()) {
@@ -100,17 +102,17 @@ public class PresetModel extends AbstractListModel implements ComboBoxModel, Com
                        fireContentsChanged(this, 0, getSize());
                }
        }
-
+       
        @Override
        public void elementAdded(ComponentPreset element, Database<ComponentPreset> source) {
                presets = Application.getComponentPresetDao().listForType(component.getPresetType(), true);
                this.fireContentsChanged(this, 0, getSize());
        }
-
+       
        @Override
        public void elementRemoved(ComponentPreset element, Database<ComponentPreset> source) {
                presets = Application.getComponentPresetDao().listForType(component.getPresetType(), true);
                this.fireContentsChanged(this, 0, getSize());
        }
-
+       
 }
diff --git a/core/src/net/sf/openrocket/gui/components/StarCheckBox.java b/core/src/net/sf/openrocket/gui/components/StarCheckBox.java
new file mode 100644 (file)
index 0000000..a7bdb6d
--- /dev/null
@@ -0,0 +1,20 @@
+package net.sf.openrocket.gui.components;
+
+import java.awt.Graphics;
+
+import javax.swing.JCheckBox;
+import javax.swing.JLabel;
+
+import net.sf.openrocket.gui.util.Icons;
+
+public class StarCheckBox extends JCheckBox {
+       
+       
+       
+       @Override
+       public void paint(Graphics g) {
+               JLabel l = new JLabel(Icons.FAVORITE);
+               l.paint(g);
+       }
+       
+}
index 09b3297bb217e008934d8d9285822ecc5985a12e..cf70d463fe715244e290000cc31e566a207f1762 100644 (file)
@@ -47,6 +47,18 @@ public class MassComponentConfig extends RocketComponentConfig {
                panel.add(new BasicSlider(m.getSliderModel(0, 0.05, 0.5)), "w 100lp, wrap");
                
                
+               panel.add(new JLabel(trans.get("MassComponentCfg.lbl.Density")));
+               
+               m = new DoubleModel(component, "Density", UnitGroup.UNITS_DENSITY_BULK, 0);
+               
+               spin = new JSpinner(m.getSpinnerModel());
+               spin.setEditor(new SpinnerEditor(spin));
+               panel.add(spin, "growx");
+               
+               panel.add(new UnitSelector(m), "growx");
+               panel.add(new BasicSlider(m.getSliderModel(500, 2000, 10000)), "w 100lp, wrap");
+               
+               
                
                ////  Mass length
                //// Length
index de867ba4c2b950b875aaff60721781e9b048ab3f..24d8220f8a6efe0603e6fb62131ddeeabfed8164 100644 (file)
@@ -43,6 +43,7 @@ import net.sf.openrocket.gui.util.GUIUtil;
 import net.sf.openrocket.gui.util.SwingPreferences;
 import net.sf.openrocket.l10n.Translator;
 import net.sf.openrocket.material.Material;
+import net.sf.openrocket.preset.ComponentPreset;
 import net.sf.openrocket.rocketcomponent.ComponentAssembly;
 import net.sf.openrocket.rocketcomponent.ExternalComponent;
 import net.sf.openrocket.rocketcomponent.ExternalComponent.Finish;
@@ -65,7 +66,7 @@ public class RocketComponentConfig extends JPanel {
        
        private JComboBox presetComboBox;
        private PresetModel presetModel;
-
+       
        protected final JTextField componentNameField;
        protected JTextArea commentTextArea;
        private final TextFieldListener textFieldListener;
@@ -73,7 +74,7 @@ public class RocketComponentConfig extends JPanel {
        private JCheckBox colorDefault;
        private JPanel buttonPanel;
        
-       private JLabel massLabel;
+       private JLabel infoLabel;
        
        
        public RocketComponentConfig(OpenRocketDocument document, RocketComponent component) {
@@ -85,7 +86,7 @@ public class RocketComponentConfig extends JPanel {
                JLabel label = new JLabel(trans.get("RocketCompCfg.lbl.Componentname"));
                //// The component name.
                label.setToolTipText(trans.get("RocketCompCfg.ttip.Thecomponentname"));
-               this.add(label);
+               this.add(label, "spanx, split");
                
                componentNameField = new JTextField(15);
                textFieldListener = new TextFieldListener();
@@ -93,21 +94,20 @@ public class RocketComponentConfig extends JPanel {
                componentNameField.addFocusListener(textFieldListener);
                //// The component name.
                componentNameField.setToolTipText(trans.get("RocketCompCfg.ttip.Thecomponentname"));
-               this.add(componentNameField, "wrap");
+               this.add(componentNameField, "growx");
                
-               if ( component.getPresetType() != null ) {
+               if (component.getPresetType() != null) {
                        // If the component supports a preset, show the preset selection box.
-                       this.add(new JLabel(trans.get("PresetModel.lbl.select")));
-                       presetModel = new PresetModel( this, component);
-                       ((ComponentPresetDatabase)Application.getComponentPresetDao()).addDatabaseListener(presetModel);
+                       presetModel = new PresetModel(this, component);
+                       ((ComponentPresetDatabase) Application.getComponentPresetDao()).addDatabaseListener(presetModel);
                        presetComboBox = new JComboBox(presetModel);
                        presetComboBox.setEditable(false);
-                       this.add(presetComboBox, "wrap");
+                       this.add(presetComboBox, "");
                }
                
-
+               
                tabbedPane = new JTabbedPane();
-               this.add(tabbedPane, "span, growx, growy 1, wrap");
+               this.add(tabbedPane, "newline, span, growx, growy 1, wrap");
                
                //// Override and Mass and CG override options
                tabbedPane.addTab(trans.get("RocketCompCfg.tab.Override"), null, overrideTab(),
@@ -134,8 +134,8 @@ public class RocketComponentConfig extends JPanel {
                buttonPanel = new JPanel(new MigLayout("fill, ins 0"));
                
                //// Mass:
-               massLabel = new StyledLabel(trans.get("RocketCompCfg.lbl.Mass") + " ", -1);
-               buttonPanel.add(massLabel, "growx");
+               infoLabel = new StyledLabel(" ", -1);
+               buttonPanel.add(infoLabel, "growx");
                
                for (JButton b : buttons) {
                        buttonPanel.add(b, "right, gap para");
@@ -173,33 +173,38 @@ public class RocketComponentConfig extends JPanel {
                                colorDefault.setSelected(component.getColor() == null);
                }
                
-               // Mass label
+               // Info label
+               StringBuilder sb = new StringBuilder();
+               
+               if (component.getPresetComponent() != null) {
+                       ComponentPreset preset = component.getPresetComponent();
+                       sb.append(preset.getManufacturer() + " " + preset.getPartNo() + "      ");
+               }
+               
                if (component.isMassive()) {
-                       //// Component mass:
-                       String text = trans.get("RocketCompCfg.lbl.Componentmass") + " ";
-                       text += UnitGroup.UNITS_MASS.getDefaultUnit().toStringUnit(
-                                       component.getComponentMass());
+                       sb.append(trans.get("RocketCompCfg.lbl.Componentmass") + " ");
+                       sb.append(UnitGroup.UNITS_MASS.getDefaultUnit().toStringUnit(
+                                       component.getComponentMass()));
                        
                        String overridetext = null;
                        if (component.isMassOverridden()) {
-                               //// (overridden to 
                                overridetext = trans.get("RocketCompCfg.lbl.overriddento") + " " + UnitGroup.UNITS_MASS.getDefaultUnit().
                                                toStringUnit(component.getOverrideMass()) + ")";
                        }
                        
                        for (RocketComponent c = component.getParent(); c != null; c = c.getParent()) {
                                if (c.isMassOverridden() && c.getOverrideSubcomponents()) {
-                                       ///// (overridden by
                                        overridetext = trans.get("RocketCompCfg.lbl.overriddenby") + " " + c.getName() + ")";
                                }
                        }
                        
-                       if (overridetext != null)
-                               text = text + " " + overridetext;
+                       if (overridetext != null) {
+                               sb.append(" " + overridetext);
+                       }
                        
-                       massLabel.setText(text);
+                       infoLabel.setText(sb.toString());
                } else {
-                       massLabel.setText("");
+                       infoLabel.setText("");
                }
        }
        
@@ -651,8 +656,8 @@ public class RocketComponentConfig extends JPanel {
                for (Invalidatable i : invalidatables) {
                        i.invalidate();
                }
-               ((ComponentPresetDatabase)Application.getComponentPresetDao()).removeChangeListener(presetModel);
-
+               ((ComponentPresetDatabase) Application.getComponentPresetDao()).removeChangeListener(presetModel);
+               
        }
        
 }
\ No newline at end of file
index e17acf2bb0af48c12e2c45cf4cece8c4fba7e520..b74bd827182dec2e0613f812b2e08808eec3772f 100644 (file)
@@ -21,6 +21,7 @@ import javax.swing.JTextField;
 import javax.swing.RowFilter;
 import javax.swing.event.DocumentEvent;
 import javax.swing.event.DocumentListener;
+import javax.swing.table.TableColumn;
 import javax.swing.table.TableModel;
 
 import net.miginfocom.swing.MigLayout;
@@ -28,194 +29,205 @@ import net.sf.openrocket.gui.util.GUIUtil;
 import net.sf.openrocket.l10n.Translator;
 import net.sf.openrocket.preset.ComponentPreset;
 import net.sf.openrocket.preset.TypedKey;
-import net.sf.openrocket.rocketcomponent.ExternalComponent;
-import net.sf.openrocket.rocketcomponent.InternalComponent;
 import net.sf.openrocket.rocketcomponent.RocketComponent;
 import net.sf.openrocket.rocketcomponent.SymmetricComponent;
 import net.sf.openrocket.startup.Application;
 
+/**
+ * Dialog shown for selecting a preset component.
+ */
 public class ComponentPresetChooserDialog extends JDialog {
-
+       
        private static final Translator trans = Application.getTranslator();
-
+       
        private final RocketComponent component;
-
+       
        private ComponentPresetTable componentSelectionTable;
-       private final JTextField filterText;
-       private final JCheckBox foreDiameterFilterCheckBox;
-       private final JCheckBox aftDiameterFilterCheckBox;
-
+       private JTextField filterText;
+       private JCheckBox foreDiameterFilterCheckBox;
+       private JCheckBox aftDiameterFilterCheckBox;
+       
+       private ComponentPresetRowFilter foreDiameterFilter;
+       private ComponentPresetRowFilter aftDiameterFilter;
+       
+       
        /*
         * outerDiamtereColumnIndex is the index of the column associated with the OUTER_DIAMETER
         * field.  This index is needed by the matchOuterDiameterCheckBox to implement filtering.
         */
        int aftDiameterColumnIndex = -1;
        int foreDiameterColumnIndex = -1;
-
+       
        private List<ComponentPreset> presets;
-
+       
        private boolean okClicked = false;
-
-
+       
+       
        public ComponentPresetChooserDialog(Window owner, RocketComponent component) {
                super(owner, trans.get("title"), Dialog.ModalityType.APPLICATION_MODAL);
                this.component = component;
                this.presets = Application.getComponentPresetDao().listForType(component.getPresetType());
                
-               List<TypedKey<?>> displayedColumnKeys = Arrays.<TypedKey<?>>asList(component.getPresetType().getDisplayedColumns());
+               List<TypedKey<?>> displayedColumnKeys = Arrays.asList(component.getPresetType().getDisplayedColumns());
+               
                {
-                       final List<TypedKey<?>> columnKeys = ComponentPreset.orderedKeyList;
-                       int i=0;  // We start at 0 but use preincrement because the first column is favorite.
+                       final List<TypedKey<?>> columnKeys = ComponentPreset.ORDERED_KEY_LIST;
+                       int i = 0; // We start at 0 but use preincrement because the first column is favorite.
                        for (final TypedKey<?> key : columnKeys) {
                                // Note the increment early in the loop.  This really means that initial loop i=1
                                // we do it here so the continue below doesn't mess up the counting.
                                i++;
                                // Don't allow the matching filters if the column is not part of the default set for
                                // this kind of preset.
-                               if ( ! displayedColumnKeys.contains(key) ) { 
+                               if (!displayedColumnKeys.contains(key)) {
                                        continue;
                                }
-                               if ( key == ComponentPreset.OUTER_DIAMETER || key == ComponentPreset.AFT_OUTER_DIAMETER ) {
+                               if (key == ComponentPreset.OUTER_DIAMETER || key == ComponentPreset.AFT_OUTER_DIAMETER) {
                                        aftDiameterColumnIndex = i;
                                }
-                               if ( key == ComponentPreset.OUTER_DIAMETER || key == ComponentPreset.FORE_OUTER_DIAMETER ) {
+                               if (key == ComponentPreset.OUTER_DIAMETER || key == ComponentPreset.FORE_OUTER_DIAMETER) {
                                        foreDiameterColumnIndex = i;
                                }
                        }
                }
                
+               
+               JPanel panel = new JPanel(new MigLayout("fill, ins para"));
+               
                /*
                 * Add filter by text.
                 */
-               JPanel panel = new JPanel(new MigLayout("fill"));
+               JPanel sub = new JPanel(new MigLayout("fill, ins 0"));
                JLabel filterLabel = new JLabel(trans.get("ComponentPresetChooserDialog.filter.label"));
-               panel.add(filterLabel);
-               filterText = new JTextField(15);
-               panel.add(filterText,"growx, growy 0, wrap");
+               sub.add(filterLabel, "gapright para");
+               
+               filterText = new JTextField();
+               sub.add(filterText, "growx");
                filterText.getDocument().addDocumentListener(new DocumentListener() {
                        @Override
                        public void changedUpdate(DocumentEvent e) {
                                updateFilters();
                        }
+                       
                        @Override
                        public void insertUpdate(DocumentEvent e) {
                                updateFilters();
                        }
+                       
                        @Override
                        public void removeUpdate(DocumentEvent e) {
                                updateFilters();
                        }
                });
-
+               
+               panel.add(sub, "growx, ay 0, gapright para");
+               
+               
+               panel.add(getFilterCheckboxes(), "wrap para");
+               
+               
+               componentSelectionTable = new ComponentPresetTable(presets, displayedColumnKeys);
+               //              GUIUtil.setAutomaticColumnTableWidths(componentSelectionTable, 20);
+               int w = componentSelectionTable.getRowHeight() + 4;
+               TableColumn tc = componentSelectionTable.getColumnModel().getColumn(0);
+               tc.setPreferredWidth(w);
+               tc.setMaxWidth(w);
+               tc.setMinWidth(w);
+               
+               JScrollPane scrollpane = new JScrollPane();
+               scrollpane.setViewportView(componentSelectionTable);
+               panel.add(scrollpane, "grow, width 700lp, height 300lp, spanx, 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);
+               
+               GUIUtil.rememberWindowSize(this);
+               GUIUtil.setDisposableDialogOptions(this, okButton);
+       }
+       
+       
+       private JPanel getFilterCheckboxes() {
+               SymmetricComponent sc;
+               
+               JPanel panel = new JPanel(new MigLayout("fill, ins 0"));
+               
                /*
                 * Add show all compatible check box.
                 */
                final List<ComponentPreset.Type> compatibleTypes = component.getPresetType().getCompatibleTypes();
                final ComponentPreset.Type nativeType = component.getPresetType();
-               if ( compatibleTypes != null && compatibleTypes.size() >  0 ) {
+               if (compatibleTypes != null && compatibleTypes.size() > 0) {
                        JCheckBox showAll = new JCheckBox();
                        showAll.setText(trans.get("ComponentPresetChooserDialog.checkbox.showAllCompatible"));
-                       panel.add(showAll, "skip, span 2");
-                       showAll.addItemListener( new ItemListener () {
+                       panel.add(showAll, "wrap");
+                       showAll.addItemListener(new ItemListener() {
                                @Override
                                public void itemStateChanged(ItemEvent e) {
-                                       if ( ((JCheckBox)e.getItem()).isSelected()  ) {
+                                       if (((JCheckBox) e.getItem()).isSelected()) {
                                                presets = Application.getComponentPresetDao().listForTypes(compatibleTypes);
                                        } else {
                                                presets = Application.getComponentPresetDao().listForType(nativeType);
                                        }
-                                       componentSelectionTable.updateData( presets );
+                                       componentSelectionTable.updateData(presets);
                                }
                        });
-
-
                }
-
+               
                /*
                 * Add filter by fore diameter
                 */
-               foreDiameterFilterCheckBox = new JCheckBox();
-               foreDiameterFilterCheckBox.setText(trans.get("ComponentPresetChooserDialog.checkbox.filterForeDiameter"));
-               panel.add(foreDiameterFilterCheckBox, "skip, span 2");
-               foreDiameterFilterCheckBox.addItemListener( new ItemListener () {
-                       @Override
-                       public void itemStateChanged(ItemEvent e) {
-                               updateFilters();
-                       }
-               });
-
-               RocketComponent previousComponent = component.getPreviousComponent(); 
-               /* hide the fore diameter filter if it is not applicable */
-               if ( foreDiameterColumnIndex < 0 ) {
-                       foreDiameterFilterCheckBox.setVisible(false);
-               }
-               if ( previousComponent == null ) {
-                       foreDiameterFilterCheckBox.setVisible(false);
-               } else {
-                       if ( !(previousComponent instanceof ExternalComponent) && !(previousComponent instanceof InternalComponent) )
-                               foreDiameterFilterCheckBox.setVisible(false);
+               foreDiameterFilterCheckBox = new JCheckBox(trans.get("ComponentPresetChooserDialog.checkbox.filterForeDiameter"));
+               sc = getPreviousSymmetricComponent();
+               if (sc != null && foreDiameterColumnIndex >= 0) {
+                       foreDiameterFilter = new ComponentPresetRowFilter(sc.getAftRadius() * 2.0, foreDiameterColumnIndex);
+                       panel.add(foreDiameterFilterCheckBox, "wrap");
+                       foreDiameterFilterCheckBox.addItemListener(new ItemListener() {
+                               @Override
+                               public void itemStateChanged(ItemEvent e) {
+                                       updateFilters();
+                               }
+                       });
                }
-
+               
                /*
                 * Add filter by aft diameter
                 */
-               aftDiameterFilterCheckBox = new JCheckBox();
-               aftDiameterFilterCheckBox.setText(trans.get("ComponentPresetChooserDialog.checkbox.filterAftDiameter"));
-               panel.add(aftDiameterFilterCheckBox, "skip, span 2, wrap");
-               aftDiameterFilterCheckBox.addItemListener( new ItemListener () {
-                       @Override
-                       public void itemStateChanged(ItemEvent e) {
-                               updateFilters();
-                       }
-               });
-
-               RocketComponent nextComponent = component.getNextComponent();
-               /* hide the aft diameter filter if it is not applicable */
-               if ( aftDiameterColumnIndex < 0 ) {
-                       aftDiameterFilterCheckBox.setVisible(false);
-               }
-               if ( nextComponent == null ) {
-                       aftDiameterFilterCheckBox.setVisible(false);
-               } else if ( !(nextComponent instanceof ExternalComponent) && !(nextComponent instanceof InternalComponent)) {
-                       aftDiameterFilterCheckBox.setVisible(false);
+               aftDiameterFilterCheckBox = new JCheckBox(trans.get("ComponentPresetChooserDialog.checkbox.filterAftDiameter"));
+               sc = getNextSymmetricComponent();
+               if (sc != null && aftDiameterColumnIndex >= 0) {
+                       aftDiameterFilter = new ComponentPresetRowFilter(sc.getForeRadius() * 2.0, aftDiameterColumnIndex);
+                       panel.add(aftDiameterFilterCheckBox, "wrap");
+                       aftDiameterFilterCheckBox.addItemListener(new ItemListener() {
+                               @Override
+                               public void itemStateChanged(ItemEvent e) {
+                                       updateFilters();
+                               }
+                       });
                }
-
-               componentSelectionTable = new ComponentPresetTable( presets, displayedColumnKeys );
-
-               JScrollPane scrollpane = new JScrollPane();
-               scrollpane.setViewportView(componentSelectionTable);
-               panel.add(scrollpane, "grow, width :500:, height :300:, spanx, 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);
-
+               
+               return panel;
        }
-
+       
        /**
         * Return the motor selected by this chooser dialog, or <code>null</code> if the selection has been aborted.
         * 
@@ -228,60 +240,54 @@ public class ComponentPresetChooserDialog extends JDialog {
                row = componentSelectionTable.convertRowIndexToModel(row);
                return presets.get(row);
        }
-
+       
        public void close(boolean ok) {
                okClicked = ok;
                this.setVisible(false);
        }
-
+       
        private void updateFilters() {
-               List<RowFilter<TableModel,Object>> filters = new ArrayList<RowFilter<TableModel,Object>> (2);
+               List<RowFilter<TableModel, Object>> filters = new ArrayList<RowFilter<TableModel, Object>>(2);
                String filterTextRegex = filterText.getText();
-               if ( filterTextRegex != null ) {
+               if (filterTextRegex != null) {
                        try {
                                // The "(?iu)" magic turns on case insensitivity with unicode chars
-                               RowFilter<TableModel,Object> regexFilter = RowFilter.regexFilter("(?iu)"+filterTextRegex);
+                               RowFilter<TableModel, Object> regexFilter = RowFilter.regexFilter("(?iu)" + filterTextRegex);
                                filters.add(regexFilter);
-                       } catch ( java.util.regex.PatternSyntaxException e ) {
+                       } catch (java.util.regex.PatternSyntaxException e) {
                        }
                }
-               if ( aftDiameterFilterCheckBox.isSelected() ) {
-                       // FIXME - please verify this logic looks correct.
-                       // Grab the next component.
-                       // If this.component is an InternalComponent, then we want to filter the outer diameter field
-                       // against the next component's inner diameter.
-                       RocketComponent nextComponent = component.getNextComponent();
-                       if ( nextComponent != null && nextComponent instanceof SymmetricComponent ) {
-                               SymmetricComponent parent = (SymmetricComponent) nextComponent;
-                               double nextDiameter;
-                               if ( this.component instanceof InternalComponent ) {
-                                       nextDiameter = parent.getInnerRadius(0) * 2.0;
-                               } else {
-                                       nextDiameter = parent.getForeRadius() * 2.0;
-                               }
-                               RowFilter<TableModel,Object> outerDiameterFilter = new ComponentPresetRowFilter( nextDiameter, aftDiameterColumnIndex);
-                               filters.add(outerDiameterFilter);
+               if (aftDiameterFilterCheckBox.isSelected()) {
+                       filters.add(aftDiameterFilter);
+               }
+               if (foreDiameterFilterCheckBox.isSelected()) {
+                       filters.add(foreDiameterFilter);
+               }
+               
+               componentSelectionTable.setRowFilter(RowFilter.andFilter(filters));
+       }
+       
+       
+       private SymmetricComponent getPreviousSymmetricComponent() {
+               RocketComponent c = component;
+               while (c != null) {
+                       c = c.getPreviousComponent();
+                       if (c instanceof SymmetricComponent) {
+                               return (SymmetricComponent) c;
                        }
                }
-               if ( foreDiameterFilterCheckBox.isSelected() ) {
-                       // FIXME - please verify this logic looks correct.
-                       // Grab the previous component.
-                       // If this.component is an InternalComponent, then we want to filter the outer diameter field
-                       // against the previous component's inner diameter.
-                       RocketComponent previousComponent = component.getPreviousComponent();
-                       if ( previousComponent != null && previousComponent instanceof SymmetricComponent ) {
-                               SymmetricComponent parent = (SymmetricComponent) previousComponent;
-                               double previousDaimeter;
-                               if ( this.component instanceof InternalComponent ) {
-                                       previousDaimeter = parent.getInnerRadius(parent.getLength()) * 2.0;
-                               } else {
-                                       previousDaimeter = parent.getAftRadius() * 2.0;
-                               }
-                               RowFilter<TableModel,Object> outerDiameterFilter = new ComponentPresetRowFilter( previousDaimeter, foreDiameterColumnIndex);
-                               filters.add(outerDiameterFilter);
+               return null;
+       }
+       
+       
+       private SymmetricComponent getNextSymmetricComponent() {
+               RocketComponent c = component;
+               while (c != null) {
+                       c = c.getNextComponent();
+                       if (c instanceof SymmetricComponent) {
+                               return (SymmetricComponent) c;
                        }
                }
-
-               componentSelectionTable.setRowFilter( RowFilter.andFilter(filters) );
+               return null;
        }
 }
index 283ec027901fb91265fb01b89fab79c695434ac7..7c66aa136d593b42cd6900f00769cbc6c9a1811b 100644 (file)
@@ -4,31 +4,35 @@ import javax.swing.RowFilter;
 import javax.swing.table.TableModel;
 
 import net.sf.openrocket.unit.Value;
+import net.sf.openrocket.util.MathUtil;
 
 public class ComponentPresetRowFilter extends RowFilter<TableModel, Object> {
        
        private final double value;
        private final int column;
-       // I chose epsilon to be 0.005 units.  Since this is mostly used diameters, it represents 5mm.
-       private final double epsilon = .005;
+       private final double epsilon;
        
-       ComponentPresetRowFilter( double value, int column ) {
+       ComponentPresetRowFilter(double value, int column) {
                this.value = value;
                this.column = column;
+               /*
+                * Accept 5% difference, but at least 1mm.
+                */
+               this.epsilon = MathUtil.max(value * 0.05, 0.001);
        }
-
+       
        @Override
-       public boolean include( RowFilter.Entry<? extends TableModel, ? extends Object> entry) {
+       public boolean include(RowFilter.Entry<? extends TableModel, ? extends Object> entry) {
                Object o = entry.getValue(column);
-               if ( o instanceof Value ) {
-                       Value v = (Value)o;
-                       return Math.abs( value - v.getValue() ) < epsilon;
+               if (o instanceof Value) {
+                       Value v = (Value) o;
+                       return Math.abs(value - v.getValue()) < epsilon;
                }
-               if ( o instanceof Double ) {
+               if (o instanceof Double) {
                        Double d = (Double) o;
-                       return Math.abs( value - d ) < epsilon;
+                       return Math.abs(value - d) < epsilon;
                }
                return true;
        }
-
+       
 }
index e74669cea9dc9a721a5401efa076a451721d06b8..175e08585095c9d0733493d4c07890a825d8ed21 100644 (file)
@@ -45,7 +45,7 @@ public class ComponentPresetTable extends JTable {
        public ComponentPresetTable(List<ComponentPreset> presets, List<TypedKey<?>> visibleColumnKeys) {
                super();
                this.presets = presets;
-               this.columns = new ComponentPresetTableColumn[ComponentPreset.orderedKeyList.size()+1];
+               this.columns = new ComponentPresetTableColumn[ComponentPreset.ORDERED_KEY_LIST.size()+1];
 
 
                tableModel = new AbstractTableModel() {
@@ -101,7 +101,7 @@ public class ComponentPresetTable extends JTable {
                List<TableColumn> hiddenColumns = new ArrayList<TableColumn>();
                {
                        int index = 1;
-                       for (final TypedKey<?> key: ComponentPreset.orderedKeyList ) {
+                       for (final TypedKey<?> key: ComponentPreset.ORDERED_KEY_LIST ) {
                                if ( key.getType() == Double.class && key.getUnitGroup() != null ) {
                                        columns[index] = new ComponentPresetTableColumn.DoubleWithUnit((TypedKey<Double>)key,index);
                                } else {
index 9968e247236136e62656d955b31999ae3485dfb0..ac05c7894d5bfd3b1fc85e12163376b404eb8dd8 100644 (file)
@@ -6,20 +6,20 @@ import java.util.Vector;
 import javax.swing.table.DefaultTableColumnModel;
 import javax.swing.table.TableColumn;
 
-public class XTableColumnModel extends DefaultTableColumnModel  {
-
+public class XTableColumnModel extends DefaultTableColumnModel {
+       
        /** Array of TableColumn objects in this model.
         *  Holds all column objects, regardless of their visibility
         */
        protected Vector<TableColumn> allTableColumns = new Vector<TableColumn>();
-
+       
        /**
         * Creates an extended table column model.
         */
        XTableColumnModel() {
                super();
        }
-
+       
        /**
         * Sets the visibility of the specified TableColumn.
         * The call is ignored if the TableColumn is not found in this column model
@@ -31,47 +31,47 @@ public class XTableColumnModel extends DefaultTableColumnModel  {
         */
        // listeners will receive columnAdded()/columnRemoved() event
        public void setColumnVisible(TableColumn column, boolean visible) {
-               if(!visible) {
+               if (!visible) {
                        super.removeColumn(column);
                }
                else {
                        // find the visible index of the column:
                        // iterate through both collections of visible and all columns, counting
                        // visible columns up to the one that's about to be shown again
-                       int noVisibleColumns    = tableColumns.size();
-                       int noInvisibleColumns  = allTableColumns.size();
-                       int visibleIndex        = 0;
-
-                       for(int invisibleIndex = 0; invisibleIndex < noInvisibleColumns; ++invisibleIndex) {
-                               TableColumn visibleColumn   = (visibleIndex < noVisibleColumns ? (TableColumn)tableColumns.get(visibleIndex) : null);
-                               TableColumn testColumn      = (TableColumn)allTableColumns.get(invisibleIndex);
-
-                               if(testColumn == column) {
-                                       if(visibleColumn != column) {
+                       int noVisibleColumns = tableColumns.size();
+                       int noInvisibleColumns = allTableColumns.size();
+                       int visibleIndex = 0;
+                       
+                       for (int invisibleIndex = 0; invisibleIndex < noInvisibleColumns; ++invisibleIndex) {
+                               TableColumn visibleColumn = (visibleIndex < noVisibleColumns ? (TableColumn) tableColumns.get(visibleIndex) : null);
+                               TableColumn testColumn allTableColumns.get(invisibleIndex);
+                               
+                               if (testColumn == column) {
+                                       if (visibleColumn != column) {
                                                super.addColumn(column);
                                                super.moveColumn(tableColumns.size() - 1, visibleIndex);
                                        }
                                        return; // ####################
                                }
-                               if(testColumn == visibleColumn) {
+                               if (testColumn == visibleColumn) {
                                        ++visibleIndex;
                                }
                        }
                }
        }
-
+       
        /**
         * Makes all columns in this model visible
         */
        public void setAllColumnsVisible(boolean visible) {
-               int noColumns       = allTableColumns.size();
-
-               for(int columnIndex = 0; columnIndex < noColumns; ++columnIndex) {
-                       TableColumn visibleColumn = (columnIndex < tableColumns.size() ? (TableColumn)tableColumns.get(columnIndex) : null);
-                       TableColumn invisibleColumn = (TableColumn)allTableColumns.get(columnIndex);
-                       if ( visible ) {
-
-                               if(visibleColumn != invisibleColumn) {
+               int noColumns = allTableColumns.size();
+               
+               for (int columnIndex = 0; columnIndex < noColumns; ++columnIndex) {
+                       TableColumn visibleColumn = (columnIndex < tableColumns.size() ? (TableColumn) tableColumns.get(columnIndex) : null);
+                       TableColumn invisibleColumn = allTableColumns.get(columnIndex);
+                       if (visible) {
+                               
+                               if (visibleColumn != invisibleColumn) {
                                        super.addColumn(invisibleColumn);
                                        super.moveColumn(tableColumns.size() - 1, columnIndex);
                                }
@@ -80,7 +80,7 @@ public class XTableColumnModel extends DefaultTableColumnModel  {
                        }
                }
        }
-
+       
        /**
         * Maps the index of the column in the table model at
         * <code>modelColumnIndex</code> to the TableColumn object.
@@ -91,50 +91,51 @@ public class XTableColumnModel extends DefaultTableColumnModel  {
         */
        public TableColumn getColumnByModelIndex(int modelColumnIndex) {
                for (int columnIndex = 0; columnIndex < allTableColumns.size(); ++columnIndex) {
-                       TableColumn column = (TableColumn)allTableColumns.get(columnIndex);
-                       if(column.getModelIndex() == modelColumnIndex) {
+                       TableColumn column = allTableColumns.get(columnIndex);
+                       if (column.getModelIndex() == modelColumnIndex) {
                                return column;
                        }
                }
                return null;
        }
-
+       
        /** Checks wether the specified column is currently visible.
         * @param aColumn column to check
         * @return visibility of specified column (false if there is no such column at all. [It's not visible, right?])
-        */    
+        */
        public boolean isColumnVisible(TableColumn aColumn) {
                return (tableColumns.indexOf(aColumn) >= 0);
        }
-
+       
        /** Append <code>column</code> to the right of exisiting columns.
         * Posts <code>columnAdded</code> event.
         * @param column The column to be added
         * @see #removeColumn
         * @exception IllegalArgumentException if <code>column</code> is <code>null</code>
-        */    
+        */
        @Override
        public void addColumn(TableColumn column) {
                allTableColumns.add(column);
                super.addColumn(column);
        }
-
+       
        /** Removes <code>column</code> from this column model.
         * Posts <code>columnRemoved</code> event.
         * Will do nothing if the column is not in this model.
         * @param column the column to be added
         * @see #addColumn
-        */    
+        */
        @Override
        public void removeColumn(TableColumn column) {
                int allColumnsIndex = allTableColumns.indexOf(column);
-               if(allColumnsIndex != -1) {
+               if (allColumnsIndex != -1) {
                        allTableColumns.remove(allColumnsIndex);
                }
                super.removeColumn(column);
        }
-
-       /** Moves the column from <code>oldIndex</code> to <code>newIndex</code>.
+       
+       /** 
+        * Moves the column from <code>oldIndex</code> to <code>newIndex</code>.
         * Posts  <code>columnMoved</code> event.
         * Will not move any columns if <code>oldIndex</code> equals <code>newIndex</code>.
         *
@@ -149,21 +150,21 @@ public class XTableColumnModel extends DefaultTableColumnModel  {
                if ((oldIndex < 0) || (oldIndex >= getColumnCount()) ||
                                (newIndex < 0) || (newIndex >= getColumnCount()))
                        throw new IllegalArgumentException("moveColumn() - Index out of range");
-
-               TableColumn fromColumn  = (TableColumn) tableColumns.get(oldIndex);
-               TableColumn toColumn    = (TableColumn) tableColumns.get(newIndex);
-
-               int allColumnsOldIndex  = allTableColumns.indexOf(fromColumn);
-               int allColumnsNewIndex  = allTableColumns.indexOf(toColumn);
-
-               if(oldIndex != newIndex) {
+               
+               TableColumn fromColumn = tableColumns.get(oldIndex);
+               TableColumn toColumn = tableColumns.get(newIndex);
+               
+               int allColumnsOldIndex = allTableColumns.indexOf(fromColumn);
+               int allColumnsNewIndex = allTableColumns.indexOf(toColumn);
+               
+               if (oldIndex != newIndex) {
                        allTableColumns.remove(allColumnsOldIndex);
                        allTableColumns.add(allColumnsNewIndex, fromColumn);
                }
-
+               
                super.moveColumn(oldIndex, newIndex);
        }
-
+       
        /**
         * Returns the total number of columns in this model.
         *
@@ -175,7 +176,7 @@ public class XTableColumnModel extends DefaultTableColumnModel  {
                Vector<TableColumn> columns = (onlyVisible ? tableColumns : allTableColumns);
                return columns.size();
        }
-
+       
        /**
         * Returns an <code>Enumeration</code> of all the columns in the model.
         *
@@ -184,10 +185,10 @@ public class XTableColumnModel extends DefaultTableColumnModel  {
         */
        public Enumeration<TableColumn> getColumns(boolean onlyVisible) {
                Vector<TableColumn> columns = (onlyVisible ? tableColumns : allTableColumns);
-
+               
                return columns.elements();
        }
-
+       
        /**
         * Returns the position of the first column whose identifier equals <code>identifier</code>.
         * Position is the the index in all visible columns if <code>onlyVisible</code> is true or
@@ -209,21 +210,21 @@ public class XTableColumnModel extends DefaultTableColumnModel  {
                if (identifier == null) {
                        throw new IllegalArgumentException("Identifier is null");
                }
-
-               Vector<TableColumn>      columns     = (onlyVisible ? tableColumns : allTableColumns);
-               int         noColumns   = columns.size();
+               
+               Vector<TableColumn> columns = (onlyVisible ? tableColumns : allTableColumns);
+               int noColumns = columns.size();
                TableColumn column;
-
-               for(int columnIndex = 0; columnIndex < noColumns; ++columnIndex) {
-                       column = (TableColumn)columns.get(columnIndex);
-
-                       if(identifier.equals(column.getIdentifier()))
+               
+               for (int columnIndex = 0; columnIndex < noColumns; ++columnIndex) {
+                       column = columns.get(columnIndex);
+                       
+                       if (identifier.equals(column.getIdentifier()))
                                return columnIndex;
                }
-
+               
                throw new IllegalArgumentException("Identifier not found");
        }
-
+       
        /**
         * Returns the <code>TableColumn</code> object for the column
         * at <code>columnIndex</code>.
@@ -236,6 +237,6 @@ public class XTableColumnModel extends DefaultTableColumnModel  {
         *                              at <code>columnIndex</code>
         */
        public TableColumn getColumn(int columnIndex, boolean onlyVisible) {
-               return (TableColumn)tableColumns.elementAt(columnIndex);
+               return tableColumns.elementAt(columnIndex);
        }
 }
index cdd7c8534890db50ccb238b2238fff7685b96494..9d1b220cc3d9779cd0e8b7be850f6c074baafc64 100644 (file)
@@ -1,42 +1,5 @@
 package net.sf.openrocket.gui.preset;
 
-import net.miginfocom.swing.MigLayout;
-import net.sf.openrocket.gui.SpinnerEditor;
-import net.sf.openrocket.gui.adaptors.DoubleModel;
-import net.sf.openrocket.gui.components.UnitSelector;
-import net.sf.openrocket.l10n.Translator;
-import net.sf.openrocket.logging.LogHelper;
-import net.sf.openrocket.material.Material;
-import net.sf.openrocket.motor.Manufacturer;
-import net.sf.openrocket.preset.ComponentPreset;
-import net.sf.openrocket.preset.ComponentPresetFactory;
-import net.sf.openrocket.preset.InvalidComponentPresetException;
-import net.sf.openrocket.preset.TypedKey;
-import net.sf.openrocket.preset.TypedPropertyMap;
-import net.sf.openrocket.preset.loader.MaterialHolder;
-import net.sf.openrocket.rocketcomponent.Transition;
-import net.sf.openrocket.startup.Application;
-import net.sf.openrocket.unit.UnitGroup;
-
-import javax.imageio.ImageIO;
-import javax.swing.ComboBoxModel;
-import javax.swing.DefaultComboBoxModel;
-import javax.swing.ImageIcon;
-import javax.swing.InputVerifier;
-import javax.swing.JButton;
-import javax.swing.JCheckBox;
-import javax.swing.JComboBox;
-import javax.swing.JComponent;
-import javax.swing.JDialog;
-import javax.swing.JFileChooser;
-import javax.swing.JLabel;
-import javax.swing.JOptionPane;
-import javax.swing.JPanel;
-import javax.swing.JSpinner;
-import javax.swing.JTextField;
-import javax.swing.border.EmptyBorder;
-import javax.swing.filechooser.FileNameExtensionFilter;
-import javax.swing.text.JTextComponent;
 import java.awt.BorderLayout;
 import java.awt.CardLayout;
 import java.awt.Dimension;
@@ -61,2168 +24,2194 @@ import java.util.Map;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
-public class PresetEditorDialog extends JDialog implements ItemListener {
-
-    private static Translator trans = Application.getTranslator();
-
-    private static LogHelper log = Application.getLogger();
-
-    private static final String NON_NEGATIVE_INTEGER_FIELD = "(\\d){0,10}";
-
-    /**
-     * Input of non-negative decimals.
-     */
-    final PresetInputVerifier NON_NEGATIVE_INTEGER = new PresetInputVerifier(Pattern.compile(NON_NEGATIVE_INTEGER_FIELD));
-
-    private final JPanel contentPanel = new JPanel();
-    private DeselectableComboBox typeCombo;
-    private JTextField mfgTextField;
-    private MaterialChooser materialChooser;
-    private MaterialHolder holder = null;
-
-    private JTextField ncPartNoTextField;
-    private JTextField ncDescTextField;
-    private DoubleModel ncLength;
-    private JCheckBox ncFilledCB;
-    private JComboBox ncShapeCB;
-    private DoubleModel ncAftDia;
-    private DoubleModel ncAftShoulderDia;
-    private DoubleModel ncAftShoulderLen;
-    private DoubleModel ncMass;
-    private ImageIcon ncImage;
-    private JButton ncImageBtn;
-
-    private JTextField trPartNoTextField;
-    private JTextField trDescTextField;
-    private DoubleModel trLength;
-    private DoubleModel trAftDia;
-    private DoubleModel trAftShoulderDia;
-    private DoubleModel trAftShoulderLen;
-    private DoubleModel trForeDia;
-    private DoubleModel trForeShoulderDia;
-    private DoubleModel trForeShoulderLen;
-    private DoubleModel trMass;
-    private ImageIcon trImage;
-    private JCheckBox trFilledCB;
-    private JComboBox trShapeCB;
-    private JButton trImageBtn;
-
-    private JTextField btPartNoTextField;
-    private JTextField btDescTextField;
-    private DoubleModel btMass;
-    private DoubleModel btInnerDia;
-    private DoubleModel btOuterDia;
-    private DoubleModel btLength;
-    private ImageIcon btImage;
-    private JButton btImageBtn;
-
-    private JTextField tcPartNoTextField;
-    private JTextField tcDescTextField;
-    private DoubleModel tcMass;
-    private DoubleModel tcInnerDia;
-    private DoubleModel tcOuterDia;
-    private DoubleModel tcLength;
-    private ImageIcon tcImage;
-    private JButton tcImageBtn;
-
-    private JTextField bhPartNoTextField;
-    private JTextField bhDescTextField;
-    private DoubleModel bhOuterDia;
-    private DoubleModel bhLength;
-    private DoubleModel bhMass;
-    private ImageIcon bhImage;
-    private JButton bhImageBtn;
-
-    private JTextField crPartNoTextField;
-    private JTextField crDescTextField;
-    private DoubleModel crOuterDia;
-    private DoubleModel crInnerDia;
-    private DoubleModel crThickness;
-    private DoubleModel crMass;
-    private ImageIcon crImage;
-    private JButton crImageBtn;
-
-    private JTextField ebPartNoTextField;
-    private JTextField ebDescTextField;
-    private DoubleModel ebOuterDia;
-    private DoubleModel ebInnerDia;
-    private DoubleModel ebThickness;
-    private DoubleModel ebMass;
-    private ImageIcon ebImage;
-    private JButton ebImageBtn;
-
-    private JTextField llPartNoTextField;
-    private JTextField llDescTextField;
-    private DoubleModel llOuterDia;
-    private DoubleModel llInnerDia;
-    private DoubleModel llLength;
-    private DoubleModel llMass;
-    private ImageIcon llImage;
-    private JButton llImageBtn;
-
-    private JTextField stPartNoTextField;
-    private JTextField stDescTextField;
-    private DoubleModel stThickness;
-    private DoubleModel stWidth;
-    private DoubleModel stLength;
-    private DoubleModel stMass;
-    private ImageIcon stImage;
-    private JButton stImageBtn;
-
-    private JTextField pcPartNoTextField;
-    private JTextField pcDescTextField;
-    private JTextField pcSides;
-    private JTextField pcLineCount;
-    private DoubleModel pcDiameter;
-    private DoubleModel pcLineLength;
-    private MaterialChooser pcLineMaterialChooser;
-    private DoubleModel pcMass;
-    private ImageIcon pcImage;
-    private JButton pcImageBtn;
-
-    private final JFileChooser imageChooser = createImageChooser();
-
-    private JPanel componentOverlayPanel;
-
-    private PresetResultListener resultListener;
-
-    private static Map<String, String> componentMap = new HashMap<String, String>();
-
-    private static final String NOSE_CONE_KEY = "NoseCone.NoseCone";
-    private static final String BODY_TUBE_KEY = "BodyTube.BodyTube";
-    private static final String TUBE_COUPLER_KEY = "TubeCoupler.TubeCoupler";
-    private static final String TRANSITION_KEY = "Transition.Transition";
-    private static final String CR_KEY = "ComponentIcons.Centeringring";
-    private static final String BULKHEAD_KEY = "Bulkhead.Bulkhead";
-    private static final String EB_KEY = "ComponentIcons.Engineblock";
-    private static final String LAUNCH_LUG_KEY = "ComponentIcons.Launchlug";
-    private static final String STREAMER_KEY = "ComponentIcons.Streamer";
-    private static final String PARACHUTE_KEY = "ComponentIcons.Parachute";
-
-
-    static {
-        componentMap.put(trans.get(NOSE_CONE_KEY), "NOSECONE");
-        componentMap.put(trans.get(BODY_TUBE_KEY), "BODYTUBE");
-        componentMap.put(trans.get(TUBE_COUPLER_KEY), "TUBECOUPLER");
-        componentMap.put(trans.get(TRANSITION_KEY), "TRANSITION");
-        componentMap.put(trans.get(CR_KEY), "CENTERINGRING");
-        componentMap.put(trans.get(BULKHEAD_KEY), "BULKHEAD");
-        componentMap.put(trans.get(EB_KEY), "ENGINEBLOCK");
-        componentMap.put(trans.get(LAUNCH_LUG_KEY), "LAUNCHLUG");
-        componentMap.put(trans.get(PARACHUTE_KEY), "PARACHUTE");
-        componentMap.put(trans.get(STREAMER_KEY), "STREAMER");
-    }
-
-    /**
-     * Create the dialog.
-     *
-     * @param theCallback the listener that gets the results of editing the presets
-     */
-    public PresetEditorDialog(PresetResultListener theCallback) {
-        this(theCallback, null, null);
-    }
-
-    /**
-     * Create the dialog.
-     *
-     * @param theCallback the listener that gets the results of editing the presets
-     * @param toEdit      the ComponentPreset to be edited; or null if a new one is being added
-     * @param matHolder   the set of materials; if null then use system materials
-     */
-    public PresetEditorDialog(PresetResultListener theCallback, ComponentPreset toEdit, MaterialHolder matHolder) {
-        resultListener = theCallback;
-        getContentPane().setMinimumSize(new Dimension(200, 200));
-        setBounds(100, 100, 825, 610);
-        getContentPane().setLayout(new BorderLayout());
-        contentPanel.setBorder(new EmptyBorder(5, 5, 5, 5));
-        getContentPane().add(contentPanel, BorderLayout.CENTER);
-        contentPanel.setLayout(new MigLayout("", "[][grow][94.00,grow][232.0,grow][130.00][grow]", "[][][20.00,grow][grow]"));
-        JLabel lblManufacturer = new JLabel("Manufacturer:");
-        contentPanel.add(lblManufacturer, "cell 2 0,alignx left,aligny center");
-
-        mfgTextField = new JTextField();
-        contentPanel.add(mfgTextField, "cell 3 0,growx");
-        mfgTextField.setColumns(10);
-
-        JLabel typeLabel = new JLabel("Type:");
-        contentPanel.add(typeLabel, "cell 2 1,alignx left,aligny center");
-
-        componentOverlayPanel = new JPanel();
-        contentPanel.add(componentOverlayPanel, "cell 1 3 5 2,grow");
-        componentOverlayPanel.setLayout(new CardLayout(0, 0));
-
-        typeCombo = new DeselectableComboBox();
-        typeCombo.addItemListener(this);
-        typeCombo.setModel(new DefaultComboBoxModel());
-        setItems(typeCombo, toEdit);
-        contentPanel.add(typeCombo, "cell 3 1,growx");
-
-        JLabel bhMaterialLabel = new JLabel("Material:");
-        contentPanel.add(bhMaterialLabel, "cell 2 2, alignx left");
-
-        materialChooser = new MaterialChooser(new MaterialModel(this, Material.Type.BULK));
-
-        contentPanel.add(materialChooser, "cell 3 2,growx");
-
-        {
-            JPanel ncPanel = new JPanel();
-            componentOverlayPanel.add(ncPanel, "NOSECONE");
-            ncPanel.setLayout(new MigLayout("", "[61px][159.00,grow][45.00][109.00,grow][189.00,grow][grow]", "[16px][][][][][]"));
-            JLabel ncPartNoLabel = new JLabel("Part No:");
-            ncPanel.add(ncPartNoLabel, "cell 0 0,alignx left,aligny center");
-
-            ncPartNoTextField = new JTextField();
-            ncPanel.add(ncPartNoTextField, "cell 1 0,growx");
-            ncPartNoTextField.setColumns(10);
-
-            JLabel ncDescLabel = new JLabel("Description:");
-            ncPanel.add(ncDescLabel, "cell 3 0,alignx left,aligny center");
-
-            ncDescTextField = new JTextField();
-            ncPanel.add(ncDescTextField, "cell 4 0,growx");
-            ncDescTextField.setColumns(10);
-
-            ncFilledCB = new JCheckBox("Filled");
-            ncPanel.add(ncFilledCB, "cell 1 1");
-
-            JLabel ncMaterialLabel = new JLabel(trans.get("RocketCompCfg.lbl.Componentmaterial"));
-            ncPanel.add(ncMaterialLabel, "cell 0 1,alignx left");
-
-            JLabel ncMassLabel = new JLabel(trans.get("RocketCompCfg.lbl.Componentmass"));
-            ncPanel.add(ncMassLabel, "cell 3 1,alignx left");
-
-            ncMass = new DoubleModel(0, UnitGroup.UNITS_MASS, 0);
-            JSpinner spin = new JSpinner(ncMass.getSpinnerModel());
-            spin.setEditor(new SpinnerEditor(spin));
-            ncPanel.add(spin, "cell 4 1, growx");
-            ncPanel.add(new UnitSelector(ncMass), "growx");
-
-            JLabel ncShapeLabel = new JLabel(trans.get("NoseConeCfg.lbl.Noseconeshape"));
-            ncPanel.add(ncShapeLabel, "cell 0 2,alignx left");
-
-            ncShapeCB = new JComboBox();
-            ncShapeCB.setModel(new DefaultComboBoxModel(new String[]{Transition.Shape.OGIVE.getName(), Transition.Shape.CONICAL.getName(), Transition.Shape.PARABOLIC.getName(), Transition.Shape.ELLIPSOID.getName(), Transition.Shape.HAACK.getName()}));
-            ncPanel.add(ncShapeCB, "cell 1 2,growx");
-
-            JLabel ncLengthLabel = new JLabel(trans.get("NoseConeCfg.lbl.Noseconelength"));
-            ncPanel.add(ncLengthLabel, "cell 3 2,alignx left");
-
-            ncLength = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0, 2);
-            spin = new JSpinner(ncLength.getSpinnerModel());
-            spin.setEditor(new SpinnerEditor(spin));
-            ncPanel.add(spin, "cell 4 2, growx");
-            ncPanel.add(new UnitSelector(ncLength), "growx");
-
-            JLabel ncAftDiaLabel = new JLabel("Aft Dia.:");
-            ncPanel.add(ncAftDiaLabel, "cell 0 3,alignx left");
-
-            ncAftDia = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0, 2);
-            spin = new JSpinner(ncAftDia.getSpinnerModel());
-            spin.setEditor(new SpinnerEditor(spin));
-            ncPanel.add(spin, "cell 1 3, growx");
-            ncPanel.add(new UnitSelector(ncAftDia), "growx");
-
-            JLabel ncAftShoulderLenLabel = new JLabel("Aft Shoulder Len:");
-            ncPanel.add(ncAftShoulderLenLabel, "cell 0 4,alignx left");
-
-            ncAftShoulderLen = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0, 2);
-            spin = new JSpinner(ncAftShoulderLen.getSpinnerModel());
-            spin.setEditor(new SpinnerEditor(spin));
-            ncPanel.add(spin, "cell 1 4, growx");
-            ncPanel.add(new UnitSelector(ncAftShoulderLen), "growx");
-
-            JLabel ncAftShoulderDiaLabel = new JLabel("Aft Shoulder Dia.:");
-            ncPanel.add(ncAftShoulderDiaLabel, "cell 0 5,alignx left, aligny top, pad 7 0 0 0");
-
-            ncAftShoulderDia = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0, 2);
-            spin = new JSpinner(ncAftShoulderDia.getSpinnerModel());
-            spin.setEditor(new SpinnerEditor(spin));
-            ncPanel.add(spin, "cell 1 5, growx, aligny top");
-            ncPanel.add(new UnitSelector(ncAftShoulderDia), "growx, aligny top, pad 7 0 0 0");
-
-            JPanel panel = new JPanel();
-            panel.setMinimumSize(new Dimension(200, 200));
-            ncPanel.add(panel, "cell 4 3, span 1 3");
-            panel.setLayout(null);
-            ncImageBtn = new JButton("No Image");
-            ncImageBtn.setMaximumSize(new Dimension(75, 75));
-            ncImageBtn.setMinimumSize(new Dimension(75, 75));
-            panel.add(ncImageBtn);
-            ncImageBtn.setBounds(new Rectangle(6, 6, 132, 145));
-
-            ncImageBtn.addActionListener(new ActionListener() {
-                @Override
-                public void actionPerformed(final ActionEvent e) {
-                    int returnVal = imageChooser.showOpenDialog(PresetEditorDialog.this);
-
-                    if (returnVal == JFileChooser.APPROVE_OPTION) {
-                        File file = imageChooser.getSelectedFile();
-                        ncImage = scaleImage(new ImageIcon(file.getAbsolutePath()).getImage(), 155);
-                        ncImageBtn.setIcon(ncImage);
-                    }
-                }
-            });
-
-        }
-        {
-            JPanel trPanel = new JPanel();
-            componentOverlayPanel.add(trPanel, "TRANSITION");
-            trPanel.setLayout(new MigLayout("", "[61px][159.00,grow][45.00][109.00,grow][189.00,grow][grow]", "[16px][][][][][]"));
-
-            JLabel trPartNoLabel = new JLabel("Part No:");
-            trPanel.add(trPartNoLabel, "cell 0 0,alignx left");
-
-            trPartNoTextField = new JTextField();
-            trPanel.add(trPartNoTextField, "cell 1 0,growx");
-            trPartNoTextField.setColumns(10);
-
-            JLabel trDescLabel = new JLabel("Description:");
-            trPanel.add(trDescLabel, "cell 3 0,alignx left");
-
-            trDescTextField = new JTextField();
-            trPanel.add(trDescTextField, "cell 4 0,growx");
-            trDescTextField.setColumns(10);
-
-            trFilledCB = new JCheckBox("Filled");
-            trPanel.add(trFilledCB, "cell 1 1");
-
-            JLabel trMassLabel = new JLabel("Mass:");
-            trPanel.add(trMassLabel, "cell 3 1,alignx left");
-
-            trMass = new DoubleModel(0, UnitGroup.UNITS_MASS, 0);
-            JSpinner spin = new JSpinner(trMass.getSpinnerModel());
-            spin.setEditor(new SpinnerEditor(spin));
-            trPanel.add(spin, "cell 4 1, growx");
-            trPanel.add(new UnitSelector(trMass), "growx");
-
-            JLabel trShapeLabel = new JLabel("Shape:");
-            trPanel.add(trShapeLabel, "cell 0 2,alignx left");
-
-            trShapeCB = new JComboBox();
-            trShapeCB.setModel(new DefaultComboBoxModel(new String[]{Transition.Shape.OGIVE.getName(), Transition.Shape.CONICAL.getName(), Transition.Shape.PARABOLIC.getName(), Transition.Shape.ELLIPSOID.getName(), Transition.Shape.HAACK.getName()}));
-            trPanel.add(trShapeCB, "cell 1 2,growx");
-
-            JLabel trLengthLabel = new JLabel("Length:");
-            trPanel.add(trLengthLabel, "cell 3 2,alignx left");
-
-            trLength = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0, 2);
-            spin = new JSpinner(trLength.getSpinnerModel());
-            spin.setEditor(new SpinnerEditor(spin));
-            trPanel.add(spin, "cell 4 2, growx");
-            trPanel.add(new UnitSelector(trLength), "growx");
-
-            JLabel trAftDiaLabel = new JLabel("Aft Dia.:");
-            trPanel.add(trAftDiaLabel, "cell 0 3,alignx left");
-
-            trAftDia = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0, 2);
-            spin = new JSpinner(trAftDia.getSpinnerModel());
-            spin.setEditor(new SpinnerEditor(spin));
-            trPanel.add(spin, "cell 1 3, growx");
-            trPanel.add(new UnitSelector(trAftDia), "growx");
-
-            JLabel trForeDiaLabel = new JLabel("Fore Dia.:");
-            trPanel.add(trForeDiaLabel, "cell 3 3,alignx left");
-
-            trForeDia = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0, 2);
-            spin = new JSpinner(trForeDia.getSpinnerModel());
-            spin.setEditor(new SpinnerEditor(spin));
-            trPanel.add(spin, "cell 4 3, growx");
-            trPanel.add(new UnitSelector(trForeDia), "growx");
-
-            JLabel trAftShouldDiaLabel = new JLabel("Aft Shoulder Dia.:");
-            trPanel.add(trAftShouldDiaLabel, "cell 0 4,alignx left");
-
-            trAftShoulderDia = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0, 2);
-            spin = new JSpinner(trAftShoulderDia.getSpinnerModel());
-            spin.setEditor(new SpinnerEditor(spin));
-            trPanel.add(spin, "cell 1 4, growx");
-            trPanel.add(new UnitSelector(trAftShoulderDia), "growx");
-
-            JLabel trForeShouldDiaLabel = new JLabel("Fore Shoulder Dia.:");
-            trPanel.add(trForeShouldDiaLabel, "cell 3 4,alignx left");
-
-            trForeShoulderDia = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0, 2);
-            spin = new JSpinner(trForeShoulderDia.getSpinnerModel());
-            spin.setEditor(new SpinnerEditor(spin));
-            trPanel.add(spin, "cell 4 4, growx");
-            trPanel.add(new UnitSelector(trForeShoulderDia), "growx");
-
-            JLabel trAftShoulderLenLabel = new JLabel("Aft Shoulder Len.:");
-            trPanel.add(trAftShoulderLenLabel, "cell 0 5,alignx left");
-
-            trAftShoulderLen = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0, 2);
-            spin = new JSpinner(trAftShoulderLen.getSpinnerModel());
-            spin.setEditor(new SpinnerEditor(spin));
-            trPanel.add(spin, "cell 1 5, growx");
-            trPanel.add(new UnitSelector(trAftShoulderLen), "growx");
-
-            JLabel lblForeShoulderLen = new JLabel("Fore Shoulder Len.:");
-            trPanel.add(lblForeShoulderLen, "cell 3 5,alignx left");
-
-            trForeShoulderLen = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0, 2);
-            spin = new JSpinner(trForeShoulderLen.getSpinnerModel());
-            spin.setEditor(new SpinnerEditor(spin));
-            trPanel.add(spin, "cell 4 5, growx");
-            trPanel.add(new UnitSelector(trForeShoulderLen), "growx");
-
-            JPanel panel = new JPanel();
-            panel.setMinimumSize(new Dimension(200, 200));
-            trPanel.add(panel, "cell 4 6");
-            panel.setLayout(null);
-            trImageBtn = new JButton("No Image");
-            trImageBtn.setMaximumSize(new Dimension(75, 75));
-            trImageBtn.setMinimumSize(new Dimension(75, 75));
-            panel.add(trImageBtn);
-            trImageBtn.setBounds(new Rectangle(6, 6, 132, 145));
-
-            trImageBtn.addActionListener(new ActionListener() {
-                @Override
-                public void actionPerformed(final ActionEvent e) {
-                    int returnVal = imageChooser.showOpenDialog(PresetEditorDialog.this);
-
-                    if (returnVal == JFileChooser.APPROVE_OPTION) {
-                        File file = imageChooser.getSelectedFile();
-                        trImage = scaleImage(new ImageIcon(file.getAbsolutePath()).getImage(), 155);
-                        trImageBtn.setIcon(trImage);
-                    }
-                }
-            });
-
-        }
-        {
-            JPanel btPanel = new JPanel();
-            componentOverlayPanel.add(btPanel, "BODYTUBE");
-            btPanel.setLayout(new MigLayout("", "[][grow][][grow]", "[][][][]"));
-            JLabel btPartNoLabel = new JLabel("Part No:");
-            btPanel.add(btPartNoLabel, "cell 0 0,alignx left");
-
-            btPartNoTextField = new JTextField();
-            btPanel.add(btPartNoTextField, "cell 1 0,growx");
-            btPartNoTextField.setColumns(10);
-
-            JLabel btDescLabel = new JLabel("Description:");
-            btPanel.add(btDescLabel, "cell 3 0,alignx left");
-
-            btDescTextField = new JTextField();
-            btPanel.add(btDescTextField, "cell 4 0,growx");
-            btDescTextField.setColumns(10);
-
-            JLabel btLengthLabel = new JLabel("Length:");
-            btPanel.add(btLengthLabel, "cell 0 1,alignx left");
-
-            btLength = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0);
-            JSpinner spin = new JSpinner(btLength.getSpinnerModel());
-            spin.setEditor(new SpinnerEditor(spin));
-            btPanel.add(spin, "cell 1 1, growx");
-            btPanel.add(new UnitSelector(btLength), "growx");
-
-            JLabel btMassLabel = new JLabel("Mass:");
-            btPanel.add(btMassLabel, "cell 3 1,alignx left");
-
-            btMass = new DoubleModel(0, UnitGroup.UNITS_MASS, 0);
-            spin = new JSpinner(btMass.getSpinnerModel());
-            spin.setEditor(new SpinnerEditor(spin));
-            btPanel.add(spin, "cell 4 1, growx");
-            btPanel.add(new UnitSelector(btMass), "w 34lp!");
-
-            JLabel btInnerDiaLabel = new JLabel("Inner Dia.:");
-            btPanel.add(btInnerDiaLabel, "cell 0 2,alignx left");
-
-            btInnerDia = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0);
-            spin = new JSpinner(btInnerDia.getSpinnerModel());
-            spin.setEditor(new SpinnerEditor(spin));
-            btPanel.add(spin, "cell 1 2, growx");
-            btPanel.add(new UnitSelector(btInnerDia), "growx");
-
-            JLabel btOuterDiaLabel = new JLabel("Outer Dia.:");
-            btPanel.add(btOuterDiaLabel, "cell 3 2,alignx left");
-
-            btOuterDia = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0);
-            spin = new JSpinner(btOuterDia.getSpinnerModel());
-            spin.setEditor(new SpinnerEditor(spin));
-            btPanel.add(spin, "cell 4 2, growx");
-            btPanel.add(new UnitSelector(btOuterDia), "w 34lp!");
-
-            JPanel panel = new JPanel();
-            panel.setMinimumSize(new Dimension(200, 200));
-            btPanel.add(panel, "cell 4 3");
-            panel.setLayout(null);
-            btImageBtn = new JButton("No Image");
-            btImageBtn.setMaximumSize(new Dimension(75, 75));
-            btImageBtn.setMinimumSize(new Dimension(75, 75));
-            panel.add(btImageBtn);
-            btImageBtn.setBounds(new Rectangle(6, 6, 132, 145));
-
-            btImageBtn.addActionListener(new ActionListener() {
-                @Override
-                public void actionPerformed(final ActionEvent e) {
-                    int returnVal = imageChooser.showOpenDialog(PresetEditorDialog.this);
-
-                    if (returnVal == JFileChooser.APPROVE_OPTION) {
-                        File file = imageChooser.getSelectedFile();
-                        btImage = scaleImage(new ImageIcon(file.getAbsolutePath()).getImage(), 155);
-                        btImageBtn.setIcon(btImage);
-                    }
-                }
-            });
-
-        }
-        {
-            JPanel tcPanel = new JPanel();
-            componentOverlayPanel.add(tcPanel, "TUBECOUPLER");
-            tcPanel.setLayout(new MigLayout("", "[][grow][][grow]", "[][][][]"));
-            JLabel tcPartNoLabel = new JLabel("Part No:");
-            tcPanel.add(tcPartNoLabel, "cell 0 0,alignx left");
-
-            tcPartNoTextField = new JTextField();
-            tcPanel.add(tcPartNoTextField, "cell 1 0,growx");
-            tcPartNoTextField.setColumns(10);
-
-            JLabel tcDescLabel = new JLabel("Description:");
-            tcPanel.add(tcDescLabel, "cell 3 0,alignx left");
-
-            tcDescTextField = new JTextField();
-            tcPanel.add(tcDescTextField, "cell 4 0,growx");
-            tcDescTextField.setColumns(10);
-
-            JLabel tcLengthLabel = new JLabel("Length:");
-            tcPanel.add(tcLengthLabel, "cell 0 1,alignx left");
-
-            tcLength = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0);
-            JSpinner spin = new JSpinner(tcLength.getSpinnerModel());
-            spin.setEditor(new SpinnerEditor(spin));
-            tcPanel.add(spin, "cell 1 1, growx");
-            tcPanel.add(new UnitSelector(tcLength), "growx");
-
-            JLabel tcMassLabel = new JLabel("Mass:");
-            tcPanel.add(tcMassLabel, "cell 3 1,alignx left");
-
-            tcMass = new DoubleModel(0, UnitGroup.UNITS_MASS, 0);
-            spin = new JSpinner(tcMass.getSpinnerModel());
-            spin.setEditor(new SpinnerEditor(spin));
-            tcPanel.add(spin, "cell 4 1, growx");
-            tcPanel.add(new UnitSelector(tcMass), "w 34lp!");
-
-            JLabel tcInnerDiaLabel = new JLabel("Inner Dia.:");
-            tcPanel.add(tcInnerDiaLabel, "cell 0 2,alignx left");
-
-            tcInnerDia = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0);
-            spin = new JSpinner(tcInnerDia.getSpinnerModel());
-            spin.setEditor(new SpinnerEditor(spin));
-            tcPanel.add(spin, "cell 1 2, growx");
-            tcPanel.add(new UnitSelector(tcInnerDia), "growx");
-
-            JLabel tcOuterDiaLabel = new JLabel("Outer Dia.:");
-            tcPanel.add(tcOuterDiaLabel, "cell 3 2,alignx left");
-
-            tcOuterDia = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0);
-            spin = new JSpinner(tcOuterDia.getSpinnerModel());
-            spin.setEditor(new SpinnerEditor(spin));
-            tcPanel.add(spin, "cell 4 2, growx");
-            tcPanel.add(new UnitSelector(tcOuterDia), "w 34lp!");
-
-            JPanel panel = new JPanel();
-            panel.setMinimumSize(new Dimension(200, 200));
-            tcPanel.add(panel, "cell 4 3");
-            panel.setLayout(null);
-            tcImageBtn = new JButton("No Image");
-            tcImageBtn.setMaximumSize(new Dimension(75, 75));
-            tcImageBtn.setMinimumSize(new Dimension(75, 75));
-            panel.add(tcImageBtn);
-            tcImageBtn.setBounds(new Rectangle(6, 6, 132, 145));
-
-            tcImageBtn.addActionListener(new ActionListener() {
-                @Override
-                public void actionPerformed(final ActionEvent e) {
-                    int returnVal = imageChooser.showOpenDialog(PresetEditorDialog.this);
-
-                    if (returnVal == JFileChooser.APPROVE_OPTION) {
-                        File file = imageChooser.getSelectedFile();
-                        tcImage = scaleImage(new ImageIcon(file.getAbsolutePath()).getImage(), 155);
-                        tcImageBtn.setIcon(tcImage);
-                    }
-                }
-            });
-
-
-        }
-        {
-            JPanel bhPanel = new JPanel();
-            componentOverlayPanel.add(bhPanel, "BULKHEAD");
-            bhPanel.setLayout(new MigLayout("", "[][157.00,grow 79][65.00][grow]", "[][][][]"));
-
-            JLabel bhPartNoLabel = new JLabel("Part No:");
-            bhPanel.add(bhPartNoLabel, "cell 0 0,alignx left");
-
-            bhPartNoTextField = new JTextField();
-            bhPanel.add(bhPartNoTextField, "cell 1 0,growx");
-            bhPartNoTextField.setColumns(10);
-
-            JLabel bhDescLabel = new JLabel("Description:");
-            bhPanel.add(bhDescLabel, "cell 3 0,alignx left");
-
-            bhDescTextField = new JTextField();
-            bhPanel.add(bhDescTextField, "cell 4 0,growx");
-            bhDescTextField.setColumns(10);
-
-            JLabel bhLengthLabel = new JLabel("Thickness:");
-            bhPanel.add(bhLengthLabel, "cell 0 1,alignx left");
-
-            bhLength = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0);
-            JSpinner spin = new JSpinner(bhLength.getSpinnerModel());
-            spin.setEditor(new SpinnerEditor(spin));
-            bhPanel.add(spin, "cell 1 1, growx");
-            bhPanel.add(new UnitSelector(bhLength), "w 34lp!");
-
-            JLabel bhMassLabel = new JLabel("Mass:");
-            bhPanel.add(bhMassLabel, "cell 3 1,alignx left");
-
-            bhMass = new DoubleModel(0, UnitGroup.UNITS_MASS, 0);
-            spin = new JSpinner(bhMass.getSpinnerModel());
-            spin.setEditor(new SpinnerEditor(spin));
-            bhPanel.add(spin, "cell 4 1, growx");
-            bhPanel.add(new UnitSelector(bhMass), "growx");
-
-            JLabel bhOuterDiaLabel = new JLabel("Outer Dia.:");
-            bhPanel.add(bhOuterDiaLabel, "cell 0 2,alignx left, aligny top, pad 7 0 0 0");
-
-            bhOuterDia = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0);
-            spin = new JSpinner(bhOuterDia.getSpinnerModel());
-            spin.setEditor(new SpinnerEditor(spin));
-            bhPanel.add(spin, "cell 1 2, growx, aligny top");
-            bhPanel.add(new UnitSelector(bhOuterDia), "w 34lp!, h 27lp!, aligny top, pad 7 0 0 0");
-
-            JPanel panel = new JPanel();
-            panel.setMinimumSize(new Dimension(200, 200));
-            bhPanel.add(panel, "cell 4 2");
-            panel.setLayout(null);
-            bhImageBtn = new JButton("No Image");
-            bhImageBtn.setMaximumSize(new Dimension(75, 75));
-            bhImageBtn.setMinimumSize(new Dimension(75, 75));
-            panel.add(bhImageBtn);
-            bhImageBtn.setBounds(new Rectangle(6, 6, 132, 145));
-
-            bhImageBtn.addActionListener(new ActionListener() {
-                @Override
-                public void actionPerformed(final ActionEvent e) {
-                    int returnVal = imageChooser.showOpenDialog(PresetEditorDialog.this);
-
-                    if (returnVal == JFileChooser.APPROVE_OPTION) {
-                        File file = imageChooser.getSelectedFile();
-                        bhImage = scaleImage(new ImageIcon(file.getAbsolutePath()).getImage(), 155);
-                        bhImageBtn.setIcon(bhImage);
-                    }
-                }
-            });
-
-        }
-        {
-            JPanel crPanel = new JPanel();
-            componentOverlayPanel.add(crPanel, "CENTERINGRING");
-            crPanel.setLayout(new MigLayout("", "[][grow][][grow]", "[][][][]"));
-
-            JLabel crPartNoLabel = new JLabel("Part No:");
-            crPanel.add(crPartNoLabel, "cell 0 0,alignx left");
-
-            crPartNoTextField = new JTextField();
-            crPanel.add(crPartNoTextField, "cell 1 0, growx");
-            crPartNoTextField.setColumns(10);
-
-            JLabel crDescLabel = new JLabel("Description:");
-            crPanel.add(crDescLabel, "cell 3 0,alignx left");
-
-            crDescTextField = new JTextField();
-            crPanel.add(crDescTextField, "cell 4 0, growx");
-            crDescTextField.setColumns(10);
-
-            JLabel crThicknessLabel = new JLabel("Thickness:");
-            crPanel.add(crThicknessLabel, "cell 0 1,alignx left");
-
-            crThickness = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0);
-            JSpinner spin = new JSpinner(crThickness.getSpinnerModel());
-            spin.setEditor(new SpinnerEditor(spin));
-            crPanel.add(spin, "cell 1 1, growx");
-            crPanel.add(new UnitSelector(crThickness), "growx");
-
-            JLabel crMassLabel = new JLabel("Mass:");
-            crPanel.add(crMassLabel, "cell 3 1,alignx left");
-
-            crMass = new DoubleModel(0, UnitGroup.UNITS_MASS, 0);
-            spin = new JSpinner(crMass.getSpinnerModel());
-            spin.setEditor(new SpinnerEditor(spin));
-            crPanel.add(spin, "cell 4 1, growx");
-            crPanel.add(new UnitSelector(crMass), "w 34lp!");
-
-            JLabel crOuterDiaLabel = new JLabel("Outer Dia.:");
-            crPanel.add(crOuterDiaLabel, "cell 0 2,alignx left");
-
-            crOuterDia = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0);
-            spin = new JSpinner(crOuterDia.getSpinnerModel());
-            spin.setEditor(new SpinnerEditor(spin));
-            crPanel.add(spin, "cell 1 2, growx");
-            crPanel.add(new UnitSelector(crOuterDia), "w 34lp!");
-
-            JLabel crInnerDiaLabel = new JLabel("Inner Dia.:");
-            crPanel.add(crInnerDiaLabel, "cell 3 2,alignx left");
-
-            crInnerDia = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0);
-            spin = new JSpinner(crInnerDia.getSpinnerModel());
-            spin.setEditor(new SpinnerEditor(spin));
-            crPanel.add(spin, "cell 4 2, growx");
-            crPanel.add(new UnitSelector(crInnerDia), "w 34lp!");
-
-            JPanel panel = new JPanel();
-            panel.setMinimumSize(new Dimension(200, 200));
-            crPanel.add(panel, "cell 4 3");
-            panel.setLayout(null);
-            crImageBtn = new JButton("No Image");
-            crImageBtn.setMaximumSize(new Dimension(75, 75));
-            crImageBtn.setMinimumSize(new Dimension(75, 75));
-            panel.add(crImageBtn);
-            crImageBtn.setBounds(new Rectangle(6, 6, 132, 145));
-
-            crImageBtn.addActionListener(new ActionListener() {
-                @Override
-                public void actionPerformed(final ActionEvent e) {
-                    int returnVal = imageChooser.showOpenDialog(PresetEditorDialog.this);
-
-                    if (returnVal == JFileChooser.APPROVE_OPTION) {
-                        File file = imageChooser.getSelectedFile();
-                        crImage = scaleImage(new ImageIcon(file.getAbsolutePath()).getImage(), 155);
-                        crImageBtn.setIcon(crImage);
-                    }
-                }
-            });
-
-        }
-        {
-            JPanel ebPanel = new JPanel();
-            componentOverlayPanel.add(ebPanel, "ENGINEBLOCK");
-            ebPanel.setLayout(new MigLayout("", "[][grow][][grow]", "[][][][]"));
-            JLabel ebPartNoLabel = new JLabel("Part No:");
-            ebPanel.add(ebPartNoLabel, "cell 0 0,alignx left");
-
-            ebPartNoTextField = new JTextField();
-            ebPanel.add(ebPartNoTextField, "cell 1 0,growx");
-            ebPartNoTextField.setColumns(10);
-
-            JLabel ebDescLabel = new JLabel("Description:");
-            ebPanel.add(ebDescLabel, "cell 3 0,alignx left");
-
-            ebDescTextField = new JTextField();
-            ebPanel.add(ebDescTextField, "cell 4 0,growx");
-            ebDescTextField.setColumns(10);
-
-            JLabel ebThicknessLabel = new JLabel("Thickness:");
-            ebPanel.add(ebThicknessLabel, "cell 0 1,alignx left");
-
-            ebThickness = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0);
-            JSpinner spin = new JSpinner(ebThickness.getSpinnerModel());
-            spin.setEditor(new SpinnerEditor(spin));
-            ebPanel.add(spin, "cell 1 1, growx");
-            ebPanel.add(new UnitSelector(ebThickness), "growx");
-
-            JLabel ebMassLabel = new JLabel("Mass:");
-            ebPanel.add(ebMassLabel, "cell 3 1,alignx left");
-
-            ebMass = new DoubleModel(0, UnitGroup.UNITS_MASS, 0);
-            spin = new JSpinner(ebMass.getSpinnerModel());
-            spin.setEditor(new SpinnerEditor(spin));
-            ebPanel.add(spin, "cell 4 1, growx");
-            ebPanel.add(new UnitSelector(ebMass), "w 34lp!");
-
-            JLabel ebOuterDiaLabel = new JLabel("Outer Dia.:");
-            ebPanel.add(ebOuterDiaLabel, "cell 0 2,alignx left");
-
-            ebOuterDia = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0);
-            spin = new JSpinner(ebOuterDia.getSpinnerModel());
-            spin.setEditor(new SpinnerEditor(spin));
-            ebPanel.add(spin, "cell 1 2, growx");
-            ebPanel.add(new UnitSelector(ebOuterDia), "growx");
-
-            JLabel ebInnerDiaLabel = new JLabel("Inner Dia.:");
-            ebPanel.add(ebInnerDiaLabel, "cell 3 2,alignx left");
-
-            ebInnerDia = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0);
-            spin = new JSpinner(ebInnerDia.getSpinnerModel());
-            spin.setEditor(new SpinnerEditor(spin));
-            ebPanel.add(spin, "cell 4 2, growx");
-            ebPanel.add(new UnitSelector(ebInnerDia), "w 34lp!");
-
-            JPanel panel = new JPanel();
-            panel.setMinimumSize(new Dimension(200, 200));
-            ebPanel.add(panel, "cell 4 3");
-            panel.setLayout(null);
-            ebImageBtn = new JButton("No Image");
-            ebImageBtn.setMaximumSize(new Dimension(75, 75));
-            ebImageBtn.setMinimumSize(new Dimension(75, 75));
-            panel.add(ebImageBtn);
-            ebImageBtn.setBounds(new Rectangle(6, 6, 132, 145));
-
-            ebImageBtn.addActionListener(new ActionListener() {
-                @Override
-                public void actionPerformed(final ActionEvent e) {
-                    int returnVal = imageChooser.showOpenDialog(PresetEditorDialog.this);
-
-                    if (returnVal == JFileChooser.APPROVE_OPTION) {
-                        File file = imageChooser.getSelectedFile();
-                        ebImage = scaleImage(new ImageIcon(file.getAbsolutePath()).getImage(), 155);
-                        ebImageBtn.setIcon(ebImage);
-                    }
-                }
-            });
-        }
-
-        {
-            JPanel llPanel = new JPanel();
-            componentOverlayPanel.add(llPanel, "LAUNCHLUG");
-            llPanel.setLayout(new MigLayout("", "[][grow][][grow]", "[][][][]"));
-            JLabel llPartNoLabel = new JLabel("Part No:");
-            llPanel.add(llPartNoLabel, "cell 0 0,alignx left");
-
-            llPartNoTextField = new JTextField();
-            llPanel.add(llPartNoTextField, "cell 1 0,growx");
-            llPartNoTextField.setColumns(10);
-
-            JLabel llDescLabel = new JLabel("Description:");
-            llPanel.add(llDescLabel, "cell 3 0,alignx left");
-
-            llDescTextField = new JTextField();
-            llPanel.add(llDescTextField, "cell 4 0,growx");
-            llDescTextField.setColumns(10);
-
-            JLabel llLengthLabel = new JLabel("Length:");
-            llPanel.add(llLengthLabel, "cell 0 1,alignx left");
-
-            llLength = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0);
-            JSpinner spin = new JSpinner(llLength.getSpinnerModel());
-            spin.setEditor(new SpinnerEditor(spin));
-            llPanel.add(spin, "cell 1 1, growx");
-            llPanel.add(new UnitSelector(llLength), "growx");
-
-            JLabel llMassLabel = new JLabel("Mass:");
-            llPanel.add(llMassLabel, "cell 3 1,alignx left");
-
-            llMass = new DoubleModel(0, UnitGroup.UNITS_MASS, 0);
-            spin = new JSpinner(llMass.getSpinnerModel());
-            spin.setEditor(new SpinnerEditor(spin));
-            llPanel.add(spin, "cell 4 1, growx");
-            llPanel.add(new UnitSelector(llMass), "w 34lp!");
-
-            JLabel llOuterDiaLabel = new JLabel("Outer Dia.:");
-            llPanel.add(llOuterDiaLabel, "cell 0 2,alignx left");
-
-            llOuterDia = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0);
-            spin = new JSpinner(llOuterDia.getSpinnerModel());
-            spin.setEditor(new SpinnerEditor(spin));
-            llPanel.add(spin, "cell 1 2, growx");
-            llPanel.add(new UnitSelector(llOuterDia), "growx");
-
-            JLabel llInnerDiaLabel = new JLabel("Inner Dia.:");
-            llPanel.add(llInnerDiaLabel, "cell 3 2,alignx left");
-
-            llInnerDia = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0);
-            spin = new JSpinner(llInnerDia.getSpinnerModel());
-            spin.setEditor(new SpinnerEditor(spin));
-            llPanel.add(spin, "cell 4 2, growx");
-            llPanel.add(new UnitSelector(llInnerDia), "w 34lp!");
-
-            JPanel panel = new JPanel();
-            panel.setMinimumSize(new Dimension(200, 200));
-            llPanel.add(panel, "cell 4 3");
-            panel.setLayout(null);
-            llImageBtn = new JButton("No Image");
-            llImageBtn.setMaximumSize(new Dimension(75, 75));
-            llImageBtn.setMinimumSize(new Dimension(75, 75));
-            panel.add(llImageBtn);
-            llImageBtn.setBounds(new Rectangle(6, 6, 132, 145));
-
-            llImageBtn.addActionListener(new ActionListener() {
-                @Override
-                public void actionPerformed(final ActionEvent e) {
-                    int returnVal = imageChooser.showOpenDialog(PresetEditorDialog.this);
-
-                    if (returnVal == JFileChooser.APPROVE_OPTION) {
-                        File file = imageChooser.getSelectedFile();
-                        llImage = scaleImage(new ImageIcon(file.getAbsolutePath()).getImage(), 155);
-                        llImageBtn.setIcon(llImage);
-                    }
-                }
-            });
-        }
-
-        {
-            JPanel stPanel = new JPanel();
-            componentOverlayPanel.add(stPanel, "STREAMER");
-            stPanel.setLayout(new MigLayout("", "[][grow][][grow]", "[][][][]"));
-            JLabel stPartNoLabel = new JLabel("Part No:");
-            stPanel.add(stPartNoLabel, "cell 0 0,alignx left");
-
-            stPartNoTextField = new JTextField();
-            stPanel.add(stPartNoTextField, "cell 1 0,growx");
-            stPartNoTextField.setColumns(10);
-
-            JLabel stDescLabel = new JLabel("Description:");
-            stPanel.add(stDescLabel, "cell 3 0,alignx left");
-
-            stDescTextField = new JTextField();
-            stPanel.add(stDescTextField, "cell 4 0,growx");
-            stDescTextField.setColumns(10);
-
-            JLabel stLengthLabel = new JLabel("Length:");
-            stPanel.add(stLengthLabel, "cell 0 1,alignx left");
-
-            stLength = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0);
-            JSpinner spin = new JSpinner(stLength.getSpinnerModel());
-            spin.setEditor(new SpinnerEditor(spin));
-            stPanel.add(spin, "cell 1 1, growx");
-            stPanel.add(new UnitSelector(stLength), "growx");
-
-            JLabel stMassLabel = new JLabel("Mass:");
-            stPanel.add(stMassLabel, "cell 3 1,alignx left");
-
-            stMass = new DoubleModel(0, UnitGroup.UNITS_MASS, 0);
-            spin = new JSpinner(stMass.getSpinnerModel());
-            spin.setEditor(new SpinnerEditor(spin));
-            stPanel.add(spin, "cell 4 1, growx");
-            stPanel.add(new UnitSelector(stMass), "growx");
-
-            JLabel stThicknessLabel = new JLabel("Thickness:");
-            stPanel.add(stThicknessLabel, "cell 0 2,alignx left");
-
-            stThickness = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0);
-            spin = new JSpinner(stThickness.getSpinnerModel());
-            spin.setEditor(new SpinnerEditor(spin));
-            stPanel.add(spin, "cell 1 2, growx");
-            stPanel.add(new UnitSelector(stThickness), "growx");
-
-            JLabel stWidthLabel = new JLabel("Width:");
-            stPanel.add(stWidthLabel, "cell 3 2,alignx left");
-
-            stWidth = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0);
-            spin = new JSpinner(stWidth.getSpinnerModel());
-            spin.setEditor(new SpinnerEditor(spin));
-            stPanel.add(spin, "cell 4 2, growx");
-            stPanel.add(new UnitSelector(stWidth), "growx");
-
-            JPanel panel = new JPanel();
-            panel.setMinimumSize(new Dimension(200, 200));
-            stPanel.add(panel, "cell 4 3");
-            panel.setLayout(null);
-            stImageBtn = new JButton("No Image");
-            stImageBtn.setMaximumSize(new Dimension(75, 75));
-            stImageBtn.setMinimumSize(new Dimension(75, 75));
-            panel.add(stImageBtn);
-            stImageBtn.setBounds(new Rectangle(6, 6, 132, 145));
-
-            stImageBtn.addActionListener(new ActionListener() {
-                @Override
-                public void actionPerformed(final ActionEvent e) {
-                    int returnVal = imageChooser.showOpenDialog(PresetEditorDialog.this);
-
-                    if (returnVal == JFileChooser.APPROVE_OPTION) {
-                        File file = imageChooser.getSelectedFile();
-                        stImage = scaleImage(new ImageIcon(file.getAbsolutePath()).getImage(), 155);
-                        stImageBtn.setIcon(stImage);
-                    }
-                }
-            });
-        }
-
-        {
-            JPanel pcPanel = new JPanel();
-            componentOverlayPanel.add(pcPanel, "PARACHUTE");
-            pcPanel.setLayout(new MigLayout("", "[][157.00,grow 79][65.00][grow][][]", "[][][][][][]"));
-            JLabel pcPartNoLabel = new JLabel("Part No:");
-            pcPanel.add(pcPartNoLabel, "cell 0 0,alignx left");
-
-            pcPartNoTextField = new JTextField();
-            pcPanel.add(pcPartNoTextField, "cell 1 0,growx");
-            pcPartNoTextField.setColumns(10);
-
-            JLabel pcDescLabel = new JLabel("Description:");
-            pcPanel.add(pcDescLabel, "cell 3 0,alignx left");
-
-            pcDescTextField = new JTextField();
-            pcPanel.add(pcDescTextField, "cell 4 0,growx");
-            pcDescTextField.setColumns(10);
-
-            JLabel pcSidesLabel = new JLabel("Sides:");
-            pcPanel.add(pcSidesLabel, "cell 0 1,alignx left");
-
-            pcSides = new JTextField();
-            pcPanel.add(pcSides, "cell 1 1, growx");
-            pcSides.setInputVerifier(NON_NEGATIVE_INTEGER);
-            pcSides.setColumns(10);
-
-            JLabel pcMassLabel = new JLabel("Mass:");
-            pcPanel.add(pcMassLabel, "cell 3 1,alignx left");
-
-            pcMass = new DoubleModel(0, UnitGroup.UNITS_MASS, 0);
-            JSpinner spin = new JSpinner(pcMass.getSpinnerModel());
-            spin.setEditor(new SpinnerEditor(spin));
-            pcPanel.add(spin, "cell 4 1, growx");
-            pcPanel.add(new UnitSelector(pcMass), "growx");
-
-            JLabel pcDiameterLabel = new JLabel("Diameter:");
-            pcPanel.add(pcDiameterLabel, "cell 0 2,alignx left");
-
-            pcDiameter = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0);
-            spin = new JSpinner(pcDiameter.getSpinnerModel());
-            spin.setEditor(new SpinnerEditor(spin));
-            pcPanel.add(spin, "cell 1 2, growx");
-            pcPanel.add(new UnitSelector(pcDiameter));
-
-            JLabel pcLineLengthLabel = new JLabel("Line Length:");
-            pcPanel.add(pcLineLengthLabel, "cell 3 2,alignx left");
-
-            pcLineLength = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0);
-            spin = new JSpinner(pcLineLength.getSpinnerModel());
-            spin.setEditor(new SpinnerEditor(spin));
-            pcPanel.add(spin, "cell 4 2, growx");
-            pcPanel.add(new UnitSelector(pcLineLength), "growx");
-
-            JLabel pcLineCountLabel = new JLabel("Line Count:");
-            pcPanel.add(pcLineCountLabel, "cell 3 3,alignx left");
-
-            pcLineCount = new JTextField();
-            pcLineCount.setInputVerifier(NON_NEGATIVE_INTEGER);
-            pcPanel.add(pcLineCount, "cell 4 3, growx");
-            pcLineCount.setColumns(10);
-
-            JLabel pcLineMaterialLabel = new JLabel("Line Material:");
-            pcPanel.add(pcLineMaterialLabel, "cell 3 4,alignx left, aligny top, pad 7 0 0 0 ");
-
-            pcLineMaterialChooser = new MaterialChooser();
-            pcLineMaterialChooser.setModel(new MaterialModel(PresetEditorDialog.this, Material.Type.LINE));
-            pcPanel.add(pcLineMaterialChooser, "cell 4 4, span 3 1, growx, aligny top");
-
-            JPanel panel = new JPanel();
-            panel.setMinimumSize(new Dimension(200, 200));
-            pcPanel.add(panel, "cell 1 3, span 1 3");
-            panel.setLayout(null);
-            pcImageBtn = new JButton("No Image");
-            pcImageBtn.setMaximumSize(new Dimension(75, 75));
-            pcImageBtn.setMinimumSize(new Dimension(75, 75));
-            panel.add(pcImageBtn);
-            pcImageBtn.setBounds(new Rectangle(6, 6, 132, 145));
-
-            pcImageBtn.addActionListener(new ActionListener() {
-                @Override
-                public void actionPerformed(final ActionEvent e) {
-                    int returnVal = imageChooser.showOpenDialog(PresetEditorDialog.this);
-
-                    if (returnVal == JFileChooser.APPROVE_OPTION) {
-                        File file = imageChooser.getSelectedFile();
-                        pcImage = scaleImage(new ImageIcon(file.getAbsolutePath()).getImage(), 155);
-                        pcImageBtn.setIcon(pcImage);
-                    }
-                }
-            });
-        }
-
-        JPanel buttonPane = new JPanel();
-        getContentPane().add(buttonPane, BorderLayout.SOUTH);
-        buttonPane.setLayout(new MigLayout("", "[130px][176.00px][131.00px]", "[29px]"));
-        JButton btnSaveAndNew = new JButton("Save and New");
-        btnSaveAndNew.addMouseListener(new MouseAdapter() {
-            @Override
-            public void mouseClicked(MouseEvent arg0) {
-                saveResult();
-            }
-        });
-        buttonPane.add(btnSaveAndNew, "cell 0 0,alignx left,aligny top");
-
-        JButton okButton = new JButton("Save and Close");
-        okButton.addActionListener(new ActionListener() {
-            public void actionPerformed(ActionEvent event) {
-                if (saveResult()) {
-                    dispose();
-                }
-            }
-        });
-        okButton.setActionCommand("OK");
-        buttonPane.add(okButton, "cell 1 0,alignx left,aligny top");
-        getRootPane().setDefaultButton(okButton);
-
-        JButton cancelButton = new JButton("Close");
-        cancelButton.addActionListener(new ActionListener() {
-            public void actionPerformed(ActionEvent event) {
-                dispose();
-            }
-        });
-        cancelButton.setActionCommand("Close");
-        buttonPane.add(cancelButton, "cell 6 0,alignx right,aligny top");
-
-        if (toEdit != null) {
-            fillEditor(toEdit, matHolder);
-        }
-        holder = matHolder;
-    }
-
-    /**
-     * When an existing preset is edited, we want to disable the other types of presets.  If the user wants a different
-     * type of component, then they should delete this one and add a new one.
-     *
-     * @param cb     the combo box component
-     * @param preset the preset being edited
-     */
-    private void setItems(DeselectableComboBox cb, ComponentPreset preset) {
-        cb.addItem(trans.get(NOSE_CONE_KEY), preset != null && !preset.get(ComponentPreset.TYPE).equals(ComponentPreset.Type.NOSE_CONE));
-        cb.addItem(trans.get(BODY_TUBE_KEY), preset != null && !preset.get(ComponentPreset.TYPE).equals(ComponentPreset.Type.BODY_TUBE));
-        cb.addItem(trans.get(BULKHEAD_KEY), preset != null && !preset.get(ComponentPreset.TYPE).equals(ComponentPreset.Type.BULK_HEAD));
-        cb.addItem(trans.get(CR_KEY), preset != null && !preset.get(ComponentPreset.TYPE).equals(ComponentPreset.Type.CENTERING_RING));
-        cb.addItem(trans.get(EB_KEY), preset != null && !preset.get(ComponentPreset.TYPE).equals(ComponentPreset.Type.ENGINE_BLOCK));
-        cb.addItem(trans.get(TRANSITION_KEY), preset != null && !preset.get(ComponentPreset.TYPE).equals(ComponentPreset.Type.TRANSITION));
-        cb.addItem(trans.get(TUBE_COUPLER_KEY), preset != null && !preset.get(ComponentPreset.TYPE).equals(ComponentPreset.Type.TUBE_COUPLER));
-        cb.addItem(trans.get(LAUNCH_LUG_KEY), preset != null && !preset.get(ComponentPreset.TYPE).equals(ComponentPreset.Type.LAUNCH_LUG));
-        cb.addItem(trans.get(PARACHUTE_KEY), preset != null && !preset.get(ComponentPreset.TYPE).equals(ComponentPreset.Type.PARACHUTE));
-        cb.addItem(trans.get(STREAMER_KEY), preset != null && !preset.get(ComponentPreset.TYPE).equals(ComponentPreset.Type.STREAMER));
-    }
-
-    /**
-     * Create an image chooser.  Currently png and jpg are supported.
-     *
-     * @return a file chooser that looks for image files
-     */
-    private JFileChooser createImageChooser() {
-        final JFileChooser chooser = new JFileChooser();
-        ImagePreviewPanel preview = new ImagePreviewPanel();
-        chooser.setAccessory(preview);
-        chooser.addPropertyChangeListener(preview);
-        chooser.setAcceptAllFileFilterUsed(false);
-        chooser.addChoosableFileFilter(new FileNameExtensionFilter("Image Files", "png", "jpg", "jpeg"));
-        return chooser;
-    }
-
-    /**
-     * To support editing of an existing preset, the swing components need to be prepopulated with the field data.
-     *
-     * @param preset the preset to edit
-     */
-    private void fillEditor(ComponentPreset preset, MaterialHolder holder) {
-        ComponentPreset.Type t = preset.getType();
-
-        mfgTextField.setText(preset.get(ComponentPreset.MANUFACTURER).getDisplayName());
-        setMaterial(materialChooser, preset, holder, Material.Type.BULK, ComponentPreset.MATERIAL);
-        switch (t) {
-            case BODY_TUBE:
-                typeCombo.setSelectedItem(trans.get(BODY_TUBE_KEY));
-                btDescTextField.setText(preset.get(ComponentPreset.DESCRIPTION));
-
-                if (preset.has(ComponentPreset.INNER_DIAMETER)) {
-                    btInnerDia.setValue(preset.get(ComponentPreset.INNER_DIAMETER));
-                    btInnerDia.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
-                }
-                if (preset.has(ComponentPreset.LENGTH)) {
-                    btLength.setValue(preset.get(ComponentPreset.LENGTH));
-                    btLength.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
-                }
-                if (preset.has(ComponentPreset.MASS)) {
-                    btMass.setValue(preset.get(ComponentPreset.MASS));
-                    btMass.setCurrentUnit(UnitGroup.UNITS_MASS.getDefaultUnit());
-                }
-                if (preset.has(ComponentPreset.OUTER_DIAMETER)) {
-                    btOuterDia.setValue(preset.get(ComponentPreset.OUTER_DIAMETER));
-                    btOuterDia.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
-                }
-                if (preset.has(ComponentPreset.IMAGE)) {
-                    btImage = new ImageIcon(byteArrayToImage(preset.get(ComponentPreset.IMAGE)));
-                    btImageBtn.setIcon(btImage);
-                }
-                btPartNoTextField.setText(preset.get(ComponentPreset.PARTNO));
-                break;
-            case BULK_HEAD:
-                typeCombo.setSelectedItem(trans.get(BULKHEAD_KEY));
-                bhDescTextField.setText(preset.get(ComponentPreset.DESCRIPTION));
-                if (preset.has(ComponentPreset.LENGTH)) {
-                    bhLength.setValue(preset.get(ComponentPreset.LENGTH));
-                    bhLength.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
-                }
-                if (preset.has(ComponentPreset.MASS)) {
-                    bhMass.setValue(preset.get(ComponentPreset.MASS));
-                    bhMass.setCurrentUnit(UnitGroup.UNITS_MASS.getDefaultUnit());
-                }
-                if (preset.has(ComponentPreset.OUTER_DIAMETER)) {
-                    bhOuterDia.setValue(preset.get(ComponentPreset.OUTER_DIAMETER));
-                    bhOuterDia.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
-                }
-                if (preset.has(ComponentPreset.IMAGE)) {
-                    bhImage = new ImageIcon(byteArrayToImage(preset.get(ComponentPreset.IMAGE)));
-                    bhImageBtn.setIcon(bhImage);
-                }
-                bhPartNoTextField.setText(preset.get(ComponentPreset.PARTNO));
-                break;
-            case CENTERING_RING:
-                typeCombo.setSelectedItem(trans.get(CR_KEY));
-                crDescTextField.setText(preset.get(ComponentPreset.DESCRIPTION));
-                if (preset.has(ComponentPreset.INNER_DIAMETER)) {
-                    crInnerDia.setValue(preset.get(ComponentPreset.INNER_DIAMETER));
-                    crInnerDia.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
-                }
-                if (preset.has(ComponentPreset.LENGTH)) {
-                    crThickness.setValue(preset.get(ComponentPreset.LENGTH));
-                    crThickness.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
-                }
-                if (preset.has(ComponentPreset.MASS)) {
-                    crMass.setValue(preset.get(ComponentPreset.MASS));
-                    crMass.setCurrentUnit(UnitGroup.UNITS_MASS.getDefaultUnit());
-                }
-                if (preset.has(ComponentPreset.OUTER_DIAMETER)) {
-                    crOuterDia.setValue(preset.get(ComponentPreset.OUTER_DIAMETER));
-                    crOuterDia.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
-                }
-                if (preset.has(ComponentPreset.IMAGE)) {
-                    crImage = new ImageIcon(byteArrayToImage(preset.get(ComponentPreset.IMAGE)));
-                    crImageBtn.setIcon(crImage);
-                }
-                crPartNoTextField.setText(preset.get(ComponentPreset.PARTNO));
-                break;
-            case ENGINE_BLOCK:
-                typeCombo.setSelectedItem(trans.get(EB_KEY));
-                ebDescTextField.setText(preset.get(ComponentPreset.DESCRIPTION));
-                if (preset.has(ComponentPreset.INNER_DIAMETER)) {
-                    ebInnerDia.setValue(preset.get(ComponentPreset.INNER_DIAMETER));
-                    ebInnerDia.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
-                }
-                if (preset.has(ComponentPreset.LENGTH)) {
-                    ebThickness.setValue(preset.get(ComponentPreset.LENGTH));
-                    ebThickness.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
-                }
-                if (preset.has(ComponentPreset.MASS)) {
-                    ebMass.setValue(preset.get(ComponentPreset.MASS));
-                    ebMass.setCurrentUnit(UnitGroup.UNITS_MASS.getDefaultUnit());
-                }
-                if (preset.has(ComponentPreset.OUTER_DIAMETER)) {
-                    ebOuterDia.setValue(preset.get(ComponentPreset.OUTER_DIAMETER));
-                    ebOuterDia.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
-                }
-                if (preset.has(ComponentPreset.IMAGE)) {
-                    ebImage = new ImageIcon(byteArrayToImage(preset.get(ComponentPreset.IMAGE)));
-                    ebImageBtn.setIcon(ebImage);
-                }
-                ebPartNoTextField.setText(preset.get(ComponentPreset.PARTNO));
-                break;
-            case NOSE_CONE:
-                typeCombo.setSelectedItem(trans.get(NOSE_CONE_KEY));
-                ncDescTextField.setText(preset.get(ComponentPreset.DESCRIPTION));
-                if (preset.has(ComponentPreset.AFT_OUTER_DIAMETER)) {
-                    ncAftDia.setValue(preset.get(ComponentPreset.AFT_OUTER_DIAMETER));
-                    ncAftDia.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
-                }
-                if (preset.has(ComponentPreset.AFT_SHOULDER_DIAMETER)) {
-                    ncAftShoulderDia.setValue(preset.get(ComponentPreset.AFT_SHOULDER_DIAMETER));
-                    ncAftShoulderDia.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
-                }
-                if (preset.has(ComponentPreset.AFT_SHOULDER_LENGTH)) {
-                    ncAftShoulderLen.setValue(preset.get(ComponentPreset.AFT_SHOULDER_LENGTH));
-                    ncAftShoulderLen.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
-                }
-                if (preset.has(ComponentPreset.MASS)) {
-                    ncMass.setValue(preset.get(ComponentPreset.MASS));
-                    ncMass.setCurrentUnit(UnitGroup.UNITS_MASS.getDefaultUnit());
-                }
-                if (preset.has(ComponentPreset.SHAPE)) {
-                    ncShapeCB.setSelectedItem(preset.get(ComponentPreset.SHAPE).toString());
-                }
-                if (preset.has(ComponentPreset.FILLED)) {
-                    ncFilledCB.setSelected((preset.get(ComponentPreset.FILLED)));
-                }
-                if (preset.has(ComponentPreset.LENGTH)) {
-                    ncLength.setValue(preset.get(ComponentPreset.LENGTH));
-                    ncLength.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
-                }
-                if (preset.has(ComponentPreset.IMAGE)) {
-                    ncImage = new ImageIcon(byteArrayToImage(preset.get(ComponentPreset.IMAGE)));
-                    ncImageBtn.setIcon(ncImage);
-                }
-                ncPartNoTextField.setText(preset.get(ComponentPreset.PARTNO));
-                break;
-            case TRANSITION:
-                typeCombo.setSelectedItem(trans.get(TRANSITION_KEY));
-                trDescTextField.setText(preset.get(ComponentPreset.DESCRIPTION));
-                if (preset.has(ComponentPreset.AFT_OUTER_DIAMETER)) {
-                    trAftDia.setValue(preset.get(ComponentPreset.AFT_OUTER_DIAMETER));
-                    trAftDia.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
-                }
-                if (preset.has(ComponentPreset.AFT_SHOULDER_DIAMETER)) {
-                    trAftShoulderDia.setValue(preset.get(ComponentPreset.AFT_SHOULDER_DIAMETER));
-                    trAftShoulderDia.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
-                }
-                if (preset.has(ComponentPreset.AFT_SHOULDER_LENGTH)) {
-                    trAftShoulderLen.setValue(preset.get(ComponentPreset.AFT_SHOULDER_LENGTH));
-                    trAftShoulderLen.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
-                }
-                if (preset.has(ComponentPreset.FORE_OUTER_DIAMETER)) {
-                    trForeDia.setValue(preset.get(ComponentPreset.FORE_OUTER_DIAMETER));
-                    trForeDia.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
-                }
-                if (preset.has(ComponentPreset.FORE_SHOULDER_DIAMETER)) {
-                    trForeShoulderDia.setValue(preset.get(ComponentPreset.FORE_SHOULDER_DIAMETER));
-                    trForeShoulderDia.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
-                }
-                if (preset.has(ComponentPreset.FORE_SHOULDER_LENGTH)) {
-                    trForeShoulderLen.setValue(preset.get(ComponentPreset.FORE_SHOULDER_LENGTH));
-                    trForeShoulderLen.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
-                }
-                if (preset.has(ComponentPreset.MASS)) {
-                    trMass.setValue(preset.get(ComponentPreset.MASS));
-                    trMass.setCurrentUnit(UnitGroup.UNITS_MASS.getDefaultUnit());
-                }
-                if (preset.has(ComponentPreset.SHAPE)) {
-                    trShapeCB.setSelectedItem(preset.get(ComponentPreset.SHAPE).toString());
-                }
-                if (preset.has(ComponentPreset.FILLED)) {
-                    trFilledCB.setSelected((preset.get(ComponentPreset.FILLED)));
-                }
-                if (preset.has(ComponentPreset.LENGTH)) {
-                    trLength.setValue(preset.get(ComponentPreset.LENGTH));
-                    trLength.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
-                }
-                if (preset.has(ComponentPreset.IMAGE)) {
-                    trImage = new ImageIcon(byteArrayToImage(preset.get(ComponentPreset.IMAGE)));
-                    trImageBtn.setIcon(trImage);
-                }
-                trPartNoTextField.setText(preset.get(ComponentPreset.PARTNO));
-                break;
-            case TUBE_COUPLER:
-                typeCombo.setSelectedItem(trans.get(TUBE_COUPLER_KEY));
-                tcDescTextField.setText(preset.get(ComponentPreset.DESCRIPTION));
-                if (preset.has(ComponentPreset.INNER_DIAMETER)) {
-                    tcInnerDia.setValue(preset.get(ComponentPreset.INNER_DIAMETER));
-                    tcInnerDia.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
-                }
-                if (preset.has(ComponentPreset.LENGTH)) {
-                    tcLength.setValue(preset.get(ComponentPreset.LENGTH));
-                    tcLength.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
-                }
-                if (preset.has(ComponentPreset.MASS)) {
-                    tcMass.setValue(preset.get(ComponentPreset.MASS));
-                    tcMass.setCurrentUnit(UnitGroup.UNITS_MASS.getDefaultUnit());
-                }
-                if (preset.has(ComponentPreset.OUTER_DIAMETER)) {
-                    tcOuterDia.setValue(preset.get(ComponentPreset.OUTER_DIAMETER));
-                    tcOuterDia.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
-                }
-                tcPartNoTextField.setText(preset.get(ComponentPreset.PARTNO));
-                if (preset.has(ComponentPreset.IMAGE)) {
-                    tcImage = new ImageIcon(byteArrayToImage(preset.get(ComponentPreset.IMAGE)));
-                    tcImageBtn.setIcon(tcImage);
-                }
-                break;
-            case LAUNCH_LUG:
-                typeCombo.setSelectedItem(trans.get(LAUNCH_LUG_KEY));
-                llDescTextField.setText(preset.get(ComponentPreset.DESCRIPTION));
-                if (preset.has(ComponentPreset.INNER_DIAMETER)) {
-                    llInnerDia.setValue(preset.get(ComponentPreset.INNER_DIAMETER));
-                    llInnerDia.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
-                }
-                if (preset.has(ComponentPreset.LENGTH)) {
-                    llLength.setValue(preset.get(ComponentPreset.LENGTH));
-                    llLength.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
-                }
-                if (preset.has(ComponentPreset.MASS)) {
-                    llMass.setValue(preset.get(ComponentPreset.MASS));
-                    llMass.setCurrentUnit(UnitGroup.UNITS_MASS.getDefaultUnit());
-                }
-                if (preset.has(ComponentPreset.OUTER_DIAMETER)) {
-                    llOuterDia.setValue(preset.get(ComponentPreset.OUTER_DIAMETER));
-                    llOuterDia.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
-                }
-                llPartNoTextField.setText(preset.get(ComponentPreset.PARTNO));
-                if (preset.has(ComponentPreset.IMAGE)) {
-                    llImage = new ImageIcon(byteArrayToImage(preset.get(ComponentPreset.IMAGE)));
-                    llImageBtn.setIcon(llImage);
-                }
-                break;
-            case PARACHUTE:
-                setMaterial(materialChooser, preset, holder, Material.Type.SURFACE, ComponentPreset.MATERIAL);
-                typeCombo.setSelectedItem(trans.get(PARACHUTE_KEY));
-                pcDescTextField.setText(preset.get(ComponentPreset.DESCRIPTION));
-                if (preset.has(ComponentPreset.LINE_COUNT)) {
-                    pcLineCount.setText(preset.get(ComponentPreset.LINE_COUNT).toString());
-                }
-                if (preset.has(ComponentPreset.SIDES)) {
-                    pcSides.setText(preset.get(ComponentPreset.SIDES).toString());
-                }
-                if (preset.has(ComponentPreset.MASS)) {
-                    pcMass.setValue(preset.get(ComponentPreset.MASS));
-                    pcMass.setCurrentUnit(UnitGroup.UNITS_MASS.getDefaultUnit());
-                }
-                if (preset.has(ComponentPreset.DIAMETER)) {
-                    pcDiameter.setValue(preset.get(ComponentPreset.DIAMETER));
-                    pcDiameter.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
-                }
-                if (preset.has(ComponentPreset.LINE_LENGTH)) {
-                    pcLineLength.setValue(preset.get(ComponentPreset.LINE_LENGTH));
-                    pcLineLength.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
-                }
-                pcPartNoTextField.setText(preset.get(ComponentPreset.PARTNO));
-                if (preset.has(ComponentPreset.IMAGE)) {
-                    pcImage = new ImageIcon(byteArrayToImage(preset.get(ComponentPreset.IMAGE)));
-                    pcImageBtn.setIcon(pcImage);
-                }
-                setMaterial(pcLineMaterialChooser, preset, holder, Material.Type.LINE, ComponentPreset.LINE_MATERIAL);
-//                pcLineMaterialChooser.setModel(new MaterialModel(PresetEditorDialog.this, Material.Type.LINE));
-
-//                pcLineMaterialChooser.getModel().setSelectedItem(preset.get(ComponentPreset.LINE_MATERIAL));
-                break;
-            case STREAMER:
-                setMaterial(materialChooser, preset, holder, Material.Type.SURFACE, ComponentPreset.MATERIAL);
-                typeCombo.setSelectedItem(trans.get(STREAMER_KEY));
-                stDescTextField.setText(preset.get(ComponentPreset.DESCRIPTION));
-                if (preset.has(ComponentPreset.LENGTH)) {
-                    stLength.setValue(preset.get(ComponentPreset.LENGTH));
-                    stLength.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
-                }
-                if (preset.has(ComponentPreset.THICKNESS)) {
-                    stThickness.setValue(preset.get(ComponentPreset.LENGTH));
-                    stThickness.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
-                }
-                if (preset.has(ComponentPreset.MASS)) {
-                    stMass.setValue(preset.get(ComponentPreset.MASS));
-                    stMass.setCurrentUnit(UnitGroup.UNITS_MASS.getDefaultUnit());
-                }
-                if (preset.has(ComponentPreset.WIDTH)) {
-                    stWidth.setValue(preset.get(ComponentPreset.WIDTH));
-                    stWidth.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
-                }
-                if (preset.has(ComponentPreset.IMAGE)) {
-                    stImage = new ImageIcon(byteArrayToImage(preset.get(ComponentPreset.IMAGE)));
-                    stImageBtn.setIcon(stImage);
-                }
-                stPartNoTextField.setText(preset.get(ComponentPreset.PARTNO));
-                break;
-            default:
-        }
-    }
-
-    private void setMaterial(final JComboBox chooser, final ComponentPreset preset, final MaterialHolder holder,
-                             final Material.Type theType, final TypedKey key) {
-        if (holder == null) {
-            chooser.setModel(new MaterialModel(PresetEditorDialog.this, theType));
-        }
-        else {
-            chooser.setModel(new MaterialModel(PresetEditorDialog.this, theType,
-                    holder.asDatabase(theType)));
-        }
-        if (preset != null) {
-            chooser.getModel().setSelectedItem(preset.get(key));
-        }
-    }
-
-    /**
-     * Extract the preset data from the UI fields, create a ComponentPreset instance, and notify the listener.
-     */
-    private boolean saveResult() {
-        String type = (String) typeCombo.getSelectedItem();
-
-        ComponentPreset result = null;
-
-        if (type.equals(trans.get(NOSE_CONE_KEY))) {
-            result = extractNoseCone();
-            if (result != null) {
-                clearNoseCone();
-            }
-        }
-        else if (type.equals(trans.get(TRANSITION_KEY))) {
-            result = extractTransition();
-            if (result != null) {
-                clearTransition();
-            }
-        }
-        else if (type.equals(trans.get(BODY_TUBE_KEY))) {
-            result = extractBodyTube();
-            if (result != null) {
-                clearBodyTube();
-            }
-        }
-        else if (type.equals(trans.get(TUBE_COUPLER_KEY))) {
-            result = extractTubeCoupler();
-            if (result != null) {
-                clearTubeCoupler();
-            }
-        }
-        else if (type.equals(trans.get(EB_KEY))) {
-            result = extractEngineBlock();
-            if (result != null) {
-                clearEngineBlock();
-            }
-        }
-        else if (type.equals(trans.get(CR_KEY))) {
-            result = extractCenteringRing();
-            if (result != null) {
-                clearCenteringRing();
-            }
-        }
-        else if (type.equals(trans.get(BULKHEAD_KEY))) {
-            result = extractBulkhead();
-            if (result != null) {
-                clearBulkhead();
-            }
-        }
-        else if (type.equals(trans.get(LAUNCH_LUG_KEY))) {
-            result = extractLaunchLug();
-            if (result != null) {
-                clearLaunchLug();
-            }
-        }
-        else if (type.equals(trans.get(PARACHUTE_KEY))) {
-            result = extractParachute();
-            if (result != null) {
-                clearParachute();
-            }
-        }
-        else if (type.equals(trans.get(STREAMER_KEY))) {
-            result = extractStreamer();
-            if (result != null) {
-                clearStreamer();
-            }
-        }
-        if (result != null) {
-            resultListener.notifyResult(result);
-            return true;
-        }
-        else {
-            return false;
-        }
-    }
-
-    private ComponentPreset extractNoseCone() {
-        TypedPropertyMap props = new TypedPropertyMap();
-        try {
-            props.put(ComponentPreset.TYPE, ComponentPreset.Type.NOSE_CONE);
-            props.put(ComponentPreset.AFT_OUTER_DIAMETER, ncAftDia.getValue());
-            props.put(ComponentPreset.AFT_SHOULDER_DIAMETER, ncAftShoulderDia.getValue());
-            props.put(ComponentPreset.AFT_SHOULDER_LENGTH, ncAftShoulderLen.getValue());
-            props.put(ComponentPreset.DESCRIPTION, ncDescTextField.getText());
-            props.put(ComponentPreset.PARTNO, ncPartNoTextField.getText());
-            props.put(ComponentPreset.MANUFACTURER, Manufacturer.getManufacturer(mfgTextField.getText()));
-            props.put(ComponentPreset.LENGTH, ncLength.getValue());
-            props.put(ComponentPreset.SHAPE, Transition.Shape.toShape((String) ncShapeCB.getSelectedItem()));
-            final Material material = (Material) materialChooser.getSelectedItem();
-            if (material != null) {
-                props.put(ComponentPreset.MATERIAL, material);
-            }
-            else {
-                JOptionPane.showMessageDialog(null, "A material must be selected.", "Error", JOptionPane.ERROR_MESSAGE);
-                return null;
-            }
-            props.put(ComponentPreset.MASS, ncMass.getValue());
-            props.put(ComponentPreset.FILLED, ncFilledCB.isSelected());
-            if (ncImage != null) {
-                props.put(ComponentPreset.IMAGE, imageToByteArray(ncImage.getImage()));
-            }
-
-            return ComponentPresetFactory.create(props);
-        }
-        catch (NumberFormatException nfe) {
-            JOptionPane.showMessageDialog(null, "Could not convert nose cone attribute.", "Error", JOptionPane.ERROR_MESSAGE);
-        }
-        catch (InvalidComponentPresetException e) {
-            JOptionPane.showMessageDialog(null, craftErrorMessage(e, "Mandatory nose cone attribute not set."), "Error", JOptionPane.ERROR_MESSAGE);
-        }
-        return null;
-    }
-
-    private void clearNoseCone() {
-        ncAftDia.setValue(0);
-        ncAftShoulderDia.setValue(0);
-        ncAftShoulderLen.setValue(0);
-        ncDescTextField.setText("");
-        ncPartNoTextField.setText("");
-        ncLength.setValue(0);
-        ncMass.setValue(0);
-        ncFilledCB.setSelected(false);
-        ncImage = null;
-        ncImageBtn.setIcon(null);
-    }
-
-    private ComponentPreset extractTransition() {
-        TypedPropertyMap props = new TypedPropertyMap();
-        try {
-            props.put(ComponentPreset.TYPE, ComponentPreset.Type.TRANSITION);
-            props.put(ComponentPreset.AFT_OUTER_DIAMETER, trAftDia.getValue());
-            props.put(ComponentPreset.AFT_SHOULDER_DIAMETER, trAftShoulderDia.getValue());
-            props.put(ComponentPreset.AFT_SHOULDER_LENGTH, trAftShoulderLen.getValue());
-            props.put(ComponentPreset.FORE_OUTER_DIAMETER, trForeDia.getValue());
-            props.put(ComponentPreset.FORE_SHOULDER_DIAMETER, trForeShoulderDia.getValue());
-            props.put(ComponentPreset.FORE_SHOULDER_LENGTH, trForeShoulderLen.getValue());
-            props.put(ComponentPreset.DESCRIPTION, trDescTextField.getText());
-            props.put(ComponentPreset.PARTNO, trPartNoTextField.getText());
-            props.put(ComponentPreset.MANUFACTURER, Manufacturer.getManufacturer(mfgTextField.getText()));
-
-            props.put(ComponentPreset.LENGTH, trLength.getValue());
-            props.put(ComponentPreset.SHAPE, Transition.Shape.toShape((String) trShapeCB.getSelectedItem()));
-            final Material material = (Material) materialChooser.getSelectedItem();
-            if (material != null) {
-                props.put(ComponentPreset.MATERIAL, material);
-            }
-            else {
-                JOptionPane.showMessageDialog(null, "A material must be selected.", "Error", JOptionPane.ERROR_MESSAGE);
-                return null;
-            }
-            props.put(ComponentPreset.MASS, trMass.getValue());
-            props.put(ComponentPreset.FILLED, trFilledCB.isSelected());
-            if (trImage != null) {
-                props.put(ComponentPreset.IMAGE, imageToByteArray(trImage.getImage()));
-            }
-
-            return ComponentPresetFactory.create(props);
-        }
-        catch (NumberFormatException nfe) {
-            JOptionPane.showMessageDialog(null, "Could not convert transition attribute.", "Error", JOptionPane.ERROR_MESSAGE);
-        }
-        catch (InvalidComponentPresetException e) {
-            JOptionPane.showMessageDialog(null, craftErrorMessage(e, "Mandatory transition attribute not set."), "Error", JOptionPane.ERROR_MESSAGE);
-        }
-        return null;
-    }
-
-    private void clearTransition() {
-        trAftDia.setValue(0);
-        trAftShoulderDia.setValue(0);
-        trAftShoulderLen.setValue(0);
-        trForeDia.setValue(0);
-        trForeShoulderDia.setValue(0);
-        trForeShoulderLen.setValue(0);
-        trDescTextField.setText("");
-        trPartNoTextField.setText("");
-        trLength.setValue(0);
-        trMass.setValue(0);
-        trFilledCB.setSelected(false);
-        trImage = null;
-        trImageBtn.setIcon(null);
-    }
-
-    private ComponentPreset extractBodyTube() {
-        TypedPropertyMap props = new TypedPropertyMap();
-        try {
-            props.put(ComponentPreset.TYPE, ComponentPreset.Type.BODY_TUBE);
-            props.put(ComponentPreset.OUTER_DIAMETER, btOuterDia.getValue());
-            props.put(ComponentPreset.INNER_DIAMETER, btInnerDia.getValue());
-            props.put(ComponentPreset.DESCRIPTION, btDescTextField.getText());
-            props.put(ComponentPreset.PARTNO, btPartNoTextField.getText());
-            props.put(ComponentPreset.MANUFACTURER, Manufacturer.getManufacturer(mfgTextField.getText()));
-            props.put(ComponentPreset.LENGTH, btLength.getValue());
-            final Material material = (Material) materialChooser.getSelectedItem();
-            if (material != null) {
-                props.put(ComponentPreset.MATERIAL, material);
-            }
-            else {
-                JOptionPane.showMessageDialog(null, "A material must be selected.", "Error", JOptionPane.ERROR_MESSAGE);
-                return null;
-            }
-            props.put(ComponentPreset.MASS, btMass.getValue());
-            if (btImage != null) {
-                props.put(ComponentPreset.IMAGE, imageToByteArray(btImage.getImage()));
-            }
-            return ComponentPresetFactory.create(props);
-        }
-        catch (NumberFormatException nfe) {
-            JOptionPane.showMessageDialog(null, "Could not convert body tube attribute.", "Error", JOptionPane.ERROR_MESSAGE);
-        }
-        catch (InvalidComponentPresetException e) {
-            JOptionPane.showMessageDialog(null, craftErrorMessage(e, "Mandatory body tube attribute not set."), "Error", JOptionPane.ERROR_MESSAGE);
-        }
-        return null;
-    }
-
-    private void clearBodyTube() {
-        btOuterDia.setValue(0);
-        btInnerDia.setValue(0);
-        btDescTextField.setText("");
-        btPartNoTextField.setText("");
-        btLength.setValue(0);
-        btMass.setValue(0);
-        btImage = null;
-        btImageBtn.setIcon(null);
-    }
-
-    public ComponentPreset extractTubeCoupler() {
-        TypedPropertyMap props = new TypedPropertyMap();
-        try {
-            props.put(ComponentPreset.TYPE, ComponentPreset.Type.TUBE_COUPLER);
-            props.put(ComponentPreset.OUTER_DIAMETER, tcOuterDia.getValue());
-            props.put(ComponentPreset.INNER_DIAMETER, tcInnerDia.getValue());
-            props.put(ComponentPreset.DESCRIPTION, tcDescTextField.getText());
-            props.put(ComponentPreset.PARTNO, tcPartNoTextField.getText());
-            props.put(ComponentPreset.MANUFACTURER, Manufacturer.getManufacturer(mfgTextField.getText()));
-            props.put(ComponentPreset.LENGTH, tcLength.getValue());
-            final Material material = (Material) materialChooser.getSelectedItem();
-            if (material != null) {
-                props.put(ComponentPreset.MATERIAL, material);
-            }
-            else {
-                JOptionPane.showMessageDialog(null, "A material must be selected.", "Error", JOptionPane.ERROR_MESSAGE);
-                return null;
-            }
-            props.put(ComponentPreset.MASS, tcMass.getValue());
-            if (tcImage != null) {
-                props.put(ComponentPreset.IMAGE, imageToByteArray(tcImage.getImage()));
-            }
-
-            return ComponentPresetFactory.create(props);
-        }
-        catch (NumberFormatException nfe) {
-            JOptionPane.showMessageDialog(null, "Could not convert tube coupler attribute.", "Error", JOptionPane.ERROR_MESSAGE);
-        }
-        catch (InvalidComponentPresetException e) {
-            JOptionPane.showMessageDialog(null, craftErrorMessage(e, "Mandatory tube coupler attribute not set."), "Error", JOptionPane.ERROR_MESSAGE);
-        }
-        return null;
-    }
-
-    private void clearTubeCoupler() {
-        tcOuterDia.setValue(0);
-        tcInnerDia.setValue(0);
-        tcDescTextField.setText("");
-        tcPartNoTextField.setText("");
-        tcLength.setValue(0);
-        tcMass.setValue(0);
-        tcImage = null;
-        tcImageBtn.setIcon(null);
-    }
-
-    private ComponentPreset extractBulkhead() {
-        TypedPropertyMap props = new TypedPropertyMap();
-        try {
-            props.put(ComponentPreset.TYPE, ComponentPreset.Type.BULK_HEAD);
-            props.put(ComponentPreset.OUTER_DIAMETER, bhOuterDia.getValue());
-            props.put(ComponentPreset.DESCRIPTION, bhDescTextField.getText());
-            props.put(ComponentPreset.PARTNO, bhPartNoTextField.getText());
-            props.put(ComponentPreset.MANUFACTURER, Manufacturer.getManufacturer(mfgTextField.getText()));
-            props.put(ComponentPreset.LENGTH, bhLength.getValue());
-            final Material material = (Material) materialChooser.getSelectedItem();
-            if (material != null) {
-                props.put(ComponentPreset.MATERIAL, material);
-            }
-            else {
-                JOptionPane.showMessageDialog(null, "A material must be selected.", "Error", JOptionPane.ERROR_MESSAGE);
-                return null;
-            }
-            props.put(ComponentPreset.MASS, bhMass.getValue());
-            if (bhImage != null) {
-                props.put(ComponentPreset.IMAGE, imageToByteArray(bhImage.getImage()));
-            }
-            return ComponentPresetFactory.create(props);
-        }
-        catch (NumberFormatException nfe) {
-            JOptionPane.showMessageDialog(null, "Could not convert bulkhead attribute.", "Error", JOptionPane.ERROR_MESSAGE);
-        }
-        catch (InvalidComponentPresetException e) {
-            JOptionPane.showMessageDialog(null, craftErrorMessage(e, "Mandatory bulkhead attribute not set."), "Error", JOptionPane.ERROR_MESSAGE);
-        }
-        return null;
-    }
-
-    private void clearBulkhead() {
-        bhOuterDia.setValue(0);
-        bhDescTextField.setText("");
-        bhPartNoTextField.setText("");
-        bhLength.setValue(0);
-        bhMass.setValue(0);
-        bhImage = null;
-        bhImageBtn.setIcon(null);
-    }
-
-    private ComponentPreset extractCenteringRing() {
-        TypedPropertyMap props = new TypedPropertyMap();
-        try {
-            props.put(ComponentPreset.TYPE, ComponentPreset.Type.CENTERING_RING);
-            props.put(ComponentPreset.OUTER_DIAMETER, crOuterDia.getValue());
-            props.put(ComponentPreset.INNER_DIAMETER, crInnerDia.getValue());
-            props.put(ComponentPreset.DESCRIPTION, crDescTextField.getText());
-            props.put(ComponentPreset.PARTNO, crPartNoTextField.getText());
-            props.put(ComponentPreset.MANUFACTURER, Manufacturer.getManufacturer(mfgTextField.getText()));
-            props.put(ComponentPreset.LENGTH, crThickness.getValue());
-            final Material material = (Material) materialChooser.getSelectedItem();
-            if (material != null) {
-                props.put(ComponentPreset.MATERIAL, material);
-            }
-            else {
-                JOptionPane.showMessageDialog(null, "A material must be selected.", "Error", JOptionPane.ERROR_MESSAGE);
-                return null;
-            }
-            props.put(ComponentPreset.MASS, crMass.getValue());
-            if (crImage != null) {
-                props.put(ComponentPreset.IMAGE, imageToByteArray(crImage.getImage()));
-            }
-            return ComponentPresetFactory.create(props);
-        }
-        catch (NumberFormatException nfe) {
-            JOptionPane.showMessageDialog(null, "Could not convert centering ring attribute.", "Error", JOptionPane.ERROR_MESSAGE);
-        }
-        catch (InvalidComponentPresetException e) {
-            JOptionPane.showMessageDialog(null, craftErrorMessage(e, "Mandatory centering ring attribute not set."), "Error", JOptionPane.ERROR_MESSAGE);
-        }
-        return null;
-    }
-
-    private void clearCenteringRing() {
-        crOuterDia.setValue(0);
-        crInnerDia.setValue(0);
-        crDescTextField.setText("");
-        crPartNoTextField.setText("");
-        crThickness.setValue(0);
-        crMass.setValue(0);
-        crImage = null;
-        crImageBtn.setIcon(null);
-    }
-
-    public ComponentPreset extractEngineBlock() {
-        TypedPropertyMap props = new TypedPropertyMap();
-        try {
-            props.put(ComponentPreset.TYPE, ComponentPreset.Type.ENGINE_BLOCK);
-            props.put(ComponentPreset.OUTER_DIAMETER, ebOuterDia.getValue());
-            props.put(ComponentPreset.INNER_DIAMETER, ebInnerDia.getValue());
-            props.put(ComponentPreset.DESCRIPTION, ebDescTextField.getText());
-            props.put(ComponentPreset.PARTNO, ebPartNoTextField.getText());
-            props.put(ComponentPreset.MANUFACTURER, Manufacturer.getManufacturer(mfgTextField.getText()));
-            props.put(ComponentPreset.LENGTH, ebThickness.getValue());
-            final Material material = (Material) materialChooser.getSelectedItem();
-            if (material != null) {
-                props.put(ComponentPreset.MATERIAL, material);
-            }
-            else {
-                JOptionPane.showMessageDialog(null, "A material must be selected.", "Error", JOptionPane.ERROR_MESSAGE);
-                return null;
-            }
-            props.put(ComponentPreset.MASS, ebMass.getValue());
-            if (ebImage != null) {
-                props.put(ComponentPreset.IMAGE, imageToByteArray(ebImage.getImage()));
-            }
-            return ComponentPresetFactory.create(props);
-        }
-        catch (NumberFormatException nfe) {
-            JOptionPane.showMessageDialog(null, "Could not convert engine block attribute.", "Error", JOptionPane.ERROR_MESSAGE);
-        }
-        catch (InvalidComponentPresetException e) {
-            JOptionPane.showMessageDialog(null, craftErrorMessage(e, "Mandatory engine block attribute not set."), "Error", JOptionPane.ERROR_MESSAGE);
-        }
-        return null;
-    }
-
-    private void clearEngineBlock() {
-        ebOuterDia.setValue(0);
-        ebInnerDia.setValue(0);
-        ebDescTextField.setText("");
-        ebPartNoTextField.setText("");
-        ebThickness.setValue(0);
-        ebMass.setValue(0);
-        ebImage = null;
-        ebImageBtn.setIcon(null);
-    }
-
-    public ComponentPreset extractLaunchLug() {
-        TypedPropertyMap props = new TypedPropertyMap();
-        try {
-            props.put(ComponentPreset.TYPE, ComponentPreset.Type.LAUNCH_LUG);
-            props.put(ComponentPreset.OUTER_DIAMETER, llOuterDia.getValue());
-            props.put(ComponentPreset.INNER_DIAMETER, llInnerDia.getValue());
-            props.put(ComponentPreset.DESCRIPTION, llDescTextField.getText());
-            props.put(ComponentPreset.PARTNO, llPartNoTextField.getText());
-            props.put(ComponentPreset.MANUFACTURER, Manufacturer.getManufacturer(mfgTextField.getText()));
-            props.put(ComponentPreset.LENGTH, llLength.getValue());
-            final Material material = (Material) materialChooser.getSelectedItem();
-            if (material != null) {
-                props.put(ComponentPreset.MATERIAL, material);
-            }
-            else {
-                JOptionPane.showMessageDialog(null, "A material must be selected.", "Error", JOptionPane.ERROR_MESSAGE);
-                return null;
-            }
-            props.put(ComponentPreset.MASS, llMass.getValue());
-            if (llImage != null) {
-                props.put(ComponentPreset.IMAGE, imageToByteArray(llImage.getImage()));
-            }
-            return ComponentPresetFactory.create(props);
-        }
-        catch (NumberFormatException nfe) {
-            JOptionPane.showMessageDialog(null, "Could not convert launch lug attribute.", "Error", JOptionPane.ERROR_MESSAGE);
-        }
-        catch (InvalidComponentPresetException e) {
-            JOptionPane.showMessageDialog(null, craftErrorMessage(e, "Mandatory launch lug attribute not set."), "Error", JOptionPane.ERROR_MESSAGE);
-        }
-        return null;
-    }
-
-    private void clearLaunchLug() {
-        llOuterDia.setValue(0);
-        llInnerDia.setValue(0);
-        llDescTextField.setText("");
-        llPartNoTextField.setText("");
-        llLength.setValue(0);
-        llMass.setValue(0);
-        llImage = null;
-        llImageBtn.setIcon(null);
-    }
-
-    public ComponentPreset extractParachute() {
-        TypedPropertyMap props = new TypedPropertyMap();
-        try {
-            props.put(ComponentPreset.TYPE, ComponentPreset.Type.PARACHUTE);
-            props.put(ComponentPreset.DIAMETER, pcDiameter.getValue());
-            props.put(ComponentPreset.DESCRIPTION, pcDescTextField.getText());
-            props.put(ComponentPreset.PARTNO, pcPartNoTextField.getText());
-            props.put(ComponentPreset.MANUFACTURER, Manufacturer.getManufacturer(mfgTextField.getText()));
-            if (!pcLineCount.getText().equals("")) {
-                props.put(ComponentPreset.LINE_COUNT, Integer.parseInt(pcLineCount.getText()));
-            }
-            if (!pcSides.getText().equals("")) {
-                props.put(ComponentPreset.SIDES, Integer.parseInt(pcSides.getText()));
-            }
-            props.put(ComponentPreset.LINE_LENGTH, pcLineLength.getValue());
-            Material material = (Material) materialChooser.getSelectedItem();
-            if (material != null) {
-                props.put(ComponentPreset.MATERIAL, material);
-            }
-            else {
-                JOptionPane.showMessageDialog(null, "A material must be selected.", "Error", JOptionPane.ERROR_MESSAGE);
-                return null;
-            }
-            material = (Material) pcLineMaterialChooser.getSelectedItem();
-            if (material != null) {
-                props.put(ComponentPreset.LINE_MATERIAL, material);
-            }
-            props.put(ComponentPreset.MASS, pcMass.getValue());
-            if (pcImage != null) {
-                props.put(ComponentPreset.IMAGE, imageToByteArray(pcImage.getImage()));
-            }
-            return ComponentPresetFactory.create(props);
-        }
-        catch (NumberFormatException nfe) {
-            JOptionPane.showMessageDialog(null, "Could not convert parachute attribute.", "Error", JOptionPane.ERROR_MESSAGE);
-        }
-        catch (InvalidComponentPresetException e) {
-            JOptionPane.showMessageDialog(null, craftErrorMessage(e, "Mandatory parachute attribute not set."), "Error", JOptionPane.ERROR_MESSAGE);
-        }
-        return null;
-    }
-
-    private void clearParachute() {
-        ebOuterDia.setValue(0);
-        ebInnerDia.setValue(0);
-        ebDescTextField.setText("");
-        ebPartNoTextField.setText("");
-        ebThickness.setValue(0);
-        ebMass.setValue(0);
-        ebImage = null;
-        ebImageBtn.setIcon(null);
-    }
-
-    public ComponentPreset extractStreamer() {
-        TypedPropertyMap props = new TypedPropertyMap();
-        try {
-            props.put(ComponentPreset.TYPE, ComponentPreset.Type.STREAMER);
-            props.put(ComponentPreset.DESCRIPTION, stDescTextField.getText());
-            props.put(ComponentPreset.PARTNO, stPartNoTextField.getText());
-            props.put(ComponentPreset.MANUFACTURER, Manufacturer.getManufacturer(mfgTextField.getText()));
-            props.put(ComponentPreset.THICKNESS, stThickness.getValue());
-            props.put(ComponentPreset.LENGTH, stLength.getValue());
-            props.put(ComponentPreset.WIDTH, stWidth.getValue());
-            final Material material = (Material) materialChooser.getSelectedItem();
-            if (material != null) {
-                props.put(ComponentPreset.MATERIAL, material);
-            }
-            else {
-                JOptionPane.showMessageDialog(null, "A material must be selected.", "Error", JOptionPane.ERROR_MESSAGE);
-                return null;
-            }
-            props.put(ComponentPreset.MASS, stMass.getValue());
-            if (stImage != null) {
-                props.put(ComponentPreset.IMAGE, imageToByteArray(stImage.getImage()));
-            }
-            return ComponentPresetFactory.create(props);
-        }
-        catch (NumberFormatException nfe) {
-            JOptionPane.showMessageDialog(null, "Could not convert engine block attribute.", "Error", JOptionPane.ERROR_MESSAGE);
-        }
-        catch (InvalidComponentPresetException e) {
-            JOptionPane.showMessageDialog(null, craftErrorMessage(e, "Mandatory engine block attribute not set."), "Error", JOptionPane.ERROR_MESSAGE);
-        }
-        return null;
-    }
-
-    private void clearStreamer() {
-        stWidth.setValue(0);
-        stLength.setValue(0);
-        stDescTextField.setText("");
-        stPartNoTextField.setText("");
-        stThickness.setValue(0);
-        stMass.setValue(0);
-        stImage = null;
-        stImageBtn.setIcon(null);
-    }
-
-    public void itemStateChanged(ItemEvent evt) {
-        CardLayout cl = (CardLayout) (componentOverlayPanel.getLayout());
-        final String item = (String) evt.getItem();
-        if (materialChooser != null && evt.getStateChange() == ItemEvent.SELECTED) {
-            if (item.equals(trans.get(PARACHUTE_KEY)) || item.equals(trans.get(STREAMER_KEY))) {
-                if (!((MaterialModel) materialChooser.getModel()).getType().equals(Material.Type.SURFACE)) {
-                    setMaterial(materialChooser, null, holder, Material.Type.SURFACE, ComponentPreset.MATERIAL);
-                }
-            }
-            else {
-                if (!((MaterialModel) materialChooser.getModel()).getType().equals(Material.Type.BULK)) {
-                    setMaterial(materialChooser, null, holder, Material.Type.BULK, ComponentPreset.MATERIAL);
-                }
-            }
-        }
-        cl.show(componentOverlayPanel, componentMap.get(item));
-    }
-
-    //Todo: I18N
-    private String craftErrorMessage(InvalidComponentPresetException e, String baseMsg) {
-        StringBuilder stringBuilder = new StringBuilder();
-        List<String> invalids = e.getErrors();
-        stringBuilder.append(baseMsg).append("\n");
-        for (int i = 0; i < invalids.size(); i++) {
-            String s = invalids.get(i);
-            stringBuilder.append(s).append("\n");
-        }
-
-        return stringBuilder.toString();
-    }
-
-    /**
-     * Convert an image to a byte array in png format.
-     *
-     * @param originalImage
-     *
-     * @return
-     */
-    private byte[] imageToByteArray(Image originalImage) {
-        byte[] imageInByte = null;
-        try {
-            BufferedImage bi = imageToBufferedImage(originalImage);
-            ByteArrayOutputStream baos = new ByteArrayOutputStream();
-            ImageIO.write(bi, "png", baos);
-            baos.flush();
-            imageInByte = baos.toByteArray();
-            baos.close();
-        }
-        catch (IOException e) {
-            log.error("Could not read image.");
-        }
-        return imageInByte;
-    }
-
-    private BufferedImage imageToBufferedImage(final Image originalImage) {
-        BufferedImage bi = new BufferedImage(originalImage.getWidth(null), originalImage.getHeight(null), BufferedImage.TYPE_INT_RGB);
-
-        Graphics2D g2 = bi.createGraphics();
-        g2.drawImage(originalImage, 0, 0, null);
-        return bi;
-    }
-
-    private BufferedImage byteArrayToImage(byte[] src) {
-        // convert byte array back to BufferedImage
-        InputStream in = new ByteArrayInputStream(src);
-        try {
-            return ImageIO.read(in);
-        }
-        catch (IOException e) {
-            log.error("Could not convert image.");
-        }
-        return null;
-    }
-
-    private ImageIcon scaleImage(Image image, int targetDimension) {
-        int width = image.getWidth(this);
-        int height = image.getHeight(this);
-        double ratio = 1.0;
-
-        /*
-         * Determine how to scale the image. Since the accessory can expand
-         * vertically make sure we don't go larger than 150 when scaling
-         * vertically.
-         */
-        if (width >= height) {
-            ratio = (double) (targetDimension - 5) / width;
-            width = targetDimension - 5;
-            height = (int) (height * ratio);
-        }
-        else {
-            if (getHeight() > 150) {
-                ratio = (double) (targetDimension - 5) / height;
-                height = targetDimension - 5;
-                width = (int) (width * ratio);
-            }
-            else {
-                ratio = (double) getHeight() / height;
-                height = getHeight();
-                width = (int) (width * ratio);
-            }
-        }
-
-        return new ImageIcon(image.getScaledInstance(width, height, Image.SCALE_DEFAULT));
-    }
-
-    static class PresetInputVerifier extends InputVerifier {
-
-        /**
-         * Matches user input against a regular expression.
-         */
-        private Matcher matcher;
-
-        PresetInputVerifier(final Pattern thePattern) {
-            matcher = thePattern.matcher("");
-        }
-
-        /**
-         * Return true only if the untrimmed user input matches the regular expression provided to the constructor.
-         *
-         * @param aComponent must be an instance of JTextComponent.
-         */
-        public boolean verify(JComponent aComponent) {
-            JTextComponent textComponent = (JTextComponent) aComponent;
-            String text = textComponent.getText();
-            matcher.reset(text);
-            return matcher.matches();
-        }
-
-        /**
-         * Always returns <tt>true</tt>, in this implementation, such that focus can always transfer to another
-         * component whenever the validation fails.
-         * <p/>
-         * <P>If <tt>super.shouldYieldFocus</tt> returns <tt>false</tt>, then clear the text field.
-         *
-         * @param aComponent is a <tt>JTextComponent</tt>.
-         */
-        @Override
-        public boolean shouldYieldFocus(JComponent aComponent) {
-            if (!super.shouldYieldFocus(aComponent)) {
-                ((JTextComponent) aComponent).setText("");
-            }
-            return true;
-        }
-    }
-
-    class MaterialChooser extends JComboBox {
-
-        public MaterialChooser() {
-        }
-        public MaterialChooser(MaterialModel model) {
-            super(model);
-        }
+import javax.imageio.ImageIO;
+import javax.swing.ComboBoxModel;
+import javax.swing.DefaultComboBoxModel;
+import javax.swing.ImageIcon;
+import javax.swing.InputVerifier;
+import javax.swing.JButton;
+import javax.swing.JCheckBox;
+import javax.swing.JComboBox;
+import javax.swing.JComponent;
+import javax.swing.JDialog;
+import javax.swing.JFileChooser;
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JSpinner;
+import javax.swing.JTextField;
+import javax.swing.border.EmptyBorder;
+import javax.swing.filechooser.FileNameExtensionFilter;
+import javax.swing.text.JTextComponent;
 
-        /**
-         * Sets the data model that the <code>JComboBox</code> uses to obtain the list of items.
-         *
-         * @param aModel the <code>ComboBoxModel</code> that provides the displayed list of items
-         *
-         * @beaninfo bound: true description: Model that the combo box uses to get data to display.
-         */
-        @Override
-        public void setModel(final ComboBoxModel aModel) {
-            if (getModel() instanceof MaterialModel) {
-                MaterialModel old = (MaterialModel) getModel();
-                old.removeListener();
-            }
-            super.setModel(aModel);
+import net.miginfocom.swing.MigLayout;
+import net.sf.openrocket.gui.SpinnerEditor;
+import net.sf.openrocket.gui.adaptors.DoubleModel;
+import net.sf.openrocket.gui.components.UnitSelector;
+import net.sf.openrocket.l10n.Translator;
+import net.sf.openrocket.logging.LogHelper;
+import net.sf.openrocket.material.Material;
+import net.sf.openrocket.motor.Manufacturer;
+import net.sf.openrocket.preset.ComponentPreset;
+import net.sf.openrocket.preset.ComponentPresetFactory;
+import net.sf.openrocket.preset.InvalidComponentPresetException;
+import net.sf.openrocket.preset.TypedKey;
+import net.sf.openrocket.preset.TypedPropertyMap;
+import net.sf.openrocket.preset.loader.MaterialHolder;
+import net.sf.openrocket.rocketcomponent.Transition;
+import net.sf.openrocket.startup.Application;
+import net.sf.openrocket.unit.UnitGroup;
 
-        }
-    }
+/**
+ * Preset editor for creating new preset components.
+ */
+public class PresetEditorDialog extends JDialog implements ItemListener {
+       
+       private static Translator trans = Application.getTranslator();
+       
+       private static LogHelper log = Application.getLogger();
+       
+       private static final String NON_NEGATIVE_INTEGER_FIELD = "(\\d){0,10}";
+       
+       /**
+        * Input of non-negative decimals.
+        */
+       final PresetInputVerifier NON_NEGATIVE_INTEGER = new PresetInputVerifier(Pattern.compile(NON_NEGATIVE_INTEGER_FIELD));
+       
+       private final JPanel contentPanel = new JPanel();
+       private DeselectableComboBox typeCombo;
+       private JTextField mfgTextField;
+       private MaterialChooser materialChooser;
+       private MaterialHolder holder = null;
+       
+       private JTextField ncPartNoTextField;
+       private JTextField ncDescTextField;
+       private DoubleModel ncLength;
+       private JCheckBox ncFilledCB;
+       private JComboBox ncShapeCB;
+       private DoubleModel ncAftDia;
+       private DoubleModel ncAftShoulderDia;
+       private DoubleModel ncAftShoulderLen;
+       private DoubleModel ncMass;
+       private ImageIcon ncImage;
+       private JButton ncImageBtn;
+       
+       private JTextField trPartNoTextField;
+       private JTextField trDescTextField;
+       private DoubleModel trLength;
+       private DoubleModel trAftDia;
+       private DoubleModel trAftShoulderDia;
+       private DoubleModel trAftShoulderLen;
+       private DoubleModel trForeDia;
+       private DoubleModel trForeShoulderDia;
+       private DoubleModel trForeShoulderLen;
+       private DoubleModel trMass;
+       private ImageIcon trImage;
+       private JCheckBox trFilledCB;
+       private JComboBox trShapeCB;
+       private JButton trImageBtn;
+       
+       private JTextField btPartNoTextField;
+       private JTextField btDescTextField;
+       private DoubleModel btMass;
+       private DoubleModel btInnerDia;
+       private DoubleModel btOuterDia;
+       private DoubleModel btLength;
+       private ImageIcon btImage;
+       private JButton btImageBtn;
+       
+       private JTextField tcPartNoTextField;
+       private JTextField tcDescTextField;
+       private DoubleModel tcMass;
+       private DoubleModel tcInnerDia;
+       private DoubleModel tcOuterDia;
+       private DoubleModel tcLength;
+       private ImageIcon tcImage;
+       private JButton tcImageBtn;
+       
+       private JTextField bhPartNoTextField;
+       private JTextField bhDescTextField;
+       private DoubleModel bhOuterDia;
+       private DoubleModel bhLength;
+       private DoubleModel bhMass;
+       private ImageIcon bhImage;
+       private JButton bhImageBtn;
+       
+       private JTextField crPartNoTextField;
+       private JTextField crDescTextField;
+       private DoubleModel crOuterDia;
+       private DoubleModel crInnerDia;
+       private DoubleModel crThickness;
+       private DoubleModel crMass;
+       private ImageIcon crImage;
+       private JButton crImageBtn;
+       
+       private JTextField ebPartNoTextField;
+       private JTextField ebDescTextField;
+       private DoubleModel ebOuterDia;
+       private DoubleModel ebInnerDia;
+       private DoubleModel ebThickness;
+       private DoubleModel ebMass;
+       private ImageIcon ebImage;
+       private JButton ebImageBtn;
+       
+       private JTextField llPartNoTextField;
+       private JTextField llDescTextField;
+       private DoubleModel llOuterDia;
+       private DoubleModel llInnerDia;
+       private DoubleModel llLength;
+       private DoubleModel llMass;
+       private ImageIcon llImage;
+       private JButton llImageBtn;
+       
+       private JTextField stPartNoTextField;
+       private JTextField stDescTextField;
+       private DoubleModel stThickness;
+       private DoubleModel stWidth;
+       private DoubleModel stLength;
+       private DoubleModel stMass;
+       private ImageIcon stImage;
+       private JButton stImageBtn;
+       
+       private JTextField pcPartNoTextField;
+       private JTextField pcDescTextField;
+       private JTextField pcSides;
+       private JTextField pcLineCount;
+       private DoubleModel pcDiameter;
+       private DoubleModel pcLineLength;
+       private MaterialChooser pcLineMaterialChooser;
+       private DoubleModel pcMass;
+       private ImageIcon pcImage;
+       private JButton pcImageBtn;
+       
+       private final JFileChooser imageChooser = createImageChooser();
+       
+       private JPanel componentOverlayPanel;
+       
+       private PresetResultListener resultListener;
+       
+       private static Map<String, String> componentMap = new HashMap<String, String>();
+       
+       private static final String NOSE_CONE_KEY = "NoseCone.NoseCone";
+       private static final String BODY_TUBE_KEY = "BodyTube.BodyTube";
+       private static final String TUBE_COUPLER_KEY = "TubeCoupler.TubeCoupler";
+       private static final String TRANSITION_KEY = "Transition.Transition";
+       private static final String CR_KEY = "ComponentIcons.Centeringring";
+       private static final String BULKHEAD_KEY = "Bulkhead.Bulkhead";
+       private static final String EB_KEY = "ComponentIcons.Engineblock";
+       private static final String LAUNCH_LUG_KEY = "ComponentIcons.Launchlug";
+       private static final String STREAMER_KEY = "ComponentIcons.Streamer";
+       private static final String PARACHUTE_KEY = "ComponentIcons.Parachute";
+       
+       
+       static {
+               componentMap.put(trans.get(NOSE_CONE_KEY), "NOSECONE");
+               componentMap.put(trans.get(BODY_TUBE_KEY), "BODYTUBE");
+               componentMap.put(trans.get(TUBE_COUPLER_KEY), "TUBECOUPLER");
+               componentMap.put(trans.get(TRANSITION_KEY), "TRANSITION");
+               componentMap.put(trans.get(CR_KEY), "CENTERINGRING");
+               componentMap.put(trans.get(BULKHEAD_KEY), "BULKHEAD");
+               componentMap.put(trans.get(EB_KEY), "ENGINEBLOCK");
+               componentMap.put(trans.get(LAUNCH_LUG_KEY), "LAUNCHLUG");
+               componentMap.put(trans.get(PARACHUTE_KEY), "PARACHUTE");
+               componentMap.put(trans.get(STREAMER_KEY), "STREAMER");
+       }
+       
+       /**
+        * Create the dialog.
+        *
+        * @param theCallback the listener that gets the results of editing the presets
+        */
+       public PresetEditorDialog(PresetResultListener theCallback) {
+               this(theCallback, null, null);
+       }
+       
+       /**
+        * Create the dialog.
+        *
+        * @param theCallback the listener that gets the results of editing the presets
+        * @param toEdit      the ComponentPreset to be edited; or null if a new one is being added
+        * @param matHolder   the set of materials; if null then use system materials
+        */
+       public PresetEditorDialog(PresetResultListener theCallback, ComponentPreset toEdit, MaterialHolder matHolder) {
+               resultListener = theCallback;
+               getContentPane().setMinimumSize(new Dimension(200, 200));
+               setBounds(100, 100, 825, 610);
+               getContentPane().setLayout(new BorderLayout());
+               contentPanel.setBorder(new EmptyBorder(5, 5, 5, 5));
+               getContentPane().add(contentPanel, BorderLayout.CENTER);
+               contentPanel.setLayout(new MigLayout("", "[][grow][94.00,grow][232.0,grow][130.00][grow]", "[][][20.00,grow][grow]"));
+               JLabel lblManufacturer = new JLabel("Manufacturer:");
+               contentPanel.add(lblManufacturer, "cell 2 0,alignx left,aligny center");
+               
+               mfgTextField = new JTextField();
+               contentPanel.add(mfgTextField, "cell 3 0,growx");
+               mfgTextField.setColumns(10);
+               
+               JLabel typeLabel = new JLabel("Type:");
+               contentPanel.add(typeLabel, "cell 2 1,alignx left,aligny center");
+               
+               componentOverlayPanel = new JPanel();
+               contentPanel.add(componentOverlayPanel, "cell 1 3 5 2,grow");
+               componentOverlayPanel.setLayout(new CardLayout(0, 0));
+               
+               typeCombo = new DeselectableComboBox();
+               typeCombo.addItemListener(this);
+               typeCombo.setModel(new DefaultComboBoxModel());
+               setItems(typeCombo, toEdit);
+               contentPanel.add(typeCombo, "cell 3 1,growx");
+               
+               JLabel bhMaterialLabel = new JLabel("Material:");
+               contentPanel.add(bhMaterialLabel, "cell 2 2, alignx left");
+               
+               materialChooser = new MaterialChooser(new MaterialModel(this, Material.Type.BULK));
+               
+               contentPanel.add(materialChooser, "cell 3 2,growx");
+               
+               {
+                       JPanel ncPanel = new JPanel();
+                       componentOverlayPanel.add(ncPanel, "NOSECONE");
+                       ncPanel.setLayout(new MigLayout("", "[61px][159.00,grow][45.00][109.00,grow][189.00,grow][grow]", "[16px][][][][][]"));
+                       JLabel ncPartNoLabel = new JLabel("Part No:");
+                       ncPanel.add(ncPartNoLabel, "cell 0 0,alignx left,aligny center");
+                       
+                       ncPartNoTextField = new JTextField();
+                       ncPanel.add(ncPartNoTextField, "cell 1 0,growx");
+                       ncPartNoTextField.setColumns(10);
+                       
+                       JLabel ncDescLabel = new JLabel("Description:");
+                       ncPanel.add(ncDescLabel, "cell 3 0,alignx left,aligny center");
+                       
+                       ncDescTextField = new JTextField();
+                       ncPanel.add(ncDescTextField, "cell 4 0,growx");
+                       ncDescTextField.setColumns(10);
+                       
+                       ncFilledCB = new JCheckBox("Filled");
+                       ncPanel.add(ncFilledCB, "cell 1 1");
+                       
+                       JLabel ncMaterialLabel = new JLabel(trans.get("RocketCompCfg.lbl.Componentmaterial"));
+                       ncPanel.add(ncMaterialLabel, "cell 0 1,alignx left");
+                       
+                       JLabel ncMassLabel = new JLabel(trans.get("RocketCompCfg.lbl.Componentmass"));
+                       ncPanel.add(ncMassLabel, "cell 3 1,alignx left");
+                       
+                       ncMass = new DoubleModel(0, UnitGroup.UNITS_MASS, 0);
+                       JSpinner spin = new JSpinner(ncMass.getSpinnerModel());
+                       spin.setEditor(new SpinnerEditor(spin));
+                       ncPanel.add(spin, "cell 4 1, growx");
+                       ncPanel.add(new UnitSelector(ncMass), "growx");
+                       
+                       JLabel ncShapeLabel = new JLabel(trans.get("NoseConeCfg.lbl.Noseconeshape"));
+                       ncPanel.add(ncShapeLabel, "cell 0 2,alignx left");
+                       
+                       ncShapeCB = new JComboBox();
+                       ncShapeCB.setModel(new DefaultComboBoxModel(new String[] { Transition.Shape.OGIVE.getName(), Transition.Shape.CONICAL.getName(), Transition.Shape.PARABOLIC.getName(),
+                                       Transition.Shape.ELLIPSOID.getName(), Transition.Shape.HAACK.getName() }));
+                       ncPanel.add(ncShapeCB, "cell 1 2,growx");
+                       
+                       JLabel ncLengthLabel = new JLabel(trans.get("NoseConeCfg.lbl.Noseconelength"));
+                       ncPanel.add(ncLengthLabel, "cell 3 2,alignx left");
+                       
+                       ncLength = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0, 2);
+                       spin = new JSpinner(ncLength.getSpinnerModel());
+                       spin.setEditor(new SpinnerEditor(spin));
+                       ncPanel.add(spin, "cell 4 2, growx");
+                       ncPanel.add(new UnitSelector(ncLength), "growx");
+                       
+                       JLabel ncAftDiaLabel = new JLabel("Aft Dia.:");
+                       ncPanel.add(ncAftDiaLabel, "cell 0 3,alignx left");
+                       
+                       ncAftDia = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0, 2);
+                       spin = new JSpinner(ncAftDia.getSpinnerModel());
+                       spin.setEditor(new SpinnerEditor(spin));
+                       ncPanel.add(spin, "cell 1 3, growx");
+                       ncPanel.add(new UnitSelector(ncAftDia), "growx");
+                       
+                       JLabel ncAftShoulderLenLabel = new JLabel("Aft Shoulder Len:");
+                       ncPanel.add(ncAftShoulderLenLabel, "cell 0 4,alignx left");
+                       
+                       ncAftShoulderLen = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0, 2);
+                       spin = new JSpinner(ncAftShoulderLen.getSpinnerModel());
+                       spin.setEditor(new SpinnerEditor(spin));
+                       ncPanel.add(spin, "cell 1 4, growx");
+                       ncPanel.add(new UnitSelector(ncAftShoulderLen), "growx");
+                       
+                       JLabel ncAftShoulderDiaLabel = new JLabel("Aft Shoulder Dia.:");
+                       ncPanel.add(ncAftShoulderDiaLabel, "cell 0 5,alignx left, aligny top, pad 7 0 0 0");
+                       
+                       ncAftShoulderDia = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0, 2);
+                       spin = new JSpinner(ncAftShoulderDia.getSpinnerModel());
+                       spin.setEditor(new SpinnerEditor(spin));
+                       ncPanel.add(spin, "cell 1 5, growx, aligny top");
+                       ncPanel.add(new UnitSelector(ncAftShoulderDia), "growx, aligny top, pad 7 0 0 0");
+                       
+                       JPanel panel = new JPanel();
+                       panel.setMinimumSize(new Dimension(200, 200));
+                       ncPanel.add(panel, "cell 4 3, span 1 3");
+                       panel.setLayout(null);
+                       ncImageBtn = new JButton("No Image");
+                       ncImageBtn.setMaximumSize(new Dimension(75, 75));
+                       ncImageBtn.setMinimumSize(new Dimension(75, 75));
+                       panel.add(ncImageBtn);
+                       ncImageBtn.setBounds(new Rectangle(6, 6, 132, 145));
+                       
+                       ncImageBtn.addActionListener(new ActionListener() {
+                               @Override
+                               public void actionPerformed(final ActionEvent e) {
+                                       int returnVal = imageChooser.showOpenDialog(PresetEditorDialog.this);
+                                       
+                                       if (returnVal == JFileChooser.APPROVE_OPTION) {
+                                               File file = imageChooser.getSelectedFile();
+                                               ncImage = scaleImage(new ImageIcon(file.getAbsolutePath()).getImage(), 155);
+                                               ncImageBtn.setIcon(ncImage);
+                                       }
+                               }
+                       });
+                       
+               }
+               {
+                       JPanel trPanel = new JPanel();
+                       componentOverlayPanel.add(trPanel, "TRANSITION");
+                       trPanel.setLayout(new MigLayout("", "[61px][159.00,grow][45.00][109.00,grow][189.00,grow][grow]", "[16px][][][][][]"));
+                       
+                       JLabel trPartNoLabel = new JLabel("Part No:");
+                       trPanel.add(trPartNoLabel, "cell 0 0,alignx left");
+                       
+                       trPartNoTextField = new JTextField();
+                       trPanel.add(trPartNoTextField, "cell 1 0,growx");
+                       trPartNoTextField.setColumns(10);
+                       
+                       JLabel trDescLabel = new JLabel("Description:");
+                       trPanel.add(trDescLabel, "cell 3 0,alignx left");
+                       
+                       trDescTextField = new JTextField();
+                       trPanel.add(trDescTextField, "cell 4 0,growx");
+                       trDescTextField.setColumns(10);
+                       
+                       trFilledCB = new JCheckBox("Filled");
+                       trPanel.add(trFilledCB, "cell 1 1");
+                       
+                       JLabel trMassLabel = new JLabel("Mass:");
+                       trPanel.add(trMassLabel, "cell 3 1,alignx left");
+                       
+                       trMass = new DoubleModel(0, UnitGroup.UNITS_MASS, 0);
+                       JSpinner spin = new JSpinner(trMass.getSpinnerModel());
+                       spin.setEditor(new SpinnerEditor(spin));
+                       trPanel.add(spin, "cell 4 1, growx");
+                       trPanel.add(new UnitSelector(trMass), "growx");
+                       
+                       JLabel trShapeLabel = new JLabel("Shape:");
+                       trPanel.add(trShapeLabel, "cell 0 2,alignx left");
+                       
+                       trShapeCB = new JComboBox();
+                       trShapeCB.setModel(new DefaultComboBoxModel(new String[] { Transition.Shape.OGIVE.getName(), Transition.Shape.CONICAL.getName(), Transition.Shape.PARABOLIC.getName(),
+                                       Transition.Shape.ELLIPSOID.getName(), Transition.Shape.HAACK.getName() }));
+                       trPanel.add(trShapeCB, "cell 1 2,growx");
+                       
+                       JLabel trLengthLabel = new JLabel("Length:");
+                       trPanel.add(trLengthLabel, "cell 3 2,alignx left");
+                       
+                       trLength = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0, 2);
+                       spin = new JSpinner(trLength.getSpinnerModel());
+                       spin.setEditor(new SpinnerEditor(spin));
+                       trPanel.add(spin, "cell 4 2, growx");
+                       trPanel.add(new UnitSelector(trLength), "growx");
+                       
+                       JLabel trAftDiaLabel = new JLabel("Aft Dia.:");
+                       trPanel.add(trAftDiaLabel, "cell 0 3,alignx left");
+                       
+                       trAftDia = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0, 2);
+                       spin = new JSpinner(trAftDia.getSpinnerModel());
+                       spin.setEditor(new SpinnerEditor(spin));
+                       trPanel.add(spin, "cell 1 3, growx");
+                       trPanel.add(new UnitSelector(trAftDia), "growx");
+                       
+                       JLabel trForeDiaLabel = new JLabel("Fore Dia.:");
+                       trPanel.add(trForeDiaLabel, "cell 3 3,alignx left");
+                       
+                       trForeDia = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0, 2);
+                       spin = new JSpinner(trForeDia.getSpinnerModel());
+                       spin.setEditor(new SpinnerEditor(spin));
+                       trPanel.add(spin, "cell 4 3, growx");
+                       trPanel.add(new UnitSelector(trForeDia), "growx");
+                       
+                       JLabel trAftShouldDiaLabel = new JLabel("Aft Shoulder Dia.:");
+                       trPanel.add(trAftShouldDiaLabel, "cell 0 4,alignx left");
+                       
+                       trAftShoulderDia = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0, 2);
+                       spin = new JSpinner(trAftShoulderDia.getSpinnerModel());
+                       spin.setEditor(new SpinnerEditor(spin));
+                       trPanel.add(spin, "cell 1 4, growx");
+                       trPanel.add(new UnitSelector(trAftShoulderDia), "growx");
+                       
+                       JLabel trForeShouldDiaLabel = new JLabel("Fore Shoulder Dia.:");
+                       trPanel.add(trForeShouldDiaLabel, "cell 3 4,alignx left");
+                       
+                       trForeShoulderDia = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0, 2);
+                       spin = new JSpinner(trForeShoulderDia.getSpinnerModel());
+                       spin.setEditor(new SpinnerEditor(spin));
+                       trPanel.add(spin, "cell 4 4, growx");
+                       trPanel.add(new UnitSelector(trForeShoulderDia), "growx");
+                       
+                       JLabel trAftShoulderLenLabel = new JLabel("Aft Shoulder Len.:");
+                       trPanel.add(trAftShoulderLenLabel, "cell 0 5,alignx left");
+                       
+                       trAftShoulderLen = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0, 2);
+                       spin = new JSpinner(trAftShoulderLen.getSpinnerModel());
+                       spin.setEditor(new SpinnerEditor(spin));
+                       trPanel.add(spin, "cell 1 5, growx");
+                       trPanel.add(new UnitSelector(trAftShoulderLen), "growx");
+                       
+                       JLabel lblForeShoulderLen = new JLabel("Fore Shoulder Len.:");
+                       trPanel.add(lblForeShoulderLen, "cell 3 5,alignx left");
+                       
+                       trForeShoulderLen = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0, 2);
+                       spin = new JSpinner(trForeShoulderLen.getSpinnerModel());
+                       spin.setEditor(new SpinnerEditor(spin));
+                       trPanel.add(spin, "cell 4 5, growx");
+                       trPanel.add(new UnitSelector(trForeShoulderLen), "growx");
+                       
+                       JPanel panel = new JPanel();
+                       panel.setMinimumSize(new Dimension(200, 200));
+                       trPanel.add(panel, "cell 4 6");
+                       panel.setLayout(null);
+                       trImageBtn = new JButton("No Image");
+                       trImageBtn.setMaximumSize(new Dimension(75, 75));
+                       trImageBtn.setMinimumSize(new Dimension(75, 75));
+                       panel.add(trImageBtn);
+                       trImageBtn.setBounds(new Rectangle(6, 6, 132, 145));
+                       
+                       trImageBtn.addActionListener(new ActionListener() {
+                               @Override
+                               public void actionPerformed(final ActionEvent e) {
+                                       int returnVal = imageChooser.showOpenDialog(PresetEditorDialog.this);
+                                       
+                                       if (returnVal == JFileChooser.APPROVE_OPTION) {
+                                               File file = imageChooser.getSelectedFile();
+                                               trImage = scaleImage(new ImageIcon(file.getAbsolutePath()).getImage(), 155);
+                                               trImageBtn.setIcon(trImage);
+                                       }
+                               }
+                       });
+                       
+               }
+               {
+                       JPanel btPanel = new JPanel();
+                       componentOverlayPanel.add(btPanel, "BODYTUBE");
+                       btPanel.setLayout(new MigLayout("", "[][grow][][grow]", "[][][][]"));
+                       JLabel btPartNoLabel = new JLabel("Part No:");
+                       btPanel.add(btPartNoLabel, "cell 0 0,alignx left");
+                       
+                       btPartNoTextField = new JTextField();
+                       btPanel.add(btPartNoTextField, "cell 1 0,growx");
+                       btPartNoTextField.setColumns(10);
+                       
+                       JLabel btDescLabel = new JLabel("Description:");
+                       btPanel.add(btDescLabel, "cell 3 0,alignx left");
+                       
+                       btDescTextField = new JTextField();
+                       btPanel.add(btDescTextField, "cell 4 0,growx");
+                       btDescTextField.setColumns(10);
+                       
+                       JLabel btLengthLabel = new JLabel("Length:");
+                       btPanel.add(btLengthLabel, "cell 0 1,alignx left");
+                       
+                       btLength = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0);
+                       JSpinner spin = new JSpinner(btLength.getSpinnerModel());
+                       spin.setEditor(new SpinnerEditor(spin));
+                       btPanel.add(spin, "cell 1 1, growx");
+                       btPanel.add(new UnitSelector(btLength), "growx");
+                       
+                       JLabel btMassLabel = new JLabel("Mass:");
+                       btPanel.add(btMassLabel, "cell 3 1,alignx left");
+                       
+                       btMass = new DoubleModel(0, UnitGroup.UNITS_MASS, 0);
+                       spin = new JSpinner(btMass.getSpinnerModel());
+                       spin.setEditor(new SpinnerEditor(spin));
+                       btPanel.add(spin, "cell 4 1, growx");
+                       btPanel.add(new UnitSelector(btMass), "w 34lp!");
+                       
+                       JLabel btInnerDiaLabel = new JLabel("Inner Dia.:");
+                       btPanel.add(btInnerDiaLabel, "cell 0 2,alignx left");
+                       
+                       btInnerDia = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0);
+                       spin = new JSpinner(btInnerDia.getSpinnerModel());
+                       spin.setEditor(new SpinnerEditor(spin));
+                       btPanel.add(spin, "cell 1 2, growx");
+                       btPanel.add(new UnitSelector(btInnerDia), "growx");
+                       
+                       JLabel btOuterDiaLabel = new JLabel("Outer Dia.:");
+                       btPanel.add(btOuterDiaLabel, "cell 3 2,alignx left");
+                       
+                       btOuterDia = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0);
+                       spin = new JSpinner(btOuterDia.getSpinnerModel());
+                       spin.setEditor(new SpinnerEditor(spin));
+                       btPanel.add(spin, "cell 4 2, growx");
+                       btPanel.add(new UnitSelector(btOuterDia), "w 34lp!");
+                       
+                       JPanel panel = new JPanel();
+                       panel.setMinimumSize(new Dimension(200, 200));
+                       btPanel.add(panel, "cell 4 3");
+                       panel.setLayout(null);
+                       btImageBtn = new JButton("No Image");
+                       btImageBtn.setMaximumSize(new Dimension(75, 75));
+                       btImageBtn.setMinimumSize(new Dimension(75, 75));
+                       panel.add(btImageBtn);
+                       btImageBtn.setBounds(new Rectangle(6, 6, 132, 145));
+                       
+                       btImageBtn.addActionListener(new ActionListener() {
+                               @Override
+                               public void actionPerformed(final ActionEvent e) {
+                                       int returnVal = imageChooser.showOpenDialog(PresetEditorDialog.this);
+                                       
+                                       if (returnVal == JFileChooser.APPROVE_OPTION) {
+                                               File file = imageChooser.getSelectedFile();
+                                               btImage = scaleImage(new ImageIcon(file.getAbsolutePath()).getImage(), 155);
+                                               btImageBtn.setIcon(btImage);
+                                       }
+                               }
+                       });
+                       
+               }
+               {
+                       JPanel tcPanel = new JPanel();
+                       componentOverlayPanel.add(tcPanel, "TUBECOUPLER");
+                       tcPanel.setLayout(new MigLayout("", "[][grow][][grow]", "[][][][]"));
+                       JLabel tcPartNoLabel = new JLabel("Part No:");
+                       tcPanel.add(tcPartNoLabel, "cell 0 0,alignx left");
+                       
+                       tcPartNoTextField = new JTextField();
+                       tcPanel.add(tcPartNoTextField, "cell 1 0,growx");
+                       tcPartNoTextField.setColumns(10);
+                       
+                       JLabel tcDescLabel = new JLabel("Description:");
+                       tcPanel.add(tcDescLabel, "cell 3 0,alignx left");
+                       
+                       tcDescTextField = new JTextField();
+                       tcPanel.add(tcDescTextField, "cell 4 0,growx");
+                       tcDescTextField.setColumns(10);
+                       
+                       JLabel tcLengthLabel = new JLabel("Length:");
+                       tcPanel.add(tcLengthLabel, "cell 0 1,alignx left");
+                       
+                       tcLength = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0);
+                       JSpinner spin = new JSpinner(tcLength.getSpinnerModel());
+                       spin.setEditor(new SpinnerEditor(spin));
+                       tcPanel.add(spin, "cell 1 1, growx");
+                       tcPanel.add(new UnitSelector(tcLength), "growx");
+                       
+                       JLabel tcMassLabel = new JLabel("Mass:");
+                       tcPanel.add(tcMassLabel, "cell 3 1,alignx left");
+                       
+                       tcMass = new DoubleModel(0, UnitGroup.UNITS_MASS, 0);
+                       spin = new JSpinner(tcMass.getSpinnerModel());
+                       spin.setEditor(new SpinnerEditor(spin));
+                       tcPanel.add(spin, "cell 4 1, growx");
+                       tcPanel.add(new UnitSelector(tcMass), "w 34lp!");
+                       
+                       JLabel tcInnerDiaLabel = new JLabel("Inner Dia.:");
+                       tcPanel.add(tcInnerDiaLabel, "cell 0 2,alignx left");
+                       
+                       tcInnerDia = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0);
+                       spin = new JSpinner(tcInnerDia.getSpinnerModel());
+                       spin.setEditor(new SpinnerEditor(spin));
+                       tcPanel.add(spin, "cell 1 2, growx");
+                       tcPanel.add(new UnitSelector(tcInnerDia), "growx");
+                       
+                       JLabel tcOuterDiaLabel = new JLabel("Outer Dia.:");
+                       tcPanel.add(tcOuterDiaLabel, "cell 3 2,alignx left");
+                       
+                       tcOuterDia = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0);
+                       spin = new JSpinner(tcOuterDia.getSpinnerModel());
+                       spin.setEditor(new SpinnerEditor(spin));
+                       tcPanel.add(spin, "cell 4 2, growx");
+                       tcPanel.add(new UnitSelector(tcOuterDia), "w 34lp!");
+                       
+                       JPanel panel = new JPanel();
+                       panel.setMinimumSize(new Dimension(200, 200));
+                       tcPanel.add(panel, "cell 4 3");
+                       panel.setLayout(null);
+                       tcImageBtn = new JButton("No Image");
+                       tcImageBtn.setMaximumSize(new Dimension(75, 75));
+                       tcImageBtn.setMinimumSize(new Dimension(75, 75));
+                       panel.add(tcImageBtn);
+                       tcImageBtn.setBounds(new Rectangle(6, 6, 132, 145));
+                       
+                       tcImageBtn.addActionListener(new ActionListener() {
+                               @Override
+                               public void actionPerformed(final ActionEvent e) {
+                                       int returnVal = imageChooser.showOpenDialog(PresetEditorDialog.this);
+                                       
+                                       if (returnVal == JFileChooser.APPROVE_OPTION) {
+                                               File file = imageChooser.getSelectedFile();
+                                               tcImage = scaleImage(new ImageIcon(file.getAbsolutePath()).getImage(), 155);
+                                               tcImageBtn.setIcon(tcImage);
+                                       }
+                               }
+                       });
+                       
+                       
+               }
+               {
+                       JPanel bhPanel = new JPanel();
+                       componentOverlayPanel.add(bhPanel, "BULKHEAD");
+                       bhPanel.setLayout(new MigLayout("", "[][157.00,grow 79][65.00][grow]", "[][][][]"));
+                       
+                       JLabel bhPartNoLabel = new JLabel("Part No:");
+                       bhPanel.add(bhPartNoLabel, "cell 0 0,alignx left");
+                       
+                       bhPartNoTextField = new JTextField();
+                       bhPanel.add(bhPartNoTextField, "cell 1 0,growx");
+                       bhPartNoTextField.setColumns(10);
+                       
+                       JLabel bhDescLabel = new JLabel("Description:");
+                       bhPanel.add(bhDescLabel, "cell 3 0,alignx left");
+                       
+                       bhDescTextField = new JTextField();
+                       bhPanel.add(bhDescTextField, "cell 4 0,growx");
+                       bhDescTextField.setColumns(10);
+                       
+                       JLabel bhLengthLabel = new JLabel("Thickness:");
+                       bhPanel.add(bhLengthLabel, "cell 0 1,alignx left");
+                       
+                       bhLength = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0);
+                       JSpinner spin = new JSpinner(bhLength.getSpinnerModel());
+                       spin.setEditor(new SpinnerEditor(spin));
+                       bhPanel.add(spin, "cell 1 1, growx");
+                       bhPanel.add(new UnitSelector(bhLength), "w 34lp!");
+                       
+                       JLabel bhMassLabel = new JLabel("Mass:");
+                       bhPanel.add(bhMassLabel, "cell 3 1,alignx left");
+                       
+                       bhMass = new DoubleModel(0, UnitGroup.UNITS_MASS, 0);
+                       spin = new JSpinner(bhMass.getSpinnerModel());
+                       spin.setEditor(new SpinnerEditor(spin));
+                       bhPanel.add(spin, "cell 4 1, growx");
+                       bhPanel.add(new UnitSelector(bhMass), "growx");
+                       
+                       JLabel bhOuterDiaLabel = new JLabel("Outer Dia.:");
+                       bhPanel.add(bhOuterDiaLabel, "cell 0 2,alignx left, aligny top, pad 7 0 0 0");
+                       
+                       bhOuterDia = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0);
+                       spin = new JSpinner(bhOuterDia.getSpinnerModel());
+                       spin.setEditor(new SpinnerEditor(spin));
+                       bhPanel.add(spin, "cell 1 2, growx, aligny top");
+                       bhPanel.add(new UnitSelector(bhOuterDia), "w 34lp!, h 27lp!, aligny top, pad 7 0 0 0");
+                       
+                       JPanel panel = new JPanel();
+                       panel.setMinimumSize(new Dimension(200, 200));
+                       bhPanel.add(panel, "cell 4 2");
+                       panel.setLayout(null);
+                       bhImageBtn = new JButton("No Image");
+                       bhImageBtn.setMaximumSize(new Dimension(75, 75));
+                       bhImageBtn.setMinimumSize(new Dimension(75, 75));
+                       panel.add(bhImageBtn);
+                       bhImageBtn.setBounds(new Rectangle(6, 6, 132, 145));
+                       
+                       bhImageBtn.addActionListener(new ActionListener() {
+                               @Override
+                               public void actionPerformed(final ActionEvent e) {
+                                       int returnVal = imageChooser.showOpenDialog(PresetEditorDialog.this);
+                                       
+                                       if (returnVal == JFileChooser.APPROVE_OPTION) {
+                                               File file = imageChooser.getSelectedFile();
+                                               bhImage = scaleImage(new ImageIcon(file.getAbsolutePath()).getImage(), 155);
+                                               bhImageBtn.setIcon(bhImage);
+                                       }
+                               }
+                       });
+                       
+               }
+               {
+                       JPanel crPanel = new JPanel();
+                       componentOverlayPanel.add(crPanel, "CENTERINGRING");
+                       crPanel.setLayout(new MigLayout("", "[][grow][][grow]", "[][][][]"));
+                       
+                       JLabel crPartNoLabel = new JLabel("Part No:");
+                       crPanel.add(crPartNoLabel, "cell 0 0,alignx left");
+                       
+                       crPartNoTextField = new JTextField();
+                       crPanel.add(crPartNoTextField, "cell 1 0, growx");
+                       crPartNoTextField.setColumns(10);
+                       
+                       JLabel crDescLabel = new JLabel("Description:");
+                       crPanel.add(crDescLabel, "cell 3 0,alignx left");
+                       
+                       crDescTextField = new JTextField();
+                       crPanel.add(crDescTextField, "cell 4 0, growx");
+                       crDescTextField.setColumns(10);
+                       
+                       JLabel crThicknessLabel = new JLabel("Thickness:");
+                       crPanel.add(crThicknessLabel, "cell 0 1,alignx left");
+                       
+                       crThickness = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0);
+                       JSpinner spin = new JSpinner(crThickness.getSpinnerModel());
+                       spin.setEditor(new SpinnerEditor(spin));
+                       crPanel.add(spin, "cell 1 1, growx");
+                       crPanel.add(new UnitSelector(crThickness), "growx");
+                       
+                       JLabel crMassLabel = new JLabel("Mass:");
+                       crPanel.add(crMassLabel, "cell 3 1,alignx left");
+                       
+                       crMass = new DoubleModel(0, UnitGroup.UNITS_MASS, 0);
+                       spin = new JSpinner(crMass.getSpinnerModel());
+                       spin.setEditor(new SpinnerEditor(spin));
+                       crPanel.add(spin, "cell 4 1, growx");
+                       crPanel.add(new UnitSelector(crMass), "w 34lp!");
+                       
+                       JLabel crOuterDiaLabel = new JLabel("Outer Dia.:");
+                       crPanel.add(crOuterDiaLabel, "cell 0 2,alignx left");
+                       
+                       crOuterDia = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0);
+                       spin = new JSpinner(crOuterDia.getSpinnerModel());
+                       spin.setEditor(new SpinnerEditor(spin));
+                       crPanel.add(spin, "cell 1 2, growx");
+                       crPanel.add(new UnitSelector(crOuterDia), "w 34lp!");
+                       
+                       JLabel crInnerDiaLabel = new JLabel("Inner Dia.:");
+                       crPanel.add(crInnerDiaLabel, "cell 3 2,alignx left");
+                       
+                       crInnerDia = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0);
+                       spin = new JSpinner(crInnerDia.getSpinnerModel());
+                       spin.setEditor(new SpinnerEditor(spin));
+                       crPanel.add(spin, "cell 4 2, growx");
+                       crPanel.add(new UnitSelector(crInnerDia), "w 34lp!");
+                       
+                       JPanel panel = new JPanel();
+                       panel.setMinimumSize(new Dimension(200, 200));
+                       crPanel.add(panel, "cell 4 3");
+                       panel.setLayout(null);
+                       crImageBtn = new JButton("No Image");
+                       crImageBtn.setMaximumSize(new Dimension(75, 75));
+                       crImageBtn.setMinimumSize(new Dimension(75, 75));
+                       panel.add(crImageBtn);
+                       crImageBtn.setBounds(new Rectangle(6, 6, 132, 145));
+                       
+                       crImageBtn.addActionListener(new ActionListener() {
+                               @Override
+                               public void actionPerformed(final ActionEvent e) {
+                                       int returnVal = imageChooser.showOpenDialog(PresetEditorDialog.this);
+                                       
+                                       if (returnVal == JFileChooser.APPROVE_OPTION) {
+                                               File file = imageChooser.getSelectedFile();
+                                               crImage = scaleImage(new ImageIcon(file.getAbsolutePath()).getImage(), 155);
+                                               crImageBtn.setIcon(crImage);
+                                       }
+                               }
+                       });
+                       
+               }
+               {
+                       JPanel ebPanel = new JPanel();
+                       componentOverlayPanel.add(ebPanel, "ENGINEBLOCK");
+                       ebPanel.setLayout(new MigLayout("", "[][grow][][grow]", "[][][][]"));
+                       JLabel ebPartNoLabel = new JLabel("Part No:");
+                       ebPanel.add(ebPartNoLabel, "cell 0 0,alignx left");
+                       
+                       ebPartNoTextField = new JTextField();
+                       ebPanel.add(ebPartNoTextField, "cell 1 0,growx");
+                       ebPartNoTextField.setColumns(10);
+                       
+                       JLabel ebDescLabel = new JLabel("Description:");
+                       ebPanel.add(ebDescLabel, "cell 3 0,alignx left");
+                       
+                       ebDescTextField = new JTextField();
+                       ebPanel.add(ebDescTextField, "cell 4 0,growx");
+                       ebDescTextField.setColumns(10);
+                       
+                       JLabel ebThicknessLabel = new JLabel("Thickness:");
+                       ebPanel.add(ebThicknessLabel, "cell 0 1,alignx left");
+                       
+                       ebThickness = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0);
+                       JSpinner spin = new JSpinner(ebThickness.getSpinnerModel());
+                       spin.setEditor(new SpinnerEditor(spin));
+                       ebPanel.add(spin, "cell 1 1, growx");
+                       ebPanel.add(new UnitSelector(ebThickness), "growx");
+                       
+                       JLabel ebMassLabel = new JLabel("Mass:");
+                       ebPanel.add(ebMassLabel, "cell 3 1,alignx left");
+                       
+                       ebMass = new DoubleModel(0, UnitGroup.UNITS_MASS, 0);
+                       spin = new JSpinner(ebMass.getSpinnerModel());
+                       spin.setEditor(new SpinnerEditor(spin));
+                       ebPanel.add(spin, "cell 4 1, growx");
+                       ebPanel.add(new UnitSelector(ebMass), "w 34lp!");
+                       
+                       JLabel ebOuterDiaLabel = new JLabel("Outer Dia.:");
+                       ebPanel.add(ebOuterDiaLabel, "cell 0 2,alignx left");
+                       
+                       ebOuterDia = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0);
+                       spin = new JSpinner(ebOuterDia.getSpinnerModel());
+                       spin.setEditor(new SpinnerEditor(spin));
+                       ebPanel.add(spin, "cell 1 2, growx");
+                       ebPanel.add(new UnitSelector(ebOuterDia), "growx");
+                       
+                       JLabel ebInnerDiaLabel = new JLabel("Inner Dia.:");
+                       ebPanel.add(ebInnerDiaLabel, "cell 3 2,alignx left");
+                       
+                       ebInnerDia = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0);
+                       spin = new JSpinner(ebInnerDia.getSpinnerModel());
+                       spin.setEditor(new SpinnerEditor(spin));
+                       ebPanel.add(spin, "cell 4 2, growx");
+                       ebPanel.add(new UnitSelector(ebInnerDia), "w 34lp!");
+                       
+                       JPanel panel = new JPanel();
+                       panel.setMinimumSize(new Dimension(200, 200));
+                       ebPanel.add(panel, "cell 4 3");
+                       panel.setLayout(null);
+                       ebImageBtn = new JButton("No Image");
+                       ebImageBtn.setMaximumSize(new Dimension(75, 75));
+                       ebImageBtn.setMinimumSize(new Dimension(75, 75));
+                       panel.add(ebImageBtn);
+                       ebImageBtn.setBounds(new Rectangle(6, 6, 132, 145));
+                       
+                       ebImageBtn.addActionListener(new ActionListener() {
+                               @Override
+                               public void actionPerformed(final ActionEvent e) {
+                                       int returnVal = imageChooser.showOpenDialog(PresetEditorDialog.this);
+                                       
+                                       if (returnVal == JFileChooser.APPROVE_OPTION) {
+                                               File file = imageChooser.getSelectedFile();
+                                               ebImage = scaleImage(new ImageIcon(file.getAbsolutePath()).getImage(), 155);
+                                               ebImageBtn.setIcon(ebImage);
+                                       }
+                               }
+                       });
+               }
+               
+               {
+                       JPanel llPanel = new JPanel();
+                       componentOverlayPanel.add(llPanel, "LAUNCHLUG");
+                       llPanel.setLayout(new MigLayout("", "[][grow][][grow]", "[][][][]"));
+                       JLabel llPartNoLabel = new JLabel("Part No:");
+                       llPanel.add(llPartNoLabel, "cell 0 0,alignx left");
+                       
+                       llPartNoTextField = new JTextField();
+                       llPanel.add(llPartNoTextField, "cell 1 0,growx");
+                       llPartNoTextField.setColumns(10);
+                       
+                       JLabel llDescLabel = new JLabel("Description:");
+                       llPanel.add(llDescLabel, "cell 3 0,alignx left");
+                       
+                       llDescTextField = new JTextField();
+                       llPanel.add(llDescTextField, "cell 4 0,growx");
+                       llDescTextField.setColumns(10);
+                       
+                       JLabel llLengthLabel = new JLabel("Length:");
+                       llPanel.add(llLengthLabel, "cell 0 1,alignx left");
+                       
+                       llLength = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0);
+                       JSpinner spin = new JSpinner(llLength.getSpinnerModel());
+                       spin.setEditor(new SpinnerEditor(spin));
+                       llPanel.add(spin, "cell 1 1, growx");
+                       llPanel.add(new UnitSelector(llLength), "growx");
+                       
+                       JLabel llMassLabel = new JLabel("Mass:");
+                       llPanel.add(llMassLabel, "cell 3 1,alignx left");
+                       
+                       llMass = new DoubleModel(0, UnitGroup.UNITS_MASS, 0);
+                       spin = new JSpinner(llMass.getSpinnerModel());
+                       spin.setEditor(new SpinnerEditor(spin));
+                       llPanel.add(spin, "cell 4 1, growx");
+                       llPanel.add(new UnitSelector(llMass), "w 34lp!");
+                       
+                       JLabel llOuterDiaLabel = new JLabel("Outer Dia.:");
+                       llPanel.add(llOuterDiaLabel, "cell 0 2,alignx left");
+                       
+                       llOuterDia = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0);
+                       spin = new JSpinner(llOuterDia.getSpinnerModel());
+                       spin.setEditor(new SpinnerEditor(spin));
+                       llPanel.add(spin, "cell 1 2, growx");
+                       llPanel.add(new UnitSelector(llOuterDia), "growx");
+                       
+                       JLabel llInnerDiaLabel = new JLabel("Inner Dia.:");
+                       llPanel.add(llInnerDiaLabel, "cell 3 2,alignx left");
+                       
+                       llInnerDia = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0);
+                       spin = new JSpinner(llInnerDia.getSpinnerModel());
+                       spin.setEditor(new SpinnerEditor(spin));
+                       llPanel.add(spin, "cell 4 2, growx");
+                       llPanel.add(new UnitSelector(llInnerDia), "w 34lp!");
+                       
+                       JPanel panel = new JPanel();
+                       panel.setMinimumSize(new Dimension(200, 200));
+                       llPanel.add(panel, "cell 4 3");
+                       panel.setLayout(null);
+                       llImageBtn = new JButton("No Image");
+                       llImageBtn.setMaximumSize(new Dimension(75, 75));
+                       llImageBtn.setMinimumSize(new Dimension(75, 75));
+                       panel.add(llImageBtn);
+                       llImageBtn.setBounds(new Rectangle(6, 6, 132, 145));
+                       
+                       llImageBtn.addActionListener(new ActionListener() {
+                               @Override
+                               public void actionPerformed(final ActionEvent e) {
+                                       int returnVal = imageChooser.showOpenDialog(PresetEditorDialog.this);
+                                       
+                                       if (returnVal == JFileChooser.APPROVE_OPTION) {
+                                               File file = imageChooser.getSelectedFile();
+                                               llImage = scaleImage(new ImageIcon(file.getAbsolutePath()).getImage(), 155);
+                                               llImageBtn.setIcon(llImage);
+                                       }
+                               }
+                       });
+               }
+               
+               {
+                       JPanel stPanel = new JPanel();
+                       componentOverlayPanel.add(stPanel, "STREAMER");
+                       stPanel.setLayout(new MigLayout("", "[][grow][][grow]", "[][][][]"));
+                       JLabel stPartNoLabel = new JLabel("Part No:");
+                       stPanel.add(stPartNoLabel, "cell 0 0,alignx left");
+                       
+                       stPartNoTextField = new JTextField();
+                       stPanel.add(stPartNoTextField, "cell 1 0,growx");
+                       stPartNoTextField.setColumns(10);
+                       
+                       JLabel stDescLabel = new JLabel("Description:");
+                       stPanel.add(stDescLabel, "cell 3 0,alignx left");
+                       
+                       stDescTextField = new JTextField();
+                       stPanel.add(stDescTextField, "cell 4 0,growx");
+                       stDescTextField.setColumns(10);
+                       
+                       JLabel stLengthLabel = new JLabel("Length:");
+                       stPanel.add(stLengthLabel, "cell 0 1,alignx left");
+                       
+                       stLength = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0);
+                       JSpinner spin = new JSpinner(stLength.getSpinnerModel());
+                       spin.setEditor(new SpinnerEditor(spin));
+                       stPanel.add(spin, "cell 1 1, growx");
+                       stPanel.add(new UnitSelector(stLength), "growx");
+                       
+                       JLabel stMassLabel = new JLabel("Mass:");
+                       stPanel.add(stMassLabel, "cell 3 1,alignx left");
+                       
+                       stMass = new DoubleModel(0, UnitGroup.UNITS_MASS, 0);
+                       spin = new JSpinner(stMass.getSpinnerModel());
+                       spin.setEditor(new SpinnerEditor(spin));
+                       stPanel.add(spin, "cell 4 1, growx");
+                       stPanel.add(new UnitSelector(stMass), "growx");
+                       
+                       JLabel stThicknessLabel = new JLabel("Thickness:");
+                       stPanel.add(stThicknessLabel, "cell 0 2,alignx left");
+                       
+                       stThickness = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0);
+                       spin = new JSpinner(stThickness.getSpinnerModel());
+                       spin.setEditor(new SpinnerEditor(spin));
+                       stPanel.add(spin, "cell 1 2, growx");
+                       stPanel.add(new UnitSelector(stThickness), "growx");
+                       
+                       JLabel stWidthLabel = new JLabel("Width:");
+                       stPanel.add(stWidthLabel, "cell 3 2,alignx left");
+                       
+                       stWidth = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0);
+                       spin = new JSpinner(stWidth.getSpinnerModel());
+                       spin.setEditor(new SpinnerEditor(spin));
+                       stPanel.add(spin, "cell 4 2, growx");
+                       stPanel.add(new UnitSelector(stWidth), "growx");
+                       
+                       JPanel panel = new JPanel();
+                       panel.setMinimumSize(new Dimension(200, 200));
+                       stPanel.add(panel, "cell 4 3");
+                       panel.setLayout(null);
+                       stImageBtn = new JButton("No Image");
+                       stImageBtn.setMaximumSize(new Dimension(75, 75));
+                       stImageBtn.setMinimumSize(new Dimension(75, 75));
+                       panel.add(stImageBtn);
+                       stImageBtn.setBounds(new Rectangle(6, 6, 132, 145));
+                       
+                       stImageBtn.addActionListener(new ActionListener() {
+                               @Override
+                               public void actionPerformed(final ActionEvent e) {
+                                       int returnVal = imageChooser.showOpenDialog(PresetEditorDialog.this);
+                                       
+                                       if (returnVal == JFileChooser.APPROVE_OPTION) {
+                                               File file = imageChooser.getSelectedFile();
+                                               stImage = scaleImage(new ImageIcon(file.getAbsolutePath()).getImage(), 155);
+                                               stImageBtn.setIcon(stImage);
+                                       }
+                               }
+                       });
+               }
+               
+               {
+                       JPanel pcPanel = new JPanel();
+                       componentOverlayPanel.add(pcPanel, "PARACHUTE");
+                       pcPanel.setLayout(new MigLayout("", "[][157.00,grow 79][65.00][grow][][]", "[][][][][][]"));
+                       JLabel pcPartNoLabel = new JLabel("Part No:");
+                       pcPanel.add(pcPartNoLabel, "cell 0 0,alignx left");
+                       
+                       pcPartNoTextField = new JTextField();
+                       pcPanel.add(pcPartNoTextField, "cell 1 0,growx");
+                       pcPartNoTextField.setColumns(10);
+                       
+                       JLabel pcDescLabel = new JLabel("Description:");
+                       pcPanel.add(pcDescLabel, "cell 3 0,alignx left");
+                       
+                       pcDescTextField = new JTextField();
+                       pcPanel.add(pcDescTextField, "cell 4 0,growx");
+                       pcDescTextField.setColumns(10);
+                       
+                       JLabel pcSidesLabel = new JLabel("Sides:");
+                       pcPanel.add(pcSidesLabel, "cell 0 1,alignx left");
+                       
+                       pcSides = new JTextField();
+                       pcPanel.add(pcSides, "cell 1 1, growx");
+                       pcSides.setInputVerifier(NON_NEGATIVE_INTEGER);
+                       pcSides.setColumns(10);
+                       
+                       JLabel pcMassLabel = new JLabel("Mass:");
+                       pcPanel.add(pcMassLabel, "cell 3 1,alignx left");
+                       
+                       pcMass = new DoubleModel(0, UnitGroup.UNITS_MASS, 0);
+                       JSpinner spin = new JSpinner(pcMass.getSpinnerModel());
+                       spin.setEditor(new SpinnerEditor(spin));
+                       pcPanel.add(spin, "cell 4 1, growx");
+                       pcPanel.add(new UnitSelector(pcMass), "growx");
+                       
+                       JLabel pcDiameterLabel = new JLabel("Diameter:");
+                       pcPanel.add(pcDiameterLabel, "cell 0 2,alignx left");
+                       
+                       pcDiameter = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0);
+                       spin = new JSpinner(pcDiameter.getSpinnerModel());
+                       spin.setEditor(new SpinnerEditor(spin));
+                       pcPanel.add(spin, "cell 1 2, growx");
+                       pcPanel.add(new UnitSelector(pcDiameter));
+                       
+                       JLabel pcLineLengthLabel = new JLabel("Line Length:");
+                       pcPanel.add(pcLineLengthLabel, "cell 3 2,alignx left");
+                       
+                       pcLineLength = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0);
+                       spin = new JSpinner(pcLineLength.getSpinnerModel());
+                       spin.setEditor(new SpinnerEditor(spin));
+                       pcPanel.add(spin, "cell 4 2, growx");
+                       pcPanel.add(new UnitSelector(pcLineLength), "growx");
+                       
+                       JLabel pcLineCountLabel = new JLabel("Line Count:");
+                       pcPanel.add(pcLineCountLabel, "cell 3 3,alignx left");
+                       
+                       pcLineCount = new JTextField();
+                       pcLineCount.setInputVerifier(NON_NEGATIVE_INTEGER);
+                       pcPanel.add(pcLineCount, "cell 4 3, growx");
+                       pcLineCount.setColumns(10);
+                       
+                       JLabel pcLineMaterialLabel = new JLabel("Line Material:");
+                       pcPanel.add(pcLineMaterialLabel, "cell 3 4,alignx left, aligny top, pad 7 0 0 0 ");
+                       
+                       pcLineMaterialChooser = new MaterialChooser();
+                       pcLineMaterialChooser.setModel(new MaterialModel(PresetEditorDialog.this, Material.Type.LINE));
+                       pcPanel.add(pcLineMaterialChooser, "cell 4 4, span 3 1, growx, aligny top");
+                       
+                       JPanel panel = new JPanel();
+                       panel.setMinimumSize(new Dimension(200, 200));
+                       pcPanel.add(panel, "cell 1 3, span 1 3");
+                       panel.setLayout(null);
+                       pcImageBtn = new JButton("No Image");
+                       pcImageBtn.setMaximumSize(new Dimension(75, 75));
+                       pcImageBtn.setMinimumSize(new Dimension(75, 75));
+                       panel.add(pcImageBtn);
+                       pcImageBtn.setBounds(new Rectangle(6, 6, 132, 145));
+                       
+                       pcImageBtn.addActionListener(new ActionListener() {
+                               @Override
+                               public void actionPerformed(final ActionEvent e) {
+                                       int returnVal = imageChooser.showOpenDialog(PresetEditorDialog.this);
+                                       
+                                       if (returnVal == JFileChooser.APPROVE_OPTION) {
+                                               File file = imageChooser.getSelectedFile();
+                                               pcImage = scaleImage(new ImageIcon(file.getAbsolutePath()).getImage(), 155);
+                                               pcImageBtn.setIcon(pcImage);
+                                       }
+                               }
+                       });
+               }
+               
+               JPanel buttonPane = new JPanel();
+               getContentPane().add(buttonPane, BorderLayout.SOUTH);
+               buttonPane.setLayout(new MigLayout("", "[130px][176.00px][131.00px]", "[29px]"));
+               JButton btnSaveAndNew = new JButton("Save and New");
+               btnSaveAndNew.addMouseListener(new MouseAdapter() {
+                       @Override
+                       public void mouseClicked(MouseEvent arg0) {
+                               saveResult();
+                       }
+               });
+               buttonPane.add(btnSaveAndNew, "cell 0 0,alignx left,aligny top");
+               
+               JButton okButton = new JButton("Save and Close");
+               okButton.addActionListener(new ActionListener() {
+                       @Override
+                       public void actionPerformed(ActionEvent event) {
+                               if (saveResult()) {
+                                       dispose();
+                               }
+                       }
+               });
+               okButton.setActionCommand("OK");
+               buttonPane.add(okButton, "cell 1 0,alignx left,aligny top");
+               getRootPane().setDefaultButton(okButton);
+               
+               JButton cancelButton = new JButton("Close");
+               cancelButton.addActionListener(new ActionListener() {
+                       @Override
+                       public void actionPerformed(ActionEvent event) {
+                               dispose();
+                       }
+               });
+               cancelButton.setActionCommand("Close");
+               buttonPane.add(cancelButton, "cell 6 0,alignx right,aligny top");
+               
+               if (toEdit != null) {
+                       fillEditor(toEdit, matHolder);
+               }
+               holder = matHolder;
+       }
+       
+       /**
+        * When an existing preset is edited, we want to disable the other types of presets.  If the user wants a different
+        * type of component, then they should delete this one and add a new one.
+        *
+        * @param cb     the combo box component
+        * @param preset the preset being edited
+        */
+       private void setItems(DeselectableComboBox cb, ComponentPreset preset) {
+               cb.addItem(trans.get(NOSE_CONE_KEY), preset != null && !preset.get(ComponentPreset.TYPE).equals(ComponentPreset.Type.NOSE_CONE));
+               cb.addItem(trans.get(BODY_TUBE_KEY), preset != null && !preset.get(ComponentPreset.TYPE).equals(ComponentPreset.Type.BODY_TUBE));
+               cb.addItem(trans.get(BULKHEAD_KEY), preset != null && !preset.get(ComponentPreset.TYPE).equals(ComponentPreset.Type.BULK_HEAD));
+               cb.addItem(trans.get(CR_KEY), preset != null && !preset.get(ComponentPreset.TYPE).equals(ComponentPreset.Type.CENTERING_RING));
+               cb.addItem(trans.get(EB_KEY), preset != null && !preset.get(ComponentPreset.TYPE).equals(ComponentPreset.Type.ENGINE_BLOCK));
+               cb.addItem(trans.get(TRANSITION_KEY), preset != null && !preset.get(ComponentPreset.TYPE).equals(ComponentPreset.Type.TRANSITION));
+               cb.addItem(trans.get(TUBE_COUPLER_KEY), preset != null && !preset.get(ComponentPreset.TYPE).equals(ComponentPreset.Type.TUBE_COUPLER));
+               cb.addItem(trans.get(LAUNCH_LUG_KEY), preset != null && !preset.get(ComponentPreset.TYPE).equals(ComponentPreset.Type.LAUNCH_LUG));
+               cb.addItem(trans.get(PARACHUTE_KEY), preset != null && !preset.get(ComponentPreset.TYPE).equals(ComponentPreset.Type.PARACHUTE));
+               cb.addItem(trans.get(STREAMER_KEY), preset != null && !preset.get(ComponentPreset.TYPE).equals(ComponentPreset.Type.STREAMER));
+       }
+       
+       /**
+        * Create an image chooser.  Currently png and jpg are supported.
+        *
+        * @return a file chooser that looks for image files
+        */
+       private JFileChooser createImageChooser() {
+               final JFileChooser chooser = new JFileChooser();
+               ImagePreviewPanel preview = new ImagePreviewPanel();
+               chooser.setAccessory(preview);
+               chooser.addPropertyChangeListener(preview);
+               chooser.setAcceptAllFileFilterUsed(false);
+               chooser.addChoosableFileFilter(new FileNameExtensionFilter("Image Files", "png", "jpg", "jpeg"));
+               return chooser;
+       }
+       
+       /**
+        * To support editing of an existing preset, the swing components need to be prepopulated with the field data.
+        *
+        * @param preset the preset to edit
+        */
+       private void fillEditor(ComponentPreset preset, MaterialHolder holder) {
+               ComponentPreset.Type t = preset.getType();
+               
+               mfgTextField.setText(preset.get(ComponentPreset.MANUFACTURER).getDisplayName());
+               setMaterial(materialChooser, preset, holder, Material.Type.BULK, ComponentPreset.MATERIAL);
+               switch (t) {
+               case BODY_TUBE:
+                       typeCombo.setSelectedItem(trans.get(BODY_TUBE_KEY));
+                       btDescTextField.setText(preset.get(ComponentPreset.DESCRIPTION));
+                       
+                       if (preset.has(ComponentPreset.INNER_DIAMETER)) {
+                               btInnerDia.setValue(preset.get(ComponentPreset.INNER_DIAMETER));
+                               btInnerDia.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
+                       }
+                       if (preset.has(ComponentPreset.LENGTH)) {
+                               btLength.setValue(preset.get(ComponentPreset.LENGTH));
+                               btLength.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
+                       }
+                       if (preset.has(ComponentPreset.MASS)) {
+                               btMass.setValue(preset.get(ComponentPreset.MASS));
+                               btMass.setCurrentUnit(UnitGroup.UNITS_MASS.getDefaultUnit());
+                       }
+                       if (preset.has(ComponentPreset.OUTER_DIAMETER)) {
+                               btOuterDia.setValue(preset.get(ComponentPreset.OUTER_DIAMETER));
+                               btOuterDia.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
+                       }
+                       if (preset.has(ComponentPreset.IMAGE)) {
+                               btImage = new ImageIcon(byteArrayToImage(preset.get(ComponentPreset.IMAGE)));
+                               btImageBtn.setIcon(btImage);
+                       }
+                       btPartNoTextField.setText(preset.get(ComponentPreset.PARTNO));
+                       break;
+               case BULK_HEAD:
+                       typeCombo.setSelectedItem(trans.get(BULKHEAD_KEY));
+                       bhDescTextField.setText(preset.get(ComponentPreset.DESCRIPTION));
+                       if (preset.has(ComponentPreset.LENGTH)) {
+                               bhLength.setValue(preset.get(ComponentPreset.LENGTH));
+                               bhLength.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
+                       }
+                       if (preset.has(ComponentPreset.MASS)) {
+                               bhMass.setValue(preset.get(ComponentPreset.MASS));
+                               bhMass.setCurrentUnit(UnitGroup.UNITS_MASS.getDefaultUnit());
+                       }
+                       if (preset.has(ComponentPreset.OUTER_DIAMETER)) {
+                               bhOuterDia.setValue(preset.get(ComponentPreset.OUTER_DIAMETER));
+                               bhOuterDia.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
+                       }
+                       if (preset.has(ComponentPreset.IMAGE)) {
+                               bhImage = new ImageIcon(byteArrayToImage(preset.get(ComponentPreset.IMAGE)));
+                               bhImageBtn.setIcon(bhImage);
+                       }
+                       bhPartNoTextField.setText(preset.get(ComponentPreset.PARTNO));
+                       break;
+               case CENTERING_RING:
+                       typeCombo.setSelectedItem(trans.get(CR_KEY));
+                       crDescTextField.setText(preset.get(ComponentPreset.DESCRIPTION));
+                       if (preset.has(ComponentPreset.INNER_DIAMETER)) {
+                               crInnerDia.setValue(preset.get(ComponentPreset.INNER_DIAMETER));
+                               crInnerDia.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
+                       }
+                       if (preset.has(ComponentPreset.LENGTH)) {
+                               crThickness.setValue(preset.get(ComponentPreset.LENGTH));
+                               crThickness.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
+                       }
+                       if (preset.has(ComponentPreset.MASS)) {
+                               crMass.setValue(preset.get(ComponentPreset.MASS));
+                               crMass.setCurrentUnit(UnitGroup.UNITS_MASS.getDefaultUnit());
+                       }
+                       if (preset.has(ComponentPreset.OUTER_DIAMETER)) {
+                               crOuterDia.setValue(preset.get(ComponentPreset.OUTER_DIAMETER));
+                               crOuterDia.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
+                       }
+                       if (preset.has(ComponentPreset.IMAGE)) {
+                               crImage = new ImageIcon(byteArrayToImage(preset.get(ComponentPreset.IMAGE)));
+                               crImageBtn.setIcon(crImage);
+                       }
+                       crPartNoTextField.setText(preset.get(ComponentPreset.PARTNO));
+                       break;
+               case ENGINE_BLOCK:
+                       typeCombo.setSelectedItem(trans.get(EB_KEY));
+                       ebDescTextField.setText(preset.get(ComponentPreset.DESCRIPTION));
+                       if (preset.has(ComponentPreset.INNER_DIAMETER)) {
+                               ebInnerDia.setValue(preset.get(ComponentPreset.INNER_DIAMETER));
+                               ebInnerDia.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
+                       }
+                       if (preset.has(ComponentPreset.LENGTH)) {
+                               ebThickness.setValue(preset.get(ComponentPreset.LENGTH));
+                               ebThickness.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
+                       }
+                       if (preset.has(ComponentPreset.MASS)) {
+                               ebMass.setValue(preset.get(ComponentPreset.MASS));
+                               ebMass.setCurrentUnit(UnitGroup.UNITS_MASS.getDefaultUnit());
+                       }
+                       if (preset.has(ComponentPreset.OUTER_DIAMETER)) {
+                               ebOuterDia.setValue(preset.get(ComponentPreset.OUTER_DIAMETER));
+                               ebOuterDia.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
+                       }
+                       if (preset.has(ComponentPreset.IMAGE)) {
+                               ebImage = new ImageIcon(byteArrayToImage(preset.get(ComponentPreset.IMAGE)));
+                               ebImageBtn.setIcon(ebImage);
+                       }
+                       ebPartNoTextField.setText(preset.get(ComponentPreset.PARTNO));
+                       break;
+               case NOSE_CONE:
+                       typeCombo.setSelectedItem(trans.get(NOSE_CONE_KEY));
+                       ncDescTextField.setText(preset.get(ComponentPreset.DESCRIPTION));
+                       if (preset.has(ComponentPreset.AFT_OUTER_DIAMETER)) {
+                               ncAftDia.setValue(preset.get(ComponentPreset.AFT_OUTER_DIAMETER));
+                               ncAftDia.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
+                       }
+                       if (preset.has(ComponentPreset.AFT_SHOULDER_DIAMETER)) {
+                               ncAftShoulderDia.setValue(preset.get(ComponentPreset.AFT_SHOULDER_DIAMETER));
+                               ncAftShoulderDia.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
+                       }
+                       if (preset.has(ComponentPreset.AFT_SHOULDER_LENGTH)) {
+                               ncAftShoulderLen.setValue(preset.get(ComponentPreset.AFT_SHOULDER_LENGTH));
+                               ncAftShoulderLen.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
+                       }
+                       if (preset.has(ComponentPreset.MASS)) {
+                               ncMass.setValue(preset.get(ComponentPreset.MASS));
+                               ncMass.setCurrentUnit(UnitGroup.UNITS_MASS.getDefaultUnit());
+                       }
+                       if (preset.has(ComponentPreset.SHAPE)) {
+                               ncShapeCB.setSelectedItem(preset.get(ComponentPreset.SHAPE).toString());
+                       }
+                       if (preset.has(ComponentPreset.FILLED)) {
+                               ncFilledCB.setSelected((preset.get(ComponentPreset.FILLED)));
+                       }
+                       if (preset.has(ComponentPreset.LENGTH)) {
+                               ncLength.setValue(preset.get(ComponentPreset.LENGTH));
+                               ncLength.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
+                       }
+                       if (preset.has(ComponentPreset.IMAGE)) {
+                               ncImage = new ImageIcon(byteArrayToImage(preset.get(ComponentPreset.IMAGE)));
+                               ncImageBtn.setIcon(ncImage);
+                       }
+                       ncPartNoTextField.setText(preset.get(ComponentPreset.PARTNO));
+                       break;
+               case TRANSITION:
+                       typeCombo.setSelectedItem(trans.get(TRANSITION_KEY));
+                       trDescTextField.setText(preset.get(ComponentPreset.DESCRIPTION));
+                       if (preset.has(ComponentPreset.AFT_OUTER_DIAMETER)) {
+                               trAftDia.setValue(preset.get(ComponentPreset.AFT_OUTER_DIAMETER));
+                               trAftDia.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
+                       }
+                       if (preset.has(ComponentPreset.AFT_SHOULDER_DIAMETER)) {
+                               trAftShoulderDia.setValue(preset.get(ComponentPreset.AFT_SHOULDER_DIAMETER));
+                               trAftShoulderDia.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
+                       }
+                       if (preset.has(ComponentPreset.AFT_SHOULDER_LENGTH)) {
+                               trAftShoulderLen.setValue(preset.get(ComponentPreset.AFT_SHOULDER_LENGTH));
+                               trAftShoulderLen.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
+                       }
+                       if (preset.has(ComponentPreset.FORE_OUTER_DIAMETER)) {
+                               trForeDia.setValue(preset.get(ComponentPreset.FORE_OUTER_DIAMETER));
+                               trForeDia.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
+                       }
+                       if (preset.has(ComponentPreset.FORE_SHOULDER_DIAMETER)) {
+                               trForeShoulderDia.setValue(preset.get(ComponentPreset.FORE_SHOULDER_DIAMETER));
+                               trForeShoulderDia.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
+                       }
+                       if (preset.has(ComponentPreset.FORE_SHOULDER_LENGTH)) {
+                               trForeShoulderLen.setValue(preset.get(ComponentPreset.FORE_SHOULDER_LENGTH));
+                               trForeShoulderLen.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
+                       }
+                       if (preset.has(ComponentPreset.MASS)) {
+                               trMass.setValue(preset.get(ComponentPreset.MASS));
+                               trMass.setCurrentUnit(UnitGroup.UNITS_MASS.getDefaultUnit());
+                       }
+                       if (preset.has(ComponentPreset.SHAPE)) {
+                               trShapeCB.setSelectedItem(preset.get(ComponentPreset.SHAPE).toString());
+                       }
+                       if (preset.has(ComponentPreset.FILLED)) {
+                               trFilledCB.setSelected((preset.get(ComponentPreset.FILLED)));
+                       }
+                       if (preset.has(ComponentPreset.LENGTH)) {
+                               trLength.setValue(preset.get(ComponentPreset.LENGTH));
+                               trLength.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
+                       }
+                       if (preset.has(ComponentPreset.IMAGE)) {
+                               trImage = new ImageIcon(byteArrayToImage(preset.get(ComponentPreset.IMAGE)));
+                               trImageBtn.setIcon(trImage);
+                       }
+                       trPartNoTextField.setText(preset.get(ComponentPreset.PARTNO));
+                       break;
+               case TUBE_COUPLER:
+                       typeCombo.setSelectedItem(trans.get(TUBE_COUPLER_KEY));
+                       tcDescTextField.setText(preset.get(ComponentPreset.DESCRIPTION));
+                       if (preset.has(ComponentPreset.INNER_DIAMETER)) {
+                               tcInnerDia.setValue(preset.get(ComponentPreset.INNER_DIAMETER));
+                               tcInnerDia.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
+                       }
+                       if (preset.has(ComponentPreset.LENGTH)) {
+                               tcLength.setValue(preset.get(ComponentPreset.LENGTH));
+                               tcLength.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
+                       }
+                       if (preset.has(ComponentPreset.MASS)) {
+                               tcMass.setValue(preset.get(ComponentPreset.MASS));
+                               tcMass.setCurrentUnit(UnitGroup.UNITS_MASS.getDefaultUnit());
+                       }
+                       if (preset.has(ComponentPreset.OUTER_DIAMETER)) {
+                               tcOuterDia.setValue(preset.get(ComponentPreset.OUTER_DIAMETER));
+                               tcOuterDia.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
+                       }
+                       tcPartNoTextField.setText(preset.get(ComponentPreset.PARTNO));
+                       if (preset.has(ComponentPreset.IMAGE)) {
+                               tcImage = new ImageIcon(byteArrayToImage(preset.get(ComponentPreset.IMAGE)));
+                               tcImageBtn.setIcon(tcImage);
+                       }
+                       break;
+               case LAUNCH_LUG:
+                       typeCombo.setSelectedItem(trans.get(LAUNCH_LUG_KEY));
+                       llDescTextField.setText(preset.get(ComponentPreset.DESCRIPTION));
+                       if (preset.has(ComponentPreset.INNER_DIAMETER)) {
+                               llInnerDia.setValue(preset.get(ComponentPreset.INNER_DIAMETER));
+                               llInnerDia.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
+                       }
+                       if (preset.has(ComponentPreset.LENGTH)) {
+                               llLength.setValue(preset.get(ComponentPreset.LENGTH));
+                               llLength.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
+                       }
+                       if (preset.has(ComponentPreset.MASS)) {
+                               llMass.setValue(preset.get(ComponentPreset.MASS));
+                               llMass.setCurrentUnit(UnitGroup.UNITS_MASS.getDefaultUnit());
+                       }
+                       if (preset.has(ComponentPreset.OUTER_DIAMETER)) {
+                               llOuterDia.setValue(preset.get(ComponentPreset.OUTER_DIAMETER));
+                               llOuterDia.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
+                       }
+                       llPartNoTextField.setText(preset.get(ComponentPreset.PARTNO));
+                       if (preset.has(ComponentPreset.IMAGE)) {
+                               llImage = new ImageIcon(byteArrayToImage(preset.get(ComponentPreset.IMAGE)));
+                               llImageBtn.setIcon(llImage);
+                       }
+                       break;
+               case PARACHUTE:
+                       setMaterial(materialChooser, preset, holder, Material.Type.SURFACE, ComponentPreset.MATERIAL);
+                       typeCombo.setSelectedItem(trans.get(PARACHUTE_KEY));
+                       pcDescTextField.setText(preset.get(ComponentPreset.DESCRIPTION));
+                       if (preset.has(ComponentPreset.LINE_COUNT)) {
+                               pcLineCount.setText(preset.get(ComponentPreset.LINE_COUNT).toString());
+                       }
+                       if (preset.has(ComponentPreset.SIDES)) {
+                               pcSides.setText(preset.get(ComponentPreset.SIDES).toString());
+                       }
+                       if (preset.has(ComponentPreset.MASS)) {
+                               pcMass.setValue(preset.get(ComponentPreset.MASS));
+                               pcMass.setCurrentUnit(UnitGroup.UNITS_MASS.getDefaultUnit());
+                       }
+                       if (preset.has(ComponentPreset.DIAMETER)) {
+                               pcDiameter.setValue(preset.get(ComponentPreset.DIAMETER));
+                               pcDiameter.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
+                       }
+                       if (preset.has(ComponentPreset.LINE_LENGTH)) {
+                               pcLineLength.setValue(preset.get(ComponentPreset.LINE_LENGTH));
+                               pcLineLength.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
+                       }
+                       pcPartNoTextField.setText(preset.get(ComponentPreset.PARTNO));
+                       if (preset.has(ComponentPreset.IMAGE)) {
+                               pcImage = new ImageIcon(byteArrayToImage(preset.get(ComponentPreset.IMAGE)));
+                               pcImageBtn.setIcon(pcImage);
+                       }
+                       setMaterial(pcLineMaterialChooser, preset, holder, Material.Type.LINE, ComponentPreset.LINE_MATERIAL);
+                       //                pcLineMaterialChooser.setModel(new MaterialModel(PresetEditorDialog.this, Material.Type.LINE));
+                       
+                       //                pcLineMaterialChooser.getModel().setSelectedItem(preset.get(ComponentPreset.LINE_MATERIAL));
+                       break;
+               case STREAMER:
+                       setMaterial(materialChooser, preset, holder, Material.Type.SURFACE, ComponentPreset.MATERIAL);
+                       typeCombo.setSelectedItem(trans.get(STREAMER_KEY));
+                       stDescTextField.setText(preset.get(ComponentPreset.DESCRIPTION));
+                       if (preset.has(ComponentPreset.LENGTH)) {
+                               stLength.setValue(preset.get(ComponentPreset.LENGTH));
+                               stLength.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
+                       }
+                       if (preset.has(ComponentPreset.THICKNESS)) {
+                               stThickness.setValue(preset.get(ComponentPreset.LENGTH));
+                               stThickness.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
+                       }
+                       if (preset.has(ComponentPreset.MASS)) {
+                               stMass.setValue(preset.get(ComponentPreset.MASS));
+                               stMass.setCurrentUnit(UnitGroup.UNITS_MASS.getDefaultUnit());
+                       }
+                       if (preset.has(ComponentPreset.WIDTH)) {
+                               stWidth.setValue(preset.get(ComponentPreset.WIDTH));
+                               stWidth.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
+                       }
+                       if (preset.has(ComponentPreset.IMAGE)) {
+                               stImage = new ImageIcon(byteArrayToImage(preset.get(ComponentPreset.IMAGE)));
+                               stImageBtn.setIcon(stImage);
+                       }
+                       stPartNoTextField.setText(preset.get(ComponentPreset.PARTNO));
+                       break;
+               default:
+               }
+       }
+       
+       private void setMaterial(final JComboBox chooser, final ComponentPreset preset, final MaterialHolder holder,
+                       final Material.Type theType, final TypedKey key) {
+               if (holder == null) {
+                       chooser.setModel(new MaterialModel(PresetEditorDialog.this, theType));
+               }
+               else {
+                       chooser.setModel(new MaterialModel(PresetEditorDialog.this, theType,
+                                       holder.asDatabase(theType)));
+               }
+               if (preset != null) {
+                       chooser.getModel().setSelectedItem(preset.get(key));
+               }
+       }
+       
+       /**
+        * Extract the preset data from the UI fields, create a ComponentPreset instance, and notify the listener.
+        */
+       private boolean saveResult() {
+               String type = (String) typeCombo.getSelectedItem();
+               
+               ComponentPreset result = null;
+               
+               if (type.equals(trans.get(NOSE_CONE_KEY))) {
+                       result = extractNoseCone();
+                       if (result != null) {
+                               clearNoseCone();
+                       }
+               }
+               else if (type.equals(trans.get(TRANSITION_KEY))) {
+                       result = extractTransition();
+                       if (result != null) {
+                               clearTransition();
+                       }
+               }
+               else if (type.equals(trans.get(BODY_TUBE_KEY))) {
+                       result = extractBodyTube();
+                       if (result != null) {
+                               clearBodyTube();
+                       }
+               }
+               else if (type.equals(trans.get(TUBE_COUPLER_KEY))) {
+                       result = extractTubeCoupler();
+                       if (result != null) {
+                               clearTubeCoupler();
+                       }
+               }
+               else if (type.equals(trans.get(EB_KEY))) {
+                       result = extractEngineBlock();
+                       if (result != null) {
+                               clearEngineBlock();
+                       }
+               }
+               else if (type.equals(trans.get(CR_KEY))) {
+                       result = extractCenteringRing();
+                       if (result != null) {
+                               clearCenteringRing();
+                       }
+               }
+               else if (type.equals(trans.get(BULKHEAD_KEY))) {
+                       result = extractBulkhead();
+                       if (result != null) {
+                               clearBulkhead();
+                       }
+               }
+               else if (type.equals(trans.get(LAUNCH_LUG_KEY))) {
+                       result = extractLaunchLug();
+                       if (result != null) {
+                               clearLaunchLug();
+                       }
+               }
+               else if (type.equals(trans.get(PARACHUTE_KEY))) {
+                       result = extractParachute();
+                       if (result != null) {
+                               clearParachute();
+                       }
+               }
+               else if (type.equals(trans.get(STREAMER_KEY))) {
+                       result = extractStreamer();
+                       if (result != null) {
+                               clearStreamer();
+                       }
+               }
+               if (result != null) {
+                       resultListener.notifyResult(result);
+                       return true;
+               }
+               else {
+                       return false;
+               }
+       }
+       
+       private ComponentPreset extractNoseCone() {
+               TypedPropertyMap props = new TypedPropertyMap();
+               try {
+                       props.put(ComponentPreset.TYPE, ComponentPreset.Type.NOSE_CONE);
+                       props.put(ComponentPreset.AFT_OUTER_DIAMETER, ncAftDia.getValue());
+                       props.put(ComponentPreset.AFT_SHOULDER_DIAMETER, ncAftShoulderDia.getValue());
+                       props.put(ComponentPreset.AFT_SHOULDER_LENGTH, ncAftShoulderLen.getValue());
+                       props.put(ComponentPreset.DESCRIPTION, ncDescTextField.getText());
+                       props.put(ComponentPreset.PARTNO, ncPartNoTextField.getText());
+                       props.put(ComponentPreset.MANUFACTURER, Manufacturer.getManufacturer(mfgTextField.getText()));
+                       props.put(ComponentPreset.LENGTH, ncLength.getValue());
+                       props.put(ComponentPreset.SHAPE, Transition.Shape.toShape((String) ncShapeCB.getSelectedItem()));
+                       final Material material = (Material) materialChooser.getSelectedItem();
+                       if (material != null) {
+                               props.put(ComponentPreset.MATERIAL, material);
+                       }
+                       else {
+                               JOptionPane.showMessageDialog(null, "A material must be selected.", "Error", JOptionPane.ERROR_MESSAGE);
+                               return null;
+                       }
+                       props.put(ComponentPreset.MASS, ncMass.getValue());
+                       props.put(ComponentPreset.FILLED, ncFilledCB.isSelected());
+                       if (ncImage != null) {
+                               props.put(ComponentPreset.IMAGE, imageToByteArray(ncImage.getImage()));
+                       }
+                       
+                       return ComponentPresetFactory.create(props);
+               } catch (NumberFormatException nfe) {
+                       JOptionPane.showMessageDialog(null, "Could not convert nose cone attribute.", "Error", JOptionPane.ERROR_MESSAGE);
+               } catch (InvalidComponentPresetException e) {
+                       JOptionPane.showMessageDialog(null, craftErrorMessage(e, "Mandatory nose cone attribute not set."), "Error", JOptionPane.ERROR_MESSAGE);
+               }
+               return null;
+       }
+       
+       private void clearNoseCone() {
+               ncAftDia.setValue(0);
+               ncAftShoulderDia.setValue(0);
+               ncAftShoulderLen.setValue(0);
+               ncDescTextField.setText("");
+               ncPartNoTextField.setText("");
+               ncLength.setValue(0);
+               ncMass.setValue(0);
+               ncFilledCB.setSelected(false);
+               ncImage = null;
+               ncImageBtn.setIcon(null);
+       }
+       
+       private ComponentPreset extractTransition() {
+               TypedPropertyMap props = new TypedPropertyMap();
+               try {
+                       props.put(ComponentPreset.TYPE, ComponentPreset.Type.TRANSITION);
+                       props.put(ComponentPreset.AFT_OUTER_DIAMETER, trAftDia.getValue());
+                       props.put(ComponentPreset.AFT_SHOULDER_DIAMETER, trAftShoulderDia.getValue());
+                       props.put(ComponentPreset.AFT_SHOULDER_LENGTH, trAftShoulderLen.getValue());
+                       props.put(ComponentPreset.FORE_OUTER_DIAMETER, trForeDia.getValue());
+                       props.put(ComponentPreset.FORE_SHOULDER_DIAMETER, trForeShoulderDia.getValue());
+                       props.put(ComponentPreset.FORE_SHOULDER_LENGTH, trForeShoulderLen.getValue());
+                       props.put(ComponentPreset.DESCRIPTION, trDescTextField.getText());
+                       props.put(ComponentPreset.PARTNO, trPartNoTextField.getText());
+                       props.put(ComponentPreset.MANUFACTURER, Manufacturer.getManufacturer(mfgTextField.getText()));
+                       
+                       props.put(ComponentPreset.LENGTH, trLength.getValue());
+                       props.put(ComponentPreset.SHAPE, Transition.Shape.toShape((String) trShapeCB.getSelectedItem()));
+                       final Material material = (Material) materialChooser.getSelectedItem();
+                       if (material != null) {
+                               props.put(ComponentPreset.MATERIAL, material);
+                       }
+                       else {
+                               JOptionPane.showMessageDialog(null, "A material must be selected.", "Error", JOptionPane.ERROR_MESSAGE);
+                               return null;
+                       }
+                       props.put(ComponentPreset.MASS, trMass.getValue());
+                       props.put(ComponentPreset.FILLED, trFilledCB.isSelected());
+                       if (trImage != null) {
+                               props.put(ComponentPreset.IMAGE, imageToByteArray(trImage.getImage()));
+                       }
+                       
+                       return ComponentPresetFactory.create(props);
+               } catch (NumberFormatException nfe) {
+                       JOptionPane.showMessageDialog(null, "Could not convert transition attribute.", "Error", JOptionPane.ERROR_MESSAGE);
+               } catch (InvalidComponentPresetException e) {
+                       JOptionPane.showMessageDialog(null, craftErrorMessage(e, "Mandatory transition attribute not set."), "Error", JOptionPane.ERROR_MESSAGE);
+               }
+               return null;
+       }
+       
+       private void clearTransition() {
+               trAftDia.setValue(0);
+               trAftShoulderDia.setValue(0);
+               trAftShoulderLen.setValue(0);
+               trForeDia.setValue(0);
+               trForeShoulderDia.setValue(0);
+               trForeShoulderLen.setValue(0);
+               trDescTextField.setText("");
+               trPartNoTextField.setText("");
+               trLength.setValue(0);
+               trMass.setValue(0);
+               trFilledCB.setSelected(false);
+               trImage = null;
+               trImageBtn.setIcon(null);
+       }
+       
+       private ComponentPreset extractBodyTube() {
+               TypedPropertyMap props = new TypedPropertyMap();
+               try {
+                       props.put(ComponentPreset.TYPE, ComponentPreset.Type.BODY_TUBE);
+                       props.put(ComponentPreset.OUTER_DIAMETER, btOuterDia.getValue());
+                       props.put(ComponentPreset.INNER_DIAMETER, btInnerDia.getValue());
+                       props.put(ComponentPreset.DESCRIPTION, btDescTextField.getText());
+                       props.put(ComponentPreset.PARTNO, btPartNoTextField.getText());
+                       props.put(ComponentPreset.MANUFACTURER, Manufacturer.getManufacturer(mfgTextField.getText()));
+                       props.put(ComponentPreset.LENGTH, btLength.getValue());
+                       final Material material = (Material) materialChooser.getSelectedItem();
+                       if (material != null) {
+                               props.put(ComponentPreset.MATERIAL, material);
+                       }
+                       else {
+                               JOptionPane.showMessageDialog(null, "A material must be selected.", "Error", JOptionPane.ERROR_MESSAGE);
+                               return null;
+                       }
+                       props.put(ComponentPreset.MASS, btMass.getValue());
+                       if (btImage != null) {
+                               props.put(ComponentPreset.IMAGE, imageToByteArray(btImage.getImage()));
+                       }
+                       return ComponentPresetFactory.create(props);
+               } catch (NumberFormatException nfe) {
+                       JOptionPane.showMessageDialog(null, "Could not convert body tube attribute.", "Error", JOptionPane.ERROR_MESSAGE);
+               } catch (InvalidComponentPresetException e) {
+                       JOptionPane.showMessageDialog(null, craftErrorMessage(e, "Mandatory body tube attribute not set."), "Error", JOptionPane.ERROR_MESSAGE);
+               }
+               return null;
+       }
+       
+       private void clearBodyTube() {
+               btOuterDia.setValue(0);
+               btInnerDia.setValue(0);
+               btDescTextField.setText("");
+               btPartNoTextField.setText("");
+               btLength.setValue(0);
+               btMass.setValue(0);
+               btImage = null;
+               btImageBtn.setIcon(null);
+       }
+       
+       public ComponentPreset extractTubeCoupler() {
+               TypedPropertyMap props = new TypedPropertyMap();
+               try {
+                       props.put(ComponentPreset.TYPE, ComponentPreset.Type.TUBE_COUPLER);
+                       props.put(ComponentPreset.OUTER_DIAMETER, tcOuterDia.getValue());
+                       props.put(ComponentPreset.INNER_DIAMETER, tcInnerDia.getValue());
+                       props.put(ComponentPreset.DESCRIPTION, tcDescTextField.getText());
+                       props.put(ComponentPreset.PARTNO, tcPartNoTextField.getText());
+                       props.put(ComponentPreset.MANUFACTURER, Manufacturer.getManufacturer(mfgTextField.getText()));
+                       props.put(ComponentPreset.LENGTH, tcLength.getValue());
+                       final Material material = (Material) materialChooser.getSelectedItem();
+                       if (material != null) {
+                               props.put(ComponentPreset.MATERIAL, material);
+                       }
+                       else {
+                               JOptionPane.showMessageDialog(null, "A material must be selected.", "Error", JOptionPane.ERROR_MESSAGE);
+                               return null;
+                       }
+                       props.put(ComponentPreset.MASS, tcMass.getValue());
+                       if (tcImage != null) {
+                               props.put(ComponentPreset.IMAGE, imageToByteArray(tcImage.getImage()));
+                       }
+                       
+                       return ComponentPresetFactory.create(props);
+               } catch (NumberFormatException nfe) {
+                       JOptionPane.showMessageDialog(null, "Could not convert tube coupler attribute.", "Error", JOptionPane.ERROR_MESSAGE);
+               } catch (InvalidComponentPresetException e) {
+                       JOptionPane.showMessageDialog(null, craftErrorMessage(e, "Mandatory tube coupler attribute not set."), "Error", JOptionPane.ERROR_MESSAGE);
+               }
+               return null;
+       }
+       
+       private void clearTubeCoupler() {
+               tcOuterDia.setValue(0);
+               tcInnerDia.setValue(0);
+               tcDescTextField.setText("");
+               tcPartNoTextField.setText("");
+               tcLength.setValue(0);
+               tcMass.setValue(0);
+               tcImage = null;
+               tcImageBtn.setIcon(null);
+       }
+       
+       private ComponentPreset extractBulkhead() {
+               TypedPropertyMap props = new TypedPropertyMap();
+               try {
+                       props.put(ComponentPreset.TYPE, ComponentPreset.Type.BULK_HEAD);
+                       props.put(ComponentPreset.OUTER_DIAMETER, bhOuterDia.getValue());
+                       props.put(ComponentPreset.DESCRIPTION, bhDescTextField.getText());
+                       props.put(ComponentPreset.PARTNO, bhPartNoTextField.getText());
+                       props.put(ComponentPreset.MANUFACTURER, Manufacturer.getManufacturer(mfgTextField.getText()));
+                       props.put(ComponentPreset.LENGTH, bhLength.getValue());
+                       final Material material = (Material) materialChooser.getSelectedItem();
+                       if (material != null) {
+                               props.put(ComponentPreset.MATERIAL, material);
+                       }
+                       else {
+                               JOptionPane.showMessageDialog(null, "A material must be selected.", "Error", JOptionPane.ERROR_MESSAGE);
+                               return null;
+                       }
+                       props.put(ComponentPreset.MASS, bhMass.getValue());
+                       if (bhImage != null) {
+                               props.put(ComponentPreset.IMAGE, imageToByteArray(bhImage.getImage()));
+                       }
+                       return ComponentPresetFactory.create(props);
+               } catch (NumberFormatException nfe) {
+                       JOptionPane.showMessageDialog(null, "Could not convert bulkhead attribute.", "Error", JOptionPane.ERROR_MESSAGE);
+               } catch (InvalidComponentPresetException e) {
+                       JOptionPane.showMessageDialog(null, craftErrorMessage(e, "Mandatory bulkhead attribute not set."), "Error", JOptionPane.ERROR_MESSAGE);
+               }
+               return null;
+       }
+       
+       private void clearBulkhead() {
+               bhOuterDia.setValue(0);
+               bhDescTextField.setText("");
+               bhPartNoTextField.setText("");
+               bhLength.setValue(0);
+               bhMass.setValue(0);
+               bhImage = null;
+               bhImageBtn.setIcon(null);
+       }
+       
+       private ComponentPreset extractCenteringRing() {
+               TypedPropertyMap props = new TypedPropertyMap();
+               try {
+                       props.put(ComponentPreset.TYPE, ComponentPreset.Type.CENTERING_RING);
+                       props.put(ComponentPreset.OUTER_DIAMETER, crOuterDia.getValue());
+                       props.put(ComponentPreset.INNER_DIAMETER, crInnerDia.getValue());
+                       props.put(ComponentPreset.DESCRIPTION, crDescTextField.getText());
+                       props.put(ComponentPreset.PARTNO, crPartNoTextField.getText());
+                       props.put(ComponentPreset.MANUFACTURER, Manufacturer.getManufacturer(mfgTextField.getText()));
+                       props.put(ComponentPreset.LENGTH, crThickness.getValue());
+                       final Material material = (Material) materialChooser.getSelectedItem();
+                       if (material != null) {
+                               props.put(ComponentPreset.MATERIAL, material);
+                       }
+                       else {
+                               JOptionPane.showMessageDialog(null, "A material must be selected.", "Error", JOptionPane.ERROR_MESSAGE);
+                               return null;
+                       }
+                       props.put(ComponentPreset.MASS, crMass.getValue());
+                       if (crImage != null) {
+                               props.put(ComponentPreset.IMAGE, imageToByteArray(crImage.getImage()));
+                       }
+                       return ComponentPresetFactory.create(props);
+               } catch (NumberFormatException nfe) {
+                       JOptionPane.showMessageDialog(null, "Could not convert centering ring attribute.", "Error", JOptionPane.ERROR_MESSAGE);
+               } catch (InvalidComponentPresetException e) {
+                       JOptionPane.showMessageDialog(null, craftErrorMessage(e, "Mandatory centering ring attribute not set."), "Error", JOptionPane.ERROR_MESSAGE);
+               }
+               return null;
+       }
+       
+       private void clearCenteringRing() {
+               crOuterDia.setValue(0);
+               crInnerDia.setValue(0);
+               crDescTextField.setText("");
+               crPartNoTextField.setText("");
+               crThickness.setValue(0);
+               crMass.setValue(0);
+               crImage = null;
+               crImageBtn.setIcon(null);
+       }
+       
+       public ComponentPreset extractEngineBlock() {
+               TypedPropertyMap props = new TypedPropertyMap();
+               try {
+                       props.put(ComponentPreset.TYPE, ComponentPreset.Type.ENGINE_BLOCK);
+                       props.put(ComponentPreset.OUTER_DIAMETER, ebOuterDia.getValue());
+                       props.put(ComponentPreset.INNER_DIAMETER, ebInnerDia.getValue());
+                       props.put(ComponentPreset.DESCRIPTION, ebDescTextField.getText());
+                       props.put(ComponentPreset.PARTNO, ebPartNoTextField.getText());
+                       props.put(ComponentPreset.MANUFACTURER, Manufacturer.getManufacturer(mfgTextField.getText()));
+                       props.put(ComponentPreset.LENGTH, ebThickness.getValue());
+                       final Material material = (Material) materialChooser.getSelectedItem();
+                       if (material != null) {
+                               props.put(ComponentPreset.MATERIAL, material);
+                       }
+                       else {
+                               JOptionPane.showMessageDialog(null, "A material must be selected.", "Error", JOptionPane.ERROR_MESSAGE);
+                               return null;
+                       }
+                       props.put(ComponentPreset.MASS, ebMass.getValue());
+                       if (ebImage != null) {
+                               props.put(ComponentPreset.IMAGE, imageToByteArray(ebImage.getImage()));
+                       }
+                       return ComponentPresetFactory.create(props);
+               } catch (NumberFormatException nfe) {
+                       JOptionPane.showMessageDialog(null, "Could not convert engine block attribute.", "Error", JOptionPane.ERROR_MESSAGE);
+               } catch (InvalidComponentPresetException e) {
+                       JOptionPane.showMessageDialog(null, craftErrorMessage(e, "Mandatory engine block attribute not set."), "Error", JOptionPane.ERROR_MESSAGE);
+               }
+               return null;
+       }
+       
+       private void clearEngineBlock() {
+               ebOuterDia.setValue(0);
+               ebInnerDia.setValue(0);
+               ebDescTextField.setText("");
+               ebPartNoTextField.setText("");
+               ebThickness.setValue(0);
+               ebMass.setValue(0);
+               ebImage = null;
+               ebImageBtn.setIcon(null);
+       }
+       
+       public ComponentPreset extractLaunchLug() {
+               TypedPropertyMap props = new TypedPropertyMap();
+               try {
+                       props.put(ComponentPreset.TYPE, ComponentPreset.Type.LAUNCH_LUG);
+                       props.put(ComponentPreset.OUTER_DIAMETER, llOuterDia.getValue());
+                       props.put(ComponentPreset.INNER_DIAMETER, llInnerDia.getValue());
+                       props.put(ComponentPreset.DESCRIPTION, llDescTextField.getText());
+                       props.put(ComponentPreset.PARTNO, llPartNoTextField.getText());
+                       props.put(ComponentPreset.MANUFACTURER, Manufacturer.getManufacturer(mfgTextField.getText()));
+                       props.put(ComponentPreset.LENGTH, llLength.getValue());
+                       final Material material = (Material) materialChooser.getSelectedItem();
+                       if (material != null) {
+                               props.put(ComponentPreset.MATERIAL, material);
+                       }
+                       else {
+                               JOptionPane.showMessageDialog(null, "A material must be selected.", "Error", JOptionPane.ERROR_MESSAGE);
+                               return null;
+                       }
+                       props.put(ComponentPreset.MASS, llMass.getValue());
+                       if (llImage != null) {
+                               props.put(ComponentPreset.IMAGE, imageToByteArray(llImage.getImage()));
+                       }
+                       return ComponentPresetFactory.create(props);
+               } catch (NumberFormatException nfe) {
+                       JOptionPane.showMessageDialog(null, "Could not convert launch lug attribute.", "Error", JOptionPane.ERROR_MESSAGE);
+               } catch (InvalidComponentPresetException e) {
+                       JOptionPane.showMessageDialog(null, craftErrorMessage(e, "Mandatory launch lug attribute not set."), "Error", JOptionPane.ERROR_MESSAGE);
+               }
+               return null;
+       }
+       
+       private void clearLaunchLug() {
+               llOuterDia.setValue(0);
+               llInnerDia.setValue(0);
+               llDescTextField.setText("");
+               llPartNoTextField.setText("");
+               llLength.setValue(0);
+               llMass.setValue(0);
+               llImage = null;
+               llImageBtn.setIcon(null);
+       }
+       
+       public ComponentPreset extractParachute() {
+               TypedPropertyMap props = new TypedPropertyMap();
+               try {
+                       props.put(ComponentPreset.TYPE, ComponentPreset.Type.PARACHUTE);
+                       props.put(ComponentPreset.DIAMETER, pcDiameter.getValue());
+                       props.put(ComponentPreset.DESCRIPTION, pcDescTextField.getText());
+                       props.put(ComponentPreset.PARTNO, pcPartNoTextField.getText());
+                       props.put(ComponentPreset.MANUFACTURER, Manufacturer.getManufacturer(mfgTextField.getText()));
+                       if (!pcLineCount.getText().equals("")) {
+                               props.put(ComponentPreset.LINE_COUNT, Integer.parseInt(pcLineCount.getText()));
+                       }
+                       if (!pcSides.getText().equals("")) {
+                               props.put(ComponentPreset.SIDES, Integer.parseInt(pcSides.getText()));
+                       }
+                       props.put(ComponentPreset.LINE_LENGTH, pcLineLength.getValue());
+                       Material material = (Material) materialChooser.getSelectedItem();
+                       if (material != null) {
+                               props.put(ComponentPreset.MATERIAL, material);
+                       }
+                       else {
+                               JOptionPane.showMessageDialog(null, "A material must be selected.", "Error", JOptionPane.ERROR_MESSAGE);
+                               return null;
+                       }
+                       material = (Material) pcLineMaterialChooser.getSelectedItem();
+                       if (material != null) {
+                               props.put(ComponentPreset.LINE_MATERIAL, material);
+                       }
+                       props.put(ComponentPreset.MASS, pcMass.getValue());
+                       if (pcImage != null) {
+                               props.put(ComponentPreset.IMAGE, imageToByteArray(pcImage.getImage()));
+                       }
+                       return ComponentPresetFactory.create(props);
+               } catch (NumberFormatException nfe) {
+                       JOptionPane.showMessageDialog(null, "Could not convert parachute attribute.", "Error", JOptionPane.ERROR_MESSAGE);
+               } catch (InvalidComponentPresetException e) {
+                       JOptionPane.showMessageDialog(null, craftErrorMessage(e, "Mandatory parachute attribute not set."), "Error", JOptionPane.ERROR_MESSAGE);
+               }
+               return null;
+       }
+       
+       private void clearParachute() {
+               ebOuterDia.setValue(0);
+               ebInnerDia.setValue(0);
+               ebDescTextField.setText("");
+               ebPartNoTextField.setText("");
+               ebThickness.setValue(0);
+               ebMass.setValue(0);
+               ebImage = null;
+               ebImageBtn.setIcon(null);
+       }
+       
+       public ComponentPreset extractStreamer() {
+               TypedPropertyMap props = new TypedPropertyMap();
+               try {
+                       props.put(ComponentPreset.TYPE, ComponentPreset.Type.STREAMER);
+                       props.put(ComponentPreset.DESCRIPTION, stDescTextField.getText());
+                       props.put(ComponentPreset.PARTNO, stPartNoTextField.getText());
+                       props.put(ComponentPreset.MANUFACTURER, Manufacturer.getManufacturer(mfgTextField.getText()));
+                       props.put(ComponentPreset.THICKNESS, stThickness.getValue());
+                       props.put(ComponentPreset.LENGTH, stLength.getValue());
+                       props.put(ComponentPreset.WIDTH, stWidth.getValue());
+                       final Material material = (Material) materialChooser.getSelectedItem();
+                       if (material != null) {
+                               props.put(ComponentPreset.MATERIAL, material);
+                       }
+                       else {
+                               JOptionPane.showMessageDialog(null, "A material must be selected.", "Error", JOptionPane.ERROR_MESSAGE);
+                               return null;
+                       }
+                       props.put(ComponentPreset.MASS, stMass.getValue());
+                       if (stImage != null) {
+                               props.put(ComponentPreset.IMAGE, imageToByteArray(stImage.getImage()));
+                       }
+                       return ComponentPresetFactory.create(props);
+               } catch (NumberFormatException nfe) {
+                       JOptionPane.showMessageDialog(null, "Could not convert engine block attribute.", "Error", JOptionPane.ERROR_MESSAGE);
+               } catch (InvalidComponentPresetException e) {
+                       JOptionPane.showMessageDialog(null, craftErrorMessage(e, "Mandatory engine block attribute not set."), "Error", JOptionPane.ERROR_MESSAGE);
+               }
+               return null;
+       }
+       
+       private void clearStreamer() {
+               stWidth.setValue(0);
+               stLength.setValue(0);
+               stDescTextField.setText("");
+               stPartNoTextField.setText("");
+               stThickness.setValue(0);
+               stMass.setValue(0);
+               stImage = null;
+               stImageBtn.setIcon(null);
+       }
+       
+       @Override
+       public void itemStateChanged(ItemEvent evt) {
+               CardLayout cl = (CardLayout) (componentOverlayPanel.getLayout());
+               final String item = (String) evt.getItem();
+               if (materialChooser != null && evt.getStateChange() == ItemEvent.SELECTED) {
+                       if (item.equals(trans.get(PARACHUTE_KEY)) || item.equals(trans.get(STREAMER_KEY))) {
+                               if (!((MaterialModel) materialChooser.getModel()).getType().equals(Material.Type.SURFACE)) {
+                                       setMaterial(materialChooser, null, holder, Material.Type.SURFACE, ComponentPreset.MATERIAL);
+                               }
+                       }
+                       else {
+                               if (!((MaterialModel) materialChooser.getModel()).getType().equals(Material.Type.BULK)) {
+                                       setMaterial(materialChooser, null, holder, Material.Type.BULK, ComponentPreset.MATERIAL);
+                               }
+                       }
+               }
+               cl.show(componentOverlayPanel, componentMap.get(item));
+       }
+       
+       //Todo: I18N
+       private String craftErrorMessage(InvalidComponentPresetException e, String baseMsg) {
+               StringBuilder stringBuilder = new StringBuilder();
+               List<String> invalids = e.getErrors();
+               stringBuilder.append(baseMsg).append("\n");
+               for (int i = 0; i < invalids.size(); i++) {
+                       String s = invalids.get(i);
+                       stringBuilder.append(s).append("\n");
+               }
+               
+               return stringBuilder.toString();
+       }
+       
+       /**
+        * Convert an image to a byte array in png format.
+        *
+        * @param originalImage
+        *
+        * @return
+        */
+       private byte[] imageToByteArray(Image originalImage) {
+               byte[] imageInByte = null;
+               try {
+                       BufferedImage bi = imageToBufferedImage(originalImage);
+                       ByteArrayOutputStream baos = new ByteArrayOutputStream();
+                       ImageIO.write(bi, "png", baos);
+                       baos.flush();
+                       imageInByte = baos.toByteArray();
+                       baos.close();
+               } catch (IOException e) {
+                       log.error("Could not read image.");
+               }
+               return imageInByte;
+       }
+       
+       private BufferedImage imageToBufferedImage(final Image originalImage) {
+               BufferedImage bi = new BufferedImage(originalImage.getWidth(null), originalImage.getHeight(null), BufferedImage.TYPE_INT_RGB);
+               
+               Graphics2D g2 = bi.createGraphics();
+               g2.drawImage(originalImage, 0, 0, null);
+               return bi;
+       }
+       
+       private BufferedImage byteArrayToImage(byte[] src) {
+               // convert byte array back to BufferedImage
+               InputStream in = new ByteArrayInputStream(src);
+               try {
+                       return ImageIO.read(in);
+               } catch (IOException e) {
+                       log.error("Could not convert image.");
+               }
+               return null;
+       }
+       
+       private ImageIcon scaleImage(Image image, int targetDimension) {
+               int width = image.getWidth(this);
+               int height = image.getHeight(this);
+               double ratio = 1.0;
+               
+               /*
+                * Determine how to scale the image. Since the accessory can expand
+                * vertically make sure we don't go larger than 150 when scaling
+                * vertically.
+                */
+               if (width >= height) {
+                       ratio = (double) (targetDimension - 5) / width;
+                       width = targetDimension - 5;
+                       height = (int) (height * ratio);
+               }
+               else {
+                       if (getHeight() > 150) {
+                               ratio = (double) (targetDimension - 5) / height;
+                               height = targetDimension - 5;
+                               width = (int) (width * ratio);
+                       }
+                       else {
+                               ratio = (double) getHeight() / height;
+                               height = getHeight();
+                               width = (int) (width * ratio);
+                       }
+               }
+               
+               return new ImageIcon(image.getScaledInstance(width, height, Image.SCALE_DEFAULT));
+       }
+       
+       static class PresetInputVerifier extends InputVerifier {
+               
+               /**
+                * Matches user input against a regular expression.
+                */
+               private Matcher matcher;
+               
+               PresetInputVerifier(final Pattern thePattern) {
+                       matcher = thePattern.matcher("");
+               }
+               
+               /**
+                * Return true only if the untrimmed user input matches the regular expression provided to the constructor.
+                *
+                * @param aComponent must be an instance of JTextComponent.
+                */
+               @Override
+               public boolean verify(JComponent aComponent) {
+                       JTextComponent textComponent = (JTextComponent) aComponent;
+                       String text = textComponent.getText();
+                       matcher.reset(text);
+                       return matcher.matches();
+               }
+               
+               /**
+                * Always returns <tt>true</tt>, in this implementation, such that focus can always transfer to another
+                * component whenever the validation fails.
+                * <p/>
+                * <P>If <tt>super.shouldYieldFocus</tt> returns <tt>false</tt>, then clear the text field.
+                *
+                * @param aComponent is a <tt>JTextComponent</tt>.
+                */
+               @Override
+               public boolean shouldYieldFocus(JComponent aComponent) {
+                       if (!super.shouldYieldFocus(aComponent)) {
+                               ((JTextComponent) aComponent).setText("");
+                       }
+                       return true;
+               }
+       }
+       
+       class MaterialChooser extends JComboBox {
+               
+               public MaterialChooser() {
+               }
+               
+               public MaterialChooser(MaterialModel model) {
+                       super(model);
+               }
+               
+               /**
+                * Sets the data model that the <code>JComboBox</code> uses to obtain the list of items.
+                *
+                * @param aModel the <code>ComboBoxModel</code> that provides the displayed list of items
+                *
+                * @beaninfo bound: true description: Model that the combo box uses to get data to display.
+                */
+               @Override
+               public void setModel(final ComboBoxModel aModel) {
+                       if (getModel() instanceof MaterialModel) {
+                               MaterialModel old = (MaterialModel) getModel();
+                               old.removeListener();
+                       }
+                       super.setModel(aModel);
+                       
+               }
+       }
 }
index 4ee74ba4e83edfc75245c9020ecaf00e26d9ba84..2e78d8da0fc146ed0f1946673421438367d218c8 100644 (file)
@@ -348,6 +348,26 @@ public class GUIUtil {
        }
        
        
+       public static void setAutomaticColumnTableWidths(JTable table, int max) {
+               int columns = table.getColumnCount();
+               int widths[] = new int[columns];
+               Arrays.fill(widths, 1);
+               
+               for (int row = 0; row < table.getRowCount(); row++) {
+                       for (int col = 0; col < columns; col++) {
+                               Object value = table.getValueAt(row, col);
+                               System.out.println("row=" + row + " col=" + col + " : " + value);
+                               widths[col] = Math.max(widths[col], value == null ? 0 : value.toString().length());
+                       }
+               }
+               
+               
+               for (int col = 0; col < columns; col++) {
+                       System.err.println("Setting column " + col + " to width " + widths[col]);
+                       table.getColumnModel().getColumn(col).setPreferredWidth(Math.min(widths[col], max) * 100);
+               }
+       }
+       
        /**
         * Changes the style of the font of the specified border.
         * 
index b202ff4e881f141f608921c5a17a37e91038989d..0fa2b67c57ad55f59ec6c75262fb56b60b502d61 100644 (file)
@@ -77,6 +77,9 @@ public class Icons {
        public static final Icon UP = loadImageIcon("pix/icons/up.png", "Up");
        public static final Icon DOWN = loadImageIcon("pix/icons/down.png", "Down");
        
+       public static final Icon NOT_FAVORITE = loadImageIcon("pix/icons/star_silver.png", "Not favorite");
+       public static final Icon FAVORITE = loadImageIcon("pix/icons/star_gold.png", "Favorite");
+       
        
        static {
                log.debug("Icons loaded");
index 12331495df47421e22aafa98ad6cca98ea1c76e3..28afb30db9f83b94924b8bddc6c3d5ecdadf4ae9 100644 (file)
@@ -1,13 +1,5 @@
 package net.sf.openrocket.preset;
 
-import net.sf.openrocket.material.Material;
-import net.sf.openrocket.motor.Manufacturer;
-import net.sf.openrocket.rocketcomponent.ExternalComponent.Finish;
-import net.sf.openrocket.rocketcomponent.Transition.Shape;
-import net.sf.openrocket.unit.UnitGroup;
-import net.sf.openrocket.util.BugException;
-import net.sf.openrocket.util.TextUtil;
-
 import java.io.ByteArrayOutputStream;
 import java.io.DataOutputStream;
 import java.security.MessageDigest;
@@ -19,6 +11,14 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
+import net.sf.openrocket.material.Material;
+import net.sf.openrocket.motor.Manufacturer;
+import net.sf.openrocket.rocketcomponent.ExternalComponent.Finish;
+import net.sf.openrocket.rocketcomponent.Transition.Shape;
+import net.sf.openrocket.unit.UnitGroup;
+import net.sf.openrocket.util.BugException;
+import net.sf.openrocket.util.TextUtil;
+
 
 /**
  * A model for a preset component.
@@ -30,32 +30,32 @@ import java.util.Map;
  */
 // FIXME - Implement clone.
 public class ComponentPreset implements Comparable<ComponentPreset> {
-
+       
        private final TypedPropertyMap properties = new TypedPropertyMap();
-
+       
        private boolean favorite = false;
        private String digest = "";
-
+       
        public enum Type {
-               BODY_TUBE( new TypedKey<?>[] {
+               BODY_TUBE(new TypedKey<?>[] {
                                ComponentPreset.MANUFACTURER,
                                ComponentPreset.PARTNO,
                                ComponentPreset.DESCRIPTION,
                                ComponentPreset.INNER_DIAMETER,
                                ComponentPreset.OUTER_DIAMETER,
-                               ComponentPreset.LENGTH),
-
-               NOSE_CONE( new TypedKey<?>[] {
+                               ComponentPreset.LENGTH }),
+               
+               NOSE_CONE(new TypedKey<?>[] {
                                ComponentPreset.MANUFACTURER,
                                ComponentPreset.PARTNO,
                                ComponentPreset.DESCRIPTION,
                                ComponentPreset.SHAPE,
                                ComponentPreset.AFT_OUTER_DIAMETER,
                                ComponentPreset.AFT_SHOULDER_DIAMETER,
-                ComponentPreset.AFT_SHOULDER_LENGTH,
-                               ComponentPreset.LENGTH),
-
-               TRANSITION( new TypedKey<?>[] {
+                               ComponentPreset.AFT_SHOULDER_LENGTH,
+                               ComponentPreset.LENGTH }),
+               
+               TRANSITION(new TypedKey<?>[] {
                                ComponentPreset.MANUFACTURER,
                                ComponentPreset.PARTNO,
                                ComponentPreset.DESCRIPTION,
@@ -66,106 +66,106 @@ public class ComponentPreset implements Comparable<ComponentPreset> {
                                ComponentPreset.AFT_OUTER_DIAMETER,
                                ComponentPreset.AFT_SHOULDER_DIAMETER,
                                ComponentPreset.AFT_SHOULDER_LENGTH,
-                               ComponentPreset.LENGTH),
-
-               TUBE_COUPLER( new TypedKey<?>[] {
+                               ComponentPreset.LENGTH }),
+               
+               TUBE_COUPLER(new TypedKey<?>[] {
                                ComponentPreset.MANUFACTURER,
                                ComponentPreset.PARTNO,
-                ComponentPreset.DESCRIPTION,
+                               ComponentPreset.DESCRIPTION,
                                ComponentPreset.OUTER_DIAMETER,
                                ComponentPreset.INNER_DIAMETER,
-                               ComponentPreset.LENGTH),
-
-               BULK_HEAD( new TypedKey<?>[] {
+                               ComponentPreset.LENGTH }),
+               
+               BULK_HEAD(new TypedKey<?>[] {
                                ComponentPreset.MANUFACTURER,
                                ComponentPreset.PARTNO,
                                ComponentPreset.DESCRIPTION,
                                ComponentPreset.OUTER_DIAMETER,
-                               ComponentPreset.LENGTH),
-
-               CENTERING_RING( new TypedKey<?>[] {
+                               ComponentPreset.LENGTH }),
+               
+               CENTERING_RING(new TypedKey<?>[] {
                                ComponentPreset.MANUFACTURER,
                                ComponentPreset.PARTNO,
                                ComponentPreset.DESCRIPTION,
                                ComponentPreset.INNER_DIAMETER,
                                ComponentPreset.OUTER_DIAMETER,
-                               ComponentPreset.LENGTH),
-
-               ENGINE_BLOCK( new TypedKey<?>[] {
+                               ComponentPreset.LENGTH }),
+               
+               ENGINE_BLOCK(new TypedKey<?>[] {
                                ComponentPreset.MANUFACTURER,
                                ComponentPreset.PARTNO,
                                ComponentPreset.DESCRIPTION,
                                ComponentPreset.INNER_DIAMETER,
                                ComponentPreset.OUTER_DIAMETER,
-                               ComponentPreset.LENGTH),
-
-               LAUNCH_LUG( new TypedKey<?>[] {
+                               ComponentPreset.LENGTH }),
+               
+               LAUNCH_LUG(new TypedKey<?>[] {
                                ComponentPreset.MANUFACTURER,
                                ComponentPreset.PARTNO,
                                ComponentPreset.DESCRIPTION,
                                ComponentPreset.INNER_DIAMETER,
                                ComponentPreset.OUTER_DIAMETER,
-                               ComponentPreset.LENGTH),
-
-               STREAMER( new TypedKey<?>[] {
+                               ComponentPreset.LENGTH }),
+               
+               STREAMER(new TypedKey<?>[] {
                                ComponentPreset.MANUFACTURER,
                                ComponentPreset.PARTNO,
-                ComponentPreset.DESCRIPTION,
+                               ComponentPreset.DESCRIPTION,
                                ComponentPreset.LENGTH,
                                ComponentPreset.WIDTH,
                                ComponentPreset.THICKNESS,
-                               ComponentPreset.MATERIAL),
-
-               PARACHUTE( new TypedKey<?>[] {
+                               ComponentPreset.MATERIAL }),
+               
+               PARACHUTE(new TypedKey<?>[] {
                                ComponentPreset.MANUFACTURER,
                                ComponentPreset.PARTNO,
-                ComponentPreset.DESCRIPTION,
+                               ComponentPreset.DESCRIPTION,
                                ComponentPreset.DIAMETER,
                                ComponentPreset.SIDES,
                                ComponentPreset.LINE_COUNT,
                                ComponentPreset.LINE_LENGTH,
                                ComponentPreset.LINE_MATERIAL,
-                               ComponentPreset.MATERIAL);
-
+                               ComponentPreset.MATERIAL });
+               
                TypedKey<?>[] displayedColumns;
-
-               Type( TypedKey<?>[] displayedColumns) {
+               
+               Type(TypedKey<?>[] displayedColumns) {
                        this.displayedColumns = displayedColumns;
                }
-
+               
                public List<Type> getCompatibleTypes() {
                        return compatibleTypeMap.get(Type.this);
                }
-
+               
                public TypedKey<?>[] getDisplayedColumns() {
                        return displayedColumns;
                }
-
-               private static Map<Type,List<Type>> compatibleTypeMap = new HashMap<Type,List<Type>>();
-
+               
+               private static Map<Type, List<Type>> compatibleTypeMap = new HashMap<Type, List<Type>>();
+               
                static {
-                       compatibleTypeMap.put( BODY_TUBE, Arrays.asList( BODY_TUBE, TUBE_COUPLER, LAUNCH_LUG ) );
-                       compatibleTypeMap.put( TUBE_COUPLER, Arrays.asList( BODY_TUBE,TUBE_COUPLER, LAUNCH_LUG ) );
-                       compatibleTypeMap.put( LAUNCH_LUG, Arrays.asList( BODY_TUBE,TUBE_COUPLER, LAUNCH_LUG ) );
-                       compatibleTypeMap.put( CENTERING_RING, Arrays.asList( CENTERING_RING, ENGINE_BLOCK ) );
-                       compatibleTypeMap.put( NOSE_CONE, Arrays.asList( NOSE_CONE, TRANSITION));
+                       compatibleTypeMap.put(BODY_TUBE, Arrays.asList(BODY_TUBE, TUBE_COUPLER, LAUNCH_LUG));
+                       compatibleTypeMap.put(TUBE_COUPLER, Arrays.asList(BODY_TUBE, TUBE_COUPLER, LAUNCH_LUG));
+                       compatibleTypeMap.put(LAUNCH_LUG, Arrays.asList(BODY_TUBE, TUBE_COUPLER, LAUNCH_LUG));
+                       compatibleTypeMap.put(CENTERING_RING, Arrays.asList(CENTERING_RING, ENGINE_BLOCK));
+                       compatibleTypeMap.put(NOSE_CONE, Arrays.asList(NOSE_CONE, TRANSITION));
                }
-
+               
        }
-
+       
        public final static TypedKey<Manufacturer> MANUFACTURER = new TypedKey<Manufacturer>("Manufacturer", Manufacturer.class);
-       public final static TypedKey<String> PARTNO = new TypedKey<String>("PartNo",String.class);
+       public final static TypedKey<String> PARTNO = new TypedKey<String>("PartNo", String.class);
        public final static TypedKey<String> DESCRIPTION = new TypedKey<String>("Description", String.class);
-       public final static TypedKey<Type> TYPE = new TypedKey<Type>("Type",Type.class);
+       public final static TypedKey<Type> TYPE = new TypedKey<Type>("Type", Type.class);
        public final static TypedKey<Double> LENGTH = new TypedKey<Double>("Length", Double.class, UnitGroup.UNITS_LENGTH);
        public final static TypedKey<Double> WIDTH = new TypedKey<Double>("Width", Double.class, UnitGroup.UNITS_LENGTH);
        public final static TypedKey<Double> INNER_DIAMETER = new TypedKey<Double>("InnerDiameter", Double.class, UnitGroup.UNITS_LENGTH);
        public final static TypedKey<Double> OUTER_DIAMETER = new TypedKey<Double>("OuterDiameter", Double.class, UnitGroup.UNITS_LENGTH);
-       public final static TypedKey<Double> FORE_SHOULDER_LENGTH = new TypedKey<Double>("ForeShoulderLength",Double.class, UnitGroup.UNITS_LENGTH);
-       public final static TypedKey<Double> FORE_SHOULDER_DIAMETER = new TypedKey<Double>("ForeShoulderDiameter",Double.class, UnitGroup.UNITS_LENGTH);
+       public final static TypedKey<Double> FORE_SHOULDER_LENGTH = new TypedKey<Double>("ForeShoulderLength", Double.class, UnitGroup.UNITS_LENGTH);
+       public final static TypedKey<Double> FORE_SHOULDER_DIAMETER = new TypedKey<Double>("ForeShoulderDiameter", Double.class, UnitGroup.UNITS_LENGTH);
        public final static TypedKey<Double> FORE_OUTER_DIAMETER = new TypedKey<Double>("ForeOuterDiameter", Double.class, UnitGroup.UNITS_LENGTH);
-       public final static TypedKey<Double> AFT_SHOULDER_LENGTH = new TypedKey<Double>("AftShoulderLength",Double.class, UnitGroup.UNITS_LENGTH);
-       public final static TypedKey<Double> AFT_SHOULDER_DIAMETER = new TypedKey<Double>("AftShoulderDiameter",Double.class, UnitGroup.UNITS_LENGTH);
+       public final static TypedKey<Double> AFT_SHOULDER_LENGTH = new TypedKey<Double>("AftShoulderLength", Double.class, UnitGroup.UNITS_LENGTH);
+       public final static TypedKey<Double> AFT_SHOULDER_DIAMETER = new TypedKey<Double>("AftShoulderDiameter", Double.class, UnitGroup.UNITS_LENGTH);
        public final static TypedKey<Double> AFT_OUTER_DIAMETER = new TypedKey<Double>("AftOuterDiameter", Double.class, UnitGroup.UNITS_LENGTH);
        public final static TypedKey<Shape> SHAPE = new TypedKey<Shape>("Shape", Shape.class);
        public final static TypedKey<Material> MATERIAL = new TypedKey<Material>("Material", Material.class);
@@ -178,9 +178,9 @@ public class ComponentPreset implements Comparable<ComponentPreset> {
        public final static TypedKey<Integer> LINE_COUNT = new TypedKey<Integer>("LineCount", Integer.class);
        public final static TypedKey<Double> LINE_LENGTH = new TypedKey<Double>("LineLength", Double.class, UnitGroup.UNITS_LENGTH);
        public final static TypedKey<Material> LINE_MATERIAL = new TypedKey<Material>("LineMaterial", Material.class);
-    public final static TypedKey<byte[]> IMAGE = new TypedKey<byte[]>("Image", byte[].class);
-
-       public final static List<TypedKey<?>> orderedKeyList = Arrays.<TypedKey<?>>asList(
+       public final static TypedKey<byte[]> IMAGE = new TypedKey<byte[]>("Image", byte[].class);
+       
+       public final static List<TypedKey<?>> ORDERED_KEY_LIST = Collections.unmodifiableList(Arrays.<TypedKey<?>> asList(
                        MANUFACTURER,
                        PARTNO,
                        DESCRIPTION,
@@ -205,13 +205,13 @@ public class ComponentPreset implements Comparable<ComponentPreset> {
                        MASS,
                        FINISH,
                        MATERIAL
-                       );
-
-
+                       ));
+       
+       
        // package scope constructor to encourage use of factory.
        ComponentPreset() {
        }
-
+       
        /**
         * Convenience method to retrieve the Type of this ComponentPreset.
         *
@@ -220,7 +220,7 @@ public class ComponentPreset implements Comparable<ComponentPreset> {
        public Type getType() {
                return properties.get(TYPE);
        }
-
+       
        /**
         * Convenience method to retrieve the Manufacturer of this ComponentPreset.
         * @return
@@ -228,7 +228,7 @@ public class ComponentPreset implements Comparable<ComponentPreset> {
        public Manufacturer getManufacturer() {
                return properties.get(MANUFACTURER);
        }
-
+       
        /**
         * Convenience method to retrieve the PartNo of this ComponentPreset.
         * @return
@@ -236,15 +236,15 @@ public class ComponentPreset implements Comparable<ComponentPreset> {
        public String getPartNo() {
                return properties.get(PARTNO);
        }
-
+       
        public String getDigest() {
                return digest;
        }
-
+       
        public boolean has(Object key) {
                return properties.containsKey(key);
        }
-
+       
        /**
         * Package scope so the ComponentPresetFactory can call it.
         * @param other
@@ -255,134 +255,133 @@ public class ComponentPreset implements Comparable<ComponentPreset> {
                }
                properties.putAll(other);
        }
-
+       
        /**
         * Package scope so the ComponentPresetFactory can call it.
         * @param key
         * @param value
         */
-       <T> void put( TypedKey<T> key, T value ) {
+       <T> void put(TypedKey<T> key, T value) {
                properties.put(key, value);
        }
-
+       
        public <T> T get(TypedKey<T> key) {
                T value = properties.get(key);
                if (value == null) {
                        throw new BugException("Preset did not contain key " + key + " " + properties.toString());
                }
-               return (T) value;
+               return value;
        }
-
+       
        public boolean isFavorite() {
                return favorite;
        }
-
+       
        public void setFavorite(boolean favorite) {
                this.favorite = favorite;
        }
-
+       
        @Override
        public int compareTo(ComponentPreset p2) {
                int manuCompare = this.getManufacturer().getSimpleName().compareTo(p2.getManufacturer().getSimpleName());
-               if ( manuCompare != 0 )
+               if (manuCompare != 0)
                        return manuCompare;
-
+               
                int partNoCompare = this.getPartNo().compareTo(p2.getPartNo());
                return partNoCompare;
        }
-
+       
        @Override
        public String toString() {
-               return get(MANUFACTURER).toString() + " " + get(PARTNO);
+               return get(PARTNO);
        }
-
+       
        public String preferenceKey() {
                return get(MANUFACTURER).toString() + "|" + get(PARTNO);
        }
-
-    @Override
-    public boolean equals(final Object o) {
-        if (this == o) {
-            return true;
-        }
-        if (o == null || getClass() != o.getClass()) {
-            return false;
-        }
-
-        ComponentPreset that = (ComponentPreset) o;
-
-        if (digest != null ? !digest.equals(that.digest) : that.digest != null) {
-            return false;
-        }
-
-        return true;
-    }
-
-    @Override
-    public int hashCode() {
-        return digest != null ? digest.hashCode() : 0;
-    }
-
-    /**
+       
+       @Override
+       public boolean equals(final Object o) {
+               if (this == o) {
+                       return true;
+               }
+               if (o == null || getClass() != o.getClass()) {
+                       return false;
+               }
+               
+               ComponentPreset that = (ComponentPreset) o;
+               
+               if (digest != null ? !digest.equals(that.digest) : that.digest != null) {
+                       return false;
+               }
+               
+               return true;
+       }
+       
+       @Override
+       public int hashCode() {
+               return digest != null ? digest.hashCode() : 0;
+       }
+       
+       /**
         * Package scope so the factory can call it.
         */
        void computeDigest() {
-
+               
                try {
                        ByteArrayOutputStream bos = new ByteArrayOutputStream();
                        DataOutputStream os = new DataOutputStream(bos);
-
-                       List<TypedKey<?>> keys = new ArrayList<TypedKey<?>>( properties.keySet());
-
+                       
+                       List<TypedKey<?>> keys = new ArrayList<TypedKey<?>>(properties.keySet());
+                       
                        Collections.sort(keys, new Comparator<TypedKey<?>>() {
                                @Override
-                               public int compare( TypedKey<?> a, TypedKey<?> b ) {
+                               public int compare(TypedKey<?> a, TypedKey<?> b) {
                                        return a.getName().compareTo(b.getName());
                                }
                        });
-
-                       for ( TypedKey<?> key : keys  ) {
-
+                       
+                       for (TypedKey<?> key : keys) {
+                               
                                Object value = properties.get(key);
-
+                               
                                os.writeBytes(key.getName());
-
-                               if ( key.getType() == Double.class ) {
+                               
+                               if (key.getType() == Double.class) {
                                        Double d = (Double) value;
                                        os.writeDouble(d);
-                               } else if (key.getType() == String.class ) {
+                               } else if (key.getType() == String.class) {
                                        String s = (String) value;
                                        os.writeBytes(s);
-                               } else if (key.getType() == Manufacturer.class ) {
-                                       String s = ((Manufacturer)value).getSimpleName();
+                               } else if (key.getType() == Manufacturer.class) {
+                                       String s = ((Manufacturer) value).getSimpleName();
                                        os.writeBytes(s);
-                               } else if ( key.getType() == Finish.class ) {
-                                       String s = ((Finish)value).name();
+                               } else if (key.getType() == Finish.class) {
+                                       String s = ((Finish) value).name();
                                        os.writeBytes(s);
-                               } else if ( key.getType() == Type.class ) {
-                                       String s = ((Type)value).name();
+                               } else if (key.getType() == Type.class) {
+                                       String s = ((Type) value).name();
                                        os.writeBytes(s);
-                               } else if ( key.getType() == Boolean.class ) {
+                               } else if (key.getType() == Boolean.class) {
                                        Boolean b = (Boolean) value;
                                        os.writeBoolean(b);
-                               } else if ( key.getType() == Material.class ) {
-                                       double d = ((Material)value).getDensity();
+                               } else if (key.getType() == Material.class) {
+                                       double d = ((Material) value).getDensity();
                                        os.writeDouble(d);
-                               } else if ( key.getType() == Shape.class ) {
+                               } else if (key.getType() == Shape.class) {
                                        // this is ugly to use the ordinal but what else?
-                                       int i = ((Shape)value).ordinal();
+                                       int i = ((Shape) value).ordinal();
                                        os.writeInt(i);
                                }
-
+                               
                        }
-
+                       
                        MessageDigest md5 = MessageDigest.getInstance("MD5");
-                       digest = TextUtil.hexString(md5.digest( bos.toByteArray() ));
-               }
-               catch ( Exception e ) {
-            e.printStackTrace();
+                       digest = TextUtil.hexString(md5.digest(bos.toByteArray()));
+               } catch (Exception e) {
+                       e.printStackTrace();
                        throw new BugException(e);
                }
        }
-
+       
 }
index 49c139b0bbf1a06416e0c1bf36463f2b4cac45e1..81e5a63d820cb07ec637541cec69d0eafc0f0150 100644 (file)
@@ -40,6 +40,27 @@ public class MassComponent extends MassObject {
        }
        
        
+       public double getDensity() {
+               double d = getComponentMass() / getVolume();
+               if (Double.isNaN(d))
+                       d = 0;
+               return d;
+       }
+       
+       public void setDensity(double density) {
+               double m = density * getVolume();
+               m = MathUtil.clamp(m, 0, 1000000);
+               if (Double.isNaN(m))
+                       m = 0;
+               setComponentMass(m);
+       }
+       
+       
+       private double getVolume() {
+               return Math.PI * MathUtil.pow2(getRadius()) * getLength();
+       }
+       
+       
        @Override
        public String getComponentName() {
                //// Mass component
index 2cbc2cf64f6466dcadc34f5c7181ed21eae98cee..740e4776d0b5ba73489c10335337bc204088b85a 100644 (file)
@@ -4,91 +4,93 @@ import java.text.DecimalFormat;
 import java.text.NumberFormat;
 import java.util.ArrayList;
 
-public class FractionalUnit extends Unit {
+import net.sf.openrocket.util.Chars;
 
-       private final static String fraction = "\u2044";
-       
-       private final static String[] numerator = {
-               "\u2070",  // 0
-               "\u00B9",  // 1
-               "\u00B2",  // 2
-               "\u00B3",  // 3
-               "\u2074",  // 4
-               "\u2075",  // 5
-               "\u2076",  // 6
-               "\u2077",  // 7
-               "\u2078",  // 8
-               "\u2079"   // 9
+public class FractionalUnit extends Unit {
+       
+       private final static char FRACTION = Chars.FRACTION;
+       
+       private final static String[] NUMERATOR = {
+                       "\u2070", // 0
+                       "\u00B9", // 1
+                       "\u00B2", // 2
+                       "\u00B3", // 3
+                       "\u2074", // 4
+                       "\u2075", // 5
+                       "\u2076", // 6
+                       "\u2077", // 7
+                       "\u2078", // 8
+                       "\u2079" // 9
        };
        
-       private final static String[] denominator = {
-               "\u2080",  // 0
-               "\u2081",  // 1
-               "\u2082",  // 2
-               "\u2083",  // 3
-               "\u2084",  // 4
-               "\u2085",  // 5
-               "\u2086",  // 6
-               "\u2087",  // 7
-               "\u2088",  // 8
-               "\u2089"   // 9
+       private final static String[] DENOMINATOR = {
+                       "\u2080", // 0
+                       "\u2081", // 1
+                       "\u2082", // 2
+                       "\u2083", // 3
+                       "\u2084", // 4
+                       "\u2085", // 5
+                       "\u2086", // 6
+                       "\u2087", // 7
+                       "\u2088", // 8
+                       "\u2089" // 9
        };
        
        // This is the base of the fractions.  ie, 16d for 1/16ths.
        private final int fractionBase;
        // This is 1d/fractionBase;
        private final double fractionValue;
-
+       
        // This is the value used when incrementing/decrementing.
        private final double incrementValue;
-
+       
        // If the actual value differs from the decimal representation by more than this,
        // we display as decimals.
        private final double epsilon;
-
+       
        private final String unitLabel;
-
+       
        public FractionalUnit(double multiplier, String unit, String unitLabel, int fractionBase, double incrementValue) {
-               this( multiplier, unit, unitLabel, fractionBase, incrementValue, 0.1d/fractionBase);
+               this(multiplier, unit, unitLabel, fractionBase, incrementValue, 0.1d / fractionBase);
        }
-
+       
        public FractionalUnit(double multiplier, String unit, String unitLabel, int fractionBase, double incrementValue, double epsilon) {
                super(multiplier, unit);
                this.unitLabel = unitLabel;
                this.fractionBase = fractionBase;
-               this.fractionValue = 1.0d/fractionBase;
+               this.fractionValue = 1.0d / fractionBase;
                this.incrementValue = incrementValue;
                this.epsilon = epsilon;
        }
-
+       
        @Override
        public double round(double value) {
-               return roundTo( value, fractionValue );
+               return roundTo(value, fractionValue);
        }
-
-       private double roundTo( double value, double fraction ) {
-               double remainder = Math.IEEEremainder( value, fraction );
+       
+       private double roundTo(double value, double fraction) {
+               double remainder = Math.IEEEremainder(value, fraction);
                return value - remainder;
        }
-
+       
        @Override
        public double getNextValue(double value) {
                double rounded = roundTo(value, incrementValue);
-               if ( rounded <= value + epsilon) {
+               if (rounded <= value + epsilon) {
                        rounded += incrementValue;
                }
                return rounded;
        }
-
+       
        @Override
        public double getPreviousValue(double value) {
                double rounded = roundTo(value, incrementValue);
-               if ( rounded >= value - epsilon ) {
+               if (rounded >= value - epsilon) {
                        rounded -= incrementValue;
                }
                return rounded;
        }
-
+       
        @Override
        public Tick[] getTicks(double start, double end, double minor, double major) {
                // Convert values
@@ -96,148 +98,148 @@ public class FractionalUnit extends Unit {
                end = toUnit(end);
                minor = toUnit(minor);
                major = toUnit(major);
-
+               
                if (minor <= 0 || major <= 0 || major < minor) {
-                       throw new IllegalArgumentException("getTicks called with minor="+minor+" major="+major);
+                       throw new IllegalArgumentException("getTicks called with minor=" + minor + " major=" + major);
                }
-
+               
                ArrayList<Tick> ticks = new ArrayList<Tick>();
-
-               int mod2,mod3,mod4;  // Moduli for minor-notable, major-nonnotable, major-notable
+               
+               int mod2, mod3, mod4; // Moduli for minor-notable, major-nonnotable, major-notable
                double minstep;
-
+               
                // Find the smallest possible step size
-               double one=1;
+               double one = 1;
                while (one > minor)
                        one /= 2;
                while (one < minor)
                        one *= 2;
                minstep = one;
                mod2 = 16;
-
+               
                // Find step size for major ticks
                one = 1;
                while (one > major)
                        one /= 10;
                while (one < major)
                        one *= 10;
-               if (one/2 >= major) {
+               if (one / 2 >= major) {
                        // major step is round-five, major-notable is next round-ten
-                       double majorstep = one/2;
-                       mod3 = (int)Math.round(majorstep/minstep);
-                       mod4 = mod3*2;
+                       double majorstep = one / 2;
+                       mod3 = (int) Math.round(majorstep / minstep);
+                       mod4 = mod3 * 2;
                } else {
                        // major step is round-ten, major-notable is next round-ten
-                       mod3 = (int)Math.round(one/minstep);
-                       mod4 = mod3*10;
+                       mod3 = (int) Math.round(one / minstep);
+                       mod4 = mod3 * 10;
                }
                // Check for clashes between minor-notable and major-nonnotable
                if (mod3 == mod2) {
-                       if (mod2==2)
-                               mod2 = 1;  // Every minor tick is notable
+                       if (mod2 == 2)
+                               mod2 = 1; // Every minor tick is notable
                        else
-                               mod2 = 5;  // Every fifth minor tick is notable
+                               mod2 = 5; // Every fifth minor tick is notable
                }
-
-
+               
+               
                // Calculate starting position
-               int pos = (int)Math.ceil(start/minstep);
+               int pos = (int) Math.ceil(start / minstep);
                //              System.out.println("mod2="+mod2+" mod3="+mod3+" mod4="+mod4);
-               while (pos*minstep <= end) {
-                       double unitValue = pos*minstep;
+               while (pos * minstep <= end) {
+                       double unitValue = pos * minstep;
                        double value = fromUnit(unitValue);
-
-                       if (pos%mod4 == 0)
-                               ticks.add(new Tick(value,unitValue,true,true));
-                       else if (pos%mod3 == 0)
-                               ticks.add(new Tick(value,unitValue,true,false));
-                       else if (pos%mod2 == 0)
-                               ticks.add(new Tick(value,unitValue,false,true));
+                       
+                       if (pos % mod4 == 0)
+                               ticks.add(new Tick(value, unitValue, true, true));
+                       else if (pos % mod3 == 0)
+                               ticks.add(new Tick(value, unitValue, true, false));
+                       else if (pos % mod2 == 0)
+                               ticks.add(new Tick(value, unitValue, false, true));
                        else
-                               ticks.add(new Tick(value,unitValue,false,false));
-
+                               ticks.add(new Tick(value, unitValue, false, false));
+                       
                        pos++;
                }
-
+               
                return ticks.toArray(new Tick[0]);
        }
-
-
+       
+       
        @Override
        public String toString(double value) {
-
+               
                double correctVal = toUnit(value);
                double val = round(correctVal);
-
-
-               if ( Math.abs( val - correctVal ) > epsilon ) {
+               
+               
+               if (Math.abs(val - correctVal) > epsilon) {
                        NumberFormat decFormat = new DecimalFormat("#.###");
                        return decFormat.format(correctVal);
                }
-
+               
                NumberFormat intFormat = new DecimalFormat("#");
                double sign = Math.signum(val);
-
+               
                double posValue = sign * val;
-
+               
                double intPart = Math.floor(posValue);
-
-               double frac = Math.rint((posValue - intPart)/fractionValue);
+               
+               double frac = Math.rint((posValue - intPart) / fractionValue);
                double fracBase = fractionBase;
-
+               
                // Reduce fraction.
-               while ( frac > 0 && fracBase > 2 && frac % 2 == 0 ) {
+               while (frac > 0 && fracBase > 2 && frac % 2 == 0) {
                        frac /= 2.0;
                        fracBase /= 2.0;
                }
-
+               
                posValue *= sign;
-
-               if ( frac == 0.0 )  {
+               
+               if (frac == 0.0) {
                        return intFormat.format(posValue);
-               } else if (intPart == 0.0 ){
-                       return (sign <0 ? "-" : "" ) + numeratorString(Double.valueOf(frac).intValue()) 
-                                       + fraction + denominatorString(Double.valueOf(fracBase).intValue());
+               } else if (intPart == 0.0{
+                       return (sign < 0 ? "-" : "") + numeratorString(Double.valueOf(frac).intValue())
+                                       + FRACTION + denominatorString(Double.valueOf(fracBase).intValue());
                } else {
-                       return intFormat.format(sign*intPart) + " " + numeratorString(Double.valueOf(frac).intValue())
-                                       + fraction + denominatorString(Double.valueOf(fracBase).intValue());
+                       return intFormat.format(sign * intPart) + " " + numeratorString(Double.valueOf(frac).intValue())
+                                       + FRACTION + denominatorString(Double.valueOf(fracBase).intValue());
                }
-
+               
        }
        
-       private String numeratorString( int value ) {
-
+       private String numeratorString(int value) {
+               
                String rep = "";
-               if ( value == 0 ) {
+               if (value == 0) {
                        return "0";
                }
-               while ( value > 0 ) {
-                       rep = numerator[ value % 10 ] + rep;
-                       value = value /10;
+               while (value > 0) {
+                       rep = NUMERATOR[value % 10] + rep;
+                       value = value / 10;
                }
                return rep;
        }
        
-       private String denominatorString( int value ) {
+       private String denominatorString(int value) {
                String rep = "";
-               if ( value == 0 ) {
+               if (value == 0) {
                        return "0";
                }
-               while ( value > 0 ) {
-                       rep = denominator[ value % 10 ] + rep;
-                       value = value /10;
+               while (value > 0) {
+                       rep = DENOMINATOR[value % 10] + rep;
+                       value = value / 10;
                }
                return rep;
        }
-
+       
        @Override
        public String toStringUnit(double value) {
                if (Double.isNaN(value))
                        return "N/A";
-
+               
                String s = toString(value);
                s += " " + unitLabel;
                return s;
        }
-
+       
 }
index 75774dc1c3d1d4eeba29ca7746cd5a445d2b11cb..88ab4a77fd11be5f57ed0a6d49bed6fb69373e10 100644 (file)
@@ -85,7 +85,7 @@ public class UnitGroup {
                UNITS_LENGTH.addUnit(new GeneralUnit(0.01, "cm"));
                UNITS_LENGTH.addUnit(new GeneralUnit(1, "m"));
                UNITS_LENGTH.addUnit(new GeneralUnit(0.0254, "in"));
-               UNITS_LENGTH.addUnit(new FractionalUnit(0.0254, "in/64", "in", 64, 1d/16d, 0.5d/64d));
+               UNITS_LENGTH.addUnit(new FractionalUnit(0.0254, "in/64", "in", 64, 1d / 16d, 0.5d / 64d));
                UNITS_LENGTH.addUnit(new GeneralUnit(0.3048, "ft"));
                UNITS_LENGTH.setDefaultUnit(1);
                
@@ -162,6 +162,7 @@ public class UnitGroup {
                
                UNITS_DENSITY_BULK = new UnitGroup();
                UNITS_DENSITY_BULK.addUnit(new GeneralUnit(1000, "g/cm" + CUBED));
+               UNITS_DENSITY_BULK.addUnit(new GeneralUnit(1000, "kg/dm" + CUBED));
                UNITS_DENSITY_BULK.addUnit(new GeneralUnit(1, "kg/m" + CUBED));
                UNITS_DENSITY_BULK.addUnit(new GeneralUnit(1729.99404, "oz/in" + CUBED));
                UNITS_DENSITY_BULK.addUnit(new GeneralUnit(16.0184634, "lb/ft" + CUBED));
@@ -429,7 +430,7 @@ public class UnitGroup {
                throw new IllegalArgumentException("name=" + name);
        }
        
-       public Unit getUnit( String name ) throws IllegalArgumentException {
+       public Unit getUnit(String name) throws IllegalArgumentException {
                for (int i = 0; i < units.size(); i++) {
                        if (units.get(i).getUnit().equals(name)) {
                                return units.get(i);
index eeba22bcaf2ae7daff79ce9d8d4e4387ba942992..1b2857a2b7cd1d1ed2a29d42467ffb245eb512df 100644 (file)
@@ -13,6 +13,8 @@ public class Chars {
        public static final char FRAC14 = '\u00BC';
        /** The fraction 3/4 */
        public static final char FRAC34 = '\u00BE';
+       /** Fraction slash */
+       public static final char FRACTION = '\u2044';
        
        /** Degree sign */
        public static final char DEGREE = '\u00B0';
index a309fddd01a7548c1582302c6076cef413ef1778..b180f61928cad3c18f64084ee41e7c33058aff93 100644 (file)
@@ -1,48 +1,67 @@
 package net.sf.openrocket.util;
 
+import java.text.DecimalFormatSymbols;
+
+import net.sf.openrocket.logging.LogHelper;
+import net.sf.openrocket.startup.Application;
 import de.congrace.exp4j.Calculable;
 import de.congrace.exp4j.ExpressionBuilder;
-import de.congrace.exp4j.UnknownFunctionException;
-import de.congrace.exp4j.UnparsableExpressionException;
 
 public class ExpressionParser {
+       private static final LogHelper log = Application.getLogger();
        
+       private static final char DECIMAL_SEPARATOR;
+       private static final char MINUS_SIGN;
+       static {
+               DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance();
+               DECIMAL_SEPARATOR = symbols.getDecimalSeparator();
+               MINUS_SIGN = symbols.getMinusSign();
+       }
        
        public double parse(String expression) throws InvalidExpressionException {
+               
+               String modified = null;
                try {
-                       ExpressionBuilder builder = new ExpressionBuilder(modify(expression));
+                       modified = modify(expression);
+                       ExpressionBuilder builder = new ExpressionBuilder(modified);
                        Calculable calc = builder.build();
-                       return calc.calculate();
-               } catch (java.lang.NumberFormatException e) {
-                       throw new InvalidExpressionException("Invalid expression: " + expression, e);
-               } catch (UnknownFunctionException e) {
-                       throw new InvalidExpressionException("Invalid expression: " + expression, e);
-               } catch (UnparsableExpressionException e) {
-                       throw new InvalidExpressionException("Invalid expression: " + expression, e);
-               } catch (java.util.EmptyStackException e) {
+                       double n = calc.calculate();
+                       log.debug("Evaluated expression '" + expression + "' (modified='" + modified + "') to " + n);
+                       return n;
+               } catch (Exception e) {
+                       log.warn("Unable to parse expression '" + expression + "' (modified='" + modified + "')", e);
                        throw new InvalidExpressionException("Invalid expression: " + expression, e);
                }
        }
        
        private String modify(String exp) throws InvalidExpressionException {
+               
+               // Normalize digit equivalents, fraction sign, decimal separators and minus sign
                char[] chars = exp.toCharArray();
-               for( int i = 0; i< chars.length; i++ ) {
+               for (int i = 0; i < chars.length; i++) {
                        int value = Character.getNumericValue(chars[i]);
-                       if ( value >= 0 && value < 10 ) {
+                       if (value >= 0 && value < 10) {
                                chars[i] = Character.toChars(48 + value)[0];
                        }
-                       if ( chars[i] == '\u2044') {
+                       if (chars[i] == Chars.FRACTION) {
                                chars[i] = '/';
                        }
+                       if (chars[i] == DECIMAL_SEPARATOR || chars[i] == ',') {
+                               chars[i] = '.';
+                       }
+                       if (chars[i] == MINUS_SIGN) {
+                               chars[i] = '-';
+                       }
                }
                exp = String.copyValueOf(chars);
-               exp = exp.replaceAll("(\\d+)\\s+(\\d+)\\s*/\\s*(\\d+)", "($1+$2/$3)");
-               exp = exp.replace(',', '.');
+               
+               // Replace fraction equivalents "1 3/4" with "(1+3/4)"
+               exp = exp.replaceAll("(?<![\\d.])(\\d+)\\s+(\\d+)\\s*/\\s*(\\d+)(?![\\d.])", "($1+$2/$3)");
+               
                // Disallow spaces between numbers - default is to remove spaces!
                if (exp.matches(".*[0-9.]\\s+[0-9.].*")) {
-                       throw new InvalidExpressionException("Invalid expression: " + exp);
+                       throw new InvalidExpressionException("Expression contains excess space: " + exp);
                }
                return exp;
        }
-       
 }
diff --git a/core/src/net/sf/openrocket/util/enums/EnumConversion.java b/core/src/net/sf/openrocket/util/enums/EnumConversion.java
new file mode 100644 (file)
index 0000000..4b8624f
--- /dev/null
@@ -0,0 +1,7 @@
+package net.sf.openrocket.util.enums;
+
+public interface EnumConversion {
+       
+       public String convert(Enum<?> e);
+       
+}
diff --git a/core/src/net/sf/openrocket/util/enums/EnumName.java b/core/src/net/sf/openrocket/util/enums/EnumName.java
new file mode 100644 (file)
index 0000000..7821061
--- /dev/null
@@ -0,0 +1,63 @@
+package net.sf.openrocket.util.enums;
+
+import java.util.EnumMap;
+import java.util.HashMap;
+import java.util.Map;
+
+import net.sf.openrocket.util.BugException;
+
+public class EnumName<E extends Enum<E>> {
+       
+       public static final EnumConversion NAME = new EnumConversion() {
+               @Override
+               public String convert(Enum<?> e) {
+                       return e.name();
+               }
+       };
+       
+       
+       private final Class<E> type;
+       private final Map<E, String> map;
+       private final Map<String, E> reverse;
+       
+       public EnumName(Class<E> type) {
+               this(type, NAME);
+       }
+       
+       public EnumName(Class<E> type, EnumConversion conversion) {
+               this.type = type;
+               map = new EnumMap<E, String>(type);
+               reverse = new HashMap<String, E>();
+               
+               E[] keys = type.getEnumConstants();
+               if (keys == null) {
+                       throw new IllegalArgumentException("Type " + type + " is not of enum type");
+               }
+               for (E key : keys) {
+                       String value = conversion.convert(key);
+                       if (reverse.containsKey(value)) {
+                               throw new BugException("Two enum constants were converted to have the name value: " + reverse.get(value)
+                                               + " and " + key + " both convert to '" + value + "'");
+                       }
+                       map.put(key, value);
+                       reverse.put(value, key);
+                       
+               }
+       }
+       
+       
+       
+       public String getName(E key) {
+               String name = map.get(key);
+               if (name == null) {
+                       throw new IllegalArgumentException("No name found for enum " + key + " from map of type " + type);
+               }
+               return name;
+       }
+       
+       public E getEnum(String name) {
+               return reverse.get(name);
+       }
+       
+       
+}
index 738f5b7187b51d0da86c27fa75b16c731b2e6e18..94e23bbbc2fb8c8c438e03f6430b71c4bf2bbeca 100644 (file)
@@ -41,9 +41,19 @@ public class ExpressionParserTest {
        @Test
        public void testFraction() throws InvalidExpressionException {
                assertEquals(1.5, parser.parse("1 1/2"), EPS);
+               assertEquals(11 + 11.0 / 22.0, parser.parse("11 11/22"), EPS);
+               assertEquals(-11 - 11.0 / 22.0, parser.parse("-11 11/22"), EPS);
                assertEquals(1.5, parser.parse("  1    1 / 2"), EPS);
+               assertEquals(11 + 11.0 / 22.0, parser.parse("  11    11 / 22"), EPS);
                assertEquals(2.0 + 3.0 / 7.0, parser.parse("1 + 1 3/7"), EPS);
-               assertEquals(3.0, parser.parse("1 1/2 * 2"), EPS);
+               assertEquals(2.0 + 3.0 / 7.0, parser.parse("1 + 1 3/7"), EPS);
+               assertEquals(3.0, parser.parse("1 1/2* 2"), EPS);
+               assertEquals(3.0, parser.parse("1 1/2* 2"), EPS);
+       }
+       
+       @Test
+       public void testCharConversion() throws InvalidExpressionException {
+               assertEquals(1 + 1.0 / 9.0, parser.parse("1 \u2081 \u2044 \u2089"), EPS);
        }
        
        @Test
@@ -53,6 +63,12 @@ public class ExpressionParserTest {
                expectInvalid("1 2");
                expectInvalid("12 2.5");
                expectInvalid("1 2.5/4");
+               expectInvalid("11 22.55/44");
+               expectInvalid("1 2/4.1");
+               expectInvalid("11 22/44.11");
+               expectInvalid("1.2 3/4");
+               expectInvalid("12.23 34/45");
+               
                expectInvalid("1. 2");
                expectInvalid("1 .2");
        }
diff --git a/core/test/net/sf/openrocket/util/enums/TestEnumName.java b/core/test/net/sf/openrocket/util/enums/TestEnumName.java
new file mode 100644 (file)
index 0000000..8c22593
--- /dev/null
@@ -0,0 +1,11 @@
+package net.sf.openrocket.util.enums;
+
+import net.sf.openrocket.rocketcomponent.Transition.Shape;
+
+public class TestEnumName {
+       
+       private void testConstructor() {
+               EnumName<Shape> name = new EnumName<Shape>(Shape.class);
+       }
+       
+}