Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » Rich Client Platform (RCP) » How to use global actions in a context menu
How to use global actions in a context menu [message #464018] Thu, 22 February 2007 13:14 Go to next message
Marc Schlegel is currently offline Marc SchlegelFriend
Messages: 92
Registered: July 2009
Member
Hi. I am new to the rcp framework but I already like it a lot. At the
moment I am trying to figure out how I can use a global action within a
views context menu (and the view-toolbar). For the menubar this is easy
with the ActionFactory and the methods register and getAction, but in my
view I don't have the method getAction(id) available and I cant get an
IAction from the ActionFactory??

Or am I totaly wrong here?

Thanks in advance
--Marc
Re: How to use global actions in a context menu [message #464043 is a reply to message #464018] Thu, 22 February 2007 18:19 Go to previous messageGo to next message
Paul Webster is currently offline Paul WebsterFriend
Messages: 6859
Registered: July 2009
Location: Ottawa
Senior Member

Some of the global actions are actions that do stuff ... like
SaveAction. As long as that was registered in your ActionBarAdvisor
class, you can use the command id (the action's definition id) to ask
eclipse to execute that command.

For other actions (that are RetargetActions) you need to create an
action to implement the behaviour (for example, the ActionFactory COPY
action doesn't do anything).

Later,
PW


Re: How to use global actions in a context menu [message #464044 is a reply to message #464043] Thu, 22 February 2007 18:40 Go to previous messageGo to next message
Marc Schlegel is currently offline Marc SchlegelFriend
Messages: 92
Registered: July 2009
Member
Thank you for your help

I alreadsy figured out how to use retargetable actions and exactly in
this case (delete-action) I have my problem.

In the menubar I added ActionFactory.DELETE which gives me the text and
a nice icon for the action. In my view I am using

getViewSite().getActionBars().setGlobalActionHandler(ActionF actory.DELETE.toString(),
deleteAction);
and this causes that the displayed action now uses the text and the icon
from my action (where I retargeted the global one). But I just want to
the change the actions behavior (the run()-method) not the look.

I hope I this is not to confusing :-)

Thx again
-- Marc

Paul Webster schrieb:
> Some of the global actions are actions that do stuff ... like
> SaveAction. As long as that was registered in your ActionBarAdvisor
> class, you can use the command id (the action's definition id) to ask
> eclipse to execute that command.
>
> For other actions (that are RetargetActions) you need to create an
> action to implement the behaviour (for example, the ActionFactory COPY
> action doesn't do anything).
>
> Later,
> PW
Re: How to use global actions in a context menu [message #464060 is a reply to message #464044] Fri, 23 February 2007 10:47 Go to previous messageGo to next message
Robert Jaemmrich is currently offline Robert JaemmrichFriend
Messages: 17
Registered: July 2009
Junior Member
> In the menubar I added ActionFactory.DELETE which gives me the text and
> a nice icon for the action. In my view I am using
>
> getViewSite().getActionBars().setGlobalActionHandler(ActionF actory.DELETE.toString(),
> deleteAction);
> and this causes that the displayed action now uses the text and the icon
> from my action (where I retargeted the global one). But I just want to
> the change the actions behavior (the run()-method) not the look.

Same problem here. :-)

As a workaround I am copying those values in the constructor of my Action:

IAction tmpAction=
ActionFactory.DELETE.create(PlatformUI.getWorkbench().getAct iveWorkbenchWindow());
this.setText(tmpAction.getText());
this.setImageDescriptor(tmpAction.getImageDescriptor());

This is not very nice - but It's not only about icons and labels: It's
about languages/i18n too :-/

I'm very interested in a "real" solution too. :-)


Regards,

Robert
Re: How to use global actions in a context menu [message #464074 is a reply to message #464044] Fri, 23 February 2007 16:25 Go to previous messageGo to next message
Paul Webster is currently offline Paul WebsterFriend
Messages: 6859
Registered: July 2009
Location: Ottawa
Senior Member

Marc Schlegel wrote:
> Thank you for your help
>
> I alreadsy figured out how to use retargetable actions and exactly in
> this case (delete-action) I have my problem.
>
> In the menubar I added ActionFactory.DELETE which gives me the text and
> a nice icon for the action. In my view I am using
>
> getViewSite().getActionBars().setGlobalActionHandler(ActionF actory.DELETE.toString(),
> deleteAction);

That should be setGlobalActionHandler(ActionFactory.DELETE.getId(),
deleteAction) ... that tells the retarget action to use your
deleteAction for run().

Later,
PW


Re: How to use global actions in a context menu [message #464123 is a reply to message #464074] Mon, 26 February 2007 10:07 Go to previous messageGo to next message
Marc Schlegel is currently offline Marc SchlegelFriend
Messages: 92
Registered: July 2009
Member
Paul Webster schrieb:
> That should be setGlobalActionHandler(ActionFactory.DELETE.getId(),
> > deleteAction) ... that tells the retarget action to use your
> > deleteAction for run().
> >
> > Later,
> > PW

Thx again, I guess I understand now how this retargetable action things
works. The global Action is used (text, icon) but when called it uses
the run() from MyDeleteAction.

But still I have the problem that I can't add this global action to any
MenuManager because a MenuManager accepts IAction. I cant get an IAction
from the ActionFactory.DELETE (which is again an ActionFactory instance)??

I also tried to get at least the Image for the DELETE-Action from
ImageRegistry. But it seems that the ImageDescriptor for this isn't
stored with actions id. Maybe someone has an idea for this workaround.

best regards
-- Marc
Re: How to use global actions in a context menu [message #464132 is a reply to message #464123] Mon, 26 February 2007 14:24 Go to previous messageGo to next message
Robert Jaemmrich is currently offline Robert JaemmrichFriend
Messages: 17
Registered: July 2009
Junior Member
Marc Schlegel schrieb:
> Thx again, I guess I understand now how this retargetable action things
> works. The global Action is used (text, icon) but when called it uses
> the run() from MyDeleteAction.
>
> But still I have the problem that I can't add this global action to any
> MenuManager because a MenuManager accepts IAction. I cant get an IAction
> from the ActionFactory.DELETE (which is again an ActionFactory instance)??
>
> I also tried to get at least the Image for the DELETE-Action from
> ImageRegistry. But it seems that the ImageDescriptor for this isn't
> stored with actions id. Maybe someone has an idea for this workaround.

Marc -

I just played around with the way Actions are added by the
ActionBarAdvisor:


public class ApplicationActionBarAdvisor extends ActionBarAdvisor {

private IWorkbenchAction deleteAction;

protected void makeActions(IWorkbenchWindow window) {
deleteAction = ActionFactory.DELETE.create(window);
register(deleteAction);
...

In my ViewPart (createPartControl):
....
getViewSite().getActionBars().setGlobalActionHandler(
ActionFactory.DELETE.getId(), myDeleteAction);
....

(myDeleteAction extends Action and implements ISelectionListener)

If you use EXACTLY THIS deleteAction (from makeActions in
ApplicationActionBarAdvisor) for your context menu

private void createPopupMenu() {
MenuManager manager = new MenuManager();
Menu menu = manager.createContextMenu(tableViewer.getControl());
tableViewer.getControl().setMenu(menu);
getSite().registerContextMenu(manager, tableViewer);
manager.setRemoveAllWhenShown(true);
manager.addMenuListener(new IMenuListener() {
public void menuAboutToShow(IMenuManager manager) {
manager.add(deleteAction);
...

then the Action gets shown correctly in the context menu. I think this
"solution" is an ugly workaround too, but not as ugly as trying to
imitate the global delete action.

What do you think?


Regards,

Robert
Re: How to use global actions in a context menu [message #464135 is a reply to message #464132] Mon, 26 February 2007 15:52 Go to previous messageGo to next message
Marc Schlegel is currently offline Marc SchlegelFriend
Messages: 92
Registered: July 2009
Member
> I just played around with the way Actions are added by the
> ActionBarAdvisor:
>
>
> public class ApplicationActionBarAdvisor extends ActionBarAdvisor {
>
> private IWorkbenchAction deleteAction;
>
> protected void makeActions(IWorkbenchWindow window) {
> deleteAction = ActionFactory.DELETE.create(window);
> register(deleteAction);
> ...
>
> In my ViewPart (createPartControl):
> ...
> getViewSite().getActionBars().setGlobalActionHandler(
> ActionFactory.DELETE.getId(), myDeleteAction);
> ...
>
> (myDeleteAction extends Action and implements ISelectionListener)
>
> If you use EXACTLY THIS deleteAction (from makeActions in
> ApplicationActionBarAdvisor) for your context menu

But how can you access exactly this action from your view? In my case
the view is also in another plugin to seperate it from my rcp-plugin.

> private void createPopupMenu() {
> MenuManager manager = new MenuManager();
> Menu menu = manager.createContextMenu(tableViewer.getControl());
> tableViewer.getControl().setMenu(menu);
> getSite().registerContextMenu(manager, tableViewer);
> manager.setRemoveAllWhenShown(true);
> manager.addMenuListener(new IMenuListener() {
> public void menuAboutToShow(IMenuManager manager) {
> manager.add(deleteAction);
> ...
>
> then the Action gets shown correctly in the context menu. I think this
> "solution" is an ugly workaround too, but not as ugly as trying to
> imitate the global delete action.
>
> What do you think?

Doesn't sound bad but I can't get it running...
Re: How to use global actions in a context menu [message #464137 is a reply to message #464135] Mon, 26 February 2007 18:17 Go to previous messageGo to next message
Robert Jaemmrich is currently offline Robert JaemmrichFriend
Messages: 17
Registered: July 2009
Junior Member
Marc Schlegel schrieb:
>> I just played around with the way Actions are added by the
>> ActionBarAdvisor:
>>
>>
>> public class ApplicationActionBarAdvisor extends ActionBarAdvisor {
>>
>> private IWorkbenchAction deleteAction;
>>
>> protected void makeActions(IWorkbenchWindow window) {
>> deleteAction = ActionFactory.DELETE.create(window);
>> register(deleteAction);
>> ...
>>
>> In my ViewPart (createPartControl):
>> ...
>> getViewSite().getActionBars().setGlobalActionHandler(
>> ActionFactory.DELETE.getId(), myDeleteAction);
>> ...
>>
>> (myDeleteAction extends Action and implements ISelectionListener)
>>
>> If you use EXACTLY THIS deleteAction (from makeActions in
>> ApplicationActionBarAdvisor) for your context menu
>
> But how can you access exactly this action from your view? In my case
> the view is also in another plugin to seperate it from my rcp-plugin.

OK, you asked - here is my dirty hack:

1. When I create the delete action in the ApplicationActionBarAdvisor, I
store it in a field of the Activator:

public class ApplicationActionBarAdvisor extends ActionBarAdvisor {
private IWorkbenchAction deleteAction;
protected void makeActions(IWorkbenchWindow window) {
deleteAction = ActionFactory.DELETE.create(window);
register(deleteAction);
Activator.getDefault().setDeleteAction(deleteAction);
...

public class Activator extends AbstractUIPlugin {
private IWorkbenchAction deleteAction;

public IWorkbenchAction getDeleteAction() {
return deleteAction;
}

public void setDeleteAction(IWorkbenchAction deleteAction) {
this.deleteAction = deleteAction;
}
...

2. To get the action you have to define a dependency: The view plugin
has to be dependent of the RCP plugin. Then you can access it from your
view like this:

public class MyView extends ViewPart {
public void createPartControl(final Composite parent) {
...
createPopupMenu();
...
}

private void createPopupMenu() {
MenuManager manager = new MenuManager();
Menu menu = manager.createContextMenu(tableViewer.getControl());
tableViewer.getControl().setMenu(menu);
getSite().registerContextMenu(manager, tableViewer);
manager.setRemoveAllWhenShown(true);
manager.addMenuListener(new IMenuListener() {
public void menuAboutToShow(IMenuManager manager) {
manager.add(myDeleteAction);
manager.add(my.rcp.Activator
.getDefault().getDeleteAction());
}
});
}
...

The evil thing is the new dependency I have to define. :-(

Maybe there is a better way using extension points, but unfortunatly I
don't know anything about creating extension points up to now.


HTH

Robert
Re: How to use global actions in a context menu [message #464145 is a reply to message #464137] Mon, 26 February 2007 20:04 Go to previous messageGo to next message
Marc Schlegel is currently offline Marc SchlegelFriend
Messages: 92
Registered: July 2009
Member
Robert, thank you very much for your help..it works just fine.

I added a private class (ActionRegistry) in my RcpPlugin (the Activator)
where I store all this global actions in a HashMap.

I analysed some plugins, and a lot of them are using their own
DeleteActions in the ContextMenu. If you have a look at the Quantum DB
plugin (source) you can see that they also used kind of a ActionRegistry
for the same purpose.

Maybe there will be a more sophisticated solution in the next Eclipse
release (or there is one already but we just didn't see it :-) ). The
Platform must store the actions somewhere (remember the register-method)
and it would be nice to access this Registry directly with a simple id.

------------------------------------------------------------ ---
Here is my Solution:

RcpPlugin extends AbstractUIplugin

.....

public IWorkbenchAction getActionFromRegistry(String id){
return actionRegistry.getAction(id);
}

/**
* Adds an <code>IWorkbenchAction</code> to a Registry.
* Note: this method should only be used by the
<code>ApplicationActionBarAdvisor</code>
* @param id - for excample ActionFactory.DELETE.getId()
* @param action
*/
public void addActionToRegistry(String id, IWorkbenchAction action){
actionRegistry.addAction(id, action);
}

/**
* This class stores global actions (<code>IWorkbenchAction</code>) to be
able use them
* in later MenuManagers (views and editors)
* @author Marc Schlegel
*/
private class ActionRegistry {
private Map <String, IWorkbenchAction>registry = new HashMap<String,
IWorkbenchAction>();

protected IWorkbenchAction getAction(String id){
return registry.get(id);
}

protected void addAction(String id, IWorkbenchAction action){
registry.put(id, action);
}
}// end (local) class

}
------------------------------------------------------------ ---

Best regards
-- Marc
Re: How to use global actions in a context menu [message #464200 is a reply to message #464145] Tue, 27 February 2007 11:20 Go to previous messageGo to next message
Eclipse UserFriend
Originally posted by: 11235813.despammed.com

Marc Schlegel schrieb:
> Robert, thank you very much for your help..it works just fine.
>
> I added a private class (ActionRegistry) in my RcpPlugin (the Activator)
> where I store all this global actions in a HashMap.

Thanks for your solution.

A few days ago, when I was faced with the same problem, I tried 2
similar approaches: One was to create the actions as Singletons and to
ask for the single instance (doing well, but not very elegant), the
other one was very similar to yours. I added a public function
getGlobalAction(String actionId) to the ApplicationActionBarAdvisor
class, which returns the action with the given id:

public class ApplicationActionBarAdvisor extends ActionBarAdvisor {

private static ApplicationActionBarAdvisor advisor = null;

public ApplicationActionBarAdvisor(IActionBarConfigurer configurer) {
super(configurer);
advisor = this;
}

public static IAction getGlobalAction(String actionId) {
if (advisor != null)
return getAction(actionId);
return null;
}
}

Ok, I have a singleton, too, but now the singleton is the advisor, not
each of the actions. The advisor 'knows' all of the registered actions
via getAction(...). My own actions are declared and created the way the
ActionFactory does it (MyActionFactory), so I can use
MyActionFactory.EXAMPLEACTION.getId() everywhere in the plugin to get
the id of one of my own actions.

Can someone with more experience give me some feedback about this
solution? The solution is doing well, but IMHO it's not the Eclipse-way :-)

>
> Maybe there will be a more sophisticated solution in the next Eclipse
> release (or there is one already but we just didn't see it :-) ).

I really hope so, too.

> The
> Platform must store the actions somewhere (remember the register-method)
> and it would be nice to access this Registry directly with a simple id.

Yes. The platform stores the values in the actions field of the
ActionAdvisor. But the access is protected.


Regards,

Carmen
Re: How to use global actions in a context menu [message #677771 is a reply to message #464200] Thu, 09 June 2011 10:54 Go to previous messageGo to next message
Kazimir Hruska is currently offline Kazimir HruskaFriend
Messages: 5
Registered: September 2010
Junior Member
>>> duplicate removed <<<

[Updated on: Thu, 09 June 2011 11:15]

Report message to a moderator

Re: How to use global actions in a context menu [message #677775 is a reply to message #464018] Thu, 09 June 2011 11:05 Go to previous message
Kazimir Hruska is currently offline Kazimir HruskaFriend
Messages: 5
Registered: September 2010
Junior Member
Hi all,
I've been playing with access to global actions from plugin and here is the solution (it is for "Select All" action):

First, the action needs to be created (in ActionBarAdvisor instance):
register(ActionFactory.SELECT_ALL.create(window));


Then to handle the action in my view (in WorkBenchPart#createPartControl(Composite)):
getViewSite().getActionBars().setGlobalActionHandler(ActionFactory.SELECT_ALL.getId(), new Action() {
            @Override
            public void run() {
                selectAll();
            }
        });


And finally to add the global action to the context menu:
menuManager.add(new CommandContributionItem(
                    new CommandContributionItemParameter(
                            getViewSite().getActionBars().getServiceLocator(),
                            ActionFactory.SELECT_ALL.getId(),
                            ActionFactory.SELECT_ALL.getCommandId(),
                            CommandContributionItem.STYLE_PUSH)
                    )
            );


Pretty obvious, like all of RCP... Wink
Previous Topic:adding the project explorer to a perspective
Next Topic:Don't understand Eclipse - MVC, yet
Goto Forum:
  


Current Time: Sun Dec 21 22:15:35 GMT 2014

Powered by FUDForum. Page generated in 0.04712 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software