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