UIDefaultsLoader: added fadein(), fadeout(), fade() and spin() color functions (inspired by Less CSS)

This commit is contained in:
Karl Tauber
2020-11-19 11:31:38 +01:00
parent 8b8ed0b9ff
commit 0101171159
9 changed files with 135 additions and 20 deletions

View File

@@ -586,13 +586,17 @@ class UIDefaultsLoader
case "darken": return parseColorHSLIncreaseDecrease( 2, false, params, resolver, reportError ); case "darken": return parseColorHSLIncreaseDecrease( 2, false, params, resolver, reportError );
case "saturate": return parseColorHSLIncreaseDecrease( 1, true, params, resolver, reportError ); case "saturate": return parseColorHSLIncreaseDecrease( 1, true, params, resolver, reportError );
case "desaturate": return parseColorHSLIncreaseDecrease( 1, false, params, resolver, reportError ); case "desaturate": return parseColorHSLIncreaseDecrease( 1, false, params, resolver, reportError );
case "fadein": return parseColorHSLIncreaseDecrease( 3, true, params, resolver, reportError );
case "fadeout": return parseColorHSLIncreaseDecrease( 3, false, params, resolver, reportError );
case "fade": return parseColorFade( params, resolver, reportError );
case "spin": return parseColorSpin( params, resolver, reportError );
} }
throw new IllegalArgumentException( "unknown color function '" + value + "'" ); throw new IllegalArgumentException( "unknown color function '" + value + "'" );
} }
/** /**
* Syntax: rgb(red,green,blue) or rgba(red,green,blue,alpha) or rgba(color,alpha) * Syntax: rgb(red,green,blue) or rgba(red,green,blue,alpha)
* - red: an integer 0-255 or a percentage 0-100% * - red: an integer 0-255 or a percentage 0-100%
* - green: an integer 0-255 or a percentage 0-100% * - green: an integer 0-255 or a percentage 0-100%
* - blue: an integer 0-255 or a percentage 0-100% * - blue: an integer 0-255 or a percentage 0-100%
@@ -603,6 +607,8 @@ class UIDefaultsLoader
{ {
if( hasAlpha && params.size() == 2 ) { if( hasAlpha && params.size() == 2 ) {
// syntax rgba(color,alpha), which allows adding alpha to any color // syntax rgba(color,alpha), which allows adding alpha to any color
// NOTE: this syntax is deprecated
// use fade(color,alpha) instead
String colorStr = params.get( 0 ); String colorStr = params.get( 0 );
int alpha = parseInteger( params.get( 1 ), 0, 255, true ); int alpha = parseInteger( params.get( 1 ), 0, 255, true );
@@ -639,7 +645,8 @@ class UIDefaultsLoader
/** /**
* Syntax: lighten(color,amount[,options]) or darken(color,amount[,options]) or * Syntax: lighten(color,amount[,options]) or darken(color,amount[,options]) or
* saturate(color,amount[,options]) or desaturate(color,amount[,options]) * saturate(color,amount[,options]) or desaturate(color,amount[,options]) or
* fadein(color,amount[,options]) or fadeout(color,amount[,options])
* - color: a color (e.g. #f00) or a color function * - color: a color (e.g. #f00) or a color function
* - amount: percentage 0-100% * - amount: percentage 0-100%
* - options: [relative] [autoInverse] [noAutoInverse] [lazy] [derived] * - options: [relative] [autoInverse] [noAutoInverse] [lazy] [derived]
@@ -679,6 +686,59 @@ class UIDefaultsLoader
}; };
} }
// parse base color, apply function and create derived color
return parseFunctionBaseColor( colorStr, function, derived, resolver, reportError );
}
/**
* Syntax: fade(color,amount[,options])
* - color: a color (e.g. #f00) or a color function
* - amount: percentage 0-100%
* - options: [derived]
*/
private static Object parseColorFade( List<String> params, Function<String, String> resolver, boolean reportError ) {
String colorStr = params.get( 0 );
int amount = parsePercentage( params.get( 1 ) );
boolean derived = false;
if( params.size() > 2 ) {
String options = params.get( 2 );
derived = options.contains( "derived" );
}
// create function
ColorFunction function = new ColorFunctions.Fade( amount );
// parse base color, apply function and create derived color
return parseFunctionBaseColor( colorStr, function, derived, resolver, reportError );
}
/**
* Syntax: spin(color,angle[,options])
* - color: a color (e.g. #f00) or a color function
* - angle: number of degrees to rotate
* - options: [derived]
*/
private static Object parseColorSpin( List<String> params, Function<String, String> resolver, boolean reportError ) {
String colorStr = params.get( 0 );
int amount = parseInteger( params.get( 1 ), true );
boolean derived = false;
if( params.size() > 2 ) {
String options = params.get( 2 );
derived = options.contains( "derived" );
}
// create function
ColorFunction function = new ColorFunctions.HSLIncreaseDecrease( 0, true, amount, false, false );
// parse base color, apply function and create derived color
return parseFunctionBaseColor( colorStr, function, derived, resolver, reportError );
}
private static Object parseFunctionBaseColor( String colorStr, ColorFunction function,
boolean derived, Function<String, String> resolver, boolean reportError )
{
// parse base color // parse base color
String resolvedColorStr = resolver.apply( colorStr ); String resolvedColorStr = resolver.apply( colorStr );
ColorUIResource baseColor = (ColorUIResource) parseColorOrFunction( resolvedColorStr, resolver, reportError ); ColorUIResource baseColor = (ColorUIResource) parseColorOrFunction( resolvedColorStr, resolver, reportError );

View File

@@ -28,11 +28,12 @@ public class ColorFunctions
public static Color applyFunctions( Color color, ColorFunction... functions ) { public static Color applyFunctions( Color color, ColorFunction... functions ) {
float[] hsl = HSLColor.fromRGB( color ); float[] hsl = HSLColor.fromRGB( color );
float alpha = color.getAlpha() / 255f; float alpha = color.getAlpha() / 255f;
float[] hsla = { hsl[0], hsl[1], hsl[2], alpha * 100 };
for( ColorFunction function : functions ) for( ColorFunction function : functions )
function.apply( hsl ); function.apply( hsla );
return HSLColor.toRGB( hsl, alpha ); return HSLColor.toRGB( hsla[0], hsla[1], hsla[2], hsla[3] / 100 );
} }
public static float clamp( float value ) { public static float clamp( float value ) {
@@ -46,13 +47,13 @@ public class ColorFunctions
//---- interface ColorFunction -------------------------------------------- //---- interface ColorFunction --------------------------------------------
public interface ColorFunction { public interface ColorFunction {
void apply( float[] hsl ); void apply( float[] hsla );
} }
//---- class HSLIncreaseDecrease ------------------------------------------ //---- class HSLIncreaseDecrease ------------------------------------------
/** /**
* Increase or decrease hue, saturation or luminance of a color in the HSL color space * Increase or decrease hue, saturation, luminance or alpha of a color in the HSL color space
* by an absolute or relative amount. * by an absolute or relative amount.
*/ */
public static class HSLIncreaseDecrease public static class HSLIncreaseDecrease
@@ -75,18 +76,45 @@ public class ColorFunctions
} }
@Override @Override
public void apply( float[] hsl ) { public void apply( float[] hsla ) {
float amount2 = increase ? amount : -amount; float amount2 = increase ? amount : -amount;
amount2 = autoInverse && shouldInverse( hsl ) ? -amount2 : amount2;
hsl[hslIndex] = clamp( relative if( hslIndex == 0 ) {
? (hsl[hslIndex] * ((100 + amount2) / 100)) // hue is range 0-360
: (hsl[hslIndex] + amount2) ); hsla[0] = (hsla[0] + amount2) % 360;
return;
} }
protected boolean shouldInverse( float[] hsl ) { amount2 = autoInverse && shouldInverse( hsla ) ? -amount2 : amount2;
hsla[hslIndex] = clamp( relative
? (hsla[hslIndex] * ((100 + amount2) / 100))
: (hsla[hslIndex] + amount2) );
}
protected boolean shouldInverse( float[] hsla ) {
return increase return increase
? hsl[hslIndex] >= 50 ? hsla[hslIndex] >= 50
: hsl[hslIndex] < 50; : hsla[hslIndex] < 50;
}
}
//---- class HSLIncreaseDecrease ------------------------------------------
/**
* Set the alpha of a color.
*/
public static class Fade
implements ColorFunction
{
public final float amount;
public Fade( float amount ) {
this.amount = amount;
}
@Override
public void apply( float[] hsla ) {
hsla[3] = clamp( amount );
} }
} }
} }

