Skip to content
Merged
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
7fecf27
Remove ContributionManager and ContributionPane UI files
Stefterv Oct 14, 2025
838ea14
Enhance Preferences reactivity and test coverage
Stefterv Oct 14, 2025
d459fd8
Merge branch 'clean-contributions-prototype' into preferenceskt-update
Stefterv Oct 14, 2025
e1e1e3a
Small bugfix for removed function
Stefterv Oct 14, 2025
20fa9be
Add compose ui test to the deps
Stefterv Oct 14, 2025
5ae8b84
Refactor theme system to Material 3 color schemes
Stefterv Oct 23, 2025
ca29800
Add PDEWelcome Composable UI screen
Stefterv Oct 23, 2025
3fd4ea9
Merge branch 'welcome-screen' into preferenceskt-update
Stefterv Oct 27, 2025
40a1188
Merge branch 'preferenceskt-update' into colors
Stefterv Oct 27, 2025
2fc5682
Initial layout
Stefterv Oct 27, 2025
6037275
Revamp welcome screen UI and add social icons
Stefterv Oct 27, 2025
33ad602
Add example previews to welcome screen
Stefterv Oct 27, 2025
20aac81
Add hover-activated play button to example previews
Stefterv Oct 27, 2025
e036cdf
Localize welcome screen UI strings
Stefterv Oct 27, 2025
d8f9d75
Add language selector and UI improvements to welcome screen
Stefterv Oct 28, 2025
97ab23e
Refactor example listing and randomize welcome sketches
Stefterv Oct 28, 2025
0ee8929
Refactor example handling to use Sketch objects
Stefterv Oct 28, 2025
8e32abf
Add vertical scrollbar to welcome screen examples
Stefterv Oct 28, 2025
2769a07
Add rounded corners to buttons in PDEWelcome
Stefterv Oct 28, 2025
3b5ea1d
Refactor PDEWelcome UI and add Sketch card composable
Stefterv Oct 28, 2025
bef00f9
Add unique window handling to prevent duplicates
Stefterv Oct 28, 2025
07e05be
Refactor dialog handling and improve AlertDialog UI
Stefterv Oct 28, 2025
3bdd00e
Set application window icon using Toolkit.setIcon
Stefterv Oct 28, 2025
65173d4
Simplify imports and update scrollbar colors in Theme.kt
Stefterv Oct 29, 2025
1143547
Removing the Preferences work to keep the PR clean
Stefterv Nov 4, 2025
bb0f531
Merge branch 'welcome-screen' into welcome-screen-impl
Stefterv Nov 4, 2025
0f1173f
Update background color in PDEWelcome UI
Stefterv Nov 6, 2025
ab9358f
Tweak welcome actions naming and order
SableRaf Nov 7, 2025
f19b256
Rather than setting the decorations app wide, just modify the editor …
Stefterv Nov 11, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions app/src/main/resources/icons/Discord.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 10 additions & 0 deletions app/src/main/resources/icons/GitHub.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions app/src/main/resources/icons/Instagram.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 3 additions & 9 deletions app/src/processing/app/Base.java
Original file line number Diff line number Diff line change
Expand Up @@ -375,13 +375,7 @@ static private void handleWelcomeScreen(Base base) {
// Needs to be shown after the first editor window opens, so that it
// shows up on top, and doesn't prevent an editor window from opening.
if (Preferences.getBoolean("welcome.four.show")) {
try {
new Welcome(base);
} catch (IOException e) {
Messages.showTrace("Unwelcoming",
"Please report this error to\n" +
"https://github.com/processing/processing4/issues", e, false);
}
PDEWelcomeKt.showWelcomeScreen(base);
}
}

