You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by pa...@apache.org on 2026/04/19 10:44:44 UTC
(groovy) branch master updated: GROOVY-11932: Allow theme switching light/dark/system in groovyConsole (minor color tweaks)
This is an automated email from the ASF dual-hosted git repository.
paulk-asert pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/groovy.git
The following commit(s) were added to refs/heads/master by this push:
new 2f78e78e19 GROOVY-11932: Allow theme switching light/dark/system in groovyConsole (minor color tweaks)
2f78e78e19 is described below
commit 2f78e78e196da58183846695c6ef05a984faca3a
Author: Paul King <pa...@asert.com.au>
AuthorDate: Sun Apr 19 20:44:35 2026 +1000
GROOVY-11932: Allow theme switching light/dark/system in groovyConsole (minor color tweaks)
---
.../groovy/groovy/console/ui/ConsoleActions.groovy | 14 ++--
.../groovy/groovy/console/ui/ConsoleView.groovy | 12 ++--
.../src/main/groovy/groovy/console/ui/Icons.groovy | 75 +++++++++++++---------
.../groovy/console/ui/view/BasicToolBar.groovy | 8 +--
4 files changed, 60 insertions(+), 49 deletions(-)
diff --git a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/ConsoleActions.groovy b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/ConsoleActions.groovy
index cc642a83bb..1466b8fe88 100644
--- a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/ConsoleActions.groovy
+++ b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/ConsoleActions.groovy
@@ -139,7 +139,7 @@ cutAction = action(
closure: controller.&cut,
mnemonic: 'T',
accelerator: shortcut('X'),
- smallIcon: Icons.menu('content_cut'),
+ smallIcon: Icons.menuSubtleBlue('content_cut'),
shortDescription: 'Cut'
)
@@ -148,7 +148,7 @@ copyAction = action(
closure: controller.©,
mnemonic: 'C',
accelerator: shortcut('C'),
- smallIcon: Icons.menu('content_copy'),
+ smallIcon: Icons.menuSubtleBlue('content_copy'),
shortDescription: 'Copy'
)
@@ -157,7 +157,7 @@ pasteAction = action(
closure: controller.&paste,
mnemonic: 'P',
accelerator: shortcut('V'),
- smallIcon: Icons.menu('content_paste'),
+ smallIcon: Icons.menuSubtleBlue('content_paste'),
shortDescription: 'Paste'
)
@@ -165,7 +165,7 @@ selectAllAction = action(
name: 'Select All',
closure: controller.&selectAll,
mnemonic: 'A',
- smallIcon: Icons.menu('select_all'),
+ smallIcon: Icons.menuSubtleBlue('select_all'),
accelerator: shortcut('A')
)
@@ -213,7 +213,7 @@ runJavaAction = action(
closure: controller.&runJava,
mnemonic: 'J',
accelerator: shortcut('alt R'),
- smallIcon: Icons.menu('coffee'),
+ smallIcon: Icons.menuJavaBlue('coffee'),
shortDescription: 'Execute Java Code'
)
@@ -265,7 +265,7 @@ listClasspath = action(
clearClassloader = action(
name: 'Clear Script Context',
closure: controller.&clearContext,
- smallIcon: Icons.menu('bolt'),
+ smallIcon: Icons.menuAmber('bolt'),
mnemonic: 'C',
)
@@ -413,7 +413,7 @@ smartHighlighterAction = action(
aboutAction = action(
name: 'About',
closure: controller.&showAbout,
- smallIcon: Icons.menu('info'),
+ smallIcon: Icons.menuBlue('info'),
mnemonic: 'A'
)
diff --git a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/ConsoleView.groovy b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/ConsoleView.groovy
index cc71c74149..4119fb1c45 100644
--- a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/ConsoleView.groovy
+++ b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/ConsoleView.groovy
@@ -76,10 +76,10 @@ container(consoleFrame) {
// — override each action's smallIcon (which is OS-themed for the screen
// menu bar) with an app-themed instance here.
inputEditor.textEditor.componentPopupMenu = popupMenu {
- menuItem(cutAction, icon: Icons.load('content_cut'))
- menuItem(copyAction, icon: Icons.load('content_copy'))
- menuItem(pasteAction, icon: Icons.load('content_paste'))
- menuItem(selectAllAction, icon: Icons.load('select_all'))
+ menuItem(cutAction, icon: Icons.subtleBlue('content_cut'))
+ menuItem(copyAction, icon: Icons.subtleBlue('content_copy'))
+ menuItem(pasteAction, icon: Icons.subtleBlue('content_paste'))
+ menuItem(selectAllAction, icon: Icons.subtleBlue('select_all'))
separator()
menuItem(undoAction, icon: Icons.load('undo'))
menuItem(redoAction, icon: Icons.load('redo'))
@@ -89,8 +89,8 @@ inputEditor.textEditor.componentPopupMenu = popupMenu {
}
outputArea.componentPopupMenu = popupMenu {
- menuItem(copyAction, icon: Icons.load('content_copy'))
- menuItem(selectAllAction, icon: Icons.load('select_all'))
+ menuItem(copyAction, icon: Icons.subtleBlue('content_copy'))
+ menuItem(selectAllAction, icon: Icons.subtleBlue('select_all'))
menuItem(clearOutputAction, icon: Icons.load('delete_sweep'))
}
diff --git a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/Icons.groovy b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/Icons.groovy
index 8c9529f10b..2e7c2240bd 100644
--- a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/Icons.groovy
+++ b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/Icons.groovy
@@ -61,13 +61,14 @@ class Icons {
menuIcon(name, { Color c -> UIManager.getColor('Label.foreground') ?: c })
}
- static DynamicSVGIcon green(String name) {
- menuIcon(name, greenMapper({ ThemeManager.isDark() }))
- }
-
- static DynamicSVGIcon red(String name) {
- menuIcon(name, redMapper({ ThemeManager.isDark() }))
- }
+ static DynamicSVGIcon green(String name) { menuIcon(name, greenMapper({ ThemeManager.isDark() })) }
+ static DynamicSVGIcon red(String name) { menuIcon(name, redMapper({ ThemeManager.isDark() })) }
+ static DynamicSVGIcon blue(String name) { menuIcon(name, blueMapper({ ThemeManager.isDark() })) }
+ static DynamicSVGIcon amber(String name) { menuIcon(name, amberMapper({ ThemeManager.isDark() })) }
+ static DynamicSVGIcon violet(String name) { menuIcon(name, violetMapper({ ThemeManager.isDark() })) }
+ static DynamicSVGIcon teal(String name) { menuIcon(name, tealMapper({ ThemeManager.isDark() })) }
+ static DynamicSVGIcon javaBlue(String name) { menuIcon(name, javaBlueMapper({ ThemeManager.isDark() })) }
+ static DynamicSVGIcon subtleBlue(String name) { menuIcon(name, subtleBlueMapper({ ThemeManager.isDark() })) }
// ---- main menu-bar icons (tint follows the menu-bar background, which is OS-drawn on macOS) ----
@@ -75,13 +76,14 @@ class Icons {
menuIcon(name, { Color c -> ThemeManager.menuIconForeground ?: c })
}
- static DynamicSVGIcon menuGreen(String name) {
- menuIcon(name, greenMapper({ ThemeManager.isMenuDark() }))
- }
-
- static DynamicSVGIcon menuRed(String name) {
- menuIcon(name, redMapper({ ThemeManager.isMenuDark() }))
- }
+ static DynamicSVGIcon menuGreen(String name) { menuIcon(name, greenMapper({ ThemeManager.isMenuDark() })) }
+ static DynamicSVGIcon menuRed(String name) { menuIcon(name, redMapper({ ThemeManager.isMenuDark() })) }
+ static DynamicSVGIcon menuBlue(String name) { menuIcon(name, blueMapper({ ThemeManager.isMenuDark() })) }
+ static DynamicSVGIcon menuAmber(String name) { menuIcon(name, amberMapper({ ThemeManager.isMenuDark() })) }
+ static DynamicSVGIcon menuViolet(String name) { menuIcon(name, violetMapper({ ThemeManager.isMenuDark() })) }
+ static DynamicSVGIcon menuTeal(String name) { menuIcon(name, tealMapper({ ThemeManager.isMenuDark() })) }
+ static DynamicSVGIcon menuJavaBlue(String name) { menuIcon(name, javaBlueMapper({ ThemeManager.isMenuDark() })) }
+ static DynamicSVGIcon menuSubtleBlue(String name) { menuIcon(name, subtleBlueMapper({ ThemeManager.isMenuDark() })) }
// ---- toolbar / resizable ----
@@ -89,24 +91,33 @@ class Icons {
toolbarIcon(name, { Color c -> UIManager.getColor('Label.foreground') ?: c })
}
- static DynamicSVGIcon toolbarGreen(String name) {
- toolbarIcon(name, greenMapper({ ThemeManager.isDark() }))
- }
-
- static DynamicSVGIcon toolbarRed(String name) {
- toolbarIcon(name, redMapper({ ThemeManager.isDark() }))
- }
-
- private static Closure<Color> greenMapper(Closure<Boolean> darkCheck) {
- Color light = new Color(0x2E7D32)
- Color dark = new Color(0x81C784)
- return { Color c -> darkCheck() ? dark : light }
- }
-
- private static Closure<Color> redMapper(Closure<Boolean> darkCheck) {
- Color light = new Color(0xC62828)
- Color dark = new Color(0xEF5350)
- return { Color c -> darkCheck() ? dark : light }
+ static DynamicSVGIcon toolbarGreen(String name) { toolbarIcon(name, greenMapper({ ThemeManager.isDark() })) }
+ static DynamicSVGIcon toolbarRed(String name) { toolbarIcon(name, redMapper({ ThemeManager.isDark() })) }
+ static DynamicSVGIcon toolbarBlue(String name) { toolbarIcon(name, blueMapper({ ThemeManager.isDark() })) }
+ static DynamicSVGIcon toolbarAmber(String name) { toolbarIcon(name, amberMapper({ ThemeManager.isDark() })) }
+ static DynamicSVGIcon toolbarViolet(String name) { toolbarIcon(name, violetMapper({ ThemeManager.isDark() })) }
+ static DynamicSVGIcon toolbarTeal(String name) { toolbarIcon(name, tealMapper({ ThemeManager.isDark() })) }
+ static DynamicSVGIcon toolbarJavaBlue(String name) { toolbarIcon(name, javaBlueMapper({ ThemeManager.isDark() })) }
+ static DynamicSVGIcon toolbarSubtleBlue(String name) { toolbarIcon(name, subtleBlueMapper({ ThemeManager.isDark() })) }
+
+ // Material "700" for light theme / "400" for dark — muted enough not to
+ // shout next to grayscale neighbours, lifted in value for dark readability
+ private static Closure<Color> greenMapper (Closure<Boolean> darkCheck) { hueMapper(darkCheck, 0x2E7D32, 0x81C784) }
+ private static Closure<Color> redMapper (Closure<Boolean> darkCheck) { hueMapper(darkCheck, 0xC62828, 0xEF5350) }
+ private static Closure<Color> blueMapper (Closure<Boolean> darkCheck) { hueMapper(darkCheck, 0x1565C0, 0x64B5F6) }
+ private static Closure<Color> amberMapper (Closure<Boolean> darkCheck) { hueMapper(darkCheck, 0xEF6C00, 0xFFB74D) }
+ private static Closure<Color> violetMapper(Closure<Boolean> darkCheck) { hueMapper(darkCheck, 0x7E57C2, 0xB39DDB) }
+ private static Closure<Color> tealMapper (Closure<Boolean> darkCheck) { hueMapper(darkCheck, 0x00838F, 0x4DD0E1) }
+ // Official Java brand blue (#007396) for light; a lifted variant for dark
+ private static Closure<Color> javaBlueMapper(Closure<Boolean> darkCheck) { hueMapper(darkCheck, 0x007396, 0x4DB6E3) }
+ // Blue-leaning slate — reads as "almost the text colour" but with enough
+ // blue to group related but unremarkable actions (cut/copy/paste).
+ private static Closure<Color> subtleBlueMapper(Closure<Boolean> darkCheck) { hueMapper(darkCheck, 0x4A6A8A, 0xA0B5CC) }
+
+ private static Closure<Color> hueMapper(Closure<Boolean> darkCheck, int light, int dark) {
+ Color lightColor = new Color(light)
+ Color darkColor = new Color(dark)
+ return { Color c -> darkCheck() ? darkColor : lightColor }
}
private static DynamicSVGIcon menuIcon(String name, Closure<Color> mapper) {
diff --git a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/view/BasicToolBar.groovy b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/view/BasicToolBar.groovy
index 98db7ec925..07cd511532 100644
--- a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/view/BasicToolBar.groovy
+++ b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/view/BasicToolBar.groovy
@@ -34,9 +34,9 @@ toolbar = toolBar(rollover: true, visible: controller.showToolbar, constraints:
button(undoAction, text: null, icon: Icons.toolbar('undo'))
button(redoAction, text: null, icon: Icons.toolbar('redo'))
separator(orientation: SwingConstants.VERTICAL)
- button(cutAction, text: null, icon: Icons.toolbar('content_cut'))
- button(copyAction, text: null, icon: Icons.toolbar('content_copy'))
- button(pasteAction, text: null, icon: Icons.toolbar('content_paste'))
+ button(cutAction, text: null, icon: Icons.toolbarSubtleBlue('content_cut'))
+ button(copyAction, text: null, icon: Icons.toolbarSubtleBlue('content_copy'))
+ button(pasteAction, text: null, icon: Icons.toolbarSubtleBlue('content_paste'))
separator(orientation: SwingConstants.VERTICAL)
button(findAction, text: null, icon: Icons.toolbar('search'))
button(replaceAction, text: null, icon: Icons.toolbar('find_replace'))
@@ -52,5 +52,5 @@ toolbar = toolBar(rollover: true, visible: controller.showToolbar, constraints:
button(smallerFontAction, text: null, icon: Icons.toolbar('text_decrease'))
button(largerFontAction, text: null, icon: Icons.toolbar('text_increase'))
separator(orientation: SwingConstants.VERTICAL)
- button(cycleThemeAction, text: null, icon: Icons.toolbar('refresh'))
+ button(cycleThemeAction, text: null, icon: Icons.toolbarViolet('refresh'))
}