Browse Source

Add foreground color generation demo.

Remove unused method.
Move #getLuminance to ColorUtil.
Made Background luminance threshold variable (use 0.5 by default).
pull/189/head
weisj 4 years ago
parent
commit
656943a9d3
  1. 2
      core/src/main/java/com/github/weisj/darklaf/components/ColoredRadioButton.java
  2. 29
      core/src/main/java/com/github/weisj/darklaf/components/color/QuickColorChooser.java
  3. 59
      core/src/main/java/com/github/weisj/darklaf/task/ForegroundColorGenerationTask.java
  4. 77
      core/src/test/java/ui/ForegroundDemo.java
  5. 14
      utils/src/main/java/com/github/weisj/darklaf/util/ColorUtil.java

2
core/src/main/java/com/github/weisj/darklaf/components/ColoredRadioButton.java

@ -210,8 +210,10 @@ public class ColoredRadioButton extends JRadioButton {
}
}
for (String prop : FOREGROUND_PROPERTIES) {
ForegroundColorGenerationTask.Bias bias = ForegroundColorGenerationTask.Bias.getBackground(0.552);
Color fg = ForegroundColorGenerationTask.makeAdjustedForeground((Color) props.get(prop),
accentCol,
bias,
MIN_FG_CONTRAST);
propertyMap.put(prop, fg);
}

29
core/src/main/java/com/github/weisj/darklaf/components/color/QuickColorChooser.java

@ -39,7 +39,9 @@ import com.github.weisj.darklaf.listener.MouseClickListener;
public class QuickColorChooser extends JPanel {
private final SolidColorIcon icon;
private JCheckBox checkBox;
private final JCheckBox checkBox;
private final JLabel colorLabel;
private final BiConsumer<Boolean, Color> onStatusChange;
public QuickColorChooser(final String title, final Color color, final Consumer<Color> onColorChange) {
this(title, color, (b, c) -> onColorChange.accept(c), false);
@ -52,20 +54,25 @@ public class QuickColorChooser extends JPanel {
checkBox = new JCheckBox();
checkBox.addActionListener(e -> onStatusChange.accept(isSelected(), getColor()));
add(checkBox);
} else {
checkBox = null;
}
icon = new SolidColorIcon(color);
JLabel colorLabel = new JLabel(icon, JLabel.LEFT);
attachToComponent(colorLabel, c -> {
onStatusChange.accept(isSelected(), c);
icon.setColor(c);
colorLabel.repaint();
}, icon::getColor);
colorLabel = new JLabel(icon, JLabel.LEFT);
this.onStatusChange = onStatusChange;
attachToComponent(colorLabel, this::onColorChange, icon::getColor);
add(colorLabel);
add(new JLabel(title, EmptyIcon.create(2, 2), JLabel.LEFT));
}
private void onColorChange(final Color c) {
onStatusChange.accept(isSelected(), c);
icon.setColor(c);
colorLabel.repaint();
}
public QuickColorChooser(final String title, final Color color, final BiConsumer<Boolean, Color> onStatusChange) {
this(title, color, onStatusChange, true);
}
@ -96,7 +103,15 @@ public class QuickColorChooser extends JPanel {
return checkBox != null && checkBox.isSelected();
}
public void setSelected(final boolean selected) {
if (checkBox != null) checkBox.setSelected(selected);
}
public Color getColor() {
return icon.getColor();
}
public void setColor(final Color color) {
onColorChange(color);
}
}

59
core/src/main/java/com/github/weisj/darklaf/task/ForegroundColorGenerationTask.java

