picrate 0.0.2-java

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (179) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +47 -0
  3. data/.mvn/extensions.xml +9 -0
  4. data/.mvn/wrapper/maven-wrapper.properties +1 -0
  5. data/.travis.yml +10 -0
  6. data/CHANGELOG.md +4 -0
  7. data/LICENSE.md +165 -0
  8. data/README.md +51 -0
  9. data/Rakefile +59 -0
  10. data/bin/picrate +8 -0
  11. data/docs/.gitignore +6 -0
  12. data/docs/_config.yml +30 -0
  13. data/docs/_includes/footer.html +38 -0
  14. data/docs/_includes/head.html +16 -0
  15. data/docs/_includes/header.html +27 -0
  16. data/docs/_includes/icon-github.html +1 -0
  17. data/docs/_includes/icon-github.svg +1 -0
  18. data/docs/_includes/icon-twitter.html +1 -0
  19. data/docs/_includes/icon-twitter.svg +1 -0
  20. data/docs/_includes/navigation.html +24 -0
  21. data/docs/_layouts/default.html +20 -0
  22. data/docs/_layouts/page.html +14 -0
  23. data/docs/_layouts/post.html +15 -0
  24. data/docs/_posts/2018-05-06-getting_started.md +8 -0
  25. data/docs/_posts/2018-05-06-install_jruby.md +35 -0
  26. data/docs/_sass/_base.scss +206 -0
  27. data/docs/_sass/_layout.scss +242 -0
  28. data/docs/_sass/_syntax-highlighting.scss +71 -0
  29. data/docs/about.md +10 -0
  30. data/docs/css/main.scss +38 -0
  31. data/docs/favicon.ico +0 -0
  32. data/docs/feed.xml +30 -0
  33. data/docs/index.html +38 -0
  34. data/lib/picrate.rb +10 -0
  35. data/lib/picrate/app.rb +187 -0
  36. data/lib/picrate/creators/sketch_class.rb +57 -0
  37. data/lib/picrate/creators/sketch_factory.rb +12 -0
  38. data/lib/picrate/creators/sketch_writer.rb +21 -0
  39. data/lib/picrate/helper_methods.rb +214 -0
  40. data/lib/picrate/helpers/numeric.rb +9 -0
  41. data/lib/picrate/library.rb +69 -0
  42. data/lib/picrate/library_loader.rb +53 -0
  43. data/lib/picrate/native_folder.rb +35 -0
  44. data/lib/picrate/native_loader.rb +27 -0
  45. data/lib/picrate/runner.rb +81 -0
  46. data/lib/picrate/version.rb +4 -0
  47. data/library/boids/boids.rb +209 -0
  48. data/library/chooser/chooser.rb +19 -0
  49. data/library/control_panel/control_panel.rb +182 -0
  50. data/library/library_proxy/README.md +99 -0
  51. data/library/library_proxy/library_proxy.rb +14 -0
  52. data/library/slider/slider.rb +42 -0
  53. data/library/vector_utils/vector_utils.rb +69 -0
  54. data/library/video_event/video_event.rb +3 -0
  55. data/license.txt +508 -0
  56. data/picrate.gemspec +35 -0
  57. data/pom.rb +122 -0
  58. data/pom.xml +214 -0
  59. data/src/main/java/japplemenubar/JAppleMenuBar.java +88 -0
  60. data/src/main/java/japplemenubar/libjAppleMenuBar.jnilib +0 -0
  61. data/src/main/java/monkstone/ColorUtil.java +115 -0
  62. data/src/main/java/monkstone/MathToolModule.java +236 -0
  63. data/src/main/java/monkstone/PicrateLibrary.java +47 -0
  64. data/src/main/java/monkstone/core/LibraryProxy.java +127 -0
  65. data/src/main/java/monkstone/fastmath/Deglut.java +122 -0
  66. data/src/main/java/monkstone/fastmath/package-info.java +6 -0
  67. data/src/main/java/monkstone/filechooser/Chooser.java +48 -0
  68. data/src/main/java/monkstone/noise/SimplexNoise.java +465 -0
  69. data/src/main/java/monkstone/slider/CustomHorizontalSlider.java +168 -0
  70. data/src/main/java/monkstone/slider/CustomVerticalSlider.java +182 -0
  71. data/src/main/java/monkstone/slider/SimpleHorizontalSlider.java +149 -0
  72. data/src/main/java/monkstone/slider/SimpleSlider.java +196 -0
  73. data/src/main/java/monkstone/slider/SimpleVerticalSlider.java +163 -0
  74. data/src/main/java/monkstone/slider/Slider.java +67 -0
  75. data/src/main/java/monkstone/slider/SliderBar.java +277 -0
  76. data/src/main/java/monkstone/slider/SliderGroup.java +78 -0
  77. data/src/main/java/monkstone/slider/WheelHandler.java +35 -0
  78. data/src/main/java/monkstone/vecmath/AppRender.java +87 -0
  79. data/src/main/java/monkstone/vecmath/JRender.java +56 -0
  80. data/src/main/java/monkstone/vecmath/ShapeRender.java +87 -0
  81. data/src/main/java/monkstone/vecmath/package-info.java +20 -0
  82. data/src/main/java/monkstone/vecmath/vec2/Vec2.java +757 -0
  83. data/src/main/java/monkstone/vecmath/vec2/package-info.java +6 -0
  84. data/src/main/java/monkstone/vecmath/vec3/Vec3.java +727 -0
  85. data/src/main/java/monkstone/vecmath/vec3/package-info.java +6 -0
  86. data/src/main/java/monkstone/videoevent/VideoInterface.java +42 -0
  87. data/src/main/java/monkstone/videoevent/package-info.java +20 -0
  88. data/src/main/java/processing/awt/PGraphicsJava2D.java +3098 -0
  89. data/src/main/java/processing/awt/PShapeJava2D.java +401 -0
  90. data/src/main/java/processing/awt/PSurfaceAWT.java +1660 -0
  91. data/src/main/java/processing/core/PApplet.java +17647 -0
  92. data/src/main/java/processing/core/PConstants.java +1033 -0
  93. data/src/main/java/processing/core/PFont.java +1250 -0
  94. data/src/main/java/processing/core/PGraphics.java +9614 -0
  95. data/src/main/java/processing/core/PImage.java +3608 -0
  96. data/src/main/java/processing/core/PMatrix.java +347 -0
  97. data/src/main/java/processing/core/PMatrix2D.java +694 -0
  98. data/src/main/java/processing/core/PMatrix3D.java +1153 -0
  99. data/src/main/java/processing/core/PShape.java +4332 -0
  100. data/src/main/java/processing/core/PShapeOBJ.java +544 -0
  101. data/src/main/java/processing/core/PShapeSVG.java +1987 -0
  102. data/src/main/java/processing/core/PStyle.java +208 -0
  103. data/src/main/java/processing/core/PSurface.java +242 -0
  104. data/src/main/java/processing/core/PSurfaceNone.java +479 -0
  105. data/src/main/java/processing/core/PVector.java +1140 -0
  106. data/src/main/java/processing/data/FloatDict.java +829 -0
  107. data/src/main/java/processing/data/FloatList.java +912 -0
  108. data/src/main/java/processing/data/IntDict.java +796 -0
  109. data/src/main/java/processing/data/IntList.java +913 -0
  110. data/src/main/java/processing/data/JSONArray.java +1260 -0
  111. data/src/main/java/processing/data/JSONObject.java +2282 -0
  112. data/src/main/java/processing/data/JSONTokener.java +435 -0
  113. data/src/main/java/processing/data/Sort.java +46 -0
  114. data/src/main/java/processing/data/StringDict.java +601 -0
  115. data/src/main/java/processing/data/StringList.java +775 -0
  116. data/src/main/java/processing/data/Table.java +4923 -0
  117. data/src/main/java/processing/data/TableRow.java +198 -0
  118. data/src/main/java/processing/data/XML.java +1149 -0
  119. data/src/main/java/processing/event/Event.java +108 -0
  120. data/src/main/java/processing/event/KeyEvent.java +70 -0
  121. data/src/main/java/processing/event/MouseEvent.java +149 -0
  122. data/src/main/java/processing/event/TouchEvent.java +57 -0
  123. data/src/main/java/processing/javafx/PGraphicsFX2D.java +354 -0
  124. data/src/main/java/processing/opengl/FontTexture.java +379 -0
  125. data/src/main/java/processing/opengl/FrameBuffer.java +503 -0
  126. data/src/main/java/processing/opengl/LinePath.java +623 -0
  127. data/src/main/java/processing/opengl/LineStroker.java +685 -0
  128. data/src/main/java/processing/opengl/PGL.java +3366 -0
  129. data/src/main/java/processing/opengl/PGraphics2D.java +615 -0
  130. data/src/main/java/processing/opengl/PGraphics3D.java +281 -0
  131. data/src/main/java/processing/opengl/PGraphicsOpenGL.java +13634 -0
  132. data/src/main/java/processing/opengl/PJOGL.java +1966 -0
  133. data/src/main/java/processing/opengl/PShader.java +1478 -0
  134. data/src/main/java/processing/opengl/PShapeOpenGL.java +5234 -0
  135. data/src/main/java/processing/opengl/PSurfaceJOGL.java +1315 -0
  136. data/src/main/java/processing/opengl/Texture.java +1670 -0
  137. data/src/main/java/processing/opengl/VertexBuffer.java +88 -0
  138. data/src/main/java/processing/opengl/cursors/arrow.png +0 -0
  139. data/src/main/java/processing/opengl/cursors/cross.png +0 -0
  140. data/src/main/java/processing/opengl/cursors/hand.png +0 -0
  141. data/src/main/java/processing/opengl/cursors/license.txt +27 -0
  142. data/src/main/java/processing/opengl/cursors/move.png +0 -0
  143. data/src/main/java/processing/opengl/cursors/text.png +0 -0
  144. data/src/main/java/processing/opengl/cursors/wait.png +0 -0
  145. data/src/main/java/processing/opengl/shaders/ColorFrag.glsl +32 -0
  146. data/src/main/java/processing/opengl/shaders/ColorVert.glsl +34 -0
  147. data/src/main/java/processing/opengl/shaders/LightFrag.glsl +33 -0
  148. data/src/main/java/processing/opengl/shaders/LightVert-vc4.glsl +154 -0
  149. data/src/main/java/processing/opengl/shaders/LightVert.glsl +151 -0
  150. data/src/main/java/processing/opengl/shaders/LineFrag.glsl +32 -0
  151. data/src/main/java/processing/opengl/shaders/LineVert.glsl +100 -0
  152. data/src/main/java/processing/opengl/shaders/MaskFrag.glsl +40 -0
  153. data/src/main/java/processing/opengl/shaders/PointFrag.glsl +32 -0
  154. data/src/main/java/processing/opengl/shaders/PointVert.glsl +56 -0
  155. data/src/main/java/processing/opengl/shaders/TexFrag.glsl +37 -0
  156. data/src/main/java/processing/opengl/shaders/TexLightFrag.glsl +37 -0
  157. data/src/main/java/processing/opengl/shaders/TexLightVert-vc4.glsl +160 -0
  158. data/src/main/java/processing/opengl/shaders/TexLightVert.glsl +157 -0
  159. data/src/main/java/processing/opengl/shaders/TexVert.glsl +38 -0
  160. data/src/main/resources/icon/icon-1024.png +0 -0
  161. data/src/main/resources/icon/icon-128.png +0 -0
  162. data/src/main/resources/icon/icon-16.png +0 -0
  163. data/src/main/resources/icon/icon-256.png +0 -0
  164. data/src/main/resources/icon/icon-32.png +0 -0
  165. data/src/main/resources/icon/icon-48.png +0 -0
  166. data/src/main/resources/icon/icon-512.png +0 -0
  167. data/src/main/resources/icon/icon-64.png +0 -0
  168. data/src/main/resources/license.txt +508 -0
  169. data/test/create_test.rb +68 -0
  170. data/test/deglut_spec_test.rb +24 -0
  171. data/test/helper_methods_test.rb +58 -0
  172. data/test/math_tool_test.rb +75 -0
  173. data/test/respond_to_test.rb +215 -0
  174. data/test/sketches/key_event.rb +37 -0
  175. data/test/sketches/library/my_library/my_library.rb +32 -0
  176. data/test/test_helper.rb +3 -0
  177. data/test/vecmath_spec_test.rb +522 -0
  178. data/vendors/Rakefile +127 -0
  179. metadata +289 -0
