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