Skip to content

Commit 1c6553e

Browse files
committed
*: block start button
Signed-off-by: Ce Gao <[email protected]>
1 parent 1680f33 commit 1c6553e

File tree

6 files changed

+154
-34
lines changed

6 files changed

+154
-34
lines changed

raw-docs/howto.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ Configure `./scripts/generate-ant-file.sh`:
2929
- `modes`: the destination for installing the mode once it is built.
3030
- MacOSX: `/Users/[MyUserName]/Documents/Processing/modes/`
3131
- Windows: `%homepath%\Documents\modes\`
32-
- Linux: `~/sketchbook/modes/`
32+
- Linux: `${HOME}/sketchbook/modes/`
3333
- `core` and `pde`: paths to pde.jar and core.jar. They are be used to build RLangMode.
3434
- MacOSX: `/Applications/Processing.app/Contents/Java/core.jar` and `/Applications/Processing.app/Contents/Java/pde.jar`
3535
- Linux: `[MyPDE]/core/library/core.jar` and `[MyPDE]/lib/pde.jar`
@@ -65,7 +65,7 @@ $ ant build
6565
Then set the two paths accordingly in `./scripts/generate-ant-file.sh`:
6666

6767
```
68-
modes="~/Documents/Processing/modes"
68+
modes="${HOME}/Documents/Processing/modes"
6969
core="../processing/core/library/"
7070
pde="../processing/app/"
7171
executable="/Applications/Processing.app/Contents/MacOS/Processing"

scripts/generate-ant-file.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
source "$(dirname "${BASH_SOURCE}")/utils/generator-util.sh"
44

55
# Path to be changed
6-
modes="~/Documents/Processing/modes"
6+
modes="${HOME}/Documents/Processing/modes"
77
executable="/Applications/Processing.app/Contents/MacOS/Processing"
88
core="/Applications/Processing.app/Contents/Java/core.jar"
99
pde="/Applications/Processing.app/Contents/Java/pde.jar"

src/rprocessing/RLangPApplet.java

+122-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
package 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+
311
import javax.script.ScriptEngine;
412
import javax.script.ScriptEngineManager;
513
import javax.script.ScriptException;
@@ -12,11 +20,19 @@
1220
import org.renjin.sexp.SEXP;
1321
import 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;
1529
import rprocessing.applet.BuiltinApplet;
1630
import rprocessing.exception.NotFoundException;
1731
import rprocessing.util.Constant;
1832
import rprocessing.util.Printer;
1933

34+
import com.jogamp.newt.opengl.GLWindow;
35+
2036
/**
2137
* RlangPApplet
2238
* PApplet for R language, powered by Renjin.
@@ -25,8 +41,8 @@
2541
*/
2642
public 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
*/

src/rprocessing/Runner.java

+12-11
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
import org.renjin.eval.EvalException;
44
import org.renjin.parser.ParseException;
55

6-
import processing.core.PApplet;
76
import rprocessing.exception.NotFoundException;
87
import rprocessing.exception.REvalException;
98
import rprocessing.lancher.StandaloneSketch;
@@ -21,10 +20,10 @@ public class Runner {
2120

2221
@SuppressWarnings("unused")
2322
private static final String CORE_TEXT = RScriptReader.readResourceAsText(Runner.class,
24-
"r/core.R");
23+
"r/core.R");
2524

26-
private static final boolean VERBOSE = Boolean
27-
.parseBoolean(System.getenv("VERBOSE_RLANG_MODE"));
25+
private static final boolean VERBOSE = Boolean.parseBoolean(System
26+
.getenv("VERBOSE_RLANG_MODE"));
2827