@@ -0,0 +1,401 @@
1
+ /* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
2
+
3
+ /*
4
+ Part of the Processing project - http://processing.org
5
+
6
+ Copyright (c) 2015 The Processing Foundation
7
+
8
+ This library is free software; you can redistribute it and/or
9
+ modify it under the terms of the GNU Lesser General Public
10
+ License version 2.1 as published by the Free Software Foundation.
11
+
12
+ This library is distributed in the hope that it will be useful,
13
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
+ Lesser General Public License for more details.
16
+
17
+ You should have received a copy of the GNU Lesser General
18
+ Public License along with this library; if not, write to the
19
+ Free Software Foundation, Inc., 59 Temple Place, Suite 330,
20
+ Boston, MA 02111-1307 USA
21
+ */
22
+
23
+ package processing.awt;
24
+
25
+ import java.awt.Paint;
26
+ import java.awt.PaintContext;
27
+ import java.awt.Rectangle;
28
+ import java.awt.RenderingHints;
29
+ import java.awt.geom.AffineTransform;
30
+ import java.awt.geom.Point2D;
31
+ import java.awt.geom.Rectangle2D;
32
+ import java.awt.image.ColorModel;
33
+ import java.awt.image.Raster;
34
+ import java.awt.image.WritableRaster;
35
+
36
+ import processing.core.PApplet;
37
+ import processing.core.PGraphics;
38
+ import processing.core.PShapeSVG;
39
+ import processing.data.*;
40
+
41
+
42
+ /**
43
+ * Implements features for PShape that are specific to AWT and Java2D.
44
+ * At the moment, this is gradients and java.awt.Paint handling.
45
+ */
46
+ public class PShapeJava2D extends PShapeSVG {
47
+ Paint strokeGradientPaint;
48
+ Paint fillGradientPaint;
49
+
50
+ /**
51
+ *
52
+ * @param svg
53
+ */
54
+ public PShapeJava2D(XML svg) {
55
+ super(svg);
56
+ }
57
+
58
+ /**
59
+ *
60
+ * @param parent
61
+ * @param properties
62
+ * @param parseKids
63
+ */
64
+ public PShapeJava2D(PShapeSVG parent, XML properties, boolean parseKids) {
65
+ super(parent, properties, parseKids);
66
+ }
67
+
68
+ /**
69
+ *
70
+ * @param parent
71
+ */
72
+ @Override
73
+ protected void setParent(PShapeSVG parent) {
74
+ super.setParent(parent);
75
+
76
+ if (parent instanceof PShapeJava2D) {
77
+ PShapeJava2D pj = (PShapeJava2D) parent;
78
+ fillGradientPaint = pj.fillGradientPaint;
79
+ strokeGradientPaint = pj.strokeGradientPaint;
80
+
81
+ } else { // parent is null or not Java2D
82
+ fillGradientPaint = null;
83
+ strokeGradientPaint = null;
84
+ }
85
+ }
86
+
87
+
88
+ /** Factory method for subclasses.
89
+ * @param parent
90
+ * @param properties
91
+ * @param parseKids
92
+ * @return */
93
+ @Override
94
+ protected PShapeSVG createShape(PShapeSVG parent, XML properties, boolean parseKids) {
95
+ return new PShapeJava2D(parent, properties, parseKids);
96
+ }
97
+
98
+
99
+ /*
100
+ @Override
101
+ public void setColor(String colorText, boolean isFill) {
102
+ super.setColor(colorText, isFill);
103
+
104
+ if (fillGradient != null) {
105
+ fillGradientPaint = calcGradientPaint(fillGradient);
106
+ }
107
+ if (strokeGradient != null) {
108
+ strokeGradientPaint = calcGradientPaint(strokeGradient);
109
+ }
110
+ }
111
+ */
112
+
113
+
114
+ static class LinearGradientPaint implements Paint {
115
+ float x1, y1, x2, y2;
116
+ float[] offset;
117
+ int[] color;
118
+ int count;
119
+ float opacity;
120
+
121
+ public LinearGradientPaint(float x1, float y1, float x2, float y2,
122
+ float[] offset, int[] color, int count,
123
+ float opacity) {
124
+ this.x1 = x1;
125
+ this.y1 = y1;
126
+ this.x2 = x2;
127
+ this.y2 = y2;
128
+ this.offset = offset;
129
+ this.color = color;
130
+ this.count = count;
131
+ this.opacity = opacity;
132
+ }
133
+
134
+ public PaintContext createContext(ColorModel cm,
135
+ Rectangle deviceBounds, Rectangle2D userBounds,
136
+ AffineTransform xform, RenderingHints hints) {
137
+ Point2D t1 = xform.transform(new Point2D.Float(x1, y1), null);
138
+ Point2D t2 = xform.transform(new Point2D.Float(x2, y2), null);
139
+ return new LinearGradientContext((float) t1.getX(), (float) t1.getY(),
140
+ (float) t2.getX(), (float) t2.getY());
141
+ }
142
+
143
+ public int getTransparency() {
144
+ return TRANSLUCENT; // why not.. rather than checking each color
145
+ }
146
+
147
+ public class LinearGradientContext implements PaintContext {
148
+ int ACCURACY = 2;
149
+ float tx1, ty1, tx2, ty2;
150
+
151
+ public LinearGradientContext(float tx1, float ty1, float tx2, float ty2) {
152
+ this.tx1 = tx1;
153
+ this.ty1 = ty1;
154
+ this.tx2 = tx2;
155
+ this.ty2 = ty2;
156
+ }
157
+
158
+ public void dispose() { }
159
+
160
+ public ColorModel getColorModel() { return ColorModel.getRGBdefault(); }
161
+
162
+ public Raster getRaster(int x, int y, int w, int h) {
163
+ WritableRaster raster =
164
+ getColorModel().createCompatibleWritableRaster(w, h);
165
+
166
+ int[] data = new int[w * h * 4];
167
+
168
+ // make normalized version of base vector
169
+ float nx = tx2 - tx1;
170
+ float ny = ty2 - ty1;
171
+ float len = (float) Math.sqrt(nx*nx + ny*ny);
172
+ if (len != 0) {
173
+ nx /= len;
174
+ ny /= len;
175
+ }
176
+
177
+ int span = (int) PApplet.dist(tx1, ty1, tx2, ty2) * ACCURACY;
178
+ if (span <= 0) {
179
+ //System.err.println("span is too small");
180
+ // annoying edge case where the gradient isn't legit
181
+ int index = 0;
182
+ for (int j = 0; j < h; j++) {
183
+ for (int i = 0; i < w; i++) {
184
+ data[index++] = 0;
185
+ data[index++] = 0;
186
+ data[index++] = 0;
187
+ data[index++] = 255;
188
+ }
189
+ }
190
+
191
+ } else {
192
+ int[][] interp = new int[span][4];
193
+ int prev = 0;
194
+ for (int i = 1; i < count; i++) {
195
+ int c0 = color[i-1];
196
+ int c1 = color[i];
197
+ int last = (int) (offset[i] * (span-1));
198
+ //System.out.println("last is " + last);
199
+ for (int j = prev; j <= last; j++) {
200
+ float btwn = PApplet.norm(j, prev, last);
201
+ interp[j][0] = (int) PApplet.lerp((c0 >> 16) & 0xff, (c1 >> 16) & 0xff, btwn);
202
+ interp[j][1] = (int) PApplet.lerp((c0 >> 8) & 0xff, (c1 >> 8) & 0xff, btwn);
203
+ interp[j][2] = (int) PApplet.lerp(c0 & 0xff, c1 & 0xff, btwn);
204
+ interp[j][3] = (int) (PApplet.lerp((c0 >> 24) & 0xff, (c1 >> 24) & 0xff, btwn) * opacity);
205
+ //System.out.println(j + " " + interp[j][0] + " " + interp[j][1] + " " + interp[j][2]);
206
+ }
207
+ prev = last;
208
+ }
209
+
210
+ int index = 0;
211
+ for (int j = 0; j < h; j++) {
212
+ for (int i = 0; i < w; i++) {
213
+ //float distance = 0; //PApplet.dist(cx, cy, x + i, y + j);
214
+ //int which = PApplet.min((int) (distance * ACCURACY), interp.length-1);
215
+ float px = (x + i) - tx1;
216
+ float py = (y + j) - ty1;
217
+ // distance up the line is the dot product of the normalized
218
+ // vector of the gradient start/stop by the point being tested
219
+ int which = (int) ((px*nx + py*ny) * ACCURACY);
220
+ if (which < 0) which = 0;
221
+ if (which > interp.length-1) which = interp.length-1;
222
+ //if (which > 138) System.out.println("grabbing " + which);
223
+
224
+ data[index++] = interp[which][0];
225
+ data[index++] = interp[which][1];
226
+ data[index++] = interp[which][2];
227
+ data[index++] = interp[which][3];
228
+ }
229
+ }
230
+ }
231
+ raster.setPixels(0, 0, w, h, data);
232
+
233
+ return raster;
234
+ }
235
+ }
236
+ }
237
+
238
+
239
+ static class RadialGradientPaint implements Paint {
240
+ float cx, cy, radius;
241
+ float[] offset;
242
+ int[] color;
243
+ int count;
244
+ float opacity;
245
+
246
+ public RadialGradientPaint(float cx, float cy, float radius,
247
+ float[] offset, int[] color, int count,
248
+ float opacity) {
249
+ this.cx = cx;
250
+ this.cy = cy;
251
+ this.radius = radius;
252
+ this.offset = offset;
253
+ this.color = color;
254
+ this.count = count;
255
+ this.opacity = opacity;
256
+ }
257
+
258
+ public PaintContext createContext(ColorModel cm,
259
+ Rectangle deviceBounds, Rectangle2D userBounds,
260
+ AffineTransform xform, RenderingHints hints) {
261
+ return new RadialGradientContext();
262
+ }
263
+
264
+ public int getTransparency() {
265
+ return TRANSLUCENT;
266
+ }
267
+
268
+ public class RadialGradientContext implements PaintContext {
269
+ int ACCURACY = 5;
270
+
271
+ public void dispose() {}
272
+
273
+ public ColorModel getColorModel() { return ColorModel.getRGBdefault(); }
274
+
275
+ public Raster getRaster(int x, int y, int w, int h) {
276
+ WritableRaster raster =
277
+ getColorModel().createCompatibleWritableRaster(w, h);
278
+
279
+ int span = (int) radius * ACCURACY;
280
+ int[][] interp = new int[span][4];
281
+ int prev = 0;
282
+ for (int i = 1; i < count; i++) {
283
+ int c0 = color[i-1];
284
+ int c1 = color[i];
285
+ int last = (int) (offset[i] * (span - 1));
286
+ for (int j = prev; j <= last; j++) {
287
+ float btwn = PApplet.norm(j, prev, last);
288
+ interp[j][0] = (int) PApplet.lerp((c0 >> 16) & 0xff, (c1 >> 16) & 0xff, btwn);
289
+ interp[j][1] = (int) PApplet.lerp((c0 >> 8) & 0xff, (c1 >> 8) & 0xff, btwn);
290
+ interp[j][2] = (int) PApplet.lerp(c0 & 0xff, c1 & 0xff, btwn);
291
+ interp[j][3] = (int) (PApplet.lerp((c0 >> 24) & 0xff, (c1 >> 24) & 0xff, btwn) * opacity);
292
+ }
293
+ prev = last;
294
+ }
295
+
296
+ int[] data = new int[w * h * 4];
297
+ int index = 0;
298
+ for (int j = 0; j < h; j++) {
299
+ for (int i = 0; i < w; i++) {
300
+ float distance = PApplet.dist(cx, cy, x + i, y + j);
301
+ int which = PApplet.min((int) (distance * ACCURACY), interp.length-1);
302
+
303
+ data[index++] = interp[which][0];
304
+ data[index++] = interp[which][1];
305
+ data[index++] = interp[which][2];
306
+ data[index++] = interp[which][3];
307
+ }
308
+ }
309
+ raster.setPixels(0, 0, w, h, data);
310
+
311
+ return raster;
312
+ }
313
+ }
314
+ }
315
+
316
+ /**
317
+ *
318
+ * @param gradient
319
+ * @return
320
+ */
321
+ protected Paint calcGradientPaint(Gradient gradient) {
322
+ if (gradient instanceof LinearGradient) {
323
+ // System.out.println("creating linear gradient");
324
+ LinearGradient grad = (LinearGradient) gradient;
325
+ return new LinearGradientPaint(grad.x1, grad.y1, grad.x2, grad.y2,
326
+ grad.offset, grad.color, grad.count,
327
+ opacity);
328
+
329
+ } else if (gradient instanceof RadialGradient) {
330
+ // System.out.println("creating radial gradient");
331
+ RadialGradient grad = (RadialGradient) gradient;
332
+ return new RadialGradientPaint(grad.cx, grad.cy, grad.r,
333
+ grad.offset, grad.color, grad.count,
334
+ opacity);
335
+ }
336
+ return null;
337
+ }
338
+
339
+
340
+ // protected Paint calcGradientPaint(Gradient gradient,
341
+ // float x1, float y1, float x2, float y2) {
342
+ // if (gradient instanceof LinearGradient) {
343
+ // LinearGradient grad = (LinearGradient) gradient;
344
+ // return new LinearGradientPaint(x1, y1, x2, y2,
345
+ // grad.offset, grad.color, grad.count,
346
+ // opacity);
347
+ // }
348
+ // throw new RuntimeException("Not a linear gradient.");
349
+ // }
350
+
351
+
352
+ // protected Paint calcGradientPaint(Gradient gradient,
353
+ // float cx, float cy, float r) {
354
+ // if (gradient instanceof RadialGradient) {
355
+ // RadialGradient grad = (RadialGradient) gradient;
356
+ // return new RadialGradientPaint(cx, cy, r,
357
+ // grad.offset, grad.color, grad.count,
358
+ // opacity);
359
+ // }
360
+ // throw new RuntimeException("Not a radial gradient.");
361
+ // }
362
+
363
+
364
+ // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
365
+
366
+ /**
367
+ *
368
+ * @param g
369
+ */
370
+
371
+
372
+ @Override
373
+ protected void styles(PGraphics g) {
374
+ super.styles(g);
375
+
376
+ //if (g instanceof PGraphicsJava2D) {
377
+ PGraphicsJava2D p2d = (PGraphicsJava2D) g;
378
+
379
+ if (strokeGradient != null) {
380
+ p2d.strokeGradient = true;
381
+ if (strokeGradientPaint == null) {
382
+ strokeGradientPaint = calcGradientPaint(strokeGradient);
383
+ }
384
+ p2d.strokeGradientObject = strokeGradientPaint;
385
+ } else {
386
+ // need to shut off, in case parent object has a gradient applied
387
+ //p2d.strokeGradient = false;
388
+ }
389
+ if (fillGradient != null) {
390
+ p2d.fillGradient = true;
391
+ if (fillGradientPaint == null) {
392
+ fillGradientPaint = calcGradientPaint(fillGradient);
393
+ }
394
+ p2d.fillGradientObject = fillGradientPaint;
395
+ } else {
396
+ // need to shut off, in case parent object has a gradient applied
397
+ //p2d.fillGradient = false;
398
+ }
399
+ //}
400
+ }
401
+ }
@@ -0,0 +1,1660 @@
1
+ /* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
2
+
3
+ /*
4
+ Part of the Processing project - http://processing.org
5
+
6
+ Copyright (c) 2014-15 The Processing Foundation
7
+
8
+ This library is free software; you can redistribute it and/or
9
+ modify it under the terms of the GNU Lesser General Public
10
+ License as published by the Free Software Foundation, version 2.1.
11
+
12
+ This library is distributed in the hope that it will be useful,
13
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
+ Lesser General Public License for more details.
16
+
17
+ You should have received a copy of the GNU Lesser General
18
+ Public License along with this library; if not, write to the
19
+ Free Software Foundation, Inc., 59 Temple Place, Suite 330,
20
+ Boston, MA 02111-1307 USA
21
+ */
22
+
23
+ package processing.awt;
24
+
25
+ import java.awt.Canvas;
26
+ import java.awt.Color;
27
+ import java.awt.Cursor;
28
+ import java.awt.Dimension;
29
+ import java.awt.Frame;
30
+ import java.awt.Graphics;
31
+ import java.awt.Graphics2D;
32
+ import java.awt.GraphicsConfiguration;
33
+ import java.awt.GraphicsDevice;
34
+ import java.awt.GraphicsEnvironment;
35
+ import java.awt.Image;
36
+ import java.awt.Insets;
37
+ import java.awt.Label;
38
+ import java.awt.Point;
39
+ import java.awt.Rectangle;
40
+ import java.awt.Toolkit;
41
+ import java.awt.event.*;
42
+ import java.awt.geom.Rectangle2D;
43
+ import java.awt.image.*;
44
+ import java.lang.management.ManagementFactory;
45
+ import java.lang.reflect.Method;
46
+ import java.net.URL;
47
+ import java.util.ArrayList;
48
+ import java.util.List;
49
+
50
+ import javax.swing.JFrame;
51
+
52
+ import processing.core.PApplet;
53
+ import processing.core.PConstants;
54
+ import processing.core.PGraphics;
55
+ import processing.core.PImage;
56
+ import processing.core.PSurfaceNone;
57
+ import processing.event.KeyEvent;
58
+ import processing.event.MouseEvent;
59
+
60
+ /**
61
+ *
62
+ * @author tux
63
+ */
64
+ public class PSurfaceAWT extends PSurfaceNone {
65
+ GraphicsDevice displayDevice;
66
+
67
+ // used for canvas to determine whether resizable or not
68
+ // boolean resizable; // default is false
69
+
70
+ // Internally, we know it's always a JFrame (not just a Frame)
71
+ // JFrame frame;
72
+ // Trying Frame again with a11 to see if this avoids some Swing nastiness.
73
+ // In the past, AWT Frames caused some problems on Windows and Linux,
74
+ // but those may not be a problem for our reworked PSurfaceAWT class.
75
+ Frame frame;
76
+
77
+ // Note that x and y may not be zero, depending on the display configuration
78
+ Rectangle screenRect;
79
+
80
+ // Used for resizing, at least on Windows insets size changes when
81
+ // frame.setResizable() is called, and in resize listener we need
82
+ // to know what size the window was before.
83
+ Insets currentInsets = new Insets(0, 0, 0, 0);
84
+
85
+ // 3.0a5 didn't use strategy, and active was shut off during init() w/ retina
86
+ // boolean useStrategy = true;
87
+
88
+ Canvas canvas;
89
+ // Component canvas;
90
+
91
+ // PGraphics graphics; // moved to PSurfaceNone
92
+
93
+ int sketchWidth;
94
+ int sketchHeight;
95
+
96
+ int windowScaleFactor;
97
+
98
+ /**
99
+ *
100
+ * @param graphics
101
+ */
102
+ public PSurfaceAWT(PGraphics graphics) {
103
+ //this.graphics = graphics;
104
+ super(graphics);
105
+
106
+ /*
107
+ if (checkRetina()) {
108
+ // System.out.println("retina in use");
109
+
110
+ // The active-mode rendering seems to be 2x slower, so disable it
111
+ // with retina. On a non-retina machine, however, useActive seems
112
+ // the only (or best) way to handle the rendering.
113
+ // useActive = false;
114
+ // canvas = new JPanel(true) {
115
+ // @Override
116
+ // public void paint(Graphics screen) {
117
+ //// if (!sketch.insideDraw) {
118
+ // screen.drawImage(PSurfaceAWT.this.graphics.image, 0, 0, sketchWidth, sketchHeight, null);
119
+ //// }
120
+ // }
121
+ // };
122
+ // Under 1.8 and the current 3.0a6 threading regime, active mode w/o
123
+ // strategy is far faster, but perhaps only because it's blitting with
124
+ // flicker--pushing pixels out before the screen has finished rendering.
125
+ // useStrategy = false;
126
+ }
127
+ */
128
+ canvas = new SmoothCanvas();
129
+ // if (useStrategy) {
130
+ //canvas.setIgnoreRepaint(true);
131
+ // }
132
+
133
+ // Pass tab key to the sketch, rather than moving between components
134
+ canvas.setFocusTraversalKeysEnabled(false);
135
+
136
+ canvas.addComponentListener(new ComponentAdapter() {
137
+ @Override
138
+ public void componentResized(ComponentEvent e) {
139
+ if (!sketch.isLooping()) {
140
+ // make sure this is a real resize event, not just initial setup
141
+ // https://github.com/processing/processing/issues/3310
142
+ Dimension canvasSize = canvas.getSize();
143
+ if (canvasSize.width != sketch.sketchWidth() ||
144
+ canvasSize.height != sketch.sketchHeight()) {
145
+ sketch.redraw();
146
+ }
147
+ }
148
+ }
149
+ });
150
+ addListeners();
151
+ }
152
+
153
+
154
+ // /**
155
+ // * Handle grabbing the focus on startup. Other renderers can override this
156
+ // * if handling needs to be different. For the AWT, the request is invoked
157
+ // * later on the EDT. Other implementations may not require that, so the
158
+ // * invokeLater() happens in here rather than requiring the caller to wrap it.
159
+ // */
160
+ // @Override
161
+ // void requestFocus() {
162
+ //// System.out.println("requesFocus() outer " + EventQueue.isDispatchThread());
163
+ // // for 2.0a6, moving this request to the EDT
164
+ // EventQueue.invokeLater(new Runnable() {
165
+ // public void run() {
166
+ // // Call the request focus event once the image is sure to be on
167
+ // // screen and the component is valid. The OpenGL renderer will
168
+ // // request focus for its canvas inside beginDraw().
169
+ // // http://java.sun.com/j2se/1.4.2/docs/api/java/awt/doc-files/FocusSpec.html
170
+ // // Disabling for 0185, because it causes an assertion failure on OS X
171
+ // // http://code.google.com/p/processing/issues/detail?id=258
172
+ // // requestFocus();
173
+ //
174
+ // // Changing to this version for 0187
175
+ // // http://code.google.com/p/processing/issues/detail?id=279
176
+ // //requestFocusInWindow();
177
+ //
178
+ // // For 3.0, just call this directly on the Canvas object
179
+ // if (canvas != null) {
180
+ // //System.out.println("requesting focus " + EventQueue.isDispatchThread());
181
+ // //System.out.println("requesting focus " + frame.isVisible());
182
+ // //canvas.requestFocusInWindow();
183
+ // canvas.requestFocus();
184
+ // }
185
+ // }
186
+ // });
187
+ // }
188
+
189
+
190
+ // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
191
+
192
+ /**
193
+ *
194
+ */
195
+
196
+
197
+ public class SmoothCanvas extends Canvas {
198
+ private Dimension oldSize = new Dimension(0, 0);
199
+ private Dimension newSize = new Dimension(0, 0);
200
+
201
+
202
+ // Turns out getParent() returns a JPanel on a JFrame. Yech.
203
+
204
+ /**
205
+ *
206
+ * @return
207
+ */
208
+ public Frame getFrame() {
209
+ return frame;
210
+ }
211
+
212
+ /**
213
+ *
214
+ * @return
215
+ */
216
+ @Override
217
+ public Dimension getPreferredSize() {
218
+ return new Dimension(sketchWidth, sketchHeight);
219
+ }
220
+
221
+ /**
222
+ *
223
+ * @return
224
+ */
225
+ @Override
226
+ public Dimension getMinimumSize() {
227
+ return getPreferredSize();
228
+ }
229
+
230
+ /**
231
+ *
232
+ * @return
233
+ */
234
+ @Override
235
+ public Dimension getMaximumSize() {
236
+ //return resizable ? super.getMaximumSize() : getPreferredSize();
237
+ return frame.isResizable() ? super.getMaximumSize() : getPreferredSize();
238
+ }
239
+
240
+ /**
241
+ *
242
+ */
243
+ @Override
244
+ public void validate() {
245
+ super.validate();
246
+ newSize.width = getWidth();
247
+ newSize.height = getHeight();
248
+ // if (oldSize.equals(newSize)) {
249
+ //// System.out.println("validate() return " + oldSize);
250
+ // return;
251
+ // } else {
252
+ if (!oldSize.equals(newSize)) {
253
+ // System.out.println("validate() render old=" + oldSize + " -> new=" + newSize);
254
+ oldSize = newSize;
255
+ sketch.setSize(newSize.width / windowScaleFactor, newSize.height / windowScaleFactor);
256
+ // try {
257
+ render();
258
+ // } catch (IllegalStateException ise) {
259
+ // System.out.println(ise.getMessage());
260
+ // }
261
+ }
262
+ }
263
+
264
+ /**
265
+ *
266
+ * @param g
267
+ */
268
+ @Override
269
+ public void update(Graphics g) {
270
+ // System.out.println("updating");
271
+ paint(g);
272
+ }
273
+
274
+ /**
275
+ *
276
+ * @param screen
277
+ */
278
+ @Override
279
+ public void paint(Graphics screen) {
280
+ // System.out.println("painting");
281
+ // if (useStrategy) {
282
+ render();
283
+ /*
284
+ if (graphics != null) {
285
+ System.out.println("drawing to screen " + canvas);
286
+ screen.drawImage(graphics.image, 0, 0, sketchWidth, sketchHeight, null);
287
+ }
288
+ */
289
+
290
+ // } else {
291
+ //// new Exception("painting").printStackTrace(System.out);
292
+ //// if (graphics.image != null) { // && !sketch.insideDraw) {
293
+ // if (onscreen != null) {
294
+ //// synchronized (graphics.image) {
295
+ // // Needs the width/height to be set so that retina images are properly scaled down
296
+ //// screen.drawImage(graphics.image, 0, 0, sketchWidth, sketchHeight, null);
297
+ // synchronized (offscreenLock) {
298
+ // screen.drawImage(onscreen, 0, 0, sketchWidth, sketchHeight, null);
299
+ // }
300
+ // }
301
+ // }
302
+ }
303
+ }
304
+
305
+ /*
306
+ @Override
307
+ public void addNotify() {
308
+ // System.out.println("adding notify");
309
+ super.addNotify();
310
+ // prior to Java 7 on OS X, this no longer works [121222]
311
+ // createBufferStrategy(2);
312
+ }
313
+ */
314
+
315
+ /**
316
+ *
317
+ */
318
+ synchronized protected void render() {
319
+ if (canvas.isDisplayable() &&
320
+ graphics.image != null) {
321
+ if (canvas.getBufferStrategy() == null) {
322
+ canvas.createBufferStrategy(2);
323
+ }
324
+ BufferStrategy strategy = canvas.getBufferStrategy();
325
+ if (strategy != null) {
326
+ // Render single frame
327
+ // try {
328
+ do {
329
+ // The following loop ensures that the contents of the drawing buffer
330
+ // are consistent in case the underlying surface was recreated
331
+ do {
332
+ Graphics2D draw = (Graphics2D) strategy.getDrawGraphics();
333
+ // draw to width/height, since this may be a 2x image
334
+ draw.drawImage(graphics.image, 0, 0, sketchWidth, sketchHeight, null);
335
+ draw.dispose();
336
+ } while (strategy.contentsRestored());
337
+
338
+ // Display the buffer
339
+ strategy.show();
340
+
341
+ // Repeat the rendering if the drawing buffer was lost
342
+ } while (strategy.contentsLost());
343
+ }
344
+ }
345
+ }
346
+
347
+
348
+ /*
349
+ protected void blit() {
350
+ // Other folks that call render() (i.e. paint()) are already on the EDT.
351
+ // We need to be using the EDT since we're messing with the Canvas
352
+ // object and BufferStrategy and friends.
353
+ //EventQueue.invokeLater(new Runnable() {
354
+ //public void run() {
355
+ //((SmoothCanvas) canvas).render();
356
+ //}
357
+ //});
358
+
359
+ if (useStrategy) {
360
+ // Not necessary to be on the EDT to update BufferStrategy
361
+ //((SmoothCanvas) canvas).render();
362
+ render();
363
+ } else {
364
+ if (graphics.image != null) {
365
+ BufferedImage graphicsImage = (BufferedImage) graphics.image;
366
+ if (offscreen == null ||
367
+ offscreen.getWidth() != graphicsImage.getWidth() ||
368
+ offscreen.getHeight() != graphicsImage.getHeight()) {
369
+ System.out.println("creating new image");
370
+ offscreen = (BufferedImage)
371
+ canvas.createImage(graphicsImage.getWidth(),
372
+ graphicsImage.getHeight());
373
+ // off = offscreen.getGraphics();
374
+ }
375
+ // synchronized (offscreen) {
376
+ Graphics2D off = (Graphics2D) offscreen.getGraphics();
377
+ // off.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1));
378
+ off.drawImage(graphicsImage, 0, 0, null);
379
+ // }
380
+ off.dispose();
381
+ synchronized (offscreenLock) {
382
+ BufferedImage temp = onscreen;
383
+ onscreen = offscreen;
384
+ offscreen = temp;
385
+ }
386
+ canvas.repaint();
387
+ }
388
+ }
389
+ }
390
+ */
391
+
392
+
393
+ // what needs to happen here?
394
+
395
+ /**
396
+ *
397
+ * @param sketch
398
+ */
399
+ @Override
400
+ public void initOffscreen(PApplet sketch) {
401
+ this.sketch = sketch;
402
+ }
403
+
404
+ /*
405
+ public Frame initOffscreen() {
406
+ Frame dummy = new Frame();
407
+ dummy.pack(); // get legit AWT graphics
408
+ // but don't show it
409
+ return dummy;
410
+ }
411
+ */
412
+
413
+ /*
414
+ @Override
415
+ public Component initComponent(PApplet sketch) {
416
+ this.sketch = sketch;
417
+
418
+ // needed for getPreferredSize() et al
419
+ sketchWidth = sketch.sketchWidth();
420
+ sketchHeight = sketch.sketchHeight();
421
+
422
+ return canvas;
423
+ }
424
+ */
425
+
426
+ /**
427
+ *
428
+ * @param sketch
429
+ */
430
+ @Override
431
+ public void initFrame(final PApplet sketch) {/*, int backgroundColor,
432
+ int deviceIndex, boolean fullScreen, boolean spanDisplays) {*/
433
+ this.sketch = sketch;
434
+
435
+ GraphicsEnvironment environment =
436
+ GraphicsEnvironment.getLocalGraphicsEnvironment();
437
+
438
+ int displayNum = sketch.sketchDisplay();
439
+ // System.out.println("display from sketch is " + displayNum);
440
+ if (displayNum > 0) { // if -1, use the default device
441
+ GraphicsDevice[] devices = environment.getScreenDevices();
442
+ if (displayNum <= devices.length) {
443
+ displayDevice = devices[displayNum - 1];
444
+ } else {
445
+ System.err.format("Display %d does not exist, " +
446
+ "using the default display instead.%n", displayNum);
447
+ for (int i = 0; i < devices.length; i++) {
448
+ System.err.format("Display %d is %s%n", (i+1), devices[i]);
449
+ }
450
+ }
451
+ }
452
+ if (displayDevice == null) {
453
+ displayDevice = environment.getDefaultScreenDevice();
454
+ }
455
+
456
+ // Need to save the window bounds at full screen,
457
+ // because pack() will cause the bounds to go to zero.
458
+ // http://dev.processing.org/bugs/show_bug.cgi?id=923
459
+ boolean spanDisplays = sketch.sketchDisplay() == PConstants.SPAN;
460
+ screenRect = spanDisplays ? getDisplaySpan() :
461
+ displayDevice.getDefaultConfiguration().getBounds();
462
+ // DisplayMode doesn't work here, because we can't get the upper-left
463
+ // corner of the display, which is important for multi-display setups.
464
+
465
+ // Set the displayWidth/Height variables inside PApplet, so that they're
466
+ // usable and can even be returned by the sketchWidth()/Height() methods.
467
+ sketch.displayWidth = screenRect.width;
468
+ sketch.displayHeight = screenRect.height;
469
+
470
+ windowScaleFactor = PApplet.platform == PConstants.MACOSX ?
471
+ 1 : sketch.pixelDensity;
472
+
473
+ sketchWidth = sketch.sketchWidth() * windowScaleFactor;
474
+ sketchHeight = sketch.sketchHeight() * windowScaleFactor;
475
+
476
+ boolean fullScreen = sketch.sketchFullScreen();
477
+ // Removing the section below because sometimes people want to do the
478
+ // full screen size in a window, and it also breaks insideSettings().
479
+ // With 3.x, fullScreen() is so easy, that it's just better that way.
480
+ // https://github.com/processing/processing/issues/3545
481
+ /*
482
+ // Sketch has already requested to be the same as the screen's
483
+ // width and height, so let's roll with full screen mode.
484
+ if (screenRect.width == sketchWidth &&
485
+ screenRect.height == sketchHeight) {
486
+ fullScreen = true;
487
+ sketch.fullScreen(); // won't change the renderer
488
+ }
489
+ */
490
+
491
+ if (fullScreen || spanDisplays) {
492
+ sketchWidth = screenRect.width;
493
+ sketchHeight = screenRect.height;
494
+ }
495
+
496
+ // Using a JFrame fixes a Windows problem with Present mode. This might
497
+ // be our error, but usually this is the sort of crap we usually get from
498
+ // OS X. It's time for a turnaround: Redmond is thinking different too!
499
+ // https://github.com/processing/processing/issues/1955
500
+ frame = new JFrame(displayDevice.getDefaultConfiguration());
501
+ // frame = new Frame(displayDevice.getDefaultConfiguration());
502
+ // // Default Processing gray, which will be replaced below if another
503
+ // // color is specified on the command line (i.e. in the prefs).
504
+ // ((JFrame) frame).getContentPane().setBackground(WINDOW_BGCOLOR);
505
+ // // Cannot call setResizable(false) until later due to OS X (issue #467)
506
+
507
+ // // Removed code above, also removed from what's now in the placeXxxx()
508
+ // // methods. Not sure why it was being double-set; hopefully anachronistic.
509
+ // if (backgroundColor == 0) {
510
+ // backgroundColor = WINDOW_BGCOLOR;
511
+ // }
512
+ final Color windowColor = new Color(sketch.sketchWindowColor(), false);
513
+ if (frame instanceof JFrame) {
514
+ ((JFrame) frame).getContentPane().setBackground(windowColor);
515
+ } else {
516
+ frame.setBackground(windowColor);
517
+ }
518
+
519
+ // Put the p5 logo in the Frame's corner to override the Java coffee cup.
520
+ setProcessingIcon(frame);
521
+
522
+ // For 0149, moving this code (up to the pack() method) before init().
523
+ // For OpenGL (and perhaps other renderers in the future), a peer is
524
+ // needed before a GLDrawable can be created. So pack() needs to be
525
+ // called on the Frame before applet.init(), which itself calls size(),
526
+ // and launches the Thread that will kick off setup().
527
+ // http://dev.processing.org/bugs/show_bug.cgi?id=891
528
+ // http://dev.processing.org/bugs/show_bug.cgi?id=908
529
+
530
+ frame.add(canvas);
531
+ setSize(sketchWidth / windowScaleFactor, sketchHeight / windowScaleFactor);
532
+
533
+ /*
534
+ if (fullScreen) {
535
+ // Called here because the graphics device is needed before we can
536
+ // determine whether the sketch wants size(displayWidth, displayHeight),
537
+ // and getting the graphics device will be PSurface-specific.
538
+ PApplet.hideMenuBar();
539
+
540
+ // Tried to use this to fix the 'present' mode issue.
541
+ // Did not help, and the screenRect setup seems to work fine.
542
+ //frame.setExtendedState(Frame.MAXIMIZED_BOTH);
543
+
544
+ // https://github.com/processing/processing/pull/3162
545
+ frame.dispose(); // release native resources, allows setUndecorated()
546
+ frame.setUndecorated(true);
547
+ // another duplicate?
548
+ // if (backgroundColor != null) {
549
+ // frame.getContentPane().setBackground(backgroundColor);
550
+ // }
551
+ // this may be the bounds of all screens
552
+ frame.setBounds(screenRect);
553
+ // will be set visible in placeWindow() [3.0a10]
554
+ //frame.setVisible(true); // re-add native resources
555
+ }
556
+ */
557
+ frame.setLayout(null);
558
+ //frame.add(applet);
559
+
560
+ // Need to pass back our new sketchWidth/Height here, because it may have
561
+ // been overridden by numbers we calculated above if fullScreen and/or
562
+ // spanScreens was in use.
563
+ // pg = sketch.makePrimaryGraphics(sketchWidth, sketchHeight);
564
+ // pg = sketch.makePrimaryGraphics();
565
+
566
+ // resize sketch to sketchWidth/sketchHeight here
567
+
568
+ if (fullScreen) {
569
+ frame.invalidate();
570
+ } else {
571
+ // frame.pack();
572
+ }
573
+
574
+ // insufficient, places the 100x100 sketches offset strangely
575
+ //frame.validate();
576
+
577
+ // disabling resize has to happen after pack() to avoid apparent Apple bug
578
+ // http://code.google.com/p/processing/issues/detail?id=467
579
+ frame.setResizable(false);
580
+
581
+ frame.addWindowListener(new WindowAdapter() {
582
+ @Override
583
+ public void windowClosing(WindowEvent e) {
584
+ sketch.exit(); // don't quit, need to just shut everything down (0133)
585
+ }
586
+ });
587
+
588
+ // sketch.setFrame(frame);
589
+ }
590
+
591
+
592
+ @Override
593
+ public Object getNative() {
594
+ return canvas;
595
+ }
596
+
597
+
598
+ // public Toolkit getToolkit() {
599
+ // return canvas.getToolkit();
600
+ // }
601
+
602
+
603
+ /** Set the window (and dock, or whatever necessary) title.
604
+ * @param title */
605
+ @Override
606
+ public void setTitle(String title) {
607
+ frame.setTitle(title);
608
+ // Workaround for apparent Java bug on OS X?
609
+ // https://github.com/processing/processing/issues/3472
610
+ if (cursorVisible &&
611
+ (PApplet.platform == PConstants.MACOSX) &&
612
+ (cursorType != PConstants.ARROW)) {
613
+ hideCursor();
614
+ showCursor();
615
+ }
616
+ }
617
+
618
+
619
+ /** Set true if we want to resize things (default is not resizable)
620
+ * @param resizable */
621
+ @Override
622
+ public void setResizable(boolean resizable) {
623
+ //this.resizable = resizable; // really only used for canvas
624
+
625
+ if (frame != null) {
626
+ frame.setResizable(resizable);
627
+ }
628
+ }
629
+
630
+ /**
631
+ *
632
+ * @param image
633
+ */
634
+ @Override
635
+ public void setIcon(PImage image) {
636
+ Image awtImage = (Image) image.getNative();
637
+ frame.setIconImage(awtImage);
638
+ // if (PApplet.platform != PConstants.MACOSX) {
639
+ // frame.setIconImage(awtImage);
640
+ //
641
+ // } else {
642
+ // try {
643
+ // final String td = "processing.core.ThinkDifferent";
644
+ // Class<?> thinkDifferent =
645
+ // Thread.currentThread().getContextClassLoader().loadClass(td);
646
+ // Method method =
647
+ // thinkDifferent.getMethod("setIconImage", new Class[] { java.awt.Image.class });
648
+ // method.invoke(null, new Object[] { awtImage });
649
+ // } catch (Exception e) {
650
+ // e.printStackTrace(); // That's unfortunate
651
+ // }
652
+ // }
653
+ }
654
+
655
+
656
+ @Override
657
+ public void setAlwaysOnTop(boolean always) {
658
+ frame.setAlwaysOnTop(always);
659
+ }
660
+
661
+ /**
662
+ *
663
+ * @param x
664
+ * @param y
665
+ */
666
+ @Override
667
+ public void setLocation(int x, int y) {
668
+ frame.setLocation(x, y);
669
+ }
670
+
671
+
672
+ List<Image> iconImages;
673
+
674
+ /**
675
+ *
676
+ * @param frame
677
+ */
678
+ protected void setProcessingIcon(Frame frame) {
679
+ // On OS X, this only affects what shows up in the dock when minimized.
680
+ // So replacing it is actually a step backwards. Brilliant.
681
+ // if (PApplet.platform != PConstants.MACOSX) {
682
+ //Image image = Toolkit.getDefaultToolkit().createImage(ICON_IMAGE);
683
+ //frame.setIconImage(image);
684
+ try {
685
+ if (iconImages == null) {
686
+ iconImages = new ArrayList<Image>();
687
+ final int[] sizes = { 16, 32, 48, 64, 128, 256, 512 };
688
+
689
+ for (int sz : sizes) {
690
+ //URL url = getClass().getResource("/icon/icon-" + sz + ".png");
691
+ URL url = PApplet.class.getResource("/icon/icon-" + sz + ".png");
692
+ Image image = Toolkit.getDefaultToolkit().getImage(url);
693
+ iconImages.add(image);
694
+ //iconImages.add(Toolkit.getLibImage("icons/pde-" + sz + ".png", frame));
695
+ }
696
+ }
697
+ frame.setIconImages(iconImages);
698
+
699
+ } catch (Exception e) { } // harmless; keep this to ourselves
700
+
701
+ // } else { // handle OS X differently
702
+ // if (!dockIconSpecified()) { // don't override existing -Xdock param
703
+ // // On OS X, set this for AWT surfaces, which handles the dock image
704
+ // // as well as the cmd-tab image that's shown. Just one size, I guess.
705
+ // URL url = PApplet.class.getResource("/icon/icon-512.png");
706
+ // // Seems dangerous to have this in code instead of using reflection, no?
707
+ // //ThinkDifferent.setIconImage(Toolkit.getDefaultToolkit().getImage(url));
708
+ // try {
709
+ // final String td = "processing.core.ThinkDifferent";
710
+ // Class<?> thinkDifferent =
711
+ // Thread.currentThread().getContextClassLoader().loadClass(td);
712
+ // Method method =
713
+ // thinkDifferent.getMethod("setIconImage", new Class[] { java.awt.Image.class });
714
+ // method.invoke(null, new Object[] { Toolkit.getDefaultToolkit().getImage(url) });
715
+ // } catch (Exception e) {
716
+ // e.printStackTrace(); // That's unfortunate
717
+ // }
718
+ // }
719
+ // }
720
+ }
721
+
722
+
723
+ /**
724
+ * @return true if -Xdock:icon was specified on the command line
725
+ */
726
+ private boolean dockIconSpecified() {
727
+ // TODO This is incomplete... Haven't yet found a way to figure out if
728
+ // the app has an icns file specified already. Help?
729
+ List<String> jvmArgs =
730
+ ManagementFactory.getRuntimeMXBean().getInputArguments();
731
+ for (String arg : jvmArgs) {
732
+ if (arg.startsWith("-Xdock:icon")) {
733
+ return true; // dock image already set
734
+ }
735
+ }
736
+ return false;
737
+ }
738
+
739
+
740
+ @Override
741
+ public void setVisible(boolean visible) {
742
+ frame.setVisible(visible);
743
+
744
+ // Generally useful whenever setting the frame visible
745
+ if (canvas != null) {
746
+ //canvas.requestFocusInWindow();
747
+ canvas.requestFocus();
748
+ }
749
+
750
+ // removing per https://github.com/processing/processing/pull/3162
751
+ // can remove the code below once 3.0a6 is tested and behaving
752
+ /*
753
+ if (visible && PApplet.platform == PConstants.LINUX) {
754
+ // Linux doesn't deal with insets the same way. We get fake insets
755
+ // earlier, and then the window manager will slap its own insets
756
+ // onto things once the frame is realized on the screen. Awzm.
757
+ if (PApplet.platform == PConstants.LINUX) {
758
+ Insets insets = frame.getInsets();
759
+ frame.setSize(Math.max(sketchWidth, MIN_WINDOW_WIDTH) +
760
+ insets.left + insets.right,
761
+ Math.max(sketchHeight, MIN_WINDOW_HEIGHT) +
762
+ insets.top + insets.bottom);
763
+ }
764
+ }
765
+ */
766
+ }
767
+
768
+
769
+ //public void placeFullScreen(boolean hideStop) {
770
+
771
+ /**
772
+ *
773
+ * @param stopColor
774
+ */
775
+ @Override
776
+ public void placePresent(int stopColor) {
777
+ setFullFrame();
778
+
779
+ // After the pack(), the screen bounds are gonna be 0s
780
+ // frame.setBounds(screenRect); // already called in setFullFrame()
781
+ canvas.setBounds((screenRect.width - sketchWidth) / 2,
782
+ (screenRect.height - sketchHeight) / 2,
783
+ sketchWidth, sketchHeight);
784
+
785
+ // if (PApplet.platform == PConstants.MACOSX) {
786
+ // macosxFullScreenEnable(frame);
787
+ // macosxFullScreenToggle(frame);
788
+ // }
789
+
790
+ if (stopColor != 0) {
791
+ Label label = new Label("stop");
792
+ label.setForeground(new Color(stopColor, false));
793
+ label.addMouseListener(new MouseAdapter() {
794
+ @Override
795
+ public void mousePressed(java.awt.event.MouseEvent e) {
796
+ sketch.exit();
797
+ }
798
+ });
799
+ frame.add(label);
800
+
801
+ Dimension labelSize = label.getPreferredSize();
802
+ // sometimes shows up truncated on mac
803
+ //System.out.println("label width is " + labelSize.width);
804
+ labelSize = new Dimension(100, labelSize.height);
805
+ label.setSize(labelSize);
806
+ label.setLocation(20, screenRect.height - labelSize.height - 20);
807
+ }
808
+
809
+ // if (sketch.getGraphics().displayable()) {
810
+ // setVisible(true);
811
+ // }
812
+ }
813
+
814
+
815
+ /*
816
+ @Override
817
+ public void placeWindow(int[] location) {
818
+ setFrameSize(); //sketchWidth, sketchHeight);
819
+
820
+ if (location != null) {
821
+ // a specific location was received from the Runner
822
+ // (applet has been run more than once, user placed window)
823
+ frame.setLocation(location[0], location[1]);
824
+
825
+ } else { // just center on screen
826
+ // Can't use frame.setLocationRelativeTo(null) because it sends the
827
+ // frame to the main display, which undermines the --display setting.
828
+ frame.setLocation(screenRect.x + (screenRect.width - sketchWidth) / 2,
829
+ screenRect.y + (screenRect.height - sketchHeight) / 2);
830
+ }
831
+ Point frameLoc = frame.getLocation();
832
+ if (frameLoc.y < 0) {
833
+ // Windows actually allows you to place frames where they can't be
834
+ // closed. Awesome. http://dev.processing.org/bugs/show_bug.cgi?id=1508
835
+ frame.setLocation(frameLoc.x, 30);
836
+ }
837
+
838
+ // if (backgroundColor != null) {
839
+ // ((JFrame) frame).getContentPane().setBackground(backgroundColor);
840
+ // }
841
+
842
+ setCanvasSize(); //sketchWidth, sketchHeight);
843
+
844
+ frame.addWindowListener(new WindowAdapter() {
845
+ @Override
846
+ public void windowClosing(WindowEvent e) {
847
+ System.exit(0);
848
+ }
849
+ });
850
+
851
+ // handle frame resizing events
852
+ setupFrameResizeListener();
853
+
854
+ // all set for rockin
855
+ if (sketch.getGraphics().displayable()) {
856
+ frame.setVisible(true);
857
+ }
858
+ }
859
+ */
860
+
861
+
862
+ private void setCanvasSize() {
863
+ // System.out.format("setting canvas size %d %d%n", sketchWidth, sketchHeight);
864
+ // new Exception().printStackTrace(System.out);
865
+ int contentW = Math.max(sketchWidth, MIN_WINDOW_WIDTH);
866
+ int contentH = Math.max(sketchHeight, MIN_WINDOW_HEIGHT);
867
+
868
+ canvas.setBounds((contentW - sketchWidth)/2,
869
+ (contentH - sketchHeight)/2,
870
+ sketchWidth, sketchHeight);
871
+ }
872
+
873
+
874
+ /** Resize frame for these sketch (canvas) dimensions. */
875
+ private Dimension setFrameSize() { //int sketchWidth, int sketchHeight) {
876
+ // https://github.com/processing/processing/pull/3162
877
+ frame.addNotify(); // using instead of show() to add the peer [fry]
878
+
879
+ // System.out.format("setting frame size %d %d %n", sketchWidth, sketchHeight);
880
+ // new Exception().printStackTrace(System.out);
881
+ currentInsets = frame.getInsets();
882
+ int windowW = Math.max(sketchWidth, MIN_WINDOW_WIDTH) +
883
+ currentInsets.left + currentInsets.right;
884
+ int windowH = Math.max(sketchHeight, MIN_WINDOW_HEIGHT) +
885
+ currentInsets.top + currentInsets.bottom;
886
+ frame.setSize(windowW, windowH);
887
+ return new Dimension(windowW, windowH);
888
+ }
889
+
890
+
891
+ private void setFrameCentered() {
892
+ // Can't use frame.setLocationRelativeTo(null) because it sends the
893
+ // frame to the main display, which undermines the --display setting.
894
+ frame.setLocation(screenRect.x + (screenRect.width - sketchWidth) / 2,
895
+ screenRect.y + (screenRect.height - sketchHeight) / 2);
896
+ }
897
+
898
+
899
+ /** Hide the menu bar, make the Frame undecorated, set it to screenRect. */
900
+ private void setFullFrame() {
901
+ // Called here because the graphics device is needed before we can
902
+ // determine whether the sketch wants size(displayWidth, displayHeight),
903
+ // and getting the graphics device will be PSurface-specific.
904
+ PApplet.hideMenuBar();
905
+
906
+ // Tried to use this to fix the 'present' mode issue.
907
+ // Did not help, and the screenRect setup seems to work fine.
908
+ //frame.setExtendedState(Frame.MAXIMIZED_BOTH);
909
+
910
+ // https://github.com/processing/processing/pull/3162
911
+ //frame.dispose(); // release native resources, allows setUndecorated()
912
+ frame.removeNotify();
913
+ frame.setUndecorated(true);
914
+ frame.addNotify();
915
+
916
+ // this may be the bounds of all screens
917
+ frame.setBounds(screenRect);
918
+ // will be set visible in placeWindow() [3.0a10]
919
+ //frame.setVisible(true); // re-add native resources
920
+ }
921
+
922
+ /**
923
+ *
924
+ * @param location
925
+ * @param editorLocation
926
+ */
927
+ @Override
928
+ public void placeWindow(int[] location, int[] editorLocation) {
929
+ //Dimension window = setFrameSize(sketchWidth, sketchHeight);
930
+ Dimension window = setFrameSize(); //sketchWidth, sketchHeight);
931
+
932
+ int contentW = Math.max(sketchWidth, MIN_WINDOW_WIDTH);
933
+ int contentH = Math.max(sketchHeight, MIN_WINDOW_HEIGHT);
934
+
935
+ if (sketch.sketchFullScreen()) {
936
+ setFullFrame();
937
+ }
938
+
939
+ // Ignore placement of previous window and editor when full screen
940
+ if (!sketch.sketchFullScreen()) {
941
+ if (location != null) {
942
+ // a specific location was received from the Runner
943
+ // (applet has been run more than once, user placed window)
944
+ frame.setLocation(location[0], location[1]);
945
+
946
+ } else if (editorLocation != null) {
947
+ int locationX = editorLocation[0] - 20;
948
+ int locationY = editorLocation[1];
949
+
950
+ if (locationX - window.width > 10) {
951
+ // if it fits to the left of the window
952
+ frame.setLocation(locationX - window.width, locationY);
953
+
954
+ } else { // doesn't fit
955
+ // if it fits inside the editor window,
956
+ // offset slightly from upper lefthand corner
957
+ // so that it's plunked inside the text area
958
+ //locationX = editorLocation[0] + 66;
959
+ //locationY = editorLocation[1] + 66;
960
+ locationX = (sketch.displayWidth - window.width) / 2;
961
+ locationY = (sketch.displayHeight - window.height) / 2;
962
+
963
+ /*
964
+ if ((locationX + window.width > sketch.displayWidth - 33) ||
965
+ (locationY + window.height > sketch.displayHeight - 33)) {
966
+ // otherwise center on screen
967
+ locationX = (sketch.displayWidth - window.width) / 2;
968
+ locationY = (sketch.displayHeight - window.height) / 2;
969
+ }
970
+ */
971
+ frame.setLocation(locationX, locationY);
972
+ }
973
+ } else { // just center on screen
974
+ setFrameCentered();
975
+ }
976
+ Point frameLoc = frame.getLocation();
977
+ if (frameLoc.y < 0) {
978
+ // Windows actually allows you to place frames where they can't be
979
+ // closed. Awesome. http://dev.processing.org/bugs/show_bug.cgi?id=1508
980
+ frame.setLocation(frameLoc.x, 30);
981
+ }
982
+ }
983
+
984
+ canvas.setBounds((contentW - sketchWidth)/2,
985
+ (contentH - sketchHeight)/2,
986
+ sketchWidth, sketchHeight);
987
+
988
+ // handle frame resizing events
989
+ setupFrameResizeListener();
990
+
991
+ /*
992
+ // If displayable() is false, then PSurfaceNone should be used, but...
993
+ if (sketch.getGraphics().displayable()) {
994
+ frame.setVisible(true);
995
+ // System.out.println("setting visible on EDT? " + EventQueue.isDispatchThread());
996
+ //requestFocus();
997
+ // if (canvas != null) {
998
+ // //canvas.requestFocusInWindow();
999
+ // canvas.requestFocus();
1000
+ // }
1001
+ }
1002
+ */
1003
+ // if (sketch.getGraphics().displayable()) {
1004
+ // setVisible(true);
1005
+ // }
1006
+ }
1007
+
1008
+
1009
+ // needs to resize the frame, which will resize the canvas, and so on...
1010
+
1011
+ /**
1012
+ *
1013
+ * @param wide
1014
+ * @param high
1015
+ */
1016
+ @Override
1017
+ public void setSize(int wide, int high) {
1018
+ // When the surface is set to resizable via surface.setResizable(true),
1019
+ // a crash may occur if the user sets the window to size zero.
1020
+ // https://github.com/processing/processing/issues/5052
1021
+ if (high <= 0) {
1022
+ high = 1;
1023
+ }
1024
+ if (wide <= 0) {
1025
+ wide = 1;
1026
+ }
1027
+
1028
+ // if (PApplet.DEBUG) {
1029
+ // //System.out.format("frame visible %b, setSize(%d, %d) %n", frame.isVisible(), wide, high);
1030
+ // new Exception(String.format("setSize(%d, %d)", wide, high)).printStackTrace(System.out);
1031
+ // }
1032
+
1033
+ //if (wide == sketchWidth && high == sketchHeight) { // doesn't work on launch
1034
+ if (wide == sketch.width && high == sketch.height &&
1035
+ (frame == null || currentInsets.equals(frame.getInsets()))) {
1036
+ // if (PApplet.DEBUG) {
1037
+ // new Exception("w/h unchanged " + wide + " " + high).printStackTrace(System.out);
1038
+ // }
1039
+ return; // unchanged, don't rebuild everything
1040
+ }
1041
+
1042
+ sketchWidth = wide * windowScaleFactor;
1043
+ sketchHeight = high * windowScaleFactor;
1044
+
1045
+ // canvas.setSize(wide, high);
1046
+ // frame.setSize(wide, high);
1047
+ if (frame != null) { // skip if just a canvas
1048
+ setFrameSize(); //wide, high);
1049
+ }
1050
+ setCanvasSize();
1051
+ // if (frame != null) {
1052
+ // frame.setLocationRelativeTo(null);
1053
+ // }
1054
+
1055
+ //initImage(graphics, wide, high);
1056
+
1057
+ //throw new RuntimeException("implement me, see readme.md");
1058
+ sketch.setSize(wide, high);
1059
+ // sketch.width = wide;
1060
+ // sketch.height = high;
1061
+
1062
+ // set PGraphics variables for width/height/pixelWidth/pixelHeight
1063
+ graphics.setSize(wide, high);
1064
+ // System.out.println("out of setSize()");
1065
+ }
1066
+
1067
+
1068
+ //public void initImage(PGraphics gr, int wide, int high) {
1069
+ /*
1070
+ @Override
1071
+ public void initImage(PGraphics graphics) {
1072
+ GraphicsConfiguration gc = canvas.getGraphicsConfiguration();
1073
+ // If not realized (off-screen, i.e the Color Selector Tool), gc will be null.
1074
+ if (gc == null) {
1075
+ System.err.println("GraphicsConfiguration null in initImage()");
1076
+ GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
1077
+ gc = ge.getDefaultScreenDevice().getDefaultConfiguration();
1078
+ }
1079
+
1080
+ // Formerly this was broken into separate versions based on offscreen or
1081
+ // not, but we may as well create a compatible image; it won't hurt, right?
1082
+ int wide = graphics.width * graphics.pixelFactor;
1083
+ int high = graphics.height * graphics.pixelFactor;
1084
+ graphics.image = gc.createCompatibleImage(wide, high);
1085
+ }
1086
+ */
1087
+
1088
+
1089
+ // @Override
1090
+ // public Component getComponent() {
1091
+ // return canvas;
1092
+ // }
1093
+
1094
+
1095
+ // @Override
1096
+ // public void setSmooth(int level) {
1097
+ // }
1098
+
1099
+
1100
+ /*
1101
+ private boolean checkRetina() {
1102
+ if (PApplet.platform == PConstants.MACOSX) {
1103
+ // This should probably be reset each time there's a display change.
1104
+ // A 5-minute search didn't turn up any such event in the Java 7 API.
1105
+ // Also, should we use the Toolkit associated with the editor window?
1106
+ final String javaVendor = System.getProperty("java.vendor");
1107
+ if (javaVendor.contains("Oracle")) {
1108
+ GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment();
1109
+ GraphicsDevice device = env.getDefaultScreenDevice();
1110
+
1111
+ try {
1112
+ Field field = device.getClass().getDeclaredField("scale");
1113
+ if (field != null) {
1114
+ field.setAccessible(true);
1115
+ Object scale = field.get(device);
1116
+
1117
+ if (scale instanceof Integer && ((Integer)scale).intValue() == 2) {
1118
+ return true;
1119
+ }
1120
+ }
1121
+ } catch (Exception ignore) { }
1122
+ }
1123
+ }
1124
+ return false;
1125
+ }
1126
+ */
1127
+
1128
+
1129
+ /** Get the bounds rectangle for all displays. */
1130
+ static Rectangle getDisplaySpan() {
1131
+ Rectangle bounds = new Rectangle();
1132
+ GraphicsEnvironment environment =
1133
+ GraphicsEnvironment.getLocalGraphicsEnvironment();
1134
+ for (GraphicsDevice device : environment.getScreenDevices()) {
1135
+ for (GraphicsConfiguration config : device.getConfigurations()) {
1136
+ Rectangle2D.union(bounds, config.getBounds(), bounds);
1137
+ }
1138
+ }
1139
+ return bounds;
1140
+ }
1141
+
1142
+
1143
+ /*
1144
+ private void checkDisplaySize() {
1145
+ if (canvas.getGraphicsConfiguration() != null) {
1146
+ GraphicsDevice displayDevice = getGraphicsConfiguration().getDevice();
1147
+
1148
+ if (displayDevice != null) {
1149
+ Rectangle screenRect =
1150
+ displayDevice.getDefaultConfiguration().getBounds();
1151
+
1152
+ displayWidth = screenRect.width;
1153
+ displayHeight = screenRect.height;
1154
+ }
1155
+ }
1156
+ }
1157
+ */
1158
+
1159
+
1160
+ /**
1161
+ * Set this sketch to communicate its state back to the PDE.
1162
+ * <p/>
1163
+ * This uses the stderr stream to write positions of the window
1164
+ * (so that it will be saved by the PDE for the next run) and
1165
+ * notify on quit. See more notes in the Worker class.
1166
+ */
1167
+ @Override
1168
+ public void setupExternalMessages() {
1169
+ frame.addComponentListener(new ComponentAdapter() {
1170
+ @Override
1171
+ public void componentMoved(ComponentEvent e) {
1172
+ Point where = ((Frame) e.getSource()).getLocation();
1173
+ sketch.frameMoved(where.x, where.y);
1174
+ }
1175
+ });
1176
+ }
1177
+
1178
+
1179
+ /**
1180
+ * Set up a listener that will fire proper component resize events
1181
+ * in cases where frame.setResizable(true) is called.
1182
+ */
1183
+ private void setupFrameResizeListener() {
1184
+ frame.addWindowStateListener(new WindowStateListener() {
1185
+ @Override
1186
+ // Detecting when the frame is resized in order to handle the frame
1187
+ // maximization bug in OSX:
1188
+ // http://bugs.java.com/bugdatabase/view_bug.do?bug_id=8036935
1189
+ public void windowStateChanged(WindowEvent e) {
1190
+ // This seems to be firing when dragging the window on OS X
1191
+ // https://github.com/processing/processing/issues/3092
1192
+ if (Frame.MAXIMIZED_BOTH == e.getNewState()) {
1193
+ // Supposedly, sending the frame to back and then front is a
1194
+ // workaround for this bug:
1195
+ // http://stackoverflow.com/a/23897602
1196
+ // but is not working for me...
1197
+ //frame.toBack();
1198
+ //frame.toFront();
1199
+ // Packing the frame works, but that causes the window to collapse
1200
+ // on OS X when the window is dragged. Changing to addNotify() for
1201
+ // https://github.com/processing/processing/issues/3092
1202
+ //frame.pack();
1203
+ frame.addNotify();
1204
+ }
1205
+ }
1206
+ });
1207
+
1208
+ frame.addComponentListener(new ComponentAdapter() {
1209
+ @Override
1210
+ public void componentResized(ComponentEvent e) {
1211
+ // Ignore bad resize events fired during setup to fix
1212
+ // http://dev.processing.org/bugs/show_bug.cgi?id=341
1213
+ // This should also fix the blank screen on Linux bug
1214
+ // http://dev.processing.org/bugs/show_bug.cgi?id=282
1215
+ if (frame.isResizable()) {
1216
+ // might be multiple resize calls before visible (i.e. first
1217
+ // when pack() is called, then when it's resized for use).
1218
+ // ignore them because it's not the user resizing things.
1219
+ Frame farm = (Frame) e.getComponent();
1220
+ if (farm.isVisible()) {
1221
+ Dimension windowSize = farm.getSize();
1222
+ int x = farm.getX() + currentInsets.left;
1223
+ int y = farm.getY() + currentInsets.top;
1224
+
1225
+ // JFrame (unlike java.awt.Frame) doesn't include the left/top
1226
+ // insets for placement (though it does seem to need them for
1227
+ // overall size of the window. Perhaps JFrame sets its coord
1228
+ // system so that (0, 0) is always the upper-left of the content
1229
+ // area. Which seems nice, but breaks any f*ing AWT-based code.
1230
+ int w = windowSize.width - currentInsets.left - currentInsets.right;
1231
+ int h = windowSize.height - currentInsets.top - currentInsets.bottom;
1232
+ setSize(w / windowScaleFactor, h / windowScaleFactor);
1233
+
1234
+ // correct the location when inset size changes
1235
+ setLocation(x - currentInsets.left, y - currentInsets.top);
1236
+ }
1237
+ }
1238
+ }
1239
+ });
1240
+ }
1241
+
1242
+
1243
+ // /**
1244
+ // * (No longer in use) Use reflection to call
1245
+ // * <code>com.apple.eawt.FullScreenUtilities.setWindowCanFullScreen(window, true);</code>
1246
+ // */
1247
+ // static void macosxFullScreenEnable(Window window) {
1248
+ // try {
1249
+ // Class<?> util = Class.forName("com.apple.eawt.FullScreenUtilities");
1250
+ // Class params[] = new Class[] { Window.class, Boolean.TYPE };
1251
+ // Method method = util.getMethod("setWindowCanFullScreen", params);
1252
+ // method.invoke(util, window, true);
1253
+ //
1254
+ // } catch (ClassNotFoundException cnfe) {
1255
+ // // ignored
1256
+ // } catch (Exception e) {
1257
+ // e.printStackTrace();
1258
+ // }
1259
+ // }
1260
+ //
1261
+ //
1262
+ // /**
1263
+ // * (No longer in use) Use reflection to call
1264
+ // * <code>com.apple.eawt.Application.getApplication().requestToggleFullScreen(window);</code>
1265
+ // */
1266
+ // static void macosxFullScreenToggle(Window window) {
1267
+ // try {
1268
+ // Class<?> appClass = Class.forName("com.apple.eawt.Application");
1269
+ //
1270
+ // Method getAppMethod = appClass.getMethod("getApplication");
1271
+ // Object app = getAppMethod.invoke(null, new Object[0]);
1272
+ //
1273
+ // Method requestMethod =
1274
+ // appClass.getMethod("requestToggleFullScreen", Window.class);
1275
+ // requestMethod.invoke(app, window);
1276
+ //
1277
+ // } catch (ClassNotFoundException cnfe) {
1278
+ // // ignored
1279
+ // } catch (Exception e) {
1280
+ // e.printStackTrace();
1281
+ // }
1282
+ // }
1283
+
1284
+
1285
+ //////////////////////////////////////////////////////////////
1286
+
1287
+
1288
+ /*
1289
+ // disabling for now; requires Java 1.7 and "precise" semantics are odd...
1290
+ // returns 0.1 for tick-by-tick scrolling on OS X, but it's not a matter of
1291
+ // calling ceil() on the value: 1.5 goes to 1, but 2.3 goes to 2.
1292
+ // "precise" is a whole different animal, so add later API to shore that up.
1293
+ static protected Method preciseWheelMethod;
1294
+ static {
1295
+ try {
1296
+ preciseWheelMethod = MouseWheelEvent.class.getMethod("getPreciseWheelRotation", new Class[] { });
1297
+ } catch (Exception e) {
1298
+ // ignored, the method will just be set to null
1299
+ }
1300
+ }
1301
+ */
1302
+
1303
+
1304
+ /**
1305
+ * Figure out how to process a mouse event. When loop() has been
1306
+ * called, the events will be queued up until drawing is complete.
1307
+ * If noLoop() has been called, then events will happen immediately.
1308
+ * @param nativeEvent
1309
+ */
1310
+ protected void nativeMouseEvent(java.awt.event.MouseEvent nativeEvent) {
1311
+ // the 'amount' is the number of button clicks for a click event,
1312
+ // or the number of steps/clicks on the wheel for a mouse wheel event.
1313
+ int peCount = nativeEvent.getClickCount();
1314
+
1315
+ int peAction = 0;
1316
+ switch (nativeEvent.getID()) {
1317
+ case java.awt.event.MouseEvent.MOUSE_PRESSED:
1318
+ peAction = MouseEvent.PRESS;
1319
+ break;
1320
+ case java.awt.event.MouseEvent.MOUSE_RELEASED:
1321
+ peAction = MouseEvent.RELEASE;
1322
+ break;
1323
+ case java.awt.event.MouseEvent.MOUSE_CLICKED:
1324
+ peAction = MouseEvent.CLICK;
1325
+ break;
1326
+ case java.awt.event.MouseEvent.MOUSE_DRAGGED:
1327
+ peAction = MouseEvent.DRAG;
1328
+ break;
1329
+ case java.awt.event.MouseEvent.MOUSE_MOVED:
1330
+ peAction = MouseEvent.MOVE;
1331
+ break;
1332
+ case java.awt.event.MouseEvent.MOUSE_ENTERED:
1333
+ peAction = MouseEvent.ENTER;
1334
+ break;
1335
+ case java.awt.event.MouseEvent.MOUSE_EXITED:
1336
+ peAction = MouseEvent.EXIT;
1337
+ break;
1338
+ //case java.awt.event.MouseWheelEvent.WHEEL_UNIT_SCROLL:
1339
+ case java.awt.event.MouseEvent.MOUSE_WHEEL:
1340
+ peAction = MouseEvent.WHEEL;
1341
+ /*
1342
+ if (preciseWheelMethod != null) {
1343
+ try {
1344
+ peAmount = ((Double) preciseWheelMethod.invoke(nativeEvent, (Object[]) null)).floatValue();
1345
+ } catch (Exception e) {
1346
+ preciseWheelMethod = null;
1347
+ }
1348
+ }
1349
+ */
1350
+ peCount = ((MouseWheelEvent) nativeEvent).getWheelRotation();
1351
+ break;
1352
+ }
1353
+
1354
+ //System.out.println(nativeEvent);
1355
+ //int modifiers = nativeEvent.getModifiersEx();
1356
+ // If using getModifiersEx(), the regular modifiers don't set properly.
1357
+ int modifiers = nativeEvent.getModifiers();
1358
+
1359
+ int peModifiers = modifiers &
1360
+ (InputEvent.SHIFT_MASK |
1361
+ InputEvent.CTRL_MASK |
1362
+ InputEvent.META_MASK |
1363
+ InputEvent.ALT_MASK);
1364
+
1365
+ // Windows and OS X seem to disagree on how to handle this. Windows only
1366
+ // sets BUTTON1_DOWN_MASK, while OS X seems to set BUTTON1_MASK.
1367
+ // This is an issue in particular with mouse release events:
1368
+ // http://code.google.com/p/processing/issues/detail?id=1294
1369
+ // The fix for which led to a regression (fixed here by checking both):
1370
+ // http://code.google.com/p/processing/issues/detail?id=1332
1371
+ int peButton = 0;
1372
+ // if ((modifiers & InputEvent.BUTTON1_MASK) != 0 ||
1373
+ // (modifiers & InputEvent.BUTTON1_DOWN_MASK) != 0) {
1374
+ // peButton = LEFT;
1375
+ // } else if ((modifiers & InputEvent.BUTTON2_MASK) != 0 ||
1376
+ // (modifiers & InputEvent.BUTTON2_DOWN_MASK) != 0) {
1377
+ // peButton = CENTER;
1378
+ // } else if ((modifiers & InputEvent.BUTTON3_MASK) != 0 ||
1379
+ // (modifiers & InputEvent.BUTTON3_DOWN_MASK) != 0) {
1380
+ // peButton = RIGHT;
1381
+ // }
1382
+ if ((modifiers & InputEvent.BUTTON1_MASK) != 0) {
1383
+ peButton = PConstants.LEFT;
1384
+ } else if ((modifiers & InputEvent.BUTTON2_MASK) != 0) {
1385
+ peButton = PConstants.CENTER;
1386
+ } else if ((modifiers & InputEvent.BUTTON3_MASK) != 0) {
1387
+ peButton = PConstants.RIGHT;
1388
+ }
1389
+
1390
+ // If running on Mac OS, allow ctrl-click as right mouse. Prior to 0215,
1391
+ // this used isPopupTrigger() on the native event, but that doesn't work
1392
+ // for mouseClicked and mouseReleased (or others).
1393
+ if (PApplet.platform == PConstants.MACOSX) {
1394
+ //if (nativeEvent.isPopupTrigger()) {
1395
+ if ((modifiers & InputEvent.CTRL_MASK) != 0) {
1396
+ peButton = PConstants.RIGHT;
1397
+ }
1398
+ }
1399
+
1400
+ sketch.postEvent(new MouseEvent(nativeEvent, nativeEvent.getWhen(),
1401
+ peAction, peModifiers,
1402
+ nativeEvent.getX() / windowScaleFactor,
1403
+ nativeEvent.getY() / windowScaleFactor,
1404
+ peButton,
1405
+ peCount));
1406
+ }
1407
+
1408
+ /**
1409
+ *
1410
+ * @param event
1411
+ */
1412
+ protected void nativeKeyEvent(java.awt.event.KeyEvent event) {
1413
+ int peAction = 0;
1414
+ switch (event.getID()) {
1415
+ case java.awt.event.KeyEvent.KEY_PRESSED:
1416
+ peAction = KeyEvent.PRESS;
1417
+ break;
1418
+ case java.awt.event.KeyEvent.KEY_RELEASED:
1419
+ peAction = KeyEvent.RELEASE;
1420
+ break;
1421
+ case java.awt.event.KeyEvent.KEY_TYPED:
1422
+ peAction = KeyEvent.TYPE;
1423
+ break;
1424
+ }
1425
+
1426
+ // int peModifiers = event.getModifiersEx() &
1427
+ // (InputEvent.SHIFT_DOWN_MASK |
1428
+ // InputEvent.CTRL_DOWN_MASK |
1429
+ // InputEvent.META_DOWN_MASK |
1430
+ // InputEvent.ALT_DOWN_MASK);
1431
+ int peModifiers = event.getModifiers() &
1432
+ (InputEvent.SHIFT_MASK |
1433
+ InputEvent.CTRL_MASK |
1434
+ InputEvent.META_MASK |
1435
+ InputEvent.ALT_MASK);
1436
+
1437
+ sketch.postEvent(new KeyEvent(event, event.getWhen(),
1438
+ peAction, peModifiers,
1439
+ event.getKeyChar(), event.getKeyCode()));
1440
+ }
1441
+
1442
+
1443
+ // listeners, for all my men!
1444
+
1445
+ /**
1446
+ *
1447
+ */
1448
+ protected void addListeners() {
1449
+
1450
+ canvas.addMouseListener(new MouseListener() {
1451
+
1452
+ public void mousePressed(java.awt.event.MouseEvent e) {
1453
+ nativeMouseEvent(e);
1454
+ }
1455
+
1456
+ public void mouseReleased(java.awt.event.MouseEvent e) {
1457
+ nativeMouseEvent(e);
1458
+ }
1459
+
1460
+ public void mouseClicked(java.awt.event.MouseEvent e) {
1461
+ nativeMouseEvent(e);
1462
+ }
1463
+
1464
+ public void mouseEntered(java.awt.event.MouseEvent e) {
1465
+ nativeMouseEvent(e);
1466
+ }
1467
+
1468
+ public void mouseExited(java.awt.event.MouseEvent e) {
1469
+ nativeMouseEvent(e);
1470
+ }
1471
+ });
1472
+
1473
+ canvas.addMouseMotionListener(new MouseMotionListener() {
1474
+
1475
+ public void mouseDragged(java.awt.event.MouseEvent e) {
1476
+ nativeMouseEvent(e);
1477
+ }
1478
+
1479
+ public void mouseMoved(java.awt.event.MouseEvent e) {
1480
+ nativeMouseEvent(e);
1481
+ }
1482
+ });
1483
+
1484
+ canvas.addMouseWheelListener(new MouseWheelListener() {
1485
+
1486
+ public void mouseWheelMoved(MouseWheelEvent e) {
1487
+ nativeMouseEvent(e);
1488
+ }
1489
+ });
1490
+
1491
+ canvas.addKeyListener(new KeyListener() {
1492
+
1493
+ public void keyPressed(java.awt.event.KeyEvent e) {
1494
+ nativeKeyEvent(e);
1495
+ }
1496
+
1497
+
1498
+ public void keyReleased(java.awt.event.KeyEvent e) {
1499
+ nativeKeyEvent(e);
1500
+ }
1501
+
1502
+
1503
+ public void keyTyped(java.awt.event.KeyEvent e) {
1504
+ nativeKeyEvent(e);
1505
+ }
1506
+ });
1507
+
1508
+ canvas.addFocusListener(new FocusListener() {
1509
+
1510
+ public void focusGained(FocusEvent e) {
1511
+ sketch.focused = true;
1512
+ sketch.focusGained();
1513
+ }
1514
+
1515
+ public void focusLost(FocusEvent e) {
1516
+ sketch.focused = false;
1517
+ sketch.focusLost();
1518
+ }
1519
+ });
1520
+ }
1521
+
1522
+
1523
+ /*
1524
+ public void addListeners(Component comp) {
1525
+ comp.addMouseListener(this);
1526
+ comp.addMouseWheelListener(this);
1527
+ comp.addMouseMotionListener(this);
1528
+ comp.addKeyListener(this);
1529
+ comp.addFocusListener(this);
1530
+ }
1531
+
1532
+
1533
+ public void removeListeners(Component comp) {
1534
+ comp.removeMouseListener(this);
1535
+ comp.removeMouseWheelListener(this);
1536
+ comp.removeMouseMotionListener(this);
1537
+ comp.removeKeyListener(this);
1538
+ comp.removeFocusListener(this);
1539
+ }
1540
+ */
1541
+
1542
+
1543
+ // /**
1544
+ // * Call to remove, then add, listeners to a component.
1545
+ // * Avoids issues with double-adding.
1546
+ // */
1547
+ // public void updateListeners(Component comp) {
1548
+ // removeListeners(comp);
1549
+ // addListeners(comp);
1550
+ // }
1551
+
1552
+
1553
+
1554
+ // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1555
+
1556
+
1557
+ int cursorType = PConstants.ARROW;
1558
+ boolean cursorVisible = true;
1559
+ Cursor invisibleCursor;
1560
+
1561
+ /**
1562
+ *
1563
+ * @param kind
1564
+ */
1565
+ @Override
1566
+ public void setCursor(int kind) {
1567
+ // Swap the HAND cursor because MOVE doesn't seem to be available on OS X
1568
+ // https://github.com/processing/processing/issues/2358
1569
+ if (PApplet.platform == PConstants.MACOSX && kind == PConstants.MOVE) {
1570
+ kind = PConstants.HAND;
1571
+ }
1572
+ canvas.setCursor(Cursor.getPredefinedCursor(kind));
1573
+ cursorVisible = true;
1574
+ this.cursorType = kind;
1575
+ }
1576
+
1577
+ /**
1578
+ *
1579
+ * @param img
1580
+ * @param x
1581
+ * @param y
1582
+ */
1583
+ @Override
1584
+ public void setCursor(PImage img, int x, int y) {
1585
+ // Don't set cursorType, instead use cursorType to save the last
1586
+ // regular cursor type used for when cursor() is called.
1587
+ //cursor_type = Cursor.CUSTOM_CURSOR;
1588
+
1589
+ // this is a temporary workaround for the CHIP, will be removed
1590
+ Dimension cursorSize = Toolkit.getDefaultToolkit().getBestCursorSize(img.width, img.height);
1591
+ if (cursorSize.width == 0 || cursorSize.height == 0) {
1592
+ return;
1593
+ }
1594
+
1595
+ Cursor cursor =
1596
+ canvas.getToolkit().createCustomCursor((Image) img.getNative(),
1597
+ new Point(x, y),
1598
+ "custom");
1599
+ canvas.setCursor(cursor);
1600
+ cursorVisible = true;
1601
+ }
1602
+
1603
+ /**
1604
+ *
1605
+ */
1606
+ @Override
1607
+ public void showCursor() {
1608
+ // Maybe should always set here? Seems dangerous, since it's likely that
1609
+ // Java will set the cursor to something else on its own, and the sketch
1610
+ // will be stuck b/c p5 thinks the cursor is set to one particular thing.
1611
+ if (!cursorVisible) {
1612
+ cursorVisible = true;
1613
+ canvas.setCursor(Cursor.getPredefinedCursor(cursorType));
1614
+ }
1615
+ }
1616
+
1617
+ /**
1618
+ *
1619
+ */
1620
+ @Override
1621
+ public void hideCursor() {
1622
+ // Because the OS may have shown the cursor on its own,
1623
+ // don't return if 'cursorVisible' is set to true. [rev 0216]
1624
+
1625
+ if (invisibleCursor == null) {
1626
+ BufferedImage cursorImg =
1627
+ new BufferedImage(16, 16, BufferedImage.TYPE_INT_ARGB);
1628
+ // this is a temporary workaround for the CHIP, will be removed
1629
+ Dimension cursorSize = Toolkit.getDefaultToolkit().getBestCursorSize(16, 16);
1630
+ if (cursorSize.width == 0 || cursorSize.height == 0) {
1631
+ invisibleCursor = Cursor.getDefaultCursor();
1632
+ } else {
1633
+ invisibleCursor =
1634
+ canvas.getToolkit().createCustomCursor(cursorImg, new Point(8, 8), "blank");
1635
+ }
1636
+ }
1637
+ canvas.setCursor(invisibleCursor);
1638
+ cursorVisible = false;
1639
+ }
1640
+
1641
+ /**
1642
+ *
1643
+ * @return
1644
+ */
1645
+ @Override
1646
+ public Thread createThread() {
1647
+ return new AnimationThread() {
1648
+ @Override
1649
+ public void callDraw() {
1650
+ sketch.handleDraw();
1651
+ render();
1652
+ }
1653
+ };
1654
+ }
1655
+
1656
+
1657
+ void debug(String format, Object ... args) {
1658
+ System.out.format(format + "%n", args);
1659
+ }
1660
+ }