NetBeans Forums

 FAQFAQ   SearchSearch   MemberlistMemberlist   RegisterRegister   ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 
  

Submenu in a nodes context menu with @ActionReference.path

 
Post new topic   Reply to topic    NetBeans Forums -> NetBeans Platform Users
View previous topic :: View next topic  
Author Message
funfried



Joined: 08 Sep 2010
Posts: 14

PostPosted: Mon Sep 19, 2011 1:54 pm    Post subject: Submenu in a nodes context menu with @ActionReference.path Reply with quote

Hi all,

I'm trying to put some Actions of a Node inside a submenu of a Nodes context menu, here is my Node:

Code:

public class MyNode extends AbstractFavoritesNode
{
   public MyNode(AbstractNavigationItem item)
   {
      super(item);
   }

   /**
    * {@inheritDoc}
    */
   @Override
   public Action[] getActions(boolean context)
   {
      String[] paths =
      {
         "MyNode/General/Actions", "MyNode/Local/Actions"
      };

      return createActions(context, paths);
   }

   protected Action[] createActions(boolean context, String... paths)
   {
      ArrayList<Action> actions = new ArrayList<Action>();
      for(String path : paths)
      {
         List<? extends Action> actionsForPath = Utilities.actionsForPath(path);
         actions.addAll(actionsForPath);
      }

      List<Action> parent = Arrays.asList(super.getActions(context));
      actions.addAll(parent);

      return actions.toArray(new Action[actions.size()]);
   }
}


As you can see I'm fetching the Actions based on their ActionReference path, because MyNode is inside a module where NOT the Actions are and some of those Actions are used more than once, so in my opinion that was the best way to implement this (If someone has a better idea, please let me know Wink )

So here is one of my Actions:

Code:

@ActionID(id = "com.my.package.actions.MyAction", category = "MyNode/General")
@ActionRegistration(displayName = "MyAction.name")
@ActionReference(path = "MyNode/General/Actions", position = 500)
public class MyAction extends AbstractAction implements ContextAwareAction
{
   private MyDevice myDevice;

   public MyAction()
   {
      super(NbBundle.getMessage(MyAction.class, "MyAction.name"));
   }

   public MyAction(MyDevice myDevice)
   {
      this();
      this.myDevice = myDevice;
   }

   @Override
   public void actionPerformed(ActionEvent e)
   {
      this.myDevice.connect();
   }

   @Override
   public Action createContextAwareInstance(Lookup actionContext)
   {
      MyDevice dev = actionContext.lookup(MyDevice.class);
      Action action = new MyAction(dev);
      action.setEnabled(lkp.isConnected());

      return action;
   }
}


So far so good, everything is just working fine as long as I don't use submenus, because I have no idea how I possibly could get a submenu there. The only thing I found about submenus in context menus is this:

http://platform.netbeans.org/tutorials/nbm-nodesapi2.html#action-presenters

But the problem is that I can't and don't want to reference my Actions directly in another Action (Presenter.Popup), I tried to do it like in other System Menus (e. g. Menu/Edit) and just added another folder in my ActionReference path, but it seems to be not that easy, in that way it seems it is just working with system menus Sad

Any Idea how to solve this? How can I get submenus with ActionReference paths that are non system paths?


Thanks in advance.

Kind regards,
Fabian


Last edited by funfried on Tue Sep 20, 2011 9:29 am; edited 1 time in total
Back to top
Jonathan Spooner
Posted via mailing list.





PostPosted: Tue Sep 20, 2011 4:51 am    Post subject: [platform-dev] Re: Submenu in a nodes context menu with @ActionReference.path Reply with quote

funfried,

While I have not used the new annotations for action registration that
are available in NB 7.0, I can tell you that action registration in the
layer is hierarchical. So if I have an action called MyAction which is
located at Actions/MyNode/MyAction my sub-menu action, called
MySubAction, would be located at Actions/MyNode/MyAction/MySubAction.
Because MySubAction is a child of the MyAction it would be represented
in a menu as a sub-menu.

On 9/19/2011 6:54 AM, funfried wrote:
Quote:
Hi all,

I'm trying to put some Actions of a Node inside a submenu of a Nodes context menu, here is my Node:


