1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package io.github.tonywasher.joceanus.tethys.swing.base;
18
19 import io.github.tonywasher.joceanus.oceanus.convert.OceanusDataConverter;
20 import io.github.tonywasher.joceanus.oceanus.logger.OceanusLogManager;
21 import io.github.tonywasher.joceanus.oceanus.logger.OceanusLogger;
22 import io.github.tonywasher.joceanus.tethys.api.base.TethysUIIconId;
23
24 import javax.swing.BorderFactory;
25 import javax.swing.ImageIcon;
26 import javax.swing.JComponent;
27 import javax.swing.JPanel;
28 import javax.swing.SwingConstants;
29 import javax.swing.border.Border;
30 import java.awt.BorderLayout;
31 import java.awt.Color;
32 import java.awt.Component;
33 import java.awt.Dimension;
34 import java.awt.Font;
35 import java.awt.FontMetrics;
36 import java.awt.GraphicsConfiguration;
37 import java.awt.GraphicsDevice;
38 import java.awt.GraphicsEnvironment;
39 import java.awt.Image;
40 import java.awt.Point;
41 import java.awt.Rectangle;
42 import java.io.IOException;
43
44
45
46
47 public final class TethysUISwingUtils {
48
49
50
51 private static final OceanusLogger LOGGER = OceanusLogManager.getLogger(TethysUISwingUtils.class);
52
53
54
55
56 private static final int PADDING_HEIGHT = 4;
57
58
59
60
61 private TethysUISwingUtils() {
62 }
63
64
65
66
67
68
69
70 public static void restrictField(final JComponent pComponent,
71 final int pWidth) {
72
73 final Font myFont = pComponent.getFont();
74 final FontMetrics myMetrics = pComponent.getFontMetrics(myFont);
75 final int myCharWidth = myMetrics.stringWidth("w");
76 final int myCharHeight = myMetrics.getHeight() + PADDING_HEIGHT;
77
78
79 final Dimension myPrefDims = new Dimension(pWidth * myCharWidth, myCharHeight);
80 final Dimension myMaxDims = new Dimension(Integer.MAX_VALUE, myCharHeight);
81 final Dimension myMinDims = new Dimension(1, myCharHeight);
82
83
84 pComponent.setPreferredSize(myPrefDims);
85 pComponent.setMaximumSize(myMaxDims);
86 pComponent.setMinimumSize(myMinDims);
87 }
88
89
90
91
92
93
94
95
96
97 public static JComponent addPanelBorder(final String pTitle,
98 final Integer pPadding,
99 final JComponent pNode) {
100 if (pPadding == null
101 && pTitle == null) {
102 return pNode;
103 } else {
104 final JComponent myNode = new JPanel(new BorderLayout());
105 myNode.add(pNode, BorderLayout.CENTER);
106 setPanelBorder(pTitle, pPadding, myNode);
107 return myNode;
108 }
109 }
110
111
112
113
114
115
116
117
118 protected static void setPanelBorder(final String pTitle,
119 final Integer pPadding,
120 final JComponent pNode) {
121
122 final boolean hasTitle = pTitle != null;
123 final boolean hasPadding = pPadding != null;
124
125
126 final Border myPaddedBorder = hasPadding
127 ? BorderFactory.createEmptyBorder(pPadding, pPadding, pPadding, pPadding)
128 : null;
129 final Border myTitleBorder = hasTitle
130 ? BorderFactory.createTitledBorder(pTitle)
131 : null;
132
133
134 if (hasPadding) {
135 pNode.setBorder(hasTitle ? BorderFactory.createCompoundBorder(myPaddedBorder, myTitleBorder) : myPaddedBorder);
136 } else {
137 pNode.setBorder(hasTitle ? myTitleBorder : BorderFactory.createEmptyBorder());
138 }
139 }
140
141
142
143
144
145
146
147
148
149 public static Point obtainDisplayPoint(final Component pAnchor,
150 final Point pLocation,
151 final Dimension pSize) {
152
153 final GraphicsDevice myScreen = getScreenForComponent(pAnchor);
154
155
156 final Point myLocation = getLocationForComponent(pAnchor, pLocation);
157
158
159 Rectangle myArea = new Rectangle(myLocation.x, myLocation.y,
160 pSize.width, pSize.height);
161 myArea = adjustDisplayLocation(myArea, myScreen);
162
163
164 return new Point(myArea.x, myArea.y);
165 }
166
167
168
169
170
171
172
173
174
175 public static Point obtainDisplayPoint(final Component pAnchor,
176 final int pSide,
177 final Dimension pSize) {
178
179 final GraphicsDevice myScreen = getScreenForComponent(pAnchor);
180
181
182 final Point myLocation = pAnchor.getLocationOnScreen();
183
184
185 Rectangle myArea = new Rectangle(myLocation.x, myLocation.y,
186 pSize.width, pSize.height);
187 myArea = adjustDisplayLocation(myArea, pAnchor.getBounds(), pSide, myScreen);
188
189
190 return new Point(myArea.x, myArea.y);
191 }
192
193
194
195
196
197
198
199
200
201 public static Point obtainDisplayPoint(final Rectangle pAnchor,
202 final int pSide,
203 final Dimension pSize) {
204
205 final GraphicsDevice myScreen = getScreenForRectangle(pAnchor);
206
207
208 Rectangle myArea = new Rectangle(pAnchor.x, pAnchor.y,
209 pSize.width, pSize.height);
210 myArea = adjustDisplayLocation(myArea, pAnchor.getBounds(), pSide, myScreen);
211
212
213 return new Point(myArea.x, myArea.y);
214 }
215
216
217
218
219
220
221
222 private static GraphicsDevice getScreenForComponent(final Component pAnchor) {
223
224 final Point myOrigin = pAnchor.getLocationOnScreen();
225
226
227 final Rectangle myLocalBounds = pAnchor.getBounds();
228 final Rectangle myBounds = new Rectangle(myOrigin.x,
229 myOrigin.y,
230 myLocalBounds.width,
231 myLocalBounds.height);
232
233
234 return getScreenForRectangle(myBounds);
235 }
236
237
238
239
240
241
242
243 private static GraphicsDevice getScreenForRectangle(final Rectangle pAnchor) {
244
245 final GraphicsEnvironment myEnv = GraphicsEnvironment.getLocalGraphicsEnvironment();
246 final GraphicsDevice[] myDevices = myEnv.getScreenDevices();
247
248
249 double myBest = 0;
250 GraphicsDevice myBestDevice = null;
251
252
253 for (final GraphicsDevice myDevice : myDevices) {
254
255 if (myDevice.getType() == GraphicsDevice.TYPE_RASTER_SCREEN) {
256
257 final GraphicsConfiguration myConfig = myDevice.getDefaultConfiguration();
258 final Rectangle myDevBounds = myConfig.getBounds();
259
260
261 final double myIntersection = getIntersection(pAnchor, myDevBounds);
262 if (myIntersection > myBest) {
263 myBest = myIntersection;
264 myBestDevice = myDevice;
265 }
266 }
267 }
268
269
270 return myBestDevice == null
271 ? myEnv.getDefaultScreenDevice()
272 : myBestDevice;
273 }
274
275
276
277
278
279
280
281
282 private static double getIntersection(final Rectangle pBounds,
283 final Rectangle pScreen) {
284
285
286 final double myMinX = Math.max(pBounds.getMinX(), pScreen.getMinX());
287 final double myMaxX = Math.min(pBounds.getMaxX(), pScreen.getMaxX());
288 final double myMinY = Math.max(pBounds.getMinY(), pScreen.getMinY());
289 final double myMaxY = Math.min(pBounds.getMaxY(), pScreen.getMaxY());
290
291
292 final double myX = Math.max(myMaxX - myMinX, 0);
293 final double myY = Math.max(myMaxY - myMinY, 0);
294
295
296 return myX * myY;
297 }
298
299
300
301
302
303
304
305
306 private static Point getLocationForComponent(final Component pAnchor,
307 final Point pLocation) {
308
309 final Point myOrigin = pAnchor.getLocationOnScreen();
310
311
312 return new Point(myOrigin.x + pLocation.x,
313 myOrigin.y + pLocation.y);
314 }
315
316
317
318
319
320
321
322
323 private static Rectangle adjustDisplayLocation(final Rectangle pSource,
324 final GraphicsDevice pScreen) {
325
326 final Rectangle myScreenBounds = pScreen.getDefaultConfiguration().getBounds();
327 double myAdjustX = 0;
328 double myAdjustY = 0;
329
330
331 if (pSource.getMaxX() > myScreenBounds.getMaxX()) {
332 myAdjustX = myScreenBounds.getMaxX() - pSource.getMaxX();
333 }
334
335
336 if (pSource.getMaxY() > myScreenBounds.getMaxY()) {
337 myAdjustY = myScreenBounds.getMaxY() - pSource.getMaxY();
338 }
339
340
341 if (pSource.getMinX() + myAdjustX < myScreenBounds.getMinX()) {
342 myAdjustX = myScreenBounds.getMinX() - pSource.getMinX();
343 }
344
345
346 if (pSource.getMinY() + myAdjustY < myScreenBounds.getMinY()) {
347 myAdjustY = myScreenBounds.getMinY() - pSource.getMinY();
348 }
349
350
351 return (Double.doubleToRawLongBits(myAdjustX) != 0)
352 || (Double.doubleToRawLongBits(myAdjustY) != 0)
353 ? new Rectangle((int) (pSource.getX() + myAdjustX),
354 (int) (pSource.getY() + myAdjustY),
355 pSource.width,
356 pSource.height)
357 : pSource;
358 }
359
360
361
362
363
364
365
366
367
368
369 private static Rectangle adjustDisplayLocation(final Rectangle pSource,
370 final Rectangle pAnchor,
371 final int pSide,
372 final GraphicsDevice pScreen) {
373
374 final Rectangle myScreenBounds = pScreen.getDefaultConfiguration().getBounds();
375 double myAdjustX = 0;
376 double myAdjustY = 0;
377
378
379 switch (pSide) {
380 case SwingConstants.RIGHT:
381 myAdjustX = pAnchor.getWidth();
382 if (pSource.getMaxX() + myAdjustX > myScreenBounds.getMaxX()) {
383 myAdjustX = -pSource.getWidth();
384 }
385 break;
386 case SwingConstants.LEFT:
387 myAdjustX = -pSource.getWidth();
388 if (pSource.getMinX() + myAdjustX < myScreenBounds.getMinX()) {
389 myAdjustX = pAnchor.getWidth();
390 }
391 break;
392 case SwingConstants.BOTTOM:
393 myAdjustY = pAnchor.getHeight();
394 if (pSource.getMaxY() + myAdjustY > myScreenBounds.getMaxY()) {
395 myAdjustY = -pSource.getHeight();
396 }
397 break;
398 case SwingConstants.TOP:
399 myAdjustY = -pSource.getHeight();
400 if (pSource.getMinY() + myAdjustY < myScreenBounds.getMinY()) {
401 myAdjustY = pAnchor.getHeight();
402 }
403 break;
404 default:
405 break;
406 }
407
408
409 final Rectangle myArea = (Double.doubleToRawLongBits(myAdjustX) != 0)
410 || (Double.doubleToRawLongBits(myAdjustY) != 0)
411 ? new Rectangle((int) (pSource.getMinX() + myAdjustX),
412 (int) (pSource.getMinY() + myAdjustY),
413 pSource.width,
414 pSource.height)
415 : pSource;
416 return adjustDisplayLocation(myArea, pScreen);
417 }
418
419
420
421
422
423
424
425 public static String colorToHexString(final Color pValue) {
426
427 int myValue = pValue.getRGB();
428 myValue &= OceanusDataConverter.COLOR_MASK;
429
430
431 final StringBuilder myBuilder = new StringBuilder();
432
433
434 while (myValue > 0) {
435
436 final int myDigit = myValue & OceanusDataConverter.NYBBLE_MASK;
437 final char myChar = Character.forDigit(myDigit, OceanusDataConverter.HEX_RADIX);
438 myBuilder.insert(0, myChar);
439 myValue >>>= OceanusDataConverter.NYBBLE_SHIFT;
440 }
441
442
443 while (myBuilder.length() < OceanusDataConverter.RGB_LENGTH) {
444 myBuilder.insert(0, '0');
445 }
446
447
448 myBuilder.insert(0, '#');
449
450
451 return myBuilder.toString();
452 }
453
454
455
456
457
458
459
460 public static TethysUISwingIcon getIcon(final TethysUIIconId pId) {
461 try {
462 final ImageIcon myIcon = new ImageIcon(pId.loadResourceToBytes());
463 return new TethysUISwingIcon(myIcon);
464 } catch (IOException e) {
465 LOGGER.error("Failed to load Icon " + pId.getSourceName(), e);
466 return null;
467 }
468 }
469
470
471
472
473
474
475
476 public static Image[] getIcons(final TethysUIIconId[] pIds) {
477 final Image[] myIcons = new Image[pIds.length];
478 for (int i = 0; i < pIds.length; i++) {
479 final TethysUISwingIcon myIcon = getIcon(pIds[i]);
480 myIcons[i] = myIcon == null
481 ? null
482 : myIcon.getImage();
483 }
484 return myIcons;
485 }
486
487
488
489
490
491
492
493
494 public static TethysUISwingIcon getIconAtSize(final TethysUIIconId pId,
495 final int pSize) {
496 final TethysUISwingIcon mySource = getIcon(pId);
497 if (mySource == null) {
498 return null;
499 }
500 final Image myImage = mySource.getImage();
501 final Image myNewImage = myImage.getScaledInstance(pSize,
502 pSize,
503 Image.SCALE_DEFAULT);
504 final ImageIcon myIcon = new ImageIcon(myNewImage);
505 return new TethysUISwingIcon(myIcon);
506 }
507 }
508