Skip to content

Commit 77eba30

Browse files
authored
Theming (#1298)
* Add Material3-based Processing theme and typography Introduces Colors.kt with custom color schemes for light and dark themes using Material3. Refactors Theme.kt to use Material3 theming, adds a PDETheme composable, and provides a desktop preview app for theme components. Updates Typography.kt to use Space Grotesk font family and defines new typography styles for Material3. * Refactor to use Material3 and update theme usage Replaces Material2 components with Material3 in WelcomeToBeta, removes custom PDEButton in favor of Material3 Button, and updates theme usage to PDETheme. Also simplifies background modifier in PDETheme and removes unused Kotlin Multiplatform plugin from build.gradle.kts. * Add Space Grotesk font files and license Includes SpaceGrotesk font variants (Bold, Light, Medium, Regular, SemiBold) and the associated SIL Open Font License. This enables usage of the Space Grotesk typeface in the project. * Update markdown renderer to m3 and adjust UI Switched markdown renderer imports from m2 to m3 and updated the dependency version to 0.37.0. Adjusted WelcomeToBeta window size, layout, and logo dimensions for improved appearance. Ensured Box in Theme.kt fills available space for better layout consistency.
1 parent bf4d163 commit 77eba30

File tree

13 files changed

+700
-137
lines changed

13 files changed

+700
-137
lines changed

app/build.gradle.kts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ plugins{
1717

1818
alias(libs.plugins.compose.compiler)
1919
alias(libs.plugins.jetbrainsCompose)
20+
2021
alias(libs.plugins.serialization)
2122
alias(libs.plugins.download)
2223
}
@@ -60,7 +61,7 @@ compose.desktop {
6061
).map { "-D${it.first}=${it.second}" }.toTypedArray())
6162

