    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.util.Iterator;
    018import java.util.List;
    019import java.util.Vector;
    020
    021import org.eclipse.swt.SWT;
    022import org.eclipse.swt.events.SelectionAdapter;
    023import org.eclipse.swt.events.SelectionEvent;
    024import org.eclipse.swt.graphics.Font;
    025import org.eclipse.swt.layout.GridData;
    026import org.eclipse.swt.layout.GridLayout;
    027import org.eclipse.swt.widgets.Button;
    028import org.eclipse.swt.widgets.Combo;
    029import org.eclipse.swt.widgets.Dialog;
    030import org.eclipse.swt.widgets.Display;
    031import org.eclipse.swt.widgets.Label;
    032import org.eclipse.swt.widgets.Shell;
    033import org.eclipse.swt.widgets.Text;
    034
    035import hdf.object.Datatype;
    036import hdf.object.FileFormat;
    037import hdf.object.Group;
    038import hdf.object.HObject;
    039import hdf.object.h5.H5Datatype;
    040import hdf.view.Tools;
    041import hdf.view.ViewProperties;
    042
    043/**
    044 * NewDataDialog is an intermediate class for creating data types.
    045 */
    046public class NewDataObjectDialog extends Dialog {
    047
    048    private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(NewDataObjectDialog.class);
    049
    050    protected Shell   shell;
    051
    052    protected Font    curFont;
    053
    054    /** the object which the this object is attached */
    055    protected HObject parentObj;
    056
    057    /** the object referenced */
    058    protected HObject refObject;
    059
    060    /** the object created */
    061    protected HObject newObject;
    062
    063    /** TextField for entering the length of the data array or string. */
    064    protected Text    lengthField;
    065
    066    /** The Choice of the datatypes */
    067    protected Combo   namedChoice;
    068    protected Combo   classChoice;
    069    protected Combo   sizeChoice;
    070    protected Combo   endianChoice;
    071
    072    /** The Choice of the object list */
    073    protected Button  useCommittedType;
    074    protected Button  checkUnsigned;
    075    protected List<?> objList;
    076    protected List<Datatype> namedList;
    077    protected Label   arrayLengthLabel;
    078
    079    /** The attributes of the datatype */
    080    public int tclass = Datatype.CLASS_NO_CLASS;
    081    public int tsize = Datatype.NATIVE;
    082    public int torder = Datatype.NATIVE;
    083    public int tsign = Datatype.NATIVE;
    084    public boolean isEnum = false;
    085    public String strEnumMap = null;
    086    public boolean isVLen = false;
    087    public boolean isVlenStr = false;
    088
    089    protected FileFormat fileFormat;
    090
    091    protected boolean isH5;
    092
    093    public NewDataObjectDialog(Shell parent, HObject pGroup, List<?> objs) {
    094        super(parent, SWT.APPLICATION_MODAL);
    095
    096        try {
    097            curFont = new Font(
    098                    Display.getCurrent(),
    099                    ViewProperties.getFontType(),
    100                    ViewProperties.getFontSize(),
    101                    SWT.NORMAL);
    102        }
    103        catch (Exception ex) {
    104            curFont = null;
    105        }
    106
    107        newObject = null;
    108        parentObj = pGroup;
    109        objList = objs;
    110
    111        fileFormat = pGroup.getFileFormat();
    112        isH5 = pGroup.getFileFormat().isThisType(FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF5));
    113    }
    114
    115    /* the new dataset properties to be created. */
    116    public void createDatatypeWidget() {
    117        Label label;
    118
    119        // Create Datatype region
    120        org.eclipse.swt.widgets.Group datatypeGroup = new org.eclipse.swt.widgets.Group(shell, SWT.NONE);
    121        datatypeGroup.setFont(curFont);
    122        datatypeGroup.setText("Datatype");
    123        datatypeGroup.setLayout(new GridLayout(4, true));
    124        datatypeGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
    125
    126        useCommittedType = new Button(datatypeGroup, SWT.CHECK);
    127        useCommittedType.setFont(curFont);
    128        useCommittedType.setText("Use Committed Datatype");
    129        useCommittedType.setLayoutData(new GridData(SWT.END, SWT.FILL, true, false));
    130        useCommittedType.setEnabled(isH5);
    131
    132        if(isH5) {
    133            label = new Label(datatypeGroup, SWT.LEFT);
    134            label.setFont(curFont);
    135            label.setText("Committed Datatype: ");
    136
    137            namedChoice = new Combo(datatypeGroup, SWT.DROP_DOWN | SWT.BORDER | SWT.READ_ONLY);
    138            namedChoice.setFont(curFont);
    139            namedChoice.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
    140            namedChoice.addSelectionListener(new SelectionAdapter() {
    141                @Override
    142                public void widgetSelected(SelectionEvent e) {
    143                    refObject = namedList.get(namedChoice.getSelectionIndex());
    144                }
    145            });
    146
    147            //Dummy label
    148            label = new Label(datatypeGroup, SWT.LEFT);
    149            label.setFont(curFont);
    150            label.setText("");
    151
    152            namedList = new Vector<>(objList.size());
    153            Object obj = null;
    154            Iterator<?> iterator = objList.iterator();
    155            while (iterator.hasNext()) {
    156                obj = iterator.next();
    157                if (obj instanceof Datatype) {
    158                    H5Datatype ndt = (H5Datatype) obj;
    159                    namedList.add(ndt);
    160                    namedChoice.add(((Datatype)obj).getFullName());
    161                }
    162            }
    163
    164            if (refObject != null)
    165                namedChoice.select(namedChoice.indexOf(((Datatype)refObject).getFullName()));
    166        }
    167
    168        label = new Label(datatypeGroup, SWT.LEFT);
    169        label.setFont(curFont);
    170        label.setText("Datatype Class");
    171
    172        label = new Label(datatypeGroup, SWT.LEFT);
    173        label.setFont(curFont);
    174        label.setText("Size (bits)");
    175
    176        label = new Label(datatypeGroup, SWT.LEFT);
    177        label.setFont(curFont);
    178        label.setText("Byte Ordering");
    179
    180        checkUnsigned = new Button(datatypeGroup, SWT.CHECK);
    181        checkUnsigned.setFont(curFont);
    182        checkUnsigned.setText("Unsigned");
    183        checkUnsigned.setLayoutData(new GridData(SWT.END, SWT.FILL, true, false));
    184
    185        classChoice = new Combo(datatypeGroup, SWT.DROP_DOWN | SWT.READ_ONLY);
    186        classChoice.setFont(curFont);
    187        classChoice.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
    188        classChoice.addSelectionListener(new SelectionAdapter() {
    189            @Override
    190            public void widgetSelected(SelectionEvent e) {
    191                int idx = classChoice.getSelectionIndex();
    192                sizeChoice.select(0);
    193                endianChoice.select(0);
    194                lengthField.setEnabled(false);
    195
    196                if ((idx == 0) || (idx == 6)) { // INTEGER
    197                    sizeChoice.setEnabled(true);
    198                    endianChoice.setEnabled(isH5);
    199                    checkUnsigned.setEnabled(true);
    200
    201                    if (sizeChoice.getItemCount() == 3) {
    202                        sizeChoice.remove("32");
    203                        sizeChoice.remove("64");
    204                        sizeChoice.add("8");
    205                        sizeChoice.add("16");
    206                        sizeChoice.add("32");
    207                        sizeChoice.add("64");
    208                    }
    209                }
    210                else if ((idx == 1) || (idx == 7)) { // FLOAT
    211                    sizeChoice.setEnabled(true);
    212                    endianChoice.setEnabled(isH5);
    213                    checkUnsigned.setEnabled(false);
    214
    215                    if (sizeChoice.getItemCount() == 5) {
    216                        sizeChoice.remove("16");
    217                        sizeChoice.remove("8");
    218                    }
    219                }
    220                else if (idx == 2) { // CHAR
    221                    sizeChoice.setEnabled(false);
    222                    endianChoice.setEnabled(isH5);
    223                    checkUnsigned.setEnabled(true);
    224                }
    225                else if (idx == 3) { // STRING
    226                    sizeChoice.setEnabled(false);
    227                    endianChoice.setEnabled(false);
    228                    checkUnsigned.setEnabled(false);
    229                    lengthField.setEnabled(true);
    230                    lengthField.setText("String length");
    231                }
    232                else if (idx == 4) { // REFERENCE
    233                    sizeChoice.setEnabled(false);
    234                    endianChoice.setEnabled(false);
    235                    checkUnsigned.setEnabled(false);
    236                    lengthField.setEnabled(false);
    237                }
    238                else if (idx == 5) { // ENUM
    239                    sizeChoice.setEnabled(true);
    240                    checkUnsigned.setEnabled(true);
    241                    lengthField.setEnabled(true);
    242                    lengthField.setText("0=R,1=G,#=TXT,...");
    243                }
    244                else if (idx == 8) {
    245                    sizeChoice.setEnabled(false);
    246                    endianChoice.setEnabled(false);
    247                    checkUnsigned.setEnabled(false);
    248                    lengthField.setEnabled(false);
    249                }
    250            }
    251        });
    252
    253        classChoice.add("INTEGER");
    254        classChoice.add("FLOAT");
    255        classChoice.add("CHAR");
    256
    257        if(isH5) {
    258            classChoice.add("STRING");
    259            classChoice.add("REFERENCE");
    260            classChoice.add("ENUM");
    261            classChoice.add("VLEN_INTEGER");
    262            classChoice.add("VLEN_FLOAT");
    263            classChoice.add("VLEN_STRING");
    264        }
    265
    266        sizeChoice = new Combo(datatypeGroup, SWT.DROP_DOWN | SWT.READ_ONLY);
    267        sizeChoice.setFont(curFont);
    268        sizeChoice.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
    269        sizeChoice.addSelectionListener(new SelectionAdapter() {
    270            @Override
    271            public void widgetSelected(SelectionEvent e) {
    272                if (classChoice.getSelectionIndex() == 0) {
    273                    checkUnsigned.setEnabled(true);
    274                }
    275            }
    276        });
    277
    278        if(isH5) {
    279            sizeChoice.add("NATIVE");
    280        }
    281        else {
    282            sizeChoice.add("DEFAULT");
    283        }
    284
    285        sizeChoice.add("8");
    286        sizeChoice.add("16");
    287        sizeChoice.add("32");
    288        sizeChoice.add("64");
    289
    290        endianChoice = new Combo(datatypeGroup, SWT.DROP_DOWN | SWT.READ_ONLY);
    291        endianChoice.setFont(curFont);
    292        endianChoice.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
    293        endianChoice.setEnabled(isH5);
    294
    295        if(isH5) {
    296            endianChoice.add("NATIVE");
    297            endianChoice.add("LITTLE ENDIAN");
    298            endianChoice.add("BIG ENDIAN");
    299        }
    300        else {
    301            endianChoice.add("DEFAULT");
    302        }
    303
    304        lengthField = new Text(datatypeGroup, SWT.SINGLE | SWT.BORDER);
    305        lengthField.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
    306        lengthField.setFont(curFont);
    307        lengthField.setText("String Length");
    308        lengthField.setEnabled(false);
    309
    310        classChoice.select(0);
    311        sizeChoice.select(0);
    312        endianChoice.select(0);
    313
    314        refObject = null;
    315        classChoice.setEnabled(true);
    316        sizeChoice.setEnabled(true);
    317        endianChoice.setEnabled(isH5);
    318        checkUnsigned.setEnabled(true);
    319    }
    320
    321    public Datatype createNewDatatype(String name) {
    322        Datatype datatype = null;
    323
    324        tclass = Datatype.CLASS_NO_CLASS;
    325        tsize = Datatype.NATIVE;
    326        torder = Datatype.NATIVE;
    327        tsign = Datatype.NATIVE;
    328        isEnum = false;
    329        strEnumMap = null;
    330        isVLen = false;
    331        isVlenStr = false;
    332
    333        if (useCommittedType.getSelection()) {
    334            datatype = (Datatype)refObject;
    335        }
    336        else {
    337           // idx is set to datatype class
    338            int idx = classChoice.getSelectionIndex();
    339            if (idx == 0) {
    340                tclass = Datatype.CLASS_INTEGER;
    341                if (checkUnsigned.getSelection()) {
    342                    tsign = Datatype.SIGN_NONE;
    343                }
    344            }
    345            else if (idx == 1) {
    346                tclass = Datatype.CLASS_FLOAT;
    347            }
    348            else if (idx == 2) {
    349                tclass = Datatype.CLASS_CHAR;
    350                if (checkUnsigned.getSelection()) {
    351                    tsign = Datatype.SIGN_NONE;
    352                }
    353            }
    354            else if (idx == 3) {
    355                tclass = Datatype.CLASS_STRING;
    356            }
    357            else if (idx == 4) {
    358                tclass = Datatype.CLASS_REFERENCE;
    359            }
    360            else if (idx == 5) {
    361                isEnum = true;
    362                tclass = Datatype.CLASS_ENUM;
    363            }
    364            else if (idx == 6) {
    365                isVLen = true;
    366                tclass = Datatype.CLASS_INTEGER;
    367                if (checkUnsigned.getSelection()) {
    368                    tsign = Datatype.SIGN_NONE;
    369                }
    370            }
    371            else if (idx == 7) {
    372                isVLen = true;
    373                tclass = Datatype.CLASS_FLOAT;
    374            }
    375            else if (idx == 8) {
    376                tclass = Datatype.CLASS_STRING;
    377                isVlenStr = true;
    378                tsize = -1;
    379            }
    380
    381            // idx is set to datatype size
    382            idx = sizeChoice.getSelectionIndex();
    383            if (tclass == Datatype.CLASS_STRING) {
    384                if (!isVlenStr) {
    385                    int stringLength = 0;
    386                    try {
    387                        stringLength = Integer.parseInt(lengthField.getText());
    388                    }
    389                    catch (NumberFormatException ex) {
    390                        stringLength = -1;
    391                    }
    392
    393                    if (stringLength <= 0) {
    394                        shell.getDisplay().beep();
    395                        Tools.showError(shell, "Create", "Invalid string length: " + lengthField.getText());
    396                        return null;
    397                    }
    398                    tsize = stringLength;
    399                }
    400            }
    401            else if (tclass == Datatype.CLASS_REFERENCE) {
    402                tsize = 1;
    403                torder = Datatype.NATIVE;
    404            }
    405            else if (idx == 0) {
    406                tsize = Datatype.NATIVE;
    407            }
    408            else if (tclass == Datatype.CLASS_FLOAT) {
    409                tsize = idx * 4;
    410            }
    411            else if (tclass == Datatype.CLASS_INTEGER || tclass == Datatype.CLASS_ENUM) {
    412                // Note that idx == 0 is set to either
    413                //       "NATIVE" if isH5 is true
    414                //       "DEFAULT" otherwise
    415                switch(idx) {
    416                    case 1:
    417                        tsize = 1;
    418                        break;
    419                    case 2:
    420                        tsize = 2;
    421                        break;
    422                    case 3:
    423                        tsize = 4;
    424                        break;
    425                    case 4:
    426                        tsize = 8;
    427                        break;
    428                    default:
    429                        break;
    430                }
    431                log.trace("CLASS_INTEGER or CLASS_ENUM: tsize={}", tsize);
    432            }
    433            else if (tclass == Datatype.CLASS_FLOAT) {
    434                tsize = (idx + 1) * 4;
    435                log.trace("CLASS_FLOAT: tsize={}", tsize);
    436            }
    437            else {
    438                tsize = 1 << (idx - 1);
    439            }
    440
    441            if ((tsize == 8) && !isH5 && (tclass == Datatype.CLASS_INTEGER)) {
    442                shell.getDisplay().beep();
    443                Tools.showError(shell, "Create", "HDF4 does not support 64-bit integer.");
    444                return null;
    445            }
    446
    447            // set order
    448            idx = endianChoice.getSelectionIndex();
    449            if (idx == 0) {
    450                torder = Datatype.NATIVE;
    451            }
    452            else if (idx == 1) {
    453                torder = Datatype.ORDER_LE;
    454            }
    455            else {
    456                torder = Datatype.ORDER_BE;
    457            }
    458
    459            Datatype thedatatype = null;
    460            try {
    461                Datatype basedatatype = null;
    462                if (isVLen) {
    463                    basedatatype = fileFormat.createDatatype(tclass, tsize, torder, tsign);
    464                    tclass = Datatype.CLASS_VLEN;
    465                    thedatatype = fileFormat.createDatatype(tclass, tsize, torder, tsign, basedatatype);
    466                }
    467                else if (isEnum && isH5) {
    468                    strEnumMap = lengthField.getText();
    469                    if ((strEnumMap == null) || (strEnumMap.length() < 1) || strEnumMap.endsWith("...")) {
    470                        shell.getDisplay().beep();
    471                        Tools.showError(shell, "Create", "Invalid member values: " + lengthField.getText());
    472                        return null;
    473                    }
    474                    log.trace("CLASS_ENUM enumStr={}", strEnumMap);
    475
    476                    thedatatype = fileFormat.createDatatype(tclass, tsize, torder, tsign);
    477                    thedatatype.setEnumMembers(strEnumMap);
    478                }
    479                else
    480                    thedatatype = fileFormat.createDatatype(tclass, tsize, torder, tsign);
    481                datatype = fileFormat.createNamedDatatype(thedatatype, name);
    482            }
    483            catch (Exception ex) {
    484                shell.getDisplay().beep();
    485                Tools.showError(shell, "Create", ex.getMessage());
    486                return null;
    487            }
    488        }
    489        return datatype;
    490    }
    491
    492    /** @return the new object created. */
    493    public HObject getObject() {
    494        return newObject;
    495    }
    496
    497    /** @return the parent group of the new dataset. */
    498    public Group getParentGroup() {
    499        return (Group) parentObj;
    500    }
    501}