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