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