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