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; 016 017import java.io.BufferedInputStream; 018import java.io.BufferedOutputStream; 019import java.io.File; 020import java.io.FileOutputStream; 021import java.net.URL; 022import java.util.ArrayList; 023import java.util.Arrays; 024import java.util.Enumeration; 025import java.util.Iterator; 026import java.util.List; 027 028import org.eclipse.jface.preference.PreferenceManager; 029import org.eclipse.swt.SWT; 030import org.eclipse.swt.custom.SashForm; 031import org.eclipse.swt.custom.ScrolledComposite; 032import org.eclipse.swt.dnd.DND; 033import org.eclipse.swt.dnd.DropTarget; 034import org.eclipse.swt.dnd.DropTargetEvent; 035import org.eclipse.swt.dnd.DropTargetListener; 036import org.eclipse.swt.dnd.FileTransfer; 037import org.eclipse.swt.dnd.Transfer; 038import org.eclipse.swt.events.DisposeEvent; 039import org.eclipse.swt.events.DisposeListener; 040import org.eclipse.swt.events.KeyAdapter; 041import org.eclipse.swt.events.KeyEvent; 042import org.eclipse.swt.events.SelectionAdapter; 043import org.eclipse.swt.events.SelectionEvent; 044import org.eclipse.swt.graphics.Font; 045import org.eclipse.swt.graphics.Image; 046import org.eclipse.swt.graphics.Point; 047import org.eclipse.swt.graphics.Rectangle; 048import org.eclipse.swt.layout.FillLayout; 049import org.eclipse.swt.layout.GridData; 050import org.eclipse.swt.layout.GridLayout; 051import org.eclipse.swt.layout.RowLayout; 052import org.eclipse.swt.widgets.Button; 053import org.eclipse.swt.widgets.Combo; 054import org.eclipse.swt.widgets.Composite; 055import org.eclipse.swt.widgets.Control; 056import org.eclipse.swt.widgets.Dialog; 057import org.eclipse.swt.widgets.Display; 058import org.eclipse.swt.widgets.Event; 059import org.eclipse.swt.widgets.FileDialog; 060import org.eclipse.swt.widgets.Label; 061import org.eclipse.swt.widgets.Listener; 062import org.eclipse.swt.widgets.Menu; 063import org.eclipse.swt.widgets.MenuItem; 064import org.eclipse.swt.widgets.Monitor; 065import org.eclipse.swt.widgets.Shell; 066import org.eclipse.swt.widgets.Text; 067import org.eclipse.swt.widgets.ToolBar; 068import org.eclipse.swt.widgets.ToolItem; 069 070import hdf.HDFVersions; 071import hdf.object.FileFormat; 072import hdf.object.HObject; 073import hdf.view.ViewProperties.DataViewType; 074import hdf.view.DataView.DataView; 075import hdf.view.DataView.DataViewFactory; 076import hdf.view.DataView.DataViewFactoryProducer; 077import hdf.view.DataView.DataViewManager; 078import hdf.view.HelpView.HelpView; 079import hdf.view.MetaDataView.MetaDataView; 080import hdf.view.TableView.TableView; 081import hdf.view.TreeView.DefaultTreeView; 082import hdf.view.TreeView.TreeView; 083import hdf.view.dialog.ImageConversionDialog; 084import hdf.view.dialog.InputDialog; 085import hdf.view.dialog.UserOptionsDialog; 086import hdf.view.dialog.UserOptionsGeneralPage; 087import hdf.view.dialog.UserOptionsHDFPage; 088import hdf.view.dialog.UserOptionsNode; 089import hdf.view.dialog.UserOptionsViewModulesPage; 090 091 092/** 093 * HDFView is the main class of this HDF visual tool. It is used to layout the 094 * graphical components of the hdfview. The major GUI components of the HDFView 095 * include Menubar, Toolbar, TreeView, ContentView, and MessageArea. 096 * <p> 097 * The HDFView is designed in such a way that it does not have direct access to 098 * the HDF library. All the HDF library access is done through HDF objects. 099 * Therefore, the HDFView package depends on the object package but not the 100 * library package. The source code of the view package (hdf.view) should 101 * be compiled with the library package (hdf.hdflib and hdf.hdf5lib). 102 * 103 * @author Jordan T. Henderson 104 * @version 2.4 //2015 105 */ 106public class HDFView implements DataViewManager { 107 108 private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(HDFView.class); 109 110 private static Display display; 111 private static Shell mainWindow; 112 113 /* Determines whether HDFView is being executed for GUI testing */ 114 private boolean isTesting = false; 115 116 /* The directory where HDFView is installed */ 117 private String rootDir; 118 119 /* The current working directory */ 120 private String currentDir; 121 122 /* The current working file */ 123 private String currentFile = null; 124 125 /* The view properties */ 126 private ViewProperties props; 127 128 /* A list of tree view implementations. */ 129 private static List<String> treeViews; 130 131 /* A list of image view implementations. */ 132 private static List<String> imageViews; 133 134 /* A list of tree table implementations. */ 135 private static List<?> tableViews; 136 137 /* A list of metadata view implementations. */ 138 private static List<?> metaDataViews; 139 140 /* A list of palette view implementations. */ 141 private static List<?> paletteViews; 142 143 /* A list of help view implementations. */ 144 private static List<?> helpViews; 145 146 /* The list of GUI components related to NetCDF3 */ 147 private final List<MenuItem> n3GUIs = new ArrayList<>(); 148 149 /* The list of GUI components related to HDF4 */ 150 private final List<MenuItem> h4GUIs = new ArrayList<>(); 151 152 /* The list of GUI components related to HDF5 */ 153 private final List<MenuItem> h5GUIs = new ArrayList<>(); 154 155 /* The list of GUI components related to editing */ 156 //private final List<?> editGUIs; 157 158 /* GUI component: the TreeView */ 159 private TreeView treeView = null; 160 161 private static final String HDF4_VERSION = HDFVersions.HDF4_VERSION; 162 private static final String HDF5_VERSION = HDFVersions.HDF5_VERSION; 163 private static final String HDFVIEW_VERSION = HDFVersions.HDFVIEW_VERSION; 164 private static final String HDFVIEW_USERSGUIDE_URL = "https://portal.hdfgroup.org/display/HDFVIEW/HDFView+3.x+User%27s+Guide"; 165 private static final String JAVA_COMPILER = "jdk 1.11"; 166 private static final String JAVA_VER_INFO = "Compiled at " + JAVA_COMPILER + "\nRunning at " + System.getProperty("java.version"); 167 168 private static final String ABOUT_HDFVIEW = "HDF Viewer, " + "Version " + ViewProperties.VERSION + "\n" 169 + "For " + System.getProperty("os.name") + "\n\n" 170 + "Copyright " + '\u00a9' + " 2006-2020 The HDF Group.\n" 171 + "All rights reserved."; 172 173 /* GUI component: The toolbar for open, close, help and hdf4 and hdf5 library information */ 174 private ToolBar toolBar; 175 176 /* GUI component: The text area for showing status messages */ 177 private Text status; 178 179 /* GUI component: The area for quick general view */ 180 private ScrolledComposite generalArea; 181 182 /* GUI component: To add and display URLs */ 183 private Combo urlBar; 184 185 private Button recentFilesButton; 186 private Button clearTextButton; 187 188 /* GUI component: A list of current data windows */ 189 private Menu windowMenu; 190 191 /* GUI component: File menu on the menubar */ 192 //private final Menu fileMenu; 193 194 /* The font to be used for display text on all Controls */ 195 private Font currentFont; 196 197 private UserOptionsDialog userOptionDialog; 198 199 /** 200 * Constructs HDFView with a given root directory, where the HDFView is 201 * installed, and opens the given files in the viewer. 202 * 203 * @param root 204 * the directory where the HDFView is installed. 205 */ 206 public HDFView(String root) { 207 log.debug("Root is {}", root); 208 209 if (display == null || display.isDisposed()) display = new Display(); 210 211 rootDir = root; 212 213 //editGUIs = new Vector<Object>(); 214 215 props = new ViewProperties(rootDir); 216 try { 217 props.load(); 218 } 219 catch (Exception ex) { 220 log.debug("Failed to load View Properties from {}", rootDir); 221 } 222 223 ViewProperties.loadIcons(); 224 225 String workDir = System.getProperty("hdfview.workdir"); 226 if (workDir != null) 227 currentDir = workDir; 228 else 229 currentDir = ViewProperties.getWorkDir(); 230 231 if (currentDir == null) 232 currentDir = System.getProperty("user.home"); 233 234 log.info("Current directory is {}", currentDir); 235 236 try { 237 currentFont = new Font( 238 display, 239 ViewProperties.getFontType(), 240 ViewProperties.getFontSize(), 241 SWT.NORMAL); 242 } 243 catch (Exception ex) { 244 currentFont = null; 245 } 246 247 treeViews = ViewProperties.getTreeViewList(); 248 metaDataViews = ViewProperties.getMetaDataViewList(); 249 tableViews = ViewProperties.getTableViewList(); 250 imageViews = ViewProperties.getImageViewList(); 251 paletteViews = ViewProperties.getPaletteViewList(); 252 helpViews = ViewProperties.getHelpViewList(); 253 254 log.debug("Constructor exit"); 255 } 256 257 258 /** 259 * Creates HDFView with a given size, and opens the given files in the viewer. 260 * 261 * @param flist 262 * a list of files to open. 263 * @param width 264 * the width of the app in pixels 265 * @param height 266 * the height of the app in pixels 267 * @param x 268 * the coord x of the app in pixels 269 * @param y 270 * the coord y of the app in pixels 271 * 272 * @return 273 * the newly-created HDFView Shell 274 */ 275 public Shell openMainWindow(List<File> flist, int width, int height, int x, int y) { 276 log.debug("openMainWindow enter"); 277 278 // Initialize all GUI components 279 mainWindow = createMainWindow(); 280 281 try { 282 Font font = null; 283 String fType = ViewProperties.getFontType(); 284 int fSize = ViewProperties.getFontSize(); 285 286 try { 287 font = new Font(display, fType, fSize, SWT.NORMAL); 288 } 289 catch (Exception ex) { 290 font = null; 291 } 292 293 if (font != null) 294 updateFont(font); 295 } 296 catch (Exception ex) { 297 log.debug("Failed to load Font properties"); 298 } 299 300 // Make sure all GUI components are in place before 301 // opening any files 302 mainWindow.pack(); 303 304 int nfiles = flist.size(); 305 File theFile = null; 306 for (int i = 0; i < nfiles; i++) { 307 theFile = flist.get(i); 308 309 if (theFile.isFile()) { 310 currentDir = theFile.getParentFile().getAbsolutePath(); 311 currentFile = theFile.getAbsolutePath(); 312 313 try { 314 treeView.openFile(currentFile, FileFormat.WRITE); 315 316 try { 317 urlBar.remove(currentFile); 318 } 319 catch (Exception ex) {} 320 321 urlBar.add(currentFile, 0); 322 urlBar.select(0); 323 } 324 catch (Exception ex) { 325 showError(ex.toString()); 326 } 327 } 328 else { 329 currentDir = theFile.getAbsolutePath(); 330 } 331 332 log.info("CurrentDir is {}", currentDir); 333 } 334 335 if (FileFormat.getFileFormat(FileFormat.FILE_TYPE_NC3) == null) 336 setEnabled(n3GUIs, false); 337 338 if (FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF4) == null) 339 setEnabled(h4GUIs, false); 340 341 if (FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF5) == null) 342 setEnabled(h5GUIs, false); 343 344 // Set size of main window 345 // float inset = 0.17f; // for UG only. 346 float inset = 0.04f; 347 Point winDim = new Point(width, height); 348 349 // If given height and width are too small, adjust accordingly 350 if (height <= 300) { 351 winDim.y = (int) ((1 - 2 * inset) * mainWindow.getSize().y); 352 } 353 354 if (width <= 300) { 355 winDim.x = (int) (0.9 * mainWindow.getSize().y); 356 } 357 358 mainWindow.setLocation(x, y); 359 mainWindow.setSize(winDim.x + 200, winDim.y); 360 361 // Display the window 362 mainWindow.open(); 363 log.debug("openMainWindow exit"); 364 return mainWindow; 365 } 366 367 public void runMainWindow() { 368 log.debug("runMainWindow enter"); 369 370 while(!mainWindow.isDisposed()) { 371 // =================================================== 372 // Wrap each event dispatch in an exception handler 373 // so that if any event causes an exception it does 374 // not break the main UI loop 375 // =================================================== 376 try { 377 if (!display.readAndDispatch()) { 378 display.sleep(); 379 } 380 } 381 catch (Exception e) { 382 e.printStackTrace(); 383 } 384 } 385 386 if (!isTesting) display.dispose(); 387 log.debug("runMainWindow exit"); 388 } 389 390 /** 391 * Creates and lays out GUI components. 392 * 393 * <pre> 394 * ||=========||=============================|| 395 * || || || 396 * || || || 397 * || TreeView|| ContentPane || 398 * || || || 399 * ||=========||=============================|| 400 * || Message Area || 401 * ||========================================|| 402 * </pre> 403 */ 404 private Shell createMainWindow() { 405 // Create a new display window 406 final Shell shell = new Shell(display); 407 shell.setImage(ViewProperties.getHdfIcon()); 408 shell.setFont(currentFont); 409 shell.setText("HDFView " + HDFVIEW_VERSION); 410 shell.setLayout(new GridLayout(3, false)); 411 shell.addDisposeListener(new DisposeListener() { 412 @Override 413 public void widgetDisposed(DisposeEvent e) { 414 ViewProperties.setRecentFiles(new ArrayList<>(Arrays.asList(urlBar.getItems()))); 415 416 try { 417 props.save(); 418 } 419 catch (Exception ex) {} 420 421 closeAllWindows(); 422 423 // Close all open files 424 try { 425 List<FileFormat> filelist = treeView.getCurrentFiles(); 426 427 if ((filelist != null) && !filelist.isEmpty()) { 428 Object[] files = filelist.toArray(); 429 430 for (int i = 0; i < files.length; i++) { 431 try { 432 treeView.closeFile((FileFormat) files[i]); 433 } 434 catch (Exception ex) { 435 continue; 436 } 437 } 438 } 439 } 440 catch (Exception ex) {} 441 442 if (currentFont != null) currentFont.dispose(); 443 } 444 }); 445 446 createMenuBar(shell); 447 createToolbar(shell); 448 createUrlToolbar(shell); 449 createContentArea(shell); 450 451 log.info("Main Window created"); 452 453 return shell; 454 } 455 456 private void createMenuBar(final Shell shell) { 457 Menu menu = new Menu(shell, SWT.BAR); 458 shell.setMenuBar(menu); 459 460 MenuItem menuItem = new MenuItem(menu, SWT.CASCADE); 461 menuItem.setText("&File"); 462 463 Menu fileMenu = new Menu(menuItem); 464 menuItem.setMenu(fileMenu); 465 466 MenuItem item = new MenuItem(fileMenu, SWT.PUSH); 467 item.setText("&Open\tCtrl-O"); 468 item.setAccelerator(SWT.MOD1 + 'O'); 469 item.addSelectionListener(new SelectionAdapter() { 470 @Override 471 public void widgetSelected(SelectionEvent e) { 472 openLocalFile(null, -1); 473 } 474 }); 475 476 item = new MenuItem(fileMenu, SWT.CASCADE); 477 item.setText("Open As"); 478 479 Menu openAsMenu = new Menu(item); 480 item.setMenu(openAsMenu); 481 482 item = new MenuItem(openAsMenu, SWT.PUSH); 483 item.setText("Read-Only"); 484 item.addSelectionListener(new SelectionAdapter() { 485 @Override 486 public void widgetSelected(SelectionEvent e) { 487 openLocalFile(null, FileFormat.READ); 488 } 489 }); 490 491 item = new MenuItem(openAsMenu, SWT.PUSH); 492 item.setText("Read/Write"); 493 item.addSelectionListener(new SelectionAdapter() { 494 @Override 495 public void widgetSelected(SelectionEvent e) { 496 openLocalFile(null, FileFormat.WRITE); 497 } 498 }); 499 500 new MenuItem(fileMenu, SWT.SEPARATOR); 501 502 MenuItem fileNewMenu = new MenuItem(fileMenu, SWT.CASCADE); 503 fileNewMenu.setText("New"); 504 505 Menu newMenu = new Menu(fileNewMenu); 506 fileNewMenu.setMenu(newMenu); 507 508 item = new MenuItem(newMenu, SWT.PUSH); 509 item.setText("HDF&4"); 510 h4GUIs.add(item); 511 item.addSelectionListener(new SelectionAdapter() { 512 @Override 513 public void widgetSelected(SelectionEvent e) { 514 if (currentDir != null) { 515 currentDir += File.separator; 516 } 517 else { 518 currentDir = ""; 519 } 520 521 String filename = null; 522 523 if (!isTesting) { 524 FileDialog fChooser = new FileDialog(shell, SWT.SAVE); 525 fChooser.setFileName(Tools.checkNewFile(currentDir, ".hdf").getName()); 526 527 DefaultFileFilter filter = DefaultFileFilter.getFileFilterHDF4(); 528 fChooser.setFilterExtensions(new String[] {filter.getExtensions()}); 529 fChooser.setFilterNames(new String[] {filter.getDescription()}); 530 fChooser.setFilterIndex(0); 531 532 filename = fChooser.open(); 533 } 534 else { 535 // Prepend test file directory to filename 536 filename = currentDir.concat(new InputDialog(mainWindow, "Enter a file name", "").open()); 537 } 538 539 if(filename == null) return; 540 541 try { 542 log.trace("HDFView create hdf4 file"); 543 FileFormat theFile = Tools.createNewFile(filename, currentDir, 544 FileFormat.FILE_TYPE_HDF4, getTreeView().getCurrentFiles()); 545 546 if (theFile == null) return; 547 548 currentDir = theFile.getParent(); 549 } 550 catch (Exception ex) { 551 Tools.showError(mainWindow, "New", ex.getMessage()); 552 return; 553 } 554 555 try { 556 treeView.openFile(filename, FileFormat.WRITE); 557 currentFile = filename; 558 559 try { 560 urlBar.remove(filename); 561 } 562 catch (Exception ex) { 563 log.debug("unable to remove {} from urlBar", filename); 564 } 565 566 urlBar.add(filename, 0); 567 urlBar.select(0); 568 } 569 catch (Exception ex) { 570 display.beep(); 571 Tools.showError(mainWindow, "New", ex.getMessage() + "\n" + filename); 572 } 573 } 574 }); 575 576 item = new MenuItem(newMenu, SWT.PUSH); 577 item.setText("HDF&5"); 578 h5GUIs.add(item); 579 item.addSelectionListener(new SelectionAdapter() { 580 @Override 581 public void widgetSelected(SelectionEvent e) { 582 if (currentDir != null) { 583 currentDir += File.separator; 584 } 585 else { 586 currentDir = ""; 587 } 588 589 String filename = null; 590 591 if (!isTesting) { 592 FileDialog fChooser = new FileDialog(shell, SWT.SAVE); 593 fChooser.setFileName(Tools.checkNewFile(currentDir, ".h5").getName()); 594 595 DefaultFileFilter filter = DefaultFileFilter.getFileFilterHDF5(); 596 fChooser.setFilterExtensions(new String[] {filter.getExtensions()}); 597 fChooser.setFilterNames(new String[] {filter.getDescription()}); 598 fChooser.setFilterIndex(0); 599 600 filename = fChooser.open(); 601 } 602 else { 603 // Prepend test file directory to filename 604 filename = currentDir.concat(new InputDialog(mainWindow, "Enter a file name", "").open()); 605 } 606 607 if(filename == null) return; 608 609 try { 610 log.trace("HDFView create hdf5 file"); 611 FileFormat theFile = Tools.createNewFile(filename, currentDir, 612 FileFormat.FILE_TYPE_HDF5, getTreeView().getCurrentFiles()); 613 614 if (theFile == null) return; 615 616 currentDir = theFile.getParent(); 617 } 618 catch (Exception ex) { 619 Tools.showError(mainWindow, "New", ex.getMessage()); 620 return; 621 } 622 623 try { 624 treeView.openFile(filename, FileFormat.WRITE); 625 currentFile = filename; 626 627 try { 628 urlBar.remove(filename); 629 } 630 catch (Exception ex) { 631 log.debug("unable to remove {} from urlBar", filename); 632 } 633 634 urlBar.add(filename, 0); 635 urlBar.select(0); 636 } 637 catch (Exception ex) { 638 display.beep(); 639 Tools.showError(mainWindow, "New", ex.getMessage() + "\n" + filename); 640 } 641 } 642 }); 643 644 new MenuItem(fileMenu, SWT.SEPARATOR); 645 646 item = new MenuItem(fileMenu, SWT.PUSH); 647 item.setText("&Close"); 648 item.addSelectionListener(new SelectionAdapter() { 649 @Override 650 public void widgetSelected(SelectionEvent e) { 651 closeFile(treeView.getSelectedFile()); 652 } 653 }); 654 655 item = new MenuItem(fileMenu, SWT.PUSH); 656 item.setText("Close &All"); 657 item.addSelectionListener(new SelectionAdapter() { 658 @Override 659 public void widgetSelected(SelectionEvent e) { 660 closeAllWindows(); 661 662 List<FileFormat> files = treeView.getCurrentFiles(); 663 while (!files.isEmpty()) { 664 try { 665 treeView.closeFile(files.get(0)); 666 } 667 catch (Exception ex) { 668 log.trace("unable to close {} in treeView", files.get(0)); 669 } 670 } 671 672 currentFile = null; 673 674 for (Control control : generalArea.getChildren()) control.dispose(); 675 generalArea.setContent(null); 676 677 urlBar.setText(""); 678 } 679 }); 680 681 new MenuItem(fileMenu, SWT.SEPARATOR); 682 683 item = new MenuItem(fileMenu, SWT.PUSH); 684 item.setText("&Save"); 685 item.addSelectionListener(new SelectionAdapter() { 686 @Override 687 public void widgetSelected(SelectionEvent e) { 688 if (treeView.getCurrentFiles().isEmpty()) { 689 Tools.showError(mainWindow, "Save", "No files currently open."); 690 return; 691 } 692 693 if (treeView.getSelectedFile() == null) { 694 Tools.showError(mainWindow, "Save", "No files currently selected."); 695 return; 696 } 697 698 // Save what has been changed in memory into file 699 writeDataToFile(treeView.getSelectedFile()); 700 } 701 }); 702 703 item = new MenuItem(fileMenu, SWT.PUSH); 704 item.setText("S&ave As"); 705 item.addSelectionListener(new SelectionAdapter() { 706 @Override 707 public void widgetSelected(SelectionEvent e) { 708 if (treeView.getCurrentFiles().isEmpty()) { 709 Tools.showError(mainWindow, "Save", "No files currently open."); 710 return; 711 } 712 713 if (treeView.getSelectedFile() == null) { 714 Tools.showError(mainWindow, "Save", "No files currently selected."); 715 return; 716 } 717 718 try { 719 treeView.saveFile(treeView.getSelectedFile()); 720 } 721 catch (Exception ex) { 722 display.beep(); 723 Tools.showError(mainWindow, "Save", ex.getMessage()); 724 } 725 } 726 }); 727 728 new MenuItem(fileMenu, SWT.SEPARATOR); 729 730 item = new MenuItem(fileMenu, SWT.PUSH); 731 item.setText("E&xit\tCtrl-Q"); 732 item.setAccelerator(SWT.MOD1 + 'Q'); 733 item.addSelectionListener(new SelectionAdapter() { 734 @Override 735 public void widgetSelected(SelectionEvent e) { 736 mainWindow.dispose(); 737 } 738 }); 739 740 menuItem = new MenuItem(menu, SWT.CASCADE); 741 menuItem.setText("&Window"); 742 743 windowMenu = new Menu(menuItem); 744 menuItem.setMenu(windowMenu); 745 746 item = new MenuItem(windowMenu, SWT.PUSH); 747 item.setText("&Cascade"); 748 item.addSelectionListener(new SelectionAdapter() { 749 @Override 750 public void widgetSelected(SelectionEvent e) { 751 cascadeWindows(); 752 } 753 }); 754 755 item = new MenuItem(windowMenu, SWT.PUSH); 756 item.setText("&Tile"); 757 item.addSelectionListener(new SelectionAdapter() { 758 @Override 759 public void widgetSelected(SelectionEvent e) { 760 tileWindows(); 761 } 762 }); 763 764 new MenuItem(windowMenu, SWT.SEPARATOR); 765 766 item = new MenuItem(windowMenu, SWT.PUSH); 767 item.setText("Close &All"); 768 item.addSelectionListener(new SelectionAdapter() { 769 @Override 770 public void widgetSelected(SelectionEvent e) { 771 closeAllWindows(); 772 } 773 }); 774 775 new MenuItem(windowMenu, SWT.SEPARATOR); 776 777 menuItem = new MenuItem(menu, SWT.CASCADE); 778 menuItem.setText("&Tools"); 779 780 Menu toolsMenu = new Menu(menuItem); 781 menuItem.setMenu(toolsMenu); 782 783 MenuItem convertMenuItem = new MenuItem(toolsMenu, SWT.CASCADE); 784 convertMenuItem.setText("Convert Image To"); 785 786 Menu convertMenu = new Menu(convertMenuItem); 787 convertMenuItem.setMenu(convertMenu); 788 789 item = new MenuItem(convertMenu, SWT.PUSH); 790 item.setText("HDF4"); 791 item.addSelectionListener(new SelectionAdapter() { 792 @Override 793 public void widgetSelected(SelectionEvent e) { 794 convertFile(Tools.FILE_TYPE_IMAGE, FileFormat.FILE_TYPE_HDF4); 795 } 796 }); 797 h4GUIs.add(item); 798 799 item = new MenuItem(convertMenu, SWT.PUSH); 800 item.setText("HDF5"); 801 item.addSelectionListener(new SelectionAdapter() { 802 @Override 803 public void widgetSelected(SelectionEvent e) { 804 convertFile(Tools.FILE_TYPE_IMAGE, FileFormat.FILE_TYPE_HDF5); 805 } 806 }); 807 h5GUIs.add(item); 808 809 new MenuItem(toolsMenu, SWT.SEPARATOR); 810 811 item = new MenuItem(toolsMenu, SWT.PUSH); 812 item.setText("User &Options"); 813 item.addSelectionListener(new SelectionAdapter() { 814 @Override 815 public void widgetSelected(SelectionEvent e) { 816 // Create the preference manager 817 PreferenceManager mgr = new PreferenceManager(); 818 819 // Create the nodes 820 UserOptionsNode one = new UserOptionsNode("general", new UserOptionsGeneralPage()); 821 UserOptionsNode two = new UserOptionsNode("hdf", new UserOptionsHDFPage()); 822 UserOptionsNode three = new UserOptionsNode("modules", new UserOptionsViewModulesPage()); 823 824 // Add the nodes 825 mgr.addToRoot(one); 826 mgr.addToRoot(two); 827 mgr.addToRoot(three); 828 829 // Create the preferences dialog 830 userOptionDialog = new UserOptionsDialog(shell, mgr, rootDir); 831 832 // Set the preference store 833 userOptionDialog.setPreferenceStore(props); 834 userOptionDialog.create(); 835 836 // Open the dialog 837 userOptionDialog.open(); 838 839 // TODO: this functionality is currently broken because isWorkDirChanged() is not exposed correctly. 840 // if (userOptionDialog.isWorkDirChanged()) 841 // currentDir = ViewProperties.getWorkDir(); 842 843 //if (userOptionDialog.isFontChanged()) { 844 Font font = null; 845 846 try { 847 font = new Font(display, ViewProperties.getFontType(), ViewProperties.getFontSize(), SWT.NORMAL); 848 } 849 catch (Exception ex) { 850 font = null; 851 } 852 853 updateFont(font); 854 //} 855 } 856 }); 857 858 new MenuItem(toolsMenu, SWT.SEPARATOR); 859 860 item = new MenuItem(toolsMenu, SWT.PUSH); 861 item.setText("&Register File Format"); 862 item.addSelectionListener(new SelectionAdapter() { 863 @Override 864 public void widgetSelected(SelectionEvent e) { 865 registerFileFormat(); 866 } 867 }); 868 869 item = new MenuItem(toolsMenu, SWT.PUSH); 870 item.setText("&Unregister File Format"); 871 item.addSelectionListener(new SelectionAdapter() { 872 @Override 873 public void widgetSelected(SelectionEvent e) { 874 unregisterFileFormat(); 875 } 876 }); 877 878 menuItem = new MenuItem(menu, SWT.CASCADE); 879 menuItem.setText("&Help"); 880 881 Menu helpMenu = new Menu(menuItem); 882 menuItem.setMenu(helpMenu); 883 884 item = new MenuItem(helpMenu, SWT.PUSH); 885 item.setText("&User's Guide"); 886 item.addSelectionListener(new SelectionAdapter() { 887 @Override 888 public void widgetSelected(SelectionEvent e) { 889 org.eclipse.swt.program.Program.launch(HDFVIEW_USERSGUIDE_URL); 890 } 891 }); 892 893 if ((helpViews != null) && !helpViews.isEmpty()) { 894 int n = helpViews.size(); 895 for (int i = 0; i < n; i++) { 896 HelpView theView = (HelpView) helpViews.get(i); 897 item = new MenuItem(helpMenu, SWT.PUSH); 898 item.setText(theView.getLabel()); 899 //item.setActionCommand(theView.getActionCommand()); 900 } 901 } 902 903 new MenuItem(helpMenu, SWT.SEPARATOR); 904 905 item = new MenuItem(helpMenu, SWT.PUSH); 906 item.setText("HDF&4 Library Version"); 907 h4GUIs.add(item); 908 item.addSelectionListener(new SelectionAdapter() { 909 @Override 910 public void widgetSelected(SelectionEvent e) { 911 new LibraryVersionDialog(shell, FileFormat.FILE_TYPE_HDF4).open(); 912 } 913 }); 914 915 item = new MenuItem(helpMenu, SWT.PUSH); 916 item.setText("HDF&5 Library Version"); 917 h5GUIs.add(item); 918 item.addSelectionListener(new SelectionAdapter() { 919 @Override 920 public void widgetSelected(SelectionEvent e) { 921 new LibraryVersionDialog(shell, FileFormat.FILE_TYPE_HDF5).open(); 922 } 923 }); 924 925 item = new MenuItem(helpMenu, SWT.PUSH); 926 item.setText("&Java Version"); 927 item.addSelectionListener(new SelectionAdapter() { 928 @Override 929 public void widgetSelected(SelectionEvent e) { 930 new JavaVersionDialog(mainWindow).open(); 931 } 932 }); 933 934 new MenuItem(helpMenu, SWT.SEPARATOR); 935 936 item = new MenuItem(helpMenu, SWT.PUSH); 937 item.setText("Supported Fi&le Formats"); 938 item.addSelectionListener(new SelectionAdapter() { 939 @Override 940 public void widgetSelected(SelectionEvent e) { 941 new SupportedFileFormatsDialog(mainWindow).open(); 942 } 943 }); 944 945 new MenuItem(helpMenu, SWT.SEPARATOR); 946 947 item = new MenuItem(helpMenu, SWT.PUSH); 948 item.setText("&About..."); 949 item.addSelectionListener(new SelectionAdapter() { 950 @Override 951 public void widgetSelected(SelectionEvent e) { 952 new AboutDialog(mainWindow).open(); 953 } 954 }); 955 956 setEnabled(Arrays.asList(windowMenu.getItems()), false); 957 958 log.info("Menubar created"); 959 } 960 961 private void createToolbar(final Shell shell) { 962 toolBar = new ToolBar(shell, SWT.HORIZONTAL | SWT.RIGHT); 963 toolBar.setFont(Display.getCurrent().getSystemFont()); 964 toolBar.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 3, 1)); 965 966 ToolItem openItem = new ToolItem(toolBar, SWT.PUSH); 967 openItem.setToolTipText("Open"); 968 openItem.setImage(ViewProperties.getFileopenIcon()); 969 openItem.addSelectionListener(new SelectionAdapter() { 970 @Override 971 public void widgetSelected(SelectionEvent e) { 972 openLocalFile(null, -1); 973 } 974 }); 975 976 new ToolItem(toolBar, SWT.SEPARATOR).setWidth(4); 977 978 ToolItem closeItem = new ToolItem(toolBar, SWT.PUSH); 979 closeItem.setImage(ViewProperties.getFilecloseIcon()); 980 closeItem.setToolTipText("Close"); 981 closeItem.addSelectionListener(new SelectionAdapter() { 982 @Override 983 public void widgetSelected(SelectionEvent e) { 984 closeFile(treeView.getSelectedFile()); 985 } 986 }); 987 988 new ToolItem(toolBar, SWT.SEPARATOR).setWidth(20); 989 990 ToolItem helpItem = new ToolItem(toolBar, SWT.PUSH); 991 helpItem.setImage(ViewProperties.getHelpIcon()); 992 helpItem.setToolTipText("Help"); 993 helpItem.addSelectionListener(new SelectionAdapter() { 994 @Override 995 public void widgetSelected(SelectionEvent e) { 996 String ugPath = ViewProperties.getUsersGuide(); 997 998 if(ugPath == null || !ugPath.startsWith("http://")) { 999 String sep = File.separator; 1000 File tmpFile = new File(ugPath); 1001 1002 if(!(tmpFile.exists())) { 1003 ugPath = rootDir + sep + "UsersGuide" + sep + "index.html"; 1004 tmpFile = new File(ugPath); 1005 1006 if(!(tmpFile.exists())) { 1007 ugPath = HDFVIEW_USERSGUIDE_URL; 1008 } 1009 1010 ViewProperties.setUsersGuide(ugPath); 1011 } 1012 } 1013 1014 try { 1015 org.eclipse.swt.program.Program.launch(ugPath); 1016 } 1017 catch (Exception ex) { 1018 Tools.showError(shell, "Help", ex.getMessage()); 1019 } 1020 } 1021 }); 1022 1023 new ToolItem(toolBar, SWT.SEPARATOR).setWidth(4); 1024 1025 ToolItem hdf4Item = new ToolItem(toolBar, SWT.PUSH); 1026 hdf4Item.setImage(ViewProperties.getH4Icon()); 1027 hdf4Item.setToolTipText("HDF4 Library Version"); 1028 hdf4Item.addSelectionListener(new SelectionAdapter() { 1029 @Override 1030 public void widgetSelected(SelectionEvent e) { 1031 new LibraryVersionDialog(shell, FileFormat.FILE_TYPE_HDF4).open(); 1032 } 1033 }); 1034 1035 if(FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF4) == null) { 1036 hdf4Item.setEnabled(false); 1037 } 1038 1039 new ToolItem(toolBar, SWT.SEPARATOR).setWidth(4); 1040 1041 ToolItem hdf5Item = new ToolItem(toolBar, SWT.PUSH); 1042 hdf5Item.setImage(ViewProperties.getH5Icon()); 1043 hdf5Item.setToolTipText("HDF5 Library Version"); 1044 hdf5Item.addSelectionListener(new SelectionAdapter() { 1045 @Override 1046 public void widgetSelected(SelectionEvent e) { 1047 new LibraryVersionDialog(shell, FileFormat.FILE_TYPE_HDF5).open(); 1048 } 1049 }); 1050 1051 if(FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF5) == null) { 1052 hdf5Item.setEnabled(false); 1053 } 1054 1055 // Make the toolbar as wide as the window and as 1056 // tall as the buttons 1057 toolBar.setSize(shell.getClientArea().width, openItem.getBounds().height); 1058 toolBar.setLocation(0, 0); 1059 1060 log.info("Toolbar created"); 1061 } 1062 1063 private void createUrlToolbar(final Shell shell) { 1064 // Recent Files button 1065 recentFilesButton = new Button(shell, SWT.PUSH); 1066 recentFilesButton.setFont(currentFont); 1067 recentFilesButton.setText("Recent Files"); 1068 recentFilesButton.setToolTipText("List of recent files"); 1069 recentFilesButton.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false)); 1070 recentFilesButton.addSelectionListener(new SelectionAdapter() { 1071 @Override 1072 public void widgetSelected(SelectionEvent e) { 1073 urlBar.setListVisible(true); 1074 } 1075 }); 1076 1077 // Recent files combo box 1078 urlBar = new Combo(shell, SWT.BORDER | SWT.SINGLE); 1079 urlBar.setFont(currentFont); 1080 urlBar.setItems(ViewProperties.getMRF().toArray(new String[0])); 1081 urlBar.setVisibleItemCount(ViewProperties.MAX_RECENT_FILES); 1082 urlBar.deselectAll(); 1083 urlBar.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); 1084 urlBar.addKeyListener(new KeyAdapter() { 1085 @Override 1086 public void keyPressed(KeyEvent e) { 1087 if(e.keyCode == SWT.CR) { 1088 String filename = urlBar.getText(); 1089 if (filename == null || filename.length() < 1 || filename.equals(currentFile)) { 1090 return; 1091 } 1092 1093 if (!(filename.startsWith("http://") || filename.startsWith("https://") || filename.startsWith("ftp://"))) { 1094 openLocalFile(filename, -1); 1095 } 1096 else { 1097 String remoteFile = openRemoteFile(filename); 1098 1099 if (remoteFile != null) openLocalFile(remoteFile, -1); 1100 } 1101 } 1102 } 1103 }); 1104 urlBar.addSelectionListener(new SelectionAdapter() { 1105 @Override 1106 public void widgetSelected(SelectionEvent e) { 1107 String filename = urlBar.getText(); 1108 if (filename == null || filename.length() < 1 || filename.equals(currentFile)) { 1109 return; 1110 } 1111 1112 if (!(filename.startsWith("http://") || filename.startsWith("https://") || filename.startsWith("ftp://"))) { 1113 openLocalFile(filename, -1); 1114 } 1115 else { 1116 String remoteFile = openRemoteFile(filename); 1117 1118 if (remoteFile != null) openLocalFile(remoteFile, -1); 1119 } 1120 } 1121 }); 1122 1123 clearTextButton = new Button(shell, SWT.PUSH); 1124 clearTextButton.setToolTipText("Clear current selection"); 1125 clearTextButton.setFont(currentFont); 1126 clearTextButton.setText("Clear Text"); 1127 clearTextButton.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false)); 1128 clearTextButton.addSelectionListener(new SelectionAdapter() { 1129 @Override 1130 public void widgetSelected(SelectionEvent e) { 1131 urlBar.setText(""); 1132 urlBar.deselectAll(); 1133 } 1134 }); 1135 1136 log.info("URL Toolbar created"); 1137 } 1138 1139 private void createContentArea(final Shell shell) { 1140 SashForm content = new SashForm(shell, SWT.VERTICAL); 1141 content.setSashWidth(10); 1142 content.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 3, 1)); 1143 1144 // Add Data content area and Status Area to main window 1145 Composite container = new Composite(content, SWT.NONE); 1146 container.setLayout(new FillLayout()); 1147 1148 Composite statusArea = new Composite(content, SWT.NONE); 1149 statusArea.setLayout(new FillLayout(SWT.HORIZONTAL)); 1150 1151 final SashForm contentArea = new SashForm(container, SWT.HORIZONTAL); 1152 contentArea.setSashWidth(10); 1153 1154 // Add TreeView and DataView to content area pane 1155 ScrolledComposite treeArea = new ScrolledComposite(contentArea, SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER); 1156 treeArea.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_WHITE)); 1157 treeArea.setExpandHorizontal(true); 1158 treeArea.setExpandVertical(true); 1159 1160 generalArea = new ScrolledComposite(contentArea, SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER); 1161 generalArea.setExpandHorizontal(true); 1162 generalArea.setExpandVertical(true); 1163 generalArea.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_WIDGET_LIGHT_SHADOW)); 1164 generalArea.setMinHeight(contentArea.getSize().y - 2); 1165 1166 // Create status area for displaying messages and metadata 1167 status = new Text(statusArea, SWT.V_SCROLL | SWT.MULTI | SWT.BORDER); 1168 status.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_WIDGET_LIGHT_SHADOW)); 1169 status.setEditable(false); 1170 status.setFont(currentFont); 1171 1172 contentArea.addListener(SWT.Resize, new Listener() { 1173 @Override 1174 public void handleEvent(Event arg0) { 1175 generalArea.setMinHeight(contentArea.getSize().y - 2); 1176 } 1177 }); 1178 1179 // Add drag and drop support for opening files 1180 DropTarget target = new DropTarget(treeArea, DND.DROP_COPY); 1181 final FileTransfer fileTransfer = FileTransfer.getInstance(); 1182 target.setTransfer(new Transfer[] { fileTransfer }); 1183 target.addDropListener(new DropTargetListener() { 1184 @Override 1185 public void dragEnter(DropTargetEvent e) { 1186 e.detail = DND.DROP_COPY; 1187 } 1188 @Override 1189 public void dragOver(DropTargetEvent e) { 1190 // Intentional 1191 } 1192 @Override 1193 public void dragOperationChanged(DropTargetEvent e) { 1194 // Intentional 1195 } 1196 @Override 1197 public void dragLeave(DropTargetEvent e) { 1198 // Intentional 1199 } 1200 @Override 1201 public void dropAccept(DropTargetEvent e) { 1202 // Intentional 1203 } 1204 @Override 1205 public void drop(DropTargetEvent e) { 1206 if (fileTransfer.isSupportedType(e.currentDataType)) { 1207 String[] files = (String[]) e.data; 1208 for (int i = 0; i < files.length; i++) { 1209 openLocalFile(files[i], -1); 1210 } 1211 } 1212 } 1213 }); 1214 1215 showStatus("HDFView root - " + rootDir); 1216 showStatus("User property file - " + ViewProperties.getPropertyFile()); 1217 1218 content.setWeights(new int[] { 9, 1 }); 1219 contentArea.setWeights(new int[] { 1, 3 }); 1220 1221 log.trace("createContentArea(): load TreeView"); 1222 1223 DataViewFactory treeViewFactory = null; 1224 try { 1225 treeViewFactory = DataViewFactoryProducer.getFactory(DataViewType.TREEVIEW); 1226 } 1227 catch (Exception ex) { 1228 log.debug("createContentArea(): error occurred while instantiating TreeView factory class", ex); 1229 this.showError("Error occurred while instantiating TreeView factory class"); 1230 return; 1231 } 1232 1233 if (treeViewFactory == null) { 1234 log.debug("createContentArea(): TreeView factory is null"); 1235 return; 1236 } 1237 1238 try { 1239 treeView = treeViewFactory.getTreeView(treeArea, this); 1240 1241 if (treeView == null) { 1242 log.debug("createContentArea(): error occurred while instantiating TreeView class"); 1243 this.showError("Error occurred while instantiating TreeView class"); 1244 return; 1245 } 1246 } 1247 catch (ClassNotFoundException ex) { 1248 log.debug("createContentArea(): no suitable TreeView class found"); 1249 this.showError("Unable to find suitable TreeView class"); 1250 return; 1251 } 1252 1253 treeArea.setContent(treeView.getTree()); 1254 1255 log.info("Content Area created"); 1256 } 1257 1258 /** 1259 * @return a list of treeview implementations. 1260 */ 1261 public static final List<String> getListOfTreeViews() { 1262 return treeViews; 1263 } 1264 1265 /** 1266 * @return a list of imageview implementations. 1267 */ 1268 public static final List<String> getListOfImageViews() { 1269 return imageViews; 1270 } 1271 1272 /** 1273 * @return a list of tableview implementations. 1274 */ 1275 public static final List<?> getListOfTableViews() { 1276 return tableViews; 1277 } 1278 1279 /** 1280 * @return a list of metaDataview implementations. 1281 */ 1282 public static final List<?> getListOfMetaDataViews() { 1283 return metaDataViews; 1284 } 1285 1286 /** 1287 * @return a list of paletteview implementations. 1288 */ 1289 public static final List<?> getListOfPaletteViews() { 1290 return paletteViews; 1291 } 1292 1293 @Override 1294 public TreeView getTreeView() { 1295 return treeView; 1296 } 1297 1298 public Combo getUrlBar() { 1299 return urlBar; 1300 } 1301 1302 /** 1303 * Display feedback message. 1304 * 1305 * @param msg 1306 * the message to display. 1307 */ 1308 @Override 1309 public void showStatus(String msg) { 1310 if (status == null) { 1311 log.debug("showStatus(): status area is null"); 1312 return; 1313 } 1314 1315 status.append(msg); 1316 status.append("\n"); 1317 } 1318 1319 /** 1320 * Display error message 1321 * 1322 * @param errMsg 1323 * the error message to display 1324 */ 1325 @Override 1326 public void showError(String errMsg) { 1327 if (status == null) { 1328 log.debug("showError(): status area is null"); 1329 return; 1330 } 1331 1332 status.append(" *** "); 1333 status.append(errMsg); 1334 if (log.isDebugEnabled()) 1335 status.append(" - see log for more info"); 1336 status.append(" *** "); 1337 status.append("\n"); 1338 } 1339 1340 public void showMetaData(final HObject obj) { 1341 for (Control control : generalArea.getChildren()) control.dispose(); 1342 generalArea.setContent(null); 1343 1344 if (obj == null) return; 1345 1346 log.trace("showMetaData(): start"); 1347 1348 DataViewFactory metaDataViewFactory = null; 1349 try { 1350 metaDataViewFactory = DataViewFactoryProducer.getFactory(DataViewType.METADATA); 1351 } 1352 catch (Exception ex) { 1353 log.debug("showMetaData(): error occurred while instantiating MetaDataView factory class", ex); 1354 this.showError("Error occurred while instantiating MetaDataView factory class"); 1355 return; 1356 } 1357 1358 if (metaDataViewFactory == null) { 1359 log.debug("showMetaData(): MetaDataView factory is null"); 1360 return; 1361 } 1362 1363 MetaDataView theView; 1364 try { 1365 theView = metaDataViewFactory.getMetaDataView(generalArea, this, obj); 1366 1367 if (theView == null) { 1368 log.debug("showMetaData(): error occurred while instantiating MetaDataView class"); 1369 this.showError("Error occurred while instantiating MetaDataView class"); 1370 return; 1371 } 1372 } 1373 catch (ClassNotFoundException ex) { 1374 log.debug("showMetaData(): no suitable MetaDataView class found"); 1375 this.showError("Unable to find suitable MetaDataView class"); 1376 return; 1377 } 1378 1379 log.trace("showMetaData(): finish"); 1380 } 1381 1382 public void closeFile(FileFormat theFile) { 1383 if (theFile == null) { 1384 display.beep(); 1385 Tools.showError(mainWindow, "Close", "Select a file to close"); 1386 return; 1387 } 1388 1389 // Close all the data windows of this file 1390 Shell[] views = display.getShells(); 1391 if (views != null) { 1392 for (int i = 0; i < views.length; i++) { 1393 Object shellData = views[i].getData(); 1394 1395 if (!(shellData instanceof DataView)) continue; 1396 1397 if ((DataView) shellData != null) { 1398 HObject obj = ((DataView) shellData).getDataObject(); 1399 1400 if (obj == null || obj.getFileFormat() == null) continue; 1401 1402 if (obj.getFileFormat().equals(theFile)) { 1403 views[i].dispose(); 1404 views[i] = null; 1405 } 1406 } 1407 } 1408 } 1409 1410 int index = urlBar.getSelectionIndex(); 1411 if (index >= 0) { 1412 String fName = urlBar.getItem(urlBar.getSelectionIndex()); 1413 if (theFile.getFilePath().equals(fName)) { 1414 currentFile = null; 1415 urlBar.setText(""); 1416 } 1417 } 1418 1419 try { 1420 treeView.closeFile(theFile); 1421 } 1422 catch (Exception ex) { 1423 // Intentional 1424 } 1425 1426 for (Control control : generalArea.getChildren()) control.dispose(); 1427 generalArea.setContent(null); 1428 1429 System.gc(); 1430 } 1431 1432 /** 1433 * Write the change of data to the given file. 1434 * 1435 * @param theFile 1436 * The file to be updated. 1437 */ 1438 public void writeDataToFile(FileFormat theFile) { 1439 try { 1440 Shell[] openShells = display.getShells(); 1441 1442 if (openShells != null) { 1443 for (int i = 0; i < openShells.length; i++) { 1444 DataView theView = (DataView) openShells[i].getData(); 1445 1446 if (theView instanceof TableView) { 1447 TableView tableView = (TableView) theView; 1448 FileFormat file = tableView.getDataObject().getFileFormat(); 1449 if (file.equals(theFile)) tableView.updateValueInFile(); 1450 } 1451 } 1452 } 1453 } 1454 catch (Exception ex) { 1455 display.beep(); 1456 Tools.showError(mainWindow, "Save", ex.getMessage()); 1457 } 1458 } 1459 1460 @Override 1461 public void addDataView(DataView dataView) { 1462 if (dataView == null || dataView instanceof MetaDataView) { 1463 return; 1464 } 1465 1466 // Check if the data content is already displayed 1467 Shell[] shellList = display.getShells(); 1468 if (shellList != null) { 1469 for (int i = 0; i < shellList.length; i++) { 1470 if (dataView.equals(shellList[i].getData()) 1471 && shellList[i].isVisible()) { 1472 showWindow(shellList[i]); 1473 return; 1474 } 1475 } 1476 } 1477 1478 // First window being added 1479 if (shellList != null && shellList.length == 2) { 1480 setEnabled(Arrays.asList(windowMenu.getItems()), true); 1481 } 1482 1483 HObject obj = dataView.getDataObject(); 1484 String fullPath = ((obj.getPath() == null) ? "" : obj.getPath()) 1485 + ((obj.getName() == null) ? "" : obj.getName()); 1486 1487 MenuItem item = new MenuItem(windowMenu, SWT.PUSH); 1488 item.setText(fullPath); 1489 item.addSelectionListener(new SelectionAdapter() { 1490 @Override 1491 public void widgetSelected(SelectionEvent e) { 1492 Shell[] sList = display.getShells(); 1493 1494 for (int i = 0; i < sList.length; i++) { 1495 DataView view = (DataView) sList[i].getData(); 1496 1497 if (view != null) { 1498 HObject obj = view.getDataObject(); 1499 1500 if (obj.getFullName().equals(((MenuItem) e.widget).getText())) { 1501 showWindow(sList[i]); 1502 } 1503 } 1504 } 1505 } 1506 }); 1507 1508 mainWindow.setCursor(null); 1509 } 1510 1511 @Override 1512 public void removeDataView(DataView dataView) { 1513 if (mainWindow.isDisposed()) return; 1514 1515 HObject obj = dataView.getDataObject(); 1516 if (obj == null) return; 1517 1518 MenuItem[] items = windowMenu.getItems(); 1519 for (int i = 0; i < items.length; i++) { 1520 if(items[i].getText().equals(obj.getFullName())) { 1521 items[i].dispose(); 1522 } 1523 } 1524 1525 // Last window being closed 1526 if (display.getShells().length == 2) { 1527 for (MenuItem item : windowMenu.getItems()) item.setEnabled(false); 1528 } 1529 } 1530 1531 @Override 1532 public DataView getDataView(HObject dataObject) { 1533 Shell[] openShells = display.getShells(); 1534 DataView view = null; 1535 HObject currentObj = null; 1536 FileFormat currentDataViewFile = null; 1537 1538 for (int i = 0; i < openShells.length; i++) { 1539 view = (DataView) openShells[i].getData(); 1540 1541 if (view != null) { 1542 currentObj = view.getDataObject(); 1543 if (currentObj == null) continue; 1544 1545 currentDataViewFile = currentObj.getFileFormat(); 1546 1547 if (currentObj.equals(dataObject) && currentDataViewFile.equals(dataObject.getFileFormat())) 1548 return view; 1549 } 1550 } 1551 1552 return null; 1553 } 1554 1555 /** 1556 * Set the testing state that determines if HDFView 1557 * is being executed for GUI testing. 1558 * 1559 * @param testing 1560 * Provides SWTBot native dialog compatibility 1561 * workarounds if set to true. 1562 */ 1563 public void setTestState(boolean testing) { 1564 isTesting = testing; 1565 currentDir = rootDir; 1566 } 1567 1568 public boolean getTestState() { 1569 return isTesting; 1570 } 1571 1572 /** 1573 * Set default UI fonts. 1574 */ 1575 private void updateFont(Font font) { 1576 if (currentFont != null) currentFont.dispose(); 1577 1578 currentFont = font; 1579 1580 mainWindow.setFont(font); 1581 recentFilesButton.setFont(font); 1582 urlBar.setFont(font); 1583 clearTextButton.setFont(font); 1584 status.setFont(font); 1585 1586 // On certain platforms the url_bar items don't update their size after 1587 // a font change. Removing and replacing them fixes this. 1588 for (String item : urlBar.getItems()) { 1589 urlBar.remove(item); 1590 urlBar.add(item); 1591 } 1592 1593 if (treeView.getSelectedFile() != null) { 1594 urlBar.select(0); 1595 } 1596 1597 if (treeView instanceof DefaultTreeView) 1598 ((DefaultTreeView) treeView).updateFont(font); 1599 1600 mainWindow.layout(); 1601 } 1602 1603 /** 1604 * Bring window to the front. 1605 * <p> 1606 * 1607 * @param name 1608 * the name of the window to show. 1609 */ 1610 private void showWindow(final Shell shell) { 1611 shell.getDisplay().asyncExec(new Runnable() { 1612 @Override 1613 public void run() { 1614 shell.forceActive(); 1615 } 1616 }); 1617 } 1618 1619 /** 1620 * Cascade all windows. 1621 */ 1622 private void cascadeWindows() { 1623 Shell[] sList = display.getShells(); 1624 1625 // Return if main window (shell) is the only open shell 1626 if (sList.length <= 1) return; 1627 1628 Shell shell = null; 1629 1630 Rectangle bounds = Display.getCurrent().getPrimaryMonitor().getClientArea(); 1631 int w = Math.max(50, bounds.width - 100); 1632 int h = Math.max(50, bounds.height - 100); 1633 1634 int x = bounds.x; 1635 int y = bounds.y; 1636 1637 for (int i = 0; i < sList.length; i++) { 1638 shell = sList[i]; 1639 shell.setBounds(x, y, w, h); 1640 shell.setActive(); 1641 x += 20; 1642 y += 20; 1643 } 1644 } 1645 1646 /** 1647 * Tile all windows. 1648 */ 1649 private void tileWindows() { 1650 Shell[] sList = display.getShells(); 1651 1652 // Return if main window (shell) is the only open shell 1653 if (sList.length <= 1) return; 1654 1655 int x = 0; 1656 int y = 0; 1657 int idx = 0; 1658 Shell shell = null; 1659 1660 int n = sList.length; 1661 int cols = (int) Math.sqrt(n); 1662 int rows = (int) Math.ceil((double) n / (double) cols); 1663 1664 Rectangle bounds = Display.getCurrent().getPrimaryMonitor().getClientArea(); 1665 int w = bounds.width / cols; 1666 int h = bounds.height / rows; 1667 1668 y = bounds.y; 1669 for (int i = 0; i < rows; i++) { 1670 x = bounds.x; 1671 1672 for (int j = 0; j < cols; j++) { 1673 idx = i * cols + j; 1674 if (idx >= n) 1675 return; 1676 1677 shell = sList[idx]; 1678 shell.setBounds(x, y, w, h); 1679 shell.setActive(); 1680 x += w; 1681 } 1682 1683 y += h; 1684 } 1685 } 1686 1687 /** 1688 * Closes all windows. 1689 */ 1690 private void closeAllWindows() { 1691 Shell[] sList = display.getShells(); 1692 1693 for (int i = 0; i < sList.length; i++) { 1694 if (sList[i].equals(mainWindow)) continue; 1695 sList[i].dispose(); 1696 } 1697 } 1698 1699 /* Enable and disable GUI components */ 1700 private static void setEnabled(List<MenuItem> list, boolean b) { 1701 Iterator<MenuItem> it = list.iterator(); 1702 1703 while (it.hasNext()) 1704 it.next().setEnabled(b); 1705 } 1706 1707 /** Open local file */ 1708 private void openLocalFile(String filename, int fileAccessID) { 1709 log.trace("openLocalFile {},{}",filename, fileAccessID); 1710 1711 /* 1712 * If given a specific access mode, use it without changing it. If not given a 1713 * specific access mode, check the current status of the "is read only" property 1714 * to determine how to open the file. This is to allow one time overrides of the 1715 * default file access mode when opening a file. 1716 */ 1717 int accessMode = fileAccessID; 1718 if (accessMode < 0) { 1719 if (ViewProperties.isReadOnly()) 1720 accessMode = FileFormat.READ; 1721 else 1722 accessMode = FileFormat.WRITE; 1723 } 1724 1725 String[] selectedFilenames = null; 1726 File[] chosenFiles = null; 1727 1728 if (filename != null) { 1729 File file = new File(filename); 1730 if(!file.exists()) { 1731 Tools.showError(mainWindow, "Open", "File " + filename + " does not exist."); 1732 return; 1733 } 1734 1735 if(file.isDirectory()) { 1736 currentDir = filename; 1737 openLocalFile(null, -1); 1738 } 1739 else { 1740 currentFile = filename; 1741 1742 try { 1743 treeView.openFile(filename, accessMode); 1744 } 1745 catch (Exception ex) { 1746 try { 1747 treeView.openFile(filename, FileFormat.READ); 1748 } 1749 catch (Exception ex2) { 1750 display.beep(); 1751 urlBar.deselectAll(); 1752 Tools.showError(mainWindow, "Open", "Failed to open file " + filename + "\n" + ex2); 1753 currentFile = null; 1754 } 1755 } 1756 } 1757 1758 try { 1759 urlBar.remove(filename); 1760 } 1761 catch (Exception ex) { 1762 log.trace("unable to remove {} from urlBar", filename); 1763 } 1764 1765 urlBar.add(filename, 0); 1766 urlBar.select(0); 1767 } 1768 else { 1769 if (!isTesting) { 1770 log.trace("openLocalFile filename is null"); 1771 FileDialog fChooser = new FileDialog(mainWindow, SWT.OPEN | SWT.MULTI); 1772 fChooser.setText(mainWindow.getText() + " - Open File " + ((accessMode == FileFormat.READ) ? "Read-only" : "Read/Write")); 1773 fChooser.setFilterPath(currentDir); 1774 1775 DefaultFileFilter filter = DefaultFileFilter.getFileFilter(); 1776 fChooser.setFilterExtensions(new String[] {"*.*", filter.getExtensions()}); 1777 fChooser.setFilterNames(new String[] {"All Files", filter.getDescription()}); 1778 fChooser.setFilterIndex(1); 1779 1780 fChooser.open(); 1781 1782 selectedFilenames = fChooser.getFileNames(); 1783 if(selectedFilenames.length <= 0) return; 1784 1785 chosenFiles = new File[selectedFilenames.length]; 1786 for(int i = 0; i < chosenFiles.length; i++) { 1787 log.trace("openLocalFile selectedFilenames[{}]: {}",i,selectedFilenames[i]); 1788 chosenFiles[i] = new File(fChooser.getFilterPath() + File.separator + selectedFilenames[i]); 1789 1790 if(!chosenFiles[i].exists()) { 1791 Tools.showError(mainWindow, "Open", "File " + chosenFiles[i].getName() + " does not exist."); 1792 continue; 1793 } 1794 1795 if (chosenFiles[i].isDirectory()) { 1796 currentDir = chosenFiles[i].getPath(); 1797 } 1798 else { 1799 currentDir = chosenFiles[i].getParent(); 1800 } 1801 1802 try { 1803 urlBar.remove(chosenFiles[i].getAbsolutePath()); 1804 } 1805 catch (Exception ex) { 1806 log.trace("unable to remove {} from urlBar", chosenFiles[i].getAbsolutePath()); 1807 } 1808 1809 urlBar.add(chosenFiles[i].getAbsolutePath(), 0); 1810 urlBar.select(0); 1811 1812 log.trace("openLocalFile treeView.openFile(chosenFiles[{}]: {}",i,chosenFiles[i].getAbsolutePath()); 1813 try { 1814 treeView.openFile(chosenFiles[i].getAbsolutePath(), accessMode + FileFormat.OPEN_NEW); 1815 } 1816 catch (Exception ex) { 1817 try { 1818 treeView.openFile(chosenFiles[i].getAbsolutePath(), FileFormat.READ); 1819 } 1820 catch (Exception ex2) { 1821 display.beep(); 1822 urlBar.deselectAll(); 1823 Tools.showError(mainWindow, "Open", "Failed to open file " + selectedFilenames[i] + "\n" + ex2); 1824 currentFile = null; 1825 } 1826 } 1827 } 1828 1829 currentFile = chosenFiles[0].getAbsolutePath(); 1830 } 1831 else { 1832 // Prepend test file directory to filename 1833 String fName = currentDir + File.separator + new InputDialog(mainWindow, "Enter a file name", "").open(); 1834 1835 File chosenFile = new File(fName); 1836 1837 if(!chosenFile.exists()) { 1838 Tools.showError(mainWindow, "Open", "File " + chosenFile.getName() + " does not exist."); 1839 return; 1840 } 1841 1842 if (chosenFile.isDirectory()) { 1843 currentDir = chosenFile.getPath(); 1844 } 1845 else { 1846 currentDir = chosenFile.getParent(); 1847 } 1848 1849 try { 1850 urlBar.remove(chosenFile.getAbsolutePath()); 1851 } 1852 catch (Exception ex) { 1853 log.trace("unable to remove {} from urlBar", chosenFile.getAbsolutePath()); 1854 } 1855 1856 urlBar.add(chosenFile.getAbsolutePath(), 0); 1857 urlBar.select(0); 1858 1859 log.trace("openLocalFile treeView.openFile(chosenFile[{}]: {}", chosenFile.getAbsolutePath(), accessMode + FileFormat.OPEN_NEW); 1860 try { 1861 treeView.openFile(chosenFile.getAbsolutePath(), accessMode + FileFormat.OPEN_NEW); 1862 } 1863 catch (Exception ex) { 1864 try { 1865 treeView.openFile(chosenFile.getAbsolutePath(), FileFormat.READ); 1866 } 1867 catch (Exception ex2) { 1868 display.beep(); 1869 urlBar.deselectAll(); 1870 Tools.showError(mainWindow, "Open", "Failed to open file " + chosenFile + "\n" + ex2); 1871 currentFile = null; 1872 } 1873 } 1874 1875 currentFile = chosenFile.getAbsolutePath(); 1876 } 1877 } 1878 } 1879 1880 /** Load remote file and save it to local temporary directory */ 1881 private String openRemoteFile(String urlStr) { 1882 if (urlStr == null) 1883 return null; 1884 1885 String localFile = null; 1886 1887 if(urlStr.startsWith("http://")) { 1888 localFile = urlStr.substring(7); 1889 } 1890 else if (urlStr.startsWith("https://")) { 1891 localFile = urlStr.substring(8); 1892 } 1893 else if (urlStr.startsWith("ftp://")) { 1894 localFile = urlStr.substring(6); 1895 } 1896 else { 1897 return null; 1898 } 1899 1900 localFile = localFile.replace('/', '@'); 1901 localFile = localFile.replace('\\', '@'); 1902 1903 // Search the local file cache 1904 String tmpDir = System.getProperty("java.io.tmpdir"); 1905 1906 File tmpFile = new File(tmpDir); 1907 if (!tmpFile.canWrite()) 1908 tmpDir = System.getProperty("user.home"); 1909 1910 localFile = tmpDir + File.separator + localFile; 1911 1912 tmpFile = new File(localFile); 1913 if (tmpFile.exists()) 1914 return localFile; 1915 1916 URL url = null; 1917 1918 try { 1919 url = new URL(urlStr); 1920 } 1921 catch (Exception ex) { 1922 url = null; 1923 display.beep(); 1924 Tools.showError(mainWindow, "Open", ex.getMessage()); 1925 return null; 1926 } 1927 1928 try (BufferedInputStream in = new BufferedInputStream(url.openStream())) { 1929 try (BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(tmpFile))) { 1930 mainWindow.setCursor(display.getSystemCursor(SWT.CURSOR_WAIT)); 1931 byte[] buff = new byte[512]; // set default buffer size to 512 1932 int n = 0; 1933 while ((n = in.read(buff)) > 0) { 1934 out.write(buff, 0, n); 1935 } 1936 } 1937 catch (Exception ex) { 1938 log.debug("Remote file: ", ex); 1939 throw ex; 1940 } 1941 } 1942 catch (Exception ex) { 1943 display.beep(); 1944 Tools.showError(mainWindow, "Open", ex.getMessage()); 1945 // Want to call setCursor always 1946 localFile = null; 1947 } 1948 1949 mainWindow.setCursor(null); 1950 1951 return localFile; 1952 } 1953 1954 private void convertFile(String typeFrom, String typeTo) { 1955 ImageConversionDialog dialog = new ImageConversionDialog(mainWindow, typeFrom, typeTo, 1956 currentDir, treeView.getCurrentFiles()); 1957 dialog.open(); 1958 1959 if (dialog.isFileConverted()) { 1960 String filename = dialog.getConvertedFile(); 1961 File theFile = new File(filename); 1962 1963 if (!theFile.exists()) return; 1964 1965 currentDir = theFile.getParentFile().getAbsolutePath(); 1966 currentFile = theFile.getAbsolutePath(); 1967 1968 try { 1969 treeView.openFile(filename, FileFormat.WRITE); 1970 1971 try { 1972 urlBar.remove(filename); 1973 } 1974 catch (Exception ex) { 1975 log.trace("unable to remove {} from urlBar", filename); 1976 } 1977 1978 urlBar.add(filename, 0); 1979 urlBar.select(0); 1980 } 1981 catch (Exception ex) { 1982 showError(ex.toString()); 1983 } 1984 } 1985 } 1986 1987 private void registerFileFormat() { 1988 String msg = "Register a new file format by \nKEY:FILE_FORMAT:FILE_EXTENSION\n" 1989 + "where, KEY: the unique identifier for the file format" 1990 + "\n FILE_FORMAT: the full class name of the file format" 1991 + "\n FILE_EXTENSION: the file extension for the file format" + "\n\nFor example, " 1992 + "\n\t to add NetCDF, \"NetCDF:hdf.object.nc2.NC2File:nc\"" 1993 + "\n\t to add FITS, \"FITS:hdf.object.fits.FitsFile:fits\"\n\n"; 1994 1995 // TODO:Add custom HDFLarge icon to dialog 1996 InputDialog dialog = new InputDialog(mainWindow, "Register a file format", msg, SWT.ICON_INFORMATION); 1997 1998 String str = dialog.open(); 1999 2000 if ((str == null) || (str.length() < 1)) return; 2001 2002 int idx1 = str.indexOf(':'); 2003 int idx2 = str.lastIndexOf(':'); 2004 2005 if ((idx1 < 0) || (idx2 <= idx1)) { 2006 Tools.showError(mainWindow, "Register File Format", "Failed to register " + str 2007 + "\n\nMust in the form of KEY:FILE_FORMAT:FILE_EXTENSION"); 2008 return; 2009 } 2010 2011 String key = str.substring(0, idx1); 2012 String className = str.substring(idx1 + 1, idx2); 2013 String extension = str.substring(idx2 + 1); 2014 2015 // Check if the file format has been registered or the key is taken. 2016 String theKey = null; 2017 String theClassName = null; 2018 Enumeration<?> localEnum = FileFormat.getFileFormatKeys(); 2019 while (localEnum.hasMoreElements()) { 2020 theKey = (String) localEnum.nextElement(); 2021 if (theKey.endsWith(key)) { 2022 Tools.showError(mainWindow, "Register File Format", "Invalid key: " + key + " is taken."); 2023 return; 2024 } 2025 2026 theClassName = FileFormat.getFileFormat(theKey).getClass().getName(); 2027 if (theClassName.endsWith(className)) { 2028 Tools.showError(mainWindow, "Register File Format", "The file format has already been registered: " + className); 2029 return; 2030 } 2031 } 2032 2033 // Enables use of JHDF5 in JNLP (Web Start) applications, the system 2034 // class loader with reflection first. 2035 Class<?> theClass = null; 2036 try { 2037 theClass = Class.forName(className); 2038 } 2039 catch (Exception ex) { 2040 try { 2041 theClass = ViewProperties.loadExtClass().loadClass(className); 2042 } 2043 catch (Exception ex2) { 2044 theClass = null; 2045 } 2046 } 2047 2048 if (theClass == null) { 2049 return; 2050 } 2051 2052 try { 2053 Object theObject = theClass.newInstance(); 2054 if (theObject instanceof FileFormat) { 2055 FileFormat.addFileFormat(key, (FileFormat) theObject); 2056 } 2057 } 2058 catch (Exception ex) { 2059 Tools.showError(mainWindow, "Register File Format", "Failed to register " + str + "\n\n" + ex); 2060 return; 2061 } 2062 2063 if ((extension != null) && (extension.length() > 0)) { 2064 extension = extension.trim(); 2065 String ext = ViewProperties.getFileExtension(); 2066 ext += ", " + extension; 2067 ViewProperties.setFileExtension(ext); 2068 } 2069 } 2070 2071 private void unregisterFileFormat() { 2072 Enumeration<?> keys = FileFormat.getFileFormatKeys(); 2073 ArrayList<Object> keyList = new ArrayList<>(); 2074 2075 while (keys.hasMoreElements()) 2076 keyList.add(keys.nextElement()); 2077 2078 String theKey = new UnregisterFileFormatDialog(mainWindow, SWT.NONE, keyList).open(); 2079 2080 if (theKey == null) return; 2081 2082 FileFormat.removeFileFormat(theKey); 2083 } 2084 2085 private class LibraryVersionDialog extends Dialog { 2086 private String message; 2087 2088 public LibraryVersionDialog(Shell parent, String libType) { 2089 super(parent, SWT.APPLICATION_MODAL | SWT.DIALOG_TRIM); 2090 2091 if (libType.equals(FileFormat.FILE_TYPE_HDF4)) 2092 setMessage("HDF " + HDF4_VERSION); 2093 else if (libType.equals(FileFormat.FILE_TYPE_HDF5)) 2094 setMessage("HDF5 " + HDF5_VERSION); 2095 } 2096 2097 public void setMessage(String message) { 2098 this.message = message; 2099 } 2100 2101 public void open() { 2102 Shell dialog = new Shell(getParent(), getStyle()); 2103 dialog.setFont(currentFont); 2104 dialog.setText("HDF Library Version"); 2105 2106 createContents(dialog); 2107 2108 dialog.pack(); 2109 2110 Point computedSize = dialog.computeSize(SWT.DEFAULT, SWT.DEFAULT); 2111 dialog.setSize(computedSize.x + 50, computedSize.y + 50); 2112 2113 // Center the window relative to the main HDFView window 2114 Point winCenter = new Point( 2115 mainWindow.getBounds().x + (mainWindow.getBounds().width / 2), 2116 mainWindow.getBounds().y + (mainWindow.getBounds().height / 2)); 2117 2118 dialog.setLocation(winCenter.x - (dialog.getSize().x / 2), winCenter.y - (dialog.getSize().y / 2)); 2119 2120 dialog.open(); 2121 2122 Display display = getParent().getDisplay(); 2123 while (!dialog.isDisposed()) { 2124 if (!display.readAndDispatch()) { 2125 display.sleep(); 2126 } 2127 } 2128 } 2129 2130 private void createContents(final Shell shell) { 2131 shell.setLayout(new GridLayout(2, false)); 2132 2133 Image hdfImage = ViewProperties.getLargeHdfIcon(); 2134 2135 Label imageLabel = new Label(shell, SWT.CENTER); 2136 imageLabel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); 2137 imageLabel.setImage(hdfImage); 2138 2139 Label versionLabel = new Label(shell, SWT.CENTER); 2140 versionLabel.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false)); 2141 versionLabel.setFont(currentFont); 2142 versionLabel.setText(message); 2143 2144 // Draw HDF Icon and Version string 2145 Composite buttonComposite = new Composite(shell, SWT.NONE); 2146 buttonComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 2, 1)); 2147 RowLayout buttonLayout = new RowLayout(); 2148 buttonLayout.center = true; 2149 buttonLayout.justify = true; 2150 buttonLayout.type = SWT.HORIZONTAL; 2151 buttonComposite.setLayout(buttonLayout); 2152 2153 Button okButton = new Button(buttonComposite, SWT.PUSH); 2154 okButton.setFont(currentFont); 2155 okButton.setText(" &OK "); 2156 shell.setDefaultButton(okButton); 2157 okButton.addSelectionListener(new SelectionAdapter() { 2158 @Override 2159 public void widgetSelected(SelectionEvent e) { 2160 shell.dispose(); 2161 } 2162 }); 2163 } 2164 } 2165 2166 private class JavaVersionDialog extends Dialog { 2167 public JavaVersionDialog(Shell parent) { 2168 super(parent, SWT.APPLICATION_MODAL | SWT.DIALOG_TRIM); 2169 } 2170 2171 public void open() { 2172 final Shell dialog = new Shell(getParent(), getStyle()); 2173 dialog.setFont(currentFont); 2174 dialog.setText("HDFView Java Version"); 2175 dialog.setLayout(new GridLayout(2, false)); 2176 2177 Image hdfImage = ViewProperties.getLargeHdfIcon(); 2178 2179 Label imageLabel = new Label(dialog, SWT.CENTER); 2180 imageLabel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); 2181 imageLabel.setImage(hdfImage); 2182 2183 Label versionLabel = new Label(dialog, SWT.CENTER); 2184 versionLabel.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false)); 2185 versionLabel.setFont(currentFont); 2186 versionLabel.setText(JAVA_VER_INFO); 2187 2188 Composite buttonComposite = new Composite(dialog, SWT.NONE); 2189 buttonComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 2, 1)); 2190 RowLayout buttonLayout = new RowLayout(); 2191 buttonLayout.center = true; 2192 buttonLayout.justify = true; 2193 buttonLayout.type = SWT.HORIZONTAL; 2194 buttonComposite.setLayout(buttonLayout); 2195 2196 Button okButton = new Button(buttonComposite, SWT.PUSH); 2197 okButton.setFont(currentFont); 2198 okButton.setText(" &OK "); 2199 dialog.setDefaultButton(okButton); 2200 okButton.addSelectionListener(new SelectionAdapter() { 2201 @Override 2202 public void widgetSelected(SelectionEvent e) { 2203 dialog.dispose(); 2204 } 2205 }); 2206 2207 dialog.pack(); 2208 2209 Point computedSize = dialog.computeSize(SWT.DEFAULT, SWT.DEFAULT); 2210 dialog.setSize(computedSize.x + 50, computedSize.y + 50); 2211 2212 // Center the window relative to the main HDFView window 2213 Point winCenter = new Point( 2214 mainWindow.getBounds().x + (mainWindow.getBounds().width / 2), 2215 mainWindow.getBounds().y + (mainWindow.getBounds().height / 2)); 2216 2217 dialog.setLocation(winCenter.x - (dialog.getSize().x / 2), winCenter.y - (dialog.getSize().y / 2)); 2218 2219 dialog.open(); 2220 2221 Display openDisplay = getParent().getDisplay(); 2222 while (!dialog.isDisposed()) { 2223 if (!openDisplay.readAndDispatch()) { 2224 openDisplay.sleep(); 2225 } 2226 } 2227 } 2228 } 2229 2230 private class SupportedFileFormatsDialog extends Dialog { 2231 public SupportedFileFormatsDialog(Shell parent) { 2232 super(parent, SWT.APPLICATION_MODAL | SWT.DIALOG_TRIM); 2233 } 2234 2235 public void open() { 2236 final Shell dialog = new Shell(getParent(), getStyle()); 2237 dialog.setFont(currentFont); 2238 dialog.setText("Supported File Formats"); 2239 dialog.setLayout(new GridLayout(2, false)); 2240 2241 Image hdfImage = ViewProperties.getLargeHdfIcon(); 2242 2243 Label imageLabel = new Label(dialog, SWT.CENTER); 2244 imageLabel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); 2245 imageLabel.setImage(hdfImage); 2246 2247 Enumeration<?> formatKeys = FileFormat.getFileFormatKeys(); 2248 2249 StringBuilder formats = new StringBuilder("\nSupported File Formats: \n"); 2250 while (formatKeys.hasMoreElements()) { 2251 formats.append(" ").append(formatKeys.nextElement()).append("\n"); 2252 } 2253 formats.append("\n"); 2254 2255 Label formatsLabel = new Label(dialog, SWT.LEFT); 2256 formatsLabel.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false)); 2257 formatsLabel.setFont(currentFont); 2258 formatsLabel.setText(formats.toString()); 2259 2260 Composite buttonComposite = new Composite(dialog, SWT.NONE); 2261 buttonComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 2, 1)); 2262 RowLayout buttonLayout = new RowLayout(); 2263 buttonLayout.center = true; 2264 buttonLayout.justify = true; 2265 buttonLayout.type = SWT.HORIZONTAL; 2266 buttonComposite.setLayout(buttonLayout); 2267 2268 Button okButton = new Button(buttonComposite, SWT.PUSH); 2269 okButton.setFont(currentFont); 2270 okButton.setText(" &OK "); 2271 dialog.setDefaultButton(okButton); 2272 okButton.addSelectionListener(new SelectionAdapter() { 2273 @Override 2274 public void widgetSelected(SelectionEvent e) { 2275 dialog.dispose(); 2276 } 2277 }); 2278 2279 dialog.pack(); 2280 2281 Point computedSize = dialog.computeSize(SWT.DEFAULT, SWT.DEFAULT); 2282 dialog.setSize(computedSize.x + 50, computedSize.y + 50); 2283 2284 // Center the window relative to the main HDFView window 2285 Point winCenter = new Point( 2286 mainWindow.getBounds().x + (mainWindow.getBounds().width / 2), 2287 mainWindow.getBounds().y + (mainWindow.getBounds().height / 2)); 2288 2289 dialog.setLocation(winCenter.x - (dialog.getSize().x / 2), winCenter.y - (dialog.getSize().y / 2)); 2290 2291 dialog.open(); 2292 2293 Display openDisplay = getParent().getDisplay(); 2294 while (!dialog.isDisposed()) { 2295 if (!openDisplay.readAndDispatch()) { 2296 openDisplay.sleep(); 2297 } 2298 } 2299 } 2300 } 2301 2302 private class AboutDialog extends Dialog { 2303 public AboutDialog(Shell parent) { 2304 super(parent, SWT.APPLICATION_MODAL | SWT.DIALOG_TRIM); 2305 } 2306 2307 public void open() { 2308 final Shell dialog = new Shell(getParent(), getStyle()); 2309 dialog.setFont(currentFont); 2310 dialog.setText("About HDFView"); 2311 dialog.setLayout(new GridLayout(2, false)); 2312 2313 Image hdfImage = ViewProperties.getLargeHdfIcon(); 2314 2315 Label imageLabel = new Label(dialog, SWT.CENTER); 2316 imageLabel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); 2317 imageLabel.setImage(hdfImage); 2318 2319 Label aboutLabel = new Label(dialog, SWT.LEFT); 2320 aboutLabel.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false)); 2321 aboutLabel.setFont(currentFont); 2322 aboutLabel.setText(ABOUT_HDFVIEW); 2323 2324 Composite buttonComposite = new Composite(dialog, SWT.NONE); 2325 buttonComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 2, 1)); 2326 RowLayout buttonLayout = new RowLayout(); 2327 buttonLayout.center = true; 2328 buttonLayout.justify = true; 2329 buttonLayout.type = SWT.HORIZONTAL; 2330 buttonComposite.setLayout(buttonLayout); 2331 2332 Button okButton = new Button(buttonComposite, SWT.PUSH); 2333 okButton.setFont(currentFont); 2334 okButton.setText(" &OK "); 2335 dialog.setDefaultButton(okButton); 2336 okButton.addSelectionListener(new SelectionAdapter() { 2337 @Override 2338 public void widgetSelected(SelectionEvent e) { 2339 dialog.dispose(); 2340 } 2341 }); 2342 2343 dialog.pack(); 2344 2345 Point computedSize = dialog.computeSize(SWT.DEFAULT, SWT.DEFAULT); 2346 dialog.setSize(computedSize.x + 50, computedSize.y + 50); 2347 2348 // Center the window relative to the main HDFView window 2349 Point winCenter = new Point( 2350 mainWindow.getBounds().x + (mainWindow.getBounds().width / 2), 2351 mainWindow.getBounds().y + (mainWindow.getBounds().height / 2)); 2352 2353 dialog.setLocation(winCenter.x - (dialog.getSize().x / 2), winCenter.y - (dialog.getSize().y / 2)); 2354 2355 dialog.open(); 2356 2357 Display openDisplay = getParent().getDisplay(); 2358 while (!dialog.isDisposed()) { 2359 if (!openDisplay.readAndDispatch()) { 2360 openDisplay.sleep(); 2361 } 2362 } 2363 } 2364 } 2365 2366 private class UnregisterFileFormatDialog extends Dialog { 2367 2368 private List<Object> keyList; 2369 private String formatChoice = null; 2370 2371 public UnregisterFileFormatDialog(Shell parent, int style, List<Object> keyList) { 2372 super(parent, style); 2373 2374 this.keyList = keyList; 2375 } 2376 2377 public String open() { 2378 Shell parent = getParent(); 2379 final Shell shell = new Shell(parent, SWT.APPLICATION_MODAL | SWT.DIALOG_TRIM); 2380 shell.setFont(currentFont); 2381 shell.setText("Unregister a file format"); 2382 shell.setLayout(new GridLayout(2, false)); 2383 2384 Image hdfImage = ViewProperties.getLargeHdfIcon(); 2385 2386 Label imageLabel = new Label(shell, SWT.CENTER); 2387 imageLabel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); 2388 imageLabel.setImage(hdfImage); 2389 2390 2391 final Combo formatChoiceCombo = new Combo(shell, SWT.SINGLE | SWT.DROP_DOWN | SWT.READ_ONLY); 2392 formatChoiceCombo.setFont(currentFont); 2393 formatChoiceCombo.setItems(keyList.toArray(new String[0])); 2394 formatChoiceCombo.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, true)); 2395 formatChoiceCombo.select(0); 2396 formatChoiceCombo.addSelectionListener(new SelectionAdapter() { 2397 @Override 2398 public void widgetSelected(SelectionEvent e) { 2399 formatChoice = formatChoiceCombo.getItem(formatChoiceCombo.getSelectionIndex()); 2400 } 2401 }); 2402 2403 Composite buttonComposite = new Composite(shell, SWT.NONE); 2404 buttonComposite.setLayout(new GridLayout(2, true)); 2405 buttonComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 2, 1)); 2406 2407 Button okButton = new Button(buttonComposite, SWT.PUSH); 2408 okButton.setFont(currentFont); 2409 okButton.setText(" &OK "); 2410 okButton.setLayoutData(new GridData(SWT.END, SWT.FILL, true, false)); 2411 okButton.addSelectionListener(new SelectionAdapter() { 2412 @Override 2413 public void widgetSelected(SelectionEvent e) { 2414 shell.dispose(); 2415 } 2416 }); 2417 2418 Button cancelButton = new Button(buttonComposite, SWT.PUSH); 2419 cancelButton.setFont(currentFont); 2420 cancelButton.setText(" &Cancel "); 2421 cancelButton.setLayoutData(new GridData(SWT.BEGINNING, SWT.FILL, true, false)); 2422 cancelButton.addSelectionListener(new SelectionAdapter() { 2423 @Override 2424 public void widgetSelected(SelectionEvent e) { 2425 shell.dispose(); 2426 } 2427 }); 2428 2429 shell.pack(); 2430 2431 Point computedSize = shell.computeSize(SWT.DEFAULT, SWT.DEFAULT); 2432 shell.setSize(computedSize.x + 50, computedSize.y + 50); 2433 2434 Rectangle parentBounds = parent.getBounds(); 2435 Point shellSize = shell.getSize(); 2436 shell.setLocation((parentBounds.x + (parentBounds.width / 2)) - (shellSize.x / 2), 2437 (parentBounds.y + (parentBounds.height / 2)) - (shellSize.y / 2)); 2438 2439 shell.open(); 2440 2441 Display openDisplay = parent.getDisplay(); 2442 while(!shell.isDisposed()) { 2443 if (!openDisplay.readAndDispatch()) 2444 openDisplay.sleep(); 2445 } 2446 2447 return formatChoice; 2448 } 2449 } 2450 2451 /** 2452 * The starting point of this application. 2453 * 2454 * <pre> 2455 * Usage: java(w) 2456 * -Dhdf.hdf5lib.H5.hdf5lib="your HDF5 library path" 2457 * -Dhdf.hdflib.HDFLibrary.hdflib="your HDF4 library path" 2458 * -root "the directory where the HDFView is installed" 2459 * [filename] "the file to open" 2460 * </pre> 2461 * 2462 * @param args the command line arguments 2463 */ 2464 public static void main(String[] args) { 2465 if (display == null || display.isDisposed()) display = new Display(); 2466 2467 String rootDir = System.getProperty("hdfview.root"); 2468 log.trace("main: rootDir = {} ", rootDir); 2469 if (rootDir == null) 2470 rootDir = System.getProperty("user.dir"); 2471 2472 File tmpFile = null; 2473 Monitor primaryMonitor = display.getPrimaryMonitor(); 2474 Point margin = new Point(primaryMonitor.getBounds().width, 2475 primaryMonitor.getBounds().height); 2476 2477 int j = args.length; 2478 int W = margin.x / 2; 2479 int H = margin.y; 2480 int X = 0; 2481 int Y = 0; 2482 2483 for(int i = 0; i < args.length; i++) { 2484 if ("-root".equalsIgnoreCase(args[i])) { 2485 j--; 2486 try { 2487 j--; 2488 tmpFile = new File(args[++i]); 2489 2490 if(tmpFile.isDirectory()) 2491 rootDir = tmpFile.getPath(); 2492 else if(tmpFile.isFile()) 2493 rootDir = tmpFile.getParent(); 2494 } 2495 catch (Exception ex) {} 2496 } 2497 else if("-g".equalsIgnoreCase(args[i]) || "-geometry".equalsIgnoreCase(args[i])) { 2498 j--; 2499 // -geometry WIDTHxHEIGHT+XOFF+YOFF 2500 try { 2501 String geom = args[++i]; 2502 j--; 2503 2504 int idx = 0; 2505 int idx2 = geom.lastIndexOf('-'); 2506 int idx3 = geom.lastIndexOf('+'); 2507 2508 idx = Math.max(idx2, idx3); 2509 if(idx > 0) { 2510 Y = Integer.parseInt(geom.substring(idx + 1)); 2511 2512 if(idx == idx2) 2513 Y = -Y; 2514 2515 geom = geom.substring(0, idx); 2516 idx2 = geom.lastIndexOf('-'); 2517 idx3 = geom.lastIndexOf('+'); 2518 idx = Math.max(idx2, idx3); 2519 2520 if(idx > 0) { 2521 X = Integer.parseInt(geom.substring(idx + 1)); 2522 2523 if(idx == idx2) 2524 X = -X; 2525 2526 geom = geom.substring(0, idx); 2527 } 2528 } 2529 2530 idx = geom.indexOf('x'); 2531 2532 if(idx > 0) { 2533 W = Integer.parseInt(geom.substring(0, idx)); 2534 H = Integer.parseInt(geom.substring(idx + 1)); 2535 } 2536 2537 } 2538 catch (Exception ex) { 2539 ex.printStackTrace(); 2540 } 2541 } 2542 else if("-java.version".equalsIgnoreCase(args[i])) { 2543 /* Set icon to ViewProperties.getLargeHdfIcon() */ 2544 Tools.showInformation(mainWindow, "Java Version", JAVA_VER_INFO); 2545 System.exit(0); 2546 } 2547 } 2548 2549 ArrayList<File> fList = new ArrayList<>(); 2550 2551 if(j >= 0) { 2552 for(int i = args.length - j; i < args.length; i++) { 2553 tmpFile = new File(args[i]); 2554 if(!tmpFile.isAbsolute()) 2555 tmpFile = new File(rootDir, args[i]); 2556 log.trace("main: filelist - file = {} ", tmpFile.getAbsolutePath()); 2557 log.trace("main: filelist - add file = {} exists={} isFile={} isDir={}", tmpFile, tmpFile.exists(), tmpFile.isFile(), tmpFile.isDirectory()); 2558 if(tmpFile.exists() && (tmpFile.isFile() || tmpFile.isDirectory())) { 2559 log.trace("main: flist - add file = {}", tmpFile.getAbsolutePath()); 2560 fList.add(new File(tmpFile.getAbsolutePath())); 2561 } 2562 } 2563 } 2564 2565 final ArrayList<File> theFileList = fList; 2566 final String the_rootDir = rootDir; 2567 final int the_X = X, the_Y = Y, the_W = W, the_H = H; 2568 2569 display.syncExec(new Runnable() { 2570 @Override 2571 public void run() { 2572 HDFView app = new HDFView(the_rootDir); 2573 2574 // TODO: Look for a better solution to native dialog problem 2575 app.setTestState(false); 2576 2577 app.openMainWindow(theFileList, the_W, the_H, the_X, the_Y); 2578 app.runMainWindow(); 2579 } 2580 }); 2581 } 2582}