/*******************************************************************************
* Copyright (c) 2007 IBM Corporation.
* 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:
* Robert Fuhrer (rfuhrer@watson.ibm.com) - initial API and implementation
*******************************************************************************/
package org.eclipse.imp.editor;
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.imp.runtime.RuntimePlugin;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.Region;
import org.eclipse.jface.text.hyperlink.IHyperlink;
import org.eclipse.ui.IEditorDescriptor;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.ide.IDE;
import org.eclipse.ui.part.FileEditorInput;
/**
* Common class to represent a hyperlink to a given target location.
*
* @author rfuhrer
*/
public final class TargetLink implements IHyperlink {
private final String fText;
private final Object fTarget;
private final int fStart;
private final int fLength;
private final int fTargetStart;
private final int fTargetLength;
private IRegionSelectionService fSelectionService;
/**
* @param text
* @param srcStart
* @param srcLength
* @param target a workspace-relative or filesystem-absolute IPath to the file,
* if 'editor' is null; otherwise, an object that indicates the particular target within the source file
* @param targetStart
* @param targetLength
* @param editor may be null, if the target is in another compilation unit
*/
public TargetLink(String text, int srcStart, int srcLength, Object target, int targetStart, int targetLength, IRegionSelectionService selService) {
fText= text;
fStart= srcStart;
fTarget= target;
fLength= srcLength;
fTargetStart= targetStart;
fTargetLength= targetLength;
fSelectionService= selService;
}
public IRegion getHyperlinkRegion() {
return new Region(fStart, fLength);
}
public String getTypeLabel() {
return fTarget.getClass().getName();
}
public String getHyperlinkText() {
return new String(fText);
}
public void open() {
if (fSelectionService == null) {
// Either we're opening up a new editor, or there's an existing one open on the target file.
// Either way, get a handle to an IEditorPart for the target file, and try to get an
// IRegionSelectionService interface on it.
if (!(fTarget instanceof IPath)) {
RuntimePlugin.getInstance().writeErrorMsg("Unable to link to a target of type other than IPath: " + fTarget.getClass().getName());
return;
}
final IPath targetPath= (IPath) fTarget;
IEditorDescriptor ed= PlatformUI.getWorkbench().getEditorRegistry().getDefaultEditor(targetPath.lastSegment());
IWorkbenchWindow activeWindow= PlatformUI.getWorkbench().getActiveWorkbenchWindow();
IWorkbenchPage activePage= activeWindow.getActivePage();
if (ed == null) {
MessageDialog.openError(activeWindow.getShell(), "Error", "No editor defined for target file "
+ targetPath.toPortableString());
return;
}
IWorkspaceRoot wsRoot= ResourcesPlugin.getWorkspace().getRoot();
IPath wsLoc= wsRoot.getLocation();
IEditorPart editor;
// Abortive attempt to support links to class files embedded in jars (e.g., Java rt.jar).
// if (targetPath.toPortableString().endsWith(".class")) {
// IFile jarFile= null; // Can't get an IFile for something not in the workspace... and rt.jar usually isn't...
// // Anyway, we'll have to use something other than a plain IFileEditorInput.
// // JDT has IClassFileEditorInput, but it's internal... Hmmm...
// JavaCore.createClassFileFrom(jarFile);
// } else
try {
boolean targetPathHasWSPrefix= wsLoc.isPrefixOf(targetPath);
if (targetPathHasWSPrefix || wsRoot.getFile(targetPath).exists()) {
IFile file= wsRoot.getFile(targetPathHasWSPrefix ? targetPath.removeFirstSegments(wsLoc.segmentCount()) : targetPath);
IEditorInput editorInput= new FileEditorInput(file);
editor= activePage.openEditor(editorInput, ed.getId());
} else {
// if (targetPath.isAbsolute() && !wsLoc.isPrefixOf(targetPath)) {
// http://wiki.eclipse.org/index.php/FAQ_How_do_I_open_an_editor_on_a_file_outside_the_workspace%3F
IFileStore fileStore = EFS.getLocalFileSystem().getStore(targetPath);
editor= IDE.openEditorOnFileStore(activePage, fileStore);
}
} catch (PartInitException e) {
RuntimePlugin.getInstance().logException(e.getLocalizedMessage(), e);
return;
}
// Don't assume the target editor is a text editor; the target might be
// in a class file or another kind of binary file.
if (editor instanceof IRegionSelectionService)
fSelectionService= (IRegionSelectionService) editor;
else
fSelectionService= (IRegionSelectionService) editor.getAdapter(IRegionSelectionService.class);
}
if (fSelectionService != null)
fSelectionService.selectAndReveal(fTargetStart, fTargetLength);
}
}