Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.desktop/share/classes/sun/swing/plaf/DesktopProperty.java
41159 views
1
/*
2
* Copyright (c) 2001, 2018, 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
26
package sun.swing.plaf;
27
28
import java.awt.Color;
29
import java.awt.Font;
30
import java.awt.Frame;
31
import java.awt.Toolkit;
32
import java.awt.Window;
33
import java.beans.PropertyChangeEvent;
34
import java.beans.PropertyChangeListener;
35
import java.lang.ref.ReferenceQueue;
36
import java.lang.ref.WeakReference;
37
38
import javax.swing.LookAndFeel;
39
import javax.swing.SwingUtilities;
40
import javax.swing.UIDefaults;
41
import javax.swing.UIManager;
42
import javax.swing.plaf.ColorUIResource;
43
import javax.swing.plaf.FontUIResource;
44
45
import sun.awt.AppContext;
46
47
/**
48
* Wrapper for a value from the desktop. The value is lazily looked up, and
49
* can be accessed using the <code>UIManager.ActiveValue</code> method
50
* <code>createValue</code>. If the underlying desktop property changes this
51
* will force the UIs to update all known Frames. You can invoke
52
* <code>invalidate</code> to force the value to be fetched again.
53
*/
54
public class DesktopProperty implements UIDefaults.ActiveValue {
55
private static final StringBuilder DESKTOP_PROPERTY_UPDATE_PENDING_KEY =
56
new StringBuilder("DesktopPropertyUpdatePending");
57
58
/**
59
* ReferenceQueue of unreferenced WeakPCLs.
60
*/
61
private static final ReferenceQueue<DesktopProperty> queue = new ReferenceQueue<DesktopProperty>();
62
63
/**
64
* PropertyChangeListener attached to the Toolkit.
65
*/
66
private WeakPCL pcl;
67
/**
68
* Key used to lookup value from desktop.
69
*/
70
private final String key;
71
/**
72
* Value to return.
73
*/
74
private Object value;
75
/**
76
* Fallback value in case we get null from desktop.
77
*/
78
private final Object fallback;
79
80
81
/**
82
* Cleans up any lingering state held by unrefeernced
83
* DesktopProperties.
84
*/
85
public static void flushUnreferencedProperties() {
86
WeakPCL pcl;
87
88
while ((pcl = (WeakPCL)queue.poll()) != null) {
89
pcl.dispose();
90
}
91
}
92
93
94
/**
95
* Sets whether or not an updateUI call is pending.
96
*/
97
private static synchronized void setUpdatePending(boolean update) {
98
AppContext.getAppContext()
99
.put(DESKTOP_PROPERTY_UPDATE_PENDING_KEY, update);
100
}
101
102
/**
103
* Returns true if a UI update is pending.
104
*/
105
private static synchronized boolean isUpdatePending() {
106
return Boolean.TRUE.equals(AppContext.getAppContext()
107
.get(DESKTOP_PROPERTY_UPDATE_PENDING_KEY));
108
}
109
110
/**
111
* Updates the UIs of all the known Frames.
112
*/
113
protected void updateAllUIs() {
114
Frame[] appFrames = Frame.getFrames();
115
for (Frame appFrame : appFrames) {
116
updateWindowUI(appFrame);
117
}
118
}
119
120
/**
121
* Updates the UI of the passed in window and all its children.
122
*/
123
private static void updateWindowUI(Window window) {
124
SwingUtilities.updateComponentTreeUI(window);
125
Window[] ownedWins = window.getOwnedWindows();
126
for (Window ownedWin : ownedWins) {
127
updateWindowUI(ownedWin);
128
}
129
}
130
131
132
/**
133
* Creates a DesktopProperty.
134
*
135
* @param key Key used in looking up desktop value.
136
* @param fallback Value used if desktop property is null.
137
*/
138
public DesktopProperty(String key, Object fallback) {
139
this.key = key;
140
this.fallback = fallback;
141
// The only sure fire way to clear our references is to create a
142
// Thread and wait for a reference to be added to the queue.
143
// Because it is so rare that you will actually change the look
144
// and feel, this stepped is forgoed and a middle ground of
145
// flushing references from the constructor is instead done.
146
// The implication is that once one DesktopProperty is created
147
// there will most likely be n (number of DesktopProperties created
148
// by the LookAndFeel) WeakPCLs around, but this number will not
149
// grow past n.
150
flushUnreferencedProperties();
151
}
152
153
/**
154
* UIManager.LazyValue method, returns the value from the desktop
155
* or the fallback value if the desktop value is null.
156
*/
157
public Object createValue(UIDefaults table) {
158
if (value == null) {
159
value = configureValue(getValueFromDesktop());
160
if (value == null) {
161
value = configureValue(getDefaultValue());
162
}
163
}
164
return value;
165
}
166
167
/**
168
* Returns the value from the desktop.
169
*/
170
protected Object getValueFromDesktop() {
171
Toolkit toolkit = Toolkit.getDefaultToolkit();
172
173
if (pcl == null) {
174
pcl = new WeakPCL(this, getKey(), UIManager.getLookAndFeel());
175
toolkit.addPropertyChangeListener(getKey(), pcl);
176
}
177
178
return toolkit.getDesktopProperty(getKey());
179
}
180
181
/**
182
* Returns the value to use if the desktop property is null.
183
*/
184
protected Object getDefaultValue() {
185
return fallback;
186
}
187
188
/**
189
* Invalidates the current value.
190
*
191
* @param laf the LookAndFeel this DesktopProperty was created with
192
*/
193
public void invalidate(LookAndFeel laf) {
194
invalidate();
195
}
196
197
/**
198
* Invalides the current value so that the next invocation of
199
* <code>createValue</code> will ask for the property again.
200
*/
201
public void invalidate() {
202
value = null;
203
}
204
205
/**
206
* Requests that all components in the GUI hierarchy be updated
207
* to reflect dynamic changes in this {@literal look&feel}. This update occurs
208
* by uninstalling and re-installing the UI objects. Requests are
209
* batched and collapsed into a single update pass because often
210
* many desktop properties will change at once.
211
*/
212
protected void updateUI() {
213
if (!isUpdatePending()) {
214
setUpdatePending(true);
215
Runnable uiUpdater = new Runnable() {
216
public void run() {
217
updateAllUIs();
218
setUpdatePending(false);
219
}
220
};
221
SwingUtilities.invokeLater(uiUpdater);
222
}
223
}
224
225
/**
226
* Configures the value as appropriate for a defaults property in
227
* the UIDefaults table.
228
*/
229
protected Object configureValue(Object value) {
230
if (value != null) {
231
if (value instanceof Color) {
232
return new ColorUIResource((Color)value);
233
}
234
else if (value instanceof Font) {
235
return new FontUIResource((Font)value);
236
}
237
else if (value instanceof UIDefaults.LazyValue) {
238
value = ((UIDefaults.LazyValue)value).createValue(null);
239
}
240
else if (value instanceof UIDefaults.ActiveValue) {
241
value = ((UIDefaults.ActiveValue)value).createValue(null);
242
}
243
}
244
return value;
245
}
246
247
/**
248
* Returns the key used to lookup the desktop properties value.
249
*/
250
protected String getKey() {
251
return key;
252
}
253
254
/**
255
* As there is typically only one Toolkit, the PropertyChangeListener
256
* is handled via a WeakReference so as not to pin down the
257
* DesktopProperty.
258
*/
259
private static class WeakPCL extends WeakReference<DesktopProperty>
260
implements PropertyChangeListener {
261
private String key;
262
private LookAndFeel laf;
263
264
WeakPCL(DesktopProperty target, String key, LookAndFeel laf) {
265
super(target, queue);
266
this.key = key;
267
this.laf = laf;
268
}
269
270
public void propertyChange(PropertyChangeEvent pce) {
271
DesktopProperty property = get();
272
273
if (property == null || laf != UIManager.getLookAndFeel()) {
274
// The property was GC'ed, we're no longer interested in
275
// PropertyChanges, remove the listener.
276
dispose();
277
}
278
else {
279
property.invalidate(laf);
280
property.updateUI();
281
}
282
}
283
284
void dispose() {
285
Toolkit.getDefaultToolkit().removePropertyChangeListener(key, this);
286
}
287
}
288
}
289
290