Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/macosx/classes/com/apple/laf/AquaInternalFrameBorder.java
38831 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.beans.PropertyVetoException;
30
31
import javax.swing.*;
32
import javax.swing.border.Border;
33
import javax.swing.plaf.UIResource;
34
35
import sun.swing.SwingUtilities2;
36
37
import apple.laf.*;
38
import apple.laf.JRSUIConstants.*;
39
import apple.laf.JRSUIState.TitleBarHeightState;
40
41
import com.apple.laf.AquaUtils.RecyclableSingleton;
42
import com.apple.laf.AquaInternalFrameBorderMetrics;
43
44
public class AquaInternalFrameBorder implements Border, UIResource {
45
private static final int kCloseButton = 0;
46
private static final int kIconButton = 1;
47
private static final int kGrowButton = 2;
48
49
private static final int sMaxIconWidth = 15;
50
private static final int sMaxIconHeight = sMaxIconWidth;
51
private static final int sAfterButtonPad = 11;
52
private static final int sAfterIconPad = 5;
53
private static final int sRightSideTitleClip = 0;
54
55
private static final int kContentTester = 100; // For getting region insets
56
57
static final RecyclableSingleton<AquaInternalFrameBorder> documentWindowFrame = new RecyclableSingleton<AquaInternalFrameBorder>() {
58
protected AquaInternalFrameBorder getInstance() {
59
return new AquaInternalFrameBorder(WindowType.DOCUMENT);
60
}
61
};
62
protected static AquaInternalFrameBorder window() {
63
return documentWindowFrame.get();
64
}
65
66
static final RecyclableSingleton<AquaInternalFrameBorder> utilityWindowFrame = new RecyclableSingleton<AquaInternalFrameBorder>() {
67
protected AquaInternalFrameBorder getInstance() {
68
return new AquaInternalFrameBorder(WindowType.UTILITY);
69
}
70
};
71
protected static AquaInternalFrameBorder utility() {
72
return utilityWindowFrame.get();
73
}
74
75
static final RecyclableSingleton<AquaInternalFrameBorder> dialogWindowFrame = new RecyclableSingleton<AquaInternalFrameBorder>() {
76
protected AquaInternalFrameBorder getInstance() {
77
return new AquaInternalFrameBorder(WindowType.DOCUMENT);
78
}
79
};
80
protected static AquaInternalFrameBorder dialog() {
81
return dialogWindowFrame.get();
82
}
83
84
private final AquaInternalFrameBorderMetrics metrics;
85
86
private final int fThisButtonSpan;
87
private final int fThisLeftSideTotal;
88
89
private final boolean fIsUtility;
90
91
// Instance variables
92
private final WindowType fWindowKind; // Which kind of window to draw
93
private Insets fBorderInsets; // Cached insets object
94
95
private Color selectedTextColor;
96
private Color notSelectedTextColor;
97
98
private Rectangle fInBounds; // Cached bounds rect object
99
100
protected final AquaPainter<TitleBarHeightState> titleBarPainter = AquaPainter.create(JRSUIStateFactory.getTitleBar());
101
protected final AquaPainter<JRSUIState> widgetPainter = AquaPainter.create(JRSUIState.getInstance());
102
103
protected AquaInternalFrameBorder(final WindowType kind) {
104
fWindowKind = kind;
105
106
titleBarPainter.state.set(WindowClipCorners.YES);
107
if (fWindowKind == WindowType.UTILITY) {
108
fIsUtility = true;
109
metrics = AquaInternalFrameBorderMetrics.getMetrics(true);
110
111
widgetPainter.state.set(WindowType.UTILITY);
112
titleBarPainter.state.set(WindowType.UTILITY);
113
} else {
114
fIsUtility = false;
115
metrics = AquaInternalFrameBorderMetrics.getMetrics(false);
116
117
widgetPainter.state.set(WindowType.DOCUMENT);
118
titleBarPainter.state.set(WindowType.DOCUMENT);
119
}
120
titleBarPainter.state.setValue(metrics.titleBarHeight);
121
titleBarPainter.state.set(WindowTitleBarSeparator.YES);
122
widgetPainter.state.set(AlignmentVertical.CENTER);
123
124
fThisButtonSpan = (metrics.buttonWidth * 3) + (metrics.buttonPadding * 2);
125
fThisLeftSideTotal = metrics.leftSidePadding + fThisButtonSpan + sAfterButtonPad;
126
}
127
128
public void setColors(final Color inSelectedTextColor, final Color inNotSelectedTextColor) {
129
selectedTextColor = inSelectedTextColor;
130
notSelectedTextColor = inNotSelectedTextColor;
131
}
132
133
// Utility to lazy-init and fill in fInBounds
134
protected void setInBounds(final int x, final int y, final int w, final int h) {
135
if (fInBounds == null) fInBounds = new Rectangle();
136
137
fInBounds.x = x;
138
fInBounds.y = y;
139
fInBounds.width = w;
140
fInBounds.height = h;
141
}
142
143
// Border interface
144
public boolean isBorderOpaque() {
145
return false;
146
}
147
148
// Border interface
149
public void paintBorder(final Component c, final Graphics g, final int x, final int y, final int w, final int h) {
150
// For expanded InternalFrames, the frame & component are the same object
151
paintBorder((JInternalFrame)c, c, g, x, y, w, h);
152
}
153
154
protected void paintTitleContents(final Graphics g, final JInternalFrame frame, final int x, final int y, final int w, final int h) {
155
final boolean isSelected = frame.isSelected();
156
final Font f = g.getFont();
157
158
g.setFont(metrics.font);
159
160
// Center text vertically.
161
final FontMetrics fm = g.getFontMetrics();
162
final int baseline = (metrics.titleBarHeight + fm.getAscent() - fm.getLeading() - fm.getDescent()) / 2;
163
164
// max button is the rightmost so use it
165
final int usedWidth = fThisLeftSideTotal + sRightSideTitleClip;
166
int iconWidth = getIconWidth(frame);
167
if (iconWidth > 0) iconWidth += sAfterIconPad;
168
169
final int totalWidth = w;
170
171
// window title looks like: | 0 0 0(sAfterButtonPad)IconWidth Title(right pad) |
172
final int availTextWidth = totalWidth - usedWidth - iconWidth - sAfterButtonPad;
173
174
final String title = frame.getTitle();
175
176
String text = title;
177
int totalTextWidth = 0;
178
179
int startXPosition = fThisLeftSideTotal;
180
boolean wasTextShortened = false;
181
// shorten the string to fit in the
182
if ((text != null) && !(text.equals(""))) {
183
totalTextWidth = SwingUtilities.computeStringWidth(fm, text);
184
final String clipString = "\u2026";
185
if (totalTextWidth > availTextWidth) {
186
wasTextShortened = true;
187
totalTextWidth = SwingUtilities.computeStringWidth(fm, clipString);
188
int nChars;
189
for (nChars = 0; nChars < text.length(); nChars++) {
190
final int nextCharWidth = fm.charWidth(text.charAt(nChars));
191
if ((totalTextWidth + nextCharWidth) > availTextWidth) {
192
break;
193
}
194
totalTextWidth += nextCharWidth;
195
}
196
text = text.substring(0, nChars) + clipString;
197
}
198
199
if (!wasTextShortened) {
200
// center it!
201
startXPosition = (totalWidth - (totalTextWidth + iconWidth)) / 2;
202
if (startXPosition < fThisLeftSideTotal) {
203
startXPosition = fThisLeftSideTotal;
204
}
205
}
206
207
if (isSelected || fIsUtility) {
208
g.setColor(Color.lightGray);
209
} else {
210
g.setColor(Color.white);
211
}
212
SwingUtilities2.drawString(frame, g, text, x + startXPosition + iconWidth, y + baseline + 1);
213
214
if (isSelected || fIsUtility) {
215
g.setColor(selectedTextColor);
216
} else {
217
g.setColor(notSelectedTextColor);
218
}
219
220
SwingUtilities2.drawString(frame, g, text, x + startXPosition + iconWidth, y + baseline);
221
g.setFont(f);
222
}
223
224
// sja fix x & y
225
final int iconYPostion = (metrics.titleBarHeight - getIconHeight(frame)) / 2;
226
paintTitleIcon(g, frame, x + startXPosition, y + iconYPostion);
227
}
228
229
public int getWhichButtonHit(final JInternalFrame frame, final int x, final int y) {
230
int buttonHit = -1;
231
232
final Insets i = frame.getInsets();
233
int startX = i.left + metrics.leftSidePadding - 1;
234
if (isInsideYButtonArea(i, y) && x >= startX) {
235
if (x <= (startX + metrics.buttonWidth)) {
236
if (frame.isClosable()) {
237
buttonHit = kCloseButton;
238
}
239
} else {
240
startX += metrics.buttonWidth + metrics.buttonPadding;
241
if (x >= startX && x <= (startX + metrics.buttonWidth)) {
242
if (frame.isIconifiable()) {
243
buttonHit = kIconButton;
244
}
245
} else {
246
startX += metrics.buttonWidth + metrics.buttonPadding;
247
if (x >= startX && x <= (startX + metrics.buttonWidth)) {
248
if (frame.isMaximizable()) {
249
buttonHit = kGrowButton;
250
}
251
}
252
}
253
}
254
}
255
256
return buttonHit;
257
}
258
259
public void doButtonAction(final JInternalFrame frame, final int whichButton) {
260
switch (whichButton) {
261
case kCloseButton:
262
frame.doDefaultCloseAction();
263
break;
264
265
case kIconButton:
266
if (frame.isIconifiable()) {
267
if (!frame.isIcon()) {
268
try {
269
frame.setIcon(true);
270
} catch(final PropertyVetoException e1) {}
271
} else {
272
try {
273
frame.setIcon(false);
274
} catch(final PropertyVetoException e1) {}
275
}
276
}
277
break;
278
279
case kGrowButton:
280
if (frame.isMaximizable()) {
281
if (!frame.isMaximum()) {
282
try {
283
frame.setMaximum(true);
284
} catch(final PropertyVetoException e5) {}
285
} else {
286
try {
287
frame.setMaximum(false);
288
} catch(final PropertyVetoException e6) {}
289
}
290
}
291
break;
292
293
default:
294
System.err.println("AquaInternalFrameBorder should never get here!!!!");
295
Thread.dumpStack();
296
break;
297
}
298
}
299
300
public boolean isInsideYButtonArea(final Insets i, final int y) {
301
final int startY = (i.top - metrics.titleBarHeight / 2) - (metrics.buttonHeight / 2) - 1;
302
final int endY = startY + metrics.buttonHeight;
303
return y >= startY && y <= endY;
304
}
305
306
public boolean getWithinRolloverArea(final Insets i, final int x, final int y) {
307
final int startX = i.left + metrics.leftSidePadding;
308
final int endX = startX + fThisButtonSpan;
309
return isInsideYButtonArea(i, y) && x >= startX && x <= endX;
310
}
311
312
protected void paintTitleIcon(final Graphics g, final JInternalFrame frame, final int x, final int y) {
313
Icon icon = frame.getFrameIcon();
314
if (icon == null) icon = UIManager.getIcon("InternalFrame.icon");
315
if (icon == null) return;
316
317
// Resize to 16x16 if necessary.
318
if (icon instanceof ImageIcon && (icon.getIconWidth() > sMaxIconWidth || icon.getIconHeight() > sMaxIconHeight)) {
319
final Image img = ((ImageIcon)icon).getImage();
320
((ImageIcon)icon).setImage(img.getScaledInstance(sMaxIconWidth, sMaxIconHeight, Image.SCALE_SMOOTH));
321
}
322
323
icon.paintIcon(frame, g, x, y);
324
}
325
326
protected int getIconWidth(final JInternalFrame frame) {
327
int width = 0;
328
329
Icon icon = frame.getFrameIcon();
330
if (icon == null) {
331
icon = UIManager.getIcon("InternalFrame.icon");
332
}
333
334
if (icon != null && icon instanceof ImageIcon) {
335
// Resize to 16x16 if necessary.
336
width = Math.min(icon.getIconWidth(), sMaxIconWidth);
337
}
338
339
return width;
340
}
341
342
protected int getIconHeight(final JInternalFrame frame) {
343
int height = 0;
344
345
Icon icon = frame.getFrameIcon();
346
if (icon == null) {
347
icon = UIManager.getIcon("InternalFrame.icon");
348
}
349
350
if (icon != null && icon instanceof ImageIcon) {
351
// Resize to 16x16 if necessary.
352
height = Math.min(icon.getIconHeight(), sMaxIconHeight);
353
}
354
355
return height;
356
}
357
358
public void drawWindowTitle(final Graphics g, final JInternalFrame frame, final int inX, final int inY, final int inW, final int inH) {
359
final int x = inX;
360
final int y = inY;
361
final int w = inW;
362
int h = inH;
363
364
h = metrics.titleBarHeight + inH;
365
366
// paint the background
367
titleBarPainter.state.set(frame.isSelected() ? State.ACTIVE : State.INACTIVE);
368
titleBarPainter.paint(g, frame, x, y, w, h);
369
370
// now the title and the icon
371
paintTitleContents(g, frame, x, y, w, h);
372
373
// finally the widgets
374
drawAllWidgets(g, frame); // rollover is last attribute
375
}
376
377
// Component could be a JInternalFrame or a JDesktopIcon
378
void paintBorder(final JInternalFrame frame, final Component c, final Graphics g, final int x, final int y, final int w, final int h) {
379
if (fBorderInsets == null) getBorderInsets(c);
380
// Set the contentRect - inset by border size
381
setInBounds(x + fBorderInsets.left, y + fBorderInsets.top, w - (fBorderInsets.right + fBorderInsets.left), h - (fBorderInsets.top + fBorderInsets.bottom));
382
383
// Set parameters
384
setMetrics(frame, c);
385
386
// Draw the frame
387
drawWindowTitle(g, frame, x, y, w, h);
388
}
389
390
// defaults to false
391
boolean isDirty(final JInternalFrame frame) {
392
final Object dirty = frame.getClientProperty("windowModified");
393
if (dirty == null || dirty == Boolean.FALSE) return false;
394
return true;
395
}
396
397
// Border interface
398
public Insets getBorderInsets(final Component c) {
399
if (fBorderInsets == null) fBorderInsets = new Insets(0, 0, 0, 0);
400
401
// Paranoia check
402
if (!(c instanceof JInternalFrame)) return fBorderInsets;
403
404
final JInternalFrame frame = (JInternalFrame)c;
405
406
// Set the contentRect to an arbitrary value (in case the current real one is too small)
407
setInBounds(0, 0, kContentTester, kContentTester);
408
409
// Set parameters
410
setMetrics(frame, c);
411
412
fBorderInsets.left = 0;
413
fBorderInsets.top = metrics.titleBarHeight;
414
fBorderInsets.right = 0;
415
fBorderInsets.bottom = 0;
416
417
return fBorderInsets;
418
}
419
420
public void repaintButtonArea(final JInternalFrame frame) {
421
final Insets i = frame.getInsets();
422
final int x = i.left + metrics.leftSidePadding;
423
final int y = i.top - metrics.titleBarHeight + 1;
424
frame.repaint(x, y, fThisButtonSpan, metrics.titleBarHeight - 2);
425
}
426
427
// Draw all the widgets this frame supports
428
void drawAllWidgets(final Graphics g, final JInternalFrame frame) {
429
int x = metrics.leftSidePadding;
430
int y = (metrics.titleBarHeight - metrics.buttonHeight) / 2 - metrics.titleBarHeight;
431
432
final Insets insets = frame.getInsets();
433
x += insets.left;
434
y += insets.top + metrics.downShift;
435
436
final AquaInternalFrameUI ui = (AquaInternalFrameUI)frame.getUI();
437
final int buttonPressedIndex = ui.getWhichButtonPressed();
438
final boolean overButton = ui.getMouseOverPressedButton();
439
final boolean rollover = ui.getRollover();
440
441
final boolean frameSelected = frame.isSelected() || fIsUtility;
442
final boolean generalActive = rollover || frameSelected;
443
444
final boolean dirty = isDirty(frame);
445
446
paintButton(g, frame, x, y, kCloseButton, buttonPressedIndex, overButton, frame.isClosable(), generalActive, rollover, dirty);
447
448
x += metrics.buttonPadding + metrics.buttonWidth;
449
paintButton(g, frame, x, y, kIconButton, buttonPressedIndex, overButton, frame.isIconifiable(), generalActive, rollover, false);
450
451
x += metrics.buttonPadding + metrics.buttonWidth;
452
paintButton(g, frame, x, y, kGrowButton, buttonPressedIndex, overButton, frame.isMaximizable(), generalActive, rollover, false);
453
}
454
455
public void paintButton(final Graphics g, final JInternalFrame frame, final int x, final int y, final int buttonType, final int buttonPressedIndex, final boolean overButton, final boolean enabled, final boolean active, final boolean anyRollover, final boolean dirty) {
456
widgetPainter.state.set(getWidget(frame, buttonType));
457
widgetPainter.state.set(getState(buttonPressedIndex == buttonType && overButton, anyRollover, active, enabled));
458
widgetPainter.state.set(dirty ? BooleanValue.YES : BooleanValue.NO);
459
widgetPainter.paint(g, frame, x, y, metrics.buttonWidth, metrics.buttonHeight);
460
}
461
462
static Widget getWidget(final JInternalFrame frame, final int buttonType) {
463
switch (buttonType) {
464
case kIconButton: return Widget.TITLE_BAR_COLLAPSE_BOX;
465
case kGrowButton: return Widget.TITLE_BAR_ZOOM_BOX;
466
}
467
468
return Widget.TITLE_BAR_CLOSE_BOX;
469
}
470
471
static State getState(final boolean pressed, final boolean rollover, final boolean active, final boolean enabled) {
472
if (!enabled) return State.DISABLED;
473
if (!active) return State.INACTIVE;
474
if (pressed) return State.PRESSED;
475
if (rollover) return State.ROLLOVER;
476
return State.ACTIVE;
477
}
478
479
protected void setMetrics(final JInternalFrame frame, final Component window) {
480
final String title = frame.getTitle();
481
final FontMetrics fm = frame.getFontMetrics(UIManager.getFont("InternalFrame.titleFont"));
482
int titleWidth = 0;
483
int titleHeight = fm.getAscent();
484
if (title != null) {
485
titleWidth = SwingUtilities.computeStringWidth(fm, title);
486
}
487
// Icon space
488
final Icon icon = frame.getFrameIcon();
489
if (icon != null) {
490
titleWidth += icon.getIconWidth();
491
titleHeight = Math.max(titleHeight, icon.getIconHeight());
492
}
493
}
494
495
protected int getTitleHeight() {
496
return metrics.titleBarHeight;
497
}
498
}
499
500