blob: b72e16974fc294c9b785c186aa94da2b40d287b9 [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>
<!-- -*- xhtml -*- -->
<title>NetBeans Code Folding Tutorial</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 Nodes API.">
<!-- Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. -->
<!-- Use is subject to license terms.-->
</head>
<body>
<h1>NetBeans Code Folding Tutorial</h1>
<table class="tablebg" align="right">
<tbody><tr>
<td class="tblheader">Tutorial Downloads</td>
</tr>
<tr>
<td class="tbltd0">
<p><a href="https://netbeans.org/files/documents/4/1213/TextFileDictionary.zip">Tutorial end point</a></p>
</td>
</tr>
</tbody></table>
<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 Folding API</a>. You will be shown how to implement the API
in the context of text files. When a text file is opened
in the IDE, a new code fold will be created for each paragraph
in the file, as shown here:
<p><img border="1" src="../images/tutorials/cc/result-of-cc.png" alt="Code completion in text file">
<p>In addition, you will provide the user with an
extension to the Options window. The Options window
extension will allow your users to select a text file
containing the words that should be displayed in
the code completion box.
<p>When this tutorial is complete, the Projects window will
contain the files shown in the illustration below. Note that
the only files that relate directly to the Editor Code
Completion API are those that are selected in the screenshot:
<p><img border="1" src="../images/tutorials/cc/final-projects-window.png" alt="Final Projects window">
<p>The following topics are covered in this tutorial:</p>
<ul>
<li><a href="#creating-the-module-project">Creating the Module Project</a></li>
<li><a href="#recognizing-text-files">Recognizing Text Files</a></li>
<li><a href="#extending-the-options-window">Extending the Options Window</a></li>
<li><a href="#implementing-the-code-completion-provider">Implementing the Code Completion Provider</a></li>
<ul>
<li><a href="#completionprovider">Getting Started with the Code Completion Provider</a></li>
<li><a href="#completiontask">Getting Started with the Code Completion Task</a></li>
<li><a href="#autoquerytype">Getting Started with the AutoQueryType</a></li>
</ul>
<li><a href="#implementing-the-code-completion-item">Implementing the Code Completion Item</a></li>
<ul>
<li><a href="#defining-the-action">Defining the Action</a></li>
<li><a href="#defining-the-filter">Defining the Filter</a></li>
</ul>
<li><a href="#applying">Applying What You Have Learned</a></li>
</ul>
<p><a name="top"></a>This tutorial can be completed in 60 minutes.
<p>For more information on creating NetBeans plug-in modules, see the <a href="https://platform.netbeans.org/index.html">
NetBeans Development Project home</a> on the NetBeans website. If you have questions, visit the
<a href="http://wiki.netbeans.org/wiki/view/NetBeansDeveloperFAQ">NetBeans Developer FAQ</a> or use the feedback link
at the top of this page.</p>
<br />
<!-- ===================================================================================== -->
<h2><a name="creating-the-module-project"></a>Creating the Module Project</h2>
<p>Before you start writing the module, you have to make sure you
that your project is set up correctly. <a href="http://www.netbeans.info/downloads/download.php?a=n&p=1">NetBeans IDE 5.x</a> provides a wizard that sets up all the basic files
needed for a module.</p>
<ol>
<li>Choose File &gt; New Project. Under Categories, select NetBeans Plug-in Modules. Under Projects,
select Module Project and click Next.</li>
<li>In the Name and Location panel, type <tt>TextFileDictionary</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
and the Set as Main Project checkbox selected.
Click Next.
<p><li>In the Basic Module Configuration panel, replace <tt>yourorghere</tt> in Code Name Base with <tt>netbeans.modules</tt>
so that the whole name is <tt>org.netbeans.modules.textfiledictionary</tt>. Leave <tt>TextFileDictionary</tt> as the Module Display Name.
Leave the location of the localizing bundle and XML layer, so that they will be stored in a
package with the name <tt>org.netbeans.modules.textfiledictionary</tt>. Click Finish.</ol>
<p> The IDE creates the <tt>TextFileDictionary</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).
<!-- ===================================================================================== -->
<h2><a name="recognizing-text-files"></a>Recognizing Text Files</h2>
<p>By default, the IDE does not give text files any special treatment. While JSP files,
Java files, and HTML files (as well as many other types of files) have distinct
syntax coloring, for example, the text file is not recognized. Before we can provide
code completion for text files, we first need to make sure that the IDE will
recognize text files and that the IDE will be able to distinguish text files
from all other types of files. To do this, we need to create a loader that will
load text files for us. The File Type wizard generates all the files that we will need.</p>
<ol>
<li>Right-click the <tt>TextFileDictionary</tt> project and choose New &gt; File Type.
<li>In the New File Type wizard, specify that <tt>text/x-text</tt> will be
our MIME type. In the Extension(s) text field, type "txt". This will tell the IDE
that files with the extension "txt" belong to the MIME type <tt>text/x-text</tt>. Later,
we will see in the XML layer file that various actions will be registered for text
files within a folder for the <tt>text/x-text</tt> MIME type.
Click Next.
<li>In the Name, Icon and Location panel, type "Text" in Class Name Prefix.
This will ensure that all the files created by this wizard will have the
prefix "Text". You could type anything you want here, this prefix has
no impact on anything other than the names of the generated files. However, since we are
dealing with text files, we type "Text" here.
<p><br>Optionally, you can browse to an icon with a dimension of 16x16 pixels.
This icon will be displayed in explorer windows such as the Projects window,
just like the icons for the other file types. However, no icon is needed.
<li>Click Finish. The IDE generates various files. We will not need to
modify any of them in this tutorial. If you would like to know what
each of these files is for, see the <a href="https://platform.netbeans.org/tutorials/nbm-filetype.html">Recognizing a File Type Tutorial</a>.
</ol>
<!-- ===================================================================================== -->
<h2><a name="extending-the-options-window"></a>Extending the Options Window</h2>
<p>In this section, we will extend the Options window. Using a simple wizard,
we will get a skeleton implementation of an Options window extension. Once we have
that, we will add a JPanel, a JTextField, a JLabel, and a JButton. When the user clicks
the JButton, they will be able to browse to a file on disk containing the words that will
appear in the code completion box. Here, we are only concerned with letting the user <i>get</i>
the file. Later, we will integrate the chosen file into the code completion box.</p>
<ol>
<li>Right-click the <tt>TextFileDictionary</tt> project and choose New &gt; File/Folder.
In the NetBeans Module Development category, choose Options Panel. Click Next.
<p><br>Two types of panels can be created. Here, we create an extension to the
Miscellaneous panel in the Options window.
<li>Type "Dictionary File" in both the Title and the Tool Tip fields. Click Next.
<li>Change the Class Name Prefix to "Text". Note that, when you do so, the
Created Files area in the wizard shows you what the files will be named. In each
case, the Class Name Prefix will be prepended to the file in question.
<li>Click Finish. The IDE generates various files. It also adds registration
entries in the XML layer file.
<li>Open TextPanel.java. Notice that it opens in a visual designer. Drag and
drop a JPanel onto the form. In the Properties window, change the background color
to white. Using the Properties window again, add a titled border with
the text "File Location".
<li>Add a JLabel, a JTextField, and a JButton. Design the components so that
the panel looks as follows:
<p><br><img border="1" src="../images/tutorials/cc/options-window-design.png" alt="Options window design">
<p><li>Right-click the JButton and choose Events &gt; Action &gt; actionPerformed.
In the jButton1ActionPerformed event, paste the following code:
<pre class=examplecode>String filename = jTextField1.getText();
JFileChooser chooser = new JFileChooser(new File(filename));
// Show open dialog; this method does not return until the dialog is closed:
int result = chooser.showOpenDialog(this);
// Determine which button was clicked to close the dialog:
switch (result) {
case JFileChooser.APPROVE_OPTION:
File selFile = chooser.getSelectedFile();
jTextField1.setText(selFile.getAbsolutePath());
break;
case JFileChooser.CANCEL_OPTION:
// Cancel or the close-dialog icon was clicked:
break;
case JFileChooser.ERROR_OPTION:
// The selection process did not complete successfully:
break;
}</pre>
<p>This will let the user browse to a file on disk. When prompted by the
lightbulb, let the IDE add import statements
for <tt>java.io.File</tt> and <tt>javax.swing.JFileChooser</tt>.
<li>In the source, add this line inside the
<tt>load()</tt> method:
<p><pre class=examplecode>jTextField1.setText(Preferences.userNodeForPackage(TextPanel.class).get("DICTIONARY_KEY", ""));</pre>
<p>Put the cursor on the line above. A lightbulb appears. When you click it, you can let
the IDE add the necessary import statement. For details on the Preferences API, see the
standard JDK Javadoc.
<P><li>In the <tt>store()</tt> method, put the following line of code:
<p><pre class=examplecode>Preferences.userNodeForPackage(TextPanel.class).put("DICTIONARY_KEY", jTextField1.getText());</pre>
<p><li>Right-click the TextFileDictionary project node in the Projects window.
Choose Install/Reload in Target Platform.
<p><br>In the Tools menu, choose Options. Check that you see the following
in the Miscellaneous panel:
<p><br><img border="1" src="../images/tutorials/cc/options-window-design2.png" alt="Options window design">
<li>Click the browse button and browse to a file containing the words you
want to display in the code completion box. For example, if you
download <a href="http://sourceforge.net/project/showfiles.php?group_id=34472&package_id=62241&release_id=116705">this file</a>
from the Jazzy - Java Spell Check API on SourceForge.net, you will have a file containing
a very long list of English words.
</ol>
<!-- ===================================================================================== -->
<h2><a name="implementing-the-code-completion-provider"></a>Implementing the Code Completion Provider</h2>
<p>The first class we will deal with when creating a code completion feature
for text 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 the entries retrieved from the file selected in the Options window, using the extension
created in the previous section.
</p>
<ol>
<li>Right-click the <tt>TextFileDictionary</tt> project and choose New &gt; Java Class.
<li>In Class Name, type TextCompletionProvider. In Package, choose <tt>org.netbeans.modules.textfiledictionary</tt>.
Click Finish.
<li>Before implementing the CompletionProvider class, let's register it in the XML layer file.
Open the XML layer file, and right below the opening <tt>&lt;filesystem&gt;</tt> tag, add the following tags:
<pre class=examplecode>&lt;folder name="Editors"&gt;
&lt;folder name="text"&gt;
&lt;folder name="x-text"&gt;
&lt;folder name="CompletionProviders"&gt;
&lt;file name="org-netbeans-modules-textfiledictionary-TextCompletionProvider.instance"/&gt;
&lt;/folder&gt;
&lt;/folder&gt;
&lt;/folder&gt;
&lt;/folder&gt;</pre>
<p>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>tex/x-text</tt>, the
code completion infrastructure will ask the TextCompletionProvider
to create its CompletionTask. In the next steps we will define our CompletionTask.</p>
</ol>
<div class="indent">
<h3 class="tutorial"><a name="completionprovider"></a>Getting Started with the CompletionProvider</h3>
<p>In this section we create a skeleton implementation of
our CompletionProvider. We also make the file that the user sets in
the Options window available to the CompletionProvider.
<ol>
<li>Right-click the <tt>TextFileDictionary</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 TextCompletionProvider 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><br>You should now see this:
<pre class=examplecode>package org.netbeans.modules.textfiledictionary;
import javax.swing.text.JTextComponent;
import org.netbeans.spi.editor.completion.CompletionProvider;
import org.netbeans.spi.editor.completion.CompletionTask;
public class TextCompletionProvider implements <a href="https://netbeans.org/download/dev/javadoc/org-netbeans-modules-editor-completion/org/netbeans/spi/editor/completion/CompletionProvider.html">CompletionProvider</a> {
public TextCompletionProvider() {
}
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, 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.
<li>Next, let's make the dictionary file that the user defines
in the Options window available to the <tt>createTask</tt> method.
At the start of the method, add the following:
<pre class=examplecode>Preferences pref = Preferences.userNodeForPackage(TextPanel.class);
dict = pref.get("DICTIONARY_KEY", "");
pref.addPreferenceChangeListener(new PreferenceChangeListener() {
public void preferenceChange(PreferenceChangeEvent evt) {
if (evt.getKey().equals("DICTIONARY_KEY")) {
dict = evt.getNewValue();
}
}
});
</pre>
<p>Above, we retrieve the preference set by the user,
via the key. We also want to make sure that when the user selects
a different file, that the changed file is immediately reflected in
the code completion box. The PreferenceChangeListener above listens
for changes to the key, whenever a new task is created. As pointed out
earlier, a new task is created at each keystroke, because the
code completion infrastructure asks the MIME type's registered
completion providers to create tasks at each keystroke.
<p>Note that you need to declare the String dict at the top of the file:
<pre class=examplecode>private String dict;</pre>
<p>When prompted by the lightbulb, let the IDE add import statements for
<tt>java.util.prefs.PreferenceChangeEvent</tt>, <tt>java.util.prefs.PreferenceChangeListener</tt>,
and <tt>java.util.prefs.Preferences</tt>.
</ol>
<div class="indent">
<h3 class="tutorial"><a name="completiontask"></a>Getting Started with the CompletionTask</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 previousb 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><br>At this stage, the createTask method should look as follows:
<pre class=examplecode>public CompletionTask createTask(int i, JTextComponent jTextComponent) {
Preferences pref = Preferences.userNodeForPackage(TextPanel.class);
dict = pref.get("DICTIONARY_KEY", "");
pref.addPreferenceChangeListener(new PreferenceChangeListener() {
public void preferenceChange(PreferenceChangeEvent evt) {
if (evt.getKey().equals("DICTIONARY_KEY")) {
dict = evt.getNewValue();
}
}
});
return new AsyncCompletionTask(new AsyncCompletionQuery() {
protected void query(CompletionResultSet completionResultSet, Document document, int i) {
}
});
}
</pre>
</ol>
<div class="indent">
<h3 class="tutorial"><a name="autoquerytype"></a>Getting Started with the AutoQueryType</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>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 Code Completion Item</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 click the
<tt>TextFileDictionary</tt> project and choose New &gt; Java Class.
In Class Name, type TextCompletionItem. In Package, choose
<tt>org.netbeans.modules.textfiledictionary</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() {
protected void query(CompletionResultSet completionResultSet, Document document, int i) {
int startOffset = i-1;
try {
FileReader fr = new FileReader(dict);
BufferedReader br = new BufferedReader(fr);
String record = new String();
while ((record = br.readLine()) != null) {
completionResultSet.addItem(new TextCompletionItem(record, startOffset, i));
}
} catch (IOException ex) {
ex.printStackTrace();
}
completionResultSet.finish();
}
},jTextComponent);
</pre>
<p>Note that 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 TextCompletionItem class, change the signature so that
the class <tt>implements CompletionItem</tt>.
<li>Let the IDE create import statements and skeleton implementations for
the class's required methods.
<li>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.
<p><br>For now, we will implement a minimal completion item, just enough to
be able to compile the module and see the code completion box. Later, we will
add a lot more detail to the implementation.
<li>In the CompletionItem class, replace the constructor with the following:
<pre class=examplecode>private static Color fieldColor = Color.decode("0x0000B2");
private static ImageIcon fieldIcon = null;
private ImageIcon _icon;
private int _type;
private int _carretOffset;
private int _dotOffset;
private String _text;
public TextCompletionItem(String text, int dotOffset, int carretOffset) {
_text = text;
_dotOffset = dotOffset;
_carretOffset = carretOffset;
if(fieldIcon == null){
fieldIcon = new ImageIcon(Utilities.loadImage("org/netbeans/modules/textfiledictionary/icon.png"));
}
_icon = fieldIcon;
}
</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, the illustration at the start of this tutorial makes use of this icon:
<p><br><img border="1" src="../images/tutorials/cc/icon.png" alt="icon">
<p>If you want, 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(_icon, _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>
<li>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 Install/Reload in Target Platform.
A new instance of the IDE starts up and installs your module. In the Tools menu,
choose Options. In the Miscellaneous panel, browse to the file containing the
words that you want to see in the code completion box. Open a text file in
the IDE. Type something and press Ctrl-Space.
<p><br>You should now see the following:
<p><br><img border="1" src="../images/tutorials/cc/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>Defining 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>In the same way that you set a dependency
on the Editor Code Completion API, set a dependency
on the Editor Library API.
<li>Define a new method, called <tt>doSubstitute</tt>.
We will call this method from our <tt>defaultAction()</tt> method.
We will also call it from the <a href="https://netbeans.org/download/dev/javadoc/org-netbeans-modules-editor-completion/org/netbeans/spi/editor/completion/CompletionItem.html#processKeyEvent(java.awt.event.KeyEvent)">processKeyEvent()</a>
method.
<pre class=examplecode>private void doSubstitute(JTextComponent component, String toAdd, int backOffset) {
final BaseDocument doc = (BaseDocument) component.getDocument();
final int caretOffset = component.getCaretPosition();
String value = _text;
if (toAdd != null) {
value += toAdd;
}
doc.atomicLock();
try {
doc.remove(_dotOffset+1, _carretOffset-_dotOffset-1);
doc.insertString(_dotOffset+1, value, null);
component.setCaretPosition(component.getCaretPosition() - backOffset);
} catch (BadLocationException e) {
ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, e);
} finally {
doc.atomicUnlock();
}
}
</pre>
<li>Fill out the <tt>defaultAction()</tt> and <tt>processKeyEevent()</tt> methods
as follows:
<pre class=examplecode>public void defaultAction(JTextComponent jTextComponent) {
doSubstitute(jTextComponent, null, 0);
Completion.get().hideAll();
}
public void processKeyEvent(KeyEvent evt) {
if (evt.getID() == KeyEvent.KEY_TYPED && evt.getKeyCode() == KeyEvent.VK_ENTER) {
doSubstitute((JTextComponent) evt.getSource(), _text, _text.length() - 1);
evt.consume();
}
}</pre>
<p>Note that, among other
import statements, you need an import statement for <tt>org.netbeans.api.editor.completion.Completion</tt>.
<li>Install the module again. Notice that when
you press Enter or click the mouse over an entry
in the code completion box, it is added at the cursor
in your text file.
</ol>
<div class="indent">
<h3 class="tutorial"><a name="defining-the-filter"></a>Defining 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 TextCompletionProvider class.
<ol>
<li>In the TextCompletionProvider class,
add this right above the <tt>try</tt> block,
in the query method:
<pre class=examplecode>String filter = null;
final BaseDocument bDoc = (BaseDocument)document;
try {
bDoc.readLock();
final int lineStartOffset = Utilities.getRowFirstNonWhite(bDoc, i);
if(lineStartOffset > -1 && i > lineStartOffset){
final char[] line = bDoc.getChars(lineStartOffset, i-lineStartOffset);
final int whiteOffset = indexOfWhite(line);
filter = new String(line, whiteOffset+1, line.length-whiteOffset-1);
if(whiteOffset > 0){
startOffset = lineStartOffset + whiteOffset;
} else{
startOffset = lineStartOffset - 1;
}
}
} catch (BadLocationException ex) {
ErrorManager.getDefault().notify(ex);
} finally{
bDoc.readUnlock();
}
</pre>
<li>Right at the end of the TextCompletionProvider, add the
following method:
<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>Finally, rewrite the interaction with the
TextCompletionItem so that, if there is a match
between the start of the word being typed and
the words in the text file, only the
matching words in the text file are shown
in the code completion box:
<pre class=examplecode>if (filter != null) {
while ((record = br.readLine()) != null) {
if(record.startsWith(filter)){
completionResultSet.addItem(new TextCompletionItem(record, startOffset, i));
}
}
} else {
while ((record = br.readLine()) != null) {
completionResultSet.addItem(new TextCompletionItem(record, startOffset, i));
}
}
</pre>
<li>Install the module again and notice that this time the list of
words narrows while you are typing:
<p><br><img border="1" src="../images/tutorials/cc/result-of-cc2.png" alt="Code completion in text file">
<li>Use the Options window to select a different file.
Notice that the very next time you press Ctrl-Space,
the entries from the new file appear in the code completion box:
<p><br><img border="1" src="../images/tutorials/cc/result-of-cc3.png" alt="Code completion in text file">
</ol>
</div>
<!-- ===================================================================================== -->
<!-- ===================================================================================== -->
<h2><a name="applying"></a>Applying What You Have Learned</h2>
<p>Whenever an entry is selected in the code completion box, save it to a new file.
Create another CompletionItem class that loads the new file and places the entries before
the entries from the first file (hint: use <tt>getSortPriority</tt>). Make sure that
the second CompletionItem class uses a new icon, so that the user is able to distinguish
the selected entries from the standard list of entries provided by the first CompletionItem. Extend the Options
window further so that the user can specify the supporting file, to which you will
write the selected entries.
<p>The ZIP file at the top of this tutorial includes the
extension to the Options window as well as the additional CompletionItem and its
integration in the CompletionProvider class.
<!-- ===================================================================================== -->
<p>
<!-- ===================================================================================== -->
<br>
<div class="feedback-box"><a href="https://netbeans.org/about/contact_form.html?to=3&amp;subject=Feedback:%20Code%20Completion%20Tutorial">Send Us Your Feedback</a></div>
<br style="clear:both;" />
<!-- ======================================================================================== -->
<h2><a name="nextsteps"></a>Next Steps</h2>
<p>For more information about creating and developing NetBeans modules, see the following resources:
<ul>
<p><li><a href="https://platform.netbeans.org/index.html">Module Developer's Resources</a></li>
<p><li><a href="https://netbeans.org/download/dev/javadoc/">NetBeans API List (Current Development Version)</a></li>
<p><li><a href="http://apisupport.netbeans.org/new-apisupport.html">New API Support-Proposal</a></li></ul>
</p>
<hr>
</body>
</html>