This commit is contained in:
Tungstend 2023-03-02 21:53:21 +08:00
parent 6078459bb2
commit 34be0f88cb
4 changed files with 108 additions and 129 deletions

View File

@ -284,7 +284,7 @@ public class BaseInfoData implements Cloneable, Observable {
} }
@JsonAdapter(PercentageSize.Serializer.class) @JsonAdapter(PercentageSize.Serializer.class)
public static class PercentageSize implements Cloneable { public static class PercentageSize implements Cloneable, Observable {
public enum Reference { public enum Reference {
SCREEN_WIDTH, SCREEN_WIDTH,
@ -329,7 +329,7 @@ public class BaseInfoData implements Cloneable, Observable {
} }
public PercentageSize() { public PercentageSize() {
addPropertyChangedListener(onInvalidating(this::invalidate));
} }
public void addPropertyChangedListener(InvalidationListener listener) { public void addPropertyChangedListener(InvalidationListener listener) {
@ -337,6 +337,22 @@ public class BaseInfoData implements Cloneable, Observable {
sizeProperty.addListener(listener); sizeProperty.addListener(listener);
} }
private ObservableHelper observableHelper = new ObservableHelper(this);
@Override
public void addListener(InvalidationListener listener) {
observableHelper.addListener(listener);
}
@Override
public void removeListener(InvalidationListener listener) {
observableHelper.removeListener(listener);
}
private void invalidate() {
observableHelper.invalidate();
}
@Override @Override
public PercentageSize clone() { public PercentageSize clone() {
PercentageSize size = new PercentageSize(); PercentageSize size = new PercentageSize();

View File

@ -22,6 +22,8 @@ import com.tungsten.fclcore.fakefx.beans.property.SimpleBooleanProperty;
import com.tungsten.fclcore.fakefx.beans.property.SimpleObjectProperty; import com.tungsten.fclcore.fakefx.beans.property.SimpleObjectProperty;
import com.tungsten.fclcore.fakefx.beans.property.SimpleStringProperty; import com.tungsten.fclcore.fakefx.beans.property.SimpleStringProperty;
import com.tungsten.fclcore.fakefx.beans.property.StringProperty; import com.tungsten.fclcore.fakefx.beans.property.StringProperty;
import com.tungsten.fclcore.fakefx.collections.FXCollections;
import com.tungsten.fclcore.fakefx.collections.ObservableList;
import com.tungsten.fclcore.util.fakefx.ObservableHelper; import com.tungsten.fclcore.util.fakefx.ObservableHelper;
import java.lang.reflect.Type; import java.lang.reflect.Type;
@ -312,74 +314,33 @@ public class ButtonEventData implements Cloneable, Observable {
/** /**
* Output keycodes * Output keycodes
*/ */
private final ObjectProperty<ArrayList<Integer>> outputKeycodesProperty = new SimpleObjectProperty<>(this, "outputKeycodes", new ArrayList<>()); private final ObservableList<Integer> outputKeycodesList = FXCollections.observableList(new ArrayList<>());
public ObjectProperty<ArrayList<Integer>> outputKeycodesProperty() { public ObservableList<Integer> outputKeycodesList() {
return outputKeycodesProperty; return outputKeycodesList;
} }
public void setOutputKeycodes(ArrayList<Integer> outputKeycodes) { public void setOutputKeycodes(ObservableList<Integer> outputKeycodes) {
outputKeycodesProperty.set(outputKeycodes); outputKeycodesList.setAll(outputKeycodes);
}
public ArrayList<Integer> getOutputKeycodes() {
return outputKeycodesProperty.get();
} }
/** /**
* Switch view group visibility * Switch view group visibility
*/ */
private final ObjectProperty<ArrayList<String>> bindViewGroupProperty = new SimpleObjectProperty<>(this, "bindViewGroup", new ArrayList<>()); private final ObservableList<String> bindViewGroupList = FXCollections.observableList(new ArrayList<>());
public ObjectProperty<ArrayList<String>> bindViewGroupProperty() { public ObservableList<String> bindViewGroupList() {
return bindViewGroupProperty; return bindViewGroupList;
} }
public void setBindViewGroup(ArrayList<String> bindViewGroup) { public void setBindViewGroup(ObservableList<String> bindViewGroup) {
bindViewGroupProperty.set(bindViewGroup); bindViewGroupList.setAll(bindViewGroup);
}
public ArrayList<String> getBindViewGroup() {
return bindViewGroupProperty.get();
} }
public Event() { public Event() {
addPropertyChangedListener(onInvalidating(this::invalidate)); addPropertyChangedListener(onInvalidating(this::invalidate));
} }
public void addKeycode(int keycode) {
ArrayList<Integer> keycodes = getOutputKeycodes();
if (!keycodes.contains(keycode)) {
keycodes.add(keycode);
setOutputKeycodes(keycodes);
}
}
public void removeKeycode(int keycode) {
ArrayList<Integer> keycodes = getOutputKeycodes();
for (int i = 0; i < keycodes.size(); i++) {
if (keycodes.get(i) == keycode) {
keycodes.remove(i);
break;
}
}
setOutputKeycodes(keycodes);
}
public void bindViewGroup(String groupId) {
ArrayList<String> groups = getBindViewGroup();
if (!groups.contains(groupId)) {
groups.add(groupId);
setBindViewGroup(groups);
}
}
public void unbindViewGroup(String groupId) {
ArrayList<String> groups = getBindViewGroup();
groups.remove(groupId);
setBindViewGroup(groups);
}
public void addPropertyChangedListener(InvalidationListener listener) { public void addPropertyChangedListener(InvalidationListener listener) {
pointerFollowProperty.addListener(listener); pointerFollowProperty.addListener(listener);
autoKeepProperty.addListener(listener); autoKeepProperty.addListener(listener);
@ -389,8 +350,8 @@ public class ButtonEventData implements Cloneable, Observable {
switchTouchModeProperty.addListener(listener); switchTouchModeProperty.addListener(listener);
inputProperty.addListener(listener); inputProperty.addListener(listener);
outputTextProperty.addListener(listener); outputTextProperty.addListener(listener);
outputKeycodesProperty.addListener(listener); outputKeycodesList.addListener(listener);
bindViewGroupProperty.addListener(listener); bindViewGroupList.addListener(listener);
} }
private ObservableHelper observableHelper = new ObservableHelper(this); private ObservableHelper observableHelper = new ObservableHelper(this);
@ -420,8 +381,8 @@ public class ButtonEventData implements Cloneable, Observable {
event.setSwitchTouchMode(isSwitchTouchMode()); event.setSwitchTouchMode(isSwitchTouchMode());
event.setInput(isInput()); event.setInput(isInput());
event.setOutputText(getOutputText()); event.setOutputText(getOutputText());
event.setOutputKeycodes(getOutputKeycodes()); event.setOutputKeycodes(outputKeycodesList());
event.setBindViewGroup(getBindViewGroup()); event.setBindViewGroup(bindViewGroupList());
return event; return event;
} }
@ -441,8 +402,8 @@ public class ButtonEventData implements Cloneable, Observable {
obj.addProperty("switchTouchMode", src.isSwitchTouchMode()); obj.addProperty("switchTouchMode", src.isSwitchTouchMode());
obj.addProperty("input", src.isInput()); obj.addProperty("input", src.isInput());
obj.addProperty("outputText", src.getOutputText()); obj.addProperty("outputText", src.getOutputText());
obj.addProperty("outputKeycodes", gson.toJson(src.getOutputKeycodes())); obj.addProperty("outputKeycodes", gson.toJson(src.outputKeycodesList()));
obj.addProperty("bindViewGroup", gson.toJson(src.getBindViewGroup())); obj.addProperty("bindViewGroup", gson.toJson(src.bindViewGroupList()));
return obj; return obj;
} }
@ -464,8 +425,8 @@ public class ButtonEventData implements Cloneable, Observable {
event.setSwitchTouchMode(Optional.ofNullable(obj.get("switchTouchMode")).map(JsonElement::getAsBoolean).orElse(false)); event.setSwitchTouchMode(Optional.ofNullable(obj.get("switchTouchMode")).map(JsonElement::getAsBoolean).orElse(false));
event.setInput(Optional.ofNullable(obj.get("input")).map(JsonElement::getAsBoolean).orElse(false)); event.setInput(Optional.ofNullable(obj.get("input")).map(JsonElement::getAsBoolean).orElse(false));
event.setOutputText(Optional.ofNullable(obj.get("outputText")).map(JsonElement::getAsString).orElse("")); event.setOutputText(Optional.ofNullable(obj.get("outputText")).map(JsonElement::getAsString).orElse(""));
event.setOutputKeycodes(gson.fromJson(Optional.ofNullable(obj.get("outputKeycodes")).map(JsonElement::getAsString).orElse(gson.toJson(new ArrayList<>())), new TypeToken<Integer>(){}.getType())); event.setOutputKeycodes(gson.fromJson(Optional.ofNullable(obj.get("outputKeycodes")).map(JsonElement::getAsString).orElse(gson.toJson(FXCollections.observableArrayList(new ArrayList<>()))), new TypeToken<Integer>(){}.getType()));
event.setBindViewGroup(gson.fromJson(Optional.ofNullable(obj.get("bindViewGroup")).map(JsonElement::getAsString).orElse(gson.toJson(new ArrayList<>())), new TypeToken<String>(){}.getType())); event.setBindViewGroup(gson.fromJson(Optional.ofNullable(obj.get("bindViewGroup")).map(JsonElement::getAsString).orElse(gson.toJson(FXCollections.observableArrayList(new ArrayList<>()))), new TypeToken<String>(){}.getType()));
return event; return event;
} }

View File

@ -20,6 +20,8 @@ import com.tungsten.fclcore.fakefx.beans.property.ObjectProperty;
import com.tungsten.fclcore.fakefx.beans.property.SimpleObjectProperty; import com.tungsten.fclcore.fakefx.beans.property.SimpleObjectProperty;
import com.tungsten.fclcore.fakefx.beans.property.SimpleStringProperty; import com.tungsten.fclcore.fakefx.beans.property.SimpleStringProperty;
import com.tungsten.fclcore.fakefx.beans.property.StringProperty; import com.tungsten.fclcore.fakefx.beans.property.StringProperty;
import com.tungsten.fclcore.fakefx.collections.FXCollections;
import com.tungsten.fclcore.fakefx.collections.ObservableList;
import com.tungsten.fclcore.util.fakefx.ObservableHelper; import com.tungsten.fclcore.util.fakefx.ObservableHelper;
import java.lang.reflect.Type; import java.lang.reflect.Type;
@ -169,108 +171,108 @@ public class ControlViewGroup implements Cloneable, Observable {
} }
@JsonAdapter(ViewData.Serializer.class) @JsonAdapter(ViewData.Serializer.class)
public static class ViewData implements Cloneable { public static class ViewData implements Cloneable, Observable {
/** /**
* Button data list * Button data list
*/ */
private final ObjectProperty<ArrayList<ControlButtonData>> buttonListProperty = new SimpleObjectProperty<>(this, "buttonList", new ArrayList<>()); private final ObservableList<ControlButtonData> buttonList = FXCollections.observableArrayList(new ArrayList<>());
public ObjectProperty<ArrayList<ControlButtonData>> buttonListProperty() { public ObservableList<ControlButtonData> buttonList() {
return buttonListProperty; return buttonList;
} }
public void setButtonList(ArrayList<ControlButtonData> buttonList) { public void setButtonList(ObservableList<ControlButtonData> list) {
buttonListProperty.set(buttonList); buttonList.setAll(list);
}
public ArrayList<ControlButtonData> getButtonList() {
return buttonListProperty.get();
} }
/** /**
* Direction data list * Direction data list
*/ */
private final ObjectProperty<ArrayList<ControlDirectionData>> directionListProperty = new SimpleObjectProperty<>(this, "directionList", new ArrayList<>()); private final ObservableList<ControlDirectionData> directionList = FXCollections.observableArrayList(new ArrayList<>());
public ObjectProperty<ArrayList<ControlDirectionData>> directionListProperty() { public ObservableList<ControlDirectionData> directionList() {
return directionListProperty; return directionList;
} }
public void setDirectionList(ArrayList<ControlDirectionData> directionList) { public void setDirectionList(ObservableList<ControlDirectionData> list) {
directionListProperty.set(directionList); directionList.setAll(list);
}
public ArrayList<ControlDirectionData> getDirectionList() {
return directionListProperty.get();
} }
public void addButton(ControlButtonData data) { public void addButton(ControlButtonData data) {
ArrayList<ControlButtonData> list = getButtonList();
boolean exist = false; boolean exist = false;
for (ControlButtonData buttonData : list) { for (ControlButtonData buttonData : buttonList()) {
if (buttonData.equals(data)) { if (buttonData.equals(data)) {
exist = true; exist = true;
break; break;
} }
} }
if (!exist) { if (!exist) {
list.add(data); buttonList.add(data);
setButtonList(list);
} }
} }
public void removeButton(ControlButtonData data) { public void removeButton(ControlButtonData data) {
ArrayList<ControlButtonData> list = getButtonList(); for (ControlButtonData buttonData : buttonList()) {
for (ControlButtonData buttonData : list) {
if (buttonData.equals(data)) { if (buttonData.equals(data)) {
list.remove(buttonData); buttonList.remove(buttonData);
setButtonList(list);
break; break;
} }
} }
} }
public void addDirection(ControlDirectionData data) { public void addDirection(ControlDirectionData data) {
ArrayList<ControlDirectionData> list = getDirectionList();
boolean exist = false; boolean exist = false;
for (ControlDirectionData directionData : list) { for (ControlDirectionData directionData : directionList()) {
if (directionData.equals(data)) { if (directionData.equals(data)) {
exist = true; exist = true;
break; break;
} }
} }
if (!exist) { if (!exist) {
list.add(data); directionList.add(data);
setDirectionList(list);
} }
} }
public void removeDirection(ControlDirectionData data) { public void removeDirection(ControlDirectionData data) {
ArrayList<ControlDirectionData> list = getDirectionList(); for (ControlDirectionData directionData : directionList()) {
for (ControlDirectionData directionData : list) {
if (directionData.equals(data)) { if (directionData.equals(data)) {
list.remove(directionData); directionList.remove(directionData);
setDirectionList(list);
break; break;
} }
} }
} }
public ViewData() { public ViewData() {
addPropertyChangedListener(onInvalidating(this::invalidate));
} }
public void addPropertyChangedListener(InvalidationListener listener) { public void addPropertyChangedListener(InvalidationListener listener) {
buttonListProperty.addListener(listener); buttonList.addListener(listener);
directionListProperty.addListener(listener); directionList.addListener(listener);
}
private ObservableHelper observableHelper = new ObservableHelper(this);
@Override
public void addListener(InvalidationListener listener) {
observableHelper.addListener(listener);
}
@Override
public void removeListener(InvalidationListener listener) {
observableHelper.removeListener(listener);
}
private void invalidate() {
observableHelper.invalidate();
} }
@Override @Override
public ViewData clone() { public ViewData clone() {
ViewData data = new ViewData(); ViewData data = new ViewData();
data.setButtonList(getButtonList()); data.setButtonList(buttonList());
data.setDirectionList(getDirectionList()); data.setDirectionList(directionList());
return data; return data;
} }
@ -281,8 +283,8 @@ public class ControlViewGroup implements Cloneable, Observable {
JsonObject obj = new JsonObject(); JsonObject obj = new JsonObject();
Gson gson = new GsonBuilder().setPrettyPrinting().create(); Gson gson = new GsonBuilder().setPrettyPrinting().create();
obj.addProperty("buttonList", gson.toJson(src.getButtonList())); obj.addProperty("buttonList", gson.toJson(src.buttonList()));
obj.addProperty("directionList", gson.toJson(src.getDirectionList())); obj.addProperty("directionList", gson.toJson(src.directionList()));
return obj; return obj;
} }
@ -296,8 +298,8 @@ public class ControlViewGroup implements Cloneable, Observable {
ViewData data = new ViewData(); ViewData data = new ViewData();
Gson gson = new GsonBuilder().setPrettyPrinting().create(); Gson gson = new GsonBuilder().setPrettyPrinting().create();
data.setButtonList(gson.fromJson(Optional.ofNullable(obj.get("buttonList")).map(JsonElement::getAsString).orElse(gson.toJson(new ArrayList<>())), new TypeToken<ControlButtonData>(){}.getType())); data.setButtonList(gson.fromJson(Optional.ofNullable(obj.get("buttonList")).map(JsonElement::getAsString).orElse(gson.toJson(FXCollections.observableArrayList(new ArrayList<>()))), new TypeToken<ControlButtonData>(){}.getType()));
data.setDirectionList(gson.fromJson(Optional.ofNullable(obj.get("directionList")).map(JsonElement::getAsString).orElse(gson.toJson(new ArrayList<>())), new TypeToken<ControlDirectionData>(){}.getType())); data.setDirectionList(gson.fromJson(Optional.ofNullable(obj.get("directionList")).map(JsonElement::getAsString).orElse(gson.toJson(FXCollections.observableArrayList(new ArrayList<>()))), new TypeToken<ControlDirectionData>(){}.getType()));
return data; return data;
} }

View File

@ -22,12 +22,12 @@ import com.tungsten.fclauncher.FCLPath;
import com.tungsten.fclcore.fakefx.beans.InvalidationListener; import com.tungsten.fclcore.fakefx.beans.InvalidationListener;
import com.tungsten.fclcore.fakefx.beans.Observable; import com.tungsten.fclcore.fakefx.beans.Observable;
import com.tungsten.fclcore.fakefx.beans.property.IntegerProperty; import com.tungsten.fclcore.fakefx.beans.property.IntegerProperty;
import com.tungsten.fclcore.fakefx.beans.property.ObjectProperty;
import com.tungsten.fclcore.fakefx.beans.property.ReadOnlyIntegerProperty; import com.tungsten.fclcore.fakefx.beans.property.ReadOnlyIntegerProperty;
import com.tungsten.fclcore.fakefx.beans.property.SimpleIntegerProperty; import com.tungsten.fclcore.fakefx.beans.property.SimpleIntegerProperty;
import com.tungsten.fclcore.fakefx.beans.property.SimpleObjectProperty;
import com.tungsten.fclcore.fakefx.beans.property.SimpleStringProperty; import com.tungsten.fclcore.fakefx.beans.property.SimpleStringProperty;
import com.tungsten.fclcore.fakefx.beans.property.StringProperty; import com.tungsten.fclcore.fakefx.beans.property.StringProperty;
import com.tungsten.fclcore.fakefx.collections.FXCollections;
import com.tungsten.fclcore.fakefx.collections.ObservableList;
import com.tungsten.fclcore.util.ToStringBuilder; import com.tungsten.fclcore.util.ToStringBuilder;
import com.tungsten.fclcore.util.fakefx.ObservableHelper; import com.tungsten.fclcore.util.fakefx.ObservableHelper;
import com.tungsten.fclcore.util.gson.fakefx.factories.JavaFxPropertyTypeAdapterFactory; import com.tungsten.fclcore.util.gson.fakefx.factories.JavaFxPropertyTypeAdapterFactory;
@ -38,9 +38,10 @@ import java.io.IOException;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Optional; import java.util.Optional;
import java.util.stream.Collectors;
@JsonAdapter(Controller.Serializer.class) @JsonAdapter(Controller.Serializer.class)
public class Controller implements Observable { public class Controller implements Cloneable, Observable {
private final SimpleStringProperty name; private final SimpleStringProperty name;
@ -108,18 +109,14 @@ public class Controller implements Observable {
return controllerVersion.get(); return controllerVersion.get();
} }
private final SimpleObjectProperty<ArrayList<ControlViewGroup>> viewGroups; private final ObservableList<ControlViewGroup> viewGroups;
public ObjectProperty<ArrayList<ControlViewGroup>> viewGroupsProperty() { public ObservableList<ControlViewGroup> viewGroups() {
return viewGroups; return viewGroups;
} }
public ArrayList<ControlViewGroup> getViewGroups() { public void setViewGroups(ObservableList<ControlViewGroup> viewGroups) {
return viewGroups.get(); this.viewGroups.addAll(viewGroups);
}
public void setViewGroups(ArrayList<ControlViewGroup> viewGroups) {
this.viewGroups.set(viewGroups);
} }
public Controller(String name) { public Controller(String name) {
@ -139,15 +136,15 @@ public class Controller implements Observable {
} }
public Controller(String name, String version, String author, String description, int controllerVersion) { public Controller(String name, String version, String author, String description, int controllerVersion) {
this(name, version, author, description, controllerVersion, new ArrayList<>()); this(name, version, author, description, controllerVersion, FXCollections.observableArrayList(new ArrayList<>()));
} }
public Controller(String name, String version, String author, String description, int controllerVersion, ArrayList<ControlViewGroup> viewGroups) { public Controller(String name, String version, String author, String description, int controllerVersion, ObservableList<ControlViewGroup> viewGroups) {
this.name = new SimpleStringProperty(this, "name", name); this.name = new SimpleStringProperty(this, "name", name);
this.version = new SimpleStringProperty(this, "version", version); this.version = new SimpleStringProperty(this, "version", version);
this.author = new SimpleStringProperty(this, "author", author); this.author = new SimpleStringProperty(this, "author", author);
this.description = new SimpleStringProperty(this, "description", description); this.description = new SimpleStringProperty(this, "description", description);
this.viewGroups = new SimpleObjectProperty<>(this, "viewGroups", viewGroups); this.viewGroups = viewGroups;
this.controllerVersion.set(controllerVersion); this.controllerVersion.set(controllerVersion);
@ -155,26 +152,22 @@ public class Controller implements Observable {
} }
public void addViewGroup(ControlViewGroup viewGroup) { public void addViewGroup(ControlViewGroup viewGroup) {
ArrayList<ControlViewGroup> list = getViewGroups();
boolean exist = false; boolean exist = false;
for (ControlViewGroup group : list) { for (ControlViewGroup group : viewGroups()) {
if (viewGroup.getId().equals(group.getId())) { if (viewGroup.getId().equals(group.getId())) {
exist = true; exist = true;
break; break;
} }
} }
if (!exist) { if (!exist) {
list.add(viewGroup); viewGroups.add(viewGroup);
setViewGroups(list);
} }
} }
public void removeViewGroup(ControlViewGroup viewGroup) { public void removeViewGroup(ControlViewGroup viewGroup) {
ArrayList<ControlViewGroup> list = getViewGroups(); for (ControlViewGroup group : viewGroups()) {
for (ControlViewGroup group : list) {
if (viewGroup.getId().equals(group.getId())) { if (viewGroup.getId().equals(group.getId())) {
list.remove(group); viewGroups.remove(group);
setViewGroups(list);
break; break;
} }
} }
@ -217,6 +210,13 @@ public class Controller implements Observable {
observableHelper.invalidate(); observableHelper.invalidate();
} }
@Override
public Controller clone() {
ObservableList<ControlViewGroup> viewGroups = FXCollections.observableArrayList(new ArrayList<>());
viewGroups.addAll(viewGroups().stream().map(ControlViewGroup::clone).collect(Collectors.toList()));
return new Controller(getName() + "_clone", getVersion(), getAuthor(), getDescription(), getControllerVersion(), viewGroups);
}
// function // function
public String getFileName() { public String getFileName() {
@ -249,7 +249,7 @@ public class Controller implements Observable {
jsonObject.addProperty("author", src.getAuthor()); jsonObject.addProperty("author", src.getAuthor());
jsonObject.addProperty("description", src.getDescription()); jsonObject.addProperty("description", src.getDescription());
jsonObject.addProperty("controllerVersion", src.getControllerVersion()); jsonObject.addProperty("controllerVersion", src.getControllerVersion());
jsonObject.addProperty("viewGroups", new GsonBuilder().setPrettyPrinting().create().toJson(src.getViewGroups())); jsonObject.addProperty("viewGroups", new GsonBuilder().setPrettyPrinting().create().toJson(src.viewGroups()));
return jsonObject; return jsonObject;
} }
@ -265,7 +265,7 @@ public class Controller implements Observable {
String author = Optional.ofNullable(obj.get("author")).map(JsonElement::getAsString).orElse(""); String author = Optional.ofNullable(obj.get("author")).map(JsonElement::getAsString).orElse("");
String description = Optional.ofNullable(obj.get("description")).map(JsonElement::getAsString).orElse(""); String description = Optional.ofNullable(obj.get("description")).map(JsonElement::getAsString).orElse("");
int controllerVersion = Optional.ofNullable(obj.get("controllerVersion")).map(JsonElement::getAsInt).orElse(Constants.CONTROLLER_VERSION); int controllerVersion = Optional.ofNullable(obj.get("controllerVersion")).map(JsonElement::getAsInt).orElse(Constants.CONTROLLER_VERSION);
ArrayList<ControlViewGroup> viewGroups = gson.fromJson(Optional.ofNullable(obj.get("controllerVersion")).map(JsonElement::getAsString).orElse(gson.toJson(new ArrayList<>())), new TypeToken<ControlViewGroup>(){}.getType()); ObservableList<ControlViewGroup> viewGroups = gson.fromJson(Optional.ofNullable(obj.get("viewGroups")).map(JsonElement::getAsString).orElse(gson.toJson(FXCollections.observableArrayList(new ArrayList<>()))), new TypeToken<ControlViewGroup>(){}.getType());
return new Controller(name, version, author, description, controllerVersion, viewGroups); return new Controller(name, version, author, description, controllerVersion, viewGroups);
} }