001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: /**
019: * @author Anton Avtamonov
020: * @version $Revision$
021: */package javax.swing;
022:
023: import java.awt.Component;
024: import java.awt.Container;
025: import java.util.Collections;
026: import java.util.Comparator;
027: import java.util.LinkedList;
028: import java.util.List;
029:
030: import org.apache.harmony.x.swing.internal.nls.Messages;
031:
032: public class SortingFocusTraversalPolicy extends
033: InternalFrameFocusTraversalPolicy {
034: private Comparator<? super java.awt.Component> comparator;
035: private boolean isImplicitDownCycleTraversal = true;
036:
037: private final NextComponentFinder afterComponentFinder = new NextComponentFinder() {
038: public Component findNextComponent(
039: final List availableComponents,
040: final int currentComponentIndex) {
041: if (isImplicitDownCycleTraversal
042: && currentComponent instanceof Container
043: && ((Container) currentComponent)
044: .isFocusCycleRoot()) {
045:
046: Container innerCycleRoot = (Container) currentComponent;
047: return innerCycleRoot.getFocusTraversalPolicy()
048: .getDefaultComponent(innerCycleRoot);
049: } else {
050: int nextIndex = (currentComponentIndex + 1)
051: % availableComponents.size();
052: Component result = (Component) availableComponents
053: .get(nextIndex);
054:
055: if (focusCycleRoot.isFocusCycleRoot()) {
056: Container policyProviderForCurrentComponent = getPolicyProvider(currentComponent);
057: if (currentComponent == focusCycleRoot
058: || policyProviderForCurrentComponent == focusCycleRoot) {
059: if (result instanceof Container
060: && ((Container) result)
061: .isFocusTraversalPolicyProvider()
062: && !accept(result)) {
063:
064: Container policyProvider = (Container) result;
065:
066: return policyProvider
067: .getFocusTraversalPolicy()
068: .getDefaultComponent(policyProvider);
069: }
070:
071: return result;
072: } else {
073: Component resultFromProvider = policyProviderForCurrentComponent
074: .getFocusTraversalPolicy()
075: .getComponentAfter(
076: policyProviderForCurrentComponent,
077: currentComponent);
078: if (resultFromProvider != policyProviderForCurrentComponent
079: .getFocusTraversalPolicy()
080: .getDefaultComponent(
081: policyProviderForCurrentComponent)) {
082: return resultFromProvider;
083: } else {
084: return focusCycleRoot
085: .getFocusTraversalPolicy()
086: .getComponentAfter(focusCycleRoot,
087: policyProviderForCurrentComponent);
088: }
089: }
090: } else {
091: return result;
092: }
093: }
094: }
095: };
096:
097: private final NextComponentFinder beforeComponentFinder = new NextComponentFinder() {
098: public Component findNextComponent(
099: final List availableComponents,
100: final int currentComponentIndex) {
101: int nextIndex = (currentComponentIndex
102: + availableComponents.size() - 1)
103: % availableComponents.size();
104: Component result = (Component) availableComponents
105: .get(nextIndex);
106:
107: if (focusCycleRoot.isFocusCycleRoot()) {
108: Container policyProviderForCurrentComponent = getPolicyProvider(currentComponent);
109: if (currentComponent == focusCycleRoot
110: || policyProviderForCurrentComponent == focusCycleRoot) {
111: if (result instanceof Container
112: && ((Container) result)
113: .isFocusTraversalPolicyProvider()
114: && !accept(result)) {
115:
116: Container policyProvider = (Container) result;
117:
118: return policyProvider.getFocusTraversalPolicy()
119: .getLastComponent(policyProvider);
120: }
121:
122: return result;
123: } else {
124: Component resultFromProvider = policyProviderForCurrentComponent
125: .getFocusTraversalPolicy()
126: .getComponentBefore(
127: policyProviderForCurrentComponent,
128: currentComponent);
129: if (resultFromProvider != policyProviderForCurrentComponent
130: .getFocusTraversalPolicy()
131: .getLastComponent(
132: policyProviderForCurrentComponent)) {
133: return resultFromProvider;
134: } else {
135: return focusCycleRoot
136: .getFocusTraversalPolicy()
137: .getComponentBefore(focusCycleRoot,
138: policyProviderForCurrentComponent);
139: }
140: }
141: } else {
142: return result;
143: }
144: }
145: };
146:
147: private final NextComponentFinder firstComponentFinder = new NextComponentFinder() {
148: public Component findNextComponent(
149: final List availableComponents,
150: final int currentComponentIndex) {
151: return (Component) availableComponents.get(0);
152: }
153: };
154:
155: private final NextComponentFinder lastComponentFinder = new NextComponentFinder() {
156: public Component findNextComponent(
157: final List availableComponents,
158: final int currentComponentIndex) {
159: return (Component) availableComponents
160: .get(availableComponents.size() - 1);
161: }
162: };
163:
164: public SortingFocusTraversalPolicy(
165: final Comparator<? super java.awt.Component> comparator) {
166: setComparator(comparator);
167: }
168:
169: protected SortingFocusTraversalPolicy() {
170: }
171:
172: public Component getComponentBefore(final Container focusCycleRoot,
173: final Component component) {
174: beforeComponentFinder.focusCycleRoot = focusCycleRoot;
175: beforeComponentFinder.currentComponent = component;
176:
177: return getComponentBeforeOrAfter(beforeComponentFinder);
178: }
179:
180: public Component getComponentAfter(final Container focusCycleRoot,
181: final Component component) {
182: afterComponentFinder.focusCycleRoot = focusCycleRoot;
183: afterComponentFinder.currentComponent = component;
184:
185: return getComponentBeforeOrAfter(afterComponentFinder);
186: }
187:
188: public Component getLastComponent(final Container focusCycleRoot) {
189: lastComponentFinder.focusCycleRoot = focusCycleRoot;
190:
191: return getFirstOrLastComponent(lastComponentFinder);
192: }
193:
194: public Component getFirstComponent(final Container focusCycleRoot) {
195: firstComponentFinder.focusCycleRoot = focusCycleRoot;
196:
197: return getFirstOrLastComponent(firstComponentFinder);
198: }
199:
200: public Component getDefaultComponent(final Container focusCycleRoot) {
201: return getFirstComponent(focusCycleRoot);
202: }
203:
204: public void setImplicitDownCycleTraversal(
205: final boolean implicitDownCycleTraversal) {
206: isImplicitDownCycleTraversal = implicitDownCycleTraversal;
207: }
208:
209: public boolean getImplicitDownCycleTraversal() {
210: return isImplicitDownCycleTraversal;
211: }
212:
213: protected void setComparator(
214: final Comparator<? super java.awt.Component> c) {
215: comparator = c;
216: }
217:
218: protected Comparator<? super java.awt.Component> getComparator() {
219: return comparator;
220: }
221:
222: protected boolean accept(final Component candidate) {
223: return candidate.isVisible() && candidate.isDisplayable()
224: && candidate.isEnabled() && candidate.isFocusable();
225: }
226:
227: private List getAllAcceptableComponentsSorted(
228: final Container focusCycleRoot,
229: final Component currentComponent,
230: final boolean includeCycleRootAndComponent) {
231: assert comparator != null;
232:
233: List result = new LinkedList();
234:
235: if (!focusCycleRoot.isShowing()) {
236: return result;
237: }
238:
239: if (includeCycleRootAndComponent && accept(focusCycleRoot)) {
240: result.add(focusCycleRoot);
241: }
242:
243: collectAllAcceptableComponents(focusCycleRoot, result);
244: if (includeCycleRootAndComponent && !result.isEmpty()
245: && currentComponent != null
246: && !result.contains(currentComponent)) {
247:
248: result.add(currentComponent);
249: }
250: Collections.sort(result, comparator);
251:
252: return result;
253: }
254:
255: private List collectAllAcceptableComponents(
256: final Container container, final List result) {
257: Component[] components = container.getComponents();
258: for (int i = 0; i < components.length; i++) {
259: Component component = components[i];
260: if (accept(component)
261: || ((component instanceof Container)
262: && ((Container) component)
263: .isFocusTraversalPolicyProvider() && ((Container) component)
264: .getComponentCount() > 0)) {
265:
266: result.add(component);
267: }
268:
269: if (component.isDisplayable() && component.isVisible()
270: && component instanceof Container
271: && !isPolicyRoot((Container) component)) {
272: collectAllAcceptableComponents((Container) component,
273: result);
274: }
275: }
276:
277: return result;
278: }
279:
280: private Component getComponentBeforeOrAfter(
281: final NextComponentFinder finder) {
282: checkCycleRootIsNotNull(finder.focusCycleRoot);
283: if (!finder.focusCycleRoot.isFocusCycleRoot()
284: && !finder.focusCycleRoot
285: .isFocusTraversalPolicyProvider()) {
286: throw new IllegalArgumentException(Messages
287: .getString("swing.54")); //$NON-NLS-1$
288: }
289:
290: if (finder.currentComponent == null) {
291: throw new IllegalArgumentException(Messages.getString(
292: "swing.55", "Component")); //$NON-NLS-1$ //$NON-NLS-2$
293: }
294:
295: if (finder.currentComponent != finder.focusCycleRoot
296: && finder.currentComponent.getFocusCycleRootAncestor() != finder.focusCycleRoot
297: && getPolicyProvider(finder.currentComponent) != finder.focusCycleRoot) {
298:
299: throw new IllegalArgumentException(Messages
300: .getString("swing.56")); //$NON-NLS-1$
301: }
302:
303: List components = getAllAcceptableComponentsSorted(
304: finder.focusCycleRoot, finder.currentComponent, true);
305: if (components.size() == 0) {
306: return null;
307: }
308:
309: int componentIndex = components
310: .indexOf(finder.currentComponent);
311: return finder.findNextComponent(components, componentIndex);
312: }
313:
314: private Component getFirstOrLastComponent(
315: final NextComponentFinder finder) {
316: checkCycleRootIsNotNull(finder.focusCycleRoot);
317:
318: List components = getAllAcceptableComponentsSorted(
319: finder.focusCycleRoot, null, false);
320: if (components.size() == 0) {
321: return null;
322: }
323:
324: return finder.findNextComponent(components, -1);
325: }
326:
327: private static void checkCycleRootIsNotNull(
328: final Container focusCycleRoot) {
329: if (focusCycleRoot == null) {
330: throw new IllegalArgumentException(Messages.getString(
331: "swing.55", "Container")); //$NON-NLS-1$ //$NON-NLS-2$
332: }
333: }
334:
335: private Container getPolicyProvider(final Component c) {
336: Container parent = c.getParent();
337: if (parent == null || isPolicyRoot(parent)) {
338: return parent;
339: }
340: return getPolicyProvider(parent);
341: }
342:
343: private boolean isPolicyRoot(final Container c) {
344: return c.isFocusTraversalPolicyProvider()
345: || c.isFocusCycleRoot();
346: }
347:
348: private abstract class NextComponentFinder {
349: public Container focusCycleRoot;
350: public Component currentComponent;
351:
352: public abstract Component findNextComponent(
353: List availableComponents, int currentComponentIndex);
354: }
355: }
|