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.awt.Image;
018import java.awt.Rectangle;
019import java.awt.Toolkit;
020import java.awt.image.BufferedImage;
021import java.awt.image.ComponentColorModel;
022import java.awt.image.DirectColorModel;
023import java.awt.image.FilteredImageSource;
024import java.awt.image.ImageFilter;
025import java.awt.image.ImageProducer;
026import java.awt.image.IndexColorModel;
027import java.awt.image.WritableRaster;
028import java.util.BitSet;
029import java.util.StringTokenizer;
030import java.util.Vector;
031
032import org.eclipse.swt.SWT;
033import org.eclipse.swt.events.DisposeEvent;
034import org.eclipse.swt.events.DisposeListener;
035import org.eclipse.swt.events.MouseEvent;
036import org.eclipse.swt.events.MouseListener;
037import org.eclipse.swt.events.MouseMoveListener;
038import org.eclipse.swt.events.PaintEvent;
039import org.eclipse.swt.events.PaintListener;
040import org.eclipse.swt.events.SelectionAdapter;
041import org.eclipse.swt.events.SelectionEvent;
042import org.eclipse.swt.graphics.Font;
043import org.eclipse.swt.graphics.GC;
044import org.eclipse.swt.graphics.ImageData;
045import org.eclipse.swt.graphics.PaletteData;
046import org.eclipse.swt.graphics.Point;
047import org.eclipse.swt.graphics.RGB;
048import org.eclipse.swt.layout.GridData;
049import org.eclipse.swt.layout.GridLayout;
050import org.eclipse.swt.widgets.Button;
051import org.eclipse.swt.widgets.Canvas;
052import org.eclipse.swt.widgets.Combo;
053import org.eclipse.swt.widgets.Composite;
054import org.eclipse.swt.widgets.Dialog;
055import org.eclipse.swt.widgets.Display;
056import org.eclipse.swt.widgets.Event;
057import org.eclipse.swt.widgets.Label;
058import org.eclipse.swt.widgets.List;
059import org.eclipse.swt.widgets.Listener;
060import org.eclipse.swt.widgets.Shell;
061import org.eclipse.swt.widgets.Text;
062
063import hdf.object.CompoundDS;
064import hdf.object.DataFormat;
065import hdf.object.Dataset;
066import hdf.object.Datatype;
067import hdf.object.FileFormat;
068import hdf.object.HObject;
069import hdf.object.ScalarDS;
070import hdf.view.HDFView;
071import hdf.view.Tools;
072import hdf.view.ViewProperties;
073import hdf.view.ImageView.DefaultImageView;
074import hdf.view.ImageView.DefaultImageView.FlipFilter;
075import hdf.view.ImageView.DefaultImageView.Rotate90Filter;
076
077/**
078 * DataOptionDialog is an dialog window used to select display options. Display options include
079 * selection of subset, display type (image, text, or spreadsheet).
080 *
081 * @author Jordan T. Henderson
082 * @version 2.4 3/26/2016
083 */
084public class DataOptionDialog extends Dialog {
085
086    private Shell               shell;
087
088    private Font                curFont;
089
090    /** the rank of the dataset/image */
091    private int                 rank;
092
093    /** the starting point of selected subset */
094    private long[]              start;
095
096    /** the sizes of all dimensions */
097    private long[]              dims;
098
099    /** the selected sizes of all dimensions */
100    private long[]              selected;
101
102    /** the stride */
103    private long[]              stride;
104
105    /** the indices of the selected dimensions. */
106    private int[]               selectedIndex;
107    private int[]               currentIndex;
108
109    private BitSet              bitmask;
110
111    private Button              spreadsheetButton;
112    private Button              imageButton;
113    private Button              base1Button;
114    private Button              base0Button;
115    private Button              charCheckbox;
116    private Button              bitmaskHelp;
117    private Button              applyBitmaskButton;
118    private Button              extractBitButton;
119    private Button[]            bitmaskButtons;
120
121    private Combo               choiceTableView;
122    private Combo               choiceImageView;
123    private Combo               choicePalette;
124    private Combo               transposeChoice;
125    private Combo[]             choices;
126
127    private boolean             isSelectionCancelled;
128    private boolean             isTrueColorImage;
129    private boolean             isH5;
130    private boolean             isImageDisplay = false;
131    private boolean             isDisplayTypeChar = false;
132    private boolean             isTransposed = false;
133    private boolean             isIndexBase1 = false;
134    private boolean             isApplyBitmaskOnly = false;
135
136    private String              dataViewName;
137
138    private Label[]             maxLabels;
139
140    private Text[]              startFields;
141    private Text[]              endFields;
142    private Text[]              strideFields;
143
144    private Text                dataRangeField;
145    private Text                fillValueField;
146
147    private List                fieldList;
148
149    private PreviewNavigator    navigator;
150
151    private int                 numberOfPalettes;
152
153    /** the selected dataset/image */
154    private DataFormat          dataObject;
155
156
157    /**
158     * Constructs a DataOptionDialog with the given HDFView.
159     *
160     * @param parent
161     *            the parent of this dialog
162     * @param dataObject
163     *            the data object associated with this dialog
164     */
165    public DataOptionDialog(Shell parent, DataFormat dataObject) {
166        super(parent, SWT.APPLICATION_MODAL);
167
168        if (dataObject == null) return;
169
170        this.dataObject = dataObject;
171
172        try {
173            curFont = new Font(
174                    Display.getCurrent(),
175                    ViewProperties.getFontType(),
176                    ViewProperties.getFontSize(),
177                    SWT.NORMAL);
178        }
179        catch (Exception ex) {
180            curFont = null;
181        }
182
183        isSelectionCancelled = true;
184        isTrueColorImage = false;
185        bitmask = null;
186        numberOfPalettes = 1;
187
188        if (!dataObject.isInited())
189            dataObject.init();
190
191        if (isH5 && (dataObject instanceof ScalarDS)) {
192            byte[] palRefs = ((ScalarDS) dataObject).getPaletteRefs();
193            if ((palRefs != null) && (palRefs.length > 8)) {
194                numberOfPalettes = palRefs.length / 8;
195            }
196        }
197
198        rank = dataObject.getRank();
199        dims = dataObject.getDims();
200        selected = dataObject.getSelectedDims();
201        start = dataObject.getStartDims();
202        selectedIndex = dataObject.getSelectedIndex();
203        stride = dataObject.getStride();
204        currentIndex = new int[Math.min(3, rank)];
205
206        maxLabels = new Label[3];
207        startFields = new Text[3];
208        endFields = new Text[3];
209        strideFields = new Text[3];
210        choices = new Combo[3];
211
212        isH5 = ((HObject) dataObject).getFileFormat().isThisType(
213                FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF5));
214    }
215
216    public void open() {
217        Shell parent = getParent();
218        shell = new Shell(parent, SWT.SHELL_TRIM | SWT.APPLICATION_MODAL);
219        shell.setFont(curFont);
220        shell.setText("Dataset Selection - " + ((HObject) dataObject).getPath() + ((HObject) dataObject).getName());
221        shell.setImage(ViewProperties.getHdfIcon());
222        shell.setLayout(new GridLayout(1, true));
223
224        if (dataObject instanceof ScalarDS) {
225            createScalarDSContents();
226        }
227        else if (dataObject instanceof CompoundDS) {
228            createCompoundDSContents();
229        }
230
231        // Create Ok/Cancel button region
232        Composite buttonComposite = new Composite(shell, SWT.NONE);
233        buttonComposite.setLayout(new GridLayout(2, true));
234        buttonComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 2, 1));
235
236        Button okButton = new Button(buttonComposite, SWT.PUSH);
237        okButton.setFont(curFont);
238        okButton.setText("   &OK   ");
239        okButton.setLayoutData(new GridData(SWT.END, SWT.FILL, true, false));
240        okButton.addSelectionListener(new SelectionAdapter() {
241            @Override
242            public void widgetSelected(SelectionEvent e) {
243                // set palette for image view
244                if(imageButton != null) {
245                    if ((dataObject instanceof ScalarDS) && imageButton.getSelection()) {
246                        setPalette();
247                    }
248                }
249
250                isSelectionCancelled = !setSelection();
251
252                if (isSelectionCancelled) {
253                    return;
254                }
255
256                if(imageButton != null) {
257                    if (dataObject instanceof ScalarDS) {
258                        ((ScalarDS) dataObject).setIsImageDisplay(imageButton.getSelection());
259                    }
260                }
261
262                shell.notifyListeners(SWT.Close, null);
263
264                shell.dispose();
265            }
266        });
267
268        Button cancelButton = new Button(buttonComposite, SWT.PUSH);
269        cancelButton.setFont(curFont);
270        cancelButton.setText(" &Cancel ");
271        cancelButton.setLayoutData(new GridData(SWT.BEGINNING, SWT.FILL, true, false));
272        cancelButton.addSelectionListener(new SelectionAdapter() {
273            @Override
274            public void widgetSelected(SelectionEvent e) {
275                shell.notifyListeners(SWT.Close, null);
276
277                shell.dispose();
278            }
279        });
280
281        shell.pack();
282
283        init();
284
285        shell.setMinimumSize(shell.computeSize(SWT.DEFAULT, SWT.DEFAULT));
286
287        org.eclipse.swt.graphics.Rectangle parentBounds = parent.getBounds();
288        Point shellSize = shell.getSize();
289        shell.setLocation((parentBounds.x + (parentBounds.width / 2)) - (shellSize.x / 2),
290                (parentBounds.y + (parentBounds.height / 2)) - (shellSize.y / 2));
291
292        shell.addListener(SWT.Close, new Listener() {
293            @Override
294            public void handleEvent(Event e) {
295                if (imageButton == null) {
296                    isImageDisplay = false;
297                }
298                else {
299                    isImageDisplay = imageButton.getSelection();
300                }
301
302                if (charCheckbox == null) {
303                    isDisplayTypeChar = false;
304                }
305                else {
306                    isDisplayTypeChar = charCheckbox.getSelection();
307                }
308
309                if (transposeChoice == null) {
310                    isTransposed = false;
311                }
312                else {
313                    isTransposed = transposeChoice.isEnabled() && transposeChoice.getSelectionIndex() == 0;
314                }
315
316                if (base1Button == null) {
317                    isIndexBase1 = false;
318                }
319                else {
320                    isIndexBase1 = base1Button.getSelection();
321                }
322
323                if (applyBitmaskButton == null) {
324                    isApplyBitmaskOnly = false;
325                }
326                else {
327                    isApplyBitmaskOnly = applyBitmaskButton.getSelection();
328                }
329
330                if (isImageDisplay()) {
331                    dataViewName = choiceImageView.getItem(choiceImageView.getSelectionIndex());
332                }
333                else {
334                    dataViewName = choiceTableView.getItem(choiceTableView.getSelectionIndex());
335                }
336            }
337        });
338
339        shell.addDisposeListener(new DisposeListener() {
340            @Override
341            public void widgetDisposed(DisposeEvent e) {
342                if (curFont != null) curFont.dispose();
343            }
344        });
345
346        shell.open();
347
348        // Prevent SWT from selecting TableView button by
349        // default if dataset is an image
350        if (dataObject instanceof ScalarDS) {
351            if (((ScalarDS) dataObject).isImageDisplay()) {
352                spreadsheetButton.setSelection(false);
353            }
354        }
355
356        Display display = parent.getDisplay();
357        while(!shell.isDisposed()) {
358            if (!display.readAndDispatch())
359                display.sleep();
360        }
361    }
362
363    /**
364     * Set the initial state of all the variables
365     */
366    private void init() {
367        // set the imagebutton state
368        boolean isImage = false;
369
370        if (dataObject instanceof ScalarDS) {
371            if (!dataObject.getDatatype().isText()) {
372                ScalarDS sd = (ScalarDS) dataObject;
373                isImage = sd.isImageDisplay();
374                isTrueColorImage = sd.isTrueColor();
375                // compound datasets don't have data range or fill values
376                // (JAVA-1825)
377                dataRangeField.setEnabled(isImage);
378                fillValueField.setEnabled(isImage);
379            }
380        }
381
382        if(choiceTableView != null) {
383            choiceTableView.setEnabled(!isImage);
384        }
385
386        if(choiceImageView != null) {
387            choiceImageView.setEnabled(isImage);
388        }
389
390        if(imageButton != null) {
391            imageButton.setSelection(isImage);
392        }
393
394        if(choicePalette != null) {
395            choicePalette.setEnabled(isImage && !isTrueColorImage);
396        }
397
398        int n = Math.min(3, rank);
399        long endIdx = 0;
400        for (int i = 0; i < n; i++) {
401            choices[i].setEnabled(true);
402            startFields[i].setEnabled(true);
403            endFields[i].setEnabled(true);
404            strideFields[i].setEnabled(true);
405            maxLabels[i].setEnabled(true);
406
407            int idx = selectedIndex[i];
408            endIdx = start[idx] + selected[idx] * stride[idx];
409            if (endIdx >= dims[idx]) {
410                endIdx = dims[idx];
411            }
412
413            choices[i].select(idx);
414            maxLabels[i].setText(String.valueOf(dims[idx]));
415            startFields[i].setText(String.valueOf(start[idx]));
416            endFields[i].setText(String.valueOf(endIdx - 1));
417
418            if (!isH5 && (dataObject instanceof CompoundDS)) {
419                strideFields[i].setEnabled(false);
420            }
421            else {
422                strideFields[i].setText(String.valueOf(stride[idx]));
423            }
424        }
425
426        if (rank > 1) {
427            transposeChoice.setEnabled((choices[0].getSelectionIndex() > choices[1]
428                    .getSelectionIndex()));
429
430            if (rank > 2) {
431                endFields[2].setEnabled(false);
432                strideFields[2].setEnabled(false);
433
434                if (isTrueColorImage && imageButton != null) {
435                    if(imageButton.getSelection()) {
436                        choices[0].setEnabled(false);
437                        choices[1].setEnabled(false);
438                        choices[2].setEnabled(false);
439                        startFields[2].setEnabled(false);
440                        startFields[2].setText("0");
441                        endFields[2].setEnabled(false);
442                        endFields[2].setText("0");
443                    }
444                }
445                else {
446                    endFields[2].setText(startFields[2].getText());
447                }
448            }
449        }
450
451        for (int i = 0; i < n; i++) {
452            currentIndex[i] = choices[i].getSelectionIndex();
453        }
454
455        // reset show char button
456        Datatype dtype = dataObject.getDatatype();
457        if (dtype.isChar() || dtype.isInteger()) {
458            int tsize = (int) dtype.getDatatypeSize();
459
460            if(charCheckbox != null) {
461                charCheckbox.setEnabled((tsize == 1) && spreadsheetButton.getSelection());
462            }
463
464            if(extractBitButton != null) {
465                extractBitButton.setEnabled(tsize <= 8);
466            }
467
468            if(applyBitmaskButton != null) {
469                applyBitmaskButton.setEnabled(tsize <= 8);
470            }
471        }
472        else {
473            if(charCheckbox != null) {
474                charCheckbox.setEnabled(false);
475                charCheckbox.setSelection(false);
476            }
477
478            if(extractBitButton != null) {
479                extractBitButton.setEnabled(false);
480            }
481
482            if(applyBitmaskButton != null) {
483                applyBitmaskButton.setEnabled(false);
484            }
485        }
486    }
487
488    private void setPalette() {
489        if (!(dataObject instanceof ScalarDS)) {
490            return;
491        }
492
493        byte[][] pal = null;
494        int palChoice = choicePalette.getSelectionIndex();
495
496        if (palChoice == 0) {
497            return; /* using default palette */
498        }
499
500        if (palChoice == numberOfPalettes + 1) {
501            pal = Tools.createGrayPalette();
502        }
503        else if (palChoice == numberOfPalettes + 2) {
504            pal = Tools.createReverseGrayPalette();
505        }
506        else if (palChoice == numberOfPalettes + 3) {
507            pal = Tools.createGrayWavePalette();
508        }
509        else if (palChoice == numberOfPalettes + 4) {
510            pal = Tools.createRainbowPalette();
511        }
512        else if (palChoice == numberOfPalettes + 5) {
513            pal = Tools.createNaturePalette();
514        }
515        else if (palChoice == numberOfPalettes + 6) {
516            pal = Tools.createWavePalette();
517        }
518        else if ((palChoice > 0) && (palChoice <= numberOfPalettes)) {
519            // multiple palettes attached
520            pal = ((ScalarDS) dataObject).readPalette(palChoice - 1);
521        }
522
523        ((ScalarDS) dataObject).setPalette(pal);
524    }
525
526    private boolean setSelection() {
527        long[] n0 = { 0, 0, 0 }; // start
528        long[] n1 = { 0, 0, 0 }; // end
529        long[] n2 = { 1, 1, 1 }; // stride
530        int[] sIndex = { 0, 1, 2 };
531        boolean retVal = true;
532
533        int n = Math.min(3, rank);
534        for (int i = 0; i < n; i++) {
535            sIndex[i] = choices[i].getSelectionIndex();
536
537            try {
538                n0[i] = Long.parseLong(startFields[i].getText());
539                if (i < 2) {
540                    n1[i] = Long.parseLong(endFields[i].getText());
541                    n2[i] = Long.parseLong(strideFields[i].getText());
542                }
543            }
544            catch (NumberFormatException ex) {
545                shell.getDisplay().beep();
546                Tools.showError(shell, "Set", ex.getMessage());
547                return false;
548            }
549
550            // silently correct errors
551            if (n0[i] < 0) {
552                n0[i] = 0; // start
553            }
554            if (n0[i] >= dims[sIndex[i]]) {
555                n0[i] = dims[sIndex[i]] - 1;
556            }
557            if (n1[i] < 0) {
558                n1[i] = 0; // end
559            }
560            if (n1[i] >= dims[sIndex[i]]) {
561                n1[i] = dims[sIndex[i]] - 1;
562            }
563            if (n0[i] > n1[i]) {
564                n1[i] = n0[i]; // end <= start
565            }
566            if (n2[i] > dims[sIndex[i]]) {
567                n2[i] = dims[sIndex[i]];
568            }
569            if (n2[i] <= 0) {
570                n2[i] = 1; // stride cannot be zero
571            }
572        } //  (int i=0; i<n; i++)
573
574        if (dataObject instanceof CompoundDS) {
575            CompoundDS d = (CompoundDS) dataObject;
576            int[] selectedFieldIndices = fieldList.getSelectionIndices();
577            if ((selectedFieldIndices == null)
578                    || (selectedFieldIndices.length < 1)) {
579                shell.getDisplay().beep();
580                Tools.showError(shell, "Set", "No member/field is selected.");
581                return false;
582            }
583
584            d.setAllMemberSelection(false); // deselect all members
585            for (int i = 0; i < selectedFieldIndices.length; i++) {
586                d.selectMember(selectedFieldIndices[i]);
587            }
588        }
589        else {
590            ScalarDS ds = (ScalarDS) dataObject;
591
592            if (!ds.getDatatype().isText()) {
593                StringTokenizer st = new StringTokenizer(dataRangeField.getText(), ",");
594                if (st.countTokens() == 2) {
595                    double min = 0, max = 0;
596                    try {
597                        min = Double.valueOf(st.nextToken());
598                        max = Double.valueOf(st.nextToken());
599                    }
600                    catch (Exception ex) {
601                    }
602                    if (max > min)
603                        ds.setImageDataRange(min, max);
604                }
605                st = new StringTokenizer(fillValueField.getText(), ",");
606                while (st.hasMoreTokens()) {
607                    double x = 0;
608                    try {
609                        x = Double.valueOf(st.nextToken());
610                        ds.addFilteredImageValue(x);
611                    }
612                    catch (Exception ex) {
613                    }
614                }
615            }
616        }
617
618        // reset selected size
619        for (int i = 0; i < rank; i++) {
620            selected[i] = 1;
621            stride[i] = 1;
622        }
623
624        // find no error, set selection the the dataset object
625        for (int i = 0; i < n; i++) {
626            long selectedSize = ((n1[i] - n0[i]) / n2[i]) + 1;
627
628            /*
629             * Since Java does not allow array indices to be larger than int type, check the
630             * given value to see if it is within the valid range of a Java int.
631             */
632            if (!Tools.checkValidJavaArrayIndex(selectedSize)) {
633                shell.getDisplay().beep();
634                Tools.showError(shell, "Set", "Subset selection too large to display.");
635                return false;
636            }
637
638            selectedIndex[i] = sIndex[i];
639            start[selectedIndex[i]] = n0[i];
640            selected[selectedIndex[i]] = (int) selectedSize;
641            stride[selectedIndex[i]] = n2[i];
642        }
643
644        if ((rank > 2) && isTrueColorImage && imageButton.getSelection()) {
645            start[selectedIndex[2]] = 0;
646            selected[selectedIndex[2]] = 3;
647        }
648
649        // clear the old data
650        dataObject.clearData();
651
652        setBitmask();
653
654        return retVal;
655    }
656
657    private void setBitmask() {
658        boolean isAll = true;
659        boolean isNothing = true;
660
661        if (bitmaskButtons == null) {
662            bitmask = null;
663            return;
664        }
665
666        if (!(applyBitmaskButton.getSelection() || extractBitButton.getSelection())) {
667            bitmask = null;
668            return;
669        }
670
671        int len = bitmaskButtons.length;
672        for (int i = 0; i < len; i++) {
673            isAll = (isAll && bitmaskButtons[i].getSelection());
674            isNothing = (isNothing && !bitmaskButtons[i].getSelection());
675        }
676
677        if (isAll || isNothing) {
678            bitmask = null;
679            return;
680        }
681
682        if (bitmask == null)
683            bitmask = new BitSet(len);
684
685        for (int i = 0; i < len; i++) {
686            /* Bitmask buttons are indexed from highest to lowest */
687            bitmask.set(i, bitmaskButtons[len - i - 1].getSelection());
688        }
689    }
690
691    /** @return true if the display option is image. */
692    public boolean isImageDisplay() {
693        return isImageDisplay;
694    }
695
696    /** @return true if the index starts with 0. */
697    public boolean isIndexBase1() {
698        return isIndexBase1;
699    }
700
701    /**
702     * @return the bitmask.
703     */
704    public BitSet getBitmask() {
705        if (bitmask == null)
706            return null;
707
708        // do not use bitmask if it is empty (all bits are zero)
709        if (bitmask.isEmpty())
710            return null;
711
712        boolean isAllSelected = true;
713        int size = bitmask.size();
714        for (int i = 0; i < size; i++)
715            isAllSelected = (bitmask.get(i) && isAllSelected);
716
717        // do not use bitmask if it is full (all bits are one)
718        if (isAllSelected)
719            return null;
720
721        return bitmask;
722    }
723
724    /** @return the name of the selected dataview */
725    public String getDataViewName() {
726        return dataViewName;
727    }
728
729    /**
730     *
731     * @return true if display the data as characters; otherwise, display as numbers.
732     */
733    public boolean isDisplayTypeChar() {
734        return isDisplayTypeChar;
735    }
736
737    /**
738     * @return if it only apply bitmask.
739     */
740    public boolean isApplyBitmaskOnly() {
741        return isApplyBitmaskOnly;
742    }
743
744    /**
745     *
746     * @return true if transpose the data in 2D table; otherwise, do not transpose the data.
747     */
748    public boolean isTransposed() {
749        return isTransposed;
750    }
751
752    /** @return true if the data selection is cancelled. */
753    public boolean isCancelled() {
754        return isSelectionCancelled;
755    }
756
757    private void createScalarDSContents() {
758        // Create display type region
759        org.eclipse.swt.widgets.Group displayAsGroup = new org.eclipse.swt.widgets.Group(shell, SWT.NONE);
760        displayAsGroup.setFont(curFont);
761        displayAsGroup.setText("Display As");
762        displayAsGroup.setLayout(new GridLayout(1, true));
763        displayAsGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
764
765        Composite spreadsheetComposite = new Composite(displayAsGroup, SWT.BORDER);
766        spreadsheetComposite.setLayout(new GridLayout(2, false));
767        spreadsheetComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
768
769        spreadsheetButton = new Button(spreadsheetComposite, SWT.RADIO);
770        spreadsheetButton.setFont(curFont);
771        spreadsheetButton.setText("&Spreadsheet");
772        spreadsheetButton.setSelection(true);
773        spreadsheetButton.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
774        spreadsheetButton.addSelectionListener(new SelectionAdapter() {
775            @Override
776            public void widgetSelected(SelectionEvent e) {
777                imageButton.setSelection(!spreadsheetButton.getSelection());
778                choicePalette.setEnabled(false);
779                choiceImageView.setEnabled(false);
780                choiceTableView.setEnabled(true);
781                dataRangeField.setEnabled(false);
782                fillValueField.setEnabled(false);
783                Datatype dtype = dataObject.getDatatype();
784                charCheckbox.setEnabled((dtype.isChar() || dtype.isInteger()) &&
785                        (dtype.getDatatypeSize() == 1));
786            }
787        });
788
789        charCheckbox = new Button(spreadsheetComposite, SWT.CHECK);
790        charCheckbox.setFont(curFont);
791        charCheckbox.setText("Show As &Char");
792        charCheckbox.setSelection(false);
793        charCheckbox.setLayoutData(new GridData(SWT.CENTER, SWT.FILL, false, false));
794
795        if (dataObject.getDatatype().isChar()
796                || (dataObject.getDatatype().isInteger() && dataObject.getDatatype().getDatatypeSize() == 1)) {
797            charCheckbox.setEnabled(false);
798        }
799
800        Label label = new Label(spreadsheetComposite, SWT.RIGHT);
801        label.setFont(curFont);
802        label.setText("TableView: ");
803
804        choiceTableView = new Combo(spreadsheetComposite, SWT.SINGLE | SWT.DROP_DOWN | SWT.READ_ONLY);
805        choiceTableView.setFont(curFont);
806        choiceTableView.setItems(HDFView.getListOfTableViews().toArray(new String[0]));
807        choiceTableView.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
808        choiceTableView.select(0);
809
810
811        Composite imageComposite = new Composite(displayAsGroup, SWT.BORDER);
812        imageComposite.setLayout(new GridLayout(4, false));
813        imageComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
814
815        imageButton = new Button(imageComposite, SWT.RADIO);
816        imageButton.setFont(curFont);
817        imageButton.setText("&Image");
818        imageButton.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
819        imageButton.addSelectionListener(new SelectionAdapter() {
820            @Override
821            public void widgetSelected(SelectionEvent e) {
822                spreadsheetButton.setSelection(!imageButton.getSelection());
823                choicePalette.setEnabled(!isTrueColorImage);
824                dataRangeField.setEnabled(true);
825                fillValueField.setEnabled(true);
826                choiceImageView.setEnabled(true);
827                choiceTableView.setEnabled(false);
828                charCheckbox.setSelection(false);
829                charCheckbox.setEnabled(false);
830            }
831        });
832
833        choicePalette = new Combo(imageComposite, SWT.SINGLE | SWT.DROP_DOWN | SWT.READ_ONLY);
834        choicePalette.setFont(curFont);
835        choicePalette.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
836
837        choicePalette.add("Select palette");
838
839        if (dataObject instanceof ScalarDS) {
840            String paletteName = ((ScalarDS) dataObject).getPaletteName(0);
841            if (paletteName == null) {
842                paletteName = "Default";
843            }
844            choicePalette.add(paletteName);
845            for (int i = 2; i <= numberOfPalettes; i++) {
846                paletteName = ((ScalarDS) dataObject).getPaletteName(i - 1);
847                choicePalette.add(paletteName);
848            }
849        }
850        choicePalette.add("Gray");
851        choicePalette.add("ReverseGray");
852        choicePalette.add("GrayWave");
853        choicePalette.add("Rainbow");
854        choicePalette.add("Nature");
855        choicePalette.add("Wave");
856
857        choicePalette.select(0);
858
859        label = new Label(imageComposite, SWT.RIGHT);
860        label.setFont(curFont);
861        label.setText("Valid Range: ");
862
863        dataRangeField = new Text(imageComposite, SWT.SINGLE | SWT.BORDER);
864        dataRangeField.setFont(curFont);
865        dataRangeField.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
866
867        String minmaxStr = "min, max";
868
869        double[] minmax = ((ScalarDS) dataObject).getImageDataRange();
870        if (minmax != null) {
871            if (dataObject.getDatatype().isFloat())
872                minmaxStr = minmax[0] + "," + minmax[1];
873            else
874                minmaxStr = ((long) minmax[0]) + "," + ((long) minmax[1]);
875        }
876
877        dataRangeField.setText(minmaxStr);
878
879        label = new Label(imageComposite, SWT.RIGHT);
880        label.setFont(curFont);
881        label.setText("ImageView: ");
882
883        choiceImageView = new Combo(imageComposite, SWT.SINGLE | SWT.DROP_DOWN | SWT.READ_ONLY);
884        choiceImageView.setFont(curFont);
885        choiceImageView.setItems(HDFView.getListOfImageViews().toArray(new String[0]));
886        choiceImageView.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
887        choiceImageView.select(0);
888
889        label = new Label(imageComposite, SWT.RIGHT);
890        label.setFont(curFont);
891        label.setText("Invalid Values: ");
892
893        fillValueField = new Text(imageComposite, SWT.SINGLE | SWT.BORDER);
894        fillValueField.setFont(curFont);
895        fillValueField.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
896
897        String fillStr = "val1, val2, ...";
898
899        java.util.List<Number> fillValue = ((ScalarDS) dataObject).getFilteredImageValues();
900        int n = fillValue.size();
901        if (n > 0) {
902            fillStr = fillValue.get(0).toString();
903            for (int i = 1; i < n; i++) {
904                fillStr += ", " + fillValue.get(i);
905            }
906        }
907
908        fillValueField.setText(fillStr);
909
910        // Create Index Base region
911        org.eclipse.swt.widgets.Group indexBaseGroup = new org.eclipse.swt.widgets.Group(shell, SWT.NONE);
912        indexBaseGroup.setFont(curFont);
913        indexBaseGroup.setText("Index Base");
914        indexBaseGroup.setLayout(new GridLayout(2, true));
915        indexBaseGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
916
917        base0Button = new Button(indexBaseGroup, SWT.RADIO);
918        base0Button.setFont(curFont);
919        base0Button.setText("0-based");
920        base0Button.setLayoutData(new GridData(SWT.CENTER, SWT.FILL, true, false));
921
922        base1Button = new Button(indexBaseGroup, SWT.RADIO);
923        base1Button.setFont(curFont);
924        base1Button.setText("1-based");
925        base1Button.setLayoutData(new GridData(SWT.CENTER, SWT.FILL, true, false));
926
927        if(ViewProperties.isIndexBase1()) {
928            base0Button.setSelection(false);
929            base1Button.setSelection(true);
930        }
931        else {
932            base0Button.setSelection(true);
933            base1Button.setSelection(false);
934        }
935
936
937        // Create Bitmask region
938        org.eclipse.swt.widgets.Group bitmaskGroup = new org.eclipse.swt.widgets.Group(shell, SWT.NONE);
939        bitmaskGroup.setFont(curFont);
940        bitmaskGroup.setText("Bitmask");
941        bitmaskGroup.setLayout(new GridLayout(2, false));
942        bitmaskGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
943
944        extractBitButton = new Button(bitmaskGroup, SWT.CHECK);
945        extractBitButton.setFont(curFont);
946        extractBitButton.setText("Show &Value of Selected Bits");
947        extractBitButton.setLayoutData(new GridData(SWT.BEGINNING, SWT.FILL, false, false));
948        extractBitButton.setSelection(false);
949        extractBitButton.addSelectionListener(new SelectionAdapter() {
950            @Override
951            public void widgetSelected(SelectionEvent e) {
952                boolean selected = extractBitButton.getSelection();
953
954                if(selected) {
955                    if(applyBitmaskButton.getSelection()) {
956                        applyBitmaskButton.setSelection(false);
957                    }
958
959                    if(!bitmaskButtons[0].getEnabled()) {
960                        for(int i = 0; i < bitmaskButtons.length; i++) {
961                            bitmaskButtons[i].setEnabled(true);
962                        }
963                    }
964
965                    int n = 0;
966
967                    if(bitmaskButtons[0].getSelection()) n = 1;
968
969                    for(int i = 1; i < bitmaskButtons.length; i++) {
970                        if(bitmaskButtons[i].getSelection() && !bitmaskButtons[i - 1].getSelection()) {
971                            n++;
972                        }
973                    }
974
975                    if(n > 1) {
976                        extractBitButton.setSelection(false);
977                        applyBitmaskButton.setSelection(true);
978
979                        Tools.showError(shell, "Select",
980                                "Selecting non-adjacent bits is only allowed \nfor the \"Apply Bitmask\" option.");
981                        return;
982                    }
983                }
984                else {
985                    for(int i = 0; i < bitmaskButtons.length; i++) {
986                        bitmaskButtons[i].setEnabled(false);
987                    }
988                }
989            }
990        });
991
992        bitmaskHelp = new Button(bitmaskGroup, SWT.PUSH);
993        bitmaskHelp.setImage(ViewProperties.getHelpIcon());
994        bitmaskHelp.setToolTipText("Help on how to set bitmask");
995        bitmaskHelp.setLayoutData(new GridData(SWT.END, SWT.FILL, false, false));
996        bitmaskHelp.setEnabled(false);
997        bitmaskHelp.addSelectionListener(new SelectionAdapter() {
998            @Override
999            public void widgetSelected(SelectionEvent e) {
1000                String msg = ""
1001                        + "\"Apply Bitmask\" applies bitwise \"AND\" to the original data.\n"
1002                        + "For example, bits 2, 3, and 4 are selected for the bitmask\n"
1003                        + "         10010101 (data)\n"
1004                        + "AND 00011100 (mask)  \n"
1005                        + "  =     00010100 (result) ==> the decimal value is 20. \n"
1006                        + "\n"
1007                        + "\"Extract Bit(s)\" removes all the bits from the result above where\n"
1008                        + "their corresponding bits in the bitmask are 0. \nFor the same example above, "
1009                        + "the result is \n101 ==> the decimal value is 5.\n\n";
1010
1011                Tools.showInformation(shell, "Help", msg);
1012            }
1013        });
1014
1015        applyBitmaskButton = new Button(bitmaskGroup, SWT.CHECK);
1016        applyBitmaskButton.setFont(curFont);
1017        applyBitmaskButton.setText("&Apply Bitmask");
1018        applyBitmaskButton.setLayoutData(new GridData(SWT.BEGINNING, SWT.FILL, false, false));
1019        applyBitmaskButton.setSelection(false);
1020        applyBitmaskButton.addSelectionListener(new SelectionAdapter() {
1021            @Override
1022            public void widgetSelected(SelectionEvent e) {
1023                if(extractBitButton.getSelection()) {
1024                    extractBitButton.setSelection(false);
1025                }
1026                else if (!applyBitmaskButton.getSelection()) {
1027                    for(int i = 0; i < bitmaskButtons.length; i++) {
1028                        bitmaskButtons[i].setEnabled(false);
1029                    }
1030                }
1031                else {
1032                    if(!bitmaskButtons[0].getEnabled()) {
1033                        for(int i = 0; i < bitmaskButtons.length; i++) {
1034                            bitmaskButtons[i].setEnabled(true);
1035                        }
1036                    }
1037                }
1038            }
1039        });
1040
1041        new Label(bitmaskGroup, SWT.RIGHT).setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
1042
1043        Composite buttonComposite = new Composite(bitmaskGroup, SWT.NO_RADIO_GROUP);
1044        buttonComposite.setLayout(new GridLayout(16, true));
1045        buttonComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 2, 1));
1046
1047        int tsize;
1048
1049        if (dataObject.getDatatype().isArray()) {
1050            Datatype baseType = dataObject.getDatatype().getDatatypeBase();
1051
1052            while (baseType.isArray()) {
1053                baseType = baseType.getDatatypeBase();
1054            }
1055
1056            tsize = (int) baseType.getDatatypeSize();
1057        }
1058        else {
1059            tsize = (int) dataObject.getDatatype().getDatatypeSize();
1060        }
1061
1062        bitmaskButtons = (tsize >= 0 && !dataObject.getDatatype().isText()) ? new Button[8 * tsize] : new Button[0];
1063
1064        for (int i = 0; i < bitmaskButtons.length; i++) {
1065            bitmaskButtons[i] = new Button(buttonComposite, SWT.RADIO);
1066            bitmaskButtons[i].setFont(curFont);
1067            bitmaskButtons[i].setText(String.valueOf(bitmaskButtons.length - i - 1));
1068            bitmaskButtons[i].setEnabled(false);
1069            bitmaskButtons[i].addSelectionListener(
1070                new SelectionAdapter() {
1071                    @Override
1072                    public void widgetSelected(SelectionEvent e) {
1073                        if(extractBitButton.getSelection()) {
1074                            Button source = (Button) e.widget;
1075
1076                            // Don't allow non-adjacent selection of bits when extracting bits
1077                            int n = 0;
1078
1079                            if(bitmaskButtons[0].getSelection()) n = 1;
1080
1081                            for(int i = 1; i < bitmaskButtons.length; i++) {
1082                                if(bitmaskButtons[i].getSelection() && !bitmaskButtons[i - 1].getSelection()) {
1083                                    n++;
1084                                }
1085                            }
1086
1087                            if(n > 1) {
1088                                Tools.showError(shell, "Select",
1089                                        "Please select contiguous bits \nwhen the \"Show Value of Selected Bits\" option is checked.");
1090
1091                                source.setSelection(false);
1092                                return;
1093                            }
1094                        }
1095                    }
1096                }
1097            );
1098        }
1099
1100        if (dataObject.getDatatype().isChar() || (dataObject.getDatatype().isInteger() && tsize <= 8)) {
1101            extractBitButton.setEnabled(true);
1102            applyBitmaskButton.setEnabled(true);
1103            bitmaskHelp.setEnabled(true);
1104        }
1105
1106
1107        // Create Dimension/Subset selection region
1108        org.eclipse.swt.widgets.Group dimSubGroup = new org.eclipse.swt.widgets.Group(shell, SWT.NONE);
1109        dimSubGroup.setFont(curFont);
1110        dimSubGroup.setText("Dimension and Subset Selection");
1111        dimSubGroup.setLayout(new GridLayout(2, false));
1112        dimSubGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
1113
1114        int h = 1, w = 1;
1115        h = (int) dims[selectedIndex[0]];
1116        if (rank > 1) {
1117            w = (int) dims[selectedIndex[1]];
1118        }
1119
1120        if (rank > 1) {
1121            navigator = new PreviewNavigator(dimSubGroup, SWT.DOUBLE_BUFFERED | SWT.BORDER, w, h);
1122        }
1123        else {
1124            dimSubGroup.setLayout(new GridLayout(1, true));
1125        }
1126
1127        createDimSubSelectionComposite(dimSubGroup);
1128    }
1129
1130    private void createCompoundDSContents() {
1131        Composite content = new Composite(shell, SWT.NONE);
1132        content.setLayout(new GridLayout(2, false));
1133        content.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
1134
1135        org.eclipse.swt.widgets.Group membersGroup = new org.eclipse.swt.widgets.Group(content, SWT.NONE);
1136        membersGroup.setFont(curFont);
1137        membersGroup.setText("Select Members");
1138        membersGroup.setLayout(new GridLayout(1, true));
1139        membersGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, true));
1140
1141        final String[] names = ((CompoundDS) dataObject).getMemberNames();
1142        String[] columnNames = new String[names.length];
1143        for (int i = 0; i < names.length; i++) {
1144            columnNames[i] = new String(names[i]);
1145            columnNames[i] = columnNames[i].replaceAll(CompoundDS.SEPARATOR, "->");
1146        }
1147        fieldList = new List(membersGroup, SWT.MULTI | SWT.BORDER | SWT.V_SCROLL);
1148        fieldList.setFont(curFont);
1149        fieldList.setItems(columnNames);
1150        fieldList.selectAll();
1151
1152        GridData data = new GridData(SWT.FILL, SWT.FILL, false, true);
1153        data.heightHint = fieldList.getItemHeight() * 10;
1154        data.widthHint = fieldList.computeSize(SWT.DEFAULT, SWT.DEFAULT).x + 10;
1155        fieldList.setLayoutData(data);
1156
1157        org.eclipse.swt.widgets.Group dimSubGroup = new org.eclipse.swt.widgets.Group(content, SWT.NONE);
1158        dimSubGroup.setFont(curFont);
1159        dimSubGroup.setText("Dimension and Subset Selection");
1160        dimSubGroup.setLayout(new GridLayout());
1161        dimSubGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
1162
1163        createDimSubSelectionComposite(dimSubGroup);
1164
1165        Composite tableViewComposite = new Composite(dimSubGroup, SWT.BORDER);
1166        tableViewComposite.setLayout(new GridLayout(2, false));
1167        tableViewComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
1168
1169        Label label = new Label(tableViewComposite, SWT.RIGHT);
1170        label.setFont(curFont);
1171        label.setText("TableView: ");
1172
1173        choiceTableView = new Combo(tableViewComposite, SWT.SINGLE | SWT.DROP_DOWN | SWT.READ_ONLY);
1174        choiceTableView.setFont(curFont);
1175        choiceTableView.setItems(HDFView.getListOfTableViews().toArray(new String[0]));
1176        choiceTableView.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
1177        choiceTableView.select(0);
1178    }
1179
1180    private void createDimSubSelectionComposite(Composite parent) {
1181        String[] dimNames = ((Dataset) dataObject).getDimNames();
1182
1183        Composite selectionComposite = new Composite(parent, SWT.BORDER);
1184        selectionComposite.setLayout(new GridLayout(6, true));
1185        selectionComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
1186
1187        new Label(selectionComposite, SWT.RIGHT).setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
1188
1189        if (rank > 1) {
1190            transposeChoice = new Combo(selectionComposite, SWT.SINGLE | SWT.READ_ONLY);
1191            transposeChoice.setFont(curFont);
1192            transposeChoice.setLayoutData(new GridData(SWT.FILL, SWT.END, true, false));
1193
1194            transposeChoice.add("Transpose");
1195            transposeChoice.add("Reshape");
1196
1197            transposeChoice.select(0);
1198        }
1199        else {
1200            new Label(selectionComposite, SWT.RIGHT).setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
1201        }
1202
1203        Label label = new Label(selectionComposite, SWT.RIGHT);
1204        label.setFont(curFont);
1205        label.setText("Start: ");
1206        label.setLayoutData(new GridData(SWT.CENTER, SWT.END, true, true));
1207
1208        label = new Label(selectionComposite, SWT.RIGHT);
1209        label.setFont(curFont);
1210        label.setText("End: ");
1211        label.setLayoutData(new GridData(SWT.CENTER, SWT.END, true, true));
1212
1213        label = new Label(selectionComposite, SWT.RIGHT);
1214        label.setFont(curFont);
1215        label.setText("Stride: ");
1216        label.setLayoutData(new GridData(SWT.CENTER, SWT.END, true, true));
1217
1218        label = new Label(selectionComposite, SWT.RIGHT);
1219        label.setFont(curFont);
1220        label.setText("Max Size");
1221        label.setLayoutData(new GridData(SWT.CENTER, SWT.END, true, true));
1222
1223
1224        // Create Height selection row
1225        label = new Label(selectionComposite, SWT.RIGHT);
1226        label.setFont(curFont);
1227        label.setText("Height: ");
1228        label.setLayoutData(new GridData(SWT.END, SWT.CENTER, true, true));
1229
1230        choices[0] = new Combo(selectionComposite, SWT.SINGLE | SWT.READ_ONLY);
1231        choices[0].setFont(curFont);
1232        choices[0].setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
1233        choices[0].addSelectionListener(new SelectionAdapter() {
1234            @Override
1235            public void widgetSelected(SelectionEvent e) {
1236                Combo source = (Combo) e.widget;
1237
1238                processComboBoxEvent(source);
1239            }
1240        });
1241
1242        for (int j = 0; j < rank; j++) {
1243            if (dimNames == null) {
1244                choices[0].add("dim " + j);
1245            }
1246            else {
1247                choices[0].add(dimNames[j]);
1248            }
1249        }
1250
1251        choices[0].select(0);
1252
1253        startFields[0] = new Text(selectionComposite, SWT.SINGLE | SWT.BORDER);
1254        startFields[0].setFont(curFont);
1255        startFields[0].setText("0");
1256        startFields[0].setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
1257
1258        endFields[0] = new Text(selectionComposite, SWT.SINGLE | SWT.BORDER);
1259        endFields[0].setFont(curFont);
1260        endFields[0].setText("0");
1261        endFields[0].setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
1262
1263        strideFields[0] = new Text(selectionComposite, SWT.SINGLE | SWT.BORDER);
1264        strideFields[0].setFont(curFont);
1265        strideFields[0].setText("1");
1266        strideFields[0].setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
1267
1268        maxLabels[0] = new Label(selectionComposite, SWT.NONE);
1269        maxLabels[0].setFont(curFont);
1270        maxLabels[0].setText("1");
1271        maxLabels[0].setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
1272
1273
1274        // Create Width selection row
1275        label = new Label(selectionComposite, SWT.RIGHT);
1276        label.setFont(curFont);
1277        label.setText("Width: ");
1278        label.setLayoutData(new GridData(SWT.END, SWT.CENTER, true, true));
1279
1280        choices[1] = new Combo(selectionComposite, SWT.SINGLE | SWT.READ_ONLY);
1281        choices[1].setFont(curFont);
1282        choices[1].setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
1283        choices[1].addSelectionListener(new SelectionAdapter() {
1284            @Override
1285            public void widgetSelected(SelectionEvent e) {
1286                Combo source = (Combo) e.widget;
1287
1288                processComboBoxEvent(source);
1289            }
1290        });
1291
1292        for (int j = 0; j < rank; j++) {
1293            if (dimNames == null) {
1294                choices[1].add("dim " + j);
1295            }
1296            else {
1297                choices[1].add(dimNames[j]);
1298            }
1299        }
1300
1301        choices[1].select(0);
1302
1303        startFields[1] = new Text(selectionComposite, SWT.SINGLE | SWT.BORDER);
1304        startFields[1].setFont(curFont);
1305        startFields[1].setText("0");
1306        startFields[1].setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
1307
1308        endFields[1] = new Text(selectionComposite, SWT.SINGLE | SWT.BORDER);
1309        endFields[1].setFont(curFont);
1310        endFields[1].setText("0");
1311        endFields[1].setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
1312
1313        strideFields[1] = new Text(selectionComposite, SWT.SINGLE | SWT.BORDER);
1314        strideFields[1].setFont(curFont);
1315        strideFields[1].setText("1");
1316        strideFields[1].setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
1317
1318        maxLabels[1] = new Label(selectionComposite, SWT.NONE);
1319        maxLabels[1].setFont(curFont);
1320        maxLabels[1].setText("1");
1321        maxLabels[1].setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
1322
1323
1324        // Create Depth selection row
1325        label = new Label(selectionComposite, SWT.RIGHT);
1326        label.setFont(curFont);
1327        label.setText("Depth: ");
1328        label.setLayoutData(new GridData(SWT.END, SWT.CENTER, true, true));
1329
1330        choices[2] = new Combo(selectionComposite, SWT.SINGLE | SWT.READ_ONLY);
1331        choices[2].setFont(curFont);
1332        choices[2].setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
1333        choices[2].addSelectionListener(new SelectionAdapter() {
1334            @Override
1335            public void widgetSelected(SelectionEvent e) {
1336                Combo source = (Combo) e.widget;
1337
1338                processComboBoxEvent(source);
1339            }
1340        });
1341
1342        for (int j = 0; j < rank; j++) {
1343            if (dimNames == null) {
1344                choices[2].add("dim " + j);
1345            }
1346            else {
1347                choices[2].add(dimNames[j]);
1348            }
1349        }
1350
1351        choices[2].select(0);
1352
1353        startFields[2] = new Text(selectionComposite, SWT.SINGLE | SWT.BORDER);
1354        startFields[2].setFont(curFont);
1355        startFields[2].setText("0");
1356        startFields[2].setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
1357
1358        endFields[2] = new Text(selectionComposite, SWT.SINGLE | SWT.BORDER);
1359        endFields[2].setFont(curFont);
1360        endFields[2].setText("0");
1361        endFields[2].setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
1362
1363        strideFields[2] = new Text(selectionComposite, SWT.SINGLE | SWT.BORDER);
1364        strideFields[2].setFont(curFont);
1365        strideFields[2].setText("1");
1366        strideFields[2].setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
1367
1368        maxLabels[2] = new Label(selectionComposite, SWT.NONE);
1369        maxLabels[2].setFont(curFont);
1370        maxLabels[2].setText("1");
1371        maxLabels[2].setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
1372
1373
1374        // Create row for Dims and reset button
1375        new Label(selectionComposite, SWT.RIGHT).setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
1376
1377        Button dimsButton = new Button(selectionComposite, SWT.PUSH);
1378        dimsButton.setFont(curFont);
1379        dimsButton.setText("Dims...");
1380        dimsButton.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
1381        dimsButton.setEnabled((rank > 3));
1382        dimsButton.addSelectionListener(new SelectionAdapter() {
1383            @Override
1384            public void widgetSelected(SelectionEvent e) {
1385                if (rank < 4) {
1386                    return;
1387                }
1388
1389                int idx = 0;
1390                Vector<Object> choice4 = new Vector<>(rank);
1391                int[] choice4Index = new int[rank - 3];
1392                for (int i = 0; i < rank; i++) {
1393                    if ((i != currentIndex[0]) && (i != currentIndex[1])
1394                            && (i != currentIndex[2])) {
1395                        choice4.add(choices[0].getItem(i));
1396                        choice4Index[idx++] = i;
1397                    }
1398                }
1399
1400                String msg = "Select slice location for dimension(s):\n\""
1401                        + choice4.get(0) + " [0 .. " + (dims[choice4Index[0]] - 1)
1402                        + "]\"";
1403                String initValue = String.valueOf(start[choice4Index[0]]);
1404                int n = choice4.size();
1405                for (int i = 1; i < n; i++) {
1406                    msg += " x \"" + choice4.get(i) + " [0 .. "
1407                            + (dims[choice4Index[i]] - 1) + "]\"";
1408                    initValue += " x " + String.valueOf(start[choice4Index[i]]);
1409                }
1410
1411                String result = new InputDialog(shell, shell.getText(), msg, initValue).open();
1412                if ((result == null) || ((result = result.trim()) == null)
1413                        || (result.length() < 1)) {
1414                    return;
1415                }
1416
1417                StringTokenizer st = new StringTokenizer(result, "x");
1418                if (st.countTokens() < n) {
1419                    Tools.showError(shell, "Select", "Number of dimension(s) is less than " + n + "\n" + result);
1420                    return;
1421                }
1422
1423                long[] start4 = new long[n];
1424                for (int i = 0; i < n; i++) {
1425                    try {
1426                        start4[i] = Long.parseLong(st.nextToken().trim());
1427                    }
1428                    catch (Exception ex) {
1429                        Tools.showError(shell, "Select", ex.getMessage());
1430                        return;
1431                    }
1432
1433                    if ((start4[i] < 0) || (start4[i] >= dims[choice4Index[i]])) {
1434                        Tools.showError(shell, "Select",
1435                                "Slice location is out of range.\n" + start4[i] + " >= " + dims[choice4Index[i]]);
1436
1437                        return;
1438                    }
1439
1440                }
1441
1442                for (int i = 0; i < n; i++) {
1443                    start[choice4Index[i]] = start4[i];
1444                }
1445            }
1446        });
1447
1448        new Label(selectionComposite, SWT.RIGHT).setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
1449
1450        new Label(selectionComposite, SWT.RIGHT).setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
1451
1452        Button resetButton = new Button(selectionComposite, SWT.PUSH);
1453        resetButton.setFont(curFont);
1454        resetButton.setText("Reset");
1455        resetButton.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
1456        resetButton.addSelectionListener(new SelectionAdapter() {
1457            @Override
1458            public void widgetSelected(SelectionEvent e) {
1459                int n = startFields.length;
1460
1461                for (int i = 0; i < n; i++) {
1462                    startFields[i].setText("0");
1463                    strideFields[i].setText("1");
1464                    long l = Long.valueOf(maxLabels[i].getText()) - 1;
1465                    endFields[i].setText(String.valueOf(l));
1466                }
1467            }
1468        });
1469
1470        new Label(selectionComposite, SWT.RIGHT).setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
1471
1472
1473        for (int i = 0; i < 3; i++) {
1474            // Disable the selection components
1475            // init() will set them appropriately
1476            choices[i].setEnabled(false);
1477            startFields[i].setEnabled(false);
1478            endFields[i].setEnabled(false);
1479            strideFields[i].setEnabled(false);
1480            maxLabels[i].setEnabled(false);
1481        }
1482    }
1483
1484    private void processComboBoxEvent(Combo source) {
1485        int theSelectedChoice = -1;
1486
1487        int n = Math.min(3, rank);
1488        for (int i = 0; i < n; i++) {
1489            if (source.equals(choices[i])) {
1490                theSelectedChoice = i;
1491            }
1492        }
1493
1494        if (theSelectedChoice < 0) {
1495            return; // the selected ComboBox is not a dimension choice
1496        }
1497
1498        int theIndex = source.getSelectionIndex();
1499        if (theIndex == currentIndex[theSelectedChoice]) {
1500            return; // select the same item, no change
1501        }
1502
1503        start[currentIndex[theSelectedChoice]] = 0;
1504
1505        // reset the selected dimension choice
1506        startFields[theSelectedChoice].setText("0");
1507        endFields[theSelectedChoice].setText(String
1508                .valueOf(dims[theIndex] - 1));
1509        strideFields[theSelectedChoice].setText("1");
1510        maxLabels[theSelectedChoice]
1511                .setText(String.valueOf(dims[theIndex]));
1512
1513        // if the selected choice selects the dimension that is selected by
1514        // other dimension choice, exchange the dimensions
1515        for (int i = 0; i < n; i++) {
1516            if (i == theSelectedChoice) {
1517                continue; // don't exchange itself
1518            }
1519            else if (theIndex == choices[i].getSelectionIndex()) {
1520                choices[i].select(currentIndex[theSelectedChoice]);
1521                startFields[i].setText("0");
1522                endFields[i]
1523                        .setText(String
1524                                .valueOf(dims[currentIndex[theSelectedChoice]] - 1));
1525                strideFields[i].setText("1");
1526                maxLabels[i].setText(String
1527                        .valueOf(dims[currentIndex[theSelectedChoice]]));
1528            }
1529        }
1530
1531        for (int i = 0; i < n; i++) {
1532            currentIndex[i] = choices[i].getSelectionIndex();
1533        }
1534
1535        // update the navigator
1536        if (rank > 1) {
1537            int hIdx = choices[0].getSelectionIndex();
1538            int wIdx = choices[1].getSelectionIndex();
1539            transposeChoice.select(0);
1540
1541            // Use transpose option only if the dims are not in original
1542            // order
1543            if (hIdx < wIdx)
1544                transposeChoice.setEnabled(false);
1545            else
1546                transposeChoice.setEnabled(true);
1547
1548            long dims[] = dataObject.getDims();
1549            int w = (int) dims[wIdx];
1550            int h = (int) dims[hIdx];
1551
1552            if (navigator != null) {
1553                navigator.setDimensionSize(w, h);
1554                navigator.redraw();
1555            }
1556        }
1557
1558        if (rank > 2) {
1559            endFields[2].setText(startFields[2].getText());
1560        }
1561    }
1562
1563    /** PreviewNavigator draws a selection rectangle for selecting a subset
1564     *  of the data to be displayed. */
1565    private class PreviewNavigator extends Canvas {
1566        private final int         NAVIGATOR_SIZE   = 150;
1567        private int               dimX, dimY, x, y;
1568        private double            r;
1569        private Point             startPosition; // mouse clicked position
1570        private Rectangle         selectedArea;
1571        private Image             previewImage     = null;
1572        private String            selStr;
1573
1574        private PreviewNavigator(Composite parent, int style, int w, int h) {
1575            super(parent, style);
1576
1577            GridData data = new GridData(SWT.FILL, SWT.FILL, false, true);
1578            data.widthHint = NAVIGATOR_SIZE;
1579            data.heightHint = NAVIGATOR_SIZE;
1580            this.setLayoutData(data);
1581
1582            dimX = w;
1583            dimY = h;
1584            if (dimX > dimY) {
1585                x = NAVIGATOR_SIZE;
1586                r = dimX / (double) x;
1587                y = (int) (dimY / r);
1588            }
1589            else {
1590                y = NAVIGATOR_SIZE;
1591                r = dimY / (double) y;
1592                x = (int) (dimX / r);
1593            }
1594
1595            selectedArea = new Rectangle();
1596
1597            selStr = "";
1598
1599            try {
1600                previewImage = createPreviewImage();
1601
1602                String origStr = ViewProperties.getImageOrigin();
1603                if (ViewProperties.ORIGIN_LL.equalsIgnoreCase(origStr))
1604                    flip(DefaultImageView.FLIP_VERTICAL);
1605                else if (ViewProperties.ORIGIN_UR.equalsIgnoreCase(origStr))
1606                    flip(DefaultImageView.FLIP_HORIZONTAL);
1607                else if (ViewProperties.ORIGIN_LR.equalsIgnoreCase(origStr)) {
1608                    rotate(DefaultImageView.ROTATE_CW_90);
1609                    rotate(DefaultImageView.ROTATE_CW_90);
1610                }
1611            }
1612            catch (Exception ex) {
1613                ex.printStackTrace();
1614            }
1615
1616            this.addMouseListener(new MouseListener() {
1617                @Override
1618                public void mouseDoubleClick(MouseEvent e) {
1619
1620                }
1621
1622                @Override
1623                public void mouseDown(MouseEvent e) {
1624                    startPosition = new Point(e.x, e.y);
1625                    selectedArea.setBounds(startPosition.x, startPosition.y, 0, 0);
1626                }
1627
1628                @Override
1629                public void mouseUp(MouseEvent e) {
1630                    if(startPosition.x == e.x && startPosition.y == e.y) {
1631                        selectedArea.setBounds(startPosition.x, startPosition.y, 0, 0);
1632                        redraw();
1633                    }
1634                }
1635            });
1636
1637            this.addMouseMoveListener(new MouseMoveListener() {
1638                @Override
1639                public void mouseMove(MouseEvent e) {
1640                    if(e.stateMask == SWT.BUTTON1 || e.stateMask == SWT.BUTTON3) {
1641                        Point p0 = startPosition;
1642                        Point p1 = new Point(e.x, e.y);
1643
1644                        int x0 = Math.max(0, Math.min(p0.x, p1.x));
1645                        int y0 = Math.max(0, Math.min(p0.y, p1.y));
1646                        int x1 = Math.min(x, Math.max(p0.x, p1.x));
1647                        int y1 = Math.min(y, Math.max(p0.y, p1.y));
1648
1649                        int w = x1 - x0;
1650                        int h = y1 - y0;
1651
1652                        selectedArea.setBounds(x0, y0, w, h);
1653
1654                        try {
1655                            updateSelection(x0, y0, w, h);
1656                        }
1657                        catch (Exception ex) {
1658                        }
1659
1660                        redraw();
1661                    }
1662                }
1663            });
1664
1665            this.addPaintListener(new PaintListener() {
1666                @Override
1667                public void paintControl(PaintEvent e) {
1668                    GC gc = e.gc;
1669
1670                    gc.setForeground(Display.getCurrent().getSystemColor(SWT.COLOR_BLUE));
1671
1672                    if (previewImage != null) {
1673                        gc.drawImage(convertBufferedImageToSWTImage((BufferedImage) previewImage), 0, 0);
1674                    }
1675                    else {
1676                        gc.fillRectangle(0, 0, x, y);
1677                    }
1678
1679                    int w = selectedArea.width;
1680                    int h = selectedArea.height;
1681                    if ((w > 0) && (h > 0)) {
1682                        gc.setForeground(Display.getCurrent().getSystemColor(SWT.COLOR_RED));
1683                        gc.drawRectangle(selectedArea.x, selectedArea.y, w, h);
1684                    }
1685
1686                    org.eclipse.swt.graphics.Rectangle bounds = ((Canvas) e.widget).getBounds();
1687                    Point textSize = gc.stringExtent(selStr);
1688                    gc.setForeground(Display.getCurrent().getSystemColor(SWT.COLOR_BLACK));
1689                    gc.drawString(selStr, (bounds.width / 2) - (textSize.x / 2), bounds.height - textSize.y - 4);
1690                }
1691            });
1692        }
1693
1694        private Image createPreviewImage ( ) throws Exception {
1695            if ((rank <= 1) || !(dataObject instanceof ScalarDS)) {
1696                return null;
1697            }
1698
1699            Image preImage = null;
1700            ScalarDS sd = (ScalarDS) dataObject;
1701
1702            if (sd.getDatatype().isText()) {
1703                return null;
1704            }
1705
1706            // backup the selection
1707            long[] strideBackup = new long[rank];
1708            long[] selectedBackup = new long[rank];
1709            long[] startBackup = new long[rank];
1710            int[] selectedIndexBackup = new int[3];
1711            System.arraycopy(stride, 0, strideBackup, 0, rank);
1712            System.arraycopy(selected, 0, selectedBackup, 0, rank);
1713            System.arraycopy(start, 0, startBackup, 0, rank);
1714            System.arraycopy(selectedIndex, 0, selectedIndexBackup, 0, 3);
1715
1716            // set the selection for preview
1717            for (int i = 0; i < rank; i++) {
1718                start[i] = 0;
1719                stride[i] = 1;
1720                selected[i] = 1;
1721            }
1722
1723            if (choices != null) {
1724                try {
1725                    selectedIndex[0] = choices[0].getSelectionIndex();
1726                    selectedIndex[1] = choices[1].getSelectionIndex();
1727                } catch (Exception ex) {
1728                }
1729            }
1730            long steps = (long) Math.ceil(r);
1731            selected[selectedIndex[0]] = (dims[selectedIndex[0]] / steps);
1732            selected[selectedIndex[1]] = (dims[selectedIndex[1]] / steps);
1733            stride[selectedIndex[0]] = stride[selectedIndex[1]] = steps;
1734
1735            if (selected[selectedIndex[0]] == 0) {
1736                selected[selectedIndex[0]] = 1;
1737            }
1738            if (selected[selectedIndex[1]] == 0) {
1739                selected[selectedIndex[1]] = 1;
1740            }
1741
1742            if (isTrueColorImage && (start.length > 2)) {
1743                start[selectedIndex[2]] = 0;
1744                selected[selectedIndex[2]] = 3;
1745                stride[selectedIndex[2]] = 1;
1746            }
1747
1748            // update the ratio of preview image size to the real dataset
1749            y = (int) selected[selectedIndex[0]];
1750            x = (int) selected[selectedIndex[1]];
1751            r = Math.min((double) dims[selectedIndex[0]]
1752                    / (double) selected[selectedIndex[0]],
1753                    (double) dims[selectedIndex[1]]
1754                            / (double) selected[selectedIndex[1]]);
1755
1756            try {
1757                Object data = sd.read();
1758                int h = (int)sd.getHeight();
1759                int w = (int)sd.getWidth();
1760
1761                byte[] bData = Tools.getBytes(data, sd.getImageDataRange(), w, h, false, sd.getFilteredImageValues(), null);
1762
1763                if (isTrueColorImage) {
1764                    boolean isPlaneInterlace = (sd.getInterlace() == ScalarDS.INTERLACE_PLANE);
1765                    preImage = Tools.createTrueColorImage(bData,
1766                            isPlaneInterlace, w, h);
1767                }
1768                else {
1769                    byte[][] imagePalette = sd.getPalette();
1770                    if (imagePalette == null) {
1771                        imagePalette = Tools.createGrayPalette();
1772                    }
1773
1774                    if ((isH5 || (rank > 2))
1775                            && (selectedIndex[0] > selectedIndex[1])) {
1776                        // transpose data
1777                        int n = bData.length;
1778                        byte[] bData2 = new byte[n];
1779                        for (int i = 0; i < h; i++) {
1780                            for (int j = 0; j < w; j++) {
1781                                bData[i * w + j] = bData2[j * h + i];
1782                            }
1783                        }
1784                    }
1785                    if (!isH5 && !sd.isDefaultImageOrder() && (selectedIndex[1] > selectedIndex[0])) {
1786                        // transpose data for hdf4 images where selectedIndex[1]
1787                        // > selectedIndex[0]
1788                        int n = bData.length;
1789                        byte[] bData2 = new byte[n];
1790                        for (int i = 0; i < h; i++) {
1791                            for (int j = 0; j < w; j++) {
1792                                bData[i * w + j] = bData2[j * h + i];
1793                            }
1794                        }
1795                    }
1796                    preImage = Tools.createIndexedImage(null, bData, imagePalette, w, h);
1797                }
1798            }
1799            finally {
1800                // set back the original selection
1801                System.arraycopy(strideBackup, 0, stride, 0, rank);
1802                System.arraycopy(selectedBackup, 0, selected, 0, rank);
1803                System.arraycopy(startBackup, 0, start, 0, rank);
1804                System.arraycopy(selectedIndexBackup, 0, selectedIndex, 0, 3);
1805            }
1806
1807            return preImage;
1808        }
1809
1810        private void updateSelection (int x0, int y0, int w, int h) {
1811            int i0 = 0, i1 = 0;
1812
1813            i0 = (int) (y0 * r);
1814            if (i0 > dims[currentIndex[0]]) {
1815                i0 = (int) dims[currentIndex[0]];
1816            }
1817            startFields[0].setText(String.valueOf(i0));
1818
1819            i1 = (int) ((y0 + h) * r);
1820
1821            if (i1 < i0) {
1822                i1 = i0;
1823            }
1824            endFields[0].setText(String.valueOf(i1));
1825
1826            selStr = String.valueOf((int) (h * r));
1827
1828            if (rank > 1) {
1829                i0 = (int) (x0 * r);
1830                if (i0 > dims[currentIndex[1]]) {
1831                    i0 = (int) dims[currentIndex[1]];
1832                }
1833                startFields[1].setText(String.valueOf(i0));
1834
1835                i1 = (int) ((x0 + w) * r);
1836                if (i1 < i0) {
1837                    i1 = i0;
1838                }
1839                endFields[1].setText(String.valueOf(i1));
1840
1841                selStr += " x " + ((int) (w * r));
1842            }
1843        }
1844
1845        private void setDimensionSize (int w, int h) {
1846            dimX = w;
1847            dimY = h;
1848            if (dimX > dimY) {
1849                x = NAVIGATOR_SIZE;
1850                r = dimX / (double) x;
1851                y = (int) (dimY / r);
1852            }
1853            else {
1854                y = NAVIGATOR_SIZE;
1855                r = dimY / (double) y;
1856                x = (int) (dimX / r);
1857            }
1858
1859            selectedArea.setSize(0, 0);
1860
1861            try {
1862                previewImage = createPreviewImage();
1863            }
1864            catch (Exception ex) {
1865            }
1866
1867            this.redraw();
1868        }
1869
1870        private boolean applyImageFilter(ImageFilter filter) {
1871            boolean status = true;
1872            ImageProducer imageProducer = previewImage.getSource();
1873
1874            try {
1875                previewImage = Tools.toBufferedImage(Toolkit.getDefaultToolkit().createImage(new FilteredImageSource(imageProducer, filter)));
1876            }
1877            catch (Exception err) {
1878                shell.getDisplay().beep();
1879                Tools.showError(shell, "Apply Image Filter", err.getMessage());
1880                status = false;
1881            }
1882
1883            return status;
1884        }
1885
1886        private void flip(int direction) {
1887            applyImageFilter(new FlipFilter(direction));
1888        }
1889
1890        private void rotate(int direction) {
1891            if (!(direction == DefaultImageView.ROTATE_CW_90 || direction == DefaultImageView.ROTATE_CCW_90)) return;
1892
1893            applyImageFilter(new Rotate90Filter(direction));
1894        }
1895
1896        /**
1897         * Converts a given BufferedImage to ImageData for a SWT-readable Image
1898         *
1899         * @param image The BufferedImage to be converted
1900         *
1901         * @return the Image
1902         */
1903        private org.eclipse.swt.graphics.Image convertBufferedImageToSWTImage(BufferedImage image) {
1904            Display display = this.getDisplay();
1905
1906            if (image.getColorModel() instanceof DirectColorModel) {
1907                DirectColorModel colorModel = (DirectColorModel) image
1908                        .getColorModel();
1909                PaletteData palette = new PaletteData(colorModel.getRedMask(),
1910                        colorModel.getGreenMask(), colorModel.getBlueMask());
1911                ImageData data = new ImageData(image.getWidth(),
1912                        image.getHeight(), colorModel.getPixelSize(),
1913                        palette);
1914
1915                for (int y = 0; y < data.height; y++) {
1916                    for (int x = 0; x < data.width; x++) {
1917                        int rgb = image.getRGB(x, y);
1918                        int pixel = palette.getPixel(new RGB((rgb >> 16) & 0xFF, (rgb >> 8) & 0xFF, rgb & 0xFF));
1919                        data.setPixel(x, y, pixel);
1920                        if (colorModel.hasAlpha()) {
1921                            data.setAlpha(x, y, (rgb >> 24) & 0xFF);
1922                        }
1923                    }
1924                }
1925
1926                return new org.eclipse.swt.graphics.Image(display, data);
1927            }
1928            else if (image.getColorModel() instanceof IndexColorModel) {
1929                IndexColorModel colorModel = (IndexColorModel) image
1930                        .getColorModel();
1931                int size = colorModel.getMapSize();
1932                byte[] reds = new byte[size];
1933                byte[] greens = new byte[size];
1934                byte[] blues = new byte[size];
1935                colorModel.getReds(reds);
1936                colorModel.getGreens(greens);
1937                colorModel.getBlues(blues);
1938                RGB[] rgbs = new RGB[size];
1939                for (int i = 0; i < rgbs.length; i++) {
1940                    rgbs[i] = new RGB(reds[i] & 0xFF, greens[i] & 0xFF,
1941                            blues[i] & 0xFF);
1942                }
1943                PaletteData palette = new PaletteData(rgbs);
1944                ImageData data = new ImageData(image.getWidth(),
1945                        image.getHeight(), colorModel.getPixelSize(),
1946                        palette);
1947                data.transparentPixel = colorModel.getTransparentPixel();
1948                WritableRaster raster = image.getRaster();
1949                int[] pixelArray = new int[1];
1950                for (int y = 0; y < data.height; y++) {
1951                    for (int x = 0; x < data.width; x++) {
1952                        raster.getPixel(x, y, pixelArray);
1953                        data.setPixel(x, y, pixelArray[0]);
1954                    }
1955                }
1956
1957                return new org.eclipse.swt.graphics.Image(display, data);
1958            }
1959            else if (image.getColorModel() instanceof ComponentColorModel) {
1960                ComponentColorModel colorModel = (ComponentColorModel) image.getColorModel();
1961                //ASSUMES: 3 BYTE BGR IMAGE TYPE
1962                PaletteData palette = new PaletteData(0x0000FF, 0x00FF00,0xFF0000);
1963                ImageData data = new ImageData(image.getWidth(), image.getHeight(),
1964                        colorModel.getPixelSize(), palette);
1965                //This is valid because we are using a 3-byte Data model with no transparent pixels
1966                data.transparentPixel = -1;
1967                WritableRaster raster = image.getRaster();
1968                int[] pixelArray = new int[3];
1969                for (int y = 0; y < data.height; y++) {
1970                    for (int x = 0; x < data.width; x++) {
1971                        raster.getPixel(x, y, pixelArray);
1972                        int pixel = palette.getPixel(new RGB(pixelArray[0], pixelArray[1], pixelArray[2]));
1973                        data.setPixel(x, y, pixel);
1974                    }
1975                }
1976                return new org.eclipse.swt.graphics.Image(display, data);
1977            }
1978
1979            return null;
1980        }
1981    }
1982}