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