Let Config implement Observable

This commit is contained in:
yushijinhun 2018-07-09 21:58:18 +08:00
parent 5cf6ef88a6
commit b0d71a5511
No known key found for this signature in database
GPG Key ID: 5BC167F73EA558E4
2 changed files with 48 additions and 2 deletions

View File

@ -18,8 +18,10 @@
package org.jackhuang.hmcl.setting; package org.jackhuang.hmcl.setting;
import java.io.File; import java.io.File;
import java.lang.reflect.Modifier;
import java.util.Map; import java.util.Map;
import java.util.TreeMap; import java.util.TreeMap;
import java.util.stream.Stream;
import org.hildan.fxgson.creators.ObservableListCreator; import org.hildan.fxgson.creators.ObservableListCreator;
import org.hildan.fxgson.creators.ObservableMapCreator; import org.hildan.fxgson.creators.ObservableMapCreator;
@ -28,12 +30,15 @@ import org.hildan.fxgson.factories.JavaFxPropertyTypeAdapterFactory;
import org.jackhuang.hmcl.Launcher; import org.jackhuang.hmcl.Launcher;
import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorServer; import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorServer;
import org.jackhuang.hmcl.util.FileTypeAdapter; import org.jackhuang.hmcl.util.FileTypeAdapter;
import org.jackhuang.hmcl.util.ObservableHelper;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.GsonBuilder; import com.google.gson.GsonBuilder;
import com.google.gson.JsonParseException; import com.google.gson.JsonParseException;
import com.google.gson.annotations.SerializedName; import com.google.gson.annotations.SerializedName;
import javafx.beans.InvalidationListener;
import javafx.beans.Observable;
import javafx.beans.property.BooleanProperty; import javafx.beans.property.BooleanProperty;
import javafx.beans.property.DoubleProperty; import javafx.beans.property.DoubleProperty;
import javafx.beans.property.IntegerProperty; import javafx.beans.property.IntegerProperty;
@ -47,7 +52,7 @@ import javafx.collections.ObservableList;
import javafx.collections.ObservableMap; import javafx.collections.ObservableMap;
import javafx.collections.ObservableSet; import javafx.collections.ObservableSet;
public final class Config implements Cloneable { public final class Config implements Cloneable, Observable {
private static final Gson CONFIG_GSON = new GsonBuilder() private static final Gson CONFIG_GSON = new GsonBuilder()
.registerTypeAdapter(VersionSetting.class, VersionSetting.Serializer.INSTANCE) .registerTypeAdapter(VersionSetting.class, VersionSetting.Serializer.INSTANCE)
@ -61,7 +66,11 @@ public final class Config implements Cloneable {
.create(); .create();
public static Config fromJson(String json) throws JsonParseException { public static Config fromJson(String json) throws JsonParseException {
return CONFIG_GSON.fromJson(json, Config.class); Config instance = CONFIG_GSON.fromJson(json, Config.class);
// Gson will replace the property fields (even they are final!)
// So we have to add the listeners again after deserialization
instance.addListenerToProperties();
return instance;
} }
@SerializedName("last") @SerializedName("last")
@ -129,6 +138,39 @@ public final class Config implements Cloneable {
public final ObservableList<AuthlibInjectorServer> authlibInjectorServers = FXCollections.observableArrayList(); public final ObservableList<AuthlibInjectorServer> authlibInjectorServers = FXCollections.observableArrayList();
private transient ObservableHelper helper = new ObservableHelper(this);
public Config() {
addListenerToProperties();
}
private void addListenerToProperties() {
Stream.of(getClass().getFields())
.filter(it -> {
int modifiers = it.getModifiers();
return Modifier.isPublic(modifiers) && !Modifier.isStatic(modifiers);
})
.filter(it -> Observable.class.isAssignableFrom(it.getType()))
.map(it -> {
try {
return (Observable) it.get(this);
} catch (IllegalAccessException e) {
throw new IllegalStateException("Failed to get my own properties");
}
})
.forEach(helper::receiveUpdatesFrom);
}
@Override
public void addListener(InvalidationListener listener) {
helper.addListener(listener);
}
@Override
public void removeListener(InvalidationListener listener) {
helper.removeListener(listener);
}
public String toJson() { public String toJson() {
return CONFIG_GSON.toJson(this); return CONFIG_GSON.toJson(this);
} }

View File

@ -62,4 +62,8 @@ public class ObservableHelper implements Observable, InvalidationListener {
this.invalidate(); this.invalidate();
} }
public void receiveUpdatesFrom(Observable observable) {
observable.removeListener(this); // remove the previously added listener(if any)
observable.addListener(this);
}
} }