View File

@@ -241,7 +241,7 @@ Slider.trackValueColor=#4A88C7
Slider.trackColor=#646464 Slider.trackColor=#646464
Slider.thumbColor=$Slider.trackValueColor Slider.thumbColor=$Slider.trackValueColor
Slider.tickColor=#888 Slider.tickColor=#888
Slider.focusedColor=rgba($Component.focusColor,80%) Slider.focusedColor=fade($Component.focusColor,80%)
Slider.hoverThumbColor=darken($Slider.thumbColor,10%,derived) Slider.hoverThumbColor=darken($Slider.thumbColor,10%,derived)
Slider.pressedThumbColor=darken($Slider.thumbColor,15%,derived) Slider.pressedThumbColor=darken($Slider.thumbColor,15%,derived)
Slider.disabledTrackColor=#4c5052 Slider.disabledTrackColor=#4c5052

View File

@@ -682,7 +682,7 @@ TitlePane.foreground=@foreground
TitlePane.inactiveForeground=@disabledText TitlePane.inactiveForeground=@disabledText
TitlePane.closeHoverBackground=#e81123 TitlePane.closeHoverBackground=#e81123
TitlePane.closePressedBackground=rgba($TitlePane.closeHoverBackground,60%) TitlePane.closePressedBackground=fade($TitlePane.closeHoverBackground,60%)
TitlePane.closeHoverForeground=#fff TitlePane.closeHoverForeground=#fff
TitlePane.closePressedForeground=#fff TitlePane.closePressedForeground=#fff

