1. /*
  2. * @(#)LegacyGlueFocusTraversalPolicy.java 1.6 03/12/19
  3. *
  4. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package javax.swing;
  8. import java.awt.FocusTraversalPolicy;
  9. import java.awt.Component;
  10. import java.awt.Container;
  11. import java.awt.Window;
  12. import java.util.HashMap;
  13. import java.util.HashSet;
  14. import java.io.*;
  15. /**
  16. * A FocusTraversalPolicy which provides support for legacy applications which
  17. * handle focus traversal via JComponent.setNextFocusableComponent or by
  18. * installing a custom DefaultFocusManager. If a specific traversal has not
  19. * been hard coded, then that traversal is provided either by the custom
  20. * DefaultFocusManager, or by a wrapped FocusTraversalPolicy instance.
  21. *
  22. * @version 1.6, 12/19/03
  23. * @author David Mendenhall
  24. */
  25. final class LegacyGlueFocusTraversalPolicy extends FocusTraversalPolicy
  26. implements Serializable
  27. {
  28. private transient FocusTraversalPolicy delegatePolicy;
  29. private transient DefaultFocusManager delegateManager;
  30. private HashMap forwardMap = new HashMap(),
  31. backwardMap = new HashMap();
  32. LegacyGlueFocusTraversalPolicy(FocusTraversalPolicy delegatePolicy) {
  33. this.delegatePolicy = delegatePolicy;
  34. }
  35. LegacyGlueFocusTraversalPolicy(DefaultFocusManager delegateManager) {
  36. this.delegateManager = delegateManager;
  37. }
  38. void setNextFocusableComponent(Component left, Component right) {
  39. forwardMap.put(left, right);
  40. backwardMap.put(right, left);
  41. }
  42. void unsetNextFocusableComponent(Component left, Component right) {
  43. forwardMap.remove(left);
  44. backwardMap.remove(right);
  45. }
  46. public Component getComponentAfter(Container focusCycleRoot,
  47. Component aComponent) {
  48. Component hardCoded = aComponent, prevHardCoded;
  49. HashSet sanity = new HashSet();
  50. do {
  51. prevHardCoded = hardCoded;
  52. hardCoded = (Component)forwardMap.get(hardCoded);
  53. if (hardCoded == null) {
  54. if (delegatePolicy != null &&
  55. prevHardCoded.isFocusCycleRoot(focusCycleRoot)) {
  56. return delegatePolicy.getComponentAfter(focusCycleRoot,
  57. prevHardCoded);
  58. } else if (delegateManager != null) {
  59. return delegateManager.
  60. getComponentAfter(focusCycleRoot, aComponent);
  61. } else {
  62. return null;
  63. }
  64. }
  65. if (sanity.contains(hardCoded)) {
  66. // cycle detected; bail
  67. return null;
  68. }
  69. sanity.add(hardCoded);
  70. } while (!accept(hardCoded));
  71. return hardCoded;
  72. }
  73. public Component getComponentBefore(Container focusCycleRoot,
  74. Component aComponent) {
  75. Component hardCoded = aComponent, prevHardCoded;
  76. HashSet sanity = new HashSet();
  77. do {
  78. prevHardCoded = hardCoded;
  79. hardCoded = (Component)backwardMap.get(hardCoded);
  80. if (hardCoded == null) {
  81. if (delegatePolicy != null &&
  82. prevHardCoded.isFocusCycleRoot(focusCycleRoot)) {
  83. return delegatePolicy.getComponentBefore(focusCycleRoot,
  84. prevHardCoded);
  85. } else if (delegateManager != null) {
  86. return delegateManager.
  87. getComponentBefore(focusCycleRoot, aComponent);
  88. } else {
  89. return null;
  90. }
  91. }
  92. if (sanity.contains(hardCoded)) {
  93. // cycle detected; bail
  94. return null;
  95. }
  96. sanity.add(hardCoded);
  97. } while (!accept(hardCoded));
  98. return hardCoded;
  99. }
  100. public Component getFirstComponent(Container focusCycleRoot) {
  101. if (delegatePolicy != null) {
  102. return delegatePolicy.getFirstComponent(focusCycleRoot);
  103. } else if (delegateManager != null) {
  104. return delegateManager.getFirstComponent(focusCycleRoot);
  105. } else {
  106. return null;
  107. }
  108. }
  109. public Component getLastComponent(Container focusCycleRoot) {
  110. if (delegatePolicy != null) {
  111. return delegatePolicy.getLastComponent(focusCycleRoot);
  112. } else if (delegateManager != null) {
  113. return delegateManager.getLastComponent(focusCycleRoot);
  114. } else {
  115. return null;
  116. }
  117. }
  118. public Component getDefaultComponent(Container focusCycleRoot) {
  119. if (delegatePolicy != null) {
  120. return delegatePolicy.getDefaultComponent(focusCycleRoot);
  121. } else {
  122. return getFirstComponent(focusCycleRoot);
  123. }
  124. }
  125. private boolean accept(Component aComponent) {
  126. if (!(aComponent.isVisible() && aComponent.isDisplayable() &&
  127. aComponent.isFocusable() && aComponent.isEnabled())) {
  128. return false;
  129. }
  130. // Verify that the Component is recursively enabled. Disabling a
  131. // heavyweight Container disables its children, whereas disabling
  132. // a lightweight Container does not.
  133. if (!(aComponent instanceof Window)) {
  134. for (Container enableTest = aComponent.getParent();
  135. enableTest != null;
  136. enableTest = enableTest.getParent())
  137. {
  138. if (!(enableTest.isEnabled() || enableTest.isLightweight())) {
  139. return false;
  140. }
  141. if (enableTest instanceof Window) {
  142. break;
  143. }
  144. }
  145. }
  146. return true;
  147. }
  148. private void writeObject(ObjectOutputStream out) throws IOException {
  149. out.defaultWriteObject();
  150. if (delegatePolicy instanceof Serializable) {
  151. out.writeObject(delegatePolicy);
  152. } else {
  153. out.writeObject(null);
  154. }
  155. if (delegateManager instanceof Serializable) {
  156. out.writeObject(delegateManager);
  157. } else {
  158. out.writeObject(null);
  159. }
  160. }
  161. private void readObject(ObjectInputStream in)
  162. throws IOException, ClassNotFoundException
  163. {
  164. in.defaultReadObject();
  165. delegatePolicy = (FocusTraversalPolicy)in.readObject();
  166. delegateManager = (DefaultFocusManager)in.readObject();
  167. }
  168. }