From 9efff74c0c30ac1533fc681f9b39f7d2238e2a5c Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Sat, 28 Jan 2023 14:51:05 -0600 Subject: [PATCH] update TUI renderer to new approach --- packages/native-core/src/lib.rs | 1 + packages/native-core/src/node_ref.rs | 16 +- packages/native-core/src/real_dom.rs | 195 ++++++++++++------ packages/native-core/src/tree.rs | 8 +- packages/native-core/src/utils/mod.rs | 4 +- .../src/utils/persistant_iterator.rs | 62 ++---- packages/tui/src/focus.rs | 79 +++---- packages/tui/src/hooks.rs | 54 ++--- packages/tui/src/layout.rs | 30 +-- packages/tui/src/lib.rs | 23 ++- packages/tui/src/node.rs | 36 ++-- packages/tui/src/query.rs | 19 +- packages/tui/src/render.rs | 50 +++-- packages/tui/src/style_attributes.rs | 32 ++- 14 files changed, 339 insertions(+), 270 deletions(-) diff --git a/packages/native-core/src/lib.rs b/packages/native-core/src/lib.rs index 051a8731d..c54daab10 100644 --- a/packages/native-core/src/lib.rs +++ b/packages/native-core/src/lib.rs @@ -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; diff --git a/packages/native-core/src/node_ref.rs b/packages/native-core/src/node_ref.rs index 14145b5cc..beb8519dc 100644 --- a/packages/native-core/src/node_ref.rs +++ b/packages/native-core/src/node_ref.rs @@ -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 diff --git a/packages/native-core/src/real_dom.rs b/packages/native-core/src/real_dom.rs index 367a11eb7..9a874ea99 100644 --- a/packages/native-core/src/real_dom.rs +++ b/packages/native-core/src/real_dom.rs @@ -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 { +pub struct RealDom { pub(crate) tree: Tree, /// a map from element id to real node id node_id_mapping: Vec>, @@ -38,7 +38,7 @@ impl RealDom { pub fn new(mut passes: Box<[TypeErasedPass]>) -> RealDom { let mut tree = Tree::new(); let root_id = tree.root(); - let root: &mut NodeData = tree.write(root_id).unwrap(); + let root: &mut NodeData = tree.get_mut(root_id).unwrap(); let mut root_node: NodeData = NodeData::new(NodeType::Element(ElementNode { tag: "Root".to_string(), namespace: Some("Root".to_string()), @@ -95,7 +95,7 @@ impl RealDom { } fn set_element_id(&mut self, node_id: NodeId, element_id: ElementId) { - let mut node = self.tree.write::(node_id).unwrap(); + let mut node = self.tree.get_mut::(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 RealDom { /// 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 { + pub fn get_listening_sorted(&self, event: &'static str) -> Vec> { 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 RealDom { 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 RealDom { self.tree.root() } - pub fn get(&self, id: NodeId) -> Option> { + pub fn get(&self, id: impl IntoNodeId) -> Option> { + 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> { + pub fn get_mut(&mut self, id: impl IntoNodeId) -> Option> { + let id = id.into_node_id(self); self.tree.contains(id).then(|| NodeMut { id, dirty: NodeMask::default(), @@ -395,8 +401,11 @@ impl RealDom { } /// 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> { - self.tree.write(id) + pub fn get_mut_raw(&mut self, id: impl IntoNodeId) -> Option> { + 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 RealDom { 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 RealDom { 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::>(); 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 RealDom { 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 RealDom { } } -// impl Index for RealDom { -// type Output = Node; +pub trait IntoNodeId { + fn into_node_id(self, rdom: &RealDom) -> NodeId; +} -// fn index(&self, id: ElementId) -> &Self::Output { -// self.tree.get(self.element_to_node_id(id)).unwrap() -// } -// } +impl IntoNodeId for NodeId { + fn into_node_id(self, _rdom: &RealDom) -> NodeId { + self + } +} -// impl Index for RealDom { -// type Output = Node; +impl IntoNodeId for ElementId { + fn into_node_id(self, rdom: &RealDom) -> NodeId { + rdom.element_to_node_id(self) + } +} -// fn index(&self, idx: NodeId) -> &Self::Output { -// self.tree.get(idx).unwrap() -// } -// } +pub trait NodeImmutable: Sized { + fn real_dom(&self) -> &RealDom; -// impl IndexMut for RealDom { -// 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 IndexMut for RealDom { -// fn index_mut(&mut self, idx: NodeId) -> &mut Self::Output { -// self.tree.get_mut(idx).unwrap() -// } -// } + fn mounted_id(&self) -> Option { + self.node_data().mounted_id() + } -pub struct NodeRef<'a, V: FromAnyValue + Send = ()> { + fn node_data(&self) -> &NodeData { + self.get().unwrap() + } + + fn node_type(&self) -> &NodeType { + &self.node_data().node_type + } + + fn get(&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>> { + self.child_ids().map(|ids| { + ids.iter() + .map(|id| NodeRef { + id: *id, + dom: self.real_dom(), + }) + .collect() + }) + } + + fn parent_id(&self) -> Option { + self.real_dom().tree.parent_id(self.id()) + } + + fn parent(&self) -> Option> { + self.parent_id().map(|id| NodeRef { + id, + dom: self.real_dom(), + }) + } +} + +pub trait NodeMutable: Sized + NodeImmutable { + fn get_mut(&mut self) -> Option<&mut T>; +} + +#[derive(Clone, Copy)] +pub struct NodeRef<'a, V: FromAnyValue + Send + Sync = ()> { id: NodeId, dom: &'a RealDom, } -impl<'a, V: FromAnyValue + Send> NodeRef<'a, V> { - pub fn node_data(&self) -> &NodeData { - self.read().unwrap() +impl<'a, V: FromAnyValue + Send + Sync> NodeImmutable for NodeRef<'a, V> { + fn real_dom(&self) -> &RealDom { + self.dom } - pub fn node_type(&self) -> &NodeType { - &self.node_data().node_type - } - - pub fn read(&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, dirty: NodeMask, } -impl<'a, V: FromAnyValue + Send> NodeMut<'a, V> { - fn node_data(&self) -> &NodeData { - self.read().unwrap() +impl<'a, V: FromAnyValue + Send + Sync> NodeImmutable for NodeMut<'a, V> { + fn real_dom(&self) -> &RealDom { + self.dom } - fn node_data_mut(&mut self) -> &mut NodeData { - self.dom.tree.write(self.id).unwrap() + fn id(&self) -> NodeId { + self.id } +} - pub fn node_type(&self) -> &NodeType { - &self.node_data().node_type +impl<'a, V: FromAnyValue + Send + Sync> NodeMutable for NodeMut<'a, V> { + fn get_mut(&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::>(*id).unwrap().node_type; + let node_type = &mut dom.tree.get_mut::>(*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) { - self.node_data_mut().node_type = new; + self.dom + .tree + .get_mut::>(self.id) + .unwrap() + .node_type = new; self.dirty = NodeMaskBuilder::ALL.build(); } - - pub fn read(&self) -> Option<&T> { - self.dom.tree.read(self.id) - } - - pub fn write(&mut self) -> Option<&T> { - todo!("get_mut with mark as dirty") - } } -impl Drop for NodeMut<'_, V> { +impl 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 ElementNodeMut<'_, V> { &mut self.element.listeners } } + +pub struct NodeMutRaw<'a, V: FromAnyValue + Send + Sync = ()> { + id: NodeId, + dom: &'a mut RealDom, +} + +impl<'a, V: FromAnyValue + Send + Sync> NodeImmutable for NodeMutRaw<'a, V> { + fn real_dom(&self) -> &RealDom { + self.dom + } + + fn id(&self) -> NodeId { + self.id + } +} + +impl<'a, V: FromAnyValue + Send + Sync> NodeMutable for NodeMutRaw<'a, V> { + fn get_mut(&mut self) -> Option<&mut T> { + self.dom.tree.get_mut::(self.id) + } +} diff --git a/packages/native-core/src/tree.rs b/packages/native-core/src/tree.rs index a5bef626c..f4d43e89f 100644 --- a/packages/native-core/src/tree.rs +++ b/packages/native-core/src/tree.rs @@ -164,11 +164,11 @@ impl Tree { } } - pub fn read(&self, id: NodeId) -> Option<&T> { + pub fn get(&self, id: NodeId) -> Option<&T> { self.nodes.read_slab().get(id) } - pub fn write(&mut self, id: NodeId) -> Option<&mut T> { + pub fn get_mut(&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> { - 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 { diff --git a/packages/native-core/src/utils/mod.rs b/packages/native-core/src/utils/mod.rs index 9ddb1a1c7..58e98b0fa 100644 --- a/packages/native-core/src/utils/mod.rs +++ b/packages/native-core/src/utils/mod.rs @@ -1,3 +1,3 @@ -// mod persistant_iterator; -// pub use persistant_iterator::*; +mod persistant_iterator; +pub use persistant_iterator::*; pub mod cursor; diff --git a/packages/native-core/src/utils/persistant_iterator.rs b/packages/native-core/src/utils/persistant_iterator.rs index f5423cb76..7263619a1 100644 --- a/packages/native-core/src/utils/persistant_iterator.rs +++ b/packages/native-core/src/utils/persistant_iterator.rs @@ -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, V: FromAnyValue>( + pub fn prune( &mut self, mutations: &Mutations, - rdom: &RealDom, + rdom: &RealDom, ) -> 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, V: FromAnyValue>(&mut self, rdom: &RealDom) -> ElementProduced { + pub fn next(&mut self, rdom: &RealDom) -> 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 + Send, V: FromAnyValue>( - &mut self, - rdom: &RealDom, - ) -> ElementProduced { + pub fn prev(&mut self, rdom: &RealDom) -> ElementProduced { // recursively add the last child element to the stack - fn push_back + Send, V: FromAnyValue>( + fn push_back( stack: &mut smallvec::SmallVec<[(NodeId, NodePosition); 5]>, new_node: NodeId, - rdom: &RealDom, + rdom: &RealDom, ) -> 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(&self) -> Option<&T> { - None - } - - fn get_mut(&mut self) -> Option<&mut T> { - None - } -} -impl State for Empty { - fn create_passes() -> Box<[TypeErasedPass]> { - 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 = 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 = 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 = 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 = RealDom::new(); + let mut rdom: RealDom = RealDom::new(Box::new([])); let build = vdom.rebuild(); let _to_update = rdom.apply_mutations(build); diff --git a/packages/tui/src/focus.rs b/packages/tui/src/focus.rs index 6d7f89154..4441f44f3 100644 --- a/packages/tui/src/focus.rs +++ b/packages/tui/src/focus.rs @@ -1,15 +1,17 @@ -use crate::{node::PreventDefault, TuiDom}; +use crate::node::PreventDefault; use dioxus_native_core::{ - tree::TreeView, + node_ref::{AttributeMaskBuilder, NodeMaskBuilder}, + real_dom::{NodeImmutable, NodeMutable}, utils::{ElementProduced, PersistantElementIter}, - NodeId, Pass, SendAnyMap, + Dependancy, NodeId, Pass, RealDom, SendAnyMap, }; -use dioxus_native_core_macro::sorted_str_slice; use std::{cmp::Ordering, num::NonZeroU16}; -use dioxus_native_core::node_ref::{AttributeMask, NodeMask, NodeView}; +use dioxus_native_core::node_ref::NodeView; + +pub struct Focused(pub bool); #[derive(Clone, Copy, PartialEq, Eq, Debug)] pub(crate) enum FocusLevel { @@ -62,8 +64,9 @@ pub(crate) struct Focus { } impl Pass for Focus { - const NODE_MASK: NodeMask = - NodeMask::new_with_attrs(AttributeMask::Static(FOCUS_ATTRIBUTES)).with_listeners(); + const NODE_MASK: NodeMaskBuilder = NodeMaskBuilder::new() + .with_attrs(AttributeMaskBuilder::Some(FOCUS_ATTRIBUTES)) + .with_listeners(); type ParentDependencies = (); type ChildDependencies = (); @@ -72,18 +75,10 @@ impl Pass for Focus { fn pass<'a>( &mut self, node_view: NodeView, - _: ::ElementBorrowed<'a>, - _: Option< - ::ElementBorrowed<'a>, - >, - _: Option< - impl Iterator< - Item = ::ElementBorrowed< - 'a, - >, - >, - >, - _: &SendAnyMap, + node: ::ElementBorrowed<'a>, + parent: Option<::ElementBorrowed<'a>>, + children: Option::ElementBorrowed<'a>>>, + context: &SendAnyMap, ) -> bool { let new = Focus { level: if let Some(a) = node_view @@ -128,8 +123,8 @@ impl Pass for Focus { } } -const FOCUS_EVENTS: &[&str] = &sorted_str_slice!(["keydown", "keypress", "keyup"]); -const FOCUS_ATTRIBUTES: &[&str] = &sorted_str_slice!(["tabindex"]); +const FOCUS_EVENTS: &[&str] = &["keydown", "keypress", "keyup"]; +const FOCUS_ATTRIBUTES: &[&str] = &["tabindex"]; #[derive(Default)] pub(crate) struct FocusState { @@ -141,9 +136,11 @@ pub(crate) struct FocusState { impl FocusState { /// Returns true if the focus has changed. - pub fn progress(&mut self, rdom: &mut TuiDom, forward: bool) -> bool { + pub fn progress(&mut self, rdom: &mut RealDom, forward: bool) -> bool { if let Some(last) = self.last_focused_id { - if rdom[last].state.prevent_default == PreventDefault::KeyDown { + if rdom.get(last).unwrap().get::().copied() + == Some(PreventDefault::KeyDown) + { return false; } } @@ -165,7 +162,7 @@ impl FocusState { if forward { // find the closest focusable element after the current level rdom.traverse_depth_first(|n| { - let node_level = n.state.focus.level; + let node_level = n.get::().unwrap().level; if node_level != *focus_level && node_level.focusable() && node_level > *focus_level @@ -182,7 +179,7 @@ impl FocusState { } else { // find the closest focusable element before the current level rdom.traverse_depth_first(|n| { - let node_level = n.state.focus.level; + let node_level = n.get::().unwrap().level; if node_level != *focus_level && node_level.focusable() && node_level < *focus_level @@ -219,7 +216,7 @@ impl FocusState { loop_marker_id = Some(new_id); } - let current_level = rdom[new_id].state.focus.level; + let current_level = rdom.get(new_id).unwrap().get::().unwrap().level; let after_previous_focused = if forward { current_level >= *focus_level } else { @@ -233,12 +230,16 @@ impl FocusState { } if let Some(id) = next_focus { - if !rdom[id].state.focus.level.focusable() { + let mut node = rdom.get_mut_raw(id).unwrap(); + if !node.get::().unwrap().level.focusable() { panic!() } - rdom[id].state.focused = true; + let focused = node.get_mut::().unwrap(); + focused.0 = true; if let Some(old) = self.last_focused_id.replace(id) { - rdom[old].state.focused = false; + let mut old = rdom.get_mut_raw(old).unwrap(); + let focused = old.get_mut::().unwrap(); + focused.0 = false; } // reset the position to the currently focused element while self.focus_iter.next(rdom).id() != id {} @@ -249,8 +250,8 @@ impl FocusState { false } - pub(crate) fn prune(&mut self, mutations: &dioxus_core::Mutations, rdom: &TuiDom) { - fn remove_children(to_prune: &mut [&mut Option], rdom: &TuiDom, removed: NodeId) { + pub(crate) fn prune(&mut self, mutations: &dioxus_core::Mutations, rdom: &RealDom) { + fn remove_children(to_prune: &mut [&mut Option], rdom: &RealDom, removed: NodeId) { for opt in to_prune.iter_mut() { if let Some(id) = opt { if *id == removed { @@ -258,8 +259,9 @@ impl FocusState { } } } - if let Some(children) = &rdom.children_ids(removed) { - for child in *children { + let node = rdom.get(removed).unwrap(); + if let Some(children) = node.child_ids() { + for child in children { remove_children(to_prune, rdom, *child); } } @@ -284,13 +286,14 @@ impl FocusState { } } - pub(crate) fn set_focus(&mut self, rdom: &mut TuiDom, id: NodeId) { + pub(crate) fn set_focus(&mut self, rdom: &mut RealDom, id: NodeId) { if let Some(old) = self.last_focused_id.replace(id) { - rdom[old].state.focused = false; + let mut node = rdom.get_mut_raw(old).unwrap(); + node.get_mut::().unwrap().0 = false; } - let state = &mut rdom[id].state; - state.focused = true; - self.focus_level = state.focus.level; + let mut node = &mut rdom.get_mut_raw(id).unwrap(); + node.get_mut::().unwrap().0 = true; + self.focus_level = node.get::().unwrap().level; // reset the position to the currently focused element while self.focus_iter.next(rdom).id() != id {} self.dirty = true; diff --git a/packages/tui/src/hooks.rs b/packages/tui/src/hooks.rs index ab5064bc7..6f043d522 100644 --- a/packages/tui/src/hooks.rs +++ b/packages/tui/src/hooks.rs @@ -2,8 +2,8 @@ use crossterm::event::{ Event as TermEvent, KeyCode as TermKeyCode, KeyModifiers, MouseButton, MouseEventKind, }; use dioxus_core::*; -use dioxus_native_core::tree::TreeView; -use dioxus_native_core::NodeId; +use dioxus_native_core::real_dom::NodeImmutable; +use dioxus_native_core::{NodeId, NodeRef, RealDom}; use rustc_hash::{FxHashMap, FxHashSet}; use dioxus_html::geometry::euclid::{Point2D, Rect, Size2D}; @@ -23,8 +23,9 @@ use std::{ use taffy::geometry::{Point, Size}; use taffy::{prelude::Layout, Taffy}; +use crate::focus::{Focus, Focused}; +use crate::layout::TaffyLayout; use crate::{layout_to_screen_space, FocusState}; -use crate::{TuiDom, TuiNode}; pub(crate) struct Event { pub id: ElementId, @@ -173,7 +174,7 @@ impl InnerInputState { evts: &mut Vec, resolved_events: &mut Vec, layout: &Taffy, - dom: &mut TuiDom, + dom: &mut RealDom, ) { let previous_mouse = self.mouse.clone(); @@ -201,7 +202,7 @@ impl InnerInputState { // elements with listeners will always have a element id if let Some(id) = self.focus_state.last_focused_id { let element = dom.get(id).unwrap(); - if let Some(id) = element.node_data.element_id { + if let Some(id) = element.node_data().element_id { resolved_events.push(Event { name: "focus", id, @@ -218,7 +219,7 @@ impl InnerInputState { } if let Some(id) = old_focus { let element = dom.get(id).unwrap(); - if let Some(id) = element.node_data.element_id { + if let Some(id) = element.node_data().element_id { resolved_events.push(Event { name: "focusout", id, @@ -239,7 +240,7 @@ impl InnerInputState { previous_mouse: Option, resolved_events: &mut Vec, layout: &Taffy, - dom: &mut TuiDom, + dom: &mut RealDom, ) { fn layout_contains_point(layout: &Layout, point: ScreenPoint) -> bool { let Point { x, y } = layout.location; @@ -262,17 +263,17 @@ impl InnerInputState { data: Rc, will_bubble: &mut FxHashSet, resolved_events: &mut Vec, - node: &TuiNode, - dom: &TuiDom, + node: NodeRef, + dom: &RealDom, ) { // only trigger event if the event was not triggered already by a child - let id = node.node_data.node_id; + let id = node.node_data().node_id; if will_bubble.insert(id) { - let mut parent = dom.parent(id); + let mut parent = Some(node); while let Some(current_parent) = parent { - let parent_id = current_parent.node_data.node_id; + let parent_id = current_parent.node_data().node_id; will_bubble.insert(parent_id); - parent = dom.parent(parent_id); + parent = current_parent.parent_id().and_then(|id| dom.get(id)); } if let Some(id) = node.mounted_id() { resolved_events.push(Event { @@ -564,11 +565,13 @@ impl InnerInputState { if was_released { let mut focus_id = None; dom.traverse_depth_first(|node| { - let node_layout = layout.layout(node.state.layout.node.unwrap()).unwrap(); + let node_layout = layout + .layout(node.get::().unwrap().node.unwrap()) + .unwrap(); let currently_contains = layout_contains_point(node_layout, new_pos); - if currently_contains && node.state.focus.level.focusable() { - focus_id = Some(node.node_data.node_id); + if currently_contains && node.get::().unwrap().level.focusable() { + focus_id = Some(node.node_data().node_id); } }); if let Some(id) = focus_id { @@ -583,13 +586,18 @@ impl InnerInputState { // } } -fn get_abs_layout(node: &TuiNode, dom: &TuiDom, taffy: &Taffy) -> Layout { - let mut node_layout = *taffy.layout(node.state.layout.node.unwrap()).unwrap(); +fn get_abs_layout(node: NodeRef, dom: &RealDom, taffy: &Taffy) -> Layout { + let mut node_layout = *taffy + .layout(node.get::().unwrap().node.unwrap()) + .unwrap(); let mut current = node; - while let Some(parent) = dom.parent(current.node_data.node_id) { + while let Some(parent) = current.parent_id() { + let parent = dom.get(parent).unwrap(); current = parent; - let parent_layout = taffy.layout(parent.state.layout.node.unwrap()).unwrap(); + let parent_layout = taffy + .layout(parent.get::().unwrap().node.unwrap()) + .unwrap(); node_layout.location.x += parent_layout.location.x; node_layout.location.y += parent_layout.location.y; } @@ -632,11 +640,11 @@ impl RinkInputHandler { ) } - pub(crate) fn prune(&self, mutations: &dioxus_core::Mutations, rdom: &TuiDom) { + pub(crate) fn prune(&self, mutations: &dioxus_core::Mutations, rdom: &RealDom) { self.state.borrow_mut().focus_state.prune(mutations, rdom); } - pub(crate) fn get_events(&self, layout: &Taffy, dom: &mut TuiDom) -> Vec { + pub(crate) fn get_events(&self, layout: &Taffy, dom: &mut RealDom) -> Vec { let mut resolved_events = Vec::new(); (*self.state).borrow_mut().update( @@ -680,7 +688,7 @@ impl RinkInputHandler { for (event, datas) in hm { for node in dom.get_listening_sorted(event) { for data in &datas { - if node.state.focused { + if node.get::().unwrap().0 { if let Some(id) = node.mounted_id() { resolved_events.push(Event { name: event, diff --git a/packages/tui/src/layout.rs b/packages/tui/src/layout.rs index 5d539e7e0..87241a287 100644 --- a/packages/tui/src/layout.rs +++ b/packages/tui/src/layout.rs @@ -4,9 +4,8 @@ use dioxus_native_core::layout_attributes::{ apply_layout_attributes_cfg, BorderWidths, LayoutConfigeration, }; use dioxus_native_core::node::OwnedAttributeView; -use dioxus_native_core::node_ref::{AttributeMask, NodeMask, NodeView}; -use dioxus_native_core::{Pass, SendAnyMap}; -use dioxus_native_core_macro::sorted_str_slice; +use dioxus_native_core::node_ref::{AttributeMaskBuilder, NodeMaskBuilder, NodeView}; +use dioxus_native_core::{Dependancy, Pass, SendAnyMap}; use taffy::prelude::*; use crate::{screen_to_layout_space, unit_to_layout_space}; @@ -48,23 +47,16 @@ impl Pass for TaffyLayout { type ParentDependencies = (); type NodeDependencies = (); - const NODE_MASK: NodeMask = - NodeMask::new_with_attrs(AttributeMask::Static(SORTED_LAYOUT_ATTRS)).with_text(); + const NODE_MASK: NodeMaskBuilder = NodeMaskBuilder::new() + .with_attrs(AttributeMaskBuilder::Some(SORTED_LAYOUT_ATTRS)) + .with_text(); fn pass<'a>( &mut self, node_view: NodeView, - _: ::ElementBorrowed<'a>, - _: Option< - ::ElementBorrowed<'a>, - >, - children: Option< - impl Iterator< - Item = ::ElementBorrowed< - 'a, - >, - >, - >, + node: ::ElementBorrowed<'a>, + parent: Option<::ElementBorrowed<'a>>, + children: Option::ElementBorrowed<'a>>>, ctx: &SendAnyMap, ) -> bool { let mut changed = false; @@ -203,7 +195,7 @@ impl Pass for TaffyLayout { } // these are the attributes in layout_attiributes in native-core -const SORTED_LAYOUT_ATTRS: &[&str] = &sorted_str_slice!([ +const SORTED_LAYOUT_ATTRS: &[&str] = &[ "align-content", "align-items", "align-self", @@ -355,5 +347,5 @@ const SORTED_LAYOUT_ATTRS: &[&str] = &sorted_str_slice!([ "word-break", "word-spacing", "word-wrap", - "z-index" -]); + "z-index", +]; diff --git a/packages/tui/src/lib.rs b/packages/tui/src/lib.rs index c90893bf9..99d531215 100644 --- a/packages/tui/src/lib.rs +++ b/packages/tui/src/lib.rs @@ -6,6 +6,7 @@ use crossterm::{ terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen}, }; use dioxus_core::*; +use dioxus_native_core::{node_ref::NodeMaskBuilder, real_dom::NodeImmutable, Pass}; use dioxus_native_core::{real_dom::RealDom, FxDashSet, NodeId, NodeMask, SendAnyMap}; use focus::FocusState; use futures::{ @@ -13,6 +14,7 @@ use futures::{ pin_mut, StreamExt, }; use futures_channel::mpsc::unbounded; +use layout::TaffyLayout; use query::Query; use std::rc::Rc; use std::{ @@ -101,7 +103,9 @@ pub fn launch_cfg_with_props(app: Component, props: Props } let cx = dom.base_scope(); - let rdom = Rc::new(RefCell::new(RealDom::new())); + let rdom = Rc::new(RefCell::new(RealDom::new(Box::new([ + TaffyLayout::to_type_erased(), + ])))); let taffy = Arc::new(Mutex::new(Taffy::new())); cx.provide_context(state); cx.provide_context(TuiContext { tx: event_tx_clone }); @@ -136,7 +140,7 @@ fn render_vdom( mut event_reciever: UnboundedReceiver, handler: RinkInputHandler, cfg: Config, - rdom: Rc>, + rdom: Rc>, taffy: Arc>, mut register_event: impl FnMut(crossterm::event::Event), ) -> Result<()> { @@ -177,10 +181,16 @@ fn render_vdom( if !to_rerender.is_empty() || updated { updated = false; - fn resize(dims: Rect, taffy: &mut Taffy, rdom: &TuiDom) { + fn resize(dims: Rect, taffy: &mut Taffy, rdom: &RealDom) { let width = screen_to_layout_space(dims.width); let height = screen_to_layout_space(dims.height); - let root_node = rdom[NodeId(0)].state.layout.node.unwrap(); + let root_node = rdom + .get(NodeId(0)) + .unwrap() + .get::() + .unwrap() + .node + .unwrap(); // the root node fills the entire area @@ -204,7 +214,7 @@ fn render_vdom( let mut taffy = taffy.lock().expect("taffy lock poisoned"); // size is guaranteed to not change when rendering resize(frame.size(), &mut taffy, &rdom); - let root = &rdom[NodeId(0)]; + let root = rdom.get(NodeId(0)).unwrap(); render::render_vnode(frame, &taffy, &rdom, root, cfg, Point::ZERO); })?; execute!(terminal.backend_mut(), RestorePosition, Show).unwrap(); @@ -277,8 +287,9 @@ fn render_vdom( any_map.insert(taffy.clone()); let (new_to_rerender, dirty) = rdom.update_state(any_map); to_rerender = new_to_rerender; + let text_mask = NodeMaskBuilder::new().with_text().build(); for (id, mask) in dirty { - if mask.overlaps(&NodeMask::new().with_text()) { + if mask.overlaps(&text_mask) { to_rerender.insert(id); } } diff --git a/packages/tui/src/node.rs b/packages/tui/src/node.rs index 8dc418b24..3d38d1cd7 100644 --- a/packages/tui/src/node.rs +++ b/packages/tui/src/node.rs @@ -1,23 +1,18 @@ use crate::focus::Focus; use crate::layout::TaffyLayout; use crate::style_attributes::StyleModifier; -use dioxus_native_core::{real_dom::RealDom, Dependancy, Pass, SendAnyMap}; -use dioxus_native_core_macro::{sorted_str_slice, AnyMapLike, State}; +use dioxus_native_core::{node_ref::NodeView, Dependancy, Pass, SendAnyMap}; -pub(crate) type TuiDom = RealDom; -pub(crate) type TuiNode = dioxus_native_core::node::Node; - -#[derive(Debug, Clone, State, AnyMapLike, Default)] +#[derive(Debug, Clone, Default)] pub(crate) struct NodeState { pub layout: TaffyLayout, pub style: StyleModifier, pub prevent_default: PreventDefault, pub focus: Focus, - #[skip] pub focused: bool, } -#[derive(PartialEq, Debug, Clone)] +#[derive(PartialEq, Debug, Clone, Copy)] pub(crate) enum PreventDefault { Focus, KeyPress, @@ -47,23 +42,20 @@ impl Pass for PreventDefault { type ChildDependencies = (); type NodeDependencies = (); - const NODE_MASK: dioxus_native_core::node_ref::NodeMask = - dioxus_native_core::node_ref::NodeMask::new_with_attrs( - dioxus_native_core::node_ref::AttributeMask::Static(&sorted_str_slice!([ - "dioxus-prevent-default" - ])), - ) - .with_listeners(); + const NODE_MASK: dioxus_native_core::node_ref::NodeMaskBuilder = + dioxus_native_core::node_ref::NodeMaskBuilder::new() + .with_attrs(dioxus_native_core::node_ref::AttributeMaskBuilder::Some(&[ + "dioxus-prevent-default", + ])) + .with_listeners(); fn pass<'a>( &mut self, - node_view: dioxus_native_core::node_ref::NodeView, - _: ::ElementBorrowed<'a>, - _: Option<::ElementBorrowed<'a>>, - _: Option< - impl Iterator::ElementBorrowed<'a>>, - >, - _: &SendAnyMap, + node_view: NodeView, + node: ::ElementBorrowed<'a>, + parent: Option<::ElementBorrowed<'a>>, + children: Option::ElementBorrowed<'a>>>, + context: &SendAnyMap, ) -> bool { let new = match node_view.attributes().and_then(|mut attrs| { attrs diff --git a/packages/tui/src/query.rs b/packages/tui/src/query.rs index c052ad9ea..df1f69fbd 100644 --- a/packages/tui/src/query.rs +++ b/packages/tui/src/query.rs @@ -5,13 +5,14 @@ use std::{ }; use dioxus_core::ElementId; +use dioxus_native_core::{real_dom::NodeImmutable, RealDom}; use taffy::{ geometry::Point, prelude::{Layout, Size}, Taffy, }; -use crate::{layout_to_screen_space, TuiDom}; +use crate::{layout::TaffyLayout, layout_to_screen_space}; /// Allows querying the layout of nodes after rendering. It will only provide a correct value after a node is rendered. /// Provided as a root context for all tui applictions. @@ -46,7 +47,7 @@ use crate::{layout_to_screen_space, TuiDom}; /// ``` #[derive(Clone)] pub struct Query { - pub(crate) rdom: Rc>, + pub(crate) rdom: Rc>, pub(crate) stretch: Arc>, } @@ -61,13 +62,13 @@ impl Query { } pub struct ElementRef<'a> { - inner: Ref<'a, TuiDom>, + inner: Ref<'a, RealDom>, stretch: MutexGuard<'a, Taffy>, id: ElementId, } impl<'a> ElementRef<'a> { - fn new(inner: Ref<'a, TuiDom>, stretch: MutexGuard<'a, Taffy>, id: ElementId) -> Self { + fn new(inner: Ref<'a, RealDom>, stretch: MutexGuard<'a, Taffy>, id: ElementId) -> Self { Self { inner, stretch, id } } @@ -85,7 +86,15 @@ impl<'a> ElementRef<'a> { pub fn layout(&self) -> Option { let layout = self .stretch - .layout(self.inner[self.id].state.layout.node.ok()?) + .layout( + self.inner + .get(self.id) + .unwrap() + .get::() + .unwrap() + .node + .ok()?, + ) .ok(); layout.map(|layout| Layout { order: layout.order, diff --git a/packages/tui/src/render.rs b/packages/tui/src/render.rs index c6d5c6923..372d26183 100644 --- a/packages/tui/src/render.rs +++ b/packages/tui/src/render.rs @@ -1,18 +1,24 @@ -use dioxus_native_core::tree::TreeView; +use dioxus_native_core::{real_dom::NodeImmutable, NodeRef, RealDom}; use std::io::Stdout; use taffy::{ geometry::Point, prelude::{Dimension, Layout, Size}, Taffy, }; -use tui::{backend::CrosstermBackend, layout::Rect, style::Color}; +use tui::{ + backend::CrosstermBackend, + layout::Rect, + style::{Color, Style}, +}; use crate::{ + focus::Focused, + layout::TaffyLayout, layout_to_screen_space, style::{RinkColor, RinkStyle}, - style_attributes::{BorderEdge, BorderStyle}, + style_attributes::{BorderEdge, BorderStyle, StyleModifier}, widget::{RinkBuffer, RinkCell, RinkWidget, WidgetWithContext}, - Config, TuiDom, TuiNode, + Config, }; const RADIUS_MULTIPLIER: [f32; 2] = [1.0, 0.5]; @@ -20,20 +26,22 @@ const RADIUS_MULTIPLIER: [f32; 2] = [1.0, 0.5]; pub(crate) fn render_vnode( frame: &mut tui::Frame>, layout: &Taffy, - rdom: &TuiDom, - node: &TuiNode, + rdom: &RealDom, + node: NodeRef, cfg: Config, parent_location: Point, ) { use dioxus_native_core::node::NodeType; - if let NodeType::Placeholder = &node.node_data.node_type { + if let NodeType::Placeholder = &node.node_type() { return; } let Layout { mut location, size, .. - } = layout.layout(node.state.layout.node.unwrap()).unwrap(); + } = layout + .layout(node.get::().unwrap().node.unwrap()) + .unwrap(); location.x += parent_location.x; location.y += parent_location.y; @@ -44,7 +52,7 @@ pub(crate) fn render_vnode( let width = layout_to_screen_space(fx + width).round() as u16 - x; let height = layout_to_screen_space(fy + height).round() as u16 - y; - match &node.node_data.node_type { + match node.node_type() { NodeType::Text(text) => { #[derive(Default)] struct Label<'a> { @@ -65,7 +73,7 @@ pub(crate) fn render_vnode( let label = Label { text, - style: node.state.style.core, + style: node.get::().unwrap().core, }; let area = Rect::new(x, y, width, height); @@ -82,15 +90,15 @@ pub(crate) fn render_vnode( frame.render_widget(WidgetWithContext::new(node, cfg), area); } - for c in rdom.children_ids(node.node_data.node_id).unwrap() { - render_vnode(frame, layout, rdom, &rdom[*c], cfg, location); + for c in node.children().unwrap() { + render_vnode(frame, layout, rdom, c, cfg, location); } } NodeType::Placeholder => unreachable!(), } } -impl RinkWidget for &TuiNode { +impl RinkWidget for NodeRef<'_> { fn render(self, area: Rect, mut buf: RinkBuffer<'_>) { use tui::symbols::line::*; @@ -275,10 +283,10 @@ impl RinkWidget for &TuiNode { for x in area.left()..area.right() { for y in area.top()..area.bottom() { let mut new_cell = RinkCell::default(); - if let Some(c) = self.state.style.core.bg { + if let Some(c) = self.get::().unwrap().core.bg { new_cell.bg = c; } - if self.state.focused { + if self.get::().unwrap().0 { new_cell.bg.alpha = 100; new_cell.bg.color = new_cell.bg.blend(Color::White); } @@ -286,7 +294,9 @@ impl RinkWidget for &TuiNode { } } - let borders = &self.state.style.modifier.borders; + let style = self.get::().unwrap(); + + let borders = &style.modifier.borders; let last_edge = &borders.left; let current_edge = &borders.top; @@ -303,7 +313,7 @@ impl RinkWidget for &TuiNode { (last_r * RADIUS_MULTIPLIER[0]) as u16, (last_r * RADIUS_MULTIPLIER[1]) as u16, ]; - let color = current_edge.color.or(self.state.style.core.fg); + let color = current_edge.color.or(style.core.fg); let mut new_cell = RinkCell::default(); if let Some(c) = color { new_cell.fg = c; @@ -338,7 +348,7 @@ impl RinkWidget for &TuiNode { (last_r * RADIUS_MULTIPLIER[0]) as u16, (last_r * RADIUS_MULTIPLIER[1]) as u16, ]; - let color = current_edge.color.or(self.state.style.core.fg); + let color = current_edge.color.or(style.core.fg); let mut new_cell = RinkCell::default(); if let Some(c) = color { new_cell.fg = c; @@ -373,7 +383,7 @@ impl RinkWidget for &TuiNode { (last_r * RADIUS_MULTIPLIER[0]) as u16, (last_r * RADIUS_MULTIPLIER[1]) as u16, ]; - let color = current_edge.color.or(self.state.style.core.fg); + let color = current_edge.color.or(style.core.fg); let mut new_cell = RinkCell::default(); if let Some(c) = color { new_cell.fg = c; @@ -408,7 +418,7 @@ impl RinkWidget for &TuiNode { (last_r * RADIUS_MULTIPLIER[0]) as u16, (last_r * RADIUS_MULTIPLIER[1]) as u16, ]; - let color = current_edge.color.or(self.state.style.core.fg); + let color = current_edge.color.or(style.core.fg); let mut new_cell = RinkCell::default(); if let Some(c) = color { new_cell.fg = c; diff --git a/packages/tui/src/style_attributes.rs b/packages/tui/src/style_attributes.rs index e6f5d5527..75b956ecd 100644 --- a/packages/tui/src/style_attributes.rs +++ b/packages/tui/src/style_attributes.rs @@ -32,10 +32,9 @@ use dioxus_native_core::{ layout_attributes::parse_value, node::OwnedAttributeView, - node_ref::{AttributeMask, NodeMask, NodeView}, - Pass, SendAnyMap, + node_ref::{AttributeMaskBuilder, NodeMaskBuilder, NodeView}, + Dependancy, Pass, SendAnyMap, }; -use dioxus_native_core_macro::sorted_str_slice; use taffy::prelude::*; use crate::style::{RinkColor, RinkStyle}; @@ -52,24 +51,17 @@ impl Pass for StyleModifier { type NodeDependencies = (); // todo: seperate each attribute into it's own class - const NODE_MASK: NodeMask = - NodeMask::new_with_attrs(AttributeMask::Static(SORTED_STYLE_ATTRS)).with_element(); + const NODE_MASK: NodeMaskBuilder = NodeMaskBuilder::new() + .with_attrs(AttributeMaskBuilder::Some(SORTED_STYLE_ATTRS)) + .with_element(); fn pass<'a>( &mut self, node_view: NodeView, - _: ::ElementBorrowed<'a>, - parent: Option< - ::ElementBorrowed<'a>, - >, - _: Option< - impl Iterator< - Item = ::ElementBorrowed< - 'a, - >, - >, - >, - _: &SendAnyMap, + node: ::ElementBorrowed<'a>, + parent: Option<::ElementBorrowed<'a>>, + children: Option::ElementBorrowed<'a>>>, + context: &SendAnyMap, ) -> bool { let mut new = StyleModifier::default(); if parent.is_some() { @@ -615,7 +607,7 @@ fn apply_transition(_name: &str, _value: &str, _style: &mut StyleModifier) { todo!() } -const SORTED_STYLE_ATTRS: &[&str] = &sorted_str_slice!([ +const SORTED_STYLE_ATTRS: &[&str] = &[ "animation", "animation-delay", "animation-direction", @@ -816,5 +808,5 @@ const SORTED_STYLE_ATTRS: &[&str] = &sorted_str_slice!([ "text-justify", "text-overflow", "text-shadow", - "text-transform" -]); + "text-transform", +];