View File

@@ -253,7 +253,7 @@ Slider.trackValueColor=#1E82E6
Slider.trackColor=#c4c4c4 Slider.trackColor=#c4c4c4
Slider.thumbColor=$Slider.trackValueColor Slider.thumbColor=$Slider.trackValueColor
Slider.tickColor=#888 Slider.tickColor=#888
Slider.focusedColor=rgba($Component.focusColor,50%) Slider.focusedColor=fade($Component.focusColor,50%)
Slider.hoverThumbColor=lighten($Slider.thumbColor,10%,derived) Slider.hoverThumbColor=lighten($Slider.thumbColor,10%,derived)
Slider.pressedThumbColor=lighten($Slider.thumbColor,15%,derived) Slider.pressedThumbColor=lighten($Slider.thumbColor,15%,derived)
Slider.disabledTrackColor=#c0c0c0 Slider.disabledTrackColor=#c0c0c0

View File

@@ -851,7 +851,7 @@ Slider.disabledTrackColor #c0c0c0 javax.swing.plaf.ColorUIResource [UI]
Slider.focus #9e9e9e javax.swing.plaf.ColorUIResource [UI] Slider.focus #9e9e9e javax.swing.plaf.ColorUIResource [UI]
Slider.focusInsets 0,0,0,0 javax.swing.plaf.InsetsUIResource [UI] Slider.focusInsets 0,0,0,0 javax.swing.plaf.InsetsUIResource [UI]
Slider.focusWidth 4 Slider.focusWidth 4
Slider.focusedColor #7f97c3f3 javax.swing.plaf.ColorUIResource [UI] Slider.focusedColor #8097c3f3 javax.swing.plaf.ColorUIResource [UI]
Slider.font [active] $defaultFont [UI] Slider.font [active] $defaultFont [UI]
Slider.foreground #000000 javax.swing.plaf.ColorUIResource [UI] Slider.foreground #000000 javax.swing.plaf.ColorUIResource [UI]
Slider.highlight #ffffff javax.swing.plaf.ColorUIResource [UI] Slider.highlight #ffffff javax.swing.plaf.ColorUIResource [UI]

View File

