11package processing.app.gradle
22
3+ import androidx.compose.foundation.VerticalScrollbar
4+ import androidx.compose.foundation.background
5+ import androidx.compose.foundation.gestures.scrollable
6+ import androidx.compose.foundation.layout.Arrangement
7+ import androidx.compose.foundation.layout.Box
8+ import androidx.compose.foundation.layout.Column
9+ import androidx.compose.foundation.layout.Row
10+ import androidx.compose.foundation.layout.fillMaxHeight
11+ import androidx.compose.foundation.layout.fillMaxSize
12+ import androidx.compose.foundation.layout.padding
13+ import androidx.compose.foundation.layout.size
14+ import androidx.compose.foundation.rememberScrollState
15+ import androidx.compose.foundation.rememberScrollbarAdapter
16+ import androidx.compose.foundation.verticalScroll
17+ import androidx.compose.material.Checkbox
18+ import androidx.compose.material.MaterialTheme
19+ import androidx.compose.material.Surface
320import androidx.compose.material.Text
421import androidx.compose.runtime.Composable
22+ import androidx.compose.runtime.LaunchedEffect
23+ import androidx.compose.runtime.getValue
24+ import androidx.compose.runtime.mutableStateOf
25+ import androidx.compose.runtime.remember
26+ import androidx.compose.runtime.setValue
27+ import androidx.compose.runtime.snapshotFlow
28+ import androidx.compose.ui.Alignment
29+ import androidx.compose.ui.Modifier
530import androidx.compose.ui.awt.ComposePanel
31+ import androidx.compose.ui.awt.SwingPanel
32+ import androidx.compose.ui.graphics.Color
33+ import androidx.compose.ui.text.font.FontWeight
34+ import androidx.compose.ui.text.style.TextAlign
35+ import androidx.compose.ui.text.style.TextDecoration
36+ import androidx.compose.ui.unit.dp
37+ import androidx.compose.ui.unit.em
38+ import androidx.compose.ui.unit.sp
39+ import com.formdev.flatlaf.util.SwingUtils
40+ import com.github.ajalt.mordant.rendering.TextStyle
41+ import kotlinx.coroutines.CoroutineScope
42+ import kotlinx.coroutines.Dispatchers
43+ import kotlinx.coroutines.launch
44+ import processing.app.Language.text
45+ import processing.app.Settings
46+ import processing.app.Sketch
47+ import processing.app.ui.Editor
48+ import processing.app.ui.EditorFooter
49+ import processing.app.ui.Theme
50+ import processing.app.ui.theme.ProcessingTheme
51+ import processing.app.watchFile
52+ import java.awt.Dimension
53+ import java.util.UUID
54+ import javax.swing.JCheckBox
655import javax.swing.JPanel
56+ import javax.swing.SwingUtilities
757
8- class GradleSettings : JPanel () {
9- init {
10- val compose = ComposePanel ()
11- compose.setContent {
12- Panel ()
13- }
14- this .add(compose)
15- }
58+ class GradleSettings {
1659 companion object {
60+ private val scope = CoroutineScope (Dispatchers .IO )
61+
62+ @JvmStatic
63+ fun addGradleSettings (footer : EditorFooter , service : GradleService ){
64+ val panel = ComposePanel ()
65+ panel.setContent {
66+ Panel (service)
67+ }
68+ scope.launch {
69+ // Only add the panel to the footer when Gradle is active
70+ // Can be removed later when Gradle becomes the default build system
71+ snapshotFlow { service.active.value }
72+ .collect { active ->
73+ SwingUtilities .invokeLater {
74+ if (active){
75+ footer.addPanel(panel, text(" gradle.settings" ), " /lib/footer/settings" )
76+ }else {
77+ footer.removePanel(panel)
78+ }
79+ }
80+ }
81+ }
82+ }
83+
1784 @Composable
18- fun Panel (){
19- Text (" Gradle settings will be here soon" )
85+ fun Panel (service : GradleService ){
86+ val properties = service.sketch.value?.folder?.resolve(Sketch .PROPERTIES_NAME ) ? : return
87+ // TODO: Rewatch again is the sketch is saved in a different location
88+
89+ val changed = watchFile(properties)
90+
91+ val settings = remember(changed) {Settings (properties) }
92+
93+ LaunchedEffect (changed){
94+ /*
95+ If the sketch.id is not set, generate a new UUID and save it.
96+ We will use this key to save preferences that do not influence the sketch itself,
97+ so they are not code, but do influence how the sketch shows up in the editor.
98+ This is useful for things like favoring a sketch
99+ These are items that should not be shared between users/computers
100+ // TODO: Reset id on save-as?
101+ */
102+ if (settings.get(" sketch.id" ) == null ){
103+ // TODO: Should this watch the file or should it update a bunch on running the sketch?
104+ settings.set(" sketch.id" , UUID .randomUUID().toString())
105+ settings.save()
106+ }
107+ }
108+ val stateVertical = rememberScrollState(0 )
109+
110+ ProcessingTheme {
111+ Box {
112+ Row (
113+ modifier = Modifier
114+ .background(Color (Theme .getColor(" editor.line.highlight.color" ).rgb))
115+ .padding(start = Editor .LEFT_GUTTER .dp)
116+ .fillMaxSize()
117+ .verticalScroll(stateVertical)
118+ .padding(vertical = 4 .dp)
119+ ) {
120+ PluginsPanel (settings)
121+ }
122+ VerticalScrollbar (
123+ modifier = Modifier
124+ .align(Alignment .CenterEnd )
125+ .padding(8 .dp)
126+ .fillMaxHeight(),
127+ adapter = rememberScrollbarAdapter(stateVertical)
128+ )
129+ }
130+ }
20131 }
21132
133+ @Composable
134+ private fun PluginsPanel (settings : Settings ) {
135+ // Grab the installed plugins
136+ val plugins = GradlePlugin .plugins
137+
138+ // Grab the enabled plugins
139+ val pluginSetting = (settings.get(GradlePlugin .PROPERTIES_KEY ) ? : " " )
140+ .split(" ," )
141+ .map { it.trim() }
142+ .filter{ it.isNotEmpty() }
143+
144+ // Link plugins in the settings to their installed counterparts
145+ val enabledPlugins = pluginSetting
146+ .map { id -> plugins.find { plugin -> plugin.id == id } }
147+ Column {
148+ Text (
149+ text = text(" gradle.settings.plugins" ),
150+ textAlign = TextAlign .Start ,
151+ fontSize = 10 .sp,
152+ fontWeight = FontWeight .Bold
153+ )
154+ Column (verticalArrangement = Arrangement .spacedBy(4 .dp)) {
155+ GradlePlugin .plugins.map { plugin ->
156+ Row () {
157+ Checkbox (
158+ checked = enabledPlugins.contains(plugin),
159+ modifier = Modifier
160+ .padding(start = 0 .dp, end = 8 .dp)
161+ .size(24 .dp),
162+ onCheckedChange = { checked ->
163+ scope.launch {
164+ // Work from the setting as we do not want to remove missing plugins
165+ val current = pluginSetting.toMutableSet()
166+ if (checked) {
167+ current.add(plugin.id)
168+ } else {
169+ current.remove(plugin.id)
170+ }
171+ settings.set(GradlePlugin .PROPERTIES_KEY , current.joinToString(" ," ))
172+ settings.save()
173+ }
174+ },
175+ )
176+ Column {
177+ Text (
178+ text = plugin.name,
179+ textAlign = TextAlign .Start ,
180+ fontSize = 12 .sp
181+ )
182+ Text (
183+ text = plugin.description,
184+ textAlign = TextAlign .Start ,
185+ fontSize = 10 .sp,
186+ )
187+ }
188+ }
189+
190+ }
191+ }
192+ }
193+ }
22194 }
23195}
0 commit comments