1. /*
  2. * @(#)LazyActionMap.java 1.2 03/01/23
  3. *
  4. * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package com.sun.java.swing.plaf.gtk;
  8. import java.lang.reflect.*;
  9. import javax.swing.*;
  10. import javax.swing.plaf.*;
  11. /**
  12. * An ActionMap that populates its contents as necessary. The
  13. * contents can be populated in one of two ways:
  14. * <ul><li>By way of the <code>LazyActionMap.Loader</code> interface.
  15. * This should be used if the ActionMap will be unique and not
  16. * shared.
  17. * <li>By passing in a <code>Class</code> object that has the
  18. * public method <code>loadActionMap</code> which can be used for
  19. * populating the ActionMap. This is used if the ActionMap can be
  20. * shared.
  21. * </ul>
  22. *
  23. * @version 1.2, 01/23/03
  24. * @author Scott Violet
  25. */
  26. class LazyActionMap extends ActionMapUIResource {
  27. /**
  28. * This will either be an instanceof Loader, or a Class object
  29. * indicating we should use the static method loadActionMap
  30. * to load the actions.
  31. */
  32. private transient Object _loader;
  33. /**
  34. * Component passed to loadActionMap, may be null.
  35. */
  36. private transient JComponent _component;
  37. /**
  38. * Installs an ActionMap that will be populated by invoking the
  39. * <code>loadActionMap</code> method on the <code>loader</code>
  40. * when necessary.
  41. * <p>
  42. * This should be used if the ActionMap needs to be specific to
  43. * the Component.
  44. *
  45. * @param c JComponent to install the AcitonMap on.
  46. * @param loader Object used to populate ActionMap when needed.
  47. */
  48. static void installLazyActionMap(JComponent c, Loader loader) {
  49. SwingUtilities.replaceUIActionMap(c, new LazyActionMap(loader, c));
  50. }
  51. /**
  52. * Installs an ActionMap that will be populated by invoking the
  53. * <code>loadActionMap</code> method on the specified Class
  54. * when necessary.
  55. * <p>
  56. * This should be used if the ActionMap can be shared.
  57. *
  58. * @param c JComponent to install the ActionMap on.
  59. * @param loaderClass Class object that gets loadActionMap invoked
  60. * on.
  61. * @param defaultsKey Key to use to defaults table to check for
  62. * existing map and what resulting Map will be registered on.
  63. */
  64. static void installLazyActionMap(JComponent c, Class loaderClass,
  65. String defaultsKey) {
  66. ActionMap map = (ActionMap)UIManager.get(defaultsKey);
  67. if (map == null) {
  68. map = new LazyActionMap(loaderClass);
  69. UIManager.getLookAndFeelDefaults().put(defaultsKey, map);
  70. }
  71. SwingUtilities.replaceUIActionMap(c, map);
  72. }
  73. /**
  74. * Returns an ActionMap registered under the given name, creating
  75. * one as necessary.
  76. *
  77. * @param loaderClass Class object that gets loadActionMap invoked
  78. * on.
  79. * @param defaultsKey Key to use to defaults table to check for
  80. * existing map and what resulting Map will be registered on.
  81. */
  82. static ActionMap getActionMap(Class loaderClass, String defaultsKey) {
  83. ActionMap map = (ActionMap)UIManager.get(defaultsKey);
  84. if (map == null) {
  85. map = new LazyActionMap(loaderClass);
  86. UIManager.getLookAndFeelDefaults().put(defaultsKey, map);
  87. }
  88. return map;
  89. }
  90. private LazyActionMap(Loader loader, JComponent c) {
  91. _loader = loader;
  92. _component = c;
  93. }
  94. private LazyActionMap(Class loader) {
  95. _loader = loader;
  96. }
  97. public void put(Object key, Action action) {
  98. loadIfNecessary();
  99. super.put(key, action);
  100. }
  101. public Action get(Object key) {
  102. loadIfNecessary();
  103. return super.get(key);
  104. }
  105. public void remove(Object key) {
  106. loadIfNecessary();
  107. super.remove(key);
  108. }
  109. public void clear() {
  110. loadIfNecessary();
  111. super.clear();
  112. }
  113. public Object[] keys() {
  114. loadIfNecessary();
  115. return super.keys();
  116. }
  117. public int size() {
  118. loadIfNecessary();
  119. return super.size();
  120. }
  121. public Object[] allKeys() {
  122. loadIfNecessary();
  123. return super.allKeys();
  124. }
  125. private void loadIfNecessary() {
  126. if (_loader != null) {
  127. Object loader = _loader;
  128. _loader = null;
  129. if (loader instanceof Loader) {
  130. ((Loader)loader).loadActionMap(_component, this);
  131. }
  132. else {
  133. Class klass = (Class)loader;
  134. try {
  135. Method method = klass.getDeclaredMethod("loadActionMap",
  136. new Class[] { ActionMap.class });
  137. method.invoke(klass, new Object[] { this });
  138. } catch (NoSuchMethodException nsme) {
  139. assert false : "LazyActionMap unable to load actions " +
  140. klass;
  141. } catch (IllegalAccessException iae) {
  142. assert false : "LazyActionMap unable to load actions " +
  143. iae;
  144. } catch (InvocationTargetException ite) {
  145. assert false : "LazyActionMap unable to load actions " +
  146. ite;
  147. } catch (IllegalArgumentException iae) {
  148. assert false : "LazyActionMap unable to load actions " +
  149. iae;
  150. }
  151. }
  152. _component = null;
  153. }
  154. }
  155. /**
  156. * Interface used to populate the ActionMap.
  157. */
  158. public interface Loader {
  159. public void loadActionMap(JComponent c, ActionMap map);
  160. }
  161. }