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