update TUI renderer to new approach

This commit is contained in:
Evan Almloff committed 2023-01-28 14:51:05 -06:00
1 parent ce59ccfd44
commit 9efff74c0c
14 files changed
+339 -270

No files matched your search

+1
View File
@@ -4,6 +4,7 @@ use std::hash::BuildHasherDefault;
pub use node_ref::NodeMask;
pub use passes::AnyMapLike;
pub use passes::{Dependancy, Pass, TypeErasedPass};
pub use real_dom::{NodeMut, NodeRef, RealDom};
use rustc_hash::FxHasher;
pub use tree::NodeId;
+9 -7
View File
@@ -262,15 +262,16 @@ impl NodeMaskBuilder {
/// A node mask with no parts visible.
pub const NONE: Self = Self::new();
/// A node mask with every part visible.
pub const ALL: Self = Self::new_with_attrs(AttributeMaskBuilder::All)
pub const ALL: Self = Self::new()
.with_attrs(AttributeMaskBuilder::All)
.with_text()
.with_element()
.with_listeners();
/// Create a new node mask with the given attributes
pub const fn new_with_attrs(attritutes: AttributeMaskBuilder) -> Self {
/// Create a empty node mask
pub const fn new() -> Self {
Self {
attritutes,
attritutes: AttributeMaskBuilder::Some(&[]),
tag: false,
namespace: false,
text: false,
@@ -278,9 +279,10 @@ impl NodeMaskBuilder {
}
}
/// Create a empty node mask
pub const fn new() -> Self {
Self::new_with_attrs(AttributeMaskBuilder::Some(&[]))
/// Allow the mask to view the given attributes
pub const fn with_attrs(mut self, attritutes: AttributeMaskBuilder) -> Self {
self.attritutes = attritutes;
self
}
/// Allow the mask to view the tag
+132 -63
View File
@@ -18,7 +18,7 @@ use crate::{FxDashSet, SendAnyMap};
///
/// # Custom values
/// To allow custom values to be passed into attributes implement FromAnyValue on a type that can represent your custom value and specify the V generic to be that type. If you have many different custom values, it can be useful to use a enum type to represent the varients.
pub struct RealDom<V: FromAnyValue + Send = ()> {
pub struct RealDom<V: FromAnyValue + Send + Sync = ()> {
pub(crate) tree: Tree,
/// a map from element id to real node id
node_id_mapping: Vec<Option<NodeId>>,
@@ -38,7 +38,7 @@ impl<V: FromAnyValue + Send + Sync> RealDom<V> {
pub fn new(mut passes: Box<[TypeErasedPass<V>]>) -> RealDom<V> {
let mut tree = Tree::new();
let root_id = tree.root();
let root: &mut NodeData<V> = tree.write(root_id).unwrap();
let root: &mut NodeData<V> = tree.get_mut(root_id).unwrap();
let mut root_node: NodeData<V> = NodeData::new(NodeType::Element(ElementNode {
tag: "Root".to_string(),
namespace: Some("Root".to_string()),
@@ -95,7 +95,7 @@ impl<V: FromAnyValue + Send + Sync> RealDom<V> {
}
fn set_element_id(&mut self, node_id: NodeId, element_id: ElementId) {
let mut node = self.tree.write::<NodeData>(node_id).unwrap();
let mut node = self.tree.get_mut::<NodeData>(node_id).unwrap();
let node_id = node.node_id;
node.element_id = Some(element_id);
if self.node_id_mapping.len() <= element_id.0 {
@@ -342,14 +342,17 @@ impl<V: FromAnyValue + Send + Sync> RealDom<V> {
/// Find all nodes that are listening for an event, sorted by there height in the dom progressing starting at the bottom and progressing up.
/// This can be useful to avoid creating duplicate events.
pub fn get_listening_sorted(&self, event: &'static str) -> Vec<NodeId> {
pub fn get_listening_sorted(&self, event: &'static str) -> Vec<NodeRef<V>> {
if let Some(nodes) = self.nodes_listening.get(event) {
let mut listening: Vec<_> = nodes
.iter()
.map(|id| (*id, self.tree.height(*id).unwrap()))
.collect();
listening.sort_by(|(_, h1), (_, h2)| h1.cmp(h2).reverse());
listening.into_iter().map(|(id, _)| id).collect()
listening
.into_iter()
.map(|(id, _)| NodeRef { id, dom: self })
.collect()
} else {
Vec::new()
}
@@ -371,7 +374,8 @@ impl<V: FromAnyValue + Send + Sync> RealDom<V> {
let new_node = node.node_data().clone();
let new_id = self.create_node(new_node, None, true).id();
for child in self.tree.children_ids(node_id).unwrap() {
let children = self.tree.children_ids(node_id).unwrap().to_vec();
for child in children {
let child_id = self.clone_node(child);
self.add_child(new_id, child_id);
}
@@ -382,11 +386,13 @@ impl<V: FromAnyValue + Send + Sync> RealDom<V> {
self.tree.root()
}
pub fn get(&self, id: NodeId) -> Option<NodeRef<'_, V>> {
pub fn get(&self, id: impl IntoNodeId<V>) -> Option<NodeRef<'_, V>> {
let id = id.into_node_id(self);
self.tree.contains(id).then_some(NodeRef { id, dom: self })
}
pub fn get_mut(&mut self, id: NodeId) -> Option<NodeMut<'_, V>> {
pub fn get_mut(&mut self, id: impl IntoNodeId<V>) -> Option<NodeMut<'_, V>> {
let id = id.into_node_id(self);
self.tree.contains(id).then(|| NodeMut {
id,
dirty: NodeMask::default(),
@@ -395,8 +401,11 @@ impl<V: FromAnyValue + Send + Sync> RealDom<V> {
}
/// WARNING: This escapes the reactive system that the real dom uses. Any changes made with this method will not trigger updates in states when [RealDom::update_state] is called.
pub fn get_mut_raw(&mut self, id: NodeId) -> Option<&mut NodeData<V>> {
self.tree.write(id)
pub fn get_mut_raw(&mut self, id: impl IntoNodeId<V>) -> Option<NodeMutRaw<V>> {
let id = id.into_node_id(self);
self.tree
.contains(id)
.then_some(NodeMutRaw { id, dom: self })
}
/// 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.
@@ -499,7 +508,7 @@ impl<V: FromAnyValue + Send + Sync> RealDom<V> {
f(node);
if let Some(children) = self.tree.children_ids(id) {
for id in children {
queue.push_back(id);
queue.push_back(*id);
}
}
}
@@ -510,10 +519,11 @@ impl<V: FromAnyValue + Send + Sync> RealDom<V> {
let mut stack = vec![self.root()];
while let Some(id) = stack.pop() {
if let Some(children) = self.tree.children_ids(id) {
let children = children.iter().copied().rev().collect::<Vec<_>>();
if let Some(node) = self.get_mut(id) {
let node = node;
f(node);
stack.extend(children.iter().copied().rev());
stack.extend(children.iter());
}
}
}
@@ -524,6 +534,7 @@ impl<V: FromAnyValue + Send + Sync> RealDom<V> {
queue.push_back(self.root());
while let Some(id) = queue.pop_front() {
if let Some(children) = self.tree.children_ids(id) {
let children = children.to_vec();
if let Some(node) = self.get_mut(id) {
f(node);
for id in children {
@@ -535,75 +546,116 @@ impl<V: FromAnyValue + Send + Sync> RealDom<V> {
}
}
// impl<V: FromAnyValue> Index<ElementId> for RealDom<V> {
// type Output = Node<V>;
pub trait IntoNodeId<V: FromAnyValue + Send + Sync> {
fn into_node_id(self, rdom: &RealDom<V>) -> NodeId;
}
// fn index(&self, id: ElementId) -> &Self::Output {
// self.tree.get(self.element_to_node_id(id)).unwrap()
// }
// }
impl<V: FromAnyValue + Send + Sync> IntoNodeId<V> for NodeId {
fn into_node_id(self, _rdom: &RealDom<V>) -> NodeId {
self
}
}
// impl<V: FromAnyValue> Index<NodeId> for RealDom<V> {
// type Output = Node<V>;
impl<V: FromAnyValue + Send + Sync> IntoNodeId<V> for ElementId {
fn into_node_id(self, rdom: &RealDom<V>) -> NodeId {
rdom.element_to_node_id(self)
}
}
// fn index(&self, idx: NodeId) -> &Self::Output {
// self.tree.get(idx).unwrap()
// }
// }
pub trait NodeImmutable<V: FromAnyValue + Send + Sync>: Sized {
fn real_dom(&self) -> &RealDom<V>;
// impl<V: FromAnyValue> IndexMut<ElementId> for RealDom<V> {
// fn index_mut(&mut self, id: ElementId) -> &mut Self::Output {
// self.tree.get_mut(self.element_to_node_id(id)).unwrap()
// }
// }
fn id(&self) -> NodeId;
// impl<V: FromAnyValue> IndexMut<NodeId> for RealDom<V> {
// fn index_mut(&mut self, idx: NodeId) -> &mut Self::Output {
// self.tree.get_mut(idx).unwrap()
// }
// }
fn mounted_id(&self) -> Option<ElementId> {
self.node_data().mounted_id()
}
pub struct NodeRef<'a, V: FromAnyValue + Send = ()> {
fn node_data(&self) -> &NodeData<V> {
self.get().unwrap()
}
fn node_type(&self) -> &NodeType<V> {
&self.node_data().node_type
}
fn get<T: Any>(&self) -> Option<&T> {
self.real_dom().tree.get(self.id())
}
fn child_ids(&self) -> Option<&[NodeId]> {
self.real_dom().tree.children_ids(self.id())
}
fn children(&self) -> Option<Vec<NodeRef<V>>> {
self.child_ids().map(|ids| {
ids.iter()
.map(|id| NodeRef {
id: *id,
dom: self.real_dom(),
})
.collect()
})
}
fn parent_id(&self) -> Option<NodeId> {
self.real_dom().tree.parent_id(self.id())
}
fn parent(&self) -> Option<NodeRef<V>> {
self.parent_id().map(|id| NodeRef {
id,
dom: self.real_dom(),
})
}
}
pub trait NodeMutable<V: FromAnyValue + Send + Sync>: Sized + NodeImmutable<V> {
fn get_mut<T: Any>(&mut self) -> Option<&mut T>;
}
#[derive(Clone, Copy)]
pub struct NodeRef<'a, V: FromAnyValue + Send + Sync = ()> {
id: NodeId,
dom: &'a RealDom<V>,
}
impl<'a, V: FromAnyValue + Send> NodeRef<'a, V> {
pub fn node_data(&self) -> &NodeData<V> {
self.read().unwrap()
impl<'a, V: FromAnyValue + Send + Sync> NodeImmutable<V> for NodeRef<'a, V> {
fn real_dom(&self) -> &RealDom<V> {
self.dom
}
pub fn node_type(&self) -> &NodeType<V> {
&self.node_data().node_type
}
pub fn read<T: Any>(&self) -> Option<&T> {
self.dom.tree.read(self.id)
fn id(&self) -> NodeId {
self.id
}
}
pub struct NodeMut<'a, V: FromAnyValue + Send = ()> {
pub struct NodeMut<'a, V: FromAnyValue + Send + Sync = ()> {
id: NodeId,
dom: &'a mut RealDom<V>,
dirty: NodeMask,
}
impl<'a, V: FromAnyValue + Send> NodeMut<'a, V> {
fn node_data(&self) -> &NodeData<V> {
self.read().unwrap()
impl<'a, V: FromAnyValue + Send + Sync> NodeImmutable<V> for NodeMut<'a, V> {
fn real_dom(&self) -> &RealDom<V> {
self.dom
}
fn node_data_mut(&mut self) -> &mut NodeData<V> {
self.dom.tree.write(self.id).unwrap()
fn id(&self) -> NodeId {
self.id
}
}
pub fn node_type(&self) -> &NodeType<V> {
&self.node_data().node_type
impl<'a, V: FromAnyValue + Send + Sync> NodeMutable<V> for NodeMut<'a, V> {
fn get_mut<T: Any>(&mut self) -> Option<&mut T> {
todo!("get_mut with mark as dirty")
}
}
impl<'a, V: FromAnyValue + Send + Sync> NodeMut<'a, V> {
pub fn node_type_mut(&mut self) -> NodeTypeMut<'_, V> {
let Self { id, dom, dirty } = self;
let node_type = &mut dom.tree.write::<NodeData<V>>(*id).unwrap().node_type;
let node_type = &mut dom.tree.get_mut::<NodeData<V>>(*id).unwrap().node_type;
match node_type {
NodeType::Element(element) => NodeTypeMut::Element(ElementNodeMut { element, dirty }),
NodeType::Text(text) => {
@@ -615,20 +667,16 @@ impl<'a, V: FromAnyValue + Send> NodeMut<'a, V> {
}
pub fn set_type(&mut self, new: NodeType<V>) {
self.node_data_mut().node_type = new;
self.dom
.tree
.get_mut::<NodeData<V>>(self.id)
.unwrap()
.node_type = new;
self.dirty = NodeMaskBuilder::ALL.build();
}
pub fn read<T: Any>(&self) -> Option<&T> {
self.dom.tree.read(self.id)
}
pub fn write<T: Any>(&mut self) -> Option<&T> {
todo!("get_mut with mark as dirty")
}
}
impl<V: FromAnyValue + Send> Drop for NodeMut<'_, V> {
impl<V: FromAnyValue + Send + Sync> Drop for NodeMut<'_, V> {
fn drop(&mut self) {
let node_id = self.node_data().node_id;
let mask = std::mem::take(&mut self.dirty);
@@ -716,3 +764,24 @@ impl<V: FromAnyValue> ElementNodeMut<'_, V> {
&mut self.element.listeners
}
}
pub struct NodeMutRaw<'a, V: FromAnyValue + Send + Sync = ()> {
id: NodeId,
dom: &'a mut RealDom<V>,
}
impl<'a, V: FromAnyValue + Send + Sync> NodeImmutable<V> for NodeMutRaw<'a, V> {
fn real_dom(&self) -> &RealDom<V> {
self.dom
}
fn id(&self) -> NodeId {
self.id
}
}
impl<'a, V: FromAnyValue + Send + Sync> NodeMutable<V> for NodeMutRaw<'a, V> {
fn get_mut<T: Any>(&mut self) -> Option<&mut T> {
self.dom.tree.get_mut::<T>(self.id)
}
}
+4 -4
View File
@@ -164,11 +164,11 @@ impl Tree {
}
}
pub fn read<T: Any>(&self, id: NodeId) -> Option<&T> {
pub fn get<T: Any>(&self, id: NodeId) -> Option<&T> {
self.nodes.read_slab().get(id)
}
pub fn write<T: Any>(&mut self, id: NodeId) -> Option<&mut T> {
pub fn get_mut<T: Any>(&mut self, id: NodeId) -> Option<&mut T> {
self.nodes.write_slab().get_mut(id)
}
@@ -184,8 +184,8 @@ impl Tree {
self.get_node_data(id).parent
}
pub fn children_ids(&self, id: NodeId) -> Option<Vec<NodeId>> {
Some(self.get_node_data(id).children.clone())
pub fn children_ids(&self, id: NodeId) -> Option<&[NodeId]> {
Some(&self.get_node_data(id).children)
}
pub fn height(&self, id: NodeId) -> Option<u16> {
+2 -2
View File
@@ -1,3 +1,3 @@
// mod persistant_iterator;
// pub use persistant_iterator::*;
mod persistant_iterator;
pub use persistant_iterator::*;
pub mod cursor;
@@ -1,7 +1,6 @@
use crate::{
node::{ElementNode, FromAnyValue, NodeType},
passes::{AnyMapLike, TypeErasedPass},
real_dom::RealDom,
real_dom::{NodeImmutable, RealDom},
NodeId,
};
use dioxus_core::{Mutation, Mutations};
@@ -72,10 +71,10 @@ impl PersistantElementIter {
/// remove stale element refreneces
/// returns true if the focused element is removed
pub fn prune<S: State<V>, V: FromAnyValue>(
pub fn prune<V: FromAnyValue + Send + Sync>(
&mut self,
mutations: &Mutations,
rdom: &RealDom<S, V>,
rdom: &RealDom<V>,
) -> bool {
let mut changed = false;
let ids_removed: Vec<_> = mutations
@@ -102,7 +101,7 @@ impl PersistantElementIter {
// if a child is removed or inserted before or at the current element, update the child index
for (el_id, child_idx) in self.stack.iter_mut() {
if let NodePosition::InChild(child_idx) = child_idx {
if let Some(children) = &rdom.children_ids(*el_id) {
if let Some(children) = &rdom.get(*el_id).unwrap().child_ids() {
for m in &mutations.edits {
match m {
Mutation::Remove { id } => {
@@ -133,7 +132,7 @@ impl PersistantElementIter {
}
/// get the next element
pub fn next<S: State<V>, V: FromAnyValue>(&mut self, rdom: &RealDom<S, V>) -> ElementProduced {
pub fn next<V: FromAnyValue + Send + Sync>(&mut self, rdom: &RealDom<V>) -> ElementProduced {
if self.stack.is_empty() {
let id = NodeId(0);
let new = (id, NodePosition::AtNode);
@@ -142,9 +141,9 @@ impl PersistantElementIter {
} else {
let (last, old_child_idx) = self.stack.last_mut().unwrap();
let node = rdom.get(*last).unwrap();
match &node.node_data.node_type {
match &node.node_data().node_type {
NodeType::Element(ElementNode { .. }) => {
let children = rdom.children_ids(*last).unwrap();
let children = node.child_ids().unwrap();
*old_child_idx = old_child_idx.map(|i| i + 1);
// if we have children, go to the next child
let child_idx = old_child_idx.get_or_insert(0);
@@ -154,7 +153,7 @@ impl PersistantElementIter {
} else {
let id = children[child_idx];
if let NodeType::Element(ElementNode { .. }) =
rdom.get(id).unwrap().node_data.node_type
rdom.get(id).unwrap().node_data().node_type
{
self.stack.push((id, NodePosition::AtNode));
}
@@ -171,19 +170,17 @@ impl PersistantElementIter {
}
/// get the previous element
pub fn prev<S: State<V> + Send, V: FromAnyValue>(
&mut self,
rdom: &RealDom<S, V>,
) -> ElementProduced {
pub fn prev<V: FromAnyValue + Send + Sync>(&mut self, rdom: &RealDom<V>) -> ElementProduced {
// recursively add the last child element to the stack
fn push_back<S: State<V> + Send, V: FromAnyValue>(
fn push_back<V: FromAnyValue + Send + Sync>(
stack: &mut smallvec::SmallVec<[(NodeId, NodePosition); 5]>,
new_node: NodeId,
rdom: &RealDom<S, V>,
rdom: &RealDom<V>,
) -> NodeId {
match &rdom[new_node].node_data.node_type {
let node = rdom.get(new_node).unwrap();
match &node.node_data().node_type {
NodeType::Element(ElementNode { .. }) => {
let children = rdom.children_ids(new_node).unwrap();
let children = node.child_ids().unwrap();
if children.is_empty() {
new_node
} else {
@@ -199,10 +196,10 @@ impl PersistantElementIter {
ElementProduced::Looped(push_back(&mut self.stack, new_node, rdom))
} else {
let (last, old_child_idx) = self.stack.last_mut().unwrap();
let node = &rdom[*last];
match &node.node_data.node_type {
let node = rdom.get(*last).unwrap();
match &node.node_data().node_type {
NodeType::Element(ElementNode { .. }) => {
let children = rdom.children_ids(*last).unwrap();
let children = node.child_ids().unwrap();
// if we have children, go to the next child
if let NodePosition::InChild(0) = old_child_idx {
ElementProduced::Progressed(self.pop())
@@ -240,23 +237,6 @@ impl PersistantElementIter {
}
}
#[derive(Default, Clone, Debug)]
struct Empty {}
impl AnyMapLike for Empty {
fn get<T: std::any::Any>(&self) -> Option<&T> {
None
}
fn get_mut<T: std::any::Any>(&mut self) -> Option<&mut T> {
None
}
}
impl State for Empty {
fn create_passes() -> Box<[TypeErasedPass<Self>]> {
Box::new([])
}
}
#[test]
#[allow(unused_variables)]
fn traverse() {
@@ -279,7 +259,7 @@ fn traverse() {
let mut vdom = VirtualDom::new(Base);
let mutations = vdom.rebuild();
let mut rdom: RealDom<Empty> = RealDom::new();
let mut rdom: RealDom = RealDom::new(Box::new([]));
let _to_update = rdom.apply_mutations(mutations);
@@ -378,7 +358,7 @@ fn persist_removes() {
}
let mut vdom = VirtualDom::new(Base);
let mut rdom: RealDom<Empty> = RealDom::new();
let mut rdom: RealDom = RealDom::new(Box::new([]));
let build = vdom.rebuild();
println!("{:#?}", build);
@@ -460,7 +440,7 @@ fn persist_instertions_before() {
}
let mut vdom = VirtualDom::new(Base);
let mut rdom: RealDom<Empty> = RealDom::new();
let mut rdom: RealDom = RealDom::new(Box::new([]));
let build = vdom.rebuild();
let _to_update = rdom.apply_mutations(build);
@@ -516,7 +496,7 @@ fn persist_instertions_after() {
}
let mut vdom = VirtualDom::new(Base);
let mut rdom: RealDom<Empty> = RealDom::new();
let mut rdom: RealDom = RealDom::new(Box::new([]));
let build = vdom.rebuild();
let _to_update = rdom.apply_mutations(build);