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