From db61051a3065e84b3bf0154e27c86c78843f6d51 Mon Sep 17 00:00:00 2001 From: Jonathan Feinberg Date: Sat, 22 Jan 2022 10:21:36 -0500 Subject: [PATCH 01/21] Fix runner for newer Javas which require permission to introspect. --- .classpath | 8 +- .project | 11 +++ Base - Launch Mode in Eclipse.launch | 50 ++++++------ Base - Sketch Runner First.launch | 56 +++++++------- HOWTO-HACK.txt | 4 +- README.markdown | 16 ++-- SketchRunner.launch | 39 ++++++---- build.xml | 8 +- mode/mode.properties | 6 +- processing-py-test-suite.launch | 76 +++++++++---------- .../src/jycessing/PAppletJythonDriver.java | 2 +- runtime/src/jycessing/build.properties | 2 +- runtime/src/jycessing/jni/OSX.java | 8 +- .../mode/run/SketchServiceProcess.java | 33 ++++++++ testmode.sh | 2 +- 15 files changed, 186 insertions(+), 135 deletions(-) diff --git a/.classpath b/.classpath index 61c34d64..846c5e76 100644 --- a/.classpath +++ b/.classpath @@ -5,8 +5,12 @@ - - + + + + + + diff --git a/.project b/.project index 2ff7c3d9..79e62f8b 100644 --- a/.project +++ b/.project @@ -20,4 +20,15 @@ org.eclipse.jdt.core.javanature org.python.pydev.pythonNature + + + 1642294714551 + + 30 + + org.eclipse.core.resources.regexFilterMatcher + node_modules|.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__ + + + diff --git a/Base - Launch Mode in Eclipse.launch b/Base - Launch Mode in Eclipse.launch index e561a978..fead4b7f 100644 --- a/Base - Launch Mode in Eclipse.launch +++ b/Base - Launch Mode in Eclipse.launch @@ -1,7 +1,7 @@ - + @@ -12,37 +12,35 @@ - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - - - - - - - - - + + + + + + + - + diff --git a/Base - Sketch Runner First.launch b/Base - Sketch Runner First.launch index dc466d79..2d663d80 100644 --- a/Base - Sketch Runner First.launch +++ b/Base - Sketch Runner First.launch @@ -1,29 +1,33 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/HOWTO-HACK.txt b/HOWTO-HACK.txt index 54e9902c..9a6608ec 100644 --- a/HOWTO-HACK.txt +++ b/HOWTO-HACK.txt @@ -44,8 +44,8 @@ the original repo: You'll need source for processing and processing-video. - $ git clone --depth=1 https://github.com/processing/processing.git - $ git clone --depth=1 https://github.com/processing/processing-video.git + $ git clone https://github.com/processing/processing4.git + $ git clone https://github.com/processing/processing-video.git If you are a Linux user, you'll also have to create a directory named `linux` inside your `processing.py` directory. diff --git a/README.markdown b/README.markdown index 568ec63e..2c3e5717 100644 --- a/README.markdown +++ b/README.markdown @@ -2,10 +2,10 @@ Write real [Processing](http://processing.org/) sketches in Python. -* Based on [Processing 3.0](http://processing.org/), and compatible with most [3rd party libraries](http://www.processing.org/reference/libraries/). +* Based on [Processing 4](http://processing.org/), and compatible with most [3rd party libraries](http://www.processing.org/reference/libraries/). * Source compatible with [Python 2.7.3](http://python.org). -Tested on Mac OS 10.10 and Ubuntu 14. +Tested on Mac OS 11.6.2 and Ubuntu 14. [![Build Status](https://travis-ci.org/jdf/processing.py.svg?branch=master)](https://travis-ci.org/jdf/processing.py) [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fjdf%2Fprocessing.py.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2Fjdf%2Fprocessing.py?ref=badge_shield) @@ -14,13 +14,11 @@ Tested on Mac OS 10.10 and Ubuntu 14. ### Processing Development Environment ### -If you're looking to write Processing sketches in Python, your best bet is to use -Python Mode. The project is still in its early days, and documentation is lacking, -but there are many example sketches to get you started. In general, the Processing -reference works just fine for Python mode. +If you're looking to write Processing 4 sketches in Python, your best bet is to use +Python Mode. First, [download Processing](http://processing.org/download). Then, install -Python Mode: +Python Mode 4: @@ -82,9 +80,9 @@ In case you need other primitive values, please [let us know](http://github.com/ ### Why was this project created? ### -I ([Jonathan](http://MrFeinberg.com/)) recently gave a talk about Processing to a group of rather bright 8th-graders, +I ([Jonathan](http://MrFeinberg.com/)) once gave a talk about Processing to a group of rather bright 8th-graders, as part of a computer-programming summer camp they were attending at my office. -Their curriculum up to that point had been in Python, which is an eminently +Their curriculum up to that point had been in Python, which is a sensible choice, given the [pedagogical roots](http://en.wikipedia.org/wiki/ABC_%28programming_language%29) of the language. diff --git a/SketchRunner.launch b/SketchRunner.launch index e0c7b6f2..0d4711ff 100644 --- a/SketchRunner.launch +++ b/SketchRunner.launch @@ -1,19 +1,26 @@ - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + diff --git a/build.xml b/build.xml index e162ee55..9f23b81b 100644 --- a/build.xml +++ b/build.xml @@ -28,7 +28,7 @@ By default, we'll look in a directory next to this one. The same goes for processing-video (https://github.com/processing/processing-video). --> - + @@ -62,7 +62,7 @@ - + @@ -72,7 +72,7 @@ file="runtime/src/jycessing/build.properties" comment="Python mode build number"> - + @@ -133,7 +133,7 @@ - + diff --git a/mode/mode.properties b/mode/mode.properties index 87e5ee02..fe6b531d 100644 --- a/mode/mode.properties +++ b/mode/mode.properties @@ -1,11 +1,11 @@ -name = Python Mode for Processing 3 +name = Python Mode for Processing 4 authorList = [Jonathan Feinberg](http://MrFeinberg.com/) url = https://github.com/jdf/processing.py -sentence = Write Processing sketches in Python. +sentence = Write Processing 4 sketches in Python. paragraph = version = @@version@@ prettyVersion = @@pretty-version@@ # 3.0 -minRevision = 246 +minRevision = 1279 # <3.2 maxRevision = 0 diff --git a/processing-py-test-suite.launch b/processing-py-test-suite.launch index 7d5ac6b7..b5c2dad2 100644 --- a/processing-py-test-suite.launch +++ b/processing-py-test-suite.launch @@ -1,44 +1,38 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/runtime/src/jycessing/PAppletJythonDriver.java b/runtime/src/jycessing/PAppletJythonDriver.java index b310a352..0576eea2 100755 --- a/runtime/src/jycessing/PAppletJythonDriver.java +++ b/runtime/src/jycessing/PAppletJythonDriver.java @@ -934,7 +934,7 @@ public void runAndBlock(final String[] args) throws PythonSketchError { maybeShutdownSoundEngine(); Thread.setDefaultUncaughtExceptionHandler(null); - if (PApplet.platform == PConstants.MACOSX && Arrays.asList(args).contains("fullScreen")) { + if (PApplet.platform == PConstants.MACOS && Arrays.asList(args).contains("fullScreen")) { // Frame should be OS-X fullscreen, and it won't stop being that unless the jvm // exits or we explicitly tell it to minimize. // (If it's disposed, it'll leave a gray blank window behind it.) diff --git a/runtime/src/jycessing/build.properties b/runtime/src/jycessing/build.properties index 1a22f6ed..c0007f82 100644 --- a/runtime/src/jycessing/build.properties +++ b/runtime/src/jycessing/build.properties @@ -2,4 +2,4 @@ #Tue, 19 May 2020 13:23:09 -0400 build.date=2020/05/19 13\:23 -build.number=3063 +build.number=4000 diff --git a/runtime/src/jycessing/jni/OSX.java b/runtime/src/jycessing/jni/OSX.java index aeb2ebfb..0d7c78f2 100644 --- a/runtime/src/jycessing/jni/OSX.java +++ b/runtime/src/jycessing/jni/OSX.java @@ -8,7 +8,7 @@ public class OSX { private static volatile boolean didLoad = false; public static void bringToFront() { - if (!didLoad && (PApplet.platform == PConstants.MACOSX)) { + if (!didLoad && (PApplet.platform == PConstants.MACOS)) { try { System.loadLibrary("jniosx"); didLoad = true; @@ -22,14 +22,16 @@ public static void bringToFront() { } public static void bringToFront(PythonMode mode) { - if (!didLoad && (PApplet.platform == PConstants.MACOSX)) { + if (!didLoad && (PApplet.platform == PConstants.MACOS)) { String path = null; try { path = mode.getContentFile("mode").getAbsolutePath() + "/libjniosx.dylib"; System.load(path); didLoad = true; } catch (final UnsatisfiedLinkError err) { - System.err.println("Hmm. Can't load native code to bring window to front using the absolute path: " + path + "."); + System.err.println( + "Hmm. Can't load native code to bring window to front using the absolute path: " + path + + "."); } } bringToFront(); diff --git a/runtime/src/jycessing/mode/run/SketchServiceProcess.java b/runtime/src/jycessing/mode/run/SketchServiceProcess.java index b2e018fa..352aec62 100644 --- a/runtime/src/jycessing/mode/run/SketchServiceProcess.java +++ b/runtime/src/jycessing/mode/run/SketchServiceProcess.java @@ -155,6 +155,39 @@ private ProcessBuilder createServerCommand() { // enable assertions command.add("-ea"); + // Give introspection permissions. + final String[] exports = {"java.base/sun.nio.ch", // + "java.base/java.nio", // + "java.base/java.lang", // + "java.base/java.lang.constant", // + "java.base/java.lang.reflect", // + "java.base/java.io", // + "jdk.unsupported/sun.misc", // + "java.base/java.nio.charset", // + "java.base/java.util", // + "java.base/java.net", // + "java.base/java.text", // + "java.base/java.util.concurrent", // + "java.sql/java.sql", // + "java.base/java.util.concurrent.locks", // + "java.base/sun.util.calendar", // + "java.base/java.nio.channels", // + "java.base/java.security", // + "java.base/java.util.concurrent.atomic", // + "java.base/java.security.cert", // + "java.base/javax.net.ssl", // + "java.naming/javax.naming.ldap", // + "java.base/java.security.spec", // + "java.base/javax.net.ssl", // + "java.base/javax.security.auth.x500", // + "java.security.jgss/org.ietf.jgss", // + "java.desktop/com.apple.eawt", // + }; + for (final String s : exports) { + command.add(String.format("--add-exports=%s=ALL-UNNAMED", s)); + command.add(String.format("--add-opens=%s=ALL-UNNAMED", s)); + } + // Run the SketchRunner main. command.add(SketchRunner.class.getName()); diff --git a/testmode.sh b/testmode.sh index f7356c29..4ab499b8 100755 --- a/testmode.sh +++ b/testmode.sh @@ -2,7 +2,7 @@ export VERBOSE_PYTHON_MODE=true PROCESSINGPY=$(pwd) -PROCESSING=../processing +PROCESSING=../processing4 MODES=~/Documents/Processing/modes; if [[ $(uname) == 'Darwin' ]]; then From 4c5b47f94f23aaaa6bd0adaf3f10fc889034f88d Mon Sep 17 00:00:00 2001 From: Jonathan Feinberg Date: Sat, 22 Jan 2022 11:36:58 -0500 Subject: [PATCH 02/21] Build 4001. --- build.xml | 2 +- runtime/src/jycessing/build.properties | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build.xml b/build.xml index 9f23b81b..8e367fcb 100644 --- a/build.xml +++ b/build.xml @@ -138,7 +138,7 @@ - + diff --git a/runtime/src/jycessing/build.properties b/runtime/src/jycessing/build.properties index c0007f82..acd55828 100644 --- a/runtime/src/jycessing/build.properties +++ b/runtime/src/jycessing/build.properties @@ -1,5 +1,5 @@ #Python mode build number -#Tue, 19 May 2020 13:23:09 -0400 +#Sat, 22 Jan 2022 11:36:58 -0500 -build.date=2020/05/19 13\:23 -build.number=4000 +build.date=2022/01/22 11\:36 +build.number=4001 From a08380f09814e8511594ef2c9b6c50cf464b08b5 Mon Sep 17 00:00:00 2001 From: Ben Fry Date: Thu, 3 Mar 2022 13:17:49 -0500 Subject: [PATCH 03/21] call PSurfaceFX instanceof check dynamically --- runtime/src/jycessing/PAppletJythonDriver.java | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/runtime/src/jycessing/PAppletJythonDriver.java b/runtime/src/jycessing/PAppletJythonDriver.java index 0576eea2..5a127c83 100755 --- a/runtime/src/jycessing/PAppletJythonDriver.java +++ b/runtime/src/jycessing/PAppletJythonDriver.java @@ -78,7 +78,6 @@ import processing.core.PSurface; import processing.event.KeyEvent; import processing.event.MouseEvent; -import processing.javafx.PSurfaceFX; import processing.opengl.PGraphicsOpenGL; import processing.opengl.PShader; import processing.opengl.PSurfaceJOGL; @@ -106,6 +105,14 @@ public class PAppletJythonDriver extends PApplet { private Field frameField; + static private Class fxSurfaceClass; + static { + try { + // Get class object for use in dynamic instanceof calls for PSurfaceFX + fxSurfaceClass = Class.forName("processing.javafx.PSurfaceFX"); + } catch (ClassNotFoundException ignored) { } + } + private PythonSketchError terminalException = null; protected final PyStringMap builtins; @@ -326,7 +333,7 @@ private static PythonSketchError extractSketchErrorFromPyExceptionValue(final Py * slightly less cryptic error message. * * @param file - * @param line + * @param lineNo * @param column * @return */ @@ -502,7 +509,7 @@ public void windowDestroyed(final com.jogamp.newt.event.WindowEvent arg0) { finishedLatch.countDown(); } }); - } else if (s instanceof PSurfaceFX) { + } else if (fxSurfaceClass != null && fxSurfaceClass.isInstance(s)) { System.err.println("I don't know how to watch FX2D windows for close."); } @@ -949,7 +956,7 @@ public void runAndBlock(final String[] args) throws PythonSketchError { } } } - if (surface instanceof PSurfaceFX) { + if (fxSurfaceClass != null && fxSurfaceClass.isInstance(surface)) { // Sadly, JavaFX is an abomination, and there's no way to run an FX sketch more than once, // so we must actually exit. Runner.log("JavaFX requires SketchRunner to terminate. Farewell!"); From 3318efbbead8ef8fcc57d6f5e1655ea8de139bb1 Mon Sep 17 00:00:00 2001 From: Kurt Steinkraus Date: Tue, 28 Jun 2022 20:28:23 -0700 Subject: [PATCH 04/21] Updates for changes to processing4: build/macos was renamed to build/macosx in d6fe5cac339bce5dfa8bb589779aabba5c7c496d. javafx was moved in a605ff53ba08480856e64938d78d3c6a15d6b018 and then removed entirely in bade983019dff85f59cdaadc1be25410ea7afc93; see also https://github.com/processing/processing4/issues/348. --- runtime/src/jycessing/PAppletJythonDriver.java | 9 --------- testmode.sh | 4 ++-- 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/runtime/src/jycessing/PAppletJythonDriver.java b/runtime/src/jycessing/PAppletJythonDriver.java index 0576eea2..d68a4ea8 100755 --- a/runtime/src/jycessing/PAppletJythonDriver.java +++ b/runtime/src/jycessing/PAppletJythonDriver.java @@ -78,7 +78,6 @@ import processing.core.PSurface; import processing.event.KeyEvent; import processing.event.MouseEvent; -import processing.javafx.PSurfaceFX; import processing.opengl.PGraphicsOpenGL; import processing.opengl.PShader; import processing.opengl.PSurfaceJOGL; @@ -502,8 +501,6 @@ public void windowDestroyed(final com.jogamp.newt.event.WindowEvent arg0) { finishedLatch.countDown(); } }); - } else if (s instanceof PSurfaceFX) { - System.err.println("I don't know how to watch FX2D windows for close."); } final PyObject pyG; @@ -949,12 +946,6 @@ public void runAndBlock(final String[] args) throws PythonSketchError { } } } - if (surface instanceof PSurfaceFX) { - // Sadly, JavaFX is an abomination, and there's no way to run an FX sketch more than once, - // so we must actually exit. - Runner.log("JavaFX requires SketchRunner to terminate. Farewell!"); - System.exit(0); - } final Object nativeWindow = surface.getNative(); if (nativeWindow instanceof com.jogamp.newt.Window) { ((com.jogamp.newt.Window) nativeWindow).destroy(); diff --git a/testmode.sh b/testmode.sh index 4ab499b8..d318e0d1 100755 --- a/testmode.sh +++ b/testmode.sh @@ -6,8 +6,8 @@ PROCESSING=../processing4 MODES=~/Documents/Processing/modes; if [[ $(uname) == 'Darwin' ]]; then - RUNPROCESSING=$PROCESSING/build/macosx/work/Processing.app/Contents/MacOS/Processing -else + RUNPROCESSING=$PROCESSING/build/macos/work/Processing.app/Contents/MacOS/Processing +else RUNPROCESSING="$PROCESSING/build/linux/work/processing" MODES=~/sketchbook/modes; fi From dc0e3ff4313fde1e4e162f8f35dee9584ecd70d5 Mon Sep 17 00:00:00 2001 From: Ben Fry Date: Tue, 14 Feb 2023 11:25:16 -0500 Subject: [PATCH 05/21] fix typo --- HOWTO-HACK.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/HOWTO-HACK.txt b/HOWTO-HACK.txt index 9a6608ec..5fb20355 100644 --- a/HOWTO-HACK.txt +++ b/HOWTO-HACK.txt @@ -67,7 +67,7 @@ Configuring Eclipse ------------------- If you want to modify the code, and you're an Eclipse user, you can "Import -existing project into workspace" a few of times, once for processing.py +existing project into workspace" a few times, once for processing.py itself (which lives in the processing.py top level directory), and once each for processing.core, processing-java, processing-app, and processing-video, which you'll find in the directories where you've From e5a856d340fceafeb9396d83feece641cbfb2e2a Mon Sep 17 00:00:00 2001 From: Ben Fry Date: Tue, 14 Feb 2023 11:26:41 -0500 Subject: [PATCH 06/21] switch to using local.properties for repo locations --- .gitignore | 3 ++ build.xml | 80 ++++++++++++++++++++++++++++-------------------------- 2 files changed, 45 insertions(+), 38 deletions(-) diff --git a/.gitignore b/.gitignore index 6e756686..53e0869c 100644 --- a/.gitignore +++ b/.gitignore @@ -32,3 +32,6 @@ misc/windowsexecutablestub/Release *.sdf *.suo linux/ + +local.properties + diff --git a/build.xml b/build.xml index 8e367fcb..df8af9c9 100644 --- a/build.xml +++ b/build.xml @@ -22,22 +22,26 @@ Write Processing sketches in Python - - - + + + + + + + - - + + @@ -74,7 +78,7 @@ - + @@ -134,7 +138,7 @@ - + @@ -149,8 +153,8 @@ - - + + @@ -164,9 +168,9 @@ + file="${processing.dir}/core/library/gluegen-rt-natives-${natives.platform}.jar"/> + file="${processing.dir}/core/library/jogl-all-natives-${natives.platform}.jar"/> @@ -177,7 +181,7 @@ - + @@ -193,39 +197,39 @@ - + - + - + - + - + targetfile="${processing-video.dir}/library/video.jar"> + - + @@ -234,7 +238,7 @@ - + @@ -244,7 +248,7 @@ - + - @@ -420,9 +424,9 @@ - - @@ -435,10 +439,10 @@ - + - @@ -537,12 +541,12 @@ - + - - + + From edc25631a412c2f298d854eb7861b8f4688c2aca Mon Sep 17 00:00:00 2001 From: Ben Fry Date: Tue, 14 Feb 2023 11:29:12 -0500 Subject: [PATCH 07/21] root out a few tabs that snuck into the file; convert to spaces --- build.xml | 50 +++++++++++++++++++++++++------------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/build.xml b/build.xml index df8af9c9..c49e79ca 100644 --- a/build.xml +++ b/build.xml @@ -79,7 +79,7 @@ ${line.separator}and the processing-video library cloned from git." /> - + @@ -94,7 +94,7 @@ ${line.separator}and the processing-video library cloned from git." /> - + @@ -108,7 +108,7 @@ ${line.separator}and the processing-video library cloned from git." /> - + - + @@ -230,7 +230,7 @@ ${line.separator}and the processing-video library cloned from git." /> unless="video-is-uptodate"> - + @@ -318,13 +318,13 @@ ${line.separator}and the processing-video library cloned from git." /> + force="yes" + class="jycessing.jni.OSX" + classpath="./bin" /> - + @@ -513,7 +513,7 @@ ${line.separator}and the processing-video library cloned from git." /> @@ -538,21 +538,21 @@ ${line.separator}and the processing-video library cloned from git." /> - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + From ec7080762d90d3334851733bc1e848e9e61efe0b Mon Sep 17 00:00:00 2001 From: Ben Fry Date: Tue, 14 Feb 2023 11:31:30 -0500 Subject: [PATCH 08/21] replace hardcoded path to core with variable --- build.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/build.xml b/build.xml index c49e79ca..6e721b39 100644 --- a/build.xml +++ b/build.xml @@ -226,11 +226,11 @@ ${line.separator}and the processing-video library cloned from git." /> + depends="check-video-needs-build" + unless="video-is-uptodate"> - + From 2e80ae7defc8bdd502823677debbd5b2e189a626 Mon Sep 17 00:00:00 2001 From: Ben Fry Date: Tue, 14 Feb 2023 19:37:04 -0500 Subject: [PATCH 09/21] these updates will require Processing 4.2 --- mode/mode.properties | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mode/mode.properties b/mode/mode.properties index fe6b531d..9274ee27 100644 --- a/mode/mode.properties +++ b/mode/mode.properties @@ -5,7 +5,7 @@ sentence = Write Processing 4 sketches in Python. paragraph = version = @@version@@ prettyVersion = @@pretty-version@@ -# 3.0 -minRevision = 1279 -# <3.2 +# 4.1.4 or 4.2 (additional changes made to support Python Mode) +minRevision = 1292 +# works with any later release maxRevision = 0 From f1115f5c54dde60f566213e6c410b84e19bd1cf2 Mon Sep 17 00:00:00 2001 From: Ben Fry Date: Tue, 14 Feb 2023 19:42:26 -0500 Subject: [PATCH 10/21] clean up export so things can at least compile --- runtime/src/jycessing/mode/export/Arch.java | 16 - .../jycessing/mode/export/ExportDialog.java | 389 ------------------ .../jycessing/mode/export/ExportedSketch.java | 4 +- .../src/jycessing/mode/export/Exporter.java | 66 +-- .../jycessing/mode/export/LinuxExport.java | 17 +- .../src/jycessing/mode/export/MacExport.java | 14 +- .../jycessing/mode/export/PlatformExport.java | 3 +- .../jycessing/mode/export/WindowsExport.java | 28 +- 8 files changed, 37 insertions(+), 500 deletions(-) delete mode 100644 runtime/src/jycessing/mode/export/Arch.java delete mode 100644 runtime/src/jycessing/mode/export/ExportDialog.java diff --git a/runtime/src/jycessing/mode/export/Arch.java b/runtime/src/jycessing/mode/export/Arch.java deleted file mode 100644 index 122cf781..00000000 --- a/runtime/src/jycessing/mode/export/Arch.java +++ /dev/null @@ -1,16 +0,0 @@ -package jycessing.mode.export; - -/** - * The architecture of the platform we're exporting to. (The "bits" field is necessary because the - * processing Library API uses magic integers for architecture.) - */ -public enum Arch { - X86(32), - AMD64(64); - - public final int bits; - - Arch(final int bits) { - this.bits = bits; - } -} diff --git a/runtime/src/jycessing/mode/export/ExportDialog.java b/runtime/src/jycessing/mode/export/ExportDialog.java deleted file mode 100644 index c92ec1aa..00000000 --- a/runtime/src/jycessing/mode/export/ExportDialog.java +++ /dev/null @@ -1,389 +0,0 @@ -package jycessing.mode.export; - -import java.awt.Color; -import java.awt.Component; -import java.awt.Dimension; -import java.awt.Graphics; -import java.awt.Rectangle; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.ItemEvent; -import java.awt.event.ItemListener; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.io.File; - -import javax.swing.BorderFactory; -import javax.swing.Box; -import javax.swing.BoxLayout; -import javax.swing.JCheckBox; -import javax.swing.JDialog; -import javax.swing.JLabel; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.SwingConstants; -import javax.swing.border.BevelBorder; -import javax.swing.border.EmptyBorder; -import javax.swing.border.TitledBorder; - -import jycessing.mode.PyEditor; -import jycessing.mode.PythonMode; -import processing.app.Platform; -import processing.app.Preferences; -import processing.app.Sketch; -import processing.app.ui.ColorChooser; - -/** - * This is the export window that pops up when the user clicks [=>]. It tries to look as much as - * possible like java mode's exporter. Rather than passing the options they select directly to - * Exporter, it sets them in their user preferences, which Exporter and the various Export classes - * reference later. - */ -@SuppressWarnings("serial") -public class ExportDialog extends JDialog { - - @SuppressWarnings("unused") - private static void log(final String msg) { - if (PythonMode.VERBOSE) { - System.err.println(ExportDialog.class.getSimpleName() + ": " + msg); - } - } - - private final Sketch sketch; - private final PyEditor editor; - private final JOptionPane optionPane; - - public ExportDialog(final PyEditor editor, final Sketch sketch) { - super(editor, "Export Application", true); - - this.editor = editor; - this.sketch = sketch; - - log("Setting up export dialog"); - - final JPanel center = createCenterPanel(); - - final JPanel platforms = createPlatformsPanel(); - center.add(platforms); - - final JPanel present = createPresentPanel(); - center.add(present); - - final JPanel embed = createEmbedJavaPanel(platforms.getPreferredSize().width); - center.add(embed); - - // I haven't tested this on a Mac yet - if (Platform.isMacOS()) { - final JPanel signingProblems = createMacSigningWarning(platforms.getPreferredSize().width); - center.add(signingProblems); - } - - final String[] options = {"Export", "Cancel"}; - optionPane = - new JOptionPane( - center, - JOptionPane.PLAIN_MESSAGE, - JOptionPane.YES_NO_OPTION, - null, - options, - options[0]); - - this.setContentPane(optionPane); - optionPane.addPropertyChangeListener( - new PropertyChangeListener() { - @Override - public void propertyChange(final PropertyChangeEvent e) { - final String prop = e.getPropertyName(); - - if (isVisible() - && (e.getSource() == optionPane) - && (prop.equals(JOptionPane.VALUE_PROPERTY))) { - setVisible(false); - } - } - }); - this.pack(); - this.setResizable(false); - - final Rectangle bounds = editor.getBounds(); - final Dimension size = this.getSize(); - this.setLocation( - bounds.x + (bounds.width - size.width) / 2, bounds.y + (bounds.height - size.height) / 2); - } - - public void go() { - log("Launching export dialog"); - - this.setVisible(true); - - // Wait until they click "Export" or "Cancel" - final Object value = optionPane.getValue(); - - if (value.equals("Export")) { - new Exporter(editor, sketch).export(); - } else { - editor.statusNotice("Export to Application Cancelled"); - } - } - - private JPanel createCenterPanel() { - final JPanel panel = new JPanel(); - panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); - panel.add(Box.createVerticalStrut(6)); - final String line1 = "Export to Application creates double-clickable,"; - final String line2 = "standalone applications for the selected plaforms."; - final JLabel label1 = new JLabel(line1, SwingConstants.CENTER); - final JLabel label2 = new JLabel(line2, SwingConstants.CENTER); - label1.setAlignmentX(Component.LEFT_ALIGNMENT); - label2.setAlignmentX(Component.LEFT_ALIGNMENT); - panel.add(label1); - panel.add(label2); - panel.add(Box.createVerticalStrut(12)); - return panel; - } - - private JPanel createPlatformsPanel() { - final JCheckBox windowsButton = new JCheckBox("Windows"); - windowsButton.setSelected(Preferences.getBoolean("export.application.platform.windows")); - windowsButton.addItemListener( - new ItemListener() { - @Override - public void itemStateChanged(final ItemEvent e) { - Preferences.setBoolean( - "export.application.platform.windows", windowsButton.isSelected()); - } - }); - - final JCheckBox macosxButton = new JCheckBox("Mac OS X"); - macosxButton.setSelected(Preferences.getBoolean("export.application.platform.macosx")); - macosxButton.addItemListener( - new ItemListener() { - @Override - public void itemStateChanged(final ItemEvent e) { - Preferences.setBoolean("export.application.platform.macosx", macosxButton.isSelected()); - } - }); - - final JCheckBox linuxButton = new JCheckBox("Linux"); - linuxButton.setSelected(Preferences.getBoolean("export.application.platform.linux")); - linuxButton.addItemListener( - new ItemListener() { - @Override - public void itemStateChanged(final ItemEvent e) { - Preferences.setBoolean("export.application.platform.linux", linuxButton.isSelected()); - } - }); - - final JPanel platformPanel = new JPanel(); - platformPanel.add(windowsButton); - platformPanel.add(Box.createHorizontalStrut(6)); - platformPanel.add(macosxButton); - platformPanel.add(Box.createHorizontalStrut(6)); - platformPanel.add(linuxButton); - platformPanel.setBorder(new TitledBorder("Platforms")); - platformPanel.setAlignmentX(Component.LEFT_ALIGNMENT); - return platformPanel; - } - - private JPanel createPresentPanel() { - final JPanel presentPanel = new JPanel(); - presentPanel.setLayout(new BoxLayout(presentPanel, BoxLayout.Y_AXIS)); - - final JCheckBox showStopButton = new JCheckBox("Show a Stop button"); - showStopButton.setSelected(Preferences.getBoolean("export.application.stop")); - showStopButton.addItemListener( - new ItemListener() { - @Override - public void itemStateChanged(final ItemEvent e) { - Preferences.setBoolean("export.application.stop", showStopButton.isSelected()); - } - }); - showStopButton.setEnabled(Preferences.getBoolean("export.application.fullscreen")); - showStopButton.setBorder(new EmptyBorder(3, 13, 6, 13)); - - final JCheckBox fullScreenButton = new JCheckBox("Full Screen (Present mode)"); - fullScreenButton.setSelected(Preferences.getBoolean("export.application.fullscreen")); - fullScreenButton.addItemListener( - new ItemListener() { - @Override - public void itemStateChanged(final ItemEvent e) { - final boolean selected = fullScreenButton.isSelected(); - Preferences.setBoolean("export.application.fullscreen", selected); - showStopButton.setEnabled(selected); - } - }); - fullScreenButton.setBorder(new EmptyBorder(3, 13, 3, 13)); - - final Box fullScreenBox = Box.createHorizontalBox(); - fullScreenBox.add(fullScreenButton); - fullScreenBox.add(new ColorPreference("run.present.bgcolor", editor)); - fullScreenBox.add(Box.createHorizontalStrut(10)); - fullScreenBox.add(Box.createHorizontalGlue()); - presentPanel.add(fullScreenBox); - - final Box showStopBox = Box.createHorizontalBox(); - showStopBox.add(showStopButton); - showStopBox.add(new ColorPreference("run.present.stop.color", editor)); - showStopBox.add(Box.createHorizontalStrut(10)); - showStopBox.add(Box.createHorizontalGlue()); - presentPanel.add(showStopBox); - - presentPanel.setBorder(new TitledBorder("Full Screen")); - presentPanel.setAlignmentX(Component.LEFT_ALIGNMENT); - - return presentPanel; - } - - private JPanel createEmbedJavaPanel(final int divWidth) { - final JPanel embedPanel = new JPanel(); - embedPanel.setLayout(new BoxLayout(embedPanel, BoxLayout.Y_AXIS)); - - String platformName = null; - if (Platform.isMacOS()) { - platformName = "Mac OS X"; - } else if (Platform.isWindows()) { - platformName = "Windows (" + Platform.getNativeBits() + "-bit)"; - } else if (Platform.isLinux()) { - platformName = "Linux (" + Platform.getNativeBits() + "-bit)"; - } - - final boolean embed = Preferences.getBoolean("export.application.embed_java"); - final String embedWarning = - "
" - + "Embedding Java will make the " - + platformName - + " application " - + "larger, but it will be far more likely to work. " - + "Users on other platforms will need to install Java 7."; - final String nopeWarning = - "
" - + "Users on all platforms will have to install the latest " - + "version of Java 7 from http://java.com/download. " - + "
 "; - // "from java.com/download."; - final JLabel warningLabel = new JLabel(embed ? embedWarning : nopeWarning); - warningLabel.addMouseListener( - new MouseAdapter() { - @Override - public void mousePressed(final MouseEvent event) { - Platform.openURL("http://java.com/download"); - } - }); - warningLabel.setBorder(new EmptyBorder(3, 13, 3, 13)); - - final JCheckBox embedJavaButton = new JCheckBox("Embed Java for " + platformName); - embedJavaButton.setSelected(embed); - embedJavaButton.addItemListener( - new ItemListener() { - @Override - public void itemStateChanged(final ItemEvent e) { - final boolean selected = embedJavaButton.isSelected(); - Preferences.setBoolean("export.application.embed_java", selected); - if (selected) { - warningLabel.setText(embedWarning); - } else { - warningLabel.setText(nopeWarning); - } - } - }); - embedJavaButton.setBorder(new EmptyBorder(3, 13, 3, 13)); - - embedPanel.add(embedJavaButton); - embedPanel.add(warningLabel); - embedPanel.setBorder(new TitledBorder("Embed Java")); - - return embedPanel; - } - - private JPanel createMacSigningWarning(final int divWidth) { - final JPanel signPanel = new JPanel(); - signPanel.setLayout(new BoxLayout(signPanel, BoxLayout.Y_AXIS)); - signPanel.setBorder(new TitledBorder("Code Signing")); - - final StringBuilder thePain = - new StringBuilder( - "In recent versions of OS X, Apple has introduced the \u201CGatekeeper\u201D system, " - + "which makes it more difficult to run applications like those exported from Processing. "); - - if (new File("/usr/bin/codesign_allocate").exists()) { - thePain.append( - "This application will be \u201Cself-signed\u201D which means that Finder may report that the " - + "application is from an \u201Cunidentified developer\u201D. If the application will not " - + "run, try right-clicking the app and selecting Open from the pop-up menu. Or you can visit " - + "System Preferences \u2192 Security & Privacy and select Allow apps downloaded from: anywhere. "); - } else { - thePain.append( - "Gatekeeper requires applications to be \u201Csigned\u201D, or they will be reported as damaged. " - + "To prevent this message, install Xcode (and the Command Line Tools) from the App Store, or visit " - + "System Preferences \u2192 Security & Privacy and select Allow apps downloaded from: anywhere. "); - } - thePain.append( - "To avoid the messages entirely, manually code sign your app. " - + "For more information: https://developer.apple.com/developer-id/"); - - final JLabel area = - new JLabel( - "
" - + thePain.toString() - + "
"); - - area.setBorder(new EmptyBorder(3, 13, 3, 13)); - signPanel.add(area); - signPanel.setAlignmentX(Component.LEFT_ALIGNMENT); - - area.addMouseListener( - new MouseAdapter() { - @Override - public void mousePressed(final MouseEvent event) { - Platform.openURL("https://developer.apple.com/developer-id/"); - } - }); - return signPanel; - } - - static class ColorPreference extends JPanel implements ActionListener { - ColorChooser chooser; - String prefName; - - public ColorPreference(final String pref, final PyEditor editor) { - prefName = pref; - - setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED)); - setPreferredSize(new Dimension(30, 20)); - setMaximumSize(new Dimension(30, 20)); - - addMouseListener( - new MouseAdapter() { - @Override - public void mouseReleased(final MouseEvent e) { - final Color color = Preferences.getColor(prefName); - chooser = new ColorChooser(editor, true, color, "Select", ColorPreference.this); - chooser.show(); - } - }); - } - - @Override - public void paintComponent(final Graphics g) { - g.setColor(Preferences.getColor(prefName)); - final Dimension size = getSize(); - g.fillRect(0, 0, size.width, size.height); - } - - @Override - public void actionPerformed(final ActionEvent e) { - final Color color = chooser.getColor(); - Preferences.setColor(prefName, color); - repaint(); - chooser.hide(); - } - } -} diff --git a/runtime/src/jycessing/mode/export/ExportedSketch.java b/runtime/src/jycessing/mode/export/ExportedSketch.java index 5b3fc216..9b69387a 100644 --- a/runtime/src/jycessing/mode/export/ExportedSketch.java +++ b/runtime/src/jycessing/mode/export/ExportedSketch.java @@ -2,7 +2,7 @@ import java.io.File; import java.io.FileNotFoundException; -import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.util.ArrayList; import java.util.Arrays; @@ -46,7 +46,7 @@ public ExportedSketch(final String[] args) throws Exception { } final List codeLines = - Files.readAllLines(sketchPath.toPath(), Charset.forName("UTF-8")); + Files.readAllLines(sketchPath.toPath(), StandardCharsets.UTF_8); final StringBuilder code = new StringBuilder(); for (final String line : codeLines) { diff --git a/runtime/src/jycessing/mode/export/Exporter.java b/runtime/src/jycessing/mode/export/Exporter.java index b4386b36..e7b7a9e1 100644 --- a/runtime/src/jycessing/mode/export/Exporter.java +++ b/runtime/src/jycessing/mode/export/Exporter.java @@ -1,5 +1,6 @@ package jycessing.mode.export; +import java.io.File; import java.io.IOException; import java.util.Set; @@ -9,6 +10,7 @@ import processing.app.Platform; import processing.app.Preferences; import processing.app.Sketch; +import processing.app.ui.ExportPrompt; /** * Class that handles doing the actual exporting. All this currently does is figure out libraries @@ -23,23 +25,8 @@ private static void log(final String msg) { } } - // Architecture of the currently running Processing JRE. - // Used to determine what platform we can embed java in. - public static final Arch processingArch; - - static { - if (Platform.getNativeBits() == Arch.X86.bits) { - processingArch = Arch.X86; - } else { - processingArch = Arch.AMD64; - } - } - private final Sketch sketch; - private final PyEditor editor; // I don't really want to pass this around but there's some - // functionality - - // I need + private final PyEditor editor; public Exporter(final PyEditor editor, final Sketch sketch) { this.sketch = sketch; @@ -50,43 +37,26 @@ public void export() { // Work out the libraries the sketch exports - we only need to do this once. final Set libraries = new ImportExtractor(sketch).getLibraries(); - // Now, do this for each platform: - if (Preferences.getBoolean("export.application.platform.linux")) { - try { - new LinuxExport(Arch.X86, sketch, editor, libraries).export(); - } catch (final IOException e) { - e.printStackTrace(); - editor.statusError("Export to linux32 failed!"); - } - try { - new LinuxExport(Arch.AMD64, sketch, editor, libraries).export(); - } catch (final IOException e) { - e.printStackTrace(); - editor.statusError("Export to linux64 failed!"); - } - } - if (Preferences.getBoolean("export.application.platform.windows")) { - try { - new WindowsExport(Arch.X86, sketch, editor, libraries).export(); - } catch (final IOException e) { - e.printStackTrace(); - editor.statusError("Export to windows32 failed!"); - } - try { - new WindowsExport(Arch.AMD64, sketch, editor, libraries).export(); - } catch (final IOException e) { - e.printStackTrace(); - editor.statusError("Export to windows64 failed!"); - } - } - if (Preferences.getBoolean("export.application.platform.macosx")) { + final String hostVariant = Platform.getVariant(); + for (String variant : Preferences.get(ExportPrompt.EXPORT_VARIANTS).split(",")) { + // Can only embed Java on the native platform + boolean embed = variant.equals(hostVariant) && + Preferences.getBoolean("export.application.embed_java"); + try { - new MacExport(sketch, editor, libraries).export(); + if (variant.startsWith("windows-")) { + new WindowsExport(variant, sketch, editor, libraries, embed).export(); + } else if (variant.startsWith("macos-")) { + new MacExport(variant, sketch, editor, libraries, embed).export(); + } else if (variant.startsWith("linux-")) { + new LinuxExport(variant, sketch, editor, libraries, embed).export(); + } } catch (final IOException e) { e.printStackTrace(); - editor.statusError("Export to macosx failed!"); + editor.statusError("Export to " + variant + " failed"); } } + log("Opening result folder."); Platform.openFolder(sketch.getFolder()); } diff --git a/runtime/src/jycessing/mode/export/LinuxExport.java b/runtime/src/jycessing/mode/export/LinuxExport.java index 0450f273..fb568540 100644 --- a/runtime/src/jycessing/mode/export/LinuxExport.java +++ b/runtime/src/jycessing/mode/export/LinuxExport.java @@ -18,7 +18,6 @@ import processing.app.Sketch; import processing.app.Util; import processing.core.PApplet; -import processing.core.PConstants; /** * Performs an export to Linux (32/64). The linux export folder layout is as follows: @@ -41,26 +40,18 @@ protected void log(final String msg) { } } - public LinuxExport( - final Arch arch, final Sketch sketch, final PyEditor editor, final Set libraries) { - this.id = PConstants.LINUX; - this.arch = arch; - this.name = PConstants.platformNames[id] + arch.bits; + public LinuxExport(final String variant, final Sketch sketch, final PyEditor editor, final Set libraries, boolean embedJava) { + this.variant = variant; this.sketch = sketch; this.editor = editor; this.libraries = libraries; + this.embedJava = embedJava; } @Override public void export() throws IOException { - // Work out user preferences and other possibilities we care about - final boolean embedJava = - (id == PApplet.platform) - && Preferences.getBoolean("export.application.embed_java") - && arch == Exporter.processingArch; - // Work out the folders we'll be (maybe) using - final File destFolder = new File(sketch.getFolder(), "application." + name); + final File destFolder = new File(sketch.getFolder(), variant); final File javaFolder = new File(destFolder, "java"); copyBasicStructure(destFolder); diff --git a/runtime/src/jycessing/mode/export/MacExport.java b/runtime/src/jycessing/mode/export/MacExport.java index 948370e0..0a7cf18a 100644 --- a/runtime/src/jycessing/mode/export/MacExport.java +++ b/runtime/src/jycessing/mode/export/MacExport.java @@ -23,7 +23,6 @@ import processing.app.Sketch; import processing.app.Util; import processing.core.PApplet; -import processing.core.PConstants; /** * A Mac export. @@ -50,23 +49,18 @@ protected void log(final String msg) { } } - public MacExport(final Sketch sketch, final PyEditor editor, final Set libraries) { - this.id = PConstants.MACOSX; - this.name = PConstants.platformNames[id]; + public MacExport(final String variant, final Sketch sketch, final PyEditor editor, final Set libraries, final boolean embedJava) { + this.variant = variant; this.sketch = sketch; this.editor = editor; this.libraries = libraries; - this.arch = Arch.AMD64; + this.embedJava = embedJava; } @Override public void export() throws IOException { - // Work out user preferences and other possibilities we care about - final boolean embedJava = - (id == PApplet.platform) && Preferences.getBoolean("export.application.embed_java"); - // Work out the folders we'll be (maybe) using - final File destFolder = new File(sketch.getFolder(), "application." + name); + final File destFolder = new File(sketch.getFolder(), variant); final File appRootFolder = new File(destFolder, sketch.getName() + ".app"); final File contentsFolder = new File(appRootFolder, "Contents"); final File binFolder = new File(contentsFolder, "MacOS"); diff --git a/runtime/src/jycessing/mode/export/PlatformExport.java b/runtime/src/jycessing/mode/export/PlatformExport.java index db3c8d59..c72f6317 100644 --- a/runtime/src/jycessing/mode/export/PlatformExport.java +++ b/runtime/src/jycessing/mode/export/PlatformExport.java @@ -17,10 +17,11 @@ public abstract class PlatformExport { //protected int id; //protected Arch arch; protected String variant; // replaces id and arch in Processing 4 - protected String name; +// protected String name; protected PyEditor editor; protected Sketch sketch; protected Set libraries; + protected boolean embedJava; /** Instance so that subclasses can override it. */ protected abstract void log(final String msg); diff --git a/runtime/src/jycessing/mode/export/WindowsExport.java b/runtime/src/jycessing/mode/export/WindowsExport.java index 5aa2fd96..a89f336d 100644 --- a/runtime/src/jycessing/mode/export/WindowsExport.java +++ b/runtime/src/jycessing/mode/export/WindowsExport.java @@ -47,24 +47,17 @@ protected void log(final String msg) { } } - public WindowsExport( - final Arch arch, final Sketch sketch, final PyEditor editor, final Set libraries) { - this.id = PConstants.WINDOWS; - this.arch = arch; - this.name = PConstants.platformNames[id] + arch.bits; + public WindowsExport(final String variant, final Sketch sketch, final PyEditor editor, final Set libraries, boolean embedJava) { + this.variant = variant; this.sketch = sketch; this.editor = editor; this.libraries = libraries; + this.embedJava = embedJava; } @Override public void export() throws IOException { - final boolean embedJava = - (id == PApplet.platform) - && Preferences.getBoolean("export.application.embed_java") - && arch == Exporter.processingArch; - - final File destFolder = new File(sketch.getFolder(), "application." + name); + final File destFolder = new File(sketch.getFolder(), variant); final File javaFolder = new File(destFolder, "java"); copyBasicStructure(destFolder); @@ -109,7 +102,7 @@ private XML buildLaunch4jConfig(final File destFolder, final boolean embedJava) config.addChild("errTitle").setContent("Sketchy Behavior"); config.addChild("icon").setContent(iconFile.getAbsolutePath()); config.addChild("chdir").setContent("."); - config.addChild(buildJREOptions(embedJava, setMemory, arch)); + config.addChild(buildJREOptions(embedJava, setMemory)); config.addChild(buildRunnerOptions(presentMode, stopButton)); config.addChild(buildClassPathOptions(jycessingFolder)); log("Configuration done: " + config.format(0)); @@ -188,7 +181,7 @@ private void runLaunch4j(final File configFile) throws IOException { } } - private XML buildJREOptions(final boolean embedJava, final boolean setMemory, final Arch arch) { + private XML buildJREOptions(final boolean embedJava, final boolean setMemory) { log("Building JRE options."); final XML jre = new XML("jre"); if (embedJava) { @@ -200,14 +193,7 @@ private XML buildJREOptions(final boolean embedJava, final boolean setMemory, fi // We always add the minVersion tag, which means that the sketch will always try to look for // Java on the system - by default when java isn't embedded, as a fallback when it is jre.addChild("minVersion").setContent("1.7.0_40"); - - switch (arch) { - case AMD64: - jre.addChild("runtimeBits").setContent("64"); - break; - case X86: - jre.addChild("runtimeBits").setContent("32"); - } + jre.addChild("runtimeBits").setContent("64"); if (setMemory) { jre.addChild("initialHeapSize").setContent(Preferences.get("run.options.memory.initial")); From f10fb084ffe78531bc8aeb823f10d2ec9f7625a1 Mon Sep 17 00:00:00 2001 From: Ben Fry Date: Tue, 14 Feb 2023 19:46:34 -0500 Subject: [PATCH 11/21] switch ExportDialog to ExportPrompt --- runtime/src/jycessing/mode/PyEditor.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/runtime/src/jycessing/mode/PyEditor.java b/runtime/src/jycessing/mode/PyEditor.java index 7bd824b8..07dc6f5b 100644 --- a/runtime/src/jycessing/mode/PyEditor.java +++ b/runtime/src/jycessing/mode/PyEditor.java @@ -22,7 +22,6 @@ import jycessing.DisplayType; import jycessing.IOUtil; import jycessing.jni.OSX; -import jycessing.mode.export.ExportDialog; import jycessing.mode.run.PdeSketch; import jycessing.mode.run.PdeSketch.LocationType; import jycessing.mode.run.SketchService; @@ -45,6 +44,7 @@ import processing.app.ui.EditorException; import processing.app.ui.EditorState; import processing.app.ui.EditorToolbar; +import processing.app.ui.ExportPrompt; import processing.app.ui.Toolkit; import processing.core.PApplet; import processing.core.PConstants; @@ -288,7 +288,13 @@ public void handleExportApplication() { } } - new ExportDialog(this, sketch).go(); + //new ExportDialog(this, sketch).go(); + new ExportPrompt(this, new Runnable() { + @Override + public void run() { + // callback after export complete + } + }); } public File getModeContentFile(final String filename) { From f23d5b6c371af3151e451589dfe69317ad72de66 Mon Sep 17 00:00:00 2001 From: Ben Fry Date: Tue, 14 Feb 2023 19:51:21 -0500 Subject: [PATCH 12/21] wire in the exporter and make a few lambdas --- runtime/src/jycessing/mode/PyEditor.java | 64 +++++-------------- .../src/jycessing/mode/export/Exporter.java | 5 +- 2 files changed, 18 insertions(+), 51 deletions(-) diff --git a/runtime/src/jycessing/mode/PyEditor.java b/runtime/src/jycessing/mode/PyEditor.java index 07dc6f5b..bad91b53 100644 --- a/runtime/src/jycessing/mode/PyEditor.java +++ b/runtime/src/jycessing/mode/PyEditor.java @@ -2,13 +2,13 @@ import java.awt.Point; import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; import java.awt.event.MouseWheelEvent; import java.awt.event.MouseWheelListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.File; import java.io.IOException; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.util.UUID; @@ -22,6 +22,7 @@ import jycessing.DisplayType; import jycessing.IOUtil; import jycessing.jni.OSX; +import jycessing.mode.export.Exporter; import jycessing.mode.run.PdeSketch; import jycessing.mode.run.PdeSketch.LocationType; import jycessing.mode.run.SketchService; @@ -49,7 +50,6 @@ import processing.core.PApplet; import processing.core.PConstants; -@SuppressWarnings("serial") public class PyEditor extends Editor { @SuppressWarnings("unused") @@ -108,7 +108,7 @@ public void windowClosing(final WindowEvent e) { @Override protected JEditTextArea createTextArea() { - return new PdeTextArea(new PdeTextAreaDefaults(mode), new PyInputHandler(this), this); + return new PdeTextArea(new PdeTextAreaDefaults(), new PyInputHandler(this), this); } public String getId() { @@ -116,14 +116,11 @@ public String getId() { } private MouseWheelListener createHorizontalScrollListener() { - return new MouseWheelListener() { - @Override - public void mouseWheelMoved(final MouseWheelEvent e) { - if (e.getScrollType() == MouseWheelEvent.WHEEL_UNIT_SCROLL && e.isShiftDown()) { - final int current = textarea.getHorizontalScrollPosition(); - final int delta = e.getUnitsToScroll() * 6; - textarea.setHorizontalScrollPosition(current + delta); - } + return e -> { + if (e.getScrollType() == MouseWheelEvent.WHEEL_UNIT_SCROLL && e.isShiftDown()) { + final int current = textarea.getHorizontalScrollPosition(); + final int delta = e.getUnitsToScroll() * 6; + textarea.setHorizontalScrollPosition(current + delta); } }; } @@ -153,7 +150,7 @@ private void cleanupTempSketch() { log("Deleted " + tempSketch); assert (!tempSketch.toFile().exists()); } catch (final IOException e) { - System.err.println(e); + e.printStackTrace(); } } tempSketch = null; @@ -166,12 +163,7 @@ public JMenu buildFileMenu() { final String appTitle = Language.text("Export Application"); final JMenuItem exportApplication = Toolkit.newJMenuItem(appTitle, 'E'); exportApplication.addActionListener( - new ActionListener() { - @Override - public void actionPerformed(final ActionEvent e) { - handleExportApplication(); - } - }); + e -> handleExportApplication()); return buildFileMenu(new JMenuItem[] {exportApplication}); } @@ -227,31 +219,13 @@ public void actionPerformed(final ActionEvent e) { @Override public JMenu buildSketchMenu() { final JMenuItem runItem = Toolkit.newJMenuItem(Language.text("toolbar.run"), 'R'); - runItem.addActionListener( - new ActionListener() { - @Override - public void actionPerformed(final ActionEvent e) { - handleRun(); - } - }); + runItem.addActionListener(e -> handleRun()); final JMenuItem presentItem = Toolkit.newJMenuItemShift(Language.text("toolbar.present"), 'R'); - presentItem.addActionListener( - new ActionListener() { - @Override - public void actionPerformed(final ActionEvent e) { - handlePresent(); - } - }); + presentItem.addActionListener(e -> handlePresent()); final JMenuItem stopItem = new JMenuItem(Language.text("toolbar.stop")); - stopItem.addActionListener( - new ActionListener() { - @Override - public void actionPerformed(final ActionEvent e) { - handleStop(); - } - }); + stopItem.addActionListener(e -> handleStop()); return buildSketchMenu(new JMenuItem[] {runItem, presentItem, stopItem}); } @@ -289,12 +263,7 @@ public void handleExportApplication() { } //new ExportDialog(this, sketch).go(); - new ExportPrompt(this, new Runnable() { - @Override - public void run() { - // callback after export complete - } - }); + new ExportPrompt(this, () -> new Exporter(PyEditor.this).export()); } public File getModeContentFile(final String filename) { @@ -310,12 +279,11 @@ public File getSplashFile() { * * @return a new directory containing a saved version of the current (presumably modified) sketch * code. - * @throws IOException */ private Path createTempSketch() throws IOException { final Path tmp = Files.createTempDirectory(sketch.getName()); for (final SketchCode code : sketch.getCode()) { - Files.write(tmp.resolve(code.getFileName()), code.getProgram().getBytes("utf-8")); + Files.write(tmp.resolve(code.getFileName()), code.getProgram().getBytes(StandardCharsets.UTF_8)); } return tmp; } @@ -359,7 +327,7 @@ private void runSketch(final DisplayType displayType) { } private void bringToFront() { - if (PApplet.platform == PConstants.MACOSX) { + if (PApplet.platform == PConstants.MACOS) { OSX.bringToFront(pyMode); } } diff --git a/runtime/src/jycessing/mode/export/Exporter.java b/runtime/src/jycessing/mode/export/Exporter.java index e7b7a9e1..fd86f41d 100644 --- a/runtime/src/jycessing/mode/export/Exporter.java +++ b/runtime/src/jycessing/mode/export/Exporter.java @@ -1,6 +1,5 @@ package jycessing.mode.export; -import java.io.File; import java.io.IOException; import java.util.Set; @@ -28,9 +27,9 @@ private static void log(final String msg) { private final Sketch sketch; private final PyEditor editor; - public Exporter(final PyEditor editor, final Sketch sketch) { - this.sketch = sketch; + public Exporter(final PyEditor editor) { this.editor = editor; + this.sketch = editor.getSketch(); } public void export() { From 4ec4dba8a5a33e5392d543bab02d847c00b06e80 Mon Sep 17 00:00:00 2001 From: Ben Fry Date: Tue, 14 Feb 2023 20:03:53 -0500 Subject: [PATCH 13/21] removing extra JNI code, now hoisted to ThinkDifferent in core --- .../src/jycessing/PAppletJythonDriver.java | 4 +- runtime/src/jycessing/jni/OSX.java | 41 ------------------- .../src/jycessing/jni/jniosx/jniosx/jniosx.m | 8 ---- runtime/src/jycessing/jni/jycessing_jni_OSX.h | 21 ---------- runtime/src/jycessing/mode/PyEditor.java | 4 +- 5 files changed, 4 insertions(+), 74 deletions(-) delete mode 100644 runtime/src/jycessing/jni/OSX.java delete mode 100644 runtime/src/jycessing/jni/jniosx/jniosx/jniosx.m delete mode 100644 runtime/src/jycessing/jni/jycessing_jni_OSX.h diff --git a/runtime/src/jycessing/PAppletJythonDriver.java b/runtime/src/jycessing/PAppletJythonDriver.java index 5a127c83..b0a88f96 100755 --- a/runtime/src/jycessing/PAppletJythonDriver.java +++ b/runtime/src/jycessing/PAppletJythonDriver.java @@ -68,7 +68,6 @@ import com.jogamp.newt.opengl.GLWindow; import jycessing.IOUtil.ResourceReader; -import jycessing.jni.OSX; import jycessing.mode.run.WrappedPrintStream; import jycessing.mode.run.WrappedPrintStream.PushedOut; import processing.awt.PSurfaceAWT; @@ -76,6 +75,7 @@ import processing.core.PConstants; import processing.core.PImage; import processing.core.PSurface; +import processing.core.ThinkDifferent; import processing.event.KeyEvent; import processing.event.MouseEvent; import processing.opengl.PGraphicsOpenGL; @@ -908,7 +908,7 @@ public void uncaughtException(final Thread t, final Throwable e) { private void bringToFront() { if (PApplet.platform == PConstants.MACOSX) { - OSX.bringToFront(); + ThinkDifferent.activateIgnoringOtherApps(); } } diff --git a/runtime/src/jycessing/jni/OSX.java b/runtime/src/jycessing/jni/OSX.java deleted file mode 100644 index 0d7c78f2..00000000 --- a/runtime/src/jycessing/jni/OSX.java +++ /dev/null @@ -1,41 +0,0 @@ -package jycessing.jni; - -import jycessing.mode.PythonMode; -import processing.core.PApplet; -import processing.core.PConstants; - -public class OSX { - private static volatile boolean didLoad = false; - - public static void bringToFront() { - if (!didLoad && (PApplet.platform == PConstants.MACOS)) { - try { - System.loadLibrary("jniosx"); - didLoad = true; - } catch (final UnsatisfiedLinkError err) { - System.err.println("Hmm. Can't load native code to bring window to front."); - } - } - if (didLoad) { - activateIgnoringOtherApps(); - } - } - - public static void bringToFront(PythonMode mode) { - if (!didLoad && (PApplet.platform == PConstants.MACOS)) { - String path = null; - try { - path = mode.getContentFile("mode").getAbsolutePath() + "/libjniosx.dylib"; - System.load(path); - didLoad = true; - } catch (final UnsatisfiedLinkError err) { - System.err.println( - "Hmm. Can't load native code to bring window to front using the absolute path: " + path - + "."); - } - } - bringToFront(); - } - - private static native void activateIgnoringOtherApps(); -} diff --git a/runtime/src/jycessing/jni/jniosx/jniosx/jniosx.m b/runtime/src/jycessing/jni/jniosx/jniosx/jniosx.m deleted file mode 100644 index dd58aae4..00000000 --- a/runtime/src/jycessing/jni/jniosx/jniosx/jniosx.m +++ /dev/null @@ -1,8 +0,0 @@ -#include "jycessing_jni_OSX.h" - -#import "AppKit/AppKit.h" - -JNIEXPORT void JNICALL Java_jycessing_jni_OSX_activateIgnoringOtherApps -(JNIEnv *env, jclass klass) { - [NSApp activateIgnoringOtherApps:true]; -} diff --git a/runtime/src/jycessing/jni/jycessing_jni_OSX.h b/runtime/src/jycessing/jni/jycessing_jni_OSX.h deleted file mode 100644 index 79fa36f5..00000000 --- a/runtime/src/jycessing/jni/jycessing_jni_OSX.h +++ /dev/null @@ -1,21 +0,0 @@ -/* DO NOT EDIT THIS FILE - it is machine generated */ -#include -/* Header for class jycessing_jni_OSX */ - -#ifndef _Included_jycessing_jni_OSX -#define _Included_jycessing_jni_OSX -#ifdef __cplusplus -extern "C" { -#endif -/* - * Class: jycessing_jni_OSX - * Method: activateIgnoringOtherApps - * Signature: ()V - */ -JNIEXPORT void JNICALL Java_jycessing_jni_OSX_activateIgnoringOtherApps - (JNIEnv *, jclass); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/runtime/src/jycessing/mode/PyEditor.java b/runtime/src/jycessing/mode/PyEditor.java index bad91b53..cfdfb99a 100644 --- a/runtime/src/jycessing/mode/PyEditor.java +++ b/runtime/src/jycessing/mode/PyEditor.java @@ -21,7 +21,6 @@ import jycessing.DisplayType; import jycessing.IOUtil; -import jycessing.jni.OSX; import jycessing.mode.export.Exporter; import jycessing.mode.run.PdeSketch; import jycessing.mode.run.PdeSketch.LocationType; @@ -49,6 +48,7 @@ import processing.app.ui.Toolkit; import processing.core.PApplet; import processing.core.PConstants; +import processing.core.ThinkDifferent; public class PyEditor extends Editor { @@ -328,7 +328,7 @@ private void runSketch(final DisplayType displayType) { private void bringToFront() { if (PApplet.platform == PConstants.MACOS) { - OSX.bringToFront(pyMode); + ThinkDifferent.activateIgnoringOtherApps(); } } From bd10b89bd696f844fb0b37abac5f1afcd187f4f8 Mon Sep 17 00:00:00 2001 From: Ben Fry Date: Tue, 14 Feb 2023 20:18:24 -0500 Subject: [PATCH 14/21] OS X is now macOS --- build.xml | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/build.xml b/build.xml index 6e721b39..ce03e859 100644 --- a/build.xml +++ b/build.xml @@ -7,7 +7,7 @@ Processing Development Environment and for the standalone processing.py distribution. - This has been tested on Mac OSX and linux. It is not expected to work at + This has been tested on macOS and Linux. It is not expected to work at all on Windows. -jdf @@ -16,7 +16,7 @@ ant test - to run unit tests. ant mode.zip - to create a Python Mode zip file. ant make-all-distributions - to create a processing.py release. - ant -Dplatform=macosx make-distribution - to create the OSX processing.py release. + ant -Dplatform=macos make-distribution - to create the macOS processing.py release. ====================================================================== --> @@ -160,7 +160,7 @@ ${line.separator}and the processing-video library cloned from git." /> @@ -295,7 +295,7 @@ ${line.separator}and the processing-video library cloned from git." /> - + @@ -316,17 +316,10 @@ ${line.separator}and the processing-video library cloned from git." /> - - - - - + @@ -366,7 +359,7 @@ ${line.separator}and the processing-video library cloned from git." /> - + @@ -490,7 +483,7 @@ ${line.separator}and the processing-video library cloned from git." /> @@ -506,7 +499,7 @@ ${line.separator}and the processing-video library cloned from git." /> From 2403d1b2cac78af76aa75a31925ba58bc7ebed85 Mon Sep 17 00:00:00 2001 From: Ben Fry Date: Wed, 15 Feb 2023 20:30:06 -0500 Subject: [PATCH 15/21] clean warnings and using some Java 17 features --- .../src/jycessing/PAppletJythonDriver.java | 297 ++++++++---------- 1 file changed, 124 insertions(+), 173 deletions(-) diff --git a/runtime/src/jycessing/PAppletJythonDriver.java b/runtime/src/jycessing/PAppletJythonDriver.java index b0a88f96..34872d4b 100755 --- a/runtime/src/jycessing/PAppletJythonDriver.java +++ b/runtime/src/jycessing/PAppletJythonDriver.java @@ -20,10 +20,8 @@ import java.awt.event.ComponentAdapter; import java.awt.event.ComponentEvent; import java.io.File; -import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; -import java.lang.Thread.UncaughtExceptionHandler; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; @@ -51,7 +49,6 @@ import org.python.core.PyFunction; import org.python.core.PyIndentationError; import org.python.core.PyInteger; -import org.python.core.PyJavaType; import org.python.core.PyObject; import org.python.core.PyObjectDerived; import org.python.core.PySet; @@ -63,13 +60,12 @@ import org.python.core.PyUnicode; import org.python.util.InteractiveConsole; -import com.google.common.base.Charsets; -import com.google.common.io.Files; import com.jogamp.newt.opengl.GLWindow; import jycessing.IOUtil.ResourceReader; import jycessing.mode.run.WrappedPrintStream; import jycessing.mode.run.WrappedPrintStream.PushedOut; + import processing.awt.PSurfaceAWT; import processing.core.PApplet; import processing.core.PConstants; @@ -82,7 +78,6 @@ import processing.opengl.PShader; import processing.opengl.PSurfaceJOGL; -@SuppressWarnings("serial") public class PAppletJythonDriver extends PApplet { public static final String C_LIKE_LOGICAL_AND_ERROR_MESSAGE = @@ -105,7 +100,7 @@ public class PAppletJythonDriver extends PApplet { private Field frameField; - static private Class fxSurfaceClass; + static private Class fxSurfaceClass; static { try { // Get class object for use in dynamic instanceof calls for PSurfaceFX @@ -265,16 +260,13 @@ private static PythonSketchError toSketchException(Throwable t) { if (t instanceof PythonSketchError) { return (PythonSketchError) t; } - if (t instanceof PySyntaxError) { - final PySyntaxError e = (PySyntaxError) t; + if (t instanceof final PySyntaxError e) { return extractSketchErrorFromPyExceptionValue((PyTuple) e.value); } - if (t instanceof PyIndentationError) { - final PyIndentationError e = (PyIndentationError) t; + if (t instanceof final PyIndentationError e) { return extractSketchErrorFromPyExceptionValue((PyTuple) e.value); } - if (t instanceof PyException) { - final PyException e = (PyException) t; + if (t instanceof final PyException e) { final Pattern tbParse = Pattern.compile("^\\s*File \"([^\"]+)\", line (\\d+)", Pattern.MULTILINE); final Matcher m = tbParse.matcher(e.toString()); @@ -312,8 +304,8 @@ private static PythonSketchError extractSketchErrorFromPyExceptionValue(final Py final PyTuple context = (PyTuple) tup.get(1); final File file = new File((String) context.get(0)); final String fileName = file.getName(); - final int lineNumber = ((Integer) context.get(1)).intValue() - 1; - final int column = ((Integer) context.get(2)).intValue(); + final int lineNumber = (Integer) context.get(1) - 1; + final int column = (Integer) context.get(2); if (pyMessage.startsWith("no viable alternative")) { return noViableAlternative(file, lineNumber, column, pyMessage); } @@ -331,11 +323,6 @@ private static PythonSketchError extractSketchErrorFromPyExceptionValue(final Py * *

This function takes a stab at finding such a thing, and reporting it. Otherwise, it throws a * slightly less cryptic error message. - * - * @param file - * @param lineNo - * @param column - * @return */ private static PythonSketchError noViableAlternative( final File file, final int lineNo, final int column, final String message) { @@ -352,29 +339,24 @@ private static PythonSketchError noViableAlternative( file.getName(), lineNo, column); - try { - int lineIndex = 0; - for (final String line : Files.readLines(file, Charsets.UTF_8)) { - final Matcher m = NAKED_COLOR.matcher(line); - if (m.find()) { - final String color = m.group(1); - return new PythonSketchError( - "Did you try to name a color here? " - + "Colors in Python mode are either strings, like '#" - + color - + "', or " - + "large hex integers, like 0xFF" - + color.toUpperCase() - + ".", - file.getName(), - lineIndex, - m.start(1)); - } - lineIndex++; + int lineIndex = 0; + for (final String line : PApplet.loadStrings(file)) { + final Matcher m = NAKED_COLOR.matcher(line); + if (m.find()) { + final String color = m.group(1); + return new PythonSketchError( + "Did you try to name a color here? " + + "Colors in Python mode are either strings, like '#" + + color + + "', or " + + "large hex integers, like 0xFF" + + color.toUpperCase() + + ".", + file.getName(), + lineIndex, + m.start(1)); } - } catch (final IOException e) { - System.err.println("While trying to read " + file + ": " + e.getMessage()); - return defaultException; + lineIndex++; } return defaultException; } @@ -430,24 +412,15 @@ public void doPrint(final String s) { detectedSmooth = interp.get("__smooth__").asInt() != 0; detectedNoSmooth = interp.get("__noSmooth__").asInt() != 0; final String r = interp.get("__renderer__").asString(); - if (r.equals("JAVA2D")) { - detectedRenderer = JAVA2D; - } else if (r.equals("P2D")) { - detectedRenderer = P2D; - } else if (r.equals("P3D")) { - detectedRenderer = P3D; - } else if (r.equals("OPENGL")) { - detectedRenderer = P3D; - } else if (r.equals("FX2D")) { - detectedRenderer = FX2D; - } else if (r.equals("PDF")) { - detectedRenderer = PDF; - } else if (r.equals("SVG")) { - detectedRenderer = SVG; - } else if (r.equals("DXF")) { - detectedRenderer = DXF; - } else { - detectedRenderer = r; + switch (r) { + case "JAVA2D" -> detectedRenderer = JAVA2D; + case "P2D" -> detectedRenderer = P2D; + case "P3D", "OPENGL" -> detectedRenderer = P3D; + case "FX2D" -> detectedRenderer = FX2D; + case "PDF" -> detectedRenderer = PDF; + case "SVG" -> detectedRenderer = SVG; + case "DXF" -> detectedRenderer = DXF; + default -> detectedRenderer = r; } processedStaticSketch = interp.get("__cleaned_sketch__"); } @@ -489,8 +462,7 @@ protected PSurface initSurface() { } s.setTitle(pySketchPath.getFileName().toString().replaceAll("\\..*$", "")); - if (s instanceof PSurfaceAWT) { - final PSurfaceAWT surf = (PSurfaceAWT) s; + if (s instanceof final PSurfaceAWT surf) { final Component c = (Component) surf.getNative(); c.addComponentListener( new ComponentAdapter() { @@ -514,7 +486,7 @@ public void windowDestroyed(final com.jogamp.newt.event.WindowEvent arg0) { } final PyObject pyG; - if (g instanceof PGraphicsOpenGL) { + if (g instanceof final PGraphicsOpenGL glGraphics) { /* * The name "camera" in PGraphicsOpenGL can refer to either a PMatrix3D field * or a couple of functions of that name. Unfortunately, Python only has one namespace, @@ -535,7 +507,6 @@ public void windowDestroyed(final com.jogamp.newt.event.WindowEvent arg0) { * # read back what we did * print g.cameraMatrix.m02 */ - final PGraphicsOpenGL glGraphics = (PGraphicsOpenGL) g; final PyObject cameraMatrix = Py.java2py(glGraphics.camera); final PyObject cameraInvMatrix = Py.java2py(glGraphics.cameraInv); final PyObject modelviewMatrix = Py.java2py(glGraphics.modelview); @@ -599,16 +570,12 @@ public void method(final String name) { * * @param obj either a {@link PyString} or a {@link PyFunction} to run in a thread. */ + @SuppressWarnings("unused") public void thread(final Object obj) { if (obj instanceof String) { super.thread((String) obj); } else if (obj instanceof PyFunction) { - new Thread() { - @Override - public void run() { - ((PyFunction) obj).__call__(); - } - }.start(); + new Thread(() -> ((PyFunction) obj).__call__()).start(); } } @@ -634,63 +601,63 @@ public void findSketchMethods() throws PythonSketchError { setupMeth = interp.get("setup"); mousePressedFunc = - new EventFunction("mousePressed") { - @Override - protected void callSuper(final MouseEvent event) { - PAppletJythonDriver.super.mousePressed(event); - } - }; + new EventFunction<>("mousePressed") { + @Override + protected void callSuper(final MouseEvent event) { + PAppletJythonDriver.super.mousePressed(event); + } + }; mouseClickedFunc = - new EventFunction("mouseClicked") { - @Override - protected void callSuper(final MouseEvent event) { - PAppletJythonDriver.super.mouseClicked(event); - } - }; + new EventFunction<>("mouseClicked") { + @Override + protected void callSuper(final MouseEvent event) { + PAppletJythonDriver.super.mouseClicked(event); + } + }; mouseMovedFunc = - new EventFunction("mouseMoved") { - @Override - protected void callSuper(final MouseEvent event) { - PAppletJythonDriver.super.mouseMoved(event); - } - }; + new EventFunction<>("mouseMoved") { + @Override + protected void callSuper(final MouseEvent event) { + PAppletJythonDriver.super.mouseMoved(event); + } + }; mouseReleasedFunc = - new EventFunction("mouseReleased") { - @Override - protected void callSuper(final MouseEvent event) { - PAppletJythonDriver.super.mouseReleased(event); - } - }; + new EventFunction<>("mouseReleased") { + @Override + protected void callSuper(final MouseEvent event) { + PAppletJythonDriver.super.mouseReleased(event); + } + }; mouseDraggedFunc = - new EventFunction("mouseDragged") { - @Override - protected void callSuper(final MouseEvent event) { - PAppletJythonDriver.super.mouseDragged(event); - } - }; + new EventFunction<>("mouseDragged") { + @Override + protected void callSuper(final MouseEvent event) { + PAppletJythonDriver.super.mouseDragged(event); + } + }; // keyPressed is renamed to __keyPressed__ by the preprocessor. keyPressedFunc = - new EventFunction("__keyPressed__") { - @Override - protected void callSuper(final KeyEvent event) { - PAppletJythonDriver.super.keyPressed(event); - } - }; + new EventFunction<>("__keyPressed__") { + @Override + protected void callSuper(final KeyEvent event) { + PAppletJythonDriver.super.keyPressed(event); + } + }; keyReleasedFunc = - new EventFunction("keyReleased") { - @Override - protected void callSuper(final KeyEvent event) { - PAppletJythonDriver.super.keyReleased(event); - } - }; + new EventFunction<>("keyReleased") { + @Override + protected void callSuper(final KeyEvent event) { + PAppletJythonDriver.super.keyReleased(event); + } + }; keyTypedFunc = - new EventFunction("keyTyped") { - @Override - protected void callSuper(final KeyEvent event) { - PAppletJythonDriver.super.keyTyped(event); - } - }; + new EventFunction<>("keyTyped") { + @Override + protected void callSuper(final KeyEvent event) { + PAppletJythonDriver.super.keyTyped(event); + } + }; settingsMeth = interp.get("settings"); stopMeth = interp.get("stop"); @@ -737,62 +704,44 @@ public PyObject __call__(final PyObject[] args, final String[] kws) { PyObject meth; if ((meth = interp.get("noteOn")) != null) { switch (argCount(meth)) { - default: - throw new RuntimeException( - "only noteOn(channel, pitch, velocity) or " - + "noteOn(channel, pitch, velocity, timestamp, bus_name) " - + "are supported by Python Mode"); - case 3: - noteOn3Meth = meth; - break; - case 5: - noteOn5Meth = meth; + default -> throw new RuntimeException( + "only noteOn(channel, pitch, velocity) or " + + "noteOn(channel, pitch, velocity, timestamp, bus_name) " + + "are supported by Python Mode"); + case 3 -> noteOn3Meth = meth; + case 5 -> noteOn5Meth = meth; } } if ((meth = interp.get("noteOff")) != null) { switch (argCount(meth)) { - case 1: - throw new RuntimeException( - "only noteOff(channel, pitch, velocity) or " - + "noteOff(channel, pitch, velocity, timestamp, bus_name) " - + "are supported by Python Mode"); - case 3: - noteOff3Meth = meth; - break; - case 5: - noteOff5Meth = meth; + case 1 -> throw new RuntimeException( + "only noteOff(channel, pitch, velocity) or " + + "noteOff(channel, pitch, velocity, timestamp, bus_name) " + + "are supported by Python Mode"); + case 3 -> noteOff3Meth = meth; + case 5 -> noteOff5Meth = meth; } } if ((meth = interp.get("controllerChange")) != null) { switch (argCount(meth)) { - case 1: - throw new RuntimeException( - "only controllerChange(channel, pitch, velocity) or " - + "controllerChange(channel, pitch, velocity, timestamp, bus_name) " - + "are supported by Python Mode"); - case 3: - controllerChange3Meth = meth; - break; - case 5: - controllerChange5Meth = meth; + case 1 -> throw new RuntimeException( + "only controllerChange(channel, pitch, velocity) or " + + "controllerChange(channel, pitch, velocity, timestamp, bus_name) " + + "are supported by Python Mode"); + case 3 -> controllerChange3Meth = meth; + case 5 -> controllerChange5Meth = meth; } } if ((meth = interp.get("rawMidi")) != null) { switch (argCount(meth)) { - case 1: - rawMidi1Meth = meth; - break; - case 3: - rawMidi3Meth = meth; + case 1 -> rawMidi1Meth = meth; + case 3 -> rawMidi3Meth = meth; } } if ((meth = interp.get("midiMessage")) != null) { switch (argCount(meth)) { - case 1: - midiMessage1Meth = meth; - break; - case 3: - midiMessage3Meth = meth; + case 1 -> midiMessage1Meth = meth; + case 3 -> midiMessage3Meth = meth; } } @@ -890,24 +839,20 @@ private void wrapMouseVariables() { public void start() { // I want to quit on runtime exceptions. // Processing just sits there by default. - Thread.setDefaultUncaughtExceptionHandler( - new UncaughtExceptionHandler() { - @Override - public void uncaughtException(final Thread t, final Throwable e) { - terminalException = toSketchException(e); - try { - handleMethods("dispose"); - } catch (final Exception noop) { - // give up - } - finishedLatch.countDown(); - } - }); + Thread.setDefaultUncaughtExceptionHandler((t, e) -> { + terminalException = toSketchException(e); + try { + handleMethods("dispose"); + } catch (final Exception noop) { + // give up + } + finishedLatch.countDown(); + }); super.start(); } private void bringToFront() { - if (PApplet.platform == PConstants.MACOSX) { + if (PApplet.platform == PConstants.MACOS) { ThinkDifferent.activateIgnoringOtherApps(); } } @@ -1024,7 +969,7 @@ private void setSet() { new PyType(PyType.TYPE) { { builtin = true; - init(PySet.class, new HashSet()); + init(PySet.class, new HashSet<>()); invalidateMethodCache(); } @@ -1142,14 +1087,17 @@ public int lerpColor(final int c1, final int c2, final float amt) { * invoke the fill(float) method, unless we provide a long int * version to catch it. */ + @SuppressWarnings("unused") public void fill(final long argb) { fill((int) (argb & 0xFFFFFFFF)); } + @SuppressWarnings("unused") public void stroke(final long argb) { stroke((int) (argb & 0xFFFFFFFF)); } + @SuppressWarnings("unused") public void background(final long argb) { background((int) (argb & 0xFFFFFFFF)); } @@ -1158,14 +1106,17 @@ public void background(final long argb) { * Python can't parse web colors, so we let the user do '#RRGGBB' * as a string. */ + @SuppressWarnings("unused") public void fill(final String argbSpec) { fill(parseColorSpec(argbSpec)); } + @SuppressWarnings("unused") public void stroke(final String argbSpec) { stroke(parseColorSpec(argbSpec)); } + @SuppressWarnings("unused") public void background(final String argbSpec) { background(parseColorSpec(argbSpec)); } From 3e8422cb74d693d202392ee7c0fc187a3f1cebe5 Mon Sep 17 00:00:00 2001 From: Ben Fry Date: Wed, 15 Feb 2023 20:38:34 -0500 Subject: [PATCH 16/21] remove outdated OSXAdapter code, update quit handler --- .../src/jycessing/mode/run/OSXAdapter.java | 233 ------------------ .../src/jycessing/mode/run/SketchRunner.java | 13 +- 2 files changed, 11 insertions(+), 235 deletions(-) delete mode 100644 runtime/src/jycessing/mode/run/OSXAdapter.java diff --git a/runtime/src/jycessing/mode/run/OSXAdapter.java b/runtime/src/jycessing/mode/run/OSXAdapter.java deleted file mode 100644 index fd84d349..00000000 --- a/runtime/src/jycessing/mode/run/OSXAdapter.java +++ /dev/null @@ -1,233 +0,0 @@ -package jycessing.mode.run; - -/* - -File: OSXAdapter.java - -Abstract: Hooks existing preferences/about/quit functionality from an - existing Java app into handlers for the Mac OS X application menu. - Uses a Proxy object to dynamically implement the - com.apple.eawt.ApplicationListener interface and register it with the - com.apple.eawt.Application object. This allows the complete project - to be both built and run on any platform without any stubs or - placeholders. Useful for developers looking to implement Mac OS X - features while supporting multiple platforms with minimal impact. - -Version: 2.0 - -Disclaimer: IMPORTANT: This Apple software is supplied to you by -Apple Inc. ("Apple") in consideration of your agreement to the -following terms, and your use, installation, modification or -redistribution of this Apple software constitutes acceptance of these -terms. If you do not agree with these terms, please do not use, -install, modify or redistribute this Apple software. - -In consideration of your agreement to abide by the following terms, and -subject to these terms, Apple grants you a personal, non-exclusive -license, under Apple's copyrights in this original Apple software (the -"Apple Software"), to use, reproduce, modify and redistribute the Apple -Software, with or without modifications, in source and/or binary forms; -provided that if you redistribute the Apple Software in its entirety and -without modifications, you must retain this notice and the following -text and disclaimers in all such redistributions of the Apple Software. -Neither the name, trademarks, service marks or logos of Apple Inc. -may be used to endorse or promote products derived from the Apple -Software without specific prior written permission from Apple. Except -as expressly stated in this notice, no other rights or licenses, express -or implied, are granted by Apple herein, including but not limited to -any patent rights that may be infringed by your derivative works or by -other works in which the Apple Software may be incorporated. - -The Apple Software is provided by Apple on an "AS IS" basis. APPLE -MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION -THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS -FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND -OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. - -IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL -OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, -MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED -AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), -STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -Copyright (C) 2003-2007 Apple, Inc., All Rights Reserved - -*/ - -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; - -public class OSXAdapter implements InvocationHandler { - - protected Object targetObject; - protected Method targetMethod; - protected String proxySignature; - - static Object macOSXApplication; - - // Pass this method an Object and Method equipped to perform application shutdown logic - // The method passed should return a boolean stating whether or not the quit should occur - public static void setQuitHandler(final Object target, final Method quitHandler) { - setHandler(new OSXAdapter("handleQuit", target, quitHandler)); - } - - // Pass this method an Object and Method equipped to display application info - // They will be called when the About menu item is selected from the application menu - public static void setAboutHandler(final Object target, final Method aboutHandler) { - final boolean enableAboutMenu = (target != null && aboutHandler != null); - if (enableAboutMenu) { - setHandler(new OSXAdapter("handleAbout", target, aboutHandler)); - } - // If we're setting a handler, enable the About menu item by calling - // com.apple.eawt.Application reflectively - try { - final Method enableAboutMethod = - macOSXApplication - .getClass() - .getDeclaredMethod("setEnabledAboutMenu", new Class[] {boolean.class}); - enableAboutMethod.invoke(macOSXApplication, new Object[] {Boolean.valueOf(enableAboutMenu)}); - } catch (final Exception ex) { - System.err.println("OSXAdapter could not access the About Menu"); - ex.printStackTrace(); - } - } - - // Pass this method an Object and a Method equipped to display application options - // They will be called when the Preferences menu item is selected from the application menu - public static void setPreferencesHandler(final Object target, final Method prefsHandler) { - final boolean enablePrefsMenu = (target != null && prefsHandler != null); - if (enablePrefsMenu) { - setHandler(new OSXAdapter("handlePreferences", target, prefsHandler)); - } - // If we're setting a handler, enable the Preferences menu item by calling - // com.apple.eawt.Application reflectively - try { - final Method enablePrefsMethod = - macOSXApplication - .getClass() - .getDeclaredMethod("setEnabledPreferencesMenu", new Class[] {boolean.class}); - enablePrefsMethod.invoke(macOSXApplication, new Object[] {Boolean.valueOf(enablePrefsMenu)}); - } catch (final Exception ex) { - System.err.println("OSXAdapter could not access the About Menu: " + ex); - } - } - - // Pass this method an Object and a Method equipped to handle document events from the Finder - // Documents are registered with the Finder via the CFBundleDocumentTypes dictionary in the - // application bundle's Info.plist - public static void setFileHandler(final Object target, final Method fileHandler) { - setHandler( - new OSXAdapter("handleOpenFile", target, fileHandler) { - // Override OSXAdapter.callTarget to send information on the - // file to be opened - @Override - public boolean callTarget(final Object appleEvent) { - if (appleEvent != null) { - try { - final Method getFilenameMethod = - appleEvent.getClass().getDeclaredMethod("getFilename", (Class[]) null); - final String filename = - (String) getFilenameMethod.invoke(appleEvent, (Object[]) null); - this.targetMethod.invoke(this.targetObject, new Object[] {filename}); - } catch (final Exception ex) { - - } - } - return true; - } - }); - } - - // setHandler creates a Proxy object from the passed OSXAdapter and adds it as an - // ApplicationListener - public static void setHandler(final OSXAdapter adapter) { - try { - final Class applicationClass = Class.forName("com.apple.eawt.Application"); - if (macOSXApplication == null) { - macOSXApplication = - applicationClass.getConstructor((Class[]) null).newInstance((Object[]) null); - } - final Class applicationListenerClass = Class.forName("com.apple.eawt.ApplicationListener"); - final Method addListenerMethod = - applicationClass.getDeclaredMethod( - "addApplicationListener", new Class[] {applicationListenerClass}); - // Create a proxy object around this handler that can be reflectively added as an Apple - // ApplicationListener - final Object osxAdapterProxy = - Proxy.newProxyInstance( - OSXAdapter.class.getClassLoader(), new Class[] {applicationListenerClass}, adapter); - addListenerMethod.invoke(macOSXApplication, new Object[] {osxAdapterProxy}); - } catch (final ClassNotFoundException cnfe) { - System.err.println( - "This version of Mac OS X does not support the Apple EAWT. ApplicationEvent handling has been disabled (" - + cnfe - + ")"); - } catch (final Exception ex) { // Likely a NoSuchMethodException or an IllegalAccessException - // loading/invoking eawt.Application methods - System.err.println("Mac OS X Adapter could not talk to EAWT:" + ex); - } - } - - // Each OSXAdapter has the name of the EAWT method it intends to listen for (handleAbout, for - // example), - // the Object that will ultimately perform the task, and the Method to be called on that Object - protected OSXAdapter(final String proxySignature, final Object target, final Method handler) { - this.proxySignature = proxySignature; - this.targetObject = target; - this.targetMethod = handler; - } - - // Override this method to perform any operations on the event - // that comes with the various callbacks - // See setFileHandler above for an example - public boolean callTarget(final Object appleEvent) - throws InvocationTargetException, IllegalAccessException { - final Object result = targetMethod.invoke(targetObject, (Object[]) null); - if (result == null) { - return true; - } - return Boolean.valueOf(result.toString()).booleanValue(); - } - - // InvocationHandler implementation - // This is the entry point for our proxy object; it is called every time an ApplicationListener - // method is invoked - @Override - public Object invoke(final Object proxy, final Method method, final Object[] args) - throws Throwable { - if (isCorrectMethod(method, args)) { - final boolean handled = callTarget(args[0]); - setApplicationEventHandled(args[0], handled); - } - // All of the ApplicationListener methods are void; return null regardless of what happens - return null; - } - - // Compare the method that was called to the intended method when the OSXAdapter instance was - // created - // (e.g. handleAbout, handleQuit, handleOpenFile, etc.) - protected boolean isCorrectMethod(final Method method, final Object[] args) { - return (targetMethod != null && proxySignature.equals(method.getName()) && args.length == 1); - } - - // It is important to mark the ApplicationEvent as handled and cancel the default behavior - // This method checks for a boolean result from the proxy method and sets the event accordingly - protected void setApplicationEventHandled(final Object event, final boolean handled) { - if (event != null) { - try { - final Method setHandledMethod = - event.getClass().getDeclaredMethod("setHandled", new Class[] {boolean.class}); - // If the target method returns a boolean, use that as a hint - setHandledMethod.invoke(event, new Object[] {Boolean.valueOf(handled)}); - } catch (final Exception ex) { - System.err.println("OSXAdapter was unable to handle an ApplicationEvent: " + event); - ex.printStackTrace(); - } - } - } -} diff --git a/runtime/src/jycessing/mode/run/SketchRunner.java b/runtime/src/jycessing/mode/run/SketchRunner.java index cb79df20..67286929 100644 --- a/runtime/src/jycessing/mode/run/SketchRunner.java +++ b/runtime/src/jycessing/mode/run/SketchRunner.java @@ -1,5 +1,6 @@ package jycessing.mode.run; +import java.awt.Desktop; import java.rmi.RemoteException; import jycessing.Printer; @@ -8,6 +9,7 @@ import jycessing.SketchPositionListener; import jycessing.mode.PythonMode; import jycessing.mode.run.RMIUtils.RMIProblem; +import processing.app.Platform; import processing.app.SketchException; import processing.core.PApplet; import processing.core.PConstants; @@ -28,9 +30,16 @@ private static void log(final String msg) { public SketchRunner(final String id, final ModeService modeService) { this.id = id; this.modeService = modeService; - if (PApplet.platform == PConstants.MACOSX) { + if (Platform.isMacOS()) { + //OSXAdapter.setQuitHandler(this, this.getClass().getMethod("preventUserQuit")); try { - OSXAdapter.setQuitHandler(this, this.getClass().getMethod("preventUserQuit")); + Desktop.getDesktop().setQuitHandler((event, quitResponse) -> { + if (preventUserQuit()) { + quitResponse.performQuit(); + } else { + quitResponse.cancelQuit(); + } + }); } catch (final Throwable e) { System.err.println(e.getMessage()); } From 82c715fff80762c90af69ac58c42a69f2252534c Mon Sep 17 00:00:00 2001 From: Ben Fry Date: Wed, 15 Feb 2023 20:51:32 -0500 Subject: [PATCH 17/21] lambdas and a little cleaning --- runtime/src/jycessing/mode/run/RMIUtils.java | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/runtime/src/jycessing/mode/run/RMIUtils.java b/runtime/src/jycessing/mode/run/RMIUtils.java index a096b6bf..5cfdf987 100644 --- a/runtime/src/jycessing/mode/run/RMIUtils.java +++ b/runtime/src/jycessing/mode/run/RMIUtils.java @@ -1,6 +1,5 @@ package jycessing.mode.run; -import java.io.IOException; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; @@ -19,19 +18,10 @@ public class RMIUtils { static final int RMI_PORT = 8220; - private static final RMIClientSocketFactory clientFactory = new RMIClientSocketFactory() { - @Override - public Socket createSocket(final String host, final int port) throws IOException { - return new Socket(host, port); - } - }; + private static final RMIClientSocketFactory clientFactory = Socket::new; - private static final RMIServerSocketFactory serverFactory = new RMIServerSocketFactory() { - @Override - public ServerSocket createServerSocket(final int port) throws IOException { - return new ServerSocket(port, 50, InetAddress.getLoopbackAddress()); - } - }; + private static final RMIServerSocketFactory serverFactory = + port -> new ServerSocket(port, 50, InetAddress.getLoopbackAddress()); static { System.setProperty("sun.rmi.transport.tcp.localHostNameTimeOut", "1000"); @@ -90,7 +80,7 @@ public static void bind(final Remote remote, final Class remot try { log("Unbinding " + registryKey + " from registry."); registry().unbind(registryKey); - } catch (final Exception e) { + } catch (final Exception ignored) { } })); } catch (final Exception e) { From 2557b685a83a0f15877cc41a1cd8f5ba82764da7 Mon Sep 17 00:00:00 2001 From: Ben Fry Date: Tue, 21 Feb 2023 05:55:18 -0500 Subject: [PATCH 18/21] minor tweaks for warnings --- runtime/src/jycessing/Runner.java | 4 ++-- runtime/src/jycessing/mode/run/SketchRunner.java | 13 ++++++------- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/runtime/src/jycessing/Runner.java b/runtime/src/jycessing/Runner.java index 29d3b712..1f395738 100755 --- a/runtime/src/jycessing/Runner.java +++ b/runtime/src/jycessing/Runner.java @@ -53,7 +53,7 @@ public class Runner { static { final int archBits = Integer.parseInt(System.getProperty("sun.arch.data.model")); - if (PApplet.platform == PConstants.MACOSX) { + if (PApplet.platform == PConstants.MACOS) { ARCH = "macosx" + archBits; } else if (PApplet.platform == PConstants.WINDOWS) { ARCH = "macosx" + archBits; @@ -89,7 +89,7 @@ static void log(final Object... objs) { return; } for (final Object o : objs) { - System.err.print(String.valueOf(o)); + System.err.print(o); } System.err.println(); } diff --git a/runtime/src/jycessing/mode/run/SketchRunner.java b/runtime/src/jycessing/mode/run/SketchRunner.java index 67286929..0a274d5f 100644 --- a/runtime/src/jycessing/mode/run/SketchRunner.java +++ b/runtime/src/jycessing/mode/run/SketchRunner.java @@ -3,16 +3,15 @@ import java.awt.Desktop; import java.rmi.RemoteException; +import processing.app.Platform; +import processing.app.SketchException; + import jycessing.Printer; import jycessing.PythonSketchError; import jycessing.Runner; import jycessing.SketchPositionListener; import jycessing.mode.PythonMode; import jycessing.mode.run.RMIUtils.RMIProblem; -import processing.app.Platform; -import processing.app.SketchException; -import processing.core.PApplet; -import processing.core.PConstants; public class SketchRunner implements SketchService { @@ -44,7 +43,7 @@ public SketchRunner(final String id, final ModeService modeService) { System.err.println(e.getMessage()); } } - new Thread(() -> Runner.warmup(), "SketchRunner Warmup Thread").start(); + new Thread(Runner::warmup, "SketchRunner Warmup Thread").start(); } /** @@ -66,7 +65,7 @@ public boolean preventUserQuit() { return true; } log("Cancelling quit, but stopping sketch."); - new Thread(() -> stopSketch()).start(); + new Thread(this::stopSketch).start(); return false; } @@ -77,7 +76,7 @@ public void shutdown() { System.exit(0); } - private abstract class RemotePrinter implements Printer { + private abstract static class RemotePrinter implements Printer { abstract protected void doPrint(String s) throws RemoteException; public void print(final Object o) { From ad0fc22c54e48514ca8c5baf034ef725bf8832d2 Mon Sep 17 00:00:00 2001 From: Ben Fry Date: Tue, 21 Feb 2023 07:10:54 -0500 Subject: [PATCH 19/21] one typo, one IntelliJ fussing about grammar --- runtime/src/jycessing/Runner.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/runtime/src/jycessing/Runner.java b/runtime/src/jycessing/Runner.java index 1f395738..8fac8e0d 100755 --- a/runtime/src/jycessing/Runner.java +++ b/runtime/src/jycessing/Runner.java @@ -337,7 +337,7 @@ public static synchronized void runSketchBlocking( interp.exec("import sys\n"); - // Add all of the sketch's requested sys.path entries, and add all jar + // Add all the sketch's requested sys.path entries, and add all jar // files found there, recursively. final Set userLibs = new TreeSet<>(); for (final File entry : sketch.getPathEntries()) { @@ -351,7 +351,7 @@ public static synchronized void runSketchBlocking( new LibraryImporter(libDirs, interp); if (sketch.getLibraryPolicy() == LibraryPolicy.PROMISCUOUS) { - log("Promiscusouly adding all libraries in " + libDirs); + log("Promiscuously adding all libraries in " + libDirs); // Recursively search the "libraries" directory for jar files and // directories containing dynamic libraries. final Set libs = new HashSet<>(); From b798afa91a7d360bb2fcdba684a2c1310938f988 Mon Sep 17 00:00:00 2001 From: Ben Fry Date: Tue, 21 Feb 2023 07:15:19 -0500 Subject: [PATCH 20/21] using native full screen because hiding menu bar not working --- .../src/jycessing/PAppletJythonDriver.java | 75 +++++++++---------- 1 file changed, 35 insertions(+), 40 deletions(-) diff --git a/runtime/src/jycessing/PAppletJythonDriver.java b/runtime/src/jycessing/PAppletJythonDriver.java index 34872d4b..e5a4cbf7 100755 --- a/runtime/src/jycessing/PAppletJythonDriver.java +++ b/runtime/src/jycessing/PAppletJythonDriver.java @@ -15,19 +15,17 @@ import java.awt.Component; import java.awt.Frame; +import java.awt.GraphicsDevice; import java.awt.Point; -import java.awt.Window; import java.awt.event.ComponentAdapter; import java.awt.event.ComponentEvent; import java.io.File; import java.io.PrintWriter; import java.io.StringWriter; import java.lang.reflect.Field; -import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.nio.file.Path; import java.nio.file.Paths; -import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.Map; @@ -340,23 +338,28 @@ private static PythonSketchError noViableAlternative( lineNo, column); int lineIndex = 0; - for (final String line : PApplet.loadStrings(file)) { - final Matcher m = NAKED_COLOR.matcher(line); - if (m.find()) { - final String color = m.group(1); - return new PythonSketchError( + String[] lines = PApplet.loadStrings(file); + if (lines != null) { + for (final String line : lines) { + final Matcher m = NAKED_COLOR.matcher(line); + if (m.find()) { + final String color = m.group(1); + return new PythonSketchError( "Did you try to name a color here? " - + "Colors in Python mode are either strings, like '#" - + color - + "', or " - + "large hex integers, like 0xFF" - + color.toUpperCase() - + ".", + + "Colors in Python mode are either strings, like '#" + + color + + "', or " + + "large hex integers, like 0xFF" + + color.toUpperCase() + + ".", file.getName(), lineIndex, m.start(1)); + } + lineIndex++; } - lineIndex++; + } else { + System.err.println("Could not read " + file); } return defaultException; } @@ -411,6 +414,7 @@ public void doPrint(final String s) { detectedPixelDensity = interp.get("__pixelDensity__").asInt(); detectedSmooth = interp.get("__smooth__").asInt() != 0; detectedNoSmooth = interp.get("__noSmooth__").asInt() != 0; + detectedFullScreen = interp.get("__fullScreen__").asInt() != 0; // TODO does not work [fry 230221] final String r = interp.get("__renderer__").asString(); switch (r) { case "JAVA2D" -> detectedRenderer = JAVA2D; @@ -471,8 +475,7 @@ public void componentHidden(final ComponentEvent e) { finishedLatch.countDown(); } }); - } else if (s instanceof PSurfaceJOGL) { - final PSurfaceJOGL surf = (PSurfaceJOGL) s; + } else if (s instanceof final PSurfaceJOGL surf) { final GLWindow win = (GLWindow) surf.getNative(); win.addWindowListener( new com.jogamp.newt.event.WindowAdapter() { @@ -851,15 +854,22 @@ public void start() { super.start(); } - private void bringToFront() { + + public void runAndBlock(final String[] args) throws PythonSketchError { + PApplet.runSketch(args, this); + + // bring the sketch to the front if (PApplet.platform == PConstants.MACOS) { ThinkDifferent.activateIgnoringOtherApps(); } - } - public void runAndBlock(final String[] args) throws PythonSketchError { - PApplet.runSketch(args, this); - bringToFront(); + if (detectedFullScreen) { + if (surface instanceof PSurfaceAWT) { + Frame frame = ((PSurfaceAWT.SmoothCanvas) surface.getNative()).getFrame(); + GraphicsDevice displayDevice = frame.getGraphicsConfiguration().getDevice(); + displayDevice.setFullScreenWindow(frame); + } + } try { finishedLatch.await(); @@ -886,6 +896,8 @@ public void runAndBlock(final String[] args) throws PythonSketchError { maybeShutdownSoundEngine(); Thread.setDefaultUncaughtExceptionHandler(null); + + /* if (PApplet.platform == PConstants.MACOS && Arrays.asList(args).contains("fullScreen")) { // Frame should be OS-X fullscreen, and it won't stop being that unless the jvm // exits or we explicitly tell it to minimize. @@ -901,6 +913,7 @@ public void runAndBlock(final String[] args) throws PythonSketchError { } } } + */ if (fxSurfaceClass != null && fxSurfaceClass.isInstance(surface)) { // Sadly, JavaFX is an abomination, and there's no way to run an FX sketch more than once, // so we must actually exit. @@ -939,24 +952,6 @@ private void maybeShutdownSoundEngine() { } } - /** - * Use reflection to call - * com.apple.eawt.Application.getApplication().requestToggleFullScreen(window); - */ - private static void macosxFullScreenToggle(final Window window) { - try { - final Class appClass = Class.forName("com.apple.eawt.Application"); - final Method getAppMethod = appClass.getMethod("getApplication"); - final Object app = getAppMethod.invoke(null); - final Method requestMethod = appClass.getMethod("requestToggleFullScreen", Window.class); - requestMethod.invoke(app, window); - } catch (final ClassNotFoundException cnfe) { - // ignored - } catch (final Exception e) { - e.printStackTrace(); - } - } - /** * Permit the punning use of set() by mucking with the builtin "set" Type. If you call it with 3 * arguments, it acts like the Processing set(x, y, whatever) method. If you call it with 0 or 1 From a21df583b01d903a3e5d995c223901529ff430be Mon Sep 17 00:00:00 2001 From: Jonathan Feinberg Date: Sun, 5 Mar 2023 15:40:14 -0500 Subject: [PATCH 21/21] idea stuff --- .idea/.gitignore | 3 +++ .idea/ant.xml | 6 ++++++ .idea/misc.xml | 6 ++++++ .idea/vcs.xml | 6 ++++++ 4 files changed, 21 insertions(+) create mode 100644 .idea/.gitignore create mode 100644 .idea/ant.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/vcs.xml diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 00000000..26d33521 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/.idea/ant.xml b/.idea/ant.xml new file mode 100644 index 00000000..a2a47698 --- /dev/null +++ b/.idea/ant.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 00000000..ebc8004b --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 00000000..35eb1ddf --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file