diff --git a/CHANGELOG.md b/CHANGELOG.md index 19f82468..e8354494 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,9 @@ FlatLaf Change Log - ToolBar: Toolbars are no longer floatable by default (dots on left side of toolbar that allows dragging toolbar). Use `UIManager.put( "ToolBar.floatable", true )` if you want the old behavior. +- Added more color functions to class `ColorFunctions` for easy use in + applications: `lighten()`, `darken()`, `saturate()`, `desaturate()`, `spin()`, + `tint()`, `shade()` and `luma()`. #### Fixed bugs diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/util/ColorFunctions.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/util/ColorFunctions.java index 47fbc473..2b5794a6 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/util/ColorFunctions.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/util/ColorFunctions.java @@ -25,6 +25,86 @@ import java.awt.Color; */ public class ColorFunctions { + /** + * Increase the lightness of a color in HSL color space by an absolute amount. + *

+ * Consider using {@link #tint(Color, float)} as alternative. + * + * @param color base color + * @param amount the amount (in range 0-1) that is added to the lightness + * @return new color + * @since 2 + */ + public static Color lighten( Color color, float amount ) { + return hslIncreaseDecrease( color, amount, 2, true ); + } + + /** + * Decrease the lightness of a color in HSL color space by an absolute amount. + *

+ * Consider using {@link #shade(Color, float)} as alternative. + * + * @param color base color + * @param amount the amount (in range 0-1) that is subtracted from the lightness + * @return new color + * @since 2 + */ + public static Color darken( Color color, float amount ) { + return hslIncreaseDecrease( color, amount, 2, false ); + } + + /** + * Increase the saturation of a color in HSL color space by an absolute amount. + * + * @param color base color + * @param amount the amount (in range 0-1) that is added to the saturation + * @return new color + * @since 2 + */ + public static Color saturate( Color color, float amount ) { + return hslIncreaseDecrease( color, amount, 1, true ); + } + + /** + * Decrease the saturation of a color in HSL color space by an absolute amount. + * + * @param color base color + * @param amount the amount (in range 0-1) that is subtracted from the saturation + * @return new color + * @since 2 + */ + public static Color desaturate( Color color, float amount ) { + return hslIncreaseDecrease( color, amount, 1, false ); + } + + /** + * Rotate the hue angle (0-360) of a color in HSL color space in either direction. + * + * @param color base color + * @param angle the number of degrees to rotate (in range -360 - 360) + * @return new color + * @since 2 + */ + public static Color spin( Color color, float angle ) { + return hslIncreaseDecrease( color, angle, 0, true ); + } + + private static Color hslIncreaseDecrease( Color color, float amount, int hslIndex, boolean increase ) { + // convert RGB to HSL + float[] hsl = HSLColor.fromRGB( color ); + float alpha = color.getAlpha() / 255f; + + // apply HSL color change + float amount2 = increase ? amount : -amount; + if( hslIndex == 0 ) + hsl[0] = (hsl[0] + amount2) % 360; + else + hsl[hslIndex] = clamp( hsl[hslIndex] + (amount2 * 100) ); + + // convert HSL to RGB + return HSLColor.toRGB( hsl[0], hsl[1], hsl[2], alpha ); + } + /** * Returns a color that is a mixture of two colors. *

diff --git a/flatlaf-core/src/test/java/com/formdev/flatlaf/util/TestColorFunctions.java b/flatlaf-core/src/test/java/com/formdev/flatlaf/util/TestColorFunctions.java index 74843273..960ff57a 100644 --- a/flatlaf-core/src/test/java/com/formdev/flatlaf/util/TestColorFunctions.java +++ b/flatlaf-core/src/test/java/com/formdev/flatlaf/util/TestColorFunctions.java @@ -25,6 +25,37 @@ import org.junit.jupiter.api.Test; */ public class TestColorFunctions { + @Test + void colorFunctions() { + assertEquals( new Color( 0xff6666 ), ColorFunctions.lighten( Color.red, 0.2f ) ); + assertEquals( new Color( 0x990000 ), ColorFunctions.darken( Color.red, 0.2f ) ); + + // saturate, desaturate + assertEquals( new Color( 0x9c3030 ), ColorFunctions.saturate( new Color( 0x884444 ), 0.2f ) ); + assertEquals( new Color( 0x745858 ), ColorFunctions.desaturate( new Color( 0x884444 ), 0.2f ) ); + + // spin + assertEquals( new Color( 0xffaa00 ), ColorFunctions.spin( Color.red,40 ) ); + assertEquals( new Color( 0xff00aa ), ColorFunctions.spin( Color.red,-40 ) ); + + // mix + assertEquals( new Color( 0x1ae600 ), ColorFunctions.mix( Color.red, Color.green, 0.1f ) ); + assertEquals( new Color( 0x40bf00 ), ColorFunctions.mix( Color.red, Color.green, 0.25f ) ); + assertEquals( new Color( 0x808000 ), ColorFunctions.mix( Color.red, Color.green, 0.5f ) ); + assertEquals( new Color( 0xbf4000 ), ColorFunctions.mix( Color.red, Color.green, 0.75f ) ); + assertEquals( new Color( 0xe61a00 ), ColorFunctions.mix( Color.red, Color.green, 0.9f ) ); + + // tint + assertEquals( new Color( 0xff40ff ), ColorFunctions.tint( Color.magenta, 0.25f ) ); + assertEquals( new Color( 0xff80ff ), ColorFunctions.tint( Color.magenta, 0.5f ) ); + assertEquals( new Color( 0xffbfff ), ColorFunctions.tint( Color.magenta, 0.75f ) ); + + // shade + assertEquals( new Color( 0xbf00bf ), ColorFunctions.shade( Color.magenta, 0.25f ) ); + assertEquals( new Color( 0x800080 ), ColorFunctions.shade( Color.magenta, 0.5f ) ); + assertEquals( new Color( 0x400040 ), ColorFunctions.shade( Color.magenta, 0.75f ) ); + } + @Test void luma() { assertEquals( 0, ColorFunctions.luma( Color.black ) );