picrate 1.2.3-java → 2.1.0-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (101) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +8 -0
  3. data/Gemfile +3 -1
  4. data/README.md +8 -9
  5. data/Rakefile +10 -9
  6. data/bin/picrate +3 -1
  7. data/docs/_config.yml +1 -1
  8. data/docs/_editors/geany.md +1 -0
  9. data/docs/_gems/gems/gems.md +1 -1
  10. data/docs/_posts/2018-05-06-getting_started.md +4 -4
  11. data/docs/_posts/2018-05-06-install_jruby.md +5 -11
  12. data/docs/_posts/2018-05-11-arch-linux-arm.md +1 -11
  13. data/docs/_posts/2018-11-18-building-gem.md +2 -2
  14. data/docs/_posts/2018-11-27-getting_started_geany.md +4 -4
  15. data/docs/_posts/2019-11-11-getting_started_buster.md +4 -7
  16. data/docs/_posts/2020-03-09-auto_install_picrate.md +34 -0
  17. data/docs/_posts/2020-05-11-getting_started_manjaro.md +94 -0
  18. data/docs/about.md +1 -1
  19. data/lib/picrate.rb +1 -1
  20. data/lib/picrate/app.rb +11 -3
  21. data/lib/picrate/creators/parameters.rb +8 -8
  22. data/lib/picrate/creators/sketch_factory.rb +5 -3
  23. data/lib/picrate/helper_methods.rb +21 -21
  24. data/lib/picrate/helpers/numeric.rb +2 -0
  25. data/lib/picrate/library.rb +5 -1
  26. data/lib/picrate/library_loader.rb +2 -0
  27. data/lib/picrate/native_folder.rb +2 -1
  28. data/lib/picrate/native_loader.rb +3 -0
  29. data/lib/picrate/runner.rb +5 -2
  30. data/lib/picrate/version.rb +1 -1
  31. data/library/boids/boids.rb +17 -8
  32. data/library/chooser/chooser.rb +10 -9
  33. data/library/color_group/color_group.rb +2 -0
  34. data/library/control_panel/control_panel.rb +7 -4
  35. data/library/dxf/dxf.rb +2 -0
  36. data/library/library_proxy/library_proxy.rb +2 -0
  37. data/library/net/net.rb +2 -0
  38. data/library/slider/slider.rb +24 -23
  39. data/library/vector_utils/vector_utils.rb +4 -0
  40. data/library/video_event/video_event.rb +2 -0
  41. data/picrate.gemspec +13 -14
  42. data/pom.rb +28 -26
  43. data/pom.xml +18 -6
  44. data/src/main/java/monkstone/ColorUtil.java +1 -1
  45. data/src/main/java/monkstone/MathToolModule.java +1 -1
  46. data/src/main/java/monkstone/PicrateLibrary.java +8 -8
  47. data/src/main/java/monkstone/fastmath/Deglut.java +16 -16
  48. data/src/main/java/monkstone/filechooser/Chooser.java +1 -1
  49. data/src/main/java/monkstone/noise/SimplexNoise.java +3 -3
  50. data/src/main/java/monkstone/slider/CustomHorizontalSlider.java +1 -1
  51. data/src/main/java/monkstone/slider/CustomVerticalSlider.java +1 -1
  52. data/src/main/java/monkstone/slider/SimpleHorizontalSlider.java +12 -12
  53. data/src/main/java/monkstone/slider/SimpleVerticalSlider.java +1 -1
  54. data/src/main/java/monkstone/slider/SliderBar.java +1 -1
  55. data/src/main/java/monkstone/slider/SliderGroup.java +1 -1
  56. data/src/main/java/monkstone/slider/WheelHandler.java +1 -1
  57. data/src/main/java/monkstone/vecmath/package-info.java +1 -1
  58. data/src/main/java/monkstone/vecmath/vec2/Vec2.java +1 -1
  59. data/src/main/java/monkstone/vecmath/vec3/Vec3.java +1 -1
  60. data/src/main/java/monkstone/videoevent/CaptureEvent.java +1 -1
  61. data/src/main/java/monkstone/videoevent/MovieEvent.java +1 -1
  62. data/src/main/java/monkstone/videoevent/package-info.java +1 -1
  63. data/src/main/java/processing/awt/PGraphicsJava2D.java +33 -36
  64. data/src/main/java/processing/awt/PImageAWT.java +377 -0
  65. data/src/main/java/processing/awt/PSurfaceAWT.java +0 -20
  66. data/src/main/java/processing/awt/ShimAWT.java +545 -0
  67. data/src/main/java/processing/core/PApplet.java +699 -1523
  68. data/src/main/java/processing/core/PConstants.java +180 -180
  69. data/src/main/java/processing/core/PFont.java +2 -2
  70. data/src/main/java/processing/core/PGraphics.java +190 -176
  71. data/src/main/java/processing/core/PImage.java +1536 -1721
  72. data/src/main/java/processing/core/PMatrix.java +39 -39
  73. data/src/main/java/processing/core/PSurface.java +69 -103
  74. data/src/main/java/processing/core/PSurfaceNone.java +29 -0
  75. data/src/main/java/processing/core/PVector.java +2 -2
  76. data/src/main/java/processing/data/FloatDict.java +251 -284
  77. data/src/main/java/processing/data/TableRow.java +32 -32
  78. data/src/main/java/processing/dxf/RawDXF.java +3 -3
  79. data/src/main/java/processing/net/Client.java +1 -1
  80. data/src/main/java/processing/opengl/PGL.java +1016 -4132
  81. data/src/main/java/processing/opengl/PGraphicsOpenGL.java +223 -184
  82. data/src/main/java/processing/opengl/PJOGL.java +374 -1526
  83. data/src/main/java/processing/opengl/PShapeOpenGL.java +5 -6
  84. data/src/main/java/processing/opengl/PSurfaceJOGL.java +262 -147
  85. data/test/color_group_test.rb +4 -4
  86. data/test/deglut_spec_test.rb +2 -0
  87. data/test/helper_methods_test.rb +41 -13
  88. data/test/math_tool_test.rb +46 -37
  89. data/test/respond_to_test.rb +5 -3
  90. data/test/sketches/key_event.rb +2 -2
  91. data/test/sketches/library/my_library/my_library.rb +3 -0
  92. data/test/test_helper.rb +2 -0
  93. data/test/vecmath_spec_test.rb +30 -19
  94. data/vendors/Rakefile +13 -7
  95. data/vendors/{picrate_sketches.geany → geany.rb} +32 -7
  96. metadata +26 -47
  97. data/docs/_posts/2018-06-26-auto_install_picrate.md +0 -30
  98. data/src/main/java/processing/opengl/shaders/LightVert-brcm.glsl +0 -154
  99. data/src/main/java/processing/opengl/shaders/LightVert-vc4.glsl +0 -154
  100. data/src/main/java/processing/opengl/shaders/TexLightVert-brcm.glsl +0 -160
  101. data/src/main/java/processing/opengl/shaders/TexLightVert-vc4.glsl +0 -160
