1 /* 2 * Copyright (c) 2002, 2017, 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 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 }