Merge pull request #282 from yushijinhun/javafx

重构
This commit is contained in:
huanghongxun
2018-02-18 17:12:16 +08:00
committed by GitHub
27 changed files with 105 additions and 136 deletions

View File

@@ -20,8 +20,7 @@ package org.jackhuang.hmcl.game;
import com.google.gson.JsonParseException;
import org.jackhuang.hmcl.mod.Modpack;
import org.jackhuang.hmcl.util.CompressingUtils;
import org.jackhuang.hmcl.util.Constants;
import org.jackhuang.hmcl.util.Lang;
import org.jackhuang.hmcl.util.JsonUtils;
import org.jackhuang.hmcl.util.StringUtils;
import java.io.File;
@@ -82,9 +81,9 @@ public final class HMCLModpackManager {
*/
public static Modpack readHMCLModpackManifest(File file) throws IOException, JsonParseException {
String manifestJson = CompressingUtils.readTextZipEntry(file, "modpack.json");
Modpack manifest = Lang.requireJsonNonNull(Constants.GSON.fromJson(manifestJson, Modpack.class));
Modpack manifest = JsonUtils.fromNonNullJson(manifestJson, Modpack.class);
String gameJson = CompressingUtils.readTextZipEntry(file, "minecraft/pack.json");
Version game = Lang.requireJsonNonNull(Constants.GSON.fromJson(gameJson, Version.class));
Version game = JsonUtils.fromNonNullJson(gameJson, Version.class);
if (game.getJar() == null)
if (StringUtils.isBlank(manifest.getVersion()))
throw new JsonParseException("Cannot recognize the game version of modpack " + file + ".");

View File

@@ -106,7 +106,7 @@ public final class ModpackHelper {
else throw new IllegalStateException("Unrecognized modpack: " + modpack);
}
public static Task getUpdateTask(Profile profile, File zipFile, String name, ModpackConfiguration configuration) throws UnsupportedModpackException, MismatchedModpackTypeException, IOException {
public static Task getUpdateTask(Profile profile, File zipFile, String name, ModpackConfiguration<?> configuration) throws UnsupportedModpackException, MismatchedModpackTypeException, IOException {
Modpack modpack = ModpackHelper.readModpackManifest(zipFile);
switch (configuration.getType()) {

View File

@@ -73,9 +73,8 @@ public final class Accounts {
}
public static Optional<String> getCurrentCharacter(Map<Object, Object> storage) {
Optional<Map> properties = Lang.get(storage, "properties", Map.class);
if (!properties.isPresent()) return Optional.empty();
return Lang.get(properties.get(), "character", String.class);
return Lang.get(storage, "properties", Map.class)
.flatMap(properties -> Lang.get(properties, "character", String.class));
}
static String getAccountId(Account account) {

View File

@@ -69,7 +69,7 @@ public class Settings {
{
for (Map<Object, Object> settings : SETTINGS.getAccounts()) {
Optional<String> characterName = Accounts.getCurrentCharacter(settings);
AccountFactory factory = Accounts.ACCOUNT_FACTORY.get(Lang.get(settings, "type", String.class, ""));
AccountFactory<?> factory = Accounts.ACCOUNT_FACTORY.get(Lang.get(settings, "type", String.class, ""));
if (factory == null || !characterName.isPresent()) {
// unrecognized account type, so remove it.
SETTINGS.getAccounts().remove(settings);

View File

@@ -138,7 +138,7 @@ public final class VersionSetting {
permSizeProperty.set(permSize);
}
private final ImmediateIntegerProperty maxMemoryProperty = new ImmediateIntegerProperty(this, "maxMemory", (int) OperatingSystem.SUGGESTED_MEMORY);
private final ImmediateIntegerProperty maxMemoryProperty = new ImmediateIntegerProperty(this, "maxMemory", OperatingSystem.SUGGESTED_MEMORY);
public ImmediateIntegerProperty maxMemoryProperty() {
return maxMemoryProperty;

View File

@@ -214,19 +214,19 @@ public final class AccountsPage extends StackPane implements DecoratorPage {
this.title.set(title);
}
public static String accountException(Exception account) {
if (account instanceof InvalidCredentialsException) {
public static String accountException(Exception exception) {
if (exception instanceof InvalidCredentialsException) {
return Main.i18n("account.failed.invalid_credentials");
} else if (account instanceof NoCharacterException) {
} else if (exception instanceof NoCharacterException) {
return Main.i18n("account.failed.no_charactor");
} else if (account instanceof ServerDisconnectException) {
} else if (exception instanceof ServerDisconnectException) {
return Main.i18n("account.failed.connect_authentication_server");
} else if (account instanceof InvalidTokenException) {
} else if (exception instanceof InvalidTokenException) {
return Main.i18n("account.failed.invalid_token");
} else if (account instanceof InvalidPasswordException) {
} else if (exception instanceof InvalidPasswordException) {
return Main.i18n("account.failed.invalid_password");
} else {
return account.getClass() + ": " + ((Exception) account).getLocalizedMessage();
return exception.getClass() + ": " + exception.getLocalizedMessage();
}
}

View File

@@ -94,19 +94,36 @@ public final class FXUtils {
});
}
public static <T> void addListener(Node node, String key, ObservableValue<T> value, Consumer<T> callback) {
ChangeListener<T> listener = (a, b, newValue) -> callback.accept(newValue);
node.getProperties().put(key, new Pair<>(callback, listener));
value.addListener(listener);
private static class ListenerPair<T> {
ObservableValue<T> value;
ChangeListener<? super T> listener;
ListenerPair(ObservableValue<T> value, ChangeListener<? super T> listener) {
this.value = value;
this.listener = listener;
}
void bind() {
value.addListener(listener);
}
void unbind() {
value.removeListener(listener);
}
}
public static <T> void removeListener(Node node, String key) {
if (node.getProperties().get(key) instanceof Pair) {
Pair pair = (Pair) node.getProperties().get(key);
if (pair.getValue() instanceof ObservableValue && pair.getKey() instanceof ChangeListener) {
((ObservableValue) pair.getValue()).removeListener((ChangeListener) pair.getKey());
}
}
public static <T> void addListener(Node node, String key, ObservableValue<T> value, Consumer<? super T> callback) {
ListenerPair<T> pair = new ListenerPair<>(value, (a, b, newValue) -> callback.accept(newValue));
node.getProperties().put(key, pair);
pair.bind();
}
public static void removeListener(Node node, String key) {
Lang.convert(node.getProperties().get(key), ListenerPair.class)
.ifPresent(info -> {
info.unbind();
node.getProperties().remove(key);
});
}
public static void setValidateWhileTextChanged(Node field, boolean validate) {

View File

@@ -21,13 +21,9 @@ import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.control.MultipleSelectionModel;
public final class NoneMultipleSelectionModel<T> extends MultipleSelectionModel<T> {
private static final NoneMultipleSelectionModel INSTANCE = new NoneMultipleSelectionModel();
private NoneMultipleSelectionModel() {}
public class NoneMultipleSelectionModel<T> extends MultipleSelectionModel<T> {
@SuppressWarnings("unchecked")
public static <T> NoneMultipleSelectionModel<T> getInstance() {
return (NoneMultipleSelectionModel<T>) INSTANCE;
public NoneMultipleSelectionModel() {
}
@Override

View File

@@ -217,10 +217,12 @@ public class RipplerContainer extends StackPane {
private static class StyleableProperties {
private static final CssMetaData<RipplerContainer, Paint> RIPPLER_FILL = new CssMetaData<RipplerContainer, Paint>("-jfx-rippler-fill", StyleConverter.getPaintConverter(), Color.rgb(0, 200, 255)) {
@Override
public boolean isSettable(RipplerContainer control) {
return control.ripplerFill == null || !control.ripplerFill.isBound();
}
@Override
public StyleableProperty<Paint> getStyleableProperty(RipplerContainer control) {
return control.ripplerFillProperty();
}
@@ -232,7 +234,7 @@ public class RipplerContainer extends StackPane {
}
static {
List<CssMetaData<? extends Styleable, ?>> styleables = new ArrayList<>(Parent.getClassCssMetaData());
List<CssMetaData<? extends Styleable, ?>> styleables = new ArrayList<>(Node.getClassCssMetaData());
Collections.addAll(styleables, RIPPLER_FILL);
STYLEABLES = Collections.unmodifiableList(styleables);
}

View File

@@ -44,7 +44,10 @@ public final class ExportWizardProvider implements WizardProvider {
@Override
public Object finish(Map<String, Object> settings) {
return new HMCLModpackExportTask(profile.getRepository(), version, (List<String>) settings.get(ModpackFileSelectionPage.MODPACK_FILE_SELECTION),
@SuppressWarnings("unchecked")
List<String> whitelist = (List<String>) settings.get(ModpackFileSelectionPage.MODPACK_FILE_SELECTION);
return new HMCLModpackExportTask(profile.getRepository(), version, whitelist,
new Modpack(
(String) settings.get(ModpackInfoPage.MODPACK_NAME),
(String) settings.get(ModpackInfoPage.MODPACK_AUTHOR),

View File

@@ -62,7 +62,7 @@ public final class ModpackFileSelectionPage extends StackPane implements WizardP
FXUtils.loadFXML(this, "/assets/fxml/modpack/selection.fxml");
rootNode = getTreeItem(profile.getRepository().getRunDirectory(version), "minecraft");
treeView.setRoot(rootNode);
treeView.setSelectionModel(NoneMultipleSelectionModel.getInstance());
treeView.setSelectionModel(new NoneMultipleSelectionModel<>());
}
private CheckBoxTreeItem<String> getTreeItem(File file, String basePath) {

View File

@@ -56,7 +56,7 @@ public class AppDataUpgrader extends IUpgrader {
al.add("--noupdate");
AccessController.doPrivileged((PrivilegedExceptionAction<Void>) () -> {
new URLClassLoader(new URL[]{jar.toURI().toURL()},
URLClassLoader.getSystemClassLoader().getParent()).loadClass(mainClass)
ClassLoader.getSystemClassLoader().getParent()).loadClass(mainClass)
.getMethod("main", String[].class).invoke(null, new Object[]{al.toArray(new String[0])});
return null;
});

View File

@@ -47,6 +47,7 @@ public class OfflineAccount extends Account {
throw new IllegalArgumentException("Username cannot be blank");
}
@Override
public UUID getUUID() {
return UUIDTypeAdapter.fromString(uuid);
}

View File

@@ -1,9 +1,8 @@
package org.jackhuang.hmcl.auth.yggdrasil;
import com.google.gson.JsonParseException;
import org.jackhuang.hmcl.util.Constants;
import org.jackhuang.hmcl.util.Immutable;
import org.jackhuang.hmcl.util.Lang;
import org.jackhuang.hmcl.util.JsonUtils;
import org.jackhuang.hmcl.util.NetworkUtils;
import java.io.IOException;
@@ -36,7 +35,7 @@ public final class AuthlibInjectorBuildInfo {
}
public static AuthlibInjectorBuildInfo requestBuildInfo(String updateUrl) throws IOException, JsonParseException {
return Lang.requireJsonNonNull(Constants.GSON.fromJson(NetworkUtils.doGet(NetworkUtils.toURL(updateUrl)), AuthlibInjectorBuildInfo.class));
return JsonUtils.fromNonNullJson(NetworkUtils.doGet(NetworkUtils.toURL(updateUrl)), AuthlibInjectorBuildInfo.class);
}
public static final String UPDATE_URL = "https://authlib-injector.to2mbn.org/api/buildInfo";

View File

@@ -198,7 +198,7 @@ public class DefaultLauncher extends Launcher {
}
private final Map<String, Supplier<Boolean>> forbiddens = Lang.mapOf(
new Pair<>("-Xincgc", () -> options.getJava().getParsedVersion() >= JavaVersion.JAVA_9)
new Pair<String, Supplier<Boolean>>("-Xincgc", () -> options.getJava().getParsedVersion() >= JavaVersion.JAVA_9)
);
protected Map<String, Supplier<Boolean>> getForbiddens() {

View File

@@ -20,15 +20,13 @@ package org.jackhuang.hmcl.mod;
import com.google.gson.JsonParseException;
import com.google.gson.annotations.SerializedName;
import org.jackhuang.hmcl.util.CompressingUtils;
import org.jackhuang.hmcl.util.Constants;
import org.jackhuang.hmcl.util.Immutable;
import org.jackhuang.hmcl.util.Lang;
import org.jackhuang.hmcl.util.JsonUtils;
import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
/**
*
@@ -120,7 +118,7 @@ public final class CurseManifest {
*/
public static Modpack readCurseForgeModpackManifest(File f) throws IOException, JsonParseException {
String json = CompressingUtils.readTextZipEntry(f, "manifest.json");
CurseManifest manifest = Lang.requireJsonNonNull(Constants.GSON.fromJson(json, CurseManifest.class));
CurseManifest manifest = JsonUtils.fromNonNullJson(json, CurseManifest.class);
return new Modpack(manifest.getName(), manifest.getAuthor(), manifest.getVersion(), manifest.getMinecraft().getGameVersion(),
CompressingUtils.readTextZipEntryQuietly(f, "modlist.html").orElse( "No description"), manifest);
}

View File

@@ -94,4 +94,8 @@ public final class Constants {
public static <T> Predicate<T> falsePredicate() {
return s -> false;
}
public static <T> Consumer<T> emptyConsumer() {
return x -> {};
}
}

View File

@@ -48,7 +48,7 @@ public class ImmediateBooleanProperty extends SimpleBooleanProperty {
super.unbind();
}
private Consumer<Boolean> listener = Lang.EMPTY_CONSUMER;
private Consumer<Boolean> listener = Constants.emptyConsumer();
private final ChangeListener<Boolean> changeListener = (a, b, newValue) -> listener.accept(newValue);
public void setChangedListener(Consumer<Boolean> listener) {

View File

@@ -49,7 +49,7 @@ public class ImmediateDoubleProperty extends SimpleDoubleProperty {
super.unbind();
}
private Consumer<Double> listener = Lang.EMPTY_CONSUMER;
private Consumer<Double> listener = Constants.emptyConsumer();
private final ChangeListener<Number> changeListener = (a, b, newValue) -> listener.accept(newValue.doubleValue());
public void setChangedListener(Consumer<Double> listener) {

View File

@@ -48,7 +48,7 @@ public class ImmediateIntegerProperty extends SimpleIntegerProperty {
super.unbind();
}
private Consumer<Integer> listener = Lang.EMPTY_CONSUMER;
private Consumer<Integer> listener = Constants.emptyConsumer();
private final ChangeListener<Number> changeListener = (a, b, newValue) -> listener.accept(newValue.intValue());
public void setChangedListener(Consumer<Integer> listener) {

View File

@@ -48,7 +48,7 @@ public class ImmediateObjectProperty<T> extends SimpleObjectProperty<T> {
super.unbind();
}
private Consumer<T> listener = Lang.EMPTY_CONSUMER;
private Consumer<T> listener = Constants.emptyConsumer();
private final ChangeListener<T> changeListener = (a, b, newValue) -> listener.accept(newValue);
public void setChangedListener(Consumer<T> listener) {

View File

@@ -0,0 +1,15 @@
package org.jackhuang.hmcl.util;
import com.google.gson.JsonParseException;
public final class JsonUtils {
private JsonUtils() {}
public static <T> T fromNonNullJson(String json, Class<T> classOfT) throws JsonParseException {
T parsed = Constants.GSON.fromJson(json, classOfT);
if (parsed == null)
throw new JsonParseException("Json object cannot be null.");
return parsed;
}
}

View File

@@ -5,8 +5,6 @@
*/
package org.jackhuang.hmcl.util;
import com.google.gson.JsonParseException;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
@@ -22,19 +20,7 @@ public final class Lang {
private Lang() {
}
public static final Consumer EMPTY_CONSUMER = a -> {
};
public static <T> T requireJsonNonNull(T obj) throws JsonParseException {
return requireJsonNonNull(obj, "Json object cannot be null.");
}
public static <T> T requireJsonNonNull(T obj, String message) throws JsonParseException {
if (obj == null)
throw new JsonParseException(message);
return obj;
}
@SafeVarargs
public static <K, V> Map<K, V> mapOf(Pair<K, V>... pairs) {
HashMap<K, V> map = new HashMap<>();
for (Pair<K, V> pair : pairs)
@@ -42,14 +28,14 @@ public final class Lang {
return map;
}
public static <K, V> V getOrPut(Map<K, V> map, K key, Supplier<V> defaultValue) {
public static <K, V> V computeIfAbsent(Map<K, V> map, K key, Supplier<V> computingFunction) {
V value = map.get(key);
if (value == null) {
V answer = defaultValue.get();
map.put(key, answer);
return answer;
} else
return value;
V newValue = computingFunction.get();
map.put(key, newValue);
return newValue;
}
return value;
}
public static <E extends Throwable> void throwable(Throwable exception) throws E {
@@ -230,8 +216,8 @@ public final class Lang {
return convert(map.get(key), clazz, defaultValue);
}
public static <T> List<T> merge(Collection<T> a, Collection<T> b) {
LinkedList<T> result = new LinkedList<>();
public static <T> List<T> merge(Collection<? extends T> a, Collection<? extends T> b) {
List<T> result = new ArrayList<>();
if (a != null)
result.addAll(a);
if (b != null)
@@ -239,17 +225,6 @@ public final class Lang {
return result;
}
public static <T> List<T> merge(Collection<T> a, Collection<T> b, Collection<T> c) {
LinkedList<T> result = new LinkedList<>();
if (a != null)
result.addAll(a);
if (b != null)
result.addAll(b);
if (c != null)
result.addAll(c);
return result;
}
public static void executeDelayed(Runnable runnable, TimeUnit timeUnit, long timeout, boolean isDaemon) {
thread(() -> {
try {
@@ -322,6 +297,7 @@ public final class Lang {
}
}
@SafeVarargs
public static <T> T nonNull(T... t) {
for (T a : t) if (a != null) return a;
return null;

View File

@@ -17,10 +17,6 @@
*/
package org.jackhuang.hmcl.util;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.X509TrustManager;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -28,9 +24,6 @@ import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.Proxy;
import java.net.URL;
import java.security.GeneralSecurityException;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import java.util.Map;
import java.util.Objects;
import java.util.function.Supplier;
@@ -46,41 +39,6 @@ public final class NetworkUtils {
private NetworkUtils() {
}
private static final X509TrustManager XTM = new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] xcs, String string) {
}
@Override
public void checkServerTrusted(X509Certificate[] xcs, String string) {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
};
private static final HostnameVerifier HNV = (a, b) -> true;
private static volatile boolean initHttps = false;
private static synchronized void initHttps() {
if (initHttps)
return;
initHttps = true;
System.setProperty("https.protocols", "SSLv3,TLSv1");
try {
SSLContext c = SSLContext.getInstance("SSL");
c.init(null, new X509TrustManager[] { XTM }, new SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(c.getSocketFactory());
} catch (GeneralSecurityException ignore) {
}
HttpsURLConnection.setDefaultHostnameVerifier(HNV);
}
private static Supplier<String> userAgentSupplier = RandomUserAgent::randomUserAgent;
public static String getUserAgent() {
@@ -92,7 +50,6 @@ public final class NetworkUtils {
}
public static HttpURLConnection createConnection(URL url, Proxy proxy) throws IOException {
initHttps();
HttpURLConnection connection = (HttpURLConnection) url.openConnection(proxy);
connection.setDoInput(true);
connection.setUseCaches(false);

View File

@@ -3,6 +3,9 @@ package org.jackhuang.hmcl.util;
import java.util.HashMap;
import java.util.Map;
/**
* Optifine has blocked Java's useragent, so we have to make up one.
*/
public class RandomUserAgent {
private static final HashMap<String, String[]> uaMap = new HashMap<>();

View File

@@ -52,14 +52,14 @@ public final class ReflectionHelper {
}
PRIMITIVES = Lang.mapOf(
new Pair("byte", Byte.class),
new Pair("short", Short.class),
new Pair("int", Integer.class),
new Pair("long", Long.class),
new Pair("char", Character.class),
new Pair("float", Float.class),
new Pair("double", Double.class),
new Pair("boolean", Boolean.class)
new Pair<>("byte", Byte.class),
new Pair<>("short", Short.class),
new Pair<>("int", Integer.class),
new Pair<>("long", Long.class),
new Pair<>("char", Character.class),
new Pair<>("float", Float.class),
new Pair<>("double", Double.class),
new Pair<>("boolean", Boolean.class)
);
}

View File

@@ -62,7 +62,7 @@ public final class SimpleMultimap<K, V> {
}
public Collection<V> get(K key) {
return Lang.getOrPut(map, key, valuer);
return Lang.computeIfAbsent(map, key, valuer);
}
public void put(K key, V value) {