Reputation: 909
I would like to have special contextual menu for a right-click+ALT event.
So far, I can set the menu for that event to my custom one. but I am not able to reset it back to the default on a regular right-click (no ALT is down).
I tried to store the default menu via textarea.getContextualMenu(), and use that menu for the regular right click, but it still shows my custom menu for both events with and without ALT.
Any ideas on how I can get reset the menu back?
//store default menu
defaultMenu = controller.txtArea.getContextMenu();
//check if alt is down
controller.txtArea.addEventHandler(KeyEvent.KEY_PRESSED, new EventHandler<KeyEvent>() {
@Override
public void handle(KeyEvent keyEvent) {
if (keyEvent.getCode().equals(ALT)) {
System.out.println("alt typed---" + controller.txtArea.getCaretPosition());
//check if right click is performed
controller.txtArea.addEventFilter(MouseEvent.MOUSE_PRESSED, new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent mouseEvent) {
if (mouseEvent.getButton().equals(MouseButton.SECONDARY)) {
//override default menu by custom one
ContextMenu customMenu = new ContextMenu(new MenuItem("testing"));
controller.txtArea.setContextMenu(customMenu);
}
}
});
}
else{
//reset menu to default
controller.txtArea.setContextMenu(defaultMenu);
}
}
});
Upvotes: 1
Views: 3399
Reputation: 909
Here is the solution! thanks for your comments. There were two issues: The first is the contextual menus which was solved by setOnContextMenuRequested. And the second is the fact that ALT was "pressed", I had to make another event to fire when it is unpressed.. to reset the menu back. So the following combination works:
//add custom menu actions..
controller.inLineCSSTextArea.addEventFilter(MouseEvent.MOUSE_PRESSED, new EventHandler<MouseEvent>() {//check for mouse click
@Override
public void handle(MouseEvent mouseEvent) {//handle event this way...
if (mouseEvent.getButton().equals(MouseButton.SECONDARY)) {//if right mouse button
controller.inLineCSSTextArea.setOnContextMenuRequested(new EventHandler<ContextMenuEvent>() {//check for context menu request
@Override
public void handle(ContextMenuEvent arg0) {//handle event this way...
//set a custom menu based on key event
controller.inLineCSSTextArea.addEventHandler(KeyEvent.KEY_PRESSED, new EventHandler<KeyEvent>() {//check for key event...
@Override
public void handle(KeyEvent keyEvent) {//handle event this way...
if (keyEvent.getCode().equals(CONTROL)) {//if control key is pressed
controller.inLineCSSTextArea.setContextMenu(CNTRLmenu);
}
if (keyEvent.getCode().equals(ALT) ) {//if alt key is pressed
controller.inLineCSSTextArea.setContextMenu(ALTmenu);
}
}
});
}
});
}
}
});
//reset the context menu when any key is released. this is needed, otherwise default menu will not be set again on right click.
controller.inLineCSSTextArea.addEventHandler(KeyEvent.KEY_RELEASED, new EventHandler<KeyEvent>() {
@Override
public void handle(KeyEvent keyEvent) {
controller.inLineCSSTextArea.setContextMenu(DEFAULTmenu);
}
});
Upvotes: 0
Reputation: 10969
I would switch it up (or build one depending on cases) in the menu requested event.
I do something like this to build menus depending on the situation. Not exactly your situation but you could just set a different menu in the event handler. It is a method of Node so you can use it for TextArea.
private static final class TextFieldTreeCellImpl extends TreeCell<String> {
private TextField textField;
public TextFieldTreeCellImpl() {
setOnContextMenuRequested((ContextMenuEvent event) -> {
setContextMenu(getCtxMenu());
});
}
private ContextMenu getCtxMenu() {
ContextMenu ctxMenu = new ContextMenu();
((TreeNode)getTreeItem()).addMenuItems(ctxMenu);
return ctxMenu;
}
...
Upvotes: 2
Reputation: 2240
Your problem is very interesting. Although you have not submitted your application code so that we could precisely analyze the problem, I can introduce you another solution (maybe better).
There were few times I've worked with contextual menu. Maybe you can do something more interesting. For example, maybe you can create a context menu using only the junction of JavaFX components. For this, you could define an area in your program which would be reserved for the appearance of the contextual menu. This area would probably be a JavaFX component (a control), such as a text area. You could start by applying a mouse event on this control. Once the user clicked with the mouse, you could reveal your own context menu.
You could create an extension of the Parent class, which would serve as an area for placement of JavaFX controls. With the use of the new CSS API, you could styling via CSS this area of placement of controls. Having put all controls within that area, you would have your context menu. With your controls within your context menu when the mouse clicked within your text area, you could reveal your own context menu.
For this to be done correctly, you could at the beginning of your application add your context menu in the same collection of your text area by setting the opacity property to zero, and mouseTransparent to true. When the user clicks, the triggered event must change these properties, and also correctly position your context menu with layoutXY properties. Or you could not use opacity and mouseTransparent. You could just add and remove your context menu when necessary.
In order for your program to become even better, you could use Timeline to add an opacity animation, gradually revealing your custom context menu. You could also add shading effects, such as DropShadow that would leave your context menu noticeably above your text area.
This would allow you much more flexibility and customization, making your application be more appealing. ;)
Upvotes: 1