1+ package processing.app.gradle
2+
3+ import androidx.compose.runtime.mutableStateListOf
4+ import androidx.compose.runtime.mutableStateOf
5+ import kotlinx.coroutines.*
6+ import org.gradle.tooling.BuildLauncher
7+ import org.gradle.tooling.GradleConnector
8+ import org.gradle.tooling.ProjectConnection
9+ import org.gradle.tooling.events.ProgressListener
10+ import org.gradle.tooling.events.task.TaskFinishEvent
11+ import org.gradle.tooling.events.task.TaskStartEvent
12+ import processing.app.Base
13+ import processing.app.Messages
14+ import processing.app.ui.Editor
15+ import java.io.File
16+ import javax.swing.SwingUtilities
17+ import javax.swing.event.DocumentEvent
18+ import javax.swing.event.DocumentListener
19+
20+
21+ class GradleService (val editor : Editor ) {
22+ val availableTasks = mutableStateListOf<String >()
23+ val finishedTasks = mutableStateListOf<String >()
24+ val running = mutableStateOf(false )
25+
26+ private var connection: ProjectConnection ? = null
27+ private var preparation: Job ? = null
28+ private var preparing = false
29+
30+ private var run: Job ? = null
31+ private var cancel = GradleConnector .newCancellationTokenSource()
32+
33+ val folder: File get() = editor.sketch.folder
34+
35+ fun prepare (){
36+ if (preparing) return
37+ preparation?.cancel()
38+ preparation = CoroutineScope (Dispatchers .IO ).launch {
39+ val connection = connection ? : return @launch
40+ delay(1000 )
41+ preparing = true
42+
43+ connection.newSketchBuild()
44+ .forTasks(" build" )
45+ .run ()
46+
47+ preparing = false
48+ }
49+ }
50+
51+ fun run (){
52+ val connection = connection ? : return
53+ if (! preparing) preparation?.cancel()
54+
55+ run?.cancel()
56+ run = CoroutineScope (Dispatchers .IO ).launch {
57+ preparation?.join()
58+ cancel.cancel()
59+ cancel = GradleConnector .newCancellationTokenSource()
60+ connection.newSketchBuild()
61+ .forTasks(" run" )
62+ .withCancellationToken(cancel.token())
63+ .run ()
64+ }
65+
66+ CoroutineScope (Dispatchers .IO ).launch {
67+ running.value = true
68+ run?.join()
69+ running.value = false
70+ }
71+ }
72+
73+ fun stop (){
74+ cancel.cancel()
75+ }
76+
77+ fun startService (){
78+ Messages .log(" Starting Gradle service at ${folder} " )
79+
80+ connection = GradleConnector .newConnector()
81+ .forProjectDirectory(folder)
82+ .connect()
83+
84+ // TODO: recreate connection if sketch folder changes
85+
86+ SwingUtilities .invokeLater {
87+ editor.sketch.code.forEach {
88+ it.document.addDocumentListener(object : DocumentListener {
89+ override fun insertUpdate (e : DocumentEvent ) {
90+ prepare()
91+ }
92+
93+ override fun removeUpdate (e : DocumentEvent ) {
94+ prepare()
95+ }
96+
97+ override fun changedUpdate (e : DocumentEvent ) {
98+ prepare()
99+ }
100+ })
101+ }
102+
103+ // TODO: Attach listener if new tab is created
104+ }
105+ }
106+
107+
108+
109+
110+ fun ProjectConnection.newSketchBuild (): BuildLauncher {
111+ finishedTasks.clear()
112+
113+ val buildGradle = folder.resolve(" build.gradle.kts" )
114+ if (! buildGradle.exists()){
115+ Messages .log(" build.gradle.kts not found in ${folder} , creating one" )
116+ val content = """
117+ plugins{
118+ id("processing.java.gradle") version "${Base .getVersionName()} "
119+ }
120+ """ .trimIndent()
121+ buildGradle.writeText(content)
122+ }
123+
124+ val settingsGradle = folder.resolve(" settings.gradle.kts" )
125+ if (! settingsGradle.exists()){
126+ Messages .log(" settings.gradle.kts not found in ${folder} , creating one" )
127+ val content = """
128+ pluginManagement {
129+ repositories {
130+ mavenLocal()
131+ mavenCentral()
132+ }
133+ }
134+ """ .trimIndent()
135+ settingsGradle.writeText(content)
136+ }
137+
138+ return this .newBuild()
139+ .addProgressListener(ProgressListener { event ->
140+ val name = event.descriptor.name
141+ if (event is TaskStartEvent ) {
142+ if (! availableTasks.contains(name)) availableTasks.add(name)
143+ }
144+ if (event is TaskFinishEvent ){
145+ finishedTasks.add(name)
146+ }
147+ })
148+ // .setStandardOutput(System.out)
149+ // .setJavaHome(Platform.getJavaHome())
150+ }
151+ }
0 commit comments