Index: editor/manifest.mf =================================================================== RCS file: /cvs/editor/manifest.mf,v retrieving revision 1.61 diff -u -r1.61 manifest.mf --- editor/manifest.mf 12 Jan 2005 07:34:41 -0000 1.61 +++ editor/manifest.mf 18 Jan 2005 08:49:14 -0000 @@ -4,4 +4,5 @@ OpenIDE-Module-Install: org/netbeans/modules/editor/EditorModule.class OpenIDE-Module-Specification-Version: 1.18 OpenIDE-Module-Layer: org/netbeans/modules/editor/resources/layer.xml +OpenIDE-Module-Module-Dependencies: org.netbeans.modules.editor.lib/1 = @BUILD_NUMBER_SUBST@, org.netbeans.modules.editor.fold/1, org.netbeans.modules.editor.lib/1, org.netbeans.modules.editor.util/1, org.openidex.util/3, org.openide.loaders > 4.11 Index: editor/arch/arch-editor.xml =================================================================== RCS file: /cvs/editor/arch/arch-editor.xml,v retrieving revision 1.18 diff -u -r1.18 arch-editor.xml --- editor/arch/arch-editor.xml 13 Dec 2004 16:18:10 -0000 1.18 +++ editor/arch/arch-editor.xml 18 Jan 2005 08:49:14 -0000 @@ -678,7 +678,12 @@ --> - No. + org.netbeans.modules.editor.hyperlink.LayerHyperlinkProviderManager + is registered using META-INF/services. +
+ It is an extension of org.netbeans.lib.editor.hyperlink.HyperlinkProviderManager + allowing to instantiate the org.netbeans.lib.editor.hyperlink.spi.HyperlinkProvider + instances from the xml layer of the System FS for particular mime-types.
@@ -983,6 +988,17 @@

Please see layer.xml for further details.

+ +

+ The org.netbeans.lib.editor.hyperlink.spi.HyperlinkProvider + instances can be registered by editors for the particular mime-types + into Editors/|mime-type|/HyperlinkProviders. +
+ There can be multiple providers registered and their order + will be respected during querying by the hyperlinking infrastructure + (first provider which recognizes the given offset as a hyperlinking point + will be used). +

@@ -1079,8 +1095,24 @@ The editor functionality are mainly implementations of the Swing Text package APIs plus extension features such as Syntax Coloring, Code Completion, Word Matching, Abbreviations or Macros. -There are no official APIs yet but the Code Folding API -and other extensions APIs are being formed. + +

Hyperlink SPI

