Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.desktop/macosx/classes/com/apple/laf/AquaRootPaneUI.java
41154 views
1
/*
2
* Copyright (c) 2011, 2012, 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 com.apple.laf;
27
28
import java.awt.*;
29
import java.awt.event.*;
30
import java.beans.PropertyChangeEvent;
31
32
import javax.swing.*;
33
import javax.swing.event.*;
34
import javax.swing.plaf.*;
35
import javax.swing.plaf.basic.BasicRootPaneUI;
36
37
import com.apple.laf.AquaUtils.RecyclableSingleton;
38
import com.apple.laf.AquaUtils.RecyclableSingletonFromDefaultConstructor;
39
40
/**
41
* From AquaRootPaneUI.java
42
*
43
* The JRootPane manages the default button. There can be only one active rootpane,
44
* and one default button, so we need only one timer
45
*
46
* AquaRootPaneUI is a singleton object
47
*/
48
public class AquaRootPaneUI extends BasicRootPaneUI implements AncestorListener, WindowListener, ContainerListener {
49
private static final RecyclableSingleton<AquaRootPaneUI> sRootPaneUI = new RecyclableSingletonFromDefaultConstructor<AquaRootPaneUI>(AquaRootPaneUI.class);
50
51
static final int kDefaultButtonPaintDelayBetweenFrames = 50;
52
JButton fCurrentDefaultButton = null;
53
Timer fTimer = null;
54
static final boolean sUseScreenMenuBar = AquaMenuBarUI.getScreenMenuBarProperty();
55
56
public static ComponentUI createUI(final JComponent c) {
57
return sRootPaneUI.get();
58
}
59
60
public void installUI(final JComponent c) {
61
super.installUI(c);
62
c.addAncestorListener(this);
63
64
if (c.isShowing() && c.isEnabled()) {
65
updateDefaultButton((JRootPane)c);
66
}
67
68
// for <rdar://problem/3689020> REGR: Realtime LAF updates no longer work
69
//
70
// because the JFrame parent has a LAF background set (why without a UI element I don't know!)
71
// we have to set it from the root pane so when we are coming from metal we will set it to
72
// the aqua color.
73
// This is because the aqua color is a magical color that gets the background of the window,
74
// so for most other LAFs the root pane changing is enough since it would be opaque, but for us
75
// it is not since we are going to grab the one that was set on the JFrame. :(
76
final Component parent = c.getParent();
77
78
if (parent != null && parent instanceof JFrame) {
79
final JFrame frameParent = (JFrame)parent;
80
final Color bg = frameParent.getBackground();
81
if (bg == null || bg instanceof UIResource) {
82
frameParent.setBackground(UIManager.getColor("Panel.background"));
83
}
84
}
85
86
// for <rdar://problem/3750909> OutOfMemoryError swapping menus.
87
// Listen for layered pane/JMenuBar updates if the screen menu bar is active.
88
if (sUseScreenMenuBar) {
89
final JRootPane root = (JRootPane)c;
90
root.addContainerListener(this);
91
root.getLayeredPane().addContainerListener(this);
92
}
93
}
94
95
public void uninstallUI(final JComponent c) {
96
stopTimer();
97
c.removeAncestorListener(this);
98
99
if (sUseScreenMenuBar) {
100
final JRootPane root = (JRootPane)c;
101
root.removeContainerListener(this);
102
root.getLayeredPane().removeContainerListener(this);
103
}
104
105
super.uninstallUI(c);
106
}
107
108
/**
109
* If the screen menu bar is active we need to listen to the layered pane of the root pane
110
* because it holds the JMenuBar. So, if a new layered pane was added, listen to it.
111
* If a new JMenuBar was added, tell the menu bar UI, because it will need to update the menu bar.
112
*/
113
public void componentAdded(final ContainerEvent e) {
114
if (e.getContainer() instanceof JRootPane) {
115
final JRootPane root = (JRootPane)e.getContainer();
116
if (e.getChild() == root.getLayeredPane()) {
117
final JLayeredPane layered = root.getLayeredPane();
118
layered.addContainerListener(this);
119
}
120
} else {
121
if (e.getChild() instanceof JMenuBar) {
122
final JMenuBar jmb = (JMenuBar)e.getChild();
123
final MenuBarUI mbui = jmb.getUI();
124
125
if (mbui instanceof AquaMenuBarUI) {
126
final Window owningWindow = SwingUtilities.getWindowAncestor(jmb);
127
128
// Could be a JDialog, and may have been added to a JRootPane not yet in a window.
129
if (owningWindow != null && owningWindow instanceof JFrame) {
130
((AquaMenuBarUI)mbui).setScreenMenuBar((JFrame)owningWindow);
131
}
132
}
133
}
134
}
135
}
136
137
/**
138
* Likewise, when the layered pane is removed from the root pane, stop listening to it.
139
* If the JMenuBar is removed, tell the menu bar UI to clear the menu bar.
140
*/
141
public void componentRemoved(final ContainerEvent e) {
142
if (e.getContainer() instanceof JRootPane) {
143
final JRootPane root = (JRootPane)e.getContainer();
144
if (e.getChild() == root.getLayeredPane()) {
145
final JLayeredPane layered = root.getLayeredPane();
146
layered.removeContainerListener(this);
147
}
148
} else {
149
if (e.getChild() instanceof JMenuBar) {
150
final JMenuBar jmb = (JMenuBar)e.getChild();
151
final MenuBarUI mbui = jmb.getUI();
152
153
if (mbui instanceof AquaMenuBarUI) {
154
final Window owningWindow = SwingUtilities.getWindowAncestor(jmb);
155
156
// Could be a JDialog, and may have been added to a JRootPane not yet in a window.
157
if (owningWindow != null && owningWindow instanceof JFrame) {
158
((AquaMenuBarUI)mbui).clearScreenMenuBar((JFrame)owningWindow);
159
}
160
}
161
}
162
}
163
}
164
165
/**
166
* Invoked when a property changes on the root pane. If the event
167
* indicates the {@code defaultButton} has changed, this will
168
* update the animation.
169
* If the enabled state changed, it will start or stop the animation
170
*/
171
public void propertyChange(final PropertyChangeEvent e) {
172
super.propertyChange(e);
173
174
final String prop = e.getPropertyName();
175
if ("defaultButton".equals(prop) || "temporaryDefaultButton".equals(prop)) {
176
// Change the animating button if this root is showing and enabled
177
// otherwise do nothing - someone else may be active
178
final JRootPane root = (JRootPane)e.getSource();
179
180
if (root.isShowing() && root.isEnabled()) {
181
updateDefaultButton(root);
182
}
183
} else if ("enabled".equals(prop) || AquaFocusHandler.FRAME_ACTIVE_PROPERTY.equals(prop)) {
184
final JRootPane root = (JRootPane)e.getSource();
185
if (root.isShowing()) {
186
if (((Boolean)e.getNewValue()).booleanValue()) {
187
updateDefaultButton((JRootPane)e.getSource());
188
} else {
189
stopTimer();
190
}
191
}
192
}
193
}
194
195
synchronized void stopTimer() {
196
if (fTimer != null) {
197
fTimer.stop();
198
fTimer = null;
199
}
200
}
201
202
synchronized void updateDefaultButton(final JRootPane root) {
203
final JButton button = root.getDefaultButton();
204
//System.err.println("in updateDefaultButton button = " + button);
205
fCurrentDefaultButton = button;
206
stopTimer();
207
if (button != null) {
208
fTimer = new Timer(kDefaultButtonPaintDelayBetweenFrames, new DefaultButtonPainter(root));
209
fTimer.start();
210
}
211
}
212
213
class DefaultButtonPainter implements ActionListener {
214
JRootPane root;
215
216
public DefaultButtonPainter(final JRootPane root) {
217
this.root = root;
218
}
219
220
public void actionPerformed(final ActionEvent e) {
221
final JButton defaultButton = root.getDefaultButton();
222
if ((defaultButton != null) && defaultButton.isShowing()) {
223
if (defaultButton.isEnabled()) {
224
defaultButton.repaint();
225
}
226
} else {
227
stopTimer();
228
}
229
}
230
}
231
232
/**
233
* This is sort of like viewDidMoveToWindow:. When the root pane is put into a window
234
* this method gets called for the notification.
235
* We need to set up the listener relationship so we can pick up activation events.
236
* And, if a JMenuBar was added before the root pane was added to the window, we now need
237
* to notify the menu bar UI.
238
*/
239
public void ancestorAdded(final AncestorEvent event) {
240
// this is so we can handle window activated and deactivated events so
241
// our swing controls can color/enable/disable/focus draw correctly
242
final Container ancestor = event.getComponent();
243
final Window owningWindow = SwingUtilities.getWindowAncestor(ancestor);
244
245
if (owningWindow != null) {
246
// We get this message even when a dialog is opened and the owning window is a window
247
// that could already be listened to. We should only be a listener once.
248
// adding multiple listeners was the cause of <rdar://problem/3534047>
249
// but the incorrect removal of them caused <rdar://problem/3617848>
250
owningWindow.removeWindowListener(this);
251
owningWindow.addWindowListener(this);
252
}
253
254
// The root pane has been added to the hierarchy. If it's enabled update the default
255
// button to start the throbbing. Since the UI is a singleton make sure the root pane
256
// we are checking has a default button before calling update otherwise we will stop
257
// throbbing the current default button.
258
final JComponent comp = event.getComponent();
259
if (comp instanceof JRootPane) {
260
final JRootPane rp = (JRootPane)comp;
261
if (rp.isEnabled() && rp.getDefaultButton() != null) {
262
updateDefaultButton((JRootPane)comp);
263
}
264
}
265
}
266
267
/**
268
* If the JRootPane was removed from the window we should clear the screen menu bar.
269
* That's a non-trivial problem, because you need to know which window the JRootPane was in
270
* before it was removed. By the time ancestorRemoved was called, the JRootPane has already been removed
271
*/
272
273
public void ancestorRemoved(final AncestorEvent event) { }
274
public void ancestorMoved(final AncestorEvent event) { }
275
276
public void windowActivated(final WindowEvent e) {
277
updateComponentTreeUIActivation((Component)e.getSource(), Boolean.TRUE);
278
}
279
280
public void windowDeactivated(final WindowEvent e) {
281
updateComponentTreeUIActivation((Component)e.getSource(), Boolean.FALSE);
282
}
283
284
public void windowOpened(final WindowEvent e) { }
285
public void windowClosing(final WindowEvent e) { }
286
287
public void windowClosed(final WindowEvent e) {
288
// We know the window is closed so remove the listener.
289
final Window w = e.getWindow();
290
w.removeWindowListener(this);
291
}
292
293
public void windowIconified(final WindowEvent e) { }
294
public void windowDeiconified(final WindowEvent e) { }
295
public void windowStateChanged(final WindowEvent e) { }
296
public void windowGainedFocus(final WindowEvent e) { }
297
public void windowLostFocus(final WindowEvent e) { }
298
299
private static void updateComponentTreeUIActivation(final Component c, Object active) {
300
if (c instanceof javax.swing.JInternalFrame) {
301
active = (((JInternalFrame)c).isSelected() ? Boolean.TRUE : Boolean.FALSE);
302
}
303
304
if (c instanceof javax.swing.JComponent) {
305
((javax.swing.JComponent)c).putClientProperty(AquaFocusHandler.FRAME_ACTIVE_PROPERTY, active);
306
}
307
308
Component[] children = null;
309
310
if (c instanceof javax.swing.JMenu) {
311
children = ((javax.swing.JMenu)c).getMenuComponents();
312
} else if (c instanceof Container) {
313
children = ((Container)c).getComponents();
314
}
315
316
if (children == null) return;
317
318
for (final Component element : children) {
319
updateComponentTreeUIActivation(element, active);
320
}
321
}
322
323
@Override
324
public final void update(final Graphics g, final JComponent c) {
325
if (c.isOpaque()) {
326
AquaUtils.fillRect(g, c);
327
}
328
paint(g, c);
329
}
330
}
331
332