blob: f8a37fe7a2bee4b900033578eb2d7f3385c0e360 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2000-2002 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 */
25package javax.swing;
26
27import java.awt.FocusTraversalPolicy;
28import java.awt.Component;
29import java.awt.Container;
30import java.awt.Window;
31import java.util.HashMap;
32import java.util.HashSet;
33import java.io.*;
34
35
36/**
37 * A FocusTraversalPolicy which provides support for legacy applications which
38 * handle focus traversal via JComponent.setNextFocusableComponent or by
39 * installing a custom DefaultFocusManager. If a specific traversal has not
40 * been hard coded, then that traversal is provided either by the custom
41 * DefaultFocusManager, or by a wrapped FocusTraversalPolicy instance.
42 *
43 * @author David Mendenhall
44 */
45final class LegacyGlueFocusTraversalPolicy extends FocusTraversalPolicy
46 implements Serializable
47{
48 private transient FocusTraversalPolicy delegatePolicy;
49 private transient DefaultFocusManager delegateManager;
50
51 private HashMap forwardMap = new HashMap(),
52 backwardMap = new HashMap();
53
54 LegacyGlueFocusTraversalPolicy(FocusTraversalPolicy delegatePolicy) {
55 this.delegatePolicy = delegatePolicy;
56 }
57 LegacyGlueFocusTraversalPolicy(DefaultFocusManager delegateManager) {
58 this.delegateManager = delegateManager;
59 }
60
61 void setNextFocusableComponent(Component left, Component right) {
62 forwardMap.put(left, right);
63 backwardMap.put(right, left);
64 }
65 void unsetNextFocusableComponent(Component left, Component right) {
66 forwardMap.remove(left);
67 backwardMap.remove(right);
68 }
69
70 public Component getComponentAfter(Container focusCycleRoot,
71 Component aComponent) {
72 Component hardCoded = aComponent, prevHardCoded;
73 HashSet sanity = new HashSet();
74
75 do {
76 prevHardCoded = hardCoded;
77 hardCoded = (Component)forwardMap.get(hardCoded);
78 if (hardCoded == null) {
79 if (delegatePolicy != null &&
80 prevHardCoded.isFocusCycleRoot(focusCycleRoot)) {
81 return delegatePolicy.getComponentAfter(focusCycleRoot,
82 prevHardCoded);
83 } else if (delegateManager != null) {
84 return delegateManager.
85 getComponentAfter(focusCycleRoot, aComponent);
86 } else {
87 return null;
88 }
89 }
90 if (sanity.contains(hardCoded)) {
91 // cycle detected; bail
92 return null;
93 }
94 sanity.add(hardCoded);
95 } while (!accept(hardCoded));
96
97 return hardCoded;
98 }
99 public Component getComponentBefore(Container focusCycleRoot,
100 Component aComponent) {
101 Component hardCoded = aComponent, prevHardCoded;
102 HashSet sanity = new HashSet();
103
104 do {
105 prevHardCoded = hardCoded;
106 hardCoded = (Component)backwardMap.get(hardCoded);
107 if (hardCoded == null) {
108 if (delegatePolicy != null &&
109 prevHardCoded.isFocusCycleRoot(focusCycleRoot)) {
110 return delegatePolicy.getComponentBefore(focusCycleRoot,
111 prevHardCoded);
112 } else if (delegateManager != null) {
113 return delegateManager.
114 getComponentBefore(focusCycleRoot, aComponent);
115 } else {
116 return null;
117 }
118 }
119 if (sanity.contains(hardCoded)) {
120 // cycle detected; bail
121 return null;
122 }
123 sanity.add(hardCoded);
124 } while (!accept(hardCoded));
125
126 return hardCoded;
127 }
128 public Component getFirstComponent(Container focusCycleRoot) {
129 if (delegatePolicy != null) {
130 return delegatePolicy.getFirstComponent(focusCycleRoot);
131 } else if (delegateManager != null) {
132 return delegateManager.getFirstComponent(focusCycleRoot);
133 } else {
134 return null;
135 }
136 }
137 public Component getLastComponent(Container focusCycleRoot) {
138 if (delegatePolicy != null) {
139 return delegatePolicy.getLastComponent(focusCycleRoot);
140 } else if (delegateManager != null) {
141 return delegateManager.getLastComponent(focusCycleRoot);
142 } else {
143 return null;
144 }
145 }
146 public Component getDefaultComponent(Container focusCycleRoot) {
147 if (delegatePolicy != null) {
148 return delegatePolicy.getDefaultComponent(focusCycleRoot);
149 } else {
150 return getFirstComponent(focusCycleRoot);
151 }
152 }
153 private boolean accept(Component aComponent) {
154 if (!(aComponent.isVisible() && aComponent.isDisplayable() &&
155 aComponent.isFocusable() && aComponent.isEnabled())) {
156 return false;
157 }
158
159 // Verify that the Component is recursively enabled. Disabling a
160 // heavyweight Container disables its children, whereas disabling
161 // a lightweight Container does not.
162 if (!(aComponent instanceof Window)) {
163 for (Container enableTest = aComponent.getParent();
164 enableTest != null;
165 enableTest = enableTest.getParent())
166 {
167 if (!(enableTest.isEnabled() || enableTest.isLightweight())) {
168 return false;
169 }
170 if (enableTest instanceof Window) {
171 break;
172 }
173 }
174 }
175
176 return true;
177 }
178 private void writeObject(ObjectOutputStream out) throws IOException {
179 out.defaultWriteObject();
180
181 if (delegatePolicy instanceof Serializable) {
182 out.writeObject(delegatePolicy);
183 } else {
184 out.writeObject(null);
185 }
186
187 if (delegateManager instanceof Serializable) {
188 out.writeObject(delegateManager);
189 } else {
190 out.writeObject(null);
191 }
192 }
193 private void readObject(ObjectInputStream in)
194 throws IOException, ClassNotFoundException
195 {
196 in.defaultReadObject();
197 delegatePolicy = (FocusTraversalPolicy)in.readObject();
198 delegateManager = (DefaultFocusManager)in.readObject();
199 }
200}