package org.eclipse.ui.views.file; import static java.text.MessageFormat.format; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IConfigurationElement; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Platform; import org.eclipse.jface.action.Action; import org.eclipse.jface.action.ActionContributionItem; import org.eclipse.jface.action.IAction; import org.eclipse.jface.action.IContributionItem; import org.eclipse.jface.action.IToolBarManager; import org.eclipse.jface.action.Separator; import org.eclipse.jface.dialogs.IDialogSettings; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Label; import org.eclipse.ui.IEditorInput; import org.eclipse.ui.IKeyBindingService; import org.eclipse.ui.IMemento; import org.eclipse.ui.IPathEditorInput; import org.eclipse.ui.ISelectionListener; import org.eclipse.ui.ISelectionService; import org.eclipse.ui.IViewSite; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.PartInitException; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.part.EditorPart; import org.eclipse.ui.part.FileEditorInput; import org.eclipse.ui.part.IShowInTarget; import org.eclipse.ui.part.PageBook; import org.eclipse.ui.part.ShowInContext; import org.eclipse.ui.part.ViewPart; /** * A view that displays the file determined by its current source. */ public class FileView extends ViewPart implements IShowInTarget{ public static final String BINDINGS = "bindings"; //$NON-NLS-1$ public static final String VIEW_ID = "viewId"; //$NON-NLS-1$ public static final String TYPE = "type"; //$NON-NLS-1$ private static class ErrorPage extends Composite { public ErrorPage(Composite parent, String errorMessage) { super(parent, SWT.NONE); setLayout(new GridLayout()); Label errorLabel = new Label(this, SWT.CENTER); errorLabel.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, true, true)); errorLabel.setText(errorMessage); } } private static final String PATH = "path"; //$NON-NLS-1$ private static final String LINKED = "linked"; //$NON-NLS-1$ private IFileViewType<? super Composite> type; private final List<String> extensions = new ArrayList<String>(); private String errorMessage = "File not found"; private PageBook pageBook; private final Map<IFile, Composite> pages = new HashMap<IFile, Composite>(); private IFile file; private Control errorPage; private Label fileNameDisplay; private IToolBarManager toolbar; private boolean toolbarFilled = false; private IContributionItem[] toolbarContributions; private boolean linked = true; @Override public void init(IViewSite site, IMemento memento) throws PartInitException { super.init(site, memento); IConfigurationElement[] configurationElements = Platform.getExtensionRegistry().getConfigurationElementsFor(Activator.getId(), BINDINGS); for (IConfigurationElement configurationElement : configurationElements) { if (site.getId().equals(configurationElement.getAttribute(VIEW_ID))) { // Type try { Object type = configurationElement.createExecutableExtension(TYPE); if (type instanceof IFileViewType) { @SuppressWarnings("unchecked") IFileViewType<? super Composite> fileViewType = (IFileViewType<? super Composite>)type; this.setType(fileViewType); } } catch (CoreException e) { Activator.logError(format("Can't initialize type of file view {0}", site.getId()), e); } // Extensions for (IConfigurationElement extensionElement : configurationElement.getChildren("fileExtension")) { //$NON-NLS-1$ extensions.add(extensionElement.getAttribute("extension")); //$NON-NLS-1$ } // Error message String errorMessage = configurationElement.getAttribute("errorMessage"); //$NON-NLS-1$ if (errorMessage != null) { this.errorMessage = errorMessage; } } } // Toolbar toolbar = site.getActionBars().getToolBarManager(); toolbarContributions = getType().getToolbarContributions(); registerToolbarActionShortcuts(); // Restore settings IDialogSettings dialogSettings = Activator.getInstance().getDialogSettings(); if (dialogSettings != null) { // Path String pathString = dialogSettings.get(getSettingsKey(PATH)); if (pathString != null) { IPath path = Path.fromPortableString(pathString); IFile file = ResourcesPlugin.getWorkspace().getRoot().getFileForLocation(path); setFile(file); } // Linked Boolean linked = dialogSettings.getBoolean(getSettingsKey(LINKED)); if (linked != null) { this.linked = linked; } } toggleLinkedAction.setChecked(this.linked); } @SuppressWarnings("deprecation") private void registerToolbarActionShortcuts(){ IKeyBindingService keybindingService = getSite().getKeyBindingService(); for (IContributionItem contrib : toolbarContributions) { if(contrib instanceof ActionContributionItem){ IAction action = ((ActionContributionItem) contrib).getAction(); if(action instanceof ToolbarSubmenuAction){ for (IAction subMenuAction : ((ToolbarSubmenuAction) action).getActions()) { keybindingService.registerAction(subMenuAction); } }else{ keybindingService.registerAction(action); } } } } @Override public void createPartControl(Composite parent) { GridLayout layout = new GridLayout(); layout.marginWidth = 0; layout.marginHeight = 0; layout.horizontalSpacing = 0; layout.verticalSpacing = 0; parent.setLayout(layout); fileNameDisplay = new Label(parent, SWT.NONE); GridData fileNameDisplayLayoutData = new GridData(); fileNameDisplayLayoutData.horizontalAlignment = GridData.FILL; fileNameDisplay.setLayoutData(fileNameDisplayLayoutData); pageBook = new PageBook(parent, SWT.NONE); GridData pageBookLayoutData = new GridData(); pageBookLayoutData.horizontalAlignment = GridData.FILL; pageBookLayoutData.verticalAlignment = GridData.FILL; pageBookLayoutData.grabExcessHorizontalSpace = true; pageBookLayoutData.grabExcessVerticalSpace = true; pageBook.setLayoutData(pageBookLayoutData); errorPage = new ErrorPage(pageBook, errorMessage); toolbar.add(toggleLinkedAction); toolbar.add(closeAction); toolbar.add(switchFileAction); if (getFile() != null) { show(getFile()); } // Selection listener ISelectionService selectionService = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getSelectionService(); selectionService.addPostSelectionListener(selectionListener); } @Override public void setFocus() { pageBook.setFocus(); } private void saveSettings() { IDialogSettings dialogSettings = Activator.getInstance().getDialogSettings(); if(dialogSettings!=null){ dialogSettings.put(getSettingsKey(PATH), (file == null || file.getLocation() == null) ? null : file.getLocation().toPortableString()); dialogSettings.put(getSettingsKey(LINKED), linked); } } private String getSettingsKey(String prefix){ return prefix+getType().getClass().getSimpleName(); } @Override public void dispose() { saveSettings(); for (Composite page : pages.values()) { if (page != null) { getType().pageClosed(page); } } super.dispose(); pageBook=null; pages.clear(); ISelectionService selectionService = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getSelectionService(); selectionService.removePostSelectionListener(selectionListener); } public List<String> getExtensions() { return extensions; } public void hide() { if (!pageBook.isDisposed()) { pageBook.setVisible(false); setFile(null); } refreshToolbarContributions(); } public void show(IFile file) { if (pageBook!=null && !pageBook.isDisposed()) { pageBook.setVisible(true); setFile(file); setTitleToolTip(file.getFullPath().toString()); Composite page = getPage(); if ((page == null) || page.isDisposed()) { load(file); } refresh(); // Fill toolbar for the first time if (!toolbarFilled) { toolbarFilled = true; if(toolbarContributions.length>0){ toolbar.add(new Separator()); } for (IContributionItem toolbarContribution : toolbarContributions) { toolbar.add(toolbarContribution); } toolbar.update(true); } } if (!fileNameDisplay.isDisposed()) { fileNameDisplay.setText(file.getFullPath().toOSString()); } } private void load(IFile file) { Composite page = null; if (file.exists()) { try { page = getType().createPage(pageBook, file); } catch (Exception e) { Activator.logError("Can't create file view page", e); } pages.put(file, page); } else { showErrorPage(); } } private void refresh() { if (pageBook != null) { Composite page = getPage(); if (page == null) { showErrorPage(); } else { pageBook.showPage(page); getType().pageShown(page); for (IContributionItem contributionItem : toolbarContributions) { contributionItem.setVisible(true); } } } refreshToolbarContributions(); } private void showErrorPage() { pageBook.showPage(errorPage); for (IContributionItem contributionItem : toolbarContributions) { contributionItem.setVisible(false); } toolbar.update(true); } private void refreshToolbarContributions() { for (IContributionItem toolbarContribution : toolbarContributions) { boolean visible = (getFile() != null) && (getPage() != null); if (visible) { toolbarContribution.update(); } toolbarContribution.setVisible(visible); } toolbar.update(true); } public void reload(IFile file) { Composite oldPage = pages.get(file); if (oldPage != null) { if (file.exists()) { try { getType().reload(oldPage); } catch (Exception e) { Activator.logError("Error while reloading file", e); pages.put(file, null); } } else { pages.put(file, null); } if (file.equals(getFile())) { refresh(); } } } private Composite getPage() { return pages.get(getFile()); } private void setFile(IFile file) { this.file = file; } public IFile getFile() { return file; } private void setType(IFileViewType<? super Composite> type) { this.type = type; } public IFileViewType<? super Composite> getType() { return type; } private final ISelectionListener selectionListener = new ISelectionListener() { @Override public void selectionChanged(IWorkbenchPart part, ISelection selection) { if (linked) { IFile selectedFile = null; if (selection instanceof IStructuredSelection) { IStructuredSelection structuredSelection = (IStructuredSelection)selection; Object selectedElement = structuredSelection.getFirstElement(); if (selectedElement instanceof IFile) { selectedFile = (IFile)selectedElement; } } else if (part instanceof EditorPart) { EditorPart editorPart = (EditorPart)part; IEditorInput editorInput = editorPart.getEditorInput(); if (editorInput instanceof IPathEditorInput) { IPathEditorInput pathEditorInput = (IPathEditorInput)editorInput; IPath locationPath = pathEditorInput.getPath(); selectedFile = ResourcesPlugin.getWorkspace().getRoot().getFileForLocation(locationPath); } } if (selectedFile != null) { IFile fileToView = getType().getFile(selectedFile); if (getExtensions().contains(fileToView.getFileExtension())) { show(fileToView); } } } } }; private final IAction toggleLinkedAction = new Action("Link with Editor and Selection", IAction.AS_CHECK_BOX) { { setImageDescriptor(Activator.getImageDescriptor("icons/Link.png"));//$NON-NLS-1$ } @Override public void run() { linked = !linked; } }; private final IAction closeAction= new ToolbarSubmenuAction("Close", Activator.getImageDescriptor("icons/remove.png")){//$NON-NLS-2$ { addAction(new Action("Close all"){ public void run() { closeAll(true); }; }); addAction(new Action("Close others"){ public void run() { closeAll(false); }; }); } private void closeAll(boolean includeCurrent){ List<IFile> files = new ArrayList<IFile>(pages.keySet()); for (IFile iFile : files) { if(includeCurrent || !iFile.equals(getFile())){ close(iFile); } } } public void run() { if(getFile()!=null){ close(getFile()); } }; private void close(IFile file){ Composite composite = pages.remove(file); if(composite!=null){ getType().pageClosed(composite); if(file.equals(getFile())){ fileNameDisplay.setText("");//$NON-NLS-1$ setFile(null); showErrorPage(); } } } }; private final Comparator<IFile> fileNameComparator=new Comparator<IFile>() { @Override public int compare(IFile o1, IFile o2) { return o1.getName().compareTo(o2.getName()); } }; private final IAction switchFileAction=new ToolbarSubmenuAction("Choose Opened Document", Activator.getImageDescriptor("icons/documents.png")){//$NON-NLS-2$ @Override List<IAction> getActions() { List<IAction> result=new ArrayList<IAction>(); List<IFile> files=new ArrayList<IFile>(pages.keySet()); Collections.sort(files, fileNameComparator); for(IFile file: files){ final IFile theFile=file; Action action = new Action(theFile.getName()) { public void run() { show(theFile); }; }; if(file.equals(getFile())){ action.setChecked(true); } result.add(action); } return result; }; }; @Override public boolean show(ShowInContext context) { if (context == null) return false; Object potentialFile=null; ISelection sel = context.getSelection(); if (sel instanceof IStructuredSelection) { IStructuredSelection ss = (IStructuredSelection) sel; potentialFile = ss.getFirstElement(); }else{ Object input = context.getInput(); if(input instanceof FileEditorInput){ potentialFile=((FileEditorInput)input).getFile(); } } if (potentialFile instanceof IFile) { IFile actualFileToOpen = type.getFile((IFile) potentialFile); if (actualFileToOpen.exists()) { show(actualFileToOpen); return true; } } return false; } }