In progress: [ Issue 44 ] Add ability to hyperlink to imported files https://code.google.com/p/protobuf-dt/issues/detail?id=44
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/ProtobufUiModule.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/ProtobufUiModule.java index 0ada389..a006703 100644 --- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/ProtobufUiModule.java +++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/ProtobufUiModule.java
@@ -10,6 +10,7 @@ import static com.google.inject.name.Names.named; +import org.eclipse.jface.text.hyperlink.IHyperlinkDetector; import org.eclipse.ui.plugin.AbstractUIPlugin; import org.eclipse.ui.views.contentoutline.IContentOutlinePage; import org.eclipse.xtext.ui.editor.IXtextEditorCallback; @@ -18,6 +19,7 @@ import com.google.eclipse.protobuf.scoping.IFileUriResolver; import com.google.eclipse.protobuf.ui.builder.AutoAddNatureEditorCallback; +import com.google.eclipse.protobuf.ui.editor.ProtobufHyperlinkDetector; import com.google.eclipse.protobuf.ui.outline.LinkWithEditor; import com.google.eclipse.protobuf.ui.outline.ProtobufOutlinePage; import com.google.eclipse.protobuf.ui.preferences.compiler.CompilerPreferenceStoreInitializer; @@ -40,6 +42,10 @@ return ProtobufOutlinePage.class; } + @Override public Class<? extends IHyperlinkDetector> bindIHyperlinkDetector() { + return ProtobufHyperlinkDetector.class; + } + @Override public Class<? extends IXtextEditorCallback> bindIXtextEditorCallback() { return AutoAddNatureEditorCallback.class; } @@ -58,12 +64,12 @@ public void configurePathsPreferencesInitializer(Binder binder) { configurePreferenceInitializer(binder, "pathsPreferences", PathsPreferenceStoreInitializer.class); } - + private void configurePreferenceInitializer(Binder binder, String name, Class<? extends IPreferenceStoreInitializer> initializerType) { binder.bind(IPreferenceStoreInitializer.class).annotatedWith(named(name)).to(initializerType); } - + public void configureFileUriResolver(Binder binder) { binder.bind(IFileUriResolver.class).to(FileUriResolver.class); }
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/editor/ImportHyperlink.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/editor/ImportHyperlink.java new file mode 100644 index 0000000..78f284e --- /dev/null +++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/editor/ImportHyperlink.java
@@ -0,0 +1,58 @@ +/* + * Copyright (c) 2011 Google Inc. + * + * 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 + */ + +package com.google.eclipse.protobuf.ui.editor; + +import org.eclipse.emf.common.util.URI; +import org.eclipse.jface.text.IRegion; +import org.eclipse.jface.text.hyperlink.IHyperlink; + +/** + * A hyperlink for imported .proto files. + * + * @author alruiz@google.com (Alex Ruiz) + */ +class ImportHyperlink implements IHyperlink { + + private final URI importUri; + private final String uriText; + private final IRegion region; + + ImportHyperlink(URI importUri, String uriText, IRegion region) { + this.importUri = importUri; + this.uriText = uriText; + this.region = region; + } + + public IRegion getHyperlinkRegion() { + return region; + } + + public String getTypeLabel() { + return "type"; + } + + public String getHyperlinkText() { + return "text"; + } + + public void open() { + String scheme = importUri.scheme(); + if ("platform".equals(scheme)) openFromWorkspace(); + if ("file".equals(scheme)) openFromFileSystem(); + } + + private void openFromWorkspace() { + System.out.println("open from Workspace"); + } + + private void openFromFileSystem() { + System.out.println("open from file system"); + } +}
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/editor/ProtobufHyperlinkDetector.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/editor/ProtobufHyperlinkDetector.java new file mode 100644 index 0000000..2d29674 --- /dev/null +++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/editor/ProtobufHyperlinkDetector.java
@@ -0,0 +1,67 @@ +/* + * Copyright (c) 2011 Google Inc. + * + * 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 + */ +package com.google.eclipse.protobuf.ui.editor; + +import static org.eclipse.emf.common.util.URI.createURI; + +import org.eclipse.emf.ecore.EObject; +import org.eclipse.jface.text.*; +import org.eclipse.jface.text.hyperlink.IHyperlink; +import org.eclipse.jface.text.hyperlink.IHyperlinkDetector; +import org.eclipse.xtext.CrossReference; +import org.eclipse.xtext.resource.EObjectAtOffsetHelper; +import org.eclipse.xtext.resource.XtextResource; +import org.eclipse.xtext.ui.editor.hyperlinking.DefaultHyperlinkDetector; +import org.eclipse.xtext.ui.editor.model.IXtextDocument; +import org.eclipse.xtext.util.concurrent.IUnitOfWork; + +import com.google.eclipse.protobuf.protobuf.Import; +import com.google.inject.Inject; + +/** + * Represents an implementation of interface <code>{@link IHyperlinkDetector}</code> to find and convert + * {@link CrossReference elements}, at a given location, to {@code IHyperlink}. + * + * @author alruiz@google.com (Alex Ruiz) + */ +public class ProtobufHyperlinkDetector extends DefaultHyperlinkDetector { + + @Inject private EObjectAtOffsetHelper eObjectAtOffsetHelper; + + @Override public IHyperlink[] detectHyperlinks(ITextViewer textViewer, final IRegion region, + final boolean canShowMultipleHyperlinks) { + IXtextDocument document = (IXtextDocument)textViewer.getDocument(); + IHyperlink[] importHyperlinks = importHyperlinks(document, region); + if (importHyperlinks != null) return importHyperlinks; + return document.readOnly(new IUnitOfWork<IHyperlink[], XtextResource>() { + public IHyperlink[] exec(XtextResource resource) { + return getHelper().createHyperlinksByOffset(resource, region.getOffset(), canShowMultipleHyperlinks); + } + }); + } + + private IHyperlink[] importHyperlinks(final IXtextDocument document, final IRegion region) { + return document.readOnly(new IUnitOfWork<IHyperlink[], XtextResource>() { + public IHyperlink[] exec(XtextResource resource) { + EObject resolved = eObjectAtOffsetHelper.resolveElementAt(resource, region.getOffset()); + if (!(resolved instanceof Import)) return null; + Import anImport = (Import) resolved; + try { + int lineNumber = document.getLineOfOffset(region.getOffset()); + int lineLength = document.getLineLength(lineNumber); + document.get(region.getOffset(), lineLength - region.getOffset()); + } catch (BadLocationException e) { + } + String importUri = anImport.getImportURI(); + IHyperlink hyperlink = new ImportHyperlink(createURI(importUri), importUri, region); + return new IHyperlink[] { hyperlink }; + } + }); + } +}