The only reason you'd be providing code completion is if you're creating an editor for some specific syntax that the IDE doesn't already support. However, though this scenario is limited, within the confines of this scenario, code completion is vital. Basically, without code completion, your editor isn't going to be very nice. (Wait and see what the next NetBeans editor will look like, in 6.0, with immense improvements in the editor area, including a sped up code completion infrastructure.)
Anyway, this is the simplest approach to providing code completion. We start by creating a module project, then we use a wizard to add files that will recognize our new file type (which has ".hello" as its extension), and then we add three Java files that implement the Code Completion API. One of the files is the factory for the other two. We register the factory in the XML layer. Here we provide an absolutely minimal implementation. We will only be able to make the code completion box appear. We will not be able to do anything with it at this stage.
The first method, createTask(int i, JTextComponent jTextComponent), creates a CompletionTask. In the next step, we will register our CompletionProvider class in the XML layer, within a folder applicable to our data object's MIME type. Whenever the user types anything, the completion infrastructure asks all completion providers registered for the given MIME type to create tasks. The createTask(int i, JTextComponent jTextComponent) method is the method that creates the task. The task is invoked by the CompletionTask's query() method. So, let's provide for the creation of a simple task, using the AsyncCompletionTask, because we want to perform our code completion asynchronously:
public CompletionTask createTask(int queryType, final JTextComponent component) {
return new AsyncCompletionTask(new AsyncCompletionQuery() {
protected void query(CompletionResultSet resultSet, Document doc, int caretOffset) {
int startOffset = caretOffset-1;
final Iterator it1 = morningKeywords.iterator();
while(it1.hasNext()){
final String entry = (String)it1.next();
resultSet.addItem(new HelloCompletionItem(entry, startOffset, caretOffset));
}
final Iterator it2 = eveningKeywords.iterator();
while(it2.hasNext()){
final String entry = (String)it2.next();
resultSet.addItem(new GoodbyeCompletionItem(entry, startOffset, caretOffset));
}
resultSet.finish();
}
});
}
And, at the bottom of the file, here are our two sets of keywords:
private final static List morningKeywords = new ArrayList();
static{
morningKeywords.add("Good morning");
morningKeywords.add("Want some breakfast?");
morningKeywords.add("How are you?");
morningKeywords.add("Did you sleep well?");
morningKeywords.add("You need a shower!");
}
private final static List eveningKeywords = new ArrayList();
static{
eveningKeywords.add("Sleep well.");
eveningKeywords.add("Good night!");
eveningKeywords.add("Don't let the bed bugs bite.");
eveningKeywords.add("Sweet dreams.");
eveningKeywords.add("Don't snore so loud.");
}
Change the signature and add variables as follows:
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 HelloCompletionItem(String text, int dotOffset, int carretOffset) {
_text = text;
_dotOffset = dotOffset;
_carretOffset = carretOffset;
if(fieldIcon == null){
fieldIcon = new ImageIcon(Utilities.loadImage("org/netbeans/modules/helloworldfiletype/icon1.png"));
}
_icon = fieldIcon;
}
Next, for createDocumentationTask(), createToolTipTask(), and getInsertPrefix(), return null. Next, for getSortPriority, return 0. Finally, for instantSubstitution(), return false.
Only three methods need to be filled out. The first is render():
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);
}
Next, fill out getPreferredWidth() as follows:
public int getPreferredWidth(Graphics graphics, Font font) {
return CompletionUtilities.getPreferredWidth(_text, null, graphics, font);
}
Finally, change getSortText() as follows:
public CharSequence getSortText() {
return _text;
}
<folder name="Editors">
<folder name="text">
<folder name="x-hello">
<folder name="CompletionProviders">
<file name="org-netbeans-modules-helloworldfiletype-HelloCompletionProvider.instance"/>
</folder>
</folder>
</folder>
</folder>
It's maybe not all that much yet, but it is definitely a start on your journey into the land of code completion.
Yes. The code related ones (pre-init, etc.) provide code completion. The debugger also provides code completion when you add a watch.
Hi..Great Article!!!
I have a question: I am using beanshell inside an app and I would like to have code completion in my custom editor. Can I implement this code completion in a JEditorPane and use it OUTSIDE netbeans? (in my custom app)? Can you please guide me on that?
Many thanks
Bruno