<!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> | |
<!-- -*- xhtml -*- --> | |
<title>NetBeans Code Completion 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 the Editor Code Completion API."/> | |
<!-- Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. --> | |
<!-- Use is subject to license terms.--> | |
</head> | |
<body> | |
<h1>NetBeans Code Completion Tutorial</h1> | |
<p>This tutorial shows you how to implement the <a href="https://netbeans.org/download/dev/javadoc/org-netbeans-modules-editor-completion/overview-summary.html">Editor | |
Code Completion API</a>. You will be shown how to implement the API | |
in the context of HTML files. When the user invokes the | |
code completion feature, a code completion box will appear, | |
displaying words that can complete the text typed in the editor. At the | |
end of this tutorial, HTML files will have a code completion | |
box as follows:</p> | |
<p>The content of the code completion box will come from | |
country names retrieved from the JDK's | |
<tt>java.util.Locale</tt> package.</p> | |
<p><strong class="notes">Note: </strong>This document uses NetBeans IDE 7.2 | |
and NetBeans Platform 7.2. If you | |
are using an earlier version, see <a href="71/nbm-code-completion.html">the previous version | |
of this document</a>.</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 Code Completion Integration</a></li> | |
<li><a href="#creating-the-module-project">Creating the Module Project</a></li> | |
<li><a href="#implementing-the-code-completion-provider">Implementing the Completion Provider Class</a> | |
<ul> | |
<li><a href="#completiontask">Implementing the createTask Method</a></li> | |
<li><a href="#autoquerytype">Implementing the getAutoQueryTypes Method</a></li> | |
</ul></li> | |
<li><a href="#implementing-the-code-completion-item">Implementing the Completion Item Class</a> | |
<ul> | |
<li><a href="#defining-the-action">Implementing the Action</a></li> | |
<li><a href="#defining-the-filter">Implementing the Filter</a></li> | |
<li><a href="#defining-the-tooltip-documentation">Implementing the Tooltip and Documentation Task</a></li> | |
</ul></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 or above</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 Code Completion Integration</h2> | |
<p>Two classes apply to code completion and these will be developed in this tutorial:</p> | |
<ul> | |
<li><tt><a href="http://bits.netbeans.org/dev/javadoc/org-netbeans-modules-editor-completion/org/netbeans/spi/editor/completion/CompletionItem.html">CompletionItem</a></tt></li> | |
<li><tt><a href="http://bits.netbeans.org/dev/javadoc/org-netbeans-modules-editor-completion/org/netbeans/spi/editor/completion/CompletionProvider.html">CompletionProvider</a></tt></li> | |
</ul> | |
<p class="tips">Both of these come from the | |
<a href="http://bits.netbeans.org/dev/javadoc/org-netbeans-modules-editor-completion/overview-summary.html">Editor | |
Code Completion API</a> and are implemented in this tutorial's module as | |
CountriesCompletionItem and CountriesCompletionProvider.</p> | |
<!-- ===================================================================================== --> | |
<h2 class="tutorial"><a name="creating"></a>Creating the Module Project</h2> | |
<p>In this section, we use a wizard to create the source structure that every NetBeans module requires. The | |
source structure consists of certain folders in specific places and a set of files that are | |
always needed. For example, every Ant-based NetBeans module requires | |
a <tt>nbproject</tt> folder, which holds | |
the project's metadata.</p> | |
<div class="indent"> | |
<ol> | |
<li>Choose File > 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>CountryCodeCompleter</tt> in Project Name. | |
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.countries</tt> | |
as the Code Name Base. Click Finish.</li> | |
</ol> | |
</div> | |
<p> The IDE creates the <tt>CountryCodeCompleter</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="implementing-the-code-completion-provider"></a>Implementing the Completion Provider Class</h2> | |
<p>The first class we will deal with when creating a code completion feature | |
for HTML files is the <tt><a href="https://netbeans.org/download/dev/javadoc/org-netbeans-modules-editor-completion/org/netbeans/spi/editor/completion/CompletionProvider.html">CompletionProvider</a></tt>. | |
As the user types in an editor, the code completion infrastructure asks all code | |
completion providers registered in the XML layer file to create <tt><a href="https://netbeans.org/download/dev/javadoc/org-netbeans-modules-editor-completion/org/netbeans/spi/editor/completion/CompletionTask.html">CompletionTasks</a></tt>. | |
The tasks are created by the <tt><a href="https://netbeans.org/download/dev/javadoc/org-netbeans-modules-editor-completion/org/netbeans/spi/editor/completion/CompletionProvider.html#createTask(int,%20javax.swing.text.JTextComponent)">CompletionProvider.createTask</a></tt> | |
method. What <i>happens</i> when the method is invoked is up to the implementation. In <i>our</i> | |
implementation, we will create a <tt><a href="https://netbeans.org/download/dev/javadoc/org-netbeans-modules-editor-completion/org/netbeans/spi/editor/completion/CompletionItem.html">CompletionItem</a></tt> | |
for a list of countries. | |
</p> | |
<div class="indent"> | |
<ol> | |
<li><p>Right-click the LIbraries node of the <tt>CountryCodeCompleter</tt> project and choose Add Module Dependency:</p> | |
<br/> | |
<p><img src="../images/tutorials/cc/72/deps.png" alt="Code completion in text file"/></p> | |
<br/> | |
<p>Set dependencies on the following:</p> | |
<br/> | |
<ul> | |
<li>"Editor Code Completion", which provides the API classes that we need in this tutorial.</li> | |
<li>"MIME Lookup API", which provides the Java annotation for registering | |
completion providers.</li> | |
<li>"Utilities API".</li> | |
</ul> | |
</li> | |
<li>Right-click the <tt>CountryCodeCompleter</tt> project and choose New > Java Class. In | |
Class Name, type <tt>CountriesCompletionProvider</tt>. In Package, choose <tt>org.netbeans.modules.countries</tt>. | |
Click Finish.</li> | |
<li><p>In the <tt>CountriesCompletionProvider</tt> class, change the signature so that | |
the class <tt>implements CompletionProvider</tt>. Place the cursor on the line | |
that defines the signature. A lightbulb appears. Click it and the | |
IDE adds an import statement for <tt>org.netbeans.spi.editor.completion.CompletionProvider</tt>. | |
The lightbulb appears again. Click it again and the IDE creates | |
skeleton methods for the two methods required by the CompletionProvider class. You should now see this:</p> | |
<pre class="examplecode">package org.netbeans.modules.CountryCodeCompleter; | |
import javax.swing.text.JTextComponent; | |
import org.netbeans.spi.editor.completion.CompletionProvider; | |
import org.netbeans.spi.editor.completion.CompletionTask; | |
public class CountriesCompletionProvider implements <a href="https://netbeans.org/download/dev/javadoc/org-netbeans-modules-editor-completion/org/netbeans/spi/editor/completion/CompletionProvider.html">CompletionProvider</a> { | |
public CountriesCompletionProvider() { | |
} | |
@Override | |
public <a href="https://netbeans.org/download/dev/javadoc/org-netbeans-modules-editor-completion/org/netbeans/spi/editor/completion/CompletionTask.html">CompletionTask</a> <a href="http://www.netbeans.org/download/dev/javadoc/org-netbeans-modules-editor-completion/org/netbeans/spi/editor/completion/CompletionProvider.html#createTask(int,%20javax.swing.text.JTextComponent)">createTask(int queryType, JTextComponent jtc)</a> { | |
throw new UnsupportedOperationException("Not supported yet."); | |
} | |
@Override | |
public int <a href="https://netbeans.org/download/dev/javadoc/org-netbeans-modules-editor-completion/org/netbeans/spi/editor/completion/CompletionProvider.html#getAutoQueryTypes(javax.swing.text.JTextComponent,%20java.lang.String)">getAutoQueryTypes(JTextComponent component, String typedText)</a> { | |
throw new UnsupportedOperationException("Not supported yet."); | |
} | |
} | |
</pre></li> | |
<li>Before coding the | |
<tt>CompletionProvider</tt> class, let's | |
register it in the XML layer file, | |
via a NetBeans Platform annotation: | |
<pre class="examplecode">package org.netbeans.modules.countries; | |
import javax.swing.text.JTextComponent; | |
<b>import org.netbeans.api.editor.mimelookup.MimeRegistration;</b> | |
import org.netbeans.spi.editor.completion.CompletionProvider; | |
import org.netbeans.spi.editor.completion.CompletionTask; | |
<b>@MimeRegistration(mimeType = "text/html", service = CompletionProvider.class)</b> | |
public class CountriesCompletionProvider implements CompletionProvider { | |
@Override | |
public CompletionTask createTask(int queryType, JTextComponent jtc) { | |
throw new UnsupportedOperationException("Not supported yet."); | |
} | |
@Override | |
public int getAutoQueryTypes(JTextComponent component, String typedText) { | |
throw new UnsupportedOperationException("Not supported yet."); | |
} | |
}</pre> | |
<p class="tips"> Read <a href="http://netbeans.dzone.com/news/mimelocation-mimeregistration">@MimeLocation, @MimeRegistration and @MimeRegistrations added</a> for details | |
on the annotation above.</p> | |
</li> | |
</ol> | |
</div> | |
<div class="indent"> | |
<h3 class="tutorial"><a name="completiontask"></a>Implementing the createTask Method</h3> | |
<p>In this section we create a skeleton implementation of | |
<tt><a href="https://netbeans.org/download/dev/javadoc/org-netbeans-modules-editor-completion/org/netbeans/spi/editor/completion/support/AsyncCompletionTask.html">AsyncCompletionTask</a></tt>. | |
In the next sections, we will fill this skeleton method out.</p> | |
<div class="indent"> | |
<ol> | |
<li>In the createTask method, | |
below the code from the previous section, add the following lines: | |
<pre class="examplecode">return new AsyncCompletionTask(new AsyncCompletionQuery() { | |
});</pre> | |
<p>Here, we're returning <tt><a href="https://netbeans.org/download/dev/javadoc/org-netbeans-modules-editor-completion/org/netbeans/spi/editor/completion/support/AsyncCompletionTask.html">AsyncCompletionTask</a></tt>, | |
which will allow for the asynchronous creation of our task. The class | |
comes from the <tt><a href="https://netbeans.org/download/dev/javadoc/org-netbeans-modules-editor-completion/org/netbeans/spi/editor/completion/support/package-summary.html">org.netbeans.spi.editor.completion.support</a></tt> package, | |
which provides several useful supporting classes for code completion implementations. We will | |
use several of | |
them in this tutorial.</p></li> | |
<li>Place the cursor on the line. Click the lightbulb that appears and let | |
the IDE add import statements. Also let it create a skeleton method for the | |
<a href="https://netbeans.org/download/dev/javadoc/org-netbeans-modules-editor-completion/org/netbeans/spi/editor/completion/support/AsyncCompletionTask.html#query(org.netbeans.spi.editor.completion.CompletionResultSet)">query</a> method.</li> | |
<li>Next, we need to specify which code completion type we are working with. When | |
the user clicks Ctrl-Space, or an alternative key combination defined by the user, | |
our code completion entries should appear. This is the COMPLETION_QUERY_TYPE. Alternative | |
query types exist, such as DOCUMENTATION_QUERY_TYPE and TOOLTIP_QUERY_TYPE. We need to test | |
whether the user pressed the keys applicable to the COMPLETION_QUERY_TYPE. Therefore add | |
the following test to the start of the <tt>createTask</tt> method: | |
<pre class="examplecode">if (queryType != CompletionProvider.COMPLETION_QUERY_TYPE) | |
return null;</pre> | |
<p>At this stage, the <tt>createTask</tt> method should look as follows:</p> | |
<pre class="examplecode">@Override | |
public CompletionTask createTask(int queryType, JTextComponent jtc) { | |
if (queryType != CompletionProvider.COMPLETION_QUERY_TYPE) | |
return null; | |
return new AsyncCompletionTask(new AsyncCompletionQuery() { | |
protected void query(CompletionResultSet completionResultSet, Document document, int caretOffset) { | |
} | |
}); | |
}</pre> | |
</li> | |
</ol> | |
</div> | |
</div> | |
<div class="indent"> | |
<h3 class="tutorial"><a name="autoquerytype"></a>Implementing the getAutoQueryTypes Method</h3> | |
<p>In this section we return 0 as our <tt>AutoQueryType</tt>, so that | |
the code completion box does not appear automatically, but only | |
when requested by the user.</p> | |
<p>Before filling out the <tt>query</tt> method, let's look at the <tt><a href="https://netbeans.org/download/dev/javadoc/org-netbeans-modules-editor-completion/org/netbeans/spi/editor/completion/CompletionProvider.html#getAutoQueryTypes(javax.swing.text.JTextComponent,%20java.lang.String)">getAutoQueryTypes(JTextComponent jTextComponent, String string)</a></tt> | |
method. This method determines whether the code completion box appears <i>automatically</i> | |
or not. For now, let's return 0. This means that the code completion box | |
will never appear unless the user explicitly asks for it. So, this method should | |
now look as follows:</p> | |
<pre class="examplecode">@Override | |
public int getAutoQueryTypes(JTextComponent component, String string) { | |
return 0; | |
}</pre> | |
<p class="tips">By default, the | |
user would press Ctrl-Space to make the code completion box appear. Later, we | |
can add a new option to our Options window extension, such as a checkbox which | |
will change the int returned in this method from 0 to 1, so that the code completion | |
box appears automatically. (There are also other types of queries, as | |
shown <a href="https://netbeans.org/download/dev/javadoc/org-netbeans-modules-editor-completion/constant-values.html#org.netbeans.spi.editor.completion.CompletionProvider.COMPLETION_QUERY_TYPE">here</a>.) | |
</p></li> | |
</ol> | |
</div> | |
</div> | |
<!-- ===================================================================================== --> | |
<h2><a name="implementing-the-code-completion-item"></a>Implementing the Completion Item Class</h2> | |
<p>In this section | |
we will create a class that implements <tt><a href="https://netbeans.org/download/dev/javadoc/org-netbeans-modules-editor-completion/org/netbeans/spi/editor/completion/CompletionItem.html">CompletionItem</a></tt>. | |
Once we have defined this class, we will fill out the query method in the | |
<tt>CompletionProvider</tt> class. The <tt>CompletionProvider</tt> will create instances of | |
our <tt>CompletionItem</tt>.</p> | |
<div class="indent"> | |
<ol><li>Right-click the | |
<tt>CountryCodeCompleter</tt> project and choose New > Java Class. | |
In Class Name, type <tt>CountriesCompletionItem</tt>. In Package, choose | |
<tt>org.netbeans.modules.countries</tt>. Click Finish.</li> | |
<li>We will return to this class in later steps. For now, we | |
will fill out the query method that we defined in the CompletionProvider class. | |
Fill out the AsyncCompletionTask as follows, and note | |
the explanatory comments in the code: | |
<pre class="examplecode">return new <a href="http://bits.netbeans.org/dev/javadoc/org-netbeans-modules-editor-completion/org/netbeans/spi/editor/completion/support/AsyncCompletionTask.html">AsyncCompletionTask</a>(new AsyncCompletionQuery() { | |
@Override | |
protected void query(CompletionResultSet completionResultSet, Document document, int caretOffset) { | |
//Iterate through the available locales | |
//and assign each country display name | |
//to a CompletionResultSet: | |
Locale[] locales = Locale.getAvailableLocales(); | |
for (int i = 0; i < locales.length; i++) { | |
final Locale locale = locales[i]; | |
final String country = locale.getDisplayCountry(); | |
if (!country.equals("")) { | |
completionResultSet.addItem(new CountriesCompletionItem(country, caretOffset)); | |
} | |
} | |
completionResultSet.finish(); | |
} | |
}, jtc);</pre> | |
<p> A red underline remains, after you let the IDE add various import statements. | |
The error underline tells you that the CompletionItem's constructor does not expect the | |
values that you are passing to it. In the next step, we will fill out the CompletionItem | |
so that it meets the requirements of the CompletionProvider.</p> | |
<p class="tips"> Read <a href="http://blogs.oracle.com/geertjan/entry/java_classes_in_code_completion">Java Classes in Code Completion</a> | |
to learn how to put Java classes in the code completion box, instead of the locales that are used above.</p> | |
</li> | |
<li>In the <tt>CountriesCompletionItem</tt> class, change the signature so that | |
the class <tt>implements CompletionItem</tt>. Let the IDE create import statements and skeleton | |
implementations for | |
the class's required methods. | |
Read the entry in the NetBeans Javadoc for | |
<tt><a href="https://netbeans.org/download/dev/javadoc/org-netbeans-modules-editor-completion/org/netbeans/spi/editor/completion/CompletionItem.html">CompletionItem</a></tt> | |
to begin to understand what each of the methods is for. For now, we will implement a | |
minimal completion item, just enough to | |
be able to compile the module and see the code completion box.</li> | |
<li>In the CountriesCompletionItem class, define the constructor as follows: | |
<pre class="examplecode">private String text; | |
private static ImageIcon fieldIcon = | |
new ImageIcon(ImageUtilities.loadImage("org/netbeans/modules/countries/icon.png")); | |
private static Color fieldColor = Color.decode("0x0000B2"); | |
private int caretOffset; | |
public CountriesCompletionItem(String text, int caretOffset) { | |
this.text = text; | |
this.caretOffset = caretOffset; | |
}</pre> | |
<p>Note that here we're referencing an icon. This is the icon that will | |
appear next to each entry represented by the CompletionItem in the | |
code completion box. The icon can be any icon with a dimension of 16x16 pixels. | |
For example, you could make use of this icon:</p> | |
<p><img src="../images/tutorials/cc/icon.png" alt="icon"/></p> | |
<p>If you like, you can right-click the image above and save it to the location | |
specified in the ImageIcon definition above.</p></li> | |
<li>Next define the <tt><a href="https://netbeans.org/download/dev/javadoc/org-netbeans-modules-editor-completion/org/netbeans/spi/editor/completion/CompletionItem.html#getPreferredWidth(java.awt.Graphics,%20java.awt.Font)">getPreferredWidth()</a></tt> | |
and <tt><a href="https://netbeans.org/download/dev/javadoc/org-netbeans-modules-editor-completion/org/netbeans/spi/editor/completion/CompletionItem.html#render(java.awt.Graphics,%20java.awt.Font,%20java.awt.Color,%20java.awt.Color,%20int,%20int,%20boolean)">render()</a></tt> | |
methods as follows: | |
<pre class="examplecode">@Override | |
public int getPreferredWidth(Graphics graphics, Font font) { | |
return CompletionUtilities.getPreferredWidth(text, null, graphics, font); | |
} | |
@Override | |
public void render(Graphics g, Font defaultFont, Color defaultColor, | |
Color backgroundColor, int width, int height, boolean selected) { | |
CompletionUtilities.renderHtml(fieldIcon, text, null, g, defaultFont, | |
(selected ? Color.white : fieldColor), width, height, selected); | |
}</pre> | |
<p>Define the <tt><a href="https://netbeans.org/download/dev/javadoc/org-netbeans-modules-editor-completion/org/netbeans/spi/editor/completion/CompletionItem.html#getSortText()">getSortText()</a></tt> method as follows:</p> | |
<pre class="examplecode">@Override | |
public CharSequence getSortText() { | |
return text; | |
}</pre> | |
<p>Next, define the <tt><a href="https://netbeans.org/download/dev/javadoc/org-netbeans-modules-editor-completion/org/netbeans/spi/editor/completion/CompletionItem.html#getInsertPrefix()">getInsertPrefix()</a></tt> method:</p> | |
<pre class="examplecode">@Override | |
public CharSequence getInsertPrefix() { | |
return text; | |
}</pre> | |
<p>Finally, create dummy implementations of the remaining methods. So, | |
return <tt>null</tt> for <tt>createDocumentationTask()</tt> and <tt>createToolTipTask()</tt>. Then return <tt>false</tt> for | |
<tt>instantSubstitution()</tt> and return <tt>0</tt> for <tt>getSortPriority()</tt>. Finally, | |
empty the methods <tt>defaultAction</tt> and <tt>processKeyEvent</tt>.</p></li> | |
<li>Right-click the module and choose Run. | |
A new instance of the IDE starts up and installs your module. Open an HTML file in | |
the IDE. Type something and press Ctrl-Space. | |
You should now see the following:</p> | |
<p><img src="../images/tutorials/cc/72/result-1.png" alt="icon"/></p> | |
<p class="tips"> When you press Enter in the list above, nothing happens. That is because | |
we have not defined the <tt><a href="https://netbeans.org/download/dev/javadoc/org-netbeans-modules-editor-completion/org/netbeans/spi/editor/completion/CompletionItem.html#defaultAction(javax.swing.text.JTextComponent)">defaultAction()</a></tt> | |
method yet. We will do so in the next section. Also note that the list does not narrow while you are typing. That | |
is because we have not created a filter yet. The filter will detect | |
what we are typing and adjust the entries in the list accordingly. We will create | |
a filter in a later section.</p></li> | |
</ol> | |
</div> | |
<div class="indent"> | |
<h3 class="tutorial"><a name="defining-the-action"></a>Implementing the Action</h3> | |
<p>In this section we specify what happens when the user | |
presses the Enter key or clicks the mouse over an entry in the | |
code completion box.</p> | |
<div class="indent"> | |
<ol> | |
<li>Fill out the <tt>defaultAction()</tt> method | |
as follows: | |
<pre class="examplecode">@Override | |
public void defaultAction(JTextComponent jtc) { | |
try { | |
StyledDocument doc = (StyledDocument) jtc.getDocument(); | |
doc.insertString(caretOffset, text, null); | |
//This statement will close the code completion box: | |
Completion.get().hideAll(); | |
} catch (BadLocationException ex) { | |
Exceptions.printStackTrace(ex); | |
} | |
}</pre> </li> | |
<li>Install the module again. Notice that when | |
you press Enter or click the mouse over an entry | |
in the code completion box, the selected text is added at the cursor | |
in your HTML file. However, the text that you typed | |
prior to calling up the code completion box is | |
not removed. Below, the "V" should be removed, because "Vietnam" | |
was selected from the code completion box: | |
<p><img src="../images/tutorials/cc/65-result-of-cc2.png" alt="icon"/></p> | |
<p>In the next section, we will add functionality to detect the number of | |
characters that have been typed and remove them when the selected country | |
is inserted into the document.</p></li> | |
</ol> | |
</div> | |
</div> | |
<div class="indent"> | |
<h3 class="tutorial"><a name="defining-the-filter"></a>Implementing the Filter</h3> | |
<p>In this section we enable the code completion box | |
to narrow while the user is typing. In this way, when the user types | |
'hel', only words that begin with those letters are | |
shown in the code completion box. The filter is defined | |
in the <tt>CountriesCompletionProvider</tt> class.</p> | |
<div class="indent"> | |
<ol> | |
<li>In the CountriesCompletionProvider class, | |
rewrite the <tt>AsyncCompletionTask()</tt> method by | |
adding the statements highlighted in bold below: | |
<pre class="examplecode">return new AsyncCompletionTask(new AsyncCompletionQuery() { | |
@Override | |
protected void query(CompletionResultSet completionResultSet, Document document, int caretOffset) { | |
<b>String filter = null; | |
int startOffset = caretOffset - 1; | |
try { | |
final StyledDocument bDoc = (StyledDocument) document; | |
final int lineStartOffset = getRowFirstNonWhite(bDoc, caretOffset); | |
final char[] line = bDoc.getText(lineStartOffset, caretOffset - lineStartOffset).toCharArray(); | |
final int whiteOffset = indexOfWhite(line); | |
filter = new String(line, whiteOffset + 1, line.length - whiteOffset - 1); | |
if (whiteOffset > 0) { | |
startOffset = lineStartOffset + whiteOffset + 1; | |
} else { | |
startOffset = lineStartOffset; | |
} | |
} catch (BadLocationException ex) { | |
Exceptions.printStackTrace(ex); | |
}</b> | |
//Iterate through the available locales | |
//and assign each country display name | |
//to a CompletionResultSet: | |
Locale[] locales = Locale.getAvailableLocales(); | |
for (int i = 0; i < locales.length; i++) { | |
final Locale locale = locales[i]; | |
final String country = locale.getDisplayCountry(); | |
<b>//Here we test whether the country starts with the filter defined above:</b> | |
if (!country.equals("") <b>&& country.startsWith(filter)</b>) { | |
<b>//Here we include the start offset, so that we'll be able to figure out | |
//the number of characters that we'll need to remove:</b> | |
completionResultSet.addItem(new CountriesCompletionItem(country, <b>startOffset,</b> caretOffset)); | |
} | |
} | |
completionResultSet.finish(); | |
} | |
}, jtc);</pre> </li> | |
<li>Right at the end of the CountriesCompletionProvider, add the | |
following two methods: | |
<pre class="examplecode">static int getRowFirstNonWhite(StyledDocument doc, int offset) | |
throws BadLocationException { | |
Element lineElement = doc.getParagraphElement(offset); | |
int start = lineElement.getStartOffset(); | |
while (start + 1 < lineElement.getEndOffset()) { | |
try { | |
if (doc.getText(start, 1).charAt(0) != ' ') { | |
break; | |
} | |
} catch (BadLocationException ex) { | |
throw (BadLocationException)new BadLocationException( | |
"calling getText(" + start + ", " + (start + 1) + | |
") on doc of length: " + doc.getLength(), start | |
).initCause(ex); | |
} | |
start++; | |
} | |
return start; | |
}</pre> | |
<pre class="examplecode">static int indexOfWhite(char[] line){ | |
int i = line.length; | |
while(--i > -1){ | |
final char c = line[i]; | |
if(Character.isWhitespace(c)){ | |
return i; | |
} | |
} | |
return -1; | |
} | |
</pre> </li> | |
<li>Change the constructor of the <tt>CountriesCompletionItem</tt> to receive the start offset. | |
Then change the <tt>defaultAction</tt> so that the start offset will be used in | |
determining the characters that will be removed when the selected country is inserted. | |
Below, the statements highlighted in bold are those that should be added: | |
<pre class="examplecode"><b>private int dotOffset;</b> | |
public CountriesCompletionItem(String text, <b>int dotOffset,</b> int caretOffset) { | |
this.text = text; | |
<b>this.dotOffset = dotOffset;</b> | |
this.caretOffset = caretOffset; | |
} | |
@Override | |
public void defaultAction(JTextComponent component) { | |
try { | |
StyledDocument doc = (StyledDocument) component.getDocument(); | |
//Here we remove the characters starting at the start offset | |
//and ending at the point where the caret is currently found: | |
doc.remove(dotOffset, caretOffset-dotOffset); | |
doc.insertString(dotOffset, text, null); | |
Completion.get().hideAll(); | |
} catch (BadLocationException ex) { | |
Exceptions.printStackTrace(ex); | |
} | |
} | |
... | |
... | |
...</pre></li> | |
<li>Install the module again and notice that this time the list of | |
words narrows while you are typing... | |
<p><img src="../images/tutorials/cc/65-result-of-cc.png" alt="Code completion in text file"/></p> | |
<p>...and that when you press Enter, the characters that you typed are removed and replaced by | |
the country selected from the code completion box.</p></li> | |
</ol> | |
</div> | |
</div> | |
<div class="indent"> | |
<h3 class="tutorial"><a name="defining-the-tooltip-documentation"></a>Implementing the Tooltip and Documentation Task</h3> | |
<p>Some optional features can also be added, as described below.</p> | |
<div class="indent"> | |
<ol> | |
<li>Optionally, you can implement the <tt>createToolTipTask</tt> method in the <tt>CountriesCompletionItem</tt>, with | |
this result when Ctrl-P is pressed: | |
<p><img src="../images/tutorials/cc/65-result-of-cc3.png" alt="Code completion in text file"/></p> | |
<p>Here is the code that will achieve the result shown in the screenshot above:</p> | |
<pre class="examplecode">@Override | |
public CompletionTask createToolTipTask() { | |
return new AsyncCompletionTask(new AsyncCompletionQuery() { | |
@Override | |
protected void query(CompletionResultSet completionResultSet, Document document, int i) { | |
JToolTip toolTip = new JToolTip(); | |
toolTip.setTipText("Press Enter to insert \"" + text + "\""); | |
completionResultSet.setToolTip(toolTip); | |
completionResultSet.finish(); | |
} | |
}); | |
}</pre> | |
</li> | |
<li>Optionally, you can provide documentation for the entries in the code completion box: | |
<p><img src="../images/tutorials/cc/65-result-of-cc4.png" alt="Code completion in text file"/></p> | |
<p>Make use of the documentation box like this, by implementing the <tt>createDocumentationTask</tt> method | |
in the <tt>CountriesCompletionItem</tt> class:</p> | |
<pre class="examplecode">@Override | |
public CompletionTask createDocumentationTask() { | |
return new AsyncCompletionTask(new AsyncCompletionQuery() { | |
@Override | |
protected void query(CompletionResultSet completionResultSet, Document document, int i) { | |
completionResultSet.setDocumentation(new CountriesCompletionDocumentation(CountriesCompletionItem.this)); | |
completionResultSet.finish(); | |
} | |
}); | |
}</pre> | |
<p>In the code above, the reference to the CountriesCompletionDocumentation class could be implemented as follows:</p> | |
<pre class="examplecode">public class CountriesCompletionDocumentation implements CompletionDocumentation { | |
private CountriesCompletionItem item; | |
public CountriesCompletionDocumentation(CountriesCompletionItem item) { | |
this.item = item; | |
} | |
@Override | |
public String getText() { | |
return "Information about " + item.text; | |
} | |
@Override | |
public URL getURL() { | |
return null; | |
} | |
@Override | |
public CompletionDocumentation resolveLink(String string) { | |
return null; | |
} | |
@Override | |
public Action getGotoSourceAction() { | |
return null; | |
} | |
}</pre> | |
<p>By implementing the <tt>getURL()</tt> in the code above, you can enable | |
the URL button, as shown below:</p> | |
<p><img src="../images/tutorials/cc/65-result-of-cc5.png" alt="Code completion in text file"/></p> | |
<p>When the user clicks the URL button, the browser set in the IDE will open, displaying | |
the content provided by the specified URL.</p> | |
</li> | |
</ol> | |
</div> | |
</div> | |
<p>Congratulations, you have now completed a simple implementation of a code completion | |
integration module.</p> | |
<br> | |
<div class="feedback-box"><a name="feedback"></a> | |
<a href="https://netbeans.org/about/contact_form.html?to=3&subject=Feedback:%20NetBeans%20Code%20Completion%20Tutorial%207.2"> | |
Send Us Your Feedback</a></div> | |
<br style="clear:both;" /> | |
<!-- ======================================================================================== --> | |
<h2><a name="nextsteps"></a>See Also</h2> | |
<p> | |
For more information about creating and developing plugins, see the following resources: | |
<ul> | |
<li><a href="https://netbeans.org/kb/trails/platform.html">NetBeans Platform Learning Trail</a></li> | |
<li><a href="http://bits.netbeans.org/dev/javadoc/">NetBeans API Javadoc</a></li> | |
</ul> | |
<!-- ======================================================================================== --> | |
</body> | |
</html> |