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 hdf.hdf5lib.H5; 018import hdf.hdf5lib.exceptions.HDF5Exception; 019import hdf.object.CompoundDS; 020import hdf.object.Dataset; 021import hdf.object.Datatype; 022import hdf.object.FileFormat; 023import hdf.object.Group; 024import hdf.object.HObject; 025import hdf.object.ScalarDS; 026import hdf.object.h5.H5Datatype; 027import hdf.view.ViewProperties.BITMASK_OP; 028import java.awt.BorderLayout; 029import java.awt.Color; 030import java.awt.Component; 031import java.awt.Cursor; 032import java.awt.Dimension; 033import java.awt.GridLayout; 034import java.awt.Insets; 035import java.awt.Point; 036import java.awt.Toolkit; 037import java.awt.datatransfer.Clipboard; 038import java.awt.datatransfer.DataFlavor; 039import java.awt.datatransfer.StringSelection; 040import java.awt.event.ActionEvent; 041import java.awt.event.ActionListener; 042import java.awt.event.InputEvent; 043import java.awt.event.ItemEvent; 044import java.awt.event.ItemListener; 045import java.awt.event.KeyEvent; 046import java.awt.event.MouseEvent; 047import java.awt.event.MouseListener; 048import java.io.BufferedInputStream; 049import java.io.BufferedReader; 050import java.io.BufferedWriter; 051import java.io.DataOutputStream; 052import java.io.File; 053import java.io.FileInputStream; 054import java.io.FileNotFoundException; 055import java.io.FileOutputStream; 056import java.io.FileReader; 057import java.io.FileWriter; 058import java.io.IOException; 059import java.io.PrintWriter; 060import java.io.StringReader; 061import java.lang.reflect.Array; 062import java.lang.reflect.Constructor; 063import java.math.BigInteger; 064import java.nio.ByteBuffer; 065import java.nio.ByteOrder; 066import java.nio.DoubleBuffer; 067import java.nio.FloatBuffer; 068import java.nio.IntBuffer; 069import java.nio.LongBuffer; 070import java.nio.ShortBuffer; 071import java.text.DecimalFormat; 072import java.text.NumberFormat; 073import java.util.BitSet; 074import java.util.Enumeration; 075import java.util.HashMap; 076import java.util.Iterator; 077import java.util.List; 078import java.util.StringTokenizer; 079import java.util.Vector; 080import javax.swing.BorderFactory; 081import javax.swing.ButtonGroup; 082import javax.swing.CellEditor; 083import javax.swing.JButton; 084import javax.swing.JCheckBoxMenuItem; 085import javax.swing.JComboBox; 086import javax.swing.JComponent; 087import javax.swing.JDialog; 088import javax.swing.JFileChooser; 089import javax.swing.JFrame; 090import javax.swing.JInternalFrame; 091import javax.swing.JLabel; 092import javax.swing.JList; 093import javax.swing.JMenu; 094import javax.swing.JMenuBar; 095import javax.swing.JMenuItem; 096import javax.swing.JOptionPane; 097import javax.swing.JPanel; 098import javax.swing.JPopupMenu; 099import javax.swing.JRadioButton; 100import javax.swing.JScrollPane; 101import javax.swing.JSplitPane; 102import javax.swing.JTable; 103import javax.swing.JTextArea; 104import javax.swing.JTextField; 105import javax.swing.JViewport; 106import javax.swing.KeyStroke; 107import javax.swing.SwingConstants; 108import javax.swing.UIManager; 109import javax.swing.WindowConstants; 110import javax.swing.border.Border; 111import javax.swing.border.CompoundBorder; 112import javax.swing.border.EtchedBorder; 113import javax.swing.border.LineBorder; 114import javax.swing.border.MatteBorder; 115import javax.swing.border.TitledBorder; 116import javax.swing.event.ChangeEvent; 117import javax.swing.event.ListSelectionEvent; 118import javax.swing.table.AbstractTableModel; 119import javax.swing.table.JTableHeader; 120import javax.swing.table.TableCellRenderer; 121import javax.swing.table.TableColumn; 122import javax.swing.tree.DefaultMutableTreeNode; 123import javax.swing.tree.TreeNode; 124 125/** 126 * TableView displays an HDF dataset as a two-dimensional table. 127 */ 128public class DefaultTableView extends JInternalFrame implements TableView, ActionListener, MouseListener { 129 private static final long serialVersionUID = -7452459299532863847L; 130 131 private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(DefaultTableView.class); 132 133 /** 134 * The main HDFView. 135 */ 136 private final ViewManager viewer; 137 138 /** 139 * Numerical data type. B = byte array, S = short array, I = int array, J = long array, F = 140 * float array, and D = double array. 141 */ 142 private char NT = ' '; 143 144 /** 145 * The Scalar Dataset. 146 */ 147 private Dataset dataset; 148 149 /** 150 * The value of the dataset. 151 */ 152 private Object dataValue; 153 154 /** 155 * The table used to hold the table data. 156 */ 157 private JTable table; 158 159 /** Label to indicate the current cell location. */ 160 private JLabel cellLabel; 161 162 /** Text field to display the value of of the current cell. */ 163 private JTextArea cellValueField; 164 165 private boolean isValueChanged; 166 167 private final Toolkit toolkit; 168 169 private boolean isReadOnly; 170 171 private boolean isDisplayTypeChar; 172 173 private boolean isDataTransposed; 174 175 private boolean isRegRef; 176 private boolean isObjRef; 177 178 private final JCheckBoxMenuItem checkFixedDataLength; 179 private int fixedDataLength; 180 private final JCheckBoxMenuItem checkCustomNotation; 181 private final JCheckBoxMenuItem checkScientificNotation; 182 private final JCheckBoxMenuItem checkHex; 183 private final JCheckBoxMenuItem checkBin; 184 185 // changed to use normalized scientific notation (1 <= coefficient < 10). 186 // private final DecimalFormat scientificFormat = new DecimalFormat("###.#####E0#"); 187 private final DecimalFormat scientificFormat = new DecimalFormat("0.0###E0###"); 188 private DecimalFormat customFormat = new DecimalFormat("###.#####"); 189 private final NumberFormat normalFormat = null; // NumberFormat.getInstance(); 190 private NumberFormat numberFormat = normalFormat; 191 private boolean showAsHex = false, showAsBin = false; 192 private final boolean startEditing[] = { false }; 193 private JPopupMenu popupMenu; 194 195 private enum ViewType { 196 TABLE, IMAGE, TEXT 197 } 198 199 private ViewType viewType; 200 201 private JTextField frameField; 202 203 private long curFrame = 0; 204 private long maxFrame = 1; 205 206 private Object fillValue = null; 207 208 private BitSet bitmask; 209 210 private BITMASK_OP bitmaskOP = BITMASK_OP.EXTRACT; 211 212 private int binaryOrder; 213 214 private int indexBase = 0; 215 216 private static final int FLOAT_BUFFER_SIZE = 524288; 217 218 private static final int INT_BUFFER_SIZE = 524288; 219 220 private static final int SHORT_BUFFER_SIZE = 1048576; 221 222 private static final int LONG_BUFFER_SIZE = 262144; 223 224 private static final int DOUBLE_BUFFER_SIZE = 262144; 225 226 private static final int BYTE_BUFFER_SIZE = 2097152; 227 228 /* the value of the current cell value in editing. */ 229 private Object currentEditingCellValue = null; 230 231 /** 232 * Constructs an TableView. 233 * <p> 234 * 235 * @param theView 236 * the main HDFView. 237 */ 238 public DefaultTableView(ViewManager theView) { 239 this(theView, null); 240 } 241 242 /** 243 * Constructs an TableView. 244 * <p> 245 * 246 * @param theView 247 * the main HDFView. 248 * @param map 249 * the properties on how to show the data. The map is used to allow applications to 250 * pass properties on how to display the data, such as, transposing data, showing 251 * data as character, applying bitmask, and etc. Predefined keys are listed at 252 * ViewProperties.DATA_VIEW_KEY. 253 */ 254 public DefaultTableView(ViewManager theView, HashMap map) { 255 super(); 256 257 setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); 258 log.trace("DefaultTableView start"); 259 260 viewer = theView; 261 toolkit = Toolkit.getDefaultToolkit(); 262 isValueChanged = false; 263 isReadOnly = false; 264 isRegRef = false; 265 isObjRef = false; 266 viewType = ViewType.TABLE; 267 fixedDataLength = -1; 268 HObject hobject = null; 269 popupMenu = null; 270 bitmask = null; 271 272 if (ViewProperties.isIndexBase1()) indexBase = 1; 273 log.trace("isIndexBase1() is {}", indexBase); 274 275 checkFixedDataLength = new JCheckBoxMenuItem("Fixed Data Length", false); 276 checkCustomNotation = new JCheckBoxMenuItem("Show Custom Notation", false); 277 checkScientificNotation = new JCheckBoxMenuItem("Show Scientific Notation", false); 278 checkHex = new JCheckBoxMenuItem("Show Hexadecimal", false); 279 checkBin = new JCheckBoxMenuItem("Show Binary", false); 280 281 if (map != null) { 282 hobject = (HObject) map.get(ViewProperties.DATA_VIEW_KEY.OBJECT); 283 284 bitmask = (BitSet) map.get(ViewProperties.DATA_VIEW_KEY.BITMASK); 285 bitmaskOP = (BITMASK_OP) map.get(ViewProperties.DATA_VIEW_KEY.BITMASKOP); 286 287 Boolean b = (Boolean) map.get(ViewProperties.DATA_VIEW_KEY.CHAR); 288 if (b != null) isDisplayTypeChar = b.booleanValue(); 289 290 b = (Boolean) map.get(ViewProperties.DATA_VIEW_KEY.TRANSPOSED); 291 if (b != null) isDataTransposed = b.booleanValue(); 292 293 b = (Boolean) map.get(ViewProperties.DATA_VIEW_KEY.INDEXBASE1); 294 if (b != null) { 295 if (b.booleanValue()) 296 indexBase = 1; 297 else 298 indexBase = 0; 299 } 300 } 301 log.trace("isIndexBase={} - isDataTransposed={} - isDisplayTypeChar={}", indexBase, isDataTransposed, isDisplayTypeChar); 302 303 if (hobject == null) hobject = viewer.getTreeView().getCurrentObject(); 304 305 if ((hobject == null) || !(hobject instanceof Dataset)) { 306 return; 307 } 308 309 dataset = (Dataset) hobject; 310 isReadOnly = dataset.getFileFormat().isReadOnly(); 311 log.trace("dataset({}) isReadOnly={}", dataset, isReadOnly); 312 313 long[] dims = dataset.getDims(); 314 long tsize = 1; 315 316 for (int i = 0; i < dims.length; i++) 317 tsize *= dims[i]; 318 319 log.trace("dataset size={} Height={} Width={}", tsize, dataset.getHeight(), dataset.getWidth()); 320 if (dataset.getHeight() <= 0 || dataset.getWidth() <= 0 || tsize <= 0) { 321 JOptionPane.showMessageDialog(this, "Could not open dataset '" + dataset.getName() + "'. Dataset has dimension of size 0."); 322 return; 323 } 324 325 // cannot edit hdf4 vdata 326 if (dataset.getFileFormat().isThisType(FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF4)) 327 && (dataset instanceof CompoundDS)) { 328 isReadOnly = true; 329 } 330 331 // disable edit feature for szip compression when encode is not enabled 332 if (!isReadOnly) { 333 String compression = dataset.getCompression(); 334 if ((compression != null) && compression.startsWith("SZIP")) { 335 if (!compression.endsWith("ENCODE_ENABLED")) { 336 isReadOnly = true; 337 } 338 } 339 } 340 341 Datatype dtype = dataset.getDatatype(); 342 log.trace("dataset dtype.getDatatypeClass()={}", dtype.getDatatypeClass()); 343 isDisplayTypeChar = (isDisplayTypeChar && (dtype.getDatatypeSize() == 1 || (dtype.getDatatypeClass() == Datatype.CLASS_ARRAY && dtype 344 .getBasetype().getDatatypeClass() == Datatype.CLASS_CHAR))); 345 346 log.trace("dataset isDisplayTypeChar={} isConvertEnum={}", isDisplayTypeChar, ViewProperties.isConvertEnum()); 347 dataset.setEnumConverted(ViewProperties.isConvertEnum()); 348 349 // set title & border 350 TitledBorder border = BorderFactory.createTitledBorder(BorderFactory.createLineBorder(Color.lightGray, 1), indexBase 351 + "-based", 352 TitledBorder.RIGHT, TitledBorder.TOP, this.getFont(), Color.black); 353 ((JPanel) getContentPane()).setBorder(border); 354 355 // create the table and its columnHeader 356 if (dataset instanceof CompoundDS) { 357 isDataTransposed = false; // disable transpose for compound dataset 358 this.setFrameIcon(ViewProperties.getTableIcon()); 359 table = createTable((CompoundDS) dataset); 360 } 361 else { /* if (dataset instanceof ScalarDS) */ 362 this.setFrameIcon(ViewProperties.getDatasetIcon()); 363 table = createTable((ScalarDS) dataset); 364 log.trace("createTable((ScalarDS) dataset) dtype.getDatatypeClass()={}", dtype.getDatatypeClass()); 365 366 if (dtype.getDatatypeClass() == Datatype.CLASS_REFERENCE) { 367 table.addMouseListener(this); 368 369 if (dtype.getDatatypeSize() > 8) { 370 isReadOnly = true; 371 isRegRef = true; 372 } 373 else 374 isObjRef = true; 375 } 376 else if ((dtype.getDatatypeClass() == Datatype.CLASS_BITFIELD) || (dtype.getDatatypeClass() == Datatype.CLASS_OPAQUE)) { 377 showAsHex = true; 378 checkHex.setSelected(true); 379 checkScientificNotation.setSelected(false); 380 checkCustomNotation.setSelected(false); 381 checkBin.setSelected(false); 382 showAsBin = false; 383 numberFormat = normalFormat; 384 } 385 log.trace("createTable((ScalarDS) dataset) isRegRef={} isObjRef={} showAsHex={}", isRegRef, isObjRef, showAsHex); 386 } 387 388 if (table == null) { 389 viewer.showStatus("Creating table failed - " + dataset.getName()); 390 dataset = null; 391 super.dispose(); 392 return; 393 } 394 table.setName("data"); 395 396 log.trace("DefaultTableView create ColumnHeader"); 397 ColumnHeader columnHeaders = new ColumnHeader(table); 398 columnHeaders.setName("columnHeaders"); 399 table.setTableHeader(columnHeaders); 400 table.setCellSelectionEnabled(true); 401 table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); 402 table.setGridColor(Color.gray); 403 404 // add the table to a scroller 405 JScrollPane scrollingTable = new JScrollPane(table); 406 scrollingTable.getVerticalScrollBar().setUnitIncrement(100); 407 scrollingTable.getHorizontalScrollBar().setUnitIncrement(100); 408 409 // create row headers and add it to the scroller 410 log.trace("DefaultTableView create RowHeader"); 411 RowHeader rowHeaders = new RowHeader(table, dataset); 412 rowHeaders.setName("rowHeaders"); 413 414 JViewport viewp = new JViewport(); 415 viewp.add(rowHeaders); 416 viewp.setPreferredSize(rowHeaders.getPreferredSize()); 417 scrollingTable.setRowHeader(viewp); 418 419 cellLabel = new JLabel(""); 420 cellLabel.setBorder(new EtchedBorder(EtchedBorder.LOWERED)); 421 Dimension dim = cellLabel.getPreferredSize(); 422 dim.width = 75; 423 cellLabel.setPreferredSize(dim); 424 cellLabel.setHorizontalAlignment(SwingConstants.RIGHT); 425 426 cellValueField = new JTextArea(); 427 cellValueField.setLineWrap(true); 428 cellValueField.setWrapStyleWord(true); 429 cellValueField.setEditable(false); 430 cellValueField.setBackground(new Color(255, 255, 240)); 431 432 JScrollPane scrollingcellValue = new JScrollPane(cellValueField); 433 scrollingcellValue.getVerticalScrollBar().setUnitIncrement(50); 434 scrollingcellValue.getHorizontalScrollBar().setUnitIncrement(50); 435 436 JPanel valuePane = new JPanel(); 437 valuePane.setLayout(new BorderLayout()); 438 valuePane.add(cellLabel, BorderLayout.WEST); 439 valuePane.add(scrollingcellValue, BorderLayout.CENTER); 440 441 JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, valuePane, scrollingTable); 442 splitPane.setDividerLocation(25); 443 JPanel contentPane = (JPanel) getContentPane(); 444 contentPane.add(splitPane); 445 446 StringBuffer sb = new StringBuffer(hobject.getName()); 447 sb.append(" at "); 448 sb.append(hobject.getPath()); 449 sb.append(" ["); 450 sb.append(dataset.getFileFormat().getName()); 451 sb.append(" in "); 452 sb.append(dataset.getFileFormat().getParent()); 453 sb.append("]"); 454 setTitle(sb.toString()); 455 456 // setup subset information 457 log.trace("DefaultTableView setup subset information"); 458 int rank = dataset.getRank(); 459 int[] selectedIndex = dataset.getSelectedIndex(); 460 long[] count = dataset.getSelectedDims(); 461 long[] stride = dataset.getStride(); 462 // long[] dims = dataset.getDims(); 463 long[] start = dataset.getStartDims(); 464 int n = Math.min(3, rank); 465 if (rank > 2) { 466 curFrame = start[selectedIndex[2]] + indexBase; 467 maxFrame = dims[selectedIndex[2]]; 468 } 469 470 sb.append(" [ dims"); 471 sb.append(selectedIndex[0]); 472 for (int i = 1; i < n; i++) { 473 sb.append("x"); 474 sb.append(selectedIndex[i]); 475 } 476 sb.append(", start"); 477 sb.append(start[selectedIndex[0]]); 478 for (int i = 1; i < n; i++) { 479 sb.append("x"); 480 sb.append(start[selectedIndex[i]]); 481 } 482 sb.append(", count"); 483 sb.append(count[selectedIndex[0]]); 484 for (int i = 1; i < n; i++) { 485 sb.append("x"); 486 sb.append(count[selectedIndex[i]]); 487 } 488 sb.append(", stride"); 489 sb.append(stride[selectedIndex[0]]); 490 for (int i = 1; i < n; i++) { 491 sb.append("x"); 492 sb.append(stride[selectedIndex[i]]); 493 } 494 sb.append(" ] "); 495 log.trace("DefaultTableView subset={}", sb.toString()); 496 497 setJMenuBar(createMenuBar()); 498 viewer.showStatus(sb.toString()); 499 500 // set cell height for large fonts 501 int cellRowHeight = table.getFontMetrics(table.getFont()).getHeight(); 502 rowHeaders.setRowHeight(cellRowHeight); 503 table.setRowHeight(cellRowHeight); 504 505 // create popup menu for reg. ref. 506 if (isRegRef || isObjRef) popupMenu = createPopupMenu(); 507 log.trace("DefaultTableView finish"); 508 } 509 510 private JMenuBar createMenuBar ( ) { 511 JMenuBar bar = new JMenuBar(); 512 JButton button; 513 boolean isEditable = !isReadOnly; 514 boolean is3D = (dataset.getRank() > 2); 515 516 JMenu menu = new JMenu("Table", false); 517 menu.setMnemonic('T'); 518 bar.add(menu); 519 520 JMenuItem item = new JMenuItem("Export Data to Text File"); 521 item.addActionListener(this); 522 item.setActionCommand("Save table as text"); 523 menu.add(item); 524 525 JMenu exportAsBinaryMenu = new JMenu("Export Data to Binary File"); 526 if ((dataset instanceof ScalarDS)) { 527 menu.add(exportAsBinaryMenu); 528 } 529 item = new JMenuItem("Native Order"); 530 item.addActionListener(this); 531 item.setActionCommand("Save table as binary Native Order"); 532 exportAsBinaryMenu.add(item); 533 item = new JMenuItem("Little Endian"); 534 item.addActionListener(this); 535 item.setActionCommand("Save table as binary Little Endian"); 536 exportAsBinaryMenu.add(item); 537 item = new JMenuItem("Big Endian"); 538 item.addActionListener(this); 539 item.setActionCommand("Save table as binary Big Endian"); 540 exportAsBinaryMenu.add(item); 541 542 menu.addSeparator(); 543 544 item = new JMenuItem("Import Data from Text File"); 545 item.addActionListener(this); 546 item.setActionCommand("Import data from file"); 547 item.setEnabled(isEditable); 548 menu.add(item); 549 550 item = checkFixedDataLength; 551 item.addActionListener(this); 552 item.setActionCommand("Fixed data length"); 553 if (dataset instanceof ScalarDS) { 554 menu.add(item); 555 } 556 557 JMenu importFromBinaryMenu = new JMenu("Import Data from Binary File"); 558 if ((dataset instanceof ScalarDS)) { 559 menu.add(importFromBinaryMenu); 560 } 561 item = new JMenuItem("Native Order"); 562 item.addActionListener(this); 563 item.setActionCommand("Order as Native Order"); 564 importFromBinaryMenu.add(item); 565 item = new JMenuItem("Little Endian"); 566 item.addActionListener(this); 567 item.setActionCommand("Order as Little Endian"); 568 importFromBinaryMenu.add(item); 569 item = new JMenuItem("Big Endian"); 570 item.addActionListener(this); 571 item.setActionCommand("Order as Big Endian"); 572 importFromBinaryMenu.add(item); 573 574 menu.addSeparator(); 575 576 item = new JMenuItem("Copy"); 577 item.addActionListener(this); 578 item.setActionCommand("Copy data"); 579 item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(), true)); 580 menu.add(item); 581 582 item = new JMenuItem("Paste"); 583 item.addActionListener(this); 584 item.setActionCommand("Paste data"); 585 item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_V, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(), true)); 586 item.setEnabled(isEditable); 587 menu.add(item); 588 589 menu.addSeparator(); 590 591 item = new JMenuItem("Copy to New Dataset"); 592 item.addActionListener(this); 593 item.setActionCommand("Write selection to dataset"); 594 item.setEnabled(isEditable && (dataset instanceof ScalarDS)); 595 menu.add(item); 596 597 item = new JMenuItem("Save Changes to File"); 598 item.addActionListener(this); 599 item.setActionCommand("Save dataset"); 600 item.setEnabled(isEditable); 601 item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_U, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(), true)); 602 menu.add(item); 603 604 menu.addSeparator(); 605 606 item = new JMenuItem("Select All"); 607 item.addActionListener(this); 608 item.setActionCommand("Select all data"); 609 item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_A, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(), true)); 610 menu.add(item); 611 612 menu.addSeparator(); 613 614 item = new JMenuItem("Show Lineplot"); 615 item.addActionListener(this); 616 item.setActionCommand("Show chart"); 617 menu.add(item); 618 619 item = new JMenuItem("Show Statistics"); 620 item.addActionListener(this); 621 item.setActionCommand("Show statistics"); 622 menu.add(item); 623 624 menu.addSeparator(); 625 626 item = new JMenuItem("Math Conversion"); 627 item.addActionListener(this); 628 item.setActionCommand("Math conversion"); 629 item.setEnabled(isEditable); 630 menu.add(item); 631 632 menu.addSeparator(); 633 634 item = checkScientificNotation; 635 item.addActionListener(this); 636 item.setActionCommand("Show scientific notation"); 637 if (dataset instanceof ScalarDS) { 638 menu.add(item); 639 } 640 641 item = checkCustomNotation; 642 item.addActionListener(this); 643 item.setActionCommand("Show custom notation"); 644 if (dataset instanceof ScalarDS) { 645 menu.add(item); 646 } 647 648 item = new JMenuItem("Create custom notation"); 649 item.addActionListener(this); 650 item.setActionCommand("Create custom notation"); 651 menu.add(item); 652 653 boolean isInt = (NT == 'B' || NT == 'S' || NT == 'I' || NT == 'J'); 654 // this will allow disabling of hex and binary display menu options 655 // boolean isUINT64 = (dataset.getDatatype().isUnsigned() && (NT == 'J')); 656 item = checkHex; 657 item.addActionListener(this); 658 item.setActionCommand("Show hexadecimal"); 659 if ((dataset instanceof ScalarDS) && isInt /* && !isUINT64 */) { 660 menu.add(item); 661 } 662 663 item = checkBin; 664 item.addActionListener(this); 665 item.setActionCommand("Show binary"); 666 if ((dataset instanceof ScalarDS) && isInt /* && !isUINT64 */) { 667 menu.add(item); 668 } 669 670 menu.addSeparator(); 671 672 item = new JMenuItem("Close"); 673 item.addActionListener(this); 674 item.setActionCommand("Close"); 675 menu.add(item); 676 677 bar.add(new JLabel(" ")); 678 679 // add icons to the menubar 680 681 Insets margin = new Insets(0, 2, 0, 2); 682 683 // chart button 684 button = new JButton(ViewProperties.getChartIcon()); 685 bar.add(button); 686 button.setToolTipText("Line Plot"); 687 button.setMargin(margin); 688 button.addActionListener(this); 689 button.setActionCommand("Show chart"); 690 691 if (is3D) { 692 bar.add(new JLabel(" ")); 693 694 // first button 695 button = new JButton(ViewProperties.getFirstIcon()); 696 bar.add(button); 697 button.setToolTipText("First"); 698 button.setMargin(margin); 699 button.setName("firstbutton"); 700 button.addActionListener(this); 701 button.setActionCommand("First page"); 702 703 // previous button 704 button = new JButton(ViewProperties.getPreviousIcon()); 705 bar.add(button); 706 button.setToolTipText("Previous"); 707 button.setMargin(margin); 708 button.setName("prevbutton"); 709 button.addActionListener(this); 710 button.setActionCommand("Previous page"); 711 712 frameField = new JTextField(String.valueOf(curFrame)); 713 frameField.setMaximumSize(new Dimension(50, 30)); 714 bar.add(frameField); 715 frameField.setMargin(margin); 716 frameField.setName("framenumber"); 717 frameField.addActionListener(this); 718 frameField.setActionCommand("Go to frame"); 719 720 JLabel tmpField = new JLabel(String.valueOf(maxFrame), SwingConstants.CENTER); 721 tmpField.setMaximumSize(new Dimension(50, 30)); 722 bar.add(tmpField); 723 724 // next button 725 button = new JButton(ViewProperties.getNextIcon()); 726 bar.add(button); 727 button.setToolTipText("Next"); 728 button.setMargin(margin); 729 button.setName("nextbutton"); 730 button.addActionListener(this); 731 button.setActionCommand("Next page"); 732 733 // last button 734 button = new JButton(ViewProperties.getLastIcon()); 735 bar.add(button); 736 button.setToolTipText("Last"); 737 button.setMargin(margin); 738 button.setName("lastbutton"); 739 button.addActionListener(this); 740 button.setActionCommand("Last page"); 741 } 742 743 return bar; 744 } 745 746 @Override 747 public void actionPerformed (ActionEvent e) { 748 try { 749 setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); 750 751 e.getSource(); 752 String cmd = e.getActionCommand(); 753 log.trace("DefaultTableView actionPerformed: {}", cmd); 754 755 if (cmd.equals("Close")) { 756 dispose(); // terminate the application 757 } 758 else if (cmd.equals("Save table as text")) { 759 try { 760 saveAsText(); 761 } 762 catch (Exception ex) { 763 toolkit.beep(); 764 JOptionPane.showMessageDialog((JFrame) viewer, ex, getTitle(), JOptionPane.ERROR_MESSAGE); 765 } 766 } 767 else if (cmd.startsWith("Save table as binary")) { 768 if (cmd.equals("Save table as binary Native Order")) binaryOrder = 1; 769 if (cmd.equals("Save table as binary Little Endian")) binaryOrder = 2; 770 if (cmd.equals("Save table as binary Big Endian")) binaryOrder = 3; 771 try { 772 saveAsBinary(); 773 } 774 catch (Exception ex) { 775 toolkit.beep(); 776 JOptionPane.showMessageDialog((JFrame) viewer, ex, getTitle(), JOptionPane.ERROR_MESSAGE); 777 } 778 } 779 else if (cmd.equals("Copy data")) { 780 copyData(); 781 } 782 else if (cmd.equals("Paste data")) { 783 pasteData(); 784 } 785 else if (cmd.equals("Import data from file")) { 786 String currentDir = dataset.getFileFormat().getParent(); 787 JFileChooser fchooser = new JFileChooser(currentDir); 788 fchooser.setFileFilter(DefaultFileFilter.getFileFilterText()); 789 int returnVal = fchooser.showOpenDialog(this); 790 791 if (returnVal != JFileChooser.APPROVE_OPTION) { 792 return; 793 } 794 795 File choosedFile = fchooser.getSelectedFile(); 796 if (choosedFile == null) { 797 return; 798 } 799 800 String txtFile = choosedFile.getAbsolutePath(); 801 importTextData(txtFile); 802 } 803 else if (cmd.startsWith("Order as")) { 804 if (cmd.equals("Order as Native Order")) binaryOrder = 1; 805 if (cmd.equals("Order as Little Endian")) binaryOrder = 2; 806 if (cmd.equals("Order as Big Endian")) binaryOrder = 3; 807 808 importBinaryData(); 809 } 810 else if (cmd.equals("Write selection to dataset")) { 811 JTable jtable = getTable(); 812 if ((jtable.getSelectedColumnCount() <= 0) || (jtable.getSelectedRowCount() <= 0)) { 813 JOptionPane.showMessageDialog(this, "Select table cells to write.", "HDFView", JOptionPane.INFORMATION_MESSAGE); 814 return; 815 } 816 817 TreeView treeView = viewer.getTreeView(); 818 TreeNode node = viewer.getTreeView().findTreeNode(dataset); 819 Group pGroup = (Group) ((DefaultMutableTreeNode) node.getParent()).getUserObject(); 820 TreeNode root = dataset.getFileFormat().getRootNode(); 821 822 if (root == null) { 823 return; 824 } 825 826 Vector<Object> list = new Vector<Object>(dataset.getFileFormat().getNumberOfMembers() + 5); 827 DefaultMutableTreeNode theNode = null; 828 Enumeration<?> local_enum = ((DefaultMutableTreeNode) root).depthFirstEnumeration(); 829 while (local_enum.hasMoreElements()) { 830 theNode = (DefaultMutableTreeNode) local_enum.nextElement(); 831 list.add(theNode.getUserObject()); 832 } 833 834 NewDatasetDialog dialog = new NewDatasetDialog((JFrame) viewer, pGroup, list, this); 835 dialog.setVisible(true); 836 837 HObject obj = (HObject) dialog.getObject(); 838 if (obj != null) { 839 Group pgroup = dialog.getParentGroup(); 840 try { 841 treeView.addObject(obj, pgroup); 842 } 843 catch (Exception ex) { 844 log.debug("Write selection to dataset:", ex); 845 } 846 } 847 848 list.setSize(0); 849 } 850 else if (cmd.equals("Save dataset")) { 851 try { 852 updateValueInFile(); 853 } 854 catch (Exception ex) { 855 toolkit.beep(); 856 JOptionPane.showMessageDialog((JFrame) viewer, ex, getTitle(), JOptionPane.ERROR_MESSAGE); 857 } 858 } 859 else if (cmd.equals("Select all data")) { 860 try { 861 selectAll(); 862 } 863 catch (Exception ex) { 864 toolkit.beep(); 865 JOptionPane.showMessageDialog((JFrame) viewer, ex, getTitle(), JOptionPane.ERROR_MESSAGE); 866 } 867 } 868 else if (cmd.equals("Show chart")) { 869 showLineplot(); 870 } 871 else if (cmd.equals("First page")) { 872 firstPage(); 873 } 874 else if (cmd.equals("Previous page")) { 875 previousPage(); 876 } 877 else if (cmd.equals("Next page")) { 878 nextPage(); 879 } 880 else if (cmd.equals("Last page")) { 881 lastPage(); 882 } 883 else if (cmd.equals("Show statistics")) { 884 try { 885 Object theData = null; 886 theData = getSelectedData(); 887 888 if (dataset instanceof CompoundDS) { 889 int cols = table.getSelectedColumnCount(); 890 if (cols != 1) { 891 JOptionPane.showMessageDialog(this, "Please select one colunm a time for compound dataset.", 892 getTitle(), JOptionPane.ERROR_MESSAGE); 893 return; 894 } 895 } 896 else if (theData == null) { 897 theData = dataValue; 898 } 899 900 double[] minmax = new double[2]; 901 double[] stat = new double[2]; 902 Tools.findMinMax(theData, minmax, fillValue); 903 if (Tools.computeStatistics(theData, stat, fillValue) > 0) { 904 String statistics = "Min = " + minmax[0] + "\nMax = " + minmax[1] 905 + "\nMean = " + stat[0] + "\nStandard deviation = " + stat[1]; 906 JOptionPane.showMessageDialog(this, statistics, "Statistics", JOptionPane.INFORMATION_MESSAGE); 907 } 908 909 theData = null; 910 System.gc(); 911 } 912 catch (Exception ex) { 913 toolkit.beep(); 914 JOptionPane.showMessageDialog((JFrame) viewer, ex, getTitle(), JOptionPane.ERROR_MESSAGE); 915 } 916 } 917 else if (cmd.equals("Math conversion")) { 918 try { 919 mathConversion(); 920 } 921 catch (Exception ex) { 922 toolkit.beep(); 923 JOptionPane.showMessageDialog((JFrame) viewer, ex, getTitle(), JOptionPane.ERROR_MESSAGE); 924 } 925 } 926 else if (cmd.startsWith("Go to frame")) { 927 int page = 0; 928 try { 929 page = Integer.parseInt(frameField.getText().trim()) - indexBase; 930 } 931 catch (Exception ex) { 932 page = -1; 933 } 934 935 gotoPage(page); 936 } 937 else if (cmd.equals("Show scientific notation")) { 938 if (checkScientificNotation.isSelected()) { 939 checkCustomNotation.setSelected(false); 940 numberFormat = scientificFormat; 941 checkHex.setSelected(false); 942 checkBin.setSelected(false); 943 showAsHex = false; 944 showAsBin = false; 945 } 946 else 947 numberFormat = normalFormat; 948 this.updateUI(); 949 } 950 else if (cmd.equals("Create custom notation")) { 951 String msg = "Create number format by pattern \nINTEGER . FRACTION E EXPONENT\nusing # for optional digits and 0 for required digits" 952 + "\nwhere, INTEGER: the pattern for the integer part" 953 + "\n FRACTION: the pattern for the fractional part" 954 + "\n EXPONENT: the pattern for the exponent part" 955 + "\n\nFor example, " 956 + "\n\t the normalized scientific notation format is \"#.0###E0##\"" 957 + "\n\t to make the digits required \"0.00000E000\"\n\n"; 958 String str = (String) JOptionPane.showInputDialog(this, msg, "Create a custom number format", 959 JOptionPane.PLAIN_MESSAGE, ViewProperties.getLargeHdfIcon(), null, null); 960 if ((str == null) || (str.length() < 1)) { 961 return; 962 } 963 964 customFormat.applyPattern(str); 965 966 } 967 else if (cmd.equals("Show custom notation")) { 968 if (checkCustomNotation.isSelected()) { 969 numberFormat = customFormat; 970 checkScientificNotation.setSelected(false); 971 checkHex.setSelected(false); 972 checkBin.setSelected(false); 973 showAsHex = false; 974 showAsBin = false; 975 } 976 else 977 numberFormat = normalFormat; 978 this.updateUI(); 979 } 980 else if (cmd.equals("Show hexadecimal")) { 981 showAsHex = checkHex.isSelected(); 982 if (showAsHex) { 983 checkScientificNotation.setSelected(false); 984 checkCustomNotation.setSelected(false); 985 checkBin.setSelected(false); 986 showAsBin = false; 987 numberFormat = normalFormat; 988 } 989 this.updateUI(); 990 } 991 else if (cmd.equals("Show binary")) { 992 showAsBin = checkBin.isSelected(); 993 if (showAsBin) { 994 checkScientificNotation.setSelected(false); 995 checkCustomNotation.setSelected(false); 996 checkHex.setSelected(false); 997 showAsHex = false; 998 numberFormat = normalFormat; 999 } 1000 this.updateUI(); 1001 } 1002 else if (cmd.equals("Fixed data length")) { 1003 if (!checkFixedDataLength.isSelected()) { 1004 fixedDataLength = -1; 1005 this.updateUI(); 1006 return; 1007 } 1008 1009 String str = JOptionPane 1010 .showInputDialog( 1011 this, 1012 "Enter fixed data length when importing text data\n\n" 1013 + "For example, for a text string of \"12345678\"\n\t\tenter 2, the data will be 12, 34, 56, 78\n\t\tenter 4, the data will be 1234, 5678\n", 1014 ""); 1015 1016 if ((str == null) || (str.length() < 1)) { 1017 checkFixedDataLength.setSelected(false); 1018 return; 1019 } 1020 1021 try { 1022 fixedDataLength = Integer.parseInt(str); 1023 } 1024 catch (Exception ex) { 1025 fixedDataLength = -1; 1026 } 1027 1028 if (fixedDataLength < 1) { 1029 checkFixedDataLength.setSelected(false); 1030 return; 1031 } 1032 } 1033 else if (cmd.startsWith("Show data as")) { 1034 log.trace("DefaultTableView actionPerformed: {}", cmd); 1035 // show data pointed by reg. ref. 1036 if (cmd.endsWith("table")) 1037 viewType = ViewType.TABLE; 1038 else if (cmd.endsWith("image")) 1039 viewType = ViewType.IMAGE; 1040 else 1041 viewType = ViewType.TABLE; 1042 log.trace("DefaultTableView actionPerformed: Show data as: {}", viewType); 1043 1044 Object theData = getSelectedData(); 1045 if (theData == null) { 1046 toolkit.beep(); 1047 JOptionPane.showMessageDialog(this, "No data selected.", getTitle(), JOptionPane.ERROR_MESSAGE); 1048 return; 1049 1050 } 1051 1052 int[] selectedRows = table.getSelectedRows(); 1053 int[] selectedCols = table.getSelectedColumns(); 1054 if (selectedRows == null || selectedRows.length <= 0) { 1055 log.trace("DefaultTableView actionPerformed: Show data as: selectedRows is empty"); 1056 return; 1057 } 1058 int len = Array.getLength(selectedRows) * Array.getLength(selectedCols); 1059 log.trace("DefaultTableView actionPerformed: Show data as: len={}", len); 1060 for (int i = 0; i < len; i++) { 1061 if (isRegRef) { 1062 log.trace("DefaultTableView actionPerformed: Show data[{}] as: isRegRef={}", i, isRegRef); 1063 showRegRefData((String) Array.get(theData, i)); 1064 } 1065 else if (isObjRef) { 1066 log.trace("DefaultTableView actionPerformed: Show data[{}] as: isObjRef={}", i, isObjRef); 1067 showObjRefData(Array.getLong(theData, i)); 1068 } 1069 } 1070 } 1071 } 1072 finally { 1073 setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); 1074 } 1075 } 1076 1077 // Implementing DataView. 1078 @Override 1079 public HObject getDataObject ( ) { 1080 return dataset; 1081 } 1082 1083 @Override 1084 public void dispose ( ) { 1085 if (isValueChanged && !isReadOnly) { 1086 int op = JOptionPane.showConfirmDialog(this, "\"" + dataset.getName() + "\" has changed.\n" 1087 + "Do you want to save the changes?", getTitle(), JOptionPane.YES_NO_OPTION); 1088 1089 if (op == JOptionPane.YES_OPTION) { 1090 updateValueInFile(); 1091 } 1092 else 1093 dataset.clearData(); // reload data 1094 1095 } 1096 1097 if (dataset instanceof ScalarDS) { 1098 ScalarDS sds = (ScalarDS) dataset; 1099 // reload the data when it is displayed next time 1100 // because the display type (table or image) may be 1101 // different. 1102 1103 if (sds.isImage()) { 1104 sds.clearData(); 1105 } 1106 1107 dataValue = null; 1108 table = null; 1109 } 1110 1111 viewer.removeDataView(this); 1112 1113 super.dispose(); 1114 } 1115 1116 // Implementing DataObserver. 1117 private void previousPage ( ) { 1118 int rank = dataset.getRank(); 1119 1120 if (rank < 3) { 1121 return; 1122 } 1123 1124 long[] start = dataset.getStartDims(); 1125 dataset.getDims(); 1126 int[] selectedIndex = dataset.getSelectedIndex(); 1127 long idx = start[selectedIndex[2]]; 1128 if (idx == 0) { 1129 return; // current page is the first page 1130 } 1131 1132 gotoPage(start[selectedIndex[2]] - 1); 1133 } 1134 1135 // Implementing DataObserver. 1136 private void nextPage ( ) { 1137 int rank = dataset.getRank(); 1138 1139 if (rank < 3) { 1140 return; 1141 } 1142 1143 long[] start = dataset.getStartDims(); 1144 int[] selectedIndex = dataset.getSelectedIndex(); 1145 long[] dims = dataset.getDims(); 1146 long idx = start[selectedIndex[2]]; 1147 if (idx == dims[selectedIndex[2]] - 1) { 1148 return; // current page is the last page 1149 } 1150 1151 gotoPage(start[selectedIndex[2]] + 1); 1152 } 1153 1154 // Implementing DataObserver. 1155 private void firstPage ( ) { 1156 int rank = dataset.getRank(); 1157 1158 if (rank < 3) { 1159 return; 1160 } 1161 1162 long[] start = dataset.getStartDims(); 1163 int[] selectedIndex = dataset.getSelectedIndex(); 1164 dataset.getDims(); 1165 long idx = start[selectedIndex[2]]; 1166 if (idx == 0) { 1167 return; // current page is the first page 1168 } 1169 1170 gotoPage(0); 1171 } 1172 1173 // Implementing DataObserver. 1174 private void lastPage ( ) { 1175 int rank = dataset.getRank(); 1176 1177 if (rank < 3) { 1178 return; 1179 } 1180 1181 long[] start = dataset.getStartDims(); 1182 int[] selectedIndex = dataset.getSelectedIndex(); 1183 long[] dims = dataset.getDims(); 1184 long idx = start[selectedIndex[2]]; 1185 if (idx == dims[selectedIndex[2]] - 1) { 1186 return; // current page is the last page 1187 } 1188 1189 gotoPage(dims[selectedIndex[2]] - 1); 1190 } 1191 1192 // Implementing TableObserver. 1193 @Override 1194 public JTable getTable ( ) { 1195 return table; 1196 } 1197 1198 // Implementing TableObserver. 1199 private void showLineplot ( ) { 1200 int[] rows = table.getSelectedRows(); 1201 int[] cols = table.getSelectedColumns(); 1202 1203 if ((rows == null) || (cols == null) || (rows.length <= 0) || (cols.length <= 0)) { 1204 toolkit.beep(); 1205 JOptionPane.showMessageDialog(this, "Select rows/columns to draw line plot.", getTitle(), JOptionPane.ERROR_MESSAGE); 1206 return; 1207 } 1208 1209 int nrow = table.getRowCount(); 1210 int ncol = table.getColumnCount(); 1211 1212 log.trace("DefaultTableView showLineplot: {} - {}", nrow, ncol); 1213 LineplotOption lpo = new LineplotOption((JFrame) viewer, "Line Plot Options -- " + dataset.getName(), nrow, ncol); 1214 lpo.setVisible(true); 1215 1216 int plotType = lpo.getPlotBy(); 1217 if (plotType == LineplotOption.NO_PLOT) { 1218 return; 1219 } 1220 1221 boolean isRowPlot = (plotType == LineplotOption.ROW_PLOT); 1222 int xIndex = lpo.getXindex(); 1223 1224 // figure out to plot data by row or by column 1225 // Plot data by rows if all columns are selected and part of 1226 // rows are selected, otherwise plot data by column 1227 double[][] data = null; 1228 int nLines = 0; 1229 String title = "Lineplot - " + dataset.getPath() + dataset.getName(); 1230 String[] lineLabels = null; 1231 double[] yRange = { Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY }; 1232 double xData[] = null; 1233 1234 if (isRowPlot) { 1235 title += " - by row"; 1236 nLines = rows.length; 1237 if (nLines > 10) { 1238 toolkit.beep(); 1239 nLines = 10; 1240 JOptionPane.showMessageDialog(this, "More than 10 rows are selected.\n" + "The first 10 rows will be displayed.", 1241 getTitle(), JOptionPane.WARNING_MESSAGE); 1242 } 1243 lineLabels = new String[nLines]; 1244 data = new double[nLines][cols.length]; 1245 1246 double value = 0.0; 1247 for (int i = 0; i < nLines; i++) { 1248 lineLabels[i] = String.valueOf(rows[i] + indexBase); 1249 for (int j = 0; j < cols.length; j++) { 1250 data[i][j] = 0; 1251 try { 1252 value = Double.parseDouble(table.getValueAt(rows[i], cols[j]).toString()); 1253 data[i][j] = value; 1254 yRange[0] = Math.min(yRange[0], value); 1255 yRange[1] = Math.max(yRange[1], value); 1256 } 1257 catch (NumberFormatException ex) { 1258 log.debug("rows[{}]:", i, ex); 1259 } 1260 } // for (int j = 0; j < ncols; j++) 1261 } // for (int i = 0; i < rows.length; i++) 1262 1263 if (xIndex >= 0) { 1264 xData = new double[cols.length]; 1265 for (int j = 0; j < cols.length; j++) { 1266 xData[j] = 0; 1267 try { 1268 value = Double.parseDouble(table.getValueAt(xIndex, cols[j]).toString()); 1269 xData[j] = value; 1270 } 1271 catch (NumberFormatException ex) { 1272 log.debug("xIndex of {}:", xIndex, ex); 1273 } 1274 } 1275 } 1276 } // if (isRowPlot) 1277 else { 1278 title += " - by column"; 1279 nLines = cols.length; 1280 if (nLines > 10) { 1281 toolkit.beep(); 1282 nLines = 10; 1283 JOptionPane.showMessageDialog(this, "More than 10 columns are selected.\n" 1284 + "The first 10 columns will be displayed.", getTitle(), JOptionPane.WARNING_MESSAGE); 1285 } 1286 lineLabels = new String[nLines]; 1287 data = new double[nLines][rows.length]; 1288 double value = 0.0; 1289 for (int j = 0; j < nLines; j++) { 1290 lineLabels[j] = table.getColumnName(cols[j] /* + indexBase */); 1291 for (int i = 0; i < rows.length; i++) { 1292 data[j][i] = 0; 1293 try { 1294 value = Double.parseDouble(table.getValueAt(rows[i], cols[j]).toString()); 1295 data[j][i] = value; 1296 yRange[0] = Math.min(yRange[0], value); 1297 yRange[1] = Math.max(yRange[1], value); 1298 } 1299 catch (NumberFormatException ex) { 1300 log.debug("cols[{}]:", j, ex); 1301 } 1302 } // for (int j=0; j<ncols; j++) 1303 } // for (int i=0; i<rows.length; i++) 1304 1305 if (xIndex >= 0) { 1306 xData = new double[rows.length]; 1307 for (int j = 0; j < rows.length; j++) { 1308 xData[j] = 0; 1309 try { 1310 value = Double.parseDouble(table.getValueAt(rows[j], xIndex).toString()); 1311 xData[j] = value; 1312 } 1313 catch (NumberFormatException ex) { 1314 log.debug("xIndex of {}:", xIndex, ex); 1315 } 1316 } 1317 } 1318 } // else 1319 1320 int n = removeInvalidPlotData(data, xData, yRange); 1321 if (n < data[0].length) { 1322 double[][] dataNew = new double[data.length][n]; 1323 for (int i = 0; i < data.length; i++) 1324 System.arraycopy(data[i], 0, dataNew[i], 0, n); 1325 1326 data = dataNew; 1327 1328 if (xData != null) { 1329 double[] xDataNew = new double[n]; 1330 System.arraycopy(xData, 0, xDataNew, 0, n); 1331 xData = xDataNew; 1332 } 1333 } 1334 1335 // allow to draw a flat line: all values are the same 1336 if (yRange[0] == yRange[1]) { 1337 yRange[1] += 1; 1338 yRange[0] -= 1; 1339 } 1340 else if (yRange[0] > yRange[1]) { 1341 toolkit.beep(); 1342 JOptionPane.showMessageDialog(this, 1343 "Cannot show line plot for the selected data. \n" + "Please check the data range: (" 1344 + yRange[0] + ", " + yRange[1] + ").", getTitle(), JOptionPane.ERROR_MESSAGE); 1345 data = null; 1346 return; 1347 } 1348 if (xData == null) { // use array index and length for x data range 1349 xData = new double[2]; 1350 xData[0] = indexBase; // 1- or zero-based 1351 xData[1] = data[0].length + indexBase - 1; // maximum index 1352 } 1353 1354 Chart cv = new Chart((JFrame) viewer, title, Chart.LINEPLOT, data, xData, yRange); 1355 cv.setLineLabels(lineLabels); 1356 1357 String cname = dataValue.getClass().getName(); 1358 char dname = cname.charAt(cname.lastIndexOf("[") + 1); 1359 if ((dname == 'B') || (dname == 'S') || (dname == 'I') || (dname == 'J')) { 1360 cv.setTypeToInteger(); 1361 } 1362 1363 cv.setVisible(true); 1364 } 1365 1366 /** 1367 * Remove values of NaN, INF from the array. 1368 * 1369 * @param data 1370 * the data array 1371 * @param xData 1372 * the x-axis data points 1373 * @param yRange 1374 * the range of data values 1375 * @return number of data points in the plot data if successful; otherwise, returns false. 1376 */ 1377 private int removeInvalidPlotData (double[][] data, double[] xData, double[] yRange) { 1378 int idx = 0; 1379 boolean hasInvalid = false; 1380 1381 if (data == null || yRange == null) return -1; 1382 1383 yRange[0] = Double.POSITIVE_INFINITY; 1384 yRange[1] = Double.NEGATIVE_INFINITY; 1385 1386 for (int i = 0; i < data[0].length; i++) { 1387 hasInvalid = false; 1388 1389 for (int j = 0; j < data.length; j++) { 1390 hasInvalid = Tools.isNaNINF(data[j][i]); 1391 if (xData != null) hasInvalid = hasInvalid || Tools.isNaNINF(xData[i]); 1392 1393 if (hasInvalid) 1394 break; 1395 else { 1396 data[j][idx] = data[j][i]; 1397 if (xData != null) xData[idx] = xData[i]; 1398 yRange[0] = Math.min(yRange[0], data[j][idx]); 1399 yRange[1] = Math.max(yRange[1], data[j][idx]); 1400 } 1401 } 1402 1403 if (!hasInvalid) idx++; 1404 } 1405 1406 return idx; 1407 } 1408 1409 /** 1410 * Returns the selected data values. 1411 */ 1412 @Override 1413 public Object getSelectedData ( ) { 1414 if (dataset instanceof CompoundDS) { 1415 return getSelectedCompoundData(); 1416 } 1417 else { 1418 return getSelectedScalarData(); 1419 } 1420 } 1421 1422 /** 1423 * Returns the selected data values. 1424 */ 1425 private Object getSelectedScalarData ( ) { 1426 Object selectedData = null; 1427 1428 int[] selectedRows = table.getSelectedRows(); 1429 int[] selectedCols = table.getSelectedColumns(); 1430 if (selectedRows == null || selectedRows.length <= 0 || selectedCols == null || selectedCols.length <= 0) { 1431 return null; 1432 } 1433 1434 int size = selectedCols.length * selectedRows.length; 1435 log.trace("DefaultTableView getSelectedScalarData: {}", size); 1436 1437 // the whole table is selected 1438 if ((table.getColumnCount() == selectedCols.length) && (table.getRowCount() == selectedRows.length)) { 1439 return dataValue; 1440 } 1441 1442 selectedData = null; 1443 if (isRegRef) { 1444 // reg. ref data are stored in strings 1445 selectedData = new String[size]; 1446 } 1447 else { 1448 switch (NT) { 1449 case 'B': 1450 selectedData = new byte[size]; 1451 break; 1452 case 'S': 1453 selectedData = new short[size]; 1454 break; 1455 case 'I': 1456 selectedData = new int[size]; 1457 break; 1458 case 'J': 1459 selectedData = new long[size]; 1460 break; 1461 case 'F': 1462 selectedData = new float[size]; 1463 break; 1464 case 'D': 1465 selectedData = new double[size]; 1466 break; 1467 default: 1468 selectedData = null; 1469 break; 1470 } 1471 } 1472 1473 if (selectedData == null) { 1474 toolkit.beep(); 1475 JOptionPane.showMessageDialog(this, "Unsupported data type.", getTitle(), JOptionPane.ERROR_MESSAGE); 1476 return null; 1477 } 1478 log.trace("DefaultTableView getSelectedScalarData: selectedData is type {}", NT); 1479 1480 table.getSelectedRow(); 1481 table.getSelectedColumn(); 1482 int w = table.getColumnCount(); 1483 log.trace("DefaultTableView getSelectedScalarData: getColumnCount={}", w); 1484 int idx_src = 0; 1485 int idx_dst = 0; 1486 log.trace("DefaultTableView getSelectedScalarData: Rows.length={} Cols.length={}", selectedRows.length, selectedCols.length); 1487 for (int i = 0; i < selectedRows.length; i++) { 1488 for (int j = 0; j < selectedCols.length; j++) { 1489 idx_src = selectedRows[i] * w + selectedCols[j]; 1490 log.trace("DefaultTableView getSelectedScalarData[{},{}]: dataValue[{}]={} from r{} and c{}", i, j, idx_src, 1491 Array.get(dataValue, idx_src), selectedRows[i], selectedCols[j]); 1492 Array.set(selectedData, idx_dst, Array.get(dataValue, idx_src)); 1493 log.trace("DefaultTableView getSelectedScalarData[{},{}]: selectedData[{}]={}", i, j, idx_dst, 1494 Array.get(selectedData, idx_dst)); 1495 idx_dst++; 1496 } 1497 } 1498 1499 // this only works for continuous cells 1500 // for (int i = 0; i < rows; i++) { 1501 // idx_src = (r0 + i) * w + c0; 1502 // System.arraycopy(dataValue, idx_src, selectedData, idx_dst, cols); 1503 // idx_dst += cols; 1504 // } 1505 1506 return selectedData; 1507 } 1508 1509 /** 1510 * Returns the selected data values. 1511 */ 1512 private Object getSelectedCompoundData ( ) { 1513 Object selectedData = null; 1514 1515 int cols = table.getSelectedColumnCount(); 1516 int rows = table.getSelectedRowCount(); 1517 1518 if ((cols <= 0) || (rows <= 0)) { 1519 toolkit.beep(); 1520 JOptionPane.showMessageDialog(this, "No data is selected.", getTitle(), JOptionPane.ERROR_MESSAGE); 1521 return null; 1522 } 1523 1524 Object colData = null; 1525 try { 1526 colData = ((List<?>) dataset.getData()).get(table.getSelectedColumn()); 1527 } 1528 catch (Exception ex) { 1529 log.debug("colData:", ex); 1530 return null; 1531 } 1532 1533 int size = Array.getLength(colData); 1534 String cName = colData.getClass().getName(); 1535 int cIndex = cName.lastIndexOf("["); 1536 char nt = ' '; 1537 if (cIndex >= 0) { 1538 nt = cName.charAt(cIndex + 1); 1539 } 1540 log.trace("DefaultTableView getSelectedCompoundData: size={} cName={} nt={}", size, cName, nt); 1541 1542 if (nt == 'B') { 1543 selectedData = new byte[size]; 1544 } 1545 else if (nt == 'S') { 1546 selectedData = new short[size]; 1547 } 1548 else if (nt == 'I') { 1549 selectedData = new int[size]; 1550 } 1551 else if (nt == 'J') { 1552 selectedData = new long[size]; 1553 } 1554 else if (nt == 'F') { 1555 selectedData = new float[size]; 1556 } 1557 else if (nt == 'D') { 1558 selectedData = new double[size]; 1559 } 1560 else { 1561 toolkit.beep(); 1562 JOptionPane.showMessageDialog(this, "Unsupported data type.", getTitle(), JOptionPane.ERROR_MESSAGE); 1563 return null; 1564 } 1565 log.trace("DefaultTableView getSelectedCompoundData: selectedData={}", selectedData); 1566 1567 System.arraycopy(colData, 0, selectedData, 0, size); 1568 1569 return selectedData; 1570 } 1571 1572 /** 1573 * Creates a JTable to hold a scalar dataset. 1574 */ 1575 private JTable createTable (ScalarDS d) { 1576 JTable theTable = null; 1577 int rows = 0; 1578 int cols = 0; 1579 1580 log.trace("createTable: ScalarDS start"); 1581 int rank = d.getRank(); 1582 if (rank <= 0) { 1583 try { 1584 d.init(); 1585 log.trace("createTable: d.inited"); 1586 } 1587 catch (Exception ex) { 1588 JOptionPane.showMessageDialog(this, ex, "createTable:" + getTitle(), JOptionPane.ERROR_MESSAGE); 1589 dataValue = null; 1590 return null; 1591 } 1592 1593 rank = d.getRank(); 1594 } 1595 long[] dims = d.getSelectedDims(); 1596 log.trace("createTable dims={}", dims); 1597 1598 rows = (int) dims[0]; 1599 cols = 1; 1600 if (rank > 1) { 1601 rows = d.getHeight(); 1602 cols = d.getWidth(); 1603 } 1604 1605 log.trace("createTable: rows={} : cols={}", rows, cols); 1606 dataValue = null; 1607 try { 1608 dataValue = d.getData(); 1609 if (dataValue == null) { 1610 JOptionPane.showMessageDialog(this, "No data read", "ScalarDS createTable:" + getTitle(), 1611 JOptionPane.WARNING_MESSAGE); 1612 return null; 1613 } 1614 1615 log.trace("createTable: dataValue={}", dataValue); 1616 if (Tools.applyBitmask(dataValue, bitmask, bitmaskOP)) { 1617 isReadOnly = true; 1618 String opName = "Bits "; 1619 1620 if (bitmaskOP == ViewProperties.BITMASK_OP.AND) opName = "Bitwise AND "; 1621 1622 JPanel contentpane = (JPanel) getContentPane(); 1623 Border border = contentpane.getBorder(); 1624 1625 String btitle = ((TitledBorder) border).getTitle(); 1626 btitle += ", " + opName + bitmask; 1627 ((TitledBorder) border).setTitle(btitle); 1628 } 1629 1630 d.convertFromUnsignedC(); 1631 dataValue = d.getData(); 1632 1633 if (Array.getLength(dataValue) <= rows) cols = 1; 1634 } 1635 catch (Throwable ex) { 1636 JOptionPane.showMessageDialog(this, ex, "ScalarDS createTable:" + getTitle(), JOptionPane.ERROR_MESSAGE); 1637 dataValue = null; 1638 } 1639 1640 if (dataValue == null) { 1641 return null; 1642 } 1643 1644 fillValue = d.getFillValue(); 1645 log.trace("createTable: fillValue={}", fillValue); 1646 1647 String cName = dataValue.getClass().getName(); 1648 int cIndex = cName.lastIndexOf("["); 1649 if (cIndex >= 0) { 1650 NT = cName.charAt(cIndex + 1); 1651 } 1652 log.trace("createTable: cName={} NT={}", cName, NT); 1653 1654 // convert numerical data into char 1655 // only possible cases are byte[] and short[] (converted from unsigned 1656 // byte) 1657 if (isDisplayTypeChar && ((NT == 'B') || (NT == 'S'))) { 1658 int n = Array.getLength(dataValue); 1659 char[] charData = new char[n]; 1660 for (int i = 0; i < n; i++) { 1661 if (NT == 'B') { 1662 charData[i] = (char) Array.getByte(dataValue, i); 1663 } 1664 else if (NT == 'S') { 1665 charData[i] = (char) Array.getShort(dataValue, i); 1666 } 1667 } 1668 1669 dataValue = charData; 1670 } 1671 else if ((NT == 'B') && dataset.getDatatype().getDatatypeClass() == Datatype.CLASS_ARRAY) { 1672 Datatype baseType = dataset.getDatatype().getBasetype(); 1673 if (baseType.getDatatypeClass() == Datatype.CLASS_STRING) { 1674 dataValue = Dataset.byteToString((byte[]) dataValue, baseType.getDatatypeSize()); 1675 } 1676 } 1677 1678 final String columnNames[] = new String[cols]; 1679 final int rowCount = rows; 1680 final int colCount = cols; 1681 final long[] startArray = dataset.getStartDims(); 1682 final long[] strideArray = dataset.getStride(); 1683 int[] selectedIndex = dataset.getSelectedIndex(); 1684 final int rowStart = (int) startArray[selectedIndex[0]]; 1685 final int rowStride = (int) strideArray[selectedIndex[0]]; 1686 int start = 0; 1687 int stride = 1; 1688 1689 if (rank > 1) { 1690 start = (int) startArray[selectedIndex[1]]; 1691 stride = (int) strideArray[selectedIndex[1]]; 1692 1693 for (int i = 0; i < cols; i++) { 1694 columnNames[i] = String.valueOf(start + indexBase + i * stride); 1695 } 1696 } 1697 else { 1698 columnNames[0] = " "; 1699 } 1700 1701 AbstractTableModel tm = new AbstractTableModel() { 1702 private static final long serialVersionUID = 254175303655079056L; 1703 private final StringBuffer stringBuffer = new StringBuffer(); 1704 private final Datatype dtype = dataset.getDatatype(); 1705 private final Datatype btype = dtype.getBasetype(); 1706 private final int typeSize = dtype.getDatatypeSize(); 1707 private final boolean isArray = (dtype.getDatatypeClass() == Datatype.CLASS_ARRAY); 1708 private final boolean isStr = (NT == 'L'); 1709 private final boolean isInt = (NT == 'B' || NT == 'S' || NT == 'I' || NT == 'J'); 1710 private final boolean isUINT64 = (dtype.isUnsigned() && (NT == 'J')); 1711 private Object theValue; 1712 1713 boolean isNaturalOrder = (dataset.getRank() == 1 || (dataset.getSelectedIndex()[0] < dataset 1714 .getSelectedIndex()[1])); 1715 1716 @Override 1717 public int getColumnCount ( ) { 1718 return columnNames.length; 1719 } 1720 1721 @Override 1722 public int getRowCount ( ) { 1723 return rowCount; 1724 } 1725 1726 @Override 1727 public String getColumnName (int col) { 1728 return columnNames[col]; 1729 } 1730 1731 @Override 1732 public Object getValueAt (int row, int column) { 1733 if (startEditing[0]) return ""; 1734 log.trace("ScalarDS:createTable:AbstractTableModel:getValueAt({},{}) start", row, column); 1735 log.trace("ScalarDS:createTable:AbstractTableModel:getValueAt isInt={} isArray={} showAsHex={} showAsBin={}", 1736 isInt, isArray, showAsHex, showAsBin); 1737 1738 if (isArray) { 1739 // ARRAY dataset 1740 log.trace("ScalarDS:createTable:AbstractTableModel:getValueAt({},{}) ARRAY", row, column); 1741 1742 stringBuffer.setLength(0); // clear the old string 1743 1744 if (dtype instanceof H5Datatype) { 1745 // Since variable-length strings have no datatype size, 1746 // just directly append the data to the string buffer 1747 if (((H5Datatype) dtype).isVLEN() && dtype.getBasetype().getDatatypeClass() == Datatype.CLASS_STRING) { 1748 stringBuffer.append(Array.get(dataValue, 0)); 1749 for (int i = 0; i < dtype.getArrayDims()[0]; i++) { 1750 if (i > 0) stringBuffer.append(", "); 1751 stringBuffer.append(Array.get(dataValue, i)); 1752 } 1753 return stringBuffer; 1754 } 1755 } 1756 1757 int arraySize = dtype.getDatatypeSize() / btype.getDatatypeSize(); 1758 log.trace( 1759 "ScalarDS:createTable:AbstractTableModel:getValueAt ARRAY dataset size={} isDisplayTypeChar={} isUINT64={}", 1760 arraySize, isDisplayTypeChar, isUINT64); 1761 1762 int i0 = (row * colCount + column) * arraySize; 1763 int i1 = i0 + arraySize; 1764 1765 if (isDisplayTypeChar) { 1766 for (int i = i0; i < i1; i++) { 1767 stringBuffer.append(Array.getChar(dataValue, i)); 1768 if (stringBuffer.length() > 0 && i < (i1 - 1)) stringBuffer.append(", "); 1769 } 1770 } 1771 else { 1772 if (isUINT64) { 1773 log.trace("ScalarDS:createTable:AbstractTableModel:getValueAt({},{}) ARRAY of unsigned longs", row, column); 1774 // array of unsigned longs 1775 for (int i = i0; i < i1; i++) { 1776 Long l = (Long) Array.get(dataValue, i); 1777 BigInteger big; 1778 if (l < 0) { 1779 l = (l << 1) >>> 1; 1780 BigInteger big1 = new BigInteger("9223372036854775808"); // 2^65 1781 BigInteger big2 = new BigInteger(l.toString()); 1782 big = big1.add(big2); 1783 } 1784 else { 1785 big = new BigInteger(l.toString()); 1786 } 1787 if (showAsHex) 1788 theValue = Tools.toHexString(big.longValue(), 8); 1789 else if (showAsBin) 1790 theValue = Tools.toBinaryString(big.longValue(), 8); 1791 else 1792 theValue = big.toString(10); 1793 1794 stringBuffer.append(theValue); 1795 if (stringBuffer.length() > 0 && i < (i1 - 1)) stringBuffer.append(", "); 1796 } 1797 } 1798 else { 1799 log.trace("ScalarDS:createTable:AbstractTableModel:getValueAt({},{}) ARRAY not unsigned longs", row, column); 1800 for (int i = i0; i < i1; i++) { 1801 theValue = Array.get(dataValue, i); 1802 log.trace("ScalarDS:createTable:AbstractTableModel:getValueAt({},{}) ARRAY[{}]={}", row, column, i, theValue); 1803 if (showAsHex) 1804 theValue = Tools.toHexString(Long.valueOf(theValue.toString()), typeSize / arraySize); 1805 else if (showAsBin) 1806 theValue = Tools.toBinaryString(Long.valueOf(theValue.toString()), typeSize / arraySize); 1807 else 1808 theValue = theValue.toString(); 1809 1810 stringBuffer.append(theValue); 1811 1812 if (stringBuffer.length() > 0 && i < (i1 - 1)) 1813 stringBuffer.append(", "); 1814 } 1815 } 1816 } 1817 theValue = stringBuffer; 1818 } 1819 else { 1820 // not an array 1821 int index = column * rowCount + row; 1822 1823 if (dataset.getRank() > 1) { 1824 log.trace( 1825 "ScalarDS:createTable:AbstractTableModel:getValueAt rank={} isDataTransposed={} isNaturalOrder={}", 1826 dataset.getRank(), isDataTransposed, isNaturalOrder); 1827 if (isDataTransposed && isNaturalOrder) 1828 index = column * rowCount + row; 1829 else if (!isDataTransposed && !isNaturalOrder) 1830 // Reshape Data 1831 index = row * colCount + column; 1832 else if (isDataTransposed && !isNaturalOrder) 1833 // Transpose Data 1834 index = column * rowCount + row; 1835 else 1836 index = row * colCount + column; 1837 } 1838 log.trace("ScalarDS:createTable:AbstractTableModel:getValueAt index={} isStr={} isUINT64={}", index, isStr, 1839 isUINT64); 1840 1841 if (isStr) { 1842 theValue = Array.get(dataValue, index); 1843 return theValue; 1844 } 1845 1846 if (isUINT64) { 1847 theValue = Array.get(dataValue, index); 1848 Long l = (Long) theValue; 1849 BigInteger big; 1850 if (l < 0) { 1851 l = (l << 1) >>> 1; 1852 BigInteger big1 = new BigInteger("9223372036854775808"); // 2^65 1853 BigInteger big2 = new BigInteger(l.toString()); 1854 big = big1.add(big2); 1855 } 1856 else { 1857 big = new BigInteger(l.toString()); 1858 } 1859 if (showAsHex) 1860 theValue = Tools.toHexString(big.longValue(), 8);// big.toString(16); 1861 else if (showAsBin) 1862 theValue = Tools.toBinaryString(big.longValue(), 8); 1863 else 1864 theValue = big.toString(10); 1865 } 1866 else if (showAsHex && isInt) { 1867 // show in Hexadecimal 1868 theValue = Array.get(dataValue, index); 1869 theValue = Tools.toHexString(Long.valueOf(theValue.toString()), typeSize); 1870 } 1871 else if (showAsBin && isInt) { 1872 theValue = Array.get(dataValue, index); 1873 theValue = Tools.toBinaryString(Long.valueOf(theValue.toString()), typeSize); 1874 } 1875 else if (numberFormat != null) { 1876 // show in scientific format 1877 theValue = Array.get(dataValue, index); 1878 theValue = numberFormat.format(theValue); 1879 } 1880 else { 1881 theValue = Array.get(dataValue, index); 1882 } 1883 } 1884 1885 log.trace("ScalarDS:createTable:AbstractTableModel:getValueAt finish"); 1886 return theValue; 1887 } // getValueAt(int row, int column) 1888 }; 1889 1890 theTable = new JTable(tm) { 1891 private static final long serialVersionUID = -145476220959400488L; 1892 private final Datatype dtype = dataset.getDatatype(); 1893 private final boolean isArray = (dtype.getDatatypeClass() == Datatype.CLASS_ARRAY); 1894 1895 @Override 1896 public boolean isCellEditable (int row, int col) { 1897 if (isReadOnly || isDisplayTypeChar || isArray || showAsBin || showAsHex) { 1898 return false; 1899 } 1900 else { 1901 return true; 1902 } 1903 } 1904 1905 @Override 1906 public boolean editCellAt (int row, int column, java.util.EventObject e) { 1907 if (!isCellEditable(row, column)) { 1908 return super.editCellAt(row, column, e); 1909 } 1910 1911 if (e instanceof KeyEvent) { 1912 KeyEvent ke = (KeyEvent) e; 1913 if (ke.getID() == KeyEvent.KEY_PRESSED) { 1914 startEditing[0] = true; 1915 } 1916 } 1917 else if (e instanceof MouseEvent) { 1918 MouseEvent me = (MouseEvent) e; 1919 int mc = me.getClickCount(); 1920 if (mc > 1) { 1921 currentEditingCellValue = getValueAt(row, column); 1922 } 1923 } 1924 1925 return super.editCellAt(row, column, e); 1926 } 1927 1928 @Override 1929 public void editingStopped (ChangeEvent e) { 1930 int row = getEditingRow(); 1931 int col = getEditingColumn(); 1932 super.editingStopped(e); 1933 startEditing[0] = false; 1934 1935 Object source = e.getSource(); 1936 1937 if (source instanceof CellEditor) { 1938 CellEditor editor = (CellEditor) source; 1939 String cellValue = (String) editor.getCellEditorValue(); 1940 1941 try { 1942 updateValueInMemory(cellValue, row, col); 1943 } 1944 catch (Exception ex) { 1945 toolkit.beep(); 1946 JOptionPane.showMessageDialog(this, ex, getTitle(), JOptionPane.ERROR_MESSAGE); 1947 } 1948 } // if (source instanceof CellEditor) 1949 } 1950 1951 @Override 1952 public boolean isCellSelected (int row, int column) { 1953 if ((getSelectedRow() == row) && (getSelectedColumn() == column)) { 1954 cellLabel.setText(String.valueOf(rowStart + indexBase + row * rowStride) + ", " + table.getColumnName(column) 1955 + " = "); 1956 1957 log.trace("JTable.ScalarDS isCellSelected isRegRef={} isObjRef={}", isRegRef, isObjRef); 1958 Object val = getValueAt(row, column); 1959 String strVal = null; 1960 1961 if (isRegRef) { 1962 boolean displayValues = ViewProperties.showRegRefValues(); 1963 log.trace("JTable.ScalarDS isCellSelected displayValues={}", displayValues); 1964 if (displayValues && val != null && ((String) val).compareTo("NULL") != 0) { 1965 String reg = (String) val; 1966 boolean isPointSelection = (reg.indexOf('-') <= 0); 1967 1968 // find the object location 1969 String oidStr = reg.substring(reg.indexOf('/'), reg.indexOf(' ')); 1970 log.trace("JTable.ScalarDS isCellSelected: isPointSelection={} oidStr={}", isPointSelection, oidStr); 1971 1972 // decode the region selection 1973 String regStr = reg.substring(reg.indexOf('{') + 1, reg.indexOf('}')); 1974 if (regStr == null || regStr.length() <= 0) { // no 1975 // selection 1976 strVal = null; 1977 } 1978 else { 1979 reg.substring(reg.indexOf('}') + 1); 1980 1981 StringTokenizer st = new StringTokenizer(regStr); 1982 int nSelections = st.countTokens(); 1983 if (nSelections <= 0) { // no selection 1984 strVal = null; 1985 } 1986 else { 1987 log.trace("JTable.ScalarDS isCellSelected: nSelections={}", nSelections); 1988 1989 HObject obj = FileFormat.findObject(dataset.getFileFormat(), oidStr); 1990 if (obj == null || !(obj instanceof ScalarDS)) { // no 1991 // selection 1992 strVal = null; 1993 } 1994 else { 1995 ScalarDS dset = (ScalarDS) obj; 1996 try { 1997 dset.init(); 1998 } 1999 catch (Exception ex) { 2000 log.debug("reference dset did not init()", ex); 2001 } 2002 StringBuffer selectionSB = new StringBuffer(); 2003 StringBuffer strvalSB = new StringBuffer(); 2004 2005 int idx = 0; 2006 while (st.hasMoreTokens()) { 2007 log.trace("JTable.ScalarDS isCellSelected: st.hasMoreTokens() begin"); 2008 2009 int rank = dset.getRank(); 2010 long start[] = dset.getStartDims(); 2011 long count[] = dset.getSelectedDims(); 2012 // long count[] = new long[rank]; 2013 2014 // set the selected dimension sizes 2015 // based on the region selection 2016 // info. 2017 String sizeStr = null; 2018 String token = st.nextToken(); 2019 2020 selectionSB.setLength(0); 2021 selectionSB.append(token); 2022 log.trace("JTable.ScalarDS isCellSelected: selectionSB={}", selectionSB); 2023 2024 token = token.replace('(', ' '); 2025 token = token.replace(')', ' '); 2026 if (isPointSelection) { 2027 // point selection 2028 String[] tmp = token.split(","); 2029 for (int x = 0; x < tmp.length; x++) { 2030 count[x] = 1; 2031 sizeStr = tmp[x].trim(); 2032 start[x] = Long.valueOf(sizeStr); 2033 log.trace("JTable.ScalarDS isCellSelected: point sel={}", tmp[x]); 2034 } 2035 } 2036 else { 2037 // rectangle selection 2038 String startStr = token.substring(0, token.indexOf('-')); 2039 String endStr = token.substring(token.indexOf('-') + 1); 2040 log.trace("JTable.ScalarDS isCellSelected: rect sel with startStr={} endStr={}", 2041 startStr, endStr); 2042 String[] tmp = startStr.split(","); 2043 log.trace("JTable.ScalarDS isCellSelected: tmp with length={} rank={}", tmp.length, 2044 rank); 2045 for (int x = 0; x < tmp.length; x++) { 2046 sizeStr = tmp[x].trim(); 2047 start[x] = Long.valueOf(sizeStr); 2048 log.trace("JTable.ScalarDS isCellSelected: rect start={}", tmp[x]); 2049 } 2050 tmp = endStr.split(","); 2051 for (int x = 0; x < tmp.length; x++) { 2052 sizeStr = tmp[x].trim(); 2053 count[x] = Long.valueOf(sizeStr) - start[x] + 1; 2054 log.trace("JTable.ScalarDS isCellSelected: rect end={} count={}", tmp[x], 2055 count[x]); 2056 } 2057 } 2058 log.trace("JTable.ScalarDS isCellSelected: selection inited"); 2059 2060 Object dbuf = null; 2061 try { 2062 dbuf = dset.getData(); 2063 } 2064 catch (Exception ex) { 2065 JOptionPane.showMessageDialog(this, ex, "Region Reference:" + getTitle(), 2066 JOptionPane.ERROR_MESSAGE); 2067 } 2068 2069 // Convert dbuf to a displayable 2070 // string 2071 String cName = dbuf.getClass().getName(); 2072 int cIndex = cName.lastIndexOf("["); 2073 if (cIndex >= 0) { 2074 NT = cName.charAt(cIndex + 1); 2075 } 2076 log.trace("JTable.ScalarDS isCellSelected: cName={} NT={}", cName, NT); 2077 2078 if (idx > 0) strvalSB.append(','); 2079 2080 // convert numerical data into char 2081 // only possible cases are byte[] 2082 // and short[] (converted from 2083 // unsigned 2084 // byte) 2085 Datatype dtype = dset.getDatatype(); 2086 Datatype baseType = dtype.getBasetype(); 2087 log.trace("JTable.ScalarDS isCellSelected: dtype={} baseType={}", 2088 dtype.getDatatypeDescription(), baseType); 2089 if (baseType == null) baseType = dtype; 2090 if ((dtype.getDatatypeClass() == Datatype.CLASS_ARRAY && baseType.getDatatypeClass() == Datatype.CLASS_CHAR) 2091 && ((NT == 'B') || (NT == 'S'))) { 2092 int n = Array.getLength(dbuf); 2093 log.trace("JTable.ScalarDS isCellSelected charData length = {}", n); 2094 char[] charData = new char[n]; 2095 for (int i = 0; i < n; i++) { 2096 if (NT == 'B') { 2097 charData[i] = (char) Array.getByte(dbuf, i); 2098 } 2099 else if (NT == 'S') { 2100 charData[i] = (char) Array.getShort(dbuf, i); 2101 } 2102 } 2103 2104 strvalSB.append(charData); 2105 log.trace("JTable.ScalarDS isCellSelected charData");// = 2106 // {}", 2107 // strvalSB); 2108 } 2109 else { 2110 // numerical values 2111 if (dtype.getDatatypeClass() == Datatype.CLASS_ARRAY) dtype = baseType; 2112 boolean is_unsigned = dtype.isUnsigned(); 2113 int n = Array.getLength(dbuf); 2114 if (is_unsigned) { 2115 switch (NT) { 2116 case 'B': 2117 byte[] barray = (byte[]) dbuf; 2118 short sValue = barray[0]; 2119 if (sValue < 0) { 2120 sValue += 256; 2121 } 2122 strvalSB.append(sValue); 2123 for (int i = 1; i < n; i++) { 2124 strvalSB.append(','); 2125 sValue = barray[i]; 2126 if (sValue < 0) { 2127 sValue += 256; 2128 } 2129 strvalSB.append(sValue); 2130 } 2131 break; 2132 case 'S': 2133 short[] sarray = (short[]) dbuf; 2134 int iValue = sarray[0]; 2135 if (iValue < 0) { 2136 iValue += 65536; 2137 } 2138 strvalSB.append(iValue); 2139 for (int i = 1; i < n; i++) { 2140 strvalSB.append(','); 2141 iValue = sarray[i]; 2142 if (iValue < 0) { 2143 iValue += 65536; 2144 } 2145 strvalSB.append(iValue); 2146 } 2147 break; 2148 case 'I': 2149 int[] iarray = (int[]) dbuf; 2150 long lValue = iarray[0]; 2151 if (lValue < 0) { 2152 lValue += 4294967296L; 2153 } 2154 strvalSB.append(lValue); 2155 for (int i = 1; i < n; i++) { 2156 strvalSB.append(','); 2157 lValue = iarray[i]; 2158 if (lValue < 0) { 2159 lValue += 4294967296L; 2160 } 2161 strvalSB.append(lValue); 2162 } 2163 break; 2164 case 'J': 2165 long[] larray = (long[]) dbuf; 2166 Long l = (Long) larray[0]; 2167 String theValue = Long.toString(l); 2168 if (l < 0) { 2169 l = (l << 1) >>> 1; 2170 BigInteger big1 = new BigInteger("9223372036854775808"); // 2^65 2171 BigInteger big2 = new BigInteger(l.toString()); 2172 BigInteger big = big1.add(big2); 2173 theValue = big.toString(); 2174 } 2175 strvalSB.append(theValue); 2176 for (int i = 1; i < n; i++) { 2177 strvalSB.append(','); 2178 l = (Long) larray[i]; 2179 theValue = Long.toString(l); 2180 if (l < 0) { 2181 l = (l << 1) >>> 1; 2182 BigInteger big1 = new BigInteger("9223372036854775808"); // 2^65 2183 BigInteger big2 = new BigInteger(l.toString()); 2184 BigInteger big = big1.add(big2); 2185 theValue = big.toString(); 2186 } 2187 strvalSB.append(theValue); 2188 } 2189 break; 2190 default: 2191 strvalSB.append(Array.get(dbuf, 0)); 2192 for (int i = 1; i < n; i++) { 2193 strvalSB.append(','); 2194 strvalSB.append(Array.get(dbuf, i)); 2195 } 2196 break; 2197 } 2198 } 2199 else { 2200 for (int x = 0; x < n; x++) { 2201 Object theValue = Array.get(dbuf, x); 2202 if (x > 0) strvalSB.append(','); 2203 strvalSB.append(theValue); 2204 } 2205 } 2206 log.trace("JTable.ScalarDS isCellSelected byteString");// = 2207 // {}", 2208 // strvalSB); 2209 } 2210 idx++; 2211 dset.clearData(); 2212 log.trace("JTable.ScalarDS isCellSelected: st.hasMoreTokens() end");// strvalSB 2213 // = 2214 // {}", 2215 // strvalSB); 2216 } // while (st.hasMoreTokens()) 2217 strVal = strvalSB.toString(); 2218 log.trace("JTable.ScalarDS isCellSelected: st.hasMoreTokens() end");// value 2219 // = 2220 // {}", 2221 // strVal); 2222 } 2223 } 2224 } 2225 } 2226 else { 2227 strVal = null; 2228 } 2229 } 2230 else if (isObjRef) { 2231 Long ref = (Long) val; 2232 long oid[] = { ref.longValue() }; 2233 2234 // decode object ID 2235 try { 2236 HObject obj = FileFormat.findObject(dataset.getFileFormat(), oid); 2237 strVal = obj.getFullName(); 2238 } 2239 catch (Exception ex) { 2240 strVal = null; 2241 } 2242 } 2243 2244 if (strVal == null && val != null) strVal = val.toString(); 2245 2246 log.trace("JTable.ScalarDS isCellSelected finish");// value 2247 // = 2248 // {}",strVal); 2249 cellValueField.setText(strVal); 2250 } 2251 2252 return super.isCellSelected(row, column); 2253 } 2254 }; 2255 theTable.setName("ScalarDS"); 2256 2257 log.trace("createTable: ScalarDS finish"); 2258 return theTable; 2259 } 2260 2261 /** 2262 * Creates a JTable to hold a compound dataset. 2263 */ 2264 private JTable createTable (CompoundDS d) { 2265 JTable theTable = null; 2266 log.trace("createTable: CompoundDS start"); 2267 2268 int rank = d.getRank(); 2269 if (rank <= 0) { 2270 d.init(); 2271 } 2272 2273 long[] startArray = d.getStartDims(); 2274 long[] strideArray = d.getStride(); 2275 int[] selectedIndex = d.getSelectedIndex(); 2276 final int rowStart = (int) startArray[selectedIndex[0]]; 2277 final int rowStride = (int) strideArray[selectedIndex[0]]; 2278 2279 // use lazy convert for large number of strings 2280 if (d.getHeight() > 10000) { 2281 d.setConvertByteToString(false); 2282 } 2283 2284 dataValue = null; 2285 try { 2286 dataValue = d.getData(); 2287 } 2288 catch (Throwable ex) { 2289 log.debug("getData failure: ", ex); 2290 toolkit.beep(); 2291 JOptionPane.showMessageDialog(this, ex, "TableView" + getTitle(), JOptionPane.ERROR_MESSAGE); 2292 dataValue = null; 2293 } 2294 2295 if ((dataValue == null) || !(dataValue instanceof List)) { 2296 return null; 2297 } 2298 2299 final int rows = d.getHeight(); 2300 int cols = d.getSelectedMemberCount(); 2301 String[] columnNames = new String[cols]; 2302 2303 int idx = 0; 2304 String[] columnNamesAll = d.getMemberNames(); 2305 for (int i = 0; i < columnNamesAll.length; i++) { 2306 if (d.isMemberSelected(i)) { 2307 columnNames[idx] = columnNamesAll[i]; 2308 columnNames[idx] = columnNames[idx].replaceAll(CompoundDS.separator, "->"); 2309 idx++; 2310 } 2311 } 2312 2313 String[] subColumnNames = columnNames; 2314 int columns = d.getWidth(); 2315 if (columns > 1) { 2316 // multi-dimension compound dataset 2317 subColumnNames = new String[columns * columnNames.length]; 2318 int halfIdx = columnNames.length / 2; 2319 for (int i = 0; i < columns; i++) { 2320 for (int j = 0; j < columnNames.length; j++) { 2321 // display column index only once, in the middle of the 2322 // compound fields 2323 if (j == halfIdx) { 2324 // subColumnNames[i * columnNames.length + j] = (i + 1) 2325 // + "\n " + columnNames[j]; 2326 subColumnNames[i * columnNames.length + j] = (i + indexBase) + "\n " + columnNames[j]; 2327 } 2328 else { 2329 subColumnNames[i * columnNames.length + j] = " \n " + columnNames[j]; 2330 } 2331 } 2332 } 2333 } 2334 2335 final String[] allColumnNames = subColumnNames; 2336 AbstractTableModel tm = new AbstractTableModel() { 2337 private static final long serialVersionUID = -2176296469630678304L; 2338 CompoundDS compound = (CompoundDS) dataset; 2339 int orders[] = compound.getSelectedMemberOrders(); 2340 Datatype types[] = compound.getSelectedMemberTypes(); 2341 StringBuffer stringBuffer = new StringBuffer(); 2342 int nFields = ((List<?>) dataValue).size(); 2343 int nRows = getRowCount(); 2344 int nSubColumns = (nFields > 0) ? getColumnCount() / nFields : 0; 2345 2346 @Override 2347 public int getColumnCount ( ) { 2348 return allColumnNames.length; 2349 } 2350 2351 @Override 2352 public int getRowCount ( ) { 2353 return rows; 2354 } 2355 2356 @Override 2357 public String getColumnName (int col) { 2358 return allColumnNames[col]; 2359 } 2360 2361 @Override 2362 public Object getValueAt (int row, int col) { 2363 if (startEditing[0]) return ""; 2364 2365 int fieldIdx = col; 2366 int rowIdx = row; 2367 char CNT = ' '; 2368 boolean CshowAsHex = false; 2369 boolean CshowAsBin = false; 2370 log.trace("CompoundDS:createTable:AbstractTableModel:getValueAt({},{}) start", row, col); 2371 2372 if (nSubColumns > 1) { // multi-dimension compound dataset 2373 int colIdx = col / nFields; 2374 fieldIdx = col - colIdx * nFields; 2375 // BUG 573: rowIdx = row * orders[fieldIdx] + colIdx * nRows 2376 // * orders[fieldIdx]; 2377 rowIdx = row * orders[fieldIdx] * nSubColumns + colIdx * orders[fieldIdx]; 2378 log.trace( 2379 "CompoundDS:createTable:AbstractTableModel:getValueAt() row={} orders[{}]={} nSubColumns={} colIdx={}", 2380 row, fieldIdx, orders[fieldIdx], nSubColumns, colIdx); 2381 } 2382 else { 2383 rowIdx = row * orders[fieldIdx]; 2384 log.trace("CompoundDS:createTable:AbstractTableModel:getValueAt() row={} orders[{}]={}", row, fieldIdx, 2385 orders[fieldIdx]); 2386 } 2387 log.trace("CompoundDS:createTable:AbstractTableModel:getValueAt() fieldIdx={} rowIdx={}", fieldIdx, rowIdx); 2388 2389 Object colValue = ((List<?>) dataValue).get(fieldIdx); 2390 if (colValue == null) { 2391 return "Null"; 2392 } 2393 2394 stringBuffer.setLength(0); // clear the old string 2395 Datatype dtype = types[fieldIdx]; 2396 boolean isString = (dtype.getDatatypeClass() == Datatype.CLASS_STRING); 2397 boolean isArray = (dtype.getDatatypeClass() == Datatype.CLASS_ARRAY); 2398 if (isArray) { 2399 dtype = types[fieldIdx].getBasetype(); 2400 isString = (dtype.getDatatypeClass() == Datatype.CLASS_STRING); 2401 log.trace("**CompoundDS:createTable:AbstractTableModel:getValueAt(): isArray={} isString={}", isArray, isString); 2402 2403 if (dtype instanceof H5Datatype) { 2404 // Since variable-length strings are of type CLASS_STRING, not CLASS_VLEN, 2405 // the check below cannot determine if the datatype is a variable-length string 2406 if (((H5Datatype) dtype).isVLEN() && isString) { 2407 for (int i = 0; i < orders[fieldIdx]; i++) { 2408 if (i > 0) stringBuffer.append(", "); 2409 stringBuffer.append(((String[]) colValue)[i]); 2410 } 2411 return stringBuffer; 2412 } 2413 } 2414 else if (dtype.getDatatypeClass() == Datatype.CLASS_VLEN) { 2415 // Only support variable length strings 2416 if (!(dtype.getBasetype().getDatatypeClass() == Datatype.CLASS_STRING)) { 2417 int arraylen = (int) types[fieldIdx].getDatatypeSize(); 2418 log.trace("**CompoundDS:createTable:AbstractTableModel:getValueAt(): isArray={} of {} istype={}", isArray, arraylen, dtype); 2419 String str = new String( "*unsupported*"); 2420 stringBuffer.append(str.trim()); 2421 return stringBuffer; 2422 } 2423 } 2424 } 2425 log.trace("CompoundDS:createTable:AbstractTableModel:getValueAt(): isString={} getBasetype()={}", isString, types[fieldIdx].getDatatypeClass()); 2426 if (isString && ((colValue instanceof byte[]) || isArray)) { 2427 // strings 2428 int strlen = dtype.getDatatypeSize(); 2429 int arraylen = strlen; 2430 if(isArray) { 2431 arraylen = types[fieldIdx].getDatatypeSize(); 2432 } 2433 log.trace("**CompoundDS:createTable:AbstractTableModel:getValueAt(): isArray={} of {} isString={} of {}", isArray, arraylen, isString, strlen); 2434 int arraycnt = arraylen / strlen; 2435 for (int loopidx = 0; loopidx < arraycnt; loopidx++) { 2436 if(isArray && loopidx > 0) { 2437 stringBuffer.append(", "); 2438 } 2439 String str = new String(((byte[]) colValue), rowIdx * strlen + loopidx * strlen, strlen); 2440 int idx = str.indexOf('\0'); 2441 if (idx > 0) { 2442 str = str.substring(0, idx); 2443 } 2444 stringBuffer.append(str.trim()); 2445 } 2446 } 2447 else if (isArray && dtype.getDatatypeClass() == Datatype.CLASS_COMPOUND) { 2448 for (int i = 0; i < orders[fieldIdx]; i++) { 2449 try { 2450 int tid = dtype.toNative(); 2451 int numberOfMembers = H5.H5Tget_nmembers(tid); 2452 Object field_data = null; 2453 2454 try { 2455 field_data = Array.get(colValue, rowIdx + i); 2456 } 2457 catch (Exception ex) { 2458 log.debug("CompoundDS:createTable:AbstractTableModel:getValueAt(): could not retrieve field_data: ", ex); 2459 } 2460 2461 if (i > 0) stringBuffer.append(", "); 2462 stringBuffer.append("[ "); 2463 2464 for (int j = 0; j < numberOfMembers; j++) { 2465 Object theValue = null; 2466 2467 try { 2468 theValue = Array.get(field_data, j); 2469 log.trace("CompoundDS:createTable:AbstractTableModel:getValueAt() theValue[{}]={}", j, theValue.toString()); 2470 } 2471 catch (Exception ex) { 2472 log.debug("CompoundDS:createTable:AbstractTableModel:getValueAt() member[{}] is unsupported", j, ex); 2473 theValue = "*unsupported*"; 2474 } 2475 2476 if (j > 0) stringBuffer.append(", "); 2477 stringBuffer.append(theValue); 2478 } 2479 2480 stringBuffer.append(" ]"); 2481 } 2482 catch (Exception ex) { 2483 log.trace("CompoundDS:createTable:AbstractTableModel:getValueAt(): ", ex); 2484 } 2485 } 2486 2487 return stringBuffer; 2488 } 2489 else { 2490 // numerical values 2491 2492 String cName = colValue.getClass().getName(); 2493 int cIndex = cName.lastIndexOf("["); 2494 if (cIndex >= 0) { 2495 CNT = cName.charAt(cIndex + 1); 2496 } 2497 log.trace("CompoundDS:createTable:AbstractTableModel:getValueAt(): cName={} CNT={}", cName, CNT); 2498 2499 boolean isUINT64 = false; 2500 boolean isInt = (CNT == 'B' || CNT == 'S' || CNT == 'I' || CNT == 'J'); 2501 boolean isEnum = dtype.getDatatypeClass() == Datatype.CLASS_ENUM; 2502 int typeSize = dtype.getDatatypeSize(); 2503 2504 if ((dtype.getDatatypeClass() == Datatype.CLASS_BITFIELD) 2505 || (dtype.getDatatypeClass() == Datatype.CLASS_OPAQUE)) { 2506 CshowAsHex = true; 2507 log.trace("CompoundDS:createTable:AbstractTableModel:getValueAt() class={} (BITFIELD or OPAQUE)", 2508 dtype.getDatatypeClass()); 2509 } 2510 if (dtype.isUnsigned()) { 2511 if (cIndex >= 0) { 2512 isUINT64 = (cName.charAt(cIndex + 1) == 'J'); 2513 } 2514 } 2515 log.trace( 2516 "CompoundDS:createTable:AbstractTableModel:getValueAt() isUINT64={} isInt={} CshowAsHex={} typeSize={}", 2517 isUINT64, isInt, CshowAsHex, typeSize); 2518 2519 if (isEnum) { 2520 String[] outValues = new String[getRowCount() * orders[fieldIdx]]; 2521 2522 if (!dataset.isEnumConverted()) { 2523 try { 2524 H5Datatype.convertEnumValueToName(dtype.toNative(), colValue, outValues); 2525 } 2526 catch (HDF5Exception ex) { 2527 log.trace("CompoundDS:createTable:AbstractTableModel:getValueAt(): Could not convert enum values to names: ex"); 2528 return stringBuffer; 2529 } 2530 } 2531 else 2532 outValues = (String[])colValue; 2533 for (int i = rowIdx; i < (rowIdx + orders[fieldIdx]); i++) { 2534 if (i > rowIdx) stringBuffer.append(", "); 2535 stringBuffer.append(outValues[i]); 2536 } 2537 } 2538 else { 2539 for (int i = 0; i < orders[fieldIdx]; i++) { 2540 log.trace("CompoundDS:createTable:AbstractTableModel:getValueAt():for[{}]", i); 2541 if (isUINT64) { 2542 Object theValue = Array.get(colValue, rowIdx + i); 2543 log.trace("CompoundDS:createTable:AbstractTableModel:getValueAt() isUINT64 theValue[{}]={}", i, 2544 theValue.toString()); 2545 Long l = (Long) theValue; 2546 BigInteger big; 2547 if (l < 0) { 2548 l = (l << 1) >>> 1; 2549 BigInteger big1 = new BigInteger("9223372036854775808"); // 2^65 2550 BigInteger big2 = new BigInteger(l.toString()); 2551 big = big1.add(big2); 2552 } 2553 else { 2554 big = new BigInteger(l.toString()); 2555 } 2556 if (showAsHex) 2557 theValue = Tools.toHexString(big.longValue(), typeSize);// big.toString(16); 2558 else if (showAsBin) 2559 theValue = Tools.toBinaryString(big.longValue(), typeSize); 2560 else 2561 theValue = big.toString(10); 2562 2563 if (i > 0) stringBuffer.append(", "); 2564 stringBuffer.append(theValue); 2565 } 2566 else if (CshowAsHex && isInt) { 2567 char[] hexArray = "0123456789ABCDEF".toCharArray(); 2568 Object theValue = Array.get(colValue, rowIdx * typeSize + typeSize * i); 2569 log.trace("CompoundDS:createTable:AbstractTableModel:getValueAt() CshowAsHex theValue[{}]={}", i, 2570 theValue.toString()); 2571 // show in Hexadecimal 2572 char[] hexChars = new char[2]; 2573 if (i > 0) stringBuffer.append(", "); 2574 for (int x = 0; x < typeSize; x++) { 2575 if (x > 0) 2576 theValue = Array.get(colValue, rowIdx * typeSize + typeSize * i + x); 2577 int v = (int) ((Byte) theValue) & 0xFF; 2578 hexChars[0] = hexArray[v >>> 4]; 2579 hexChars[1] = hexArray[v & 0x0F]; 2580 if (x > 0) stringBuffer.append(":"); 2581 stringBuffer.append(hexChars); 2582 log.trace("CompoundDS:createTable:AbstractTableModel:getValueAt() hexChars[{}]={}", x, hexChars); 2583 } 2584 } 2585 else if (showAsBin && isInt) { 2586 Object theValue = Array.get(colValue, rowIdx + typeSize * i); 2587 log.trace("CompoundDS:createTable:AbstractTableModel:getValueAt() showAsBin theValue[{}]={}", i, 2588 theValue.toString()); 2589 theValue = Tools.toBinaryString(Long.valueOf(theValue.toString()), typeSize); 2590 if (i > 0) stringBuffer.append(", "); 2591 stringBuffer.append(theValue); 2592 } 2593 else if (numberFormat != null) { 2594 // show in scientific format 2595 Object theValue = Array.get(colValue, rowIdx + i); 2596 log.trace("CompoundDS:createTable:AbstractTableModel:getValueAt() numberFormat theValue[{}]={}", i, 2597 theValue.toString()); 2598 theValue = numberFormat.format(theValue); 2599 if (i > 0) stringBuffer.append(", "); 2600 stringBuffer.append(theValue); 2601 } 2602 else { 2603 Object theValue = Array.get(colValue, rowIdx + i); 2604 log.trace("CompoundDS:createTable:AbstractTableModel:getValueAt() theValue[{}]={}", i, 2605 theValue.toString()); 2606 if (i > 0) stringBuffer.append(", "); 2607 stringBuffer.append(theValue); 2608 } 2609 } 2610 } // end of else { 2611 } // end of else { 2612 2613 return stringBuffer; 2614 } 2615 }; 2616 2617 theTable = new JTable(tm) { 2618 private static final long serialVersionUID = 3221288637329958074L; 2619 int lastSelectedRow = -1; 2620 int lastSelectedColumn = -1; 2621 2622 @Override 2623 public boolean isCellEditable (int row, int column) { 2624 return !isReadOnly; 2625 } 2626 2627 @Override 2628 public boolean editCellAt (int row, int column, java.util.EventObject e) { 2629 if (!isCellEditable(row, column)) { 2630 return super.editCellAt(row, column, e); 2631 } 2632 2633 if (e instanceof KeyEvent) { 2634 KeyEvent ke = (KeyEvent) e; 2635 if (ke.getID() == KeyEvent.KEY_PRESSED) startEditing[0] = true; 2636 } 2637 else if (e instanceof MouseEvent) { 2638 MouseEvent me = (MouseEvent) e; 2639 int mc = me.getClickCount(); 2640 if (mc > 1) { 2641 currentEditingCellValue = getValueAt(row, column); 2642 } 2643 } 2644 2645 return super.editCellAt(row, column, e); 2646 } 2647 2648 @Override 2649 public void editingStopped (ChangeEvent e) { 2650 int row = getEditingRow(); 2651 int col = getEditingColumn(); 2652 super.editingStopped(e); 2653 startEditing[0] = false; 2654 2655 Object source = e.getSource(); 2656 2657 if (source instanceof CellEditor) { 2658 CellEditor editor = (CellEditor) source; 2659 String cellValue = (String) editor.getCellEditorValue(); 2660 2661 try { 2662 updateValueInMemory(cellValue, row, col); 2663 } 2664 catch (Exception ex) { 2665 log.debug("updateValueInMemory: ", ex); 2666 toolkit.beep(); 2667 JOptionPane.showMessageDialog(this, ex, getTitle(), JOptionPane.ERROR_MESSAGE); 2668 } 2669 } // if (source instanceof CellEditor) 2670 } 2671 2672 @Override 2673 public boolean isCellSelected (int row, int column) { 2674 if ((lastSelectedRow == row) && (lastSelectedColumn == column)) { 2675 return super.isCellSelected(row, column); 2676 } 2677 log.trace("JTable.CompoundDS isCellSelected row={} column={}", row, column); 2678 2679 lastSelectedRow = row; 2680 lastSelectedColumn = column; 2681 if ((getSelectedRow() == row) && (getSelectedColumn() == column)) { 2682 cellLabel.setText(String.valueOf(rowStart + indexBase + row * rowStride) + ", " + table.getColumnName(column) 2683 + " = "); 2684 cellValueField.setText(getValueAt(row, column).toString()); 2685 } 2686 2687 return super.isCellSelected(row, column); 2688 } 2689 }; 2690 2691 if (columns > 1) { 2692 // multi-dimension compound dataset 2693 MultiLineHeaderRenderer renderer = new MultiLineHeaderRenderer(columns, columnNames.length); 2694 Enumeration<?> local_enum = theTable.getColumnModel().getColumns(); 2695 while (local_enum.hasMoreElements()) { 2696 ((TableColumn) local_enum.nextElement()).setHeaderRenderer(renderer); 2697 } 2698 } 2699 theTable.setName("CompoundDS"); 2700 2701 log.trace("createTable: CompoundDS finish"); 2702 return theTable; 2703 } /* createTable */ 2704 2705 private void gotoPage (long idx) { 2706 if (dataset.getRank() < 3 || idx == (curFrame - indexBase)) { 2707 return; 2708 } 2709 2710 if (isValueChanged) { 2711 updateValueInFile(); 2712 } 2713 2714 long[] start = dataset.getStartDims(); 2715 int[] selectedIndex = dataset.getSelectedIndex(); 2716 long[] dims = dataset.getDims(); 2717 2718 if ((idx < 0) || (idx >= dims[selectedIndex[2]])) { 2719 toolkit.beep(); 2720 JOptionPane.showMessageDialog(this, "Frame number must be between" + indexBase + " and " 2721 + (dims[selectedIndex[2]] - 1 + indexBase), getTitle(), JOptionPane.ERROR_MESSAGE); 2722 return; 2723 } 2724 2725 start[selectedIndex[2]] = idx; 2726 curFrame = idx + indexBase; 2727 dataset.clearData(); 2728 2729 setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); 2730 2731 try { 2732 dataValue = dataset.getData(); 2733 if (dataset instanceof ScalarDS) { 2734 ((ScalarDS) dataset).convertFromUnsignedC(); 2735 dataValue = dataset.getData(); 2736 } 2737 } 2738 catch (Exception ex) { 2739 setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); 2740 dataValue = null; 2741 JOptionPane.showMessageDialog(this, ex, getTitle(), JOptionPane.ERROR_MESSAGE); 2742 return; 2743 } 2744 2745 setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); 2746 2747 frameField.setText(String.valueOf(curFrame)); 2748 updateUI(); 2749 } 2750 2751 /** copy data from the spreadsheet to the system clipboard. */ 2752 private void copyData ( ) { 2753 StringBuffer sb = new StringBuffer(); 2754 2755 int r0 = table.getSelectedRow(); // starting row 2756 int c0 = table.getSelectedColumn(); // starting column 2757 2758 if ((r0 < 0) || (c0 < 0)) { 2759 return; 2760 } 2761 2762 int nr = table.getSelectedRowCount(); 2763 int nc = table.getSelectedColumnCount(); 2764 int r1 = r0 + nr; // finish row 2765 int c1 = c0 + nc; // finishing column 2766 2767 try { 2768 for (int i = r0; i < r1; i++) { 2769 sb.append(table.getValueAt(i, c0).toString()); 2770 for (int j = c0 + 1; j < c1; j++) { 2771 sb.append("\t"); 2772 sb.append(table.getValueAt(i, j).toString()); 2773 } 2774 sb.append("\n"); 2775 } 2776 } 2777 catch (java.lang.OutOfMemoryError err) { 2778 toolkit.beep(); 2779 JOptionPane.showMessageDialog((JFrame) viewer, 2780 "Copying data to system clipboard failed. \nUsing \"export/import data\" for copying/pasting large data.", 2781 getTitle(), JOptionPane.ERROR_MESSAGE); 2782 return; 2783 } 2784 2785 Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard(); 2786 StringSelection contents = new StringSelection(sb.toString()); 2787 cb.setContents(contents, null); 2788 } 2789 2790 /** paste data from the system clipboard to the spreadsheet. */ 2791 private void pasteData ( ) { 2792 int pasteDataFlag = JOptionPane.showConfirmDialog(this, "Do you want to paste selected data?", this.getTitle(), 2793 JOptionPane.YES_NO_OPTION); 2794 if (pasteDataFlag == JOptionPane.NO_OPTION) { 2795 return; 2796 } 2797 2798 int cols = table.getColumnCount(); 2799 int rows = table.getRowCount(); 2800 int r0 = table.getSelectedRow(); 2801 int c0 = table.getSelectedColumn(); 2802 2803 if (c0 < 0) { 2804 c0 = 0; 2805 } 2806 if (r0 < 0) { 2807 r0 = 0; 2808 } 2809 int r = r0; 2810 int c = c0; 2811 2812 Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard(); 2813 // Transferable content = cb.getContents(this); 2814 String line = ""; 2815 try { 2816 String s = (String) cb.getData(DataFlavor.stringFlavor); 2817 2818 StringTokenizer st = new StringTokenizer(s, "\n"); 2819 // read line by line 2820 while (st.hasMoreTokens() && (r < rows)) { 2821 line = st.nextToken(); 2822 2823 if (fixedDataLength < 1) { 2824 // separate by delimiter 2825 StringTokenizer lt = new StringTokenizer(line, "\t"); 2826 while (lt.hasMoreTokens() && (c < cols)) { 2827 try { 2828 updateValueInMemory(lt.nextToken(), r, c); 2829 } 2830 catch (Exception ex) { 2831 continue; 2832 } 2833 c++; 2834 } 2835 r = r + 1; 2836 c = c0; 2837 } 2838 else { 2839 // the data has fixed length 2840 int n = line.length(); 2841 String theVal; 2842 for (int i = 0; i < n; i = i + fixedDataLength) { 2843 try { 2844 theVal = line.substring(i, i + fixedDataLength); 2845 updateValueInMemory(theVal, r, c); 2846 } 2847 catch (Exception ex) { 2848 continue; 2849 } 2850 c++; 2851 } 2852 } 2853 } 2854 } 2855 catch (Throwable ex) { 2856 toolkit.beep(); 2857 JOptionPane.showMessageDialog(this, ex, getTitle(), JOptionPane.ERROR_MESSAGE); 2858 } 2859 2860 table.updateUI(); 2861 } 2862 2863 /** 2864 * import data values from text file. 2865 */ 2866 private void importTextData (String fname) { 2867 int pasteDataFlag = JOptionPane.showConfirmDialog(this, "Do you want to paste selected data?", this.getTitle(), 2868 JOptionPane.YES_NO_OPTION); 2869 if (pasteDataFlag == JOptionPane.NO_OPTION) { 2870 return; 2871 } 2872 int cols = table.getColumnCount(); 2873 int rows = table.getRowCount(); 2874 int r0 = table.getSelectedRow(); 2875 int c0 = table.getSelectedColumn(); 2876 2877 if (c0 < 0) { 2878 c0 = 0; 2879 } 2880 if (r0 < 0) { 2881 r0 = 0; 2882 } 2883 2884 // start at the first column for compound datasets 2885 if (dataset instanceof CompoundDS) c0 = 0; 2886 2887 BufferedReader in = null; 2888 try { 2889 in = new BufferedReader(new FileReader(fname)); 2890 } 2891 catch (FileNotFoundException ex) { 2892 log.debug("import data values from text file {}:", fname, ex); 2893 return; 2894 } 2895 2896 String line = null; 2897 StringTokenizer tokenizer1 = null; 2898 2899 try { 2900 line = in.readLine(); 2901 } 2902 catch (IOException ex) { 2903 try { 2904 in.close(); 2905 } 2906 catch (IOException ex2) { 2907 log.debug("close text file {}:", fname, ex2); 2908 } 2909 log.debug("read text file {}:", fname, ex); 2910 return; 2911 } 2912 2913 String delName = ViewProperties.getDataDelimiter(); 2914 String delimiter = ""; 2915 2916 // delimiter must include a tab to be consistent with copy/paste for 2917 // compound fields 2918 if (dataset instanceof CompoundDS) 2919 delimiter = "\t"; 2920 else { 2921 if (delName.equalsIgnoreCase(ViewProperties.DELIMITER_TAB)) { 2922 delimiter = "\t"; 2923 } 2924 else if (delName.equalsIgnoreCase(ViewProperties.DELIMITER_SPACE)) { 2925 delimiter = " " + delimiter; 2926 } 2927 else if (delName.equalsIgnoreCase(ViewProperties.DELIMITER_COMMA)) { 2928 delimiter = ","; 2929 } 2930 else if (delName.equalsIgnoreCase(ViewProperties.DELIMITER_COLON)) { 2931 delimiter = ":"; 2932 } 2933 else if (delName.equalsIgnoreCase(ViewProperties.DELIMITER_SEMI_COLON)) { 2934 delimiter = ";"; 2935 } 2936 } 2937 String token = null; 2938 int r = r0; 2939 int c = c0; 2940 while ((line != null) && (r < rows)) { 2941 if (fixedDataLength > 0) { 2942 // the data has fixed length 2943 int n = line.length(); 2944 String theVal; 2945 for (int i = 0; i < n; i = i + fixedDataLength) { 2946 try { 2947 theVal = line.substring(i, i + fixedDataLength); 2948 updateValueInMemory(theVal, r, c); 2949 } 2950 catch (Exception ex) { 2951 continue; 2952 } 2953 c++; 2954 } 2955 } 2956 else { 2957 try { 2958 tokenizer1 = new StringTokenizer(line, delimiter); 2959 while (tokenizer1.hasMoreTokens() && (c < cols)) { 2960 token = tokenizer1.nextToken(); 2961 if (dataset instanceof ScalarDS) { 2962 StringTokenizer tokenizer2 = new StringTokenizer(token); 2963 while (tokenizer2.hasMoreTokens() && (c < cols)) { 2964 updateValueInMemory(tokenizer2.nextToken(), r, c); 2965 c++; 2966 } 2967 } 2968 else { 2969 updateValueInMemory(token, r, c); 2970 c++; 2971 } 2972 } // while (tokenizer1.hasMoreTokens() && index < size) 2973 } 2974 catch (Exception ex) { 2975 JOptionPane.showMessageDialog(this, ex, getTitle(), JOptionPane.ERROR_MESSAGE); 2976 try { 2977 in.close(); 2978 } 2979 catch (IOException ex2) { 2980 log.debug("close text file {}:", fname, ex2); 2981 } 2982 return; 2983 } 2984 } 2985 2986 try { 2987 line = in.readLine(); 2988 } 2989 catch (IOException ex) { 2990 log.debug("read text file {}:", fname, ex); 2991 line = null; 2992 } 2993 c = 0; 2994 r++; 2995 } // while ((line != null) && (r < rows)) 2996 2997 try { 2998 in.close(); 2999 } 3000 catch (IOException ex) { 3001 log.debug("close text file {}:", fname, ex); 3002 } 3003 3004 table.updateUI(); 3005 } 3006 3007 /** 3008 * import data values from binary file. 3009 */ 3010 private void importBinaryData ( ) { 3011 String currentDir = dataset.getFileFormat().getParent(); 3012 JFileChooser fchooser = new JFileChooser(currentDir); 3013 fchooser.setFileFilter(DefaultFileFilter.getFileFilterBinary()); 3014 int returnVal = fchooser.showOpenDialog(this); 3015 3016 if (returnVal != JFileChooser.APPROVE_OPTION) { 3017 return; 3018 } 3019 File choosedFile = fchooser.getSelectedFile(); 3020 if (choosedFile == null) { 3021 return; 3022 } 3023 String fname = choosedFile.getAbsolutePath(); 3024 3025 int pasteDataFlag = JOptionPane.showConfirmDialog(this, "Do you want to paste selected data?", this.getTitle(), 3026 JOptionPane.YES_NO_OPTION); 3027 if (pasteDataFlag == JOptionPane.NO_OPTION) { 3028 return; 3029 } 3030 3031 getBinaryDatafromFile(fname); 3032 } 3033 3034 /** Reads data from a binary file into a buffer and updates table. */ 3035 private void getBinaryDatafromFile (String fileName) { 3036 String fname = fileName; 3037 FileInputStream inputFile = null; 3038 BufferedInputStream in = null; 3039 ByteBuffer byteBuffer = null; 3040 try { 3041 inputFile = new FileInputStream(fname); 3042 long fileSize = inputFile.getChannel().size(); 3043 in = new BufferedInputStream(inputFile); 3044 3045 Object data = dataset.getData(); 3046 int datasetSize = Array.getLength(data); 3047 String cname = data.getClass().getName(); 3048 char dname = cname.charAt(cname.lastIndexOf("[") + 1); 3049 3050 if (dname == 'B') { 3051 long datasetByteSize = datasetSize; 3052 byteBuffer = ByteBuffer.allocate(BYTE_BUFFER_SIZE); 3053 if (binaryOrder == 1) 3054 byteBuffer.order(ByteOrder.nativeOrder()); 3055 else if (binaryOrder == 2) 3056 byteBuffer.order(ByteOrder.LITTLE_ENDIAN); 3057 else if (binaryOrder == 3) byteBuffer.order(ByteOrder.BIG_ENDIAN); 3058 3059 int bufferSize = (int) Math.min(fileSize, datasetByteSize); 3060 3061 int remainingSize = bufferSize - (BYTE_BUFFER_SIZE); 3062 int allocValue = 0; 3063 int iterationNumber = 0; 3064 byte[] byteArray = new byte[BYTE_BUFFER_SIZE]; 3065 do { 3066 if (remainingSize <= 0) { 3067 allocValue = remainingSize + (BYTE_BUFFER_SIZE); 3068 } 3069 else { 3070 allocValue = (BYTE_BUFFER_SIZE); 3071 } 3072 3073 in.read(byteBuffer.array(), 0, allocValue); 3074 3075 byteBuffer.get(byteArray, 0, allocValue); 3076 System.arraycopy(byteArray, 0, dataValue, (iterationNumber * BYTE_BUFFER_SIZE), allocValue); 3077 byteBuffer.clear(); 3078 remainingSize = remainingSize - (BYTE_BUFFER_SIZE); 3079 iterationNumber++; 3080 } while (remainingSize > -(BYTE_BUFFER_SIZE)); 3081 3082 isValueChanged = true; 3083 } 3084 else if (dname == 'S') { 3085 long datasetShortSize = datasetSize * 2; 3086 byteBuffer = ByteBuffer.allocate(SHORT_BUFFER_SIZE * 2); 3087 if (binaryOrder == 1) 3088 byteBuffer.order(ByteOrder.nativeOrder()); 3089 else if (binaryOrder == 2) 3090 byteBuffer.order(ByteOrder.LITTLE_ENDIAN); 3091 else if (binaryOrder == 3) byteBuffer.order(ByteOrder.BIG_ENDIAN); 3092 3093 int bufferSize = (int) Math.min(fileSize, datasetShortSize); 3094 int remainingSize = bufferSize - (SHORT_BUFFER_SIZE * 2); 3095 int allocValue = 0; 3096 int iterationNumber = 0; 3097 ShortBuffer sb = byteBuffer.asShortBuffer(); 3098 short[] shortArray = new short[SHORT_BUFFER_SIZE]; 3099 3100 do { 3101 if (remainingSize <= 0) { 3102 allocValue = remainingSize + (SHORT_BUFFER_SIZE * 2); 3103 } 3104 else { 3105 allocValue = (SHORT_BUFFER_SIZE * 2); 3106 } 3107 in.read(byteBuffer.array(), 0, allocValue); 3108 sb.get(shortArray, 0, allocValue / 2); 3109 System.arraycopy(shortArray, 0, dataValue, (iterationNumber * SHORT_BUFFER_SIZE), allocValue / 2); 3110 byteBuffer.clear(); 3111 sb.clear(); 3112 remainingSize = remainingSize - (SHORT_BUFFER_SIZE * 2); 3113 iterationNumber++; 3114 } while (remainingSize > -(SHORT_BUFFER_SIZE * 2)); 3115 3116 isValueChanged = true; 3117 } 3118 else if (dname == 'I') { 3119 long datasetIntSize = datasetSize * 4; 3120 byteBuffer = ByteBuffer.allocate(INT_BUFFER_SIZE * 4); 3121 if (binaryOrder == 1) 3122 byteBuffer.order(ByteOrder.nativeOrder()); 3123 else if (binaryOrder == 2) 3124 byteBuffer.order(ByteOrder.LITTLE_ENDIAN); 3125 else if (binaryOrder == 3) byteBuffer.order(ByteOrder.BIG_ENDIAN); 3126 3127 int bufferSize = (int) Math.min(fileSize, datasetIntSize); 3128 int remainingSize = bufferSize - (INT_BUFFER_SIZE * 4); 3129 int allocValue = 0; 3130 int iterationNumber = 0; 3131 int[] intArray = new int[INT_BUFFER_SIZE]; 3132 byte[] tmpBuf = byteBuffer.array(); 3133 IntBuffer ib = byteBuffer.asIntBuffer(); 3134 3135 do { 3136 if (remainingSize <= 0) { 3137 allocValue = remainingSize + (INT_BUFFER_SIZE * 4); 3138 } 3139 else { 3140 allocValue = (INT_BUFFER_SIZE * 4); 3141 } 3142 in.read(tmpBuf, 0, allocValue); 3143 ib.get(intArray, 0, allocValue / 4); 3144 System.arraycopy(intArray, 0, dataValue, (iterationNumber * INT_BUFFER_SIZE), allocValue / 4); 3145 byteBuffer.clear(); 3146 ib.clear(); 3147 remainingSize = remainingSize - (INT_BUFFER_SIZE * 4); 3148 iterationNumber++; 3149 } while (remainingSize > -(INT_BUFFER_SIZE * 4)); 3150 3151 isValueChanged = true; 3152 } 3153 else if (dname == 'J') { 3154 long datasetLongSize = datasetSize * 8; 3155 byteBuffer = ByteBuffer.allocate(LONG_BUFFER_SIZE * 8); 3156 3157 if (binaryOrder == 1) 3158 byteBuffer.order(ByteOrder.nativeOrder()); 3159 else if (binaryOrder == 2) 3160 byteBuffer.order(ByteOrder.LITTLE_ENDIAN); 3161 else if (binaryOrder == 3) byteBuffer.order(ByteOrder.BIG_ENDIAN); 3162 3163 int bufferSize = (int) Math.min(fileSize, datasetLongSize); 3164 int remainingSize = bufferSize - (LONG_BUFFER_SIZE * 8); 3165 int allocValue = 0; 3166 int iterationNumber = 0; 3167 long[] longArray = new long[LONG_BUFFER_SIZE]; 3168 LongBuffer lb = byteBuffer.asLongBuffer(); 3169 3170 do { 3171 if (remainingSize <= 0) { 3172 allocValue = remainingSize + (LONG_BUFFER_SIZE * 8); 3173 } 3174 else { 3175 allocValue = (LONG_BUFFER_SIZE * 8); 3176 } 3177 3178 in.read(byteBuffer.array(), 0, allocValue); 3179 lb.get(longArray, 0, allocValue / 8); 3180 System.arraycopy(longArray, 0, dataValue, (iterationNumber * LONG_BUFFER_SIZE), allocValue / 8); 3181 byteBuffer.clear(); 3182 lb.clear(); 3183 remainingSize = remainingSize - (LONG_BUFFER_SIZE * 8); 3184 iterationNumber++; 3185 } while (remainingSize > -(LONG_BUFFER_SIZE * 8)); 3186 3187 isValueChanged = true; 3188 } 3189 else if (dname == 'F') { 3190 long datasetFloatSize = datasetSize * 4; 3191 byteBuffer = ByteBuffer.allocate(FLOAT_BUFFER_SIZE * 4); 3192 if (binaryOrder == 1) 3193 byteBuffer.order(ByteOrder.nativeOrder()); 3194 else if (binaryOrder == 2) 3195 byteBuffer.order(ByteOrder.LITTLE_ENDIAN); 3196 else if (binaryOrder == 3) byteBuffer.order(ByteOrder.BIG_ENDIAN); 3197 3198 int bufferSize = (int) Math.min(fileSize, datasetFloatSize); 3199 int remainingSize = bufferSize - (FLOAT_BUFFER_SIZE * 4); 3200 int allocValue = 0; 3201 int iterationNumber = 0; 3202 FloatBuffer fb = byteBuffer.asFloatBuffer(); 3203 float[] floatArray = new float[FLOAT_BUFFER_SIZE]; 3204 do { 3205 if (remainingSize <= 0) { 3206 allocValue = remainingSize + (FLOAT_BUFFER_SIZE * 4); 3207 } 3208 else { 3209 allocValue = (FLOAT_BUFFER_SIZE * 4); 3210 } 3211 3212 in.read(byteBuffer.array(), 0, allocValue); 3213 fb.get(floatArray, 0, allocValue / 4); 3214 System.arraycopy(floatArray, 0, dataValue, (iterationNumber * FLOAT_BUFFER_SIZE), allocValue / 4); 3215 byteBuffer.clear(); 3216 fb.clear(); 3217 remainingSize = remainingSize - (FLOAT_BUFFER_SIZE * 4); 3218 iterationNumber++; 3219 } while (remainingSize > -(FLOAT_BUFFER_SIZE * 4)); 3220 3221 isValueChanged = true; 3222 } 3223 else if (dname == 'D') { 3224 long datasetDoubleSize = datasetSize * 8; 3225 byteBuffer = ByteBuffer.allocate(DOUBLE_BUFFER_SIZE * 8); 3226 if (binaryOrder == 1) 3227 byteBuffer.order(ByteOrder.nativeOrder()); 3228 else if (binaryOrder == 2) 3229 byteBuffer.order(ByteOrder.LITTLE_ENDIAN); 3230 else if (binaryOrder == 3) byteBuffer.order(ByteOrder.BIG_ENDIAN); 3231 3232 int bufferSize = (int) Math.min(fileSize, datasetDoubleSize); 3233 int remainingSize = bufferSize - (DOUBLE_BUFFER_SIZE * 8); 3234 int allocValue = 0; 3235 int iterationNumber = 0; 3236 DoubleBuffer db = byteBuffer.asDoubleBuffer(); 3237 double[] doubleArray = new double[DOUBLE_BUFFER_SIZE]; 3238 3239 do { 3240 if (remainingSize <= 0) { 3241 allocValue = remainingSize + (DOUBLE_BUFFER_SIZE * 8); 3242 } 3243 else { 3244 allocValue = (DOUBLE_BUFFER_SIZE * 8); 3245 } 3246 3247 in.read(byteBuffer.array(), 0, allocValue); 3248 db.get(doubleArray, 0, allocValue / 8); 3249 System.arraycopy(doubleArray, 0, dataValue, (iterationNumber * DOUBLE_BUFFER_SIZE), allocValue / 8); 3250 byteBuffer.clear(); 3251 db.clear(); 3252 remainingSize = remainingSize - (DOUBLE_BUFFER_SIZE * 8); 3253 iterationNumber++; 3254 } while (remainingSize > -(DOUBLE_BUFFER_SIZE * 8)); 3255 3256 isValueChanged = true; 3257 3258 } 3259 3260 } 3261 catch (Exception es) { 3262 es.printStackTrace(); 3263 } 3264 finally { 3265 try { 3266 in.close(); 3267 inputFile.close(); 3268 } 3269 catch (IOException ex) { 3270 log.debug("close binary file {}:", fname, ex); 3271 } 3272 } 3273 table.updateUI(); 3274 } 3275 3276 /** Save data as text. */ 3277 private void saveAsText ( ) throws Exception { 3278 final JFileChooser fchooser = new JFileChooser(dataset.getFile()); 3279 fchooser.setFileFilter(DefaultFileFilter.getFileFilterText()); 3280 // fchooser.changeToParentDirectory(); 3281 fchooser.setDialogTitle("Save Current Data To Text File --- " + dataset.getName()); 3282 3283 File choosedFile = new File(dataset.getName() + ".txt"); 3284 3285 fchooser.setSelectedFile(choosedFile); 3286 int returnVal = fchooser.showSaveDialog(this); 3287 3288 if (returnVal != JFileChooser.APPROVE_OPTION) { 3289 return; 3290 } 3291 3292 choosedFile = fchooser.getSelectedFile(); 3293 if (choosedFile == null) { 3294 return; 3295 } 3296 String fname = choosedFile.getAbsolutePath(); 3297 log.trace("DefaultTableView saveAsText: file={}", fname); 3298 3299 // check if the file is in use 3300 List<?> fileList = viewer.getTreeView().getCurrentFiles(); 3301 if (fileList != null) { 3302 FileFormat theFile = null; 3303 Iterator<?> iterator = fileList.iterator(); 3304 while (iterator.hasNext()) { 3305 theFile = (FileFormat) iterator.next(); 3306 if (theFile.getFilePath().equals(fname)) { 3307 toolkit.beep(); 3308 JOptionPane.showMessageDialog(this, "Unable to save data to file \"" + fname + "\". \nThe file is being used.", 3309 getTitle(), JOptionPane.ERROR_MESSAGE); 3310 return; 3311 } 3312 } 3313 } 3314 3315 if (choosedFile.exists()) { 3316 int newFileFlag = JOptionPane.showConfirmDialog(this, "File exists. Do you want to replace it?", this.getTitle(), 3317 JOptionPane.YES_NO_OPTION); 3318 if (newFileFlag == JOptionPane.NO_OPTION) { 3319 return; 3320 } 3321 } 3322 3323 PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(choosedFile))); 3324 3325 String delName = ViewProperties.getDataDelimiter(); 3326 String delimiter = ""; 3327 3328 // delimiter must include a tab to be consistent with copy/paste for 3329 // compound fields 3330 if (dataset instanceof CompoundDS) delimiter = "\t"; 3331 3332 if (delName.equalsIgnoreCase(ViewProperties.DELIMITER_TAB)) { 3333 delimiter = "\t"; 3334 } 3335 else if (delName.equalsIgnoreCase(ViewProperties.DELIMITER_SPACE)) { 3336 delimiter = " " + delimiter; 3337 } 3338 else if (delName.equalsIgnoreCase(ViewProperties.DELIMITER_COMMA)) { 3339 delimiter = "," + delimiter; 3340 } 3341 else if (delName.equalsIgnoreCase(ViewProperties.DELIMITER_COLON)) { 3342 delimiter = ":" + delimiter; 3343 } 3344 else if (delName.equalsIgnoreCase(ViewProperties.DELIMITER_SEMI_COLON)) { 3345 delimiter = ";" + delimiter; 3346 } 3347 3348 int cols = table.getColumnCount(); 3349 int rows = table.getRowCount(); 3350 3351 for (int i = 0; i < rows; i++) { 3352 out.print(table.getValueAt(i, 0)); 3353 for (int j = 1; j < cols; j++) { 3354 out.print(delimiter); 3355 out.print(table.getValueAt(i, j)); 3356 } 3357 out.println(); 3358 } 3359 3360 out.flush(); 3361 out.close(); 3362 3363 viewer.showStatus("Data save to: " + fname); 3364 } 3365 3366 /** Save data as binary. */ 3367 private void saveAsBinary ( ) throws Exception { 3368 final JFileChooser fchooser = new JFileChooser(dataset.getFile()); 3369 fchooser.setFileFilter(DefaultFileFilter.getFileFilterBinary()); 3370 // fchooser.changeToParentDirectory(); 3371 fchooser.setDialogTitle("Save Current Data To Binary File --- " + dataset.getName()); 3372 3373 File choosedFile = new File(dataset.getName() + ".bin"); 3374 fchooser.setSelectedFile(choosedFile); 3375 int returnVal = fchooser.showSaveDialog(this); 3376 3377 if (returnVal != JFileChooser.APPROVE_OPTION) { 3378 return; 3379 } 3380 3381 choosedFile = fchooser.getSelectedFile(); 3382 if (choosedFile == null) { 3383 return; 3384 } 3385 String fname = choosedFile.getAbsolutePath(); 3386 log.trace("DefaultTableView saveAsBinary: file={}", fname); 3387 3388 // check if the file is in use 3389 List<?> fileList = viewer.getTreeView().getCurrentFiles(); 3390 if (fileList != null) { 3391 FileFormat theFile = null; 3392 Iterator<?> iterator = fileList.iterator(); 3393 while (iterator.hasNext()) { 3394 theFile = (FileFormat) iterator.next(); 3395 if (theFile.getFilePath().equals(fname)) { 3396 toolkit.beep(); 3397 JOptionPane.showMessageDialog(this, "Unable to save data to file \"" + fname + "\". \nThe file is being used.", 3398 getTitle(), JOptionPane.ERROR_MESSAGE); 3399 return; 3400 } 3401 } 3402 } 3403 3404 // check if the file exists 3405 if (choosedFile.exists()) { 3406 int newFileFlag = JOptionPane.showConfirmDialog(this, "File exists. Do you want to replace it?", this.getTitle(), 3407 JOptionPane.YES_NO_OPTION); 3408 if (newFileFlag == JOptionPane.NO_OPTION) { 3409 return; 3410 } 3411 } 3412 3413 FileOutputStream outputFile = new FileOutputStream(choosedFile); 3414 DataOutputStream out = new DataOutputStream(outputFile); 3415 3416 if (dataset instanceof ScalarDS) { 3417 ((ScalarDS) dataset).convertToUnsignedC(); 3418 Object data = dataset.getData(); 3419 String cname = data.getClass().getName(); 3420 char dname = cname.charAt(cname.lastIndexOf("[") + 1); 3421 ByteBuffer bb = null; 3422 3423 int size = Array.getLength(data); 3424 3425 if (dname == 'B') { 3426 byte[] bdata = new byte[size]; 3427 bdata = (byte[]) data; 3428 3429 bb = ByteBuffer.allocate(BYTE_BUFFER_SIZE); 3430 if (binaryOrder == 1) 3431 bb.order(ByteOrder.nativeOrder()); 3432 else if (binaryOrder == 2) 3433 bb.order(ByteOrder.LITTLE_ENDIAN); 3434 else if (binaryOrder == 3) bb.order(ByteOrder.BIG_ENDIAN); 3435 3436 int remainingSize = size - BYTE_BUFFER_SIZE; 3437 int allocValue = 0; 3438 int iterationNumber = 0; 3439 do { 3440 if (remainingSize <= 0) { 3441 allocValue = remainingSize + BYTE_BUFFER_SIZE; 3442 } 3443 else { 3444 allocValue = BYTE_BUFFER_SIZE; 3445 } 3446 bb.clear(); 3447 bb.put(bdata, (iterationNumber * BYTE_BUFFER_SIZE), allocValue); 3448 out.write(bb.array(), 0, allocValue); 3449 remainingSize = remainingSize - BYTE_BUFFER_SIZE; 3450 iterationNumber++; 3451 } while (remainingSize > -BYTE_BUFFER_SIZE); 3452 3453 out.flush(); 3454 out.close(); 3455 } 3456 else if (dname == 'S') { 3457 short[] sdata = new short[size]; 3458 sdata = (short[]) data; 3459 bb = ByteBuffer.allocate(SHORT_BUFFER_SIZE * 2); 3460 if (binaryOrder == 1) 3461 bb.order(ByteOrder.nativeOrder()); 3462 else if (binaryOrder == 2) 3463 bb.order(ByteOrder.LITTLE_ENDIAN); 3464 else if (binaryOrder == 3) bb.order(ByteOrder.BIG_ENDIAN); 3465 3466 ShortBuffer sb = bb.asShortBuffer(); 3467 int remainingSize = size - SHORT_BUFFER_SIZE; 3468 int allocValue = 0; 3469 int iterationNumber = 0; 3470 do { 3471 if (remainingSize <= 0) { 3472 allocValue = remainingSize + SHORT_BUFFER_SIZE; 3473 } 3474 else { 3475 allocValue = SHORT_BUFFER_SIZE; 3476 } 3477 bb.clear(); 3478 sb.clear(); 3479 sb.put(sdata, (iterationNumber * SHORT_BUFFER_SIZE), allocValue); 3480 out.write(bb.array(), 0, allocValue * 2); 3481 remainingSize = remainingSize - SHORT_BUFFER_SIZE; 3482 iterationNumber++; 3483 } while (remainingSize > -SHORT_BUFFER_SIZE); 3484 3485 out.flush(); 3486 out.close(); 3487 } 3488 else if (dname == 'I') { 3489 int[] idata = new int[size]; 3490 idata = (int[]) data; 3491 bb = ByteBuffer.allocate(INT_BUFFER_SIZE * 4); 3492 if (binaryOrder == 1) 3493 bb.order(ByteOrder.nativeOrder()); 3494 else if (binaryOrder == 2) 3495 bb.order(ByteOrder.LITTLE_ENDIAN); 3496 else if (binaryOrder == 3) bb.order(ByteOrder.BIG_ENDIAN); 3497 3498 IntBuffer ib = bb.asIntBuffer(); 3499 int remainingSize = size - INT_BUFFER_SIZE; 3500 int allocValue = 0; 3501 int iterationNumber = 0; 3502 do { 3503 if (remainingSize <= 0) { 3504 allocValue = remainingSize + INT_BUFFER_SIZE; 3505 } 3506 else { 3507 allocValue = INT_BUFFER_SIZE; 3508 } 3509 bb.clear(); 3510 ib.clear(); 3511 ib.put(idata, (iterationNumber * INT_BUFFER_SIZE), allocValue); 3512 out.write(bb.array(), 0, allocValue * 4); 3513 remainingSize = remainingSize - INT_BUFFER_SIZE; 3514 iterationNumber++; 3515 } while (remainingSize > -INT_BUFFER_SIZE); 3516 3517 out.flush(); 3518 out.close(); 3519 } 3520 else if (dname == 'J') { 3521 long[] ldata = new long[size]; 3522 ldata = (long[]) data; 3523 3524 bb = ByteBuffer.allocate(LONG_BUFFER_SIZE * 8); 3525 if (binaryOrder == 1) 3526 bb.order(ByteOrder.nativeOrder()); 3527 else if (binaryOrder == 2) 3528 bb.order(ByteOrder.LITTLE_ENDIAN); 3529 else if (binaryOrder == 3) bb.order(ByteOrder.BIG_ENDIAN); 3530 3531 LongBuffer lb = bb.asLongBuffer(); 3532 int remainingSize = size - LONG_BUFFER_SIZE; 3533 int allocValue = 0; 3534 int iterationNumber = 0; 3535 do { 3536 if (remainingSize <= 0) { 3537 allocValue = remainingSize + LONG_BUFFER_SIZE; 3538 } 3539 else { 3540 allocValue = LONG_BUFFER_SIZE; 3541 } 3542 bb.clear(); 3543 lb.clear(); 3544 lb.put(ldata, (iterationNumber * LONG_BUFFER_SIZE), allocValue); 3545 out.write(bb.array(), 0, allocValue * 8); 3546 remainingSize = remainingSize - LONG_BUFFER_SIZE; 3547 iterationNumber++; 3548 } while (remainingSize > -LONG_BUFFER_SIZE); 3549 3550 out.flush(); 3551 out.close(); 3552 } 3553 else if (dname == 'F') { 3554 float[] fdata = new float[size]; 3555 fdata = (float[]) data; 3556 3557 bb = ByteBuffer.allocate(FLOAT_BUFFER_SIZE * 4); 3558 if (binaryOrder == 1) 3559 bb.order(ByteOrder.nativeOrder()); 3560 else if (binaryOrder == 2) 3561 bb.order(ByteOrder.LITTLE_ENDIAN); 3562 else if (binaryOrder == 3) bb.order(ByteOrder.BIG_ENDIAN); 3563 3564 FloatBuffer fb = bb.asFloatBuffer(); 3565 int remainingSize = size - FLOAT_BUFFER_SIZE; 3566 int allocValue = 0; 3567 int iterationNumber = 0; 3568 do { 3569 if (remainingSize <= 0) { 3570 allocValue = remainingSize + FLOAT_BUFFER_SIZE; 3571 } 3572 else { 3573 allocValue = FLOAT_BUFFER_SIZE; 3574 } 3575 bb.clear(); 3576 fb.clear(); 3577 fb.put(fdata, (iterationNumber * FLOAT_BUFFER_SIZE), allocValue); 3578 out.write(bb.array(), 0, allocValue * 4); 3579 remainingSize = remainingSize - FLOAT_BUFFER_SIZE; 3580 iterationNumber++; 3581 } while (remainingSize > -FLOAT_BUFFER_SIZE); 3582 3583 out.flush(); 3584 out.close(); 3585 } 3586 else if (dname == 'D') { 3587 double[] ddata = new double[size]; 3588 ddata = (double[]) data; 3589 3590 bb = ByteBuffer.allocate(DOUBLE_BUFFER_SIZE * 8); 3591 if (binaryOrder == 1) 3592 bb.order(ByteOrder.nativeOrder()); 3593 else if (binaryOrder == 2) 3594 bb.order(ByteOrder.LITTLE_ENDIAN); 3595 else if (binaryOrder == 3) bb.order(ByteOrder.BIG_ENDIAN); 3596 3597 DoubleBuffer db = bb.asDoubleBuffer(); 3598 int remainingSize = size - DOUBLE_BUFFER_SIZE; 3599 int allocValue = 0; 3600 int iterationNumber = 0; 3601 do { 3602 if (remainingSize <= 0) { 3603 allocValue = remainingSize + DOUBLE_BUFFER_SIZE; 3604 } 3605 else { 3606 allocValue = DOUBLE_BUFFER_SIZE; 3607 } 3608 bb.clear(); 3609 db.clear(); 3610 db.put(ddata, (iterationNumber * DOUBLE_BUFFER_SIZE), allocValue); 3611 out.write(bb.array(), 0, allocValue * 8); 3612 remainingSize = remainingSize - DOUBLE_BUFFER_SIZE; 3613 iterationNumber++; 3614 } while (remainingSize > -DOUBLE_BUFFER_SIZE); 3615 3616 out.flush(); 3617 out.close(); 3618 } 3619 } 3620 3621 viewer.showStatus("Data save to: " + fname); 3622 } 3623 3624 /** 3625 * update dataset value in file. The change will go to file. 3626 */ 3627 @Override 3628 public void updateValueInFile ( ) { 3629 log.trace("DefaultTableView updateValueInFile enter"); 3630 if (isReadOnly || showAsBin || showAsHex) { 3631 return; 3632 } 3633 3634 if (!isValueChanged) { 3635 return; 3636 } 3637 3638 try { 3639 log.trace("DefaultTableView updateValueInFile write"); 3640 dataset.write(); 3641 } 3642 catch (Exception ex) { 3643 toolkit.beep(); 3644 JOptionPane.showMessageDialog(this, ex, getTitle(), JOptionPane.ERROR_MESSAGE); 3645 return; 3646 } 3647 3648 isValueChanged = false; 3649 log.trace("DefaultTableView updateValueInFile exit"); 3650 } 3651 3652 /** 3653 * Selects all rows, columns, and cells in the table. 3654 */ 3655 private void selectAll ( ) throws Exception { 3656 table.selectAll(); 3657 } 3658 3659 /** 3660 * Converting selected data based on predefined math functions. 3661 */ 3662 private void mathConversion ( ) throws Exception { 3663 if (isReadOnly) { 3664 return; 3665 } 3666 3667 int cols = table.getSelectedColumnCount(); 3668 // if (!(dataset instanceof ScalarDS)) return; 3669 if ((dataset instanceof CompoundDS) && (cols > 1)) { 3670 toolkit.beep(); 3671 JOptionPane.showMessageDialog(this, "Please select one colunm a time for math conversion for compound dataset.", 3672 getTitle(), JOptionPane.ERROR_MESSAGE); 3673 return; 3674 } 3675 3676 Object theData = getSelectedData(); 3677 if (theData == null) { 3678 toolkit.beep(); 3679 JOptionPane.showMessageDialog(this, "No data is selected.", getTitle(), JOptionPane.ERROR_MESSAGE); 3680 return; 3681 } 3682 3683 MathConversionDialog dialog = new MathConversionDialog((JFrame) viewer, theData); 3684 dialog.setVisible(true); 3685 3686 if (dialog.isConverted()) { 3687 if (dataset instanceof CompoundDS) { 3688 Object colData = null; 3689 try { 3690 colData = ((List<?>) dataset.getData()).get(table.getSelectedColumn()); 3691 } 3692 catch (Exception ex) { 3693 log.debug("colData:", ex); 3694 } 3695 3696 if (colData != null) { 3697 int size = Array.getLength(theData); 3698 System.arraycopy(theData, 0, colData, 0, size); 3699 } 3700 } 3701 else { 3702 int rows = table.getSelectedRowCount(); 3703 int r0 = table.getSelectedRow(); 3704 int c0 = table.getSelectedColumn(); 3705 int w = table.getColumnCount(); 3706 int idx_src = 0; 3707 int idx_dst = 0; 3708 for (int i = 0; i < rows; i++) { 3709 idx_dst = (r0 + i) * w + c0; 3710 System.arraycopy(theData, idx_src, dataValue, idx_dst, cols); 3711 idx_src += cols; 3712 } 3713 } 3714 3715 theData = null; 3716 System.gc(); 3717 table.updateUI(); 3718 isValueChanged = true; 3719 } 3720 3721 } 3722 3723 /** 3724 * update cell value in memory. It does not change the dataset value in file. 3725 * 3726 * @param cellValue 3727 * the string value of input. 3728 * @param row 3729 * the row of the editing cell. 3730 * @param col 3731 * the column of the editing cell. 3732 */ 3733 private void updateValueInMemory (String cellValue, int row, int col) throws Exception { 3734 log.trace("DefaultTableView updateValueInMemory"); 3735 if (currentEditingCellValue != null) { 3736 // data values are the same, no need to change the data 3737 if (currentEditingCellValue.toString().equals(cellValue)) return; 3738 } 3739 3740 if (dataset instanceof ScalarDS) { 3741 updateScalarData(cellValue, row, col); 3742 } 3743 else if (dataset instanceof CompoundDS) { 3744 updateCompoundData(cellValue, row, col); 3745 } 3746 } 3747 3748 /** 3749 * update cell value in memory. It does not change the dataset value in file. 3750 * 3751 * @param cellValue 3752 * the string value of input. 3753 * @param row 3754 * the row of the editing cell. 3755 * @param col 3756 * the column of the editing cell. 3757 */ 3758 private void updateScalarData (String cellValue, int row, int col) throws Exception { 3759 if (!(dataset instanceof ScalarDS) || (cellValue == null) || ((cellValue = cellValue.trim()) == null) || showAsBin 3760 || showAsHex) { 3761 return; 3762 } 3763 3764 int i = 0; 3765 if (isDataTransposed) { 3766 i = col * table.getRowCount() + row; 3767 } 3768 else { 3769 i = row * table.getColumnCount() + col; 3770 } 3771 log.trace("DefaultTableView updateScalarData {} NT={}", cellValue, NT); 3772 3773 ScalarDS sds = (ScalarDS) dataset; 3774 boolean isUnsigned = sds.isUnsigned(); 3775 String cname = dataset.getOriginalClass().getName(); 3776 char dname = cname.charAt(cname.lastIndexOf("[") + 1); 3777 log.trace("updateScalarData isUnsigned={} cname={} dname={}", isUnsigned, cname, dname); 3778 3779 // check data range for unsigned datatype converted sizes! 3780 if (isUnsigned) { 3781 long lvalue = -1; 3782 long maxValue = Long.MAX_VALUE; 3783 if (dname == 'B') { 3784 maxValue = 255; 3785 lvalue = Long.parseLong(cellValue); 3786 3787 if (lvalue < 0) { 3788 throw new NumberFormatException("Negative value for unsigned integer: " + lvalue); 3789 } 3790 3791 if (lvalue > maxValue) { 3792 throw new NumberFormatException("Data value is out of range: " + lvalue); 3793 } 3794 } 3795 else if (dname == 'S') { 3796 maxValue = 65535; 3797 lvalue = Long.parseLong(cellValue); 3798 3799 if (lvalue < 0) { 3800 throw new NumberFormatException("Negative value for unsigned integer: " + lvalue); 3801 } 3802 3803 if (lvalue > maxValue) { 3804 throw new NumberFormatException("Data value is out of range: " + lvalue); 3805 } 3806 } 3807 else if (dname == 'I') { 3808 maxValue = 4294967295L; 3809 lvalue = Long.parseLong(cellValue); 3810 3811 if (lvalue < 0) { 3812 throw new NumberFormatException("Negative value for unsigned integer: " + lvalue); 3813 } 3814 3815 if (lvalue > maxValue) { 3816 throw new NumberFormatException("Data value is out of range: " + lvalue); 3817 } 3818 } 3819 else if (dname == 'J') { 3820 BigInteger Jmax = new BigInteger("18446744073709551615"); 3821 BigInteger big = new BigInteger(cellValue); 3822 if (big.compareTo(Jmax) > 0) { 3823 throw new NumberFormatException("Negative value for unsigned integer: " + cellValue); 3824 } 3825 if (big.compareTo(BigInteger.ZERO) < 0) { 3826 throw new NumberFormatException("Data value is out of range: " + cellValue); 3827 } 3828 } 3829 } 3830 3831 switch (NT) { 3832 case 'B': 3833 byte bvalue = 0; 3834 bvalue = Byte.parseByte(cellValue); 3835 Array.setByte(dataValue, i, bvalue); 3836 break; 3837 case 'S': 3838 short svalue = 0; 3839 svalue = Short.parseShort(cellValue); 3840 Array.setShort(dataValue, i, svalue); 3841 break; 3842 case 'I': 3843 int ivalue = 0; 3844 ivalue = Integer.parseInt(cellValue); 3845 Array.setInt(dataValue, i, ivalue); 3846 break; 3847 case 'J': 3848 long lvalue = 0; 3849 if (dname == 'J') { 3850 BigInteger big = new BigInteger(cellValue); 3851 lvalue = big.longValue(); 3852 } 3853 else 3854 lvalue = Long.parseLong(cellValue); 3855 Array.setLong(dataValue, i, lvalue); 3856 break; 3857 case 'F': 3858 float fvalue = 0; 3859 fvalue = Float.parseFloat(cellValue); 3860 Array.setFloat(dataValue, i, fvalue); 3861 break; 3862 case 'D': 3863 double dvalue = 0; 3864 dvalue = Double.parseDouble(cellValue); 3865 Array.setDouble(dataValue, i, dvalue); 3866 break; 3867 default: 3868 Array.set(dataValue, i, cellValue); 3869 break; 3870 } 3871 3872 isValueChanged = true; 3873 } 3874 3875 private void updateCompoundData (String cellValue, int row, int col) throws Exception { 3876 if (!(dataset instanceof CompoundDS) || (cellValue == null) || ((cellValue = cellValue.trim()) == null)) { 3877 return; 3878 } 3879 log.trace("DefaultTableView updateCompoundData"); 3880 3881 CompoundDS compDS = (CompoundDS) dataset; 3882 List<?> cdata = (List<?>) compDS.getData(); 3883 int orders[] = compDS.getSelectedMemberOrders(); 3884 Datatype types[] = compDS.getSelectedMemberTypes(); 3885 int nFields = cdata.size(); 3886 int nSubColumns = table.getColumnCount() / nFields; 3887 table.getRowCount(); 3888 int column = col; 3889 int offset = 0; 3890 int morder = 1; 3891 3892 if (nSubColumns > 1) { // multi-dimension compound dataset 3893 int colIdx = col / nFields; 3894 column = col - colIdx * nFields; 3895 // //BUG 573: offset = row * orders[column] + colIdx * nRows * 3896 // orders[column]; 3897 offset = row * orders[column] * nSubColumns + colIdx * orders[column]; 3898 } 3899 else { 3900 offset = row * orders[column]; 3901 } 3902 morder = orders[column]; 3903 3904 Object mdata = cdata.get(column); 3905 3906 // strings 3907 if (Array.get(mdata, 0) instanceof String) { 3908 Array.set(mdata, offset, cellValue); 3909 isValueChanged = true; 3910 return; 3911 } 3912 else if (types[column].getDatatypeClass() == Datatype.CLASS_STRING) { 3913 // it is string but not converted, still byte array 3914 int strlen = types[column].getDatatypeSize(); 3915 offset *= strlen; 3916 byte[] bytes = cellValue.getBytes(); 3917 byte[] bData = (byte[]) mdata; 3918 int n = Math.min(strlen, bytes.length); 3919 System.arraycopy(bytes, 0, bData, offset, n); 3920 offset += n; 3921 n = strlen - bytes.length; 3922 // space padding 3923 for (int i = 0; i < n; i++) { 3924 bData[offset + i] = ' '; 3925 } 3926 isValueChanged = true; 3927 return; 3928 } 3929 3930 // Numeric data 3931 char mNT = ' '; 3932 String cName = mdata.getClass().getName(); 3933 int cIndex = cName.lastIndexOf("["); 3934 if (cIndex >= 0) { 3935 mNT = cName.charAt(cIndex + 1); 3936 } 3937 3938 StringTokenizer st = new StringTokenizer(cellValue, ","); 3939 if (st.countTokens() < morder) { 3940 toolkit.beep(); 3941 JOptionPane.showMessageDialog(this, "Number of data point < " + morder + ".", getTitle(), JOptionPane.ERROR_MESSAGE); 3942 return; 3943 } 3944 3945 String token = ""; 3946 isValueChanged = true; 3947 switch (mNT) { 3948 case 'B': 3949 byte bvalue = 0; 3950 for (int i = 0; i < morder; i++) { 3951 token = st.nextToken().trim(); 3952 bvalue = Byte.parseByte(token); 3953 Array.setByte(mdata, offset + i, bvalue); 3954 } 3955 break; 3956 case 'S': 3957 short svalue = 0; 3958 for (int i = 0; i < morder; i++) { 3959 token = st.nextToken().trim(); 3960 svalue = Short.parseShort(token); 3961 Array.setShort(mdata, offset + i, svalue); 3962 } 3963 break; 3964 case 'I': 3965 int ivalue = 0; 3966 for (int i = 0; i < morder; i++) { 3967 token = st.nextToken().trim(); 3968 ivalue = Integer.parseInt(token); 3969 Array.setInt(mdata, offset + i, ivalue); 3970 } 3971 break; 3972 case 'J': 3973 long lvalue = 0; 3974 for (int i = 0; i < morder; i++) { 3975 token = st.nextToken().trim(); 3976 BigInteger big = new BigInteger(token); 3977 lvalue = big.longValue(); 3978 // lvalue = Long.parseLong(token); 3979 Array.setLong(mdata, offset + i, lvalue); 3980 } 3981 break; 3982 case 'F': 3983 float fvalue = 0; 3984 for (int i = 0; i < morder; i++) { 3985 token = st.nextToken().trim(); 3986 fvalue = Float.parseFloat(token); 3987 Array.setFloat(mdata, offset + i, fvalue); 3988 } 3989 break; 3990 case 'D': 3991 double dvalue = 0; 3992 for (int i = 0; i < morder; i++) { 3993 token = st.nextToken().trim(); 3994 dvalue = Double.parseDouble(token); 3995 Array.setDouble(mdata, offset + i, dvalue); 3996 } 3997 break; 3998 default: 3999 isValueChanged = false; 4000 } 4001 } 4002 4003 private class LineplotOption extends JDialog implements ActionListener, ItemListener { 4004 private static final long serialVersionUID = -3457035832213978906L; 4005 public static final int NO_PLOT = -1; 4006 public static final int ROW_PLOT = 0; 4007 public static final int COLUMN_PLOT = 1; 4008 4009 private int idx_xaxis = -1, plotType = -1; 4010 private JRadioButton rowButton, colButton; 4011 @SuppressWarnings("rawtypes") 4012 private JComboBox rowBox, colBox; 4013 4014 @SuppressWarnings({ "rawtypes", "unchecked" }) 4015 public LineplotOption(JFrame owner, String title, int nrow, int ncol) { 4016 super(owner, title, true); 4017 4018 rowBox = new JComboBox(); 4019 rowBox.setEditable(false); 4020 colBox = new JComboBox(); 4021 colBox.setEditable(false); 4022 4023 JPanel contentPane = (JPanel) this.getContentPane(); 4024 contentPane.setPreferredSize(new Dimension(400, 150)); 4025 contentPane.setLayout(new BorderLayout(10, 10)); 4026 4027 long[] startArray = dataset.getStartDims(); 4028 long[] strideArray = dataset.getStride(); 4029 int[] selectedIndex = dataset.getSelectedIndex(); 4030 int start = (int) startArray[selectedIndex[0]]; 4031 int stride = (int) strideArray[selectedIndex[0]]; 4032 4033 rowBox.addItem("array index"); 4034 for (int i = 0; i < nrow; i++) { 4035 rowBox.addItem("row " + (start + indexBase + i * stride)); 4036 } 4037 4038 colBox.addItem("array index"); 4039 for (int i = 0; i < ncol; i++) { 4040 colBox.addItem("column " + table.getColumnName(i)); 4041 } 4042 4043 rowButton = new JRadioButton("Row"); 4044 colButton = new JRadioButton("Column", true); 4045 rowButton.addItemListener(this); 4046 colButton.addItemListener(this); 4047 ButtonGroup rgroup = new ButtonGroup(); 4048 rgroup.add(rowButton); 4049 rgroup.add(colButton); 4050 4051 JPanel p1 = new JPanel(); 4052 p1.setLayout(new GridLayout(2, 1, 5, 5)); 4053 p1.add(new JLabel(" Series in:", SwingConstants.RIGHT)); 4054 p1.add(new JLabel(" For abscissa use:", SwingConstants.RIGHT)); 4055 4056 JPanel p2 = new JPanel(); 4057 p2.setLayout(new GridLayout(2, 1, 5, 5)); 4058 // p2.setBorder(new LineBorder(Color.lightGray)); 4059 p2.add(colButton); 4060 p2.add(colBox); 4061 4062 JPanel p3 = new JPanel(); 4063 p3.setLayout(new GridLayout(2, 1, 5, 5)); 4064 // p3.setBorder(new LineBorder(Color.lightGray)); 4065 p3.add(rowButton); 4066 p3.add(rowBox); 4067 4068 JPanel p = new JPanel(); 4069 p.setBorder(new LineBorder(Color.lightGray)); 4070 p.setLayout(new GridLayout(1, 3, 20, 5)); 4071 p.add(p1); 4072 p.add(p2); 4073 p.add(p3); 4074 4075 JPanel bp = new JPanel(); 4076 4077 JButton okButton = new JButton("Ok"); 4078 okButton.addActionListener(this); 4079 okButton.setActionCommand("Ok"); 4080 bp.add(okButton); 4081 4082 JButton cancelButton = new JButton("Cancel"); 4083 cancelButton.addActionListener(this); 4084 cancelButton.setActionCommand("Cancel"); 4085 bp.add(cancelButton); 4086 4087 contentPane.add(new JLabel(" Select plot options:"), BorderLayout.NORTH); 4088 contentPane.add(p, BorderLayout.CENTER); 4089 contentPane.add(bp, BorderLayout.SOUTH); 4090 4091 colBox.setEnabled(colButton.isSelected()); 4092 rowBox.setEnabled(rowButton.isSelected()); 4093 4094 Point l = getParent().getLocation(); 4095 l.x += 450; 4096 l.y += 200; 4097 setLocation(l); 4098 pack(); 4099 } 4100 4101 int getXindex ( ) { 4102 return idx_xaxis; 4103 } 4104 4105 int getPlotBy ( ) { 4106 return plotType; 4107 } 4108 4109 @Override 4110 public void actionPerformed (ActionEvent e) { 4111 e.getSource(); 4112 String cmd = e.getActionCommand(); 4113 4114 if (cmd.equals("Cancel")) { 4115 plotType = NO_PLOT; 4116 this.dispose(); // terminate the application 4117 } 4118 else if (cmd.equals("Ok")) { 4119 if (colButton.isSelected()) { 4120 idx_xaxis = colBox.getSelectedIndex() - 1; 4121 plotType = COLUMN_PLOT; 4122 } 4123 else { 4124 idx_xaxis = rowBox.getSelectedIndex() - 1; 4125 plotType = ROW_PLOT; 4126 } 4127 4128 this.dispose(); // terminate the application 4129 } 4130 } 4131 4132 @Override 4133 public void itemStateChanged (ItemEvent e) { 4134 Object source = e.getSource(); 4135 4136 if (source.equals(colButton) || source.equals(rowButton)) { 4137 colBox.setEnabled(colButton.isSelected()); 4138 rowBox.setEnabled(rowButton.isSelected()); 4139 } 4140 } 4141 } 4142 4143 private class ColumnHeader extends JTableHeader { 4144 private static final long serialVersionUID = -3179653809792147055L; 4145 private int currentColumnIndex = -1; 4146 private int lastColumnIndex = -1; 4147 private JTable parentTable; 4148 4149 public ColumnHeader(JTable theTable) { 4150 super(theTable.getColumnModel()); 4151 4152 parentTable = theTable; 4153 setReorderingAllowed(false); 4154 } 4155 4156 @Override 4157 protected void processMouseMotionEvent (MouseEvent e) { 4158 super.processMouseMotionEvent(e); 4159 4160 if (e.getID() == MouseEvent.MOUSE_DRAGGED) { 4161 // do not do anything, just resize the column 4162 if (getResizingColumn() != null) return; 4163 4164 int colEnd = columnAtPoint(e.getPoint()); 4165 4166 if (colEnd < 0) { 4167 colEnd = 0; 4168 } 4169 if (currentColumnIndex < 0) { 4170 currentColumnIndex = 0; 4171 } 4172 4173 parentTable.clearSelection(); 4174 4175 if (colEnd > currentColumnIndex) { 4176 parentTable.setColumnSelectionInterval(currentColumnIndex, colEnd); 4177 } 4178 else { 4179 parentTable.setColumnSelectionInterval(colEnd, currentColumnIndex); 4180 } 4181 4182 parentTable.setRowSelectionInterval(0, parentTable.getRowCount() - 1); 4183 } 4184 } 4185 4186 @Override 4187 protected void processMouseEvent (MouseEvent e) { 4188 super.processMouseEvent(e); 4189 4190 int mouseID = e.getID(); 4191 4192 if (mouseID == MouseEvent.MOUSE_CLICKED) { 4193 if (currentColumnIndex < 0) { 4194 return; 4195 } 4196 4197 if (e.isControlDown()) { 4198 // select discontinuous columns 4199 parentTable.addColumnSelectionInterval(currentColumnIndex, currentColumnIndex); 4200 } 4201 else if (e.isShiftDown()) { 4202 // select continuous columns 4203 if (lastColumnIndex < 0) { 4204 parentTable.addColumnSelectionInterval(0, currentColumnIndex); 4205 } 4206 else if (lastColumnIndex < currentColumnIndex) { 4207 parentTable.addColumnSelectionInterval(lastColumnIndex, currentColumnIndex); 4208 } 4209 else { 4210 parentTable.addColumnSelectionInterval(currentColumnIndex, lastColumnIndex); 4211 } 4212 } 4213 else { 4214 // clear old selection and set new column selection 4215 parentTable.clearSelection(); 4216 parentTable.setColumnSelectionInterval(currentColumnIndex, currentColumnIndex); 4217 } 4218 4219 lastColumnIndex = currentColumnIndex; 4220 parentTable.setRowSelectionInterval(0, parentTable.getRowCount() - 1); 4221 } 4222 else if (mouseID == MouseEvent.MOUSE_PRESSED) { 4223 currentColumnIndex = columnAtPoint(e.getPoint()); 4224 } 4225 } 4226 } // private class ColumnHeader 4227 4228 /** RowHeader defines the row header component of the Spreadsheet. */ 4229 private class RowHeader extends JTable { 4230 private static final long serialVersionUID = -1548007702499873626L; 4231 private int currentRowIndex = -1; 4232 private int lastRowIndex = -1; 4233 private JTable parentTable; 4234 4235 public RowHeader(JTable pTable, Dataset dset) { 4236 // Create a JTable with the same number of rows as 4237 // the parent table and one column. 4238 // super( pTable.getRowCount(), 1 ); 4239 4240 final long[] startArray = dset.getStartDims(); 4241 final long[] strideArray = dset.getStride(); 4242 final int[] selectedIndex = dset.getSelectedIndex(); 4243 final int start = (int) startArray[selectedIndex[0]]; 4244 final int stride = (int) strideArray[selectedIndex[0]]; 4245 final int rowCount = pTable.getRowCount(); 4246 parentTable = pTable; 4247 4248 AbstractTableModel tm = new AbstractTableModel() { 4249 private static final long serialVersionUID = -8117073107569884677L; 4250 4251 @Override 4252 public int getColumnCount ( ) { 4253 return 1; 4254 } 4255 4256 @Override 4257 public int getRowCount ( ) { 4258 return rowCount; 4259 } 4260 4261 @Override 4262 public String getColumnName (int col) { 4263 return " "; 4264 } 4265 4266 @Override 4267 public Object getValueAt (int row, int column) { 4268 log.trace("RowHeader:AbstractTableModel:getValueAt"); 4269 return String.valueOf(start + indexBase + row * stride); 4270 } 4271 }; 4272 4273 this.setModel(tm); 4274 4275 // Get the only table column. 4276 TableColumn col = getColumnModel().getColumn(0); 4277 4278 // Use the cell renderer in the column. 4279 col.setCellRenderer(new RowHeaderRenderer()); 4280 } 4281 4282 /** Overridden to return false since the headers are not editable. */ 4283 @Override 4284 public boolean isCellEditable (int row, int col) { 4285 return false; 4286 } 4287 4288 /** This is called when the selection changes in the row headers. */ 4289 @Override 4290 public void valueChanged (ListSelectionEvent e) { 4291 if (parentTable == null) { 4292 return; 4293 } 4294 4295 int rows[] = getSelectedRows(); 4296 if ((rows == null) || (rows.length == 0)) { 4297 return; 4298 } 4299 4300 parentTable.clearSelection(); 4301 parentTable.setRowSelectionInterval(rows[0], rows[rows.length - 1]); 4302 parentTable.setColumnSelectionInterval(0, parentTable.getColumnCount() - 1); 4303 } 4304 4305 @Override 4306 protected void processMouseMotionEvent (MouseEvent e) { 4307 if (e.getID() == MouseEvent.MOUSE_DRAGGED) { 4308 int colEnd = rowAtPoint(e.getPoint()); 4309 4310 if (colEnd < 0) { 4311 colEnd = 0; 4312 } 4313 if (currentRowIndex < 0) { 4314 currentRowIndex = 0; 4315 } 4316 4317 parentTable.clearSelection(); 4318 4319 if (colEnd > currentRowIndex) { 4320 parentTable.setRowSelectionInterval(currentRowIndex, colEnd); 4321 } 4322 else { 4323 parentTable.setRowSelectionInterval(colEnd, currentRowIndex); 4324 } 4325 4326 parentTable.setColumnSelectionInterval(0, parentTable.getColumnCount() - 1); 4327 } 4328 } 4329 4330 @Override 4331 protected void processMouseEvent (MouseEvent e) { 4332 int mouseID = e.getID(); 4333 4334 if (mouseID == MouseEvent.MOUSE_CLICKED) { 4335 if (currentRowIndex < 0) { 4336 return; 4337 } 4338 4339 if (e.isControlDown()) { 4340 // select discontinuous rows 4341 parentTable.addRowSelectionInterval(currentRowIndex, currentRowIndex); 4342 } 4343 else if (e.isShiftDown()) { 4344 // select contiguous columns 4345 if (lastRowIndex < 0) { 4346 parentTable.addRowSelectionInterval(0, currentRowIndex); 4347 } 4348 else if (lastRowIndex < currentRowIndex) { 4349 parentTable.addRowSelectionInterval(lastRowIndex, currentRowIndex); 4350 } 4351 else { 4352 parentTable.addRowSelectionInterval(currentRowIndex, lastRowIndex); 4353 } 4354 } 4355 else { 4356 // clear old selection and set new column selection 4357 parentTable.clearSelection(); 4358 parentTable.setRowSelectionInterval(currentRowIndex, currentRowIndex); 4359 } 4360 4361 lastRowIndex = currentRowIndex; 4362 4363 parentTable.setColumnSelectionInterval(0, parentTable.getColumnCount() - 1); 4364 } 4365 else if (mouseID == MouseEvent.MOUSE_PRESSED) { 4366 currentRowIndex = rowAtPoint(e.getPoint()); 4367 } 4368 } 4369 } // private class RowHeader extends JTable 4370 4371 /** 4372 * RowHeaderRenderer is a custom cell renderer that displays cells as buttons. 4373 */ 4374 private class RowHeaderRenderer extends JLabel implements TableCellRenderer { 4375 private static final long serialVersionUID = -8963879626159783226L; 4376 4377 public RowHeaderRenderer( ) { 4378 super(); 4379 setHorizontalAlignment(SwingConstants.CENTER); 4380 4381 setOpaque(true); 4382 setBorder(UIManager.getBorder("TableHeader.cellBorder")); 4383 setBackground(Color.lightGray); 4384 } 4385 4386 /** Configures the button for the current cell, and returns it. */ 4387 @Override 4388 public Component getTableCellRendererComponent (JTable table, Object value, boolean isSelected, boolean hasFocus, int row, 4389 int column) { 4390 setFont(table.getFont()); 4391 4392 if (value != null) { 4393 setText(value.toString()); 4394 } 4395 4396 return this; 4397 } 4398 } // private class RowHeaderRenderer extends JLabel implements 4399 // TableCellRenderer 4400 4401 @SuppressWarnings("rawtypes") 4402 private class MultiLineHeaderRenderer extends JList implements TableCellRenderer { 4403 private static final long serialVersionUID = -3697496960833719169L; 4404 private final CompoundBorder subBorder = new CompoundBorder(new MatteBorder(1, 0, 1, 0, java.awt.Color.darkGray), 4405 new MatteBorder(1, 0, 1, 0, java.awt.Color.white)); 4406 private final CompoundBorder majorBorder = new CompoundBorder(new MatteBorder(1, 1, 1, 0, java.awt.Color.darkGray), 4407 new MatteBorder(1, 2, 1, 0, java.awt.Color.white)); 4408 Vector<String> lines = new Vector<String>(); 4409 int nSubcolumns = 1; 4410 4411 public MultiLineHeaderRenderer(int majorColumns, int subColumns) { 4412 nSubcolumns = subColumns; 4413 setOpaque(true); 4414 setForeground(UIManager.getColor("TableHeader.foreground")); 4415 setBackground(UIManager.getColor("TableHeader.background")); 4416 } 4417 4418 @Override 4419 public Component getTableCellRendererComponent (JTable table, Object value, boolean isSelected, boolean hasFocus, int row, 4420 int column) { 4421 setFont(table.getFont()); 4422 String str = (value == null) ? "" : value.toString(); 4423 BufferedReader br = new BufferedReader(new StringReader(str)); 4424 String line; 4425 4426 lines.clear(); 4427 try { 4428 while ((line = br.readLine()) != null) { 4429 lines.addElement(line); 4430 } 4431 } 4432 catch (IOException ex) { 4433 log.debug("string read:", ex); 4434 } 4435 4436 if ((column / nSubcolumns) * nSubcolumns == column) { 4437 setBorder(majorBorder); 4438 } 4439 else { 4440 setBorder(subBorder); 4441 } 4442 setListData(lines); 4443 4444 return this; 4445 } 4446 } 4447 4448 // //////////////////////////////////////////////////////////////////////// 4449 // // 4450 // The code below was added to deal with region references // 4451 // Peter Cao, 4/30/2009 // 4452 // // 4453 // //////////////////////////////////////////////////////////////////////// 4454 4455 @Override 4456 public void mouseClicked (MouseEvent e) { 4457 // only deal with reg. ref 4458 if (!(isRegRef || isObjRef)) return; 4459 4460 int eMod = e.getModifiers(); 4461 4462 // provide two options here: double click to show data in table, or 4463 // right mouse to choose to show data in table or in image 4464 4465 // right mouse click 4466 if (e.isPopupTrigger() 4467 || (eMod == InputEvent.BUTTON3_MASK) 4468 || (System.getProperty("os.name").startsWith("Mac") 4469 && (eMod == (InputEvent.BUTTON1_MASK 4470 | Toolkit.getDefaultToolkit().getMenuShortcutKeyMask())))) { 4471 if (popupMenu != null) { 4472 popupMenu.show((JComponent) e.getSource(), e.getX(), e.getY()); 4473 } 4474 } 4475 else if (e.getClickCount() == 2) { 4476 // double click 4477 viewType = ViewType.TABLE; 4478 Object theData = null; 4479 try { 4480 theData = ((Dataset) getDataObject()).getData(); 4481 } 4482 catch (Exception ex) { 4483 JOptionPane.showMessageDialog(this, ex.getMessage(), getTitle(), JOptionPane.ERROR_MESSAGE); 4484 } 4485 4486 if (theData == null) { 4487 toolkit.beep(); 4488 JOptionPane.showMessageDialog(this, "No data selected.", getTitle(), JOptionPane.ERROR_MESSAGE); 4489 return; 4490 4491 } 4492 4493 int[] selectedRows = table.getSelectedRows(); 4494 if (selectedRows == null || selectedRows.length <= 0) { 4495 return; 4496 } 4497 int len = Array.getLength(selectedRows); 4498 for (int i = 0; i < len; i++) { 4499 if (isRegRef) 4500 showRegRefData((String) Array.get(theData, selectedRows[i])); 4501 else if (isObjRef) showObjRefData(Array.getLong(theData, selectedRows[i])); 4502 } 4503 } 4504 } 4505 4506 @Override 4507 public void mouseEntered (MouseEvent e) { 4508 } 4509 4510 @Override 4511 public void mouseExited (MouseEvent e) { 4512 } 4513 4514 @Override 4515 public void mousePressed (MouseEvent e) { 4516 } 4517 4518 @Override 4519 public void mouseReleased (MouseEvent e) { 4520 } 4521 4522 /** creates a popup menu for a right mouse click on a data object */ 4523 private JPopupMenu createPopupMenu ( ) { 4524 JPopupMenu menu = new JPopupMenu(); 4525 JMenuItem item; 4526 4527 item = new JMenuItem("Show As Table"); 4528 item.setMnemonic(KeyEvent.VK_T); 4529 item.addActionListener(this); 4530 item.setActionCommand("Show data as table"); 4531 menu.add(item); 4532 4533 item = new JMenuItem("Show As Image"); 4534 item.setMnemonic(KeyEvent.VK_I); 4535 item.addActionListener(this); 4536 item.setActionCommand("Show data as image"); 4537 menu.add(item); 4538 4539 // item = new JMenuItem( "Show As Text"); 4540 // item.setMnemonic(KeyEvent.VK_I); 4541 // item.addActionListener(this); 4542 // item.setActionCommand("Show data as text"); 4543 // menu.add(item); 4544 4545 return menu; 4546 } 4547 4548 /** 4549 * Display data pointed by object references. Data of each object is shown in a separate 4550 * spreadsheet. 4551 * 4552 * @param ref 4553 * the array of strings that contain the object reference information. 4554 * 4555 */ 4556 private void showObjRefData (long ref) { 4557 long[] oid = { ref }; 4558 log.trace("DefaultTableView showObjRefData: ref={}", ref); 4559 4560 HObject obj = FileFormat.findObject(dataset.getFileFormat(), oid); 4561 if (obj == null || !(obj instanceof ScalarDS)) return; 4562 4563 ScalarDS dset = (ScalarDS) obj; 4564 ScalarDS dset_copy = null; 4565 4566 // create an instance of the dataset constructor 4567 Constructor<? extends ScalarDS> constructor = null; 4568 Object[] paramObj = null; 4569 Object data = null; 4570 4571 try { 4572 Class[] paramClass = { FileFormat.class, String.class, String.class }; 4573 constructor = dset.getClass().getConstructor(paramClass); 4574 paramObj = new Object[] { dset.getFileFormat(), dset.getName(), dset.getPath() }; 4575 dset_copy = (ScalarDS) constructor.newInstance(paramObj); 4576 data = dset_copy.getData(); 4577 } 4578 catch (Exception ex) { 4579 JOptionPane.showMessageDialog(this, ex, "Object Reference:" + getTitle(), JOptionPane.ERROR_MESSAGE); 4580 data = null; 4581 } 4582 4583 if (data == null) return; 4584 4585 JInternalFrame dataView = null; 4586 HashMap map = new HashMap(1); 4587 map.put(ViewProperties.DATA_VIEW_KEY.OBJECT, dset_copy); 4588 switch (viewType) { 4589 case TEXT: 4590 dataView = new DefaultTextView(viewer, map); 4591 break; 4592 case IMAGE: 4593 dataView = new DefaultImageView(viewer, map); 4594 break; 4595 default: 4596 dataView = new DefaultTableView(viewer, map); 4597 break; 4598 } 4599 4600 if (dataView != null) { 4601 viewer.addDataView((DataView) dataView); 4602 } 4603 } 4604 4605 /** 4606 * Display data pointed by region references. Data of each region is shown in a separate 4607 * spreadsheet. The reg. ref. information is stored in strings of the format below: 4608 * <p /> 4609 * <ul> 4610 * <li>For point selections: "file_id:obj_id { <point1> <point2> ...) }", where <point1> is in 4611 * the form of (location_of_dim0, location_of_dim1, ...). For example, 0:800 { (0,1) (2,11) 4612 * (1,0) (2,4) }</li> 4613 * <li>For rectangle selections: 4614 * "file_id:obj_id { <corner coordinates1> <corner coordinates2> ... }", where <corner 4615 * coordinates1> is in the form of (start_corner)-(oposite_corner). For example, 0:800 { 4616 * (0,0)-(0,2) (0,11)-(0,13) (2,0)-(2,2) (2,11)-(2,13) }</li> 4617 * </ul> 4618 * 4619 * @param reg 4620 * the array of strings that contain the reg. ref information. 4621 * 4622 */ 4623 @SuppressWarnings({ "rawtypes", "unchecked" }) 4624 private void showRegRefData (String reg) { 4625 boolean isPointSelection = false; 4626 4627 if (reg == null || (reg.length() <= 0) || (reg.compareTo("NULL") == 0)) return; 4628 log.trace("DefaultTableView showRegRefData: reg={}", reg); 4629 4630 isPointSelection = (reg.indexOf('-') <= 0); 4631 4632 // find the object location 4633 String oidStr = reg.substring(reg.indexOf('/'), reg.indexOf(' ')); 4634 log.trace("DefaultTableView showRegRefData: isPointSelection={} oidStr={}", isPointSelection, oidStr); 4635 4636 // decode the region selection 4637 String regStr = reg.substring(reg.indexOf('{') + 1, reg.indexOf('}')); 4638 if (regStr == null || regStr.length() <= 0) return; // no selection 4639 4640 reg.substring(reg.indexOf('}') + 1); 4641 4642 StringTokenizer st = new StringTokenizer(regStr); 4643 int nSelections = st.countTokens(); 4644 if (nSelections <= 0) return; // no selection 4645 log.trace("DefaultTableView showRegRefData: nSelections={}", nSelections); 4646 4647 HObject obj = FileFormat.findObject(dataset.getFileFormat(), oidStr); 4648 if (obj == null || !(obj instanceof ScalarDS)) return; 4649 4650 ScalarDS dset = (ScalarDS) obj; 4651 ScalarDS dset_copy = null; 4652 4653 // create an instance of the dataset constructor 4654 Constructor<? extends ScalarDS> constructor = null; 4655 Object[] paramObj = null; 4656 try { 4657 @SuppressWarnings("rawtypes") 4658 Class[] paramClass = { FileFormat.class, String.class, String.class }; 4659 constructor = dset.getClass().getConstructor(paramClass); 4660 paramObj = new Object[] { dset.getFileFormat(), dset.getName(), dset.getPath() }; 4661 } 4662 catch (Exception ex) { 4663 constructor = null; 4664 } 4665 4666 // load each selection into a separate dataset and display it in 4667 // a separate spreadsheet 4668 StringBuffer titleSB = new StringBuffer(); 4669 log.trace("DefaultTableView showRegRefData: titleSB created"); 4670 4671 while (st.hasMoreTokens()) { 4672 log.trace("DefaultTableView showRegRefData: st.hasMoreTokens() begin"); 4673 try { 4674 dset_copy = (ScalarDS) constructor.newInstance(paramObj); 4675 } 4676 catch (Exception ex) { 4677 continue; 4678 } 4679 4680 if (dset_copy == null) continue; 4681 4682 try { 4683 dset_copy.init(); 4684 } 4685 catch (Exception ex) { 4686 continue; 4687 } 4688 4689 dset_copy.getRank(); 4690 long start[] = dset_copy.getStartDims(); 4691 long count[] = dset_copy.getSelectedDims(); 4692 4693 // set the selected dimension sizes based on the region selection 4694 // info. 4695 int idx = 0; 4696 String sizeStr = null; 4697 String token = st.nextToken(); 4698 4699 titleSB.setLength(0); 4700 titleSB.append(token); 4701 titleSB.append(" at "); 4702 log.trace("DefaultTableView showRegRefData: titleSB={}", titleSB); 4703 4704 token = token.replace('(', ' '); 4705 token = token.replace(')', ' '); 4706 if (isPointSelection) { 4707 // point selection 4708 StringTokenizer tmp = new StringTokenizer(token, ","); 4709 while (tmp.hasMoreTokens()) { 4710 count[idx] = 1; 4711 sizeStr = tmp.nextToken().trim(); 4712 start[idx] = Long.valueOf(sizeStr); 4713 idx++; 4714 } 4715 } 4716 else { 4717 // rectangle selection 4718 String startStr = token.substring(0, token.indexOf('-')); 4719 String endStr = token.substring(token.indexOf('-') + 1); 4720 StringTokenizer tmp = new StringTokenizer(startStr, ","); 4721 while (tmp.hasMoreTokens()) { 4722 sizeStr = tmp.nextToken().trim(); 4723 start[idx] = Long.valueOf(sizeStr); 4724 idx++; 4725 } 4726 4727 idx = 0; 4728 tmp = new StringTokenizer(endStr, ","); 4729 while (tmp.hasMoreTokens()) { 4730 sizeStr = tmp.nextToken().trim(); 4731 count[idx] = Long.valueOf(sizeStr) - start[idx] + 1; 4732 idx++; 4733 } 4734 } 4735 log.trace("DefaultTableView showRegRefData: selection inited"); 4736 4737 try { 4738 dset_copy.getData(); 4739 } 4740 catch (Exception ex) { 4741 JOptionPane.showMessageDialog(this, ex, "Region Reference:" + getTitle(), JOptionPane.ERROR_MESSAGE); 4742 } 4743 4744 JInternalFrame dataView = null; 4745 HashMap map = new HashMap(1); 4746 map.put(ViewProperties.DATA_VIEW_KEY.OBJECT, dset_copy); 4747 switch (viewType) { 4748 case TEXT: 4749 dataView = new DefaultTextView(viewer, map); 4750 break; 4751 case IMAGE: 4752 dataView = new DefaultImageView(viewer, map); 4753 break; 4754 default: 4755 dataView = new DefaultTableView(viewer, map); 4756 break; 4757 } 4758 4759 if (dataView != null) { 4760 viewer.addDataView((DataView) dataView); 4761 dataView.setTitle(dataView.getTitle() + "; " + titleSB.toString()); 4762 } 4763 log.trace("DefaultTableView showRegRefData: st.hasMoreTokens() end"); 4764 } // while (st.hasMoreTokens()) 4765 } // private void showRegRefData(String reg) 4766}