Merge pull request #962 from Stefterv/gradle-beta-indicator

Processing Beta Indicator
This commit is contained in:
Stef Tervelde
2025-03-14 14:55:25 +01:00
committed by GitHub
15 changed files with 740 additions and 30 deletions

View File

@@ -0,0 +1,11 @@
package processing.app.ui;
// Stub class for backwards compatibility with the ant-build system
// This class is not used in the Gradle build system
// The actual implementation is in src/.../Schema.kt
public class WelcomeToBeta {
public static void showWelcomeToBeta(){
}
}

View File

@@ -8,6 +8,8 @@ import java.io.FileOutputStream
import java.util.zip.ZipEntry
import java.util.zip.ZipOutputStream
// TODO: Update to 2.10.20 and add hot-reloading: https://github.com/JetBrains/compose-hot-reload
plugins{
id("java")
kotlin("jvm") version libs.versions.kotlin
@@ -32,6 +34,9 @@ sourceSets{
kotlin{
srcDirs("src")
}
resources{
srcDirs("resources", listOf("languages", "fonts", "theme").map { "../build/shared/lib/$it" })
}
}
test{
kotlin{
@@ -108,6 +113,8 @@ dependencies {
implementation(libs.compottie)
implementation(libs.kaml)
implementation(libs.markdown)
implementation(libs.markdownJVM)
testImplementation(kotlin("test"))
testImplementation(libs.mockitoKotlin)

View File

@@ -0,0 +1,5 @@
<svg width="900" height="900" viewBox="0 0 900 900" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M456.735 552.393L155.9 151.279" stroke="#A44D28" stroke-width="150.418"/>
<path d="M757.575 452.113C456.738 552.391 456.738 752.948 155.903 652.67" stroke="#FF7D45" stroke-width="150.418"/>
<path d="M556.832 552.392L456.555 51" stroke="#FFBEA2" stroke-width="150.418"/>
</svg>

After

Width:  |  Height:  |  Size: 386 B

View File

@@ -0,0 +1,309 @@
# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
# DO NOT MAKE CHANGES TO THIS FILE!!!
# These are the default preferences. If you want to modify
# them directly, use the per-user local version of the file:
# Users -> [username] -> AppData -> Roaming ->
# Processing -> preferences.txt (on Windows 10)
# ~/Library -> Processing -> preferences.txt (on macOS)
# ~/.config/processing -> preferences.txt (on Linux)
# The exact location of your preferences file can be found at
# the bottom of the Preferences window inside Processing.
# Because AppData and Application Data may be considered
# hidden or system folders on Windows, you'll have to ensure
# that they're visible in order to get at preferences.txt
# You'll have problems running Processing if you incorrectly
# modify lines in this file. It will probably not start at all.
# AGAIN, DO NOT ALTER THIS FILE! I'M ONLY YELLING BECAUSE I LOVE YOU!
# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
# If you don't want users to have their sketchbook default to
# "My Documents/Processing" on Windows and "Documents/Processing" on OS X,
# set this to another path that will be used by default.
# Note that this path must exist already otherwise it won't see
# the sketchbook folder, and will instead assume the sketchbook
# has gone missing, and that it should instead use the default.
# In 4.0, the location has changed.
#sketchbook.path.four=
# Whether or not to show the Welcome screen for 4.0
# (It's always available under Help → Welcome)
welcome.four.show = true
welcome.four.seen = false
# Set 'true' for the default behavior before 4.0, where the
# main tab must have the same name as the sketch folder
editor.sync_folder_and_filename = true
# By default, contributions are moved to backup folders when
# they are removed or replaced. The backups can be found at
# sketchbook/libraries/old, sketchbook/tools/old, and sketchbook/modes/old
# true to backup contributions when "Remove" button is pressed
contribution.backup.on_remove = true
# true to backup contributions when installing a newer version
contribution.backup.on_install = true
recent.count = 10
# Default to the native (AWT) file selector where possible
chooser.files.native = true
# We were shutting this off on macOS because it broke Copy/Paste:
# https://github.com/processing/processing/issues/1035
# But removing again for 4.0 alpha 5, because the JFileChooser is awful,
# and worse on Big Sur, so a bigger problem than the Copy/Paste issue.
# https://github.com/processing/processing4/issues/77
#chooser.files.native.macos = false
# set to 'lab' to interpolate theme gradients using L*a*b* color space
theme.gradient.method = rgb
# by default, check the processing server for any updates
# (please avoid disabling, this also helps us know basic numbers
# on how many people are using Processing)
update.check = true
# on windows, automatically associate .pde files with processing.exe
platform.auto_file_type_associations = true
# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
# default size for the main window
editor.window.width.default = 700
editor.window.height.default = 600
editor.window.width.min = 400
editor.window.height.min = 500
# tested as approx 440 on OS X
editor.window.height.min.macos = 450
# tested to be 515 on Windows XP, this leaves some room
editor.window.height.min.windows = 530
# tested with Raspberry Pi display
editor.window.height.min.linux = 480
# scaling for the interface (to handle Windows and Linux HiDPI displays)
editor.zoom = 100%
# automatically set based on system dpi (only helps on Windows)
editor.zoom.auto = true
# Use the default monospace font included in lib/fonts.
# (As of Processing 4 alpha 5, that's Source Code Pro)
editor.font.family = processing.mono
editor.font.size = 12
# To reset everyone's default, replaced editor.antialias with editor.smooth
# for 2.1. Fonts are unusably gross on OS X (and Linux) w/o smoothing and
# the Oracle JVM, and many longtime users have anti-aliasing turned off.
editor.smooth = true
# blink the caret by default
editor.caret.blink = true
# change to true to use a block (instead of a bar)
editor.caret.block = false
# enable ctrl-ins, shift-ins, shift-delete for cut/copy/paste
# on windows and linux, but disable on the mac
editor.keys.alternative_cut_copy_paste = true
editor.keys.alternative_cut_copy_paste.macos = false
# true if shift-backspace sends the delete character,
# false if shift-backspace just means backspace
editor.keys.shift_backspace_is_delete = false
# home and end keys should only travel to the start/end of the current line
editor.keys.home_and_end_travel_far = false
# home and end keys move to the first/last non-whitespace character,
# and move to the actual start/end when pressed a second time.
# Only works if editor.keys.home_and_end_travel_far is false.
editor.keys.home_and_end_travel_smart = true
# The OS X HI Guidelines say that home/end are relative to the document,
# but that drives some people nuts. This pref enables/disables it.
editor.keys.home_and_end_travel_far.macos = true
# Enable/disable support for complex scripts. Used for Japanese and others,
# but disable when not needed, otherwise basic Western European chars break.
editor.input_method_support = false
# convert tabs to spaces? how many spaces?
editor.tabs.expand = true
editor.tabs.size = 2
# Set to true to automatically close [ { ( " and '
editor.completion.auto_close = false
# automatically indent each line
editor.indent = true
# Whether to check files to see if they've been modified externally
editor.watcher = true
# Set true to enable debugging, since this is quirky on others' machines
editor.watcher.debug = false
# The window of time (in milliseconds) in which a change won't be counted
editor.watcher.window = 1500
# Format and search engine to use for online queries
search.format = https://google.com/search?q=%s
# font choice and size for the console
console.font.size = 12
# number of lines to show by default
console.lines = 4
# Number of blank lines to advance/clear console.
# Note that those lines are also printed in the terminal when
# Processing is executed there.
# Setting to 0 stops this behavior.
console.head_padding = 10
# Set to false to disable automatically clearing the console
# each time 'run' is hit
# If one sets it to false, one may also want to set 'console.head_padding'
# to a positive number to separate outputs from different runs.
console.auto_clear = true
# number of days of history to keep around before cleaning
# setting to 0 will never clean files
console.temp.days = 7
# set the maximum number of lines remembered by the console
# the default is 500, lengthen at your own peril
console.scrollback.lines = 500
console.scrollback.chars = 40000
# Any additional Java options when running.
# If you change this and can't run things, it's your own durn fault.
run.options =
# settings for the -XmsNNNm and -XmxNNNm command line option
run.options.memory = false
run.options.memory.initial = 64
run.options.memory.maximum = 512
# Index of the display to use for running sketches (starts at 1).
# Kept this 1-indexed because older vesions of Processing were setting
# the preference even before it was being used.
# -1 means the default display, 0 means all displays
run.display = -1
# set internally because it comes from the system
#run.window.bgcolor=
# set to false to open a new untitled window when closing the last window
# (otherwise, the environment will quit)
# default to the relative norm for the different platforms,
# but the setting can be changed in the prefs dialog anyway
#sketchbook.closing_last_window_quits = true
#sketchbook.closing_last_window_quits.macos = false
editor.untitled.prefix=sketch_
# The old (pre-1.0, back for 2.0) style for default sketch name.
# If you change this, be careful that this will work with your language
# settings. For instance, MMMdd won't work on Korean-language systems
# because it'll insert non-ASCII characters and break the environment.
# https://github.com/processing/processing/issues/322
editor.untitled.suffix=yyMMdd
# replace underscores in .pde file names with spaces
sketch.name.replace_underscore = true
# what to use for generating sketch names (change in the prefs window)
#sketch.name.approach =
# number of days of build history and other temp files to keep around
# these are kept around for debugging purposes, and in case code is lost
temp.days = 7
# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
# whether or not to export as full screen (present) mode
export.application.fullscreen = false
# whether to show the stop button when exporting to application
export.application.stop = true
# embed Java by default for lower likelihood of problems
export.application.embed_java = true
# set to false to no longer delete application folders before export
# (removed from the Preferences windows in 4.0 beta 9)
export.delete_target_folder = true
# may be useful when attempting to debug the preprocessor
preproc.save_build_files=false
# allows various preprocessor features to be toggled
# in case they are causing problems
# preprocessor: pde.g
preproc.color_datatype = true
preproc.web_colors = true
preproc.enhanced_casting = true
# preprocessor: PdeEmitter.java
preproc.substitute_floats = true
# PdePreproc.java
# writes out the parse tree as parseTree.xml, which can be usefully
# viewed in (at least) Mozilla or IE. useful when debugging the preprocessor.
preproc.output_parse_tree = false
# set to the program to be used for opening HTML files, folders, etc.
#launcher.linux = xdg-open
# FULL SCREEN (PRESENT MODE)
run.present.bgcolor = #666666
run.present.stop.color = #cccccc
# PROXIES
# Set a proxy server for folks that require it. This will allow the update
# checker and the contrib manager to run properly in those environments.
# This changed from proxy.host and proxy.port to proxy.http.host and
# proxy.http.port in 3.0a8. In addition, https and socks were added.
proxy.http.host=
proxy.http.port=
proxy.https.host=
proxy.https.port=
proxy.socks.host=
proxy.socks.port=
# Example of usage (replace 'http' with 'https' or 'socks' as needed)
#proxy.http.host=proxy.example.com
#proxy.http.port=8080
# Whether to use the system proxy by default
proxy.system=true
# PDE X
pdex.errorCheckEnabled = true
pdex.warningsEnabled = true
pdex.writeErrorLogs = false
pdex.autoSave.autoSaveEnabled = false
pdex.autoSaveInterval = 5
pdex.autoSave.promptDisplay = true
pdex.autoSave.autoSaveByDefault = true
# Enable auto-completion when hitting ctrl-space
pdex.completion = false
# Setting this true will show completions whenever available, not just after ctrl-space
pdex.completion.trigger = false
# Suggest libraries to import when a class is undefined/unavailable
pdex.suggest.imports = true
# Set to false to disable ctrl/cmd-click jump to definition
pdex.inspectMode.hotkey = true

View File

@@ -0,0 +1,5 @@
<svg width="800" height="800" viewBox="0 0 800 800" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M400 500C700 500 700 100 400 100" stroke="#0468FF" stroke-width="150"/>
<path d="M400 200L100 600" stroke="#1F34AB" stroke-width="150"/>
<path d="M100 300L200 500" stroke="#85AEFF" stroke-width="150"/>
</svg>

After

Width:  |  Height:  |  Size: 329 B

View File

@@ -1,11 +1,10 @@
package processing.app.contrib.ui
package processing.app
import androidx.compose.runtime.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import processing.app.Base
import processing.app.Platform
import java.io.File
import java.io.InputStream
import java.nio.file.*
import java.util.Properties
@@ -13,10 +12,13 @@ import java.util.Properties
const val PREFERENCES_FILE_NAME = "preferences.txt"
const val DEFAULTS_FILE_NAME = "defaults.txt"
fun PlatformStart(){
Platform.inst ?: Platform.init()
}
@Composable
fun loadPreferences(): Properties{
Platform.init()
PlatformStart()
val settingsFolder = Platform.getSettingsFolder()
val preferencesFile = settingsFolder.resolve(PREFERENCES_FILE_NAME)
@@ -24,20 +26,12 @@ fun loadPreferences(): Properties{
if(!preferencesFile.exists()){
preferencesFile.createNewFile()
}
val watched = watchFile(preferencesFile)
watchFile(preferencesFile)
val preferences by remember {
mutableStateOf(Properties())
return Properties().apply {
load(ClassLoader.getSystemResourceAsStream(DEFAULTS_FILE_NAME) ?: InputStream.nullInputStream())
load(preferencesFile.inputStream())
}
LaunchedEffect(watched){
val defaults = Base::class.java.getResourceAsStream("/lib/${DEFAULTS_FILE_NAME}") ?: return@LaunchedEffect
preferences.load(defaults)
preferences.load(preferencesFile.inputStream())
}
return preferences
}
@Composable
@@ -68,4 +62,12 @@ fun watchFile(file: File): Any? {
}
}
return event
}
val LocalPreferences = compositionLocalOf<Properties> { error("No preferences provided") }
@Composable
fun PreferencesProvider(content: @Composable () -> Unit){
val preferences = loadPreferences()
CompositionLocalProvider(LocalPreferences provides preferences){
content()
}
}

View File

@@ -31,6 +31,7 @@ import java.util.Random;
import javax.swing.JOptionPane;
import processing.app.ui.WelcomeToBeta;
import processing.core.PApplet;
@@ -116,7 +117,7 @@ public class UpdateCheck {
long now = System.currentTimeMillis();
if (lastString != null) {
long when = Long.parseLong(lastString);
if (now - when < ONE_DAY) {
if (now - when < ONE_DAY && !Base.DEBUG) {
// don't annoy the shit outta people
return;
}
@@ -134,6 +135,9 @@ public class UpdateCheck {
// offerToUpdateContributions = !promptToVisitDownloadPage();
promptToVisitDownloadPage();
}
if(latest < Base.getRevision()){
WelcomeToBeta.showWelcomeToBeta();
}
/*
if (offerToUpdateContributions) {

View File

@@ -12,8 +12,6 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.awt.ComposePanel
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.key.Key
import androidx.compose.ui.input.key.key
import androidx.compose.ui.input.pointer.PointerIcon
import androidx.compose.ui.input.pointer.pointerHoverIcon
import androidx.compose.ui.text.font.FontWeight
@@ -25,6 +23,7 @@ import com.charleskorn.kaml.Yaml
import com.charleskorn.kaml.YamlConfiguration
import kotlinx.serialization.Serializable
import processing.app.Platform
import processing.app.loadPreferences
import java.net.URL
import java.util.*
import javax.swing.JFrame
@@ -33,16 +32,7 @@ import kotlin.io.path.*
fun main() = application {
val active = remember { mutableStateOf(true) }
if(!active.value){
Window(onCloseRequest = ::exitApplication) {
}
return@application
}
Window(
onCloseRequest = { active.value = false },
) {
Window(onCloseRequest = ::exitApplication) {
contributionsManager()
}
}

View File

@@ -0,0 +1,211 @@
package processing.app.ui
import androidx.compose.animation.animateColorAsState
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.material.MaterialTheme
import androidx.compose.material.MaterialTheme.colors
import androidx.compose.material.MaterialTheme.typography
import androidx.compose.material.Surface
import androidx.compose.material.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.awt.ComposePanel
import androidx.compose.ui.graphics.Color
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.res.painterResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.DpSize
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
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 com.mikepenz.markdown.compose.Markdown
import com.mikepenz.markdown.m2.markdownColor
import com.mikepenz.markdown.m2.markdownTypography
import com.mikepenz.markdown.model.MarkdownColors
import com.mikepenz.markdown.model.MarkdownTypography
import processing.app.Base.getRevision
import processing.app.Base.getVersionName
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 java.awt.Cursor
import java.awt.Dimension
import java.awt.event.KeyAdapter
import java.awt.event.KeyEvent
import java.io.InputStream
import java.util.Properties
import javax.swing.JFrame
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()
}
}
}
@Composable
fun welcomeToBeta(close: () -> Unit = {}) {
Row(
modifier = Modifier
.padding(20.dp, 10.dp)
.size(windowSize.width.dp, windowSize.height.dp),
horizontalArrangement = Arrangement
.spacedBy(20.dp)
){
val locale = LocalLocale.current
Image(
painter = painterResource("bird.svg"),
contentDescription = locale["beta.logo"],
modifier = Modifier
.align(Alignment.CenterVertically)
.size(100.dp, 100.dp)
.offset(0.dp, (-25).dp)
)
Column(
modifier = Modifier
.fillMaxHeight(),
verticalArrangement = Arrangement
.spacedBy(
10.dp,
alignment = Alignment.CenterVertically
)
) {
Text(
text = locale["beta.title"],
style = typography.subtitle1,
)
val text = locale["beta.message"]
.replace('$' + "version", getVersionName())
.replace('$' + "revision", getRevision().toString())
Markdown(
text,
colors = markdownColor(),
typography = markdownTypography(text = typography.body1, link = typography.body1.copy(color = colors.primary)),
modifier = Modifier.background(Color.Transparent).padding(bottom = 10.dp)
)
Row {
Spacer(modifier = Modifier.weight(1f))
PDEButton(onClick = {
close()
}) {
Text(
text = locale["beta.button"],
color = colors.onPrimary
)
}
}
}
}
}
@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<String>) {
application {
val windowState = rememberWindowState(
size = DpSize.Unspecified,
position = WindowPosition(Alignment.Center)
)
Window(onCloseRequest = ::exitApplication, state = windowState, title = windowTitle) {
ProcessingTheme {
Surface(color = colors.background) {
welcomeToBeta {
exitApplication()
}
}
}
}
}
}
}
}

View File

@@ -0,0 +1,45 @@
package processing.app.ui.theme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.compositionLocalOf
import processing.app.LocalPreferences
import processing.app.Messages
import processing.app.Platform
import processing.app.PlatformStart
import processing.app.watchFile
import java.io.File
import java.io.InputStream
import java.util.*
class Locale(language: String = "") : Properties() {
init {
val locale = java.util.Locale.getDefault()
load(ClassLoader.getSystemResourceAsStream("PDE.properties"))
load(ClassLoader.getSystemResourceAsStream("PDE_${locale.language}.properties") ?: InputStream.nullInputStream())
load(ClassLoader.getSystemResourceAsStream("PDE_${locale.toLanguageTag()}.properties") ?: InputStream.nullInputStream())
load(ClassLoader.getSystemResourceAsStream("PDE_${language}.properties") ?: InputStream.nullInputStream())
}
@Deprecated("Use get instead", ReplaceWith("get(key)"))
override fun getProperty(key: String?, default: String): String {
val value = super.getProperty(key, default)
if(value == default) Messages.log("Missing translation for $key")
return value
}
operator fun get(key: String): String = getProperty(key, key)
}
val LocalLocale = compositionLocalOf { Locale() }
@Composable
fun LocaleProvider(content: @Composable () -> Unit) {
PlatformStart()
val settingsFolder = Platform.getSettingsFolder()
val languageFile = File(settingsFolder, "language.txt")
watchFile(languageFile)
val locale = Locale(languageFile.readText().substring(0, 2))
CompositionLocalProvider(LocalLocale provides locale) {
content()
}
}

View File

@@ -0,0 +1,75 @@
package processing.app.ui.theme
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.material.Colors
import androidx.compose.material.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.compositionLocalOf
import androidx.compose.ui.graphics.Color
import processing.app.LocalPreferences
import processing.app.PreferencesProvider
import java.io.InputStream
import java.util.Properties
class Theme(themeFile: String? = "") : Properties() {
init {
load(ClassLoader.getSystemResourceAsStream("theme.txt"))
load(ClassLoader.getSystemResourceAsStream(themeFile) ?: InputStream.nullInputStream())
}
fun getColor(key: String): Color {
return Color(getProperty(key).toColorInt())
}
}
val LocalTheme = compositionLocalOf<Theme> { error("No theme provided") }
@Composable
fun ProcessingTheme(
darkTheme: Boolean = isSystemInDarkTheme(),
content: @Composable() () -> Unit
) {
PreferencesProvider {
val preferences = LocalPreferences.current
val theme = Theme(preferences.getProperty("theme"))
val colors = Colors(
primary = theme.getColor("editor.gradient.top"),
primaryVariant = theme.getColor("toolbar.button.pressed.field"),
secondary = theme.getColor("editor.gradient.bottom"),
secondaryVariant = theme.getColor("editor.scrollbar.thumb.pressed.color"),
background = theme.getColor("editor.bgcolor"),
surface = theme.getColor("editor.bgcolor"),
error = theme.getColor("status.error.bgcolor"),
onPrimary = theme.getColor("toolbar.button.enabled.field"),
onSecondary = theme.getColor("toolbar.button.enabled.field"),
onBackground = theme.getColor("editor.fgcolor"),
onSurface = theme.getColor("editor.fgcolor"),
onError = theme.getColor("status.error.fgcolor"),
isLight = theme.getProperty("laf.mode").equals("light")
)
CompositionLocalProvider(LocalTheme provides theme) {
LocaleProvider {
MaterialTheme(
colors = colors,
typography = Typography,
content = content
)
}
}
}
}
fun String.toColorInt(): Int {
if (this[0] == '#') {
var color = substring(1).toLong(16)
if (length == 7) {
color = color or 0x00000000ff000000L
} else if (length != 9) {
throw IllegalArgumentException("Unknown color")
}
return color.toInt()
}
throw IllegalArgumentException("Unknown color")
}

View File

@@ -0,0 +1,38 @@
package processing.app.ui.theme
import androidx.compose.material.MaterialTheme.typography
import androidx.compose.material.Typography
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.platform.Font
import androidx.compose.ui.unit.sp
val processingFont = FontFamily(
Font(
resource = "ProcessingSans-Regular.ttf",
weight = FontWeight.Normal,
style = FontStyle.Normal
),
Font(
resource = "ProcessingSans-Bold.ttf",
weight = FontWeight.Bold,
style = FontStyle.Normal
)
)
val Typography = Typography(
body1 = TextStyle(
fontFamily = processingFont,
fontWeight = FontWeight.Normal,
fontSize = 13.sp,
lineHeight = 16.sp
),
subtitle1 = TextStyle(
fontFamily = processingFont,
fontWeight = FontWeight.Bold,
fontSize = 16.sp,
lineHeight = 20.sp
)
)

View File

@@ -613,7 +613,6 @@ update_check = Update
update_check.updates_available.core = A new version of Processing is available,\nwould you like to visit the Processing download page?
update_check.updates_available.contributions = There are updates available for some of the installed contributions,\nwould you like to open the the Contribution Manager now?
# ---------------------------------------
# Color Chooser

View File

@@ -315,6 +315,13 @@ update_check = Update
update_check.updates_available.core = Een nieuwe versie van Processing is beschikbaar,\nwilt u de Processing download pagina bezoeken?
update_check.updates_available.contributions = Er zijn updates beschikbaar voor sommige van de door u geïnstalleerde bijdragen,\nwilt u nu de Bijdragen Manager openen?
# ---------------------------------------
# Beta
beta.window.title = Welkom bij Beta
beta.title = Welkom bij de Processing Beta
beta.message = Bedankt dat je de nieuwe versie van Processing uitprobeert. We zijn je zeer dankbaar!\n\nMeld eventuele bugs alsjeblieft op de forums.
beta.button = Okee!
# ---------------------------------------
# Color Chooser

View File

@@ -25,6 +25,8 @@ netbeansSwing = { module = "org.netbeans.api:org-netbeans-swing-outline", versio
ant = { module = "org.apache.ant:ant", version = "1.10.14" }
lsp4j = { module = "org.eclipse.lsp4j:org.eclipse.lsp4j", version = "0.22.0" }
jsoup = { module = "org.jsoup:jsoup", version = "1.17.2" }
markdown = { module = "com.mikepenz:multiplatform-markdown-renderer-m2", version = "0.31.0" }
markdownJVM = { module = "com.mikepenz:multiplatform-markdown-renderer-jvm", version = "0.31.0" }
[plugins]
jetbrainsCompose = { id = "org.jetbrains.compose", version.ref = "compose-plugin" }