View Javadoc

1   /*
2    * $Id: TemplateEditorPanel.java,v 1.2 2004/01/12 18:44:18 mch Exp $
3    *
4    * See end for log
5    */
6   
7   package org.astrogrid.ace.client;
8   
9   import java.awt.*;
10  import java.io.*;
11  import javax.swing.*;
12  import org.astrogrid.ui.*;
13  import org.astrogrid.fits.*;
14  
15  import java.awt.event.ActionEvent;
16  import java.awt.event.ActionListener;
17  import java.awt.event.WindowAdapter;
18  import java.awt.event.WindowEvent;
19  import java.util.Arrays;
20  import java.util.Vector;
21  import javax.xml.parsers.DocumentBuilder;
22  import javax.xml.parsers.DocumentBuilderFactory;
23  import javax.xml.parsers.ParserConfigurationException;
24  import org.astrogrid.intensity.Passband;
25  import org.astrogrid.log.Log;
26  import org.astrogrid.tools.xml.XmlOutput;
27  import org.w3c.dom.Document;
28  import org.w3c.dom.Element;
29  import org.w3c.dom.Node;
30  import org.w3c.dom.NodeList;
31  import org.xml.sax.InputSource;
32  import org.xml.sax.SAXException;
33  
34  /***
35   * A subclass of JPanel that provides a complete tabbed-pane type
36   * dialog box with all the configuration parameters needed for the
37   * AVO Demo. (This class can be used anywhere a JPanel would
38   * normally go, allowing flexible placement/display.)
39   *
40   * Used by AVODemoDialog.java to display the tabs for a dialog box...
41   *
42   * @author Alan Maxwell
43   */
44  public class TemplateEditorPanel extends JTabbedPane
45  {
46  
47     // -- AJWM's MAIN -------------------------------------------------------------
48  
49     // This main is needed to test the returned XML string!
50  
51     public static void main(String[] args)
52     {
53        final JFrame frame = new JFrame("AVODemoDialog - Test");
54        frame.setSize(300, 300);
55        frame.setLocation(100, 100);
56  
57        frame.addWindowListener(
58           new WindowAdapter()
59           {
60              public void windowClosing(WindowEvent we) {
61                 System.exit(0);
62              }
63           }
64        );
65  
66        final TemplateEditorPanel templateEditorPanel = new TemplateEditorPanel();
67        final JTextPane output = new JTextPane();
68  
69  
70        JButton goButton = new JButton("Test AVODemo Dialog Panel >>");
71        goButton.addActionListener( new ActionListener() {
72                 public void actionPerformed(ActionEvent ae) {
73                    JDialog dialog = new JDialog(frame, "AVODemoDialogPanel - Test", true);
74  
75                    dialog.setSize(480,520);
76                    dialog.getContentPane().add(templateEditorPanel);
77                    dialog.setVisible(true);
78  
79                    output.setText(templateEditorPanel.toXmlString());
80                 }
81              });
82  
83        frame.getContentPane().setLayout(new BorderLayout());
84        frame.getContentPane().add(new JScrollPane(output), BorderLayout.CENTER);
85        frame.getContentPane().add(goButton, BorderLayout.SOUTH);
86        frame.setVisible(true);
87     };
88  
89     // ----------------------------------------------------------------------------
90  
91     // -- MCH's MAIN --------------------------------------------------------------
92     /*
93  
94      // This main does not allow easy testing of the XML strings...
95  
96      public static void main(String[] args)
97      {
98      JDialog dialog = new JDialog( (Frame) null, "AVODemoDialogPanel - Test", true);
99  
100     dialog.setSize(480,520);
101     dialog.getContentPane().add(
102     new TemplateEditorPanel()
103     );
104     dialog.setVisible(true);
105     };
106     */
107    // ----------------------------------------------------------------------------
108 
109    public static final int DEF_BUTTON_HEIGHT = 22;
110    public static final int DEF_BUTTON_WIDTH = 100;
111 
112    public static final int DEF_TEXTFIELD_HEIGHT = 20;
113    public static final int DEF_TEXTFIELD_WIDTH = 200;
114 
115    public static final Dimension DEF_BUTTON_DIMENSION =
116       new Dimension(DEF_BUTTON_WIDTH, DEF_BUTTON_HEIGHT);
117    public static final Dimension DEF_TEXTFIELD_DIMENSION =
118       new Dimension (DEF_TEXTFIELD_WIDTH, DEF_TEXTFIELD_HEIGHT);
119    public static final Dimension DEF_HALF_TEXTFIELD_DIMENSION =
120       new Dimension ((DEF_TEXTFIELD_WIDTH / 2) - 20, DEF_TEXTFIELD_HEIGHT);
121 
122    public static final int DEF_PADDING = 3;
123 
124    public static final Insets DEF_INSETS =
125       new Insets(DEF_PADDING, DEF_PADDING, DEF_PADDING, DEF_PADDING);
126 
127    public static final Insets DEF_VSPACE_INSETS =
128       new Insets(DEF_PADDING + DEF_TEXTFIELD_HEIGHT, DEF_PADDING, DEF_PADDING, DEF_PADDING);
129 
130    //set automatically public static final String DEF_SET_FILE_BUTTON_TEXT = "..";
131    //set automatically public static final String DEF_SET_FILE_BUTTON_TOOLTIP_TEXT =
132    //  "Choose a filename...";
133 
134    GridBagConstraints constraints = new GridBagConstraints();
135 
136    //=== IMAGE TAB ===========================================================
137    JTextField imageTextField = null;
138    JSetFileButton imageChooserButton = null;
139    JPasteButton imagePasteButton = null;
140    JButton imageHeaderButton = null;
141 
142    JCheckBox dualImageToggle = null;
143    JTextField dualImageTextField = null;
144    JSetFileButton dualImageChooserButton = null;
145    JPasteButton dualImagePasteButton = null;
146 
147    ButtonGroup radiobuttongroupDetectType = null;
148    JRadioButton radiobuttonDetectTypeCCD = null;
149    JRadioButton radiobuttonDetectTypePHOTO = null;
150 
151    //JComboBox passbandUcdPicker = null;
152    public PassbandSpecifierPanel passbandPanel = null;
153 
154    JButton imageHeaderViewerBtn = null;
155 
156    boolean imageFixed = false; //set if the image has been 'fixed' to a certain valude
157 
158    // == EXTRACTION TAB ======================================================
159 
160    JLabel labelFlagImage = null;
161    JTextField textFlagImage = null;
162 
163    JLabel labelDetMinArea = null;
164    JIntegerField integertextDetMinArea = null;
165 
166    JLabel labelDetThresh = null;
167    JDoubleField doubletextDetThresh1 = null;
168    JDoubleField doubletextDetThresh2 = null;
169 
170    JLabel labelAnalysisThresh = null;
171    JDoubleField doubletextAnalysisThresh1 = null;
172    JDoubleField doubletextAnalysisThresh2 = null;
173 
174    JCheckBox checkApplyFilter = null;
175    JComboBox textFilterName = null;
176 
177    JLabel labelDeblendThresh = null;
178    JIntegerField integertextDeblendThresh = null;
179 
180    JLabel labelDeblendMinCont = null;
181    JDoubleField doubletextDeblendMinCont = null;
182 
183    JCheckBox checkCleaning = null;
184    JDoubleField doubletextCleaning = null;
185 
186    JLabel labelMaskType = null;
187    JPanel panelMaskType = null;
188    ButtonGroup radiobuttongroupMaskType = null;
189    JRadioButton radiobuttonMaskTypeCORRECT = null;
190    JRadioButton radiobuttonMaskTypeBLANK = null;
191    JRadioButton radiobuttonMaskTypeNONE = null;
192 
193    // == PHOTOMETRY TAB ======================================================
194    JLabel labelPhotApertures = null;
195    JIntegerField inttextPhotApertures = null;
196 
197    JLabel labelPhotAutoParams = null;
198    JDoubleField doubletextPhotAutoParams1 = null;
199    JDoubleField doubletextPhotAutoParams2 = null;
200 
201    JLabel labelSatLevel = null;
202    JDoubleField doubletextSatLevel = null;
203 
204    JLabel labelMagZero = null;
205    JDoubleField doubletextMagZero = null;
206 
207    JLabel labelMagGamma = null;
208    JDoubleField doubletextMagGamma = null;
209 
210    JLabel labelGain = null;
211    JDoubleField doubletextGain = null;
212 
213    JLabel labelPixelScale = null;
214    JDoubleField doubletextPixelScale = null;
215 
216    // == STAR_GALAXY_SEPARATION TAB ======================================================
217    JLabel labelSeeingFWHM = null;
218    JDoubleField doubletextSeeingFWHM = null;
219 
220    JLabel labelStarNNWName = null;
221    JTextField textStarNNWName = null;
222 
223    // == BACKGROUND TAB ======================================================
224    JLabel labelBackSize = null;
225    JIntegerField integertextBackSize1 = null;
226    JIntegerField integertextBackSize2 = null;
227 
228    JLabel labelBackFilter = null;
229    JIntegerField integertextBackFilter1 = null;
230    JIntegerField integertextBackFilter2 = null;
231 
232    JLabel labelBackPhotoType = null;
233    JPanel panelBackPhotoType = null;
234    ButtonGroup radiobuttongroupBackPhotoType = null;
235    JRadioButton radiobuttonBackPhotoTypeGLOBAL = null;
236    JRadioButton radiobuttonBackPhotoTypeLOCAL = null;
237 
238    JLabel labelBackPhotoThick = null;
239    JIntegerField inttextBackPhotoThick = null;
240 
241    JCheckBox checkApplyPixFlag = null;
242    JTextField textApplyPixFlag = null;
243 
244    // == OUTPUT TAB =====================================================
245    JLabel  labelCheckImageType = null;
246    JComboBox comboCheckImageType = null;
247 
248    JMutableList listOutputColumns = null;
249    JMutableList listOutputColumnsSelected = null;
250 
251    JButton buttonOutputColumnsADD = null;
252    JButton buttonOutputColumnsREMOVE = null;
253 
254    Vector obligatoryOutputColumns = new Vector();
255 
256    static final String [] itemsOutputColumns =
257    {
258       "FLUX_ISO",
259          "MAG_ISO",
260          "MAGERR_ISO",
261          "FLUX_ISOCOR",
262          "FLUXERR_ISOCOR",
263          "MAG_ISOCOR",
264          "MAGERR_ISOCOR",
265          //         "FLUX_APER(-)",
266          //         "FLUXERR_APER(-)",
267          //         "MAG_APER(-)",
268          //         "MAGERR_APER(-)",
269          "MAG_AUTO",
270          "MAGERR_AUTO",
271          "FLUX_AUTO",
272          "FLUXERR_AUTO",
273          "FLUX_BEST",
274          "FLUXERR_BEST",
275          "MAG_BEST",
276          "MAGERR_BEST",
277          "KRON_RADIUS",
278          "BACKGROUND",
279          "THRESHOLD",
280          "MU_THRESHOLD",
281          "FLUX_MAX",
282          "MU_MAX",
283          "ISOAREA_IMAGE",
284          "ISOAREA_WORLD",
285          "XMIN_IMAGE",
286          "YMIN_IMAGE",
287          "XMAX_IMAGE",
288          "YMAX_IMAGE",
289          "X_WORLD",
290          "Y_WORLD",
291          "ALPHA_SKY",
292          "DELTA_SKY",
293          "ALPHA_J2000",
294          "DELTA_J2000",
295          "ALPHA_B1950",
296          "DELTA_B1950",
297          "X2_IMAGE",
298          "Y2_IMAGE",
299          "XY_IMAGE",
300          "X2_WORLD",
301          "Y2_WORLD",
302          "XY_WORLD",
303          "CXX_IMAGE",
304          "CYY_IMAGE",
305          "CXY_IMAGE",
306          "CXX_WORLD",
307          "CYY_WORLD",
308          "CXY_WORLD",
309          "A_IMAGE",
310          "B_IMAGE",
311          "A_WORLD",
312          "B_WORLD",
313          "THETA_IMAGE",
314          "THETA_WORLD",
315          "THETA_SKY",
316          "THETA_J2000",
317          "THETA_B1950",
318          "ELONGATION",
319          "ELLIPTICITY",
320          "ERRX2_IMAGE",
321          "ERRY2_IMAGE",
322          "ERRXY_IMAGE",
323          "ERRX2_WORLD",
324          "ERRY2_WORLD",
325          "ERRXY_WORLD",
326          "ERRCXX_IMAGE",
327          "ERRCYY_IMAGE",
328          "ERRCXY_IMAGE",
329          "ERRCXX_WORLD",
330          "ERRCYY_WORLD",
331          "ERRCXY_WORLD",
332          "ERRA_IMAGE",
333          "ERRB_IMAGE",
334          "ERRA_WORLD",
335          "ERRB_WORLD",
336          "ERRTHETA_IMAGE",
337          "ERRTHETA_WORLD",
338          "ERRTHETA_SKY",
339          "ERRTHETA_J2000",
340          "ERRTHETA_B1950",
341          "FWHM_IMAGE",
342          "FWHM_WORLD",
343          "ISO0",
344          "ISO1",
345          "ISO2",
346          "ISO3",
347          "ISO4",
348          "ISO5",
349          "ISO6",
350          "ISO7",
351          //         "IMAFLAGS_ISO(-)",
352          //         "NIMAFLAGS_ISO(-)",
353          "CLASS_STAR",
354          //         "VIGNET(-,-)"
355    };
356 
357 
358    // == ADVANCED TAB =====================================================
359    JLabel labelMemObjStack = null;
360    JIntegerField inttextMemObjStack = null;
361 
362    JLabel labelMemPixStack = null;
363    JIntegerField inttextMemPixStack = null;
364 
365    JLabel labelMemBufSize = null;
366    JIntegerField inttextMemBufSize = null;
367 
368    JLabel labelVerboseType = null;
369    JPanel panelVerboseType = null;
370    ButtonGroup radiobuttongroupVerboseType = null;
371    JRadioButton radiobuttonVerboseTypeNORMAL = null;
372    JRadioButton radiobuttonVerboseTypeQUIET = null;
373    JRadioButton radiobuttonVerboseTypeFULL = null;
374 
375 
376 
377    /***
378     * Constructs a JPanel with a set of tabbed pages depicting all of the options
379     * needed for the AVO Demo...(options are initialised to be blank or a
380     * sensible default if a checkbox/button).
381     *
382     * @author Alan Maxwell
383     */
384    public TemplateEditorPanel()
385    {
386       // Call the JPanel's constructor first...
387       super();
388 
389       // Setup constraints that are common to all items...
390       constraints.insets = DEF_INSETS;
391       constraints.ipadx = DEF_PADDING;
392       constraints.ipady = DEF_PADDING;
393 
394       // Now we put together the user interface...
395 
396       // == IMAGE TAB ======================================================
397       //describes the image
398       JPanel imagePanel = newPanel();
399       constraints.gridy = 0;
400 
401       // image to catalog
402       setLabelConstraints(constraints);
403       imagePanel.add(new JLabel("Image to extract", JLabel.RIGHT), constraints);
404 
405       imageTextField = new JTextField();
406       imageTextField.setToolTipText("Pixel image that will be examined for objects and measured");
407       /* not entirely happy the whole updateFromImage thing by the user
408        imageTextField.addKeyListener(new KeyListener() {
409 
410        public void keyReleased(KeyEvent e)  { }
411        public void keyTyped(KeyEvent e)    { }
412 
413        // Invoked when a key has been pressed.
414        public void keyPressed(KeyEvent e)
415        {
416        if (e.getKeyCode() == e.VK_ENTER)
417        {
418        updateFromImageHeader();
419        }
420        }
421        });
422        /**/
423 
424       setEntryConstraints(constraints);
425       imagePanel.add(imageTextField, constraints);
426 
427       imageChooserButton = new JSetFileButton();
428       imageChooserButton.addChoosableFilter(new ExtensionFileFilter(new String[] {"fits", "FITS"},"FITS files"));
429       imageChooserButton.setTextField(imageTextField);
430       setControlConstraints(constraints);
431       imagePanel.add(imageChooserButton, constraints);
432 
433       //adds another action listener, which should be called after the image text
434       //field has been updated, to update the image information
435       //beware that this might be called *before* the text field is updated
436       /*
437       imageChooserButton.addActionListener(new ActionListener() {
438                public void actionPerformed(ActionEvent e)
439                {
440                   if (imageChooserButton.getChosenFile() != null)
441                   {
442                      setImage(imageChooserButton.getChosenFile().getAbsolutePath());
443                   }
444                }
445             });
446        */
447 
448       imagePasteButton = new JPasteButton(imageTextField);
449       constraints.gridx++;
450       imagePanel.add(imagePasteButton, constraints);
451 
452       imageHeaderButton = new JButton("Ex");
453       imageHeaderButton.setToolTipText("Auto-examines FITS header");
454       imageHeaderButton.addActionListener(new ActionListener() {
455                public void actionPerformed(ActionEvent e)
456                {
457                   setImage(imageTextField.getText());
458                }
459             });
460       constraints.gridx = constraints.RELATIVE;
461       imagePanel.add(imageHeaderButton, constraints);
462 
463 //    imageHeaderViewerBtn = new JButton("View");
464 //    imageHeaderViewerBtn.setToolTipText("View FITS header");
465 
466 
467       //---- Dual Image mode -----
468       constraints.gridy++;  //new line
469       setLabelConstraints(constraints);
470 
471       dualImageToggle = new JCheckBox("Dual Image mode", false);
472       //      constraints.anchor = constraints.EAST;
473       imagePanel.add(dualImageToggle, constraints);
474 
475       dualImageToggle.addActionListener( new ActionListener() {
476                public void actionPerformed(ActionEvent ae) {
477                   setDualImageMode(dualImageToggle.isSelected());
478                }
479             });
480 
481       setEntryConstraints(constraints);
482       dualImageTextField = new JTextField();
483       dualImageTextField.setToolTipText("In dual image mode, fluxes will be returned for THIS image, for objects found in the ABOVE image");
484       imagePanel.add(dualImageTextField, constraints);
485 
486       dualImageChooserButton = new JSetFileButton();
487       dualImageChooserButton.setTextField(dualImageTextField);
488       dualImageChooserButton.addChoosableFilter(new ExtensionFileFilter(new String[] {"fits", "FITS"},"FITS files"));
489       setControlConstraints(constraints);
490       imagePanel.add(dualImageChooserButton, constraints);
491 
492       dualImagePasteButton = new JPasteButton(dualImageTextField);
493       constraints.gridx = constraints.RELATIVE;
494       imagePanel.add(dualImagePasteButton, constraints);
495 
496       /*
497        // header viewer button - reads & displays image header if it's FITS, and
498        // updates other input fields if poss
499        constraints.gridy++;  //new line
500 
501        imageHeaderViewerBtn = new JButton("Examine Header");
502        setControlConstraints(constraints);
503        constraints.gridwidth = constraints.REMAINDER;
504        imagePanel.add(imageHeaderViewerBtn, constraints);
505 
506        imageHeaderViewerBtn.addActionListener( new ActionListener()
507        {
508        public void actionPerformed(ActionEvent ae)
509        {
510        readImageHeader();
511        }
512        }
513        );
514        */
515       setDualImageMode(false);
516 
517       // what type is it - ccd or photo
518       constraints.gridy++;  //new line
519       setControlConstraints(constraints);
520       constraints.gridwidth=constraints.REMAINDER;
521       JPanel panelDetectType = new JPanel(new FlowLayout(FlowLayout.LEFT));
522       panelDetectType.setToolTipText("Type of detection image [DETECT_TYPE]");
523 
524       radiobuttongroupDetectType = new ButtonGroup();
525 
526       radiobuttonDetectTypeCCD = new JRadioButton("CCD");
527       radiobuttonDetectTypeCCD.setToolTipText(panelDetectType.getToolTipText());
528       radiobuttonDetectTypeCCD.setActionCommand("CCD");
529       radiobuttongroupDetectType.add(radiobuttonDetectTypeCCD);
530       panelDetectType.add(radiobuttonDetectTypeCCD);
531 
532       radiobuttonDetectTypePHOTO = new JRadioButton("Photo");
533       radiobuttonDetectTypePHOTO.setToolTipText(panelDetectType.getToolTipText());
534       radiobuttonDetectTypePHOTO.setActionCommand("PHOTO");
535       radiobuttongroupDetectType.add(radiobuttonDetectTypePHOTO);
536       panelDetectType.add(radiobuttonDetectTypePHOTO);
537 
538       radiobuttongroupDetectType.setSelected(
539          radiobuttonDetectTypeCCD.getModel(), true
540       );
541 
542       setEntryConstraints(constraints);
543       imagePanel.add(panelDetectType, constraints);
544 
545       //what wavelength band.  At the moment, pick from a list of UCDs - later,
546       //we might want to specify wavelength/frequency and bandwidth; later still,
547       //filter charecteristics.  These may be derived from the image...
548       constraints.gridy++;
549 
550       setLabelConstraints(constraints);
551       //      constraints.anchor = constraints.NORTHEAST;
552       imagePanel.add(new JLabel("Passband", JLabel.RIGHT),constraints);
553 
554       passbandPanel = new PassbandSpecifierPanel();
555       setEntryConstraints(constraints);
556       constraints.gridheight = 2;
557       constraints.insets = new Insets(0,8,0,5); //don't know why we need this here...
558       imagePanel.add(passbandPanel, constraints);
559       constraints.insets = null;
560 
561       /***
562        passbandUcdPicker = new JComboBox(new String[]  {
563        "PHOT_MAG",
564        "PHOT_MAG_U",
565        "PHOT_MAG_B",
566        "PHOT_MAG_V",
567        "PHOT_MAG_R",
568        "PHOT_MAG_I",
569        "PHOT_MAG_J",
570        "PHOT_MAG_K",
571        });
572        setEntryConstraints(constraints);
573        imagePanel.add(passbandUcdPicker, constraints);
574        passbandUcdPicker.setSelectedItem("PHOT_MAG");
575        **/
576 
577       // ------------------------------------------------------------------------
578 
579 
580       // == EXTRACTION TAB ======================================================
581       // Create all items for the panel...
582 
583       labelFlagImage = new JLabel("Flag Image:  ");
584       textFlagImage = new JTextField("");
585       textFlagImage.setToolTipText(
586          "The filename of an input flag image [FLAG_IMAGE]"
587       );
588       sizeComponent(textFlagImage, DEF_TEXTFIELD_DIMENSION);
589 
590       JSetFileButton fbFlagImage = new JSetFileButton(textFlagImage);
591 
592       labelDetMinArea = new JLabel("Detect Min. Area:  ");
593       integertextDetMinArea = new JIntegerField();
594       integertextDetMinArea.setToolTipText(
595          "Minimum number of pixels above threshold [DETECT_MINAREA]"
596       );
597       sizeComponent(integertextDetMinArea, DEF_TEXTFIELD_DIMENSION);
598 
599       labelDetThresh = new JLabel("Detect Threshold:  ");
600 
601       doubletextDetThresh1 = new JDoubleField();
602       doubletextDetThresh1.setToolTipText(
603          "<sigmas> or <threshold> [DETECT_THRESH]"
604       );
605       sizeComponent(doubletextDetThresh1, DEF_HALF_TEXTFIELD_DIMENSION);
606 
607       doubletextDetThresh2 = new JDoubleField();
608       doubletextDetThresh2.setToolTipText(
609          "<ZP> in mag.arcsec-2 [DETECT_THRESH]"
610       );
611       sizeComponent(doubletextDetThresh2, DEF_HALF_TEXTFIELD_DIMENSION);
612 
613       labelAnalysisThresh = new JLabel("Analysis Threshold:  ");
614       doubletextAnalysisThresh1 = new JDoubleField();
615       doubletextAnalysisThresh1.setToolTipText(
616          "<sigmas> or <threshold> [ANALYSIS_THRESH]"
617       );
618       sizeComponent(doubletextAnalysisThresh1, DEF_HALF_TEXTFIELD_DIMENSION);
619       doubletextAnalysisThresh2 = new JDoubleField();
620       doubletextAnalysisThresh2.setToolTipText(
621          "<ZP> in mag.arcsec-2 [ANALYSIS_THRESH]"
622       );
623       sizeComponent(doubletextAnalysisThresh2, DEF_HALF_TEXTFIELD_DIMENSION);
624 
625       checkApplyFilter = new JCheckBox("  Apply Detection Filter:", true);
626       checkApplyFilter.setActionCommand("APPLYFILTER");
627       ToggleButtonControllerListener listenerApplyFilter =
628          new ToggleButtonControllerListener();
629       checkApplyFilter.addActionListener(listenerApplyFilter);
630       checkApplyFilter.setToolTipText(
631          "Apply filter On[Y]/Off[N] [FILTER]"
632       );
633       String [] filterNames = {
634          "default.conv", "block_3x3.conv", "gauss_1.5_3x3.conv", "gauss_2.0_3x3.conv",
635             "gauss_2.0_5x5.conv", "gauss_2.5_5x5.conv", "gauss_3.0_5x5.conv",
636             "gauss_3.0_7x7.conv", "gauss_4.0_7x7.conv", "gauss_5.0_9x9.conv",
637             "mexhat_1.5_5x5.conv", "mexhat_2.0_7x7.conv", "mexhat_2.5_7x7.conv",
638             "mexhat_3.0_9x9.conv", "mexhat_4.0_9x9.conv", "mexhat_5.0_11x11.conv",
639             "tophat_1.5_3x3.conv", "tophat_2.0_3x3.conv", "tophat_2.5_3x3.conv",
640             "tophat_3.0_3x3.conv", "tophat_4.0_5x5.conv", "tophat_5.0_5x5.conv"
641       };
642 
643       textFilterName = new JComboBox(filterNames);
644       textFilterName.setEditable(true);
645       textFilterName.setToolTipText(
646          "The filename of a detection filter to apply [FILTER_NAME]"
647       );
648       textFilterName.setSelectedItem("");
649       sizeComponent(textFilterName, DEF_TEXTFIELD_DIMENSION);
650       // Auto-hide of text field, dependant on check box!
651       listenerApplyFilter.addComponent(textFilterName);
652 
653       JSetFileButton fbFilterName = new JSetFileButton();
654       fbFilterName.setComboBox(textFilterName);
655       listenerApplyFilter.addComponent(fbFilterName);
656 
657       labelDeblendThresh = new JLabel("Deblending # Sub-Thresholds:  ");
658       integertextDeblendThresh = new JIntegerField();
659       integertextDeblendThresh.setToolTipText(
660          "Number of deblending sub-thresholds [DEBLEND_NTHRESH]"
661       );
662       sizeComponent(integertextDeblendThresh, DEF_TEXTFIELD_DIMENSION);
663 
664       labelDeblendMinCont = new JLabel("Deblending Min. Contrast:  ");
665       doubletextDeblendMinCont = new JDoubleField();
666       doubletextDeblendMinCont.setToolTipText(
667          "Minimum contrast parameter for deblending [DEBLEND_MINCONT]"
668       );
669       sizeComponent(doubletextDeblendMinCont, DEF_TEXTFIELD_DIMENSION);
670 
671       checkCleaning = new JCheckBox("  Clean with Efficiency:", true);
672       checkCleaning.setActionCommand("CLEANING");
673       ToggleButtonControllerListener listenerCleaning =
674          new ToggleButtonControllerListener();
675       checkCleaning.addActionListener(listenerCleaning);
676       checkCleaning.setToolTipText(
677          "Apply cleaning On[Y]/Off[N] [CLEAN]"
678       );
679       doubletextCleaning = new JDoubleField();
680       doubletextCleaning.setToolTipText(
681          "Cleaning efficiency for spurious detections [CLEAN_PARAM]"
682       );
683       sizeComponent(doubletextCleaning, DEF_TEXTFIELD_DIMENSION);
684 
685       // Auto-hide of text field, dependant on check box!
686       listenerCleaning.addComponent(doubletextCleaning);
687 
688       labelMaskType = new JLabel("Mask Type:  ");
689       panelMaskType = new JPanel(new FlowLayout(FlowLayout.LEFT));
690       panelMaskType.setToolTipText(
691          "Type of detection MASKing [MASK_TYPE]"
692       );
693       radiobuttongroupMaskType = new ButtonGroup();
694       radiobuttonMaskTypeCORRECT =
695          new JRadioButton("Correct");
696       radiobuttonMaskTypeCORRECT.setActionCommand("CORRECT");
697       radiobuttonMaskTypeCORRECT.setToolTipText(
698          panelMaskType.getToolTipText()
699       );
700       radiobuttongroupMaskType.add(radiobuttonMaskTypeCORRECT);
701       panelMaskType.add(radiobuttonMaskTypeCORRECT);
702       radiobuttonMaskTypeBLANK =
703          new JRadioButton("Blank");
704       radiobuttonMaskTypeBLANK.setActionCommand("BLANK");
705       radiobuttonMaskTypeBLANK.setToolTipText(
706          panelMaskType.getToolTipText()
707       );
708       radiobuttongroupMaskType.add(radiobuttonMaskTypeBLANK);
709       panelMaskType.add(radiobuttonMaskTypeBLANK);
710       radiobuttonMaskTypeNONE =
711          new JRadioButton("None");
712       radiobuttonMaskTypeNONE.setActionCommand("NONE");
713       radiobuttonMaskTypeNONE.setToolTipText(
714          panelMaskType.getToolTipText()
715       );
716       radiobuttongroupMaskType.add(radiobuttonMaskTypeNONE);
717       panelMaskType.add(radiobuttonMaskTypeNONE);
718       radiobuttongroupMaskType.setSelected(
719          radiobuttonMaskTypeCORRECT.getModel(), true
720       );
721 
722       // Now assemble the contents into the tabbed panel...
723       JPanel panelContentsExtraction = new JPanel(new GridBagLayout());
724 
725       addGB(
726          panelContentsExtraction, labelFlagImage,
727          0, 1, GridBagConstraints.EAST, false, 1
728       );
729 
730       addGB(
731          panelContentsExtraction, textFlagImage,
732          1, 1, GridBagConstraints.WEST, false, 2
733       );
734 
735       addGB(
736          panelContentsExtraction, fbFlagImage,
737          3, 1, GridBagConstraints.WEST, false, 1
738       );
739 
740       addGB(
741          panelContentsExtraction, labelDetMinArea,
742          0, 2, GridBagConstraints.EAST, false, 1
743       );
744 
745       addGB(
746          panelContentsExtraction, integertextDetMinArea,
747          1, 2, GridBagConstraints.WEST, false, 2
748       );
749 
750       addGB(
751          panelContentsExtraction, labelDetThresh,
752          0, 3, GridBagConstraints.EAST, false, 1
753       );
754 
755       addGB(
756          panelContentsExtraction, doubletextDetThresh1,
757          1, 3, GridBagConstraints.WEST, false, 1
758       );
759 
760       addGB(
761          panelContentsExtraction, doubletextDetThresh2,
762          2, 3, GridBagConstraints.WEST, false, 1
763       );
764 
765       addGB(
766          panelContentsExtraction, labelAnalysisThresh,
767          0, 4, GridBagConstraints.EAST, false, 1
768       );
769 
770       addGB(
771          panelContentsExtraction, doubletextAnalysisThresh1,
772          1, 4, GridBagConstraints.WEST, false, 1
773       );
774 
775       addGB(
776          panelContentsExtraction, doubletextAnalysisThresh2,
777          2, 4, GridBagConstraints.WEST, false, 1
778       );
779 
780       addGB(
781          panelContentsExtraction, checkApplyFilter,
782          0, 5, GridBagConstraints.EAST, true, 1
783       );
784 
785       addGB(
786          panelContentsExtraction, textFilterName,
787          1, 5, GridBagConstraints.WEST, true, 2
788       );
789 
790       addGB(
791          panelContentsExtraction, fbFilterName,
792          3, 5, GridBagConstraints.WEST, true, 1
793       );
794 
795       addGB(
796          panelContentsExtraction, labelDeblendThresh,
797          0, 6, GridBagConstraints.EAST, true, 1
798       );
799 
800       addGB(
801          panelContentsExtraction, integertextDeblendThresh,
802          1, 6, GridBagConstraints.WEST, true, 2
803       );
804 
805       addGB(
806          panelContentsExtraction, labelDeblendMinCont,
807          0, 7, GridBagConstraints.EAST, false, 1
808       );
809 
810       addGB(
811          panelContentsExtraction, doubletextDeblendMinCont,
812          1, 7, GridBagConstraints.WEST, false, 2
813       );
814 
815       addGB(
816          panelContentsExtraction, checkCleaning,
817          0, 8, GridBagConstraints.EAST, true, 1
818       );
819 
820       addGB(
821          panelContentsExtraction, doubletextCleaning,
822          1, 8, GridBagConstraints.WEST, true, 2
823       );
824 
825       addGB(
826          panelContentsExtraction, labelMaskType,
827          0, 9, GridBagConstraints.EAST, true, 1
828       );
829 
830       addGB(
831          panelContentsExtraction, panelMaskType,
832          1, 9, GridBagConstraints.WEST, true, 2
833       );
834 
835       JPanel panelExtraction = new JPanel(new FlowLayout(FlowLayout.LEFT));
836       panelExtraction.add(panelContentsExtraction);
837       // ------------------------------------------------------------------------
838 
839 
840       // == PHOTOMETRY TAB ======================================================
841       // Create all items for the panel...
842       labelPhotApertures = new JLabel("Photo Aperture(s):  ");
843       inttextPhotApertures = new JIntegerField();
844       inttextPhotApertures.setToolTipText(
845          "MAG_APER aperture diameter(s) in pixels [PHOT_APERTURES]"
846       );
847       sizeComponent(inttextPhotApertures, DEF_TEXTFIELD_DIMENSION);
848 
849       labelPhotAutoParams = new JLabel("Photo Auto Parameters:  ");
850       doubletextPhotAutoParams1 = new JDoubleField();
851       doubletextPhotAutoParams1.setToolTipText(
852          "MAG_AUTO parameter: <Kron_fact> [PHOT_AUTOPARAMS]"
853       );
854       sizeComponent(doubletextPhotAutoParams1, DEF_HALF_TEXTFIELD_DIMENSION);
855       doubletextPhotAutoParams2 = new JDoubleField();
856       doubletextPhotAutoParams2.setToolTipText(
857          "MAG_AUTO parameter: <min_radius> [PHOT_AUTOPARAMS]"
858       );
859       sizeComponent(doubletextPhotAutoParams2, DEF_HALF_TEXTFIELD_DIMENSION);
860 
861       labelSatLevel = new JLabel("Saturation Level:  ");
862       doubletextSatLevel = new JDoubleField();
863       doubletextSatLevel.setToolTipText(
864          "Level (in ADUs) at which arises saturation [SATUR_LEVEL]"
865       );
866       sizeComponent(doubletextSatLevel, DEF_TEXTFIELD_DIMENSION);
867 
868       labelMagZero = new JLabel("Magnitude Zero-point:  ");
869       doubletextMagZero = new JDoubleField();
870       doubletextMagZero.setToolTipText(
871          "Megnitude zero-point [MAG_ZEROPOINT]"
872       );
873       sizeComponent(doubletextMagZero, DEF_TEXTFIELD_DIMENSION);
874 
875       labelMagGamma = new JLabel("Gamma of Emulsion:  ");
876       doubletextMagGamma = new JDoubleField();
877       doubletextMagGamma.setToolTipText(
878          "Gamma of emulsion (for photographic scans) [MAG_GAMMA]"
879       );
880       sizeComponent(doubletextMagGamma, DEF_TEXTFIELD_DIMENSION);
881 
882       labelGain = new JLabel("Detector Gain:  ");
883       doubletextGain = new JDoubleField();
884       doubletextGain.setToolTipText(
885          "Detector gain in e-/ADU [GAIN]"
886       );
887       sizeComponent(doubletextGain, DEF_TEXTFIELD_DIMENSION);
888 
889       labelPixelScale = new JLabel("Pixel Scale:  ");
890       doubletextPixelScale = new JDoubleField();
891       doubletextPixelScale.setToolTipText(
892          "Size of pixel in arcsec (0 = use FITS info) [PIXEL_SCALE]"
893       );
894       sizeComponent(doubletextPixelScale, DEF_TEXTFIELD_DIMENSION);
895 
896       // Now assemble the contents into the tabbed panel...
897       JPanel panelContentsPhotometry = new JPanel(new GridBagLayout());
898 
899       addGB(
900          panelContentsPhotometry, labelPhotApertures,
901          0, 0, GridBagConstraints.EAST, true, 1
902       );
903 
904       addGB(
905          panelContentsPhotometry, inttextPhotApertures,
906          1, 0, GridBagConstraints.WEST, true, 2
907       );
908 
909       addGB(
910          panelContentsPhotometry, labelPhotAutoParams,
911          0, 1, GridBagConstraints.EAST, false, 1
912       );
913 
914       addGB(
915          panelContentsPhotometry, doubletextPhotAutoParams1,
916          1, 1, GridBagConstraints.WEST, false, 1
917       );
918 
919       addGB(
920          panelContentsPhotometry, doubletextPhotAutoParams2,
921          2, 1, GridBagConstraints.WEST, false, 1
922       );
923 
924       addGB(
925          panelContentsPhotometry, labelSatLevel,
926          0, 2, GridBagConstraints.EAST, true, 1
927       );
928 
929       addGB(
930          panelContentsPhotometry, doubletextSatLevel,
931          1, 2, GridBagConstraints.WEST, true, 2
932       );
933 
934       addGB(
935          panelContentsPhotometry, labelMagZero,
936          0, 3, GridBagConstraints.EAST, true, 1
937       );
938 
939       addGB(
940          panelContentsPhotometry, doubletextMagZero,
941          1, 3, GridBagConstraints.WEST, true, 2
942       );
943 
944       addGB(
945          panelContentsPhotometry, labelMagGamma,
946          0, 4, GridBagConstraints.EAST, false, 1
947       );
948 
949       addGB(
950          panelContentsPhotometry, doubletextMagGamma,
951          1, 4, GridBagConstraints.WEST, false, 2
952       );
953 
954       addGB(
955          panelContentsPhotometry, labelGain,
956          0, 5, GridBagConstraints.EAST, false, 1
957       );
958 
959       addGB(
960          panelContentsPhotometry, doubletextGain,
961          1, 5, GridBagConstraints.WEST, false, 2
962       );
963 
964       addGB(
965          panelContentsPhotometry, labelPixelScale,
966          0, 6, GridBagConstraints.EAST, false, 1
967       );
968 
969       addGB(
970          panelContentsPhotometry, doubletextPixelScale,
971          1, 6, GridBagConstraints.WEST, false, 2
972       );
973 
974       JPanel panelPhotometry = new JPanel(new FlowLayout(FlowLayout.LEFT));
975       panelPhotometry.add(panelContentsPhotometry);
976       // ------------------------------------------------------------------------
977 
978 
979       // == STAR_GALAXY_SEPARATION TAB ======================================================
980       // Create all items for the panel...
981       labelSeeingFWHM = new JLabel("Seeing FWHM:  ");
982       doubletextSeeingFWHM = new JDoubleField();
983       doubletextSeeingFWHM.setToolTipText(
984          "Stellar Full-Width-Half-Maximum (in arcsec) [SEEING_FWHM]"
985       );
986       sizeComponent(doubletextSeeingFWHM, DEF_TEXTFIELD_DIMENSION);
987 
988       labelStarNNWName = new JLabel("Neural Net Weight File:  ");
989       textStarNNWName = new JTextField();
990       textStarNNWName.setToolTipText(
991          "The filename of the Neural-Network_Weight table [STARNNW_NAME]"
992       );
993       sizeComponent(textStarNNWName, DEF_TEXTFIELD_DIMENSION);
994 
995       JSetFileButton fbStarNNWName = new JSetFileButton(textStarNNWName);
996 
997       // Now assemble the contents into the tabbed panel...
998       JPanel panelContentsStar_Galaxy_Separation = new JPanel(new GridBagLayout());
999 
1000       addGB(
1001          panelContentsStar_Galaxy_Separation, labelSeeingFWHM,
1002          0, 0, GridBagConstraints.EAST, true, 1
1003       );
1004 
1005       addGB(
1006          panelContentsStar_Galaxy_Separation, doubletextSeeingFWHM,
1007          1, 0, GridBagConstraints.WEST, true, 2
1008       );
1009 
1010       addGB(
1011          panelContentsStar_Galaxy_Separation, labelStarNNWName,
1012          0, 1, GridBagConstraints.EAST, true, 1
1013       );
1014 
1015       addGB(
1016          panelContentsStar_Galaxy_Separation, textStarNNWName,
1017          1, 1, GridBagConstraints.WEST, true, 2
1018       );
1019 
1020       addGB(
1021          panelContentsStar_Galaxy_Separation, fbStarNNWName,
1022          3, 1, GridBagConstraints.WEST, true, 1
1023       );
1024 
1025       JPanel panelStar_Galaxy_Separation = new JPanel(new FlowLayout(FlowLayout.LEFT));
1026       panelStar_Galaxy_Separation.add(panelContentsStar_Galaxy_Separation);
1027 
1028       // ------------------------------------------------------------------------
1029 
1030 
1031       // == BACKGROUND TAB ======================================================
1032       // Create all items for the panel...
1033       labelBackSize = new JLabel("Background mesh:  ");
1034       integertextBackSize1 = new JIntegerField();
1035       integertextBackSize1.setToolTipText(
1036          "<size> or <width> [BACKSIZE]"
1037       );
1038       sizeComponent(integertextBackSize1, DEF_HALF_TEXTFIELD_DIMENSION);
1039       integertextBackSize2 = new JIntegerField();
1040       integertextBackSize2.setToolTipText(
1041          "<height> [BACKSIZE]"
1042       );
1043       sizeComponent(integertextBackSize2, DEF_HALF_TEXTFIELD_DIMENSION);
1044 
1045       labelBackFilter = new JLabel("Background filter:  ");
1046       integertextBackFilter1 = new JIntegerField();
1047       integertextBackFilter1.setToolTipText(
1048          "<size> or <width> [BACK_FILTERSIZE]"
1049       );
1050       sizeComponent(integertextBackFilter1, DEF_HALF_TEXTFIELD_DIMENSION);
1051       integertextBackFilter2 = new JIntegerField();
1052       integertextBackFilter2.setToolTipText(
1053          "<height> [BACK_FILTERSIZE]"
1054       );
1055       sizeComponent(integertextBackFilter2, DEF_HALF_TEXTFIELD_DIMENSION);
1056 
1057       labelBackPhotoType = new JLabel("Photo Type:  ");
1058       panelBackPhotoType = new JPanel(new FlowLayout(FlowLayout.LEFT));
1059       panelBackPhotoType.setToolTipText(
1060          "Background photo type [BACKPHOTO_TYPE]"
1061       );
1062       radiobuttongroupBackPhotoType = new ButtonGroup();
1063       radiobuttonBackPhotoTypeGLOBAL =
1064          new JRadioButton("Global");
1065       radiobuttonBackPhotoTypeGLOBAL.setActionCommand("GLOBAL");
1066       radiobuttonBackPhotoTypeGLOBAL.setToolTipText(
1067          panelBackPhotoType.getToolTipText()
1068       );
1069       radiobuttongroupBackPhotoType.add(radiobuttonBackPhotoTypeGLOBAL);
1070       panelBackPhotoType.add(radiobuttonBackPhotoTypeGLOBAL);
1071       radiobuttonBackPhotoTypeLOCAL =
1072          new JRadioButton("Local");
1073       radiobuttonBackPhotoTypeLOCAL.setActionCommand("LOCAL");
1074       radiobuttonBackPhotoTypeLOCAL.setToolTipText(
1075          panelBackPhotoType.getToolTipText()
1076       );
1077       radiobuttongroupBackPhotoType.add(radiobuttonBackPhotoTypeLOCAL);
1078       panelBackPhotoType.add(radiobuttonBackPhotoTypeLOCAL);
1079       radiobuttongroupBackPhotoType.setSelected(
1080          radiobuttonBackPhotoTypeGLOBAL.getModel(), true
1081       );
1082 
1083       labelBackPhotoThick = new JLabel("Background thickness:  ");
1084       inttextBackPhotoThick = new JIntegerField();
1085       inttextBackPhotoThick.setToolTipText(
1086          "Thickness of the background LOCAL annulus [BACKPHOTO_THICK]"
1087       );
1088       sizeComponent(inttextBackPhotoThick, DEF_TEXTFIELD_DIMENSION);
1089 
1090       checkApplyPixFlag = new JCheckBox("  Apply Pixel Flag:", true);
1091       checkApplyPixFlag.setActionCommand("PIXELFLAG");
1092       ToggleButtonControllerListener listenerApplyPixFlag =
1093          new ToggleButtonControllerListener();
1094       checkApplyPixFlag.addActionListener(listenerApplyPixFlag);
1095       checkApplyPixFlag.setToolTipText(
1096          "Apply Pixel Flag On[Y]/Off[N] [**PARAMETER_NAME_HERE**]"
1097       );
1098       textApplyPixFlag = new JTextField();
1099       textApplyPixFlag.setToolTipText(
1100          "**TOOLTIP TEXT TO BE DEFINED HERE** [**PARAMETER_NAME_HERE**]"
1101       );
1102       // Link this text field with one on the Extraction tab...
1103       textApplyPixFlag.setDocument(
1104          textFlagImage.getDocument()
1105       );
1106       sizeComponent(textApplyPixFlag, DEF_TEXTFIELD_DIMENSION);
1107 
1108       // Auto-hide of text field, dependant on check box!
1109       listenerApplyPixFlag.addComponent(textApplyPixFlag);
1110 
1111       // Now assemble the contents into the tabbed panel...
1112       JPanel panelContentsBackground = new JPanel(new GridBagLayout());
1113 
1114       addGB(
1115          panelContentsBackground, labelBackSize,
1116          0, 0, GridBagConstraints.EAST, true, 1
1117       );
1118 
1119       addGB(
1120          panelContentsBackground, integertextBackSize1,
1121          1, 0, GridBagConstraints.WEST, true, 1
1122       );
1123 
1124       addGB(
1125          panelContentsBackground, integertextBackSize2,
1126          2, 0, GridBagConstraints.WEST, true, 1
1127       );
1128 
1129       addGB(
1130          panelContentsBackground, labelBackFilter,
1131          0, 1, GridBagConstraints.EAST, false, 1
1132       );
1133 
1134       addGB(
1135          panelContentsBackground, integertextBackFilter1,
1136          1, 1, GridBagConstraints.WEST, false, 1
1137       );
1138 
1139       addGB(
1140          panelContentsBackground, integertextBackFilter2,
1141          2, 1, GridBagConstraints.WEST, false, 1
1142       );
1143 
1144       addGB(
1145          panelContentsBackground, labelBackPhotoType,
1146          0, 2, GridBagConstraints.EAST, true, 1
1147       );
1148 
1149       addGB(
1150          panelContentsBackground, panelBackPhotoType,
1151          1, 2, GridBagConstraints.WEST, true, 2
1152       );
1153 
1154       addGB(
1155          panelContentsBackground, labelBackPhotoThick,
1156          0, 3, GridBagConstraints.EAST, false, 1
1157       );
1158 
1159       addGB(
1160          panelContentsBackground, inttextBackPhotoThick,
1161          1, 3, GridBagConstraints.WEST, false, 2
1162       );
1163 
1164       addGB(
1165          panelContentsBackground, checkApplyPixFlag,
1166          0, 4, GridBagConstraints.EAST, true, 1
1167       );
1168       addGB(
1169          panelContentsBackground, textApplyPixFlag,
1170          1, 4, GridBagConstraints.WEST, true, 2
1171       );
1172 
1173       JPanel panelBackground = new JPanel(new FlowLayout(FlowLayout.LEFT));
1174       panelBackground.add(panelContentsBackground);
1175 
1176       // ------------------------------------------------------------------------
1177 
1178       // == OUTPUT TAB ======================================================
1179       // Create all items for the panel...
1180 
1181       labelCheckImageType = new JLabel("Check Image Type:  ");
1182       String[] itemsCheckImageType =
1183       {
1184          "NONE", "MINIBACKGROUND", "BACKGROUND", "-BACKGROUND", "OBJECTS",
1185             "-OJBECTS", "SEGMENTATION", "APERTURES", "FILTERED"
1186       };
1187       comboCheckImageType = new JComboBox(itemsCheckImageType);
1188       comboCheckImageType.setSelectedIndex(0);
1189       comboCheckImageType.setToolTipText(
1190          "[CHECKIMAGE_TYPE]"
1191       );
1192       sizeComponent(comboCheckImageType, DEF_TEXTFIELD_DIMENSION);
1193 
1194       JLabel labelOutput = new JLabel("Output Columns:  ");
1195 
1196       JLabel labelOutputColumns = new JLabel("Available");
1197       listOutputColumns = new JMutableList();
1198       JScrollPane scrollOutputColumns =
1199          new JScrollPane(listOutputColumns);
1200 
1201       JLabel labelOutputColumnsSelected = new JLabel("Selected");
1202       listOutputColumnsSelected = new JMutableList();
1203       JScrollPane scrollOutputColumnsSelected =
1204          new JScrollPane(listOutputColumnsSelected);
1205 
1206       resetListOutputColumns();
1207 
1208       sizeComponent(
1209          scrollOutputColumns,
1210          new Dimension(
1211                       listOutputColumns.getPreferredSize().width + 30,
1212                       DEF_TEXTFIELD_HEIGHT * 12
1213                    )
1214       );
1215       sizeComponent(
1216          scrollOutputColumnsSelected,
1217          scrollOutputColumns.getPreferredSize()
1218       );
1219 
1220       buttonOutputColumnsADD = new JButton("Add  >>");
1221       buttonOutputColumnsADD.addActionListener( new ActionListener() {
1222                public void actionPerformed(ActionEvent ae) {
1223                   int [] availableIndices =
1224                      listOutputColumns.getSelectedIndices();
1225 
1226                   // Copy selected object(s) to the 'selected' column
1227                   for ( int indexLoop = 0;
1228                        indexLoop < availableIndices.length;
1229                        indexLoop++ )
1230                   {
1231                      listOutputColumnsSelected.getContents().addElement(
1232                         listOutputColumns.getContents().elementAt(
1233                                                                           availableIndices[indexLoop]
1234                                                                        )
1235                      );
1236                   };
1237 
1238                   // Remove them from the 'available' column, note MUST GO BACKWARDS!!
1239                   // (DUE TO DELETING OBJECTS - so it doesn't affect indices)...
1240                   for ( int indexLoop = availableIndices.length - 1;
1241                        indexLoop >= 0;
1242                        indexLoop-- )
1243                   {
1244                      listOutputColumns.getContents().removeElementAt(
1245                         availableIndices[indexLoop]
1246                      );
1247                   };
1248                }
1249             });
1250 
1251       buttonOutputColumnsREMOVE = new JButton("<<  Remove");
1252       buttonOutputColumnsREMOVE.addActionListener( new ActionListener() {
1253                public void actionPerformed(ActionEvent ae) {
1254                   int [] selectedIndices =
1255                      listOutputColumnsSelected.getSelectedIndices();
1256 
1257                   // Remove them from the 'available' column, note MUST GO BACKWARDS!!
1258                   // (DUE TO DELETING OBJECTS - so it doesn't affect indices)...
1259                   for ( int indexLoop = selectedIndices.length - 1;
1260                        indexLoop >= 0;
1261                        indexLoop-- )
1262                   {
1263                      //check it's removable (ie it's not in the obligatory list)
1264                      if (
1265                         !obligatoryOutputColumns.contains(
1266                            listOutputColumnsSelected.getContents().elementAt(
1267                                                             selectedIndices[indexLoop]
1268                                                          )
1269                         )
1270                      )
1271                      {
1272                         listOutputColumnsSelected.getContents().removeElementAt(
1273                            selectedIndices[indexLoop]
1274                         );
1275                      }
1276                   };
1277 
1278                   // Now clear and replace the contents of the available list,
1279                   // this is to preserve the original ORDER! Only adds items
1280                   // if they are not in the selected list...
1281                   listOutputColumns.getContents().clear();
1282 
1283                   for ( int indexLoop = 0;
1284                        indexLoop < itemsOutputColumns.length;
1285                        indexLoop++ )
1286                   {
1287                      if (
1288                         listOutputColumnsSelected.getContents().indexOf(
1289                            itemsOutputColumns[indexLoop]
1290                         ) == -1
1291                      )
1292                      {
1293                         listOutputColumns.getContents().addElement(
1294                            itemsOutputColumns[indexLoop]
1295                         );
1296                      }
1297                   }
1298                }
1299             });
1300 
1301       // Now assemble the contents into the tabbed panel...
1302       JPanel panelContentsOutput = new JPanel(new GridBagLayout());
1303 
1304       addGB(
1305          panelContentsOutput, labelCheckImageType,
1306          0, 0, GridBagConstraints.EAST, true, 1
1307       );
1308 
1309       addGB(
1310          panelContentsOutput, comboCheckImageType,
1311          1, 0, GridBagConstraints.WEST, true, 2
1312       );
1313 
1314       addGB(
1315          panelContentsOutput, labelOutputColumns,
1316          1, 1, GridBagConstraints.SOUTH, true, 1
1317       );
1318 
1319       addGB(
1320          panelContentsOutput, labelOutputColumnsSelected,
1321          2, 1, GridBagConstraints.SOUTH, true, 1
1322       );
1323 
1324       addGB(
1325          panelContentsOutput, labelOutput,
1326          0, 2, GridBagConstraints.NORTHEAST, false, 1
1327       );
1328 
1329       addGB(
1330          panelContentsOutput, scrollOutputColumns,
1331          1, 2, GridBagConstraints.CENTER, false, 1
1332       );
1333 
1334       addGB(
1335          panelContentsOutput, scrollOutputColumnsSelected,
1336          2, 2, GridBagConstraints.CENTER, false, 1
1337       );
1338 
1339       addGB(
1340          panelContentsOutput, buttonOutputColumnsADD,
1341          1, 3, GridBagConstraints.WEST, false, 1
1342       );
1343 
1344       addGB(
1345          panelContentsOutput, buttonOutputColumnsREMOVE,
1346          2, 3, GridBagConstraints.EAST, false, 1
1347       );
1348 
1349 
1350       JPanel panelOutput = new JPanel(new FlowLayout(FlowLayout.LEFT));
1351       panelOutput.add(panelContentsOutput);
1352       // ------------------------------------------------------------------------
1353 
1354 
1355       // == ADVANCED TAB =====================================================
1356       // Create all items for the panel...
1357 
1358       labelMemObjStack = new JLabel("Object Stack:  ");
1359       inttextMemObjStack = new JIntegerField();
1360       inttextMemObjStack.setToolTipText(
1361          "Number of objects in object stack [MEMORY_OBJSTACK]"
1362       );
1363       sizeComponent(inttextMemObjStack, DEF_TEXTFIELD_DIMENSION);
1364 
1365       labelMemPixStack = new JLabel("Pixel Stack:  ");
1366       inttextMemPixStack = new JIntegerField();
1367       inttextMemPixStack.setToolTipText(
1368          "Number of pixels in pixel stack [MEMORY_PIXSTACK]"
1369       );
1370       sizeComponent(inttextMemPixStack, DEF_TEXTFIELD_DIMENSION);
1371 
1372       labelMemBufSize = new JLabel("Buffer Size:  ");
1373       inttextMemBufSize = new JIntegerField();
1374       inttextMemBufSize.setToolTipText(
1375          "Number of lines in buffer [MEMORY_BUFSIZE]"
1376       );
1377       sizeComponent(inttextMemBufSize, DEF_TEXTFIELD_DIMENSION);
1378 
1379       labelVerboseType = new JLabel("Verbose Type:  ");
1380       panelVerboseType = new JPanel(new FlowLayout(FlowLayout.LEFT));
1381       panelVerboseType.setToolTipText(
1382          "Verbosity [VERBOSE_TYPE]"
1383       );
1384       radiobuttongroupVerboseType = new ButtonGroup();
1385       radiobuttonVerboseTypeNORMAL =
1386          new JRadioButton("Normal");
1387       radiobuttonVerboseTypeNORMAL.setActionCommand("NORMAL");
1388       radiobuttonVerboseTypeNORMAL.setToolTipText(
1389          panelVerboseType.getToolTipText()
1390       );
1391       radiobuttongroupVerboseType.add(radiobuttonVerboseTypeNORMAL);
1392       panelVerboseType.add(radiobuttonVerboseTypeNORMAL);
1393       radiobuttonVerboseTypeQUIET =
1394          new JRadioButton("Quiet");
1395       radiobuttonVerboseTypeQUIET.setActionCommand("QUIET");
1396       radiobuttonVerboseTypeQUIET.setToolTipText(
1397          panelVerboseType.getToolTipText()
1398       );
1399       radiobuttongroupVerboseType.add(radiobuttonVerboseTypeQUIET);
1400       panelVerboseType.add(radiobuttonVerboseTypeQUIET);
1401       radiobuttonVerboseTypeFULL =
1402          new JRadioButton("Full");
1403       radiobuttonVerboseTypeFULL.setActionCommand("FULL");
1404       radiobuttonVerboseTypeFULL.setToolTipText(
1405          panelVerboseType.getToolTipText()
1406       );
1407       radiobuttongroupVerboseType.add(radiobuttonVerboseTypeFULL);
1408       panelVerboseType.add(radiobuttonVerboseTypeFULL);
1409       radiobuttongroupVerboseType.setSelected(
1410          radiobuttonVerboseTypeNORMAL.getModel(), true
1411       );
1412 
1413       // Now assemble the contents into the tabbed panel...
1414       JPanel panelContentsAdvanced = new JPanel(new GridBagLayout());
1415 
1416       addGB(
1417          panelContentsAdvanced, labelMemObjStack,
1418          0, 0, GridBagConstraints.NORTHEAST, true, 1
1419       );
1420 
1421       addGB(
1422          panelContentsAdvanced, inttextMemObjStack,
1423          1, 0, GridBagConstraints.WEST, true, 2
1424       );
1425 
1426       addGB(
1427          panelContentsAdvanced, labelMemPixStack,
1428          0, 1, GridBagConstraints.NORTHEAST, false, 1
1429       );
1430 
1431       addGB(
1432          panelContentsAdvanced, inttextMemPixStack,
1433          1, 1, GridBagConstraints.WEST, false, 2
1434       );
1435 
1436       addGB(
1437          panelContentsAdvanced, labelMemBufSize,
1438          0, 2, GridBagConstraints.NORTHEAST, false, 1
1439       );
1440 
1441       addGB(
1442          panelContentsAdvanced, inttextMemBufSize,
1443          1, 2, GridBagConstraints.WEST, false, 2
1444       );
1445 
1446       addGB(
1447          panelContentsAdvanced, labelVerboseType,
1448          0, 3, GridBagConstraints.EAST, true, 1
1449       );
1450 
1451       addGB(
1452          panelContentsAdvanced, panelVerboseType,
1453          1, 3, GridBagConstraints.WEST, true, 2
1454       );
1455 
1456       JPanel panelAdvanced = new JPanel(new FlowLayout(FlowLayout.LEFT));
1457       panelAdvanced.add(panelContentsAdvanced);
1458 
1459       // ------------------------------------------------------------------------
1460 
1461       // Assemble all the above panels into a nice tabbed display
1462 
1463       setTabPlacement(JTabbedPane.TOP);
1464 
1465       addTab("Image", imagePanel);
1466       addTab("Extraction", panelExtraction);
1467       addTab("Photometry", panelPhotometry);
1468       addTab("Separation", panelStar_Galaxy_Separation);
1469       addTab("Background", panelBackground);
1470       addTab("Output", panelOutput);
1471       addTab("Advanced", panelAdvanced);
1472    };
1473 
1474 
1475    /***
1476     * Overrides addTab(...) to force added panels to the top of the pane
1477     */
1478    public void addTab(String s, Component c)
1479    {
1480       JPanel p = new JPanel(new BorderLayout());
1481       p.add(c, BorderLayout.NORTH);
1482       super.addTab(s,p);
1483    }
1484    /***
1485     * A simple method to force a JComponent to become a specific size.
1486     *
1487     * @author Alan Maxwell
1488     */
1489    public static void sizeComponent(JComponent item, Dimension dimension)
1490    {
1491       item.setMinimumSize(dimension);
1492       item.setPreferredSize(dimension);
1493       // item.setMaximumSize(dimension);
1494    };
1495 
1496    /***
1497     * A simple method to easily add a Component to a (GridBagLayout)
1498     * Container - note that if the container does not have a GridBagLayout
1499     * set as its layout manager, this method will update the layout manager.
1500     *
1501     * @author Alan Maxwell
1502     */
1503    public void addGB(Container cont, Component comp, int x, int y,
1504                      int anchor, boolean spaceAbove, int colSpan)
1505    {
1506 
1507       if ((cont.getLayout() instanceof GridBagLayout) == false)
1508       {
1509          cont.setLayout(new GridBagLayout());
1510       }
1511       {
1512          if (spaceAbove == true)
1513          {
1514             constraints.insets = DEF_VSPACE_INSETS;
1515          }
1516          else
1517          {
1518             constraints.insets = DEF_INSETS;
1519          };
1520 
1521          constraints.gridwidth = colSpan;
1522          constraints.gridheight = 1;
1523 
1524          constraints.anchor = anchor;
1525          constraints.gridx = x;
1526          constraints.gridy = y;
1527          cont.add(comp, constraints);
1528       };
1529    };
1530 
1531    /***
1532     * A convenience routine setting constraints suitable for a label
1533     * (full fill, low weighting, etc)
1534     */
1535    private void setLabelConstraints(GridBagConstraints constraints)
1536    {
1537       constraints.fill = constraints.BOTH;
1538       constraints.gridheight = 1;
1539       constraints.gridwidth = 1;
1540       constraints.gridx = 0;
1541       constraints.weightx = 0;
1542       constraints.weighty = 0;
1543    }
1544 
1545    /***
1546     * A convenience routine setting constraints for a user entry component -
1547     * centers in its cell, fills horizontally, high weight
1548     */
1549    private void setEntryConstraints(GridBagConstraints constraints)
1550    {
1551       constraints.anchor = constraints.CENTER;
1552       constraints.fill = constraints.HORIZONTAL;
1553       constraints.gridheight = 1;
1554       constraints.gridwidth = 1;
1555       constraints.gridx = 1;
1556       constraints.weightx = 1;
1557       constraints.weighty = 0;
1558    }
1559 
1560    /***
1561     * A convenience routine setting constraints for a supplementary control
1562     * (eg button for selecting a file).  centers in its cell, does not fill,
1563     * low weight
1564     */
1565    private void setControlConstraints(GridBagConstraints constraints)
1566    {
1567       constraints.anchor = constraints.CENTER;
1568       constraints.fill = constraints.NONE;
1569       constraints.gridheight = 1;
1570       constraints.gridwidth = 1;
1571       constraints.gridx = 3;
1572       constraints.weightx = 0;
1573       constraints.weighty = 0;
1574    }
1575 
1576    /***
1577     * A convenience routine to create the standard panels used
1578     */
1579    protected JPanel newPanel()
1580    {
1581       //      GridLayout2 flexilayout = new GridLayout2(0,4,2,10);
1582 
1583       //FlexiGridLayout flexilayout = new FlexiGridLayout(4);
1584       // flexilayout.setHGap(2);
1585       // flexilayout.setVGap(10);
1586 
1587       // JPanel panel = new JPanel(flexilayout);
1588       // panel.setBorder(BorderFactory.createEmptyBorder(10,5,5,5));
1589       // return panel;
1590 
1591       JPanel panel = new JPanel(new GridBagLayout());
1592       panel.setBorder(BorderFactory.createEmptyBorder(10,5,5,5));
1593       return panel;
1594    }
1595 
1596    /***
1597     * sets the image to the given string (might be a path, might be a url)
1598     * , fixing it so that loading a new config
1599     * file does not change it
1600     */
1601    public void fixImage(String location)
1602    {
1603       setImage(location);
1604       imageTextField.setEnabled(false);
1605       imageChooserButton.setEnabled(false);
1606       imagePasteButton.setEnabled(false);
1607       imageFixed = true;
1608 
1609       setDualImageMode(false);
1610       dualImageToggle.setEnabled(false);
1611    }
1612 
1613    public boolean isImageFixed()
1614    {
1615       return imageFixed;
1616    }
1617 
1618    /***
1619     * Some output columns will be required for particular application.  For
1620     * example, Aladin requires X_WORLD, Y_WORLD, shape information (for
1621     * drawing) and the AVO demo needs magnitude information for doing SEDs.  The
1622     * application can set these here, so the user cannot unselect them.
1623     */
1624    public void addObligatoryOutputColumn(String columnName)
1625    {
1626       obligatoryOutputColumns.add(columnName);
1627       selectOutputColumn(columnName);
1628    }
1629 
1630    /***
1631     * Some output columns will be required for particular application.  For
1632     * example, Aladin requires X_WORLD, Y_WORLD, shape information (for
1633     * drawing) and the AVO demo needs magnitude information for doing SEDs.  The
1634     * application can set these here, so the user cannot unselect them.
1635     */
1636    public void setObligatoryOutputColumns(String[] columnNames)
1637    {
1638       obligatoryOutputColumns.clear();
1639       obligatoryOutputColumns.addAll(Arrays.asList(columnNames));
1640       for (int i=0;i<columnNames.length;i++)
1641       {
1642          selectOutputColumn(columnNames[i]);
1643       }
1644    }
1645 
1646    /***
1647     * Some output columns will be required for particular application.  For
1648     * example, Aladin requires X_WORLD, Y_WORLD, shape information (for
1649     * drawing) and the AVO demo needs magnitude information for doing SEDs.  The
1650     * application can set these here, so the user cannot unselect them.
1651     */
1652    public String[] getObligatoryOutputColumns()
1653    {
1654       return (String[]) obligatoryOutputColumns.toArray(new String[] {});
1655 
1656    }
1657 
1658    /***
1659     * Clears the list of selected output columns and sets it to the minimum
1660     * set (ie, the obligatory cols), and sets the list of possible output
1661     * columns to the set of all columns minus the selected ones
1662     */
1663    public void resetListOutputColumns()
1664    {
1665       if ((listOutputColumns != null) && (listOutputColumnsSelected != null))
1666       {
1667          listOutputColumns.getContents().clear();
1668          listOutputColumnsSelected.getContents().clear();
1669 
1670          for (int listLoop = 0; listLoop < obligatoryOutputColumns.size(); listLoop++)
1671          {
1672             listOutputColumnsSelected.getContents().addElement(
1673                obligatoryOutputColumns.elementAt(listLoop)
1674             );
1675          };
1676 
1677          for (int listLoop = 0; listLoop < itemsOutputColumns.length; listLoop++)
1678          {
1679             //if it's not already selected
1680             if (
1681                listOutputColumnsSelected.getContents().indexOf(
1682                   itemsOutputColumns[listLoop]
1683                ) == -1
1684             )
1685             {
1686                listOutputColumns.getContents().addElement(
1687                   itemsOutputColumns[listLoop]
1688                );
1689             };
1690          };
1691       };
1692    }
1693 
1694    /***
1695     * Selects the given output column - ie moves it from the possible list to
1696     * the selected list, if it's not already there
1697     */
1698    public void selectOutputColumn(String columnName)
1699    {
1700       //check the column name exists
1701       if ((listOutputColumns.getContents().indexOf(columnName) == -1)   &&
1702              (listOutputColumnsSelected.getContents().indexOf(columnName) == -1))
1703       {
1704          throw new IllegalArgumentException("Unknown column name '"+columnName+"'");
1705       }
1706       //move if not already moved (we don't want duplicates)
1707       if (listOutputColumns.getContents().indexOf(columnName) != -1)
1708       {
1709          listOutputColumns.getContents().removeElement(columnName);
1710          listOutputColumnsSelected.getContents().addElement(columnName);
1711       }
1712    }
1713 
1714    /***
1715     * Selects the given output column - ie moves it from the possible list to
1716     * the selected list, if it's not already there
1717     */
1718    public void deselectOutputColumn(String columnName)
1719    {
1720       //check the column name exists
1721       if ((listOutputColumns.getContents().indexOf(columnName) == -1)   &&
1722              (listOutputColumnsSelected.getContents().indexOf(columnName) == -1))
1723       {
1724          throw new IllegalArgumentException("Unknown column name '"+columnName+"'");
1725       }
1726       //move if not already moved (we don't want duplicates)
1727       if (listOutputColumns.getContents().indexOf(columnName) == -1)
1728       {
1729          listOutputColumns.getContents().addElement(columnName);
1730          listOutputColumnsSelected.getContents().removeElement(columnName);
1731       }
1732    }
1733 
1734 
1735 
1736    /***
1737     * Reads the image header, updating entry fields if it can
1738     */
1739 
1740    /***
1741     * Called when the (main) image has changed.  Note that due to the way
1742     * events fire, we cannot count on reading the imageTextField entry, as
1743     * this routine might be called before that entry is updated in the list of
1744     * events.  So we pass the new file as a parameter, and make use of this
1745     * routine to set all the correct fields from the image.
1746     */
1747    protected void setImage(String newFile)
1748    {
1749       imageTextField.setText(newFile);
1750 
1751       if (newFile.trim().length() == 0)
1752       {
1753          //JOptionPane.showMessageDialog(this, "No image entered");
1754          //empty - don't do anything.
1755          return;
1756       }
1757 
1758       try
1759       {
1760          FitsImage fitsImage = new FitsImage(newFile);
1761          fitsImage.loadHeader();
1762 
1763          boolean mightBeCCD = false;
1764          boolean mightBePhoto = false;
1765 
1766          //look for EIS filter
1767          String filterValue = fitsImage.getHeaderValue("FILTER");
1768          if ( (filterValue != null) && (filterValue.length() > 0))
1769          {
1770             try
1771             {
1772                Passband filterPassband = (Passband) Passband.getFor(Passband.class, ""+filterValue.charAt(0));
1773 
1774                passbandPanel.eisSingleBandBtn.doClick();
1775 
1776                passbandPanel.eisSingleBandPicker.setSelectedItem(filterPassband);
1777             }
1778             catch (IllegalArgumentException iae)
1779             {
1780                //no passband match for the given string.  Just report
1781                Log.logWarning("Unknown passband specified by FILTER: '"+filterValue+"'");
1782             }
1783 
1784          }
1785          else
1786          {
1787             //no filter value given, so look at given physical unit stuff
1788             passbandPanel.physicalBtn.doClick();
1789 
1790             String freqValue = fitsImage.getHeaderValue("CRVAL3");
1791             if ((freqValue != null) && (freqValue.length() > 0))
1792             {
1793                passbandPanel.obsFreqField.setText(freqValue);
1794             }
1795             String fwhmValue = fitsImage.getHeaderValue("CDELT3");
1796             if ((fwhmValue != null) && (fwhmValue.length() > 0))
1797             {
1798                passbandPanel.filterFwhmField.setText(fwhmValue);
1799             }
1800          }
1801 
1802          //these two checks should really be on 'starts with' or 'contains'...
1803          if (fitsImage.getHeaderValue("CCD") != null)
1804          {
1805             mightBeCCD = true;
1806          }
1807 
1808          if (fitsImage.getHeaderValue("PHOTO") != null)
1809          {
1810             mightBePhoto = true;
1811          }
1812 
1813          //if they're different, one will be true and the other false, so
1814          //we can make a good guess
1815          if (mightBePhoto != mightBeCCD)
1816          {
1817             if (mightBePhoto)
1818             {
1819                radiobuttonDetectTypePHOTO.doClick();
1820 
1821             }
1822             else
1823             {
1824                radiobuttonDetectTypeCCD.doClick();
1825             }
1826          }
1827       }
1828 
1829       catch (FileNotFoundException fnfe)
1830       {
1831          //JOptionPane.showMessageDialog(this, "File '"+imageEntry+"' not found");
1832          Log.logError("Could not find image '"+newFile+"'",fnfe);
1833       }
1834       catch (IOException ioe)
1835       {
1836          //JOptionPane.showMessageDialog(this, "No image entered");
1837          Log.logError("Could not read from image '"+newFile+"'",ioe);
1838       }
1839 
1840 
1841    }
1842 
1843 
1844 
1845 
1846    /***
1847     * Returns text value of given tag
1848     */
1849    protected String getXmlTagValue(Element rootElement, String tagName, int argNum)
1850    {
1851       if (argNum > 0)
1852       {
1853          String [] results = getXmlTagValues(rootElement, tagName);
1854 
1855          if ((results != null) && (results.length >= argNum))
1856          {
1857             return results[argNum - 1];
1858          }
1859       }
1860 
1861       return "";
1862    }
1863 
1864    /***
1865     * Returns (as a String array) all of the FIRST 'text' child Elements
1866     * belonging to all the 'arg' Elements belonging to the
1867     * FIRST matching (tagName) XML Element falling
1868     * within the sub-tree having 'anElement' as its root. (Eh?)
1869     *
1870     * Returns a zero-length array if the element cannot be found or
1871     * if there is an error. (AJWM: NOT a NULL value...???)
1872     *
1873     * Asking for getXmlElementArgs(Element:animals, "monkey") would return:
1874     *    {"1","2","3"}
1875     * When provided with the following XML:
1876     *    <animals>
1877     *      <monkey>
1878     *        <arg>1</arg>
1879     *        <arg>2</arg>
1880     *        <arg>3</arg>
1881     *      </monkey>
1882     *    </animals>
1883     *
1884     * @author Alan Maxwell
1885     */
1886    protected String [] getXmlTagValues(Element rootElement, String tagName)
1887    {
1888       NodeList tempNodeList = null;
1889       Node tempNode = null;
1890 
1891       String [] result = null;
1892 
1893       if (rootElement != null)
1894       {
1895          tempNodeList = rootElement.getElementsByTagName(tagName);
1896 
1897          if (tempNodeList.getLength() > 1)
1898          {
1899             Log.logError("More than one node matches " + tagName+", using first one");
1900          }
1901 
1902          if (tempNodeList.getLength() > 0)
1903          {
1904             tempNode = tempNodeList.item(0);
1905             tempNodeList = ((Element) tempNode).getElementsByTagName("arg");
1906 
1907             // If we found some <arg> sub nodes, process them...
1908             // Otherwise, see if the value has been written directly into the tag...
1909             if (tempNodeList.getLength() > 0)
1910             {
1911                // Got some arg nodes (this is what we hope for)
1912                result = new String[tempNodeList.getLength()];
1913 
1914                for (int argLoop = 0; argLoop < tempNodeList.getLength(); argLoop++ )
1915                {
1916                   result[argLoop] =
1917                      tempNodeList.item(argLoop).getFirstChild().getNodeValue().trim();
1918 
1919                   // AJWM: Should we be protecting against null strings?
1920                   if (result[argLoop] == null)
1921                   {
1922                      result[argLoop] = "";
1923                   };
1924                };
1925 
1926                return result;
1927             }
1928             else
1929             {
1930                // There were NO arg nodes, look for a direct value under main tag
1931                String tempString = tempNode.getFirstChild().getNodeValue().trim();
1932 
1933                if (tempString != null)
1934                {
1935                   result = new String[1];
1936 
1937                   result[0] = tempString;
1938 
1939                   return result;
1940                }
1941             }
1942          }
1943       }
1944 
1945       // If we get here, we haven't found what we want so return empty array...
1946       return new String[] { };
1947    }
1948 
1949    /***
1950     * Returns (as a String array) all of the FIRST 'text' child Elements
1951     * belonging to all the 'arg' Elements belonging to the
1952     * FIRST matching (tagName) XML Element falling
1953     * within the sub-tree having 'anElement' as its root. (Eh?)
1954     *
1955     * Returns null if the element cannot be found or if there is an error.
1956     *
1957     * Asking for getXmlElementArgs(Element:animals, "monkey") would return:
1958     *    {"1","2","3"}
1959     * When provided with the following XML:
1960     *    <animals>
1961     *      <monkey>
1962     *        <arg>1</arg>
1963     *        <arg>2</arg>
1964     *        <arg>3</arg>
1965     *      </monkey>
1966     *    </animals>
1967     *
1968     * @author Alan Maxwell
1969     *
1970     protected String [] getXmlElementArgs(Element anElement, String tagName)
1971     {
1972     NodeList tempNodeList = null;
1973     Node tempNode = null;
1974 
1975     tempNodeList = anElement.getElementsByTagName(tagName);
1976 
1977     if (tempNodeList.getLength() < 1)
1978     {
1979     return null;
1980     };
1981 
1982     // Getting here means we found an element(s) matching the provided tag name,
1983     // so we attempt to get any 'arg' sub elements it might (should) have...
1984 
1985     tempNodeList = ((Element) tempNodeList.item(0)).getElementsByTagName("arg");
1986 
1987     if (tempNodeList.getLength() < 1)
1988     {
1989     return null;
1990     };
1991 
1992     // If it has 1 or more child elements, load them into the returned array..
1993 
1994     String [] result = new String[tempNodeList.getLength()];
1995 
1996     for (int nodeLoop = 0; nodeLoop < tempNodeList.getLength(); nodeLoop++ )
1997     {
1998     result[nodeLoop] =
1999     getXmlElementValueText((Element) tempNodeList.item(nodeLoop));
2000     //          tempNodeList.item(nodeLoop).getFirstChild().getNodeValue();
2001     };
2002 
2003     return result;
2004     };
2005 
2006     /**
2007     * Convenience routine for loading fields.  Loads given text field component
2008     * with text from given tag
2009     */
2010    private void setTextFieldFromTag(JTextField field,
2011                                     Element rootElement,
2012                                     String tagName,
2013                                     int argNum)
2014    {
2015       if (field != null)
2016       {
2017          field.setText(getXmlTagValue(rootElement, tagName, argNum));
2018       }
2019    };
2020 
2021    private void setComboBoxFromTag(JComboBox combo,
2022                                    Element rootElement,
2023                                    String tagName,
2024                                    int argNum)
2025    {
2026       if (combo != null)
2027       {
2028          combo.setSelectedItem(getXmlTagValue(rootElement, tagName, argNum));
2029       }
2030    };
2031 
2032 
2033    private void setCheckBoxFromTag(JCheckBox check,
2034                                    Element rootElement,
2035                                    String tagName,
2036                                    int argNum)
2037    {
2038       if (check != null)
2039       {
2040          check.setSelected(
2041             getXmlTagValue(rootElement, tagName, argNum).equalsIgnoreCase("true")
2042          );
2043 
2044          check.doClick();
2045          check.doClick();
2046       }
2047    };
2048 
2049    public void setDualImageMode(boolean b)
2050    {
2051       dualImageToggle.setSelected(b);
2052       dualImageTextField.setEnabled(b);
2053       dualImageChooserButton.setEnabled(b);
2054       dualImagePasteButton.setEnabled(b);
2055    }
2056 
2057 
2058    /***
2059     * Populates the tabbed pages with values taken from the provided XML File!
2060     *
2061     * @author Alan Maxwell
2062     */
2063    public void loadXmlFile(File xmlFile) throws IOException
2064    {
2065       try
2066       {
2067          DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
2068          //dbf.setIgnoringElementContentWhitespace(true);
2069          dbf.setNamespaceAware(true);
2070          DocumentBuilder builder = dbf.newDocumentBuilder();
2071          Document doc = builder.parse(xmlFile);
2072 
2073          loadXmlDoc(doc);
2074       }
2075       catch (SAXException se)
2076       {
2077          IOException ioe = new IOException("Parsing error: "+se);
2078          //ioe.setStackTrace(e.getStackTrace());  //java v1.4+
2079          ioe.fillInStackTrace(); //java v1.3
2080          throw ioe;
2081       }
2082       catch (ParserConfigurationException pce)
2083       {
2084          IOException ioe = new IOException("Parser error: "+pce);
2085          //ioe.setStackTrace(e.getStackTrace());  //java v1.4+
2086          ioe.fillInStackTrace(); //java v1.3
2087          throw ioe;
2088       }
2089    };
2090 
2091    /***
2092     * Populates the tabbed pages with values taken from the provided XML String!
2093     *
2094     * @author Alan Maxwell
2095     */
2096    public void loadXmlString(String xmlString)
2097    {
2098       try
2099       {
2100          DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
2101          //dbf.setIgnoringElementContentWhitespace(true);
2102          dbf.setNamespaceAware(true);
2103          DocumentBuilder builder = dbf.newDocumentBuilder();
2104          Document doc = builder.parse(new InputSource(new StringReader(xmlString)));
2105 
2106          loadXmlDoc(doc);
2107       }
2108       catch (Exception e)
2109       {
2110          Log.logError("Error parsing string '"+xmlString+"'",e);
2111       }
2112    };
2113 
2114    /***
2115     * Populates the tabbed pages with values taken from the provided XML Document!
2116     *
2117     * @author Alan Maxwell
2118     */
2119    public void loadXmlDoc(Document xmlDoc)
2120    {
2121       Element docRoot = (Element) xmlDoc.getDocumentElement();
2122 
2123       String returnValue = null;
2124       String [] returnValues = null;
2125 
2126       // Go through the XML extracting the config information...
2127 
2128       // Image tab... - don't do if the image has been 'fixed' externally
2129       if (!imageFixed)
2130       {
2131          setImage(getXmlTagValue(docRoot, "ImageToCatalog", 1));
2132 
2133          //check and see if dual image, ie imageToCatalog is different to
2134          //image to measure
2135          if (!getXmlTagValue(docRoot, "ImageToCatalog", 1).equals(getXmlTagValue(docRoot, "ImageToMeasure", 1)))
2136          {
2137             setDualImageMode(true);
2138             setTextFieldFromTag(dualImageTextField, docRoot, "ImageToMeasure", 1);
2139          }
2140          else
2141          {
2142             setDualImageMode(false);
2143          }
2144       }
2145 
2146       returnValue = getXmlTagValue(docRoot, "DETECT_TYPE", 1);
2147       if (returnValue.equalsIgnoreCase("PHOTO"))
2148       {
2149          radiobuttongroupDetectType.setSelected(
2150             radiobuttonDetectTypePHOTO.getModel(), true
2151          );
2152       }
2153       else
2154       {
2155          radiobuttongroupDetectType.setSelected(
2156             radiobuttonDetectTypeCCD.getModel(), true
2157          );
2158       };
2159 
2160       //at some point this will have to be done properly, but at the moment, we just store this info in a special 'for Aladin' tag
2161       passbandPanel.setFromIds(getXmlTagValues(docRoot, "Passband"));
2162 
2163       /*
2164        setComboBoxFromTag(passbandUcdPicker, docRoot, "Wavelength", 1);
2165        **/
2166 
2167       // Extraction tab...
2168       setTextFieldFromTag(textFlagImage, docRoot, "FLAG_IMAGE", 1);
2169       setTextFieldFromTag(integertextDetMinArea, docRoot, "DETECT_MINAREA", 1);
2170       setTextFieldFromTag(doubletextDetThresh1, docRoot, "DETECT_THRESH", 1);
2171       setTextFieldFromTag(doubletextDetThresh2, docRoot, "DETECT_THRESH", 2);
2172       setTextFieldFromTag(doubletextAnalysisThresh1, docRoot, "ANALYSIS_THRESH", 1);
2173       setTextFieldFromTag(doubletextAnalysisThresh2, docRoot, "ANALYSIS_THRESH", 2);
2174       setCheckBoxFromTag(checkApplyFilter, docRoot, "FILTER", 1);
2175       setComboBoxFromTag(textFilterName, docRoot, "FILTER_NAME", 1);
2176       setTextFieldFromTag(integertextDeblendThresh, docRoot, "DEBLEND_NTHRESH", 1);
2177       setTextFieldFromTag(doubletextDeblendMinCont, docRoot, "DEBLEND_MINCONT", 1);
2178       setCheckBoxFromTag(checkCleaning, docRoot, "CLEAN", 1);
2179       setTextFieldFromTag(doubletextCleaning, docRoot, "CLEAN_PARAM", 1);
2180 
2181       returnValue = getXmlTagValue(docRoot, "MASK_TYPE", 1);
2182       if (returnValue.equalsIgnoreCase("CORRECT"))
2183       {
2184          radiobuttongroupMaskType.setSelected(
2185             radiobuttonMaskTypeCORRECT.getModel(), true
2186          );
2187       }
2188       else if (returnValue.equalsIgnoreCase("BLANK"))
2189       {
2190          radiobuttongroupMaskType.setSelected(
2191             radiobuttonMaskTypeBLANK.getModel(), true
2192          );
2193       }
2194       else
2195       {
2196          radiobuttongroupMaskType.setSelected(
2197             radiobuttonMaskTypeNONE.getModel(), true
2198          );
2199       };
2200 
2201       // Photometry tab...
2202       setTextFieldFromTag(inttextPhotApertures, docRoot, "PHOT_APERTURES", 1);
2203       setTextFieldFromTag(doubletextPhotAutoParams1, docRoot, "PHOT_AUTOPARAMS", 1);
2204       setTextFieldFromTag(doubletextPhotAutoParams2, docRoot, "PHOT_AUTOPARAMS", 2);
2205       setTextFieldFromTag(doubletextSatLevel, docRoot, "SATUR_LEVEL", 1);
2206       setTextFieldFromTag(doubletextMagZero, docRoot, "MAG_ZEROPOINT", 1);
2207       setTextFieldFromTag(doubletextMagGamma, docRoot, "MAG_GAMMA", 1);
2208       setTextFieldFromTag(doubletextGain, docRoot, "GAIN", 1);
2209       setTextFieldFromTag(doubletextPixelScale, docRoot, "PIXEL_SCALE", 1);
2210 
2211       // Separation tab...
2212       setTextFieldFromTag(doubletextSeeingFWHM, docRoot, "SEEING_FWHM", 1);
2213       setTextFieldFromTag(textStarNNWName, docRoot, "STARNNW_NAME", 1);
2214 
2215       // Background tab...
2216       setTextFieldFromTag(integertextBackSize1, docRoot, "BACK_SIZE", 1);
2217       setTextFieldFromTag(integertextBackSize2, docRoot, "BACK_SIZE", 2);
2218       setTextFieldFromTag(integertextBackFilter1, docRoot, "BACK_FILTERSIZE", 1);
2219       setTextFieldFromTag(integertextBackFilter2, docRoot, "BACK_FILTERSIZE", 2);
2220 
2221       returnValue = getXmlTagValue(docRoot, "BACKPHOTO_TYPE", 1);
2222       if (returnValue.equalsIgnoreCase("GLOBAL"))
2223       {
2224          radiobuttongroupBackPhotoType.setSelected(
2225             radiobuttonBackPhotoTypeGLOBAL.getModel(), true
2226          );
2227       }
2228       else
2229       {
2230          radiobuttongroupBackPhotoType.setSelected(
2231             radiobuttonBackPhotoTypeLOCAL.getModel(), true
2232          );
2233       };
2234       setTextFieldFromTag(inttextBackPhotoThick, docRoot, "BACKPHOTO_THICK", 1);
2235       // What about "Apply Pixel Flag" checkbox and textfield?
2236 
2237       // Output tab...
2238       setComboBoxFromTag(comboCheckImageType, docRoot, "CHECKIMAGE_TYPE", 1);
2239       resetListOutputColumns();
2240 
2241       returnValues = getXmlTagValues(docRoot, "OUTPUT_COLUMNS");
2242       int [] selections = new int[returnValues.length];
2243 
2244       for (int outputLoop = 0; outputLoop < returnValues.length; outputLoop++)
2245       {
2246          selections[outputLoop] =
2247             listOutputColumns.getContents().indexOf(returnValues[outputLoop]);
2248       };
2249       listOutputColumns.setSelectedIndices(selections);
2250       buttonOutputColumnsADD.doClick();
2251 
2252       // Advanced tab...
2253       setTextFieldFromTag(inttextMemObjStack, docRoot, "MEMORY_OBJSTACK", 1);
2254       setTextFieldFromTag(inttextMemPixStack, docRoot, "MEMORY_PIXSTACK", 1);
2255       setTextFieldFromTag(inttextMemBufSize, docRoot, "MEMORY_BUFSIZE", 1);
2256 
2257       returnValue = getXmlTagValue(docRoot, "VERBOSE_TYPE", 1);
2258       if (returnValue.equalsIgnoreCase("QUIET"))
2259       {
2260          radiobuttongroupVerboseType.setSelected(
2261             radiobuttonVerboseTypeQUIET.getModel(), true
2262          );
2263       }
2264       else if (returnValue.equalsIgnoreCase("FULL"))
2265       {
2266          radiobuttongroupVerboseType.setSelected(
2267             radiobuttonVerboseTypeFULL.getModel(), true
2268          );
2269       }
2270       else
2271       {
2272          radiobuttongroupVerboseType.setSelected(
2273             radiobuttonVerboseTypeNORMAL.getModel(), true
2274          );
2275       };
2276    };
2277 
2278    /***
2279     * Returns all of the tabbed pages' options encoded as an XML String.
2280     *
2281     * @author Alan Maxwell
2282     */
2283    public String toXmlString()
2284    {
2285       StringBuffer xmlResult =
2286          new StringBuffer("<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n\n");
2287 
2288       xmlResult.append(
2289          "<ace:AceInputDoc \n" +
2290             "        xmlns:ace=\"http://www.astrogrid.org/namespace/AceInput-1_0\" \n" +
2291             "        xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" \n" +
2292             "        xsi:schemaLocation=\"http://www.astrogrid.org/namespace/AceInput-1_0 \n" +
2293             "        http://astrogrid.ast.cam.ac.uk/namespace/AceInput-1_0.xsd\"> \n\n"
2294       );
2295 
2296       xmlResult.append(
2297          "<!-- Generated by TemplateEditorPanel --> \n\n"
2298       );
2299 
2300       xmlResult.append(
2301          makeTag("ImageToCatalog", imageTextField.getText())
2302       );
2303 
2304       if (dualImageToggle.isSelected())
2305       {
2306          xmlResult.append(
2307             makeTag("ImageToMeasure", dualImageTextField.getText())
2308          );
2309       }
2310       else
2311       {
2312          xmlResult.append(
2313             makeTag("ImageToMeasure", imageTextField.getText())
2314          );
2315       }
2316 
2317       xmlResult.append(
2318          makeTag(
2319                          "DETECT_TYPE",
2320                          radiobuttongroupDetectType.getSelection().getActionCommand()
2321                       )
2322       );
2323 
2324       //at some point this will have to be done properly, but at the moment, we just store this info in a special 'for Aladin' tag
2325       xmlResult.append(
2326          makeTag("Passband", passbandPanel.getIds())
2327       );
2328 
2329       //botch to help v0.2 server
2330       xmlResult.append(
2331          makeTag("Wavelength", "PHOT_MAG")
2332       );
2333 
2334       /*
2335        xmlResult.append(
2336        makeTag("Wavelength", (String) passbandUcdPicker.getSelectedItem())
2337        );
2338        **/
2339 
2340       xmlResult.append(
2341          makeTag("FLAG_IMAGE", textFlagImage.getText())
2342       );
2343 
2344       xmlResult.append(
2345          makeTag("DETECT_MINAREA", integertextDetMinArea.getText())
2346       );
2347 
2348       xmlResult.append(
2349          makeTag(
2350                          "DETECT_THRESH",
2351                          new String [] {doubletextDetThresh1.getText(), doubletextDetThresh2.getText()}
2352                       )
2353       );
2354 
2355       xmlResult.append(
2356          makeTag(
2357                          "ANALYSIS_THRESH",
2358                          new String [] {doubletextAnalysisThresh1.getText(), doubletextAnalysisThresh2.getText()}
2359                       )
2360       );
2361 
2362       if (checkApplyFilter.isSelected())
2363       {
2364          xmlResult.append(makeTag("FILTER", "true"));
2365       }
2366       else
2367       {
2368          xmlResult.append(makeTag("FILTER", "false"));
2369       };
2370 
2371       xmlResult.append(
2372          makeTag("FILTER_NAME", (String) textFilterName.getSelectedItem())
2373       );
2374 
2375       xmlResult.append(
2376          makeTag("DEBLEND_NTHRESH", integertextDeblendThresh.getText())
2377       );
2378 
2379       xmlResult.append(
2380          makeTag("DEBLEND_MINCONT", doubletextDeblendMinCont.getText())
2381       );
2382 
2383       if (checkCleaning.isSelected())
2384       {
2385          xmlResult.append(makeTag("CLEAN", "true"));
2386       }
2387       else
2388       {
2389          xmlResult.append(makeTag("CLEAN", "false"));
2390       };
2391 
2392       xmlResult.append(
2393          makeTag("CLEAN_PARAM", doubletextCleaning.getText())
2394       );
2395 
2396       xmlResult.append(
2397          makeTag(
2398                          "MASK_TYPE",
2399                          radiobuttongroupMaskType.getSelection().getActionCommand()
2400                       )
2401       );
2402 
2403       xmlResult.append(
2404          makeTag("PHOT_APERTURES", inttextPhotApertures.getText())
2405       );
2406 
2407       xmlResult.append(
2408          makeTag(
2409                          "PHOT_AUTOPARAMS",
2410                          new String [] {doubletextPhotAutoParams1.getText(), doubletextPhotAutoParams2.getText()}
2411                       )
2412       );
2413 
2414       xmlResult.append(
2415          makeTag("SATUR_LEVEL", doubletextSatLevel.getText())
2416       );
2417 
2418       xmlResult.append(
2419          makeTag("MAG_ZEROPOINT", doubletextMagZero.getText())
2420       );
2421 
2422       xmlResult.append(
2423          makeTag("MAG_GAMMA", doubletextMagGamma.getText())
2424       );
2425 
2426       xmlResult.append(
2427          makeTag("GAIN", doubletextGain.getText())
2428       );
2429 
2430       xmlResult.append(
2431          makeTag("PIXEL_SCALE", doubletextPixelScale.getText())
2432       );
2433 
2434       xmlResult.append(
2435          makeTag("SEEING_FWHM", doubletextSeeingFWHM.getText())
2436       );
2437 
2438       xmlResult.append(
2439          makeTag("STARNNW_NAME", textStarNNWName.getText())
2440       );
2441 
2442       xmlResult.append(
2443          makeTag(
2444                          "BACK_SIZE",
2445                          new String [] {integertextBackSize1.getText(), integertextBackSize2.getText()}
2446                       )
2447       );
2448 
2449       xmlResult.append(
2450          makeTag(
2451                          "BACK_FILTERSIZE",
2452                          new String [] {integertextBackFilter1.getText(), integertextBackFilter2.getText()}
2453                       )
2454       );
2455 
2456       xmlResult.append(
2457          makeTag(
2458                          "BACKPHOTO_TYPE",
2459                          radiobuttongroupBackPhotoType.getSelection().getActionCommand()
2460                       )
2461       );
2462 
2463       xmlResult.append(
2464          makeTag("BACKPHOTO_THICK", inttextBackPhotoThick.getText())
2465       );
2466 
2467       xmlResult.append(
2468          makeTag("CHECKIMAGE_TYPE", (String) comboCheckImageType.getSelectedItem())
2469       );
2470 
2471       /*    xmlResult.append(
2472        makeTag("CHECKIMAGE_NAME", textCheckImageName.getText())
2473        );*/
2474 
2475       String[] outputItems =
2476          new String[listOutputColumnsSelected.getContents().size()];
2477 
2478       for (
2479          int itemLoop = 0;
2480          itemLoop < listOutputColumnsSelected.getContents().size();
2481          itemLoop++
2482       )
2483       {
2484          outputItems[itemLoop] = (String)
2485             listOutputColumnsSelected.getContents().getElementAt(itemLoop);
2486       };
2487 
2488       xmlResult.append(
2489          makeTag("OUTPUT_COLUMNS", outputItems)
2490       );
2491 
2492       xmlResult.append(
2493          makeTag("MEMORY_OBJSTACK", inttextMemObjStack.getText())
2494       );
2495 
2496       xmlResult.append(
2497          makeTag("MEMORY_PIXSTACK", inttextMemPixStack.getText())
2498       );
2499 
2500       xmlResult.append(
2501          makeTag("MEMORY_BUFSIZE", inttextMemBufSize.getText())
2502       );
2503 
2504       xmlResult.append(
2505          makeTag(
2506                          "VERBOSE_TYPE",
2507                          radiobuttongroupVerboseType.getSelection().getActionCommand()
2508                       )
2509       );
2510 
2511       xmlResult.append(
2512          "</ace:AceInputDoc> \n\n"
2513       );
2514 
2515       return xmlResult.toString();
2516    };
2517 
2518    /***
2519     * Makes a tag from the given strings
2520     */
2521    private String makeTag(String tag, String value)
2522    {
2523       if ((value != null) && (value.length() >0))
2524       {
2525          return "  <"+tag+"> \n" +
2526             "    <arg>" + XmlOutput.transformSpecials(value) + "</arg> \n" +
2527             "  </"+tag+"> \n\n";
2528       }
2529 
2530       return "";
2531    }
2532 
2533    /***
2534     * makes a tag from the given strings = naughtily overloaded from above
2535     */
2536    private String makeTag(String tag, String[] values)
2537    {
2538       //don't do it if there are no values
2539       if ((values != null)    && (values.length >0) &&
2540              (values[0] != null) && (values[0].length() >0))
2541       {
2542          StringBuffer xml = new StringBuffer();
2543          xml.append("  <"+tag+"> \n");
2544          for (int i=0;i<values.length;i++)
2545          {
2546             if ((values[i] != null) && (values[i].length() > 0))
2547             {
2548                xml.append("    <arg>" + XmlOutput.transformSpecials(values[i]) + "</arg> \n");
2549             }
2550          }
2551          xml.append("  </"+tag+"> \n\n");
2552          return xml.toString();
2553       }
2554 
2555       return "";
2556    }
2557 
2558    /***
2559     * Surrounds an existing set of tags with a new tag
2560     *
2561     private String surroundTags(String parentTag, String[] childTags)
2562     {
2563 
2564     }
2565     */
2566 
2567    /***
2568     * Returns all of the tabbed pages' options encoded as an XML Document.
2569     *
2570     * Returns null if this cannot be done!
2571     *
2572     * @author Alan Maxwell
2573     */
2574    public Document toXmlDocument() throws IOException
2575    {
2576       try
2577       {
2578          String xmlString = toXmlString();
2579 
2580          //validate
2581          Log.trace("Validating entry-generated xml...");
2582          org.astrogrid.xmlutils.XmlValidatorXercesImpl validator = new org.astrogrid.xmlutils.XmlValidatorXercesImpl();
2583          validator.validate(new StringReader(xmlString));
2584          Log.trace("...generated xml valid");
2585 
2586          DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
2587          dbf.setNamespaceAware(true);
2588          DocumentBuilder builder = dbf.newDocumentBuilder();
2589 
2590          return builder.parse(xmlString);
2591       }
2592       catch (SAXException se)
2593       {
2594          IOException ioe = new IOException("XML generated from entered values is invalid: "+se);
2595          //ioe.setStackTrace(e.getStackTrace());  //java v1.4+
2596          ioe.fillInStackTrace(); //java v1.3
2597          throw ioe;
2598       }
2599       catch (ParserConfigurationException pce)
2600       {
2601          IOException ioe = new IOException("Parser error: "+pce);
2602          //ioe.setStackTrace(e.getStackTrace());  //java v1.4+
2603          ioe.fillInStackTrace(); //java v1.3
2604          throw ioe;
2605       }
2606    };
2607 
2608    public void saveXmlFile(File xmlFile)
2609    {
2610       try
2611       {
2612          OutputStream out = new BufferedOutputStream(new FileOutputStream(xmlFile));
2613          out.write(toXmlString().getBytes());
2614       }
2615       catch (IOException ioe)
2616       {
2617          Log.logError("Could not save template to '"+xmlFile+"'",ioe);
2618       }
2619    }
2620 
2621 };
2622 
2623 // Alan Maxwell
2624 //
2625 // Version History
2626 //
2627 // $Log: TemplateEditorPanel.java,v $
2628 // Revision 1.2  2004/01/12 18:44:18  mch
2629 // Removed unnecessary import
2630 //
2631 // Revision 1.1.1.1  2003/08/25 18:36:13  mch
2632 // Reimported to fit It02 source structure
2633 //
2634 // Revision 1.17  2003/07/11 10:43:46  mch
2635 // Fix for examining FITS headers; also better reporting on invalid web config files
2636 //
2637 // Revision 1.16  2003/07/03 18:12:00  mch
2638 // Moved fits header-reading code out to fits.FitsImage
2639 //
2640 // Revision 1.15  2003/06/26 19:14:59  mch
2641 // Passband stuff added
2642 //
2643 // Revision 1.14  2003/06/18 15:56:43  mch
2644 // Dual Image field added
2645 //
2646 // Revision 1.13  2003/01/16 22:20:38  mch
2647 // Fix for double quotes in fits headers
2648 //
2649 // Revision 1.12  2003/01/10 14:17:17  mch
2650 // Removed vectored output columns
2651 //
2652 // Revision 1.11  2002/12/21 12:10:35  mch
2653 // Made compatible with Java 1.3
2654 //
2655 // Revision 1.10  2002/12/18 12:58:19  mch
2656 // Imported from MCHs laptop after Dec AVO Demo meeting in Cambridge
2657 //
2658 // Revision 1.8  2002/12/14 20:18:22  mch
2659 // Fix to run under Java 1.3, fix for special characters
2660 //
2661 // Revision 1.7  2002/12/13 16:36:01  mch
2662 // XML load/store
2663 //
2664 // Revision 1.6  2002/12/12 11:47:17  mch
2665 // Added edit and help button
2666 //
2667 // Revision 1.5  2002/12/09 22:49:47  mch
2668 // UI & XML fixes
2669 //
2670 // Revision 1.4  2002/12/09 18:53:19  mch
2671 // UI changes
2672 //
2673 // Revision 1.3  2002/12/09 10:28:17  mch
2674 // Added keyword
2675 //
2676 // Revision 1.2  2002/12/09 10:27 mch
2677 // Added ImageTab from AceDialog, logging, some XML helper methods.
2678 //
2679 // 0.1.6 : 12 Dec 2002
2680 //       The class now correctly reads in all (known) XML tags, either with
2681 //       or without the <args> sub tag (preferably WITH for correctness and
2682 //       sets the UI accordingly. It correctly outputs the XML too now, with
2683 //       neater helper routines added.
2684 // 0.1.5 : 09 Dec 2002
2685 //       Corrected the writing out of the XML, use 'makeTag()' function to
2686 //       remove lots of the code repetition and make it easier to change
2687 //       the output in future. The code no longer outputs EMPTY tags and
2688 //       all tags enclose their values in sub '<arg>' tags...
2689 // 0.1.4 : 21 Nov 2002
2690 //       Alan Maxwell implemented Martin's recommendations for UI alterations
2691 //       as in e-mail to Alan Maxwell dated 20 November 2002.
2692 // 0.1.3 : 14 Nov 2002
2693 //       Martin Hill changed a fair bit of the functionality, including
2694 //       subclassing from JTabbedPane instead of JPanel... (CVS v1.1)
2695 // 0.1.2 : 11 Nov 2002
2696 //       Added the functionality to LOAD the parameters from and XML
2697 //       file to 'pre-populate' the dialog's selections with default values.
2698 // 0.1.1 : 07 Nov 2002
2699 //       Added the ability to request all the dialog's parameters as
2700 //       a result XML file.
2701 // 0.1.0 : 05 Nov 2002
2702 //       Initial dialog panel version, presents a JPanel with a tabbed
2703 //       type selection of pages with various options.
2704 //
2705 
2706