diff --git a/.idea/artifacts/app_jvm_1_0_SNAPSHOT.xml b/.idea/artifacts/app_jvm_1_0_SNAPSHOT.xml
new file mode 100644
index 0000000..72b19be
--- /dev/null
+++ b/.idea/artifacts/app_jvm_1_0_SNAPSHOT.xml
@@ -0,0 +1,6 @@
+
+
+ $PROJECT_DIR$/app/build/libs
+
+
+
\ No newline at end of file
diff --git a/.idea/runConfigurations/Processing.xml b/.idea/runConfigurations/Processing.xml
index 1691f58..034ebd1 100644
--- a/.idea/runConfigurations/Processing.xml
+++ b/.idea/runConfigurations/Processing.xml
@@ -1,11 +1,6 @@
-
diff --git a/.idea/uiDesigner.xml b/.idea/uiDesigner.xml
new file mode 100644
index 0000000..2b63946
--- /dev/null
+++ b/.idea/uiDesigner.xml
@@ -0,0 +1,124 @@
+
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+
+
+
\ No newline at end of file
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 94c42fa..4742873 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -1,13 +1,24 @@
+import org.gradle.nativeplatform.platform.internal.DefaultNativePlatform
+import org.jetbrains.compose.desktop.application.dsl.TargetFormat
+import de.undercouch.gradle.tasks.download.Download
+
plugins {
id("java")
- id("application")
- id("io.github.fvarrui.javapackager.plugin")
+ id("de.undercouch.download") version "5.6.0"
+ kotlin("jvm") version "1.9.23"
+ id("org.jetbrains.compose") version "1.6.11"
}
-group = "org.example"
-version = "1.0-SNAPSHOT"
+group = rootProject.name
+version = rootProject.version
+
+kotlin {
+ jvmToolchain(21)
+}
repositories {
+ maven("https://plugins.gradle.org/m2/" )
+ google()
mavenCentral()
maven { url = uri("https://jogamp.org/deployment/maven") }
}
@@ -15,21 +26,11 @@ repositories {
sourceSets{
main{
resources{
- srcDirs("src/main/java/")
+ srcDirs("src/main/java/","../shared")
}
}
}
-application {
- mainClass = "processing.app.ui.Splash"
-}
-
-javapackager {
- mainClass("processing.app.ui.Splash")
- bundleJre(true)
- additionalResources(files("../shared").toMutableList())
-}
-
dependencies {
implementation("com.formdev:flatlaf:3.4.1")
@@ -41,6 +42,15 @@ dependencies {
testImplementation(platform("org.junit:junit-bom:5.9.1"))
testImplementation("org.junit.jupiter:junit-jupiter")
+
+ implementation(compose.runtime)
+ implementation(compose.foundation)
+ implementation(compose.material)
+ implementation(compose.ui)
+ implementation(compose.components.resources)
+ implementation(compose.components.uiToolingPreview)
+
+ implementation(compose.desktop.currentOs)
}
tasks.test {
diff --git a/app/src/main/java/processing/app/Platform.java b/app/src/main/java/processing/app/Platform.java
index 33233b3..051450b 100644
--- a/app/src/main/java/processing/app/Platform.java
+++ b/app/src/main/java/processing/app/Platform.java
@@ -28,10 +28,9 @@
import java.lang.management.ManagementFactory;
import java.net.URISyntaxException;
import java.net.URL;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.nio.file.*;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.*;
import com.sun.jna.platform.FileUtils;
@@ -320,23 +319,70 @@ static public boolean isLinux() {
* or inside Contents/Resources/Java on Mac OS X. This will return the local
* JRE location, *whether it is the active JRE*.
*/
+ static File tempFolder;
+
@Deprecated
static public File getContentFile(String name) {
var url = Platform.class.getClassLoader().getResource("defaults.txt");
if(url == null) Messages.showError("Missing defaults.txt", "Could not find the main resource file", new Exception(""));
- if(!url.toString().startsWith("jar")){
+ var urlString = url.toString();
+ if(!urlString.startsWith("jar")){
var path = url.getPath();
var parent = new File(path).getParent();
var removeLib = name.replace("lib","");
return new File(parent, removeLib);
}
- return new File(System.getProperty("user.dir"),name.replace("lib",""));
+ if(tempFolder == null){
+ try {
+ tempFolder = Files.createTempDirectory("processing").toFile();
+ copyFromJar("/", tempFolder.toPath());
+ } catch (IOException | URISyntaxException e) {
+ e.printStackTrace();
+ }
+ }
+
+ return new File(tempFolder,name.replace("lib",""));
}
+ public static void copyFromJar(String source, final Path target) throws URISyntaxException, IOException {
+ var resource = Platform.class.getResource("").toURI();
+ var fileSystem = FileSystems.newFileSystem(
+ resource,
+ Collections.emptyMap()
+ );
+
+
+ final Path jarPath = fileSystem.getPath(source);
+ Files.walkFileTree(jarPath, new SimpleFileVisitor() {
+
+ private Path currentTarget;
+
+ @Override
+ public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
+ currentTarget = target.resolve(jarPath.relativize(dir).toString());
+ Files.createDirectories(currentTarget);
+ return FileVisitResult.CONTINUE;
+ }
+
+ @Override
+ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
+ Files.copy(file, target.resolve(jarPath.relativize(file).toString()), StandardCopyOption.REPLACE_EXISTING);
+ return FileVisitResult.CONTINUE;
+ }
+
+ });
+ }
static public File getJavaHome() {
- return new File(System.getProperty("java.home"));
+ var home = System.getProperty("java.home");
+ var resourceHome = getContentFile(("lib/jdk/Contents/Home"));
+ var resoucesCompose = System.getProperty("compose.application.resources.dir");
+ var exists = resourceHome.exists();
+ if(exists){
+ return resourceHome;
+ }
+ return new File(home);
}
diff --git a/app/src/main/java/processing/app/ui/Editor.java b/app/src/main/java/processing/app/ui/Editor.java
index 0dd133d..ab2b758 100644
--- a/app/src/main/java/processing/app/ui/Editor.java
+++ b/app/src/main/java/processing/app/ui/Editor.java
@@ -71,6 +71,8 @@
import processing.app.syntax.*;
import processing.core.*;
+import static org.processing.test.ComposeHelloWorldKt.Start;
+
/**
* Main editor panel for the Processing Development Environment.
@@ -218,6 +220,8 @@ public void windowDeactivated(WindowEvent e) {
Box box = Box.createVerticalBox();
Box upper = Box.createVerticalBox();
+ Start(upper);
+
rebuildModePopup();
toolbar = createToolbar();
upper.add(toolbar);
diff --git a/app/src/main/kotlin/ComposeHelloWorld.kt b/app/src/main/kotlin/ComposeHelloWorld.kt
new file mode 100644
index 0000000..0262a40
--- /dev/null
+++ b/app/src/main/kotlin/ComposeHelloWorld.kt
@@ -0,0 +1,90 @@
+package org.processing.test
+
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.padding
+import androidx.compose.material.Button
+import androidx.compose.material.ExperimentalMaterialApi
+import androidx.compose.material.Surface
+import androidx.compose.material.Text
+import androidx.compose.runtime.*
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.awt.ComposePanel
+import androidx.compose.ui.geometry.Size
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.drawscope.DrawScope
+import androidx.compose.ui.graphics.painter.Painter
+import androidx.compose.ui.input.key.Key
+import androidx.compose.ui.input.key.KeyShortcut
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.window.MenuBar
+import androidx.compose.ui.window.Window
+import androidx.compose.ui.window.application
+import java.awt.BorderLayout
+import javax.swing.Box
+import javax.swing.SwingUtilities
+
+@OptIn(ExperimentalMaterialApi::class)
+@Composable
+fun ComposeHelloWorld() {
+ var open by remember { mutableStateOf(false) }
+ Text("Hello, World from Jetpack Compose!", modifier = Modifier.clickable { open = !open })
+ if(!open) return
+ var isSubmenuShowing by remember { mutableStateOf(false) }
+ var action by remember { mutableStateOf("Last action: None") }
+ var isOpen by remember { mutableStateOf(true) }
+
+ Window(onCloseRequest = {
+ open = false
+ }, title = "Processing") {
+ MenuBar {
+ Menu("File", mnemonic = 'F') {
+ Item("Copy", onClick = { action = "Last action: Copy" }, shortcut = KeyShortcut(Key.C, ctrl = true))
+ Item(
+ "Paste",
+ onClick = { action = "Last action: Paste" },
+ shortcut = KeyShortcut(Key.V, ctrl = true)
+ )
+ }
+ Menu("Actions", mnemonic = 'A') {
+ CheckboxItem(
+ "Advanced settings",
+ checked = isSubmenuShowing,
+ onCheckedChange = {
+ isSubmenuShowing = !isSubmenuShowing
+ }
+ )
+ if (isSubmenuShowing) {
+ Menu("Settings") {
+ Item("Setting 1", onClick = { action = "Last action: Setting 1" })
+ Item("Setting 2", onClick = { action = "Last action: Setting 2" })
+ }
+ }
+ Separator()
+ Item("About", icon = AboutIcon, onClick = { action = "Last action: About" })
+ Item("Exit", onClick = { isOpen = false }, shortcut = KeyShortcut(Key.Escape), mnemonic = 'E')
+ }
+ }
+ Text("Hello, World!", modifier = Modifier.padding(16.dp))
+ }
+}
+object AboutIcon : Painter() {
+ override val intrinsicSize = Size(256f, 256f)
+
+ override fun DrawScope.onDraw() {
+ drawOval(Color(0xFFFFA500))
+ }
+}
+
+fun Start(box: Box){
+ SwingUtilities.invokeLater {
+ val composePanel = ComposePanel().apply {
+ setContent {
+ ComposeHelloWorld()
+ }
+ }
+ box.apply {
+ add(composePanel, BorderLayout.CENTER)
+ }
+ }
+}
\ No newline at end of file
diff --git a/build.gradle.kts b/build.gradle.kts
index 8b7bece..54df890 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -1,8 +1,11 @@
plugins {
id("java")
+ kotlin("jvm") version "1.9.23"
+ id("org.jetbrains.compose") version "1.6.11" apply false
}
group = "org.processing"
+version = "4.4.0"
repositories {
mavenCentral()
diff --git a/core/build.gradle.kts b/core/build.gradle.kts
index c5b2b36..af18f0c 100644
--- a/core/build.gradle.kts
+++ b/core/build.gradle.kts
@@ -4,8 +4,8 @@ plugins {
kotlin("jvm") version "1.9.23"
}
-group = "org.example"
-version = "1.0-SNAPSHOT"
+group = rootProject.group
+version = rootProject.version
repositories {
mavenCentral()
diff --git a/java/build.gradle.kts b/java/build.gradle.kts
index 6984f2a..dbe40b4 100644
--- a/java/build.gradle.kts
+++ b/java/build.gradle.kts
@@ -1,15 +1,14 @@
-
-
plugins {
id("java")
- id("application")
id("antlr")
}
-group = "org.processing"
-version = "4.4"
+group = rootProject.group
+version = rootProject.version
repositories {
+ maven("https://maven.pkg.jetbrains.space/public/p/compose/dev")
+ google()
mavenCentral()
maven { url = uri("https://jogamp.org/deployment/maven") }
}
@@ -17,7 +16,6 @@ repositories {
dependencies {
implementation("com.google.classpath-explorer:classpath-explorer:1.0")
-// implementation("org.antlr:antlr4-runtime:4.13.1")
implementation("org.netbeans.api:org-netbeans-swing-outline:RELEASE210")
implementation("org.apache.ant:ant:1.10.14")
implementation("org.eclipse.lsp4j:org.eclipse.lsp4j:0.22.0")
diff --git a/package/assets/linux/processing.icns b/package/assets/linux/processing.icns
new file mode 100644
index 0000000..cb42dad
Binary files /dev/null and b/package/assets/linux/processing.icns differ
diff --git a/package/build.gradle.kts b/package/build.gradle.kts
index 9ac687a..aed1014 100644
--- a/package/build.gradle.kts
+++ b/package/build.gradle.kts
@@ -1,75 +1,49 @@
import de.undercouch.gradle.tasks.download.Download
-import io.github.fvarrui.javapackager.model.FileAssociation
+import org.gradle.nativeplatform.platform.internal.DefaultNativePlatform
+import org.jetbrains.compose.desktop.application.dsl.TargetFormat
plugins {
id("java")
- id("application")
- id("io.github.fvarrui.javapackager.plugin")
id("de.undercouch.download") version "5.6.0"
+ kotlin("jvm") version "1.9.23"
+ id("org.jetbrains.compose") version "1.6.11"
}
-group = "org.processing"
+group = rootProject.group
version = "4.4"
-application {
- mainClass = "processing.app.Base"
-}
-
-// This can be removed by moving the asset management to native Java resources
-sourceSets{
- main{
- resources {
- srcDirs("../shared")
- }
- }
-}
-javapackager {
- mainClass("processing.app.ui.Splash")
+compose.desktop {
+ application {
+ mainClass = "processing.app.ui.Splash"
-// bundleJre(false)
- // Bundling the JRE is what is causing the missing classes for the autocomplete, it doesn't copy over the jmod files that we need
- bundleJre(true)
-// customizedJre(false) // Disabled to enabled debugging on the build package
+ nativeDistributions {
+ targetFormats(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb)
+ packageName = "Processing"
+ packageVersion = rootProject.version as String
- displayName("Processing")
- name("Processing")
- url("https://processing.org")
- // licenseFile("todo")
- // TODO: Add after resources folder
- additionalResources( file("build/resources/main").list()?.map { t-> file("build/resources/main/${t}") }?.toMutableList() ?: mutableListOf())
- fileAssociations(mutableListOf(
- FileAssociation().apply {
- extension = "pde"
- description = "Processing Source Code"
+ appResourcesRootDir.set(project.layout.projectDirectory.dir("resources"))
+ macOS{
+ bundleID = "org.processingfoundation.processing.app"
+// entitlementsFile = project.file("resources/mac-entitlements.plist")
+ iconFile = project.file("assets/mac/processing.icns")
+ }
+ windows{
+ iconFile = project.file("assets/windows/processing.ico")
+ }
+ linux {
+ iconFile = project.file("assets/linux/processing.png")
+ }
+ buildTypes.release.proguard{
+ optimize = false
+ }
}
- ))
- macConfig.apply {
- isGeneratePkg = false
- isGenerateDmg = false
- appId = "org.processing.app"
- entitlements = file("assets/mac/processing.entitlements")
- backgroundImage = file("assets/mac/background.png")
- windowWidth = 750
- windowHeight = 450
- iconX = 50
- iconSize = 250
- iconY = (windowHeight - iconSize) / 2 + 35
- appsLinkIconX = (windowWidth - iconSize)
- appsLinkIconY = iconY
- windowX = 200
- windowY = 200
- }
- winConfig.apply {
- isGenerateMsi = false
- isGenerateMsm = false
- fileVersion = project.version as String
- productVersion = project.version as String
- isDisableRunAfterInstall = false
}
}
repositories {
+ maven("https://maven.pkg.jetbrains.space/public/p/compose/dev")
+ google()
mavenCentral()
maven { url = uri("https://jogamp.org/deployment/maven") }
}
@@ -111,4 +85,29 @@ tasks.register("unzipExamples"){
into(layout.buildDirectory.dir("resources/main/modes/java/examples"))
}
-tasks.jar{ finalizedBy("unzipExamples") }
\ No newline at end of file
+tasks.jar{ finalizedBy("unzipExamples") }
+
+val os: OperatingSystem = DefaultNativePlatform.getCurrentOperatingSystem()
+val arch = System.getProperty("os.arch")
+var platform = "linux"
+if (os.isWindows) {
+ platform = "windows"
+} else if (os.isMacOsX) {
+ platform = "mac"
+}
+tasks.register("downloadJDK"){
+ src("https://api.adoptium.net/v3/binary/latest/17/ga/${platform}/${arch}/jdk/hotspot/normal/eclipse?project=jdk")
+ dest(layout.buildDirectory.file("jdk-${platform}-${arch}.tar.gz"))
+ overwrite(false)
+}
+tasks.register("unzipJDK"){
+ val dl = tasks.findByPath("downloadJDK") as Download
+ dependsOn(dl)
+ from(tarTree(dl.dest))
+ eachFile{
+ path = Regex("jdk-[\\d.+]+").replaceFirst(path, "jdk")
+ }
+ into(layout.buildDirectory.dir("resources/${platform}-${arch}/"))
+}
+tasks.jar { dependsOn("unzipJDK") }
+tasks.processResources{ finalizedBy("unzipJDK") }
\ No newline at end of file
diff --git a/settings.gradle.kts b/settings.gradle.kts
index 69276fe..92a85ec 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -2,7 +2,23 @@ pluginManagement {
plugins {
kotlin("jvm") version "1.9.23"
}
+ repositories {
+ maven("https://plugins.gradle.org/m2/")
+ google()
+ gradlePluginPortal()
+ mavenCentral()
+ }
+}
+
+
+dependencyResolutionManagement {
+ repositories {
+ google()
+ mavenCentral()
+ maven("https://plugins.gradle.org/m2/")
+ }
}
+
plugins {
id("org.gradle.toolchains.foojay-resolver-convention") version "0.5.0"
}