diff --git a/CHANGELOG.md b/CHANGELOG.md index e6e21218..c870765f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -52,6 +52,8 @@ FlatLaf Change Log #188; regression in 0.42 in fix for #164) - IntelliJ Themes: Added suffix "(Material)" to names of all Material UI Lite themes to avoid duplicate theme names. (issue #201) +- Extras: `FlatSVGIcon` icons were not painted in disabled labels and disabled + tabs. (issue #205) ## 0.43 diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatLaf.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatLaf.java index 69af8217..925864cf 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatLaf.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatLaf.java @@ -170,6 +170,9 @@ public abstract class FlatLaf @Override public Icon getDisabledIcon( JComponent component, Icon icon ) { + if( icon instanceof DisabledIconProvider ) + return ((DisabledIconProvider)icon).getDisabledIcon(); + if( icon instanceof ImageIcon ) { Object grayFilter = UIManager.get( "Component.grayFilter" ); ImageFilter filter = (grayFilter instanceof ImageFilter) @@ -762,4 +765,24 @@ public abstract class FlatLaf super( image ); } } + + //---- interface DisabledIconProvider ------------------------------------- + + /** + * A provider for disabled icons. + *

+ * This is intended to be implemented by {@link javax.swing.Icon} implementations + * that provide the ability to paint disabled state. + *