Code:

public class MyNode extends AbstractFavoritesNode
{
public InfomanNode(AbstractNavigationItem item)
{
super(item);
}

/**
* {@inheritDoc}
*/
@Override
public Action[] getActions(boolean context)
{
String[] paths =
{
"MyNode/General/Actions", "MyNode/Local/Actions"
};

return createActions(context, paths);
}

protected Action[] createActions(boolean context, String... paths)
{
ArrayList<Action> actions = new ArrayList<Action>();
for(String path : paths)
{
List<? extends Action> actionsForPath = Utilities.actionsForPath(path);
actions.addAll(actionsForPath);
}

List<Action> parent = Arrays.asList(super.getActions(context));
actions.addAll(parent);

return actions.toArray(new Action[actions.size()]);
}
}




As you can see I'm fetching the Actions based on their ActionReference path, because MyNode is inside a module where NOT the Actions are and some of those Actions are used more than once, so in my opinion that was the best way to implement this (If someone has a better idea, please let me know [Wink] )

So here is one of my Actions:


Code:

@ActionID(id = "com.my.package.actions.MyAction", category = "MyNode/General")
@ActionRegistration(displayName = "MyAction.name")
@ActionReference(path = "MyNode/General/Actions", position = 500)
public class MyAction extends AbstractAction implements ContextAwareAction
{
private MyDevice myDevice;

public MyAction()
{
super(NbBundle.getMessage(MyAction.class, "MyAction.name"));
}

public MyAction(MyDevice myDevice)
{
this();
this.myDevice = myDevice;
}

@Override
public void actionPerformed(ActionEvent e)
{
this.myDevice.connect();
}

@Override
public Action createContextAwareInstance(Lookup actionContext)
{
MyDevice dev = actionContext.lookup(MyDevice.class);
Action action = new MyAction(dev);
action.setEnabled(lkp.isConnected());

return action;
}
}




So far so good, everything is just working fine as long as I don't use submenus, because I have no idea how I possibly could get a submenu there. The only thing I found about submenus in context menus is this:

http://platform.netbeans.org/tutorials/nbm-nodesapi2.html#action-presenters

