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