+ * Used in {@link FlatLaf#getDisabledIcon(JComponent, Icon)} to create a disabled icon from an enabled icon. + */ + public interface DisabledIconProvider + { + /** + * Returns an icon with a disabled appearance. + * + * @return a disabled icon + */ + Icon getDisabledIcon(); + } } 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 6876a19c..c6789e84 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 @@ -20,18 +20,22 @@ import java.awt.Color; import java.awt.Component; import java.awt.Graphics; import java.awt.Graphics2D; +import java.awt.Image; import java.awt.Paint; import java.awt.Rectangle; import java.awt.RenderingHints; +import java.awt.image.BufferedImage; import java.awt.image.RGBImageFilter; import java.net.URISyntaxException; import java.net.URL; import java.util.HashMap; import java.util.Map; import javax.swing.Icon; +import javax.swing.ImageIcon; import javax.swing.UIManager; import com.formdev.flatlaf.FlatIconColors; import com.formdev.flatlaf.FlatLaf; +import com.formdev.flatlaf.FlatLaf.DisabledIconProvider; import com.formdev.flatlaf.ui.FlatUIUtils; import com.formdev.flatlaf.util.Graphics2DProxy; import com.formdev.flatlaf.util.GrayFilter; @@ -46,7 +50,8 @@ import com.kitfox.svg.SVGUniverse; * @author Karl Tauber */ public class FlatSVGIcon - implements Icon + extends ImageIcon + implements DisabledIconProvider { // use own SVG universe so that it can not be cleared from anywhere private static final SVGUniverse svgUniverse = new SVGUniverse(); @@ -55,6 +60,7 @@ public class FlatSVGIcon private final int width; private final int height; private final float scale; + private final boolean disabled; private final ClassLoader classLoader; private SVGDiagram diagram; @@ -70,7 +76,7 @@ public class FlatSVGIcon * @see ClassLoader#getResource(String) */ public FlatSVGIcon( String name ) { - this( name, -1, -1, 1, null ); + this( name, -1, -1, 1, false, null ); } /** @@ -85,7 +91,7 @@ public class FlatSVGIcon * @see ClassLoader#getResource(String) */ public FlatSVGIcon( String name, ClassLoader classLoader ) { - this( name, -1, -1, 1, classLoader ); + this( name, -1, -1, 1, false, classLoader ); } /** @@ -99,7 +105,7 @@ public class FlatSVGIcon * @see ClassLoader#getResource(String) */ public FlatSVGIcon( String name, int width, int height ) { - this( name, width, height, 1, null ); + this( name, width, height, 1, false, null ); } /** @@ -115,7 +121,7 @@ public class FlatSVGIcon * @see ClassLoader#getResource(String) */ public FlatSVGIcon( String name, int width, int height, ClassLoader classLoader ) { - this( name, width, height, 1, classLoader ); + this( name, width, height, 1, false, classLoader ); } /** @@ -130,7 +136,7 @@ public class FlatSVGIcon * @see ClassLoader#getResource(String) */ public FlatSVGIcon( String name, float scale ) { - this( name, -1, -1, scale, null ); + this( name, -1, -1, scale, false, null ); } /** @@ -147,15 +153,16 @@ public class FlatSVGIcon * @see ClassLoader#getResource(String) */ public FlatSVGIcon( String name, float scale, ClassLoader classLoader ) { - this( name, -1, -1, scale, classLoader ); + this( name, -1, -1, scale, false, classLoader ); } - private FlatSVGIcon( String name, int width, int height, float scale, ClassLoader classLoader ) { + private FlatSVGIcon( String name, int width, int height, float scale, boolean disabled, ClassLoader classLoader ) { this.name = name; this.classLoader = classLoader; this.width = width; this.height = height; this.scale = scale; + this.disabled = disabled; } /** @@ -166,7 +173,10 @@ public class FlatSVGIcon * @return a new icon */ public FlatSVGIcon derive( int width, int height ) { - FlatSVGIcon icon = new FlatSVGIcon( name, width, height, scale, classLoader ); + if( width == this.width && height == this.height ) + return this; + + FlatSVGIcon icon = new FlatSVGIcon( name, width, height, scale, false, classLoader ); icon.diagram = diagram; icon.dark = dark; return icon; @@ -179,7 +189,26 @@ public class FlatSVGIcon * @return a new icon */ public FlatSVGIcon derive( float scale ) { - FlatSVGIcon icon = new FlatSVGIcon( name, width, height, scale, classLoader ); + if( scale == this.scale ) + return this; + + FlatSVGIcon icon = new FlatSVGIcon( name, width, height, scale, false, classLoader ); + icon.diagram = diagram; + icon.dark = dark; + return icon; + } + + /** + * Creates a new icon with disabled appearance, which is derived from this icon. + * + * @return a new icon + */ + @Override + public Icon getDisabledIcon() { + if( disabled ) + return this; + + FlatSVGIcon icon = new FlatSVGIcon( name, width, height, scale, true, classLoader ); icon.diagram = diagram; icon.dark = dark; return icon; @@ -264,7 +293,7 @@ public class FlatSVGIcon // get gray filter RGBImageFilter grayFilter = null; - if( c != null && !c.isEnabled() ) { + if( disabled ) { Object grayFilterObj = UIManager.get( "Component.grayFilter" ); grayFilter = (grayFilterObj instanceof RGBImageFilter) ? (RGBImageFilter) grayFilterObj @@ -316,6 +345,20 @@ public class FlatSVGIcon g.fillRect( x, y, getIconWidth(), getIconHeight() ); } + @Override + public Image getImage() { + update(); + + BufferedImage image = new BufferedImage( getIconWidth(), getIconHeight(), BufferedImage.TYPE_INT_ARGB ); + Graphics2D g = image.createGraphics(); + try { + paintIcon( null, g, 0, 0 ); + } finally { + g.dispose(); + } + return image; + } + private static Boolean darkLaf; private static boolean isDarkLaf() { diff --git a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/extras/FlatExtrasTest.java b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/extras/FlatExtrasTest.java index f010302f..14da1a5d 100644 --- a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/extras/FlatExtrasTest.java +++ b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/extras/FlatExtrasTest.java @@ -58,6 +58,23 @@ public class FlatExtrasTest addSVGIcon( "errorDialog.svg" ); addSVGIcon( "informationDialog.svg" ); addSVGIcon( "warningDialog.svg" ); + + FlatSVGIcon icon = new FlatSVGIcon( "com/formdev/flatlaf/demo/extras/svg/warningDialog.svg" ); + Icon disabledIcon = icon.getDisabledIcon(); + disabledLabel.setIcon( icon ); + disabledButton.setIcon( icon ); + disabledTabbedPane.addTab( "tab", null ); + disabledTabbedPane.setIconAt( 0, icon ); + + disabledLabel2.setIcon( icon ); + disabledLabel2.setDisabledIcon( disabledIcon ); + disabledButton2.setIcon( icon ); + disabledButton2.setDisabledIcon( disabledIcon ); + disabledTabbedPane2.addTab( "tab", null ); + disabledTabbedPane2.setIconAt( 0, icon ); + disabledTabbedPane2.setDisabledIconAt( 0, disabledIcon ); + + disabledChanged(); } private void addSVGIcon( String name ) { @@ -72,6 +89,31 @@ public class FlatExtrasTest triStateLabel2.setText( triStateCheckBox2.getState().toString() ); } + private void disabledChanged() { + boolean enabled = !disabledCheckBox.isSelected(); + + disabledLabel.setEnabled( enabled ); + disabledButton.setEnabled( enabled ); + disabledTabbedPane.setEnabledAt( 0, enabled ); + + disabledLabel2.setEnabled( enabled ); + disabledButton2.setEnabled( enabled ); + disabledTabbedPane2.setEnabledAt( 0, enabled ); + } + + @Override + public void updateUI() { + super.updateUI(); + + if( disabledLabel == null ) + return; + + // clear automatically created disabled icons when switching Laf + disabledLabel.setDisabledIcon( null ); + disabledButton.setDisabledIcon( null ); + disabledTabbedPane.setDisabledIconAt( 0, null ); + } + private void initComponents() { // JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents label1 = new JLabel(); @@ -82,6 +124,16 @@ public class FlatExtrasTest label2 = new JLabel(); svgIconsPanel = new JPanel(); label3 = new JLabel(); + label4 = new JLabel(); + disabledLabel = new JLabel(); + disabledButton = new JButton(); + disabledTabbedPane = new JTabbedPane(); + label5 = new JLabel(); + disabledCheckBox = new JCheckBox(); + disabledLabel2 = new JLabel(); + disabledButton2 = new JButton(); + disabledTabbedPane2 = new JTabbedPane(); + label6 = new JLabel(); //======== this ======== setLayout(new MigLayout( @@ -94,6 +146,9 @@ public class FlatExtrasTest "[]" + "[]" + "[]" + + "[]" + + "[]" + + "[]" + "[]")); //---- label1 ---- @@ -139,6 +194,45 @@ public class FlatExtrasTest //---- label3 ---- label3.setText("The icons may change colors when switching to another theme."); add(label3, "cell 1 3 2 1"); + + //---- label4 ---- + label4.setText("Disabled SVG Icons:"); + add(label4, "cell 0 4"); + + //---- disabledLabel ---- + disabledLabel.setText("label"); + add(disabledLabel, "cell 1 4 2 1"); + + //---- disabledButton ---- + disabledButton.setText("button"); + add(disabledButton, "cell 1 4 2 1"); + add(disabledTabbedPane, "cell 1 4 2 1"); + + //---- label5 ---- + label5.setText("only setIcon()"); + label5.setEnabled(false); + add(label5, "cell 1 4 2 1,gapx 20"); + + //---- disabledCheckBox ---- + disabledCheckBox.setText("disabled"); + disabledCheckBox.setSelected(true); + disabledCheckBox.setMnemonic('D'); + disabledCheckBox.addActionListener(e -> disabledChanged()); + add(disabledCheckBox, "cell 0 5,alignx left,growx 0"); + + //---- disabledLabel2 ---- + disabledLabel2.setText("label"); + add(disabledLabel2, "cell 1 5 2 1"); + + //---- disabledButton2 ---- + disabledButton2.setText("button"); + add(disabledButton2, "cell 1 5 2 1"); + add(disabledTabbedPane2, "cell 1 5 2 1"); + + //---- label6 ---- + label6.setText("setIcon() and setDisabledIcon()"); + label6.setEnabled(false); + add(label6, "cell 1 5 2 1,gapx 20"); // JFormDesigner - End of component initialization //GEN-END:initComponents } @@ -151,5 +245,15 @@ public class FlatExtrasTest private JLabel label2; private JPanel svgIconsPanel; private JLabel label3; + private JLabel label4; + private JLabel disabledLabel; + private JButton disabledButton; + private JTabbedPane disabledTabbedPane; + private JLabel label5; + private JCheckBox disabledCheckBox; + private JLabel disabledLabel2; + private JButton disabledButton2; + private JTabbedPane disabledTabbedPane2; + private JLabel label6; // JFormDesigner - End of variables declaration //GEN-END:variables } diff --git a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/extras/FlatExtrasTest.jfd b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/extras/FlatExtrasTest.jfd index 85f30970..fc34f236 100644 --- a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/extras/FlatExtrasTest.jfd +++ b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/extras/FlatExtrasTest.jfd @@ -1,4 +1,4 @@ -JFDML JFormDesigner: "7.0.2.0.298" Java: "14" encoding: "UTF-8" +JFDML JFormDesigner: "7.0.2.0.298" Java: "15" encoding: "UTF-8" new FormModel { contentType: "form/swing" @@ -6,7 +6,7 @@ new FormModel { add( new FormContainer( "com.formdev.flatlaf.testing.FlatTestPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) { "$layoutConstraints": "ltr,insets dialog,hidemode 3" "$columnConstraints": "[][][left]" - "$rowConstraints": "[][][][]" + "$rowConstraints": "[][][][][][][]" } ) { name: "this" add( new FormComponent( "javax.swing.JLabel" ) { @@ -65,9 +65,72 @@ new FormModel { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { "value": "cell 1 3 2 1" } ) + add( new FormComponent( "javax.swing.JLabel" ) { + name: "label4" + "text": "Disabled SVG Icons:" + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 0 4" + } ) + add( new FormComponent( "javax.swing.JLabel" ) { + name: "disabledLabel" + "text": "label" + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 1 4 2 1" + } ) + add( new FormComponent( "javax.swing.JButton" ) { + name: "disabledButton" + "text": "button" + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 1 4 2 1" + } ) + add( new FormContainer( "javax.swing.JTabbedPane", new FormLayoutManager( class javax.swing.JTabbedPane ) ) { + name: "disabledTabbedPane" + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 1 4 2 1" + } ) + add( new FormComponent( "javax.swing.JLabel" ) { + name: "label5" + "text": "only setIcon()" + "enabled": false + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 1 4 2 1,gapx 20" + } ) + add( new FormComponent( "javax.swing.JCheckBox" ) { + name: "disabledCheckBox" + "text": "disabled" + "selected": true + "mnemonic": 68 + addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "disabledChanged", false ) ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 0 5,alignx left,growx 0" + } ) + add( new FormComponent( "javax.swing.JLabel" ) { + name: "disabledLabel2" + "text": "label" + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 1 5 2 1" + } ) + add( new FormComponent( "javax.swing.JButton" ) { + name: "disabledButton2" + "text": "button" + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 1 5 2 1" + } ) + add( new FormContainer( "javax.swing.JTabbedPane", new FormLayoutManager( class javax.swing.JTabbedPane ) ) { + name: "disabledTabbedPane2" + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 1 5 2 1" + } ) + add( new FormComponent( "javax.swing.JLabel" ) { + name: "label6" + "text": "setIcon() and setDisabledIcon()" + "enabled": false + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 1 5 2 1,gapx 20" + } ) }, new FormLayoutConstraints( null ) { "location": new java.awt.Point( 0, 0 ) - "size": new java.awt.Dimension( 500, 300 ) + "size": new java.awt.Dimension( 595, 300 ) } ) } }