layer.xml

a netbeans rcp blog

Great Lookup video

Posted by Nicklas Löf on November 3, 2010

Just found this great video about Lookup on blip.tv by NetBeans API architect Jaroslav Tulach.

http://blip.tv/file/2631958/

Posted in Netbeans | Tagged: | Leave a Comment »

That other Lookup

Posted by Nicklas Löf on November 2, 2010

In my previous posts I have shown Lookup as a way to communicate between different components in a Netbeans RCP application, even between different modules by using Lookup as a communication device where one component can send out a message without knowing who is listening and what they do with the data.

When I started using Lookup at first I was a bit confused because I did mix up the two Lookups that exists in Netbeans. The first one is the one above which is an more advanced way of implemeting listners. The other Lookup is a way to get an instance of a class. I did play a bit with it but I always found 0 instances. Now I have learned more and have started to using this method in my application.

Lets code!

In my the Basic of nodes I was using a CustomerService class that had a bunch of static methods for retreving and adding customers. And the customers was stored in static arraylist. And then I did use this by calling CustomerService.getCustomers(). Now we gonna do this trough the Lookup instead. First of all we need to create an Interface. Netbeans actually contains refactoring tools for this. The best way to convert a class to an interface is doing this:

* Replace all static methods with normal ones
* Make the methods public

In my case my class was called CustomerService which I want my Interface to be called so I’m just renaming it to CustomerServiceImpl. To create an interface just go to the refactor menu and choose Extract interface. Select all the methods, name it CustomerService and we are done. CustomerServiceimpl will now automatically implement CustomerService.

Adding an implementation as a ServiceProvider.

We are not completly done yet. We need to tell Netbeans that out Impl class is a serviceprovider, just implementing an interface isn’t good enough. So we need to add an annotation just before the class implementation line.

@ServiceProvider(service=CustomerService.class)

Doing this is that easy in Netbeans 6.9. In earlier versions you had to create files into the META-INF folder specifying this but with help of annotations it’s done automatically now.

Replace our static call in the application

Now we need to replace our CustomerService.getCustomer() call with the Lookup version instead. It’s done with this modification to our createKeys() method in our ChildFactory:

    @Override
    protected boolean createKeys(List<Customer> list) {
        CustomerService cs = Lookup.getDefault().lookup(CustomerService.class);
        list.addAll(cs.getCustomers());
        return true;
    }

See how we call Lookup and asking for the default lookup. Then we tells it to get a CustomerService implementation. And as you can see we aren’t asking for CustomerServiceImpl but for the Interface that we did extract and implemented. This is very powerful as I will show later.

Also you probably noticed that our CustomerServiceImpl got it’s instance automatically created for us, we didn’t have to invoke new on it. So how can this be useful? Well.. you don’t have to know the name of the class that implements the feature you want, all you need to know is the service. So you can rename the implementation class without having to change the code.

Multiple instances

Here is the thing that can be very powerful. This isn’t an example one would use in a real application but as an example. lets say that our register of customers can be retrieved from more than one location. One is from a database and another one is from a web service. How can we fetch them in one call? It’s probably tempting to add code into the getCustomer method that will fetch data from both locations and join them in an arraylist. It’s working but since we have something more powerful here to use lets use Lookup instead. The way to do it is by creating two classes that implements the CustomerService interface. So we can have CustomerDatabase implements CustomerService and CustomerWebservice implements CustomerService.

Now we have two classes that grabs the data in different ways. Now we have to do some small modifications to our Node childfactory. Instead of using lookup(Interface) we are gonna use lookupAll(Interface) and guess what that will return? Yes! A collection!

    protected boolean createKeys(List<Customer> list) {
        Collection<? extends CustomerService> customerServices = Lookup.getDefault().lookupAll(CustomerService.class);

        for (CustomerService cs : customerServices) {
            list.addAll(cs.getCustomers());
        }
        return true;
    }

So we are getting all our classes that implements CustomerService (and has the @ServiceProvider annotation). THen we just loop over them and ask for getting the customers for each of them. And as you can see our factory doesnt have a clue of what instances there is and how many there is. It could be 0, it could be 25. And the different classes doesnt have to be in the same module.

Lookup without Netbeans

Yes it’s possible. You can use all of this outside a netbeans application. You just have to add the openide-lookup jar to your application and start using it and you will get both Lookup methods.

Posted in Netbeans | Tagged: , | 2 Comments »

Bye bye Webstart Hello Update center

Posted by Nicklas Löf on October 19, 2010

I have always heard about Update centers and that Netbeans modules could be put into them and have the module being updated automatically… But I have always been frigthend about it because it sounds so complicated.. setting up your own update center.. sounds like a big installation needed but I have just found out it was so easy to do.

A few days ago we were about to go into a internal alpha prototype testing internally which would require lot of updates. Webstart have been the choice for a long time but there is so many strange things that can happen and I did run into some strange jnlp bug that caused some of my Modes not to work. Then I decided I have had enough! Lets look at that complicated Update center stuff!

