001 /* JAPI - (Yet another (hopefully) useful) Java API
002 *
003 * Copyright (C) 2004-2006 Christian Hujer
004 *
005 * This program is free software; you can redistribute it and/or
006 * modify it under the terms of the GNU General Public License as
007 * published by the Free Software Foundation; either version 2 of the
008 * License, or (at your option) any later version.
009 *
010 * This program is distributed in the hope that it will be useful, but
011 * WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
013 * General Public License for more details.
014 *
015 * You should have received a copy of the GNU General Public License
016 * along with this program; if not, write to the Free Software
017 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
018 * 02111-1307, USA.
019 */
020
021 package net.sf.japi.swing;
022
023 import java.net.URL;
024 import java.util.Map;
025 import java.util.WeakHashMap;
026 import java.util.List;
027 import java.util.ArrayList;
028 import java.util.Iterator;
029 import java.security.AccessController;
030 import java.security.PrivilegedAction;
031 import javax.swing.Icon;
032 import javax.swing.ImageIcon;
033 import org.jetbrains.annotations.Nullable;
034
035 /** Class to handle icons.
036 * Default size is 16.
037 * Instances must have an associated ClassLoader, otherwise several methods will not work properly but throw a NullPointerException instead.
038 * So if you do not provide a ClassLoader, be sure the class you provide has one, or if you use the no-arg constructor resp. the default instance, be
039 * sure the IconManager class itself was loaded with some ClassLoader other than <code>null</code>.
040 * @author <a href="mailto:chris@riedquat.de">Christian Hujer</a>
041 * @todo this class should be refactored into a more generic version and accessible through ActionFactory?
042 * @todo it should be possible to initialize the paths through properties
043 */
044 public final class IconManager {
045
046 /** The default IconManager. */
047 private static final IconManager DEFAULT_ICON_MANAGER = createDefaultIconManager();
048
049 /** Create the default IconManager.
050 * @return default IconManager
051 */
052 private static IconManager createDefaultIconManager() {
053 final IconManager defaultIconManager = new IconManager();
054 defaultIconManager.iconPaths.add("icons/");
055 defaultIconManager.iconPaths.add("toolbarButtonGraphics/");
056 return defaultIconManager;
057 }
058
059 /** ClassLoader to get icons from, must not be null. */
060 private final ClassLoader classLoader;
061
062 /** The available sizes provided by this IconManager. */
063 private final int[] availableSizes = { 16, 24 };
064
065 /** The icon cache.
066 * Key: short name for icon, which is likely to be used as a relative file name.
067 * Value: Icon
068 */
069 private final Map<String,Icon> smallCache = new WeakHashMap<String,Icon>();
070
071 /** The paths to search icons in. */
072 private final List<String> iconPaths = new ArrayList<String>();
073
074 /** Get the default IconManager.
075 * The ClassLoader in use is the classloader IconManager was loaded with, whatever classloader that was.
076 * @return default IconManaager
077 */
078 public static IconManager getDefaultIconManager() {
079 return DEFAULT_ICON_MANAGER;
080 }
081
082 /** Create a IconManager.
083 * Uses the IconManager's class loader.
084 * Only use this if you want to be independent of the global icon size settings.
085 * The recommended way to get a default IconManager instance is {#getDefaultIconManager()}.
086 */
087 public IconManager() {
088 this(getContextClassLoader());
089 //this(IconManager.class.getClassLoader());
090 }
091
092 private static ClassLoader getContextClassLoader() {
093 return AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
094 public ClassLoader run() {
095 try {
096 return Thread.currentThread().getContextClassLoader();
097 } catch (final SecurityException e) {
098 return getClass().getClassLoader();
099 }
100 }
101 });
102 }
103
104 /** Create an IconManager.
105 * @param clazz Class to get ClassLoader for IconManager
106 */
107 public IconManager(final Class<?> clazz) {
108 classLoader = clazz.getClassLoader();
109 }
110
111 /** Create an IconManager.
112 * @param cl ClassLoader to create IconManager for
113 */
114 public IconManager(final ClassLoader cl) {
115 classLoader = cl;
116 }
117
118 /** Return the available sizes for icons.
119 * @return available icon sizes
120 */
121 public int[] getAvailableSizes() {
122 return availableSizes.clone();
123 }
124
125 /** Load an icon.
126 * @param s icon name, like "general/About" or "navigation/Forward"
127 * @return Icon for <var>s</var>
128 */
129 @Nullable public Icon getIcon(final String s) {
130 Icon icon = smallCache.get(s);
131 if (icon == null) {
132 URL url = null;
133 // Search the configured class loader
134 for (final Iterator<String> it = iconPaths.iterator(); url == null && it.hasNext();) {
135 final String path = it.next();
136 final String iconPath = path + (path.endsWith("/") ? "" : "/") + s + ".gif";
137 url = classLoader.getResource(iconPath);
138 }
139 if (url == null) {
140 // if searching the configured class loader failed, search the system class loader
141 for (final Iterator<String> it = iconPaths.iterator(); url == null && it.hasNext();) {
142 final String path = it.next();
143 final String iconPath = path + (path.endsWith("/") ? "" : "/") + s + ".gif";
144 url = ClassLoader.getSystemResource(iconPath);
145 }
146 }
147 if (url == null) {
148 return null;
149 }
150 icon = new ImageIcon(url);
151 smallCache.put(s, icon);
152 }
153 return icon;
154 }
155
156 } // class IconManager