@@ -668,26 +668,6 @@ public class PSurfaceAWT extends PSurfaceNone {
668
668
 
669
669
  } catch (Exception e) {
670
670
  } // harmless; keep this to ourselves
671
-
672
- // } else { // handle OS X differently
673
- // if (!dockIconSpecified()) { // don't override existing -Xdock param
674
- // // On OS X, set this for AWT surfaces, which handles the dock image
675
- // // as well as the cmd-tab image that's shown. Just one size, I guess.
676
- // URL url = PApplet.class.getResource("/icon/icon-512.png");
677
- // // Seems dangerous to have this in code instead of using reflection, no?
678
- // //ThinkDifferent.setIconImage(Toolkit.getDefaultToolkit().getImage(url));
679
- // try {
680
- // final String td = "processing.core.ThinkDifferent";
681
- // Class<?> thinkDifferent =
682
- // Thread.currentThread().getContextClassLoader().loadClass(td);
683
- // Method method =
684
- // thinkDifferent.getMethod("setIconImage", new Class[] { java.awt.Image.class });
685
- // method.invoke(null, new Object[] { Toolkit.getDefaultToolkit().getImage(url) });
686
- // } catch (Exception e) {
687
- // e.printStackTrace(); // That's unfortunate
688
- // }
689
- // }
690
- // }
691
671
  }
692
672
 
693
673
  /**
@@ -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
+ }