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