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