Merge branch 'javafx' into refactor-account
This commit is contained in:
@@ -18,6 +18,7 @@
|
|||||||
package org.jackhuang.hmcl.game;
|
package org.jackhuang.hmcl.game;
|
||||||
|
|
||||||
import org.jackhuang.hmcl.setting.Profile;
|
import org.jackhuang.hmcl.setting.Profile;
|
||||||
|
import org.jackhuang.hmcl.setting.Settings;
|
||||||
import org.jackhuang.hmcl.task.FileDownloadTask;
|
import org.jackhuang.hmcl.task.FileDownloadTask;
|
||||||
import org.jackhuang.hmcl.task.FileDownloadTask.IntegrityCheck;
|
import org.jackhuang.hmcl.task.FileDownloadTask.IntegrityCheck;
|
||||||
import org.jackhuang.hmcl.task.Task;
|
import org.jackhuang.hmcl.task.Task;
|
||||||
@@ -29,6 +30,7 @@ import java.io.File;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
|
||||||
import static org.jackhuang.hmcl.setting.ConfigHolder.CONFIG;
|
import static org.jackhuang.hmcl.setting.ConfigHolder.CONFIG;
|
||||||
@@ -59,7 +61,11 @@ public class HMCLGameDownloadTask extends Task {
|
|||||||
public void execute() {
|
public void execute() {
|
||||||
File jar = profile.getRepository().getVersionJar(version);
|
File jar = profile.getRepository().getVersionJar(version);
|
||||||
|
|
||||||
File cache = new File(CONFIG.getCommonDirectory(), "jars/" + gameVersion + ".jar");
|
// Force using common directory will not affect the behaviour that repository acts
|
||||||
|
// Since we always copy the downloaded jar to .minecraft/versions/<version>/
|
||||||
|
File cache = new File(Optional.ofNullable(Settings.INSTANCE.getCommonDirectory())
|
||||||
|
.orElse(Settings.getDefaultCommonDirectory()),
|
||||||
|
"jars/" + gameVersion + ".jar");
|
||||||
if (cache.exists())
|
if (cache.exists())
|
||||||
try {
|
try {
|
||||||
FileUtils.copyFile(cache, jar);
|
FileUtils.copyFile(cache, jar);
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import org.jackhuang.hmcl.event.RefreshedVersionsEvent;
|
|||||||
import org.jackhuang.hmcl.event.RefreshingVersionsEvent;
|
import org.jackhuang.hmcl.event.RefreshingVersionsEvent;
|
||||||
import org.jackhuang.hmcl.setting.EnumGameDirectory;
|
import org.jackhuang.hmcl.setting.EnumGameDirectory;
|
||||||
import org.jackhuang.hmcl.setting.Profile;
|
import org.jackhuang.hmcl.setting.Profile;
|
||||||
|
import org.jackhuang.hmcl.setting.Settings;
|
||||||
import org.jackhuang.hmcl.setting.VersionSetting;
|
import org.jackhuang.hmcl.setting.VersionSetting;
|
||||||
import org.jackhuang.hmcl.util.FileUtils;
|
import org.jackhuang.hmcl.util.FileUtils;
|
||||||
import org.jackhuang.hmcl.util.Logging;
|
import org.jackhuang.hmcl.util.Logging;
|
||||||
@@ -51,17 +52,16 @@ public class HMCLGameRepository extends DefaultGameRepository {
|
|||||||
return profile;
|
return profile;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean useSelf(String version, String assetId) {
|
private boolean useSelf(String assetId) {
|
||||||
VersionSetting vs = profile.getVersionSetting(version);
|
return new File(getBaseDirectory(), "assets/indexes/" + assetId + ".json").exists();
|
||||||
return new File(getBaseDirectory(), "assets/indexes/" + assetId + ".json").exists() || vs.isNoCommon();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public File getAssetDirectory(String version, String assetId) {
|
public File getAssetDirectory(String version, String assetId) {
|
||||||
if (useSelf(version, assetId))
|
if (Settings.INSTANCE.isCommonDirectoryDisabled() || useSelf(assetId))
|
||||||
return super.getAssetDirectory(version, assetId);
|
return super.getAssetDirectory(version, assetId);
|
||||||
else
|
else
|
||||||
return new File(CONFIG.getCommonDirectory(), "assets");
|
return new File(Settings.INSTANCE.getCommonDirectory(), "assets");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -83,10 +83,10 @@ public class HMCLGameRepository extends DefaultGameRepository {
|
|||||||
public File getLibraryFile(Version version, Library lib) {
|
public File getLibraryFile(Version version, Library lib) {
|
||||||
VersionSetting vs = profile.getVersionSetting(version.getId());
|
VersionSetting vs = profile.getVersionSetting(version.getId());
|
||||||
File self = super.getLibraryFile(version, lib);
|
File self = super.getLibraryFile(version, lib);
|
||||||
if (self.exists() || vs.isNoCommon())
|
if (Settings.INSTANCE.isCommonDirectoryDisabled() || self.exists())
|
||||||
return self;
|
return self;
|
||||||
else
|
else
|
||||||
return new File(CONFIG.getCommonDirectory(), "libraries/" + lib.getPath());
|
return new File(Settings.INSTANCE.getCommonDirectory(), "libraries/" + lib.getPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -89,6 +89,9 @@ public final class Config implements Cloneable, Observable {
|
|||||||
@SerializedName("bgpath")
|
@SerializedName("bgpath")
|
||||||
private StringProperty backgroundImage = new SimpleStringProperty();
|
private StringProperty backgroundImage = new SimpleStringProperty();
|
||||||
|
|
||||||
|
@SerializedName("commonDirType")
|
||||||
|
private ObjectProperty<EnumCommonDirectory> commonDirType = new SimpleObjectProperty<>(EnumCommonDirectory.DEFAULT);
|
||||||
|
|
||||||
@SerializedName("commonpath")
|
@SerializedName("commonpath")
|
||||||
private StringProperty commonDirectory = new SimpleStringProperty(Launcher.MINECRAFT_DIRECTORY.getAbsolutePath());
|
private StringProperty commonDirectory = new SimpleStringProperty(Launcher.MINECRAFT_DIRECTORY.getAbsolutePath());
|
||||||
|
|
||||||
@@ -146,6 +149,9 @@ public final class Config implements Cloneable, Observable {
|
|||||||
@SerializedName("authlibInjectorServers")
|
@SerializedName("authlibInjectorServers")
|
||||||
private ObservableList<AuthlibInjectorServer> authlibInjectorServers = FXCollections.observableArrayList();
|
private ObservableList<AuthlibInjectorServer> authlibInjectorServers = FXCollections.observableArrayList();
|
||||||
|
|
||||||
|
@SerializedName("_version")
|
||||||
|
private IntegerProperty configVersion = new SimpleIntegerProperty(0);
|
||||||
|
|
||||||
private transient ObservableHelper helper = new ObservableHelper(this);
|
private transient ObservableHelper helper = new ObservableHelper(this);
|
||||||
|
|
||||||
public Config() {
|
public Config() {
|
||||||
@@ -225,6 +231,18 @@ public final class Config implements Cloneable, Observable {
|
|||||||
return backgroundImage;
|
return backgroundImage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public EnumCommonDirectory getCommonDirType() {
|
||||||
|
return commonDirType.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ObjectProperty<EnumCommonDirectory> commonDirTypeProperty() {
|
||||||
|
return commonDirType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCommonDirType(EnumCommonDirectory commonDirType) {
|
||||||
|
this.commonDirType.set(commonDirType);
|
||||||
|
}
|
||||||
|
|
||||||
public String getCommonDirectory() {
|
public String getCommonDirectory() {
|
||||||
return commonDirectory.get();
|
return commonDirectory.get();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,8 +24,10 @@ import java.io.IOException;
|
|||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.JsonParseException;
|
import com.google.gson.JsonParseException;
|
||||||
|
|
||||||
public final class ConfigHolder {
|
public final class ConfigHolder {
|
||||||
@@ -36,15 +38,23 @@ public final class ConfigHolder {
|
|||||||
public static final Path CONFIG_PATH = Paths.get(CONFIG_FILENAME).toAbsolutePath();
|
public static final Path CONFIG_PATH = Paths.get(CONFIG_FILENAME).toAbsolutePath();
|
||||||
public static final Config CONFIG = initSettings();
|
public static final Config CONFIG = initSettings();
|
||||||
|
|
||||||
|
private static Config upgradeSettings(Config deserialized, Map rawJson) {
|
||||||
|
if (!rawJson.containsKey("commonDirType"))
|
||||||
|
deserialized.setCommonDirType(deserialized.getCommonDirectory().equals(Settings.getDefaultCommonDirectory()) ? EnumCommonDirectory.DEFAULT : EnumCommonDirectory.CUSTOM);
|
||||||
|
return deserialized;
|
||||||
|
}
|
||||||
|
|
||||||
private static Config initSettings() {
|
private static Config initSettings() {
|
||||||
Config config = new Config();
|
Config config = new Config();
|
||||||
if (Files.exists(CONFIG_PATH)) {
|
if (Files.exists(CONFIG_PATH)) {
|
||||||
try {
|
try {
|
||||||
Config deserialized = Config.fromJson(new String(Files.readAllBytes(CONFIG_PATH), UTF_8));
|
String json = new String(Files.readAllBytes(CONFIG_PATH), UTF_8);
|
||||||
|
Map raw = new Gson().fromJson(json, Map.class);
|
||||||
|
Config deserialized = Config.fromJson(json);
|
||||||
if (deserialized == null) {
|
if (deserialized == null) {
|
||||||
LOG.finer("Settings file is empty, use the default settings.");
|
LOG.finer("Settings file is empty, use the default settings.");
|
||||||
} else {
|
} else {
|
||||||
config = deserialized;
|
config = upgradeSettings(deserialized, raw);
|
||||||
}
|
}
|
||||||
LOG.finest("Initialized settings.");
|
LOG.finest("Initialized settings.");
|
||||||
} catch (IOException | JsonParseException e) {
|
} catch (IOException | JsonParseException e) {
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* Hello Minecraft! Launcher.
|
||||||
|
* Copyright (C) 2017 huangyuhui <huanghongxun2008@126.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see {http://www.gnu.org/licenses/}.
|
||||||
|
*/
|
||||||
|
package org.jackhuang.hmcl.setting;
|
||||||
|
|
||||||
|
public enum EnumCommonDirectory {
|
||||||
|
/**
|
||||||
|
* same to game directory
|
||||||
|
*/
|
||||||
|
DISABLED,
|
||||||
|
/**
|
||||||
|
* %appdata%/.minecraft or ~/.minecraft
|
||||||
|
*/
|
||||||
|
DEFAULT,
|
||||||
|
/**
|
||||||
|
* user customized common directory.
|
||||||
|
*/
|
||||||
|
CUSTOM
|
||||||
|
}
|
||||||
@@ -27,6 +27,7 @@ import org.jackhuang.hmcl.task.Schedulers;
|
|||||||
import org.jackhuang.hmcl.util.*;
|
import org.jackhuang.hmcl.util.*;
|
||||||
import org.jackhuang.hmcl.util.i18n.Locales;
|
import org.jackhuang.hmcl.util.i18n.Locales;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@@ -94,6 +95,27 @@ public class Settings {
|
|||||||
CONFIG.setLogLines(logLines);
|
CONFIG.setLogLines(logLines);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isCommonDirectoryDisabled() {
|
||||||
|
return CONFIG.getCommonDirType() == EnumCommonDirectory.DISABLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getDefaultCommonDirectory() {
|
||||||
|
return Launcher.MINECRAFT_DIRECTORY.getAbsolutePath();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCommonDirectory() {
|
||||||
|
switch (CONFIG.getCommonDirType()) {
|
||||||
|
case DISABLED:
|
||||||
|
return null;
|
||||||
|
case DEFAULT:
|
||||||
|
return getDefaultCommonDirectory();
|
||||||
|
case CUSTOM:
|
||||||
|
return CONFIG.getCommonDirectory();
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************
|
/****************************************
|
||||||
* DOWNLOAD PROVIDERS *
|
* DOWNLOAD PROVIDERS *
|
||||||
****************************************/
|
****************************************/
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ public final class VersionSetting {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Java version or null if user customizes java directory.
|
* Java version or "Custom" if user customizes java directory, "Default" if the jvm that this app relies on.
|
||||||
*/
|
*/
|
||||||
public String getJava() {
|
public String getJava() {
|
||||||
return javaProperty.get();
|
return javaProperty.get();
|
||||||
@@ -91,6 +91,15 @@ public final class VersionSetting {
|
|||||||
javaProperty.set(java);
|
javaProperty.set(java);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isUsesCustomJavaDir() {
|
||||||
|
return "Custom".equals(getJava());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUsesCustomJavaDir() {
|
||||||
|
setJava("Custom");
|
||||||
|
setDefaultJavaPath(null);
|
||||||
|
}
|
||||||
|
|
||||||
private final ImmediateStringProperty defaultJavaPathProperty = new ImmediateStringProperty(this, "defaultJavaPath", "");
|
private final ImmediateStringProperty defaultJavaPathProperty = new ImmediateStringProperty(this, "defaultJavaPath", "");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -278,23 +287,6 @@ public final class VersionSetting {
|
|||||||
notCheckGameProperty.set(notCheckGame);
|
notCheckGameProperty.set(notCheckGame);
|
||||||
}
|
}
|
||||||
|
|
||||||
private final ImmediateBooleanProperty noCommonProperty = new ImmediateBooleanProperty(this, "noCommon", false);
|
|
||||||
|
|
||||||
public ImmediateBooleanProperty noCommonProperty() {
|
|
||||||
return noCommonProperty;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* True if HMCL does not find/download libraries in/to common path.
|
|
||||||
*/
|
|
||||||
public boolean isNoCommon() {
|
|
||||||
return noCommonProperty.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setNoCommon(boolean noCommon) {
|
|
||||||
noCommonProperty.set(noCommon);
|
|
||||||
}
|
|
||||||
|
|
||||||
private final ImmediateBooleanProperty showLogsProperty = new ImmediateBooleanProperty(this, "showLogs", false);
|
private final ImmediateBooleanProperty showLogsProperty = new ImmediateBooleanProperty(this, "showLogs", false);
|
||||||
|
|
||||||
public ImmediateBooleanProperty showLogsProperty() {
|
public ImmediateBooleanProperty showLogsProperty() {
|
||||||
@@ -455,7 +447,7 @@ public final class VersionSetting {
|
|||||||
if (StringUtils.isBlank(getJava()))
|
if (StringUtils.isBlank(getJava()))
|
||||||
setJava(StringUtils.isBlank(getJavaDir()) ? "Default" : "Custom");
|
setJava(StringUtils.isBlank(getJavaDir()) ? "Default" : "Custom");
|
||||||
if ("Default".equals(getJava())) return JavaVersion.fromCurrentEnvironment();
|
if ("Default".equals(getJava())) return JavaVersion.fromCurrentEnvironment();
|
||||||
else if ("Custom".equals(getJava())) {
|
else if (isUsesCustomJavaDir()) {
|
||||||
try {
|
try {
|
||||||
return JavaVersion.fromExecutable(new File(getJavaDir()));
|
return JavaVersion.fromExecutable(new File(getJavaDir()));
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
@@ -477,6 +469,11 @@ public final class VersionSetting {
|
|||||||
} else throw new Error();
|
} else throw new Error();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setJavaVersion(JavaVersion java) {
|
||||||
|
setJava(java.getVersion());
|
||||||
|
setDefaultJavaPath(java.getBinary().toString());
|
||||||
|
}
|
||||||
|
|
||||||
public void addPropertyChangedListener(InvalidationListener listener) {
|
public void addPropertyChangedListener(InvalidationListener listener) {
|
||||||
usesGlobalProperty.addListener(listener);
|
usesGlobalProperty.addListener(listener);
|
||||||
javaProperty.addListener(listener);
|
javaProperty.addListener(listener);
|
||||||
@@ -490,7 +487,6 @@ public final class VersionSetting {
|
|||||||
minecraftArgsProperty.addListener(listener);
|
minecraftArgsProperty.addListener(listener);
|
||||||
noJVMArgsProperty.addListener(listener);
|
noJVMArgsProperty.addListener(listener);
|
||||||
notCheckGameProperty.addListener(listener);
|
notCheckGameProperty.addListener(listener);
|
||||||
noCommonProperty.addListener(listener);
|
|
||||||
showLogsProperty.addListener(listener);
|
showLogsProperty.addListener(listener);
|
||||||
serverIpProperty.addListener(listener);
|
serverIpProperty.addListener(listener);
|
||||||
fullscreenProperty.addListener(listener);
|
fullscreenProperty.addListener(listener);
|
||||||
@@ -555,7 +551,6 @@ public final class VersionSetting {
|
|||||||
obj.addProperty("fullscreen", src.isFullscreen());
|
obj.addProperty("fullscreen", src.isFullscreen());
|
||||||
obj.addProperty("noJVMArgs", src.isNoJVMArgs());
|
obj.addProperty("noJVMArgs", src.isNoJVMArgs());
|
||||||
obj.addProperty("notCheckGame", src.isNotCheckGame());
|
obj.addProperty("notCheckGame", src.isNotCheckGame());
|
||||||
obj.addProperty("noCommon", src.isNoCommon());
|
|
||||||
obj.addProperty("showLogs", src.isShowLogs());
|
obj.addProperty("showLogs", src.isShowLogs());
|
||||||
obj.addProperty("gameDir", src.getGameDir());
|
obj.addProperty("gameDir", src.getGameDir());
|
||||||
obj.addProperty("launcherVisibility", src.getLauncherVisibility().ordinal());
|
obj.addProperty("launcherVisibility", src.getLauncherVisibility().ordinal());
|
||||||
@@ -593,7 +588,6 @@ public final class VersionSetting {
|
|||||||
vs.setFullscreen(Optional.ofNullable(obj.get("fullscreen")).map(JsonElement::getAsBoolean).orElse(false));
|
vs.setFullscreen(Optional.ofNullable(obj.get("fullscreen")).map(JsonElement::getAsBoolean).orElse(false));
|
||||||
vs.setNoJVMArgs(Optional.ofNullable(obj.get("noJVMArgs")).map(JsonElement::getAsBoolean).orElse(false));
|
vs.setNoJVMArgs(Optional.ofNullable(obj.get("noJVMArgs")).map(JsonElement::getAsBoolean).orElse(false));
|
||||||
vs.setNotCheckGame(Optional.ofNullable(obj.get("notCheckGame")).map(JsonElement::getAsBoolean).orElse(false));
|
vs.setNotCheckGame(Optional.ofNullable(obj.get("notCheckGame")).map(JsonElement::getAsBoolean).orElse(false));
|
||||||
vs.setNoCommon(Optional.ofNullable(obj.get("noCommon")).map(JsonElement::getAsBoolean).orElse(false));
|
|
||||||
vs.setShowLogs(Optional.ofNullable(obj.get("showLogs")).map(JsonElement::getAsBoolean).orElse(false));
|
vs.setShowLogs(Optional.ofNullable(obj.get("showLogs")).map(JsonElement::getAsBoolean).orElse(false));
|
||||||
vs.setLauncherVisibility(LauncherVisibility.values()[Optional.ofNullable(obj.get("launcherVisibility")).map(JsonElement::getAsInt).orElse(1)]);
|
vs.setLauncherVisibility(LauncherVisibility.values()[Optional.ofNullable(obj.get("launcherVisibility")).map(JsonElement::getAsInt).orElse(1)]);
|
||||||
vs.setGameDirType(EnumGameDirectory.values()[Optional.ofNullable(obj.get("gameDirType")).map(JsonElement::getAsInt).orElse(0)]);
|
vs.setGameDirType(EnumGameDirectory.values()[Optional.ofNullable(obj.get("gameDirType")).map(JsonElement::getAsInt).orElse(0)]);
|
||||||
|
|||||||
@@ -69,6 +69,7 @@ import org.jackhuang.hmcl.ui.wizard.*;
|
|||||||
import org.jackhuang.hmcl.util.Lang;
|
import org.jackhuang.hmcl.util.Lang;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.InvalidPathException;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -227,7 +228,7 @@ public final class Decorator extends StackPane implements TaskExecutorDialogWiza
|
|||||||
Bindings.createObjectBinding(
|
Bindings.createObjectBinding(
|
||||||
() -> {
|
() -> {
|
||||||
Image image = null;
|
Image image = null;
|
||||||
if (CONFIG.getBackgroundImageType() == EnumBackgroundImage.CUSTOM) {
|
if (CONFIG.getBackgroundImageType() == EnumBackgroundImage.CUSTOM && CONFIG.getBackgroundImage() != null) {
|
||||||
image = tryLoadImage(Paths.get(CONFIG.getBackgroundImage()))
|
image = tryLoadImage(Paths.get(CONFIG.getBackgroundImage()))
|
||||||
.orElse(null);
|
.orElse(null);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ package org.jackhuang.hmcl.ui;
|
|||||||
import com.jfoenix.controls.*;
|
import com.jfoenix.controls.*;
|
||||||
import com.jfoenix.effects.JFXDepthManager;
|
import com.jfoenix.effects.JFXDepthManager;
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
|
import javafx.beans.binding.Bindings;
|
||||||
import javafx.beans.binding.When;
|
import javafx.beans.binding.When;
|
||||||
import javafx.beans.property.ObjectProperty;
|
import javafx.beans.property.ObjectProperty;
|
||||||
import javafx.beans.property.SimpleObjectProperty;
|
import javafx.beans.property.SimpleObjectProperty;
|
||||||
@@ -50,8 +51,10 @@ import static org.jackhuang.hmcl.setting.ConfigHolder.CONFIG;
|
|||||||
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
||||||
|
|
||||||
import java.net.Proxy;
|
import java.net.Proxy;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
public final class SettingsPage extends StackPane implements DecoratorPage {
|
public final class SettingsPage extends StackPane implements DecoratorPage {
|
||||||
private final StringProperty title = new SimpleStringProperty(this, "title", i18n("settings.launcher"));
|
private final StringProperty title = new SimpleStringProperty(this, "title", i18n("settings.launcher"));
|
||||||
@@ -73,7 +76,7 @@ public final class SettingsPage extends StackPane implements DecoratorPage {
|
|||||||
@FXML
|
@FXML
|
||||||
private FontComboBox cboFont;
|
private FontComboBox cboFont;
|
||||||
@FXML
|
@FXML
|
||||||
private FileItem fileCommonLocation;
|
private MultiFileItem<EnumCommonDirectory> fileCommonLocation;
|
||||||
@FXML
|
@FXML
|
||||||
private Label lblDisplay;
|
private Label lblDisplay;
|
||||||
@FXML
|
@FXML
|
||||||
@@ -85,7 +88,7 @@ public final class SettingsPage extends StackPane implements DecoratorPage {
|
|||||||
@FXML
|
@FXML
|
||||||
private ScrollPane scroll;
|
private ScrollPane scroll;
|
||||||
@FXML
|
@FXML
|
||||||
private MultiFileItem backgroundItem;
|
private MultiFileItem<EnumBackgroundImage> backgroundItem;
|
||||||
@FXML
|
@FXML
|
||||||
private StackPane themeColorPickerContainer;
|
private StackPane themeColorPickerContainer;
|
||||||
@FXML
|
@FXML
|
||||||
@@ -102,7 +105,6 @@ public final class SettingsPage extends StackPane implements DecoratorPage {
|
|||||||
private Pane proxyPane;
|
private Pane proxyPane;
|
||||||
|
|
||||||
private ObjectProperty<Proxy.Type> selectedProxyType;
|
private ObjectProperty<Proxy.Type> selectedProxyType;
|
||||||
private ObjectProperty<EnumBackgroundImage> backgroundType;
|
|
||||||
|
|
||||||
public SettingsPage() {
|
public SettingsPage() {
|
||||||
FXUtils.loadFXML(this, "/assets/fxml/setting.fxml");
|
FXUtils.loadFXML(this, "/assets/fxml/setting.fxml");
|
||||||
@@ -182,7 +184,16 @@ public final class SettingsPage extends StackPane implements DecoratorPage {
|
|||||||
}));
|
}));
|
||||||
// ====
|
// ====
|
||||||
|
|
||||||
fileCommonLocation.pathProperty().bindBidirectional(CONFIG.commonDirectoryProperty());
|
fileCommonLocation.loadChildren(Arrays.asList(
|
||||||
|
fileCommonLocation.createChildren(i18n("launcher.common_directory.disabled"), EnumCommonDirectory.DISABLED),
|
||||||
|
fileCommonLocation.createChildren(i18n("launcher.common_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.common_directory.disabled")),
|
||||||
|
CONFIG.commonDirectoryProperty(), CONFIG.commonDirTypeProperty()));
|
||||||
|
|
||||||
FXUtils.installTooltip(btnUpdate, i18n("update.tooltip"));
|
FXUtils.installTooltip(btnUpdate, i18n("update.tooltip"));
|
||||||
checkUpdate();
|
checkUpdate();
|
||||||
@@ -190,28 +201,11 @@ public final class SettingsPage extends StackPane implements DecoratorPage {
|
|||||||
// ==== Background ====
|
// ==== Background ====
|
||||||
backgroundItem.loadChildren(Collections.singletonList(
|
backgroundItem.loadChildren(Collections.singletonList(
|
||||||
backgroundItem.createChildren(i18n("launcher.background.default"), EnumBackgroundImage.DEFAULT)
|
backgroundItem.createChildren(i18n("launcher.background.default"), EnumBackgroundImage.DEFAULT)
|
||||||
));
|
), EnumBackgroundImage.CUSTOM);
|
||||||
backgroundItem.setCustomUserData(EnumBackgroundImage.CUSTOM);
|
backgroundItem.customTextProperty().bindBidirectional(CONFIG.backgroundImageProperty());
|
||||||
backgroundItem.getTxtCustom().textProperty().bindBidirectional(CONFIG.backgroundImageProperty());
|
backgroundItem.selectedDataProperty().bindBidirectional(CONFIG.backgroundImageTypeProperty());
|
||||||
|
|
||||||
backgroundType = new SimpleObjectProperty<EnumBackgroundImage>(EnumBackgroundImage.DEFAULT) {
|
|
||||||
{
|
|
||||||
invalidated();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void invalidated() {
|
|
||||||
backgroundItem.getGroup().getToggles().stream()
|
|
||||||
.filter(it -> it.getUserData() == get())
|
|
||||||
.findFirst()
|
|
||||||
.ifPresent(it -> it.setSelected(true));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
backgroundItem.getGroup().selectedToggleProperty().addListener((observable, oldValue, newValue) -> backgroundType.set((EnumBackgroundImage) newValue.getUserData()));
|
|
||||||
backgroundType.bindBidirectional(CONFIG.backgroundImageTypeProperty());
|
|
||||||
|
|
||||||
backgroundItem.subtitleProperty().bind(
|
backgroundItem.subtitleProperty().bind(
|
||||||
new When(backgroundType.isEqualTo(EnumBackgroundImage.DEFAULT))
|
new When(backgroundItem.selectedDataProperty().isEqualTo(EnumBackgroundImage.DEFAULT))
|
||||||
.then(i18n("launcher.background.default"))
|
.then(i18n("launcher.background.default"))
|
||||||
.otherwise(CONFIG.backgroundImageProperty()));
|
.otherwise(CONFIG.backgroundImageProperty()));
|
||||||
// ====
|
// ====
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import com.jfoenix.controls.JFXComboBox;
|
|||||||
import com.jfoenix.controls.JFXTextField;
|
import com.jfoenix.controls.JFXTextField;
|
||||||
import com.jfoenix.controls.JFXToggleButton;
|
import com.jfoenix.controls.JFXToggleButton;
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
|
import javafx.beans.binding.Bindings;
|
||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
import javafx.scene.control.Label;
|
import javafx.scene.control.Label;
|
||||||
import javafx.scene.control.ScrollPane;
|
import javafx.scene.control.ScrollPane;
|
||||||
@@ -43,6 +44,7 @@ import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
|||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Paths;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
@@ -70,11 +72,10 @@ public final class VersionSettingsController {
|
|||||||
@FXML private JFXCheckBox chkFullscreen;
|
@FXML private JFXCheckBox chkFullscreen;
|
||||||
@FXML private Label lblPhysicalMemory;
|
@FXML private Label lblPhysicalMemory;
|
||||||
@FXML private JFXToggleButton chkNoJVMArgs;
|
@FXML private JFXToggleButton chkNoJVMArgs;
|
||||||
@FXML private JFXToggleButton chkNoCommon;
|
|
||||||
@FXML private JFXToggleButton chkNoGameCheck;
|
@FXML private JFXToggleButton chkNoGameCheck;
|
||||||
@FXML private MultiFileItem globalItem;
|
@FXML private MultiFileItem<Boolean> globalItem;
|
||||||
@FXML private MultiFileItem javaItem;
|
@FXML private MultiFileItem<JavaVersion> javaItem;
|
||||||
@FXML private MultiFileItem gameDirItem;
|
@FXML private MultiFileItem<EnumGameDirectory> gameDirItem;
|
||||||
@FXML private JFXToggleButton chkShowLogs;
|
@FXML private JFXToggleButton chkShowLogs;
|
||||||
@FXML private ImagePickerItem iconPickerItem;
|
@FXML private ImagePickerItem iconPickerItem;
|
||||||
|
|
||||||
@@ -94,9 +95,12 @@ public final class VersionSettingsController {
|
|||||||
initializeSelectedJava();
|
initializeSelectedJava();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
javaItem.setSelectedData(null);
|
||||||
|
javaItem.setFallbackData(JavaVersion.fromCurrentEnvironment());
|
||||||
if (OperatingSystem.CURRENT_OS == OperatingSystem.WINDOWS)
|
if (OperatingSystem.CURRENT_OS == OperatingSystem.WINDOWS)
|
||||||
javaItem.getExtensionFilters().add(new FileChooser.ExtensionFilter("Java", "java.exe", "javaw.exe"));
|
javaItem.getExtensionFilters().add(new FileChooser.ExtensionFilter("Java", "java.exe", "javaw.exe"));
|
||||||
|
|
||||||
|
gameDirItem.setCustomUserData(EnumGameDirectory.CUSTOM);
|
||||||
gameDirItem.loadChildren(Arrays.asList(
|
gameDirItem.loadChildren(Arrays.asList(
|
||||||
gameDirItem.createChildren(i18n("settings.advanced.game_dir.default"), EnumGameDirectory.ROOT_FOLDER),
|
gameDirItem.createChildren(i18n("settings.advanced.game_dir.default"), EnumGameDirectory.ROOT_FOLDER),
|
||||||
gameDirItem.createChildren(i18n("settings.advanced.game_dir.independent"), EnumGameDirectory.VERSION_FOLDER)
|
gameDirItem.createChildren(i18n("settings.advanced.game_dir.independent"), EnumGameDirectory.VERSION_FOLDER)
|
||||||
@@ -132,16 +136,19 @@ public final class VersionSettingsController {
|
|||||||
FXUtils.unbindString(txtServerIP, lastVersionSetting.serverIpProperty());
|
FXUtils.unbindString(txtServerIP, lastVersionSetting.serverIpProperty());
|
||||||
FXUtils.unbindBoolean(chkFullscreen, lastVersionSetting.fullscreenProperty());
|
FXUtils.unbindBoolean(chkFullscreen, lastVersionSetting.fullscreenProperty());
|
||||||
FXUtils.unbindBoolean(chkNoGameCheck, lastVersionSetting.notCheckGameProperty());
|
FXUtils.unbindBoolean(chkNoGameCheck, lastVersionSetting.notCheckGameProperty());
|
||||||
FXUtils.unbindBoolean(chkNoCommon, lastVersionSetting.noCommonProperty());
|
|
||||||
FXUtils.unbindBoolean(chkNoJVMArgs, lastVersionSetting.noJVMArgsProperty());
|
FXUtils.unbindBoolean(chkNoJVMArgs, lastVersionSetting.noJVMArgsProperty());
|
||||||
FXUtils.unbindBoolean(chkShowLogs, lastVersionSetting.showLogsProperty());
|
FXUtils.unbindBoolean(chkShowLogs, lastVersionSetting.showLogsProperty());
|
||||||
FXUtils.unbindEnum(cboLauncherVisibility);
|
FXUtils.unbindEnum(cboLauncherVisibility);
|
||||||
|
|
||||||
|
globalItem.selectedDataProperty().unbindBidirectional(lastVersionSetting.usesGlobalProperty());
|
||||||
|
|
||||||
|
gameDirItem.selectedDataProperty().unbindBidirectional(lastVersionSetting.gameDirTypeProperty());
|
||||||
|
gameDirItem.subtitleProperty().unbind();
|
||||||
}
|
}
|
||||||
|
|
||||||
// unbind data fields
|
// unbind data fields
|
||||||
globalItem.setToggleSelectedListener(null);
|
globalItem.setToggleSelectedListener(null);
|
||||||
javaItem.setToggleSelectedListener(null);
|
javaItem.setToggleSelectedListener(null);
|
||||||
gameDirItem.setToggleSelectedListener(null);
|
|
||||||
|
|
||||||
// bind new data fields
|
// bind new data fields
|
||||||
FXUtils.bindInt(txtWidth, versionSetting.widthProperty());
|
FXUtils.bindInt(txtWidth, versionSetting.widthProperty());
|
||||||
@@ -157,19 +164,15 @@ public final class VersionSettingsController {
|
|||||||
FXUtils.bindString(txtServerIP, versionSetting.serverIpProperty());
|
FXUtils.bindString(txtServerIP, versionSetting.serverIpProperty());
|
||||||
FXUtils.bindBoolean(chkFullscreen, versionSetting.fullscreenProperty());
|
FXUtils.bindBoolean(chkFullscreen, versionSetting.fullscreenProperty());
|
||||||
FXUtils.bindBoolean(chkNoGameCheck, versionSetting.notCheckGameProperty());
|
FXUtils.bindBoolean(chkNoGameCheck, versionSetting.notCheckGameProperty());
|
||||||
FXUtils.bindBoolean(chkNoCommon, versionSetting.noCommonProperty());
|
|
||||||
FXUtils.bindBoolean(chkNoJVMArgs, versionSetting.noJVMArgsProperty());
|
FXUtils.bindBoolean(chkNoJVMArgs, versionSetting.noJVMArgsProperty());
|
||||||
FXUtils.bindBoolean(chkShowLogs, versionSetting.showLogsProperty());
|
FXUtils.bindBoolean(chkShowLogs, versionSetting.showLogsProperty());
|
||||||
FXUtils.bindEnum(cboLauncherVisibility, versionSetting.launcherVisibilityProperty());
|
FXUtils.bindEnum(cboLauncherVisibility, versionSetting.launcherVisibilityProperty());
|
||||||
|
|
||||||
javaItem.setToggleSelectedListener(newValue -> {
|
javaItem.setToggleSelectedListener(newValue -> {
|
||||||
if (javaItem.isCustomToggle(newValue)) {
|
if (javaItem.isCustomToggle(newValue)) {
|
||||||
versionSetting.setJava("Custom");
|
versionSetting.setUsesCustomJavaDir();
|
||||||
versionSetting.setDefaultJavaPath(null);
|
|
||||||
} else {
|
} else {
|
||||||
JavaVersion java = (JavaVersion) newValue.getUserData();
|
versionSetting.setJavaVersion((JavaVersion) newValue.getUserData());
|
||||||
versionSetting.setJava(java.getVersion());
|
|
||||||
versionSetting.setDefaultJavaPath(java.getBinary().toString());
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -177,13 +180,13 @@ public final class VersionSettingsController {
|
|||||||
versionSetting.javaProperty().setChangedListener(it -> initJavaSubtitle(versionSetting));
|
versionSetting.javaProperty().setChangedListener(it -> initJavaSubtitle(versionSetting));
|
||||||
initJavaSubtitle(versionSetting);
|
initJavaSubtitle(versionSetting);
|
||||||
|
|
||||||
if (versionSetting.isUsesGlobal())
|
globalItem.selectedDataProperty().bindBidirectional(versionSetting.usesGlobalProperty());
|
||||||
globalItem.getGroup().getToggles().stream().filter(it -> it.getUserData() == Boolean.TRUE).findFirst().ifPresent(it -> it.setSelected(true));
|
globalItem.subtitleProperty().bind(Bindings.createStringBinding(() -> i18n(versionSetting.isUsesGlobal() ? "settings.type.global" : "settings.type.special"),
|
||||||
else
|
versionSetting.usesGlobalProperty()));
|
||||||
globalItem.getGroup().getToggles().stream().filter(it -> it.getUserData() == Boolean.FALSE).findFirst().ifPresent(it -> it.setSelected(true));
|
|
||||||
globalItem.setToggleSelectedListener(newValue -> {
|
globalItem.setToggleSelectedListener(newValue -> {
|
||||||
// do not call versionSettings.setUsesGlobal(true/false)
|
// do not call versionSettings.setUsesGlobal(true/false)
|
||||||
// because versionSettings can be the global one.
|
// because versionSettings can be the global one.
|
||||||
|
// global versionSettings.usesGlobal is always true.
|
||||||
if ((Boolean) newValue.getUserData())
|
if ((Boolean) newValue.getUserData())
|
||||||
profile.globalizeVersionSetting(versionId);
|
profile.globalizeVersionSetting(versionId);
|
||||||
else
|
else
|
||||||
@@ -192,19 +195,9 @@ public final class VersionSettingsController {
|
|||||||
Platform.runLater(() -> loadVersionSetting(profile, versionId));
|
Platform.runLater(() -> loadVersionSetting(profile, versionId));
|
||||||
});
|
});
|
||||||
|
|
||||||
versionSetting.usesGlobalProperty().setChangedListenerAndOperate(it ->
|
gameDirItem.selectedDataProperty().bindBidirectional(versionSetting.gameDirTypeProperty());
|
||||||
globalItem.setSubtitle(i18n(versionSetting.isUsesGlobal() ? "settings.type.global" : "settings.type.special")));
|
gameDirItem.subtitleProperty().bind(Bindings.createStringBinding(() -> Paths.get(profile.getRepository().getRunDirectory(versionId).getAbsolutePath()).normalize().toString(),
|
||||||
|
versionSetting.gameDirProperty(), versionSetting.gameDirTypeProperty()));
|
||||||
gameDirItem.getGroup().getToggles().stream()
|
|
||||||
.filter(it -> it.getUserData() == versionSetting.getGameDirType())
|
|
||||||
.findFirst().ifPresent(toggle -> toggle.setSelected(true));
|
|
||||||
|
|
||||||
gameDirItem.setCustomUserData(EnumGameDirectory.CUSTOM);
|
|
||||||
gameDirItem.setToggleSelectedListener(newValue -> versionSetting.setGameDirType((EnumGameDirectory) newValue.getUserData()));
|
|
||||||
|
|
||||||
versionSetting.gameDirProperty().setChangedListener(it -> initGameDirSubtitle(versionSetting));
|
|
||||||
versionSetting.gameDirTypeProperty().setChangedListener(it -> initGameDirSubtitle(versionSetting));
|
|
||||||
initGameDirSubtitle(versionSetting);
|
|
||||||
|
|
||||||
lastVersionSetting = versionSetting;
|
lastVersionSetting = versionSetting;
|
||||||
|
|
||||||
@@ -219,30 +212,14 @@ public final class VersionSettingsController {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Toggle> toggles = javaItem.getGroup().getToggles();
|
if (lastVersionSetting.isUsesCustomJavaDir()) {
|
||||||
if ("Custom".equals(lastVersionSetting.getJava())) {
|
javaItem.setSelectedData(null);
|
||||||
toggles.stream()
|
|
||||||
.filter(javaItem::isCustomToggle)
|
|
||||||
.findFirst()
|
|
||||||
.get().setSelected(true);
|
|
||||||
} else {
|
} else {
|
||||||
JavaVersion selectedJava;
|
|
||||||
try {
|
try {
|
||||||
selectedJava = lastVersionSetting.getJavaVersion();
|
javaItem.setSelectedData(lastVersionSetting.getJavaVersion());
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
Thread.currentThread().interrupt();
|
Thread.currentThread().interrupt();
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
toggles.stream()
|
|
||||||
.filter(it -> it.getUserData() == selectedJava)
|
|
||||||
.findFirst()
|
|
||||||
.orElseGet( // fallback to select current java
|
|
||||||
() -> toggles.stream()
|
|
||||||
.filter(it -> it.getUserData() == JavaVersion.fromCurrentEnvironment())
|
|
||||||
.findFirst()
|
|
||||||
.get())
|
|
||||||
.setSelected(true);
|
|
||||||
;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -253,10 +230,6 @@ public final class VersionSettingsController {
|
|||||||
.map(JavaVersion::getBinary).map(File::getAbsolutePath).orElse("Invalid Java Directory"))));
|
.map(JavaVersion::getBinary).map(File::getAbsolutePath).orElse("Invalid Java Directory"))));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initGameDirSubtitle(VersionSetting versionSetting) {
|
|
||||||
gameDirItem.setSubtitle(profile.getRepository().getRunDirectory(versionId).getAbsolutePath());
|
|
||||||
}
|
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private void onExploreIcon() {
|
private void onExploreIcon() {
|
||||||
FileChooser chooser = new FileChooser();
|
FileChooser chooser = new FileChooser();
|
||||||
|
|||||||
@@ -21,10 +21,7 @@ import com.jfoenix.controls.JFXButton;
|
|||||||
import com.jfoenix.controls.JFXRadioButton;
|
import com.jfoenix.controls.JFXRadioButton;
|
||||||
import com.jfoenix.controls.JFXTextField;
|
import com.jfoenix.controls.JFXTextField;
|
||||||
import javafx.beans.NamedArg;
|
import javafx.beans.NamedArg;
|
||||||
import javafx.beans.property.BooleanProperty;
|
import javafx.beans.property.*;
|
||||||
import javafx.beans.property.SimpleBooleanProperty;
|
|
||||||
import javafx.beans.property.SimpleStringProperty;
|
|
||||||
import javafx.beans.property.StringProperty;
|
|
||||||
import javafx.collections.FXCollections;
|
import javafx.collections.FXCollections;
|
||||||
import javafx.collections.ObservableList;
|
import javafx.collections.ObservableList;
|
||||||
import javafx.geometry.Pos;
|
import javafx.geometry.Pos;
|
||||||
@@ -46,12 +43,15 @@ import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
|||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
public class MultiFileItem extends ComponentList {
|
public class MultiFileItem<T> extends ComponentList {
|
||||||
private final StringProperty customTitle = new SimpleStringProperty(this, "customTitle", i18n("selector.custom"));
|
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 StringProperty chooserTitle = new SimpleStringProperty(this, "chooserTitle", i18n("selector.choose_file"));
|
||||||
private final BooleanProperty directory = new SimpleBooleanProperty(this, "directory", false);
|
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 ObservableList<FileChooser.ExtensionFilter> extensionFilters = FXCollections.observableArrayList();
|
||||||
|
|
||||||
private final ToggleGroup group = new ToggleGroup();
|
private final ToggleGroup group = new ToggleGroup();
|
||||||
@@ -64,6 +64,7 @@ public class MultiFileItem extends ComponentList {
|
|||||||
|
|
||||||
private Consumer<Toggle> toggleSelectedListener;
|
private Consumer<Toggle> toggleSelectedListener;
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
public MultiFileItem(@NamedArg(value = "hasCustom", defaultValue = "true") boolean hasCustom) {
|
public MultiFileItem(@NamedArg(value = "hasCustom", defaultValue = "true") boolean hasCustom) {
|
||||||
this.hasCustom = hasCustom;
|
this.hasCustom = hasCustom;
|
||||||
|
|
||||||
@@ -110,6 +111,20 @@ public class MultiFileItem extends ComponentList {
|
|||||||
group.selectedToggleProperty().addListener((a, b, newValue) -> {
|
group.selectedToggleProperty().addListener((a, b, newValue) -> {
|
||||||
if (toggleSelectedListener != null)
|
if (toggleSelectedListener != null)
|
||||||
toggleSelectedListener.accept(newValue);
|
toggleSelectedListener.accept(newValue);
|
||||||
|
|
||||||
|
selectedData.set((T) newValue.getUserData());
|
||||||
|
});
|
||||||
|
selectedData.addListener((a, b, newValue) -> {
|
||||||
|
Optional<Toggle> selecting = group.getToggles().stream()
|
||||||
|
.filter(it -> it.getUserData() == newValue)
|
||||||
|
.findFirst();
|
||||||
|
if (!selecting.isPresent()) {
|
||||||
|
selecting = group.getToggles().stream()
|
||||||
|
.filter(it -> it.getUserData() == getFallbackData())
|
||||||
|
.findFirst();
|
||||||
|
}
|
||||||
|
|
||||||
|
selecting.ifPresent(toggle -> toggle.setSelected(true));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -117,11 +132,11 @@ public class MultiFileItem extends ComponentList {
|
|||||||
return createChildren(title, null);
|
return createChildren(title, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Node createChildren(String title, Object userData) {
|
public Node createChildren(String title, T userData) {
|
||||||
return createChildren(title, "", userData);
|
return createChildren(title, "", userData);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Node createChildren(String title, String subtitle, Object userData) {
|
public Node createChildren(String title, String subtitle, T userData) {
|
||||||
BorderPane pane = new BorderPane();
|
BorderPane pane = new BorderPane();
|
||||||
pane.setStyle("-fx-padding: 3;");
|
pane.setStyle("-fx-padding: 3;");
|
||||||
FXUtils.setLimitHeight(pane, 20);
|
FXUtils.setLimitHeight(pane, 20);
|
||||||
@@ -146,12 +161,9 @@ public class MultiFileItem extends ComponentList {
|
|||||||
pane.getChildren().add(custom);
|
pane.getChildren().add(custom);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onExploreJavaDir() {
|
public void loadChildren(Collection<Node> list, T customUserData) {
|
||||||
DirectoryChooser chooser = new DirectoryChooser();
|
loadChildren(list);
|
||||||
chooser.setTitle(i18n(getChooserTitle()));
|
setCustomUserData(customUserData);
|
||||||
File selectedDir = chooser.showDialog(Controllers.getStage());
|
|
||||||
if (selectedDir != null)
|
|
||||||
txtCustom.setText(selectedDir.getAbsolutePath());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ToggleGroup getGroup() {
|
public ToggleGroup getGroup() {
|
||||||
@@ -182,7 +194,7 @@ public class MultiFileItem extends ComponentList {
|
|||||||
this.chooserTitle.set(chooserTitle);
|
this.chooserTitle.set(chooserTitle);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCustomUserData(Object userData) {
|
public void setCustomUserData(T userData) {
|
||||||
radioCustom.setUserData(userData);
|
radioCustom.setUserData(userData);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -225,4 +237,28 @@ public class MultiFileItem extends ComponentList {
|
|||||||
public ObservableList<FileChooser.ExtensionFilter> getExtensionFilters() {
|
public ObservableList<FileChooser.ExtensionFilter> getExtensionFilters() {
|
||||||
return extensionFilters;
|
return extensionFilters;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public T getSelectedData() {
|
||||||
|
return selectedData.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ObjectProperty<T> selectedDataProperty() {
|
||||||
|
return selectedData;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSelectedData(T selectedData) {
|
||||||
|
this.selectedData.set(selectedData);
|
||||||
|
}
|
||||||
|
|
||||||
|
public T getFallbackData() {
|
||||||
|
return fallbackData.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ObjectProperty<T> fallbackDataProperty() {
|
||||||
|
return fallbackData;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFallbackData(T fallbackData) {
|
||||||
|
this.fallbackData.set(fallbackData);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,7 +31,7 @@
|
|||||||
</right>
|
</right>
|
||||||
</BorderPane>
|
</BorderPane>
|
||||||
|
|
||||||
<FileItem fx:id="fileCommonLocation" name="%launcher.common_directory" title="%launcher.common_directory.choose" tooltip="%settings.launcher.common_path.tooltip" />
|
<MultiFileItem fx:id="fileCommonLocation" title="%launcher.common_directory" chooserTitle="%launcher.common_directory.choose" hasSubtitle="true" customText="%settings.custom" />
|
||||||
|
|
||||||
<MultiFileItem fx:id="backgroundItem" title="%launcher.background" chooserTitle="%launcher.background.choose"
|
<MultiFileItem fx:id="backgroundItem" title="%launcher.background" chooserTitle="%launcher.background.choose"
|
||||||
hasSubtitle="true" customText="%settings.custom" />
|
hasSubtitle="true" customText="%settings.custom" />
|
||||||
|
|||||||
@@ -139,14 +139,6 @@
|
|||||||
<JFXToggleButton fx:id="chkNoJVMArgs" size="7" FXUtils.limitHeight="10" />
|
<JFXToggleButton fx:id="chkNoJVMArgs" size="7" FXUtils.limitHeight="10" />
|
||||||
</right>
|
</right>
|
||||||
</BorderPane>
|
</BorderPane>
|
||||||
<BorderPane>
|
|
||||||
<left>
|
|
||||||
<Label text="%settings.advanced.no_common"/>
|
|
||||||
</left>
|
|
||||||
<right>
|
|
||||||
<JFXToggleButton fx:id="chkNoCommon" size="7" FXUtils.limitHeight="10" />
|
|
||||||
</right>
|
|
||||||
</BorderPane>
|
|
||||||
<BorderPane>
|
<BorderPane>
|
||||||
<left>
|
<left>
|
||||||
<Label text="%settings.advanced.dont_check_game_completeness"/>
|
<Label text="%settings.advanced.dont_check_game_completeness"/>
|
||||||
|
|||||||
@@ -153,6 +153,8 @@ launcher.background.choose=Choose background path.
|
|||||||
launcher.background.default=Default
|
launcher.background.default=Default
|
||||||
launcher.common_directory=Common Directory
|
launcher.common_directory=Common Directory
|
||||||
launcher.common_directory.choose=Choose common directory.
|
launcher.common_directory.choose=Choose common directory.
|
||||||
|
launcher.common_directory.default=Default
|
||||||
|
launcher.common_directory.disabled=Disabled
|
||||||
launcher.contact=Contact Us
|
launcher.contact=Contact Us
|
||||||
launcher.crash=Hello Minecraft! Launcher has crashed!
|
launcher.crash=Hello Minecraft! Launcher has crashed!
|
||||||
launcher.crash_out_dated=Hello Minecraft! Launcher has crashed! Your launcher is outdated. Update it!
|
launcher.crash_out_dated=Hello Minecraft! Launcher has crashed! Your launcher is outdated. Update it!
|
||||||
|
|||||||
@@ -153,6 +153,8 @@ launcher.background.choose=選擇背景路徑
|
|||||||
launcher.background.default=默認(自動檢索啓動器同目錄下的 background.png/jpg 及 bg 文件夾內的圖片)
|
launcher.background.default=默認(自動檢索啓動器同目錄下的 background.png/jpg 及 bg 文件夾內的圖片)
|
||||||
launcher.common_directory=公共文件夾
|
launcher.common_directory=公共文件夾
|
||||||
launcher.common_directory.choose=選擇公共文件夾
|
launcher.common_directory.choose=選擇公共文件夾
|
||||||
|
launcher.common_directory.default=默認
|
||||||
|
launcher.common_directory.disabled=禁用
|
||||||
launcher.contact=聯繫我們
|
launcher.contact=聯繫我們
|
||||||
launcher.crash=Hello Minecraft! Launcher 遇到了無法處理的錯誤,請複製下列內容並通過 MCBBS、貼吧、GitHub 或 Minecraft Forum 反饋 bug。
|
launcher.crash=Hello Minecraft! Launcher 遇到了無法處理的錯誤,請複製下列內容並通過 MCBBS、貼吧、GitHub 或 Minecraft Forum 反饋 bug。
|
||||||
launcher.crash_out_dated=Hello Minecraft! Launcher 遇到了無法處理的錯誤,已檢測到您的啓動器不是最新版本,請更新後再試!
|
launcher.crash_out_dated=Hello Minecraft! Launcher 遇到了無法處理的錯誤,已檢測到您的啓動器不是最新版本,請更新後再試!
|
||||||
|
|||||||
@@ -151,8 +151,10 @@ launcher=启动器
|
|||||||
launcher.background=背景地址
|
launcher.background=背景地址
|
||||||
launcher.background.choose=选择背景路径
|
launcher.background.choose=选择背景路径
|
||||||
launcher.background.default=默认(自动检索启动器同目录下的 background.png/jpg 及 bg 文件夹内的图片)
|
launcher.background.default=默认(自动检索启动器同目录下的 background.png/jpg 及 bg 文件夹内的图片)
|
||||||
launcher.common_directory=公共文件夹
|
launcher.common_directory=公共文件夹(统一存放游戏资源文件,减少游戏体积)
|
||||||
launcher.common_directory.choose=选择公共文件夹
|
launcher.common_directory.choose=选择公共文件夹
|
||||||
|
launcher.common_directory.default=默认(%AppData%/.minecraft 或者 ~/.minecraft)
|
||||||
|
launcher.common_directory.disabled=禁用(总是使用游戏路径)
|
||||||
launcher.contact=联系我们
|
launcher.contact=联系我们
|
||||||
launcher.crash=Hello Minecraft! Launcher 遇到了无法处理的错误,请复制下列内容并通过 MCBBS、贴吧、GitHub 或 Minecraft Forum 反馈 bug。
|
launcher.crash=Hello Minecraft! Launcher 遇到了无法处理的错误,请复制下列内容并通过 MCBBS、贴吧、GitHub 或 Minecraft Forum 反馈 bug。
|
||||||
launcher.crash_out_dated=Hello Minecraft! Launcher 遇到了无法处理的错误,已检测到您的启动器不是最新版本,请更新后再试!
|
launcher.crash_out_dated=Hello Minecraft! Launcher 遇到了无法处理的错误,已检测到您的启动器不是最新版本,请更新后再试!
|
||||||
|
|||||||
Reference in New Issue
Block a user