@@ -5,17 +5,12 @@ import androidx.compose.animation.core.LinearEasing
5
5
import androidx.compose.animation.core.tween
6
6
import androidx.compose.animation.fadeIn
7
7
import androidx.compose.animation.fadeOut
8
- import androidx.compose.foundation.ExperimentalFoundationApi
9
- import androidx.compose.foundation.Image
10
- import androidx.compose.foundation.background
8
+ import androidx.compose.foundation.*
11
9
import androidx.compose.foundation.layout.*
12
- import androidx.compose.foundation.onClick
13
10
import androidx.compose.foundation.shape.CircleShape
14
11
import androidx.compose.material.*
15
12
import androidx.compose.material.icons.Icons
16
13
import androidx.compose.material.icons.filled.PlayArrow
17
- import androidx.compose.material.icons.filled.Settings
18
- import androidx.compose.material.icons.outlined.Share
19
14
import androidx.compose.runtime.*
20
15
import androidx.compose.ui.Alignment
21
16
import androidx.compose.ui.ExperimentalComposeUiApi
@@ -29,11 +24,15 @@ import androidx.compose.ui.graphics.StrokeCap
29
24
import androidx.compose.ui.input.pointer.PointerEventType
30
25
import androidx.compose.ui.input.pointer.onPointerEvent
31
26
import androidx.compose.ui.res.loadImageBitmap
27
+ import androidx.compose.ui.res.loadSvgPainter
28
+ import androidx.compose.ui.res.useResource
29
+ import androidx.compose.ui.unit.Density
32
30
import androidx.compose.ui.unit.Dp
33
31
import androidx.compose.ui.unit.dp
34
32
import androidx.compose.ui.window.Window
35
33
import androidx.compose.ui.window.WindowPosition
36
34
import androidx.compose.ui.window.rememberWindowState
35
+ import groovyjarjarantlr4.v4.runtime.misc.Args
37
36
import processing.app.gradle.helpers.ActionGradleJob
38
37
import processing.app.gradle.GradleJob
39
38
import processing.app.gradle.ScreenshotService
@@ -44,7 +43,7 @@ import processing.app.ui.theme.toColorInt
44
43
import java.io.File
45
44
import javax.swing.JComponent
46
45
47
- class Toolbar (val editor : Editor ) {
46
+ class Toolbar (val editor : Editor ? ) {
48
47
companion object {
49
48
@JvmStatic
50
49
fun legacyWrapped (editor : Editor , toolbar : EditorToolbar ): JComponent {
@@ -64,6 +63,10 @@ class Toolbar(val editor: Editor) {
64
63
65
64
return panel
66
65
}
66
+ @JvmStatic
67
+ fun main (args : Array <String >) {
68
+
69
+ }
67
70
}
68
71
69
72
// TODO: Split into multiple files
@@ -117,67 +120,92 @@ class Toolbar(val editor: Editor) {
117
120
118
121
}
119
122
120
- // TODO: Indicate waiting for vm connection to be ready
121
- val vm = editor.service.jobs.lastOrNull()?.vm?.value
122
- // TODO: Fade in
123
- // TODO: Set icon
124
- vm?.apply {
125
- ActionButton (
126
- modifier = Modifier
127
- .onClick {
128
- ScreenshotService .takeScreenshot(this ) { file ->
123
+ Row {
124
+ hoverPill(actions = {
125
+ actionButton(
126
+ onClick = {
127
+
128
+ }
129
+ ) {
130
+ val icon = useResource(" toolbar/Settings.svg" ) { loadSvgPainter(it, Density (1f )) }
131
+ val color = LocalContentColor .current
132
+ Icon (
133
+ painter = icon,
134
+ contentDescription = " Settings" ,
135
+ tint = color
136
+ )
137
+ }
138
+ val vm = editor?.service?.jobs?.lastOrNull()?.vm?.value
139
+ actionButton(
140
+ enabled = vm != null ,
141
+ onClick = {
142
+ vm ? : return @actionButton
143
+ ScreenshotService .takeScreenshot(vm) { file ->
129
144
screenshot = file.toFile()
130
145
}
131
146
}
132
- ) {
133
- Icon (
134
- imageVector = Icons .Outlined .Share ,
135
- contentDescription = " Settings" ,
136
- tint = Color (Theme .get(" toolbar.button.enabled.glyph" ).toColorInt()),
137
- modifier = Modifier .padding(6 .dp)
138
- )
139
- }
147
+ ) {
148
+ val icon = useResource(" toolbar/Screenshot.svg" ) { loadSvgPainter(it, Density (1f )) }
149
+ val color = LocalContentColor .current
150
+ Icon (
151
+ painter = icon,
152
+ contentDescription = " Screenshot" ,
153
+ tint = color
154
+ )
155
+ }
140
156
141
- }
142
157
143
- // TODO: Set icon
144
- var expanded by remember { mutableStateOf(false ) }
145
- ActionButton (
146
- active = expanded,
147
- modifier = Modifier
148
- .onClick {
149
- val x = editor.location.x + editor.width
150
- val y = editor.location.y
151
- windowState.position = WindowPosition (
152
- x = x.dp,
153
- y = y.dp,
158
+ var expanded by remember { mutableStateOf(false ) }
159
+ actionButton(
160
+ active = expanded,
161
+ modifier = Modifier
162
+ .onClick {
163
+ editor ? : return @onClick
164
+ val x = editor.location.x + editor.width
165
+ val y = editor.location.y
166
+ windowState.position = WindowPosition (
167
+ x = x.dp,
168
+ y = y.dp,
169
+ )
170
+ expanded = ! expanded
171
+ }
172
+ ) {
173
+ val icon = useResource(" toolbar/Sketch Settings.svg" ) { loadSvgPainter(it, Density (1f )) }
174
+ val color = LocalContentColor .current
175
+ Icon (
176
+ painter = icon,
177
+ contentDescription = " Sketch Settings" ,
178
+ tint = color
154
179
)
155
- expanded = ! expanded
156
180
}
157
- ){
158
- Icon (
159
- imageVector = Icons .Filled .Settings ,
160
- contentDescription = " Settings" ,
161
- tint = Color (Theme .get(" toolbar.button.enabled.glyph" ).toColorInt()),
162
- modifier = Modifier .padding(6 .dp)
163
- )
164
- }
165
- Window (
166
- visible = expanded,
167
- onCloseRequest = {
168
- expanded = false
169
- },
170
- resizable = true ,
171
- title = " Sketch Settings" ,
172
- state = windowState,
173
- ) {
174
- Column (modifier = Modifier .padding(16 .dp)) {
175
- Chip (onClick = {
176
- editor.service.active.value = false
177
- }) {
178
- Text (" Switch back to legacy" )
181
+ Window (
182
+ visible = expanded,
183
+ onCloseRequest = {
184
+ expanded = false
185
+ },
186
+ resizable = true ,
187
+ title = " Sketch Settings" ,
188
+ state = windowState,
189
+ ) {
190
+ Column (modifier = Modifier .padding(16 .dp)) {
191
+ Chip (onClick = {
192
+ editor?.service?.active?.value = false
193
+ }) {
194
+ Text (" Switch back to legacy" )
195
+ }
196
+ }
179
197
}
180
- }
198
+ }, base = {
199
+ actionButton {
200
+ val icon = useResource(" toolbar/More.svg" ) { loadSvgPainter(it, Density (1f )) }
201
+ val color = LocalContentColor .current
202
+ Icon (
203
+ painter = icon,
204
+ contentDescription = " More" ,
205
+ tint = color
206
+ )
207
+ }
208
+ })
181
209
}
182
210
}
183
211
@@ -186,15 +214,15 @@ class Toolbar(val editor: Editor) {
186
214
@OptIn(ExperimentalComposeUiApi ::class )
187
215
@Composable
188
216
fun SketchButtons () {
189
- val job = editor.service.jobs.filterIsInstance<ActionGradleJob >().lastOrNull()
217
+ val job = editor? .service? .jobs? .filterIsInstance<ActionGradleJob >()? .lastOrNull()
190
218
val state = job?.state?.value ? : GradleJob .State .NONE
191
219
val isActive = state != GradleJob .State .NONE && state != GradleJob .State .DONE
192
220
Row (horizontalArrangement = Arrangement .spacedBy(8 .dp)) {
193
- ActionButton (
221
+ actionButton (
194
222
active = isActive,
195
223
modifier = Modifier
196
224
.onPointerEvent(PointerEventType .Press ) {
197
- editor.service.run ()
225
+ editor? .service? .run ()
198
226
}
199
227
.padding(2 .dp)
200
228
) {
@@ -207,27 +235,26 @@ class Toolbar(val editor: Editor) {
207
235
strokeWidth = 3 .dp
208
236
)
209
237
}
210
- Box (modifier = Modifier .padding(4 .dp)) {
211
- Icon (
212
- imageVector = Icons .Filled .PlayArrow ,
213
- contentDescription = " Play" ,
214
- tint = color
215
- )
216
- }
238
+ val icon = useResource(" toolbar/Play.svg" ) { loadSvgPainter(it, Density (1f )) }
239
+ Icon (
240
+ painter = icon,
241
+ contentDescription = " Play" ,
242
+ tint = color
243
+ )
217
244
}
218
245
Fading (visible = isActive) {
219
- ActionButton (
246
+ actionButton (
220
247
modifier = Modifier
221
248
.onPointerEvent(PointerEventType .Press ) {
222
- editor.service.stop()
249
+ editor? .service? .stop()
223
250
}
224
251
) {
252
+ val icon = useResource(" toolbar/Stop.svg" ) { loadSvgPainter(it, Density (1f )) }
225
253
val color = LocalContentColor .current
226
- Box (
227
- modifier = Modifier
228
- .padding(12 .dp)
229
- .size(12 .dp)
230
- .background(color)
254
+ Icon (
255
+ painter = icon,
256
+ contentDescription = " Stop" ,
257
+ tint = color
231
258
)
232
259
}
233
260
}
@@ -236,7 +263,38 @@ class Toolbar(val editor: Editor) {
236
263
237
264
@OptIn(ExperimentalComposeUiApi ::class )
238
265
@Composable
239
- fun ActionButton (modifier : Modifier = Modifier , active : Boolean = false, content : @Composable () -> Unit ) {
266
+ fun hoverPill (actions : @Composable () -> Unit , base : @Composable () -> Unit ) {
267
+ var hover by remember { mutableStateOf(false ) }
268
+ val baseColor = Theme .get(" toolbar.button.enabled.field" ).toColorInt().let { Color (it) }
269
+
270
+ Row (
271
+ modifier = Modifier
272
+ .onPointerEvent(PointerEventType .Enter ) {
273
+ hover = true
274
+ }
275
+ .onPointerEvent(PointerEventType .Exit ) {
276
+ hover = false
277
+ }
278
+ .clip(CircleShape )
279
+ .background(baseColor)
280
+
281
+
282
+ ){
283
+ if (hover) actions()
284
+ base()
285
+ }
286
+ }
287
+
288
+
289
+ @OptIn(ExperimentalComposeUiApi ::class , ExperimentalFoundationApi ::class )
290
+ @Composable
291
+ fun actionButton (
292
+ modifier : Modifier = Modifier ,
293
+ enabled : Boolean = true,
294
+ active : Boolean = false,
295
+ onClick : () -> Unit = {},
296
+ content : @Composable () -> Unit
297
+ ) {
240
298
val baseColor = Theme .get(" toolbar.button.enabled.field" )
241
299
val baseTextColor = Theme .get(" toolbar.button.enabled.glyph" )
242
300
@@ -283,6 +341,11 @@ class Toolbar(val editor: Editor) {
283
341
.clip(CircleShape )
284
342
.aspectRatio(1f )
285
343
.background(color = Color (color))
344
+ .onClick{
345
+ if (enabled) {
346
+ onClick()
347
+ }
348
+ }
286
349
.then(modifier)
287
350
) {
288
351
CompositionLocalProvider (LocalContentColor provides Color (textColor.toColorInt())) {
0 commit comments