Fixes to number validation and component type combo box selectability.
[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.print.PrintUnit;
5 import net.sf.openrocket.l10n.Translator;
6 import net.sf.openrocket.logging.LogHelper;
7 import net.sf.openrocket.material.Material;
8 import net.sf.openrocket.motor.Manufacturer;
9 import net.sf.openrocket.preset.ComponentPreset;
10 import net.sf.openrocket.preset.ComponentPresetFactory;
11 import net.sf.openrocket.preset.InvalidComponentPresetException;
12 import net.sf.openrocket.preset.TypedPropertyMap;
13 import net.sf.openrocket.rocketcomponent.Transition;
14 import net.sf.openrocket.startup.Application;
15
16 import javax.imageio.ImageIO;
17 import javax.swing.*;
18 import javax.swing.border.EmptyBorder;
19 import javax.swing.filechooser.FileFilter;
20 import javax.swing.text.JTextComponent;
21 import java.awt.*;
22 import java.awt.event.ActionEvent;
23 import java.awt.event.ActionListener;
24 import java.awt.event.ItemEvent;
25 import java.awt.event.ItemListener;
26 import java.awt.event.MouseAdapter;
27 import java.awt.event.MouseEvent;
28 import java.awt.image.BufferedImage;
29 import java.io.ByteArrayInputStream;
30 import java.io.ByteArrayOutputStream;
31 import java.io.File;
32 import java.io.IOException;
33 import java.io.InputStream;
34 import java.util.HashMap;
35 import java.util.Map;
36 import java.util.regex.Matcher;
37 import java.util.regex.Pattern;
38
39 public class PresetEditorDialog extends JDialog implements ItemListener {
40
41     private static Translator trans = Application.getTranslator();
42
43     private static LogHelper log = Application.getLogger();
44
45     private static final String NON_NEGATIVE_DECIMAL_FIELD = "(\\d){1,10}\\.(\\d){1,10}";
46
47     /**
48      * Input of non-negative decimals.
49      */
50     final PresetInputVerifier NON_NEGATIVE_DECIMAL =
51             new PresetInputVerifier(Pattern.compile(NON_NEGATIVE_DECIMAL_FIELD));
52
53     private final JPanel contentPanel = new JPanel();
54     private DeselectableComboBox typeCombo;
55     private JTextField mfgTextField;
56     private JComboBox materialChooser;
57     private JComboBox massUnitCombo;
58     private JComboBox lenUnitCombo;
59
60     private JTextField ncPartNoTextField;
61     private JTextField ncDescTextField;
62     private JTextField ncLengthTextField;
63     private JCheckBox ncFilledCB;
64     private JComboBox ncShapeCB;
65     private JTextField ncAftDiaTextField;
66     private JTextField ncAftShoulderDiaTextField;
67     private JTextField ncAftShoulderLenTextField;
68     private JTextField ncMassTextField;
69     private ImageIcon ncImage;
70     private JButton ncImageBtn;
71
72     private JTextField trPartNoTextField;
73     private JTextField trDescTextField;
74     private JTextField trLengthTextField;
75     private JTextField trAftDiaTextField;
76     private JTextField trAftShoulderDiaTextField;
77     private JTextField trAftShoulderLenTextField;
78     private JTextField trForeDiaTextField;
79     private JTextField trForeShoulderDiaTextField;
80     private JTextField trForeShoulderLenTextField;
81     private JTextField trMassTextField;
82     private ImageIcon trImage;
83     private JCheckBox trFilledCB;
84     private JComboBox trShapeCB;
85     private JButton trImageBtn;
86
87     private JTextField btPartNoTextField;
88     private JTextField btDescTextField;
89     private JTextField btMassTextField;
90     private JTextField btInnerDiaTextField;
91     private JTextField btOuterDiaTextField;
92     private JTextField btLengthTextField;
93     private ImageIcon btImage;
94     private JButton btImageBtn;
95
96     private JTextField tcPartNoTextField;
97     private JTextField tcDescTextField;
98     private JTextField tcMassTextField;
99     private JTextField tcInnerDiaTextField;
100     private JTextField tcOuterDiaTextField;
101     private JTextField tcLengthTextField;
102     private ImageIcon tcImage;
103     private JButton tcImageBtn;
104
105     private JTextField bhPartNoTextField;
106     private JTextField bhDescTextField;
107     private JTextField bhOuterDiaTextField;
108     private JTextField bhLengthTextField;
109     private JTextField bhMassTextField;
110     private ImageIcon bhImage;
111     private JButton bhImageBtn;
112
113     private JTextField crPartNoTextField;
114     private JTextField crDescTextField;
115     private JTextField crOuterDiaTextField;
116     private JTextField crInnerDiaTextField;
117     private JTextField crThicknessTextField;
118     private JTextField crMassTextField;
119     private ImageIcon crImage;
120     private JButton crImageBtn;
121
122     private JTextField ebPartNoTextField;
123     private JTextField ebDescTextField;
124     private JTextField ebOuterDiaTextField;
125     private JTextField ebInnerDiaTextField;
126     private JTextField ebThicknessTextField;
127     private JTextField ebMassTextField;
128     private ImageIcon ebImage;
129     private JButton ebImageBtn;
130
131     private final JFileChooser imageChooser = createImageChooser();
132
133     private JPanel componentOverlayPanel;
134
135     private PresetResultListener resultListener;
136
137     private static Map<String, String> componentMap = new HashMap<String, String>();
138     private static Map<String, PrintUnit> lengthMap = new HashMap<String, PrintUnit>();
139
140     private static final String NOSE_CONE_KEY = "NoseCone.NoseCone";
141     private static final String BODY_TUBE_KEY = "BodyTube.BodyTube";
142     private static final String TUBE_COUPLER_KEY = "TubeCoupler.TubeCoupler";
143     private static final String TRANSITION_KEY = "Transition.Transition";
144     private static final String CR_KEY = "ComponentIcons.Centeringring";
145     private static final String BULKHEAD_KEY = "Bulkhead.Bulkhead";
146     private static final String EB_KEY = "ComponentIcons.Engineblock";
147
148
149     static {
150         componentMap.put(trans.get(NOSE_CONE_KEY), "NOSECONE");
151         componentMap.put(trans.get(BODY_TUBE_KEY), "BODYTUBE");
152         componentMap.put(trans.get(TUBE_COUPLER_KEY), "TUBECOUPLER");
153         componentMap.put(trans.get(TRANSITION_KEY), "TRANSITION");
154         componentMap.put(trans.get(CR_KEY), "CENTERINGRING");
155         componentMap.put(trans.get(BULKHEAD_KEY), "BULKHEAD");
156         componentMap.put(trans.get(EB_KEY), "ENGINEBLOCK");
157
158         lengthMap.put("m", PrintUnit.METERS);
159         lengthMap.put("cm", PrintUnit.CENTIMETERS);
160         lengthMap.put("mm", PrintUnit.MILLIMETERS);
161         lengthMap.put("in", PrintUnit.INCHES);
162         lengthMap.put("ft", PrintUnit.FOOT);
163     }
164
165     /**
166      * Create the dialog.
167      *
168      * @param theCallback the listener that gets the results of editing the presets
169      */
170     public PresetEditorDialog(PresetResultListener theCallback) {
171         this(theCallback, null);
172     }
173
174     /**
175      * Create the dialog.
176      *
177      * @param theCallback the listener that gets the results of editing the presets
178      * @param toEdit      the ComponentPreset to be edited; or null if a new one is being added
179      */
180     public PresetEditorDialog(PresetResultListener theCallback, ComponentPreset toEdit) {
181         resultListener = theCallback;
182         getContentPane().setMinimumSize(new Dimension(200, 200));
183         setBounds(100, 100, 720, 610);
184         getContentPane().setLayout(new BorderLayout());
185         contentPanel.setBorder(new EmptyBorder(5, 5, 5, 5));
186         getContentPane().add(contentPanel, BorderLayout.CENTER);
187         contentPanel.setLayout(new MigLayout("", "[][grow][94.00,grow][232.0,grow][130.00][grow]", "[][][20.00,grow][grow]"));
188         JLabel lblManufacturer = new JLabel("Manufacturer:");
189         contentPanel.add(lblManufacturer, "cell 2 0,alignx left,aligny center");
190
191         mfgTextField = new JTextField();
192         contentPanel.add(mfgTextField, "cell 3 0,growx");
193         mfgTextField.setColumns(10);
194
195         JLabel lenUnitLabel = new JLabel("Length Unit:");
196         contentPanel.add(lenUnitLabel, "cell 4 0,alignx left,aligny center");
197
198         lenUnitCombo = new JComboBox();
199         lenUnitCombo.setModel(new DefaultComboBoxModel(new String[]{"m", "cm", "mm", "in", "ft"}));
200         contentPanel.add(lenUnitCombo, "cell 5 0,growx");
201
202         JLabel typeLabel = new JLabel("Type:");
203         contentPanel.add(typeLabel, "cell 2 1,alignx left,aligny center");
204
205         componentOverlayPanel = new JPanel();
206         contentPanel.add(componentOverlayPanel, "cell 1 3 5 2,grow");
207         componentOverlayPanel.setLayout(new CardLayout(0, 0));
208
209         typeCombo = new DeselectableComboBox();
210         typeCombo.addItemListener(this);
211         typeCombo.setModel(new DefaultComboBoxModel());
212         setItems(typeCombo, toEdit);
213         contentPanel.add(typeCombo, "cell 3 1,growx");
214
215         JLabel massUnitLabel = new JLabel("Mass Unit:");
216         contentPanel.add(massUnitLabel, "cell 4 1,alignx left,aligny center");
217
218         massUnitCombo = new JComboBox();
219         massUnitCombo.setModel(new DefaultComboBoxModel(new String[]{"kg", "g", "oz", "lb"}));
220         contentPanel.add(massUnitCombo, "cell 5 1,growx");
221
222         JLabel bhMaterialLabel = new JLabel("Material:");
223         contentPanel.add(bhMaterialLabel, "cell 2 2, alignx left");
224
225         materialChooser = new JComboBox(new MaterialModel(this, Material.Type.BULK));
226         contentPanel.add(materialChooser, "cell 3 2,growx");
227
228         {
229             JPanel ncPanel = new JPanel();
230             componentOverlayPanel.add(ncPanel, "NOSECONE");
231             ncPanel.setLayout(new MigLayout("", "[61px][159.00,grow][35.00][109.00,grow][189.00,grow][grow]", "[16px][][][][][]"));
232             JLabel ncPartNoLabel = new JLabel("Part No:");
233             ncPanel.add(ncPartNoLabel, "cell 0 0,alignx left,aligny center");
234
235             ncPartNoTextField = new JTextField();
236             ncPanel.add(ncPartNoTextField, "cell 1 0,growx");
237             ncPartNoTextField.setColumns(10);
238
239             JLabel ncDescLabel = new JLabel("Description:");
240             ncPanel.add(ncDescLabel, "cell 3 0,alignx left,aligny center");
241
242             ncDescTextField = new JTextField();
243             ncPanel.add(ncDescTextField, "cell 4 0,growx");
244             ncDescTextField.setColumns(10);
245
246             ncFilledCB = new JCheckBox("Filled");
247             ncPanel.add(ncFilledCB, "cell 1 1");
248
249             JLabel ncMaterialLabel = new JLabel("Material:");
250             ncPanel.add(ncMaterialLabel, "cell 0 1,alignx left");
251
252             JLabel ncMassLabel = new JLabel("Mass:");
253             ncPanel.add(ncMassLabel, "cell 3 1,alignx left");
254
255             ncMassTextField = new JTextField();
256             ncMassTextField.setInputVerifier(NON_NEGATIVE_DECIMAL);
257             ncPanel.add(ncMassTextField, "cell 4 1,growx");
258             ncMassTextField.setColumns(10);
259
260             JLabel ncShapeLabel = new JLabel("Shape:");
261             ncPanel.add(ncShapeLabel, "cell 0 2,alignx left");
262
263             ncShapeCB = new JComboBox();
264             ncShapeCB.setModel(new DefaultComboBoxModel(new String[]{Transition.Shape.OGIVE.getName(),
265                     Transition.Shape.CONICAL.getName(), Transition.Shape.PARABOLIC.getName(),
266                     Transition.Shape.ELLIPSOID.getName(), Transition.Shape.HAACK.getName()}));
267             ncPanel.add(ncShapeCB, "cell 1 2,growx");
268
269             JLabel ncLengthLabel = new JLabel("Length:");
270             ncPanel.add(ncLengthLabel, "cell 3 2,alignx left");
271
272             ncLengthTextField = new JTextField();
273             ncLengthTextField.setInputVerifier(NON_NEGATIVE_DECIMAL);
274             ncPanel.add(ncLengthTextField, "cell 4 2,growx");
275             ncLengthTextField.setColumns(10);
276
277             JLabel ncAftDiaLabel = new JLabel("Aft Dia.:");
278             ncPanel.add(ncAftDiaLabel, "cell 0 3,alignx left, aligny top");
279
280             ncAftDiaTextField = new JTextField();
281             ncAftDiaTextField.setInputVerifier(NON_NEGATIVE_DECIMAL);
282             ncPanel.add(ncAftDiaTextField, "cell 1 3,growx, aligny top");
283             ncAftDiaTextField.setColumns(10);
284
285             JLabel ncAftShoulderLenLabel = new JLabel("Aft Shoulder Len:");
286             ncPanel.add(ncAftShoulderLenLabel, "cell 0 4,alignx left, aligny top");
287
288             ncAftShoulderLenTextField = new JTextField();
289             ncAftShoulderLenTextField.setInputVerifier(NON_NEGATIVE_DECIMAL);
290             ncPanel.add(ncAftShoulderLenTextField, "cell 1 4,growx,aligny top");
291             ncAftShoulderLenTextField.setColumns(10);
292
293             JLabel ncAftShoulderDiaLabel = new JLabel("Aft Shoulder Dia.:");
294             ncPanel.add(ncAftShoulderDiaLabel, "cell 0 5,alignx left, aligny top");
295
296             ncAftShoulderDiaTextField = new JTextField();
297             ncAftShoulderDiaTextField.setInputVerifier(NON_NEGATIVE_DECIMAL);
298             ncPanel.add(ncAftShoulderDiaTextField, "cell 1 5,growx, aligny top");
299             ncAftShoulderDiaTextField.setColumns(10);
300
301             JPanel panel = new JPanel();
302             panel.setMinimumSize(new Dimension(200, 200));
303             ncPanel.add(panel, "cell 4 3, span 1 3");
304             panel.setLayout(null);
305             ncImageBtn = new JButton("No Image");
306             ncImageBtn.setMaximumSize(new Dimension(75, 75));
307             ncImageBtn.setMinimumSize(new Dimension(75, 75));
308             panel.add(ncImageBtn);
309             ncImageBtn.setBounds(new Rectangle(6, 6, 132, 145));
310
311             ncImageBtn.addActionListener(new ActionListener() {
312                 @Override
313                 public void actionPerformed(final ActionEvent e) {
314                     int returnVal = imageChooser.showOpenDialog(PresetEditorDialog.this);
315
316                     if (returnVal == JFileChooser.APPROVE_OPTION) {
317                         File file = imageChooser.getSelectedFile();
318                         ncImage = scaleImage(new ImageIcon(file.getAbsolutePath()).getImage(), 155);
319                         ncImageBtn.setIcon(ncImage);
320                     }
321                 }
322             });
323
324         }
325         {
326             JPanel trPanel = new JPanel();
327             componentOverlayPanel.add(trPanel, "TRANSITION");
328             trPanel.setLayout(new MigLayout("", "[][grow][][grow]", "[][][28.00][31.00][][]"));
329
330             JLabel trPartNoLabel = new JLabel("Part No:");
331             trPanel.add(trPartNoLabel, "cell 0 0,alignx left");
332
333             trPartNoTextField = new JTextField();
334             trPanel.add(trPartNoTextField, "cell 1 0,growx");
335             trPartNoTextField.setColumns(10);
336
337             JLabel trDescLabel = new JLabel("Description:");
338             trPanel.add(trDescLabel, "cell 2 0,alignx left");
339
340             trDescTextField = new JTextField();
341             trPanel.add(trDescTextField, "cell 3 0,growx");
342             trDescTextField.setColumns(10);
343
344             trFilledCB = new JCheckBox("Filled");
345             trPanel.add(trFilledCB, "cell 1 1");
346
347             JLabel trMassLabel = new JLabel("Mass:");
348             trPanel.add(trMassLabel, "cell 2 1,alignx left");
349
350             trMassTextField = new JTextField();
351             trMassTextField.setInputVerifier(NON_NEGATIVE_DECIMAL);
352             trPanel.add(trMassTextField, "cell 3 1,growx");
353             trMassTextField.setColumns(10);
354
355             JLabel trShapeLabel = new JLabel("Shape:");
356             trPanel.add(trShapeLabel, "cell 0 2,alignx left");
357
358             trShapeCB = new JComboBox();
359             trShapeCB.setModel(new DefaultComboBoxModel(new String[]{Transition.Shape.OGIVE.getName(),
360                     Transition.Shape.CONICAL.getName(), Transition.Shape.PARABOLIC.getName(),
361                     Transition.Shape.ELLIPSOID.getName(), Transition.Shape.HAACK.getName()}));
362             trPanel.add(trShapeCB, "cell 1 2,growx");
363
364             JLabel trLengthLabel = new JLabel("Length:");
365             trPanel.add(trLengthLabel, "cell 2 2,alignx left");
366
367             trLengthTextField = new JTextField();
368             trLengthTextField.setInputVerifier(NON_NEGATIVE_DECIMAL);
369             trPanel.add(trLengthTextField, "cell 3 2,growx");
370             trLengthTextField.setColumns(10);
371
372             JLabel trAftDiaLabel = new JLabel("Aft Dia.:");
373             trPanel.add(trAftDiaLabel, "cell 0 3,alignx left");
374
375             trAftDiaTextField = new JTextField();
376             trAftDiaTextField.setInputVerifier(NON_NEGATIVE_DECIMAL);
377             trPanel.add(trAftDiaTextField, "cell 1 3,growx");
378             trAftDiaTextField.setColumns(10);
379
380             JLabel trForeDiaLabel = new JLabel("Fore Dia.:");
381             trPanel.add(trForeDiaLabel, "cell 2 3,alignx left");
382
383             trForeDiaTextField = new JTextField();
384             trForeDiaTextField.setInputVerifier(NON_NEGATIVE_DECIMAL);
385             trPanel.add(trForeDiaTextField, "cell 3 3,growx");
386             trForeDiaTextField.setColumns(10);
387
388             JLabel trAftShouldDiaLabel = new JLabel("Aft Shoulder Dia.:");
389             trPanel.add(trAftShouldDiaLabel, "cell 0 4,alignx left");
390
391             trAftShoulderDiaTextField = new JTextField();
392             trAftShoulderDiaTextField.setInputVerifier(NON_NEGATIVE_DECIMAL);
393             trPanel.add(trAftShoulderDiaTextField, "cell 1 4,growx");
394             trAftShoulderDiaTextField.setColumns(10);
395
396             JLabel trForeShouldDiaLabel = new JLabel("Fore Shoulder Dia.:");
397             trPanel.add(trForeShouldDiaLabel, "cell 2 4,alignx left");
398
399             trForeShoulderDiaTextField = new JTextField();
400             trForeShoulderDiaTextField.setInputVerifier(NON_NEGATIVE_DECIMAL);
401             trPanel.add(trForeShoulderDiaTextField, "cell 3 4,growx");
402             trForeShoulderDiaTextField.setColumns(10);
403
404             JLabel trAftShoulderLenLabel = new JLabel("Aft Shoulder Len.:");
405             trPanel.add(trAftShoulderLenLabel, "cell 0 5,alignx left");
406
407             trAftShoulderLenTextField = new JTextField();
408             trAftShoulderLenTextField.setInputVerifier(NON_NEGATIVE_DECIMAL);
409             trPanel.add(trAftShoulderLenTextField, "cell 1 5,growx");
410             trAftShoulderLenTextField.setColumns(10);
411
412             JLabel lblForeShoulderLen = new JLabel("Fore Shoulder Len.:");
413             trPanel.add(lblForeShoulderLen, "cell 2 5,alignx left");
414
415             trForeShoulderLenTextField = new JTextField();
416             trForeShoulderLenTextField.setInputVerifier(NON_NEGATIVE_DECIMAL);
417             trPanel.add(trForeShoulderLenTextField, "cell 3 5,growx");
418             trForeShoulderLenTextField.setColumns(10);
419
420             JPanel panel = new JPanel();
421             panel.setMinimumSize(new Dimension(200, 200));
422             trPanel.add(panel, "cell 3 6");
423             panel.setLayout(null);
424             trImageBtn = new JButton("No Image");
425             trImageBtn.setMaximumSize(new Dimension(75, 75));
426             trImageBtn.setMinimumSize(new Dimension(75, 75));
427             panel.add(trImageBtn);
428             trImageBtn.setBounds(new Rectangle(6, 6, 132, 145));
429
430             trImageBtn.addActionListener(new ActionListener() {
431                 @Override
432                 public void actionPerformed(final ActionEvent e) {
433                     int returnVal = imageChooser.showOpenDialog(PresetEditorDialog.this);
434
435                     if (returnVal == JFileChooser.APPROVE_OPTION) {
436                         File file = imageChooser.getSelectedFile();
437                         trImage = scaleImage(new ImageIcon(file.getAbsolutePath()).getImage(), 155);
438                         trImageBtn.setIcon(trImage);
439                     }
440                 }
441             });
442
443         }
444         {
445             JPanel btPanel = new JPanel();
446             componentOverlayPanel.add(btPanel, "BODYTUBE");
447             btPanel.setLayout(new MigLayout("", "[][grow][][grow]", "[][][][]"));
448             JLabel btPartNoLabel = new JLabel("Part No:");
449             btPanel.add(btPartNoLabel, "cell 0 0,alignx left");
450
451             btPartNoTextField = new JTextField();
452             btPanel.add(btPartNoTextField, "cell 1 0,growx");
453             btPartNoTextField.setColumns(10);
454
455             JLabel btDescLabel = new JLabel("Description:");
456             btPanel.add(btDescLabel, "cell 2 0,alignx left");
457
458             btDescTextField = new JTextField();
459             btPanel.add(btDescTextField, "cell 3 0,growx");
460             btDescTextField.setColumns(10);
461
462             JLabel btMassLabel = new JLabel("Mass:");
463             btPanel.add(btMassLabel, "cell 2 1,alignx left");
464
465             btMassTextField = new JTextField();
466             btMassTextField.setInputVerifier(NON_NEGATIVE_DECIMAL);
467             btPanel.add(btMassTextField, "cell 3 1,growx");
468             btMassTextField.setColumns(10);
469
470             JLabel btInnerDiaLabel = new JLabel("Inner Dia.:");
471             btPanel.add(btInnerDiaLabel, "cell 0 2,alignx left");
472
473             btInnerDiaTextField = new JTextField();
474             btInnerDiaTextField.setInputVerifier(NON_NEGATIVE_DECIMAL);
475             btPanel.add(btInnerDiaTextField, "cell 1 2,growx");
476             btInnerDiaTextField.setColumns(10);
477
478             JLabel btOuterDiaLabel = new JLabel("Outer Dia.:");
479             btPanel.add(btOuterDiaLabel, "cell 2 2,alignx left");
480
481             btOuterDiaTextField = new JTextField();
482             btOuterDiaTextField.setInputVerifier(NON_NEGATIVE_DECIMAL);
483             btPanel.add(btOuterDiaTextField, "cell 3 2,growx");
484             btOuterDiaTextField.setColumns(10);
485
486             JLabel btLengthLabel = new JLabel("Length:");
487             btPanel.add(btLengthLabel, "cell 0 1,alignx left");
488
489             btLengthTextField = new JTextField();
490             btLengthTextField.setInputVerifier(NON_NEGATIVE_DECIMAL);
491             btPanel.add(btLengthTextField, "cell 1 1,growx");
492             btLengthTextField.setColumns(10);
493
494             JPanel panel = new JPanel();
495             panel.setMinimumSize(new Dimension(200, 200));
496             btPanel.add(panel, "cell 3 3");
497             panel.setLayout(null);
498             btImageBtn = new JButton("No Image");
499             btImageBtn.setMaximumSize(new Dimension(75, 75));
500             btImageBtn.setMinimumSize(new Dimension(75, 75));
501             panel.add(btImageBtn);
502             btImageBtn.setBounds(new Rectangle(6, 6, 132, 145));
503
504             btImageBtn.addActionListener(new ActionListener() {
505                 @Override
506                 public void actionPerformed(final ActionEvent e) {
507                     int returnVal = imageChooser.showOpenDialog(PresetEditorDialog.this);
508
509                     if (returnVal == JFileChooser.APPROVE_OPTION) {
510                         File file = imageChooser.getSelectedFile();
511                         btImage = scaleImage(new ImageIcon(file.getAbsolutePath()).getImage(), 155);
512                         btImageBtn.setIcon(btImage);
513                     }
514                 }
515             });
516
517         }
518         {
519             JPanel tcPanel = new JPanel();
520             componentOverlayPanel.add(tcPanel, "TUBECOUPLER");
521             tcPanel.setLayout(new MigLayout("", "[][grow][][grow]", "[][][][]"));
522             JLabel tcPartNoLabel = new JLabel("Part No:");
523             tcPanel.add(tcPartNoLabel, "cell 0 0,alignx left");
524
525             tcPartNoTextField = new JTextField();
526             tcPanel.add(tcPartNoTextField, "cell 1 0,growx");
527             tcPartNoTextField.setColumns(10);
528
529             JLabel tcDescLabel = new JLabel("Description:");
530             tcPanel.add(tcDescLabel, "cell 2 0,alignx left");
531
532             tcDescTextField = new JTextField();
533             tcPanel.add(tcDescTextField, "cell 3 0,growx");
534             tcDescTextField.setColumns(10);
535
536             JLabel tcMassLabel = new JLabel("Mass:");
537             tcPanel.add(tcMassLabel, "cell 2 1,alignx left");
538
539             tcMassTextField = new JTextField();
540             tcMassTextField.setInputVerifier(NON_NEGATIVE_DECIMAL);
541             tcPanel.add(tcMassTextField, "cell 3 1,growx");
542             tcMassTextField.setColumns(10);
543
544             JLabel tcInnerDiaLabel = new JLabel("Inner Dia.:");
545             tcPanel.add(tcInnerDiaLabel, "cell 0 2,alignx left, aligny top");
546
547             tcInnerDiaTextField = new JTextField();
548             tcInnerDiaTextField.setInputVerifier(NON_NEGATIVE_DECIMAL);
549             tcPanel.add(tcInnerDiaTextField, "cell 1 2,growx, aligny top");
550             tcInnerDiaTextField.setColumns(10);
551
552             JLabel tcOuterDiaLabel = new JLabel("Outer Dia.:");
553             tcPanel.add(tcOuterDiaLabel, "cell 2 2,alignx left, aligny top");
554
555             tcOuterDiaTextField = new JTextField();
556             tcOuterDiaTextField.setInputVerifier(NON_NEGATIVE_DECIMAL);
557             tcPanel.add(tcOuterDiaTextField, "cell 3 2,growx, aligny top");
558             tcOuterDiaTextField.setColumns(10);
559
560             JLabel tcLengthLabel = new JLabel("Length:");
561             tcPanel.add(tcLengthLabel, "cell 0 1,alignx left");
562
563             tcLengthTextField = new JTextField();
564             tcLengthTextField.setInputVerifier(NON_NEGATIVE_DECIMAL);
565             tcPanel.add(tcLengthTextField, "cell 1 1,growx");
566             tcLengthTextField.setColumns(10);
567
568             JPanel panel = new JPanel();
569             panel.setMinimumSize(new Dimension(200, 200));
570             tcPanel.add(panel, "cell 3 3");
571             panel.setLayout(null);
572             tcImageBtn = new JButton("No Image");
573             tcImageBtn.setMaximumSize(new Dimension(75, 75));
574             tcImageBtn.setMinimumSize(new Dimension(75, 75));
575             panel.add(tcImageBtn);
576             tcImageBtn.setBounds(new Rectangle(6, 6, 132, 145));
577
578             tcImageBtn.addActionListener(new ActionListener() {
579                 @Override
580                 public void actionPerformed(final ActionEvent e) {
581                     int returnVal = imageChooser.showOpenDialog(PresetEditorDialog.this);
582
583                     if (returnVal == JFileChooser.APPROVE_OPTION) {
584                         File file = imageChooser.getSelectedFile();
585                         tcImage = scaleImage(new ImageIcon(file.getAbsolutePath()).getImage(), 155);
586                         tcImageBtn.setIcon(tcImage);
587                     }
588                 }
589             });
590
591
592         }
593         {
594             JPanel bhPanel = new JPanel();
595             componentOverlayPanel.add(bhPanel, "BULKHEAD");
596             bhPanel.setLayout(new MigLayout("", "[][157.00,grow 79][65.00][grow]", "[][][][]"));
597
598             JLabel bhPartNoLabel = new JLabel("Part No:");
599             bhPanel.add(bhPartNoLabel, "cell 0 0,alignx left");
600
601             bhPartNoTextField = new JTextField();
602             bhPanel.add(bhPartNoTextField, "cell 1 0,growx");
603             bhPartNoTextField.setColumns(10);
604
605             JLabel bhDescLabel = new JLabel("Description:");
606             bhPanel.add(bhDescLabel, "cell 2 0,alignx left");
607
608             bhDescTextField = new JTextField();
609             bhPanel.add(bhDescTextField, "cell 3 0,growx");
610             bhDescTextField.setColumns(10);
611
612             JLabel bhOuterDiaLabel = new JLabel("Outer Dia.:");
613             bhPanel.add(bhOuterDiaLabel, "cell 0 2,alignx left, aligny top");
614
615             bhOuterDiaTextField = new JTextField();
616             bhPanel.add(bhOuterDiaTextField, "cell 1 2,growx, aligny top");
617             bhOuterDiaTextField.setColumns(10);
618
619             JLabel bhMassLabel = new JLabel("Mass:");
620             bhPanel.add(bhMassLabel, "cell 2 1,alignx left");
621
622             bhMassTextField = new JTextField();
623             bhPanel.add(bhMassTextField, "cell 3 1,growx");
624             bhMassTextField.setColumns(10);
625
626             JLabel bhLengthLabel = new JLabel("Thickness:");
627             bhPanel.add(bhLengthLabel, "cell 0 1,alignx left");
628
629             bhLengthTextField = new JTextField();
630             bhPanel.add(bhLengthTextField, "cell 1 1,growx");
631             bhLengthTextField.setColumns(10);
632
633             JPanel panel = new JPanel();
634             panel.setMinimumSize(new Dimension(200, 200));
635             bhPanel.add(panel, "cell 3 2");
636             panel.setLayout(null);
637             bhImageBtn = new JButton("No Image");
638             bhImageBtn.setMaximumSize(new Dimension(75, 75));
639             bhImageBtn.setMinimumSize(new Dimension(75, 75));
640             panel.add(bhImageBtn);
641             bhImageBtn.setBounds(new Rectangle(6, 6, 132, 145));
642
643             bhImageBtn.addActionListener(new ActionListener() {
644                 @Override
645                 public void actionPerformed(final ActionEvent e) {
646                     int returnVal = imageChooser.showOpenDialog(PresetEditorDialog.this);
647
648                     if (returnVal == JFileChooser.APPROVE_OPTION) {
649                         File file = imageChooser.getSelectedFile();
650                         bhImage = scaleImage(new ImageIcon(file.getAbsolutePath()).getImage(), 155);
651                         bhImageBtn.setIcon(bhImage);
652                     }
653                 }
654             });
655
656         }
657         {
658             JPanel crPanel = new JPanel();
659             componentOverlayPanel.add(crPanel, "CENTERINGRING");
660             crPanel.setLayout(new MigLayout("", "[][grow][][grow]", "[][][][]"));
661
662             JLabel crPartNoLabel = new JLabel("Part No:");
663             crPanel.add(crPartNoLabel, "cell 0 0,alignx left");
664
665             crPartNoTextField = new JTextField();
666             crPanel.add(crPartNoTextField, "cell 1 0, growx");
667             crPartNoTextField.setColumns(10);
668
669             JLabel crDescLabel = new JLabel("Description:");
670             crPanel.add(crDescLabel, "cell 2 0,alignx left");
671
672             crDescTextField = new JTextField();
673             crPanel.add(crDescTextField, "cell 3 0, growx");
674             crDescTextField.setColumns(10);
675
676             JLabel crMassLabel = new JLabel("Mass:");
677             crPanel.add(crMassLabel, "cell 2 1,alignx left");
678
679             crMassTextField = new JTextField();
680             crMassTextField.setInputVerifier(NON_NEGATIVE_DECIMAL);
681             crPanel.add(crMassTextField, "cell 3 1, growx");
682             crMassTextField.setColumns(10);
683
684             JLabel crOuterDiaLabel = new JLabel("Outer Dia.:");
685             crPanel.add(crOuterDiaLabel, "cell 0 2,alignx left");
686
687             crOuterDiaTextField = new JTextField();
688             crOuterDiaTextField.setInputVerifier(NON_NEGATIVE_DECIMAL);
689             crPanel.add(crOuterDiaTextField, "cell 1 2, growx");
690             crOuterDiaTextField.setColumns(10);
691
692             JLabel crInnerDiaLabel = new JLabel("Inner Dia.:");
693             crPanel.add(crInnerDiaLabel, "cell 2 2,alignx left");
694
695             crInnerDiaTextField = new JTextField();
696             crInnerDiaTextField.setInputVerifier(NON_NEGATIVE_DECIMAL);
697             crPanel.add(crInnerDiaTextField, "cell 3 2, growx");
698             crInnerDiaTextField.setColumns(10);
699
700             JLabel crThicknessLabel = new JLabel("Thickness:");
701             crPanel.add(crThicknessLabel, "cell 0 1,alignx left");
702
703             crThicknessTextField = new JTextField();
704             crThicknessTextField.setInputVerifier(NON_NEGATIVE_DECIMAL);
705             crPanel.add(crThicknessTextField, "cell 1 1, growx");
706             crThicknessTextField.setColumns(10);
707
708             JPanel panel = new JPanel();
709             panel.setMinimumSize(new Dimension(200, 200));
710             crPanel.add(panel, "cell 3 3");
711             panel.setLayout(null);
712             crImageBtn = new JButton("No Image");
713             crImageBtn.setMaximumSize(new Dimension(75, 75));
714             crImageBtn.setMinimumSize(new Dimension(75, 75));
715             panel.add(crImageBtn);
716             crImageBtn.setBounds(new Rectangle(6, 6, 132, 145));
717
718             crImageBtn.addActionListener(new ActionListener() {
719                 @Override
720                 public void actionPerformed(final ActionEvent e) {
721                     int returnVal = imageChooser.showOpenDialog(PresetEditorDialog.this);
722
723                     if (returnVal == JFileChooser.APPROVE_OPTION) {
724                         File file = imageChooser.getSelectedFile();
725                         crImage = scaleImage(new ImageIcon(file.getAbsolutePath()).getImage(), 155);
726                         crImageBtn.setIcon(crImage);
727                     }
728                 }
729             });
730
731         }
732         {
733             JPanel ebPanel = new JPanel();
734             componentOverlayPanel.add(ebPanel, "ENGINEBLOCK");
735             ebPanel.setLayout(new MigLayout("", "[][grow][][grow]", "[][][][]"));
736             JLabel ebPartNoLabel = new JLabel("Part No:");
737             ebPanel.add(ebPartNoLabel, "cell 0 0,alignx left");
738
739             ebPartNoTextField = new JTextField();
740             ebPanel.add(ebPartNoTextField, "cell 1 0,growx");
741             ebPartNoTextField.setColumns(10);
742
743             JLabel ebDescLabel = new JLabel("Description:");
744             ebPanel.add(ebDescLabel, "cell 2 0,alignx left");
745
746             ebDescTextField = new JTextField();
747             ebPanel.add(ebDescTextField, "cell 3 0,growx");
748             ebDescTextField.setColumns(10);
749
750             JLabel ebMassLabel = new JLabel("Mass:");
751             ebPanel.add(ebMassLabel, "cell 2 1,alignx left");
752
753             ebMassTextField = new JTextField();
754             ebMassTextField.setInputVerifier(NON_NEGATIVE_DECIMAL);
755             ebPanel.add(ebMassTextField, "cell 3 1,growx");
756             ebMassTextField.setColumns(10);
757
758             JLabel ebOuterDiaLabel = new JLabel("Outer Dia.:");
759             ebPanel.add(ebOuterDiaLabel, "cell 0 2,alignx left");
760
761             ebOuterDiaTextField = new JTextField();
762             ebOuterDiaTextField.setInputVerifier(NON_NEGATIVE_DECIMAL);
763             ebPanel.add(ebOuterDiaTextField, "cell 1 2,growx");
764             ebOuterDiaTextField.setColumns(10);
765
766             JLabel ebInnerDiaLabel = new JLabel("Inner Dia.:");
767             ebPanel.add(ebInnerDiaLabel, "cell 2 2,alignx left");
768
769             ebInnerDiaTextField = new JTextField();
770             ebInnerDiaTextField.setInputVerifier(NON_NEGATIVE_DECIMAL);
771             ebPanel.add(ebInnerDiaTextField, "cell 3 2,growx");
772             ebInnerDiaTextField.setColumns(10);
773
774             JLabel ebThicknessLabel = new JLabel("Thickness:");
775             ebPanel.add(ebThicknessLabel, "cell 0 1,alignx left");
776
777             ebThicknessTextField = new JTextField();
778             ebThicknessTextField.setInputVerifier(NON_NEGATIVE_DECIMAL);
779             ebPanel.add(ebThicknessTextField, "cell 1 1,growx");
780             ebThicknessTextField.setColumns(10);
781
782             JPanel panel = new JPanel();
783             panel.setMinimumSize(new Dimension(200, 200));
784             ebPanel.add(panel, "cell 3 3");
785             panel.setLayout(null);
786             ebImageBtn = new JButton("No Image");
787             ebImageBtn.setMaximumSize(new Dimension(75, 75));
788             ebImageBtn.setMinimumSize(new Dimension(75, 75));
789             panel.add(ebImageBtn);
790             ebImageBtn.setBounds(new Rectangle(6, 6, 132, 145));
791
792             ebImageBtn.addActionListener(new ActionListener() {
793                 @Override
794                 public void actionPerformed(final ActionEvent e) {
795                     int returnVal = imageChooser.showOpenDialog(PresetEditorDialog.this);
796
797                     if (returnVal == JFileChooser.APPROVE_OPTION) {
798                         File file = imageChooser.getSelectedFile();
799                         ebImage = scaleImage(new ImageIcon(file.getAbsolutePath()).getImage(), 155);
800                         ebImageBtn.setIcon(ebImage);
801                     }
802                 }
803             });
804         }
805
806         JPanel buttonPane = new JPanel();
807         getContentPane().add(buttonPane, BorderLayout.SOUTH);
808         buttonPane.setLayout(new MigLayout("", "[130px][176.00px][131.00px]", "[29px]"));
809         JButton btnSaveAndNew = new JButton("Save and New");
810         btnSaveAndNew.addMouseListener(new MouseAdapter() {
811             @Override
812             public void mouseClicked(MouseEvent arg0) {
813                 saveResult();
814             }
815         });
816         buttonPane.add(btnSaveAndNew, "cell 0 0,alignx left,aligny top");
817
818         JButton okButton = new JButton("Save and Close");
819         okButton.addActionListener(new ActionListener() {
820             public void actionPerformed(ActionEvent event) {
821                 saveResult();
822                 dispose();
823             }
824         });
825         okButton.setActionCommand("OK");
826         buttonPane.add(okButton, "cell 1 0,alignx left,aligny top");
827         getRootPane().setDefaultButton(okButton);
828
829         JButton cancelButton = new JButton("Close");
830         cancelButton.addActionListener(new ActionListener() {
831             public void actionPerformed(ActionEvent event) {
832                 dispose();
833             }
834         });
835         cancelButton.setActionCommand("Close");
836         buttonPane.add(cancelButton, "cell 6 0,alignx right,aligny top");
837
838         if (toEdit != null) {
839             fillEditor(toEdit);
840         }
841     }
842
843     /**
844      * When an existing preset is edited, we want to disable the other types of presets.  If the user wants a different
845      * type of component, then they should delete this one and add a new one.
846      *
847      * @param cb
848      * @param preset
849      */
850     private void setItems(DeselectableComboBox cb, ComponentPreset preset) {
851         cb.addItem(trans.get(NOSE_CONE_KEY), preset == null ? false : !preset.get(ComponentPreset.TYPE).equals(ComponentPreset.Type.NOSE_CONE));
852         cb.addItem(trans.get(BODY_TUBE_KEY), preset == null ? false : !preset.get(ComponentPreset.TYPE).equals(ComponentPreset.Type.BODY_TUBE));
853         cb.addItem(trans.get(TUBE_COUPLER_KEY), preset == null ? false : !preset.get(ComponentPreset.TYPE).equals(ComponentPreset.Type.TUBE_COUPLER));
854         cb.addItem(trans.get(TRANSITION_KEY), preset == null ? false : !preset.get(ComponentPreset.TYPE).equals(ComponentPreset.Type.TRANSITION));
855         cb.addItem(trans.get(CR_KEY), preset == null ? false : !preset.get(ComponentPreset.TYPE).equals(ComponentPreset.Type.CENTERING_RING));
856         cb.addItem(trans.get(BULKHEAD_KEY), preset == null ? false : !preset.get(ComponentPreset.TYPE).equals(ComponentPreset.Type.BULK_HEAD));
857         cb.addItem(trans.get(EB_KEY), preset == null ? false : !preset.get(ComponentPreset.TYPE).equals(ComponentPreset.Type.ENGINE_BLOCK));
858     }
859
860     /**
861      * Create an image chooser.  Currently png and jpg are supported.
862      *
863      * @return
864      */
865     private JFileChooser createImageChooser() {
866         final JFileChooser chooser = new JFileChooser();
867         ImagePreviewPanel preview = new ImagePreviewPanel();
868         chooser.setAccessory(preview);
869         chooser.addPropertyChangeListener(preview);
870         chooser.setAcceptAllFileFilterUsed(false);
871         chooser.addChoosableFileFilter(new FileFilter() {
872             @Override
873             public boolean accept(final File f) {
874                 return f.getName().endsWith(".png") || f.getName().endsWith(".jpg");
875             }
876
877             @Override
878             public String getDescription() {
879                 return "Image Files";
880             }
881         });
882         return chooser;
883     }
884
885     private void fillEditor(ComponentPreset preset) {
886         ComponentPreset.Type t = preset.getType();
887
888         mfgTextField.setText(preset.get(ComponentPreset.MANUFACTURER).getDisplayName());
889         materialChooser.getModel().setSelectedItem(preset.get(ComponentPreset.MATERIAL));
890         switch (t) {
891             case BODY_TUBE:
892                 typeCombo.setSelectedItem(trans.get(BODY_TUBE_KEY));
893                 btDescTextField.setText(preset.get(ComponentPreset.DESCRIPTION));
894
895                 if (preset.has(ComponentPreset.INNER_DIAMETER)) {
896                     btInnerDiaTextField.setText(preset.get(ComponentPreset.INNER_DIAMETER).toString());
897                 }
898                 if (preset.has(ComponentPreset.LENGTH)) {
899                     btLengthTextField.setText(preset.get(ComponentPreset.LENGTH).toString());
900                 }
901                 if (preset.has(ComponentPreset.MASS)) {
902                     btMassTextField.setText(preset.get(ComponentPreset.MASS).toString());
903                 }
904                 if (preset.has(ComponentPreset.OUTER_DIAMETER)) {
905                     btOuterDiaTextField.setText(preset.get(ComponentPreset.OUTER_DIAMETER).toString());
906                 }
907                 if (preset.has(ComponentPreset.IMAGE)) {
908                     btImage = new ImageIcon(byteArrayToImage(preset.get(ComponentPreset.IMAGE)));
909                     btImageBtn.setIcon(btImage);
910                 }
911                 btPartNoTextField.setText(preset.get(ComponentPreset.PARTNO));
912                 break;
913             case BULK_HEAD:
914                 typeCombo.setSelectedItem(trans.get(BULKHEAD_KEY));
915                 bhDescTextField.setText(preset.get(ComponentPreset.DESCRIPTION));
916                 if (preset.has(ComponentPreset.LENGTH)) {
917                     bhLengthTextField.setText(preset.get(ComponentPreset.LENGTH).toString());
918                 }
919                 if (preset.has(ComponentPreset.MASS)) {
920                     bhMassTextField.setText(preset.get(ComponentPreset.MASS).toString());
921                 }
922                 if (preset.has(ComponentPreset.OUTER_DIAMETER)) {
923                     bhOuterDiaTextField.setText(preset.get(ComponentPreset.OUTER_DIAMETER).toString());
924                 }
925                 if (preset.has(ComponentPreset.IMAGE)) {
926                     bhImage = new ImageIcon(byteArrayToImage(preset.get(ComponentPreset.IMAGE)));
927                     bhImageBtn.setIcon(bhImage);
928                 }
929                 bhPartNoTextField.setText(preset.get(ComponentPreset.PARTNO));
930                 break;
931             case CENTERING_RING:
932                 typeCombo.setSelectedItem(trans.get(CR_KEY));
933                 crDescTextField.setText(preset.get(ComponentPreset.DESCRIPTION));
934                 if (preset.has(ComponentPreset.INNER_DIAMETER)) {
935                     crInnerDiaTextField.setText(preset.get(ComponentPreset.INNER_DIAMETER).toString());
936                 }
937                 if (preset.has(ComponentPreset.LENGTH)) {
938                     crThicknessTextField.setText(preset.get(ComponentPreset.LENGTH).toString());
939                 }
940                 if (preset.has(ComponentPreset.MASS)) {
941                     crMassTextField.setText(preset.get(ComponentPreset.MASS).toString());
942                 }
943                 if (preset.has(ComponentPreset.OUTER_DIAMETER)) {
944                     crOuterDiaTextField.setText(preset.get(ComponentPreset.OUTER_DIAMETER).toString());
945                 }
946                 if (preset.has(ComponentPreset.IMAGE)) {
947                     crImage = new ImageIcon(byteArrayToImage(preset.get(ComponentPreset.IMAGE)));
948                     crImageBtn.setIcon(crImage);
949                 }
950                 crPartNoTextField.setText(preset.get(ComponentPreset.PARTNO));
951                 break;
952             case ENGINE_BLOCK:
953                 typeCombo.setSelectedItem(trans.get(EB_KEY));
954                 ebDescTextField.setText(preset.get(ComponentPreset.DESCRIPTION));
955                 if (preset.has(ComponentPreset.INNER_DIAMETER)) {
956                     ebInnerDiaTextField.setText(preset.get(ComponentPreset.INNER_DIAMETER).toString());
957                 }
958                 if (preset.has(ComponentPreset.LENGTH)) {
959                     ebThicknessTextField.setText(preset.get(ComponentPreset.LENGTH).toString());
960                 }
961                 if (preset.has(ComponentPreset.MASS)) {
962                     ebMassTextField.setText(preset.get(ComponentPreset.MASS).toString());
963                 }
964                 if (preset.has(ComponentPreset.OUTER_DIAMETER)) {
965                     ebOuterDiaTextField.setText(preset.get(ComponentPreset.OUTER_DIAMETER).toString());
966                 }
967                 if (preset.has(ComponentPreset.IMAGE)) {
968                     ebImage = new ImageIcon(byteArrayToImage(preset.get(ComponentPreset.IMAGE)));
969                     ebImageBtn.setIcon(ebImage);
970                 }
971                 ebPartNoTextField.setText(preset.get(ComponentPreset.PARTNO));
972                 break;
973             case NOSE_CONE:
974                 typeCombo.setSelectedItem(trans.get(NOSE_CONE_KEY));
975                 ncDescTextField.setText(preset.get(ComponentPreset.DESCRIPTION));
976                 if (preset.has(ComponentPreset.AFT_OUTER_DIAMETER)) {
977                     ncAftDiaTextField.setText(preset.get(ComponentPreset.AFT_OUTER_DIAMETER).toString());
978                 }
979                 if (preset.has(ComponentPreset.AFT_SHOULDER_DIAMETER)) {
980                     ncAftShoulderDiaTextField.setText(preset.get(ComponentPreset.AFT_SHOULDER_DIAMETER).toString());
981                 }
982                 if (preset.has(ComponentPreset.AFT_SHOULDER_LENGTH)) {
983                     ncAftShoulderLenTextField.setText(preset.get(ComponentPreset.AFT_SHOULDER_LENGTH).toString());
984                 }
985                 if (preset.has(ComponentPreset.MASS)) {
986                     ncMassTextField.setText(preset.get(ComponentPreset.MASS).toString());
987                 }
988                 if (preset.has(ComponentPreset.SHAPE)) {
989                     ncShapeCB.setSelectedItem(preset.get(ComponentPreset.SHAPE).toString());
990                 }
991                 if (preset.has(ComponentPreset.FILLED)) {
992                     ncFilledCB.setSelected((preset.get(ComponentPreset.FILLED)));
993                 }
994                 if (preset.has(ComponentPreset.LENGTH)) {
995                     ncLengthTextField.setText(preset.get(ComponentPreset.LENGTH).toString());
996                 }
997                 if (preset.has(ComponentPreset.IMAGE)) {
998                     ncImage = new ImageIcon(byteArrayToImage(preset.get(ComponentPreset.IMAGE)));
999                     ncImageBtn.setIcon(ncImage);
1000                 }
1001                 ncPartNoTextField.setText(preset.get(ComponentPreset.PARTNO));
1002                 break;
1003             case TRANSITION:
1004                 typeCombo.setSelectedItem(trans.get(TRANSITION_KEY));
1005                 trDescTextField.setText(preset.get(ComponentPreset.DESCRIPTION));
1006                 if (preset.has(ComponentPreset.AFT_OUTER_DIAMETER)) {
1007                     trAftDiaTextField.setText(preset.get(ComponentPreset.AFT_OUTER_DIAMETER).toString());
1008                 }
1009                 if (preset.has(ComponentPreset.AFT_SHOULDER_DIAMETER)) {
1010                     trAftShoulderDiaTextField.setText(preset.get(ComponentPreset.AFT_SHOULDER_DIAMETER).toString());
1011                 }
1012                 if (preset.has(ComponentPreset.AFT_SHOULDER_LENGTH)) {
1013                     trAftShoulderLenTextField.setText(preset.get(ComponentPreset.AFT_SHOULDER_LENGTH).toString());
1014                 }
1015                 if (preset.has(ComponentPreset.FORE_OUTER_DIAMETER)) {
1016                     trForeDiaTextField.setText(preset.get(ComponentPreset.FORE_OUTER_DIAMETER).toString());
1017                 }
1018                 if (preset.has(ComponentPreset.FORE_SHOULDER_DIAMETER)) {
1019                     trForeShoulderDiaTextField.setText(preset.get(ComponentPreset.FORE_SHOULDER_DIAMETER).toString());
1020                 }
1021                 if (preset.has(ComponentPreset.FORE_SHOULDER_LENGTH)) {
1022                     trForeShoulderLenTextField.setText(preset.get(ComponentPreset.FORE_SHOULDER_LENGTH).toString());
1023                 }
1024                 if (preset.has(ComponentPreset.MASS)) {
1025                     trMassTextField.setText(preset.get(ComponentPreset.MASS).toString());
1026                 }
1027                 if (preset.has(ComponentPreset.SHAPE)) {
1028                     trShapeCB.setSelectedItem(preset.get(ComponentPreset.SHAPE).toString());
1029                 }
1030                 if (preset.has(ComponentPreset.FILLED)) {
1031                     trFilledCB.setSelected((preset.get(ComponentPreset.FILLED)));
1032                 }
1033                 if (preset.has(ComponentPreset.LENGTH)) {
1034                     trLengthTextField.setText(preset.get(ComponentPreset.LENGTH).toString());
1035                 }
1036                 if (preset.has(ComponentPreset.IMAGE)) {
1037                     trImage = new ImageIcon(byteArrayToImage(preset.get(ComponentPreset.IMAGE)));
1038                     trImageBtn.setIcon(trImage);
1039                 }
1040                 trPartNoTextField.setText(preset.get(ComponentPreset.PARTNO));
1041                 break;
1042             case TUBE_COUPLER:
1043                 typeCombo.setSelectedItem(trans.get(TUBE_COUPLER_KEY));
1044                 tcDescTextField.setText(preset.get(ComponentPreset.DESCRIPTION));
1045                 if (preset.has(ComponentPreset.INNER_DIAMETER)) {
1046                     tcInnerDiaTextField.setText(preset.get(ComponentPreset.INNER_DIAMETER).toString());
1047                 }
1048                 if (preset.has(ComponentPreset.LENGTH)) {
1049                     tcLengthTextField.setText(preset.get(ComponentPreset.LENGTH).toString());
1050                 }
1051                 if (preset.has(ComponentPreset.MASS)) {
1052                     tcMassTextField.setText(preset.get(ComponentPreset.MASS).toString());
1053                 }
1054                 if (preset.has(ComponentPreset.OUTER_DIAMETER)) {
1055                     tcOuterDiaTextField.setText(preset.get(ComponentPreset.OUTER_DIAMETER).toString());
1056                 }
1057                 tcPartNoTextField.setText(preset.get(ComponentPreset.PARTNO));
1058                 if (preset.has(ComponentPreset.IMAGE)) {
1059                     tcImage = new ImageIcon(byteArrayToImage(preset.get(ComponentPreset.IMAGE)));
1060                     tcImageBtn.setIcon(tcImage);
1061                 }
1062                 break;
1063             default:
1064         }
1065     }
1066
1067     private void saveResult() {
1068         String type = (String) typeCombo.getSelectedItem();
1069
1070         ComponentPreset result = null;
1071
1072         if (type.equals(trans.get(NOSE_CONE_KEY))) {
1073             result = extractNoseCone();
1074             if (result != null) {
1075                 clearNoseCone();
1076             }
1077         }
1078         else if (type.equals(trans.get(TRANSITION_KEY))) {
1079             result = extractTransition();
1080             if (result != null) {
1081                 clearTransition();
1082             }
1083         }
1084         else if (type.equals(trans.get(BODY_TUBE_KEY))) {
1085             result = extractBodyTube();
1086             if (result != null) {
1087                 clearBodyTube();
1088             }
1089         }
1090         else if (type.equals(trans.get(TUBE_COUPLER_KEY))) {
1091             result = extractTubeCoupler();
1092             if (result != null) {
1093                 clearTubeCoupler();
1094             }
1095         }
1096         else if (type.equals(trans.get(EB_KEY))) {
1097             result = extractEngineBlock();
1098             if (result != null) {
1099                 clearEngineBlock();
1100             }
1101         }
1102         else if (type.equals(trans.get(CR_KEY))) {
1103             result = extractCenteringRing();
1104             if (result != null) {
1105                 clearCenteringRing();
1106             }
1107         }
1108         else if (type.equals(trans.get(BULKHEAD_KEY))) {
1109             result = extractBulkhead();
1110             if (result != null) {
1111                 clearBulkhead();
1112             }
1113         }
1114         resultListener.notifyResult(result);
1115     }
1116
1117     private ComponentPreset extractNoseCone() {
1118         TypedPropertyMap props = new TypedPropertyMap();
1119         try {
1120             PrintUnit lpu = lengthMap.get(lenUnitCombo.getSelectedItem());
1121
1122             props.put(ComponentPreset.TYPE, ComponentPreset.Type.NOSE_CONE);
1123             if (!ncAftDiaTextField.getText().equals("")) {
1124                 props.put(ComponentPreset.AFT_OUTER_DIAMETER, lpu.toMeters(Double.parseDouble(ncAftDiaTextField.getText())));
1125             }
1126             if (!ncAftShoulderDiaTextField.getText().equals("")) {
1127                 props.put(ComponentPreset.AFT_SHOULDER_DIAMETER, lpu.toMeters(Double.parseDouble(ncAftShoulderDiaTextField.getText())));
1128             }
1129             if (!ncAftShoulderLenTextField.getText().equals("")) {
1130                 props.put(ComponentPreset.AFT_SHOULDER_LENGTH, lpu.toMeters(Double.parseDouble(ncAftShoulderLenTextField.getText())));
1131             }
1132             props.put(ComponentPreset.DESCRIPTION, ncDescTextField.getText());
1133             props.put(ComponentPreset.PARTNO, ncPartNoTextField.getText());
1134             props.put(ComponentPreset.MANUFACTURER, Manufacturer.getManufacturer(mfgTextField.getText()));
1135             if (!ncLengthTextField.getText().equals("")) {
1136                 props.put(ComponentPreset.LENGTH, lpu.toMeters(Double.parseDouble(ncLengthTextField.getText())));
1137             }
1138             props.put(ComponentPreset.SHAPE, Transition.Shape.toShape((String) ncShapeCB.getSelectedItem()));
1139             final Material material = (Material) materialChooser.getSelectedItem();
1140             if (material != null) {
1141                 props.put(ComponentPreset.MATERIAL, material);
1142             }
1143             else {
1144                 JOptionPane.showMessageDialog(null, "A material must be selected.", "Error", JOptionPane.ERROR_MESSAGE);
1145                 return null;
1146             }
1147             if (!ncMassTextField.getText().equals("")) {
1148                 props.put(ComponentPreset.MASS, lpu.toMeters(Double.parseDouble(ncMassTextField.getText())));
1149             }
1150             props.put(ComponentPreset.FILLED, ncFilledCB.isSelected());
1151             if (ncImage != null) {
1152                 props.put(ComponentPreset.IMAGE, imageToByteArray(ncImage.getImage()));
1153             }
1154
1155             return ComponentPresetFactory.create(props);
1156         }
1157         catch (NumberFormatException nfe) {
1158             JOptionPane.showMessageDialog(null, "Could not convert nose cone attribute.", "Error", JOptionPane.ERROR_MESSAGE);
1159         }
1160         catch (InvalidComponentPresetException e) {
1161             JOptionPane.showMessageDialog(null, "Mandatory nose cone attribute not set.", "Error", JOptionPane.ERROR_MESSAGE);
1162         }
1163         return null;
1164     }
1165
1166     private void clearNoseCone() {
1167         ncAftDiaTextField.setText("");
1168         ncAftShoulderDiaTextField.setText("");
1169         ncAftShoulderLenTextField.setText("");
1170         ncDescTextField.setText("");
1171         ncPartNoTextField.setText("");
1172         ncLengthTextField.setText("");
1173         ncMassTextField.setText("");
1174         ncFilledCB.setSelected(false);
1175         ncImage = null;
1176         ncImageBtn.setIcon(null);
1177     }
1178
1179     private ComponentPreset extractTransition() {
1180         TypedPropertyMap props = new TypedPropertyMap();
1181         try {
1182             PrintUnit lpu = lengthMap.get(lenUnitCombo.getSelectedItem());
1183             props.put(ComponentPreset.TYPE, ComponentPreset.Type.TRANSITION);
1184             if (!trAftDiaTextField.getText().equals("")) {
1185                 props.put(ComponentPreset.AFT_OUTER_DIAMETER, lpu.toMeters(Double.parseDouble(trAftDiaTextField.getText())));
1186             }
1187             if (!trAftShoulderDiaTextField.getText().equals("")) {
1188                 props.put(ComponentPreset.AFT_SHOULDER_DIAMETER, lpu.toMeters(Double.parseDouble(trAftShoulderDiaTextField.getText())));
1189             }
1190             if (!trAftShoulderLenTextField.getText().equals("")) {
1191                 props.put(ComponentPreset.AFT_SHOULDER_LENGTH, lpu.toMeters(Double.parseDouble(trAftShoulderLenTextField.getText())));
1192             }
1193             if (!trForeDiaTextField.getText().equals("")) {
1194                 props.put(ComponentPreset.FORE_OUTER_DIAMETER, lpu.toMeters(Double.parseDouble(trForeDiaTextField.getText())));
1195             }
1196             if (!trForeShoulderDiaTextField.getText().equals("")) {
1197                 props.put(ComponentPreset.FORE_SHOULDER_DIAMETER, lpu.toMeters(Double.parseDouble(trForeShoulderDiaTextField.getText())));
1198             }
1199             if (!trForeShoulderLenTextField.getText().equals("")) {
1200                 props.put(ComponentPreset.FORE_SHOULDER_LENGTH, lpu.toMeters(Double.parseDouble(trForeShoulderLenTextField.getText())));
1201             }
1202             props.put(ComponentPreset.DESCRIPTION, trDescTextField.getText());
1203             props.put(ComponentPreset.PARTNO, trPartNoTextField.getText());
1204             props.put(ComponentPreset.MANUFACTURER, Manufacturer.getManufacturer(mfgTextField.getText()));
1205
1206             if (!trLengthTextField.getText().equals("")) {
1207                 props.put(ComponentPreset.LENGTH, lpu.toMeters(Double.parseDouble(trLengthTextField.getText())));
1208             }
1209             props.put(ComponentPreset.SHAPE, Transition.Shape.toShape((String) trShapeCB.getSelectedItem()));
1210             final Material material = (Material) materialChooser.getSelectedItem();
1211             if (material != null) {
1212                 props.put(ComponentPreset.MATERIAL, material);
1213             }
1214             else {
1215                 JOptionPane.showMessageDialog(null, "A material must be selected.", "Error", JOptionPane.ERROR_MESSAGE);
1216                 return null;
1217             }
1218             if (!trMassTextField.getText().equals("")) {
1219                 props.put(ComponentPreset.MASS, lpu.toMeters(Double.parseDouble(trMassTextField.getText())));
1220             }
1221             props.put(ComponentPreset.FILLED, trFilledCB.isSelected());
1222             if (trImage != null) {
1223                 props.put(ComponentPreset.IMAGE, imageToByteArray(trImage.getImage()));
1224             }
1225
1226             return ComponentPresetFactory.create(props);
1227         }
1228         catch (NumberFormatException nfe) {
1229             JOptionPane.showMessageDialog(null, "Could not convert transition attribute.", "Error", JOptionPane.ERROR_MESSAGE);
1230         }
1231         catch (InvalidComponentPresetException e) {
1232             JOptionPane.showMessageDialog(null, "Mandatory transition attribute not set.", "Error", JOptionPane.ERROR_MESSAGE);
1233         }
1234         return null;
1235     }
1236
1237     private void clearTransition() {
1238         trAftDiaTextField.setText("");
1239         trAftShoulderDiaTextField.setText("");
1240         trAftShoulderLenTextField.setText("");
1241         trForeDiaTextField.setText("");
1242         trForeShoulderDiaTextField.setText("");
1243         trForeShoulderLenTextField.setText("");
1244         trDescTextField.setText("");
1245         trPartNoTextField.setText("");
1246         trLengthTextField.setText("");
1247         trMassTextField.setText("");
1248         trFilledCB.setSelected(false);
1249         trImage = null;
1250         trImageBtn.setIcon(null);
1251     }
1252
1253     private ComponentPreset extractBodyTube() {
1254         TypedPropertyMap props = new TypedPropertyMap();
1255         try {
1256             PrintUnit lpu = lengthMap.get(lenUnitCombo.getSelectedItem());
1257             props.put(ComponentPreset.TYPE, ComponentPreset.Type.BODY_TUBE);
1258             if (!btOuterDiaTextField.getText().equals("")) {
1259                 props.put(ComponentPreset.OUTER_DIAMETER, lpu.toMeters(Double.parseDouble(btOuterDiaTextField.getText())));
1260             }
1261             if (!btInnerDiaTextField.getText().equals("")) {
1262                 props.put(ComponentPreset.INNER_DIAMETER, lpu.toMeters(Double.parseDouble(btInnerDiaTextField.getText())));
1263             }
1264             props.put(ComponentPreset.DESCRIPTION, btDescTextField.getText());
1265             props.put(ComponentPreset.PARTNO, btPartNoTextField.getText());
1266             props.put(ComponentPreset.MANUFACTURER, Manufacturer.getManufacturer(mfgTextField.getText()));
1267             if (!btLengthTextField.getText().equals("")) {
1268                 props.put(ComponentPreset.LENGTH, lpu.toMeters(Double.parseDouble(btLengthTextField.getText())));
1269             }
1270             final Material material = (Material) materialChooser.getSelectedItem();
1271             if (material != null) {
1272                 props.put(ComponentPreset.MATERIAL, material);
1273             }
1274             else {
1275                 JOptionPane.showMessageDialog(null, "A material must be selected.", "Error", JOptionPane.ERROR_MESSAGE);
1276                 return null;
1277             }
1278             if (!btMassTextField.getText().equals("")) {
1279                 props.put(ComponentPreset.MASS, lpu.toMeters(Double.parseDouble(btMassTextField.getText())));
1280             }
1281             if (btImage != null) {
1282                 props.put(ComponentPreset.IMAGE, imageToByteArray(btImage.getImage()));
1283             }
1284             return ComponentPresetFactory.create(props);
1285         }
1286         catch (NumberFormatException nfe) {
1287             nfe.printStackTrace();
1288             JOptionPane.showMessageDialog(null, "Could not convert body tube attribute.", "Error", JOptionPane.ERROR_MESSAGE);
1289         }
1290         catch (InvalidComponentPresetException e) {
1291             JOptionPane.showMessageDialog(null, "Mandatory body tube attribute not set.", "Error", JOptionPane.ERROR_MESSAGE);
1292         }
1293         return null;
1294     }
1295
1296     private void clearBodyTube() {
1297         btOuterDiaTextField.setText("");
1298         btInnerDiaTextField.setText("");
1299         btDescTextField.setText("");
1300         btPartNoTextField.setText("");
1301         btLengthTextField.setText("");
1302         btMassTextField.setText("");
1303         btImage = null;
1304         btImageBtn.setIcon(null);
1305     }
1306
1307     public ComponentPreset extractTubeCoupler() {
1308         TypedPropertyMap props = new TypedPropertyMap();
1309         try {
1310             PrintUnit lpu = lengthMap.get(lenUnitCombo.getSelectedItem());
1311             props.put(ComponentPreset.TYPE, ComponentPreset.Type.TUBE_COUPLER);
1312             if (!tcOuterDiaTextField.getText().equals("")) {
1313                 props.put(ComponentPreset.OUTER_DIAMETER, lpu.toMeters(Double.parseDouble(tcOuterDiaTextField.getText())));
1314             }
1315             if (!tcInnerDiaTextField.getText().equals("")) {
1316                 props.put(ComponentPreset.INNER_DIAMETER, lpu.toMeters(Double.parseDouble(tcInnerDiaTextField.getText())));
1317             }
1318             props.put(ComponentPreset.DESCRIPTION, tcDescTextField.getText());
1319             props.put(ComponentPreset.PARTNO, tcPartNoTextField.getText());
1320             props.put(ComponentPreset.MANUFACTURER, Manufacturer.getManufacturer(mfgTextField.getText()));
1321             if (!tcLengthTextField.getText().equals("")) {
1322                 props.put(ComponentPreset.LENGTH, lpu.toMeters(Double.parseDouble(tcLengthTextField.getText())));
1323             }
1324             final Material material = (Material) materialChooser.getSelectedItem();
1325             if (material != null) {
1326                 props.put(ComponentPreset.MATERIAL, material);
1327             }
1328             else {
1329                 JOptionPane.showMessageDialog(null, "A material must be selected.", "Error", JOptionPane.ERROR_MESSAGE);
1330                 return null;
1331             }
1332             if (!tcMassTextField.getText().equals("")) {
1333                 props.put(ComponentPreset.MASS, lpu.toMeters(Double.parseDouble(tcMassTextField.getText())));
1334             }
1335             if (tcImage != null) {
1336                 props.put(ComponentPreset.IMAGE, imageToByteArray(tcImage.getImage()));
1337             }
1338
1339             return ComponentPresetFactory.create(props);
1340         }
1341         catch (NumberFormatException nfe) {
1342             JOptionPane.showMessageDialog(null, "Could not convert tube coupler attribute.", "Error", JOptionPane.ERROR_MESSAGE);
1343         }
1344         catch (InvalidComponentPresetException e) {
1345             JOptionPane.showMessageDialog(null, "Mandatory tube coupler attribute not set.", "Error", JOptionPane.ERROR_MESSAGE);
1346         }
1347         return null;
1348     }
1349
1350     private void clearTubeCoupler() {
1351         tcOuterDiaTextField.setText("");
1352         tcInnerDiaTextField.setText("");
1353         tcDescTextField.setText("");
1354         tcPartNoTextField.setText("");
1355         tcLengthTextField.setText("");
1356         tcMassTextField.setText("");
1357         tcImage = null;
1358         tcImageBtn.setIcon(null);
1359     }
1360
1361     private ComponentPreset extractBulkhead() {
1362         TypedPropertyMap props = new TypedPropertyMap();
1363         try {
1364             PrintUnit lpu = lengthMap.get(lenUnitCombo.getSelectedItem());
1365             props.put(ComponentPreset.TYPE, ComponentPreset.Type.BULK_HEAD);
1366             if (!bhOuterDiaTextField.getText().equals("")) {
1367                 props.put(ComponentPreset.OUTER_DIAMETER, lpu.toMeters(Double.parseDouble(bhOuterDiaTextField.getText())));
1368             }
1369             props.put(ComponentPreset.DESCRIPTION, bhDescTextField.getText());
1370             props.put(ComponentPreset.PARTNO, bhPartNoTextField.getText());
1371             props.put(ComponentPreset.MANUFACTURER, Manufacturer.getManufacturer(mfgTextField.getText()));
1372             if (!bhLengthTextField.getText().equals("")) {
1373                 props.put(ComponentPreset.LENGTH, lpu.toMeters(Double.parseDouble(bhLengthTextField.getText())));
1374             }
1375             final Material material = (Material) materialChooser.getSelectedItem();
1376             if (material != null) {
1377                 props.put(ComponentPreset.MATERIAL, material);
1378             }
1379             else {
1380                 JOptionPane.showMessageDialog(null, "A material must be selected.", "Error", JOptionPane.ERROR_MESSAGE);
1381                 return null;
1382             }
1383             if (!bhMassTextField.getText().equals("")) {
1384                 props.put(ComponentPreset.MASS, lpu.toMeters(Double.parseDouble(bhMassTextField.getText())));
1385             }
1386             if (bhImage != null) {
1387                 props.put(ComponentPreset.IMAGE, imageToByteArray(bhImage.getImage()));
1388             }
1389             return ComponentPresetFactory.create(props);
1390         }
1391         catch (NumberFormatException nfe) {
1392             JOptionPane.showMessageDialog(null, "Could not convert bulkhead attribute.", "Error", JOptionPane.ERROR_MESSAGE);
1393         }
1394         catch (InvalidComponentPresetException e) {
1395             JOptionPane.showMessageDialog(null, "Mandatory bulkhead attribute not set.", "Error", JOptionPane.ERROR_MESSAGE);
1396         }
1397         return null;
1398     }
1399
1400     private void clearBulkhead() {
1401         bhOuterDiaTextField.setText("");
1402         bhDescTextField.setText("");
1403         bhPartNoTextField.setText("");
1404         bhLengthTextField.setText("");
1405         bhMassTextField.setText("");
1406         bhImage = null;
1407         bhImageBtn.setIcon(null);
1408     }
1409
1410     private ComponentPreset extractCenteringRing() {
1411         TypedPropertyMap props = new TypedPropertyMap();
1412         try {
1413             PrintUnit lpu = lengthMap.get(lenUnitCombo.getSelectedItem());
1414             props.put(ComponentPreset.TYPE, ComponentPreset.Type.CENTERING_RING);
1415             if (!crOuterDiaTextField.getText().equals("")) {
1416                 props.put(ComponentPreset.OUTER_DIAMETER, lpu.toMeters(Double.parseDouble(crOuterDiaTextField.getText())));
1417             }
1418             if (!crInnerDiaTextField.getText().equals("")) {
1419                 props.put(ComponentPreset.INNER_DIAMETER, lpu.toMeters(Double.parseDouble(crInnerDiaTextField.getText())));
1420             }
1421             props.put(ComponentPreset.DESCRIPTION, crDescTextField.getText());
1422             props.put(ComponentPreset.PARTNO, crPartNoTextField.getText());
1423             props.put(ComponentPreset.MANUFACTURER, Manufacturer.getManufacturer(mfgTextField.getText()));
1424             if (!crThicknessTextField.getText().equals("")) {
1425                 props.put(ComponentPreset.LENGTH, lpu.toMeters(Double.parseDouble(crThicknessTextField.getText())));
1426             }
1427             final Material material = (Material) materialChooser.getSelectedItem();
1428             if (material != null) {
1429                 props.put(ComponentPreset.MATERIAL, material);
1430             }
1431             else {
1432                 JOptionPane.showMessageDialog(null, "A material must be selected.", "Error", JOptionPane.ERROR_MESSAGE);
1433                 return null;
1434             }
1435             if (!crMassTextField.getText().equals("")) {
1436                 props.put(ComponentPreset.MASS, lpu.toMeters(Double.parseDouble(crMassTextField.getText())));
1437             }
1438             if (crImage != null) {
1439                 props.put(ComponentPreset.IMAGE, imageToByteArray(crImage.getImage()));
1440             }
1441             return ComponentPresetFactory.create(props);
1442         }
1443         catch (NumberFormatException nfe) {
1444             JOptionPane.showMessageDialog(null, "Could not convert centering ring attribute.", "Error", JOptionPane.ERROR_MESSAGE);
1445         }
1446         catch (InvalidComponentPresetException e) {
1447             JOptionPane.showMessageDialog(null, "Mandatory centering ring attribute not set.", "Error", JOptionPane.ERROR_MESSAGE);
1448         }
1449         return null;
1450     }
1451
1452     private void clearCenteringRing() {
1453         crOuterDiaTextField.setText("");
1454         crInnerDiaTextField.setText("");
1455         crDescTextField.setText("");
1456         crPartNoTextField.setText("");
1457         crThicknessTextField.setText("");
1458         crMassTextField.setText("");
1459         crImage = null;
1460         crImageBtn.setIcon(null);
1461     }
1462
1463     public ComponentPreset extractEngineBlock() {
1464         TypedPropertyMap props = new TypedPropertyMap();
1465         try {
1466             PrintUnit lpu = lengthMap.get(lenUnitCombo.getSelectedItem());
1467             props.put(ComponentPreset.TYPE, ComponentPreset.Type.ENGINE_BLOCK);
1468             if (!ebOuterDiaTextField.getText().equals("")) {
1469                 props.put(ComponentPreset.OUTER_DIAMETER, lpu.toMeters(Double.parseDouble(ebOuterDiaTextField.getText())));
1470             }
1471             if (!ebInnerDiaTextField.getText().equals("")) {
1472                 props.put(ComponentPreset.INNER_DIAMETER, lpu.toMeters(Double.parseDouble(ebInnerDiaTextField.getText())));
1473             }
1474             props.put(ComponentPreset.DESCRIPTION, ebDescTextField.getText());
1475             props.put(ComponentPreset.PARTNO, ebPartNoTextField.getText());
1476             props.put(ComponentPreset.MANUFACTURER, Manufacturer.getManufacturer(mfgTextField.getText()));
1477             if (!ebThicknessTextField.getText().equals("")) {
1478                 props.put(ComponentPreset.LENGTH, lpu.toMeters(Double.parseDouble(ebThicknessTextField.getText())));
1479             }
1480             final Material material = (Material) materialChooser.getSelectedItem();
1481             if (material != null) {
1482                 props.put(ComponentPreset.MATERIAL, material);
1483             }
1484             else {
1485                 JOptionPane.showMessageDialog(null, "A material must be selected.", "Error", JOptionPane.ERROR_MESSAGE);
1486                 return null;
1487             }
1488             if (!ebMassTextField.getText().equals("")) {
1489                 props.put(ComponentPreset.MASS, lpu.toMeters(Double.parseDouble(ebMassTextField.getText())));
1490             }
1491             if (ebImage != null) {
1492                 props.put(ComponentPreset.IMAGE, imageToByteArray(ebImage.getImage()));
1493             }
1494             return ComponentPresetFactory.create(props);
1495         }
1496         catch (NumberFormatException nfe) {
1497             JOptionPane.showMessageDialog(null, "Could not convert engine block attribute.", "Error", JOptionPane.ERROR_MESSAGE);
1498         }
1499         catch (InvalidComponentPresetException e) {
1500             JOptionPane.showMessageDialog(null, "Mandatory engine block attribute not set.", "Error", JOptionPane.ERROR_MESSAGE);
1501         }
1502         return null;
1503     }
1504
1505     private void clearEngineBlock() {
1506         ebOuterDiaTextField.setText("");
1507         ebInnerDiaTextField.setText("");
1508         ebDescTextField.setText("");
1509         ebPartNoTextField.setText("");
1510         ebThicknessTextField.setText("");
1511         ebMassTextField.setText("");
1512         ebImage = null;
1513         ebImageBtn.setIcon(null);
1514     }
1515
1516     public void itemStateChanged(ItemEvent evt) {
1517         CardLayout cl = (CardLayout) (componentOverlayPanel.getLayout());
1518         cl.show(componentOverlayPanel, componentMap.get((String) evt.getItem()));
1519
1520     }
1521
1522     /**
1523      * Convert an image to a byte array in png format.
1524      *
1525      * @param originalImage
1526      *
1527      * @return
1528      */
1529     private byte[] imageToByteArray(Image originalImage) {
1530         byte[] imageInByte = null;
1531         try {
1532             BufferedImage bi = imageToBufferedImage(originalImage);
1533             ByteArrayOutputStream baos = new ByteArrayOutputStream();
1534             ImageIO.write(bi, "png", baos);
1535             baos.flush();
1536             imageInByte = baos.toByteArray();
1537             baos.close();
1538         }
1539         catch (IOException e) {
1540             log.error("Could not read image.");
1541         }
1542         return imageInByte;
1543     }
1544
1545     private BufferedImage imageToBufferedImage(final Image originalImage) {
1546         BufferedImage bi = new BufferedImage(
1547                 originalImage.getWidth(null),
1548                 originalImage.getHeight(null),
1549                 BufferedImage.TYPE_INT_RGB);
1550
1551         Graphics2D g2 = bi.createGraphics();
1552         g2.drawImage(originalImage, 0, 0, null);
1553         return bi;
1554     }
1555
1556     private BufferedImage byteArrayToImage(byte[] src) {
1557         // convert byte array back to BufferedImage
1558         InputStream in = new ByteArrayInputStream(src);
1559         try {
1560             return ImageIO.read(in);
1561         }
1562         catch (IOException e) {
1563             log.error("Could not convert image.");
1564         }
1565         return null;
1566     }
1567
1568     private ImageIcon scaleImage(Image image, int targetDimension) {
1569         int width = image.getWidth(this);
1570         int height = image.getHeight(this);
1571         double ratio = 1.0;
1572
1573         /*
1574          * Determine how to scale the image. Since the accessory can expand
1575          * vertically make sure we don't go larger than 150 when scaling
1576          * vertically.
1577          */
1578         if (width >= height) {
1579             ratio = (double) (targetDimension - 5) / width;
1580             width = targetDimension - 5;
1581             height = (int) (height * ratio);
1582         }
1583         else {
1584             if (getHeight() > 150) {
1585                 ratio = (double) (targetDimension - 5) / height;
1586                 height = targetDimension - 5;
1587                 width = (int) (width * ratio);
1588             }
1589             else {
1590                 ratio = (double) getHeight() / height;
1591                 height = getHeight();
1592                 width = (int) (width * ratio);
1593             }
1594         }
1595
1596         return new ImageIcon(image.getScaledInstance(width, height, Image.SCALE_DEFAULT));
1597     }
1598
1599     static class PresetInputVerifier extends InputVerifier {
1600
1601         /**
1602          * Matches user input against a regular expression.
1603          */
1604         private Matcher matcher;
1605
1606         PresetInputVerifier(final Pattern thePattern) {
1607             matcher = thePattern.matcher("");
1608         }
1609
1610         /**
1611          * Return true only if the untrimmed user input matches the regular expression provided to the constructor.
1612          *
1613          * @param aComponent must be an instance of JTextComponent.
1614          */
1615         public boolean verify(JComponent aComponent) {
1616             JTextComponent textComponent = (JTextComponent) aComponent;
1617             String text = textComponent.getText();
1618             boolean munged = false;
1619             //Make sure there's a leading number
1620             if (text.startsWith(".")) {
1621                 text = "0" + text;
1622                 munged = true;
1623             }
1624             //Make sure there's a trailing number
1625             if (text.endsWith(".")) {
1626                 text = text + "0";
1627                 munged = true;
1628             }
1629             //Make sure if it's a decimal format
1630             else if (text.length() > 0 && !text.contains(".")) {
1631                 text = text + ".0";
1632                 munged = true;
1633             }
1634
1635             if (munged) {
1636                 textComponent.setInputVerifier(null);
1637                 textComponent.setText(text);
1638                 textComponent.setInputVerifier(this);
1639             }
1640             matcher.reset(text);
1641             return matcher.matches();
1642         }
1643
1644         /**
1645          * Always returns <tt>true</tt>, in this implementation, such that focus can always transfer to another
1646          * component whenever the validation fails.
1647          * <p/>
1648          * <P>If <tt>super.shouldYieldFocus</tt> returns <tt>false</tt>, then clear the text field.
1649          *
1650          * @param aComponent is a <tt>JTextComponent</tt>.
1651          */
1652         @Override
1653         public boolean shouldYieldFocus(JComponent aComponent) {
1654             if (!super.shouldYieldFocus(aComponent)) {
1655                 ((JTextComponent) aComponent).setText("");
1656             }
1657             return true;
1658         }
1659     }
1660 }