diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/SettingsView.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/SettingsView.java index 6638a61e8..a719a0d45 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/SettingsView.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/SettingsView.java @@ -108,7 +108,9 @@ public abstract class SettingsView extends StackPane { sponsorPane.getChildren().setAll(gridPane); settingsPane.getContent().add(sponsorPane); } + } + { ComponentSublist updatePane = new ComponentSublist(); updatePane.setTitle(i18n("update")); updatePane.setHasSubtitle(true); @@ -152,7 +154,7 @@ public abstract class SettingsView extends StackPane { } { - BorderPane updatePane = new BorderPane(); + BorderPane docPane = new BorderPane(); { VBox headerLeft = new VBox(); @@ -161,7 +163,7 @@ public abstract class SettingsView extends StackPane { helpSubtitle.getStyleClass().add("subtitle-label"); headerLeft.getChildren().setAll(help, helpSubtitle); - updatePane.setLeft(headerLeft); + docPane.setLeft(headerLeft); } { @@ -170,9 +172,9 @@ public abstract class SettingsView extends StackPane { btnExternal.getStyleClass().add("toggle-icon4"); btnExternal.setGraphic(SVG.openInNew(Theme.blackFillBinding(), -1, -1)); - updatePane.setRight(btnExternal); + docPane.setRight(btnExternal); } - settingsPane.getContent().add(updatePane); + settingsPane.getContent().add(docPane); } { diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/ComponentList.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/ComponentList.java index b5522ef18..01c8e59af 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/ComponentList.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/ComponentList.java @@ -34,6 +34,8 @@ import javafx.scene.control.Control; import javafx.scene.control.SkinBase; import javafx.scene.layout.VBox; +import java.util.function.Consumer; + @DefaultProperty("content") public class ComponentList extends Control { private final StringProperty title = new SimpleStringProperty(this, "title", "Group"); @@ -41,6 +43,8 @@ public class ComponentList extends Control { private final IntegerProperty depth = new SimpleIntegerProperty(this, "depth", 0); private boolean hasSubtitle = false; public final ObservableList content = FXCollections.observableArrayList(); + private boolean expanded = false; + private Consumer lazyInitializer; public ComponentList() { getStyleClass().add("options-list"); @@ -94,6 +98,18 @@ public class ComponentList extends Control { return content; } + public void setLazyInitializer(Consumer lazyInitializer) { + this.lazyInitializer = lazyInitializer; + } + + public void onExpand() { + if (!expanded && lazyInitializer != null) { + lazyInitializer.accept(this); + } + + expanded = true; + } + @Override protected javafx.scene.control.Skin createDefaultSkin() { return new Skin(this); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/ComponentListCell.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/ComponentListCell.java index a862992a9..059919a93 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/ComponentListCell.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/ComponentListCell.java @@ -143,6 +143,7 @@ class ComponentListCell extends StackPane { if (isExpanded()) { updateClip(newHeight); + list.onExpand(); } expandAnimation = new Timeline(new KeyFrame(new Duration(320.0), @@ -161,8 +162,9 @@ class ComponentListCell extends StackPane { expandIcon.setRotate(newValue ? 180 : 0)); getChildren().setAll(groupNode); - } else + } else { getChildren().setAll(content); + } } public boolean isExpanded() { diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/Decorator.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/Decorator.java index cd15cf249..c9f35cc7d 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/Decorator.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/Decorator.java @@ -41,7 +41,6 @@ public class Decorator extends Control { private final ObjectProperty> onCloseNavButtonAction = new SimpleObjectProperty<>(); private final ObjectProperty> onBackNavButtonAction = new SimpleObjectProperty<>(); private final ObjectProperty> onRefreshNavButtonAction = new SimpleObjectProperty<>(); - private final BooleanProperty closeNavButtonVisible = new SimpleBooleanProperty(true); private final BooleanProperty canRefresh = new SimpleBooleanProperty(false); private final BooleanProperty canBack = new SimpleBooleanProperty(false); private final BooleanProperty canClose = new SimpleBooleanProperty(false); @@ -127,18 +126,6 @@ public class Decorator extends Control { this.onCloseButtonAction.set(onCloseButtonAction); } - public boolean isCloseNavButtonVisible() { - return closeNavButtonVisible.get(); - } - - public BooleanProperty closeNavButtonVisibleProperty() { - return closeNavButtonVisible; - } - - public void setCloseNavButtonVisible(boolean closeNavButtonVisible) { - this.closeNavButtonVisible.set(closeNavButtonVisible); - } - public ObservableList getContainer() { return container.get(); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorSkin.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorSkin.java index 3687eb9cc..16d9354ff 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorSkin.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorSkin.java @@ -44,9 +44,6 @@ public class DecoratorSkin extends SkinBase { private final BorderPane titleContainer; private final StackPane contentPlaceHolder; - private final JFXButton refreshNavButton; - private final JFXButton closeNavButton; - private final HBox navLeft; private final Stage primaryStage; private double xOffset, yOffset, newX, newY, initX, initY; @@ -152,74 +149,13 @@ public class DecoratorSkin extends SkinBase { rectangle.heightProperty().bind(titleContainer.heightProperty().add(100)); titleContainer.setClip(rectangle); { - BorderPane navBar = new BorderPane(); - { - navLeft = new HBox(); - navLeft.setAlignment(Pos.CENTER_LEFT); - navLeft.setPadding(new Insets(0, 5, 0, 5)); - { - JFXButton backNavButton = new JFXButton(); - backNavButton.setGraphic(SVG.back(Theme.foregroundFillBinding(), -1, -1)); - backNavButton.getStyleClass().add("jfx-decorator-button"); - backNavButton.ripplerFillProperty().bind(Theme.whiteFillBinding()); - backNavButton.onActionProperty().bind(skinnable.onBackNavButtonActionProperty()); - backNavButton.visibleProperty().bind(skinnable.canBackProperty()); - - closeNavButton = new JFXButton(); - closeNavButton.setGraphic(SVG.close(Theme.foregroundFillBinding(), -1, -1)); - closeNavButton.getStyleClass().add("jfx-decorator-button"); - closeNavButton.ripplerFillProperty().bind(Theme.whiteFillBinding()); - closeNavButton.onActionProperty().bind(skinnable.onCloseNavButtonActionProperty()); - - FXUtils.onChangeAndOperate(skinnable.canBackProperty(), (newValue) -> { - navLeft.getChildren().remove(backNavButton); - if (newValue) navLeft.getChildren().add(0, backNavButton); - }); - FXUtils.onChangeAndOperate(skinnable.canCloseProperty(), (newValue) -> { - navLeft.getChildren().remove(closeNavButton); - if (newValue) navLeft.getChildren().add(closeNavButton); - }); - - FXUtils.onChangeAndOperate(skinnable.showCloseAsHomeProperty(), (newValue) -> { - if (newValue) - closeNavButton.setGraphic(SVG.home(Theme.foregroundFillBinding(), -1, -1)); - else - closeNavButton.setGraphic(SVG.close(Theme.foregroundFillBinding(), -1, -1)); - }); - } - navBar.setLeft(navLeft); - - VBox navCenter = new VBox(); - navCenter.setAlignment(Pos.CENTER_LEFT); - Label titleLabel = new Label(); - titleLabel.getStyleClass().add("jfx-decorator-title"); - titleLabel.textProperty().bind(skinnable.drawerTitleProperty()); - navCenter.getChildren().setAll(titleLabel); - navBar.setCenter(navCenter); - - HBox navRight = new HBox(); - navRight.setAlignment(Pos.CENTER_RIGHT); - refreshNavButton = new JFXButton(); - refreshNavButton.setGraphic(SVG.refresh(Theme.foregroundFillBinding(), -1, -1)); - refreshNavButton.getStyleClass().add("jfx-decorator-button"); - refreshNavButton.ripplerFillProperty().bind(Theme.whiteFillBinding()); - refreshNavButton.onActionProperty().bind(skinnable.onRefreshNavButtonActionProperty()); - refreshNavButton.visibleProperty().bind(skinnable.canRefreshProperty()); - navRight.getChildren().setAll(refreshNavButton); - navBar.setRight(navRight); - } - titleContainer.setCenter(navBar); + titleContainer.setCenter(createNavBar(skinnable)); HBox buttonsContainer = new HBox(); buttonsContainer.setStyle("-fx-background-color: transparent;"); buttonsContainer.setAlignment(Pos.CENTER_RIGHT); buttonsContainer.setPadding(new Insets(4)); { - Rectangle separator = new Rectangle(); - separator.visibleProperty().bind(refreshNavButton.visibleProperty()); - separator.heightProperty().bind(navBar.heightProperty()); - separator.setFill(Color.GRAY); - JFXButton btnMin = new JFXButton(); StackPane pane = new StackPane(minus); pane.setAlignment(Pos.CENTER); @@ -232,18 +168,79 @@ public class DecoratorSkin extends SkinBase { btnClose.getStyleClass().add("jfx-decorator-button"); btnClose.setOnAction(e -> skinnable.close()); - buttonsContainer.getChildren().setAll(separator, btnMin, btnClose); + buttonsContainer.getChildren().setAll(btnMin, btnClose); } titleContainer.setRight(buttonsContainer); } root.setTop(titleContainer); getChildren().setAll(root); + } - getSkinnable().closeNavButtonVisibleProperty().addListener((a, b, newValue) -> { - if (newValue) navLeft.getChildren().add(closeNavButton); - else navLeft.getChildren().remove(closeNavButton); - }); + private Node createNavBar(Decorator skinnable) { + BorderPane navBar = new BorderPane(); + { + HBox navLeft = new HBox(); + navLeft.setAlignment(Pos.CENTER_LEFT); + navLeft.setPadding(new Insets(0, 5, 0, 5)); + { + JFXButton backNavButton = new JFXButton(); + backNavButton.setGraphic(SVG.back(Theme.foregroundFillBinding(), -1, -1)); + backNavButton.getStyleClass().add("jfx-decorator-button"); + backNavButton.ripplerFillProperty().bind(Theme.whiteFillBinding()); + backNavButton.onActionProperty().bind(skinnable.onBackNavButtonActionProperty()); + backNavButton.visibleProperty().bind(skinnable.canBackProperty()); + + JFXButton closeNavButton = new JFXButton(); + closeNavButton.setGraphic(SVG.close(Theme.foregroundFillBinding(), -1, -1)); + closeNavButton.getStyleClass().add("jfx-decorator-button"); + closeNavButton.ripplerFillProperty().bind(Theme.whiteFillBinding()); + closeNavButton.onActionProperty().bind(skinnable.onCloseNavButtonActionProperty()); + + FXUtils.onChangeAndOperate(skinnable.canBackProperty(), (newValue) -> { + navLeft.getChildren().remove(backNavButton); + if (newValue) navLeft.getChildren().add(0, backNavButton); + }); + FXUtils.onChangeAndOperate(skinnable.canCloseProperty(), (newValue) -> { + navLeft.getChildren().remove(closeNavButton); + if (newValue) navLeft.getChildren().add(closeNavButton); + }); + + FXUtils.onChangeAndOperate(skinnable.showCloseAsHomeProperty(), (newValue) -> { + if (newValue) + closeNavButton.setGraphic(SVG.home(Theme.foregroundFillBinding(), -1, -1)); + else + closeNavButton.setGraphic(SVG.close(Theme.foregroundFillBinding(), -1, -1)); + }); + } + navBar.setLeft(navLeft); + + VBox navCenter = new VBox(); + navCenter.setAlignment(Pos.CENTER_LEFT); + Label titleLabel = new Label(); + titleLabel.getStyleClass().add("jfx-decorator-title"); + titleLabel.textProperty().bind(skinnable.drawerTitleProperty()); + navCenter.getChildren().setAll(titleLabel); + navBar.setCenter(navCenter); + + HBox navRight = new HBox(); + navRight.setAlignment(Pos.CENTER_RIGHT); + JFXButton refreshNavButton = new JFXButton(); + refreshNavButton.setGraphic(SVG.refresh(Theme.foregroundFillBinding(), -1, -1)); + refreshNavButton.getStyleClass().add("jfx-decorator-button"); + refreshNavButton.ripplerFillProperty().bind(Theme.whiteFillBinding()); + refreshNavButton.onActionProperty().bind(skinnable.onRefreshNavButtonActionProperty()); + refreshNavButton.visibleProperty().bind(skinnable.canRefreshProperty()); + + Rectangle separator = new Rectangle(); + separator.visibleProperty().bind(refreshNavButton.visibleProperty()); + separator.heightProperty().bind(navBar.heightProperty()); + separator.setFill(Color.GRAY); + + navRight.getChildren().setAll(refreshNavButton, separator); + navBar.setRight(navRight); + } + return navBar; } private void updateInitMouseValues(MouseEvent mouseEvent) {