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