    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}