2928
private static void log(final Object... objs) {
3029
if (!VERBOSE) {
@@ -50,16 +49,18 @@ public static void main(final String[] args) throws Exception {
5049
}
5150

5251
public synchronized static void runSketchBlocking(final RunnableSketch sketch,
53-
final Printer stdout,
54-
final Printer stderr) throws REvalException,
55-
NotFoundException {
52+
final Printer stdout, final Printer stderr)
53+
throws REvalException,
54+
NotFoundException {
5655
runSketchBlocking(sketch, stdout, stderr, null);
5756
}
5857

5958
public synchronized static void runSketchBlocking(final RunnableSketch sketch,
60-
final Printer stdout, final Printer stderr,
61-
final SketchPositionListener sketchPositionListener) throws REvalException,
62-
NotFoundException {
59+
final Printer stdout,
60+
final Printer stderr,
61+
final SketchPositionListener sketchPositionListener)
62+
throws REvalException,
63+
NotFoundException {
6364
final String[] args = sketch.getPAppletArguments();
6465

6566
log("Tring to initialize RLangPApplet.");
@@ -69,7 +70,7 @@ public synchronized static void runSketchBlocking(final RunnableSketch sketch,
6970

7071
try {
7172
// Run Sketch.
72-
PApplet.runSketch(args, rp);
73+
rp.runBlock(args);
7374
} catch (ParseException pe) {
7475
throw new REvalException(pe.getMessage());
7576
} catch (EvalException ee) {

src/rprocessing/mode/RLangEditor.java

+10-8
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,8 @@
4646
*/
4747
public class RLangEditor extends Editor {
4848

49-
private static final boolean VERBOSE = Boolean
50-
.parseBoolean(System.getenv("VERBOSE_RLANG_MODE"));
49+
private static final boolean VERBOSE = Boolean.parseBoolean(System
50+
.getenv("VERBOSE_RLANG_MODE"));
5151

5252
/** */
5353
private static final long serialVersionUID = -5993950683909551427L;
@@ -82,8 +82,8 @@ public String getId() {
8282
* @param mode
8383
* @throws EditorException
8484
*/
85-
protected RLangEditor(Base base, String path, EditorState state,
86-
Mode mode) throws EditorException {
85+
protected RLangEditor(Base base, String path, EditorState state, Mode mode)
86+
throws EditorException {
8787
super(base, path, state, mode);
8888
log("Initialize RLangEditor now.");
8989

@@ -205,6 +205,7 @@ public EditorToolbar createToolbar() {
205205
*/
206206
@Override
207207
public void deactivateRun() {
208+
log("deactivateRun");
208209
restoreToolbar();
209210
cleanupTempSketch();
210211
}
@@ -272,6 +273,7 @@ public void handlePresent() {
272273
}
273274

274275
public void handleStop() {
276+
log("handleStop");
275277
toolbar.activateStop();
276278
internalCloseRunner();
277279
restoreToolbar();
@@ -299,8 +301,8 @@ private void runSketch(final DisplayType displayType) {
299301
tempSketch = createTempSketch();
300302
sketchPath = tempSketch.resolve(sketchMainFileName).toFile();
301303
} catch (final IOException e) {
302-
Messages.showError("Sketchy Behavior",
303-
"I can't copy your unsaved work\n" + "to a temp directory.", e);
304+
Messages.showError("Sketchy Behavior", "I can't copy your unsaved work\n"
305+
+ "to a temp directory.", e);
304306
return;
305307
}
306308
} else {
@@ -318,8 +320,8 @@ private void runSketch(final DisplayType displayType) {
318320
}
319321

320322
try {
321-
sketchService
322-
.runSketch(new PdeSketch(sketch, sketchPath, displayType, location, locationType));
323+
sketchService.runSketch(new PdeSketch(sketch, sketchPath, displayType, location,
324+
locationType));
323325
} catch (final SketchException e) {
324326
statusError(e);
325327
}

src/rprocessing/mode/RLangMode.java

+7-7
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,16 @@
1818
*/
1919
public class RLangMode extends Mode {
2020

21-
private static final boolean VERBOSE = Boolean
22-
.parseBoolean(System.getenv("VERBOSE_RLANG_MODE"));
21+
private static final boolean VERBOSE = Boolean.parseBoolean(System
22+
.getenv("VERBOSE_RLANG_MODE"));
2323

2424
/**
2525
* If the environment variable SKETCH_RUNNER_FIRST is equal to the string "true", then
2626
* {@link RLangMode} expects that the {@link SketchRunner} is already running and waiting
2727
* to be communicated with (as when you're debugging it in Eclipse, for example).
2828
*/
29-
public static final boolean SKETCH_RUNNER_FIRST = Boolean
30-
.parseBoolean(System.getenv("SKETCH_RUNNER_FIRST"));
29+
public static final boolean SKETCH_RUNNER_FIRST = Boolean.parseBoolean(System
30+
.getenv("SKETCH_RUNNER_FIRST"));
3131

3232
private final SketchServiceManager sketchServiceManager;
3333

@@ -40,7 +40,7 @@ private static void log(final String msg) {
4040

4141
public RLangMode(final Base base, final File folder) {
4242
super(base, folder);
43-
43+
log("DEBUG the RLangMode");
4444
sketchServiceManager = new SketchServiceManager(this);
4545
}
4646

@@ -52,8 +52,8 @@ public SketchServiceManager getSketchServiceManager() {
5252
* @see processing.app.Mode#createEditor(processing.app.Base, java.lang.String, processing.app.ui.EditorState)
5353
*/
5454
@Override
55-
public Editor createEditor(Base base, final String path,
56-
final EditorState state) throws EditorException {
55+
public Editor createEditor(Base base, final String path, final EditorState state)
56+
throws EditorException {
5757
// Lazily start the sketch running service only when an editor is required.
5858
if (!sketchServiceManager.isStarted()) {
5959
sketchServiceManager.start();

0 commit comments

Comments
 (0)