But the problem is that I can't and don't want to reference my Actions directly in another Action (Presenter.Popup), I tried to do it like in other System Menus (e. g. Menu/Edit) and just added another folder in my ActionReference path, but it seems to be not that easy, in that way it seems it is just working with system menus :(

Any Idea how to solve this? How can I get submenus with ActionReference paths that are non system paths?


Thanks in advance.

Kind regards,
Fabian





--
Jonathan Spooner
address-removed
Back to top
funfried



Joined: 08 Sep 2010
Posts: 14

PostPosted: Tue Sep 20, 2011 11:02 am    Post subject: Re: [platform-dev] Re: Submenu in a nodes context menu with @ActionReference.path Reply with quote

Hi Jonathan,

first of all, thanks for your answer!

I tried the following:

The sub menu item action annotations:

@ActionID(id = "com.my.package.actions.MyAction", category = "MyNode/General")
@ActionRegistration(displayName = "MyAction.name")
@ActionReference(path = "MyNode/General/Actions/SubMenuAction/MyAction", position = 500)

The sub menu annotations:

@ActionID(id = "com.my.package.actions.SubMenuAction", category = "MyNode/General")
@ActionRegistration(displayName = "SubMenuAction.name")
@ActionReference(path = "MyNode/General/Actions/SubMenuAction", position = 400)

The strange thing is, the generated-layer.xml of the module's jar file seems to be correct, but the items are shown next to each other in the sub menu:

Code:

    <folder name="Actions">
        <folder name="MyNode">
            <folder name="General">
                <folder name="Actions">
                    <folder name="SubMenuAction">
                        <file name="com-my-package-actions-MyAction.instance">
                            <attr name="displayName" stringvalue="MyAction.name"/>
                            <attr name="instanceCreate" newvalue="com.my.package.actions.MyAction"/>
                        </file>
                    </folder>
                    <file name="com-my-package-actions-SubMenuAction.instance">
                        <attr name="displayName" stringvalue="SubMenuAction.name"/>
                        <attr name="instanceCreate" newvalue="com.my.package.actions.SubMenuAction"/>
                    </file>
                </folder>
            </folder>
        </folder>
    </folder>


Maybe the way of creating / fetching the actions inside the node isn't correct?

Code:

   /**
    * {@inheritDoc}
    */
   @Override
   public Action[] getActions(boolean context)
   {
      String[] paths =
      {
         "MyNode/General/Actions", "MyNode/Local/Actions"
      };

      return createActions(context, paths);
   }

   protected Action[] createActions(boolean context, String... paths)
   {
      ArrayList<Action> actions = new ArrayList<Action>();
      for(String path : paths)
      {
         List<? extends Action> actionsForPath = Utilities.actionsForPath(path);
         actions.addAll(actionsForPath);
      }

      List<Action> parent = Arrays.asList(super.getActions(context));
      actions.addAll(parent);

      return actions.toArray(new Action[actions.size()]);
   }


Jonathan Spooner wrote:
funfried,

While I have not used the new annotations for action registration that
are available in NB 7.0, I can tell you that action registration in the
layer is hierarchical. So if I have an action called MyAction which is
located at Actions/MyNode/MyAction my sub-menu action, called
MySubAction, would be located at Actions/MyNode/MyAction/MySubAction.
Because MySubAction is a child of the MyAction it would be represented
in a menu as a sub-menu.

--
Jonathan Spooner
address-removed
Back to top
Jonathan Spooner
Posted via mailing list.





PostPosted: Wed Sep 21, 2011 5:31 am    Post subject: [platform-dev] Re: Submenu in a nodes context menu with @ActionReference.path Reply with quote

funfried,

I find that in time like these, when things aren't working as you
expect, that it's helpful to go down one layer of abstraction and try
and figure it out there. The abstraction in question is the JMenu and
how you would build a sub-menu[1].

So, to build a sub-menu really means to have two actions at the same
hierarchy. In this case your paths would look something like:

Actions/MyNode/MySubmenu/MyAction1
and
Actions/MyNode/MySubmenu/MyAction2

and you would build the rest of your actions like this:

Actions/MyNode/MyOtherAction
Actions/MyNode/SomeThingElse
...

So, MySubmenu _wouldn't_ be an action, only a path where two actions reside.


[1] http://download.oracle.com/javase/tutorial/uiswing/components/menu.html

On 9/20/2011 4:02 AM, funfried wrote:
Quote:
Hi Jonathan,

first of all, thanks for your answer!

I tried the following:

The sub menu item action annotations:

@ActionID(id = "com.my.package.actions.MyAction", category = "MyNode/General")
@ActionRegistration(displayName = "MyAction.name")
@ActionReference(path = "MyNode/General/Actions/SubMenuAction/MyAction", position = 500)

The sub menu annotations:

@ActionID(id = "com.my.package.actions.SubMenuAction", category = "MyNode/General")
@ActionRegistration(displayName = "SubMenuAction.name")
@ActionReference(path = "MyNode/General/Actions/SubMenuAction", position = 400)

The strange thing is, the generated-layer.xml of the module's jar file seems to be correct, but the items are shown next to each other in the sub menu:


Code:

<folder name="Actions">
<folder name="MyNode">
<folder name="General">
<folder name="Actions">
<folder name="SubMenuAction">
<file name="com-my-package-actions-MyAction.instance">
<attr name="displayName" stringvalue="MyAction.name"/>
<attr name="instanceCreate" newvalue="com.my.package.actions.MyAction"/>
</file>
</folder>
<file name="com-my-package-actions-SubMenuAction.instance">
<attr name="displayName" stringvalue="SubMenuAction.name"/>
<attr name="instanceCreate" newvalue="com.my.package.actions.SubMenuAction"/>
</file>
</folder>
</folder>
</folder>
</folder>



Maybe the way of creating / fetching the actions inside the node isn't correct?


Code:

/**
* {@inheritDoc}
*/
@Override
public Action[] getActions(boolean context)
{
String[] paths =
{
"MyNode/General/Actions", "MyNode/Local/Actions"
};

return createActions(context, paths);
}

protected Action[] createActions(boolean context, String... paths)
{
ArrayList<Action> actions = new ArrayList<Action>();
for(String path : paths)
{
List<? extends Action> actionsForPath = Utilities.actionsForPath(path);
actions.addAll(actionsForPath);
}

List<Action> parent = Arrays.asList(super.getActions(context));
actions.addAll(parent);

return actions.toArray(new Action[actions.size()]);
}





Jonathan Spooner wrote:
Quote:
funfried,

While I have not used the new annotations for action registration that
are available in NB 7.0, I can tell you that action registration in the
layer is hierarchical. So if I have an action called MyAction which is
located at Actions/MyNode/MyAction my sub-menu action, called
MySubAction, would be located at Actions/MyNode/MyAction/MySubAction.
Because MySubAction is a child of the MyAction it would be represented
in a menu as a sub-menu.

--
Jonathan Spooner
address-removed






--
Jonathan Spooner
address-removed
Back to top
funfried



Joined: 08 Sep 2010
Posts: 14

PostPosted: Thu Sep 22, 2011 8:37 am    Post subject: Re: [platform-dev] Re: Submenu in a nodes context menu with @ActionReference.path Reply with quote

Hi Jonathan,

and again thanks for answering!

I think your suggestion to go down one layer is not a bad idea, but in my case (and in my opinion) the problem isn't swing, the problem is how to create a sub menus in NetBeans RCP with the available annotations.

However, I followed your suggestions regarding the paths and still no chance, so I made a simple NetBeans Platform project (see attachment) where I did the same as in my real project and it is also not working (what a surprise Wink ), but hopefully someone sees what I'm doing wrong there. Any help is very appreciated.

Thanks in advance.

Regards,
Fabian


//EDIT:

Forgot to explain the project a bit:

There are 4 actions in sum in the project, two of them (MyFirstAction and MySecondAction) are NOT in a submenu, the other two actions (MyFirstSubAction and MySecondSubAction) aren't in a submenu either, but they should, their ActionReference.path annotation has a "sub path" (../SubMenu/My...) in it, as far as I understood the NetBeans RCP that should be enough to create a submenu, isn't it? And the class MyNode fetches those actions in its getActions(boolean) method. I think that's it everything else is just to have a running application.


Jonathan Spooner wrote:
funfried,

I find that in time like these, when things aren't working as you
expect, that it's helpful to go down one layer of abstraction and try
and figure it out there. The abstraction in question is the JMenu and
how you would build a sub-menu[1].

So, to build a sub-menu really means to have two actions at the same
hierarchy. In this case your paths would look something like:

Actions/MyNode/MySubmenu/MyAction1
and
Actions/MyNode/MySubmenu/MyAction2

and you would build the rest of your actions like this:

Actions/MyNode/MyOtherAction
Actions/MyNode/SomeThingElse
...

So, MySubmenu _wouldn't_ be an action, only a path where two actions reside.


[1] http://download.oracle.com/javase/tutorial/uiswing/components/menu.html



--
Jonathan Spooner
address-removed[/quote]



SubMenuForNodes.zip
 Description:

Download
 Filename:  SubMenuForNodes.zip
 Filesize:  22.16 KB
 Downloaded:  63 Time(s)

Back to top
Jonathan Spooner
Posted via mailing list.





PostPosted: Thu Sep 22, 2011 7:34 pm    Post subject: [platform-dev] Re: Submenu in a nodes context menu with @ActionReference.path Reply with quote

funfried,

Well, I must admit after thinking about this I can't recall ever putting
a sub-menu into a node's context menu. I _will_ look at this tomorrow
and see if I can help point you in the right direction.

On 9/22/2011 1:38 AM, funfried wrote:
Quote:
Hi Jonathan,

and again thanks for answering!

I think your suggestion to go down one layer is not a bad idea, but in my case (and in my opinion) the problem isn't swing, the problem is how to create a sub menus in NetBeans RCP with the available annotations.

However, I followed your suggestions regarding the paths and still no chance, so I made a simple NetBeans Platform project (see attachment) where I did the same as in my real project and it is also not working (what a surprise [Wink] ), but hopefully someone sees what I'm doing wrong there. Any help is very appreciated.

Thanks in advance.

Regards,
Fabian



Jonathan Spooner wrote:
Quote:
funfried,

I find that in time like these, when things aren't working as you
expect, that it's helpful to go down one layer of abstraction and try
and figure it out there. The abstraction in question is the JMenu and
how you would build a sub-menu[1].

So, to build a sub-menu really means to have two actions at the same
hierarchy. In this case your paths would look something like:

Actions/MyNode/MySubmenu/MyAction1
and
Actions/MyNode/MySubmenu/MyAction2

and you would build the rest of your actions like this:

Actions/MyNode/MyOtherAction
Actions/MyNode/SomeThingElse
...

So, MySubmenu _wouldn't_ be an action, only a path where two actions reside.


[1] http://download.oracle.com/javase/tutorial/uiswing/components/menu.html





--
Jonathan Spooner
address-removed
Back to top
funfried



Joined: 08 Sep 2010
Posts: 14

PostPosted: Thu Sep 22, 2011 7:53 pm    Post subject: Re: [platform-dev] Re: Submenu in a nodes context menu with @ActionReference.path Reply with quote

That's very kind of you, thank you very much!!!

It's really making me crazy, I have no idea what I could try anymore.

I'm looking forward hearing from you tomorrow.


Regards,
Fabian

Jonathan Spooner wrote:
funfried,

Well, I must admit after thinking about this I can't recall ever putting
a sub-menu into a node's context menu. I _will_ look at this tomorrow
and see if I can help point you in the right direction.

--
Jonathan Spooner
address-removed
Back to top
funfried



Joined: 08 Sep 2010
Posts: 14

PostPosted: Mon Sep 26, 2011 10:26 am    Post subject: Re: [platform-dev] Re: Submenu in a nodes context menu with @ActionReference.path Reply with quote

Hi Jonathan,

again, thanks a lot, but I now those tutorials and I already tried this and of course it works, but unfortunately it doesn't solve my problem.

I made another NetBeans Platform project which makes my problem more clearer (at least I hope so). The problem is, that my actions are in more than one module and also the actions that belong to one sub menu are in more than one module and those modules don't know each other so I can't instantiate them in any module within a Presenter.Popup class, so those "sub actions" should also be build by any lookup mechanism like the menu itself (see MyNode.getActions(boolean)).

Regards,
Fabian

Jonathan Spooner wrote:

(I sent this to the forum but since it didn't show up online I'm resending it to your address.)

Fabian,

Okay Fabian, I got it working with the help of a link[1] to a section of a tutorial and a little persistence (thanks to Tom Wheeler for the
link). I've included an attachment with the SubMenuForNodes suite
project which has a new class de.funfried.submenu.actions.SubMenuAction
which implements the necessary functionality.

The section of the tutorial teaches you how to use a Presenter.Popup[2]
to add the sub-menu (and is useful for adding custom components to the
toolbar as well). If you need any more help, don't hesitate to ask.

[1]
http://platform.netbeans.org/tutorials/nbm-nodesapi2.html#action-presenters

[2]
http://bits.netbeans.org/dev/javadoc/org-openide-util/org/openide/util/actions/Presenter.Menu.html

--
Jonathan Spooner
address-removed



SubMenuForNodes.zip
 Description:

Download
 Filename:  SubMenuForNodes.zip
 Filesize:  54.78 KB
 Downloaded:  61 Time(s)

Back to top
funfried



Joined: 08 Sep 2010
Posts: 14

PostPosted: Tue Sep 27, 2011 9:26 am    Post subject: Re: [platform-dev] Re: Submenu in a nodes context menu with @ActionReference.path Reply with quote

Hi Jonathan,

yes, I already did something like this, but this seems to me as a workaround and not really a solution, and a workaround means often a bug, so the question is, is there a better solution and if not is there a bug inside the platform?


Regards,
Fabian


Jonathan Spooner wrote:

(I sent this to the forum but since it didn't show up online I'm resending it to your address.)

Fabian,

You can still do this using the Presenter.Popup interface. The thing that has to change is that you need to register your sub-menu actions outside of the MyNode path so the Utilities.actionsForPath() inside your node doesn't pick up the sub-menu actions. Then in your SubMenuAction use Utilities.actionsForPath() to lookup the sub-menu path. I've included the working example you sent with these adjustments.

It's not the cleanest solution but this will at least get you moving forward. If anyone else has a better solution please let us know.
--
Jonathan Spooner
address-removed
Back to top
Jonathan Spooner
Posted via mailing list.





PostPosted: Tue Sep 27, 2011 11:49 pm    Post subject: [platform-dev] Re: Submenu in a nodes context menu with @ActionReference.path Reply with quote

Fabian,

I thought as much. You could spend some time trying to see how the NB
menu does this. If you decide to do this the menu is located in the
Core - Windows module (core.windows) and the class is
org.openide.awt.MenuBar.

Sorry I couldn't be any more help.

On 9/27/2011 2:27 AM, funfried wrote:
Quote:
Hi Jonathan,

yes, I already did something like this, but this seems to me as a workaround and not really a solution, and a workaround means often a bug, so the question is, is there a better solution and if not is there a bug inside the platform?


Regards,
Fabian



Jonathan Spooner wrote:
Quote:

(I sent this to the forum but since it didn't show up online I'm resending it to your address.)

Fabian,

You can still do this using the Presenter.Popup interface. The thing that has to change is that you need to register your sub-menu actions outside of the MyNode path so the Utilities.actionsForPath() inside your node doesn't pick up the sub-menu actions. Then in your SubMenuAction use Utilities.actionsForPath() to lookup the sub-menu path. I've included the working example you sent with these adjustments.

It's not the cleanest solution but this will at least get you moving forward. If anyone else has a better solution please let us know.
--
Jonathan Spooner
address-removed






--
Jonathan Spooner
address-removed
Back to top
funfried



Joined: 08 Sep 2010
Posts: 14

PostPosted: Wed Sep 28, 2011 8:58 am    Post subject: Re: [platform-dev] Re: Submenu in a nodes context menu with @ActionReference.path Reply with quote

Hi Jonathan,

you we're the only help I got so far, so thanks a lot for all your effort in this!

Thanks for the tip with NetBeans, I also tried this, but wasn't sure where the menu is build, so I will try to find out how they do it. If I find what I need, I'll post again here, maybe someone else has the same problem as me.

So thanks again for all your help!

Regards,
Fabian

Jonathan Spooner wrote:
Fabian,

I thought as much. You could spend some time trying to see how the NB
menu does this. If you decide to do this the menu is located in the
Core - Windows module (core.windows) and the class is
org.openide.awt.MenuBar.

Sorry I couldn't be any more help.

--
Jonathan Spooner
address-removed
Back to top
funfried



Joined: 08 Sep 2010
Posts: 14

PostPosted: Wed Sep 28, 2011 2:33 pm    Post subject: My solution so far ... Reply with quote

Well, I've got a solution, I'm not sure if it is the best available for that problem, but it seems to me the best solution which is currently possible with NetBeans 7.0.1 (if not, please tell me!!!)

Let's begin with the actions for the submenus:

e.g. AnotherSubAction.class:

Code:

@ActionID(category = "MyNode/AnotherSubMenu", id = "de.funfried.anothermodule.actions.AnotherSubAction")
@ActionRegistration(displayName = "#CTL_AnotherSubAction")
@ActionReference(path = "MyNode/AnotherSubMenu/AnotherSubAction", position=10)
public final class AnotherSubAction implements ActionListener
{
   @Override
   public void actionPerformed(ActionEvent e)
   {
      // do something ...
   }
}


Nothing special here, just a normal Action, but I found out that it's important that the path has to start with the category (category = MyNode/AnotherSubMenu so the ActionReference.path has to be MyNode/AnotherSubMenu/...), otherwise you'll see this item twice in your submenu or menu. I have absolutely no clue why (If someone knows why, or knows that this is a bug, please tell me! I couldn't find any explanation for ActionID.category. For what is this? Does anybody know?)

Ok, now let's have a look at the SubMenuAction:

e. g. AnotherSubMenuAction.class:

Code:

@ActionID(category = "MyNode", id = "de.funfried.anothermodule.actions.AnotherSubMenuAction")
@ActionRegistration(displayName = "CTL_AnotherSubMenuAction")
@ActionReference(path = "MyNode/AnotherSubMenuAction", position = 100)
public class AnotherSubMenuAction extends AbstractAction implements Presenter.Popup
{
   public AnotherSubMenuAction()
   {
      super(NbBundle.getMessage(AnotherSubMenuAction.class, "CTL_AnotherSubMenuAction"));
   }

   @Override
   public void actionPerformed(ActionEvent e)
   {
      // this = submenu => do nothing
   }

   @Override
   public JMenuItem getPopupPresenter()
   {
      JMenu menu = new JMenu(this);

      List<? extends Action> actionsForPath = Utilities.actionsForPath("Actions/MyNode/AnotherSubMenu");
      for(Action a : actionsForPath)
      {
         menu.add(a);
      }

      return menu;
   }
}


Here it's also just a normal Action which implements Presenter.Popup, also nothing special, you can see this in a lot tutorials, maybe one thing, I'll fetch here the actions for the ActionReference.path "Actions/MyNode/AnotherSubMenu", every action we want to have in this submenu has to start with this path, see AnotherSubAction.class above.


So here comes the trick, let's have a look at the Node:

MyNode.class:

Code:

public class MyNode extends AbstractNode
{
   [...]

   /**
    * {@inheritDoc}
    */
   @Override
   public Action[] getActions(boolean context)
   {
      return this.createActions(context, "Actions/MyNode");
   }

   /**
    * Retrieves actions from the given paths.
    *
    * @param context Action context sensitivity
    * @param paths Action paths
    * @return All found actions from the given paths
    */
   protected Action[] createActions(boolean context, String... paths)
   {
      ArrayList<Action> subActions = new ArrayList<Action>();
      ArrayList<Action> actions = new ArrayList<Action>();
      for(String path : paths)
      {
         List<? extends Action> actionsForPath = Utilities.actionsForPath(path);
         for(Action a : actionsForPath)
         {
            if(a instanceof Presenter.Popup)
            {
               List<Action> presenterActions = this.findSubActions((Presenter.Popup) a);
               if(!presenterActions.isEmpty())
               {
                  subActions.addAll(presenterActions);
               }
               else
               {
                  continue;
               }
            }

            actions.add(a);
         }
      }

      List<Action> parent = Arrays.asList(super.getActions(context));
      actions.addAll(parent);

      // remove all actions that are already in a submenu
      actions.removeAll(subActions);
      
      return actions.toArray(new Action[actions.size()]);
   }

   private List<Action> findSubActions(Presenter.Popup subMenu)
   {
      List<Action> actions = new ArrayList<Action>();

      JMenuItem item = subMenu.getPopupPresenter();
      if(item instanceof JMenu)
      {
         JMenu menu = (JMenu) item;
         for(int i = 0; i < menu.getItemCount(); i++)
         {
            Action a = menu.getItem(i).getAction();
            actions.add(a);

            if(a instanceof Presenter.Popup)
            {
               actions.addAll(this.findSubActions((Presenter.Popup) a));
            }
         }
      }

      return actions;
   }
}


So I fetch all action in the ActionReference.path "Actions/MyNode", which includes also the actions of the submenu items, but if I have a Presenter.Popup instance, I remember the actions which are returned by getPopupPresenter() (more or less they aren't action but MenuItems, but look at the code) recursive and remove them for all actions I've found, so I can ensure that nothing will be shown twice. And another advantage of this solution is, if the sub menu action isn't in the same module as one of its child actions, the child action will be shown in the top layer of the context menu instead of the sub menu, but it won't be lost. And the other way round, if there are no entries for a submenu it won't be added to the actions.

In the attachment you'll find the mentioned classes and some others as an example NetBeans Platform project.

So that was my solution for this problem, if someone has a better one, please let me know!

Hope that will help other users, too.


And again, thanks for your help Jonathan.

Regards,
Fabian



SubMenuForNodes.zip
 Description:

Download
 Filename:  SubMenuForNodes.zip
 Filesize:  32.6 KB
 Downloaded:  81 Time(s)

Back to top
Display posts from previous:   
Post new topic   Reply to topic    NetBeans Forums -> NetBeans Platform Users All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Powered by phpBB
By use of this website, you agree to the NetBeans Policies and Terms of Use. © 2012, Oracle Corporation and/or its affiliates. Sponsored by Oracle logo