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.HelpView.HelpView; 076import hdf.view.MetaDataView.MetaDataView; 077import hdf.view.TableView.TableView; 078import hdf.view.TreeView.DefaultTreeView; 079import hdf.view.TreeView.TreeView; 080import hdf.view.dialog.ImageConversionDialog; 081import hdf.view.dialog.InputDialog; 082import hdf.view.dialog.UserOptionsDialog; 083import hdf.view.dialog.UserOptionsGeneralPage; 084import hdf.view.dialog.UserOptionsHDFPage; 085import hdf.view.dialog.UserOptionsNode; 086 087 088/** 089 * HDFView is the main class of this HDF visual tool. It is used to layout the 090 * graphical components of the hdfview. The major GUI components of the HDFView 091 * include Menubar, Toolbar, TreeView, ContentView, and MessageArea. 092 * <p> 093 * The HDFView is designed in such a way that it does not have direct access to 094 * the HDF library. All the HDF library access is done through HDF objects. 095 * Therefore, the HDFView package depends on the object package but not the 096 * library package. The source code of the view package (hdf.view) should 097 * be compiled with the library package (hdf.hdflib and hdf.hdf5lib). 098 * 099 * @author Jordan T. Henderson 100 * @version 2.4 //2015 101 */ 102public class HDFView implements ViewManager { 103 104 private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(HDFView.class); 105 106 private static Display display; 107 private static Shell mainWindow; 108 109 /* Determines whether HDFView is being executed for GUI testing */ 110 private boolean isTesting = false; 111 112 /* The directory where HDFView is installed */ 113 private String rootDir; 114 115 /* The current working directory */ 116 private String currentDir; 117 118 /* The current working file */ 119 private String currentFile = null; 120 121 /* The view properties */ 122 private ViewProperties props; 123 124 /* A list of tree view implementations. */ 125 private static List<String> treeViews; 126 127 /* A list of image view implementations. */ 128 private static List<String> imageViews; 129 130 /* A list of tree table implementations. */ 131 private static List<?> tableViews; 132 133 /* A list of metadata view implementations. */ 134 private static List<?> metaDataViews; 135 136 /* A list of palette view implementations. */ 137 private static List<?> paletteViews; 138 139 /* A list of help view implementations. */ 140 private static List<?> helpViews; 141 142 /* The list of GUI components related to HDF4 */ 143 private final List<MenuItem> h4GUIs = new Vector<>(); 144 145 /* The list of GUI components related to HDF5 */ 146 private final List<MenuItem> h5GUIs = new Vector<>(); 147 148 /* The list of GUI components related to editing */ 149 //private final List<?> editGUIs; 150 151 /* GUI component: the TreeView */ 152 private TreeView treeView = null; 153 154 private static final String HDF4_VERSION = HDFVersions.HDF4_VERSION; 155 private static final String HDF5_VERSION = HDFVersions.HDF5_VERSION; 156 private static final String HDFVIEW_VERSION = HDFVersions.HDFVIEW_VERSION; 157 private static final String HDFVIEW_USERSGUIDE_URL = "https://support.hdfgroup.org/products/java/hdfview/index.html"; 158 private static final String JAVA_COMPILER = "jdk 1.7"; 159 private static final String JAVA_VER_INFO = "Compiled at " + JAVA_COMPILER + "\nRunning at " + System.getProperty("java.version"); 160 161 private static final String aboutHDFView = "HDF Viewer, " + "Version " + ViewProperties.VERSION + "\n" 162 + "For " + System.getProperty("os.name") + "\n\n" 163 + "Copyright " + '\u00a9' + " 2006-2017 The HDF Group.\n" 164 + "All rights reserved."; 165 166 /* GUI component: The toolbar for open, close, help and hdf4 and hdf5 library information */ 167 private ToolBar toolBar; 168 169 /* GUI component: The text area for showing status messages */ 170 private Text status; 171 172 /* GUI component: The area for quick general view */ 173 private ScrolledComposite generalArea; 174 175 /* GUI component: To add and display URLs */ 176 private Combo url_bar; 177 178 private Button recentFilesButton; 179 private Button clearTextButton; 180 181 /* GUI component: A list of current data windows */ 182 private Menu windowMenu; 183 184 /* GUI component: File menu on the menubar */ 185 //private final Menu fileMenu; 186 187 /* The font to be used for display text on all Controls */ 188 private Font currentFont; 189 190 private UserOptionsDialog userOptionDialog; 191 192 /** 193 * Constructs HDFView with a given root directory, where the HDFView is 194 * installed, and opens the given files in the viewer. 195 * 196 * @param root 197 * the directory where the HDFView is installed. 198 */ 199 public HDFView(String root) { 200 log.debug("Root is {}", root); 201 202 if (display == null || display.isDisposed()) display = new Display(); 203 204 rootDir = root; 205 206 //editGUIs = new Vector<Object>(); 207 208 props = new ViewProperties(rootDir); 209 try { 210 props.load(); 211 } 212 catch (Exception ex) { 213 log.debug("Failed to load View Properties from {}", rootDir); 214 } 215 216 ViewProperties.loadIcons(); 217 218 currentDir = ViewProperties.getWorkDir(); 219 if (currentDir == null) currentDir = System.getProperty("user.home"); 220 221 log.info("Current directory is {}", currentDir); 222 223 try { 224 currentFont = new Font( 225 display, 226 ViewProperties.getFontType(), 227 ViewProperties.getFontSize(), 228 SWT.NORMAL); 229 } 230 catch (Exception ex) { 231 currentFont = null; 232 } 233 234 treeViews = ViewProperties.getTreeViewList(); 235 metaDataViews = ViewProperties.getMetaDataViewList(); 236 tableViews = ViewProperties.getTableViewList(); 237 imageViews = ViewProperties.getImageViewList(); 238 paletteViews = ViewProperties.getPaletteViewList(); 239 helpViews = ViewProperties.getHelpViewList(); 240 241 log.debug("Constructor exit"); 242 } 243 244 245 /** 246 * Creates HDFView with a given size, and opens the given files in the viewer. 247 * 248 * @param flist 249 * a list of files to open. 250 * @param width 251 * the width of the app in pixels 252 * @param height 253 * the height of the app in pixels 254 * @param x 255 * the coord x of the app in pixels 256 * @param y 257 * the coord y of the app in pixels 258 * 259 * @return 260 * the newly-created HDFView Shell 261 */ 262 public Shell openMainWindow(List<File> flist, int width, int height, int x, int y) { 263 log.debug("openMainWindow enter"); 264 265 // Initialize all GUI components 266 mainWindow = createMainWindow(); 267 268 try { 269 Font font = null; 270 String fType = ViewProperties.getFontType(); 271 int fSize = ViewProperties.getFontSize(); 272 273 try { 274 font = new Font(display, fType, fSize, SWT.NORMAL); 275 } 276 catch (Exception ex) { 277 font = null; 278 } 279 280 if (font != null) 281 updateFont(font); 282 } 283 catch (Exception ex) { 284 log.debug("Failed to load Font properties"); 285 } 286 287 // Make sure all GUI components are in place before 288 // opening any files 289 mainWindow.pack(); 290 291 int nfiles = flist.size(); 292 File theFile = null; 293 for (int i = 0; i < nfiles; i++) { 294 theFile = flist.get(i); 295 296 if (theFile.isFile()) { 297 currentDir = theFile.getParentFile().getAbsolutePath(); 298 currentFile = theFile.getAbsolutePath(); 299 300 try { 301 treeView.openFile(currentFile, FileFormat.WRITE); 302 303 try { 304 url_bar.remove(currentFile); 305 } 306 catch (Exception ex) {} 307 308 url_bar.add(currentFile, 0); 309 url_bar.select(0); 310 } 311 catch (Exception ex) { 312 showStatus(ex.toString()); 313 } 314 } 315 else { 316 currentDir = theFile.getAbsolutePath(); 317 } 318 319 log.info("CurrentDir is {}", currentDir); 320 } 321 322 if (FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF4) == null) 323 setEnabled(h4GUIs, false); 324 325 if (FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF5) == null) 326 setEnabled(h5GUIs, false); 327 328 // Set size of main window 329 // float inset = 0.17f; // for UG only. 330 float inset = 0.04f; 331 Point winDim = new Point(width, height); 332 333 // If given height and width are too small, adjust accordingly 334 if (height <= 300) { 335 winDim.y = (int) ((1 - 2 * inset) * mainWindow.getSize().y); 336 } 337 338 if (width <= 300) { 339 winDim.x = (int) (0.9 * mainWindow.getSize().y); 340 } 341 342 mainWindow.setLocation(x, y); 343 mainWindow.setSize(winDim.x + 200, winDim.y); 344 345 // Display the window 346 mainWindow.open(); 347 log.debug("openMainWindow exit"); 348 return mainWindow; 349 } 350 351 public void runMainWindow() { 352 log.debug("runMainWindow enter"); 353 354 while(!mainWindow.isDisposed()) { 355 // =================================================== 356 // Wrap each event dispatch in an exception handler 357 // so that if any event causes an exception it does 358 // not break the main UI loop 359 // =================================================== 360 try { 361 if (!display.readAndDispatch()) { 362 display.sleep(); 363 } 364 } 365 catch (Exception e) { 366 e.printStackTrace(); 367 } 368 } 369 370 if (!isTesting) display.dispose(); 371 log.debug("runMainWindow exit"); 372 } 373 374 /** 375 * Creates and lays out GUI components. 376 * 377 * <pre> 378 * ||=========||=============================|| 379 * || || || 380 * || || || 381 * || TreeView|| ContentPane || 382 * || || || 383 * ||=========||=============================|| 384 * || Message Area || 385 * ||========================================|| 386 * </pre> 387 */ 388 private Shell createMainWindow() { 389 // Create a new display window 390 final Shell shell = new Shell(display); 391 shell.setImage(ViewProperties.getHdfIcon()); 392 shell.setFont(currentFont); 393 shell.setText("HDFView " + HDFVIEW_VERSION); 394 shell.setLayout(new GridLayout(3, false)); 395 shell.addDisposeListener(new DisposeListener() { 396 @Override 397 public void widgetDisposed(DisposeEvent e) { 398 ViewProperties.setRecentFiles(new Vector<>(Arrays.asList(url_bar.getItems()))); 399 400 try { 401 props.save(); 402 } 403 catch (Exception ex) {} 404 405 closeAllWindows(); 406 407 // Close all open files 408 try { 409 List<FileFormat> filelist = treeView.getCurrentFiles(); 410 411 if((filelist != null) && (filelist.size() > 0)) { 412 Object[] files = filelist.toArray(); 413 414 for (int i = 0; i < files.length; i++) { 415 try { 416 treeView.closeFile((FileFormat) files[i]); 417 } 418 catch (Throwable ex) { 419 continue; 420 } 421 } 422 } 423 } 424 catch (Exception ex) {} 425 426 if (currentFont != null) currentFont.dispose(); 427 } 428 }); 429 430 createMenuBar(shell); 431 createToolbar(shell); 432 createUrlToolbar(shell); 433 createContentArea(shell); 434 435 log.info("Main Window created"); 436 437 return shell; 438 } 439 440 private void createMenuBar(final Shell shell) { 441 Menu menu = new Menu(shell, SWT.BAR); 442 shell.setMenuBar(menu); 443 444 MenuItem menuItem = new MenuItem(menu, SWT.CASCADE); 445 menuItem.setText("&File"); 446 447 Menu fileMenu = new Menu(menuItem); 448 menuItem.setMenu(fileMenu); 449 450 MenuItem item = new MenuItem(fileMenu, SWT.PUSH); 451 item.setText("&Open\tCtrl-O"); 452 item.setAccelerator(SWT.MOD1 + 'O'); 453 item.addSelectionListener(new SelectionAdapter() { 454 @Override 455 public void widgetSelected(SelectionEvent e) { 456 openLocalFile(null, -1); 457 } 458 }); 459 460 item = new MenuItem(fileMenu, SWT.CASCADE); 461 item.setText("Open As"); 462 463 Menu openAsMenu = new Menu(item); 464 item.setMenu(openAsMenu); 465 466 item = new MenuItem(openAsMenu, SWT.PUSH); 467 item.setText("Read-Only"); 468 item.addSelectionListener(new SelectionAdapter() { 469 @Override 470 public void widgetSelected(SelectionEvent e) { 471 openLocalFile(null, FileFormat.READ); 472 } 473 }); 474 475 item = new MenuItem(openAsMenu, SWT.PUSH); 476 item.setText("Read/Write"); 477 item.addSelectionListener(new SelectionAdapter() { 478 @Override 479 public void widgetSelected(SelectionEvent e) { 480 openLocalFile(null, FileFormat.WRITE); 481 } 482 }); 483 484 new MenuItem(fileMenu, SWT.SEPARATOR); 485 486 MenuItem fileNewMenu = new MenuItem(fileMenu, SWT.CASCADE); 487 fileNewMenu.setText("New"); 488 489 Menu newMenu = new Menu(fileNewMenu); 490 fileNewMenu.setMenu(newMenu); 491 492 item = new MenuItem(newMenu, SWT.PUSH); 493 item.setText("HDF&4"); 494 h4GUIs.add(item); 495 item.addSelectionListener(new SelectionAdapter() { 496 @Override 497 public void widgetSelected(SelectionEvent e) { 498 if (currentDir != null) { 499 currentDir += File.separator; 500 } 501 else { 502 currentDir = ""; 503 } 504 505 String filename = null; 506 507 if (!isTesting) { 508 FileDialog fChooser = new FileDialog(shell, SWT.SAVE); 509 fChooser.setFileName(Tools.checkNewFile(currentDir, ".hdf").getName()); 510 511 DefaultFileFilter filter = DefaultFileFilter.getFileFilterHDF4(); 512 fChooser.setFilterExtensions(new String[] {filter.getExtensions()}); 513 fChooser.setFilterNames(new String[] {filter.getDescription()}); 514 fChooser.setFilterIndex(0); 515 516 filename = fChooser.open(); 517 } 518 else { 519 // Prepend test file directory to filename 520 filename = currentDir.concat(new InputDialog(mainWindow, "Enter a file name", "").open()); 521 } 522 523 if(filename == null) return; 524 525 try { 526 log.trace("HDFView create hdf4 file"); 527 FileFormat theFile = Tools.createNewFile(filename, currentDir, 528 FileFormat.FILE_TYPE_HDF4, getTreeView().getCurrentFiles()); 529 530 if (theFile == null) return; 531 532 currentDir = theFile.getParent(); 533 } 534 catch (Exception ex) { 535 Tools.showError(mainWindow, "New", ex.getMessage()); 536 return; 537 } 538 539 try { 540 treeView.openFile(filename, FileFormat.WRITE); 541 currentFile = filename; 542 543 try { 544 url_bar.remove(filename); 545 } 546 catch (Exception ex) {} 547 548 url_bar.add(filename, 0); 549 url_bar.select(0); 550 } 551 catch (Exception ex) { 552 display.beep(); 553 Tools.showError(mainWindow, "New", ex.getMessage() + "\n" + filename); 554 } 555 } 556 }); 557 558 item = new MenuItem(newMenu, SWT.PUSH); 559 item.setText("HDF&5"); 560 h5GUIs.add(item); 561 item.addSelectionListener(new SelectionAdapter() { 562 @Override 563 public void widgetSelected(SelectionEvent e) { 564 if (currentDir != null) { 565 currentDir += File.separator; 566 } 567 else { 568 currentDir = ""; 569 } 570 571 String filename = null; 572 573 if (!isTesting) { 574 FileDialog fChooser = new FileDialog(shell, SWT.SAVE); 575 fChooser.setFileName(Tools.checkNewFile(currentDir, ".h5").getName()); 576 577 DefaultFileFilter filter = DefaultFileFilter.getFileFilterHDF5(); 578 fChooser.setFilterExtensions(new String[] {filter.getExtensions()}); 579 fChooser.setFilterNames(new String[] {filter.getDescription()}); 580 fChooser.setFilterIndex(0); 581 582 filename = fChooser.open(); 583 } 584 else { 585 // Prepend test file directory to filename 586 filename = currentDir.concat(new InputDialog(mainWindow, "Enter a file name", "").open()); 587 } 588 589 if(filename == null) return; 590 591 try { 592 log.trace("HDFView create hdf5 file"); 593 FileFormat theFile = Tools.createNewFile(filename, currentDir, 594 FileFormat.FILE_TYPE_HDF5, getTreeView().getCurrentFiles()); 595 596 if (theFile == null) return; 597 598 currentDir = theFile.getParent(); 599 } 600 catch (Exception ex) { 601 Tools.showError(mainWindow, "New", ex.getMessage()); 602 return; 603 } 604 605 try { 606 treeView.openFile(filename, FileFormat.WRITE); 607 currentFile = filename; 608 609 try { 610 url_bar.remove(filename); 611 } 612 catch (Exception ex) {} 613 614 url_bar.add(filename, 0); 615 url_bar.select(0); 616 } 617 catch (Exception ex) { 618 display.beep(); 619 Tools.showError(mainWindow, "New", ex.getMessage() + "\n" + filename); 620 } 621 } 622 }); 623 624 new MenuItem(fileMenu, SWT.SEPARATOR); 625 626 item = new MenuItem(fileMenu, SWT.PUSH); 627 item.setText("&Close"); 628 item.addSelectionListener(new SelectionAdapter() { 629 @Override 630 public void widgetSelected(SelectionEvent e) { 631 closeFile(treeView.getSelectedFile()); 632 } 633 }); 634 635 item = new MenuItem(fileMenu, SWT.PUSH); 636 item.setText("Close &All"); 637 item.addSelectionListener(new SelectionAdapter() { 638 @Override 639 public void widgetSelected(SelectionEvent e) { 640 closeAllWindows(); 641 642 List<FileFormat> files = treeView.getCurrentFiles(); 643 while (!files.isEmpty()) { 644 try { 645 treeView.closeFile(files.get(0)); 646 } 647 catch (Exception ex) {} 648 } 649 650 currentFile = null; 651 652 for (Control control : generalArea.getChildren()) control.dispose(); 653 generalArea.setContent(null); 654 655 url_bar.setText(""); 656 } 657 }); 658 659 new MenuItem(fileMenu, SWT.SEPARATOR); 660 661 item = new MenuItem(fileMenu, SWT.PUSH); 662 item.setText("&Save"); 663 item.addSelectionListener(new SelectionAdapter() { 664 @Override 665 public void widgetSelected(SelectionEvent e) { 666 if (treeView.getCurrentFiles().size() <= 0) { 667 Tools.showError(mainWindow, "Save", "No files currently open."); 668 return; 669 } 670 671 if (treeView.getSelectedFile() == null) { 672 Tools.showError(mainWindow, "Save", "No files currently selected."); 673 return; 674 } 675 676 // Save what has been changed in memory into file 677 writeDataToFile(treeView.getSelectedFile()); 678 } 679 }); 680 681 item = new MenuItem(fileMenu, SWT.PUSH); 682 item.setText("S&ave As"); 683 item.addSelectionListener(new SelectionAdapter() { 684 @Override 685 public void widgetSelected(SelectionEvent e) { 686 if (treeView.getCurrentFiles().size() <= 0) { 687 Tools.showError(mainWindow, "Save", "No files currently open."); 688 return; 689 } 690 691 if (treeView.getSelectedFile() == null) { 692 Tools.showError(mainWindow, "Save", "No files currently selected."); 693 return; 694 } 695 696 try { 697 treeView.saveFile(treeView.getSelectedFile()); 698 } 699 catch (Exception ex) { 700 display.beep(); 701 Tools.showError(mainWindow, "Save", ex.getMessage()); 702 } 703 } 704 }); 705 706 new MenuItem(fileMenu, SWT.SEPARATOR); 707 708 item = new MenuItem(fileMenu, SWT.PUSH); 709 item.setText("E&xit\tCtrl-Q"); 710 item.setAccelerator(SWT.MOD1 + 'Q'); 711 item.addSelectionListener(new SelectionAdapter() { 712 @Override 713 public void widgetSelected(SelectionEvent e) { 714 mainWindow.dispose(); 715 } 716 }); 717 718 menuItem = new MenuItem(menu, SWT.CASCADE); 719 menuItem.setText("&Window"); 720 721 windowMenu = new Menu(menuItem); 722 menuItem.setMenu(windowMenu); 723 724 item = new MenuItem(windowMenu, SWT.PUSH); 725 item.setText("&Cascade"); 726 item.addSelectionListener(new SelectionAdapter() { 727 @Override 728 public void widgetSelected(SelectionEvent e) { 729 cascadeWindows(); 730 } 731 }); 732 733 item = new MenuItem(windowMenu, SWT.PUSH); 734 item.setText("&Tile"); 735 item.addSelectionListener(new SelectionAdapter() { 736 @Override 737 public void widgetSelected(SelectionEvent e) { 738 tileWindows(); 739 } 740 }); 741 742 new MenuItem(windowMenu, SWT.SEPARATOR); 743 744 item = new MenuItem(windowMenu, SWT.PUSH); 745 item.setText("Close &All"); 746 item.addSelectionListener(new SelectionAdapter() { 747 @Override 748 public void widgetSelected(SelectionEvent e) { 749 closeAllWindows(); 750 } 751 }); 752 753 new MenuItem(windowMenu, SWT.SEPARATOR); 754 755 menuItem = new MenuItem(menu, SWT.CASCADE); 756 menuItem.setText("&Tools"); 757 758 Menu toolsMenu = new Menu(menuItem); 759 menuItem.setMenu(toolsMenu); 760 761 MenuItem convertMenuItem = new MenuItem(toolsMenu, SWT.CASCADE); 762 convertMenuItem.setText("Convert Image To"); 763 764 Menu convertMenu = new Menu(convertMenuItem); 765 convertMenuItem.setMenu(convertMenu); 766 767 item = new MenuItem(convertMenu, SWT.PUSH); 768 item.setText("HDF4"); 769 item.addSelectionListener(new SelectionAdapter() { 770 @Override 771 public void widgetSelected(SelectionEvent e) { 772 convertFile(Tools.FILE_TYPE_IMAGE, FileFormat.FILE_TYPE_HDF4); 773 } 774 }); 775 h4GUIs.add(item); 776 777 item = new MenuItem(convertMenu, SWT.PUSH); 778 item.setText("HDF5"); 779 item.addSelectionListener(new SelectionAdapter() { 780 @Override 781 public void widgetSelected(SelectionEvent e) { 782 convertFile(Tools.FILE_TYPE_IMAGE, FileFormat.FILE_TYPE_HDF5); 783 } 784 }); 785 h5GUIs.add(item); 786 787 new MenuItem(toolsMenu, SWT.SEPARATOR); 788 789 item = new MenuItem(toolsMenu, SWT.PUSH); 790 item.setText("User &Options"); 791 item.addSelectionListener(new SelectionAdapter() { 792 @Override 793 public void widgetSelected(SelectionEvent e) { 794 // Create the preference manager 795 PreferenceManager mgr = new PreferenceManager(); 796 797 // Create the nodes 798 UserOptionsNode one = new UserOptionsNode("general", new UserOptionsGeneralPage()); 799 UserOptionsNode two = new UserOptionsNode("hdf", new UserOptionsHDFPage()); 800 801 /* 802 * TODO: Disabled until module loading is supported 803 */ 804 /* 805 * UserOptionsNode three = new UserOptionsNode("modules", new UserOptionsViewModulesPage()); 806 */ 807 808 // Add the nodes 809 mgr.addToRoot(one); 810 mgr.addToRoot(two); 811 812 /* 813 * TODO: Disabled until module loading is supported 814 */ 815 /* mgr.addToRoot(three); */ 816 817 // Create the preferences dialog 818 userOptionDialog = new UserOptionsDialog(shell, mgr, rootDir); 819 820 // Set the preference store 821 userOptionDialog.setPreferenceStore(props); 822 userOptionDialog.create(); 823 824 // Open the dialog 825 userOptionDialog.open(); 826 827 //if (userOptionDialog.isWorkDirChanged()) 828 currentDir = ViewProperties.getWorkDir(); 829 830 //if (userOptionDialog.isFontChanged()) { 831 Font font = null; 832 833 try { 834 font = new Font(display, ViewProperties.getFontType(), ViewProperties.getFontSize(), SWT.NORMAL); 835 } 836 catch (Exception ex) { 837 font = null; 838 } 839 840 updateFont(font); 841 //} 842 } 843 }); 844 845 new MenuItem(toolsMenu, SWT.SEPARATOR); 846 847 item = new MenuItem(toolsMenu, SWT.PUSH); 848 item.setText("&Register File Format"); 849 item.addSelectionListener(new SelectionAdapter() { 850 @Override 851 public void widgetSelected(SelectionEvent e) { 852 registerFileFormat(); 853 } 854 }); 855 856 item = new MenuItem(toolsMenu, SWT.PUSH); 857 item.setText("&Unregister File Format"); 858 item.addSelectionListener(new SelectionAdapter() { 859 @Override 860 public void widgetSelected(SelectionEvent e) { 861 unregisterFileFormat(); 862 } 863 }); 864 865 menuItem = new MenuItem(menu, SWT.CASCADE); 866 menuItem.setText("&Help"); 867 868 Menu helpMenu = new Menu(menuItem); 869 menuItem.setMenu(helpMenu); 870 871 item = new MenuItem(helpMenu, SWT.PUSH); 872 item.setText("&User's Guide"); 873 item.addSelectionListener(new SelectionAdapter() { 874 @Override 875 public void widgetSelected(SelectionEvent e) { 876 org.eclipse.swt.program.Program.launch(HDFVIEW_USERSGUIDE_URL); 877 } 878 }); 879 880 if ((helpViews != null) && (helpViews.size() > 0)) { 881 int n = helpViews.size(); 882 for (int i = 0; i < n; i++) { 883 HelpView theView = (HelpView) helpViews.get(i); 884 item = new MenuItem(helpMenu, SWT.PUSH); 885 item.setText(theView.getLabel()); 886 //item.setActionCommand(theView.getActionCommand()); 887 } 888 } 889 890 new MenuItem(helpMenu, SWT.SEPARATOR); 891 892 item = new MenuItem(helpMenu, SWT.PUSH); 893 item.setText("HDF&4 Library Version"); 894 h4GUIs.add(item); 895 item.addSelectionListener(new SelectionAdapter() { 896 @Override 897 public void widgetSelected(SelectionEvent e) { 898 new LibraryVersionDialog(shell, FileFormat.FILE_TYPE_HDF4).open(); 899 } 900 }); 901 902 item = new MenuItem(helpMenu, SWT.PUSH); 903 item.setText("HDF&5 Library Version"); 904 h5GUIs.add(item); 905 item.addSelectionListener(new SelectionAdapter() { 906 @Override 907 public void widgetSelected(SelectionEvent e) { 908 new LibraryVersionDialog(shell, FileFormat.FILE_TYPE_HDF5).open(); 909 } 910 }); 911 912 item = new MenuItem(helpMenu, SWT.PUSH); 913 item.setText("&Java Version"); 914 item.addSelectionListener(new SelectionAdapter() { 915 @Override 916 public void widgetSelected(SelectionEvent e) { 917 new JavaVersionDialog(mainWindow).open(); 918 } 919 }); 920 921 new MenuItem(helpMenu, SWT.SEPARATOR); 922 923 item = new MenuItem(helpMenu, SWT.PUSH); 924 item.setText("Supported Fi&le Formats"); 925 item.addSelectionListener(new SelectionAdapter() { 926 @Override 927 public void widgetSelected(SelectionEvent e) { 928 new SupportedFileFormatsDialog(mainWindow).open(); 929 } 930 }); 931 932 new MenuItem(helpMenu, SWT.SEPARATOR); 933 934 item = new MenuItem(helpMenu, SWT.PUSH); 935 item.setText("&About..."); 936 item.addSelectionListener(new SelectionAdapter() { 937 @Override 938 public void widgetSelected(SelectionEvent e) { 939 new AboutDialog(mainWindow).open(); 940 } 941 }); 942 943 setEnabled(Arrays.asList(windowMenu.getItems()), false); 944 945 log.info("Menubar created"); 946 } 947 948 private void createToolbar(final Shell shell) { 949 toolBar = new ToolBar(shell, SWT.HORIZONTAL | SWT.RIGHT); 950 toolBar.setFont(Display.getCurrent().getSystemFont()); 951 toolBar.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 3, 1)); 952 953 ToolItem openItem = new ToolItem(toolBar, SWT.PUSH); 954 openItem.setToolTipText("Open"); 955 openItem.setImage(ViewProperties.getFileopenIcon()); 956 openItem.addSelectionListener(new SelectionAdapter() { 957 @Override 958 public void widgetSelected(SelectionEvent e) { 959 openLocalFile(null, -1); 960 } 961 }); 962 963 new ToolItem(toolBar, SWT.SEPARATOR).setWidth(4); 964 965 ToolItem closeItem = new ToolItem(toolBar, SWT.PUSH); 966 closeItem.setImage(ViewProperties.getFilecloseIcon()); 967 closeItem.setToolTipText("Close"); 968 closeItem.addSelectionListener(new SelectionAdapter() { 969 @Override 970 public void widgetSelected(SelectionEvent e) { 971 closeFile(treeView.getSelectedFile()); 972 } 973 }); 974 975 new ToolItem(toolBar, SWT.SEPARATOR).setWidth(20); 976 977 ToolItem helpItem = new ToolItem(toolBar, SWT.PUSH); 978 helpItem.setImage(ViewProperties.getHelpIcon()); 979 helpItem.setToolTipText("Help"); 980 helpItem.addSelectionListener(new SelectionAdapter() { 981 @Override 982 public void widgetSelected(SelectionEvent e) { 983 String ugPath = ViewProperties.getUsersGuide(); 984 985 if(ugPath == null || !ugPath.startsWith("http://")) { 986 String sep = File.separator; 987 File tmpFile = new File(ugPath); 988 989 if(!(tmpFile.exists())) { 990 ugPath = rootDir + sep + "UsersGuide" + sep + "index.html"; 991 tmpFile = new File(ugPath); 992 993 if(!(tmpFile.exists())) { 994 ugPath = HDFVIEW_USERSGUIDE_URL; 995 } 996 997 ViewProperties.setUsersGuide(ugPath); 998 } 999 } 1000 1001 try { 1002 org.eclipse.swt.program.Program.launch(ugPath); 1003 } 1004 catch (Exception ex) { 1005 Tools.showError(shell, "Help", ex.getMessage()); 1006 } 1007 } 1008 }); 1009 1010 new ToolItem(toolBar, SWT.SEPARATOR).setWidth(4); 1011 1012 ToolItem hdf4Item = new ToolItem(toolBar, SWT.PUSH); 1013 hdf4Item.setImage(ViewProperties.getH4Icon()); 1014 hdf4Item.setToolTipText("HDF4 Library Version"); 1015 hdf4Item.addSelectionListener(new SelectionAdapter() { 1016 @Override 1017 public void widgetSelected(SelectionEvent e) { 1018 new LibraryVersionDialog(shell, FileFormat.FILE_TYPE_HDF4).open(); 1019 } 1020 }); 1021 1022 if(FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF4) == null) { 1023 hdf4Item.setEnabled(false); 1024 } 1025 1026 new ToolItem(toolBar, SWT.SEPARATOR).setWidth(4); 1027 1028 ToolItem hdf5Item = new ToolItem(toolBar, SWT.PUSH); 1029 hdf5Item.setImage(ViewProperties.getH5Icon()); 1030 hdf5Item.setToolTipText("HDF5 Library Version"); 1031 hdf5Item.addSelectionListener(new SelectionAdapter() { 1032 @Override 1033 public void widgetSelected(SelectionEvent e) { 1034 new LibraryVersionDialog(shell, FileFormat.FILE_TYPE_HDF5).open(); 1035 } 1036 }); 1037 1038 if(FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF5) == null) { 1039 hdf5Item.setEnabled(false); 1040 } 1041 1042 // Make the toolbar as wide as the window and as 1043 // tall as the buttons 1044 toolBar.setSize(shell.getClientArea().width, openItem.getBounds().height); 1045 toolBar.setLocation(0, 0); 1046 1047 log.info("Toolbar created"); 1048 } 1049 1050 private void createUrlToolbar(final Shell shell) { 1051 // Recent Files button 1052 recentFilesButton = new Button(shell, SWT.PUSH); 1053 recentFilesButton.setFont(currentFont); 1054 recentFilesButton.setText("Recent Files"); 1055 recentFilesButton.setToolTipText("List of recent files"); 1056 recentFilesButton.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false)); 1057 recentFilesButton.addSelectionListener(new SelectionAdapter() { 1058 @Override 1059 public void widgetSelected(SelectionEvent e) { 1060 url_bar.setListVisible(true); 1061 } 1062 }); 1063 1064 // Recent files combo box 1065 url_bar = new Combo(shell, SWT.BORDER | SWT.SINGLE); 1066 url_bar.setFont(currentFont); 1067 url_bar.setItems(ViewProperties.getMRF().toArray(new String[0])); 1068 url_bar.setVisibleItemCount(ViewProperties.MAX_RECENT_FILES); 1069 url_bar.deselectAll(); 1070 url_bar.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); 1071 url_bar.addKeyListener(new KeyAdapter() { 1072 @Override 1073 public void keyPressed(KeyEvent e) { 1074 if(e.keyCode == SWT.CR) { 1075 String filename = url_bar.getText(); 1076 if (filename == null || filename.length() < 1 || filename.equals(currentFile)) { 1077 return; 1078 } 1079 1080 if (!(filename.startsWith("http://") || filename.startsWith("https://") || filename.startsWith("ftp://"))) { 1081 openLocalFile(filename, -1); 1082 } 1083 else { 1084 String remoteFile = openRemoteFile(filename); 1085 1086 if (remoteFile != null) openLocalFile(remoteFile, -1); 1087 } 1088 } 1089 } 1090 }); 1091 url_bar.addSelectionListener(new SelectionAdapter() { 1092 @Override 1093 public void widgetSelected(SelectionEvent e) { 1094 String filename = url_bar.getText(); 1095 if (filename == null || filename.length() < 1 || filename.equals(currentFile)) { 1096 return; 1097 } 1098 1099 if (!(filename.startsWith("http://") || filename.startsWith("https://") || filename.startsWith("ftp://"))) { 1100 openLocalFile(filename, -1); 1101 } 1102 else { 1103 String remoteFile = openRemoteFile(filename); 1104 1105 if (remoteFile != null) openLocalFile(remoteFile, -1); 1106 } 1107 } 1108 }); 1109 1110 clearTextButton = new Button(shell, SWT.PUSH); 1111 clearTextButton.setToolTipText("Clear current selection"); 1112 clearTextButton.setFont(currentFont); 1113 clearTextButton.setText("Clear Text"); 1114 clearTextButton.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false)); 1115 clearTextButton.addSelectionListener(new SelectionAdapter() { 1116 @Override 1117 public void widgetSelected(SelectionEvent e) { 1118 url_bar.setText(""); 1119 url_bar.deselectAll(); 1120 } 1121 }); 1122 1123 log.info("URL Toolbar created"); 1124 } 1125 1126 private void createContentArea(final Shell shell) { 1127 SashForm content = new SashForm(shell, SWT.VERTICAL); 1128 content.setSashWidth(10); 1129 content.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 3, 1)); 1130 1131 // Add Data content area and Status Area to main window 1132 Composite container = new Composite(content, SWT.NONE); 1133 container.setLayout(new FillLayout()); 1134 1135 Composite statusArea = new Composite(content, SWT.NONE); 1136 statusArea.setLayout(new FillLayout(SWT.HORIZONTAL)); 1137 1138 final SashForm contentArea = new SashForm(container, SWT.HORIZONTAL); 1139 contentArea.setSashWidth(10); 1140 1141 // Add TreeView and DataView to content area pane 1142 ScrolledComposite treeArea = new ScrolledComposite(contentArea, SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER); 1143 treeArea.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_WHITE)); 1144 treeArea.setExpandHorizontal(true); 1145 treeArea.setExpandVertical(true); 1146 1147 generalArea = new ScrolledComposite(contentArea, SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER); 1148 generalArea.setExpandHorizontal(true); 1149 generalArea.setExpandVertical(true); 1150 generalArea.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_WIDGET_LIGHT_SHADOW)); 1151 generalArea.setMinHeight(contentArea.getSize().y - 2); 1152 1153 // Create status area for displaying messages and metadata 1154 status = new Text(statusArea, SWT.V_SCROLL | SWT.MULTI | SWT.BORDER); 1155 status.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_WIDGET_LIGHT_SHADOW)); 1156 status.setEditable(false); 1157 status.setFont(currentFont); 1158 1159 contentArea.addListener(SWT.Resize, new Listener() { 1160 @Override 1161 public void handleEvent(Event arg0) { 1162 generalArea.setMinHeight(contentArea.getSize().y - 2); 1163 } 1164 }); 1165 1166 // Add drag and drop support for opening files 1167 DropTarget target = new DropTarget(treeArea, DND.DROP_COPY); 1168 final FileTransfer fileTransfer = FileTransfer.getInstance(); 1169 target.setTransfer(new Transfer[] { fileTransfer }); 1170 target.addDropListener(new DropTargetListener() { 1171 @Override 1172 public void dragEnter(DropTargetEvent e) { 1173 e.detail = DND.DROP_COPY; 1174 } 1175 @Override 1176 public void dragOver(DropTargetEvent e) {} 1177 @Override 1178 public void dragOperationChanged(DropTargetEvent e) { } 1179 @Override 1180 public void dragLeave(DropTargetEvent e) {} 1181 @Override 1182 public void dropAccept(DropTargetEvent e) {} 1183 @Override 1184 public void drop(DropTargetEvent e) { 1185 if (fileTransfer.isSupportedType(e.currentDataType)) { 1186 String[] files = (String[]) e.data; 1187 for (int i = 0; i < files.length; i++) { 1188 openLocalFile(files[i], -1); 1189 } 1190 } 1191 } 1192 }); 1193 1194 showStatus("HDFView root - " + rootDir); 1195 showStatus("User property file - " + ViewProperties.getPropertyFile()); 1196 1197 content.setWeights(new int[] { 9, 1 }); 1198 contentArea.setWeights(new int[] { 1, 3 }); 1199 1200 log.trace("createContentArea(): load TreeView"); 1201 1202 DataViewFactory treeViewFactory = DataViewFactoryProducer.getFactory(DataViewType.TREEVIEW); 1203 if (treeViewFactory == null) { 1204 log.debug("createContentArea(): TreeView Factory is null"); 1205 return; 1206 } 1207 1208 try { 1209 treeView = treeViewFactory.getTreeView(treeArea, this); 1210 1211 if (treeView == null) { 1212 log.debug("createContentArea(): error occurred while instantiating TreeView class"); 1213 this.showStatus("Error occurred while instantiating TreeView class - see log for more info"); 1214 return; 1215 } 1216 } 1217 catch (ClassNotFoundException ex) { 1218 log.debug("createContentArea(): no suitable TreeView class found"); 1219 this.showStatus("Unable to find suitable TreeView class"); 1220 return; 1221 } 1222 1223 treeArea.setContent(treeView.getTree()); 1224 1225 log.info("Content Area created"); 1226 } 1227 1228 /** 1229 * @return a list of treeview implementations. 1230 */ 1231 public static final List<String> getListOfTreeViews() { 1232 return treeViews; 1233 } 1234 1235 /** 1236 * @return a list of imageview implementations. 1237 */ 1238 public static final List<String> getListOfImageViews() { 1239 return imageViews; 1240 } 1241 1242 /** 1243 * @return a list of tableview implementations. 1244 */ 1245 public static final List<?> getListOfTableViews() { 1246 return tableViews; 1247 } 1248 1249 /** 1250 * @return a list of metaDataview implementations. 1251 */ 1252 public static final List<?> getListOfMetaDataViews() { 1253 return metaDataViews; 1254 } 1255 1256 /** 1257 * @return a list of paletteview implementations. 1258 */ 1259 public static final List<?> getListOfPaletteViews() { 1260 return paletteViews; 1261 } 1262 1263 @Override 1264 public TreeView getTreeView() { 1265 return treeView; 1266 } 1267 1268 public Combo getUrlBar() { 1269 return url_bar; 1270 } 1271 1272 /** 1273 * Display feedback message. 1274 * 1275 * @param msg 1276 * the message to display. 1277 */ 1278 @Override 1279 public void showStatus(String msg) { 1280 if (status == null) { 1281 log.debug("showStatus(): status area is null"); 1282 return; 1283 } 1284 1285 status.append(msg); 1286 status.append("\n"); 1287 } 1288 1289 public void showMetaData(final HObject obj) { 1290 for (Control control : generalArea.getChildren()) control.dispose(); 1291 generalArea.setContent(null); 1292 1293 if (obj == null) return; 1294 1295 log.trace("showMetaData(): start"); 1296 1297 DataViewFactory metaDataViewFactory = DataViewFactoryProducer.getFactory(DataViewType.METADATA); 1298 if (metaDataViewFactory == null) return; 1299 1300 MetaDataView theView; 1301 try { 1302 theView = metaDataViewFactory.getMetaDataView(generalArea, this, obj); 1303 1304 if (theView == null) { 1305 log.debug("showMetaData(): error occurred while instantiating MetaDataView class"); 1306 this.showStatus("Error occurred while instantiating MetaDataView class - see log for more info"); 1307 return; 1308 } 1309 } 1310 catch (ClassNotFoundException ex) { 1311 log.debug("showMetaData(): no suitable MetaDataView class found"); 1312 this.showStatus("Unable to find suitable MetaDataView class"); 1313 return; 1314 } 1315 1316 // String viewName = (String) HDFView.getListOfMetaDataViews().get(0); 1317 // 1318 // try { 1319 // Class<?> theClass = Class.forName(viewName); 1320 // if ("hdf.view.DefaultMetaDataView".equals(viewName)) { 1321 // Object[] initargs = { generalArea, this, obj }; 1322 // Tools.newInstance(theClass, initargs); 1323 // } 1324 // else { 1325 // Object[] initargs = { this, obj }; 1326 // Tools.newInstance(theClass, initargs); 1327 // } 1328 // } 1329 // catch (Exception ex) { 1330 // this.showStatus(ex.toString()); 1331 // } 1332 1333 log.trace("showMetaData(): finish"); 1334 } 1335 1336 public void closeFile(FileFormat theFile) { 1337 if (theFile == null) { 1338 display.beep(); 1339 Tools.showError(mainWindow, "Close", "Select a file to close"); 1340 return; 1341 } 1342 1343 // Close all the data windows of this file 1344 Shell[] views = display.getShells(); 1345 if (views != null) { 1346 for (int i = 0; i < views.length; i++) { 1347 Object shellData = views[i].getData(); 1348 1349 if (!(shellData instanceof DataView)) continue; 1350 1351 if ((DataView) shellData != null) { 1352 HObject obj = ((DataView) shellData).getDataObject(); 1353 1354 if (obj == null || obj.getFileFormat() == null) continue; 1355 1356 if (obj.getFileFormat().equals(theFile)) { 1357 views[i].dispose(); 1358 views[i] = null; 1359 } 1360 } 1361 } 1362 } 1363 1364 int index = url_bar.getSelectionIndex(); 1365 if (index >= 0) { 1366 String fName = url_bar.getItem(url_bar.getSelectionIndex()); 1367 if (theFile.getFilePath().equals(fName)) { 1368 currentFile = null; 1369 url_bar.setText(""); 1370 } 1371 } 1372 1373 try { 1374 treeView.closeFile(theFile); 1375 } 1376 catch (Exception ex) {} 1377 1378 theFile = null; 1379 1380 for (Control control : generalArea.getChildren()) control.dispose(); 1381 generalArea.setContent(null); 1382 1383 System.gc(); 1384 } 1385 1386 /** 1387 * Write the change of data to the given file. 1388 * 1389 * @param theFile 1390 * The file to be updated. 1391 */ 1392 public void writeDataToFile(FileFormat theFile) { 1393 try { 1394 Shell[] openShells = display.getShells(); 1395 1396 if (openShells != null) { 1397 for (int i = 0; i < openShells.length; i++) { 1398 DataView theView = (DataView) openShells[i].getData(); 1399 1400 if (theView instanceof TableView) { 1401 TableView tableView = (TableView) theView; 1402 FileFormat file = tableView.getDataObject().getFileFormat(); 1403 if (file.equals(theFile)) tableView.updateValueInFile(); 1404 } 1405 } 1406 } 1407 } 1408 catch (Exception ex) { 1409 display.beep(); 1410 Tools.showError(mainWindow, "Save", ex.getMessage()); 1411 } 1412 } 1413 1414 @Override 1415 public void addDataView(DataView dataView) { 1416 if (dataView == null || dataView instanceof MetaDataView) { 1417 return; 1418 } 1419 1420 // Check if the data content is already displayed 1421 Shell[] shellList = display.getShells(); 1422 if (shellList != null) { 1423 for (int i = 0; i < shellList.length; i++) { 1424 if (dataView.equals(shellList[i].getData()) 1425 && shellList[i].isVisible()) { 1426 showWindow(shellList[i]); 1427 return; 1428 } 1429 } 1430 } 1431 1432 // First window being added 1433 if (shellList.length == 2) { 1434 setEnabled(Arrays.asList(windowMenu.getItems()), true); 1435 } 1436 1437 HObject obj = dataView.getDataObject(); 1438 String fullPath = ((obj.getPath() == null) ? "" : obj.getPath()) 1439 + ((obj.getName() == null) ? "" : obj.getName()); 1440 1441 MenuItem item = new MenuItem(windowMenu, SWT.PUSH); 1442 item.setText(fullPath); 1443 item.addSelectionListener(new SelectionAdapter() { 1444 @Override 1445 public void widgetSelected(SelectionEvent e) { 1446 Shell[] sList = display.getShells(); 1447 1448 for (int i = 0; i < sList.length; i++) { 1449 DataView view = (DataView) sList[i].getData(); 1450 1451 if (view != null) { 1452 HObject obj = view.getDataObject(); 1453 1454 if (obj.getFullName().equals(((MenuItem) e.widget).getText())) { 1455 showWindow(sList[i]); 1456 } 1457 } 1458 } 1459 } 1460 }); 1461 1462 mainWindow.setCursor(null); 1463 } 1464 1465 @Override 1466 public void removeDataView(DataView dataView) { 1467 if (mainWindow.isDisposed()) return; 1468 1469 HObject obj = dataView.getDataObject(); 1470 if (obj == null) return; 1471 1472 MenuItem[] items = windowMenu.getItems(); 1473 for (int i = 0; i < items.length; i++) { 1474 if(items[i].getText().equals(obj.getFullName())) { 1475 items[i].dispose(); 1476 } 1477 } 1478 1479 // Last window being closed 1480 if (display.getShells().length == 2) { 1481 for (MenuItem item : windowMenu.getItems()) item.setEnabled(false); 1482 } 1483 } 1484 1485 @Override 1486 public DataView getDataView(HObject dataObject) { 1487 Shell[] openShells = display.getShells(); 1488 DataView view = null; 1489 HObject currentObj = null; 1490 FileFormat currentFile = null; 1491 1492 for (int i = 0; i < openShells.length; i++) { 1493 view = (DataView) openShells[i].getData(); 1494 1495 if (view != null) { 1496 currentObj = view.getDataObject(); 1497 if (currentObj == null) continue; 1498 1499 currentFile = currentObj.getFileFormat(); 1500 1501 if (currentObj.equals(dataObject) && currentFile.equals(dataObject.getFileFormat())) 1502 return view; 1503 } 1504 } 1505 1506 return null; 1507 } 1508 1509 /** 1510 * Set the testing state that determines if HDFView 1511 * is being executed for GUI testing. 1512 * 1513 * @param testing 1514 * Provides SWTBot native dialog compatibility 1515 * workarounds if set to true. 1516 */ 1517 public void setTestState(boolean testing) { 1518 isTesting = testing; 1519 currentDir = rootDir; 1520 } 1521 1522 public boolean getTestState() { 1523 return isTesting; 1524 } 1525 1526 /** 1527 * Set default UI fonts. 1528 */ 1529 private void updateFont(Font font) { 1530 if (currentFont != null) currentFont.dispose(); 1531 1532 currentFont = font; 1533 1534 mainWindow.setFont(font); 1535 recentFilesButton.setFont(font); 1536 url_bar.setFont(font); 1537 clearTextButton.setFont(font); 1538 status.setFont(font); 1539 1540 // On certain platforms the url_bar items don't update their size after 1541 // a font change. Removing and replacing them fixes this. 1542 for (String item : url_bar.getItems()) { 1543 url_bar.remove(item); 1544 url_bar.add(item); 1545 } 1546 1547 if (treeView.getSelectedFile() != null) { 1548 url_bar.select(0); 1549 } 1550 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 1695 try { 1696 url_bar.remove(filename); 1697 } 1698 catch (Exception ex) {} 1699 1700 url_bar.add(filename, 0); 1701 url_bar.select(0); 1702 1703 try { 1704 treeView.openFile(filename, accessMode); 1705 } 1706 catch (Throwable ex) { 1707 try { 1708 treeView.openFile(filename, FileFormat.READ); 1709 } 1710 catch (Throwable ex2) { 1711 display.beep(); 1712 url_bar.deselectAll(); 1713 Tools.showError(mainWindow, "Open", "Failed to open file " + filename + "\n" + ex2); 1714 currentFile = null; 1715 } 1716 } 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}