/*******************************************************************************
* Copyright (c) 2009 Andrey Loskutov.
* 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
* Contributor: Andrey Loskutov - initial API and implementation
*******************************************************************************/
package de.loskutov.anyedit.actions;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import org.eclipse.core.filesystem.EFS;
import org.eclipse.core.filesystem.IFileStore;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.content.IContentType;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.ui.IEditorDescriptor;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IEditorRegistry;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.editors.text.EditorsUI;
import org.eclipse.ui.ide.FileStoreEditorInput;
import org.eclipse.ui.ide.IDE;
import de.loskutov.anyedit.AnyEditToolsPlugin;
import de.loskutov.anyedit.IOpenEditorParticipant;
import de.loskutov.anyedit.util.EclipseUtils;
import de.loskutov.anyedit.util.TextUtil;
import de.loskutov.anyedit.util.TextUtil.LineAndCaret;
/**
* @author Andrey
*/
public class DefaultOpenEditorParticipant implements IOpenEditorParticipant {
public DefaultOpenEditorParticipant() {
super();
}
@Override
public int getPriority() {
// a bit higher as default
return PRIO_DEFAULT + 1;
}
@Override
public int guessLine(IDocument doc, ISelectionProvider selectionProvider,
IWorkbenchPart editorPart) {
if (doc == null) {
return -1;
}
// only if line information available
int caretPosition = EclipseUtils.getCaretPosition(selectionProvider);
String line = getLinePart(doc, caretPosition);
int lineReference = TextUtil.getDefaultTextUtilities().findLineReferenceRegex(line, 0);
return lineReference;
}
private static String getLinePart(IDocument doc, int caretPosition) {
String linePart = null;
// try to get line after caret
try {
IRegion line = doc.getLineInformation(doc.getLineOfOffset(caretPosition));
linePart = doc.get(line.getOffset(), line.getLength());
int startOffset = caretPosition - line.getOffset();
if (linePart != null && startOffset < linePart.length()) {
linePart = linePart.substring(startOffset);
}
} catch (BadLocationException e) {
AnyEditToolsPlugin.logError(null, e);
}
return linePart;
}
@Override
public IEditorPart openEditor(IDocument doc, ISelectionProvider selectionProvider,
IEditorInput currentInput, IFile file) throws OperationCanceledException {
IEditorPart editorPart = null;
if (file != null) {
try {
// external files do not have location in workspace...
if (file.getLocation() == null) {
editorPart = openExternalEditor(file);
} else {
editorPart = openInternalEditor(file);
}
} catch (CoreException e) {
AnyEditToolsPlugin.logError("'Open file' operation failed", e);
}
}
return editorPart;
}
private IEditorPart openInternalEditor(IFile file) throws PartInitException {
return IDE.openEditor(PlatformUI.getWorkbench().getActiveWorkbenchWindow()
.getActivePage(), file, true);
}
private IEditorPart openExternalEditor(IFile file) throws CoreException {
File file2 = new File(file.getFullPath().toOSString());
if (!file2.isFile()) {
return null;
}
String editorId = getEditorId(file2);
IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow()
.getActivePage();
IFileStore fileStore;
try {
fileStore = EFS.getLocalFileSystem().getStore(
new Path(file2.getCanonicalPath()));
IEditorInput input = new FileStoreEditorInput(fileStore);
return page.openEditor(input, editorId);
} catch (IOException e) {
AnyEditToolsPlugin.logError("Could not get canonical file path", e);
}
return null;
}
private static String getEditorId(File file) {
IWorkbench workbench = PlatformUI.getWorkbench();
IEditorRegistry editorRegistry = workbench.getEditorRegistry();
IEditorDescriptor descriptor = editorRegistry.getDefaultEditor(file.getName(),
getContentType(file));
if (descriptor != null) {
return descriptor.getId();
}
return EditorsUI.DEFAULT_TEXT_EDITOR_ID;
}
private static IContentType getContentType(File file) {
if (file == null) {
return null;
}
InputStream stream = null;
try {
stream = new FileInputStream(file);
return Platform.getContentTypeManager().findContentTypeFor(stream,
file.getName());
} catch (IOException e) {
AnyEditToolsPlugin.logError("'Open file' operation failed", e);
return null;
} finally {
try {
if (stream != null) {
stream.close();
}
} catch (IOException e) {
AnyEditToolsPlugin.logError("'Open file' operation failed", e);
}
}
}
@Override
public IFile guessFile(IDocument doc, ISelectionProvider selectionProvider,
IEditorInput currentInput, IWorkbenchPart currentPart) throws OperationCanceledException {
String selection = EclipseUtils.getSelectedText(selectionProvider);
String pathString = guessPath(doc, selectionProvider, selection);
IFile file = getFromPath(currentInput, pathString, selection, currentPart);
return file;
}
private String guessPath(IDocument doc, ISelectionProvider selectionProvider,
String selection) {
TextUtil textUtil = TextUtil.getDefaultTextUtilities();
String selectedText = textUtil.trimPath(selection);
if(selectedText == null) {
return null;
}
boolean mayBeFilePath = textUtil.isFilePath(selectedText);
if (!mayBeFilePath) {
// try to search around caret
if (doc != null) {
int caretPosition = EclipseUtils.getCaretPosition(selectionProvider);
try {
IRegion line = doc.getLineInformation(doc.getLineOfOffset(caretPosition));
String lineText = doc.get(line.getOffset(), line.getLength());
selectedText = textUtil.trimPath(lineText);
int index = lineText.indexOf(selectedText);
selectedText = textUtil.findPath(new LineAndCaret(selectedText, caretPosition - index - line.getOffset()));
} catch (BadLocationException e) {
AnyEditToolsPlugin.logError("", e);
selectedText = textUtil.findPath(new LineAndCaret(selectedText, selectedText.length() / 2));
}
} else {
// virtual caret in the middle of string
selectedText = textUtil.findPath(new LineAndCaret(selectedText, selectedText.length() / 2));
}
if(selectedText == null) {
return null;
}
}
if (selectedText.length() == 0) {
selectedText = null;
}
return selectedText;
}
private IFile getFromPath(IEditorInput currentInput, String pathStr, String selection,
IWorkbenchPart currentPart) throws OperationCanceledException {
if (pathStr == null || pathStr.length() == 0) {
return getFromSelection(selection);
}
IProject project = EclipseUtils.getProject(currentInput);
// nothing found with current input? try with viewPart
if (project == null) {
project = EclipseUtils.getProject(currentPart);
}
IFile resource = EclipseUtils.getResource(project, currentInput, pathStr);
if (resource != null) {
return resource;
}
// no luck with guessed path string - so try the entire selection instead
return getFromSelection(selection);
}
private static IFile getFromSelection(String selection) throws OperationCanceledException {
if (selection == null || selection.length() == 0) {
return EclipseUtils.queryFile(null, ResourcesPlugin.getWorkspace().getRoot());
}
Path path = new Path(selection);
// remove all stuff but let only the file name there
String pathString = selection;
if (path.segmentCount() > 1) {
pathString = path.lastSegment();
}
return EclipseUtils.queryFile(pathString, ResourcesPlugin.getWorkspace()
.getRoot());
}
}