Improve control and widget samples
This commit is contained in:
parent
1c4c6a5232
commit
cc3cd4a391
@ -137,6 +137,7 @@ public class RingProgressIndicatorSkin extends SkinBase<RingProgressIndicator> {
|
|||||||
protected void toggleIndeterminate() {
|
protected void toggleIndeterminate() {
|
||||||
var indeterminate = getSkinnable().isIndeterminate();
|
var indeterminate = getSkinnable().isIndeterminate();
|
||||||
progressLabel.setManaged(!indeterminate);
|
progressLabel.setManaged(!indeterminate);
|
||||||
|
progressLabel.setVisible(!indeterminate);
|
||||||
|
|
||||||
if (indeterminate) {
|
if (indeterminate) {
|
||||||
if (getSkinnable().isVisible()) {
|
if (getSkinnable().isVisible()) {
|
||||||
|
@ -75,6 +75,7 @@ public final class Styles {
|
|||||||
public static final String TEXT_OBLIQUE = "text-oblique";
|
public static final String TEXT_OBLIQUE = "text-oblique";
|
||||||
public static final String TEXT_STRIKETHROUGH = "text-strikethrough";
|
public static final String TEXT_STRIKETHROUGH = "text-strikethrough";
|
||||||
public static final String TEXT_UNDERLINED = "text-underlined";
|
public static final String TEXT_UNDERLINED = "text-underlined";
|
||||||
|
public static final String TEXT_MUTED = "text-muted";
|
||||||
|
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
|
|
||||||
|
@ -0,0 +1,158 @@
|
|||||||
|
/* SPDX-License-Identifier: MIT */
|
||||||
|
package atlantafx.base.util;
|
||||||
|
|
||||||
|
import javafx.application.Platform;
|
||||||
|
import javafx.beans.property.BooleanProperty;
|
||||||
|
import javafx.beans.property.ReadOnlyStringProperty;
|
||||||
|
import javafx.beans.property.ReadOnlyStringWrapper;
|
||||||
|
import javafx.beans.property.SimpleBooleanProperty;
|
||||||
|
import javafx.scene.control.TextField;
|
||||||
|
import javafx.scene.control.TextFormatter;
|
||||||
|
import javafx.util.StringConverter;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.function.UnaryOperator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An alternative for the {@link javafx.scene.control.PasswordField}.
|
||||||
|
* The formatter (un)masks text field content based on boolean property.
|
||||||
|
*/
|
||||||
|
public class PasswordTextFormatter extends TextFormatter<String> {
|
||||||
|
|
||||||
|
public static final char BULLET = '\u2731'; // heavy asterisk
|
||||||
|
|
||||||
|
protected PasswordTextFormatter(StringConverter<String> valueConverter,
|
||||||
|
UnaryOperator<Change> filter,
|
||||||
|
TextField textField,
|
||||||
|
char bullet) {
|
||||||
|
super(valueConverter, null, filter);
|
||||||
|
|
||||||
|
Objects.requireNonNull(valueConverter);
|
||||||
|
Objects.requireNonNull(filter);
|
||||||
|
Objects.requireNonNull(textField);
|
||||||
|
|
||||||
|
PasswordFilter passwordFilter = (PasswordFilter) getFilter();
|
||||||
|
passwordFilter.setBullet(bullet);
|
||||||
|
passwordFilter.setInitialText(textField.getText());
|
||||||
|
|
||||||
|
revealPasswordProperty().addListener((obs, old, val) -> {
|
||||||
|
// Force text field update, because converter is only called on focus
|
||||||
|
// events by default. Don't use commitValue() here because caret position
|
||||||
|
// won't be correct due to #javafx-bug (https://bugs.openjdk.org/browse/JDK-8248914).
|
||||||
|
if (val == null) { return; }
|
||||||
|
textField.setText(passwordProperty().get());
|
||||||
|
});
|
||||||
|
|
||||||
|
// force text field update on scene show
|
||||||
|
Platform.runLater(textField::commitValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ReadOnlyStringProperty passwordProperty() {
|
||||||
|
return ((PasswordFilter) getFilter()).password.getReadOnlyProperty();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPassword() {
|
||||||
|
return passwordProperty().get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public BooleanProperty revealPasswordProperty() {
|
||||||
|
return ((PasswordFilter) getFilter()).revealPassword;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isRevealPassword() {
|
||||||
|
return revealPasswordProperty().get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRevealPassword(boolean reveal) {
|
||||||
|
revealPasswordProperty().set(reveal);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Life would be easier if TextFormatter had the default constructor.
|
||||||
|
public static PasswordTextFormatter create(TextField textField, char bullet) {
|
||||||
|
var filter = new PasswordFilter();
|
||||||
|
var converter = new PasswordStringConverter(filter);
|
||||||
|
return new PasswordTextFormatter(converter, filter, textField, bullet);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PasswordTextFormatter create(TextField textField) {
|
||||||
|
return create(textField, BULLET);
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
protected static class PasswordStringConverter extends StringConverter<String> {
|
||||||
|
|
||||||
|
protected final PasswordFilter filter;
|
||||||
|
|
||||||
|
public PasswordStringConverter(PasswordFilter filter) {
|
||||||
|
this.filter = filter;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString(String s) {
|
||||||
|
if (s == null) { return ""; }
|
||||||
|
return filter.revealPassword.get() ? filter.password.get() : filter.maskText(s.length());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String fromString(String string) {
|
||||||
|
return filter.password.get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static class PasswordFilter implements UnaryOperator<Change> {
|
||||||
|
|
||||||
|
protected final ReadOnlyStringWrapper password = new ReadOnlyStringWrapper("");
|
||||||
|
protected final BooleanProperty revealPassword = new SimpleBooleanProperty(false);
|
||||||
|
protected final StringBuilder sb = new StringBuilder();
|
||||||
|
protected char bullet = PasswordTextFormatter.BULLET;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TextFormatter.Change apply(TextFormatter.Change change) {
|
||||||
|
// Since we are using setText() to force text field to update (see above),
|
||||||
|
// we should protect internal password value from changing when `revealPassword`is toggled.
|
||||||
|
if (Objects.equals(change.getText(), sb.toString())) {
|
||||||
|
if (!revealPassword.get()) {
|
||||||
|
change.setText(maskText(change.getText().length()));
|
||||||
|
}
|
||||||
|
return change;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (change.isReplaced()) {
|
||||||
|
sb.replace(change.getRangeStart(), change.getRangeEnd(), change.getText());
|
||||||
|
} else if (change.isDeleted()) {
|
||||||
|
sb.delete(change.getRangeStart(), change.getRangeEnd());
|
||||||
|
} else if (change.isAdded()) {
|
||||||
|
if (change.getRangeStart() == sb.length()) {
|
||||||
|
sb.append(change.getText());
|
||||||
|
} else {
|
||||||
|
sb.insert(change.getRangeStart(), change.getText());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// mask new text, so it won't appear on user input
|
||||||
|
if (change.getText() != null && !change.getText().isEmpty() && !revealPassword.get()) {
|
||||||
|
change.setText(maskText(change.getText().length()));
|
||||||
|
}
|
||||||
|
|
||||||
|
password.set(sb.toString());
|
||||||
|
|
||||||
|
return change;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void setBullet(char bullet) {
|
||||||
|
this.bullet = bullet;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String maskText(int length) {
|
||||||
|
return String.valueOf(bullet).repeat(length);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void setInitialText(String text) {
|
||||||
|
if (text != null && !text.isEmpty()) {
|
||||||
|
sb.append(text);
|
||||||
|
password.set(sb.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -119,11 +119,11 @@ class MainLayer extends BorderPane {
|
|||||||
|
|
||||||
// animate switching between pages
|
// animate switching between pages
|
||||||
subLayerPane.getChildren().add(nextPage.getView());
|
subLayerPane.getChildren().add(nextPage.getView());
|
||||||
|
subLayerPane.getChildren().remove(prevPage.getView());
|
||||||
var transition = new FadeTransition(Duration.millis(PAGE_TRANSITION_DURATION), nextPage.getView());
|
var transition = new FadeTransition(Duration.millis(PAGE_TRANSITION_DURATION), nextPage.getView());
|
||||||
transition.setFromValue(0.0);
|
transition.setFromValue(0.0);
|
||||||
transition.setToValue(1.0);
|
transition.setToValue(1.0);
|
||||||
transition.setOnFinished(t -> {
|
transition.setOnFinished(t -> {
|
||||||
subLayerPane.getChildren().remove(prevPage.getView());
|
|
||||||
if (nextPage instanceof Pane nextPane) { nextPane.toFront(); }
|
if (nextPage instanceof Pane nextPane) { nextPane.toFront(); }
|
||||||
});
|
});
|
||||||
transition.play();
|
transition.play();
|
||||||
|
@ -2,8 +2,10 @@
|
|||||||
package atlantafx.sampler.page.components;
|
package atlantafx.sampler.page.components;
|
||||||
|
|
||||||
import atlantafx.base.controls.CustomTextField;
|
import atlantafx.base.controls.CustomTextField;
|
||||||
|
import atlantafx.base.util.PasswordTextFormatter;
|
||||||
import atlantafx.sampler.page.AbstractPage;
|
import atlantafx.sampler.page.AbstractPage;
|
||||||
import atlantafx.sampler.page.SampleBlock;
|
import atlantafx.sampler.page.SampleBlock;
|
||||||
|
import javafx.scene.Cursor;
|
||||||
import javafx.scene.layout.FlowPane;
|
import javafx.scene.layout.FlowPane;
|
||||||
import org.kordamp.ikonli.feather.Feather;
|
import org.kordamp.ikonli.feather.Feather;
|
||||||
import org.kordamp.ikonli.javafx.FontIcon;
|
import org.kordamp.ikonli.javafx.FontIcon;
|
||||||
@ -27,47 +29,71 @@ public class CustomTextFieldPage extends AbstractPage {
|
|||||||
rightIconSample(),
|
rightIconSample(),
|
||||||
bothIconsSample(),
|
bothIconsSample(),
|
||||||
successSample(),
|
successSample(),
|
||||||
dangerSample()
|
dangerSample(),
|
||||||
|
passwordSample()
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
private SampleBlock leftIconSample() {
|
private SampleBlock leftIconSample() {
|
||||||
var leftIconField = new CustomTextField();
|
var tf = new CustomTextField();
|
||||||
leftIconField.setPromptText("Prompt text");
|
tf.setPromptText("Prompt text");
|
||||||
leftIconField.setRight(new FontIcon(Feather.X));
|
tf.setRight(new FontIcon(Feather.X));
|
||||||
leftIconField.setPrefWidth(PREF_WIDTH);
|
tf.setPrefWidth(PREF_WIDTH);
|
||||||
return new SampleBlock("Left", leftIconField);
|
return new SampleBlock("Left", tf);
|
||||||
}
|
}
|
||||||
|
|
||||||
private SampleBlock rightIconSample() {
|
private SampleBlock rightIconSample() {
|
||||||
var rightIconField = new CustomTextField();
|
var tf = new CustomTextField();
|
||||||
rightIconField.setPromptText("Prompt text");
|
tf.setPromptText("Prompt text");
|
||||||
rightIconField.setLeft(new FontIcon(Feather.MAP_PIN));
|
tf.setLeft(new FontIcon(Feather.MAP_PIN));
|
||||||
rightIconField.setPrefWidth(PREF_WIDTH);
|
tf.setPrefWidth(PREF_WIDTH);
|
||||||
return new SampleBlock("Right", rightIconField);
|
return new SampleBlock("Right", tf);
|
||||||
}
|
}
|
||||||
|
|
||||||
private SampleBlock bothIconsSample() {
|
private SampleBlock bothIconsSample() {
|
||||||
var bothIconField = new CustomTextField("Text");
|
var tf = new CustomTextField("Text");
|
||||||
bothIconField.setLeft(new FontIcon(Feather.MAP_PIN));
|
tf.setLeft(new FontIcon(Feather.MAP_PIN));
|
||||||
bothIconField.setRight(new FontIcon(Feather.X));
|
tf.setRight(new FontIcon(Feather.X));
|
||||||
bothIconField.setPrefWidth(PREF_WIDTH);
|
tf.setPrefWidth(PREF_WIDTH);
|
||||||
return new SampleBlock("Both Sides", bothIconField);
|
return new SampleBlock("Both Sides", tf);
|
||||||
}
|
}
|
||||||
|
|
||||||
private SampleBlock successSample() {
|
private SampleBlock successSample() {
|
||||||
var successField = new CustomTextField("Text");
|
var tf = new CustomTextField("Text");
|
||||||
successField.pseudoClassStateChanged(STATE_SUCCESS, true);
|
tf.pseudoClassStateChanged(STATE_SUCCESS, true);
|
||||||
successField.setRight(new FontIcon(Feather.X));
|
tf.setRight(new FontIcon(Feather.X));
|
||||||
successField.setPrefWidth(PREF_WIDTH);
|
tf.setPrefWidth(PREF_WIDTH);
|
||||||
return new SampleBlock("Success", successField);
|
return new SampleBlock("Success", tf);
|
||||||
}
|
}
|
||||||
|
|
||||||
private SampleBlock dangerSample() {
|
private SampleBlock dangerSample() {
|
||||||
var dangerField = new CustomTextField("Text");
|
var tf = new CustomTextField();
|
||||||
dangerField.pseudoClassStateChanged(STATE_DANGER, true);
|
tf.pseudoClassStateChanged(STATE_DANGER, true);
|
||||||
dangerField.setLeft(new FontIcon(Feather.MAP_PIN));
|
tf.setLeft(new FontIcon(Feather.MAP_PIN));
|
||||||
dangerField.setPrefWidth(PREF_WIDTH);
|
tf.setPrefWidth(PREF_WIDTH);
|
||||||
return new SampleBlock("Danger", dangerField);
|
return new SampleBlock("Danger", tf);
|
||||||
|
}
|
||||||
|
|
||||||
|
private SampleBlock passwordSample() {
|
||||||
|
var tf = new CustomTextField("qwerty");
|
||||||
|
tf.setPrefWidth(PREF_WIDTH);
|
||||||
|
|
||||||
|
var passwordFormatter = PasswordTextFormatter.create(tf);
|
||||||
|
tf.setTextFormatter(passwordFormatter);
|
||||||
|
|
||||||
|
var icon = new FontIcon(Feather.EYE_OFF);
|
||||||
|
icon.setCursor(Cursor.HAND);
|
||||||
|
icon.setOnMouseClicked(e -> {
|
||||||
|
if (passwordFormatter.revealPasswordProperty().get()) {
|
||||||
|
passwordFormatter.revealPasswordProperty().set(false);
|
||||||
|
icon.setIconCode(Feather.EYE_OFF);
|
||||||
|
} else {
|
||||||
|
passwordFormatter.revealPasswordProperty().set(true);
|
||||||
|
icon.setIconCode(Feather.EYE);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
tf.setRight(icon);
|
||||||
|
|
||||||
|
return new SampleBlock("Password", tf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,16 @@
|
|||||||
/* SPDX-License-Identifier: MIT */
|
/* SPDX-License-Identifier: MIT */
|
||||||
package atlantafx.sampler.page.components;
|
package atlantafx.sampler.page.components;
|
||||||
|
|
||||||
|
import atlantafx.base.theme.Styles;
|
||||||
import atlantafx.sampler.page.AbstractPage;
|
import atlantafx.sampler.page.AbstractPage;
|
||||||
import atlantafx.sampler.page.SampleBlock;
|
import atlantafx.sampler.page.SampleBlock;
|
||||||
import javafx.scene.layout.VBox;
|
import javafx.scene.layout.VBox;
|
||||||
|
import javafx.scene.text.Text;
|
||||||
|
import javafx.scene.text.TextFlow;
|
||||||
import javafx.scene.web.HTMLEditor;
|
import javafx.scene.web.HTMLEditor;
|
||||||
|
|
||||||
|
import static atlantafx.sampler.page.SampleBlock.BLOCK_VGAP;
|
||||||
|
|
||||||
public class HTMLEditorPage extends AbstractPage {
|
public class HTMLEditorPage extends AbstractPage {
|
||||||
|
|
||||||
public static final String NAME = "HTMLEditor";
|
public static final String NAME = "HTMLEditor";
|
||||||
@ -21,9 +26,16 @@ public class HTMLEditorPage extends AbstractPage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private SampleBlock editorSample() {
|
private SampleBlock editorSample() {
|
||||||
|
var description = new Text(
|
||||||
|
"HTMLEditor toolbar buttons use images from 'com/sun/javafx/scene/control/skin/modena'. " +
|
||||||
|
"In opposite, since AtlantaFX themes are also distributed as single CSS files, it contains no images. " +
|
||||||
|
"Unfortunately reusing Modena resources isn't possible, because the package isn't opened in OpenJFX 'module-info'."
|
||||||
|
);
|
||||||
|
description.getStyleClass().addAll(Styles.TEXT, Styles.WARNING);
|
||||||
|
|
||||||
var editor = new HTMLEditor();
|
var editor = new HTMLEditor();
|
||||||
editor.setPrefHeight(400);
|
editor.setPrefHeight(400);
|
||||||
editor.setHtmlText(String.join("<br/><br/>", FAKER.lorem().paragraphs(10)));
|
editor.setHtmlText(String.join("<br/><br/>", FAKER.lorem().paragraphs(10)));
|
||||||
return new SampleBlock("Playground", editor);
|
return new SampleBlock("Playground", new VBox(BLOCK_VGAP, new TextFlow(description), editor));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,13 +8,18 @@ import atlantafx.sampler.page.AbstractPage;
|
|||||||
import atlantafx.sampler.page.Page;
|
import atlantafx.sampler.page.Page;
|
||||||
import atlantafx.sampler.page.SampleBlock;
|
import atlantafx.sampler.page.SampleBlock;
|
||||||
import atlantafx.sampler.theme.CSSFragment;
|
import atlantafx.sampler.theme.CSSFragment;
|
||||||
|
import javafx.geometry.Insets;
|
||||||
import javafx.geometry.Pos;
|
import javafx.geometry.Pos;
|
||||||
|
import javafx.scene.control.Button;
|
||||||
import javafx.scene.control.Hyperlink;
|
import javafx.scene.control.Hyperlink;
|
||||||
|
import javafx.scene.control.Label;
|
||||||
import javafx.scene.layout.GridPane;
|
import javafx.scene.layout.GridPane;
|
||||||
import javafx.scene.layout.HBox;
|
import javafx.scene.layout.HBox;
|
||||||
import javafx.scene.layout.VBox;
|
import javafx.scene.layout.VBox;
|
||||||
import javafx.scene.text.Text;
|
import javafx.scene.text.Text;
|
||||||
import javafx.scene.text.TextFlow;
|
import javafx.scene.text.TextFlow;
|
||||||
|
import org.kordamp.ikonli.feather.Feather;
|
||||||
|
import org.kordamp.ikonli.javafx.FontIcon;
|
||||||
|
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
|
|
||||||
@ -31,7 +36,7 @@ public class PopoverPage extends AbstractPage {
|
|||||||
public PopoverPage() {
|
public PopoverPage() {
|
||||||
super();
|
super();
|
||||||
setUserContent(new VBox(Page.PAGE_VGAP,
|
setUserContent(new VBox(Page.PAGE_VGAP,
|
||||||
new HBox(PAGE_HGAP, textSample(), datePickerSample()),
|
new HBox(PAGE_HGAP, textSample(), datePickerSample(), dialogSample()),
|
||||||
positionSample()
|
positionSample()
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@ -72,6 +77,42 @@ public class PopoverPage extends AbstractPage {
|
|||||||
return new SampleBlock("Date Picker", link);
|
return new SampleBlock("Date Picker", link);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private SampleBlock dialogSample() {
|
||||||
|
var root = new VBox(BLOCK_VGAP);
|
||||||
|
|
||||||
|
var popover = new Popover(root);
|
||||||
|
popover.setHeaderAlwaysVisible(false);
|
||||||
|
popover.setDetachable(true);
|
||||||
|
|
||||||
|
var icon = new FontIcon(Feather.ALERT_TRIANGLE);
|
||||||
|
icon.setIconSize(32); // not always works
|
||||||
|
icon.setStyle("-fx-icon-size:32px;-fx-icon-color:-color-warning-fg;-fx-fill:-color-warning-fg;" + icon.getStyle());
|
||||||
|
|
||||||
|
var label = new Label(FAKER.chuckNorris().fact(), icon);
|
||||||
|
label.setStyle("-fx-graphic-text-gap:10;");
|
||||||
|
label.setWrapText(true);
|
||||||
|
label.setMaxWidth(300);
|
||||||
|
label.setMaxHeight(Double.MAX_VALUE);
|
||||||
|
root.getChildren().add(label);
|
||||||
|
|
||||||
|
var yesBtn = new Button("Yes");
|
||||||
|
yesBtn.setDefaultButton(true);
|
||||||
|
yesBtn.setOnAction(e -> popover.hide());
|
||||||
|
|
||||||
|
var noBtn = new Button("No");
|
||||||
|
noBtn.setOnAction(e -> popover.hide());
|
||||||
|
|
||||||
|
var box = new HBox(10, yesBtn, noBtn);
|
||||||
|
box.setPadding(new Insets(0, 0, 0, 42));
|
||||||
|
box.setAlignment(Pos.CENTER_LEFT);
|
||||||
|
root.getChildren().add(box);
|
||||||
|
|
||||||
|
var link = createHyperlink("Click me");
|
||||||
|
link.setOnAction(e -> popover.show(link));
|
||||||
|
|
||||||
|
return new SampleBlock("Dialog", link);
|
||||||
|
}
|
||||||
|
|
||||||
private SampleBlock positionSample() {
|
private SampleBlock positionSample() {
|
||||||
var grid = new GridPane();
|
var grid = new GridPane();
|
||||||
grid.setHgap(BLOCK_HGAP);
|
grid.setHgap(BLOCK_HGAP);
|
||||||
|
@ -6,13 +6,13 @@ import atlantafx.sampler.page.AbstractPage;
|
|||||||
import atlantafx.sampler.page.Page;
|
import atlantafx.sampler.page.Page;
|
||||||
import atlantafx.sampler.page.SampleBlock;
|
import atlantafx.sampler.page.SampleBlock;
|
||||||
import atlantafx.sampler.theme.CSSFragment;
|
import atlantafx.sampler.theme.CSSFragment;
|
||||||
|
import javafx.beans.binding.Bindings;
|
||||||
import javafx.concurrent.Task;
|
import javafx.concurrent.Task;
|
||||||
import javafx.css.PseudoClass;
|
import javafx.css.PseudoClass;
|
||||||
|
import javafx.geometry.HPos;
|
||||||
import javafx.geometry.Pos;
|
import javafx.geometry.Pos;
|
||||||
import javafx.scene.control.Button;
|
import javafx.geometry.VPos;
|
||||||
import javafx.scene.control.Label;
|
import javafx.scene.control.*;
|
||||||
import javafx.scene.control.ProgressBar;
|
|
||||||
import javafx.scene.control.ProgressIndicator;
|
|
||||||
import javafx.scene.layout.*;
|
import javafx.scene.layout.*;
|
||||||
import javafx.scene.text.Text;
|
import javafx.scene.text.Text;
|
||||||
import javafx.util.StringConverter;
|
import javafx.util.StringConverter;
|
||||||
@ -24,7 +24,7 @@ import static atlantafx.sampler.page.SampleBlock.BLOCK_HGAP;
|
|||||||
import static atlantafx.sampler.page.SampleBlock.BLOCK_VGAP;
|
import static atlantafx.sampler.page.SampleBlock.BLOCK_VGAP;
|
||||||
|
|
||||||
// #javafx-bug Indeterminate (animated) progress bar and also progress indicator
|
// #javafx-bug Indeterminate (animated) progress bar and also progress indicator
|
||||||
// are VERY resource expensive. It consumes a single CPU core and a lot of memory.
|
// are very resource expensive. It consumes a single CPU core and a lot of memory.
|
||||||
public class ProgressPage extends AbstractPage {
|
public class ProgressPage extends AbstractPage {
|
||||||
|
|
||||||
public static final String NAME = "Progress";
|
public static final String NAME = "Progress";
|
||||||
@ -45,27 +45,46 @@ public class ProgressPage extends AbstractPage {
|
|||||||
grid.add(ringIndicatorSample(), 0, 1);
|
grid.add(ringIndicatorSample(), 0, 1);
|
||||||
grid.add(barSizeSample(), 1, 1);
|
grid.add(barSizeSample(), 1, 1);
|
||||||
|
|
||||||
grid.add(colorChangeSample(), 0, 2);
|
grid.add(indeterminateSample(), 0, 2);
|
||||||
|
grid.add(colorChangeSample(), 1, 2);
|
||||||
|
|
||||||
setUserContent(grid);
|
setUserContent(grid);
|
||||||
}
|
}
|
||||||
|
|
||||||
private SampleBlock basicBarSample() {
|
private SampleBlock basicBarSample() {
|
||||||
var flowPane = new FlowPane(BLOCK_HGAP, BLOCK_VGAP, createBar(0, false), createBar(0.5, false), createBar(1, false), createBar(0.5, true));
|
var flowPane = new FlowPane(
|
||||||
|
BLOCK_HGAP, BLOCK_VGAP,
|
||||||
|
createBar(0, false),
|
||||||
|
createBar(0.5, false),
|
||||||
|
createBar(1, false),
|
||||||
|
createBar(0.5, true)
|
||||||
|
);
|
||||||
flowPane.setAlignment(Pos.CENTER_LEFT);
|
flowPane.setAlignment(Pos.CENTER_LEFT);
|
||||||
|
|
||||||
return new SampleBlock("Progress Bar", flowPane);
|
return new SampleBlock("Progress Bar", flowPane);
|
||||||
}
|
}
|
||||||
|
|
||||||
private SampleBlock basicIndicatorSample() {
|
private SampleBlock basicIndicatorSample() {
|
||||||
var flowPane = new FlowPane(BLOCK_HGAP, BLOCK_VGAP, createIndicator(0, false), createIndicator(0.5, false), createIndicator(1, false), createIndicator(0.5, true));
|
var flowPane = new FlowPane(
|
||||||
|
BLOCK_HGAP, BLOCK_VGAP,
|
||||||
|
createIndicator(0, false),
|
||||||
|
createIndicator(0.5, false),
|
||||||
|
createIndicator(1, false),
|
||||||
|
createIndicator(0.5, true)
|
||||||
|
);
|
||||||
flowPane.setAlignment(Pos.TOP_LEFT);
|
flowPane.setAlignment(Pos.TOP_LEFT);
|
||||||
|
|
||||||
return new SampleBlock("Progress Indicator", flowPane);
|
return new SampleBlock("Progress Indicator", flowPane);
|
||||||
}
|
}
|
||||||
|
|
||||||
private SampleBlock barSizeSample() {
|
private SampleBlock barSizeSample() {
|
||||||
var container = new VBox(BLOCK_VGAP, new HBox(20, createBar(0.5, false, SMALL), new Text("small")), new HBox(20, createBar(0.5, false, MEDIUM), new Text("medium")), new HBox(20, createBar(0.5, false, LARGE), new Text("large")));
|
var container = new VBox(
|
||||||
|
BLOCK_VGAP,
|
||||||
|
new HBox(20, createBar(0.5, false, SMALL), new Text("small")),
|
||||||
|
new HBox(20, createBar(0.5, false, MEDIUM), new Text("medium")),
|
||||||
|
new HBox(20, createBar(0.5, false, LARGE), new Text("large"))
|
||||||
|
);
|
||||||
|
container.setAlignment(Pos.TOP_LEFT);
|
||||||
container.getChildren().forEach(c -> ((HBox) c).setAlignment(Pos.CENTER_LEFT));
|
container.getChildren().forEach(c -> ((HBox) c).setAlignment(Pos.CENTER_LEFT));
|
||||||
|
|
||||||
return new SampleBlock("Size", container);
|
return new SampleBlock("Size", container);
|
||||||
@ -75,7 +94,7 @@ public class ProgressPage extends AbstractPage {
|
|||||||
var basicIndicator = new RingProgressIndicator(0, false);
|
var basicIndicator = new RingProgressIndicator(0, false);
|
||||||
|
|
||||||
var customTextIndicator = new RingProgressIndicator(0.5, false);
|
var customTextIndicator = new RingProgressIndicator(0.5, false);
|
||||||
customTextIndicator.setPrefSize(75, 75);
|
customTextIndicator.setMinSize(75, 75);
|
||||||
customTextIndicator.setStringConverter(new StringConverter<>() {
|
customTextIndicator.setStringConverter(new StringConverter<>() {
|
||||||
@Override
|
@Override
|
||||||
public String toString(Double progress) {
|
public String toString(Double progress) {
|
||||||
@ -89,7 +108,7 @@ public class ProgressPage extends AbstractPage {
|
|||||||
});
|
});
|
||||||
|
|
||||||
var reverseIndicator = new RingProgressIndicator(0.25, true);
|
var reverseIndicator = new RingProgressIndicator(0.25, true);
|
||||||
reverseIndicator.setPrefSize(150, 150);
|
reverseIndicator.setMinSize(150, 150);
|
||||||
|
|
||||||
var reverseIndicatorLabel = new Label("25%");
|
var reverseIndicatorLabel = new Label("25%");
|
||||||
reverseIndicatorLabel.getStyleClass().add(TITLE_4);
|
reverseIndicatorLabel.getStyleClass().add(TITLE_4);
|
||||||
@ -139,6 +158,60 @@ public class ProgressPage extends AbstractPage {
|
|||||||
return new SampleBlock("Ring Indicator", box);
|
return new SampleBlock("Ring Indicator", box);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private SampleBlock indeterminateSample() {
|
||||||
|
var grid = new GridPane();
|
||||||
|
grid.setHgap(40);
|
||||||
|
grid.setVgap(BLOCK_VGAP);
|
||||||
|
grid.getColumnConstraints().setAll(
|
||||||
|
new ColumnConstraints(-1, -1, -1, Priority.NEVER, HPos.CENTER, true),
|
||||||
|
new ColumnConstraints(-1, -1, -1, Priority.NEVER, HPos.CENTER, true),
|
||||||
|
new ColumnConstraints(-1, -1, -1, Priority.NEVER, HPos.CENTER, true)
|
||||||
|
);
|
||||||
|
grid.getRowConstraints().setAll(
|
||||||
|
new RowConstraints(-1, -1, -1, Priority.ALWAYS, VPos.CENTER, true),
|
||||||
|
new RowConstraints(-1, -1, -1, Priority.NEVER, VPos.CENTER, true)
|
||||||
|
);
|
||||||
|
|
||||||
|
var barToggle = new ToggleButton("Start");
|
||||||
|
barToggle.textProperty().bind(Bindings.createStringBinding(
|
||||||
|
() -> barToggle.isSelected() ? "Stop" : "Start", barToggle.selectedProperty())
|
||||||
|
);
|
||||||
|
var bar = createBar(0, false);
|
||||||
|
bar.progressProperty().bind(Bindings.createDoubleBinding(
|
||||||
|
() -> barToggle.isSelected() ? -1d : 0d, barToggle.selectedProperty())
|
||||||
|
);
|
||||||
|
grid.add(bar, 0, 0);
|
||||||
|
grid.add(barToggle, 0, 1);
|
||||||
|
|
||||||
|
var indicatorToggle = new ToggleButton("Start");
|
||||||
|
indicatorToggle.textProperty().bind(Bindings.createStringBinding(
|
||||||
|
() -> indicatorToggle.isSelected() ? "Stop" : "Start", indicatorToggle.selectedProperty())
|
||||||
|
);
|
||||||
|
var indicator = createIndicator(0, false);
|
||||||
|
indicator.setPrefSize(75, 75);
|
||||||
|
indicator.progressProperty().bind(Bindings.createDoubleBinding(
|
||||||
|
() -> indicatorToggle.isSelected() ? -1d : 0d, indicatorToggle.selectedProperty())
|
||||||
|
);
|
||||||
|
grid.add(indicator, 1, 0);
|
||||||
|
grid.add(indicatorToggle, 1, 1);
|
||||||
|
|
||||||
|
var ringToggle = new ToggleButton("Start");
|
||||||
|
ringToggle.textProperty().bind(Bindings.createStringBinding(
|
||||||
|
() -> ringToggle.isSelected() ? "Stop" : "Start", ringToggle.selectedProperty())
|
||||||
|
);
|
||||||
|
var ring = new RingProgressIndicator(0, false);
|
||||||
|
ring.setMinSize(75, 75);
|
||||||
|
ring.progressProperty().bind(Bindings.createDoubleBinding(
|
||||||
|
() -> ringToggle.isSelected() ? -1d : 0d, ringToggle.selectedProperty())
|
||||||
|
);
|
||||||
|
grid.add(ring, 2, 0);
|
||||||
|
grid.add(ringToggle, 2, 1);
|
||||||
|
|
||||||
|
return new SampleBlock("Indeterminate", grid,
|
||||||
|
"Animated JavaFX progress indicators aren't cheap. They can consume quite a lot of CPU time."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
private SampleBlock colorChangeSample() {
|
private SampleBlock colorChangeSample() {
|
||||||
var stateSuccess = PseudoClass.getPseudoClass("state-success");
|
var stateSuccess = PseudoClass.getPseudoClass("state-success");
|
||||||
var stateDanger = PseudoClass.getPseudoClass("state-danger");
|
var stateDanger = PseudoClass.getPseudoClass("state-danger");
|
||||||
@ -164,6 +237,7 @@ public class ProgressPage extends AbstractPage {
|
|||||||
var content = new VBox(BLOCK_VGAP);
|
var content = new VBox(BLOCK_VGAP);
|
||||||
content.getChildren().setAll(barStack, runBtn);
|
content.getChildren().setAll(barStack, runBtn);
|
||||||
content.setAlignment(Pos.CENTER_LEFT);
|
content.setAlignment(Pos.CENTER_LEFT);
|
||||||
|
content.setPrefHeight(200);
|
||||||
|
|
||||||
bar.progressProperty().addListener((obs, old, val) -> {
|
bar.progressProperty().addListener((obs, old, val) -> {
|
||||||
if (val == null) { return; }
|
if (val == null) { return; }
|
||||||
@ -176,17 +250,17 @@ public class ProgressPage extends AbstractPage {
|
|||||||
});
|
});
|
||||||
|
|
||||||
new CSSFragment("""
|
new CSSFragment("""
|
||||||
.example:state-success .progress-bar {
|
.example:state-success .progress-bar {
|
||||||
-color-progress-bar-fill: -color-success-emphasis;
|
-color-progress-bar-fill: -color-success-emphasis;
|
||||||
}
|
}
|
||||||
.example:state-danger .progress-bar {
|
.example:state-danger .progress-bar {
|
||||||
-color-progress-bar-fill: -color-danger-emphasis;
|
-color-progress-bar-fill: -color-danger-emphasis;
|
||||||
}
|
}
|
||||||
.example:state-success .label,
|
.example:state-success .label,
|
||||||
.example:state-danger .label {
|
.example:state-danger .label {
|
||||||
-fx-text-fill: -color-fg-emphasis;
|
-fx-text-fill: -color-fg-emphasis;
|
||||||
}
|
}
|
||||||
""").addTo(content);
|
""").addTo(content);
|
||||||
|
|
||||||
runBtn.setOnAction(e1 -> {
|
runBtn.setOnAction(e1 -> {
|
||||||
var task = new Task<Void>() {
|
var task = new Task<Void>() {
|
||||||
@ -224,7 +298,7 @@ public class ProgressPage extends AbstractPage {
|
|||||||
return new SampleBlock("Dynamic Color Change", content);
|
return new SampleBlock("Dynamic Color Change", content);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ProgressIndicator createBar(double progress, boolean disabled, String... styleClasses) {
|
private ProgressBar createBar(double progress, boolean disabled, String... styleClasses) {
|
||||||
var bar = new ProgressBar(progress);
|
var bar = new ProgressBar(progress);
|
||||||
bar.getStyleClass().addAll(styleClasses);
|
bar.getStyleClass().addAll(styleClasses);
|
||||||
bar.setDisable(disabled);
|
bar.setDisable(disabled);
|
||||||
|
@ -7,15 +7,19 @@ import atlantafx.sampler.theme.CSSFragment;
|
|||||||
import javafx.geometry.Pos;
|
import javafx.geometry.Pos;
|
||||||
import javafx.scene.control.Button;
|
import javafx.scene.control.Button;
|
||||||
import javafx.scene.control.Hyperlink;
|
import javafx.scene.control.Hyperlink;
|
||||||
|
import javafx.scene.control.Label;
|
||||||
import javafx.scene.image.Image;
|
import javafx.scene.image.Image;
|
||||||
import javafx.scene.image.ImageView;
|
import javafx.scene.image.ImageView;
|
||||||
import javafx.scene.image.PixelReader;
|
import javafx.scene.image.PixelReader;
|
||||||
import javafx.scene.image.WritableImage;
|
import javafx.scene.image.WritableImage;
|
||||||
|
import javafx.scene.layout.GridPane;
|
||||||
import javafx.scene.layout.HBox;
|
import javafx.scene.layout.HBox;
|
||||||
import javafx.scene.layout.VBox;
|
import javafx.scene.layout.VBox;
|
||||||
import javafx.scene.text.Text;
|
import javafx.scene.text.Text;
|
||||||
import javafx.scene.text.TextFlow;
|
import javafx.scene.text.TextFlow;
|
||||||
import net.datafaker.Faker;
|
import net.datafaker.Faker;
|
||||||
|
import org.kordamp.ikonli.javafx.FontIcon;
|
||||||
|
import org.kordamp.ikonli.material2.Material2AL;
|
||||||
|
|
||||||
import static atlantafx.sampler.page.Page.PAGE_HGAP;
|
import static atlantafx.sampler.page.Page.PAGE_HGAP;
|
||||||
import static atlantafx.sampler.page.Page.PAGE_VGAP;
|
import static atlantafx.sampler.page.Page.PAGE_VGAP;
|
||||||
@ -43,7 +47,8 @@ public class CardSample extends HBox {
|
|||||||
new VBox(
|
new VBox(
|
||||||
PAGE_VGAP,
|
PAGE_VGAP,
|
||||||
imageTextCard(),
|
imageTextCard(),
|
||||||
titleImageCard()
|
titleImageCard(),
|
||||||
|
statisticCard()
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -111,7 +116,7 @@ public class CardSample extends HBox {
|
|||||||
card.setImage(new ImageView(cropImage));
|
card.setImage(new ImageView(cropImage));
|
||||||
card.setTitle("Title");
|
card.setTitle("Title");
|
||||||
|
|
||||||
var text = new Text(FAKER.lorem().paragraph());
|
var text = new Text(FAKER.lorem().sentence());
|
||||||
card.setBody(new TextFlow(text));
|
card.setBody(new TextFlow(text));
|
||||||
|
|
||||||
return card;
|
return card;
|
||||||
@ -141,4 +146,34 @@ public class CardSample extends HBox {
|
|||||||
|
|
||||||
return card;
|
return card;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Card statisticCard() {
|
||||||
|
var card = new Card();
|
||||||
|
card.setMinWidth(CARD_WIDTH);
|
||||||
|
card.setMaxWidth(CARD_WIDTH);
|
||||||
|
card.setTitle("Statistic");
|
||||||
|
|
||||||
|
var grid = new GridPane();
|
||||||
|
grid.setHgap(40);
|
||||||
|
grid.setVgap(10);
|
||||||
|
card.setBody(grid);
|
||||||
|
|
||||||
|
var leftHead = new Text("Active");
|
||||||
|
leftHead.getStyleClass().add(Styles.TEXT_MUTED);
|
||||||
|
grid.add(leftHead, 0, 0);
|
||||||
|
|
||||||
|
var leftData = new Label("12.87", new FontIcon(Material2AL.ARROW_UPWARD));
|
||||||
|
leftData.getStyleClass().addAll(Styles.SUCCESS, Styles.TITLE_2);
|
||||||
|
grid.add(leftData, 0, 1);
|
||||||
|
|
||||||
|
var rightHead = new Text("Idle");
|
||||||
|
rightHead.getStyleClass().add(Styles.TEXT_MUTED);
|
||||||
|
grid.add(rightHead, 1, 0);
|
||||||
|
|
||||||
|
var rightData = new Label("3.74", new FontIcon(Material2AL.ARROW_DOWNWARD));
|
||||||
|
rightData.getStyleClass().addAll(Styles.DANGER, Styles.TITLE_2);
|
||||||
|
grid.add(rightData, 1, 1);
|
||||||
|
|
||||||
|
return card;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -56,7 +56,7 @@ public class Stepper extends HBox {
|
|||||||
-fx-icon-color: -color-stepper-fg;
|
-fx-icon-color: -color-stepper-fg;
|
||||||
}
|
}
|
||||||
.stepper > .item:selected > .graphic {
|
.stepper > .item:selected > .graphic {
|
||||||
-color-stepper-bg: -color-accent-subtle;
|
-color-stepper-bg: -color-bg-default;
|
||||||
-color-stepper-fg: -color-accent-fg;
|
-color-stepper-fg: -color-accent-fg;
|
||||||
-color-stepper-border: -color-accent-emphasis;
|
-color-stepper-border: -color-accent-emphasis;
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ import atlantafx.base.theme.Styles;
|
|||||||
import atlantafx.sampler.page.SampleBlock;
|
import atlantafx.sampler.page.SampleBlock;
|
||||||
import atlantafx.sampler.page.showcase.widget.Stepper.Item;
|
import atlantafx.sampler.page.showcase.widget.Stepper.Item;
|
||||||
import atlantafx.sampler.theme.CSSFragment;
|
import atlantafx.sampler.theme.CSSFragment;
|
||||||
|
import javafx.beans.binding.Bindings;
|
||||||
import javafx.geometry.Pos;
|
import javafx.geometry.Pos;
|
||||||
import javafx.geometry.Side;
|
import javafx.geometry.Side;
|
||||||
import javafx.scene.Node;
|
import javafx.scene.Node;
|
||||||
@ -61,20 +62,24 @@ public class StepperSample extends SampleBlock {
|
|||||||
|
|
||||||
// == CONTROLS ==
|
// == CONTROLS ==
|
||||||
|
|
||||||
var saveBtn = new Button("Save");
|
var nextBtn = new Button("Next");
|
||||||
saveBtn.setDefaultButton(true);
|
nextBtn.setDefaultButton(true);
|
||||||
saveBtn.setOnAction(e -> {
|
nextBtn.setOnAction(e -> {
|
||||||
// you can validate user input before moving forward here
|
// you can validate user input before moving forward here
|
||||||
stepper.getSelectedItem().setCompleted(true);
|
stepper.getSelectedItem().setCompleted(true);
|
||||||
stepper.forward();
|
stepper.forward();
|
||||||
});
|
});
|
||||||
|
nextBtn.textProperty().bind(Bindings.createStringBinding(
|
||||||
|
() -> stepper.canGoForwardProperty().get() ? "Next" : "Done", stepper.canGoForwardProperty())
|
||||||
|
);
|
||||||
|
|
||||||
var cancelBtn = new Button("Cancel");
|
var prevBtn = new Button("Previous");
|
||||||
cancelBtn.getStyleClass().addAll(Styles.FLAT);
|
prevBtn.getStyleClass().addAll(Styles.FLAT);
|
||||||
cancelBtn.setOnAction(e -> {
|
prevBtn.setOnAction(e -> {
|
||||||
stepper.getSelectedItem().setCompleted(false);
|
stepper.getSelectedItem().setCompleted(false);
|
||||||
stepper.backward();
|
stepper.backward();
|
||||||
});
|
});
|
||||||
|
prevBtn.disableProperty().bind(stepper.canGoBackProperty().not());
|
||||||
|
|
||||||
var iconToggle = new ToggleSwitch("Icons");
|
var iconToggle = new ToggleSwitch("Icons");
|
||||||
iconToggle.selectedProperty().addListener((obs, old, val) -> {
|
iconToggle.selectedProperty().addListener((obs, old, val) -> {
|
||||||
@ -101,8 +106,8 @@ public class StepperSample extends SampleBlock {
|
|||||||
|
|
||||||
var controls = new HBox(
|
var controls = new HBox(
|
||||||
BLOCK_HGAP,
|
BLOCK_HGAP,
|
||||||
saveBtn,
|
nextBtn,
|
||||||
cancelBtn,
|
prevBtn,
|
||||||
new Spacer(),
|
new Spacer(),
|
||||||
iconToggle,
|
iconToggle,
|
||||||
rotateBtn
|
rotateBtn
|
||||||
|
@ -3,6 +3,9 @@ package atlantafx.sampler.page.showcase.widget;
|
|||||||
|
|
||||||
import javafx.scene.Node;
|
import javafx.scene.Node;
|
||||||
import javafx.scene.control.Button;
|
import javafx.scene.control.Button;
|
||||||
|
import javafx.scene.layout.Pane;
|
||||||
|
|
||||||
|
import static javafx.scene.control.ContentDisplay.RIGHT;
|
||||||
|
|
||||||
public class Tag extends Button {
|
public class Tag extends Button {
|
||||||
|
|
||||||
@ -10,6 +13,7 @@ public class Tag extends Button {
|
|||||||
.tag {
|
.tag {
|
||||||
-fx-padding: 4px 6px 4px 6px;
|
-fx-padding: 4px 6px 4px 6px;
|
||||||
-fx-cursor: hand;
|
-fx-cursor: hand;
|
||||||
|
-color-button-border-hover: -color-button-border;
|
||||||
-color-button-border-focused: -color-button-border;
|
-color-button-border-focused: -color-button-border;
|
||||||
-color-button-border-pressed: -color-button-border;
|
-color-button-border-pressed: -color-button-border;
|
||||||
}
|
}
|
||||||
@ -21,6 +25,27 @@ public class Tag extends Button {
|
|||||||
|
|
||||||
public Tag(String text, Node graphic) {
|
public Tag(String text, Node graphic) {
|
||||||
super(text, graphic);
|
super(text, graphic);
|
||||||
|
|
||||||
|
if (graphic != null) {
|
||||||
|
graphic.setOnMouseEntered(e -> {
|
||||||
|
if (getContentDisplay() == RIGHT) {
|
||||||
|
graphic.setScaleX(1.2);
|
||||||
|
graphic.setScaleY(1.2);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
graphic.setOnMouseExited(e -> {
|
||||||
|
if (getContentDisplay() == RIGHT) {
|
||||||
|
graphic.setScaleX(1);
|
||||||
|
graphic.setScaleY(1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
graphic.setOnMouseClicked(e -> {
|
||||||
|
if (getContentDisplay() == RIGHT && getParent() != null && getParent() instanceof Pane pane) {
|
||||||
|
pane.getChildren().remove(this);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
getStyleClass().add("tag");
|
getStyleClass().add("tag");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,6 +30,7 @@ public class TagSample extends GridPane {
|
|||||||
add(iconTagSample(), 1, 0);
|
add(iconTagSample(), 1, 0);
|
||||||
add(outlinedTagSample(), 0, 1);
|
add(outlinedTagSample(), 0, 1);
|
||||||
add(closeableTagSample(), 1, 1);
|
add(closeableTagSample(), 1, 1);
|
||||||
|
add(customColorTagSample(), 0, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
private SampleBlock filledTagSample() {
|
private SampleBlock filledTagSample() {
|
||||||
@ -114,4 +115,42 @@ public class TagSample extends GridPane {
|
|||||||
|
|
||||||
return new SampleBlock("Removable", content);
|
return new SampleBlock("Removable", content);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private SampleBlock customColorTagSample() {
|
||||||
|
var content = new FlowPane(BLOCK_HGAP, BLOCK_VGAP);
|
||||||
|
content.setPrefWidth(PREF_WIDTH);
|
||||||
|
new CSSFragment("""
|
||||||
|
.brand {
|
||||||
|
-color-button-fg: -color-fg-emphasis;
|
||||||
|
-color-button-bg-hover: -color-button-bg;
|
||||||
|
-color-button-bg-pressed: -color-button-bg;
|
||||||
|
}
|
||||||
|
.twitter {
|
||||||
|
-color-button-bg: rgb(85, 172, 238);
|
||||||
|
-color-button-border: rgb(85, 172, 238);
|
||||||
|
}
|
||||||
|
.youtube {
|
||||||
|
-color-button-bg: rgb(205, 32, 31);
|
||||||
|
-color-button-border: rgb(205, 32, 31);
|
||||||
|
}
|
||||||
|
.facebook {
|
||||||
|
-color-button-bg: rgb(59, 89, 153);
|
||||||
|
-color-button-border: rgb(59, 89, 153);
|
||||||
|
}
|
||||||
|
""").addTo(content);
|
||||||
|
|
||||||
|
var twitterTag = new Tag("Twitter", new FontIcon(Feather.TWITTER));
|
||||||
|
twitterTag.getStyleClass().addAll("brand", "twitter");
|
||||||
|
content.getChildren().add(twitterTag);
|
||||||
|
|
||||||
|
var youtubeTag = new Tag("YouTube", new FontIcon(Feather.YOUTUBE));
|
||||||
|
youtubeTag.getStyleClass().addAll("brand", "youtube");
|
||||||
|
content.getChildren().add(youtubeTag);
|
||||||
|
|
||||||
|
var facebookTag = new Tag("Facebook", new FontIcon(Feather.FACEBOOK));
|
||||||
|
facebookTag.getStyleClass().addAll("brand", "facebook");
|
||||||
|
content.getChildren().add(facebookTag);
|
||||||
|
|
||||||
|
return new SampleBlock("Custom Color", content);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -53,14 +53,10 @@ $color-button-bg-selected: if(cfg.$darkMode, -color-base-6, -color-base-1) !defa
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sadly JavaFX devs have a mania to declare everyting private and final.
|
// JavaFX doesn't export (open) Modena resources package, so the below links won't work.
|
||||||
// The below code isn't working, while there are no runtime errors and URLs are correct
|
// Because of AtlantaFX themes are also distributed as single CSS files, it can't be fixed here.
|
||||||
// it's still not loaded for unknown reason.
|
// You can copy Modena resources and override those URLs in your app CSS to tackle the problem
|
||||||
// There are to many images here and HMTLEditor itself is obsolete type of control,
|
// or better use TinyMCE or any other modern JS WYSIWYG editor instead of this legacy control.
|
||||||
// so I don't want to use data-url. It's either be fixed at OpenJFX or not.
|
|
||||||
// Anyone who treats this as a problem can easily fix it by using addtitional CSS file.
|
|
||||||
// Just copy CSS rules from below and images from the OpenJFX repo and then use relative
|
|
||||||
// URLs. #javafx-bug
|
|
||||||
$image-path: "/com/sun/javafx/scene/control/skin/modena" !default;
|
$image-path: "/com/sun/javafx/scene/control/skin/modena" !default;
|
||||||
|
|
||||||
.color-picker.html-editor-foreground {
|
.color-picker.html-editor-foreground {
|
||||||
|
@ -48,24 +48,55 @@ Text {
|
|||||||
}
|
}
|
||||||
.label.accent {
|
.label.accent {
|
||||||
-fx-text-fill: -color-accent-fg;
|
-fx-text-fill: -color-accent-fg;
|
||||||
|
|
||||||
|
#{cfg.$font-icon-selector} {
|
||||||
|
-fx-icon-color: -color-accent-fg;
|
||||||
|
-fx-fill: -color-accent-fg;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.text.success {
|
.text.success {
|
||||||
-fx-fill: -color-success-fg;
|
-fx-fill: -color-success-fg;
|
||||||
}
|
}
|
||||||
.label.success {
|
.label.success {
|
||||||
-fx-text-fill: -color-success-fg;
|
-fx-text-fill: -color-success-fg;
|
||||||
|
|
||||||
|
#{cfg.$font-icon-selector} {
|
||||||
|
-fx-icon-color: -color-success-fg;
|
||||||
|
-fx-fill: -color-success-fg;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.text.warning {
|
.text.warning {
|
||||||
-fx-fill: -color-warning-fg;
|
-fx-fill: -color-warning-fg;
|
||||||
}
|
}
|
||||||
.label.warning {
|
.label.warning {
|
||||||
-fx-text-fill: -color-warning-fg;
|
-fx-text-fill: -color-warning-fg;
|
||||||
|
|
||||||
|
#{cfg.$font-icon-selector} {
|
||||||
|
-fx-icon-color: -color-warning-fg;
|
||||||
|
-fx-fill: -color-warning-fg;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.text.danger {
|
.text.danger {
|
||||||
-fx-fill: -color-danger-fg;
|
-fx-fill: -color-danger-fg;
|
||||||
}
|
}
|
||||||
.label.danger {
|
.label.danger {
|
||||||
-fx-text-fill: -color-danger-fg;
|
-fx-text-fill: -color-danger-fg;
|
||||||
|
|
||||||
|
#{cfg.$font-icon-selector} {
|
||||||
|
-fx-icon-color: -color-danger-fg;
|
||||||
|
-fx-fill: -color-danger-fg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.text-muted {
|
||||||
|
-fx-fill: -color-fg-muted;
|
||||||
|
}
|
||||||
|
.label.text-muted {
|
||||||
|
-fx-text-fill: -color-accent-fg;
|
||||||
|
|
||||||
|
#{cfg.$font-icon-selector} {
|
||||||
|
-fx-icon-color: -color-accent-fg;
|
||||||
|
-fx-fill: -color-accent-fg;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// font weight
|
// font weight
|
||||||
|
Loading…
Reference in New Issue
Block a user