/*******************************************************************************
* Copyright (c) 2014 Bruno Medeiros and other Contributors.
* 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:
* Bruno Medeiros - initial API and implementation
*******************************************************************************/
package melnorme.lang.ide.ui.editor;
import static melnorme.utilbox.core.CoreUtil.tryCast;
import java.net.URI;
import java.nio.file.Path;
import java.nio.file.Paths;
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.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.Region;
import org.eclipse.jface.text.TextSelection;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.IReusableEditor;
import org.eclipse.ui.IStorageEditorInput;
import org.eclipse.ui.IURIEditorInput;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.ide.FileStoreEditorInput;
import org.eclipse.ui.ide.ResourceUtil;
import org.eclipse.ui.part.FileEditorInput;
import org.eclipse.ui.texteditor.IEditorStatusLine;
import org.eclipse.ui.texteditor.ITextEditor;
import melnorme.lang.ide.core.EclipseCore;
import melnorme.lang.ide.core.utils.ResourceUtils;
import melnorme.lang.ide.ui.utils.WorkbenchUtils;
import melnorme.lang.tooling.ast.SourceRange;
import melnorme.utilbox.core.CommonException;
import melnorme.utilbox.misc.Location;
public class EditorUtils {
public static IDocument getEditorDocument(ITextEditor textEditor) {
return textEditor.getDocumentProvider().getDocument(textEditor.getEditorInput());
}
public static TextSelection getSelection(ITextEditor editor) {
return (TextSelection) editor.getSelectionProvider().getSelection();
}
public static SourceRange getSelectionSR(ITextEditor editor) {
TextSelection sel = getSelection(editor);
return new SourceRange(sel.getOffset(), sel.getLength());
}
public static void setEditorSelection(ITextEditor textEditor, SourceRange sourceRange) {
EditorUtils.setEditorSelection(textEditor, sourceRange.getOffset(), sourceRange.getLength());
}
public static void setEditorSelection(ITextEditor textEditor, int offset, int length) {
textEditor.getSelectionProvider().setSelection(new TextSelection(offset, length));
}
/* ----------------- Editor input utils ----------------- */
public static IProject getAssociatedProject(IEditorInput input) {
if(input == null) {
return null;
}
IResource resource = getAssociatedResource(input);
if(resource != null) {
return resource.getProject();
}
return null;
}
public static IResource getAssociatedResource(IEditorInput input) {
if(input == null) {
return null;
}
if(input instanceof IFileEditorInput) {
return ((IFileEditorInput) input).getFile();
}
IResource resource = (IResource) input.getAdapter(IResource.class);
if(resource != null) {
return resource;
}
return (IProject) input.getAdapter(IProject.class);
}
public static IFile getAssociatedFile(IEditorInput editorInput) {
// if (editorInput instanceof IFileEditorInput) {
// return ((IFileEditorInput) editorInput).getFile();
// }
return ResourceUtil.getFile(editorInput);
}
/** Get a resource related to the input of this editor, or null if none. */
public static IFile findFileOfEditor(IEditorPart editor) {
return getAssociatedFile(editor.getEditorInput());
}
public static IEditorInput getBestEditorInputForLoc(Location fileLoc) {
return getBestEditorInputForUri(fileLoc.toUri());
}
public static IEditorInput getBestEditorInputForUri(URI uri) {
return getBestEditorInputForUri(uri, IResource.NONE);
}
public static IEditorInput getBestEditorInputForUri(URI uri, int memberFlags) {
IFile[] files = ResourceUtils.getWorkspaceRoot().findFilesForLocationURI(uri, memberFlags);
if(files.length != 0) {
// As an improvement, if there is more than one file, we could try to see which one is more relevant
// instead of just using the first one.
IFile file = files[0];
return new FileEditorInput(file);
} else {
//file not in workspace
IFileStore fileOnLocalDisk = EFS.getLocalFileSystem().getStore(uri);
return new FileStoreEditorInput(fileOnLocalDisk);
}
}
public static Path getFilePathFromEditorInput(IEditorInput editorInput) {
IURIEditorInput uriEditorInput;
if(editorInput instanceof IURIEditorInput) {
uriEditorInput = (IURIEditorInput) editorInput;
} else {
uriEditorInput = (IURIEditorInput) editorInput.getAdapter(IURIEditorInput.class);
}
if(uriEditorInput != null && uriEditorInput.getURI() != null) {
try {
return Paths.get(uriEditorInput.getURI());
} catch (Exception e) {
}
}
if(editorInput instanceof IStorageEditorInput) {
IStorageEditorInput storageEditorInput = (IStorageEditorInput) editorInput;
try {
IPath fullPath = storageEditorInput.getStorage().getFullPath();
if(fullPath != null) {
return fullPath.toFile().toPath();
}
} catch (CoreException ce) {
EclipseCore.logStatus(ce);
}
}
return null;
}
public static Location getLocationFromEditorInput(IEditorInput editorInput) throws CommonException {
Path filePath = getFilePathFromEditorInput(editorInput);
if (filePath == null) {
throw new CommonException("Error: Could not determine file path for editor.", null);
}
return Location.createValidLocation(filePath, "Invalid editorInput path: ");
}
public static Location getLocationOrNull(IEditorInput editorInput) {
try {
return getLocationFromEditorInput(editorInput);
} catch(CommonException e) {
return null;
}
}
public static Location getInputLocationOrNull(IEditorPart editor) {
Path inputPath = getFilePathFromEditorInput(editor.getEditorInput());
return Location.createValidOrNull(inputPath);
}
public static Location getInputLocation(IEditorPart editor) throws CommonException {
Location inputLocationOrNull = getInputLocationOrNull(editor);
if(inputLocationOrNull == null) {
throw new CommonException("Error, invalid location for editor input.");
}
return inputLocationOrNull;
}
/* ----------------- Editor opening utils ----------------- */
public static enum OpenNewEditorMode { ALWAYS, TRY_REUSING_EXISTING, NEVER }
public static IEditorPart openEditor(IEditorInput newInput, String editorId) throws PartInitException {
return openEditor(newInput, editorId, false);
}
public static IEditorPart openEditor(IEditorInput newInput, String editorId, boolean reuseExisitingEditor)
throws PartInitException {
IWorkbenchPage page = WorkbenchUtils.getActiveWorkbenchWindow().getActivePage();
int matchFlags = reuseExisitingEditor ? IWorkbenchPage.MATCH_INPUT : IWorkbenchPage.MATCH_NONE;
return page.openEditor(newInput, editorId, true, matchFlags);
}
public static ITextEditor openTextEditorAndSetSelection(String editorId, IEditorInput newInput,
SourceRange sourceRange) throws CoreException {
return openTextEditorAndSetSelection(null, editorId, newInput, OpenNewEditorMode.ALWAYS, sourceRange);
}
public static ITextEditor openTextEditorAndSetSelection(ITextEditor currentEditor, String editorId,
IEditorInput newInput, OpenNewEditorMode openNewEditor, SourceRange selectionRange)
throws PartInitException, CoreException {
ITextEditor editor = openTextEditor(currentEditor, editorId, newInput, openNewEditor);
if(selectionRange != null) {
setEditorSelection(editor, selectionRange);
}
return editor;
}
public static ITextEditor openTextEditor(ITextEditor currentEditor, String editorId, IEditorInput newInput,
OpenNewEditorMode openNewEditor) throws PartInitException, CoreException {
IWorkbenchPage page;
if(currentEditor == null) {
page = WorkbenchUtils.getActivePage();
openNewEditor = OpenNewEditorMode.ALWAYS;
} else {
page = currentEditor.getEditorSite().getWorkbenchWindow().getActivePage();
}
if(openNewEditor == OpenNewEditorMode.NEVER) {
if(currentEditor.getEditorInput().equals(newInput)) {
return currentEditor;
} else if(currentEditor instanceof IReusableEditor) {
IReusableEditor reusableEditor = (IReusableEditor) currentEditor;
reusableEditor.setInput(newInput);
return currentEditor;
} else {
openNewEditor = OpenNewEditorMode.ALWAYS;
}
}
int matchFlags = openNewEditor == OpenNewEditorMode.ALWAYS ?
IWorkbenchPage.MATCH_NONE : IWorkbenchPage.MATCH_INPUT | IWorkbenchPage.MATCH_ID;
IEditorPart editor = page.openEditor(newInput, editorId, true, matchFlags);
ITextEditor targetEditor = tryCast(editor, ITextEditor.class);
if(targetEditor == null) {
throw EclipseCore.createCoreException("Not a text editor", null);
}
return targetEditor;
}
/* ----------------- ----------------- */
public static void setStatusLineErrorMessage(ITextEditor editor, String message, Image image) {
IEditorStatusLine statusLine= (IEditorStatusLine)editor.getAdapter(IEditorStatusLine.class);
if(statusLine != null) {
statusLine.setMessage(true, message, image);
}
}
public static SourceRange getSelectedRange(ITextViewer viewer) {
Point selectedRange = viewer.getSelectedRange();
return new SourceRange(selectedRange.x, selectedRange.y);
}
/* ----------------- JDT ----------------- */
/**
* Copy of {@link org.eclipse.jface.text.source.MatchingCharacterPainter#getSignedSelection()}
*/
public static final IRegion getSignedSelection(ITextViewer sourceViewer) {
Point viewerSelection= sourceViewer.getSelectedRange();
StyledText text= sourceViewer.getTextWidget();
Point selection= text.getSelectionRange();
if (text.getCaretOffset() == selection.x) {
viewerSelection.x= viewerSelection.x + viewerSelection.y;
viewerSelection.y= -viewerSelection.y;
}
return new Region(viewerSelection.x, viewerSelection.y);
}
}