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