picrate 0.0.2-java

Sign up to get free protection for your applications and to get access to all the features.
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
+ }