picrate 2.0.1-java → 2.1.0-java

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,545 @@
1
+ package processing.awt;
2
+
3
+ import java.awt.Desktop;
4
+ import java.awt.EventQueue;
5
+ import java.awt.FileDialog;
6
+ import java.awt.Frame;
7
+ import java.awt.HeadlessException;
8
+ import java.awt.Image;
9
+ import java.awt.Toolkit;
10
+ import java.awt.color.ColorSpace;
11
+ import java.awt.image.BufferedImage;
12
+ import java.io.File;
13
+ import java.io.IOException;
14
+ import java.io.InputStream;
15
+ import java.net.URI;
16
+ import java.net.URISyntaxException;
17
+
18
+ import java.awt.DisplayMode;
19
+ import java.awt.GraphicsConfiguration;
20
+ import java.awt.GraphicsDevice;
21
+ import java.awt.GraphicsEnvironment;
22
+ import java.awt.geom.AffineTransform;
23
+
24
+ import javax.imageio.ImageIO;
25
+ import javax.swing.ImageIcon;
26
+ import javax.swing.JFileChooser;
27
+ import javax.swing.UIManager;
28
+ import javax.swing.UnsupportedLookAndFeelException;
29
+
30
+ // used by desktopFile() method
31
+ import javax.swing.filechooser.FileSystemView;
32
+
33
+ import processing.core.PApplet;
34
+ import processing.core.PConstants;
35
+ import processing.core.PImage;
36
+
37
+ /**
38
+ * This class exists as an abstraction layer to remove AWT from PApplet. It is a
39
+ * staging area for AWT-specific code that's shared by the Java2D, JavaFX, and
40
+ * JOGL renderers. Once PSurfaceFX and PSurfaceJOGL have their own
41
+ * implementations, these methods will move to PSurfaceAWT.
42
+ */
43
+ public class ShimAWT implements PConstants {
44
+
45
+ /*
46
+ PGraphics graphics;
47
+ PApplet sketch;
48
+
49
+
50
+ public ShimAWT(PApplet sketch) {
51
+ this.graphics = graphics;
52
+ this.sketch = sketch;
53
+ }
54
+ */
55
+ static private ShimAWT instance;
56
+
57
+ private GraphicsDevice[] displayDevices;
58
+
59
+ private final int displayWidth;
60
+ private final int displayHeight;
61
+
62
+ /**
63
+ * Only needed for display functions
64
+ */
65
+ static private ShimAWT getInstance() {
66
+ if (instance == null) {
67
+ instance = new ShimAWT();
68
+ }
69
+ return instance;
70
+ }
71
+
72
+ private ShimAWT() {
73
+ // Need the list of display devices to be queried already for usage below.
74
+ // https://github.com/processing/processing/issues/3295
75
+ // https://github.com/processing/processing/issues/3296
76
+ // Not doing this from a static initializer because it may cause
77
+ // PApplet to cache and the values to stick through subsequent runs.
78
+ // Instead make it a runtime thing and a local variable.
79
+ GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
80
+ GraphicsDevice device = ge.getDefaultScreenDevice();
81
+ displayDevices = ge.getScreenDevices();
82
+
83
+ // // Default or unparsed will be -1, spanning will be 0, actual displays will
84
+ // // be numbered from 1 because it's too weird to say "display 0" in prefs.
85
+ // if (display > 0 && display <= displayDevices.length) {
86
+ // device = displayDevices[display-1];
87
+ // }
88
+ // When this was called, display will always be unset (even in 3.x),
89
+ // since this happens before settings() is called.
90
+ // Set displayWidth and displayHeight for people still using those.
91
+ DisplayMode displayMode = device.getDisplayMode();
92
+ displayWidth = displayMode.getWidth();
93
+ displayHeight = displayMode.getHeight();
94
+ }
95
+
96
+ static public int getDisplayWidth() {
97
+ return getInstance().displayWidth;
98
+ }
99
+
100
+ static public int getDisplayHeight() {
101
+ return getInstance().displayHeight;
102
+ }
103
+
104
+ static public int getDisplayCount() {
105
+ return getInstance().displayDevices.length;
106
+ }
107
+
108
+ static public int getDisplayDensity(int num) {
109
+ return getInstance().displayDensityImpl(num);
110
+ }
111
+
112
+
113
+ /*
114
+ private int displayDensityImpl() {
115
+ if (display != SPAN && (fullScreen || present)) {
116
+ return displayDensity(display);
117
+ }
118
+ // walk through all displays, use 2 if any display is 2
119
+ for (int i = 0; i < displayDevices.length; i++) {
120
+ if (displayDensity(i+1) == 2) {
121
+ return 2;
122
+ }
123
+ }
124
+ // If nobody's density is 2 then everyone is 1
125
+ return 1;
126
+ }
127
+ */
128
+ private int displayDensityImpl(int display) {
129
+ if (display > 0 && display <= displayDevices.length) {
130
+ GraphicsConfiguration graphicsConfig
131
+ = displayDevices[display - 1].getDefaultConfiguration();
132
+ AffineTransform tx = graphicsConfig.getDefaultTransform();
133
+ return (int) Math.round(tx.getScaleX());
134
+ }
135
+
136
+ System.err.println("Display " + display + " does not exist, "
137
+ + "returning 1 for displayDensity(" + display + ")");
138
+ return 1; // not the end of the world, so don't throw a RuntimeException
139
+ }
140
+
141
+ static public PImage loadImage(PApplet sketch, String filename, Object... args) {
142
+ String extension = null;
143
+ if (args != null && args.length > 0) {
144
+ // the only one that's supported for now
145
+ extension = (String) args[0];
146
+ }
147
+
148
+ if (extension == null) {
149
+ String lower = filename.toLowerCase();
150
+ int dot = filename.lastIndexOf('.');
151
+ if (dot == -1) {
152
+ extension = "unknown"; // no extension found
153
+
154
+ } else {
155
+ extension = lower.substring(dot + 1);
156
+
157
+ // check for, and strip any parameters on the url, i.e.
158
+ // filename.jpg?blah=blah&something=that
159
+ int question = extension.indexOf('?');
160
+ if (question != -1) {
161
+ extension = extension.substring(0, question);
162
+ }
163
+ }
164
+ }
165
+
166
+ // just in case. them users will try anything!
167
+ extension = extension.toLowerCase();
168
+
169
+ if (extension.equals("tga")) {
170
+ try {
171
+ InputStream input = sketch.createInput(filename);
172
+ if (input == null) {
173
+ return null;
174
+ }
175
+
176
+ PImage image = PImage.loadTGA(input);
177
+ image.parent = sketch;
178
+ return image;
179
+
180
+ } catch (IOException e) {
181
+ return null;
182
+ }
183
+ }
184
+
185
+ if (extension.equals("tif") || extension.equals("tiff")) {
186
+ InputStream input = sketch.createInput(filename);
187
+ PImage image = (input == null) ? null : PImage.loadTIFF(input);
188
+ return image;
189
+ }
190
+
191
+ // For jpeg, gif, and png, load them using createImage(),
192
+ // because the javax.imageio code was found to be much slower.
193
+ // http://dev.processing.org/bugs/show_bug.cgi?id=392
194
+ try {
195
+ if (extension.equals("jpg") || extension.equals("jpeg")
196
+ || extension.equals("gif") || extension.equals("png")
197
+ || extension.equals("unknown")) {
198
+ byte[] bytes = sketch.loadBytes(filename);
199
+ if (bytes == null) {
200
+ return null;
201
+ } else {
202
+ //Image awtImage = Toolkit.getDefaultToolkit().createImage(bytes);
203
+ Image awtImage = new ImageIcon(bytes).getImage();
204
+
205
+ if (awtImage instanceof BufferedImage) {
206
+ BufferedImage buffImage = (BufferedImage) awtImage;
207
+ int space = buffImage.getColorModel().getColorSpace().getType();
208
+ if (space == ColorSpace.TYPE_CMYK) {
209
+ System.err.println(filename + " is a CMYK image, "
210
+ + "only RGB images are supported.");
211
+ return null;
212
+ /*
213
+ // wishful thinking, appears to not be supported
214
+ // https://community.oracle.com/thread/1272045?start=0&tstart=0
215
+ BufferedImage destImage =
216
+ new BufferedImage(buffImage.getWidth(),
217
+ buffImage.getHeight(),
218
+ BufferedImage.TYPE_3BYTE_BGR);
219
+ ColorConvertOp op = new ColorConvertOp(null);
220
+ op.filter(buffImage, destImage);
221
+ image = new PImage(destImage);
222
+ */
223
+ }
224
+ }
225
+
226
+ PImage image = new PImageAWT(awtImage);
227
+ if (image.width == -1) {
228
+ System.err.println("The file " + filename
229
+ + " contains bad image data, or may not be an image.");
230
+ }
231
+
232
+ // if it's a .gif image, test to see if it has transparency
233
+ if (extension.equals("gif") || extension.equals("png")
234
+ || extension.equals("unknown")) {
235
+ image.checkAlpha();
236
+ }
237
+
238
+ image.parent = sketch;
239
+ return image;
240
+ }
241
+ }
242
+ } catch (Exception e) {
243
+ // show error, but move on to the stuff below, see if it'll work
244
+
245
+ }
246
+
247
+ if (loadImageFormats == null) {
248
+ loadImageFormats = ImageIO.getReaderFormatNames();
249
+ }
250
+ if (loadImageFormats != null) {
251
+ for (String loadImageFormat : loadImageFormats) {
252
+ if (extension.equals(loadImageFormat)) {
253
+ return loadImageIO(sketch, filename);
254
+ }
255
+ }
256
+ }
257
+
258
+ // failed, could not load image after all those attempts
259
+ System.err.println("Could not find a method to load " + filename);
260
+ return null;
261
+ }
262
+
263
+ static protected String[] loadImageFormats;
264
+
265
+ /**
266
+ * Use Java 1.4 ImageIO methods to load an image.
267
+ */
268
+ static protected PImage loadImageIO(PApplet sketch, String filename) {
269
+ InputStream stream = sketch.createInput(filename);
270
+ if (stream == null) {
271
+ System.err.println("The image " + filename + " could not be found.");
272
+ return null;
273
+ }
274
+
275
+ try {
276
+ BufferedImage bi = ImageIO.read(stream);
277
+ //PImage outgoing = new PImage(bi.getWidth(), bi.getHeight());
278
+ PImage outgoing = new PImageAWT(bi);
279
+ outgoing.parent = sketch;
280
+
281
+ //bi.getRGB(0, 0, outgoing.width, outgoing.height,
282
+ // outgoing.pixels, 0, outgoing.width);
283
+ // check the alpha for this image
284
+ // was gonna call getType() on the image to see if RGB or ARGB,
285
+ // but it's not actually useful, since gif images will come through
286
+ // as TYPE_BYTE_INDEXED, which means it'll still have to check for
287
+ // the transparency. also, would have to iterate through all the other
288
+ // types and guess whether alpha was in there, so.. just gonna stick
289
+ // with the old method.
290
+ outgoing.checkAlpha();
291
+
292
+ stream.close();
293
+ // return the image
294
+ return outgoing;
295
+
296
+ } catch (IOException e) {
297
+ return null;
298
+ }
299
+ }
300
+
301
+ static public void initRun() {
302
+ // Supposed to help with flicker, but no effect on OS X.
303
+ // TODO IIRC this helped on Windows, but need to double check.
304
+ System.setProperty("sun.awt.noerasebackground", "true");
305
+
306
+ // Remove 60fps limit on the JavaFX "pulse" timer
307
+ System.setProperty("javafx.animation.fullspeed", "true");
308
+
309
+ // Catch any HeadlessException to provide more useful feedback
310
+ try {
311
+ // Call validate() while resize events are in progress
312
+ Toolkit.getDefaultToolkit().setDynamicLayout(true);
313
+ } catch (HeadlessException e) {
314
+ System.err.println("Cannot run sketch without a display. Read this for possible solutions:");
315
+ System.err.println("https://github.com/processing/processing/wiki/Running-without-a-Display");
316
+ System.exit(1);
317
+ }
318
+ }
319
+
320
+
321
+ /*
322
+ public int displayDensity() {
323
+ if (sketch.display != PConstants.SPAN && (sketch.fullScreen || sketch.present)) {
324
+ return displayDensity(sketch.display);
325
+ }
326
+ // walk through all displays, use 2 if any display is 2
327
+ for (int i = 0; i < displayDevices.length; i++) {
328
+ if (displayDensity(i+1) == 2) {
329
+ return 2;
330
+ }
331
+ }
332
+ // If nobody's density is 2 then everyone is 1
333
+ return 1;
334
+ }
335
+ */
336
+ /**
337
+ * @param display the display number to check (1-indexed to match the
338
+ * Preferences dialog box)
339
+ */
340
+ /*
341
+ public int displayDensity(int display) {
342
+ if (display > 0 && display <= displayDevices.length) {
343
+ GraphicsConfiguration graphicsConfig =
344
+ displayDevices[display - 1].getDefaultConfiguration();
345
+ AffineTransform tx = graphicsConfig.getDefaultTransform();
346
+ return (int) Math.round(tx.getScaleX());
347
+ }
348
+
349
+ System.err.println("Display " + display + " does not exist, returning ");
350
+ return 1; // not the end of the world, so don't throw a RuntimeException
351
+ }
352
+ */
353
+ static public void selectInput(String prompt, String callbackMethod,
354
+ File file, Object callbackObject) {
355
+ EventQueue.invokeLater(() -> {
356
+ selectImpl(prompt, callbackMethod, file,
357
+ callbackObject, null, FileDialog.LOAD);
358
+ });
359
+ }
360
+
361
+
362
+ /*
363
+ static public void selectOutput(String prompt, String callbackMethod,
364
+ File file, Object callbackObject, Frame parent) {
365
+ selectImpl(prompt, callbackMethod, file, callbackObject, parent, FileDialog.SAVE, null);
366
+ }
367
+
368
+
369
+ static public void selectOutput(String prompt, String callbackMethod,
370
+ File file, Object callbackObject, Frame parent,
371
+ PApplet sketch) {
372
+ selectImpl(prompt, callbackMethod, file, callbackObject, parent, FileDialog.SAVE, sketch);
373
+ }
374
+ */
375
+ static public void selectOutput(String prompt, String callbackMethod,
376
+ File file, Object callbackObject) {
377
+ EventQueue.invokeLater(() -> {
378
+ selectImpl(prompt, callbackMethod, file,
379
+ callbackObject, null, FileDialog.SAVE);
380
+ });
381
+ }
382
+
383
+
384
+ /*
385
+ // Will remove the 'sketch' parameter once we get an upstream JOGL fix
386
+ // https://github.com/processing/processing/issues/3831
387
+ static protected void selectEvent(final String prompt,
388
+ final String callbackMethod,
389
+ final File defaultSelection,
390
+ final Object callbackObject,
391
+ final Frame parentFrame,
392
+ final int mode,
393
+ final PApplet sketch) {
394
+ EventQueue.invokeLater(new Runnable() {
395
+ public void run() {
396
+ boolean hide = (sketch != null) &&
397
+ (sketch.g instanceof PGraphicsOpenGL) &&
398
+ (PApplet.platform == PConstants.WINDOWS);
399
+ if (hide) sketch.getSurface().setVisible(false);
400
+
401
+ selectImpl(prompt, callbackMethod, defaultSelection, callbackObject,
402
+ parentFrame, mode, sketch);
403
+
404
+ if (hide) sketch.getSurface().setVisible(true);
405
+ }
406
+ });
407
+ }
408
+ */
409
+ static public void selectImpl(final String prompt,
410
+ final String callbackMethod,
411
+ final File defaultSelection,
412
+ final Object callbackObject,
413
+ final Frame parentFrame,
414
+ final int mode) {
415
+ File selectedFile = null;
416
+
417
+ if (PApplet.useNativeSelect) {
418
+ FileDialog dialog = new FileDialog(parentFrame, prompt, mode);
419
+ if (defaultSelection != null) {
420
+ dialog.setDirectory(defaultSelection.getParent());
421
+ dialog.setFile(defaultSelection.getName());
422
+ }
423
+
424
+ dialog.setVisible(true);
425
+ String directory = dialog.getDirectory();
426
+ String filename = dialog.getFile();
427
+ if (filename != null) {
428
+ selectedFile = new File(directory, filename);
429
+ }
430
+
431
+ } else {
432
+ JFileChooser chooser = new JFileChooser();
433
+ chooser.setDialogTitle(prompt);
434
+ if (defaultSelection != null) {
435
+ chooser.setSelectedFile(defaultSelection);
436
+ }
437
+
438
+ int result = -1;
439
+ if (mode == FileDialog.SAVE) {
440
+ result = chooser.showSaveDialog(parentFrame);
441
+ } else if (mode == FileDialog.LOAD) {
442
+ result = chooser.showOpenDialog(parentFrame);
443
+ }
444
+ if (result == JFileChooser.APPROVE_OPTION) {
445
+ selectedFile = chooser.getSelectedFile();
446
+ }
447
+ }
448
+ PApplet.selectCallback(selectedFile, callbackMethod, callbackObject);
449
+ }
450
+
451
+ static public void selectFolder(final String prompt,
452
+ final String callbackMethod,
453
+ final File defaultSelection,
454
+ final Object callbackObject) {
455
+ EventQueue.invokeLater(() -> {
456
+ selectFolderImpl(prompt, callbackMethod, defaultSelection,
457
+ callbackObject, null);
458
+ });
459
+ }
460
+
461
+
462
+ /*
463
+ static public void selectFolder(final String prompt,
464
+ final String callbackMethod,
465
+ final File defaultSelection,
466
+ final Object callbackObject,
467
+ final Frame parentFrame) {
468
+ selectFolderEvent(prompt, callbackMethod, defaultSelection, callbackObject, parentFrame, null);
469
+ }
470
+
471
+
472
+ // Will remove the 'sketch' parameter once we get an upstream JOGL fix
473
+ // https://github.com/processing/processing/issues/3831
474
+ static public void selectFolderEvent(final String prompt,
475
+ final String callbackMethod,
476
+ final File defaultSelection,
477
+ final Object callbackObject,
478
+ final Frame parentFrame,
479
+ final PApplet sketch) {
480
+ EventQueue.invokeLater(() -> {
481
+ selectFolderImpl(prompt, callbackMethod, defaultSelection,
482
+ callbackObject, parentFrame, sketch);
483
+ });
484
+ }
485
+ */
486
+ static public void selectFolderImpl(final String prompt,
487
+ final String callbackMethod,
488
+ final File defaultSelection,
489
+ final Object callbackObject,
490
+ final Frame parentFrame) {
491
+ File selectedFile = null;
492
+
493
+ checkLookAndFeel();
494
+ JFileChooser fileChooser = new JFileChooser();
495
+ fileChooser.setDialogTitle(prompt);
496
+ fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
497
+ if (defaultSelection != null) {
498
+ fileChooser.setCurrentDirectory(defaultSelection);
499
+ }
500
+
501
+ int result = fileChooser.showOpenDialog(parentFrame);
502
+ if (result == JFileChooser.APPROVE_OPTION) {
503
+ selectedFile = fileChooser.getSelectedFile();
504
+ }
505
+
506
+ PApplet.selectCallback(selectedFile, callbackMethod, callbackObject);
507
+ }
508
+
509
+ static private boolean lookAndFeelCheck;
510
+
511
+ /**
512
+ * Initialize the Look & Feel if it hasn't been already. Call this before
513
+ * using any Swing-related code in PApplet methods.
514
+ */
515
+ static private void checkLookAndFeel() {
516
+ if (!lookAndFeelCheck) {
517
+ if (PApplet.platform == PConstants.WINDOWS) {
518
+ // Windows is defaulting to Metal or something else awful.
519
+ // Which also is not scaled properly with HiDPI interfaces.
520
+ try {
521
+ UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
522
+ } catch (ClassNotFoundException | IllegalAccessException | InstantiationException | UnsupportedLookAndFeelException e) {
523
+ }
524
+ }
525
+ lookAndFeelCheck = true;
526
+ }
527
+ }
528
+
529
+ // TODO maybe call this with reflection from inside PApplet?
530
+ // longer term, develop a more general method for other platforms
531
+ static public File getWindowsDesktop() {
532
+ return FileSystemView.getFileSystemView().getHomeDirectory();
533
+ }
534
+
535
+ static public boolean openLink(String url) {
536
+ try {
537
+ if (Desktop.isDesktopSupported()) {
538
+ Desktop.getDesktop().browse(new URI(url));
539
+ return true;
540
+ }
541
+ } catch (IOException | URISyntaxException e) {
542
+ }
543
+ return false;
544
+ }
545
+ }