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 COPYING file, which can be found * 009 * at the root of the source code distribution tree, * 010 * or in https://www.hdfgroup.org/licenses. * 011 * If you do not have access to either file, you may request a copy from * 012 * help@hdfgroup.org. * 013 ****************************************************************************/ 014 015package hdf.view.TableView; 016 017import java.lang.reflect.Array; 018import java.lang.reflect.Constructor; 019import java.math.BigInteger; 020import java.util.ArrayList; 021import java.util.HashMap; 022import java.util.Iterator; 023import java.util.LinkedHashSet; 024import java.util.List; 025import java.util.Set; 026import java.util.StringTokenizer; 027 028import hdf.object.Attribute; 029import hdf.object.DataFormat; 030import hdf.object.Dataset; 031import hdf.object.Datatype; 032import hdf.object.FileFormat; 033import hdf.object.HObject; 034import hdf.object.ScalarDS; 035import hdf.object.Utils; 036import hdf.object.h5.H5Datatype; 037import hdf.object.h5.H5File; 038import hdf.object.h5.H5ReferenceType; 039import hdf.object.h5.H5ReferenceType.H5ReferenceData; 040import hdf.object.h5.H5ScalarAttr; 041import hdf.view.DataView.DataViewManager; 042import hdf.view.HDFView; 043import hdf.view.Tools; 044import hdf.view.ViewProperties; 045import hdf.view.dialog.InputDialog; 046 047import hdf.hdf5lib.HDF5Constants; 048 049import org.slf4j.Logger; 050import org.slf4j.LoggerFactory; 051 052import org.eclipse.nebula.widgets.nattable.NatTable; 053import org.eclipse.nebula.widgets.nattable.command.VisualRefreshCommand; 054import org.eclipse.nebula.widgets.nattable.config.DefaultNatTableStyleConfiguration; 055import org.eclipse.nebula.widgets.nattable.config.EditableRule; 056import org.eclipse.nebula.widgets.nattable.config.IEditableRule; 057import org.eclipse.nebula.widgets.nattable.coordinate.PositionCoordinate; 058import org.eclipse.nebula.widgets.nattable.coordinate.Range; 059import org.eclipse.nebula.widgets.nattable.data.IDataProvider; 060import org.eclipse.nebula.widgets.nattable.grid.data.DefaultCornerDataProvider; 061import org.eclipse.nebula.widgets.nattable.grid.layer.ColumnHeaderLayer; 062import org.eclipse.nebula.widgets.nattable.grid.layer.CornerLayer; 063import org.eclipse.nebula.widgets.nattable.grid.layer.GridLayer; 064import org.eclipse.nebula.widgets.nattable.grid.layer.RowHeaderLayer; 065import org.eclipse.nebula.widgets.nattable.layer.DataLayer; 066import org.eclipse.nebula.widgets.nattable.layer.ILayer; 067import org.eclipse.nebula.widgets.nattable.layer.ILayerListener; 068import org.eclipse.nebula.widgets.nattable.layer.event.ILayerEvent; 069import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer; 070import org.eclipse.nebula.widgets.nattable.selection.command.SelectCellCommand; 071import org.eclipse.nebula.widgets.nattable.selection.event.CellSelectionEvent; 072import org.eclipse.nebula.widgets.nattable.viewport.ViewportLayer; 073import org.eclipse.swt.SWT; 074import org.eclipse.swt.custom.ScrolledComposite; 075import org.eclipse.swt.events.DisposeEvent; 076import org.eclipse.swt.events.DisposeListener; 077import org.eclipse.swt.events.SelectionAdapter; 078import org.eclipse.swt.events.SelectionEvent; 079import org.eclipse.swt.widgets.Composite; 080import org.eclipse.swt.widgets.Menu; 081import org.eclipse.swt.widgets.MenuItem; 082import org.eclipse.swt.widgets.Shell; 083 084/** 085 * A class to construct a ScalarDS TableView. 086 */ 087public class DefaultScalarDSTableView extends DefaultBaseTableView implements TableView { 088 private static final Logger log = LoggerFactory.getLogger(DefaultScalarDSTableView.class); 089 090 /** 091 * Constructs a ScalarDS TableView with no additional data properties. 092 * 093 * @param theView 094 * the main HDFView. 095 */ 096 public DefaultScalarDSTableView(DataViewManager theView) { this(theView, null); } 097 098 /** 099 * Constructs a ScalarDS TableView with the specified data properties. 100 * 101 * @param theView 102 * the main HDFView. 103 * 104 * @param dataPropertiesMap 105 * the properties on how to show the data. The map is used to allow 106 * applications to pass properties on how to display the data, such 107 * as: transposing data, showing data as characters, applying a 108 * bitmask, and etc. Predefined keys are listed at 109 * ViewProperties.DATA_VIEW_KEY. 110 */ 111 @SuppressWarnings("rawtypes") 112 public DefaultScalarDSTableView(DataViewManager theView, HashMap dataPropertiesMap) 113 { 114 super(theView, dataPropertiesMap); 115 116 if (!shell.isDisposed()) { 117 if (System.getProperty("os.name").toLowerCase().contains("mac")) { 118 shell.setImages(ViewProperties.getHdfIcons()); 119 } 120 else { 121 shell.setImage(dataObject.getDatatype().isText() ? ViewProperties.getTextIcon() 122 : ViewProperties.getDatasetIcon()); 123 } 124 125 shell.addDisposeListener(new DisposeListener() { 126 @Override 127 public void widgetDisposed(DisposeEvent e) 128 { 129 if (dataObject instanceof ScalarDS) { 130 ScalarDS ds = (ScalarDS)dataObject; 131 132 /* 133 * Reload the data when it is displayed next time because the display type 134 * (table or image) may be different. 135 */ 136 if (ds.isImage()) 137 ds.clearData(); 138 } 139 } 140 }); 141 142 viewer.addDataView(this); 143 144 shell.open(); 145 } 146 } 147 148 @Override 149 protected void loadData(DataFormat dataObject) throws Exception 150 { 151 super.loadData(dataObject); 152 153 try { 154 if (Tools.applyBitmask(dataValue, bitmask, bitmaskOP)) { 155 isReadOnly = true; 156 String opName = "Bits "; 157 158 if (bitmaskOP == ViewProperties.BITMASK_OP.AND) 159 opName = "Bitwise AND "; 160 161 String title = indexBaseGroup.getText(); 162 title += ", " + opName + bitmask; 163 indexBaseGroup.setText(title); 164 } 165 166 dataObject.convertFromUnsignedC(); 167 168 dataValue = dataObject.getData(); 169 } 170 catch (Exception ex) { 171 log.debug("loadData(): ", ex); 172 dataValue = null; 173 throw ex; 174 } 175 176 if (dataValue == null) { 177 log.debug("loadData(): data value is null"); 178 throw new RuntimeException("data value is null"); 179 } 180 181 fillValue = dataObject.getFillValue(); 182 log.trace("loadData(): fillValue={}", fillValue); 183 184 char runtimeTypeClass = Utils.getJavaObjectRuntimeClass(dataValue); 185 log.trace("loadData(): cName={} runtimeTypeClass={}", dataValue.getClass().getName(), 186 runtimeTypeClass); 187 188 /* 189 * Convert numerical data into character data; only possible cases are byte[] 190 * and short[] (converted from unsigned byte) 191 */ 192 if (isDisplayTypeChar && ((runtimeTypeClass == 'B') || (runtimeTypeClass == 'S'))) { 193 int n = Array.getLength(dataValue); 194 char[] charData = new char[n]; 195 for (int i = 0; i < n; i++) { 196 if (runtimeTypeClass == 'B') 197 charData[i] = (char)Array.getByte(dataValue, i); 198 else if (runtimeTypeClass == 'S') 199 charData[i] = (char)Array.getShort(dataValue, i); 200 } 201 202 dataValue = charData; 203 } 204 else if ((runtimeTypeClass == 'B') && dataObject.getDatatype().isArray()) { 205 Datatype baseType = dataObject.getDatatype().getDatatypeBase(); 206 if (baseType.isString()) 207 dataValue = Dataset.byteToString((byte[])dataValue, (int)baseType.getDatatypeSize()); 208 } 209 } 210 211 /** 212 * Creates the menubar for the Shell. 213 */ 214 @Override 215 protected Menu createMenuBar(final Shell theShell) 216 { 217 Menu baseMenu = super.createMenuBar(theShell); 218 MenuItem[] baseMenuItems = baseMenu.getItems(); 219 MenuItem item = null; 220 221 /***************************************************************************** 222 * * 223 * Add in a few MenuItems for importing/exporting data from/to binary files. * 224 * * 225 *****************************************************************************/ 226 227 MenuItem importExportMenuItem = null; 228 for (int i = 0; i < baseMenuItems.length; i++) 229 if (baseMenuItems[i].getText().equals("&Import/Export Data")) 230 importExportMenuItem = baseMenuItems[i]; 231 232 if (importExportMenuItem != null) { 233 Menu importExportMenu = importExportMenuItem.getMenu(); 234 MenuItem[] importExportMenuItems = importExportMenu.getItems(); 235 236 for (int i = 0; i < importExportMenuItems.length; i++) 237 if (importExportMenuItems[i].getText().equals("Export Data to")) 238 item = importExportMenuItems[i]; 239 240 if (item != null) { 241 Menu exportMenu = item.getMenu(); 242 243 MenuItem exportAsBinaryMenuItem = new MenuItem(exportMenu, SWT.CASCADE); 244 exportAsBinaryMenuItem.setText("Binary File"); 245 246 Menu exportAsBinaryMenu = new Menu(exportAsBinaryMenuItem); 247 exportAsBinaryMenuItem.setMenu(exportAsBinaryMenu); 248 249 item = new MenuItem(exportAsBinaryMenu, SWT.PUSH); 250 item.setText("Native Order"); 251 item.addSelectionListener(new SelectionAdapter() { 252 @Override 253 public void widgetSelected(SelectionEvent e) 254 { 255 binaryOrder = 1; 256 257 try { 258 saveAsBinary(); 259 } 260 catch (Exception ex) { 261 theShell.getDisplay().beep(); 262 Tools.showError(theShell, "Export", ex.getMessage()); 263 } 264 } 265 }); 266 267 item = new MenuItem(exportAsBinaryMenu, SWT.PUSH); 268 item.setText("Little Endian"); 269 item.addSelectionListener(new SelectionAdapter() { 270 @Override 271 public void widgetSelected(SelectionEvent e) 272 { 273 binaryOrder = 2; 274 275 try { 276 saveAsBinary(); 277 } 278 catch (Exception ex) { 279 theShell.getDisplay().beep(); 280 Tools.showError(theShell, "Export", ex.getMessage()); 281 } 282 } 283 }); 284 285 item = new MenuItem(exportAsBinaryMenu, SWT.PUSH); 286 item.setText("Big Endian"); 287 item.addSelectionListener(new SelectionAdapter() { 288 @Override 289 public void widgetSelected(SelectionEvent e) 290 { 291 binaryOrder = 3; 292 293 try { 294 saveAsBinary(); 295 } 296 catch (Exception ex) { 297 theShell.getDisplay().beep(); 298 Tools.showError(theShell, "Export", ex.getMessage()); 299 } 300 } 301 }); 302 } 303 304 item = null; 305 for (int i = 0; i < importExportMenuItems.length; i++) 306 if (importExportMenuItems[i].getText().equals("Import Data from")) 307 item = importExportMenuItems[i]; 308 309 if (item != null) { 310 Menu importMenu = item.getMenu(); 311 312 MenuItem importAsBinaryMenuItem = new MenuItem(importMenu, SWT.CASCADE); 313 importAsBinaryMenuItem.setText("Binary File"); 314 315 Menu importAsBinaryMenu = new Menu(importAsBinaryMenuItem); 316 importAsBinaryMenuItem.setMenu(importAsBinaryMenu); 317 318 item = new MenuItem(importAsBinaryMenu, SWT.PUSH); 319 item.setText("Native Order"); 320 item.setEnabled(!isReadOnly); 321 item.addSelectionListener(new SelectionAdapter() { 322 @Override 323 public void widgetSelected(SelectionEvent e) 324 { 325 binaryOrder = 1; 326 327 try { 328 importBinaryData(); 329 } 330 catch (Exception ex) { 331 Tools.showError(theShell, "Import", ex.getMessage()); 332 } 333 } 334 }); 335 336 item = new MenuItem(importAsBinaryMenu, SWT.PUSH); 337 item.setText("Little Endian"); 338 item.setEnabled(!isReadOnly); 339 item.addSelectionListener(new SelectionAdapter() { 340 @Override 341 public void widgetSelected(SelectionEvent e) 342 { 343 binaryOrder = 2; 344 345 try { 346 importBinaryData(); 347 } 348 catch (Exception ex) { 349 Tools.showError(theShell, "Import", ex.getMessage()); 350 } 351 } 352 }); 353 354 item = new MenuItem(importAsBinaryMenu, SWT.PUSH); 355 item.setText("Big Endian"); 356 item.setEnabled(!isReadOnly); 357 item.addSelectionListener(new SelectionAdapter() { 358 @Override 359 public void widgetSelected(SelectionEvent e) 360 { 361 binaryOrder = 3; 362 363 try { 364 importBinaryData(); 365 } 366 catch (Exception ex) { 367 Tools.showError(theShell, "Import", ex.getMessage()); 368 } 369 } 370 }); 371 } 372 373 new MenuItem(importExportMenu, SWT.SEPARATOR); 374 375 checkFixedDataLength = new MenuItem(importExportMenu, SWT.CHECK); 376 checkFixedDataLength.setText("Fixed Data Length"); 377 checkFixedDataLength.addSelectionListener(new SelectionAdapter() { 378 @Override 379 public void widgetSelected(SelectionEvent e) 380 { 381 if (!checkFixedDataLength.getSelection()) { 382 fixedDataLength = -1; 383 return; 384 } 385 386 String str = 387 new InputDialog(theShell, "", 388 "Enter fixed data length when importing text data\n\n" 389 + "For example, for a text string of \"12345678\"\n\t\tenter 2," 390 + "the data will be 12, 34, 56, 78\n\t\tenter 4, the data will be" 391 + "1234, 5678\n") 392 .open(); 393 394 if ((str == null) || (str.length() < 1)) { 395 checkFixedDataLength.setSelection(false); 396 return; 397 } 398 399 try { 400 fixedDataLength = Integer.parseInt(str); 401 } 402 catch (Exception ex) { 403 fixedDataLength = -1; 404 } 405 406 if (fixedDataLength < 1) { 407 checkFixedDataLength.setSelection(false); 408 } 409 } 410 }); 411 } 412 413 /***************************************************************************************** 414 * * 415 * Add a section for changing the way that data is displayed, e.g. as hexadecimal values * 416 * * 417 *****************************************************************************************/ 418 419 MenuItem dataDisplayMenuItem = new MenuItem(baseMenu, SWT.CASCADE); 420 dataDisplayMenuItem.setText("Data Display"); 421 422 Menu dataDisplayMenu = new Menu(theShell, SWT.DROP_DOWN); 423 dataDisplayMenuItem.setMenu(dataDisplayMenu); 424 425 checkScientificNotation = new MenuItem(dataDisplayMenu, SWT.CHECK); 426 checkScientificNotation.setText("Show Scientific Notation"); 427 checkScientificNotation.addSelectionListener(new SelectionAdapter() { 428 @Override 429 public void widgetSelected(SelectionEvent e) 430 { 431 if (checkScientificNotation.getSelection()) { 432 if (checkCustomNotation != null) 433 checkCustomNotation.setSelection(false); 434 if (checkEnum != null) 435 checkEnum.setSelection(false); 436 if (checkHex != null) 437 checkHex.setSelection(false); 438 if (checkBin != null) 439 checkBin.setSelection(false); 440 441 numberFormat = scientificFormat; 442 showAsHex = false; 443 showAsBin = false; 444 } 445 else { 446 numberFormat = normalFormat; 447 } 448 449 updateDataConversionSettings(); 450 451 dataTable.doCommand(new VisualRefreshCommand()); 452 453 PositionCoordinate lastSelectedCell = getSelectionLayer().getLastSelectedCellPosition(); 454 if (lastSelectedCell != null) { 455 /* 456 * Send down a cell selection event for the current cell to update the cell 457 * value labels 458 */ 459 dataTable.doCommand(new SelectCellCommand(getSelectionLayer(), 460 lastSelectedCell.columnPosition, 461 lastSelectedCell.rowPosition, false, false)); 462 } 463 } 464 }); 465 466 checkCustomNotation = new MenuItem(dataDisplayMenu, SWT.CHECK); 467 checkCustomNotation.setText("Show Custom Notation"); 468 checkCustomNotation.addSelectionListener(new SelectionAdapter() { 469 @Override 470 public void widgetSelected(SelectionEvent e) 471 { 472 if (checkCustomNotation.getSelection()) { 473 if (checkScientificNotation != null) 474 checkScientificNotation.setSelection(false); 475 if (checkEnum != null) 476 checkEnum.setSelection(false); 477 if (checkHex != null) 478 checkHex.setSelection(false); 479 if (checkBin != null) 480 checkBin.setSelection(false); 481 482 numberFormat = customFormat; 483 showAsHex = false; 484 showAsBin = false; 485 } 486 else { 487 numberFormat = normalFormat; 488 } 489 490 updateDataConversionSettings(); 491 492 dataTable.doCommand(new VisualRefreshCommand()); 493 494 PositionCoordinate lastSelectedCell = getSelectionLayer().getLastSelectedCellPosition(); 495 if (lastSelectedCell != null) { 496 /* 497 * Send down a cell selection event for the current cell to update the cell 498 * value labels 499 */ 500 dataTable.doCommand(new SelectCellCommand(getSelectionLayer(), 501 lastSelectedCell.columnPosition, 502 lastSelectedCell.rowPosition, false, false)); 503 } 504 } 505 }); 506 507 item = new MenuItem(dataDisplayMenu, SWT.PUSH); 508 item.setText("Create custom notation"); 509 item.addSelectionListener(new SelectionAdapter() { 510 @Override 511 public void widgetSelected(SelectionEvent e) 512 { 513 String msg = 514 "Create number format by pattern \nINTEGER . FRACTION E EXPONENT\nusing # for optional digits and 0 for required digits" 515 + "\nwhere, INTEGER: the pattern for the integer part" 516 + "\n FRACTION: the pattern for the fractional part" 517 + "\n EXPONENT: the pattern for the exponent part" 518 + "\n\nFor example, " 519 + "\n\t the normalized scientific notation format is \"#.0###E0##\"" 520 + "\n\t to make the digits required \"0.00000E000\"\n\n"; 521 522 String str = (new InputDialog(theShell, "Create a custom number format", msg, 523 customFormat.toPattern())) 524 .open(); 525 526 if ((str == null) || (str.length() < 1)) 527 return; 528 529 try { 530 customFormat.applyPattern(str); 531 } 532 catch (Exception ex) { 533 log.debug("Invalid custom number notation format: {}:", str, ex); 534 Tools.showError(shell, "Create", "Invalid custom notation format " + str); 535 } 536 } 537 }); 538 539 char runtimeTypeClass = Utils.getJavaObjectRuntimeClass(dataValue); 540 boolean isInt = (runtimeTypeClass == 'B' || runtimeTypeClass == 'S' || runtimeTypeClass == 'I' || 541 runtimeTypeClass == 'J'); 542 543 if (isInt || dataObject.getDatatype().isBitField() || dataObject.getDatatype().isOpaque()) { 544 checkHex = new MenuItem(dataDisplayMenu, SWT.CHECK); 545 checkHex.setText("Show Hexadecimal"); 546 checkHex.addSelectionListener(new SelectionAdapter() { 547 @Override 548 public void widgetSelected(SelectionEvent e) 549 { 550 showAsHex = checkHex.getSelection(); 551 if (showAsHex) { 552 if (checkScientificNotation != null) 553 checkScientificNotation.setSelection(false); 554 if (checkCustomNotation != null) 555 checkCustomNotation.setSelection(false); 556 if (checkEnum != null) 557 checkEnum.setSelection(false); 558 if (checkBin != null) 559 checkBin.setSelection(false); 560 561 showAsBin = false; 562 numberFormat = normalFormat; 563 } 564 565 updateDataConversionSettings(); 566 567 dataTable.doCommand(new VisualRefreshCommand()); 568 569 PositionCoordinate lastSelectedCell = getSelectionLayer().getLastSelectedCellPosition(); 570 if (lastSelectedCell != null) { 571 /* 572 * Send down a cell selection event for the current cell to update the cell 573 * value labels 574 */ 575 dataTable.doCommand( 576 new SelectCellCommand(getSelectionLayer(), lastSelectedCell.columnPosition, 577 lastSelectedCell.rowPosition, false, false)); 578 } 579 } 580 }); 581 582 checkBin = new MenuItem(dataDisplayMenu, SWT.CHECK); 583 checkBin.setText("Show Binary"); 584 checkBin.addSelectionListener(new SelectionAdapter() { 585 @Override 586 public void widgetSelected(SelectionEvent e) 587 { 588 showAsBin = checkBin.getSelection(); 589 if (showAsBin) { 590 if (checkScientificNotation != null) 591 checkScientificNotation.setSelection(false); 592 if (checkCustomNotation != null) 593 checkCustomNotation.setSelection(false); 594 if (checkEnum != null) 595 checkEnum.setSelection(false); 596 if (checkHex != null) 597 checkHex.setSelection(false); 598 599 showAsHex = false; 600 numberFormat = normalFormat; 601 } 602 603 updateDataConversionSettings(); 604 605 dataTable.doCommand(new VisualRefreshCommand()); 606 607 PositionCoordinate lastSelectedCell = getSelectionLayer().getLastSelectedCellPosition(); 608 if (lastSelectedCell != null) { 609 /* 610 * Send down a cell selection event for the current cell to update the cell 611 * value labels 612 */ 613 dataTable.doCommand( 614 new SelectCellCommand(getSelectionLayer(), lastSelectedCell.columnPosition, 615 lastSelectedCell.rowPosition, false, false)); 616 } 617 } 618 }); 619 620 checkEnum = new MenuItem(dataDisplayMenu, SWT.CHECK); 621 checkEnum.setText("Show Enum Values"); 622 checkEnum.addSelectionListener(new SelectionAdapter() { 623 @Override 624 public void widgetSelected(SelectionEvent e) 625 { 626 isEnumConverted = checkEnum.getSelection(); 627 if (isEnumConverted) { 628 if (checkScientificNotation != null) 629 checkScientificNotation.setSelection(false); 630 if (checkCustomNotation != null) 631 checkCustomNotation.setSelection(false); 632 if (checkHex != null) 633 checkHex.setSelection(false); 634 if (checkBin != null) 635 checkBin.setSelection(false); 636 637 showAsBin = false; 638 showAsHex = false; 639 numberFormat = normalFormat; 640 } 641 642 updateDataConversionSettings(); 643 644 dataTable.doCommand(new VisualRefreshCommand()); 645 646 PositionCoordinate lastSelectedCell = getSelectionLayer().getLastSelectedCellPosition(); 647 if (lastSelectedCell != null) { 648 /* 649 * Send down a cell selection event for the current cell to update the cell 650 * value labels 651 */ 652 dataTable.doCommand( 653 new SelectCellCommand(getSelectionLayer(), lastSelectedCell.columnPosition, 654 lastSelectedCell.rowPosition, false, false)); 655 } 656 } 657 }); 658 } 659 660 return baseMenu; 661 } 662 663 /** 664 * Creates a NatTable for a Scalar dataset. 665 * 666 * @param parent 667 * The parent for the NatTable 668 * @param dataObject 669 * The Scalar dataset for the NatTable to display 670 * 671 * @return The newly created NatTable 672 */ 673 @Override 674 protected NatTable createTable(Composite parent, DataFormat dataObject) 675 { 676 // Create body layer 677 try { 678 dataProvider = DataProviderFactory.getDataProvider(dataObject, dataValue, isDataTransposed); 679 680 log.trace("createTable(): rows={} : cols={}", dataProvider.getRowCount(), 681 dataProvider.getColumnCount()); 682 683 dataLayer = new DataLayer(dataProvider); 684 } 685 catch (Exception ex) { 686 log.debug("createTable(): failed to retrieve DataProvider for table: ", ex); 687 return null; 688 } 689 690 selectionLayer = new SelectionLayer(dataLayer); 691 final ViewportLayer viewportLayer = new ViewportLayer(selectionLayer); 692 693 dataLayer.setDefaultColumnWidth(80); 694 695 // Create the Column Header layer 696 columnHeaderDataProvider = new ScalarDSColumnHeaderDataProvider(dataObject); 697 ColumnHeaderLayer columnHeaderLayer = 698 new ColumnHeader(new DataLayer(columnHeaderDataProvider), viewportLayer, selectionLayer); 699 700 // Create the Row Header layer 701 rowHeaderDataProvider = new RowHeaderDataProvider(dataObject); 702 703 // Try to adapt row height to current font 704 int defaultRowHeight = curFont == null ? 20 : (2 * curFont.getFontData()[0].getHeight()); 705 706 DataLayer baseLayer = new DataLayer(rowHeaderDataProvider, 40, defaultRowHeight); 707 RowHeaderLayer rowHeaderLayer = new RowHeader(baseLayer, viewportLayer, selectionLayer); 708 709 // Create the Corner Layer 710 ILayer cornerLayer = new CornerLayer( 711 new DataLayer(new DefaultCornerDataProvider(columnHeaderDataProvider, rowHeaderDataProvider)), 712 rowHeaderLayer, columnHeaderLayer); 713 714 // Create the Grid Layer 715 GridLayer gridLayer = 716 new EditingGridLayer(viewportLayer, columnHeaderLayer, rowHeaderLayer, cornerLayer); 717 718 final NatTable natTable = new NatTable(parent, gridLayer, false); 719 natTable.addConfiguration(new DefaultNatTableStyleConfiguration()); 720 natTable.addLayerListener(new ScalarDSCellSelectionListener()); 721 722 // Create popup menu for region or object ref. 723 if (isStdRef || isRegRef || isObjRef) 724 natTable.addConfiguration(new RefContextMenu(natTable)); 725 726 natTable.configure(); 727 728 return natTable; 729 } 730 731 /** 732 * Returns the selected data values of the ScalarDS 733 */ 734 @Override 735 public Object getSelectedData() 736 { 737 Object selectedData = null; 738 739 // Since NatTable returns the selected row positions as a Set<Range>, convert 740 // this to an Integer[] 741 Set<Range> rowPositions = selectionLayer.getSelectedRowPositions(); 742 log.trace("getSelectedData() rowPositions: {}", rowPositions); 743 Set<Integer> selectedRowPos = new LinkedHashSet<>(); 744 Iterator<Range> i1 = rowPositions.iterator(); 745 while (i1.hasNext()) 746 selectedRowPos.addAll(i1.next().getMembers()); 747 748 Integer[] selectedRows = selectedRowPos.toArray(new Integer[0]); 749 int[] selectedCols = selectionLayer.getSelectedColumnPositions(); 750 751 if (selectedRows == null || selectedRows.length <= 0 || selectedCols == null || 752 selectedCols.length <= 0) { 753 shell.getDisplay().beep(); 754 Tools.showError(shell, "Select", "No data is selected."); 755 return null; 756 } 757 758 int size = selectedCols.length * selectedRows.length; 759 log.trace("getSelectedData() data size: {}", size); 760 761 // the whole table is selected 762 if ((dataTable.getPreferredColumnCount() - 1 == selectedCols.length) && 763 (dataTable.getPreferredRowCount() - 1 == selectedRows.length)) 764 return dataValue; 765 766 if (dataObject.getDatatype().isRef()) { 767 // ref data are stored in bytes 768 selectedData = new byte[size * (int)dataObject.getDatatype().getDatatypeSize()]; 769 } 770 else { 771 switch (Utils.getJavaObjectRuntimeClass(dataValue)) { 772 case 'B': 773 selectedData = new byte[size]; 774 break; 775 case 'S': 776 selectedData = new short[size]; 777 break; 778 case 'I': 779 selectedData = new int[size]; 780 break; 781 case 'J': 782 selectedData = new long[size]; 783 break; 784 case 'F': 785 selectedData = new float[size]; 786 break; 787 case 'D': 788 selectedData = new double[size]; 789 break; 790 default: 791 selectedData = null; 792 break; 793 } 794 } 795 796 if (selectedData == null) { 797 shell.getDisplay().beep(); 798 Tools.showError(shell, "Select", "Unsupported data type."); 799 return null; 800 } 801 802 log.trace("getSelectedData(): selectedData is type {}", Utils.getJavaObjectRuntimeClass(dataValue)); 803 804 int w = dataTable.getPreferredColumnCount() - 1; 805 log.trace("getSelectedData(): getColumnCount={}", w); 806 int idxSrc = 0; 807 int idxDst = 0; 808 log.trace("getSelectedData(): Rows.length={} Cols.length={}", selectedRows.length, 809 selectedCols.length); 810 for (int i = 0; i < selectedRows.length; i++) { 811 for (int j = 0; j < selectedCols.length; j++) { 812 idxSrc = selectedRows[i] * w + selectedCols[j]; 813 Object dataArrayValue = null; 814 if (dataValue instanceof ArrayList) { 815 dataArrayValue = ((ArrayList)dataValue).get(idxSrc); 816 System.arraycopy(dataArrayValue, 0, selectedData, idxDst, 817 (int)dataObject.getDatatype().getDatatypeSize()); 818 } 819 else { 820 dataArrayValue = Array.get(dataValue, idxSrc); 821 Array.set(selectedData, idxDst, dataArrayValue); 822 } 823 log.trace("getSelectedData()[{},{}]: dataValue[{}]={} from r{} and c{}", i, j, idxSrc, 824 dataArrayValue, selectedRows[i], selectedCols[j]); 825 idxDst++; 826 } 827 } 828 829 return selectedData; 830 } 831 832 /** 833 * Returns an IEditableRule that determines whether cells can be edited. 834 * 835 * Cells can be edited as long as the dataset is not opened in read-only mode 836 * and the data is not currently displayed in hexadecimal, binary, or character 837 * mode. 838 * 839 * @param dataObject 840 * The dataset for editing 841 * 842 * @return a new IEditableRule for the dataset 843 */ 844 @Override 845 protected IEditableRule getDataEditingRule(final DataFormat dataObject) 846 { 847 if (dataObject == null) 848 return null; 849 850 // Only Allow editing if not in read-only mode 851 return new EditableRule() { 852 @Override 853 public boolean isEditable(int columnIndex, int rowIndex) 854 { 855 /* 856 * TODO: Should be able to edit character-displayed types and datasets when 857 * displayed as hex/binary. 858 */ 859 return !(isReadOnly || isDisplayTypeChar || showAsBin || showAsHex); 860 } 861 }; 862 } 863 864 /** 865 * Display data pointed to by object references. Data of each object is shown in 866 * a separate spreadsheet. 867 * 868 * @param refarr 869 * the array of bytes that contain the object reference information. 870 * 871 */ 872 @Override 873 @SuppressWarnings({"rawtypes", "unchecked"}) 874 protected void showObjRefData(byte[] refarr) 875 { 876 log.trace("showObjRefData(): start: refarr={}", refarr); 877 878 if (refarr == null || (refarr.length <= 0) || H5Datatype.zeroArrayCheck(refarr)) { 879 Tools.showError(shell, "Select", "Could not show object reference data: invalid or null data"); 880 log.debug("showObjRefData(): refarr is null or invalid"); 881 return; 882 } 883 884 String objref = 885 H5Datatype.descReferenceObject(((HObject)dataObject).getFileFormat().getFID(), refarr); 886 log.trace("showObjRefData(): start: objref={}", objref); 887 888 // find the object location 889 String oidStr = objref.substring(objref.indexOf('/'), objref.indexOf("H5O_TYPE_OBJ_REF") - 1); 890 HObject obj = FileFormat.findObject(((HObject)dataObject).getFileFormat(), oidStr); 891 if (obj == null || !(obj instanceof ScalarDS)) { 892 Tools.showError(shell, "Select", "Could not show object reference data: invalid or null data"); 893 log.debug("showObjRefData(): obj is null or not a Scalar Dataset"); 894 return; 895 } 896 897 ScalarDS dset = (ScalarDS)obj; 898 ScalarDS dsetCopy = null; 899 900 // create an instance of the dataset constructor 901 Constructor<? extends ScalarDS> constructor = null; 902 Object[] paramObj = null; 903 Object data = null; 904 905 try { 906 Class[] paramClass = {FileFormat.class, String.class, String.class}; 907 constructor = dset.getClass().getConstructor(paramClass); 908 paramObj = new Object[] {dset.getFileFormat(), dset.getName(), dset.getPath()}; 909 dsetCopy = constructor.newInstance(paramObj); 910 data = dsetCopy.getData(); 911 } 912 catch (Exception ex) { 913 log.debug("showObjRefData(): couldn't show data: ", ex); 914 Tools.showError(shell, "Select", "Object Reference: " + ex.getMessage()); 915 data = null; 916 } 917 918 if (data == null) 919 return; 920 921 Class<?> theClass = null; 922 String viewName = null; 923 924 switch (viewType) { 925 case IMAGE: 926 viewName = HDFView.getListOfImageViews().get(0); 927 break; 928 case TABLE: 929 viewName = (String)HDFView.getListOfTableViews().get(0); 930 break; 931 default: 932 viewName = null; 933 } 934 935 try { 936 theClass = Class.forName(viewName); 937 } 938 catch (Exception ex) { 939 try { 940 theClass = ViewProperties.loadExtClass().loadClass(viewName); 941 } 942 catch (Exception ex2) { 943 theClass = null; 944 } 945 } 946 947 // Use default dataview 948 if (theClass == null) { 949 switch (viewType) { 950 case IMAGE: 951 viewName = ViewProperties.DEFAULT_IMAGEVIEW_NAME; 952 break; 953 case TABLE: 954 viewName = ViewProperties.DEFAULT_SCALAR_DATASET_TABLEVIEW_NAME; 955 break; 956 default: 957 viewName = null; 958 } 959 960 try { 961 theClass = Class.forName(viewName); 962 } 963 catch (Exception ex) { 964 log.debug("showObjRefData(): no suitable display class found"); 965 Tools.showError(shell, "Select", 966 "Could not show reference data: no suitable display class found"); 967 return; 968 } 969 } 970 971 HashMap map = new HashMap(1); 972 map.put(ViewProperties.DATA_VIEW_KEY.OBJECT, dsetCopy); 973 Object[] args = {viewer, map}; 974 975 try { 976 Tools.newInstance(theClass, args); 977 } 978 catch (Exception ex) { 979 log.debug("showObjRefData(): Could not show reference data: ", ex); 980 Tools.showError(shell, "Select", "Could not show reference data: " + ex.toString()); 981 } 982 } 983 984 /** 985 * Display data pointed to by region references. Data of each region is shown in 986 * a separate spreadsheet. 987 * 988 * @param refarr 989 * the array of bytes that contain the reg. ref information. 990 * 991 */ 992 @Override 993 @SuppressWarnings({"rawtypes", "unchecked"}) 994 protected void showRegRefData(byte[] refarr) 995 { 996 if (refarr == null || (refarr.length <= 0) || H5Datatype.zeroArrayCheck(refarr)) { 997 Tools.showError(shell, "Select", "Could not show region reference data: invalid or null data"); 998 log.debug("showRegRefData(): refarr is null or invalid"); 999 return; 1000 } 1001 1002 String reg = null; 1003 if (refarr.length == HDF5Constants.H5R_DSET_REG_REF_BUF_SIZE) 1004 reg = H5Datatype.descRegionDataset(((HObject)dataObject).getFileFormat().getFID(), refarr); 1005 else 1006 reg = ((H5ReferenceType)dataObject.getDatatype()).getReferenceRegion(refarr, false); 1007 1008 boolean isPointSelection = (reg.indexOf('-') <= 0); 1009 1010 // find the object location 1011 String oidStr = reg.substring(reg.indexOf('/'), reg.indexOf("REGION_TYPE") - 1); 1012 1013 // decode the region selection 1014 String regStr = reg.substring(reg.indexOf('{') + 1, reg.indexOf('}')); 1015 if (regStr == null || regStr.length() <= 0) { 1016 Tools.showError(shell, "Select", 1017 "Could not show region reference data: no region selection made."); 1018 log.debug("showRegRefData(): no region selection made"); 1019 return; // no selection 1020 } 1021 1022 // TODO: do we need to do something with what's past the closing bracket 1023 // regStr = reg.substring(reg.indexOf('}') + 1); 1024 1025 StringTokenizer st = new StringTokenizer(regStr); 1026 int nSelections = st.countTokens(); 1027 if (nSelections <= 0) { 1028 Tools.showError(shell, "Select", 1029 "Could not show region reference data: no region selection made."); 1030 log.debug("showRegRefData(): no region selection made"); 1031 return; // no selection 1032 } 1033 1034 HObject obj = FileFormat.findObject(((HObject)dataObject).getFileFormat(), oidStr); 1035 if (obj == null || !(obj instanceof ScalarDS)) { 1036 Tools.showError(shell, "Select", "Could not show object reference data: invalid or null data"); 1037 log.debug("showRegRefData(): obj is null or not a Scalar Dataset"); 1038 return; 1039 } 1040 1041 ScalarDS dset = (ScalarDS)obj; 1042 ScalarDS dsetCopy = null; 1043 1044 // create an instance of the dataset constructor 1045 Constructor<? extends ScalarDS> constructor = null; 1046 Object[] paramObj = null; 1047 try { 1048 Class[] paramClass = {FileFormat.class, String.class, String.class}; 1049 constructor = dset.getClass().getConstructor(paramClass); 1050 paramObj = new Object[] {dset.getFileFormat(), dset.getName(), dset.getPath()}; 1051 } 1052 catch (Exception ex) { 1053 log.debug("showRegRefData(): constructor failure: ", ex); 1054 constructor = null; 1055 } 1056 1057 // load each selection into a separate dataset and display it in 1058 // a separate spreadsheet 1059 1060 while (st.hasMoreTokens()) { 1061 try { 1062 dsetCopy = constructor.newInstance(paramObj); 1063 } 1064 catch (Exception ex) { 1065 log.debug("showRegRefData(): constructor newInstance failure: ", ex); 1066 continue; 1067 } 1068 1069 if (dsetCopy == null) { 1070 log.debug("showRegRefData(): continue after null dataset copy"); 1071 continue; 1072 } 1073 1074 try { 1075 dsetCopy.init(); 1076 } 1077 catch (Exception ex) { 1078 log.debug("showRegRefData(): continue after copied dataset init failure: ", ex); 1079 continue; 1080 } 1081 1082 dsetCopy.getRank(); 1083 long[] start = dsetCopy.getStartDims(); 1084 long[] count = dsetCopy.getSelectedDims(); 1085 1086 // set the selected dimension sizes based on the region selection 1087 // info. 1088 int idx = 0; 1089 String sizeStr = null; 1090 String token = st.nextToken(); 1091 1092 token = token.replace('(', ' '); 1093 token = token.replace(')', ' '); 1094 if (isPointSelection) { 1095 // point selection 1096 StringTokenizer tmp = new StringTokenizer(token, ","); 1097 while (tmp.hasMoreTokens()) { 1098 count[idx] = 1; 1099 sizeStr = tmp.nextToken().trim(); 1100 start[idx] = Long.valueOf(sizeStr); 1101 idx++; 1102 } 1103 } 1104 else { 1105 // rectangle selection 1106 String startStr = token.substring(0, token.indexOf('-')); 1107 String endStr = token.substring(token.indexOf('-') + 1); 1108 StringTokenizer tmp = new StringTokenizer(startStr, ","); 1109 while (tmp.hasMoreTokens()) { 1110 sizeStr = tmp.nextToken().trim(); 1111 start[idx] = Long.valueOf(sizeStr); 1112 idx++; 1113 } 1114 1115 idx = 0; 1116 tmp = new StringTokenizer(endStr, ","); 1117 while (tmp.hasMoreTokens()) { 1118 sizeStr = tmp.nextToken().trim(); 1119 count[idx] = Long.valueOf(sizeStr) - start[idx] + 1; 1120 idx++; 1121 } 1122 } 1123 1124 try { 1125 dsetCopy.getData(); 1126 } 1127 catch (Exception ex) { 1128 log.debug("showRegRefData(): getData failure: ", ex); 1129 Tools.showError(shell, "Select", "Region Reference: " + ex.getMessage()); 1130 } 1131 1132 Class<?> theClass = null; 1133 String viewName = null; 1134 1135 switch (viewType) { 1136 case IMAGE: 1137 viewName = HDFView.getListOfImageViews().get(0); 1138 break; 1139 case TABLE: 1140 viewName = (String)HDFView.getListOfTableViews().get(0); 1141 break; 1142 default: 1143 viewName = null; 1144 } 1145 1146 try { 1147 theClass = Class.forName(viewName); 1148 } 1149 catch (Exception ex) { 1150 try { 1151 theClass = ViewProperties.loadExtClass().loadClass(viewName); 1152 } 1153 catch (Exception ex2) { 1154 theClass = null; 1155 } 1156 } 1157 1158 // Use default dataview 1159 if (theClass == null) { 1160 switch (viewType) { 1161 case IMAGE: 1162 viewName = ViewProperties.DEFAULT_IMAGEVIEW_NAME; 1163 break; 1164 case TABLE: 1165 viewName = ViewProperties.DEFAULT_SCALAR_DATASET_TABLEVIEW_NAME; 1166 break; 1167 default: 1168 viewName = null; 1169 } 1170 1171 try { 1172 theClass = Class.forName(viewName); 1173 } 1174 catch (Exception ex) { 1175 log.debug("showRegRefData(): no suitable display class found"); 1176 Tools.showError(shell, "Select", 1177 "Could not show reference data: no suitable display class found"); 1178 return; 1179 } 1180 } 1181 1182 HashMap map = new HashMap(1); 1183 map.put(ViewProperties.DATA_VIEW_KEY.OBJECT, dsetCopy); 1184 Object[] args = {viewer, map}; 1185 1186 try { 1187 Tools.newInstance(theClass, args); 1188 } 1189 catch (Exception ex) { 1190 log.debug("showRegRefData(): Could not show reference data: ", ex); 1191 Tools.showError(shell, "Select", "Could not show reference data: " + ex.toString()); 1192 } 1193 } // (st.hasMoreTokens()) 1194 } // end of showRegRefData() 1195 1196 /** 1197 * Display data pointed to by references. Data of each reference is shown in 1198 * a separate spreadsheet. The std. ref. information is stored in bytes 1199 * 1200 * @param refarr 1201 * the array of bytes that contain the std. ref information. 1202 * 1203 */ 1204 @Override 1205 @SuppressWarnings({"rawtypes", "unchecked"}) 1206 protected void showStdRefData(byte[] refarr) 1207 { 1208 if (refarr == null || H5ReferenceType.zeroArrayCheck(refarr)) { 1209 Tools.showError(shell, "Select", "Could not show region reference data: invalid or null data"); 1210 log.debug("showStdRefData(): ref is null or invalid"); 1211 return; 1212 } 1213 1214 H5ReferenceType refType = ((H5ReferenceType)dataObject.getDatatype()); 1215 H5ReferenceData refdata = refType.getReferenceData(refarr); 1216 /* get the filename associated with the reference */ 1217 String reffile = refdata.file_name; 1218 if ((refdata.ref_type == HDF5Constants.H5R_DATASET_REGION1) || 1219 (refdata.ref_type == HDF5Constants.H5R_DATASET_REGION2)) { 1220 String ref_ptr = refType.getReferenceRegion(refarr, false); 1221 if ("REGION_TYPE UNKNOWN".equals(refdata.region_type)) { 1222 String msg = "Reference to " + ref_ptr + " cannot be displayed in a table"; 1223 Tools.showInformation(shell, "Reference", msg); 1224 } 1225 else { 1226 showRegRefData(refarr); 1227 } 1228 } 1229 if (((refdata.ref_type == HDF5Constants.H5R_OBJECT1) && 1230 (refdata.obj_type == HDF5Constants.H5O_TYPE_DATASET)) || 1231 ((refdata.ref_type == HDF5Constants.H5R_OBJECT2) && 1232 (refdata.obj_type == HDF5Constants.H5O_TYPE_DATASET))) { 1233 String ref_obj = refdata.obj_name; 1234 showObjStdRefData(ref_obj); 1235 } 1236 else if (refdata.ref_type == HDF5Constants.H5R_ATTR) { 1237 String ref_attr_name = refdata.attr_name; 1238 String ref_obj_name = refdata.obj_name; 1239 showAttrStdRefData(ref_obj_name, ref_attr_name); 1240 } 1241 else if ("H5O_TYPE_OBJ_REF".equals(refdata.region_type)) { 1242 String msg = "Reference to " + refdata.obj_name + " cannot be displayed in a table"; 1243 // String ref_ptr = refType.getObjectReferenceName(refarr); 1244 Tools.showInformation(shell, "Reference", msg); 1245 } 1246 else { 1247 // Other types 1248 } 1249 } // end of showStdRefData(byte[] refarr) 1250 1251 /** 1252 * Display data pointed to by object references. Data of each object is shown in 1253 * a separate spreadsheet. 1254 * 1255 * @param ref 1256 * the string that contain the object reference information. 1257 * 1258 */ 1259 @SuppressWarnings({"rawtypes", "unchecked"}) 1260 protected void showObjStdRefData(String ref) 1261 { 1262 if (ref == null || (ref.length() <= 0) || (ref.compareTo("NULL") == 0)) { 1263 Tools.showError(shell, "Select", "Could not show object reference data: invalid or null data"); 1264 log.debug("showObjStdRefData(): ref is null or invalid"); 1265 return; 1266 } 1267 1268 HObject obj = FileFormat.findObject(((HObject)dataObject).getFileFormat(), ref); 1269 if (obj == null || !(obj instanceof ScalarDS)) { 1270 Tools.showError(shell, "Select", "Could not show object reference data: invalid or null data"); 1271 log.debug("showObjStdRefData(): obj is null or not a Scalar Dataset"); 1272 return; 1273 } 1274 1275 ScalarDS dset = (ScalarDS)obj; 1276 ScalarDS dsetCopy = null; 1277 1278 // create an instance of the dataset constructor 1279 Constructor<? extends ScalarDS> constructor = null; 1280 Object[] paramObj = null; 1281 Object data = null; 1282 1283 try { 1284 Class[] paramClass = {FileFormat.class, String.class, String.class}; 1285 constructor = dset.getClass().getConstructor(paramClass); 1286 paramObj = new Object[] {dset.getFileFormat(), dset.getName(), dset.getPath()}; 1287 dsetCopy = constructor.newInstance(paramObj); 1288 data = dsetCopy.getData(); 1289 } 1290 catch (Exception ex) { 1291 log.debug("showObjStdRefData(): couldn't show data: ", ex); 1292 Tools.showError(shell, "Select", "Object Reference: " + ex.getMessage()); 1293 data = null; 1294 } 1295 1296 if (data == null) 1297 return; 1298 1299 Class<?> theClass = null; 1300 String viewName = null; 1301 1302 switch (viewType) { 1303 case IMAGE: 1304 viewName = HDFView.getListOfImageViews().get(0); 1305 break; 1306 case TABLE: 1307 viewName = (String)HDFView.getListOfTableViews().get(0); 1308 break; 1309 default: 1310 viewName = null; 1311 } 1312 1313 try { 1314 theClass = Class.forName(viewName); 1315 } 1316 catch (Exception ex) { 1317 try { 1318 theClass = ViewProperties.loadExtClass().loadClass(viewName); 1319 } 1320 catch (Exception ex2) { 1321 theClass = null; 1322 } 1323 } 1324 1325 // Use default dataview 1326 if (theClass == null) { 1327 switch (viewType) { 1328 case IMAGE: 1329 viewName = ViewProperties.DEFAULT_IMAGEVIEW_NAME; 1330 break; 1331 case TABLE: 1332 viewName = ViewProperties.DEFAULT_SCALAR_DATASET_TABLEVIEW_NAME; 1333 break; 1334 default: 1335 viewName = null; 1336 } 1337 1338 try { 1339 theClass = Class.forName(viewName); 1340 } 1341 catch (Exception ex) { 1342 log.debug("showObjStdRefData(): no suitable display class found"); 1343 Tools.showError(shell, "Select", 1344 "Could not show reference data: no suitable display class found"); 1345 return; 1346 } 1347 } 1348 1349 HashMap map = new HashMap(1); 1350 map.put(ViewProperties.DATA_VIEW_KEY.OBJECT, dsetCopy); 1351 Object[] args = {viewer, map}; 1352 1353 try { 1354 Tools.newInstance(theClass, args); 1355 } 1356 catch (Exception ex) { 1357 log.debug("showObjStdRefData(): Could not show reference data: ", ex); 1358 Tools.showError(shell, "Select", "Could not show reference data: " + ex.toString()); 1359 } 1360 } 1361 1362 /** 1363 * Display data pointed to by attribute references. Data of each object is shown in 1364 * a separate spreadsheet. 1365 * 1366 * @param ref_obj_name 1367 * the string that contain the attribute reference information. 1368 * @param ref_attr_name 1369 * the string that contain the attribute reference information. 1370 * 1371 */ 1372 @SuppressWarnings({"rawtypes", "unchecked"}) 1373 protected void showAttrStdRefData(String ref_obj_name, String ref_attr_name) 1374 { 1375 if (ref_obj_name == null || (ref_obj_name.length() <= 0) || (ref_obj_name.compareTo("NULL") == 0)) { 1376 log.debug("showAttrStdRefData(): ref_obj_name is null or invalid"); 1377 Tools.showError(shell, "Select", 1378 "Could not show attribute reference data: invalid or null object name"); 1379 return; 1380 } 1381 1382 if (ref_attr_name == null || (ref_attr_name.length() <= 0) || 1383 (ref_attr_name.compareTo("NULL") == 0)) { 1384 log.debug("showAttrStdRefData(): ref_attr_name is null or invalid"); 1385 Tools.showError(shell, "Select", 1386 "Could not show attribute reference data: invalid or null attribute name"); 1387 return; 1388 } 1389 1390 // find the parent object first 1391 HObject obj = FileFormat.findObject(((HObject)dataObject).getFileFormat(), ref_obj_name); 1392 if (obj == null) { 1393 log.debug("showAttrStdRefData(): obj is null"); 1394 Tools.showError(shell, "Select", "Could not show attribute reference data: invalid or null data"); 1395 return; 1396 } 1397 List<Attribute> attrs = H5File.getAttribute(obj); 1398 if ((attrs == null) || (attrs.size() < 1)) { 1399 log.debug("showAttrStdRefData(): attrs is null"); 1400 Tools.showError(shell, "Select", "Could not show attribute reference data: no attributes found"); 1401 return; 1402 } 1403 H5ScalarAttr attr = null; 1404 H5ScalarAttr attrCopy = null; 1405 int n = attrs.size(); 1406 for (int i = 0; i < n; i++) { 1407 attr = (H5ScalarAttr)attrs.get(i); 1408 if (attr.getAttributeName().equals(ref_attr_name)) 1409 break; 1410 else 1411 attr = null; 1412 } 1413 1414 // create an instance of the Attribute constructor 1415 Constructor<? extends H5ScalarAttr> constructor = null; 1416 Object[] paramObj = null; 1417 Object data = null; 1418 1419 try { 1420 Class[] paramClass = {HObject.class, String.class, Datatype.class, long[].class}; 1421 constructor = attr.getClass().getConstructor(paramClass); 1422 paramObj = new Object[] {obj, attr.getName(), attr.getDatatype(), null}; 1423 attrCopy = constructor.newInstance(paramObj); 1424 data = attrCopy.getData(); 1425 } 1426 catch (Exception ex) { 1427 log.debug("showAttrStdRefData(): couldn't show data: ", ex); 1428 Tools.showError(shell, "Select", "Attribute Reference: " + ex.getMessage()); 1429 data = null; 1430 } 1431 1432 if (data == null) 1433 return; 1434 1435 Class<?> theClass = null; 1436 String viewName = null; 1437 1438 switch (viewType) { 1439 case IMAGE: 1440 viewName = HDFView.getListOfImageViews().get(0); 1441 break; 1442 case TABLE: 1443 viewName = (String)HDFView.getListOfTableViews().get(0); 1444 break; 1445 default: 1446 viewName = null; 1447 } 1448 1449 try { 1450 theClass = Class.forName(viewName); 1451 } 1452 catch (Exception ex) { 1453 try { 1454 theClass = ViewProperties.loadExtClass().loadClass(viewName); 1455 } 1456 catch (Exception ex2) { 1457 theClass = null; 1458 } 1459 } 1460 1461 // Use default dataview 1462 if (theClass == null) { 1463 switch (viewType) { 1464 case IMAGE: 1465 viewName = ViewProperties.DEFAULT_IMAGEVIEW_NAME; 1466 break; 1467 case TABLE: 1468 viewName = ViewProperties.DEFAULT_SCALAR_DATASET_TABLEVIEW_NAME; 1469 break; 1470 default: 1471 viewName = null; 1472 } 1473 1474 try { 1475 theClass = Class.forName(viewName); 1476 } 1477 catch (Exception ex) { 1478 log.debug("showAttrStdRefData(): no suitable display class found"); 1479 Tools.showError(shell, "Select", 1480 "Could not show reference data: no suitable display class found"); 1481 return; 1482 } 1483 } 1484 1485 HashMap map = new HashMap(1); 1486 map.put(ViewProperties.DATA_VIEW_KEY.OBJECT, attrCopy); 1487 Object[] args = {viewer, map}; 1488 1489 try { 1490 Tools.newInstance(theClass, args); 1491 } 1492 catch (Exception ex) { 1493 log.debug("showAttrStdRefData(): Could not show reference data: ", ex); 1494 Tools.showError(shell, "Select", "Could not show reference data: " + ex.toString()); 1495 } 1496 } 1497 1498 /** 1499 * Update cell value label and cell value field when a cell is selected 1500 */ 1501 private class ScalarDSCellSelectionListener implements ILayerListener { 1502 @Override 1503 public void handleLayerEvent(ILayerEvent e) 1504 { 1505 if (e instanceof CellSelectionEvent) { 1506 CellSelectionEvent event = (CellSelectionEvent)e; 1507 Object val = 1508 dataTable.getDataValueByPosition(event.getColumnPosition(), event.getRowPosition()); 1509 String strVal = null; 1510 1511 String[] columnNames = 1512 ((ScalarDSColumnHeaderDataProvider)columnHeaderDataProvider).columnNames; 1513 int rowStart = ((RowHeaderDataProvider)rowHeaderDataProvider).start; 1514 int rowStride = ((RowHeaderDataProvider)rowHeaderDataProvider).stride; 1515 1516 cellLabel.setText( 1517 String.valueOf(rowStart + indexBase + 1518 dataTable.getRowIndexByPosition(event.getRowPosition()) * rowStride) + 1519 ", " + columnNames[dataTable.getColumnIndexByPosition(event.getColumnPosition())] + 1520 " = "); 1521 1522 if (val == null) { 1523 cellValueField.setText("Null"); 1524 ((ScrolledComposite)cellValueField.getParent()) 1525 .setMinSize(cellValueField.computeSize(SWT.DEFAULT, SWT.DEFAULT)); 1526 return; 1527 } 1528 1529 if (isStdRef) { 1530 boolean displayValues = ViewProperties.showRegRefValues(); 1531 1532 if (displayValues && val != null && 1533 !(val instanceof String)) { //((String) val).compareTo("NULL") != 0) { 1534 strVal = 1535 ((H5ReferenceType)dataObject.getDatatype()).getReferenceRegion((byte[])val, true); 1536 } 1537 } 1538 else if (isRegRef) { 1539 boolean displayValues = ViewProperties.showRegRefValues(); 1540 1541 if (displayValues && val != null && ((String)val).compareTo("NULL") != 0) { 1542 String reg = (String)val; 1543 boolean isPointSelection = (reg.indexOf('-') <= 0); 1544 1545 // find the object location 1546 String oidStr = reg.substring(reg.indexOf('/'), reg.indexOf(' ')); 1547 1548 // decode the region selection 1549 String regStr = reg.substring(reg.indexOf('{') + 1, reg.indexOf('}')); 1550 1551 // no selection 1552 if (regStr == null || regStr.length() <= 0) { 1553 log.debug("ScalarDSCellSelectionListener:RegRef CellSelected: no selection made"); 1554 strVal = null; 1555 } 1556 else { 1557 // TODO: do we need to do something with what's past the closing bracket 1558 // regStr = reg.substring(reg.indexOf('}') + 1); 1559 1560 StringTokenizer st = new StringTokenizer(regStr); 1561 int nSelections = st.countTokens(); 1562 if (nSelections <= 0) { // no selection 1563 strVal = null; 1564 } 1565 else { 1566 HObject obj = 1567 FileFormat.findObject(((HObject)dataObject).getFileFormat(), oidStr); 1568 if (obj == null || !(obj instanceof ScalarDS)) { // no selection 1569 strVal = null; 1570 } 1571 else { 1572 ScalarDS dset = (ScalarDS)obj; 1573 try { 1574 dset.init(); 1575 } 1576 catch (Exception ex) { 1577 log.debug( 1578 "ScalarDSCellSelectionListener:RegRef CellSelected: reference dset did not init()", 1579 ex); 1580 } 1581 StringBuilder strvalSB = new StringBuilder(); 1582 1583 int idx = 0; 1584 while (st.hasMoreTokens()) { 1585 int space_type = dset.getSpaceType(); 1586 int rank = dset.getRank(); 1587 long[] start = dset.getStartDims(); 1588 long[] count = dset.getSelectedDims(); 1589 // long count[] = new long[rank]; 1590 1591 // set the selected dimension sizes 1592 // based on the region selection 1593 // info. 1594 String sizeStr = null; 1595 String token = st.nextToken(); 1596 1597 token = token.replace('(', ' '); 1598 token = token.replace(')', ' '); 1599 if (isPointSelection) { 1600 // point selection 1601 String[] tmp = token.split(","); 1602 for (int x = 0; x < tmp.length; x++) { 1603 count[x] = 1; 1604 sizeStr = tmp[x].trim(); 1605 start[x] = Long.valueOf(sizeStr); 1606 log.trace( 1607 "ScalarDSCellSelectionListener:RegRef CellSelected: point sel={}", 1608 tmp[x]); 1609 } 1610 } 1611 else { 1612 // rectangle selection 1613 String startStr = token.substring(0, token.indexOf('-')); 1614 String endStr = token.substring(token.indexOf('-') + 1); 1615 log.trace( 1616 "ScalarDSCellSelectionListener:RegRef CellSelected: rect sel with startStr={} endStr={}", 1617 startStr, endStr); 1618 String[] tmp = startStr.split(","); 1619 log.trace( 1620 "ScalarDSCellSelectionListener:RegRef CellSelected: tmp with length={} rank={}", 1621 tmp.length, rank); 1622 for (int x = 0; x < tmp.length; x++) { 1623 sizeStr = tmp[x].trim(); 1624 start[x] = Long.valueOf(sizeStr); 1625 log.trace( 1626 "ScalarDSCellSelectionListener:RegRef CellSelected: rect start={}", 1627 tmp[x]); 1628 } 1629 tmp = endStr.split(","); 1630 for (int x = 0; x < tmp.length; x++) { 1631 sizeStr = tmp[x].trim(); 1632 count[x] = Long.valueOf(sizeStr) - start[x] + 1; 1633 log.trace( 1634 "ScalarDSCellSelectionListener:RegRef CellSelected: rect end={} count={}", 1635 tmp[x], count[x]); 1636 } 1637 } 1638 1639 Object dbuf = null; 1640 try { 1641 dbuf = dset.getData(); 1642 } 1643 catch (Exception ex) { 1644 Tools.showError(shell, "Select", 1645 "Region Reference:" + ex.getMessage()); 1646 } 1647 1648 /* Convert dbuf to a displayable string */ 1649 char runtimeTypeClass = Utils.getJavaObjectRuntimeClass(dbuf); 1650 log.trace( 1651 "ScalarDSCellSelectionListener:RegRef CellSelected: cName={} runtimeTypeClass={}", 1652 dbuf.getClass().getName(), runtimeTypeClass); 1653 1654 if (idx > 0) 1655 strvalSB.append(','); 1656 1657 // convert numerical data into char 1658 // only possible cases are byte[] 1659 // and short[] (converted from 1660 // unsigned byte) 1661 Datatype dtype = dset.getDatatype(); 1662 Datatype baseType = dtype.getDatatypeBase(); 1663 log.trace( 1664 "ScalarDSCellSelectionListener:RegRef CellSelected: dtype={} baseType={}", 1665 dtype.getDescription(), baseType); 1666 if (baseType == null) 1667 baseType = dtype; 1668 if ((dtype.isArray() && baseType.isChar()) && 1669 ((runtimeTypeClass == 'B') || (runtimeTypeClass == 'S'))) { 1670 int n = Array.getLength(dbuf); 1671 log.trace( 1672 "ScalarDSCellSelectionListener:RegRef CellSelected charData length = {}", 1673 n); 1674 char[] charData = new char[n]; 1675 for (int i = 0; i < n; i++) { 1676 if (runtimeTypeClass == 'B') { 1677 charData[i] = (char)Array.getByte(dbuf, i); 1678 } 1679 else if (runtimeTypeClass == 'S') { 1680 charData[i] = (char)Array.getShort(dbuf, i); 1681 } 1682 } 1683 1684 strvalSB.append(charData); 1685 } 1686 else { 1687 // numerical values 1688 boolean isUnsigned = dtype.isUnsigned(); 1689 if (dtype.isArray()) 1690 isUnsigned = baseType.isUnsigned(); 1691 int n = Array.getLength(dbuf); 1692 if (isUnsigned) { 1693 switch (runtimeTypeClass) { 1694 case 'B': 1695 byte[] barray = (byte[])dbuf; 1696 short sValue = barray[0]; 1697 if (sValue < 0) { 1698 sValue += 256; 1699 } 1700 strvalSB.append(sValue); 1701 for (int i = 1; i < n; i++) { 1702 strvalSB.append(','); 1703 sValue = barray[i]; 1704 if (sValue < 0) { 1705 sValue += 256; 1706 } 1707 strvalSB.append(sValue); 1708 } 1709 break; 1710 case 'S': 1711 short[] sarray = (short[])dbuf; 1712 int iValue = sarray[0]; 1713 if (iValue < 0) { 1714 iValue += 65536; 1715 } 1716 strvalSB.append(iValue); 1717 for (int i = 1; i < n; i++) { 1718 strvalSB.append(','); 1719 iValue = sarray[i]; 1720 if (iValue < 0) { 1721 iValue += 65536; 1722 } 1723 strvalSB.append(iValue); 1724 } 1725 break; 1726 case 'I': 1727 int[] iarray = (int[])dbuf; 1728 long lValue = iarray[0]; 1729 if (lValue < 0) { 1730 lValue += 4294967296L; 1731 } 1732 strvalSB.append(lValue); 1733 for (int i = 1; i < n; i++) { 1734 strvalSB.append(','); 1735 lValue = iarray[i]; 1736 if (lValue < 0) { 1737 lValue += 4294967296L; 1738 } 1739 strvalSB.append(lValue); 1740 } 1741 break; 1742 case 'J': 1743 long[] larray = (long[])dbuf; 1744 Long l = larray[0]; 1745 String theValue = Long.toString(l); 1746 if (l < 0) { 1747 l = (l << 1) >>> 1; 1748 BigInteger big1 = 1749 new BigInteger("9223372036854775808"); // 2^65 1750 BigInteger big2 = new BigInteger(l.toString()); 1751 BigInteger big = big1.add(big2); 1752 theValue = big.toString(); 1753 } 1754 strvalSB.append(theValue); 1755 for (int i = 1; i < n; i++) { 1756 strvalSB.append(','); 1757 l = larray[i]; 1758 theValue = Long.toString(l); 1759 if (l < 0) { 1760 l = (l << 1) >>> 1; 1761 BigInteger big1 = 1762 new BigInteger("9223372036854775808"); // 2^65 1763 BigInteger big2 = new BigInteger(l.toString()); 1764 BigInteger big = big1.add(big2); 1765 theValue = big.toString(); 1766 } 1767 strvalSB.append(theValue); 1768 } 1769 break; 1770 default: 1771 strvalSB.append(Array.get(dbuf, 0)); 1772 for (int i = 1; i < n; i++) { 1773 strvalSB.append(','); 1774 strvalSB.append(Array.get(dbuf, i)); 1775 } 1776 break; 1777 } 1778 } 1779 else { 1780 for (int x = 0; x < n; x++) { 1781 Object theValue = Array.get(dbuf, x); 1782 if (x > 0) 1783 strvalSB.append(','); 1784 strvalSB.append(theValue); 1785 } 1786 } 1787 } 1788 idx++; 1789 dset.clearData(); 1790 } // (st.hasMoreTokens()) 1791 strVal = strvalSB.toString(); 1792 } 1793 } 1794 } 1795 } 1796 else { 1797 strVal = null; 1798 } 1799 } 1800 else if (isObjRef) { 1801 if (val != null && ((String)val).compareTo("NULL") != 0) { 1802 strVal = (String)val; 1803 } 1804 else { 1805 strVal = null; 1806 } 1807 } 1808 1809 if (strVal == null && val != null) 1810 strVal = dataDisplayConverter.canonicalToDisplayValue(val).toString(); 1811 1812 cellValueField.setText(strVal); 1813 ((ScrolledComposite)cellValueField.getParent()) 1814 .setMinSize(cellValueField.computeSize(SWT.DEFAULT, SWT.DEFAULT)); 1815 } 1816 } 1817 } 1818 1819 /** 1820 * Custom Column Header data provider to set column indices based on Index Base 1821 * for Scalar Datasets. 1822 */ 1823 private class ScalarDSColumnHeaderDataProvider implements IDataProvider { 1824 private final String columnNames[]; 1825 1826 private final int space_type; 1827 private final int rank; 1828 1829 private final long[] startArray; 1830 private final long[] strideArray; 1831 private final int[] selectedIndex; 1832 1833 private final int ncols; 1834 1835 public ScalarDSColumnHeaderDataProvider(DataFormat theDataObject) 1836 { 1837 space_type = theDataObject.getSpaceType(); 1838 rank = theDataObject.getRank(); 1839 1840 startArray = theDataObject.getStartDims(); 1841 strideArray = theDataObject.getStride(); 1842 selectedIndex = theDataObject.getSelectedIndex(); 1843 1844 if (rank > 1) { 1845 ncols = (int)theDataObject.getWidth(); 1846 1847 int start = (int)startArray[selectedIndex[1]]; 1848 int stride = (int)strideArray[selectedIndex[1]]; 1849 1850 columnNames = new String[ncols]; 1851 1852 for (int i = 0; i < ncols; i++) 1853 columnNames[i] = String.valueOf(start + indexBase + i * stride); 1854 } 1855 else { 1856 ncols = 1; 1857 1858 columnNames = new String[] {" "}; 1859 } 1860 } 1861 1862 @Override 1863 public int getColumnCount() 1864 { 1865 return ncols; 1866 } 1867 1868 @Override 1869 public int getRowCount() 1870 { 1871 return 1; 1872 } 1873 1874 @Override 1875 public Object getDataValue(int columnIndex, int rowIndex) 1876 { 1877 return columnNames[columnIndex]; 1878 } 1879 1880 @Override 1881 public void setDataValue(int columnIndex, int rowIndex, Object newValue) 1882 { 1883 // intentional 1884 } 1885 } 1886}