    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.util.Iterator;
    018import java.util.List;
    019import java.util.StringTokenizer;
    020import java.util.Vector;
    021
    022import org.slf4j.Logger;
    023import org.slf4j.LoggerFactory;
    024
    025import org.eclipse.swt.SWT;
    026import org.eclipse.swt.custom.CCombo;
    027import org.eclipse.swt.custom.TableEditor;
    028import org.eclipse.swt.events.DisposeEvent;
    029import org.eclipse.swt.events.DisposeListener;
    030import org.eclipse.swt.events.ModifyEvent;
    031import org.eclipse.swt.events.ModifyListener;
    032import org.eclipse.swt.events.SelectionAdapter;
    033import org.eclipse.swt.events.SelectionEvent;
    034import org.eclipse.swt.events.TraverseEvent;
    035import org.eclipse.swt.events.TraverseListener;
    036import org.eclipse.swt.graphics.Point;
    037import org.eclipse.swt.graphics.Rectangle;
    038import org.eclipse.swt.layout.GridData;
    039import org.eclipse.swt.layout.GridLayout;
    040import org.eclipse.swt.widgets.Button;
    041import org.eclipse.swt.widgets.Combo;
    042import org.eclipse.swt.widgets.Composite;
    043import org.eclipse.swt.widgets.Display;
    044import org.eclipse.swt.widgets.Event;
    045import org.eclipse.swt.widgets.Label;
    046import org.eclipse.swt.widgets.Listener;
    047import org.eclipse.swt.widgets.Shell;
    048import org.eclipse.swt.widgets.Table;
    049import org.eclipse.swt.widgets.TableColumn;
    050import org.eclipse.swt.widgets.TableItem;
    051import org.eclipse.swt.widgets.Text;
    052
    053import hdf.object.Attribute;
    054import hdf.object.Datatype;
    055import hdf.object.Group;
    056import hdf.object.HObject;
    057import hdf.object.h5.H5CompoundAttr;
    058import hdf.object.h5.H5Datatype;
    059
    060import hdf.view.Tools;
    061import hdf.view.ViewProperties;
    062
    063/**
    064 * NewCompoundAttributeDialog shows a message dialog requesting user input for creating
    065 * a new HDF5 compound attribute.
    066 *
    067 * @author Allen Byrne
    068 * @version 1.0 7/20/2021
    069 */
    070public class NewCompoundAttributeDialog extends NewDataObjectDialog {
    071
    072    private static final Logger log = LoggerFactory.getLogger(NewCompoundAttributeDialog.class);
    073
    074    private static final String[] DATATYPE_NAMES   = {
    075        "byte (8-bit)", // 0
    076        "short (16-bit)", // 1
    077        "int (32-bit)", // 2
    078        "unsigned byte (8-bit)", // 3
    079        "unsigned short (16-bit)", // 4
    080        "unsigned int (32-bit)", // 5
    081        "long (64-bit)", // 6
    082        "float", // 7
    083        "double", // 8
    084        "string", // 9
    085        "enum", // 10
    086        "unsigned long (64-bit)" // 11
    087    };
    088
    089    private Combo                 nFieldBox, templateChoice;
    090
    091    private Vector<H5CompoundAttr>  compoundAttrList;
    092
    093    private int                   numberOfMembers;
    094
    095    private Table                 table;
    096
    097    private TableEditor[][]       editors;
    098
    099    private Text                  nameField, currentSizeField;
    100
    101    private Combo                 rankChoice;
    102
    103    /**
    104     * Constructs a NewCompoundAttributeDialog with specified list of possible parent
    105     * objects.
    106     *
    107     * @param parent
    108     *            the parent shell of the dialog
    109     * @param pObject
    110     *            the parent object which the new attribute is attached to.
    111     * @param objs
    112     *            the list of all objects.
    113     */
    114    public NewCompoundAttributeDialog(Shell parent, HObject pObject, List<HObject> objs) {
    115        super(parent, pObject, objs);
    116
    117        numberOfMembers = 2;
    118
    119        compoundAttrList = new Vector<>(objs.size());
    120    }
    121
    122    /**
    123     * Open the NewCompoundAttributeDialog for adding a new compound attribute.
    124     */
    125    public void open() {
    126        Shell parent = getParent();
    127        shell = new Shell(parent, SWT.SHELL_TRIM | SWT.APPLICATION_MODAL);
    128        shell.setFont(curFont);
    129        shell.setText("New Compound Attribute...");
    130        shell.setImages(ViewProperties.getHdfIcons());
    131        shell.setLayout(new GridLayout(1, false));
    132
    133
    134        // Create Name/Parent Object/Import field region
    135        Composite fieldComposite = new Composite(shell, SWT.NONE);
    136        GridLayout layout = new GridLayout(2, false);
    137        layout.verticalSpacing = 0;
    138        fieldComposite.setLayout(layout);
    139        fieldComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
    140
    141        Label attributeNameLabel = new Label(fieldComposite, SWT.LEFT);
    142        attributeNameLabel.setFont(curFont);
    143        attributeNameLabel.setText("Attribute name: ");
    144
    145        nameField = new Text(fieldComposite, SWT.SINGLE | SWT.BORDER);
    146        nameField.setFont(curFont);
    147        nameField.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
    148
    149        // Create Dataspace region
    150        org.eclipse.swt.widgets.Group dataspaceGroup = new org.eclipse.swt.widgets.Group(shell, SWT.NONE);
    151        dataspaceGroup.setFont(curFont);
    152        dataspaceGroup.setText("Dataspace");
    153        dataspaceGroup.setLayout(new GridLayout(3, true));
    154        dataspaceGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
    155
    156        Label label = new Label(dataspaceGroup, SWT.LEFT);
    157        label.setFont(curFont);
    158        label.setText("No. of dimensions");
    159
    160        label = new Label(dataspaceGroup, SWT.LEFT);
    161        label.setFont(curFont);
    162        label.setText("Current size");
    163
    164        // Dummy label
    165        label = new Label(dataspaceGroup, SWT.LEFT);
    166        label.setFont(curFont);
    167        label.setText("");
    168
    169        rankChoice = new Combo(dataspaceGroup, SWT.DROP_DOWN | SWT.READ_ONLY);
    170        rankChoice.setFont(curFont);
    171        rankChoice.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
    172        rankChoice.addSelectionListener(new SelectionAdapter() {
    173            @Override
    174            public void widgetSelected(SelectionEvent e) {
    175                int rank = rankChoice.getSelectionIndex() + 1;
    176                StringBuilder currentSizeStr = new StringBuilder("1");
    177
    178                for (int i = 1; i < rank; i++) {
    179                    currentSizeStr.append(" x 1");
    180                }
    181
    182                currentSizeField.setText(currentSizeStr.toString());
    183
    184                String currentStr = currentSizeField.getText();
    185                int idx = currentStr.lastIndexOf('x');
    186            }
    187        });
    188
    189        for (int i = 1; i < 33; i++) {
    190            rankChoice.add(String.valueOf(i));
    191        }
    192        rankChoice.select(1);
    193
    194        currentSizeField = new Text(dataspaceGroup, SWT.SINGLE | SWT.BORDER);
    195        currentSizeField.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
    196        currentSizeField.setFont(curFont);
    197        currentSizeField.setText("1 x 1");
    198
    199        // Create Properties region
    200        org.eclipse.swt.widgets.Group propertiesGroup = new org.eclipse.swt.widgets.Group(shell, SWT.NONE);
    201        propertiesGroup.setLayout(new GridLayout(2, false));
    202        propertiesGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
    203        propertiesGroup.setFont(curFont);
    204        propertiesGroup.setText("Compound Datatype Properties");
    205
    206        label = new Label(propertiesGroup, SWT.LEFT);
    207        label.setFont(curFont);
    208        label.setText("Number of Members:");
    209
    210        nFieldBox = new Combo(propertiesGroup, SWT.DROP_DOWN);
    211        nFieldBox.setFont(curFont);
    212        nFieldBox.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
    213        nFieldBox.addSelectionListener(new SelectionAdapter() {
    214            @Override
    215            public void widgetSelected(SelectionEvent e) {
    216                updateMemberTableItems();
    217            }
    218        });
    219        nFieldBox.addTraverseListener(new TraverseListener() {
    220            @Override
    221            public void keyTraversed(TraverseEvent e) {
    222                if (e.detail == SWT.TRAVERSE_RETURN) updateMemberTableItems();
    223            }
    224        });
    225
    226        for (int i = 1; i <= 100; i++) {
    227            nFieldBox.add(String.valueOf(i));
    228        }
    229
    230        table = new Table(propertiesGroup, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL);
    231        table.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1));
    232        table.setLinesVisible(false);
    233        table.setHeaderVisible(true);
    234        table.setFont(curFont);
    235
    236        editors = new TableEditor[nFieldBox.getItemCount()][3];
    237
    238        String[] colNames = { "Name", "Datatype", "Array size / String length / Enum names" };
    239
    240        TableColumn column = new TableColumn(table, SWT.NONE);
    241        column.setText(colNames[0]);
    242
    243        column = new TableColumn(table, SWT.NONE);
    244        column.setText(colNames[1]);
    245
    246        column = new TableColumn(table, SWT.NONE);
    247        column.setText(colNames[2]);
    248
    249        for (int i = 0; i < 2; i++) {
    250            TableEditor[] editor = addMemberTableItem(table);
    251            editors[i][0] = editor[0];
    252            editors[i][1] = editor[1];
    253            editors[i][2] = editor[2];
    254        }
    255
    256        for(int i = 0; i < table.getColumnCount(); i++) {
    257            table.getColumn(i).pack();
    258        }
    259
    260        // Last table column always expands to fill remaining table size
    261        table.addListener(SWT.Resize, new Listener() {
    262            @Override
    263            public void handleEvent(Event e) {
    264                Table table = (Table) e.widget;
    265                Rectangle area = table.getClientArea();
    266                int columnCount = table.getColumnCount();
    267                int totalGridLineWidth = (columnCount - 1) * table.getGridLineWidth();
    268
    269                int totalColumnWidth = 0;
    270                for (TableColumn column : table.getColumns()) {
    271                    totalColumnWidth += column.getWidth();
    272                }
    273
    274                int diff = area.width - (totalColumnWidth + totalGridLineWidth);
    275
    276                TableColumn col = table.getColumns()[columnCount - 1];
    277                col.setWidth(diff + col.getWidth());
    278            }
    279        });
    280
    281        // Disable table selection highlighting
    282        table.addListener(SWT.EraseItem, new Listener() {
    283            @Override
    284            public void handleEvent(Event e) {
    285                if ((e.detail & SWT.SELECTED) != 0) {
    286                    e.detail &= ~SWT.SELECTED;
    287                }
    288            }
    289        });
    290
    291        // Create Ok/Cancel button region
    292        Composite buttonComposite = new Composite(shell, SWT.NONE);
    293        buttonComposite.setLayout(new GridLayout(2, true));
    294        buttonComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 2, 1));
    295
    296        Button okButton = new Button(buttonComposite, SWT.PUSH);
    297        okButton.setFont(curFont);
    298        okButton.setText("   &OK   ");
    299        okButton.setLayoutData(new GridData(SWT.END, SWT.FILL, true, false));
    300        okButton.addSelectionListener(new SelectionAdapter() {
    301            @Override
    302            public void widgetSelected(SelectionEvent e) {
    303                if (createAttribute()) {
    304                    shell.dispose();
    305                }
    306            }
    307        });
    308
    309        Button cancelButton = new Button(buttonComposite, SWT.PUSH);
    310        cancelButton.setFont(curFont);
    311        cancelButton.setText(" &Cancel ");
    312        cancelButton.setLayoutData(new GridData(SWT.BEGINNING, SWT.FILL, true, false));
    313        cancelButton.addSelectionListener(new SelectionAdapter() {
    314            @Override
    315            public void widgetSelected(SelectionEvent e) {
    316                newObject = null;
    317                shell.dispose();
    318            }
    319        });
    320
    321        rankChoice.select(0);
    322        nFieldBox.select(nFieldBox.indexOf(String.valueOf(numberOfMembers)));
    323
    324        shell.pack();
    325
    326        table.getColumn(0).setWidth(table.getClientArea().width / 3);
    327        table.getColumn(1).setWidth(table.getClientArea().width / 3);
    328
    329        shell.addDisposeListener(new DisposeListener() {
    330            @Override
    331            public void widgetDisposed(DisposeEvent e) {
    332                if (curFont != null) curFont.dispose();
    333            }
    334        });
    335
    336        shell.setMinimumSize(shell.computeSize(SWT.DEFAULT, SWT.DEFAULT));
    337
    338        Rectangle parentBounds = parent.getBounds();
    339        Point shellSize = shell.getSize();
    340        shell.setLocation((parentBounds.x + (parentBounds.width / 2)) - (shellSize.x / 2),
    341                          (parentBounds.y + (parentBounds.height / 2)) - (shellSize.y / 2));
    342
    343        shell.open();
    344
    345        Display display = shell.getDisplay();
    346        while (!shell.isDisposed())
    347            if (!display.readAndDispatch())
    348                display.sleep();
    349    }
    350
    351    @SuppressWarnings("unchecked")
    352    private boolean createAttribute() {
    353        String attrName = null;
    354        int rank = -1;
    355        long[] dims;
    356
    357        attrName = nameField.getText();
    358        if (attrName != null) {
    359            attrName = attrName.trim();
    360        }
    361
    362        if ((attrName == null) || (attrName.length() < 1)) {
    363            shell.getDisplay().beep();
    364            Tools.showError(shell, "Create", "Attribute name is not specified.");
    365            return false;
    366        }
    367
    368        int n = table.getItemCount();
    369        if (n <= 0) {
    370            return false;
    371        }
    372
    373        String[] mNames = new String[n];
    374        Datatype[] mDatatypes = new Datatype[n];
    375        int[] mOrders = new int[n];
    376
    377        for (int i = 0; i < n; i++) {
    378            String name = (String) table.getItem(i).getData("MemberName");
    379            if ((name == null) || (name.length() <= 0)) {
    380                throw new IllegalArgumentException("Member name is empty");
    381            }
    382            mNames[i] = name;
    383            log.trace("createCompoundAttribute member[{}] name = {}", i, mNames[i]);
    384
    385            int order = 1;
    386            String orderStr = (String) table.getItem(i).getData("MemberSize");
    387            if (orderStr != null) {
    388                try {
    389                    order = Integer.parseInt(orderStr);
    390                }
    391                catch (Exception ex) {
    392                    log.debug("compound order:", ex);
    393                }
    394            }
    395            mOrders[i] = order;
    396
    397            String typeName = (String) table.getItem(i).getData("MemberType");
    398            log.trace("createCompoundAttribute type[{}] name = {}", i, typeName);
    399            Datatype type = null;
    400            try {
    401                if (DATATYPE_NAMES[0].equals(typeName)) {
    402                    type = fileFormat.createDatatype(Datatype.CLASS_INTEGER, 1, Datatype.NATIVE, Datatype.NATIVE);
    403                }
    404                else if (DATATYPE_NAMES[1].equals(typeName)) {
    405                    type = fileFormat.createDatatype(Datatype.CLASS_INTEGER, 2, Datatype.NATIVE, Datatype.NATIVE);
    406                }
    407                else if (DATATYPE_NAMES[2].equals(typeName)) {
    408                    type = fileFormat.createDatatype(Datatype.CLASS_INTEGER, 4, Datatype.NATIVE, Datatype.NATIVE);
    409                }
    410                else if (DATATYPE_NAMES[3].equals(typeName)) {
    411                    type = fileFormat.createDatatype(Datatype.CLASS_INTEGER, 1, Datatype.NATIVE, Datatype.SIGN_NONE);
    412                }
    413                else if (DATATYPE_NAMES[4].equals(typeName)) {
    414                    type = fileFormat.createDatatype(Datatype.CLASS_INTEGER, 2, Datatype.NATIVE, Datatype.SIGN_NONE);
    415                }
    416                else if (DATATYPE_NAMES[5].equals(typeName)) {
    417                    type = fileFormat.createDatatype(Datatype.CLASS_INTEGER, 4, Datatype.NATIVE, Datatype.SIGN_NONE);
    418                }
    419                else if (DATATYPE_NAMES[6].equals(typeName)) {
    420                    type = fileFormat.createDatatype(Datatype.CLASS_INTEGER, 8, Datatype.NATIVE, Datatype.NATIVE);
    421                }
    422                else if (DATATYPE_NAMES[7].equals(typeName)) {
    423                    type = fileFormat.createDatatype(Datatype.CLASS_FLOAT, 4, Datatype.NATIVE, Datatype.NATIVE);
    424                }
    425                else if (DATATYPE_NAMES[8].equals(typeName)) {
    426                    type = fileFormat.createDatatype(Datatype.CLASS_FLOAT, 8, Datatype.NATIVE, Datatype.NATIVE);
    427                }
    428                else if (DATATYPE_NAMES[9].equals(typeName)) {
    429                    type = fileFormat.createDatatype(Datatype.CLASS_STRING, order, Datatype.NATIVE, Datatype.NATIVE);
    430                }
    431                else if (DATATYPE_NAMES[10].equals(typeName)) { // enum
    432                    type = fileFormat.createDatatype(Datatype.CLASS_ENUM, 4, Datatype.NATIVE, Datatype.NATIVE);
    433                    if ((orderStr == null) || (orderStr.length() < 1) || orderStr.endsWith("...")) {
    434                        shell.getDisplay().beep();
    435                        Tools.showError(shell, "Create", "Invalid member values: " + orderStr);
    436                        return false;
    437                    }
    438                    else {
    439                        type.setEnumMembers(orderStr);
    440                    }
    441                }
    442                else if (DATATYPE_NAMES[11].equals(typeName)) {
    443                    type = fileFormat.createDatatype(Datatype.CLASS_INTEGER, 8, Datatype.NATIVE, Datatype.SIGN_NONE);
    444                }
    445                else {
    446                    throw new IllegalArgumentException("Invalid data type.");
    447                }
    448                mDatatypes[i] = type;
    449            }
    450            catch (Exception ex) {
    451                Tools.showError(shell, "Create", ex.getMessage());
    452                log.debug("createAttribute(): ", ex);
    453                return false;
    454            }
    455        } //  (int i=0; i<n; i++)
    456
    457        rank = rankChoice.getSelectionIndex() + 1;
    458        log.trace("createCompoundAttribute rank={}", rank);
    459        StringTokenizer st = new StringTokenizer(currentSizeField.getText(), "x");
    460        if (st.countTokens() < rank) {
    461            shell.getDisplay().beep();
    462            Tools.showError(shell, "Create", "Number of values in the current dimension size is less than " + rank);
    463            return false;
    464        }
    465
    466        long lsize = 1; // The total size
    467        long l = 0;
    468        dims = new long[rank];
    469        String token = null;
    470        for (int i = 0; i < rank; i++) {
    471            token = st.nextToken().trim();
    472            try {
    473                l = Long.parseLong(token);
    474            }
    475            catch (NumberFormatException ex) {
    476                shell.getDisplay().beep();
    477                Tools.showError(shell, "Create", "Invalid dimension size: " + currentSizeField.getText());
    478                return false;
    479            }
    480
    481            if (l <= 0) {
    482                shell.getDisplay().beep();
    483                Tools.showError(shell, "Create", "Dimension size must be greater than zero.");
    484                return false;
    485            }
    486
    487            dims[i] = l;
    488            lsize *= l;
    489        }
    490        log.trace("Create: lsize={}", lsize);
    491
    492        Attribute attr = null;
    493        try {
    494            H5Datatype datatype = (H5Datatype)createNewDatatype(null);
    495
    496            attr = (Attribute)new H5CompoundAttr(parentObj, attrName, datatype, dims);
    497            Object value = H5Datatype.allocateArray(datatype, (int) lsize);
    498            attr.setAttributeData(value);
    499
    500            log.trace("writeMetadata() via write()");
    501            attr.writeAttribute();
    502        }
    503        catch (Exception ex) {
    504            Tools.showError(shell, "Create", ex.getMessage());
    505            log.debug("createAttribute(): ", ex);
    506            return false;
    507        }
    508
    509        newObject = (HObject)attr;
    510
    511        return true;
    512    }
    513
    514    private void updateMemberTableItems() {
    515        int n = 0;
    516
    517        try {
    518            n = Integer.valueOf(nFieldBox.getItem(nFieldBox.getSelectionIndex())).intValue();
    519        }
    520        catch (Exception ex) {
    521            log.debug("Change number of members:", ex);
    522            return;
    523        }
    524
    525        if (n == numberOfMembers) {
    526            return;
    527        }
    528
    529        if(n > numberOfMembers) {
    530            try {
    531                for (int i = numberOfMembers; i < n; i++) {
    532                    TableEditor[] editor = addMemberTableItem(table);
    533                    editors[i][0] = editor[0];
    534                    editors[i][1] = editor[1];
    535                    editors[i][2] = editor[2];
    536                }
    537            }
    538            catch (Exception ex) {
    539                log.debug("Error adding member table items: ", ex);
    540                return;
    541            }
    542        }
    543        else {
    544            try {
    545                for(int i = numberOfMembers - 1; i >= n; i--) {
    546                    table.remove(i);
    547                }
    548            }
    549            catch (Exception ex) {
    550                log.debug("Error removing member table items: ", ex);
    551                return;
    552            }
    553        }
    554
    555        table.setItemCount(n);
    556        numberOfMembers = n;
    557    }
    558
    559    private TableEditor[] addMemberTableItem(Table table) {
    560        final TableItem item = new TableItem(table, SWT.NONE);
    561        final TableEditor[] editor = new TableEditor[3];
    562
    563        for (int i = 0; i < editor.length; i++) editor[i] = new TableEditor(table);
    564
    565        final Text nameText = new Text(table, SWT.SINGLE | SWT.BORDER);
    566        nameText.setFont(curFont);
    567
    568        editor[0].grabHorizontal = true;
    569        editor[0].grabVertical = true;
    570        editor[0].horizontalAlignment = SWT.LEFT;
    571        editor[0].verticalAlignment = SWT.TOP;
    572        editor[0].setEditor(nameText, item, 0);
    573
    574        nameText.addModifyListener(new ModifyListener() {
    575            @Override
    576            public void modifyText(ModifyEvent e) {
    577                Text text = (Text) e.widget;
    578                item.setData("MemberName", text.getText());
    579            }
    580        });
    581
    582        final CCombo typeCombo = new CCombo(table, SWT.DROP_DOWN | SWT.READ_ONLY);
    583        typeCombo.setFont(curFont);
    584        typeCombo.setItems(DATATYPE_NAMES);
    585
    586        editor[1].grabHorizontal = true;
    587        editor[1].grabVertical = true;
    588        editor[1].horizontalAlignment = SWT.LEFT;
    589        editor[1].verticalAlignment = SWT.TOP;
    590        editor[1].setEditor(typeCombo, item, 1);
    591
    592        typeCombo.addSelectionListener(new SelectionAdapter() {
    593            @Override
    594            public void widgetSelected(SelectionEvent e) {
    595                CCombo combo = (CCombo) e.widget;
    596                item.setData("MemberType", combo.getItem(combo.getSelectionIndex()));
    597            }
    598        });
    599
    600        final Text sizeText = new Text(table, SWT.SINGLE | SWT.BORDER);
    601        sizeText.setFont(curFont);
    602
    603        editor[2].grabHorizontal = true;
    604        editor[2].grabVertical = true;
    605        editor[2].horizontalAlignment = SWT.LEFT;
    606        editor[2].verticalAlignment = SWT.TOP;
    607        editor[2].setEditor(sizeText, item, 2);
    608
    609        sizeText.addModifyListener(new ModifyListener() {
    610            @Override
    611            public void modifyText(ModifyEvent e) {
    612                Text text = (Text) e.widget;
    613                item.setData("MemberSize", text.getText());
    614            }
    615        });
    616
    617        item.setData("MemberName", "");
    618        item.setData("MemberType", "");
    619        item.setData("MemberSize", "");
    620
    621        item.addDisposeListener(new DisposeListener() {
    622            @Override
    623            public void widgetDisposed(DisposeEvent e) {
    624                editor[0].dispose();
    625                editor[1].dispose();
    626                editor[2].dispose();
    627                nameText.dispose();
    628                typeCombo.dispose();
    629                sizeText.dispose();
    630            }
    631        });
    632
    633        return editor;
    634    }
    635}