Geertjan's Blog

  • March 23, 2007

Reusing the Matisse GUI Builder Palette...

Geertjan Wielenga
Product Manager
Sometimes small changes have large consequences, unforeseen and, as a result, surprising. In Palette API and 6.0, Testing the Waters... (Part 1), I talked about the resolution of issue 90213. As a result, you can create palettes for existing editors, without changing the sources of the editor in question. The clearest illustration of this is that you can now create a module containing a palette and assign it to the Java MIME type, which means it appears when the Java editor is opened in Source view. Very useful, because then you can drag and drop snippets into the source view of a Java document in NetBeans IDE. (There was a very recent, i.e., a few days ago, further issue resolution which I will blog about in a few days, which is also very powerful in the context of creating, rather than using snippets.)

However, a probably unintended, but potentially useful, consequence of the above is that an existing editor can ask palettes created for other editors to be associated with itself. So, it works both ways. Either you create a palette for someone else's editor OR you use someone else's palette in your editor. And this is not confined to editors! This also works for TopComponents. Think about that. You can take any palette anywhere and associate it with your own TopComponent. Before showing how, here are the two major disadvantages or, at the very least, caveats:

  • This approach will result in your module depending on the module that provides the palette. If the palette in the other module is provided by someone over whom you have no control, then the palette can change without you having any influence over it!

  • This approach will give you a palette, but not necessarily all the functionality defined for the palette in the module where it is created. It is possible to extract some information from the palette, but you are still limited in terms of what you can do with the palette. The module where the palette was originally created probably has a lot of code that is very useful to the palette, code that you cannot extract along with the palette.

A better solution than following the steps below, is to provide the palette yourself, especially if the alternative is reusing a palette that comes from some module over which you have no/little control.

