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.

This commit is contained in:
DUDSS
2021-04-09 00:07:04 +02:00
parent 638af4bcd7
commit ba0f43455b
3 changed files with 197 additions and 43 deletions

View File

@@ -18,8 +18,10 @@ package com.formdev.flatlaf.demo.extras;
import javax.swing.*; import javax.swing.*;
import com.formdev.flatlaf.extras.*; import com.formdev.flatlaf.extras.*;
import com.formdev.flatlaf.extras.FlatSVGIcon.ColorFilter;
import com.formdev.flatlaf.extras.components.FlatTriStateCheckBox; import com.formdev.flatlaf.extras.components.FlatTriStateCheckBox;
import net.miginfocom.swing.*; import net.miginfocom.swing.*;
import java.awt.*;
/** /**
* @author Karl Tauber * @author Karl Tauber
@@ -27,6 +29,8 @@ import net.miginfocom.swing.*;
public class ExtrasPanel public class ExtrasPanel
extends JPanel extends JPanel
{ {
public int counter = 0;
public ExtrasPanel() { public ExtrasPanel() {
initComponents(); initComponents();
@@ -69,6 +73,12 @@ public class ExtrasPanel
label2 = new JLabel(); label2 = new JLabel();
svgIconsPanel = new JPanel(); svgIconsPanel = new JPanel();
label3 = new JLabel(); label3 = new JLabel();
separator1 = new JSeparator();
label5 = new JLabel();
label6 = new JLabel();
label7 = new JLabel();
rainbowIcon = new JLabel();
toggleButton1 = new JToggleButton();
//======== this ======== //======== this ========
setLayout(new MigLayout( setLayout(new MigLayout(
@@ -81,6 +91,9 @@ public class ExtrasPanel
"[]para" + "[]para" +
"[]" + "[]" +
"[]" + "[]" +
"[]" +
"[]" +
"[]" +
"[]")); "[]"));
//---- label4 ---- //---- label4 ----
@@ -119,9 +132,55 @@ public class ExtrasPanel
//---- label3 ---- //---- label3 ----
label3.setText("The icons may change colors when switching to another theme."); label3.setText("The icons may change colors when switching to another theme.");
add(label3, "cell 1 3 2 1"); 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 // 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 // JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables
private JLabel label4; private JLabel label4;
private JLabel label1; private JLabel label1;
@@ -130,5 +189,11 @@ public class ExtrasPanel
private JLabel label2; private JLabel label2;
private JPanel svgIconsPanel; private JPanel svgIconsPanel;
private JLabel label3; 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 // JFormDesigner - End of variables declaration //GEN-END:variables
} }

View File

@@ -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);
}

View File

@@ -66,7 +66,7 @@ public class FlatSVGIcon
private final boolean disabled; private final boolean disabled;
private final ClassLoader classLoader; private final ClassLoader classLoader;
private RGBImageFilter userFilter = null; private ColorFilter userColorFilter = null;
private SVGDiagram diagram; private SVGDiagram diagram;
private boolean dark; private boolean dark;
@@ -161,7 +161,7 @@ public class FlatSVGIcon
this( name, -1, -1, scale, false, classLoader ); 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.name = name;
this.classLoader = classLoader; this.classLoader = classLoader;
this.width = width; this.width = width;
@@ -171,16 +171,29 @@ public class FlatSVGIcon
} }
/** /**
* Sets an RGBImageFilter to be used when painting the icon. * Sets a color filter that can freely modify colors of this icon during painting.<br>
* For simple RGB modifications you can use the {@link FlatRGBFilter}. * <br>
* @param filter * This method accepts a {@link ColorFilter}. Usually you would want to use a ColorFilter created using the
* {@link ColorFilter#ColorFilter(Function)} constructor.<br>
* <br>
* This can be used to brighten colors of the icon:
* <pre>icon.setFilter( new FlatSVGIcon.ColorFilter( color -> color.brighter() ) );</pre><br>
* <br>
* Using a filter, icons can also be turned monochrome (painted with a single color):
* <pre>icon.setFilter( new FlatSVGIcon.ColorFilter( color -> Color.RED ) );</pre><br>
* <br>
* Note: If a filter is already set, it will be replaced.
* @param filter The color filter
*/ */
public void setFilter(RGBImageFilter filter) { public void setFilter(ColorFilter filter) {
this.userFilter = 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 ); : 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 { try {
FlatUIUtils.setRenderingHints( g2 ); FlatUIUtils.setRenderingHints( g2 );
@@ -416,37 +429,139 @@ public class FlatSVGIcon
//---- class ColorFilter -------------------------------------------------- //---- class ColorFilter --------------------------------------------------
/**
* A color filter that can modify colors of a painted {@link FlatSVGIcon}.<br>
* <br>
* The ColorFilter modifes color in two ways.<br>
* Either using a color map, where specific colors are mapped to different ones.<br>
* And/or by modifying the colors directly, applying a modification to their rgba values.<br>
* <br>
* When filtering a color. Mappings are applied first, then an rgb color filter is applied.<br>
* <br>
* 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 public static class ColorFilter
{ {
private static ColorFilter instance; private static ColorFilter instance;
//Color maps
private final Map<Integer, String> rgb2keyMap = new HashMap<>(); private final Map<Integer, String> rgb2keyMap = new HashMap<>();
private final Map<Color, Color> color2colorMap = new HashMap<>(); private final Map<Color, Color> color2colorMap = new HashMap<>();
//Color modification
private Function<Color, Color> colorFilter = null;
/**
* Returns the global ColorFilter instance. If one doesn't exist, a new one is created.
*/
public static ColorFilter getInstance() { 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 ) if( instance == null )
instance = new ColorFilter(); instance = new ColorFilter();
return instance; return instance;
} }
/**
* Creates a color filter with default color mappings.
*/
public ColorFilter() { public ColorFilter() {
for( FlatIconColors c : FlatIconColors.values() ) this(true);
rgb2keyMap.put( c.rgb, c.key );
} }
/**
* 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.<br>
* The {@link Function} gets passed the original color and returns a modified one.
* <br>
* Examples:
* A ColorFilter can be used to brighten colors of the icon:
* <pre>new ColorFilter( color -> color.brighter() );</pre>
* <br>
* Using a ColorFilter, icons can also be turned monochrome (painted with a single color):
* <pre>new ColorFilter( color -> Color.RED );</pre>
* <br>
* @param filter The color filter function
*/
public ColorFilter(Function<Color, Color> filter) {
setFilter(filter);
}
/**
* Sets a color modifying function that changes painted colors.<br>
* The {@link Function} gets passed the original color and returns a modified one.
* <br>
* Examples:
* A ColorFilter can be used to brighten colors of the icon:
* <pre>filter.setFilter( color -> color.brighter() );</pre>
* <br>
* Using a ColorFilter, icons can also be turned monochrome (painted with a single color):
* <pre>filter.setFilter( color -> Color.RED );</pre>
* <br>
* @param filter The color filter function
*/
public void setFilter(Function<Color, Color> filter) {
this.colorFilter = filter;
}
/**
* Adds a color mappings.
*/
public void addAll( Map<Color, Color> from2toMap ) { public void addAll( Map<Color, Color> from2toMap ) {
color2colorMap.putAll( from2toMap ); color2colorMap.putAll( from2toMap );
} }
/**
* Adds a color mapping.
*/
public void add( Color from, Color to ) { public void add( Color from, Color to ) {
color2colorMap.put( from, to ); color2colorMap.put( from, to );
} }
/**
* Removes a specific color mapping.
*/
public void remove( Color from ) { public void remove( Color from ) {
color2colorMap.remove( from ); color2colorMap.remove( from );
} }
/**
* Removes all color mappings.
*/
public void removeAll() {
for ( Color from : color2colorMap.keySet()) {
color2colorMap.remove( from );
}
}
public Color filter( Color color ) { 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 ); Color newColor = color2colorMap.get( color );
if( newColor != null ) if( newColor != null )
return newColor; return newColor;
@@ -462,7 +577,7 @@ public class FlatSVGIcon
return (newColor.getAlpha() != color.getAlpha()) return (newColor.getAlpha() != color.getAlpha())
? new Color( (newColor.getRGB() & 0x00ffffff) | (color.getRGB() & 0xff000000) ) ? new Color( (newColor.getRGB() & 0x00ffffff) | (color.getRGB() & 0xff000000) )
: newColor; : newColor;
}; }
} }
//---- class GraphicsFilter ----------------------------------------------- //---- class GraphicsFilter -----------------------------------------------
@@ -472,9 +587,9 @@ public class FlatSVGIcon
{ {
private final ColorFilter colorFilter; private final ColorFilter colorFilter;
private final RGBImageFilter grayFilter; 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 ); super( delegate );
this.colorFilter = colorFilter; this.colorFilter = colorFilter;
this.grayFilter = grayFilter; this.grayFilter = grayFilter;
@@ -494,11 +609,8 @@ public class FlatSVGIcon
} }
private Color filterColor( Color color ) { private Color filterColor( Color color ) {
if( userFilter != null ) { if( userFilter != null )
int oldRGB = color.getRGB(); color = userFilter.filter( color );
int newRGB = userFilter.filterRGB( 0, 0, oldRGB );
color = (newRGB != oldRGB) ? new Color( newRGB, true ) : color;
}
if( colorFilter != null ) if( colorFilter != null )
color = colorFilter.filter( color ); color = colorFilter.filter( color );
if( grayFilter != null ) { if( grayFilter != null ) {