<!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 > 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 > 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 > 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 > Action > 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 > 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><filesystem></tt> tag, add the following tags: | |
<pre class=examplecode><folder name="Editors"> | |
<folder name="text"> | |
<folder name="x-text"> | |
<folder name="CompletionProviders"> | |
<file name="org-netbeans-modules-textfiledictionary-TextCompletionProvider.instance"/> | |
</folder> | |
</folder> | |
</folder> | |
</folder></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 > 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&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> |