You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@netbeans.apache.org by sd...@apache.org on 2023/01/06 13:10:58 UTC

[netbeans] branch master updated: Allow to collect contextual actions from layer path.

This is an automated email from the ASF dual-hosted git repository.

sdedic pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/netbeans.git


The following commit(s) were added to refs/heads/master by this push:
     new 8d960aa926 Allow to collect contextual actions from layer path.
     new 575e58c800 Merge pull request #5198 from sdedic/platform/action-forpath-lookup
8d960aa926 is described below

commit 8d960aa92632369280e96260937131d08d6ea36b
Author: Svata Dedic <sv...@oracle.com>
AuthorDate: Wed Jan 4 14:44:25 2023 +0100

    Allow to collect contextual actions from layer path.
---
 platform/openide.util.ui/apichanges.xml            | 16 ++++++
 platform/openide.util.ui/manifest.mf               |  2 +-
 .../src/org/openide/util/Utilities.java            | 36 ++++++++++++
 .../unit/src/org/openide/util/UtilitiesTest.java   | 67 ++++++++++++++++++----
 4 files changed, 110 insertions(+), 11 deletions(-)

diff --git a/platform/openide.util.ui/apichanges.xml b/platform/openide.util.ui/apichanges.xml
index c6c18b20d0..df05fa02de 100644
--- a/platform/openide.util.ui/apichanges.xml
+++ b/platform/openide.util.ui/apichanges.xml
@@ -27,6 +27,22 @@
     <apidef name="actions">Actions API</apidef>
 </apidefs>
 <changes>
+    <change id="actionsForPathLookup">
+         <api name="util"/>
+         <summary>Added variant Utilities.actionsForPath with Lookup that produces context-aware actions</summary>
+         <version major="9" minor="28"/>
+         <date day="5" month="1" year="2023"/>
+         <author login="sdedic"/>
+         <compatibility addition="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" deletion="no" modification="no"/>
+         <description>
+             <p>
+                 Added a variant <a href="@TOP@/org/openide/util/Utilities.html#actionsForPath-java.lang.String-org.openide.util.Lookup-">actionsToPath</a> that instantiates context-bound actions if the registered action(s) implements 
+                 <a href="@TOP@/org/openide/util/ContextAwareAction.html">ContextAwareAction</a>.
+                 Improves consistency with <a href="@TOP@/org/openide/util/Utilities.html#actionsToPopup-javax.swing.Action:A-org.openide.util.Lookup-">actionsToPopup</a> that supports contextual actions. 
+             </p>
+         </description>
+         <class package="org.openide.util" name="Utilities"/>
+    </change>
     <change id="findDialogParent">
          <api name="util"/>
          <summary>static method Utilities.findDialogParent added</summary>
diff --git a/platform/openide.util.ui/manifest.mf b/platform/openide.util.ui/manifest.mf
index 55ba833d87..b43b2faf9e 100644
--- a/platform/openide.util.ui/manifest.mf
+++ b/platform/openide.util.ui/manifest.mf
@@ -1,5 +1,5 @@
 Manifest-Version: 1.0
 OpenIDE-Module: org.openide.util.ui
 OpenIDE-Module-Localizing-Bundle: org/openide/util/Bundle.properties
-OpenIDE-Module-Specification-Version: 9.27
+OpenIDE-Module-Specification-Version: 9.28
 
diff --git a/platform/openide.util.ui/src/org/openide/util/Utilities.java b/platform/openide.util.ui/src/org/openide/util/Utilities.java
index 3310e33657..ba5d85eb3e 100644
--- a/platform/openide.util.ui/src/org/openide/util/Utilities.java
+++ b/platform/openide.util.ui/src/org/openide/util/Utilities.java
@@ -1842,6 +1842,42 @@ public final class Utilities {
         return actions;
     }
 
