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;
import java.io.File;
import java.lang.reflect.Modifier;
import java.util.Map;
import java.util.TreeMap;
import java.util.stream.Stream;
import org.hildan.fxgson.creators.ObservableListCreator;
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.auth.authlibinjector.AuthlibInjectorServer;
import org.jackhuang.hmcl.util.FileTypeAdapter;
import org.jackhuang.hmcl.util.ObservableHelper;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonParseException;
import com.google.gson.annotations.SerializedName;
import javafx.beans.InvalidationListener;
import javafx.beans.Observable;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.IntegerProperty;
@ -47,7 +52,7 @@ import javafx.collections.ObservableList;
import javafx.collections.ObservableMap;
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()
.registerTypeAdapter(VersionSetting.class, VersionSetting.Serializer.INSTANCE)
@ -61,7 +66,11 @@ public final class Config implements Cloneable {
.create();
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")
@ -129,6 +138,39 @@ public final class Config implements Cloneable {
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() {
return CONFIG_GSON.toJson(this);
}

View File

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