blob: 9da10401581ae127fc151ec27ba7bab3fdbe4add [file] [log] [blame]
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>NetBeans Mark Occurrences Module Tutorial for NetBeans Platform 7.2</title>
<link rel="stylesheet" type="text/css" href="https://netbeans.org/netbeans.css"/>
<meta name="AUDIENCE" content="NBUSER"/>
<meta name="TYPE" content="ARTICLE"/>
<meta name="EXPIRES" content="N"/>
<meta name="developer" content="gwielenga@netbeans.org"/>
<meta name="indexed" content="y"/>
<meta name="description" content="A short guide to using Highlighting SPI."/>
<!-- Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. -->
<!-- Use is subject to license terms.-->
</head>
<body>
<h1>NetBeans Mark Occurrences Module Tutorial</h1>
<p>This tutorial demonstrates how to create a NetBeans module that highlights
all instances of a selected word in an HTML file, as shown below:</p>
<p><img src="../../images/tutorials/mark-occs/72/result-3.png" alt="result"/></p>
<p><b>Contents</b></p>
<p><img src="../../images/articles/72/netbeans-stamp.gif" class="stamp" width="114" height="114" alt="Content on this page applies to NetBeans IDE 7.2" title="Content on this page applies to NetBeans IDE 7.2"/></p>
<ul class="toc">
<li><a href="#intro">Introduction to Highlight Layers</a>
<ul>
<li><a href="#installing-sample">Getting to Know the Sample</a></li>
</ul>
</li>
<li><a href="#creatingthemoduleproject">Setting Up the Module Project</a></li>
<li><a href="#coding-module">Creating the Highlight Layer and Factory</a>
<ul>
<li><a href="#specifying">Specifying the Module's Dependencies</a></li>
<li><a href="#creating-highlight">Creating the Highlight Layer</a></li>
<li><a href="#creating-factory">Creating the Highlight Layer Factory</a></li>
</ul></li>
<li><a href="#building">Building and Installing the Module</a></li>
</ul>
<p><b>To follow this tutorial, you need the software and resources listed in the following
table.</b></p>
<table>
<tbody>
<tr>
<th class="tblheader" scope="col">Software or Resource</th>
<th class="tblheader" scope="col">Version Required</th>
</tr>
<tr>
<td class="tbltd1"><a href="https://netbeans.org/downloads/index.html">NetBeans IDE</a></td>
<td class="tbltd1">version 7.2</td>
</tr>
<tr>
<td class="tbltd1"><a href="http://java.sun.com/javase/downloads/index.jsp">Java Developer Kit (JDK)</a></td>
<td class="tbltd1">version 6 or above</td>
</tr>
</tbody>
</table>
<h2 class="tutorial"><a name="intro"></a>Introduction to Highlight Layers</h2>
<p>In this tutorial, you implement several classes provided by the
<a href="http://bits.netbeans.org/dev/javadoc/org-netbeans-modules-editor-lib2/org/netbeans/spi/editor/highlighting/package-summary.html">NetBeans Highlighting SPI</a>.
The two principle classes in this context are as follows:</p>
<ul>
<li><b><a href="http://bits.netbeans.org/dev/javadoc/org-netbeans-modules-editor-lib2/org/netbeans/spi/editor/highlighting/HighlightsLayer.html">Highlight Layer</a></b>.
Defines a set of highlights used for rendering a document.</li>
<li><b><a href="http://bits.netbeans.org/dev/javadoc/org-netbeans-modules-editor-lib2/org/netbeans/spi/editor/highlighting/HighlightsLayerFactory.html">Highlight Layer Factory</a></b>.
Defines a MIME-specific factory for creating highlight layers.</li>
</ul>
<p>The above two classes need to be registered in the module's <tt>layer.xml</tt> file,
within the editor folder of the relevant MIME-type.</p>
<!-- ===================================================================================== -->
<h2 class="tutorial"><a name="creatingthemoduleproject"></a>Setting up the Module Project</h2>
<p>Before you start writing the module, you have to make sure you
that your project is set up correctly. The IDE provides a wizard that sets up all the basic files
needed for a module.</p>
<div class="indent">
<ol>
<li>Choose File &gt; New Project (Ctrl+Shift+N). Under Categories, select NetBeans Modules.
Under Projects, select Module. Click Next.</li>
<li>In the Name and Location panel, type <tt>MarkHTMLOccurrences</tt> in the Project Name field.
Change the Project Location to any directory on your computer. Click Next.</li>
<li>In the Basic Module Configuration panel, type <tt>org.netbeans.modules.markhtmloccurrences</tt>
in Code Name Base. Click Finish.</li>
</ol>
</div>
<p> The IDE creates the <tt>MarkHTMLOccurrences</tt>
project. The project contains all of your sources and
project metadata, such as the project's Ant build script. The project
opens in the IDE. You can view its logical structure in the Projects window (Ctrl-1) and its
file structure in the Files window (Ctrl-2).</p>
<!-- ===================================================================================== -->
<h2><a name="coding-module"></a>Creating the Highlight Layer and Factory</h2>
<p>Next, we will implement the Highlighting SPI. The SPI's classes are as follows:</p>
<table>
<tbody>
<tr>
<th class="tblheader" scope="col">Class</th>
<th class="tblheader" scope="col">Description</th>
</tr>
<tr>
<td class="tbltd1"><a href="http://bits.netbeans.org/dev/javadoc/org-netbeans-modules-editor-lib2/org/netbeans/spi/editor/highlighting/HighlightsLayerFactory.html">HighlightsLayerFactory</a></td>
<td class="tbltd1">Defines the factory for creating highlight layers.</td>
</tr>
<tr>
<td class="tbltd1"><a href="http://bits.netbeans.org/dev/javadoc/org-netbeans-modules-editor-lib2/org/netbeans/spi/editor/highlighting/HighlightsLayerFactory.Context.html">HighlightsLayerFactory.Context</a></td>
<td class="tbltd1">Defines the context passed to the factory when the
factory is asked to create highlight layers.</td>
</tr>
<tr>
<td class="tbltd1"><a href="http://bits.netbeans.org/dev/javadoc/org-netbeans-modules-editor-lib2/org/netbeans/spi/editor/highlighting/HighlightsContainer.html">HighlightsContainer</a></td>
<td class="tbltd1">Defines the container of highlighted
areas and related attributes.</td>
</tr>
<tr>
<td class="tbltd1"><a href="http://bits.netbeans.org/dev/javadoc/org-netbeans-modules-editor-lib2/org/netbeans/spi/editor/highlighting/HighlightsLayer.html">HighlightsLayer</a></td>
<td class="tbltd1">Defines the highlight layer, consisting
of attributes.</td>
</tr>
<tr>
<td class="tbltd1"><a href="http://bits.netbeans.org/dev/javadoc/org-netbeans-modules-editor-lib2/org/netbeans/spi/editor/highlighting/ZOrder.html">ZOrder</a></td>
<td class="tbltd1">Defines position of highlight layer
in relation to other highlight layers.</td>
</tr>
<tr>
<td class="tbltd1"><a href="http://bits.netbeans.org/dev/javadoc/org-netbeans-modules-editor-lib2/org/netbeans/spi/editor/highlighting/support/OffsetsBag.html">OffsetsBag</a></td>
<td class="tbltd1">Defines a set of highlighted areas
specified by their offsets in the document.</td>
</tr>
</tbody>
</table>
<div class="indent">
<h3 class="tutorial"><a name="specifying"></a>Specifying the Module's Dependencies</h3>
<p>You will need to subclass several classes that belong to <a href="http://bits.netbeans.org/dev/javadoc/index.html">NetBeans APIs</a>.
Each has to be declared as a Module dependency. Use the Project Properties dialog box for this purpose.</p>
<div class="indent">
<ol>
<li>In the Projects window, right-click the Libraries node
in the <tt>MarkHTMLOccurrences</tt> project and choose Add Module Dependency.</li>
<li>For each of the following APIs, select the name from
the Module list, and then click OK to confirm that
you want to depend on it:
<br/><br/>
<ul>
<li>Datasystems API</li>
<li>Editor</li>
<li>Editor Library 2</li>
<li>Editor Settings</li>
<li>File System API</li>
<li>Lookup API</li>
<li>MIME Lookup API</li>
<li>Nodes API</li>
<li>Text API</li>
<li>UI Utilities API</li>
<li>Utilities API</li>
</ul>
<p>You should now see the following:</p>
<br/><img src="../../images/tutorials/mark-occs/72/project-1.png" alt="Step 0 of New Project wizard"/>
</li>
<li>In the Projects window, expand the Important Files node, double-click the Project Metadata node, and note the
long list of APIs that you selected have been
declared as module dependencies. When the module
is built, the dependencies will be registered
in the manifest file.</li>
</ol>
</div>
<h3 class="tutorial"><a name="creating-factory"></a>Creating the Highlight Layer Factory</h3>
<p>Highlight layer factories are defined
by the <a href="http://bits.netbeans.org/dev/javadoc/org-netbeans-modules-editor-lib2/org/netbeans/spi/editor/highlighting/package-summary.html">Highlighting SPI</a>.</p>
<p>To use the Highlighting SPI to create the palette in this tutorial, take the following steps:</p>
<div class="indent">
<ol>
<li>Right-click the <tt>MarkHTMLOccurrences</tt> project node and
choose New &gt; Java Class. Create a Java file
called <tt>MarkHTMLOccurrencesHighlightsLayerFactory</tt>.</li>
<li>Replace the default content of the <tt>MarkHTMLOccurrencesHighlightsLayerFactory.java</tt> file with the following:
<pre class="examplecode">import javax.swing.text.Document;
import org.netbeans.api.editor.mimelookup.MimeRegistration;
import org.netbeans.api.editor.mimelookup.MimeRegistrations;
import <a href="http://bits.netbeans.org/dev/javadoc/org-netbeans-modules-editor-lib2/org/netbeans/spi/editor/highlighting/HighlightsLayer.html">org.netbeans.spi.editor.highlighting.HighlightsLayer</a>;
import <a href="http://bits.netbeans.org/dev/javadoc/org-netbeans-modules-editor-lib2/org/netbeans/spi/editor/highlighting/HighlightsLayerFactory.html">org.netbeans.spi.editor.highlighting.HighlightsLayerFactory</a>;
import <a href="http://bits.netbeans.org/dev/javadoc/org-netbeans-modules-editor-lib2/org/netbeans/spi/editor/highlighting/ZOrder.html">org.netbeans.spi.editor.highlighting.ZOrder</a>;
@MimeRegistrations({
@MimeRegistration(mimeType = "text/html", service = HighlightsLayerFactory.class),
@MimeRegistration(mimeType = "text/xml", service = HighlightsLayerFactory.class)
})
public class MarkHTMLOccurrencesHighlightsLayerFactory implements <a href="http://bits.netbeans.org/dev/javadoc/org-netbeans-modules-editor-lib2/org/netbeans/spi/editor/highlighting/HighlightsLayerFactory.html">HighlightsLayerFactory</a> {
public static MarkHTMLOccurrencesHighlighter getMarkOccurrencesHighlighter(Document doc) {
MarkHTMLOccurrencesHighlighter highlighter =
(MarkHTMLOccurrencesHighlighter) doc.getProperty(MarkHTMLOccurrencesHighlighter.class);
if (highlighter == null) {
doc.putProperty(MarkHTMLOccurrencesHighlighter.class,
highlighter = new MarkHTMLOccurrencesHighlighter(doc));
}
return highlighter;
}
@Override
public HighlightsLayer[] <a href="http://bits.netbeans.org/dev/javadoc/org-netbeans-modules-editor-lib2/org/netbeans/spi/editor/highlighting/HighlightsLayerFactory.html#createLayers(org.netbeans.spi.editor.highlighting.HighlightsLayerFactory.Context)">createLayers</a>(<a href="http://bits.netbeans.org/dev/javadoc/org-netbeans-modules-editor-lib2/org/netbeans/spi/editor/highlighting/HighlightsLayerFactory.Context.html">Context</a> context) {
return new HighlightsLayer[]{
<a href="http://bits.netbeans.org/dev/javadoc/org-netbeans-modules-editor-lib2/org/netbeans/spi/editor/highlighting/HighlightsLayer.html#create(java.lang.String,%20org.netbeans.spi.editor.highlighting.ZOrder,%20boolean,%20org.netbeans.spi.editor.highlighting.HighlightsContainer)">HighlightsLayer.create</a>(
MarkHTMLOccurrencesHighlighter.class.getName(),
<a href="http://bits.netbeans.org/dev/javadoc/org-netbeans-modules-editor-lib2/org/netbeans/spi/editor/highlighting/ZOrder.html">ZOrder.CARET_RACK.forPosition(2000)</a>,
true,
<a href="http://bits.netbeans.org/dev/javadoc/org-netbeans-modules-editor-lib2/org/netbeans/spi/editor/highlighting/HighlightsContainer.html">getMarkOccurrencesHighlighter(context.getDocument()).getHighlightsBag()</a>)
};
}
}</pre></li>
</ol>
</div>
<p class="tips">Several statements remain underlined in red
because they refer to the "MarkHTMLOccurrencesHighlighter" class,
which we will create in the next section.</p>
<h3 class="tutorial"><a name="creating-highlight"></a>Creating the Highlight Layer</h3>
<p>In this section, we create the highlight layer. Create a new Java
class named <tt>MarkHTMLOccurrencesHighlighter</tt>, with the content below.</p>
<pre class="examplecode">import java.awt.Color;
import java.lang.ref.WeakReference;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.swing.JEditorPane;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
import javax.swing.text.AttributeSet;
import javax.swing.text.Document;
import javax.swing.text.JTextComponent;
import javax.swing.text.StyleConstants;
import <a href="http://bits.netbeans.org/dev/javadoc/org-netbeans-modules-editor-settings/org/netbeans/api/editor/settings/AttributesUtilities.html">org.netbeans.api.editor.settings.AttributesUtilities</a>;
import <a href="http://bits.netbeans.org/dev/javadoc/org-netbeans-modules-editor/org/netbeans/modules/editor/NbEditorUtilities.html">org.netbeans.modules.editor.NbEditorUtilities</a>;
import <a href="http://bits.netbeans.org/dev/javadoc/org-netbeans-modules-editor-lib2/org/netbeans/spi/editor/highlighting/support/OffsetsBag.html">org.netbeans.spi.editor.highlighting.support.OffsetsBag</a>;
import <a href="http://bits.netbeans.org/dev/javadoc/org-openide-text/org/openide/cookies/EditorCookie.html">org.openide.cookies.EditorCookie</a>;
import <a href="http://bits.netbeans.org/dev/javadoc/org-openide-loaders/org/openide/loaders/DataObject.html">org.openide.loaders.DataObject</a>;
import <a href="http://bits.netbeans.org/dev/javadoc/org-openide-util/org/openide/util/RequestProcessor.html">org.openide.util.RequestProcessor</a>;
public class MarkHTMLOccurrencesHighlighter implements CaretListener {
private static final AttributeSet defaultColors =
AttributesUtilities.createImmutable(StyleConstants.Background,
new Color(236, 235, 163));
private final OffsetsBag bag;
private JTextComponent comp;
private final WeakReference&lt;Document&gt; weakDoc;
private final RequestProcessor rp;
private final static int REFRESH_DELAY = 100;
private RequestProcessor.Task lastRefreshTask;
public MarkHTMLOccurrencesHighlighter(Document doc) {
rp = new RequestProcessor(MarkHTMLOccurrencesHighlighter.class);
bag = new OffsetsBag(doc);
weakDoc = new WeakReference&lt;Document&gt;((Document) doc);
DataObject dobj = NbEditorUtilities.getDataObject(weakDoc.get());
if (dobj != null) {
EditorCookie pane = dobj.getLookup().lookup(EditorCookie.class);
JEditorPane[] panes = pane.getOpenedPanes();
if (panes != null && panes.length > 0) {
comp = panes[0];
comp.addCaretListener(this);
}
}
}
@Override
public void caretUpdate(CaretEvent e) {
bag.clear();
setupAutoRefresh();
}
public void setupAutoRefresh() {
if (lastRefreshTask == null) {
lastRefreshTask = rp.create(new Runnable() {
@Override
public void run() {
String selection = comp.getSelectedText();
if (selection != null) {
Pattern p = Pattern.compile(selection);
Matcher m = p.matcher(comp.getText());
while (m.find() == true) {
int startOffset = m.start();
int endOffset = m.end();
bag.addHighlight(startOffset, endOffset, defaultColors);
}
}
}
});
}
lastRefreshTask.schedule(REFRESH_DELAY);
}
public OffsetsBag getHighlightsBag() {
return bag;
}
}</pre>
</div>
<!-- ======================================================================================= -->
<h2><a name="building"></a>Building and Installing the Module</h2>
<p>The IDE uses an Ant build script to build and install your module. The build script is created for you
when you create the module project.</p>
<div class="indent">
<ol>
<li>In the Projects window, right-click
the <tt>MarkHTMLOccurrences</tt> project and choose Run.</li>
<li>The module is built and installed in a new instance of the IDE.
Open an HTML file or an XML file, double-click on a word,
and notice that all matching words are automatically
highlighted:
<br/><br/><img src="../../images/tutorials/mark-occs/72/result-3.png" alt="result"/></p>
</li>
<li>Navigate from one matching word to the next
via Ctrl-F3.</li>
</ol>
</div>
<div class="feedback-box"><a href="https://netbeans.org/about/contact_form.html?to=3&amp;subject=Feedback:%20Mark%20Occurrences%20Module%207.2%20Tutorial">Send Us Your Feedback</a></div>
<!-- ======================================================================================== -->
<h2><a name="nextsteps"></a>Next Steps</h2>
<p>For more information about creating and developing NetBeans modules, see the following resources:</p>
<ul>
<li><a href="https://netbeans.org/kb/trails/platform.html">Other Related Tutorials</a></li>
<li><a href="http://bits.netbeans.org/dev/javadoc/index.html">NetBeans API Javadoc</a></li>
</ul>
<!-- ======================================================================================== -->
<!--
<h2><a name="version"></a>Versioning </h2>
<table width="76%" border="1">
<tbody>
<tr>
<td>
<div align="left"><b>Version</b></div>
</td>
<td>
<div align="left"><b>Date</b></div>
</td>
<td>
<div align="left"><b>Changes</b></div>
</td>
<td>
<div align="left"><b>Open Issues</b></div>
</td>
</tr>
<tr>
<td>
1
</td>
<td>
5 November 2008
</td>
<td>
Initial version
</td>
<td>
...
</td>
</tr>
<tr>
<td>
2
</td>
<td>
16 November 2008
</td>
<td>
Added more details, including more links to Javadoc.
</td>
<tr>
<td>
3
</td>
<td>
13 November 2011
</td>
<td>
Updated to 7.1. Added null check for DataObject and rewrote the RequestProcessor.
</td>
<tr>
<td>
4
</td>
<td>
15 July 2012
</td>
<td>
Updated to 7.2. Replaced getCookie with getLookup and added screenshots.
</td>
</tr>
</tbody>
</table>
-->
</body>
</html>