Thursday Aug 28, 2008

Update on the NetBeans Podcast!

Lloyd and I started doing recordings for the next NetBeans Podcast today. More will be done during the coming week (so there's still time to send your suggestions to nbpodcast AT netbeans DOT org), including, probably, an interview with one of the NetBeans Platform customers. We're aiming to release it on Monday, 8 September. One thing you'll hear is Jaroslav Tulach announcing the winner of the "Will Code HTML for Food" competition. And, of course, among many other things, there'll also be a NetBeans Podcast Puzzler. For now, meet Cormac Lawless from Ireland, holding his prize (a signed copy of "Rich Client Programming: Plugging into the NetBeans Platform") as the winner from two podcasts ago ("What does NetCAT stand for?"):

Cormac is the support manager with Ram Technologies Ltd, which is part of the Ram Group. He is responsible for hardware and software support for Duplication Systems in Ireland. He says: "I have recently undertaken a Java programming course so this book should help me as I progress through the course."

Well, if you're interested in developing large, complex Java desktop applications, you've certainly got hold of the right book, Cormac. The NetBeans Platform will give you a great starting point, guided by the book you won in the puzzler!

Tuesday Aug 26, 2008

Jumping from the Swing Explorer Back into NetBeans IDE

I saw Maxim's announcement about a NetBeans plugin for his Swing Explorer and tried it. First I was unable to install his plugin. But then I checked out his sources and rebuilt the plugin and installed it and everything worked as expected. For the first time, I was able to jump to the source, from within the Swing Explorer, as below:

And here's the new "Addition Trace" tab in action, where you can see every line of code that is executed, with hyperlinks that let you jump back into the NetBeans Java Editor:

Really brilliant. By the way, this is the plugin that Maxim and I started back at JavaOne 2008, as described in Coding a Swing Explorer Plugin for NetBeans IDE .

Monday Aug 25, 2008

Collaborative Writing in a Distributed Environment

Here you can read how Alex Kotchnev is putting together a few people to write a new book on Tapestry 5. I got an e-mail from him this morning, asking: "Since you're the only person that I know that has written a technical book, I was wondering if you could give me some advice about it e.g. how did you guys collaborate on the RCP book, what worked, what didn't, how did you keep the code from breaking, stuff like that..."

Well, since I've now been through a few collaborative book-writing/editing processes, all of them involving contributors who were distributed across the globe, here are my thoughts, take from them what you will, reject what doesn't make sense. I'd be interested in hearing other people's thoughts on this topic too.

First of all, what are the distinct factors that are involved in collaborative writing in a distributed environment (hereafter CWiDE, pronounced "cwide", with the "c" like a "k", the whole word rhyming with "pride")? In other words, what are my assumptions. Firstly, the collaborators (i.e., the writers/editors/reviewers) are potentially in different parts of the world and have, in the most extreme case, never seen each other before. Secondly, the type of books that we're talking about here are typically written in the collaborators' spare time (i.e., they're actually developers, but they're very enthusiastic about something, and that something forms the subject of the book). Thirdly, the collaborators (at least the writers themselves) are programmers.

So given that CWiDE is primarily carried out by programmers who don't have much time in a distributed environment, it stands to reason that the writing project should be treated as any other application development project. Why? Well, quite a lot can be automated and, since you're distributed and are unlikely to have face-to-face meetings, the more that is made to be consistent, the better. Plus, you have the know-how (i.e., you know about Ant, you know about continuous builds, you know about XML), therefore why not employ it when writing your book? Maybe set up on a project on java.net and get everyone to check in their work through Subversion or CVS, etc.

So since your writing project is comparable to an application development project, you need to find the appropriate methodologies and tools and then construct some kind of development cycle. For "Rich Client Programming: Plugging into the NetBeans Platform", we used DocBook, for which we wrote a plugin for NetBeans IDE, which is where we wrote the whole book:

And every chapter was equivalent to a Java source file that we simply checked into CVS. One nice thing was that we were able to generate HTML output from our DocBook chapters:

Plus, we were able to extend our plugin as we went along! I.e., we were writing about the NetBeans APIs, so more often than not, I applied the code I was writing about to the DocBook plugin (e.g., I created new code snippets and I extended the DocBook editor with new code generating menu items). That was kind of interesting—having the book we were writing benefit from the content that we were writing about.

So, Alex, I hope this helps and good luck with your project. On a sidenote, if anyone is interested in translating a German book into English, please drop me a line and we can set up a process as described above—plus you'll gain some knowledge about the NetBeans APIs.

Jumping to Related Places in the NetBeans Java Editor

I learned something interesting about the NetBeans Java Editor today. Say you have an import statement (or anything else) selected, as here:

Now look at those browny-greeny marks in the right sidebar. When you click them, the cursor jumps to places where the selected item is used. So, in the case of import statements, you can click the browny-greeny mark and then find yourself in places in the code where you're doing something with that class.

I never knew that and it's pretty cool.

Sunday Aug 24, 2008

Which of these is "better"?

Today I was studying this piece of code:

Lookup lkp = Lookups.forPath("MessageProviders");  

Collection  coll = (Collection) lkp.lookupAll(MessageInterface.class);  
for (Iterator it = coll.iterator(); it.hasNext();) {  
     MessageInterface messageInterface = (MessageInterface) it.next();  
     jTextArea1.append(messageInterface.getMessage());  
}

I figured out that I was able to rewrite it to this:

Lookup lkp = Lookups.forPath("MessageProviders");

Collection<MessageInterface> coll = (Collection<MessageInterface>) lkp.lookupAll(MessageInterface.class);
for (MessageInterface it : coll) {
    jTextArea1.append(it.getMessage());
}

Which of the two, in your opinion (this is inevitably going to be a subjective question of taste) is "better"? And why?

Friday Aug 22, 2008

Video: Ted Neward, Tim Boudreau, and Me on the NetBeans Platform

During the most recent JavaOne, Ted Neward interviewed Tim and myself about the NetBeans Platform, in light of the release of "Rich Client Programming: Plugging into the NetBeans Platform". Yesterday, while googling my name (do it once a month, not more otherwise you'll think you're weird, not less otherwise you'll miss the gossip), I came across the result (very cool despite/because severely shortened). I really enjoyed it a lot, because it really shows Tim and I (and, possibly, Ted Neward) at our best:

Part 1:

Summary: It's ridiculously easy to create NetBeans plugins.

Part 2:

I'm really impressed by the result! Both Tim (and Ted) and I come across like (relatively) sane people. Go figure.

FAQ Nodes in TopComponent

Combining the info from yesterday's blog entry with the Quick Search Integration Tutorial, you can implement an ExplorerManager Provider in a TopComponent, with this result:

I.e. a FAQ window in the navigator position in the IDE for the NetBeans User FAQs.

In other news. Today during breakfast at a local breakfast place, I met two people who are behind Future Cities Forum. They've picked up a lot of open source perspectives and want to apply them to their project. So watch that space, open source believers everywhere.

Thursday Aug 21, 2008

Create Lazy Children with NetBeans Platform 6.5

The NetBeans System Properties Module Tutorial uses Children.Keys to create the children of the node. There are two other (better) ways of doing this instead:
  • org.openide.nodes.ChildFactory. Use when creation of nodes would otherwise take a long time, because it creates them asynchronously. To experiment with it, replace the "AllPropsChildren" class in the tutorial with the following:

    public class AllPropsChildren extends ChildFactory<String> {
    
        @Override
        protected boolean createKeys(List<String> keys) {
            Properties p = System.getProperties();
            Enumeration e = p.propertyNames();
            while (e.hasMoreElements()) {
                keys.add(e.nextElement().toString());
            }
            Collections.sort(keys);
            return true;
        }
    
        @Override
        protected Node createNodeForKey(String key) {
            return new OnePropNode(key);
        }
          
    }

    Read the ChildFactory Javadoc, as well as this example for details.

  • org.openide.nodes.Children.Keys(boolean lazy). From 6.5 Beta onwards (as explained here in the API Changes document), children can be created lazily. I.e., say you have +1000 nodes that need to be created. If the children are lazy, they will only be created as the user makes them visible by scrolling in the explorer view. Until that point, they're not created. The only difference between using the standard org.openide.nodes.Children.Keys and the lazy version is to pass in the boolean true via the constructor (i.e., you're saying 'yes I want my children to be lazy'). This approach is/will be used throughout the IDE to speed up performance and is, thanks to the API, also possible to use in your own implementations.

So, when deciding to use one or the other, ask yourself this: "Will I need to create +1000 nodes?" If your answer is "yes", create the children lazily by passing in true to Children.Keys. If your answer is "no", then use ChildFactory instead, particularly if you anticipate a lot of processing time being required, because ChildFactory will create the children asynchronously.

Tuesday Aug 19, 2008

Sakila and "org.netbeans.swing.etable.ETable"

I read about the Sakila sample database in James' blog and thought it a good opportunity to try out the new "ETable" component. "ETable? What's that?" you might be wondering. ETable is a Swing component that extends JTable (hence the "E" for "extension"). It was created by Nokia in 2003 when David Strupl worked there as a freelancer. David is now back in the NetBeans engineering team and the ETable is part of the NetBeans Platform, within the "org-netbeans-swing-outline.jar" in "platform9".

Here it is in action, notice that one can sort (for which I needed to do no coding whatsoever) and that there's a dialog that can be used to hide columns that you, as the end user, don't want to see (no coding for that either):

The data is from the aforementioned Sakila database. (I did no coding whatsoever to create the small app above, just dragged the ETable onto the JFrame and then dragged the table from the Services window into the ETable.)

You're able to prevent the hiding of columns very simply, like this:

eTable1.setColumnHidingAllowed(false);

So what does the "ETable" provide, exactly, i.e., aside from the above briefly mentioned features? Broadly, David told me that they created this component based on features that Excel spreadsheets provide. I.e., they looked at Excel spreadsheets and thought: "Wouldn't it be cool if we had these features in our own tables?" So, the ETable is inspired by Excel's features, in particular those that were missing in the JDK 1.4 (i.e., 2003) JTable. In addition, David told me they decided to base the tree-like features on Tim Boudreau's Outline component.

Here are some further notes on the feature candidates for the ETable (most of these are implemented), which are portions of 2003 e-mails between David Strupl and the developers from Nokia.

  • Properties support, i.e., the table should have an API to find out the properties of the displayed object and render the table columns dependent on that.
  • Column selection, i.e., there should be a selection dialog for selecting the visible table columns (based on the properties model).
  • Popup menus, i.e., table rows should display popup menus for the selected objects (based on enode functionality).
  • Sorting, possibly also multi-way.
  • Improved layouting, i.e., Sensible initial layout based on data content.
  • Possibility to persist the layout.
  • Double-click/ctrl-+ sizing of columns.
  • Fixed first column (i.e., doesn't scroll along horizontally).
  • Categorization/tree table functionality (i.e., hierarchy API).
  • Keyboard jumping/quick find? (I.e., hit a key/set of keys to jump to a particular line of the table.)
  • Quickfilter? (I.e., show only rows with a particular value in a column).

Here's multisort in action. First, I click the header of the Last Name column and then the values are sorted alphabetically:

Next, I hold down the shift key and then click the header of the First Name column:

Now look above at the First Name column and notice that they're alphabetical, within the alphabetical-sort of the Last Name column.

Next, we'll look at the Quickfilter mentioned in the list above. I simply type this:

eTable1.setQuickFilter(1, "AKROYD");

And then the result is like this:

Various other customizations are possible. For example, do you like the ability to hide the columns, but not the dialog for doing so? Add one extra statement to your code:

eTable1.setPopupUsedFromTheCorner(true);

Then you'll have a small popup, instead of the dialog, for hiding columns, like this:

How to get started with "ETable"? Simply add "org-netbeans-swing-outline.jar" from "platform9" to your app's classpath. Then browse to it via the Palette Manager and add the "ETable" to the Palette so that you can drag it into your Swing containers from there.

Monday Aug 18, 2008

Deadline Approaching for the 1st Annual "Will Code For Food" Competition

As mentioned in Jarda's blog, don't forget the 1st Annual "Will Code For Food" Competition! The closing date for the competition is now set as the 28th of August, i.e., you have 10 more days! The prize for the best pic is a signed copy of "Practical API Design: Confessions of a Java Framework Architect" by Jarda himself:

The current entries for the competition are as follows:

Take inspiration from the above entries (click the links above for seeing the entries) and remember the guidelines in the original announcement of the competition, i.e., the earlier blog entry called 1st Annual "Will Code For Food" Competition.

If you need some more context, read Jarda's recent blog entry on this topic. Good luck everyone!

Saturday Aug 16, 2008

Thanks Sandip!

Some pretty bad news—Sandip Chitale, one of the key players in the popularization of the NetBeans Platform, has left Sun. Although he never worked in any official capacity in relation to the NetBeans Platform, his contributions were really significant:

  • His blog is a rich mine for anyone interested in the NetBeans Platform. Unlike virtually everyone else, he didn't only write about the plugins he created, but he provided LOTS of code that others could learn from. Over the years, in particular when the official documentation was a lot more sparse than it is now, his blog was one of the few bastions of clear reference materials for the NetBeans Platform.

    Most recently, I learned a lot from his entries relating to the extendability of the NetBeans Java editor. In fact, nowhere in the world is there more info on this than in his blog! Here's a list of some of them for anyone interested in the NetBeans Java editor:

    Fortunately his blog will continue to exist and will continue being a central resource for countless interesting NetBeans API problems. I know I'll keep going back to it, there's so many things I haven't had the time to look into yet.

  • Several NetBeans Platform tutorials could not have been written without Sandip. A clear example is the NetBeans Java Language Infrastructure Tutorial, which is the starting point for anyone wanting to learn about the NetBeans Java editor. I wrote it, based completely on one of Sandip's modules! Not only that: the entire introduction to that tutorial comes verbatim from an e-mail he sent me when I wanted to know how the Retouche APIs fit with the previous JMI approach underpinning the editor. Aside from clear fingerprints such as these, he's also reviewed countless tutorials, in particular when I first started writing them and didn't have much of a clue about what it was all about.

  • His helpfulness on the dev@openide.netbeans.org mailing list also goes back several years. There have been many periods in time when Sandip was one of the only people responding to questions that users sent to the mailing list. And he was able to answer questions on a very wide range of topics, because he'd implemented the NetBeans APIs both in his own work-related projects as well as in his own hobby-like experimental modules. Aside from his helpfulness on the mailing lists, I've always found him to be very helpful and responsive to any questions I've sent him directly. Often he'd write back with just one or two lines referring to classes that might be useful in solving whatever problem I had at the time—exactly enough info for me to continue my own investigations from there.

  • On top of all that, most of Rich Client Programming: Plugging into the NetBeans Platform could not have been written without him. He patiently and with infinite care reviewed most of the 2nd half (most of it mine) over and over again. And I still have all the notes to prove it!

  • Also, in particular around the early days of NetBeans Plugin tooling being introduced (i.e., NetBeans IDE 5.0), Sandip played an incredible role in evangelizing the NetBeans Platform. One of the first technical interviews I ever did was this one with Sandip. In it, note these words:

    In other words, Sandip very successfully introduced James Gosling to the practical side of working with the NetBeans Platform. If that isn't a significant contribution, I don't know what is. Maybe his hands-on-lab at JavaOne two (or three?) years ago? A room full of new people to the NetBeans Platform, guided through some pretty challenging modules, overseen by Sandip and a few others, but all based on modules that Sandip himself had written.

Now, look again at all the above and then do a search on the NetBeans Wiki for "Sandip". Here, I did it for you. Notice something? Sandip's function was, all along, a senior engineer in the web area (Creator, then Visual Web, and then various other web-things, such as analyzing ways in which the IDE might integrate an embedded browser). He never had an official function in the NetBeans Platform area, yet his contribution is immeasurable. (In the IDE itself, he contributed far too much to mention, but as you can read here whenever you move or copy a line up/down, you should quietly say "thanks Sandip!" to yourself.)

So, wherever Sandip is going, they're very lucky to have him! Thanks for everything Sandip and hope to run into you again soon.

Friday Aug 15, 2008

Migrating from TreeTableView to OutlineView

Here, based on an existing example, is how to migrate from "TreeTableView" to the new NetBeans Platform 6.5 "OutlineView":
  1. Install the Marilyn TreeTableView Sample.

  2. Create the sample, i.e., choose "Samples | Java | Marilyn" in the New Project wizard and complete the steps in the wizard.

  3. Add the following JARs from "platform9" folder in the NetBeans installation directory to the app's classpath: org-openide-actions.jar, org-openide-awt.jar, org-openide-dialogs.jar, org-openide-explorer.jar, org-openide-nodes.jar, org-openide-util.jar.

  4. Run the application to check everything is working and that you're set for migration.

  5. Open demo.MyFirstFrame.java in the Design view. Delete the Swing component you find there, which is the TreeTableView.

  6. Right-click in the Palette to the right of the Design view and choose Palette Manager. Click "Add from JAR" and browse to "org-openide-explorer.jar". From the list of available components, choose "OutlineView" and click Next. Add it to any palette category and then click Finish.

  7. From the "platform9" folder, add the org-netbeans-swing-outline.jar onto the app's classpath.

  8. From the category where you added the "OutlineView" component, drag it onto the JFrame. Then switch to the Source view.

  9. Change these lines:
    treeTableView1.setProperties(props);
    treeTableView1.setRootVisible(false);

    To these lines:

    outlineView1.setProperties(props);
    //treeTableView1.setRootVisible(false);

  10. Run the application again and now you have the same result as before, except that you're using "OutlineView" instead of "TreeTableView".

In other words, you're using the same concepts as before, i.e., the Nodes API, the ExplorerManager, and the NodeTableModel. However, the explorer view is changed to one that is not buggy (which was the original reason for replacing TreeTableView) and has a few extra features, based on the "Outline" component. These additional features will be discussed here soon.

Wednesday Aug 13, 2008

Project Type Sample

In the coming weeks, a free on-line NetBeans Platform Training Course will be made available. It will be based on Tim's excellent "PovRay" series, which is currently severely out of date and has been causing a lot of questions for a while, even though those who work their way through the problems tend to end up with the result they were looking for in the first place. In that context, his tutorial will be removed from the web because it will be part of the course. The most interesting part of his tutorial, on a technical NetBeans Platform level, is the material relating to the creation of NetBeans project types. Those taking the course won't necessarily be interested in that, but will probably be taking the course to gain a general understanding of how to work with the NetBeans Platform.

But what about those who're interested specifically in creating new NetBeans project types? They first need to ask themselves whether they really need a new project type because since 6.1 it is possible to extend existing project types, which should be seen as the preferred approach, as outlined in the NetBeans Project Type Extension Module Tutorial. However, what if you STILL need to create a new project type? For these special cases, a sample is now available:

http://plugins.netbeans.org/PluginPortal/faces/PluginDetailPage.jsp?pluginid=12170

It will create a new project type. The project type will treat any folder as a NetBeans project if it has a subfolder called "texts". The content of the "texts" folder will be displayed in the Projects window. The project will have some of the typical project-level commands at its disposal:

So, if in the coming weeks the PovRay tutorial suddenly disappears, now you know why. At that point, you can either take the free on-line NetBeans Platform Training Course or (and in the period where it isn't available yet) you can simply download the sample and adapt it to your own needs.

The sample was created in NetBeans IDE 6.5 Beta, so you need at least that release if you need to work with it.

Tuesday Aug 12, 2008

OutlineView Sample

The Plugin Portal now provides a new sample demonstrating the new (NetBeans Platform 6.5) Explorer View called "OutlineView", which is a simpler and more powerful alternative to the NetBeans TreeTableView:

http://plugins.netbeans.org/PluginPortal/faces/PluginDetailPage.jsp?pluginid=12094

After downloading and installing the plugin, you will find the sample here:

After completing the wizard, you will have these sources:

Run the sample module and you will have a TopComponent with this content:

A new tutorial that will result in the above sample will be created this week. It will be based on these two resources:

So watch this space for the announcement of the new tutorial that relates to this subject. In the meantime, feel free to download the sample and inspect the sources and adapt them to your own scenarios.

Sunday Aug 10, 2008

Wicket in Action: Undoubtedly The Wicket Bible

Without question, Wicket in Action, soon to be released by Manning, is the be-all and end-all when it comes to Wicket. How could it be otherwise, since it is written by two of its core members and key players, Martijn Dashorst and Eelco Hillenius? I've been lucky enough to have been given a chance to examine it prior to its release... and here are my impressions.

First of all, if you're new to Wicket look no further. "Wicket in Action" provides everything you need. In particular for beginners, chapter 4 ("Building a cheesy Wicket application") is excellent: it shows you step by step how to create a pretty advanced Wicket application... and covers 30 pages. That's pretty impressive and it's a very thorough introduction to what Wicket offers you. My favorite aspects of Wicket are (1) its separation of concerns between design (HTML) and coding (Java) and (2) its component model for Ajax (hurray, this means no need to touch JavaScript at all, while still getting partial page refresh). Both these aspects are dealt with at length in the book, as well as a myriad of others, in fact everything that Wicket is about is covered in detail in this book. I have read large chunks of the book in great detail, and I worked through all the code samples in the first half, and have found it very thorough and detailed.

Here's a quick break down of the sections: "Part 1: Getting Started with Wicket" ("What is Wicket?", "The architecture of Wicket", "Setting up a Wicket Project", "Creating a cheesy Wicket application"), "Part 2: Getting a basic grip on Wicket" ("Understanding models", "Using basic components", "Using forms for data entry", "Composing your pages"), "Part 3: Advanced Wicket" ("Creating Custom Components", "Working with Wicket resources", "Rich Components and Ajax", "Authentication and authorization", "Localization", "Multi-tiered architecture", "Putting your application in production", "Component index").

As you can see from the above, it's a very meaty book (375 pages in my review copy). After the first section, which is mostly architectural and introductory, a set of themes are covered in part 2. It's really good that the first of these themes is "Wicket models", since that's just about the most complex area in Wicket, because it is quite foreign to web frameworks. However, if you think of Swing development, then models aren't so foreign anymore. Both in Swing and in Wicket, models serve as abstraction layers for working with data, which is a comparison that could be made more strongly in this book. Each of the models is discussed in great detail with a lot of very practical (and compilable) code snippets throughout.

One quirky aspect of this book is its reliance on cheese as a metaphor for application development. (E.g: "[K]nowing what a lasagna is and how it tastes is not enough to create your own lasagna. You will need to know which ingredients you need, when and how to apply them.") In fact, the example application built in chapter 4 is an on-line cheese store. This is a pretty fun approach and the digressions into the world of cheese, with which most chapters begin, provide useful relief from the intensity of the world of code.

It is a well written book, presented with the enthusiasm that is typical of those who are steeped in everything the framework provides and have the gift of explaining it all, step by step. Both beginners and more advanced Wicket users should grab this one as soon as it is available.

Saturday Aug 09, 2008

How to Create a Caret Aware Code Completion Box

Casper Bang asked a great question at the end of my previous blog entry about the new code completion tutorial:

We have a desire in our team to get code completion for JPA queries. However, JPA is an embedded DSL inside string annotations. Does the approach described in the tutorial also apply if one wanted to "sub-tokenize" and provide completion inside a String token of a x-java MIME type?

The answer is, of course, "Yes!" To set up a scenario, I recreated my code completion plugin so that it now ONLY works for Java parameters. I.e., as you can see in the screenshot below (more or less), whenever I invoke code completion and ONLY IF the cursor is on a parameter (or in the place where a parameter SHOULD BE defined), will my custom items be displayed in the code completion box:

The three high level clues to understanding how to do this are provided by the following:

Especially the last of the above is extremely relevant (it is from Sandip's great blog), it taught me everything I now know in this case, but the other two should be read first (especially the first, don't worry too much about the second, just be aware that it is there and can be useful when actually implementing a scenario).

In short, starting from the sample that the code completion tutorial provides, you need to do the following:

  1. Change the layer.xml file so that the code completion plugin will apply to Java files instead of HTML files. Do this by simply replacing "text/html" with "text/x-java" in the folder hierarchy. Now, anywhere in a Java file, you will see your code completion entries. That's not what you want, you only want to see it in very specific cases.

  2. So, as discussed in Sandip's blog entry, you need to create a class that extends CaretAwareJavaSourceTaskFactory:

    import org.netbeans.api.java.source.CancellableTask;
    import org.netbeans.api.java.source.CompilationInfo;
    import org.netbeans.api.java.source.JavaSource.Phase;
    import org.netbeans.api.java.source.JavaSource.Priority;
    import org.netbeans.api.java.source.support.CaretAwareJavaSourceTaskFactory;
    import org.openide.filesystems.FileObject;
    
    public class CountriesCompletionJavaSourceTaskFactory extends CaretAwareJavaSourceTaskFactory {
        
        public CountriesCompletionJavaSourceTaskFactory() {
            super(Phase.ELEMENTS_RESOLVED, Priority.LOW);
        }
    
        public CancellableTask<CompilationInfo> createTask(FileObject fileObject) {
            return new CountriesCompletionTask(this, fileObject);
        }
        
    }

  3. Next, register the above class in META-INF/Services, for the "org.netbeans.api.java.source.JavaSourceTaskFactory" interface.

  4. Then create the task that you see referred to above, i.e., "CountriesCompletionTask", which exists for no other reason than to toggle a boolean whenever the required element is found under the cursor:

    import com.sun.source.util.TreePath;
    import javax.lang.model.element.Element;
    import javax.lang.model.element.ElementKind;
    import org.netbeans.api.java.source.CancellableTask;
    import org.netbeans.api.java.source.CompilationInfo;
    import org.openide.awt.StatusDisplayer;
    import org.openide.filesystems.FileObject;
    
    public class CountriesCompletionTask implements CancellableTask<CompilationInfo> {
    
        private CountriesCompletionJavaSourceTaskFactory 
                countriesCompletionJavaSourceTaskFactory;
        private FileObject fileObject;
        private boolean canceled;
    
        //Toggle whether code completion should be shown:
        private static boolean showCC = false;
        
        public static boolean isShowCC() {
            return showCC;
        }
        
        public static void setShowCC(boolean showCC) {
            CountriesCompletionTask.showCC = showCC;
        }
        
        //Constructor:
        CountriesCompletionTask(CountriesCompletionJavaSourceTaskFactory
                countriesCompletionJavaSourceTaskFactory, FileObject fileObject) {
            this.countriesCompletionJavaSourceTaskFactory = 
                    countriesCompletionJavaSourceTaskFactory;
            this.fileObject = fileObject;
            
        }
    
        public void run(CompilationInfo compilationInfo) {
    
            //Find the TreePath for the caret position:
            @SuppressWarnings("static-access")
            TreePath tp =
                    compilationInfo.getTreeUtilities().pathFor(
                    countriesCompletionJavaSourceTaskFactory.getLastPosition(fileObject));
    
            //If cancelled, return:
            if (isCancelled()) {
                return;
            }
    
            //Get Element:
            Element element = compilationInfo.getTrees().getElement(tp);
    
            //If cancelled, return:
            if (isCancelled()) {
                return;
            }
    
            if (element != null) {
                //If the element is a parameter...
                if (element.getKind() == ElementKind.PARAMETER) {
                    //...toggle the boolean to show the code completion:
                    showCC = true;
                    StatusDisplayer.getDefault().setStatusText("" +
                            "You can invoke code completion for \\'" 
                            + element.getSimpleName()+"\\'");
                }
            }
        }
    
        public final synchronized void cancel() {
            canceled = true;
        }
    
        protected final synchronized boolean isCancelled() {
            return canceled;
        }
    
    }

    So, Casper, you'd need to identify the element in the code that you want to deal with. I.e., instead of a parameter, you'd look for a certain kind of string for your JPA queries. Here's something I've been playing with, although it doesn't get into the strings:

    Refer to the documents referenced earlier for details.

  5. Finally, in the CompletionProvider class, which is discussed at length in the code completion tutorial, check whether the boolean has been switched or not and, if so, show the code completion box. Once shown, set the boolean back to false so that it is back in its default state. All that's done in the lines in bold below:

    import java.util.Locale;
    import javax.swing.text.Document;
    import javax.swing.text.JTextComponent;
    import org.netbeans.spi.editor.completion.CompletionProvider;
    import org.netbeans.spi.editor.completion.CompletionResultSet;
    import org.netbeans.spi.editor.completion.CompletionTask;
    import org.netbeans.spi.editor.completion.support.AsyncCompletionQuery;
    import org.netbeans.spi.editor.completion.support.AsyncCompletionTask;
    
    public class CountriesCompletionProvider implements CompletionProvider {
    
        public CompletionTask createTask(int i, final JTextComponent jTextComponent) {
    
            
            if (i != CompletionProvider.COMPLETION_QUERY_TYPE) {
                return null;
            }
    
            return new AsyncCompletionTask(new AsyncCompletionQuery() {
    
                @Override
                protected void query(CompletionResultSet completionResultSet, final 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("") && CountriesCompletionTask.isShowCC()) {
                            completionResultSet.addItem(new CountriesCompletionItem(country, caretOffset));
                        }
                    }
                    completionResultSet.finish();
                    CountriesCompletionTask.setShowCC(false);
                }
            }, jTextComponent);
    
        }
    
        public int getAutoQueryTypes(JTextComponent arg0, String arg1) {
            return 0;
        }
    
    }

And that's all. Now you can have a code completion box for very specific elements within your Java code.

Friday Aug 08, 2008

Tutorial for Editor Code Completion API

When you press Ctrl-Space in the IDE, a code completion box pops up with words that you can use to complete the word under the curser. Here's a new tutorial that explains how you can create code completion functionality for your own MIME types or for one of the existing ones:

NetBeans Code Completion Tutorial

The tutorial replaces an older one. It's much better because it focuses specifically on code completion, not on extraneous stuff like web service clients and Options window integrations. In the end, you'll have a simple code completion box in HTML files, listing countries that can be selected and inserted into the editor:

The tutorial applies to NetBeans IDE 6.0 and upwards. It also contains a link to a plugin that provides the sources of the sample, in case you get stuck.

Sunday Aug 03, 2008

NetBeans Podcast Episode 45

Here's the next podcast, featuring a lengthy interview with Python's Ted Leung, a short chat with NetBeans User Researcher Jakub Franc, and all the regular bits: Jaroslav Tulach's API Design tip, the project of the podcast, the plugin of the podcast and ... the puzzler!

NetBeans Podcast Episode 45 (30 min, size: 38.7 MB)

Send the answer to the puzzler to: nbpodcast@netbeans.org by Thursday, 30 August 2008.

If there are topics/people you'd like to hear about in future podcasts, please also let us know at nbpodcast@netbeans.org.

To subscribe via iTunes or similar players, visit http://feeds.feedburner.com/NetBeansPodcast.

Friday Aug 01, 2008

"grails netbeans"

In the last few days, I've blogged about Groovy scripts that generate application source structures. As examples, I used a Groovy script that generates a skeleton NetBeans Platform application and a Groovy script that generates a skeleton NetBeans module. At this point, it should be possible for me to put the scripts into the Grails "scripts" folder, create a GANT script that calls the Groovy scripts, and then run this command from the command line:
grails netbeans

Then a script named "Netbeans.groovy" should run. However, global scripts of this kind cannot be created, currently. Only a small subset of such commands are permissible, since they're hardcoded into the applicable class. So, although I can run "grails create-app" and "grails help", for example, I can't currently run "grails netbeans". (See the helpful explanation here for details.)

So, there's currently three solutions: (1) Be satisfied with application-level scripts, which can have any name at all, and forget about global scripts; (2) Copy your script into one of the permitted global scripts (i.e., copy your "Netbeans.groovy" code into the "CreateApp.groovy", for example); (3) Rewrite the Java source code ("GrailsScriptRunner.java") and recompile the library to create a new JAR and replace the old one in your Grails distribution with the new one.

The first solution wasn't good enough for me, while the third is too much work. So now I can run "grails create-plugin" and I get the sources of a NetBeans module. I simply replaced the content of "CreatePlugin.groovy" with this:

grailsHome = Ant.antProject.properties."env.GRAILS_HOME"    
includeTargets << new File ( "${grailsHome}/scripts/Netbeans.groovy" )

target ( "default" : "Message at the end of it all.") {
   println 'Finished!'
}

Note the line in bold above. That pulls in the Groovy script that generates the skeleton NetBeans module. The only remaining question I have is: what must I do if my Groovy script is making use of a GroovyBuilder? The above "Netbeans.groovy" script actually works via a GroovyBuilder. Couldn't get them to work together within this content, however.

In other news. If you're a fan of Groovy and Grails and want to see it in action with MySQL in the context of NetBeans IDE, click here for a truly amazing article.

About

Geertjan Wielenga (@geertjanw) is a Principal Product Manager in the Oracle Developer Tools group living & working in Amsterdam. He is a Java technology enthusiast, evangelist, trainer, speaker, and writer. He blogs here daily.

The focus of this blog is mostly on NetBeans (a development tool primarily for Java programmers), with an occasional reference to NetBeans, and sometimes diverging to topics relating to NetBeans. And then there are days when NetBeans is mentioned, just for a change.

Search

Archives
« August 2008 »
SunMonTueWedThuFriSat
     
2
4
5
6
7
11
14
17
20
23
27
29
30
31
      
Today