finish shadow dom docs
This commit is contained in:
1 parent
baeb4251ba
commit
9877b0f0b1
11 files changed
+123
-69
No files matched your search
@@ -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(true, |node| {
|
rdom.traverse_depth_first_advanced(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(true, |node| {
|
rdom.traverse_depth_first_advanced(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(true, |node| {
|
rdom.traverse_depth_first_advanced(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(true, |node| {
|
rdom.traverse_depth_first_advanced(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();
|
||||||
|
|||||||
@@ -1,5 +1,10 @@
|
|||||||
//! A custom element is a controlled element that renders to a shadow DOM.
|
//! A custom element is a controlled element that renders to a shadow DOM. This allows you to create elements that act like widgets without relying on a specific framework.
|
||||||
//! Each custom element is registered with a element name
|
//!
|
||||||
|
//! Each custom element is registered with a element name and namespace with [`RealDom::register_custom_element`] or [`RealDom::register_custom_element_with_factory`]. Once registered, they will be created automatically when the element is added to the DOM.
|
||||||
|
|
||||||
|
// Used in doc links
|
||||||
|
#[allow(unused)]
|
||||||
|
use crate::real_dom::RealDom;
|
||||||
|
|
||||||
use std::sync::{Arc, RwLock};
|
use std::sync::{Arc, RwLock};
|
||||||
|
|
||||||
@@ -48,22 +53,22 @@ impl<V: FromAnyValue + Send + Sync> CustomElementRegistry<V> {
|
|||||||
};
|
};
|
||||||
if let Some((tag, ns)) = element_tag {
|
if let Some((tag, ns)) = element_tag {
|
||||||
if let Some(builder) = self.builders.get(&(tag.as_str(), ns.as_deref())) {
|
if let Some(builder) = self.builders.get(&(tag.as_str(), ns.as_deref())) {
|
||||||
let boxed_widget = { (builder.create)(node.reborrow()) };
|
let boxed_custom_element = { (builder.create)(node.reborrow()) };
|
||||||
|
|
||||||
let shadow_roots = boxed_widget.roots();
|
let shadow_roots = boxed_custom_element.roots();
|
||||||
|
|
||||||
let light_id = node.id();
|
let light_id = node.id();
|
||||||
node.real_dom_mut().tree_mut().create_subtree(
|
node.real_dom_mut().tree_mut().create_subtree(
|
||||||
light_id,
|
light_id,
|
||||||
shadow_roots,
|
shadow_roots,
|
||||||
boxed_widget.slot(),
|
boxed_custom_element.slot(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let boxed_widget = CustomElementManager {
|
let boxed_custom_element = CustomElementManager {
|
||||||
inner: Arc::new(RwLock::new(boxed_widget)),
|
inner: Arc::new(RwLock::new(boxed_custom_element)),
|
||||||
};
|
};
|
||||||
|
|
||||||
node.insert(boxed_widget);
|
node.insert(boxed_custom_element);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -73,40 +78,49 @@ struct CustomElementBuilder<V: FromAnyValue + Send + Sync> {
|
|||||||
create: fn(NodeMut<V>) -> Box<dyn CustomElementUpdater<V>>,
|
create: fn(NodeMut<V>) -> Box<dyn CustomElementUpdater<V>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A controlled element that renders to a shadow DOM
|
/// A controlled element that renders to a shadow DOM.
|
||||||
|
///
|
||||||
|
/// Register with [`RealDom::register_custom_element`]
|
||||||
|
///
|
||||||
|
/// This is a simplified custom element trait for elements that can create themselves. For more granular control, implement [`CustomElementFactory`] and [`CustomElementUpdater`] instead.
|
||||||
pub trait CustomElement<V: FromAnyValue + Send + Sync = ()>: Send + Sync + 'static {
|
pub trait CustomElement<V: FromAnyValue + Send + Sync = ()>: Send + Sync + 'static {
|
||||||
/// The tag the widget is registered under.
|
/// The tag of the element
|
||||||
const NAME: &'static str;
|
const NAME: &'static str;
|
||||||
|
|
||||||
/// The namespace the widget is registered under.
|
/// The namespace of the element
|
||||||
const NAMESPACE: Option<&'static str> = None;
|
const NAMESPACE: Option<&'static str> = None;
|
||||||
|
|
||||||
/// Create a new widget *without mounting* it.
|
/// Create a new element *without mounting* it.
|
||||||
fn create(node: NodeMut<V>) -> Self;
|
/// The node passed in is the light DOM node. The element should not modify the light DOM node, but it can get the [`NodeMut::real_dom_mut`] from the node to create new nodes.
|
||||||
|
fn create(light_root: NodeMut<V>) -> Self;
|
||||||
|
|
||||||
/// The root node of the widget. This must be static once the element is created.
|
/// The root node of the custom element. These roots must be not change once the element is created.
|
||||||
fn roots(&self) -> Vec<NodeId>;
|
fn roots(&self) -> Vec<NodeId>;
|
||||||
|
|
||||||
/// The slot to render children of the element into. This must be static once the element is created.
|
/// The slot to render children of the element into. The slot must be not change once the element is created.
|
||||||
fn slot(&self) -> Option<NodeId> {
|
fn slot(&self) -> Option<NodeId> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Called when the attributes of the widget are changed.
|
/// Update the custom element's shadow tree with the new attributes.
|
||||||
|
/// Called when the attributes of the custom element are changed.
|
||||||
fn attributes_changed(&mut self, light_node: NodeMut<V>, attributes: &AttributeMask);
|
fn attributes_changed(&mut self, light_node: NodeMut<V>, attributes: &AttributeMask);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A factory for creating widgets
|
/// A factory for creating custom elements
|
||||||
|
///
|
||||||
|
/// Register with [`RealDom::register_custom_element_with_factory`]
|
||||||
pub trait CustomElementFactory<W: CustomElementUpdater<V>, V: FromAnyValue + Send + Sync = ()>:
|
pub trait CustomElementFactory<W: CustomElementUpdater<V>, V: FromAnyValue + Send + Sync = ()>:
|
||||||
Send + Sync + 'static
|
Send + Sync + 'static
|
||||||
{
|
{
|
||||||
/// The tag the widget is registered under.
|
/// The tag of the element
|
||||||
const NAME: &'static str;
|
const NAME: &'static str;
|
||||||
|
|
||||||
/// The namespace the widget is registered under.
|
/// The namespace of the element
|
||||||
const NAMESPACE: Option<&'static str> = None;
|
const NAMESPACE: Option<&'static str> = None;
|
||||||
|
|
||||||
/// Create a new widget.
|
/// Create a new element *without mounting* it.
|
||||||
|
/// The node passed in is the light DOM node. The element should not modify the light DOM node, but it can get the [`NodeMut::real_dom_mut`] from the node to create new nodes.
|
||||||
fn create(dom: NodeMut<V>) -> W;
|
fn create(dom: NodeMut<V>) -> W;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,16 +134,19 @@ impl<W: CustomElement<V>, V: FromAnyValue + Send + Sync> CustomElementFactory<W,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A trait for updating widgets
|
/// A trait for updating custom elements
|
||||||
pub trait CustomElementUpdater<V: FromAnyValue + Send + Sync = ()>: Send + Sync + 'static {
|
pub trait CustomElementUpdater<V: FromAnyValue + Send + Sync = ()>: Send + Sync + 'static {
|
||||||
/// Called when the attributes of the widget are changed.
|
/// Update the custom element's shadow tree with the new attributes.
|
||||||
|
/// Called when the attributes of the custom element are changed.
|
||||||
fn attributes_changed(&mut self, light_root: NodeMut<V>, attributes: &AttributeMask);
|
fn attributes_changed(&mut self, light_root: NodeMut<V>, attributes: &AttributeMask);
|
||||||
|
|
||||||
/// The root node of the widget.
|
/// The root node of the custom element. These roots must be not change once the element is created.
|
||||||
fn roots(&self) -> Vec<NodeId>;
|
fn roots(&self) -> Vec<NodeId>;
|
||||||
|
|
||||||
/// The slot to render children of the element into.
|
/// The slot to render children of the element into. The slot must be not change once the element is created.
|
||||||
fn slot(&self) -> Option<NodeId>;
|
fn slot(&self) -> Option<NodeId> {
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<W: CustomElement<V>, V: FromAnyValue + Send + Sync> CustomElementUpdater<V> for W {
|
impl<W: CustomElement<V>, V: FromAnyValue + Send + Sync> CustomElementUpdater<V> for W {
|
||||||
@@ -146,23 +163,13 @@ impl<W: CustomElement<V>, V: FromAnyValue + Send + Sync> CustomElementUpdater<V>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A concrete structure for managing a any widget.
|
/// A dynamic trait object wrapper for [`CustomElementUpdater`]
|
||||||
#[derive(Component, Clone)]
|
#[derive(Component, Clone)]
|
||||||
pub struct CustomElementManager<V: FromAnyValue = ()> {
|
pub(crate) struct CustomElementManager<V: FromAnyValue = ()> {
|
||||||
inner: Arc<RwLock<Box<dyn CustomElementUpdater<V>>>>,
|
inner: Arc<RwLock<Box<dyn CustomElementUpdater<V>>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<V: FromAnyValue + Send + Sync> CustomElementManager<V> {
|
impl<V: FromAnyValue + Send + Sync> CustomElementManager<V> {
|
||||||
/// The root node of the widget's shadow DOM.
|
|
||||||
pub fn roots(&self) -> Vec<NodeId> {
|
|
||||||
self.inner.read().unwrap().roots()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The slot to render children of the element into.
|
|
||||||
pub fn slot(&self) -> Option<NodeId> {
|
|
||||||
self.inner.read().unwrap().slot()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Update the custom element based on attributes changed.
|
/// Update the custom element based on attributes changed.
|
||||||
pub fn on_attributes_changed(&self, light_root: NodeMut<V>, attributes: &AttributeMask) {
|
pub fn on_attributes_changed(&self, light_root: NodeMut<V>, attributes: &AttributeMask) {
|
||||||
self.inner
|
self.inner
|
||||||
|
|||||||
@@ -384,20 +384,35 @@ 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, enter_shadow_doms: bool, mut f: impl FnMut(NodeRef<V>)) {
|
/// If `enter_shadow_dom` is true, then the traversal will enter shadow doms in the tree.
|
||||||
|
pub fn traverse_depth_first_advanced(
|
||||||
|
&self,
|
||||||
|
enter_shadow_dom: 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_advanced(id, enter_shadow_doms);
|
let children = tree.children_ids_advanced(id, enter_shadow_dom);
|
||||||
stack.extend(children.iter().copied().rev());
|
stack.extend(children.iter().copied().rev());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Traverses the dom in a depth first manner, calling the provided function on each node.
|
||||||
|
pub fn traverse_depth_first(&self, f: impl FnMut(NodeRef<V>)) {
|
||||||
|
self.traverse_depth_first_advanced(true, f)
|
||||||
|
}
|
||||||
|
|
||||||
/// 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, enter_shadow_doms: bool, mut f: impl FnMut(NodeRef<V>)) {
|
/// If `enter_shadow_dom` is true, then the traversal will enter shadow doms in the tree.
|
||||||
|
pub fn traverse_breadth_first_advanced(
|
||||||
|
&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();
|
||||||
@@ -412,8 +427,14 @@ impl<V: FromAnyValue + Send + Sync> RealDom<V> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Traverses the dom in a breadth first manner, calling the provided function on each node.
|
||||||
|
pub fn traverse_breadth_first(&self, f: impl FnMut(NodeRef<V>)) {
|
||||||
|
self.traverse_breadth_first_advanced(true, f);
|
||||||
|
}
|
||||||
|
|
||||||
/// 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(
|
/// If `enter_shadow_dom` is true, then the traversal will enter shadow doms in the tree.
|
||||||
|
pub fn traverse_depth_first_mut_advanced(
|
||||||
&mut self,
|
&mut self,
|
||||||
enter_shadow_doms: bool,
|
enter_shadow_doms: bool,
|
||||||
mut f: impl FnMut(NodeMut<V>),
|
mut f: impl FnMut(NodeMut<V>),
|
||||||
@@ -432,8 +453,14 @@ impl<V: FromAnyValue + Send + Sync> RealDom<V> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Traverses the dom in a depth first manner mutably, calling the provided function on each node.
|
||||||
|
pub fn traverse_depth_first_mut(&mut self, f: impl FnMut(NodeMut<V>)) {
|
||||||
|
self.traverse_depth_first_mut_advanced(true, f)
|
||||||
|
}
|
||||||
|
|
||||||
/// 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(
|
/// If `enter_shadow_dom` is true, then the traversal will enter shadow doms in the tree.
|
||||||
|
pub fn traverse_breadth_first_mut_advanced(
|
||||||
&mut self,
|
&mut self,
|
||||||
enter_shadow_doms: bool,
|
enter_shadow_doms: bool,
|
||||||
mut f: impl FnMut(NodeMut<V>),
|
mut f: impl FnMut(NodeMut<V>),
|
||||||
@@ -453,6 +480,11 @@ impl<V: FromAnyValue + Send + Sync> RealDom<V> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Traverses the dom in a breadth first manner mutably, calling the provided function on each node.
|
||||||
|
pub fn traverse_breadth_first_mut(&mut self, f: impl FnMut(NodeMut<V>)) {
|
||||||
|
self.traverse_breadth_first_mut_advanced(true, f);
|
||||||
|
}
|
||||||
|
|
||||||
/// Adds a [`NodeWatcher`] to the dom. Node watchers are called whenever a node is created or removed.
|
/// Adds a [`NodeWatcher`] to the dom. Node watchers are called whenever a node is created or removed.
|
||||||
pub fn add_node_watcher(&mut self, watcher: impl NodeWatcher<V> + 'static + Send + Sync) {
|
pub fn add_node_watcher(&mut self, watcher: impl NodeWatcher<V> + 'static + Send + Sync) {
|
||||||
self.node_watchers.write().unwrap().push(Box::new(watcher));
|
self.node_watchers.write().unwrap().push(Box::new(watcher));
|
||||||
@@ -481,11 +513,11 @@ impl<V: FromAnyValue + Send + Sync> RealDom<V> {
|
|||||||
|
|
||||||
/// Registers a new custom element.
|
/// Registers a new custom element.
|
||||||
pub fn register_custom_element<E: CustomElement<V>>(&mut self) {
|
pub fn register_custom_element<E: CustomElement<V>>(&mut self) {
|
||||||
self.register_custom_element_factory::<E, E>()
|
self.register_custom_element_with_factory::<E, E>()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Registers a new custom element with a custom factory.
|
/// Registers a new custom element with a custom factory.
|
||||||
pub fn register_custom_element_factory<F, U>(&mut self)
|
pub fn register_custom_element_with_factory<F, U>(&mut self)
|
||||||
where
|
where
|
||||||
F: CustomElementFactory<U, V>,
|
F: CustomElementFactory<U, V>,
|
||||||
U: CustomElementUpdater<V>,
|
U: CustomElementUpdater<V>,
|
||||||
@@ -563,6 +595,14 @@ pub trait NodeImmutable<V: FromAnyValue + Send + Sync = ()>: Sized {
|
|||||||
.then(|| ViewEntry::new(view, self.id()))
|
.then(|| ViewEntry::new(view, self.id()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 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> {
|
||||||
|
self.real_dom()
|
||||||
|
.tree_ref()
|
||||||
|
.children_ids_advanced(id, enter_shadow_dom)
|
||||||
|
}
|
||||||
|
|
||||||
/// Get the ids of the children of the current node
|
/// Get the ids of the children of the current node
|
||||||
#[inline]
|
#[inline]
|
||||||
fn child_ids(&self) -> Vec<NodeId> {
|
fn child_ids(&self) -> Vec<NodeId> {
|
||||||
@@ -581,6 +621,14 @@ pub trait NodeImmutable<V: FromAnyValue + Send + Sync = ()>: Sized {
|
|||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 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> {
|
||||||
|
self.real_dom()
|
||||||
|
.tree_ref()
|
||||||
|
.parent_id_advanced(id, enter_shadow_dom)
|
||||||
|
}
|
||||||
|
|
||||||
/// Get the id of the parent of the current node
|
/// Get the id of the parent of the current node
|
||||||
#[inline]
|
#[inline]
|
||||||
fn parent_id(&self) -> Option<NodeId> {
|
fn parent_id(&self) -> Option<NodeId> {
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ use crate::NodeId;
|
|||||||
use shipyard::{Component, EntitiesViewMut, Get, View, ViewMut};
|
use shipyard::{Component, EntitiesViewMut, Get, View, ViewMut};
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
|
|
||||||
/// A shadow_tree of a tree.
|
/// A shadow tree reference inside of a tree. This tree is isolated from the main tree.
|
||||||
#[derive(PartialEq, Eq, Clone, Debug, Component)]
|
#[derive(PartialEq, Eq, Clone, Debug, Component)]
|
||||||
pub struct ShadowTree {
|
pub struct ShadowTree {
|
||||||
/// The root of the shadow_tree
|
/// The root of the shadow tree
|
||||||
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>,
|
||||||
@@ -22,7 +22,7 @@ pub struct Node {
|
|||||||
/// If this node is a slot in a shadow_tree, this is node whose child_subtree is that shadow_tree.
|
/// If this node is a slot in a shadow_tree, this is node whose child_subtree is that shadow_tree.
|
||||||
slot_for_light_tree: Option<NodeId>,
|
slot_for_light_tree: Option<NodeId>,
|
||||||
/// If this node is a root of a shadow_tree, this is the node whose child_subtree is that shadow_tree.
|
/// If this node is a root of a shadow_tree, this is the node whose child_subtree is that shadow_tree.
|
||||||
light_tree_root: Option<NodeId>,
|
root_for_light_tree: Option<NodeId>,
|
||||||
height: u16,
|
height: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -37,8 +37,8 @@ pub trait TreeRef {
|
|||||||
#[inline]
|
#[inline]
|
||||||
fn parent_id_advanced(&self, id: NodeId, enter_shadow_dom: bool) -> Option<NodeId> {
|
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
|
// 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);
|
let root_for_light_tree = self.root_for_light_tree(id);
|
||||||
match (light_tree_root, enter_shadow_dom) {
|
match (root_for_light_tree, enter_shadow_dom) {
|
||||||
(Some(id), true) => Some(id),
|
(Some(id), true) => Some(id),
|
||||||
_ => {
|
_ => {
|
||||||
let parent_id = self.parent_id(id);
|
let parent_id = self.parent_id(id);
|
||||||
@@ -74,11 +74,10 @@ pub trait TreeRef {
|
|||||||
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.
|
||||||
fn shadow_tree(&self, id: NodeId) -> Option<&ShadowTree>;
|
fn shadow_tree(&self, id: NodeId) -> Option<&ShadowTree>;
|
||||||
// TODO: rethink naming
|
|
||||||
/// The node that contains the shadow tree this node is a slot for
|
/// The node that contains the shadow tree this node is a slot for
|
||||||
fn slot_for_light_tree(&self, id: NodeId) -> Option<NodeId>;
|
fn slot_for_light_tree(&self, id: NodeId) -> Option<NodeId>;
|
||||||
/// The node that contains the shadow tree this node is a root of
|
/// The node that contains the shadow tree this node is a root of
|
||||||
fn light_tree_root(&self, id: NodeId) -> Option<NodeId>;
|
fn root_for_light_tree(&self, id: NodeId) -> Option<NodeId>;
|
||||||
/// The height of the node.
|
/// The height of the node.
|
||||||
fn height(&self, id: NodeId) -> Option<u16>;
|
fn height(&self, id: NodeId) -> Option<u16>;
|
||||||
/// Returns true if the node exists.
|
/// Returns true if the node exists.
|
||||||
@@ -132,8 +131,8 @@ impl<'a> TreeRef for TreeRefView<'a> {
|
|||||||
self.get(id).ok()?.slot_for_light_tree
|
self.get(id).ok()?.slot_for_light_tree
|
||||||
}
|
}
|
||||||
|
|
||||||
fn light_tree_root(&self, id: NodeId) -> Option<NodeId> {
|
fn root_for_light_tree(&self, id: NodeId) -> Option<NodeId> {
|
||||||
self.get(id).ok()?.light_tree_root
|
self.get(id).ok()?.root_for_light_tree
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -151,14 +150,14 @@ impl<'a> TreeMut for TreeMutView<'a> {
|
|||||||
|
|
||||||
// If this node is a slot in a shadow_tree, remove it from the shadow_tree.
|
// If this node is a slot in a shadow_tree, remove it from the shadow_tree.
|
||||||
if let Some(light_tree) = light_tree {
|
if let Some(light_tree) = light_tree {
|
||||||
let light_tree_root = (&mut tree.1).get(light_tree).unwrap();
|
let root_for_light_tree = (&mut tree.1).get(light_tree).unwrap();
|
||||||
|
|
||||||
if let Some(shadow_tree) = &mut light_tree_root.child_subtree {
|
if let Some(shadow_tree) = &mut root_for_light_tree.child_subtree {
|
||||||
shadow_tree.slot = None;
|
shadow_tree.slot = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
debug_assert!(
|
debug_assert!(
|
||||||
light_tree_root.children.is_empty(),
|
root_for_light_tree.children.is_empty(),
|
||||||
"ShadowTree root should have no children when slot is removed."
|
"ShadowTree root should have no children when slot is removed."
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -186,7 +185,7 @@ impl<'a> TreeMut for TreeMutView<'a> {
|
|||||||
height: 0,
|
height: 0,
|
||||||
child_subtree: None,
|
child_subtree: None,
|
||||||
slot_for_light_tree: None,
|
slot_for_light_tree: None,
|
||||||
light_tree_root: None,
|
root_for_light_tree: None,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -283,7 +282,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);
|
(&mut self.1).get(root).unwrap().root_for_light_tree = Some(id);
|
||||||
set_height(self, root, light_root_height + 1);
|
set_height(self, root, light_root_height + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -403,9 +402,9 @@ impl<'a> TreeRef for TreeMutView<'a> {
|
|||||||
node_data.get(id).ok()?.slot_for_light_tree
|
node_data.get(id).ok()?.slot_for_light_tree
|
||||||
}
|
}
|
||||||
|
|
||||||
fn light_tree_root(&self, id: NodeId) -> Option<NodeId> {
|
fn root_for_light_tree(&self, id: NodeId) -> Option<NodeId> {
|
||||||
let node_data = &self.1;
|
let node_data = &self.1;
|
||||||
node_data.get(id).ok()?.light_tree_root
|
node_data.get(id).ok()?.root_for_light_tree
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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(false, |n| {
|
dom.traverse_depth_first_advanced(false, |n| {
|
||||||
$(
|
$(
|
||||||
assert_eq!(n.get::<$state>().unwrap().0, 1);
|
assert_eq!(n.get::<$state>().unwrap().0, 1);
|
||||||
)*
|
)*
|
||||||
|
|||||||
@@ -301,7 +301,7 @@ fn custom_elements_work() {
|
|||||||
rdom.update_state(ctx);
|
rdom.update_state(ctx);
|
||||||
|
|
||||||
// render...
|
// render...
|
||||||
rdom.traverse_depth_first(true, |node| {
|
rdom.traverse_depth_first_advanced(true, |node| {
|
||||||
let node_type = &*node.node_type();
|
let node_type = &*node.node_type();
|
||||||
let height = node.height() as usize;
|
let height = node.height() as usize;
|
||||||
let indent = " ".repeat(height);
|
let indent = " ".repeat(height);
|
||||||
|
|||||||
@@ -183,7 +183,7 @@ impl FocusState {
|
|||||||
|
|
||||||
if forward {
|
if forward {
|
||||||
// find the closest focusable element after the current level
|
// find the closest focusable element after the current level
|
||||||
rdom.traverse_depth_first(true, |n| {
|
rdom.traverse_depth_first(|n| {
|
||||||
let node_level = n.get::<Focus>().unwrap().level;
|
let node_level = n.get::<Focus>().unwrap().level;
|
||||||
if node_level != *focus_level
|
if node_level != *focus_level
|
||||||
&& node_level.focusable()
|
&& node_level.focusable()
|
||||||
@@ -200,7 +200,7 @@ impl FocusState {
|
|||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
// find the closest focusable element before the current level
|
// find the closest focusable element before the current level
|
||||||
rdom.traverse_depth_first(true, |n| {
|
rdom.traverse_depth_first(|n| {
|
||||||
let node_level = n.get::<Focus>().unwrap().level;
|
let node_level = n.get::<Focus>().unwrap().level;
|
||||||
if node_level != *focus_level
|
if node_level != *focus_level
|
||||||
&& node_level.focusable()
|
&& node_level.focusable()
|
||||||
|
|||||||
@@ -550,7 +550,7 @@ impl InnerInputState {
|
|||||||
// update focus
|
// update focus
|
||||||
if was_released {
|
if was_released {
|
||||||
let mut focus_id = None;
|
let mut focus_id = None;
|
||||||
dom.traverse_depth_first(true, |node| {
|
dom.traverse_depth_first(|node| {
|
||||||
let node_layout = layout
|
let node_layout = layout
|
||||||
.layout(node.get::<TaffyLayout>().unwrap().node.unwrap())
|
.layout(node.get::<TaffyLayout>().unwrap().node.unwrap())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|||||||
Reference in new issue
Block a user