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