Implement changing color variables at runtime via contrast checker
This commit is contained in:
parent
aad6b06e12
commit
8479d9431f
@ -3,6 +3,7 @@ package atlantafx.sampler.page.general;
|
|||||||
|
|
||||||
import atlantafx.base.controls.CustomTextField;
|
import atlantafx.base.controls.CustomTextField;
|
||||||
import atlantafx.base.theme.Styles;
|
import atlantafx.base.theme.Styles;
|
||||||
|
import atlantafx.sampler.theme.ThemeManager;
|
||||||
import atlantafx.sampler.util.JColor;
|
import atlantafx.sampler.util.JColor;
|
||||||
import atlantafx.sampler.util.JColorUtils;
|
import atlantafx.sampler.util.JColorUtils;
|
||||||
import javafx.beans.binding.Bindings;
|
import javafx.beans.binding.Bindings;
|
||||||
@ -256,8 +257,8 @@ public class ColorContrastChecker extends GridPane {
|
|||||||
|
|
||||||
// ~
|
// ~
|
||||||
|
|
||||||
var flattenButton = new Button("Flatten");
|
var flattenBtn = new Button("Flatten");
|
||||||
flattenButton.setOnAction(e -> {
|
flattenBtn.setOnAction(e -> {
|
||||||
double[] flatBg = flattenColor(bgBaseColor.get(), bgColor.getColor());
|
double[] flatBg = flattenColor(bgBaseColor.get(), bgColor.getColor());
|
||||||
setBackground(Color.color(flatBg[0], flatBg[1], flatBg[2]));
|
setBackground(Color.color(flatBg[0], flatBg[1], flatBg[2]));
|
||||||
|
|
||||||
@ -265,6 +266,17 @@ public class ColorContrastChecker extends GridPane {
|
|||||||
setForeground(Color.color(flatFg[0], flatFg[1], flatFg[2]));
|
setForeground(Color.color(flatFg[0], flatFg[1], flatFg[2]));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
var applyBtn = new Button("Apply");
|
||||||
|
applyBtn.setOnAction(e -> {
|
||||||
|
var tm = ThemeManager.getInstance();
|
||||||
|
tm.setColor(getBgColorName(), bgColor.getColor());
|
||||||
|
tm.setColor(getFgColorName(), fgColor.getColor());
|
||||||
|
tm.reloadCustomCSS();
|
||||||
|
});
|
||||||
|
|
||||||
|
var controlsBox = new HBox(20, flattenBtn, applyBtn);
|
||||||
|
controlsBox.setAlignment(Pos.CENTER_LEFT);
|
||||||
|
|
||||||
// ~
|
// ~
|
||||||
|
|
||||||
getStyleClass().add("contrast-checker");
|
getStyleClass().add("contrast-checker");
|
||||||
@ -283,7 +295,7 @@ public class ColorContrastChecker extends GridPane {
|
|||||||
add(bgAlphaLabel, 0, 10);
|
add(bgAlphaLabel, 0, 10);
|
||||||
add(bgAlphaSlider, 0, 11);
|
add(bgAlphaSlider, 0, 11);
|
||||||
|
|
||||||
add(flattenButton, 0, 12);
|
add(controlsBox, 0, 12, REMAINING, 1);
|
||||||
|
|
||||||
// column 1
|
// column 1
|
||||||
add(wsagBox, 1, 0);
|
add(wsagBox, 1, 0);
|
||||||
|
@ -3,6 +3,7 @@ package atlantafx.sampler.page.general;
|
|||||||
|
|
||||||
import atlantafx.base.theme.Theme;
|
import atlantafx.base.theme.Theme;
|
||||||
import atlantafx.sampler.page.AbstractPage;
|
import atlantafx.sampler.page.AbstractPage;
|
||||||
|
import atlantafx.sampler.theme.ThemeEvent.EventType;
|
||||||
import atlantafx.sampler.theme.ThemeManager;
|
import atlantafx.sampler.theme.ThemeManager;
|
||||||
import javafx.scene.control.ChoiceBox;
|
import javafx.scene.control.ChoiceBox;
|
||||||
import javafx.scene.control.Label;
|
import javafx.scene.control.Label;
|
||||||
@ -24,6 +25,12 @@ public class ThemePage extends AbstractPage {
|
|||||||
public ThemePage() {
|
public ThemePage() {
|
||||||
super();
|
super();
|
||||||
createView();
|
createView();
|
||||||
|
ThemeManager.getInstance().addEventListener(e -> {
|
||||||
|
if (e.eventType() == EventType.THEME_CHANGE || e.eventType() == EventType.CUSTOM_CSS_CHANGE) {
|
||||||
|
// only works for managed nodes
|
||||||
|
colorPalette.updateColorInfo(Duration.ofSeconds(1));
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -37,6 +44,8 @@ public class ThemePage extends AbstractPage {
|
|||||||
optionsGrid(),
|
optionsGrid(),
|
||||||
colorPalette
|
colorPalette
|
||||||
);
|
);
|
||||||
|
// if you want to enable quick menu don't forget that
|
||||||
|
// theme selection choice box have to be updated accordingly
|
||||||
quickConfigBtn.setVisible(false);
|
quickConfigBtn.setVisible(false);
|
||||||
quickConfigBtn.setManaged(false);
|
quickConfigBtn.setManaged(false);
|
||||||
sourceCodeToggleBtn.setVisible(false);
|
sourceCodeToggleBtn.setVisible(false);
|
||||||
@ -69,7 +78,6 @@ public class ThemePage extends AbstractPage {
|
|||||||
var tm = ThemeManager.getInstance();
|
var tm = ThemeManager.getInstance();
|
||||||
tm.setTheme(val);
|
tm.setTheme(val);
|
||||||
tm.reloadCustomCSS();
|
tm.reloadCustomCSS();
|
||||||
colorPalette.updateColorInfo(Duration.ofSeconds(1));
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@ package atlantafx.sampler.page.general;
|
|||||||
|
|
||||||
import atlantafx.sampler.page.AbstractPage;
|
import atlantafx.sampler.page.AbstractPage;
|
||||||
import atlantafx.sampler.page.SampleBlock;
|
import atlantafx.sampler.page.SampleBlock;
|
||||||
|
import atlantafx.sampler.theme.ThemeEvent.EventType;
|
||||||
import atlantafx.sampler.theme.ThemeManager;
|
import atlantafx.sampler.theme.ThemeManager;
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
import javafx.collections.FXCollections;
|
import javafx.collections.FXCollections;
|
||||||
@ -41,6 +42,12 @@ public class TypographyPage extends AbstractPage {
|
|||||||
public TypographyPage() {
|
public TypographyPage() {
|
||||||
super();
|
super();
|
||||||
createView();
|
createView();
|
||||||
|
ThemeManager.getInstance().addEventListener(e -> {
|
||||||
|
if (e.eventType() == EventType.FONT_FAMILY_CHANGE || e.eventType() == EventType.FONT_SIZE_CHANGE) {
|
||||||
|
// only works for managed nodes
|
||||||
|
updateFontInfo(Duration.ofMillis(1000));
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createView() {
|
private void createView() {
|
||||||
@ -65,6 +72,8 @@ public class TypographyPage extends AbstractPage {
|
|||||||
textColorSample().getRoot(),
|
textColorSample().getRoot(),
|
||||||
textFlowSample().getRoot()
|
textFlowSample().getRoot()
|
||||||
);
|
);
|
||||||
|
// if you want to enable quick menu don't forget that
|
||||||
|
// font size spinner value have to be updated accordingly
|
||||||
quickConfigBtn.setVisible(false);
|
quickConfigBtn.setVisible(false);
|
||||||
quickConfigBtn.setManaged(false);
|
quickConfigBtn.setManaged(false);
|
||||||
sourceCodeToggleBtn.setVisible(false);
|
sourceCodeToggleBtn.setVisible(false);
|
||||||
@ -84,7 +93,6 @@ public class TypographyPage extends AbstractPage {
|
|||||||
if (val != null) {
|
if (val != null) {
|
||||||
tm.setFontFamily(DEFAULT_FONT_ID.equals(val) ? ThemeManager.DEFAULT_FONT_FAMILY_NAME : val);
|
tm.setFontFamily(DEFAULT_FONT_ID.equals(val) ? ThemeManager.DEFAULT_FONT_FAMILY_NAME : val);
|
||||||
tm.reloadCustomCSS();
|
tm.reloadCustomCSS();
|
||||||
updateFontInfo(Duration.ofMillis(1000));
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -0,0 +1,11 @@
|
|||||||
|
package atlantafx.sampler.theme;
|
||||||
|
|
||||||
|
public record ThemeEvent(EventType eventType) {
|
||||||
|
|
||||||
|
public enum EventType {
|
||||||
|
THEME_CHANGE,
|
||||||
|
FONT_FAMILY_CHANGE,
|
||||||
|
FONT_SIZE_CHANGE,
|
||||||
|
CUSTOM_CSS_CHANGE
|
||||||
|
}
|
||||||
|
}
|
@ -6,12 +6,16 @@ import atlantafx.base.theme.PrimerLight;
|
|||||||
import atlantafx.base.theme.Theme;
|
import atlantafx.base.theme.Theme;
|
||||||
import atlantafx.sampler.Launcher;
|
import atlantafx.sampler.Launcher;
|
||||||
import atlantafx.sampler.Resources;
|
import atlantafx.sampler.Resources;
|
||||||
|
import atlantafx.sampler.theme.ThemeEvent.EventType;
|
||||||
|
import atlantafx.sampler.util.JColor;
|
||||||
import javafx.application.Application;
|
import javafx.application.Application;
|
||||||
import javafx.css.PseudoClass;
|
import javafx.css.PseudoClass;
|
||||||
import javafx.scene.Scene;
|
import javafx.scene.Scene;
|
||||||
|
import javafx.scene.paint.Color;
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||||
|
|
||||||
@ -33,11 +37,16 @@ public final class ThemeManager {
|
|||||||
private Theme currentTheme = null;
|
private Theme currentTheme = null;
|
||||||
private String fontFamily = DEFAULT_FONT_FAMILY_NAME;
|
private String fontFamily = DEFAULT_FONT_FAMILY_NAME;
|
||||||
private int fontSize = DEFAULT_FONT_SIZE;
|
private int fontSize = DEFAULT_FONT_SIZE;
|
||||||
|
private final List<Consumer<ThemeEvent>> eventListeners = new ArrayList<>();
|
||||||
|
|
||||||
public Scene getScene() {
|
public Scene getScene() {
|
||||||
return scene;
|
return scene;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addEventListener(Consumer<ThemeEvent> listener) {
|
||||||
|
eventListeners.add(Objects.requireNonNull(listener));
|
||||||
|
}
|
||||||
|
|
||||||
public void setScene(Scene scene) {
|
public void setScene(Scene scene) {
|
||||||
this.scene = scene;
|
this.scene = scene;
|
||||||
}
|
}
|
||||||
@ -66,6 +75,7 @@ public final class ThemeManager {
|
|||||||
|
|
||||||
theme.getStylesheets().forEach(uri -> scene.getStylesheets().add(uri.toString()));
|
theme.getStylesheets().forEach(uri -> scene.getStylesheets().add(uri.toString()));
|
||||||
currentTheme = theme;
|
currentTheme = theme;
|
||||||
|
notifyEventListeners(EventType.THEME_CHANGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Theme> getAvailableThemes() {
|
public List<Theme> getAvailableThemes() {
|
||||||
@ -104,6 +114,7 @@ public final class ThemeManager {
|
|||||||
Objects.requireNonNull(fontFamily);
|
Objects.requireNonNull(fontFamily);
|
||||||
setCustomDeclaration("-fx-font-family", "\"" + fontFamily + "\"");
|
setCustomDeclaration("-fx-font-family", "\"" + fontFamily + "\"");
|
||||||
this.fontFamily = fontFamily;
|
this.fontFamily = fontFamily;
|
||||||
|
notifyEventListeners(EventType.FONT_FAMILY_CHANGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isDefaultFontFamily() {
|
public boolean isDefaultFontFamily() {
|
||||||
@ -118,16 +129,38 @@ public final class ThemeManager {
|
|||||||
setCustomDeclaration("-fx-font-size", fontSize + "px");
|
setCustomDeclaration("-fx-font-size", fontSize + "px");
|
||||||
setCustomRule(".ikonli-font-icon", String.format("-fx-icon-size: %dpx;", fontSize + 2));
|
setCustomRule(".ikonli-font-icon", String.format("-fx-icon-size: %dpx;", fontSize + 2));
|
||||||
this.fontSize = fontSize;
|
this.fontSize = fontSize;
|
||||||
|
notifyEventListeners(EventType.FONT_SIZE_CHANGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setColor(String colorName, Color color) {
|
||||||
|
Objects.requireNonNull(colorName);
|
||||||
|
Objects.requireNonNull(color);
|
||||||
|
setCustomDeclaration(colorName, JColor.color(
|
||||||
|
(float) color.getRed(), (float) color.getGreen(), (float) color.getBlue(), (float) color.getOpacity()).getColorHexWithAlpha()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void resetColor(String colorName) {
|
||||||
|
Objects.requireNonNull(colorName);
|
||||||
|
removeCustomDeclaration(colorName);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setCustomDeclaration(String property, String value) {
|
private void setCustomDeclaration(String property, String value) {
|
||||||
customCSSDeclarations.put(property, value);
|
customCSSDeclarations.put(property, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void removeCustomDeclaration(String property) {
|
||||||
|
customCSSDeclarations.remove(property);
|
||||||
|
}
|
||||||
|
|
||||||
private void setCustomRule(String selector, String rule) {
|
private void setCustomRule(String selector, String rule) {
|
||||||
customCSSRules.put(selector, rule);
|
customCSSRules.put(selector, rule);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void removeCustomRule(String selector) {
|
||||||
|
customCSSRules.remove(selector);
|
||||||
|
}
|
||||||
|
|
||||||
public void reloadCustomCSS() {
|
public void reloadCustomCSS() {
|
||||||
Objects.requireNonNull(scene);
|
Objects.requireNonNull(scene);
|
||||||
StringBuilder css = new StringBuilder();
|
StringBuilder css = new StringBuilder();
|
||||||
@ -159,12 +192,14 @@ public final class ThemeManager {
|
|||||||
"data:text/css;base64," + Base64.getEncoder().encodeToString(css.toString().getBytes(UTF_8))
|
"data:text/css;base64," + Base64.getEncoder().encodeToString(css.toString().getBytes(UTF_8))
|
||||||
);
|
);
|
||||||
scene.getRoot().pseudoClassStateChanged(USER_CUSTOM, true);
|
scene.getRoot().pseudoClassStateChanged(USER_CUSTOM, true);
|
||||||
|
notifyEventListeners(EventType.CUSTOM_CSS_CHANGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void resetCustomCSS() {
|
public void resetCustomCSS() {
|
||||||
customCSSDeclarations.clear();
|
customCSSDeclarations.clear();
|
||||||
customCSSRules.clear();
|
customCSSRules.clear();
|
||||||
scene.getRoot().pseudoClassStateChanged(USER_CUSTOM, false);
|
scene.getRoot().pseudoClassStateChanged(USER_CUSTOM, false);
|
||||||
|
notifyEventListeners(EventType.CUSTOM_CSS_CHANGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public HighlightJSTheme getMatchingHighlightJSTheme(Theme theme) {
|
public HighlightJSTheme getMatchingHighlightJSTheme(Theme theme) {
|
||||||
@ -174,6 +209,11 @@ public final class ThemeManager {
|
|||||||
return theme.isDarkMode() ? HighlightJSTheme.githubDark() : HighlightJSTheme.githubLight();
|
return theme.isDarkMode() ? HighlightJSTheme.githubDark() : HighlightJSTheme.githubLight();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void notifyEventListeners(EventType eventType) {
|
||||||
|
var e = new ThemeEvent(eventType);
|
||||||
|
eventListeners.forEach(l -> l.accept(e));
|
||||||
|
}
|
||||||
|
|
||||||
@SafeVarargs
|
@SafeVarargs
|
||||||
private <T> Set<T> merge(T first, T... arr) {
|
private <T> Set<T> merge(T first, T... arr) {
|
||||||
var set = new LinkedHashSet<T>();
|
var set = new LinkedHashSet<T>();
|
||||||
|
@ -126,12 +126,14 @@ public class JColorUtils {
|
|||||||
validateHexSingle(green);
|
validateHexSingle(green);
|
||||||
validateHexSingle(blue);
|
validateHexSingle(blue);
|
||||||
StringBuilder color = new StringBuilder("#");
|
StringBuilder color = new StringBuilder("#");
|
||||||
if (alpha != null) {
|
|
||||||
color.append(expandShorthandHexSingle(alpha));
|
|
||||||
}
|
|
||||||
color.append(expandShorthandHexSingle(red));
|
color.append(expandShorthandHexSingle(red));
|
||||||
color.append(expandShorthandHexSingle(green));
|
color.append(expandShorthandHexSingle(green));
|
||||||
color.append(expandShorthandHexSingle(blue));
|
color.append(expandShorthandHexSingle(blue));
|
||||||
|
// alpha must be at the end of the string
|
||||||
|
// not at the start, like it was originally
|
||||||
|
if (alpha != null) {
|
||||||
|
color.append(expandShorthandHexSingle(alpha));
|
||||||
|
}
|
||||||
return color.toString();
|
return color.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -897,4 +899,4 @@ public class JColorUtils {
|
|||||||
fgColor.getBlue(),
|
fgColor.getBlue(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user