feat: show nav to special settings page in global settings page if needed.

This commit is contained in:
huanghongxun
2021-09-23 21:20:16 +08:00
parent 3f4dbb6978
commit 79e4aa5aaf
22 changed files with 214 additions and 88 deletions

View File

@@ -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();

View File

@@ -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);

View File

@@ -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) {

View File

@@ -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);
} }

View File

@@ -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")

View File

@@ -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);
}
} }

View File

@@ -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:

View File

@@ -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);

View File

@@ -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);
} }

View File

@@ -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"));

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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());

View File

@@ -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);

View File

@@ -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);

View File

@@ -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;
} }

View File

@@ -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;

View File

@@ -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 {
} }

View File

@@ -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.

View File

@@ -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) 提供高速下載服務

View File

@@ -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 以获得稳定高速的下载服务,点击此处查阅详细信息。