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