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