< prev index next >

src/java.desktop/share/classes/javax/swing/SortingFocusTraversalPolicy.java

Print this page




  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 


 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     }


 263                 retComp = (traversalDirection == FORWARD_TRAVERSAL ?
 264                            cont.getFocusTraversalPolicy().getDefaultComponent(cont) :
 265                            cont.getFocusTraversalPolicy().getLastComponent(cont));
 266 
 267                 if (retComp != null && log.isLoggable(PlatformLogger.Level.FINE)) {
 268                     log.fine("### Transfered focus to " + retComp + " in the FTP provider " + cont);
 269                 }
 270             }
 271         }
 272         return retComp;
 273     }
 274 
 275     /**
 276      * Returns the Component that should receive the focus after aComponent.
 277      * aContainer must be a focus cycle root of aComponent or a focus traversal policy provider.
 278      * <p>
 279      * By default, SortingFocusTraversalPolicy implicitly transfers focus down-
 280      * cycle. That is, during normal focus traversal, the Component
 281      * traversed after a focus cycle root will be the focus-cycle-root's
 282      * default Component to focus. This behavior can be disabled using the
 283      * <code>setImplicitDownCycleTraversal</code> method.
 284      * <p>
 285      * If aContainer is <a href="../../java/awt/doc-files/FocusSpec.html#FocusTraversalPolicyProviders">focus
 286      * traversal policy provider</a>, the focus is always transferred down-cycle.
 287      *
 288      * @param aContainer a focus cycle root of aComponent or a focus traversal policy provider
 289      * @param aComponent a (possibly indirect) child of aContainer, or
 290      *        aContainer itself
 291      * @return the Component that should receive the focus after aComponent, or
 292      *         null if no suitable Component can be found
 293      * @throws IllegalArgumentException if aContainer is not a focus cycle
 294      *         root of aComponent or a focus traversal policy provider, or if either aContainer or
 295      *         aComponent is null
 296      */
 297     public Component getComponentAfter(Container aContainer, Component aComponent) {
 298         if (log.isLoggable(PlatformLogger.Level.FINE)) {
 299             log.fine("### Searching in " + aContainer + " for component after " + aComponent);
 300         }
 301 
 302         if (aContainer == null || aComponent == null) {
 303             throw new IllegalArgumentException("aContainer and aComponent cannot be null");


 367             this.cachedCycle = cycle;
 368 
 369             comp = getFirstComponent(aContainer);
 370 
 371             this.cachedRoot = null;
 372             this.cachedCycle = null;
 373 
 374             return comp;
 375         }
 376         return null;
 377     }
 378 
 379     /**
 380      * Returns the Component that should receive the focus before aComponent.
 381      * aContainer must be a focus cycle root of aComponent or a focus traversal policy provider.
 382      * <p>
 383      * By default, SortingFocusTraversalPolicy implicitly transfers focus down-
 384      * cycle. That is, during normal focus traversal, the Component
 385      * traversed after a focus cycle root will be the focus-cycle-root's
 386      * default Component to focus. This behavior can be disabled using the
 387      * <code>setImplicitDownCycleTraversal</code> method.
 388      * <p>
 389      * If aContainer is <a href="../../java/awt/doc-files/FocusSpec.html#FocusTraversalPolicyProviders">focus
 390      * traversal policy provider</a>, the focus is always transferred down-cycle.
 391      *
 392      * @param aContainer a focus cycle root of aComponent or a focus traversal policy provider
 393      * @param aComponent a (possibly indirect) child of aContainer, or
 394      *        aContainer itself
 395      * @return the Component that should receive the focus before aComponent,
 396      *         or null if no suitable Component can be found
 397      * @throws IllegalArgumentException if aContainer is not a focus cycle
 398      *         root of aComponent or a focus traversal policy provider, or if either aContainer or
 399      *         aComponent is null
 400      */
 401     public Component getComponentBefore(Container aContainer, Component aComponent) {
 402         if (aContainer == null || aComponent == null) {
 403             throw new IllegalArgumentException("aContainer and aComponent cannot be null");
 404         }
 405         if (!aContainer.isFocusTraversalPolicyProvider() && !aContainer.isFocusCycleRoot()) {
 406             throw new IllegalArgumentException("aContainer should be focus cycle root or focus traversal policy provider");
 407 


 567             Component comp = cycle.get(i);
 568             if (accept(comp)) {
 569                 return comp;
 570             } else if (comp instanceof Container && comp != aContainer) {
 571                 Container cont = (Container)comp;
 572                 if (cont.isFocusTraversalPolicyProvider()) {
 573                     Component retComp = cont.getFocusTraversalPolicy().getLastComponent(cont);
 574                     if (retComp != null) {
 575                         return retComp;
 576                     }
 577                 }
 578             }
 579         }
 580         return null;
 581     }
 582 
 583     /**
 584      * Returns the default Component to focus. This Component will be the first
 585      * to receive focus when traversing down into a new focus traversal cycle
 586      * rooted at aContainer. The default implementation of this method
 587      * returns the same Component as <code>getFirstComponent</code>.
 588      *
 589      * @param aContainer a focus cycle root of aComponent or a focus traversal policy provider whose
 590      *        default Component is to be returned
 591      * @return the default Component in the traversal cycle of aContainer,
 592      *         or null if no suitable Component can be found
 593      * @see #getFirstComponent
 594      * @throws IllegalArgumentException if aContainer is null
 595      */
 596     public Component getDefaultComponent(Container aContainer) {
 597         return getFirstComponent(aContainer);
 598     }
 599 
 600     /**
 601      * Sets whether this SortingFocusTraversalPolicy transfers focus down-cycle
 602      * implicitly. If <code>true</code>, during normal focus traversal,
 603      * the Component traversed after a focus cycle root will be the focus-
 604      * cycle-root's default Component to focus. If <code>false</code>, the
 605      * next Component in the focus traversal cycle rooted at the specified
 606      * focus cycle root will be traversed instead. The default value for this
 607      * property is <code>true</code>.
 608      *
 609      * @param implicitDownCycleTraversal whether this
 610      *        SortingFocusTraversalPolicy transfers focus down-cycle implicitly
 611      * @see #getImplicitDownCycleTraversal
 612      * @see #getFirstComponent
 613      */
 614     public void setImplicitDownCycleTraversal(boolean implicitDownCycleTraversal) {
 615         this.implicitDownCycleTraversal = implicitDownCycleTraversal;
 616     }
 617 
 618     /**
 619      * Returns whether this SortingFocusTraversalPolicy transfers focus down-
 620      * cycle implicitly. If <code>true</code>, during normal focus
 621      * traversal, the Component traversed after a focus cycle root will be the
 622      * focus-cycle-root's default Component to focus. If <code>false</code>,
 623      * the next Component in the focus traversal cycle rooted at the specified
 624      * focus cycle root will be traversed instead.
 625      *
 626      * @return whether this SortingFocusTraversalPolicy transfers focus down-
 627      *         cycle implicitly
 628      * @see #setImplicitDownCycleTraversal
 629      * @see #getFirstComponent
 630      */
 631     public boolean getImplicitDownCycleTraversal() {
 632         return implicitDownCycleTraversal;
 633     }
 634 
 635     /**
 636      * Sets the Comparator which will be used to sort the Components in a
 637      * focus traversal cycle.
 638      *
 639      * @param comparator the Comparator which will be used for sorting
 640      */
 641     protected void setComparator(Comparator<? super Component> comparator) {
 642         this.comparator = comparator;
 643     }
 644 
 645     /**
 646      * Returns the Comparator which will be used to sort the Components in a
 647      * focus traversal cycle.
 648      *
 649      * @return the Comparator which will be used for sorting
 650      */
 651     protected Comparator<? super Component> getComparator() {
 652         return comparator;
 653     }
 654 
 655     /**
 656      * Determines whether a Component is an acceptable choice as the new
 657      * focus owner. By default, this method will accept a Component if and
 658      * only if it is visible, displayable, enabled, and focusable.
 659      *
 660      * @param aComponent the Component whose fitness as a focus owner is to
 661      *        be tested
 662      * @return <code>true</code> if aComponent is visible, displayable,
 663      *         enabled, and focusable; <code>false</code> otherwise
 664      */
 665     protected boolean accept(Component aComponent) {
 666         return fitnessTestPolicy.accept(aComponent);
 667     }
 668 }
 669 
 670 // Create our own subclass and change accept to public so that we can call
 671 // accept.
 672 @SuppressWarnings("serial") // JDK-implementation class
 673 class SwingContainerOrderFocusTraversalPolicy
 674     extends java.awt.ContainerOrderFocusTraversalPolicy
 675 {
 676     public boolean accept(Component aComponent) {
 677         return super.accept(aComponent);
 678     }
 679 }


  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} 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} 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 


 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}
 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     }


 263                 retComp = (traversalDirection == FORWARD_TRAVERSAL ?
 264                            cont.getFocusTraversalPolicy().getDefaultComponent(cont) :
 265                            cont.getFocusTraversalPolicy().getLastComponent(cont));
 266 
 267                 if (retComp != null && log.isLoggable(PlatformLogger.Level.FINE)) {
 268                     log.fine("### Transfered focus to " + retComp + " in the FTP provider " + cont);
 269                 }
 270             }
 271         }
 272         return retComp;
 273     }
 274 
 275     /**
 276      * Returns the Component that should receive the focus after aComponent.
 277      * aContainer must be a focus cycle root of aComponent or a focus traversal policy provider.
 278      * <p>
 279      * By default, SortingFocusTraversalPolicy implicitly transfers focus down-
 280      * cycle. That is, during normal focus traversal, the Component
 281      * traversed after a focus cycle root will be the focus-cycle-root's
 282      * default Component to focus. This behavior can be disabled using the
 283      * {@code setImplicitDownCycleTraversal} method.
 284      * <p>
 285      * If aContainer is <a href="../../java/awt/doc-files/FocusSpec.html#FocusTraversalPolicyProviders">focus
 286      * traversal policy provider</a>, the focus is always transferred down-cycle.
 287      *
 288      * @param aContainer a focus cycle root of aComponent or a focus traversal policy provider
 289      * @param aComponent a (possibly indirect) child of aContainer, or
 290      *        aContainer itself
 291      * @return the Component that should receive the focus after aComponent, or
 292      *         null if no suitable Component can be found
 293      * @throws IllegalArgumentException if aContainer is not a focus cycle
 294      *         root of aComponent or a focus traversal policy provider, or if either aContainer or
 295      *         aComponent is null
 296      */
 297     public Component getComponentAfter(Container aContainer, Component aComponent) {
 298         if (log.isLoggable(PlatformLogger.Level.FINE)) {
 299             log.fine("### Searching in " + aContainer + " for component after " + aComponent);
 300         }
 301 
 302         if (aContainer == null || aComponent == null) {
 303             throw new IllegalArgumentException("aContainer and aComponent cannot be null");


 367             this.cachedCycle = cycle;
 368 
 369             comp = getFirstComponent(aContainer);
 370 
 371             this.cachedRoot = null;
 372             this.cachedCycle = null;
 373 
 374             return comp;
 375         }
 376         return null;
 377     }
 378 
 379     /**
 380      * Returns the Component that should receive the focus before aComponent.
 381      * aContainer must be a focus cycle root of aComponent or a focus traversal policy provider.
 382      * <p>
 383      * By default, SortingFocusTraversalPolicy implicitly transfers focus down-
 384      * cycle. That is, during normal focus traversal, the Component
 385      * traversed after a focus cycle root will be the focus-cycle-root's
 386      * default Component to focus. This behavior can be disabled using the
 387      * {@code setImplicitDownCycleTraversal} method.
 388      * <p>
 389      * If aContainer is <a href="../../java/awt/doc-files/FocusSpec.html#FocusTraversalPolicyProviders">focus
 390      * traversal policy provider</a>, the focus is always transferred down-cycle.
 391      *
 392      * @param aContainer a focus cycle root of aComponent or a focus traversal policy provider
 393      * @param aComponent a (possibly indirect) child of aContainer, or
 394      *        aContainer itself
 395      * @return the Component that should receive the focus before aComponent,
 396      *         or null if no suitable Component can be found
 397      * @throws IllegalArgumentException if aContainer is not a focus cycle
 398      *         root of aComponent or a focus traversal policy provider, or if either aContainer or
 399      *         aComponent is null
 400      */
 401     public Component getComponentBefore(Container aContainer, Component aComponent) {
 402         if (aContainer == null || aComponent == null) {
 403             throw new IllegalArgumentException("aContainer and aComponent cannot be null");
 404         }
 405         if (!aContainer.isFocusTraversalPolicyProvider() && !aContainer.isFocusCycleRoot()) {
 406             throw new IllegalArgumentException("aContainer should be focus cycle root or focus traversal policy provider");
 407 


 567             Component comp = cycle.get(i);
 568             if (accept(comp)) {
 569                 return comp;
 570             } else if (comp instanceof Container && comp != aContainer) {
 571                 Container cont = (Container)comp;
 572                 if (cont.isFocusTraversalPolicyProvider()) {
 573                     Component retComp = cont.getFocusTraversalPolicy().getLastComponent(cont);
 574                     if (retComp != null) {
 575                         return retComp;
 576                     }
 577                 }
 578             }
 579         }
 580         return null;
 581     }
 582 
 583     /**
 584      * Returns the default Component to focus. This Component will be the first
 585      * to receive focus when traversing down into a new focus traversal cycle
 586      * rooted at aContainer. The default implementation of this method
 587      * returns the same Component as {@code getFirstComponent}.
 588      *
 589      * @param aContainer a focus cycle root of aComponent or a focus traversal policy provider whose
 590      *        default Component is to be returned
 591      * @return the default Component in the traversal cycle of aContainer,
 592      *         or null if no suitable Component can be found
 593      * @see #getFirstComponent
 594      * @throws IllegalArgumentException if aContainer is null
 595      */
 596     public Component getDefaultComponent(Container aContainer) {
 597         return getFirstComponent(aContainer);
 598     }
 599 
 600     /**
 601      * Sets whether this SortingFocusTraversalPolicy transfers focus down-cycle
 602      * implicitly. If {@code true}, during normal focus traversal,
 603      * the Component traversed after a focus cycle root will be the focus-
 604      * cycle-root's default Component to focus. If {@code false}, the
 605      * next Component in the focus traversal cycle rooted at the specified
 606      * focus cycle root will be traversed instead. The default value for this
 607      * property is {@code true}.
 608      *
 609      * @param implicitDownCycleTraversal whether this
 610      *        SortingFocusTraversalPolicy transfers focus down-cycle implicitly
 611      * @see #getImplicitDownCycleTraversal
 612      * @see #getFirstComponent
 613      */
 614     public void setImplicitDownCycleTraversal(boolean implicitDownCycleTraversal) {
 615         this.implicitDownCycleTraversal = implicitDownCycleTraversal;
 616     }
 617 
 618     /**
 619      * Returns whether this SortingFocusTraversalPolicy transfers focus down-
 620      * cycle implicitly. If {@code true}, during normal focus
 621      * traversal, the Component traversed after a focus cycle root will be the
 622      * focus-cycle-root's default Component to focus. If {@code false},
 623      * the next Component in the focus traversal cycle rooted at the specified
 624      * focus cycle root will be traversed instead.
 625      *
 626      * @return whether this SortingFocusTraversalPolicy transfers focus down-
 627      *         cycle implicitly
 628      * @see #setImplicitDownCycleTraversal
 629      * @see #getFirstComponent
 630      */
 631     public boolean getImplicitDownCycleTraversal() {
 632         return implicitDownCycleTraversal;
 633     }
 634 
 635     /**
 636      * Sets the Comparator which will be used to sort the Components in a
 637      * focus traversal cycle.
 638      *
 639      * @param comparator the Comparator which will be used for sorting
 640      */
 641     protected void setComparator(Comparator<? super Component> comparator) {
 642         this.comparator = comparator;
 643     }
 644 
 645     /**
 646      * Returns the Comparator which will be used to sort the Components in a
 647      * focus traversal cycle.
 648      *
 649      * @return the Comparator which will be used for sorting
 650      */
 651     protected Comparator<? super Component> getComparator() {
 652         return comparator;
 653     }
 654 
 655     /**
 656      * Determines whether a Component is an acceptable choice as the new
 657      * focus owner. By default, this method will accept a Component if and
 658      * only if it is visible, displayable, enabled, and focusable.
 659      *
 660      * @param aComponent the Component whose fitness as a focus owner is to
 661      *        be tested
 662      * @return {@code true} if aComponent is visible, displayable,
 663      *         enabled, and focusable; {@code false} otherwise
 664      */
 665     protected boolean accept(Component aComponent) {
 666         return fitnessTestPolicy.accept(aComponent);
 667     }
 668 }
 669 
 670 // Create our own subclass and change accept to public so that we can call
 671 // accept.
 672 @SuppressWarnings("serial") // JDK-implementation class
 673 class SwingContainerOrderFocusTraversalPolicy
 674     extends java.awt.ContainerOrderFocusTraversalPolicy
 675 {
 676     public boolean accept(Component aComponent) {
 677         return super.accept(aComponent);
 678     }
 679 }
< prev index next >