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 COPYING file, which can be found  *
009 * at the root of the source code distribution tree,                         *
010 * or in https://www.hdfgroup.org/licenses.                                  *
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.dialog;
016
017import java.io.InputStream;
018import java.net.URL;
019import java.net.URLClassLoader;
020import java.util.Iterator;
021import java.util.List;
022import java.util.Scanner;
023import java.util.StringTokenizer;
024import java.util.Vector;
025
026import org.slf4j.Logger;
027import org.slf4j.LoggerFactory;
028
029import org.eclipse.swt.SWT;
030import org.eclipse.swt.browser.Browser;
031import org.eclipse.swt.events.DisposeEvent;
032import org.eclipse.swt.events.DisposeListener;
033import org.eclipse.swt.events.SelectionAdapter;
034import org.eclipse.swt.events.SelectionEvent;
035import org.eclipse.swt.graphics.Point;
036import org.eclipse.swt.graphics.Rectangle;
037import org.eclipse.swt.layout.GridData;
038import org.eclipse.swt.layout.GridLayout;
039import org.eclipse.swt.widgets.Button;
040import org.eclipse.swt.widgets.Combo;
041import org.eclipse.swt.widgets.Composite;
042import org.eclipse.swt.widgets.Dialog;
043import org.eclipse.swt.widgets.Display;
044import org.eclipse.swt.widgets.Label;
045import org.eclipse.swt.widgets.Shell;
046import org.eclipse.swt.widgets.Text;
047
048import hdf.object.Dataset;
049import hdf.object.Datatype;
050import hdf.object.Group;
051import hdf.object.HObject;
052import hdf.object.ScalarDS;
053import hdf.view.Tools;
054import hdf.view.ViewProperties;
055import hdf.view.DataView.DataView;
056import hdf.view.ImageView.ImageView;
057import hdf.view.TableView.TableView;
058
059/**
060 * NewDatasetDialog shows a message dialog requesting user input for creating a
061 * new HDF4/5 dataset.
062 *
063 * @author Jordan T. Henderson
064 * @version 2.4 12/31/2015
065 */
066public class NewDatasetDialog extends NewDataObjectDialog {
067
068    private static final Logger log = LoggerFactory.getLogger(NewDatasetDialog.class);
069
070    private String            maxSize;
071
072    private Text              currentSizeField, chunkSizeField, fillValueField;
073
074    private Combo             parentChoice, rankChoice, compressionLevel;
075
076    private Button            checkCompression, checkFillValue;
077
078    private Button            checkContiguous, checkChunked;
079
080    /** TextField for entering the name of the object */
081    protected Text            nameField;
082
083    /** A list of current groups */
084    private List<Group>       groupList;
085
086    private final DataView    dataView;
087
088    /**
089     * Constructs a NewDatasetDialog with specified list of possible parent
090     * groups.
091     *
092     * @param parent
093     *            the parent shell of the dialog
094     * @param pGroup
095     *            the parent group which the new group is added to.
096     * @param objs
097     *            the list of all objects.
098     */
099    public NewDatasetDialog(Shell parent, Group pGroup, List<?> objs) {
100        super(parent, pGroup, objs);
101
102        dataView = null;
103    }
104
105    /**
106     * Constructs a NewDatasetDialog with specified list of possible parent
107     * groups.
108     *
109     * @param parent
110     *            the parent shell of the dialog
111     * @param pGroup
112     *            the parent group which the new group is added to.
113     * @param objs
114     *            the list of all objects.
115     * @param observer
116     *            the Dataview attached to this dialog.
117     */
118    public NewDatasetDialog(Shell parent, Group pGroup, List<?> objs, DataView observer) {
119        super(parent, pGroup, objs);
120
121        dataView = observer;
122    }
123
124    /**
125     * Open the NewDataseteDialog for adding a new dataset.
126     */
127    public void open() {
128        Shell parent = getParent();
129        shell = new Shell(parent, SWT.SHELL_TRIM | SWT.APPLICATION_MODAL);
130        shell.setFont(curFont);
131        shell.setText("New Dataset...");
132        shell.setImages(ViewProperties.getHdfIcons());
133        shell.setLayout(new GridLayout(1, true));
134
135
136        // Create Dataset name / Parent Group region
137        Composite fieldComposite = new Composite(shell, SWT.NONE);
138        fieldComposite.setLayout(new GridLayout(2, false));
139        fieldComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
140
141        Label datasetNameLabel = new Label(fieldComposite, SWT.LEFT);
142        datasetNameLabel.setFont(curFont);
143        datasetNameLabel.setText("Dataset name: ");
144
145        nameField = new Text(fieldComposite, SWT.SINGLE | SWT.BORDER);
146        nameField.setFont(curFont);
147        GridData data = new GridData(SWT.FILL, SWT.FILL, true, false);
148
149        data.minimumWidth = 250;
150        nameField.setLayoutData(data);
151
152        Label parentGroupLabel = new Label(fieldComposite, SWT.LEFT);
153        parentGroupLabel.setFont(curFont);
154        parentGroupLabel.setText("Parent group: ");
155
156        parentChoice = new Combo(fieldComposite, SWT.DROP_DOWN | SWT.BORDER | SWT.READ_ONLY);
157        parentChoice.setFont(curFont);
158        parentChoice.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
159        parentChoice.addSelectionListener(new SelectionAdapter() {
160            @Override
161            public void widgetSelected(SelectionEvent e) {
162                parentObj = groupList.get(parentChoice.getSelectionIndex());
163            }
164        });
165
166        groupList = new Vector<>();
167        Object obj = null;
168        Iterator<?> iterator = objList.iterator();
169
170        while (iterator.hasNext()) {
171            obj = iterator.next();
172            if (obj instanceof Group) {
173                Group g = (Group) obj;
174                groupList.add(g);
175                if (g.isRoot()) {
176                    parentChoice.add(HObject.SEPARATOR);
177                }
178                else {
179                    parentChoice.add(g.getPath() + g.getName() + HObject.SEPARATOR);
180                }
181            }
182        }
183
184        if (((Group) parentObj).isRoot()) {
185            parentChoice.select(parentChoice.indexOf(HObject.SEPARATOR));
186        }
187        else {
188            parentChoice.select(parentChoice.indexOf(parentObj.getPath() + parentObj.getName() + HObject.SEPARATOR));
189        }
190
191        // Create New Dataset from scratch
192        if (dataView == null) {
193            // Create Datatype region
194            createDatatypeWidget();
195
196            // Create Dataspace region
197            org.eclipse.swt.widgets.Group dataspaceGroup = new org.eclipse.swt.widgets.Group(shell, SWT.NONE);
198            dataspaceGroup.setFont(curFont);
199            dataspaceGroup.setText("Dataspace");
200            dataspaceGroup.setLayout(new GridLayout(3, true));
201            dataspaceGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
202
203            Label label = new Label(dataspaceGroup, SWT.LEFT);
204            label.setFont(curFont);
205            label.setText("No. of dimensions");
206
207            label = new Label(dataspaceGroup, SWT.LEFT);
208            label.setFont(curFont);
209            label.setText("Current size");
210
211            // Dummy label
212            label = new Label(dataspaceGroup, SWT.LEFT);
213            label.setFont(curFont);
214            label.setText("");
215
216            rankChoice = new Combo(dataspaceGroup, SWT.DROP_DOWN | SWT.READ_ONLY);
217            rankChoice.setFont(curFont);
218            rankChoice.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
219            rankChoice.addSelectionListener(new SelectionAdapter() {
220                @Override
221                public void widgetSelected(SelectionEvent e) {
222                    int rank = rankChoice.getSelectionIndex() + 1;
223                    StringBuilder currentSizeStr = new StringBuilder("1");
224
225                    for (int i = 1; i < rank; i++) {
226                        currentSizeStr.append(" x 1");
227                    }
228
229                    currentSizeField.setText(currentSizeStr.toString());
230
231                    String currentStr = currentSizeField.getText();
232                    int idx = currentStr.lastIndexOf('x');
233
234                    StringBuilder chunkStr = new StringBuilder();
235
236                    if (rank <= 1) {
237                        chunkStr.append(currentStr);
238                    }
239                    else {
240                        chunkStr.append("1");
241                        for (int i = 1; i < rank - 1; i++) {
242                            chunkStr.append(" x 1");
243                        }
244                        if (idx > 0) {
245                            chunkStr.append(" x ");
246                            chunkStr.append(currentStr.substring(idx + 1));
247                        }
248                    }
249
250                    chunkSizeField.setText(chunkStr.toString());
251                }
252            });
253
254            for (int i = 1; i < 33; i++) {
255                rankChoice.add(String.valueOf(i));
256            }
257            rankChoice.select(1);
258
259            currentSizeField = new Text(dataspaceGroup, SWT.SINGLE | SWT.BORDER);
260            currentSizeField.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
261            currentSizeField.setFont(curFont);
262            currentSizeField.setText("1 x 1");
263
264            Button setMaxSizeButton = new Button(dataspaceGroup, SWT.PUSH);
265            setMaxSizeButton.setFont(curFont);
266            setMaxSizeButton.setText("Set Max Size");
267            setMaxSizeButton.setLayoutData(new GridData(SWT.END, SWT.FILL, false, false));
268            setMaxSizeButton.addSelectionListener(new SelectionAdapter() {
269                @Override
270                public void widgetSelected(SelectionEvent e) {
271                    if (maxSize == null || maxSize.length() < 1)
272                        maxSize = currentSizeField.getText();
273
274                    String msg = new InputDialog(shell, "Set Max Size", "Enter max dimension sizes. \n"
275                            + "Use \"unlimited\" for unlimited dimension size.\n\n" + "For example,\n" + "    200 x 100\n"
276                            + "    100 x unlimited\n\n", maxSize).open();
277
278                    if (msg == null || msg.length() < 1)
279                        maxSize = currentSizeField.getText();
280                    else
281                        maxSize = msg;
282
283                    checkMaxSize();
284                }
285            });
286
287
288            // Create Storage Properties region
289            org.eclipse.swt.widgets.Group storagePropertiesGroup = new org.eclipse.swt.widgets.Group(shell, SWT.NONE);
290            storagePropertiesGroup.setFont(curFont);
291            storagePropertiesGroup.setText("Storage Properties");
292            storagePropertiesGroup.setLayout(new GridLayout(5, true));
293            storagePropertiesGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
294
295            label = new Label(storagePropertiesGroup, SWT.LEFT);
296            label.setFont(curFont);
297            label.setText("Storage layout: ");
298
299            checkContiguous = new Button(storagePropertiesGroup, SWT.RADIO);
300            checkContiguous.setFont(curFont);
301            checkContiguous.setText("Contiguous");
302            checkContiguous.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
303            checkContiguous.setSelection(true);
304            checkContiguous.addSelectionListener(new SelectionAdapter() {
305                @Override
306                public void widgetSelected(SelectionEvent e) {
307                    chunkSizeField.setEnabled(false);
308                }
309            });
310
311            // Dummy label
312            label = new Label(storagePropertiesGroup, SWT.LEFT);
313            label.setFont(curFont);
314            label.setText("");
315            label.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
316
317            checkChunked = new Button(storagePropertiesGroup, SWT.RADIO);
318            checkChunked.setFont(curFont);
319            checkChunked.setText("Chunked (size) ");
320            checkChunked.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
321            checkChunked.addSelectionListener(new SelectionAdapter() {
322                @Override
323                public void widgetSelected(SelectionEvent e) {
324                    chunkSizeField.setEnabled(true);
325                    StringBuilder chunkStr = new StringBuilder();
326                    StringTokenizer st = new StringTokenizer(currentSizeField.getText(), "x");
327                    int rank = rankChoice.getSelectionIndex() + 1;
328                    while (st.hasMoreTokens()) {
329                        long l = Math.max(1, Long.valueOf(st.nextToken().trim()) / (2 * rank));
330                        chunkStr.append(String.valueOf(l));
331                        chunkStr.append("x");
332                    }
333                    String chunkString = chunkStr.substring(0, chunkStr.lastIndexOf("x"));
334                    chunkSizeField.setText(chunkString);
335                }
336            });
337
338            chunkSizeField = new Text(storagePropertiesGroup, SWT.SINGLE | SWT.BORDER);
339            chunkSizeField.setFont(curFont);
340            chunkSizeField.setText("1 x 1");
341            chunkSizeField.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
342            chunkSizeField.setEnabled(false);
343
344            label = new Label(storagePropertiesGroup, SWT.LEFT);
345            label.setFont(curFont);
346            label.setText("Compression: ");
347
348            checkCompression = new Button(storagePropertiesGroup, SWT.CHECK);
349            checkCompression.setFont(curFont);
350            checkCompression.setText("gzip (level) ");
351            checkCompression.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
352            checkCompression.addSelectionListener(new SelectionAdapter() {
353                @Override
354                public void widgetSelected(SelectionEvent e) {
355                    boolean isCompressed = checkCompression.getSelection();
356
357                    if (isCompressed && isH5) {
358                        if (!checkChunked.getSelection()) {
359                            int rank = rankChoice.getSelectionIndex() + 1;
360                            String currentStr = currentSizeField.getText();
361                            int idx = currentStr.lastIndexOf('x');
362                            StringBuilder chunkStr = new StringBuilder();
363
364                            if (rank <= 1) {
365                                chunkStr.append(currentStr);
366                            }
367                            else {
368                                chunkStr.append("1");
369                                for (int i = 1; i < rank - 1; i++) {
370                                    chunkStr.append(" x 1");
371                                }
372                                if (idx > 0) {
373                                    chunkStr.append(" x ");
374                                    chunkStr.append(currentStr.substring(idx + 1));
375                                }
376                            }
377
378                            chunkSizeField.setText(chunkStr.toString());
379                        }
380                        compressionLevel.setEnabled(true);
381                        checkContiguous.setEnabled(false);
382                        checkContiguous.setSelection(false);
383                        checkChunked.setSelection(true);
384                        chunkSizeField.setEnabled(true);
385                    }
386                    else {
387                        compressionLevel.setEnabled(isCompressed);
388                        checkContiguous.setEnabled(true);
389                    }
390                }
391            });
392
393            compressionLevel = new Combo(storagePropertiesGroup, SWT.DROP_DOWN | SWT.READ_ONLY);
394            compressionLevel.setFont(curFont);
395            compressionLevel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
396
397            for (int i = 0; i < 10; i++) {
398                compressionLevel.add(String.valueOf(i));
399            }
400            compressionLevel.select(6);
401            compressionLevel.setEnabled(false);
402
403            if(isH5) {
404                checkFillValue = new Button(storagePropertiesGroup, SWT.CHECK);
405                checkFillValue.setFont(curFont);
406                checkFillValue.setText("Fill Value");
407                checkFillValue.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
408                checkFillValue.setSelection(false);
409                checkFillValue.addSelectionListener(new SelectionAdapter() {
410                    @Override
411                    public void widgetSelected(SelectionEvent e) {
412                        fillValueField.setEnabled(checkFillValue.getSelection());
413                    }
414                });
415
416                fillValueField = new Text(storagePropertiesGroup, SWT.SINGLE | SWT.BORDER);
417                fillValueField.setFont(curFont);
418                fillValueField.setText("0");
419                fillValueField.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
420                fillValueField.setEnabled(false);
421            } else {
422                // Add two dummy labels
423                label = new Label(storagePropertiesGroup, SWT.LEFT);
424                label.setFont(curFont);
425                label.setText("");
426                label.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
427
428                label = new Label(storagePropertiesGroup, SWT.LEFT);
429                label.setFont(curFont);
430                label.setText("");
431                label.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
432            }
433        }
434
435
436        // Create Ok/Cancel/Help button region
437        Composite buttonComposite = new Composite(shell, SWT.NONE);
438        buttonComposite.setLayout(new GridLayout((dataView == null) ? 3 : 2, false));
439        buttonComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
440
441        Button okButton = new Button(buttonComposite, SWT.PUSH);
442        okButton.setFont(curFont);
443        okButton.setText("   &OK   ");
444        okButton.setLayoutData(new GridData(SWT.END, SWT.FILL, true, false));
445        okButton.addSelectionListener(new SelectionAdapter() {
446            @Override
447            public void widgetSelected(SelectionEvent e) {
448                if (dataView instanceof TableView) {
449                    newObject = createFromTable();
450                }
451                else if (dataView instanceof ImageView) {
452                    newObject = createFromImage();
453                }
454                else if (dataView == null) {
455                    newObject = createFromScratch();
456                }
457
458                if (newObject != null) {
459                    shell.dispose();
460                }
461            }
462        });
463
464        Button cancelButton = new Button(buttonComposite, SWT.PUSH);
465        cancelButton.setFont(curFont);
466        cancelButton.setText(" &Cancel ");
467        cancelButton.setLayoutData(new GridData((dataView == null) ? SWT.CENTER : SWT.BEGINNING, SWT.FILL,
468                (dataView == null) ? false : true, false));
469        cancelButton.addSelectionListener(new SelectionAdapter() {
470            @Override
471            public void widgetSelected(SelectionEvent e) {
472                newObject = null;
473                shell.dispose();
474                ((Vector<Group>) groupList).setSize(0);
475            }
476        });
477
478        if (dataView == null) {
479            Button helpButton = new Button(buttonComposite, SWT.PUSH);
480            helpButton.setFont(curFont);
481            helpButton.setText(" &Help ");
482            helpButton.setLayoutData(new GridData(SWT.BEGINNING, SWT.FILL, true, false));
483            helpButton.addSelectionListener(new SelectionAdapter() {
484                @Override
485                public void widgetSelected(SelectionEvent e) {
486                    new HelpDialog(shell).open();
487                }
488            });
489        }
490
491        shell.pack();
492
493        shell.addDisposeListener(new DisposeListener() {
494            @Override
495            public void widgetDisposed(DisposeEvent e) {
496                if (curFont != null) curFont.dispose();
497            }
498        });
499
500        shell.setMinimumSize(shell.computeSize(SWT.DEFAULT, SWT.DEFAULT));
501
502        Rectangle parentBounds = parent.getBounds();
503        Point shellSize = shell.getSize();
504        shell.setLocation((parentBounds.x + (parentBounds.width / 2)) - (shellSize.x / 2),
505                          (parentBounds.y + (parentBounds.height / 2)) - (shellSize.y / 2));
506
507        shell.open();
508
509        Display display = shell.getDisplay();
510        while (!shell.isDisposed())
511            if (!display.readAndDispatch())
512                display.sleep();
513    }
514
515    /** Check if the max size is valid */
516    private void checkMaxSize() {
517        boolean isChunkNeeded = false;
518        String dimStr = currentSizeField.getText();
519        String maxSizeStr = maxSize;
520        StringTokenizer stMax = new StringTokenizer(maxSizeStr, "x");
521        StringTokenizer stDim = new StringTokenizer(dimStr, "x");
522
523        if (stMax.countTokens() != stDim.countTokens()) {
524            shell.getDisplay().beep();
525            Tools.showError(shell, "Check", "Wrong number of values in the max dimension size " + maxSize);
526            maxSize = null;
527            return;
528        }
529
530        int rank = stDim.countTokens();
531        long max = 0, dim = 0;
532        long[] maxdims = new long[rank];
533        for (int i = 0; i < rank; i++) {
534            String token = stMax.nextToken().trim();
535
536            token = token.toLowerCase();
537            if (token.startsWith("u")) {
538                max = -1;
539                isChunkNeeded = true;
540            }
541            else {
542                try {
543                    max = Long.parseLong(token);
544                }
545                catch (NumberFormatException ex) {
546                    shell.getDisplay().beep();
547                    Tools.showError(shell, "Check", "Invalid max dimension size: " + maxSize);
548                    maxSize = null;
549                    return;
550                }
551            }
552
553            token = stDim.nextToken().trim();
554            try {
555                dim = Long.parseLong(token);
556            }
557            catch (NumberFormatException ex) {
558                shell.getDisplay().beep();
559                Tools.showError(shell, "Check", "Invalid dimension size: " + dimStr);
560                return;
561            }
562
563            if (max != -1 && max < dim) {
564                shell.getDisplay().beep();
565                Tools.showError(shell, "Check", "Invalid max dimension size: " + maxSize);
566                maxSize = null;
567                return;
568            }
569            else if (max > dim) {
570                isChunkNeeded = true;
571            }
572
573            maxdims[i] = max;
574        } //  (int i = 0; i < rank; i++)
575
576        if (isH5) {
577            if (isChunkNeeded && !checkChunked.getSelection()) {
578                shell.getDisplay().beep();
579                Tools.showError(shell, "Check", "Chunking is required for the max dimensions of " + maxSize);
580                checkChunked.setSelection(true);
581            }
582        }
583        else {
584            for (int i = 1; i < rank; i++) {
585                if (maxdims[i] <= 0) {
586                    maxSize = currentSizeField.getText();
587                    shell.getDisplay().beep();
588                    Tools.showError(shell, "Check", "Only dim[0] can be unlimited." + maxSize);
589                    return;
590                }
591            }
592        }
593    }
594
595    private HObject createFromScratch() {
596        String name = null;
597        Group pgroup = null;
598        int rank = -1;
599        int gzip = -1;
600        long[] dims;
601        long[] maxdims = null;
602        long[] chunks = null;
603
604        name = nameField.getText().trim();
605        if ((name == null) || (name.length() < 1)) {
606            shell.getDisplay().beep();
607            Tools.showError(shell, "Create", "Dataset name is not specified.");
608            return null;
609        }
610
611        if (name.indexOf(HObject.SEPARATOR) >= 0) {
612            shell.getDisplay().beep();
613            Tools.showError(shell, "Create", "Dataset name cannot contain path.");
614            return null;
615        }
616
617        pgroup = groupList.get(parentChoice.getSelectionIndex());
618
619        if (pgroup == null) {
620            shell.getDisplay().beep();
621            Tools.showError(shell, "Create", "Parent group is null.");
622            return null;
623        }
624
625        rank = rankChoice.getSelectionIndex() + 1;
626        StringTokenizer st = new StringTokenizer(currentSizeField.getText(), "x");
627        if (st.countTokens() < rank) {
628            shell.getDisplay().beep();
629            Tools.showError(shell, "Create", "Number of values in the current dimension size is less than " + rank);
630            return null;
631        }
632
633        long l = 0;
634        dims = new long[rank];
635        String token = null;
636        for (int i = 0; i < rank; i++) {
637            token = st.nextToken().trim();
638            try {
639                l = Long.parseLong(token);
640            }
641            catch (NumberFormatException ex) {
642                shell.getDisplay().beep();
643                Tools.showError(shell, "Create", "Invalid dimension size: " + currentSizeField.getText());
644                return null;
645            }
646
647            if (l <= 0) {
648                shell.getDisplay().beep();
649                Tools.showError(shell, "Create", "Dimension size must be greater than zero.");
650                return null;
651            }
652
653            dims[i] = l;
654        }
655
656        String maxSizeStr = maxSize;
657        if (maxSizeStr != null && maxSizeStr.length() > 1) {
658            st = new StringTokenizer(maxSizeStr, "x");
659            if (st.countTokens() < rank) {
660                shell.getDisplay().beep();
661                Tools.showError(shell, "Create", "Number of values in the max dimension size is less than " + rank);
662                return null;
663            }
664
665            l = 0;
666            maxdims = new long[rank];
667            for (int i = 0; i < rank; i++) {
668                token = st.nextToken().trim();
669
670                token = token.toLowerCase();
671                if (token.startsWith("u"))
672                    l = -1;
673                else {
674                    try {
675                        l = Long.parseLong(token);
676                    }
677                    catch (NumberFormatException ex) {
678                        shell.getDisplay().beep();
679                        Tools.showError(shell, "Create", "Invalid max dimension size: " + maxSize);
680                        return null;
681                    }
682                }
683
684                if (l < -1) {
685                    shell.getDisplay().beep();
686                    Tools.showError(shell, "Create", "Dimension size cannot be less than -1.");
687                    return null;
688                }
689                else if (l == 0) {
690                    l = dims[i];
691                }
692
693                maxdims[i] = l;
694            }
695        }
696
697        chunks = null;
698        if (checkChunked.getSelection()) {
699            st = new StringTokenizer(chunkSizeField.getText(), "x");
700            if (st.countTokens() < rank) {
701                shell.getDisplay().beep();
702                Tools.showError(shell, "Create", "Number of values in the chunk size is less than " + rank);
703                return null;
704            }
705
706            l = 0;
707            chunks = new long[rank];
708            for (int i = 0; i < rank; i++) {
709                token = st.nextToken().trim();
710                try {
711                    l = Long.parseLong(token);
712                }
713                catch (NumberFormatException ex) {
714                    shell.getDisplay().beep();
715                    Tools.showError(shell, "Create", "Invalid chunk dimension size: " + chunkSizeField.getText());
716                    return null;
717                }
718
719                if (l < 1) {
720                    shell.getDisplay().beep();
721                    Tools.showError(shell, "Create", "Chunk size cannot be less than 1.");
722                    return null;
723                }
724
725                chunks[i] = l;
726            } //  (int i=0; i<rank; i++)
727
728            long tchunksize = 1;
729            long tdimsize = 1;
730            for (int i = 0; i < rank; i++) {
731                tchunksize *= chunks[i];
732                tdimsize *= dims[i];
733            }
734
735            if (tchunksize >= tdimsize) {
736                shell.getDisplay().beep();
737                if(!Tools.showConfirm(shell, "Create",
738                        "Chunk size is equal/greater than the current size. "
739                        + "\nAre you sure you want to set chunk size to " + chunkSizeField.getText() + "?")) {
740                    return null;
741                }
742            }
743
744            if (tchunksize == 1) {
745                shell.getDisplay().beep();
746                if(!Tools.showConfirm(shell, "Create",
747                        "Chunk size is one, which may cause large memory overhead for large dataset."
748                        + "\nAre you sure you want to set chunk size to " + chunkSizeField.getText() + "?")) {
749                    return null;
750                }
751            }
752        } //  (checkChunked.isSelected())
753
754        if (checkCompression.getSelection()) {
755            gzip = compressionLevel.getSelectionIndex();
756        }
757        else {
758            gzip = 0;
759        }
760
761        HObject obj = null;
762        try {
763            Datatype datatype = createNewDatatype(null);
764
765            String fillValue = null;
766
767            if (fillValueField != null) {
768                if (fillValueField.isEnabled()) fillValue = fillValueField.getText();
769            }
770
771            obj = fileFormat.createScalarDS(name, pgroup, datatype, dims, maxdims, chunks, gzip, fillValue, null);
772        }
773        catch (Exception ex) {
774            shell.getDisplay().beep();
775            Tools.showError(shell, "Create", ex.getMessage());
776            return null;
777        }
778
779        return obj;
780    }
781
782    private HObject createFromTable() {
783        HObject obj = null;
784
785        String name = null;
786        Group pgroup = null;
787
788        name = nameField.getText();
789        if (name == null || name.length() == 0) {
790            shell.getDisplay().beep();
791            Tools.showError(shell, "Create", "Dataset name is not specified.");
792            return null;
793        }
794
795        if (name.indexOf(HObject.SEPARATOR) >= 0) {
796            shell.getDisplay().beep();
797            Tools.showError(shell, "Create", "Dataset name cannot contain path.");
798            return null;
799        }
800
801        pgroup = groupList.get(parentChoice.getSelectionIndex());
802        if (pgroup == null) {
803            shell.getDisplay().beep();
804            Tools.showError(shell, "Create", "Parent group is null.");
805            return null;
806        }
807
808        TableView tableView = (TableView) dataView;
809        Object theData = tableView.getSelectedData();
810        if (theData == null) {
811            return null;
812        }
813
814        int w = tableView.getSelectedColumnCount();
815        int h = tableView.getSelectedRowCount();
816        Dataset dataset = (Dataset) tableView.getDataObject();
817        if (dataset instanceof ScalarDS) {
818            ScalarDS sd = (ScalarDS) dataset;
819            if (sd.getDatatype().isUnsigned()) {
820                theData = Dataset.convertToUnsignedC(theData, null);
821            }
822        }
823
824        try {
825            long[] dims = { h, w };
826            obj = dataset.copy(pgroup, name, dims, theData);
827        }
828        catch (Exception ex) {
829            shell.getDisplay().beep();
830            Tools.showError(shell, "Create", ex.getMessage());
831            return null;
832        }
833
834        return obj;
835    }
836
837    private HObject createFromImage() {
838        HObject obj = null;
839        String name = null;
840        Group pgroup = null;
841
842        name = nameField.getText();
843        if (name == null || name.length() == 0) {
844            shell.getDisplay().beep();
845            Tools.showError(shell, "Create", "Dataset name is not specified.");
846            return null;
847        }
848
849        if (name.indexOf(HObject.SEPARATOR) >= 0) {
850            shell.getDisplay().beep();
851            Tools.showError(shell, "Create", "Dataset name cannot contain path.");
852            return null;
853        }
854
855        pgroup = groupList.get(parentChoice.getSelectionIndex());
856        if (pgroup == null) {
857            shell.getDisplay().beep();
858            Tools.showError(shell, "Create", "Parent group is null.");
859            return null;
860        }
861
862        ImageView imageView = (ImageView) dataView;
863        ScalarDS dataset = (ScalarDS) imageView.getDataObject();
864        Object theData = imageView.getSelectedData();
865
866        if (theData == null) {
867            return null;
868        }
869
870        // in version 2.4, unsigned image data is converted to signed data
871        // to write data, the data needs to be converted back to unsigned.
872        if (dataset.getDatatype().isUnsigned()) {
873            theData = Dataset.convertToUnsignedC(theData, null);
874        }
875
876        int w = imageView.getSelectedArea().width;
877        int h = imageView.getSelectedArea().height;
878
879        try {
880            long[] dims = null;
881            if (isH5) {
882                if (imageView.isTrueColor()) {
883                    dims = new long[3];
884                    if (imageView.isPlaneInterlace()) {
885                        dims[0] = 3;
886                        dims[1] = h;
887                        dims[2] = w;
888                    }
889                    else {
890                        dims[0] = h;
891                        dims[1] = w;
892                        dims[2] = 3;
893                    }
894                }
895                else {
896                    dims = new long[2];
897                    dims[0] = h;
898                    dims[1] = w;
899                }
900            }
901            else {
902                dims = new long[2];
903                dims[0] = w;
904                dims[1] = h;
905            }
906
907            obj = dataset.copy(pgroup, name, dims, theData);
908        }
909        catch (Exception ex) {
910            shell.getDisplay().beep();
911            Tools.showError(shell, "Create", ex.getMessage());
912            return null;
913        }
914
915        return obj;
916    }
917
918    private class HelpDialog extends Dialog {
919        private Shell helpShell;
920
921        public HelpDialog(Shell parent) {
922            super(parent, SWT.APPLICATION_MODAL);
923        }
924
925        public void open() {
926            Shell parent = getParent();
927            helpShell = new Shell(parent, SWT.TITLE | SWT.CLOSE |
928                    SWT.RESIZE | SWT.BORDER | SWT.APPLICATION_MODAL);
929            helpShell.setFont(curFont);
930            helpShell.setText("Create New Dataset");
931            helpShell.setImages(ViewProperties.getHdfIcons());
932            helpShell.setLayout(new GridLayout(1, true));
933
934            // Try to create a Browser on platforms that support it
935            try {
936                Browser browser = new Browser(helpShell, SWT.NONE);
937                browser.setFont(curFont);
938                browser.setBounds(0, 0, 500, 500);
939                browser.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
940
941                if (ClassLoader.getSystemResource("hdf/view/HDFView.class").toString().startsWith("jar")) {
942                    // Attempt to load HTML help file from jar
943                    try (InputStream in = getClass().getClassLoader().getResourceAsStream("hdf/view/NewDatasetHelp.html")) {
944                        Scanner scan = new Scanner(in);
945                        StringBuilder buffer = new StringBuilder();
946                        while(scan.hasNextLine()) {
947                            buffer.append(scan.nextLine());
948                        }
949
950                        browser.setText(buffer.toString());
951
952                        scan.close();
953                    }
954                    catch (Exception e) {
955                        StringBuilder buff = new StringBuilder();
956                        buff.append("<html>")
957                            .append("<body>")
958                            .append("ERROR: cannot load help information.")
959                            .append("</body>")
960                            .append("</html>");
961                        browser.setText(buff.toString(), true);
962                    }
963                }
964                else {
965                    try {
966                        URL url = null, url2 = null, url3 = null;
967                        String rootPath = ViewProperties.getViewRoot();
968
969                        try {
970                            url = new URL("file://" + rootPath + "/HDFView.jar");
971                        }
972                        catch (java.net.MalformedURLException mfu) {
973                            log.debug("help information:", mfu);
974                        }
975
976                        try {
977                            url2 = new URL("file://" + rootPath + "/");
978                        }
979                        catch (java.net.MalformedURLException mfu) {
980                            log.debug("help information:", mfu);
981                        }
982
983                        try {
984                            url3 = new URL("file://" + rootPath + "/src/");
985                        }
986                        catch (java.net.MalformedURLException mfu) {
987                            log.debug("help information:", mfu);
988                        }
989
990                        URL uu[] = { url, url2, url3 };
991                        try (URLClassLoader cl = new URLClassLoader(uu)) {
992                            URL u = cl.findResource("hdf/view/NewDatasetHelp.html");
993
994                            browser.setUrl(u.toString());
995                        }
996                        catch (Exception ex) {
997                            log.trace("URLClassLoader failed:", ex);
998                        }
999                    }
1000                    catch (Exception e) {
1001                        StringBuilder buff = new StringBuilder();
1002                        buff.append("<html>")
1003                            .append("<body>")
1004                            .append("ERROR: cannot load help information.")
1005                            .append("</body>")
1006                            .append("</html>");
1007                        browser.setText(buff.toString(), true);
1008                    }
1009                }
1010
1011                Button okButton = new Button(helpShell, SWT.PUSH);
1012                okButton.setFont(curFont);
1013                okButton.setText("   &OK   ");
1014                okButton.setLayoutData(new GridData(SWT.CENTER, SWT.FILL, true, false));
1015                okButton.addSelectionListener(new SelectionAdapter() {
1016                    @Override
1017                    public void widgetSelected(SelectionEvent e) {
1018                        helpShell.dispose();
1019                    }
1020                });
1021
1022                helpShell.pack();
1023
1024                helpShell.setSize(new Point(500, 500));
1025
1026                Rectangle parentBounds = parent.getBounds();
1027                Point shellSize = helpShell.getSize();
1028                helpShell.setLocation((parentBounds.x + (parentBounds.width / 2)) - (shellSize.x / 2),
1029                                      (parentBounds.y + (parentBounds.height / 2)) - (shellSize.y / 2));
1030
1031                helpShell.open();
1032
1033                Display display = parent.getDisplay();
1034                while(!helpShell.isDisposed()) {
1035                    if (!display.readAndDispatch())
1036                        display.sleep();
1037                }
1038            }
1039            catch (Error er) {
1040                // Try opening help link in external browser if platform
1041                // doesn't support SWT browser
1042                Tools.showError(shell, "Browser support",
1043                        "Platform doesn't support Browser. Opening external link in web browser...");
1044
1045                //TODO: Add support for launching in external browser
1046            }
1047            catch (Exception ex) {
1048                log.debug("Open New Dataset Help failure: ", ex);
1049            }
1050        }
1051    }
1052}