feat: new about page
This commit is contained in:
@@ -44,7 +44,9 @@ import org.jackhuang.hmcl.ui.construct.PromptDialogPane;
|
|||||||
import org.jackhuang.hmcl.ui.construct.TaskExecutorDialogPane;
|
import org.jackhuang.hmcl.ui.construct.TaskExecutorDialogPane;
|
||||||
import org.jackhuang.hmcl.ui.decorator.DecoratorController;
|
import org.jackhuang.hmcl.ui.decorator.DecoratorController;
|
||||||
import org.jackhuang.hmcl.ui.download.ModpackInstallWizardProvider;
|
import org.jackhuang.hmcl.ui.download.ModpackInstallWizardProvider;
|
||||||
|
import org.jackhuang.hmcl.ui.main.LauncherSettingsPage;
|
||||||
import org.jackhuang.hmcl.ui.main.RootPage;
|
import org.jackhuang.hmcl.ui.main.RootPage;
|
||||||
|
import org.jackhuang.hmcl.ui.main.SettingsPage;
|
||||||
import org.jackhuang.hmcl.ui.versions.GameListPage;
|
import org.jackhuang.hmcl.ui.versions.GameListPage;
|
||||||
import org.jackhuang.hmcl.ui.versions.ModDownloadListPage;
|
import org.jackhuang.hmcl.ui.versions.ModDownloadListPage;
|
||||||
import org.jackhuang.hmcl.ui.versions.VersionPage;
|
import org.jackhuang.hmcl.ui.versions.VersionPage;
|
||||||
@@ -91,6 +93,7 @@ public final class Controllers {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
private static Lazy<LauncherSettingsPage> settingsPage = new Lazy<>(LauncherSettingsPage::new);
|
||||||
|
|
||||||
private Controllers() {
|
private Controllers() {
|
||||||
}
|
}
|
||||||
@@ -130,6 +133,11 @@ public final class Controllers {
|
|||||||
return modDownloadListPage.get();
|
return modDownloadListPage.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FXThread
|
||||||
|
public static LauncherSettingsPage getSettingsPage() {
|
||||||
|
return settingsPage.get();
|
||||||
|
}
|
||||||
|
|
||||||
// FXThread
|
// FXThread
|
||||||
public static DecoratorController getDecorator() {
|
public static DecoratorController getDecorator() {
|
||||||
return decorator;
|
return decorator;
|
||||||
@@ -255,6 +263,7 @@ public final class Controllers {
|
|||||||
versionPage = null;
|
versionPage = null;
|
||||||
serversPage = null;
|
serversPage = null;
|
||||||
gameListPage = null;
|
gameListPage = null;
|
||||||
|
settingsPage = null;
|
||||||
modDownloadListPage = null;
|
modDownloadListPage = null;
|
||||||
decorator = null;
|
decorator = null;
|
||||||
stage = null;
|
stage = null;
|
||||||
|
|||||||
@@ -85,6 +85,10 @@ public class AdvancedListBox extends ScrollPane {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public AdvancedListBox startCategory() {
|
||||||
|
return add(new ClassTitle());
|
||||||
|
}
|
||||||
|
|
||||||
public AdvancedListBox startCategory(String category) {
|
public AdvancedListBox startCategory(String category) {
|
||||||
return add(new ClassTitle(category));
|
return add(new ClassTitle(category));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -142,12 +142,16 @@ public class AdvancedListItem extends Control {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static Pair<Node, ImageView> createImageView(Image image) {
|
public static Pair<Node, ImageView> createImageView(Image image) {
|
||||||
|
return createImageView(image, 32, 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Pair<Node, ImageView> createImageView(Image image, double width, double height) {
|
||||||
StackPane imageViewContainer = new StackPane();
|
StackPane imageViewContainer = new StackPane();
|
||||||
FXUtils.setLimitWidth(imageViewContainer, 32);
|
FXUtils.setLimitWidth(imageViewContainer, width);
|
||||||
FXUtils.setLimitHeight(imageViewContainer, 32);
|
FXUtils.setLimitHeight(imageViewContainer, height);
|
||||||
|
|
||||||
ImageView imageView = new ImageView();
|
ImageView imageView = new ImageView();
|
||||||
FXUtils.limitSize(imageView, 32, 32);
|
FXUtils.limitSize(imageView, width, height);
|
||||||
imageView.setPreserveRatio(true);
|
imageView.setPreserveRatio(true);
|
||||||
imageView.setImage(image);
|
imageView.setImage(image);
|
||||||
imageViewContainer.getChildren().setAll(imageView);
|
imageViewContainer.getChildren().setAll(imageView);
|
||||||
|
|||||||
@@ -17,7 +17,9 @@
|
|||||||
*/
|
*/
|
||||||
package org.jackhuang.hmcl.ui.construct;
|
package org.jackhuang.hmcl.ui.construct;
|
||||||
|
|
||||||
|
import javafx.geometry.Insets;
|
||||||
import javafx.scene.Node;
|
import javafx.scene.Node;
|
||||||
|
import javafx.scene.control.Label;
|
||||||
import javafx.scene.layout.BorderPane;
|
import javafx.scene.layout.BorderPane;
|
||||||
import javafx.scene.layout.StackPane;
|
import javafx.scene.layout.StackPane;
|
||||||
import javafx.scene.layout.VBox;
|
import javafx.scene.layout.VBox;
|
||||||
@@ -32,20 +34,29 @@ import org.jackhuang.hmcl.util.Lang;
|
|||||||
public class ClassTitle extends StackPane {
|
public class ClassTitle extends StackPane {
|
||||||
private final Node content;
|
private final Node content;
|
||||||
|
|
||||||
|
public ClassTitle() {
|
||||||
|
this((Node) null);
|
||||||
|
}
|
||||||
|
|
||||||
public ClassTitle(String text) {
|
public ClassTitle(String text) {
|
||||||
this(new Text(text));
|
this(new Label(text));
|
||||||
}
|
}
|
||||||
|
|
||||||
public ClassTitle(Node content) {
|
public ClassTitle(Node content) {
|
||||||
this.content = content;
|
this.content = content;
|
||||||
|
|
||||||
VBox vbox = new VBox();
|
VBox vbox = new VBox();
|
||||||
vbox.getChildren().addAll(content);
|
|
||||||
Rectangle rectangle = new Rectangle();
|
Rectangle rectangle = new Rectangle();
|
||||||
rectangle.widthProperty().bind(vbox.widthProperty());
|
rectangle.widthProperty().bind(vbox.widthProperty());
|
||||||
rectangle.setHeight(1.0);
|
rectangle.setHeight(1.0);
|
||||||
rectangle.setFill(Color.GRAY);
|
rectangle.setFill(Color.GRAY);
|
||||||
vbox.getChildren().add(rectangle);
|
vbox.getChildren().add(rectangle);
|
||||||
|
|
||||||
|
if (content != null) {
|
||||||
|
vbox.getChildren().addAll(content);
|
||||||
|
VBox.setMargin(content, new Insets(16, 16, 0, 16));
|
||||||
|
}
|
||||||
|
|
||||||
getChildren().setAll(vbox);
|
getChildren().setAll(vbox);
|
||||||
getStyleClass().add("class-title");
|
getStyleClass().add("class-title");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,8 +17,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.jackhuang.hmcl.ui.construct;
|
package org.jackhuang.hmcl.ui.construct;
|
||||||
|
|
||||||
import org.jackhuang.hmcl.util.javafx.MappedObservableList;
|
|
||||||
|
|
||||||
import javafx.beans.DefaultProperty;
|
import javafx.beans.DefaultProperty;
|
||||||
import javafx.beans.binding.Bindings;
|
import javafx.beans.binding.Bindings;
|
||||||
import javafx.beans.binding.ObjectBinding;
|
import javafx.beans.binding.ObjectBinding;
|
||||||
@@ -29,10 +27,15 @@ import javafx.beans.property.StringProperty;
|
|||||||
import javafx.collections.FXCollections;
|
import javafx.collections.FXCollections;
|
||||||
import javafx.collections.ObservableList;
|
import javafx.collections.ObservableList;
|
||||||
import javafx.css.PseudoClass;
|
import javafx.css.PseudoClass;
|
||||||
|
import javafx.geometry.Insets;
|
||||||
|
import javafx.geometry.Pos;
|
||||||
import javafx.scene.Node;
|
import javafx.scene.Node;
|
||||||
import javafx.scene.control.Control;
|
import javafx.scene.control.Control;
|
||||||
|
import javafx.scene.control.Label;
|
||||||
import javafx.scene.control.SkinBase;
|
import javafx.scene.control.SkinBase;
|
||||||
|
import javafx.scene.layout.HBox;
|
||||||
import javafx.scene.layout.VBox;
|
import javafx.scene.layout.VBox;
|
||||||
|
import org.jackhuang.hmcl.util.javafx.MappedObservableList;
|
||||||
|
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
@@ -153,8 +156,21 @@ public class ComponentList extends Control {
|
|||||||
list.get(list.size() - 1).pseudoClassStateChanged(PSEUDO_CLASS_LAST, true);
|
list.get(list.size() - 1).pseudoClassStateChanged(PSEUDO_CLASS_LAST, true);
|
||||||
|
|
||||||
VBox vbox = new VBox();
|
VBox vbox = new VBox();
|
||||||
|
vbox.setFillWidth(true);
|
||||||
Bindings.bindContent(vbox.getChildren(), list);
|
Bindings.bindContent(vbox.getChildren(), list);
|
||||||
getChildren().setAll(vbox);
|
getChildren().setAll(vbox);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Node createComponentListTitle(String title) {
|
||||||
|
HBox node = new HBox();
|
||||||
|
node.setAlignment(Pos.CENTER_LEFT);
|
||||||
|
node.setPadding(new Insets(8, 0, 0, 0));
|
||||||
|
{
|
||||||
|
Label advanced = new Label(title);
|
||||||
|
advanced.setStyle("-fx-text-fill: #616161");
|
||||||
|
node.getChildren().setAll(advanced);
|
||||||
|
}
|
||||||
|
return node;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,114 @@
|
|||||||
|
package org.jackhuang.hmcl.ui.construct;
|
||||||
|
|
||||||
|
import com.jfoenix.controls.JFXButton;
|
||||||
|
import javafx.beans.InvalidationListener;
|
||||||
|
import javafx.beans.binding.Bindings;
|
||||||
|
import javafx.beans.property.ObjectProperty;
|
||||||
|
import javafx.beans.property.SimpleObjectProperty;
|
||||||
|
import javafx.beans.property.SimpleStringProperty;
|
||||||
|
import javafx.beans.property.StringProperty;
|
||||||
|
import javafx.collections.FXCollections;
|
||||||
|
import javafx.collections.ObservableList;
|
||||||
|
import javafx.geometry.Pos;
|
||||||
|
import javafx.scene.image.Image;
|
||||||
|
import javafx.scene.image.ImageView;
|
||||||
|
import javafx.scene.layout.HBox;
|
||||||
|
import javafx.scene.layout.Priority;
|
||||||
|
import org.jackhuang.hmcl.setting.Theme;
|
||||||
|
import org.jackhuang.hmcl.ui.FXUtils;
|
||||||
|
import org.jackhuang.hmcl.ui.SVG;
|
||||||
|
import org.jackhuang.hmcl.util.Lazy;
|
||||||
|
import org.jackhuang.hmcl.util.StringUtils;
|
||||||
|
|
||||||
|
public class IconedTwoLineListItem extends HBox {
|
||||||
|
private final StringProperty title = new SimpleStringProperty(this, "title");
|
||||||
|
private final ObservableList<String> tags = FXCollections.observableArrayList();
|
||||||
|
private final StringProperty subtitle = new SimpleStringProperty(this, "subtitle");
|
||||||
|
private final StringProperty externalLink = new SimpleStringProperty(this, "externalLink");
|
||||||
|
private final ObjectProperty<Image> image = new SimpleObjectProperty<>(this, "image");
|
||||||
|
|
||||||
|
private final ImageView imageView = new ImageView();
|
||||||
|
private final TwoLineListItem twoLineListItem = new TwoLineListItem();
|
||||||
|
private final Lazy<JFXButton> externalLinkButton = new Lazy<>(() -> {
|
||||||
|
JFXButton button = new JFXButton();
|
||||||
|
button.getStyleClass().add("toggle-icon4");
|
||||||
|
button.setGraphic(SVG.openInNew(Theme.blackFillBinding(), -1, -1));
|
||||||
|
button.setOnAction(e -> FXUtils.openLink(externalLink.get()));
|
||||||
|
return button;
|
||||||
|
});
|
||||||
|
@SuppressWarnings("FieldCanBeLocal")
|
||||||
|
private final InvalidationListener observer;
|
||||||
|
|
||||||
|
public IconedTwoLineListItem() {
|
||||||
|
setAlignment(Pos.CENTER);
|
||||||
|
setSpacing(16);
|
||||||
|
imageView.imageProperty().bind(image);
|
||||||
|
twoLineListItem.titleProperty().bind(title);
|
||||||
|
twoLineListItem.subtitleProperty().bind(subtitle);
|
||||||
|
HBox.setHgrow(twoLineListItem, Priority.ALWAYS);
|
||||||
|
Bindings.bindContent(twoLineListItem.getTags(), tags);
|
||||||
|
|
||||||
|
observer = FXUtils.observeWeak(() -> {
|
||||||
|
getChildren().clear();
|
||||||
|
if (image.get() != null) getChildren().add(imageView);
|
||||||
|
getChildren().add(twoLineListItem);
|
||||||
|
if (StringUtils.isNotBlank(externalLink.get())) getChildren().add(externalLinkButton.get());
|
||||||
|
}, image, externalLink);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTitle() {
|
||||||
|
return title.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public StringProperty titleProperty() {
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTitle(String title) {
|
||||||
|
this.title.set(title);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ObservableList<String> getTags() {
|
||||||
|
return tags;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSubtitle() {
|
||||||
|
return subtitle.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public StringProperty subtitleProperty() {
|
||||||
|
return subtitle;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSubtitle(String subtitle) {
|
||||||
|
this.subtitle.set(subtitle);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getExternalLink() {
|
||||||
|
return externalLink.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public StringProperty externalLinkProperty() {
|
||||||
|
return externalLink;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setExternalLink(String externalLink) {
|
||||||
|
this.externalLink.set(externalLink);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Image getImage() {
|
||||||
|
return image.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ObjectProperty<Image> imageProperty() {
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setImage(Image image) {
|
||||||
|
this.image.set(image);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ImageView getImageView() {
|
||||||
|
return imageView;
|
||||||
|
}
|
||||||
|
}
|
||||||
142
HMCL/src/main/java/org/jackhuang/hmcl/ui/main/AboutPage.java
Normal file
142
HMCL/src/main/java/org/jackhuang/hmcl/ui/main/AboutPage.java
Normal file
@@ -0,0 +1,142 @@
|
|||||||
|
package org.jackhuang.hmcl.ui.main;
|
||||||
|
|
||||||
|
import javafx.geometry.Insets;
|
||||||
|
import javafx.scene.control.ScrollPane;
|
||||||
|
import javafx.scene.image.Image;
|
||||||
|
import javafx.scene.layout.StackPane;
|
||||||
|
import javafx.scene.layout.VBox;
|
||||||
|
import org.jackhuang.hmcl.Metadata;
|
||||||
|
import org.jackhuang.hmcl.ui.construct.ComponentList;
|
||||||
|
import org.jackhuang.hmcl.ui.construct.IconedTwoLineListItem;
|
||||||
|
import org.jackhuang.hmcl.ui.construct.TwoLineListItem;
|
||||||
|
|
||||||
|
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
||||||
|
|
||||||
|
public class AboutPage extends StackPane {
|
||||||
|
|
||||||
|
public AboutPage() {
|
||||||
|
ComponentList about = new ComponentList();
|
||||||
|
{
|
||||||
|
IconedTwoLineListItem launcher = new IconedTwoLineListItem();
|
||||||
|
launcher.setImage(new Image("/assets/img/craft_table.png", 32, 32, false, true));
|
||||||
|
launcher.setTitle("Hello Minecraft! Launcher");
|
||||||
|
launcher.setSubtitle(Metadata.VERSION);
|
||||||
|
launcher.setExternalLink("https://hmcl.huangyuhui.net");
|
||||||
|
|
||||||
|
IconedTwoLineListItem author = new IconedTwoLineListItem();
|
||||||
|
author.setImage(new Image("/assets/img/yellow_fish.png", 32, 32, false, true));
|
||||||
|
author.setTitle("huanghongxun");
|
||||||
|
author.setSubtitle("https://www.huangyuhui.net");
|
||||||
|
author.setExternalLink("https://www.huangyuhui.net");
|
||||||
|
|
||||||
|
about.getContent().setAll(launcher, author);
|
||||||
|
}
|
||||||
|
|
||||||
|
ComponentList thanks = new ComponentList();
|
||||||
|
{
|
||||||
|
IconedTwoLineListItem yushijinhun = new IconedTwoLineListItem();
|
||||||
|
yushijinhun.setTitle("yushijinhun");
|
||||||
|
yushijinhun.setSubtitle(i18n("about.thanks_to.yushijinhun.statement"));
|
||||||
|
yushijinhun.setExternalLink("https://yushi.moe/");
|
||||||
|
|
||||||
|
IconedTwoLineListItem bangbang93 = new IconedTwoLineListItem();
|
||||||
|
bangbang93.setTitle("bangbang93");
|
||||||
|
bangbang93.setSubtitle(i18n("about.thanks_to.bangbang93.statement"));
|
||||||
|
bangbang93.setExternalLink("https://bmclapi2.bangbang93.com/");
|
||||||
|
|
||||||
|
IconedTwoLineListItem gamerteam = new IconedTwoLineListItem();
|
||||||
|
gamerteam.setTitle("gamerteam");
|
||||||
|
gamerteam.setSubtitle(i18n("about.thanks_to.gamerteam.statement"));
|
||||||
|
gamerteam.setExternalLink("http://www.zhaisoul.com/");
|
||||||
|
|
||||||
|
IconedTwoLineListItem contributors = new IconedTwoLineListItem();
|
||||||
|
contributors.setTitle(i18n("about.thanks_to.contributors"));
|
||||||
|
contributors.setSubtitle(i18n("about.thanks_to.contributors.statement"));
|
||||||
|
contributors.setExternalLink("https://github.com/huanghongxun/HMCL/graphs/contributors");
|
||||||
|
|
||||||
|
thanks.getContent().setAll(yushijinhun, bangbang93, gamerteam, contributors);
|
||||||
|
}
|
||||||
|
|
||||||
|
ComponentList dep = new ComponentList();
|
||||||
|
{
|
||||||
|
IconedTwoLineListItem jfoenix = new IconedTwoLineListItem();
|
||||||
|
jfoenix.setTitle("JFoenix");
|
||||||
|
jfoenix.setSubtitle("Copyright (c) 2016 JFoenix.\nLicensed under the MIT License.");
|
||||||
|
jfoenix.setExternalLink("http://www.jfoenix.com/");
|
||||||
|
|
||||||
|
IconedTwoLineListItem gson = new IconedTwoLineListItem();
|
||||||
|
gson.setTitle("Gson");
|
||||||
|
gson.setSubtitle("Copyright 2008 Google Inc.\nLicensed under the Apache 2.0 License.");
|
||||||
|
gson.setExternalLink("https://github.com/google/gson");
|
||||||
|
|
||||||
|
IconedTwoLineListItem xz = new IconedTwoLineListItem();
|
||||||
|
xz.setTitle("XZ for Java");
|
||||||
|
xz.setSubtitle("Lasse Collin, Igor Pavlov, and/or Brett Okken.\nPublic Domain.");
|
||||||
|
xz.setExternalLink("https://tukaani.org/xz/java.html");
|
||||||
|
|
||||||
|
IconedTwoLineListItem fxgson = new IconedTwoLineListItem();
|
||||||
|
fxgson.setTitle("fx-gson");
|
||||||
|
fxgson.setSubtitle("Copyright (c) 2016 Joffrey Bion.\nLicensed under the MIT License.");
|
||||||
|
fxgson.setExternalLink("https://github.com/joffrey-bion/fx-gson");
|
||||||
|
|
||||||
|
IconedTwoLineListItem constantPoolScanner = new IconedTwoLineListItem();
|
||||||
|
constantPoolScanner.setTitle("Constant Pool Scanner");
|
||||||
|
constantPoolScanner.setSubtitle("Copyright 1997-2010 Oracle and/or its affiliates.\nLicensed under the GPL 2 or the CDDL.");
|
||||||
|
constantPoolScanner.setExternalLink("https://github.com/jenkinsci/constant-pool-scanner");
|
||||||
|
|
||||||
|
IconedTwoLineListItem openNBT = new IconedTwoLineListItem();
|
||||||
|
openNBT.setTitle("OpenNBT");
|
||||||
|
openNBT.setSubtitle("Copyright (C) 2013-2021 Steveice10.\nLicensed under the MIT License.");
|
||||||
|
openNBT.setExternalLink("https://github.com/Steveice10/OpenNBT");
|
||||||
|
|
||||||
|
dep.getContent().setAll(jfoenix, gson, xz, fxgson, constantPoolScanner, openNBT);
|
||||||
|
}
|
||||||
|
|
||||||
|
ComponentList legal = new ComponentList();
|
||||||
|
{
|
||||||
|
TwoLineListItem copyright = new TwoLineListItem();
|
||||||
|
copyright.setTitle(i18n("about.copyright"));
|
||||||
|
copyright.setSubtitle(i18n("about.copyright.statement"));
|
||||||
|
|
||||||
|
TwoLineListItem claim = new TwoLineListItem();
|
||||||
|
claim.setTitle(i18n("about.claim"));
|
||||||
|
claim.setSubtitle(i18n("about.claim.statement"));
|
||||||
|
|
||||||
|
TwoLineListItem openSource = new TwoLineListItem();
|
||||||
|
openSource.setTitle(i18n("about.open_source"));
|
||||||
|
openSource.setSubtitle(i18n("about.open_source.statement"));
|
||||||
|
|
||||||
|
legal.getContent().setAll(copyright, claim, openSource);
|
||||||
|
}
|
||||||
|
|
||||||
|
ComponentList donations = new ComponentList();
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
VBox content = new VBox(16);
|
||||||
|
content.setPadding(new Insets(10));
|
||||||
|
content.getChildren().setAll(
|
||||||
|
ComponentList.createComponentListTitle(i18n("about")),
|
||||||
|
about,
|
||||||
|
|
||||||
|
ComponentList.createComponentListTitle(i18n("about.thanks_to")),
|
||||||
|
thanks,
|
||||||
|
|
||||||
|
ComponentList.createComponentListTitle(i18n("about.dependency")),
|
||||||
|
dep,
|
||||||
|
|
||||||
|
ComponentList.createComponentListTitle(i18n("about.legal")),
|
||||||
|
legal,
|
||||||
|
|
||||||
|
ComponentList.createComponentListTitle(i18n("about.donations")),
|
||||||
|
donations
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
ScrollPane scrollPane = new ScrollPane();
|
||||||
|
scrollPane.setContent(content);
|
||||||
|
scrollPane.setFitToWidth(true);
|
||||||
|
getChildren().setAll(scrollPane);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
package org.jackhuang.hmcl.ui.main;
|
||||||
|
|
||||||
|
import javafx.beans.property.ReadOnlyObjectProperty;
|
||||||
|
import javafx.beans.property.ReadOnlyObjectWrapper;
|
||||||
|
import javafx.scene.layout.BorderPane;
|
||||||
|
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.ui.construct.AdvancedListBox;
|
||||||
|
import org.jackhuang.hmcl.ui.construct.AdvancedListItem;
|
||||||
|
import org.jackhuang.hmcl.ui.construct.TabHeader;
|
||||||
|
import org.jackhuang.hmcl.ui.decorator.DecoratorPage;
|
||||||
|
|
||||||
|
import static org.jackhuang.hmcl.ui.versions.VersionPage.wrap;
|
||||||
|
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
||||||
|
|
||||||
|
public class LauncherSettingsPage extends BorderPane implements DecoratorPage {
|
||||||
|
private final ReadOnlyObjectWrapper<State> state = new ReadOnlyObjectWrapper<>(new State(i18n("settings.launcher"), null, true, false, true, false, 200));
|
||||||
|
private final TabHeader tab;
|
||||||
|
private final TabHeader.Tab<SettingsPage> settingsTab = new TabHeader.Tab<>("settingsPage");
|
||||||
|
private final TabHeader.Tab<AboutPage> aboutTab = new TabHeader.Tab<>("aboutPage");
|
||||||
|
private final TransitionPane transitionPane = new TransitionPane();
|
||||||
|
|
||||||
|
public LauncherSettingsPage() {
|
||||||
|
settingsTab.setNodeSupplier(SettingsPage::new);
|
||||||
|
aboutTab.setNodeSupplier(AboutPage::new);
|
||||||
|
tab = new TabHeader(settingsTab, aboutTab);
|
||||||
|
|
||||||
|
tab.getSelectionModel().select(settingsTab);
|
||||||
|
FXUtils.onChangeAndOperate(tab.getSelectionModel().selectedItemProperty(), newValue -> {
|
||||||
|
newValue.initializeIfNeeded();
|
||||||
|
transitionPane.setContent(newValue.getNode(), ContainerAnimations.FADE.getAnimationProducer());
|
||||||
|
});
|
||||||
|
|
||||||
|
{
|
||||||
|
AdvancedListItem settingsItem = new AdvancedListItem();
|
||||||
|
settingsItem.getStyleClass().add("navigation-drawer-item");
|
||||||
|
settingsItem.setTitle(i18n("settings.launcher"));
|
||||||
|
settingsItem.setLeftGraphic(wrap(SVG.gearOutline(null, 20, 20)));
|
||||||
|
settingsItem.setActionButtonVisible(false);
|
||||||
|
settingsItem.activeProperty().bind(tab.getSelectionModel().selectedItemProperty().isEqualTo(settingsTab));
|
||||||
|
settingsItem.setOnAction(e -> tab.getSelectionModel().select(settingsTab));
|
||||||
|
|
||||||
|
AdvancedListItem aboutItem = new AdvancedListItem();
|
||||||
|
aboutItem.getStyleClass().add("navigation-drawer-item");
|
||||||
|
aboutItem.setTitle(i18n("about"));
|
||||||
|
aboutItem.setLeftGraphic(wrap(SVG.informationOutline(null, 20, 20)));
|
||||||
|
aboutItem.setActionButtonVisible(false);
|
||||||
|
aboutItem.activeProperty().bind(tab.getSelectionModel().selectedItemProperty().isEqualTo(aboutTab));
|
||||||
|
aboutItem.setOnAction(e -> tab.getSelectionModel().select(aboutTab));
|
||||||
|
|
||||||
|
AdvancedListBox sideBar = new AdvancedListBox()
|
||||||
|
.add(settingsItem)
|
||||||
|
.add(aboutItem);
|
||||||
|
FXUtils.setLimitWidth(sideBar, 200);
|
||||||
|
setLeft(sideBar);
|
||||||
|
}
|
||||||
|
|
||||||
|
setCenter(transitionPane);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ReadOnlyObjectProperty<State> stateProperty() {
|
||||||
|
return state.getReadOnlyProperty();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -33,6 +33,7 @@ import org.jackhuang.hmcl.task.Schedulers;
|
|||||||
import org.jackhuang.hmcl.task.Task;
|
import org.jackhuang.hmcl.task.Task;
|
||||||
import org.jackhuang.hmcl.ui.Controllers;
|
import org.jackhuang.hmcl.ui.Controllers;
|
||||||
import org.jackhuang.hmcl.ui.FXUtils;
|
import org.jackhuang.hmcl.ui.FXUtils;
|
||||||
|
import org.jackhuang.hmcl.ui.SVG;
|
||||||
import org.jackhuang.hmcl.ui.account.AccountAdvancedListItem;
|
import org.jackhuang.hmcl.ui.account.AccountAdvancedListItem;
|
||||||
import org.jackhuang.hmcl.ui.account.AccountList;
|
import org.jackhuang.hmcl.ui.account.AccountList;
|
||||||
import org.jackhuang.hmcl.ui.account.AddAccountPane;
|
import org.jackhuang.hmcl.ui.account.AddAccountPane;
|
||||||
@@ -55,8 +56,8 @@ import java.util.Date;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static org.jackhuang.hmcl.ui.FXUtils.newImage;
|
|
||||||
import static org.jackhuang.hmcl.ui.FXUtils.runInFX;
|
import static org.jackhuang.hmcl.ui.FXUtils.runInFX;
|
||||||
|
import static org.jackhuang.hmcl.ui.versions.VersionPage.wrap;
|
||||||
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
||||||
|
|
||||||
public class RootPage extends DecoratorTabPage {
|
public class RootPage extends DecoratorTabPage {
|
||||||
@@ -64,9 +65,8 @@ public class RootPage extends DecoratorTabPage {
|
|||||||
private SettingsPage settingsPage = null;
|
private SettingsPage settingsPage = null;
|
||||||
private AccountList accountListPage = null;
|
private AccountList accountListPage = null;
|
||||||
|
|
||||||
private final TabHeader.Tab mainTab = new TabHeader.Tab("main");
|
private final TabHeader.Tab<MainPage> mainTab = new TabHeader.Tab<>("main");
|
||||||
private final TabHeader.Tab settingsTab = new TabHeader.Tab("settings");
|
private final TabHeader.Tab<AccountList> accountTab = new TabHeader.Tab<>("account");
|
||||||
private final TabHeader.Tab accountTab = new TabHeader.Tab("account");
|
|
||||||
|
|
||||||
public RootPage() {
|
public RootPage() {
|
||||||
setLeftPaneWidth(200);
|
setLeftPaneWidth(200);
|
||||||
@@ -78,9 +78,8 @@ public class RootPage extends DecoratorTabPage {
|
|||||||
onRefreshedVersions(Profiles.selectedProfileProperty().get().getRepository());
|
onRefreshedVersions(Profiles.selectedProfileProperty().get().getRepository());
|
||||||
|
|
||||||
mainTab.setNodeSupplier(this::getMainPage);
|
mainTab.setNodeSupplier(this::getMainPage);
|
||||||
settingsTab.setNodeSupplier(this::getSettingsPage);
|
|
||||||
accountTab.setNodeSupplier(this::getAccountListPage);
|
accountTab.setNodeSupplier(this::getAccountListPage);
|
||||||
getTabs().setAll(mainTab, settingsTab, accountTab);
|
getTabs().setAll(mainTab, accountTab);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -155,10 +154,6 @@ public class RootPage extends DecoratorTabPage {
|
|||||||
return mainTab;
|
return mainTab;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Tab getSettingsTab() {
|
|
||||||
return settingsTab;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Tab getAccountTab() {
|
public Tab getAccountTab() {
|
||||||
return accountTab;
|
return accountTab;
|
||||||
}
|
}
|
||||||
@@ -196,22 +191,23 @@ public class RootPage extends DecoratorTabPage {
|
|||||||
|
|
||||||
// third item in left sidebar
|
// third item in left sidebar
|
||||||
AdvancedListItem gameItem = new AdvancedListItem();
|
AdvancedListItem gameItem = new AdvancedListItem();
|
||||||
gameItem.setLeftGraphic(AdvancedListItem.createImageView(newImage("/assets/img/bookshelf.png")).getKey());
|
gameItem.getStyleClass().add("navigation-drawer-item");
|
||||||
|
gameItem.setLeftGraphic(wrap(SVG.gamepad(null, 20, 20)));
|
||||||
gameItem.setTitle(i18n("version.manage"));
|
gameItem.setTitle(i18n("version.manage"));
|
||||||
gameItem.setOnAction(e -> Controllers.navigate(Controllers.getGameListPage()));
|
gameItem.setOnAction(e -> Controllers.navigate(Controllers.getGameListPage()));
|
||||||
|
|
||||||
// fifth item in left sidebar
|
// fifth item in left sidebar
|
||||||
AdvancedListItem launcherSettingsItem = new AdvancedListItem();
|
AdvancedListItem launcherSettingsItem = new AdvancedListItem();
|
||||||
launcherSettingsItem.activeProperty().bind(control.settingsTab.selectedProperty());
|
launcherSettingsItem.getStyleClass().add("navigation-drawer-item");
|
||||||
launcherSettingsItem.setLeftGraphic(AdvancedListItem.createImageView(newImage("/assets/img/command.png")).getKey());
|
launcherSettingsItem.setLeftGraphic(wrap(SVG.gearOutline(null, 20, 20)));
|
||||||
|
launcherSettingsItem.setActionButtonVisible(false);
|
||||||
launcherSettingsItem.setTitle(i18n("settings.launcher"));
|
launcherSettingsItem.setTitle(i18n("settings.launcher"));
|
||||||
launcherSettingsItem.setOnAction(e -> control.selectPage(control.settingsTab));
|
launcherSettingsItem.setOnAction(e -> Controllers.navigate(Controllers.getSettingsPage()));
|
||||||
|
|
||||||
// the left sidebar
|
// the left sidebar
|
||||||
AdvancedListBox sideBar = new AdvancedListBox()
|
AdvancedListBox sideBar = new AdvancedListBox()
|
||||||
.startCategory(i18n("account").toUpperCase())
|
|
||||||
.add(accountListItem)
|
.add(accountListItem)
|
||||||
.startCategory(i18n("version").toUpperCase())
|
.startCategory()
|
||||||
.add(gameListItem)
|
.add(gameListItem)
|
||||||
.add(gameItem)
|
.add(gameItem)
|
||||||
.startCategory(i18n("launcher").toUpperCase())
|
.startCategory(i18n("launcher").toUpperCase())
|
||||||
|
|||||||
@@ -23,8 +23,6 @@ import javafx.beans.InvalidationListener;
|
|||||||
import javafx.beans.WeakInvalidationListener;
|
import javafx.beans.WeakInvalidationListener;
|
||||||
import javafx.beans.binding.Bindings;
|
import javafx.beans.binding.Bindings;
|
||||||
import javafx.beans.binding.When;
|
import javafx.beans.binding.When;
|
||||||
import javafx.beans.property.ReadOnlyObjectProperty;
|
|
||||||
import javafx.beans.property.ReadOnlyObjectWrapper;
|
|
||||||
import javafx.scene.control.ColorPicker;
|
import javafx.scene.control.ColorPicker;
|
||||||
import javafx.scene.control.ToggleGroup;
|
import javafx.scene.control.ToggleGroup;
|
||||||
import javafx.scene.paint.Color;
|
import javafx.scene.paint.Color;
|
||||||
@@ -35,7 +33,6 @@ import org.jackhuang.hmcl.ui.Controllers;
|
|||||||
import org.jackhuang.hmcl.ui.FXUtils;
|
import org.jackhuang.hmcl.ui.FXUtils;
|
||||||
import org.jackhuang.hmcl.ui.construct.MessageDialogPane.MessageType;
|
import org.jackhuang.hmcl.ui.construct.MessageDialogPane.MessageType;
|
||||||
import org.jackhuang.hmcl.ui.construct.Validator;
|
import org.jackhuang.hmcl.ui.construct.Validator;
|
||||||
import org.jackhuang.hmcl.ui.decorator.DecoratorPage;
|
|
||||||
import org.jackhuang.hmcl.upgrade.RemoteVersion;
|
import org.jackhuang.hmcl.upgrade.RemoteVersion;
|
||||||
import org.jackhuang.hmcl.upgrade.UpdateChannel;
|
import org.jackhuang.hmcl.upgrade.UpdateChannel;
|
||||||
import org.jackhuang.hmcl.upgrade.UpdateChecker;
|
import org.jackhuang.hmcl.upgrade.UpdateChecker;
|
||||||
@@ -65,8 +62,7 @@ import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
|||||||
import static org.jackhuang.hmcl.util.javafx.ExtendedProperties.reversedSelectedPropertyFor;
|
import static org.jackhuang.hmcl.util.javafx.ExtendedProperties.reversedSelectedPropertyFor;
|
||||||
import static org.jackhuang.hmcl.util.javafx.ExtendedProperties.selectedItemPropertyFor;
|
import static org.jackhuang.hmcl.util.javafx.ExtendedProperties.selectedItemPropertyFor;
|
||||||
|
|
||||||
public final class SettingsPage extends SettingsView implements DecoratorPage {
|
public final class SettingsPage extends SettingsView {
|
||||||
private final ReadOnlyObjectWrapper<State> state = new ReadOnlyObjectWrapper<>(State.fromTitle(i18n("settings.launcher")));
|
|
||||||
|
|
||||||
private InvalidationListener updateListener;
|
private InvalidationListener updateListener;
|
||||||
|
|
||||||
@@ -196,11 +192,6 @@ public final class SettingsPage extends SettingsView implements DecoratorPage {
|
|||||||
// ====
|
// ====
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public ReadOnlyObjectProperty<State> stateProperty() {
|
|
||||||
return state.getReadOnlyProperty();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onUpdate() {
|
protected void onUpdate() {
|
||||||
RemoteVersion target = UpdateChecker.getLatestVersion();
|
RemoteVersion target = UpdateChecker.getLatestVersion();
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import javafx.beans.property.ReadOnlyObjectProperty;
|
|||||||
import javafx.beans.property.ReadOnlyObjectWrapper;
|
import javafx.beans.property.ReadOnlyObjectWrapper;
|
||||||
import javafx.geometry.Insets;
|
import javafx.geometry.Insets;
|
||||||
import javafx.geometry.Pos;
|
import javafx.geometry.Pos;
|
||||||
|
import javafx.scene.Node;
|
||||||
import javafx.scene.control.Label;
|
import javafx.scene.control.Label;
|
||||||
import javafx.scene.control.ScrollPane;
|
import javafx.scene.control.ScrollPane;
|
||||||
import javafx.scene.image.Image;
|
import javafx.scene.image.Image;
|
||||||
@@ -246,14 +247,7 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag
|
|||||||
componentList.getContent().setAll(javaItem, gameDirItem, maxMemoryPane, launcherVisibilityPane, dimensionPane, showLogsPane);
|
componentList.getContent().setAll(javaItem, gameDirItem, maxMemoryPane, launcherVisibilityPane, dimensionPane, showLogsPane);
|
||||||
}
|
}
|
||||||
|
|
||||||
HBox advancedHintPane = new HBox();
|
Node advancedHintPane = ComponentList.createComponentListTitle(i18n("settings.advanced"));
|
||||||
advancedHintPane.setAlignment(Pos.CENTER_LEFT);
|
|
||||||
advancedHintPane.setPadding(new Insets(8, 0, 0, 0));
|
|
||||||
{
|
|
||||||
Label advanced = new Label(i18n("settings.advanced"));
|
|
||||||
advanced.setStyle("-fx-text-fill: #616161");
|
|
||||||
advancedHintPane.getChildren().setAll(advanced);
|
|
||||||
}
|
|
||||||
|
|
||||||
advancedSettingsPane = new ComponentList();
|
advancedSettingsPane = new ComponentList();
|
||||||
advancedSettingsPane.setDepth(1);
|
advancedSettingsPane.setDepth(1);
|
||||||
|
|||||||
@@ -131,7 +131,8 @@
|
|||||||
|
|
||||||
.class-title {
|
.class-title {
|
||||||
-fx-font-size: 12px;
|
-fx-font-size: 12px;
|
||||||
-fx-padding: 16 16 8 16;
|
-fx-text-fill: gray;
|
||||||
|
-fx-padding: 8 0 8 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.advanced-list-box-item {
|
.advanced-list-box-item {
|
||||||
|
|||||||
BIN
HMCL/src/main/resources/assets/img/yellow_fish.png
Normal file
BIN
HMCL/src/main/resources/assets/img/yellow_fish.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 183 KiB |
Reference in New Issue
Block a user