6263
nativeDistributions{
63-
modules("jdk.jdi", "java.compiler", "jdk.accessibility", "java.management.rmi", "java.scripting", "jdk.httpserver")
64+
modules("jdk.jdi", "java.compiler", "jdk.accessibility", "jdk.zipfs", "java.management.rmi", "java.scripting", "jdk.httpserver")
6465
targetFormats(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb)
6566
packageName = "Processing"
6667

@@ -108,27 +109,29 @@ dependencies {
108109

109110
implementation(compose.runtime)
110111
implementation(compose.foundation)
111-
implementation(compose.material)
112112
implementation(compose.ui)
113113
implementation(compose.components.resources)
114114
implementation(compose.components.uiToolingPreview)
115+
implementation(compose.materialIconsExtended)
115116

116117
implementation(compose.desktop.currentOs)
118+
implementation(libs.material3)
117119

118120
implementation(libs.compottie)
119121
implementation(libs.kaml)
120122
implementation(libs.markdown)
121123
implementation(libs.markdownJVM)
122124

125+
implementation(libs.clikt)
126+
implementation(libs.kotlinxSerializationJson)
127+
123128
@OptIn(ExperimentalComposeLibrary::class)
124129
testImplementation(compose.uiTest)
125130
testImplementation(kotlin("test"))
126131
testImplementation(libs.mockitoKotlin)
127132
testImplementation(libs.junitJupiter)
128133
testImplementation(libs.junitJupiterParams)
129-
130-
implementation(libs.clikt)
131-
implementation(libs.kotlinxSerializationJson)
134+
132135
}
133136

134137
tasks.test {

app/src/processing/app/ui/WelcomeToBeta.kt

Lines changed: 20 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@ import androidx.compose.animation.core.animateFloatAsState
55
import androidx.compose.foundation.Image
66
import androidx.compose.foundation.background
77
import androidx.compose.foundation.layout.*
8-
import androidx.compose.material.MaterialTheme
9-
import androidx.compose.material.MaterialTheme.colors
10-
import androidx.compose.material.MaterialTheme.typography
11-
import androidx.compose.material.Surface
12-
import androidx.compose.material.Text
8+
import androidx.compose.material3.Button
9+
import androidx.compose.material3.MaterialTheme
10+
import androidx.compose.material3.MaterialTheme.typography
11+
import androidx.compose.material3.Surface
12+
import androidx.compose.material3.Text
1313
import androidx.compose.runtime.*
1414
import androidx.compose.ui.Alignment
1515
import androidx.compose.ui.ExperimentalComposeUiApi
@@ -31,17 +31,16 @@ import androidx.compose.ui.window.application
3131
import androidx.compose.ui.window.rememberWindowState
3232
import com.formdev.flatlaf.util.SystemInfo
3333
import com.mikepenz.markdown.compose.Markdown
34-
import com.mikepenz.markdown.m2.markdownColor
35-
import com.mikepenz.markdown.m2.markdownTypography
34+
import com.mikepenz.markdown.m3.markdownColor
35+
import com.mikepenz.markdown.m3.markdownTypography
3636
import com.mikepenz.markdown.model.MarkdownColors
3737
import com.mikepenz.markdown.model.MarkdownTypography
3838
import processing.app.Preferences
3939
import processing.app.Base.getRevision
4040
import processing.app.Base.getVersionName
4141
import processing.app.ui.theme.LocalLocale
42-
import processing.app.ui.theme.LocalTheme
4342
import processing.app.ui.theme.Locale
44-
import processing.app.ui.theme.ProcessingTheme
43+
import processing.app.ui.theme.PDETheme
4544
import java.awt.Cursor
4645
import java.awt.Dimension
4746
import java.awt.event.KeyAdapter
@@ -54,7 +53,7 @@ import javax.swing.SwingUtilities
5453

5554
class WelcomeToBeta {
5655
companion object{
57-
val windowSize = Dimension(400, 200)
56+
val windowSize = Dimension(400, 250)
5857
val windowTitle = Locale()["beta.window.title"]
5958

6059
@JvmStatic
@@ -72,7 +71,7 @@ class WelcomeToBeta {
7271
contentPane.add(ComposePanel().apply {
7372
size = windowSize
7473
setContent {
75-
ProcessingTheme {
74+
PDETheme(darkTheme = false) {
7675
Box(modifier = Modifier.padding(top = if (mac) 22.dp else 0.dp)) {
7776
welcomeToBeta(close)
7877
}
@@ -99,7 +98,7 @@ class WelcomeToBeta {
9998
Row(
10099
modifier = Modifier
101100
.padding(20.dp, 10.dp)
102-
.size(windowSize.width.dp, windowSize.height.dp),
101+
.fillMaxSize(),
103102
horizontalArrangement = Arrangement
104103
.spacedBy(20.dp)
105104
){
@@ -109,7 +108,7 @@ class WelcomeToBeta {
109108
contentDescription = locale["beta.logo"],
110109
modifier = Modifier
111110
.align(Alignment.CenterVertically)
112-
.size(100.dp, 100.dp)
111+
.size(120.dp)
113112
.offset(0.dp, (-25).dp)
114113
)
115114
Column(
@@ -123,88 +122,44 @@ class WelcomeToBeta {
123122
) {
124123
Text(
125124
text = locale["beta.title"],
126-
style = typography.subtitle1,
125+
style = typography.titleLarge,
127126
)
128127
val text = locale["beta.message"]
129128
.replace('$' + "version", getVersionName())
130129
.replace('$' + "revision", getRevision().toString())
131130
Markdown(
132131
text,
133132
colors = markdownColor(),
134-
typography = markdownTypography(text = typography.body1, link = typography.body1.copy(color = colors.primary)),
133+
typography = markdownTypography(),
135134
modifier = Modifier.background(Color.Transparent).padding(bottom = 10.dp)
136135
)
137136
Row {
138137
Spacer(modifier = Modifier.weight(1f))
139-
PDEButton(onClick = {
138+
Button(onClick = {
140139
close()
141140
}) {
142141
Text(
143142
text = locale["beta.button"],
144-
color = colors.onPrimary
143+
color = MaterialTheme.colorScheme.onPrimary
145144
)
146145
}
147146
}
148147
}
149148
}
150149
}
151-
@OptIn(ExperimentalComposeUiApi::class)
152-
@Composable
153-
fun PDEButton(onClick: () -> Unit, content: @Composable BoxScope.() -> Unit) {
154-
val theme = LocalTheme.current
155-
156-
var hover by remember { mutableStateOf(false) }
157-
var clicked by remember { mutableStateOf(false) }
158-
val offset by animateFloatAsState(if (hover) -5f else 5f)
159-
val color by animateColorAsState(if(clicked) colors.primaryVariant else colors.primary)
160-
161-
Box(modifier = Modifier.padding(end = 5.dp, top = 5.dp)) {
162-
Box(
163-
modifier = Modifier
164-
.offset((-offset).dp, (offset).dp)
165-
.background(theme.getColor("toolbar.button.pressed.field"))
166-
.matchParentSize()
167-
)
168-
Box(
169-
modifier = Modifier
170-
.onPointerEvent(PointerEventType.Press) {
171-
clicked = true
172-
}
173-
.onPointerEvent(PointerEventType.Release) {
174-
clicked = false
175-
onClick()
176-
}
177-
.onPointerEvent(PointerEventType.Enter) {
178-
hover = true
179-
}
180-
.onPointerEvent(PointerEventType.Exit) {
181-
hover = false
182-
}
183-
.pointerHoverIcon(PointerIcon(Cursor(Cursor.HAND_CURSOR)))
184-
.background(color)
185-
.padding(10.dp)
186-
.sizeIn(minWidth = 100.dp),
187-
contentAlignment = Alignment.Center,
188-
content = content
189-
)
190-
}
191-
}
192-
193150

194151
@JvmStatic
195152
fun main(args: Array<String>) {
196153
application {
197154
val windowState = rememberWindowState(
198-
size = DpSize.Unspecified,
155+
size = windowSize.let { DpSize(it.width.dp, it.height.dp) },
199156
position = WindowPosition(Alignment.Center)
200157
)
201158

202159
Window(onCloseRequest = ::exitApplication, state = windowState, title = windowTitle) {
203-
ProcessingTheme {
204-
Surface(color = colors.background) {
205-
welcomeToBeta {
206-
exitApplication()
207-
}
160+
PDETheme(darkTheme = false) {
161+
welcomeToBeta {
162+
exitApplication()
208163
}
209164
}
210165
}
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
package processing.app.ui.theme
2+
3+
import androidx.compose.material.Colors
4+
import androidx.compose.material3.darkColorScheme
5+
import androidx.compose.material3.lightColorScheme
6+
import androidx.compose.ui.graphics.Color
7+
8+
class ProcessingColors{
9+
companion object{
10+
val blue = Color(0xFF0251c8)
11+
val lightBlue = Color(0xFF82AFFF)
12+
13+
val deepBlue = Color(0xFF1e32aa)
14+
val darkBlue = Color(0xFF0F195A)
15+
16+
val white = Color(0xFFFFFFFF)
17+
val lightGray = Color(0xFFF5F5F5)
18+
val gray = Color(0xFFDBDBDB)
19+
val darkGray = Color(0xFF898989)
20+
val darkerGray = Color(0xFF727070)
21+
val veryDarkGray = Color(0xFF1E1E1E)
22+
val black = Color(0xFF0D0D0D)
23+
24+
val error = Color(0xFFFF5757)
25+
val errorContainer = Color(0xFFFFA6A6)
26+
27+
val p5Light = Color(0xFFfd9db9)
28+
val p5Mid = Color(0xFFff4077)
29+
val p5Dark = Color(0xFFaf1f42)
30+
31+
val foundationLight = Color(0xFFd4b2fe)
32+
val foundationMid = Color(0xFF9c4bff)
33+
val foundationDark = Color(0xFF5501a4)
34+
35+
val downloadInactive = Color(0xFF8890B3)
36+
val downloadBackgroundActive = Color(0x14508BFF)
37+
}
38+
}
39+
40+
@Deprecated("Use PDE3LightColor instead")
41+
val PDE2LightColors = Colors(
42+
primary = ProcessingColors.blue,
43+
primaryVariant = ProcessingColors.lightBlue,
44+
onPrimary = ProcessingColors.white,
45+
46+
secondary = ProcessingColors.deepBlue,
47+
secondaryVariant = ProcessingColors.darkBlue,
48+
onSecondary = ProcessingColors.white,
49+
50+
background = ProcessingColors.white,
51+
onBackground = ProcessingColors.darkBlue,
52+
53+
surface = ProcessingColors.lightGray,
54+
onSurface = ProcessingColors.darkerGray,
55+
56+
error = ProcessingColors.error,
57+
onError = ProcessingColors.white,
58+
59+
isLight = true,
60+
)
61+
62+
@Deprecated("Use PDE3DarkColor instead")
63+
val PDE2DarkColors = Colors(
64+
primary = ProcessingColors.deepBlue,
65+
primaryVariant = ProcessingColors.darkBlue,
66+
onPrimary = ProcessingColors.white,
67+
68+
secondary = ProcessingColors.lightBlue,
69+
secondaryVariant = ProcessingColors.blue,
70+
onSecondary = ProcessingColors.white,
71+
72+
background = ProcessingColors.veryDarkGray,
73+
onBackground = ProcessingColors.white,
74+
75+
surface = ProcessingColors.darkerGray,
76+
onSurface = ProcessingColors.lightGray,
77+
78+
error = ProcessingColors.error,
79+
onError = ProcessingColors.white,
80+
81+
isLight = false,
82+
)
83+
84+
val PDELightColor = lightColorScheme(
85+
primary = ProcessingColors.blue,
86+
onPrimary = ProcessingColors.white,
87+
88+
primaryContainer = ProcessingColors.downloadBackgroundActive,
89+
onPrimaryContainer = ProcessingColors.darkBlue,
90+
91+
secondary = ProcessingColors.deepBlue,
92+
onSecondary = ProcessingColors.white,
93+
94+
secondaryContainer = ProcessingColors.downloadInactive,
95+
onSecondaryContainer = ProcessingColors.white,
96+
97+
tertiary = ProcessingColors.p5Mid,
98+
onTertiary = ProcessingColors.white,
99+
100+
tertiaryContainer = ProcessingColors.p5Light,
101+
onTertiaryContainer = ProcessingColors.p5Dark,
102+
103+
background = ProcessingColors.white,
104+
onBackground = ProcessingColors.darkBlue,
105+
106+
surface = ProcessingColors.lightGray,
107+
onSurface = ProcessingColors.darkerGray,
108+
109+
error = ProcessingColors.error,
110+
onError = ProcessingColors.white,
111+
112+
errorContainer = ProcessingColors.errorContainer,
113+
onErrorContainer = ProcessingColors.white
114+
)
115+
116+
val PDEDarkColor = darkColorScheme(
117+
primary = ProcessingColors.deepBlue,
118+
onPrimary = ProcessingColors.white,
119+
120+
secondary = ProcessingColors.lightBlue,
121+
onSecondary = ProcessingColors.white,
122+
123+
tertiary = ProcessingColors.blue,
124+
onTertiary = ProcessingColors.white,
125+
126+
background = ProcessingColors.veryDarkGray,
127+
onBackground = ProcessingColors.white,
128+
129+
surface = ProcessingColors.darkerGray,
130+
onSurface = ProcessingColors.lightGray,
131+
132+
error = ProcessingColors.error,
133+
onError = ProcessingColors.white,
134+
)

0 commit comments

Comments
 (0)