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