mirror of
https://github.com/HMCL-dev/HMCL.git
synced 2025-02-05 16:44:47 +08:00
add: animation at title bar
This commit is contained in:
parent
334e93196b
commit
fa13b1fc0d
@ -101,8 +101,10 @@ public final class FXUtils {
|
||||
value.addListener((a, b, c) -> consumer.accept(c));
|
||||
}
|
||||
|
||||
public static <T> void onWeakChange(ObservableValue<T> value, Consumer<T> consumer) {
|
||||
value.addListener(new WeakChangeListener<>((a, b, c) -> consumer.accept(c)));
|
||||
public static <T> WeakChangeListener<T> onWeakChange(ObservableValue<T> value, Consumer<T> consumer) {
|
||||
WeakChangeListener<T> listener = new WeakChangeListener<>((a, b, c) -> consumer.accept(c));
|
||||
value.addListener(listener);
|
||||
return listener;
|
||||
}
|
||||
|
||||
public static <T> void onChangeAndOperate(ObservableValue<T> value, Consumer<T> consumer) {
|
||||
@ -110,9 +112,9 @@ public final class FXUtils {
|
||||
onChange(value, consumer);
|
||||
}
|
||||
|
||||
public static <T> void onWeakChangeAndOperate(ObservableValue<T> value, Consumer<T> consumer) {
|
||||
public static <T> WeakChangeListener<T> onWeakChangeAndOperate(ObservableValue<T> value, Consumer<T> consumer) {
|
||||
consumer.accept(value.getValue());
|
||||
onWeakChange(value, consumer);
|
||||
return onWeakChange(value, consumer);
|
||||
}
|
||||
|
||||
public static void runLaterIf(BooleanSupplier condition, Runnable runnable) {
|
||||
|
@ -24,11 +24,12 @@ import org.jackhuang.hmcl.ui.Controllers;
|
||||
import org.jackhuang.hmcl.ui.ListPage;
|
||||
import org.jackhuang.hmcl.ui.decorator.DecoratorPage;
|
||||
import org.jackhuang.hmcl.util.javafx.MappedObservableList;
|
||||
|
||||
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
||||
import static org.jackhuang.hmcl.util.javafx.ExtendedProperties.createSelectedItemPropertyFor;
|
||||
|
||||
public class AccountList extends ListPage<AccountListItem> implements DecoratorPage {
|
||||
private final ReadOnlyStringWrapper title = new ReadOnlyStringWrapper(this, "title", i18n("account.manage"));
|
||||
private final ReadOnlyObjectWrapper<State> state = new ReadOnlyObjectWrapper<>(State.fromTitle(i18n("account.manage")));
|
||||
private final ListProperty<Account> accounts = new SimpleListProperty<>(this, "accounts", FXCollections.observableArrayList());
|
||||
private final ObjectProperty<Account> selectedAccount;
|
||||
|
||||
@ -51,7 +52,7 @@ public class AccountList extends ListPage<AccountListItem> implements DecoratorP
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReadOnlyStringProperty titleProperty() {
|
||||
return title.getReadOnlyProperty();
|
||||
public ReadOnlyObjectProperty<State> stateProperty() {
|
||||
return state.getReadOnlyProperty();
|
||||
}
|
||||
}
|
||||
|
@ -18,8 +18,7 @@
|
||||
package org.jackhuang.hmcl.ui.account;
|
||||
|
||||
import javafx.beans.binding.Bindings;
|
||||
import javafx.beans.property.ReadOnlyStringProperty;
|
||||
import javafx.beans.property.ReadOnlyStringWrapper;
|
||||
import javafx.beans.property.ReadOnlyObjectWrapper;
|
||||
import javafx.collections.ObservableList;
|
||||
import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorServer;
|
||||
import org.jackhuang.hmcl.ui.Controllers;
|
||||
@ -31,7 +30,7 @@ import static org.jackhuang.hmcl.setting.ConfigHolder.config;
|
||||
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
||||
|
||||
public class AuthlibInjectorServersPage extends ListPage<AuthlibInjectorServerItem> implements DecoratorPage {
|
||||
private final ReadOnlyStringWrapper title = new ReadOnlyStringWrapper(this, "title", i18n("account.injector.manage.title"));
|
||||
private final ReadOnlyObjectWrapper<State> state = new ReadOnlyObjectWrapper<>(State.fromTitle(i18n("account.injector.manage.title")));
|
||||
|
||||
private final ObservableList<AuthlibInjectorServerItem> serverItems;
|
||||
|
||||
@ -50,16 +49,8 @@ public class AuthlibInjectorServersPage extends ListPage<AuthlibInjectorServerIt
|
||||
Controllers.dialog(new AddAuthlibInjectorServerPane());
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReadOnlyStringProperty titleProperty() {
|
||||
return title.getReadOnlyProperty();
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title.set(title);
|
||||
public ReadOnlyObjectWrapper<State> stateProperty() {
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
@ -71,7 +71,6 @@ public class Navigator extends TransitionPane {
|
||||
setContent(node, animationProducer);
|
||||
|
||||
NavigationEvent navigated = new NavigationEvent(this, node, NavigationEvent.NAVIGATED);
|
||||
fireEvent(navigated);
|
||||
node.fireEvent(navigated);
|
||||
|
||||
EventHandler<PageCloseEvent> handler = event -> close(node);
|
||||
@ -118,7 +117,6 @@ public class Navigator extends TransitionPane {
|
||||
}
|
||||
|
||||
NavigationEvent navigated = new NavigationEvent(this, node, NavigationEvent.NAVIGATED);
|
||||
fireEvent(navigated);
|
||||
node.fireEvent(navigated);
|
||||
|
||||
Optional.ofNullable(from.getProperties().get(PROPERTY_DIALOG_CLOSE_HANDLER))
|
||||
|
@ -35,7 +35,7 @@ public class Decorator extends Control {
|
||||
private final ListProperty<Node> content = new SimpleListProperty<>(FXCollections.observableArrayList());
|
||||
private final ListProperty<Node> container = new SimpleListProperty<>(FXCollections.observableArrayList());
|
||||
private final ObjectProperty<Background> contentBackground = new SimpleObjectProperty<>();
|
||||
private final StringProperty title = new SimpleStringProperty();
|
||||
private final ObjectProperty<DecoratorPage.State> state = new SimpleObjectProperty<>();
|
||||
private final StringProperty drawerTitle = new SimpleStringProperty();
|
||||
private final ObjectProperty<Runnable> onCloseButtonAction = new SimpleObjectProperty<>();
|
||||
private final ObjectProperty<EventHandler<ActionEvent>> onCloseNavButtonAction = new SimpleObjectProperty<>();
|
||||
@ -90,16 +90,16 @@ public class Decorator extends Control {
|
||||
this.content.set(content);
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title.get();
|
||||
public DecoratorPage.State getState() {
|
||||
return state.get();
|
||||
}
|
||||
|
||||
public StringProperty titleProperty() {
|
||||
return title;
|
||||
public ObjectProperty<DecoratorPage.State> stateProperty() {
|
||||
return state;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title.set(title);
|
||||
public void setState(DecoratorPage.State state) {
|
||||
this.state.set(state);
|
||||
}
|
||||
|
||||
public String getDrawerTitle() {
|
||||
|
@ -71,14 +71,11 @@ public class DecoratorController {
|
||||
private final Decorator decorator;
|
||||
private final ImageView welcomeView;
|
||||
private final Navigator navigator;
|
||||
private final Node mainPage;
|
||||
|
||||
private JFXDialog dialog;
|
||||
private StackContainerPane dialogPane;
|
||||
|
||||
public DecoratorController(Stage stage, Node mainPage) {
|
||||
this.mainPage = mainPage;
|
||||
|
||||
decorator = new Decorator(stage);
|
||||
decorator.setOnCloseButtonAction(Launcher::stopApplication);
|
||||
|
||||
@ -269,16 +266,12 @@ public class DecoratorController {
|
||||
}
|
||||
|
||||
if (to instanceof DecoratorPage) {
|
||||
decorator.drawerTitleProperty().bind(((DecoratorPage) to).titleProperty());
|
||||
decorator.showCloseAsHomeProperty().set(!((DecoratorPage) to).isPageCloseable());
|
||||
decorator.canBackProperty().bind(Bindings.createBooleanBinding(() -> navigator.canGoBack() || ((DecoratorPage) to).backableProperty().get(),
|
||||
((DecoratorPage) to).backableProperty()));
|
||||
decorator.stateProperty().bind(((DecoratorPage) to).stateProperty());
|
||||
} else {
|
||||
decorator.drawerTitleProperty().unbind();
|
||||
decorator.drawerTitleProperty().set("");
|
||||
decorator.showCloseAsHomeProperty().set(true);
|
||||
decorator.canBackProperty().unbind();
|
||||
decorator.canBackProperty().setValue(navigator.canGoBack());
|
||||
decorator.stateProperty().unbind();
|
||||
decorator.stateProperty().set(new DecoratorPage.State("", null, navigator.canGoBack(), false, true));
|
||||
}
|
||||
|
||||
decorator.canCloseProperty().set(navigator.canGoBack());
|
||||
|
@ -17,6 +17,7 @@
|
||||
*/
|
||||
package org.jackhuang.hmcl.ui.decorator;
|
||||
|
||||
import javafx.beans.binding.Bindings;
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.layout.Region;
|
||||
import javafx.scene.layout.StackPane;
|
||||
@ -35,7 +36,6 @@ public abstract class DecoratorNavigatorPage extends DecoratorTransitionPage {
|
||||
@Override
|
||||
protected void navigate(Node page, AnimationProducer animationProducer) {
|
||||
navigator.navigate(page, animationProducer);
|
||||
setRefreshable(page instanceof Refreshable);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -68,14 +68,15 @@ public abstract class DecoratorNavigatorPage extends DecoratorTransitionPage {
|
||||
}
|
||||
|
||||
if (to instanceof DecoratorPage) {
|
||||
titleProperty().bind(((DecoratorPage) to).titleProperty());
|
||||
state.bind(Bindings.createObjectBinding(() -> {
|
||||
State state = ((DecoratorPage) to).stateProperty().get();
|
||||
return new State(state.getTitle(), state.getTitleNode(), navigator.canGoBack(), state.isRefreshable(), true);
|
||||
}, ((DecoratorPage) to).stateProperty()));
|
||||
} else {
|
||||
titleProperty().unbind();
|
||||
titleProperty().set("");
|
||||
state.unbind();
|
||||
state.set(new State("", null, navigator.canGoBack(), false, true));
|
||||
}
|
||||
|
||||
setBackable(navigator.canGoBack());
|
||||
|
||||
if (to instanceof Region) {
|
||||
Region region = (Region) to;
|
||||
// Let root pane fix window size.
|
||||
|
@ -17,14 +17,13 @@
|
||||
*/
|
||||
package org.jackhuang.hmcl.ui.decorator;
|
||||
|
||||
import javafx.beans.property.BooleanProperty;
|
||||
import javafx.beans.property.ReadOnlyStringProperty;
|
||||
import javafx.beans.property.SimpleBooleanProperty;
|
||||
import javafx.beans.property.ReadOnlyObjectProperty;
|
||||
import javafx.scene.Node;
|
||||
import org.jackhuang.hmcl.ui.construct.Navigator;
|
||||
import org.jackhuang.hmcl.ui.wizard.Refreshable;
|
||||
|
||||
public interface DecoratorPage {
|
||||
ReadOnlyStringProperty titleProperty();
|
||||
public interface DecoratorPage extends Refreshable {
|
||||
ReadOnlyObjectProperty<State> stateProperty();
|
||||
|
||||
default boolean isPageCloseable() {
|
||||
return false;
|
||||
@ -34,8 +33,8 @@ public interface DecoratorPage {
|
||||
return true;
|
||||
}
|
||||
|
||||
default BooleanProperty backableProperty() {
|
||||
return new SimpleBooleanProperty(true);
|
||||
@Override
|
||||
default void refresh() {
|
||||
}
|
||||
|
||||
default void closePage() {
|
||||
@ -44,4 +43,48 @@ public interface DecoratorPage {
|
||||
default void onDecoratorPageNavigating(Navigator.NavigationEvent event) {
|
||||
((Node) this).getStyleClass().add("content-background");
|
||||
}
|
||||
|
||||
class State {
|
||||
private final String title;
|
||||
private final Node titleNode;
|
||||
private final boolean backable;
|
||||
private final boolean refreshable;
|
||||
private final boolean animate;
|
||||
|
||||
public State(String title, Node titleNode, boolean backable, boolean refreshable, boolean animate) {
|
||||
this.title = title;
|
||||
this.titleNode = titleNode;
|
||||
this.backable = backable;
|
||||
this.refreshable = refreshable;
|
||||
this.animate = animate;
|
||||
}
|
||||
|
||||
public static State fromTitle(String title) {
|
||||
return new State(title, null, true, false, true);
|
||||
}
|
||||
|
||||
public static State fromTitleNode(Node titleNode) {
|
||||
return new State(null, titleNode, true, false, true);
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public Node getTitleNode() {
|
||||
return titleNode;
|
||||
}
|
||||
|
||||
public boolean isBackable() {
|
||||
return backable;
|
||||
}
|
||||
|
||||
public boolean isRefreshable() {
|
||||
return refreshable;
|
||||
}
|
||||
|
||||
public boolean isAnimate() {
|
||||
return animate;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -29,13 +29,18 @@ import javafx.scene.Node;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.SkinBase;
|
||||
import javafx.scene.input.MouseEvent;
|
||||
import javafx.scene.layout.*;
|
||||
import javafx.scene.layout.BorderPane;
|
||||
import javafx.scene.layout.HBox;
|
||||
import javafx.scene.layout.Region;
|
||||
import javafx.scene.layout.StackPane;
|
||||
import javafx.scene.paint.Color;
|
||||
import javafx.scene.shape.Rectangle;
|
||||
import javafx.stage.Stage;
|
||||
import org.jackhuang.hmcl.setting.Theme;
|
||||
import org.jackhuang.hmcl.ui.FXUtils;
|
||||
import org.jackhuang.hmcl.ui.SVG;
|
||||
import org.jackhuang.hmcl.ui.animation.ContainerAnimations;
|
||||
import org.jackhuang.hmcl.ui.animation.TransitionPane;
|
||||
import org.jackhuang.hmcl.util.Lang;
|
||||
|
||||
public class DecoratorSkin extends SkinBase<Decorator> {
|
||||
@ -45,6 +50,7 @@ public class DecoratorSkin extends SkinBase<Decorator> {
|
||||
private final BorderPane titleContainer;
|
||||
private final StackPane contentPlaceHolder;
|
||||
private final Stage primaryStage;
|
||||
private final TransitionPane navBarPane;
|
||||
|
||||
private double xOffset, yOffset, newX, newY, initX, initY;
|
||||
private boolean allowMove, isDragging;
|
||||
@ -125,7 +131,17 @@ public class DecoratorSkin extends SkinBase<Decorator> {
|
||||
rectangle.heightProperty().bind(titleContainer.heightProperty().add(100));
|
||||
titleContainer.setClip(rectangle);
|
||||
{
|
||||
titleContainer.setCenter(createNavBar(skinnable));
|
||||
navBarPane = new TransitionPane();
|
||||
FXUtils.onChangeAndOperate(skinnable.stateProperty(), s -> {
|
||||
if (s == null) return;
|
||||
Node node = createNavBar(skinnable, s.isBackable(), skinnable.canCloseProperty().get(), skinnable.showCloseAsHomeProperty().get(), s.isRefreshable(), s.getTitle(), s.getTitleNode());
|
||||
if (s.isAnimate()) {
|
||||
navBarPane.setContent(node, ContainerAnimations.FADE.getAnimationProducer());
|
||||
} else {
|
||||
navBarPane.getChildren().setAll(node);
|
||||
}
|
||||
});
|
||||
titleContainer.setCenter(navBarPane);
|
||||
|
||||
HBox buttonsContainer = new HBox();
|
||||
buttonsContainer.setStyle("-fx-background-color: transparent;");
|
||||
@ -153,7 +169,7 @@ public class DecoratorSkin extends SkinBase<Decorator> {
|
||||
getChildren().setAll(root);
|
||||
}
|
||||
|
||||
private Node createNavBar(Decorator skinnable) {
|
||||
private Node createNavBar(Decorator skinnable, boolean canBack, boolean canClose, boolean showCloseAsHome, boolean canRefresh, String title, Node titleNode) {
|
||||
BorderPane navBar = new BorderPane();
|
||||
{
|
||||
HBox navLeft = new HBox();
|
||||
@ -165,7 +181,7 @@ public class DecoratorSkin extends SkinBase<Decorator> {
|
||||
backNavButton.getStyleClass().add("jfx-decorator-button");
|
||||
backNavButton.ripplerFillProperty().bind(Theme.whiteFillBinding());
|
||||
backNavButton.onActionProperty().bind(skinnable.onBackNavButtonActionProperty());
|
||||
backNavButton.visibleProperty().bind(skinnable.canBackProperty());
|
||||
backNavButton.visibleProperty().set(canBack);
|
||||
|
||||
JFXButton closeNavButton = new JFXButton();
|
||||
closeNavButton.setGraphic(SVG.close(Theme.foregroundFillBinding(), -1, -1));
|
||||
@ -173,31 +189,29 @@ public class DecoratorSkin extends SkinBase<Decorator> {
|
||||
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));
|
||||
});
|
||||
if (canBack) navLeft.getChildren().add(backNavButton);
|
||||
if (canClose) navLeft.getChildren().add(closeNavButton);
|
||||
if (showCloseAsHome)
|
||||
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);
|
||||
BorderPane center = new BorderPane();
|
||||
if (title != null) {
|
||||
Label titleLabel = new Label();
|
||||
titleLabel.getStyleClass().add("jfx-decorator-title");
|
||||
titleLabel.setText(title);
|
||||
center.setLeft(titleLabel);
|
||||
BorderPane.setAlignment(titleLabel, Pos.CENTER_LEFT);
|
||||
}
|
||||
if (titleNode != null) {
|
||||
center.setCenter(titleNode);
|
||||
BorderPane.setAlignment(titleNode, Pos.CENTER_LEFT);
|
||||
BorderPane.setMargin(titleNode, new Insets(0, 0, 0, 8));
|
||||
}
|
||||
navBar.setCenter(center);
|
||||
|
||||
HBox navRight = new HBox();
|
||||
navRight.setAlignment(Pos.CENTER_RIGHT);
|
||||
@ -206,7 +220,7 @@ public class DecoratorSkin extends SkinBase<Decorator> {
|
||||
refreshNavButton.getStyleClass().add("jfx-decorator-button");
|
||||
refreshNavButton.ripplerFillProperty().bind(Theme.whiteFillBinding());
|
||||
refreshNavButton.onActionProperty().bind(skinnable.onRefreshNavButtonActionProperty());
|
||||
refreshNavButton.visibleProperty().bind(skinnable.canRefreshProperty());
|
||||
refreshNavButton.visibleProperty().set(canRefresh);
|
||||
|
||||
Rectangle separator = new Rectangle();
|
||||
separator.visibleProperty().bind(refreshNavButton.visibleProperty());
|
||||
|
@ -18,9 +18,9 @@
|
||||
package org.jackhuang.hmcl.ui.decorator;
|
||||
|
||||
import javafx.beans.property.BooleanProperty;
|
||||
import javafx.beans.property.ReadOnlyObjectProperty;
|
||||
import javafx.beans.property.ReadOnlyObjectWrapper;
|
||||
import javafx.beans.property.SimpleBooleanProperty;
|
||||
import javafx.beans.property.SimpleStringProperty;
|
||||
import javafx.beans.property.StringProperty;
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.control.Control;
|
||||
import javafx.scene.control.Skin;
|
||||
@ -28,10 +28,11 @@ import org.jackhuang.hmcl.ui.animation.AnimationProducer;
|
||||
import org.jackhuang.hmcl.ui.animation.TransitionPane;
|
||||
import org.jackhuang.hmcl.ui.wizard.Refreshable;
|
||||
|
||||
public abstract class DecoratorTransitionPage extends Control implements DecoratorPage, Refreshable {
|
||||
private final StringProperty title = new SimpleStringProperty();
|
||||
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
||||
|
||||
public abstract class DecoratorTransitionPage extends Control implements DecoratorPage {
|
||||
protected final ReadOnlyObjectWrapper<State> state = new ReadOnlyObjectWrapper<>(State.fromTitle(i18n("")));
|
||||
private final BooleanProperty refreshable = new SimpleBooleanProperty(false);
|
||||
private final BooleanProperty backable = new SimpleBooleanProperty();
|
||||
private Node currentPage;
|
||||
protected final TransitionPane transitionPane = new TransitionPane();
|
||||
|
||||
@ -47,28 +48,10 @@ public abstract class DecoratorTransitionPage extends Control implements Decorat
|
||||
return currentPage;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public StringProperty titleProperty() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title.set(title);
|
||||
}
|
||||
|
||||
public boolean isRefreshable() {
|
||||
return refreshable.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refresh() {
|
||||
// empty implementation for default
|
||||
}
|
||||
|
||||
@Override
|
||||
public BooleanProperty refreshableProperty() {
|
||||
return refreshable;
|
||||
@ -78,16 +61,8 @@ public abstract class DecoratorTransitionPage extends Control implements Decorat
|
||||
this.refreshable.set(refreshable);
|
||||
}
|
||||
|
||||
public boolean isBackable() {
|
||||
return backable.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BooleanProperty backableProperty() {
|
||||
return backable;
|
||||
}
|
||||
|
||||
public void setBackable(boolean backable) {
|
||||
this.backable.set(backable);
|
||||
public ReadOnlyObjectProperty<State> stateProperty() {
|
||||
return state.getReadOnlyProperty();
|
||||
}
|
||||
}
|
||||
|
@ -71,8 +71,12 @@ public class DecoratorWizardDisplayer extends DecoratorTransitionPage implements
|
||||
|
||||
String prefix = category == null ? "" : category + " - ";
|
||||
|
||||
String title;
|
||||
if (page instanceof WizardPage)
|
||||
setTitle(prefix + ((WizardPage) page).getTitle());
|
||||
title = prefix + ((WizardPage) page).getTitle();
|
||||
else
|
||||
title = "";
|
||||
state.set(new State(title, null, true, refreshableProperty().get(), true));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -59,7 +59,7 @@ import static org.jackhuang.hmcl.ui.FXUtils.SINE;
|
||||
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
||||
|
||||
public final class MainPage extends StackPane implements DecoratorPage {
|
||||
private final ReadOnlyStringWrapper title = new ReadOnlyStringWrapper(this, "title", "Hello Minecraft! Launcher " + Metadata.VERSION);
|
||||
private final ReadOnlyObjectWrapper<State> state = new ReadOnlyObjectWrapper<>(State.fromTitle("Hello Minecraft! Launcher " + Metadata.VERSION));
|
||||
|
||||
private final PopupMenu menu = new PopupMenu();
|
||||
private final JFXPopup popup = new JFXPopup(menu);
|
||||
@ -236,17 +236,9 @@ public final class MainPage extends StackPane implements DecoratorPage {
|
||||
showUpdate.set(false);
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReadOnlyStringProperty titleProperty() {
|
||||
return title.getReadOnlyProperty();
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title.set(title);
|
||||
public ReadOnlyObjectWrapper<State> stateProperty() {
|
||||
return state;
|
||||
}
|
||||
|
||||
public String getCurrentGame() {
|
||||
|
@ -24,8 +24,8 @@ import javafx.beans.InvalidationListener;
|
||||
import javafx.beans.WeakInvalidationListener;
|
||||
import javafx.beans.binding.Bindings;
|
||||
import javafx.beans.binding.When;
|
||||
import javafx.beans.property.ReadOnlyStringProperty;
|
||||
import javafx.beans.property.ReadOnlyStringWrapper;
|
||||
import javafx.beans.property.ReadOnlyObjectProperty;
|
||||
import javafx.beans.property.ReadOnlyObjectWrapper;
|
||||
import javafx.scene.control.ToggleGroup;
|
||||
import javafx.scene.paint.Color;
|
||||
import javafx.scene.text.Font;
|
||||
@ -67,7 +67,7 @@ import static org.jackhuang.hmcl.util.javafx.ExtendedProperties.reservedSelected
|
||||
import static org.jackhuang.hmcl.util.javafx.ExtendedProperties.selectedItemPropertyFor;
|
||||
|
||||
public final class SettingsPage extends SettingsView implements DecoratorPage {
|
||||
private final ReadOnlyStringWrapper title = new ReadOnlyStringWrapper(this, "title", i18n("settings.launcher"));
|
||||
private final ReadOnlyObjectWrapper<State> state = new ReadOnlyObjectWrapper<>(State.fromTitle(i18n("settings.launcher")));
|
||||
|
||||
private InvalidationListener updateListener;
|
||||
|
||||
@ -200,17 +200,9 @@ public final class SettingsPage extends SettingsView implements DecoratorPage {
|
||||
// ====
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReadOnlyStringProperty titleProperty() {
|
||||
return title.getReadOnlyProperty();
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title.set(title);
|
||||
public ReadOnlyObjectProperty<State> stateProperty() {
|
||||
return state.getReadOnlyProperty();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -29,7 +29,7 @@ import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
||||
import static org.jackhuang.hmcl.util.javafx.ExtendedProperties.createSelectedItemPropertyFor;
|
||||
|
||||
public class ProfileList extends ListPage<ProfileListItem> implements DecoratorPage {
|
||||
private final ReadOnlyStringWrapper title = new ReadOnlyStringWrapper(i18n("profile.manage"));
|
||||
private final ReadOnlyObjectWrapper<State> state = new ReadOnlyObjectWrapper<>(State.fromTitle(i18n("profile.manage")));
|
||||
private final ListProperty<Profile> profiles = new SimpleListProperty<>(FXCollections.observableArrayList());
|
||||
private ObjectProperty<Profile> selectedProfile;
|
||||
|
||||
@ -52,7 +52,7 @@ public class ProfileList extends ListPage<ProfileListItem> implements DecoratorP
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReadOnlyStringProperty titleProperty() {
|
||||
return title.getReadOnlyProperty();
|
||||
public ReadOnlyObjectProperty<State> stateProperty() {
|
||||
return state.getReadOnlyProperty();
|
||||
}
|
||||
}
|
||||
|
@ -21,8 +21,8 @@ import com.jfoenix.controls.JFXButton;
|
||||
import com.jfoenix.controls.JFXCheckBox;
|
||||
import com.jfoenix.controls.JFXTextField;
|
||||
import com.jfoenix.validation.base.ValidatorBase;
|
||||
import javafx.beans.property.ReadOnlyStringProperty;
|
||||
import javafx.beans.property.ReadOnlyStringWrapper;
|
||||
import javafx.beans.property.ReadOnlyObjectProperty;
|
||||
import javafx.beans.property.ReadOnlyObjectWrapper;
|
||||
import javafx.beans.property.SimpleStringProperty;
|
||||
import javafx.beans.property.StringProperty;
|
||||
import javafx.fxml.FXML;
|
||||
@ -41,7 +41,7 @@ import java.util.Optional;
|
||||
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
||||
|
||||
public final class ProfilePage extends StackPane implements DecoratorPage {
|
||||
private final ReadOnlyStringWrapper title;
|
||||
private final ReadOnlyObjectWrapper<State> state = new ReadOnlyObjectWrapper<>();
|
||||
private final StringProperty location;
|
||||
private final Profile profile;
|
||||
|
||||
@ -57,8 +57,7 @@ public final class ProfilePage extends StackPane implements DecoratorPage {
|
||||
this.profile = profile;
|
||||
String profileDisplayName = Optional.ofNullable(profile).map(Profiles::getProfileDisplayName).orElse("");
|
||||
|
||||
title = new ReadOnlyStringWrapper(this, "title",
|
||||
profile == null ? i18n("profile.new") : i18n("profile") + " - " + profileDisplayName);
|
||||
state.set(State.fromTitle(profile == null ? i18n("profile.new") : i18n("profile") + " - " + profileDisplayName));
|
||||
location = new SimpleStringProperty(this, "location",
|
||||
Optional.ofNullable(profile).map(Profile::getGameDir).map(File::getAbsolutePath).orElse(".minecraft"));
|
||||
|
||||
@ -111,17 +110,9 @@ public final class ProfilePage extends StackPane implements DecoratorPage {
|
||||
fireEvent(new PageCloseEvent());
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReadOnlyStringProperty titleProperty() {
|
||||
return title.getReadOnlyProperty();
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title.set(title);
|
||||
public ReadOnlyObjectProperty<State> stateProperty() {
|
||||
return state.getReadOnlyProperty();
|
||||
}
|
||||
|
||||
public String getLocation() {
|
||||
|
@ -17,8 +17,8 @@
|
||||
*/
|
||||
package org.jackhuang.hmcl.ui.versions;
|
||||
|
||||
import javafx.beans.property.SimpleStringProperty;
|
||||
import javafx.beans.property.StringProperty;
|
||||
import javafx.beans.property.ReadOnlyObjectProperty;
|
||||
import javafx.beans.property.ReadOnlyObjectWrapper;
|
||||
import javafx.collections.ObservableList;
|
||||
import javafx.scene.control.Skin;
|
||||
import javafx.stage.FileChooser;
|
||||
@ -43,7 +43,7 @@ import java.util.logging.Level;
|
||||
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
||||
|
||||
public class DatapackListPage extends ListPageBase<DatapackListPageSkin.DatapackInfoObject> implements DecoratorPage {
|
||||
private final StringProperty title = new SimpleStringProperty();
|
||||
private final ReadOnlyObjectWrapper<State> state = new ReadOnlyObjectWrapper<>();
|
||||
private final Path worldDir;
|
||||
private final Datapack datapack;
|
||||
|
||||
@ -52,7 +52,7 @@ public class DatapackListPage extends ListPageBase<DatapackListPageSkin.Datapack
|
||||
public DatapackListPage(String worldName, Path worldDir) {
|
||||
this.worldDir = worldDir;
|
||||
|
||||
title.set(i18n("datapack.title", worldName));
|
||||
state.set(State.fromTitle(i18n("datapack.title", worldName)));
|
||||
|
||||
datapack = new Datapack(worldDir.resolve("datapacks"));
|
||||
datapack.loadFromDir();
|
||||
@ -86,8 +86,8 @@ public class DatapackListPage extends ListPageBase<DatapackListPageSkin.Datapack
|
||||
}
|
||||
|
||||
@Override
|
||||
public StringProperty titleProperty() {
|
||||
return title;
|
||||
public ReadOnlyObjectProperty<State> stateProperty() {
|
||||
return state.getReadOnlyProperty();
|
||||
}
|
||||
|
||||
public void add() {
|
||||
|
@ -18,8 +18,8 @@
|
||||
package org.jackhuang.hmcl.ui.versions;
|
||||
|
||||
import javafx.application.Platform;
|
||||
import javafx.beans.property.ReadOnlyStringProperty;
|
||||
import javafx.beans.property.ReadOnlyStringWrapper;
|
||||
import javafx.beans.property.ReadOnlyObjectProperty;
|
||||
import javafx.beans.property.ReadOnlyObjectWrapper;
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.control.ToggleGroup;
|
||||
import org.jackhuang.hmcl.event.EventBus;
|
||||
@ -33,7 +33,6 @@ import org.jackhuang.hmcl.ui.construct.Navigator;
|
||||
import org.jackhuang.hmcl.ui.decorator.DecoratorPage;
|
||||
import org.jackhuang.hmcl.ui.download.ModpackInstallWizardProvider;
|
||||
import org.jackhuang.hmcl.ui.download.VanillaInstallWizardProvider;
|
||||
import org.jackhuang.hmcl.util.i18n.I18n;
|
||||
import org.jackhuang.hmcl.util.versioning.VersionNumber;
|
||||
|
||||
import java.util.Arrays;
|
||||
@ -46,7 +45,7 @@ import static org.jackhuang.hmcl.ui.FXUtils.runInFX;
|
||||
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
||||
|
||||
public class GameList extends ListPageBase<GameListItem> implements DecoratorPage {
|
||||
private final ReadOnlyStringWrapper title = new ReadOnlyStringWrapper(I18n.i18n("version.manage"));
|
||||
private final ReadOnlyObjectWrapper<State> state = new ReadOnlyObjectWrapper<>(State.fromTitle(i18n("version.manage")));
|
||||
|
||||
private ToggleGroup toggleGroup;
|
||||
|
||||
@ -123,8 +122,8 @@ public class GameList extends ListPageBase<GameListItem> implements DecoratorPag
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReadOnlyStringProperty titleProperty() {
|
||||
return title.getReadOnlyProperty();
|
||||
public ReadOnlyObjectProperty<State> stateProperty() {
|
||||
return state.getReadOnlyProperty();
|
||||
}
|
||||
|
||||
private class GameListSkin extends ToolbarListPageSkin<GameList> {
|
||||
|
@ -18,13 +18,15 @@
|
||||
package org.jackhuang.hmcl.ui.versions;
|
||||
|
||||
import com.jfoenix.controls.JFXListView;
|
||||
import com.jfoenix.controls.JFXTabPane;
|
||||
import javafx.beans.property.BooleanProperty;
|
||||
import javafx.beans.property.ReadOnlyStringProperty;
|
||||
import javafx.beans.property.ReadOnlyStringWrapper;
|
||||
import javafx.beans.property.ReadOnlyObjectProperty;
|
||||
import javafx.beans.property.ReadOnlyObjectWrapper;
|
||||
import javafx.beans.property.SimpleBooleanProperty;
|
||||
import javafx.scene.control.Control;
|
||||
import javafx.scene.control.SelectionMode;
|
||||
import javafx.scene.control.SkinBase;
|
||||
import javafx.scene.control.Tab;
|
||||
import javafx.scene.layout.BorderPane;
|
||||
import javafx.scene.layout.StackPane;
|
||||
import javafx.scene.paint.Color;
|
||||
@ -35,6 +37,7 @@ import org.jackhuang.hmcl.setting.Profile;
|
||||
import org.jackhuang.hmcl.setting.Profiles;
|
||||
import org.jackhuang.hmcl.ui.FXUtils;
|
||||
import org.jackhuang.hmcl.ui.construct.SpinnerPane;
|
||||
import org.jackhuang.hmcl.ui.construct.TabHeader;
|
||||
import org.jackhuang.hmcl.ui.decorator.DecoratorPage;
|
||||
import org.jackhuang.hmcl.util.versioning.VersionNumber;
|
||||
|
||||
@ -44,9 +47,10 @@ import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.jackhuang.hmcl.ui.FXUtils.runInFX;
|
||||
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
||||
|
||||
public class VersionRootPage extends Control implements DecoratorPage {
|
||||
private final ReadOnlyStringWrapper title = new ReadOnlyStringWrapper();
|
||||
private final ReadOnlyObjectWrapper<State> state = new ReadOnlyObjectWrapper<>();
|
||||
private final BooleanProperty loading = new SimpleBooleanProperty();
|
||||
private final JFXListView<String> listView = new JFXListView<>();
|
||||
private final VersionPage versionPage = new VersionPage();
|
||||
@ -88,8 +92,8 @@ public class VersionRootPage extends Control implements DecoratorPage {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReadOnlyStringProperty titleProperty() {
|
||||
return title.getReadOnlyProperty();
|
||||
public ReadOnlyObjectProperty<State> stateProperty() {
|
||||
return state.getReadOnlyProperty();
|
||||
}
|
||||
|
||||
public static class Skin extends SkinBase<VersionRootPage> {
|
||||
@ -129,8 +133,9 @@ public class VersionRootPage extends Control implements DecoratorPage {
|
||||
root.setLeft(leftRootPane);
|
||||
}
|
||||
|
||||
control.state.set(new State(i18n("version.manage.manage"), null, true, false, true));
|
||||
|
||||
root.setCenter(control.versionPage);
|
||||
control.title.bind(control.versionPage.titleProperty());
|
||||
|
||||
spinnerPane.loadingProperty().bind(control.versionPage.loadingProperty());
|
||||
spinnerPane.setContent(root);
|
||||
|
@ -24,8 +24,8 @@ import com.jfoenix.controls.JFXToggleButton;
|
||||
import javafx.application.Platform;
|
||||
import javafx.beans.InvalidationListener;
|
||||
import javafx.beans.binding.Bindings;
|
||||
import javafx.beans.property.ReadOnlyStringProperty;
|
||||
import javafx.beans.property.ReadOnlyStringWrapper;
|
||||
import javafx.beans.property.ReadOnlyObjectProperty;
|
||||
import javafx.beans.property.ReadOnlyObjectWrapper;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.ScrollPane;
|
||||
@ -63,7 +63,7 @@ import static org.jackhuang.hmcl.ui.FXUtils.stringConverter;
|
||||
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
||||
|
||||
public final class VersionSettingsPage extends StackPane implements DecoratorPage {
|
||||
private final ReadOnlyStringWrapper title = new ReadOnlyStringWrapper();
|
||||
private final ReadOnlyObjectWrapper<State> state = new ReadOnlyObjectWrapper<>(new State("", null, false, false, false));
|
||||
|
||||
private VersionSetting lastVersionSetting = null;
|
||||
private Profile profile;
|
||||
@ -163,7 +163,7 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag
|
||||
rootPane.getChildren().remove(iconPickerItemWrapper);
|
||||
rootPane.getChildren().remove(settingsTypePane);
|
||||
chkEnableSpecificSettings.setSelected(true);
|
||||
title.set(Profiles.getProfileDisplayName(profile) + " - " + i18n("settings.type.global.manage"));
|
||||
state.set(State.fromTitle(Profiles.getProfileDisplayName(profile) + " - " + i18n("settings.type.global.manage")));
|
||||
}
|
||||
|
||||
VersionSetting versionSetting = profile.getVersionSetting(versionId);
|
||||
@ -328,7 +328,7 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReadOnlyStringProperty titleProperty() {
|
||||
return title;
|
||||
public ReadOnlyObjectProperty<State> stateProperty() {
|
||||
return state.getReadOnlyProperty();
|
||||
}
|
||||
}
|
||||
|
@ -23,10 +23,6 @@
|
||||
}
|
||||
|
||||
.scroll-bar .track {
|
||||
-fx-stroke-width: 1;
|
||||
-fx-stroke: -c-dark-glass;
|
||||
-fx-arc-width: 5px;
|
||||
-fx-arc-height: 5px;
|
||||
-fx-fill: transparent;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user