Lets setup an Update center!
So what do we need? We need space on a web server. It can be any web server where you can upload your own files. You need this URL already in this stage. Now we need to enter this URL into our application. This can be done in two different ways. Either added to one of your existing modules. This is the way I did choose but have figured out later that the other way is probably better and that is to create a new module just for the update center information.

Either way choosen to add the URL is simple. RIght click-> New-> Module Development-> Update center. Enter your URL here. It should be something like http://www.yourdomain/updates/update.xml

Was that everything? Yes. Now your application will check for updates!

Create an installer
Next I decided to create an installable version of my application. It’s very easy, just select which installers you want to create in your Suite settings. (OSX, Solaris, Linux and Windows are supported). Then right click the suite and select Build installers and you will end up with installers. I built for Windows so I got an .exe

The only drawback I have found so far is that the installer seems to require JDK. I’m not 100% sure if it’s any of my module or suite settings that are causing this but my application runs just fine without a JDK installed.

It’s update time!
So lets say that you have an update in one of your modules and you want the users that have installed your application to get a notification about this. How can you do this?

Right click your module and select Properties. In the API versioning settings change the Specification Version number to 1.1 or maybe 1.0.1 if you don’t want to raise the versioning number so high.

Then right click your suite and select Create NBMs. And quite soon you will see a file link to where your updated modules are located. It’s the content of this folder that you need to upload to the server that you specified earlier. The files to upload is yourmodule.nbm, updates.xml and the licenses folder.

Update pushed to clients
And thats is everything needed! Your application will detect that there are changes and display a message that there are updates available. Just the same message you get when something in Netbeans IDE is updated. The user will select that he/she wants to update and the application will restart automatically and your updated module is loaded.

Update center in it’s own module
I had an issue today where my suite needed to download a module from the official Netbeans update center. But my problem was that I couldn’t add this update center into my clients because my module was requiring other modules and therefore the update couldn’t be installed. If I had put my update centers into a separate module I could have just updated that one and the application would had first update the update centers URLs and then download the required modules.

Word of the day: Update.. I have never typed that word so many time before I think 😉

Posted in Netbeans | Tagged: , | 1 Comment »

Global font size

Posted by Nicklas Löf on October 15, 2010

This is a really nice trick. I usually think that the font size of a Netbeans RCP application is too big. Even if it’s possible to change the font size on swing components the over all user interface can’t be changed from there.

So this is a trick I have been using for some time but always forget where to put it and the syntax.. So here it is.. To change the global font size setting just add the following line to project.properties (I always put it in both the suite and my modules)

run.args.extra=--fontsize 11

And voila.. the global font size is much better now.

Now you are happy.. you finally have changed that fontsize problem! Let’s build the JNLP application and deploy it on the server! 5 minutes later you stand at your boss desk.. cleaning the jnlp java cache just to be sure that everything works! So the application launches.. Nice splash screen showing.. and eeehh.. what? the font size is still to big? Damn Nicklas!!! lying about this stuff in his blog!!!!!

So.. this doesn’t seem to work when running the application as a webstart application.. you actually need to add two more lines in that case.. In your suite open the JNLP Descriptor that can be found in the Important Files folder. Look for this part:

    <application-desc>
        <argument>--branding</argument>
        <argument>${branding.token}</argument>
    </application-desc>

This is the part of the jnlp file that sends extra argument to java when the application is started. So we need to add two lines so it looks like this:

    <application-desc>
        <argument>--branding</argument>
        <argument>${branding.token}</argument>
        <argument>--fontsize</argument>
        <argument>11</argument>
    </application-desc>

And voila.. now you can walk to your boss desk again and show the application.. (but remember to clear the java cache first.. you never know…)

Posted in Netbeans | Tagged: , | 1 Comment »

Refresh Node children automatically

Posted by Nicklas Löf on October 14, 2010

Hello followers!

Todays problem to solve is how to refresh your Node children when there is a change in the data model. For example if you have a list of Customers and a delete button. When it’s pressed you have added code that are removing the selected customer from the list of customers but the node will still be visible in your list view. How can this be resolved?

In my basic of nodes post I did use a ChildFactory to create my nodes. Childfactories has a createKeys() method. In createKeys you populate a list with all the data objects you want to create nodes from and createNodeForKey() is called automatically for each object. Childfactories also have a nice method called refresh(). What refresh does is that it calls the createKeys() method again but it only calls createNodeForKey() for objects that doens’t already have a node. This is great. The old nodes (with current cookiesets and other states) are still there, only the new ones are added (or removed in case there is data that has been removed).

So lets call this refresh method then? well.. you can’t.. it’s protected and can only be called from the class that are extends Childfactory which is our nodechildfactory. At first I created a public method called update() which then called the refresh() method but then I started to realize that I need to keep an instance of my childfactory public in my TopComponent and call it when my data was updated. This works but isn’t a good way to do it. You know.. decoupling and all that. The lesser dependencies the better.

