modules/controls/src/main/java/com/sun/javafx/scene/control/behavior/MenuButtonBehaviorBase.java
Print this page
rev 9240 : 8076423: JEP 253: Prepare JavaFX UI Controls & CSS APIs for Modularization
@@ -1,7 +1,7 @@
/*
- * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
@@ -23,104 +23,92 @@
* questions.
*/
package com.sun.javafx.scene.control.behavior;
-import static javafx.scene.input.KeyCode.UP;
-import static javafx.scene.input.KeyCode.DOWN;
-import static javafx.scene.input.KeyCode.LEFT;
-import static javafx.scene.input.KeyCode.RIGHT;
-import static javafx.scene.input.KeyCode.CANCEL;
-import static javafx.scene.input.KeyCode.ESCAPE;
-import static javafx.scene.input.KeyEvent.KEY_PRESSED;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import javafx.geometry.NodeOrientation;
import javafx.geometry.Side;
import javafx.scene.control.MenuButton;
+import com.sun.javafx.scene.control.inputmap.InputMap;
+import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseEvent;
+import static com.sun.javafx.scene.control.inputmap.InputMap.KeyMapping;
+import static javafx.scene.input.KeyCode.*;
+
/**
* The base behavior for a MenuButton.
*/
public abstract class MenuButtonBehaviorBase<C extends MenuButton> extends ButtonBehavior<C> {
- /***************************************************************************
- * *
- * Constructors *
- * *
- **************************************************************************/
-
- public MenuButtonBehaviorBase(final C menuButton, List<KeyBinding> bindings) {
- super(menuButton, bindings);
- }
+ private final InputMap<C> buttonInputMap;
/***************************************************************************
* *
- * Key event handling *
+ * Constructors *
* *
**************************************************************************/
- /**
- * Opens the popup menu.
- */
- protected static final String OPEN_ACTION = "Open";
+ public MenuButtonBehaviorBase(final C menuButton) {
+ super(menuButton);
- /**
- * Closes the popup menu.
- */
- protected static final String CLOSE_ACTION = "Close";
+ // pull down the parent input map, no need to add focus traversal
+ // mappings - added in ButtonBehavior.
+ buttonInputMap = super.getInputMap();
+
+ // We want to remove the maping for MOUSE_RELEASED, as the event is
+ // handled by the skin instead, which calls the mouseReleased method below.
+ removeMapping(MouseEvent.MOUSE_RELEASED);
/**
* The base key bindings for a MenuButton. These basically just define the
* bindings to close an open menu. Subclasses will tell you what can be done
* to open it.
*/
- protected static final List<KeyBinding> BASE_MENU_BUTTON_BINDINGS = new ArrayList<KeyBinding>();
- static {
- BASE_MENU_BUTTON_BINDINGS.add(new KeyBinding(UP, "TraverseUp"));
- BASE_MENU_BUTTON_BINDINGS.add(new KeyBinding(DOWN, "TraverseDown"));
- BASE_MENU_BUTTON_BINDINGS.add(new KeyBinding(LEFT, "TraverseLeft"));
- BASE_MENU_BUTTON_BINDINGS.add(new KeyBinding(RIGHT, "TraverseRight"));
- BASE_MENU_BUTTON_BINDINGS.add(new KeyBinding(ESCAPE, KEY_PRESSED, CLOSE_ACTION));
- BASE_MENU_BUTTON_BINDINGS.add(new KeyBinding(CANCEL, KEY_PRESSED, CLOSE_ACTION));
- }
+ addDefaultMapping(new KeyMapping(ESCAPE, e -> getNode().hide()));
+ addDefaultMapping(new KeyMapping(CANCEL, e -> getNode().hide()));
- /**
- * Invokes the given named action.
- *
- * @param name the name of the action to invoke
- */
- @Override protected void callAction(String name) {
- MenuButton button = getControl();
- Side popupSide = button.getPopupSide();
-
- if (CLOSE_ACTION.equals(name)) {
- button.hide();
- } else if (OPEN_ACTION.equals(name)) {
- if (button.isShowing()) {
- button.hide();
- } else {
- button.show();
+ // we create a child input map, as we want to override some of the
+ // focus traversal behaviors (and child maps take precedence over parent maps)
+ InputMap<C> customFocusInputMap = new InputMap<>(menuButton);
+ addDefaultMapping(customFocusInputMap, new KeyMapping(UP, this::overrideTraversalInput));
+ addDefaultMapping(customFocusInputMap, new KeyMapping(DOWN, this::overrideTraversalInput));
+ addDefaultMapping(customFocusInputMap, new KeyMapping(LEFT, this::overrideTraversalInput));
+ addDefaultMapping(customFocusInputMap, new KeyMapping(RIGHT, this::overrideTraversalInput));
+ addDefaultChildMap(buttonInputMap, customFocusInputMap);
}
- } else if (!button.isShowing() &&
- ("TraverseUp".equals(name) && popupSide == Side.TOP) ||
- ("TraverseDown".equals(name) && (popupSide == Side.BOTTOM || popupSide == Side.TOP)) ||
- ("TraverseLeft".equals(name) && (popupSide == Side.RIGHT || popupSide == Side.LEFT)) ||
- ("TraverseRight".equals(name) && (popupSide == Side.RIGHT || popupSide == Side.LEFT))) {
+
+
+ /***************************************************************************
+ * *
+ * Key event handling *
+ * *
+ **************************************************************************/
+
+ private void overrideTraversalInput(KeyEvent event) {
+ final MenuButton button = getNode();
+ final Side popupSide = button.getPopupSide();
+ if (!button.isShowing() &&
+ (event.getCode() == UP && popupSide == Side.TOP) ||
+ (event.getCode() == DOWN && (popupSide == Side.BOTTOM || popupSide == Side.TOP)) ||
+ (event.getCode() == LEFT && (popupSide == Side.RIGHT || popupSide == Side.LEFT)) ||
+ (event.getCode() == RIGHT && (popupSide == Side.RIGHT || popupSide == Side.LEFT))) {
// Show the menu when arrow key matches the popupSide
// direction -- but also allow RIGHT key for LEFT position and
// DOWN key for TOP position. To be symmetrical, we also allow for
// the LEFT key to work when in the RIGHT position. This is needed
// because the skin only paints right- and down-facing arrows in
// these cases.
button.show();
+ }
+ }
+
+ protected void openAction() {
+ if (getNode().isShowing()) {
+ getNode().hide();
} else {
- super.callAction(name);
+ getNode().show();
}
}
/***************************************************************************
* *
@@ -134,11 +122,11 @@
*
* @param e the mouse press event
* @param behaveLikeButton if true, this should act just like a button
*/
public void mousePressed(MouseEvent e, boolean behaveLikeButton) {
- final C control = getControl();
+ final C control = getNode();
/*
* Behaving like a button is easy - we just call super. But, we cannot
* call super if all we want to do is show the popup. The reason for
* this is that super also handles all the arm/disarm/fire logic, and
@@ -163,28 +151,22 @@
}
}
}
}
- @Override public void mouseReleased(MouseEvent e) {
- // Overriding to not call fire() on mouseReleased.
- // The event is handled by the skin instead, which calls
- // the method below.
- }
-
/**
* Handles mouse release events. This will be called by the skin.
*
* @param e the mouse press event
* @param behaveLikeButton if true, this should act just like a button
*/
public void mouseReleased(MouseEvent e, boolean behaveLikeButton) {
if (behaveLikeButton) {
super.mouseReleased(e);
} else {
- if (getControl().isShowing() && !getControl().contains(e.getX(), e.getY())) {
- getControl().hide();
+ if (getNode().isShowing() && !getNode().contains(e.getX(), e.getY())) {
+ getNode().hide();
}
- getControl().disarm();
+ getNode().disarm();
}
}
}