Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/javax/swing/AbstractAction.java
38829 views
1
/*
2
* Copyright (c) 1997, 2013, 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
package javax.swing;
26
27
import java.awt.*;
28
import java.awt.event.*;
29
import java.beans.*;
30
import java.util.Hashtable;
31
import java.util.Enumeration;
32
import java.io.Serializable;
33
import java.io.IOException;
34
import java.io.ObjectInputStream;
35
import java.io.ObjectOutputStream;
36
import java.security.AccessController;
37
import javax.swing.event.SwingPropertyChangeSupport;
38
import sun.security.action.GetPropertyAction;
39
40
/**
41
* This class provides default implementations for the JFC <code>Action</code>
42
* interface. Standard behaviors like the get and set methods for
43
* <code>Action</code> object properties (icon, text, and enabled) are defined
44
* here. The developer need only subclass this abstract class and
45
* define the <code>actionPerformed</code> method.
46
* <p>
47
* <strong>Warning:</strong>
48
* Serialized objects of this class will not be compatible with
49
* future Swing releases. The current serialization support is
50
* appropriate for short term storage or RMI between applications running
51
* the same version of Swing. As of 1.4, support for long term storage
52
* of all JavaBeans&trade;
53
* has been added to the <code>java.beans</code> package.
54
* Please see {@link java.beans.XMLEncoder}.
55
*
56
* @author Georges Saab
57
* @see Action
58
*/
59
public abstract class AbstractAction implements Action, Cloneable, Serializable
60
{
61
/**
62
* Whether or not actions should reconfigure all properties on null.
63
*/
64
private static Boolean RECONFIGURE_ON_NULL;
65
66
/**
67
* Specifies whether action is enabled; the default is true.
68
*/
69
protected boolean enabled = true;
70
71
72
/**
73
* Contains the array of key bindings.
74
*/
75
private transient ArrayTable arrayTable;
76
77
/**
78
* Whether or not to reconfigure all action properties from the
79
* specified event.
80
*/
81
static boolean shouldReconfigure(PropertyChangeEvent e) {
82
if (e.getPropertyName() == null) {
83
synchronized(AbstractAction.class) {
84
if (RECONFIGURE_ON_NULL == null) {
85
RECONFIGURE_ON_NULL = Boolean.valueOf(
86
AccessController.doPrivileged(new GetPropertyAction(
87
"swing.actions.reconfigureOnNull", "false")));
88
}
89
return RECONFIGURE_ON_NULL;
90
}
91
}
92
return false;
93
}
94
95
/**
96
* Sets the enabled state of a component from an Action.
97
*
98
* @param c the Component to set the enabled state on
99
* @param a the Action to set the enabled state from, may be null
100
*/
101
static void setEnabledFromAction(JComponent c, Action a) {
102
c.setEnabled((a != null) ? a.isEnabled() : true);
103
}
104
105
/**
106
* Sets the tooltip text of a component from an Action.
107
*
108
* @param c the Component to set the tooltip text on
109
* @param a the Action to set the tooltip text from, may be null
110
*/
111
static void setToolTipTextFromAction(JComponent c, Action a) {
112
c.setToolTipText(a != null ?
113
(String)a.getValue(Action.SHORT_DESCRIPTION) : null);
114
}
115
116
static boolean hasSelectedKey(Action a) {
117
return (a != null && a.getValue(Action.SELECTED_KEY) != null);
118
}
119
120
static boolean isSelected(Action a) {
121
return Boolean.TRUE.equals(a.getValue(Action.SELECTED_KEY));
122
}
123
124
125
126
/**
127
* Creates an {@code Action}.
128
*/
129
public AbstractAction() {
130
}
131
132
/**
133
* Creates an {@code Action} with the specified name.
134
*
135
* @param name the name ({@code Action.NAME}) for the action; a
136
* value of {@code null} is ignored
137
*/
138
public AbstractAction(String name) {
139
putValue(Action.NAME, name);
140
}
141
142
/**
143
* Creates an {@code Action} with the specified name and small icon.
144
*
145
* @param name the name ({@code Action.NAME}) for the action; a
146
* value of {@code null} is ignored
147
* @param icon the small icon ({@code Action.SMALL_ICON}) for the action; a
148
* value of {@code null} is ignored
149
*/
150
public AbstractAction(String name, Icon icon) {
151
this(name);
152
putValue(Action.SMALL_ICON, icon);
153
}
154
155
/**
156
* Gets the <code>Object</code> associated with the specified key.
157
*
158
* @param key a string containing the specified <code>key</code>
159
* @return the binding <code>Object</code> stored with this key; if there
160
* are no keys, it will return <code>null</code>
161
* @see Action#getValue
162
*/
163
public Object getValue(String key) {
164
if (key == "enabled") {
165
return enabled;
166
}
167
if (arrayTable == null) {
168
return null;
169
}
170
return arrayTable.get(key);
171
}
172
173
/**
174
* Sets the <code>Value</code> associated with the specified key.
175
*
176
* @param key the <code>String</code> that identifies the stored object
177
* @param newValue the <code>Object</code> to store using this key
178
* @see Action#putValue
179
*/
180
public void putValue(String key, Object newValue) {
181
Object oldValue = null;
182
if (key == "enabled") {
183
// Treat putValue("enabled") the same way as a call to setEnabled.
184
// If we don't do this it means the two may get out of sync, and a
185
// bogus property change notification would be sent.
186
//
187
// To avoid dependencies between putValue & setEnabled this
188
// directly changes enabled. If we instead called setEnabled
189
// to change enabled, it would be possible for stack
190
// overflow in the case where a developer implemented setEnabled
191
// in terms of putValue.
192
if (newValue == null || !(newValue instanceof Boolean)) {
193
newValue = false;
194
}
195
oldValue = enabled;
196
enabled = (Boolean)newValue;
197
} else {
198
if (arrayTable == null) {
199
arrayTable = new ArrayTable();
200
}
201
if (arrayTable.containsKey(key))
202
oldValue = arrayTable.get(key);
203
// Remove the entry for key if newValue is null
204
// else put in the newValue for key.
205
if (newValue == null) {
206
arrayTable.remove(key);
207
} else {
208
arrayTable.put(key,newValue);
209
}
210
}
211
firePropertyChange(key, oldValue, newValue);
212
}
213
214
/**
215
* Returns true if the action is enabled.
216
*
217
* @return true if the action is enabled, false otherwise
218
* @see Action#isEnabled
219
*/
220
public boolean isEnabled() {
221
return enabled;
222
}
223
224
/**
225
* Sets whether the {@code Action} is enabled. The default is {@code true}.
226
*
227
* @param newValue {@code true} to enable the action, {@code false} to
228
* disable it
229
* @see Action#setEnabled
230
*/
231
public void setEnabled(boolean newValue) {
232
boolean oldValue = this.enabled;
233
234
if (oldValue != newValue) {
235
this.enabled = newValue;
236
firePropertyChange("enabled",
237
Boolean.valueOf(oldValue), Boolean.valueOf(newValue));
238
}
239
}
240
241
242
/**
243
* Returns an array of <code>Object</code>s which are keys for
244
* which values have been set for this <code>AbstractAction</code>,
245
* or <code>null</code> if no keys have values set.
246
* @return an array of key objects, or <code>null</code> if no
247
* keys have values set
248
* @since 1.3
249
*/
250
public Object[] getKeys() {
251
if (arrayTable == null) {
252
return null;
253
}
254
Object[] keys = new Object[arrayTable.size()];
255
arrayTable.getKeys(keys);
256
return keys;
257
}
258
259
/**
260
* If any <code>PropertyChangeListeners</code> have been registered, the
261
* <code>changeSupport</code> field describes them.
262
*/
263
protected SwingPropertyChangeSupport changeSupport;
264
265
/**
266
* Supports reporting bound property changes. This method can be called
267
* when a bound property has changed and it will send the appropriate
268
* <code>PropertyChangeEvent</code> to any registered
269
* <code>PropertyChangeListeners</code>.
270
*/
271
protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) {
272
if (changeSupport == null ||
273
(oldValue != null && newValue != null && oldValue.equals(newValue))) {
274
return;
275
}
276
changeSupport.firePropertyChange(propertyName, oldValue, newValue);
277
}
278
279
280
/**
281
* Adds a <code>PropertyChangeListener</code> to the listener list.
282
* The listener is registered for all properties.
283
* <p>
284
* A <code>PropertyChangeEvent</code> will get fired in response to setting
285
* a bound property, e.g. <code>setFont</code>, <code>setBackground</code>,
286
* or <code>setForeground</code>.
287
* Note that if the current component is inheriting its foreground,
288
* background, or font from its container, then no event will be
289
* fired in response to a change in the inherited property.
290
*
291
* @param listener The <code>PropertyChangeListener</code> to be added
292
*
293
* @see Action#addPropertyChangeListener
294
*/
295
public synchronized void addPropertyChangeListener(PropertyChangeListener listener) {
296
if (changeSupport == null) {
297
changeSupport = new SwingPropertyChangeSupport(this);
298
}
299
changeSupport.addPropertyChangeListener(listener);
300
}
301
302
303
/**
304
* Removes a <code>PropertyChangeListener</code> from the listener list.
305
* This removes a <code>PropertyChangeListener</code> that was registered
306
* for all properties.
307
*
308
* @param listener the <code>PropertyChangeListener</code> to be removed
309
*
310
* @see Action#removePropertyChangeListener
311
*/
312
public synchronized void removePropertyChangeListener(PropertyChangeListener listener) {
313
if (changeSupport == null) {
314
return;
315
}
316
changeSupport.removePropertyChangeListener(listener);
317
}
318
319
320
/**
321
* Returns an array of all the <code>PropertyChangeListener</code>s added
322
* to this AbstractAction with addPropertyChangeListener().
323
*
324
* @return all of the <code>PropertyChangeListener</code>s added or an empty
325
* array if no listeners have been added
326
* @since 1.4
327
*/
328
public synchronized PropertyChangeListener[] getPropertyChangeListeners() {
329
if (changeSupport == null) {
330
return new PropertyChangeListener[0];
331
}
332
return changeSupport.getPropertyChangeListeners();
333
}
334
335
336
/**
337
* Clones the abstract action. This gives the clone
338
* its own copy of the key/value list,
339
* which is not handled for you by <code>Object.clone()</code>.
340
**/
341
342
protected Object clone() throws CloneNotSupportedException {
343
AbstractAction newAction = (AbstractAction)super.clone();
344
synchronized(this) {
345
if (arrayTable != null) {
346
newAction.arrayTable = (ArrayTable)arrayTable.clone();
347
}
348
}
349
return newAction;
350
}
351
352
private void writeObject(ObjectOutputStream s) throws IOException {
353
// Store the default fields
354
s.defaultWriteObject();
355
356
// And the keys
357
ArrayTable.writeArrayTable(s, arrayTable);
358
}
359
360
private void readObject(ObjectInputStream s) throws ClassNotFoundException,
361
IOException {
362
s.defaultReadObject();
363
for (int counter = s.readInt() - 1; counter >= 0; counter--) {
364
putValue((String)s.readObject(), s.readObject());
365
}
366
}
367
}
368
369