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