1 /* 2 * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package com.sun.javafx.scene.control; 26 27 import com.sun.javafx.scene.control.infrastructure.KeyEventFirer; 28 import com.sun.javafx.scene.control.infrastructure.MouseEventFirer; 29 import javafx.collections.ObservableList; 30 import javafx.scene.Node; 31 import javafx.scene.control.ContextMenu; 32 import javafx.scene.control.CustomMenuItem; 33 import javafx.scene.control.Menu; 34 import javafx.scene.control.MenuItem; 35 import javafx.scene.control.skin.ContextMenuSkin; 36 import javafx.scene.input.KeyCode; 37 38 import java.util.Optional; 39 40 public class ContextMenuContentRetriever { 41 42 private ContextMenuContentRetriever() { 43 // no-op 44 } 45 46 public static Menu getOpenSubMenu(ContextMenu menu) { 47 ContextMenuContent content = getMenuContent(menu); 48 return content.getOpenSubMenu(); 49 } 50 51 public static Menu getShowingSubMenu(ContextMenu menu) { 52 ContextMenuContent content = getMenuContent(menu); 53 Menu showingSubMenu = content.getOpenSubMenu(); 54 ContextMenu subContextMenu = content.getSubMenu(); 55 56 while (showingSubMenu != null) { 57 content = getMenuContent(subContextMenu); 58 59 Menu newShowingMenu = content == null ? null : content.getOpenSubMenu(); 60 subContextMenu = content == null ? null : content.getSubMenu(); 61 62 if (newShowingMenu == null) { 63 break; 64 } 65 } 66 return showingSubMenu; 67 } 68 69 public static ObservableList<MenuItem> getShowingMenuItems(ContextMenu menu) { 70 ContextMenuContent content = getMenuContent(menu); 71 Menu showingSubMenu = content.getOpenSubMenu(); 72 ContextMenu subContextMenu = content.getSubMenu(); 73 74 if (showingSubMenu == null || subContextMenu == null) { 75 return menu.getItems(); 76 } 77 78 while (showingSubMenu != null) { 79 content = getMenuContent(subContextMenu); 80 81 Menu newShowingMenu = content == null ? null : content.getOpenSubMenu(); 82 subContextMenu = content == null ? null : content.getSubMenu(); 83 84 if (newShowingMenu == null) { 85 break; 86 } 87 } 88 return showingSubMenu.getItems(); 89 } 90 91 public static Optional<ContextMenuContent> getShowingMenuContent(ContextMenu menu) { 92 ContextMenuContent content = getMenuContent(menu); 93 Menu showingSubMenu = content.getOpenSubMenu(); 94 ContextMenu subContextMenu = content.getSubMenu(); 95 return showingSubMenu != null && 96 subContextMenu != null && 97 subContextMenu.isShowing() ? getShowingMenuContent(subContextMenu) : Optional.of(content); 98 } 99 100 private static ContextMenuContent getMenuContent(ContextMenu menu) { 101 ContextMenuSkin skin = (ContextMenuSkin) menu.getSkin(); 102 Node node = skin.getNode(); 103 if (node instanceof ContextMenuContent) { 104 return (ContextMenuContent) node; 105 } 106 return null; 107 } 108 109 public static int getCurrentFocusedIndex(ContextMenu menu) { 110 // Optional<Integer> index = getShowingMenuContent(menu).flatMap(content -> Optional.of(content.getCurrentFocusIndex())); 111 // return index.orElse(-1); 112 113 Optional<ContextMenuContent> showingMenuContent = getShowingMenuContent(menu); 114 if (showingMenuContent.isPresent()) { 115 ContextMenuContent content = showingMenuContent.get(); 116 return content.getCurrentFocusIndex(); 117 } 118 119 return -1; 120 } 121 122 public static MenuItem getCurrentFocusedItem(ContextMenu menu) { 123 ObservableList<MenuItem> showingMenuItems = getShowingMenuItems(menu); 124 125 // Optional<MenuItem> item = getShowingMenuContent(menu) 126 // .flatMap(content -> Optional.of(content.getCurrentFocusIndex())) 127 // .flatMap(index -> Optional.of(showingMenuItems.get(index))); 128 // return item.orElse(null); 129 130 Optional<ContextMenuContent> showingMenuContent = getShowingMenuContent(menu); 131 if (showingMenuContent.isPresent()) { 132 ContextMenuContent content = showingMenuContent.get(); 133 int currentFocusIndex = content.getCurrentFocusIndex(); 134 return showingMenuItems.get(currentFocusIndex); 135 } 136 137 return null; 138 } 139 140 public static void pressDownKey(ContextMenu menu) { 141 // getShowingMenuContent(menu).ifPresent(content -> new KeyEventFirer(content).doDownArrowPress()); 142 Optional<ContextMenuContent> showingMenuContent = getShowingMenuContent(menu); 143 if (showingMenuContent.isPresent()) { 144 ContextMenuContent content = showingMenuContent.get(); 145 new KeyEventFirer(content).doDownArrowPress(); 146 } 147 } 148 149 public static void pressUpKey(ContextMenu menu) { 150 // getShowingMenuContent(menu).ifPresent(content -> new KeyEventFirer(content).doUpArrowPress()); 151 Optional<ContextMenuContent> showingMenuContent = getShowingMenuContent(menu); 152 if (showingMenuContent.isPresent()) { 153 ContextMenuContent content = showingMenuContent.get(); 154 new KeyEventFirer(content).doUpArrowPress(); 155 } 156 } 157 158 public static void pressLeftKey(ContextMenu menu) { 159 // getShowingMenuContent(menu).ifPresent(content -> new KeyEventFirer(content).doLeftArrowPress()); 160 Optional<ContextMenuContent> showingMenuContent = getShowingMenuContent(menu); 161 if (showingMenuContent.isPresent()) { 162 ContextMenuContent content = showingMenuContent.get(); 163 new KeyEventFirer(content).doLeftArrowPress(); 164 } 165 } 166 167 public static void pressRightKey(ContextMenu menu) { 168 // getShowingMenuContent(menu).ifPresent(content -> new KeyEventFirer(content).doRightArrowPress()); 169 Optional<ContextMenuContent> showingMenuContent = getShowingMenuContent(menu); 170 if (showingMenuContent.isPresent()) { 171 ContextMenuContent content = showingMenuContent.get(); 172 new KeyEventFirer(content).doRightArrowPress(); 173 } 174 } 175 176 public static void pressEnterKey(ContextMenu menu) { 177 // getShowingMenuContent(menu).ifPresent(content -> new KeyEventFirer(content).doKeyPress(KeyCode.ENTER)); 178 Optional<ContextMenuContent> showingMenuContent = getShowingMenuContent(menu); 179 if (showingMenuContent.isPresent()) { 180 ContextMenuContent content = showingMenuContent.get(); 181 new KeyEventFirer(content).doKeyPress(KeyCode.ENTER); 182 } 183 } 184 185 public static void pressMouseButton(ContextMenu menu) { 186 Optional<ContextMenuContent> showingMenuContent = getShowingMenuContent(menu); 187 if (showingMenuContent.isPresent()) { 188 ContextMenuContent.MenuItemContainer itemContainer = 189 (ContextMenuContent.MenuItemContainer) showingMenuContent.get().selectedBackground; 190 191 MenuItem item = itemContainer.getItem(); 192 if (item instanceof CustomMenuItem) { 193 // If the item is a CustomMenuItem, we fire the event on the 194 // content of that CustomMenuItem. 195 // Also, note that we firea mouse _clicked_ event, as opposed to 196 // a press and release. I'm not sure why this is what the 197 // ContextMenuContent code expects, but I didn't want to mess with 198 // it at this point. 199 Node customContent = ((CustomMenuItem)item).getContent(); 200 new MouseEventFirer(customContent).fireMouseClicked(); 201 } else { 202 new MouseEventFirer(itemContainer).fireMousePressAndRelease(); 203 } 204 } 205 } 206 }