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