mirror of
https://github.com/HMCL-dev/HMCL.git
synced 2025-09-18 08:16:58 -04:00
feat: show nav to special settings page in global settings page if needed.
This commit is contained in:
parent
3f4dbb6978
commit
79e4aa5aaf
@ -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();
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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")
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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:
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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"));
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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());
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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 {
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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) 提供高速下載服務
|
||||
|
@ -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 以获得稳定高速的下载服务,点击此处查阅详细信息。
|
||||
|
Loading…
x
Reference in New Issue
Block a user