What can we do instead? Once again the power of lookups saves us! This solution is very simliar to the one I used in my post about using Lookup to change views in your application but lets look at some code again and lets start with creating a total empty class.

public class NodeRefreshEvent {
}

Phew.. that was a complicated one. Now lets look at our class that provides us with the model data objects. It’s the same class that I used in Basic for nodes. It’s a class with a static method that returns a list of Customer. Lets say that we have a deleteCustomer() method now and when a customer is deleted I want my node view to reflect this change.

public class CustomerService implements Lookup.Provider{
    private InstanceContent content = new InstanceContent();
    private Lookup lookup = new AbstractLookup(content);

    @Override
    public Lookup getLookup()
    {
        return lookup;
    }
}

So what have been added? I’m implemeting Lookup.Provider that contains the method getLookup(). And I need a Lookup to return so I create a lookup using the InstanceContent class which is a List where I can put instances of any object. So what do you say.. should I be crazy and put my small and silly NodeRefreshEvent class into this list when my data has been updated? Let’s try that!

public void deleteCustomer(int id){
    customers.delete(id);  // Lets pretend customers is a map with id as key
    content.add(new NodeRefreshEvent());
}

(See the Important section at the end of this post for some important information about this method)

Was that everything? So easy!.. No.. you need to do one more thing. Remember the childfactory?

class CustomerNodeFactory extends ChildFactory<Customer> implements LookupListener{
    private final Result<NodeRefreshEvent> lookupResult;
    public CustomerNodeFactory() {
        lookupResult = CustomerService.getLookup().lookupResult(NodeRefreshEvent.class);
        lookupResult.addLookupListener(this);
    }
}

So.. in my ChildFactory I’m now implementing a LookupListener. It does excatly what it says. It listens to changes on a Lookup. Which Lookup? Thats what I define in the constructor. I say that I want to listen for changes in the Lookup of CustomerService but only ones that are of the type NodeRefreshEvent.

Now we need to react when a change is done. How can that be done? Trough the resultChanged method that the LookupListener have added for me off course. This is where we will do our magic.

    @Override
    public void resultChanged(LookupEvent le)
    {
        Lookup.Result r = (Lookup.Result) le.getSource();
        Collection c = r.allInstances();

        for (Object object : c)
        {
            if (object instanceof NodeRefreshEvent){
                refresh(true);
            }
        }
    }

So here we check if the event we got in the Lookup is an instance of NodeRefreshEvent. If it is then do refresh() and boom.. the magic happens.. The createKeys() method is called and together with createNodeForKey() the nodes list is updated with new entries or removal of deleted entries!

And once again we have done some decoupling. Our CustomerService doesn’t have any idea who is interested in the addition or removal of customers. And remember we aren’t limited to just one listener. We could have 20 of them that listen to a NodeRefreshEvent and do things.

If you need to send a message together with the NodeRefreshEvent it can easily be done. Just create a field and a getter. When you creates your new instance of NodeRefreshEvent add the message to the constructor and pick it up in the Listener like this:

for (Object object : c)
{
    if (object instanceof NodeRefreshEvent){
        String message = ((NodeRefreshEvent)object).getMessage();
        refresh(true);
        doSomethingWithMessage;
    }
}

Message is offcourse not limited to a String. It can be anything you want. An enum, another object….

One last important thing

As Darrin pointed out in the comments section I forgot to include one important thing. The InstanceContent list is never emptied. We just add new things into the Lookup but we never removes them. And since we loop over all content in the Lookup we gonna update the nodes multiple time. So this is something we must prevent and that is to remove our previous NodeRefreshEvent instance before adding a new one.

Unfortuneatly there is no removeAll or clear method that can be called. The only way to remove an object from the InstanceContent is by using the instance itself. So we would need to save our created instance of NodeRefreshEvent and then call content.remove(ourInstance); This is how I did in a previous blog post but a few days ago I found this post that showed me another way to do it. BeanDev

So lets use a modified version of this example in our removeCustomer method

public void deleteCustomer(int id){
    customers.delete(id);  // Lets pretend customers is a map with id as key
    content.set(Arrays.asList(new NodeRefreshEvent()), null);
}

So instead of adding one object we use set which wants a list that we simply can create with Arrays.asList. And now the whole content of the InstanceContent is replaced.

Posted in Netbeans | Tagged: , , | 11 Comments »

The one with the cookies and some action and a little bit of Lookup

Posted by Nicklas Löf on October 13, 2010

So.. this is a blog post about cookies. Don’t we all love cookies? Sure we do but this isn’t about those small sugar bombs, neither is it about cookies in web browsers. Since this is a blog about Netbeans you might have already guessed that there is something in Netbeans RCP called Cookies.

