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