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