I recently needed a way to tell my application that my data was updated and I knew that those cookies could help me. What I wanted to achieve was that by pressing a button in my toolbar the nodes that was updated had to be processed. What cookies does is giving your nodes a temporary state so you can track them.

Lets start by see if we can feed our nodes with some cookies…

First we need to create a cookie. In this example I’m creating an interface that extends a Node cookie. The interface contains one method called update().

public interface UpdateCookie extends Node.Cookie{
    public String update();
}

Ok.. now I have a cookie! What should I do with it? Should I have my node to implement this interface? No.. remember what I said earlier.. I want to give my node a temporary state. But add and remove interfaces can’t be done at runtime can they? No.. so we need to something else in our node so lets look at that.

public class CustomerNode extends BeanNode<Customer> {
    public CustomerNode(Customer bean) throws IntrospectionException {
        super(bean);
        setDisplayName(bean.getName());
    }
}

So this is a basic BeanNode. It has something called a CookieSet which is a Java Collection with Cookies. By default it’s empty but let’s add our cookie to it. And remember it’s an interface so it will ask us to implement all our abstract methods.

getCookieSet().add(new UpdateCookie() {
    @Override
    public String update() {
        return "Hello from" + getDisplayName() +" I'm updated!";
    }
});

Cookie added! And our update method will just return a String in this example but this is where you should call your application logic and do something with your data for example update a database or call a webservice..

This is a bit of bad example because now we have added the cookie to all our nodes. Normally you would have a method in your node that you call when the data is updated for example.. and that method should add the cookie to the cookieset. And to improve this example let’s add a small if statement that only adds this cookie to one of the nodes.. like this:

if (bean.getName().equals("Apple")) {
    getCookieSet().add(new UpdateCookie() {.........  like above....}
}

As I said, this is only to add the cookie for just one node in this example, normally it’s done somewhere else in your application.

Ok.. so now one of our Nodes has a UpdateCookie assigned. What can we do now? Let’s create an action so we can do something with our nodes. What actions are is out of scope of this post but the basic is that an action is something that are called when you click an icon in the toolbar or select something in the menu. So let’s create a menu item.

Add a new action by right click at your project and select New->Netbeans Module->Action. Leave the action to be Always enabled. Put it in the file category and call it UpdateCustomerAction with display name Update customers. Netbeans will now do everything for you and open up our newly created action. When an action is choosen the actionPerformed() method is called so this is where we will add our code.

What do we want to do? We want to grab all our Nodes that have the UpdateCookie assigned. First of all we need to get hold of our Nodes which are located in an Explorermanager in a Topcomponent. It’s VERY important that we add this command to our Topcomponent first:

associateLookup(ExplorerUtils.createLookup(myExplorerManager, this.getActionMap()));

This tells the Topcomponent that it should place the current selected nodes into the Lookup of the Topcomponent. So each time one or serveral nodes are selected those nodes are put into the Lookup of our Topcomponent so we can grab them externally.

So lets go back to our action. Now we can get our nodes.. at first this code might be tempting to write:

public final class UpdateCustomerAction implements ActionListener {
    public void actionPerformed(ActionEvent e) {
        Node[] nodes = TopComponent.getRegistry().getCurrentNodes();

        for (int i = 0; i < nodes.length; i++) {
            Node node = nodes[i];
            UpdateCookie cookie = node.getCookie(UpdateCookie.class);
            if (cookie != null) {
                System.out.println(cookie.update());
            }
        }
    }
}

If we run our application now and select Update customer in the File menu with all our nodes selected in the Topcomponent it would correctly say in the Output window “Hello from Apple I’m updated!” but before explaining what happend I want to make the code above a bit cleaner. Instead of looping over all nodes and assign the cookie to a local variable and check for null there is a much more elegant way to do this. How? By using Lookup off course!

public void actionPerformed(ActionEvent e) {
        Collection<? extends UpdateCookie> lookupAll = TopComponent.getRegistry().getActivated().getLookup().lookupAll(UpdateCookie.class);
        for (UpdateCookie updateCookie : lookupAll) {
            System.out.println(updateCookie.update());
        }
    }
}

So what am I doing here? I’m asking for the current activated TopComponent. From this TopComponent I’m asking for the Lookup and tells it that I want to get all Nodes that are associated with an UpdateCookie. I will get a Java Collection with the result and since I just asked for UpdateCookie I only got the Cooke instance and not the whole Node and I can also be sure that it’s safe to call the update method.

Decoupling
There is actually a third way to grab our cookies. It’s a bit like above but using the global lookup instead. This is a proxy of all TopComponent lookups and from here you can get the selected node without having to reference to a specific TopComponet. This is good for decoupling and reusage. If we do it that way we can actually reuse our UpdateCustomerAction in other components. So the final code would look like this:

    public void actionPerformed(ActionEvent e) {
        for (UpdateCookie updateCookie : Utilities.actionsGlobalContext().lookupAll(UpdateCookie.class)) {
            System.out.println(updateCookie.update());
        }
    }

