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