Display contrast checker in overlay dialog
This commit is contained in:
parent
3ab95551f3
commit
9b0b0bf44c
@ -109,12 +109,6 @@
|
||||
<directory>src/main/java/atlantafx/sampler/page</directory>
|
||||
<targetPath>atlantafx/sampler/page</targetPath>
|
||||
<filtering>false</filtering>
|
||||
<excludes>
|
||||
<exclude>**/AbstractPage.java</exclude>
|
||||
<exclude>**/CodeViewer.java</exclude>
|
||||
<exclude>**/Page.java</exclude>
|
||||
<exclude>**/SampleBlock.java</exclude>
|
||||
</excludes>
|
||||
</resource>
|
||||
<!-- copy icons -->
|
||||
<resource>
|
||||
|
@ -1,61 +1,14 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
package atlantafx.sampler.layout;
|
||||
|
||||
import atlantafx.sampler.page.Page;
|
||||
import atlantafx.sampler.page.components.OverviewPage;
|
||||
import javafx.animation.FadeTransition;
|
||||
import javafx.application.Platform;
|
||||
import javafx.scene.layout.BorderPane;
|
||||
import javafx.scene.layout.HBox;
|
||||
import javafx.scene.layout.StackPane;
|
||||
import javafx.util.Duration;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import static javafx.scene.layout.Priority.ALWAYS;
|
||||
|
||||
public class ApplicationWindow extends BorderPane {
|
||||
public class ApplicationWindow extends StackPane {
|
||||
|
||||
public ApplicationWindow() {
|
||||
var sidebar = new Sidebar();
|
||||
sidebar.setMinWidth(200);
|
||||
|
||||
final var pageContainer = new StackPane();
|
||||
HBox.setHgrow(pageContainer, ALWAYS);
|
||||
|
||||
sidebar.setOnSelect(pageClass -> {
|
||||
try {
|
||||
final Page prevPage = (!pageContainer.getChildren().isEmpty() && pageContainer.getChildren().get(0) instanceof Page page) ? page : null;
|
||||
final Page nextPage = pageClass.getDeclaredConstructor().newInstance();
|
||||
|
||||
// startup, no animation
|
||||
if (getScene() == null) {
|
||||
pageContainer.getChildren().add(nextPage.getView());
|
||||
return;
|
||||
}
|
||||
|
||||
Objects.requireNonNull(prevPage);
|
||||
|
||||
// reset previous page, e.g. to free resources
|
||||
prevPage.reset();
|
||||
|
||||
// animate switching between pages
|
||||
pageContainer.getChildren().add(nextPage.getView());
|
||||
FadeTransition transition = new FadeTransition(Duration.millis(300), nextPage.getView());
|
||||
transition.setFromValue(0.0);
|
||||
transition.setToValue(1.0);
|
||||
transition.setOnFinished(t -> pageContainer.getChildren().remove(prevPage.getView()));
|
||||
transition.play();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
|
||||
// ~
|
||||
setLeft(sidebar);
|
||||
setCenter(pageContainer);
|
||||
|
||||
sidebar.select(OverviewPage.class);
|
||||
Platform.runLater(sidebar::requestFocus);
|
||||
getChildren().setAll(
|
||||
new Overlay(),
|
||||
new MainLayer()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,66 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
package atlantafx.sampler.layout;
|
||||
|
||||
import atlantafx.sampler.page.Page;
|
||||
import atlantafx.sampler.page.components.OverviewPage;
|
||||
import javafx.animation.FadeTransition;
|
||||
import javafx.application.Platform;
|
||||
import javafx.scene.layout.BorderPane;
|
||||
import javafx.scene.layout.HBox;
|
||||
import javafx.scene.layout.StackPane;
|
||||
import javafx.util.Duration;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import static javafx.scene.layout.Priority.ALWAYS;
|
||||
|
||||
class MainLayer extends BorderPane {
|
||||
|
||||
public MainLayer() {
|
||||
super();
|
||||
createView();
|
||||
}
|
||||
|
||||
private void createView() {
|
||||
var sidebar = new Sidebar();
|
||||
sidebar.setMinWidth(200);
|
||||
|
||||
final var pageContainer = new StackPane();
|
||||
HBox.setHgrow(pageContainer, ALWAYS);
|
||||
|
||||
sidebar.setOnSelect(pageClass -> {
|
||||
try {
|
||||
final Page prevPage = (!pageContainer.getChildren().isEmpty() && pageContainer.getChildren().get(0) instanceof Page page) ? page : null;
|
||||
final Page nextPage = pageClass.getDeclaredConstructor().newInstance();
|
||||
|
||||
// startup, no animation
|
||||
if (getScene() == null) {
|
||||
pageContainer.getChildren().add(nextPage.getView());
|
||||
return;
|
||||
}
|
||||
|
||||
Objects.requireNonNull(prevPage);
|
||||
|
||||
// reset previous page, e.g. to free resources
|
||||
prevPage.reset();
|
||||
|
||||
// animate switching between pages
|
||||
pageContainer.getChildren().add(nextPage.getView());
|
||||
FadeTransition transition = new FadeTransition(Duration.millis(300), nextPage.getView());
|
||||
transition.setFromValue(0.0);
|
||||
transition.setToValue(1.0);
|
||||
transition.setOnFinished(t -> pageContainer.getChildren().remove(prevPage.getView()));
|
||||
transition.play();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
|
||||
// ~
|
||||
setLeft(sidebar);
|
||||
setCenter(pageContainer);
|
||||
|
||||
sidebar.select(OverviewPage.class);
|
||||
Platform.runLater(sidebar::requestFocus);
|
||||
}
|
||||
}
|
156
sampler/src/main/java/atlantafx/sampler/layout/Overlay.java
Normal file
156
sampler/src/main/java/atlantafx/sampler/layout/Overlay.java
Normal file
@ -0,0 +1,156 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
package atlantafx.sampler.layout;
|
||||
|
||||
import atlantafx.sampler.util.Animations;
|
||||
import atlantafx.sampler.util.Containers;
|
||||
import atlantafx.sampler.util.NodeUtils;
|
||||
import javafx.animation.Timeline;
|
||||
import javafx.beans.property.ReadOnlyBooleanProperty;
|
||||
import javafx.beans.property.ReadOnlyBooleanWrapper;
|
||||
import javafx.event.Event;
|
||||
import javafx.geometry.HPos;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.control.ScrollPane;
|
||||
import javafx.scene.input.KeyCode;
|
||||
import javafx.scene.input.KeyEvent;
|
||||
import javafx.scene.input.MouseButton;
|
||||
import javafx.scene.layout.AnchorPane;
|
||||
import javafx.scene.layout.Pane;
|
||||
import javafx.scene.layout.StackPane;
|
||||
import javafx.util.Duration;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class Overlay extends StackPane {
|
||||
|
||||
public static final String STYLE_CLASS = "overlay";
|
||||
|
||||
private ScrollPane scrollPane;
|
||||
private AnchorPane edgeContentWrapper;
|
||||
private StackPane centerContentWrapper;
|
||||
|
||||
private final ReadOnlyBooleanWrapper onFrontProperty = new ReadOnlyBooleanWrapper(false);
|
||||
private final Timeline fadeInTransition = Animations.fadeIn(this, Duration.millis(100));
|
||||
private final Timeline fadeOutTransition = Animations.fadeOut(this, Duration.millis(200));
|
||||
|
||||
private HPos currentContentPos;
|
||||
|
||||
public Overlay() {
|
||||
createView();
|
||||
}
|
||||
|
||||
private void createView() {
|
||||
edgeContentWrapper = new AnchorPane();
|
||||
edgeContentWrapper.getStyleClass().add("scrollable-content");
|
||||
|
||||
centerContentWrapper = new StackPane();
|
||||
centerContentWrapper.getStyleClass().add("scrollable-content");
|
||||
centerContentWrapper.setAlignment(Pos.CENTER);
|
||||
|
||||
scrollPane = new ScrollPane();
|
||||
Containers.setScrollConstraints(scrollPane,
|
||||
ScrollPane.ScrollBarPolicy.AS_NEEDED, true,
|
||||
ScrollPane.ScrollBarPolicy.NEVER, true
|
||||
);
|
||||
scrollPane.setMaxHeight(10_000); // scroll pane won't work without height specified
|
||||
|
||||
// ~
|
||||
|
||||
Consumer<Event> hideAndConsume = e -> {
|
||||
removeContent();
|
||||
toBack();
|
||||
e.consume();
|
||||
};
|
||||
|
||||
// hide overlay by pressing ESC (only works when overlay or one of its children has focus,
|
||||
// that's why we requesting it in the toFront())
|
||||
addEventHandler(KeyEvent.KEY_PRESSED, e -> {
|
||||
if (e.getCode() == KeyCode.ESCAPE) { hideAndConsume.accept(e); }
|
||||
});
|
||||
|
||||
// hide overlay by clicking outside content area
|
||||
setOnMouseClicked(e -> {
|
||||
Pane content = getContent();
|
||||
Node eventSource = e.getPickResult().getIntersectedNode();
|
||||
if (e.getButton() == MouseButton.PRIMARY && content != null && !NodeUtils.isDescendant(content, eventSource)) {
|
||||
hideAndConsume.accept(e);
|
||||
}
|
||||
});
|
||||
|
||||
getChildren().add(scrollPane);
|
||||
getStyleClass().add(STYLE_CLASS);
|
||||
}
|
||||
|
||||
public Pane getContent() {
|
||||
return NodeUtils.getChildByIndex(getContentWrapper(), 0, Pane.class);
|
||||
}
|
||||
|
||||
private Pane getContentWrapper() {
|
||||
return currentContentPos == HPos.CENTER ? centerContentWrapper : edgeContentWrapper;
|
||||
}
|
||||
|
||||
public void setContent(Pane content, HPos pos) {
|
||||
Objects.requireNonNull(content);
|
||||
Objects.requireNonNull(pos);
|
||||
|
||||
// clear old content
|
||||
if (pos != currentContentPos) {
|
||||
removeContent();
|
||||
currentContentPos = pos;
|
||||
}
|
||||
|
||||
switch (pos) {
|
||||
case LEFT -> {
|
||||
edgeContentWrapper.getChildren().setAll(content);
|
||||
Containers.setAnchors(content, new Insets(0, -1, 0, 0));
|
||||
}
|
||||
case RIGHT -> {
|
||||
edgeContentWrapper.getChildren().setAll(content);
|
||||
Containers.setAnchors(content, new Insets(0, 0, 0, -1));
|
||||
}
|
||||
case CENTER -> {
|
||||
centerContentWrapper.getChildren().setAll(content);
|
||||
StackPane.setAlignment(content, Pos.CENTER);
|
||||
}
|
||||
}
|
||||
|
||||
scrollPane.setContent(getContentWrapper());
|
||||
}
|
||||
|
||||
public void removeContent() {
|
||||
getContentWrapper().getChildren().clear();
|
||||
}
|
||||
|
||||
public boolean contains(Pane content) {
|
||||
return content != null &&
|
||||
getContentWrapper().getChildren().size() > 0 &&
|
||||
getContentWrapper().getChildren().get(0).equals(content);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toFront() {
|
||||
if (onFrontProperty.get()) { return; }
|
||||
super.toFront();
|
||||
fadeInTransition.playFromStart();
|
||||
onFrontProperty.set(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toBack() {
|
||||
if (!onFrontProperty.get()) { return; }
|
||||
super.toBack();
|
||||
fadeOutTransition.playFromStart();
|
||||
onFrontProperty.set(false);
|
||||
}
|
||||
|
||||
public ReadOnlyBooleanProperty onFrontProperty() {
|
||||
return onFrontProperty.getReadOnlyProperty();
|
||||
}
|
||||
|
||||
public boolean isOnFront() {
|
||||
return onFrontProperty().get();
|
||||
}
|
||||
}
|
@ -30,7 +30,7 @@ import java.util.function.Consumer;
|
||||
|
||||
import static javafx.scene.layout.Priority.ALWAYS;
|
||||
|
||||
public class Sidebar extends VBox {
|
||||
class Sidebar extends VBox {
|
||||
|
||||
private static final PseudoClass SELECTED = PseudoClass.getPseudoClass("selected");
|
||||
|
||||
|
@ -4,6 +4,7 @@ package atlantafx.sampler.page;
|
||||
import atlantafx.base.controls.Popover;
|
||||
import atlantafx.base.controls.Spacer;
|
||||
import atlantafx.base.theme.Styles;
|
||||
import atlantafx.sampler.layout.Overlay;
|
||||
import atlantafx.sampler.theme.ThemeManager;
|
||||
import javafx.event.ActionEvent;
|
||||
import javafx.event.EventHandler;
|
||||
@ -48,6 +49,7 @@ public abstract class AbstractPage extends BorderPane implements Page {
|
||||
protected StackPane codeViewerWrapper;
|
||||
protected CodeViewer codeViewer;
|
||||
protected VBox userContent;
|
||||
protected Overlay overlay;
|
||||
protected boolean isRendered = false;
|
||||
|
||||
protected AbstractPage() {
|
||||
@ -96,8 +98,8 @@ public abstract class AbstractPage extends BorderPane implements Page {
|
||||
|
||||
var scrollPane = new ScrollPane(userContentWrapper);
|
||||
setScrollConstraints(scrollPane,
|
||||
ScrollPane.ScrollBarPolicy.AS_NEEDED, true,
|
||||
ScrollPane.ScrollBarPolicy.AS_NEEDED, true
|
||||
ScrollPane.ScrollBarPolicy.AS_NEEDED, true,
|
||||
ScrollPane.ScrollBarPolicy.AS_NEEDED, true
|
||||
);
|
||||
scrollPane.setMaxHeight(10_000);
|
||||
|
||||
@ -129,9 +131,16 @@ public abstract class AbstractPage extends BorderPane implements Page {
|
||||
|
||||
// Some properties can only be obtained after node placed
|
||||
// to the scene graph and here is the place do this.
|
||||
protected void onRendered() { }
|
||||
protected void onRendered() {
|
||||
this.overlay = lookupOverlay();
|
||||
}
|
||||
|
||||
private void showThemeConfigPopover() {
|
||||
protected Overlay lookupOverlay() {
|
||||
return getScene() != null && getScene().lookup("." + Overlay.STYLE_CLASS) instanceof Overlay overlay ?
|
||||
overlay : null;
|
||||
}
|
||||
|
||||
protected void showThemeConfigPopover() {
|
||||
if (quickConfigPopover == null) {
|
||||
var content = new QuickConfigMenu();
|
||||
content.setExitHandler(() -> quickConfigPopover.hide());
|
||||
|
113
sampler/src/main/java/atlantafx/sampler/page/OverlayDialog.java
Normal file
113
sampler/src/main/java/atlantafx/sampler/page/OverlayDialog.java
Normal file
@ -0,0 +1,113 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
package atlantafx.sampler.page;
|
||||
|
||||
import atlantafx.base.controls.Spacer;
|
||||
import atlantafx.sampler.util.Containers;
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.layout.HBox;
|
||||
import javafx.scene.layout.Priority;
|
||||
import javafx.scene.layout.Region;
|
||||
import javafx.scene.layout.VBox;
|
||||
import org.kordamp.ikonli.javafx.FontIcon;
|
||||
import org.kordamp.ikonli.material2.Material2AL;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import static atlantafx.base.theme.Styles.*;
|
||||
|
||||
public abstract class OverlayDialog<T extends Region> extends VBox {
|
||||
|
||||
protected static final int CONTENT_CHILD_INDEX = 1;
|
||||
|
||||
protected Label titleLabel;
|
||||
protected Button topCloseBtn;
|
||||
protected HBox headerBox;
|
||||
|
||||
protected Button bottomCloseBtn;
|
||||
protected HBox footerBox;
|
||||
|
||||
protected Runnable onCloseCallback;
|
||||
|
||||
public OverlayDialog() {
|
||||
createView();
|
||||
}
|
||||
|
||||
protected void createView() {
|
||||
titleLabel = new Label();
|
||||
titleLabel.getStyleClass().addAll(TITLE_4, "title");
|
||||
|
||||
topCloseBtn = new Button("", new FontIcon(Material2AL.CLOSE));
|
||||
topCloseBtn.getStyleClass().addAll(BUTTON_ICON, BUTTON_CIRCLE, FLAT, "close-button");
|
||||
topCloseBtn.setOnAction(e -> close());
|
||||
|
||||
headerBox = new HBox(10);
|
||||
headerBox.getStyleClass().add("header");
|
||||
headerBox.setAlignment(Pos.CENTER_LEFT);
|
||||
headerBox.getChildren().setAll(
|
||||
titleLabel,
|
||||
new Spacer(),
|
||||
topCloseBtn
|
||||
);
|
||||
VBox.setVgrow(headerBox, Priority.NEVER);
|
||||
|
||||
bottomCloseBtn = new Button("Close");
|
||||
bottomCloseBtn.getStyleClass().add("form-action");
|
||||
bottomCloseBtn.setOnAction(e -> close());
|
||||
bottomCloseBtn.setCancelButton(true);
|
||||
|
||||
footerBox = new HBox(10);
|
||||
footerBox.getStyleClass().add("footer");
|
||||
footerBox.setAlignment(Pos.CENTER_RIGHT);
|
||||
footerBox.getChildren().setAll(
|
||||
new Spacer(),
|
||||
bottomCloseBtn
|
||||
);
|
||||
VBox.setVgrow(footerBox, Priority.NEVER);
|
||||
|
||||
// IMPORTANT: this guarantees client will use correct width and height
|
||||
Containers.usePrefWidth(this);
|
||||
Containers.usePrefHeight(this);
|
||||
|
||||
// if you're updating this line, update setContent() method as well
|
||||
getChildren().setAll(headerBox, footerBox);
|
||||
|
||||
getStyleClass().add("overlay-dialog");
|
||||
}
|
||||
|
||||
protected void setContent(T content) {
|
||||
Objects.requireNonNull(content);
|
||||
VBox.setVgrow(content, Priority.ALWAYS);
|
||||
|
||||
// content have to be placed exactly between header and footer
|
||||
if (getChildren().size() == 2) {
|
||||
// add new content
|
||||
getChildren().add(CONTENT_CHILD_INDEX, content);
|
||||
} else if (getChildren().size() == 3) {
|
||||
// overwrite existing content
|
||||
getChildren().set(CONTENT_CHILD_INDEX, content);
|
||||
} else {
|
||||
throw new UnsupportedOperationException("Content cannot be placed because of unexpected children size. " +
|
||||
"You should override 'OverlayDialog#setContent()' and place it manually.");
|
||||
}
|
||||
}
|
||||
|
||||
protected void setTitle(String title) {
|
||||
titleLabel.setText(title);
|
||||
}
|
||||
|
||||
public void close() {
|
||||
if (onCloseCallback != null) {
|
||||
onCloseCallback.run();
|
||||
}
|
||||
}
|
||||
|
||||
public Runnable getOnCloseRequest() {
|
||||
return onCloseCallback;
|
||||
}
|
||||
|
||||
public void setOnCloseRequest(Runnable handler) {
|
||||
this.onCloseCallback = handler;
|
||||
}
|
||||
}
|
@ -16,7 +16,7 @@ import org.kordamp.ikonli.material2.Material2AL;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import static atlantafx.sampler.page.general.ColorContrastChecker.*;
|
||||
import static atlantafx.sampler.page.general.ContrastChecker.*;
|
||||
import static atlantafx.sampler.util.JColorUtils.flattenColor;
|
||||
import static atlantafx.sampler.util.JColorUtils.getColorLuminance;
|
||||
|
||||
@ -71,8 +71,8 @@ class ColorBlock extends VBox {
|
||||
if (bgFill == null) { return; }
|
||||
|
||||
toggleHover(true);
|
||||
expandIcon.setFill(
|
||||
getColorLuminance(flattenColor(bgBaseColor.get(), bgFill)) < LUMINANCE_THRESHOLD ? Color.WHITE : Color.BLACK
|
||||
expandIcon.setFill(getColorLuminance(flattenColor(bgBaseColor.get(), bgFill)) < LUMINANCE_THRESHOLD ?
|
||||
Color.WHITE : Color.BLACK
|
||||
);
|
||||
});
|
||||
colorBox.setOnMouseExited(e -> toggleHover(false));
|
||||
|
@ -4,82 +4,42 @@ package atlantafx.sampler.page.general;
|
||||
import atlantafx.base.controls.Spacer;
|
||||
import atlantafx.base.theme.Styles;
|
||||
import javafx.application.Platform;
|
||||
import javafx.beans.property.ReadOnlyBooleanProperty;
|
||||
import javafx.beans.property.ReadOnlyBooleanWrapper;
|
||||
import javafx.beans.property.ReadOnlyObjectProperty;
|
||||
import javafx.beans.property.ReadOnlyObjectWrapper;
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.layout.GridPane;
|
||||
import javafx.scene.layout.HBox;
|
||||
import javafx.scene.layout.Priority;
|
||||
import javafx.scene.layout.VBox;
|
||||
import javafx.scene.paint.Color;
|
||||
import org.kordamp.ikonli.feather.Feather;
|
||||
import org.kordamp.ikonli.javafx.FontIcon;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import java.util.*;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
class ColorPalette extends VBox {
|
||||
|
||||
private Label headerLabel;
|
||||
private Button backBtn;
|
||||
private GridPane colorGrid;
|
||||
private ColorContrastChecker contrastChecker;
|
||||
private VBox contrastCheckerArea;
|
||||
|
||||
private final List<ColorBlock> blocks = new ArrayList<>();
|
||||
private final Consumer<ColorBlock> colorBlockActionHandler = colorBlock -> {
|
||||
ColorContrastChecker c = getOrCreateContrastChecker();
|
||||
c.setValues(colorBlock.getFgColorName(),
|
||||
colorBlock.getFgColor(),
|
||||
colorBlock.getBgColorName(),
|
||||
colorBlock.getBgColor()
|
||||
);
|
||||
|
||||
if (contrastCheckerArea.getChildren().isEmpty()) {
|
||||
contrastCheckerArea.getChildren().setAll(c);
|
||||
}
|
||||
|
||||
showContrastChecker();
|
||||
};
|
||||
|
||||
private final ReadOnlyBooleanWrapper contrastCheckerActive = new ReadOnlyBooleanWrapper(false);
|
||||
private final ReadOnlyObjectWrapper<Color> bgBaseColor = new ReadOnlyObjectWrapper<>(Color.WHITE);
|
||||
private final Consumer<ColorBlock> colorBlockActionHandler;
|
||||
|
||||
public ReadOnlyBooleanProperty contrastCheckerActiveProperty() {
|
||||
return contrastCheckerActive.getReadOnlyProperty();
|
||||
}
|
||||
|
||||
public ColorPalette() {
|
||||
public ColorPalette(Consumer<ColorBlock> blockClickedHandler) {
|
||||
super();
|
||||
|
||||
this.colorBlockActionHandler = Objects.requireNonNull(blockClickedHandler);
|
||||
createView();
|
||||
}
|
||||
|
||||
private void createView() {
|
||||
headerLabel = new Label("Color Palette");
|
||||
var headerLabel = new Label("Color Palette");
|
||||
headerLabel.getStyleClass().add(Styles.TITLE_4);
|
||||
|
||||
backBtn = new Button("Back", new FontIcon(Feather.CHEVRONS_LEFT));
|
||||
backBtn.getStyleClass().add(Styles.FLAT);
|
||||
backBtn.setVisible(false);
|
||||
backBtn.setManaged(false);
|
||||
backBtn.setOnAction(e -> showColorPalette());
|
||||
|
||||
var headerBox = new HBox();
|
||||
headerBox.getChildren().setAll(headerLabel, new Spacer(), backBtn);
|
||||
headerBox.getChildren().setAll(headerLabel, new Spacer());
|
||||
headerBox.setAlignment(Pos.CENTER_LEFT);
|
||||
headerBox.getStyleClass().add("header");
|
||||
|
||||
contrastCheckerArea = new VBox();
|
||||
contrastCheckerArea.getStyleClass().add("contrast-checker-area");
|
||||
|
||||
colorGrid = colorGrid();
|
||||
var colorGrid = colorGrid();
|
||||
|
||||
backgroundProperty().addListener((obs, old, val) -> bgBaseColor.set(
|
||||
val != null && !val.getFills().isEmpty() ? (Color) val.getFills().get(0).getFill() : Color.WHITE
|
||||
@ -132,28 +92,6 @@ class ColorPalette extends VBox {
|
||||
return block;
|
||||
}
|
||||
|
||||
private ColorContrastChecker getOrCreateContrastChecker() {
|
||||
if (contrastChecker == null) { contrastChecker = new ColorContrastChecker(bgBaseColor.getReadOnlyProperty()); }
|
||||
VBox.setVgrow(contrastChecker, Priority.ALWAYS);
|
||||
return contrastChecker;
|
||||
}
|
||||
|
||||
private void showColorPalette() {
|
||||
headerLabel.setText("Color Palette");
|
||||
backBtn.setVisible(false);
|
||||
backBtn.setManaged(false);
|
||||
getChildren().set(1, colorGrid);
|
||||
contrastCheckerActive.set(false);
|
||||
}
|
||||
|
||||
private void showContrastChecker() {
|
||||
headerLabel.setText("Contrast Checker");
|
||||
backBtn.setVisible(true);
|
||||
backBtn.setManaged(true);
|
||||
getChildren().set(1, contrastCheckerArea);
|
||||
contrastCheckerActive.set(true);
|
||||
}
|
||||
|
||||
// To calculate contrast ratio, we have to obtain all components colors first.
|
||||
// Unfortunately, JavaFX doesn't provide an API to observe when stylesheet changes has been applied.
|
||||
// The timer is introduced to defer widget update to a time when scene changes supposedly will be finished.
|
||||
@ -165,4 +103,8 @@ class ColorPalette extends VBox {
|
||||
}
|
||||
}, delay.toMillis());
|
||||
}
|
||||
|
||||
public ReadOnlyObjectProperty<Color> bgBaseColorProperty() {
|
||||
return bgBaseColor.getReadOnlyProperty();
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
package atlantafx.sampler.page.general;
|
||||
|
||||
import atlantafx.base.controls.CustomTextField;
|
||||
import atlantafx.base.controls.Spacer;
|
||||
import atlantafx.base.theme.Styles;
|
||||
import atlantafx.sampler.theme.ThemeManager;
|
||||
import atlantafx.sampler.util.JColor;
|
||||
@ -33,16 +34,15 @@ import org.kordamp.ikonli.material2.Material2AL;
|
||||
import java.util.Objects;
|
||||
|
||||
import static atlantafx.sampler.page.general.ColorBlock.validateColorName;
|
||||
import static atlantafx.sampler.util.JColorUtils.*;
|
||||
import static atlantafx.sampler.util.JColorUtils.flattenColor;
|
||||
import static atlantafx.sampler.util.JColorUtils.getColorLuminance;
|
||||
|
||||
// Inspired by the https://colourcontrast.cc/
|
||||
public class ColorContrastChecker extends GridPane {
|
||||
public class ContrastChecker extends GridPane {
|
||||
|
||||
static final PseudoClass PASSED = PseudoClass.getPseudoClass("passed");
|
||||
static final float[] COLOR_WHITE = new float[] { 255f, 255f, 255f, 1f };
|
||||
static final float[] COLOR_BLACK = new float[] { 0f, 0f, 0f, 1f };
|
||||
static final double CONTRAST_RATIO_THRESHOLD = 1.5;
|
||||
static final double LUMINANCE_THRESHOLD = 0.55;
|
||||
public static final double CONTRAST_RATIO_THRESHOLD = 1.5;
|
||||
public static final double LUMINANCE_THRESHOLD = 0.55;
|
||||
public static final PseudoClass PASSED = PseudoClass.getPseudoClass("passed");
|
||||
|
||||
private static final int SLIDER_WIDTH = 300;
|
||||
|
||||
@ -65,7 +65,7 @@ public class ColorContrastChecker extends GridPane {
|
||||
private Slider fgLightnessSlider;
|
||||
private Slider fgAlphaSlider;
|
||||
|
||||
public ColorContrastChecker(ReadOnlyObjectProperty<Color> bgBaseColor) {
|
||||
public ContrastChecker(ReadOnlyObjectProperty<Color> bgBaseColor) {
|
||||
super();
|
||||
|
||||
this.bgBaseColor = bgBaseColor;
|
||||
@ -98,6 +98,19 @@ public class ColorContrastChecker extends GridPane {
|
||||
|
||||
public Color getFgColor() { return fgColor.colorProperty().get(); }
|
||||
|
||||
public ReadOnlyObjectProperty<Color> bgColorProperty() { return bgColor.colorProperty(); }
|
||||
|
||||
public ReadOnlyObjectProperty<Color> fgColorProperty() { return fgColor.colorProperty(); }
|
||||
|
||||
// Returns fg color that guaranteed to be visible on the current bg.
|
||||
public Color getSafeFgColor() {
|
||||
if (contrastRatio.get() <= CONTRAST_RATIO_THRESHOLD) {
|
||||
return getColorLuminance(flattenColor(bgBaseColor.get(), bgColor.getColor())) < LUMINANCE_THRESHOLD ? Color.WHITE : Color.BLACK;
|
||||
} else {
|
||||
return fgColor.getColor();
|
||||
}
|
||||
}
|
||||
|
||||
private void createView() {
|
||||
var textLabel = new Label("Aa");
|
||||
textLabel.getStyleClass().add("text");
|
||||
@ -268,21 +281,22 @@ public class ColorContrastChecker extends GridPane {
|
||||
|
||||
var applyBtn = new Button("Apply");
|
||||
applyBtn.setOnAction(e -> {
|
||||
var tm = ThemeManager.getInstance();
|
||||
var tm = ThemeManager.getInstance();
|
||||
tm.setColor(getBgColorName(), bgColor.getColor());
|
||||
tm.setColor(getFgColorName(), fgColor.getColor());
|
||||
tm.reloadCustomCSS();
|
||||
});
|
||||
|
||||
var controlsBox = new HBox(20, flattenBtn, applyBtn);
|
||||
var controlsBox = new HBox(20, new Spacer(), flattenBtn, applyBtn);
|
||||
controlsBox.setAlignment(Pos.CENTER_LEFT);
|
||||
controlsBox.setPadding(new Insets(10, 0, 0, 0));
|
||||
|
||||
// ~
|
||||
|
||||
getStyleClass().add("contrast-checker");
|
||||
|
||||
// column 0
|
||||
add(fontBox, 0, 0);
|
||||
add(new HBox(fontBox, new Spacer(), wsagBox), 0, 0, REMAINING, 1);
|
||||
add(new Label("Background Color"), 0, 1);
|
||||
add(bgColorNameLabel, 0, 2);
|
||||
add(bgTextField, 0, 3);
|
||||
@ -298,7 +312,6 @@ public class ColorContrastChecker extends GridPane {
|
||||
add(controlsBox, 0, 12, REMAINING, 1);
|
||||
|
||||
// column 1
|
||||
add(wsagBox, 1, 0);
|
||||
add(new Label("Foreground Color"), 1, 1);
|
||||
add(fgColorNameLabel, 1, 2);
|
||||
add(fgTextField, 1, 3);
|
||||
@ -321,40 +334,14 @@ public class ColorContrastChecker extends GridPane {
|
||||
}
|
||||
|
||||
private void updateStyle() {
|
||||
float[] bg = bgColor.getRGBAColor();
|
||||
float[] fg = fgColor.getRGBAColor();
|
||||
|
||||
// use fallback color if contrast ratio is too low
|
||||
if (contrastRatio.get() <= CONTRAST_RATIO_THRESHOLD) {
|
||||
fg = getColorLuminance(flattenColor(bgBaseColor.get(), bgColor.getColor())) < LUMINANCE_THRESHOLD ?
|
||||
COLOR_WHITE :
|
||||
COLOR_BLACK;
|
||||
}
|
||||
|
||||
// flat colors are necessary for controls that use reverse styling (bg color over fg color),
|
||||
// it won't be readable if we not remove transparency first
|
||||
double[] bgFlat = flattenColor(bgBaseColor.get(), bgColor.getColor());
|
||||
double[] fgFlat = flattenColor(bgBaseColor.get(), fgColor.getColor());
|
||||
|
||||
var style = String.format("-color-contrast-checker-bg:rgba(%.0f,%.0f,%.0f,%.2f);" +
|
||||
"-color-contrast-checker-fg:rgba(%.0f,%.0f,%.0f,%.2f);" +
|
||||
"-color-contrast-checker-bg-flat:%s;" +
|
||||
"-color-contrast-checker-fg-flat:%s;",
|
||||
bg[0], bg[1], bg[2], bg[3],
|
||||
fg[0], fg[1], fg[2], fg[3],
|
||||
JColor.color((float) bgFlat[0], (float) bgFlat[1], (float) bgFlat[2]).getColorHex(),
|
||||
JColor.color((float) fgFlat[0], (float) fgFlat[1], (float) fgFlat[2]).getColorHex()
|
||||
);
|
||||
|
||||
setStyle(style);
|
||||
setStyle(String.format("-color-contrast-checker-bg:%s;-color-contrast-checker-fg:%s;",
|
||||
JColorUtils.toHexWithAlpha(bgColor.getColor()),
|
||||
JColorUtils.toHexWithAlpha(getSafeFgColor())
|
||||
));
|
||||
}
|
||||
|
||||
private void setBackground(Color color) {
|
||||
float[] hsl = JColorUtils.toHSL(
|
||||
(float) color.getRed(),
|
||||
(float) color.getGreen(),
|
||||
(float) color.getBlue()
|
||||
);
|
||||
float[] hsl = JColorUtils.toHSL(color);
|
||||
bgHueSlider.setValue(hsl[0]);
|
||||
bgSaturationSlider.setValue(hsl[1]);
|
||||
bgLightnessSlider.setValue(hsl[2]);
|
||||
@ -362,11 +349,7 @@ public class ColorContrastChecker extends GridPane {
|
||||
}
|
||||
|
||||
private void setForeground(Color color) {
|
||||
float[] hsl = JColorUtils.toHSL(
|
||||
(float) color.getRed(),
|
||||
(float) color.getGreen(),
|
||||
(float) color.getBlue()
|
||||
);
|
||||
float[] hsl = JColorUtils.toHSL(color);
|
||||
fgHueSlider.setValue(hsl[0]);
|
||||
fgSaturationSlider.setValue(hsl[1]);
|
||||
fgLightnessSlider.setValue(hsl[2]);
|
||||
@ -412,7 +395,7 @@ public class ColorContrastChecker extends GridPane {
|
||||
static double getContrastRatioOpacityAware(Color bgColor, Color fgColor, Color bgBaseColor) {
|
||||
double luminance1 = getColorLuminance(flattenColor(bgBaseColor, bgColor));
|
||||
double luminance2 = getColorLuminance(flattenColor(bgBaseColor, fgColor));
|
||||
return getContrastRatio(luminance1, luminance2);
|
||||
return JColorUtils.getContrastRatio(luminance1, luminance2);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
@ -435,11 +418,7 @@ public class ColorContrastChecker extends GridPane {
|
||||
}
|
||||
|
||||
public void setColor(Color color) {
|
||||
float[] hsl = JColorUtils.toHSL(
|
||||
(float) color.getRed(),
|
||||
(float) color.getGreen(),
|
||||
(float) color.getBlue()
|
||||
);
|
||||
float[] hsl = JColorUtils.toHSL(color);
|
||||
values.setAll(hsl[0], hsl[1], hsl[2], (float) color.getOpacity());
|
||||
}
|
||||
|
||||
@ -490,17 +469,6 @@ public class ColorContrastChecker extends GridPane {
|
||||
};
|
||||
}
|
||||
|
||||
public float[] getRGBAColor() {
|
||||
float[] hsl = new float[] { getHue(), getSaturation(), getLightness() };
|
||||
var color = JColor.color(hsl, getAlpha());
|
||||
return new float[] {
|
||||
color.getRed(),
|
||||
color.getGreen(),
|
||||
color.getBlue(),
|
||||
getAlpha()
|
||||
};
|
||||
}
|
||||
|
||||
public String getColorHexWithAlpha() {
|
||||
float[] hsl = new float[] { getHue(), getSaturation(), getLightness() };
|
||||
return JColor.color(hsl, getAlpha()).getColorHexWithAlpha();
|
@ -0,0 +1,36 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
package atlantafx.sampler.page.general;
|
||||
|
||||
import atlantafx.sampler.page.OverlayDialog;
|
||||
import atlantafx.sampler.util.JColorUtils;
|
||||
import atlantafx.sampler.util.NodeUtils;
|
||||
import javafx.beans.property.ReadOnlyObjectProperty;
|
||||
import javafx.scene.paint.Color;
|
||||
|
||||
class ContrastCheckerDialog extends OverlayDialog<ContrastChecker> {
|
||||
|
||||
private final ContrastChecker contrastChecker;
|
||||
|
||||
public ContrastCheckerDialog(ReadOnlyObjectProperty<Color> bgBaseColor) {
|
||||
this.contrastChecker = new ContrastChecker(bgBaseColor);
|
||||
|
||||
contrastChecker.bgColorProperty().addListener((obs, old, val) -> updateStyle());
|
||||
contrastChecker.fgColorProperty().addListener((obs, old, val) -> updateStyle());
|
||||
|
||||
getStyleClass().add("contrast-checker-dialog");
|
||||
setTitle("Contrast Checker");
|
||||
setContent(contrastChecker);
|
||||
NodeUtils.toggleVisibility(footerBox, false);
|
||||
}
|
||||
|
||||
private void updateStyle() {
|
||||
setStyle(String.format("-color-dialog-bg:%s;-color-dialog-fg:%s;",
|
||||
JColorUtils.toHexWithAlpha(contrastChecker.getBgColor()),
|
||||
JColorUtils.toHexWithAlpha(contrastChecker.getSafeFgColor())
|
||||
));
|
||||
}
|
||||
|
||||
public ContrastChecker getContent() {
|
||||
return contrastChecker;
|
||||
}
|
||||
}
|
@ -5,6 +5,8 @@ import atlantafx.base.theme.Theme;
|
||||
import atlantafx.sampler.page.AbstractPage;
|
||||
import atlantafx.sampler.theme.ThemeEvent.EventType;
|
||||
import atlantafx.sampler.theme.ThemeManager;
|
||||
import atlantafx.sampler.util.NodeUtils;
|
||||
import javafx.geometry.HPos;
|
||||
import javafx.scene.control.ChoiceBox;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.layout.GridPane;
|
||||
@ -12,12 +14,26 @@ import javafx.util.StringConverter;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class ThemePage extends AbstractPage {
|
||||
|
||||
public static final String NAME = "Theme";
|
||||
|
||||
private final ColorPalette colorPalette = new ColorPalette();
|
||||
private final Consumer<ColorBlock> colorBlockActionHandler = colorBlock -> {
|
||||
ContrastCheckerDialog dialog = getOrCreateContrastCheckerDialog();
|
||||
dialog.getContent().setValues(colorBlock.getFgColorName(),
|
||||
colorBlock.getFgColor(),
|
||||
colorBlock.getBgColorName(),
|
||||
colorBlock.getBgColor()
|
||||
);
|
||||
overlay.setContent(dialog, HPos.CENTER);
|
||||
overlay.toFront();
|
||||
};
|
||||
|
||||
private final ColorPalette colorPalette = new ColorPalette(colorBlockActionHandler);
|
||||
|
||||
private ContrastCheckerDialog contrastCheckerDialog;
|
||||
|
||||
@Override
|
||||
public String getName() { return NAME; }
|
||||
@ -46,16 +62,13 @@ public class ThemePage extends AbstractPage {
|
||||
);
|
||||
// if you want to enable quick menu don't forget that
|
||||
// theme selection choice box have to be updated accordingly
|
||||
quickConfigBtn.setVisible(false);
|
||||
quickConfigBtn.setManaged(false);
|
||||
sourceCodeToggleBtn.setVisible(false);
|
||||
sourceCodeToggleBtn.setManaged(false);
|
||||
NodeUtils.toggleVisibility(quickConfigBtn, false);
|
||||
NodeUtils.toggleVisibility(sourceCodeToggleBtn, false);
|
||||
}
|
||||
|
||||
private GridPane optionsGrid() {
|
||||
ChoiceBox<Theme> themeSelector = themeSelector();
|
||||
themeSelector.setPrefWidth(200);
|
||||
themeSelector.disableProperty().bind(colorPalette.contrastCheckerActiveProperty());
|
||||
|
||||
// ~
|
||||
|
||||
@ -106,4 +119,17 @@ public class ThemePage extends AbstractPage {
|
||||
|
||||
return selector;
|
||||
}
|
||||
|
||||
private ContrastCheckerDialog getOrCreateContrastCheckerDialog() {
|
||||
if (contrastCheckerDialog == null) {
|
||||
contrastCheckerDialog = new ContrastCheckerDialog(colorPalette.bgBaseColorProperty());
|
||||
}
|
||||
|
||||
contrastCheckerDialog.setOnCloseRequest(() -> {
|
||||
overlay.removeContent();
|
||||
overlay.toBack();
|
||||
});
|
||||
|
||||
return contrastCheckerDialog;
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import atlantafx.sampler.page.AbstractPage;
|
||||
import atlantafx.sampler.page.SampleBlock;
|
||||
import atlantafx.sampler.theme.ThemeEvent.EventType;
|
||||
import atlantafx.sampler.theme.ThemeManager;
|
||||
import atlantafx.sampler.util.NodeUtils;
|
||||
import javafx.application.Platform;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.geometry.Pos;
|
||||
@ -74,10 +75,8 @@ public class TypographyPage extends AbstractPage {
|
||||
);
|
||||
// if you want to enable quick menu don't forget that
|
||||
// font size spinner value have to be updated accordingly
|
||||
quickConfigBtn.setVisible(false);
|
||||
quickConfigBtn.setManaged(false);
|
||||
sourceCodeToggleBtn.setVisible(false);
|
||||
sourceCodeToggleBtn.setManaged(false);
|
||||
NodeUtils.toggleVisibility(quickConfigBtn, false);
|
||||
NodeUtils.toggleVisibility(sourceCodeToggleBtn, false);
|
||||
}
|
||||
|
||||
private ComboBox<String> fontFamilyChooser() {
|
||||
|
63
sampler/src/main/java/atlantafx/sampler/util/Animations.java
Normal file
63
sampler/src/main/java/atlantafx/sampler/util/Animations.java
Normal file
@ -0,0 +1,63 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
package atlantafx.sampler.util;
|
||||
|
||||
import javafx.animation.Interpolator;
|
||||
import javafx.animation.KeyFrame;
|
||||
import javafx.animation.KeyValue;
|
||||
import javafx.animation.Timeline;
|
||||
import javafx.scene.Node;
|
||||
import javafx.util.Duration;
|
||||
|
||||
public final class Animations {
|
||||
|
||||
public static final Interpolator EASE = Interpolator.SPLINE(0.25, 0.1, 0.25, 1);
|
||||
|
||||
public static Timeline fadeIn(Node node, Duration duration) {
|
||||
return new Timeline(
|
||||
new KeyFrame(Duration.millis(0), new KeyValue(node.opacityProperty(), 0, EASE)),
|
||||
new KeyFrame(duration, new KeyValue(node.opacityProperty(), 1, EASE))
|
||||
);
|
||||
}
|
||||
|
||||
public static Timeline fadeOut(Node node, Duration duration) {
|
||||
return new Timeline(
|
||||
new KeyFrame(Duration.millis(0), new KeyValue(node.opacityProperty(), 1, EASE)),
|
||||
new KeyFrame(duration, new KeyValue(node.opacityProperty(), 0, EASE))
|
||||
);
|
||||
}
|
||||
|
||||
public static Timeline zoomIn(Node node, Duration duration) {
|
||||
return new Timeline(
|
||||
new KeyFrame(Duration.millis(0),
|
||||
new KeyValue(node.opacityProperty(), 0, EASE),
|
||||
new KeyValue(node.scaleXProperty(), 0.3, EASE),
|
||||
new KeyValue(node.scaleYProperty(), 0.3, EASE),
|
||||
new KeyValue(node.scaleZProperty(), 0.3, EASE)
|
||||
),
|
||||
new KeyFrame(duration,
|
||||
new KeyValue(node.opacityProperty(), 1, EASE),
|
||||
new KeyValue(node.scaleXProperty(), 1, EASE),
|
||||
new KeyValue(node.scaleYProperty(), 1, EASE),
|
||||
new KeyValue(node.scaleZProperty(), 1, EASE)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public static Timeline zoomOut(Node node, Duration duration) {
|
||||
return new Timeline(
|
||||
new KeyFrame(Duration.millis(0),
|
||||
new KeyValue(node.opacityProperty(), 1, EASE),
|
||||
new KeyValue(node.scaleXProperty(), 1, EASE),
|
||||
new KeyValue(node.scaleYProperty(), 1, EASE),
|
||||
new KeyValue(node.scaleZProperty(), 0.3, EASE)
|
||||
),
|
||||
new KeyFrame(duration.divide(2),
|
||||
new KeyValue(node.opacityProperty(), 0, EASE),
|
||||
new KeyValue(node.scaleXProperty(), 0.3, EASE),
|
||||
new KeyValue(node.scaleYProperty(), 0.3, EASE),
|
||||
new KeyValue(node.scaleZProperty(), 0.3, EASE)
|
||||
),
|
||||
new KeyFrame(duration, new KeyValue(node.opacityProperty(), 0, EASE))
|
||||
);
|
||||
}
|
||||
}
|
@ -7,6 +7,7 @@ import javafx.scene.control.ScrollPane;
|
||||
import javafx.scene.layout.AnchorPane;
|
||||
import javafx.scene.layout.ColumnConstraints;
|
||||
import javafx.scene.layout.Priority;
|
||||
import javafx.scene.layout.Region;
|
||||
|
||||
import static javafx.scene.layout.Region.USE_COMPUTED_SIZE;
|
||||
import static javafx.scene.layout.Region.USE_PREF_SIZE;
|
||||
@ -41,4 +42,14 @@ public final class Containers {
|
||||
constraints.setHgrow(hgrow);
|
||||
return constraints;
|
||||
}
|
||||
|
||||
public static void usePrefWidth(Region region) {
|
||||
region.setMinWidth(USE_PREF_SIZE);
|
||||
region.setMaxWidth(USE_PREF_SIZE);
|
||||
}
|
||||
|
||||
public static void usePrefHeight(Region region) {
|
||||
region.setMinHeight(USE_PREF_SIZE);
|
||||
region.setMaxHeight(USE_PREF_SIZE);
|
||||
}
|
||||
}
|
||||
|
@ -51,10 +51,9 @@ public class JColorUtils {
|
||||
/**
|
||||
* Convert the hex color values to a hex color
|
||||
*
|
||||
* @param red red hex color in format RR or R
|
||||
* @param red red hex color in format RR or R
|
||||
* @param green green hex color in format GG or G
|
||||
* @param blue blue hex color in format BB or B
|
||||
*
|
||||
* @param blue blue hex color in format BB or B
|
||||
* @return hex color in format #RRGGBB
|
||||
*/
|
||||
public static String toColor(String red, String green, String blue) {
|
||||
@ -64,10 +63,9 @@ public class JColorUtils {
|
||||
/**
|
||||
* Convert the hex color values to a hex color, shorthanded when possible
|
||||
*
|
||||
* @param red red hex color in format RR or R
|
||||
* @param red red hex color in format RR or R
|
||||
* @param green green hex color in format GG or G
|
||||
* @param blue blue hex color in format BB or B
|
||||
*
|
||||
* @param blue blue hex color in format BB or B
|
||||
* @return hex color in format #RGB or #RRGGBB
|
||||
*/
|
||||
public static String toColorShorthand(String red, String green,
|
||||
@ -79,10 +77,9 @@ public class JColorUtils {
|
||||
* Convert the hex color values to a hex color including an opaque alpha
|
||||
* value of FF
|
||||
*
|
||||
* @param red red hex color in format RR or R
|
||||
* @param red red hex color in format RR or R
|
||||
* @param green green hex color in format GG or G
|
||||
* @param blue blue hex color in format BB or B
|
||||
*
|
||||
* @param blue blue hex color in format BB or B
|
||||
* @return hex color in format #AARRGGBB
|
||||
*/
|
||||
public static String toColorWithAlpha(String red, String green,
|
||||
@ -99,10 +96,9 @@ public class JColorUtils {
|
||||
* Convert the hex color values to a hex color including an opaque alpha
|
||||
* value of FF or F, shorthanded when possible
|
||||
*
|
||||
* @param red red hex color in format RR or R
|
||||
* @param red red hex color in format RR or R
|
||||
* @param green green hex color in format GG or G
|
||||
* @param blue blue hex color in format BB or B
|
||||
*
|
||||
* @param blue blue hex color in format BB or B
|
||||
* @return hex color in format #ARGB or #AARRGGBB
|
||||
*/
|
||||
public static String toColorShorthandWithAlpha(String red, String green,
|
||||
@ -113,11 +109,10 @@ public class JColorUtils {
|
||||
/**
|
||||
* Convert the hex color values to a hex color
|
||||
*
|
||||
* @param red red hex color in format RR or R
|
||||
* @param red red hex color in format RR or R
|
||||
* @param green green hex color in format GG or G
|
||||
* @param blue blue hex color in format BB or B
|
||||
* @param blue blue hex color in format BB or B
|
||||
* @param alpha alpha hex color in format AA or A, null to not include alpha
|
||||
*
|
||||
* @return hex color in format #AARRGGBB or #RRGGBB
|
||||
*/
|
||||
public static String toColorWithAlpha(String red, String green, String blue,
|
||||
@ -140,11 +135,10 @@ public class JColorUtils {
|
||||
/**
|
||||
* Convert the hex color values to a hex color, shorthanded when possible
|
||||
*
|
||||
* @param red red hex color in format RR or R
|
||||
* @param red red hex color in format RR or R
|
||||
* @param green green hex color in format GG or G
|
||||
* @param blue blue hex color in format BB or B
|
||||
* @param blue blue hex color in format BB or B
|
||||
* @param alpha alpha hex color in format AA or A, null to not include alpha
|
||||
*
|
||||
* @return hex color in format #ARGB, #RGB, #AARRGGBB, or #RRGGBB
|
||||
*/
|
||||
public static String toColorShorthandWithAlpha(String red, String green,
|
||||
@ -155,10 +149,9 @@ public class JColorUtils {
|
||||
/**
|
||||
* Convert the RGB values to a color integer
|
||||
*
|
||||
* @param red red integer color inclusively between 0 and 255
|
||||
* @param red red integer color inclusively between 0 and 255
|
||||
* @param green green integer color inclusively between 0 and 255
|
||||
* @param blue blue integer color inclusively between 0 and 255
|
||||
*
|
||||
* @param blue blue integer color inclusively between 0 and 255
|
||||
* @return integer color
|
||||
*/
|
||||
public static int toColor(int red, int green, int blue) {
|
||||
@ -169,10 +162,9 @@ public class JColorUtils {
|
||||
* Convert the RGB values to a color integer including an opaque alpha value
|
||||
* of 255
|
||||
*
|
||||
* @param red red integer color inclusively between 0 and 255
|
||||
* @param red red integer color inclusively between 0 and 255
|
||||
* @param green green integer color inclusively between 0 and 255
|
||||
* @param blue blue integer color inclusively between 0 and 255
|
||||
*
|
||||
* @param blue blue integer color inclusively between 0 and 255
|
||||
* @return integer color
|
||||
*/
|
||||
public static int toColorWithAlpha(int red, int green, int blue) {
|
||||
@ -182,12 +174,11 @@ public class JColorUtils {
|
||||
/**
|
||||
* Convert the RGBA values to a color integer
|
||||
*
|
||||
* @param red red integer color inclusively between 0 and 255
|
||||
* @param red red integer color inclusively between 0 and 255
|
||||
* @param green green integer color inclusively between 0 and 255
|
||||
* @param blue blue integer color inclusively between 0 and 255
|
||||
* @param blue blue integer color inclusively between 0 and 255
|
||||
* @param alpha alpha integer color inclusively between 0 and 255, -1 to not
|
||||
* include alpha
|
||||
*
|
||||
* include alpha
|
||||
* @return integer color
|
||||
*/
|
||||
public static int toColorWithAlpha(int red, int green, int blue,
|
||||
@ -207,7 +198,6 @@ public class JColorUtils {
|
||||
* Convert the RGB integer to a hex single color
|
||||
*
|
||||
* @param color integer color inclusively between 0 and 255
|
||||
*
|
||||
* @return hex single color in format FF
|
||||
*/
|
||||
public static String toHex(int color) {
|
||||
@ -223,7 +213,6 @@ public class JColorUtils {
|
||||
* Convert the arithmetic RGB float to a hex single color
|
||||
*
|
||||
* @param color float color inclusively between 0.0 and 1.0
|
||||
*
|
||||
* @return hex single color in format FF
|
||||
*/
|
||||
public static String toHex(float color) {
|
||||
@ -234,7 +223,6 @@ public class JColorUtils {
|
||||
* Convert the hex single color to a RGB integer
|
||||
*
|
||||
* @param color hex single color in format FF or F
|
||||
*
|
||||
* @return integer color inclusively between 0 and 255
|
||||
*/
|
||||
public static int toRGB(String color) {
|
||||
@ -249,7 +237,6 @@ public class JColorUtils {
|
||||
* Convert the arithmetic RGB float to a RGB integer
|
||||
*
|
||||
* @param color float color inclusively between 0.0 and 1.0
|
||||
*
|
||||
* @return integer color inclusively between 0 and 255
|
||||
*/
|
||||
public static int toRGB(float color) {
|
||||
@ -261,7 +248,6 @@ public class JColorUtils {
|
||||
* Convert the hex single color to an arithmetic RGB float
|
||||
*
|
||||
* @param color hex single color in format FF or F
|
||||
*
|
||||
* @return float color inclusively between 0.0 and 1.0
|
||||
*/
|
||||
public static float toArithmeticRGB(String color) {
|
||||
@ -272,7 +258,6 @@ public class JColorUtils {
|
||||
* Convert the RGB integer to an arithmetic RGB float
|
||||
*
|
||||
* @param color integer color inclusively between 0 and 255
|
||||
*
|
||||
* @return float color inclusively between 0.0 and 1.0
|
||||
*/
|
||||
public static float toArithmeticRGB(int color) {
|
||||
@ -284,10 +269,9 @@ public class JColorUtils {
|
||||
* Convert red, green, and blue arithmetic values to HSL (hue, saturation,
|
||||
* lightness) values
|
||||
*
|
||||
* @param red red color inclusively between 0.0 and 1.0
|
||||
* @param red red color inclusively between 0.0 and 1.0
|
||||
* @param green green color inclusively between 0.0 and 1.0
|
||||
* @param blue blue color inclusively between 0.0 and 1.0
|
||||
*
|
||||
* @param blue blue color inclusively between 0.0 and 1.0
|
||||
* @return HSL array where: 0 = hue, 1 = saturation, 2 = lightness
|
||||
*/
|
||||
public static float[] toHSL(float red, float green, float blue) {
|
||||
@ -339,25 +323,23 @@ public class JColorUtils {
|
||||
* Convert red, green, and blue integer values to HSL (hue, saturation,
|
||||
* lightness) values
|
||||
*
|
||||
* @param red red color inclusively between 0 and 255
|
||||
* @param red red color inclusively between 0 and 255
|
||||
* @param green green color inclusively between 0 and 255
|
||||
* @param blue blue color inclusively between 0 and 255
|
||||
*
|
||||
* @param blue blue color inclusively between 0 and 255
|
||||
* @return HSL array where: 0 = hue, 1 = saturation, 2 = lightness
|
||||
*/
|
||||
public static float[] toHSL(int red, int green, int blue) {
|
||||
return toHSL(toArithmeticRGB(red), toArithmeticRGB(green),
|
||||
toArithmeticRGB(blue));
|
||||
toArithmeticRGB(blue));
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert HSL (hue, saturation, and lightness) values to RGB arithmetic
|
||||
* values
|
||||
*
|
||||
* @param hue hue value inclusively between 0.0 and 360.0
|
||||
* @param hue hue value inclusively between 0.0 and 360.0
|
||||
* @param saturation saturation inclusively between 0.0 and 1.0
|
||||
* @param lightness lightness inclusively between 0.0 and 1.0
|
||||
*
|
||||
* @param lightness lightness inclusively between 0.0 and 1.0
|
||||
* @return arithmetic RGB array where: 0 = red, 1 = green, 2 = blue
|
||||
*/
|
||||
public static float[] toArithmeticRGB(float hue, float saturation,
|
||||
@ -386,10 +368,9 @@ public class JColorUtils {
|
||||
/**
|
||||
* Convert HSL (hue, saturation, and lightness) values to RGB integer values
|
||||
*
|
||||
* @param hue hue value inclusively between 0.0 and 360.0
|
||||
* @param hue hue value inclusively between 0.0 and 360.0
|
||||
* @param saturation saturation inclusively between 0.0 and 1.0
|
||||
* @param lightness lightness inclusively between 0.0 and 1.0
|
||||
*
|
||||
* @param lightness lightness inclusively between 0.0 and 1.0
|
||||
* @return RGB integer array where: 0 = red, 1 = green, 2 = blue
|
||||
*/
|
||||
public static int[] toRGB(float hue, float saturation, float lightness) {
|
||||
@ -400,10 +381,9 @@ public class JColorUtils {
|
||||
/**
|
||||
* HSL convert helper method
|
||||
*
|
||||
* @param t1 t1
|
||||
* @param t2 t2
|
||||
* @param t1 t1
|
||||
* @param t2 t2
|
||||
* @param hue hue
|
||||
*
|
||||
* @return arithmetic RGB value
|
||||
*/
|
||||
private static float hslConvert(float t1, float t2, float hue) {
|
||||
@ -430,7 +410,6 @@ public class JColorUtils {
|
||||
* Get the hex red color from the hex string
|
||||
*
|
||||
* @param hex hex color
|
||||
*
|
||||
* @return hex red color in format RR
|
||||
*/
|
||||
public static String getRed(String hex) {
|
||||
@ -441,7 +420,6 @@ public class JColorUtils {
|
||||
* Get the hex green color from the hex string
|
||||
*
|
||||
* @param hex hex color
|
||||
*
|
||||
* @return hex green color in format GG
|
||||
*/
|
||||
public static String getGreen(String hex) {
|
||||
@ -452,7 +430,6 @@ public class JColorUtils {
|
||||
* Get the hex blue color from the hex string
|
||||
*
|
||||
* @param hex hex color
|
||||
*
|
||||
* @return hex blue color in format BB
|
||||
*/
|
||||
public static String getBlue(String hex) {
|
||||
@ -463,7 +440,6 @@ public class JColorUtils {
|
||||
* Get the hex alpha color from the hex string if it exists
|
||||
*
|
||||
* @param hex hex color
|
||||
*
|
||||
* @return hex alpha color in format AA or null
|
||||
*/
|
||||
public static String getAlpha(String hex) {
|
||||
@ -473,9 +449,8 @@ public class JColorUtils {
|
||||
/**
|
||||
* Get the hex single color
|
||||
*
|
||||
* @param hex hex color
|
||||
* @param hex hex color
|
||||
* @param colorIndex red=0, green=1, blue=2, alpha=-1
|
||||
*
|
||||
* @return hex single color in format FF or null
|
||||
*/
|
||||
private static String getHexSingle(String hex, int colorIndex) {
|
||||
@ -512,7 +487,6 @@ public class JColorUtils {
|
||||
* Get the red color from color integer
|
||||
*
|
||||
* @param color color integer
|
||||
*
|
||||
* @return red color
|
||||
*/
|
||||
public static int getRed(int color) {
|
||||
@ -523,7 +497,6 @@ public class JColorUtils {
|
||||
* Get the green color from color integer
|
||||
*
|
||||
* @param color color integer
|
||||
*
|
||||
* @return green color
|
||||
*/
|
||||
public static int getGreen(int color) {
|
||||
@ -534,7 +507,6 @@ public class JColorUtils {
|
||||
* Get the blue color from color integer
|
||||
*
|
||||
* @param color color integer
|
||||
*
|
||||
* @return blue color
|
||||
*/
|
||||
public static int getBlue(int color) {
|
||||
@ -545,7 +517,6 @@ public class JColorUtils {
|
||||
* Get the alpha color from color integer
|
||||
*
|
||||
* @param color color integer
|
||||
*
|
||||
* @return alpha color
|
||||
*/
|
||||
public static int getAlpha(int color) {
|
||||
@ -556,7 +527,6 @@ public class JColorUtils {
|
||||
* Shorthand the hex color if possible
|
||||
*
|
||||
* @param color hex color
|
||||
*
|
||||
* @return shorthand hex color or original value
|
||||
*/
|
||||
public static String shorthandHex(String color) {
|
||||
@ -589,7 +559,6 @@ public class JColorUtils {
|
||||
* Expand the hex if it is in shorthand
|
||||
*
|
||||
* @param color hex color
|
||||
*
|
||||
* @return expanded hex color or original value
|
||||
*/
|
||||
public static String expandShorthandHex(String color) {
|
||||
@ -615,7 +584,6 @@ public class JColorUtils {
|
||||
* Shorthand the hex single color if possible
|
||||
*
|
||||
* @param color hex single color
|
||||
*
|
||||
* @return shorthand hex color or original value
|
||||
*/
|
||||
public static String shorthandHexSingle(String color) {
|
||||
@ -632,7 +600,6 @@ public class JColorUtils {
|
||||
* Expand the hex single if it is in shorthand
|
||||
*
|
||||
* @param color hex single color
|
||||
*
|
||||
* @return expanded hex color or original value
|
||||
*/
|
||||
public static String expandShorthandHexSingle(String color) {
|
||||
@ -647,7 +614,6 @@ public class JColorUtils {
|
||||
* Check if the hex color value is valid
|
||||
*
|
||||
* @param color hex color
|
||||
*
|
||||
* @return true if valid
|
||||
*/
|
||||
public static boolean isValidHex(String color) {
|
||||
@ -671,7 +637,6 @@ public class JColorUtils {
|
||||
* Check if the hex single color value is valid
|
||||
*
|
||||
* @param color hex single color
|
||||
*
|
||||
* @return true if valid
|
||||
*/
|
||||
public static boolean isValidHexSingle(String color) {
|
||||
@ -694,7 +659,6 @@ public class JColorUtils {
|
||||
* Check if the RGB integer color is valid, inclusively between 0 and 255
|
||||
*
|
||||
* @param color decimal color
|
||||
*
|
||||
* @return true if valid
|
||||
*/
|
||||
public static boolean isValidRGB(int color) {
|
||||
@ -719,7 +683,6 @@ public class JColorUtils {
|
||||
* and 1.0
|
||||
*
|
||||
* @param color decimal color
|
||||
*
|
||||
* @return true if valid
|
||||
*/
|
||||
public static boolean isValidArithmeticRGB(float color) {
|
||||
@ -745,7 +708,6 @@ public class JColorUtils {
|
||||
* 360.0
|
||||
*
|
||||
* @param hue hue value
|
||||
*
|
||||
* @return true if valid
|
||||
*/
|
||||
public static boolean isValidHue(float hue) {
|
||||
@ -770,7 +732,6 @@ public class JColorUtils {
|
||||
* and 1.0
|
||||
*
|
||||
* @param saturation saturation value
|
||||
*
|
||||
* @return true if valid
|
||||
*/
|
||||
public static boolean isValidSaturation(float saturation) {
|
||||
@ -796,7 +757,6 @@ public class JColorUtils {
|
||||
* and 1.0
|
||||
*
|
||||
* @param lightness lightness value
|
||||
*
|
||||
* @return true if valid
|
||||
*/
|
||||
public static boolean isValidLightness(float lightness) {
|
||||
@ -899,4 +859,21 @@ public class JColorUtils {
|
||||
fgColor.getBlue(),
|
||||
};
|
||||
}
|
||||
|
||||
public static float[] toHSL(Color color) {
|
||||
return JColorUtils.toHSL(
|
||||
(float) color.getRed(),
|
||||
(float) color.getGreen(),
|
||||
(float) color.getBlue()
|
||||
);
|
||||
}
|
||||
|
||||
public static String toHexWithAlpha(Color color) {
|
||||
return JColor.color(
|
||||
(float) color.getRed(),
|
||||
(float) color.getGreen(),
|
||||
(float) color.getBlue(),
|
||||
(float) color.getOpacity()
|
||||
).getColorHexShorthandWithAlpha();
|
||||
}
|
||||
}
|
||||
|
38
sampler/src/main/java/atlantafx/sampler/util/NodeUtils.java
Normal file
38
sampler/src/main/java/atlantafx/sampler/util/NodeUtils.java
Normal file
@ -0,0 +1,38 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
package atlantafx.sampler.util;
|
||||
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.Parent;
|
||||
import javafx.scene.input.MouseButton;
|
||||
import javafx.scene.input.MouseEvent;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public final class NodeUtils {
|
||||
|
||||
public static void toggleVisibility(Node node, boolean on) {
|
||||
node.setVisible(on);
|
||||
node.setManaged(on);
|
||||
}
|
||||
|
||||
public static boolean isDoubleClick(MouseEvent e) {
|
||||
return e.getButton().equals(MouseButton.PRIMARY) && e.getClickCount() == 2;
|
||||
}
|
||||
|
||||
public static <T> T getChildByIndex(Parent parent, int index, Class<T> contentType) {
|
||||
List<Node> children = parent.getChildrenUnmodifiable();
|
||||
if (index < 0 || index >= children.size()) { return null; }
|
||||
Node node = children.get(index);
|
||||
return contentType.isInstance(node) ? contentType.cast(node) : null;
|
||||
}
|
||||
|
||||
public static boolean isDescendant(Node ancestor, Node descendant) {
|
||||
if (ancestor == null) { return true; }
|
||||
|
||||
while (descendant != null) {
|
||||
if (descendant == ancestor) { return true; }
|
||||
descendant = descendant.getParent();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
@ -3,3 +3,4 @@
|
||||
@use "sidebar";
|
||||
@use "page";
|
||||
@use "components";
|
||||
@use "overlay";
|
@ -0,0 +1,31 @@
|
||||
.overlay {
|
||||
-fx-background-color: transparent;
|
||||
|
||||
>.scroll-pane {
|
||||
>.viewport {
|
||||
>* {
|
||||
>.scrollable-content {
|
||||
-fx-background-color: rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.overlay-dialog {
|
||||
-fx-background-color: -color-bg-default;
|
||||
-fx-background-radius: 5px;
|
||||
-fx-border-radius: 5px;
|
||||
-fx-border-width: 1px;
|
||||
-fx-border-color: -color-border-default;
|
||||
|
||||
>.header {
|
||||
-fx-padding: 10px 5px 5px 20px;
|
||||
}
|
||||
|
||||
>.footer {
|
||||
-fx-border-width: 1 0 0 0;
|
||||
-fx-border-color: -color-border-default;
|
||||
-fx-padding: 10;
|
||||
}
|
||||
}
|
@ -45,88 +45,4 @@ $color-wsag-fg: white;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
>.contrast-checker-area {
|
||||
-fx-padding: 0 0 0 -20px;
|
||||
|
||||
>.contrast-checker {
|
||||
-fx-background-color: -color-contrast-checker-bg;
|
||||
-fx-hgap: 40px;
|
||||
-fx-vgap: 20px;
|
||||
-fx-padding: 20px 20px 40px 20px;
|
||||
|
||||
.label {
|
||||
-fx-text-fill: -color-contrast-checker-fg;
|
||||
}
|
||||
|
||||
.text-field {
|
||||
-fx-background-insets: 0;
|
||||
-fx-background-color: transparent;
|
||||
-fx-background-radius: 0;
|
||||
-fx-text-fill: -color-contrast-checker-fg;
|
||||
-fx-border-color: -color-contrast-checker-fg;
|
||||
-fx-border-width: 0 0 1 0;
|
||||
}
|
||||
|
||||
.button {
|
||||
-color-button-bg: -color-contrast-checker-fg-flat;
|
||||
-color-button-fg: -color-contrast-checker-bg-flat;
|
||||
-color-button-border: -color-contrast-checker-bg-flat;
|
||||
|
||||
-color-button-bg-hover: -color-contrast-checker-fg-flat;
|
||||
-color-button-fg-hover: -color-contrast-checker-bg-flat;
|
||||
-color-button-border-hover: -color-contrast-checker-bg-flat;
|
||||
|
||||
-color-button-bg-focused: -color-contrast-checker-fg-flat;
|
||||
-color-button-fg-focused: -color-contrast-checker-bg-flat;
|
||||
-color-button-border-focused: -color-contrast-checker-bg-flat;
|
||||
|
||||
-color-button-bg-pressed: -color-contrast-checker-bg-flat;
|
||||
-color-button-fg-pressed: -color-contrast-checker-fg-flat;
|
||||
-color-button-border-pressed: -color-contrast-checker-fg-flat;
|
||||
}
|
||||
|
||||
.ikonli-font-icon {
|
||||
-fx-icon-color: -color-contrast-checker-fg;
|
||||
-fx-fill: -color-contrast-checker-fg;
|
||||
}
|
||||
|
||||
.slider {
|
||||
>.thumb {
|
||||
-fx-background-color: -color-contrast-checker-fg;
|
||||
}
|
||||
|
||||
>.track {
|
||||
-fx-background-color: transparent, -color-contrast-checker-fg;
|
||||
-fx-opacity: 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
.font-box {
|
||||
>.text {
|
||||
-fx-font-size: 4em;
|
||||
}
|
||||
|
||||
>.ratio {
|
||||
-fx-font-size: 2em;
|
||||
}
|
||||
}
|
||||
|
||||
>.wsag-box>*>.wsag-label {
|
||||
-fx-padding: 0.5em 1em 0.5em 1em;
|
||||
-fx-background-color: $color-wsag-bg-failed;
|
||||
-fx-background-radius: 6px;
|
||||
-fx-text-fill: $color-wsag-fg;
|
||||
|
||||
&:passed {
|
||||
-fx-background-color: $color-wsag-bg-passed;
|
||||
}
|
||||
|
||||
>.ikonli-font-icon {
|
||||
-fx-fill: $color-wsag-fg;
|
||||
-fx-icon-color: $color-wsag-fg;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,112 @@
|
||||
@use "color-palette" as palette;
|
||||
|
||||
.contrast-checker {
|
||||
-fx-background-color: -color-contrast-checker-bg;
|
||||
-fx-hgap: 40px;
|
||||
-fx-vgap: 20px;
|
||||
-fx-padding: 20px;
|
||||
|
||||
.label {
|
||||
-fx-text-fill: -color-contrast-checker-fg;
|
||||
}
|
||||
|
||||
.text-field {
|
||||
-fx-background-insets: 0;
|
||||
-fx-background-color: transparent;
|
||||
-fx-background-radius: 0;
|
||||
-fx-text-fill: -color-contrast-checker-fg;
|
||||
-fx-border-color: -color-contrast-checker-fg;
|
||||
-fx-border-width: 0 0 1 0;
|
||||
}
|
||||
|
||||
.button {
|
||||
-color-button-bg: transparent;
|
||||
-color-button-fg: -color-contrast-checker-fg;
|
||||
-color-button-border: transparent;
|
||||
|
||||
-color-button-bg-hover: transparent;
|
||||
-color-button-fg-hover: -color-contrast-checker-fg;
|
||||
-color-button-border-hover: transparent;
|
||||
|
||||
-color-button-bg-focused: transparent;
|
||||
-color-button-fg-focused: -color-contrast-checker-fg;
|
||||
-color-button-border-focused: transparent;
|
||||
|
||||
-color-button-bg-pressed: transparent;
|
||||
-color-button-fg-pressed: -color-contrast-checker-fg;
|
||||
-color-button-border-pressed: transparent;
|
||||
|
||||
-fx-border-width: 1px;
|
||||
-fx-border-color: -color-contrast-checker-fg;
|
||||
-fx-border-radius: 4px;
|
||||
|
||||
&:armed,
|
||||
&:focused:armed {
|
||||
-fx-border-color: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
.ikonli-font-icon {
|
||||
-fx-icon-color: -color-contrast-checker-fg;
|
||||
-fx-fill: -color-contrast-checker-fg;
|
||||
}
|
||||
|
||||
.slider {
|
||||
>.thumb {
|
||||
-fx-background-color: -color-contrast-checker-fg;
|
||||
}
|
||||
|
||||
>.track {
|
||||
-fx-background-color: transparent, -color-contrast-checker-fg;
|
||||
-fx-opacity: 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
.font-box {
|
||||
-fx-padding: 0 40px 0 0;
|
||||
|
||||
>.text {
|
||||
-fx-font-size: 4em;
|
||||
}
|
||||
|
||||
>.ratio {
|
||||
-fx-font-size: 2em;
|
||||
}
|
||||
}
|
||||
|
||||
.wsag-box>*>.wsag-label {
|
||||
-fx-padding: 0.5em 1em 0.5em 1em;
|
||||
-fx-background-color: palette.$color-wsag-bg-failed;
|
||||
-fx-background-radius: 4px;
|
||||
-fx-text-fill: palette.$color-wsag-fg;
|
||||
|
||||
&:passed {
|
||||
-fx-background-color: palette.$color-wsag-bg-passed;
|
||||
}
|
||||
|
||||
>.ikonli-font-icon {
|
||||
-fx-fill: palette.$color-wsag-fg;
|
||||
-fx-icon-color: palette.$color-wsag-fg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.contrast-checker-dialog {
|
||||
-color-dialog-bg: white;
|
||||
-color-dialog-fg: black;
|
||||
|
||||
>.header {
|
||||
-fx-background-color: -color-dialog-bg;
|
||||
|
||||
>.title {
|
||||
-fx-text-fill: -color-dialog-fg;
|
||||
}
|
||||
|
||||
>.close-button {
|
||||
-color-button-fg: -color-dialog-fg;
|
||||
-color-button-bg-hover: derive(-color-dialog-bg, 10%);
|
||||
}
|
||||
}
|
||||
|
||||
-fx-border-color: -color-dialog-bg;
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
@use "color-palette";
|
||||
@use "contrast-checker";
|
||||
@use "quick-config-menu";
|
Loading…
Reference in New Issue
Block a user