So to summarize what have been done.

  • I added an UpdateCookie to my Apple node. UpdateCookie is an interface with one method. This method will be called and from it I can do whatever I need to do with my node. In this case I just returned a string with the display name of the Node.
  • Then I added an action that grabbed all my UpdateCookie nodes. I looped over them and called the update() method that returned me the string with the name of the Node.

After we have done our updates we want our Cookie to be removed from our node since it’s only a temporary state. This can be done with this line added to the update() method:

getCookieSet().remove(getCookieSet().getCookie(UpdateCookie.class));

The next time you select Update customer nothing will happen because the cookie was removed.

Ending and exercise

This is just one example of what can be done with cookies. For fun and exercise try add SaveCookie to one of your nodes cookieset. Then watch the default Save button in the toolbar when you select different nodes. I will explain what happens in a later episode of Layer.xml 🙂

Posted in Netbeans | Tagged: , , , , | 1 Comment »

Power of Lookup

Posted by Nicklas Löf on October 7, 2010

Just as Nodes are one very important building block of Netbeans RCP applications Lookup are almost even more important. At first the concept can be confusing and you might not know what usage you have of them. I only have a basic knowledge of Lookups and had one of those A-ha! moments a few days ago. As I’m still learning Netbeans I probably missunderstand things and everything written in this post might not be the correct way to do things.

Scenario

Lets look at a scenario where Lookup can help us a lot to create a much better design of our code. Lets say that you are building an application that only consists of one module in a suite. You have a menu (maybe a JXTaskpane shown earlier in my blog) and when you select one item the content in a Topcomponent that contains an Outlineview showing nodes are changes to a different set of nodes. How would the communication between the menu and the Outlineview be done?

The easiest way would seem to be a call to a public method like this: WindowManager.getDefault.findTopComponent(“YourTopComponent”).switchViewToB(), WindowManager.getDefault.findTopComponent(“YourTopComponent”).switchViewToC(), WindowManager.getDefault.findTopComponent(“YourTopComponent”).switchViewToD(). And this method would take care of updating the nodes. This is a working solution and would probably work fine for a one menu with one topcomponent application. But what if you want to bring up another Topcomponent when you switch to D? Where should you do this? In the menu action calling the other topcomponent? Or in the switchViewToD() method?

Adding this to the SwitchViewToD() method also works but now you need to make sure that you are showing and hiding a bunch of topcomponents from the method. When you add one more TopComponent you need to go trough all others and make sure that they are opened and closed correctly. Starts to feel like a small nightmare doesn’t it?

Now lets say that your boss wants to earn more money. He wants to sell an enterprise edition of your application that only should be distributed to customers paying extra. This enterprise application contains a few more panels that should be opened up on certain views. The best way to implement this part is by creating an Enterprise module to your suite. But now things starts to get complicated..  How will you bring up the extra panels? You can’t have calls to TopComponents that only exists in this module since this would cause Nullpointers for customers without the Enterprise module. You could add if statements that checks if the enterprise module is installed and only call the TopComponents then..   or maybe…

No!  stop thinking now! This has gone the completely wrong path from the beginning. There is a much much better ways than creating dependency hell between the TopComponents. If we do this correctly TopComponentA would not know that TopComponentB even exists. This is something called decoupling in the software development world.

The solution is by using Lookup

So how could this Lookup thing help us? As always.. lets dive into some source code.

First of all I want to create some kind of object that tells my TopComponents what view I want to switch to. This object will then be sent out into the Lookup. So let’s create a very basic class.

public class TaskSwitch {
    private final GUITask task;
    public TaskSwitch(GUITask task) {
        this.task = task;
    }
    public GUITask getTask() {
        return task;
    }
}

What is GUITask? It’s an enum and it’s created like this:

public enum GUITask {
    myFirstView,
    mySecondView,
    myThirdView
}

Ok.. so now we a class and an enum. How can we use them? First by adding this fields to our menu (I’m using JXTaskPane in a separate TopComponent for switching views).

private InstanceContent taskContent = new InstanceContent();
private Lookup lookup = new AbstractLookup(taskContent);
private TaskSwitch taskSwitch;

This will create a Lookup based on InstanceContent which is a builtin class in Netbeans that provides the Lookup with content where we can add instances of our classes.

InstanceContent works as a list and instances can be added and removed but there exists now removeAll() method so we need to keep track of our instance added to it. For this I created a small method that will remove the previous TaskSwitch instance from the content and add the new one.

private void switchTask(TaskSwitch taskSwitch) {
    try {
        taskContent.remove(this.taskSwitch);
    } catch (Exception e) {
    }
    this.taskSwitch = taskSwitch;
    taskContent.add(this.taskSwitch);
}

Now I can use this method in my menu actions to add a new TaskSwitch instance to my Lookup.

