feat: show nav to special settings page in global settings page if needed.
This commit is contained in:
@@ -38,12 +38,14 @@ import org.jackhuang.hmcl.util.gson.JsonUtils;
|
|||||||
import org.jackhuang.hmcl.util.io.FileUtils;
|
import org.jackhuang.hmcl.util.io.FileUtils;
|
||||||
import org.jackhuang.hmcl.util.platform.JavaVersion;
|
import org.jackhuang.hmcl.util.platform.JavaVersion;
|
||||||
import org.jackhuang.hmcl.util.platform.OperatingSystem;
|
import org.jackhuang.hmcl.util.platform.OperatingSystem;
|
||||||
|
import org.jackhuang.hmcl.util.versioning.VersionNumber;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import static org.jackhuang.hmcl.setting.ConfigHolder.config;
|
import static org.jackhuang.hmcl.setting.ConfigHolder.config;
|
||||||
import static org.jackhuang.hmcl.ui.FXUtils.newImage;
|
import static org.jackhuang.hmcl.ui.FXUtils.newImage;
|
||||||
@@ -89,6 +91,13 @@ public class HMCLGameRepository extends DefaultGameRepository {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Stream<Version> getDisplayVersions() {
|
||||||
|
return getVersions().stream()
|
||||||
|
.filter(v -> !v.isHidden())
|
||||||
|
.sorted(Comparator.comparing((Version v) -> v.getReleaseTime() == null ? new Date(0L) : v.getReleaseTime())
|
||||||
|
.thenComparing(v -> VersionNumber.asVersion(v.getId())));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void refreshVersionsImpl() {
|
protected void refreshVersionsImpl() {
|
||||||
localVersionSettings.clear();
|
localVersionSettings.clear();
|
||||||
|
|||||||
@@ -418,7 +418,7 @@ public final class LauncherHelper {
|
|||||||
if (java8.isPresent()) {
|
if (java8.isPresent()) {
|
||||||
java8required = true;
|
java8required = true;
|
||||||
setting.setJavaVersion(java8.get());
|
setting.setJavaVersion(java8.get());
|
||||||
Controllers.dialog(i18n("launch.advice.java9") + "\n" + i18n("launch.advice.corrected"), i18n("message.info"), MessageType.INFORMATION, onAccept);
|
Controllers.dialog(i18n("launch.advice.java9") + "\n" + i18n("launch.advice.corrected"), i18n("message.info"), MessageType.INFO, onAccept);
|
||||||
javaChanged = true;
|
javaChanged = true;
|
||||||
} else {
|
} else {
|
||||||
Controllers.dialog(i18n("launch.advice.java9") + "\n" + i18n("launch.advice.uncorrected"), i18n("message.error"), MessageType.ERROR, null);
|
Controllers.dialog(i18n("launch.advice.java9") + "\n" + i18n("launch.advice.uncorrected"), i18n("message.error"), MessageType.ERROR, null);
|
||||||
|
|||||||
@@ -235,7 +235,7 @@ public final class Controllers {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void dialog(String text, String title) {
|
public static void dialog(String text, String title) {
|
||||||
dialog(text, title, MessageType.INFORMATION);
|
dialog(text, title, MessageType.INFO);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void dialog(String text, String title, MessageType type) {
|
public static void dialog(String text, String title, MessageType type) {
|
||||||
|
|||||||
@@ -216,6 +216,10 @@ public final class SVG {
|
|||||||
return createSVGPath("M13,14H11V10H13M13,18H11V16H13M1,21H23L12,2L1,21Z", fill, width, height);
|
return createSVGPath("M13,14H11V10H13M13,18H11V16H13M1,21H23L12,2L1,21Z", fill, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Node alertOutline(ObjectBinding<? extends Paint> fill, double width, double height) {
|
||||||
|
return createSVGPath("M12,2L1,21H23M12,6L19.53,19H4.47M11,10V14H13V10M11,16V18H13V16", fill, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
public static Node plus(ObjectBinding<? extends Paint> fill, double width, double height) {
|
public static Node plus(ObjectBinding<? extends Paint> fill, double width, double height) {
|
||||||
return createSVGPath("M19,13H13V19H11V13H5V11H11V5H13V11H19V13Z", fill, width, height);
|
return createSVGPath("M19,13H13V19H11V13H5V11H11V5H13V11H19V13Z", fill, width, height);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -261,7 +261,7 @@ public class CreateAccountPane extends JFXDialogLayout implements DialogAware {
|
|||||||
}
|
}
|
||||||
if (factory == Accounts.FACTORY_MICROSOFT) {
|
if (factory == Accounts.FACTORY_MICROSOFT) {
|
||||||
VBox vbox = new VBox(8);
|
VBox vbox = new VBox(8);
|
||||||
HintPane hintPane = new HintPane(MessageDialogPane.MessageType.INFORMATION);
|
HintPane hintPane = new HintPane(MessageDialogPane.MessageType.INFO);
|
||||||
hintPane.textProperty().bind(BindingMapping.of(logging).map(logging ->
|
hintPane.textProperty().bind(BindingMapping.of(logging).map(logging ->
|
||||||
logging
|
logging
|
||||||
? i18n("account.methods.microsoft.manual")
|
? i18n("account.methods.microsoft.manual")
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import javafx.beans.property.SimpleStringProperty;
|
|||||||
import javafx.beans.property.StringProperty;
|
import javafx.beans.property.StringProperty;
|
||||||
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.layout.HBox;
|
import javafx.scene.layout.HBox;
|
||||||
import javafx.scene.layout.VBox;
|
import javafx.scene.layout.VBox;
|
||||||
@@ -36,27 +37,44 @@ import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
|||||||
public class HintPane extends VBox {
|
public class HintPane extends VBox {
|
||||||
private final Text label = new Text();
|
private final Text label = new Text();
|
||||||
private final StringProperty text = new SimpleStringProperty(this, "text");
|
private final StringProperty text = new SimpleStringProperty(this, "text");
|
||||||
|
private final TextFlow flow = new TextFlow();
|
||||||
|
|
||||||
public HintPane() {
|
public HintPane() {
|
||||||
this(MessageDialogPane.MessageType.INFORMATION);
|
this(MessageDialogPane.MessageType.INFO);
|
||||||
}
|
}
|
||||||
|
|
||||||
public HintPane(MessageDialogPane.MessageType type) {
|
public HintPane(MessageDialogPane.MessageType type) {
|
||||||
setFillWidth(true);
|
setFillWidth(true);
|
||||||
getStyleClass().add("hint");
|
getStyleClass().addAll("hint", type.name().toLowerCase());
|
||||||
HBox hbox = new HBox();
|
HBox hbox = new HBox();
|
||||||
hbox.setAlignment(Pos.CENTER_LEFT);
|
hbox.setAlignment(Pos.CENTER_LEFT);
|
||||||
hbox.getChildren().setAll(
|
|
||||||
SVG.informationOutline(Theme.blackFillBinding(), 16, 16),
|
switch (type) {
|
||||||
new Label(i18n("message.info"))
|
case INFO:
|
||||||
);
|
hbox.getChildren().add(SVG.informationOutline(Theme.blackFillBinding(), 16, 16));
|
||||||
TextFlow flow = new TextFlow();
|
break;
|
||||||
|
case ERROR:
|
||||||
|
hbox.getChildren().add(SVG.closeCircleOutline(Theme.blackFillBinding(), 16, 16));
|
||||||
|
break;
|
||||||
|
case SUCCESS:
|
||||||
|
hbox.getChildren().add(SVG.checkCircleOutline(Theme.blackFillBinding(), 16, 16));
|
||||||
|
break;
|
||||||
|
case WARNING:
|
||||||
|
hbox.getChildren().add(SVG.alertOutline(Theme.blackFillBinding(), 16, 16));
|
||||||
|
break;
|
||||||
|
case QUESTION:
|
||||||
|
hbox.getChildren().add(SVG.helpCircleOutline(Theme.blackFillBinding(), 16, 16));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException("Unrecognized message box message type " + type);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
hbox.getChildren().add(new Text(type.getDisplayName()));
|
||||||
flow.getChildren().setAll(label);
|
flow.getChildren().setAll(label);
|
||||||
getChildren().setAll(hbox, flow);
|
getChildren().setAll(hbox, flow);
|
||||||
label.textProperty().bind(text);
|
label.textProperty().bind(text);
|
||||||
VBox.setMargin(flow, new Insets(2, 2, 0, 2));
|
VBox.setMargin(flow, new Insets(2, 2, 0, 2));
|
||||||
|
|
||||||
label.fillProperty().bind(BindingMapping.of(disabledProperty()).map(disabled -> disabled ? new Color(0, 0, 0, 0.5) : Color.BLACK));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getText() {
|
public String getText() {
|
||||||
@@ -70,4 +88,8 @@ public class HintPane extends VBox {
|
|||||||
public void setText(String text) {
|
public void setText(String text) {
|
||||||
this.text.set(text);
|
this.text.set(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setChildren(Node... children) {
|
||||||
|
flow.getChildren().setAll(children);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,6 +31,8 @@ import org.jackhuang.hmcl.ui.SVG;
|
|||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
import static org.jackhuang.hmcl.ui.FXUtils.onEscPressed;
|
import static org.jackhuang.hmcl.ui.FXUtils.onEscPressed;
|
||||||
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
||||||
|
|
||||||
@@ -38,10 +40,14 @@ public final class MessageDialogPane extends StackPane {
|
|||||||
|
|
||||||
public enum MessageType {
|
public enum MessageType {
|
||||||
ERROR,
|
ERROR,
|
||||||
INFORMATION,
|
INFO,
|
||||||
WARNING,
|
WARNING,
|
||||||
QUESTION,
|
QUESTION,
|
||||||
FINE,
|
SUCCESS;
|
||||||
|
|
||||||
|
public String getDisplayName() {
|
||||||
|
return i18n("message." + name().toLowerCase(Locale.ROOT));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
@@ -64,13 +70,13 @@ public final class MessageDialogPane extends StackPane {
|
|||||||
this.title.setText(title);
|
this.title.setText(title);
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case INFORMATION:
|
case INFO:
|
||||||
graphic.setGraphic(SVG.infoCircle(Theme.blackFillBinding(), 40, 40));
|
graphic.setGraphic(SVG.infoCircle(Theme.blackFillBinding(), 40, 40));
|
||||||
break;
|
break;
|
||||||
case ERROR:
|
case ERROR:
|
||||||
graphic.setGraphic(SVG.closeCircle(Theme.blackFillBinding(), 40, 40));
|
graphic.setGraphic(SVG.closeCircle(Theme.blackFillBinding(), 40, 40));
|
||||||
break;
|
break;
|
||||||
case FINE:
|
case SUCCESS:
|
||||||
graphic.setGraphic(SVG.checkCircle(Theme.blackFillBinding(), 40, 40));
|
graphic.setGraphic(SVG.checkCircle(Theme.blackFillBinding(), 40, 40));
|
||||||
break;
|
break;
|
||||||
case WARNING:
|
case WARNING:
|
||||||
|
|||||||
@@ -120,7 +120,7 @@ public class ModpackInstallWizardProvider implements WizardProvider {
|
|||||||
if (exception.getCause() instanceof FileNotFoundException) {
|
if (exception.getCause() instanceof FileNotFoundException) {
|
||||||
Controllers.dialog(i18n("modpack.type.curse.not_found"), i18n("install.failed"), MessageType.ERROR, next);
|
Controllers.dialog(i18n("modpack.type.curse.not_found"), i18n("install.failed"), MessageType.ERROR, next);
|
||||||
} else {
|
} else {
|
||||||
Controllers.dialog(i18n("install.success"), i18n("install.success"), MessageType.INFORMATION, next);
|
Controllers.dialog(i18n("install.success"), i18n("install.success"), MessageType.SUCCESS, next);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
UpdateInstallerWizardProvider.alertFailureMessage(exception, next);
|
UpdateInstallerWizardProvider.alertFailureMessage(exception, next);
|
||||||
|
|||||||
@@ -187,7 +187,7 @@ public final class ModpackInfoPage extends Control implements WizardPage {
|
|||||||
});
|
});
|
||||||
borderPane.setTop(hyperlink);
|
borderPane.setTop(hyperlink);
|
||||||
} else {
|
} else {
|
||||||
HintPane pane = new HintPane(MessageDialogPane.MessageType.INFORMATION);
|
HintPane pane = new HintPane(MessageDialogPane.MessageType.INFO);
|
||||||
pane.setText(i18n("modpack.wizard.step.initialization.warning"));
|
pane.setText(i18n("modpack.wizard.step.initialization.warning"));
|
||||||
borderPane.setTop(pane);
|
borderPane.setTop(pane);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -154,7 +154,7 @@ public class DownloadSettingsPage extends StackPane {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
HintPane hintPane = new HintPane(MessageDialogPane.MessageType.INFORMATION);
|
HintPane hintPane = new HintPane(MessageDialogPane.MessageType.INFO);
|
||||||
VBox.setMargin(hintPane, new Insets(0, 0, 0, 30));
|
VBox.setMargin(hintPane, new Insets(0, 0, 0, 30));
|
||||||
hintPane.disableProperty().bind(config().autoDownloadThreadsProperty());
|
hintPane.disableProperty().bind(config().autoDownloadThreadsProperty());
|
||||||
hintPane.setText(i18n("settings.launcher.download.threads.hint"));
|
hintPane.setText(i18n("settings.launcher.download.threads.hint"));
|
||||||
|
|||||||
@@ -326,7 +326,7 @@ public class FeedbackPage extends VBox {
|
|||||||
searchHintPane.setText(i18n("feedback.add.hint.search_before_add"));
|
searchHintPane.setText(i18n("feedback.add.hint.search_before_add"));
|
||||||
body.addRow(0, searchHintPane);
|
body.addRow(0, searchHintPane);
|
||||||
|
|
||||||
HintPane titleHintPane = new HintPane(MessageDialogPane.MessageType.INFORMATION);
|
HintPane titleHintPane = new HintPane(MessageDialogPane.MessageType.INFO);
|
||||||
GridPane.setColumnSpan(titleHintPane, 2);
|
GridPane.setColumnSpan(titleHintPane, 2);
|
||||||
titleHintPane.setText(i18n("feedback.add.hint.title"));
|
titleHintPane.setText(i18n("feedback.add.hint.title"));
|
||||||
body.addRow(1, titleHintPane);
|
body.addRow(1, titleHintPane);
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ public class LauncherSettingsPage extends BorderPane implements DecoratorPage {
|
|||||||
private final TransitionPane transitionPane = new TransitionPane();
|
private final TransitionPane transitionPane = new TransitionPane();
|
||||||
|
|
||||||
public LauncherSettingsPage() {
|
public LauncherSettingsPage() {
|
||||||
gameTab.setNodeSupplier(VersionSettingsPage::new);
|
gameTab.setNodeSupplier(() -> new VersionSettingsPage(true));
|
||||||
settingsTab.setNodeSupplier(SettingsPage::new);
|
settingsTab.setNodeSupplier(SettingsPage::new);
|
||||||
personalizationTab.setNodeSupplier(PersonalizationPage::new);
|
personalizationTab.setNodeSupplier(PersonalizationPage::new);
|
||||||
downloadTab.setNodeSupplier(DownloadSettingsPage::new);
|
downloadTab.setNodeSupplier(DownloadSettingsPage::new);
|
||||||
|
|||||||
@@ -120,7 +120,7 @@ public class MultiplayerPageSkin extends SkinBase<MultiplayerPage> {
|
|||||||
scrollPane.setFitToHeight(true);
|
scrollPane.setFitToHeight(true);
|
||||||
root.setCenter(scrollPane);
|
root.setCenter(scrollPane);
|
||||||
|
|
||||||
HintPane hint = new HintPane(MessageDialogPane.MessageType.INFORMATION);
|
HintPane hint = new HintPane(MessageDialogPane.MessageType.INFO);
|
||||||
hint.setText(i18n("multiplayer.hint"));
|
hint.setText(i18n("multiplayer.hint"));
|
||||||
|
|
||||||
ComponentList roomPane = new ComponentList();
|
ComponentList roomPane = new ComponentList();
|
||||||
@@ -130,7 +130,7 @@ public class MultiplayerPageSkin extends SkinBase<MultiplayerPage> {
|
|||||||
|
|
||||||
VBox disconnectedPane = new VBox(8);
|
VBox disconnectedPane = new VBox(8);
|
||||||
{
|
{
|
||||||
HintPane hintPane = new HintPane(MessageDialogPane.MessageType.INFORMATION);
|
HintPane hintPane = new HintPane(MessageDialogPane.MessageType.INFO);
|
||||||
hintPane.setText(i18n("multiplayer.state.disconnected.hint"));
|
hintPane.setText(i18n("multiplayer.state.disconnected.hint"));
|
||||||
|
|
||||||
Label label = new Label(i18n("multiplayer.state.disconnected"));
|
Label label = new Label(i18n("multiplayer.state.disconnected"));
|
||||||
@@ -190,7 +190,7 @@ public class MultiplayerPageSkin extends SkinBase<MultiplayerPage> {
|
|||||||
pane.setHgap(16);
|
pane.setHgap(16);
|
||||||
pane.setVgap(8);
|
pane.setVgap(8);
|
||||||
|
|
||||||
HintPane hintPane = new HintPane(MessageDialogPane.MessageType.INFORMATION);
|
HintPane hintPane = new HintPane(MessageDialogPane.MessageType.INFO);
|
||||||
hintPane.setText(i18n("multiplayer.nat.hint"));
|
hintPane.setText(i18n("multiplayer.nat.hint"));
|
||||||
GridPane.setColumnSpan(hintPane, 2);
|
GridPane.setColumnSpan(hintPane, 2);
|
||||||
pane.addRow(0, hintPane);
|
pane.addRow(0, hintPane);
|
||||||
|
|||||||
@@ -124,10 +124,7 @@ public class DownloadListPage extends Control implements DecoratorPage, VersionP
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (versionSelection) {
|
if (versionSelection) {
|
||||||
versions.setAll(profile.getRepository().getVersions().stream()
|
versions.setAll(profile.getRepository().getDisplayVersions()
|
||||||
.filter(v -> !v.isHidden())
|
|
||||||
.sorted(Comparator.comparing((Version v) -> v.getReleaseTime() == null ? new Date(0L) : v.getReleaseTime())
|
|
||||||
.thenComparing(v -> VersionNumber.asVersion(v.getId())))
|
|
||||||
.map(Version::getId)
|
.map(Version::getId)
|
||||||
.collect(Collectors.toList()));
|
.collect(Collectors.toList()));
|
||||||
selectedVersion.set(profile.getSelectedVersion());
|
selectedVersion.set(profile.getSelectedVersion());
|
||||||
|
|||||||
@@ -190,15 +190,12 @@ public class GameListPage extends ListPageBase<GameListItem> implements Decorato
|
|||||||
toggleGroup = new ToggleGroup();
|
toggleGroup = new ToggleGroup();
|
||||||
WeakListenerHolder listenerHolder = new WeakListenerHolder();
|
WeakListenerHolder listenerHolder = new WeakListenerHolder();
|
||||||
toggleGroup.getProperties().put("ReferenceHolder", listenerHolder);
|
toggleGroup.getProperties().put("ReferenceHolder", listenerHolder);
|
||||||
List<GameListItem> children = repository.getVersions().parallelStream()
|
|
||||||
.filter(version -> !version.isHidden())
|
|
||||||
.sorted(Comparator.comparing((Version version) -> version.getReleaseTime() == null ? new Date(0L) : version.getReleaseTime())
|
|
||||||
.thenComparing(a -> VersionNumber.asVersion(a.getId())))
|
|
||||||
.map(version -> new GameListItem(toggleGroup, profile, version.getId()))
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
runInFX(() -> {
|
runInFX(() -> {
|
||||||
if (profile == Profiles.getSelectedProfile()) {
|
if (profile == Profiles.getSelectedProfile()) {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
|
List<GameListItem> children = repository.getDisplayVersions()
|
||||||
|
.map(version -> new GameListItem(toggleGroup, profile, version.getId()))
|
||||||
|
.collect(Collectors.toList());
|
||||||
itemsProperty().setAll(children);
|
itemsProperty().setAll(children);
|
||||||
children.forEach(GameListItem::checkSelection);
|
children.forEach(GameListItem::checkSelection);
|
||||||
|
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ public class VersionPage extends Control implements DecoratorPage {
|
|||||||
private String preferredVersionName = null;
|
private String preferredVersionName = null;
|
||||||
|
|
||||||
{
|
{
|
||||||
versionSettingsTab.setNodeSupplier(VersionSettingsPage::new);
|
versionSettingsTab.setNodeSupplier(() -> new VersionSettingsPage(false));
|
||||||
modListTab.setNodeSupplier(ModListPage::new);
|
modListTab.setNodeSupplier(ModListPage::new);
|
||||||
installerListTab.setNodeSupplier(InstallerListPage::new);
|
installerListTab.setNodeSupplier(InstallerListPage::new);
|
||||||
worldListTab.setNodeSupplier(WorldListPage::new);
|
worldListTab.setNodeSupplier(WorldListPage::new);
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ 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;
|
||||||
import javafx.scene.layout.*;
|
import javafx.scene.layout.*;
|
||||||
|
import javafx.scene.text.Text;
|
||||||
import javafx.stage.FileChooser;
|
import javafx.stage.FileChooser;
|
||||||
import org.jackhuang.hmcl.game.GameDirectoryType;
|
import org.jackhuang.hmcl.game.GameDirectoryType;
|
||||||
import org.jackhuang.hmcl.game.HMCLGameRepository;
|
import org.jackhuang.hmcl.game.HMCLGameRepository;
|
||||||
@@ -42,11 +43,13 @@ 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.WeakListenerHolder;
|
||||||
import org.jackhuang.hmcl.ui.construct.*;
|
import org.jackhuang.hmcl.ui.construct.*;
|
||||||
import org.jackhuang.hmcl.ui.decorator.DecoratorPage;
|
import org.jackhuang.hmcl.ui.decorator.DecoratorPage;
|
||||||
import org.jackhuang.hmcl.util.Lang;
|
import org.jackhuang.hmcl.util.Lang;
|
||||||
import org.jackhuang.hmcl.util.Logging;
|
import org.jackhuang.hmcl.util.Logging;
|
||||||
import org.jackhuang.hmcl.util.io.FileUtils;
|
import org.jackhuang.hmcl.util.io.FileUtils;
|
||||||
|
import org.jackhuang.hmcl.util.javafx.BindingMapping;
|
||||||
import org.jackhuang.hmcl.util.javafx.SafeStringConverter;
|
import org.jackhuang.hmcl.util.javafx.SafeStringConverter;
|
||||||
import org.jackhuang.hmcl.util.platform.JavaVersion;
|
import org.jackhuang.hmcl.util.platform.JavaVersion;
|
||||||
import org.jackhuang.hmcl.util.platform.OperatingSystem;
|
import org.jackhuang.hmcl.util.platform.OperatingSystem;
|
||||||
@@ -69,8 +72,11 @@ import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
|||||||
public final class VersionSettingsPage extends StackPane implements DecoratorPage, VersionPage.VersionLoadable {
|
public final class VersionSettingsPage extends StackPane implements DecoratorPage, VersionPage.VersionLoadable {
|
||||||
private final ReadOnlyObjectWrapper<State> state = new ReadOnlyObjectWrapper<>(new State("", null, false, false, false));
|
private final ReadOnlyObjectWrapper<State> state = new ReadOnlyObjectWrapper<>(new State("", null, false, false, false));
|
||||||
|
|
||||||
|
private final boolean globalSetting;
|
||||||
|
|
||||||
private VersionSetting lastVersionSetting = null;
|
private VersionSetting lastVersionSetting = null;
|
||||||
private Profile profile;
|
private Profile profile;
|
||||||
|
private WeakListenerHolder listenerHolder;
|
||||||
private String versionId;
|
private String versionId;
|
||||||
private boolean javaItemsLoaded;
|
private boolean javaItemsLoaded;
|
||||||
|
|
||||||
@@ -85,7 +91,6 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag
|
|||||||
private final JFXTextField txtPostExitCommand;
|
private final JFXTextField txtPostExitCommand;
|
||||||
private final JFXTextField txtServerIP;
|
private final JFXTextField txtServerIP;
|
||||||
private final ComponentList componentList;
|
private final ComponentList componentList;
|
||||||
private final ComponentList iconPickerItemWrapper;
|
|
||||||
private final JFXComboBox<LauncherVisibility> cboLauncherVisibility;
|
private final JFXComboBox<LauncherVisibility> cboLauncherVisibility;
|
||||||
private final JFXCheckBox chkAutoAllocate;
|
private final JFXCheckBox chkAutoAllocate;
|
||||||
private final JFXCheckBox chkFullscreen;
|
private final JFXCheckBox chkFullscreen;
|
||||||
@@ -102,19 +107,23 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag
|
|||||||
private final MultiFileItem.FileOption<NativesDirectoryType> nativesDirCustomOption;
|
private final MultiFileItem.FileOption<NativesDirectoryType> nativesDirCustomOption;
|
||||||
private final JFXComboBox<ProcessPriority> cboProcessPriority;
|
private final JFXComboBox<ProcessPriority> cboProcessPriority;
|
||||||
private final OptionToggleButton showLogsPane;
|
private final OptionToggleButton showLogsPane;
|
||||||
private final ImagePickerItem iconPickerItem;
|
private ImagePickerItem iconPickerItem;
|
||||||
private final JFXCheckBox chkEnableSpecificSettings;
|
|
||||||
private final BorderPane settingsTypePane;
|
|
||||||
|
|
||||||
private final InvalidationListener specificSettingsListener;
|
private final InvalidationListener specificSettingsListener;
|
||||||
|
|
||||||
private final InvalidationListener javaListener = any -> initJavaSubtitle();
|
private final InvalidationListener javaListener = any -> initJavaSubtitle();
|
||||||
|
|
||||||
private boolean uiVisible = false;
|
private boolean uiVisible = false;
|
||||||
private final IntegerProperty maxMemoryProperty = new SimpleIntegerProperty();
|
private final StringProperty selectedVersion = new SimpleStringProperty();
|
||||||
private final ObjectProperty<OperatingSystem.PhysicalMemoryStatus> memoryStatusProperty = new SimpleObjectProperty<>(OperatingSystem.PhysicalMemoryStatus.INVALID);
|
private final BooleanProperty navigateToSpecificSettings = new SimpleBooleanProperty(false);
|
||||||
|
private final BooleanProperty enableSpecificSettings = new SimpleBooleanProperty(true);
|
||||||
|
private final IntegerProperty maxMemory = new SimpleIntegerProperty();
|
||||||
|
private final ObjectProperty<OperatingSystem.PhysicalMemoryStatus> memoryStatus = new SimpleObjectProperty<>(OperatingSystem.PhysicalMemoryStatus.INVALID);
|
||||||
|
private final BooleanProperty modpack = new SimpleBooleanProperty();
|
||||||
|
|
||||||
|
public VersionSettingsPage(boolean globalSetting) {
|
||||||
|
this.globalSetting = globalSetting;
|
||||||
|
|
||||||
public VersionSettingsPage() {
|
|
||||||
ScrollPane scrollPane = new ScrollPane();
|
ScrollPane scrollPane = new ScrollPane();
|
||||||
scrollPane.setFitToHeight(true);
|
scrollPane.setFitToHeight(true);
|
||||||
scrollPane.setFitToWidth(true);
|
scrollPane.setFitToWidth(true);
|
||||||
@@ -122,34 +131,58 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag
|
|||||||
getChildren().setAll(scrollPane);
|
getChildren().setAll(scrollPane);
|
||||||
|
|
||||||
rootPane = new VBox();
|
rootPane = new VBox();
|
||||||
|
rootPane.setFillWidth(true);
|
||||||
scrollPane.setContent(rootPane);
|
scrollPane.setContent(rootPane);
|
||||||
FXUtils.smoothScrolling(scrollPane);
|
FXUtils.smoothScrolling(scrollPane);
|
||||||
rootPane.getStyleClass().add("card-list");
|
rootPane.getStyleClass().add("card-list");
|
||||||
|
|
||||||
{
|
if (globalSetting) {
|
||||||
iconPickerItemWrapper = new ComponentList();
|
HintPane skinHint = new HintPane(MessageDialogPane.MessageType.INFO);
|
||||||
|
skinHint.setText(i18n("settings.skin"));
|
||||||
|
rootPane.getChildren().add(skinHint);
|
||||||
|
|
||||||
|
HintPane specificSettingsHint = new HintPane(MessageDialogPane.MessageType.WARNING);
|
||||||
|
Text text = new Text();
|
||||||
|
text.textProperty().bind(BindingMapping.of(selectedVersion)
|
||||||
|
.map(selectedVersion -> i18n("settings.type.special.edit.hint", selectedVersion)));
|
||||||
|
|
||||||
|
JFXHyperlink specificSettingsLink = new JFXHyperlink();
|
||||||
|
specificSettingsLink.setText(i18n("settings.type.special.edit"));
|
||||||
|
specificSettingsLink.setOnMouseClicked(e -> editSpecificSettings());
|
||||||
|
|
||||||
|
specificSettingsHint.setChildren(text, specificSettingsLink);
|
||||||
|
|
||||||
|
rootPane.getChildren().addAll(specificSettingsHint);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!globalSetting) {
|
||||||
|
ComponentList iconPickerItemWrapper = new ComponentList();
|
||||||
|
rootPane.getChildren().add(iconPickerItemWrapper);
|
||||||
|
|
||||||
iconPickerItem = new ImagePickerItem();
|
iconPickerItem = new ImagePickerItem();
|
||||||
iconPickerItem.setImage(new Image("/assets/img/icon.png"));
|
iconPickerItem.setImage(new Image("/assets/img/icon.png"));
|
||||||
iconPickerItem.setTitle(i18n("settings.icon"));
|
iconPickerItem.setTitle(i18n("settings.icon"));
|
||||||
iconPickerItem.setOnSelectButtonClicked(e -> onExploreIcon());
|
iconPickerItem.setOnSelectButtonClicked(e -> onExploreIcon());
|
||||||
iconPickerItem.setOnDeleteButtonClicked(e -> onDeleteIcon());
|
iconPickerItem.setOnDeleteButtonClicked(e -> onDeleteIcon());
|
||||||
iconPickerItemWrapper.getContent().setAll(iconPickerItem);
|
iconPickerItemWrapper.getContent().setAll(iconPickerItem);
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
settingsTypePane = new BorderPane();
|
|
||||||
|
|
||||||
chkEnableSpecificSettings = new JFXCheckBox();
|
BorderPane settingsTypePane = new BorderPane();
|
||||||
settingsTypePane.setLeft(chkEnableSpecificSettings);
|
settingsTypePane.disableProperty().bind(modpack);
|
||||||
chkEnableSpecificSettings.setText(i18n("settings.type.special.enable"));
|
rootPane.getChildren().add(settingsTypePane);
|
||||||
BorderPane.setAlignment(chkEnableSpecificSettings, Pos.CENTER_RIGHT);
|
|
||||||
|
JFXCheckBox enableSpecificCheckBox = new JFXCheckBox();
|
||||||
|
enableSpecificCheckBox.selectedProperty().bindBidirectional(enableSpecificSettings);
|
||||||
|
settingsTypePane.setLeft(enableSpecificCheckBox);
|
||||||
|
enableSpecificCheckBox.setText(i18n("settings.type.special.enable"));
|
||||||
|
BorderPane.setAlignment(enableSpecificCheckBox, Pos.CENTER_RIGHT);
|
||||||
|
|
||||||
JFXButton editGlobalSettingsButton = new JFXButton();
|
JFXButton editGlobalSettingsButton = new JFXButton();
|
||||||
settingsTypePane.setRight(editGlobalSettingsButton);
|
settingsTypePane.setRight(editGlobalSettingsButton);
|
||||||
editGlobalSettingsButton.setText(i18n("settings.type.global.edit"));
|
editGlobalSettingsButton.setText(i18n("settings.type.global.edit"));
|
||||||
editGlobalSettingsButton.getStyleClass().add("jfx-button-raised");
|
editGlobalSettingsButton.getStyleClass().add("jfx-button-raised");
|
||||||
editGlobalSettingsButton.setButtonType(JFXButton.ButtonType.RAISED);
|
editGlobalSettingsButton.setButtonType(JFXButton.ButtonType.RAISED);
|
||||||
editGlobalSettingsButton.disableProperty().bind(chkEnableSpecificSettings.selectedProperty());
|
editGlobalSettingsButton.disableProperty().bind(enableSpecificCheckBox.selectedProperty());
|
||||||
BorderPane.setAlignment(editGlobalSettingsButton, Pos.CENTER_RIGHT);
|
BorderPane.setAlignment(editGlobalSettingsButton, Pos.CENTER_RIGHT);
|
||||||
editGlobalSettingsButton.setOnMouseClicked(e -> editGlobalSettings());
|
editGlobalSettingsButton.setOnMouseClicked(e -> editGlobalSettings());
|
||||||
}
|
}
|
||||||
@@ -167,6 +200,7 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag
|
|||||||
gameDirItem = new MultiFileItem<>();
|
gameDirItem = new MultiFileItem<>();
|
||||||
gameDirItem.setTitle(i18n("settings.game.working_directory"));
|
gameDirItem.setTitle(i18n("settings.game.working_directory"));
|
||||||
gameDirItem.setHasSubtitle(true);
|
gameDirItem.setHasSubtitle(true);
|
||||||
|
gameDirItem.disableProperty().bind(modpack);
|
||||||
gameDirCustomOption = new MultiFileItem.FileOption<>(i18n("settings.custom"), GameDirectoryType.CUSTOM)
|
gameDirCustomOption = new MultiFileItem.FileOption<>(i18n("settings.custom"), GameDirectoryType.CUSTOM)
|
||||||
.setChooserTitle(i18n("settings.game.working_directory.choose"))
|
.setChooserTitle(i18n("settings.game.working_directory.choose"))
|
||||||
.setDirectory(true);
|
.setDirectory(true);
|
||||||
@@ -203,20 +237,20 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag
|
|||||||
HBox.setHgrow(slider, Priority.ALWAYS);
|
HBox.setHgrow(slider, Priority.ALWAYS);
|
||||||
slider.setValueFactory(self -> Bindings.createStringBinding(() -> (int) (self.getValue() * 100) + "%", self.valueProperty()));
|
slider.setValueFactory(self -> Bindings.createStringBinding(() -> (int) (self.getValue() * 100) + "%", self.valueProperty()));
|
||||||
AtomicBoolean changedByTextField = new AtomicBoolean(false);
|
AtomicBoolean changedByTextField = new AtomicBoolean(false);
|
||||||
FXUtils.onChangeAndOperate(maxMemoryProperty, maxMemory -> {
|
FXUtils.onChangeAndOperate(maxMemory, maxMemory -> {
|
||||||
changedByTextField.set(true);
|
changedByTextField.set(true);
|
||||||
slider.setValue(maxMemory.intValue() * 1.0 / OperatingSystem.TOTAL_MEMORY);
|
slider.setValue(maxMemory.intValue() * 1.0 / OperatingSystem.TOTAL_MEMORY);
|
||||||
changedByTextField.set(false);
|
changedByTextField.set(false);
|
||||||
});
|
});
|
||||||
slider.valueProperty().addListener((value, oldVal, newVal) -> {
|
slider.valueProperty().addListener((value, oldVal, newVal) -> {
|
||||||
if (changedByTextField.get()) return;
|
if (changedByTextField.get()) return;
|
||||||
maxMemoryProperty.set((int) (value.getValue().doubleValue() * OperatingSystem.TOTAL_MEMORY));
|
maxMemory.set((int) (value.getValue().doubleValue() * OperatingSystem.TOTAL_MEMORY));
|
||||||
});
|
});
|
||||||
|
|
||||||
JFXTextField txtMaxMemory = new JFXTextField();
|
JFXTextField txtMaxMemory = new JFXTextField();
|
||||||
FXUtils.setLimitWidth(txtMaxMemory, 60);
|
FXUtils.setLimitWidth(txtMaxMemory, 60);
|
||||||
FXUtils.setValidateWhileTextChanged(txtMaxMemory, true);
|
FXUtils.setValidateWhileTextChanged(txtMaxMemory, true);
|
||||||
txtMaxMemory.textProperty().bindBidirectional(maxMemoryProperty, SafeStringConverter.fromInteger());
|
txtMaxMemory.textProperty().bindBidirectional(maxMemory, SafeStringConverter.fromInteger());
|
||||||
txtMaxMemory.setValidators(new NumberValidator(i18n("input.number"), false));
|
txtMaxMemory.setValidators(new NumberValidator(i18n("input.number"), false));
|
||||||
|
|
||||||
lowerBoundPane.getChildren().setAll(label, slider, txtMaxMemory, new Label("MB"));
|
lowerBoundPane.getChildren().setAll(label, slider, txtMaxMemory, new Label("MB"));
|
||||||
@@ -233,16 +267,16 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag
|
|||||||
usedMemory.getStyleClass().add("memory-used");
|
usedMemory.getStyleClass().add("memory-used");
|
||||||
usedMemory.maxWidthProperty().bind(Bindings.createDoubleBinding(() ->
|
usedMemory.maxWidthProperty().bind(Bindings.createDoubleBinding(() ->
|
||||||
progressBarPane.getWidth() *
|
progressBarPane.getWidth() *
|
||||||
(memoryStatusProperty.get().getUsed() * 1.0 / memoryStatusProperty.get().getTotal()), progressBarPane.widthProperty(),
|
(memoryStatus.get().getUsed() * 1.0 / memoryStatus.get().getTotal()), progressBarPane.widthProperty(),
|
||||||
memoryStatusProperty));
|
memoryStatus));
|
||||||
StackPane allocateMemory = new StackPane();
|
StackPane allocateMemory = new StackPane();
|
||||||
allocateMemory.getStyleClass().add("memory-allocate");
|
allocateMemory.getStyleClass().add("memory-allocate");
|
||||||
allocateMemory.maxWidthProperty().bind(Bindings.createDoubleBinding(() ->
|
allocateMemory.maxWidthProperty().bind(Bindings.createDoubleBinding(() ->
|
||||||
progressBarPane.getWidth() *
|
progressBarPane.getWidth() *
|
||||||
Math.min(1.0,
|
Math.min(1.0,
|
||||||
(double) (HMCLGameRepository.getAllocatedMemory(maxMemoryProperty.get() * 1024L * 1024L, memoryStatusProperty.get().getAvailable(), chkAutoAllocate.isSelected())
|
(double) (HMCLGameRepository.getAllocatedMemory(maxMemory.get() * 1024L * 1024L, memoryStatus.get().getAvailable(), chkAutoAllocate.isSelected())
|
||||||
+ memoryStatusProperty.get().getUsed()) / memoryStatusProperty.get().getTotal()), progressBarPane.widthProperty(),
|
+ memoryStatus.get().getUsed()) / memoryStatus.get().getTotal()), progressBarPane.widthProperty(),
|
||||||
maxMemoryProperty, memoryStatusProperty, chkAutoAllocate.selectedProperty()));
|
maxMemory, memoryStatus, chkAutoAllocate.selectedProperty()));
|
||||||
|
|
||||||
progressBarPane.getChildren().setAll(allocateMemory, usedMemory);
|
progressBarPane.getChildren().setAll(allocateMemory, usedMemory);
|
||||||
}
|
}
|
||||||
@@ -254,19 +288,19 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag
|
|||||||
lblPhysicalMemory.getStyleClass().add("memory-label");
|
lblPhysicalMemory.getStyleClass().add("memory-label");
|
||||||
digitalPane.setLeft(lblPhysicalMemory);
|
digitalPane.setLeft(lblPhysicalMemory);
|
||||||
lblPhysicalMemory.textProperty().bind(Bindings.createStringBinding(() -> {
|
lblPhysicalMemory.textProperty().bind(Bindings.createStringBinding(() -> {
|
||||||
return i18n("settings.memory.used_per_total", memoryStatusProperty.get().getUsedGB(), memoryStatusProperty.get().getTotalGB());
|
return i18n("settings.memory.used_per_total", memoryStatus.get().getUsedGB(), memoryStatus.get().getTotalGB());
|
||||||
}, memoryStatusProperty));
|
}, memoryStatus));
|
||||||
|
|
||||||
Label lblAllocateMemory = new Label();
|
Label lblAllocateMemory = new Label();
|
||||||
lblAllocateMemory.textProperty().bind(Bindings.createStringBinding(() -> {
|
lblAllocateMemory.textProperty().bind(Bindings.createStringBinding(() -> {
|
||||||
long maxMemory = Lang.parseInt(maxMemoryProperty.get(), 0) * 1024L * 1024L;
|
long maxMemory = Lang.parseInt(this.maxMemory.get(), 0) * 1024L * 1024L;
|
||||||
return i18n(memoryStatusProperty.get().hasAvailable() && maxMemory > memoryStatusProperty.get().getAvailable()
|
return i18n(memoryStatus.get().hasAvailable() && maxMemory > memoryStatus.get().getAvailable()
|
||||||
? (chkAutoAllocate.isSelected() ? "settings.memory.allocate.auto.exceeded" : "settings.memory.allocate.manual.exceeded")
|
? (chkAutoAllocate.isSelected() ? "settings.memory.allocate.auto.exceeded" : "settings.memory.allocate.manual.exceeded")
|
||||||
: (chkAutoAllocate.isSelected() ? "settings.memory.allocate.auto" : "settings.memory.allocate.manual"),
|
: (chkAutoAllocate.isSelected() ? "settings.memory.allocate.auto" : "settings.memory.allocate.manual"),
|
||||||
OperatingSystem.PhysicalMemoryStatus.toGigaBytes(maxMemory),
|
OperatingSystem.PhysicalMemoryStatus.toGigaBytes(maxMemory),
|
||||||
OperatingSystem.PhysicalMemoryStatus.toGigaBytes(HMCLGameRepository.getAllocatedMemory(maxMemory, memoryStatusProperty.get().getAvailable(), chkAutoAllocate.isSelected())),
|
OperatingSystem.PhysicalMemoryStatus.toGigaBytes(HMCLGameRepository.getAllocatedMemory(maxMemory, memoryStatus.get().getAvailable(), chkAutoAllocate.isSelected())),
|
||||||
OperatingSystem.PhysicalMemoryStatus.toGigaBytes(memoryStatusProperty.get().getAvailable()));
|
OperatingSystem.PhysicalMemoryStatus.toGigaBytes(memoryStatus.get().getAvailable()));
|
||||||
}, memoryStatusProperty, maxMemoryProperty, chkAutoAllocate.selectedProperty()));
|
}, memoryStatus, maxMemory, chkAutoAllocate.selectedProperty()));
|
||||||
lblAllocateMemory.getStyleClass().add("memory-label");
|
lblAllocateMemory.getStyleClass().add("memory-label");
|
||||||
digitalPane.setRight(lblAllocateMemory);
|
digitalPane.setRight(lblAllocateMemory);
|
||||||
}
|
}
|
||||||
@@ -374,7 +408,7 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag
|
|||||||
}
|
}
|
||||||
|
|
||||||
ComponentList customCommandsPane = new ComponentList();
|
ComponentList customCommandsPane = new ComponentList();
|
||||||
customCommandsPane.disableProperty().bind(chkEnableSpecificSettings.selectedProperty().not());
|
customCommandsPane.disableProperty().bind(enableSpecificSettings.not());
|
||||||
{
|
{
|
||||||
GridPane pane = new GridPane();
|
GridPane pane = new GridPane();
|
||||||
pane.setHgap(16);
|
pane.setHgap(16);
|
||||||
@@ -410,7 +444,7 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag
|
|||||||
}
|
}
|
||||||
|
|
||||||
ComponentList jvmPane = new ComponentList();
|
ComponentList jvmPane = new ComponentList();
|
||||||
jvmPane.disableProperty().bind(chkEnableSpecificSettings.selectedProperty().not());
|
jvmPane.disableProperty().bind(enableSpecificSettings.not());
|
||||||
{
|
{
|
||||||
GridPane pane = new GridPane();
|
GridPane pane = new GridPane();
|
||||||
ColumnConstraints title = new ColumnConstraints();
|
ColumnConstraints title = new ColumnConstraints();
|
||||||
@@ -437,7 +471,7 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag
|
|||||||
}
|
}
|
||||||
|
|
||||||
ComponentList workaroundPane = new ComponentList();
|
ComponentList workaroundPane = new ComponentList();
|
||||||
workaroundPane.disableProperty().bind(chkEnableSpecificSettings.selectedProperty().not());
|
workaroundPane.disableProperty().bind(enableSpecificSettings.not());
|
||||||
{
|
{
|
||||||
nativesDirItem = new MultiFileItem<>();
|
nativesDirItem = new MultiFileItem<>();
|
||||||
nativesDirItem.setTitle(i18n("settings.advanced.natives_directory"));
|
nativesDirItem.setTitle(i18n("settings.advanced.natives_directory"));
|
||||||
@@ -468,7 +502,7 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag
|
|||||||
workaroundPane.getContent().setAll(nativesDirItem, noJVMArgsPane, noGameCheckPane, noJVMCheckPane, useNativeGLFWPane, useNativeOpenALPane);
|
workaroundPane.getContent().setAll(nativesDirItem, noJVMArgsPane, noGameCheckPane, noJVMCheckPane, useNativeGLFWPane, useNativeOpenALPane);
|
||||||
}
|
}
|
||||||
|
|
||||||
rootPane.getChildren().setAll(iconPickerItemWrapper, settingsTypePane, componentList,
|
rootPane.getChildren().addAll(componentList,
|
||||||
advancedHintPane,
|
advancedHintPane,
|
||||||
ComponentList.createComponentListTitle(i18n("settings.advanced.custom_commands")), customCommandsPane,
|
ComponentList.createComponentListTitle(i18n("settings.advanced.custom_commands")), customCommandsPane,
|
||||||
ComponentList.createComponentListTitle(i18n("settings.advanced.jvm")), jvmPane,
|
ComponentList.createComponentListTitle(i18n("settings.advanced.jvm")), jvmPane,
|
||||||
@@ -477,7 +511,7 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag
|
|||||||
initialize();
|
initialize();
|
||||||
|
|
||||||
specificSettingsListener = any -> {
|
specificSettingsListener = any -> {
|
||||||
chkEnableSpecificSettings.setSelected(!lastVersionSetting.isUsesGlobal());
|
enableSpecificSettings.set(!lastVersionSetting.isUsesGlobal());
|
||||||
};
|
};
|
||||||
|
|
||||||
addEventHandler(Navigator.NavigationEvent.NAVIGATED, this::onDecoratorPageNavigating);
|
addEventHandler(Navigator.NavigationEvent.NAVIGATED, this::onDecoratorPageNavigating);
|
||||||
@@ -490,7 +524,7 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void initialize() {
|
private void initialize() {
|
||||||
memoryStatusProperty.set(OperatingSystem.getPhysicalMemoryStatus().orElse(OperatingSystem.PhysicalMemoryStatus.INVALID));
|
memoryStatus.set(OperatingSystem.getPhysicalMemoryStatus().orElse(OperatingSystem.PhysicalMemoryStatus.INVALID));
|
||||||
|
|
||||||
Task.supplyAsync(JavaVersion::getJavas).thenAcceptAsync(Schedulers.javafx(), list -> {
|
Task.supplyAsync(JavaVersion::getJavas).thenAcceptAsync(Schedulers.javafx(), list -> {
|
||||||
List<MultiFileItem.Option<JavaVersion>> options = list.stream()
|
List<MultiFileItem.Option<JavaVersion>> options = list.stream()
|
||||||
@@ -509,7 +543,7 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag
|
|||||||
if (OperatingSystem.CURRENT_OS == OperatingSystem.WINDOWS)
|
if (OperatingSystem.CURRENT_OS == OperatingSystem.WINDOWS)
|
||||||
javaCustomOption.getExtensionFilters().add(new FileChooser.ExtensionFilter("Java", "java.exe", "javaw.exe"));
|
javaCustomOption.getExtensionFilters().add(new FileChooser.ExtensionFilter("Java", "java.exe", "javaw.exe"));
|
||||||
|
|
||||||
chkEnableSpecificSettings.selectedProperty().addListener((a, b, newValue) -> {
|
enableSpecificSettings.addListener((a, b, newValue) -> {
|
||||||
if (versionId == null) return;
|
if (versionId == null) return;
|
||||||
|
|
||||||
// do not call versionSettings.setUsesGlobal(true/false)
|
// do not call versionSettings.setUsesGlobal(true/false)
|
||||||
@@ -523,31 +557,36 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag
|
|||||||
Platform.runLater(() -> loadVersion(profile, versionId));
|
Platform.runLater(() -> loadVersion(profile, versionId));
|
||||||
});
|
});
|
||||||
|
|
||||||
componentList.disableProperty().bind(chkEnableSpecificSettings.selectedProperty().not());
|
componentList.disableProperty().bind(enableSpecificSettings.not());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void loadVersion(Profile profile, String versionId) {
|
public void loadVersion(Profile profile, String versionId) {
|
||||||
this.profile = profile;
|
this.profile = profile;
|
||||||
this.versionId = versionId;
|
this.versionId = versionId;
|
||||||
|
this.listenerHolder = new WeakListenerHolder();
|
||||||
|
|
||||||
if (versionId == null) {
|
if (versionId == null) {
|
||||||
rootPane.getChildren().remove(iconPickerItemWrapper);
|
enableSpecificSettings.set(true);
|
||||||
rootPane.getChildren().remove(settingsTypePane);
|
|
||||||
chkEnableSpecificSettings.setSelected(true);
|
|
||||||
state.set(State.fromTitle(Profiles.getProfileDisplayName(profile) + " - " + i18n("settings.type.global.manage")));
|
state.set(State.fromTitle(Profiles.getProfileDisplayName(profile) + " - " + i18n("settings.type.global.manage")));
|
||||||
|
|
||||||
|
listenerHolder.add(FXUtils.onWeakChangeAndOperate(profile.selectedVersionProperty(), selectedVersion -> {
|
||||||
|
this.selectedVersion.setValue(selectedVersion);
|
||||||
|
navigateToSpecificSettings.set(!profile.getRepository().getVersionSetting(selectedVersion).isUsesGlobal());
|
||||||
|
}));
|
||||||
|
} else {
|
||||||
|
navigateToSpecificSettings.set(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
VersionSetting versionSetting = profile.getVersionSetting(versionId);
|
VersionSetting versionSetting = profile.getVersionSetting(versionId);
|
||||||
|
|
||||||
gameDirItem.setDisable(versionId != null && profile.getRepository().isModpack(versionId));
|
modpack.set(versionId != null && profile.getRepository().isModpack(versionId));
|
||||||
settingsTypePane.setDisable(versionId != null && profile.getRepository().isModpack(versionId));
|
|
||||||
|
|
||||||
// unbind data fields
|
// unbind data fields
|
||||||
if (lastVersionSetting != null) {
|
if (lastVersionSetting != null) {
|
||||||
FXUtils.unbindInt(txtWidth, lastVersionSetting.widthProperty());
|
FXUtils.unbindInt(txtWidth, lastVersionSetting.widthProperty());
|
||||||
FXUtils.unbindInt(txtHeight, lastVersionSetting.heightProperty());
|
FXUtils.unbindInt(txtHeight, lastVersionSetting.heightProperty());
|
||||||
maxMemoryProperty.unbindBidirectional(lastVersionSetting.maxMemoryProperty());
|
maxMemory.unbindBidirectional(lastVersionSetting.maxMemoryProperty());
|
||||||
javaCustomOption.valueProperty().unbindBidirectional(lastVersionSetting.javaDirProperty());
|
javaCustomOption.valueProperty().unbindBidirectional(lastVersionSetting.javaDirProperty());
|
||||||
gameDirCustomOption.valueProperty().unbindBidirectional(lastVersionSetting.gameDirProperty());
|
gameDirCustomOption.valueProperty().unbindBidirectional(lastVersionSetting.gameDirProperty());
|
||||||
nativesDirCustomOption.valueProperty().unbindBidirectional(lastVersionSetting.nativesDirProperty());
|
nativesDirCustomOption.valueProperty().unbindBidirectional(lastVersionSetting.nativesDirProperty());
|
||||||
@@ -586,7 +625,7 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag
|
|||||||
// bind new data fields
|
// bind new data fields
|
||||||
FXUtils.bindInt(txtWidth, versionSetting.widthProperty());
|
FXUtils.bindInt(txtWidth, versionSetting.widthProperty());
|
||||||
FXUtils.bindInt(txtHeight, versionSetting.heightProperty());
|
FXUtils.bindInt(txtHeight, versionSetting.heightProperty());
|
||||||
maxMemoryProperty.bindBidirectional(versionSetting.maxMemoryProperty());
|
maxMemory.bindBidirectional(versionSetting.maxMemoryProperty());
|
||||||
|
|
||||||
javaCustomOption.bindBidirectional(versionSetting.javaDirProperty());
|
javaCustomOption.bindBidirectional(versionSetting.javaDirProperty());
|
||||||
gameDirCustomOption.bindBidirectional(versionSetting.gameDirProperty());
|
gameDirCustomOption.bindBidirectional(versionSetting.gameDirProperty());
|
||||||
@@ -610,7 +649,7 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag
|
|||||||
|
|
||||||
versionSetting.usesGlobalProperty().addListener(specificSettingsListener);
|
versionSetting.usesGlobalProperty().addListener(specificSettingsListener);
|
||||||
if (versionId != null)
|
if (versionId != null)
|
||||||
chkEnableSpecificSettings.setSelected(!versionSetting.isUsesGlobal());
|
enableSpecificSettings.set(!versionSetting.isUsesGlobal());
|
||||||
|
|
||||||
javaItem.setToggleSelectedListener(newValue -> {
|
javaItem.setToggleSelectedListener(newValue -> {
|
||||||
if (newValue.getUserData() == null) {
|
if (newValue.getUserData() == null) {
|
||||||
@@ -669,6 +708,10 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag
|
|||||||
.start();
|
.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void editSpecificSettings() {
|
||||||
|
Versions.modifyGameSettings(profile, profile.getSelectedVersion());
|
||||||
|
}
|
||||||
|
|
||||||
private void editGlobalSettings() {
|
private void editGlobalSettings() {
|
||||||
Versions.modifyGlobalSettings(profile);
|
Versions.modifyGlobalSettings(profile);
|
||||||
}
|
}
|
||||||
@@ -703,7 +746,6 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag
|
|||||||
|
|
||||||
private void loadIcon() {
|
private void loadIcon() {
|
||||||
if (versionId == null) {
|
if (versionId == null) {
|
||||||
iconPickerItem.setImage(newImage("/assets/img/grass.png"));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -62,9 +62,9 @@ public abstract class TaskExecutorDialogWizardDisplayer extends AbstractWizardDi
|
|||||||
runInFX(() -> {
|
runInFX(() -> {
|
||||||
if (success) {
|
if (success) {
|
||||||
if (settings.containsKey("success_message") && settings.get("success_message") instanceof String)
|
if (settings.containsKey("success_message") && settings.get("success_message") instanceof String)
|
||||||
Controllers.dialog((String) settings.get("success_message"), null, MessageType.FINE, () -> onEnd());
|
Controllers.dialog((String) settings.get("success_message"), null, MessageType.SUCCESS, () -> onEnd());
|
||||||
else if (!settings.containsKey("forbid_success_message"))
|
else if (!settings.containsKey("forbid_success_message"))
|
||||||
Controllers.dialog(i18n("message.success"), null, MessageType.FINE, () -> onEnd());
|
Controllers.dialog(i18n("message.success"), null, MessageType.SUCCESS, () -> onEnd());
|
||||||
} else {
|
} else {
|
||||||
if (executor.getException() == null)
|
if (executor.getException() == null)
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -43,14 +43,54 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.hint {
|
.hint {
|
||||||
-fx-border-color: #b8daff;
|
|
||||||
-fx-background-color: #cce5ff;
|
|
||||||
-fx-background-radius: 5;
|
-fx-background-radius: 5;
|
||||||
-fx-border-width: 1;
|
-fx-border-width: 1;
|
||||||
-fx-border-radius: 5;
|
-fx-border-radius: 5;
|
||||||
-fx-padding: 6;
|
-fx-padding: 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Colors are picked from bootstrap
|
||||||
|
|
||||||
|
https://getbootstrap.com/docs/4.1/components/alerts/
|
||||||
|
*/
|
||||||
|
|
||||||
|
.hint.info {
|
||||||
|
-fx-background-color: #cce5ff;
|
||||||
|
-fx-border-color: #b8daff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hint.info Text, .hint.info .svg {
|
||||||
|
-fx-fill: #004085;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hint.success {
|
||||||
|
-fx-background-color: #d4edda;
|
||||||
|
-fx-border-color: #c3e6cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hint.success Text, .hint.success .svg {
|
||||||
|
-fx-fill: #155724;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hint.error {
|
||||||
|
-fx-background-color: #f8d7da;
|
||||||
|
-fx-border-color: #f5c6cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hint.error Text, .hint.error .svg {
|
||||||
|
-fx-fill: #721c24;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hint.warning {
|
||||||
|
-fx-background-color: #fff3cd;
|
||||||
|
-fx-border-color: #ffeeba;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hint.warning Text, .hint.warning .svg {
|
||||||
|
-fx-fill: #856404;
|
||||||
|
}
|
||||||
|
|
||||||
.memory-label {
|
.memory-label {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -797,12 +797,15 @@ settings.memory.lower_bound=Minimum Memory
|
|||||||
settings.memory.used_per_total=%1$.1f GB Used / %2$.1f GB Total
|
settings.memory.used_per_total=%1$.1f GB Used / %2$.1f GB Total
|
||||||
settings.physical_memory=Physical Memory Size
|
settings.physical_memory=Physical Memory Size
|
||||||
settings.show_log=Show Logs
|
settings.show_log=Show Logs
|
||||||
|
settings.skin=Now changing skin of offline account is supported! Go to account page and change your skin now!
|
||||||
settings.tabs.installers=Installers
|
settings.tabs.installers=Installers
|
||||||
settings.type=Version setting type
|
settings.type=Version setting type
|
||||||
settings.type.global=Global game settings (all settings shared among games)
|
settings.type.global=Global game settings (all settings shared among games)
|
||||||
settings.type.global.manage=Global Game Settings
|
settings.type.global.manage=Global Game Settings
|
||||||
settings.type.global.edit=Configure global game settings
|
settings.type.global.edit=Configure global game settings
|
||||||
settings.type.special.enable=Enable specialized settings for this game
|
settings.type.special.enable=Enable specialized settings for this game
|
||||||
|
settings.type.special.edit=Configure current game settings
|
||||||
|
settings.type.special.edit.hint=Current game version %s has enabled specialized settings, resulting in options in current page not applied to that game version. Click link to configure current game settings.
|
||||||
|
|
||||||
sponsor=Donations
|
sponsor=Donations
|
||||||
sponsor.bmclapi=Download services are provided by BMCLAPI and MCBBS. Click here for more information.
|
sponsor.bmclapi=Download services are provided by BMCLAPI and MCBBS. Click here for more information.
|
||||||
|
|||||||
@@ -796,12 +796,15 @@ settings.memory.lower_bound=最低分配
|
|||||||
settings.memory.used_per_total=已使用 %1$.1f GB / 總記憶體 %2$.1f GB
|
settings.memory.used_per_total=已使用 %1$.1f GB / 總記憶體 %2$.1f GB
|
||||||
settings.physical_memory=實體記憶體大小
|
settings.physical_memory=實體記憶體大小
|
||||||
settings.show_log=查看記錄
|
settings.show_log=查看記錄
|
||||||
|
settings.skin=現已支持離線帳戶更換皮膚,你可以到帳戶頁面更改離線帳戶的皮膚和披風(多人遊戲下其他玩家無法看到你的皮膚)
|
||||||
settings.tabs.installers=自動安裝
|
settings.tabs.installers=自動安裝
|
||||||
settings.type=版本設定類型
|
settings.type=版本設定類型
|
||||||
settings.type.global=全域版本設定(使用該設定的版本共用一套設定)
|
settings.type.global=全域版本設定(使用該設定的版本共用一套設定)
|
||||||
settings.type.global.manage=全域遊戲設定
|
settings.type.global.manage=全域遊戲設定
|
||||||
settings.type.global.edit=編輯全域遊戲設定
|
settings.type.global.edit=編輯全域遊戲設定
|
||||||
settings.type.special.enable=啟用遊戲特別設定(不影響其他遊戲版本)
|
settings.type.special.enable=啟用遊戲特別設定(不影響其他遊戲版本)
|
||||||
|
settings.type.special.edit=編輯遊戲特定設置
|
||||||
|
settings.type.special.edit.hint=當前遊戲版本 %s 啟動了遊戲特定設置,本頁面選項不對當前遊戲生效。點擊連結以修改當前遊戲設置。
|
||||||
|
|
||||||
sponsor=贊助
|
sponsor=贊助
|
||||||
sponsor.bmclapi=大中華區下載源由 BMCLAPI 和我的世界中文論壇 (MCBBS) 提供高速下載服務
|
sponsor.bmclapi=大中華區下載源由 BMCLAPI 和我的世界中文論壇 (MCBBS) 提供高速下載服務
|
||||||
|
|||||||
@@ -796,12 +796,15 @@ settings.memory.lower_bound=最低分配
|
|||||||
settings.memory.used_per_total=已使用 %1$.1f GB / 总内存 %2$.1f GB
|
settings.memory.used_per_total=已使用 %1$.1f GB / 总内存 %2$.1f GB
|
||||||
settings.physical_memory=物理内存大小
|
settings.physical_memory=物理内存大小
|
||||||
settings.show_log=查看日志
|
settings.show_log=查看日志
|
||||||
|
settings.skin=现已支持离线账户更换皮肤,你可以到账户页面更改离线账户的皮肤和披风(多人游戏下其他玩家无法看到你的皮肤)
|
||||||
settings.tabs.installers=自动安装
|
settings.tabs.installers=自动安装
|
||||||
settings.type=版本设置类型
|
settings.type=版本设置类型
|
||||||
settings.type.global=全局版本设置(使用该设置的版本共用一套设定)
|
settings.type.global=全局版本设置(使用该设置的版本共用一套设定)
|
||||||
settings.type.global.manage=全局游戏设置
|
settings.type.global.manage=全局游戏设置
|
||||||
settings.type.global.edit=编辑全局版本设置
|
settings.type.global.edit=编辑全局版本设置
|
||||||
settings.type.special.enable=启用游戏特定设置(不影响其他游戏版本)
|
settings.type.special.enable=启用游戏特定设置(不影响其他游戏版本)
|
||||||
|
settings.type.special.edit=编辑游戏特定设置
|
||||||
|
settings.type.special.edit.hint=当前游戏版本 %s 启动了游戏特定设置,本页面选项不对当前游戏生效。点击链接以修改当前游戏设置。
|
||||||
|
|
||||||
sponsor=赞助
|
sponsor=赞助
|
||||||
sponsor.bmclapi=国内下载源由 BMCLAPI 和我的世界中文论坛 (MCBBS) 提供高速下载服务。BMCLAPI 是公益服务,请赞助 BMCLAPI 以获得稳定高速的下载服务,点击此处查阅详细信息。
|
sponsor.bmclapi=国内下载源由 BMCLAPI 和我的世界中文论坛 (MCBBS) 提供高速下载服务。BMCLAPI 是公益服务,请赞助 BMCLAPI 以获得稳定高速的下载服务,点击此处查阅详细信息。
|
||||||
|
|||||||
Reference in New Issue
Block a user