handle height
This commit is contained in:
1 parent
dcad2fe8a2
commit
f9059c3f30
5 files changed
+146
-86
No files matched your search
@@ -21,7 +21,6 @@ pub struct NodeData {
|
|||||||
pub node_type: NodeType,
|
pub node_type: NodeType,
|
||||||
/// The number of parents before the root node. The root node has height 1.
|
/// The number of parents before the root node. The root node has height 1.
|
||||||
pub height: u16,
|
pub height: u16,
|
||||||
height_dirty: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A type of node with data specific to the node type. The types are a subset of the [VNode] types.
|
/// A type of node with data specific to the node type. The types are a subset of the [VNode] types.
|
||||||
@@ -48,7 +47,6 @@ impl<S: State> Node<S> {
|
|||||||
node_type,
|
node_type,
|
||||||
height: 0,
|
height: 0,
|
||||||
node_id: NodeId(0),
|
node_id: NodeId(0),
|
||||||
height_dirty: true,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use anymap::AnyMap;
|
use anymap::AnyMap;
|
||||||
use dioxus_core::{ElementId, Mutations};
|
use dioxus_core::{ElementId, Mutations};
|
||||||
use rustc_hash::{FxHashMap, FxHashSet};
|
use rustc_hash::{FxHashMap, FxHashSet};
|
||||||
use std::ops::{Deref, DerefMut, Index, IndexMut};
|
use std::ops::{Index, IndexMut};
|
||||||
|
|
||||||
use crate::node::{Node, NodeData, NodeType, OwnedAttributeDiscription};
|
use crate::node::{Node, NodeData, NodeType, OwnedAttributeDiscription};
|
||||||
use crate::node_ref::{AttributeMask, NodeMask};
|
use crate::node_ref::{AttributeMask, NodeMask};
|
||||||
@@ -9,6 +9,18 @@ use crate::state::State;
|
|||||||
use crate::tree::{NodeId, Tree, TreeLike, TreeView};
|
use crate::tree::{NodeId, Tree, TreeLike, TreeView};
|
||||||
use crate::RealNodeId;
|
use crate::RealNodeId;
|
||||||
|
|
||||||
|
fn mark_dirty(
|
||||||
|
node_id: NodeId,
|
||||||
|
mask: NodeMask,
|
||||||
|
nodes_updated: &mut FxHashMap<RealNodeId, NodeMask>,
|
||||||
|
) {
|
||||||
|
if let Some(node) = nodes_updated.get_mut(&node_id) {
|
||||||
|
*node = node.union(&mask);
|
||||||
|
} else {
|
||||||
|
nodes_updated.insert(node_id, mask);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A Dom that can sync with the VirtualDom mutations intended for use in lazy renderers.
|
/// A Dom that can sync with the VirtualDom mutations intended for use in lazy renderers.
|
||||||
/// The render state passes from parent to children and or accumulates state from children to parents.
|
/// The render state passes from parent to children and or accumulates state from children to parents.
|
||||||
/// To get started implement [crate::state::ParentDepState], [crate::state::NodeDepState], or [crate::state::ChildDepState] and call [RealDom::apply_mutations] to update the dom and [RealDom::update_state] to update the state of the nodes.
|
/// To get started implement [crate::state::ParentDepState], [crate::state::NodeDepState], or [crate::state::ChildDepState] and call [RealDom::apply_mutations] to update the dom and [RealDom::update_state] to update the state of the nodes.
|
||||||
@@ -79,12 +91,31 @@ impl<S: State> RealDom<S> {
|
|||||||
node_id
|
node_id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn add_child(&mut self, node_id: RealNodeId, child_id: RealNodeId) {
|
||||||
|
self.tree.add_child(node_id, child_id);
|
||||||
|
self.resolve_height(child_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn resolve_height(&mut self, node_id: RealNodeId) {
|
||||||
|
if let Some((node, parent)) = self.tree.node_parent_mut(node_id) {
|
||||||
|
let height = parent.node_data.height;
|
||||||
|
node.node_data.height = height + 1;
|
||||||
|
unsafe {
|
||||||
|
let self_mut = self as *mut Self;
|
||||||
|
// Safety: No node will have itself as a child
|
||||||
|
for child in self.tree.children_ids(node_id).unwrap() {
|
||||||
|
(*self_mut).resolve_height(*child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Updates the dom with some mutations and return a set of nodes that were updated. Pass the dirty nodes to update_state.
|
/// Updates the dom with some mutations and return a set of nodes that were updated. Pass the dirty nodes to update_state.
|
||||||
pub fn apply_mutations<'a>(
|
pub fn apply_mutations(
|
||||||
&mut self,
|
&mut self,
|
||||||
mutations_vec: Vec<Mutations<'a>>,
|
mutations_vec: Vec<Mutations>,
|
||||||
) -> Vec<(RealNodeId, NodeMask)> {
|
) -> FxHashMap<RealNodeId, NodeMask> {
|
||||||
let mut nodes_updated: Vec<(RealNodeId, NodeMask)> = Vec::new();
|
let mut nodes_updated: FxHashMap<RealNodeId, NodeMask> = FxHashMap::default();
|
||||||
for mutations in mutations_vec {
|
for mutations in mutations_vec {
|
||||||
for e in mutations.edits {
|
for e in mutations.edits {
|
||||||
use dioxus_core::Mutation::*;
|
use dioxus_core::Mutation::*;
|
||||||
@@ -93,12 +124,12 @@ impl<S: State> RealDom<S> {
|
|||||||
let data = self.stack.split_off(m);
|
let data = self.stack.split_off(m);
|
||||||
let (parent, children) = data.split_first().unwrap();
|
let (parent, children) = data.split_first().unwrap();
|
||||||
for child in children {
|
for child in children {
|
||||||
self.tree.add_child(*parent, *child);
|
self.add_child(*parent, *child);
|
||||||
nodes_updated.push((*parent, NodeMask::ALL));
|
mark_dirty(*parent, NodeMask::ALL, &mut nodes_updated);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AssignId { path, id } => {
|
AssignId { path, id } => {
|
||||||
self.set_element_id(self.load_child(&path), id);
|
self.set_element_id(self.load_child(path), id);
|
||||||
}
|
}
|
||||||
CreateElement { name } => {
|
CreateElement { name } => {
|
||||||
let node = Node::new(NodeType::Element {
|
let node = Node::new(NodeType::Element {
|
||||||
@@ -109,7 +140,7 @@ impl<S: State> RealDom<S> {
|
|||||||
});
|
});
|
||||||
let id = self.create_node(node);
|
let id = self.create_node(node);
|
||||||
self.stack.push(id);
|
self.stack.push(id);
|
||||||
nodes_updated.push((id, NodeMask::ALL));
|
mark_dirty(id, NodeMask::ALL, &mut nodes_updated);
|
||||||
}
|
}
|
||||||
CreateElementNamespace { name, namespace } => {
|
CreateElementNamespace { name, namespace } => {
|
||||||
let node = Node::new(NodeType::Element {
|
let node = Node::new(NodeType::Element {
|
||||||
@@ -120,20 +151,20 @@ impl<S: State> RealDom<S> {
|
|||||||
});
|
});
|
||||||
let id = self.create_node(node);
|
let id = self.create_node(node);
|
||||||
self.stack.push(id);
|
self.stack.push(id);
|
||||||
nodes_updated.push((id, NodeMask::ALL));
|
mark_dirty(id, NodeMask::ALL, &mut nodes_updated);
|
||||||
}
|
}
|
||||||
CreatePlaceholder { id } => {
|
CreatePlaceholder { id } => {
|
||||||
let node = Node::new(NodeType::Placeholder);
|
let node = Node::new(NodeType::Placeholder);
|
||||||
let node_id = self.create_node(node);
|
let node_id = self.create_node(node);
|
||||||
self.set_element_id(node_id, id);
|
self.set_element_id(node_id, id);
|
||||||
self.stack.push(node_id);
|
self.stack.push(node_id);
|
||||||
nodes_updated.push((node_id, NodeMask::ALL));
|
mark_dirty(node_id, NodeMask::ALL, &mut nodes_updated);
|
||||||
}
|
}
|
||||||
CreateStaticPlaceholder => {
|
CreateStaticPlaceholder => {
|
||||||
let node = Node::new(NodeType::Placeholder);
|
let node = Node::new(NodeType::Placeholder);
|
||||||
let id = self.create_node(node);
|
let id = self.create_node(node);
|
||||||
self.stack.push(id);
|
self.stack.push(id);
|
||||||
nodes_updated.push((id, NodeMask::ALL));
|
mark_dirty(id, NodeMask::ALL, &mut nodes_updated);
|
||||||
}
|
}
|
||||||
CreateStaticText { value } => {
|
CreateStaticText { value } => {
|
||||||
let node = Node::new(NodeType::Text {
|
let node = Node::new(NodeType::Text {
|
||||||
@@ -141,7 +172,7 @@ impl<S: State> RealDom<S> {
|
|||||||
});
|
});
|
||||||
let id = self.create_node(node);
|
let id = self.create_node(node);
|
||||||
self.stack.push(id);
|
self.stack.push(id);
|
||||||
nodes_updated.push((id, NodeMask::new().with_text()));
|
mark_dirty(id, NodeMask::new().with_text(), &mut nodes_updated);
|
||||||
}
|
}
|
||||||
CreateTextNode { value, id } => {
|
CreateTextNode { value, id } => {
|
||||||
let node = Node::new(NodeType::Text {
|
let node = Node::new(NodeType::Text {
|
||||||
@@ -151,7 +182,7 @@ impl<S: State> RealDom<S> {
|
|||||||
let node = self.tree.get_mut(node_id).unwrap();
|
let node = self.tree.get_mut(node_id).unwrap();
|
||||||
node.node_data.element_id = Some(id);
|
node.node_data.element_id = Some(id);
|
||||||
self.stack.push(node_id);
|
self.stack.push(node_id);
|
||||||
nodes_updated.push((node_id, NodeMask::new().with_text()));
|
mark_dirty(node_id, NodeMask::new().with_text(), &mut nodes_updated);
|
||||||
}
|
}
|
||||||
HydrateText { path, value, id } => {
|
HydrateText { path, value, id } => {
|
||||||
let node_id = self.load_child(path);
|
let node_id = self.load_child(path);
|
||||||
@@ -160,7 +191,7 @@ impl<S: State> RealDom<S> {
|
|||||||
if let NodeType::Text { text } = &mut node.node_data.node_type {
|
if let NodeType::Text { text } = &mut node.node_data.node_type {
|
||||||
*text = value.to_string();
|
*text = value.to_string();
|
||||||
}
|
}
|
||||||
nodes_updated.push((node_id, NodeMask::new().with_text()));
|
mark_dirty(node_id, NodeMask::new().with_text(), &mut nodes_updated);
|
||||||
}
|
}
|
||||||
LoadTemplate { name, index, id } => {
|
LoadTemplate { name, index, id } => {
|
||||||
let template_id = self.templates[name][index];
|
let template_id = self.templates[name][index];
|
||||||
@@ -172,7 +203,7 @@ impl<S: State> RealDom<S> {
|
|||||||
let old_node_id = self.element_to_node_id(id);
|
let old_node_id = self.element_to_node_id(id);
|
||||||
for new in new_nodes {
|
for new in new_nodes {
|
||||||
self.tree.insert_after(old_node_id, new);
|
self.tree.insert_after(old_node_id, new);
|
||||||
nodes_updated.push((new, NodeMask::ALL));
|
mark_dirty(new, NodeMask::ALL, &mut nodes_updated);
|
||||||
}
|
}
|
||||||
self.tree.remove(old_node_id);
|
self.tree.remove(old_node_id);
|
||||||
}
|
}
|
||||||
@@ -181,7 +212,7 @@ impl<S: State> RealDom<S> {
|
|||||||
let old_node_id = self.load_child(path);
|
let old_node_id = self.load_child(path);
|
||||||
for new in new_nodes {
|
for new in new_nodes {
|
||||||
self.tree.insert_after(old_node_id, new);
|
self.tree.insert_after(old_node_id, new);
|
||||||
nodes_updated.push((new, NodeMask::ALL));
|
mark_dirty(new, NodeMask::ALL, &mut nodes_updated);
|
||||||
}
|
}
|
||||||
self.tree.remove(old_node_id);
|
self.tree.remove(old_node_id);
|
||||||
}
|
}
|
||||||
@@ -190,7 +221,7 @@ impl<S: State> RealDom<S> {
|
|||||||
let old_node_id = self.element_to_node_id(id);
|
let old_node_id = self.element_to_node_id(id);
|
||||||
for new in new_nodes {
|
for new in new_nodes {
|
||||||
self.tree.insert_after(old_node_id, new);
|
self.tree.insert_after(old_node_id, new);
|
||||||
nodes_updated.push((new, NodeMask::ALL));
|
mark_dirty(new, NodeMask::ALL, &mut nodes_updated);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
InsertBefore { id, m } => {
|
InsertBefore { id, m } => {
|
||||||
@@ -198,7 +229,7 @@ impl<S: State> RealDom<S> {
|
|||||||
let old_node_id = self.element_to_node_id(id);
|
let old_node_id = self.element_to_node_id(id);
|
||||||
for new in new_nodes {
|
for new in new_nodes {
|
||||||
self.tree.insert_before(old_node_id, new);
|
self.tree.insert_before(old_node_id, new);
|
||||||
nodes_updated.push((new, NodeMask::ALL));
|
mark_dirty(new, NodeMask::ALL, &mut nodes_updated);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SaveTemplate { name, m } => {
|
SaveTemplate { name, m } => {
|
||||||
@@ -223,10 +254,11 @@ impl<S: State> RealDom<S> {
|
|||||||
},
|
},
|
||||||
crate::node::OwnedAttributeValue::Text(value.to_string()),
|
crate::node::OwnedAttributeValue::Text(value.to_string()),
|
||||||
);
|
);
|
||||||
nodes_updated.push((
|
mark_dirty(
|
||||||
node_id,
|
node_id,
|
||||||
NodeMask::new_with_attrs(AttributeMask::single(name)),
|
NodeMask::new_with_attrs(AttributeMask::single(name)),
|
||||||
));
|
&mut nodes_updated,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SetStaticAttribute { name, value, ns } => {
|
SetStaticAttribute { name, value, ns } => {
|
||||||
@@ -242,10 +274,11 @@ impl<S: State> RealDom<S> {
|
|||||||
},
|
},
|
||||||
crate::node::OwnedAttributeValue::Text(value.to_string()),
|
crate::node::OwnedAttributeValue::Text(value.to_string()),
|
||||||
);
|
);
|
||||||
nodes_updated.push((
|
mark_dirty(
|
||||||
*node_id,
|
*node_id,
|
||||||
NodeMask::new_with_attrs(AttributeMask::single(name)),
|
NodeMask::new_with_attrs(AttributeMask::single(name)),
|
||||||
));
|
&mut nodes_updated,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SetBoolAttribute { name, value, id } => {
|
SetBoolAttribute { name, value, id } => {
|
||||||
@@ -261,10 +294,11 @@ impl<S: State> RealDom<S> {
|
|||||||
},
|
},
|
||||||
crate::node::OwnedAttributeValue::Bool(value),
|
crate::node::OwnedAttributeValue::Bool(value),
|
||||||
);
|
);
|
||||||
nodes_updated.push((
|
mark_dirty(
|
||||||
node_id,
|
node_id,
|
||||||
NodeMask::new_with_attrs(AttributeMask::single(name)),
|
NodeMask::new_with_attrs(AttributeMask::single(name)),
|
||||||
));
|
&mut nodes_updated,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SetInnerText { value } => {
|
SetInnerText { value } => {
|
||||||
@@ -276,7 +310,7 @@ impl<S: State> RealDom<S> {
|
|||||||
text: value.to_string(),
|
text: value.to_string(),
|
||||||
});
|
});
|
||||||
let text_node_id = self.create_node(text_node);
|
let text_node_id = self.create_node(text_node);
|
||||||
self.tree.add_child(node_id, text_node_id);
|
self.add_child(node_id, text_node_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SetText { value, id } => {
|
SetText { value, id } => {
|
||||||
@@ -285,7 +319,7 @@ impl<S: State> RealDom<S> {
|
|||||||
if let NodeType::Text { text } = &mut node.node_data.node_type {
|
if let NodeType::Text { text } = &mut node.node_data.node_type {
|
||||||
*text = value.to_string();
|
*text = value.to_string();
|
||||||
}
|
}
|
||||||
nodes_updated.push((node_id, NodeMask::new().with_text()));
|
mark_dirty(node_id, NodeMask::new().with_text(), &mut nodes_updated);
|
||||||
}
|
}
|
||||||
NewEventListener {
|
NewEventListener {
|
||||||
event_name,
|
event_name,
|
||||||
@@ -321,14 +355,14 @@ impl<S: State> RealDom<S> {
|
|||||||
}
|
}
|
||||||
Remove { id } => {
|
Remove { id } => {
|
||||||
let node_id = self.element_to_node_id(id);
|
let node_id = self.element_to_node_id(id);
|
||||||
self.remove(node_id);
|
self.tree.remove(node_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove any nodes that were created and then removed in the same mutations from the dirty nodes list
|
// remove any nodes that were created and then removed in the same mutations from the dirty nodes list
|
||||||
nodes_updated.retain(|n| self.tree.get(n.0).is_some());
|
nodes_updated.retain(|k, _| self.tree.get(*k).is_some());
|
||||||
|
|
||||||
nodes_updated
|
nodes_updated
|
||||||
}
|
}
|
||||||
@@ -336,7 +370,7 @@ impl<S: State> RealDom<S> {
|
|||||||
/// Update the state of the dom, after appling some mutations. This will keep the nodes in the dom up to date with their VNode counterparts.
|
/// Update the state of the dom, after appling some mutations. This will keep the nodes in the dom up to date with their VNode counterparts.
|
||||||
pub fn update_state(
|
pub fn update_state(
|
||||||
&mut self,
|
&mut self,
|
||||||
nodes_updated: Vec<(RealNodeId, NodeMask)>,
|
nodes_updated: FxHashMap<RealNodeId, NodeMask>,
|
||||||
ctx: AnyMap,
|
ctx: AnyMap,
|
||||||
) -> FxHashSet<RealNodeId> {
|
) -> FxHashSet<RealNodeId> {
|
||||||
let (mut state_tree, node_tree) = self.split();
|
let (mut state_tree, node_tree) = self.split();
|
||||||
@@ -370,8 +404,12 @@ impl<S: State> RealDom<S> {
|
|||||||
let raw = self as *mut Self;
|
let raw = self as *mut Self;
|
||||||
// this is safe beacuse the treeview trait does not allow mutation of the position of elements, and within elements the access is disjoint.
|
// this is safe beacuse the treeview trait does not allow mutation of the position of elements, and within elements the access is disjoint.
|
||||||
(
|
(
|
||||||
unsafe { &mut *raw }.map(|n| &n.state, |n| &mut n.state),
|
unsafe { &mut *raw }
|
||||||
unsafe { &mut *raw }.map(|n| &n.node_data, |n| &mut n.node_data),
|
.tree
|
||||||
|
.map(|n| &n.state, |n| &mut n.state),
|
||||||
|
unsafe { &mut *raw }
|
||||||
|
.tree
|
||||||
|
.map(|n| &n.node_data, |n| &mut n.node_data),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -385,7 +423,7 @@ impl<S: State> RealDom<S> {
|
|||||||
// this is safe because no node has itself as a child
|
// this is safe because no node has itself as a child
|
||||||
let self_mut = &mut *self_ptr;
|
let self_mut = &mut *self_ptr;
|
||||||
let child_id = self_mut.clone_node(*child);
|
let child_id = self_mut.clone_node(*child);
|
||||||
self_mut.tree.add_child(new_id, child_id);
|
self_mut.add_child(new_id, child_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
new_id
|
new_id
|
||||||
@@ -419,17 +457,3 @@ impl<S: State> IndexMut<RealNodeId> for RealDom<S> {
|
|||||||
self.tree.get_mut(idx).unwrap()
|
self.tree.get_mut(idx).unwrap()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S: State> Deref for RealDom<S> {
|
|
||||||
type Target = Tree<Node<S>>;
|
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
|
||||||
&self.tree
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<S: State> DerefMut for RealDom<S> {
|
|
||||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
|
||||||
&mut self.tree
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -5,7 +5,7 @@ use crate::node_ref::{NodeMask, NodeView};
|
|||||||
use crate::tree::TreeView;
|
use crate::tree::TreeView;
|
||||||
use crate::RealNodeId;
|
use crate::RealNodeId;
|
||||||
use anymap::AnyMap;
|
use anymap::AnyMap;
|
||||||
use rustc_hash::FxHashSet;
|
use rustc_hash::{FxHashMap, FxHashSet};
|
||||||
|
|
||||||
/// Join two sorted iterators
|
/// Join two sorted iterators
|
||||||
pub(crate) fn union_ordered_iter<'a>(
|
pub(crate) fn union_ordered_iter<'a>(
|
||||||
@@ -81,15 +81,15 @@ pub trait ChildDepState {
|
|||||||
/// The context is passed to the [ChildDepState::reduce] when it is resolved.
|
/// The context is passed to the [ChildDepState::reduce] when it is resolved.
|
||||||
type Ctx;
|
type Ctx;
|
||||||
/// A state from each child node that this node depends on. Typically this is Self, but it could be any state that is within the state tree.
|
/// A state from each child node that this node depends on. Typically this is Self, but it could be any state that is within the state tree.
|
||||||
/// This must be either a [ChildDepState], or [NodeDepState].
|
/// Depstate must be a tuple containing any number of borrowed elements that are either [ChildDepState] or [NodeDepState].
|
||||||
type DepState;
|
type DepState: ElementBorrowable;
|
||||||
/// The part of a node that this state cares about. This is used to determine if the state should be updated when a node is updated.
|
/// The part of a node that this state cares about. This is used to determine if the state should be updated when a node is updated.
|
||||||
const NODE_MASK: NodeMask = NodeMask::NONE;
|
const NODE_MASK: NodeMask = NodeMask::NONE;
|
||||||
/// Resolve the state current node's state from the state of the children, the state of the node, and some external context.
|
/// Resolve the state current node's state from the state of the children, the state of the node, and some external context.
|
||||||
fn reduce<'a>(
|
fn reduce<'a>(
|
||||||
&mut self,
|
&mut self,
|
||||||
node: NodeView,
|
node: NodeView,
|
||||||
children: impl Iterator<Item = &'a Self::DepState>,
|
children: impl Iterator<Item = <Self::DepState as ElementBorrowable>::ElementBorrowed<'a>>,
|
||||||
ctx: &Self::Ctx,
|
ctx: &Self::Ctx,
|
||||||
) -> bool
|
) -> bool
|
||||||
where
|
where
|
||||||
@@ -143,15 +143,15 @@ pub trait ParentDepState {
|
|||||||
/// The context is passed to the [ParentDepState::reduce] when it is resolved.
|
/// The context is passed to the [ParentDepState::reduce] when it is resolved.
|
||||||
type Ctx;
|
type Ctx;
|
||||||
/// A state from from the parent node that this node depends on. Typically this is Self, but it could be any state that is within the state tree.
|
/// A state from from the parent node that this node depends on. Typically this is Self, but it could be any state that is within the state tree.
|
||||||
/// This must be either a [ParentDepState] or [NodeDepState]
|
/// Depstate must be a tuple containing any number of borrowed elements that are either [ParentDepState] or [NodeDepState].
|
||||||
type DepState;
|
type DepState: ElementBorrowable;
|
||||||
/// The part of a node that this state cares about. This is used to determine if the state should be updated when a node is updated.
|
/// The part of a node that this state cares about. This is used to determine if the state should be updated when a node is updated.
|
||||||
const NODE_MASK: NodeMask = NodeMask::NONE;
|
const NODE_MASK: NodeMask = NodeMask::NONE;
|
||||||
/// Resolve the state current node's state from the state of the parent node, the state of the node, and some external context.
|
/// Resolve the state current node's state from the state of the parent node, the state of the node, and some external context.
|
||||||
fn reduce<'a>(
|
fn reduce<'a>(
|
||||||
&mut self,
|
&mut self,
|
||||||
node: NodeView,
|
node: NodeView,
|
||||||
parent: Option<&'a Self::DepState>,
|
parent: Option<<Self::DepState as ElementBorrowable>::ElementBorrowed<'a>>,
|
||||||
ctx: &Self::Ctx,
|
ctx: &Self::Ctx,
|
||||||
) -> bool;
|
) -> bool;
|
||||||
}
|
}
|
||||||
@@ -193,23 +193,27 @@ pub trait ParentDepState {
|
|||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
/// The generic argument (Depstate) must be a tuple containing any number of borrowed elements that are either a [ChildDepState], [ParentDepState] or [NodeDepState].
|
pub trait NodeDepState {
|
||||||
// Todo: once GATs land we can model multable dependencies better
|
/// Depstate must be a tuple containing any number of borrowed elements that are either [ChildDepState], [ParentDepState] or [NodeDepState].
|
||||||
|
type DepState: ElementBorrowable;
|
||||||
pub trait NodeDepState<DepState = ()> {
|
|
||||||
/// The state passed to [NodeDepState::reduce] when it is resolved.
|
/// The state passed to [NodeDepState::reduce] when it is resolved.
|
||||||
type Ctx;
|
type Ctx;
|
||||||
/// The part of a node that this state cares about. This is used to determine if the state should be updated when a node is updated.
|
/// The part of a node that this state cares about. This is used to determine if the state should be updated when a node is updated.
|
||||||
const NODE_MASK: NodeMask = NodeMask::NONE;
|
const NODE_MASK: NodeMask = NodeMask::NONE;
|
||||||
/// Resolve the state current node's state from the state of the sibling states, the state of the node, and some external context.
|
/// Resolve the state current node's state from the state of the sibling states, the state of the node, and some external context.
|
||||||
fn reduce(&mut self, node: NodeView, siblings: DepState, ctx: &Self::Ctx) -> bool;
|
fn reduce<'a>(
|
||||||
|
&mut self,
|
||||||
|
node: NodeView,
|
||||||
|
siblings: <Self::DepState as ElementBorrowable>::ElementBorrowed<'a>,
|
||||||
|
ctx: &Self::Ctx,
|
||||||
|
) -> bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Do not implement this trait. It is only meant to be derived and used through [crate::real_dom::RealDom].
|
/// Do not implement this trait. It is only meant to be derived and used through [crate::real_dom::RealDom].
|
||||||
pub trait State: Default + Clone {
|
pub trait State: Default + Clone {
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
fn update<'a, T: TreeView<Self>, T2: TreeView<NodeData>>(
|
fn update<'a, T: TreeView<Self>, T2: TreeView<NodeData>>(
|
||||||
dirty: &[(RealNodeId, NodeMask)],
|
dirty: &FxHashMap<RealNodeId, NodeMask>,
|
||||||
state_tree: &'a mut T,
|
state_tree: &'a mut T,
|
||||||
rdom: &'a T2,
|
rdom: &'a T2,
|
||||||
ctx: &AnyMap,
|
ctx: &AnyMap,
|
||||||
@@ -219,12 +223,7 @@ pub trait State: Default + Clone {
|
|||||||
impl ChildDepState for () {
|
impl ChildDepState for () {
|
||||||
type Ctx = ();
|
type Ctx = ();
|
||||||
type DepState = ();
|
type DepState = ();
|
||||||
fn reduce<'a>(
|
fn reduce<'a>(&mut self, _: NodeView, _: impl Iterator<Item = ()>, _: &Self::Ctx) -> bool
|
||||||
&mut self,
|
|
||||||
_: NodeView,
|
|
||||||
_: impl Iterator<Item = &'a Self::DepState>,
|
|
||||||
_: &Self::Ctx,
|
|
||||||
) -> bool
|
|
||||||
where
|
where
|
||||||
Self::DepState: 'a,
|
Self::DepState: 'a,
|
||||||
{
|
{
|
||||||
@@ -235,14 +234,55 @@ impl ChildDepState for () {
|
|||||||
impl ParentDepState for () {
|
impl ParentDepState for () {
|
||||||
type Ctx = ();
|
type Ctx = ();
|
||||||
type DepState = ();
|
type DepState = ();
|
||||||
fn reduce<'a>(&mut self, _: NodeView, _: Option<&'a Self::DepState>, _: &Self::Ctx) -> bool {
|
fn reduce<'a>(&mut self, _: NodeView, _: Option<()>, _: &Self::Ctx) -> bool {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NodeDepState<()> for () {
|
impl NodeDepState for () {
|
||||||
|
type DepState = ();
|
||||||
type Ctx = ();
|
type Ctx = ();
|
||||||
fn reduce(&mut self, _: NodeView, _sibling: (), _: &Self::Ctx) -> bool {
|
fn reduce(&mut self, _: NodeView, _sibling: (), _: &Self::Ctx) -> bool {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait ElementBorrowable {
|
||||||
|
type ElementBorrowed<'a>
|
||||||
|
where
|
||||||
|
Self: 'a;
|
||||||
|
|
||||||
|
fn borrow_elements(&self) -> Self::ElementBorrowed<'_>;
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! impl_element_borrowable {
|
||||||
|
($($t:ident),*) => {
|
||||||
|
impl< $($t),* > ElementBorrowable for ($($t,)*) {
|
||||||
|
type ElementBorrowed<'a> = ($(&'a $t,)*) where Self: 'a;
|
||||||
|
|
||||||
|
#[allow(clippy::unused_unit, non_snake_case)]
|
||||||
|
fn borrow_elements<'a>(&'a self) -> Self::ElementBorrowed<'a> {
|
||||||
|
let ($($t,)*) = self;
|
||||||
|
($(&$t,)*)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_element_borrowable!();
|
||||||
|
impl_element_borrowable!(A);
|
||||||
|
impl_element_borrowable!(A, B);
|
||||||
|
impl_element_borrowable!(A, B, C);
|
||||||
|
impl_element_borrowable!(A, B, C, D);
|
||||||
|
impl_element_borrowable!(A, B, C, D, E);
|
||||||
|
impl_element_borrowable!(A, B, C, D, E, F);
|
||||||
|
impl_element_borrowable!(A, B, C, D, E, F, G);
|
||||||
|
impl_element_borrowable!(A, B, C, D, E, F, G, H);
|
||||||
|
impl_element_borrowable!(A, B, C, D, E, F, G, H, I);
|
||||||
|
impl_element_borrowable!(A, B, C, D, E, F, G, H, I, J);
|
||||||
|
impl_element_borrowable!(A, B, C, D, E, F, G, H, I, J, K);
|
||||||
|
impl_element_borrowable!(A, B, C, D, E, F, G, H, I, J, K, L);
|
||||||
|
impl_element_borrowable!(A, B, C, D, E, F, G, H, I, J, K, L, M);
|
||||||
|
impl_element_borrowable!(A, B, C, D, E, F, G, H, I, J, K, L, M, N);
|
||||||
|
impl_element_borrowable!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O);
|
||||||
|
impl_element_borrowable!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P);
|
||||||
@@ -72,14 +72,11 @@ pub trait TreeView<T>: Sized {
|
|||||||
unsafe { self.get_mut(id).unwrap_unchecked() }
|
unsafe { self.get_mut(id).unwrap_unchecked() }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn children<'a>(&'a self, id: NodeId) -> Option<Self::Iterator<'a>>;
|
fn children(&self, id: NodeId) -> Option<Self::Iterator<'_>>;
|
||||||
|
|
||||||
fn children_mut<'a>(&'a mut self, id: NodeId) -> Option<Self::IteratorMut<'a>>;
|
fn children_mut(&mut self, id: NodeId) -> Option<Self::IteratorMut<'_>>;
|
||||||
|
|
||||||
fn parent_child_mut<'a>(
|
fn parent_child_mut(&mut self, id: NodeId) -> Option<(&mut T, Self::IteratorMut<'_>)> {
|
||||||
&'a mut self,
|
|
||||||
id: NodeId,
|
|
||||||
) -> Option<(&'a mut T, Self::IteratorMut<'a>)> {
|
|
||||||
let mut_ptr: *mut Self = self;
|
let mut_ptr: *mut Self = self;
|
||||||
unsafe {
|
unsafe {
|
||||||
// Safety: No node has itself as a child.
|
// Safety: No node has itself as a child.
|
||||||
@@ -91,7 +88,7 @@ pub trait TreeView<T>: Sized {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn children_ids<'a>(&'a self, id: NodeId) -> Option<&'a [NodeId]>;
|
fn children_ids(&self, id: NodeId) -> Option<&[NodeId]>;
|
||||||
|
|
||||||
fn parent(&self, id: NodeId) -> Option<&T>;
|
fn parent(&self, id: NodeId) -> Option<&T>;
|
||||||
|
|
||||||
@@ -257,7 +254,7 @@ impl<T> TreeView<T> for Tree<T> {
|
|||||||
self.nodes.get_mut(id.0).map(|node| &mut node.value)
|
self.nodes.get_mut(id.0).map(|node| &mut node.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn children<'a>(&'a self, id: NodeId) -> Option<Self::Iterator<'a>> {
|
fn children(&self, id: NodeId) -> Option<Self::Iterator<'_>> {
|
||||||
self.children_ids(id).map(|children_ids| ChildNodeIterator {
|
self.children_ids(id).map(|children_ids| ChildNodeIterator {
|
||||||
tree: self,
|
tree: self,
|
||||||
children_ids,
|
children_ids,
|
||||||
@@ -266,7 +263,7 @@ impl<T> TreeView<T> for Tree<T> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn children_mut<'a>(&'a mut self, id: NodeId) -> Option<Self::IteratorMut<'a>> {
|
fn children_mut(&mut self, id: NodeId) -> Option<Self::IteratorMut<'_>> {
|
||||||
let raw_ptr = self as *mut Self;
|
let raw_ptr = self as *mut Self;
|
||||||
unsafe {
|
unsafe {
|
||||||
// Safety: No node will appear as a child twice
|
// Safety: No node will appear as a child twice
|
||||||
@@ -280,7 +277,7 @@ impl<T> TreeView<T> for Tree<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn children_ids<'a>(&'a self, id: NodeId) -> Option<&'a [NodeId]> {
|
fn children_ids(&self, id: NodeId) -> Option<&[NodeId]> {
|
||||||
self.nodes.get(id.0).map(|node| node.children.as_slice())
|
self.nodes.get(id.0).map(|node| node.children.as_slice())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -462,7 +459,7 @@ where
|
|||||||
self.tree.get_mut(id).map(|node| (self.map_mut)(node))
|
self.tree.get_mut(id).map(|node| (self.map_mut)(node))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn children<'b>(&'b self, id: NodeId) -> Option<Self::Iterator<'b>> {
|
fn children(&self, id: NodeId) -> Option<Self::Iterator<'_>> {
|
||||||
self.children_ids(id).map(|children_ids| ChildNodeIterator {
|
self.children_ids(id).map(|children_ids| ChildNodeIterator {
|
||||||
tree: self,
|
tree: self,
|
||||||
children_ids,
|
children_ids,
|
||||||
@@ -471,7 +468,7 @@ where
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn children_mut<'b>(&'b mut self, id: NodeId) -> Option<Self::IteratorMut<'b>> {
|
fn children_mut(&mut self, id: NodeId) -> Option<Self::IteratorMut<'_>> {
|
||||||
let raw_ptr = self as *mut Self;
|
let raw_ptr = self as *mut Self;
|
||||||
unsafe {
|
unsafe {
|
||||||
// Safety: No node can be a child twice.
|
// Safety: No node can be a child twice.
|
||||||
@@ -485,7 +482,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn children_ids<'b>(&'b self, id: NodeId) -> Option<&'b [NodeId]> {
|
fn children_ids(&self, id: NodeId) -> Option<&[NodeId]> {
|
||||||
self.tree.children_ids(id)
|
self.tree.children_ids(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -609,15 +606,15 @@ impl<'a, T, Tr: TreeView<T>> TreeView<T> for SharedView<'a, T, Tr> {
|
|||||||
self.with_node(id, |t| t.get_mut(id))
|
self.with_node(id, |t| t.get_mut(id))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn children<'b>(&'b self, id: NodeId) -> Option<Self::Iterator<'b>> {
|
fn children(&self, id: NodeId) -> Option<Self::Iterator<'_>> {
|
||||||
self.with_node(id, |t| t.children(id))
|
self.with_node(id, |t| t.children(id))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn children_mut<'b>(&'b mut self, id: NodeId) -> Option<Self::IteratorMut<'b>> {
|
fn children_mut(&mut self, id: NodeId) -> Option<Self::IteratorMut<'_>> {
|
||||||
self.with_node(id, |t| t.children_mut(id))
|
self.with_node(id, |t| t.children_mut(id))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn children_ids<'b>(&'b self, id: NodeId) -> Option<&'b [NodeId]> {
|
fn children_ids(&self, id: NodeId) -> Option<&[NodeId]> {
|
||||||
self.with_node(id, |t| t.children_ids(id))
|
self.with_node(id, |t| t.children_ids(id))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
|
||||||
Reference in new issue
Block a user