+    /**
+     * Loads a menu sequence from a path, given a specific context as Lookup. This variant will allow to use action's contextual presence, enablement or selection,
+     * based on Lookup contents. If the registered action implements a {@link ContextAwareAction}, an instance bound to the passed `context' will be created - if
+     * the context factory returns {@code null}, indicating the action is not appropriate for the context, the registration will be skipped.
+     * Use {@link #actionsGlobalContext()} to supply global context.
+     * 
+     * Any {@link Action} instances are returned as is;
+     * any {@link JSeparator} instances are translated to nulls.
+     * Warnings are logged for any other instances.
+     * @param path a path as given to {@link Lookups#forPath}, generally a layer folder name
+     * @param context the context passed to the action(s)
+     * @return a list of actions interspersed with null separators
+     * @since 7.14
+     */
+    public static List<? extends Action> actionsForPath(String path, Lookup context) {
+        List<Action> actions = new ArrayList<Action>();
+        for (Lookup.Item<Object> item : Lookups.forPath(path).lookupResult(Object.class).allItems()) {
+            if (Action.class.isAssignableFrom(item.getType())) {
+                Object instance = item.getInstance();
+                if (instance instanceof ContextAwareAction) {
+                    Object contextAwareInstance = ((ContextAwareAction)instance).createContextAwareInstance(context);
+                    if (contextAwareInstance == null) {
+                        Logger.getLogger(Utilities.class.getName()).log(Level.WARNING,"ContextAwareAction.createContextAwareInstance(context) returns null. That is illegal!" + " action={0}, context={1}", new Object[] {instance, context});
+                    } else {
+                        instance = contextAwareInstance;
+                    }
+                }
+                actions.add((Action) instance);
+            } else if (JSeparator.class.isAssignableFrom(item.getType())) {
+                actions.add(null);
+            } else {
+                Logger.getLogger(Utilities.class.getName()).log(Level.WARNING, "Unrecognized object of {0} found in actions path {1}", new Object[] {item.getType(), path});
+            }
+        }
+        return actions;
+    }
     /**
      * Global context for actions. Toolbar, menu or any other "global"
      * action presenters shall operate in this context.
diff --git a/platform/openide.util.ui/test/unit/src/org/openide/util/UtilitiesTest.java b/platform/openide.util.ui/test/unit/src/org/openide/util/UtilitiesTest.java
index 9bada3d2d9..84bb0a930d 100644
--- a/platform/openide.util.ui/test/unit/src/org/openide/util/UtilitiesTest.java
+++ b/platform/openide.util.ui/test/unit/src/org/openide/util/UtilitiesTest.java
@@ -86,6 +86,7 @@ import java.awt.peer.ScrollbarPeer;
 import java.awt.peer.TextAreaPeer;
 import java.awt.peer.TextFieldPeer;
 import java.awt.peer.WindowPeer;
+import java.beans.PropertyChangeListener;
 import java.net.URL;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -273,6 +274,39 @@ public class UtilitiesTest extends NbTestCase {
             done.release();
         }
     }
+    
+    public static class ContextData {
+        final String suffix;
+
+        public ContextData(String suffix) {
+            this.suffix = suffix;
+        }
+    }
+
+    public void testActionsForPathWithLookup() throws Exception {
+        MockLookup.setInstances(new NamedServicesProviderImpl());
+        // #156829: ensure that no tree lock is acquired.
+        final Semaphore ready = new Semaphore(0);
+        final Semaphore done = new Semaphore(0);
+        EventQueue.invokeLater(new Runnable() {
+            public void run() {
+                synchronized (new JSeparator().getTreeLock()) {
+                    ready.release();
+                    try {
+                        done.acquire();
+                    } catch (InterruptedException ex) {
+                        Exceptions.printStackTrace(ex);
+                    }
+                }
+            }
+        });
+        ready.acquire();
+        try {
+            assertEquals("[hello-ehlo, null, there-ehlo]", Utilities.actionsForPath("stuff", Lookups.fixed(new ContextData("ehlo"))).toString());
+        } finally {
+            done.release();
+        }
+    }
 
     private static class CustomToolkitComponent extends Component {
         private Toolkit customToolkit;
@@ -511,21 +545,34 @@ public class UtilitiesTest extends NbTestCase {
                 return Lookup.EMPTY;
             }
             InstanceContent content = new InstanceContent();
-            InstanceContent.Convertor<String, Action> actionConvertor = new InstanceContent.Convertor<String, Action>() {
 
-                public Action convert(final String obj) {
-                    return new AbstractAction() {
+            class ContextAction extends AbstractAction implements ContextAwareAction {
+                final String obj;
 
-                        public void actionPerformed(ActionEvent e) {
-                        }
+                public ContextAction(String obj) {
+                    this.obj = obj;
+                }
+                
+                public void actionPerformed(ActionEvent e) {
+                }
 
-                        @Override
-                        public String toString() {
-                            return obj;
-                        }
-                    };
+                @Override
+                public String toString() {
+                    return obj;
                 }
 
+                @Override
+                public Action createContextAwareInstance(Lookup actionContext) {
+                    ContextData cd = actionContext.lookup(ContextData.class);
+                    return new ContextAction(obj + (cd == null ? "-ctx" : "-" + cd.suffix));
+                }
+            }
+            
+            InstanceContent.Convertor<String, Action> actionConvertor = new InstanceContent.Convertor<String, Action>() {
+                public Action convert(final String obj) {
+                    return new ContextAction(obj);
+                }
+                
                 public Class<? extends Action> type(String obj) {
                     return AbstractAction.class;
                 }


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@netbeans.apache.org
For additional commands, e-mail: commits-help@netbeans.apache.org

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