switchTask(new TaskSwitch(GUITask.myFirstView));

We also need to make our Menu to implement Lookup.Provider and a getLookup method that returns our lookup field.

public final class MyMenu extends TopComponent implements Lookup.Provider
public Lookup getLookup() {
    return lookup;
}

What have we done? We have created an InstanceContent instance which is a list of instances of any type. We have created a Lookup that monitors this List and acts when something has been added to it. Each time a menu item is selected I’m adding a new Instance of my TaskSwitch class that contains an enum value of the view I want to have.

Now lets switch to my TopComponent where I have my OutlineView.

public final class MyOutlineTopComponent implements LookupListener
private final Result taskLookupResult;

Here Im making my TopComponent to be a LookupListener. Sounds like a good idea. I want to listen to changes in the Lookup.
In my constructor I have to tell what I want to listen to.

taskLookupResult = WindowManager.getDefault().findTopComponent("MyMenuTopComponent").getLookup().lookupResult(TaskSwitch.class);
taskLookupResult.addLookupListener(this);

Ok.. now I have told what I want to listen to all changes where instances of TaskSwitch is involved into.

Now we need to do something when we get notified about a change. This is done in a method called resultChanged that contains a collection of all the changes. It can ben one or it can be many.

@Override
    public void resultChanged(LookupEvent le) {
        Lookup.Result r = (Lookup.Result) le.getSource();
        Collection c = r.allInstances();

        if (!c.isEmpty()) {
            for (Object object : c) {
                if (object instanceof TaskSwitch) {
                    changeView((TaskSwitch) object);
                }
           }
      }
}

So each time somethings happens that involves an instance of TaskSwitch.class the resultChanged method will be called. We will get a collection of all the instances that has something to do with TaskSwitch.class. In our case there should only be one. I prefer to do an extra type check by checking if Object is an instance of TaskSwitch and if it is I’m calling a method called changeView();

And this is how my changeView() method looks like:

private void changeView(TaskSwitch taskSwitch) {
    switch (taskSwitch.getTask()) {
        case myFirstView:{
            switchToFirstView();
            break;
        }
        case mySecondView:{
             switchToSecondView();
             break;
        }
    }
}

And we are done. Now I have switched the content in my TopComponent without the menu knowing where the changes occur. I can now do the same thing in every other TopComponent in my suite and it doesn’t even have to be in the same Module.

This is just an example of what can be done. Other usages could be if you have a background thread that checks for new data from a web service that needs to be added to your node views. Each time the background thread finds new data it could send the data over the lookup and the classes that are interested if there is new data can pick it up and display it, for example refresh the nodes list without knowing anything about the background thread and how the new data was added into the Lookup. It just knows the data is there and what to do with it.

And if you want to show or hide certain TopComponents depending on which view that is selected just call this.open() and this.close() in the changeView()/resultChanged method. Just make sure that you have registered your lookup in the constructor and not in componentOpened() since it would never open the first time. Also don’t deregister the lookup in componentClosed().

So this is one of the many possibilities of using Lookups in your Netbeans RCP application.

Posted in Netbeans | Tagged: , | 4 Comments »

The basic of nodes part 2

Posted by Nicklas Löf on October 2, 2010

In my previous post I did go trough the very basic of nodes and we ended up with something that looks like this screenshot.

At the end I said that by looking at this screenshot there is probably two questions. Why is there an empty node with a white icon at the top? Why is the name repeated twice?

I will clarify this in this post which isn’t finished but will be shortly.

So lets start with the empty white node. Why is it there? To understand this we need to add one thing to our knowledge of nodes that I didn’t mention in the previous post but you might have understood it from some of the methods we called. First of all our NodeFactory did extend ChildFactory. Secondly we used a static method called Children.create. Do you see a common pattern?    Yes.. children!

Every single node that are created can have 0, 1 or many children. It’s a very simple thing but can be used to build folder structures of nodes. For example the Project tab in Netbeans or the File explorer. Those are nodes with children representing folders and files.

So the white icon node shown in the top is actually the node we created with this command.

em.setRootContext(new AbstractNode(Children.create(new CustomerNodeFactory(), true)));

It’s the AbstractNode which is our RootNode. When we are creating it we say that we are creating a Node that will contain children from our factory. Sometimes we want to show this node if we are showing a folder structure but in this case we don’t. So what can we do? We can’t remove the node since our Customers are children of the RootNode. Fortunately Netbeans Outlineview provides us with a simple method that hides the root node.

outlineView.getOutline().setRootVisible(false);

And boom. The root nodes is gone and we have a nice list of our customers.

So what can we do about the name that is repeated twice? The first column is actually a node column that always is visible. Remember that we did setPropertyColumns when we created the outlineview? If we hadn’t done that only the first colum would have been visible. But where does it get the name? If you look at the Customernode you will see that we did this:

setDisplayName(bean.getName());

