001/*****************************************************************************
002 * Copyright by The HDF Group.                                               *
003 * Copyright by the Board of Trustees of the University of Illinois.         *
004 * All rights reserved.                                                      *
005 *                                                                           *
006 * This file is part of the HDF Java Products distribution.                  *
007 * The full copyright notice, including terms governing use, modification,   *
008 * and redistribution, is contained in the files COPYING and Copyright.html. *
009 * COPYING can be found at the root of the source code distribution tree.    *
010 * Or, see http://hdfgroup.org/products/hdf-java/doc/Copyright.html.         *
011 * If you do not have access to either file, you may request a copy from     *
012 * help@hdfgroup.org.                                                        *
013 ****************************************************************************/
014
015package hdf.view;
016
017import java.awt.BorderLayout;
018import java.awt.Component;
019import java.awt.Dimension;
020import java.awt.Font;
021import java.awt.GridLayout;
022import java.awt.Insets;
023import java.awt.Toolkit;
024import java.awt.datatransfer.DataFlavor;
025import java.awt.datatransfer.Transferable;
026import java.awt.datatransfer.UnsupportedFlavorException;
027import java.awt.dnd.DnDConstants;
028import java.awt.dnd.DropTarget;
029import java.awt.dnd.DropTargetDragEvent;
030import java.awt.dnd.DropTargetDropEvent;
031import java.awt.dnd.DropTargetEvent;
032import java.awt.dnd.DropTargetListener;
033import java.awt.event.ActionEvent;
034import java.awt.event.ActionListener;
035import java.awt.event.KeyEvent;
036import java.io.BufferedInputStream;
037import java.io.BufferedOutputStream;
038import java.io.File;
039import java.io.FileOutputStream;
040import java.io.IOException;
041import java.lang.reflect.Constructor;
042import java.net.URL;
043import java.util.ArrayList;
044import java.util.Enumeration;
045import java.util.Iterator;
046import java.util.List;
047import java.util.Vector;
048
049import javax.swing.ImageIcon;
050import javax.swing.JButton;
051import javax.swing.JComboBox;
052import javax.swing.JComponent;
053import javax.swing.JDesktopPane;
054import javax.swing.JDialog;
055import javax.swing.JFileChooser;
056import javax.swing.JFrame;
057import javax.swing.JInternalFrame;
058import javax.swing.JMenu;
059import javax.swing.JMenuBar;
060import javax.swing.JMenuItem;
061import javax.swing.JOptionPane;
062import javax.swing.JPanel;
063import javax.swing.JScrollPane;
064import javax.swing.JSplitPane;
065import javax.swing.JTabbedPane;
066import javax.swing.JTextArea;
067import javax.swing.JToolBar;
068import javax.swing.KeyStroke;
069import javax.swing.SwingUtilities;
070import javax.swing.UIDefaults;
071import javax.swing.UIManager;
072import javax.swing.event.ChangeEvent;
073import javax.swing.event.ChangeListener;
074
075import hdf.object.Attribute;
076import hdf.object.CompoundDS;
077import hdf.object.Dataset;
078import hdf.object.Datatype;
079import hdf.object.FileFormat;
080import hdf.object.Group;
081import hdf.object.HObject;
082import hdf.object.ScalarDS;
083
084/**
085 * HDFView is the main class of this HDF visual tool. It is used to layout the
086 * graphical components of the hdfview. The major GUI components of the HDFView
087 * include Menubar, Toolbar, TreeView, ContentView, and MessageArea.
088 * <p>
089 * The HDFView is designed in such a way that it does not have direct access to
090 * the HDF library. All the HDF library access is done through HDF objects.
091 * Therefore, the HDFView package depends on the object package but not the
092 * library package. The source code of the view package (hdf.view) should
093 * be complied with the library package (hdf.hdflib and hdf.hdf5lib).
094 *
095 * @author Peter X. Cao
096 * @version 2.4 9/6/2007
097 */
098
099public class HDFView extends JFrame implements ViewManager, ActionListener, ChangeListener, DropTargetListener {
100    private static final long     serialVersionUID = 2211017444445918998L;
101
102    private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(HDFView.class);
103
104    /** a list of tree view implementation. */
105    private static List<String>   treeViews;
106
107    /** a list of image view implementation. */
108    private static List<String>   imageViews;
109
110    /** a list of tree table implementation. */
111    private static List<?>           tableViews;
112
113    /** a list of Text view implementation. */
114    private static List<String>           textViews;
115
116    /** a list of metadata view implementation. */
117    private static List<?>           metaDataViews;
118
119    /** a list of palette view implementation. */
120    private static List<?>           paletteViews;
121
122    /** a list of help view implementation. */
123    private static List<?>           helpViews;
124
125    private static final String   aboutHDFView     = "HDF Viewer, " + "Version " + ViewProperties.VERSION + "\n"
126            + "For " + System.getProperty("os.name") + "\n\n"
127                                                                   + "Copyright " + '\u00a9' + " 2006-2015 The HDF Group.\n"
128            + "All rights reserved.";
129
130    private static final String   JAVA_COMPILER    = "jdk 1.7";
131
132    /** the directory where the HDFView is installed */
133    private String                rootDir;
134
135    /** the current working directory */
136    private String                currentDir;
137
138    /** the current working file */
139    private String                currentFile;
140
141    /** the view properties */
142    private ViewProperties        props;
143
144    /** the list of most recent files */
145    // private Vector recentFiles;
146
147    /** GUI component: the TreeView */
148    private TreeView              treeView;
149
150    /** The offset when a new dataview is added into the main window. */
151    private int                   frameOffset;
152
153    /** GUI component: the panel which is used to display the data content */
154    private final JDesktopPane    contentPane;
155
156    /** GUI component: the text area for showing status message */
157    private final JTextArea       statusArea;
158
159    /** GUI component: the text area for quick attribute view */
160    private final JTextArea       attributeArea;
161
162    /* create tab pane to display attributes and status information */
163    private final JTabbedPane     infoTabbedPane;
164
165    /** the main menu bar */
166    private JMenuBar              menuBar;
167
168    /** GUI component: a list of current data windwos */
169    private final JMenu           windowMenu;
170
171    /** GUI component: file menu on the menubar */
172    private final JMenu           fileMenu;
173
174    /** the string buffer holding the status message */
175    private final StringBuffer    message;
176
177    /** the string buffer holding the metadata information */
178    private final StringBuffer    metadata;
179
180    private final Toolkit         toolkit;
181
182    /** The list of GUI components related to editing */
183    private final List<?>         editGUIs;
184
185    /** The list of GUI components related to HDF5 */
186    private final List<JMenuItem> h5GUIs;
187
188    /** The list of GUI components related to HDF4 */
189    private final List<JMenuItem> h4GUIs;
190
191    /** to add and display url */
192    @SuppressWarnings("rawtypes")
193    private JComboBox             urlBar;
194
195    private UserOptionsDialog     userOptionDialog;
196
197    private Constructor<?>        ctrSrbFileDialog = null;
198
199    private JDialog               srbFileDialog    = null;
200
201    /**
202     * Constructs the HDFView with a given root directory, where the HDFView is
203     * installed, and opens the given file in the viewer.
204     * <p>
205     *
206     * @param root
207     *            the directory where the HDFView is installed.
208     * @param flist
209     *            a list of files to open.
210     */
211    @SuppressWarnings("unchecked")
212    public HDFView(String root, List<File> flist, int width, int height, int x, int y) {
213        super("HDFView " + ViewProperties.VERSION);
214        this.setName("hdfview");
215        try {
216            UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
217        }
218        catch(Exception e) { System.out.println("Error setting Java LAF: " + e); }
219
220
221        setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
222
223        // set the module class jar files to the class path
224        log.debug("root is {}", root);
225
226        rootDir = root;
227        currentFile = null;
228        frameOffset = 0;
229        userOptionDialog = null;
230        ctrSrbFileDialog = null;
231        toolkit = Toolkit.getDefaultToolkit();
232        ViewProperties.loadIcons();
233        ViewProperties.loadExtClass();
234
235        editGUIs = new Vector<Object>();
236        h4GUIs = new Vector<JMenuItem>();
237        h5GUIs = new Vector<JMenuItem>();
238
239        // load the view properties
240        props = new ViewProperties(rootDir);
241        try {
242            props.load();
243        }
244        catch (Exception ex) {
245            log.debug("failed to load ViewProperties from {}", rootDir);
246        }
247
248        // recentFiles = ViewProperties.getMRF();
249        currentDir = ViewProperties.getWorkDir();
250        if (currentDir == null) {
251            currentDir = System.getProperty("user.home");
252        }
253        log.info("CurrentDir is {}", currentDir);
254
255        treeViews = ViewProperties.getTreeViewList();
256        metaDataViews = ViewProperties.getMetaDataViewList();
257        textViews = ViewProperties.getTextViewList();
258        tableViews = ViewProperties.getTableViewList();
259        imageViews = ViewProperties.getImageViewList();
260        paletteViews = ViewProperties.getPaletteViewList();
261        helpViews = ViewProperties.getHelpViewList();
262
263        // initialize GUI components
264        statusArea = new JTextArea();
265        statusArea.setEditable(false);
266        statusArea.setBackground(new java.awt.Color(240, 240, 240));
267        statusArea.setLineWrap(true);
268        statusArea.setName("status");
269        message = new StringBuffer();
270        metadata = new StringBuffer();
271        showStatus("HDFView root - " + rootDir);
272        showStatus("User property file - " + ViewProperties.getPropertyFile());
273
274        attributeArea = new JTextArea();
275        attributeArea.setEditable(false);
276        attributeArea.setBackground(new java.awt.Color(240, 240, 240));
277        attributeArea.setLineWrap(true);
278        attributeArea.setName("attributes");
279
280        // create tab pane to display attributes and status information
281        infoTabbedPane = new JTabbedPane(JTabbedPane.BOTTOM);
282        infoTabbedPane.addChangeListener(this);
283        infoTabbedPane.setName("tabpane");
284
285        contentPane = new JDesktopPane();
286        contentPane.setName("contentpane");
287        windowMenu = new JMenu("Window");
288        windowMenu.setName("windowmenu");
289        fileMenu = new JMenu("File");
290        fileMenu.setName("filemenu");
291
292        int n = treeViews.size();
293        Class<?> theClass = null;
294        for (int i = 0; i < n; i++) {
295            // use the first available treeview
296            String className = treeViews.get(i);
297            // enables use of JHDF5 in JNLP (Web Start) applications, the system
298            // class loader with reflection first.
299            try {
300                theClass = Class.forName(className);
301            }
302            catch (Exception ex) {
303                try {
304                    theClass = ViewProperties.loadExtClass().loadClass(className);
305                }
306                catch (Exception ex2) {
307                    theClass = null;
308                }
309            }
310
311            if (theClass != null) break;
312        }
313
314        if (theClass != null) {
315            try {
316                @SuppressWarnings("rawtypes")
317                Class[] paramClass = { Class.forName("hdf.view.ViewManager") };
318                Constructor<?> constructor = theClass.getConstructor(paramClass);
319                Object[] paramObj = { this };
320                treeView = (TreeView) constructor.newInstance(paramObj);
321            }
322            catch (Exception ex) {
323                treeView = null;
324            }
325        }
326
327        // could not load user's treeview, use default treeview.
328        if (treeView == null) treeView = new DefaultTreeView(this);
329
330        createMainWindow(width, height, x, y);
331
332        try {
333            java.awt.Font font = null;
334            String ftype = ViewProperties.getFontType();
335            int fsize = ViewProperties.getFontSize();
336            try {
337                font = new java.awt.Font(ftype, java.awt.Font.PLAIN, fsize);
338            }
339            catch (Exception ex) {
340                font = null;
341            }
342            if (font != null) {
343                updateFontSize(font);
344            }
345        }
346        catch (Exception ex) {
347            log.debug("Failed to load Font properties");
348        }
349
350        // need to call pack() before open any file so that
351        // all GUI components will be in place.
352        pack();
353
354        /* add support for drag and drop file */
355        new DropTarget(this, this);
356
357        int nfiles = flist.size();
358
359        log.trace("flist.size() = {}", nfiles);
360        File theFile = null;
361        for (int i = 0; i < nfiles; i++) {
362            theFile = flist.get(i);
363            log.trace("flist[{}] = {}", i, theFile.toString());
364
365            if (theFile.isFile()) {
366                currentDir = theFile.getParentFile().getAbsolutePath();
367                log.trace("file dir is {}", currentFile);
368                currentFile = theFile.getAbsolutePath();
369                log.trace("file is {}", currentFile);
370
371                try {
372                    treeView.openFile(currentFile, FileFormat.WRITE);
373                    try {
374                        urlBar.removeItem(currentFile);
375                        urlBar.insertItemAt(currentFile, 0);
376                        urlBar.setSelectedIndex(0);
377                    }
378                    catch (Exception ex2) {
379                        log.info("Failed to update urlBar with {}", currentFile);
380                    }
381                }
382                catch (Exception ex) {
383                    showStatus(ex.toString());
384                }
385            }
386            else {
387                currentDir = theFile.getAbsolutePath();
388            }
389            log.info("CurrentDir is {}", currentDir);
390        }
391
392        if (FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF4) == null) {
393            setEnabled(h4GUIs, false);
394        }
395
396        if (FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF5) == null) {
397            setEnabled(h5GUIs, false);
398        }
399
400    }
401
402    /**
403     * Set default UI fonts.
404     */
405    private void updateFontSize(Font font) {
406        if (font == null) {
407            return;
408        }
409
410        UIDefaults defaults = UIManager.getLookAndFeelDefaults();
411
412        for (Iterator<?> i = defaults.keySet().iterator(); i.hasNext();) {
413            Object key = i.next();
414            if (defaults.getFont(key) != null) {
415                UIManager.put(key, new javax.swing.plaf.FontUIResource(font));
416            }
417        }
418        SwingUtilities.updateComponentTreeUI(this);
419    }
420
421    /**
422     * Creates and lays out GUI compoents.
423     *
424     * <pre>
425     * ||=========||=============================||
426     * ||         ||                             ||
427     * ||         ||                             ||
428     * || TreeView||       ContentPane           ||
429     * ||         ||                             ||
430     * ||=========||=============================||
431     * ||            Message Area                ||
432     * ||========================================||
433     * </pre>
434     */
435    @SuppressWarnings({ "unchecked", "rawtypes" })
436    private void createMainWindow(int width, int height, int x, int y) {
437        // create splitpane to separate treeview and the contentpane
438        JScrollPane treeScroller = new JScrollPane((Component) treeView);
439        treeScroller.setName("treescroller");
440        JScrollPane contentScroller = new JScrollPane(contentPane);
441        contentScroller.setName("contentscroller");
442        JSplitPane topSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, treeScroller, contentScroller);
443        topSplitPane.setDividerLocation(200);
444        topSplitPane.setName("topsplitpane");
445
446        infoTabbedPane.addTab("Log Info", new JScrollPane(statusArea));
447        infoTabbedPane.addTab("Metadata ", new JScrollPane(attributeArea));
448        infoTabbedPane.setSelectedIndex(1);
449
450        // create splitpane to separate message area and treeview-contentpane
451        topSplitPane.setBorder(null); // refer to Java bug #4131528
452        JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, topSplitPane, infoTabbedPane);
453        splitPane.setName("splitpane");
454
455        // set the window size
456        // float inset = 0.17f; // for UG only.
457        float inset = 0.04f;
458        Dimension d = toolkit.getScreenSize();
459
460        if (height > 300) {
461            d.height = height;
462        }
463        else {
464            d.height = (int) ((1 - 2 * inset) * d.height);
465        }
466
467        if (width > 300) {
468            d.width = width;
469        }
470        else {
471            d.width = (int) (0.9 * (double) d.height);
472        }
473
474        // TEST
475        if (treeView.getClass().getName().startsWith("ext.erdc")) {
476            topSplitPane.setDividerLocation(500);
477            d.width = (int) (0.9 * toolkit.getScreenSize().width);
478            d.height = (int) (d.width * 0.618);
479        }
480
481        splitPane.setDividerLocation(d.height - 180);
482        this.setLocation(x, y);
483
484        try {
485            this.setIconImage(((ImageIcon) ViewProperties.getHdfIcon()).getImage());
486        }
487        catch (Exception ex) {
488            log.debug("Failed to getImage");
489        }
490
491        this.setJMenuBar(menuBar = createMenuBar());
492        JToolBar toolBar = createToolBar();
493
494        /** create URL address bar */
495        urlBar = new JComboBox(ViewProperties.getMRF());
496        urlBar.setMaximumRowCount(ViewProperties.MAX_RECENT_FILES);
497        urlBar.setEditable(true);
498        urlBar.addActionListener(this);
499        urlBar.setActionCommand("Open file: from file bar");
500        urlBar.setSelectedIndex(-1);
501
502        JPanel urlPane = new JPanel();
503        urlPane.setLayout(new BorderLayout());
504        urlPane.setName("urlpane");
505
506        JButton b = new JButton("Clear Text");
507        b.setActionCommand("Clear current selection");
508        b.setToolTipText("Clear current selection");
509        b.setMargin(new Insets(1, 3, 1, 3));
510        b.addActionListener(this);
511        urlPane.add(b, BorderLayout.EAST);
512
513        b = new JButton("Recent Files");
514        b.addActionListener(this);
515        b.setActionCommand("Popup URL list");
516        b.setToolTipText("List of recent files");
517        b.setMargin(new Insets(1, 3, 1, 3));
518        urlPane.add(b, BorderLayout.WEST);
519
520        urlPane.add(urlBar, BorderLayout.CENTER);
521        JPanel toolPane = new JPanel();
522        toolPane.setLayout(new GridLayout(2, 1, 0, 0));
523        toolPane.add(toolBar);
524        toolPane.add(urlPane);
525        toolPane.setName("toolpane");
526
527        JPanel mainPane = (JPanel) getContentPane();
528        mainPane.setLayout(new BorderLayout());
529        mainPane.add(toolPane, BorderLayout.NORTH);
530        mainPane.add(splitPane, BorderLayout.CENTER);
531        mainPane.setPreferredSize(d);
532        mainPane.setName("mainpane");
533
534        log.info("MainWindow created");
535    }
536
537    private JMenuBar createMenuBar() {
538        JMenuBar mbar = new JMenuBar();
539        mbar.setName("mbar");
540        JMenu menu = null;
541        JMenuItem item;
542
543        // add file menu
544        fileMenu.setMnemonic('f');
545        mbar.add(fileMenu);
546
547        item = new JMenuItem("Open");
548        item.setMnemonic(KeyEvent.VK_O);
549        item.addActionListener(this);
550        item.setActionCommand("Open file");
551        item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(), true));
552        fileMenu.add(item);
553
554        item = new JMenuItem("Open Read-Only");
555        item.setMnemonic(KeyEvent.VK_R);
556        item.addActionListener(this);
557        item.setActionCommand("Open file read-only");
558        if (!ViewProperties.isReadOnly()) fileMenu.add(item);
559
560        // boolean isSrbSupported = true;
561        // try {
562        // Class.forName("hdf.srb.H5SRB");
563        // Class.forName("hdf.srb.SRBFileDialog");
564        // } catch (Throwable ex) {isSrbSupported = false;}
565        //
566        // if (isSrbSupported) {
567        // item = new JMenuItem( "Open from iRODS");
568        // item.setMnemonic(KeyEvent.VK_S);
569        // item.addActionListener(this);
570        // item.setActionCommand("Open from irods");
571        // fileMenu.add(item);
572        // }
573
574        fileMenu.addSeparator();
575
576        JMenu newFileMenu = new JMenu("New");
577        item = new JMenuItem("HDF4");
578        item.setActionCommand("New HDF4 file");
579        item.setMnemonic(KeyEvent.VK_4);
580        item.addActionListener(this);
581        h4GUIs.add(item);
582        newFileMenu.add(item);
583        item = new JMenuItem("HDF5");
584        item.setActionCommand("New HDF5 file");
585        item.setMnemonic(KeyEvent.VK_5);
586        item.addActionListener(this);
587        h5GUIs.add(item);
588        newFileMenu.add(item);
589        fileMenu.add(newFileMenu);
590
591        fileMenu.addSeparator();
592
593        item = new JMenuItem("Close");
594        item.setMnemonic(KeyEvent.VK_C);
595        item.addActionListener(this);
596        item.setActionCommand("Close file");
597        fileMenu.add(item);
598
599        item = new JMenuItem("Close All");
600        item.setMnemonic(KeyEvent.VK_A);
601        item.addActionListener(this);
602        item.setActionCommand("Close all file");
603        fileMenu.add(item);
604
605        fileMenu.addSeparator();
606
607        item = new JMenuItem("Save");
608        item.setMnemonic(KeyEvent.VK_S);
609        item.addActionListener(this);
610        item.setActionCommand("Save current file");
611        fileMenu.add(item);
612
613        item = new JMenuItem("Save As");
614        item.setMnemonic(KeyEvent.VK_A);
615        item.addActionListener(this);
616        item.setActionCommand("Save current file as");
617        fileMenu.add(item);
618
619        fileMenu.addSeparator();
620
621        item = new JMenuItem("Exit");
622        item.setMnemonic(KeyEvent.VK_X);
623        item.addActionListener(this);
624        item.setActionCommand("Exit");
625        item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(), true));
626        fileMenu.add(item);
627
628        fileMenu.addSeparator();
629
630        // add window menu
631        windowMenu.setMnemonic('w');
632        mbar.add(windowMenu);
633
634        item = new JMenuItem("Cascade");
635        item.setMnemonic(KeyEvent.VK_C);
636        item.setActionCommand("Cascade all windows");
637        item.addActionListener(this);
638        windowMenu.add(item);
639
640        item = new JMenuItem("Tile");
641        item.setMnemonic(KeyEvent.VK_T);
642        item.setActionCommand("Tile all windows");
643        item.addActionListener(this);
644        windowMenu.add(item);
645
646        windowMenu.addSeparator();
647
648        item = new JMenuItem("Close Window");
649        item.setMnemonic(KeyEvent.VK_W);
650        item.setActionCommand("Close a window");
651        item.addActionListener(this);
652        windowMenu.add(item);
653
654        item = new JMenuItem("Close All");
655        item.setMnemonic(KeyEvent.VK_A);
656        item.setActionCommand("Close all windows");
657        item.addActionListener(this);
658        windowMenu.add(item);
659
660        windowMenu.addSeparator();
661
662        // add tool menu
663        menu = new JMenu("Tools");
664        menu.setMnemonic('T');
665        mbar.add(menu);
666
667        JMenu imageSubmenu = new JMenu("Convert Image To");
668        item = new JMenuItem("HDF4");
669        item.setActionCommand("Convert image file: Image to HDF4");
670        item.addActionListener(this);
671        h4GUIs.add(item);
672        imageSubmenu.add(item);
673        item = new JMenuItem("HDF5");
674        item.setActionCommand("Convert image file: Image to HDF5");
675        item.addActionListener(this);
676        h5GUIs.add(item);
677        imageSubmenu.add(item);
678        menu.add(imageSubmenu);
679
680        menu.addSeparator();
681
682        item = new JMenuItem("User Options");
683        item.setMnemonic(KeyEvent.VK_O);
684        item.setActionCommand("User options");
685        item.addActionListener(this);
686        menu.add(item);
687
688        menu.addSeparator();
689
690        item = new JMenuItem("Register File Format");
691        item.setMnemonic(KeyEvent.VK_R);
692        item.setActionCommand("Register file format");
693        item.addActionListener(this);
694        menu.add(item);
695
696        item = new JMenuItem("Unregister File Format");
697        item.setMnemonic(KeyEvent.VK_U);
698        item.setActionCommand("Unregister file format");
699        item.addActionListener(this);
700        menu.add(item);
701
702        // add help menu
703        menu = new JMenu("Help");
704        menu.setMnemonic('H');
705        mbar.add(menu);
706
707        item = new JMenuItem("User's Guide");
708        item.setMnemonic(KeyEvent.VK_U);
709        item.setActionCommand("Users guide");
710        item.addActionListener(this);
711        menu.add(item);
712
713        menu.addSeparator();
714
715        if ((helpViews != null) && (helpViews.size() > 0)) {
716            int n = helpViews.size();
717            for (int i = 0; i < n; i++) {
718                HelpView theView = (HelpView) helpViews.get(i);
719                item = new JMenuItem(theView.getLabel());
720                item.setActionCommand(theView.getActionCommand());
721                item.addActionListener(this);
722                menu.add(item);
723            }
724            menu.addSeparator();
725        }
726
727        item = new JMenuItem("HDF4 Library Version");
728        item.setMnemonic(KeyEvent.VK_4);
729        item.setActionCommand("HDF4 library");
730        item.addActionListener(this);
731        h4GUIs.add(item);
732        menu.add(item);
733
734        item = new JMenuItem("HDF5 Library Version");
735        item.setMnemonic(KeyEvent.VK_5);
736        item.setActionCommand("HDF5 library");
737        item.addActionListener(this);
738        h5GUIs.add(item);
739        menu.add(item);
740
741        item = new JMenuItem("Java Version");
742        item.setMnemonic(KeyEvent.VK_5);
743        item.setActionCommand("Java version");
744        item.addActionListener(this);
745        menu.add(item);
746
747        menu.addSeparator();
748
749        item = new JMenuItem("Supported File Formats");
750        item.setMnemonic(KeyEvent.VK_L);
751        item.setActionCommand("File format list");
752        item.addActionListener(this);
753        menu.add(item);
754
755        menu.addSeparator();
756
757        item = new JMenuItem("About...");
758        item.setMnemonic(KeyEvent.VK_A);
759        item.setActionCommand("About");
760        item.addActionListener(this);
761        menu.add(item);
762
763        log.info("MenuBar created");
764        return mbar;
765    }
766
767    private JToolBar createToolBar() {
768        JToolBar tbar = new JToolBar();
769        tbar.setFloatable(false);
770        tbar.setName("tbar");
771
772        // open file button
773        JButton button = new JButton(ViewProperties.getFileopenIcon());
774        tbar.add(button);
775        button.setName("Open");
776        button.setToolTipText("Open");
777        button.addActionListener(this);
778        button.setActionCommand("Open file");
779
780        // close file button
781        button = new JButton(ViewProperties.getFilecloseIcon());
782        tbar.add(button);
783        button.setName("Close");
784        button.setToolTipText("Close");
785        button.addActionListener(this);
786        button.setActionCommand("Close file");
787
788        tbar.addSeparator(new Dimension(20, 20));
789
790        // help button
791        button = new JButton(ViewProperties.getHelpIcon());
792        tbar.add(button);
793        button.setName("Help");
794        button.setToolTipText("Help");
795        button.addActionListener(this);
796        button.setActionCommand("Users guide");
797
798        // HDF4 Library Version button
799        button = new JButton(ViewProperties.getH4Icon());
800        tbar.add(button);
801        button.setName("HDF4 library");
802        button.setToolTipText("HDF4 Library Version");
803        button.addActionListener(this);
804        button.setActionCommand("HDF4 library");
805        if (FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF4) == null) {
806            button.setEnabled(false);
807        }
808
809        // HDF5 Library Version button
810        button = new JButton(ViewProperties.getH5Icon());
811        tbar.add(button);
812        button.setName("HDF5 library");
813        button.setToolTipText("HDF5 Library Version");
814        button.addActionListener(this);
815        button.setActionCommand("HDF5 library");
816        if (FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF5) == null) {
817            button.setEnabled(false);
818        }
819
820        log.info("ToolBar created");
821        return tbar;
822    }
823
824    /**
825     * Bring the window to the front.
826     * <p>
827     *
828     * @param name
829     *            the name of the window to show.
830     */
831    private void showWindow(String name) {
832        int n = contentPane.getComponentCount();
833        if (n <= 0) {
834            return;
835        }
836
837        Component comp = null;
838        JInternalFrame jif = null;
839        for (int i = 0; i < n; i++) {
840            comp = contentPane.getComponent(i);
841            if (!(comp instanceof JInternalFrame)) continue;
842
843            jif = (JInternalFrame) contentPane.getComponent(i);
844
845            if (jif.getName().equals(name)) {
846                jif.toFront();
847                return;
848            }
849        }
850    }
851
852    /** Cascade all windows. */
853    private void cascadeWindow() {
854        int y = 2, x = 2;
855        JInternalFrame jif = null;
856        Component[] clist = contentPane.getComponents();
857
858        if ((clist == null) || (clist.length <= 0)) {
859            return;
860        }
861
862        Dimension d = contentPane.getSize();
863        int w = Math.max(50, d.width - 100);
864        int h = Math.max(50, d.height - 100);
865
866        for (int i = 0; i < clist.length; i++) {
867            jif = (JInternalFrame) clist[i];
868            jif.setBounds(x, y, w, h);
869            contentPane.moveToFront(jif);
870            x += 20;
871            y += 20;
872        }
873    }
874
875    /** Tile all windows. */
876    private void tileWindow() {
877        int y = 0, x = 0, idx = 0;
878        JInternalFrame jif = null;
879        Component[] clist = contentPane.getComponents();
880
881        if ((clist == null) || (clist.length <= 0)) {
882            return;
883        }
884
885        int n = clist.length;
886        int cols = (int) Math.sqrt(n);
887        int rows = (int) Math.ceil((double) n / (double) cols);
888
889        Dimension d = contentPane.getSize();
890        int w = d.width / cols;
891        int h = d.height / rows;
892
893        for (int i = 0; i < rows; i++) {
894            x = 0;
895            for (int j = 0; j < cols; j++) {
896                idx = i * cols + j;
897                if (idx >= n) {
898                    return;
899                }
900
901                jif = (JInternalFrame) clist[idx];
902                jif.setBounds(x, y, w, h);
903                x += w;
904            }
905            y += h;
906        }
907    }
908
909    /** Closes all windows. */
910    private void closeAllWindow() {
911        JInternalFrame jif = null;
912        Component[] clist = contentPane.getComponents();
913
914        if ((clist == null) || (clist.length <= 0)) {
915            return;
916        }
917
918        for (int i = 0; i < clist.length; i++) {
919            jif = (JInternalFrame) clist[i];
920            jif.dispose();
921            jif = null;
922        }
923    }
924
925    /** disable/enable GUI components */
926    private static void setEnabled(List<JMenuItem> list, boolean b) {
927        Component item = null;
928        Iterator<JMenuItem> it = list.iterator();
929        while (it.hasNext()) {
930            item = it.next();
931            item.setEnabled(b);
932        }
933    }
934
935    // To do: Implementing java.io.ActionListener
936    @SuppressWarnings("unchecked")
937    public void actionPerformed(ActionEvent e) {
938        String cmd = e.getActionCommand();
939
940        if (cmd.equals("Exit")) {
941            dispose(); // terminate the application
942        }
943        else if (cmd.startsWith("Open file")) {
944            int fileAccessID = FileFormat.WRITE;
945            String filename = null;
946
947            if (ViewProperties.isReadOnly()) fileAccessID = FileFormat.READ;
948
949            if (cmd.equals("Open file: from file bar")) {
950                filename = (String) urlBar.getSelectedItem();
951                if (filename == null || filename.length() < 1) {
952                    return;
953                }
954
955                // local file
956                if (!(filename.startsWith("http://") || filename.startsWith("ftp://"))) {
957                    File tmpFile = new File(filename);
958
959                    if (!tmpFile.exists()) return;
960
961                    if (tmpFile.isDirectory()) {
962                        currentDir = filename;
963                        filename = openLocalFile();
964                    }
965                }
966            }
967            else if (cmd.equals("Open file read-only")) {
968                fileAccessID = FileFormat.READ;
969                filename = openLocalFile();
970            }
971            else if (cmd.startsWith("Open file://")) {
972                filename = cmd.substring(12);
973            }
974            else {
975                filename = openLocalFile();
976            }
977
978            if (filename == null) {
979                return;
980            }
981
982            if (filename.startsWith("http://") || filename.startsWith("ftp://")) {
983                filename = openRemoteFile(filename);
984            }
985
986            if ((filename == null) || (filename.length() < 1) || filename.equals(currentFile)) {
987                return;
988            }
989
990            currentFile = filename;
991            try {
992                urlBar.removeItem(filename);
993                urlBar.insertItemAt(filename, 0);
994                urlBar.setSelectedIndex(0);
995            }
996            catch (Exception ex) {
997            }
998
999            try {
1000                treeView.openFile(filename, fileAccessID + FileFormat.OPEN_NEW);
1001            }
1002            catch (Throwable ex) {
1003                try {
1004                    treeView.openFile(filename, FileFormat.READ);
1005                }
1006                catch (Throwable ex2) {
1007                    String msg = "Failed to open file " + filename + "\n" + ex2;
1008                    toolkit.beep();
1009                    currentFile = null;
1010                    urlBar.setSelectedIndex(-1);
1011                    JOptionPane.showMessageDialog(this, msg, getTitle(), JOptionPane.ERROR_MESSAGE);
1012                }
1013            }
1014        }
1015        else if (cmd.equals("Open from irods")) {
1016            try {
1017                openFromSRB();
1018            }
1019            catch (Exception ex) {
1020                toolkit.beep();
1021                JOptionPane.showMessageDialog(this, ex, getTitle(), JOptionPane.ERROR_MESSAGE);
1022            }
1023        }
1024        else if (cmd.startsWith("New HDF")) {
1025            String ftype = FileFormat.FILE_TYPE_HDF5;
1026            if (cmd.equals("New HDF4 file")) {
1027                ftype = FileFormat.FILE_TYPE_HDF4;
1028            }
1029
1030            NewFileDialog dialog = new NewFileDialog(this, currentDir, ftype, treeView.getCurrentFiles());
1031            dialog.setName("newfiledialog");
1032            // dialog.show();
1033
1034            if (!dialog.isFileCreated()) {
1035                return;
1036            }
1037            String filename = dialog.getFile();
1038            if (filename == null) {
1039                return;
1040            }
1041
1042            try {
1043                treeView.openFile(filename, FileFormat.WRITE);
1044                currentFile = filename;
1045                try {
1046                    urlBar.removeItem(filename);
1047                    urlBar.insertItemAt(filename, 0);
1048                    urlBar.setSelectedIndex(0);
1049                }
1050                catch (Exception ex2) {
1051                }
1052            }
1053            catch (Exception ex) {
1054                toolkit.beep();
1055                JOptionPane.showMessageDialog(this, ex.getMessage() + "\n" + filename, getTitle(),
1056                        JOptionPane.ERROR_MESSAGE);
1057            }
1058        }
1059        else if (cmd.equals("Close file")) {
1060            closeFile(treeView.getSelectedFile());
1061        }
1062        else if (cmd.equals("Close all file")) {
1063            closeAllWindow();
1064            List<FileFormat> files = treeView.getCurrentFiles();
1065
1066            while (!files.isEmpty()) {
1067                try {
1068                    treeView.closeFile(files.get(0));
1069                }
1070                catch (Exception ex) {
1071                }
1072            }
1073            currentFile = null;
1074
1075            attributeArea.setText("");
1076        }
1077
1078        else if (cmd.equals("Reload file")) {
1079            reloadFile();
1080        }
1081        else if (cmd.equals("Save current file as")) {
1082            try {
1083                treeView.saveFile(treeView.getSelectedFile());
1084            }
1085            catch (Exception ex) {
1086                toolkit.beep();
1087                JOptionPane.showMessageDialog(this, ex, getTitle(), JOptionPane.ERROR_MESSAGE);
1088            }
1089        }
1090        else if (cmd.equals("Save current file")) {
1091            /* save what have been changed in memory into file */
1092            try {
1093                FileFormat file = treeView.getSelectedFile();
1094                List<JInternalFrame> views = getDataViews();
1095                Object theView = null;
1096                TableView tableView = null;
1097                TextView textView = null;
1098                FileFormat theFile = null;
1099                if (views != null) {
1100                    int n = views.size();
1101                    for (int i = 0; i < n; i++) {
1102                        theView = views.get(i);
1103                        if (theView instanceof TableView) {
1104                            tableView = (TableView) theView;
1105                            theFile = tableView.getDataObject().getFileFormat();
1106                            if (file.equals(theFile)) {
1107                                tableView.updateValueInFile();
1108                            }
1109                        }
1110                        else if (theView instanceof TextView) {
1111                            textView = (TextView) theView;
1112                            theFile = textView.getDataObject().getFileFormat();
1113                            if (file.equals(theFile)) {
1114                                textView.updateValueInFile();
1115                            }
1116                        }
1117                    } // for (int i=0; i<n; i++)
1118                } // if (views != null)
1119            }
1120            catch (Exception ex) {
1121                toolkit.beep();
1122                JOptionPane.showMessageDialog(this, ex, getTitle(), JOptionPane.ERROR_MESSAGE);
1123            }
1124        }
1125        else if (cmd.equals("Cascade all windows")) {
1126            cascadeWindow();
1127        }
1128        else if (cmd.equals("Tile all windows")) {
1129            tileWindow();
1130        }
1131        else if (cmd.equals("Close a window")) {
1132            JInternalFrame frame = contentPane.getSelectedFrame();
1133
1134            if (frame != null) {
1135                frame.dispose();
1136            }
1137        }
1138        else if (cmd.equals("Close all windows")) {
1139            closeAllWindow();
1140        }
1141        else if (cmd.startsWith("SHOW WINDOW")) {
1142            // a window is selected to be shown at the front
1143            showWindow(cmd);
1144        }
1145        else if (cmd.startsWith("Convert image file:")) {
1146            String typeFrom = null, typeTo = null;
1147
1148            if (cmd.equals("Convert image file: Image to HDF5")) {
1149                typeFrom = Tools.FILE_TYPE_IMAGE;
1150                typeTo = FileFormat.FILE_TYPE_HDF5;
1151            }
1152            else if (cmd.equals("Convert image file: Image to HDF4")) {
1153                typeFrom = Tools.FILE_TYPE_IMAGE;
1154                typeTo = FileFormat.FILE_TYPE_HDF4;
1155            }
1156            else {
1157                return;
1158            }
1159
1160            FileConversionDialog dialog = new FileConversionDialog(this, typeFrom, typeTo, currentDir,
1161                    treeView.getCurrentFiles());
1162            dialog.setVisible(true);
1163
1164            if (dialog.isFileConverted()) {
1165                String filename = dialog.getConvertedFile();
1166                File theFile = new File(filename);
1167
1168                if (!theFile.exists() || !theFile.exists()) {
1169                    return;
1170                }
1171
1172                currentDir = theFile.getParentFile().getAbsolutePath();
1173                currentFile = theFile.getAbsolutePath();
1174
1175                try {
1176                    treeView.openFile(filename, FileFormat.WRITE);
1177                    try {
1178                        urlBar.removeItem(filename);
1179                        urlBar.insertItemAt(filename, 0);
1180                        urlBar.setSelectedIndex(0);
1181                    }
1182                    catch (Exception ex2) {
1183                    }
1184                }
1185                catch (Exception ex) {
1186                    showStatus(ex.toString());
1187                }
1188            }
1189        }
1190        else if (cmd.equals("User options")) {
1191            if (userOptionDialog == null) {
1192                userOptionDialog = new UserOptionsDialog(this, rootDir);
1193            }
1194
1195            userOptionDialog.setVisible(true);
1196
1197            if (userOptionDialog.isWorkDirChanged()) {
1198                currentDir = ViewProperties.getWorkDir();
1199            }
1200
1201            if (userOptionDialog.isFontChanged()) {
1202                Font font = null;
1203                try {
1204                    font = new Font(ViewProperties.getFontType(), Font.PLAIN, ViewProperties.getFontSize());
1205                }
1206                catch (Exception ex) {
1207                    font = null;
1208                }
1209
1210                if (font != null) {
1211                    updateFontSize(font);
1212                }
1213            }
1214        }
1215        else if (cmd.equals("Register file format")) {
1216            String msg = "Register a new file format by \nKEY:FILE_FORMAT:FILE_EXTENSION\n"
1217                    + "where, KEY: the unique identifier for the file format"
1218                    + "\n           FILE_FORMAT: the full class name of the file format"
1219                    + "\n           FILE_EXTENSION: the file extension for the file format" + "\n\nFor example, "
1220                    + "\n\t to add NetCDF, \"NetCDF:hdf.object.nc2.NC2File:nc\""
1221                    + "\n\t to add FITS, \"FITS:hdf.object.fits.FitsFile:fits\"\n\n";
1222            String str = (String) JOptionPane.showInputDialog(this, msg, "Register a file format",
1223                    JOptionPane.PLAIN_MESSAGE, ViewProperties.getLargeHdfIcon(), null, null);
1224            if ((str == null) || (str.length() < 1)) {
1225                return;
1226            }
1227
1228            int idx1 = str.indexOf(':');
1229            int idx2 = str.lastIndexOf(':');
1230
1231            if ((idx1 < 0) || (idx2 <= idx1)) {
1232                JOptionPane.showMessageDialog(this, "Failed to register " + str
1233                        + "\n\nMust in the form of KEY:FILE_FORMAT:FILE_EXTENSION", "Register File Format",
1234                        JOptionPane.ERROR_MESSAGE);
1235                return;
1236            }
1237
1238            String key = str.substring(0, idx1);
1239            String className = str.substring(idx1 + 1, idx2);
1240            String extension = str.substring(idx2 + 1);
1241
1242            // check is the file format has been registered or the key is taken.
1243            String theKey = null;
1244            String theClassName = null;
1245            Enumeration<?> local_enum = FileFormat.getFileFormatKeys();
1246            while (local_enum.hasMoreElements()) {
1247                theKey = (String) local_enum.nextElement();
1248                if (theKey.endsWith(key)) {
1249                    JOptionPane.showMessageDialog(this, "Invalid key: " + key + " is taken.", "Register File Format",
1250                            JOptionPane.ERROR_MESSAGE);
1251                    return;
1252                }
1253
1254                theClassName = FileFormat.getFileFormat(theKey).getClass().getName();
1255                if (theClassName.endsWith(className)) {
1256                    JOptionPane.showMessageDialog(this, "The file format has already been registered: " + className,
1257                            "Register File Format", JOptionPane.ERROR_MESSAGE);
1258                    return;
1259                }
1260            }
1261
1262            // enables use of JHDF5 in JNLP (Web Start) applications, the system
1263            // class loader with reflection first.
1264            Class<?> theClass = null;
1265            try {
1266                theClass = Class.forName(className);
1267            }
1268            catch (Exception ex) {
1269                try {
1270                    theClass = ViewProperties.loadExtClass().loadClass(className);
1271                }
1272                catch (Exception ex2) {
1273                    theClass = null;
1274                }
1275            }
1276            if (theClass == null) {
1277                return;
1278            }
1279
1280            try {
1281                Object theObject = theClass.newInstance();
1282                if (theObject instanceof FileFormat) {
1283                    FileFormat.addFileFormat(key, (FileFormat) theObject);
1284                }
1285            }
1286            catch (Throwable ex) {
1287                JOptionPane.showMessageDialog(this, "Failed to register " + str + "\n\n" + ex, "Register File Format",
1288                        JOptionPane.ERROR_MESSAGE);
1289                return;
1290            }
1291
1292            if ((extension != null) && (extension.length() > 0)) {
1293                extension = extension.trim();
1294                String ext = ViewProperties.getFileExtension();
1295                ext += ", " + extension;
1296                ViewProperties.setFileExtension(ext);
1297            }
1298        }
1299        else if (cmd.equals("Unregister file format")) {
1300            Enumeration<Object> keys = FileFormat.getFileFormatKeys();
1301            ArrayList<Object> keylist = new ArrayList<Object>();
1302
1303            while (keys.hasMoreElements()) {
1304                keylist.add((Object)keys.nextElement());
1305            }
1306
1307            String theKey = (String) JOptionPane.showInputDialog(this, "Unregister a file format",
1308                    "Unregister a file format", JOptionPane.WARNING_MESSAGE, ViewProperties.getLargeHdfIcon(),
1309                    keylist.toArray(), null);
1310
1311            if (theKey == null) {
1312                return;
1313            }
1314
1315            FileFormat.removeFileFormat(theKey);
1316        }
1317        else if (cmd.equals("Users guide")) {
1318            String ugPath = ViewProperties.getUsersGuide();
1319
1320            // URL is invalid, use default path.
1321            if (ugPath == null || !ugPath.startsWith("http://")) {
1322                String sep = File.separator;
1323                File tmpFile = new File(ugPath);
1324                if (!(tmpFile.exists())) {
1325                    ugPath = rootDir + sep + "UsersGuide" + sep + "index.html";
1326                    tmpFile = new File(ugPath);
1327                    if (!(tmpFile.exists())) {
1328                        // use the online copy
1329                        ugPath = "http://www.hdfgroup.org/products/java/hdfview/UsersGuide/index.html";
1330                    }
1331                    ViewProperties.setUsersGuide(ugPath);
1332                }
1333            }
1334
1335            try {
1336                Tools.launchBrowser(ugPath);
1337            }
1338            catch (Exception ex) {
1339                JOptionPane.showMessageDialog(this, ex.getMessage(), "HDFView", JOptionPane.ERROR_MESSAGE,
1340                        ViewProperties.getLargeHdfIcon());
1341            }
1342        }
1343        else if (cmd.equals("HDF4 library")) {
1344            FileFormat thefile = FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF4);
1345            if (thefile == null) {
1346                return;
1347            }
1348
1349            JOptionPane.showMessageDialog(this, thefile.getLibversion(), "HDFView", JOptionPane.PLAIN_MESSAGE,
1350                    ViewProperties.getLargeHdfIcon());
1351        }
1352        else if (cmd.equals("HDF5 library")) {
1353            FileFormat thefile = FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF5);
1354            if (thefile == null) {
1355                return;
1356            }
1357
1358            JOptionPane.showMessageDialog(this, thefile.getLibversion(), "HDFView", JOptionPane.PLAIN_MESSAGE,
1359                    ViewProperties.getLargeHdfIcon());
1360        }
1361        else if (cmd.equals("Java version")) {
1362            String info = "Compiled at " + JAVA_COMPILER + "\nRunning at " + System.getProperty("java.version");
1363            JOptionPane.showMessageDialog(this, info, "HDFView", JOptionPane.PLAIN_MESSAGE,
1364                    ViewProperties.getLargeHdfIcon());
1365        }
1366        else if (cmd.equals("File format list")) {
1367            Enumeration<?> formatKeys = FileFormat.getFileFormatKeys();
1368
1369            String str = "\nSupported File Formats: \n";
1370            while (formatKeys.hasMoreElements()) {
1371                str += "    " + formatKeys.nextElement() + "\n";
1372            }
1373            str += "\n";
1374
1375            JOptionPane.showMessageDialog(this, str, "HDFView", JOptionPane.PLAIN_MESSAGE,
1376                    ViewProperties.getLargeHdfIcon());
1377        }
1378        else if (cmd.equals("About")) {
1379            JOptionPane.showMessageDialog(this, aboutHDFView, "HDFView", JOptionPane.PLAIN_MESSAGE,
1380                    ViewProperties.getLargeHdfIcon());
1381        }
1382        else if (cmd.equals("Popup URL list")) {
1383            urlBar.setPopupVisible(true);
1384        }
1385        else if (cmd.equals("Clear current selection")) {
1386            // urlBar.setPopupVisible(true);
1387            urlBar.setSelectedIndex(-1);
1388        }
1389        else {
1390            if ((helpViews == null) || (helpViews.size() <= 0)) {
1391                return;
1392            }
1393
1394            // try if one of the user help information;
1395            int n = helpViews.size();
1396            for (int i = 0; i < n; i++) {
1397                HelpView theView = (HelpView) helpViews.get(i);
1398                if (cmd.equals(theView.getActionCommand())) {
1399                    theView.show();
1400                    break;
1401                }
1402            } // for (int i=0; i<n; i++)
1403        }
1404    }
1405
1406    private void closeFile(FileFormat theFile) {
1407        if (theFile == null) {
1408            toolkit.beep();
1409            JOptionPane.showMessageDialog(this, "Select a file to close", getTitle(), JOptionPane.ERROR_MESSAGE);
1410            return;
1411        }
1412
1413        // close all the data windows of this file
1414        JInternalFrame[] frames = contentPane.getAllFrames();
1415        if (frames != null) {
1416            for (int i = 0; i < frames.length; i++) {
1417                HObject obj = (HObject) (((DataView) frames[i]).getDataObject());
1418                if (obj == null) {
1419                    continue;
1420                }
1421
1422                if (obj.getFileFormat().equals(theFile)) {
1423                    frames[i].dispose();
1424                    frames[i] = null;
1425                }
1426            }
1427        }
1428
1429        String fname = (String) urlBar.getSelectedItem();
1430        if (theFile.getFilePath().equals(fname)) {
1431            currentFile = null;
1432            urlBar.setSelectedIndex(-1);
1433        }
1434
1435        try {
1436            treeView.closeFile(theFile);
1437        }
1438        catch (Exception ex) {
1439        }
1440        theFile = null;
1441        attributeArea.setText("");
1442        System.gc();
1443    }
1444
1445    public void stateChanged(ChangeEvent e) {
1446        Object src = e.getSource();
1447
1448        log.trace("caught change event");
1449        if (src.equals(infoTabbedPane)) {
1450            int idx = infoTabbedPane.getSelectedIndex();
1451            if (idx == 1) {
1452                // meta info pane is selected
1453                attributeArea.setText("");
1454                showMetaData(treeView.getCurrentObject());
1455            }
1456        }
1457    }
1458
1459    public void dragEnter(DropTargetDragEvent evt) {
1460    }
1461
1462    @SuppressWarnings("unchecked")
1463    public void drop(DropTargetDropEvent evt) {
1464        try {
1465            final Transferable tr = evt.getTransferable();
1466
1467            if (tr.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
1468                evt.acceptDrop(DnDConstants.ACTION_COPY);
1469
1470                final List<?> fileList = (List<?>) tr.getTransferData(DataFlavor.javaFileListFlavor);
1471                int n = fileList.size();
1472                for (int i = 0; i < n; i++) {
1473                    File file = (File) fileList.get(i);
1474                    if (file.isDirectory()) continue;
1475
1476                    String filename = file.getAbsolutePath();
1477
1478                    currentFile = filename;
1479                    try {
1480                        treeView.openFile(filename, FileFormat.WRITE);
1481                    }
1482                    catch (Throwable ex) {
1483                        try {
1484                            treeView.openFile(filename, FileFormat.READ);
1485                        }
1486                        catch (Throwable ex2) {
1487                            String msg = "Failed to open file " + filename + "\n" + ex2;
1488                            toolkit.beep();
1489                            JOptionPane.showMessageDialog(this, msg, getTitle(), JOptionPane.ERROR_MESSAGE);
1490                            continue;
1491                        }
1492                    }
1493
1494                    try {
1495                        urlBar.removeItem(filename);
1496                        urlBar.insertItemAt(filename, 0);
1497                        urlBar.setSelectedIndex(0);
1498                    }
1499                    catch (Exception ex) {
1500                        log.debug("Unable to update urlBar:", ex);
1501                    }
1502
1503                }
1504                evt.getDropTargetContext().dropComplete(true);
1505            }
1506            else {
1507                evt.rejectDrop();
1508            }
1509        }
1510        catch (final IOException io) {
1511            evt.rejectDrop();
1512        }
1513        catch (final UnsupportedFlavorException ufe) {
1514            evt.rejectDrop();
1515        }
1516    }
1517
1518    public void dragExit(DropTargetEvent evt) {
1519    }
1520
1521    public void dropActionChanged(DropTargetDragEvent evt) {
1522    }
1523
1524    public void dragOver(DropTargetDragEvent dtde) {
1525    }
1526
1527    public void dispose() {
1528        try {
1529            props.save();
1530        }
1531        catch (Exception ex) {
1532        }
1533
1534        try {
1535            closeAllWindow();
1536        }
1537        catch (Exception ex) {
1538        }
1539
1540        // close all open files
1541        try {
1542            List<FileFormat> filelist = treeView.getCurrentFiles();
1543            if ((filelist != null) && (filelist.size() > 0)) {
1544                Object[] files = filelist.toArray();
1545                int n = files.length;
1546                for (int i = 0; i < n; i++) {
1547                    try {
1548                        treeView.closeFile((FileFormat) files[i]);
1549                    }
1550                    catch (Throwable ex) {
1551                        continue;
1552                    }
1553                }
1554            }
1555        }
1556        catch (Exception ex) {
1557        }
1558
1559        try {
1560            super.dispose();
1561        }
1562        catch (Exception ex) {
1563        }
1564
1565        System.exit(0);
1566    }
1567
1568    /** data content is displayed, and add the dataview to the main windows */
1569    public void addDataView(DataView dataView) {
1570        if (dataView == null) {
1571            return;
1572        }
1573        log.trace("addDataView: start");
1574
1575        if (!(dataView instanceof JInternalFrame)) {
1576            toolkit.beep();
1577            JOptionPane.showMessageDialog(this, "Unsupported DataView: the dataview is not a JInternalFrame.",
1578                    getTitle(), JOptionPane.ERROR_MESSAGE);
1579            return;
1580        }
1581
1582        // check if the data content is already displayed
1583        JInternalFrame[] frames = contentPane.getAllFrames();
1584        JInternalFrame theFrame = null;
1585        if (frames != null) {
1586            // test if the data is already displayed
1587            for (int i = 0; i < frames.length; i++) {
1588                if (dataView.equals(frames[i])) {
1589                    theFrame = frames[i];
1590                    break;
1591                }
1592            }
1593        }
1594
1595        if (theFrame != null) {
1596            // Data is already displayed. Just bring the dataview to the front
1597            theFrame.toFront();
1598            try {
1599                theFrame.setSelected(true);
1600            }
1601            catch (java.beans.PropertyVetoException e) {
1602            }
1603
1604            return;
1605        }
1606        log.trace("addDataView: not already displayed");
1607
1608        JInternalFrame frame = (JInternalFrame) dataView;
1609        contentPane.add(frame);
1610        HObject dataObject = null;
1611        try {
1612            dataObject = dataView.getDataObject();
1613        }
1614        catch (Exception ex) {
1615            JOptionPane.showMessageDialog(this, ex.getMessage(), getTitle(), JOptionPane.ERROR_MESSAGE);
1616        }
1617        if (dataObject == null) {
1618            // toolkit.beep();
1619            // JOptionPane
1620            // .showMessageDialog(
1621            // this,
1622            // "Unsupported DataObject: the data object is not supported.",
1623            // getTitle(), JOptionPane.ERROR_MESSAGE);
1624            return;
1625
1626        }
1627        String fullPath = dataObject.getPath() + dataObject.getName();
1628        String cmd = "SHOW WINDOW" + dataObject.getFID() + fullPath;
1629        // make the window to be unique: fid+path
1630        log.trace("addDataView: cmd={}", cmd);
1631
1632        frame.setName(fullPath); // data windows are identified by full path the file
1633        // id
1634        frame.setMaximizable(true);
1635        frame.setClosable(true);
1636        frame.setResizable(true);
1637
1638        JMenuItem item = new JMenuItem(fullPath);
1639        item.setActionCommand(cmd);
1640        item.addActionListener(this);
1641
1642        if (windowMenu.getMenuComponentCount() == 6) {
1643            Component[] menuItems = windowMenu.getMenuComponents();
1644            for (int i = 0; i < 6; i++) {
1645                menuItems[i].setEnabled(true);
1646            }
1647        }
1648
1649        windowMenu.add(item);
1650
1651        frame.setLocation(frameOffset, frameOffset);
1652        if (frameOffset < 60) {
1653            frameOffset += 15;
1654        }
1655        else {
1656            frameOffset = 0;
1657        }
1658
1659        Dimension d = contentPane.getSize();
1660        frame.setSize(d.width - 60, d.height - 60);
1661        log.trace("addDataView: finish");
1662
1663        frame.show();
1664    }
1665
1666    /** data content is closed, and remove the dataview from the main window */
1667    public void removeDataView(DataView dataView) {
1668        if (!(dataView instanceof JInternalFrame)) {
1669            toolkit.beep();
1670            JOptionPane.showMessageDialog(this, "The dataview is not a JInternalFrame.", getTitle(),
1671                    JOptionPane.ERROR_MESSAGE);
1672            return;
1673        }
1674
1675        JInternalFrame frame = (JInternalFrame) dataView;
1676        String name = frame.getName();
1677
1678        int n = windowMenu.getItemCount();
1679        JMenuItem theItem = null;
1680        for (int i = 6; i < n; i++) {
1681            theItem = windowMenu.getItem(i);
1682
1683            if (theItem == null) {
1684                continue;
1685            }
1686
1687            if (theItem.getActionCommand().equals(name)) {
1688                windowMenu.remove(i);
1689                theItem = null;
1690                break;
1691            }
1692        }
1693
1694        if (windowMenu.getMenuComponentCount() == 6) {
1695            Component[] menuItems = windowMenu.getMenuComponents();
1696            for (int i = 0; i < 6; i++) {
1697                menuItems[i].setEnabled(false);
1698            }
1699        }
1700    }
1701
1702    public TreeView getTreeView() {
1703        return treeView;
1704    }
1705
1706    /** Tree mouse event fired */
1707    public void mouseEventFired(java.awt.event.MouseEvent e) {
1708        HObject obj = treeView.getCurrentObject();
1709
1710        if (obj == null) {
1711            return;
1712        }
1713
1714        Object src = e.getSource();
1715        if ((src instanceof JComponent)) {
1716            String filename = obj.getFile();
1717            urlBar.setSelectedItem(filename);
1718
1719            if (infoTabbedPane.getSelectedIndex() == 1) showMetaData(obj);
1720        }
1721    }
1722
1723    public void showMetaData(HObject obj) {
1724        if (obj == null || currentFile == null) {
1725            return;
1726        }
1727
1728        log.trace("showMetaData: start");
1729        metadata.setLength(0);
1730        metadata.append(obj.getName());
1731
1732        String oidStr = null;
1733        long[] OID = obj.getOID();
1734        if (OID != null) {
1735            oidStr = String.valueOf(OID[0]);
1736            for (int i = 1; i < OID.length; i++) {
1737                oidStr += ", " + OID[i];
1738            }
1739        }
1740        metadata.append(" (");
1741        metadata.append(oidStr);
1742        metadata.append(")");
1743
1744        if (obj instanceof Group) {
1745            log.trace("showMetaData: instanceof Group");
1746            Group g = (Group) obj;
1747            metadata.append("\n    Group size = ");
1748            metadata.append(g.getMemberList().size());
1749        }
1750        else if (obj instanceof Dataset) {
1751            log.trace("showMetaData: instanceof Dataset");
1752            Dataset d = (Dataset) obj;
1753            if (d.getRank() <= 0) {
1754                d.init();
1755            }
1756            log.trace("showMetaData: inited");
1757
1758            metadata.append("\n    ");
1759            if (d instanceof ScalarDS) {
1760                Datatype dtype = d.getDatatype();
1761                if (dtype != null) metadata.append(dtype.getDatatypeDescription());
1762            }
1763            else if (d instanceof CompoundDS) {
1764                metadata.append("Compound/Vdata");
1765            }
1766            metadata.append(",    ");
1767
1768            long dims[] = d.getDims();
1769
1770            if (dims != null) {
1771                metadata.append(dims[0]);
1772                for (int i = 1; i < dims.length; i++) {
1773                    metadata.append(" x ");
1774                    metadata.append(dims[i]);
1775                }
1776            }
1777        } // else if (obj instanceof Dataset)
1778        else {
1779            log.debug("obj not instanceof Group or Dataset");
1780        }
1781
1782        List<?> attrList = null;
1783        try {
1784            log.trace("showMetaData: getMetadata");
1785            attrList = obj.getMetadata();
1786        }
1787        catch (Exception ex) {
1788            log.debug("getMetadata failure: ", ex);
1789        }
1790
1791        if (attrList == null) {
1792            metadata.append("\n    Number of attributes = 0");
1793        }
1794        else {
1795            int n = attrList.size();
1796            log.trace("showMetaData: append {} attributes", n);
1797            metadata.append("\n    Number of attributes = ");
1798            metadata.append(n);
1799
1800            for (int i = 0; i < n; i++) {
1801                log.trace("showMetaData: append Object[{}]", i);
1802                Object attrObj = attrList.get(i);
1803                if (!(attrObj instanceof Attribute)) {
1804                    continue;
1805                }
1806                Attribute attr = (Attribute) attrObj;
1807                metadata.append("\n        ");
1808                metadata.append(attr.getName());
1809                metadata.append(" = ");
1810                metadata.append(attr.toString(","));
1811                log.trace("showMetaData: append Object[{}]={}", i, attr.getName());
1812            }
1813        }
1814
1815        attributeArea.setText(metadata.toString());
1816        attributeArea.setCaretPosition(0);
1817        log.trace("showMetaData: finish");
1818    }
1819
1820    /**
1821     * Returns DataView contains the specified data object. It is useful to
1822     * avoid redundant display of data object that is opened already.
1823     *
1824     * @param dataObject
1825     *            the whose presence in the main view is to be tested.
1826     * @return DataView contains the specified data object, null if the data
1827     *         object is not displayed.
1828     */
1829    public DataView getDataView(HObject dataObject) {
1830        if (dataObject == null) {
1831            return null;
1832        }
1833
1834        // check if the data content is already displayed
1835        JInternalFrame[] frames = contentPane.getAllFrames();
1836        JInternalFrame theFrame = null;
1837
1838        if (frames == null) {
1839            return null;
1840        }
1841
1842        HObject obj = null;
1843        for (int i = 0; i < frames.length; i++) {
1844            if (!(frames[i] instanceof DataView)) {
1845                continue;
1846            }
1847
1848            obj = (HObject) (((DataView) frames[i]).getDataObject());
1849            if (dataObject.equals(obj)) {
1850                theFrame = frames[i];
1851                break; // data is already displayed
1852            }
1853        }
1854
1855        return (DataView) theFrame;
1856    }
1857
1858    /**
1859     * Returns a list of all open DataViews
1860     */
1861    public List<JInternalFrame> getDataViews() {
1862        // check if the data content is already displayed
1863        JInternalFrame[] frames = contentPane.getAllFrames();
1864
1865        if ((frames == null) || (frames.length <= 0)) {
1866            return null;
1867        }
1868
1869        Vector<JInternalFrame> views = new Vector<JInternalFrame>(frames.length);
1870        for (int i = 0; i < frames.length; i++) {
1871            if (!(frames[i] instanceof DataView)) {
1872                continue;
1873            }
1874            else {
1875                views.add(frames[i]);
1876            }
1877        }
1878
1879        return views;
1880    }
1881
1882    /**
1883     * @return a list of treeview implementations.
1884     */
1885    public static final List<String> getListOfTreeView() {
1886        return treeViews;
1887    }
1888
1889    /**
1890     * @return a list of imageview implementations.
1891     */
1892    public static final List<String> getListOfImageView() {
1893        return imageViews;
1894    }
1895
1896    /**
1897     * @return a list of tableview implementations.
1898     */
1899    public static final List<?> getListOfTableView() {
1900        return tableViews;
1901    }
1902
1903    /**
1904     * @return a list of textview implementations.
1905     */
1906    public static final List<?> getListOfTextView() {
1907        return textViews;
1908    }
1909
1910    /**
1911     * @return a list of metaDataview implementations.
1912     */
1913    public static final List<?> getListOfMetaDataView() {
1914        return metaDataViews;
1915    }
1916
1917    /**
1918     * @return a list of paletteview implementations.
1919     */
1920    public static final List<?> getListOfPaletteView() {
1921        return paletteViews;
1922    }
1923
1924    /**
1925     * Display feedback message.
1926     *
1927     * @param msg
1928     *            the message to display.
1929     */
1930    public void showStatus(String msg) {
1931        message.append(msg);
1932        message.append("\n");
1933        statusArea.setText(message.toString());
1934    }
1935
1936    public void reloadFile() {
1937        int temp_index_type = 0;
1938        int temp_index_order = 0;
1939
1940        FileFormat theFile = treeView.getSelectedFile();
1941        if (theFile.isThisType(FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF5))) {
1942            temp_index_type = theFile.getIndexType(null);
1943            temp_index_order = theFile.getIndexOrder(null);
1944        }
1945        closeFile(theFile);
1946
1947        if (theFile.isThisType(FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF5))) {
1948            theFile.setIndexType(temp_index_type);
1949            theFile.setIndexOrder(temp_index_order);
1950        }
1951        try {
1952            treeView.reopenFile(theFile);
1953        }
1954        catch (Exception ex) {
1955        }
1956    }
1957
1958    /** choose local file */
1959    private String openLocalFile() {
1960        JFileChooser fchooser = new JFileChooser(currentDir);
1961        fchooser.setFileFilter(DefaultFileFilter.getFileFilter());
1962
1963        int returnVal = fchooser.showOpenDialog(this);
1964
1965        if (returnVal != JFileChooser.APPROVE_OPTION) {
1966            return null;
1967        }
1968
1969        File choosedFile = fchooser.getSelectedFile();
1970        if (choosedFile == null) {
1971            return null;
1972        }
1973
1974        if (choosedFile.isDirectory()) {
1975            currentDir = choosedFile.getPath();
1976        }
1977        else {
1978            currentDir = choosedFile.getParent();
1979        }
1980
1981        return choosedFile.getAbsolutePath();
1982    }
1983
1984    /** load remote file and save it to local temporary directory */
1985    private String openRemoteFile(String urlStr) {
1986        String localFile = null;
1987
1988        if (urlStr == null) {
1989            return null;
1990        }
1991
1992        if (urlStr.startsWith("http://")) {
1993            localFile = urlStr.substring(7);
1994        }
1995        else if (urlStr.startsWith("ftp://")) {
1996            localFile = urlStr.substring(6);
1997        }
1998        else {
1999            return null;
2000        }
2001
2002        localFile = localFile.replace('/', '@');
2003        localFile = localFile.replace('\\', '@');
2004
2005        // search the local file cache
2006        String tmpDir = System.getProperty("java.io.tmpdir");
2007
2008        File tmpFile = new File(tmpDir);
2009        if (!tmpFile.canWrite()) tmpDir = System.getProperty("user.home");
2010
2011        localFile = tmpDir + localFile;
2012
2013        tmpFile = new File(localFile);
2014        if (tmpFile.exists()) {
2015            return localFile;
2016        }
2017
2018        URL url = null;
2019
2020        try {
2021            url = new URL(urlStr);
2022        }
2023        catch (Exception ex) {
2024            url = null;
2025            toolkit.beep();
2026            JOptionPane.showMessageDialog(this, ex, getTitle(), JOptionPane.ERROR_MESSAGE);
2027            return null;
2028        }
2029
2030        BufferedInputStream in = null;
2031        BufferedOutputStream out = null;
2032        try {
2033            in = new BufferedInputStream(url.openStream());
2034            out = new BufferedOutputStream(new FileOutputStream(tmpFile));
2035        }
2036        catch (Exception ex) {
2037            in = null;
2038            toolkit.beep();
2039            JOptionPane.showMessageDialog(this, ex, getTitle(), JOptionPane.ERROR_MESSAGE);
2040            try {
2041                out.close();
2042            }
2043            catch (Exception ex2) {
2044                log.debug("remote file:", ex2);
2045            }
2046            return null;
2047        }
2048
2049        setCursor(java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.WAIT_CURSOR));
2050        byte[] buff = new byte[512]; // set the default buff size to 512
2051        try {
2052            int n = 0;
2053            while ((n = in.read(buff)) > 0) {
2054                out.write(buff, 0, n);
2055            }
2056        }
2057        catch (Exception ex) {
2058            log.debug("remote file:", ex);
2059        }
2060
2061        try {
2062            in.close();
2063        }
2064        catch (Exception ex2) {
2065            log.debug("remote file:", ex2);
2066        }
2067        try {
2068            out.close();
2069        }
2070        catch (Exception ex2) {
2071            log.debug("remote file:", ex2);
2072        }
2073
2074        setCursor(java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.DEFAULT_CURSOR));
2075
2076        return localFile;
2077    }
2078
2079    /** open file from SRB server */
2080    private void openFromSRB() throws Exception {
2081        if (ctrSrbFileDialog == null) {
2082            Class<?> theClass = null;
2083
2084            try {
2085                theClass = Class.forName("hdf.srb.SRBFileDialog");
2086            }
2087            catch (Exception ex) {
2088                theClass = null;
2089                showStatus(ex.toString());
2090                throw (new ClassNotFoundException("Cannot find SRBFileDialog"));
2091            }
2092
2093            try {
2094                @SuppressWarnings("rawtypes")
2095                Class[] paramClass = { Class.forName("java.awt.Frame") };
2096                ctrSrbFileDialog = theClass.getConstructor(paramClass);
2097            }
2098            catch (Exception ex) {
2099                ctrSrbFileDialog = null;
2100                throw (new InstantiationException("Cannot construct SRBFileDialog"));
2101            }
2102        }
2103
2104        if (srbFileDialog == null) {
2105            try {
2106                Object[] paramObj = { (java.awt.Frame) this };
2107                srbFileDialog = (JDialog) ctrSrbFileDialog.newInstance(paramObj);
2108            }
2109            catch (Exception ex) {
2110                throw ex;
2111            }
2112        }
2113        else {
2114            srbFileDialog.setVisible(true);
2115        }
2116
2117        currentFile = srbFileDialog.getName();
2118    }
2119
2120    /**
2121     * The starting point of this application.
2122     *
2123     * <pre>
2124     * Usage: java(w)
2125     *        -Dhdf.hdf5lib.H5.hdf5lib="your HDF5 library path"
2126     *        -Dhdf.hdflib.HDFLibrary.hdflib="your HDF4 library path"
2127     *        -root "the directory where the HDFView is installed"
2128     *        [filename] "the file to open"
2129     * </pre>
2130     */
2131    public static void main(String args[]) {
2132        String rootDir = System.getProperty("hdfview.workdir");
2133        if (rootDir == null) {
2134            rootDir = System.getProperty("user.dir");
2135        }
2136        File tmpFile = null;
2137        int i = 0;
2138        int j = args.length;
2139        int W = 0, H = 0, X = 0, Y = 0;
2140
2141        for (i = 0; i < args.length; i++) {
2142            if ("-root".equalsIgnoreCase(args[i])) {
2143                j--;
2144                try {
2145                    j--;
2146                    tmpFile = new File(args[++i]);
2147
2148                    if (tmpFile.isDirectory()) {
2149                        rootDir = tmpFile.getPath();
2150                    }
2151                    else if (tmpFile.isFile()) {
2152                        rootDir = tmpFile.getParent();
2153                    }
2154                }
2155                catch (Exception e) {
2156                }
2157            }
2158            else if ("-g".equalsIgnoreCase(args[i]) || "-geometry".equalsIgnoreCase(args[i])) {
2159                j--;
2160                // -geometry WIDTHxHEIGHT+XOFF+YOFF
2161                try {
2162                    String geom = args[++i];
2163                    j--;
2164
2165                    int idx = 0;
2166                    int idx0 = geom.lastIndexOf('-');
2167                    int idx1 = geom.lastIndexOf('+');
2168
2169                    idx = Math.max(idx0, idx1);
2170                    if (idx > 0) {
2171                        Y = Integer.parseInt(geom.substring(idx + 1));
2172                        if (idx == idx0) {
2173                            Y = -Y;
2174                        }
2175                        geom = geom.substring(0, idx);
2176                        idx0 = geom.lastIndexOf('-');
2177                        idx1 = geom.lastIndexOf('+');
2178                        idx = Math.max(idx0, idx1);
2179                        if (idx > 0) {
2180                            X = Integer.parseInt(geom.substring(idx + 1));
2181                            if (idx == idx0) {
2182                                X = -X;
2183                            }
2184                            geom = geom.substring(0, idx);
2185                        }
2186                    }
2187
2188                    idx = geom.indexOf('x');
2189                    if (idx > 0) {
2190                        W = Integer.parseInt(geom.substring(0, idx));
2191                        H = Integer.parseInt(geom.substring(idx + 1));
2192                    }
2193                }
2194                catch (Exception e) {
2195                    e.printStackTrace();
2196                }
2197            }
2198            else if ("-java.version".equalsIgnoreCase(args[i])) {
2199                String info = "Compiled at " + JAVA_COMPILER + "\nRunning at " + System.getProperty("java.version");
2200                JOptionPane.showMessageDialog(new JFrame(), info, "HDFView", JOptionPane.PLAIN_MESSAGE,
2201                        ViewProperties.getLargeHdfIcon());
2202                System.exit(0);
2203            }
2204        }
2205
2206        Vector<File> flist = new Vector<File>();
2207        tmpFile = null;
2208        if (j >= 0) {
2209            for (i=args.length-j; i < args.length; i++) {
2210                tmpFile = new File(rootDir, args[i]);
2211                log.trace("main: filelist - file = {} ", tmpFile.getAbsolutePath());
2212                log.trace("main: filelist - add file = {} exists={} isFile={} isDir={}", tmpFile, tmpFile.exists(), tmpFile.isFile(), tmpFile.isDirectory());
2213                if (tmpFile.exists() && (tmpFile.isFile() || tmpFile.isDirectory())) {
2214                    log.trace("main: flist - add file = {}", tmpFile.getAbsolutePath());
2215                    flist.add(new File(tmpFile.getAbsolutePath()));
2216                }
2217            }
2218        }
2219
2220        final Vector<File> the_flist = flist;
2221        final String the_rootDir = rootDir;
2222        final int the_X = X, the_Y = Y, the_W = W, the_H = H;
2223
2224        log.trace("main: flist.size={} - the_rootDir={}", the_flist.size(), the_rootDir);
2225        // Schedule a job for the event-dispatching thread:
2226        // creating and showing this application's GUI.
2227        javax.swing.SwingUtilities.invokeLater(new Runnable() {
2228            public void run() {
2229                HDFView frame = new HDFView(the_rootDir, the_flist, the_W, the_H, the_X, the_Y);
2230                frame.setVisible(true);
2231            }
2232        });
2233    }
2234}