This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.
@ActionID(category = "Build", id = "testsurvive.OtherAction") @ActionRegistration(displayName = "Click Me Too") @ActionReference(path = "Toolbars/File", position = 1) public class OtherAction extends CookieAction { protected @Override int mode() { return MODE_EXACTLY_ONE; } protected @Override Class<?>[] cookieClasses() { return new Class<?>[] {DataObject.class}; } protected @Override void performAction(Node[] nodes) { System.err.println(nodes[0].getLookup().lookup(DataObject.class)); } public @Override String getName() { return "Click Me Too"; } public @Override HelpCtx getHelpCtx() { return null; } } works as you would expect: run from a standalone module, Ctrl-3, click the root Home node or some node beneath it, and the toolbar button enables and works when clicked. Ctrl-4, button remains enabled and works when clicked, since OW has no selection. Ctrl-5, button is disabled as expected, since Services does have a selection but no DataObject in it. @ActionID(category = "Build", id = "testsurvive.SomeAction") @ActionRegistration(displayName = "Click Me", surviveFocusChange=true) @ActionReference(path = "Toolbars/File", position = 0) public final class SomeAction implements ActionListener { private final DataObject context; public SomeAction(DataObject context) { this.context = context; } public @Override void actionPerformed(ActionEvent ev) { System.err.println(context); } } does not work as documented (in fact there is no apparent difference if sFC=false): after Ctrl-4, button is disabled even though OW has no selection. Also, oddly, this action is disabled on the root "Home" node (a DataShadow), though it is enabled on the child nodes.
The problem with not being enabled on "Home" is that in the lookup of the node there are two DataObjects - shadow and original one. Because you are in EXACTLY_ONE mode, the action is then disabled. You can report that as another issue.
Otherwise I can confirm your observation. Behavior of context selection is the same regardless of the surviveFocusChange. Only ActionMap interaction honors that attribute for now.
ergonomics#0a63862ca972
(In reply to comment #1) > The problem with not being enabled on "Home" is that in the lookup of the node > there are two DataObjects - shadow and original one. Makes a certain amount of sense. Arguably an issue in the Favorites tab. Not sure if it is worth fixing, or what the fix would be; certain actions might care about the original dir, others about the shadow. (Probably most actions would fall into the first category, whereas just actions implemented in the favorites module would fall into the second.) > Because you are in EXACTLY_ONE mode, the action is then disabled. Only for the factory version. The CookieAction is enabled on this - bug in CookieAction, perhaps?
Integrated into 'main-golden', will be available in build *201104150401* on http://bits.netbeans.org/dev/nightly/ (upload may still be in progress) Changeset: http://hg.netbeans.org/main/rev/0a63862ca972 User: Jaroslav Tulach <jtulach@netbeans.org> Log: #197339: Support at least bit of surviveFocusChange for context actions
Now it is broken in the other direction - it survives too much. A system action with sFC=true will remain enabled when you click on the Output Window (say), but will be correctly disabled if you click on some random node in the Services tab (say). That is because Services is an explorer view and provides a selection, but the selection does not match the criteria. But a factory action with sFC=true will now remain enabled *permanently* if it ever becomes enabled; even selecting the "Databases" node in Services, then clearing the selection entirely, leaves it enabled and still active on the last file you selected (if sensitive to DataObject as in the example). (In reply to comment #4) >> Because you are in EXACTLY_ONE mode, the action is then disabled. > > Only for the factory version. The CookieAction is enabled on this My guess is that the cause is that for either the DataShadow or its nodeDelegate, getLookup().lookupAll(DataObject.class) returns both the shadow and the original (and both are included in actionsGlobalContext), whereas (again for either the DO or its Node) getCookie(DataObject) returns just the shadow. If CookieAction is actually calling getCookie then it would be broken in this way. My impression was that it had been retrofitted to use lookup throughout, but perhaps I am wrong?
(In reply to comment #6) > Now it is broken in the other direction - it survives too much. Right. This one will be harder to fix. But I believe it is not as big problem, so making P3. > (In reply to comment #4) > >> Because you are in EXACTLY_ONE mode, the action is then disabled. > > > > Only for the factory version. The CookieAction is enabled on this > > My guess is that the cause is that for either the DataShadow or its > nodeDelegate, getLookup().lookupAll(DataObject.class) returns both the shadow NodeAction and CookieAction work on Node. First of all they obtains list of all Nodes and then they query each node's lookup for particular interface. The new context actions know nothing about nodes. As a result: 1. they don't know when to be disabled - e.g. survive too much 2. they improperly count selected objects - problems with EXACTLY_ONE & ALL I was hoping to use Lookup.Provider as a replacement for Node, but I don't think it will really work as Node, DataObject are both providers, so there will be too many of them...
I can reproduce the "surviveFocusChange=true survives too much" problem (comment #6 and comment #7) on 7.1.1 using a String (or some other simple object) as the context object. My TopComponent adds a context object to its lookup, and the context aware action works as expected, with the action surviving a focus change, also as expected. However, this has the side effect that the menu item remains enabled even after the TopComponent has been closed. Executing the action shows that the action is still connected to the context object that was in the TopComponent's lookup, even if the context object is removed from the lookup in componentClosed(). Also, another action that listens on the same class that doesn't have surviveFocusChange also remains enabled if an attempt was made to execute it using a shortcut with focus in another TopComponent, although it doesn't seem to execute. Furthermore, the menu items remain enabled after the application is closed and reopened, and before the TopComponent is opened, although they don't seem to execute. A "Clean and Build All" of the module suite disables them the next time the application is run. Hanging on to the context object means (for my application) a potentially large amount of memory is not garbage collected and resources aren't correctly cleaned up, not to mention an action being able to execute on a context object without its TopComponent. For us this *is* a big problem. Can I request a P1 priority?
You may make the problem P1, but in such case please donate a failing unit test.
Created attachment 117070 [details] Reproducer for problems in comment 8 (zipped platform application) I don't know if you want a specific format. The attachment is a reproducer for the problems.
PS see README.txt in the project root directory.
Thanks for the example. You are right, the behavior does not seem correct.
Not a P1 since you can just use CookieAction if you need sFC=true until this bug is fixed. Right?
I don't know. I'm still learning the platform, so I'm unfamiliar with CookieAction, cookies, or editing layer.xml (I've used annotations for pretty much everything so far). Looking at the documentation, it's not a simple edit of the existing actions, I'd have to rewrite them now and rewrite them back again after sFC=true is fixed. It may be technically possible but given the above, it doesn't seem practical to use "Not the preferred solution anymore" (to quote the documentation) as a workaround when I'm still trying to figure out how the preferred solutions work.
If you are interested in trying, a working example of CookieAction (with annotation-based registration) was given at the start of comment #0.
Observation about the sfc.zip example. The whole system works much better if you don't extend Node. E.g. "public class StringNode extends Object".
The "extends Node" issue was solved in ergonomics#95c221f99c03
Your comment #17 arrived as I was replying to your comment #16. But isn't this how Node is supposed to be used? As well as adding the Node to the TopComponent's lookup, should I also add the instance of my data class to the lookup and use that for context-aware actions, instead of using a Node and getting the data from that? Does comment #17 mean that the answer to the second question is "no"? :-)
I have not solved the DataObject vs. DataShadow issue, but I think now the system behaves much better: ergonomics#db3fac3100ca
Integrated into 'main-golden', will be available in build *201205040400* on http://bits.netbeans.org/dev/nightly/ (upload may still be in progress) Changeset: http://hg.netbeans.org/main-golden/rev/95c221f99c03 User: Jaroslav Tulach <jtulach@netbeans.org> Log: #197339: More sane behavior of the lookup when queried about Node subclasses and superclasses. Ensure the sfc.zip example leaves both actions disabled after restart.
Integrated into 'main-golden', will be available in build *201205050400* on http://bits.netbeans.org/dev/nightly/ (upload may still be in progress) Changeset: http://hg.netbeans.org/main-golden/rev/db3fac3100ca User: Jaroslav Tulach <jtulach@netbeans.org> Log: #197339: Paying attention to setActivatedNodes(null) or setActivatedNodes(something).