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