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