View Javadoc
1   /*
2    * Copyright (c) 2002, 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.plaf.basic;
26  
27  import java.lang.reflect.*;
28  import javax.swing.*;
29  import javax.swing.plaf.*;
30  
31  /**
32   * An ActionMap that populates its contents as necessary. The
33   * contents are populated by invoking the <code>loadActionMap</code>
34   * method on the passed in Object.
35   *
36   * @author Scott Violet
37   */
38  class LazyActionMap extends ActionMapUIResource {
39      /**
40       * Object to invoke <code>loadActionMap</code> on. This may be
41       * a Class object.
42       */
43      private transient Object _loader;
44  
45      /**
46       * Installs an ActionMap that will be populated by invoking the
47       * <code>loadActionMap</code> method on the specified Class
48       * when necessary.
49       * <p>
50       * This should be used if the ActionMap can be shared.
51       *
52       * @param c JComponent to install the ActionMap on.
53       * @param loaderClass Class object that gets loadActionMap invoked
54       *                    on.
55       * @param defaultsKey Key to use to defaults table to check for
56       *        existing map and what resulting Map will be registered on.
57       */
58      static void installLazyActionMap(JComponent c, Class loaderClass,
59                                       String defaultsKey) {
60          ActionMap map = (ActionMap)UIManager.get(defaultsKey);
61          if (map == null) {
62              map = new LazyActionMap(loaderClass);
63              UIManager.getLookAndFeelDefaults().put(defaultsKey, map);
64          }
65          SwingUtilities.replaceUIActionMap(c, map);
66      }
67  
68      /**
69       * Returns an ActionMap that will be populated by invoking the
70       * <code>loadActionMap</code> method on the specified Class
71       * when necessary.
72       * <p>
73       * This should be used if the ActionMap can be shared.
74       *
75       * @param c JComponent to install the ActionMap on.
76       * @param loaderClass Class object that gets loadActionMap invoked
77       *                    on.
78       * @param defaultsKey Key to use to defaults table to check for
79       *        existing map and what resulting Map will be registered on.
80       */
81      static ActionMap getActionMap(Class loaderClass,
82                                    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  
91  
92      private LazyActionMap(Class loader) {
93          _loader = loader;
94      }
95  
96      public void put(Action action) {
97          put(action.getValue(Action.NAME), action);
98      }
99  
100     public void put(Object key, Action action) {
101         loadIfNecessary();
102         super.put(key, action);
103     }
104 
105     public Action get(Object key) {
106         loadIfNecessary();
107         return super.get(key);
108     }
109 
110     public void remove(Object key) {
111         loadIfNecessary();
112         super.remove(key);
113     }
114 
115     public void clear() {
116         loadIfNecessary();
117         super.clear();
118     }
119 
120     public Object[] keys() {
121         loadIfNecessary();
122         return super.keys();
123     }
124 
125     public int size() {
126         loadIfNecessary();
127         return super.size();
128     }
129 
130     public Object[] allKeys() {
131         loadIfNecessary();
132         return super.allKeys();
133     }
134 
135     public void setParent(ActionMap map) {
136         loadIfNecessary();
137         super.setParent(map);
138     }
139 
140     private void loadIfNecessary() {
141         if (_loader != null) {
142             Object loader = _loader;
143 
144             _loader = null;
145             Class<?> klass = (Class<?>)loader;
146             try {
147                 Method method = klass.getDeclaredMethod("loadActionMap",
148                                       new Class[] { LazyActionMap.class });
149                 method.invoke(klass, new Object[] { this });
150             } catch (NoSuchMethodException nsme) {
151                 assert false : "LazyActionMap unable to load actions " +
152                         klass;
153             } catch (IllegalAccessException iae) {
154                 assert false : "LazyActionMap unable to load actions " +
155                         iae;
156             } catch (InvocationTargetException ite) {
157                 assert false : "LazyActionMap unable to load actions " +
158                         ite;
159             } catch (IllegalArgumentException iae) {
160                 assert false : "LazyActionMap unable to load actions " +
161                         iae;
162             }
163         }
164     }
165 }