Expand Down Expand Up @@ -609,7 +603,7 @@ public JMenu initDefaultFileMenu() {
defaultFileMenu.add(item);

item = Toolkit.newJMenuItemShift(Language.text("menu.file.examples"), 'O');
item.addActionListener(e -> thinkDifferentExamples());
item.addActionListener(e -> showExamplesFrame());
defaultFileMenu.add(item);

return defaultFileMenu;
Expand Down Expand Up @@ -1885,7 +1879,7 @@ public void handleRestart() {
// }


public void thinkDifferentExamples() {
public void showExamplesFrame() {
nextMode.showExamplesFrame();
}

Expand Down
187 changes: 168 additions & 19 deletions app/src/processing/app/Messages.kt
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,36 @@
*/
package processing.app

import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Error
import androidx.compose.material.icons.filled.Info
import androidx.compose.material.icons.filled.Warning
import androidx.compose.material3.*
import androidx.compose.runtime.Composable
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.awt.ComposeDialog
import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.layout.onSizeChanged
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.DpSize
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Window
import androidx.compose.ui.window.application
import androidx.compose.ui.window.rememberWindowState
import com.formdev.flatlaf.FlatLightLaf
import processing.app.ui.Toolkit
import java.awt.EventQueue
import processing.app.ui.theme.PDETheme
import java.awt.Dimension
import java.awt.Frame
import java.io.PrintWriter
import java.io.StringWriter
import javax.swing.JFrame
import javax.swing.JOptionPane
import javax.swing.UIManager


class Messages {
companion object {
Expand All @@ -37,10 +60,23 @@ class Messages {
if (Base.isCommandLine()) {
println("$title: $message")
} else {
JOptionPane.showMessageDialog(
Frame(), message, title,
JOptionPane.INFORMATION_MESSAGE
)
showDialog(title) { modifier, dismiss ->
AlertDialog(
modifier = modifier,
onDismissRequest = { },
shape = RectangleShape,
icon = { Icon(Icons.Default.Info, contentDescription = "Info!") },
title = { Text(title) },
text = { Text(message) },
confirmButton = {
Button(
onClick = { dismiss() }
) {
Text("OK")
}
}
)
}
}
}

Expand All @@ -57,10 +93,27 @@ class Messages {
if (Base.isCommandLine()) {
println("$title: $message")
} else {
JOptionPane.showMessageDialog(
Frame(), message, title,
JOptionPane.WARNING_MESSAGE
)
showDialog(title){ modifier, dismiss ->
AlertDialog(
modifier = modifier,
onDismissRequest = { },
shape = RectangleShape,
icon = { Icon(Icons.Default.Warning, contentDescription = "Alert!") },
iconContentColor = MaterialTheme.colorScheme.tertiary,
title = { Text(title) },
text = { Text(message) },
confirmButton = {
Button(
onClick = { dismiss() },
colors = ButtonDefaults.outlinedButtonColors(
contentColor = MaterialTheme.colorScheme.tertiary
)
) {
Text("OK")
}
}
)
}
}
e?.printStackTrace()
}
Expand All @@ -80,11 +133,30 @@ class Messages {
// proper parsing on the command line. Many have \n in them.
println("$title: $primary\n$secondary")
} else {
EventQueue.invokeLater {
JOptionPane.showMessageDialog(
JFrame(),
Toolkit.formatMessage(primary, secondary),
title, JOptionPane.WARNING_MESSAGE
showDialog(title){ modifier, dismiss ->
AlertDialog(
modifier = modifier,
onDismissRequest = { },
shape = RectangleShape,
icon = { Icon(Icons.Default.Warning, contentDescription = "Alert!") },
iconContentColor = MaterialTheme.colorScheme.tertiary,
title = { Text(title) },
text = {
Column {
Text(primary, fontWeight = FontWeight.Bold)
Text(secondary)
}
},
confirmButton = {
Button(
onClick = { dismiss() },
colors = ButtonDefaults.outlinedButtonColors(
contentColor = MaterialTheme.colorScheme.tertiary
)
) {
Text("OK")
}
}
)
}
}
Expand All @@ -102,10 +174,28 @@ class Messages {
if (Base.isCommandLine()) {
System.err.println("$title: $message")
} else {
JOptionPane.showMessageDialog(
Frame(), message, title,
JOptionPane.ERROR_MESSAGE
)
showDialog(title){ modifier, dismiss ->
AlertDialog(
modifier = modifier,
onDismissRequest = { },
shape = RectangleShape,
icon = { Icon(Icons.Default.Error, contentDescription = "Alert!") },
iconContentColor = MaterialTheme.colorScheme.error,
title = { Text(title) },
text = { Text(message) },
confirmButton = {
Button(
onClick = { dismiss() },
colors = ButtonDefaults.buttonColors(
containerColor = MaterialTheme.colorScheme.error,
contentColor = MaterialTheme.colorScheme.onError
)
) {
Text("OK")
}
}
)
}
}
e?.printStackTrace()
System.exit(1)
Expand Down Expand Up @@ -139,6 +229,8 @@ class Messages {
if (fatal) JOptionPane.ERROR_MESSAGE else JOptionPane.WARNING_MESSAGE
)



if (fatal) {
System.exit(1)
}
Expand Down Expand Up @@ -271,6 +363,63 @@ class Messages {
}
}

@OptIn(ExperimentalComposeUiApi::class)
fun showDialog(title: String, content: @Composable (modifier: Modifier, dismiss: () -> Unit) -> Unit) {
ComposeDialog().apply {
isModal = true
setTitle(title)
size = Dimension(400, 400)
rootPane.putClientProperty("apple.awt.fullWindowContent", true)
rootPane.putClientProperty("apple.awt.transparentTitleBar", true)
rootPane.putClientProperty("apple.awt.windowTitleVisible", false);


setContent {
PDETheme {
val density = LocalDensity.current
content(Modifier.onSizeChanged{
size = Dimension((it.width / density.density).toInt(), (it.height / density.density).toInt())
setLocationRelativeTo(null)
},::dispose)
}
}
setLocationRelativeTo(null)
isVisible = true
}
}

fun main(){
val types = mapOf(
"message" to { Messages.showMessage("Test Title", "This is a test message.") },
"warning" to { Messages.showWarning("Test Warning", "This is a test warning.", Exception("dfdsfjk")) },
"trace" to { Messages.showTrace("Test Trace", "This is a test trace.", Exception("Test Exception"), false) },
"tiered_warning" to { Messages.showWarningTiered("Test Tiered Warning", "Primary message", "Secondary message", null) },
"yes_no" to { Messages.showYesNoQuestion(null, "Test Yes/No", "Do you want to continue?", "Choose yes or no.") },
"custom_question" to { Messages.showCustomQuestion(null, "Test Custom Question", "Choose an option:", "Select one of the options below.", 1, "Option 1", "Option 2", "Option 3") },
"error" to { Messages.showError("Test Error", "This is a test error.", null) },
)
Platform.init()
UIManager.setLookAndFeel(FlatLightLaf())
application {
val state = rememberWindowState(
size = DpSize(500.dp, 300.dp)
)
Window(state = state, onCloseRequest = ::exitApplication, title = "Test Messages") {
PDETheme {
Column {
for ((type, action) in types) {
Button(onClick = { action() }, modifier = Modifier.padding(8.dp)) {
Text("Show $type dialog")
}
}
}
}
}

}

}

// Helper functions to give the base classes a color
fun String.formatClassName() = this
.replace("processing.", "")
Expand Down
Loading