I have a MenuManager that is filled with Actions, is it possible to access the corresponding MenuItem for the action (ContributionItem) ?
MenuManager menuManager = new MenuManager("#PopupMenu", "contextMenu");
menuManager.add(IAction1...);
menuManager.add(IAction2...);
Menu menu = menuManager.createContextMenu(myTreeVvewer.getControl());
myTreeVvewer.getControl().setMenu(menu);
myTreeVvewer.getTree().addSelectionListener(new SelectionListener() {
public void widgetDefaultSelected(SelectionEvent e) {
//Iterate menu items of menu and set something...
}
}
It would probably be easier to use the option MenuManager#.setRemoveAllWhenShown(true); and then dynamically add the menu items in a IMenuListener.
Related
I have created a menu bar where i have 5 items:
Now what i want to do is, for each items, when i click one of them, an interface dedicated for that item will be open under the menu bar in java, as shown in this example:
How can i do this in java? Thank you so much for your helps.
Here is my java code:
public class MainView extends Div {
public MainView() {
MenuBar menuBar = new MenuBar();
Text selected = new Text("");
ComponentEventListener<ClickEvent<MenuItem>> listener = e -> selected
.setText(e.getSource().getText());
Div message = new Div(new Text("Clicked item: "), selected);
menuBar.addItem("Administrateur", listener);
menuBar.addItem("Utilisateur", listener);
MenuItem share = menuBar.addItem("Article");
MenuItem move = menuBar.addItem("Fournisseur");
menuBar.addItem("Catégorie", listener);
add(menuBar, message);
}
}
Create an interface for each element of menu bar in java.
I'm adding a PopUp menu to one of my widgets, a Table. It is not working! I only achieved to make work accelerator shortcuts if they are on top menu bar items, and not in popup context menu items. Why?
This is my code, but the table is inside a Composite which is inside another composite:
membersTable.setMenu(createMembersPopUpMenu(this));
private Menu createMembersPopUpMenu(Composite parent) {
Menu popUpMenu = new Menu(parent);
//Copy
copyMemberItem = new MenuItem(popUpMenu, SWT.PUSH);
copyMemberItem.setText("Copiar Miembro");
copyMemberItem.setAccelerator(SWT.MOD1 + 'C');
copyMemberItem.addSelectionListener(new SelectionAdapter() {
#Override
public void widgetSelected(SelectionEvent e) {
copyMember();
}
});
//Paste
pasteMemberItem = new MenuItem(popUpMenu, SWT.PUSH);
pasteMemberItem.setText("Pegar Miembro");
pasteMemberItem.setAccelerator(SWT.MOD1 + 'V');
pasteMemberItem.addSelectionListener(new SelectionAdapter() {
#Override
public void widgetSelected(SelectionEvent e) {
pasteMember();
}
});
return popUpMenu;
}
I am writting a little desktop application with a TreeView according to the Oracle-Example from here: https://docs.oracle.com/javafx/2/ui_controls/tree-view.htm.
From a MenuItem action of a ContextMenu, I would like to fire an event which shall create a new TreeItem below the item where I opened the ContextMenu from.
For MenuItem, it is possible to use the setOnAction(EventHandler<ActionEvent> event) method, but I only want to fire the action from a left mouse-click.
First, it is not possible to add an EventHandler to a MenuItem although it provides the method addEventHandler(EventType type, EventHandler<EventType> handler) with the event-type MouseEvent.ANY (or anything else). The handle-method of the event-handler is not called.
Second, i can use a workarround by adding a Label to a MenuItem by menuItem.setGraphic(label) and add an EventHandler to the label. This one works although MouseEvent.MOUSE_CLICKED is not called by an EventHandler's handle-method on a Label.
Is this "normal" behaviour? I understand that a label does not react on a click-event, but I do not understand why it is not possible to register a separate EventHandler or EventFilter on a MenuItem.
ContextMenu uses a MenuItemContainer, which is a
Container responsible for laying out a single row in the menu - in other
words, this contains and lays out a single MenuItem, regardless of it's
specific subtype.
Fur this purpose it seems to create new Nodes representing the MenuItem. So any EventHandlers added to the MenuItem will not be called.
To make it work as you intended, you can use a CustomMenuItem and add the according EventHandler to its content:
public class ContextMenuCell extends TreeCell<String> {
private ContextMenu menu;
public ContextMenuCell() {
Label lbl = new Label("Add item");
MenuItem menuItem = new CustomMenuItem(lbl);
lbl.setOnMouseClicked(evt -> {
if (evt.getButton() != MouseButton.PRIMARY) {
return;
}
TreeItem treeItem =
new TreeItem<String>("New item");
if (getTreeItem().isLeaf()) {
getTreeItem().getParent().getChildren().add(getIndex(), treeItem);
} else {
getTreeItem().getChildren().add(0, treeItem);
}
});
menu = new ContextMenu(menuItem);
}
#Override
public void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setText(null);
setGraphic(null);
} else {
setText(item);
setGraphic(getTreeItem().getGraphic());
setContextMenu(menu);
}
}
}
Menu and MenuItem are not Nodes, so they will not handle mouse clicks since they are not displayed on the screen. A workaround is to set a graphics object (Node) to the MenuItem and add the listener to this Node. Works also for other menus like CheckMenuItem etc.:
public class RunJavaFX extends Application {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) throws Exception {
//the label will be our graphics object (Node)
Label l = new Label("Your Menu Text");
l.setTextFill(Color.BLACK); //set black since default CSS Style sets it to background color of the Menu
//add either over addEventFilter or addEventHandler
l.addEventFilter(MouseEvent.MOUSE_PRESSED, ev -> {
if (ev.getButton() == MouseButton.SECONDARY) {
System.out.println("RightClick: " + ev.getSource() + System.nanoTime());
} else {
System.out.println("Not Right Click: " + ev.getSource() + System.nanoTime());
}
ev.consume(); //optional
});
//create the MenuItem with an empty text and set the label l as graphics object
MenuItem mI = new MenuItem("", l);
//create the dummy menu and MenuBar for the example
Menu m = new Menu("Menu");
m.getItems().add(mI);
MenuBar mB = new MenuBar(m);
//create the dummy scene for the example
Scene scene = new Scene(mB);
primaryStage.setScene(scene);
primaryStage.show();
}
}
I need to create a context menu for a TreeViewer in an Eclipse plugin project. But, the menu should not contain constant items, they should vary depending on the type of the node that is selected. For example, my treeViewer has the following hierarchy:
Node A
|
--Node B
|
--Node C
For node A - I want to show a menu with an action, but for nodes B and C I don't want to show anything (no menu).
I managed to create the menu for node A, but then I can't get rid of it when some other type of node is selected. My code looks like:
treeViewer.addSelectionChangedListener(
new ISelectionChangedListener(){
public void selectionChanged(SelectionChangedEvent event) {
if(event.getSelection() instanceof IStructuredSelection) {
IStructuredSelection selection = (IStructuredSelection)event.getSelection();
Object o = selection.getFirstElement();
MenuManager menuMgr = new MenuManager();
if (o instanceof NodeA){
Menu menu = menuMgr.createContextMenu(treeViewer.getControl());
treeViewer.getControl().setMenu(menu);
getSite().registerContextMenu(menuMgr, treeViewer);
menuMgr.add(new SomeAction());
}else {
//what ?
}
}
}
}
);
On the else branch I tried to call dispose(),removeAll() on the MenuManager...nothing works!
Any help is appreciated, thanks.
As #jeeeyul mentioned, you should only create one MenuManager to use within your view.
You can use New>Plug-in Project and the view template to get an example of a context menu in a view using a viewer, but basically in your createPartControl(Composite) method you would hook up your context manager.
MenuManager menuMgr = new MenuManager();
menuMgr.setRemoveAllWhenShown(true);
menuMgr.addMenuListener(new IMenuListener() {
public void menuAboutToShow(IMenuManager manager) {
SampleView.this.fillContextMenu(manager);
}
});
Menu menu = menuMgr.createContextMenu(viewer.getControl());
viewer.getControl().setMenu(menu);
getSite().registerContextMenu(menuMgr, viewer);
Your fillContextMenu(MenuManager) method will have access to your viewer, so you can get the current selection from that. You can add whatever actions you want, even re-add actions after updating them with the current selection.
The registerContextMenu(*) call allows extension points like org.eclipse.ui.popupMenus and org.eclipse.ui.menus to contribute items to your context menu.
Just use single Menu Manager.
Do not make Menu Manager dynamically.
in theory, It's possible you tried, but it's inefficient and it's not general way.
Just make a Menu Manager and add all actions which you needs.
when selection has been changed, call Action#setVisible(true|false)to hide or show menu items.
You can also use Action#setEnable to enable/disable menu item.
ps.
Menu Manager is not a menu GUI(likes TreeViewer is a not tree)
It contributes Actions(business logic) to Menu(SWT). And It also manage visibility and enablement. We call this Contribution Manager. We can create a SWT menu very easy with this. (even we don't know about SWT, we just have to know only our business logic:Action) It's fundamental idea in JFace.
When you add an action into manu manager, action will be wrapped with ActionContributionItem. It hooks action's state to update UI(visibility, enablement for menu, button, toolbar and so on). It also hooks UI to launch action when it pressed.
If you are new to eclipse, It is easy to confuse role of SWT and JFace.
Thats the way I do it:
MenuManager menuMgr = new MenuManager();
Menu menu = menuMgr.createContextMenu(viewer.getControl());
menuMgr.addMenuListener(new IMenuListener() {
#Override
public void menuAboutToShow(IMenuManager manager) {
// IWorkbench wb = PlatformUI.getWorkbench();
// IWorkbenchWindow win = wb.getActiveWorkbenchWindow();
if (viewer.getSelection().isEmpty()) {
return;
}
if (viewer.getSelection() instanceof IStructuredSelection) {
IStructuredSelection selection = (IStructuredSelection) viewer.getSelection();
Node object = (Node)selection.getFirstElement();
if (object.getModel() instanceof NodeA) {
manager.add(new Action();
} else if (object.getModel() instanceof NodeB) {
manager.add(new OtherAction());
}
}
}
});
menuMgr.setRemoveAllWhenShown(true);
viewer.getControl().setMenu(menu);
I hope this helps ;)
It is important to set removeAllWhenShown property of menu manager to false, in order to hide all the other nodes actions ;)
Suppose that you know how to create Action and you are only interested in context menu following example worked for me hope this bunch of code will help you
private void hookContextMenu() {
MenuManager contextMenu = new MenuManager();
contextMenu.setRemoveAllWhenShown(true);
contextMenu.addMenuListener(new IMenuListener() {
#Override
public void menuAboutToShow(IMenuManager manager) {
IStructuredSelection sSelection = (IStructuredSelection) treeViewer.getSelection();
}
if(selectedObject instanceof A){
manager.add(action);
}
}
});
I'm having a slight problem with an Eclipse Plug-In in development.
There is a view which is comparabe to a roster. There is a list of users in there. My problem is, that I'd like to add an context menu.
The idea is to perform a right-click on a user and the menu should pop up. So far so good... but the problem is that I don't want a single menu. I'd like to have an entry "set status" to that context menu and when one hovers over this entry the menu should be extended to show stuff like "away" "busy" "invisible" and so on...
Could anyone help me out to achieve this?
I have already implemented the corresponding action and made the addition to the MenuManager.
public SessionViewContextMenu(ViewPart sessionView, TableViewer viewer,
final Action action) {
MenuManager manager = new MenuManager("#PopupMenu");
manager.setRemoveAllWhenShown(true);
manager.addMenuListener(new IMenuListener() {
public void menuAboutToShow(IMenuManager manager) {
manager.add(action);
}
});
The correspodning action looks like this:
public Action(...) {
super(provider, "Bla Bla");
// some fancy picture
setImageDescriptor(...);
// setId(ACTION_ID);
setToolTipText("Bla Bla");
update();
}
Everything is working fine (at least the context menu shows the entry). Now I'd like to extend the menu when one hovers over / selects the corresponding action. So the menu should extend and show some more possibilites here...
Any help on how to create a recursive context menu is highly appreciated!
Hope, you understand the problem and don't hesitate to ask dor clarification!
Just create a sub-menu and add the actions to this sub-menu.
Here is a quick snippet which should clarify the usage:
// submenu for a specific user
MenuManager subMenu = new MenuManager("Change Status", null);
// Actions for the sub menu
subMenu.add(someAction);
// add the action to the submenu
manager.add(subMenu);
Hope that helps!
Put together:
public SessionViewContextMenu(ViewPart sessionView, TableViewer viewer,
final Action action) {
MenuManager manager = new MenuManager("#PopupMenu");
manager.setRemoveAllWhenShown(true);
manager.addMenuListener(new IMenuListener() {
public void menuAboutToShow(IMenuManager manager) {
manager.add(action);
// submenu for a specific user
MenuManager subMenu = new MenuManager("Change Status", null);
// Actions for the sub menu
subMenu.add(someAction);
// add the action to the submenu
manager.add(subMenu);
}
});