use of org.terasology.nui.widgets.treeView.JsonTree in project Terasology by MovingBlocks.
the class NUIEditorNodeUtils method getNodeInfo.
/**
* @param node A node in an asset tree.
* @param nuiManager The {@link NUIManager} to be used for widget type resolution.
* @return The info about this node's type.
*/
public static NodeInfo getNodeInfo(JsonTree node, NUIManager nuiManager) {
Deque<JsonTree> pathToRoot = getPathToRoot(node);
// Start iterating from top to bottom.
Class<?> currentClass = null;
Class<?> activeLayoutClass = null;
Function<String, Class<? extends UIWidget>> resolve = (String type) -> verifyNotNull(nuiManager.getWidgetMetadataLibrary().resolve(type, ModuleContext.getContext()), "Failed to resolve widget %s in %s", type, ModuleContext.getContext()).getType();
for (JsonTree n : pathToRoot) {
if (n.isRoot()) {
// currentClass is not set - set it to the screen type.
String type = (String) n.getChildWithKey("type").getValue().getValue();
currentClass = resolve.apply(type);
} else {
if (List.class.isAssignableFrom(currentClass) && n.getValue().getKey() == null && "contents".equals(n.getParent().getValue().getKey())) {
// Transition from a "contents" list to a UIWidget.
currentClass = UIWidget.class;
} else {
// Retrieve the type of an unspecified UIWidget.
if (currentClass == UIWidget.class && n.hasSiblingWithKey("type")) {
String type = (String) n.getSiblingWithKey("type").getValue().getValue();
currentClass = resolve.apply(type);
}
// If the current class is a layout, remember its' value (but do not set until later on!)
Class<?> layoutClass = null;
if (UILayout.class.isAssignableFrom(currentClass)) {
layoutClass = currentClass;
}
if (UILayout.class.isAssignableFrom(currentClass) && "contents".equals(n.getValue().getKey())) {
// "contents" fields of a layout are always (widget) lists.
currentClass = List.class;
} else if (UIWidget.class.isAssignableFrom(currentClass) && "layoutInfo".equals(n.getValue().getKey())) {
// Set currentClass to the layout hint type for the active layout.
currentClass = (Class<?>) ReflectionUtil.getTypeParameter(activeLayoutClass.getGenericSuperclass(), 0);
} else {
String value = n.getValue().toString();
Set<Field> fields = ReflectionUtils.getAllFields(currentClass);
Optional<Field> newField = fields.stream().filter(f -> f.getName().equalsIgnoreCase(value)).findFirst();
if (newField.isPresent()) {
currentClass = newField.get().getType();
} else {
Optional<Field> serializedNameField = fields.stream().filter(f -> f.isAnnotationPresent(SerializedName.class) && f.getAnnotation(SerializedName.class).value().equals(value)).findFirst();
if (serializedNameField.isPresent()) {
currentClass = serializedNameField.get().getType();
} else {
return null;
}
}
}
// Set the layout class value.
if (layoutClass != null) {
activeLayoutClass = layoutClass;
}
}
}
}
// If the final result is a generic UIWidget, attempt to retrieve its type.
if (currentClass == UIWidget.class && node.hasChildWithKey("type")) {
String type = (String) node.getChildWithKey("type").getValue().getValue();
currentClass = resolve.apply(type);
}
return new NodeInfo(currentClass, activeLayoutClass);
}
use of org.terasology.nui.widgets.treeView.JsonTree in project Terasology by MovingBlocks.
the class NUIEditorNodeUtils method createNewWidget.
/**
* @param type The type of the widget.
* @param id The id of the widget.
* @param addLayoutInfo Whether a few layout settings from {@link RelativeLayout} should be added.
* @return The {@link JsonTree} with the given type/id to be used as an empty widget template within {@link
* NUIEditorScreen}.
*/
public static JsonTree createNewWidget(String type, String id, boolean addLayoutInfo) {
JsonTree widget = new JsonTree(new JsonTreeValue(null, null, JsonTreeValue.Type.OBJECT));
widget.addChild(new JsonTreeValue("type", type, JsonTreeValue.Type.KEY_VALUE_PAIR));
widget.addChild(new JsonTreeValue("id", id, JsonTreeValue.Type.KEY_VALUE_PAIR));
JsonTree layoutInfo = new JsonTree(new JsonTreeValue("layoutInfo", null, JsonTreeValue.Type.OBJECT));
if (addLayoutInfo) {
layoutInfo.addChild(new JsonTreeValue("width", 500, JsonTreeValue.Type.KEY_VALUE_PAIR));
JsonTree hPosition = new JsonTree(new JsonTreeValue("position-horizontal-center", null, JsonTreeValue.Type.OBJECT));
JsonTree vPosition = new JsonTree(new JsonTreeValue("position-vertical-center", null, JsonTreeValue.Type.OBJECT));
layoutInfo.addChild(hPosition);
layoutInfo.addChild(vPosition);
}
widget.addChild(layoutInfo);
return widget;
}
use of org.terasology.nui.widgets.treeView.JsonTree in project Terasology by MovingBlocks.
the class NUIEditorMenuTreeBuilder method populateContextMenu.
private void populateContextMenu(JsonTree node, MenuTree addTree, boolean isSkin) {
NUIEditorNodeUtils.NodeInfo nodeInfo;
if (isSkin) {
nodeInfo = NUIEditorNodeUtils.getSkinNodeInfo(node);
} else {
nodeInfo = NUIEditorNodeUtils.getNodeInfo(node, nuiManager);
}
if (nodeInfo != null) {
Class clazz = nodeInfo.getNodeClass();
if (clazz != null) {
for (Field field : ReflectionUtils.getAllFields(clazz)) {
if ((!UIWidget.class.isAssignableFrom(clazz) || field.isAnnotationPresent(LayoutConfig.class)) && // Exclude static final fields, as they shouldn't be modified.
!(Modifier.isFinal(field.getModifiers()) && Modifier.isStatic(field.getModifiers()))) {
field.setAccessible(true);
String name = getNodeName(field);
if (!node.hasChildWithKey(name)) {
addTree.addOption(name, n -> {
try {
JsonTree child = createChild(name, node, field, clazz);
for (Consumer<JsonTree> listener : addContextMenuListeners) {
listener.accept(child);
}
} catch (IllegalAccessException | InstantiationException e) {
logger.warn("Could not add child", e);
}
}, node);
}
}
}
// If the node is part of a layout, add an option to add the layoutInfo node.
if (!node.isRoot() && !node.getParent().isRoot()) {
String layoutInfo = "layoutInfo";
String contents = "contents";
Class parentParentClass = NUIEditorNodeUtils.getNodeInfo((JsonTree) node.getParent().getParent(), nuiManager).getNodeClass();
if (!node.hasChildWithKey(layoutInfo) && UIWidget.class.isAssignableFrom(clazz) && node.getParent().getValue() != null && node.getParent().getValue().getKey() != null && node.getParent().getValue().getKey().equals(contents) && UILayout.class.isAssignableFrom(parentParentClass)) {
addTree.addOption(layoutInfo, n -> {
JsonTree child = new JsonTree(new JsonTreeValue(layoutInfo, null, JsonTreeValue.Type.OBJECT));
child.setExpanded(true);
n.addChild(child);
}, node);
}
}
}
} else {
logger.warn("Could not get class for node {}", node.getValue().toString());
}
}
use of org.terasology.nui.widgets.treeView.JsonTree in project Terasology by MovingBlocks.
the class AbstractEditorScreen method pasteJson.
/**
* Attempts to serialize the system clipboard's contents - if successful,
* sets the current state of the editor to the serialized {@link JsonTree}.
*/
protected void pasteJson() {
// Get the clipboard contents.
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
Transferable t = clipboard.getContents(null);
// Attempt to convert them to a string.
String clipboardContents = null;
try {
if (t != null) {
clipboardContents = (String) t.getTransferData(DataFlavor.stringFlavor);
}
} catch (UnsupportedFlavorException | IOException e) {
logger.warn("Could not fetch clipboard contents.", e);
}
if (clipboardContents != null) {
try {
// Attempt to serialize them to a JsonTree and reset the editor state.
JsonElement json = new JsonParser().parse(clipboardContents);
JsonTree node = JsonTreeConverter.serialize(json);
resetState(node);
} catch (JsonSyntaxException | NullPointerException e) {
logger.warn("Could not construct a valid tree from clipboard contents.", e);
}
}
}
use of org.terasology.nui.widgets.treeView.JsonTree in project Terasology by MovingBlocks.
the class NUIEditorTextEntryBuilder method createObjectEditor.
/**
* @return A {@link UITextEntry} to be used to edit a JSON object node.
*/
public static UITextEntry<JsonTree> createObjectEditor() {
UITextEntry.Formatter<JsonTree> formatter = value -> value.getValue().getKey();
UITextEntry.Parser<JsonTree> parser = value -> new JsonTree(new JsonTreeValue(value, null, JsonTreeValue.Type.OBJECT));
return createEditorEntry(formatter, parser);
}
Aggregations