1 /* 2 * Copyright (c) 2000, 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 javax.swing; 26 27 import java.awt.Component; 28 import java.awt.Container; 29 import java.awt.Window; 30 import java.util.*; 31 import java.awt.FocusTraversalPolicy; 32 import sun.util.logging.PlatformLogger; 33 import java.lang.reflect.InvocationTargetException; 34 import java.lang.reflect.Method; 35 import sun.security.action.GetPropertyAction; 36 import java.security.AccessController; 37 import java.security.PrivilegedAction; 38 39 /** 40 * A FocusTraversalPolicy that determines traversal order by sorting the 41 * Components of a focus traversal cycle based on a given Comparator. Portions 42 * of the Component hierarchy that are not visible and displayable will not be 43 * included. 44 * <p> 45 * By default, SortingFocusTraversalPolicy implicitly transfers focus down- 46 * cycle. That is, during normal focus traversal, the Component 47 * traversed after a focus cycle root will be the focus-cycle-root's default 48 * Component to focus. This behavior can be disabled using the 49 * <code>setImplicitDownCycleTraversal</code> method. 50 * <p> 51 * By default, methods of this class with return a Component only if it is 52 * visible, displayable, enabled, and focusable. Subclasses can modify this 53 * behavior by overriding the <code>accept</code> method. 54 * <p> 55 * This policy takes into account <a 56 * href="../../java/awt/doc-files/FocusSpec.html#FocusTraversalPolicyProviders">focus traversal 57 * policy providers</a>. When searching for first/last/next/previous Component, 58 * if a focus traversal policy provider is encountered, its focus traversal 59 * policy is used to perform the search operation. 60 * 61 * @author David Mendenhall 62 * 63 * @see java.util.Comparator 64 * @since 1.4 65 */ 66 public class SortingFocusTraversalPolicy 67 extends InternalFrameFocusTraversalPolicy 68 { 69 private Comparator<? super Component> comparator; 70 private boolean implicitDownCycleTraversal = true; 71 72 private PlatformLogger log = PlatformLogger.getLogger("javax.swing.SortingFocusTraversalPolicy"); 73 74 /** 75 * Used by getComponentAfter and getComponentBefore for efficiency. In 76 * order to maintain compliance with the specification of 77 * FocusTraversalPolicy, if traversal wraps, we should invoke 78 * getFirstComponent or getLastComponent. These methods may be overriden in 79 * subclasses to behave in a non-generic way. However, in the generic case, 80 * these methods will simply return the first or last Components of the 81 * sorted list, respectively. Since getComponentAfter and 82 * getComponentBefore have already built the sorted list before determining 83 * that they need to invoke getFirstComponent or getLastComponent, the 84 * sorted list should be reused if possible. 85 */ 86 transient private Container cachedRoot; 87 transient private List<Component> cachedCycle; 88 89 // Delegate our fitness test to ContainerOrder so that we only have to 90 // code the algorithm once. 91 private static final SwingContainerOrderFocusTraversalPolicy 92 fitnessTestPolicy = new SwingContainerOrderFocusTraversalPolicy(); 93 94 final private int FORWARD_TRAVERSAL = 0; 95 final private int BACKWARD_TRAVERSAL = 1; 96 97 /* 98 * When true (by default), the legacy merge-sort algo is used to sort an FTP cycle. 99 * When false, the default (tim-sort) algo is used, which may lead to an exception. 100 * See: JDK-8048887 101 */ 102 private static final boolean legacySortingFTPEnabled; 103 private static final Method legacyMergeSortMethod; 104 105 static { 106 legacySortingFTPEnabled = "true".equals(AccessController.doPrivileged( 107 new GetPropertyAction("swing.legacySortingFTPEnabled", "true"))); 108 legacyMergeSortMethod = legacySortingFTPEnabled ? 109 AccessController.doPrivileged(new PrivilegedAction<Method>() { 110 public Method run() { 111 try { 112 Method m = java.util.Arrays.class.getDeclaredMethod("legacyMergeSort", 113 new Class<?>[]{Object[].class, 114 Comparator.class}); 115 m.setAccessible(true); 116 return m; 117 } catch (NoSuchMethodException e) { 118 // using default sorting algo 119 return null; 120 } 121 } 122 }) : 123 null; 124 } 125 126 /** 127 * Constructs a SortingFocusTraversalPolicy without a Comparator. 128 * Subclasses must set the Comparator using <code>setComparator</code> 129 * before installing this FocusTraversalPolicy on a focus cycle root or 130 * KeyboardFocusManager. 131 */ 132 protected SortingFocusTraversalPolicy() { 133 } 134 135 /** 136 * Constructs a SortingFocusTraversalPolicy with the specified Comparator. 137 * 138 * @param comparator the {@code Comparator} to sort by 139 */ 140 public SortingFocusTraversalPolicy(Comparator<? super Component> comparator) { 141 this.comparator = comparator; 142 } 143 144 private List<Component> getFocusTraversalCycle(Container aContainer) { 145 List<Component> cycle = new ArrayList<Component>(); 146 enumerateAndSortCycle(aContainer, cycle); 147 return cycle; 148 } 149 private int getComponentIndex(List<Component> cycle, Component aComponent) { 150 int index; 151 try { 152 index = Collections.binarySearch(cycle, aComponent, comparator); 153 } catch (ClassCastException e) { 154 if (log.isLoggable(PlatformLogger.Level.FINE)) { 155 log.fine("### During the binary search for " + aComponent + " the exception occurred: ", e); 156 } 157 return -1; 158 } 159 if (index < 0) { 160 // Fix for 5070991. 161 // A workaround for a transitivity problem caused by ROW_TOLERANCE, 162 // because of that the component may be missed in the binary search. 163 // Try to search it again directly. 164 index = cycle.indexOf(aComponent); 165 } 166 return index; 167 } 168 169 private void enumerateAndSortCycle(Container focusCycleRoot, List<Component> cycle) { 170 if (focusCycleRoot.isShowing()) { 171 enumerateCycle(focusCycleRoot, cycle); 172 if (!legacySortingFTPEnabled || 173 !legacySort(cycle, comparator)) 174 { 175 Collections.sort(cycle, comparator); 176 } 177 } 178 } 179 180 private boolean legacySort(List<Component> l, Comparator<? super Component> c) { 181 if (legacyMergeSortMethod == null) 182 return false; 183 184 Object[] a = l.toArray(); 185 try { 186 legacyMergeSortMethod.invoke(null, a, c); 187 } catch (IllegalAccessException | InvocationTargetException e) { 188 return false; 189 } 190 ListIterator<Component> i = l.listIterator(); 191 for (Object e : a) { 192 i.next(); 193 i.set((Component)e); 194 } 195 return true; 196 } 197 198 private void enumerateCycle(Container container, List<Component> cycle) { 199 if (!(container.isVisible() && container.isDisplayable())) { 200 return; 201 } 202 203 cycle.add(container); 204 205 Component[] components = container.getComponents(); 206 for (Component comp : components) { 207 if (comp instanceof Container) { 208 Container cont = (Container)comp; 209 210 if (!cont.isFocusCycleRoot() && 211 !cont.isFocusTraversalPolicyProvider() && 212 !((cont instanceof JComponent) && ((JComponent)cont).isManagingFocus())) 213 { 214 enumerateCycle(cont, cycle); 215 continue; 216 } 217 } 218 cycle.add(comp); 219 } 220 } 221 222 Container getTopmostProvider(Container focusCycleRoot, Component aComponent) { 223 Container aCont = aComponent.getParent(); 224 Container ftp = null; 225 while (aCont != focusCycleRoot && aCont != null) { 226 if (aCont.isFocusTraversalPolicyProvider()) { 227 ftp = aCont; 228 } 229 aCont = aCont.getParent(); 230 } 231 if (aCont == null) { 232 return null; 233 } 234 return ftp; 235 } 236 237 /* 238 * Checks if a new focus cycle takes place and returns a Component to traverse focus to. 239 * @param comp a possible focus cycle root or policy provider 240 * @param traversalDirection the direction of the traversal 241 * @return a Component to traverse focus to if {@code comp} is a root or provider 242 * and implicit down-cycle is set, otherwise {@code null} 243 */ 244 private Component getComponentDownCycle(Component comp, int traversalDirection) { 245 Component retComp = null; 246 247 if (comp instanceof Container) { 248 Container cont = (Container)comp; 249 250 if (cont.isFocusCycleRoot()) { 251 if (getImplicitDownCycleTraversal()) { 252 retComp = cont.getFocusTraversalPolicy().getDefaultComponent(cont); 253 254 if (retComp != null && log.isLoggable(PlatformLogger.Level.FINE)) { 255 log.fine("### Transfered focus down-cycle to " + retComp + 256 " in the focus cycle root " + cont); 257 } 258 } else { 259 return null; 260 } 261 } else if (cont.isFocusTraversalPolicyProvider()) { 262 retComp = (traversalDirection == FORWARD_TRAVERSAL ? 263 cont.getFocusTraversalPolicy().getDefaultComponent(cont) : 264 cont.getFocusTraversalPolicy().getLastComponent(cont)); 265 266 if (retComp != null && log.isLoggable(PlatformLogger.Level.FINE)) { 267 log.fine("### Transfered focus to " + retComp + " in the FTP provider " + cont); 268 } 269 } 270 } 271 return retComp; 272 } 273 274 /** 275 * Returns the Component that should receive the focus after aComponent. 276 * aContainer must be a focus cycle root of aComponent or a focus traversal policy provider. 277 * <p> 278 * By default, SortingFocusTraversalPolicy implicitly transfers focus down- 279 * cycle. That is, during normal focus traversal, the Component 280 * traversed after a focus cycle root will be the focus-cycle-root's 281 * default Component to focus. This behavior can be disabled using the 282 * <code>setImplicitDownCycleTraversal</code> method. 283 * <p> 284 * If aContainer is <a href="../../java/awt/doc-files/FocusSpec.html#FocusTraversalPolicyProviders">focus 285 * traversal policy provider</a>, the focus is always transferred down-cycle. 286 * 287 * @param aContainer a focus cycle root of aComponent or a focus traversal policy provider 288 * @param aComponent a (possibly indirect) child of aContainer, or 289 * aContainer itself 290 * @return the Component that should receive the focus after aComponent, or 291 * null if no suitable Component can be found 292 * @throws IllegalArgumentException if aContainer is not a focus cycle 293 * root of aComponent or a focus traversal policy provider, or if either aContainer or 294 * aComponent is null 295 */ 296 public Component getComponentAfter(Container aContainer, Component aComponent) { 297 if (log.isLoggable(PlatformLogger.Level.FINE)) { 298 log.fine("### Searching in " + aContainer + " for component after " + aComponent); 299 } 300 301 if (aContainer == null || aComponent == null) { 302 throw new IllegalArgumentException("aContainer and aComponent cannot be null"); 303 } 304 if (!aContainer.isFocusTraversalPolicyProvider() && !aContainer.isFocusCycleRoot()) { 305 throw new IllegalArgumentException("aContainer should be focus cycle root or focus traversal policy provider"); 306 307 } else if (aContainer.isFocusCycleRoot() && !aComponent.isFocusCycleRoot(aContainer)) { 308 throw new IllegalArgumentException("aContainer is not a focus cycle root of aComponent"); 309 } 310 311 // Before all the ckecks below we first see if it's an FTP provider or a focus cycle root. 312 // If it's the case just go down cycle (if it's set to "implicit"). 313 Component comp = getComponentDownCycle(aComponent, FORWARD_TRAVERSAL); 314 if (comp != null) { 315 return comp; 316 } 317 318 // See if the component is inside of policy provider. 319 Container provider = getTopmostProvider(aContainer, aComponent); 320 if (provider != null) { 321 if (log.isLoggable(PlatformLogger.Level.FINE)) { 322 log.fine("### Asking FTP " + provider + " for component after " + aComponent); 323 } 324 325 // FTP knows how to find component after the given. We don't. 326 FocusTraversalPolicy policy = provider.getFocusTraversalPolicy(); 327 Component afterComp = policy.getComponentAfter(provider, aComponent); 328 329 // Null result means that we overstepped the limit of the FTP's cycle. 330 // In that case we must quit the cycle, otherwise return the component found. 331 if (afterComp != null) { 332 if (log.isLoggable(PlatformLogger.Level.FINE)) { 333 log.fine("### FTP returned " + afterComp); 334 } 335 return afterComp; 336 } 337 aComponent = provider; 338 } 339 340 List<Component> cycle = getFocusTraversalCycle(aContainer); 341 342 if (log.isLoggable(PlatformLogger.Level.FINE)) { 343 log.fine("### Cycle is " + cycle + ", component is " + aComponent); 344 } 345 346 int index = getComponentIndex(cycle, aComponent); 347 348 if (index < 0) { 349 if (log.isLoggable(PlatformLogger.Level.FINE)) { 350 log.fine("### Didn't find component " + aComponent + " in a cycle " + aContainer); 351 } 352 return getFirstComponent(aContainer); 353 } 354 355 for (index++; index < cycle.size(); index++) { 356 comp = cycle.get(index); 357 if (accept(comp)) { 358 return comp; 359 } else if ((comp = getComponentDownCycle(comp, FORWARD_TRAVERSAL)) != null) { 360 return comp; 361 } 362 } 363 364 if (aContainer.isFocusCycleRoot()) { 365 this.cachedRoot = aContainer; 366 this.cachedCycle = cycle; 367 368 comp = getFirstComponent(aContainer); 369 370 this.cachedRoot = null; 371 this.cachedCycle = null; 372 373 return comp; 374 } 375 return null; 376 } 377 378 /** 379 * Returns the Component that should receive the focus before aComponent. 380 * aContainer must be a focus cycle root of aComponent or a focus traversal policy provider. 381 * <p> 382 * By default, SortingFocusTraversalPolicy implicitly transfers focus down- 383 * cycle. That is, during normal focus traversal, the Component 384 * traversed after a focus cycle root will be the focus-cycle-root's 385 * default Component to focus. This behavior can be disabled using the 386 * <code>setImplicitDownCycleTraversal</code> method. 387 * <p> 388 * If aContainer is <a href="../../java/awt/doc-files/FocusSpec.html#FocusTraversalPolicyProviders">focus 389 * traversal policy provider</a>, the focus is always transferred down-cycle. 390 * 391 * @param aContainer a focus cycle root of aComponent or a focus traversal policy provider 392 * @param aComponent a (possibly indirect) child of aContainer, or 393 * aContainer itself 394 * @return the Component that should receive the focus before aComponent, 395 * or null if no suitable Component can be found 396 * @throws IllegalArgumentException if aContainer is not a focus cycle 397 * root of aComponent or a focus traversal policy provider, or if either aContainer or 398 * aComponent is null 399 */ 400 public Component getComponentBefore(Container aContainer, Component aComponent) { 401 if (aContainer == null || aComponent == null) { 402 throw new IllegalArgumentException("aContainer and aComponent cannot be null"); 403 } 404 if (!aContainer.isFocusTraversalPolicyProvider() && !aContainer.isFocusCycleRoot()) { 405 throw new IllegalArgumentException("aContainer should be focus cycle root or focus traversal policy provider"); 406 407 } else if (aContainer.isFocusCycleRoot() && !aComponent.isFocusCycleRoot(aContainer)) { 408 throw new IllegalArgumentException("aContainer is not a focus cycle root of aComponent"); 409 } 410 411 // See if the component is inside of policy provider. 412 Container provider = getTopmostProvider(aContainer, aComponent); 413 if (provider != null) { 414 if (log.isLoggable(PlatformLogger.Level.FINE)) { 415 log.fine("### Asking FTP " + provider + " for component after " + aComponent); 416 } 417 418 // FTP knows how to find component after the given. We don't. 419 FocusTraversalPolicy policy = provider.getFocusTraversalPolicy(); 420 Component beforeComp = policy.getComponentBefore(provider, aComponent); 421 422 // Null result means that we overstepped the limit of the FTP's cycle. 423 // In that case we must quit the cycle, otherwise return the component found. 424 if (beforeComp != null) { 425 if (log.isLoggable(PlatformLogger.Level.FINE)) { 426 log.fine("### FTP returned " + beforeComp); 427 } 428 return beforeComp; 429 } 430 aComponent = provider; 431 432 // If the provider is traversable it's returned. 433 if (accept(aComponent)) { 434 return aComponent; 435 } 436 } 437 438 List<Component> cycle = getFocusTraversalCycle(aContainer); 439 440 if (log.isLoggable(PlatformLogger.Level.FINE)) { 441 log.fine("### Cycle is " + cycle + ", component is " + aComponent); 442 } 443 444 int index = getComponentIndex(cycle, aComponent); 445 446 if (index < 0) { 447 if (log.isLoggable(PlatformLogger.Level.FINE)) { 448 log.fine("### Didn't find component " + aComponent + " in a cycle " + aContainer); 449 } 450 return getLastComponent(aContainer); 451 } 452 453 Component comp; 454 Component tryComp; 455 456 for (index--; index>=0; index--) { 457 comp = cycle.get(index); 458 if (comp != aContainer && (tryComp = getComponentDownCycle(comp, BACKWARD_TRAVERSAL)) != null) { 459 return tryComp; 460 } else if (accept(comp)) { 461 return comp; 462 } 463 } 464 465 if (aContainer.isFocusCycleRoot()) { 466 this.cachedRoot = aContainer; 467 this.cachedCycle = cycle; 468 469 comp = getLastComponent(aContainer); 470 471 this.cachedRoot = null; 472 this.cachedCycle = null; 473 474 return comp; 475 } 476 return null; 477 } 478 479 /** 480 * Returns the first Component in the traversal cycle. This method is used 481 * to determine the next Component to focus when traversal wraps in the 482 * forward direction. 483 * 484 * @param aContainer a focus cycle root of aComponent or a focus traversal policy provider whose 485 * first Component is to be returned 486 * @return the first Component in the traversal cycle of aContainer, 487 * or null if no suitable Component can be found 488 * @throws IllegalArgumentException if aContainer is null 489 */ 490 public Component getFirstComponent(Container aContainer) { 491 List<Component> cycle; 492 493 if (log.isLoggable(PlatformLogger.Level.FINE)) { 494 log.fine("### Getting first component in " + aContainer); 495 } 496 if (aContainer == null) { 497 throw new IllegalArgumentException("aContainer cannot be null"); 498 } 499 500 if (this.cachedRoot == aContainer) { 501 cycle = this.cachedCycle; 502 } else { 503 cycle = getFocusTraversalCycle(aContainer); 504 } 505 506 if (cycle.size() == 0) { 507 if (log.isLoggable(PlatformLogger.Level.FINE)) { 508 log.fine("### Cycle is empty"); 509 } 510 return null; 511 } 512 if (log.isLoggable(PlatformLogger.Level.FINE)) { 513 log.fine("### Cycle is " + cycle); 514 } 515 516 for (Component comp : cycle) { 517 if (accept(comp)) { 518 return comp; 519 } else if (comp != aContainer && 520 (comp = getComponentDownCycle(comp, FORWARD_TRAVERSAL)) != null) 521 { 522 return comp; 523 } 524 } 525 return null; 526 } 527 528 /** 529 * Returns the last Component in the traversal cycle. This method is used 530 * to determine the next Component to focus when traversal wraps in the 531 * reverse direction. 532 * 533 * @param aContainer a focus cycle root of aComponent or a focus traversal policy provider whose 534 * last Component is to be returned 535 * @return the last Component in the traversal cycle of aContainer, 536 * or null if no suitable Component can be found 537 * @throws IllegalArgumentException if aContainer is null 538 */ 539 public Component getLastComponent(Container aContainer) { 540 List<Component> cycle; 541 if (log.isLoggable(PlatformLogger.Level.FINE)) { 542 log.fine("### Getting last component in " + aContainer); 543 } 544 545 if (aContainer == null) { 546 throw new IllegalArgumentException("aContainer cannot be null"); 547 } 548 549 if (this.cachedRoot == aContainer) { 550 cycle = this.cachedCycle; 551 } else { 552 cycle = getFocusTraversalCycle(aContainer); 553 } 554 555 if (cycle.size() == 0) { 556 if (log.isLoggable(PlatformLogger.Level.FINE)) { 557 log.fine("### Cycle is empty"); 558 } 559 return null; 560 } 561 if (log.isLoggable(PlatformLogger.Level.FINE)) { 562 log.fine("### Cycle is " + cycle); 563 } 564 565 for (int i= cycle.size() - 1; i >= 0; i--) { 566 Component comp = cycle.get(i); 567 if (accept(comp)) { 568 return comp; 569 } else if (comp instanceof Container && comp != aContainer) { 570 Container cont = (Container)comp; 571 if (cont.isFocusTraversalPolicyProvider()) { 572 return cont.getFocusTraversalPolicy().getLastComponent(cont); 573 } 574 } 575 } 576 return null; 577 } 578 579 /** 580 * Returns the default Component to focus. This Component will be the first 581 * to receive focus when traversing down into a new focus traversal cycle 582 * rooted at aContainer. The default implementation of this method 583 * returns the same Component as <code>getFirstComponent</code>. 584 * 585 * @param aContainer a focus cycle root of aComponent or a focus traversal policy provider whose 586 * default Component is to be returned 587 * @return the default Component in the traversal cycle of aContainer, 588 * or null if no suitable Component can be found 589 * @see #getFirstComponent 590 * @throws IllegalArgumentException if aContainer is null 591 */ 592 public Component getDefaultComponent(Container aContainer) { 593 return getFirstComponent(aContainer); 594 } 595 596 /** 597 * Sets whether this SortingFocusTraversalPolicy transfers focus down-cycle 598 * implicitly. If <code>true</code>, during normal focus traversal, 599 * the Component traversed after a focus cycle root will be the focus- 600 * cycle-root's default Component to focus. If <code>false</code>, the 601 * next Component in the focus traversal cycle rooted at the specified 602 * focus cycle root will be traversed instead. The default value for this 603 * property is <code>true</code>. 604 * 605 * @param implicitDownCycleTraversal whether this 606 * SortingFocusTraversalPolicy transfers focus down-cycle implicitly 607 * @see #getImplicitDownCycleTraversal 608 * @see #getFirstComponent 609 */ 610 public void setImplicitDownCycleTraversal(boolean implicitDownCycleTraversal) { 611 this.implicitDownCycleTraversal = implicitDownCycleTraversal; 612 } 613 614 /** 615 * Returns whether this SortingFocusTraversalPolicy transfers focus down- 616 * cycle implicitly. If <code>true</code>, during normal focus 617 * traversal, the Component traversed after a focus cycle root will be the 618 * focus-cycle-root's default Component to focus. If <code>false</code>, 619 * the next Component in the focus traversal cycle rooted at the specified 620 * focus cycle root will be traversed instead. 621 * 622 * @return whether this SortingFocusTraversalPolicy transfers focus down- 623 * cycle implicitly 624 * @see #setImplicitDownCycleTraversal 625 * @see #getFirstComponent 626 */ 627 public boolean getImplicitDownCycleTraversal() { 628 return implicitDownCycleTraversal; 629 } 630 631 /** 632 * Sets the Comparator which will be used to sort the Components in a 633 * focus traversal cycle. 634 * 635 * @param comparator the Comparator which will be used for sorting 636 */ 637 protected void setComparator(Comparator<? super Component> comparator) { 638 this.comparator = comparator; 639 } 640 641 /** 642 * Returns the Comparator which will be used to sort the Components in a 643 * focus traversal cycle. 644 * 645 * @return the Comparator which will be used for sorting 646 */ 647 protected Comparator<? super Component> getComparator() { 648 return comparator; 649 } 650 651 /** 652 * Determines whether a Component is an acceptable choice as the new 653 * focus owner. By default, this method will accept a Component if and 654 * only if it is visible, displayable, enabled, and focusable. 655 * 656 * @param aComponent the Component whose fitness as a focus owner is to 657 * be tested 658 * @return <code>true</code> if aComponent is visible, displayable, 659 * enabled, and focusable; <code>false</code> otherwise 660 */ 661 protected boolean accept(Component aComponent) { 662 return fitnessTestPolicy.accept(aComponent); 663 } 664 } 665 666 // Create our own subclass and change accept to public so that we can call 667 // accept. 668 @SuppressWarnings("serial") // JDK-implementation class 669 class SwingContainerOrderFocusTraversalPolicy 670 extends java.awt.ContainerOrderFocusTraversalPolicy 671 { 672 public boolean accept(Component aComponent) { 673 return super.accept(aComponent); 674 } 675 }