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