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 H5.H5PLappend(ViewProperties.getPluginDir()); 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 (FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF5) != null) 941 H5.H5PLappend(ViewProperties.getPluginDir()); 942 943 // if (userOptionDialog.isFontChanged()) { 944 Font font = null; 945 946 try { 947 font = new Font(display, ViewProperties.getFontType(), ViewProperties.getFontSize(), 948 SWT.NORMAL); 949 } 950 catch (Exception ex) { 951 font = null; 952 } 953 954 log.trace("update fonts"); 955 updateFont(font); 956 } 957 }); 958 959 new MenuItem(toolsMenu, SWT.SEPARATOR); 960 961 item = new MenuItem(toolsMenu, SWT.PUSH); 962 item.setText("&Register File Format"); 963 item.addSelectionListener(new SelectionAdapter() { 964 @Override 965 public void widgetSelected(SelectionEvent e) 966 { 967 registerFileFormat(); 968 } 969 }); 970 971 item = new MenuItem(toolsMenu, SWT.PUSH); 972 item.setText("&Unregister File Format"); 973 item.addSelectionListener(new SelectionAdapter() { 974 @Override 975 public void widgetSelected(SelectionEvent e) 976 { 977 unregisterFileFormat(); 978 } 979 }); 980 981 menuItem = new MenuItem(menu, SWT.CASCADE); 982 menuItem.setText("&Help"); 983 984 Menu helpMenu = new Menu(menuItem); 985 menuItem.setMenu(helpMenu); 986 987 item = new MenuItem(helpMenu, SWT.PUSH); 988 item.setText("&User's Guide"); 989 item.addSelectionListener(new SelectionAdapter() { 990 @Override 991 public void widgetSelected(SelectionEvent e) 992 { 993 org.eclipse.swt.program.Program.launch(HDFVIEW_USERSGUIDE_URL); 994 } 995 }); 996 997 if ((helpViews != null) && !helpViews.isEmpty()) { 998 int n = helpViews.size(); 999 for (int i = 0; i < n; i++) { 1000 HelpView theView = (HelpView)helpViews.get(i); 1001 item = new MenuItem(helpMenu, SWT.PUSH); 1002 item.setText(theView.getLabel()); 1003 // item.setActionCommand(theView.getActionCommand()); 1004 } 1005 } 1006 1007 new MenuItem(helpMenu, SWT.SEPARATOR); 1008 1009 item = new MenuItem(helpMenu, SWT.PUSH); 1010 item.setText("HDF&4 Library Version"); 1011 h4GUIs.add(item); 1012 item.addSelectionListener(new SelectionAdapter() { 1013 @Override 1014 public void widgetSelected(SelectionEvent e) 1015 { 1016 new LibraryVersionDialog(shell, FileFormat.FILE_TYPE_HDF4).open(); 1017 } 1018 }); 1019 1020 item = new MenuItem(helpMenu, SWT.PUSH); 1021 item.setText("HDF&5 Library Version"); 1022 h5GUIs.add(item); 1023 item.addSelectionListener(new SelectionAdapter() { 1024 @Override 1025 public void widgetSelected(SelectionEvent e) 1026 { 1027 new LibraryVersionDialog(shell, FileFormat.FILE_TYPE_HDF5).open(); 1028 } 1029 }); 1030 1031 item = new MenuItem(helpMenu, SWT.PUSH); 1032 item.setText("&Java Version"); 1033 item.addSelectionListener(new SelectionAdapter() { 1034 @Override 1035 public void widgetSelected(SelectionEvent e) 1036 { 1037 new JavaVersionDialog(mainWindow).open(); 1038 } 1039 }); 1040 1041 new MenuItem(helpMenu, SWT.SEPARATOR); 1042 1043 item = new MenuItem(helpMenu, SWT.PUSH); 1044 item.setText("Supported Fi&le Formats"); 1045 item.addSelectionListener(new SelectionAdapter() { 1046 @Override 1047 public void widgetSelected(SelectionEvent e) 1048 { 1049 new SupportedFileFormatsDialog(mainWindow).open(); 1050 } 1051 }); 1052 1053 new MenuItem(helpMenu, SWT.SEPARATOR); 1054 1055 item = new MenuItem(helpMenu, SWT.PUSH); 1056 item.setText("&About..."); 1057 item.addSelectionListener(new SelectionAdapter() { 1058 @Override 1059 public void widgetSelected(SelectionEvent e) 1060 { 1061 new AboutDialog(mainWindow).open(); 1062 } 1063 }); 1064 1065 setEnabled(Arrays.asList(windowMenu.getItems()), false); 1066 1067 log.info("Menubar created"); 1068 } 1069 1070 private void createToolbar(final Shell shell) 1071 { 1072 toolBar = new ToolBar(shell, SWT.HORIZONTAL | SWT.RIGHT); 1073 toolBar.setFont(Display.getCurrent().getSystemFont()); 1074 toolBar.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 3, 1)); 1075 1076 ToolItem openItem = new ToolItem(toolBar, SWT.PUSH); 1077 openItem.setToolTipText("Open"); 1078 openItem.setImage(ViewProperties.getFileopenIcon()); 1079 openItem.addSelectionListener(new SelectionAdapter() { 1080 @Override 1081 public void widgetSelected(SelectionEvent e) 1082 { 1083 openLocalFile(null, -1); 1084 } 1085 }); 1086 1087 new ToolItem(toolBar, SWT.SEPARATOR).setWidth(4); 1088 1089 ToolItem closeItem = new ToolItem(toolBar, SWT.PUSH); 1090 closeItem.setImage(ViewProperties.getFilecloseIcon()); 1091 closeItem.setToolTipText("Close"); 1092 closeItem.addSelectionListener(new SelectionAdapter() { 1093 @Override 1094 public void widgetSelected(SelectionEvent e) 1095 { 1096 closeFile(treeView.getSelectedFile()); 1097 } 1098 }); 1099 1100 new ToolItem(toolBar, SWT.SEPARATOR).setWidth(20); 1101 1102 ToolItem helpItem = new ToolItem(toolBar, SWT.PUSH); 1103 helpItem.setImage(ViewProperties.getHelpIcon()); 1104 helpItem.setToolTipText("Help"); 1105 helpItem.addSelectionListener(new SelectionAdapter() { 1106 @Override 1107 public void widgetSelected(SelectionEvent e) 1108 { 1109 String ugPath = ViewProperties.getUsersGuide(); 1110 1111 if (ugPath == null || !ugPath.startsWith("http://")) { 1112 String sep = File.separator; 1113 File tmpFile = new File(ugPath); 1114 1115 if (!(tmpFile.exists())) { 1116 ugPath = rootDir + sep + "UsersGuide" + sep + "index.html"; 1117 tmpFile = new File(ugPath); 1118 1119 if (!(tmpFile.exists())) 1120 ugPath = HDFVIEW_USERSGUIDE_URL; 1121 1122 ViewProperties.setUsersGuide(ugPath); 1123 } 1124 } 1125 1126 try { 1127 org.eclipse.swt.program.Program.launch(ugPath); 1128 } 1129 catch (Exception ex) { 1130 Tools.showError(shell, "Help", ex.getMessage()); 1131 } 1132 } 1133 }); 1134 1135 new ToolItem(toolBar, SWT.SEPARATOR).setWidth(4); 1136 1137 ToolItem hdf4Item = new ToolItem(toolBar, SWT.PUSH); 1138 hdf4Item.setImage(ViewProperties.getH4Icon()); 1139 hdf4Item.setToolTipText("HDF4 Library Version"); 1140 hdf4Item.addSelectionListener(new SelectionAdapter() { 1141 @Override 1142 public void widgetSelected(SelectionEvent e) 1143 { 1144 new LibraryVersionDialog(shell, FileFormat.FILE_TYPE_HDF4).open(); 1145 } 1146 }); 1147 1148 if (FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF4) == null) 1149 hdf4Item.setEnabled(false); 1150 1151 new ToolItem(toolBar, SWT.SEPARATOR).setWidth(4); 1152 1153 ToolItem hdf5Item = new ToolItem(toolBar, SWT.PUSH); 1154 hdf5Item.setImage(ViewProperties.getH5Icon()); 1155 hdf5Item.setToolTipText("HDF5 Library Version"); 1156 hdf5Item.addSelectionListener(new SelectionAdapter() { 1157 @Override 1158 public void widgetSelected(SelectionEvent e) 1159 { 1160 new LibraryVersionDialog(shell, FileFormat.FILE_TYPE_HDF5).open(); 1161 } 1162 }); 1163 1164 if (FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF5) == null) 1165 hdf5Item.setEnabled(false); 1166 1167 // Make the toolbar as wide as the window and as 1168 // tall as the buttons 1169 toolBar.setSize(shell.getClientArea().width, openItem.getBounds().height); 1170 toolBar.setLocation(0, 0); 1171 1172 log.info("Toolbar created"); 1173 } 1174 1175 private void createUrlToolbar(final Shell shell) 1176 { 1177 // Recent Files button 1178 recentFilesButton = new Button(shell, SWT.PUSH); 1179 recentFilesButton.setFont(currentFont); 1180 recentFilesButton.setText("Recent Files"); 1181 recentFilesButton.setToolTipText("List of recent files"); 1182 recentFilesButton.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false)); 1183 recentFilesButton.addSelectionListener(new SelectionAdapter() { 1184 @Override 1185 public void widgetSelected(SelectionEvent e) 1186 { 1187 urlBar.setListVisible(true); 1188 } 1189 }); 1190 1191 // Recent files combo box 1192 urlBar = new Combo(shell, SWT.BORDER | SWT.SINGLE); 1193 urlBar.setFont(currentFont); 1194 urlBar.setItems(ViewProperties.getMRF().toArray(new String[0])); 1195 urlBar.setVisibleItemCount(ViewProperties.MAX_RECENT_FILES); 1196 urlBar.deselectAll(); 1197 urlBar.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); 1198 urlBar.addKeyListener(new KeyAdapter() { 1199 @Override 1200 public void keyPressed(KeyEvent e) 1201 { 1202 if (e.keyCode == SWT.CR) { 1203 String filename = urlBar.getText(); 1204 if (filename == null || filename.length() < 1 || filename.equals(currentFile)) 1205 return; 1206 1207 if (!(filename.startsWith("http://") || filename.startsWith("https://") || 1208 filename.startsWith("ftp://"))) { 1209 openLocalFile(filename, -1); 1210 } 1211 else { 1212 String remoteFile = openRemoteFile(filename); 1213 1214 if (remoteFile != null) 1215 openLocalFile(remoteFile, -1); 1216 } 1217 } 1218 } 1219 }); 1220 urlBar.addSelectionListener(new SelectionAdapter() { 1221 @Override 1222 public void widgetSelected(SelectionEvent e) 1223 { 1224 String filename = urlBar.getText(); 1225 if (filename == null || filename.length() < 1 || filename.equals(currentFile)) { 1226 return; 1227 } 1228 1229 if (!(filename.startsWith("http://") || filename.startsWith("https://") || 1230 filename.startsWith("ftp://"))) { 1231 openLocalFile(filename, -1); 1232 } 1233 else { 1234 String remoteFile = openRemoteFile(filename); 1235 1236 if (remoteFile != null) 1237 openLocalFile(remoteFile, -1); 1238 } 1239 } 1240 }); 1241 1242 clearTextButton = new Button(shell, SWT.PUSH); 1243 clearTextButton.setToolTipText("Clear current selection"); 1244 clearTextButton.setFont(currentFont); 1245 clearTextButton.setText("Clear Text"); 1246 clearTextButton.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false)); 1247 clearTextButton.addSelectionListener(new SelectionAdapter() { 1248 @Override 1249 public void widgetSelected(SelectionEvent e) 1250 { 1251 urlBar.setText(""); 1252 urlBar.deselectAll(); 1253 } 1254 }); 1255 1256 log.info("URL Toolbar created"); 1257 } 1258 1259 private void createContentArea(final Shell shell) 1260 { 1261 SashForm content = new SashForm(shell, SWT.VERTICAL); 1262 content.setSashWidth(10); 1263 content.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 3, 1)); 1264 1265 // Add Data content area and Status Area to main window 1266 Composite container = new Composite(content, SWT.NONE); 1267 container.setLayout(new FillLayout()); 1268 1269 Composite statusArea = new Composite(content, SWT.NONE); 1270 statusArea.setLayout(new FillLayout(SWT.HORIZONTAL)); 1271 1272 final SashForm contentArea = new SashForm(container, SWT.HORIZONTAL); 1273 contentArea.setSashWidth(10); 1274 1275 // Add TreeView and DataView to content area pane 1276 treeArea = new ScrolledComposite(contentArea, SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER); 1277 treeArea.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_WHITE)); 1278 treeArea.setExpandHorizontal(true); 1279 treeArea.setExpandVertical(true); 1280 1281 generalArea = new ScrolledComposite(contentArea, SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER); 1282 generalArea.setExpandHorizontal(true); 1283 generalArea.setExpandVertical(true); 1284 generalArea.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_WIDGET_LIGHT_SHADOW)); 1285 generalArea.setMinHeight(contentArea.getSize().y - 2); 1286 1287 // Create status area for displaying messages and metadata 1288 status = new Text(statusArea, SWT.V_SCROLL | SWT.MULTI | SWT.BORDER); 1289 status.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_WIDGET_LIGHT_SHADOW)); 1290 status.setEditable(false); 1291 status.setFont(currentFont); 1292 1293 contentArea.addListener(SWT.Resize, new Listener() { 1294 @Override 1295 public void handleEvent(Event arg0) 1296 { 1297 generalArea.setMinHeight(contentArea.getSize().y - 2); 1298 } 1299 }); 1300 1301 // Add drag and drop support for opening files 1302 DropTarget target = new DropTarget(treeArea, DND.DROP_COPY); 1303 final FileTransfer fileTransfer = FileTransfer.getInstance(); 1304 target.setTransfer(new Transfer[] {fileTransfer}); 1305 target.addDropListener(new DropTargetListener() { 1306 @Override 1307 public void dragEnter(DropTargetEvent e) 1308 { 1309 e.detail = DND.DROP_COPY; 1310 } 1311 @Override 1312 public void dragOver(DropTargetEvent e) 1313 { 1314 // Intentional 1315 } 1316 @Override 1317 public void dragOperationChanged(DropTargetEvent e) 1318 { 1319 // Intentional 1320 } 1321 @Override 1322 public void dragLeave(DropTargetEvent e) 1323 { 1324 // Intentional 1325 } 1326 @Override 1327 public void dropAccept(DropTargetEvent e) 1328 { 1329 // Intentional 1330 } 1331 @Override 1332 public void drop(DropTargetEvent e) 1333 { 1334 if (fileTransfer.isSupportedType(e.currentDataType)) { 1335 String[] files = (String[])e.data; 1336 for (int i = 0; i < files.length; i++) 1337 openLocalFile(files[i], -1); 1338 } 1339 } 1340 }); 1341 1342 showStatus("HDFView root - " + rootDir); 1343 showStatus("User property file - " + ViewProperties.getPropertyFile()); 1344 1345 content.setWeights(new int[] {9, 1}); 1346 contentArea.setWeights(new int[] {1, 3}); 1347 1348 DataViewFactory treeViewFactory = null; 1349 try { 1350 treeViewFactory = DataViewFactoryProducer.getFactory(DataViewType.TREEVIEW); 1351 } 1352 catch (Exception ex) { 1353 log.debug("createContentArea(): error occurred while instantiating TreeView factory class", ex); 1354 this.showError("Error occurred while instantiating TreeView factory class"); 1355 return; 1356 } 1357 1358 if (treeViewFactory == null) { 1359 log.debug("createContentArea(): TreeView factory is null"); 1360 return; 1361 } 1362 1363 try { 1364 treeView = treeViewFactory.getTreeView(treeArea, this); 1365 1366 if (treeView == null) { 1367 log.debug("createContentArea(): error occurred while instantiating TreeView class"); 1368 this.showError("Error occurred while instantiating TreeView class"); 1369 return; 1370 } 1371 } 1372 catch (ClassNotFoundException ex) { 1373 log.debug("createContentArea(): no suitable TreeView class found"); 1374 this.showError("Unable to find suitable TreeView class"); 1375 return; 1376 } 1377 1378 treeArea.setContent(treeView.getTree()); 1379 1380 log.info("Content Area created"); 1381 } 1382 1383 /** 1384 * @return a list of treeview implementations. 1385 */ 1386 public static final List<String> getListOfTreeViews() { return treeViews; } 1387 1388 /** 1389 * @return a list of imageview implementations. 1390 */ 1391 public static final List<String> getListOfImageViews() { return imageViews; } 1392 1393 /** 1394 * @return a list of tableview implementations. 1395 */ 1396 public static final List<?> getListOfTableViews() { return tableViews; } 1397 1398 /** 1399 * @return a list of metaDataview implementations. 1400 */ 1401 public static final List<?> getListOfMetaDataViews() { return metaDataViews; } 1402 1403 /** 1404 * @return a list of paletteview implementations. 1405 */ 1406 public static final List<?> getListOfPaletteViews() { return paletteViews; } 1407 1408 @Override 1409 public TreeView getTreeView() 1410 { 1411 return treeView; 1412 } 1413 1414 /** 1415 * @return the combobox associated with a URL entry. 1416 */ 1417 public Combo getUrlBar() { return urlBar; } 1418 1419 /** 1420 * Start stop a timer. 1421 * 1422 * @param toggleTimer 1423 * -- true: start timer, false stop timer. 1424 */ 1425 @Override 1426 public final void executeTimer(boolean toggleTimer) 1427 { 1428 showStatus("toggleTimer: " + toggleTimer); 1429 viewerState = toggleTimer; 1430 if (viewerState) 1431 display.timerExec(ViewProperties.getTimerRefresh(), timer); 1432 else 1433 display.timerExec(-1, timer); 1434 } 1435 1436 /** 1437 * Display feedback message. 1438 * 1439 * @param msg 1440 * the message to display. 1441 */ 1442 @Override 1443 public void showStatus(String msg) 1444 { 1445 if (status == null) { 1446 log.debug("showStatus(): status area is null"); 1447 return; 1448 } 1449 1450 status.append(msg); 1451 status.append("\n"); 1452 } 1453 1454 /** 1455 * Display error message 1456 * 1457 * @param errMsg 1458 * the error message to display 1459 */ 1460 @Override 1461 public void showError(String errMsg) 1462 { 1463 if (status == null) { 1464 log.debug("showError(): status area is null"); 1465 return; 1466 } 1467 1468 status.append(" *** "); 1469 status.append(errMsg); 1470 if (log.isDebugEnabled()) 1471 status.append(" - see log for more info"); 1472 status.append(" *** "); 1473 status.append("\n"); 1474 } 1475 1476 /** 1477 * Display the metadata view for an object 1478 * 1479 * @param obj 1480 * the object containing the metadata to show 1481 */ 1482 public void showMetaData(final HObject obj) 1483 { 1484 for (Control control : generalArea.getChildren()) 1485 control.dispose(); 1486 generalArea.setContent(null); 1487 1488 if (obj == null) 1489 return; 1490 1491 DataViewFactory metaDataViewFactory = null; 1492 try { 1493 metaDataViewFactory = DataViewFactoryProducer.getFactory(DataViewType.METADATA); 1494 } 1495 catch (Exception ex) { 1496 log.debug("showMetaData(): error occurred while instantiating MetaDataView factory class", ex); 1497 this.showError("Error occurred while instantiating MetaDataView factory class"); 1498 return; 1499 } 1500 1501 if (metaDataViewFactory == null) { 1502 log.debug("showMetaData(): MetaDataView factory is null"); 1503 return; 1504 } 1505 1506 MetaDataView theView; 1507 try { 1508 theView = metaDataViewFactory.getMetaDataView(generalArea, this, obj); 1509 1510 if (theView == null) { 1511 log.debug("showMetaData(): error occurred while instantiating MetaDataView class"); 1512 this.showError("Error occurred while instantiating MetaDataView class"); 1513 return; 1514 } 1515 } 1516 catch (ClassNotFoundException ex) { 1517 log.debug("showMetaData(): no suitable MetaDataView class found"); 1518 this.showError("Unable to find suitable MetaDataView class"); 1519 return; 1520 } 1521 } 1522 1523 /** 1524 * close the file currently selected in the application 1525 * 1526 * @param theFile 1527 * the file selected or specified 1528 */ 1529 public void closeFile(FileFormat theFile) 1530 { 1531 if (theFile == null) { 1532 display.beep(); 1533 Tools.showError(mainWindow, "Close", "Select a file to close"); 1534 return; 1535 } 1536 1537 // Close all the data windows of this file 1538 Shell[] views = display.getShells(); 1539 if (views != null) { 1540 for (int i = 0; i < views.length; i++) { 1541 Object shellData = views[i].getData(); 1542 1543 if (!(shellData instanceof DataView)) 1544 continue; 1545 1546 if ((DataView)shellData != null) { 1547 HObject obj = ((DataView)shellData).getDataObject(); 1548 1549 if (obj == null || obj.getFileFormat() == null) 1550 continue; 1551 1552 if (obj.getFileFormat().equals(theFile)) { 1553 views[i].dispose(); 1554 views[i] = null; 1555 } 1556 } 1557 } 1558 } 1559 1560 int index = urlBar.getSelectionIndex(); 1561 if (index >= 0) { 1562 String fName = urlBar.getItem(urlBar.getSelectionIndex()); 1563 if (theFile.getFilePath().equals(fName)) { 1564 currentFile = null; 1565 urlBar.setText(""); 1566 } 1567 } 1568 1569 try { 1570 treeView.closeFile(theFile); 1571 } 1572 catch (Exception ex) { 1573 // Intentional 1574 } 1575 1576 for (Control control : generalArea.getChildren()) 1577 control.dispose(); 1578 generalArea.setContent(null); 1579 1580 System.gc(); 1581 } 1582 1583 /** 1584 * Write the change of data to the given file. 1585 * 1586 * @param theFile 1587 * The file to be updated. 1588 */ 1589 public void writeDataToFile(FileFormat theFile) 1590 { 1591 try { 1592 Shell[] openShells = display.getShells(); 1593 1594 if (openShells != null) { 1595 for (int i = 0; i < openShells.length; i++) { 1596 DataView theView = (DataView)openShells[i].getData(); 1597 1598 if (theView instanceof TableView) { 1599 TableView tableView = (TableView)theView; 1600 FileFormat file = tableView.getDataObject().getFileFormat(); 1601 if (file.equals(theFile)) 1602 tableView.updateValueInFile(); 1603 } 1604 } 1605 } 1606 } 1607 catch (Exception ex) { 1608 display.beep(); 1609 Tools.showError(mainWindow, "Save", ex.getMessage()); 1610 } 1611 } 1612 1613 @Override 1614 public void addDataView(DataView dataView) 1615 { 1616 if (dataView == null || dataView instanceof MetaDataView) 1617 return; 1618 1619 // Check if the data content is already displayed 1620 Shell[] shellList = display.getShells(); 1621 if (shellList != null) { 1622 for (int i = 0; i < shellList.length; i++) { 1623 if (dataView.equals(shellList[i].getData()) && shellList[i].isVisible()) { 1624 showWindow(shellList[i]); 1625 return; 1626 } 1627 } 1628 } 1629 1630 // First window being added 1631 if (shellList != null && shellList.length == 2) 1632 setEnabled(Arrays.asList(windowMenu.getItems()), true); 1633 1634 HObject obj = dataView.getDataObject(); 1635 String fullPath = 1636 ((obj.getPath() == null) ? "" : obj.getPath()) + ((obj.getName() == null) ? "" : obj.getName()); 1637 1638 MenuItem item = new MenuItem(windowMenu, SWT.PUSH); 1639 item.setText(fullPath); 1640 item.addSelectionListener(new SelectionAdapter() { 1641 @Override 1642 public void widgetSelected(SelectionEvent e) 1643 { 1644 Shell[] sList = display.getShells(); 1645 1646 for (int i = 0; i < sList.length; i++) { 1647 DataView view = (DataView)sList[i].getData(); 1648 1649 if (view != null) { 1650 HObject obj = view.getDataObject(); 1651 1652 if (obj.getFullName().equals(((MenuItem)e.widget).getText())) 1653 showWindow(sList[i]); 1654 } 1655 } 1656 } 1657 }); 1658 1659 mainWindow.setCursor(null); 1660 } 1661 1662 @Override 1663 public void removeDataView(DataView dataView) 1664 { 1665 if (mainWindow.isDisposed()) 1666 return; 1667 1668 HObject obj = dataView.getDataObject(); 1669 if (obj == null) 1670 return; 1671 1672 MenuItem[] items = windowMenu.getItems(); 1673 for (int i = 0; i < items.length; i++) { 1674 if (items[i].getText().equals(obj.getFullName())) 1675 items[i].dispose(); 1676 } 1677 1678 // Last window being closed 1679 if (display.getShells().length == 2) 1680 for (MenuItem item : windowMenu.getItems()) 1681 item.setEnabled(false); 1682 } 1683 1684 @Override 1685 public DataView getDataView(HObject dataObject) 1686 { 1687 Shell[] openShells = display.getShells(); 1688 DataView view = null; 1689 HObject currentObj = null; 1690 FileFormat currentDataViewFile = null; 1691 1692 for (int i = 0; i < openShells.length; i++) { 1693 view = (DataView)openShells[i].getData(); 1694 1695 if (view != null) { 1696 currentObj = view.getDataObject(); 1697 if (currentObj == null) 1698 continue; 1699 1700 currentDataViewFile = currentObj.getFileFormat(); 1701 1702 if (currentObj.equals(dataObject) && currentDataViewFile.equals(dataObject.getFileFormat())) 1703 return view; 1704 } 1705 } 1706 1707 return null; 1708 } 1709 1710 /** 1711 * Set the testing state that determines if HDFView 1712 * is being executed for GUI testing. 1713 * 1714 * @param testing 1715 * Provides SWTBot native dialog compatibility 1716 * workarounds if set to true. 1717 */ 1718 public void setTestState(boolean testing) { isTesting = testing; } 1719 1720 /** 1721 * Get the testing state that determines if HDFView 1722 * is being executed for GUI testing. 1723 * 1724 * @return true if HDFView is being executed for GUI testing. 1725 */ 1726 public boolean getTestState() { return isTesting; } 1727 1728 /** 1729 * Set default UI fonts. 1730 */ 1731 private void updateFont(Font font) 1732 { 1733 if (currentFont != null) 1734 currentFont.dispose(); 1735 1736 log.trace("updateFont():"); 1737 currentFont = font; 1738 1739 mainWindow.setFont(font); 1740 recentFilesButton.setFont(font); 1741 recentFilesButton.requestLayout(); 1742 urlBar.setFont(font); 1743 urlBar.requestLayout(); 1744 clearTextButton.setFont(font); 1745 clearTextButton.requestLayout(); 1746 status.setFont(font); 1747 1748 // On certain platforms the url_bar items don't update their size after 1749 // a font change. Removing and replacing them fixes this. 1750 for (String item : urlBar.getItems()) { 1751 urlBar.remove(item); 1752 urlBar.add(item); 1753 } 1754 1755 treeArea.setFont(font); 1756 treeArea.requestLayout(); 1757 for (Control control : treeArea.getChildren()) { 1758 control.setFont(font); 1759 control.requestLayout(); 1760 } 1761 1762 generalArea.setFont(font); 1763 generalArea.requestLayout(); 1764 for (Control control : generalArea.getChildren()) { 1765 control.setFont(font); 1766 control.requestLayout(); 1767 } 1768 1769 if (treeView.getSelectedFile() != null) 1770 urlBar.select(0); 1771 1772 if (treeView instanceof DefaultTreeView) 1773 ((DefaultTreeView)treeView).updateFont(font); 1774 1775 Shell[] shellList = display.getShells(); 1776 if (shellList != null) { 1777 for (int i = 0; i < shellList.length; i++) { 1778 shellList[i].setFont(font); 1779 shellList[i].requestLayout(); 1780 } 1781 } 1782 1783 mainWindow.requestLayout(); 1784 } 1785 1786 /** 1787 * Bring window to the front. 1788 * 1789 * @param name 1790 * the name of the window to show. 1791 */ 1792 private void showWindow(final Shell shell) 1793 { 1794 shell.getDisplay().asyncExec(new Runnable() { 1795 @Override 1796 public void run() 1797 { 1798 shell.forceActive(); 1799 } 1800 }); 1801 } 1802 1803 /** 1804 * Cascade all windows. 1805 */ 1806 private void cascadeWindows() 1807 { 1808 Shell[] sList = display.getShells(); 1809 1810 // Return if main window (shell) is the only open shell 1811 if (sList.length <= 1) 1812 return; 1813 1814 Shell shell = null; 1815 1816 Rectangle bounds = Display.getCurrent().getPrimaryMonitor().getClientArea(); 1817 int w = Math.max(50, bounds.width - 100); 1818 int h = Math.max(50, bounds.height - 100); 1819 1820 int x = bounds.x; 1821 int y = bounds.y; 1822 1823 for (int i = 0; i < sList.length; i++) { 1824 shell = sList[i]; 1825 shell.setBounds(x, y, w, h); 1826 shell.setActive(); 1827 x += 20; 1828 y += 20; 1829 } 1830 } 1831 1832 /** 1833 * Tile all windows. 1834 */ 1835 private void tileWindows() 1836 { 1837 Shell[] sList = display.getShells(); 1838 1839 // Return if main window (shell) is the only open shell 1840 if (sList.length <= 1) 1841 return; 1842 1843 int x = 0; 1844 int y = 0; 1845 int idx = 0; 1846 Shell shell = null; 1847 1848 int n = sList.length; 1849 int cols = (int)Math.sqrt(n); 1850 int rows = (int)Math.ceil((double)n / (double)cols); 1851 1852 Rectangle bounds = Display.getCurrent().getPrimaryMonitor().getClientArea(); 1853 int w = bounds.width / cols; 1854 int h = bounds.height / rows; 1855 1856 y = bounds.y; 1857 for (int i = 0; i < rows; i++) { 1858 x = bounds.x; 1859 1860 for (int j = 0; j < cols; j++) { 1861 idx = i * cols + j; 1862 if (idx >= n) 1863 return; 1864 1865 shell = sList[idx]; 1866 shell.setBounds(x, y, w, h); 1867 shell.setActive(); 1868 x += w; 1869 } 1870 1871 y += h; 1872 } 1873 } 1874 1875 /** 1876 * Closes all windows. 1877 */ 1878 private void closeAllWindows() 1879 { 1880 Shell[] sList = display.getShells(); 1881 1882 for (int i = 0; i < sList.length; i++) { 1883 if (sList[i].equals(mainWindow)) 1884 continue; 1885 sList[i].dispose(); 1886 } 1887 } 1888 1889 /* Enable and disable GUI components */ 1890 private static void setEnabled(List<MenuItem> list, boolean b) 1891 { 1892 Iterator<MenuItem> it = list.iterator(); 1893 1894 while (it.hasNext()) 1895 it.next().setEnabled(b); 1896 } 1897 1898 /** Open local file */ 1899 private void openLocalFile(String filename, int fileAccessID) 1900 { 1901 log.trace("openLocalFile {},{}", filename, fileAccessID); 1902 1903 /* 1904 * If given a specific access mode, use it without changing it. If not given a 1905 * specific access mode, check the current status of the "is read only" property 1906 * to determine how to open the file. This is to allow one time overrides of the 1907 * default file access mode when opening a file. 1908 */ 1909 int accessMode = fileAccessID; 1910 if (accessMode < 0) { 1911 if (ViewProperties.isReadOnly()) 1912 accessMode = FileFormat.READ; 1913 else if (ViewProperties.isReadSWMR()) 1914 accessMode = FileFormat.READ | FileFormat.MULTIREAD; 1915 else 1916 accessMode = FileFormat.WRITE; 1917 } 1918 1919 String[] selectedFilenames = null; 1920 File[] chosenFiles = null; 1921 1922 if (filename != null) { 1923 File file = new File(filename); 1924 if (!file.exists()) { 1925 Tools.showError(mainWindow, "Open", "File " + filename + " does not exist."); 1926 return; 1927 } 1928 1929 if (file.isDirectory()) { 1930 currentDir = filename; 1931 openLocalFile(null, -1); 1932 } 1933 else { 1934 currentFile = filename; 1935 1936 try { 1937 treeView.openFile(filename, accessMode); 1938 } 1939 catch (Exception ex) { 1940 try { 1941 treeView.openFile(filename, FileFormat.READ); 1942 } 1943 catch (Exception ex2) { 1944 display.beep(); 1945 urlBar.deselectAll(); 1946 Tools.showError(mainWindow, "Open", "Failed to open file " + filename + "\n" + ex2); 1947 currentFile = null; 1948 } 1949 } 1950 } 1951 1952 try { 1953 urlBar.remove(filename); 1954 } 1955 catch (Exception ex) { 1956 log.trace("unable to remove {} from urlBar", filename); 1957 } 1958 1959 // first entry is always the workdir 1960 urlBar.add(filename, 1); 1961 urlBar.select(1); 1962 } 1963 else { 1964 if (!isTesting) { 1965 log.trace("openLocalFile filename is null"); 1966 FileDialog fChooser = new FileDialog(mainWindow, SWT.OPEN | SWT.MULTI); 1967 String modeStr = "Read/Write"; 1968 boolean isSWMRFile = (FileFormat.MULTIREAD == (accessMode & FileFormat.MULTIREAD)); 1969 if (isSWMRFile) 1970 modeStr = "SWMR Read-only"; 1971 else if (accessMode == FileFormat.READ) 1972 modeStr = "Read-only"; 1973 fChooser.setText(mainWindow.getText() + " - Open File " + modeStr); 1974 fChooser.setFilterPath(currentDir); 1975 1976 DefaultFileFilter filter = DefaultFileFilter.getFileFilter(); 1977 fChooser.setFilterExtensions(new String[] {"*", filter.getExtensions()}); 1978 fChooser.setFilterNames(new String[] {"All Files", filter.getDescription()}); 1979 fChooser.setFilterIndex(1); 1980 1981 fChooser.open(); 1982 1983 selectedFilenames = fChooser.getFileNames(); 1984 if (selectedFilenames.length <= 0) 1985 return; 1986 1987 chosenFiles = new File[selectedFilenames.length]; 1988 for (int i = 0; i < chosenFiles.length; i++) { 1989 log.trace("openLocalFile selectedFilenames[{}]: {}", i, selectedFilenames[i]); 1990 chosenFiles[i] = 1991 new File(fChooser.getFilterPath() + File.separator + selectedFilenames[i]); 1992 1993 if (!chosenFiles[i].exists()) { 1994 Tools.showError(mainWindow, "Open", 1995 "File " + chosenFiles[i].getName() + " does not exist."); 1996 continue; 1997 } 1998 1999 if (chosenFiles[i].isDirectory()) 2000 currentDir = chosenFiles[i].getPath(); 2001 else 2002 currentDir = chosenFiles[i].getParent(); 2003 2004 try { 2005 urlBar.remove(chosenFiles[i].getAbsolutePath()); 2006 } 2007 catch (Exception ex) { 2008 log.trace("unable to remove {} from urlBar", chosenFiles[i].getAbsolutePath()); 2009 } 2010 2011 // first entry is always the workdir 2012 urlBar.add(chosenFiles[i].getAbsolutePath(), 1); 2013 urlBar.select(1); 2014 2015 log.trace("openLocalFile treeView.openFile(accessMode={} chosenFiles[{}]: {}", accessMode, 2016 i, chosenFiles[i].getAbsolutePath()); 2017 try { 2018 treeView.openFile(chosenFiles[i].getAbsolutePath(), accessMode + FileFormat.OPEN_NEW); 2019 } 2020 catch (Exception ex) { 2021 try { 2022 treeView.openFile(chosenFiles[i].getAbsolutePath(), FileFormat.READ); 2023 } 2024 catch (Exception ex2) { 2025 display.beep(); 2026 urlBar.deselectAll(); 2027 Tools.showError(mainWindow, "Open", 2028 "Failed to open file " + selectedFilenames[i] + "\n" + ex2); 2029 currentFile = null; 2030 } 2031 } 2032 } 2033 2034 currentFile = chosenFiles[0].getAbsolutePath(); 2035 } 2036 else { 2037 // Prepend test file directory to filename 2038 String fName = 2039 currentDir + File.separator + new InputDialog(mainWindow, "Enter a file name", "").open(); 2040 2041 File chosenFile = new File(fName); 2042 2043 if (!chosenFile.exists()) { 2044 Tools.showError(mainWindow, "Open", "File " + chosenFile.getName() + " does not exist."); 2045 return; 2046 } 2047 2048 if (chosenFile.isDirectory()) 2049 currentDir = chosenFile.getPath(); 2050 else 2051 currentDir = chosenFile.getParent(); 2052 2053 try { 2054 urlBar.remove(chosenFile.getAbsolutePath()); 2055 } 2056 catch (Exception ex) { 2057 log.trace("unable to remove {} from urlBar", chosenFile.getAbsolutePath()); 2058 } 2059 2060 // first entry is always the workdir 2061 urlBar.add(chosenFile.getAbsolutePath(), 1); 2062 urlBar.select(1); 2063 2064 log.trace("openLocalFile treeView.openFile(chosenFile[{}]: {}", chosenFile.getAbsolutePath(), 2065 accessMode + FileFormat.OPEN_NEW); 2066 try { 2067 treeView.openFile(chosenFile.getAbsolutePath(), accessMode + FileFormat.OPEN_NEW); 2068 } 2069 catch (Exception ex) { 2070 try { 2071 treeView.openFile(chosenFile.getAbsolutePath(), FileFormat.READ); 2072 } 2073 catch (Exception ex2) { 2074 display.beep(); 2075 urlBar.deselectAll(); 2076 Tools.showError(mainWindow, "Open", "Failed to open file " + chosenFile + "\n" + ex2); 2077 currentFile = null; 2078 } 2079 } 2080 2081 currentFile = chosenFile.getAbsolutePath(); 2082 } 2083 } 2084 } 2085 2086 /** Load remote file and save it to local temporary directory */ 2087 private String openRemoteFile(String urlStr) 2088 { 2089 if (urlStr == null) 2090 return null; 2091 2092 String localFile = null; 2093 2094 if (urlStr.startsWith("http://")) 2095 localFile = urlStr.substring(7); 2096 else if (urlStr.startsWith("https://")) 2097 localFile = urlStr.substring(8); 2098 else if (urlStr.startsWith("ftp://")) 2099 localFile = urlStr.substring(6); 2100 else 2101 return null; 2102 2103 localFile = localFile.replace('/', '@'); 2104 localFile = localFile.replace('\\', '@'); 2105 2106 // Search the local file cache 2107 String tmpDir = System.getProperty("java.io.tmpdir"); 2108 2109 File tmpFile = new File(tmpDir); 2110 if (!tmpFile.canWrite()) 2111 tmpDir = System.getProperty("user.home"); 2112 2113 localFile = tmpDir + File.separator + localFile; 2114 2115 tmpFile = new File(localFile); 2116 if (tmpFile.exists()) 2117 return localFile; 2118 2119 URL url = null; 2120 2121 try { 2122 url = new URL(urlStr); 2123 } 2124 catch (Exception ex) { 2125 url = null; 2126 display.beep(); 2127 Tools.showError(mainWindow, "Open", ex.getMessage()); 2128 return null; 2129 } 2130 2131 try (BufferedInputStream in = new BufferedInputStream(url.openStream())) { 2132 try (BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(tmpFile))) { 2133 mainWindow.setCursor(display.getSystemCursor(SWT.CURSOR_WAIT)); 2134 byte[] buff = new byte[512]; // set default buffer size to 512 2135 int n = 0; 2136 while ((n = in.read(buff)) > 0) 2137 out.write(buff, 0, n); 2138 } 2139 catch (Exception ex) { 2140 log.debug("Remote file: ", ex); 2141 throw ex; 2142 } 2143 } 2144 catch (Exception ex) { 2145 display.beep(); 2146 Tools.showError(mainWindow, "Open", ex.getMessage()); 2147 // Want to call setCursor always 2148 localFile = null; 2149 } 2150 2151 mainWindow.setCursor(null); 2152 2153 return localFile; 2154 } 2155 2156 private void convertFile(String typeFrom, String typeTo) 2157 { 2158 ImageConversionDialog dialog = 2159 new ImageConversionDialog(mainWindow, typeFrom, typeTo, currentDir, treeView.getCurrentFiles()); 2160 dialog.open(); 2161 2162 if (dialog.isFileConverted()) { 2163 String filename = dialog.getConvertedFile(); 2164 File theFile = new File(filename); 2165 2166 if (!theFile.exists()) 2167 return; 2168 2169 currentDir = theFile.getParentFile().getAbsolutePath(); 2170 currentFile = theFile.getAbsolutePath(); 2171 2172 try { 2173 treeView.openFile(filename, FileFormat.WRITE); 2174 2175 try { 2176 urlBar.remove(filename); 2177 } 2178 catch (Exception ex) { 2179 log.trace("unable to remove {} from urlBar", filename); 2180 } 2181 2182 // first entry is always the workdir 2183 urlBar.add(filename, 1); 2184 urlBar.select(1); 2185 } 2186 catch (Exception ex) { 2187 showError(ex.toString()); 2188 } 2189 } 2190 } 2191 2192 private void registerFileFormat() 2193 { 2194 String msg = "Register a new file format by \nKEY:FILE_FORMAT:FILE_EXTENSION\n" 2195 + "where, KEY: the unique identifier for the file format" 2196 + "\n FILE_FORMAT: the full class name of the file format" 2197 + "\n FILE_EXTENSION: the file extension for the file format" 2198 + "\n\nFor example, " 2199 + "\n\t to add NetCDF, \"NetCDF:hdf.object.nc2.NC2File:nc\"" 2200 + "\n\t to add FITS, \"FITS:hdf.object.fits.FitsFile:fits\"\n\n"; 2201 2202 // TODO:Add custom HDFLarge icon to dialog 2203 InputDialog dialog = new InputDialog(mainWindow, "Register a file format", msg, SWT.ICON_INFORMATION); 2204 2205 String str = dialog.open(); 2206 2207 if ((str == null) || (str.length() < 1)) 2208 return; 2209 2210 int idx1 = str.indexOf(':'); 2211 int idx2 = str.lastIndexOf(':'); 2212 2213 if ((idx1 < 0) || (idx2 <= idx1)) { 2214 Tools.showError(mainWindow, "Register File Format", 2215 "Failed to register " + str + 2216 "\n\nMust in the form of KEY:FILE_FORMAT:FILE_EXTENSION"); 2217 return; 2218 } 2219 2220 String key = str.substring(0, idx1); 2221 String className = str.substring(idx1 + 1, idx2); 2222 String extension = str.substring(idx2 + 1); 2223 2224 // Check if the file format has been registered or the key is taken. 2225 String theKey = null; 2226 String theClassName = null; 2227 Enumeration<?> localEnum = FileFormat.getFileFormatKeys(); 2228 while (localEnum.hasMoreElements()) { 2229 theKey = (String)localEnum.nextElement(); 2230 if (theKey.endsWith(key)) { 2231 Tools.showError(mainWindow, "Register File Format", "Invalid key: " + key + " is taken."); 2232 return; 2233 } 2234 2235 theClassName = FileFormat.getFileFormat(theKey).getClass().getName(); 2236 if (theClassName.endsWith(className)) { 2237 Tools.showError(mainWindow, "Register File Format", 2238 "The file format has already been registered: " + className); 2239 return; 2240 } 2241 } 2242 2243 // Enables use of JHDF5 in JNLP (Web Start) applications, the system 2244 // class loader with reflection first. 2245 Class<?> theClass = null; 2246 try { 2247 theClass = Class.forName(className); 2248 } 2249 catch (Exception ex) { 2250 try { 2251 theClass = ViewProperties.loadExtClass().loadClass(className); 2252 } 2253 catch (Exception ex2) { 2254 theClass = null; 2255 } 2256 } 2257 2258 if (theClass == null) 2259 return; 2260 2261 try { 2262 Object theObject = theClass.newInstance(); 2263 if (theObject instanceof FileFormat) 2264 FileFormat.addFileFormat(key, (FileFormat)theObject); 2265 } 2266 catch (Exception ex) { 2267 Tools.showError(mainWindow, "Register File Format", "Failed to register " + str + "\n\n" + ex); 2268 return; 2269 } 2270 2271 if ((extension != null) && (extension.length() > 0)) { 2272 extension = extension.trim(); 2273 String ext = ViewProperties.getFileExtension(); 2274 ext += ", " + extension; 2275 ViewProperties.setFileExtension(ext); 2276 } 2277 } 2278 2279 private void unregisterFileFormat() 2280 { 2281 Enumeration<?> keys = FileFormat.getFileFormatKeys(); 2282 ArrayList<Object> keyList = new ArrayList<>(); 2283 2284 while (keys.hasMoreElements()) 2285 keyList.add(keys.nextElement()); 2286 2287 String theKey = new UnregisterFileFormatDialog(mainWindow, SWT.NONE, keyList).open(); 2288 2289 if (theKey == null) 2290 return; 2291 2292 FileFormat.removeFileFormat(theKey); 2293 } 2294 2295 private class LibraryVersionDialog extends Dialog { 2296 private String message; 2297 2298 public LibraryVersionDialog(Shell parent, String libType) 2299 { 2300 super(parent, SWT.APPLICATION_MODAL | SWT.DIALOG_TRIM); 2301 2302 if (libType.equals(FileFormat.FILE_TYPE_HDF4)) 2303 setMessage("HDF " + HDF4_VERSION); 2304 else if (libType.equals(FileFormat.FILE_TYPE_HDF5)) 2305 setMessage("HDF5 " + HDF5_VERSION); 2306 } 2307 2308 public void setMessage(String message) { this.message = message; } 2309 2310 public void open() 2311 { 2312 Shell dialog = new Shell(getParent(), getStyle()); 2313 dialog.setFont(currentFont); 2314 dialog.setText("HDF Library Version"); 2315 2316 createContents(dialog); 2317 2318 dialog.pack(); 2319 2320 Point computedSize = dialog.computeSize(SWT.DEFAULT, SWT.DEFAULT); 2321 dialog.setSize(computedSize.x + 50, computedSize.y + 50); 2322 2323 // Center the window relative to the main HDFView window 2324 Point winCenter = new Point(mainWindow.getBounds().x + (mainWindow.getBounds().width / 2), 2325 mainWindow.getBounds().y + (mainWindow.getBounds().height / 2)); 2326 2327 dialog.setLocation(winCenter.x - (dialog.getSize().x / 2), 2328 winCenter.y - (dialog.getSize().y / 2)); 2329 2330 dialog.open(); 2331 2332 Display display = getParent().getDisplay(); 2333 while (!dialog.isDisposed()) { 2334 if (!display.readAndDispatch()) 2335 display.sleep(); 2336 } 2337 } 2338 2339 private void createContents(final Shell shell) 2340 { 2341 shell.setLayout(new GridLayout(2, false)); 2342 2343 Image hdfImage = ViewProperties.getHDFViewIcon(); 2344 2345 Label imageLabel = new Label(shell, SWT.CENTER); 2346 imageLabel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); 2347 imageLabel.setImage(hdfImage); 2348 2349 Label versionLabel = new Label(shell, SWT.CENTER); 2350 versionLabel.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false)); 2351 versionLabel.setFont(currentFont); 2352 versionLabel.setText(message); 2353 2354 // Draw HDF Icon and Version string 2355 Composite buttonComposite = new Composite(shell, SWT.NONE); 2356 buttonComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 2, 1)); 2357 RowLayout buttonLayout = new RowLayout(); 2358 buttonLayout.center = true; 2359 buttonLayout.justify = true; 2360 buttonLayout.type = SWT.HORIZONTAL; 2361 buttonComposite.setLayout(buttonLayout); 2362 2363 Button okButton = new Button(buttonComposite, SWT.PUSH); 2364 okButton.setFont(currentFont); 2365 okButton.setText(" &OK "); 2366 shell.setDefaultButton(okButton); 2367 okButton.addSelectionListener(new SelectionAdapter() { 2368 @Override 2369 public void widgetSelected(SelectionEvent e) 2370 { 2371 shell.dispose(); 2372 } 2373 }); 2374 } 2375 } 2376 2377 private class JavaVersionDialog extends Dialog { 2378 public JavaVersionDialog(Shell parent) { super(parent, SWT.APPLICATION_MODAL | SWT.DIALOG_TRIM); } 2379 2380 public void open() 2381 { 2382 final Shell dialog = new Shell(getParent(), getStyle()); 2383 dialog.setFont(currentFont); 2384 dialog.setText("HDFView Java Version"); 2385 dialog.setLayout(new GridLayout(2, false)); 2386 2387 Image hdfImage = ViewProperties.getHDFViewIcon(); 2388 2389 Label imageLabel = new Label(dialog, SWT.CENTER); 2390 imageLabel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); 2391 imageLabel.setImage(hdfImage); 2392 2393 Label versionLabel = new Label(dialog, SWT.CENTER); 2394 versionLabel.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false)); 2395 versionLabel.setFont(currentFont); 2396 versionLabel.setText(JAVA_VER_INFO); 2397 2398 Composite buttonComposite = new Composite(dialog, SWT.NONE); 2399 buttonComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 2, 1)); 2400 RowLayout buttonLayout = new RowLayout(); 2401 buttonLayout.center = true; 2402 buttonLayout.justify = true; 2403 buttonLayout.type = SWT.HORIZONTAL; 2404 buttonComposite.setLayout(buttonLayout); 2405 2406 Button okButton = new Button(buttonComposite, SWT.PUSH); 2407 okButton.setFont(currentFont); 2408 okButton.setText(" &OK "); 2409 dialog.setDefaultButton(okButton); 2410 okButton.addSelectionListener(new SelectionAdapter() { 2411 @Override 2412 public void widgetSelected(SelectionEvent e) 2413 { 2414 dialog.dispose(); 2415 } 2416 }); 2417 2418 dialog.pack(); 2419 2420 Point computedSize = dialog.computeSize(SWT.DEFAULT, SWT.DEFAULT); 2421 dialog.setSize(computedSize.x + 50, computedSize.y + 50); 2422 2423 // Center the window relative to the main HDFView window 2424 Point winCenter = new Point(mainWindow.getBounds().x + (mainWindow.getBounds().width / 2), 2425 mainWindow.getBounds().y + (mainWindow.getBounds().height / 2)); 2426 2427 dialog.setLocation(winCenter.x - (dialog.getSize().x / 2), 2428 winCenter.y - (dialog.getSize().y / 2)); 2429 2430 dialog.open(); 2431 2432 Display openDisplay = getParent().getDisplay(); 2433 while (!dialog.isDisposed()) { 2434 if (!openDisplay.readAndDispatch()) 2435 openDisplay.sleep(); 2436 } 2437 } 2438 } 2439 2440 private class SupportedFileFormatsDialog extends Dialog { 2441 public SupportedFileFormatsDialog(Shell parent) 2442 { 2443 super(parent, SWT.APPLICATION_MODAL | SWT.DIALOG_TRIM); 2444 } 2445 2446 public void open() 2447 { 2448 final Shell dialog = new Shell(getParent(), getStyle()); 2449 dialog.setFont(currentFont); 2450 dialog.setText("Supported File Formats"); 2451 dialog.setLayout(new GridLayout(2, false)); 2452 2453 Image hdfImage = ViewProperties.getHDFViewIcon(); 2454 2455 Label imageLabel = new Label(dialog, SWT.CENTER); 2456 imageLabel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); 2457 imageLabel.setImage(hdfImage); 2458 2459 Enumeration<?> formatKeys = FileFormat.getFileFormatKeys(); 2460 2461 StringBuilder formats = new StringBuilder("\nSupported File Formats: \n"); 2462 while (formatKeys.hasMoreElements()) 2463 formats.append(" ").append(formatKeys.nextElement()).append("\n"); 2464 formats.append("\n"); 2465 2466 Label formatsLabel = new Label(dialog, SWT.LEFT); 2467 formatsLabel.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false)); 2468 formatsLabel.setFont(currentFont); 2469 formatsLabel.setText(formats.toString()); 2470 2471 Composite buttonComposite = new Composite(dialog, SWT.NONE); 2472 buttonComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 2, 1)); 2473 RowLayout buttonLayout = new RowLayout(); 2474 buttonLayout.center = true; 2475 buttonLayout.justify = true; 2476 buttonLayout.type = SWT.HORIZONTAL; 2477 buttonComposite.setLayout(buttonLayout); 2478 2479 Button okButton = new Button(buttonComposite, SWT.PUSH); 2480 okButton.setFont(currentFont); 2481 okButton.setText(" &OK "); 2482 dialog.setDefaultButton(okButton); 2483 okButton.addSelectionListener(new SelectionAdapter() { 2484 @Override 2485 public void widgetSelected(SelectionEvent e) 2486 { 2487 dialog.dispose(); 2488 } 2489 }); 2490 2491 dialog.pack(); 2492 2493 Point computedSize = dialog.computeSize(SWT.DEFAULT, SWT.DEFAULT); 2494 dialog.setSize(computedSize.x + 50, computedSize.y + 50); 2495 2496 // Center the window relative to the main HDFView window 2497 Point winCenter = new Point(mainWindow.getBounds().x + (mainWindow.getBounds().width / 2), 2498 mainWindow.getBounds().y + (mainWindow.getBounds().height / 2)); 2499 2500 dialog.setLocation(winCenter.x - (dialog.getSize().x / 2), 2501 winCenter.y - (dialog.getSize().y / 2)); 2502 2503 dialog.open(); 2504 2505 Display openDisplay = getParent().getDisplay(); 2506 while (!dialog.isDisposed()) { 2507 if (!openDisplay.readAndDispatch()) 2508 openDisplay.sleep(); 2509 } 2510 } 2511 } 2512 2513 private class AboutDialog extends Dialog { 2514 public AboutDialog(Shell parent) { super(parent, SWT.APPLICATION_MODAL | SWT.DIALOG_TRIM); } 2515 2516 public void open() 2517 { 2518 final Shell dialog = new Shell(getParent(), getStyle()); 2519 dialog.setFont(currentFont); 2520 dialog.setText("About HDFView"); 2521 dialog.setLayout(new GridLayout(2, false)); 2522 2523 Image hdfImage = ViewProperties.getHDFViewIcon(); 2524 2525 Label imageLabel = new Label(dialog, SWT.CENTER); 2526 imageLabel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); 2527 imageLabel.setImage(hdfImage); 2528 2529 Label aboutLabel = new Label(dialog, SWT.LEFT); 2530 aboutLabel.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false)); 2531 aboutLabel.setFont(currentFont); 2532 aboutLabel.setText(ABOUT_HDFVIEW); 2533 2534 Composite buttonComposite = new Composite(dialog, SWT.NONE); 2535 buttonComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 2, 1)); 2536 RowLayout buttonLayout = new RowLayout(); 2537 buttonLayout.center = true; 2538 buttonLayout.justify = true; 2539 buttonLayout.type = SWT.HORIZONTAL; 2540 buttonComposite.setLayout(buttonLayout); 2541 2542 Button okButton = new Button(buttonComposite, SWT.PUSH); 2543 okButton.setFont(currentFont); 2544 okButton.setText(" &OK "); 2545 dialog.setDefaultButton(okButton); 2546 okButton.addSelectionListener(new SelectionAdapter() { 2547 @Override 2548 public void widgetSelected(SelectionEvent e) 2549 { 2550 dialog.dispose(); 2551 } 2552 }); 2553 2554 dialog.pack(); 2555 2556 Point computedSize = dialog.computeSize(SWT.DEFAULT, SWT.DEFAULT); 2557 dialog.setSize(computedSize.x + 50, computedSize.y + 50); 2558 2559 // Center the window relative to the main HDFView window 2560 Point winCenter = new Point(mainWindow.getBounds().x + (mainWindow.getBounds().width / 2), 2561 mainWindow.getBounds().y + (mainWindow.getBounds().height / 2)); 2562 2563 dialog.setLocation(winCenter.x - (dialog.getSize().x / 2), 2564 winCenter.y - (dialog.getSize().y / 2)); 2565 2566 dialog.open(); 2567 2568 Display openDisplay = getParent().getDisplay(); 2569 while (!dialog.isDisposed()) { 2570 if (!openDisplay.readAndDispatch()) 2571 openDisplay.sleep(); 2572 } 2573 } 2574 } 2575 2576 private class UnregisterFileFormatDialog extends Dialog { 2577 private List<Object> keyList; 2578 private String formatChoice = null; 2579 2580 public UnregisterFileFormatDialog(Shell parent, int style, List<Object> keyList) 2581 { 2582 super(parent, style); 2583 2584 this.keyList = keyList; 2585 } 2586 2587 public String open() 2588 { 2589 Shell parent = getParent(); 2590 final Shell shell = new Shell(parent, SWT.APPLICATION_MODAL | SWT.DIALOG_TRIM); 2591 shell.setFont(currentFont); 2592 shell.setText("Unregister a file format"); 2593 shell.setLayout(new GridLayout(2, false)); 2594 2595 Image hdfImage = ViewProperties.getHDFViewIcon(); 2596 2597 Label imageLabel = new Label(shell, SWT.CENTER); 2598 imageLabel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); 2599 imageLabel.setImage(hdfImage); 2600 2601 final Combo formatChoiceCombo = new Combo(shell, SWT.SINGLE | SWT.DROP_DOWN | SWT.READ_ONLY); 2602 formatChoiceCombo.setFont(currentFont); 2603 formatChoiceCombo.setItems(keyList.toArray(new String[0])); 2604 formatChoiceCombo.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, true)); 2605 formatChoiceCombo.select(0); 2606 formatChoiceCombo.addSelectionListener(new SelectionAdapter() { 2607 @Override 2608 public void widgetSelected(SelectionEvent e) 2609 { 2610 formatChoice = formatChoiceCombo.getItem(formatChoiceCombo.getSelectionIndex()); 2611 } 2612 }); 2613 2614 Composite buttonComposite = new Composite(shell, SWT.NONE); 2615 buttonComposite.setLayout(new GridLayout(2, true)); 2616 buttonComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 2, 1)); 2617 2618 Button okButton = new Button(buttonComposite, SWT.PUSH); 2619 okButton.setFont(currentFont); 2620 okButton.setText(" &OK "); 2621 okButton.setLayoutData(new GridData(SWT.END, SWT.FILL, true, false)); 2622 okButton.addSelectionListener(new SelectionAdapter() { 2623 @Override 2624 public void widgetSelected(SelectionEvent e) 2625 { 2626 shell.dispose(); 2627 } 2628 }); 2629 2630 Button cancelButton = new Button(buttonComposite, SWT.PUSH); 2631 cancelButton.setFont(currentFont); 2632 cancelButton.setText(" &Cancel "); 2633 cancelButton.setLayoutData(new GridData(SWT.BEGINNING, SWT.FILL, true, false)); 2634 cancelButton.addSelectionListener(new SelectionAdapter() { 2635 @Override 2636 public void widgetSelected(SelectionEvent e) 2637 { 2638 shell.dispose(); 2639 } 2640 }); 2641 2642 shell.pack(); 2643 2644 Point computedSize = shell.computeSize(SWT.DEFAULT, SWT.DEFAULT); 2645 shell.setSize(computedSize.x + 50, computedSize.y + 50); 2646 2647 Rectangle parentBounds = parent.getBounds(); 2648 Point shellSize = shell.getSize(); 2649 shell.setLocation((parentBounds.x + (parentBounds.width / 2)) - (shellSize.x / 2), 2650 (parentBounds.y + (parentBounds.height / 2)) - (shellSize.y / 2)); 2651 2652 shell.open(); 2653 2654 Display openDisplay = parent.getDisplay(); 2655 while (!shell.isDisposed()) { 2656 if (!openDisplay.readAndDispatch()) 2657 openDisplay.sleep(); 2658 } 2659 2660 return formatChoice; 2661 } 2662 } 2663 2664 /** 2665 * The starting point of this application. 2666 * 2667 * <pre> 2668 * Usage: java(w) 2669 * -Dhdf.hdf5lib.H5.hdf5lib="your HDF5 library path" 2670 * -Dhdf.hdflib.HDFLibrary.hdflib="your HDF4 library path" 2671 * -root "the directory where the HDFView is installed" 2672 * -start "the directory HDFView searches for files" 2673 * -geometry or -g "the preferred window size as WIDTHxHEIGHT+XOFF+YOFF" 2674 * -java.version "show the version of jave used to build the HDFView and exit" 2675 * [filename] "the file to open" 2676 * </pre> 2677 * 2678 * @param args the command line arguments 2679 */ 2680 public static void main(String[] args) 2681 { 2682 if (display == null || display.isDisposed()) 2683 display = new Display(); 2684 2685 String rootDir = System.getProperty("hdfview.root"); 2686 if (rootDir == null) 2687 rootDir = System.getProperty("user.dir"); 2688 String startDir = System.getProperty("user.dir"); 2689 log.trace("main: rootDir = {} startDir = {}", rootDir, startDir); 2690 2691 File tmpFile = null; 2692 Monitor primaryMonitor = display.getPrimaryMonitor(); 2693 Point margin = new Point(primaryMonitor.getBounds().width, primaryMonitor.getBounds().height); 2694 2695 int j = args.length; 2696 int W = margin.x / 2; 2697 int H = margin.y; 2698 int X = 0; 2699 int Y = 0; 2700 2701 for (int i = 0; i < args.length; i++) { 2702 if ("-root".equalsIgnoreCase(args[i])) { 2703 j--; 2704 try { 2705 j--; 2706 tmpFile = new File(args[++i]); 2707 2708 if (tmpFile.isDirectory()) 2709 rootDir = tmpFile.getPath(); 2710 else if (tmpFile.isFile()) 2711 rootDir = tmpFile.getParent(); 2712 } 2713 catch (Exception ex) { 2714 } 2715 } 2716 else if ("-start".equalsIgnoreCase(args[i])) { 2717 j--; 2718 try { 2719 j--; 2720 tmpFile = new File(args[++i]); 2721 2722 if (tmpFile.isDirectory()) 2723 startDir = tmpFile.getPath(); 2724 else if (tmpFile.isFile()) 2725 startDir = tmpFile.getParent(); 2726 } 2727 catch (Exception ex) { 2728 } 2729 } 2730 else if ("-g".equalsIgnoreCase(args[i]) || "-geometry".equalsIgnoreCase(args[i])) { 2731 j--; 2732 // -geometry WIDTHxHEIGHT+XOFF+YOFF 2733 try { 2734 String geom = args[++i]; 2735 j--; 2736 2737 int idx = 0; 2738 int idx2 = geom.lastIndexOf('-'); 2739 int idx3 = geom.lastIndexOf('+'); 2740 2741 idx = Math.max(idx2, idx3); 2742 if (idx > 0) { 2743 Y = Integer.parseInt(geom.substring(idx + 1)); 2744 2745 if (idx == idx2) 2746 Y = -Y; 2747 2748 geom = geom.substring(0, idx); 2749 idx2 = geom.lastIndexOf('-'); 2750 idx3 = geom.lastIndexOf('+'); 2751 idx = Math.max(idx2, idx3); 2752 2753 if (idx > 0) { 2754 X = Integer.parseInt(geom.substring(idx + 1)); 2755 2756 if (idx == idx2) 2757 X = -X; 2758 2759 geom = geom.substring(0, idx); 2760 } 2761 } 2762 2763 idx = geom.indexOf('x'); 2764 2765 if (idx > 0) { 2766 W = Integer.parseInt(geom.substring(0, idx)); 2767 H = Integer.parseInt(geom.substring(idx + 1)); 2768 } 2769 } 2770 catch (Exception ex) { 2771 ex.printStackTrace(); 2772 } 2773 } 2774 else if ("-java.version".equalsIgnoreCase(args[i])) { 2775 /* Set icon to ViewProperties.getLargeHdfIcon() */ 2776 Tools.showInformation(mainWindow, "Java Version", JAVA_VER_INFO); 2777 System.exit(0); 2778 } 2779 } 2780 2781 ArrayList<File> fList = new ArrayList<>(); 2782 2783 if (j >= 0) { 2784 for (int i = args.length - j; i < args.length; i++) { 2785 tmpFile = new File(args[i]); 2786 if (!tmpFile.isAbsolute()) 2787 tmpFile = new File(rootDir, args[i]); 2788 log.trace("main: filelist - file = {} ", tmpFile.getAbsolutePath()); 2789 log.trace("main: filelist - add file = {} exists={} isFile={} isDir={}", tmpFile, 2790 tmpFile.exists(), tmpFile.isFile(), tmpFile.isDirectory()); 2791 if (tmpFile.exists() && (tmpFile.isFile() || tmpFile.isDirectory())) { 2792 log.trace("main: flist - add file = {}", tmpFile.getAbsolutePath()); 2793 fList.add(new File(tmpFile.getAbsolutePath())); 2794 } 2795 } 2796 } 2797 2798 final ArrayList<File> theFileList = fList; 2799 final String the_rootDir = rootDir; 2800 final String the_startDir = startDir; 2801 final int the_X = X, the_Y = Y, the_W = W, the_H = H; 2802 2803 display.syncExec(new Runnable() { 2804 @Override 2805 public void run() 2806 { 2807 HDFView app = new HDFView(the_rootDir, the_startDir); 2808 2809 // TODO: Look for a better solution to native dialog problem 2810 app.setTestState(false); 2811 2812 app.openMainWindow(theFileList, the_W, the_H, the_X, the_Y); 2813 app.runMainWindow(); 2814 } 2815 }); 2816 } 2817}