Okay, now that you know the downsides, let's put these thoughts into practice.

  1. Create a module. Use the New Window Component wizard to create stubs for your TopComponent.

  2. In the layer.xml file, create a folder structure under the Editors folder. Within it, use the new MIME type structure provided by issue 90213:

    <folder name="Editors">
    <folder name="abc">
    <folder name="xyz">
    <file name="PaletteFactory.instance">
    <attr name="instanceClass" stringvalue="org.netbeans.spi.palette.PaletteController"/>
    <attr name="instanceCreate" methodvalue="org.netbeans.modules.form.palette.PaletteUtils.getPalette"/>

    The abc/xyz could be anything at all. It defines our MIME type. We're not dealing with an editor here, but the principle of MIME type registration of palettes for editors is continued to TopComponents, so... we can use the same approach here, even though we are not dealing with an editor. We just need to specify a MIME type, which could be anything, and must be represented by at least one folder, so that we can associate that folder in the TopComponent. So, instead of abc/xyz, you could have foreign/palette or just one folder, called palette, or anything at all. So the abc/xyz is irrelevant, just so long as you have a MIME type, constructed out of these folders.

    The PaletteFactory.instance element, and its attributes, are mandatory. The first attribute, instanceClass, specifies the NetBeans API class that we are returning from the second attribute, instanceCreate. What we need to have returned is an instance of the NetBeans API PaletteController class. Before the fixing of issue 90213, the PaletteController class could only be instantiated within the TopComponent's constructor. Now, however, it can be done via the layer.xml.

    And, which PaletteController class are we instantiating? Look closely, friends, because this is where things become interesting! The second attribute has this value:


    In short, what that value implies is that the getPalette method in the org.netbeans.modules.form.palette.PaletteUtils class is going to provide our palette. If you dig deep into the NetBeans sources, you will find that method in that class. If you want to go down this road, the road of having other modules provide your palettes, then you need to know which method provides the palette in the module where the palette is defined. That requires that the writer of the original module should tell you or that you should find out by actually reading the sources of the module in question.

    And which module provides the palette above? The same module that provides the Matisse GUI Builder. "Hold on now. Are you saying that at the end of this little procedure I will have the Matisse GUI Builder's palette in my own TopComponent?" Yes. That is exactly what I am saying. Now back up a second and read the two caveats above again. Are you sure you want the Matisse GUI Builder's palette? Are you prepared for it to change, with the result that your module's functionality will change too?

    The Matisse GUI Builder does not provide an API, but that is basically how we are using it here. So, that's what I meant when I started this blog entry by burbling about the unintended consequences of small changes.

  3. In your TopComponent's constructor, associate the palette that you registered in the layer.xml with the TopComponent:

    associateLookup( Lookups.fixed( new Object[] {
    } ) );

    So, here we associate our palette with the TopComponent. And here's the magical method that does the work:

    private static PaletteController pc;
    public static PaletteController getPaletteFromMimeType( String mimeType ) {
    MimePath path = MimePath.get( mimeType );
    Lookup lkp = MimeLookup.getLookup( path );
    pc = (PaletteController) lkp.lookup(org.netbeans.spi.palette.PaletteController.class);
    return pc;

  4. You will need to declare dependencies on 'Common Palette' and 'MIME Lookup API'. Later, you will need the 'Nodes API', among others, too.

  5. Now you can already install your module! Open the TopComponent and notice... the Matisse GUI Builder palette is now available to your TopComponent. They open and close together, unless you close one of them separately, and then the connection between them is lost, until they're opened together again (as discussed in detail elsewhere in this blog).

    Note: You have to open a regular form first, to initialize its palette, only then can you open your own form, which then steals the first form's initialized palette. Otherwise, you get an ugly error.

  6. Okay, so now you might say: "Big deal. I have that palette. Okay, it looks nice. But there's nothing I can do with it." Not true. Read Chapter 15 of "Rich Client Programming". There you'll read about adding a JPanel to a TopComponent and how to turn it into a "drop panel", which can accept drops.

  7. "That's nice, but I have no control over that palette, so there's no way for me to know what I am dragging, so I can't know what is being dropped." Wrong again. Readers of the tutorials at http://platform.netbeans.org/tutorials know that palette items are nodes. Therefore, you can get the selected palette item from the PaletteController and then query the node for its name and its icon. That's all you really want to know from a node in this context anyway.

    private static PaletteController pc;
    String selectedName = null;
    Image dragImage = null;
    Lookup selectedPaletteItem = pc.getSelectedItem();
    if( null != selectedPaletteItem ) {
    Node selectedNode = (Node)selectedPaletteItem.lookup( Node.class );
    if( null != selectedNode ) {
    selectedName = selectedNode.getDisplayName();
    dragImage = selectedNode.getIcon(BeanInfo.ICON_COLOR_32x32);

    Now that you have the name and the image, you're all set to do whatever you want to do with the palette items. Read the tutorials for all the details about drag images, drop targets, drag gestures, and so on. You can also find information in those tutorials about how to specify what happens when a palette item is dropped, in other words, how to get from the knowledge of the name of the node that defines the palette item to the appearance on your TopComponent of a new widget, and how to define that widget.

    Above is where things are at this stage of the story. Note that I haven't been able to get the palette associated with the design/visual view of a multiview API implementation. I'm still investigating that, but the palette appears correctly in normal plain TopComponents.

  8. At this stage, you have a perfectly useful palette. However, your drop target, i.e., a TopComponent, is far from perfect. You need much more functionality there, which is where the Visual Library comes in. Have a look at the NetBeans Visual Library 2.0, and specifically at Toni's Project Jarvis for all the details involved here. Basically, you want to create a scenario where you get guidelines and other features for helping the user position, and reposition, dropped palette items on a surface.

  9. And then you need the appropriate code to be generated. For Groovy, for example, which is the ultimate aim that I'm going for here, Groovy code would be generated in the source view whenever a palette item is dropped. However, as stated above, currently I haven't got the Matisse GUI Builder palette to appear in the design/visual view of multiview editors yet.

Probably the above approach isn't the best way to do things. However, it is interesting and, as regular readers of this blog know, this blog is defined more by what is interesting than by what is correct. :-) Hopefully, anyway, this gives a new perspective on the flexibility that you now have when working with palettes. Essentially, you can treat a palette as if it is just a component that can be created in one module and then reused anywhere else. Watch those caveats, though...

In other news. Things are going slowly with my Groovy Editor because I've been distracted by Sun's freshly launched interactive game, "Temple of the Sun". It's funny and it's fun and it's free. I've been able to test it out and it's pretty cool. Folks who finish the game, with the highest scores, will be eligible to win some serious cash and prizes. The top winner will receive $5,000 USD. Anyone can play the game, but you'll need Sun Studio software or Solaris Express Developer Edition to complete it. And they're free. Unfortunately for me, Sun employees aren't eligible. But you can play and win, hurray. Go here to download Sun Studio and go here to get a free media kit of Solaris Express, Developer Edition.

Join the discussion

Comments ( 9 )
  • good Monday, April 30, 2007
    nice to you
  • scape Tuesday, May 1, 2007
  • good Monday, July 30, 2007
    大阪 風俗 東京 風俗 <a href="http://www.uguisunet.com">uguisu 断熱 塗料
  • Top News Search Thursday, March 27, 2008

    Needfornews.com New great news aggregator. With it You won't need anything else to read news.



  • Miss Potter Monday, April 14, 2008

    Thousands of hot movies that you dare to watch. Movies are playable on various devices including iPod, PDA (HandHelds), PC, DVD & DivX players. Lowest prices on the web ever. Start downloading movies from $1.99 only! Absolutely no limits. You can download as much as you want with incredibly high speeds. No additional software required. Click on a link, download a movie and watch it on your favourite player.


  • &#12464;&#12483;&#12489; Wednesday, May 7, 2008


  • aeixx Friday, August 8, 2008
  • Peter Kutschera Thursday, March 26, 2009

    Well, unforunatly I cant find either




    within my NB6.7M2 platform :-(

    "Add Modul Dependency" did not find anything as does a find within th netbeans sources.

    What did I miss?

  • Geertjan Wielenga Thursday, March 26, 2009

    This blog entry was written 2 years ago. You think maybe things might have changed since then?

Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.