feat: multifileitem supports multiple custom type.

This commit is contained in:
huanghongxun 2021-09-20 01:54:08 +08:00
parent 43236049ac
commit ca3bc69a61
11 changed files with 299 additions and 218 deletions

View File

@ -83,6 +83,9 @@ public final class Config implements Cloneable, Observable {
@SerializedName("bgpath")
private StringProperty backgroundImage = new SimpleStringProperty();
@SerializedName("bgurl")
private StringProperty backgroundImageUrl = new SimpleStringProperty();
@SerializedName("commonDirType")
private ObjectProperty<EnumCommonDirectory> commonDirType = new SimpleObjectProperty<>(EnumCommonDirectory.DEFAULT);
@ -149,6 +152,9 @@ public final class Config implements Cloneable, Observable {
@SerializedName("fontSize")
private DoubleProperty fontSize = new SimpleDoubleProperty(12);
@SerializedName("launcherFontFamily")
private StringProperty launcherFontFamily = new SimpleStringProperty();
@SerializedName("logLines")
private IntegerProperty logLines = new SimpleIntegerProperty(100);
@ -239,6 +245,18 @@ public final class Config implements Cloneable, Observable {
return backgroundImage;
}
public String getBackgroundImageUrl() {
return backgroundImageUrl.get();
}
public StringProperty backgroundImageUrlProperty() {
return backgroundImageUrl;
}
public void setBackgroundImageUrl(String backgroundImageUrl) {
this.backgroundImageUrl.set(backgroundImageUrl);
}
public EnumCommonDirectory getCommonDirType() {
return commonDirType.get();
}
@ -487,6 +505,18 @@ public final class Config implements Cloneable, Observable {
return fontSize;
}
public String getLauncherFontFamily() {
return launcherFontFamily.get();
}
public StringProperty launcherFontFamilyProperty() {
return launcherFontFamily;
}
public void setLauncherFontFamily(String launcherFontFamily) {
this.launcherFontFamily.set(launcherFontFamily);
}
public int getLogLines() {
return logLines.get();
}

View File

@ -19,5 +19,7 @@ package org.jackhuang.hmcl.setting;
public enum EnumBackgroundImage {
DEFAULT,
CUSTOM
CUSTOM,
CLASSIC,
NETWORK
}

View File

@ -20,7 +20,6 @@ package org.jackhuang.hmcl.ui.construct;
import com.jfoenix.controls.JFXButton;
import com.jfoenix.controls.JFXRadioButton;
import com.jfoenix.controls.JFXTextField;
import javafx.beans.NamedArg;
import javafx.beans.property.*;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
@ -39,74 +38,30 @@ import org.jackhuang.hmcl.setting.Theme;
import org.jackhuang.hmcl.ui.Controllers;
import org.jackhuang.hmcl.ui.FXUtils;
import org.jackhuang.hmcl.ui.SVG;
import org.jackhuang.hmcl.util.StringUtils;
import java.io.File;
import java.util.Collection;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
public class MultiFileItem<T> extends ComponentSublist {
private final StringProperty customTitle = new SimpleStringProperty(this, "customTitle", i18n("selector.custom"));
private final StringProperty chooserTitle = new SimpleStringProperty(this, "chooserTitle", i18n("selector.choose_file"));
private final BooleanProperty directory = new SimpleBooleanProperty(this, "directory", false);
private final ObjectProperty<T> selectedData = new SimpleObjectProperty<>(this, "selectedData");
private final ObjectProperty<T> fallbackData = new SimpleObjectProperty<>(this, "fallbackData");
private final ObservableList<FileChooser.ExtensionFilter> extensionFilters = FXCollections.observableArrayList();
private final ToggleGroup group = new ToggleGroup();
private final JFXTextField txtCustom = new JFXTextField();
private final JFXButton btnSelect = new JFXButton();
private final JFXRadioButton radioCustom = new JFXRadioButton();
private final BorderPane custom = new BorderPane();
private final VBox pane = new VBox();
private final boolean hasCustom;
private Consumer<Toggle> toggleSelectedListener;
@SuppressWarnings("unchecked")
public MultiFileItem(@NamedArg(value = "hasCustom", defaultValue = "true") boolean hasCustom) {
this.hasCustom = hasCustom;
BorderPane.setAlignment(txtCustom, Pos.CENTER_RIGHT);
btnSelect.setGraphic(SVG.folderOpen(Theme.blackFillBinding(), 15, 15));
btnSelect.setOnMouseClicked(e -> {
if (isDirectory()) {
DirectoryChooser chooser = new DirectoryChooser();
chooser.titleProperty().bind(chooserTitle);
File dir = chooser.showDialog(Controllers.getStage());
if (dir != null)
txtCustom.setText(dir.getAbsolutePath());
} else {
FileChooser chooser = new FileChooser();
chooser.getExtensionFilters().addAll(getExtensionFilters());
chooser.titleProperty().bind(chooserTitle);
File file = chooser.showOpenDialog(Controllers.getStage());
if (file != null)
txtCustom.setText(file.getAbsolutePath());
}
});
radioCustom.textProperty().bind(customTitleProperty());
radioCustom.setToggleGroup(group);
txtCustom.disableProperty().bind(radioCustom.selectedProperty().not());
btnSelect.disableProperty().bind(radioCustom.selectedProperty().not());
custom.setLeft(radioCustom);
custom.setStyle("-fx-padding: 3;");
HBox right = new HBox();
right.setSpacing(3);
right.getChildren().addAll(txtCustom, btnSelect);
custom.setRight(right);
FXUtils.setLimitHeight(custom, 20);
public MultiFileItem() {
pane.setStyle("-fx-padding: 0 0 10 0;");
pane.setSpacing(8);
if (hasCustom)
pane.getChildren().add(custom);
getContent().add(pane);
group.selectedToggleProperty().addListener((a, b, newValue) -> {
@ -129,117 +84,20 @@ public class MultiFileItem<T> extends ComponentSublist {
});
}
public Node createChildren(String title) {
return createChildren(title, null);
}
public Node createChildren(String title, T userData) {
return createChildren(title, "", userData);
}
public Node createChildren(String title, String subtitle, T userData) {
BorderPane pane = new BorderPane();
pane.setPadding(new Insets(3));
FXUtils.setLimitHeight(pane, 20);
JFXRadioButton left = new JFXRadioButton(title);
left.setToggleGroup(group);
left.setUserData(userData);
pane.setLeft(left);
Label right = new Label(subtitle);
right.setWrapText(true);
right.getStyleClass().add("subtitle-label");
right.setStyle("-fx-font-size: 10;");
pane.setRight(right);
return pane;
}
public void loadChildren(Collection<Node> list) {
pane.getChildren().setAll(list);
if (hasCustom)
pane.getChildren().add(custom);
}
public void loadChildren(Collection<Node> list, T customUserData) {
loadChildren(list);
setCustomUserData(customUserData);
public void loadChildren(Collection<Option<T>> options) {
pane.getChildren().setAll(options.stream()
.map(option -> option.createItem(group))
.collect(Collectors.toList()));
}
public ToggleGroup getGroup() {
return group;
}
public String getCustomTitle() {
return customTitle.get();
}
public StringProperty customTitleProperty() {
return customTitle;
}
public void setCustomTitle(String customTitle) {
this.customTitle.set(customTitle);
}
public String getChooserTitle() {
return chooserTitle.get();
}
public StringProperty chooserTitleProperty() {
return chooserTitle;
}
public void setChooserTitle(String chooserTitle) {
this.chooserTitle.set(chooserTitle);
}
public void setCustomUserData(T userData) {
radioCustom.setUserData(userData);
}
public boolean isCustomToggle(Toggle toggle) {
return radioCustom == toggle;
}
public void setToggleSelectedListener(Consumer<Toggle> consumer) {
toggleSelectedListener = consumer;
}
public StringProperty customTextProperty() {
return txtCustom.textProperty();
}
public String getCustomText() {
return txtCustom.getText();
}
public void setCustomText(String customText) {
txtCustom.setText(customText);
}
public JFXTextField getTxtCustom() {
return txtCustom;
}
public boolean isDirectory() {
return directory.get();
}
public BooleanProperty directoryProperty() {
return directory;
}
public void setDirectory(boolean directory) {
this.directory.set(directory);
}
public ObservableList<FileChooser.ExtensionFilter> getExtensionFilters() {
return extensionFilters;
}
public T getSelectedData() {
return selectedData.get();
}
@ -263,4 +121,187 @@ public class MultiFileItem<T> extends ComponentSublist {
public void setFallbackData(T fallbackData) {
this.fallbackData.set(fallbackData);
}
public static class Option<T> {
protected final String title;
protected String subtitle;
protected final T data;
public Option(String title, T data) {
this.title = title; this.data = data;
}
public T getData() {
return data;
}
public String getTitle() {
return title;
}
public String getSubtitle() {
return subtitle;
}
public Option<T> setSubtitle(String subtitle) {
this.subtitle = subtitle;
return this;
}
protected Node createItem(ToggleGroup group) {
BorderPane pane = new BorderPane();
pane.setPadding(new Insets(3));
FXUtils.setLimitHeight(pane, 30);
JFXRadioButton left = new JFXRadioButton(title);
BorderPane.setAlignment(left, Pos.CENTER_LEFT);
left.setToggleGroup(group);
left.setUserData(data);
pane.setLeft(left);
if (StringUtils.isNotBlank(subtitle)) {
Label right = new Label(subtitle);
BorderPane.setAlignment(right, Pos.CENTER_RIGHT);
right.setWrapText(true);
right.getStyleClass().add("subtitle-label");
right.setStyle("-fx-font-size: 10;");
pane.setRight(right);
}
return pane;
}
}
public static class StringOption<T> extends Option<T> {
private StringProperty value = new SimpleStringProperty();
public StringOption(String title, T data) {
super(title, data);
}
public String getValue() {
return value.get();
}
public StringProperty valueProperty() {
return value;
}
public void setValue(String value) {
this.value.set(value);
}
public StringOption<T> bindBidirectional(Property<String> property) {
this.value.bindBidirectional(property);
return this;
}
@Override
protected Node createItem(ToggleGroup group) {
BorderPane pane = new BorderPane();
pane.setPadding(new Insets(3));
FXUtils.setLimitHeight(pane, 30);
JFXRadioButton left = new JFXRadioButton(title);
BorderPane.setAlignment(left, Pos.CENTER_LEFT);
left.setToggleGroup(group);
left.setUserData(data);
pane.setLeft(left);
JFXTextField customField = new JFXTextField();
BorderPane.setAlignment(customField, Pos.CENTER_RIGHT);
customField.textProperty().bindBidirectional(valueProperty());
customField.disableProperty().bind(left.selectedProperty().not());
pane.setRight(customField);
return pane;
}
}
public static class FileOption<T> extends Option<T> {
private StringProperty value = new SimpleStringProperty();
private String chooserTitle = i18n("selector.choose_file");
private boolean directory = false;
private final ObservableList<FileChooser.ExtensionFilter> extensionFilters = FXCollections.observableArrayList();
public FileOption(String title, T data) {
super(title, data);
}
public String getValue() {
return value.get();
}
public StringProperty valueProperty() {
return value;
}
public void setValue(String value) {
this.value.set(value);
}
public FileOption<T> setDirectory(boolean directory) {
this.directory = directory;
return this;
}
public FileOption<T> bindBidirectional(Property<String> property) {
this.value.bindBidirectional(property);
return this;
}
public FileOption<T> setChooserTitle(String chooserTitle) {
this.chooserTitle = chooserTitle;
return this;
}
public ObservableList<FileChooser.ExtensionFilter> getExtensionFilters() {
return extensionFilters;
}
@Override
protected Node createItem(ToggleGroup group) {
BorderPane pane = new BorderPane();
pane.setPadding(new Insets(3));
FXUtils.setLimitHeight(pane, 30);
JFXRadioButton left = new JFXRadioButton(title);
BorderPane.setAlignment(left, Pos.CENTER_LEFT);
left.setToggleGroup(group);
left.setUserData(data);
pane.setLeft(left);
JFXTextField customField = new JFXTextField();
customField.textProperty().bindBidirectional(valueProperty());
customField.disableProperty().bind(left.selectedProperty().not());
JFXButton selectButton = new JFXButton();
selectButton.disableProperty().bind(left.selectedProperty().not());
selectButton.setGraphic(SVG.folderOpen(Theme.blackFillBinding(), 15, 15));
selectButton.setOnMouseClicked(e -> {
if (directory) {
DirectoryChooser chooser = new DirectoryChooser();
chooser.setTitle(chooserTitle);
File dir = chooser.showDialog(Controllers.getStage());
if (dir != null)
customField.setText(dir.getAbsolutePath());
} else {
FileChooser chooser = new FileChooser();
chooser.getExtensionFilters().addAll(getExtensionFilters());
chooser.setTitle(chooserTitle);
File file = chooser.showOpenDialog(Controllers.getStage());
if (file != null)
customField.setText(file.getAbsolutePath());
}
});
HBox right = new HBox();
right.setAlignment(Pos.CENTER_RIGHT);
BorderPane.setAlignment(right, Pos.CENTER_RIGHT);
right.setSpacing(3);
right.getChildren().addAll(customField, selectButton);
pane.setRight(right);
return pane;
}
}
}

View File

@ -137,6 +137,9 @@ public class DecoratorController {
if (config().getBackgroundImageType() == EnumBackgroundImage.CUSTOM && config().getBackgroundImage() != null) {
image = tryLoadImage(Paths.get(config().getBackgroundImage()))
.orElse(null);
}
if (config().getBackgroundImageType() == EnumBackgroundImage.NETWORK) {
}
if (image == null) {
image = loadDefaultBackgroundImage();

View File

@ -41,7 +41,7 @@ import org.jackhuang.hmcl.ui.FXUtils;
import org.jackhuang.hmcl.ui.construct.*;
import org.jackhuang.hmcl.util.javafx.SafeStringConverter;
import java.util.Collections;
import java.util.Arrays;
import static org.jackhuang.hmcl.setting.ConfigHolder.config;
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
@ -86,17 +86,19 @@ public class PersonalizationPage extends StackPane {
{
StackPane componentList = new StackPane();
MultiFileItem<EnumBackgroundImage> backgroundItem = new MultiFileItem<>(true);
MultiFileItem<EnumBackgroundImage> backgroundItem = new MultiFileItem<>();
backgroundItem.setTitle(i18n("launcher.background"));
backgroundItem.setChooserTitle(i18n("launcher.background.choose"));
backgroundItem.setHasSubtitle(true);
backgroundItem.setCustomText(i18n("settings.custom"));
backgroundItem.setStyle("-fx-padding: 8 0 0 0");
backgroundItem.loadChildren(Collections.singletonList(
backgroundItem.createChildren(i18n("launcher.background.default"), EnumBackgroundImage.DEFAULT)
), EnumBackgroundImage.CUSTOM);
backgroundItem.customTextProperty().bindBidirectional(config().backgroundImageProperty());
backgroundItem.loadChildren(Arrays.asList(
new MultiFileItem.Option<>(i18n("launcher.background.default"), EnumBackgroundImage.DEFAULT),
new MultiFileItem.Option<>(i18n("launcher.background.classic"), EnumBackgroundImage.CLASSIC),
new MultiFileItem.FileOption<>(i18n("settings.custom"), EnumBackgroundImage.CUSTOM)
.setChooserTitle(i18n("launcher.background.choose"))
.bindBidirectional(config().backgroundImageProperty()),
new MultiFileItem.StringOption<>(i18n("launcher.background.network"), EnumBackgroundImage.NETWORK)
.bindBidirectional(config().backgroundImageUrlProperty())
));
backgroundItem.selectedDataProperty().bindBidirectional(config().backgroundImageTypeProperty());
backgroundItem.subtitleProperty().bind(
new When(backgroundItem.selectedDataProperty().isEqualTo(EnumBackgroundImage.DEFAULT))
@ -181,18 +183,9 @@ public class PersonalizationPage extends StackPane {
hBox.setSpacing(3);
FontComboBox cboFont = new FontComboBox(12);
cboFont.valueProperty().bindBidirectional(config().fontFamilyProperty());
cboFont.valueProperty().bindBidirectional(config().launcherFontFamilyProperty());
JFXTextField txtFontSize = new JFXTextField();
FXUtils.setLimitWidth(txtFontSize, 50);
txtFontSize.textProperty().bindBidirectional(config().fontSizeProperty(),
SafeStringConverter.fromFiniteDouble()
.restrict(it -> it > 0)
.fallbackTo(12.0)
.asPredicate(Validator.addTo(txtFontSize)));
hBox.getChildren().setAll(cboFont, txtFontSize);
hBox.getChildren().setAll(cboFont);
borderPane.setRight(hBox);
}
@ -200,8 +193,8 @@ public class PersonalizationPage extends StackPane {
Label lblFontDisplay = new Label("Hello Minecraft! Launcher");
lblFontDisplay.fontProperty().bind(Bindings.createObjectBinding(
() -> Font.font(config().getFontFamily(), config().getFontSize()),
config().fontFamilyProperty(), config().fontSizeProperty()));
() -> Font.font(config().getLauncherFontFamily(), 12),
config().launcherFontFamilyProperty()));
vbox.getChildren().add(lblFontDisplay);

View File

@ -22,7 +22,6 @@ import javafx.beans.InvalidationListener;
import javafx.beans.WeakInvalidationListener;
import javafx.beans.binding.Bindings;
import javafx.scene.control.ToggleGroup;
import org.jackhuang.hmcl.setting.EnumCommonDirectory;
import org.jackhuang.hmcl.setting.Settings;
import org.jackhuang.hmcl.ui.Controllers;
import org.jackhuang.hmcl.ui.FXUtils;
@ -43,7 +42,6 @@ import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Collections;
import java.util.Optional;
import java.util.logging.Level;
@ -65,11 +63,7 @@ public final class SettingsPage extends SettingsView {
selectedItemPropertyFor(cboLanguage).bindBidirectional(config().localizationProperty());
// ====
fileCommonLocation.loadChildren(Collections.singletonList(
fileCommonLocation.createChildren(i18n("launcher.cache_directory.default"), EnumCommonDirectory.DEFAULT)
), EnumCommonDirectory.CUSTOM);
fileCommonLocation.selectedDataProperty().bindBidirectional(config().commonDirTypeProperty());
fileCommonLocation.customTextProperty().bindBidirectional(config().commonDirectoryProperty());
fileCommonLocation.subtitleProperty().bind(
Bindings.createObjectBinding(() -> Optional.ofNullable(Settings.instance().getCommonDirectory())
.orElse(i18n("launcher.cache_directory.disabled")),

View File

@ -38,6 +38,8 @@ import org.jackhuang.hmcl.ui.construct.ComponentSublist;
import org.jackhuang.hmcl.ui.construct.MultiFileItem;
import org.jackhuang.hmcl.util.i18n.Locales.SupportedLocale;
import java.util.Arrays;
import static org.jackhuang.hmcl.setting.ConfigHolder.config;
import static org.jackhuang.hmcl.ui.FXUtils.stringConverter;
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
@ -143,12 +145,16 @@ public abstract class SettingsView extends StackPane {
}
{
fileCommonLocation = new MultiFileItem<>(true);
fileCommonLocation = new MultiFileItem<>();
fileCommonLocation.setTitle(i18n("launcher.cache_directory"));
fileCommonLocation.setDirectory(true);
fileCommonLocation.setChooserTitle(i18n("launcher.cache_directory.choose"));
fileCommonLocation.setHasSubtitle(true);
fileCommonLocation.setCustomText("settings.custom");
fileCommonLocation.loadChildren(Arrays.asList(
new MultiFileItem.Option<>(i18n("launcher.cache_directory.default"), EnumCommonDirectory.DEFAULT),
new MultiFileItem.FileOption<>(i18n("settings.custom"), EnumCommonDirectory.CUSTOM)
.setChooserTitle(i18n("launcher.cache_directory.choose"))
.setDirectory(true)
.bindBidirectional(config().commonDirectoryProperty())
));
{
JFXButton cleanButton = new JFXButton(i18n("launcher.cache_directory.clean"));

View File

@ -56,6 +56,7 @@ import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Level;
@ -94,8 +95,11 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag
private final JFXToggleButton chkUseNativeGLFW;
private final JFXToggleButton chkUseNativeOpenAL;
private final MultiFileItem<JavaVersion> javaItem;
private final MultiFileItem.FileOption<JavaVersion> javaCustomOption;
private final MultiFileItem<GameDirectoryType> gameDirItem;
private final MultiFileItem.FileOption<GameDirectoryType> gameDirCustomOption;
private final MultiFileItem<NativesDirectoryType> nativesDirItem;
private final MultiFileItem.FileOption<NativesDirectoryType> nativesDirCustomOption;
private final JFXComboBox<ProcessPriority> cboProcessPriority;
private final JFXToggleButton chkShowLogs;
private final ImagePickerItem iconPickerItem;
@ -154,19 +158,24 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag
componentList = new ComponentList();
componentList.setDepth(1);
javaItem = new MultiFileItem<>(true);
javaItem = new MultiFileItem<>();
javaItem.setTitle(i18n("settings.game.java_directory"));
javaItem.setChooserTitle(i18n("settings.game.java_directory.choose"));
javaItem.setHasSubtitle(true);
javaItem.setCustomText(i18n("settings.custom"));
javaItem.setDirectory(false);
javaCustomOption = new MultiFileItem.FileOption<JavaVersion>(i18n("settings.custom"), null)
.setChooserTitle(i18n("settings.game.java_directory.choose"));
gameDirItem = new MultiFileItem<>(true);
gameDirItem = new MultiFileItem<>();
gameDirItem.setTitle(i18n("settings.game.working_directory"));
gameDirItem.setChooserTitle(i18n("settings.game.working_directory.choose"));
gameDirItem.setHasSubtitle(true);
gameDirItem.setCustomText(i18n("settings.custom"));
gameDirItem.setDirectory(true);
gameDirCustomOption = new MultiFileItem.FileOption<>(i18n("settings.custom"), GameDirectoryType.CUSTOM)
.setChooserTitle(i18n("settings.game.working_directory.choose"))
.setDirectory(true);
gameDirItem.loadChildren(Arrays.asList(
new MultiFileItem.Option<>(i18n("settings.advanced.game_dir.default"), GameDirectoryType.ROOT_FOLDER),
new MultiFileItem.Option<>(i18n("settings.advanced.game_dir.independent"), GameDirectoryType.VERSION_FOLDER),
gameDirCustomOption
));
VBox maxMemoryPane = new VBox(8);
{
@ -439,12 +448,16 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag
ComponentList workaroundPane = new ComponentList();
workaroundPane.disableProperty().bind(chkEnableSpecificSettings.selectedProperty().not());
{
nativesDirItem = new MultiFileItem<>(true);
nativesDirItem = new MultiFileItem<>();
nativesDirItem.setTitle(i18n("settings.advanced.natives_directory"));
nativesDirItem.setChooserTitle(i18n("settings.advanced.natives_directory.choose"));
nativesDirItem.setHasSubtitle(true);
nativesDirItem.setCustomText(i18n("settings.custom"));
nativesDirItem.setDirectory(true);
nativesDirCustomOption = new MultiFileItem.FileOption<>(i18n("settings.custom"), NativesDirectoryType.CUSTOM)
.setChooserTitle(i18n("settings.advanced.natives_directory.choose"))
.setDirectory(true);
nativesDirItem.loadChildren(Arrays.asList(
new MultiFileItem.Option<>(i18n("settings.advanced.natives_directory.default"), NativesDirectoryType.VERSION_FOLDER),
nativesDirCustomOption
));
BorderPane noJVMArgsPane = new BorderPane();
{
@ -534,10 +547,13 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag
memoryStatusProperty.set(OperatingSystem.getPhysicalMemoryStatus().orElse(OperatingSystem.PhysicalMemoryStatus.INVALID));
Task.supplyAsync(JavaVersion::getJavas).thenAcceptAsync(Schedulers.javafx(), list -> {
javaItem.loadChildren(list.stream()
.map(javaVersion -> javaItem.createChildren(javaVersion.getVersion() + i18n("settings.game.java_directory.bit",
javaVersion.getPlatform().getBit()), javaVersion.getBinary().toString(), javaVersion))
.collect(Collectors.toList()));
List<MultiFileItem.Option<JavaVersion>> options = list.stream()
.map(javaVersion -> new MultiFileItem.Option<>(javaVersion.getVersion() + i18n("settings.game.java_directory.bit",
javaVersion.getPlatform().getBit()), javaVersion)
.setSubtitle(javaVersion.getBinary().toString()))
.collect(Collectors.toList());
options.add(javaCustomOption);
javaItem.loadChildren(options);
javaItemsLoaded = true;
initializeSelectedJava();
}).start();
@ -545,18 +561,7 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag
javaItem.setSelectedData(null);
javaItem.setFallbackData(JavaVersion.fromCurrentEnvironment());
if (OperatingSystem.CURRENT_OS == OperatingSystem.WINDOWS)
javaItem.getExtensionFilters().add(new FileChooser.ExtensionFilter("Java", "java.exe", "javaw.exe"));
gameDirItem.setCustomUserData(GameDirectoryType.CUSTOM);
gameDirItem.loadChildren(Arrays.asList(
gameDirItem.createChildren(i18n("settings.advanced.game_dir.default"), GameDirectoryType.ROOT_FOLDER),
gameDirItem.createChildren(i18n("settings.advanced.game_dir.independent"), GameDirectoryType.VERSION_FOLDER)
));
nativesDirItem.setCustomUserData(NativesDirectoryType.CUSTOM);
nativesDirItem.loadChildren(Arrays.asList(
nativesDirItem.createChildren(i18n("settings.advanced.natives_directory.default"), NativesDirectoryType.VERSION_FOLDER)
));
javaCustomOption.getExtensionFilters().add(new FileChooser.ExtensionFilter("Java", "java.exe", "javaw.exe"));
chkEnableSpecificSettings.selectedProperty().addListener((a, b, newValue) -> {
if (versionId == null) return;
@ -597,9 +602,9 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag
FXUtils.unbindInt(txtWidth, lastVersionSetting.widthProperty());
FXUtils.unbindInt(txtHeight, lastVersionSetting.heightProperty());
maxMemoryProperty.unbindBidirectional(lastVersionSetting.maxMemoryProperty());
FXUtils.unbindString(javaItem.getTxtCustom(), lastVersionSetting.javaDirProperty());
FXUtils.unbindString(gameDirItem.getTxtCustom(), lastVersionSetting.gameDirProperty());
FXUtils.unbindString(nativesDirItem.getTxtCustom(), lastVersionSetting.nativesDirProperty());
javaCustomOption.valueProperty().unbindBidirectional(lastVersionSetting.javaDirProperty());
gameDirCustomOption.valueProperty().unbindBidirectional(lastVersionSetting.gameDirProperty());
nativesDirCustomOption.valueProperty().unbindBidirectional(lastVersionSetting.nativesDirProperty());
FXUtils.unbindString(txtJVMArgs, lastVersionSetting.javaArgsProperty());
FXUtils.unbindString(txtGameArgs, lastVersionSetting.minecraftArgsProperty());
FXUtils.unbindString(txtMetaspace, lastVersionSetting.permSizeProperty());
@ -636,9 +641,10 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag
FXUtils.bindInt(txtWidth, versionSetting.widthProperty());
FXUtils.bindInt(txtHeight, versionSetting.heightProperty());
maxMemoryProperty.bindBidirectional(versionSetting.maxMemoryProperty());
FXUtils.bindString(javaItem.getTxtCustom(), versionSetting.javaDirProperty());
FXUtils.bindString(gameDirItem.getTxtCustom(), versionSetting.gameDirProperty());
FXUtils.bindString(nativesDirItem.getTxtCustom(), versionSetting.nativesDirProperty());
javaCustomOption.bindBidirectional(versionSetting.javaDirProperty());
gameDirCustomOption.bindBidirectional(versionSetting.gameDirProperty());
nativesDirCustomOption.bindBidirectional(versionSetting.nativesDirProperty());
FXUtils.bindString(txtJVMArgs, versionSetting.javaArgsProperty());
FXUtils.bindString(txtGameArgs, versionSetting.minecraftArgsProperty());
FXUtils.bindString(txtMetaspace, versionSetting.permSizeProperty());
@ -661,7 +667,7 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag
chkEnableSpecificSettings.setSelected(!versionSetting.isUsesGlobal());
javaItem.setToggleSelectedListener(newValue -> {
if (javaItem.isCustomToggle(newValue)) {
if (newValue.getUserData() == null) {
versionSetting.setUsesCustomJavaDir();
} else {
versionSetting.setJavaVersion((JavaVersion) newValue.getUserData());
@ -695,7 +701,7 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag
if (lastVersionSetting.isUsesCustomJavaDir()) {
javaItem.getGroup().getToggles().stream()
.filter(javaItem::isCustomToggle)
.filter(java -> java.getUserData() == null)
.findFirst().get()
.setSelected(true);
} else {

View File

@ -402,8 +402,10 @@ launch.wrong_javadir=Invalid Java directory, default Java path will be applied.
launcher=Launcher
launcher.background=Background Image
launcher.background.classic=Classic
launcher.background.choose=Choose a background image file
launcher.background.default=Standard
launcher.background.network=Network
launcher.cache_directory=Directory for caching
launcher.cache_directory.clean=Clear
launcher.cache_directory.choose=Choose the directory for caching

View File

@ -403,7 +403,9 @@ launch.wrong_javadir=Java 路徑錯誤,將自動重設為預設 Java 路徑。
launcher=啟動器
launcher.background=背景位址
launcher.background.choose=選擇背景路徑
launcher.background.classic=經典
launcher.background.default=預設(自動尋找啟動器同目錄下的 background.png/jpg 及 bg 資料夾內的圖片)
launcher.background.network=網路
launcher.cache_directory=檔案下載快取目錄
launcher.cache_directory.clean=清理
launcher.cache_directory.choose=選擇檔案下載快取目錄

View File

@ -403,7 +403,9 @@ launch.wrong_javadir=错误的 Java 路径,将自动重置为默认 Java 路
launcher=启动器
launcher.background=背景地址
launcher.background.choose=选择背景路径
launcher.background.classic=经典
launcher.background.default=默认(自动检索启动器同目录下的 background.png/jpg 及 bg 文件夹内的图片)
launcher.background.network=网络
launcher.cache_directory=文件下载缓存目录
launcher.cache_directory.clean=清理
launcher.cache_directory.choose=选择文件下载缓存目录