-
-
Notifications
You must be signed in to change notification settings - Fork 280
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
FlatSVGIcon color filters #303
Conversation
Interesting idea 👍 There is already a way to map own colors, but this is global for all icons and not dynamic. E.g.: FlatSVGIcon.ColorFilter globalColorFilter = FlatSVGIcon.ColorFilter.getInstance();
// map red to orange
globalColorFilter.add( Color.red, Color.orange ); I'm not sure whether Probably a simple public void setFilter( Function<Color, Color> filter ) {
...
} Then the example from the first post becomes: icon.setFilter( color -> color.brighter() ); What do you think? BTW please rebase the PR branch to |
f7eeb1c
to
1e6257c
Compare
I agree that there is no need to use the RGBImageFilter for this and the java.util function would work just fine, the only drawback I see is that the already existing GrayFilter can't be used with it. But I'm sure something similar can be written that would allow easy brightness/contrast modifications. So yeah, what you're suggesting would certainly work nicely. However, I see you mentioned the global color map that can be set using the ColorFilter. That got me thinking that a good way to handle could be to expand the ColorFilter class itself to act not only as a color mapper but as well as a way to directly modify the color. It could then be set as a filter for a single FlatSVGIcon instance as well as a global modification that goes beyond the scope of just mapping colors. From a user perspective, it would be easier to modify rgb values than to set a color map. It would also allow dynamic color changes like with the single FlatSVGIcon instance. 2 hours later I got a little carried away. So instead I made ColorFilter fill both roles. I added a new field to it So besides setting a filter to an instance, you can create a global icon filter using for example FlatSVGIcon.ColorFilter.getInstance().setFilter( color -> Color.RED ); and as I've said already it will work with mappings at the same time FlatSVGIcon.ColorFilter globalColorFilter = FlatSVGIcon.ColorFilter.getInstance();
globalColorFilter.add( Color.red, Color.orange );
globalColorFilter.setFilter( color -> color.brighter() ); And just to recap here is a compact way of setting an instance filter icon.setFilter( new ColorFilter( color -> color.brighter() ) ); I added some basic Javadoc wherever I could to clarify things. Also to test it I added a little demo to the flatlaf-demo extras panel. Here's a picture. Just for fun, I created a rainbow icon to show off how it can work dynamically. Also, I rebased the branch to the latest commit. I hope that's what you meant :D. |
…the ColorFilter class and can work globally too. Added related demo components to flatlaf-demo extras tab.
… a little and added a utility method to ColorFilter to easily create a brightness/contrast/alpha filter.
9fab67c
to
d3bf443
Compare
Also, I think it would be interesting to expand this functionality to raster icons as well. There could be a universal FlatIcon class that would have these filtering capabilities using the quite intriguing GraphicsProxy. It could delegate .svg icons to FlatSVGIcon and other image types to regular ImageIcon. For applications that are using raster icons or are on their way to convert to .svg icons, it would unify Icon declaration to just using a catchall FlatIcon (or similarly named) instead of using ImageIcon for some and FlagSVGIcon for others. Now I'm guessing that for raster images, the current color mapping defined by the themes would not work too well**. But it would be interesting to maybe explore some option to use these filters to automatically adjust icon color (be it raster or svg) based on their contrast with the background or something similar. It could also go as far as generating dark variants for icons that don't have one explicitly provided. Just an idea 😅 ** Because pixels can have slightly different colors that look the same from afar. |
Fantastic idea to use class I'll have a closer look soon... |
I kinda already mentioned the possibility to create dark theme icons automatically or similar. This could be easily simplified by obviously setting a ColorFilter like previously discussed, but I think I would be nice to add a FlatSVGIcon constructor that would allow you to set a color for both Light or Dark themes. As a constructor it would function for per icon basis, so unlike using a global mapping, for example, icons that don't use this silhouette style won't be affected by it. You could then set up a little loader method just for icons using a certain style. The only requirement is the FlatSVGIcon object to be able to figure out which theme is currently in use, I think there is a FlatLaf way to figure that out I just can't recall it. The constructor could look something like TLDR: Recoloring icons manually is tedious, same with renaming them and the simple fact is most icon repositories won't give you a _dark variant by default. Also, I'm glad you liked the ColorFilter idea 😄 |
@xDUDSSx thanks for your ideas and your contribution. I've merged it with following changes:
Additionally, I've made following changes/improvements:
Color filter now supports different mappings for light and dark themes. Following example maps colorFilter.add( Color.gray, Color.lightGray, Color.darkGray ); Class icon.setColorFilter( new ColorFilter().add( Color.black, Color.darkGray ) ); or icon.setColorFilter( new ColorFilter()
.add( Color.black, Color.darkGray )
.add( Color.red, Color.magenta )
.add( Color.gray, Color.lightGray, Color.darkGray ) ); Made also some changes to the Demo:
|
@xDUDSSx regarding the idea for an additional constructor: well, I'm not a fan of this idea for various reasons:
|
@DevCharly I like the way color mappings and the color function work now, I'm just missing a general way of specifying dark/light theme colors without worrying about the actual color of the icon. Here's what's possible right now: icon.setColorFilter(new ColorFilter((color) -> {
if (FlatLaf.isLafDark()) {
return Color.red;
} else {
return Color.green;
}
})); This works, but it feels like there could be a better way. icon.setColorFilter(new ColorFilter(color -> UIManager.getColor("Label.foreground").brighter())); This also works quite nicely, might even give interesting results for different themes. Anyway, I just want to leave these examples here as I find them quite useful. I don't know if it's necessary to make any additional changes to make this sort of a thing more accessible. It might just be enough to mention these use cases of the ColorFilter somewhere, possibly just in the javadoc. Glad that I could help 😃 |
This pull request adds the ability to specify an RGBImageFilter to a FlatSVGIcon.
I was looking for this functionality when developing a custom swing component to use with FlatLaf. This component needed to display SVG icon silhouettes that would have a different color for a hover effect.
Specifying a filter allows me to change every SVG icon to a single color silhouette as well as change its color on the fly.
That could now be accomplished with
That example uses a new class that subclasses the standard RGBImageFilter to pass and return a Color object for simplicity.
An RGBImageFilter can be passed too, as well as the com.formdev.flatlaf.util.GrayFilter like so
I'm sure some sort of a basic ability to change SVG icon colors would be useful. I saw that the ability to do so is already in the FlatSVGIcon, just not exposed publicly.
Here's an example of the component I was working on, it's a sidebar that can easily draw the hover effects using FlatSVGIcon.
