From bd3a77ef17a456aa2ceb281cc2cf293f8be9d685 Mon Sep 17 00:00:00 2001 From: Stef Tervelde Date: Fri, 7 Feb 2025 12:09:58 +0100 Subject: [PATCH] Welcome Screen: Window Abstraction --- app/src/processing/app/ui/Welcome.kt | 47 ++++-------- app/src/processing/app/ui/WelcomeToBeta.kt | 79 +------------------- app/src/processing/app/ui/theme/Button.kt | 59 +++++++++++++++ app/src/processing/app/ui/theme/Window.kt | 85 ++++++++++++++++++++++ 4 files changed, 163 insertions(+), 107 deletions(-) create mode 100644 app/src/processing/app/ui/theme/Button.kt create mode 100644 app/src/processing/app/ui/theme/Window.kt diff --git a/app/src/processing/app/ui/Welcome.kt b/app/src/processing/app/ui/Welcome.kt index d7aa9a501..8743282d6 100644 --- a/app/src/processing/app/ui/Welcome.kt +++ b/app/src/processing/app/ui/Welcome.kt @@ -1,54 +1,37 @@ package processing.app.ui import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.sizeIn import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import androidx.compose.ui.awt.ComposePanel import androidx.compose.ui.unit.dp -import com.formdev.flatlaf.util.SystemInfo import processing.app.Base -import processing.app.contrib.ui.contributionsManager -import processing.app.ui.theme.Locale +import processing.app.ui.theme.PDEWindow +import processing.app.ui.theme.pdeapplication import java.io.IOException -import javax.swing.JFrame import javax.swing.SwingUtilities class Welcome @Throws(IOException::class) constructor(base: Base) { init { SwingUtilities.invokeLater { - - - JFrame(Locale()["menu.help.welcome"]).apply{ - val mac = SystemInfo.isMacFullWindowContentSupported - - rootPane.putClientProperty("apple.awt.transparentTitleBar", mac) - rootPane.putClientProperty("apple.awt.fullWindowContent", mac) - - defaultCloseOperation = JFrame.DISPOSE_ON_CLOSE - add(ComposePanel().apply { - setContent { - Box(modifier = Modifier.padding(top = if (mac) 22.dp else 0.dp)) { - welcome() - } - } - }) - - pack() - - setLocationRelativeTo(null) - - isVisible = true - + PDEWindow("menu.help.welcome") { + welcome() } } } + companion object { + @Composable + fun welcome() { + Box(modifier = Modifier.sizeIn(815.dp, 450.dp)){ - @Composable - fun welcome() { - Box(modifier = Modifier.sizeIn(815.dp, 450.dp)){ + } + } + @JvmStatic + fun main(args: Array) { + pdeapplication("menu.help.welcome") { + welcome() + } } } } \ No newline at end of file diff --git a/app/src/processing/app/ui/WelcomeToBeta.kt b/app/src/processing/app/ui/WelcomeToBeta.kt index ddffd42d3..ab0aaa9e1 100644 --- a/app/src/processing/app/ui/WelcomeToBeta.kt +++ b/app/src/processing/app/ui/WelcomeToBeta.kt @@ -29,10 +29,7 @@ import androidx.compose.ui.window.WindowPosition import androidx.compose.ui.window.application import androidx.compose.ui.window.rememberWindowState import com.formdev.flatlaf.util.SystemInfo -import processing.app.ui.theme.LocalLocale -import processing.app.ui.theme.LocalTheme -import processing.app.ui.theme.Locale -import processing.app.ui.theme.ProcessingTheme +import processing.app.ui.theme.* import java.awt.Cursor import java.awt.Dimension import java.awt.event.KeyAdapter @@ -46,38 +43,12 @@ import javax.swing.SwingUtilities class WelcomeToBeta { companion object{ val windowSize = Dimension(400, 200) - val windowTitle = Locale()["beta.window.title"] @JvmStatic fun showWelcomeToBeta() { - val mac = SystemInfo.isMacFullWindowContentSupported SwingUtilities.invokeLater { - JFrame(windowTitle).apply { - val close = { dispose() } - rootPane.putClientProperty("apple.awt.transparentTitleBar", mac) - rootPane.putClientProperty("apple.awt.fullWindowContent", mac) - defaultCloseOperation = JFrame.DISPOSE_ON_CLOSE - contentPane.add(ComposePanel().apply { - size = windowSize - setContent { - ProcessingTheme { - Box(modifier = Modifier.padding(top = if (mac) 22.dp else 0.dp)) { - welcomeToBeta(close) - } - } - } - }) - pack() - background = java.awt.Color.white - setLocationRelativeTo(null) - addKeyListener(object : KeyAdapter() { - override fun keyPressed(e: KeyEvent) { - if (e.keyCode == KeyEvent.VK_ESCAPE) close() - } - }) - isResizable = false - isVisible = true - requestFocus() + PDEWindow("beta.window.title") { + welcomeToBeta() } } } @@ -129,48 +100,6 @@ class WelcomeToBeta { } } } - @OptIn(ExperimentalComposeUiApi::class) - @Composable - fun PDEButton(onClick: () -> Unit, content: @Composable BoxScope.() -> Unit) { - val theme = LocalTheme.current - - var hover by remember { mutableStateOf(false) } - var clicked by remember { mutableStateOf(false) } - val offset by animateFloatAsState(if (hover) -5f else 5f) - val color by animateColorAsState(if(clicked) colors.primaryVariant else colors.primary) - - Box(modifier = Modifier.padding(end = 5.dp, top = 5.dp)) { - Box( - modifier = Modifier - .offset((-offset).dp, (offset).dp) - .background(theme.getColor("toolbar.button.pressed.field")) - .matchParentSize() - ) - Box( - modifier = Modifier - .onPointerEvent(PointerEventType.Press) { - clicked = true - } - .onPointerEvent(PointerEventType.Release) { - clicked = false - onClick() - } - .onPointerEvent(PointerEventType.Enter) { - hover = true - } - .onPointerEvent(PointerEventType.Exit) { - hover = false - } - .pointerHoverIcon(PointerIcon(Cursor(Cursor.HAND_CURSOR))) - .background(color) - .padding(10.dp) - .sizeIn(minWidth = 100.dp), - contentAlignment = Alignment.Center, - content = content - ) - } - } - @JvmStatic fun main(args: Array) { @@ -180,7 +109,7 @@ class WelcomeToBeta { position = WindowPosition(Alignment.Center) ) - Window(onCloseRequest = ::exitApplication, state = windowState, title = windowTitle) { + Window(onCloseRequest = ::exitApplication, state = windowState, title = Locale()["beta.window.title"]) { ProcessingTheme { Surface(color = colors.background) { welcomeToBeta { diff --git a/app/src/processing/app/ui/theme/Button.kt b/app/src/processing/app/ui/theme/Button.kt new file mode 100644 index 000000000..5d2923ab0 --- /dev/null +++ b/app/src/processing/app/ui/theme/Button.kt @@ -0,0 +1,59 @@ +package processing.app.ui.theme + +import androidx.compose.animation.animateColorAsState +import androidx.compose.animation.core.animateFloatAsState +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.* +import androidx.compose.material.MaterialTheme.colors +import androidx.compose.runtime.* +import androidx.compose.ui.Alignment +import androidx.compose.ui.ExperimentalComposeUiApi +import androidx.compose.ui.Modifier +import androidx.compose.ui.input.pointer.PointerEventType +import androidx.compose.ui.input.pointer.PointerIcon +import androidx.compose.ui.input.pointer.onPointerEvent +import androidx.compose.ui.input.pointer.pointerHoverIcon +import androidx.compose.ui.unit.dp +import java.awt.Cursor + +@OptIn(ExperimentalComposeUiApi::class) +@Composable +fun PDEButton(onClick: () -> Unit, content: @Composable BoxScope.() -> Unit) { + val theme = LocalTheme.current + + var hover by remember { mutableStateOf(false) } + var clicked by remember { mutableStateOf(false) } + val offset by animateFloatAsState(if (hover) -5f else 5f) + val color by animateColorAsState(if(clicked) colors.primaryVariant else colors.primary) + + Box(modifier = Modifier.padding(end = 5.dp, top = 5.dp)) { + Box( + modifier = Modifier + .offset((-offset).dp, (offset).dp) + .background(theme.getColor("toolbar.button.pressed.field")) + .matchParentSize() + ) + Box( + modifier = Modifier + .onPointerEvent(PointerEventType.Press) { + clicked = true + } + .onPointerEvent(PointerEventType.Release) { + clicked = false + onClick() + } + .onPointerEvent(PointerEventType.Enter) { + hover = true + } + .onPointerEvent(PointerEventType.Exit) { + hover = false + } + .pointerHoverIcon(PointerIcon(Cursor(Cursor.HAND_CURSOR))) + .background(color) + .padding(10.dp) + .sizeIn(minWidth = 100.dp), + contentAlignment = Alignment.Center, + content = content + ) + } +} \ No newline at end of file diff --git a/app/src/processing/app/ui/theme/Window.kt b/app/src/processing/app/ui/theme/Window.kt new file mode 100644 index 000000000..eafa33a23 --- /dev/null +++ b/app/src/processing/app/ui/theme/Window.kt @@ -0,0 +1,85 @@ +package processing.app.ui.theme + +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.padding +import androidx.compose.material.MaterialTheme.colors +import androidx.compose.material.Surface +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.awt.ComposePanel +import androidx.compose.ui.unit.DpSize +import androidx.compose.ui.unit.dp +import androidx.compose.ui.window.Window +import androidx.compose.ui.window.WindowPosition +import androidx.compose.ui.window.application +import androidx.compose.ui.window.rememberWindowState +import com.formdev.flatlaf.util.SystemInfo +import processing.app.ui.WelcomeToBeta.Companion.welcomeToBeta + +import java.awt.event.KeyAdapter +import java.awt.event.KeyEvent +import javax.swing.JFrame + + +class PDEWindow(titleKey: String = "", content: @Composable () -> Unit): JFrame(){ + init{ + val mac = SystemInfo.isMacFullWindowContentSupported + + rootPane.apply{ + putClientProperty("apple.awt.transparentTitleBar", mac) + putClientProperty("apple.awt.fullWindowContent", mac) + } + + defaultCloseOperation = DISPOSE_ON_CLOSE + ComposePanel().apply { + setContent { + ProcessingTheme { + val locale = LocalLocale.current + this@PDEWindow.title = locale[titleKey] + + Box(modifier = Modifier.padding(top = if (mac) 22.dp else 0.dp)) { + content() + } + } + } + + this@PDEWindow.add(this) + } + pack() + background = java.awt.Color.white + setLocationRelativeTo(null) + addKeyListener(object : KeyAdapter() { + override fun keyPressed(e: KeyEvent) { + if (e.keyCode == KeyEvent.VK_ESCAPE) this@PDEWindow.dispose() + } + }) + isResizable = false + isVisible = true + requestFocus() + } +} + +fun pdeapplication(titleKey: String = "",content: @Composable () -> Unit){ + application { + val windowState = rememberWindowState( + size = DpSize.Unspecified, + position = WindowPosition(Alignment.Center) + ) + ProcessingTheme { + val locale = LocalLocale.current + val mac = SystemInfo.isMacFullWindowContentSupported + Window(onCloseRequest = ::exitApplication, state = windowState, title = locale[titleKey]) { + window.rootPane.apply { + putClientProperty("apple.awt.fullWindowContent", mac) + putClientProperty("apple.awt.transparentTitleBar", mac) + } + Surface(color = colors.background) { + Box(modifier = Modifier.padding(top = if (mac) 22.dp else 0.dp)) { + content() + } + } + } + } + } +} \ No newline at end of file