So we could just remove that line and we will see only the icon in that column. We can also remove the name property from our setPropertyColumns() method call. So there is lot of possiblities and what you choose depends on the situation. Removing the display name works fine if you only are showing your nodes in this list but what if you want to show the same nodes in a tree folder view? Then the display name would be empty in that case.

I choose to remove the name column from my properties list:

outlineView.setPropertyColumns("type", "Type","contacted","Contacted");

That looks better doesn’t it? But wait..  now the colum for the company name isn’t Name anymore, it says Nodes now. We don’t want that. This can be solved easily by passing our desired column name to the outlineview when we are creating it.

outlineView = new OutlineView("Name");

And here we are done with part 2 of Nodes. I will add more parts showing how the icon can be customized, how we can add menu items to the menu that are shown when you right click on a node.

Posted in Netbeans | Tagged: , | 4 Comments »

The basic of nodes

Posted by Nicklas Löf on October 1, 2010

Nodes are one of the building blocks of any Netbeans RCP application. Since I’m still learning the Netbeans RCP basics I decided to write down what I have understood of nodes so far. So this is my personal notes about nodes as a small tutorial.

The first thing to understand about nodes is that they don’t represent the data. Nodes are just a bunch of objects that shows a graphical representation of the data. They contains all the data needed to display themselves but thats all.

This screenshot shows a view of some nodes I have created. It’s possible to edit all the data visible and the changes of the data will be reflected immediately in our data objects and there isn’t much code we have to write to achive this.

The easiest way to see this is by diving into some code. Lets say that we have an application that shows us all our customers. The basic of the customer class looks like this:

public class Customer {

    private String name;
    private Type type;
    private Boolean contacted;
}

Type is a simple Enum that can be added in the class.

public enum Type{
    small,
    medium,
    big;
}

You will see later why I have choosen to have an enum as one of the properties of the Customer class.

The class also has a constructor and getters and setters. It’s very easy to have Netbeans auto create this code for us. Just place the cursor inside the class after the field and press ctrl+i. In the popup menu select Constructor and choose that you want to initialize all the three fields. Then hit ctrl+i again and choose getters and setters and select all fields. This is a very easy way to quickly build up small classes.

So now we have our class. How can we create the Nodes? The easiest way to handle Nodes and the data behind them (remember..  Nodes is only the visual layer) is to use a BeanNode. And to use a BeanNode our class needs to be a Bean. Sound complicated? It isn’t. Netbeans will take care of this. Right click on your class and choose BeanInfo editor. It will now create all the information it needs. Switch to Design view and make sure that all our three fields (or properties as they are called) are green. Toggle them by right click on them. Sometimes you have properties that you still want to have getters and setters on but not to be editable trough Bean properties thats why it’s possible to choose here. It’s also possible to set read and read/write permissions on each property. But lets leave it at default settings.

Now we need to create our Customers in some way. In a real application it would probably be created from a database, a webservice or anything else but in this test lets create them manually in a CustomerService class.

public class CustomerService {
    static List<Customer> getCustomers(){
        return Arrays.asList(new Customer("Apple", Customer.Type.big, Boolean.TRUE),new Customer("Microsoft", Customer.Type.medium, Boolean.FALSE),new Customer("John", Customer.Type.medium, Boolean.TRUE));
    }
}

A small static service that returns an ArrayList with three Customers. Now it’s time to create the nodes that will be our visible layer to the customer data!

public class CustomerNode extends BeanNode<Customer>{
    public CustomerNode(Customer bean) throws IntrospectionException{
        super(bean);
        setDisplayName(bean.getName());
    }
}

So this is our CustomerNode. There will be one Node for each customer. The node itself doesn’t contain the customer data but as you can see it has a displayName. Other properties it can have is a HTMLDisplayName an icon and some other properties used for the visual presentation that we will not touch for now.

To create a collection of Nodes we will use a ChildFactory which is a class that will take care of mapping our Customer data objects into Nodes. Once again not much code is needed.

public class CustomerNodeFactory extends ChildFactory<Customer>{
    @Override
    protected boolean createKeys(List<Customer> list) {
    list.addAll(CustomerService.getCustomers());
    return true;
}

@Override
protected Node createNodeForKey(Customer key) {
    try {
            return new CustomerNode(key);
        } catch (IntrospectionException ex) {
            return Node.EMPTY;
        }
    }
}

What the code above does is that it will take List that contains Customer. Does that look familar? The list is empty in our case so we just call our CustomerService and retrieves the three customers we created earlier. And then add all those to the list.

So what’s up with the createNodeForKey method. It’s never called? Well..  we don’t call it from our code but Netbeans will call it for each Customer found in the List. And what we do is returning a CustomerNode and that’s all. Now we have our Nodes!   Now we need to display them and this is done by creating a Topcomponent and follow these steps:
* Right click in the design view and set the Layout to BorderLayout.
* Drag a JScrollPanel on top of the design.
* Switch to source view and create two fields.

