I'm currently designing a Swing app with a custom "yellow on black" Look and Feel, and it seems SynthLookAndFeel is the way to go.
All my buttons consist of an ImageIcon (no text), for example:
When buttons are disabled, I would like the icons to turn to a faded yellow:
However, the default disabled icons are just greyscale versions of the "enabled" ones, and that breaks the yellow feel:
I read in this answer that disabled icons are generated internally by getDisabledIcon()
, but I find no place to control it from synth's XML file.
I also read about SynthLookAndFeel's SynthPainter class, but it doesn't seem to address the question of disabled icons.
Is there a way to control that "getDisabledIcon" behaviour using SynthLookAndFeel, or am I asking too much ? In the latter case, what would be the best suited look and feel to use or extend for easy definition of button backgrounds, shapes, etc ?
Any hint is welcome.
OK, I think I found a clean way.
I was hesitating between finding a way with SynthLookAndFeel or subclassing another L&F... But didn't think of subclassing SynthLookAndFeel itself :-)
I've now got an implementation of SynthLookAndFeel that does exactly what I want, meaning the "disabled" icon is not a greyscale one, it's a desaturated, dimmed, color version:
Here we go for the full code:
import javax.swing.*;
import javax.swing.plaf.synth.SynthLookAndFeel;
import java.awt.*;
import java.awt.image.FilteredImageSource;
import java.awt.image.ImageProducer;
import java.awt.image.RGBImageFilter;
public class MySynthLookAndFeel extends SynthLookAndFeel {
@Override
public Icon getDisabledIcon(JComponent component, Icon icon) {
if (icon instanceof ImageIcon) {
return new ImageIcon(createDisabledImage(((ImageIcon)icon).getImage()));
}
return null;
}
private static Image createDisabledImage(Image i) {
ImageProducer prod = new FilteredImageSource(i.getSource(), new RGBImageFilter() {
public int filterRGB(int x, int y, int rgb) {
// extract alpha mask
int alphamask = rgb & 0xFF000000;
// convert to HSB
float[] hsb = Color.RGBtoHSB((rgb >> 16) & 0xff, (rgb >> 8) & 0xff, rgb & 0xff, null);
// desaturate (half saturation)
hsb[1] *= 0.5;
// dim (half brightness)
hsb[2] *= 0.5;
// convert back to RGB
int rgbval = Color.HSBtoRGB(hsb[0], hsb[1], hsb[2]);
// reapply alpha
rgbval = rgbval & 0x00FFFFFF | alphamask;
return rgbval;
}
});
return Toolkit.getDefaultToolkit().createImage(prod);
}
}
Much simpler than I thought, in the end.