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.platform.JavaVersion;
import org.jackhuang.hmcl.util.platform.OperatingSystem;
import org.jackhuang.hmcl.util.versioning.VersionNumber;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.*;
import java.util.logging.Level;
import java.util.stream.Stream;
import static org.jackhuang.hmcl.setting.ConfigHolder.config;
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
protected void refreshVersionsImpl() {
localVersionSettings.clear();

View File

@ -418,7 +418,7 @@ public final class LauncherHelper {
if (java8.isPresent()) {
java8required = true;
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;
} else {
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) {
dialog(text, title, MessageType.INFORMATION);
dialog(text, title, MessageType.INFO);
}
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);
}
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) {
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) {
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 ->
logging
? i18n("account.methods.microsoft.manual")

View File

@ -21,6 +21,7 @@ import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.control.Label;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
@ -36,27 +37,44 @@ import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
public class HintPane extends VBox {
private final Text label = new Text();
private final StringProperty text = new SimpleStringProperty(this, "text");
private final TextFlow flow = new TextFlow();
public HintPane() {
this(MessageDialogPane.MessageType.INFORMATION);
this(MessageDialogPane.MessageType.INFO);
}
public HintPane(MessageDialogPane.MessageType type) {
setFillWidth(true);
getStyleClass().add("hint");
getStyleClass().addAll("hint", type.name().toLowerCase());
HBox hbox = new HBox();
hbox.setAlignment(Pos.CENTER_LEFT);
hbox.getChildren().setAll(
SVG.informationOutline(Theme.blackFillBinding(), 16, 16),
new Label(i18n("message.info"))
);
TextFlow flow = new TextFlow();
switch (type) {
case INFO:
hbox.getChildren().add(SVG.informationOutline(Theme.blackFillBinding(), 16, 16));
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);
getChildren().setAll(hbox, flow);
label.textProperty().bind(text);
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() {
@ -70,4 +88,8 @@ public class HintPane extends VBox {
public void setText(String 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.Nullable;
import java.util.Locale;
import static org.jackhuang.hmcl.ui.FXUtils.onEscPressed;
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
@ -38,10 +40,14 @@ public final class MessageDialogPane extends StackPane {
public enum MessageType {
ERROR,
INFORMATION,
INFO,
WARNING,
QUESTION,
FINE,
SUCCESS;
public String getDisplayName() {
return i18n("message." + name().toLowerCase(Locale.ROOT));
}
}
@FXML
@ -64,13 +70,13 @@ public final class MessageDialogPane extends StackPane {
this.title.setText(title);
switch (type) {
case INFORMATION:
case INFO:
graphic.setGraphic(SVG.infoCircle(Theme.blackFillBinding(), 40, 40));
break;
case ERROR:
graphic.setGraphic(SVG.closeCircle(Theme.blackFillBinding(), 40, 40));
break;
case FINE:
case SUCCESS:
graphic.setGraphic(SVG.checkCircle(Theme.blackFillBinding(), 40, 40));
break;
case WARNING:

View File

@ -120,7 +120,7 @@ public class ModpackInstallWizardProvider implements WizardProvider {
if (exception.getCause() instanceof FileNotFoundException) {
Controllers.dialog(i18n("modpack.type.curse.not_found"), i18n("install.failed"), MessageType.ERROR, next);
} else {
Controllers.dialog(i18n("install.success"), i18n("install.success"), MessageType.INFORMATION, next);
Controllers.dialog(i18n("install.success"), i18n("install.success"), MessageType.SUCCESS, next);
}
} else {
UpdateInstallerWizardProvider.alertFailureMessage(exception, next);

View File

@ -187,7 +187,7 @@ public final class ModpackInfoPage extends Control implements WizardPage {
});
borderPane.setTop(hyperlink);
} else {
HintPane pane = new HintPane(MessageDialogPane.MessageType.INFORMATION);
HintPane pane = new HintPane(MessageDialogPane.MessageType.INFO);
pane.setText(i18n("modpack.wizard.step.initialization.warning"));
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));
hintPane.disableProperty().bind(config().autoDownloadThreadsProperty());
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"));
body.addRow(0, searchHintPane);
HintPane titleHintPane = new HintPane(MessageDialogPane.MessageType.INFORMATION);
HintPane titleHintPane = new HintPane(MessageDialogPane.MessageType.INFO);
GridPane.setColumnSpan(titleHintPane, 2);
titleHintPane.setText(i18n("feedback.add.hint.title"));
body.addRow(1, titleHintPane);

View File

@ -48,7 +48,7 @@ public class LauncherSettingsPage extends BorderPane implements DecoratorPage {
private final TransitionPane transitionPane = new TransitionPane();
public LauncherSettingsPage() {
gameTab.setNodeSupplier(VersionSettingsPage::new);
gameTab.setNodeSupplier(() -> new VersionSettingsPage(true));
settingsTab.setNodeSupplier(SettingsPage::new);
personalizationTab.setNodeSupplier(PersonalizationPage::new);
downloadTab.setNodeSupplier(DownloadSettingsPage::new);

View File

@ -120,7 +120,7 @@ public class MultiplayerPageSkin extends SkinBase<MultiplayerPage> {
scrollPane.setFitToHeight(true);
root.setCenter(scrollPane);
HintPane hint = new HintPane(MessageDialogPane.MessageType.INFORMATION);
HintPane hint = new HintPane(MessageDialogPane.MessageType.INFO);
hint.setText(i18n("multiplayer.hint"));
ComponentList roomPane = new ComponentList();
@ -130,7 +130,7 @@ public class MultiplayerPageSkin extends SkinBase<MultiplayerPage> {
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"));
Label label = new Label(i18n("multiplayer.state.disconnected"));
@ -190,7 +190,7 @@ public class MultiplayerPageSkin extends SkinBase<MultiplayerPage> {
pane.setHgap(16);
pane.setVgap(8);
HintPane hintPane = new HintPane(MessageDialogPane.MessageType.INFORMATION);
HintPane hintPane = new HintPane(MessageDialogPane.MessageType.INFO);
hintPane.setText(i18n("multiplayer.nat.hint"));
GridPane.setColumnSpan(hintPane, 2);
pane.addRow(0, hintPane);

View File

@ -124,10 +124,7 @@ public class DownloadListPage extends Control implements DecoratorPage, VersionP
}
if (versionSelection) {
versions.setAll(profile.getRepository().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())))
versions.setAll(profile.getRepository().getDisplayVersions()
.map(Version::getId)
.collect(Collectors.toList()));
selectedVersion.set(profile.getSelectedVersion());

View File

@ -190,15 +190,12 @@ public class GameListPage extends ListPageBase<GameListItem> implements Decorato
toggleGroup = new ToggleGroup();
WeakListenerHolder listenerHolder = new WeakListenerHolder();
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(() -> {
if (profile == Profiles.getSelectedProfile()) {
setLoading(false);
List<GameListItem> children = repository.getDisplayVersions()
.map(version -> new GameListItem(toggleGroup, profile, version.getId()))
.collect(Collectors.toList());
itemsProperty().setAll(children);
children.forEach(GameListItem::checkSelection);

View File

@ -57,7 +57,7 @@ public class VersionPage extends Control implements DecoratorPage {
private String preferredVersionName = null;
{
versionSettingsTab.setNodeSupplier(VersionSettingsPage::new);
versionSettingsTab.setNodeSupplier(() -> new VersionSettingsPage(false));
modListTab.setNodeSupplier(ModListPage::new);
installerListTab.setNodeSupplier(InstallerListPage::new);
worldListTab.setNodeSupplier(WorldListPage::new);

View File

@ -29,6 +29,7 @@ import javafx.scene.control.Label;
import javafx.scene.control.ScrollPane;
import javafx.scene.image.Image;
import javafx.scene.layout.*;
import javafx.scene.text.Text;
import javafx.stage.FileChooser;
import org.jackhuang.hmcl.game.GameDirectoryType;
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.ui.Controllers;
import org.jackhuang.hmcl.ui.FXUtils;
import org.jackhuang.hmcl.ui.WeakListenerHolder;
import org.jackhuang.hmcl.ui.construct.*;
import org.jackhuang.hmcl.ui.decorator.DecoratorPage;
import org.jackhuang.hmcl.util.Lang;
import org.jackhuang.hmcl.util.Logging;
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.platform.JavaVersion;
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 {
private final ReadOnlyObjectWrapper<State> state = new ReadOnlyObjectWrapper<>(new State("", null, false, false, false));
private final boolean globalSetting;
private VersionSetting lastVersionSetting = null;
private Profile profile;
private WeakListenerHolder listenerHolder;
private String versionId;
private boolean javaItemsLoaded;
@ -85,7 +91,6 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag
private final JFXTextField txtPostExitCommand;
private final JFXTextField txtServerIP;
private final ComponentList componentList;
private final ComponentList iconPickerItemWrapper;
private final JFXComboBox<LauncherVisibility> cboLauncherVisibility;
private final JFXCheckBox chkAutoAllocate;
private final JFXCheckBox chkFullscreen;
@ -102,19 +107,23 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag
private final MultiFileItem.FileOption<NativesDirectoryType> nativesDirCustomOption;
private final JFXComboBox<ProcessPriority> cboProcessPriority;
private final OptionToggleButton showLogsPane;
private final ImagePickerItem iconPickerItem;
private final JFXCheckBox chkEnableSpecificSettings;
private final BorderPane settingsTypePane;
private ImagePickerItem iconPickerItem;
private final InvalidationListener specificSettingsListener;
private final InvalidationListener javaListener = any -> initJavaSubtitle();
private boolean uiVisible = false;
private final IntegerProperty maxMemoryProperty = new SimpleIntegerProperty();
private final ObjectProperty<OperatingSystem.PhysicalMemoryStatus> memoryStatusProperty = new SimpleObjectProperty<>(OperatingSystem.PhysicalMemoryStatus.INVALID);
private final StringProperty selectedVersion = new SimpleStringProperty();
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.setFitToHeight(true);
scrollPane.setFitToWidth(true);
@ -122,34 +131,58 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag
getChildren().setAll(scrollPane);
rootPane = new VBox();
rootPane.setFillWidth(true);
scrollPane.setContent(rootPane);
FXUtils.smoothScrolling(scrollPane);
rootPane.getStyleClass().add("card-list");
{
iconPickerItemWrapper = new ComponentList();
if (globalSetting) {
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.setImage(new Image("/assets/img/icon.png"));
iconPickerItem.setTitle(i18n("settings.icon"));
iconPickerItem.setOnSelectButtonClicked(e -> onExploreIcon());
iconPickerItem.setOnDeleteButtonClicked(e -> onDeleteIcon());
iconPickerItemWrapper.getContent().setAll(iconPickerItem);
}
{
settingsTypePane = new BorderPane();
chkEnableSpecificSettings = new JFXCheckBox();
settingsTypePane.setLeft(chkEnableSpecificSettings);
chkEnableSpecificSettings.setText(i18n("settings.type.special.enable"));
BorderPane.setAlignment(chkEnableSpecificSettings, Pos.CENTER_RIGHT);
BorderPane settingsTypePane = new BorderPane();
settingsTypePane.disableProperty().bind(modpack);
rootPane.getChildren().add(settingsTypePane);
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();
settingsTypePane.setRight(editGlobalSettingsButton);
editGlobalSettingsButton.setText(i18n("settings.type.global.edit"));
editGlobalSettingsButton.getStyleClass().add("jfx-button-raised");
editGlobalSettingsButton.setButtonType(JFXButton.ButtonType.RAISED);
editGlobalSettingsButton.disableProperty().bind(chkEnableSpecificSettings.selectedProperty());
editGlobalSettingsButton.disableProperty().bind(enableSpecificCheckBox.selectedProperty());
BorderPane.setAlignment(editGlobalSettingsButton, Pos.CENTER_RIGHT);
editGlobalSettingsButton.setOnMouseClicked(e -> editGlobalSettings());
}
@ -167,6 +200,7 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag
gameDirItem = new MultiFileItem<>();
gameDirItem.setTitle(i18n("settings.game.working_directory"));
gameDirItem.setHasSubtitle(true);
gameDirItem.disableProperty().bind(modpack);
gameDirCustomOption = new MultiFileItem.FileOption<>(i18n("settings.custom"), GameDirectoryType.CUSTOM)
.setChooserTitle(i18n("settings.game.working_directory.choose"))
.setDirectory(true);
@ -203,20 +237,20 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag
HBox.setHgrow(slider, Priority.ALWAYS);
slider.setValueFactory(self -> Bindings.createStringBinding(() -> (int) (self.getValue() * 100) + "%", self.valueProperty()));
AtomicBoolean changedByTextField = new AtomicBoolean(false);
FXUtils.onChangeAndOperate(maxMemoryProperty, maxMemory -> {
FXUtils.onChangeAndOperate(maxMemory, maxMemory -> {
changedByTextField.set(true);
slider.setValue(maxMemory.intValue() * 1.0 / OperatingSystem.TOTAL_MEMORY);
changedByTextField.set(false);
});
slider.valueProperty().addListener((value, oldVal, newVal) -> {
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();
FXUtils.setLimitWidth(txtMaxMemory, 60);
FXUtils.setValidateWhileTextChanged(txtMaxMemory, true);
txtMaxMemory.textProperty().bindBidirectional(maxMemoryProperty, SafeStringConverter.fromInteger());
txtMaxMemory.textProperty().bindBidirectional(maxMemory, SafeStringConverter.fromInteger());
txtMaxMemory.setValidators(new NumberValidator(i18n("input.number"), false));
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.maxWidthProperty().bind(Bindings.createDoubleBinding(() ->
progressBarPane.getWidth() *
(memoryStatusProperty.get().getUsed() * 1.0 / memoryStatusProperty.get().getTotal()), progressBarPane.widthProperty(),
memoryStatusProperty));
(memoryStatus.get().getUsed() * 1.0 / memoryStatus.get().getTotal()), progressBarPane.widthProperty(),
memoryStatus));
StackPane allocateMemory = new StackPane();
allocateMemory.getStyleClass().add("memory-allocate");
allocateMemory.maxWidthProperty().bind(Bindings.createDoubleBinding(() ->
progressBarPane.getWidth() *
Math.min(1.0,
(double) (HMCLGameRepository.getAllocatedMemory(maxMemoryProperty.get() * 1024L * 1024L, memoryStatusProperty.get().getAvailable(), chkAutoAllocate.isSelected())
+ memoryStatusProperty.get().getUsed()) / memoryStatusProperty.get().getTotal()), progressBarPane.widthProperty(),
maxMemoryProperty, memoryStatusProperty, chkAutoAllocate.selectedProperty()));
(double) (HMCLGameRepository.getAllocatedMemory(maxMemory.get() * 1024L * 1024L, memoryStatus.get().getAvailable(), chkAutoAllocate.isSelected())
+ memoryStatus.get().getUsed()) / memoryStatus.get().getTotal()), progressBarPane.widthProperty(),
maxMemory, memoryStatus, chkAutoAllocate.selectedProperty()));
progressBarPane.getChildren().setAll(allocateMemory, usedMemory);
}
@ -254,19 +288,19 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag
lblPhysicalMemory.getStyleClass().add("memory-label");
digitalPane.setLeft(lblPhysicalMemory);
lblPhysicalMemory.textProperty().bind(Bindings.createStringBinding(() -> {
return i18n("settings.memory.used_per_total", memoryStatusProperty.get().getUsedGB(), memoryStatusProperty.get().getTotalGB());
}, memoryStatusProperty));
return i18n("settings.memory.used_per_total", memoryStatus.get().getUsedGB(), memoryStatus.get().getTotalGB());
}, memoryStatus));
Label lblAllocateMemory = new Label();
lblAllocateMemory.textProperty().bind(Bindings.createStringBinding(() -> {
long maxMemory = Lang.parseInt(maxMemoryProperty.get(), 0) * 1024L * 1024L;
return i18n(memoryStatusProperty.get().hasAvailable() && maxMemory > memoryStatusProperty.get().getAvailable()
long maxMemory = Lang.parseInt(this.maxMemory.get(), 0) * 1024L * 1024L;
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" : "settings.memory.allocate.manual"),
OperatingSystem.PhysicalMemoryStatus.toGigaBytes(maxMemory),
OperatingSystem.PhysicalMemoryStatus.toGigaBytes(HMCLGameRepository.getAllocatedMemory(maxMemory, memoryStatusProperty.get().getAvailable(), chkAutoAllocate.isSelected())),
OperatingSystem.PhysicalMemoryStatus.toGigaBytes(memoryStatusProperty.get().getAvailable()));
}, memoryStatusProperty, maxMemoryProperty, chkAutoAllocate.selectedProperty()));
OperatingSystem.PhysicalMemoryStatus.toGigaBytes(HMCLGameRepository.getAllocatedMemory(maxMemory, memoryStatus.get().getAvailable(), chkAutoAllocate.isSelected())),
OperatingSystem.PhysicalMemoryStatus.toGigaBytes(memoryStatus.get().getAvailable()));
}, memoryStatus, maxMemory, chkAutoAllocate.selectedProperty()));
lblAllocateMemory.getStyleClass().add("memory-label");
digitalPane.setRight(lblAllocateMemory);
}
@ -374,7 +408,7 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag
}
ComponentList customCommandsPane = new ComponentList();
customCommandsPane.disableProperty().bind(chkEnableSpecificSettings.selectedProperty().not());
customCommandsPane.disableProperty().bind(enableSpecificSettings.not());
{
GridPane pane = new GridPane();
pane.setHgap(16);
@ -410,7 +444,7 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag
}
ComponentList jvmPane = new ComponentList();
jvmPane.disableProperty().bind(chkEnableSpecificSettings.selectedProperty().not());
jvmPane.disableProperty().bind(enableSpecificSettings.not());
{
GridPane pane = new GridPane();
ColumnConstraints title = new ColumnConstraints();
@ -437,7 +471,7 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag
}
ComponentList workaroundPane = new ComponentList();
workaroundPane.disableProperty().bind(chkEnableSpecificSettings.selectedProperty().not());
workaroundPane.disableProperty().bind(enableSpecificSettings.not());
{
nativesDirItem = new MultiFileItem<>();
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);
}
rootPane.getChildren().setAll(iconPickerItemWrapper, settingsTypePane, componentList,
rootPane.getChildren().addAll(componentList,
advancedHintPane,
ComponentList.createComponentListTitle(i18n("settings.advanced.custom_commands")), customCommandsPane,
ComponentList.createComponentListTitle(i18n("settings.advanced.jvm")), jvmPane,
@ -477,7 +511,7 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag
initialize();
specificSettingsListener = any -> {
chkEnableSpecificSettings.setSelected(!lastVersionSetting.isUsesGlobal());
enableSpecificSettings.set(!lastVersionSetting.isUsesGlobal());
};
addEventHandler(Navigator.NavigationEvent.NAVIGATED, this::onDecoratorPageNavigating);
@ -490,7 +524,7 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag
}
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 -> {
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)
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;
// do not call versionSettings.setUsesGlobal(true/false)
@ -523,31 +557,36 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag
Platform.runLater(() -> loadVersion(profile, versionId));
});
componentList.disableProperty().bind(chkEnableSpecificSettings.selectedProperty().not());
componentList.disableProperty().bind(enableSpecificSettings.not());
}
@Override
public void loadVersion(Profile profile, String versionId) {
this.profile = profile;
this.versionId = versionId;
this.listenerHolder = new WeakListenerHolder();
if (versionId == null) {
rootPane.getChildren().remove(iconPickerItemWrapper);
rootPane.getChildren().remove(settingsTypePane);
chkEnableSpecificSettings.setSelected(true);
enableSpecificSettings.set(true);
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);
gameDirItem.setDisable(versionId != null && profile.getRepository().isModpack(versionId));
settingsTypePane.setDisable(versionId != null && profile.getRepository().isModpack(versionId));
modpack.set(versionId != null && profile.getRepository().isModpack(versionId));
// unbind data fields
if (lastVersionSetting != null) {
FXUtils.unbindInt(txtWidth, lastVersionSetting.widthProperty());
FXUtils.unbindInt(txtHeight, lastVersionSetting.heightProperty());
maxMemoryProperty.unbindBidirectional(lastVersionSetting.maxMemoryProperty());
maxMemory.unbindBidirectional(lastVersionSetting.maxMemoryProperty());
javaCustomOption.valueProperty().unbindBidirectional(lastVersionSetting.javaDirProperty());
gameDirCustomOption.valueProperty().unbindBidirectional(lastVersionSetting.gameDirProperty());
nativesDirCustomOption.valueProperty().unbindBidirectional(lastVersionSetting.nativesDirProperty());
@ -586,7 +625,7 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag
// bind new data fields
FXUtils.bindInt(txtWidth, versionSetting.widthProperty());
FXUtils.bindInt(txtHeight, versionSetting.heightProperty());
maxMemoryProperty.bindBidirectional(versionSetting.maxMemoryProperty());
maxMemory.bindBidirectional(versionSetting.maxMemoryProperty());
javaCustomOption.bindBidirectional(versionSetting.javaDirProperty());
gameDirCustomOption.bindBidirectional(versionSetting.gameDirProperty());
@ -610,7 +649,7 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag
versionSetting.usesGlobalProperty().addListener(specificSettingsListener);
if (versionId != null)
chkEnableSpecificSettings.setSelected(!versionSetting.isUsesGlobal());
enableSpecificSettings.set(!versionSetting.isUsesGlobal());
javaItem.setToggleSelectedListener(newValue -> {
if (newValue.getUserData() == null) {
@ -669,6 +708,10 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag
.start();
}
private void editSpecificSettings() {
Versions.modifyGameSettings(profile, profile.getSelectedVersion());
}
private void editGlobalSettings() {
Versions.modifyGlobalSettings(profile);
}
@ -703,7 +746,6 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag
private void loadIcon() {
if (versionId == null) {
iconPickerItem.setImage(newImage("/assets/img/grass.png"));
return;
}

View File

@ -62,9 +62,9 @@ public abstract class TaskExecutorDialogWizardDisplayer extends AbstractWizardDi
runInFX(() -> {
if (success) {
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"))
Controllers.dialog(i18n("message.success"), null, MessageType.FINE, () -> onEnd());
Controllers.dialog(i18n("message.success"), null, MessageType.SUCCESS, () -> onEnd());
} else {
if (executor.getException() == null)
return;

View File

@ -43,14 +43,54 @@
}
.hint {
-fx-border-color: #b8daff;
-fx-background-color: #cce5ff;
-fx-background-radius: 5;
-fx-border-width: 1;
-fx-border-radius: 5;
-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 {
}

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.physical_memory=Physical Memory Size
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.type=Version setting type
settings.type.global=Global game settings (all settings shared among games)
settings.type.global.manage=Global Game Settings
settings.type.global.edit=Configure global game settings
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.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.physical_memory=實體記憶體大小
settings.show_log=查看記錄
settings.skin=現已支持離線帳戶更換皮膚,你可以到帳戶頁面更改離線帳戶的皮膚和披風(多人遊戲下其他玩家無法看到你的皮膚)
settings.tabs.installers=自動安裝
settings.type=版本設定類型
settings.type.global=全域版本設定(使用該設定的版本共用一套設定)
settings.type.global.manage=全域遊戲設定
settings.type.global.edit=編輯全域遊戲設定
settings.type.special.enable=啟用遊戲特別設定(不影響其他遊戲版本)
settings.type.special.edit=編輯遊戲特定設置
settings.type.special.edit.hint=當前遊戲版本 %s 啟動了遊戲特定設置,本頁面選項不對當前遊戲生效。點擊連結以修改當前遊戲設置。
sponsor=贊助
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.physical_memory=物理内存大小
settings.show_log=查看日志
settings.skin=现已支持离线账户更换皮肤,你可以到账户页面更改离线账户的皮肤和披风(多人游戏下其他玩家无法看到你的皮肤)
settings.tabs.installers=自动安装
settings.type=版本设置类型
settings.type.global=全局版本设置(使用该设置的版本共用一套设定)
settings.type.global.manage=全局游戏设置
settings.type.global.edit=编辑全局版本设置
settings.type.special.enable=启用游戏特定设置(不影响其他游戏版本)
settings.type.special.edit=编辑游戏特定设置
settings.type.special.edit.hint=当前游戏版本 %s 启动了游戏特定设置,本页面选项不对当前游戏生效。点击链接以修改当前游戏设置。
sponsor=赞助
sponsor.bmclapi=国内下载源由 BMCLAPI 和我的世界中文论坛 (MCBBS) 提供高速下载服务。BMCLAPI 是公益服务,请赞助 BMCLAPI 以获得稳定高速的下载服务,点击此处查阅详细信息。