<!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 6.5</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><img border="1" src="../images/tutorials/cc/65-result-of-cc.png" alt="Code completion in text file"> | |
<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><b>Contents</b></p> | |
<img src="../images/articles/65/netbeans-stamp65.gif" class="stamp" width="114" height="114" alt="Content on this page applies to NetBeans IDE 6.5" title="Content on this page applies to NetBeans IDE 6.5"> </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></li> | |
<ul> | |
<li><a href="#completiontask">Implementing the createTask Method</a></li> | |
<li><a href="#autoquerytype">Implementing the getAutoQueryTypes Method</a></li> | |
</ul> | |
<li><a href="#implementing-the-code-completion-item">Implementing the Completion Item Class</a></li> | |
<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> | |
</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 6.5</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<br/>version 5</td> | |
</tr> | |
</tbody> | |
</table> | |
<p class="tips">Optionally, for troubleshooting purposes, you can <a href="http://plugins.netbeans.org/PluginPortal/faces/PluginDetailPage.jsp?pluginid=11981">download the | |
completed sample</a> and inspect the sources. | |
<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: | |
<a href="https://netbeans.org/download/dev/javadoc/org-netbeans-modules-editor-completion/org/netbeans/spi/editor/completion/CompletionItem.html">CompletionItem</a> and | |
<a href="https://netbeans.org/download/dev/javadoc/org-netbeans-modules-editor-completion/org/netbeans/spi/editor/completion/CompletionProvider.html">CompletionProvider</a>. Both of these come from the | |
<a href="https://netbeans.org/download/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>When this tutorial is complete, the Projects window will | |
contain the files shown in the illustration below: | |
<p><img border="1" src="../images/tutorials/cc/65-final-projects-window.png" alt="Final Projects window"> | |
<br /> | |
<!-- ===================================================================================== --> | |
<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 NetBeans module requires a <tt>nbproject</tt> folder, which holds | |
the project's metadata, and a <tt>layer.xml</tt> file, for declarative registration of items | |
such as toolbar buttons and windows. | |
<ol> | |
<li>Choose File > New Project (Ctrl-Shift-N). Under Categories, select NetBeans Modules. Under Projects, | |
select Module and 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, such as <tt>c:\mymodules</tt>. Leave the Standalone Module radiobutton | |
selected. Click Next. | |
<li>In the Basic Module Configuration panel, type <tt>org.netbeans.modules.countries</tt> | |
as the Code Name Base. | |
Select the "Generate XML Layer" checkbox and | |
leave the location of the localizing bundle and XML layer as they are, | |
so that they will be stored in a | |
package with the name <tt>org/netbeans/modules/countries</tt>. Click Finish.</ol> | |
<p> The IDE creates the <tt>CountriesCodeCompleter</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). | |
<br /> | |
<!-- ===================================================================================== --> | |
<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 <a href="https://netbeans.org/download/dev/javadoc/org-netbeans-modules-editor-completion/org/netbeans/spi/editor/completion/CompletionProvider.html">CompletionProvider</a>. | |
As the user types in an editor, the code completion infrastructure asks all code | |
completion providers registered in the XML layer file to create <a href="https://netbeans.org/download/dev/javadoc/org-netbeans-modules-editor-completion/org/netbeans/spi/editor/completion/CompletionTask.html">CompletionTasks</a>. | |
The tasks are created by the <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> | |
method. What <i>happens</i> when the method is invoked is up to the implementation. In <i>our</i> | |
implementation, we will create a <a href="https://netbeans.org/download/dev/javadoc/org-netbeans-modules-editor-completion/org/netbeans/spi/editor/completion/CompletionItem.html">CompletionItem</a> | |
for a list of countries. | |
</p> | |
<ol> | |
<li>Right-click the <tt>CountryCodeCompleter</tt> project and choose New > Java Class. | |
<li>In Class Name, type CountriesCompletionProvider. In Package, choose <tt>org.netbeans.modules.countries</tt>. | |
Click Finish. | |
<li>Before coding the CompletionProvider class, let's register it in the XML layer file. | |
Open the XML layer file, and right below the opening <tt><filesystem></tt> tag, add the following tags: | |
<pre class="examplecode"><folder name="Editors"> | |
<folder name="text"> | |
<folder name="html"> | |
<folder name="CompletionProviders"> | |
<file name="org-netbeans-modules-countries-CountriesCompletionProvider.instance"/> | |
</folder> | |
</folder> | |
</folder> | |
</folder></pre> | |
<p><b>Note:</b> As explained earlier, because of the entries specified above, | |
whenever the user types a character of any kind in a file with | |
a MIME type of <tt>text/html</tt>, the | |
code completion infrastructure will ask the CountriesCompletionProvider | |
to create its CompletionTask. In the next steps we will define our CompletionTask.</p> | |
<li>Right-click the <tt>CountryCodeCompleter</tt> project and choose Properties. | |
In the Project Properties dialog box, click Libraries. Click Add next to the | |
Module Dependencies list. Scroll to "Editor Code Completion" and click OK. Click | |
OK again to exit the Project Properties dialog box. | |
<li>In the CountriesCompletionProvider 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. | |
<p>You should now see this: | |
<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() { | |
} | |
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 i,at JTextComponent jTextComponent)</a> { | |
} | |
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 jTextComponent, String string)</a> { | |
} | |
} | |
</pre> | |
<p>Click the links above to find out more about the classes and methods. Note that you | |
will see a few red error markings. Don't worry about these yet, they're just there to | |
tell you that the methods need to return something. We will work on this in the following steps. | |
</ol> | |
<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 | |
<a href="https://netbeans.org/download/dev/javadoc/org-netbeans-modules-editor-completion/org/netbeans/spi/editor/completion/support/AsyncCompletionTask.html">AsyncCompletionTask</a>. | |
In the next sections, we will fill this skeleton method out. | |
<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 <a href="https://netbeans.org/download/dev/javadoc/org-netbeans-modules-editor-completion/org/netbeans/spi/editor/completion/support/AsyncCompletionTask.html">AsyncCompletionTask</a>, | |
which will allow for the asynchronous creation of our task. The class | |
comes from the <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> package, | |
which provides several useful supporting classes for code completion implementations. We will | |
use several of | |
them in this tutorial. | |
<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. | |
<p><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 (i != CompletionProvider.COMPLETION_QUERY_TYPE) | |
return null;</pre> | |
<p>At this stage, the <tt>createTask</tt> method should look as follows: | |
<pre class="examplecode">public CompletionTask createTask(int i, JTextComponent jTextComponent) { | |
if (i != CompletionProvider.COMPLETION_QUERY_TYPE) | |
return null; | |
return new AsyncCompletionTask(new AsyncCompletionQuery() { | |
protected void query(CompletionResultSet completionResultSet, Document document, int caretOffset) { | |
} | |
}); | |
} | |
</pre> | |
</ol> | |
<div class="indent"> | |
<h3 class="tutorial"><a name="autoquerytype"></a>Implementing the getAutoQueryTypes Method</h3> | |
<p>In this section we return 0 as our AutoQueryType, so that | |
the code completion box does not appear automatically, but only | |
when requested by the user. | |
<ol> | |
<li>Change the name "i" in the createTask method | |
signature to "type". Do this to make your code | |
more readable. The name "i" does not mean anything. | |
By changing it to "type" you will later be able | |
to see more clearly that the AutoQueryType is | |
being referred to here.</li> | |
<li>Before filling out the query method, let's look at the <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> | |
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: | |
<pre class="examplecode">public int getAutoQueryTypes(JTextComponent jTextComponent, String string) { | |
return 0; | |
} | |
</pre> | |
<p>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>.) | |
</ol> | |
</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 <a href="https://netbeans.org/download/dev/javadoc/org-netbeans-modules-editor-completion/org/netbeans/spi/editor/completion/CompletionItem.html">CompletionItem</a>. | |
Once we have defined this class, we will fill out the query method in the | |
CompletionProvider class. The CompletionProvider will create instances of | |
our CompletionItem. | |
<ol><li>Right-click the | |
<tt>CountryCodeCompleter</tt> project and choose New > Java Class. | |
In Class Name, type CountriesCompletionItem. In Package, choose | |
<tt>org.netbeans.modules.countries</tt>. Click Finish. | |
<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 AsyncCompletionTask(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(); | |
} | |
}, jTextComponent);</pre> | |
<p><b>Note:</b> 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. | |
<li>In the CountriesCompletionItem 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 | |
<a href="https://netbeans.org/download/dev/javadoc/org-netbeans-modules-editor-completion/org/netbeans/spi/editor/completion/CompletionItem.html">CompletionItem</a> | |
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>In the CountriesCompletionItem class, define the constructor as follows: | |
<pre class="examplecode">private String text; | |
private static ImageIcon fieldIcon = | |
new ImageIcon(Utilities.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><img border="1" src="../images/tutorials/cc/icon.png" alt="icon"> | |
<p>If you like, you can right-click the image above and save it to the location | |
specified in the ImageIcon definition above. | |
<li>Next define the <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> | |
and <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> | |
methods as follows: | |
<pre class="examplecode">public int getPreferredWidth(Graphics graphics, Font font) { | |
return CompletionUtilities.getPreferredWidth(text, null, graphics, font); | |
} | |
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: | |
<pre class="examplecode">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: | |
<pre class="examplecode">public CharSequence getInsertPrefix() { | |
return text; | |
}</pre> | |
<p>Finally, create dummy implementations of the remaining methods. So, | |
return <tt>null</tt> for <tt>createDocumentationTask()</tt>, <tt>createToolTipTask()</tt>, | |
and <tt>getInsertPrefix()</tt>. Then return <tt>false</tt> for | |
<tt>instantSubstitution()</tt> and return <tt>0</tt> for <tt>getSortPriority()</tt>. | |
<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. | |
<p>You should now see the following: | |
<p><img border="1" src="../images/tutorials/cc/65-result-of-cc1.png" alt="icon"> | |
<p><b>Note:</b> When you press Enter, nothing happens. That is because | |
we have not defined the <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> | |
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. | |
</ol> | |
<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. | |
<ol> | |
<li>Fill out the <tt>defaultAction()</tt> method | |
as follows: | |
<pre class="examplecode">public void defaultAction(JTextComponent jTextComponent) { | |
StyledDocument doc = (StyledDocument) jTextComponent.getDocument(); | |
doc.insertString(caretOffset, text, null); | |
//This statement will close the code completion box: | |
Completion.get().hideAll(); | |
} | |
</pre> | |
<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 border="1" src="../images/tutorials/cc/65-result-of-cc2.png" alt="icon"> | |
<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. | |
</ol> | |
</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 CountriesCompletionProvider class. | |
<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(); | |
} | |
}, jTextComponent);</pre> | |
<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>Change the constructor of the CountriesCompletionItem 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; | |
} | |
public void defaultAction(JTextComponent jTextComponent) { | |
try { | |
StyledDocument doc = (StyledDocument) jTextComponent.getDocument(); | |
<b>//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);</b> | |
doc.insertString(<b>dotOffset,</b> text, null); | |
Completion.get().hideAll(); | |
} catch (BadLocationException ex) { | |
Exceptions.printStackTrace(ex); | |
} | |
} | |
... | |
... | |
...</pre> | |
<li>Install the module again and notice that this time the list of | |
words narrows while you are typing: | |
<p><img border="1" src="../images/tutorials/cc/65-result-of-cc.png" alt="Code completion in text file"> | |
<p>When you press Enter, the characters that you typed are removed and replaced by | |
the country selected from the code completion box. | |
</ol> | |
</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. | |
<ol> | |
<li>Optionally, you can implement the createToolTipTask method in the CountriesCompletionItem, with | |
this result when Ctrl-P is pressed: | |
<p><img border="1" src="../images/tutorials/cc/65-result-of-cc3.png" alt="Code completion in text file"> | |
<p>Here is the code that will achieve the result shown in the screenshot above: | |
<pre class="examplecode"> | |
public CompletionTask createToolTipTask() { | |
return new AsyncCompletionTask(new AsyncCompletionQuery() { | |
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>Optionally, you can provide documentation for the entries in the code completion box: | |
<p><img border="1" src="../images/tutorials/cc/65-result-of-cc4.png" alt="Code completion in text file"> | |
<p>Make use of the documentation box like this, by implementing the createDocumentationTask method | |
in the CountriesCompletionItem class: | |
<pre class="examplecode">public CompletionTask createDocumentationTask() { | |
return new AsyncCompletionTask(new AsyncCompletionQuery() { | |
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: | |
<pre class="examplecode">public class CountriesCompletionDocumentation implements CompletionDocumentation { | |
private CountriesCompletionItem item; | |
public CountriesCompletionDocumentation(CountriesCompletionItem item) { | |
this.item = item; | |
} | |
public String getText() { | |
return "Information about " + item.getText(); | |
} | |
public URL getURL() { | |
return null; | |
} | |
public CompletionDocumentation resolveLink(String string) { | |
return null; | |
} | |
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><img border="1" src="../images/tutorials/cc/65-result-of-cc5.png" alt="Code completion in text file"> | |
<p>When the user clicks the URL button, the browser set in the IDE will open, displaying | |
the content provided by the specified URL. | |
</ol> | |
</div> | |
<p>Congratulations, you have now completed a simple implementation of a code completion | |
integration module. | |
</body> | |
</html> |