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.Dimension;
019import java.awt.Frame;
020import java.awt.GridLayout;
021import java.awt.Insets;
022import java.awt.Point;
023import java.awt.Toolkit;
024import java.awt.event.ActionEvent;
025import java.awt.event.ActionListener;
026import java.awt.event.ItemEvent;
027import java.awt.event.ItemListener;
028import java.awt.event.KeyEvent;
029import java.awt.event.KeyListener;
030import java.util.Iterator;
031import java.util.List;
032import java.util.Vector;
033
034import javax.swing.BorderFactory;
035import javax.swing.JButton;
036import javax.swing.JCheckBox;
037import javax.swing.JComboBox;
038import javax.swing.JDialog;
039import javax.swing.JLabel;
040import javax.swing.JOptionPane;
041import javax.swing.JPanel;
042import javax.swing.JTextField;
043import javax.swing.border.TitledBorder;
044import javax.swing.text.AttributeSet;
045import javax.swing.text.BadLocationException;
046import javax.swing.text.PlainDocument;
047
048import hdf.object.DataFormat;
049import hdf.object.FileFormat;
050import hdf.object.Group;
051import hdf.object.HObject;
052
053/**
054 * NewGroupDialog shows a message dialog requesting user input for creating a new HDF4/5 group.
055 * 
056 * @author Peter X. Cao
057 * @version 2.4 9/6/2007
058 */
059public class NewGroupDialog extends JDialog implements ActionListener, ItemListener, KeyListener {
060    private static final long serialVersionUID = 7340860373483987075L;
061
062    private JTextField nameField;
063
064    private JTextField compactField;
065
066    private JTextField indexedField;
067
068    @SuppressWarnings("rawtypes")
069    private JComboBox parentChoice;
070
071    private JCheckBox useCreationOrder;
072
073    private JCheckBox setLinkStorage;
074
075    @SuppressWarnings("rawtypes")
076    private JComboBox orderFlags;
077
078    /** a list of current groups */
079    private List<Group> groupList;
080
081    private HObject newObject;
082
083    private FileFormat fileFormat;
084
085    private final Toolkit toolkit;
086
087    private int creationOrder;
088
089    private JPanel useCreationOrderJPanel;
090
091    private JPanel setLinkStorageJPanel;
092
093    private JButton moreButton;
094
095    private JPanel labelPanel;
096
097    private JPanel textPanel;
098
099    private JPanel contentPane;
100
101    private JButton creationOrderHelpButton;
102
103    private JButton storageTypeHelpButton;
104
105    private boolean isH5;
106
107    /**
108     * Constructs NewGroupDialog with specified list of possible parent groups.
109     * 
110     * @param owner
111     *            the owner of the input
112     * @param pGroup
113     *            the parent group which the new group is added to.
114     * @param objs
115     *            the list of all objects.
116     */
117    @SuppressWarnings({ "rawtypes", "unchecked" })
118    public NewGroupDialog(Frame owner, Group pGroup, List<?> objs) {
119        super(owner, "New Group...", true);
120
121        newObject = null;
122
123        fileFormat = pGroup.getFileFormat();
124        isH5 = pGroup.getFileFormat().isThisType(FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF5));
125        toolkit = Toolkit.getDefaultToolkit();
126
127        parentChoice = new JComboBox();
128        groupList = new Vector<Group>();
129        Object obj = null;
130        Iterator<?> iterator = objs.iterator();
131        while (iterator.hasNext()) {
132            obj = iterator.next();
133            if (obj instanceof Group) {
134                groupList.add((Group) obj);
135                Group g = (Group) obj;
136                if (g.isRoot()) {
137                    parentChoice.addItem(HObject.separator);
138                }
139                else {
140                    parentChoice.addItem(g.getPath() + g.getName() + HObject.separator);
141                }
142            }
143        }
144
145        if (pGroup.isRoot()) {
146            parentChoice.setSelectedItem(HObject.separator);
147        }
148        else {
149            parentChoice.setSelectedItem(pGroup.getPath() + pGroup.getName() + HObject.separator);
150        }
151
152        orderFlags = new JComboBox();
153        orderFlags.addItem("Tracked");
154        orderFlags.addItem("Tracked+Indexed");
155
156        contentPane = (JPanel) getContentPane();
157        contentPane.setLayout(new BorderLayout(5, 5));
158        contentPane.setBorder(BorderFactory.createEmptyBorder(15, 5, 5, 5));
159        int w = 400 + (ViewProperties.getFontSize() - 12) * 15;
160        int h = 150 + (ViewProperties.getFontSize() - 12) * 10;
161        contentPane.setPreferredSize(new Dimension(w, h));
162
163        JButton okButton = new JButton("   Ok   ");
164        okButton.setName("OK");
165        okButton.setActionCommand("Ok");
166        okButton.setMnemonic(KeyEvent.VK_O);
167        okButton.addActionListener(this);
168
169        JButton cancelButton = new JButton("Cancel");
170        cancelButton.setName("Cancel");
171        cancelButton.setMnemonic(KeyEvent.VK_C);
172        cancelButton.setActionCommand("Cancel");
173        cancelButton.addActionListener(this);
174
175        moreButton = new JButton("More");
176        moreButton.setName("More");
177        moreButton.addActionListener(this);
178
179        // set OK and CANCEL buttons
180        JPanel buttonPanel = new JPanel();
181        buttonPanel.add(okButton);
182        buttonPanel.add(cancelButton);
183        contentPane.add(buttonPanel, BorderLayout.SOUTH);
184
185        // set NAME and PARENT GROUP panel
186        JPanel namePanel = new JPanel();
187        namePanel.setLayout(new BorderLayout(5, 5));
188
189        labelPanel = new JPanel();
190        textPanel = new JPanel();
191
192        if (!isH5) {
193            labelPanel.setLayout(new GridLayout(2, 1));
194            labelPanel.add(new JLabel("Group name: "));
195            labelPanel.add(new JLabel("Parent group: "));
196            textPanel.setLayout(new GridLayout(2, 1));
197            textPanel.add(nameField = new JTextField());
198            textPanel.add(parentChoice);
199        }
200        else {
201            labelPanel.setLayout(new GridLayout(3, 1));
202            labelPanel.add(new JLabel("Group name: "));
203            labelPanel.add(new JLabel("Parent group: "));
204            labelPanel.add(moreButton); // if h5 format then add more button
205            textPanel.setLayout(new GridLayout(3, 1));
206            textPanel.add(nameField = new JTextField());
207            textPanel.add(parentChoice);
208            textPanel.add(new JLabel("")); // for more button
209        }
210        nameField.setName("groupname");
211        parentChoice.setName("groupparent");
212
213        creationOrderHelpButton = new JButton(ViewProperties.getHelpIcon());
214        creationOrderHelpButton.setToolTipText("Help on Creation Order");
215        creationOrderHelpButton.setMargin(new Insets(0, 0, 0, 0));
216        creationOrderHelpButton.addActionListener(this);
217        creationOrderHelpButton.setActionCommand("Help on Creation Order");
218
219        storageTypeHelpButton = new JButton(ViewProperties.getHelpIcon());
220        storageTypeHelpButton.setToolTipText("Help on set Link Storage");
221        storageTypeHelpButton.setMargin(new Insets(0, 0, 0, 0));
222        storageTypeHelpButton.addActionListener(this);
223        storageTypeHelpButton.setActionCommand("Help on set Link Storage");
224
225        namePanel.add(labelPanel, BorderLayout.WEST);
226
227        useCreationOrderJPanel = new JPanel();
228        useCreationOrderJPanel.setLayout(new GridLayout(1, 2));
229        useCreationOrderJPanel.setBorder(new TitledBorder(""));
230        useCreationOrderJPanel.add(useCreationOrder = new JCheckBox("Use Creation Order"));
231        useCreationOrder.addItemListener(this);
232        JPanel orderFlagsJPanel = new JPanel();
233        orderFlagsJPanel.setLayout(new GridLayout(1, 2));
234        orderFlagsJPanel.add(new JLabel("Order Flags: "));
235        orderFlagsJPanel.add(orderFlags);
236        orderFlags.setEnabled(false);
237        useCreationOrderJPanel.add(orderFlagsJPanel);
238
239        setLinkStorageJPanel = new JPanel();
240        setLinkStorageJPanel.setLayout(new GridLayout(1, 2));
241        setLinkStorageJPanel.setBorder(new TitledBorder(""));
242        setLinkStorageJPanel.add(setLinkStorage = new JCheckBox("Set Link Storage"));
243        setLinkStorage.addItemListener(this);
244        JPanel storageTypeJPanel = new JPanel();
245        storageTypeJPanel.setLayout(new GridLayout(2, 2));
246        storageTypeJPanel.add(new JLabel("Min Indexed: "));
247        storageTypeJPanel.add(new JLabel("Max Compact: "));
248        indexedField = new JTextField();
249        indexedField.addKeyListener(this);
250        storageTypeJPanel.add(indexedField);
251        indexedField.setDocument(new JTextFieldLimit(5));
252        indexedField.setText("6");
253        indexedField.setEnabled(false);
254        compactField = new JTextField();
255        storageTypeJPanel.add(compactField);
256        compactField.addKeyListener(this);
257        compactField.setDocument(new JTextFieldLimit(5));
258        compactField.setText("8");
259        compactField.setEnabled(false);
260        setLinkStorageJPanel.add(storageTypeJPanel);
261
262        namePanel.add(textPanel, BorderLayout.CENTER);
263        contentPane.add(namePanel, BorderLayout.CENTER);
264
265        // locate the H5Property dialog
266        Point l = owner.getLocation();
267        l.x += 250;
268        l.y += 80;
269        setLocation(l);
270        validate();
271        pack();
272    }
273
274    public void actionPerformed(ActionEvent e) {
275        String cmd = e.getActionCommand();
276
277        if (cmd.equals("More")) {
278            moreButton.setText("Less");
279            int w = 500 + (ViewProperties.getFontSize() - 12) * 15;
280            int h = 280 + (ViewProperties.getFontSize() - 12) * 10;
281            contentPane.setPreferredSize(new Dimension(w, h));
282            labelPanel.setLayout(new GridLayout(5, 1));
283            labelPanel.add(creationOrderHelpButton);
284            labelPanel.add(storageTypeHelpButton);
285            textPanel.setLayout(new GridLayout(5, 1));
286            textPanel.add(useCreationOrderJPanel);
287            textPanel.add(setLinkStorageJPanel);
288            validate();
289            pack();
290        }
291
292        if (cmd.equals("Less")) {
293            moreButton.setText("More");
294            int w = 400 + (ViewProperties.getFontSize() - 12) * 15;
295            int h = 150 + (ViewProperties.getFontSize() - 12) * 10;
296            contentPane.setPreferredSize(new Dimension(w, h));
297            labelPanel.setLayout(new GridLayout(3, 1));
298            labelPanel.remove(creationOrderHelpButton);
299            labelPanel.remove(storageTypeHelpButton);
300            textPanel.setLayout(new GridLayout(3, 1));
301            textPanel.remove(useCreationOrderJPanel);
302            textPanel.remove(setLinkStorageJPanel);
303            useCreationOrder.setSelected(false);
304            setLinkStorage.setSelected(false);
305            validate();
306            pack();
307        }
308
309        if (cmd.equals("Help on Creation Order")) {
310            final String msg = "Use Creation Order allows the user to set the creation order \n"
311                    + "of links in a group, so that tracking, indexing, and iterating over links\n"
312                    + "in groups can be possible. \n\n"
313                    + "If the order flag Tracked is selected, links in a group can now \n"
314                    + "be explicitly tracked by the order that they were created. \n\n"
315                    + "If the order flag Tracked+Indexed is selected, links in a group can \n"
316                    + "now be explicitly tracked and indexed in the order that they were created. \n\n"
317                    + "The default order in which links in a group are listed is alphanumeric-by-name. \n\n\n";
318            JOptionPane.showMessageDialog(this, msg);
319        }
320
321        if (cmd.equals("Help on set Link Storage")) {
322            final String msg = "Set Link Storage allows the users to explicitly set the storage  \n"
323                    + "type of a group to be Compact or Indexed. \n\n"
324                    + "Compact Storage: For groups with only a few links, compact link storage\n"
325                    + "allows groups containing only a few links to take up much less space \n" + "in the file. \n\n"
326                    + "Indexed Storage: For groups with large number of links, indexed link storage  \n"
327                    + "provides a faster and more scalable method for storing and working with  \n"
328                    + "large groups containing many links. \n\n"
329                    + "The threshold for switching between the compact and indexed storage   \n"
330                    + "formats is either set to default values or can be set by the user. \n\n"
331                    + "<html><b>Max Compact</b></html> \n"
332                    + "Max Compact is the maximum number of links to store in the group in a  \n"
333                    + "compact format, before converting the group to the Indexed format. Groups \n"
334                    + "that are in compact format and in which the number of links rises above \n"
335                    + " this threshold are automatically converted to indexed format. \n\n"
336                    + "<html><b>Min Indexed</b></html> \n"
337                    + "Min Indexed is the minimum number of links to store in the Indexed format.   \n"
338                    + "Groups which are in indexed format and in which the number of links falls    \n"
339                    + "below this threshold are automatically converted to compact format. \n\n\n";
340            JOptionPane.showMessageDialog(this, msg);
341        }
342
343        if (cmd.equals("Ok")) {
344            newObject = create();
345            if (newObject != null) {
346                dispose();
347            }
348        }
349        if (cmd.equals("Cancel")) {
350            newObject = null;
351            dispose();
352        }
353    }
354
355    private HObject create() {
356        String name = null;
357        Group pgroup = null;
358        int gcpl = 0;
359
360        name = nameField.getText();
361        if (name == null) {
362            toolkit.beep();
363            JOptionPane.showMessageDialog(this, "Group name is not specified.", getTitle(), JOptionPane.ERROR_MESSAGE);
364            return null;
365        }
366
367        if (name.indexOf(HObject.separator) >= 0) {
368            toolkit.beep();
369            JOptionPane.showMessageDialog(this, "Group name cannot contain path.", getTitle(),
370                    JOptionPane.ERROR_MESSAGE);
371            return null;
372        }
373
374        pgroup = groupList.get(parentChoice.getSelectedIndex());
375
376        if (pgroup == null) {
377            toolkit.beep();
378            JOptionPane.showMessageDialog(this, "Parent group is null.", getTitle(), JOptionPane.ERROR_MESSAGE);
379            return null;
380        }
381
382        Group obj = null;
383
384        if (orderFlags.isEnabled()) {
385            String order = (String) orderFlags.getSelectedItem();
386            if (order.equals("Tracked"))
387                creationOrder = Group.CRT_ORDER_TRACKED;
388            else if (order.equals("Tracked+Indexed"))
389                creationOrder = Group.CRT_ORDER_INDEXED;
390        }
391        else
392            creationOrder = 0;
393
394        if ((orderFlags.isEnabled()) || (setLinkStorage.isSelected())) {
395            int maxCompact = Integer.parseInt(compactField.getText());
396            int minDense = Integer.parseInt(indexedField.getText());
397
398            if ((maxCompact <= 0) || (maxCompact > 65536) || (minDense > 65536)) {
399                toolkit.beep();
400                JOptionPane.showMessageDialog(this, "Max Compact and Min Indexed should be > 0 and < 65536.",
401                        getTitle(), JOptionPane.ERROR_MESSAGE);
402                return null;
403            }
404
405            if (maxCompact < minDense) {
406                toolkit.beep();
407                JOptionPane.showMessageDialog(this, "Min Indexed should be <= Max Compact", getTitle(),
408                        JOptionPane.ERROR_MESSAGE);
409                return null;
410            }
411
412            try {
413                gcpl = fileFormat.createGcpl(creationOrder, maxCompact, minDense);
414            }
415            catch (Exception ex) {
416                ex.printStackTrace();
417            }
418        }
419
420        try {
421            if (isH5)
422                obj = fileFormat.createGroup(name, pgroup, 0, gcpl);
423            else
424                obj = fileFormat.createGroup(name, pgroup);
425        }
426        catch (Exception ex) {
427            toolkit.beep();
428            JOptionPane.showMessageDialog(this, ex.getMessage(), getTitle(), JOptionPane.ERROR_MESSAGE);
429            return null;
430        }
431
432        return obj;
433    }
434
435    /**
436     * Returns the new group created.
437     * 
438     * @return The new group created
439     */
440    public DataFormat getObject() {
441        return newObject;
442    }
443
444    /**
445     * Returns the parent group of the new group.
446     * 
447     * @return The parent group of the new group
448     */
449    public Group getParentGroup() {
450        return groupList.get(parentChoice.getSelectedIndex());
451    }
452
453    public void itemStateChanged(ItemEvent e) {
454        Object source = e.getSource();
455
456        if (source.equals(useCreationOrder)) {
457            boolean isOrder = useCreationOrder.isSelected();
458
459            if (isOrder)
460                orderFlags.setEnabled(true);
461            else
462                orderFlags.setEnabled(false);
463        }
464
465        if (source.equals(setLinkStorage)) {
466            boolean setStorage = setLinkStorage.isSelected();
467
468            if (setStorage) {
469                compactField.setEnabled(true);
470                indexedField.setEnabled(true);
471            }
472            else {
473                compactField.setText("8");
474                compactField.setEnabled(false);
475                indexedField.setText("6");
476                indexedField.setEnabled(false);
477            }
478        }
479    }
480
481    // Setting the length of the text fields.
482    class JTextFieldLimit extends PlainDocument {
483        private static final long serialVersionUID = -5131438789797052658L;
484        private int limit;
485
486        JTextFieldLimit(int limit) {
487            super();
488            this.limit = limit;
489        }
490
491        JTextFieldLimit(int limit, boolean upper) {
492            super();
493            this.limit = limit;
494        }
495
496        public void insertString(int offset, String str, AttributeSet attr) throws BadLocationException {
497            if (str == null)
498                return;
499
500            if ((getLength() + str.length()) <= limit) {
501                super.insertString(offset, str, attr);
502            }
503        }
504    }
505
506    public void keyPressed(java.awt.event.KeyEvent arg0) {
507    }
508
509    public void keyReleased(java.awt.event.KeyEvent arg0) {
510    }
511
512    public void keyTyped(java.awt.event.KeyEvent arg0) {
513        char c = arg0.getKeyChar();
514        if (!Character.isDigit(c))
515            arg0.consume(); // prevent event propagation
516    }
517
518}