mbien commented on code in PR #17:
URL: 
https://github.com/apache/netbeans-antora-wiki/pull/17#discussion_r2410888538


##########
modules/netbeansdevelopperfaq/pages/DevFaqActionContextSensitive.adoc:
##########
@@ -140,48 +140,74 @@ public class FooAction extends AbstractAction implements 
LookupListener, Context
 
 ----
 
-== Deprecated CookieAction
+Let's register the above action and see how it works.
 
-In many older (pre-NB 6.8) examples you may find 
link:{apidoclink}org-openide-nodes/org/openide/util/actions/CookieAction.html[CookieAction].
 It should be (but is not) deprecated. The original info is left here for 
reference and/or old code maintenance:
+[source,java]
+----
+@ActionID(category = "foocat", id = "org.fooaction")
+@ActionRegistration(displayName = "not_used", lazy = false)  // displayName 
useless if lazy is false
+@ActionReferences(
+        {
+            @ActionReference(path = "Menu/Edit", position = 100),  // add an 
entry in the app-level edit menu 
+            @ActionReference(path = "Shortcuts", name = "O-Z"),    // action 
can be directly run with alt-Z
+            @ActionReference(path = "Actions/Popupmenu", position = 3)   // 
add a menu entry in a contextual popup menu
+        })
+public class FooAction extends AbstractAction implements LookupListener, 
ContextAwareAction {
+...
+----
 
-link:{apidoclink}org-openide-nodes/org/openide/util/actions/CookieAction.html[CookieAction]
 is used to write actions that are sensitive to what is in the selected Node(s) 
xref:./DevFaqLookup.adoc[Lookup].  You can specify one or more classes that 
must be present in the selected xref:./DevFaqWhatIsANode.adoc[Node]'s Lookup, 
and some other semantics about enablement.
+When the Netbeans platform application is started:
 
-Being an older class, under the hood it is using 
xref:./DevFaqLookupCookie.adoc[Node.getCookie()], so your action will only be 
sensitive to things actually returned by that method - in other words, only 
objects that implement the marker interface `Node.Cookie` can work here.
+* a `FooAction` instance is created automatically using the no-arg constructor 
when the edit menu is created
+* the same instance is reused and associated to the alt-Z shortcut
+
+As there can be many actions in a platform app, the constructors must be 
lightweight. That's why we start listening to the `Lookup.Result` only when the 
menu item is about to be displayed.
 
-== Not-Yet-Official spi.actions
+To further optimize application startup time, you should register your action 
with `lazy=true` whenever possible (see limitations in the 
`@ActionRegistration` javadoc). In lazy instanciation mode the `displayName` 
value (and other optional parameters) is used to build the action menu item, 
and the `FooAction` instance is created only when the menu entry (or keyboard 
shortcut) is actually selected by user.
 
-This module is part of the platform as of 6.8, but has not yet become official 
API (and nobody seems to be willing to make it stable API, so judge your own 
decisions based on this fact).  Nonetheless it is there, it is not changing and 
straightforward to use.  The example below opens a visual editor window if an 
instance of RAFDataObject is selected and has a RandomAccessFile in its lookup:
+The `FooAction` no-arg constructor uses the global selection context 
(xref:./DevFaqTrackGlobalSelection.adoc[DevFaqTrackGlobalSelection]), i.e. 
action will be enabled only when `Whatever` instances are present in the lookup 
of the focused `TopComponent`.
 
+`FooAction` also implements `ContextAwareAction`. This is used by methods 
`Utilities.actionsForPath()` and `Actions.actionsToPopup()` when building a 
contextual popup menu, for example:
 [source,java]
 ----
+var actions = Utilities.actionsForPath("Actions/Popupmenu"); 
+var context = myEditorTopComponent.getLookup();
+var popupmenu = Actions.actionsToPopup(actions, context); 
+----
+In our case `actionsToPopup()` will find our FooAction_instance and, because 
it's a `ContextAwareAction`, will create a menu item based on the the return 
value of FooAction_instance `createContextAwareInstance(context)`. The return 
value must be considered as a transient instance because a new `FooAction` 
instance is created each time the popup menu is built (i.e. if the transient 
instance needs to listen to a shared object, you should probably use a 
`WeakListener`).
 
-public final class CustomOpenAction extends 
org.netbeans.spi.actions.Single<RAFDataObject>
- {
-    public CustomOpenAction() {
-      super(RAFDataObject.class, "Open", null);
-    }
-    @Override
-    protected void actionPerformed(RAFDataObject target) {
-      //If an editor is already open, just give it focus
-      for (TopComponent tc : TopComponent.getRegistry().getOpened()) {
-        if (tc instanceof RAFEditor &amp;&amp; 
tc.getLookup().lookup(RAFDataObject.class) == target) {
-          tc.requestActive();
-          return;
-        }
-      }
-      //Nope, need a new editor
-      TopComponent editorWindow = null;
-      editorWindow = new RAFEditor(target);
-      editorWindow.open();
-      editorWindow.requestActive();
-    }
-    @Override
-    protected boolean isEnabled(RAFDataObject target) {
-      //Make sure there really is a file on disk
-      return target.getLookup().lookup(RandomAccessFile.class) != null;
-    }
-  }
+Note that even if `FooAction` does not implement `ContextAwareAction`, 
different `Utilities.actionsForPath()` calls might return different `FooAction` 
instances if there is no strong reference on these instances.
 
+If you need to enforce `FooAction` as a singleton, it's possible to register a 
static factory method instead of the class:
+[source,java]
+----
+public class FooAction extends AbstractAction implements LookupListener {
+
+  private FooAction INSTANCE;
+  @ActionID(category = "foocat", id = "org.fooaction")
+  @ActionRegistration(displayName = "not_used", lazy = false)  // displayName 
useless if lazy is false
+  @ActionReferences(
+          {
+              @ActionReference(path = "Menu/Edit", position = 100),  // add an 
entry in the app-level edit menu 
+              @ActionReference(path = "Shortcuts", name = "O-Z"),    // action 
can be directly run with alt-Z
+              @ActionReference(path = "Actions/Popupmenu", position = 3)   // 
add a menu entry in a contextual popup menu
+          })
+   public static FooAction getInstance() {
+        if (INSTANCE==null)
+        {
+              INSTANCE = new FooAction();
+        }
+   return INSTANCE;
+}

Review Comment:
   formatting:
   ```java
       public static FooAction getInstance() {
           if (INSTANCE == null) {
               INSTANCE = new FooAction();
           }
           return INSTANCE;
       }
   ```



##########
modules/netbeansdevelopperfaq/pages/DevFaqActionContextSensitive.adoc:
##########
@@ -140,48 +140,74 @@ public class FooAction extends AbstractAction implements 
LookupListener, Context
 
 ----
 
-== Deprecated CookieAction
+Let's register the above action and see how it works.
 
-In many older (pre-NB 6.8) examples you may find 
link:{apidoclink}org-openide-nodes/org/openide/util/actions/CookieAction.html[CookieAction].
 It should be (but is not) deprecated. The original info is left here for 
reference and/or old code maintenance:
+[source,java]
+----
+@ActionID(category = "foocat", id = "org.fooaction")
+@ActionRegistration(displayName = "not_used", lazy = false)  // displayName 
useless if lazy is false
+@ActionReferences(
+        {
+            @ActionReference(path = "Menu/Edit", position = 100),  // add an 
entry in the app-level edit menu 
+            @ActionReference(path = "Shortcuts", name = "O-Z"),    // action 
can be directly run with alt-Z
+            @ActionReference(path = "Actions/Popupmenu", position = 3)   // 
add a menu entry in a contextual popup menu
+        })
+public class FooAction extends AbstractAction implements LookupListener, 
ContextAwareAction {
+...
+----
 
-link:{apidoclink}org-openide-nodes/org/openide/util/actions/CookieAction.html[CookieAction]
 is used to write actions that are sensitive to what is in the selected Node(s) 
xref:./DevFaqLookup.adoc[Lookup].  You can specify one or more classes that 
must be present in the selected xref:./DevFaqWhatIsANode.adoc[Node]'s Lookup, 
and some other semantics about enablement.
+When the Netbeans platform application is started:
 
-Being an older class, under the hood it is using 
xref:./DevFaqLookupCookie.adoc[Node.getCookie()], so your action will only be 
sensitive to things actually returned by that method - in other words, only 
objects that implement the marker interface `Node.Cookie` can work here.
+* a `FooAction` instance is created automatically using the no-arg constructor 
when the edit menu is created
+* the same instance is reused and associated to the alt-Z shortcut
+
+As there can be many actions in a platform app, the constructors must be 
lightweight. That's why we start listening to the `Lookup.Result` only when the 
menu item is about to be displayed.
 
-== Not-Yet-Official spi.actions
+To further optimize application startup time, you should register your action 
with `lazy=true` whenever possible (see limitations in the 
`@ActionRegistration` javadoc). In lazy instanciation mode the `displayName` 
value (and other optional parameters) is used to build the action menu item, 
and the `FooAction` instance is created only when the menu entry (or keyboard 
shortcut) is actually selected by user.
 
-This module is part of the platform as of 6.8, but has not yet become official 
API (and nobody seems to be willing to make it stable API, so judge your own 
decisions based on this fact).  Nonetheless it is there, it is not changing and 
straightforward to use.  The example below opens a visual editor window if an 
instance of RAFDataObject is selected and has a RandomAccessFile in its lookup:
+The `FooAction` no-arg constructor uses the global selection context 
(xref:./DevFaqTrackGlobalSelection.adoc[DevFaqTrackGlobalSelection]), i.e. 
action will be enabled only when `Whatever` instances are present in the lookup 
of the focused `TopComponent`.
 
+`FooAction` also implements `ContextAwareAction`. This is used by methods 
`Utilities.actionsForPath()` and `Actions.actionsToPopup()` when building a 
contextual popup menu, for example:
 [source,java]
 ----
+var actions = Utilities.actionsForPath("Actions/Popupmenu"); 
+var context = myEditorTopComponent.getLookup();
+var popupmenu = Actions.actionsToPopup(actions, context); 
+----
+In our case `actionsToPopup()` will find our FooAction_instance and, because 
it's a `ContextAwareAction`, will create a menu item based on the the return 
value of FooAction_instance `createContextAwareInstance(context)`. The return 
value must be considered as a transient instance because a new `FooAction` 
instance is created each time the popup menu is built (i.e. if the transient 
instance needs to listen to a shared object, you should probably use a 
`WeakListener`).
 
-public final class CustomOpenAction extends 
org.netbeans.spi.actions.Single<RAFDataObject>
- {
-    public CustomOpenAction() {
-      super(RAFDataObject.class, "Open", null);
-    }
-    @Override
-    protected void actionPerformed(RAFDataObject target) {
-      //If an editor is already open, just give it focus
-      for (TopComponent tc : TopComponent.getRegistry().getOpened()) {
-        if (tc instanceof RAFEditor &amp;&amp; 
tc.getLookup().lookup(RAFDataObject.class) == target) {
-          tc.requestActive();
-          return;
-        }
-      }
-      //Nope, need a new editor
-      TopComponent editorWindow = null;
-      editorWindow = new RAFEditor(target);
-      editorWindow.open();
-      editorWindow.requestActive();
-    }
-    @Override
-    protected boolean isEnabled(RAFDataObject target) {
-      //Make sure there really is a file on disk
-      return target.getLookup().lookup(RandomAccessFile.class) != null;
-    }
-  }
+Note that even if `FooAction` does not implement `ContextAwareAction`, 
different `Utilities.actionsForPath()` calls might return different `FooAction` 
instances if there is no strong reference on these instances.
 
+If you need to enforce `FooAction` as a singleton, it's possible to register a 
static factory method instead of the class:
+[source,java]
+----
+public class FooAction extends AbstractAction implements LookupListener {
+
+  private FooAction INSTANCE;
+  @ActionID(category = "foocat", id = "org.fooaction")
+  @ActionRegistration(displayName = "not_used", lazy = false)  // displayName 
useless if lazy is false
+  @ActionReferences(
+          {
+              @ActionReference(path = "Menu/Edit", position = 100),  // add an 
entry in the app-level edit menu 
+              @ActionReference(path = "Shortcuts", name = "O-Z"),    // action 
can be directly run with alt-Z
+              @ActionReference(path = "Actions/Popupmenu", position = 3)   // 
add a menu entry in a contextual popup menu
+          })
+   public static FooAction getInstance() {
+        if (INSTANCE==null)
+        {
+              INSTANCE = new FooAction();
+        }
+   return INSTANCE;
+}
+...
 ----
 
-Use `ContextAction` instead of `Single` to create actions that operate on 
multi-selections.
+
+== Deprecated CookieAction
+
+In many older (pre-NB 6.8) examples you may find 
link:{apidoclink}org-openide-nodes/org/openide/util/actions/CookieAction.html[CookieAction].
 It should be (but is not) deprecated. The original info is left here for 
reference and/or old code maintenance:

Review Comment:
   we can't call something deprecated if it isn't deprecated since the term has 
a well defined meaning in the java world.
   
   Would be good to phrase this differently. "Preferred solution" as the API 
calls it or "best practice" etc. We can still deprecate it but dependent on the 
usage this might be a larger effort.



##########
modules/netbeansdevelopperfaq/pages/DevFaqActionContextSensitive.adoc:
##########
@@ -140,48 +140,74 @@ public class FooAction extends AbstractAction implements 
LookupListener, Context
 
 ----
 
-== Deprecated CookieAction
+Let's register the above action and see how it works.
 
-In many older (pre-NB 6.8) examples you may find 
link:{apidoclink}org-openide-nodes/org/openide/util/actions/CookieAction.html[CookieAction].
 It should be (but is not) deprecated. The original info is left here for 
reference and/or old code maintenance:
+[source,java]
+----
+@ActionID(category = "foocat", id = "org.fooaction")
+@ActionRegistration(displayName = "not_used", lazy = false)  // displayName 
useless if lazy is false
+@ActionReferences(
+        {
+            @ActionReference(path = "Menu/Edit", position = 100),  // add an 
entry in the app-level edit menu 
+            @ActionReference(path = "Shortcuts", name = "O-Z"),    // action 
can be directly run with alt-Z
+            @ActionReference(path = "Actions/Popupmenu", position = 3)   // 
add a menu entry in a contextual popup menu
+        })
+public class FooAction extends AbstractAction implements LookupListener, 
ContextAwareAction {
+...
+----
 
-link:{apidoclink}org-openide-nodes/org/openide/util/actions/CookieAction.html[CookieAction]
 is used to write actions that are sensitive to what is in the selected Node(s) 
xref:./DevFaqLookup.adoc[Lookup].  You can specify one or more classes that 
must be present in the selected xref:./DevFaqWhatIsANode.adoc[Node]'s Lookup, 
and some other semantics about enablement.
+When the Netbeans platform application is started:
 
-Being an older class, under the hood it is using 
xref:./DevFaqLookupCookie.adoc[Node.getCookie()], so your action will only be 
sensitive to things actually returned by that method - in other words, only 
objects that implement the marker interface `Node.Cookie` can work here.
+* a `FooAction` instance is created automatically using the no-arg constructor 
when the edit menu is created
+* the same instance is reused and associated to the alt-Z shortcut
+
+As there can be many actions in a platform app, the constructors must be 
lightweight. That's why we start listening to the `Lookup.Result` only when the 
menu item is about to be displayed.
 
-== Not-Yet-Official spi.actions
+To further optimize application startup time, you should register your action 
with `lazy=true` whenever possible (see limitations in the 
`@ActionRegistration` javadoc). In lazy instanciation mode the `displayName` 
value (and other optional parameters) is used to build the action menu item, 
and the `FooAction` instance is created only when the menu entry (or keyboard 
shortcut) is actually selected by user.
 
-This module is part of the platform as of 6.8, but has not yet become official 
API (and nobody seems to be willing to make it stable API, so judge your own 
decisions based on this fact).  Nonetheless it is there, it is not changing and 
straightforward to use.  The example below opens a visual editor window if an 
instance of RAFDataObject is selected and has a RandomAccessFile in its lookup:
+The `FooAction` no-arg constructor uses the global selection context 
(xref:./DevFaqTrackGlobalSelection.adoc[DevFaqTrackGlobalSelection]), i.e. 
action will be enabled only when `Whatever` instances are present in the lookup 
of the focused `TopComponent`.
 
+`FooAction` also implements `ContextAwareAction`. This is used by methods 
`Utilities.actionsForPath()` and `Actions.actionsToPopup()` when building a 
contextual popup menu, for example:
 [source,java]
 ----
+var actions = Utilities.actionsForPath("Actions/Popupmenu"); 
+var context = myEditorTopComponent.getLookup();
+var popupmenu = Actions.actionsToPopup(actions, context); 

Review Comment:
   please use types instead of `var` for tutorial code, otherwise it becomes 
pseudo code without IDE support which renders the type next to it - esp for 
readers who are new to the API.
   
   feel free to force push



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists

Reply via email to