/****************************************************************************** * Copyright (C) 2013 Fabio Zadrozny * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Fabio Zadrozny <fabiofz@gmail.com> - initial API and implementation ******************************************************************************/ package org.python.pydev.shared_ui; import java.io.File; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; import org.eclipse.core.filesystem.EFS; import org.eclipse.core.filesystem.IFileStore; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IWorkspaceRoot; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IStatus; import org.eclipse.jface.action.IStatusLineManager; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.IRegion; import org.eclipse.jface.text.ITextSelection; import org.eclipse.jface.text.TextSelection; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionProvider; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.IActionBars; import org.eclipse.ui.IEditorActionBarContributor; import org.eclipse.ui.IEditorDescriptor; import org.eclipse.ui.IEditorInput; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.IEditorReference; import org.eclipse.ui.IEditorRegistry; import org.eclipse.ui.IURIEditorInput; import org.eclipse.ui.IWorkbench; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.IWorkbenchPartSite; import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.ide.FileStoreEditorInput; import org.eclipse.ui.ide.IDE; import org.eclipse.ui.part.EditorActionBarContributor; import org.eclipse.ui.part.FileEditorInput; import org.eclipse.ui.part.MultiPageEditorPart; import org.eclipse.ui.texteditor.IDocumentProvider; import org.eclipse.ui.texteditor.ITextEditor; import org.python.pydev.shared_core.log.Log; import org.python.pydev.shared_core.string.TextSelectionUtils; import org.python.pydev.shared_core.structure.Location; import org.python.pydev.shared_core.utils.Reflection; import org.python.pydev.shared_ui.editor_input.EditorInputUtils; public class EditorUtils { public static File getFileFromEditorInput(IEditorInput editorInput) { File f = null; IFile file = editorInput.getAdapter(IFile.class); if (file != null) { IPath location = file.getLocation(); if (location != null) { IPath path = location.makeAbsolute(); f = path.toFile(); } } else { try { if (editorInput instanceof IURIEditorInput) { IURIEditorInput iuriEditorInput = (IURIEditorInput) editorInput; return new File(iuriEditorInput.getURI()); } } catch (Throwable e) { //OK, IURIEditorInput was only added on eclipse 3.3 } try { IPath path = (IPath) Reflection.invoke(editorInput, "getPath", new Object[0]); f = path.toFile(); } catch (Throwable e) { //ok, it has no getPath } } return f; } public static Shell getShell() { IWorkbenchWindow activeWorkbenchWindow = getActiveWorkbenchWindow(); if (activeWorkbenchWindow == null) { Log.log("Error. Not currently with thread access (so, there is no activeWorkbenchWindow available)"); return null; } return activeWorkbenchWindow.getShell(); } /** * @return the active workbench window or null if it's not available. */ public static IWorkbenchWindow getActiveWorkbenchWindow() { IWorkbench workbench = PlatformUI.getWorkbench(); if (workbench == null) { return null; } IWorkbenchWindow activeWorkbenchWindow = workbench.getActiveWorkbenchWindow(); return activeWorkbenchWindow; } /** * @return the active text editor or null if it's not available. */ public static ITextEditor getActiveEditor() { IWorkbench workbench = PlatformUI.getWorkbench(); if (workbench != null) { IWorkbenchWindow activeWorkbenchWindow = workbench .getActiveWorkbenchWindow(); if (activeWorkbenchWindow != null) { IWorkbenchPage activePage = activeWorkbenchWindow .getActivePage(); if (activePage != null) { IEditorPart activeEditor = activePage.getActiveEditor(); if (activeEditor instanceof ITextEditor) { return (ITextEditor) activeEditor; } } } } return null; } public static IStatusLineManager getStatusLineManager(ITextEditor editor) { IEditorActionBarContributor contributor = editor.getEditorSite().getActionBarContributor(); if (!(contributor instanceof EditorActionBarContributor)) { return null; } IActionBars actionBars = ((EditorActionBarContributor) contributor).getActionBars(); if (actionBars == null) { return null; } return actionBars.getStatusLineManager(); } public static ITextSelection getTextSelection(ITextEditor editor) { ISelectionProvider selectionProvider = editor.getSelectionProvider(); if (selectionProvider == null) { return null; } ISelection selection = selectionProvider.getSelection(); if (!(selection instanceof ITextSelection)) { return null; } return (ITextSelection) selection; } public static IDocument getDocument(ITextEditor editor) { IDocumentProvider documentProvider = editor.getDocumentProvider(); if (documentProvider != null) { return documentProvider.getDocument(editor.getEditorInput()); } return null; } public static TextSelectionUtils createTextSelectionUtils(ITextEditor editor) { return new TextSelectionUtils(getDocument(editor), getTextSelection(editor)); } public static void showInEditor(ITextEditor textEdit, Location start, Location end) { try { IDocument doc = textEdit.getDocumentProvider().getDocument(textEdit.getEditorInput()); int s = start.toOffset(doc); int e = end == null ? s : end.toOffset(doc); TextSelection sel = new TextSelection(s, e - s); textEdit.getSelectionProvider().setSelection(sel); } catch (BadLocationException e1) { Log.log(IStatus.ERROR, ("Error setting selection:" + start + " - " + end + " - " + textEdit), e1); } } public static void showInEditor(ITextEditor textEdit, IRegion region) { TextSelection sel = new TextSelection(region.getOffset(), region.getLength()); textEdit.getSelectionProvider().setSelection(sel); } /** * Select the line given by lineNumber. Takes no effect if lineNumber <= 0 || lineNumber > number of lines in document * @param textEdit Text editor to select line in * @param lineNumber Line number to select. (First line in the editor is line 1) */ public static void showInEditor(ITextEditor textEdit, int lineNumber) { // Setting line number programatically courtesy of // http://stackoverflow.com/questions/2873879/eclipe-pde-jump-to-line-x-and-highlight-it if (lineNumber > 0) { IDocument document = textEdit.getDocumentProvider().getDocument( textEdit.getEditorInput()); if (document != null) { IRegion lineInfo = null; try { // line count internally starts with 0 lineInfo = document.getLineInformation(lineNumber - 1); } catch (BadLocationException e) { // ignored because line number may not really exist in document, } if (lineInfo != null) { textEdit.selectAndReveal(lineInfo.getOffset(), lineInfo.getLength()); } } } } public static IEditorPart openFile(File fileToOpen) { return openFile(fileToOpen, true); } /** * Open an editor anywhere on the file system using Eclipse's default editor registered for the given file. * * @param fileToOpen File to open * @note we must be in the UI thread for this method to work. * @return Editor opened or created */ public static IEditorPart openFile(File fileToOpen, boolean activate) { final IWorkbench workbench = PlatformUI.getWorkbench(); if (workbench == null) { throw new RuntimeException("workbench cannot be null"); } IWorkbenchWindow activeWorkbenchWindow = workbench.getActiveWorkbenchWindow(); if (activeWorkbenchWindow == null) { throw new RuntimeException( "activeWorkbenchWindow cannot be null (we have to be in a ui thread for this to work)"); } IWorkbenchPage wp = activeWorkbenchWindow.getActivePage(); final IFileStore fileStore = EFS.getLocalFileSystem().getStore(fileToOpen.toURI()); try { if (activate) { // open the editor on the file return IDE.openEditorOnFileStore(wp, fileStore); } // Workaround when we don't want to activate (as there's no suitable API // in the core for that). IEditorInput input = getEditorInput(fileStore); String editorId = getEditorId(input, null); return wp.openEditor(input, editorId, activate); } catch (Exception e) { Log.log("Editor failed to open", e); return null; } } private static IEditorInput getEditorInput(IFileStore fileStore) { IFile workspaceFile = getWorkspaceFile(fileStore); if (workspaceFile != null) { return new FileEditorInput(workspaceFile); } return new FileStoreEditorInput(fileStore); } private static IFile getWorkspaceFile(IFileStore fileStore) { IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); IFile[] files = root.findFilesForLocationURI(fileStore.toURI()); files = filterNonExistentFiles(files); if (files == null || files.length == 0) { return null; } // for now only return the first file return files[0]; } private static IFile[] filterNonExistentFiles(IFile[] files) { if (files == null) { return null; } int length = files.length; ArrayList<IFile> existentFiles = new ArrayList<IFile>(length); for (int i = 0; i < length; i++) { if (files[i].exists()) { existentFiles.add(files[i]); } } return existentFiles.toArray(new IFile[existentFiles.size()]); } /** * Open an editor anywhere on the file system using Eclipse's default editor registered for the given file. * * @param fileToOpen File to open * @note we must be in the UI thread for this method to work. * @return Editor opened or created */ public static IEditorPart openFile(IFile fileToOpen) { final IWorkbench workbench = PlatformUI.getWorkbench(); if (workbench == null) { throw new RuntimeException("workbench cannot be null"); } IWorkbenchWindow activeWorkbenchWindow = workbench.getActiveWorkbenchWindow(); if (activeWorkbenchWindow == null) { throw new RuntimeException( "activeWorkbenchWindow cannot be null (we have to be in a ui thread for this to work)"); } IWorkbenchPage wp = activeWorkbenchWindow.getActivePage(); try { return IDE.openEditor(wp, fileToOpen); } catch (Exception e) { Log.log("Editor failed to open", e); return null; } } public static IWorkbenchPartSite getSite() { final IWorkbench workbench = PlatformUI.getWorkbench(); IWorkbenchWindow activeWorkbenchWindow = workbench.getActiveWorkbenchWindow(); if (activeWorkbenchWindow == null) { return null; } IWorkbenchPage activePage = activeWorkbenchWindow.getActivePage(); if (activePage == null) { return null; } IEditorPart activeEditor = activePage.getActiveEditor(); if (activeEditor == null) { return null; } return activeEditor.getSite(); } public static String getEditorId(IEditorInput input, Object element) { String name = input.getName(); if (name == null) { return null; } try { IFile iFile = input.getAdapter(IFile.class); if (iFile != null) { IEditorDescriptor defaultEditor = IDE.getDefaultEditor(iFile); if (defaultEditor != null) { return defaultEditor.getId(); } } } catch (Exception e) { Log.log(e); // This shouldn't happen, but just in case... } IEditorRegistry editorReg = PlatformUI.getWorkbench().getEditorRegistry(); IEditorDescriptor defaultEditor = editorReg.getDefaultEditor(name); if (defaultEditor == null) { return null; } return defaultEditor.getId(); } /** * @param statusLineManager optional (to set error messages). * * Return may have IFile and File objects. */ public static List<Object> getFilesInOpenEditors(IStatusLineManager statusLineManager) { IWorkbenchWindow window = EditorUtils.getActiveWorkbenchWindow(); if (window == null) { if (statusLineManager != null) { statusLineManager.setErrorMessage("Active workbench window is null."); } return new ArrayList<>(0); } IWorkbenchPage activePage = window.getActivePage(); if (activePage == null) { if (statusLineManager != null) { statusLineManager.setErrorMessage("Active page is null."); } return new ArrayList<>(0); } IEditorReference editorsArray[] = activePage.getEditorReferences(); final List<Object> files = new ArrayList<Object>(); for (int i = 0; i < editorsArray.length; i++) { IEditorPart realEditor = editorsArray[i].getEditor(true); if (realEditor != null) { if (realEditor instanceof MultiPageEditorPart) { try { Method getPageCount = MultiPageEditorPart.class.getDeclaredMethod("getPageCount"); getPageCount.setAccessible(true); Method getEditor = MultiPageEditorPart.class.getDeclaredMethod("getEditor", int.class); getEditor.setAccessible(true); Integer pageCount = (Integer) getPageCount.invoke(realEditor); for (int j = 0; j < pageCount; j++) { IEditorPart part = (IEditorPart) getEditor.invoke(realEditor, j); if (part != null) { IEditorInput input = part.getEditorInput(); if (input != null) { IFile file = input.getAdapter(IFile.class); if (file != null) { files.add(file); } else { File file2 = EditorInputUtils.getFile(input); if (file2 != null) { files.add(file2); } } } } } } catch (Throwable e1) { //Log it but keep going on. Log.log(e1); } } else { IEditorInput input = realEditor.getEditorInput(); if (input != null) { IFile file = input.getAdapter(IFile.class); if (file != null) { files.add(file); } else { File file2 = EditorInputUtils.getFile(input); if (file2 != null) { files.add(file2); } } } } } } return files; } }