Constrain preset editor on existing files to only use populated Materials; minor...
[debian/openrocket] / core / src / net / sf / openrocket / gui / preset / PresetEditorDialog.java
1 package net.sf.openrocket.gui.preset;
2
3 import net.miginfocom.swing.MigLayout;
4 import net.sf.openrocket.gui.SpinnerEditor;
5 import net.sf.openrocket.gui.adaptors.DoubleModel;
6 import net.sf.openrocket.gui.components.UnitSelector;
7 import net.sf.openrocket.l10n.Translator;
8 import net.sf.openrocket.logging.LogHelper;
9 import net.sf.openrocket.material.Material;
10 import net.sf.openrocket.motor.Manufacturer;
11 import net.sf.openrocket.preset.ComponentPreset;
12 import net.sf.openrocket.preset.ComponentPresetFactory;
13 import net.sf.openrocket.preset.InvalidComponentPresetException;
14 import net.sf.openrocket.preset.TypedKey;
15 import net.sf.openrocket.preset.TypedPropertyMap;
16 import net.sf.openrocket.preset.loader.MaterialHolder;
17 import net.sf.openrocket.rocketcomponent.Transition;
18 import net.sf.openrocket.startup.Application;
19 import net.sf.openrocket.unit.UnitGroup;
20
21 import javax.imageio.ImageIO;
22 import javax.swing.ComboBoxModel;
23 import javax.swing.DefaultComboBoxModel;
24 import javax.swing.ImageIcon;
25 import javax.swing.InputVerifier;
26 import javax.swing.JButton;
27 import javax.swing.JCheckBox;
28 import javax.swing.JComboBox;
29 import javax.swing.JComponent;
30 import javax.swing.JDialog;
31 import javax.swing.JFileChooser;
32 import javax.swing.JLabel;
33 import javax.swing.JOptionPane;
34 import javax.swing.JPanel;
35 import javax.swing.JSpinner;
36 import javax.swing.JTextField;
37 import javax.swing.border.EmptyBorder;
38 import javax.swing.filechooser.FileNameExtensionFilter;
39 import javax.swing.text.JTextComponent;
40 import java.awt.BorderLayout;
41 import java.awt.CardLayout;
42 import java.awt.Dimension;
43 import java.awt.Graphics2D;
44 import java.awt.Image;
45 import java.awt.Rectangle;
46 import java.awt.event.ActionEvent;
47 import java.awt.event.ActionListener;
48 import java.awt.event.ItemEvent;
49 import java.awt.event.ItemListener;
50 import java.awt.event.MouseAdapter;
51 import java.awt.event.MouseEvent;
52 import java.awt.image.BufferedImage;
53 import java.io.ByteArrayInputStream;
54 import java.io.ByteArrayOutputStream;
55 import java.io.File;
56 import java.io.IOException;
57 import java.io.InputStream;
58 import java.util.HashMap;
59 import java.util.List;
60 import java.util.Map;
61 import java.util.regex.Matcher;
62 import java.util.regex.Pattern;
63
64 public class PresetEditorDialog extends JDialog implements ItemListener {
65
66     private static Translator trans = Application.getTranslator();
67
68     private static LogHelper log = Application.getLogger();
69
70     private static final String NON_NEGATIVE_INTEGER_FIELD = "(\\d){0,10}";
71
72     /**
73      * Input of non-negative decimals.
74      */
75     final PresetInputVerifier NON_NEGATIVE_INTEGER = new PresetInputVerifier(Pattern.compile(NON_NEGATIVE_INTEGER_FIELD));
76
77     private final JPanel contentPanel = new JPanel();
78     private DeselectableComboBox typeCombo;
79     private JTextField mfgTextField;
80     private MaterialChooser materialChooser;
81     private MaterialHolder holder = null;
82
83     private JTextField ncPartNoTextField;
84     private JTextField ncDescTextField;
85     private DoubleModel ncLength;
86     private JCheckBox ncFilledCB;
87     private JComboBox ncShapeCB;
88     private DoubleModel ncAftDia;
89     private DoubleModel ncAftShoulderDia;
90     private DoubleModel ncAftShoulderLen;
91     private DoubleModel ncMass;
92     private ImageIcon ncImage;
93     private JButton ncImageBtn;
94
95     private JTextField trPartNoTextField;
96     private JTextField trDescTextField;
97     private DoubleModel trLength;
98     private DoubleModel trAftDia;
99     private DoubleModel trAftShoulderDia;
100     private DoubleModel trAftShoulderLen;
101     private DoubleModel trForeDia;
102     private DoubleModel trForeShoulderDia;
103     private DoubleModel trForeShoulderLen;
104     private DoubleModel trMass;
105     private ImageIcon trImage;
106     private JCheckBox trFilledCB;
107     private JComboBox trShapeCB;
108     private JButton trImageBtn;
109
110     private JTextField btPartNoTextField;
111     private JTextField btDescTextField;
112     private DoubleModel btMass;
113     private DoubleModel btInnerDia;
114     private DoubleModel btOuterDia;
115     private DoubleModel btLength;
116     private ImageIcon btImage;
117     private JButton btImageBtn;
118
119     private JTextField tcPartNoTextField;
120     private JTextField tcDescTextField;
121     private DoubleModel tcMass;
122     private DoubleModel tcInnerDia;
123     private DoubleModel tcOuterDia;
124     private DoubleModel tcLength;
125     private ImageIcon tcImage;
126     private JButton tcImageBtn;
127
128     private JTextField bhPartNoTextField;
129     private JTextField bhDescTextField;
130     private DoubleModel bhOuterDia;
131     private DoubleModel bhLength;
132     private DoubleModel bhMass;
133     private ImageIcon bhImage;
134     private JButton bhImageBtn;
135
136     private JTextField crPartNoTextField;
137     private JTextField crDescTextField;
138     private DoubleModel crOuterDia;
139     private DoubleModel crInnerDia;
140     private DoubleModel crThickness;
141     private DoubleModel crMass;
142     private ImageIcon crImage;
143     private JButton crImageBtn;
144
145     private JTextField ebPartNoTextField;
146     private JTextField ebDescTextField;
147     private DoubleModel ebOuterDia;
148     private DoubleModel ebInnerDia;
149     private DoubleModel ebThickness;
150     private DoubleModel ebMass;
151     private ImageIcon ebImage;
152     private JButton ebImageBtn;
153
154     private JTextField llPartNoTextField;
155     private JTextField llDescTextField;
156     private DoubleModel llOuterDia;
157     private DoubleModel llInnerDia;
158     private DoubleModel llLength;
159     private DoubleModel llMass;
160     private ImageIcon llImage;
161     private JButton llImageBtn;
162
163     private JTextField stPartNoTextField;
164     private JTextField stDescTextField;
165     private DoubleModel stThickness;
166     private DoubleModel stWidth;
167     private DoubleModel stLength;
168     private DoubleModel stMass;
169     private ImageIcon stImage;
170     private JButton stImageBtn;
171
172     private JTextField pcPartNoTextField;
173     private JTextField pcDescTextField;
174     private JTextField pcSides;
175     private JTextField pcLineCount;
176     private DoubleModel pcDiameter;
177     private DoubleModel pcLineLength;
178     private MaterialChooser pcLineMaterialChooser;
179     private DoubleModel pcMass;
180     private ImageIcon pcImage;
181     private JButton pcImageBtn;
182
183     private final JFileChooser imageChooser = createImageChooser();
184
185     private JPanel componentOverlayPanel;
186
187     private PresetResultListener resultListener;
188
189     private static Map<String, String> componentMap = new HashMap<String, String>();
190
191     private static final String NOSE_CONE_KEY = "NoseCone.NoseCone";
192     private static final String BODY_TUBE_KEY = "BodyTube.BodyTube";
193     private static final String TUBE_COUPLER_KEY = "TubeCoupler.TubeCoupler";
194     private static final String TRANSITION_KEY = "Transition.Transition";
195     private static final String CR_KEY = "ComponentIcons.Centeringring";
196     private static final String BULKHEAD_KEY = "Bulkhead.Bulkhead";
197     private static final String EB_KEY = "ComponentIcons.Engineblock";
198     private static final String LAUNCH_LUG_KEY = "ComponentIcons.Launchlug";
199     private static final String STREAMER_KEY = "ComponentIcons.Streamer";
200     private static final String PARACHUTE_KEY = "ComponentIcons.Parachute";
201
202
203     static {
204         componentMap.put(trans.get(NOSE_CONE_KEY), "NOSECONE");
205         componentMap.put(trans.get(BODY_TUBE_KEY), "BODYTUBE");
206         componentMap.put(trans.get(TUBE_COUPLER_KEY), "TUBECOUPLER");
207         componentMap.put(trans.get(TRANSITION_KEY), "TRANSITION");
208         componentMap.put(trans.get(CR_KEY), "CENTERINGRING");
209         componentMap.put(trans.get(BULKHEAD_KEY), "BULKHEAD");
210         componentMap.put(trans.get(EB_KEY), "ENGINEBLOCK");
211         componentMap.put(trans.get(LAUNCH_LUG_KEY), "LAUNCHLUG");
212         componentMap.put(trans.get(PARACHUTE_KEY), "PARACHUTE");
213         componentMap.put(trans.get(STREAMER_KEY), "STREAMER");
214     }
215
216     /**
217      * Create the dialog.
218      *
219      * @param theCallback the listener that gets the results of editing the presets
220      */
221     public PresetEditorDialog(PresetResultListener theCallback) {
222         this(theCallback, null, null);
223     }
224
225     /**
226      * Create the dialog.
227      *
228      * @param theCallback the listener that gets the results of editing the presets
229      * @param toEdit      the ComponentPreset to be edited; or null if a new one is being added
230      * @param matHolder   the set of materials; if null then use system materials
231      */
232     public PresetEditorDialog(PresetResultListener theCallback, ComponentPreset toEdit, MaterialHolder matHolder) {
233         resultListener = theCallback;
234         getContentPane().setMinimumSize(new Dimension(200, 200));
235         setBounds(100, 100, 825, 610);
236         getContentPane().setLayout(new BorderLayout());
237         contentPanel.setBorder(new EmptyBorder(5, 5, 5, 5));
238         getContentPane().add(contentPanel, BorderLayout.CENTER);
239         contentPanel.setLayout(new MigLayout("", "[][grow][94.00,grow][232.0,grow][130.00][grow]", "[][][20.00,grow][grow]"));
240         JLabel lblManufacturer = new JLabel("Manufacturer:");
241         contentPanel.add(lblManufacturer, "cell 2 0,alignx left,aligny center");
242
243         mfgTextField = new JTextField();
244         contentPanel.add(mfgTextField, "cell 3 0,growx");
245         mfgTextField.setColumns(10);
246
247         JLabel typeLabel = new JLabel("Type:");
248         contentPanel.add(typeLabel, "cell 2 1,alignx left,aligny center");
249
250         componentOverlayPanel = new JPanel();
251         contentPanel.add(componentOverlayPanel, "cell 1 3 5 2,grow");
252         componentOverlayPanel.setLayout(new CardLayout(0, 0));
253
254         typeCombo = new DeselectableComboBox();
255         typeCombo.addItemListener(this);
256         typeCombo.setModel(new DefaultComboBoxModel());
257         setItems(typeCombo, toEdit);
258         contentPanel.add(typeCombo, "cell 3 1,growx");
259
260         JLabel bhMaterialLabel = new JLabel("Material:");
261         contentPanel.add(bhMaterialLabel, "cell 2 2, alignx left");
262
263         materialChooser = new MaterialChooser(new MaterialModel(this, Material.Type.BULK));
264
265         contentPanel.add(materialChooser, "cell 3 2,growx");
266
267         {
268             JPanel ncPanel = new JPanel();
269             componentOverlayPanel.add(ncPanel, "NOSECONE");
270             ncPanel.setLayout(new MigLayout("", "[61px][159.00,grow][45.00][109.00,grow][189.00,grow][grow]", "[16px][][][][][]"));
271             JLabel ncPartNoLabel = new JLabel("Part No:");
272             ncPanel.add(ncPartNoLabel, "cell 0 0,alignx left,aligny center");
273
274             ncPartNoTextField = new JTextField();
275             ncPanel.add(ncPartNoTextField, "cell 1 0,growx");
276             ncPartNoTextField.setColumns(10);
277
278             JLabel ncDescLabel = new JLabel("Description:");
279             ncPanel.add(ncDescLabel, "cell 3 0,alignx left,aligny center");
280
281             ncDescTextField = new JTextField();
282             ncPanel.add(ncDescTextField, "cell 4 0,growx");
283             ncDescTextField.setColumns(10);
284
285             ncFilledCB = new JCheckBox("Filled");
286             ncPanel.add(ncFilledCB, "cell 1 1");
287
288             JLabel ncMaterialLabel = new JLabel(trans.get("RocketCompCfg.lbl.Componentmaterial"));
289             ncPanel.add(ncMaterialLabel, "cell 0 1,alignx left");
290
291             JLabel ncMassLabel = new JLabel(trans.get("RocketCompCfg.lbl.Componentmass"));
292             ncPanel.add(ncMassLabel, "cell 3 1,alignx left");
293
294             ncMass = new DoubleModel(0, UnitGroup.UNITS_MASS, 0);
295             JSpinner spin = new JSpinner(ncMass.getSpinnerModel());
296             spin.setEditor(new SpinnerEditor(spin));
297             ncPanel.add(spin, "cell 4 1, growx");
298             ncPanel.add(new UnitSelector(ncMass), "growx");
299
300             JLabel ncShapeLabel = new JLabel(trans.get("NoseConeCfg.lbl.Noseconeshape"));
301             ncPanel.add(ncShapeLabel, "cell 0 2,alignx left");
302
303             ncShapeCB = new JComboBox();
304             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()}));
305             ncPanel.add(ncShapeCB, "cell 1 2,growx");
306
307             JLabel ncLengthLabel = new JLabel(trans.get("NoseConeCfg.lbl.Noseconelength"));
308             ncPanel.add(ncLengthLabel, "cell 3 2,alignx left");
309
310             ncLength = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0, 2);
311             spin = new JSpinner(ncLength.getSpinnerModel());
312             spin.setEditor(new SpinnerEditor(spin));
313             ncPanel.add(spin, "cell 4 2, growx");
314             ncPanel.add(new UnitSelector(ncLength), "growx");
315
316             JLabel ncAftDiaLabel = new JLabel("Aft Dia.:");
317             ncPanel.add(ncAftDiaLabel, "cell 0 3,alignx left");
318
319             ncAftDia = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0, 2);
320             spin = new JSpinner(ncAftDia.getSpinnerModel());
321             spin.setEditor(new SpinnerEditor(spin));
322             ncPanel.add(spin, "cell 1 3, growx");
323             ncPanel.add(new UnitSelector(ncAftDia), "growx");
324
325             JLabel ncAftShoulderLenLabel = new JLabel("Aft Shoulder Len:");
326             ncPanel.add(ncAftShoulderLenLabel, "cell 0 4,alignx left");
327
328             ncAftShoulderLen = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0, 2);
329             spin = new JSpinner(ncAftShoulderLen.getSpinnerModel());
330             spin.setEditor(new SpinnerEditor(spin));
331             ncPanel.add(spin, "cell 1 4, growx");
332             ncPanel.add(new UnitSelector(ncAftShoulderLen), "growx");
333
334             JLabel ncAftShoulderDiaLabel = new JLabel("Aft Shoulder Dia.:");
335             ncPanel.add(ncAftShoulderDiaLabel, "cell 0 5,alignx left, aligny top, pad 7 0 0 0");
336
337             ncAftShoulderDia = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0, 2);
338             spin = new JSpinner(ncAftShoulderDia.getSpinnerModel());
339             spin.setEditor(new SpinnerEditor(spin));
340             ncPanel.add(spin, "cell 1 5, growx, aligny top");
341             ncPanel.add(new UnitSelector(ncAftShoulderDia), "growx, aligny top, pad 7 0 0 0");
342
343             JPanel panel = new JPanel();
344             panel.setMinimumSize(new Dimension(200, 200));
345             ncPanel.add(panel, "cell 4 3, span 1 3");
346             panel.setLayout(null);
347             ncImageBtn = new JButton("No Image");
348             ncImageBtn.setMaximumSize(new Dimension(75, 75));
349             ncImageBtn.setMinimumSize(new Dimension(75, 75));
350             panel.add(ncImageBtn);
351             ncImageBtn.setBounds(new Rectangle(6, 6, 132, 145));
352
353             ncImageBtn.addActionListener(new ActionListener() {
354                 @Override
355                 public void actionPerformed(final ActionEvent e) {
356                     int returnVal = imageChooser.showOpenDialog(PresetEditorDialog.this);
357
358                     if (returnVal == JFileChooser.APPROVE_OPTION) {
359                         File file = imageChooser.getSelectedFile();
360                         ncImage = scaleImage(new ImageIcon(file.getAbsolutePath()).getImage(), 155);
361                         ncImageBtn.setIcon(ncImage);
362                     }
363                 }
364             });
365
366         }
367         {
368             JPanel trPanel = new JPanel();
369             componentOverlayPanel.add(trPanel, "TRANSITION");
370             trPanel.setLayout(new MigLayout("", "[61px][159.00,grow][45.00][109.00,grow][189.00,grow][grow]", "[16px][][][][][]"));
371
372             JLabel trPartNoLabel = new JLabel("Part No:");
373             trPanel.add(trPartNoLabel, "cell 0 0,alignx left");
374
375             trPartNoTextField = new JTextField();
376             trPanel.add(trPartNoTextField, "cell 1 0,growx");
377             trPartNoTextField.setColumns(10);
378
379             JLabel trDescLabel = new JLabel("Description:");
380             trPanel.add(trDescLabel, "cell 3 0,alignx left");
381
382             trDescTextField = new JTextField();
383             trPanel.add(trDescTextField, "cell 4 0,growx");
384             trDescTextField.setColumns(10);
385
386             trFilledCB = new JCheckBox("Filled");
387             trPanel.add(trFilledCB, "cell 1 1");
388
389             JLabel trMassLabel = new JLabel("Mass:");
390             trPanel.add(trMassLabel, "cell 3 1,alignx left");
391
392             trMass = new DoubleModel(0, UnitGroup.UNITS_MASS, 0);
393             JSpinner spin = new JSpinner(trMass.getSpinnerModel());
394             spin.setEditor(new SpinnerEditor(spin));
395             trPanel.add(spin, "cell 4 1, growx");
396             trPanel.add(new UnitSelector(trMass), "growx");
397
398             JLabel trShapeLabel = new JLabel("Shape:");
399             trPanel.add(trShapeLabel, "cell 0 2,alignx left");
400
401             trShapeCB = new JComboBox();
402             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()}));
403             trPanel.add(trShapeCB, "cell 1 2,growx");
404
405             JLabel trLengthLabel = new JLabel("Length:");
406             trPanel.add(trLengthLabel, "cell 3 2,alignx left");
407
408             trLength = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0, 2);
409             spin = new JSpinner(trLength.getSpinnerModel());
410             spin.setEditor(new SpinnerEditor(spin));
411             trPanel.add(spin, "cell 4 2, growx");
412             trPanel.add(new UnitSelector(trLength), "growx");
413
414             JLabel trAftDiaLabel = new JLabel("Aft Dia.:");
415             trPanel.add(trAftDiaLabel, "cell 0 3,alignx left");
416
417             trAftDia = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0, 2);
418             spin = new JSpinner(trAftDia.getSpinnerModel());
419             spin.setEditor(new SpinnerEditor(spin));
420             trPanel.add(spin, "cell 1 3, growx");
421             trPanel.add(new UnitSelector(trAftDia), "growx");
422
423             JLabel trForeDiaLabel = new JLabel("Fore Dia.:");
424             trPanel.add(trForeDiaLabel, "cell 3 3,alignx left");
425
426             trForeDia = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0, 2);
427             spin = new JSpinner(trForeDia.getSpinnerModel());
428             spin.setEditor(new SpinnerEditor(spin));
429             trPanel.add(spin, "cell 4 3, growx");
430             trPanel.add(new UnitSelector(trForeDia), "growx");
431
432             JLabel trAftShouldDiaLabel = new JLabel("Aft Shoulder Dia.:");
433             trPanel.add(trAftShouldDiaLabel, "cell 0 4,alignx left");
434
435             trAftShoulderDia = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0, 2);
436             spin = new JSpinner(trAftShoulderDia.getSpinnerModel());
437             spin.setEditor(new SpinnerEditor(spin));
438             trPanel.add(spin, "cell 1 4, growx");
439             trPanel.add(new UnitSelector(trAftShoulderDia), "growx");
440
441             JLabel trForeShouldDiaLabel = new JLabel("Fore Shoulder Dia.:");
442             trPanel.add(trForeShouldDiaLabel, "cell 3 4,alignx left");
443
444             trForeShoulderDia = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0, 2);
445             spin = new JSpinner(trForeShoulderDia.getSpinnerModel());
446             spin.setEditor(new SpinnerEditor(spin));
447             trPanel.add(spin, "cell 4 4, growx");
448             trPanel.add(new UnitSelector(trForeShoulderDia), "growx");
449
450             JLabel trAftShoulderLenLabel = new JLabel("Aft Shoulder Len.:");
451             trPanel.add(trAftShoulderLenLabel, "cell 0 5,alignx left");
452
453             trAftShoulderLen = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0, 2);
454             spin = new JSpinner(trAftShoulderLen.getSpinnerModel());
455             spin.setEditor(new SpinnerEditor(spin));
456             trPanel.add(spin, "cell 1 5, growx");
457             trPanel.add(new UnitSelector(trAftShoulderLen), "growx");
458
459             JLabel lblForeShoulderLen = new JLabel("Fore Shoulder Len.:");
460             trPanel.add(lblForeShoulderLen, "cell 3 5,alignx left");
461
462             trForeShoulderLen = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0, 2);
463             spin = new JSpinner(trForeShoulderLen.getSpinnerModel());
464             spin.setEditor(new SpinnerEditor(spin));
465             trPanel.add(spin, "cell 4 5, growx");
466             trPanel.add(new UnitSelector(trForeShoulderLen), "growx");
467
468             JPanel panel = new JPanel();
469             panel.setMinimumSize(new Dimension(200, 200));
470             trPanel.add(panel, "cell 4 6");
471             panel.setLayout(null);
472             trImageBtn = new JButton("No Image");
473             trImageBtn.setMaximumSize(new Dimension(75, 75));
474             trImageBtn.setMinimumSize(new Dimension(75, 75));
475             panel.add(trImageBtn);
476             trImageBtn.setBounds(new Rectangle(6, 6, 132, 145));
477
478             trImageBtn.addActionListener(new ActionListener() {
479                 @Override
480                 public void actionPerformed(final ActionEvent e) {
481                     int returnVal = imageChooser.showOpenDialog(PresetEditorDialog.this);
482
483                     if (returnVal == JFileChooser.APPROVE_OPTION) {
484                         File file = imageChooser.getSelectedFile();
485                         trImage = scaleImage(new ImageIcon(file.getAbsolutePath()).getImage(), 155);
486                         trImageBtn.setIcon(trImage);
487                     }
488                 }
489             });
490
491         }
492         {
493             JPanel btPanel = new JPanel();
494             componentOverlayPanel.add(btPanel, "BODYTUBE");
495             btPanel.setLayout(new MigLayout("", "[][grow][][grow]", "[][][][]"));
496             JLabel btPartNoLabel = new JLabel("Part No:");
497             btPanel.add(btPartNoLabel, "cell 0 0,alignx left");
498
499             btPartNoTextField = new JTextField();
500             btPanel.add(btPartNoTextField, "cell 1 0,growx");
501             btPartNoTextField.setColumns(10);
502
503             JLabel btDescLabel = new JLabel("Description:");
504             btPanel.add(btDescLabel, "cell 3 0,alignx left");
505
506             btDescTextField = new JTextField();
507             btPanel.add(btDescTextField, "cell 4 0,growx");
508             btDescTextField.setColumns(10);
509
510             JLabel btLengthLabel = new JLabel("Length:");
511             btPanel.add(btLengthLabel, "cell 0 1,alignx left");
512
513             btLength = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0);
514             JSpinner spin = new JSpinner(btLength.getSpinnerModel());
515             spin.setEditor(new SpinnerEditor(spin));
516             btPanel.add(spin, "cell 1 1, growx");
517             btPanel.add(new UnitSelector(btLength), "growx");
518
519             JLabel btMassLabel = new JLabel("Mass:");
520             btPanel.add(btMassLabel, "cell 3 1,alignx left");
521
522             btMass = new DoubleModel(0, UnitGroup.UNITS_MASS, 0);
523             spin = new JSpinner(btMass.getSpinnerModel());
524             spin.setEditor(new SpinnerEditor(spin));
525             btPanel.add(spin, "cell 4 1, growx");
526             btPanel.add(new UnitSelector(btMass), "growx");
527
528             JLabel btInnerDiaLabel = new JLabel("Inner Dia.:");
529             btPanel.add(btInnerDiaLabel, "cell 0 2,alignx left");
530
531             btInnerDia = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0);
532             spin = new JSpinner(btInnerDia.getSpinnerModel());
533             spin.setEditor(new SpinnerEditor(spin));
534             btPanel.add(spin, "cell 1 2, growx");
535             btPanel.add(new UnitSelector(btInnerDia), "growx");
536
537             JLabel btOuterDiaLabel = new JLabel("Outer Dia.:");
538             btPanel.add(btOuterDiaLabel, "cell 3 2,alignx left");
539
540             btOuterDia = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0);
541             spin = new JSpinner(btOuterDia.getSpinnerModel());
542             spin.setEditor(new SpinnerEditor(spin));
543             btPanel.add(spin, "cell 4 2, growx");
544             btPanel.add(new UnitSelector(btOuterDia), "growx");
545
546             JPanel panel = new JPanel();
547             panel.setMinimumSize(new Dimension(200, 200));
548             btPanel.add(panel, "cell 4 3");
549             panel.setLayout(null);
550             btImageBtn = new JButton("No Image");
551             btImageBtn.setMaximumSize(new Dimension(75, 75));
552             btImageBtn.setMinimumSize(new Dimension(75, 75));
553             panel.add(btImageBtn);
554             btImageBtn.setBounds(new Rectangle(6, 6, 132, 145));
555
556             btImageBtn.addActionListener(new ActionListener() {
557                 @Override
558                 public void actionPerformed(final ActionEvent e) {
559                     int returnVal = imageChooser.showOpenDialog(PresetEditorDialog.this);
560
561                     if (returnVal == JFileChooser.APPROVE_OPTION) {
562                         File file = imageChooser.getSelectedFile();
563                         btImage = scaleImage(new ImageIcon(file.getAbsolutePath()).getImage(), 155);
564                         btImageBtn.setIcon(btImage);
565                     }
566                 }
567             });
568
569         }
570         {
571             JPanel tcPanel = new JPanel();
572             componentOverlayPanel.add(tcPanel, "TUBECOUPLER");
573             tcPanel.setLayout(new MigLayout("", "[][grow][][grow]", "[][][][]"));
574             JLabel tcPartNoLabel = new JLabel("Part No:");
575             tcPanel.add(tcPartNoLabel, "cell 0 0,alignx left");
576
577             tcPartNoTextField = new JTextField();
578             tcPanel.add(tcPartNoTextField, "cell 1 0,growx");
579             tcPartNoTextField.setColumns(10);
580
581             JLabel tcDescLabel = new JLabel("Description:");
582             tcPanel.add(tcDescLabel, "cell 3 0,alignx left");
583
584             tcDescTextField = new JTextField();
585             tcPanel.add(tcDescTextField, "cell 4 0,growx");
586             tcDescTextField.setColumns(10);
587
588             JLabel tcLengthLabel = new JLabel("Length:");
589             tcPanel.add(tcLengthLabel, "cell 0 1,alignx left");
590
591             tcLength = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0);
592             JSpinner spin = new JSpinner(tcLength.getSpinnerModel());
593             spin.setEditor(new SpinnerEditor(spin));
594             tcPanel.add(spin, "cell 1 1, growx");
595             tcPanel.add(new UnitSelector(tcLength), "growx");
596
597             JLabel tcMassLabel = new JLabel("Mass:");
598             tcPanel.add(tcMassLabel, "cell 3 1,alignx left");
599
600             tcMass = new DoubleModel(0, UnitGroup.UNITS_MASS, 0);
601             spin = new JSpinner(tcMass.getSpinnerModel());
602             spin.setEditor(new SpinnerEditor(spin));
603             tcPanel.add(spin, "cell 4 1, growx");
604             tcPanel.add(new UnitSelector(tcMass), "growx");
605
606             JLabel tcInnerDiaLabel = new JLabel("Inner Dia.:");
607             tcPanel.add(tcInnerDiaLabel, "cell 0 2,alignx left");
608
609             tcInnerDia = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0);
610             spin = new JSpinner(tcInnerDia.getSpinnerModel());
611             spin.setEditor(new SpinnerEditor(spin));
612             tcPanel.add(spin, "cell 1 2, growx");
613             tcPanel.add(new UnitSelector(tcInnerDia), "growx");
614
615             JLabel tcOuterDiaLabel = new JLabel("Outer Dia.:");
616             tcPanel.add(tcOuterDiaLabel, "cell 3 2,alignx left");
617
618             tcOuterDia = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0);
619             spin = new JSpinner(tcOuterDia.getSpinnerModel());
620             spin.setEditor(new SpinnerEditor(spin));
621             tcPanel.add(spin, "cell 4 2, growx");
622             tcPanel.add(new UnitSelector(tcOuterDia), "growx");
623
624             JPanel panel = new JPanel();
625             panel.setMinimumSize(new Dimension(200, 200));
626             tcPanel.add(panel, "cell 4 3");
627             panel.setLayout(null);
628             tcImageBtn = new JButton("No Image");
629             tcImageBtn.setMaximumSize(new Dimension(75, 75));
630             tcImageBtn.setMinimumSize(new Dimension(75, 75));
631             panel.add(tcImageBtn);
632             tcImageBtn.setBounds(new Rectangle(6, 6, 132, 145));
633
634             tcImageBtn.addActionListener(new ActionListener() {
635                 @Override
636                 public void actionPerformed(final ActionEvent e) {
637                     int returnVal = imageChooser.showOpenDialog(PresetEditorDialog.this);
638
639                     if (returnVal == JFileChooser.APPROVE_OPTION) {
640                         File file = imageChooser.getSelectedFile();
641                         tcImage = scaleImage(new ImageIcon(file.getAbsolutePath()).getImage(), 155);
642                         tcImageBtn.setIcon(tcImage);
643                     }
644                 }
645             });
646
647
648         }
649         {
650             JPanel bhPanel = new JPanel();
651             componentOverlayPanel.add(bhPanel, "BULKHEAD");
652             bhPanel.setLayout(new MigLayout("", "[][157.00,grow 79][65.00][grow]", "[][][][]"));
653
654             JLabel bhPartNoLabel = new JLabel("Part No:");
655             bhPanel.add(bhPartNoLabel, "cell 0 0,alignx left");
656
657             bhPartNoTextField = new JTextField();
658             bhPanel.add(bhPartNoTextField, "cell 1 0,growx");
659             bhPartNoTextField.setColumns(10);
660
661             JLabel bhDescLabel = new JLabel("Description:");
662             bhPanel.add(bhDescLabel, "cell 3 0,alignx left");
663
664             bhDescTextField = new JTextField();
665             bhPanel.add(bhDescTextField, "cell 4 0,growx");
666             bhDescTextField.setColumns(10);
667
668             JLabel bhLengthLabel = new JLabel("Thickness:");
669             bhPanel.add(bhLengthLabel, "cell 0 1,alignx left");
670
671             bhLength = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0);
672             JSpinner spin = new JSpinner(bhLength.getSpinnerModel());
673             spin.setEditor(new SpinnerEditor(spin));
674             bhPanel.add(spin, "cell 1 1, growx");
675             bhPanel.add(new UnitSelector(bhLength), "growx");
676
677             JLabel bhMassLabel = new JLabel("Mass:");
678             bhPanel.add(bhMassLabel, "cell 3 1,alignx left");
679
680             bhMass = new DoubleModel(0, UnitGroup.UNITS_MASS, 0);
681             spin = new JSpinner(bhMass.getSpinnerModel());
682             spin.setEditor(new SpinnerEditor(spin));
683             bhPanel.add(spin, "cell 4 1, growx");
684             bhPanel.add(new UnitSelector(bhMass), "growx");
685
686             JLabel bhOuterDiaLabel = new JLabel("Outer Dia.:");
687             bhPanel.add(bhOuterDiaLabel, "cell 0 2,alignx left, aligny top, pad 7 0 0 0");
688
689             bhOuterDia = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0);
690             spin = new JSpinner(bhOuterDia.getSpinnerModel());
691             spin.setEditor(new SpinnerEditor(spin));
692             bhPanel.add(spin, "cell 1 2, growx, aligny top");
693             bhPanel.add(new UnitSelector(bhOuterDia), "growx, aligny top, pad 7 0 0 0");
694
695             JPanel panel = new JPanel();
696             panel.setMinimumSize(new Dimension(200, 200));
697             bhPanel.add(panel, "cell 4 2");
698             panel.setLayout(null);
699             bhImageBtn = new JButton("No Image");
700             bhImageBtn.setMaximumSize(new Dimension(75, 75));
701             bhImageBtn.setMinimumSize(new Dimension(75, 75));
702             panel.add(bhImageBtn);
703             bhImageBtn.setBounds(new Rectangle(6, 6, 132, 145));
704
705             bhImageBtn.addActionListener(new ActionListener() {
706                 @Override
707                 public void actionPerformed(final ActionEvent e) {
708                     int returnVal = imageChooser.showOpenDialog(PresetEditorDialog.this);
709
710                     if (returnVal == JFileChooser.APPROVE_OPTION) {
711                         File file = imageChooser.getSelectedFile();
712                         bhImage = scaleImage(new ImageIcon(file.getAbsolutePath()).getImage(), 155);
713                         bhImageBtn.setIcon(bhImage);
714                     }
715                 }
716             });
717
718         }
719         {
720             JPanel crPanel = new JPanel();
721             componentOverlayPanel.add(crPanel, "CENTERINGRING");
722             crPanel.setLayout(new MigLayout("", "[][grow][][grow]", "[][][][]"));
723
724             JLabel crPartNoLabel = new JLabel("Part No:");
725             crPanel.add(crPartNoLabel, "cell 0 0,alignx left");
726
727             crPartNoTextField = new JTextField();
728             crPanel.add(crPartNoTextField, "cell 1 0, growx");
729             crPartNoTextField.setColumns(10);
730
731             JLabel crDescLabel = new JLabel("Description:");
732             crPanel.add(crDescLabel, "cell 3 0,alignx left");
733
734             crDescTextField = new JTextField();
735             crPanel.add(crDescTextField, "cell 4 0, growx");
736             crDescTextField.setColumns(10);
737
738             JLabel crThicknessLabel = new JLabel("Thickness:");
739             crPanel.add(crThicknessLabel, "cell 0 1,alignx left");
740
741             crThickness = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0);
742             JSpinner spin = new JSpinner(crThickness.getSpinnerModel());
743             spin.setEditor(new SpinnerEditor(spin));
744             crPanel.add(spin, "cell 1 1, growx");
745             crPanel.add(new UnitSelector(crThickness), "growx");
746
747             JLabel crMassLabel = new JLabel("Mass:");
748             crPanel.add(crMassLabel, "cell 3 1,alignx left");
749
750             crMass = new DoubleModel(0, UnitGroup.UNITS_MASS, 0);
751             spin = new JSpinner(crMass.getSpinnerModel());
752             spin.setEditor(new SpinnerEditor(spin));
753             crPanel.add(spin, "cell 4 1, growx");
754             crPanel.add(new UnitSelector(crMass), "growx");
755
756             JLabel crOuterDiaLabel = new JLabel("Outer Dia.:");
757             crPanel.add(crOuterDiaLabel, "cell 0 2,alignx left");
758
759             crOuterDia = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0);
760             spin = new JSpinner(crOuterDia.getSpinnerModel());
761             spin.setEditor(new SpinnerEditor(spin));
762             crPanel.add(spin, "cell 1 2, growx");
763             crPanel.add(new UnitSelector(crOuterDia), "growx");
764
765             JLabel crInnerDiaLabel = new JLabel("Inner Dia.:");
766             crPanel.add(crInnerDiaLabel, "cell 3 2,alignx left");
767
768             crInnerDia = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0);
769             spin = new JSpinner(crInnerDia.getSpinnerModel());
770             spin.setEditor(new SpinnerEditor(spin));
771             crPanel.add(spin, "cell 4 2, growx");
772             crPanel.add(new UnitSelector(crInnerDia), "growx");
773
774             JPanel panel = new JPanel();
775             panel.setMinimumSize(new Dimension(200, 200));
776             crPanel.add(panel, "cell 4 3");
777             panel.setLayout(null);
778             crImageBtn = new JButton("No Image");
779             crImageBtn.setMaximumSize(new Dimension(75, 75));
780             crImageBtn.setMinimumSize(new Dimension(75, 75));
781             panel.add(crImageBtn);
782             crImageBtn.setBounds(new Rectangle(6, 6, 132, 145));
783
784             crImageBtn.addActionListener(new ActionListener() {
785                 @Override
786                 public void actionPerformed(final ActionEvent e) {
787                     int returnVal = imageChooser.showOpenDialog(PresetEditorDialog.this);
788
789                     if (returnVal == JFileChooser.APPROVE_OPTION) {
790                         File file = imageChooser.getSelectedFile();
791                         crImage = scaleImage(new ImageIcon(file.getAbsolutePath()).getImage(), 155);
792                         crImageBtn.setIcon(crImage);
793                     }
794                 }
795             });
796
797         }
798         {
799             JPanel ebPanel = new JPanel();
800             componentOverlayPanel.add(ebPanel, "ENGINEBLOCK");
801             ebPanel.setLayout(new MigLayout("", "[][grow][][grow]", "[][][][]"));
802             JLabel ebPartNoLabel = new JLabel("Part No:");
803             ebPanel.add(ebPartNoLabel, "cell 0 0,alignx left");
804
805             ebPartNoTextField = new JTextField();
806             ebPanel.add(ebPartNoTextField, "cell 1 0,growx");
807             ebPartNoTextField.setColumns(10);
808
809             JLabel ebDescLabel = new JLabel("Description:");
810             ebPanel.add(ebDescLabel, "cell 3 0,alignx left");
811
812             ebDescTextField = new JTextField();
813             ebPanel.add(ebDescTextField, "cell 4 0,growx");
814             ebDescTextField.setColumns(10);
815
816             JLabel ebThicknessLabel = new JLabel("Thickness:");
817             ebPanel.add(ebThicknessLabel, "cell 0 1,alignx left");
818
819             ebThickness = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0);
820             JSpinner spin = new JSpinner(ebThickness.getSpinnerModel());
821             spin.setEditor(new SpinnerEditor(spin));
822             ebPanel.add(spin, "cell 1 1, growx");
823             ebPanel.add(new UnitSelector(ebThickness), "growx");
824
825             JLabel ebMassLabel = new JLabel("Mass:");
826             ebPanel.add(ebMassLabel, "cell 3 1,alignx left");
827
828             ebMass = new DoubleModel(0, UnitGroup.UNITS_MASS, 0);
829             spin = new JSpinner(ebMass.getSpinnerModel());
830             spin.setEditor(new SpinnerEditor(spin));
831             ebPanel.add(spin, "cell 4 1, growx");
832             ebPanel.add(new UnitSelector(ebMass), "growx");
833
834             JLabel ebOuterDiaLabel = new JLabel("Outer Dia.:");
835             ebPanel.add(ebOuterDiaLabel, "cell 0 2,alignx left");
836
837             ebOuterDia = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0);
838             spin = new JSpinner(ebOuterDia.getSpinnerModel());
839             spin.setEditor(new SpinnerEditor(spin));
840             ebPanel.add(spin, "cell 1 2, growx");
841             ebPanel.add(new UnitSelector(ebOuterDia), "growx");
842
843             JLabel ebInnerDiaLabel = new JLabel("Inner Dia.:");
844             ebPanel.add(ebInnerDiaLabel, "cell 3 2,alignx left");
845
846             ebInnerDia = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0);
847             spin = new JSpinner(ebInnerDia.getSpinnerModel());
848             spin.setEditor(new SpinnerEditor(spin));
849             ebPanel.add(spin, "cell 4 2, growx");
850             ebPanel.add(new UnitSelector(ebInnerDia), "growx");
851
852             JPanel panel = new JPanel();
853             panel.setMinimumSize(new Dimension(200, 200));
854             ebPanel.add(panel, "cell 4 3");
855             panel.setLayout(null);
856             ebImageBtn = new JButton("No Image");
857             ebImageBtn.setMaximumSize(new Dimension(75, 75));
858             ebImageBtn.setMinimumSize(new Dimension(75, 75));
859             panel.add(ebImageBtn);
860             ebImageBtn.setBounds(new Rectangle(6, 6, 132, 145));
861
862             ebImageBtn.addActionListener(new ActionListener() {
863                 @Override
864                 public void actionPerformed(final ActionEvent e) {
865                     int returnVal = imageChooser.showOpenDialog(PresetEditorDialog.this);
866
867                     if (returnVal == JFileChooser.APPROVE_OPTION) {
868                         File file = imageChooser.getSelectedFile();
869                         ebImage = scaleImage(new ImageIcon(file.getAbsolutePath()).getImage(), 155);
870                         ebImageBtn.setIcon(ebImage);
871                     }
872                 }
873             });
874         }
875
876         {
877             JPanel llPanel = new JPanel();
878             componentOverlayPanel.add(llPanel, "LAUNCHLUG");
879             llPanel.setLayout(new MigLayout("", "[][grow][][grow]", "[][][][]"));
880             JLabel llPartNoLabel = new JLabel("Part No:");
881             llPanel.add(llPartNoLabel, "cell 0 0,alignx left");
882
883             llPartNoTextField = new JTextField();
884             llPanel.add(llPartNoTextField, "cell 1 0,growx");
885             llPartNoTextField.setColumns(10);
886
887             JLabel llDescLabel = new JLabel("Description:");
888             llPanel.add(llDescLabel, "cell 3 0,alignx left");
889
890             llDescTextField = new JTextField();
891             llPanel.add(llDescTextField, "cell 4 0,growx");
892             llDescTextField.setColumns(10);
893
894             JLabel llLengthLabel = new JLabel("Length:");
895             llPanel.add(llLengthLabel, "cell 0 1,alignx left");
896
897             llLength = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0);
898             JSpinner spin = new JSpinner(llLength.getSpinnerModel());
899             spin.setEditor(new SpinnerEditor(spin));
900             llPanel.add(spin, "cell 1 1, growx");
901             llPanel.add(new UnitSelector(llLength), "growx");
902
903             JLabel llMassLabel = new JLabel("Mass:");
904             llPanel.add(llMassLabel, "cell 3 1,alignx left");
905
906             llMass = new DoubleModel(0, UnitGroup.UNITS_MASS, 0);
907             spin = new JSpinner(llMass.getSpinnerModel());
908             spin.setEditor(new SpinnerEditor(spin));
909             llPanel.add(spin, "cell 4 1, growx");
910             llPanel.add(new UnitSelector(llMass), "growx");
911
912             JLabel llOuterDiaLabel = new JLabel("Outer Dia.:");
913             llPanel.add(llOuterDiaLabel, "cell 0 2,alignx left");
914
915             llOuterDia = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0);
916             spin = new JSpinner(llOuterDia.getSpinnerModel());
917             spin.setEditor(new SpinnerEditor(spin));
918             llPanel.add(spin, "cell 1 2, growx");
919             llPanel.add(new UnitSelector(llOuterDia), "growx");
920
921             JLabel llInnerDiaLabel = new JLabel("Inner Dia.:");
922             llPanel.add(llInnerDiaLabel, "cell 3 2,alignx left");
923
924             llInnerDia = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0);
925             spin = new JSpinner(llInnerDia.getSpinnerModel());
926             spin.setEditor(new SpinnerEditor(spin));
927             llPanel.add(spin, "cell 4 2, growx");
928             llPanel.add(new UnitSelector(llInnerDia), "growx");
929
930             JPanel panel = new JPanel();
931             panel.setMinimumSize(new Dimension(200, 200));
932             llPanel.add(panel, "cell 4 3");
933             panel.setLayout(null);
934             llImageBtn = new JButton("No Image");
935             llImageBtn.setMaximumSize(new Dimension(75, 75));
936             llImageBtn.setMinimumSize(new Dimension(75, 75));
937             panel.add(llImageBtn);
938             llImageBtn.setBounds(new Rectangle(6, 6, 132, 145));
939
940             llImageBtn.addActionListener(new ActionListener() {
941                 @Override
942                 public void actionPerformed(final ActionEvent e) {
943                     int returnVal = imageChooser.showOpenDialog(PresetEditorDialog.this);
944
945                     if (returnVal == JFileChooser.APPROVE_OPTION) {
946                         File file = imageChooser.getSelectedFile();
947                         llImage = scaleImage(new ImageIcon(file.getAbsolutePath()).getImage(), 155);
948                         llImageBtn.setIcon(llImage);
949                     }
950                 }
951             });
952         }
953
954         {
955             JPanel stPanel = new JPanel();
956             componentOverlayPanel.add(stPanel, "STREAMER");
957             stPanel.setLayout(new MigLayout("", "[][grow][][grow]", "[][][][]"));
958             JLabel stPartNoLabel = new JLabel("Part No:");
959             stPanel.add(stPartNoLabel, "cell 0 0,alignx left");
960
961             stPartNoTextField = new JTextField();
962             stPanel.add(stPartNoTextField, "cell 1 0,growx");
963             stPartNoTextField.setColumns(10);
964
965             JLabel stDescLabel = new JLabel("Description:");
966             stPanel.add(stDescLabel, "cell 3 0,alignx left");
967
968             stDescTextField = new JTextField();
969             stPanel.add(stDescTextField, "cell 4 0,growx");
970             stDescTextField.setColumns(10);
971
972             JLabel stLengthLabel = new JLabel("Length:");
973             stPanel.add(stLengthLabel, "cell 0 1,alignx left");
974
975             stLength = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0);
976             JSpinner spin = new JSpinner(stLength.getSpinnerModel());
977             spin.setEditor(new SpinnerEditor(spin));
978             stPanel.add(spin, "cell 1 1, growx");
979             stPanel.add(new UnitSelector(stLength), "growx");
980
981             JLabel stMassLabel = new JLabel("Mass:");
982             stPanel.add(stMassLabel, "cell 3 1,alignx left");
983
984             stMass = new DoubleModel(0, UnitGroup.UNITS_MASS, 0);
985             spin = new JSpinner(stMass.getSpinnerModel());
986             spin.setEditor(new SpinnerEditor(spin));
987             stPanel.add(spin, "cell 4 1, growx");
988             stPanel.add(new UnitSelector(stMass), "growx");
989
990             JLabel stThicknessLabel = new JLabel("Thickness:");
991             stPanel.add(stThicknessLabel, "cell 0 2,alignx left");
992
993             stThickness = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0);
994             spin = new JSpinner(stThickness.getSpinnerModel());
995             spin.setEditor(new SpinnerEditor(spin));
996             stPanel.add(spin, "cell 1 2, growx");
997             stPanel.add(new UnitSelector(stThickness), "growx");
998
999             JLabel stWidthLabel = new JLabel("Width:");
1000             stPanel.add(stWidthLabel, "cell 3 2,alignx left");
1001
1002             stWidth = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0);
1003             spin = new JSpinner(stWidth.getSpinnerModel());
1004             spin.setEditor(new SpinnerEditor(spin));
1005             stPanel.add(spin, "cell 4 2, growx");
1006             stPanel.add(new UnitSelector(stWidth), "growx");
1007
1008             JPanel panel = new JPanel();
1009             panel.setMinimumSize(new Dimension(200, 200));
1010             stPanel.add(panel, "cell 4 3");
1011             panel.setLayout(null);
1012             stImageBtn = new JButton("No Image");
1013             stImageBtn.setMaximumSize(new Dimension(75, 75));
1014             stImageBtn.setMinimumSize(new Dimension(75, 75));
1015             panel.add(stImageBtn);
1016             stImageBtn.setBounds(new Rectangle(6, 6, 132, 145));
1017
1018             stImageBtn.addActionListener(new ActionListener() {
1019                 @Override
1020                 public void actionPerformed(final ActionEvent e) {
1021                     int returnVal = imageChooser.showOpenDialog(PresetEditorDialog.this);
1022
1023                     if (returnVal == JFileChooser.APPROVE_OPTION) {
1024                         File file = imageChooser.getSelectedFile();
1025                         stImage = scaleImage(new ImageIcon(file.getAbsolutePath()).getImage(), 155);
1026                         stImageBtn.setIcon(stImage);
1027                     }
1028                 }
1029             });
1030         }
1031
1032         {
1033             JPanel pcPanel = new JPanel();
1034             componentOverlayPanel.add(pcPanel, "PARACHUTE");
1035             pcPanel.setLayout(new MigLayout("", "[][157.00,grow 79][65.00][grow][][]", "[][][][][][]"));
1036             JLabel pcPartNoLabel = new JLabel("Part No:");
1037             pcPanel.add(pcPartNoLabel, "cell 0 0,alignx left");
1038
1039             pcPartNoTextField = new JTextField();
1040             pcPanel.add(pcPartNoTextField, "cell 1 0,growx");
1041             pcPartNoTextField.setColumns(10);
1042
1043             JLabel pcDescLabel = new JLabel("Description:");
1044             pcPanel.add(pcDescLabel, "cell 3 0,alignx left");
1045
1046             pcDescTextField = new JTextField();
1047             pcPanel.add(pcDescTextField, "cell 4 0,growx");
1048             pcDescTextField.setColumns(10);
1049
1050             JLabel pcSidesLabel = new JLabel("Sides:");
1051             pcPanel.add(pcSidesLabel, "cell 0 1,alignx left");
1052
1053             pcSides = new JTextField();
1054             pcPanel.add(pcSides, "cell 1 1, growx");
1055             pcSides.setInputVerifier(NON_NEGATIVE_INTEGER);
1056             pcSides.setColumns(10);
1057
1058             JLabel pcMassLabel = new JLabel("Mass:");
1059             pcPanel.add(pcMassLabel, "cell 3 1,alignx left");
1060
1061             pcMass = new DoubleModel(0, UnitGroup.UNITS_MASS, 0);
1062             JSpinner spin = new JSpinner(pcMass.getSpinnerModel());
1063             spin.setEditor(new SpinnerEditor(spin));
1064             pcPanel.add(spin, "cell 4 1, growx");
1065             pcPanel.add(new UnitSelector(pcMass), "growx");
1066
1067             JLabel pcDiameterLabel = new JLabel("Diameter:");
1068             pcPanel.add(pcDiameterLabel, "cell 0 2,alignx left");
1069
1070             pcDiameter = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0);
1071             spin = new JSpinner(pcDiameter.getSpinnerModel());
1072             spin.setEditor(new SpinnerEditor(spin));
1073             pcPanel.add(spin, "cell 1 2, growx");
1074             pcPanel.add(new UnitSelector(pcDiameter));
1075
1076             JLabel pcLineLengthLabel = new JLabel("Line Length:");
1077             pcPanel.add(pcLineLengthLabel, "cell 3 2,alignx left");
1078
1079             pcLineLength = new DoubleModel(0, UnitGroup.UNITS_LENGTH, 0);
1080             spin = new JSpinner(pcLineLength.getSpinnerModel());
1081             spin.setEditor(new SpinnerEditor(spin));
1082             pcPanel.add(spin, "cell 4 2, growx");
1083             pcPanel.add(new UnitSelector(pcLineLength), "growx");
1084
1085             JLabel pcLineCountLabel = new JLabel("Line Count:");
1086             pcPanel.add(pcLineCountLabel, "cell 3 3,alignx left");
1087
1088             pcLineCount = new JTextField();
1089             pcLineCount.setInputVerifier(NON_NEGATIVE_INTEGER);
1090             pcPanel.add(pcLineCount, "cell 4 3, growx");
1091             pcLineCount.setColumns(10);
1092
1093             JLabel pcLineMaterialLabel = new JLabel("Line Material:");
1094             pcPanel.add(pcLineMaterialLabel, "cell 3 4,alignx left, aligny top, pad 7 0 0 0 ");
1095
1096             pcLineMaterialChooser = new MaterialChooser();
1097             pcLineMaterialChooser.setModel(new MaterialModel(PresetEditorDialog.this, Material.Type.LINE));
1098             pcPanel.add(pcLineMaterialChooser, "cell 4 4, span 3 1, growx, aligny top");
1099
1100             JPanel panel = new JPanel();
1101             panel.setMinimumSize(new Dimension(200, 200));
1102             pcPanel.add(panel, "cell 1 3, span 1 3");
1103             panel.setLayout(null);
1104             pcImageBtn = new JButton("No Image");
1105             pcImageBtn.setMaximumSize(new Dimension(75, 75));
1106             pcImageBtn.setMinimumSize(new Dimension(75, 75));
1107             panel.add(pcImageBtn);
1108             pcImageBtn.setBounds(new Rectangle(6, 6, 132, 145));
1109
1110             pcImageBtn.addActionListener(new ActionListener() {
1111                 @Override
1112                 public void actionPerformed(final ActionEvent e) {
1113                     int returnVal = imageChooser.showOpenDialog(PresetEditorDialog.this);
1114
1115                     if (returnVal == JFileChooser.APPROVE_OPTION) {
1116                         File file = imageChooser.getSelectedFile();
1117                         pcImage = scaleImage(new ImageIcon(file.getAbsolutePath()).getImage(), 155);
1118                         pcImageBtn.setIcon(pcImage);
1119                     }
1120                 }
1121             });
1122         }
1123
1124         JPanel buttonPane = new JPanel();
1125         getContentPane().add(buttonPane, BorderLayout.SOUTH);
1126         buttonPane.setLayout(new MigLayout("", "[130px][176.00px][131.00px]", "[29px]"));
1127         JButton btnSaveAndNew = new JButton("Save and New");
1128         btnSaveAndNew.addMouseListener(new MouseAdapter() {
1129             @Override
1130             public void mouseClicked(MouseEvent arg0) {
1131                 saveResult();
1132             }
1133         });
1134         buttonPane.add(btnSaveAndNew, "cell 0 0,alignx left,aligny top");
1135
1136         JButton okButton = new JButton("Save and Close");
1137         okButton.addActionListener(new ActionListener() {
1138             public void actionPerformed(ActionEvent event) {
1139                 if (saveResult()) {
1140                     dispose();
1141                 }
1142             }
1143         });
1144         okButton.setActionCommand("OK");
1145         buttonPane.add(okButton, "cell 1 0,alignx left,aligny top");
1146         getRootPane().setDefaultButton(okButton);
1147
1148         JButton cancelButton = new JButton("Close");
1149         cancelButton.addActionListener(new ActionListener() {
1150             public void actionPerformed(ActionEvent event) {
1151                 dispose();
1152             }
1153         });
1154         cancelButton.setActionCommand("Close");
1155         buttonPane.add(cancelButton, "cell 6 0,alignx right,aligny top");
1156
1157         if (toEdit != null) {
1158             fillEditor(toEdit, matHolder);
1159         }
1160         holder = matHolder;
1161     }
1162
1163     /**
1164      * When an existing preset is edited, we want to disable the other types of presets.  If the user wants a different
1165      * type of component, then they should delete this one and add a new one.
1166      *
1167      * @param cb     the combo box component
1168      * @param preset the preset being edited
1169      */
1170     private void setItems(DeselectableComboBox cb, ComponentPreset preset) {
1171         cb.addItem(trans.get(NOSE_CONE_KEY), preset != null && !preset.get(ComponentPreset.TYPE).equals(ComponentPreset.Type.NOSE_CONE));
1172         cb.addItem(trans.get(BODY_TUBE_KEY), preset != null && !preset.get(ComponentPreset.TYPE).equals(ComponentPreset.Type.BODY_TUBE));
1173         cb.addItem(trans.get(BULKHEAD_KEY), preset != null && !preset.get(ComponentPreset.TYPE).equals(ComponentPreset.Type.BULK_HEAD));
1174         cb.addItem(trans.get(CR_KEY), preset != null && !preset.get(ComponentPreset.TYPE).equals(ComponentPreset.Type.CENTERING_RING));
1175         cb.addItem(trans.get(EB_KEY), preset != null && !preset.get(ComponentPreset.TYPE).equals(ComponentPreset.Type.ENGINE_BLOCK));
1176         cb.addItem(trans.get(TRANSITION_KEY), preset != null && !preset.get(ComponentPreset.TYPE).equals(ComponentPreset.Type.TRANSITION));
1177         cb.addItem(trans.get(TUBE_COUPLER_KEY), preset != null && !preset.get(ComponentPreset.TYPE).equals(ComponentPreset.Type.TUBE_COUPLER));
1178         cb.addItem(trans.get(LAUNCH_LUG_KEY), preset != null && !preset.get(ComponentPreset.TYPE).equals(ComponentPreset.Type.LAUNCH_LUG));
1179         cb.addItem(trans.get(PARACHUTE_KEY), preset != null && !preset.get(ComponentPreset.TYPE).equals(ComponentPreset.Type.PARACHUTE));
1180         cb.addItem(trans.get(STREAMER_KEY), preset != null && !preset.get(ComponentPreset.TYPE).equals(ComponentPreset.Type.STREAMER));
1181     }
1182
1183     /**
1184      * Create an image chooser.  Currently png and jpg are supported.
1185      *
1186      * @return a file chooser that looks for image files
1187      */
1188     private JFileChooser createImageChooser() {
1189         final JFileChooser chooser = new JFileChooser();
1190         ImagePreviewPanel preview = new ImagePreviewPanel();
1191         chooser.setAccessory(preview);
1192         chooser.addPropertyChangeListener(preview);
1193         chooser.setAcceptAllFileFilterUsed(false);
1194         chooser.addChoosableFileFilter(new FileNameExtensionFilter("Image Files", "png", "jpg", "jpeg"));
1195         return chooser;
1196     }
1197
1198     /**
1199      * To support editing of an existing preset, the swing components need to be prepopulated with the field data.
1200      *
1201      * @param preset the preset to edit
1202      */
1203     private void fillEditor(ComponentPreset preset, MaterialHolder holder) {
1204         ComponentPreset.Type t = preset.getType();
1205
1206         mfgTextField.setText(preset.get(ComponentPreset.MANUFACTURER).getDisplayName());
1207         setMaterial(materialChooser, preset, holder, Material.Type.BULK, ComponentPreset.MATERIAL);
1208         switch (t) {
1209             case BODY_TUBE:
1210                 typeCombo.setSelectedItem(trans.get(BODY_TUBE_KEY));
1211                 btDescTextField.setText(preset.get(ComponentPreset.DESCRIPTION));
1212
1213                 if (preset.has(ComponentPreset.INNER_DIAMETER)) {
1214                     btInnerDia.setValue(preset.get(ComponentPreset.INNER_DIAMETER));
1215                     btInnerDia.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
1216                 }
1217                 if (preset.has(ComponentPreset.LENGTH)) {
1218                     btLength.setValue(preset.get(ComponentPreset.LENGTH));
1219                     btLength.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
1220                 }
1221                 if (preset.has(ComponentPreset.MASS)) {
1222                     btMass.setValue(preset.get(ComponentPreset.MASS));
1223                     btMass.setCurrentUnit(UnitGroup.UNITS_MASS.getDefaultUnit());
1224                 }
1225                 if (preset.has(ComponentPreset.OUTER_DIAMETER)) {
1226                     btOuterDia.setValue(preset.get(ComponentPreset.OUTER_DIAMETER));
1227                     btOuterDia.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
1228                 }
1229                 if (preset.has(ComponentPreset.IMAGE)) {
1230                     btImage = new ImageIcon(byteArrayToImage(preset.get(ComponentPreset.IMAGE)));
1231                     btImageBtn.setIcon(btImage);
1232                 }
1233                 btPartNoTextField.setText(preset.get(ComponentPreset.PARTNO));
1234                 break;
1235             case BULK_HEAD:
1236                 typeCombo.setSelectedItem(trans.get(BULKHEAD_KEY));
1237                 bhDescTextField.setText(preset.get(ComponentPreset.DESCRIPTION));
1238                 if (preset.has(ComponentPreset.LENGTH)) {
1239                     bhLength.setValue(preset.get(ComponentPreset.LENGTH));
1240                     bhLength.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
1241                 }
1242                 if (preset.has(ComponentPreset.MASS)) {
1243                     bhMass.setValue(preset.get(ComponentPreset.MASS));
1244                     bhMass.setCurrentUnit(UnitGroup.UNITS_MASS.getDefaultUnit());
1245                 }
1246                 if (preset.has(ComponentPreset.OUTER_DIAMETER)) {
1247                     bhOuterDia.setValue(preset.get(ComponentPreset.OUTER_DIAMETER));
1248                     bhOuterDia.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
1249                 }
1250                 if (preset.has(ComponentPreset.IMAGE)) {
1251                     bhImage = new ImageIcon(byteArrayToImage(preset.get(ComponentPreset.IMAGE)));
1252                     bhImageBtn.setIcon(bhImage);
1253                 }
1254                 bhPartNoTextField.setText(preset.get(ComponentPreset.PARTNO));
1255                 break;
1256             case CENTERING_RING:
1257                 typeCombo.setSelectedItem(trans.get(CR_KEY));
1258                 crDescTextField.setText(preset.get(ComponentPreset.DESCRIPTION));
1259                 if (preset.has(ComponentPreset.INNER_DIAMETER)) {
1260                     crInnerDia.setValue(preset.get(ComponentPreset.INNER_DIAMETER));
1261                     crInnerDia.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
1262                 }
1263                 if (preset.has(ComponentPreset.LENGTH)) {
1264                     crThickness.setValue(preset.get(ComponentPreset.LENGTH));
1265                     crThickness.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
1266                 }
1267                 if (preset.has(ComponentPreset.MASS)) {
1268                     crMass.setValue(preset.get(ComponentPreset.MASS));
1269                     crMass.setCurrentUnit(UnitGroup.UNITS_MASS.getDefaultUnit());
1270                 }
1271                 if (preset.has(ComponentPreset.OUTER_DIAMETER)) {
1272                     crOuterDia.setValue(preset.get(ComponentPreset.OUTER_DIAMETER));
1273                     crOuterDia.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
1274                 }
1275                 if (preset.has(ComponentPreset.IMAGE)) {
1276                     crImage = new ImageIcon(byteArrayToImage(preset.get(ComponentPreset.IMAGE)));
1277                     crImageBtn.setIcon(crImage);
1278                 }
1279                 crPartNoTextField.setText(preset.get(ComponentPreset.PARTNO));
1280                 break;
1281             case ENGINE_BLOCK:
1282                 typeCombo.setSelectedItem(trans.get(EB_KEY));
1283                 ebDescTextField.setText(preset.get(ComponentPreset.DESCRIPTION));
1284                 if (preset.has(ComponentPreset.INNER_DIAMETER)) {
1285                     ebInnerDia.setValue(preset.get(ComponentPreset.INNER_DIAMETER));
1286                     ebInnerDia.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
1287                 }
1288                 if (preset.has(ComponentPreset.LENGTH)) {
1289                     ebThickness.setValue(preset.get(ComponentPreset.LENGTH));
1290                     ebThickness.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
1291                 }
1292                 if (preset.has(ComponentPreset.MASS)) {
1293                     ebMass.setValue(preset.get(ComponentPreset.MASS));
1294                     ebMass.setCurrentUnit(UnitGroup.UNITS_MASS.getDefaultUnit());
1295                 }
1296                 if (preset.has(ComponentPreset.OUTER_DIAMETER)) {
1297                     ebOuterDia.setValue(preset.get(ComponentPreset.OUTER_DIAMETER));
1298                     ebOuterDia.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
1299                 }
1300                 if (preset.has(ComponentPreset.IMAGE)) {
1301                     ebImage = new ImageIcon(byteArrayToImage(preset.get(ComponentPreset.IMAGE)));
1302                     ebImageBtn.setIcon(ebImage);
1303                 }
1304                 ebPartNoTextField.setText(preset.get(ComponentPreset.PARTNO));
1305                 break;
1306             case NOSE_CONE:
1307                 typeCombo.setSelectedItem(trans.get(NOSE_CONE_KEY));
1308                 ncDescTextField.setText(preset.get(ComponentPreset.DESCRIPTION));
1309                 if (preset.has(ComponentPreset.AFT_OUTER_DIAMETER)) {
1310                     ncAftDia.setValue(preset.get(ComponentPreset.AFT_OUTER_DIAMETER));
1311                     ncAftDia.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
1312                 }
1313                 if (preset.has(ComponentPreset.AFT_SHOULDER_DIAMETER)) {
1314                     ncAftShoulderDia.setValue(preset.get(ComponentPreset.AFT_SHOULDER_DIAMETER));
1315                     ncAftShoulderDia.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
1316                 }
1317                 if (preset.has(ComponentPreset.AFT_SHOULDER_LENGTH)) {
1318                     ncAftShoulderLen.setValue(preset.get(ComponentPreset.AFT_SHOULDER_LENGTH));
1319                     ncAftShoulderLen.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
1320                 }
1321                 if (preset.has(ComponentPreset.MASS)) {
1322                     ncMass.setValue(preset.get(ComponentPreset.MASS));
1323                     ncMass.setCurrentUnit(UnitGroup.UNITS_MASS.getDefaultUnit());
1324                 }
1325                 if (preset.has(ComponentPreset.SHAPE)) {
1326                     ncShapeCB.setSelectedItem(preset.get(ComponentPreset.SHAPE).toString());
1327                 }
1328                 if (preset.has(ComponentPreset.FILLED)) {
1329                     ncFilledCB.setSelected((preset.get(ComponentPreset.FILLED)));
1330                 }
1331                 if (preset.has(ComponentPreset.LENGTH)) {
1332                     ncLength.setValue(preset.get(ComponentPreset.LENGTH));
1333                     ncLength.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
1334                 }
1335                 if (preset.has(ComponentPreset.IMAGE)) {
1336                     ncImage = new ImageIcon(byteArrayToImage(preset.get(ComponentPreset.IMAGE)));
1337                     ncImageBtn.setIcon(ncImage);
1338                 }
1339                 ncPartNoTextField.setText(preset.get(ComponentPreset.PARTNO));
1340                 break;
1341             case TRANSITION:
1342                 typeCombo.setSelectedItem(trans.get(TRANSITION_KEY));
1343                 trDescTextField.setText(preset.get(ComponentPreset.DESCRIPTION));
1344                 if (preset.has(ComponentPreset.AFT_OUTER_DIAMETER)) {
1345                     trAftDia.setValue(preset.get(ComponentPreset.AFT_OUTER_DIAMETER));
1346                     trAftDia.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
1347                 }
1348                 if (preset.has(ComponentPreset.AFT_SHOULDER_DIAMETER)) {
1349                     trAftShoulderDia.setValue(preset.get(ComponentPreset.AFT_SHOULDER_DIAMETER));
1350                     trAftShoulderDia.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
1351                 }
1352                 if (preset.has(ComponentPreset.AFT_SHOULDER_LENGTH)) {
1353                     trAftShoulderLen.setValue(preset.get(ComponentPreset.AFT_SHOULDER_LENGTH));
1354                     trAftShoulderLen.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
1355                 }
1356                 if (preset.has(ComponentPreset.FORE_OUTER_DIAMETER)) {
1357                     trForeDia.setValue(preset.get(ComponentPreset.FORE_OUTER_DIAMETER));
1358                     trForeDia.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
1359                 }
1360                 if (preset.has(ComponentPreset.FORE_SHOULDER_DIAMETER)) {
1361                     trForeShoulderDia.setValue(preset.get(ComponentPreset.FORE_SHOULDER_DIAMETER));
1362                     trForeShoulderDia.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
1363                 }
1364                 if (preset.has(ComponentPreset.FORE_SHOULDER_LENGTH)) {
1365                     trForeShoulderLen.setValue(preset.get(ComponentPreset.FORE_SHOULDER_LENGTH));
1366                     trForeShoulderLen.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
1367                 }
1368                 if (preset.has(ComponentPreset.MASS)) {
1369                     trMass.setValue(preset.get(ComponentPreset.MASS));
1370                     trMass.setCurrentUnit(UnitGroup.UNITS_MASS.getDefaultUnit());
1371                 }
1372                 if (preset.has(ComponentPreset.SHAPE)) {
1373                     trShapeCB.setSelectedItem(preset.get(ComponentPreset.SHAPE).toString());
1374                 }
1375                 if (preset.has(ComponentPreset.FILLED)) {
1376                     trFilledCB.setSelected((preset.get(ComponentPreset.FILLED)));
1377                 }
1378                 if (preset.has(ComponentPreset.LENGTH)) {
1379                     trLength.setValue(preset.get(ComponentPreset.LENGTH));
1380                     trLength.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
1381                 }
1382                 if (preset.has(ComponentPreset.IMAGE)) {
1383                     trImage = new ImageIcon(byteArrayToImage(preset.get(ComponentPreset.IMAGE)));
1384                     trImageBtn.setIcon(trImage);
1385                 }
1386                 trPartNoTextField.setText(preset.get(ComponentPreset.PARTNO));
1387                 break;
1388             case TUBE_COUPLER:
1389                 typeCombo.setSelectedItem(trans.get(TUBE_COUPLER_KEY));
1390                 tcDescTextField.setText(preset.get(ComponentPreset.DESCRIPTION));
1391                 if (preset.has(ComponentPreset.INNER_DIAMETER)) {
1392                     tcInnerDia.setValue(preset.get(ComponentPreset.INNER_DIAMETER));
1393                     tcInnerDia.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
1394                 }
1395                 if (preset.has(ComponentPreset.LENGTH)) {
1396                     tcLength.setValue(preset.get(ComponentPreset.LENGTH));
1397                     tcLength.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
1398                 }
1399                 if (preset.has(ComponentPreset.MASS)) {
1400                     tcMass.setValue(preset.get(ComponentPreset.MASS));
1401                     tcMass.setCurrentUnit(UnitGroup.UNITS_MASS.getDefaultUnit());
1402                 }
1403                 if (preset.has(ComponentPreset.OUTER_DIAMETER)) {
1404                     tcOuterDia.setValue(preset.get(ComponentPreset.OUTER_DIAMETER));
1405                     tcOuterDia.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
1406                 }
1407                 tcPartNoTextField.setText(preset.get(ComponentPreset.PARTNO));
1408                 if (preset.has(ComponentPreset.IMAGE)) {
1409                     tcImage = new ImageIcon(byteArrayToImage(preset.get(ComponentPreset.IMAGE)));
1410                     tcImageBtn.setIcon(tcImage);
1411                 }
1412                 break;
1413             case LAUNCH_LUG:
1414                 typeCombo.setSelectedItem(trans.get(LAUNCH_LUG_KEY));
1415                 llDescTextField.setText(preset.get(ComponentPreset.DESCRIPTION));
1416                 if (preset.has(ComponentPreset.INNER_DIAMETER)) {
1417                     llInnerDia.setValue(preset.get(ComponentPreset.INNER_DIAMETER));
1418                     llInnerDia.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
1419                 }
1420                 if (preset.has(ComponentPreset.LENGTH)) {
1421                     llLength.setValue(preset.get(ComponentPreset.LENGTH));
1422                     llLength.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
1423                 }
1424                 if (preset.has(ComponentPreset.MASS)) {
1425                     llMass.setValue(preset.get(ComponentPreset.MASS));
1426                     llMass.setCurrentUnit(UnitGroup.UNITS_MASS.getDefaultUnit());
1427                 }
1428                 if (preset.has(ComponentPreset.OUTER_DIAMETER)) {
1429                     llOuterDia.setValue(preset.get(ComponentPreset.OUTER_DIAMETER));
1430                     llOuterDia.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
1431                 }
1432                 llPartNoTextField.setText(preset.get(ComponentPreset.PARTNO));
1433                 if (preset.has(ComponentPreset.IMAGE)) {
1434                     llImage = new ImageIcon(byteArrayToImage(preset.get(ComponentPreset.IMAGE)));
1435                     llImageBtn.setIcon(llImage);
1436                 }
1437                 break;
1438             case PARACHUTE:
1439                 setMaterial(materialChooser, preset, holder, Material.Type.SURFACE, ComponentPreset.MATERIAL);
1440                 typeCombo.setSelectedItem(trans.get(PARACHUTE_KEY));
1441                 pcDescTextField.setText(preset.get(ComponentPreset.DESCRIPTION));
1442                 if (preset.has(ComponentPreset.LINE_COUNT)) {
1443                     pcLineCount.setText(preset.get(ComponentPreset.LINE_COUNT).toString());
1444                 }
1445                 if (preset.has(ComponentPreset.SIDES)) {
1446                     pcSides.setText(preset.get(ComponentPreset.SIDES).toString());
1447                 }
1448                 if (preset.has(ComponentPreset.MASS)) {
1449                     pcMass.setValue(preset.get(ComponentPreset.MASS));
1450                     pcMass.setCurrentUnit(UnitGroup.UNITS_MASS.getDefaultUnit());
1451                 }
1452                 if (preset.has(ComponentPreset.DIAMETER)) {
1453                     pcDiameter.setValue(preset.get(ComponentPreset.DIAMETER));
1454                     pcDiameter.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
1455                 }
1456                 if (preset.has(ComponentPreset.LINE_LENGTH)) {
1457                     pcLineLength.setValue(preset.get(ComponentPreset.LINE_LENGTH));
1458                     pcLineLength.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
1459                 }
1460                 pcPartNoTextField.setText(preset.get(ComponentPreset.PARTNO));
1461                 if (preset.has(ComponentPreset.IMAGE)) {
1462                     pcImage = new ImageIcon(byteArrayToImage(preset.get(ComponentPreset.IMAGE)));
1463                     pcImageBtn.setIcon(pcImage);
1464                 }
1465                 setMaterial(pcLineMaterialChooser, preset, holder, Material.Type.LINE, ComponentPreset.LINE_MATERIAL);
1466 //                pcLineMaterialChooser.setModel(new MaterialModel(PresetEditorDialog.this, Material.Type.LINE));
1467
1468 //                pcLineMaterialChooser.getModel().setSelectedItem(preset.get(ComponentPreset.LINE_MATERIAL));
1469                 break;
1470             case STREAMER:
1471                 setMaterial(materialChooser, preset, holder, Material.Type.SURFACE, ComponentPreset.MATERIAL);
1472                 typeCombo.setSelectedItem(trans.get(STREAMER_KEY));
1473                 stDescTextField.setText(preset.get(ComponentPreset.DESCRIPTION));
1474                 if (preset.has(ComponentPreset.LENGTH)) {
1475                     stLength.setValue(preset.get(ComponentPreset.LENGTH));
1476                     stLength.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
1477                 }
1478                 if (preset.has(ComponentPreset.THICKNESS)) {
1479                     stThickness.setValue(preset.get(ComponentPreset.LENGTH));
1480                     stThickness.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
1481                 }
1482                 if (preset.has(ComponentPreset.MASS)) {
1483                     stMass.setValue(preset.get(ComponentPreset.MASS));
1484                     stMass.setCurrentUnit(UnitGroup.UNITS_MASS.getDefaultUnit());
1485                 }
1486                 if (preset.has(ComponentPreset.WIDTH)) {
1487                     stWidth.setValue(preset.get(ComponentPreset.WIDTH));
1488                     stWidth.setCurrentUnit(UnitGroup.UNITS_LENGTH.getDefaultUnit());
1489                 }
1490                 if (preset.has(ComponentPreset.IMAGE)) {
1491                     stImage = new ImageIcon(byteArrayToImage(preset.get(ComponentPreset.IMAGE)));
1492                     stImageBtn.setIcon(stImage);
1493                 }
1494                 stPartNoTextField.setText(preset.get(ComponentPreset.PARTNO));
1495                 break;
1496             default:
1497         }
1498     }
1499
1500     private void setMaterial(final JComboBox chooser, final ComponentPreset preset, final MaterialHolder holder,
1501                              final Material.Type theType, final TypedKey key) {
1502         if (holder == null) {
1503             chooser.setModel(new MaterialModel(PresetEditorDialog.this, theType));
1504         }
1505         else {
1506             chooser.setModel(new MaterialModel(PresetEditorDialog.this, theType,
1507                     holder.asDatabase(theType)));
1508         }
1509         if (preset != null) {
1510             chooser.getModel().setSelectedItem(preset.get(key));
1511         }
1512     }
1513
1514     /**
1515      * Extract the preset data from the UI fields, create a ComponentPreset instance, and notify the listener.
1516      */
1517     private boolean saveResult() {
1518         String type = (String) typeCombo.getSelectedItem();
1519
1520         ComponentPreset result = null;
1521
1522         if (type.equals(trans.get(NOSE_CONE_KEY))) {
1523             result = extractNoseCone();
1524             if (result != null) {
1525                 clearNoseCone();
1526             }
1527         }
1528         else if (type.equals(trans.get(TRANSITION_KEY))) {
1529             result = extractTransition();
1530             if (result != null) {
1531                 clearTransition();
1532             }
1533         }
1534         else if (type.equals(trans.get(BODY_TUBE_KEY))) {
1535             result = extractBodyTube();
1536             if (result != null) {
1537                 clearBodyTube();
1538             }
1539         }
1540         else if (type.equals(trans.get(TUBE_COUPLER_KEY))) {
1541             result = extractTubeCoupler();
1542             if (result != null) {
1543                 clearTubeCoupler();
1544             }
1545         }
1546         else if (type.equals(trans.get(EB_KEY))) {
1547             result = extractEngineBlock();
1548             if (result != null) {
1549                 clearEngineBlock();
1550             }
1551         }
1552         else if (type.equals(trans.get(CR_KEY))) {
1553             result = extractCenteringRing();
1554             if (result != null) {
1555                 clearCenteringRing();
1556             }
1557         }
1558         else if (type.equals(trans.get(BULKHEAD_KEY))) {
1559             result = extractBulkhead();
1560             if (result != null) {
1561                 clearBulkhead();
1562             }
1563         }
1564         else if (type.equals(trans.get(LAUNCH_LUG_KEY))) {
1565             result = extractLaunchLug();
1566             if (result != null) {
1567                 clearLaunchLug();
1568             }
1569         }
1570         else if (type.equals(trans.get(PARACHUTE_KEY))) {
1571             result = extractParachute();
1572             if (result != null) {
1573                 clearParachute();
1574             }
1575         }
1576         else if (type.equals(trans.get(STREAMER_KEY))) {
1577             result = extractStreamer();
1578             if (result != null) {
1579                 clearStreamer();
1580             }
1581         }
1582         if (result != null) {
1583             resultListener.notifyResult(result);
1584             return true;
1585         }
1586         else {
1587             return false;
1588         }
1589     }
1590
1591     private ComponentPreset extractNoseCone() {
1592         TypedPropertyMap props = new TypedPropertyMap();
1593         try {
1594             props.put(ComponentPreset.TYPE, ComponentPreset.Type.NOSE_CONE);
1595             props.put(ComponentPreset.AFT_OUTER_DIAMETER, ncAftDia.getValue());
1596             props.put(ComponentPreset.AFT_SHOULDER_DIAMETER, ncAftShoulderDia.getValue());
1597             props.put(ComponentPreset.AFT_SHOULDER_LENGTH, ncAftShoulderLen.getValue());
1598             props.put(ComponentPreset.DESCRIPTION, ncDescTextField.getText());
1599             props.put(ComponentPreset.PARTNO, ncPartNoTextField.getText());
1600             props.put(ComponentPreset.MANUFACTURER, Manufacturer.getManufacturer(mfgTextField.getText()));
1601             props.put(ComponentPreset.LENGTH, ncLength.getValue());
1602             props.put(ComponentPreset.SHAPE, Transition.Shape.toShape((String) ncShapeCB.getSelectedItem()));
1603             final Material material = (Material) materialChooser.getSelectedItem();
1604             if (material != null) {
1605                 props.put(ComponentPreset.MATERIAL, material);
1606             }
1607             else {
1608                 JOptionPane.showMessageDialog(null, "A material must be selected.", "Error", JOptionPane.ERROR_MESSAGE);
1609                 return null;
1610             }
1611             props.put(ComponentPreset.MASS, ncMass.getValue());
1612             props.put(ComponentPreset.FILLED, ncFilledCB.isSelected());
1613             if (ncImage != null) {
1614                 props.put(ComponentPreset.IMAGE, imageToByteArray(ncImage.getImage()));
1615             }
1616
1617             return ComponentPresetFactory.create(props);
1618         }
1619         catch (NumberFormatException nfe) {
1620             JOptionPane.showMessageDialog(null, "Could not convert nose cone attribute.", "Error", JOptionPane.ERROR_MESSAGE);
1621         }
1622         catch (InvalidComponentPresetException e) {
1623             JOptionPane.showMessageDialog(null, craftErrorMessage(e, "Mandatory nose cone attribute not set."), "Error", JOptionPane.ERROR_MESSAGE);
1624         }
1625         return null;
1626     }
1627
1628     private void clearNoseCone() {
1629         ncAftDia.setValue(0);
1630         ncAftShoulderDia.setValue(0);
1631         ncAftShoulderLen.setValue(0);
1632         ncDescTextField.setText("");
1633         ncPartNoTextField.setText("");
1634         ncLength.setValue(0);
1635         ncMass.setValue(0);
1636         ncFilledCB.setSelected(false);
1637         ncImage = null;
1638         ncImageBtn.setIcon(null);
1639     }
1640
1641     private ComponentPreset extractTransition() {
1642         TypedPropertyMap props = new TypedPropertyMap();
1643         try {
1644             props.put(ComponentPreset.TYPE, ComponentPreset.Type.TRANSITION);
1645             props.put(ComponentPreset.AFT_OUTER_DIAMETER, trAftDia.getValue());
1646             props.put(ComponentPreset.AFT_SHOULDER_DIAMETER, trAftShoulderDia.getValue());
1647             props.put(ComponentPreset.AFT_SHOULDER_LENGTH, trAftShoulderLen.getValue());
1648             props.put(ComponentPreset.FORE_OUTER_DIAMETER, trForeDia.getValue());
1649             props.put(ComponentPreset.FORE_SHOULDER_DIAMETER, trForeShoulderDia.getValue());
1650             props.put(ComponentPreset.FORE_SHOULDER_LENGTH, trForeShoulderLen.getValue());
1651             props.put(ComponentPreset.DESCRIPTION, trDescTextField.getText());
1652             props.put(ComponentPreset.PARTNO, trPartNoTextField.getText());
1653             props.put(ComponentPreset.MANUFACTURER, Manufacturer.getManufacturer(mfgTextField.getText()));
1654
1655             props.put(ComponentPreset.LENGTH, trLength.getValue());
1656             props.put(ComponentPreset.SHAPE, Transition.Shape.toShape((String) trShapeCB.getSelectedItem()));
1657             final Material material = (Material) materialChooser.getSelectedItem();
1658             if (material != null) {
1659                 props.put(ComponentPreset.MATERIAL, material);
1660             }
1661             else {
1662                 JOptionPane.showMessageDialog(null, "A material must be selected.", "Error", JOptionPane.ERROR_MESSAGE);
1663                 return null;
1664             }
1665             props.put(ComponentPreset.MASS, trMass.getValue());
1666             props.put(ComponentPreset.FILLED, trFilledCB.isSelected());
1667             if (trImage != null) {
1668                 props.put(ComponentPreset.IMAGE, imageToByteArray(trImage.getImage()));
1669             }
1670
1671             return ComponentPresetFactory.create(props);
1672         }
1673         catch (NumberFormatException nfe) {
1674             JOptionPane.showMessageDialog(null, "Could not convert transition attribute.", "Error", JOptionPane.ERROR_MESSAGE);
1675         }
1676         catch (InvalidComponentPresetException e) {
1677             JOptionPane.showMessageDialog(null, craftErrorMessage(e, "Mandatory transition attribute not set."), "Error", JOptionPane.ERROR_MESSAGE);
1678         }
1679         return null;
1680     }
1681
1682     private void clearTransition() {
1683         trAftDia.setValue(0);
1684         trAftShoulderDia.setValue(0);
1685         trAftShoulderLen.setValue(0);
1686         trForeDia.setValue(0);
1687         trForeShoulderDia.setValue(0);
1688         trForeShoulderLen.setValue(0);
1689         trDescTextField.setText("");
1690         trPartNoTextField.setText("");
1691         trLength.setValue(0);
1692         trMass.setValue(0);
1693         trFilledCB.setSelected(false);
1694         trImage = null;
1695         trImageBtn.setIcon(null);
1696     }
1697
1698     private ComponentPreset extractBodyTube() {
1699         TypedPropertyMap props = new TypedPropertyMap();
1700         try {
1701             props.put(ComponentPreset.TYPE, ComponentPreset.Type.BODY_TUBE);
1702             props.put(ComponentPreset.OUTER_DIAMETER, btOuterDia.getValue());
1703             props.put(ComponentPreset.INNER_DIAMETER, btInnerDia.getValue());
1704             props.put(ComponentPreset.DESCRIPTION, btDescTextField.getText());
1705             props.put(ComponentPreset.PARTNO, btPartNoTextField.getText());
1706             props.put(ComponentPreset.MANUFACTURER, Manufacturer.getManufacturer(mfgTextField.getText()));
1707             props.put(ComponentPreset.LENGTH, btLength.getValue());
1708             final Material material = (Material) materialChooser.getSelectedItem();
1709             if (material != null) {
1710                 props.put(ComponentPreset.MATERIAL, material);
1711             }
1712             else {
1713                 JOptionPane.showMessageDialog(null, "A material must be selected.", "Error", JOptionPane.ERROR_MESSAGE);
1714                 return null;
1715             }
1716             props.put(ComponentPreset.MASS, btMass.getValue());
1717             if (btImage != null) {
1718                 props.put(ComponentPreset.IMAGE, imageToByteArray(btImage.getImage()));
1719             }
1720             return ComponentPresetFactory.create(props);
1721         }
1722         catch (NumberFormatException nfe) {
1723             JOptionPane.showMessageDialog(null, "Could not convert body tube attribute.", "Error", JOptionPane.ERROR_MESSAGE);
1724         }
1725         catch (InvalidComponentPresetException e) {
1726             JOptionPane.showMessageDialog(null, craftErrorMessage(e, "Mandatory body tube attribute not set."), "Error", JOptionPane.ERROR_MESSAGE);
1727         }
1728         return null;
1729     }
1730
1731     private void clearBodyTube() {
1732         btOuterDia.setValue(0);
1733         btInnerDia.setValue(0);
1734         btDescTextField.setText("");
1735         btPartNoTextField.setText("");
1736         btLength.setValue(0);
1737         btMass.setValue(0);
1738         btImage = null;
1739         btImageBtn.setIcon(null);
1740     }
1741
1742     public ComponentPreset extractTubeCoupler() {
1743         TypedPropertyMap props = new TypedPropertyMap();
1744         try {
1745             props.put(ComponentPreset.TYPE, ComponentPreset.Type.TUBE_COUPLER);
1746             props.put(ComponentPreset.OUTER_DIAMETER, tcOuterDia.getValue());
1747             props.put(ComponentPreset.INNER_DIAMETER, tcInnerDia.getValue());
1748             props.put(ComponentPreset.DESCRIPTION, tcDescTextField.getText());
1749             props.put(ComponentPreset.PARTNO, tcPartNoTextField.getText());
1750             props.put(ComponentPreset.MANUFACTURER, Manufacturer.getManufacturer(mfgTextField.getText()));
1751             props.put(ComponentPreset.LENGTH, tcLength.getValue());
1752             final Material material = (Material) materialChooser.getSelectedItem();
1753             if (material != null) {
1754                 props.put(ComponentPreset.MATERIAL, material);
1755             }
1756             else {
1757                 JOptionPane.showMessageDialog(null, "A material must be selected.", "Error", JOptionPane.ERROR_MESSAGE);
1758                 return null;
1759             }
1760             props.put(ComponentPreset.MASS, tcMass.getValue());
1761             if (tcImage != null) {
1762                 props.put(ComponentPreset.IMAGE, imageToByteArray(tcImage.getImage()));
1763             }
1764
1765             return ComponentPresetFactory.create(props);
1766         }
1767         catch (NumberFormatException nfe) {
1768             JOptionPane.showMessageDialog(null, "Could not convert tube coupler attribute.", "Error", JOptionPane.ERROR_MESSAGE);
1769         }
1770         catch (InvalidComponentPresetException e) {
1771             JOptionPane.showMessageDialog(null, craftErrorMessage(e, "Mandatory tube coupler attribute not set."), "Error", JOptionPane.ERROR_MESSAGE);
1772         }
1773         return null;
1774     }
1775
1776     private void clearTubeCoupler() {
1777         tcOuterDia.setValue(0);
1778         tcInnerDia.setValue(0);
1779         tcDescTextField.setText("");
1780         tcPartNoTextField.setText("");
1781         tcLength.setValue(0);
1782         tcMass.setValue(0);
1783         tcImage = null;
1784         tcImageBtn.setIcon(null);
1785     }
1786
1787     private ComponentPreset extractBulkhead() {
1788         TypedPropertyMap props = new TypedPropertyMap();
1789         try {
1790             props.put(ComponentPreset.TYPE, ComponentPreset.Type.BULK_HEAD);
1791             props.put(ComponentPreset.OUTER_DIAMETER, bhOuterDia.getValue());
1792             props.put(ComponentPreset.DESCRIPTION, bhDescTextField.getText());
1793             props.put(ComponentPreset.PARTNO, bhPartNoTextField.getText());
1794             props.put(ComponentPreset.MANUFACTURER, Manufacturer.getManufacturer(mfgTextField.getText()));
1795             props.put(ComponentPreset.LENGTH, bhLength.getValue());
1796             final Material material = (Material) materialChooser.getSelectedItem();
1797             if (material != null) {
1798                 props.put(ComponentPreset.MATERIAL, material);
1799             }
1800             else {
1801                 JOptionPane.showMessageDialog(null, "A material must be selected.", "Error", JOptionPane.ERROR_MESSAGE);
1802                 return null;
1803             }
1804             props.put(ComponentPreset.MASS, bhMass.getValue());
1805             if (bhImage != null) {
1806                 props.put(ComponentPreset.IMAGE, imageToByteArray(bhImage.getImage()));
1807             }
1808             return ComponentPresetFactory.create(props);
1809         }
1810         catch (NumberFormatException nfe) {
1811             JOptionPane.showMessageDialog(null, "Could not convert bulkhead attribute.", "Error", JOptionPane.ERROR_MESSAGE);
1812         }
1813         catch (InvalidComponentPresetException e) {
1814             JOptionPane.showMessageDialog(null, craftErrorMessage(e, "Mandatory bulkhead attribute not set."), "Error", JOptionPane.ERROR_MESSAGE);
1815         }
1816         return null;
1817     }
1818
1819     private void clearBulkhead() {
1820         bhOuterDia.setValue(0);
1821         bhDescTextField.setText("");
1822         bhPartNoTextField.setText("");
1823         bhLength.setValue(0);
1824         bhMass.setValue(0);
1825         bhImage = null;
1826         bhImageBtn.setIcon(null);
1827     }
1828
1829     private ComponentPreset extractCenteringRing() {
1830         TypedPropertyMap props = new TypedPropertyMap();
1831         try {
1832             props.put(ComponentPreset.TYPE, ComponentPreset.Type.CENTERING_RING);
1833             props.put(ComponentPreset.OUTER_DIAMETER, crOuterDia.getValue());
1834             props.put(ComponentPreset.INNER_DIAMETER, crInnerDia.getValue());
1835             props.put(ComponentPreset.DESCRIPTION, crDescTextField.getText());
1836             props.put(ComponentPreset.PARTNO, crPartNoTextField.getText());
1837             props.put(ComponentPreset.MANUFACTURER, Manufacturer.getManufacturer(mfgTextField.getText()));
1838             props.put(ComponentPreset.LENGTH, crThickness.getValue());
1839             final Material material = (Material) materialChooser.getSelectedItem();
1840             if (material != null) {
1841                 props.put(ComponentPreset.MATERIAL, material);
1842             }
1843             else {
1844                 JOptionPane.showMessageDialog(null, "A material must be selected.", "Error", JOptionPane.ERROR_MESSAGE);
1845                 return null;
1846             }
1847             props.put(ComponentPreset.MASS, crMass.getValue());
1848             if (crImage != null) {
1849                 props.put(ComponentPreset.IMAGE, imageToByteArray(crImage.getImage()));
1850             }
1851             return ComponentPresetFactory.create(props);
1852         }
1853         catch (NumberFormatException nfe) {
1854             JOptionPane.showMessageDialog(null, "Could not convert centering ring attribute.", "Error", JOptionPane.ERROR_MESSAGE);
1855         }
1856         catch (InvalidComponentPresetException e) {
1857             JOptionPane.showMessageDialog(null, craftErrorMessage(e, "Mandatory centering ring attribute not set."), "Error", JOptionPane.ERROR_MESSAGE);
1858         }
1859         return null;
1860     }
1861
1862     private void clearCenteringRing() {
1863         crOuterDia.setValue(0);
1864         crInnerDia.setValue(0);
1865         crDescTextField.setText("");
1866         crPartNoTextField.setText("");
1867         crThickness.setValue(0);
1868         crMass.setValue(0);
1869         crImage = null;
1870         crImageBtn.setIcon(null);
1871     }
1872
1873     public ComponentPreset extractEngineBlock() {
1874         TypedPropertyMap props = new TypedPropertyMap();
1875         try {
1876             props.put(ComponentPreset.TYPE, ComponentPreset.Type.ENGINE_BLOCK);
1877             props.put(ComponentPreset.OUTER_DIAMETER, ebOuterDia.getValue());
1878             props.put(ComponentPreset.INNER_DIAMETER, ebInnerDia.getValue());
1879             props.put(ComponentPreset.DESCRIPTION, ebDescTextField.getText());
1880             props.put(ComponentPreset.PARTNO, ebPartNoTextField.getText());
1881             props.put(ComponentPreset.MANUFACTURER, Manufacturer.getManufacturer(mfgTextField.getText()));
1882             props.put(ComponentPreset.LENGTH, ebThickness.getValue());
1883             final Material material = (Material) materialChooser.getSelectedItem();
1884             if (material != null) {
1885                 props.put(ComponentPreset.MATERIAL, material);
1886             }
1887             else {
1888                 JOptionPane.showMessageDialog(null, "A material must be selected.", "Error", JOptionPane.ERROR_MESSAGE);
1889                 return null;
1890             }
1891             props.put(ComponentPreset.MASS, ebMass.getValue());
1892             if (ebImage != null) {
1893                 props.put(ComponentPreset.IMAGE, imageToByteArray(ebImage.getImage()));
1894             }
1895             return ComponentPresetFactory.create(props);
1896         }
1897         catch (NumberFormatException nfe) {
1898             JOptionPane.showMessageDialog(null, "Could not convert engine block attribute.", "Error", JOptionPane.ERROR_MESSAGE);
1899         }
1900         catch (InvalidComponentPresetException e) {
1901             JOptionPane.showMessageDialog(null, craftErrorMessage(e, "Mandatory engine block attribute not set."), "Error", JOptionPane.ERROR_MESSAGE);
1902         }
1903         return null;
1904     }
1905
1906     private void clearEngineBlock() {
1907         ebOuterDia.setValue(0);
1908         ebInnerDia.setValue(0);
1909         ebDescTextField.setText("");
1910         ebPartNoTextField.setText("");
1911         ebThickness.setValue(0);
1912         ebMass.setValue(0);
1913         ebImage = null;
1914         ebImageBtn.setIcon(null);
1915     }
1916
1917     public ComponentPreset extractLaunchLug() {
1918         TypedPropertyMap props = new TypedPropertyMap();
1919         try {
1920             props.put(ComponentPreset.TYPE, ComponentPreset.Type.LAUNCH_LUG);
1921             props.put(ComponentPreset.OUTER_DIAMETER, llOuterDia.getValue());
1922             props.put(ComponentPreset.INNER_DIAMETER, llInnerDia.getValue());
1923             props.put(ComponentPreset.DESCRIPTION, llDescTextField.getText());
1924             props.put(ComponentPreset.PARTNO, llPartNoTextField.getText());
1925             props.put(ComponentPreset.MANUFACTURER, Manufacturer.getManufacturer(mfgTextField.getText()));
1926             props.put(ComponentPreset.LENGTH, llLength.getValue());
1927             final Material material = (Material) materialChooser.getSelectedItem();
1928             if (material != null) {
1929                 props.put(ComponentPreset.MATERIAL, material);
1930             }
1931             else {
1932                 JOptionPane.showMessageDialog(null, "A material must be selected.", "Error", JOptionPane.ERROR_MESSAGE);
1933                 return null;
1934             }
1935             props.put(ComponentPreset.MASS, llMass.getValue());
1936             if (llImage != null) {
1937                 props.put(ComponentPreset.IMAGE, imageToByteArray(llImage.getImage()));
1938             }
1939             return ComponentPresetFactory.create(props);
1940         }
1941         catch (NumberFormatException nfe) {
1942             JOptionPane.showMessageDialog(null, "Could not convert launch lug attribute.", "Error", JOptionPane.ERROR_MESSAGE);
1943         }
1944         catch (InvalidComponentPresetException e) {
1945             JOptionPane.showMessageDialog(null, craftErrorMessage(e, "Mandatory launch lug attribute not set."), "Error", JOptionPane.ERROR_MESSAGE);
1946         }
1947         return null;
1948     }
1949
1950     private void clearLaunchLug() {
1951         llOuterDia.setValue(0);
1952         llInnerDia.setValue(0);
1953         llDescTextField.setText("");
1954         llPartNoTextField.setText("");
1955         llLength.setValue(0);
1956         llMass.setValue(0);
1957         llImage = null;
1958         llImageBtn.setIcon(null);
1959     }
1960
1961     public ComponentPreset extractParachute() {
1962         TypedPropertyMap props = new TypedPropertyMap();
1963         try {
1964             props.put(ComponentPreset.TYPE, ComponentPreset.Type.PARACHUTE);
1965             props.put(ComponentPreset.DIAMETER, pcDiameter.getValue());
1966             props.put(ComponentPreset.DESCRIPTION, pcDescTextField.getText());
1967             props.put(ComponentPreset.PARTNO, pcPartNoTextField.getText());
1968             props.put(ComponentPreset.MANUFACTURER, Manufacturer.getManufacturer(mfgTextField.getText()));
1969             if (!pcLineCount.getText().equals("")) {
1970                 props.put(ComponentPreset.LINE_COUNT, Integer.parseInt(pcLineCount.getText()));
1971             }
1972             if (!pcSides.getText().equals("")) {
1973                 props.put(ComponentPreset.SIDES, Integer.parseInt(pcSides.getText()));
1974             }
1975             props.put(ComponentPreset.LINE_LENGTH, pcLineLength.getValue());
1976             Material material = (Material) materialChooser.getSelectedItem();
1977             if (material != null) {
1978                 props.put(ComponentPreset.MATERIAL, material);
1979             }
1980             else {
1981                 JOptionPane.showMessageDialog(null, "A material must be selected.", "Error", JOptionPane.ERROR_MESSAGE);
1982                 return null;
1983             }
1984             material = (Material) pcLineMaterialChooser.getSelectedItem();
1985             if (material != null) {
1986                 props.put(ComponentPreset.LINE_MATERIAL, material);
1987             }
1988             props.put(ComponentPreset.MASS, pcMass.getValue());
1989             if (pcImage != null) {
1990                 props.put(ComponentPreset.IMAGE, imageToByteArray(pcImage.getImage()));
1991             }
1992             return ComponentPresetFactory.create(props);
1993         }
1994         catch (NumberFormatException nfe) {
1995             JOptionPane.showMessageDialog(null, "Could not convert parachute attribute.", "Error", JOptionPane.ERROR_MESSAGE);
1996         }
1997         catch (InvalidComponentPresetException e) {
1998             JOptionPane.showMessageDialog(null, craftErrorMessage(e, "Mandatory parachute attribute not set."), "Error", JOptionPane.ERROR_MESSAGE);
1999         }
2000         return null;
2001     }
2002
2003     private void clearParachute() {
2004         ebOuterDia.setValue(0);
2005         ebInnerDia.setValue(0);
2006         ebDescTextField.setText("");
2007         ebPartNoTextField.setText("");
2008         ebThickness.setValue(0);
2009         ebMass.setValue(0);
2010         ebImage = null;
2011         ebImageBtn.setIcon(null);
2012     }
2013
2014     public ComponentPreset extractStreamer() {
2015         TypedPropertyMap props = new TypedPropertyMap();
2016         try {
2017             props.put(ComponentPreset.TYPE, ComponentPreset.Type.STREAMER);
2018             props.put(ComponentPreset.DESCRIPTION, stDescTextField.getText());
2019             props.put(ComponentPreset.PARTNO, stPartNoTextField.getText());
2020             props.put(ComponentPreset.MANUFACTURER, Manufacturer.getManufacturer(mfgTextField.getText()));
2021             props.put(ComponentPreset.THICKNESS, stThickness.getValue());
2022             props.put(ComponentPreset.LENGTH, stLength.getValue());
2023             props.put(ComponentPreset.WIDTH, stWidth.getValue());
2024             final Material material = (Material) materialChooser.getSelectedItem();
2025             if (material != null) {
2026                 props.put(ComponentPreset.MATERIAL, material);
2027             }
2028             else {
2029                 JOptionPane.showMessageDialog(null, "A material must be selected.", "Error", JOptionPane.ERROR_MESSAGE);
2030                 return null;
2031             }
2032             props.put(ComponentPreset.MASS, stMass.getValue());
2033             if (stImage != null) {
2034                 props.put(ComponentPreset.IMAGE, imageToByteArray(stImage.getImage()));
2035             }
2036             return ComponentPresetFactory.create(props);
2037         }
2038         catch (NumberFormatException nfe) {
2039             JOptionPane.showMessageDialog(null, "Could not convert engine block attribute.", "Error", JOptionPane.ERROR_MESSAGE);
2040         }
2041         catch (InvalidComponentPresetException e) {
2042             JOptionPane.showMessageDialog(null, craftErrorMessage(e, "Mandatory engine block attribute not set."), "Error", JOptionPane.ERROR_MESSAGE);
2043         }
2044         return null;
2045     }
2046
2047     private void clearStreamer() {
2048         stWidth.setValue(0);
2049         stLength.setValue(0);
2050         stDescTextField.setText("");
2051         stPartNoTextField.setText("");
2052         stThickness.setValue(0);
2053         stMass.setValue(0);
2054         stImage = null;
2055         stImageBtn.setIcon(null);
2056     }
2057
2058     public void itemStateChanged(ItemEvent evt) {
2059         CardLayout cl = (CardLayout) (componentOverlayPanel.getLayout());
2060         final String item = (String) evt.getItem();
2061         if (materialChooser != null && evt.getStateChange() == ItemEvent.SELECTED) {
2062             if (item.equals(trans.get(PARACHUTE_KEY)) || item.equals(trans.get(STREAMER_KEY))) {
2063                 if (!((MaterialModel) materialChooser.getModel()).getType().equals(Material.Type.SURFACE)) {
2064                     setMaterial(materialChooser, null, holder, Material.Type.SURFACE, ComponentPreset.MATERIAL);
2065                 }
2066             }
2067             else {
2068                 if (!((MaterialModel) materialChooser.getModel()).getType().equals(Material.Type.BULK)) {
2069                     setMaterial(materialChooser, null, holder, Material.Type.BULK, ComponentPreset.MATERIAL);
2070                 }
2071             }
2072         }
2073         cl.show(componentOverlayPanel, componentMap.get(item));
2074     }
2075
2076     //Todo: I18N
2077     private String craftErrorMessage(InvalidComponentPresetException e, String baseMsg) {
2078         StringBuilder stringBuilder = new StringBuilder();
2079         List<String> invalids = e.getErrors();
2080         stringBuilder.append(baseMsg).append("\n");
2081         for (int i = 0; i < invalids.size(); i++) {
2082             String s = invalids.get(i);
2083             stringBuilder.append(s).append("\n");
2084         }
2085
2086         return stringBuilder.toString();
2087     }
2088
2089     /**
2090      * Convert an image to a byte array in png format.
2091      *
2092      * @param originalImage
2093      *
2094      * @return
2095      */
2096     private byte[] imageToByteArray(Image originalImage) {
2097         byte[] imageInByte = null;
2098         try {
2099             BufferedImage bi = imageToBufferedImage(originalImage);
2100             ByteArrayOutputStream baos = new ByteArrayOutputStream();
2101             ImageIO.write(bi, "png", baos);
2102             baos.flush();
2103             imageInByte = baos.toByteArray();
2104             baos.close();
2105         }
2106         catch (IOException e) {
2107             log.error("Could not read image.");
2108         }
2109         return imageInByte;
2110     }
2111
2112     private BufferedImage imageToBufferedImage(final Image originalImage) {
2113         BufferedImage bi = new BufferedImage(originalImage.getWidth(null), originalImage.getHeight(null), BufferedImage.TYPE_INT_RGB);
2114
2115         Graphics2D g2 = bi.createGraphics();
2116         g2.drawImage(originalImage, 0, 0, null);
2117         return bi;
2118     }
2119
2120     private BufferedImage byteArrayToImage(byte[] src) {
2121         // convert byte array back to BufferedImage
2122         InputStream in = new ByteArrayInputStream(src);
2123         try {
2124             return ImageIO.read(in);
2125         }
2126         catch (IOException e) {
2127             log.error("Could not convert image.");
2128         }
2129         return null;
2130     }
2131
2132     private ImageIcon scaleImage(Image image, int targetDimension) {
2133         int width = image.getWidth(this);
2134         int height = image.getHeight(this);
2135         double ratio = 1.0;
2136
2137         /*
2138          * Determine how to scale the image. Since the accessory can expand
2139          * vertically make sure we don't go larger than 150 when scaling
2140          * vertically.
2141          */
2142         if (width >= height) {
2143             ratio = (double) (targetDimension - 5) / width;
2144             width = targetDimension - 5;
2145             height = (int) (height * ratio);
2146         }
2147         else {
2148             if (getHeight() > 150) {
2149                 ratio = (double) (targetDimension - 5) / height;
2150                 height = targetDimension - 5;
2151                 width = (int) (width * ratio);
2152             }
2153             else {
2154                 ratio = (double) getHeight() / height;
2155                 height = getHeight();
2156                 width = (int) (width * ratio);
2157             }
2158         }
2159
2160         return new ImageIcon(image.getScaledInstance(width, height, Image.SCALE_DEFAULT));
2161     }
2162
2163     static class PresetInputVerifier extends InputVerifier {
2164
2165         /**
2166          * Matches user input against a regular expression.
2167          */
2168         private Matcher matcher;
2169
2170         PresetInputVerifier(final Pattern thePattern) {
2171             matcher = thePattern.matcher("");
2172         }
2173
2174         /**
2175          * Return true only if the untrimmed user input matches the regular expression provided to the constructor.
2176          *
2177          * @param aComponent must be an instance of JTextComponent.
2178          */
2179         public boolean verify(JComponent aComponent) {
2180             JTextComponent textComponent = (JTextComponent) aComponent;
2181             String text = textComponent.getText();
2182             matcher.reset(text);
2183             return matcher.matches();
2184         }
2185
2186         /**
2187          * Always returns <tt>true</tt>, in this implementation, such that focus can always transfer to another
2188          * component whenever the validation fails.
2189          * <p/>
2190          * <P>If <tt>super.shouldYieldFocus</tt> returns <tt>false</tt>, then clear the text field.
2191          *
2192          * @param aComponent is a <tt>JTextComponent</tt>.
2193          */
2194         @Override
2195         public boolean shouldYieldFocus(JComponent aComponent) {
2196             if (!super.shouldYieldFocus(aComponent)) {
2197                 ((JTextComponent) aComponent).setText("");
2198             }
2199             return true;
2200         }
2201     }
2202
2203     class MaterialChooser extends JComboBox {
2204
2205         public MaterialChooser() {
2206         }
2207         public MaterialChooser(MaterialModel model) {
2208             super(model);
2209         }
2210
2211         /**
2212          * Sets the data model that the <code>JComboBox</code> uses to obtain the list of items.
2213          *
2214          * @param aModel the <code>ComboBoxModel</code> that provides the displayed list of items
2215          *
2216          * @beaninfo bound: true description: Model that the combo box uses to get data to display.
2217          */
2218         @Override
2219         public void setModel(final ComboBoxModel aModel) {
2220             if (getModel() instanceof MaterialModel) {
2221                 MaterialModel old = (MaterialModel) getModel();
2222                 old.removeListener();
2223             }
2224             super.setModel(aModel);
2225
2226         }
2227     }
2228 }