1 /* 2 * Copyright (c) 2010, 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 26 package javafx.scene.control; 27 28 import static org.junit.Assert.assertEquals; 29 import static org.junit.Assert.assertFalse; 30 import static org.junit.Assert.assertTrue; 31 32 import javafx.scene.Node; 33 import javafx.scene.Parent; 34 import javafx.scene.Scene; 35 import javafx.scene.control.skin.MenuBarSkinRetriever; 36 import javafx.scene.input.KeyCode; 37 import javafx.scene.input.MouseEvent; 38 import javafx.scene.layout.AnchorPane; 39 import javafx.scene.layout.VBox; 40 import javafx.stage.Stage; 41 42 import org.junit.Before; 43 import org.junit.Test; 44 45 import com.sun.javafx.pgstub.StubToolkit; 46 import com.sun.javafx.scene.control.infrastructure.KeyEventFirer; 47 import com.sun.javafx.scene.control.infrastructure.MouseEventGenerator; 48 import com.sun.javafx.scene.control.ContextMenuContent; 49 import com.sun.javafx.scene.control.MenuBarMenuButtonRetriever; 50 import javafx.scene.control.skin.MenuBarSkin; 51 import com.sun.javafx.tk.Toolkit; 52 53 54 /** 55 * 56 * @author lubermud 57 */ 58 59 public class MenuBarTest { 60 private MenuBar menuBar; 61 private Toolkit tk; 62 private Scene scene; 63 private Stage stage; 64 65 @Before public void setup() { 66 tk = (StubToolkit)Toolkit.getToolkit(); 67 menuBar = new MenuBar(); 68 menuBar.setUseSystemMenuBar(false); 69 } 70 71 protected void startApp(Parent root) { 72 scene = new Scene(root,800,600); 73 stage = new Stage(); 74 stage.setX(0); // The MouseEventGenerator set the screen X/Y to be the same as local Node X/Y, so we need to keep stage at 0,0 75 stage.setY(0); 76 stage.setScene(scene); 77 stage.show(); 78 tk.firePulse(); 79 } 80 81 @Test public void defaultConstructorHasFalseFocusTraversable() { 82 assertFalse(menuBar.isFocusTraversable()); 83 } 84 85 @Test public void defaultConstructorButSetTrueFocusTraversable() { 86 menuBar.setFocusTraversable(true); 87 assertTrue(menuBar.isFocusTraversable()); 88 } 89 90 @Test public void getMenusHasSizeZero() { 91 assertEquals(0, menuBar.getMenus().size()); 92 } 93 94 @Test public void getMenusIsAddable() { 95 menuBar.getMenus().add(new Menu("")); 96 assertTrue(menuBar.getMenus().size() > 0); 97 } 98 99 @Test public void getMenusIsClearable() { 100 menuBar.getMenus().add(new Menu("")); 101 menuBar.getMenus().clear(); 102 assertEquals(0, menuBar.getMenus().size()); 103 } 104 105 @Test public void getMenusIsRemovable() { 106 menuBar.getMenus().add(new Menu("blah")); 107 menuBar.getMenus().add(new Menu("foo")); 108 menuBar.getMenus().remove(0); 109 assertEquals(1, menuBar.getMenus().size()); 110 } 111 112 @Test public void testMenuShowHideWithMenuBarWithXYTranslation() { 113 final MouseEventGenerator generator = new MouseEventGenerator(); 114 AnchorPane root = new AnchorPane(); 115 Menu menu = new Menu("Menu"); 116 menu.getItems().add(new MenuItem("MenuItem")); 117 menuBar.getMenus().add(menu); 118 menuBar.setLayoutX(100); 119 menuBar.setLayoutY(100); 120 root.getChildren().add(menuBar); 121 startApp(root); 122 tk.firePulse(); 123 124 MenuBarSkin skin = (MenuBarSkin)menuBar.getSkin(); 125 assertTrue(skin != null); 126 127 double xval = (menuBar.localToScene(menuBar.getLayoutBounds())).getMinX(); 128 double yval = (menuBar.localToScene(menuBar.getLayoutBounds())).getMinY(); 129 130 MenuButton mb = MenuBarSkinRetriever.getNodeForMenu(skin, 0); 131 mb.getScene().getWindow().requestFocus(); 132 scene.impl_processMouseEvent( 133 generator.generateMouseEvent(MouseEvent.MOUSE_PRESSED, xval+20, yval+20)); 134 scene.impl_processMouseEvent( 135 generator.generateMouseEvent(MouseEvent.MOUSE_RELEASED, xval+20, yval+20)); 136 assertTrue(menu.isShowing()); 137 138 } 139 140 @Test public void testSubMenuDismissalWithKeyNavigation() { 141 final MouseEventGenerator generator = new MouseEventGenerator(); 142 AnchorPane root = new AnchorPane(); 143 Menu menu = new Menu("Menu"); 144 Menu menu1 = new Menu("Menu With SubMenu"); 145 menu.getItems().add(menu1); 146 147 MenuItem menuItem1 = new MenuItem("MenuItem1"); 148 MenuItem menuItem2 = new MenuItem("MenuItem2"); 149 menu1.getItems().addAll(menuItem1, menuItem2); 150 151 menuBar.getMenus().add(menu); 152 menuBar.setLayoutX(100); 153 menuBar.setLayoutY(100); 154 155 root.getChildren().add(menuBar); 156 startApp(root); 157 tk.firePulse(); 158 159 MenuBarSkin skin = (MenuBarSkin)menuBar.getSkin(); 160 assertTrue(skin != null); 161 162 double xval = (menuBar.localToScene(menuBar.getLayoutBounds())).getMinX(); 163 double yval = (menuBar.localToScene(menuBar.getLayoutBounds())).getMinY(); 164 165 MenuButton mb = MenuBarSkinRetriever.getNodeForMenu(skin, 0); 166 mb.getScene().getWindow().requestFocus(); 167 scene.impl_processMouseEvent( 168 generator.generateMouseEvent(MouseEvent.MOUSE_PRESSED, xval+20, yval+20)); 169 scene.impl_processMouseEvent( 170 generator.generateMouseEvent(MouseEvent.MOUSE_RELEASED, xval+20, yval+20)); 171 assertTrue(menu.isShowing()); 172 /* ------------------------------------------------------------------ */ 173 174 // Show subMenu 175 ContextMenuContent menuContent = MenuBarSkinRetriever.getMenuContent(mb); // ContextMenuContent 176 Node displayNode = MenuBarMenuButtonRetriever.getDisplayNodeForMenuItem(menuContent, 0); // MenuItemContainer 177 178 displayNode.getScene().getWindow().requestFocus(); 179 assertTrue(displayNode.getScene().getWindow().isFocused()); 180 181 displayNode.requestFocus(); // requestFocus on 1st Menu 182 assertTrue(displayNode.isFocused()); 183 // update currentFocusedIndex 184 MenuBarMenuButtonRetriever.setCurrentFocusedIndex(menuContent, 0); 185 186 // fire KeyEvent (Enter) on menu1 to show submenu 187 KeyEventFirer keyboard = new KeyEventFirer(menuContent); 188 keyboard.doKeyPress(KeyCode.ENTER); 189 tk.firePulse(); 190 assertTrue(menu1.isShowing()); // subMenu is showing 191 /* ------------------------------------------------------------------ */ 192 193 // Get 1st MenuItem from the submenu 194 ContextMenuContent subMenuContent = MenuBarMenuButtonRetriever.getSubMenuContent(menuContent); 195 subMenuContent.getScene().getWindow().requestFocus(); // requestFocus on submenu 196 assertTrue(subMenuContent.getScene().getWindow().isFocused()); 197 198 displayNode = MenuBarMenuButtonRetriever.getDisplayNodeForMenuItem(subMenuContent, 0); 199 displayNode.requestFocus(); 200 assertTrue(displayNode.isFocused()); 201 202 MenuBarMenuButtonRetriever.setCurrentFocusedIndex(subMenuContent, 0); 203 // fire KeyEvent (Enter) on menuItem1 to hide all menus 204 keyboard = new KeyEventFirer(subMenuContent); 205 keyboard.doKeyPress(KeyCode.ENTER); 206 tk.firePulse(); 207 208 // confirm all menus are closed. 209 assertTrue(!menu1.isShowing()); 210 assertTrue(!menu.isShowing()); 211 } 212 213 @Test public void checkMenuBarMenusSelectionResetAfterMenuItemIsSelected() { 214 final MouseEventGenerator generator = new MouseEventGenerator(); 215 AnchorPane root = new AnchorPane(); 216 Menu menu = new Menu("Menu"); 217 MenuItem menuItem = new MenuItem("MenuItem"); 218 menu.getItems().add(menuItem); 219 220 menuBar.getMenus().add(menu); 221 menuBar.setLayoutX(100); 222 menuBar.setLayoutY(100); 223 224 root.getChildren().addAll(menuBar); 225 226 startApp(root); 227 tk.firePulse(); 228 229 MenuBarSkin skin = (MenuBarSkin)menuBar.getSkin(); 230 assertTrue(skin != null); 231 MenuButton mb = MenuBarSkinRetriever.getNodeForMenu(skin, 0); 232 mb.getScene().getWindow().requestFocus(); 233 234 double xval = (menuBar.localToScene(menuBar.getLayoutBounds())).getMinX(); 235 double yval = (menuBar.localToScene(menuBar.getLayoutBounds())).getMinY(); 236 237 scene.impl_processMouseEvent( 238 generator.generateMouseEvent(MouseEvent.MOUSE_PRESSED, xval+20, yval+20)); 239 scene.impl_processMouseEvent( 240 generator.generateMouseEvent(MouseEvent.MOUSE_RELEASED, xval+20, yval+20)); 241 assertTrue(menu.isShowing()); 242 /* ------------------------------------------------------------------ */ 243 244 // Show Menu 245 ContextMenuContent menuContent = MenuBarSkinRetriever.getMenuContent(mb); // ContextMenuContent 246 Node displayNode = MenuBarMenuButtonRetriever.getDisplayNodeForMenuItem(menuContent, 0); // MenuItemContainer 247 248 displayNode.getScene().getWindow().requestFocus(); 249 assertTrue(displayNode.getScene().getWindow().isFocused()); 250 251 displayNode.requestFocus(); // requestFocus on 1st Menu 252 assertTrue(displayNode.isFocused()); 253 254 // fire KeyEvent (Enter) on menuitem 255 KeyEventFirer keyboard = new KeyEventFirer(menuContent); 256 keyboard.doKeyPress(KeyCode.ENTER); 257 tk.firePulse(); 258 259 // confirm menu is closed. 260 assertTrue(!menu.isShowing()); 261 keyboard.doKeyPress(KeyCode.LEFT); 262 tk.firePulse(); 263 264 // check if focusedMenuIndex is reset to -1 so navigation happens. 265 int focusedIndex = MenuBarSkinRetriever.getFocusedIndex(skin); 266 assertEquals(focusedIndex, -1); 267 } 268 269 @Test public void testMenuOnShownEventFiringWithKeyNavigation() { 270 final MouseEventGenerator generator = new MouseEventGenerator(); 271 VBox root = new VBox(); 272 Menu menu = new Menu("Menu"); 273 274 MenuItem menuItem1 = new MenuItem("MenuItem1"); 275 MenuItem menuItem2 = new MenuItem("MenuItem2"); 276 menu.getItems().addAll(menuItem1, menuItem2); 277 278 menuBar.getMenus().add(menu); 279 menuBar.setLayoutX(100); 280 menuBar.setLayoutY(100); 281 282 final CheckBox cb = new CheckBox("showing"); 283 284 root.getChildren().addAll(cb,menuBar); 285 startApp(root); 286 tk.firePulse(); 287 288 MenuBarSkin skin = (MenuBarSkin)menuBar.getSkin(); 289 assertTrue(skin != null); 290 291 MenuButton mb = MenuBarSkinRetriever.getNodeForMenu(skin, 0); 292 mb.getScene().getWindow().requestFocus(); 293 assertTrue(mb.getScene().getWindow().isFocused()); 294 295 296 KeyEventFirer keyboard = new KeyEventFirer(mb.getScene()); 297 keyboard.doKeyPress(KeyCode.TAB); 298 tk.firePulse(); 299 mb.requestFocus(); 300 assertTrue(mb.isFocused()); 301 302 keyboard = new KeyEventFirer(mb); 303 keyboard.doDownArrowPress(); 304 tk.firePulse(); 305 assertEquals(menu.showingProperty().get(), true); 306 } 307 308 @Test public void testKeyNavigationWithDisabledMenuItem() { 309 VBox root = new VBox(); 310 Menu menu1 = new Menu("Menu1"); 311 Menu menu2 = new Menu("Menu2"); 312 Menu menu3 = new Menu("Menu3"); 313 314 MenuItem menuItem1 = new MenuItem("MenuItem1"); 315 MenuItem menuItem2 = new MenuItem("MenuItem2"); 316 MenuItem menuItem3 = new MenuItem("MenuItem3"); 317 318 menu1.getItems().add(menuItem1); 319 menu2.getItems().add(menuItem2); 320 menu3.getItems().add(menuItem3); 321 322 menuBar.getMenus().addAll(menu1, menu2, menu3); 323 menu2.setDisable(true); 324 325 root.getChildren().addAll(menuBar); 326 startApp(root); 327 tk.firePulse(); 328 329 MenuBarSkin skin = (MenuBarSkin)menuBar.getSkin(); 330 assertTrue(skin != null); 331 332 double xval = (menuBar.localToScene(menuBar.getLayoutBounds())).getMinX(); 333 double yval = (menuBar.localToScene(menuBar.getLayoutBounds())).getMinY(); 334 335 MenuButton mb = MenuBarSkinRetriever.getNodeForMenu(skin, 0); 336 mb.getScene().getWindow().requestFocus(); 337 scene.impl_processMouseEvent( 338 MouseEventGenerator.generateMouseEvent(MouseEvent.MOUSE_PRESSED, xval+20, yval+20)); 339 scene.impl_processMouseEvent( 340 MouseEventGenerator.generateMouseEvent(MouseEvent.MOUSE_RELEASED, xval+20, yval+20)); 341 assertTrue(menu1.isShowing()); 342 343 KeyEventFirer keyboard = new KeyEventFirer(mb.getScene()); 344 keyboard.doKeyPress(KeyCode.RIGHT); 345 tk.firePulse(); 346 assertTrue(menu3.isShowing()); 347 } 348 349 350 @Test public void testMenuOnShowingEventFiringWithMenuHideOperation() { 351 VBox root = new VBox(); 352 Menu menu = new Menu("Menu"); 353 354 MenuItem menuItem1 = new MenuItem("MenuItem1"); 355 menu.getItems().addAll(menuItem1); 356 357 menuBar.getMenus().add(menu); 358 menuBar.setLayoutX(100); 359 menuBar.setLayoutY(100); 360 361 root.getChildren().addAll(menuBar); 362 startApp(root); 363 tk.firePulse(); 364 365 MenuBarSkin skin = (MenuBarSkin)menuBar.getSkin(); 366 assertTrue(skin != null); 367 double xval = (menuBar.localToScene(menuBar.getLayoutBounds())).getMinX(); 368 double yval = (menuBar.localToScene(menuBar.getLayoutBounds())).getMinY(); 369 370 boolean click = true; 371 final Boolean firstClick = new Boolean(click); 372 373 menu.setOnShowing(t -> { 374 // we should not get here when the menu is hidden 375 assertEquals(firstClick.booleanValue(), true); 376 }); 377 378 MenuButton mb = MenuBarSkinRetriever.getNodeForMenu(skin, 0); 379 mb.getScene().getWindow().requestFocus(); 380 mb.requestFocus(); 381 assertTrue(mb.isFocused()); 382 // click on menu to show 383 scene.impl_processMouseEvent( 384 MouseEventGenerator.generateMouseEvent(MouseEvent.MOUSE_PRESSED, xval+20, yval+20)); 385 scene.impl_processMouseEvent( 386 MouseEventGenerator.generateMouseEvent(MouseEvent.MOUSE_RELEASED, xval+20, yval+20)); 387 tk.firePulse(); 388 assertEquals(menu.showingProperty().get(), true); 389 click = false; 390 // click on menu to hide 391 scene.impl_processMouseEvent( 392 MouseEventGenerator.generateMouseEvent(MouseEvent.MOUSE_PRESSED, xval+20, yval+20)); 393 scene.impl_processMouseEvent( 394 MouseEventGenerator.generateMouseEvent(MouseEvent.MOUSE_RELEASED, xval+20, yval+20)); 395 tk.firePulse(); 396 assertEquals(menu.showingProperty().get(), false); 397 } 398 399 @Test public void testRemovingMenuItemFromMenuNotInScene() { 400 VBox root = new VBox(); 401 Menu menu = new Menu("Menu"); 402 403 MenuItem menuItem1 = new MenuItem("MenuItem1"); 404 menu.getItems().addAll(menuItem1); 405 406 menuBar.getMenus().add(menu); 407 root.getChildren().addAll(menuBar); 408 startApp(root); 409 tk.firePulse(); 410 411 // remove menu from menubar 412 menuBar.getMenus().remove(menu); 413 //remove menuitem from menu that was just removed itself. 414 menu.getItems().remove(menuItem1); 415 assertEquals(true, menu.getItems().isEmpty()); 416 } 417 418 @Test public void test_rt_37118() { 419 MenuBar menuBar = new MenuBar(); 420 MenuBarSkin menuBarSkin = new MenuBarSkin(menuBar); 421 } 422 }