1 /* 2 * Copyright (c) 2011, 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 test.com.sun.javafx.scene.traversal; 27 28 import com.sun.javafx.scene.traversal.Algorithm; 29 import com.sun.javafx.scene.traversal.ContainerTabOrder; 30 import com.sun.javafx.scene.traversal.ContainerTabOrderShim; 31 import com.sun.javafx.scene.traversal.Direction; 32 import com.sun.javafx.scene.traversal.ParentTraversalEngine; 33 import com.sun.javafx.scene.traversal.TopMostTraversalEngine; 34 import com.sun.javafx.scene.traversal.TopMostTraversalEngineShim; 35 import com.sun.javafx.scene.traversal.TraversalContext; 36 import javafx.scene.Group; 37 import javafx.scene.Node; 38 import javafx.scene.Parent; 39 import javafx.scene.ParentShim; 40 import javafx.scene.shape.Rectangle; 41 import org.junit.Before; 42 import org.junit.Test; 43 44 import static org.junit.Assert.assertEquals; 45 import static org.junit.Assert.fail; 46 47 public class TopMostTraversalEngineTest { 48 private TopMostTraversalEngineShim engine; 49 private Group root; 50 51 @Before 52 public void setUp() { 53 root = new Group(); 54 engine = new TopMostTraversalEngineShim(new ContainerTabOrderShim()) { 55 @Override 56 protected Parent getRoot() { 57 return root; 58 } 59 }; 60 } 61 62 @Test 63 public void selectFirst() { 64 final Node focusableNode = createFocusableNode(); 65 Group g = new Group(focusableNode, createFocusableNode()); 66 ParentShim.getChildren(root).add(g); 67 68 assertEquals(focusableNode, engine.selectFirst()); 69 } 70 71 @Test 72 public void selectFirstSkipInvisible() { 73 final Node n1 = createFocusableDisabledNode(); 74 final Node n2 = createFocusableNode(); 75 ParentShim.getChildren(root).addAll(n1, n2); 76 77 assertEquals(n2, engine.selectFirst()); 78 } 79 80 @Test 81 public void selectFirstUseParentEngine() { 82 Group g = new Group(createFocusableNode()); 83 g.setImpl_traversalEngine(new ParentTraversalEngine(g, new Algorithm() { 84 @Override 85 public Node select(Node owner, Direction dir, TraversalContext context) { 86 return null; 87 } 88 89 @Override 90 public Node selectFirst(TraversalContext context) { 91 return null; 92 } 93 94 @Override 95 public Node selectLast(TraversalContext context) { 96 return null; 97 } 98 })); 99 g.setDisable(true); 100 ParentShim.getChildren(root).add(g); 101 102 final Node focusableNode = createFocusableNode(); 103 g = new Group(createFocusableNode(), focusableNode, createFocusableNode()); 104 g.setImpl_traversalEngine(new ParentTraversalEngine(g, new Algorithm() { 105 @Override 106 public Node select(Node owner, Direction dir, TraversalContext context) { 107 fail(); 108 return null; 109 } 110 111 @Override 112 public Node selectFirst(TraversalContext context) { 113 return focusableNode; 114 } 115 116 @Override 117 public Node selectLast(TraversalContext context) { 118 fail(); 119 return null; 120 } 121 })); 122 123 ParentShim.getChildren(root).add(g); 124 125 assertEquals(focusableNode, engine.selectFirst()); 126 } 127 128 @Test 129 public void selectFirstFocusableParent() { 130 Group g = new Group(createFocusableNode(), createFocusableNode()); 131 g.setFocusTraversable(true); 132 ParentShim.getChildren(root).add(g); 133 134 assertEquals(g, engine.selectFirst()); 135 } 136 137 @Test 138 public void selectFirstTraverseOverride() { 139 Group g = new Group(createFocusableNode(), createFocusableNode()); 140 g.setFocusTraversable(true); 141 final ParentTraversalEngine pEngine = new ParentTraversalEngine(g); 142 pEngine.setOverriddenFocusTraversability(false); 143 g.setImpl_traversalEngine(pEngine); 144 145 ParentShim.getChildren(root).add(g); 146 147 assertEquals(ParentShim.getChildren(g).get(0), engine.selectFirst()); 148 } 149 150 151 @Test 152 public void selectLast() { 153 final Node focusableNode = createFocusableNode(); 154 Group g = new Group(createFocusableNode(), focusableNode); 155 ParentShim.getChildren(root).add(g); 156 157 assertEquals(focusableNode, engine.selectLast()); 158 } 159 160 @Test 161 public void selectLastSkipInvisible() { 162 final Node n1 = createFocusableNode(); 163 final Node n2 = createFocusableDisabledNode(); 164 ParentShim.getChildren(root).addAll(n1, n2); 165 166 assertEquals(n1, engine.selectFirst()); 167 } 168 169 @Test 170 public void selectLastUseParentEngine() { 171 final Node focusableNode = createFocusableNode(); 172 Group g = new Group(createFocusableNode(), focusableNode, createFocusableNode()); 173 g.setImpl_traversalEngine(new ParentTraversalEngine(g, new Algorithm() { 174 @Override 175 public Node select(Node owner, Direction dir, TraversalContext context) { 176 fail(); 177 return null; 178 } 179 180 @Override 181 public Node selectFirst(TraversalContext context) { 182 fail(); 183 return null; 184 } 185 186 @Override 187 public Node selectLast(TraversalContext context) { 188 return focusableNode; 189 } 190 })); 191 192 ParentShim.getChildren(root).add(g); 193 194 195 g = new Group(createFocusableNode()); 196 g.setImpl_traversalEngine(new ParentTraversalEngine(g, new Algorithm() { 197 @Override 198 public Node select(Node owner, Direction dir, TraversalContext context) { 199 return null; 200 } 201 202 @Override 203 public Node selectFirst(TraversalContext context) { 204 return null; 205 } 206 207 @Override 208 public Node selectLast(TraversalContext context) { 209 return null; 210 } 211 })); 212 g.setDisable(true); 213 ParentShim.getChildren(root).add(g); 214 215 216 assertEquals(focusableNode, engine.selectLast()); 217 } 218 219 @Test 220 public void selectLastFocusableParent() { 221 final Node focusableNode = createFocusableNode(); 222 Group g = new Group(createFocusableNode(), focusableNode); 223 g.setFocusTraversable(true); 224 ParentShim.getChildren(root).add(g); 225 226 assertEquals(focusableNode, engine.selectLast()); 227 } 228 229 @Test 230 public void selectLastFocusableParent_2() { 231 Group g = new Group(new Rectangle()); 232 g.setFocusTraversable(true); 233 ParentShim.getChildren(root).add(g); 234 235 assertEquals(g, engine.selectLast()); 236 } 237 238 @Test 239 public void selectLastTraverseOverride() { 240 Group g = new Group(); 241 g.setFocusTraversable(true); 242 final ParentTraversalEngine pEngine = new ParentTraversalEngine(g); 243 pEngine.setOverriddenFocusTraversability(false); 244 g.setImpl_traversalEngine(pEngine); 245 246 Node focusableNode = createFocusableNode(); 247 248 ParentShim.getChildren(root).addAll(focusableNode, g); 249 250 assertEquals(focusableNode, engine.selectLast()); 251 } 252 253 @Test 254 public void selectNext() { 255 Node n1 = createFocusableNode(); 256 Node n2 = createFocusableNode(); 257 Group g = new Group(createFocusableNode(), n1, new Rectangle(), n2, createFocusableNode()); 258 259 ParentShim.getChildren(root).addAll(g); 260 261 assertEquals(n2, engine.trav(n1, Direction.NEXT)); 262 } 263 264 @Test 265 public void selectNextFromParent() { 266 Node ng1 = createFocusableNode(); 267 Node n1 = new Group(new Rectangle(), createFocusableDisabledNode(), ng1, createFocusableNode()); 268 Node n2 = createFocusableNode(); 269 Group g = new Group(createFocusableNode(), n1, new Rectangle(), n2, createFocusableNode()); 270 271 ParentShim.getChildren(root).addAll(g); 272 273 assertEquals(ng1, engine.trav(n1, Direction.NEXT)); 274 } 275 276 @Test 277 public void selectNextFromParent_2() { 278 Node n1 = new Group(createFocusableDisabledNode(), createFocusableDisabledNode()); 279 Node n2 = createFocusableNode(); 280 Group g = new Group(createFocusableNode(), n1, new Rectangle(), n2, createFocusableNode()); 281 282 ParentShim.getChildren(root).addAll(g); 283 284 assertEquals(n2, engine.trav(n1, Direction.NEXT)); 285 } 286 287 @Test 288 public void selectNextInParentSibling() { 289 Node n1 = createFocusableNode(); 290 final Node n2 = createFocusableNode(); 291 292 ParentShim.getChildren(root).addAll(createFocusableNode(), new Group(new Group(n1, createFocusableDisabledNode(), createFocusableDisabledNode()), 293 new Group(createFocusableDisabledNode())), new Group(n2)); 294 295 assertEquals(n2, engine.trav(n1, Direction.NEXT)); 296 } 297 298 @Test 299 public void selectNextFocusableParent() { 300 Node n1 = createFocusableNode(); 301 Group g = new Group(createFocusableNode()); 302 g.setFocusTraversable(true); 303 304 ParentShim.getChildren(root).addAll(new Group(createFocusableNode(), n1, createFocusableDisabledNode(), g)); 305 306 assertEquals(g, engine.trav(n1, Direction.NEXT)); 307 } 308 309 @Test 310 public void selectNextInOverridenAlgorithm() { 311 Node n1 = createFocusableNode(); 312 Node n2 = createFocusableNode(); 313 Group g = new Group(n1, createFocusableNode(), n2); 314 g.setImpl_traversalEngine(new ParentTraversalEngine(g, new Algorithm() { 315 @Override 316 public Node select(Node owner, Direction dir, TraversalContext context) { 317 assertEquals(Direction.NEXT, dir); 318 return n2; 319 } 320 321 @Override 322 public Node selectFirst(TraversalContext context) { 323 fail(); 324 return null; 325 } 326 327 @Override 328 public Node selectLast(TraversalContext context) { 329 fail(); 330 return null; 331 } 332 })); 333 334 ParentShim.getChildren(root).add(g); 335 336 assertEquals(n2, engine.trav(n1, Direction.NEXT)); 337 } 338 339 340 @Test 341 public void selectNextInOverridenAlgorithm_NothingSelected() { 342 Node n1 = createFocusableNode(); 343 Node n2 = createFocusableNode(); 344 Group g = new Group(n1, createFocusableNode(), n2); 345 g.setFocusTraversable(true); 346 g.setImpl_traversalEngine(new ParentTraversalEngine(g, new Algorithm() { 347 @Override 348 public Node select(Node owner, Direction dir, TraversalContext context) { 349 assertEquals(Direction.NEXT, dir); 350 return null; 351 } 352 353 @Override 354 public Node selectFirst(TraversalContext context) { 355 fail(); 356 return null; 357 } 358 359 @Override 360 public Node selectLast(TraversalContext context) { 361 fail(); 362 return null; 363 } 364 })); 365 366 final Node n3 = createFocusableNode(); 367 ParentShim.getChildren(root).addAll(g, n3); 368 369 assertEquals(n3, engine.trav(n1, Direction.NEXT)); 370 } 371 372 @Test 373 public void selectNextInLine() { 374 Node n1 = new Group(createFocusableNode(), createFocusableNode()); 375 n1.setFocusTraversable(true); 376 Node n2 = createFocusableNode(); 377 Group g = new Group(createFocusableNode(), n1, new Rectangle(), n2, createFocusableNode()); 378 379 ParentShim.getChildren(root).addAll(g); 380 381 assertEquals(n2, engine.trav(n1, Direction.NEXT_IN_LINE)); 382 } 383 384 385 @Test 386 public void selectPrevious() { 387 Node n1 = createFocusableNode(); 388 Node n2 = createFocusableNode(); 389 Group g = new Group(createFocusableNode(), n2, new Rectangle(), n1, createFocusableNode()); 390 391 ParentShim.getChildren(root).addAll(g); 392 393 assertEquals(n2, engine.trav(n1, Direction.PREVIOUS)); 394 } 395 396 @Test 397 public void selectPreviousFromParent() { 398 Node ng1 = createFocusableNode(); 399 Node n1 = new Group(new Rectangle(), createFocusableDisabledNode(), ng1, createFocusableNode()); 400 Node n2 = createFocusableNode(); 401 Group g = new Group(createFocusableNode(), n2, new Rectangle(), n1, createFocusableNode()); 402 403 ParentShim.getChildren(root).addAll(g); 404 405 assertEquals(n2, engine.trav(n1, Direction.PREVIOUS)); 406 } 407 408 @Test 409 public void selectPreviousFromParent_2() { 410 Node n1 = new Group(createFocusableDisabledNode(), createFocusableDisabledNode()); 411 Node n2 = createFocusableNode(); 412 Group g = new Group(createFocusableNode(), n2, new Rectangle(), n1, createFocusableNode()); 413 414 ParentShim.getChildren(root).addAll(g); 415 416 assertEquals(n2, engine.trav(n1, Direction.PREVIOUS)); 417 } 418 419 @Test 420 public void selectPreviousInParentSibling() { 421 Node n1 = createFocusableNode(); 422 final Node n2 = createFocusableNode(); 423 424 ParentShim.getChildren(root).addAll(new Group(n2), new Group(createFocusableDisabledNode()), 425 new Group(new Group(createFocusableDisabledNode(), n1, createFocusableDisabledNode())), 426 createFocusableNode()); 427 428 assertEquals(n2, engine.trav(n1, Direction.PREVIOUS)); 429 } 430 431 @Test 432 public void selectPreviousFocusableParentsNode() { 433 Node n1 = createFocusableNode(); 434 final Node n2 = createFocusableNode(); 435 Group g = new Group(n2); 436 g.setFocusTraversable(true); 437 438 ParentShim.getChildren(root).addAll(new Group(createFocusableNode(), g, n1, createFocusableDisabledNode())); 439 440 assertEquals(n2, engine.trav(n1, Direction.PREVIOUS)); 441 } 442 443 @Test 444 public void selectPreviousFocusableParent() { 445 Node n1 = createFocusableNode(); 446 final Node n2 = createFocusableNode(); 447 Group g = new Group(createFocusableDisabledNode(), n2); 448 g.setFocusTraversable(true); 449 450 ParentShim.getChildren(root).addAll(new Group(createFocusableNode(), n1, g, createFocusableDisabledNode())); 451 452 assertEquals(g, engine.trav(n2, Direction.PREVIOUS)); 453 } 454 455 @Test 456 public void selectNextToLast() { 457 Node n1 = createFocusableNode(); 458 Node n2 = createFocusableNode(); 459 460 ParentShim.getChildren(root).addAll(new Group(n2), new Group(createFocusableNode(), n1)); 461 462 assertEquals(n2, engine.trav(n1, Direction.NEXT)); 463 } 464 465 466 @Test 467 public void selectPreviousToFirst() { 468 Node n1 = createFocusableNode(); 469 Node n2 = createFocusableNode(); 470 471 ParentShim.getChildren(root).addAll(new Group(n1, createFocusableNode()), new Group(n2)); 472 473 assertEquals(n2, engine.trav(n1, Direction.PREVIOUS)); 474 } 475 476 477 @Test 478 public void selectPreviousInOverridenAlgorithm() { 479 Node n1 = createFocusableNode(); 480 Node n2 = createFocusableNode(); 481 Group g = new Group(n2, createFocusableNode(), n1); 482 g.setImpl_traversalEngine(new ParentTraversalEngine(g, new Algorithm() { 483 @Override 484 public Node select(Node owner, Direction dir, TraversalContext context) { 485 assertEquals(Direction.PREVIOUS, dir); 486 return n2; 487 } 488 489 @Override 490 public Node selectFirst(TraversalContext context) { 491 fail(); 492 return null; 493 } 494 495 @Override 496 public Node selectLast(TraversalContext context) { 497 fail(); 498 return null; 499 } 500 })); 501 502 ParentShim.getChildren(root).add(g); 503 504 assertEquals(n2, engine.trav(n1, Direction.PREVIOUS)); 505 } 506 507 private Node createFocusableNode() { 508 Node n = new Rectangle(); 509 n.setFocusTraversable(true); 510 return n; 511 } 512 513 private Node createFocusableDisabledNode() { 514 Node n = createFocusableNode(); 515 n.setDisable(true); 516 return n; 517 } 518 }