1 /* 2 * Copyright (c) 2000, 2008, Oracle and/or its affiliates. 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package javax.swing; 26 27 import java.awt.FocusTraversalPolicy; 28 import java.awt.Component; 29 import java.awt.Container; 30 import java.awt.Window; 31 import java.util.HashMap; 32 import java.util.HashSet; 33 import 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 */ 45 final class LegacyGlueFocusTraversalPolicy extends FocusTraversalPolicy 46 implements Serializable 47 { 48 private transient FocusTraversalPolicy delegatePolicy; 49 private transient DefaultFocusManager delegateManager; 50 51 private HashMap<Component, Component> forwardMap = new HashMap<Component, Component>(), 52 backwardMap = new HashMap<Component, Component>(); 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<Component> sanity = new HashSet<Component>(); 74 75 do { 76 prevHardCoded = hardCoded; 77 hardCoded = 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<Component> sanity = new HashSet<Component>(); 103 104 do { 105 prevHardCoded = hardCoded; 106 hardCoded = 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 }