| <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> | |
| <html xmlns="http://www.w3.org/1999/xhtml"> | |
| <head> | |
| <!-- -*- xhtml -*- --> | |
| <title>NetBeans Code Completion Tutorial for NetBeans Platform 7.0</title> | |
| <link rel="stylesheet" type="text/css" href="https://netbeans.org/netbeans.css"/> | |
| <meta name="AUDIENCE" content="NBUSER"/> | |
| <meta name="TYPE" content="ARTICLE"/> | |
| <meta name="EXPIRES" content="N"/> | |
| <meta name="developer" content="gwielenga@netbeans.org"/> | |
| <meta name="indexed" content="y"/> | |
| <meta name="description" | |
| content="A short guide to using the Editor Code Completion API."/> | |
| <!-- Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. --> | |
| <!-- Use is subject to license terms.--> | |
| </head> | |
| <body> | |
| <h1>NetBeans Code Completion Tutorial</h1> | |
| <p>This tutorial shows you how to implement the <a href="https://netbeans.org/download/dev/javadoc/org-netbeans-modules-editor-completion/overview-summary.html">Editor | |
| Code Completion API</a>. You will be shown how to implement the API | |
| in the context of HTML files. When the user invokes the | |
| code completion feature, a code completion box will appear, | |
| displaying words that can complete the text typed in the editor. At the | |
| end of this tutorial, HTML files will have a code completion | |
| box as follows:</p> | |
| <p><img src="../../images/tutorials/cc/65-result-of-cc.png" alt="Code completion in text file"/></p> | |
| <p>The content of the code completion box will come from | |
| country names retrieved from the JDK's | |
| <tt>java.util.Locale</tt> package.</p> | |
| <p><b>Contents</b></p> | |
| <p><img src="../../images/articles/70/netbeans-stamp.gif" class="stamp" width="114" height="114" alt="Content on this page applies to NetBeans IDE 7.0" title="Content on this page applies to NetBeans IDE 7.0"/></p> | |
| <ul class="toc"> | |
| <li><a href="#intro">Introduction to Code Completion Integration</a></li> | |
| <li><a href="#creating-the-module-project">Creating the Module Project</a></li> | |
| <li><a href="#implementing-the-code-completion-provider">Implementing the Completion Provider Class</a> | |
| <ul> | |
| <li><a href="#completiontask">Implementing the createTask Method</a></li> | |
| <li><a href="#autoquerytype">Implementing the getAutoQueryTypes Method</a></li> | |
| </ul></li> | |
| <li><a href="#implementing-the-code-completion-item">Implementing the Completion Item Class</a> | |
| <ul> | |
| <li><a href="#defining-the-action">Implementing the Action</a></li> | |
| <li><a href="#defining-the-filter">Implementing the Filter</a></li> | |
| <li><a href="#defining-the-tooltip-documentation">Implementing the Tooltip and Documentation Task</a></li> | |
| </ul></li> | |
| </ul> | |
| <p><b>To follow this tutorial, you need the software and resources listed in the following | |
| table.</b></p> | |
| <table> | |
| <tbody> | |
| <tr> | |
| <th class="tblheader" scope="col">Software or Resource</th> | |
| <th class="tblheader" scope="col">Version Required</th> | |
| </tr> | |
| <tr> | |
| <td class="tbltd1"><a href="https://netbeans.org/downloads/index.html">NetBeans IDE</a></td> | |
| <td class="tbltd1">version 7.0 or above</td> | |
| </tr> | |
| <tr> | |
| <td class="tbltd1"><a href="http://java.sun.com/javase/downloads/index.jsp">Java Developer Kit (JDK)</a></td> | |
| <td class="tbltd1">Version 6</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.</p> | |
| <h2 class="tutorial"><a name="intro"></a>Introduction to Code Completion Integration</h2> | |
| <p>Two classes apply to code completion and these will be developed in this tutorial:</p> | |
| <ul> | |
| <li><a href="http://bits.netbeans.org/dev/javadoc/org-netbeans-modules-editor-completion/org/netbeans/spi/editor/completion/CompletionItem.html">CompletionItem</a></li> | |
| <li><a href="http://bits.netbeans.org/dev/javadoc/org-netbeans-modules-editor-completion/org/netbeans/spi/editor/completion/CompletionProvider.html">CompletionProvider</a></li> | |
| </ul> | |
| <p class="tips">Both of these come from the | |
| <a href="http://bits.netbeans.org/dev/javadoc/org-netbeans-modules-editor-completion/org/netbeans/spi/editor/completion/CompletionProvider.html">Editor | |
| Code Completion API</a> and are implemented in this tutorial's module as | |
| CountriesCompletionItem and CountriesCompletionProvider.</p> | |
| <!-- ===================================================================================== --> | |
| <h2 class="tutorial"><a name="creating"></a>Creating the Module Project</h2> | |
| <p>In this section, we use a wizard to create the source structure that every NetBeans module requires. The | |
| source structure consists of certain folders in specific places and a set of files that are | |
| always needed. For example, every 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.</p> | |
| <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> | |
| <li>In the Basic Module Configuration panel, type <tt>org.netbeans.modules.countries</tt> | |
| as the Code Name Base. | |
| Do not select the "Generate XML Layer" checkbox and do not select the "Generate OSGi Bundle" checkbox. | |
| 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.</li></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).</p> | |
| <!-- ===================================================================================== --> | |
| <h2><a name="implementing-the-code-completion-provider"></a>Implementing the Completion Provider Class</h2> | |
| <p>The first class we will deal with when creating a code completion feature | |
| for HTML files is the <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> | |
| <li>In Class Name, type <tt>CountriesCompletionProvider</tt>. In Package, choose <tt>org.netbeans.modules.countries</tt>. | |
| Click Finish.</li> | |
| <li><p>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. You have now set a dependency | |
| on the Editor Code Completion module, which provides the API classes that we need in this tutorial.</p> | |
| <p>Do the same for "MIME Lookup API", which provides the Java annotation for registering | |
| completion providers, and the "Utilities API".</p></li> | |
| <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. You should now see this:</p> | |
| <pre class="examplecode">package org.netbeans.modules.CountryCodeCompleter; | |
| import javax.swing.text.JTextComponent; | |
| import org.netbeans.spi.editor.completion.CompletionProvider; | |
| import org.netbeans.spi.editor.completion.CompletionTask; | |
| public class CountriesCompletionProvider implements <a href="https://netbeans.org/download/dev/javadoc/org-netbeans-modules-editor-completion/org/netbeans/spi/editor/completion/CompletionProvider.html">CompletionProvider</a> { | |
| public CountriesCompletionProvider() { | |
| } | |
| public <a href="https://netbeans.org/download/dev/javadoc/org-netbeans-modules-editor-completion/org/netbeans/spi/editor/completion/CompletionTask.html">CompletionTask</a> <a href="http://www.netbeans.org/download/dev/javadoc/org-netbeans-modules-editor-completion/org/netbeans/spi/editor/completion/CompletionProvider.html#createTask(int,%20javax.swing.text.JTextComponent)">createTask(int queryType, JTextComponent component)</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 component, String typedText)</a> { | |
| } | |
| } | |
| </pre> | |
| <li>Before coding the CompletionProvider class, let's register it in the XML layer file. | |
| <pre class="examplecode">package org.netbeans.modules.countries; | |
| import javax.swing.text.JTextComponent; | |
| <b>import org.netbeans.api.editor.mimelookup.MimeRegistration;</b> | |
| import org.netbeans.spi.editor.completion.CompletionProvider; | |
| import org.netbeans.spi.editor.completion.CompletionTask; | |
| <b>@MimeRegistration(mimeType = "text/html", service = CompletionProvider.class)</b> | |
| public class CountriesCompletionProvider implements CompletionProvider { | |
| @Override | |
| public CompletionTask createTask(int queryType, JTextComponent component) { | |
| throw new UnsupportedOperationException("Not supported yet."); | |
| } | |
| @Override | |
| public int getAutoQueryTypes(JTextComponent component, String typedText) { | |
| throw new UnsupportedOperationException("Not supported yet."); | |
| } | |
| }</pre> | |
| <p class="tips"> Read <a href="http://netbeans.dzone.com/news/mimelocation-mimeregistration">@MimeLocation, @MimeRegistration and @MimeRegistrations added</a> for details | |
| on the annotation above.</p> | |
| </li> | |
| </ol> | |
| <div 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.</p> | |
| <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.</p></li> | |
| <li>Place the cursor on the line. Click the lightbulb that appears and let | |
| the IDE add import statements. Also let it create a skeleton method for the | |
| <a href="https://netbeans.org/download/dev/javadoc/org-netbeans-modules-editor-completion/org/netbeans/spi/editor/completion/support/AsyncCompletionTask.html#query(org.netbeans.spi.editor.completion.CompletionResultSet)">query</a> method.</li> | |
| <li>Next, we need to specify which code completion type we are working with. When | |
| the user clicks Ctrl-Space, or an alternative key combination defined by the user, | |
| our code completion entries should appear. This is the COMPLETION_QUERY_TYPE. Alternative | |
| query types exist, such as DOCUMENTATION_QUERY_TYPE and TOOLTIP_QUERY_TYPE. We need to test | |
| whether the user pressed the keys applicable to the COMPLETION_QUERY_TYPE. Therefore add | |
| the following test to the start of the <tt>createTask</tt> method: | |
| <pre class="examplecode">if (queryType != CompletionProvider.COMPLETION_QUERY_TYPE) | |
| return null;</pre> | |
| <p>At this stage, the <tt>createTask</tt> method should look as follows:</p> | |
| <pre class="examplecode">public CompletionTask createTask(int queryType, JTextComponent component) { | |
| if (queryType != CompletionProvider.COMPLETION_QUERY_TYPE) | |
| return null; | |
| return new AsyncCompletionTask(new AsyncCompletionQuery() { | |
| protected void query(CompletionResultSet completionResultSet, Document document, int caretOffset) { | |
| } | |
| }); | |
| }</pre> | |
| </li> | |
| </ol> | |
| </div> | |
| <div 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.</p> | |
| <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 component, String string) { | |
| return 0; | |
| } | |
| </pre> | |
| <p class="tips">By default, the | |
| user would press Ctrl-Space to make the code completion box appear. Later, we | |
| can add a new option to our Options window extension, such as a checkbox which | |
| will change the int returned in this method from 0 to 1, so that the code completion | |
| box appears automatically. (There are also other types of queries, as | |
| shown <a href="https://netbeans.org/download/dev/javadoc/org-netbeans-modules-editor-completion/constant-values.html#org.netbeans.spi.editor.completion.CompletionProvider.COMPLETION_QUERY_TYPE">here</a>.) | |
| </p></li> | |
| </ol> | |
| </div> | |
| <!-- ===================================================================================== --> | |
| <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.</p> | |
| <ol><li>Right-click the | |
| <tt>CountryCodeCompleter</tt> project and choose New > Java Class. | |
| In Class Name, type <tt>CountriesCompletionItem</tt>. In Package, choose | |
| <tt>org.netbeans.modules.countries</tt>. Click Finish.</li> | |
| <li>We will return to this class in later steps. For now, we | |
| will fill out the query method that we defined in the CompletionProvider class. | |
| Fill out the AsyncCompletionTask as follows, and note | |
| the explanatory comments in the code: | |
| <pre class="examplecode">return new 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(); | |
| } | |
| }, component);</pre> | |
| <p> A red underline remains, after you let the IDE add various import statements. | |
| The error underline tells you that the CompletionItem's constructor does not expect the | |
| values that you are passing to it. In the next step, we will fill out the CompletionItem | |
| so that it meets the requirements of the CompletionProvider.</p> | |
| <p class="tips"> Read <a href="http://blogs.oracle.com/geertjan/entry/java_classes_in_code_completion">Java Classes in Code Completion</a> | |
| to learn how to put Java classes in the code completion box, instead of the locales that are used above.</p> | |
| </li> | |
| <li>In the 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> | |
| <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> | |
| <p><img src="../../images/tutorials/cc/icon.png" alt="icon"/></p> | |
| <p>If you like, you can right-click the image above and save it to the location | |
| specified in the ImageIcon definition above.</p></li> | |
| <li>Next define the <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:</p> | |
| <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:</p> | |
| <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>.</p></li> | |
| <li>Right-click the module and choose Run. | |
| A new instance of the IDE starts up and installs your module. Open an HTML file in | |
| the IDE. Type something and press Ctrl-Space. | |
| <p>You should now see the following:</p> | |
| <p><img src="../../images/tutorials/cc/65-result-of-cc1.png" alt="icon"/></p> | |
| <p class="tips"> When you press Enter in the list above, nothing happens. That is because | |
| we have not defined the <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.</p></li> | |
| </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.</p> | |
| <ol> | |
| <li>Fill out the <tt>defaultAction()</tt> method | |
| as follows: | |
| <pre class="examplecode">public void defaultAction(JTextComponent component) { | |
| StyledDocument doc = (StyledDocument) component.getDocument(); | |
| doc.insertString(caretOffset, text, null); | |
| //This statement will close the code completion box: | |
| Completion.get().hideAll(); | |
| } | |
| </pre> </li> | |
| <li>Install the module again. Notice that when | |
| you press Enter or click the mouse over an entry | |
| in the code completion box, the selected text is added at the cursor | |
| in your HTML file. However, the text that you typed | |
| prior to calling up the code completion box is | |
| not removed. Below, the "V" should be removed, because "Vietnam" | |
| was selected from the code completion box: | |
| <p><img src="../../images/tutorials/cc/65-result-of-cc2.png" alt="icon"/></p> | |
| <p>In the next section, we will add functionality to detect the number of | |
| characters that have been typed and remove them when the selected country | |
| is inserted into the document.</p></li> | |
| </ol> | |
| </div> | |
| <div 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.</p> | |
| <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(); | |
| } | |
| }, component);</pre> </li> | |
| <li>Right at the end of the CountriesCompletionProvider, add the | |
| following two methods: | |
| <pre class="examplecode">static int getRowFirstNonWhite(StyledDocument doc, int offset) | |
| throws BadLocationException { | |
| Element lineElement = doc.getParagraphElement(offset); | |
| int start = lineElement.getStartOffset(); | |
| while (start + 1 < lineElement.getEndOffset()) { | |
| try { | |
| if (doc.getText(start, 1).charAt(0) != ' ') { | |
| break; | |
| } | |
| } catch (BadLocationException ex) { | |
| throw (BadLocationException)new BadLocationException( | |
| "calling getText(" + start + ", " + (start + 1) + | |
| ") on doc of length: " + doc.getLength(), start | |
| ).initCause(ex); | |
| } | |
| start++; | |
| } | |
| return start; | |
| }</pre> | |
| <pre class="examplecode">static int indexOfWhite(char[] line){ | |
| int i = line.length; | |
| while(--i > -1){ | |
| final char c = line[i]; | |
| if(Character.isWhitespace(c)){ | |
| return i; | |
| } | |
| } | |
| return -1; | |
| } | |
| </pre> </li> | |
| <li>Change the constructor of the 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 component) { | |
| try { | |
| StyledDocument doc = (StyledDocument) component.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> | |
| <li>Install the module again and notice that this time the list of | |
| words narrows while you are typing: | |
| <p><img src="../../images/tutorials/cc/65-result-of-cc.png" alt="Code completion in text file"/></p> | |
| <p>When you press Enter, the characters that you typed are removed and replaced by | |
| the country selected from the code completion box.</p></li> | |
| </ol> | |
| </div> | |
| <div class="indent"> | |
| <h3 class="tutorial"><a name="defining-the-tooltip-documentation"></a>Implementing the Tooltip and Documentation Task</h3> | |
| <p>Some optional features can also be added, as described below.</p> | |
| <ol> | |
| <li>Optionally, you can implement the createToolTipTask method in the CountriesCompletionItem, with | |
| this result when Ctrl-P is pressed: | |
| <p><img src="../../images/tutorials/cc/65-result-of-cc3.png" alt="Code completion in text file"/></p> | |
| <p>Here is the code that will achieve the result shown in the screenshot above:</p> | |
| <pre class="examplecode"> | |
| 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> | |
| <li>Optionally, you can provide documentation for the entries in the code completion box: | |
| <p><img src="../../images/tutorials/cc/65-result-of-cc4.png" alt="Code completion in text file"/></p> | |
| <p>Make use of the documentation box like this, by implementing the createDocumentationTask method | |
| in the CountriesCompletionItem class:</p> | |
| <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:</p> | |
| <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> | |
| <p><img src="../../images/tutorials/cc/65-result-of-cc5.png" alt="Code completion in text file"/></p> | |
| <p>When the user clicks the URL button, the browser set in the IDE will open, displaying | |
| the content provided by the specified URL.</p> | |
| </li> | |
| </ol> | |
| </div> | |
| <p>Congratulations, you have now completed a simple implementation of a code completion | |
| integration module.</p> | |
| </body> | |
| </html> |