private final ExplorerManager em;
private final OutlineView outlineView;

* Modify the TopComponent class so it implements ExplorerManager.Provider and allow Netbeans to create the required methods for you.
* In the auto created getExplorerManager() method return em;
* In the constructor we need to create a view for our nodes and initialize our ExplorerManager.

outlineView = new OutlineView();
this.em = new ExplorerManager();

* Switch back to design view and select customized code on the JscrollPanel and modify the source so it says

jScrollPane1 = outlineView;

Now we are almost done! There is one thing left to do. Let our view to know which nodes it should display. This is done in the ComponentOpened() method.

public void componentOpened() {
    em.setRootContext(new AbstractNode(Children.create(new CustomerNodeFactory(), true)));
    outlineView.setPropertyColumns("name", "Name", "type", "Type","contacted","Contacted");
}

The first line says that we want to create a new Node. This node will be the Root for all other nodes. And then we basically tells it that the children of our RootNode is created by the CustomerNodeFactory class that we created earlier. The second line is a list of properties (the field name they have in the Customer class) and what the column showing this data should be called. So here we can select which of our Customer data that should be visible in the view.

If everyting went well the module should compile now and show you something that looks like this:

As we can see we have our three Customers with the names, they type of the customer and if they have been contacted. Since we used BeanNodes we can click and edit and all our changes will go directly into our Customer without any more coding needed. Netbeans contains some premade editors for the different field. Strings can be edited in place. Enums will be shown as a drop down of all available values of that enum. And booleans has automatically a checkbox.

The beautiful thing here is that we can implement other views displaying the same nodes differently. For example we could show the customers in an icon view. Or just a list without properties. We can even create our own views and display the nodes just as we want.

If you look at the screenshot above you probably are asking two questions. Why is there an empty node with a white icon at the top? Why is the name repeated twice? I will cover that in part 2 of the The basic of nodes.

Posted in Netbeans | Tagged: | 3 Comments »

Auto collapsing JxTaskPane

Posted by Nicklas Löf on September 29, 2010

This post actually doesn’t have anything to do with Netbeans RCP but I thought I would share it anyway since it can be used in a Netbeans RCP application.

I added the JXTaskPane component from the SwingX package to my application. One thing that I didn’t like in my application was that multiple panes could be open at the same time. I would rather have the possibility to collapse the other ones automatically.

But looking in the javadoc didn’t really give any hints that this was a builtin feature into the JXTaskPane so I decided to implement it myself.

To do this is quite easy. First of all we need a collection of the Panes since there is no jxTaskPaneContainer.getPanes() method. It’s probably possible to use getComponents and implement a loop that checks if component instanceof JXTaskPane then….  But I preferred to keep my panes in a separate collection instead. In my application that works since the content is static and never changes but for dynamic content the other approach might be a better choice.

So..  lets add a collection of JXTaskPanes as a field. Also add the JXTaskPaneContainer as a field.

private final Collection<JXTaskPane> taskPanes = new ArrayList<JXTaskPane>();
private final JXTaskPaneContainer jXTaskPaneContainer = new JXTaskPaneContainer();

Then create a method that will take a created pane and add it to both the Collection and the PaneContainer.

private void addPane(JXTaskPane pane) {
    jXTaskPaneContainer.add(pane);
    taskPanes.add(pane);
}

Now we need a way to get informed that a pane has been uncollapsed. This can be done with the help of listeners. JXTaskPane doesn’t have any custom Listeners so we need to use a PropertyChangeListener. Easiest way is to implement one as a private class.

private static class CollapseListener implements PropertyChangeListener {
    private final MyTopComponent component;
    private final JXTaskPane pane;
    public CollapseListener(MyTopComponent component, JXTaskPane pane) {
        this.component = component;
        this.pane = pane;
    }
    @Override
    public void propertyChange(PropertyChangeEvent evt) {
        if (evt.getPropertyName().equals("collapsed") && evt.getNewValue().toString().equals("false")) {
            component.collapseAllPanesExceptChoosen(pane);
        }
    }
}

Now we can see that there is one last method missing. The one that will take care of the actual auto collapsing.

private void collapseAllPanesExceptChoosen(JXTaskPane choosenPane) {
    for (JXTaskPane jXTaskPane : taskPanes) {
        if (!jXTaskPane.equals(choosenPane) &!jXTaskPane.isCollapsed()) {
            jXTaskPane.setCollapsed(true);
        }
    }
} 

And we almost done. We must add the listner to all the panes. Either we can do this in our addPane method or in another method that creates the panes or manually on each pane. It’s only one line of code

taskPane1.addPropertyChangeListener(new CollapseListener(this, taskPane1));
taskPane2.addPropertyChangeListener(new CollapseListener(this, taskPane2));

Done!  Now the previous taskpane that was open will be closed automatically when you click on another one.

Posted in SwingX | Tagged: | 1 Comment »