Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/solaris/classes/sun/awt/X11/InfoWindow.java
32288 views
1
/*
2
* Copyright (c) 2009, 2010, 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.awt.X11;
27
28
import java.awt.*;
29
import java.awt.event.*;
30
import java.awt.peer.TrayIconPeer;
31
import sun.awt.*;
32
import java.awt.image.*;
33
import java.text.BreakIterator;
34
import java.util.concurrent.ArrayBlockingQueue;
35
import java.security.AccessController;
36
import java.security.PrivilegedAction;
37
import java.lang.reflect.InvocationTargetException;
38
39
/**
40
* An utility window class. This is a base class for Tooltip and Balloon.
41
*/
42
public abstract class InfoWindow extends Window {
43
private Container container;
44
private Closer closer;
45
46
protected InfoWindow(Frame parent, Color borderColor) {
47
super(parent);
48
setType(Window.Type.POPUP);
49
container = new Container() {
50
@Override
51
public Insets getInsets() {
52
return new Insets(1, 1, 1, 1);
53
}
54
};
55
setLayout(new BorderLayout());
56
setBackground(borderColor);
57
add(container, BorderLayout.CENTER);
58
container.setLayout(new BorderLayout());
59
60
closer = new Closer();
61
}
62
63
public Component add(Component c) {
64
container.add(c, BorderLayout.CENTER);
65
return c;
66
}
67
68
protected void setCloser(Runnable action, int time) {
69
closer.set(action, time);
70
}
71
72
// Must be executed on EDT.
73
protected void show(Point corner, int indent) {
74
assert SunToolkit.isDispatchThreadForAppContext(this);
75
76
pack();
77
78
Dimension size = getSize();
79
// TODO: When 6356322 is fixed we should get screen bounds in
80
// this way: eframe.getGraphicsConfiguration().getBounds().
81
Dimension scrSize = Toolkit.getDefaultToolkit().getScreenSize();
82
83
if (corner.x < scrSize.width/2 && corner.y < scrSize.height/2) { // 1st square
84
setLocation(corner.x + indent, corner.y + indent);
85
86
} else if (corner.x >= scrSize.width/2 && corner.y < scrSize.height/2) { // 2nd square
87
setLocation(corner.x - indent - size.width, corner.y + indent);
88
89
} else if (corner.x < scrSize.width/2 && corner.y >= scrSize.height/2) { // 3rd square
90
setLocation(corner.x + indent, corner.y - indent - size.height);
91
92
} else if (corner.x >= scrSize.width/2 && corner.y >= scrSize.height/2) { // 4th square
93
setLocation(corner.x - indent - size.width, corner.y - indent - size.height);
94
}
95
96
super.show();
97
closer.schedule();
98
}
99
100
public void hide() {
101
closer.close();
102
}
103
104
private class Closer implements Runnable {
105
Runnable action;
106
int time;
107
108
public void run() {
109
doClose();
110
}
111
112
void set(Runnable action, int time) {
113
this.action = action;
114
this.time = time;
115
}
116
117
void schedule() {
118
XToolkit.schedule(this, time);
119
}
120
121
void close() {
122
XToolkit.remove(this);
123
doClose();
124
}
125
126
// WARNING: this method may be executed on Toolkit thread.
127
private void doClose() {
128
SunToolkit.executeOnEventHandlerThread(InfoWindow.this, new Runnable() {
129
public void run() {
130
InfoWindow.super.hide();
131
invalidate();
132
if (action != null) {
133
action.run();
134
}
135
}
136
});
137
}
138
}
139
140
141
private interface LiveArguments {
142
/** Whether the target of the InfoWindow is disposed. */
143
boolean isDisposed();
144
145
/** The bounds of the target of the InfoWindow. */
146
Rectangle getBounds();
147
}
148
149
public static class Tooltip extends InfoWindow {
150
151
public interface LiveArguments extends InfoWindow.LiveArguments {
152
/** The tooltip to be displayed. */
153
String getTooltipString();
154
}
155
156
private final Object target;
157
private final LiveArguments liveArguments;
158
159
private final Label textLabel = new Label("");
160
private final Runnable starter = new Runnable() {
161
public void run() {
162
display();
163
}};
164
165
private final static int TOOLTIP_SHOW_TIME = 10000;
166
private final static int TOOLTIP_START_DELAY_TIME = 1000;
167
private final static int TOOLTIP_MAX_LENGTH = 64;
168
private final static int TOOLTIP_MOUSE_CURSOR_INDENT = 5;
169
private final static Color TOOLTIP_BACKGROUND_COLOR = new Color(255, 255, 220);
170
private final static Font TOOLTIP_TEXT_FONT = XWindow.getDefaultFont();
171
172
public Tooltip(Frame parent, Object target,
173
LiveArguments liveArguments)
174
{
175
super(parent, Color.black);
176
177
this.target = target;
178
this.liveArguments = liveArguments;
179
180
XTrayIconPeer.suppressWarningString(this);
181
182
setCloser(null, TOOLTIP_SHOW_TIME);
183
textLabel.setBackground(TOOLTIP_BACKGROUND_COLOR);
184
textLabel.setFont(TOOLTIP_TEXT_FONT);
185
add(textLabel);
186
}
187
188
/*
189
* WARNING: this method is executed on Toolkit thread!
190
*/
191
private void display() {
192
// Execute on EDT to avoid deadlock (see 6280857).
193
SunToolkit.executeOnEventHandlerThread(target, new Runnable() {
194
public void run() {
195
if (liveArguments.isDisposed()) {
196
return;
197
}
198
199
String tooltipString = liveArguments.getTooltipString();
200
if (tooltipString == null) {
201
return;
202
} else if (tooltipString.length() > TOOLTIP_MAX_LENGTH) {
203
textLabel.setText(tooltipString.substring(0, TOOLTIP_MAX_LENGTH));
204
} else {
205
textLabel.setText(tooltipString);
206
}
207
208
Point pointer = (Point)AccessController.doPrivileged(new PrivilegedAction() {
209
public Object run() {
210
if (!isPointerOverTrayIcon(liveArguments.getBounds())) {
211
return null;
212
}
213
return MouseInfo.getPointerInfo().getLocation();
214
}
215
});
216
if (pointer == null) {
217
return;
218
}
219
show(new Point(pointer.x, pointer.y), TOOLTIP_MOUSE_CURSOR_INDENT);
220
}
221
});
222
}
223
224
public void enter() {
225
XToolkit.schedule(starter, TOOLTIP_START_DELAY_TIME);
226
}
227
228
public void exit() {
229
XToolkit.remove(starter);
230
if (isVisible()) {
231
hide();
232
}
233
}
234
235
private boolean isPointerOverTrayIcon(Rectangle trayRect) {
236
Point p = MouseInfo.getPointerInfo().getLocation();
237
return !(p.x < trayRect.x || p.x > (trayRect.x + trayRect.width) ||
238
p.y < trayRect.y || p.y > (trayRect.y + trayRect.height));
239
}
240
}
241
242
public static class Balloon extends InfoWindow {
243
244
public interface LiveArguments extends InfoWindow.LiveArguments {
245
/** The action to be performed upon clicking the baloon. */
246
String getActionCommand();
247
}
248
249
private final LiveArguments liveArguments;
250
private final Object target;
251
252
private final static int BALLOON_SHOW_TIME = 10000;
253
private final static int BALLOON_TEXT_MAX_LENGTH = 256;
254
private final static int BALLOON_WORD_LINE_MAX_LENGTH = 16;
255
private final static int BALLOON_WORD_LINE_MAX_COUNT = 4;
256
private final static int BALLOON_ICON_WIDTH = 32;
257
private final static int BALLOON_ICON_HEIGHT = 32;
258
private final static int BALLOON_TRAY_ICON_INDENT = 0;
259
private final static Color BALLOON_CAPTION_BACKGROUND_COLOR = new Color(200, 200 ,255);
260
private final static Font BALLOON_CAPTION_FONT = new Font(Font.DIALOG, Font.BOLD, 12);
261
262
private Panel mainPanel = new Panel();
263
private Panel captionPanel = new Panel();
264
private Label captionLabel = new Label("");
265
private Button closeButton = new Button("X");
266
private Panel textPanel = new Panel();
267
private XTrayIconPeer.IconCanvas iconCanvas = new XTrayIconPeer.IconCanvas(BALLOON_ICON_WIDTH, BALLOON_ICON_HEIGHT);
268
private Label[] lineLabels = new Label[BALLOON_WORD_LINE_MAX_COUNT];
269
private ActionPerformer ap = new ActionPerformer();
270
271
private Image iconImage;
272
private Image errorImage;
273
private Image warnImage;
274
private Image infoImage;
275
private boolean gtkImagesLoaded;
276
277
private Displayer displayer = new Displayer();
278
279
public Balloon(Frame parent, Object target, LiveArguments liveArguments) {
280
super(parent, new Color(90, 80 ,190));
281
this.liveArguments = liveArguments;
282
this.target = target;
283
284
XTrayIconPeer.suppressWarningString(this);
285
286
setCloser(new Runnable() {
287
public void run() {
288
if (textPanel != null) {
289
textPanel.removeAll();
290
textPanel.setSize(0, 0);
291
iconCanvas.setSize(0, 0);
292
XToolkit.awtLock();
293
try {
294
displayer.isDisplayed = false;
295
XToolkit.awtLockNotifyAll();
296
} finally {
297
XToolkit.awtUnlock();
298
}
299
}
300
}
301
}, BALLOON_SHOW_TIME);
302
303
add(mainPanel);
304
305
captionLabel.setFont(BALLOON_CAPTION_FONT);
306
captionLabel.addMouseListener(ap);
307
308
captionPanel.setLayout(new BorderLayout());
309
captionPanel.add(captionLabel, BorderLayout.WEST);
310
captionPanel.add(closeButton, BorderLayout.EAST);
311
captionPanel.setBackground(BALLOON_CAPTION_BACKGROUND_COLOR);
312
captionPanel.addMouseListener(ap);
313
314
closeButton.addActionListener(new ActionListener() {
315
public void actionPerformed(ActionEvent e) {
316
hide();
317
}
318
});
319
320
mainPanel.setLayout(new BorderLayout());
321
mainPanel.setBackground(Color.white);
322
mainPanel.add(captionPanel, BorderLayout.NORTH);
323
mainPanel.add(iconCanvas, BorderLayout.WEST);
324
mainPanel.add(textPanel, BorderLayout.CENTER);
325
326
iconCanvas.addMouseListener(ap);
327
328
for (int i = 0; i < BALLOON_WORD_LINE_MAX_COUNT; i++) {
329
lineLabels[i] = new Label();
330
lineLabels[i].addMouseListener(ap);
331
lineLabels[i].setBackground(Color.white);
332
}
333
334
displayer.start();
335
}
336
337
public void display(String caption, String text, String messageType) {
338
if (!gtkImagesLoaded) {
339
loadGtkImages();
340
}
341
displayer.display(caption, text, messageType);
342
}
343
344
private void _display(String caption, String text, String messageType) {
345
captionLabel.setText(caption);
346
347
BreakIterator iter = BreakIterator.getWordInstance();
348
if (text != null) {
349
iter.setText(text);
350
int start = iter.first(), end;
351
int nLines = 0;
352
353
do {
354
end = iter.next();
355
356
if (end == BreakIterator.DONE ||
357
text.substring(start, end).length() >= 50)
358
{
359
lineLabels[nLines].setText(text.substring(start, end == BreakIterator.DONE ?
360
iter.last() : end));
361
textPanel.add(lineLabels[nLines++]);
362
start = end;
363
}
364
if (nLines == BALLOON_WORD_LINE_MAX_COUNT) {
365
if (end != BreakIterator.DONE) {
366
lineLabels[nLines - 1].setText(
367
new String(lineLabels[nLines - 1].getText() + " ..."));
368
}
369
break;
370
}
371
} while (end != BreakIterator.DONE);
372
373
374
textPanel.setLayout(new GridLayout(nLines, 1));
375
}
376
377
if ("ERROR".equals(messageType)) {
378
iconImage = errorImage;
379
} else if ("WARNING".equals(messageType)) {
380
iconImage = warnImage;
381
} else if ("INFO".equals(messageType)) {
382
iconImage = infoImage;
383
} else {
384
iconImage = null;
385
}
386
387
if (iconImage != null) {
388
Dimension tpSize = textPanel.getSize();
389
iconCanvas.setSize(BALLOON_ICON_WIDTH, (BALLOON_ICON_HEIGHT > tpSize.height ?
390
BALLOON_ICON_HEIGHT : tpSize.height));
391
iconCanvas.validate();
392
}
393
394
SunToolkit.executeOnEventHandlerThread(target, new Runnable() {
395
public void run() {
396
if (liveArguments.isDisposed()) {
397
return;
398
}
399
Point parLoc = getParent().getLocationOnScreen();
400
Dimension parSize = getParent().getSize();
401
show(new Point(parLoc.x + parSize.width/2, parLoc.y + parSize.height/2),
402
BALLOON_TRAY_ICON_INDENT);
403
if (iconImage != null) {
404
iconCanvas.updateImage(iconImage); // call it after the show(..) above
405
}
406
}
407
});
408
}
409
410
public void dispose() {
411
displayer.interrupt();
412
super.dispose();
413
}
414
415
private void loadGtkImages() {
416
if (!gtkImagesLoaded) {
417
//check whether the gtk version is >= 3.10 as the Icon names were
418
//changed from this release
419
UNIXToolkit tk = (UNIXToolkit) Toolkit.getDefaultToolkit();
420
if (tk.checkGtkVersion(3, 10, 0)) {
421
errorImage = (Image) tk.getDesktopProperty(
422
"gtk.icon.dialog-error.6.rtl");
423
warnImage = (Image) tk.getDesktopProperty(
424
"gtk.icon.dialog-warning.6.rtl");
425
infoImage = (Image) tk.getDesktopProperty(
426
"gtk.icon.dialog-information.6.rtl");
427
} else {
428
errorImage = (Image) tk.getDesktopProperty(
429
"gtk.icon.gtk-dialog-error.6.rtl");
430
warnImage = (Image) tk.getDesktopProperty(
431
"gtk.icon.gtk-dialog-warning.6.rtl");
432
infoImage = (Image) tk.getDesktopProperty(
433
"gtk.icon.gtk-dialog-info.6.rtl");
434
}
435
gtkImagesLoaded = true;
436
}
437
}
438
439
private class ActionPerformer extends MouseAdapter {
440
public void mouseClicked(MouseEvent e) {
441
// hide the balloon by any click
442
hide();
443
if (e.getButton() == MouseEvent.BUTTON1) {
444
ActionEvent aev = new ActionEvent(target, ActionEvent.ACTION_PERFORMED,
445
liveArguments.getActionCommand(),
446
e.getWhen(), e.getModifiers());
447
XToolkit.postEvent(XToolkit.targetToAppContext(aev.getSource()), aev);
448
}
449
}
450
}
451
452
private class Displayer extends Thread {
453
final int MAX_CONCURRENT_MSGS = 10;
454
455
ArrayBlockingQueue<Message> messageQueue = new ArrayBlockingQueue<Message>(MAX_CONCURRENT_MSGS);
456
boolean isDisplayed;
457
458
Displayer() {
459
setDaemon(true);
460
}
461
462
public void run() {
463
while (true) {
464
Message msg = null;
465
try {
466
msg = (Message)messageQueue.take();
467
} catch (InterruptedException e) {
468
return;
469
}
470
471
/*
472
* Wait till the previous message is displayed if any
473
*/
474
XToolkit.awtLock();
475
try {
476
while (isDisplayed) {
477
try {
478
XToolkit.awtLockWait();
479
} catch (InterruptedException e) {
480
return;
481
}
482
}
483
isDisplayed = true;
484
} finally {
485
XToolkit.awtUnlock();
486
}
487
_display(msg.caption, msg.text, msg.messageType);
488
}
489
}
490
491
void display(String caption, String text, String messageType) {
492
messageQueue.offer(new Message(caption, text, messageType));
493
}
494
}
495
496
private static class Message {
497
String caption, text, messageType;
498
499
Message(String caption, String text, String messageType) {
500
this.caption = caption;
501
this.text = text;
502
this.messageType = messageType;
503
}
504
}
505
}
506
}
507
508