From c7b9b7329236c69b97afcb8dfebc58ce3f3c487e Mon Sep 17 00:00:00 2001 From: Glavo Date: Wed, 4 Feb 2026 20:47:45 +0800 Subject: [PATCH] =?UTF-8?q?=E5=9F=BA=E4=BA=8E=20HBox=20=E9=87=8D=E6=96=B0?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0=20LineComponent=20=20(#5416)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ui/construct/ComponentSublistWrapper.java | 6 +- .../hmcl/ui/construct/LineButton.java | 155 ++++++------ .../hmcl/ui/construct/LineButtonBase.java | 66 +---- .../hmcl/ui/construct/LineComponent.java | 233 ++++++++++++------ .../jackhuang/hmcl/ui/construct/LinePane.java | 64 ++--- .../hmcl/ui/construct/LineSelectButton.java | 182 +++++++------- .../hmcl/ui/construct/LineTextPane.java | 26 +- .../hmcl/ui/construct/LineToggleButton.java | 16 +- .../hmcl/ui/main/JavaInstallPage.java | 1 - .../terracotta/TerracottaControllerPage.java | 41 ++- .../hmcl/ui/versions/WorldInfoPage.java | 11 +- HMCL/src/main/resources/assets/css/root.css | 71 +++--- 12 files changed, 436 insertions(+), 436 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/ComponentSublistWrapper.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/ComponentSublistWrapper.java index 9b2faa775..1d4dce53c 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/ComponentSublistWrapper.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/ComponentSublistWrapper.java @@ -45,9 +45,11 @@ final class ComponentSublistWrapper extends VBox implements NoPaddingComponent { ComponentSublistWrapper(ComponentSublist sublist) { boolean noPadding = !sublist.hasComponentPadding(); + this.getStyleClass().add("options-sublist-wrapper"); + Node expandIcon = SVG.KEYBOARD_ARROW_DOWN.createIcon(20); + expandIcon.getStyleClass().add("expand-icon"); expandIcon.setMouseTransparent(true); - HBox.setMargin(expandIcon, new Insets(0, 8, 0, 8)); VBox labelVBox = new VBox(); labelVBox.setMouseTransparent(true); @@ -72,7 +74,7 @@ final class ComponentSublistWrapper extends VBox implements NoPaddingComponent { } HBox header = new HBox(); - header.setSpacing(16); + header.setSpacing(12); header.getChildren().add(labelVBox); header.setPadding(new Insets(10, 16, 10, 16)); header.setAlignment(Pos.CENTER_LEFT); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/LineButton.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/LineButton.java index 9cd2eff89..782bbdd16 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/LineButton.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/LineButton.java @@ -20,34 +20,27 @@ package org.jackhuang.hmcl.ui.construct; import javafx.beans.property.*; import javafx.event.ActionEvent; import javafx.event.EventHandler; -import javafx.geometry.Insets; -import javafx.geometry.Pos; import javafx.scene.Node; import javafx.scene.control.Label; -import javafx.scene.layout.HBox; -import org.jackhuang.hmcl.ui.FXUtils; +import javafx.scene.control.OverrunStyle; import org.jackhuang.hmcl.ui.SVG; /// @author Glavo -public final class LineButton extends LineButtonBase { +public class LineButton extends LineButtonBase { private static final String DEFAULT_STYLE_CLASS = "line-button"; + private static final int IDX_TRAILING_TEXT = IDX_TRAILING; + private static final int IDX_TRAILING_ICON = IDX_TRAILING + 1; + public static LineButton createNavigationButton() { var button = new LineButton(); - button.setRightIcon(SVG.ARROW_FORWARD); + button.setTrailingIcon(SVG.ARROW_FORWARD); return button; } public LineButton() { getStyleClass().add(DEFAULT_STYLE_CLASS); - - root.setMouseTransparent(true); - - FXUtils.onClicked(container, this::fire); - } - - public void fire() { - fireEvent(new ActionEvent()); + container.setMouseTransparent(true); } private ObjectProperty> onAction; @@ -55,12 +48,6 @@ public final class LineButton extends LineButtonBase { public ObjectProperty> onActionProperty() { if (onAction == null) { onAction = new ObjectPropertyBase<>() { - - @Override - protected void invalidated() { - setEventHandler(ActionEvent.ACTION, get()); - } - @Override public Object getBean() { return LineButton.this; @@ -70,6 +57,11 @@ public final class LineButton extends LineButtonBase { public String getName() { return "onAction"; } + + @Override + protected void invalidated() { + setEventHandler(ActionEvent.ACTION, get()); + } }; } return onAction; @@ -83,11 +75,13 @@ public final class LineButton extends LineButtonBase { onActionProperty().set(value); } - private StringProperty message; + private StringProperty trailingText; + + public StringProperty trailingTextProperty() { + if (trailingText == null) { + trailingText = new StringPropertyBase() { + private Label trailingTextLabel; - public StringProperty messageProperty() { - if (message == null) { - message = new StringPropertyBase() { @Override public Object getBean() { return LineButton.this; @@ -95,85 +89,78 @@ public final class LineButton extends LineButtonBase { @Override public String getName() { - return "message"; + return "trailingText"; } @Override protected void invalidated() { - updateRight(); + String message = get(); + if (message != null && !message.isEmpty()) { + if (trailingTextLabel == null) { + trailingTextLabel = new Label(); + trailingTextLabel.getStyleClass().add("trailing-label"); + trailingTextLabel.setTextOverrun(OverrunStyle.CENTER_ELLIPSIS); + } + trailingTextLabel.setText(message); + setNode(IDX_TRAILING_TEXT, trailingTextLabel); + } else if (trailingTextLabel != null) { + trailingTextLabel.setText(""); + setNode(IDX_TRAILING_TEXT, null); + } } }; } - return message; + return trailingText; } - public String getMessage() { - return message == null ? "" : message.get(); + public String getTrailingText() { + return trailingText != null ? trailingText.get() : null; } - public void setMessage(String message) { - messageProperty().set(message); + public void setTrailingText(String trailingText) { + trailingTextProperty().set(trailingText); } - private SVG rightIcon; - private double rightIconSize; + private ObjectProperty trailingIcon; - public void setRightIcon(SVG rightIcon) { - setRightIcon(rightIcon, SVG.DEFAULT_SIZE); + public ObjectProperty trailingIconProperty() { + if (trailingIcon == null) + trailingIcon = new ObjectPropertyBase<>() { + @Override + public Object getBean() { + return LineButton.this; + } + + @Override + public String getName() { + return "trailingIcon"; + } + + @Override + protected void invalidated() { + setNode(IDX_TRAILING_ICON, get()); + } + }; + + return trailingIcon; } - public void setRightIcon(SVG rightIcon, double size) { - this.rightIcon = rightIcon; - this.rightIconSize = size; - updateRight(); + public Node getTrailingIcon() { + return trailingIcon != null ? trailingIcon.get() : null; } - //region Right - - private Label messageLabel; - private Node rightIconNode; - private SVG currentRightIcon; - private double currentRightIconSize; - - private void updateRight() { - HBox right; - if (root.getRight() instanceof HBox box) { - right = box; - } else { - right = new HBox(); - right.setAlignment(Pos.CENTER_RIGHT); - root.setRight(right); - } - - right.getChildren().clear(); - - String message = getMessage(); - if (message != null && !message.isEmpty()) { - if (messageLabel == null) { - messageLabel = new Label(); - messageLabel.getStyleClass().add("subtitle"); - } - messageLabel.setText(message); - right.getChildren().add(messageLabel); - } else if (messageLabel != null) { - messageLabel.setText(""); - } - - if (rightIcon != currentRightIcon || rightIconSize != currentRightIconSize) { - if (rightIcon != null) { - rightIconNode = rightIcon.createIcon(rightIconSize); - HBox.setMargin(rightIconNode, new Insets(0, 8, 0, 8)); - } else { - rightIconNode = null; - } - currentRightIcon = rightIcon; - currentRightIconSize = rightIconSize; - } - - if (rightIconNode != null) - right.getChildren().add(rightIconNode); + public void setTrailingIcon(Node trailingIcon) { + trailingIconProperty().set(trailingIcon); } - //endregion + public void setTrailingIcon(SVG rightIcon) { + setTrailingIcon(rightIcon, 20); + } + + public void setTrailingIcon(SVG rightIcon, double size) { + Node rightIconNode = rightIcon.createIcon(size); + rightIconNode.getStyleClass().add("trailing-icon"); + setTrailingIcon(rightIconNode); + } } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/LineButtonBase.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/LineButtonBase.java index 879bcaec2..ae4fea007 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/LineButtonBase.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/LineButtonBase.java @@ -17,71 +17,25 @@ */ package org.jackhuang.hmcl.ui.construct; -import javafx.beans.property.SimpleStringProperty; -import javafx.beans.property.StringProperty; -import javafx.geometry.Pos; -import javafx.scene.control.Label; -import javafx.scene.layout.BorderPane; -import javafx.scene.layout.StackPane; +import javafx.event.ActionEvent; +import org.jackhuang.hmcl.ui.FXUtils; /// @author Glavo -public abstract class LineButtonBase extends StackPane implements LineComponent { - +public abstract class LineButtonBase extends LineComponent { private static final String DEFAULT_STYLE_CLASS = "line-button-base"; - protected final BorderPane root; - protected final RipplerContainer container; - - private final Label titleLabel; + protected final RipplerContainer ripplerContainer; public LineButtonBase() { - this.getStyleClass().addAll(LineComponent.DEFAULT_STYLE_CLASS, LineButtonBase.DEFAULT_STYLE_CLASS); + this.getStyleClass().addAll(LineButtonBase.DEFAULT_STYLE_CLASS); - this.root = new BorderPane(); - root.setPadding(LineComponent.PADDING); - root.setMinHeight(LineComponent.MIN_HEIGHT); + this.ripplerContainer = new RipplerContainer(container); + FXUtils.onClicked(this, this::fire); - this.container = new RipplerContainer(root); - this.getChildren().setAll(container); - - this.titleLabel = new Label(); - root.setCenter(titleLabel); - BorderPane.setAlignment(titleLabel, Pos.CENTER_LEFT); - titleLabel.textProperty().bind(titleProperty()); - titleLabel.getStyleClass().add("title"); + this.getChildren().setAll(ripplerContainer); } - @Override - public BorderPane getRoot() { - return root; + public void fire() { + fireEvent(new ActionEvent()); } - - private final StringProperty title = new SimpleStringProperty(this, "title"); - - @Override - public StringProperty titleProperty() { - return title; - } - - private StringProperty subtitle; - - @Override - public StringProperty subtitleProperty() { - if (subtitle == null) { - subtitle = new LineComponent.SubtitleProperty() { - @Override - public LineButtonBase getBean() { - return LineButtonBase.this; - } - - @Override - public Label getTitleLabel() { - return titleLabel; - } - }; - } - - return subtitle; - } - } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/LineComponent.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/LineComponent.java index c31a34929..b0448a947 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/LineComponent.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/LineComponent.java @@ -17,101 +17,203 @@ */ package org.jackhuang.hmcl.ui.construct; +import javafx.beans.property.ObjectProperty; +import javafx.beans.property.ObjectPropertyBase; import javafx.beans.property.StringProperty; import javafx.beans.property.StringPropertyBase; import javafx.css.PseudoClass; import javafx.geometry.Insets; import javafx.geometry.Pos; import javafx.scene.Node; -import javafx.scene.control.Label; +import javafx.scene.control.*; import javafx.scene.image.Image; import javafx.scene.image.ImageView; -import javafx.scene.layout.BorderPane; -import javafx.scene.layout.Region; -import javafx.scene.layout.VBox; +import javafx.scene.layout.*; import org.jackhuang.hmcl.ui.SVG; +import java.util.Arrays; +import java.util.Objects; + /// @author Glavo -public interface LineComponent extends NoPaddingComponent { - String DEFAULT_STYLE_CLASS = "line-component"; +public abstract class LineComponent extends StackPane implements NoPaddingComponent { + private static final String DEFAULT_STYLE_CLASS = "line-component"; + private static final double MIN_HEIGHT = 48.0; + private static final PseudoClass PSEUDO_LARGER_TITLE = PseudoClass.getPseudoClass("large-title"); - PseudoClass PSEUDO_LARGER_TITLE = PseudoClass.getPseudoClass("large-title"); + protected static final int IDX_LEADING = 0; + protected static final int IDX_TITLE = 1; + protected static final int IDX_TRAILING = 2; - Insets PADDING = new Insets(8, 8, 8, 16); - Insets ICON_MARGIN = new Insets(0, 16, 0, 0); - double MIN_HEIGHT = 48.0; + public static final double SPACING = 12; + public static final double DEFAULT_ICON_SIZE = 20; - private Node self() { - return (Node) this; + public static void setMargin(Node child, Insets value) { + HBox.setMargin(child, value); } - BorderPane getRoot(); + protected final HBox container; - StringProperty titleProperty(); + private final Label titleLabel; + private final VBox titleContainer; - default String getTitle() { - return titleProperty().get(); + public LineComponent() { + this.getStyleClass().add(DEFAULT_STYLE_CLASS); + + this.setMinHeight(MIN_HEIGHT); + + this.container = new HBox(SPACING); + container.getStyleClass().add("line-component-container"); + container.setAlignment(Pos.CENTER_LEFT); + + this.titleLabel = new Label(); + titleLabel.getStyleClass().add("title-label"); + titleLabel.setMinWidth(Region.USE_PREF_SIZE); + + this.titleContainer = new VBox(titleLabel); + titleContainer.getStyleClass().add("title-container"); + titleContainer.setMouseTransparent(true); + titleContainer.setAlignment(Pos.CENTER_LEFT); + titleContainer.minWidthProperty().bind(titleLabel.prefWidthProperty()); + HBox.setHgrow(titleContainer, Priority.ALWAYS); + + this.setNode(IDX_TITLE, titleContainer); + + this.getChildren().setAll(container); } - default void setTitle(String title) { - titleProperty().set(title); + private Node[] nodes = new Node[2]; + + protected void setNode(int idx, Node node) { + if (nodes.length <= idx) + nodes = Arrays.copyOf(nodes, idx + 1); + + if (nodes[idx] != node) { + nodes[idx] = node; + container.getChildren().setAll(Arrays.stream(nodes).filter(Objects::nonNull).toArray(Node[]::new)); + } } - abstract class SubtitleProperty extends StringPropertyBase { - private VBox left; - private Label subtitleLabel; + public void setLargeTitle(boolean largeTitle) { + pseudoClassStateChanged(PSEUDO_LARGER_TITLE, largeTitle); + } + + private final StringProperty title = new StringPropertyBase() { + @Override + public Object getBean() { + return LineComponent.this; + } @Override public String getName() { - return "subtitle"; + return "title"; } - @Override - public abstract LineComponent getBean(); - - public abstract Label getTitleLabel(); - @Override protected void invalidated() { - String subtitle = get(); - if (subtitle != null && !subtitle.isEmpty()) { - if (left == null) { - left = new VBox(); - left.setMouseTransparent(true); - left.setAlignment(Pos.CENTER_LEFT); - - subtitleLabel = new Label(); - subtitleLabel.setWrapText(true); - subtitleLabel.setMinHeight(Region.USE_PREF_SIZE); - subtitleLabel.getStyleClass().add("subtitle"); - } - subtitleLabel.setText(subtitle); - left.getChildren().setAll(getTitleLabel(), subtitleLabel); - getBean().getRoot().setCenter(left); - } else if (left != null) { - subtitleLabel.setText(null); - getBean().getRoot().setCenter(getTitleLabel()); - } + titleLabel.setText(get()); } + }; + + public final StringProperty titleProperty() { + return title; } - StringProperty subtitleProperty(); - - default String getSubtitle() { - return subtitleProperty().get(); + public String getTitle() { + return titleProperty().get(); } - default void setSubtitle(String subtitle) { + public void setTitle(String title) { + titleProperty().set(title); + } + + private StringProperty subtitle; + + public final StringProperty subtitleProperty() { + if (subtitle == null) { + subtitle = new StringPropertyBase() { + private Label subtitleLabel; + + @Override + public String getName() { + return "subtitle"; + } + + @Override + public Object getBean() { + return LineComponent.this; + } + + @Override + protected void invalidated() { + String subtitle = get(); + if (subtitle != null && !subtitle.isEmpty()) { + if (subtitleLabel == null) { + subtitleLabel = new Label(); + subtitleLabel.setWrapText(true); + subtitleLabel.setMinHeight(Region.USE_PREF_SIZE); + subtitleLabel.getStyleClass().add("subtitle-label"); + } + subtitleLabel.setText(subtitle); + if (titleContainer.getChildren().size() == 1) + titleContainer.getChildren().add(subtitleLabel); + } else if (subtitleLabel != null) { + subtitleLabel.setText(null); + if (titleContainer.getChildren().size() == 2) + titleContainer.getChildren().remove(1); + } + } + }; + } + + return subtitle; + } + + public final String getSubtitle() { + return subtitle != null ? subtitle.get() : null; + } + + public final void setSubtitle(String subtitle) { subtitleProperty().set(subtitle); } - default void setLeftIcon(Image icon) { - setLeftIcon(icon, -1.0); + private ObjectProperty leading; + + public final ObjectProperty leadingProperty() { + if (leading == null) { + leading = new ObjectPropertyBase<>() { + @Override + public Object getBean() { + return LineComponent.this; + } + + @Override + public String getName() { + return "leading"; + } + + @Override + protected void invalidated() { + setNode(IDX_LEADING, get()); + } + }; + } + return leading; } - default void setLeftIcon(Image icon, double size) { - ImageView imageView = new ImageView(icon); - imageView.getStyleClass().add("left-icon"); + public final Node getLeading() { + return leadingProperty().get(); + } + + public final void setLeading(Node node) { + leadingProperty().set(node); + } + + public void setLeading(Image icon) { + setLeading(icon, -1); + } + + public void setLeading(Image icon, double size) { + var imageView = new ImageView(icon); if (size > 0) { imageView.setFitWidth(size); imageView.setFitHeight(size); @@ -119,25 +221,18 @@ public interface LineComponent extends NoPaddingComponent { imageView.setSmooth(true); } imageView.setMouseTransparent(true); - BorderPane.setAlignment(imageView, Pos.CENTER); - BorderPane.setMargin(imageView, ICON_MARGIN); - getRoot().setLeft(imageView); + + setNode(IDX_LEADING, imageView); } - default void setLeftIcon(SVG svg) { - setLeftIcon(svg, SVG.DEFAULT_SIZE); + public void setLeading(SVG svg) { + setLeading(svg, DEFAULT_ICON_SIZE); } - default void setLeftIcon(SVG svg, double size) { + public void setLeading(SVG svg, double size) { Node node = svg.createIcon(size); - node.getStyleClass().add("left-icon"); node.setMouseTransparent(true); - BorderPane.setAlignment(node, Pos.CENTER); - BorderPane.setMargin(node, ICON_MARGIN); - getRoot().setLeft(node); + setNode(IDX_LEADING, node); } - default void setLargeTitle(boolean largeTitle) { - self().pseudoClassStateChanged(PSEUDO_LARGER_TITLE, largeTitle); - } } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/LinePane.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/LinePane.java index a2bbaa30b..8a2d758d6 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/LinePane.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/LinePane.java @@ -17,61 +17,47 @@ */ package org.jackhuang.hmcl.ui.construct; -import javafx.beans.property.SimpleStringProperty; -import javafx.beans.property.StringProperty; -import javafx.geometry.Pos; -import javafx.scene.control.Label; -import javafx.scene.layout.BorderPane; +import javafx.beans.property.ObjectProperty; +import javafx.beans.property.ObjectPropertyBase; +import javafx.scene.Node; /// @author Glavo -public class LinePane extends BorderPane implements LineComponent { +public class LinePane extends LineComponent { private static final String DEFAULT_STYLE_CLASS = "line-pane"; - private final Label titleLabel; - public LinePane() { - this.getStyleClass().addAll(LineComponent.DEFAULT_STYLE_CLASS, LinePane.DEFAULT_STYLE_CLASS); - - this.setPadding(LineComponent.PADDING); - this.setMinHeight(LineComponent.MIN_HEIGHT); - - this.titleLabel = new Label(); - this.setCenter(titleLabel); - BorderPane.setAlignment(titleLabel, Pos.CENTER_LEFT); - titleLabel.textProperty().bind(titleProperty()); - titleLabel.getStyleClass().add("title"); + this.getStyleClass().add(DEFAULT_STYLE_CLASS); } - @Override - public BorderPane getRoot() { - return this; - } + private ObjectProperty right; - private final StringProperty title = new SimpleStringProperty(this, "title"); - - @Override - public StringProperty titleProperty() { - return title; - } - - private StringProperty subtitle; - - @Override - public StringProperty subtitleProperty() { - if (subtitle == null) { - subtitle = new LineComponent.SubtitleProperty() { + public ObjectProperty rightProperty() { + if (right == null) { + right = new ObjectPropertyBase<>() { @Override - public LinePane getBean() { + public Object getBean() { return LinePane.this; } @Override - public Label getTitleLabel() { - return titleLabel; + public String getName() { + return "right"; + } + + @Override + protected void invalidated() { + setNode(IDX_TRAILING, get()); } }; } + return right; + } - return subtitle; + public Node getRight() { + return rightProperty().get(); + } + + public void setRight(Node right) { + rightProperty().set(right); } } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/LineSelectButton.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/LineSelectButton.java index 3cbf6d1a1..2938b2167 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/LineSelectButton.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/LineSelectButton.java @@ -24,9 +24,7 @@ import javafx.beans.property.*; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.css.PseudoClass; -import javafx.geometry.Insets; import javafx.geometry.Pos; -import javafx.scene.Node; import javafx.scene.control.Label; import javafx.scene.input.MouseButton; import javafx.scene.input.MouseEvent; @@ -43,7 +41,7 @@ import java.util.function.Function; import static org.jackhuang.hmcl.ui.FXUtils.determineOptimalPopupPosition; /// @author Glavo -public final class LineSelectButton extends LineButtonBase { +public final class LineSelectButton extends LineButton { private static final String DEFAULT_STYLE_CLASS = "line-select-button"; private static final PseudoClass SELECTED_PSEUDO_CLASS = PseudoClass.getPseudoClass("selected"); @@ -53,109 +51,96 @@ public final class LineSelectButton extends LineButtonBase { public LineSelectButton() { this.getStyleClass().add(DEFAULT_STYLE_CLASS); - root.setMouseTransparent(true); + InvalidationListener updateTrailingText = observable -> { + T value = getValue(); + if (value != null) { + Function converter = getConverter(); + setTrailingText(converter != null ? converter.apply(value) : value.toString()); + } else { + setTrailingText(null); + } + }; + converterProperty().addListener(updateTrailingText); + valueProperty().addListener(updateTrailingText); - HBox right = new HBox(); - root.setRight(right); - { - right.setAlignment(Pos.CENTER_RIGHT); + setTrailingIcon(SVG.UNFOLD_MORE); - Label valueLabel = new Label(); - valueLabel.getStyleClass().add("subtitle"); - - InvalidationListener updateValue = observable -> { - T value = getValue(); - if (value == null) - valueLabel.setText(""); - else { - Function converter = getConverter(); - valueLabel.setText(converter != null ? converter.apply(value) : value.toString()); - } - }; - converterProperty().addListener(updateValue); - valueProperty().addListener(updateValue); - - Node arrowIcon = SVG.UNFOLD_MORE.createIcon(24); - HBox.setMargin(arrowIcon, new Insets(0, 8, 0, 8)); - - right.getChildren().setAll(valueLabel, arrowIcon); - } - - container.addEventHandler(MouseEvent.MOUSE_CLICKED, event -> { - if (event.getButton() == MouseButton.PRIMARY) { - if (popup == null) { - PopupMenu popupMenu = new PopupMenu(); - this.popup = new JFXPopup(popupMenu); - - container.addEventFilter(ScrollEvent.ANY, ignored -> popup.hide()); - - Bindings.bindContent(popupMenu.getContent(), MappedObservableList.create(itemsProperty(), item -> { - VBox vbox = new VBox(); - - var itemTitleLabel = new Label(); - itemTitleLabel.getStyleClass().add("title"); - itemTitleLabel.textProperty().bind(Bindings.createStringBinding(() -> { - if (item == null) - return ""; - - Function converter = getConverter(); - return converter != null ? converter.apply(item) : Objects.toString(item, ""); - }, converterProperty())); - - var itemSubtitleLabel = new Label(); - itemSubtitleLabel.getStyleClass().add("subtitle"); - itemSubtitleLabel.textProperty().bind(Bindings.createStringBinding(() -> { - Function descriptionConverter = getDescriptionConverter(); - return descriptionConverter != null ? descriptionConverter.apply(item) : ""; - }, descriptionConverterProperty())); - - FXUtils.onChangeAndOperate(itemSubtitleLabel.textProperty(), text -> { - if (text == null || text.isEmpty()) { - vbox.getChildren().setAll(itemTitleLabel); - } else { - vbox.getChildren().setAll(itemTitleLabel, itemSubtitleLabel); - } - }); - - var wrapper = new StackPane(vbox); - wrapper.setAlignment(Pos.CENTER_LEFT); - wrapper.getStyleClass().add("menu-container"); - wrapper.setMouseTransparent(true); - RipplerContainer ripplerContainer = new RipplerContainer(wrapper); - FXUtils.onClicked(ripplerContainer, () -> { - setValue(item); - popup.hide(); - }); - - FXUtils.onChangeAndOperate(valueProperty(), - value -> wrapper.pseudoClassStateChanged(SELECTED_PSEUDO_CLASS, Objects.equals(value, item))); - - return ripplerContainer; - })); - - popup.showingProperty().addListener((observable, oldValue, newValue) -> - container.getRippler().setRipplerDisabled(newValue)); - } - - if (popup.isShowing()) { - popup.hide(); - } else { - JFXPopup.PopupVPosition vPosition = determineOptimalPopupPosition(this, popup); - popup.show(this, vPosition, JFXPopup.PopupHPosition.RIGHT, - 0, - vPosition == JFXPopup.PopupVPosition.TOP ? this.getHeight() : -this.getHeight()); - } - - event.consume(); - } else if (event.getButton() == MouseButton.SECONDARY) { + ripplerContainer.addEventHandler(MouseEvent.MOUSE_CLICKED, event -> { + if (event.getButton() == MouseButton.SECONDARY) { if (popup != null) popup.hide(); - event.consume(); } }); } + @Override + public void fire() { + super.fire(); + if (popup == null) { + PopupMenu popupMenu = new PopupMenu(); + this.popup = new JFXPopup(popupMenu); + + ripplerContainer.addEventFilter(ScrollEvent.ANY, ignored -> popup.hide()); + + Bindings.bindContent(popupMenu.getContent(), MappedObservableList.create(itemsProperty(), item -> { + VBox vbox = new VBox(); + + var itemTitleLabel = new Label(); + itemTitleLabel.getStyleClass().add("title-label"); + itemTitleLabel.textProperty().bind(Bindings.createStringBinding(() -> { + if (item == null) + return ""; + + Function converter = getConverter(); + return converter != null ? converter.apply(item) : Objects.toString(item, ""); + }, converterProperty())); + + var itemSubtitleLabel = new Label(); + itemSubtitleLabel.getStyleClass().add("subtitle-label"); + itemSubtitleLabel.textProperty().bind(Bindings.createStringBinding(() -> { + Function descriptionConverter = getDescriptionConverter(); + return descriptionConverter != null ? descriptionConverter.apply(item) : ""; + }, descriptionConverterProperty())); + + FXUtils.onChangeAndOperate(itemSubtitleLabel.textProperty(), text -> { + if (text == null || text.isEmpty()) { + vbox.getChildren().setAll(itemTitleLabel); + } else { + vbox.getChildren().setAll(itemTitleLabel, itemSubtitleLabel); + } + }); + + var wrapper = new StackPane(vbox); + wrapper.setAlignment(Pos.CENTER_LEFT); + wrapper.getStyleClass().add("menu-container"); + wrapper.setMouseTransparent(true); + RipplerContainer ripplerContainer = new RipplerContainer(wrapper); + FXUtils.onClicked(ripplerContainer, () -> { + setValue(item); + popup.hide(); + }); + + FXUtils.onChangeAndOperate(valueProperty(), + value -> wrapper.pseudoClassStateChanged(SELECTED_PSEUDO_CLASS, Objects.equals(value, item))); + + return ripplerContainer; + })); + + popup.showingProperty().addListener((observable, oldValue, newValue) -> + ripplerContainer.getRippler().setRipplerDisabled(newValue)); + } + + if (popup.isShowing()) { + popup.hide(); + } else { + JFXPopup.PopupVPosition vPosition = determineOptimalPopupPosition(this, popup); + popup.show(this, vPosition, JFXPopup.PopupHPosition.RIGHT, + 0, + vPosition == JFXPopup.PopupVPosition.TOP ? this.getHeight() : -this.getHeight()); + } + } + private final ObjectProperty value = new SimpleObjectProperty<>(this, "value"); public ObjectProperty valueProperty() { @@ -187,9 +172,8 @@ public final class LineSelectButton extends LineButtonBase { private ObjectProperty> descriptionConverter; public ObjectProperty> descriptionConverterProperty() { - if (descriptionConverter == null) { + if (descriptionConverter == null) descriptionConverter = new SimpleObjectProperty<>(this, "descriptionConverter"); - } return descriptionConverter; } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/LineTextPane.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/LineTextPane.java index 29e3d0b25..077e7af3e 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/LineTextPane.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/LineTextPane.java @@ -19,19 +19,16 @@ package org.jackhuang.hmcl.ui.construct; import javafx.beans.property.StringProperty; import javafx.beans.property.StringPropertyBase; -import javafx.geometry.Insets; -import javafx.geometry.Pos; import javafx.scene.control.Label; -import javafx.scene.layout.BorderPane; import org.jackhuang.hmcl.ui.FXUtils; /// @author Glavo -public final class LineTextPane extends LinePane { +public final class LineTextPane extends LineComponent { - private static final String DEFAULT_STYLE_CLASS = "line-label-pane"; + private static final String DEFAULT_STYLE_CLASS = "line-text-pane"; public LineTextPane() { - this.getStyleClass().add(DEFAULT_STYLE_CLASS); + this.getStyleClass().addAll(DEFAULT_STYLE_CLASS); } private StringProperty text; @@ -39,8 +36,6 @@ public final class LineTextPane extends LinePane { public StringProperty textProperty() { if (text == null) { text = new StringPropertyBase() { - private static final Insets LABEL_MARGIN = new Insets(0, 8, 0, 16); - private Label rightLabel; @Override @@ -56,19 +51,18 @@ public final class LineTextPane extends LinePane { @Override protected void invalidated() { String text = get(); - if (text == null || text.isEmpty()) { - if (rightLabel != null) - rightLabel.setText(null); - LineTextPane.this.setRight(null); - } else { + if (text != null && !text.isEmpty()) { if (rightLabel == null) { rightLabel = FXUtils.newSafeTruncatedLabel(); FXUtils.copyOnDoubleClick(rightLabel); - BorderPane.setMargin(rightLabel, LABEL_MARGIN); - BorderPane.setAlignment(rightLabel, Pos.CENTER_RIGHT); } rightLabel.setText(text); - LineTextPane.this.setRight(rightLabel); + setNode(IDX_TRAILING, rightLabel); + } else { + if (rightLabel != null) + rightLabel.setText(null); + + setNode(IDX_TRAILING, null); } } }; diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/LineToggleButton.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/LineToggleButton.java index 51bbc0ce1..91c1c459f 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/LineToggleButton.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/LineToggleButton.java @@ -20,25 +20,27 @@ package org.jackhuang.hmcl.ui.construct; import com.jfoenix.controls.JFXToggleButton; import javafx.beans.property.BooleanProperty; import javafx.beans.property.SimpleBooleanProperty; -import javafx.geometry.Pos; -import javafx.scene.layout.BorderPane; import org.jackhuang.hmcl.ui.FXUtils; public final class LineToggleButton extends LineButtonBase { private static final String DEFAULT_STYLE_CLASS = "line-toggle-button"; + private final JFXToggleButton toggleButton; + public LineToggleButton() { this.getStyleClass().add(DEFAULT_STYLE_CLASS); - JFXToggleButton toggleButton = new JFXToggleButton(); + this.toggleButton = new JFXToggleButton(); toggleButton.selectedProperty().bindBidirectional(selectedProperty()); toggleButton.setSize(8); FXUtils.setLimitHeight(toggleButton, 30); + setNode(IDX_TRAILING, toggleButton); + } - BorderPane.setAlignment(toggleButton, Pos.CENTER); - root.setRight(toggleButton); - - FXUtils.onClicked(container, toggleButton::fire); + @Override + public void fire() { + toggleButton.fire(); + super.fire(); } private final BooleanProperty selected = new SimpleBooleanProperty(this, "selected"); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/JavaInstallPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/JavaInstallPage.java index 2f34afb02..91c335907 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/JavaInstallPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/JavaInstallPage.java @@ -115,7 +115,6 @@ public final class JavaInstallPage extends WizardSinglePage { nameField = new JFXTextField(); nameField.textProperty().bindBidirectional(control.nameProperty); FXUtils.setLimitWidth(nameField, 200); - BorderPane.setAlignment(nameField, Pos.CENTER_RIGHT); namePane.setRight(nameField); nameField.setValidators( new RequiredValidator(), diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/terracotta/TerracottaControllerPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/terracotta/TerracottaControllerPage.java index cb9055f89..7b1ceb853 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/terracotta/TerracottaControllerPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/terracotta/TerracottaControllerPage.java @@ -151,10 +151,10 @@ public class TerracottaControllerPage extends StackPane { body.setLineSpacing(4); var download = createLargeTitleLineButton(); - download.setLeftIcon(FXUtils.newBuiltinImage("/assets/img/terracotta.png")); + download.setLeading(FXUtils.newBuiltinImage("/assets/img/terracotta.png")); download.setTitle(i18n(String.format("terracotta.status.uninitialized.%s.title", fork))); download.setSubtitle(i18n("terracotta.status.uninitialized.desc")); - download.setRightIcon(SVG.ARROW_FORWARD, ICON_SIZE); + download.setTrailingIcon(SVG.ARROW_FORWARD, ICON_SIZE); download.setOnAction(event -> { TerracottaState.Preparing s = TerracottaManager.download(); if (s != null) { @@ -195,10 +195,10 @@ public class TerracottaControllerPage extends StackPane { flow.setLineSpacing(4); var host = createLargeTitleLineButton(); - host.setLeftIcon(SVG.HOST, ICON_SIZE); + host.setLeading(SVG.HOST, ICON_SIZE); host.setTitle(i18n("terracotta.status.waiting.host.title")); host.setSubtitle(i18n("terracotta.status.waiting.host.desc")); - host.setRightIcon(SVG.ARROW_FORWARD, ICON_SIZE); + host.setTrailingIcon(SVG.ARROW_FORWARD, ICON_SIZE); host.setOnAction(event -> { if (LauncherHelper.countMangedProcesses() >= 1) { TerracottaState.HostScanning s1 = TerracottaManager.setScanning(); @@ -227,10 +227,10 @@ public class TerracottaControllerPage extends StackPane { }); var guest = createLargeTitleLineButton(); - guest.setLeftIcon(SVG.ADD_CIRCLE, ICON_SIZE); + guest.setLeading(SVG.ADD_CIRCLE, ICON_SIZE); guest.setTitle(i18n("terracotta.status.waiting.guest.title")); guest.setSubtitle(i18n("terracotta.status.waiting.guest.desc")); - guest.setRightIcon(SVG.ARROW_FORWARD, ICON_SIZE); + guest.setTrailingIcon(SVG.ARROW_FORWARD, ICON_SIZE); guest.setOnAction(event -> { Controllers.prompt(i18n("terracotta.status.waiting.guest.prompt.title"), (code, handler) -> { Task task = TerracottaManager.setGuesting(code); @@ -251,10 +251,10 @@ public class TerracottaControllerPage extends StackPane { if (ThreadLocalRandom.current().nextDouble() < 0.02D) { var feedback = createLargeTitleLineButton(); - feedback.setLeftIcon(SVG.FEEDBACK, ICON_SIZE); + feedback.setLeading(SVG.FEEDBACK, ICON_SIZE); feedback.setTitle(i18n("terracotta.feedback.title")); feedback.setSubtitle(i18n("terracotta.feedback.desc")); - feedback.setRightIcon(SVG.OPEN_IN_NEW, ICON_SIZE); + feedback.setTrailingIcon(SVG.OPEN_IN_NEW, ICON_SIZE); FXUtils.onClicked(feedback, () -> FXUtils.openLink(TerracottaMetadata.FEEDBACK_LINK)); nodesProperty.setAll(flow, host, guest, feedback); @@ -270,7 +270,7 @@ public class TerracottaControllerPage extends StackPane { body.setLineSpacing(4); var room = createLargeTitleLineButton(); - room.setLeftIcon(SVG.ARROW_BACK, ICON_SIZE); + room.setLeading(SVG.ARROW_BACK, ICON_SIZE); room.setTitle(i18n("terracotta.back")); room.setSubtitle(i18n("terracotta.status.scanning.back")); room.setOnAction(event -> { @@ -286,7 +286,7 @@ public class TerracottaControllerPage extends StackPane { progressProperty.set(-1); var room = createLargeTitleLineButton(); - room.setLeftIcon(SVG.ARROW_BACK, ICON_SIZE); + room.setLeading(SVG.ARROW_BACK, ICON_SIZE); room.setTitle(i18n("terracotta.back")); room.setSubtitle(i18n("terracotta.status.host_starting.back")); room.setOnAction(event -> { @@ -330,13 +330,13 @@ public class TerracottaControllerPage extends StackPane { FXUtils.onClicked(code, () -> copyCode(cs)); var copy = createLargeTitleLineButton(); - copy.setLeftIcon(SVG.CONTENT_COPY, ICON_SIZE); + copy.setLeading(SVG.CONTENT_COPY, ICON_SIZE); copy.setTitle(i18n("terracotta.status.host_ok.code.copy")); copy.setSubtitle(i18n("terracotta.status.host_ok.code.desc")); FXUtils.onClicked(copy, () -> copyCode(cs)); var back = createLargeTitleLineButton(); - back.setLeftIcon(SVG.ARROW_BACK, ICON_SIZE); + back.setLeading(SVG.ARROW_BACK, ICON_SIZE); back.setTitle(i18n("terracotta.back")); back.setSubtitle(i18n("terracotta.status.host_ok.back")); back.setOnAction(event -> { @@ -357,7 +357,7 @@ public class TerracottaControllerPage extends StackPane { progressProperty.set(-1); var room = createLargeTitleLineButton(); - room.setLeftIcon(SVG.ARROW_BACK, ICON_SIZE); + room.setLeading(SVG.ARROW_BACK, ICON_SIZE); room.setTitle(i18n("terracotta.back")); room.setSubtitle(i18n("terracotta.status.guest_starting.back")); room.setOnAction(event -> { @@ -372,7 +372,7 @@ public class TerracottaControllerPage extends StackPane { TerracottaState.GuestStarting.Difficulty difficulty = ((TerracottaState.GuestStarting) state).getDifficulty(); if (difficulty != null && difficulty != TerracottaState.GuestStarting.Difficulty.UNKNOWN) { var info = createLargeTitleLineButton(); - info.setLeftIcon(switch (difficulty) { + info.setLeading(switch (difficulty) { case UNKNOWN -> throw new AssertionError(); case EASIEST, SIMPLE -> SVG.INFO; case MEDIUM, TOUGH -> SVG.WARNING; @@ -404,7 +404,7 @@ public class TerracottaControllerPage extends StackPane { tutorial.setSubtitle(i18n("terracotta.status.guest_ok.desc", guestOK.getUrl())); var back = createLargeTitleLineButton(); - back.setLeftIcon(SVG.ARROW_BACK, ICON_SIZE); + back.setLeading(SVG.ARROW_BACK, ICON_SIZE); back.setTitle(i18n("terracotta.back")); back.setSubtitle(i18n("terracotta.status.guest_ok.back")); back.setOnAction(event -> { @@ -426,7 +426,7 @@ public class TerracottaControllerPage extends StackPane { nodesProperty.setAll(); var back = createLargeTitleLineButton(); - back.setLeftIcon(SVG.ARROW_BACK, ICON_SIZE); + back.setLeading(SVG.ARROW_BACK, ICON_SIZE); back.setTitle(i18n("terracotta.back")); back.setSubtitle(i18n("terracotta.status.exception.back")); back.setOnAction(event -> { @@ -438,7 +438,7 @@ public class TerracottaControllerPage extends StackPane { SpinnerPane exportLog = new SpinnerPane(); var exportLogInner = createLargeTitleLineButton(); - exportLogInner.setLeftIcon(SVG.OUTPUT, ICON_SIZE); + exportLogInner.setLeading(SVG.OUTPUT, ICON_SIZE); exportLogInner.setTitle(i18n("terracotta.export_log")); exportLogInner.setSubtitle(i18n("terracotta.export_log.desc")); exportLog.setContent(exportLogInner); @@ -481,7 +481,7 @@ public class TerracottaControllerPage extends StackPane { if (fatal.isRecoverable()) { var retry = createLargeTitleLineButton(); - retry.setLeftIcon(SVG.RESTORE, ICON_SIZE); + retry.setLeading(SVG.RESTORE, ICON_SIZE); retry.setTitle(i18n("terracotta.status.fatal.retry")); retry.setSubtitle(message); retry.setOnAction(event -> { @@ -552,17 +552,16 @@ public class TerracottaControllerPage extends StackPane { var header = new LinePane(); header.setLargeTitle(true); - header.setPadding(Insets.EMPTY); header.setMinHeight(LinePane.USE_COMPUTED_SIZE); header.setMouseTransparent(true); - header.setLeftIcon(FXUtils.newBuiltinImage("/assets/img/terracotta.png")); + header.setLeading(FXUtils.newBuiltinImage("/assets/img/terracotta.png")); header.setTitle(i18n("terracotta.from_local.title")); header.setSubtitle(i18n("terracotta.from_local.desc")); locals.setHeaderLeft(header); for (TerracottaMetadata.Link link : TerracottaMetadata.PACKAGE_LINKS) { LineButton item = new LineButton(); - item.setRightIcon(SVG.OPEN_IN_NEW); + item.setTrailingIcon(SVG.OPEN_IN_NEW); item.setTitle(link.description().getText(I18n.getLocale().getCandidateLocales())); item.setOnAction(event -> Controllers.dialog( i18n("terracotta.from_local.guide", TerracottaMetadata.PACKAGE_NAME), diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/WorldInfoPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/WorldInfoPage.java index 52e3216b6..d638f445a 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/WorldInfoPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/WorldInfoPage.java @@ -31,7 +31,6 @@ import javafx.scene.control.ScrollPane; import javafx.scene.effect.BoxBlur; import javafx.scene.image.Image; import javafx.scene.image.ImageView; -import javafx.scene.layout.BorderPane; import javafx.scene.layout.HBox; import javafx.scene.layout.StackPane; import javafx.scene.layout.VBox; @@ -202,7 +201,6 @@ public final class WorldInfoPage extends SpinnerPane implements WorldManagePage. HBox right = new HBox(8); { right.setAlignment(Pos.CENTER_RIGHT); - BorderPane.setAlignment(right, Pos.CENTER_RIGHT); right.getChildren().setAll(visibilityButton, seedLabel); seedPane.setRight(right); } @@ -410,9 +408,9 @@ public final class WorldInfoPage extends SpinnerPane implements WorldManagePage. } } - private void setRightTextField(BorderPane borderPane, int perfWidth, Tag tag) { + private void setRightTextField(LinePane linePane, int perfWidth, Tag tag) { JFXTextField textField = new JFXTextField(); - setRightTextField(borderPane, textField, perfWidth); + setRightTextField(linePane, textField, perfWidth); if (tag instanceof IntTag intTag) { bindTagAndTextField(intTag, textField); } else if (tag instanceof FloatTag floatTag) { @@ -422,11 +420,10 @@ public final class WorldInfoPage extends SpinnerPane implements WorldManagePage. } } - private void setRightTextField(BorderPane borderPane, JFXTextField textField, int perfWidth) { + private void setRightTextField(LinePane linePane, JFXTextField textField, int perfWidth) { textField.setDisable(isReadOnly); textField.setPrefWidth(perfWidth); - BorderPane.setAlignment(textField, Pos.CENTER_RIGHT); - borderPane.setRight(textField); + linePane.setRight(textField); } private void bindTagAndToggleButton(Tag tag, LineToggleButton toggleButton) { diff --git a/HMCL/src/main/resources/assets/css/root.css b/HMCL/src/main/resources/assets/css/root.css index 5f695da04..48dfa7ed8 100644 --- a/HMCL/src/main/resources/assets/css/root.css +++ b/HMCL/src/main/resources/assets/css/root.css @@ -1041,6 +1041,10 @@ -fx-font-size: 12; } +.options-list-item > .line-component .line-component-container { + -fx-padding: 10 16 10 16; +} + .options-list-item .svg { -fx-fill: -monet-on-surface; -fx-border-color: -monet-outline-variant; @@ -1076,6 +1080,10 @@ -fx-border-width: 0; } +.options-sublist-wrapper .expand-icon .svg { + -fx-fill: -monet-on-surface-variant; +} + /******************************************************************************* * * * JFX Toggle Button * @@ -1103,15 +1111,16 @@ .jfx-toggle-button Line { -fx-stroke: -jfx-untoggle-line-color; } -.jfx-toggle-button:selected Line{ + +.jfx-toggle-button:selected Line { -fx-stroke: -jfx-toggle-line-color; } -.jfx-toggle-button Circle{ +.jfx-toggle-button Circle { -fx-fill: -jfx-untoggle-color; } -.jfx-toggle-button:selected Circle{ +.jfx-toggle-button:selected Circle { -fx-fill: -jfx-toggle-color; } @@ -1864,47 +1873,39 @@ * * ******************************************************************************/ -.line-component .title { - -fx-text-fill: -monet-on-surface; -} - -.line-component:large-title .title { +.line-component:large-title .title-label { -fx-font-size: 15px; } -.line-component .subtitle { - -fx-text-fill: -monet-on-surface-variant; -} - -.line-button .svg { - -fx-opacity: 1; -} - .line-button .svg:disabled { -fx-opacity: 0.4; } -.line-select-button .svg { - -fx-opacity: 1; -} - -.line-select-button .svg:disabled { - -fx-opacity: 0.4; -} - -.line-select-button .menu-container .title { - -fx-font-size: 13px; - -fx-text-fill: -monet-on-surface; -} - -.line-select-button .menu-container:selected .title { - -fx-text-fill: -monet-primary; -} - -.line-select-button .menu-container .subtitle { +.line-button .trailing-label { -fx-text-fill: -monet-on-surface-variant; } -.line-select-button .menu-container:selected .subtitle { +.line-button .trailing-icon .svg { + -fx-fill: -monet-on-surface-variant; + -fx-opacity: 1; +} + +.line-button .trailing-icon .svg:disabled { + -fx-opacity: 0.4; +} + +.line-select-button .menu-container .title-label { + -fx-font-size: 13px; +} + +.line-select-button .menu-container:selected .title-label { -fx-text-fill: -monet-primary; +} + +.line-select-button .menu-container:selected .subtitle-label { + -fx-text-fill: -monet-primary; +} + +.line-toggle-button .jfx-toggle-button { + -fx-padding: 0; } \ No newline at end of file