diff --git a/app/build.gradle.kts b/app/build.gradle.kts index bb594b814..02e178927 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -41,7 +41,7 @@ sourceSets{ compose.desktop { application { - mainClass = "processing.app.ui.Splash" + mainClass = "processing.app.ui.Start" nativeDistributions{ modules("jdk.jdi", "java.compiler") diff --git a/app/src/processing/app/ui/Start.kt b/app/src/processing/app/ui/Start.kt new file mode 100644 index 000000000..8b3a2e1da --- /dev/null +++ b/app/src/processing/app/ui/Start.kt @@ -0,0 +1,103 @@ +package processing.app.ui + +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.EnterExitState +import androidx.compose.animation.core.LinearEasing +import androidx.compose.animation.core.tween +import androidx.compose.animation.fadeIn +import androidx.compose.animation.fadeOut +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.Text +import androidx.compose.runtime.* +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.draw.shadow +import androidx.compose.ui.graphics.toComposeImageBitmap +import androidx.compose.ui.unit.DpSize +import androidx.compose.ui.unit.dp +import androidx.compose.ui.window.* +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch +import processing.app.Base +import processing.app.Platform +import javax.imageio.ImageIO +import javax.swing.SwingUtilities + +/** + * Show a splash screen window. A rewrite of Splash.java + */ +class Start { + companion object { + @JvmStatic + fun main(args: Array) { + val splash = Platform.getContentFile("lib/about-2x.png") + val image = ImageIO.read(splash).toComposeImageBitmap() + val duration = 200 + val timeMargin = 50 + + application { + var starting by remember { mutableStateOf(true) } + Window( + visible = starting, + onCloseRequest = { }, + undecorated = true, + transparent = true, + resizable = false, + alwaysOnTop = true, + state = rememberWindowState( + position = WindowPosition(Alignment.Center), + size = DpSize(image.width.dp / 2 , image.height.dp / 2) + ) + ) { + var visible by remember { mutableStateOf(false) } + val composition = rememberCoroutineScope() + LaunchedEffect(Unit) { + visible = true + composition.launch { + delay(duration.toLong() + timeMargin) + try { + Base.main(args) + } catch (e: Exception) { + throw InternalError("Failed to invoke main method", e) + } + composition.launch { + visible = false + delay(duration.toLong() + timeMargin) + starting = false + } + } + } + AnimatedVisibility( + visible = visible, + enter = fadeIn( + animationSpec = tween( + durationMillis = duration, + easing = LinearEasing + ) + ), + exit = fadeOut( + animationSpec = tween( + durationMillis = duration, + easing = LinearEasing + ) + ) + ) { + Image( + bitmap = image, + contentDescription = "About", + modifier = Modifier + .fillMaxSize() + .clip(RoundedCornerShape(16.dp)) + ) + } + } + + } + } + } +} \ No newline at end of file