/******************************************************************************
* 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;
}
}