@ -35,13 +35,14 @@ import com.github.weisj.darklaf.color.DarkColorModelHSL;
import com.github.weisj.darklaf.theme.Theme;
import com.github.weisj.darklaf.theme.info.AccentColorRule;
import com.github.weisj.darklaf.uiresource.DarkColorUIResource;
import com.github.weisj.darklaf.util.ColorUtil;
import com.github.weisj.darklaf.util.Pair;
public class ForegroundColorGenerationTask extends ColorAdjustmentTask {
private static final String FOREGROUND_LIST_KEY = "selectionForeground.propertyList";
private static final String ACCENT_LIST_KEY = "accentForeground.propertyList";
private static final double MIN_FOREGROUND_DIFFERENCE = 0.4;
private static final double MIN_FOREGROUND_DIFFERENCE = 0.6;
@Override
protected void beforeTask(final Theme currentTheme, final Properties properties) {
@ -66,19 +67,22 @@ public class ForegroundColorGenerationTask extends ColorAdjustmentTask {
.filter(o -> o instanceof Pair<?, ?>)
.map(Pair.class::cast)
.filter(p -> p.getFirst() instanceof Color)
.forEach(p -> properties.put(p.getSecond(), makeForeground((Color) p.getFirst(),
MIN_FOREGROUND_DIFFERENCE)));
.forEach(p -> properties.put(p.getSecond(), makeForeground((Color) p.getFirst())));
}
public static ColorUIResource makeForeground(final Color bg) {
return makeForeground(bg, MIN_FOREGROUND_DIFFERENCE);
}
public static ColorUIResource makeForeground(final Color bg, final double minimumBrightnessDifference) {
double[] hsbBG = DarkColorModelHSB.RGBtoHSBValues(bg.getRed(), bg.getGreen(), bg.getBlue());
Color fg = DarkColorModelHSB.getColorFromHSBValues(hsbBG[0], 0, 1 - hsbBG[2]);
return makeAdjustedForeground(fg, bg, Bias.BACKGROUND, minimumBrightnessDifference);
return makeAdjustedForeground(fg, bg, Bias.getBackground(), minimumBrightnessDifference);
}
public static ColorUIResource makeAdjustedForeground(final Color fg, final Color bg,
final double minimumBrightnessDifference) {
return makeAdjustedForeground(fg, bg, Bias.BACKGROUND, minimumBrightnessDifference);
return makeAdjustedForeground(fg, bg, Bias.getBackground(), minimumBrightnessDifference);
}
public static ColorUIResource makeAdjustedForeground(final Color fg, final Color bg, final Bias bias,
@ -88,11 +92,11 @@ public class ForegroundColorGenerationTask extends ColorAdjustmentTask {
double bgBrightness = hslBG[2];
double fgBrightness = hslFG[2];
Bias b = bias != null ? bias : Bias.BACKGROUND;
Bias b = bias != null ? bias : Bias.getBackground();
if (b == Bias.BACKGROUND) {
double bgBright = getLuminance(bg);
b = bgBright <= 0.552 ? Bias.WHITE : Bias.BLACK;
double bgBright = ColorUtil.getLuminance(bg);
b = bgBright <= b.threshold ? Bias.WHITE : Bias.BLACK;
}
double bright1 = fgBrightness > bgBrightness && (fgBrightness - bgBrightness) >= minimumBrightnessDifference
@ -106,35 +110,24 @@ public class ForegroundColorGenerationTask extends ColorAdjustmentTask {
return new DarkColorUIResource(DarkColorModelHSL.getColorFromHSLValues(hslFG[0], hslFG[1], brightness));
}
private static double getLuminance(final Color c) {
return getLuminance(c.getRed(), c.getGreen(), c.getBlue());
}
private static double getLuminance(final int red, final int green, final int blue) {
double r = red / 255.0;
double g = green / 255.0;
double b = blue / 255.0;
double R = r <= 0.03928 ? r / 12.92 : Math.pow((r + 0.055) / 1.055, 2.4);
double G = g <= 0.03928 ? g / 12.92 : Math.pow((g + 0.055) / 1.055, 2.4);
double B = b <= 0.03928 ? b / 12.92 : Math.pow((b + 0.055) / 1.055, 2.4);
return 0.2126 * R + 0.7152 * G + 0.0722 * B;
}
public enum Bias {
BACKGROUND,
WHITE,
BLACK;
private static double calculateContrast(final double fgBrightness, final double bgBrightness) {
double bright = Math.max(fgBrightness, bgBrightness);
double dark = Math.min(fgBrightness, bgBrightness);
return (bright + 0.05) / (dark + 0.05);
}
public static Bias getBackground() {
return getBackground(0.5);
}
public enum Bias {
BACKGROUND(0),
WHITE(1),
BLACK(-1);
public static Bias getBackground(final double threshold) {
BACKGROUND.setThreshold(threshold);
return BACKGROUND;
}
private final int direction;
private double threshold = 0.5;
Bias(final int direction) {
this.direction = direction;
public void setThreshold(final double threshold) {
this.threshold = threshold;
}
}
}

77
core/src/test/java/ui/ForegroundDemo.java

@ -0,0 +1,77 @@
/*
* MIT License
*
* Copyright (c) 2020 Jannis Weis
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ui;
import java.awt.*;
import java.util.function.Consumer;
import javax.swing.*;
import com.github.weisj.darklaf.LafManager;
import com.github.weisj.darklaf.components.color.QuickColorChooser;
import com.github.weisj.darklaf.task.ForegroundColorGenerationTask;
import com.github.weisj.darklaf.theme.event.ThemeInstalledListener;
public class ForegroundDemo implements ComponentDemo {
public static void main(final String[] args) {
ComponentDemo.showDemo(new ForegroundDemo());
}
@Override
public JComponent createComponent() {
JPanel holder = new JPanel(new GridBagLayout());
holder.setPreferredSize(new Dimension(300, 100));
holder.setOpaque(true);
JLabel label = new JLabel("Demo Readability Text");
holder.add(label);
DemoPanel panel = new DemoPanel(holder, new BorderLayout(), 0);
JPanel controls = panel.addControls();
Consumer<Color> updater = c -> SwingUtilities.invokeLater(() -> {
holder.setBackground(c);
label.setForeground(ForegroundColorGenerationTask.makeForeground(c));
label.repaint();
});
Color current = UIManager.getColor("textCompSelectionBackground");
updater.accept(current);
QuickColorChooser quickColorChooser = new QuickColorChooser("Background", current, updater);
controls.add(quickColorChooser);
LafManager.addThemeChangeListener((ThemeInstalledListener) e -> {
Color c = UIManager.getColor("textCompSelectionBackground");
quickColorChooser.setColor(c);
updater.accept(c);
});
return panel;
}
@Override
public String getTitle() {
return "Foreground Color Demo";
}
}

14
utils/src/main/java/com/github/weisj/darklaf/util/ColorUtil.java

@ -106,4 +106,18 @@ public final class ColorUtil {
+ 0.587 * c.getGreen() * c.getGreen()
+ 0.114 * c.getBlue() * c.getBlue());
}
public static double getLuminance(final Color c) {
return getLuminance(c.getRed(), c.getGreen(), c.getBlue());
}
public static double getLuminance(final int red, final int green, final int blue) {
double r = red / 255.0;
double g = green / 255.0;
double b = blue / 255.0;
double R = r <= 0.03928 ? r / 12.92 : Math.pow((r + 0.055) / 1.055, 2.4);
double G = g <= 0.03928 ? g / 12.92 : Math.pow((g + 0.055) / 1.055, 2.4);
double B = b <= 0.03928 ? b / 12.92 : Math.pow((b + 0.055) / 1.055, 2.4);
return 0.2126 * R + 0.7152 * G + 0.0722 * B;
}
}

Loading…
Cancel
Save