11package rprocessing ;
22
3+ import java .awt .Component ;
4+ import java .awt .Window ;
5+ import java .awt .event .ComponentAdapter ;
6+ import java .awt .event .ComponentEvent ;
7+ import java .lang .reflect .Method ;
8+ import java .util .Arrays ;
9+ import java .util .concurrent .CountDownLatch ;
10+
311import javax .script .ScriptEngine ;
412import javax .script .ScriptEngineManager ;
513import javax .script .ScriptException ;
1220import org .renjin .sexp .SEXP ;
1321import org .renjin .sexp .Symbol ;
1422
23+ import processing .awt .PSurfaceAWT ;
24+ import processing .core .PApplet ;
25+ import processing .core .PConstants ;
26+ import processing .core .PSurface ;
27+ import processing .javafx .PSurfaceFX ;
28+ import processing .opengl .PSurfaceJOGL ;
1529import rprocessing .applet .BuiltinApplet ;
1630import rprocessing .exception .NotFoundException ;
1731import rprocessing .util .Constant ;
1832import rprocessing .util .Printer ;
1933
34+ import com .jogamp .newt .opengl .GLWindow ;
35+
2036/**
2137 * RlangPApplet
2238 * PApplet for R language, powered by Renjin.
2541 */
2642public class RLangPApplet extends BuiltinApplet {
2743
28- private static final boolean VERBOSE = Boolean
29- . parseBoolean ( System .getenv ("VERBOSE_RLANG_MODE" ));
44+ private static final boolean VERBOSE = Boolean . parseBoolean ( System
45+ .getenv ("VERBOSE_RLANG_MODE" ));
3046
3147 // A static-mode sketch must be interpreted from within the setup() method.
3248 // All others are interpreted during construction in order to harvest method
@@ -41,13 +57,15 @@ public class RLangPApplet extends BuiltinApplet {
4157
4258 private final Printer stdout ;
4359
60+ private final CountDownLatch finishedLatch = new CountDownLatch (1 );
61+
4462 /**
4563 * Mode for Processing.
4664 *
4765 * @author github.com/gaocegege
4866 */
4967 private enum Mode {
50- STATIC , ACTIVE , MIXED
68+ STATIC , ACTIVE , MIXED
5169 }
5270
5371 private static void log (String msg ) {
@@ -89,8 +107,8 @@ public void prePassCode() {
89107 */
90108 if (isSameClass (ev .get (i ), FunctionCall .class )
91109 && isSameClass (((FunctionCall ) ev .get (i )).getFunction (), Symbol .class )
92- && ((Symbol ) ((FunctionCall ) ev .get (i )).getFunction ()).getPrintName ()
93- . equals ( "<-" )) {
110+ && ((Symbol ) ((FunctionCall ) ev .get (i )).getFunction ()).getPrintName (). equals (
111+ "<-" )) {
94112 this .renjinEngine .getTopLevelContext ().evaluate (ev .get (i ),
95113 this .renjinEngine .getTopLevelContext ().getEnvironment ());
96114 }
@@ -123,6 +141,105 @@ public void addPAppletToRContext() {
123141 this .renjinEngine .put ("stdout" , stdout );
124142 }
125143
144+ public void runBlock (final String [] arguments ) {
145+ log ("runBlock" );
146+ PApplet .runSketch (arguments , this );
147+ try {
148+ finishedLatch .await ();
149+ log ("Down" );
150+ } catch (final InterruptedException interrupted ) {
151+ // Treat an interruption as a request to the applet to terminate.
152+ exit ();
153+ try {
154+ finishedLatch .await ();
155+ log ("Down" );
156+ } catch (final InterruptedException e ) {
157+ log (e .toString ());
158+ }
159+ } finally {
160+ Thread .setDefaultUncaughtExceptionHandler (null );
161+ if (PApplet .platform == PConstants .MACOSX
162+ && Arrays .asList (arguments ).contains ("fullScreen" )) {
163+ // Frame should be OS-X fullscreen, and it won't stop being that unless the jvm
164+ // exits or we explicitly tell it to minimize.
165+ // (If it's disposed, it'll leave a gray blank window behind it.)
166+ log ("Disabling fullscreen." );
167+ macosxFullScreenToggle (frame );
168+ }
169+ if (surface instanceof PSurfaceFX ) {
170+ // Sadly, JavaFX is an abomination, and there's no way to run an FX sketch more than once,
171+ // so we must actually exit.
172+ log ("JavaFX requires SketchRunner to terminate. Farewell!" );
173+ System .exit (0 );
174+ }
175+ final Object nativeWindow = surface .getNative ();
176+ if (nativeWindow instanceof com .jogamp .newt .Window ) {
177+ ((com .jogamp .newt .Window ) nativeWindow ).destroy ();
178+ } else {
179+ surface .setVisible (false );
180+ }
181+ }
182+ // if (terminalException != null) {
183+ // throw terminalException;
184+ // }
185+ }
186+
187+ static private void macosxFullScreenToggle (final Window window ) {
188+ try {
189+ final Class <?> appClass = Class .forName ("com.apple.eawt.Application" );
190+ final Method getAppMethod = appClass .getMethod ("getApplication" );
191+ final Object app = getAppMethod .invoke (null );
192+ final Method requestMethod = appClass
193+ .getMethod ("requestToggleFullScreen" , Window .class );
194+ requestMethod .invoke (app , window );
195+ } catch (final ClassNotFoundException cnfe ) {
196+ // ignored
197+ } catch (final Exception e ) {
198+ e .printStackTrace ();
199+ }
200+ }
201+
202+ /**
203+ *
204+ * @see processing.core.PApplet#initSurface()
205+ */
206+ @ Override
207+ protected PSurface initSurface () {
208+ final PSurface s = super .initSurface ();
209+ this .frame = null ; // eliminate a memory leak from 2.x compat hack
210+ // s.setTitle(pySketchPath.getFileName().toString().replaceAll("\\..*$", ""));
211+ if (s instanceof PSurfaceAWT ) {
212+ final PSurfaceAWT surf = (PSurfaceAWT ) s ;
213+ final Component c = (Component ) surf .getNative ();
214+ c .addComponentListener (new ComponentAdapter () {
215+ @ Override
216+ public void componentHidden (final ComponentEvent e ) {
217+ log ("initSurface" );
218+ finishedLatch .countDown ();
219+ }
220+ });
221+ } else if (s instanceof PSurfaceJOGL ) {
222+ final PSurfaceJOGL surf = (PSurfaceJOGL ) s ;
223+ final GLWindow win = (GLWindow ) surf .getNative ();
224+ win .addWindowListener (new com .jogamp .newt .event .WindowAdapter () {
225+ @ Override
226+ public void windowDestroyed (final com .jogamp .newt .event .WindowEvent arg0 ) {
227+ log ("initSurface" );
228+ finishedLatch .countDown ();
229+ }
230+ });
231+ } else if (s instanceof PSurfaceFX ) {
232+ System .err .println ("I don't know how to watch FX2D windows for close." );
233+ }
234+ return s ;
235+ }
236+
237+ @ Override
238+ public void exitActual () {
239+ log ("exitActual" );
240+ finishedLatch .countDown ();
241+ }
242+
126243 /**
127244 * @see processing.core.PApplet#settings()
128245 */
0 commit comments