27 import java.awt.Component; |
27 import java.awt.Component; |
28 import java.awt.Container; |
28 import java.awt.Container; |
29 import java.awt.Window; |
29 import java.awt.Window; |
30 import java.util.*; |
30 import java.util.*; |
31 import java.awt.FocusTraversalPolicy; |
31 import java.awt.FocusTraversalPolicy; |
32 import java.util.logging.*; |
32 import sun.util.logging.PlatformLogger; |
33 |
33 |
34 /** |
34 /** |
35 * A FocusTraversalPolicy that determines traversal order by sorting the |
35 * A FocusTraversalPolicy that determines traversal order by sorting the |
36 * Components of a focus traversal cycle based on a given Comparator. Portions |
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 |
37 * of the Component hierarchy that are not visible and displayable will not be |
62 extends InternalFrameFocusTraversalPolicy |
62 extends InternalFrameFocusTraversalPolicy |
63 { |
63 { |
64 private Comparator<? super Component> comparator; |
64 private Comparator<? super Component> comparator; |
65 private boolean implicitDownCycleTraversal = true; |
65 private boolean implicitDownCycleTraversal = true; |
66 |
66 |
67 private Logger log = Logger.getLogger("javax.swing.SortingFocusTraversalPolicy"); |
67 private PlatformLogger log = PlatformLogger.getLogger("javax.swing.SortingFocusTraversalPolicy"); |
68 |
68 |
69 /** |
69 /** |
70 * Used by getComponentAfter and getComponentBefore for efficiency. In |
70 * Used by getComponentAfter and getComponentBefore for efficiency. In |
71 * order to maintain compliance with the specification of |
71 * order to maintain compliance with the specification of |
72 * FocusTraversalPolicy, if traversal wraps, we should invoke |
72 * FocusTraversalPolicy, if traversal wraps, we should invoke |
113 private int getComponentIndex(List<Component> cycle, Component aComponent) { |
113 private int getComponentIndex(List<Component> cycle, Component aComponent) { |
114 int index; |
114 int index; |
115 try { |
115 try { |
116 index = Collections.binarySearch(cycle, aComponent, comparator); |
116 index = Collections.binarySearch(cycle, aComponent, comparator); |
117 } catch (ClassCastException e) { |
117 } catch (ClassCastException e) { |
118 if (log.isLoggable(Level.FINE)) { |
118 if (log.isLoggable(PlatformLogger.FINE)) { |
119 log.log(Level.FINE, "### During the binary search for " + aComponent + " the exception occured: ", e); |
119 log.fine("### During the binary search for " + aComponent + " the exception occured: ", e); |
120 } |
120 } |
121 return -1; |
121 return -1; |
122 } |
122 } |
123 if (index < 0) { |
123 if (index < 0) { |
124 // Fix for 5070991. |
124 // Fix for 5070991. |
191 |
191 |
192 if (cont.isFocusCycleRoot()) { |
192 if (cont.isFocusCycleRoot()) { |
193 if (getImplicitDownCycleTraversal()) { |
193 if (getImplicitDownCycleTraversal()) { |
194 retComp = cont.getFocusTraversalPolicy().getDefaultComponent(cont); |
194 retComp = cont.getFocusTraversalPolicy().getDefaultComponent(cont); |
195 |
195 |
196 if (retComp != null && log.isLoggable(Level.FINE)) { |
196 if (retComp != null && log.isLoggable(PlatformLogger.FINE)) { |
197 log.fine("### Transfered focus down-cycle to " + retComp + |
197 log.fine("### Transfered focus down-cycle to " + retComp + |
198 " in the focus cycle root " + cont); |
198 " in the focus cycle root " + cont); |
199 } |
199 } |
200 } else { |
200 } else { |
201 return null; |
201 return null; |
203 } else if (cont.isFocusTraversalPolicyProvider()) { |
203 } else if (cont.isFocusTraversalPolicyProvider()) { |
204 retComp = (traversalDirection == FORWARD_TRAVERSAL ? |
204 retComp = (traversalDirection == FORWARD_TRAVERSAL ? |
205 cont.getFocusTraversalPolicy().getDefaultComponent(cont) : |
205 cont.getFocusTraversalPolicy().getDefaultComponent(cont) : |
206 cont.getFocusTraversalPolicy().getLastComponent(cont)); |
206 cont.getFocusTraversalPolicy().getLastComponent(cont)); |
207 |
207 |
208 if (retComp != null && log.isLoggable(Level.FINE)) { |
208 if (retComp != null && log.isLoggable(PlatformLogger.FINE)) { |
209 log.fine("### Transfered focus to " + retComp + " in the FTP provider " + cont); |
209 log.fine("### Transfered focus to " + retComp + " in the FTP provider " + cont); |
210 } |
210 } |
211 } |
211 } |
212 } |
212 } |
213 return retComp; |
213 return retComp; |
234 * @throws IllegalArgumentException if aContainer is not a focus cycle |
234 * @throws IllegalArgumentException if aContainer is not a focus cycle |
235 * root of aComponent or a focus traversal policy provider, or if either aContainer or |
235 * root of aComponent or a focus traversal policy provider, or if either aContainer or |
236 * aComponent is null |
236 * aComponent is null |
237 */ |
237 */ |
238 public Component getComponentAfter(Container aContainer, Component aComponent) { |
238 public Component getComponentAfter(Container aContainer, Component aComponent) { |
239 if (log.isLoggable(Level.FINE)) { |
239 if (log.isLoggable(PlatformLogger.FINE)) { |
240 log.fine("### Searching in " + aContainer + " for component after " + aComponent); |
240 log.fine("### Searching in " + aContainer + " for component after " + aComponent); |
241 } |
241 } |
242 |
242 |
243 if (aContainer == null || aComponent == null) { |
243 if (aContainer == null || aComponent == null) { |
244 throw new IllegalArgumentException("aContainer and aComponent cannot be null"); |
244 throw new IllegalArgumentException("aContainer and aComponent cannot be null"); |
258 } |
258 } |
259 |
259 |
260 // See if the component is inside of policy provider. |
260 // See if the component is inside of policy provider. |
261 Container provider = getTopmostProvider(aContainer, aComponent); |
261 Container provider = getTopmostProvider(aContainer, aComponent); |
262 if (provider != null) { |
262 if (provider != null) { |
263 if (log.isLoggable(Level.FINE)) { |
263 if (log.isLoggable(PlatformLogger.FINE)) { |
264 log.fine("### Asking FTP " + provider + " for component after " + aComponent); |
264 log.fine("### Asking FTP " + provider + " for component after " + aComponent); |
265 } |
265 } |
266 |
266 |
267 // FTP knows how to find component after the given. We don't. |
267 // FTP knows how to find component after the given. We don't. |
268 FocusTraversalPolicy policy = provider.getFocusTraversalPolicy(); |
268 FocusTraversalPolicy policy = provider.getFocusTraversalPolicy(); |
269 Component afterComp = policy.getComponentAfter(provider, aComponent); |
269 Component afterComp = policy.getComponentAfter(provider, aComponent); |
270 |
270 |
271 // Null result means that we overstepped the limit of the FTP's cycle. |
271 // Null result means that we overstepped the limit of the FTP's cycle. |
272 // In that case we must quit the cycle, otherwise return the component found. |
272 // In that case we must quit the cycle, otherwise return the component found. |
273 if (afterComp != null) { |
273 if (afterComp != null) { |
274 if (log.isLoggable(Level.FINE)) log.fine("### FTP returned " + afterComp); |
274 if (log.isLoggable(PlatformLogger.FINE)) log.fine("### FTP returned " + afterComp); |
275 return afterComp; |
275 return afterComp; |
276 } |
276 } |
277 aComponent = provider; |
277 aComponent = provider; |
278 } |
278 } |
279 |
279 |
280 List<Component> cycle = getFocusTraversalCycle(aContainer); |
280 List<Component> cycle = getFocusTraversalCycle(aContainer); |
281 |
281 |
282 if (log.isLoggable(Level.FINE)) log.fine("### Cycle is " + cycle + ", component is " + aComponent); |
282 if (log.isLoggable(PlatformLogger.FINE)) log.fine("### Cycle is " + cycle + ", component is " + aComponent); |
283 |
283 |
284 int index = getComponentIndex(cycle, aComponent); |
284 int index = getComponentIndex(cycle, aComponent); |
285 |
285 |
286 if (index < 0) { |
286 if (index < 0) { |
287 if (log.isLoggable(Level.FINE)) { |
287 if (log.isLoggable(PlatformLogger.FINE)) { |
288 log.fine("### Didn't find component " + aComponent + " in a cycle " + aContainer); |
288 log.fine("### Didn't find component " + aComponent + " in a cycle " + aContainer); |
289 } |
289 } |
290 return getFirstComponent(aContainer); |
290 return getFirstComponent(aContainer); |
291 } |
291 } |
292 |
292 |
347 } |
347 } |
348 |
348 |
349 // See if the component is inside of policy provider. |
349 // See if the component is inside of policy provider. |
350 Container provider = getTopmostProvider(aContainer, aComponent); |
350 Container provider = getTopmostProvider(aContainer, aComponent); |
351 if (provider != null) { |
351 if (provider != null) { |
352 if (log.isLoggable(Level.FINE)) { |
352 if (log.isLoggable(PlatformLogger.FINE)) { |
353 log.fine("### Asking FTP " + provider + " for component after " + aComponent); |
353 log.fine("### Asking FTP " + provider + " for component after " + aComponent); |
354 } |
354 } |
355 |
355 |
356 // FTP knows how to find component after the given. We don't. |
356 // FTP knows how to find component after the given. We don't. |
357 FocusTraversalPolicy policy = provider.getFocusTraversalPolicy(); |
357 FocusTraversalPolicy policy = provider.getFocusTraversalPolicy(); |
358 Component beforeComp = policy.getComponentBefore(provider, aComponent); |
358 Component beforeComp = policy.getComponentBefore(provider, aComponent); |
359 |
359 |
360 // Null result means that we overstepped the limit of the FTP's cycle. |
360 // Null result means that we overstepped the limit of the FTP's cycle. |
361 // In that case we must quit the cycle, otherwise return the component found. |
361 // In that case we must quit the cycle, otherwise return the component found. |
362 if (beforeComp != null) { |
362 if (beforeComp != null) { |
363 if (log.isLoggable(Level.FINE)) log.fine("### FTP returned " + beforeComp); |
363 if (log.isLoggable(PlatformLogger.FINE)) log.fine("### FTP returned " + beforeComp); |
364 return beforeComp; |
364 return beforeComp; |
365 } |
365 } |
366 aComponent = provider; |
366 aComponent = provider; |
367 |
367 |
368 // If the provider is traversable it's returned. |
368 // If the provider is traversable it's returned. |
371 } |
371 } |
372 } |
372 } |
373 |
373 |
374 List<Component> cycle = getFocusTraversalCycle(aContainer); |
374 List<Component> cycle = getFocusTraversalCycle(aContainer); |
375 |
375 |
376 if (log.isLoggable(Level.FINE)) log.fine("### Cycle is " + cycle + ", component is " + aComponent); |
376 if (log.isLoggable(PlatformLogger.FINE)) log.fine("### Cycle is " + cycle + ", component is " + aComponent); |
377 |
377 |
378 int index = getComponentIndex(cycle, aComponent); |
378 int index = getComponentIndex(cycle, aComponent); |
379 |
379 |
380 if (index < 0) { |
380 if (index < 0) { |
381 if (log.isLoggable(Level.FINE)) { |
381 if (log.isLoggable(PlatformLogger.FINE)) { |
382 log.fine("### Didn't find component " + aComponent + " in a cycle " + aContainer); |
382 log.fine("### Didn't find component " + aComponent + " in a cycle " + aContainer); |
383 } |
383 } |
384 return getLastComponent(aContainer); |
384 return getLastComponent(aContainer); |
385 } |
385 } |
386 |
386 |
422 * @throws IllegalArgumentException if aContainer is null |
422 * @throws IllegalArgumentException if aContainer is null |
423 */ |
423 */ |
424 public Component getFirstComponent(Container aContainer) { |
424 public Component getFirstComponent(Container aContainer) { |
425 List<Component> cycle; |
425 List<Component> cycle; |
426 |
426 |
427 if (log.isLoggable(Level.FINE)) log.fine("### Getting first component in " + aContainer); |
427 if (log.isLoggable(PlatformLogger.FINE)) log.fine("### Getting first component in " + aContainer); |
428 if (aContainer == null) { |
428 if (aContainer == null) { |
429 throw new IllegalArgumentException("aContainer cannot be null"); |
429 throw new IllegalArgumentException("aContainer cannot be null"); |
430 } |
430 } |
431 |
431 |
432 if (this.cachedRoot == aContainer) { |
432 if (this.cachedRoot == aContainer) { |
434 } else { |
434 } else { |
435 cycle = getFocusTraversalCycle(aContainer); |
435 cycle = getFocusTraversalCycle(aContainer); |
436 } |
436 } |
437 |
437 |
438 if (cycle.size() == 0) { |
438 if (cycle.size() == 0) { |
439 if (log.isLoggable(Level.FINE)) log.fine("### Cycle is empty"); |
439 if (log.isLoggable(PlatformLogger.FINE)) log.fine("### Cycle is empty"); |
440 return null; |
440 return null; |
441 } |
441 } |
442 if (log.isLoggable(Level.FINE)) log.fine("### Cycle is " + cycle); |
442 if (log.isLoggable(PlatformLogger.FINE)) log.fine("### Cycle is " + cycle); |
443 |
443 |
444 for (Component comp : cycle) { |
444 for (Component comp : cycle) { |
445 if (accept(comp)) { |
445 if (accept(comp)) { |
446 return comp; |
446 return comp; |
447 } else if (comp != aContainer && |
447 } else if (comp != aContainer && |
464 * or null if no suitable Component can be found |
464 * or null if no suitable Component can be found |
465 * @throws IllegalArgumentException if aContainer is null |
465 * @throws IllegalArgumentException if aContainer is null |
466 */ |
466 */ |
467 public Component getLastComponent(Container aContainer) { |
467 public Component getLastComponent(Container aContainer) { |
468 List<Component> cycle; |
468 List<Component> cycle; |
469 if (log.isLoggable(Level.FINE)) log.fine("### Getting last component in " + aContainer); |
469 if (log.isLoggable(PlatformLogger.FINE)) log.fine("### Getting last component in " + aContainer); |
470 |
470 |
471 if (aContainer == null) { |
471 if (aContainer == null) { |
472 throw new IllegalArgumentException("aContainer cannot be null"); |
472 throw new IllegalArgumentException("aContainer cannot be null"); |
473 } |
473 } |
474 |
474 |
477 } else { |
477 } else { |
478 cycle = getFocusTraversalCycle(aContainer); |
478 cycle = getFocusTraversalCycle(aContainer); |
479 } |
479 } |
480 |
480 |
481 if (cycle.size() == 0) { |
481 if (cycle.size() == 0) { |
482 if (log.isLoggable(Level.FINE)) log.fine("### Cycle is empty"); |
482 if (log.isLoggable(PlatformLogger.FINE)) log.fine("### Cycle is empty"); |
483 return null; |
483 return null; |
484 } |
484 } |
485 if (log.isLoggable(Level.FINE)) log.fine("### Cycle is " + cycle); |
485 if (log.isLoggable(PlatformLogger.FINE)) log.fine("### Cycle is " + cycle); |
486 |
486 |
487 for (int i= cycle.size() - 1; i >= 0; i--) { |
487 for (int i= cycle.size() - 1; i >= 0; i--) { |
488 Component comp = cycle.get(i); |
488 Component comp = cycle.get(i); |
489 if (accept(comp)) { |
489 if (accept(comp)) { |
490 return comp; |
490 return comp; |