001/* ---------------------------------------------------------------------------- 002 The Kiwi Toolkit - A Java Class Library 003 Copyright (C) 1998-2004 Mark A. Lindner 004 005 This library 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 library is distributed in the hope that it will be useful, 011 but 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 library; if not, write to the Free Software 017 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 018 02111-1307, USA. 019 020 The author may be contacted at: mark_a_lindner@yahoo.com 021 ---------------------------------------------------------------------------- 022 $Log: UIChangeManager.java,v $ 023 Revision 1.12 2004/05/12 18:51:35 markl 024 comment block updates 025 026 Revision 1.11 2003/04/30 04:36:17 markl 027 Add default frame icon property. 028 029 Revision 1.10 2003/01/19 09:50:54 markl 030 Javadoc & comment header updates. 031 032 Revision 1.9 2001/03/12 09:28:01 markl 033 Source code and Javadoc cleanup. 034 035 Revision 1.8 1999/07/29 04:34:17 markl 036 Minor tweaks. 037 038 Revision 1.7 1999/06/08 06:47:22 markl 039 Added import statement. 040 041 Revision 1.6 1999/05/15 08:16:14 markl 042 bug fix 043 044 Revision 1.5 1999/05/10 08:59:17 markl 045 Changed param type on setColorTheme(), fixed default texture filename. 046 047 Revision 1.4 1999/04/26 09:27:32 markl 048 Added method for setting theme. 049 050 Revision 1.3 1999/04/25 04:12:41 markl 051 Changes to support solid backgrounds in addition to textures. 052 053 Revision 1.2 1999/01/10 03:01:37 markl 054 added GPL header & RCS tag 055 ---------------------------------------------------------------------------- 056*/ 057 058package kiwi.ui; 059 060import java.awt.*; 061import java.util.*; 062import java.beans.*; 063import javax.swing.*; 064import javax.swing.UIManager.LookAndFeelInfo; 065import javax.swing.plaf.metal.*; 066 067import kiwi.event.*; 068import kiwi.io.*; 069import kiwi.util.*; 070 071/** This class functions as a clearinghouse for global appearance and look & 072 * feel changes for an application. <code>UIChangeManager</code> manages 073 * two lists of objects. 074 * <p> 075 * The first is a list of JFC components that need to be redrawn when the 076 * application's Look & Feel changes. Generally only top-level components, 077 * like descendants of <code>JDialog</code> and <code>JFrame</code>, need to 078 * be registered, as the <code>UIChangeManager</code> updates the Look & Feel 079 * on the entire component hierarchy of each registered component. 080 * The Kiwi <code>KFrame</code> and <code>KDialog</code> 081 * superclasses automatically register themselves with the change manager, so 082 * any class that extends either of these will inherit this behavior. 083 * <p> 084 * The second is a list of classes that wish to be notified of other, more 085 * fine-grained appearance changes that take place in the application: for 086 * example, a change in the default background texture. Potentially hundreds 087 * of components could be affected by a change in one of these appearance 088 * properties, so it would be wasteful to register all of them for 089 * notification by <code>UIChangeManager</code>. The preferred alternative is 090 * for each component to consult <code>UIChangeManager</code> for the current 091 * settings of the appropriate properties when it is constructing itself, so 092 * that its appearance is in accordance with the current settings. Obviously, 093 * only subsequently-created components will inherit appearance property 094 * changes. For this reason, interface components that employ the singleton 095 * pattern will need to register themselves as 096 * <code>PropertyChangeListener</code>s of <code>UIChangeManager</code> and 097 * redraw themselves when a property changes. <code>DialogSet</code> is an 098 * example of a class that implements this behavior. 099 * 100 * @author Mark Lindner 101 */ 102 103public final class UIChangeManager implements PropertyChangeSource 104 { 105 private static UIChangeManager instance = new UIChangeManager(); 106 private static Vector components, listeners; 107 private static Properties props; 108 private static PropertyChangeSupport support; 109 /** Button opacity property. */ 110 public static final String BUTTON_OPACITY_PROPERTY = "button.opacity"; 111 /** Default texture property. */ 112 public static final String TEXTURE_PROPERTY = "texture"; 113 public static final String FRAME_ICON_PROPERTY = "frame.icon"; 114 private static final String DEFAULT_TEXTURE = "clouds.jpg"; 115 private static final String METAL_PLAF 116 = "javax.swing.plaf.metal.MetalLookAndFeel"; 117 118 /* constructor -- singleton pattern */ 119 120 private UIChangeManager() 121 { 122 components = new Vector(); 123 listeners = new Vector(); 124 props = new Config(); 125 support = new PropertyChangeSupport(this); 126 127 props.put(BUTTON_OPACITY_PROPERTY, Boolean.FALSE); 128 Image texture = KiwiUtils.getResourceManager().getTexture(DEFAULT_TEXTURE); 129 props.put(TEXTURE_PROPERTY, texture); 130 131 // MetalLookAndFeel.setCurrentTheme(new KiwiTheme()); 132 } 133 134 /** Get a reference to the <code>UIChangeManager</code> singleton. */ 135 136 public static UIChangeManager getInstance() 137 { 138 return(instance); 139 } 140 141 /** Add a <code>PropertyChangeListener</code> to this object's list of 142 * listeners. Listeners are notified whenever a property of this object 143 * is changed. 144 * 145 * @param listener The listener to add. 146 * @see #removePropertyChangeListener 147 */ 148 149 public void addPropertyChangeListener(PropertyChangeListener listener) 150 { 151 support.addPropertyChangeListener(listener); 152 } 153 154 /** Remove a <code>PropertyChangeListener</code> from this object's list of 155 * listeners. 156 * 157 * @param listener The listener to remove. 158 * @see #addPropertyChangeListener 159 */ 160 161 162 public void removePropertyChangeListener(PropertyChangeListener listener) 163 { 164 support.removePropertyChangeListener(listener); 165 } 166 167 /** Register a component with the manager. If the given component is already 168 * registered, the method call has no effect. The registered component will 169 * have its UI updated whenever the Look & Feel of the application changes. 170 * 171 * @param c The component to register. 172 * @see #unregisterComponent 173 */ 174 175 public void registerComponent(JComponent c) 176 { 177 if(!components.contains(c)) 178 components.addElement(c); 179 } 180 181 /** Unregister a component from the manager. 182 * 183 * @param c The component to unregister. 184 * @see #registerComponent 185 */ 186 187 public void unregisterComponent(JComponent c) 188 { 189 components.removeElement(c); 190 } 191 192 /** Change the Look & Feel globally. Each registered component (and every 193 * child component thereof) will be updated to use the new Look & Feel. 194 * 195 * @param lf The new Look & Feel. 196 * @exception UnsupportedLookAndFeelException If the specified Look & Feel 197 * is not available. 198 */ 199 200 public void changeLookAndFeel(LookAndFeel lf) 201 throws UnsupportedLookAndFeelException 202 { 203 UIManager.setLookAndFeel(lf); 204 _update(); 205 } 206 207 /** Change the Look & Feel globally. Each registered component (and every 208 * child component thereof) will be updated to use the new Look & Feel. 209 * 210 * @param className The fully-qualified class name for the new Look & Feel. 211 * @exception UnsupportedLookAndFeelException If the specified Look & Feel 212 * is not available. 213 * @exception IllegalAccessException If the specified class could not be 214 * accessed. 215 * @exception InstantiationException If the specified class could not be 216 * instantiated. 217 * @exception ClassNotFoundException If the specified class could not be 218 * found. 219 */ 220 221 public void changeLookAndFeel(String className) 222 throws UnsupportedLookAndFeelException, IllegalAccessException, 223 InstantiationException, ClassNotFoundException 224 { 225 UIManager.setLookAndFeel(className); 226 _update(); 227 } 228 229 /** Set the <i>transparent buttons</i> flag. 230 * 231 * @param flag The new state of the flag; if <code>true</code>, 232 * <code>KButton</code>s will be transparent by default. 233 * @see #getButtonsAreTransparent 234 * @see kiwi.ui.KButton 235 */ 236 237 public static void setButtonsAreTransparent(boolean flag) 238 { 239 props.put(BUTTON_OPACITY_PROPERTY, new Boolean(!flag)); 240 support.firePropertyChange(BUTTON_OPACITY_PROPERTY, null, 241 props.get(BUTTON_OPACITY_PROPERTY)); 242 } 243 244 /** Get the state of the <i>transparent buttons</i> flag. 245 * 246 * @return The current state of the flag. 247 * @see #setButtonsAreTransparent 248 * @see kiwi.ui.KButton 249 */ 250 251 public static boolean getButtonsAreTransparent() 252 { 253 boolean flag = ((Boolean)props.get(BUTTON_OPACITY_PROPERTY)) 254 .booleanValue(); 255 return(!flag); 256 } 257 258 /** Get the default texture used for tiling the backgrounds of 259 * <code>KPanel</code>s. 260 * 261 * @return The current texture, or <code>null</code> if there is no default 262 * texture. 263 * @see #setDefaultTexture 264 * @see kiwi.ui.KPanel 265 */ 266 267 public static Image getDefaultTexture() 268 { 269 Object o = props.get(TEXTURE_PROPERTY); 270 271 if(o == Void.class) 272 return(null); 273 else 274 return((Image)o); 275 } 276 277 /** Set the default texture used for tiling backgrounds of 278 * <code>KPanel</code>s. 279 * 280 * @param texture The new texture, or <code>null</code> if no textures 281 * should be used. 282 * @see #getDefaultTexture 283 * @see kiwi.ui.KPanel 284 */ 285 286 public static void setDefaultTexture(Image texture) 287 { 288 Object o = texture; 289 290 props.put(TEXTURE_PROPERTY, (o == null) ? Void.class : o); 291 292 support.firePropertyChange(TEXTURE_PROPERTY, null, o); 293 } 294 295 /** 296 * Set the default frame icon to be used for <code>KFrame</code>s. 297 * 298 * @param icon The new default frame icon, or <code>null</code> if a 299 * generic frame icon should be used. 300 * 301 * @since Kiwi 1.4.2 302 */ 303 304 public static void setDefaultFrameIcon(Image icon) 305 { 306 Object o = icon; 307 308 props.put(FRAME_ICON_PROPERTY, (o == null) ? Void.class : o); 309 310 support.firePropertyChange(FRAME_ICON_PROPERTY, null, o); 311 } 312 313 /** 314 * Get the default frame icon used for <code>KFrame</code>s. 315 * 316 * @return The current frame icon, or <code>null</code> if there is no 317 * default frame icon. 318 * 319 * @since Kiwi 1.4.2 320 */ 321 322 public static Image getDefaultFrameIcon() 323 { 324 Object o = props.get(FRAME_ICON_PROPERTY); 325 326 if(o == Void.class) 327 return(null); 328 else 329 return((Image)o); 330 } 331 332 /** Set the color theme. 333 * 334 * @param theme The color theme. 335 */ 336 337 public static void setColorTheme(ColorTheme theme) 338 { 339 MetalLookAndFeel.setCurrentTheme(theme); 340 try 341 { 342 UIManager.setLookAndFeel(METAL_PLAF); 343 } 344 catch(Exception ex) {} 345 } 346 347 /* update look&feel on all components */ 348 349 private void _update() 350 { 351 Enumeration e = components.elements(); 352 while(e.hasMoreElements()) 353 { 354 JComponent c = (JComponent)e.nextElement(); 355 SwingUtilities.updateComponentTreeUI(c); 356 } 357 } 358 359 } 360 361/* end of source file */