11package processing.app.gradle.ui
22
3+ import androidx.compose.animation.AnimatedVisibility
4+ import androidx.compose.animation.core.LinearEasing
5+ import androidx.compose.animation.core.tween
6+ import androidx.compose.animation.fadeIn
7+ import androidx.compose.animation.fadeOut
38import androidx.compose.foundation.background
4- import androidx.compose.foundation.combinedClickable
59import androidx.compose.foundation.layout.*
610import androidx.compose.foundation.shape.CircleShape
711import androidx.compose.material.*
812import androidx.compose.material.icons.Icons
9- import androidx.compose.material.icons.filled.Close
1013import androidx.compose.material.icons.filled.PlayArrow
11- import androidx.compose.runtime.Composable
14+ import androidx.compose.runtime.*
1215import androidx.compose.ui.ExperimentalComposeUiApi
1316import androidx.compose.ui.Modifier
1417import androidx.compose.ui.awt.ComposePanel
1518import androidx.compose.ui.awt.SwingPanel
1619import androidx.compose.ui.draw.clip
1720import androidx.compose.ui.graphics.Brush
1821import androidx.compose.ui.graphics.Color
19- import androidx.compose.ui.graphics.colorspace.ColorSpace
20- import androidx.compose.ui.graphics.colorspace.ColorSpaces
2122import androidx.compose.ui.input.pointer.PointerEventType
2223import androidx.compose.ui.input.pointer.onPointerEvent
2324import androidx.compose.ui.unit.dp
2425import processing.app.ui.Editor
2526import processing.app.ui.EditorToolbar
2627import processing.app.ui.Theme
28+ import processing.app.ui.theme.toColorInt
2729import javax.swing.JComponent
2830
2931class Toolbar (val editor : Editor ) {
3032 companion object {
3133 @JvmStatic
3234 fun legacyWrapped (editor : Editor , toolbar : EditorToolbar ): JComponent {
35+ // TODO: Somehow override the menubar items as well
36+
3337 val bar = Toolbar (editor)
3438 val panel = ComposePanel ().apply {
3539 setContent {
@@ -52,13 +56,13 @@ class Toolbar(val editor: Editor) {
5256 @OptIn(ExperimentalComposeUiApi ::class )
5357 @Composable
5458 fun display (){
55-
56- val startColor = Theme .getColor(" toolbar.gradient.top" )
57- val endColor = Theme .getColor(" toolbar.gradient.bottom" )
59+ val startColor = Theme .get(" toolbar.gradient.top" ).toColorInt()
60+ val endColor = Theme .get(" toolbar.gradient.bottom" ).toColorInt()
5861 val colorStops = arrayOf(
59- 0.0f to startColor.toComposeColor( ),
60- 1f to endColor.toComposeColor( )
62+ 0.0f to Color (startColor ),
63+ 1f to Color (endColor )
6164 )
65+
6266 Row (
6367 modifier = Modifier .background(Brush .verticalGradient(colorStops = colorStops))
6468 .fillMaxWidth()
@@ -70,59 +74,117 @@ class Toolbar(val editor: Editor) {
7074 val available = editor.service.availableTasks
7175 val finished = editor.service.finishedTasks
7276 val isRunning = editor.service.running.value
73- Surface (
77+ ActionButton (
7478 modifier = Modifier
7579 .onPointerEvent(PointerEventType .Press ){
7680 editor.service.run ()
7781 }
78- .height(34 .dp)
79- .clip(CircleShape )
80- .aspectRatio(1f )
81- .background(Color .White )
82-
83- ){
84- if (isRunning) {
82+ .padding(1 .dp)
83+ ) {
84+ val color = LocalContentColor .current
85+ Fading (visible = isRunning) {
8586 CircularProgressIndicator (
86- progress = finished.count().toFloat() / available.count() ,
87- color = startColor.toComposeColor()
87+ progress = finished.count().toFloat() / (available.count() - 1 ),
88+ color = color
89+ )
90+ }
91+ Box (modifier = Modifier .padding(4 .dp)) {
92+ Icon (
93+ imageVector = Icons .Filled .PlayArrow ,
94+ contentDescription = " Play" ,
95+ tint = color
8896 )
8997 }
90- Icon (
91- imageVector = Icons .Filled .PlayArrow ,
92- contentDescription = " Play" ,
93- tint = Color .Black ,
94- modifier = Modifier
95- .size(2 .dp)
96- )
9798 }
98- if ( isRunning){
99- Surface (
99+ Fading (visible = isRunning) {
100+ ActionButton (
100101 modifier = Modifier
101102 .onPointerEvent(PointerEventType .Press ){
102103 editor.service.stop()
103104 }
104- .height(34 .dp)
105- .clip(CircleShape )
106- .aspectRatio(1f )
107- .background(Color .White )
108- ) {
109- Icon (
110- imageVector = Icons .Filled .Close ,
111- contentDescription = " Stop" ,
112- tint = Color .Black ,
113- modifier = Modifier .size(12 .dp)
105+ ){
106+ val color = LocalContentColor .current
107+ Box (
108+ modifier = Modifier
109+ .padding(12 .dp)
110+ .size(12 .dp)
111+ .background(color)
114112 )
115113 }
116114 }
117115 }
118116 }
119117}
120118
121- fun java.awt.Color.toComposeColor (): Color {
122- return Color (
123- red = this .red / 255f ,
124- green = this .green / 255f ,
125- blue = this .blue / 255f ,
126- alpha = this .alpha / 255f
127- )
119+ @OptIn(ExperimentalComposeUiApi ::class )
120+ @Composable
121+ fun ActionButton (modifier : Modifier = Modifier , content : @Composable () -> Unit ){
122+ val baseColor = Theme .get(" toolbar.button.enabled.field" )
123+ val baseTextColor = Theme .get(" toolbar.button.enabled.glyph" )
124+
125+ var hover by remember{ mutableStateOf(false ) }
126+ val hoverColor = Theme .get(" toolbar.button.rollover.field" )
127+ val hoverTextColor = Theme .get(" toolbar.button.rollover.glyph" )
128+
129+ var pressed by remember{ mutableStateOf(false ) }
130+ val pressedColor = Theme .get(" toolbar.button.pressed.field" )
131+ val pressedTextColor = Theme .get(" toolbar.button.pressed.glyph" )
132+
133+ val color = when {
134+ pressed -> pressedColor
135+ hover -> hoverColor
136+ else -> baseColor
137+ }.toColorInt()
138+
139+ val textColor = when {
140+ pressed -> pressedTextColor
141+ hover -> hoverTextColor
142+ else -> baseTextColor
143+ }
144+
145+ Box (
146+ modifier = Modifier
147+ .onPointerEvent(PointerEventType .Enter ) {
148+ hover = true
149+ }
150+ .onPointerEvent(PointerEventType .Exit ) {
151+ hover = false
152+ }
153+ .onPointerEvent(PointerEventType .Press ) {
154+ pressed = true
155+ }
156+ .onPointerEvent(PointerEventType .Release ) {
157+ pressed = false
158+ }
159+ .height(34 .dp)
160+ .clip(CircleShape )
161+ .aspectRatio(1f )
162+ .background(color = Color (color))
163+ .then(modifier)
164+ ) {
165+ CompositionLocalProvider (LocalContentColor provides Color (textColor.toColorInt())) {
166+ content()
167+ }
168+ }
169+ }
170+
171+ @Composable
172+ fun Fading (visible : Boolean , content : @Composable () -> Unit ) {
173+ AnimatedVisibility (
174+ visible = visible,
175+ enter = fadeIn(
176+ animationSpec = tween(
177+ durationMillis = 250 ,
178+ easing = LinearEasing
179+ )
180+ ),
181+ exit = fadeOut(
182+ animationSpec = tween(
183+ durationMillis = 250 ,
184+ easing = LinearEasing
185+ )
186+ )
187+ ) {
188+ content()
189+ }
128190}
0 commit comments