KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > java > swing > plaf > windows > DesktopProperty


1 /*
2  * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
3  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
4  */

5 package com.sun.java.swing.plaf.windows;
6
7 import java.awt.*;
8 import java.beans.*;
9 import java.lang.ref.*;
10 import javax.swing.*;
11 import javax.swing.plaf.*;
12
13 /**
14  * Wrapper for a value from the desktop. The value is lazily looked up, and
15  * can be accessed using the <code>UIManager.ActiveValue</code> method
16  * <code>createValue</code>. If the underlying desktop property changes this
17  * will force the UIs to update all known Frames. You can invoke
18  * <code>invalidate</code> to force the value to be fetched again.
19  *
20  * @version @(#)DesktopProperty.java 1.9 05/03/25
21  */

22 // NOTE: Don't rely on this class staying in this location. It is likely
23
// to move to a different package in the future.
24
public class DesktopProperty implements UIDefaults.ActiveValue {
25     /**
26      * Indicates if an updateUI call is pending.
27      */

28     private static boolean updatePending;
29
30     /**
31      * ReferenceQueue of unreferenced WeakPCLs.
32      */

33     private static ReferenceQueue queue;
34
35
36     /**
37      * PropertyChangeListener attached to the Toolkit.
38      */

39     private WeakPCL pcl;
40     /**
41      * Key used to lookup value from desktop.
42      */

43     private String JavaDoc key;
44     /**
45      * Value to return.
46      */

47     private Object JavaDoc value;
48     /**
49      * Fallback value in case we get null from desktop.
50      */

51     private Object JavaDoc fallback;
52
53     /**
54      * Toolkit.
55      */

56     private Toolkit toolkit;
57
58
59     static {
60         queue = new ReferenceQueue();
61     }
62
63     /**
64      * Cleans up any lingering state held by unrefeernced
65      * DesktopProperties.
66      */

67     static void flushUnreferencedProperties() {
68         WeakPCL pcl;
69
70         while ((pcl = (WeakPCL)queue.poll()) != null) {
71             pcl.dispose();
72         }
73     }
74
75
76     /**
77      * Sets whether or not an updateUI call is pending.
78      */

79     private static synchronized void setUpdatePending(boolean update) {
80     updatePending = update;
81     }
82
83     /**
84      * Returns true if a UI update is pending.
85      */

86     private static synchronized boolean isUpdatePending() {
87     return updatePending;
88     }
89  
90     /**
91      * Updates the UIs of all the known Frames.
92      */

93     private static void updateAllUIs() {
94     // Check if the current UI is WindowsLookAndfeel and flush the XP style map.
95
// Note: Change the package test if this class is moved to a different package.
96
Class JavaDoc uiClass = UIManager.getLookAndFeel().getClass();
97     if (uiClass.getPackage().equals(DesktopProperty.class.getPackage())) {
98         XPStyle.invalidateStyle();
99     }
100         Frame appFrames[] = Frame.getFrames();
101     for (int j=0; j < appFrames.length; j++) {
102         updateWindowUI(appFrames[j]);
103     }
104     }
105
106     /**
107      * Updates the UI of the passed in window and all its children.
108      */

109     private static void updateWindowUI(Window window) {
110         SwingUtilities.updateComponentTreeUI(window);
111     Window ownedWins[] = window.getOwnedWindows();
112     for (int i=0; i < ownedWins.length; i++) {
113         updateWindowUI(ownedWins[i]);
114     }
115     }
116
117
118     /**
119      * Creates a DesktopProperty.
120      *
121      * @param key Key used in looking up desktop value.
122      * @param fallback Value used if desktop property is null.
123      * @param toolkit Toolkit used to fetch property from, can be null
124      * in which default will be used.
125      */

126     public DesktopProperty(String JavaDoc key, Object JavaDoc fallback, Toolkit toolkit) {
127         this.key = key;
128         this.fallback = fallback;
129         this.toolkit = toolkit;
130         // The only sure fire way to clear our references is to create a
131
// Thread and wait for a reference to be added to the queue.
132
// Because it is so rare that you will actually change the look
133
// and feel, this stepped is forgoed and a middle ground of
134
// flushing references from the constructor is instead done.
135
// The implication is that once one DesktopProperty is created
136
// there will most likely be n (number of DesktopProperties created
137
// by the LookAndFeel) WeakPCLs around, but this number will not
138
// grow past n.
139
flushUnreferencedProperties();
140     }
141
142     /**
143      * UIManager.LazyValue method, returns the value from the desktop
144      * or the fallback value if the desktop value is null.
145      */

146     public Object JavaDoc createValue(UIDefaults table) {
147         if (value == null) {
148             value = configureValue(getValueFromDesktop());
149             if (value == null) {
150                 value = configureValue(getDefaultValue());
151             }
152         }
153         return value;
154     }
155
156     /**
157      * Returns the value from the desktop.
158      */

159     protected Object JavaDoc getValueFromDesktop() {
160         if (this.toolkit == null) {
161             this.toolkit = Toolkit.getDefaultToolkit();
162         }
163         Object JavaDoc value = toolkit.getDesktopProperty(getKey());
164         pcl = new WeakPCL(this, toolkit, getKey(), UIManager.getLookAndFeel());
165         toolkit.addPropertyChangeListener(getKey(), pcl);
166         return value;
167     }
168
169     /**
170      * Returns the value to use if the desktop property is null.
171      */

172     protected Object JavaDoc getDefaultValue() {
173         return fallback;
174     }
175
176     /**
177      * Invalides the current value so that the next invocation of
178      * <code>createValue</code> will ask for the property again.
179      */

180     public void invalidate() {
181         if (pcl != null) {
182             toolkit.removePropertyChangeListener(getKey(), pcl);
183             toolkit = null;
184             pcl = null;
185             value = null;
186         }
187     }
188
189     /**
190      * Requests that all components in the GUI hierarchy be updated
191      * to reflect dynamic changes in this look&feel. This update occurs
192      * by uninstalling and re-installing the UI objects. Requests are
193      * batched and collapsed into a single update pass because often
194      * many desktop properties will change at once.
195      */

196     protected void updateUI() {
197     if (!isUpdatePending()) {
198             setUpdatePending(true);
199             Runnable JavaDoc uiUpdater = new Runnable JavaDoc() {
200                 public void run() {
201                     updateAllUIs();
202             setUpdatePending(false);
203                 }
204             };
205             SwingUtilities.invokeLater(uiUpdater);
206     }
207     }
208
209     /**
210      * Configures the value as appropriate for a defaults property in
211      * the UIDefaults table.
212      */

213     protected Object JavaDoc configureValue(Object JavaDoc value) {
214         if (value != null) {
215             if (value instanceof Color) {
216                 return new ColorUIResource((Color)value);
217             }
218             else if (value instanceof Font) {
219                 return new FontUIResource((Font)value);
220             }
221             else if (value instanceof UIDefaults.LazyValue) {
222                 value = ((UIDefaults.LazyValue)value).createValue(null);
223             }
224             else if (value instanceof UIDefaults.ActiveValue) {
225                 value = ((UIDefaults.ActiveValue)value).createValue(null);
226             }
227         }
228         return value;
229     }
230
231     /**
232      * Returns the key used to lookup the desktop properties value.
233      */

234     protected String JavaDoc getKey() {
235         return key;
236     }
237
238
239
240     /**
241      * As there is typically only one Toolkit, the PropertyChangeListener
242      * is handled via a WeakReference so as not to pin down the
243      * DesktopProperty.
244      */

245     private static class WeakPCL extends WeakReference
246                                implements PropertyChangeListener {
247         private Toolkit kit;
248         private String JavaDoc key;
249         private LookAndFeel laf;
250
251         WeakPCL(Object JavaDoc target, Toolkit kit, String JavaDoc key, LookAndFeel laf) {
252             super(target, queue);
253             this.kit = kit;
254             this.key = key;
255             this.laf = laf;
256         }
257
258         public void propertyChange(PropertyChangeEvent pce) {
259             DesktopProperty property = (DesktopProperty)get();
260
261             if (property == null || laf != UIManager.getLookAndFeel()) {
262                 // The property was GC'ed, we're no longer interested in
263
// PropertyChanges, remove the listener.
264
dispose();
265             }
266             else {
267                 property.invalidate();
268                 property.updateUI();
269             }
270         }
271
272         void dispose() {
273             kit.removePropertyChangeListener(key, this);
274         }
275     }
276 }
277
Popular Tags