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