use of com.vaadin.flow.internal.StateTree in project flow by vaadin.
the class NodeListAddRemoveTest method clearNodeList_clearChanges_generateChangesFromEmpty_clearChangeIsCollected.
@Test
public void clearNodeList_clearChanges_generateChangesFromEmpty_clearChangeIsCollected() {
// removes all children
nodeList.clear();
StateTree tree = new StateTree(new UI().getInternals(), ElementChildrenList.class);
// attach the feature node to the tree
tree.getRootNode().getFeature(ElementChildrenList.class).add(nodeList.getNode());
List<NodeChange> changes = new ArrayList<>();
nodeList.getNode().collectChanges(changes::add);
Assert.assertEquals(2, changes.size());
Assert.assertEquals(NodeAttachChange.class, changes.get(0).getClass());
Assert.assertEquals(ListClearChange.class, changes.get(1).getClass());
}
use of com.vaadin.flow.internal.StateTree in project flow by vaadin.
the class NodeListAddRemoveTest method clear_modifyList_collectChanges_clearChangeIsCollected.
@Test
public void clear_modifyList_collectChanges_clearChangeIsCollected() {
nodeList.clear();
nodeList.add("foo");
StateTree tree = new StateTree(new UI().getInternals(), ElementChildrenList.class);
// attach the feature node to the tree
tree.getRootNode().getFeature(ElementChildrenList.class).add(nodeList.getNode());
List<NodeChange> changes = new ArrayList<>();
nodeList.getNode().collectChanges(changes::add);
Assert.assertEquals(3, changes.size());
Assert.assertEquals(NodeAttachChange.class, changes.get(0).getClass());
Assert.assertEquals(ListClearChange.class, changes.get(1).getClass());
Assert.assertEquals(ListAddChange.class, changes.get(2).getClass());
}
use of com.vaadin.flow.internal.StateTree in project flow by vaadin.
the class ElementUtilTest method setupElementHierarchy.
private void setupElementHierarchy() {
parent = ElementFactory.createDiv();
child = ElementFactory.createDiv();
grandchild = ElementFactory.createDiv();
parent.appendChild(child.appendChild(grandchild));
stateTree = new StateTree(new UI().getInternals(), ElementChildrenList.class, InertData.class);
final StateNode rootNode = stateTree.getRootNode();
rootNode.getFeature(ElementChildrenList.class).add(0, parent.getNode());
}
use of com.vaadin.flow.internal.StateTree in project flow by vaadin.
the class UidlWriter method encodeChanges.
/**
* Encodes the state tree changes of the given UI. The executions registered
* at
* {@link StateTree#beforeClientResponse(com.vaadin.flow.internal.StateNode, com.vaadin.flow.function.SerializableConsumer)}
* at evaluated before the changes are encoded.
*
* @param ui
* the UI
* @param stateChanges
* a JSON array to put state changes into
* @param templates
* a JSON object to put new template nodes into
* @see StateTree#runExecutionsBeforeClientResponse()
*/
private void encodeChanges(UI ui, JsonArray stateChanges, JsonObject templates) {
UIInternals uiInternals = ui.getInternals();
StateTree stateTree = uiInternals.getStateTree();
stateTree.runExecutionsBeforeClientResponse();
Consumer<TemplateNode> templateEncoder = new Consumer<TemplateNode>() {
@Override
public void accept(TemplateNode templateNode) {
// Send to client if it's a new template
if (!uiInternals.isTemplateSent(templateNode)) {
uiInternals.setTemplateSent(templateNode);
templates.put(Integer.toString(templateNode.getId()), templateNode.toJson(this));
}
}
};
Set<Class<? extends Component>> componentsWithDependencies = new LinkedHashSet<>();
stateTree.collectChanges(change -> {
// Ensure new templates are sent to the client
runIfNewTemplateChange(change, templateEncoder);
if (attachesComponent(change)) {
change.getNode().getFeature(ComponentMapping.class).getComponent().ifPresent(component -> addComponentHierarchy(ui, componentsWithDependencies, component));
}
// Encode the actual change
stateChanges.set(stateChanges.length(), change.toJson(uiInternals.getConstantPool()));
});
componentsWithDependencies.forEach(uiInternals::addComponentDependencies);
}
use of com.vaadin.flow.internal.StateTree in project flow by vaadin.
the class DomEvent method extractElement.
static Element extractElement(JsonObject eventData, Element source, String key, boolean lookUnderUI) {
assert key.startsWith(JsonConstants.MAP_STATE_NODE_EVENT_DATA);
if (!eventData.hasKey(key)) {
return null;
}
final JsonValue reportedStateNodeId = eventData.get(key);
if (reportedStateNodeId == null) {
return null;
}
int id = (int) reportedStateNodeId.asNumber();
if (id == -1) {
return null;
}
AtomicReference<Element> matchingNode = new AtomicReference<>();
final Consumer<StateNode> visitor = node -> {
if (node.getId() == id) {
matchingNode.set(Element.get(node));
}
};
// first look under event source
source.getNode().visitNodeTree(visitor);
if (lookUnderUI && matchingNode.get() == null) {
// widen search to look under UI too
final NodeOwner owner = source.getNode().getOwner();
if (owner instanceof StateTree) {
((StateTree) owner).getRootNode().visitNodeTree(visitor);
}
}
final Element mappedElementOrNull = matchingNode.get();
// prevent spoofing invisible elements by sending bad state node ids
if (mappedElementOrNull != null && !mappedElementOrNull.isVisible()) {
return null;
}
return mappedElementOrNull;
}
Aggregations