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 http://hdfgroup.org/products/hdf-java/doc/Copyright.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; 016 017import java.awt.BorderLayout; 018import java.awt.Color; 019import java.awt.Dimension; 020import java.awt.Graphics; 021import java.awt.GridLayout; 022import java.awt.Image; 023import java.awt.Insets; 024import java.awt.Point; 025import java.awt.Rectangle; 026import java.awt.Toolkit; 027import java.awt.event.ActionEvent; 028import java.awt.event.ActionListener; 029import java.awt.event.ItemEvent; 030import java.awt.event.ItemListener; 031import java.awt.event.KeyEvent; 032import java.awt.event.MouseEvent; 033import java.awt.event.MouseListener; 034import java.awt.event.MouseMotionListener; 035import java.util.BitSet; 036import java.util.List; 037import java.util.StringTokenizer; 038import java.util.Vector; 039 040import javax.swing.BorderFactory; 041import javax.swing.ButtonGroup; 042import javax.swing.JButton; 043import javax.swing.JCheckBox; 044import javax.swing.JComboBox; 045import javax.swing.JComponent; 046import javax.swing.JDialog; 047import javax.swing.JFrame; 048import javax.swing.JLabel; 049import javax.swing.JList; 050import javax.swing.JOptionPane; 051import javax.swing.JPanel; 052import javax.swing.JRadioButton; 053import javax.swing.JScrollPane; 054import javax.swing.JTextField; 055import javax.swing.JToggleButton; 056import javax.swing.SwingConstants; 057import javax.swing.WindowConstants; 058import javax.swing.border.EtchedBorder; 059import javax.swing.border.LineBorder; 060import javax.swing.border.TitledBorder; 061 062import hdf.object.CompoundDS; 063import hdf.object.Dataset; 064import hdf.object.Datatype; 065import hdf.object.FileFormat; 066import hdf.object.ScalarDS; 067 068/** 069 * DataOptionDialog is an dialog window used to select display options. Display options include 070 * selection of subset, display type (image, text, or spreadsheet). 071 * 072 * @author Peter X. Cao 073 * @version 2.4 9/6/2007 074 */ 075public class DataOptionDialog extends JDialog implements ActionListener, ItemListener 076{ 077 /** 078 * 079 */ 080 private static final long serialVersionUID = -1078411885690696784L; 081 082 /** 083 * The main HDFView. 084 */ 085 private final ViewManager viewer; 086 087 /** the selected dataset/image */ 088 private Dataset dataset; 089 090 /** the rank of the dataset/image */ 091 private int rank; 092 093 /** the starting point of selected subset */ 094 private long start[]; 095 096 /** the sizes of all dimensions */ 097 private long dims[]; 098 099 /** the selected sizes of all dimensions */ 100 private long selected[]; 101 102 /** the stride */ 103 private long stride[]; 104 105 /** the indices of the selected dimensions. */ 106 private int selectedIndex[]; 107 108 private int currentIndex[]; 109 110 private JRadioButton spreadsheetButton, imageButton, base1Button, base0Button; 111 112 private JRadioButton[] bitmaskButtons; 113 private JCheckBox applyBitmaskButton, extractBitButton; 114 115 private JCheckBox charCheckbox; 116 117 private BitSet bitmask; 118 119 private JButton bitmaskHelp; 120 121 @SuppressWarnings("rawtypes") 122 private JComboBox choiceTextView; 123 @SuppressWarnings("rawtypes") 124 private JComboBox choiceTableView; 125 @SuppressWarnings("rawtypes") 126 private JComboBox choiceImageView; 127 @SuppressWarnings("rawtypes") 128 private JComboBox choicePalette; 129 @SuppressWarnings("rawtypes") 130 private JComboBox choices[]; 131 @SuppressWarnings("rawtypes") 132 private JComboBox transposeChoice; 133 134 private boolean isSelectionCancelled; 135 136 private boolean isTrueColorImage; 137 138 private boolean isText; 139 140 private boolean isH5; 141 142 private JLabel maxLabels[], selLabel; 143 144 private JTextField startFields[], endFields[], strideFields[], dataRangeField, fillValueField; 145 146 @SuppressWarnings("rawtypes") 147 private JList fieldList; 148 149 private final Toolkit toolkit; 150 151 private final PreviewNavigator navigator; 152 153 private int numberOfPalettes; 154 155 /** 156 * JComboBox.setSelectedItem() or setSelectedIndex() always fires action event. If you call 157 * setSelectedItem() or setSelectedIndex() at itemStateChanged() or actionPerformed(), the 158 * setSelectedItem() or setSelectedIndex() will make loop calls of itemStateChanged() or 159 * actionPerformed(). This is not what we want. We want the setSelectedItem() or 160 * setSelectedIndex() behavior like java.awt.Choice. This flag is used to serve this purpose. 161 */ 162 private boolean performJComboBoxEvent = false; 163 164 /** 165 * Constructs a DataOptionDialog with the given HDFView. 166 * 167 * @param theview The main HDFView 168 * 169 * @param theDataset The dataset to set display options for 170 */ 171 @SuppressWarnings({ "rawtypes", "unchecked" }) 172 public DataOptionDialog(ViewManager theview, Dataset theDataset) { 173 super((JFrame) theview, true); 174 setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); 175 176 viewer = theview; 177 dataset = theDataset; 178 isSelectionCancelled = true; 179 isTrueColorImage = false; 180 isText = false; 181 bitmask = null; 182 numberOfPalettes = 1; 183 toolkit = Toolkit.getDefaultToolkit(); 184 185 if (dataset == null) { 186 dispose(); 187 } 188 else { 189 setTitle("Dataset Selection - " + dataset.getPath() 190 + dataset.getName()); 191 } 192 193 isH5 = dataset.getFileFormat().isThisType( 194 FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF5)); 195 196 rank = dataset.getRank(); 197 if (rank <= 0) { 198 dataset.init(); 199 } 200 if (isH5 && (dataset instanceof ScalarDS)) { 201 byte[] palRefs = ((ScalarDS) dataset).getPaletteRefs(); 202 if ((palRefs != null) && (palRefs.length > 8)) { 203 numberOfPalettes = palRefs.length / 8; 204 } 205 } 206 rank = dataset.getRank(); 207 dims = dataset.getDims(); 208 selected = dataset.getSelectedDims(); 209 start = dataset.getStartDims(); 210 selectedIndex = dataset.getSelectedIndex(); 211 stride = dataset.getStride(); 212 fieldList = null; 213 214 int h = 1, w = 1; 215 h = (int) dims[selectedIndex[0]]; 216 if (rank > 1) { 217 w = (int) dims[selectedIndex[1]]; 218 } 219 220 transposeChoice = new JComboBox(); 221 transposeChoice.addItem("Reshape"); 222 transposeChoice.addItem("Transpose"); 223 224 selLabel = new JLabel("", SwingConstants.CENTER); 225 navigator = new PreviewNavigator(w, h); 226 227 currentIndex = new int[Math.min(3, rank)]; 228 229 choicePalette = new JComboBox(); 230 choicePalette.setName("modulepalette"); 231 choiceTextView = new JComboBox((Vector<?>) HDFView.getListOfTextView()); 232 choiceTextView.setName("moduletext"); 233 choiceImageView = new JComboBox((Vector<?>) HDFView.getListOfImageView()); 234 choiceImageView.setName("moduleimage"); 235 choiceTableView = new JComboBox((Vector<?>) HDFView.getListOfTableView()); 236 choiceTableView.setName("moduletable"); 237 238 choicePalette.addItem("Select palette"); 239 if (dataset instanceof ScalarDS) { 240 String paletteName = ((ScalarDS) dataset).getPaletteName(0); 241 if (paletteName == null) { 242 paletteName = "Default"; 243 } 244 choicePalette.addItem(paletteName); 245 for (int i = 2; i <= numberOfPalettes; i++) { 246 paletteName = ((ScalarDS) dataset).getPaletteName(i - 1); 247 choicePalette.addItem(paletteName); 248 } 249 } 250 choicePalette.addItem("Gray"); 251 choicePalette.addItem("ReverseGray"); 252 choicePalette.addItem("GrayWave"); 253 choicePalette.addItem("Rainbow"); 254 choicePalette.addItem("Nature"); 255 choicePalette.addItem("Wave"); 256 257 spreadsheetButton = new JRadioButton("Spreadsheet ", true); 258 spreadsheetButton.setMnemonic(KeyEvent.VK_S); 259 spreadsheetButton.setName("spreadsheetbutton"); 260 imageButton = new JRadioButton("Image "); 261 imageButton.setMnemonic(KeyEvent.VK_I); 262 imageButton.setName("imagebutton"); 263 264 charCheckbox = new JCheckBox("Show As Char", false); 265 charCheckbox.setMnemonic(KeyEvent.VK_C); 266 charCheckbox.setEnabled(false); 267 charCheckbox.addItemListener(this); 268 269 extractBitButton = new JCheckBox("Show Value of Selected Bits", false); 270 extractBitButton.setMnemonic(KeyEvent.VK_V); 271 extractBitButton.setEnabled(false); 272 extractBitButton.addItemListener(this); 273 274 applyBitmaskButton = new JCheckBox("Apply Bitmask", false); 275 applyBitmaskButton.setMnemonic(KeyEvent.VK_A); 276 applyBitmaskButton.setEnabled(false); 277 applyBitmaskButton.addItemListener(this); 278 applyBitmaskButton.setName("applybitmask"); 279 280 bitmaskHelp = new JButton(ViewProperties.getHelpIcon()); 281 bitmaskHelp.setEnabled(false); 282 bitmaskHelp.setToolTipText("Help on how to set bitmask"); 283 bitmaskHelp.setMargin(new Insets(0, 0, 0, 0)); 284 bitmaskHelp.addActionListener(this); 285 bitmaskHelp.setActionCommand("Help on how to set bitmask"); 286 287 // layout the components 288 JPanel contentPane = (JPanel) getContentPane(); 289 contentPane.setLayout(new BorderLayout(5, 5)); 290 contentPane.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); 291 int w1 = 700 + (ViewProperties.getFontSize() - 12) * 15; 292 int h1 = 350 + (ViewProperties.getFontSize() - 12) * 10; 293 contentPane.setPreferredSize(new Dimension(w1, h1)); 294 295 JPanel centerP = new JPanel(); 296 centerP.setLayout(new BorderLayout()); 297 TitledBorder tborder = new TitledBorder("Dimension and Subset Selection"); 298 tborder.setTitleColor(Color.gray); 299 centerP.setBorder(tborder); 300 301 JPanel navigatorP = new JPanel(); 302 navigatorP.setLayout(new BorderLayout()); 303 navigatorP.add(navigator, BorderLayout.CENTER); 304 navigatorP.add(selLabel, BorderLayout.SOUTH); 305 navigatorP.setBorder(new EtchedBorder(EtchedBorder.LOWERED)); 306 navigatorP.setName("navigator"); 307 performJComboBoxEvent = true; 308 309 // create and initialize these buttons here so the isIndexBase1 method 310 // functions properly 311 base0Button = new JRadioButton("0-based "); 312 base1Button = new JRadioButton("1-based "); 313 if (ViewProperties.isIndexBase1()) 314 base1Button.setSelected(true); 315 else 316 base0Button.setSelected(true); 317 318 if (dataset instanceof CompoundDS) { 319 // setup GUI components for the field selection 320 CompoundDS d = (CompoundDS) dataset; 321 String[] names = d.getMemberNames(); 322 fieldList = new JList(names); 323 fieldList.addSelectionInterval(0, names.length - 1); 324 JPanel fieldP = new JPanel(); 325 fieldP.setLayout(new BorderLayout()); 326 w1 = 150 + (ViewProperties.getFontSize() - 12) * 10; 327 h1 = 250 + (ViewProperties.getFontSize() - 12) * 15; 328 fieldP.setPreferredSize(new Dimension(w1, h1)); 329 JScrollPane scrollP = new JScrollPane(fieldList); 330 fieldP.add(scrollP); 331 tborder = new TitledBorder("Select Members"); 332 tborder.setTitleColor(Color.gray); 333 fieldP.setBorder(tborder); 334 contentPane.add(fieldP, BorderLayout.WEST); 335 336 JPanel tviewP = new JPanel(); 337 tviewP.setLayout(new BorderLayout()); 338 tviewP.add(new JLabel(" TableView: "), BorderLayout.WEST); 339 tviewP.add(choiceTableView, BorderLayout.CENTER); 340 tviewP.setBorder(new LineBorder(Color.LIGHT_GRAY)); 341 342 centerP.add(tviewP, BorderLayout.SOUTH); 343 } 344 else if (dataset instanceof ScalarDS) { 345 ScalarDS sd = (ScalarDS) dataset; 346 isText = sd.isText(); 347 348 if (isText) { 349 w1 = 700 + (ViewProperties.getFontSize() - 12) * 15; 350 h1 = 280 + (ViewProperties.getFontSize() - 12) * 10; 351 contentPane.setPreferredSize(new Dimension(w1, h1)); 352 // add textview selection 353 JPanel txtviewP = new JPanel(); 354 txtviewP.setLayout(new BorderLayout()); 355 txtviewP.add(new JLabel(" TextView: "), 356 BorderLayout.WEST); 357 txtviewP.add(choiceTextView, BorderLayout.CENTER); 358 txtviewP.setBorder(new LineBorder(Color.LIGHT_GRAY)); 359 360 centerP.add(txtviewP, BorderLayout.SOUTH); 361 } 362 else { 363 w1 = 800 + (ViewProperties.getFontSize() - 12) * 15; 364 h1 = 550 + (ViewProperties.getFontSize() - 12) * 10; 365 contentPane.setPreferredSize(new Dimension(w1, h1)); 366 if (rank > 1) { 367 centerP.add(navigatorP, BorderLayout.WEST); 368 } 369 370 // setup GUI components for the display options: table or image 371 imageButton.addItemListener(this); 372 spreadsheetButton.addItemListener(this); 373 ButtonGroup rgroup = new ButtonGroup(); 374 rgroup.add(spreadsheetButton); 375 rgroup.add(imageButton); 376 JPanel viewP = new JPanel(); 377 viewP.setLayout(new GridLayout(2, 1, 5, 5)); 378 tborder = new TitledBorder("Display As"); 379 tborder.setTitleColor(Color.gray); 380 viewP.setBorder(tborder); 381 382 JPanel sheetP = new JPanel(); 383 sheetP.setLayout(new GridLayout(1, 2, 25, 5)); 384 sheetP.add(spreadsheetButton); 385 int tclass = sd.getDatatype().getDatatypeClass(); 386 sheetP.add(charCheckbox); 387 if (tclass == Datatype.CLASS_CHAR 388 || (tclass == Datatype.CLASS_INTEGER && sd 389 .getDatatype().getDatatypeSize() == 1)) { 390 charCheckbox.setEnabled(false); 391 } 392 393 // add tableview selection 394 JPanel tviewP = new JPanel(); 395 tviewP.setLayout(new BorderLayout()); 396 tviewP.add(new JLabel("TableView: "), BorderLayout.WEST); 397 tviewP.add(choiceTableView, BorderLayout.CENTER); 398 399 JPanel leftP = new JPanel(); 400 leftP.setBorder(BorderFactory 401 .createLineBorder(Color.LIGHT_GRAY)); 402 leftP.setLayout(new GridLayout(2, 1, 5, 5)); 403 leftP.add(sheetP); 404 leftP.add(tviewP); 405 406 viewP.add(leftP); 407 408 // add imageview selection 409 JPanel rightP = new JPanel(); 410 rightP.setLayout(new BorderLayout(5, 5)); 411 rightP.setBorder(BorderFactory.createLineBorder(Color.LIGHT_GRAY)); 412 JPanel imageP1 = new JPanel(); 413 JPanel imageP2 = new JPanel(); 414 rightP.add(imageP1, BorderLayout.CENTER); 415 rightP.add(imageP2, BorderLayout.EAST); 416 viewP.add(rightP); 417 imageP1.setLayout(new BorderLayout(5, 5)); 418 JPanel tmpP = new JPanel(); 419 tmpP.setLayout(new GridLayout(2, 1, 5, 5)); 420 tmpP.add(imageButton); 421 tmpP.add(new JLabel("ImageView: ")); 422 imageP1.add(tmpP, BorderLayout.WEST); 423 tmpP = new JPanel(); 424 tmpP.setLayout(new GridLayout(2, 1, 5, 5)); 425 tmpP.add(choicePalette); 426 tmpP.add(choiceImageView); 427 imageP1.add(tmpP, BorderLayout.CENTER); 428 429 imageP2.setLayout(new GridLayout(1, 2, 5, 5)); 430 tmpP = new JPanel(); 431 tmpP.setLayout(new GridLayout(2, 1, 5, 5)); 432 tmpP.add(new JLabel(" Valid Range: ")); 433 tmpP.add(new JLabel(" Invalid Values: ")); 434 imageP2.add(tmpP); 435 tmpP = new JPanel(); 436 tmpP.setLayout(new GridLayout(2, 1, 5, 5)); 437 String minmaxStr = "min, max", fillStr = "val1, val2, ..."; 438 double minmax[] = ((ScalarDS) dataset).getImageDataRange(); 439 if (minmax != null) { 440 if (dataset.getDatatype().getDatatypeClass() == Datatype.CLASS_FLOAT) 441 minmaxStr = minmax[0] + "," + minmax[1]; 442 else 443 minmaxStr = ((long) minmax[0]) + "," + ((long) minmax[1]); 444 } 445 List<Number> fillValue = ((ScalarDS) dataset).getFilteredImageValues(); 446 int n = fillValue.size(); 447 if (n > 0) { 448 fillStr = fillValue.get(0).toString(); 449 for (int i = 1; i < n; i++) { 450 fillStr += ", " + fillValue.get(i); 451 } 452 } 453 tmpP.add(dataRangeField = new JTextField(minmaxStr)); 454 tmpP.add(fillValueField = new JTextField(fillStr)); 455 imageP2.add(tmpP); 456 457 JPanel northP = new JPanel(); 458 northP.setLayout(new BorderLayout(5, 5)); 459 northP.add(viewP, BorderLayout.CENTER); 460 461 // index base and bit mask 462 viewP = new JPanel(); 463 viewP.setLayout(new BorderLayout()); 464 northP.add(viewP, BorderLayout.SOUTH); 465 466 JPanel baseIndexP = new JPanel(); 467 viewP.add(baseIndexP, BorderLayout.NORTH); 468 tborder = new TitledBorder("Index Base"); 469 tborder.setTitleColor(Color.gray); 470 baseIndexP.setBorder(tborder); 471 baseIndexP.setLayout(new GridLayout(1, 2, 5, 5)); 472 473 ButtonGroup bgrp = new ButtonGroup(); 474 bgrp.add(base0Button); 475 bgrp.add(base1Button); 476 477 baseIndexP.add(base0Button); 478 baseIndexP.add(base1Button); 479 480 int tsize = sd.getDatatype().getDatatypeSize(); 481 bitmaskButtons = (tsize >= 0) ? new JRadioButton[8 * tsize] : new JRadioButton[0]; 482 for (int i = 0; i < bitmaskButtons.length; i++) { 483 bitmaskButtons[i] = new JRadioButton(String.valueOf(i)); 484 bitmaskButtons[i].setEnabled(false); 485 bitmaskButtons[i].addItemListener(this); 486 bitmaskButtons[i].setName("bitmaskButton"+i); 487 } 488 489 JPanel sheetP2 = new JPanel(); 490 viewP.add(sheetP2, BorderLayout.CENTER); 491 tborder = new TitledBorder("Bitmask"); 492 tborder.setTitleColor(Color.gray); 493 sheetP2.setBorder(tborder); 494 495 tmpP = new JPanel(); 496 if (bitmaskButtons.length <= 16) { 497 tmpP.setLayout(new GridLayout(1, bitmaskButtons.length)); 498 for (int i = bitmaskButtons.length; i > 0; i--) 499 tmpP.add(bitmaskButtons[i - 1]); 500 } else { 501 tmpP.setLayout(new GridLayout(tsize/2, 16)); 502 for (int i = bitmaskButtons.length; i > 0; i--) 503 tmpP.add(bitmaskButtons[i - 1]); 504 } 505 506 sheetP2.setLayout(new BorderLayout(10, 10)); 507 if (tsize <= 8) sheetP2.add(tmpP, BorderLayout.CENTER); 508 sheetP2.add(new JLabel(), BorderLayout.NORTH); 509 510 JPanel tmpP2 = new JPanel(); 511 tmpP2.setLayout(new GridLayout(2, 1)); 512 tmpP2.add(extractBitButton); 513 tmpP2.add(applyBitmaskButton); 514 tmpP = new JPanel(); 515 tmpP.setLayout(new BorderLayout()); 516 tmpP.add(tmpP2, BorderLayout.WEST); 517 tmpP2 = new JPanel(); 518 tmpP2.add(bitmaskHelp); 519 tmpP.add(tmpP2, BorderLayout.EAST); 520 sheetP2.add(tmpP, BorderLayout.NORTH); 521 contentPane.add(northP, BorderLayout.NORTH); 522 523 if (tclass == Datatype.CLASS_CHAR 524 || (tclass == Datatype.CLASS_INTEGER && tsize <= 8)) { 525 extractBitButton.setEnabled(true); 526 applyBitmaskButton.setEnabled(true); 527 bitmaskHelp.setEnabled(true); 528 } 529 } 530 } 531 532 // setup GUI for dimension and subset selection 533 JPanel selectionP = new JPanel(); 534 selectionP.setLayout(new GridLayout(5, 6, 10, 3)); 535 selectionP.setBorder(new EtchedBorder(EtchedBorder.LOWERED)); 536 537 centerP.add(selectionP, BorderLayout.CENTER); 538 contentPane.add(centerP, BorderLayout.CENTER); 539 540 selectionP.add(new JLabel(" ")); 541 if (rank > 1) 542 selectionP.add(transposeChoice); 543 else 544 selectionP.add(new JLabel(" ")); 545 546 JLabel label = new JLabel("Start:"); 547 selectionP.add(label); 548 label = new JLabel("End: "); 549 selectionP.add(label); 550 label = new JLabel("Stride:"); 551 selectionP.add(label); 552 label = new JLabel("Max Size"); 553 selectionP.add(label); 554 555 choices = new JComboBox[3]; 556 maxLabels = new JLabel[3]; 557 startFields = new JTextField[3]; 558 endFields = new JTextField[3]; 559 strideFields = new JTextField[3]; 560 JLabel dimLabels[] = { new JLabel("Height", SwingConstants.RIGHT), 561 new JLabel("Width", SwingConstants.RIGHT), 562 new JLabel("Depth", SwingConstants.RIGHT), }; 563 564 String[] dimNames = dataset.getDimNames(); 565 for (int i = 0; i < 3; i++) { 566 choices[i] = new JComboBox(); 567 choices[i].addItemListener(this); 568 for (int j = 0; j < rank; j++) { 569 if (dimNames == null) { 570 choices[i].addItem("dim " + j); 571 } 572 else { 573 choices[i].addItem(dimNames[j]); 574 } 575 } 576 maxLabels[i] = new JLabel("1"); 577 startFields[i] = new JTextField("0"); 578 endFields[i] = new JTextField("0"); 579 strideFields[i] = new JTextField("1"); 580 selectionP.add(dimLabels[i]); 581 selectionP.add(choices[i]); 582 selectionP.add(startFields[i]); 583 selectionP.add(endFields[i]); 584 selectionP.add(strideFields[i]); 585 selectionP.add(maxLabels[i]); 586 587 // disable the selection components 588 // init() will set them appropriate 589 choices[i].setEnabled(false); 590 startFields[i].setEnabled(false); 591 endFields[i].setEnabled(false); 592 strideFields[i].setEnabled(false); 593 maxLabels[i].setEnabled(false); 594 595 // Provide fields with names for access 596 startFields[i].setName("startField"+i); 597 endFields[i].setName("endField"+i); 598 strideFields[i].setName("strideField"+i); 599 choices[i].setName("dimensionBox"+i); 600 } 601 602 // add button dimension selection when dimension size >= 4 603 JButton button = new JButton("dims..."); 604 selectionP.add(new JLabel("", SwingConstants.RIGHT)); 605 selectionP.add(button); 606 607 button.setActionCommand("Select more dimensions"); 608 button.addActionListener(this); 609 button.setEnabled((rank > 3)); 610 selectionP.add(new JLabel(" ")); 611 selectionP.add(new JLabel(" ")); 612 button = new JButton("Reset"); 613 button.setName("Reset"); 614 button.setActionCommand("Reset data range"); 615 button.addActionListener(this); 616 selectionP.add(button); 617 selectionP.add(new JLabel(" ")); 618 619 // add OK and CANCEL buttons 620 JPanel confirmP = new JPanel(); 621 contentPane.add(confirmP, BorderLayout.SOUTH); 622 button = new JButton(" Ok "); 623 button.setName("OK"); 624 button.setMnemonic(KeyEvent.VK_O); 625 button.setActionCommand("Ok"); 626 button.addActionListener(this); 627 confirmP.add(button); 628 button = new JButton("Cancel"); 629 button.setName("Cancel"); 630 button.setMnemonic(KeyEvent.VK_C); 631 button.setActionCommand("Cancel"); 632 button.addActionListener(this); 633 confirmP.add(button); 634 635 init(); 636 637 // locate the H5Property dialog 638 Point l = getParent().getLocation(); 639 l.x += 250; 640 l.y += 80; 641 setLocation(l); 642 pack(); 643 } 644 645 @Override 646 public void actionPerformed (ActionEvent e) { 647 String cmd = e.getActionCommand(); 648 649 if (cmd.equals("Ok")) { 650 // set palette for image view 651 if ((dataset instanceof ScalarDS) && imageButton.isSelected()) { 652 setPalette(); 653 } 654 655 isSelectionCancelled = !setSelection(); 656 657 if (isSelectionCancelled) { 658 return; 659 } 660 661 if (dataset instanceof ScalarDS) { 662 ((ScalarDS) dataset).setIsImageDisplay(imageButton.isSelected()); 663 } 664 665 dispose(); 666 } 667 else if (cmd.equals("Cancel")) { 668 dispose(); 669 } 670 else if (cmd.equals("Reset data range")) { 671 int n = startFields.length; 672 673 for (int i = 0; i < n; i++) { 674 startFields[i].setText("0"); 675 strideFields[i].setText("1"); 676 long l = Long.valueOf(maxLabels[i].getText()) - 1; 677 endFields[i].setText(String.valueOf(l)); 678 } 679 } 680 else if (cmd.equals("Select more dimensions")) { 681 if (rank < 4) { 682 return; 683 } 684 685 int idx = 0; 686 Vector<Object> choice4 = new Vector<Object>(rank); 687 int[] choice4Index = new int[rank - 3]; 688 for (int i = 0; i < rank; i++) { 689 if ((i != currentIndex[0]) && (i != currentIndex[1]) 690 && (i != currentIndex[2])) { 691 choice4.add(choices[0].getItemAt(i)); 692 choice4Index[idx++] = i; 693 } 694 } 695 696 String msg = "Select slice location for dimension(s):\n\"" 697 + choice4.get(0) + " [0 .. " + (dims[choice4Index[0]] - 1) 698 + "]\""; 699 String initValue = String.valueOf(start[choice4Index[0]]); 700 int n = choice4.size(); 701 for (int i = 1; i < n; i++) { 702 msg += " x \"" + choice4.get(i) + " [0 .. " 703 + (dims[choice4Index[i]] - 1) + "]\""; 704 initValue += " x " + String.valueOf(start[choice4Index[i]]); 705 } 706 707 String result = JOptionPane.showInputDialog(this, msg, initValue); 708 if ((result == null) || ((result = result.trim()) == null) 709 || (result.length() < 1)) { 710 return; 711 } 712 713 StringTokenizer st = new StringTokenizer(result, "x"); 714 if (st.countTokens() < n) { 715 JOptionPane.showMessageDialog(this, 716 "Number of dimension(s) is less than " + n + "\n" 717 + result, "Select Slice Location", 718 JOptionPane.ERROR_MESSAGE); 719 return; 720 } 721 722 long[] start4 = new long[n]; 723 for (int i = 0; i < n; i++) { 724 try { 725 start4[i] = Long.parseLong(st.nextToken().trim()); 726 } 727 catch (Exception ex) { 728 JOptionPane.showMessageDialog(this, ex.getMessage(), 729 "Select Slice Location", JOptionPane.ERROR_MESSAGE); 730 return; 731 } 732 733 if ((start4[i] < 0) || (start4[i] >= dims[choice4Index[i]])) { 734 JOptionPane.showMessageDialog(this, 735 "Slice location is out of range.\n" + start4[i] 736 + " >= " + dims[choice4Index[i]], 737 "Select Slice Location", JOptionPane.ERROR_MESSAGE); 738 return; 739 } 740 741 } 742 743 for (int i = 0; i < n; i++) { 744 start[choice4Index[i]] = start4[i]; 745 } 746 } // else if (cmd.equals("Select more dimensions")) 747 else if (cmd.equals("Help on how to set bitmask")) { 748 String msg = "" 749 + "\"Apply Bitmask\" applies bitwise \"AND\" to the original data.\n" 750 + "For example, bits 2, 3, and 4 are selected for the bitmask\n" 751 + " 10010101 (data)\n" 752 + "AND 00011100 (mask) \n" 753 + " = 00010100 (result) ==> the decimal value is 20. \n" 754 + "\n" 755 + "\"Extract Bit(s)\" removes all the bits from the result above where\n" 756 + "their corresponding bits in the bitmask are 0. \nFor the same example above, " 757 + "the result is \n101 ==> the decimal value is 5.\n\n"; 758 759 JOptionPane.showMessageDialog((JFrame) viewer, msg); 760 } 761 } 762 763 @Override 764 public void itemStateChanged (ItemEvent e) { 765 Object source = e.getSource(); 766 767 if (source.equals(imageButton)) { 768 choicePalette.setEnabled(!isTrueColorImage); 769 dataRangeField.setEnabled(true); 770 fillValueField.setEnabled(true); 771 choiceImageView.setEnabled(true); 772 choiceTableView.setEnabled(false); 773 charCheckbox.setSelected(false); 774 charCheckbox.setEnabled(false); 775 } 776 else if (source.equals(spreadsheetButton)) { 777 choicePalette.setEnabled(false); 778 choiceImageView.setEnabled(false); 779 choiceTableView.setEnabled(true); 780 dataRangeField.setEnabled(false); 781 fillValueField.setEnabled(false); 782 Datatype dtype = dataset.getDatatype(); 783 int tclass = dtype.getDatatypeClass(); 784 charCheckbox.setEnabled((tclass == Datatype.CLASS_CHAR || 785 tclass == Datatype.CLASS_INTEGER) && 786 (dtype.getDatatypeSize() == 1)); 787 } 788 else if (source instanceof JToggleButton) { 789 checkBitmaskButtons((JToggleButton) source); 790 } 791 else if (source instanceof JComboBox) { 792 if (!performJComboBoxEvent) { 793 return; 794 } 795 796 if (e.getStateChange() == ItemEvent.DESELECTED) { 797 return; // don't care about the deselect 798 } 799 800 @SuppressWarnings("rawtypes") 801 JComboBox theChoice = (JComboBox) source; 802 803 int theSelectedChoice = -1; 804 805 int n = Math.min(3, rank); 806 for (int i = 0; i < n; i++) { 807 if (theChoice.equals(choices[i])) { 808 theSelectedChoice = i; 809 } 810 } 811 812 if (theSelectedChoice < 0) { 813 return; // the selected JComboBox is not a dimension choice 814 } 815 816 int theIndex = theChoice.getSelectedIndex(); 817 if (theIndex == currentIndex[theSelectedChoice]) { 818 return; // select the same item, no change 819 } 820 821 start[currentIndex[theSelectedChoice]] = 0; 822 823 // reset the selected dimension choice 824 startFields[theSelectedChoice].setText("0"); 825 endFields[theSelectedChoice].setText(String 826 .valueOf(dims[theIndex] - 1)); 827 strideFields[theSelectedChoice].setText("1"); 828 maxLabels[theSelectedChoice] 829 .setText(String.valueOf(dims[theIndex])); 830 831 // if the selected choice selects the dimension that is selected by 832 // other dimension choice, exchange the dimensions 833 for (int i = 0; i < n; i++) { 834 if (i == theSelectedChoice) { 835 continue; // don't exchange itself 836 } 837 else if (theIndex == choices[i].getSelectedIndex()) { 838 setJComboBoxSelectedIndex(choices[i], 839 currentIndex[theSelectedChoice]); 840 startFields[i].setText("0"); 841 endFields[i] 842 .setText(String 843 .valueOf(dims[currentIndex[theSelectedChoice]] - 1)); 844 strideFields[i].setText("1"); 845 maxLabels[i].setText(String 846 .valueOf(dims[currentIndex[theSelectedChoice]])); 847 } 848 } 849 850 for (int i = 0; i < n; i++) { 851 currentIndex[i] = choices[i].getSelectedIndex(); 852 } 853 854 // update the navigator 855 if (rank > 1) { 856 if (isText) { 857 endFields[1].setText(startFields[1].getText()); 858 } 859 else { 860 int hIdx = choices[0].getSelectedIndex(); 861 int wIdx = choices[1].getSelectedIndex(); 862 transposeChoice.setSelectedIndex(0); 863 864 // Use transpose option only if the dims are not in original 865 // order 866 if (hIdx < wIdx) 867 transposeChoice.setEnabled(false); 868 else 869 transposeChoice.setEnabled(true); 870 871 long dims[] = dataset.getDims(); 872 int w = (int) dims[wIdx]; 873 int h = (int) dims[hIdx]; 874 navigator.setDimensionSize(w, h); 875 navigator.updateUI(); 876 } 877 } 878 879 if (rank > 2) { 880 endFields[2].setText(startFields[2].getText()); 881 } 882 } // else if (source instanceof JComboBox) 883 } 884 885 /** 886 * Returns true if the data selection is cancelled. 887 * 888 * @return true if the data selection is cancelled; false otherwise 889 */ 890 public boolean isCancelled ( ) { 891 return isSelectionCancelled; 892 } 893 894 /** 895 * Returns true if the display option is image. 896 * 897 * @return true if the display option is image; false otherwise 898 */ 899 public boolean isImageDisplay ( ) { 900 return imageButton.isSelected(); 901 } 902 903 public boolean isIndexBase1 ( ) { 904 if (base1Button == null) 905 return false; 906 907 return base1Button.isSelected(); 908 } 909 910 /** for deal with bit masks only */ 911 private void checkBitmaskButtons (JToggleButton source) { 912 boolean b = false; 913 int n = 0; 914 915 if (source.equals(applyBitmaskButton)) { 916 if (applyBitmaskButton.isSelected()) 917 extractBitButton.setSelected(false); 918 } 919 else if (source.equals(extractBitButton)) { 920 if (extractBitButton.isSelected()) 921 applyBitmaskButton.setSelected(false); 922 } 923 924 b = (applyBitmaskButton.isSelected() || extractBitButton.isSelected()); 925 bitmaskButtons[0].setEnabled(b); 926 if (bitmaskButtons[0].isSelected()) 927 n = 1; 928 929 for (int i = 1; i < bitmaskButtons.length; i++) { 930 bitmaskButtons[i].setEnabled(b); 931 if (bitmaskButtons[i].isSelected() && !bitmaskButtons[i - 1].isSelected()) 932 n++; 933 } 934 935 // do not allow non-adjacent selection for extracting bits 936 if (extractBitButton.isSelected() && n > 1) { 937 if (source.equals(extractBitButton) && extractBitButton.isSelected()) { 938 applyBitmaskButton.setSelected(true); 939 JOptionPane.showMessageDialog(this, 940 "Selecting non-adjacent bits is only allowed \nfor the \"Apply Bitmask\" option.", 941 "Select Bitmask", 942 JOptionPane.ERROR_MESSAGE); 943 } 944 else if (source instanceof JRadioButton) { 945 JOptionPane.showMessageDialog(this, 946 "Please select contiguous bits \nwhen the \"Show Value of Selected Bits\" option is checked.", 947 "Select Bitmask", 948 JOptionPane.ERROR_MESSAGE); 949 source.setSelected(false); 950 } 951 } // if (extractBitButton.isSelected() && n>1) { 952 } 953 954 /** 955 * Set the initial state of all the variables 956 */ 957 private void init ( ) { 958 // set the imagebutton state 959 boolean isImage = false; 960 961 if (dataset instanceof ScalarDS) { 962 if(!((ScalarDS) dataset).isText()) { 963 ScalarDS sd = (ScalarDS) dataset; 964 isImage = sd.isImageDisplay(); 965 isTrueColorImage = sd.isTrueColor(); 966 // compound datasets don't have data range or fill values 967 // (JAVA-1825) 968 dataRangeField.setEnabled(isImage); 969 fillValueField.setEnabled(isImage); 970 } 971 } 972 else if (dataset instanceof CompoundDS) { 973 imageButton.setEnabled(false); 974 } 975 976 choiceTableView.setEnabled(!isImage); 977 choiceImageView.setEnabled(isImage); 978 imageButton.setSelected(isImage); 979 choicePalette.setEnabled(isImage && !isTrueColorImage); 980 981 int n = Math.min(3, rank); 982 long endIdx = 0; 983 for (int i = 0; i < n; i++) { 984 choices[i].setEnabled(true); 985 startFields[i].setEnabled(true); 986 endFields[i].setEnabled(true); 987 strideFields[i].setEnabled(true); 988 maxLabels[i].setEnabled(true); 989 990 int idx = selectedIndex[i]; 991 endIdx = start[idx] + selected[idx] * stride[idx]; 992 if (endIdx >= dims[idx]) { 993 endIdx = dims[idx]; 994 } 995 996 setJComboBoxSelectedIndex(choices[i], idx); 997 maxLabels[i].setText(String.valueOf(dims[idx])); 998 startFields[i].setText(String.valueOf(start[idx])); 999 endFields[i].setText(String.valueOf(endIdx - 1)); 1000 1001 if (!isH5 && (dataset instanceof CompoundDS)) { 1002 strideFields[i].setEnabled(false); 1003 } 1004 else { 1005 strideFields[i].setText(String.valueOf(stride[idx])); 1006 } 1007 } 1008 1009 if (rank > 1) { 1010 transposeChoice 1011 .setEnabled((choices[0].getSelectedIndex() > choices[1] 1012 .getSelectedIndex())); 1013 1014 if (isText) { 1015 endFields[1].setEnabled(false); 1016 endFields[1].setText(startFields[1].getText()); 1017 } 1018 } 1019 1020 if (rank > 2) { 1021 endFields[2].setEnabled(false); 1022 strideFields[2].setEnabled(false); 1023 if (isTrueColorImage && imageButton.isSelected()) { 1024 choices[0].setEnabled(false); 1025 choices[1].setEnabled(false); 1026 choices[2].setEnabled(false); 1027 startFields[2].setEnabled(false); 1028 startFields[2].setText("0"); 1029 endFields[2].setText("0"); 1030 } 1031 else { 1032 choices[0].setEnabled(true); 1033 choices[1].setEnabled(true); 1034 choices[2].setEnabled(true); 1035 startFields[2].setEnabled(true); 1036 startFields[2].setText(String.valueOf(start[selectedIndex[2]])); 1037 // endFields[2].setEnabled(!isText); 1038 endFields[2].setText(startFields[2].getText()); 1039 } 1040 } 1041 1042 for (int i = 0; i < n; i++) { 1043 currentIndex[i] = choices[i].getSelectedIndex(); 1044 } 1045 1046 // reset show char button 1047 Datatype dtype = dataset.getDatatype(); 1048 int tclass = dtype.getDatatypeClass(); 1049 if (tclass == Datatype.CLASS_CHAR || tclass == Datatype.CLASS_INTEGER) { 1050 int tsize = dtype.getDatatypeSize(); 1051 charCheckbox.setEnabled((tsize == 1) && spreadsheetButton.isSelected()); 1052 extractBitButton.setEnabled(tsize <= 8); 1053 applyBitmaskButton.setEnabled(tsize <= 8); 1054 } 1055 else { 1056 charCheckbox.setEnabled(false); 1057 charCheckbox.setSelected(false); 1058 extractBitButton.setEnabled(false); 1059 applyBitmaskButton.setEnabled(false); 1060 } 1061 } 1062 1063 /** 1064 * JComboBox.setSelectedItem() or setSelectedIndex() always fires action event. If you call 1065 * setSelectedItem() or setSelectedIndex() at itemStateChanged() or actionPerformed(), the 1066 * setSelectedItem() or setSelectedIndex() will make loop calls of itemStateChanged() or 1067 * actionPerformed(). This is not what we want. We want the setSelectedItem() or 1068 * setSelectedIndex() behavior like java.awt.Choice. This flag is used to serve this purpose. 1069 */ 1070 @SuppressWarnings("rawtypes") 1071 private void setJComboBoxSelectedIndex (JComboBox box, int idx) { 1072 performJComboBoxEvent = false; 1073 box.setSelectedIndex(idx); 1074 performJComboBoxEvent = true; 1075 } 1076 1077 private void setPalette ( ) { 1078 if (!(dataset instanceof ScalarDS)) { 1079 return; 1080 } 1081 1082 byte[][] pal = null; 1083 int palChoice = choicePalette.getSelectedIndex(); 1084 1085 if (palChoice == 0) { 1086 return; /* using default palette */ 1087 } 1088 1089 if (palChoice == numberOfPalettes + 1) { 1090 pal = Tools.createGrayPalette(); 1091 } 1092 else if (palChoice == numberOfPalettes + 2) { 1093 pal = Tools.createReverseGrayPalette(); 1094 } 1095 else if (palChoice == numberOfPalettes + 3) { 1096 pal = Tools.createGrayWavePalette(); 1097 } 1098 else if (palChoice == numberOfPalettes + 4) { 1099 pal = Tools.createRainbowPalette(); 1100 } 1101 else if (palChoice == numberOfPalettes + 5) { 1102 pal = Tools.createNaturePalette(); 1103 } 1104 else if (palChoice == numberOfPalettes + 6) { 1105 pal = Tools.createWavePalette(); 1106 } 1107 else if ((palChoice > 0) && (palChoice <= numberOfPalettes)) { 1108 // multiple palettes attached 1109 pal = ((ScalarDS) dataset).readPalette(palChoice - 1); 1110 } 1111 1112 ((ScalarDS) dataset).setPalette(pal); 1113 } 1114 1115 private boolean setSelection ( ) { 1116 long[] n0 = { 0, 0, 0 }; // start 1117 long[] n1 = { 0, 0, 0 }; // end 1118 long[] n2 = { 1, 1, 1 }; // stride 1119 int[] sIndex = { 0, 1, 2 }; 1120 boolean retVal = true; 1121 1122 int n = Math.min(3, rank); 1123 for (int i = 0; i < n; i++) { 1124 sIndex[i] = choices[i].getSelectedIndex(); 1125 1126 try { 1127 n0[i] = Long.parseLong(startFields[i].getText()); 1128 if (i < 2) { 1129 n1[i] = Long.parseLong(endFields[i].getText()); 1130 n2[i] = Long.parseLong(strideFields[i].getText()); 1131 } 1132 } 1133 catch (NumberFormatException ex) { 1134 toolkit.beep(); 1135 JOptionPane.showMessageDialog((JFrame) viewer, ex.getMessage(), 1136 getTitle(), JOptionPane.ERROR_MESSAGE); 1137 return false; 1138 } 1139 1140 // silently correct errors 1141 if (n0[i] < 0) { 1142 n0[i] = 0; // start 1143 } 1144 if (n0[i] >= dims[sIndex[i]]) { 1145 n0[i] = dims[sIndex[i]] - 1; 1146 } 1147 if (n1[i] < 0) { 1148 n1[i] = 0; // end 1149 } 1150 if (n1[i] >= dims[sIndex[i]]) { 1151 n1[i] = dims[sIndex[i]] - 1; 1152 } 1153 if (n0[i] > n1[i]) { 1154 n1[i] = n0[i]; // end <= start 1155 } 1156 if (n2[i] > dims[sIndex[i]]) { 1157 n2[i] = dims[sIndex[i]]; 1158 } 1159 if (n2[i] <= 0) { 1160 n2[i] = 1; // stride cannot be zero 1161 } 1162 } // for (int i=0; i<n; i++) 1163 1164 if (dataset instanceof CompoundDS) { 1165 CompoundDS d = (CompoundDS) dataset; 1166 int[] selectedFieldIndices = fieldList.getSelectedIndices(); 1167 if ((selectedFieldIndices == null) 1168 || (selectedFieldIndices.length < 1)) { 1169 toolkit.beep(); 1170 JOptionPane.showMessageDialog((JFrame) viewer, 1171 "No member/field is selected.", getTitle(), 1172 JOptionPane.ERROR_MESSAGE); 1173 return false; 1174 } 1175 1176 d.setMemberSelection(false); // deselect all members 1177 for (int i = 0; i < selectedFieldIndices.length; i++) { 1178 d.selectMember(selectedFieldIndices[i]); 1179 } 1180 } 1181 else { 1182 ScalarDS ds = (ScalarDS) dataset; 1183 1184 if(!ds.isText()) { 1185 StringTokenizer st = new StringTokenizer(dataRangeField.getText(), ","); 1186 if (st.countTokens() == 2) { 1187 double min = 0, max = 0; 1188 try { 1189 min = Double.valueOf(st.nextToken()); 1190 max = Double.valueOf(st.nextToken()); 1191 } 1192 catch (Throwable ex) { 1193 } 1194 if (max > min) 1195 ds.setImageDataRange(min, max); 1196 } 1197 st = new StringTokenizer(fillValueField.getText(), ","); 1198 while (st.hasMoreTokens()) { 1199 double x = 0; 1200 try { 1201 x = Double.valueOf(st.nextToken()); 1202 ds.addFilteredImageValue(x); 1203 } 1204 catch (Throwable ex) { 1205 } 1206 } 1207 } 1208 } 1209 1210 // reset selected size 1211 for (int i = 0; i < rank; i++) { 1212 selected[i] = 1; 1213 stride[i] = 1; 1214 } 1215 1216 // find no error, set selection the the dataset object 1217 for (int i = 0; i < n; i++) { 1218 selectedIndex[i] = sIndex[i]; 1219 start[selectedIndex[i]] = n0[i]; 1220 if (i < 2) { 1221 selected[selectedIndex[i]] = (int) ((n1[i] - n0[i]) / n2[i]) + 1; 1222 stride[selectedIndex[i]] = n2[i]; 1223 } 1224 } 1225 1226 if ((rank > 1) && isText) { 1227 selected[selectedIndex[1]] = 1; 1228 stride[selectedIndex[1]] = 1; 1229 } 1230 else if ((rank > 2) && isTrueColorImage && imageButton.isSelected()) { 1231 start[selectedIndex[2]] = 0; 1232 selected[selectedIndex[2]] = 3; 1233 } 1234 1235 // clear the old data 1236 dataset.clearData(); 1237 1238 retVal = setBitmask(); 1239 1240 return retVal; 1241 } 1242 1243 private boolean setBitmask ( ) 1244 { 1245 boolean isAll = false, isNothing = false; 1246 1247 if (bitmaskButtons == null) { 1248 bitmask = null; 1249 return true; 1250 } 1251 1252 if (!(applyBitmaskButton.isSelected() || extractBitButton.isSelected())) { 1253 bitmask = null; 1254 return true; 1255 } 1256 1257 int len = bitmaskButtons.length; 1258 for (int i = 0; i < len; i++) { 1259 isAll = (isAll && bitmaskButtons[i].isSelected()); 1260 isNothing = (isNothing && !bitmaskButtons[i].isSelected()); 1261 } 1262 1263 if (isAll || isNothing) { 1264 bitmask = null; 1265 return true; 1266 } 1267 1268 if (bitmask == null) 1269 bitmask = new BitSet(len); 1270 1271 for (int i = 0; i < len; i++) { 1272 bitmask.set(i, bitmaskButtons[i].isSelected()); 1273 } 1274 1275 return true; 1276 } 1277 1278 /** SubsetNavigator draws selection rectangle of subset. */ 1279 private class PreviewNavigator extends JComponent implements MouseListener, 1280 MouseMotionListener { 1281 private static final long serialVersionUID = -4458114008420664965L; 1282 private final int NAVIGATOR_SIZE = 150; 1283 private int dimX, dimY, x, y; 1284 private double r; 1285 private Point startPosition; // mouse 1286 // clicked 1287 // position 1288 private Rectangle selectedArea; 1289 private Image previewImage = null; 1290 1291 private PreviewNavigator(int w, int h) { 1292 dimX = w; 1293 dimY = h; 1294 if (dimX > dimY) { 1295 x = NAVIGATOR_SIZE; 1296 r = dimX / (double) x; 1297 y = (int) (dimY / r); 1298 } 1299 else { 1300 y = NAVIGATOR_SIZE; 1301 r = dimY / (double) y; 1302 x = (int) (dimX / r); 1303 } 1304 1305 selectedArea = new Rectangle(); 1306 setPreferredSize(new Dimension(NAVIGATOR_SIZE, NAVIGATOR_SIZE)); 1307 try { 1308 previewImage = createPreviewImage(); 1309 } 1310 catch (Exception ex) { 1311 ex.printStackTrace(); 1312 } 1313 1314 addMouseListener(this); 1315 addMouseMotionListener(this); 1316 } 1317 1318 private Image createPreviewImage ( ) throws Exception { 1319 if ((rank <= 1) || !(dataset instanceof ScalarDS)) { 1320 return null; 1321 } 1322 1323 Image preImage = null; 1324 ScalarDS sd = (ScalarDS) dataset; 1325 1326 if (sd.isText()) { 1327 return null; 1328 } 1329 1330 // backup the selection 1331 long[] strideBackup = new long[rank]; 1332 long[] selectedBackup = new long[rank]; 1333 long[] startBackup = new long[rank]; 1334 int[] selectedIndexBackup = new int[3]; 1335 System.arraycopy(stride, 0, strideBackup, 0, rank); 1336 System.arraycopy(selected, 0, selectedBackup, 0, rank); 1337 System.arraycopy(start, 0, startBackup, 0, rank); 1338 System.arraycopy(selectedIndex, 0, selectedIndexBackup, 0, 3); 1339 1340 // set the selection for preview 1341 for (int i = 0; i < rank; i++) { 1342 start[i] = 0; 1343 stride[i] = 1; 1344 selected[i] = 1; 1345 } 1346 1347 if (choices != null) { 1348 selectedIndex[0] = choices[0].getSelectedIndex(); 1349 selectedIndex[1] = choices[1].getSelectedIndex(); 1350 } 1351 long steps = (long) Math.ceil(r); 1352 selected[selectedIndex[0]] = (dims[selectedIndex[0]] / steps); 1353 selected[selectedIndex[1]] = (dims[selectedIndex[1]] / steps); 1354 stride[selectedIndex[0]] = stride[selectedIndex[1]] = steps; 1355 1356 if (selected[selectedIndex[0]] == 0) { 1357 selected[selectedIndex[0]] = 1; 1358 } 1359 if (selected[selectedIndex[1]] == 0) { 1360 selected[selectedIndex[1]] = 1; 1361 } 1362 1363 if (isTrueColorImage && (start.length > 2)) { 1364 start[selectedIndex[2]] = 0; 1365 selected[selectedIndex[2]] = 3; 1366 stride[selectedIndex[2]] = 1; 1367 } 1368 1369 // update the ration of preview image size to the real dataset 1370 y = (int) selected[selectedIndex[0]]; 1371 x = (int) selected[selectedIndex[1]]; 1372 r = Math.min((double) dims[selectedIndex[0]] 1373 / (double) selected[selectedIndex[0]], 1374 (double) dims[selectedIndex[1]] 1375 / (double) selected[selectedIndex[1]]); 1376 1377 try { 1378 Object data = sd.read(); 1379 int h = sd.getHeight(); 1380 int w = sd.getWidth(); 1381 1382 byte[] bData = Tools.getBytes(data, sd.getImageDataRange(), w, h, false, sd.getFilteredImageValues(), null); 1383 1384 if (isTrueColorImage) { 1385 boolean isPlaneInterlace = (sd.getInterlace() == ScalarDS.INTERLACE_PLANE); 1386 preImage = Tools.createTrueColorImage(bData, 1387 isPlaneInterlace, w, h); 1388 } 1389 else { 1390 byte[][] imagePalette = sd.getPalette(); 1391 if (imagePalette == null) { 1392 imagePalette = Tools.createGrayPalette(); 1393 } 1394 1395 if ((isH5 || (rank > 2)) 1396 && (selectedIndex[0] > selectedIndex[1])) { 1397 // transpose data 1398 int n = bData.length; 1399 byte[] bData2 = new byte[n]; 1400 for (int i = 0; i < h; i++) { 1401 for (int j = 0; j < w; j++) { 1402 bData[i * w + j] = bData2[j * h + i]; 1403 } 1404 } 1405 } 1406 if (!isH5 && !sd.isDefaultImageOrder() && (selectedIndex[1] > selectedIndex[0])) { 1407 // transpose data for hdf4 images where selectedIndex[1] 1408 // > selectedIndex[0] 1409 int n = bData.length; 1410 byte[] bData2 = new byte[n]; 1411 for (int i = 0; i < h; i++) { 1412 for (int j = 0; j < w; j++) { 1413 bData[i * w + j] = bData2[j * h + i]; 1414 } 1415 } 1416 } 1417 preImage = Tools.createIndexedImage(null, bData, imagePalette, w, h); 1418 } 1419 } 1420 finally { 1421 // set back the original selection 1422 System.arraycopy(strideBackup, 0, stride, 0, rank); 1423 System.arraycopy(selectedBackup, 0, selected, 0, rank); 1424 System.arraycopy(startBackup, 0, start, 0, rank); 1425 System.arraycopy(selectedIndexBackup, 0, selectedIndex, 0, 3); 1426 } 1427 1428 return preImage; 1429 } 1430 1431 @Override 1432 public void paint (Graphics g) { 1433 g.setColor(Color.blue); 1434 1435 if (previewImage != null) { 1436 g.drawImage(previewImage, 0, 0, this); 1437 } 1438 else { 1439 g.fillRect(0, 0, x, y); 1440 } 1441 1442 int w = selectedArea.width; 1443 int h = selectedArea.height; 1444 if ((w > 0) && (h > 0)) { 1445 g.setColor(Color.red); 1446 g.drawRect(selectedArea.x, selectedArea.y, w, h); 1447 } 1448 } 1449 1450 @Override 1451 public void mousePressed (MouseEvent e) { 1452 startPosition = e.getPoint(); 1453 selectedArea.setBounds(startPosition.x, startPosition.y, 0, 0); 1454 } 1455 1456 @Override 1457 public void mouseClicked (MouseEvent e) { 1458 startPosition = e.getPoint(); 1459 selectedArea.setBounds(startPosition.x, startPosition.y, 0, 0); 1460 repaint(); 1461 } 1462 1463 @Override 1464 public void mouseDragged (MouseEvent e) { 1465 Point p0 = startPosition; 1466 Point p1 = e.getPoint(); 1467 1468 int x0 = Math.max(0, Math.min(p0.x, p1.x)); 1469 int y0 = Math.max(0, Math.min(p0.y, p1.y)); 1470 int x1 = Math.min(x, Math.max(p0.x, p1.x)); 1471 int y1 = Math.min(y, Math.max(p0.y, p1.y)); 1472 1473 int w = x1 - x0; 1474 int h = y1 - y0; 1475 selectedArea.setBounds(x0, y0, w, h); 1476 1477 try { 1478 updateSelection(x0, y0, w, h); 1479 } 1480 catch (Exception ex) { 1481 } 1482 1483 repaint(); 1484 } 1485 1486 private void updateSelection (int x0, int y0, int w, int h) { 1487 int i0 = 0, i1 = 0; 1488 String selStr; 1489 1490 i0 = (int) (y0 * r); 1491 if (i0 > dims[currentIndex[0]]) { 1492 i0 = (int) dims[currentIndex[0]]; 1493 } 1494 startFields[0].setText(String.valueOf(i0)); 1495 1496 i1 = (int) ((y0 + h) * r); 1497 1498 if (i1 < i0) { 1499 i1 = i0; 1500 } 1501 endFields[0].setText(String.valueOf(i1)); 1502 1503 selStr = String.valueOf((int) (h * r)); 1504 1505 if (rank > 1) { 1506 i0 = (int) (x0 * r); 1507 if (i0 > dims[currentIndex[1]]) { 1508 i0 = (int) dims[currentIndex[1]]; 1509 } 1510 startFields[1].setText(String.valueOf(i0)); 1511 1512 i1 = (int) ((x0 + w) * r); 1513 if (i1 < i0) { 1514 i1 = i0; 1515 } 1516 endFields[1].setText(String.valueOf(i1)); 1517 1518 selStr += " x " + ((int) (w * r)); 1519 } 1520 1521 selLabel.setText(selStr); 1522 } 1523 1524 @Override 1525 public void mouseReleased (MouseEvent e) { 1526 } 1527 1528 @Override 1529 public void mouseEntered (MouseEvent e) { 1530 } 1531 1532 @Override 1533 public void mouseExited (MouseEvent e) { 1534 } 1535 1536 @Override 1537 public void mouseMoved (MouseEvent e) { 1538 } 1539 1540 private void setDimensionSize (int w, int h) { 1541 dimX = w; 1542 dimY = h; 1543 if (dimX > dimY) { 1544 x = NAVIGATOR_SIZE; 1545 r = dimX / (double) x; 1546 y = (int) (dimY / r); 1547 } 1548 else { 1549 y = NAVIGATOR_SIZE; 1550 r = dimY / (double) y; 1551 x = (int) (dimX / r); 1552 } 1553 setPreferredSize(new Dimension(NAVIGATOR_SIZE, NAVIGATOR_SIZE)); 1554 selectedArea.setSize(0, 0); 1555 try { 1556 previewImage = createPreviewImage(); 1557 } 1558 catch (Exception ex) { 1559 } 1560 1561 repaint(); 1562 } 1563 } // private class SubsetNavigator extends JComponent 1564 1565 /** 1566 * 1567 * @return true if display the data as characters; otherwise, display as numbers. 1568 */ 1569 public boolean isDisplayTypeChar ( ) { 1570 return charCheckbox.isSelected(); 1571 } 1572 1573 /** 1574 * Returns the bitmask. 1575 * 1576 * @return the bitmask to apply 1577 */ 1578 public BitSet getBitmask ( ) { 1579 if (bitmask == null) 1580 return null; 1581 1582 if (!extractBitButton.isEnabled()) 1583 return null; 1584 1585 // do not use bitmask if it is empty (all bits are zero) 1586 if (bitmask.isEmpty()) 1587 return null; 1588 1589 boolean isAllSelected = true; 1590 int size = bitmask.size(); 1591 for (int i = 0; i < size; i++) 1592 isAllSelected = (bitmask.get(i) && isAllSelected); 1593 1594 // do not use bitmask if it is full (all bits are one) 1595 if (isAllSelected) 1596 return null; 1597 1598 return bitmask; 1599 } 1600 1601 /** 1602 * Check if it only apply bitmask. 1603 * 1604 * @return true if only applying the bitmask; false otherwise 1605 */ 1606 public boolean isApplyBitmaskOnly ( ) 1607 { 1608 if (getBitmask() == null) 1609 return false; 1610 1611 return applyBitmaskButton.isSelected(); 1612 } 1613 1614 /** 1615 * 1616 * @return true if transpose the data in 2D table; otherwise, do not transpose the data. 1617 */ 1618 public boolean isTransposed ( ) { 1619 return (transposeChoice.getSelectedIndex() == 1); 1620 } 1621 1622 /** 1623 * Returns the name of selected dataview 1624 * 1625 * @return the name of the selected DataView 1626 */ 1627 public String getDataViewName ( ) { 1628 String viewName = null; 1629 1630 if (isText) { 1631 viewName = (String) choiceTextView.getSelectedItem(); 1632 } 1633 else if (isImageDisplay()) { 1634 viewName = (String) choiceImageView.getSelectedItem(); 1635 } 1636 else { 1637 viewName = (String) choiceTableView.getSelectedItem(); 1638 } 1639 1640 return viewName; 1641 } 1642}