+ + Hyperlink SPI in org.netbeans.lib.editor.hyperlink.spi + allows the editors for a particular mime-type to respond to the situation + when a user hovers over the text with a Ctrl key pressed. + + +
+The Hyperlink SPI resolves whether the text under the mouse is hyperlink-able +and defines the span of the hyperlink and the action to be performed +when the user clicks on the hyperlink. +
+The SPI consists of a single HyperlinkProvider +class that contains a javadoc with instructions +about how to register the implementation in the xml layer for the given +mime-type (mentioned in the layer section here as well). + Index: editor/lib/manifest.mf =================================================================== RCS file: /cvs/editor/lib/manifest.mf,v retrieving revision 1.4 diff -u -r1.4 manifest.mf --- editor/lib/manifest.mf 12 Jan 2005 07:34:41 -0000 1.4 +++ editor/lib/manifest.mf 18 Jan 2005 08:49:14 -0000 @@ -2,4 +2,5 @@ OpenIDE-Module: org.netbeans.modules.editor.lib/1 OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/editor/lib/Bundle.properties OpenIDE-Module-Specification-Version: 1.3 +OpenIDE-Module-Implementation-Version: @BUILD_NUMBER_SUBST@ Index: editor/lib/nbproject/project.xml =================================================================== RCS file: /cvs/editor/lib/nbproject/project.xml,v retrieving revision 1.1 diff -u -r1.1 project.xml --- editor/lib/nbproject/project.xml 1 Jul 2004 14:32:15 -0000 1.1 +++ editor/lib/nbproject/project.xml 18 Jan 2005 08:49:14 -0000 @@ -53,6 +53,7 @@ org.netbeans.editor.ext.plain org.netbeans.editor.view.spi org.netbeans.lib.editor.view + org.netbeans.lib.editor.hyperlink.spi Index: editor/libsrc/org/netbeans/editor/BaseKit.java =================================================================== RCS file: /cvs/editor/libsrc/org/netbeans/editor/BaseKit.java,v retrieving revision 1.126 diff -u -r1.126 BaseKit.java --- editor/libsrc/org/netbeans/editor/BaseKit.java 8 Dec 2004 13:26:13 -0000 1.126 +++ editor/libsrc/org/netbeans/editor/BaseKit.java 18 Jan 2005 08:49:15 -0000 @@ -503,6 +503,9 @@ c.enableInputMethods(enableIM); executeInstallActions(c); + + c.putClientProperty("hyperlink-operation", + org.netbeans.lib.editor.hyperlink.HyperlinkOperation.create(c, getContentType())); } protected void executeInstallActions(JEditorPane c) { Index: editor/libsrc/org/netbeans/lib/editor/hyperlink/DefaultHyperlinkProviderManager.java =================================================================== RCS file: editor/libsrc/org/netbeans/lib/editor/hyperlink/DefaultHyperlinkProviderManager.java diff -N editor/libsrc/org/netbeans/lib/editor/hyperlink/DefaultHyperlinkProviderManager.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ editor/libsrc/org/netbeans/lib/editor/hyperlink/DefaultHyperlinkProviderManager.java 18 Jan 2005 08:49:15 -0000 @@ -0,0 +1,72 @@ +/* + * Sun Public License Notice + * + * The contents of this file are subject to the Sun Public License + * Version 1.0 (the "License"). You may not use this file except in + * compliance with the License. A copy of the License is available at + * http://www.sun.com/ + * + * The Original Code is NetBeans. The Initial Developer of the Original + * Code is Sun Microsystems, Inc. Portions Copyright 1997-2004 Sun + * Microsystems, Inc. All Rights Reserved. + */ + +package org.netbeans.lib.editor.hyperlink; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.netbeans.lib.editor.hyperlink.spi.HyperlinkProvider; + +/** + * Default implementation of the provider manager. + *
+ * The default empty list of hyperlink providers + * can be extended by registering new ones for each mimetype. + * + * @author Miloslav Metelka + */ +public class DefaultHyperlinkProviderManager extends HyperlinkProviderManager { + + private Map mimeType2providerList = new HashMap(); + + /** + * Register a new HyperlinkProvider. + * + * @param mimeType mime-type for which the provider is being registered. + * @param provider provider to register. + */ + public synchronized void addHyperlinkProvider(String mimeType, HyperlinkProvider provider) { + getProviderList(mimeType, true).add(provider); + } + + /** + * Unregister a HyperlinkProvider. + * + * @param mimeType mime-type for which the provider is being unregistered. + * @param provider provider to unregister. + */ + public synchronized void removeHyperlinkProvider(String mimeType, HyperlinkProvider provider) { + List providerList = getProviderList(mimeType, false); + if (providerList != null) { + providerList.remove(provider); + } + } + + public synchronized List/**/ getHyperlinkProviders(String mimeType) { + List providers = getProviderList(mimeType, false); + return (providers != null) ? providers : Collections.EMPTY_LIST; + } + + private List getProviderList(String mimeType, boolean forceCreation) { + List providerList = (List)mimeType2providerList.get(mimeType); + if (providerList == null && forceCreation) { + providerList = new ArrayList(); + mimeType2providerList.put(mimeType, providerList); + } + return providerList; + } + +} Index: editor/libsrc/org/netbeans/lib/editor/hyperlink/HyperlinkOperation.java =================================================================== RCS file: editor/libsrc/org/netbeans/lib/editor/hyperlink/HyperlinkOperation.java diff -N editor/libsrc/org/netbeans/lib/editor/hyperlink/HyperlinkOperation.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ editor/libsrc/org/netbeans/lib/editor/hyperlink/HyperlinkOperation.java 18 Jan 2005 08:49:15 -0000 @@ -0,0 +1,302 @@ +/* + * Sun Public License Notice + * + * The contents of this file are subject to the Sun Public License + * Version 1.0 (the "License"). You may not use this file except in + * compliance with the License. A copy of the License is available at + * http://www.sun.com/ + * + * The Original Code is NetBeans. The Initial Developer of the Original + * Code is Sun Microsystems, Inc. Portions Copyright 1997-2004 Sun + * Microsystems, Inc. All Rights Reserved. + */ + +package org.netbeans.lib.editor.hyperlink; + +import java.awt.Color; +import java.awt.Cursor; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.event.MouseMotionListener; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import javax.swing.SwingUtilities; +import javax.swing.text.Document; +import javax.swing.text.JTextComponent; +import org.netbeans.editor.*; +import org.netbeans.lib.editor.hyperlink.spi.HyperlinkProvider; + +/** + * + * @author Jan Lahoda + */ +public class HyperlinkOperation implements MouseListener, MouseMotionListener, PropertyChangeListener, KeyListener { + + private JTextComponent component; + private Document currentDocument; + private HyperlinkLayer layer; + private String mimeType; + private boolean componentHadMouseCursor; + private Cursor oldComponentsMouseCursor; + private boolean hyperlinkUp; + + public static HyperlinkOperation create(JTextComponent component, String mimeType) { + return new HyperlinkOperation(component, mimeType); + } + + /** Creates a new instance of HoveringImpl */ + private HyperlinkOperation(JTextComponent component, String mimeType) { + this.component = component; + this.mimeType = mimeType; + this.oldComponentsMouseCursor = null; + this.componentHadMouseCursor = false; + this.hyperlinkUp = false; + + component.addPropertyChangeListener("document", this); + } + + private void documentUpdated() { + currentDocument = component.getDocument(); + + if (currentDocument instanceof BaseDocument) { + BaseDocument bd = (BaseDocument) currentDocument; + + bd.addLayer(layer = new HyperlinkLayer(), 1100); + + component.addMouseListener(this); + component.addMouseMotionListener(this); + component.addKeyListener(this); + } + } + + public void mouseMoved(MouseEvent e) { + if ((e.getModifiersEx() & MouseEvent.CTRL_DOWN_MASK) == MouseEvent.CTRL_DOWN_MASK) { + int position = component.viewToModel(e.getPoint()); + + if (position < 0) { + unHyperlink(true); + + return ; + } + + performHyperlinking(position); + } else { + unHyperlink(true); + } + } + + public void mouseDragged(MouseEvent e) { + //ignored + } + + private void performHyperlinking(int position) { + HyperlinkProvider provider = findProvider(position); + + if (provider != null) { + int[] offsets = provider.getHyperlinkSpan(component.getDocument(), position); + + if (offsets != null) + makeHyperlink(offsets[0], offsets[1]); + } else { + unHyperlink(true); + } + } + + private void performAction(int position) { + HyperlinkProvider provider = findProvider(position); + + if (provider != null) { + provider.performClickAction(component.getDocument(), position); + } + } + + private HyperlinkProvider findProvider(int position) { + List/**/ providers = HyperlinkProviderManager.getDefault().getHyperlinkProviders(mimeType); + + for (Iterator/**/ i = providers.iterator(); i.hasNext(); ) { + HyperlinkProvider provider = (HyperlinkProvider) i.next(); + + if (provider.isHyperlinkPoint(component.getDocument(), position)) { + return provider; + } + } + + return null; + } + + private synchronized void makeHyperlink(final int start, final int end) { + boolean makeCursorSnapshot = true; + + if (hyperlinkUp) { + unHyperlink(false); + makeCursorSnapshot = false; + } + + hyperlinkUp = true; + + layer.hyperlinkStart = start; + layer.hyperlinkEnd = end; + + SwingUtilities.invokeLater(new Runnable() { + public void run() { + component.getUI().damageRange(component, start, end); + } + }); + + if (makeCursorSnapshot) { + if (componentHadMouseCursor = component.isCursorSet()) { + oldComponentsMouseCursor = component.getCursor(); + } else { + oldComponentsMouseCursor = null; + } + component.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); + } + } + + private synchronized void unHyperlink(boolean removeCursor) { + if (!hyperlinkUp) + return ; + + final int start = layer.hyperlinkStart; + final int end = layer.hyperlinkEnd; + + layer.hyperlinkStart = -1; + layer.hyperlinkEnd = -1; + + if (start != (-1) && end != (-1)) { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + component.getUI().damageRange(component, start, end); + } + }); + } + + if (componentHadMouseCursor && removeCursor) { + component.setCursor(oldComponentsMouseCursor); + componentHadMouseCursor = false; + oldComponentsMouseCursor = null; + } + + hyperlinkUp = false; + } + + public void propertyChange(PropertyChangeEvent evt) { + if (currentDocument != component.getDocument()) + documentUpdated(); + } + + public void keyTyped(KeyEvent e) { + //ignored + } + + public void keyReleased(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_CONTROL) + unHyperlink(true); + } + + public void keyPressed(KeyEvent e) { + //ignored + } + + public void mouseReleased(MouseEvent e) { + //ignored + } + + public void mousePressed(MouseEvent e) { + //ignored + } + + public void mouseExited(MouseEvent e) { + //ignored + } + + public void mouseEntered(MouseEvent e) { + //ignored + } + + public void mouseClicked(MouseEvent e) { + if ((e.getModifiersEx() & MouseEvent.CTRL_DOWN_MASK) == MouseEvent.CTRL_DOWN_MASK) { + int position = component.viewToModel(e.getPoint()); + + if (position < 0) { + return ; + } + + performAction(position); + } + } + + private static class HyperlinkLayer extends DrawLayer.AbstractLayer { + + private int hyperlinkStart = (-1); + private int hyperlinkEnd = (-1); + + public static final String NAME = "hyperlink-layer"; + + public static final int VISIBILITY = 1050; + + private boolean initialized = false; + + public HyperlinkLayer() { + super(NAME); + + this.initialized = false; + } + + private void checkDocument(Document doc) { + } + + public boolean extendsEOL() { + return true; + } + + public synchronized void init(final DrawContext ctx) { + if (!initialized) { + Document doc = ctx.getEditorUI().getDocument(); + + initialized = true; + checkDocument(doc); + } + + if (isActive()) + setNextActivityChangeOffset(hyperlinkStart); + } + + private boolean isActive() { + return hyperlinkStart != (-1) && hyperlinkEnd != (-1); + } + + public boolean isActive(DrawContext ctx, MarkFactory.DrawMark mark) { + return isActive(); + } + + private boolean isIn(int offset) { + return offset >= hyperlinkStart && offset < hyperlinkEnd; + } + + private static Coloring hoverColoring = new Coloring(null, 0, Color.BLUE, null, Color.BLUE, null); + + public void updateContext(DrawContext ctx) { + if (!isActive()) + return ; + + int currentOffset = ctx.getFragmentOffset(); + + if (isIn(currentOffset)) { + hoverColoring.apply(ctx); + + if (isIn(currentOffset + ctx.getFragmentLength())) + setNextActivityChangeOffset(currentOffset + ctx.getFragmentLength()); + } + } + + } + +} Index: editor/libsrc/org/netbeans/lib/editor/hyperlink/HyperlinkProviderManager.java =================================================================== RCS file: editor/libsrc/org/netbeans/lib/editor/hyperlink/HyperlinkProviderManager.java diff -N editor/libsrc/org/netbeans/lib/editor/hyperlink/HyperlinkProviderManager.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ editor/libsrc/org/netbeans/lib/editor/hyperlink/HyperlinkProviderManager.java 18 Jan 2005 08:49:15 -0000 @@ -0,0 +1,71 @@ +/* + * Sun Public License Notice + * + * The contents of this file are subject to the Sun Public License + * Version 1.0 (the "License"). You may not use this file except in + * compliance with the License. A copy of the License is available at + * http://www.sun.com/ + * + * The Original Code is NetBeans. The Initial Developer of the Original + * Code is Sun Microsystems, Inc. Portions Copyright 1997-2004 Sun + * Microsystems, Inc. All Rights Reserved. + */ + +package org.netbeans.lib.editor.hyperlink; + +import java.util.List; +import org.openide.util.Lookup; + +/** + * This class provides a list of HyperlinkProvider(s) for a given mime type. + *
+ * This class is first searched in the Lookup. If no implementation + * is found then a default implementation {@link DefaultHyperlinkProviderManager} + * is constructed. + * + * Besides the default implementation there is + * {@link org.netbeans.modules.editor.hyperlink.LayerHyperlinkProviderManager} + * in the editor module (non-library part) + * which reads the hyperlink providers for the mime-types + * from the xml layer in the System FS. + *
+ * These two existing implementations should suffice for most uses. + * + * @author Jan Lahoda + */ +public abstract class HyperlinkProviderManager { + + private static HyperlinkProviderManager defaultManager; + + /** + * Find the default hyperlink provider manager in the lookup (or construct + * a simple default implementation if not found). + * + * @return non-null manager. + */ + public static synchronized HyperlinkProviderManager getDefault() { + if (defaultManager == null) { + defaultManager = createDefault(); + } + return defaultManager; + } + + private static HyperlinkProviderManager createDefault() { + HyperlinkProviderManager mgr = (HyperlinkProviderManager)Lookup.getDefault(). + lookup(HyperlinkProviderManager.class); + + if (mgr == null) { // not found in lookup -> use default + mgr = new DefaultHyperlinkProviderManager(); + } + return mgr; + } + + /** + * Provide List of HyperlinkProvider(s) for a given mime type. + * + * @param mimeType mime type to test + * @param List of HyperlinkProvider(s) for a given mime type. + */ + public abstract List/**/ getHyperlinkProviders(String mimeType); + +} Index: editor/libsrc/org/netbeans/lib/editor/hyperlink/spi/HyperlinkProvider.java =================================================================== RCS file: editor/libsrc/org/netbeans/lib/editor/hyperlink/spi/HyperlinkProvider.java diff -N editor/libsrc/org/netbeans/lib/editor/hyperlink/spi/HyperlinkProvider.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ editor/libsrc/org/netbeans/lib/editor/hyperlink/spi/HyperlinkProvider.java 18 Jan 2005 08:49:15 -0000 @@ -0,0 +1,94 @@ +/* + * Sun Public License Notice + * + * The contents of this file are subject to the Sun Public License + * Version 1.0 (the "License"). You may not use this file except in + * compliance with the License. A copy of the License is available at + * http://www.sun.com/ + * + * The Original Code is NetBeans. The Initial Developer of the Original + * Code is Sun Microsystems, Inc. Portions Copyright 1997-2004 Sun + * Microsystems, Inc. All Rights Reserved. + */ + +package org.netbeans.lib.editor.hyperlink.spi; + +import javax.swing.text.Document; + +/** + * This interface should be implemented by anyone who whats to provide hyperlinking + * functionality in the source code. + *
+ * There should be one provider instance per mime-type. + * Its methods are called for all the opened editors of the given mime-type + * where the hyperlinking functionality gets requested. + * + *

+ * The providers need to be registered. + * For NetBeans IDE, the default approach is to use System FileSystem. + *
+ * The HyperlinkProvider(s) should be registered as ".instance" objects under + * Editors/<mime-type>/HyperlinkProviders directory. + *

+ * + *

+ * Please see {@link org.netbeans.lib.editor.hyperlink.HyperlinkProviderManager} + * for more details. + *

+ * + *

+ * Note: there is no assurance on the order of calling of the methods in this class. + * The callers may call the methods in any order and even do not call some of these methods + * at all. + *

+ * + * @author Jan Lahoda + * @since 1.0 + */ +public interface HyperlinkProvider { + + /** + * Should determine whether there should be a hyperlink on the given offset + * in the given document. May be called any number of times for given parameters. + *
+ * This method is called from event dispatch thread. + * It should run very fast as it is called very often. + * + * @param doc document on which to operate. + * @param offset >=0 offset to test (it generally should be offset < doc.getLength(), but + * the implementations should not depend on it) + * @return true if the provided offset should be in a hyperlink + * false otherwise + */ + boolean isHyperlinkPoint(Document doc, int offset); + + /** + * Should determine the span of hyperlink on given offset. Generally, if + * isHyperlinkPoint returns true for a given parameters, this class should + * return a valid span, but it is not strictly required. + *
+ * This method is called from event dispatch thread. + * This method should run very fast as it is called very often. + * + * @param doc document on which to operate. + * @param offset >=0 offset to test (it generally should be offset < doc.getLength(), but + * the implementations should not depend on it) + * @return a two member array which contains starting and ending offset of a hyperlink + * that should be on a given offset + */ + int[] getHyperlinkSpan(Document doc, int offset); + + /** + * The implementor should perform an action + * corresponding to clicking on the hyperlink on the given offset. The + * nature of the action is given by the nature of given hyperlink, but + * generally should open some resource or move cursor + * to certain place in the current document. + * + * @param doc document on which to operate. + * @param offset >=0 offset to test (it generally should be offset < doc.getLength(), but + * the implementations should not depend on it) + */ + void performClickAction(Document doc, int offset); + +} Index: editor/src/META-INF/services/org.netbeans.lib.editor.hyperlink.HyperlinkProviderManager =================================================================== RCS file: editor/src/META-INF/services/org.netbeans.lib.editor.hyperlink.HyperlinkProviderManager diff -N editor/src/META-INF/services/org.netbeans.lib.editor.hyperlink.HyperlinkProviderManager --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ editor/src/META-INF/services/org.netbeans.lib.editor.hyperlink.HyperlinkProviderManager 18 Jan 2005 08:49:15 -0000 @@ -0,0 +1 @@ +org.netbeans.modules.editor.hyperlink.LayerHyperlinkProviderManager Index: editor/src/org/netbeans/modules/editor/EditorModule.java =================================================================== RCS file: /cvs/editor/src/org/netbeans/modules/editor/EditorModule.java,v retrieving revision 1.112 diff -u -r1.112 EditorModule.java --- editor/src/org/netbeans/modules/editor/EditorModule.java 17 Jan 2005 13:07:03 -0000 1.112 +++ editor/src/org/netbeans/modules/editor/EditorModule.java 18 Jan 2005 08:49:15 -0000 @@ -149,7 +149,7 @@ } catch (Throwable t) { t.printStackTrace(); } - + // Registration of the editor kits to JEditorPane // for (int i = 0; i < replacements.length; i++) { // JEditorPane.registerEditorKitForContentType( Index: editor/src/org/netbeans/modules/editor/hyperlink/LayerHyperlinkProviderManager.java =================================================================== RCS file: editor/src/org/netbeans/modules/editor/hyperlink/LayerHyperlinkProviderManager.java diff -N editor/src/org/netbeans/modules/editor/hyperlink/LayerHyperlinkProviderManager.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ editor/src/org/netbeans/modules/editor/hyperlink/LayerHyperlinkProviderManager.java 18 Jan 2005 08:49:15 -0000 @@ -0,0 +1,74 @@ +/* + * Sun Public License Notice + * + * The contents of this file are subject to the Sun Public License + * Version 1.0 (the "License"). You may not use this file except in + * compliance with the License. A copy of the License is available at + * http://www.sun.com/ + * + * The Original Code is NetBeans. The Initial Developer of the Original + * Code is Sun Microsystems, Inc. Portions Copyright 1997-2004 Sun + * Microsystems, Inc. All Rights Reserved. + */ + +package org.netbeans.modules.editor.hyperlink; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import org.netbeans.lib.editor.hyperlink.spi.HyperlinkProvider; +import org.netbeans.lib.editor.hyperlink.HyperlinkProviderManager; +import org.openide.ErrorManager; +import org.openide.filesystems.FileObject; +import org.openide.filesystems.Repository; +import org.openide.loaders.DataObject; +import org.openide.loaders.DataObjectNotFoundException; +import org.openide.loaders.FolderLookup; +import org.openide.util.Lookup; + +/** + * Finds hyperlink providers in the System FileSystem. The HyperlinkProvider(s) should + * be registered as ".instance" objects under Editors/<mime-type>/HyperlinkProviders + * directory. + * + * @author Jan Lahoda + */ +public final class LayerHyperlinkProviderManager extends HyperlinkProviderManager { + + private Lookup lookup; + + /** + * Creates a new instance of LayerHyperlinkProviderManager + */ + public LayerHyperlinkProviderManager() { + } + + public List/**/ getHyperlinkProviders(String mimeType) { + FileObject hyperlinkProvidersFolder = Repository.getDefault().getDefaultFileSystem(). + findResource("Editors/" + mimeType + "/HyperlinkProviders"); + + if (hyperlinkProvidersFolder!= null + && !hyperlinkProvidersFolder.isData() + && hyperlinkProvidersFolder.isValid() + && !hyperlinkProvidersFolder.isVirtual() + ) { + + try { + DataObject od = DataObject.find(hyperlinkProvidersFolder); + + if (od instanceof DataObject.Container) { + FolderLookup flookup = new FolderLookup((DataObject.Container) od); + + return Collections.unmodifiableList( + new ArrayList(flookup.getLookup().lookup( + new Lookup.Template(HyperlinkProvider.class)).allInstances())); + } + } catch (DataObjectNotFoundException e) { + ErrorManager.getDefault().notify(e); + } + } + + return Collections.EMPTY_LIST; + } + +} Index: ide/golden/impl-deps.txt =================================================================== RCS file: /cvs/ide/golden/impl-deps.txt,v retrieving revision 1.10 diff -u -r1.10 impl-deps.txt --- ide/golden/impl-deps.txt 12 Jan 2005 21:41:13 -0000 1.10 +++ ide/golden/impl-deps.txt 18 Jan 2005 08:49:16 -0000 @@ -2,6 +2,8 @@ REQUIRES org.netbeans.modules.xml.core/2 (ide) MODULE org.netbeans.modules.dbschema/1 (ide) REQUIRES org.netbeans.modules.db/1 (ide) +MODULE org.netbeans.modules.editor/3 (ide) + REQUIRES org.netbeans.modules.editor.lib/1 (ide) MODULE org.netbeans.modules.j2ee.ddloaders/1 (j2ee) REQUIRES org.netbeans.modules.j2ee.dd/1 (j2ee) REQUIRES org.netbeans.modules.j2ee.ejbjarproject (j2ee) Index: ide/golden/public-packages.txt =================================================================== RCS file: /cvs/ide/golden/public-packages.txt,v retrieving revision 1.11 diff -u -r1.11 public-packages.txt --- ide/golden/public-packages.txt 16 Jan 2005 19:05:44 -0000 1.11 +++ ide/golden/public-packages.txt 18 Jan 2005 08:49:16 -0000 @@ -143,6 +143,7 @@ org.netbeans.lib.cvsclient.request org.netbeans.lib.cvsclient.response org.netbeans.lib.cvsclient.util +org.netbeans.lib.editor.hyperlink.spi org.netbeans.lib.editor.view org.netbeans.modules.ant.freeform.spi org.netbeans.modules.ant.freeform.spi.support Index: java/editor/src/org/netbeans/modules/java/editor/hyperlink/JavaHyperlinkProvider.java =================================================================== RCS file: java/editor/src/org/netbeans/modules/java/editor/hyperlink/JavaHyperlinkProvider.java diff -N java/editor/src/org/netbeans/modules/java/editor/hyperlink/JavaHyperlinkProvider.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ java/editor/src/org/netbeans/modules/java/editor/hyperlink/JavaHyperlinkProvider.java 18 Jan 2005 08:49:18 -0000 @@ -0,0 +1,120 @@ +/* + * Sun Public License Notice + * + * The contents of this file are subject to the Sun Public License + * Version 1.0 (the "License"). You may not use this file except in + * compliance with the License. A copy of the License is available at + * http://www.sun.com/ + * + * The Original Code is NetBeans. The Initial Developer of the Original + * Code is Sun Microsystems, Inc. Portions Copyright 1997-2004 Sun + * Microsystems, Inc. All Rights Reserved. + */ + +package org.netbeans.modules.java.editor.hyperlink; + +import javax.swing.text.BadLocationException; +import javax.swing.text.Document; +import javax.swing.text.JTextComponent; +import org.netbeans.editor.BaseDocument; +import org.netbeans.editor.SyntaxSupport; +import org.netbeans.editor.TokenID; +import org.netbeans.editor.Utilities; +import org.netbeans.editor.ext.java.JavaTokenContext; +import org.netbeans.jmi.javamodel.ClassDefinition; +import org.netbeans.lib.editor.hyperlink.spi.HyperlinkProvider; +import org.openide.ErrorManager; +import org.netbeans.modules.editor.java.*; + + +/** + * Implementation of the hyperlink provider for java language. + *
+ * The hyperlinks are constructed for identifiers. + *
+ * The click action corresponds to performing the goto-declaration action. + * + * @author Jan Lahoda + */ +public final class JavaHyperlinkProvider implements HyperlinkProvider { + + /** Creates a new instance of JavaHyperlinkProvider */ + public JavaHyperlinkProvider() { + } + + public void performClickAction(Document originalDoc, int offset) { + if (!(originalDoc instanceof BaseDocument)) + return ; + + BaseDocument doc = (BaseDocument) originalDoc; + JTextComponent target = Utilities.getFocusedComponent(); + + if (target.getDocument() != doc) + return ; + + SyntaxSupport sup = doc.getSyntaxSupport(); + NbJavaJMISyntaxSupport nbJavaSup = (NbJavaJMISyntaxSupport)sup.get(NbJavaJMISyntaxSupport.class); + + JMIUtils jmiUtils = JMIUtils.get(doc); + + + Object item = null; + String itemDesc = null; + jmiUtils.beginTrans(false); + try { + item = jmiUtils.findItemAtCaretPos(target); + if (item instanceof NbJMIResultItem.VarResultItem) { + int pos = nbJavaSup.findLocalDeclarationPosition(((NbJMIResultItem.VarResultItem)item).getItemText(), target.getCaretPosition()); + target.setCaretPosition(pos); + } else { + if (item instanceof ClassDefinition) + item = JMIUtils.getSourceElementIfExists((ClassDefinition)item); + itemDesc = nbJavaSup.openSource(item, true); + } + } finally { + jmiUtils.endTrans(false); + } + } + + public boolean isHyperlinkPoint(Document doc, int offset) { + if (!(doc instanceof BaseDocument)) + return false; + + try { + BaseDocument bdoc = (BaseDocument) doc; + JTextComponent target = Utilities.getFocusedComponent(); + + if (target.getDocument() != bdoc) + return false; + + SyntaxSupport sup = bdoc.getSyntaxSupport(); + NbJavaJMISyntaxSupport nbJavaSup = (NbJavaJMISyntaxSupport)sup.get(NbJavaJMISyntaxSupport.class); + + TokenID token = nbJavaSup.getTokenID(offset); + + if (token == JavaTokenContext.IDENTIFIER) + return true; + + return false; + } catch (BadLocationException e) { + ErrorManager.getDefault().notify(e); + return false; + } + } + + public int[] getHyperlinkSpan(Document doc, int offset) { + if (!(doc instanceof BaseDocument)) + return null; + + try { + if (isHyperlinkPoint(doc, offset)) + return org.netbeans.editor.Utilities.getIdentifierBlock((BaseDocument) doc, offset); + else + return null; + } catch (BadLocationException e) { + ErrorManager.getDefault().notify(e); + return null; + } + } + +} Index: java/editor/src/org/netbeans/modules/java/editor/resources/layer.xml =================================================================== RCS file: /cvs/java/editor/src/org/netbeans/modules/java/editor/resources/layer.xml,v retrieving revision 1.2 diff -u -r1.2 layer.xml --- java/editor/src/org/netbeans/modules/java/editor/resources/layer.xml 12 Jan 2005 07:36:52 -0000 1.2 +++ java/editor/src/org/netbeans/modules/java/editor/resources/layer.xml 18 Jan 2005 08:49:18 -0000 @@ -135,6 +135,13 @@ + + + + + + +