februari 16, 2011

Place the quicksearch component anywhere you like

In one of my applications I needed to put the Quicksearch into one of my Topcomponents instead of having it in the standard netbeans toolbar. The main reason for this is I'm using OfficeLAF so I don't have the default toolbar at all.

This turned out to be a bit of a problem and I had to do one of my favourite things again..   dive into the Netbeans Platform source code and this is how to get hold of the Quicksearch component and place it anywhere you want.

The first problem I had is that the whole implementation of the QuickSearch component is not exposed so it's not possible to do something like new QuickSearchComboBar();

After some investigation I found out that the Action for the QuichSearch component is a CallableSystemAction which has a nice little method called getToolbarPresenter() which returns an AWT Component! So now all I need is to get hold of the Action. The QuickSearchAction is living in the Layer in "Actions/Edit" so what we could do is Utilities.actionsForPath("Actions/Edit") which returns a list of Actions. But how do we actually get the Action we want?

One answer would be  (if action instanceOf QuickSearchAction)   but that will not work because QuickSearchAction is not visible and the compile of the netbeans module will fail.

So what about (if action instanceOf Presenter.Toolbar)?  Thats a bit closer but there are multiple Actions matching.

How about (if action.getValue(Action.NAME).equals("Quick search blahblah something")? Might work but what if the name changes.. especially if you are using bundles and different languages. Also you can't get the message from the bundle since NbBundle.getMessage(QuickSearchAction.class, "CTL_QuickSearchAction"); wouldn't work since QuickSearchAction is still not visible.

Finally I did it like this. In my module layer.xml file:

<folder name="QuickSearchShadow">
    <file name="org-netbeans-modules-quicksearch-QuickSearchAction.shadow">
        <attr name="originalFile" stringvalue="Actions/Edit/org-netbeans-modules-quicksearch-QuickSearchAction.instance"/>
    >/file>
</folder>

Now I have a shadow of this instance in my layer.xml and I can finally get hold of my action like this:

List<? extends Action> actions = Utilities.actionsForPath("QuickSearchShadow");
for (Action action : actions) {
    if (action instanceof Presenter.Toolbar) {
        do stuff
    }
}

So..  there we have our QuickSearchAction instance finally!  Now to "do stuff":

quickSearchToolbarItem = ((Presenter.Toolbar) action).getToolbarPresenter();
quickSearchPanel.add(quickSearchToolbarItem);

And now the complete quicksearch component is available for you and you can put it anywhere..  in an JPanel that you have created in Matisse in your Topcomponent for example.

As usual.. if anyone has a better way to do this..  please let me know..   that's one of the reasons for having a blog by others comments :-)