mirror of
https://github.com/DioxusLabs/dioxus
synced 2024-11-23 20:53:06 +00:00
custom element test passing
This commit is contained in:
parent
43372c7609
commit
4e582d0374
10 changed files with 155 additions and 57 deletions
|
@ -224,14 +224,14 @@ pub fn partial_derive_state(_: TokenStream, input: TokenStream) -> TokenStream {
|
||||||
let get_parent_view = {
|
let get_parent_view = {
|
||||||
if parent_dependencies.is_empty() {
|
if parent_dependencies.is_empty() {
|
||||||
quote! {
|
quote! {
|
||||||
let raw_parent = tree.parent_id(id).map(|_| ());
|
let raw_parent = tree.parent_id_advanced(id, Self::TRAVERSE_SHADOW_DOM).map(|_| ());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let temps = (0..parent_dependencies.len())
|
let temps = (0..parent_dependencies.len())
|
||||||
.map(|i| format_ident!("__temp{}", i))
|
.map(|i| format_ident!("__temp{}", i))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
quote! {
|
quote! {
|
||||||
let raw_parent = tree.parent_id(id).and_then(|parent_id| {
|
let raw_parent = tree.parent_id_advanced(id, Self::TRAVERSE_SHADOW_DOM).and_then(|parent_id| {
|
||||||
let raw_parent: Option<(#(*const #parent_dependencies,)*)> = (#(&#parent_view,)*).get(parent_id).ok().map(|c| {
|
let raw_parent: Option<(#(*const #parent_dependencies,)*)> = (#(&#parent_view,)*).get(parent_id).ok().map(|c| {
|
||||||
let (#(#temps,)*) = c;
|
let (#(#temps,)*) = c;
|
||||||
(#(#temps as *const _,)*)
|
(#(#temps as *const _,)*)
|
||||||
|
@ -261,14 +261,14 @@ pub fn partial_derive_state(_: TokenStream, input: TokenStream) -> TokenStream {
|
||||||
let get_child_view = {
|
let get_child_view = {
|
||||||
if child_dependencies.is_empty() {
|
if child_dependencies.is_empty() {
|
||||||
quote! {
|
quote! {
|
||||||
let raw_children: Vec<_> = tree.children_ids(id).into_iter().map(|_| ()).collect();
|
let raw_children: Vec<_> = tree.children_ids_advanced(id, Self::TRAVERSE_SHADOW_DOM).into_iter().map(|_| ()).collect();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let temps = (0..child_dependencies.len())
|
let temps = (0..child_dependencies.len())
|
||||||
.map(|i| format_ident!("__temp{}", i))
|
.map(|i| format_ident!("__temp{}", i))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
quote! {
|
quote! {
|
||||||
let raw_children: Vec<_> = tree.children_ids(id).into_iter().filter_map(|id| {
|
let raw_children: Vec<_> = tree.children_ids_advanced(id, Self::TRAVERSE_SHADOW_DOM).into_iter().filter_map(|id| {
|
||||||
let raw_children: Option<(#(*const #child_dependencies,)*)> = (#(&#child_view,)*).get(id).ok().map(|c| {
|
let raw_children: Option<(#(*const #child_dependencies,)*)> = (#(&#child_view,)*).get(id).ok().map(|c| {
|
||||||
let (#(#temps,)*) = c;
|
let (#(#temps,)*) = c;
|
||||||
(#(#temps as *const _,)*)
|
(#(#temps as *const _,)*)
|
||||||
|
@ -336,7 +336,7 @@ pub fn partial_derive_state(_: TokenStream, input: TokenStream) -> TokenStream {
|
||||||
let (#(#split_views,)*) = data;
|
let (#(#split_views,)*) = data;
|
||||||
let tree = run_view.tree.clone();
|
let tree = run_view.tree.clone();
|
||||||
let node_types = run_view.node_type.clone();
|
let node_types = run_view.node_type.clone();
|
||||||
dioxus_native_core::prelude::run_pass(type_id, dependants.clone(), pass_direction, run_view, Self::TRAVERSE_SHADOW_DOM, |id, context| {
|
dioxus_native_core::prelude::run_pass(type_id, dependants.clone(), pass_direction, run_view, |id, context| {
|
||||||
let node_data: &NodeType<_> = node_types.get(id).unwrap_or_else(|err| panic!("Failed to get node type {:?}", err));
|
let node_data: &NodeType<_> = node_types.get(id).unwrap_or_else(|err| panic!("Failed to get node type {:?}", err));
|
||||||
// get all of the states from the tree view
|
// get all of the states from the tree view
|
||||||
// Safety: No node has itself as a parent or child.
|
// Safety: No node has itself as a parent or child.
|
||||||
|
|
|
@ -215,7 +215,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let _to_rerender = rdom.update_state(ctx);
|
let _to_rerender = rdom.update_state(ctx);
|
||||||
|
|
||||||
// render...
|
// render...
|
||||||
rdom.traverse_depth_first(|node| {
|
rdom.traverse_depth_first(true, |node| {
|
||||||
let indent = " ".repeat(node.height() as usize);
|
let indent = " ".repeat(node.height() as usize);
|
||||||
let color = *node.get::<TextColor>().unwrap();
|
let color = *node.get::<TextColor>().unwrap();
|
||||||
let size = *node.get::<Size>().unwrap();
|
let size = *node.get::<Size>().unwrap();
|
||||||
|
|
|
@ -160,7 +160,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let _to_rerender = rdom.update_state(ctx);
|
let _to_rerender = rdom.update_state(ctx);
|
||||||
|
|
||||||
// render...
|
// render...
|
||||||
rdom.traverse_depth_first(|node| {
|
rdom.traverse_depth_first(true, |node| {
|
||||||
let indent = " ".repeat(node.height() as usize);
|
let indent = " ".repeat(node.height() as usize);
|
||||||
let font_size = *node.get::<FontSize>().unwrap();
|
let font_size = *node.get::<FontSize>().unwrap();
|
||||||
let size = *node.get::<Size>().unwrap();
|
let size = *node.get::<Size>().unwrap();
|
||||||
|
|
|
@ -206,7 +206,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let _to_rerender = rdom.update_state(ctx);
|
let _to_rerender = rdom.update_state(ctx);
|
||||||
|
|
||||||
// render...
|
// render...
|
||||||
rdom.traverse_depth_first(|node| {
|
rdom.traverse_depth_first(true, |node| {
|
||||||
let indent = " ".repeat(node.height() as usize);
|
let indent = " ".repeat(node.height() as usize);
|
||||||
let color = *node.get::<TextColor>().unwrap();
|
let color = *node.get::<TextColor>().unwrap();
|
||||||
let size = *node.get::<Size>().unwrap();
|
let size = *node.get::<Size>().unwrap();
|
||||||
|
|
|
@ -234,7 +234,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let _to_rerender = rdom.update_state(ctx);
|
let _to_rerender = rdom.update_state(ctx);
|
||||||
|
|
||||||
// render...
|
// render...
|
||||||
rdom.traverse_depth_first(|node| {
|
rdom.traverse_depth_first(true, |node| {
|
||||||
let indent = " ".repeat(node.height() as usize);
|
let indent = " ".repeat(node.height() as usize);
|
||||||
let color = *node.get::<TextColor>().unwrap();
|
let color = *node.get::<TextColor>().unwrap();
|
||||||
let size = *node.get::<Size>().unwrap();
|
let size = *node.get::<Size>().unwrap();
|
||||||
|
|
|
@ -153,6 +153,7 @@ pub trait State<V: FromAnyValue + Send + Sync = ()>: Any + Send + Sync {
|
||||||
dependants: Default::default(),
|
dependants: Default::default(),
|
||||||
mask: node_mask,
|
mask: node_mask,
|
||||||
pass_direction: pass_direction::<V, Self>(),
|
pass_direction: pass_direction::<V, Self>(),
|
||||||
|
enter_shadow_dom: Self::TRAVERSE_SHADOW_DOM,
|
||||||
workload: Self::workload_system,
|
workload: Self::workload_system,
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
}
|
}
|
||||||
|
@ -193,7 +194,6 @@ pub fn run_pass<V: FromAnyValue + Send + Sync>(
|
||||||
dependants: Arc<Dependants>,
|
dependants: Arc<Dependants>,
|
||||||
pass_direction: PassDirection,
|
pass_direction: PassDirection,
|
||||||
view: RunPassView<V>,
|
view: RunPassView<V>,
|
||||||
enter_shadow_dom: bool,
|
|
||||||
mut update_node: impl FnMut(NodeId, &SendAnyMap) -> bool,
|
mut update_node: impl FnMut(NodeId, &SendAnyMap) -> bool,
|
||||||
) {
|
) {
|
||||||
let RunPassView {
|
let RunPassView {
|
||||||
|
@ -232,28 +232,42 @@ pub fn run_pass<V: FromAnyValue + Send + Sync>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
pub(crate) struct Dependant {
|
||||||
|
pub(crate) type_id: TypeId,
|
||||||
|
pub(crate) enter_shadow_dom: bool,
|
||||||
|
}
|
||||||
|
|
||||||
/// The states that depend on this state
|
/// The states that depend on this state
|
||||||
#[derive(Default, Debug, Clone, PartialEq, Eq)]
|
#[derive(Default, Debug, Clone, PartialEq, Eq)]
|
||||||
pub struct Dependants {
|
pub struct Dependants {
|
||||||
/// The states in the parent direction that should be invalidated when this state is invalidated
|
/// The states in the parent direction that should be invalidated when this state is invalidated
|
||||||
pub parent: Vec<TypeId>,
|
pub(crate) parent: Vec<Dependant>,
|
||||||
/// The states in the child direction that should be invalidated when this state is invalidated
|
/// The states in the child direction that should be invalidated when this state is invalidated
|
||||||
pub child: Vec<TypeId>,
|
pub(crate) child: Vec<Dependant>,
|
||||||
/// The states in the node direction that should be invalidated when this state is invalidated
|
/// The states in the node direction that should be invalidated when this state is invalidated
|
||||||
pub node: Vec<TypeId>,
|
pub(crate) node: Vec<TypeId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Dependants {
|
impl Dependants {
|
||||||
fn mark_dirty(&self, dirty: &DirtyNodeStates, id: NodeId, tree: &impl TreeRef, height: u16) {
|
fn mark_dirty(&self, dirty: &DirtyNodeStates, id: NodeId, tree: &impl TreeRef, height: u16) {
|
||||||
for dependant in &self.child {
|
for &Dependant {
|
||||||
for id in tree.children_ids(id) {
|
type_id,
|
||||||
dirty.insert(*dependant, id, height + 1);
|
enter_shadow_dom,
|
||||||
|
} in &self.child
|
||||||
|
{
|
||||||
|
for id in tree.children_ids_advanced(id, enter_shadow_dom) {
|
||||||
|
dirty.insert(type_id, id, height + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for dependant in &self.parent {
|
for &Dependant {
|
||||||
if let Some(id) = tree.parent_id(id) {
|
type_id,
|
||||||
dirty.insert(*dependant, id, height - 1);
|
enter_shadow_dom,
|
||||||
|
} in &self.parent
|
||||||
|
{
|
||||||
|
if let Some(id) = tree.parent_id_advanced(id, enter_shadow_dom) {
|
||||||
|
dirty.insert(type_id, id, height - 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -273,6 +287,7 @@ pub struct TypeErasedState<V: FromAnyValue + Send = ()> {
|
||||||
pub(crate) mask: NodeMask,
|
pub(crate) mask: NodeMask,
|
||||||
pub(crate) workload: fn(TypeId, Arc<Dependants>, PassDirection) -> WorkloadSystem,
|
pub(crate) workload: fn(TypeId, Arc<Dependants>, PassDirection) -> WorkloadSystem,
|
||||||
pub(crate) pass_direction: PassDirection,
|
pub(crate) pass_direction: PassDirection,
|
||||||
|
pub(crate) enter_shadow_dom: bool,
|
||||||
phantom: PhantomData<V>,
|
phantom: PhantomData<V>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ use crate::node::{
|
||||||
};
|
};
|
||||||
use crate::node_ref::{NodeMask, NodeMaskBuilder};
|
use crate::node_ref::{NodeMask, NodeMaskBuilder};
|
||||||
use crate::node_watcher::{AttributeWatcher, NodeWatcher};
|
use crate::node_watcher::{AttributeWatcher, NodeWatcher};
|
||||||
use crate::passes::{DirtyNodeStates, PassDirection, TypeErasedState};
|
use crate::passes::{Dependant, DirtyNodeStates, PassDirection, TypeErasedState};
|
||||||
use crate::prelude::AttributeMaskBuilder;
|
use crate::prelude::AttributeMaskBuilder;
|
||||||
use crate::tree::{TreeMut, TreeMutView, TreeRef, TreeRefView};
|
use crate::tree::{TreeMut, TreeMutView, TreeRef, TreeRefView};
|
||||||
use crate::NodeId;
|
use crate::NodeId;
|
||||||
|
@ -128,19 +128,25 @@ impl<V: FromAnyValue + Send + Sync> RealDom<V> {
|
||||||
let (current, before) = before.split_last_mut().unwrap();
|
let (current, before) = before.split_last_mut().unwrap();
|
||||||
for state in before.iter_mut().chain(after.iter_mut()) {
|
for state in before.iter_mut().chain(after.iter_mut()) {
|
||||||
let dependants = Arc::get_mut(&mut state.dependants).unwrap();
|
let dependants = Arc::get_mut(&mut state.dependants).unwrap();
|
||||||
|
|
||||||
|
let current_dependant = Dependant {
|
||||||
|
type_id: current.this_type_id,
|
||||||
|
enter_shadow_dom: current.enter_shadow_dom,
|
||||||
|
};
|
||||||
|
|
||||||
// If this node depends on the other state as a parent, then the other state should update its children of the current type when it is invalidated
|
// If this node depends on the other state as a parent, then the other state should update its children of the current type when it is invalidated
|
||||||
if current
|
if current
|
||||||
.parent_dependancies_ids
|
.parent_dependancies_ids
|
||||||
.contains(&state.this_type_id)
|
.contains(&state.this_type_id)
|
||||||
&& !dependants.child.contains(¤t.this_type_id)
|
&& !dependants.child.contains(¤t_dependant)
|
||||||
{
|
{
|
||||||
dependants.child.push(current.this_type_id);
|
dependants.child.push(current_dependant);
|
||||||
}
|
}
|
||||||
// If this node depends on the other state as a child, then the other state should update its parent of the current type when it is invalidated
|
// If this node depends on the other state as a child, then the other state should update its parent of the current type when it is invalidated
|
||||||
if current.child_dependancies_ids.contains(&state.this_type_id)
|
if current.child_dependancies_ids.contains(&state.this_type_id)
|
||||||
&& !dependants.parent.contains(¤t.this_type_id)
|
&& !dependants.parent.contains(¤t_dependant)
|
||||||
{
|
{
|
||||||
dependants.parent.push(current.this_type_id);
|
dependants.parent.push(current_dependant);
|
||||||
}
|
}
|
||||||
// If this node depends on the other state as a sibling, then the other state should update its siblings of the current type when it is invalidated
|
// If this node depends on the other state as a sibling, then the other state should update its siblings of the current type when it is invalidated
|
||||||
if current.node_dependancies_ids.contains(&state.this_type_id)
|
if current.node_dependancies_ids.contains(&state.this_type_id)
|
||||||
|
@ -151,15 +157,19 @@ impl<V: FromAnyValue + Send + Sync> RealDom<V> {
|
||||||
}
|
}
|
||||||
// If the current state depends on itself, then it should update itself when it is invalidated
|
// If the current state depends on itself, then it should update itself when it is invalidated
|
||||||
let dependants = Arc::get_mut(&mut current.dependants).unwrap();
|
let dependants = Arc::get_mut(&mut current.dependants).unwrap();
|
||||||
|
let current_dependant = Dependant {
|
||||||
|
type_id: current.this_type_id,
|
||||||
|
enter_shadow_dom: current.enter_shadow_dom,
|
||||||
|
};
|
||||||
match current.pass_direction {
|
match current.pass_direction {
|
||||||
PassDirection::ChildToParent => {
|
PassDirection::ChildToParent => {
|
||||||
if !dependants.parent.contains(¤t.this_type_id) {
|
if !dependants.parent.contains(¤t_dependant) {
|
||||||
dependants.parent.push(current.this_type_id);
|
dependants.parent.push(current_dependant);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PassDirection::ParentToChild => {
|
PassDirection::ParentToChild => {
|
||||||
if !dependants.child.contains(¤t.this_type_id) {
|
if !dependants.child.contains(¤t_dependant) {
|
||||||
dependants.child.push(current.this_type_id);
|
dependants.child.push(current_dependant);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
@ -371,27 +381,27 @@ impl<V: FromAnyValue + Send + Sync> RealDom<V> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Traverses the dom in a depth first manner, calling the provided function on each node.
|
/// Traverses the dom in a depth first manner, calling the provided function on each node.
|
||||||
pub fn traverse_depth_first(&self, mut f: impl FnMut(NodeRef<V>)) {
|
pub fn traverse_depth_first(&self, enter_shadow_doms: bool, mut f: impl FnMut(NodeRef<V>)) {
|
||||||
let mut stack = vec![self.root_id()];
|
let mut stack = vec![self.root_id()];
|
||||||
let tree = self.tree_ref();
|
let tree = self.tree_ref();
|
||||||
while let Some(id) = stack.pop() {
|
while let Some(id) = stack.pop() {
|
||||||
if let Some(node) = self.get(id) {
|
if let Some(node) = self.get(id) {
|
||||||
f(node);
|
f(node);
|
||||||
let children = tree.children_ids(id);
|
let children = tree.children_ids_advanced(id, enter_shadow_doms);
|
||||||
stack.extend(children.iter().copied().rev());
|
stack.extend(children.iter().copied().rev());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Traverses the dom in a breadth first manner, calling the provided function on each node.
|
/// Traverses the dom in a breadth first manner, calling the provided function on each node.
|
||||||
pub fn traverse_breadth_first(&self, mut f: impl FnMut(NodeRef<V>)) {
|
pub fn traverse_breadth_first(&self, enter_shadow_doms: bool, mut f: impl FnMut(NodeRef<V>)) {
|
||||||
let mut queue = VecDeque::new();
|
let mut queue = VecDeque::new();
|
||||||
queue.push_back(self.root_id());
|
queue.push_back(self.root_id());
|
||||||
let tree = self.tree_ref();
|
let tree = self.tree_ref();
|
||||||
while let Some(id) = queue.pop_front() {
|
while let Some(id) = queue.pop_front() {
|
||||||
if let Some(node) = self.get(id) {
|
if let Some(node) = self.get(id) {
|
||||||
f(node);
|
f(node);
|
||||||
let children = tree.children_ids(id);
|
let children = tree.children_ids_advanced(id, enter_shadow_doms);
|
||||||
for id in children {
|
for id in children {
|
||||||
queue.push_back(id);
|
queue.push_back(id);
|
||||||
}
|
}
|
||||||
|
@ -400,11 +410,15 @@ impl<V: FromAnyValue + Send + Sync> RealDom<V> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Traverses the dom in a depth first manner mutably, calling the provided function on each node.
|
/// Traverses the dom in a depth first manner mutably, calling the provided function on each node.
|
||||||
pub fn traverse_depth_first_mut(&mut self, mut f: impl FnMut(NodeMut<V>)) {
|
pub fn traverse_depth_first_mut(
|
||||||
|
&mut self,
|
||||||
|
enter_shadow_doms: bool,
|
||||||
|
mut f: impl FnMut(NodeMut<V>),
|
||||||
|
) {
|
||||||
let mut stack = vec![self.root_id()];
|
let mut stack = vec![self.root_id()];
|
||||||
while let Some(id) = stack.pop() {
|
while let Some(id) = stack.pop() {
|
||||||
let tree = self.tree_ref();
|
let tree = self.tree_ref();
|
||||||
let mut children = tree.children_ids(id);
|
let mut children = tree.children_ids_advanced(id, enter_shadow_doms);
|
||||||
drop(tree);
|
drop(tree);
|
||||||
children.reverse();
|
children.reverse();
|
||||||
if let Some(node) = self.get_mut(id) {
|
if let Some(node) = self.get_mut(id) {
|
||||||
|
@ -416,12 +430,16 @@ impl<V: FromAnyValue + Send + Sync> RealDom<V> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Traverses the dom in a breadth first manner mutably, calling the provided function on each node.
|
/// Traverses the dom in a breadth first manner mutably, calling the provided function on each node.
|
||||||
pub fn traverse_breadth_first_mut(&mut self, mut f: impl FnMut(NodeMut<V>)) {
|
pub fn traverse_breadth_first_mut(
|
||||||
|
&mut self,
|
||||||
|
enter_shadow_doms: bool,
|
||||||
|
mut f: impl FnMut(NodeMut<V>),
|
||||||
|
) {
|
||||||
let mut queue = VecDeque::new();
|
let mut queue = VecDeque::new();
|
||||||
queue.push_back(self.root_id());
|
queue.push_back(self.root_id());
|
||||||
while let Some(id) = queue.pop_front() {
|
while let Some(id) = queue.pop_front() {
|
||||||
let tree = self.tree_ref();
|
let tree = self.tree_ref();
|
||||||
let children = tree.children_ids(id);
|
let children = tree.children_ids_advanced(id, enter_shadow_doms);
|
||||||
drop(tree);
|
drop(tree);
|
||||||
if let Some(node) = self.get_mut(id) {
|
if let Some(node) = self.get_mut(id) {
|
||||||
f(node);
|
f(node);
|
||||||
|
|
|
@ -11,8 +11,6 @@ pub struct ShadowTree {
|
||||||
pub shadow_roots: Vec<NodeId>,
|
pub shadow_roots: Vec<NodeId>,
|
||||||
/// The node that children of the super tree should be inserted under.
|
/// The node that children of the super tree should be inserted under.
|
||||||
pub slot: Option<NodeId>,
|
pub slot: Option<NodeId>,
|
||||||
/// The node in the super tree that the shadow_tree is attached to.
|
|
||||||
pub super_tree_root: NodeId,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A node in a tree.
|
/// A node in a tree.
|
||||||
|
@ -35,8 +33,43 @@ pub type TreeMutView<'a> = (EntitiesViewMut<'a>, ViewMut<'a, Node>);
|
||||||
|
|
||||||
/// A immutable view of a tree.
|
/// A immutable view of a tree.
|
||||||
pub trait TreeRef {
|
pub trait TreeRef {
|
||||||
|
/// Get the id of the parent of the current node, if enter_shadow_dom is true and the current node is a shadow root, the node the shadow root is attached to will be returned
|
||||||
|
#[inline]
|
||||||
|
fn parent_id_advanced(&self, id: NodeId, enter_shadow_dom: bool) -> Option<NodeId> {
|
||||||
|
// If this node is the root of a shadow_tree, return the node the shadow_tree is attached
|
||||||
|
let light_tree_root = self.light_tree_root(id);
|
||||||
|
match (light_tree_root, enter_shadow_dom) {
|
||||||
|
(Some(id), true) => Some(id),
|
||||||
|
_ => {
|
||||||
|
let parent_id = self.parent_id(id);
|
||||||
|
if enter_shadow_dom {
|
||||||
|
// If this node is attached via a slot, return the slot as the parent instead of the light tree parent
|
||||||
|
parent_id.map(|id| {
|
||||||
|
self.shadow_tree(id)
|
||||||
|
.and_then(|tree| tree.slot)
|
||||||
|
.unwrap_or(id)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
parent_id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
/// The parent id of the node.
|
/// The parent id of the node.
|
||||||
fn parent_id(&self, id: NodeId) -> Option<NodeId>;
|
fn parent_id(&self, id: NodeId) -> Option<NodeId>;
|
||||||
|
/// Get the ids of the children of the current node, if enter_shadow_dom is true and the current node is a shadow slot, the ids of the nodes under the node the shadow slot is attached to will be returned
|
||||||
|
#[inline]
|
||||||
|
fn children_ids_advanced(&self, id: NodeId, enter_shadow_dom: bool) -> Vec<NodeId> {
|
||||||
|
let shadow_tree = self.shadow_tree(id);
|
||||||
|
let slot_of_light_tree = self.slot_for_light_tree(id);
|
||||||
|
match (shadow_tree, slot_of_light_tree, enter_shadow_dom) {
|
||||||
|
// If this node is a shadow root, return the shadow roots
|
||||||
|
(Some(tree), _, true) => tree.shadow_roots.clone(),
|
||||||
|
// If this node is a slot, return the children of the node the slot is attached to
|
||||||
|
(None, Some(id), true) => self.children_ids(id),
|
||||||
|
_ => self.children_ids(id),
|
||||||
|
}
|
||||||
|
}
|
||||||
/// The children ids of the node.
|
/// The children ids of the node.
|
||||||
fn children_ids(&self, id: NodeId) -> Vec<NodeId>;
|
fn children_ids(&self, id: NodeId) -> Vec<NodeId>;
|
||||||
/// The shadow tree tree under the node.
|
/// The shadow tree tree under the node.
|
||||||
|
@ -229,7 +262,6 @@ impl<'a> TreeMut for TreeMutView<'a> {
|
||||||
let light_root_height;
|
let light_root_height;
|
||||||
{
|
{
|
||||||
let shadow_tree = ShadowTree {
|
let shadow_tree = ShadowTree {
|
||||||
super_tree_root: id,
|
|
||||||
shadow_roots: shadow_roots.clone(),
|
shadow_roots: shadow_roots.clone(),
|
||||||
slot,
|
slot,
|
||||||
};
|
};
|
||||||
|
@ -251,6 +283,7 @@ impl<'a> TreeMut for TreeMutView<'a> {
|
||||||
|
|
||||||
// Now that we have created the shadow_tree, we need to update the height of the shadow_tree roots
|
// Now that we have created the shadow_tree, we need to update the height of the shadow_tree roots
|
||||||
for root in shadow_roots {
|
for root in shadow_roots {
|
||||||
|
(&mut self.1).get(root).unwrap().light_tree_root = Some(id);
|
||||||
set_height(self, root, light_root_height + 1);
|
set_height(self, root, light_root_height + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -319,7 +352,7 @@ fn set_height(tree: &mut TreeMutView<'_>, node: NodeId, height: u16) {
|
||||||
if let Some(shadow_tree) = shadow_tree {
|
if let Some(shadow_tree) = shadow_tree {
|
||||||
// Set the height of the shadow_tree roots
|
// Set the height of the shadow_tree roots
|
||||||
for &shadow_root in &shadow_tree.shadow_roots {
|
for &shadow_root in &shadow_tree.shadow_roots {
|
||||||
set_height(tree, shadow_root, height);
|
set_height(tree, shadow_root, height + 1);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Otherwise, we just set the height of the children to be one more than the height of the parent
|
// Otherwise, we just set the height of the children to be one more than the height of the parent
|
||||||
|
@ -362,17 +395,17 @@ impl<'a> TreeRef for TreeMutView<'a> {
|
||||||
|
|
||||||
fn shadow_tree(&self, id: NodeId) -> Option<&ShadowTree> {
|
fn shadow_tree(&self, id: NodeId) -> Option<&ShadowTree> {
|
||||||
let node_data = &self.1;
|
let node_data = &self.1;
|
||||||
node_data.get(id).unwrap().child_subtree.as_ref()
|
node_data.get(id).ok()?.child_subtree.as_ref()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn slot_for_light_tree(&self, id: NodeId) -> Option<NodeId> {
|
fn slot_for_light_tree(&self, id: NodeId) -> Option<NodeId> {
|
||||||
let node_data = &self.1;
|
let node_data = &self.1;
|
||||||
node_data.get(id).unwrap().slot_for_light_tree
|
node_data.get(id).ok()?.slot_for_light_tree
|
||||||
}
|
}
|
||||||
|
|
||||||
fn light_tree_root(&self, id: NodeId) -> Option<NodeId> {
|
fn light_tree_root(&self, id: NodeId) -> Option<NodeId> {
|
||||||
let node_data = &self.1;
|
let node_data = &self.1;
|
||||||
node_data.get(id).unwrap().light_tree_root
|
node_data.get(id).ok()?.light_tree_root
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -146,7 +146,7 @@ macro_rules! test_state{
|
||||||
dioxus_state.apply_mutations(&mut dom, mutations);
|
dioxus_state.apply_mutations(&mut dom, mutations);
|
||||||
dom.update_state(SendAnyMap::new());
|
dom.update_state(SendAnyMap::new());
|
||||||
|
|
||||||
dom.traverse_depth_first(|n| {
|
dom.traverse_depth_first(false, |n| {
|
||||||
$(
|
$(
|
||||||
assert_eq!(n.get::<$state>().unwrap().0, 1);
|
assert_eq!(n.get::<$state>().unwrap().0, 1);
|
||||||
)*
|
)*
|
||||||
|
|
|
@ -23,14 +23,26 @@ impl State for ColorState {
|
||||||
|
|
||||||
fn update<'a>(
|
fn update<'a>(
|
||||||
&mut self,
|
&mut self,
|
||||||
_: NodeView,
|
view: NodeView,
|
||||||
_: <Self::NodeDependencies as Dependancy>::ElementBorrowed<'a>,
|
_: <Self::NodeDependencies as Dependancy>::ElementBorrowed<'a>,
|
||||||
parent: Option<<Self::ParentDependencies as Dependancy>::ElementBorrowed<'a>>,
|
parent: Option<<Self::ParentDependencies as Dependancy>::ElementBorrowed<'a>>,
|
||||||
_: Vec<<Self::ChildDependencies as Dependancy>::ElementBorrowed<'a>>,
|
_: Vec<<Self::ChildDependencies as Dependancy>::ElementBorrowed<'a>>,
|
||||||
_: &SendAnyMap,
|
_: &SendAnyMap,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
if let Some((parent,)) = parent {
|
if let Some(size) = view
|
||||||
self.color = parent.color;
|
.attributes()
|
||||||
|
.into_iter()
|
||||||
|
.flatten()
|
||||||
|
.find(|attr| attr.attribute.name == "color")
|
||||||
|
{
|
||||||
|
self.color = size
|
||||||
|
.value
|
||||||
|
.as_float()
|
||||||
|
.or_else(|| size.value.as_int().map(|i| i as f64))
|
||||||
|
.or_else(|| size.value.as_text().and_then(|i| i.parse().ok()))
|
||||||
|
.unwrap_or(0.0) as usize;
|
||||||
|
} else if let Some((parent,)) = parent {
|
||||||
|
*self = *parent;
|
||||||
}
|
}
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
@ -74,11 +86,6 @@ impl State for LayoutState {
|
||||||
_: Vec<<Self::ChildDependencies as Dependancy>::ElementBorrowed<'a>>,
|
_: Vec<<Self::ChildDependencies as Dependancy>::ElementBorrowed<'a>>,
|
||||||
_: &SendAnyMap,
|
_: &SendAnyMap,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
println!(
|
|
||||||
"Updating layout state @{:?} {:?}",
|
|
||||||
parent.as_ref().map(|(p,)| p.size),
|
|
||||||
view.node_id()
|
|
||||||
);
|
|
||||||
if let Some(size) = view
|
if let Some(size) = view
|
||||||
.attributes()
|
.attributes()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
@ -93,7 +100,7 @@ impl State for LayoutState {
|
||||||
.unwrap_or(0.0) as usize;
|
.unwrap_or(0.0) as usize;
|
||||||
} else if let Some((parent,)) = parent {
|
} else if let Some((parent,)) = parent {
|
||||||
if parent.size > 0 {
|
if parent.size > 0 {
|
||||||
self.size -= 1;
|
self.size = parent.size - 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
true
|
true
|
||||||
|
@ -130,7 +137,7 @@ mod dioxus_elements {
|
||||||
$(#[$attr])*
|
$(#[$attr])*
|
||||||
pub struct $name;
|
pub struct $name;
|
||||||
|
|
||||||
#[allow(non_upper_case_globals)]
|
#[allow(non_upper_case_globals, unused)]
|
||||||
impl $name {
|
impl $name {
|
||||||
pub const TAG_NAME: &'static str = stringify!($name);
|
pub const TAG_NAME: &'static str = stringify!($name);
|
||||||
pub const NAME_SPACE: Option<&'static str> = None;
|
pub const NAME_SPACE: Option<&'static str> = None;
|
||||||
|
@ -152,10 +159,14 @@ mod dioxus_elements {
|
||||||
builder_constructors! {
|
builder_constructors! {
|
||||||
customelementslot {
|
customelementslot {
|
||||||
size: attr,
|
size: attr,
|
||||||
|
color: attr,
|
||||||
};
|
};
|
||||||
customelementnoslot {
|
customelementnoslot {
|
||||||
|
size: attr,
|
||||||
|
color: attr,
|
||||||
};
|
};
|
||||||
testing132 {
|
testing132 {
|
||||||
|
color: attr,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -253,6 +264,7 @@ fn custom_elements_work() {
|
||||||
cx.render(rsx! {
|
cx.render(rsx! {
|
||||||
customelementslot {
|
customelementslot {
|
||||||
size: "{count}",
|
size: "{count}",
|
||||||
|
color: "1",
|
||||||
customelementslot {
|
customelementslot {
|
||||||
testing132 {}
|
testing132 {}
|
||||||
}
|
}
|
||||||
|
@ -277,7 +289,7 @@ fn custom_elements_work() {
|
||||||
let ctx = SendAnyMap::new();
|
let ctx = SendAnyMap::new();
|
||||||
rdom.update_state(ctx);
|
rdom.update_state(ctx);
|
||||||
|
|
||||||
for _ in 0..10 {
|
for i in 0..10usize {
|
||||||
dom.wait_for_work().await;
|
dom.wait_for_work().await;
|
||||||
|
|
||||||
let mutations = dom.render_immediate();
|
let mutations = dom.render_immediate();
|
||||||
|
@ -287,13 +299,33 @@ fn custom_elements_work() {
|
||||||
rdom.update_state(ctx);
|
rdom.update_state(ctx);
|
||||||
|
|
||||||
// render...
|
// render...
|
||||||
rdom.traverse_depth_first(|node| {
|
rdom.traverse_depth_first(true, |node| {
|
||||||
let node_type = &*node.node_type();
|
let node_type = &*node.node_type();
|
||||||
let indent = " ".repeat(node.height() as usize);
|
let height = node.height() as usize;
|
||||||
|
let indent = " ".repeat(height);
|
||||||
let color = *node.get::<ColorState>().unwrap();
|
let color = *node.get::<ColorState>().unwrap();
|
||||||
let size = *node.get::<LayoutState>().unwrap();
|
let size = *node.get::<LayoutState>().unwrap();
|
||||||
let id = node.id();
|
let id = node.id();
|
||||||
println!("{indent}{id:?} {color:?} {size:?} {node_type:?}");
|
println!("{indent}{id:?} {color:?} {size:?} {node_type:?}");
|
||||||
|
match node_type {
|
||||||
|
NodeType::Element(el) => {
|
||||||
|
match el.tag.as_str() {
|
||||||
|
// the color should bubble up from customelementslot
|
||||||
|
"testing132" | "customelementslot" => {
|
||||||
|
assert_eq!(color.color, 1);
|
||||||
|
}
|
||||||
|
// the color of the light dom should not effect the color of the shadow dom, so the color of divs in the shadow dom should be 0
|
||||||
|
"div" => {
|
||||||
|
assert_eq!(color.color, 0);
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
if el.tag != "Root" {
|
||||||
|
assert_eq!(size.size, (i + 2).saturating_sub(height));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue