From 96f2a02cfad50881c156cccd66cbbcee2214b6d2 Mon Sep 17 00:00:00 2001 From: Karl Tauber Date: Mon, 9 May 2022 23:28:40 +0200 Subject: [PATCH] UIDefaultsLoader: added over() color function to convert a translucent color into a solid color based on any background color --- .../com/formdev/flatlaf/UIDefaultsLoader.java | 34 ++++++++++++++++++- .../themeeditor/FlatCompletionProvider.java | 4 +++ .../themeeditor/FlatThemeTokenMaker.java | 1 + .../theme-editor-test.properties | 6 ++++ 4 files changed, 44 insertions(+), 1 deletion(-) diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/UIDefaultsLoader.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/UIDefaultsLoader.java index dc47bba7..ac82bd22 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/UIDefaultsLoader.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/UIDefaultsLoader.java @@ -466,6 +466,10 @@ class UIDefaultsLoader if( knownValueTypes == null ) { // create lazy knownValueTypes = new HashMap<>(); + // system colors + knownValueTypes.put( "activeCaptionBorder", ValueType.COLOR ); + knownValueTypes.put( "inactiveCaptionBorder", ValueType.COLOR ); + knownValueTypes.put( "windowBorder", ValueType.COLOR ); // SplitPane knownValueTypes.put( "SplitPane.dividerSize", ValueType.INTEGER ); knownValueTypes.put( "SplitPaneDivider.gripDotSize", ValueType.INTEGER ); @@ -780,6 +784,7 @@ class UIDefaultsLoader case "tint": return parseColorMix( "#fff", params, resolver, reportError ); case "shade": return parseColorMix( "#000", params, resolver, reportError ); case "contrast": return parseColorContrast( params, resolver, reportError ); + case "over": return parseColorOver( params, resolver, reportError ); } } finally { parseColorDepth--; @@ -847,7 +852,7 @@ class UIDefaultsLoader int lightness = parsePercentage( params.get( 2 ) ); int alpha = hasAlpha ? parsePercentage( params.get( 3 ) ) : 100; - float[] hsl = new float[] { hue, saturation, lightness }; + float[] hsl = { hue, saturation, lightness }; return new ColorUIResource( HSLColor.toRGB( hsl, alpha / 100f ) ); } @@ -1041,6 +1046,33 @@ class UIDefaultsLoader return parseColorOrFunction( resolver.apply( darkOrLightColor ), resolver, reportError ); } + /** + * Syntax: over(foreground,background) + * - foreground: a foreground color (e.g. #f00) or a color function; + * the alpha of this color is used as weight to mix the two colors + * - background: a background color (e.g. #f00) or a color function + */ + private static Object parseColorOver( List params, Function resolver, boolean reportError ) { + String foregroundStr = params.get( 0 ); + String backgroundStr = params.get( 1 ); + + // parse foreground color + ColorUIResource foreground = (ColorUIResource) parseColorOrFunction( resolver.apply( foregroundStr ), resolver, reportError ); + if( foreground == null || foreground.getAlpha() == 255 ) + return foreground; + + Color foreground2 = new Color( foreground.getRGB() ); + + // parse background color + ColorUIResource background = (ColorUIResource) parseColorOrFunction( resolver.apply( backgroundStr ), resolver, reportError ); + if( background == null ) + return foreground2; + + // create new color + float weight = foreground.getAlpha() / 255f; + return new ColorUIResource( ColorFunctions.mix( foreground2, background, weight ) ); + } + private static Object parseFunctionBaseColor( String colorStr, ColorFunction function, boolean derived, Function resolver, boolean reportError ) { diff --git a/flatlaf-theme-editor/src/main/java/com/formdev/flatlaf/themeeditor/FlatCompletionProvider.java b/flatlaf-theme-editor/src/main/java/com/formdev/flatlaf/themeeditor/FlatCompletionProvider.java index 8d2f1b06..71959f4c 100644 --- a/flatlaf-theme-editor/src/main/java/com/formdev/flatlaf/themeeditor/FlatCompletionProvider.java +++ b/flatlaf-theme-editor/src/main/java/com/formdev/flatlaf/themeeditor/FlatCompletionProvider.java @@ -482,6 +482,10 @@ class FlatCompletionProvider "dark", colorParamDesc, "light", colorParamDesc, "threshold", "(optional) 0-100%, default is 43%" ); + + addFunction( "over", + "foreground", colorParamDesc, + "background", colorParamDesc ); } private void addFunction( String name, String... paramNamesAndDescs ) { diff --git a/flatlaf-theme-editor/src/main/java/com/formdev/flatlaf/themeeditor/FlatThemeTokenMaker.java b/flatlaf-theme-editor/src/main/java/com/formdev/flatlaf/themeeditor/FlatThemeTokenMaker.java index b8eac587..1aaa8202 100644 --- a/flatlaf-theme-editor/src/main/java/com/formdev/flatlaf/themeeditor/FlatThemeTokenMaker.java +++ b/flatlaf-theme-editor/src/main/java/com/formdev/flatlaf/themeeditor/FlatThemeTokenMaker.java @@ -76,6 +76,7 @@ public class FlatThemeTokenMaker tokenMap.put( "tint", TOKEN_FUNCTION ); tokenMap.put( "shade", TOKEN_FUNCTION ); tokenMap.put( "contrast", TOKEN_FUNCTION ); + tokenMap.put( "over", TOKEN_FUNCTION ); // function options tokenMap.put( "relative", Token.RESERVED_WORD ); diff --git a/flatlaf-theme-editor/theme-editor-test.properties b/flatlaf-theme-editor/theme-editor-test.properties index fa4bf4e5..50d46d2a 100644 --- a/flatlaf-theme-editor/theme-editor-test.properties +++ b/flatlaf-theme-editor/theme-editor-test.properties @@ -118,6 +118,12 @@ Prop.6.selectionForeground = contrast($Prop.6.selectionBackground,#000,#fff) Prop.7.selectionBackground = #FF9500 Prop.7.selectionForeground = contrast($Prop.7.selectionBackground,#000,#fff) +Prop.colorFunc60 = over(#fff8,#f00) +Prop.colorFunc61 = over(#fff8,#0f0) +Prop.colorFunc62 = over(#f000,#0f0) +Prop.colorFunc63 = over(#f00,#0f0) +Prop.colorFunc64 = over(#f008,null) + @varStyle1 = #f0f