modules/controls/src/main/java/com/sun/javafx/scene/control/ContextMenuContent.java

Print this page
rev 9240 : 8076423: JEP 253: Prepare JavaFX UI Controls & CSS APIs for Modularization

*** 21,34 **** * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ ! package com.sun.javafx.scene.control.skin; - import com.sun.javafx.scene.control.MultiplePropertyChangeListenerHandler; import com.sun.javafx.scene.control.behavior.TwoLevelFocusPopupBehavior; import javafx.animation.Animation.Status; import javafx.animation.KeyFrame; import javafx.animation.Timeline; import javafx.beans.InvalidationListener; import javafx.beans.WeakInvalidationListener; --- 21,34 ---- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ ! package com.sun.javafx.scene.control; import com.sun.javafx.scene.control.behavior.TwoLevelFocusPopupBehavior; + import com.sun.javafx.scene.control.skin.Utils; import javafx.animation.Animation.Status; import javafx.animation.KeyFrame; import javafx.animation.Timeline; import javafx.beans.InvalidationListener; import javafx.beans.WeakInvalidationListener;
*** 47,56 **** --- 47,57 ---- import javafx.scene.AccessibleAttribute; import javafx.scene.AccessibleRole; import javafx.scene.Node; import javafx.scene.Parent; import javafx.scene.control.*; + import javafx.scene.control.skin.MenuBarSkin; import javafx.scene.input.KeyEvent; import javafx.scene.input.MouseEvent; import javafx.scene.input.ScrollEvent; import javafx.scene.layout.Region; import javafx.scene.layout.StackPane;
*** 515,525 **** // menu - this will move focus up to the parent menu // as required. In the case of the parent being a // menubar button we special case in the conditional code // beneath this switch statement. See RT-34429 for more context. final Node ownerNode = contextMenu.getOwnerNode(); ! if (! (ownerNode instanceof MenuBarSkin.MenuBarButton)) { contextMenu.hide(); ke.consume(); } break; case DOWN: --- 516,526 ---- // menu - this will move focus up to the parent menu // as required. In the case of the parent being a // menubar button we special case in the conditional code // beneath this switch statement. See RT-34429 for more context. final Node ownerNode = contextMenu.getOwnerNode(); ! if (! (ownerNode instanceof MenuBarButton)) { contextMenu.hide(); ke.consume(); } break; case DOWN:
*** 551,566 **** parent = parent.getParent(); } if (parent instanceof ContextMenuContent) { parent.getOnKeyPressed().handle(ke); } ! } else if (ownerNode instanceof MenuBarSkin.MenuBarButton) { ! // This is a top-level MenuBar Menu, so forward event to MenuBar ! MenuBarSkin mbs = ((MenuBarSkin.MenuBarButton)ownerNode).getMenuBarSkin(); ! if (mbs != null && mbs.getKeyEventHandler() != null) { ! mbs.getKeyEventHandler().handle(ke); ! } } } } }); --- 552,569 ---- parent = parent.getParent(); } if (parent instanceof ContextMenuContent) { parent.getOnKeyPressed().handle(ke); } ! } else if (ownerNode instanceof MenuBarButton) { ! // the following code no longer appears necessary, but ! // leaving in intact for now... ! // // This is a top-level MenuBar Menu, so forward event to MenuBar ! // MenuBarSkin mbs = ((MenuBarButton)ownerNode).getMenuBarSkin(); ! // if (mbs != null && mbs.getKeyEventHandler() != null) { ! // mbs.getKeyEventHandler().handle(ke); ! // } } } } });
*** 759,769 **** /* * Get the Y offset from the top of the popup to the menu item whose index * is given. */ ! double getMenuYOffset(int menuIndex) { double offset = 0; if (itemsContainer.getChildren().size() > menuIndex) { offset = snappedTopInset(); Node menuitem = itemsContainer.getChildren().get(menuIndex); offset += menuitem.getLayoutY() + menuitem.prefHeight(-1); --- 762,772 ---- /* * Get the Y offset from the top of the popup to the menu item whose index * is given. */ ! public double getMenuYOffset(int menuIndex) { double offset = 0; if (itemsContainer.getChildren().size() > menuIndex) { offset = snappedTopInset(); Node menuitem = itemsContainer.getChildren().get(menuIndex); offset += menuitem.getLayoutY() + menuitem.prefHeight(-1);
*** 983,993 **** @Override public List<CssMetaData<? extends Styleable, ?>> getCssMetaData() { return getClassCssMetaData(); } ! protected Label getLabelAt(int index) { return ((MenuItemContainer)itemsContainer.getChildren().get(index)).getLabel(); } /** * Custom VBox to enable scrolling of items. Scrolling effect is achieved by --- 986,996 ---- @Override public List<CssMetaData<? extends Styleable, ?>> getCssMetaData() { return getClassCssMetaData(); } ! public Label getLabelAt(int index) { return ((MenuItemContainer)itemsContainer.getChildren().get(index)).getLabel(); } /** * Custom VBox to enable scrolling of items. Scrolling effect is achieved by
*** 1110,1124 **** private Node left; private Node graphic; private Node label; private Node right; ! private final MultiplePropertyChangeListenerHandler listener = ! new MultiplePropertyChangeListenerHandler(param -> { ! handlePropertyChanged(param); ! return null; ! }); private EventHandler<MouseEvent> mouseEnteredEventHandler; private EventHandler<MouseEvent> mouseReleasedEventHandler; private EventHandler<ActionEvent> actionEventHandler; --- 1113,1124 ---- private Node left; private Node graphic; private Node label; private Node right; ! private final LambdaMultiplePropertyChangeListenerHandler listener = ! new LambdaMultiplePropertyChangeListenerHandler(); private EventHandler<MouseEvent> mouseEnteredEventHandler; private EventHandler<MouseEvent> mouseReleasedEventHandler; private EventHandler<ActionEvent> actionEventHandler;
*** 1145,1179 **** // listen to changes in the state of certain MenuItem types ReadOnlyBooleanProperty pseudoProperty; if (item instanceof Menu) { pseudoProperty = ((Menu)item).showingProperty(); ! listener.registerChangeListener(pseudoProperty, "MENU_SHOWING"); pseudoClassStateChanged(SELECTED_PSEUDOCLASS_STATE, pseudoProperty.get()); setAccessibleRole(AccessibleRole.MENU); } else if (item instanceof RadioMenuItem) { pseudoProperty = ((RadioMenuItem)item).selectedProperty(); ! listener.registerChangeListener(pseudoProperty, "RADIO_ITEM_SELECTED"); pseudoClassStateChanged(CHECKED_PSEUDOCLASS_STATE, pseudoProperty.get()); setAccessibleRole(AccessibleRole.RADIO_MENU_ITEM); } else if (item instanceof CheckMenuItem) { pseudoProperty = ((CheckMenuItem)item).selectedProperty(); ! listener.registerChangeListener(pseudoProperty, "CHECK_ITEM_SELECTED"); pseudoClassStateChanged(CHECKED_PSEUDOCLASS_STATE, pseudoProperty.get()); setAccessibleRole(AccessibleRole.CHECK_MENU_ITEM); } else { setAccessibleRole(AccessibleRole.MENU_ITEM); } pseudoClassStateChanged(DISABLED_PSEUDOCLASS_STATE, item.disableProperty().get()); ! listener.registerChangeListener(item.disableProperty(), "DISABLE"); // Add the menu item to properties map of this node. Used by QA for testing // This allows associating this container with corresponding MenuItem. getProperties().put(MenuItem.class, item); ! listener.registerChangeListener(item.graphicProperty(), "GRAPHIC"); actionEventHandler = e -> { if (item instanceof Menu) { final Menu menu = (Menu) item; if (openSubmenu == menu && submenu.isShowing()) return; --- 1145,1186 ---- // listen to changes in the state of certain MenuItem types ReadOnlyBooleanProperty pseudoProperty; if (item instanceof Menu) { pseudoProperty = ((Menu)item).showingProperty(); ! listener.registerChangeListener(pseudoProperty, ! e -> pseudoClassStateChanged(SELECTED_PSEUDOCLASS_STATE, ((Menu) item).isShowing())); pseudoClassStateChanged(SELECTED_PSEUDOCLASS_STATE, pseudoProperty.get()); setAccessibleRole(AccessibleRole.MENU); } else if (item instanceof RadioMenuItem) { pseudoProperty = ((RadioMenuItem)item).selectedProperty(); ! listener.registerChangeListener(pseudoProperty, ! e -> pseudoClassStateChanged(CHECKED_PSEUDOCLASS_STATE, ((RadioMenuItem) item).isSelected())); pseudoClassStateChanged(CHECKED_PSEUDOCLASS_STATE, pseudoProperty.get()); setAccessibleRole(AccessibleRole.RADIO_MENU_ITEM); } else if (item instanceof CheckMenuItem) { pseudoProperty = ((CheckMenuItem)item).selectedProperty(); ! listener.registerChangeListener(pseudoProperty, ! e -> pseudoClassStateChanged(CHECKED_PSEUDOCLASS_STATE, ((CheckMenuItem) item).isSelected())); pseudoClassStateChanged(CHECKED_PSEUDOCLASS_STATE, pseudoProperty.get()); setAccessibleRole(AccessibleRole.CHECK_MENU_ITEM); } else { setAccessibleRole(AccessibleRole.MENU_ITEM); } pseudoClassStateChanged(DISABLED_PSEUDOCLASS_STATE, item.disableProperty().get()); ! listener.registerChangeListener(item.disableProperty(), ! e -> pseudoClassStateChanged(DISABLED_PSEUDOCLASS_STATE, item.isDisable())); // Add the menu item to properties map of this node. Used by QA for testing // This allows associating this container with corresponding MenuItem. getProperties().put(MenuItem.class, item); ! listener.registerChangeListener(item.graphicProperty(), e -> { ! createChildren(); ! computeVisualMetrics(); ! }); actionEventHandler = e -> { if (item instanceof Menu) { final Menu menu = (Menu) item; if (openSubmenu == menu && submenu.isShowing()) return;
*** 1209,1242 **** graphic = null; label = null; right = null; } - private void handlePropertyChanged(String p) { - if ("MENU_SHOWING".equals(p)) { - Menu menu = (Menu) item; - pseudoClassStateChanged(SELECTED_PSEUDOCLASS_STATE, menu.isShowing()); - } else if ("RADIO_ITEM_SELECTED".equals(p)) { - RadioMenuItem radioItem = (RadioMenuItem) item; - pseudoClassStateChanged(CHECKED_PSEUDOCLASS_STATE, radioItem.isSelected()); - } else if ("CHECK_ITEM_SELECTED".equals(p)) { - CheckMenuItem checkItem = (CheckMenuItem) item; - pseudoClassStateChanged(CHECKED_PSEUDOCLASS_STATE, checkItem.isSelected()); - } else if ("DISABLE".equals(p)) { - pseudoClassStateChanged(DISABLED_PSEUDOCLASS_STATE, item.isDisable()); - } else if ("GRAPHIC".equals(p)) { - createChildren(); - computeVisualMetrics(); - } else if ("ACCELERATOR".equals(p)) { - updateAccelerator(); - } else if ("FOCUSED".equals(p)) { - if (isFocused()) { - currentFocusedIndex = itemsContainer.getChildren().indexOf(MenuItemContainer.this); - } - } - } - private void createChildren() { getChildren().clear(); // draw background region for hover effects. All content (other // than Nodes from NodeMenuItems) are set to be mouseTransparent, so --- 1216,1225 ----
*** 1285,1295 **** listener.unregisterChangeListener(focusedProperty()); // RT-19546 update currentFocusedIndex when MenuItemContainer gets focused. // e.g this happens when you press the Right key to open a submenu; the first // menuitem is focused. ! listener.registerChangeListener(focusedProperty(), "FOCUSED"); // --- draw in right column - this depends on whether we are // a Menu or not. A Menu gets an arrow, whereas other MenuItems // get the ability to draw an accelerator if (item instanceof Menu) { --- 1268,1282 ---- listener.unregisterChangeListener(focusedProperty()); // RT-19546 update currentFocusedIndex when MenuItemContainer gets focused. // e.g this happens when you press the Right key to open a submenu; the first // menuitem is focused. ! listener.registerChangeListener(focusedProperty(), e -> { ! if (isFocused()) { ! currentFocusedIndex = itemsContainer.getChildren().indexOf(MenuItemContainer.this); ! } ! }); // --- draw in right column - this depends on whether we are // a Menu or not. A Menu gets an arrow, whereas other MenuItems // get the ability to draw an accelerator if (item instanceof Menu) {
*** 1362,1372 **** } addEventHandler(MouseEvent.MOUSE_ENTERED, mouseEnteredEventHandler); addEventHandler(MouseEvent.MOUSE_RELEASED, mouseReleasedEventHandler); ! listener.registerChangeListener(item.acceleratorProperty(), "ACCELERATOR"); } } } private void updateAccelerator() { --- 1349,1359 ---- } addEventHandler(MouseEvent.MOUSE_ENTERED, mouseEnteredEventHandler); addEventHandler(MouseEvent.MOUSE_RELEASED, mouseReleasedEventHandler); ! listener.registerChangeListener(item.acceleratorProperty(), e -> updateAccelerator()); } } } private void updateAccelerator() {