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