X

Geertjan's Blog

  • July 13, 2007

PrintCookie (Part 1)

Geertjan Wielenga
Product Manager
An extremely tricky, and potentially frustrating, area of the NetBeans Platform is the PrintCookie. Before anything else, if you do not understand what a Cookie is, in the NetBeans world, then you will be even more confused. A Cookie, simply put, is a capability. So an OpenCookie is the capability attributed to something to open the thing in question. It's like the ThinkCookie is the capability given to (some) people enabling them to think. For things that open in the editor, if you add implements PrintCookie to the class signature, you will be able to print the editor's content. In that case, things are easy and the NetBeans Platform takes care of everything. So, the Print menu item in the File menu is enabled and you don't need to do any coding at all.

However, in the case of a TopComponent and a DataObject, things are different. You need to explicitly provide the capability to print. The actual code that does the printing is just normal standard Java code, as explained in this helpful article sent to me by Tom Wheeler. However, the NetBeans Platform cannot know exactly what you want to have happen when printing a TopComponent or DataObject, hence you need to provide the code for this yourself. Including... the tricky (i.e., frustrating) part where you explicitly need to enable the Print menu item.

I'd thought about investigating this before, but yesterday the question was posed again, here in Munich. Tanja Drüke, from the GenoMatix team, needs to enable the Print menu item for a TopComponent. How to do it? There's lots of confusing and contradictory information on the mailing list on this topic. But, something written there by Craig Conover switched on the light for me: "You can create an inner class of your TC class that extends AbstractNode (or some other appropriate extension or impl of a NB Node). Then you can set this as the active Node and provide it with the appropriate CookieActions and such."

That right there is the crucial piece of information. Cookies are capabilities of Nodes. You need a Node in order to be able to assign the Print capability. Therefore, you need to create a Node in the TopComponent especially for this purpose:

private class MyPrintNode extends AbstractNode {
public MyPrintNode() {
super(Children.LEAF);
CookieSet cookies = getCookieSet();
cookies.add(new MyPrintCookie());
}
}

Note that a class called MyPrintCookie is added to the CookieSet above. In other words, the capability provided by my MyPrintCookie class is added to the set of capabilities assigned to the Node. That class must implement PrintCookie, which has one mandatory method, called print(). Here is the simplest (and least meaningful) definition:

class MyPrintCookie implements PrintCookie {
public void print() {
JOptionPane.showMessageDialog(null, "Printing...");
//Put all the standard Java printing code here!
}
}

And, finally, you need to associate the Node with the TopComponent's Lookup. In other words, you need to add the Node to the TopComponent's bag of tricks. So put this in the constructor, probably at the end, but possibly anywhere:

associateLookup(new MyPrintNode().getLookup());

And now the Print menu item is enabled. And when you select the Print menu item, the MyPrintCookie.print() method above is called. But, what if we're dealing with a DataObject instead of a TopComponent? Tom Wheeler wrote to say that one would have a MyPrintCookie class, like the above, and then add an instance of it to the DataObject's Lookup (or CookieSet, depending on which one you are using). Then, again, the print() method is invoked when the enabled menu item is selected.

As always, everything I've said above could be totally wrong, partially wrong, or brilliantly and surprisingly on the ball. So, use at your very own risk.

Join the discussion

Comments ( 7 )
  • Tom Wheeler Friday, July 13, 2007

    You gave the most concise and informative definition of NetBeans Cookie that I've ever heard.

    The name implies that it's similar to HTTP cookies or X Windows cookies, but in fact they're similar in name only. It's a bit confusing to programmers, especially those (like me) who already had a background in Web development and UNIX system administration before learning the NetBeans platform.

    I've wondered why the name 'cookie' was chosen in for this concept in NetBeans, but figured that maybe 'cookie' and 'capability' have some sort of connection in the Czech language.

  • kolisko Friday, July 13, 2007
    Tom, I'm native in Czech, however why is the NB cookie called 'Cookie' is a mystery to me. Maybe there is some explanation, that involves a pun in Czech, but I can't see it.
    Nevertheless I do agree the name is somewhat confusing.
  • Tom Wheeler Friday, July 13, 2007
    Thanks for the insight, kolisko. I got a little more curious, so I looked into the etymology and have found the answer:
    Origin of NetBeans term 'Cookie'.
  • Geertjan Tuesday, July 17, 2007
    Thanks Tom! The word 'capability' is the key in this context and is used in various placed in the Rich Client Programming book to explain cookies. Your discovery of that blog entry of Roman's is useful, he's nailed it down well there.
  • Matt Wood Tuesday, July 17, 2007
    If your TC has a Node explorer panel ie. TTV and you do all the necessary things to associate lookups etc that mean the selected node is checked for the PrintCookie the above approach can't be used unless all selectable nodes provide a PrintCookie? Since I wanted the PrintCookie to be relevant to the TC the only way I could see to get around this was to wrap each node as it is selected in a FilterNode that does provide the PrintCookie, it is messy but it worked.
  • Joe Poerschke Tuesday, October 9, 2007

    The instructions on this page did not quite work for me. By chance I discoved that after right clicking on the tab of any TopComponent the Print menu item would then be enabled correctly. (This is a good test to see if you have the suggested code implemented correctly) I then found the "What's wrong with this node & SaveCookie" thread on Nabble, from which I figured out that inserting the following code in layer.xml causes the Print(and Save/Save All,...) menu items to enable correctly:

    <filesystem>

    <folder name="Toolbars">

    <folder name="Build">

    <file name="org-openide-actions-PrintAction.instance" boolvalue="true"/>

    </folder>

    </folder>

    ...

    This page seems to be the primary source of Print enabling documentation. There is a bug in 5.? (I am in 5.5.1) that causes these instructions to not always work correctly. Seems the place to share my findings.


  • guest Thursday, January 10, 2013

    Hi Geertjan,

    Does the solution still work under Netbeans 7.3 Beta2? Or should I use the Print API instead?

    Thanks in advance!

    -Dunqiang


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