From ba0f43455b37a3594de05a59e7bc600afd7fb03e Mon Sep 17 00:00:00 2001 From: DUDSS Date: Fri, 9 Apr 2021 00:07:04 +0200 Subject: [PATCH] Reworked how the FlatSVGIcon filters work. Filters are now set using the ColorFilter class and can work globally too. Added related demo components to flatlaf-demo extras tab. --- .../flatlaf/demo/extras/ExtrasPanel.java | 65 ++++++++ .../formdev/flatlaf/extras/FlatRGBFilter.java | 23 --- .../formdev/flatlaf/extras/FlatSVGIcon.java | 152 +++++++++++++++--- 3 files changed, 197 insertions(+), 43 deletions(-) delete mode 100644 flatlaf-extras/src/main/java/com/formdev/flatlaf/extras/FlatRGBFilter.java diff --git a/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/extras/ExtrasPanel.java b/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/extras/ExtrasPanel.java index 37cfec1f..9614920a 100644 --- a/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/extras/ExtrasPanel.java +++ b/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/extras/ExtrasPanel.java @@ -18,8 +18,10 @@ package com.formdev.flatlaf.demo.extras; import javax.swing.*; import com.formdev.flatlaf.extras.*; +import com.formdev.flatlaf.extras.FlatSVGIcon.ColorFilter; import com.formdev.flatlaf.extras.components.FlatTriStateCheckBox; import net.miginfocom.swing.*; +import java.awt.*; /** * @author Karl Tauber @@ -27,6 +29,8 @@ import net.miginfocom.swing.*; public class ExtrasPanel extends JPanel { + public int counter = 0; + public ExtrasPanel() { initComponents(); @@ -69,6 +73,12 @@ public class ExtrasPanel label2 = new JLabel(); svgIconsPanel = new JPanel(); label3 = new JLabel(); + separator1 = new JSeparator(); + label5 = new JLabel(); + label6 = new JLabel(); + label7 = new JLabel(); + rainbowIcon = new JLabel(); + toggleButton1 = new JToggleButton(); //======== this ======== setLayout(new MigLayout( @@ -81,6 +91,9 @@ public class ExtrasPanel "[]para" + "[]" + "[]" + + "[]" + + "[]" + + "[]" + "[]")); //---- label4 ---- @@ -119,9 +132,55 @@ public class ExtrasPanel //---- label3 ---- label3.setText("The icons may change colors when switching to another theme."); add(label3, "cell 1 3 2 1"); + + add(separator1, "cell 1 4, grow"); + + //---- label5 ---- + label5.setText("Color filters can be also applied to icons. Globally or for each instance."); + add(label5, "cell 1 5"); + + //---- label6 ---- + label6.setText( "Rainbow color filter" ); + add(label6, "cell 1 6"); + + //---- rainbowIcon ---- + rainbowIcon = createRainbowIcon("informationDialog.svg"); + add(rainbowIcon, "cell 1 6"); + + //---- label7 ---- + label7.setText( "Global icon color filter" ); + add(label7, "cell 1 7"); + + // ---- button1 ---- + toggleButton1.setText( "Toggle red" ); + add(toggleButton1, "cell 1 7"); + + // ---- toggleButton1 ---- + toggleButton1.addActionListener( (e) -> { + if (toggleButton1.isSelected()) + FlatSVGIcon.ColorFilter.getInstance().setFilter( color -> Color.RED ); + else + FlatSVGIcon.ColorFilter.getInstance().setFilter( null ); + SwingUtilities.getRootPane( toggleButton1 ).repaint(); + } ); + // JFormDesigner - End of component initialization //GEN-END:initComponents } + private JLabel createRainbowIcon(String name) { + FlatSVGIcon rainbowIcon = new FlatSVGIcon( "com/formdev/flatlaf/demo/extras/svg/" + name); + rainbowIcon.setFilter( new ColorFilter( (color) -> { + counter+=1; + counter%=255; + return Color.getHSBColor(counter/255f, 1, 1); + }) ); + JLabel label = new JLabel(rainbowIcon); + new Timer(30, (e) -> { + label.repaint(); + }).start(); + return label; + } + // JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables private JLabel label4; private JLabel label1; @@ -130,5 +189,11 @@ public class ExtrasPanel private JLabel label2; private JPanel svgIconsPanel; private JLabel label3; + private JLabel label5; + private JLabel label6; + private JLabel label7; + private JSeparator separator1; + private JLabel rainbowIcon; + private JToggleButton toggleButton1; // JFormDesigner - End of variables declaration //GEN-END:variables } diff --git a/flatlaf-extras/src/main/java/com/formdev/flatlaf/extras/FlatRGBFilter.java b/flatlaf-extras/src/main/java/com/formdev/flatlaf/extras/FlatRGBFilter.java deleted file mode 100644 index 83c1917c..00000000 --- a/flatlaf-extras/src/main/java/com/formdev/flatlaf/extras/FlatRGBFilter.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.formdev.flatlaf.extras; - -import java.awt.*; -import java.awt.image.RGBImageFilter; - -/** - * A simplified RGBImageFilter that presents individual rgba components as a Color object. - * Can be used to modify the color of a {@link FlatSVGIcon}- - */ -public abstract class FlatRGBFilter extends RGBImageFilter -{ - @Override - public int filterRGB(int x, int y, int rgb) { - return filterRGB(new Color(rgb)).getRGB(); - } - - /** - * @param c Original color - * @return Modified color - */ - public abstract Color filterRGB(Color c); -} - diff --git a/flatlaf-extras/src/main/java/com/formdev/flatlaf/extras/FlatSVGIcon.java b/flatlaf-extras/src/main/java/com/formdev/flatlaf/extras/FlatSVGIcon.java index 2951c8a3..fd0c01ef 100644 --- a/flatlaf-extras/src/main/java/com/formdev/flatlaf/extras/FlatSVGIcon.java +++ b/flatlaf-extras/src/main/java/com/formdev/flatlaf/extras/FlatSVGIcon.java @@ -66,7 +66,7 @@ public class FlatSVGIcon private final boolean disabled; private final ClassLoader classLoader; - private RGBImageFilter userFilter = null; + private ColorFilter userColorFilter = null; private SVGDiagram diagram; private boolean dark; @@ -161,7 +161,7 @@ public class FlatSVGIcon this( name, -1, -1, scale, false, classLoader ); } - private FlatSVGIcon( String name, int width, int height, float scale, boolean disabled, ClassLoader classLoader ) { + protected FlatSVGIcon( String name, int width, int height, float scale, boolean disabled, ClassLoader classLoader ) { this.name = name; this.classLoader = classLoader; this.width = width; @@ -171,16 +171,29 @@ public class FlatSVGIcon } /** - * Sets an RGBImageFilter to be used when painting the icon. - * For simple RGB modifications you can use the {@link FlatRGBFilter}. - * @param filter + * Sets a color filter that can freely modify colors of this icon during painting.
+ *
+ * This method accepts a {@link ColorFilter}. Usually you would want to use a ColorFilter created using the + * {@link ColorFilter#ColorFilter(Function)} constructor.
+ *
+ * This can be used to brighten colors of the icon: + *
icon.setFilter( new FlatSVGIcon.ColorFilter( color -> color.brighter() ) );

+ *
+ * Using a filter, icons can also be turned monochrome (painted with a single color): + *
icon.setFilter( new FlatSVGIcon.ColorFilter( color -> Color.RED ) );

+ *
+ * Note: If a filter is already set, it will be replaced. + * @param filter The color filter */ - public void setFilter(RGBImageFilter filter) { - this.userFilter = filter; + public void setFilter(ColorFilter filter) { + this.userColorFilter = filter; } - public RGBImageFilter getFilter() { - return userFilter; + /** + * @return The currently active {@link ColorFilter} or null. + */ + public ColorFilter getFilter() { + return userColorFilter; } /** @@ -318,7 +331,7 @@ public class FlatSVGIcon : GrayFilter.createDisabledIconFilter( dark ); } - Graphics2D g2 = new GraphicsFilter( (Graphics2D) g.create(), ColorFilter.getInstance(), grayFilter, this.userFilter ); + Graphics2D g2 = new GraphicsFilter( (Graphics2D) g.create(), ColorFilter.getInstance(), grayFilter, this.userColorFilter ); try { FlatUIUtils.setRenderingHints( g2 ); @@ -416,37 +429,139 @@ public class FlatSVGIcon //---- class ColorFilter -------------------------------------------------- + /** + * A color filter that can modify colors of a painted {@link FlatSVGIcon}.
+ *
+ * The ColorFilter modifes color in two ways.
+ * Either using a color map, where specific colors are mapped to different ones.
+ * And/or by modifying the colors directly, applying a modification to their rgba values.
+ *
+ * When filtering a color. Mappings are applied first, then an rgb color filter is applied.
+ *
+ * Global {@link FlatSVGIcon} ColorFilter can be retrieved using the {@link ColorFilter#getInstance()} methods. + * + * @see ColorFilter#ColorFilter(Function) + * @see ColorFilter#ColorFilter(boolean) + */ public static class ColorFilter { private static ColorFilter instance; + //Color maps private final Map rgb2keyMap = new HashMap<>(); private final Map color2colorMap = new HashMap<>(); + //Color modification + private Function colorFilter = null; + + /** + * Returns the global ColorFilter instance. If one doesn't exist, a new one is created. + */ public static ColorFilter getInstance() { + return(getInstance(true)); + } + + /** + * Returns the global ColorFilter instance. If one doesn't exist, a new one is created. + * @param createDefaultColorMaps If true, default FlatLaf color maps are created. + */ + public static ColorFilter getInstance(boolean createDefaultColorMaps) { if( instance == null ) instance = new ColorFilter(); return instance; } + /** + * Creates a color filter with default color mappings. + */ public ColorFilter() { - for( FlatIconColors c : FlatIconColors.values() ) - rgb2keyMap.put( c.rgb, c.key ); + this(true); } + /** + * Creates a color filter. Default color maps can be optionally created. + * @param createDefaultColorMaps If true, default FlatLaf color maps are created. + */ + public ColorFilter(boolean createDefaultColorMaps) { + if (createDefaultColorMaps) { + for( FlatIconColors c : FlatIconColors.values() ) + rgb2keyMap.put( c.rgb, c.key ); + } + } + + /** + * Creates a color modifying function that changes painted colors.
+ * The {@link Function} gets passed the original color and returns a modified one. + *
+ * Examples: + * A ColorFilter can be used to brighten colors of the icon: + *
new ColorFilter( color -> color.brighter() );
+ *
+ * Using a ColorFilter, icons can also be turned monochrome (painted with a single color): + *
new ColorFilter( color -> Color.RED );
+ *
+ * @param filter The color filter function + */ + public ColorFilter(Function filter) { + setFilter(filter); + } + + /** + * Sets a color modifying function that changes painted colors.
+ * The {@link Function} gets passed the original color and returns a modified one. + *
+ * Examples: + * A ColorFilter can be used to brighten colors of the icon: + *
filter.setFilter( color -> color.brighter() );
+ *
+ * Using a ColorFilter, icons can also be turned monochrome (painted with a single color): + *
filter.setFilter( color -> Color.RED );
+ *
+ * @param filter The color filter function + */ + public void setFilter(Function filter) { + this.colorFilter = filter; + } + + /** + * Adds a color mappings. + */ public void addAll( Map from2toMap ) { color2colorMap.putAll( from2toMap ); } + /** + * Adds a color mapping. + */ public void add( Color from, Color to ) { color2colorMap.put( from, to ); } + /** + * Removes a specific color mapping. + */ public void remove( Color from ) { color2colorMap.remove( from ); } + /** + * Removes all color mappings. + */ + public void removeAll() { + for ( Color from : color2colorMap.keySet()) { + color2colorMap.remove( from ); + } + } + public Color filter( Color color ) { + color = filterMappings( color ); + if (colorFilter != null) { + color = colorFilter.apply( color ); + } + return color; + }; + + protected Color filterMappings( Color color ) { Color newColor = color2colorMap.get( color ); if( newColor != null ) return newColor; @@ -462,7 +577,7 @@ public class FlatSVGIcon return (newColor.getAlpha() != color.getAlpha()) ? new Color( (newColor.getRGB() & 0x00ffffff) | (color.getRGB() & 0xff000000) ) : newColor; - }; + } } //---- class GraphicsFilter ----------------------------------------------- @@ -472,9 +587,9 @@ public class FlatSVGIcon { private final ColorFilter colorFilter; private final RGBImageFilter grayFilter; - private final RGBImageFilter userFilter; + private final ColorFilter userFilter; - public GraphicsFilter( Graphics2D delegate, ColorFilter colorFilter, RGBImageFilter grayFilter, RGBImageFilter userFilter) { + public GraphicsFilter( Graphics2D delegate, ColorFilter colorFilter, RGBImageFilter grayFilter,ColorFilter userFilter) { super( delegate ); this.colorFilter = colorFilter; this.grayFilter = grayFilter; @@ -494,11 +609,8 @@ public class FlatSVGIcon } private Color filterColor( Color color ) { - if( userFilter != null ) { - int oldRGB = color.getRGB(); - int newRGB = userFilter.filterRGB( 0, 0, oldRGB ); - color = (newRGB != oldRGB) ? new Color( newRGB, true ) : color; - } + if( userFilter != null ) + color = userFilter.filter( color ); if( colorFilter != null ) color = colorFilter.filter( color ); if( grayFilter != null ) {