@@ -64,6 +64,7 @@ import com.formdev.flatlaf.intellijthemes.FlatAllIJThemes;
import com.formdev.flatlaf.testing.FlatTestLaf; import com.formdev.flatlaf.testing.FlatTestLaf;
import com.formdev.flatlaf.ui.FlatLineBorder; import com.formdev.flatlaf.ui.FlatLineBorder;
import com.formdev.flatlaf.util.ColorFunctions.ColorFunction; import com.formdev.flatlaf.util.ColorFunctions.ColorFunction;
import com.formdev.flatlaf.util.ColorFunctions.Fade;
import com.formdev.flatlaf.util.ColorFunctions.HSLIncreaseDecrease; import com.formdev.flatlaf.util.ColorFunctions.HSLIncreaseDecrease;
import com.formdev.flatlaf.util.DerivedColor; import com.formdev.flatlaf.util.DerivedColor;
import com.formdev.flatlaf.util.StringUtils; import com.formdev.flatlaf.util.StringUtils;
@@ -399,13 +400,18 @@ public class UIDefaultsDump
HSLIncreaseDecrease func = (HSLIncreaseDecrease) function; HSLIncreaseDecrease func = (HSLIncreaseDecrease) function;
String name; String name;
switch( func.hslIndex ) { switch( func.hslIndex ) {
case 2: name = func.increase ? "lighten" : "darken"; break; case 0: name = "spin"; break;
case 1: name = func.increase ? "saturate" : "desaturate"; break; case 1: name = func.increase ? "saturate" : "desaturate"; break;
case 2: name = func.increase ? "lighten" : "darken"; break;
case 3: name = func.increase ? "fadein" : "fadeout"; break;
default: throw new IllegalArgumentException(); default: throw new IllegalArgumentException();
} }
out.printf( "%s(%.0f%%%s%s)", name, func.amount, out.printf( "%s(%.0f%%%s%s)", name, func.amount,
(func.relative ? " relative" : ""), (func.relative ? " relative" : ""),
(func.autoInverse ? " autoInverse" : "") ); (func.autoInverse ? " autoInverse" : "") );
} else if( function instanceof Fade ) {
Fade func = (Fade) function;
out.printf( "fade(%.0f%%)", func.amount );
} else } else
throw new IllegalArgumentException( "unknown color function: " + function ); throw new IllegalArgumentException( "unknown color function: " + function );
} }

View File

@@ -336,8 +336,9 @@ class FlatCompletionProvider
"lightness", "0-100%", "lightness", "0-100%",
"alpha", "0-100%" ); "alpha", "0-100%" );
String colorParamDesc = "a color (e.g. #f00), a reference (e.g. $Other.key) or a color function";
String[] hslIncreaseDecreaseParams = { String[] hslIncreaseDecreaseParams = {
"color", "a color (e.g. #f00), a reference (e.g. $Other.key) or a color function", "color", colorParamDesc,
"amount", "0-100%", "amount", "0-100%",
"options", "(optional) [relative] [autoInverse] [noAutoInverse] [lazy] [derived]" "options", "(optional) [relative] [autoInverse] [noAutoInverse] [lazy] [derived]"
}; };
@@ -345,6 +346,17 @@ class FlatCompletionProvider
addFunction( "darken", hslIncreaseDecreaseParams ); addFunction( "darken", hslIncreaseDecreaseParams );
addFunction( "saturate", hslIncreaseDecreaseParams ); addFunction( "saturate", hslIncreaseDecreaseParams );
addFunction( "desaturate", hslIncreaseDecreaseParams ); addFunction( "desaturate", hslIncreaseDecreaseParams );
addFunction( "fadein", hslIncreaseDecreaseParams );
addFunction( "fadeout", hslIncreaseDecreaseParams );
addFunction( "fade",
"color", colorParamDesc,
"amount", "0-100%",
"options", "(optional) [derived]" );
addFunction( "spin",
"color", colorParamDesc,
"angle", "number of degrees to rotate",
"options", "(optional) [derived]" );
} }
private void addFunction( String name, String... paramNamesAndDescs ) { private void addFunction( String name, String... paramNamesAndDescs ) {

View File

@@ -40,3 +40,12 @@ Prop.colorFunc5=lighten(#fe1289,20%)
Prop.colorFunc6=darken(#fe1289,20%) Prop.colorFunc6=darken(#fe1289,20%)
Prop.colorFunc7=lighten($Prop.colorFunc4,20%,relative autoInverse) Prop.colorFunc7=lighten($Prop.colorFunc4,20%,relative autoInverse)
Prop.colorFunc8=lighten(Prop.colorFunc4,20%,lazy) Prop.colorFunc8=lighten(Prop.colorFunc4,20%,lazy)
Prop.colorFunc9=fadein(#ff000000,30%)
Prop.colorFunc10=fadeout(#ff0000,40%)
Prop.colorFunc11=fade(#ff0000,50%)
Prop.colorFunc12=#f00
Prop.colorFunc13=spin($Prop.colorFunc12,40)
Prop.colorFunc14=spin($Prop.colorFunc12,-40)
Prop.colorFunc15=spin($Prop.colorFunc12,400)
Prop.colorFunc16=spin($Prop.colorFunc12,-400)