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.Color;
019import java.awt.Component;
020import java.awt.Cursor;
021import java.awt.GridLayout;
022import java.awt.Point;
023import java.awt.Toolkit;
024import java.awt.event.ActionEvent;
025import java.awt.event.ActionListener;
026import java.awt.event.KeyAdapter;
027import java.awt.event.KeyEvent;
028import java.awt.event.MouseAdapter;
029import java.awt.event.MouseEvent;
030import java.io.BufferedInputStream;
031import java.io.BufferedOutputStream;
032import java.io.File;
033import java.io.FileInputStream;
034import java.io.FileOutputStream;
035import java.io.Serializable;
036import java.lang.reflect.Constructor;
037import java.lang.reflect.Method;
038import java.util.BitSet;
039import java.util.Enumeration;
040import java.util.HashMap;
041import java.util.Iterator;
042import java.util.List;
043import java.util.Vector;
044
045import javax.swing.BorderFactory;
046import javax.swing.ButtonGroup;
047import javax.swing.Icon;
048import javax.swing.JButton;
049import javax.swing.JComboBox;
050import javax.swing.JComponent;
051import javax.swing.JDialog;
052import javax.swing.JFileChooser;
053import javax.swing.JFrame;
054import javax.swing.JInternalFrame;
055import javax.swing.JMenu;
056import javax.swing.JMenuItem;
057import javax.swing.JOptionPane;
058import javax.swing.JPanel;
059import javax.swing.JPopupMenu;
060import javax.swing.JRadioButton;
061import javax.swing.JSeparator;
062import javax.swing.JTree;
063import javax.swing.border.BevelBorder;
064import javax.swing.border.SoftBevelBorder;
065import javax.swing.border.TitledBorder;
066import javax.swing.tree.DefaultMutableTreeNode;
067import javax.swing.tree.DefaultTreeCellRenderer;
068import javax.swing.tree.DefaultTreeModel;
069import javax.swing.tree.MutableTreeNode;
070import javax.swing.tree.TreeNode;
071import javax.swing.tree.TreePath;
072
073import hdf.object.CompoundDS;
074import hdf.object.Dataset;
075import hdf.object.Datatype;
076import hdf.object.FileFormat;
077import hdf.object.Group;
078import hdf.object.HObject;
079import hdf.object.ScalarDS;
080import hdf.view.ViewProperties.DATA_VIEW_KEY;
081
082/**
083 *
084 * <p>
085 * TreeView defines APIs for open a file and display the file structure in tree
086 * structure.
087 * </p>
088 *
089 * <p>
090 * TreeView uses folders and leaf nodes to represent groups and data objects in
091 * the file. You can expand or collapse folders to navigate data objects in the
092 * file.
093 * </p>
094 *
095 * <p>
096 * From the TreeView, you can open data content or metadata of selected object.
097 * You can selet object(s) to delete or add new object to the file.
098 * </p>
099 *
100 * @author Peter X. Cao
101 * @version 2.4 9/6/2007
102 */
103public class DefaultTreeView extends JPanel implements TreeView, ActionListener {
104    private static final long            serialVersionUID    = 4092566164712521186L;
105
106    private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(DefaultTreeView.class);
107
108    /** the owner of this treeview */
109    private ViewManager                  viewer;
110
111    /**
112     * The super root of tree: all open files start at this root.
113     */
114    private final DefaultMutableTreeNode root;
115
116    /**
117     * The tree which holds file structures.
118     */
119    private final JTree                  tree;
120
121    /**
122     * The tree model
123     */
124    private final DefaultTreeModel       treeModel;
125
126    /** A list open files. */
127    private final List<FileFormat>       fileList;
128
129    private final Toolkit                toolkit;
130
131    /** Selected file */
132    private FileFormat                   selectedFile;
133
134    /** The current selected node. */
135    private DefaultMutableTreeNode       selectedNode;
136
137    /** The current selected TreePath. */
138    private TreePath                     selectedTreePath;
139
140    /** the current selected object */
141    private HObject                      selectedObject;
142
143    /** flag to indicate if the dataset is displayed as default */
144    private boolean                      isDefaultDisplay;
145
146    /**
147     * The popup menu used to display user choice of actions on data object.
148     */
149    private final JPopupMenu             popupMenu;
150
151    private JSeparator                   separator;
152
153    /** a list of editing GUI components */
154    private List<JMenuItem>              editGUIs;
155
156    /** the list of current selected objects */
157    private List<Object>                 objectsToCopy;
158
159    private JMenu                        exportDatasetMenu;
160
161    private JMenuItem                    addTableMenuItem;
162
163    private JMenuItem                    addDatasetMenuItem;
164
165    private JMenuItem                    addDatatypeMenuItem;
166
167    private JMenuItem                    addLinkMenuItem;
168
169    private JMenuItem                    setLibVerBoundsItem;
170
171    private JMenuItem                    changeIndexItem;
172
173    private String                       currentSearchPhrase = null;
174
175    private boolean                      moveFlag;
176
177    private TreePath[]                   currentSelectionsForMove;
178
179    private boolean                      isApplyBitmaskOnly  = false;
180
181    private int                          currentIndexType;
182
183    private int                          currentIndexOrder;
184
185    private int                          binaryOrder;
186
187    public DefaultTreeView(ViewManager theView) {
188        viewer = theView;
189
190        root = new DefaultMutableTreeNode() {
191            private static final long serialVersionUID = -6829919815424470510L;
192
193            public boolean isLeaf() {
194                return false;
195            }
196        };
197
198        fileList = new Vector<FileFormat>();
199        toolkit = Toolkit.getDefaultToolkit();
200        editGUIs = new Vector<JMenuItem>();
201        objectsToCopy = null;
202        isDefaultDisplay = true;
203        selectedTreePath = null;
204        selectedNode = null;
205        moveFlag = false;
206        currentSelectionsForMove = null;
207
208        addDatasetMenuItem = new JMenuItem("Dataset", ViewProperties.getDatasetIcon());
209        addDatasetMenuItem.addActionListener(this);
210        addDatasetMenuItem.setActionCommand("Add dataset");
211
212        addTableMenuItem = new JMenuItem("Compound DS", ViewProperties.getTableIcon());
213        addTableMenuItem.addActionListener(this);
214        addTableMenuItem.setActionCommand("Add table");
215
216        addDatatypeMenuItem = new JMenuItem("Datatype", ViewProperties.getDatatypeIcon());
217        addDatatypeMenuItem.addActionListener(this);
218        addDatatypeMenuItem.setActionCommand("Add datatype");
219
220        addLinkMenuItem = new JMenuItem("Link", ViewProperties.getLinkIcon());
221        addLinkMenuItem.addActionListener(this);
222        addLinkMenuItem.setActionCommand("Add link");
223
224        setLibVerBoundsItem = new JMenuItem("Set Lib version bounds");
225        setLibVerBoundsItem.addActionListener(this);
226        setLibVerBoundsItem.setActionCommand("Set Lib version bounds");
227
228        changeIndexItem = new JMenuItem("Change file indexing");
229        changeIndexItem.addActionListener(this);
230        changeIndexItem.setActionCommand("Change file indexing");
231
232        // initialize the tree and root
233        treeModel = new DefaultTreeModel(root);
234        tree = new JTree(treeModel);
235
236        tree.setLargeModel(true);
237        tree.setCellRenderer(new HTreeCellRenderer());
238        tree.addMouseListener(new HTreeMouseAdapter());
239        tree.addKeyListener(new HTreeKeyAdapter());
240        tree.setRootVisible(false);
241        // tree.setShowsRootHandles(true);
242        int rowheight = 23 + (int) ((tree.getFont().getSize() - 12) * 0.5);
243        tree.setRowHeight(rowheight);
244
245        // create the separator
246        separator = new JPopupMenu.Separator();
247
248        // create the popupmenu
249        popupMenu = createPopupMenu();
250
251        // reset the scroll increament
252        // layout GUI component
253        this.setLayout(new BorderLayout());
254        this.add(tree, BorderLayout.CENTER);
255    }
256
257    /**
258     * Insert a node into the tree.
259     *
260     * @param node
261     *            the node to insert.
262     * @param pnode
263     *            the parent node.
264     */
265    private void insertNode(TreeNode node, TreeNode pnode) {
266        if ((node == null) || (pnode == null)) {
267            return;
268        }
269
270        treeModel.insertNodeInto((DefaultMutableTreeNode) node, (DefaultMutableTreeNode) pnode, pnode.getChildCount());
271    }
272
273    /**
274     * Checks if a file is already open.
275     */
276    private boolean isFileOpen(String filename) {
277        boolean isOpen = false;
278
279        // find the file by matching its file name and close the file
280        FileFormat theFile = null;
281        Iterator<FileFormat> iterator = fileList.iterator();
282        while (iterator.hasNext()) {
283            theFile = iterator.next();
284            if (theFile.getFilePath().equals(filename)) {
285                isOpen = true;
286                break;
287            }
288        } // while(iterator.hasNext())
289
290        return isOpen;
291    }
292
293    /** creates a popup menu for a right mouse click on a data object */
294    private JPopupMenu createPopupMenu() {
295        JPopupMenu menu = new JPopupMenu();
296        JMenuItem item;
297
298        item = new JMenuItem("Open");
299        item.setMnemonic(KeyEvent.VK_O);
300        item.addActionListener(this);
301        item.setActionCommand("Open data");
302        menu.add(item);
303
304        item = new JMenuItem("Open As");
305        item.setMnemonic(KeyEvent.VK_A);
306        item.addActionListener(this);
307        item.setActionCommand("Open data as");
308        menu.add(item);
309
310        menu.addSeparator();
311
312        JMenu newOjbectMenu = new JMenu("New");
313        menu.add(newOjbectMenu);
314        editGUIs.add(newOjbectMenu);
315
316        item = new JMenuItem("Group", ViewProperties.getFoldercloseIcon());
317        item.addActionListener(this);
318        item.setActionCommand("Add group");
319        newOjbectMenu.add(item);
320
321        newOjbectMenu.add(addDatasetMenuItem);
322
323        item = new JMenuItem("Image", ViewProperties.getImageIcon());
324        item.addActionListener(this);
325        item.setActionCommand("Add image");
326        newOjbectMenu.add(item);
327
328        newOjbectMenu.add(addTableMenuItem);
329        newOjbectMenu.add(addDatatypeMenuItem);
330        newOjbectMenu.add(addLinkMenuItem);
331
332        menu.addSeparator();
333
334        item = new JMenuItem("Copy");
335        item.setMnemonic(KeyEvent.VK_C);
336        item.addActionListener(this);
337        item.setActionCommand("Copy object");
338        menu.add(item);
339
340        item = new JMenuItem("Paste");
341        item.setMnemonic(KeyEvent.VK_P);
342        item.addActionListener(this);
343        item.setActionCommand("Paste object");
344        menu.add(item);
345        editGUIs.add(item);
346
347        item = new JMenuItem("Delete");
348        item.setMnemonic(KeyEvent.VK_D);
349        item.addActionListener(this);
350        item.setActionCommand("Cut object");
351        menu.add(item);
352        editGUIs.add(item);
353
354        item = new JMenuItem("Cut");
355        item.setMnemonic(KeyEvent.VK_T);
356        item.addActionListener(this);
357        item.setActionCommand("Move object");
358        menu.add(item);
359        editGUIs.add(item);
360
361        exportDatasetMenu = new JMenu("Export Dataset");
362        menu.add(exportDatasetMenu);
363        item = new JMenuItem("Export Data to Text File");
364        item.addActionListener(this);
365        item.setActionCommand("Save table as text");
366        exportDatasetMenu.add(item);
367
368        item = new JMenuItem("Export Data as Native Order");
369        item.addActionListener(this);
370        item.setActionCommand("Save table as binary Native Order");
371        exportDatasetMenu.add(item);
372        item = new JMenuItem("Export Data as Little Endian");
373        item.addActionListener(this);
374        item.setActionCommand("Save table as binary Little Endian");
375        exportDatasetMenu.add(item);
376        item = new JMenuItem("Export Data as Big Endian");
377        item.addActionListener(this);
378        item.setActionCommand("Save table as binary Big Endian");
379        exportDatasetMenu.add(item);
380
381        menu.addSeparator();
382
383        item = new JMenuItem("Save to");
384        item.setMnemonic(KeyEvent.VK_S);
385        item.addActionListener(this);
386        item.setActionCommand("Save object to file");
387        menu.add(item);
388
389        item = new JMenuItem("Rename");
390        item.setMnemonic(KeyEvent.VK_R);
391        item.addActionListener(this);
392        item.setActionCommand("Rename object");
393        menu.add(item);
394        editGUIs.add(item);
395
396        menu.addSeparator();
397
398        item = new JMenuItem("Show Properties");
399        item.addActionListener(this);
400        item.setActionCommand("Show object properties");
401        menu.add(item);
402
403        item = new JMenuItem("Show Properties As");
404        item.addActionListener(this);
405        item.setActionCommand("Show object properties as");
406        menu.add(item);
407
408        menu.add(changeIndexItem);
409
410        menu.addSeparator();
411
412        item = new JMenuItem("Find");
413        item.setMnemonic(KeyEvent.VK_F);
414        item.addActionListener(this);
415        item.setActionCommand("Find");
416        menu.add(item);
417
418        // item = new JMenuItem( "Find Next");
419        // item.setMnemonic(KeyEvent.VK_N);
420        // item.addActionListener(this);
421        // item.setActionCommand("Find next");
422        // menu.add(item);
423
424        menu.addSeparator();
425
426        item = new JMenuItem("Expand All");
427        item.addActionListener(this);
428        item.setActionCommand("Expand all");
429        menu.add(item);
430        item = new JMenuItem("Collapse All");
431        item.addActionListener(this);
432        item.setActionCommand("Collapse all");
433        menu.add(item);
434
435        menu.addSeparator();
436
437        item = new JMenuItem("Close File");
438        item.setMnemonic(KeyEvent.VK_E);
439        item.addActionListener(this);
440        item.setActionCommand("Close file");
441        menu.add(item);
442
443        item = new JMenuItem("Reload File");
444        // item.setMnemonic(KeyEvent.VK_R);
445        item.addActionListener(this);
446        item.setActionCommand("Reload file");
447        menu.add(item);
448
449        menu.add(separator);
450        menu.add(setLibVerBoundsItem);
451
452        return menu;
453    }
454
455    /** display the popupmenu of data properties */
456    private void showPopupMenu(MouseEvent e) {
457        int x = e.getX();
458        int y = e.getY();
459
460        HObject selectedObject = ((HObject) (selectedNode.getUserObject()));
461        boolean isReadOnly = selectedObject.getFileFormat().isReadOnly();
462
463        setEnabled(editGUIs, !isReadOnly);
464
465        boolean isWritable = !selectedObject.getFileFormat().isReadOnly();
466        if (selectedObject instanceof Group) {
467            popupMenu.getComponent(0).setEnabled(false); // "open" menuitem
468            popupMenu.getComponent(1).setEnabled(false); // "open as" menuitem
469
470            boolean state = !(((Group) selectedObject).isRoot());
471            popupMenu.getComponent(5).setEnabled(state); // "Copy" menuitem
472            popupMenu.getComponent(6).setEnabled(isWritable); // "Paste"
473            // menuitem
474            popupMenu.getComponent(7).setEnabled(state && isWritable); // "Delete"
475            // menuitem
476            popupMenu.getComponent(11).setEnabled(state); // "save to" menuitem
477            popupMenu.getComponent(12).setEnabled(state && isWritable); // "rename"
478            // menuitem
479            popupMenu.getComponent(8).setEnabled(
480                    (selectedObject.getFileFormat().isThisType(FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF5)))
481                    && state && isWritable); // "cut" menuitem
482        }
483        else {
484            popupMenu.getComponent(0).setEnabled(true);
485            popupMenu.getComponent(1).setEnabled(true);
486            popupMenu.getComponent(5).setEnabled(true); // "Copy" menuitem
487            popupMenu.getComponent(6).setEnabled(isWritable); // "Paste"
488            // menuitem
489            popupMenu.getComponent(7).setEnabled(isWritable); // "Delete"
490            // menuitem
491            popupMenu.getComponent(11).setEnabled(true); // "save to" menuitem
492            popupMenu.getComponent(12).setEnabled(isWritable); // "rename"
493            // menuitem
494            popupMenu.getComponent(8).setEnabled(
495                    (selectedObject.getFileFormat().isThisType(FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF5)))
496                    && isWritable); // "cut" menuitem
497        }
498
499        // adding table is only supported by HDF5
500        if ((selectedFile != null) && selectedFile.isThisType(FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF5))) {
501            addDatasetMenuItem.setText("Dataset");
502            addTableMenuItem.setVisible(true);
503            addDatatypeMenuItem.setVisible(true);
504            addLinkMenuItem.setVisible(true);
505            boolean state = false;
506            if ((selectedObject instanceof Group)) {
507                state = (((Group) selectedObject).isRoot());
508                separator.setVisible(isWritable && state);
509                setLibVerBoundsItem.setVisible(isWritable && state);
510                // added only if it is HDF5format, iswritable & isroot
511            }
512            else {
513                separator.setVisible(false);
514                setLibVerBoundsItem.setVisible(false);
515            }
516            changeIndexItem.setVisible(state);
517        }
518        else {
519            addDatasetMenuItem.setText("SDS");
520            addTableMenuItem.setVisible(false);
521            addDatatypeMenuItem.setVisible(false);
522            addLinkMenuItem.setVisible(false);
523            separator.setVisible(false);
524            setLibVerBoundsItem.setVisible(false);
525            changeIndexItem.setVisible(false);
526        }
527
528        // export table is only supported by HDF5
529        if ((selectedObject != null) && selectedObject.getFileFormat().isThisType(FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF5))) {
530            if ((selectedObject instanceof Dataset)) {
531                Dataset dataset = (Dataset) selectedObject;
532                if ((dataset instanceof ScalarDS)) {
533                    exportDatasetMenu.setVisible(true);
534                }
535            }
536            else {
537                exportDatasetMenu.setVisible(false);
538            }
539        }
540        else {
541            exportDatasetMenu.setVisible(false);
542        }
543
544        popupMenu.show((JComponent) e.getSource(), x, y);
545    }
546
547    /** disable/enable GUI components */
548    private static void setEnabled(List<JMenuItem> list, boolean b) {
549        Component item = null;
550        Iterator<JMenuItem> it = list.iterator();
551        while (it.hasNext()) {
552            item = it.next();
553            item.setEnabled(b);
554        }
555    }
556
557    /**
558     * Save the current file into HDF4. Since HDF4 does not support packing. The
559     * source file is copied into the new file with the exact same content.
560     */
561    private final void saveAsHDF4(FileFormat srcFile) {
562        if (srcFile == null) {
563            toolkit.beep();
564            JOptionPane.showMessageDialog(this, "Select a file to save.", "HDFView", JOptionPane.ERROR_MESSAGE);
565            return;
566        }
567
568        JFrame owner = (viewer == null) ? new JFrame() : (JFrame) viewer;
569        String currentDir = srcFile.getParent();
570        NewFileDialog dialog = new NewFileDialog(owner, currentDir, FileFormat.FILE_TYPE_HDF4, getCurrentFiles());
571        // dialog.show();
572
573        if (!dialog.isFileCreated()) {
574            return;
575        }
576
577        String filename = dialog.getFile();
578
579        // since cannot pack hdf4, simple copy the whole phyisical file
580        int length = 0;
581        int bsize = 512;
582        byte[] buffer;
583        BufferedInputStream bi = null;
584        BufferedOutputStream bo = null;
585
586        try {
587            bi = new BufferedInputStream(new FileInputStream(srcFile.getFilePath()));
588        }
589        catch (Exception ex) {
590            toolkit.beep();
591            JOptionPane.showMessageDialog(this, ex.getMessage() + "\n" + filename, "HDFView", JOptionPane.ERROR_MESSAGE);
592            return;
593        }
594
595        try {
596            bo = new BufferedOutputStream(new FileOutputStream(filename));
597        }
598        catch (Exception ex) {
599            try {
600                bi.close();
601            }
602            catch (Exception ex2) {
603                log.debug("output file force input close:", ex2);
604            }
605            toolkit.beep();
606            JOptionPane.showMessageDialog(this, ex, "HDFView", JOptionPane.ERROR_MESSAGE);
607            return;
608        }
609
610        buffer = new byte[bsize];
611        try {
612            length = bi.read(buffer, 0, bsize);
613        }
614        catch (Exception ex) {
615            length = 0;
616        }
617        while (length > 0) {
618            try {
619                bo.write(buffer, 0, length);
620                length = bi.read(buffer, 0, bsize);
621            }
622            catch (Exception ex) {
623                length = 0;
624            }
625        }
626
627        try {
628            bo.flush();
629        }
630        catch (Exception ex) {
631            log.debug("output file:", ex);
632        }
633        try {
634            bi.close();
635        }
636        catch (Exception ex) {
637            log.debug("input file:", ex);
638        }
639        try {
640            bo.close();
641        }
642        catch (Exception ex) {
643            log.debug("output file:", ex);
644        }
645
646        try {
647            openFile(filename, FileFormat.WRITE);
648        }
649        catch (Exception ex) {
650            toolkit.beep();
651            JOptionPane .showMessageDialog(this, ex.getMessage() + "\n" + filename, "HDFView", JOptionPane.ERROR_MESSAGE);
652        }
653    }
654
655    /**
656     * Copy the current file into a new file. The new file does not include the
657     * inaccessible objects. Values of reference dataset are not updated in the
658     * new file.
659     */
660    private void saveAsHDF5(FileFormat srcFile) {
661        if (srcFile == null) {
662            toolkit.beep();
663            JOptionPane.showMessageDialog(this, "Select a file to save.", "HDFView", JOptionPane.ERROR_MESSAGE);
664            return;
665        }
666
667        TreeNode root = srcFile.getRootNode();
668        if (root == null) {
669            toolkit.beep();
670            JOptionPane.showMessageDialog(this, "The file is empty.", "HDFView", JOptionPane.ERROR_MESSAGE);
671            return;
672        }
673
674        JFrame owner = (viewer == null) ? new JFrame() : (JFrame) viewer;
675        NewFileDialog dialog = new NewFileDialog(owner, srcFile.getParent(), FileFormat.FILE_TYPE_HDF5,
676                getCurrentFiles());
677        // dialog.show();
678
679        if (!dialog.isFileCreated()) {
680            return;
681        }
682
683        String filename = dialog.getFile();
684
685        int n = root.getChildCount();
686        Vector<Object> objList = new Vector<Object>(n);
687        DefaultMutableTreeNode node = null;
688        for (int i = 0; i < n; i++) {
689            node = (DefaultMutableTreeNode) root.getChildAt(i);
690            objList.add(node.getUserObject());
691        }
692
693        FileFormat newFile = null;
694        try {
695            newFile = openFile(filename, FileFormat.WRITE);
696        }
697        catch (Exception ex) {
698            toolkit.beep();
699            JOptionPane .showMessageDialog(this, ex.getMessage() + "\n" + filename, "HDFView", JOptionPane.ERROR_MESSAGE);
700            return;
701        }
702
703        if (newFile == null) {
704            return;
705        }
706
707        TreeNode pnode = newFile.getRootNode();
708
709        pasteObject(objList, pnode, newFile);
710        objList.setSize(0);
711
712        Group srcGroup = (Group) ((DefaultMutableTreeNode) root).getUserObject();
713        Group dstGroup = (Group) ((DefaultMutableTreeNode) newFile.getRootNode()).getUserObject();
714        Object[] parameter = new Object[2];
715        Class<?> classHOjbect = null;
716        Class<?>[] parameterClass = new Class[2];
717        Method method = null;
718
719        // copy attributes of the root group
720        try {
721            parameter[0] = srcGroup;
722            parameter[1] = dstGroup;
723            classHOjbect = Class.forName("hdf.object.HObject");
724            parameterClass[0] = parameterClass[1] = classHOjbect;
725            method = newFile.getClass().getMethod("copyAttributes", parameterClass);
726            method.invoke(newFile, parameter);
727        }
728        catch (Exception ex) {
729            toolkit.beep();
730            JOptionPane.showMessageDialog(this, ex, "HDFView", JOptionPane.ERROR_MESSAGE);
731        }
732
733        // update reference datasets
734        parameter[0] = srcGroup.getFileFormat();
735        parameter[1] = newFile;
736        parameterClass[0] = parameterClass[1] = parameter[0].getClass();
737        try {
738            method = newFile.getClass().getMethod("updateReferenceDataset", parameterClass);
739            method.invoke(newFile, parameter);
740        }
741        catch (Exception ex) {
742            toolkit.beep();
743            JOptionPane.showMessageDialog(this, ex, "HDFView", JOptionPane.ERROR_MESSAGE);
744        }
745    }
746
747    /** copy selected objects */
748    private void copyObject() {
749        log.trace("copyObject: start");
750        int op = -1;
751        if (moveFlag == true) {
752            String moveMsg = "Do you want to copy the selected object(s) instead ";
753            op = JOptionPane.showConfirmDialog(this, moveMsg, "Copy object", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
754        }
755
756        log.trace("cutObject(): op={}", op);
757        if (op == JOptionPane.NO_OPTION) {
758            return;
759        }
760        moveFlag = false;
761        currentSelectionsForMove = null;
762        objectsToCopy = getSelectedObjects();
763    }
764
765    /** move selected objects */
766    private void moveObject() {
767        log.trace("moveObject: start");
768        objectsToCopy = getSelectedObjects();
769        moveFlag = true;
770        currentSelectionsForMove = tree.getSelectionPaths();
771    }
772
773    /** delete selected objects */
774    private void cutObject() {
775        log.trace("cutObject: start");
776        int op = -1;
777        if (moveFlag == true) {
778            String moveMsg = "Do you want to delete the selected object(s) instead ";
779            op = JOptionPane.showConfirmDialog(this, moveMsg, "Delete object", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
780        }
781
782        log.trace("cutObject(): op={}", op);
783        if (op == JOptionPane.NO_OPTION) {
784            return;
785        }
786        moveFlag = false;
787        currentSelectionsForMove = null;
788        removeSelectedObjects();
789    }
790
791    /** paste selected objects */
792    private void pasteObject() {
793        log.trace("pasteObject(): start");
794        if (moveFlag == true) {
795            log.trace("pasteObject: move");
796            HObject theObj = null;
797            for (int i = 0; i < currentSelectionsForMove.length; i++) {
798                DefaultMutableTreeNode currentNode = (DefaultMutableTreeNode) (currentSelectionsForMove[i].getLastPathComponent());
799                theObj = (HObject) currentNode.getUserObject();
800
801                log.trace("pasteObject(): check if currentSelectionsForMove[{}] is open", i);
802                if (isObjectOpen(theObj)) {
803                    toolkit.beep();
804                    JOptionPane.showMessageDialog(this, "Cannot move the selected object: " + theObj
805                            + "\nThe dataset or dataset in the group is in use."
806                            + "\n\nPlease close the dataset(s) and try again.\n", "HDFView", JOptionPane.ERROR_MESSAGE);
807                    moveFlag = false;
808                    currentSelectionsForMove = null;
809                    objectsToCopy = null;
810                    return;
811                }
812            }
813        }
814
815        TreeNode pnode = selectedNode;
816
817        if ((objectsToCopy == null) || (objectsToCopy.size() <= 0) || (pnode == null)) {
818            return;
819        }
820
821        log.trace("pasteObject(): verify file properties");
822        FileFormat srcFile = ((HObject) objectsToCopy.get(0)).getFileFormat();
823        FileFormat dstFile = getSelectedFile();
824        FileFormat h5file = FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF5);
825        FileFormat h4file = FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF4);
826
827        if (srcFile == null) {
828            toolkit.beep();
829            JOptionPane.showMessageDialog(this, "Source file is null.", "HDFView", JOptionPane.ERROR_MESSAGE);
830            return;
831        }
832        else if (dstFile == null) {
833            toolkit.beep();
834            JOptionPane.showMessageDialog(this, "Destination file is null.", "HDFView", JOptionPane.ERROR_MESSAGE);
835            return;
836        }
837        else if (srcFile.isThisType(h4file) && dstFile.isThisType(h5file)) {
838            toolkit.beep();
839            JOptionPane.showMessageDialog(this, "Unsupported operation: cannot copy HDF4 object to HDF5 file",
840                    "HDFView", JOptionPane.ERROR_MESSAGE);
841            return;
842        }
843        else if (srcFile.isThisType(h5file) && dstFile.isThisType(h4file)) {
844            toolkit.beep();
845            JOptionPane.showMessageDialog(this, "Unsupported operation: cannot copy HDF5 object to HDF4 file",
846                    "HDFView", JOptionPane.ERROR_MESSAGE);
847            return;
848        }
849
850        if (moveFlag == true) {
851            log.trace("pasteObject(): check if src and dest are different files");
852            if (srcFile != dstFile) {
853                toolkit.beep();
854                JOptionPane.showMessageDialog(this, "Cannot move the selected object to different file", "HDFView",
855                        JOptionPane.ERROR_MESSAGE);
856                moveFlag = false;
857                currentSelectionsForMove = null;
858                objectsToCopy = null;
859                return;
860            }
861        }
862
863        if (pnode.isLeaf()) {
864            pnode = pnode.getParent();
865        }
866        Group pgroup = (Group) ((DefaultMutableTreeNode) pnode).getUserObject();
867        String fullPath = pgroup.getPath() + pgroup.getName();
868        if (pgroup.isRoot()) {
869            fullPath = HObject.separator;
870        }
871        log.trace("pasteObject(): fullPath={}",fullPath);
872
873        String msg = "";
874        int msgType = JOptionPane.QUESTION_MESSAGE;
875        if (srcFile.isThisType(h4file)) {
876            msg = "WARNING: object can not be deleted after it is copied.\n\n";
877            msgType = JOptionPane.WARNING_MESSAGE;
878        }
879
880        msg += "Do you want to copy the selected object(s) to \nGroup: " + fullPath + "\nFile: "
881                + dstFile.getFilePath();
882
883        int op = -1;
884        if (moveFlag == true) {
885            String moveMsg = "Do you want to move the selected object(s) to \nGroup: " + fullPath + "\nFile: "
886                    + dstFile.getFilePath();
887            op = JOptionPane.showConfirmDialog(this, moveMsg, "Move object", JOptionPane.YES_NO_OPTION, msgType);
888        }
889        else {
890            op = JOptionPane.showConfirmDialog(this, msg, "Copy object", JOptionPane.YES_NO_OPTION, msgType);
891        }
892
893        log.trace("pasteObject(): op={}", op);
894        if (op == JOptionPane.NO_OPTION) {
895            return;
896        }
897
898        pasteObject(objectsToCopy, pnode, dstFile);
899
900        // objectsToCopy = null;
901        if (moveFlag == true) {
902            removeSelectedObjects();
903            moveFlag = false;
904            currentSelectionsForMove = null;
905            objectsToCopy = null;
906        }
907        log.trace("pasteObject(): finish");
908    }
909
910    /** paste selected objects */
911    private void pasteObject(List<Object> objList, TreeNode pnode, FileFormat dstFile) {
912        if ((objList == null) || (objList.size() <= 0) || (pnode == null)) {
913            return;
914        }
915
916        ((HObject) objList.get(0)).getFileFormat();
917        Group pgroup = (Group) ((DefaultMutableTreeNode) pnode).getUserObject();
918        log.trace("pasteObject(...): start");
919
920        HObject theObj = null;
921        TreeNode newNode = null;
922        Iterator<Object> iterator = objList.iterator();
923        while (iterator.hasNext()) {
924            newNode = null;
925            theObj = (HObject) iterator.next();
926
927            if ((theObj instanceof Group) && ((Group) theObj).isRoot()) {
928                toolkit.beep();
929                JOptionPane.showMessageDialog(this, "Unsupported operation: cannot copy the root group", "HDFView",
930                        JOptionPane.ERROR_MESSAGE);
931                return;
932            }
933
934            // check if it creates infinite loop
935            Group pg = pgroup;
936            while (!pg.isRoot()) {
937                if (theObj.equals(pg)) {
938                    toolkit.beep();
939                    JOptionPane.showMessageDialog(this, "Unsupported operation: cannot copy a group to itself.",
940                            "HDFView", JOptionPane.ERROR_MESSAGE);
941                    return;
942                }
943                pg = pg.getParent();
944            }
945
946            try {
947                log.trace("pasteObject(...): dstFile.copy(theObj, pgroup, null)");
948                newNode = dstFile.copy(theObj, pgroup, null);
949            }
950            catch (Exception ex) {
951                toolkit.beep();
952                JOptionPane.showMessageDialog(this, ex, "HDFView", JOptionPane.ERROR_MESSAGE);
953                // newNode = null;
954            }
955
956            // add the node to the tree
957            if (newNode != null) {
958                insertNode(newNode, pnode);
959            }
960
961        } // while (iterator.hasNext())
962        log.trace("pasteObject(...): finish");
963    }
964
965    private void removeSelectedObjects() {
966        FileFormat theFile = getSelectedFile();
967        if (theFile.isThisType(FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF4))) {
968            toolkit.beep();
969            JOptionPane.showMessageDialog(this, "Unsupported operation: cannot delete HDF4 object.", "HDFView",
970                    JOptionPane.ERROR_MESSAGE);
971            return;
972        }
973        log.trace("removeSelectedObjects: start");
974
975        TreePath[] currentSelections = tree.getSelectionPaths();
976
977        if (moveFlag == true) {
978            currentSelections = currentSelectionsForMove;
979        }
980        if ((currentSelections == null) || (currentSelections.length <= 0)) {
981            return;
982        }
983        if (moveFlag != true) {
984            int op = JOptionPane.showConfirmDialog(this, "Do you want to remove all the selected object(s) ?",
985                    "Remove object", JOptionPane.YES_NO_OPTION);
986
987            if (op == JOptionPane.NO_OPTION) {
988                return;
989            }
990        }
991        HObject theObj = null;
992        for (int i = 0; i < currentSelections.length; i++) {
993            log.trace("removeSelectedObjects: loop[{}]",i);
994            DefaultMutableTreeNode currentNode = (DefaultMutableTreeNode) (currentSelections[i].getLastPathComponent());
995            theObj = (HObject) currentNode.getUserObject();
996
997            // cannot delete root
998            if (theObj instanceof Group) {
999                Group g = (Group) theObj;
1000                if (g.isRoot()) {
1001                    toolkit.beep();
1002                    JOptionPane.showMessageDialog(this, "Unsupported operation: cannot delete the file root.",
1003                            "HDFView", JOptionPane.ERROR_MESSAGE);
1004                    log.trace("removeSelectedObjects: cannot delete root");
1005                    return;
1006                }
1007            }
1008
1009            if (moveFlag != true) {
1010                if (isObjectOpen(theObj)) {
1011                    toolkit.beep();
1012                    JOptionPane.showMessageDialog(this, "Cannot delete the selected object: " + theObj
1013                            + "\nThe dataset or dataset in the group is in use."
1014                            + "\n\nPlease close the dataset(s) and try again.\n", "HDFView", JOptionPane.ERROR_MESSAGE);
1015                    log.trace("removeSelectedObjects: object in use");
1016                    continue;
1017                }
1018            }
1019
1020            try {
1021                theFile.delete(theObj);
1022            }
1023            catch (Exception ex) {
1024                toolkit.beep();
1025                JOptionPane.showMessageDialog(this, ex, "HDFView", JOptionPane.ERROR_MESSAGE);
1026                continue;
1027            }
1028
1029            if (theObj.equals(selectedObject)) {
1030                selectedObject = null;
1031            }
1032
1033            removeNode(currentNode);
1034        } // for (int i=0; i< currentSelections.length; i++) {
1035        log.trace("removeSelectedObjects: finish");
1036    }
1037
1038    private void removeNode(DefaultMutableTreeNode node) {
1039        if (node == null) {
1040            return;
1041        }
1042        log.trace("removeNode: start");
1043
1044        DefaultMutableTreeNode parentNode = (DefaultMutableTreeNode) (node.getParent());
1045        if (parentNode != null) {
1046            treeModel.removeNodeFromParent(node);
1047
1048            // add the two lines to fix bug in HDFView 1.2. Delete a subgroup and
1049            // then copy the group to another group, the deleted group still exists.
1050            Group pgroup = (Group) parentNode.getUserObject();
1051            pgroup.removeFromMemberList((HObject) node.getUserObject());
1052
1053            if (node.equals(selectedNode)) {
1054                selectedNode = null;
1055                selectedFile = null;
1056            }
1057        } // if (parentNode != null) {
1058        log.trace("removeNode: finish");
1059    }
1060
1061    private boolean isObjectOpen(HObject obj) {
1062        boolean isOpen = false;
1063
1064        if (obj instanceof Group) {
1065            Group g = (Group) obj;
1066            List<?> members = g.getMemberList();
1067            if ((members == null) || (members.size() == 0)) {
1068                isOpen = false;
1069            }
1070            else {
1071                int n = members.size();
1072                for (int i = 0; i < n; i++) {
1073                    HObject theObj = (HObject) members.get(i);
1074                    isOpen = (viewer.getDataView(theObj) != null);
1075                    if (isOpen) {
1076                        break;
1077                    }
1078                }
1079            }
1080        }
1081        else {
1082            if (viewer.getDataView(obj) == null) {
1083                isOpen = false;
1084            }
1085            else {
1086                isOpen = true;
1087            }
1088        }
1089
1090        return isOpen;
1091    }
1092
1093    /**
1094     * Returns a list of all user objects that traverses the subtree rooted at
1095     * this node in breadth-first order..
1096     *
1097     * @param node
1098     *            the node to start with.
1099     */
1100    private final List<Object> breadthFirstUserObjects(TreeNode node) {
1101        if (node == null) {
1102            return null;
1103        }
1104
1105        Vector<Object> list = new Vector<Object>();
1106        DefaultMutableTreeNode theNode = null;
1107        Enumeration<?> local_enum = ((DefaultMutableTreeNode) node).breadthFirstEnumeration();
1108        while (local_enum.hasMoreElements()) {
1109            theNode = (DefaultMutableTreeNode) local_enum.nextElement();
1110            list.add(theNode.getUserObject());
1111        }
1112
1113        return list;
1114    }
1115
1116    /**
1117     * Find first object that is matched by name.
1118     *
1119     * @param objName
1120     *            -- the object name.
1121     * @return the object if found, otherwise, returns null.
1122     */
1123    private final static HObject find(String objName, TreePath treePath, JTree tree) {
1124        HObject retObj = null;
1125        boolean isFound = false, isPrefix = false, isSuffix = false, isContain = false;
1126
1127        if (objName == null || objName.length() <= 0 || treePath == null) {
1128            return null;
1129        }
1130
1131        if (objName.equals("*")) return null;
1132
1133        if (objName.startsWith("*")) {
1134            isSuffix = true;
1135            objName = objName.substring(1, objName.length());
1136        }
1137
1138        if (objName.endsWith("*")) {
1139            isPrefix = true;
1140            objName = objName.substring(0, objName.length() - 1);
1141        }
1142
1143        if (isPrefix && isSuffix) {
1144            isContain = true;
1145            isPrefix = isSuffix = false;
1146        }
1147
1148        if (objName == null || objName.length() <= 0) return null;
1149
1150        DefaultMutableTreeNode node = (DefaultMutableTreeNode) treePath.getLastPathComponent();
1151        if (node == null) return null;
1152
1153        HObject obj = null;
1154        String theName = null;
1155        DefaultMutableTreeNode theNode = null;
1156        Enumeration<?> local_enum = node.breadthFirstEnumeration();
1157        while (local_enum.hasMoreElements()) {
1158            theNode = (DefaultMutableTreeNode) local_enum.nextElement();
1159            obj = (HObject) theNode.getUserObject();
1160            if (obj != null && (theName = obj.getName()) != null) {
1161                if (isPrefix)
1162                    isFound = theName.startsWith(objName);
1163                else if (isSuffix)
1164                    isFound = theName.endsWith(objName);
1165                else if (isContain)
1166                    isFound = theName.contains(objName);
1167                else
1168                    isFound = theName.equals(objName);
1169
1170                if (isFound) {
1171                    retObj = obj;
1172                    break;
1173                }
1174            }
1175        }
1176
1177        if (retObj != null) {
1178            TreePath dstPath = getTreePath(treePath, theNode, 0);
1179
1180            // tree.fireTreeExpanded(dstPath) ;
1181            tree.setSelectionPath(dstPath);
1182            tree.scrollPathToVisible(dstPath);
1183        }
1184
1185        return retObj;
1186    }
1187
1188    /**
1189     * Get the TreePath from the parent to the target node.
1190     *
1191     * @param parent
1192     *            -- the parent TreePath
1193     * @param node
1194     *            -- the target node
1195     * @param depth
1196     * @return the tree path if target node found, otherwise; returns null;
1197     */
1198    private static TreePath getTreePath(TreePath parent, TreeNode node, int depth) {
1199        if (node == null || parent == null || depth < 0) return null;
1200
1201        TreeNode theNode = (TreeNode) parent.getLastPathComponent();
1202        if (node == theNode) return parent;
1203
1204        if (theNode.getChildCount() >= 0) {
1205            for (Enumeration<?> e = theNode.children(); e.hasMoreElements();) {
1206                TreeNode n = (TreeNode) e.nextElement();
1207                TreePath path = parent.pathByAddingChild(n);
1208                TreePath result = getTreePath(path, node, depth + 1);
1209
1210                if (result != null) {
1211                    return result;
1212                }
1213            }
1214        }
1215
1216        return null;
1217    }
1218
1219    private void addGroup() {
1220        if ((selectedObject == null) || (selectedNode == null)) {
1221            return;
1222        }
1223
1224        Group pGroup = null;
1225        if (selectedObject instanceof Group) {
1226            pGroup = (Group) selectedObject;
1227        }
1228        else {
1229            pGroup = (Group) ((DefaultMutableTreeNode) selectedNode.getParent()).getUserObject();
1230        }
1231
1232        NewGroupDialog dialog = new NewGroupDialog((JFrame) viewer, pGroup,
1233                breadthFirstUserObjects(selectedObject.getFileFormat().getRootNode()));
1234        dialog.setVisible(true);
1235
1236        HObject obj = (HObject) dialog.getObject();
1237        if (obj == null) {
1238            return;
1239        }
1240
1241        Group pgroup = dialog.getParentGroup();
1242        try {
1243            this.addObject(obj, pgroup);
1244        }
1245        catch (Exception ex) {
1246            toolkit.beep();
1247            JOptionPane.showMessageDialog(this, ex, "HDFView", JOptionPane.ERROR_MESSAGE);
1248            return;
1249        }
1250    }
1251
1252    private void addDataset() {
1253        if ((selectedObject == null) || (selectedNode == null)) {
1254            return;
1255        }
1256
1257        Group pGroup = null;
1258        if (selectedObject instanceof Group) {
1259            pGroup = (Group) selectedObject;
1260        }
1261        else {
1262            pGroup = (Group) ((DefaultMutableTreeNode) selectedNode.getParent()).getUserObject();
1263        }
1264
1265        NewDatasetDialog dialog = new NewDatasetDialog((JFrame) viewer, pGroup,
1266                breadthFirstUserObjects(selectedObject.getFileFormat().getRootNode()));
1267        dialog.setVisible(true);
1268
1269        HObject obj = (HObject) dialog.getObject();
1270        if (obj == null) {
1271            return;
1272        }
1273
1274        Group pgroup = dialog.getParentGroup();
1275        try {
1276            addObject(obj, pgroup);
1277        }
1278        catch (Exception ex) {
1279            toolkit.beep();
1280            JOptionPane.showMessageDialog(this, ex, "HDFView", JOptionPane.ERROR_MESSAGE);
1281            return;
1282        }
1283    }
1284
1285    private void addImage() {
1286        if ((selectedObject == null) || (selectedNode == null)) {
1287            return;
1288        }
1289
1290        Group pGroup = null;
1291        if (selectedObject instanceof Group) {
1292            pGroup = (Group) selectedObject;
1293        }
1294        else {
1295            pGroup = (Group) ((DefaultMutableTreeNode) selectedNode.getParent()).getUserObject();
1296        }
1297
1298        NewImageDialog dialog = new NewImageDialog((JFrame) viewer, pGroup, breadthFirstUserObjects(selectedObject
1299                .getFileFormat().getRootNode()));
1300        dialog.setVisible(true);
1301
1302        HObject obj = (HObject) dialog.getObject();
1303        if (obj == null) {
1304            return;
1305        }
1306
1307        Group pgroup = dialog.getParentGroup();
1308        try {
1309            this.addObject(obj, pgroup);
1310        }
1311        catch (Exception ex) {
1312            toolkit.beep();
1313            JOptionPane.showMessageDialog(this, ex, "HDFView", JOptionPane.ERROR_MESSAGE);
1314            return;
1315        }
1316    }
1317
1318    private void addTable() {
1319        if ((selectedObject == null) || (selectedNode == null)) {
1320            return;
1321        }
1322
1323        Group pGroup = null;
1324        if (selectedObject instanceof Group) {
1325            pGroup = (Group) selectedObject;
1326        }
1327        else {
1328            pGroup = (Group) ((DefaultMutableTreeNode) selectedNode.getParent()).getUserObject();
1329        }
1330
1331        NewTableDataDialog dialog = new NewTableDataDialog((JFrame) viewer, pGroup,
1332                breadthFirstUserObjects(selectedObject.getFileFormat().getRootNode()));
1333        dialog.setVisible(true);
1334
1335        HObject obj = (HObject) dialog.getObject();
1336        if (obj == null) {
1337            return;
1338        }
1339
1340        Group pgroup = dialog.getParentGroup();
1341        try {
1342            addObject(obj, pgroup);
1343        }
1344        catch (Exception ex) {
1345            toolkit.beep();
1346            JOptionPane.showMessageDialog(this, ex, "HDFView", JOptionPane.ERROR_MESSAGE);
1347            return;
1348        }
1349    }
1350
1351    private void addDatatype() {
1352        if ((selectedObject == null) || (selectedNode == null)) {
1353            return;
1354        }
1355
1356        Group pGroup = null;
1357        if (selectedObject instanceof Group) {
1358            pGroup = (Group) selectedObject;
1359        }
1360        else {
1361            pGroup = (Group) ((DefaultMutableTreeNode) selectedNode.getParent()).getUserObject();
1362        }
1363
1364        NewDatatypeDialog dialog = new NewDatatypeDialog((JFrame) viewer, pGroup,
1365                breadthFirstUserObjects(selectedObject.getFileFormat().getRootNode()));
1366        dialog.setVisible(true);
1367
1368        HObject obj = (HObject) dialog.getObject();
1369        if (obj == null) {
1370            return;
1371        }
1372
1373        Group pgroup = dialog.getParentGroup();
1374        try {
1375            addObject(obj, pgroup);
1376        }
1377        catch (Exception ex) {
1378            toolkit.beep();
1379            JOptionPane.showMessageDialog(this, ex, "HDFView", JOptionPane.ERROR_MESSAGE);
1380            return;
1381        }
1382    }
1383
1384    private void addLink() {
1385        if ((selectedObject == null) || (selectedNode == null)) {
1386            return;
1387        }
1388
1389        Group pGroup = null;
1390        if (selectedObject instanceof Group) {
1391            pGroup = (Group) selectedObject;
1392        }
1393        else {
1394            pGroup = (Group) ((DefaultMutableTreeNode) selectedNode.getParent()).getUserObject();
1395        }
1396
1397        NewLinkDialog dialog = new NewLinkDialog((JFrame) viewer, pGroup, breadthFirstUserObjects(selectedObject
1398                .getFileFormat().getRootNode()));
1399        dialog.setVisible(true);
1400
1401        HObject obj = (HObject) dialog.getObject();
1402        if (obj == null) {
1403            return;
1404        }
1405
1406        Group pgroup = dialog.getParentGroup();
1407        try {
1408            addObject(obj, pgroup);
1409        }
1410        catch (Exception ex) {
1411            toolkit.beep();
1412            JOptionPane.showMessageDialog(this, ex, "HDFView", JOptionPane.ERROR_MESSAGE);
1413            return;
1414        }
1415    }
1416
1417    /** Save data as file. */
1418    private void saveAsFile() throws Exception {
1419        if (!(selectedObject instanceof Dataset) || (selectedObject == null) || (selectedNode == null)) {
1420            return;
1421        }
1422        Dataset dataset = (Dataset) selectedObject;
1423        final JFileChooser fchooser = new JFileChooser(dataset.getFile());
1424        fchooser.setFileFilter(DefaultFileFilter.getFileFilterText());
1425        // fchooser.changeToParentDirectory();
1426        File choosedFile = null;
1427
1428        if(binaryOrder == 99) {
1429            fchooser.setDialogTitle("Save Dataset Data To Text File --- " + dataset.getName());
1430
1431            choosedFile = new File(dataset.getName() + ".txt");
1432        }
1433        else {
1434            fchooser.setDialogTitle("Save Current Data To Binary File --- " + dataset.getName());
1435
1436            choosedFile = new File(dataset.getName() + ".bin");
1437        }
1438
1439        fchooser.setSelectedFile(choosedFile);
1440        int returnVal = fchooser.showSaveDialog(this);
1441
1442        if (returnVal != JFileChooser.APPROVE_OPTION) {
1443            return;
1444        }
1445
1446        choosedFile = fchooser.getSelectedFile();
1447        if (choosedFile == null) {
1448            return;
1449        }
1450        String fname = choosedFile.getAbsolutePath();
1451
1452        // check if the file is in use
1453        List<?> fileList = viewer.getTreeView().getCurrentFiles();
1454        if (fileList != null) {
1455            FileFormat theFile = null;
1456            Iterator<?> iterator = fileList.iterator();
1457            while (iterator.hasNext()) {
1458                theFile = (FileFormat) iterator.next();
1459                if (theFile.getFilePath().equals(fname)) {
1460                    toolkit.beep();
1461                    JOptionPane.showMessageDialog(this,
1462                            "Unable to save data to file \"" + fname + "\". \nThe file is being used.",
1463                            "Export Dataset", JOptionPane.ERROR_MESSAGE);
1464                    return;
1465                }
1466            }
1467        }
1468
1469        if (choosedFile.exists()) {
1470            int newFileFlag = JOptionPane.showConfirmDialog(this,
1471                    "File exists. Do you want to replace it ?",
1472                    "Export Dataset", JOptionPane.YES_NO_OPTION);
1473            if (newFileFlag == JOptionPane.NO_OPTION) {
1474                return;
1475            }
1476        }
1477
1478        boolean isH4 = selectedObject.getFileFormat().isThisType(FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF4));
1479
1480        if (isH4) {
1481            toolkit.beep();
1482            JOptionPane.showMessageDialog(this, "Cannot export HDF4 object.", "HDFView", JOptionPane.ERROR_MESSAGE);
1483            return;
1484        }
1485
1486        try {
1487            selectedObject.getFileFormat().exportDataset(fname, dataset.getFile(), dataset.getFullName(), binaryOrder);
1488        }
1489        catch (Exception ex) {
1490            toolkit.beep();
1491            JOptionPane.showMessageDialog(this, ex.getMessage(), "HDFView", JOptionPane.ERROR_MESSAGE);
1492        }
1493
1494        viewer.showStatus("Data save to: " + fname);
1495    }
1496
1497    private void renameObject() {
1498        int op = -1;
1499        if (moveFlag == true) {
1500            String moveMsg = "Do you want to rename the selected object(s) instead ";
1501            op = JOptionPane.showConfirmDialog(this, moveMsg, "Rename object", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
1502        }
1503
1504        log.trace("renameObject(): op={}", op);
1505        if (op == JOptionPane.NO_OPTION) {
1506            return;
1507        }
1508        moveFlag = false;
1509        currentSelectionsForMove = null;
1510
1511        if (selectedObject == null) {
1512            return;
1513        }
1514
1515        if ((selectedObject instanceof Group) && ((Group) selectedObject).isRoot()) {
1516            toolkit.beep();
1517            JOptionPane.showMessageDialog(this, "Cannot rename the root.", "HDFView", JOptionPane.ERROR_MESSAGE);
1518            return;
1519        }
1520
1521        boolean isH4 = selectedObject.getFileFormat().isThisType(FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF4));
1522
1523        if (isH4) {
1524            toolkit.beep();
1525            JOptionPane.showMessageDialog(this, "Cannot rename HDF4 object.", "HDFView", JOptionPane.ERROR_MESSAGE);
1526            return;
1527        }
1528
1529        String oldName = selectedObject.getName();
1530        String newName = (String) JOptionPane.showInputDialog(this, "Rename \"" + oldName + "\" to:", "Rename...",
1531                JOptionPane.INFORMATION_MESSAGE, null, null, oldName);
1532
1533        if (newName == null) {
1534            return;
1535        }
1536
1537        newName = newName.trim();
1538        if ((newName == null) || (newName.length() == 0) || newName.equals(oldName)) {
1539            return;
1540        }
1541
1542        try {
1543            selectedObject.setName(newName);
1544        }
1545        catch (Exception ex) {
1546            toolkit.beep();
1547            JOptionPane.showMessageDialog(this, ex.getMessage(), "HDFView", JOptionPane.ERROR_MESSAGE);
1548        }
1549    }
1550
1551    @SuppressWarnings("rawtypes")
1552    private void setLibVersionBounds() {
1553        Object[] lowValues = { "Earliest", "Latest" };
1554        Object[] highValues = { "Latest" };
1555        JComboBox lowComboBox = new JComboBox(lowValues);
1556        lowComboBox.setName("earliestversion");
1557        JComboBox highComboBox = new JComboBox(highValues);
1558        highComboBox.setName("latestversion");
1559
1560        Object[] msg = { "Earliest Version:", lowComboBox, "Latest Version:", highComboBox };
1561        Object[] options = { "Ok", "Cancel" };
1562        JOptionPane op = new JOptionPane(msg, JOptionPane.PLAIN_MESSAGE, JOptionPane.OK_CANCEL_OPTION, null, options);
1563
1564        op.setName("libselect");
1565        JDialog dialog = op.createDialog(this, "Set the library version bounds: ");
1566        dialog.setVisible(true);
1567
1568        String result = null;
1569        try {
1570            result = (String) op.getValue();
1571        }
1572        catch (Exception err) {
1573            // err.printStackTrace();
1574        }
1575
1576        if ((result != null) && (result.equals("Ok"))) {
1577            int low = -1;
1578            int high = 1;
1579            if ((lowComboBox.getSelectedItem()).equals("Earliest"))
1580                low = 0;
1581            else
1582                low = 1;
1583            try {
1584                selectedObject.getFileFormat().setLibBounds(low, high);
1585            }
1586            catch (Throwable err) {
1587                toolkit.beep();
1588                JOptionPane.showMessageDialog(this, err, "Error when setting lib version bounds",
1589                        JOptionPane.ERROR_MESSAGE);
1590                return;
1591            }
1592        }
1593        else
1594            return;
1595    }
1596
1597    // Implementing java.io.ActionListener
1598    public void actionPerformed(ActionEvent e) {
1599        String cmd = e.getActionCommand();
1600
1601        if (cmd.equals("Close file")) {
1602            ((HDFView) viewer).actionPerformed(e);
1603        }
1604        else if (cmd.equals("Reload file")) {
1605            ((HDFView) viewer).actionPerformed(e);
1606        }
1607        else if (cmd.equals("Add group")) {
1608            addGroup();
1609        }
1610        else if (cmd.equals("Add dataset")) {
1611            addDataset();
1612        }
1613        else if (cmd.equals("Add image")) {
1614            addImage();
1615        }
1616        else if (cmd.equals("Add table")) {
1617            addTable();
1618        }
1619        else if (cmd.equals("Add datatype")) {
1620            addDatatype();
1621        }
1622        else if (cmd.equals("Add link")) {
1623            addLink();
1624        }
1625        else if (cmd.equals("Save table as text")) {
1626            binaryOrder = 99;
1627            try {
1628                saveAsFile();
1629            }
1630            catch (Exception ex) {
1631                toolkit.beep();
1632                JOptionPane.showMessageDialog((JFrame) viewer, ex, "Export Dataset", JOptionPane.ERROR_MESSAGE);
1633            }
1634        }
1635        else if (cmd.startsWith("Save table as binary")) {
1636            if (cmd.equals("Save table as binary Native Order")) binaryOrder = 1;
1637            if (cmd.equals("Save table as binary Little Endian")) binaryOrder = 2;
1638            if (cmd.equals("Save table as binary Big Endian")) binaryOrder = 3;
1639            try {
1640                saveAsFile();
1641            }
1642            catch (Exception ex) {
1643                toolkit.beep();
1644                JOptionPane.showMessageDialog((JFrame) viewer, ex, "Export Dataset", JOptionPane.ERROR_MESSAGE);
1645            }
1646        }
1647        else if (cmd.startsWith("Open data")) {
1648            if (cmd.equals("Open data")) {
1649                isDefaultDisplay = true;
1650            }
1651            else {
1652                isDefaultDisplay = false;
1653            }
1654
1655            try {
1656                showDataContent(selectedObject);
1657            }
1658            catch (Throwable err) {
1659                toolkit.beep();
1660                JOptionPane.showMessageDialog(this, err, "HDFView", JOptionPane.ERROR_MESSAGE);
1661                return;
1662            }
1663        }
1664        else if (cmd.equals("Copy object")) {
1665            copyObject();
1666        }
1667        else if (cmd.equals("Paste object")) {
1668            pasteObject();
1669        }
1670        else if (cmd.equals("Cut object")) {
1671            cutObject();
1672        }
1673        else if (cmd.equals("Move object")) {
1674            moveObject();
1675        }
1676        else if (cmd.equals("Save object to file")) {
1677            if (selectedObject == null) {
1678                return;
1679            }
1680
1681            if ((selectedObject instanceof Group) && ((Group) selectedObject).isRoot()) {
1682                toolkit.beep();
1683                JOptionPane.showMessageDialog(this,
1684                        "Cannot save the root group.\nUse \"Save As\" from file menu to save the whole file",
1685                        "HDFView", JOptionPane.ERROR_MESSAGE);
1686                return;
1687            }
1688
1689            String filetype = FileFormat.FILE_TYPE_HDF4;
1690            boolean isH5 = selectedObject.getFileFormat().isThisType(
1691                    FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF5));
1692            if (isH5) {
1693                filetype = FileFormat.FILE_TYPE_HDF5;
1694            }
1695
1696            NewFileDialog dialog = new NewFileDialog((JFrame) viewer, selectedObject.getFileFormat().getParent(),
1697                    filetype, fileList);
1698            // dialog.show();
1699
1700            if (!dialog.isFileCreated()) {
1701                return;
1702            }
1703
1704            String filename = dialog.getFile();
1705            FileFormat dstFile = null;
1706            try {
1707                dstFile = openFile(filename, FileFormat.WRITE);
1708            }
1709            catch (Exception ex) {
1710                toolkit.beep();
1711                JOptionPane.showMessageDialog(this, ex.getMessage() + "\n" + filename, "HDFView",
1712                        JOptionPane.ERROR_MESSAGE);
1713            }
1714            List<Object> objList = new Vector<Object>(2);
1715            objList.add(selectedObject);
1716            pasteObject(objList, dstFile.getRootNode(), dstFile);
1717        }
1718        else if (cmd.equals("Rename object")) {
1719            renameObject();
1720        }
1721        else if (cmd.startsWith("Show object properties")) {
1722            if (cmd.equals("Show object properties")) {
1723                isDefaultDisplay = true;
1724            }
1725            else {
1726                isDefaultDisplay = false;
1727            }
1728
1729            try {
1730                showMetaData(selectedObject);
1731            }
1732            catch (Exception ex) {
1733                toolkit.beep();
1734                JOptionPane.showMessageDialog(this, ex, "HDFView", JOptionPane.ERROR_MESSAGE);
1735            }
1736        }
1737        else if (cmd.startsWith("Find")) {
1738            if (cmd.equals("Find")) {
1739                String findStr = currentSearchPhrase;
1740                if (findStr == null) findStr = "";
1741
1742                findStr = (String) JOptionPane.showInputDialog(this, "Find (e.g. O3Quality, O3*, or *Quality):",
1743                        "Find Object by Name", JOptionPane.PLAIN_MESSAGE, null, null, findStr);
1744
1745                if (findStr != null && findStr.length() > 0) currentSearchPhrase = findStr;
1746            }
1747
1748            find(currentSearchPhrase, selectedTreePath, tree);
1749        }
1750        else if (cmd.startsWith("Expand all")) {
1751            int row = 0;
1752            while (row < tree.getRowCount()) {
1753                tree.expandRow(row);
1754                row++;
1755            }
1756        }
1757        else if (cmd.startsWith("Collapse all")) {
1758            int row = tree.getRowCount() - 1;
1759            while (row >= 0) {
1760                tree.collapseRow(row);
1761                row--;
1762            }
1763        }
1764        else if (cmd.startsWith("Set Lib version bounds")) {
1765            setLibVersionBounds();
1766        }
1767        else if (cmd.startsWith("Change file indexing")) {
1768            ChangeIndexingDialog dialog = new ChangeIndexingDialog((JFrame) viewer, selectedFile);
1769            dialog.setVisible(true);
1770            if (dialog.isreloadFile()) {
1771                selectedFile.setIndexType(dialog.getIndexType());
1772                selectedFile.setIndexOrder(dialog.getIndexOrder());
1773                ((HDFView) viewer).reloadFile();
1774            }
1775        }
1776    }
1777
1778    public FileFormat reopenFile(FileFormat fileFormat) throws Exception {
1779        if (fileFormat.isThisType(FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF5))) {
1780            this.currentIndexType = fileFormat.getIndexType(null);
1781            this.currentIndexOrder = fileFormat.getIndexOrder(null);
1782        }
1783        if (fileFormat.isReadOnly())
1784            return openFile(fileFormat.getAbsolutePath(), FileFormat.READ);
1785        else
1786            return openFile(fileFormat.getAbsolutePath(), FileFormat.WRITE);
1787    }
1788
1789    /**
1790     * Opens a file and retrieves the file structure of the file. It also can be
1791     * used to create a new file by setting the accessID to FileFormat.CREATE.
1792     *
1793     * <p>
1794     * Subclasses must implement this function to take appropriate steps to open
1795     * a file.
1796     * </p>
1797     *
1798     * @param filename
1799     *            the name of the file to open.
1800     * @param accessID
1801     *            identifier for the file access. Valid value of accessID is:
1802     *            <ul>
1803     *            <li>FileFormat.READ --- allow read-only access to file.</li>
1804     *            <li>FileFormat.WRITE --- allow read and write access to file.</li>
1805     *            <li>FileFormat.CREATE --- create a new file.</li>
1806     *            </ul>
1807     *
1808     * @return the FileFormat of this file if successful; otherwise returns
1809     *         null.
1810     */
1811    public FileFormat openFile(String filename, int accessID) throws Exception {
1812        FileFormat fileFormat = null;
1813        MutableTreeNode fileRoot = null;
1814        boolean bNewFile = (FileFormat.OPEN_NEW == (accessID & FileFormat.OPEN_NEW));
1815        if(bNewFile)
1816            accessID = accessID - FileFormat.OPEN_NEW;
1817
1818        if (isFileOpen(filename)) {
1819            viewer.showStatus("File is in use");
1820            return null;
1821            // throw new UnsupportedOperationException("File is in use.");
1822        }
1823
1824        File tmpFile = new File(filename);
1825        if (!tmpFile.exists()) {
1826            throw new UnsupportedOperationException("File does not exist.");
1827        }
1828
1829        if (!tmpFile.canWrite()) {
1830            accessID = FileFormat.READ;
1831        }
1832
1833        Enumeration<?> keys = FileFormat.getFileFormatKeys();
1834
1835        String theKey = null;
1836        while (keys.hasMoreElements()) {
1837            theKey = (String) keys.nextElement();
1838            if (theKey.equals(FileFormat.FILE_TYPE_HDF4)) {
1839                try {
1840                    FileFormat h4format = FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF4);
1841                    if ((h4format != null) && h4format.isThisType(filename)) {
1842                        fileFormat = h4format.createInstance(filename, accessID);
1843                        break;
1844                    }
1845                }
1846                catch (Throwable err) {
1847                    log.debug("retrieves the file structure of {}:", filename, err);
1848                }
1849                continue;
1850            }
1851            else if (theKey.equals(FileFormat.FILE_TYPE_HDF5)) {
1852                try {
1853                    FileFormat h5format = FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF5);
1854                    if ((h5format != null) && h5format.isThisType(filename)) {
1855                        fileFormat = h5format.createInstance(filename, accessID);
1856                        break;
1857                    }
1858                }
1859                catch (Throwable err) {
1860                    log.debug("retrieves the file structure of {}:", filename, err);
1861                }
1862                continue;
1863            }
1864            else {
1865                try {
1866
1867                    FileFormat theformat = FileFormat.getFileFormat(theKey);
1868                    if (theformat.isThisType(filename)) {
1869                        fileFormat = theformat.createInstance(filename, accessID);
1870                        break;
1871                    }
1872                }
1873                catch (Throwable err) {
1874                    log.debug("retrieves the file structure of {}:", filename, err);
1875                }
1876            }
1877        }
1878
1879        if (fileFormat == null) {
1880            throw new java.io.IOException("Unsupported fileformat - " + filename);
1881        }
1882
1883        ((JFrame) viewer).setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
1884        try {
1885            fileFormat.setMaxMembers(ViewProperties.getMaxMembers());
1886            fileFormat.setStartMembers(ViewProperties.getStartMembers());
1887            if (fileFormat.isThisType(FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF5))) {
1888                if(bNewFile) {
1889                    currentIndexType = fileFormat.getIndexType(ViewProperties.getIndexType());
1890                    currentIndexOrder = fileFormat.getIndexOrder(ViewProperties.getIndexOrder());
1891                }
1892                fileFormat.setIndexType(currentIndexType);
1893                fileFormat.setIndexOrder(currentIndexOrder);
1894            }
1895
1896            fileFormat.open();
1897        }
1898        catch (Exception ex) {
1899            log.debug("fileformat init and open:", ex);
1900            fileFormat = null;
1901        }
1902        finally {
1903            ((JFrame) viewer).setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
1904        }
1905
1906        if (fileFormat == null) {
1907            throw new java.io.IOException("Failed to open file - " + filename);
1908        }
1909        else  {
1910            fileRoot = (MutableTreeNode) fileFormat.getRootNode();
1911            if (fileRoot != null) {
1912                insertNode(fileRoot, root);
1913
1914                int currentRowCount = tree.getRowCount();
1915                if (currentRowCount > 0) {
1916                    tree.expandRow(tree.getRowCount() - 1);
1917                }
1918
1919                fileList.add(fileFormat);
1920            }
1921        }
1922
1923        return fileFormat;
1924    }
1925
1926    /**
1927     * close a file
1928     *
1929     * @param file
1930     *            the file to close
1931     */
1932    public void closeFile(FileFormat file) throws Exception {
1933        if (file == null) {
1934            return;
1935        }
1936
1937        log.trace("DefaultTreeView:closeFile start");
1938        // find the file node in the tree and removed it from the tree first
1939        FileFormat theFile = null;
1940        DefaultMutableTreeNode theNode = null;
1941        Enumeration<?> enumeration = root.children();
1942        while (enumeration.hasMoreElements()) {
1943            theNode = (DefaultMutableTreeNode) enumeration.nextElement();
1944            Group g = (Group) theNode.getUserObject();
1945            theFile = g.getFileFormat();
1946
1947            if (theFile.equals(file)) {
1948                treeModel.removeNodeFromParent(theNode);
1949                try {
1950                    theFile.close();
1951                }
1952                catch (Exception ex) {
1953                    log.debug("close {}:", theFile.getFilePath(), ex);
1954                }
1955                fileList.remove(theFile);
1956                if (theFile.equals(selectedFile)) {
1957                    selectedFile = null;
1958                    selectedNode = null;
1959                }
1960                break;
1961            }
1962        } // while(enumeration.hasMoreElements())
1963        log.trace("DefaultTreeView:closeFile finish");
1964    }
1965
1966    /**
1967     * save a file
1968     *
1969     * @param file
1970     *            the file to save
1971     */
1972    public void saveFile(FileFormat file) throws Exception {
1973        if (file == null) {
1974            toolkit.beep();
1975            JOptionPane.showMessageDialog(this, "Select a file to save.", "HDFView", JOptionPane.ERROR_MESSAGE);
1976            return;
1977        }
1978
1979        boolean isH4 = file.isThisType(FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF4));
1980        boolean isH5 = file.isThisType(FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF5));
1981
1982        if (!(isH4 || isH5)) {
1983            toolkit.beep();
1984            JOptionPane.showMessageDialog(this, "Saving file is not supported for this file type", "HDFView",
1985                    JOptionPane.ERROR_MESSAGE);
1986            return;
1987        }
1988
1989        // write the change of the data into file before save the file
1990        List<?> views = ((HDFView) viewer).getDataViews();
1991        Object theView = null;
1992        TableView tableView = null;
1993        TextView textView = null;
1994        FileFormat theFile = null;
1995        if (views != null) {
1996            int n = views.size();
1997            for (int i = 0; i < n; i++) {
1998                theView = views.get(i);
1999                if (theView instanceof TableView) {
2000                    tableView = (TableView) theView;
2001                    theFile = tableView.getDataObject().getFileFormat();
2002                    if (file.equals(theFile)) {
2003                        tableView.updateValueInFile();
2004                    }
2005                }
2006                else if (theView instanceof TextView) {
2007                    textView = (TextView) theView;
2008                    theFile = textView.getDataObject().getFileFormat();
2009                    if (file.equals(theFile)) {
2010                        textView.updateValueInFile();
2011                    }
2012                }
2013            }
2014        }
2015
2016        if (isH5) {
2017            saveAsHDF5(file);
2018        }
2019        else if (isH4) {
2020            saveAsHDF4(file);
2021        }
2022    }
2023
2024    /**
2025     * Gets the selected the file. When multiple files are open, we need to know
2026     * which file is currently selected.
2027     *
2028     * @return the FileFormat of the selected file.
2029     */
2030    public FileFormat getSelectedFile() {
2031        return selectedFile;
2032    }
2033
2034    /**
2035     * Gets a list of selected object in the tree. Obtaining a list of current
2036     * selected objects is necessary for copy/paste/delete objects.
2037     *
2038     * @return a list of selected object in the tree.
2039     */
2040    public List<Object> getSelectedObjects() {
2041        TreePath[] paths = tree.getSelectionPaths();
2042        if ((paths == null) || (paths.length <= 0)) {
2043            return null;
2044        }
2045        log.trace("getSelectedObjects: start");
2046
2047        List<Object> objs = new Vector<Object>(paths.length);
2048        HObject theObject = null, parentObject;
2049        DefaultMutableTreeNode currentNode = null, parentNode = null;
2050        for (int i = 0; i < paths.length; i++) {
2051            currentNode = (DefaultMutableTreeNode) (paths[i].getLastPathComponent());
2052            theObject = (HObject) currentNode.getUserObject();
2053
2054            if (theObject != null) {
2055                log.trace("getSelectedObjects: theObject={}",theObject);
2056                objs.add(theObject);
2057                // removed the group from the selected list if some of its
2058                // members are selected
2059                // to avoid duplicated copy/paste when a group is pasted.
2060                parentNode = (DefaultMutableTreeNode) currentNode.getParent();
2061                parentObject = (HObject) parentNode.getUserObject();
2062                log.trace("getSelectedObjects: parentObject={}",parentObject);
2063                objs.remove(parentObject);
2064            }
2065        }
2066
2067        log.trace("getSelectedObjects: finish");
2068        return objs;
2069    }
2070
2071    /**
2072     * @return the current selected object in the tree.
2073     */
2074    public HObject getCurrentObject() {
2075        return selectedObject;
2076    }
2077
2078    /**
2079     * Display the content of a data object.
2080     *
2081     * @param dataObject
2082     *            the data object to display
2083     * 
2084     * @return the DataView that displays the data content
2085     * @throws Exception if an exception occurs while displaying data content
2086     */
2087    public DataView showDataContent(HObject dataObject) throws Exception {
2088        log.trace("showDataContent: start");
2089
2090        if ((dataObject == null) || !(dataObject instanceof Dataset)) {
2091            return null; // can only display dataset
2092        }
2093
2094        Dataset d = (Dataset) dataObject;
2095
2096        if (d.getRank() <= 0) {
2097            d.init();
2098        }
2099        boolean isText = ((d instanceof ScalarDS) && ((ScalarDS) d).isText());
2100        boolean isImage = ((d instanceof ScalarDS) && ((ScalarDS) d).isImage());
2101        boolean isDisplayTypeChar = false;
2102        boolean isTransposed = false;
2103        boolean isIndexBase1 = ViewProperties.isIndexBase1();
2104        BitSet bitmask = null;
2105        String dataViewName = null;
2106        log.trace("showDataContent: inited");
2107
2108        JInternalFrame theFrame = (JInternalFrame) viewer.getDataView(d);
2109
2110        if (isDefaultDisplay) {
2111
2112            if (theFrame != null) {
2113                theFrame.toFront();
2114                return null;
2115            }
2116
2117            if (isText) {
2118                dataViewName = (String) HDFView.getListOfTextView().get(0);
2119            }
2120            else if (isImage) {
2121                dataViewName = (String) HDFView.getListOfImageView().get(0);
2122            }
2123            else {
2124                dataViewName = (String) HDFView.getListOfTableView().get(0);
2125            }
2126        }
2127        else {
2128            DataOptionDialog dialog = new DataOptionDialog(viewer, d);
2129
2130            dialog.setVisible(true);
2131            if (dialog.isCancelled()) {
2132                return null;
2133            }
2134
2135            isImage = dialog.isImageDisplay();
2136            isDisplayTypeChar = dialog.isDisplayTypeChar();
2137            dataViewName = dialog.getDataViewName();
2138            isTransposed = dialog.isTransposed();
2139            bitmask = dialog.getBitmask();
2140            isIndexBase1 = dialog.isIndexBase1();
2141            isApplyBitmaskOnly = dialog.isApplyBitmaskOnly();
2142        }
2143        log.trace("showDataContent: {}", dataViewName);
2144
2145        // enables use of JHDF5 in JNLP (Web Start) applications, the system
2146        // class loader with reflection first.
2147        Class<?> theClass = null;
2148        try {
2149            theClass = Class.forName(dataViewName);
2150        }
2151        catch (Exception ex) {
2152            try {
2153                theClass = ViewProperties.loadExtClass().loadClass(dataViewName);
2154            }
2155            catch (Exception ex2) {
2156                theClass = null;
2157            }
2158        }
2159
2160        // use default dataview
2161        if (theClass == null) {
2162            log.trace("showDataContent: use default dataview");
2163            if (isText)
2164                dataViewName = "hdf.view.DefaultTextView";
2165            else if (isImage)
2166                dataViewName = "hdf.view.DefaultImageView";
2167            else
2168                dataViewName = "hdf.view.DefaultTableView";
2169            try {
2170                theClass = Class.forName(dataViewName);
2171            }
2172            catch (Exception ex) {
2173                log.debug("Class.forName {} failure: ", dataViewName, ex);
2174            }
2175        }
2176        Object theView = null;
2177        Object[] initargs = { viewer };
2178        HashMap<DATA_VIEW_KEY, Serializable> map = new HashMap<DATA_VIEW_KEY, Serializable>(8);
2179        map.put(ViewProperties.DATA_VIEW_KEY.INDEXBASE1, new Boolean(isIndexBase1));
2180        if (bitmask != null) {
2181            map.put(ViewProperties.DATA_VIEW_KEY.BITMASK, bitmask);
2182            if (isApplyBitmaskOnly) map.put(ViewProperties.DATA_VIEW_KEY.BITMASKOP, ViewProperties.BITMASK_OP.AND);
2183
2184            // create a copy of dataset
2185            ScalarDS d_copy = null;
2186            Constructor<? extends Dataset> constructor = null;
2187            Object[] paramObj = null;
2188            try {
2189                Class<?>[] paramClass = { FileFormat.class, String.class, String.class, long[].class };
2190                constructor = d.getClass().getConstructor(paramClass);
2191
2192                paramObj = new Object[] { d.getFileFormat(), d.getName(), d.getPath(), d.getOID() };
2193            }
2194            catch (Exception ex) {
2195                constructor = null;
2196            }
2197
2198            try {
2199                d_copy = (ScalarDS) constructor.newInstance(paramObj);
2200            }
2201            catch (Exception ex) {
2202                d_copy = null;
2203            }
2204            if (d_copy != null) {
2205                try {
2206                    d_copy.init();
2207                    log.trace("showDataContent: d_copy inited");
2208                    int rank = d.getRank();
2209                    System.arraycopy(d.getDims(), 0, d_copy.getDims(), 0, rank);
2210                    System.arraycopy(d.getStartDims(), 0, d_copy.getStartDims(), 0, rank);
2211                    System.arraycopy(d.getSelectedDims(), 0, d_copy.getSelectedDims(), 0, rank);
2212                    System.arraycopy(d.getStride(), 0, d_copy.getStride(), 0, rank);
2213                    System.arraycopy(d.getSelectedIndex(), 0, d_copy.getSelectedIndex(), 0, 3);
2214                }
2215                catch (Throwable ex) {
2216                    ex.printStackTrace();
2217                }
2218
2219                map.put(ViewProperties.DATA_VIEW_KEY.OBJECT, d_copy);
2220            }
2221        }
2222        if (dataViewName.startsWith("hdf.view.DefaultTableView")) {
2223            map.put(ViewProperties.DATA_VIEW_KEY.CHAR, new Boolean(isDisplayTypeChar));
2224            map.put(ViewProperties.DATA_VIEW_KEY.TRANSPOSED, new Boolean(isTransposed));
2225            Object[] tmpargs = { viewer, map };
2226            initargs = tmpargs;
2227        }
2228        else if (dataViewName.startsWith("hdf.view.DefaultImageView")) {
2229            map.put(ViewProperties.DATA_VIEW_KEY.CONVERTBYTE, new Boolean((bitmask != null)));
2230            Object[] tmpargs = { viewer, map };
2231            initargs = tmpargs;
2232        }
2233
2234        ((JFrame) viewer).setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
2235        try {
2236            theView = Tools.newInstance(theClass, initargs);
2237            log.trace("showDataContent: Tools.newInstance");
2238
2239            viewer.addDataView((DataView) theView);
2240        }
2241        finally {
2242            ((JFrame) viewer).setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
2243        }
2244
2245        log.trace("showDataContent: finish");
2246        return (DataView) theView;
2247    }
2248
2249    /**
2250     * Displays the meta data of a data object.
2251     *
2252     * @param dataObject
2253     *            the data object
2254     * @return the MetaDataView that displays the MetaData of the data object
2255     * @throws Exception if an exception occurs while displaying metadata of the object
2256     */
2257    public MetaDataView showMetaData(HObject dataObject) throws Exception {
2258        if (dataObject == null) {
2259            return null;
2260        }
2261
2262        List<?> metaDataViewList = HDFView.getListOfMetaDataView();
2263        if ((metaDataViewList == null) || (metaDataViewList.size() <= 0)) {
2264            return null;
2265        }
2266
2267        int n = metaDataViewList.size();
2268        String className = (String) metaDataViewList.get(0);
2269
2270        if (!isDefaultDisplay && (n > 1)) {
2271            className = (String) JOptionPane.showInputDialog(this, "Select MetaDataView", "HDFView",
2272                    JOptionPane.INFORMATION_MESSAGE, null, metaDataViewList.toArray(), className);
2273        }
2274
2275        // enables use of JHDF5 in JNLP (Web Start) applications, the system
2276        // class loader with reflection first.
2277        Class<?> theClass = null;
2278        try {
2279            theClass = Class.forName(className);
2280        }
2281        catch (Exception ex) {
2282            theClass = ViewProperties.loadExtClass().loadClass(className);
2283        }
2284
2285        Object[] initargs = { viewer };
2286        MetaDataView dataView = (MetaDataView) Tools.newInstance(theClass, initargs);
2287
2288        return dataView;
2289    }
2290
2291    /**
2292     * Adds a new data object to the file.
2293     *
2294     * @param newObject
2295     *            the new object to add.
2296     * @param parentGroup
2297     *            the parent group the object is to add to.
2298     * @throws Exception if an exception occurs while adding a new data object to the file
2299     */
2300    public void addObject(HObject newObject, Group parentGroup) throws Exception {
2301        if ((newObject == null) || (parentGroup == null)) {
2302            return;
2303        }
2304
2305        TreeNode pnode = findTreeNode(parentGroup);
2306        TreeNode newnode = null;
2307        if (newObject instanceof Group) {
2308            newnode = new DefaultMutableTreeNode(newObject) {
2309                private static final long serialVersionUID = -8852535261445958398L;
2310
2311                public boolean isLeaf() {
2312                    return false;
2313                }
2314            };
2315        }
2316        else {
2317            newnode = new DefaultMutableTreeNode(newObject);
2318        }
2319
2320        treeModel.insertNodeInto((DefaultMutableTreeNode) newnode, (DefaultMutableTreeNode) pnode,
2321                pnode.getChildCount());
2322    }
2323
2324    /**
2325     * Returns the JTree which holds the file structure.
2326     *
2327     * @return the JTree which holds the file structure.
2328     */
2329    public JTree getTree() {
2330        return tree;
2331    }
2332
2333    /**
2334     * Returns the list of current open files..
2335     */
2336    public List<FileFormat> getCurrentFiles() {
2337        return fileList;
2338    }
2339
2340    /**
2341     * Returns the tree node that contains the given data object.
2342     */
2343    public TreeNode findTreeNode(HObject obj) {
2344        if (obj == null) {
2345            return null;
2346        }
2347
2348        TreeNode theFileRoot = obj.getFileFormat().getRootNode();
2349        if (theFileRoot == null) {
2350            return null;
2351        }
2352
2353        DefaultMutableTreeNode theNode = null;
2354        HObject theObj = null;
2355        Enumeration<?> local_enum = ((DefaultMutableTreeNode) theFileRoot).breadthFirstEnumeration();
2356        while (local_enum.hasMoreElements()) {
2357            theNode = (DefaultMutableTreeNode) local_enum.nextElement();
2358            theObj = (HObject) theNode.getUserObject();
2359            if (theObj == null) {
2360                continue;
2361            }
2362            else if (theObj.equals(obj)) {
2363                return theNode;
2364            }
2365        }
2366
2367        return null;
2368    }
2369
2370    /**
2371     * This class is used to change the default icons for tree nodes.
2372     *
2373     * @see javax.swing.tree.DefaultTreeCellRenderer
2374     */
2375    private class HTreeCellRenderer extends DefaultTreeCellRenderer {
2376        private static final long serialVersionUID = -9030708781106435297L;
2377        private Icon              h4Icon, h4IconR, h5Icon, h5IconR, datasetIcon, imageIcon, tableIcon, textIcon, openFolder, closeFolder,
2378        datasetIconA, imageIconA, tableIconA, textIconA, openFolderA, closeFolderA, datatypeIcon,
2379        datatypeIconA, questionIcon;
2380
2381        private HTreeCellRenderer() {
2382            super();
2383
2384            openFolder = ViewProperties.getFolderopenIcon();
2385            closeFolder = ViewProperties.getFoldercloseIcon();
2386            datasetIcon = ViewProperties.getDatasetIcon();
2387            imageIcon = ViewProperties.getImageIcon();
2388            h4Icon = ViewProperties.getH4Icon();
2389            h4IconR = ViewProperties.getH4IconR();
2390            h5Icon = ViewProperties.getH5Icon();
2391            h5IconR = ViewProperties.getH5IconR();
2392            tableIcon = ViewProperties.getTableIcon();
2393            textIcon = ViewProperties.getTextIcon();
2394
2395            openFolderA = ViewProperties.getFolderopenIconA();
2396            closeFolderA = ViewProperties.getFoldercloseIconA();
2397            datasetIconA = ViewProperties.getDatasetIconA();
2398            imageIconA = ViewProperties.getImageIconA();
2399            tableIconA = ViewProperties.getTableIconA();
2400            textIconA = ViewProperties.getTextIconA();
2401            datatypeIcon = ViewProperties.getDatatypeIcon();
2402            datatypeIconA = ViewProperties.getDatatypeIconA();
2403
2404            questionIcon = ViewProperties.getQuestionIcon();
2405
2406            if (openFolder != null) {
2407                openIcon = openFolder;
2408            }
2409            else {
2410                openFolder = this.openIcon;
2411            }
2412
2413            if (closeFolder != null) {
2414                closedIcon = closeFolder;
2415            }
2416            else {
2417                closeFolder = closedIcon;
2418            }
2419
2420            if (datasetIcon == null) {
2421                datasetIcon = leafIcon;
2422            }
2423            if (imageIcon == null) {
2424                imageIcon = leafIcon;
2425            }
2426            if (tableIcon == null) {
2427                tableIcon = leafIcon;
2428            }
2429            if (textIcon == null) {
2430                textIcon = leafIcon;
2431            }
2432            if (h4Icon == null) {
2433                h4Icon = leafIcon;
2434            }
2435            if (h4IconR == null) {
2436                h4IconR = leafIcon;
2437            }
2438            if (h5Icon == null) {
2439                h5Icon = leafIcon;
2440            }
2441            if (h5IconR == null) {
2442                h5IconR = leafIcon;
2443            }
2444            if (datatypeIcon == null) {
2445                datatypeIcon = leafIcon;
2446            }
2447
2448            if (questionIcon == null) {
2449                questionIcon = leafIcon;
2450            }
2451
2452            if (openFolderA == null) {
2453                openFolderA = openFolder;
2454            }
2455            if (closeFolderA == null) {
2456                closeFolderA = closeFolder;
2457            }
2458            if (datasetIconA == null) {
2459                datasetIconA = datasetIcon;
2460            }
2461            if (imageIconA == null) {
2462                imageIconA = imageIcon;
2463            }
2464            if (tableIconA == null) {
2465                tableIconA = tableIcon;
2466            }
2467            if (textIconA == null) {
2468                textIconA = textIcon;
2469            }
2470            if (datatypeIconA == null) {
2471                datatypeIconA = datatypeIcon;
2472            }
2473        }
2474
2475        public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded,
2476                boolean leaf, int row, boolean hasFocus) {
2477            HObject theObject = (HObject) ((DefaultMutableTreeNode) value).getUserObject();
2478
2479            if (theObject == null)
2480                return super.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus);
2481
2482            boolean hasAttribute = theObject.hasAttribute();
2483
2484            if (theObject instanceof Dataset) {
2485                if (theObject instanceof ScalarDS) {
2486                    ScalarDS sd = (ScalarDS) theObject;
2487                    if (sd.isImage()) {
2488                        if (hasAttribute) {
2489                            leafIcon = imageIconA;
2490                        }
2491                        else {
2492                            leafIcon = imageIcon;
2493                        }
2494                    }
2495                    else if (sd.isText()) {
2496                        if (hasAttribute) {
2497                            leafIcon = textIconA;
2498                        }
2499                        else {
2500                            leafIcon = textIcon;
2501                        }
2502                    }
2503                    else {
2504                        if (hasAttribute) {
2505                            leafIcon = datasetIconA;
2506                        }
2507                        else {
2508                            leafIcon = datasetIcon;
2509                        }
2510
2511                    }
2512                }
2513                else if (theObject instanceof CompoundDS) {
2514                    if (hasAttribute) {
2515                        leafIcon = tableIconA;
2516                    }
2517                    else {
2518                        leafIcon = tableIcon;
2519                    }
2520                }
2521            }
2522            else if (theObject instanceof Group) {
2523                Group g = (Group) theObject;
2524
2525                if (hasAttribute) {
2526                    openIcon = openFolderA;
2527                    closedIcon = closeFolderA;
2528                }
2529                else {
2530                    openIcon = openFolder;
2531                    closedIcon = closeFolder;
2532                }
2533
2534                if (g.isRoot()) {
2535                    if (g.getFileFormat().isThisType(FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF5))) {
2536                        if(g.getFileFormat().isReadOnly())
2537                            openIcon = closedIcon = h5IconR;
2538                        else
2539                            openIcon = closedIcon = h5Icon;
2540                    }
2541                    else if (g.getFileFormat().isThisType(FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF4))) {
2542                        if(g.getFileFormat().isReadOnly())
2543                            openIcon = closedIcon = h4IconR;
2544                        else
2545                            openIcon = closedIcon = h4Icon;
2546                    }
2547                }
2548            }
2549            else if (theObject instanceof Datatype) {
2550                Datatype t = (Datatype) theObject;
2551
2552                if (hasAttribute) {
2553                    leafIcon = datatypeIconA;
2554                }
2555                else {
2556                    leafIcon = datatypeIcon;
2557                }
2558            }
2559
2560            else {
2561                leafIcon = questionIcon;
2562            }
2563
2564            return super.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus);
2565        }
2566    } // private class HTreeCellRenderer
2567
2568    /**
2569     * Handle mouse clicks on data object in the tree view. A right mouse-click
2570     * to show the popup menu for user choice. A double left-mouse-click to
2571     * display the data content. A single left-mouse-click to select the current
2572     * data object.
2573     */
2574    private class HTreeMouseAdapter extends MouseAdapter {
2575        // public void mousePressed(MouseEvent e)
2576        public void mouseReleased(MouseEvent e) {
2577            TreePath selPath = tree.getPathForLocation(e.getX(), e.getY());
2578            if (selPath == null) {
2579                return;
2580            }
2581
2582            DefaultMutableTreeNode theNode = (DefaultMutableTreeNode) selPath.getLastPathComponent();
2583            if (!theNode.equals(selectedNode)) {
2584                selectedTreePath = selPath;
2585                selectedNode = theNode;
2586                selectedObject = ((HObject) (selectedNode.getUserObject()));
2587                FileFormat theFile = selectedObject.getFileFormat();
2588                if ((theFile != null) && !theFile.equals(selectedFile)) {
2589                    // a different file is selected, handle only one file a time
2590                    selectedFile = theFile;
2591                    tree.clearSelection();
2592                    tree.setSelectionPath(selPath);
2593                }
2594
2595                viewer.mouseEventFired(e);
2596            }
2597
2598            // ***************************************************************
2599            // Different platforms have different ways to show popups
2600            // if (e.getModifiers() == MouseEvent.BUTTON3_MASK) works for all
2601            // but mac
2602            // mouseReleased() and e.isPopupTrigger() work on windows and mac
2603            // but not unix,
2604            // mouseClicked() and e.isPopupTrigger() work on unix and mac but
2605            // not windows,
2606            // to solve the problem, we use both.
2607            // 7/25/06 bug 517. e.isPopupTrigger does not work on one mouse Mac.
2608            // add (MouseEvent.BUTTON1_MASK|MouseEvent.CTRL_MASK) for MAC
2609            int eMod = e.getModifiers();
2610            if (e.isPopupTrigger()
2611                    || (eMod == MouseEvent.BUTTON3_MASK)
2612                    || (System.getProperty("os.name").startsWith("Mac") && (eMod == (MouseEvent.BUTTON1_MASK | Toolkit.getDefaultToolkit().getMenuShortcutKeyMask())))) {
2613                int selRow = tree.getRowForLocation(e.getX(), e.getY());
2614
2615                if (!tree.isRowSelected(selRow)) {
2616                    // reselect the node
2617                    tree.clearSelection();
2618                    tree.setSelectionRow(selRow);
2619                }
2620                showPopupMenu(e);
2621            }
2622            // double click to open data content
2623            else if (e.getClickCount() == 2) {
2624                isDefaultDisplay = true;
2625                try {
2626                    showDataContent(selectedObject);
2627                }
2628                catch (Exception ex) {
2629                }
2630            }
2631        } // public void mousePressed(MouseEvent e)
2632    } // private class HTreeMouseAdapter extends MouseAdapter
2633
2634    /**
2635     * Handle key pressed event.
2636     */
2637    private class HTreeKeyAdapter extends KeyAdapter {
2638
2639        @Override
2640        public void keyTyped(KeyEvent e) {
2641        }
2642
2643        @Override
2644        public void keyPressed(KeyEvent e) {
2645        }
2646
2647        @Override
2648        public void keyReleased(KeyEvent e) {
2649            int key = e.getKeyCode();
2650            if (key == KeyEvent.VK_KP_LEFT || key == KeyEvent.VK_KP_RIGHT || key == KeyEvent.VK_KP_UP
2651                    || key == KeyEvent.VK_KP_DOWN || key == KeyEvent.VK_LEFT || key == KeyEvent.VK_RIGHT
2652                    || key == KeyEvent.VK_UP || key == KeyEvent.VK_DOWN) {
2653
2654                TreePath selPath = ((JTree) e.getComponent()).getSelectionPath();
2655                if (selPath == null) {
2656                    return;
2657                }
2658
2659                DefaultMutableTreeNode theNode = (DefaultMutableTreeNode) selPath.getLastPathComponent();
2660
2661                if (!theNode.equals(selectedNode)) {
2662                    selectedTreePath = selPath;
2663                    selectedNode = theNode;
2664                    selectedObject = ((HObject) (selectedNode.getUserObject()));
2665                    FileFormat theFile = selectedObject.getFileFormat();
2666                    if ((theFile != null) && !theFile.equals(selectedFile)) {
2667                        // a different file is selected, handle only one file a
2668                        // time
2669                        selectedFile = theFile;
2670                        tree.clearSelection();
2671                        tree.setSelectionPath(selPath);
2672                    }
2673
2674                    ((HDFView) viewer).showMetaData(selectedObject);
2675                }
2676            }
2677        }
2678    }
2679
2680    /**
2681     * ChangeIndexingDialog displays file index options.
2682     */
2683    private class ChangeIndexingDialog extends JDialog implements ActionListener {
2684        private static final long serialVersionUID = 1048114401768228742L;
2685
2686        private JRadioButton checkIndexType;
2687        private JRadioButton checkIndexOrder;
2688        private JRadioButton checkIndexNative;
2689
2690        private boolean reloadFile;
2691
2692        private FileFormat selectedFile;
2693        private int indexType;
2694        private int indexOrder;
2695
2696        /**
2697         * constructs an UserOptionsDialog.
2698         *
2699         * @param view
2700         *            The HDFView.
2701         */
2702        private ChangeIndexingDialog(JFrame view, FileFormat viewSelectedFile) {
2703            super(view, "Index Options", true);
2704
2705            selectedFile = viewSelectedFile;
2706            indexType = selectedFile.getIndexType(null);
2707            indexOrder = selectedFile.getIndexOrder(null);
2708            reloadFile = false;
2709
2710            JPanel contentPane = (JPanel) getContentPane();
2711            contentPane.setLayout(new BorderLayout(8, 8));
2712            contentPane.setBorder(BorderFactory.createEmptyBorder(15, 5, 5, 5));
2713
2714            JPanel indexP = new JPanel();
2715            TitledBorder tborder = new TitledBorder("Index Options");
2716            tborder.setTitleColor(Color.darkGray);
2717            indexP.setBorder(tborder);
2718            indexP.setLayout(new GridLayout(2, 1, 10, 10));
2719            indexP.setBorder(new SoftBevelBorder(BevelBorder.LOWERED));
2720            contentPane.add(indexP);
2721
2722            JPanel pType = new JPanel();
2723            tborder = new TitledBorder("Indexing Type");
2724            tborder.setTitleColor(Color.darkGray);
2725            pType.setBorder(tborder);
2726            pType.setLayout(new GridLayout(1, 2, 8, 8));
2727            checkIndexType = new JRadioButton("By Name", (indexType) == selectedFile.getIndexType("H5_INDEX_NAME"));
2728            checkIndexType.setName("Index by Name");
2729            pType.add(checkIndexType);
2730            JRadioButton checkIndexCreateOrder = new JRadioButton("By Creation Order", (indexType) == selectedFile.getIndexType("H5_INDEX_CRT_ORDER"));
2731            checkIndexCreateOrder.setName("Index by Creation Order");
2732            pType.add(checkIndexCreateOrder);
2733            ButtonGroup bTypegrp = new ButtonGroup();
2734            bTypegrp.add(checkIndexType);
2735            bTypegrp.add(checkIndexCreateOrder);
2736            indexP.add(pType);
2737
2738            JPanel pOrder = new JPanel();
2739            tborder = new TitledBorder("Indexing Order");
2740            tborder.setTitleColor(Color.darkGray);
2741            pOrder.setBorder(tborder);
2742            pOrder.setLayout(new GridLayout(1, 3, 8, 8));
2743            checkIndexOrder = new JRadioButton("Increments", (indexOrder) == selectedFile.getIndexOrder("H5_ITER_INC"));
2744            checkIndexOrder.setName("Index Increments");
2745            pOrder.add(checkIndexOrder);
2746            JRadioButton checkIndexDecrement = new JRadioButton("Decrements", (indexOrder) == selectedFile.getIndexOrder("H5_ITER_DEC"));
2747            checkIndexDecrement.setName("Index Decrements");
2748            pOrder.add(checkIndexDecrement);
2749            checkIndexNative = new JRadioButton("Native", (indexOrder) == selectedFile.getIndexOrder("H5_ITER_NATIVE"));
2750            checkIndexNative.setName("Index Native");
2751            pOrder.add(checkIndexNative);
2752            ButtonGroup bOrdergrp = new ButtonGroup();
2753            bOrdergrp.add(checkIndexOrder);
2754            bOrdergrp.add(checkIndexDecrement);
2755            bOrdergrp.add(checkIndexNative);
2756            indexP.add(pOrder);
2757
2758            JPanel buttonP = new JPanel();
2759            JButton b = new JButton("Reload File");
2760            b.setName("Reload File");
2761            b.setActionCommand("Reload File");
2762            b.addActionListener(this);
2763            buttonP.add(b);
2764            b = new JButton("Cancel");
2765            b.setName("Cancel");
2766            b.setActionCommand("Cancel");
2767            b.addActionListener(this);
2768            buttonP.add(b);
2769
2770            contentPane.add("Center", indexP);
2771            contentPane.add("South", buttonP);
2772
2773            // locate the parent dialog
2774            Point l = getParent().getLocation();
2775            l.x += 250;
2776            l.y += 80;
2777            setLocation(l);
2778            validate();
2779            pack();
2780        }
2781
2782        public void setVisible(boolean b) {
2783            super.setVisible(b);
2784        }
2785
2786        public void actionPerformed(ActionEvent e) {
2787            String cmd = e.getActionCommand();
2788
2789            if (cmd.equals("Reload File")) {
2790                setIndexOptions();
2791                setVisible(false);
2792            }
2793            else if (cmd.equals("Cancel")) {
2794                reloadFile = false;
2795                setVisible(false);
2796            }
2797        }
2798
2799        private void setIndexOptions() {
2800            if (checkIndexType.isSelected())
2801                selectedFile.setIndexType(selectedFile.getIndexType("H5_INDEX_NAME"));
2802            else
2803                selectedFile.setIndexType(selectedFile.getIndexType("H5_INDEX_CRT_ORDER"));
2804            indexType = selectedFile.getIndexType(null);
2805
2806            if (checkIndexOrder.isSelected())
2807                selectedFile.setIndexOrder(selectedFile.getIndexOrder("H5_ITER_INC"));
2808            else if (checkIndexNative.isSelected())
2809                selectedFile.setIndexOrder(selectedFile.getIndexOrder("H5_ITER_NATIVE"));
2810            else
2811                selectedFile.setIndexOrder(selectedFile.getIndexOrder("H5_ITER_DEC"));
2812            indexOrder = selectedFile.getIndexOrder(null);
2813
2814            reloadFile = true;
2815        }
2816
2817        public int getIndexType() {
2818            return indexType;
2819        }
2820
2821        public int getIndexOrder() {
2822            return indexOrder;
2823        }
2824
2825        public boolean isreloadFile() {
2826            return reloadFile;
2827        }
2828    }
2829}