diff --git a/docs/Menu_Contributions.md b/docs/Menu_Contributions.md index 70329bc6537..721bd97043a 100644 --- a/docs/Menu_Contributions.md +++ b/docs/Menu_Contributions.md @@ -40,19 +40,19 @@ A (hopefully) growing list of menu contribution examples. | Example | comments | | --- | --- | -| [Menu Contributions/Dropdown Command](/Menu_Contributions/Dropdown_Command "Menu Contributions/Dropdown Command") | Dropdown tool items can have their menus filled in using menu contributions | -| [Menu Contributions/Problems View Example](/Menu_Contributions/Problems_View_Example "Menu Contributions/Problems View Example") | An example showing how the Problems View might be converted | -| [Menu Contributions/Populating a dynamic submenu](/Menu_Contributions/Populating_a_dynamic_submenu "Menu Contributions/Populating a dynamic submenu") | A menu contribution to populate a Problems View dynamic submenu | -| [Menu Contributions/Toggle Mark Occurrences](/Menu_Contributions/Toggle_Mark_Occurrences "Menu Contributions/Toggle Mark Occurrences") | Placing the toggle mark occurrences button | -| [Menu Contributions/Toggle Button Command](/Menu_Contributions/Toggle_Button_Command "Menu Contributions/Toggle Button Command") | Contribute a toggle state menu item thru commands | -| [Menu Contributions/Radio Button Command](/Menu_Contributions/Radio_Button_Command "Menu Contributions/Radio Button Command") | Similar to updating toggle state, you can create radio buttons using menu contributions | -| [Menu Contributions/Update checked state](/Menu_Contributions/Update_checked_state "Menu Contributions/Update checked state") | The active handler can update the checked state (and other attributes) of its button | -| [Menu Contributions/Search Menu](/Menu_Contributions/Search_Menu "Menu Contributions/Search Menu") | Adding the Java Search options to the Search menu | -| [Menu Contributions/IFile objectContribution](/Menu_Contributions/IFile_objectContribution "Menu Contributions/IFile objectContribution") | A menu contribution for context menus when the selection is an IFile | -| [Menu Contributions/TextEditor viewerContribution](/Menu_Contributions/TextEditor_viewerContribution "Menu Contributions/TextEditor viewerContribution") | A menu contribution for the text editor context menu | -| [Menu Contributions/Widget in a toolbar](/Menu_Contributions/Widget_in_a_toolbar "Menu Contributions/Widget in a toolbar") | A menu contribution adding a control into the main toolbar | -| [Menu Contributions/RCP removes the Project menu](/Menu_Contributions/RCP_removes_the_Project_menu "Menu Contributions/RCP removes the Project menu") | An RCP application removes the Project menu. Note: this will probably not be in 3.3 | -| [Menu Contributions/Workbench wizard contribution](/Menu_Contributions/Workbench_wizard_contribution "Menu Contributions/Workbench wizard contribution") | Contributing workbench wizards to Menu | +| [Menu Contributions/Dropdown Command](./Menu_Contributions/Dropdown_Command.md "Menu Contributions/Dropdown Command") | Dropdown tool items can have their menus filled in using menu contributions | +| [Menu Contributions/Problems View Example](./Menu_Contributions/Problems_View_Example.md "Menu Contributions/Problems View Example") | An example showing how the Problems View might be converted | +| [Menu Contributions/Populating a dynamic submenu](./Menu_Contributions/Populating_a_dynamic_submenu.md "Menu Contributions/Populating a dynamic submenu") | A menu contribution to populate a Problems View dynamic submenu | +| [Menu Contributions/Toggle Mark Occurrences](./Menu_Contributions/Toggle_Mark_Occurrences.md "Menu Contributions/Toggle Mark Occurrences") | Placing the toggle mark occurrences button | +| [Menu Contributions/Toggle Button Command](./Menu_Contributions/Toggle_Button_Command.md "Menu Contributions/Toggle Button Command") | Contribute a toggle state menu item thru commands | +| [Menu Contributions/Radio Button Command](./Menu_Contributions/Radio_Button_Command.md "Menu Contributions/Radio Button Command") | Similar to updating toggle state, you can create radio buttons using menu contributions | +| [Menu Contributions/Update checked state](./Menu_Contributions/Update_checked_state.md "Menu Contributions/Update checked state") | The active handler can update the checked state (and other attributes) of its button | +| [Menu Contributions/Search Menu](./Menu_Contributions/Search_Menu.md "Menu Contributions/Search Menu") | Adding the Java Search options to the Search menu | +| [Menu Contributions/IFile objectContribution](./Menu_Contributions/IFile_objectContribution.md "Menu Contributions/IFile objectContribution") | A menu contribution for context menus when the selection is an IFile | +| [Menu Contributions/TextEditor viewerContribution](./Menu_Contributions/TextEditor_viewerContribution.md "Menu Contributions/TextEditor viewerContribution") | A menu contribution for the text editor context menu | +| [Menu Contributions/Widget in a toolbar](./Menu_Contributions/Widget_in_a_toolbar.md "Menu Contributions/Widget in a toolbar") | A menu contribution adding a control into the main toolbar | +| [Menu Contributions/RCP removes the Project menu](./Menu_Contributions/RCP_removes_the_Project_menu.md "Menu Contributions/RCP removes the Project menu") | An RCP application removes the Project menu. Note: this will probably not be in 3.3 | +| [Menu Contributions/Workbench wizard contribution](./Menu_Contributions/Workbench_wizard_contribution.md "Menu Contributions/Workbench wizard contribution") | Contributing workbench wizards to Menu | Menu XML ======== diff --git a/docs/Menu_Contributions/Dropdown_Command.md b/docs/Menu_Contributions/Dropdown_Command.md new file mode 100644 index 00000000000..b8512f5ca3a --- /dev/null +++ b/docs/Menu_Contributions/Dropdown_Command.md @@ -0,0 +1,119 @@ +Menu Contributions/Dropdown Command +=================================== + +You can create dropdown commands using menu contributions, and then use multiple menu contributions to create the dropdown menu. + +Contents +-------- + +* [1 Command Definition](#Command-Definition) +* [2 Handler](#Handler) +* [3 Menu Contribution](#Menu-Contribution) + * [3.1 Toolbar declaration](#Toolbar-declaration) + * [3.2 Dropdown menu declaration](#Dropdown-menu-declaration) + +Command Definition +------------------ + +Any command can be used as a toolbar dropdown ... the command itself is not aware of its dropdown rendering. If it were to need that information, 2 common ways of sharing it are: + +1. Create a parameterized command. The commands inserted in the dropdown menu would specify the parameter, and the dropdown tool item command would not. +2. Back your handler with a model and rely on that information + +This command declaration defines a parameter: + + + + + + + + + + + + + + + + + + + +I've thrown in a default image for fun. + +Handler +------- + +The command example includes a default handler, which is common for simple global commands. The handler needs to check for the parameter and then do its stuff. Use org.eclipse.core.commands.AbstractHandler to use its default methods for most of the IHandler interface. + + public class DropDownHandler extends AbstractHandler { + private static final String PARM_MSG = "z.ex.dropdown.msg"; + + public Object execute(ExecutionEvent event) throws ExecutionException { + String msg = event.getParameter(PARM_MSG); + if (msg == null) { + System.out.println("No message"); + } else { + System.out.println("msg: " + msg); + } + return null; + } + } + + + + +As with all handlers, you can extract most of the workbench useful information out of the ExecutionEvent using HandlerUtil. + +Menu Contribution +----------------- + +Dropdown declarations come in two parts, the tool item declaration and a separate dropdown menu declaration. + +### Toolbar declaration + +You are just placing the command in the toolbar. + + + + + + + + + + + + + + + +You can use an existing toolbar id or create a new toolbar to hold the command (as this example did). + +### Dropdown menu declaration + +Now you can provide one or more menu contributions to the dropdown menu. Here is an example of the main one: + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/Menu_Contributions/IFile_objectContribution.md b/docs/Menu_Contributions/IFile_objectContribution.md new file mode 100644 index 00000000000..39fe601f7cd --- /dev/null +++ b/docs/Menu_Contributions/IFile_objectContribution.md @@ -0,0 +1,113 @@ +Menu Contributions/IFile objectContribution +=========================================== + + +IFile object contribution +========================= + +We also have to provide object contributions (which in the past were scoped by objectClass). + +Here's an example from one of our plugin.xml: + + + + + + + + +**enablesFor** is now a property of the active handler, not the visible GUI element. + +Menus +----- + +There will be a reserved popup ID, "org.eclipse.ui.popup.any" that will allow contributions to any popup menu. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +The default variable for visibleWhen/activeWhen/enabledWhen expressions is **selection**. But it's better to be specific and use `` if that's what you need. + +Menus API +--------- + +Here is a similar example programmatically. + + public static void addFileContribution() { + final IMenuService menuService = (IMenuService) PlatformUI + .getWorkbench().getService(IMenuService.class); + // an expression that walks the selection looking for objectclasses + final ObjectClassExpression ifileExpression = new ObjectClassExpression( + "org.eclipse.core.resources.IFile"); +   + final ImageDescriptor postIcon = AbstractUIPlugin + .imageDescriptorFromPlugin("org.eclise.ui.tests", + "icons/full/elcl16/post_wiki.gif"); + final ImageDescriptor loadIcon = AbstractUIPlugin + .imageDescriptorFromPlugin("org.eclise.ui.tests", + "icons/full/elcl16/load_wiki.gif"); + AbstractContributionFactory factory = new AbstractContributionFactory( + "popup:org.eclipse.ui.popup.any?after=additions") { + public void createContributionItems(IMenuService menuService, + List additions) { + CommandContributionItem item = new CommandContributionItem( + "org.eclipse.ui.examples.wiki.post", + "org.eclipse.ui.examples.wiki.post", null, postIcon, + null, null, null, "P", null, + CommandContributionItem.STYLE_PUSH); + menuService.registerVisibleWhen(item, ifileExpression); + additions.add(item); +   + item = new CommandContributionItem( + "org.eclipse.ui.examples.wiki.load", + "org.eclipse.ui.examples.wiki.load", null, loadIcon, + null, null, null, "L", null, + CommandContributionItem.STYLE_PUSH); + menuService.registerVisibleWhen(item, ifileExpression); + additions.add(item); + } +   + public void releaseContributionItems(IMenuService menuService, + List items) { + } + }; + menuService.addContributionFactory(factory); + } + +The location of org.eclipse.ui.popup.any specifies any context menu, and the expression ties it to a specific objectClass. Using the new expression syntax you can make your conditions more complex. + +You can set your visibleWhen expression on each item as you create it. + +In **3.3M6** registerVisibleWhen(*) method might be changing. + diff --git a/docs/Menu_Contributions/Populating_a_dynamic_submenu.md b/docs/Menu_Contributions/Populating_a_dynamic_submenu.md new file mode 100644 index 00000000000..cfead2127ab --- /dev/null +++ b/docs/Menu_Contributions/Populating_a_dynamic_submenu.md @@ -0,0 +1,35 @@ +Menu Contributions/Populating a dynamic submenu +=============================================== + +Add a dynamic submenu to the ProblemView menu +============================================= + +In [Menu Contributions/Problems View Example](./Menu_Contributions/Problems_View_Example.md "Menu Contributions/Problems View Example") we added 2 dynamic menus. You then have to extend the abstract [CompoundContributionItem](http://help.eclipse.org/latest/nftopic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/ui/actions/CompoundContributionItem.html) class in your provided class. + + + + + +When your menu is populated, you'll have your getContributionItems() method called: + + protected IContributionItem\[\] getContributionItems() { + IContributionItem\[\] list = new IContributionItem\[2\]; + Map parms = new HashMap(); + parms.put("groupBy", "Severity"); + list\[0\] = new CommandContributionItem(null, + "org.eclipse.ui.views.problems.grouping", + parms, null, null, null, "Severity", null, + null, CommandContributionItem.STYLE_PUSH); +   + parms = new HashMap(); + parms.put("groupBy", "None"); + list\[1\] = new CommandContributionItem(null, + "org.eclipse.ui.views.problems.grouping", + parms, null, null, null, "None", null, null, + CommandContributionItem.STYLE_PUSH); + return list; + } + diff --git a/docs/Menu_Contributions/Problems_View_Example.md b/docs/Menu_Contributions/Problems_View_Example.md new file mode 100644 index 00000000000..78873923988 --- /dev/null +++ b/docs/Menu_Contributions/Problems_View_Example.md @@ -0,0 +1,353 @@ +Menu Contributions/Problems View Example +======================================== + +Contents +-------- + +* [1 Add ProblemView menus](#Add-ProblemView-menus) + * [1.1 Commands](#Commands) + * [1.2 Handlers](#Handlers) + * [1.3 Menus](#Menus) + * [1.4 Menus API](#Menus-API) + +Add ProblemView menus +===================== + +Add the Problems view menus. The Problems view has one toolbar action and in the view menu, 3 actions and 2 dynamic submenus. It also has a dynamic menu and another bunch of actions in its context menu. + +Commands +-------- + +First define commands that are specific to the view. Since these are view commands, we can specify a default handler ... we're unlikely to replace it. + + + + + + + + + + + + + + + + +Handlers +-------- + +We can also use a number of global commands, like copy, paste, delete, quick fix, and properties. For these, we just need to define our handlers. We need to add them with clauses to restrict them to being active when the view is active. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Or we can programmatically activate them through the IHandlerService which we would retrieve from the ProblemView site. + +IHandlerService handlerServ = (IHandlerService)getSite().getService(IHandlerService.class); +CopyMarkerHandler copy = new CopyMarkerHandler(); +handlerServ.activateHandler("org.eclipse.ui.edit.copy", copy); + +Using the ProblemView site to access the IHandlerService handles the clause for us, and our programmatic handler would manage its own enablement state. + +Menus +----- + +Then we would define the ProblemView menu structures. We are using 3 **roots**: the view menu, the view toolbar, and the view context menu. This is an example of an "in-place" menu definition. The location attribute is a URI that defines the starting point for inserting the menu elements. The XML hierarchy mirrors the menu hierarchy, in that you can define items and menus within the body of other menus. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Menus API +--------- + +We can contribute menu definitions through the IMenuService API. + +The above example can be done for the view menus: + + public void addProblemsViewMenuContribution() { + IMenuService menuService = (IMenuService) PlatformUI.getWorkbench() + .getService(IMenuService.class); +   + AbstractContributionFactory viewMenuAddition = new AbstractContributionFactory( + "menu:org.eclipse.ui.views.ProblemView?after=additions") { + public void createContributionItems(IMenuService menuService, + List additions) { + CommandContributionItem item = new CommandContributionItem( + null, "org.eclipse.ui.views.problems.sorting", null, + null, null, null, "Sorting...", "S", + "Change the Sort order", + CommandContributionItem.STYLE_PUSH); + additions.add(item); +   + MenuManager submenu = new MenuManager("Group &By", + "org.eclipse.ui.views.problems.groupBy.menu"); + IContributionItem dynamicItem = new CompoundContributionItem( + "org.eclipse.ui.views.problems.groupBy.items") { + protected IContributionItem\[\] getContributionItems() { + // Here's where you would dynamically generate your list + IContributionItem\[\] list = new IContributionItem\[2\]; + Map parms = new HashMap(); + parms.put("groupBy", "Severity"); + list\[0\] = new CommandContributionItem(null, + "org.eclipse.ui.views.problems.grouping", + parms, null, null, null, "Severity", null, + null, CommandContributionItem.STYLE_PUSH); +   + parms = new HashMap(); + parms.put("groupBy", "None"); + list\[1\] = new CommandContributionItem(null, + "org.eclipse.ui.views.problems.grouping", + parms, null, null, null, "None", null, null, + CommandContributionItem.STYLE_PUSH); + return list; + } + }; + submenu.add(dynamicItem); +   + additions.add(submenu); + additions.add(new Separator("group.filter")); +   + submenu = new MenuManager("&Filters", + "org.eclipse.ui.views.problems.filters.menu"); + dynamicItem = new CompoundContributionItem( + "org.eclipse.ui.views.problems.filters.items") { + protected IContributionItem\[\] getContributionItems() { + // Here's where you would dynamically generate your list + IContributionItem\[\] list = new IContributionItem\[1\]; + Map parms = new HashMap(); + parms.put("filter", "Default"); + list\[0\] = new CommandContributionItem(null, + "org.eclipse.ui.views.problems.filters", parms, + null, null, null, "Default", null, null, + CommandContributionItem.STYLE_PUSH); + return list; + } + }; + submenu.add(dynamicItem); +   + additions.add(submenu); +   + ImageDescriptor filterIcon = PlatformUI.getWorkbench() + .getSharedImages().getImageDescriptor( + "elcl16/filter_ps.gif"); + item = new CommandContributionItem(null, + "org.eclipse.ui.views.problems.configureFilters", null, + filterIcon, null, null, "Configure Filters...", "C", + "Configure the filters to be applied to this view", + CommandContributionItem.STYLE_PUSH); + additions.add(item); +   + Map parms = new HashMap(); + parms.put("markerEnablementName", "LIMIT_PROBLEMS"); + parms.put("markerLimitName", "PROBLEMS_LIMIT"); + item = new CommandContributionItem(null, + "org.eclipse.ui.preferences.viewPreferences", parms, + null, null, null, "Preference", "P", + "Open the preference dialog", + CommandContributionItem.STYLE_PUSH); + additions.add(item); + } +   + public void releaseContributionItems(IMenuService menuService, + List items) { + // for us this is a no-op + } + }; + menuService.addContributionFactory(viewMenuAddition); + } + +The `AbstractContributionFactory` creates new contribution items every time `createContributionItems(List)` is called. The factory location tells the framework where to insert the contributions when populating `ContributionManager`s. + diff --git a/docs/Menu_Contributions/RCP_removes_the_Project_menu.md b/docs/Menu_Contributions/RCP_removes_the_Project_menu.md new file mode 100644 index 00000000000..3cbc90cb73a --- /dev/null +++ b/docs/Menu_Contributions/RCP_removes_the_Project_menu.md @@ -0,0 +1,38 @@ +Menu Contributions/RCP removes the Project menu +=============================================== + +Product removes the Project menu +================================ + +**Note:** this probably will not make it into 3.4 + +An RCP product wishes to remove the Project menu. It should be possible to override the visibility of menu contributions. + + + + public void addOverride() { + // the RCP app would already have its product key + Object productKey = null; + + IMenuService menuServ = (IMenuService) PlatformUI.getWorkbench() + .getActiveWorkbenchWindow().getService(IMenuService.class); + menuServ.addOverride(productKey, "menu:project", new OverrideAdapter() { + public Boolean getVisible() { + return Boolean.FALSE; + } + }); + } + + + + + + +The idea is to provide this ability at the product level. For example, an RCP app should be able to hide any menu items that it doesn't want but picked up through the inclusion of a plugin. + +That implies that it might not be part of the general IMenuService interface. Or (taking a page from the IExtensionRegistry) it might use a token that's available from the WorkbenchWindowAdvisor so that products can use the interface, or even expose the ability to their users. + +If it returns `null` the next level of visibility is evaluated. The `null` case is to keep it consistent with other overrides. + +The override service is ID based. For items which haven't specified their ID, the override will be applied to the commandId (which is required on every item). + diff --git a/docs/Menu_Contributions/Radio_Button_Command.md b/docs/Menu_Contributions/Radio_Button_Command.md new file mode 100644 index 00000000000..4277dbdc806 --- /dev/null +++ b/docs/Menu_Contributions/Radio_Button_Command.md @@ -0,0 +1,276 @@ +Menu Contributions/Radio Button Command +======================================= + +Contents +-------- + +* [1 Eclipse 3.5 or later](#Eclipse-3.5-or-later) + * [1.1 Command Definition](#Command-Definition) + * [1.2 Handler](#Handler) + * [1.3 Menu Contribution](#Menu-Contribution) +* [2 Eclipse 3.4 or earlier](#Eclipse-3.4-or-earlier) + * [2.1 Command Definition](#Command-Definition-2) + * [2.2 Handler](#Handler-2) + * [2.3 Menu Contribution](#Menu-Contribution-2) + * [2.4 Initializing the Handler](#Initializing-the-Handler) + +Eclipse 3.5 or later +==================== + +You can create a command with a required parameter. The parameter will be passed during every execution. + +Command Definition +------------------ + +Define a command with a state and a parameter. The state id should be org.eclipse.ui.commands.radioState and the parameter id should be org.eclipse.ui.commands.radioStateParameter. + + + + + + + + +Alternatively, the state can be initialized with a default value, which will be checked initially in the Menu. Persistence and default value can be set by parameters for org.eclipse.ui.handlers.RadioState class. The above state section would then be replaced by the following. + + + + + + + + + + + + +Handler +------- + +The handler will receive the parameter. It can then update its model (in my example my **model** is a local variable, but that might not be appropriate in command that can have multiple handlers). + + package com.example; +   + public class RadioHandler extends AbstractHandler{ +   + public Object execute(ExecutionEvent event) throws ExecutionException { +   + if(HandlerUtil.matchesRadioState(event)) + return null; // we are already in the updated state - do nothing +   + String currentState = event.getParameter(RadioState.PARAMETER_ID); +   + // do whatever having "currentState" implies +   + // and finally update the current state + HandlerUtil.updateRadioState(event.getCommand(), currentState); +   + return null; + } +   + } + +Menu Contribution +----------------- + +Then you add menu contributions with the specific parameters that you want: + + + + + + + + + + + + + + + + + + + + +Eclipse 3.4 or earlier +====================== + +You can create a command with a required parameter. The parameter will be passed during every execution. + +Command Definition +------------------ + +You want to create a command that will be executed with a paramter. The parameter in this example matches which of the radio buttons is selected. + + + + + + +Handler +------- + +The handler will receive the parameter. It can then update its model (in my example my **model** is a local variable, but that might not be appropriate in command that can have multiple handlers). + + package com.example.handlers.internal; +   + import java.util.Map; + import org.eclipse.core.commands.AbstractHandler; + import org.eclipse.core.commands.ExecutionEvent; + import org.eclipse.core.commands.ExecutionException; + import org.eclipse.ui.commands.ICommandService; + import org.eclipse.ui.commands.IElementUpdater; + import org.eclipse.ui.handlers.HandlerUtil; + import org.eclipse.ui.menus.UIElement; +   + public class RadioHandler extends AbstractHandler implements IElementUpdater { +   + private static final String PARM_INFO = "z.ex.dropdown.radio.info"; + private String fCurrentValue; +   + public Object execute(ExecutionEvent event) throws ExecutionException { + String parm = event.getParameter(PARM_INFO); + if (parm.equals(fCurrentValue)) { + return null; // in theory, we're already in the correct state + } +   + // do whatever having "parm" active implies + fCurrentValue = parm; +   +   + // update our radio button states ... get the service from + // a place that's most appropriate + ICommandService service = (ICommandService) HandlerUtil + .getActiveWorkbenchWindowChecked(event).getService( + ICommandService.class); + service.refreshElements(event.getCommand().getId(), null); + return null; + } +   + public void updateElement(UIElement element, Map parameters) { + String parm = (String) parameters.get(PARM_INFO); + if (parm != null) { + if (fCurrentValue != null && fCurrentValue.equals(parm)) { + element.setChecked(true); + } else { + element.setChecked(false); + } + } + } + } + +Menu Contribution +----------------- + +Then you add menu contributions with the specific parameters that you want: + + + + + + + + + + + + + + + + + + + + +Initializing the Handler +------------------------ + +It may happen that your radio menu contributions are not initialized the first time the menu is displayed. This is because at this time, your Handler might not yet have been instantiated (this is due to Eclipse's lazy loading policy). If this is the case, you can enforce the instantiation of your Handler within the Activator of your plug-in. Just add the following code to the start(BundleContext) method: + + UIJob job = new UIJob("InitCommandsWorkaround") { +   + public IStatus runInUIThread(@SuppressWarnings("unused") IProgressMonitor monitor) { +   + ICommandService commandService = (ICommandService) PlatformUI + .getWorkbench().getActiveWorkbenchWindow().getService( + ICommandService.class); + Command command = commandService.getCommand("z.ex.dropdown.radio"); + command.isEnabled(); + return new Status(IStatus.OK, + "my.plugin.id", + "Init commands workaround performed succesfully"); + } +   + }; + job.schedule(); + diff --git a/docs/Menu_Contributions/Search_Menu.md b/docs/Menu_Contributions/Search_Menu.md new file mode 100644 index 00000000000..d9ffa6201f7 --- /dev/null +++ b/docs/Menu_Contributions/Search_Menu.md @@ -0,0 +1,396 @@ +Menu Contributions/Search Menu +============================== + + +Contents +-------- + +* [1 Possible Java Search Menu Example](#Possible-Java-Search-Menu-Example) + * [1.1 ActionSet context](#ActionSet-context) + * [1.2 Commands](#Commands) + * [1.3 Menus](#Menus) + * [1.4 Menus API](#Menus-API) + +Possible Java Search Menu Example +================================= + +**NOTE: This is only an example and does not work as is. The example assumes that Search switched to the new menu contribution story which it didn't so far (see [bug 213385](https://bugs.eclipse.org/bugs/show_bug.cgi?id=213385)).** + +The java search menu items are added through a Java Search action set. They have code that enables/disables the action set depending on the active editor. + +ActionSet context +----------------- + +For something to go in an actionSet, then we would define the actionSet context. ActionSet contexts are only partially supported in **3.3M5**. + + + + + + + + + + + +Commands +-------- + +Also, a number of the items were retargetable actions that allow label updates. The active handler can update their appearance with an ICommandService@refreshElements(*) call. + + + + + + + + + + + + + + + + + + + + + + + + + +Menus +----- + +We'll assume that the Search menu is globally defined elsewhere by the org.eclipse.search plugin. + + + + + + + + + + + + + + + + + + + +Then the JDT plugin would contribute the menu items to search, where the menuContribution location specifies the starting point for adding the menus. For groups of actions like the Write Access or Read Access shown here, they can just be specified in order. The clauses must be specified on the items contributed if they want to belong to the actionSet, but if the contribute items are contain in a contributed menu, it can just be specified on the element. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Currently, the java search menus are in the Java Search actionSet, that is dynamically enabled/disabled. This could also be done by specifying a visibleWhen like: + + + + + + + + + + + + + +This would make the visible if either the Java or Class File editor was the active editor, and they would disappear otherwise. + +Menus API +--------- + +The API can be used to contribute to the main menu bar: + + + + public static void addSearchMenu() { + IMenuService menuService = (IMenuService) PlatformUI.getWorkbench() + .getService(IMenuService.class); + + AbstractContributionFactory searchContribution = new AbstractContributionFactory( + "menu:org.eclipse.ui.main.menu?after=navigate") { + public void createContributionItems(IMenuService menuService, + List additions) { + MenuManager search = new MenuManager("Se&arch", + "org.eclipse.search.menu"); + + search.add(new GroupMarker("internalDialogGroup")); + search.add(new GroupMarker("dialogGroup")); + search.add(new Separator("fileSearchContextMenuActionsGroup")); + search.add(new Separator("contextMenuActionsGroup")); + search.add(new Separator("occurencesActionsGroup")); + search.add(new Separator("extraSearchGroup")); + + additions.add(search); + } + + public void releaseContributionItems(IMenuService menuService, + List items) { + // nothing to do here + } + }; + + menuService.addContributionFactory(searchContribution); + } + + + + + +It's just a menu inserted at the menu root location. + + +Then another plugin can contribute to the search menu: + + + + public static void addToSearchMenu() { + final IMenuService menuService = (IMenuService) PlatformUI + .getWorkbench().getService(IMenuService.class); + final ActiveActionSetExpression activeSearchActionSet = new ActiveActionSetExpression( + "org.eclipse.jdt.ui.SearchActionSet"); + + final ImageDescriptor searchIcon = AbstractUIPlugin + .imageDescriptorFromPlugin("org.eclise.ui.tests", + "icons/full/obj16/jsearch_obj.gif"); + AbstractContributionFactory factory = new AbstractContributionFactory( + "menu:org.eclipse.search.menu?after=dialogGroup") { + public void createContributionItems(IMenuService menuService, + List additions) { + CommandContributionItem item = new CommandContributionItem( + "org.eclipse.jdt.internal.ui.search.openJavaSearchPage", + "org.eclipse.jdt.internal.ui.search.openJavaSearchPage", + null, searchIcon, null, null, null, null, null, + CommandContributionItem.STYLE_PUSH); + menuService.registerVisibleWhen(item, activeSearchActionSet); + additions.add(item); + } + + public void releaseContributionItems(IMenuService menuService, + List items) { + } + }; + menuService.addContributionFactory(factory); + + factory = new AbstractContributionFactory( + "menu:org.eclipse.search.menu?after=contextMenuActionsGroup") { + public void createContributionItems(IMenuService menuService, + List additions) { + MenuManager readMenu = new MenuManager("&Read Access", + "readAccessSubMenu"); + menuService + .registerVisibleWhen(readMenu, activeSearchActionSet); + additions.add(readMenu); + + readMenu.add(new GroupMarker("group1")); + + CommandContributionItem item = new CommandContributionItem( + "org.eclipse.jdt.ui.edit.text.java.search.read.access.in.workspace", + "org.eclipse.jdt.ui.edit.text.java.search.read.access.in.workspace", + null, null, null, null, null, "W", null, + CommandContributionItem.STYLE_PUSH); + readMenu.add(item); + item = new CommandContributionItem( + "org.eclipse.jdt.ui.edit.text.java.search.read.access.in.project", + "org.eclipse.jdt.ui.edit.text.java.search.read.access.in.project", + null, null, null, null, null, "P", null, + CommandContributionItem.STYLE_PUSH); + readMenu.add(item); + item = new CommandContributionItem( + "org.eclipse.jdt.ui.edit.text.java.search.read.access.in.hierarchy", + "org.eclipse.jdt.ui.edit.text.java.search.read.access.in.hierarchy", + null, null, null, null, null, "H", null, + CommandContributionItem.STYLE_PUSH); + readMenu.add(item); + item = new CommandContributionItem( + "org.eclipse.jdt.ui.edit.text.java.search.read.access.in.working.set", + "org.eclipse.jdt.ui.edit.text.java.search.read.access.in.working.set", + null, null, null, null, null, "S", null, + CommandContributionItem.STYLE_PUSH); + readMenu.add(item); + + MenuManager writeMenu = new MenuManager("&Write Access", + "writeAccessSubMenu"); + menuService.registerVisibleWhen(writeMenu, + activeSearchActionSet); + additions.add(writeMenu); + + writeMenu.add(new GroupMarker("group1")); + + item = new CommandContributionItem( + "org.eclipse.jdt.ui.edit.text.java.search.write.access.in.workspace", + "org.eclipse.jdt.ui.edit.text.java.search.write.access.in.workspace", + null, null, null, null, null, "W", null, + CommandContributionItem.STYLE_PUSH); + writeMenu.add(item); + item = new CommandContributionItem( + "org.eclipse.jdt.ui.edit.text.java.search.write.access.in.project", + "org.eclipse.jdt.ui.edit.text.java.search.write.access.in.project", + null, null, null, null, null, "P", null, + CommandContributionItem.STYLE_PUSH); + writeMenu.add(item); + item = new CommandContributionItem( + "org.eclipse.jdt.ui.edit.text.java.search.write.access.in.hierarchy", + "org.eclipse.jdt.ui.edit.text.java.search.write.access.in.hierarchy", + null, null, null, null, null, "H", null, + CommandContributionItem.STYLE_PUSH); + writeMenu.add(item); + item = new CommandContributionItem( + "org.eclipse.jdt.ui.edit.text.java.search.write.access.in.working.set", + "org.eclipse.jdt.ui.edit.text.java.search.write.access.in.working.set", + null, null, null, null, null, "S", null, + CommandContributionItem.STYLE_PUSH); + writeMenu.add(item); + } + + public void releaseContributionItems(IMenuService menuService, + List items) { + } + }; + menuService.addContributionFactory(factory); + } + + + + + + +When the main menu is populated, these contribution factories will be called. + diff --git a/docs/Menu_Contributions/TextEditor_viewerContribution.md b/docs/Menu_Contributions/TextEditor_viewerContribution.md new file mode 100644 index 00000000000..3362b5f9045 --- /dev/null +++ b/docs/Menu_Contributions/TextEditor_viewerContribution.md @@ -0,0 +1,72 @@ +Menu Contributions/TextEditor viewerContribution +================================================ + +Contents +-------- + +* [1 Text editor popup action](#Text-editor-popup-action) + * [1.1 Commands](#Commands) + * [1.2 Menus](#Menus) + * [1.3 Menus API](#Menus-API) + +Text editor popup action +======================== + +Popups can be targetted at any registered context menu, or at all of them. This is the Scramble Text command to be added the the standard text editor context menu. + +Commands +-------- + +First define the command and its handler. + + + + + +Menus +----- + +Placing the action (which is specifically a menu or button linked to a command) can be accomplished with the org.eclipse.ui.menus extension point. + + + + + + + +Menus API +--------- + +Programmatically do this, you would have to go through the IMenuService. + + public static void addTextMenuContribition() { + final IMenuService menuService = (IMenuService) PlatformUI + .getWorkbench().getService(IMenuService.class); +   + final ImageDescriptor scrambleIcon = AbstractUIPlugin + .imageDescriptorFromPlugin("org.eclise.ui.tests", + "icons/full/eobj16/scramble.gif"); + AbstractContributionFactory factory = new AbstractContributionFactory( + "popup:#TextEditorContext?after=additions") { + public void createContributionItems(IMenuService menuService, + List additions) { + CommandContributionItem item = new CommandContributionItem( + "org.eclipse.ui.examples.menus.scramble.text", + "org.eclipse.ui.examples.menus.scramble.text", + null, scrambleIcon, null, null, null, "c", null, + CommandContributionItem.STYLE_PUSH); + additions.add(item); + } +   + public void releaseContributionItems(IMenuService menuService, + List items) { + } + }; + menuService.addContributionFactory(factory); + } + diff --git a/docs/Menu_Contributions/Toggle_Button_Command.md b/docs/Menu_Contributions/Toggle_Button_Command.md new file mode 100644 index 00000000000..9cb8bef6217 --- /dev/null +++ b/docs/Menu_Contributions/Toggle_Button_Command.md @@ -0,0 +1,55 @@ + + +Menu Contributions/Toggle Button Command +======================================== + +You can create a command with a required parameter. The parameter will be passed during every execution. + +Command Definition +------------------ + +Define a command with a state. The state id should be org.eclipse.ui.commands.toggleState. + + + + + + +The state can be initialized with a default value, which reflects in the Menu + +Handler +------- + +The handler will receive the state. Its the responsibility of the handler to update the state of the command. + + public class CheckHandler extends AbstractHandler{ +   + public Object execute(ExecutionEvent event) throws ExecutionException { +   + Command command = event.getCommand(); + boolean oldValue = HandlerUtil.toggleCommandState(command); + // use the old value and perform the operation +   + return null; + } +   + } + +Menu Contribution +----------------- + +Then you add menu contributions as you would do with any command, except you need to set the style to toggle: + + + + + diff --git a/docs/Menu_Contributions/Toggle_Mark_Occurrences.md b/docs/Menu_Contributions/Toggle_Mark_Occurrences.md new file mode 100644 index 00000000000..4e5965a8ea0 --- /dev/null +++ b/docs/Menu_Contributions/Toggle_Mark_Occurrences.md @@ -0,0 +1,192 @@ +Menu Contributions/Toggle Mark Occurrences +========================================== + +Contents +-------- + +* [1 Add Toggle Mark Occurrences to main toolbar](#Add-Toggle-Mark-Occurrences-to-main-toolbar) + * [1.1 Commands](#Commands) + * [1.2 Handlers](#Handlers) + * [1.3 Menus](#Menus) + * [1.4 Menus API](#Menus-API) + +Add Toggle Mark Occurrences to main toolbar +=========================================== + +We can provide the Toggle Mark Occurrences toolbar button. It's normally contributed through an actionSet as a retargettable action, and the Java and Class File editors \*EditorActionBarContributors provide the implementation ToggleMarkOccurrencesAction through IActionBars#setGlobalActionHandler(\*). + +Commands +-------- + +In 3.3 the enablement is tied to the command, and for the other behaviours we allow the active handler to update the UI presentation. + +The command service keeps a list of registered UI elements, which can be updated by the active handler. The checked state can be updated through UIElement#setChecked(boolean); + + private boolean isChecked() { + return getStore().getBoolean( + PreferenceConstants.EDITOR_MARK_OCCURRENCES); + } + + public void updateElement(UIElement element, Map parameters) { + element.setChecked(isChecked()); + } + + + + +When the toggle handler runs, it can request that any UI elements have their appearance updated from its execute(*) method: + + + + ICommandService service = (ICommandService) serviceLocator + .getService(ICommandService.class); + service.refreshElements( + IJavaEditorActionDefinitionIds.TOGGLE_MARK_OCCURRENCES, + null); + + + + + + +Handlers +-------- + +This command doesn't have a default handler, as it only applies to specific editors that are provided. So we would provide the handler for the java editor. + + + + + + + + + + + + + + + + + + + + +We're active for both the Java editor and the Class File editor. There is also the option to programmatically install the handler. + + AndExpression expr = new AndExperssion(); + expr.add(new ActivePartIdExpression("org.eclipse.jdt.ui.CompilationUnitEditor")); + expr.add(new ActivePartIdExpression("org.eclipse.jdt.ui.ClassFileEditor")); + IHandlerService handlerServ = (IHandlerService)getSite().getWorkbenchWindow().getService(IHandlerService.class); + toggleOccurrencesHandler = new ToggleMarkOccurrencesHandler(); + handlerServ.activateHandler("org.eclipse.jdt.ui.edit.text.java.toggleMarkOccurrences", toggleOccurrencesHandler, expr); + + + + +Since the same handler is valid for both editors, we install it with a specific expression and **don't** tie the activation to the part site. But as written, the `toggleOccurrencesHandler` will exist as long as the workbench window exists. + +Menus +----- + +In **3.3M5** ActionSets generate and update active contexts. + + + + + + + + + + + + + + + + + + + + + + + + + + +This item is also tied to an actionSet. + +Menus API +--------- + +The above XML can be done using the menus API: + + public static void createToggleMarkOccurrences() { + final IMenuService menuService = (IMenuService) PlatformUI + .getWorkbench().getService(IMenuService.class); + final ImageDescriptor markOccurDesc = AbstractUIPlugin + .imageDescriptorFromPlugin("org.eclise.ui.tests", + "icons/full/etool16/mark_occurrences.gif"); + final ImageDescriptor disabledMarkOccurDesc = AbstractUIPlugin + .imageDescriptorFromPlugin("org.eclise.ui.tests", + "icons/full/dtool16/mark_occurrences.gif"); + + AbstractContributionFactory contribution = new AbstractContributionFactory( + "toolbar:org.eclipse.ui.edit.text.actionSet.presentation?after=Presentation") { + public void createContributionItems(IMenuService menuService, + List additions) { + IContributionItem item = new CommandContributionItem( + null, + "org.eclipse.jdt.ui.edit.text.java.toggleMarkOccurrences", + null, markOccurDesc, disabledMarkOccurDesc, null, null, + null, "Toggle Mark Occurrences", CommandContributionItem.STYLE_CHECK); + menuService + .registerVisibleWhen( + item, + new ActiveActionSetExpression( + "org.eclipse.jdt.ui.text.java.actionSet.presentation")); + additions.add(item); + } + + public void releaseContributionItems(IMenuService menuService, + List items) { + } + }; + menuService.addContributionFactory(contribution); + } + + + + + +This asks for a toolbar root in the org.eclipse.ui.edit.text.actionSet.presentation toolbar after the Presentation id. + +It's contributed with a visibleWhen clause `ActiveActionSetExpression("org.eclipse.jdt.ui.text.java.actionSet.presentation")`, so it will be visible when the actionSet is active. + +The registerVisibleWhen() method might be changing in **3.3M6** + diff --git a/docs/Menu_Contributions/Update_checked_state.md b/docs/Menu_Contributions/Update_checked_state.md new file mode 100644 index 00000000000..48d36567bc2 --- /dev/null +++ b/docs/Menu_Contributions/Update_checked_state.md @@ -0,0 +1,22 @@ +Menu Contributions/Update checked state +======================================= + +Update the toolbar item checked state +===================================== + +The active handler can update any UI elements registered against the its command. It does this by requesting the ICommandService to refresh any registered UIElements. + +As a handler becomes active and implement IElementUpdater like org.eclipse.ui.tests.menus.ToggleContextHandler, the command service calls `public void updateElement(UIElement element, Map parameters)` for every UIElement registered against the command. + + public class ToggleContextHandler extends AbstractHandler implements + IElementUpdater { + private static final String TOGGLE_ID = "toggleContext.contextId"; + // ... + public void updateElement(UIElement element, Map parameters) { + // the checked state depends on if we have an activation for that + // context ID or not + String contextId = (String) parameters.get(TOGGLE_ID); + element.setChecked(contextActivations.get(contextId) != null); + } + } + diff --git a/docs/Menu_Contributions/Widget_in_a_toolbar.md b/docs/Menu_Contributions/Widget_in_a_toolbar.md new file mode 100644 index 00000000000..d0f0445b754 --- /dev/null +++ b/docs/Menu_Contributions/Widget_in_a_toolbar.md @@ -0,0 +1,37 @@ +Menu Contributions/Widget in a toolbar +====================================== + +Widget in the main toolbar +========================== + +You can use the extension point to contribute a control to the toolbar. You use the element instead of the element. + + + + + + + + + + + + + + + +The control class must implement WorkbenchWindowControlContribution as of **3.3M5**. + + +I'm not sure how far to go with IWorkbenchWidget. We already use this interface for adding controls to the trim, and there are open bug requests about adding arbitrary controls to the toolbars. It looks like we'll deprecate it in favour of WorkbenchWindowControlContribution. + +Also, there are risks associated with this like eager plugin activation. Maybe we allow widget activation but restrict it to programmatic API only (after the plugin has been instantiated) or still allow declarative contributions but only with certain types of `` clauses. + + There are two separate reasons to use an extension point to contribute to the toolbar. One reason is to defer plug-in activation. But the other, is to allow a plug-in to contribute to another plug-in even though it depends on that plug-in, or it ships as additional, add-on function. In either case, the plug-in owning the toolbar can not depend on the contributing plug-in. While in general, one wants plug-in activation to occur as late as possible, there are cases where you just don't care. It's great to see that I can now contribute anything I want to another plug-in's toolbar. + +I think this flexibility needs to be supported. Isn't it possible for a bundle to specify exceptions that would prevent the bundle from being started even though the contribution's classes are loaded to create the Control? + +While we're still looking at this in **3.3M6** the preliminary implementation will probably be our standard proxy pattern. That means that contributing a control to the main toolbar will just start the contributing plugin (so we'll just ask people to be careful :-). But as an aside, I'm pretty sure that an exception that prevents a bundle from being started will also prevent us from getting the plugin control contribution from IConfigurationElement#createExecutableExtension(*) + + diff --git a/docs/Menu_Contributions/Workbench_wizard_contribution.md b/docs/Menu_Contributions/Workbench_wizard_contribution.md new file mode 100644 index 00000000000..67315365772 --- /dev/null +++ b/docs/Menu_Contributions/Workbench_wizard_contribution.md @@ -0,0 +1,58 @@ + + +Menu Contributions/Workbench wizard contribution +================================================ + +< [Menu Contributions](/Menu_Contributions "Menu Contributions") + +Workbench Wizard Contribution +----------------------------- + +You can add your new/import/export wizards to a menu/toolbar via Command contributions. You need to use the standard command ids (org.eclipse.ui.newWizard, org.eclipse.ui.file.import and org.eclipse.ui.file.export) with the wizard id as the parameter. Eg: + + + + + + + + + + + + + + + + + + + + + + + +Would result in: + +![Workbench-wizard-commands.png](https://raw.githubusercontent.com/eclipse-platform/eclipse.platform.ui/master/docs/images/Workbench-wizard-commands.png) + diff --git a/docs/images/Workbench-wizard-commands.png b/docs/images/Workbench-wizard-commands.png new file mode 100644 index 00000000000..2f44c983162 Binary files /dev/null and b/docs/images/Workbench-wizard-commands.png differ