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