make dioxus dependancy optional
This commit is contained in:
1 parent
8dde4e492f
commit
6fe00c4f78
12 files changed
+1152
-1195
No files matched your search
@@ -11,10 +11,9 @@ keywords = ["dom", "ui", "gui", "react"]
|
|||||||
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
dioxus-core = { path = "../core", version = "^0.3.0" }
|
dioxus-core = { path = "../core", version = "^0.3.0", optional = true }
|
||||||
dioxus-html = { path = "../html", version = "^0.3.0" }
|
|
||||||
dioxus-core-macro = { path = "../core-macro", version = "^0.3.0" }
|
|
||||||
|
|
||||||
|
keyboard-types = "0.6.2"
|
||||||
taffy = "0.2.1"
|
taffy = "0.2.1"
|
||||||
smallvec = "1.6"
|
smallvec = "1.6"
|
||||||
rustc-hash = "1.1.0"
|
rustc-hash = "1.1.0"
|
||||||
@@ -34,3 +33,8 @@ rayon = "1.6.1"
|
|||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
dioxus = { path = "../dioxus", version = "^0.3.0" }
|
dioxus = { path = "../dioxus", version = "^0.3.0" }
|
||||||
tokio = { version = "*", features = ["full"] }
|
tokio = { version = "*", features = ["full"] }
|
||||||
|
dioxus-native-core = { path = ".", features = ["dioxus"] }
|
||||||
|
|
||||||
|
[features]
|
||||||
|
default = ["dioxus"]
|
||||||
|
dioxus = ["dioxus-core"]
|
||||||
@@ -0,0 +1,254 @@
|
|||||||
|
use dioxus_core::{BorrowedAttributeValue, ElementId, Mutations, TemplateNode};
|
||||||
|
use rustc_hash::{FxHashMap, FxHashSet};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
node::{ElementNode, FromAnyValue, NodeType, OwnedAttributeDiscription, OwnedAttributeValue},
|
||||||
|
prelude::{NodeImmutable, NodeMutable},
|
||||||
|
real_dom::NodeTypeMut,
|
||||||
|
NodeId, NodeMut, RealDom,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct DioxusState {
|
||||||
|
templates: FxHashMap<String, Vec<NodeId>>,
|
||||||
|
stack: Vec<NodeId>,
|
||||||
|
node_id_mapping: Vec<Option<NodeId>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DioxusState {
|
||||||
|
pub fn new(rdom: &mut RealDom) -> Self {
|
||||||
|
rdom.insert_slab::<ElementId>();
|
||||||
|
let root_id = rdom.root_id();
|
||||||
|
let mut root = rdom.get_mut(root_id).unwrap();
|
||||||
|
root.insert(ElementId(0));
|
||||||
|
Self {
|
||||||
|
templates: FxHashMap::default(),
|
||||||
|
stack: vec![root_id],
|
||||||
|
node_id_mapping: vec![Some(root_id)],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn element_to_node_id(&self, element_id: ElementId) -> NodeId {
|
||||||
|
self.node_id_mapping.get(element_id.0).unwrap().unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_element_id(&mut self, mut node: NodeMut, element_id: ElementId) {
|
||||||
|
let node_id = node.id();
|
||||||
|
node.insert(element_id);
|
||||||
|
if self.node_id_mapping.len() <= element_id.0 {
|
||||||
|
self.node_id_mapping.resize(element_id.0 + 1, None);
|
||||||
|
}
|
||||||
|
self.node_id_mapping[element_id.0] = Some(node_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn load_child(&self, rdom: &RealDom, path: &[u8]) -> NodeId {
|
||||||
|
let mut current = rdom.get(*self.stack.last().unwrap()).unwrap();
|
||||||
|
for i in path {
|
||||||
|
let new_id = current.child_ids().unwrap()[*i as usize];
|
||||||
|
current = rdom.get(new_id).unwrap();
|
||||||
|
}
|
||||||
|
current.id()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Updates the dom with some mutations and return a set of nodes that were updated. Pass the dirty nodes to update_state.
|
||||||
|
pub fn apply_mutations(&mut self, rdom: &mut RealDom, mutations: Mutations) {
|
||||||
|
for template in mutations.templates {
|
||||||
|
let mut template_root_ids = Vec::new();
|
||||||
|
for root in template.roots {
|
||||||
|
let id = create_template_node(rdom, root);
|
||||||
|
template_root_ids.push(id);
|
||||||
|
}
|
||||||
|
self.templates
|
||||||
|
.insert(template.name.to_string(), template_root_ids);
|
||||||
|
}
|
||||||
|
|
||||||
|
for e in mutations.edits {
|
||||||
|
use dioxus_core::Mutation::*;
|
||||||
|
match e {
|
||||||
|
AppendChildren { id, m } => {
|
||||||
|
let children = self.stack.split_off(self.stack.len() - m);
|
||||||
|
let parent = self.element_to_node_id(id);
|
||||||
|
for child in children {
|
||||||
|
rdom.add_child(parent, child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AssignId { path, id } => {
|
||||||
|
let node_id = self.load_child(rdom, path);
|
||||||
|
self.set_element_id(rdom.get_mut(node_id).unwrap(), id);
|
||||||
|
}
|
||||||
|
CreatePlaceholder { id } => {
|
||||||
|
let node = NodeType::Placeholder;
|
||||||
|
let node = rdom.create_node(node, true);
|
||||||
|
let node_id = node.id();
|
||||||
|
self.set_element_id(node, id);
|
||||||
|
self.stack.push(node_id);
|
||||||
|
}
|
||||||
|
CreateTextNode { value, id } => {
|
||||||
|
let node_data = NodeType::Text(value.to_string());
|
||||||
|
let node = rdom.create_node(node_data, true);
|
||||||
|
let node_id = node.id();
|
||||||
|
self.set_element_id(node, id);
|
||||||
|
self.stack.push(node_id);
|
||||||
|
}
|
||||||
|
HydrateText { path, value, id } => {
|
||||||
|
let node_id = self.load_child(rdom, path);
|
||||||
|
let node = rdom.get_mut(node_id).unwrap();
|
||||||
|
self.set_element_id(node, id);
|
||||||
|
let mut node = rdom.get_mut(node_id).unwrap();
|
||||||
|
if let NodeTypeMut::Text(text) = node.node_type_mut() {
|
||||||
|
*text = value.to_string();
|
||||||
|
} else {
|
||||||
|
node.set_type(NodeType::Text(value.to_string()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LoadTemplate { name, index, id } => {
|
||||||
|
let template_id = self.templates[name][index];
|
||||||
|
let clone_id = rdom.clone_node(template_id);
|
||||||
|
let clone = rdom.get_mut(clone_id).unwrap();
|
||||||
|
self.set_element_id(clone, id);
|
||||||
|
self.stack.push(clone_id);
|
||||||
|
}
|
||||||
|
ReplaceWith { id, m } => {
|
||||||
|
let new_nodes = self.stack.split_off(self.stack.len() - m);
|
||||||
|
let old_node_id = self.element_to_node_id(id);
|
||||||
|
for new in new_nodes {
|
||||||
|
let mut node = rdom.get_mut(new).unwrap();
|
||||||
|
node.insert_before(old_node_id);
|
||||||
|
}
|
||||||
|
rdom.remove(old_node_id);
|
||||||
|
}
|
||||||
|
ReplacePlaceholder { path, m } => {
|
||||||
|
let new_nodes = self.stack.split_off(self.stack.len() - m);
|
||||||
|
let old_node_id = self.load_child(rdom, path);
|
||||||
|
for new in new_nodes {
|
||||||
|
let mut node = rdom.get_mut(new).unwrap();
|
||||||
|
node.insert_before(old_node_id);
|
||||||
|
}
|
||||||
|
rdom.remove(old_node_id);
|
||||||
|
}
|
||||||
|
InsertAfter { id, m } => {
|
||||||
|
let new_nodes = self.stack.split_off(self.stack.len() - m);
|
||||||
|
let old_node_id = self.element_to_node_id(id);
|
||||||
|
for new in new_nodes.into_iter().rev() {
|
||||||
|
let mut node = rdom.get_mut(new).unwrap();
|
||||||
|
node.insert_after(old_node_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
InsertBefore { id, m } => {
|
||||||
|
let new_nodes = self.stack.split_off(self.stack.len() - m);
|
||||||
|
let old_node_id = self.element_to_node_id(id);
|
||||||
|
for new in new_nodes {
|
||||||
|
rdom.tree.insert_before(old_node_id, new);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SetAttribute {
|
||||||
|
name,
|
||||||
|
value,
|
||||||
|
id,
|
||||||
|
ns,
|
||||||
|
} => {
|
||||||
|
let node_id = self.element_to_node_id(id);
|
||||||
|
let mut node = rdom.get_mut(node_id).unwrap();
|
||||||
|
if let NodeTypeMut::Element(element) = &mut node.node_type_mut() {
|
||||||
|
if let BorrowedAttributeValue::None = &value {
|
||||||
|
element.remove_attributes(&OwnedAttributeDiscription {
|
||||||
|
name: name.to_string(),
|
||||||
|
namespace: ns.map(|s| s.to_string()),
|
||||||
|
volatile: false,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
element.set_attribute(
|
||||||
|
OwnedAttributeDiscription {
|
||||||
|
name: name.to_string(),
|
||||||
|
namespace: ns.map(|s| s.to_string()),
|
||||||
|
volatile: false,
|
||||||
|
},
|
||||||
|
OwnedAttributeValue::from(value),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SetText { value, id } => {
|
||||||
|
let node_id = self.element_to_node_id(id);
|
||||||
|
let mut node = rdom.get_mut(node_id).unwrap();
|
||||||
|
if let NodeTypeMut::Text(text) = node.node_type_mut() {
|
||||||
|
*text = value.to_string();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
NewEventListener { name, id } => {
|
||||||
|
let node_id = self.element_to_node_id(id);
|
||||||
|
let mut node = rdom.get_mut(node_id).unwrap();
|
||||||
|
node.add_event_listener(name);
|
||||||
|
}
|
||||||
|
RemoveEventListener { id, name } => {
|
||||||
|
let node_id = self.element_to_node_id(id);
|
||||||
|
let mut node = rdom.get_mut(node_id).unwrap();
|
||||||
|
node.remove_event_listener(name);
|
||||||
|
}
|
||||||
|
Remove { id } => {
|
||||||
|
let node_id = self.element_to_node_id(id);
|
||||||
|
rdom.remove(node_id);
|
||||||
|
}
|
||||||
|
PushRoot { id } => {
|
||||||
|
let node_id = self.element_to_node_id(id);
|
||||||
|
self.stack.push(node_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_template_node(rdom: &mut RealDom, node: &TemplateNode) -> NodeId {
|
||||||
|
match node {
|
||||||
|
TemplateNode::Element {
|
||||||
|
tag,
|
||||||
|
namespace,
|
||||||
|
attrs,
|
||||||
|
children,
|
||||||
|
} => {
|
||||||
|
let node = NodeType::Element(ElementNode {
|
||||||
|
tag: tag.to_string(),
|
||||||
|
namespace: namespace.map(|s| s.to_string()),
|
||||||
|
attributes: attrs
|
||||||
|
.iter()
|
||||||
|
.filter_map(|attr| match attr {
|
||||||
|
dioxus_core::TemplateAttribute::Static {
|
||||||
|
name,
|
||||||
|
value,
|
||||||
|
namespace,
|
||||||
|
} => Some((
|
||||||
|
OwnedAttributeDiscription {
|
||||||
|
namespace: namespace.map(|s| s.to_string()),
|
||||||
|
name: name.to_string(),
|
||||||
|
volatile: false,
|
||||||
|
},
|
||||||
|
OwnedAttributeValue::Text(value.to_string()),
|
||||||
|
)),
|
||||||
|
dioxus_core::TemplateAttribute::Dynamic { .. } => None,
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
|
listeners: FxHashSet::default(),
|
||||||
|
});
|
||||||
|
let node_id = rdom.create_node(node, true).id();
|
||||||
|
for child in *children {
|
||||||
|
let child_id = create_template_node(rdom, child);
|
||||||
|
rdom.add_child(node_id, child_id);
|
||||||
|
}
|
||||||
|
node_id
|
||||||
|
}
|
||||||
|
TemplateNode::Text { text } => rdom
|
||||||
|
.create_node(NodeType::Text(text.to_string()), true)
|
||||||
|
.id(),
|
||||||
|
TemplateNode::Dynamic { .. } => rdom.create_node(NodeType::Placeholder, true).id(),
|
||||||
|
TemplateNode::DynamicText { .. } => {
|
||||||
|
rdom.create_node(NodeType::Text(String::new()), true).id()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
trait NodeImmutableDioxusExt<V: FromAnyValue + Send + Sync>: NodeImmutable<V> {
|
||||||
|
fn mounted_id(&self) -> Option<ElementId> {
|
||||||
|
self.get().copied()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: NodeImmutable<V>, V: FromAnyValue + Send + Sync> NodeImmutableDioxusExt<V> for T {}
|
||||||
@@ -8,6 +8,8 @@ pub use real_dom::{NodeMut, NodeRef, RealDom};
|
|||||||
use rustc_hash::FxHasher;
|
use rustc_hash::FxHasher;
|
||||||
pub use tree::NodeId;
|
pub use tree::NodeId;
|
||||||
|
|
||||||
|
#[cfg(feature = "dioxus")]
|
||||||
|
pub mod dioxus;
|
||||||
pub mod layout_attributes;
|
pub mod layout_attributes;
|
||||||
pub mod node;
|
pub mod node;
|
||||||
pub mod node_ref;
|
pub mod node_ref;
|
||||||
@@ -16,33 +18,15 @@ pub mod real_dom;
|
|||||||
pub mod tree;
|
pub mod tree;
|
||||||
pub mod utils;
|
pub mod utils;
|
||||||
|
|
||||||
|
pub mod prelude {
|
||||||
|
pub use crate::node::{ElementNode, FromAnyValue, NodeType, OwnedAttributeView};
|
||||||
|
pub use crate::node_ref::{AttributeMaskBuilder, NodeMaskBuilder, NodeView};
|
||||||
|
pub use crate::passes::{Dependancy, Pass};
|
||||||
|
pub use crate::real_dom::{NodeImmutable, NodeMut, NodeMutRaw, NodeMutable, NodeRef, RealDom};
|
||||||
|
pub use crate::tree::NodeId;
|
||||||
|
pub use crate::SendAnyMap;
|
||||||
|
}
|
||||||
|
|
||||||
pub type FxDashMap<K, V> = dashmap::DashMap<K, V, BuildHasherDefault<FxHasher>>;
|
pub type FxDashMap<K, V> = dashmap::DashMap<K, V, BuildHasherDefault<FxHasher>>;
|
||||||
pub type FxDashSet<K> = dashmap::DashSet<K, BuildHasherDefault<FxHasher>>;
|
pub type FxDashSet<K> = dashmap::DashSet<K, BuildHasherDefault<FxHasher>>;
|
||||||
pub type SendAnyMap = anymap::Map<dyn Any + Send + Sync + 'static>;
|
pub type SendAnyMap = anymap::Map<dyn Any + Send + Sync + 'static>;
|
||||||
|
|
||||||
/// Used in derived state macros
|
|
||||||
#[derive(Eq, PartialEq)]
|
|
||||||
#[doc(hidden)]
|
|
||||||
pub struct HeightOrdering {
|
|
||||||
pub height: u16,
|
|
||||||
pub id: NodeId,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl HeightOrdering {
|
|
||||||
pub fn new(height: u16, id: NodeId) -> Self {
|
|
||||||
HeightOrdering { height, id }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// not the ordering after height is just for deduplication it can be any ordering as long as it is consistent
|
|
||||||
impl Ord for HeightOrdering {
|
|
||||||
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
|
|
||||||
self.height.cmp(&other.height).then(self.id.cmp(&other.id))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PartialOrd for HeightOrdering {
|
|
||||||
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
|
||||||
Some(self.cmp(other))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,20 +1,8 @@
|
|||||||
use crate::tree::NodeId;
|
|
||||||
use dioxus_core::{AnyValue, BorrowedAttributeValue, ElementId};
|
|
||||||
use rustc_hash::{FxHashMap, FxHashSet};
|
use rustc_hash::{FxHashMap, FxHashSet};
|
||||||
use std::fmt::Debug;
|
use std::{any::Any, fmt::Debug};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct NodeData<V: FromAnyValue = ()> {
|
pub struct ElementNode<V: FromAnyValue = ()> {
|
||||||
/// The id of the node
|
|
||||||
pub node_id: NodeId,
|
|
||||||
/// The id of the node in the vdom.
|
|
||||||
pub element_id: Option<ElementId>,
|
|
||||||
/// Additional inforation specific to the node type
|
|
||||||
pub node_type: NodeType<V>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct ElementNode<V: FromAnyValue> {
|
|
||||||
pub tag: String,
|
pub tag: String,
|
||||||
pub namespace: Option<String>,
|
pub namespace: Option<String>,
|
||||||
pub attributes: FxHashMap<OwnedAttributeDiscription, OwnedAttributeValue<V>>,
|
pub attributes: FxHashMap<OwnedAttributeDiscription, OwnedAttributeValue<V>>,
|
||||||
@@ -29,21 +17,6 @@ pub enum NodeType<V: FromAnyValue = ()> {
|
|||||||
Placeholder,
|
Placeholder,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<V: FromAnyValue> NodeData<V> {
|
|
||||||
pub(crate) fn new(node_type: NodeType<V>) -> Self {
|
|
||||||
NodeData {
|
|
||||||
element_id: None,
|
|
||||||
node_type,
|
|
||||||
node_id: NodeId(0),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// get the mounted id of the node
|
|
||||||
pub fn mounted_id(&self) -> Option<ElementId> {
|
|
||||||
self.element_id
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
|
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
|
||||||
pub struct OwnedAttributeDiscription {
|
pub struct OwnedAttributeDiscription {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
@@ -72,11 +45,11 @@ pub enum OwnedAttributeValue<V: FromAnyValue = ()> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub trait FromAnyValue: Clone + 'static {
|
pub trait FromAnyValue: Clone + 'static {
|
||||||
fn from_any_value(value: &dyn AnyValue) -> Self;
|
fn from_any_value(value: &dyn Any) -> Self;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromAnyValue for () {
|
impl FromAnyValue for () {
|
||||||
fn from_any_value(_: &dyn AnyValue) -> Self {}
|
fn from_any_value(_: &dyn Any) -> Self {}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<V: FromAnyValue> Debug for OwnedAttributeValue<V> {
|
impl<V: FromAnyValue> Debug for OwnedAttributeValue<V> {
|
||||||
@@ -91,15 +64,16 @@ impl<V: FromAnyValue> Debug for OwnedAttributeValue<V> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<V: FromAnyValue> From<BorrowedAttributeValue<'_>> for OwnedAttributeValue<V> {
|
#[cfg(feature = "dioxus")]
|
||||||
fn from(value: BorrowedAttributeValue<'_>) -> Self {
|
impl<V: FromAnyValue> From<dioxus_core::BorrowedAttributeValue<'_>> for OwnedAttributeValue<V> {
|
||||||
|
fn from(value: dioxus_core::BorrowedAttributeValue<'_>) -> Self {
|
||||||
match value {
|
match value {
|
||||||
BorrowedAttributeValue::Text(text) => Self::Text(text.to_string()),
|
dioxus_core::BorrowedAttributeValue::Text(text) => Self::Text(text.to_string()),
|
||||||
BorrowedAttributeValue::Float(float) => Self::Float(float),
|
dioxus_core::BorrowedAttributeValue::Float(float) => Self::Float(float),
|
||||||
BorrowedAttributeValue::Int(int) => Self::Int(int),
|
dioxus_core::BorrowedAttributeValue::Int(int) => Self::Int(int),
|
||||||
BorrowedAttributeValue::Bool(bool) => Self::Bool(bool),
|
dioxus_core::BorrowedAttributeValue::Bool(bool) => Self::Bool(bool),
|
||||||
BorrowedAttributeValue::Any(any) => Self::Custom(V::from_any_value(&*any)),
|
dioxus_core::BorrowedAttributeValue::Any(any) => Self::Custom(V::from_any_value(any.as_any())),
|
||||||
BorrowedAttributeValue::None => panic!("None attribute values result in removing the attribute, not converting it to a None value.")
|
dioxus_core::BorrowedAttributeValue::None => panic!("None attribute values result in removing the attribute, not converting it to a None value.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,42 +1,38 @@
|
|||||||
use dioxus_core::ElementId;
|
|
||||||
use rustc_hash::FxHashSet;
|
use rustc_hash::FxHashSet;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
node::{ElementNode, FromAnyValue, NodeData, NodeType, OwnedAttributeView},
|
node::{ElementNode, FromAnyValue, NodeType, OwnedAttributeView},
|
||||||
NodeId,
|
NodeId,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A view into a [VNode] with limited access.
|
/// A view into a [VNode] with limited access.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct NodeView<'a, V: FromAnyValue = ()> {
|
pub struct NodeView<'a, V: FromAnyValue = ()> {
|
||||||
inner: &'a NodeData<V>,
|
id: NodeId,
|
||||||
|
inner: &'a NodeType<V>,
|
||||||
mask: &'a NodeMask,
|
mask: &'a NodeMask,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, V: FromAnyValue> NodeView<'a, V> {
|
impl<'a, V: FromAnyValue> NodeView<'a, V> {
|
||||||
/// Create a new NodeView from a VNode, and mask.
|
/// Create a new NodeView from a VNode, and mask.
|
||||||
pub fn new(node: &'a NodeData<V>, view: &'a NodeMask) -> Self {
|
pub fn new(id: NodeId, node: &'a NodeType<V>, view: &'a NodeMask) -> Self {
|
||||||
Self {
|
Self {
|
||||||
inner: node,
|
inner: node,
|
||||||
mask: view,
|
mask: view,
|
||||||
|
id,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the id of the node
|
|
||||||
pub fn id(&self) -> Option<ElementId> {
|
|
||||||
self.inner.element_id
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the node id of the node
|
/// Get the node id of the node
|
||||||
pub fn node_id(&self) -> NodeId {
|
pub fn node_id(&self) -> NodeId {
|
||||||
self.inner.node_id
|
self.id
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the tag of the node if the tag is enabled in the mask
|
/// Get the tag of the node if the tag is enabled in the mask
|
||||||
pub fn tag(&self) -> Option<&'a str> {
|
pub fn tag(&self) -> Option<&'a str> {
|
||||||
self.mask
|
self.mask
|
||||||
.tag
|
.tag
|
||||||
.then_some(match &self.inner.node_type {
|
.then_some(match &self.inner {
|
||||||
NodeType::Element(ElementNode { tag, .. }) => Some(&**tag),
|
NodeType::Element(ElementNode { tag, .. }) => Some(&**tag),
|
||||||
_ => None,
|
_ => None,
|
||||||
})
|
})
|
||||||
@@ -47,7 +43,7 @@ impl<'a, V: FromAnyValue> NodeView<'a, V> {
|
|||||||
pub fn namespace(&self) -> Option<&'a str> {
|
pub fn namespace(&self) -> Option<&'a str> {
|
||||||
self.mask
|
self.mask
|
||||||
.namespace
|
.namespace
|
||||||
.then_some(match &self.inner.node_type {
|
.then_some(match &self.inner {
|
||||||
NodeType::Element(ElementNode { namespace, .. }) => namespace.as_deref(),
|
NodeType::Element(ElementNode { namespace, .. }) => namespace.as_deref(),
|
||||||
_ => None,
|
_ => None,
|
||||||
})
|
})
|
||||||
@@ -58,7 +54,7 @@ impl<'a, V: FromAnyValue> NodeView<'a, V> {
|
|||||||
pub fn attributes<'b>(
|
pub fn attributes<'b>(
|
||||||
&'b self,
|
&'b self,
|
||||||
) -> Option<impl Iterator<Item = OwnedAttributeView<'a, V>> + 'b> {
|
) -> Option<impl Iterator<Item = OwnedAttributeView<'a, V>> + 'b> {
|
||||||
match &self.inner.node_type {
|
match &self.inner {
|
||||||
NodeType::Element(ElementNode { attributes, .. }) => Some(
|
NodeType::Element(ElementNode { attributes, .. }) => Some(
|
||||||
attributes
|
attributes
|
||||||
.iter()
|
.iter()
|
||||||
@@ -76,7 +72,7 @@ impl<'a, V: FromAnyValue> NodeView<'a, V> {
|
|||||||
pub fn text(&self) -> Option<&str> {
|
pub fn text(&self) -> Option<&str> {
|
||||||
self.mask
|
self.mask
|
||||||
.text
|
.text
|
||||||
.then_some(match &self.inner.node_type {
|
.then_some(match &self.inner {
|
||||||
NodeType::Text(text) => Some(&**text),
|
NodeType::Text(text) => Some(&**text),
|
||||||
_ => None,
|
_ => None,
|
||||||
})
|
})
|
||||||
@@ -86,7 +82,7 @@ impl<'a, V: FromAnyValue> NodeView<'a, V> {
|
|||||||
/// Get the listeners if it is enabled in the mask
|
/// Get the listeners if it is enabled in the mask
|
||||||
pub fn listeners(&self) -> Option<impl Iterator<Item = &'a str> + '_> {
|
pub fn listeners(&self) -> Option<impl Iterator<Item = &'a str> + '_> {
|
||||||
if self.mask.listeners {
|
if self.mask.listeners {
|
||||||
match &self.inner.node_type {
|
match &self.inner {
|
||||||
NodeType::Element(ElementNode { listeners, .. }) => {
|
NodeType::Element(ElementNode { listeners, .. }) => {
|
||||||
Some(listeners.iter().map(|l| &**l))
|
Some(listeners.iter().map(|l| &**l))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ use std::collections::BTreeMap;
|
|||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use crate::node::{FromAnyValue, NodeData};
|
use crate::node::{FromAnyValue, NodeType};
|
||||||
use crate::node_ref::{NodeMaskBuilder, NodeView};
|
use crate::node_ref::{NodeMaskBuilder, NodeView};
|
||||||
use crate::real_dom::RealDom;
|
use crate::real_dom::RealDom;
|
||||||
use crate::tree::{SlabEntry, Tree, TreeStateView};
|
use crate::tree::{SlabEntry, Tree, TreeStateView};
|
||||||
@@ -129,26 +129,35 @@ pub trait Pass<V: FromAnyValue + Send + Sync = ()>: Any + Send + Sync {
|
|||||||
) -> Self;
|
) -> Self;
|
||||||
|
|
||||||
fn validate() {
|
fn validate() {
|
||||||
// no type can be a child and parent dependency
|
|
||||||
for type_id in Self::parent_type_ids().iter().copied() {
|
|
||||||
for type_id2 in Self::child_type_ids().iter().copied() {
|
|
||||||
if type_id == type_id2 {
|
|
||||||
panic!("type cannot be both a parent and child dependency");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// this type should not be a node dependency
|
// this type should not be a node dependency
|
||||||
for type_id in Self::node_type_ids().iter().copied() {
|
for type_id in Self::node_type_ids().iter().copied() {
|
||||||
if type_id == TypeId::of::<Self>() {
|
if type_id == TypeId::of::<Self>() {
|
||||||
panic!("The current type cannot be a node dependency");
|
panic!("The current type cannot be a node dependency");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// this type cannot be both a parent and child dependency
|
||||||
|
assert!(
|
||||||
|
Self::parent_type_ids()
|
||||||
|
.iter()
|
||||||
|
.any(|type_id| *type_id != TypeId::of::<Self>())
|
||||||
|
&& Self::child_type_ids()
|
||||||
|
.iter()
|
||||||
|
.any(|type_id| *type_id != TypeId::of::<Self>()),
|
||||||
|
"The current type cannot be a parent and child dependency"
|
||||||
|
);
|
||||||
// no states have the same type id
|
// no states have the same type id
|
||||||
if Self::all_dependanices()
|
if Self::child_type_ids()
|
||||||
.iter()
|
.iter()
|
||||||
.collect::<FxDashSet<_>>()
|
.collect::<FxHashSet<_>>()
|
||||||
.len()
|
.len()
|
||||||
!= Self::all_dependanices().len()
|
!= Self::child_type_ids().len()
|
||||||
|
|| Self::parent_type_ids()
|
||||||
|
.iter()
|
||||||
|
.collect::<FxHashSet<_>>()
|
||||||
|
.len()
|
||||||
|
!= Self::parent_type_ids().len()
|
||||||
|
|| Self::node_type_ids().iter().collect::<FxHashSet<_>>().len()
|
||||||
|
!= Self::node_type_ids().len()
|
||||||
{
|
{
|
||||||
panic!("all states must have unique type ids");
|
panic!("all states must have unique type ids");
|
||||||
}
|
}
|
||||||
@@ -178,28 +187,21 @@ pub trait Pass<V: FromAnyValue + Send + Sync = ()>: Any + Send + Sync {
|
|||||||
let myself: SlabEntry<'static, Self> = unsafe {
|
let myself: SlabEntry<'static, Self> = unsafe {
|
||||||
std::mem::transmute(tree.get_slab_mut::<Self>().unwrap().entry(node_id))
|
std::mem::transmute(tree.get_slab_mut::<Self>().unwrap().entry(node_id))
|
||||||
};
|
};
|
||||||
let node_data = tree.get_single::<NodeData<V>>(node_id).unwrap();
|
let node_data = tree.get_single::<NodeType<V>>(node_id).unwrap();
|
||||||
let node = tree.get::<Self::NodeDependencies>(node_id).unwrap();
|
let node = tree.get::<Self::NodeDependencies>(node_id).unwrap();
|
||||||
let children = tree.children::<Self::ChildDependencies>(node_id);
|
let children = tree.children::<Self::ChildDependencies>(node_id);
|
||||||
let parent = tree.parent::<Self::ParentDependencies>(node_id);
|
let parent = tree.parent::<Self::ParentDependencies>(node_id);
|
||||||
|
|
||||||
|
let view = NodeView::new(node_id, node_data, &node_mask);
|
||||||
if myself.value.is_none() {
|
if myself.value.is_none() {
|
||||||
*myself.value = Some(Self::create(
|
*myself.value = Some(Self::create(view, node, parent, children, context));
|
||||||
NodeView::new(node_data, &node_mask),
|
|
||||||
node,
|
|
||||||
parent,
|
|
||||||
children,
|
|
||||||
context,
|
|
||||||
));
|
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
myself.value.as_mut().unwrap().pass(
|
myself
|
||||||
NodeView::new(node_data, &node_mask),
|
.value
|
||||||
node,
|
.as_mut()
|
||||||
parent,
|
.unwrap()
|
||||||
children,
|
.pass(view, node, parent, children, context)
|
||||||
context,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
) as PassCallback,
|
) as PassCallback,
|
||||||
@@ -409,7 +411,7 @@ pub fn resolve_passes<V: FromAnyValue + Send + Sync>(
|
|||||||
.iter()
|
.iter()
|
||||||
.filter(|id| **id != pass.this_type_id)
|
.filter(|id| **id != pass.this_type_id)
|
||||||
.copied()
|
.copied()
|
||||||
.chain(std::iter::once(TypeId::of::<NodeData<V>>())),
|
.chain(std::iter::once(TypeId::of::<NodeType<V>>())),
|
||||||
[pass.this_type_id],
|
[pass.this_type_id],
|
||||||
);
|
);
|
||||||
let dirty_nodes = dirty_nodes.clone();
|
let dirty_nodes = dirty_nodes.clone();
|
||||||
@@ -432,662 +434,3 @@ pub fn resolve_passes<V: FromAnyValue + Send + Sync>(
|
|||||||
}
|
}
|
||||||
std::sync::Arc::try_unwrap(nodes_updated).unwrap()
|
std::sync::Arc::try_unwrap(nodes_updated).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
// #[test]
|
|
||||||
// fn node_pass() {
|
|
||||||
// use crate::real_dom::RealDom;
|
|
||||||
// use crate::tree::{Tree, TreeLike};
|
|
||||||
|
|
||||||
// #[derive(Debug, Default, Clone, PartialEq)]
|
|
||||||
// struct Number(i32);
|
|
||||||
|
|
||||||
// impl State for Number {
|
|
||||||
// fn create_passes() -> Box<[TypeErasedPass<Self>]> {
|
|
||||||
// Box::new([Number::to_type_erased()])
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// impl AnyMapLike for Number {
|
|
||||||
// fn get<T: Any+Sync+Send>(&self) -> Option<&T> {
|
|
||||||
// if TypeId::of::<Self>() == TypeId::of::<T>() {
|
|
||||||
// Some(unsafe { &*(self as *const Self as *const T) })
|
|
||||||
// } else {
|
|
||||||
// None
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// fn get_mut<T: Any+Sync+Send>(&mut self) -> Option<&mut T> {
|
|
||||||
// if TypeId::of::<Self>() == TypeId::of::<T>() {
|
|
||||||
// Some(unsafe { &mut *(self as *mut Self as *mut T) })
|
|
||||||
// } else {
|
|
||||||
// None
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// impl Pass for Number {
|
|
||||||
// type ChildDependencies = ();
|
|
||||||
// type NodeDependencies = ();
|
|
||||||
// type ParentDependencies = ();
|
|
||||||
// type Ctx = ();
|
|
||||||
// const MASK: NodeMask = NodeMask::new();
|
|
||||||
|
|
||||||
// fn pass<'a>(
|
|
||||||
// &mut self,
|
|
||||||
// node_view: NodeView,
|
|
||||||
// node: <Self::NodeDependencies as Dependancy>::ElementBorrowed<'a>,
|
|
||||||
// parent: Option<<Self::ParentDependencies as Dependancy>::ElementBorrowed<'a>>,
|
|
||||||
// children: Option<
|
|
||||||
// impl Iterator<Item = <Self::ChildDependencies as Dependancy>::ElementBorrowed<'a>>,
|
|
||||||
// >,
|
|
||||||
// context: <Self::Ctx as Dependancy>::ElementBorrowed<'a>,
|
|
||||||
// ) -> bool {
|
|
||||||
// self.0 += 1;
|
|
||||||
// true
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// let mut tree: RealDom<Number> = RealDom::new();
|
|
||||||
// tree.dirty_nodes.insert(TypeId::of::<Number>(), NodeId(0));
|
|
||||||
// tree.update_state(SendAnyMap::new());
|
|
||||||
|
|
||||||
// assert_eq!(tree.get(tree.root()).unwrap().state.0, 1);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// #[test]
|
|
||||||
// fn dependant_node_pass() {
|
|
||||||
// use crate::real_dom::RealDom;
|
|
||||||
|
|
||||||
// #[derive(Debug, Default, Clone, PartialEq)]
|
|
||||||
// struct AddNumber(i32);
|
|
||||||
|
|
||||||
// impl Pass for AddNumber {
|
|
||||||
// type ChildDependencies = ();
|
|
||||||
// type NodeDependencies = (SubtractNumber,);
|
|
||||||
// type ParentDependencies = ();
|
|
||||||
// type Ctx = ();
|
|
||||||
// const MASK: NodeMask = NodeMask::new();
|
|
||||||
|
|
||||||
// fn pass<'a>(
|
|
||||||
// &mut self,
|
|
||||||
// node_view: NodeView,
|
|
||||||
// node: <Self::NodeDependencies as Dependancy>::ElementBorrowed<'a>,
|
|
||||||
// parent: Option<<Self::ParentDependencies as Dependancy>::ElementBorrowed<'a>>,
|
|
||||||
// children: Option<
|
|
||||||
// impl Iterator<Item = <Self::ChildDependencies as Dependancy>::ElementBorrowed<'a>>,
|
|
||||||
// >,
|
|
||||||
// context: <Self::Ctx as Dependancy>::ElementBorrowed<'a>,
|
|
||||||
// ) -> bool {
|
|
||||||
// self.0 += 1;
|
|
||||||
// true
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// #[derive(Debug, Default, Clone, PartialEq)]
|
|
||||||
// struct SubtractNumber(i32);
|
|
||||||
|
|
||||||
// impl Pass for SubtractNumber {
|
|
||||||
// type ChildDependencies = ();
|
|
||||||
// type NodeDependencies = ();
|
|
||||||
// type ParentDependencies = ();
|
|
||||||
// type Ctx = ();
|
|
||||||
// const MASK: NodeMask = NodeMask::new();
|
|
||||||
|
|
||||||
// fn pass<'a>(
|
|
||||||
// &mut self,
|
|
||||||
// node_view: NodeView,
|
|
||||||
// node: <Self::NodeDependencies as Dependancy>::ElementBorrowed<'a>,
|
|
||||||
// parent: Option<<Self::ParentDependencies as Dependancy>::ElementBorrowed<'a>>,
|
|
||||||
// children: Option<
|
|
||||||
// impl Iterator<Item = <Self::ChildDependencies as Dependancy>::ElementBorrowed<'a>>,
|
|
||||||
// >,
|
|
||||||
// context: <Self::Ctx as Dependancy>::ElementBorrowed<'a>,
|
|
||||||
// ) -> bool {
|
|
||||||
// self.0 -= 1;
|
|
||||||
// true
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// #[derive(Debug, Default, Clone, PartialEq)]
|
|
||||||
// struct NumberState {
|
|
||||||
// add_number: AddNumber,
|
|
||||||
// subtract_number: SubtractNumber,
|
|
||||||
// }
|
|
||||||
|
|
||||||
// impl AnyMapLike for NumberState {
|
|
||||||
// fn get<T: Any+Sync+Send>(&self) -> Option<&T> {
|
|
||||||
// if TypeId::of::<AddNumber>() == TypeId::of::<T>() {
|
|
||||||
// Some(unsafe { &*(&self.add_number as *const AddNumber as *const T) })
|
|
||||||
// } else if TypeId::of::<SubtractNumber>() == TypeId::of::<T>() {
|
|
||||||
// Some(unsafe { &*(&self.subtract_number as *const SubtractNumber as *const T) })
|
|
||||||
// } else {
|
|
||||||
// None
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// fn get_mut<T: Any+Sync+Send>(&mut self) -> Option<&mut T> {
|
|
||||||
// if TypeId::of::<AddNumber>() == TypeId::of::<T>() {
|
|
||||||
// Some(unsafe { &mut *(&mut self.add_number as *mut AddNumber as *mut T) })
|
|
||||||
// } else if TypeId::of::<SubtractNumber>() == TypeId::of::<T>() {
|
|
||||||
// Some(unsafe { &mut *(&mut self.subtract_number as *mut SubtractNumber as *mut T) })
|
|
||||||
// } else {
|
|
||||||
// None
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// impl State for NumberState {
|
|
||||||
// fn create_passes() -> Box<[TypeErasedPass<Self>]> {
|
|
||||||
// Box::new([
|
|
||||||
// AddNumber::to_type_erased(),
|
|
||||||
// SubtractNumber::to_type_erased(),
|
|
||||||
// ])
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// let mut tree: RealDom<NumberState> = RealDom::new();
|
|
||||||
// tree.dirty_nodes
|
|
||||||
// .insert(TypeId::of::<SubtractNumber>(), NodeId(0));
|
|
||||||
// tree.update_state(dirty_nodes, SendAnyMap::new());
|
|
||||||
|
|
||||||
// assert_eq!(
|
|
||||||
// tree.get(tree.root()).unwrap().state,
|
|
||||||
// NumberState {
|
|
||||||
// add_number: AddNumber(1),
|
|
||||||
// subtract_number: SubtractNumber(-1)
|
|
||||||
// }
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
|
|
||||||
// #[test]
|
|
||||||
// fn independant_node_pass() {
|
|
||||||
// use crate::real_dom::RealDom;
|
|
||||||
// use crate::tree::{Tree, TreeLike};
|
|
||||||
|
|
||||||
// #[derive(Debug, Default, Clone, PartialEq)]
|
|
||||||
// struct AddNumber(i32);
|
|
||||||
|
|
||||||
// impl Pass for AddNumber {
|
|
||||||
// type ChildDependencies = ();
|
|
||||||
// type NodeDependencies = ();
|
|
||||||
// type ParentDependencies = ();
|
|
||||||
// type Ctx = ();
|
|
||||||
// const MASK: NodeMask = NodeMask::new();
|
|
||||||
|
|
||||||
// fn pass<'a>(
|
|
||||||
// &mut self,
|
|
||||||
// node_view: NodeView,
|
|
||||||
// node: <Self::NodeDependencies as Dependancy>::ElementBorrowed<'a>,
|
|
||||||
// parent: Option<<Self::ParentDependencies as Dependancy>::ElementBorrowed<'a>>,
|
|
||||||
// children: Option<
|
|
||||||
// impl Iterator<Item = <Self::ChildDependencies as Dependancy>::ElementBorrowed<'a>>,
|
|
||||||
// >,
|
|
||||||
// context: <Self::Ctx as Dependancy>::ElementBorrowed<'a>,
|
|
||||||
// ) -> bool {
|
|
||||||
// self.0 += 1;
|
|
||||||
// true
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// #[derive(Debug, Default, Clone, PartialEq)]
|
|
||||||
// struct SubtractNumber(i32);
|
|
||||||
|
|
||||||
// impl Pass for SubtractNumber {
|
|
||||||
// type ChildDependencies = ();
|
|
||||||
// type NodeDependencies = ();
|
|
||||||
// type ParentDependencies = ();
|
|
||||||
// type Ctx = ();
|
|
||||||
// const MASK: NodeMask = NodeMask::new();
|
|
||||||
|
|
||||||
// fn pass<'a>(
|
|
||||||
// &mut self,
|
|
||||||
// node_view: NodeView,
|
|
||||||
// node: <Self::NodeDependencies as Dependancy>::ElementBorrowed<'a>,
|
|
||||||
// parent: Option<<Self::ParentDependencies as Dependancy>::ElementBorrowed<'a>>,
|
|
||||||
// children: Option<
|
|
||||||
// impl Iterator<Item = <Self::ChildDependencies as Dependancy>::ElementBorrowed<'a>>,
|
|
||||||
// >,
|
|
||||||
// context: <Self::Ctx as Dependancy>::ElementBorrowed<'a>,
|
|
||||||
// ) -> bool {
|
|
||||||
// self.0 -= 1;
|
|
||||||
// true
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// #[derive(Debug, Default, Clone, PartialEq)]
|
|
||||||
// struct NumberState {
|
|
||||||
// add_number: AddNumber,
|
|
||||||
// subtract_number: SubtractNumber,
|
|
||||||
// }
|
|
||||||
|
|
||||||
// impl AnyMapLike for NumberState {
|
|
||||||
// fn get<T: Any+Sync+Send>(&self) -> Option<&T> {
|
|
||||||
// if TypeId::of::<AddNumber>() == TypeId::of::<T>() {
|
|
||||||
// Some(unsafe { &*(&self.add_number as *const AddNumber as *const T) })
|
|
||||||
// } else if TypeId::of::<SubtractNumber>() == TypeId::of::<T>() {
|
|
||||||
// Some(unsafe { &*(&self.subtract_number as *const SubtractNumber as *const T) })
|
|
||||||
// } else {
|
|
||||||
// None
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// fn get_mut<T: Any+Sync+Send>(&mut self) -> Option<&mut T> {
|
|
||||||
// if TypeId::of::<AddNumber>() == TypeId::of::<T>() {
|
|
||||||
// Some(unsafe { &mut *(&mut self.add_number as *mut AddNumber as *mut T) })
|
|
||||||
// } else if TypeId::of::<SubtractNumber>() == TypeId::of::<T>() {
|
|
||||||
// Some(unsafe { &mut *(&mut self.subtract_number as *mut SubtractNumber as *mut T) })
|
|
||||||
// } else {
|
|
||||||
// None
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// impl State for NumberState {
|
|
||||||
// fn create_passes() -> Box<[TypeErasedPass<Self>]> {
|
|
||||||
// Box::new([
|
|
||||||
// AddNumber::to_type_erased(),
|
|
||||||
// SubtractNumber::to_type_erased(),
|
|
||||||
// ])
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// let mut tree: RealDom<NumberState> = RealDom::new();
|
|
||||||
// tree.dirty_nodes
|
|
||||||
// .insert(TypeId::of::<SubtractNumber>(), NodeId(0));
|
|
||||||
// tree.update_state(SendAnyMap::new());
|
|
||||||
|
|
||||||
// assert_eq!(
|
|
||||||
// tree.get(tree.root()).unwrap().state,
|
|
||||||
// NumberState {
|
|
||||||
// add_number: AddNumber(0),
|
|
||||||
// subtract_number: SubtractNumber(-1)
|
|
||||||
// }
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
|
|
||||||
// #[test]
|
|
||||||
// fn down_pass() {
|
|
||||||
// use crate::real_dom::RealDom;
|
|
||||||
// use crate::tree::{Tree, TreeLike};
|
|
||||||
|
|
||||||
// #[derive(Debug, Default, Clone, PartialEq)]
|
|
||||||
// struct AddNumber(i32);
|
|
||||||
|
|
||||||
// impl Pass for AddNumber {
|
|
||||||
// type ChildDependencies = ();
|
|
||||||
// type NodeDependencies = ();
|
|
||||||
// type ParentDependencies = (AddNumber,);
|
|
||||||
// type Ctx = ();
|
|
||||||
// const MASK: NodeMask = NodeMask::new();
|
|
||||||
|
|
||||||
// fn pass<'a>(
|
|
||||||
// &mut self,
|
|
||||||
// node_view: NodeView,
|
|
||||||
// node: <Self::NodeDependencies as Dependancy>::ElementBorrowed<'a>,
|
|
||||||
// parent: Option<<Self::ParentDependencies as Dependancy>::ElementBorrowed<'a>>,
|
|
||||||
// children: Option<
|
|
||||||
// impl Iterator<Item = <Self::ChildDependencies as Dependancy>::ElementBorrowed<'a>>,
|
|
||||||
// >,
|
|
||||||
// context: <Self::Ctx as Dependancy>::ElementBorrowed<'a>,
|
|
||||||
// ) -> bool {
|
|
||||||
// if let Some((parent,)) = parent {
|
|
||||||
// *self.0 += *parent.0;
|
|
||||||
// }
|
|
||||||
// true
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// #[derive(Debug, Default, Clone, PartialEq)]
|
|
||||||
// struct NumberState {
|
|
||||||
// add_number: AddNumber,
|
|
||||||
// }
|
|
||||||
|
|
||||||
// impl AnyMapLike for NumberState {
|
|
||||||
// fn get<T: Any+Sync+Send>(&self) -> Option<&T> {
|
|
||||||
// if TypeId::of::<AddNumber>() == TypeId::of::<T>() {
|
|
||||||
// Some(unsafe { &*(&self.add_number as *const AddNumber as *const T) })
|
|
||||||
// } else {
|
|
||||||
// None
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// fn get_mut<T: Any+Sync+Send>(&mut self) -> Option<&mut T> {
|
|
||||||
// if TypeId::of::<AddNumber>() == TypeId::of::<T>() {
|
|
||||||
// Some(unsafe { &mut *(&mut self.add_number as *mut AddNumber as *mut T) })
|
|
||||||
// } else {
|
|
||||||
// None
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// impl State for NumberState {
|
|
||||||
// fn create_passes() -> Box<[TypeErasedPass<Self>]> {
|
|
||||||
// Box::new([AddNumber::to_type_erased()])
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// let mut tree: RealDom<NumberState> = RealDom::new();
|
|
||||||
// let parent = tree.root();
|
|
||||||
// let child1 = tree.create_node(1);
|
|
||||||
// tree.add_child(parent, child1);
|
|
||||||
// let grandchild1 = tree.create_node(1);
|
|
||||||
// tree.add_child(child1, grandchild1);
|
|
||||||
// let child2 = tree.create_node(1);
|
|
||||||
// tree.add_child(parent, child2);
|
|
||||||
// let grandchild2 = tree.create_node(1);
|
|
||||||
// tree.add_child(child2, grandchild2);
|
|
||||||
|
|
||||||
// tree.dirty_nodes
|
|
||||||
// .insert(TypeId::of::<AddNumber>(), NodeId(0));
|
|
||||||
// tree.update_state(SendAnyMap::new());
|
|
||||||
|
|
||||||
// assert_eq!(tree.get(tree.root()).unwrap().state.add_number.0, 1);
|
|
||||||
// assert_eq!(tree.get(child1).unwrap().state.add_number.0, 2);
|
|
||||||
// assert_eq!(tree.get(grandchild1).unwrap().state.add_number.0, 3);
|
|
||||||
// assert_eq!(tree.get(child2).unwrap().state.add_number.0, 2);
|
|
||||||
// assert_eq!(tree.get(grandchild2).unwrap().state.add_number.0, 3);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// #[test]
|
|
||||||
// fn dependant_down_pass() {
|
|
||||||
// use crate::tree::{Tree, TreeLike};
|
|
||||||
// // 0
|
|
||||||
// let mut tree = Tree::new(1);
|
|
||||||
// let parent = tree.root();
|
|
||||||
// // 1
|
|
||||||
// let child1 = tree.create_node(1);
|
|
||||||
// tree.add_child(parent, child1);
|
|
||||||
// // 2
|
|
||||||
// let grandchild1 = tree.create_node(1);
|
|
||||||
// tree.add_child(child1, grandchild1);
|
|
||||||
// // 3
|
|
||||||
// let child2 = tree.create_node(1);
|
|
||||||
// tree.add_child(parent, child2);
|
|
||||||
// // 4
|
|
||||||
// let grandchild2 = tree.create_node(1);
|
|
||||||
// tree.add_child(child2, grandchild2);
|
|
||||||
|
|
||||||
// struct AddPass;
|
|
||||||
// impl Pass for AddPass {
|
|
||||||
// fn pass_id(&self) -> PassId {
|
|
||||||
// PassId(0)
|
|
||||||
// }
|
|
||||||
|
|
||||||
// fn dependancies(&self) -> &'static [PassId] {
|
|
||||||
// &[PassId(1)]
|
|
||||||
// }
|
|
||||||
|
|
||||||
// fn dependants(&self) -> &'static [PassId] {
|
|
||||||
// &[]
|
|
||||||
// }
|
|
||||||
|
|
||||||
// fn mask(&self) -> MemberMask {
|
|
||||||
// MemberMask(0)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// impl DownwardPass<i32> for AddPass {
|
|
||||||
// fn pass(&self, node: &mut i32, parent: Option<&mut i32>, _: &SendAnyMap) -> PassReturn {
|
|
||||||
// if let Some(parent) = parent {
|
|
||||||
// *node += *parent;
|
|
||||||
// } else {
|
|
||||||
// }
|
|
||||||
// PassReturn {
|
|
||||||
// progress: true,
|
|
||||||
// mark_dirty: true,
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// struct SubtractPass;
|
|
||||||
// impl Pass for SubtractPass {
|
|
||||||
// fn pass_id(&self) -> PassId {
|
|
||||||
// PassId(1)
|
|
||||||
// }
|
|
||||||
|
|
||||||
// fn dependancies(&self) -> &'static [PassId] {
|
|
||||||
// &[]
|
|
||||||
// }
|
|
||||||
|
|
||||||
// fn dependants(&self) -> &'static [PassId] {
|
|
||||||
// &[PassId(0)]
|
|
||||||
// }
|
|
||||||
|
|
||||||
// fn mask(&self) -> MemberMask {
|
|
||||||
// MemberMask(0)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// impl DownwardPass<i32> for SubtractPass {
|
|
||||||
// fn pass(&self, node: &mut i32, parent: Option<&mut i32>, _: &SendAnyMap) -> PassReturn {
|
|
||||||
// if let Some(parent) = parent {
|
|
||||||
// *node -= *parent;
|
|
||||||
// } else {
|
|
||||||
// }
|
|
||||||
// PassReturn {
|
|
||||||
// progress: true,
|
|
||||||
// mark_dirty: true,
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// let add_pass = AnyPass::Downward(&AddPass);
|
|
||||||
// let subtract_pass = AnyPass::Downward(&SubtractPass);
|
|
||||||
// let passes = vec![&add_pass, &subtract_pass];
|
|
||||||
// let dirty_nodes: DirtyNodeStates = DirtyNodeStates::default();
|
|
||||||
// dirty_nodes.insert(PassId(1), tree.root());
|
|
||||||
// resolve_passes(&mut tree, dirty_nodes, passes, SendAnyMap::new());
|
|
||||||
|
|
||||||
// // Tree before:
|
|
||||||
// // 1=\
|
|
||||||
// // 1=\
|
|
||||||
// // 1
|
|
||||||
// // 1=\
|
|
||||||
// // 1
|
|
||||||
// // Tree after subtract:
|
|
||||||
// // 1=\
|
|
||||||
// // 0=\
|
|
||||||
// // 1
|
|
||||||
// // 0=\
|
|
||||||
// // 1
|
|
||||||
// // Tree after add:
|
|
||||||
// // 1=\
|
|
||||||
// // 1=\
|
|
||||||
// // 2
|
|
||||||
// // 1=\
|
|
||||||
// // 2
|
|
||||||
// assert_eq!(tree.get(tree.root()).unwrap(), &1);
|
|
||||||
// assert_eq!(tree.get(child1).unwrap(), &1);
|
|
||||||
// assert_eq!(tree.get(grandchild1).unwrap(), &2);
|
|
||||||
// assert_eq!(tree.get(child2).unwrap(), &1);
|
|
||||||
// assert_eq!(tree.get(grandchild2).unwrap(), &2);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// #[test]
|
|
||||||
// fn up_pass() {
|
|
||||||
// use crate::tree::{Tree, TreeLike};
|
|
||||||
// // Tree before:
|
|
||||||
// // 0=\
|
|
||||||
// // 0=\
|
|
||||||
// // 1
|
|
||||||
// // 0=\
|
|
||||||
// // 1
|
|
||||||
// // Tree after:
|
|
||||||
// // 2=\
|
|
||||||
// // 1=\
|
|
||||||
// // 1
|
|
||||||
// // 1=\
|
|
||||||
// // 1
|
|
||||||
// let mut tree = Tree::new(0);
|
|
||||||
// let parent = tree.root();
|
|
||||||
// let child1 = tree.create_node(0);
|
|
||||||
// tree.add_child(parent, child1);
|
|
||||||
// let grandchild1 = tree.create_node(1);
|
|
||||||
// tree.add_child(child1, grandchild1);
|
|
||||||
// let child2 = tree.create_node(0);
|
|
||||||
// tree.add_child(parent, child2);
|
|
||||||
// let grandchild2 = tree.create_node(1);
|
|
||||||
// tree.add_child(child2, grandchild2);
|
|
||||||
|
|
||||||
// struct AddPass;
|
|
||||||
// impl Pass for AddPass {
|
|
||||||
// fn pass_id(&self) -> PassId {
|
|
||||||
// PassId(0)
|
|
||||||
// }
|
|
||||||
|
|
||||||
// fn dependancies(&self) -> &'static [PassId] {
|
|
||||||
// &[]
|
|
||||||
// }
|
|
||||||
|
|
||||||
// fn dependants(&self) -> &'static [PassId] {
|
|
||||||
// &[]
|
|
||||||
// }
|
|
||||||
|
|
||||||
// fn mask(&self) -> MemberMask {
|
|
||||||
// MemberMask(0)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// impl UpwardPass<i32> for AddPass {
|
|
||||||
// fn pass<'a>(
|
|
||||||
// &self,
|
|
||||||
// node: &mut i32,
|
|
||||||
// children: &mut dyn Iterator<Item = &'a mut i32>,
|
|
||||||
// _: &SendAnyMap,
|
|
||||||
// ) -> PassReturn {
|
|
||||||
// *node += children.map(|i| *i).sum::<i32>();
|
|
||||||
// PassReturn {
|
|
||||||
// progress: true,
|
|
||||||
// mark_dirty: true,
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// let add_pass = AnyPass::Upward(&AddPass);
|
|
||||||
// let passes = vec![&add_pass];
|
|
||||||
// let dirty_nodes: DirtyNodeStates = DirtyNodeStates::default();
|
|
||||||
// dirty_nodes.insert(PassId(0), grandchild1);
|
|
||||||
// dirty_nodes.insert(PassId(0), grandchild2);
|
|
||||||
// resolve_passes(&mut tree, dirty_nodes, passes, SendAnyMap::new());
|
|
||||||
|
|
||||||
// assert_eq!(tree.get(tree.root()).unwrap(), &2);
|
|
||||||
// assert_eq!(tree.get(child1).unwrap(), &1);
|
|
||||||
// assert_eq!(tree.get(grandchild1).unwrap(), &1);
|
|
||||||
// assert_eq!(tree.get(child2).unwrap(), &1);
|
|
||||||
// assert_eq!(tree.get(grandchild2).unwrap(), &1);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// #[test]
|
|
||||||
// fn dependant_up_pass() {
|
|
||||||
// use crate::tree::{Tree, TreeLike};
|
|
||||||
// // 0
|
|
||||||
// let mut tree = Tree::new(0);
|
|
||||||
// let parent = tree.root();
|
|
||||||
// // 1
|
|
||||||
// let child1 = tree.create_node(0);
|
|
||||||
// tree.add_child(parent, child1);
|
|
||||||
// // 2
|
|
||||||
// let grandchild1 = tree.create_node(1);
|
|
||||||
// tree.add_child(child1, grandchild1);
|
|
||||||
// // 3
|
|
||||||
// let child2 = tree.create_node(0);
|
|
||||||
// tree.add_child(parent, child2);
|
|
||||||
// // 4
|
|
||||||
// let grandchild2 = tree.create_node(1);
|
|
||||||
// tree.add_child(child2, grandchild2);
|
|
||||||
|
|
||||||
// struct AddPass;
|
|
||||||
// impl Pass for AddPass {
|
|
||||||
// fn pass_id(&self) -> PassId {
|
|
||||||
// PassId(0)
|
|
||||||
// }
|
|
||||||
|
|
||||||
// fn dependancies(&self) -> &'static [PassId] {
|
|
||||||
// &[PassId(1)]
|
|
||||||
// }
|
|
||||||
|
|
||||||
// fn dependants(&self) -> &'static [PassId] {
|
|
||||||
// &[]
|
|
||||||
// }
|
|
||||||
|
|
||||||
// fn mask(&self) -> MemberMask {
|
|
||||||
// MemberMask(0)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// impl UpwardPass<i32> for AddPass {
|
|
||||||
// fn pass<'a>(
|
|
||||||
// &self,
|
|
||||||
// node: &mut i32,
|
|
||||||
// children: &mut dyn Iterator<Item = &'a mut i32>,
|
|
||||||
// _: &SendAnyMap,
|
|
||||||
// ) -> PassReturn {
|
|
||||||
// *node += children.map(|i| *i).sum::<i32>();
|
|
||||||
// PassReturn {
|
|
||||||
// progress: true,
|
|
||||||
// mark_dirty: true,
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// struct SubtractPass;
|
|
||||||
// impl Pass for SubtractPass {
|
|
||||||
// fn pass_id(&self) -> PassId {
|
|
||||||
// PassId(1)
|
|
||||||
// }
|
|
||||||
|
|
||||||
// fn dependancies(&self) -> &'static [PassId] {
|
|
||||||
// &[]
|
|
||||||
// }
|
|
||||||
|
|
||||||
// fn dependants(&self) -> &'static [PassId] {
|
|
||||||
// &[PassId(0)]
|
|
||||||
// }
|
|
||||||
|
|
||||||
// fn mask(&self) -> MemberMask {
|
|
||||||
// MemberMask(0)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// impl UpwardPass<i32> for SubtractPass {
|
|
||||||
// fn pass<'a>(
|
|
||||||
// &self,
|
|
||||||
// node: &mut i32,
|
|
||||||
// children: &mut dyn Iterator<Item = &'a mut i32>,
|
|
||||||
// _: &SendAnyMap,
|
|
||||||
// ) -> PassReturn {
|
|
||||||
// *node -= children.map(|i| *i).sum::<i32>();
|
|
||||||
// PassReturn {
|
|
||||||
// progress: true,
|
|
||||||
// mark_dirty: true,
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// let add_pass = AnyPass::Upward(&AddPass);
|
|
||||||
// let subtract_pass = AnyPass::Upward(&SubtractPass);
|
|
||||||
// let passes = vec![&add_pass, &subtract_pass];
|
|
||||||
// let dirty_nodes: DirtyNodeStates = DirtyNodeStates::default();
|
|
||||||
// dirty_nodes.insert(PassId(1), grandchild1);
|
|
||||||
// dirty_nodes.insert(PassId(1), grandchild2);
|
|
||||||
// resolve_passes(&mut tree, dirty_nodes, passes, SendAnyMap::new());
|
|
||||||
|
|
||||||
// // Tree before:
|
|
||||||
// // 0=\
|
|
||||||
// // 0=\
|
|
||||||
// // 1
|
|
||||||
// // 0=\
|
|
||||||
// // 1
|
|
||||||
// // Tree after subtract:
|
|
||||||
// // 2=\
|
|
||||||
// // -1=\
|
|
||||||
// // 1
|
|
||||||
// // -1=\
|
|
||||||
// // 1
|
|
||||||
// // Tree after add:
|
|
||||||
// // 2=\
|
|
||||||
// // 0=\
|
|
||||||
// // 1
|
|
||||||
// // 0=\
|
|
||||||
// // 1
|
|
||||||
// assert_eq!(tree.get(tree.root()).unwrap(), &2);
|
|
||||||
// assert_eq!(tree.get(child1).unwrap(), &0);
|
|
||||||
// assert_eq!(tree.get(grandchild1).unwrap(), &1);
|
|
||||||
// assert_eq!(tree.get(child2).unwrap(), &0);
|
|
||||||
// assert_eq!(tree.get(grandchild2).unwrap(), &1);
|
|
||||||
// }
|
|
||||||
@@ -1,15 +1,13 @@
|
|||||||
use dioxus_core::{BorrowedAttributeValue, ElementId, Mutations, TemplateNode};
|
|
||||||
|
|
||||||
use rustc_hash::{FxHashMap, FxHashSet};
|
use rustc_hash::{FxHashMap, FxHashSet};
|
||||||
use std::any::{Any, TypeId};
|
use std::any::{Any, TypeId};
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
|
|
||||||
use crate::node::{
|
use crate::node::{
|
||||||
ElementNode, FromAnyValue, NodeData, NodeType, OwnedAttributeDiscription, OwnedAttributeValue,
|
ElementNode, FromAnyValue, NodeType, OwnedAttributeDiscription, OwnedAttributeValue,
|
||||||
};
|
};
|
||||||
use crate::node_ref::{AttributeMask, NodeMask, NodeMaskBuilder};
|
use crate::node_ref::{AttributeMask, NodeMask, NodeMaskBuilder};
|
||||||
use crate::passes::{resolve_passes, DirtyNodeStates, TypeErasedPass};
|
use crate::passes::{resolve_passes, DirtyNodeStates, TypeErasedPass};
|
||||||
use crate::tree::{EntryBuilder, NodeId, Tree};
|
use crate::tree::{NodeId, Tree};
|
||||||
use crate::{FxDashSet, SendAnyMap};
|
use crate::{FxDashSet, SendAnyMap};
|
||||||
|
|
||||||
/// A Dom that can sync with the VirtualDom mutations intended for use in lazy renderers.
|
/// A Dom that can sync with the VirtualDom mutations intended for use in lazy renderers.
|
||||||
@@ -20,11 +18,7 @@ use crate::{FxDashSet, SendAnyMap};
|
|||||||
/// 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.
|
/// To allow custom values to be passed into attributes implement FromAnyValue on a type that can represent your custom value and specify the V generic to be that type. If you have many different custom values, it can be useful to use a enum type to represent the varients.
|
||||||
pub struct RealDom<V: FromAnyValue + Send + Sync = ()> {
|
pub struct RealDom<V: FromAnyValue + Send + Sync = ()> {
|
||||||
pub(crate) tree: Tree,
|
pub(crate) tree: Tree,
|
||||||
/// a map from element id to real node id
|
|
||||||
node_id_mapping: Vec<Option<NodeId>>,
|
|
||||||
nodes_listening: FxHashMap<String, FxHashSet<NodeId>>,
|
nodes_listening: FxHashMap<String, FxHashSet<NodeId>>,
|
||||||
stack: Vec<NodeId>,
|
|
||||||
templates: FxHashMap<String, Vec<NodeId>>,
|
|
||||||
pub(crate) passes: Box<[TypeErasedPass<V>]>,
|
pub(crate) passes: Box<[TypeErasedPass<V>]>,
|
||||||
passes_updated: FxHashMap<NodeId, FxHashSet<TypeId>>,
|
passes_updated: FxHashMap<NodeId, FxHashSet<TypeId>>,
|
||||||
nodes_updated: FxHashMap<NodeId, NodeMask>,
|
nodes_updated: FxHashMap<NodeId, NodeMask>,
|
||||||
@@ -34,19 +28,17 @@ pub struct RealDom<V: FromAnyValue + Send + Sync = ()> {
|
|||||||
impl<V: FromAnyValue + Send + Sync> RealDom<V> {
|
impl<V: FromAnyValue + Send + Sync> RealDom<V> {
|
||||||
pub fn new(mut passes: Box<[TypeErasedPass<V>]>) -> RealDom<V> {
|
pub fn new(mut passes: Box<[TypeErasedPass<V>]>) -> RealDom<V> {
|
||||||
let mut tree = Tree::new();
|
let mut tree = Tree::new();
|
||||||
tree.insert_slab::<NodeData<V>>();
|
tree.insert_slab::<NodeType<V>>();
|
||||||
for pass in passes.iter() {
|
for pass in passes.iter() {
|
||||||
(pass.create)(&mut tree);
|
(pass.create)(&mut tree);
|
||||||
}
|
}
|
||||||
let root_id = tree.root();
|
let root_id = tree.root();
|
||||||
let mut root_node: NodeData<V> = NodeData::new(NodeType::Element(ElementNode {
|
let root_node: NodeType<V> = NodeType::Element(ElementNode {
|
||||||
tag: "Root".to_string(),
|
tag: "Root".to_string(),
|
||||||
namespace: Some("Root".to_string()),
|
namespace: Some("Root".to_string()),
|
||||||
attributes: FxHashMap::default(),
|
attributes: FxHashMap::default(),
|
||||||
listeners: FxHashSet::default(),
|
listeners: FxHashSet::default(),
|
||||||
}));
|
});
|
||||||
root_node.element_id = Some(ElementId(0));
|
|
||||||
root_node.node_id = root_id;
|
|
||||||
tree.insert(root_id, root_node);
|
tree.insert(root_id, root_node);
|
||||||
|
|
||||||
// resolve dependants for each pass
|
// resolve dependants for each pass
|
||||||
@@ -71,10 +63,7 @@ impl<V: FromAnyValue + Send + Sync> RealDom<V> {
|
|||||||
|
|
||||||
RealDom {
|
RealDom {
|
||||||
tree,
|
tree,
|
||||||
node_id_mapping: vec![Some(root_id)],
|
|
||||||
nodes_listening: FxHashMap::default(),
|
nodes_listening: FxHashMap::default(),
|
||||||
stack: vec![root_id],
|
|
||||||
templates: FxHashMap::default(),
|
|
||||||
passes,
|
passes,
|
||||||
passes_updated,
|
passes_updated,
|
||||||
nodes_updated,
|
nodes_updated,
|
||||||
@@ -114,239 +103,23 @@ impl<V: FromAnyValue + Send + Sync> RealDom<V> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn element_to_node_id(&self, element_id: ElementId) -> NodeId {
|
pub fn create_node(&mut self, node: NodeType<V>, mark_dirty: bool) -> NodeMut<'_, V> {
|
||||||
self.node_id_mapping.get(element_id.0).unwrap().unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_element_id(&mut self, node_id: NodeId, element_id: ElementId) {
|
|
||||||
let mut node = self.tree.get_mut::<NodeData>(node_id).unwrap();
|
|
||||||
let node_id = node.node_id;
|
|
||||||
node.element_id = Some(element_id);
|
|
||||||
if self.node_id_mapping.len() <= element_id.0 {
|
|
||||||
self.node_id_mapping.resize(element_id.0 + 1, None);
|
|
||||||
}
|
|
||||||
self.node_id_mapping[element_id.0] = Some(node_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn load_child(&self, path: &[u8]) -> NodeId {
|
|
||||||
let mut current = *self.stack.last().unwrap();
|
|
||||||
for i in path {
|
|
||||||
current = self.tree.children_ids(current).unwrap()[*i as usize];
|
|
||||||
}
|
|
||||||
current
|
|
||||||
}
|
|
||||||
|
|
||||||
fn create_node(
|
|
||||||
&mut self,
|
|
||||||
mut node: NodeData<V>,
|
|
||||||
id: Option<ElementId>,
|
|
||||||
mark_dirty: bool,
|
|
||||||
) -> EntryBuilder<'_> {
|
|
||||||
let mut node_entry = self.tree.create_node();
|
let mut node_entry = self.tree.create_node();
|
||||||
let node_id = node_entry.id();
|
let id = node_entry.id();
|
||||||
if mark_dirty {
|
if mark_dirty {
|
||||||
self.passes_updated
|
self.passes_updated
|
||||||
.entry(node_id)
|
.entry(id)
|
||||||
.or_default()
|
.or_default()
|
||||||
.extend(self.passes.iter().map(|x| x.this_type_id));
|
.extend(self.passes.iter().map(|x| x.this_type_id));
|
||||||
}
|
}
|
||||||
node.node_id = node_id;
|
|
||||||
node.element_id = id;
|
|
||||||
node_entry.insert(node);
|
node_entry.insert(node);
|
||||||
node_entry
|
NodeMut::new(id, self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_child(&mut self, node_id: NodeId, child_id: NodeId) {
|
pub fn add_child(&mut self, node_id: NodeId, child_id: NodeId) {
|
||||||
self.tree.add_child(node_id, child_id);
|
self.tree.add_child(node_id, child_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_template_node(&mut self, node: &TemplateNode) -> NodeId {
|
|
||||||
match node {
|
|
||||||
TemplateNode::Element {
|
|
||||||
tag,
|
|
||||||
namespace,
|
|
||||||
attrs,
|
|
||||||
children,
|
|
||||||
} => {
|
|
||||||
let node = NodeData::new(NodeType::Element(ElementNode {
|
|
||||||
tag: tag.to_string(),
|
|
||||||
namespace: namespace.map(|s| s.to_string()),
|
|
||||||
attributes: attrs
|
|
||||||
.iter()
|
|
||||||
.filter_map(|attr| match attr {
|
|
||||||
dioxus_core::TemplateAttribute::Static {
|
|
||||||
name,
|
|
||||||
value,
|
|
||||||
namespace,
|
|
||||||
} => Some((
|
|
||||||
OwnedAttributeDiscription {
|
|
||||||
namespace: namespace.map(|s| s.to_string()),
|
|
||||||
name: name.to_string(),
|
|
||||||
volatile: false,
|
|
||||||
},
|
|
||||||
OwnedAttributeValue::Text(value.to_string()),
|
|
||||||
)),
|
|
||||||
dioxus_core::TemplateAttribute::Dynamic { .. } => None,
|
|
||||||
})
|
|
||||||
.collect(),
|
|
||||||
listeners: FxHashSet::default(),
|
|
||||||
}));
|
|
||||||
let node_id = self.create_node(node, None, true).id();
|
|
||||||
for child in *children {
|
|
||||||
let child_id = self.create_template_node(child);
|
|
||||||
self.add_child(node_id, child_id);
|
|
||||||
}
|
|
||||||
node_id
|
|
||||||
}
|
|
||||||
TemplateNode::Text { text } => self
|
|
||||||
.create_node(NodeData::new(NodeType::Text(text.to_string())), None, true)
|
|
||||||
.id(),
|
|
||||||
TemplateNode::Dynamic { .. } => self
|
|
||||||
.create_node(NodeData::new(NodeType::Placeholder), None, true)
|
|
||||||
.id(),
|
|
||||||
TemplateNode::DynamicText { .. } => self
|
|
||||||
.create_node(NodeData::new(NodeType::Text(String::new())), None, true)
|
|
||||||
.id(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Updates the dom with some mutations and return a set of nodes that were updated. Pass the dirty nodes to update_state.
|
|
||||||
pub fn apply_mutations(&mut self, mutations: Mutations) {
|
|
||||||
for template in mutations.templates {
|
|
||||||
let mut template_root_ids = Vec::new();
|
|
||||||
for root in template.roots {
|
|
||||||
let id = self.create_template_node(root);
|
|
||||||
template_root_ids.push(id);
|
|
||||||
}
|
|
||||||
self.templates
|
|
||||||
.insert(template.name.to_string(), template_root_ids);
|
|
||||||
}
|
|
||||||
|
|
||||||
for e in mutations.edits {
|
|
||||||
use dioxus_core::Mutation::*;
|
|
||||||
match e {
|
|
||||||
AppendChildren { id, m } => {
|
|
||||||
let children = self.stack.split_off(self.stack.len() - m);
|
|
||||||
let parent = self.element_to_node_id(id);
|
|
||||||
for child in children {
|
|
||||||
self.add_child(parent, child);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
AssignId { path, id } => {
|
|
||||||
self.set_element_id(self.load_child(path), id);
|
|
||||||
}
|
|
||||||
CreatePlaceholder { id } => {
|
|
||||||
let node = NodeData::new(NodeType::Placeholder);
|
|
||||||
let node_id = self.create_node(node, None, true).id();
|
|
||||||
self.set_element_id(node_id, id);
|
|
||||||
self.stack.push(node_id);
|
|
||||||
}
|
|
||||||
CreateTextNode { value, id } => {
|
|
||||||
let node_data = NodeData::new(NodeType::Text(value.to_string()));
|
|
||||||
let node_id = self.create_node(node_data, None, true).id();
|
|
||||||
self.set_element_id(node_id, id);
|
|
||||||
self.stack.push(node_id);
|
|
||||||
}
|
|
||||||
HydrateText { path, value, id } => {
|
|
||||||
let node_id = self.load_child(path);
|
|
||||||
self.set_element_id(node_id, id);
|
|
||||||
let mut node = self.get_mut(node_id).unwrap();
|
|
||||||
if let NodeTypeMut::Text(text) = node.node_type_mut() {
|
|
||||||
*text = value.to_string();
|
|
||||||
} else {
|
|
||||||
node.set_type(NodeType::Text(value.to_string()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
LoadTemplate { name, index, id } => {
|
|
||||||
let template_id = self.templates[name][index];
|
|
||||||
let clone_id = self.clone_node(template_id);
|
|
||||||
self.set_element_id(clone_id, id);
|
|
||||||
self.stack.push(clone_id);
|
|
||||||
}
|
|
||||||
ReplaceWith { id, m } => {
|
|
||||||
let new_nodes = self.stack.split_off(self.stack.len() - m);
|
|
||||||
let old_node_id = self.element_to_node_id(id);
|
|
||||||
for new in new_nodes {
|
|
||||||
self.insert_before(old_node_id, new);
|
|
||||||
}
|
|
||||||
self.remove(old_node_id);
|
|
||||||
}
|
|
||||||
ReplacePlaceholder { path, m } => {
|
|
||||||
let new_nodes = self.stack.split_off(self.stack.len() - m);
|
|
||||||
let old_node_id = self.load_child(path);
|
|
||||||
for new in new_nodes {
|
|
||||||
self.insert_before(old_node_id, new);
|
|
||||||
}
|
|
||||||
self.remove(old_node_id);
|
|
||||||
}
|
|
||||||
InsertAfter { id, m } => {
|
|
||||||
let new_nodes = self.stack.split_off(self.stack.len() - m);
|
|
||||||
let old_node_id = self.element_to_node_id(id);
|
|
||||||
for new in new_nodes.into_iter().rev() {
|
|
||||||
self.insert_after(old_node_id, new);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
InsertBefore { id, m } => {
|
|
||||||
let new_nodes = self.stack.split_off(self.stack.len() - m);
|
|
||||||
let old_node_id = self.element_to_node_id(id);
|
|
||||||
for new in new_nodes {
|
|
||||||
self.tree.insert_before(old_node_id, new);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SetAttribute {
|
|
||||||
name,
|
|
||||||
value,
|
|
||||||
id,
|
|
||||||
ns,
|
|
||||||
} => {
|
|
||||||
let node_id = self.element_to_node_id(id);
|
|
||||||
let mut node = self.get_mut(node_id).unwrap();
|
|
||||||
if let NodeTypeMut::Element(element) = &mut node.node_type_mut() {
|
|
||||||
if let BorrowedAttributeValue::None = &value {
|
|
||||||
element.remove_attributes(&OwnedAttributeDiscription {
|
|
||||||
name: name.to_string(),
|
|
||||||
namespace: ns.map(|s| s.to_string()),
|
|
||||||
volatile: false,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
element.set_attribute(
|
|
||||||
OwnedAttributeDiscription {
|
|
||||||
name: name.to_string(),
|
|
||||||
namespace: ns.map(|s| s.to_string()),
|
|
||||||
volatile: false,
|
|
||||||
},
|
|
||||||
OwnedAttributeValue::from(value),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SetText { value, id } => {
|
|
||||||
let node_id = self.element_to_node_id(id);
|
|
||||||
let mut node = self.get_mut(node_id).unwrap();
|
|
||||||
if let NodeTypeMut::Text(text) = node.node_type_mut() {
|
|
||||||
*text = value.to_string();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
NewEventListener { name, id } => {
|
|
||||||
let node_id = self.element_to_node_id(id);
|
|
||||||
self.add_event_listener(node_id, name);
|
|
||||||
}
|
|
||||||
RemoveEventListener { id, name } => {
|
|
||||||
let node_id = self.element_to_node_id(id);
|
|
||||||
self.remove_event_listener(node_id, name);
|
|
||||||
}
|
|
||||||
Remove { id } => {
|
|
||||||
let node_id = self.element_to_node_id(id);
|
|
||||||
self.remove(node_id);
|
|
||||||
}
|
|
||||||
PushRoot { id } => {
|
|
||||||
let node_id = self.element_to_node_id(id);
|
|
||||||
self.stack.push(node_id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Find all nodes that are listening for an event, sorted by there height in the dom progressing starting at the bottom and progressing up.
|
/// 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.
|
/// This can be useful to avoid creating duplicate events.
|
||||||
pub fn get_listening_sorted(&self, event: &str) -> Vec<NodeRef<V>> {
|
pub fn get_listening_sorted(&self, event: &str) -> Vec<NodeRef<V>> {
|
||||||
@@ -376,10 +149,10 @@ impl<V: FromAnyValue + Send + Sync> RealDom<V> {
|
|||||||
self.tree.root()
|
self.tree.root()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clone_node(&mut self, node_id: NodeId) -> NodeId {
|
pub fn clone_node(&mut self, node_id: NodeId) -> NodeId {
|
||||||
let node = self.get(node_id).unwrap();
|
let node = self.get(node_id).unwrap();
|
||||||
let new_node = node.node_data().clone();
|
let new_node = node.node_type().clone();
|
||||||
let new_id = self.create_node(new_node, None, true).id();
|
let new_id = self.create_node(new_node, true).id();
|
||||||
|
|
||||||
let children = self.tree.children_ids(node_id).unwrap().to_vec();
|
let children = self.tree.children_ids(node_id).unwrap().to_vec();
|
||||||
for child in children {
|
for child in children {
|
||||||
@@ -389,26 +162,18 @@ impl<V: FromAnyValue + Send + Sync> RealDom<V> {
|
|||||||
new_id
|
new_id
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn root(&self) -> NodeId {
|
pub fn get(&self, id: NodeId) -> Option<NodeRef<'_, V>> {
|
||||||
self.tree.root()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get(&self, id: impl IntoNodeId<V>) -> Option<NodeRef<'_, V>> {
|
|
||||||
let id = id.into_node_id(self);
|
let id = id.into_node_id(self);
|
||||||
self.tree.contains(id).then_some(NodeRef { id, dom: self })
|
self.tree.contains(id).then_some(NodeRef { id, dom: self })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_mut(&mut self, id: impl IntoNodeId<V>) -> Option<NodeMut<'_, V>> {
|
pub fn get_mut(&mut self, id: NodeId) -> Option<NodeMut<'_, V>> {
|
||||||
let id = id.into_node_id(self);
|
let id = id.into_node_id(self);
|
||||||
self.tree.contains(id).then(|| NodeMut {
|
self.tree.contains(id).then(|| NodeMut::new(id, self))
|
||||||
id,
|
|
||||||
dirty: NodeMask::default(),
|
|
||||||
dom: self,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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.
|
/// 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: impl IntoNodeId<V>) -> Option<NodeMutRaw<V>> {
|
pub fn get_mut_raw(&mut self, id: NodeId) -> Option<NodeMutRaw<V>> {
|
||||||
let id = id.into_node_id(self);
|
let id = id.into_node_id(self);
|
||||||
self.tree
|
self.tree
|
||||||
.contains(id)
|
.contains(id)
|
||||||
@@ -439,7 +204,7 @@ impl<V: FromAnyValue + Send + Sync> RealDom<V> {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove(&mut self, id: NodeId) {
|
pub fn remove(&mut self, id: NodeId) {
|
||||||
if let Some(parent_id) = self.tree.parent_id(id) {
|
if let Some(parent_id) = self.tree.parent_id(id) {
|
||||||
self.mark_child_changed(parent_id);
|
self.mark_child_changed(parent_id);
|
||||||
}
|
}
|
||||||
@@ -454,52 +219,8 @@ impl<V: FromAnyValue + Send + Sync> RealDom<V> {
|
|||||||
self.tree.replace(old, new);
|
self.tree.replace(old, new);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn insert_before(&mut self, id: NodeId, new: NodeId) {
|
|
||||||
if let Some(parent_id) = self.tree.parent_id(id) {
|
|
||||||
self.mark_child_changed(parent_id);
|
|
||||||
self.mark_parent_added_or_removed(new);
|
|
||||||
}
|
|
||||||
self.tree.insert_before(id, new);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn insert_after(&mut self, id: NodeId, new: NodeId) {
|
|
||||||
if let Some(parent_id) = self.tree.parent_id(id) {
|
|
||||||
self.mark_child_changed(parent_id);
|
|
||||||
self.mark_parent_added_or_removed(new);
|
|
||||||
}
|
|
||||||
self.tree.insert_after(id, new);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn add_event_listener(&mut self, id: NodeId, event: &str) {
|
|
||||||
let mut node = self.get_mut(id).unwrap();
|
|
||||||
if let NodeTypeMut::Element(mut element) = node.node_type_mut() {
|
|
||||||
element.listeners_mut().insert(event.to_string());
|
|
||||||
drop(node);
|
|
||||||
match self.nodes_listening.get_mut(event) {
|
|
||||||
Some(hs) => {
|
|
||||||
hs.insert(id);
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
let mut hs = FxHashSet::default();
|
|
||||||
hs.insert(id);
|
|
||||||
self.nodes_listening.insert(event.to_string(), hs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn remove_event_listener(&mut self, id: NodeId, event: &str) {
|
|
||||||
{
|
|
||||||
let mut node = self.get_mut(id).unwrap();
|
|
||||||
if let NodeTypeMut::Element(mut element) = node.node_type_mut() {
|
|
||||||
element.listeners_mut().remove(event);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self.nodes_listening.get_mut(event).unwrap().remove(&id);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn traverse_depth_first(&self, mut f: impl FnMut(NodeRef<V>)) {
|
pub fn traverse_depth_first(&self, mut f: impl FnMut(NodeRef<V>)) {
|
||||||
let mut stack = vec![self.root()];
|
let mut stack = vec![self.root_id()];
|
||||||
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);
|
||||||
@@ -512,7 +233,7 @@ impl<V: FromAnyValue + Send + Sync> RealDom<V> {
|
|||||||
|
|
||||||
pub fn traverse_breadth_first(&self, mut f: impl FnMut(NodeRef<V>)) {
|
pub fn traverse_breadth_first(&self, mut f: impl FnMut(NodeRef<V>)) {
|
||||||
let mut queue = VecDeque::new();
|
let mut queue = VecDeque::new();
|
||||||
queue.push_back(self.root());
|
queue.push_back(self.root_id());
|
||||||
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);
|
||||||
@@ -526,7 +247,7 @@ impl<V: FromAnyValue + Send + Sync> RealDom<V> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn traverse_depth_first_mut(&mut self, mut f: impl FnMut(NodeMut<V>)) {
|
pub fn traverse_depth_first_mut(&mut self, mut f: impl FnMut(NodeMut<V>)) {
|
||||||
let mut stack = vec![self.root()];
|
let mut stack = vec![self.root_id()];
|
||||||
while let Some(id) = stack.pop() {
|
while let Some(id) = stack.pop() {
|
||||||
if let Some(children) = self.tree.children_ids(id) {
|
if let Some(children) = self.tree.children_ids(id) {
|
||||||
let children = children.iter().copied().rev().collect::<Vec<_>>();
|
let children = children.iter().copied().rev().collect::<Vec<_>>();
|
||||||
@@ -541,7 +262,7 @@ impl<V: FromAnyValue + Send + Sync> RealDom<V> {
|
|||||||
|
|
||||||
pub fn traverse_breadth_first_mut(&mut self, mut f: impl FnMut(NodeMut<V>)) {
|
pub fn traverse_breadth_first_mut(&mut self, mut f: impl FnMut(NodeMut<V>)) {
|
||||||
let mut queue = VecDeque::new();
|
let mut queue = VecDeque::new();
|
||||||
queue.push_back(self.root());
|
queue.push_back(self.root_id());
|
||||||
while let Some(id) = queue.pop_front() {
|
while let Some(id) = queue.pop_front() {
|
||||||
if let Some(children) = self.tree.children_ids(id) {
|
if let Some(children) = self.tree.children_ids(id) {
|
||||||
let children = children.to_vec();
|
let children = children.to_vec();
|
||||||
@@ -554,6 +275,10 @@ impl<V: FromAnyValue + Send + Sync> RealDom<V> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn insert_slab<T: Any + Send + Sync>(&mut self) {
|
||||||
|
self.tree.insert_slab::<T>();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait IntoNodeId<V: FromAnyValue + Send + Sync> {
|
pub trait IntoNodeId<V: FromAnyValue + Send + Sync> {
|
||||||
@@ -566,27 +291,13 @@ impl<V: FromAnyValue + Send + Sync> IntoNodeId<V> for NodeId {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<V: FromAnyValue + Send + Sync> IntoNodeId<V> for ElementId {
|
|
||||||
fn into_node_id(self, rdom: &RealDom<V>) -> NodeId {
|
|
||||||
rdom.element_to_node_id(self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait NodeImmutable<V: FromAnyValue + Send + Sync>: Sized {
|
pub trait NodeImmutable<V: FromAnyValue + Send + Sync>: Sized {
|
||||||
fn real_dom(&self) -> &RealDom<V>;
|
fn real_dom(&self) -> &RealDom<V>;
|
||||||
|
|
||||||
fn id(&self) -> NodeId;
|
fn id(&self) -> NodeId;
|
||||||
|
|
||||||
fn mounted_id(&self) -> Option<ElementId> {
|
|
||||||
self.node_data().mounted_id()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn node_data(&self) -> &NodeData<V> {
|
|
||||||
self.get().unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn node_type(&self) -> &NodeType<V> {
|
fn node_type(&self) -> &NodeType<V> {
|
||||||
&self.node_data().node_type
|
self.get().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get<T: Any + Sync + Send>(&self) -> Option<&T> {
|
fn get<T: Any + Sync + Send>(&self) -> Option<&T> {
|
||||||
@@ -621,8 +332,29 @@ pub trait NodeImmutable<V: FromAnyValue + Send + Sync>: Sized {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub trait NodeMutable<V: FromAnyValue + Send + Sync>: Sized + NodeImmutable<V> {
|
pub trait NodeMutable<V: FromAnyValue + Send + Sync>: Sized + NodeImmutable<V> {
|
||||||
fn get_mut<T: Any + Sync + Send>(&mut self) -> Option<&mut T>;
|
fn real_dom_mut(&mut self) -> &mut RealDom<V>;
|
||||||
fn insert<T: Any + Sync + Send>(&mut self, value: T);
|
fn get_mut<T: Any + Sync + Send>(&mut self) -> Option<&mut T> {
|
||||||
|
let id = self.id();
|
||||||
|
self.real_dom_mut().tree.get_mut(id)
|
||||||
|
}
|
||||||
|
fn insert<T: Any + Sync + Send>(&mut self, value: T) {
|
||||||
|
let id = self.id();
|
||||||
|
self.real_dom_mut().tree.insert(id, value);
|
||||||
|
}
|
||||||
|
fn add_child(&mut self, child: NodeId) {
|
||||||
|
let id = self.id();
|
||||||
|
self.real_dom_mut().tree.add_child(id, child);
|
||||||
|
}
|
||||||
|
fn insert_after(&mut self, old: NodeId) {
|
||||||
|
let id = self.id();
|
||||||
|
self.real_dom_mut().tree.insert_after(old, id);
|
||||||
|
}
|
||||||
|
fn insert_before(&mut self, old: NodeId) {
|
||||||
|
let id = self.id();
|
||||||
|
self.real_dom_mut().tree.insert_before(old, id);
|
||||||
|
}
|
||||||
|
fn add_event_listener(&mut self, event: &str);
|
||||||
|
fn remove_event_listener(&mut self, event: &str);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
@@ -647,6 +379,16 @@ pub struct NodeMut<'a, V: FromAnyValue + Send + Sync = ()> {
|
|||||||
dirty: NodeMask,
|
dirty: NodeMask,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a, V: FromAnyValue + Send + Sync> NodeMut<'a, V> {
|
||||||
|
pub fn new(id: NodeId, dom: &'a mut RealDom<V>) -> Self {
|
||||||
|
Self {
|
||||||
|
id,
|
||||||
|
dom,
|
||||||
|
dirty: NodeMask::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a, V: FromAnyValue + Send + Sync> NodeImmutable<V> for NodeMut<'a, V> {
|
impl<'a, V: FromAnyValue + Send + Sync> NodeImmutable<V> for NodeMut<'a, V> {
|
||||||
fn real_dom(&self) -> &RealDom<V> {
|
fn real_dom(&self) -> &RealDom<V> {
|
||||||
self.dom
|
self.dom
|
||||||
@@ -658,19 +400,78 @@ impl<'a, V: FromAnyValue + Send + Sync> NodeImmutable<V> for NodeMut<'a, V> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, V: FromAnyValue + Send + Sync> NodeMutable<V> for NodeMut<'a, V> {
|
impl<'a, V: FromAnyValue + Send + Sync> NodeMutable<V> for NodeMut<'a, V> {
|
||||||
fn get_mut<T: Any + Sync + Send>(&mut self) -> Option<&mut T> {
|
fn real_dom_mut(&mut self) -> &mut RealDom<V> {
|
||||||
todo!("get_mut with mark as dirty")
|
self.dom
|
||||||
}
|
}
|
||||||
|
|
||||||
fn insert<T: Any + Sync + Send>(&mut self, _: T) {
|
fn get_mut<T: Any + Sync + Send>(&mut self) -> Option<&mut T> {
|
||||||
todo!("insert with mark as dirty")
|
// mark the node state as dirty
|
||||||
|
self.dom
|
||||||
|
.passes_updated
|
||||||
|
.entry(self.id)
|
||||||
|
.or_default()
|
||||||
|
.insert(TypeId::of::<T>());
|
||||||
|
self.dom.tree.get_mut(self.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn insert<T: Any + Sync + Send>(&mut self, value: T) {
|
||||||
|
// mark the node state as dirty
|
||||||
|
self.dom
|
||||||
|
.passes_updated
|
||||||
|
.entry(self.id)
|
||||||
|
.or_default()
|
||||||
|
.insert(TypeId::of::<T>());
|
||||||
|
self.dom.tree.insert(self.id, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn insert_after(&mut self, old: NodeId) {
|
||||||
|
let id = self.id();
|
||||||
|
if let Some(parent_id) = self.dom.tree.parent_id(old) {
|
||||||
|
self.dom.mark_child_changed(parent_id);
|
||||||
|
self.dom.mark_parent_added_or_removed(id);
|
||||||
|
}
|
||||||
|
self.dom.tree.insert_after(old, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn insert_before(&mut self, old: NodeId) {
|
||||||
|
let id = self.id();
|
||||||
|
if let Some(parent_id) = self.dom.tree.parent_id(old) {
|
||||||
|
self.dom.mark_child_changed(parent_id);
|
||||||
|
self.dom.mark_parent_added_or_removed(id);
|
||||||
|
}
|
||||||
|
self.dom.tree.insert_before(old, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add_event_listener(&mut self, event: &str) {
|
||||||
|
let id = self.id();
|
||||||
|
if let NodeTypeMut::Element(mut element) = self.node_type_mut() {
|
||||||
|
element.listeners_mut().insert(event.to_string());
|
||||||
|
match self.dom.nodes_listening.get_mut(event) {
|
||||||
|
Some(hs) => {
|
||||||
|
hs.insert(id);
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
let mut hs = FxHashSet::default();
|
||||||
|
hs.insert(id);
|
||||||
|
self.dom.nodes_listening.insert(event.to_string(), hs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn remove_event_listener(&mut self, event: &str) {
|
||||||
|
let id = self.id();
|
||||||
|
if let NodeTypeMut::Element(mut element) = self.node_type_mut() {
|
||||||
|
element.listeners_mut().remove(event);
|
||||||
|
}
|
||||||
|
self.dom.nodes_listening.get_mut(event).unwrap().remove(&id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, V: FromAnyValue + Send + Sync> NodeMut<'a, V> {
|
impl<'a, V: FromAnyValue + Send + Sync> NodeMut<'a, V> {
|
||||||
pub fn node_type_mut(&mut self) -> NodeTypeMut<'_, V> {
|
pub fn node_type_mut(&mut self) -> NodeTypeMut<'_, V> {
|
||||||
let Self { id, dom, dirty } = self;
|
let Self { id, dom, dirty } = self;
|
||||||
let node_type = &mut dom.tree.get_mut::<NodeData<V>>(*id).unwrap().node_type;
|
let node_type = dom.tree.get_mut::<NodeType<V>>(*id).unwrap();
|
||||||
match node_type {
|
match node_type {
|
||||||
NodeType::Element(element) => NodeTypeMut::Element(ElementNodeMut { element, dirty }),
|
NodeType::Element(element) => NodeTypeMut::Element(ElementNodeMut { element, dirty }),
|
||||||
NodeType::Text(text) => {
|
NodeType::Text(text) => {
|
||||||
@@ -682,20 +483,15 @@ impl<'a, V: FromAnyValue + Send + Sync> NodeMut<'a, V> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_type(&mut self, new: NodeType<V>) {
|
pub fn set_type(&mut self, new: NodeType<V>) {
|
||||||
self.dom
|
*self.dom.tree.get_mut::<NodeType<V>>(self.id).unwrap() = new;
|
||||||
.tree
|
|
||||||
.get_mut::<NodeData<V>>(self.id)
|
|
||||||
.unwrap()
|
|
||||||
.node_type = new;
|
|
||||||
self.dirty = NodeMaskBuilder::ALL.build();
|
self.dirty = NodeMaskBuilder::ALL.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<V: FromAnyValue + Send + Sync> Drop for NodeMut<'_, V> {
|
impl<V: FromAnyValue + Send + Sync> Drop for NodeMut<'_, V> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
let node_id = self.node_data().node_id;
|
|
||||||
let mask = std::mem::take(&mut self.dirty);
|
let mask = std::mem::take(&mut self.dirty);
|
||||||
self.dom.mark_dirty(node_id, mask);
|
self.dom.mark_dirty(self.id, mask);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -780,6 +576,12 @@ pub struct NodeMutRaw<'a, V: FromAnyValue + Send + Sync = ()> {
|
|||||||
dom: &'a mut RealDom<V>,
|
dom: &'a mut RealDom<V>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a, V: FromAnyValue + Send + Sync> NodeMutRaw<'a, V> {
|
||||||
|
fn node_type_mut(&mut self) -> &mut NodeType<V> {
|
||||||
|
self.dom.tree.get_mut::<NodeType<V>>(self.id).unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a, V: FromAnyValue + Send + Sync> NodeImmutable<V> for NodeMutRaw<'a, V> {
|
impl<'a, V: FromAnyValue + Send + Sync> NodeImmutable<V> for NodeMutRaw<'a, V> {
|
||||||
fn real_dom(&self) -> &RealDom<V> {
|
fn real_dom(&self) -> &RealDom<V> {
|
||||||
self.dom
|
self.dom
|
||||||
@@ -791,11 +593,32 @@ impl<'a, V: FromAnyValue + Send + Sync> NodeImmutable<V> for NodeMutRaw<'a, V> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, V: FromAnyValue + Send + Sync> NodeMutable<V> for NodeMutRaw<'a, V> {
|
impl<'a, V: FromAnyValue + Send + Sync> NodeMutable<V> for NodeMutRaw<'a, V> {
|
||||||
fn get_mut<T: Any + Sync + Send>(&mut self) -> Option<&mut T> {
|
fn real_dom_mut(&mut self) -> &mut RealDom<V> {
|
||||||
self.dom.tree.get_mut::<T>(self.id)
|
self.dom
|
||||||
}
|
}
|
||||||
|
|
||||||
fn insert<T: Any + Sync + Send>(&mut self, value: T) {
|
fn add_event_listener(&mut self, event: &str) {
|
||||||
self.dom.tree.insert(self.id, value);
|
let id = self.id();
|
||||||
|
if let NodeType::Element(element) = self.node_type_mut() {
|
||||||
|
element.listeners.insert(event.to_string());
|
||||||
|
match self.dom.nodes_listening.get_mut(event) {
|
||||||
|
Some(hs) => {
|
||||||
|
hs.insert(id);
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
let mut hs = FxHashSet::default();
|
||||||
|
hs.insert(id);
|
||||||
|
self.dom.nodes_listening.insert(event.to_string(), hs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn remove_event_listener(&mut self, event: &str) {
|
||||||
|
let id = self.id();
|
||||||
|
if let NodeType::Element(element) = self.node_type_mut() {
|
||||||
|
element.listeners.remove(event);
|
||||||
|
}
|
||||||
|
self.dom.nodes_listening.get_mut(event).unwrap().remove(&id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -659,7 +659,7 @@ impl AnySlab {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct EntryBuilder<'a> {
|
pub(crate) struct EntryBuilder<'a> {
|
||||||
id: NodeId,
|
id: NodeId,
|
||||||
inner: &'a mut AnySlab,
|
inner: &'a mut AnySlab,
|
||||||
}
|
}
|
||||||
@@ -671,18 +671,6 @@ impl EntryBuilder<'_> {
|
|||||||
.insert(self.id, value);
|
.insert(self.id, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get<T: Any + Sync + Send>(&self) -> Option<&T> {
|
|
||||||
self.inner.read_slab().get(self.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_mut<T: Any + Sync + Send>(&mut self) -> Option<&mut T> {
|
|
||||||
self.inner.write_slab().get_mut(self.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn remove(self) {
|
|
||||||
self.inner.remove(self.id);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn id(&self) -> NodeId {
|
pub fn id(&self) -> NodeId {
|
||||||
self.id
|
self.id
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use std::{cmp::Ordering, ops::Range};
|
use std::{cmp::Ordering, ops::Range};
|
||||||
|
|
||||||
use dioxus_html::input_data::keyboard_types::{Code, Key, Modifiers};
|
use keyboard_types::{Code, Key, Modifiers};
|
||||||
|
|
||||||
/// This contains the information about the text that is used by the cursor to handle navigation.
|
/// This contains the information about the text that is used by the cursor to handle navigation.
|
||||||
pub trait Text {
|
pub trait Text {
|
||||||
@@ -221,26 +221,28 @@ impl Cursor {
|
|||||||
/// Handle moving the cursor with the given key.
|
/// Handle moving the cursor with the given key.
|
||||||
pub fn handle_input<T: Text + ?Sized>(
|
pub fn handle_input<T: Text + ?Sized>(
|
||||||
&mut self,
|
&mut self,
|
||||||
data: &dioxus_html::KeyboardData,
|
code: &Code,
|
||||||
|
key: &Key,
|
||||||
|
modifiers: &Modifiers,
|
||||||
text: &mut impl TextEditable<T>,
|
text: &mut impl TextEditable<T>,
|
||||||
max_text_length: usize,
|
max_text_length: usize,
|
||||||
) {
|
) {
|
||||||
use Code::*;
|
use Code::*;
|
||||||
match data.code() {
|
match code {
|
||||||
ArrowUp => {
|
ArrowUp => {
|
||||||
self.move_cursor(
|
self.move_cursor(
|
||||||
|c| c.up(text.as_ref()),
|
|c| c.up(text.as_ref()),
|
||||||
data.modifiers().contains(Modifiers::SHIFT),
|
modifiers.contains(Modifiers::SHIFT),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
ArrowDown => {
|
ArrowDown => {
|
||||||
self.move_cursor(
|
self.move_cursor(
|
||||||
|c| c.down(text.as_ref()),
|
|c| c.down(text.as_ref()),
|
||||||
data.modifiers().contains(Modifiers::SHIFT),
|
modifiers.contains(Modifiers::SHIFT),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
ArrowRight => {
|
ArrowRight => {
|
||||||
if data.modifiers().contains(Modifiers::CONTROL) {
|
if modifiers.contains(Modifiers::CONTROL) {
|
||||||
self.move_cursor(
|
self.move_cursor(
|
||||||
|c| {
|
|c| {
|
||||||
let mut change = 1;
|
let mut change = 1;
|
||||||
@@ -255,17 +257,17 @@ impl Cursor {
|
|||||||
}
|
}
|
||||||
c.move_col(change as i32, text.as_ref());
|
c.move_col(change as i32, text.as_ref());
|
||||||
},
|
},
|
||||||
data.modifiers().contains(Modifiers::SHIFT),
|
modifiers.contains(Modifiers::SHIFT),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
self.move_cursor(
|
self.move_cursor(
|
||||||
|c| c.right(text.as_ref()),
|
|c| c.right(text.as_ref()),
|
||||||
data.modifiers().contains(Modifiers::SHIFT),
|
modifiers.contains(Modifiers::SHIFT),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ArrowLeft => {
|
ArrowLeft => {
|
||||||
if data.modifiers().contains(Modifiers::CONTROL) {
|
if modifiers.contains(Modifiers::CONTROL) {
|
||||||
self.move_cursor(
|
self.move_cursor(
|
||||||
|c| {
|
|c| {
|
||||||
let mut change = -1;
|
let mut change = -1;
|
||||||
@@ -279,23 +281,23 @@ impl Cursor {
|
|||||||
}
|
}
|
||||||
c.move_col(change, text.as_ref());
|
c.move_col(change, text.as_ref());
|
||||||
},
|
},
|
||||||
data.modifiers().contains(Modifiers::SHIFT),
|
modifiers.contains(Modifiers::SHIFT),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
self.move_cursor(
|
self.move_cursor(
|
||||||
|c| c.left(text.as_ref()),
|
|c| c.left(text.as_ref()),
|
||||||
data.modifiers().contains(Modifiers::SHIFT),
|
modifiers.contains(Modifiers::SHIFT),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
End => {
|
End => {
|
||||||
self.move_cursor(
|
self.move_cursor(
|
||||||
|c| c.col = c.len_line(text.as_ref()),
|
|c| c.col = c.len_line(text.as_ref()),
|
||||||
data.modifiers().contains(Modifiers::SHIFT),
|
modifiers.contains(Modifiers::SHIFT),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Home => {
|
Home => {
|
||||||
self.move_cursor(|c| c.col = 0, data.modifiers().contains(Modifiers::SHIFT));
|
self.move_cursor(|c| c.col = 0, modifiers.contains(Modifiers::SHIFT));
|
||||||
}
|
}
|
||||||
Backspace => {
|
Backspace => {
|
||||||
self.start.realize_col(text.as_ref());
|
self.start.realize_col(text.as_ref());
|
||||||
@@ -305,7 +307,7 @@ impl Cursor {
|
|||||||
} else if start_idx > 0 {
|
} else if start_idx > 0 {
|
||||||
self.start.left(text.as_ref());
|
self.start.left(text.as_ref());
|
||||||
text.delete_range(start_idx - 1..start_idx);
|
text.delete_range(start_idx - 1..start_idx);
|
||||||
if data.modifiers().contains(Modifiers::CONTROL) {
|
if modifiers.contains(Modifiers::CONTROL) {
|
||||||
start_idx = self.start.idx(text.as_ref());
|
start_idx = self.start.idx(text.as_ref());
|
||||||
while start_idx > 0
|
while start_idx > 0
|
||||||
&& text
|
&& text
|
||||||
@@ -340,7 +342,7 @@ impl Cursor {
|
|||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
self.start.realize_col(text.as_ref());
|
self.start.realize_col(text.as_ref());
|
||||||
if let Key::Character(character) = data.key() {
|
if let Key::Character(character) = key {
|
||||||
if text.as_ref().length() + 1 - self.selection_len(text.as_ref())
|
if text.as_ref().length() + 1 - self.selection_len(text.as_ref())
|
||||||
<= max_text_length
|
<= max_text_length
|
||||||
{
|
{
|
||||||
@@ -460,13 +462,9 @@ fn cursor_input() {
|
|||||||
|
|
||||||
for _ in 0..5 {
|
for _ in 0..5 {
|
||||||
cursor.handle_input(
|
cursor.handle_input(
|
||||||
&dioxus_html::KeyboardData::new(
|
&keyboard_types::Code::ArrowRight,
|
||||||
dioxus_html::input_data::keyboard_types::Key::ArrowRight,
|
&keyboard_types::Key::ArrowRight,
|
||||||
dioxus_html::input_data::keyboard_types::Code::ArrowRight,
|
&Modifiers::empty(),
|
||||||
dioxus_html::input_data::keyboard_types::Location::Standard,
|
|
||||||
false,
|
|
||||||
Modifiers::empty(),
|
|
||||||
),
|
|
||||||
&mut text,
|
&mut text,
|
||||||
10,
|
10,
|
||||||
);
|
);
|
||||||
@@ -474,13 +472,9 @@ fn cursor_input() {
|
|||||||
|
|
||||||
for _ in 0..5 {
|
for _ in 0..5 {
|
||||||
cursor.handle_input(
|
cursor.handle_input(
|
||||||
&dioxus_html::KeyboardData::new(
|
&keyboard_types::Code::Backspace,
|
||||||
dioxus_html::input_data::keyboard_types::Key::Backspace,
|
&keyboard_types::Key::Backspace,
|
||||||
dioxus_html::input_data::keyboard_types::Code::Backspace,
|
&Modifiers::empty(),
|
||||||
dioxus_html::input_data::keyboard_types::Location::Standard,
|
|
||||||
false,
|
|
||||||
Modifiers::empty(),
|
|
||||||
),
|
|
||||||
&mut text,
|
&mut text,
|
||||||
10,
|
10,
|
||||||
);
|
);
|
||||||
@@ -491,61 +485,41 @@ fn cursor_input() {
|
|||||||
let goal_text = "hello world\nhi";
|
let goal_text = "hello world\nhi";
|
||||||
let max_width = goal_text.len();
|
let max_width = goal_text.len();
|
||||||
cursor.handle_input(
|
cursor.handle_input(
|
||||||
&dioxus_html::KeyboardData::new(
|
&keyboard_types::Code::KeyH,
|
||||||
dioxus_html::input_data::keyboard_types::Key::Character("h".to_string()),
|
&keyboard_types::Key::Character("h".to_string()),
|
||||||
dioxus_html::input_data::keyboard_types::Code::KeyH,
|
&Modifiers::empty(),
|
||||||
dioxus_html::input_data::keyboard_types::Location::Standard,
|
|
||||||
false,
|
|
||||||
Modifiers::empty(),
|
|
||||||
),
|
|
||||||
&mut text,
|
&mut text,
|
||||||
max_width,
|
max_width,
|
||||||
);
|
);
|
||||||
|
|
||||||
cursor.handle_input(
|
cursor.handle_input(
|
||||||
&dioxus_html::KeyboardData::new(
|
&keyboard_types::Code::KeyE,
|
||||||
dioxus_html::input_data::keyboard_types::Key::Character("e".to_string()),
|
&keyboard_types::Key::Character("e".to_string()),
|
||||||
dioxus_html::input_data::keyboard_types::Code::KeyE,
|
&Modifiers::empty(),
|
||||||
dioxus_html::input_data::keyboard_types::Location::Standard,
|
|
||||||
false,
|
|
||||||
Modifiers::empty(),
|
|
||||||
),
|
|
||||||
&mut text,
|
&mut text,
|
||||||
max_width,
|
max_width,
|
||||||
);
|
);
|
||||||
|
|
||||||
cursor.handle_input(
|
cursor.handle_input(
|
||||||
&dioxus_html::KeyboardData::new(
|
&keyboard_types::Code::KeyL,
|
||||||
dioxus_html::input_data::keyboard_types::Key::Character("l".to_string()),
|
&keyboard_types::Key::Character("l".to_string()),
|
||||||
dioxus_html::input_data::keyboard_types::Code::KeyL,
|
&Modifiers::empty(),
|
||||||
dioxus_html::input_data::keyboard_types::Location::Standard,
|
|
||||||
false,
|
|
||||||
Modifiers::empty(),
|
|
||||||
),
|
|
||||||
&mut text,
|
&mut text,
|
||||||
max_width,
|
max_width,
|
||||||
);
|
);
|
||||||
|
|
||||||
cursor.handle_input(
|
cursor.handle_input(
|
||||||
&dioxus_html::KeyboardData::new(
|
&keyboard_types::Code::KeyL,
|
||||||
dioxus_html::input_data::keyboard_types::Key::Character("l".to_string()),
|
&keyboard_types::Key::Character("l".to_string()),
|
||||||
dioxus_html::input_data::keyboard_types::Code::KeyL,
|
&Modifiers::empty(),
|
||||||
dioxus_html::input_data::keyboard_types::Location::Standard,
|
|
||||||
false,
|
|
||||||
Modifiers::empty(),
|
|
||||||
),
|
|
||||||
&mut text,
|
&mut text,
|
||||||
max_width,
|
max_width,
|
||||||
);
|
);
|
||||||
|
|
||||||
cursor.handle_input(
|
cursor.handle_input(
|
||||||
&dioxus_html::KeyboardData::new(
|
&keyboard_types::Code::KeyO,
|
||||||
dioxus_html::input_data::keyboard_types::Key::Character("o".to_string()),
|
&keyboard_types::Key::Character("o".to_string()),
|
||||||
dioxus_html::input_data::keyboard_types::Code::KeyO,
|
&Modifiers::empty(),
|
||||||
dioxus_html::input_data::keyboard_types::Location::Standard,
|
|
||||||
false,
|
|
||||||
Modifiers::empty(),
|
|
||||||
),
|
|
||||||
&mut text,
|
&mut text,
|
||||||
max_width,
|
max_width,
|
||||||
);
|
);
|
||||||
@@ -553,13 +527,9 @@ fn cursor_input() {
|
|||||||
// these should be ignored
|
// these should be ignored
|
||||||
for _ in 0..10 {
|
for _ in 0..10 {
|
||||||
cursor.handle_input(
|
cursor.handle_input(
|
||||||
&dioxus_html::KeyboardData::new(
|
&keyboard_types::Code::KeyO,
|
||||||
dioxus_html::input_data::keyboard_types::Key::Character("o".to_string()),
|
&keyboard_types::Key::Character("o".to_string()),
|
||||||
dioxus_html::input_data::keyboard_types::Code::KeyO,
|
&Modifiers::empty(),
|
||||||
dioxus_html::input_data::keyboard_types::Location::Standard,
|
|
||||||
false,
|
|
||||||
Modifiers::empty(),
|
|
||||||
),
|
|
||||||
&mut text,
|
&mut text,
|
||||||
max_width,
|
max_width,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
mod persistant_iterator;
|
// mod persistant_iterator;
|
||||||
pub use persistant_iterator::*;
|
// pub use persistant_iterator::*;
|
||||||
pub mod cursor;
|
pub mod cursor;
|
||||||
@@ -13,6 +13,7 @@ pub enum ElementProduced {
|
|||||||
/// The iterator reached the end of the tree and looped back to the root
|
/// The iterator reached the end of the tree and looped back to the root
|
||||||
Looped(NodeId),
|
Looped(NodeId),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ElementProduced {
|
impl ElementProduced {
|
||||||
pub fn id(&self) -> NodeId {
|
pub fn id(&self) -> NodeId {
|
||||||
match self {
|
match self {
|
||||||
@@ -141,7 +142,7 @@ impl PersistantElementIter {
|
|||||||
} else {
|
} else {
|
||||||
let (last, old_child_idx) = self.stack.last_mut().unwrap();
|
let (last, old_child_idx) = self.stack.last_mut().unwrap();
|
||||||
let node = rdom.get(*last).unwrap();
|
let node = rdom.get(*last).unwrap();
|
||||||
match &node.node_data().node_type {
|
match node.node_type() {
|
||||||
NodeType::Element(ElementNode { .. }) => {
|
NodeType::Element(ElementNode { .. }) => {
|
||||||
let children = node.child_ids().unwrap();
|
let children = node.child_ids().unwrap();
|
||||||
*old_child_idx = old_child_idx.map(|i| i + 1);
|
*old_child_idx = old_child_idx.map(|i| i + 1);
|
||||||
@@ -153,7 +154,7 @@ impl PersistantElementIter {
|
|||||||
} else {
|
} else {
|
||||||
let id = children[child_idx];
|
let id = children[child_idx];
|
||||||
if let NodeType::Element(ElementNode { .. }) =
|
if let NodeType::Element(ElementNode { .. }) =
|
||||||
rdom.get(id).unwrap().node_data().node_type
|
rdom.get(id).unwrap().node_type()
|
||||||
{
|
{
|
||||||
self.stack.push((id, NodePosition::AtNode));
|
self.stack.push((id, NodePosition::AtNode));
|
||||||
}
|
}
|
||||||
@@ -178,7 +179,7 @@ impl PersistantElementIter {
|
|||||||
rdom: &RealDom<V>,
|
rdom: &RealDom<V>,
|
||||||
) -> NodeId {
|
) -> NodeId {
|
||||||
let node = rdom.get(new_node).unwrap();
|
let node = rdom.get(new_node).unwrap();
|
||||||
match &node.node_data().node_type {
|
match node.node_type() {
|
||||||
NodeType::Element(ElementNode { .. }) => {
|
NodeType::Element(ElementNode { .. }) => {
|
||||||
let children = node.child_ids().unwrap();
|
let children = node.child_ids().unwrap();
|
||||||
if children.is_empty() {
|
if children.is_empty() {
|
||||||
@@ -197,7 +198,7 @@ impl PersistantElementIter {
|
|||||||
} else {
|
} else {
|
||||||
let (last, old_child_idx) = self.stack.last_mut().unwrap();
|
let (last, old_child_idx) = self.stack.last_mut().unwrap();
|
||||||
let node = rdom.get(*last).unwrap();
|
let node = rdom.get(*last).unwrap();
|
||||||
match &node.node_data().node_type {
|
match node.node_type() {
|
||||||
NodeType::Element(ElementNode { .. }) => {
|
NodeType::Element(ElementNode { .. }) => {
|
||||||
let children = node.child_ids().unwrap();
|
let children = node.child_ids().unwrap();
|
||||||
// if we have children, go to the next child
|
// if we have children, go to the next child
|
||||||
|
|||||||
@@ -0,0 +1,620 @@
|
|||||||
|
use dioxus::prelude::*;
|
||||||
|
use dioxus_native_core::node::NodeType;
|
||||||
|
use dioxus_native_core::prelude::*;
|
||||||
|
use std::any::TypeId;
|
||||||
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
|
fn create_blank_element() -> NodeType {
|
||||||
|
NodeType::Element(ElementNode {
|
||||||
|
tag: "div".to_owned(),
|
||||||
|
namespace: None,
|
||||||
|
attributes: HashMap::new(),
|
||||||
|
listeners: HashMap::new(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn node_pass() {
|
||||||
|
#[derive(Debug, Default, Clone, PartialEq)]
|
||||||
|
struct Number(i32);
|
||||||
|
|
||||||
|
impl Pass for Number {
|
||||||
|
type ChildDependencies = ();
|
||||||
|
type NodeDependencies = ();
|
||||||
|
type ParentDependencies = ();
|
||||||
|
const NODE_MASK: NodeMaskBuilder = NodeMaskBuilder::new();
|
||||||
|
|
||||||
|
fn pass<'a>(
|
||||||
|
&mut self,
|
||||||
|
node_view: NodeView,
|
||||||
|
node: <Self::NodeDependencies as Dependancy>::ElementBorrowed<'a>,
|
||||||
|
parent: Option<<Self::ParentDependencies as Dependancy>::ElementBorrowed<'a>>,
|
||||||
|
children: Option<Vec<<Self::ChildDependencies as Dependancy>::ElementBorrowed<'a>>>,
|
||||||
|
context: &SendAnyMap,
|
||||||
|
) -> bool {
|
||||||
|
self.0 += 1;
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create<'a>(
|
||||||
|
node_view: NodeView<()>,
|
||||||
|
node: <Self::NodeDependencies as Dependancy>::ElementBorrowed<'a>,
|
||||||
|
parent: Option<<Self::ParentDependencies as Dependancy>::ElementBorrowed<'a>>,
|
||||||
|
children: Option<Vec<<Self::ChildDependencies as Dependancy>::ElementBorrowed<'a>>>,
|
||||||
|
context: &SendAnyMap,
|
||||||
|
) -> Self {
|
||||||
|
let mut myself = Self::default();
|
||||||
|
myself.pass(node_view, node, parent, children, context);
|
||||||
|
myself
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut tree: RealDom = RealDom::new(Box::new([Number::to_type_erased()]));
|
||||||
|
tree.update_state(SendAnyMap::new(), false);
|
||||||
|
|
||||||
|
assert_eq!(tree.get(tree.root_id()).unwrap().get(), Some(&Number(1)));
|
||||||
|
|
||||||
|
// mark the node as dirty
|
||||||
|
tree.get_mut(tree.root_id()).unwrap().get_mut::<Number>();
|
||||||
|
|
||||||
|
tree.update_state(SendAnyMap::new(), false);
|
||||||
|
assert_eq!(tree.get(tree.root_id()).unwrap().get(), Some(&Number(2)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn dependant_node_pass() {
|
||||||
|
#[derive(Debug, Default, Clone, PartialEq)]
|
||||||
|
struct AddNumber(i32);
|
||||||
|
|
||||||
|
impl Pass for AddNumber {
|
||||||
|
type ChildDependencies = ();
|
||||||
|
type NodeDependencies = (SubtractNumber,);
|
||||||
|
type ParentDependencies = ();
|
||||||
|
const NODE_MASK: NodeMaskBuilder = NodeMaskBuilder::new();
|
||||||
|
|
||||||
|
fn pass<'a>(
|
||||||
|
&mut self,
|
||||||
|
node_view: NodeView,
|
||||||
|
node: <Self::NodeDependencies as Dependancy>::ElementBorrowed<'a>,
|
||||||
|
parent: Option<<Self::ParentDependencies as Dependancy>::ElementBorrowed<'a>>,
|
||||||
|
children: Option<Vec<<Self::ChildDependencies as Dependancy>::ElementBorrowed<'a>>>,
|
||||||
|
context: &SendAnyMap,
|
||||||
|
) -> bool {
|
||||||
|
self.0 += 1;
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create<'a>(
|
||||||
|
node_view: NodeView<()>,
|
||||||
|
node: <Self::NodeDependencies as Dependancy>::ElementBorrowed<'a>,
|
||||||
|
parent: Option<<Self::ParentDependencies as Dependancy>::ElementBorrowed<'a>>,
|
||||||
|
children: Option<Vec<<Self::ChildDependencies as Dependancy>::ElementBorrowed<'a>>>,
|
||||||
|
context: &SendAnyMap,
|
||||||
|
) -> Self {
|
||||||
|
let mut myself = Self::default();
|
||||||
|
myself.pass(node_view, node, parent, children, context);
|
||||||
|
myself
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default, Clone, PartialEq)]
|
||||||
|
struct SubtractNumber(i32);
|
||||||
|
|
||||||
|
impl Pass for SubtractNumber {
|
||||||
|
type ChildDependencies = ();
|
||||||
|
type NodeDependencies = ();
|
||||||
|
type ParentDependencies = ();
|
||||||
|
const NODE_MASK: NodeMaskBuilder = NodeMaskBuilder::new();
|
||||||
|
|
||||||
|
fn pass<'a>(
|
||||||
|
&mut self,
|
||||||
|
node_view: NodeView,
|
||||||
|
node: <Self::NodeDependencies as Dependancy>::ElementBorrowed<'a>,
|
||||||
|
parent: Option<<Self::ParentDependencies as Dependancy>::ElementBorrowed<'a>>,
|
||||||
|
children: Option<Vec<<Self::ChildDependencies as Dependancy>::ElementBorrowed<'a>>>,
|
||||||
|
context: &SendAnyMap,
|
||||||
|
) -> bool {
|
||||||
|
self.0 -= 1;
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create<'a>(
|
||||||
|
node_view: NodeView<()>,
|
||||||
|
node: <Self::NodeDependencies as Dependancy>::ElementBorrowed<'a>,
|
||||||
|
parent: Option<<Self::ParentDependencies as Dependancy>::ElementBorrowed<'a>>,
|
||||||
|
children: Option<Vec<<Self::ChildDependencies as Dependancy>::ElementBorrowed<'a>>>,
|
||||||
|
context: &SendAnyMap,
|
||||||
|
) -> Self {
|
||||||
|
let mut myself = Self::default();
|
||||||
|
myself.pass(node_view, node, parent, children, context);
|
||||||
|
myself
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut tree: RealDom = RealDom::new(Box::new([
|
||||||
|
AddNumber::to_type_erased(),
|
||||||
|
SubtractNumber::to_type_erased(),
|
||||||
|
]));
|
||||||
|
tree.update_state(SendAnyMap::new(), false);
|
||||||
|
|
||||||
|
let root = tree.get(tree.root_id()).unwrap();
|
||||||
|
assert_eq!(root.get(), Some(&AddNumber(1)));
|
||||||
|
assert_eq!(root.get(), Some(&SubtractNumber(-1)));
|
||||||
|
|
||||||
|
// mark the subtract state as dirty, it should update the add state
|
||||||
|
tree.get_mut(tree.root_id())
|
||||||
|
.unwrap()
|
||||||
|
.get_mut::<SubtractNumber>();
|
||||||
|
|
||||||
|
tree.update_state(SendAnyMap::new(), false);
|
||||||
|
let root = tree.get(tree.root_id()).unwrap();
|
||||||
|
assert_eq!(root.get(), Some(&AddNumber(2)));
|
||||||
|
assert_eq!(root.get(), Some(&SubtractNumber(-2)));
|
||||||
|
|
||||||
|
// mark the add state as dirty, it should ~not~ update the subtract state
|
||||||
|
tree.get_mut(tree.root_id()).unwrap().get_mut::<AddNumber>();
|
||||||
|
|
||||||
|
tree.update_state(SendAnyMap::new(), false);
|
||||||
|
let root = tree.get(tree.root_id()).unwrap();
|
||||||
|
assert_eq!(root.get(), Some(&AddNumber(3)));
|
||||||
|
assert_eq!(root.get(), Some(&SubtractNumber(-2)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn independant_node_pass() {
|
||||||
|
#[derive(Debug, Default, Clone, PartialEq)]
|
||||||
|
struct AddNumber(i32);
|
||||||
|
|
||||||
|
impl Pass for AddNumber {
|
||||||
|
type ChildDependencies = ();
|
||||||
|
type NodeDependencies = ();
|
||||||
|
type ParentDependencies = ();
|
||||||
|
|
||||||
|
const NODE_MASK: NodeMaskBuilder = NodeMaskBuilder::new();
|
||||||
|
|
||||||
|
fn pass<'a>(
|
||||||
|
&mut self,
|
||||||
|
node_view: NodeView,
|
||||||
|
node: <Self::NodeDependencies as Dependancy>::ElementBorrowed<'a>,
|
||||||
|
parent: Option<<Self::ParentDependencies as Dependancy>::ElementBorrowed<'a>>,
|
||||||
|
children: Option<Vec<<Self::ChildDependencies as Dependancy>::ElementBorrowed<'a>>>,
|
||||||
|
context: &SendAnyMap,
|
||||||
|
) -> bool {
|
||||||
|
self.0 += 1;
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create<'a>(
|
||||||
|
node_view: NodeView<()>,
|
||||||
|
node: <Self::NodeDependencies as Dependancy>::ElementBorrowed<'a>,
|
||||||
|
parent: Option<<Self::ParentDependencies as Dependancy>::ElementBorrowed<'a>>,
|
||||||
|
children: Option<Vec<<Self::ChildDependencies as Dependancy>::ElementBorrowed<'a>>>,
|
||||||
|
context: &SendAnyMap,
|
||||||
|
) -> Self {
|
||||||
|
let mut myself = Self::default();
|
||||||
|
myself.pass(node_view, node, parent, children, context);
|
||||||
|
myself
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default, Clone, PartialEq)]
|
||||||
|
struct SubtractNumber(i32);
|
||||||
|
|
||||||
|
impl Pass for SubtractNumber {
|
||||||
|
type ChildDependencies = ();
|
||||||
|
type NodeDependencies = ();
|
||||||
|
type ParentDependencies = ();
|
||||||
|
|
||||||
|
const NODE_MASK: NodeMaskBuilder = NodeMaskBuilder::new();
|
||||||
|
|
||||||
|
fn pass<'a>(
|
||||||
|
&mut self,
|
||||||
|
node_view: NodeView,
|
||||||
|
node: <Self::NodeDependencies as Dependancy>::ElementBorrowed<'a>,
|
||||||
|
parent: Option<<Self::ParentDependencies as Dependancy>::ElementBorrowed<'a>>,
|
||||||
|
children: Option<Vec<<Self::ChildDependencies as Dependancy>::ElementBorrowed<'a>>>,
|
||||||
|
context: &SendAnyMap,
|
||||||
|
) -> bool {
|
||||||
|
self.0 -= 1;
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create<'a>(
|
||||||
|
node_view: NodeView<()>,
|
||||||
|
node: <Self::NodeDependencies as Dependancy>::ElementBorrowed<'a>,
|
||||||
|
parent: Option<<Self::ParentDependencies as Dependancy>::ElementBorrowed<'a>>,
|
||||||
|
children: Option<Vec<<Self::ChildDependencies as Dependancy>::ElementBorrowed<'a>>>,
|
||||||
|
context: &SendAnyMap,
|
||||||
|
) -> Self {
|
||||||
|
let mut myself = Self::default();
|
||||||
|
myself.pass(node_view, node, parent, children, context);
|
||||||
|
myself
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut tree: RealDom = RealDom::new(Box::new([
|
||||||
|
AddNumber::to_type_erased(),
|
||||||
|
SubtractNumber::to_type_erased(),
|
||||||
|
]));
|
||||||
|
tree.update_state(SendAnyMap::new(), false);
|
||||||
|
|
||||||
|
let root = tree.get(tree.root_id()).unwrap();
|
||||||
|
assert_eq!(root.get(), Some(&AddNumber(1)));
|
||||||
|
assert_eq!(root.get(), Some(&SubtractNumber(-1)));
|
||||||
|
|
||||||
|
// mark the subtract state as dirty, it should ~not~ update the add state
|
||||||
|
tree.get_mut(tree.root_id())
|
||||||
|
.unwrap()
|
||||||
|
.get_mut::<SubtractNumber>();
|
||||||
|
|
||||||
|
tree.update_state(SendAnyMap::new(), false);
|
||||||
|
|
||||||
|
let root = tree.get(tree.root_id()).unwrap();
|
||||||
|
assert_eq!(root.get(), Some(&AddNumber(1)));
|
||||||
|
assert_eq!(root.get(), Some(&SubtractNumber(-2)));
|
||||||
|
|
||||||
|
// mark the add state as dirty, it should ~not~ update the subtract state
|
||||||
|
tree.get_mut(tree.root_id()).unwrap().get_mut::<AddNumber>();
|
||||||
|
|
||||||
|
tree.update_state(SendAnyMap::new(), false);
|
||||||
|
|
||||||
|
let root = tree.get(tree.root_id()).unwrap();
|
||||||
|
assert_eq!(root.get(), Some(&AddNumber(2)));
|
||||||
|
assert_eq!(root.get(), Some(&SubtractNumber(-2)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn down_pass() {
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
struct AddNumber(i32);
|
||||||
|
|
||||||
|
impl Default for AddNumber {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Pass for AddNumber {
|
||||||
|
type ChildDependencies = ();
|
||||||
|
type NodeDependencies = ();
|
||||||
|
type ParentDependencies = (AddNumber,);
|
||||||
|
|
||||||
|
const NODE_MASK: NodeMaskBuilder = NodeMaskBuilder::new();
|
||||||
|
|
||||||
|
fn pass<'a>(
|
||||||
|
&mut self,
|
||||||
|
node_view: NodeView,
|
||||||
|
node: <Self::NodeDependencies as Dependancy>::ElementBorrowed<'a>,
|
||||||
|
parent: Option<<Self::ParentDependencies as Dependancy>::ElementBorrowed<'a>>,
|
||||||
|
children: Option<Vec<<Self::ChildDependencies as Dependancy>::ElementBorrowed<'a>>>,
|
||||||
|
context: &SendAnyMap,
|
||||||
|
) -> bool {
|
||||||
|
if let Some((parent,)) = parent {
|
||||||
|
*self.0 += *parent.0;
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut tree: RealDom = RealDom::new(Box::new([AddNumber::to_type_erased()]));
|
||||||
|
let parent = tree.root_id();
|
||||||
|
let child1 = tree.create_node(create_blank_element(), true);
|
||||||
|
tree.add_child(parent, child1);
|
||||||
|
let grandchild1 = tree.create_node(create_blank_element(), true);
|
||||||
|
tree.add_child(child1, grandchild1);
|
||||||
|
let child2 = tree.create_node(create_blank_element(), true);
|
||||||
|
tree.add_child(parent, child2);
|
||||||
|
let grandchild2 = tree.create_node(create_blank_element(), true);
|
||||||
|
tree.add_child(child2, grandchild2);
|
||||||
|
|
||||||
|
tree.dirty_nodes
|
||||||
|
.insert(TypeId::of::<AddNumber>(), NodeId(0));
|
||||||
|
tree.update_state(SendAnyMap::new(), false);
|
||||||
|
|
||||||
|
assert_eq!(tree.get(tree.root_id()).unwrap().state.add_number.0, 1);
|
||||||
|
assert_eq!(tree.get(child1).unwrap().state.add_number.0, 2);
|
||||||
|
assert_eq!(tree.get(grandchild1).unwrap().state.add_number.0, 3);
|
||||||
|
assert_eq!(tree.get(child2).unwrap().state.add_number.0, 2);
|
||||||
|
assert_eq!(tree.get(grandchild2).unwrap().state.add_number.0, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
// #[test]
|
||||||
|
// fn dependant_down_pass() {
|
||||||
|
// // 0
|
||||||
|
// let mut tree = Tree::new(1);
|
||||||
|
// let parent = tree.root_id();
|
||||||
|
// // 1
|
||||||
|
// let child1 = tree.create_node(1);
|
||||||
|
// tree.add_child(parent, child1);
|
||||||
|
// // 2
|
||||||
|
// let grandchild1 = tree.create_node(1);
|
||||||
|
// tree.add_child(child1, grandchild1);
|
||||||
|
// // 3
|
||||||
|
// let child2 = tree.create_node(1);
|
||||||
|
// tree.add_child(parent, child2);
|
||||||
|
// // 4
|
||||||
|
// let grandchild2 = tree.create_node(1);
|
||||||
|
// tree.add_child(child2, grandchild2);
|
||||||
|
|
||||||
|
// struct AddPass;
|
||||||
|
// impl Pass for AddPass {
|
||||||
|
// fn pass_id(&self) -> PassId {
|
||||||
|
// PassId(0)
|
||||||
|
// }
|
||||||
|
|
||||||
|
// fn dependancies(&self) -> &'static [PassId] {
|
||||||
|
// &[PassId(1)]
|
||||||
|
// }
|
||||||
|
|
||||||
|
// fn dependants(&self) -> &'static [PassId] {
|
||||||
|
// &[]
|
||||||
|
// }
|
||||||
|
|
||||||
|
// fn mask(&self) -> MemberMask {
|
||||||
|
// MemberMask(0)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// impl DownwardPass<i32> for AddPass {
|
||||||
|
// fn pass(&self, node: &mut i32, parent: Option<&mut i32>, _: &SendAnyMap) -> PassReturn {
|
||||||
|
// if let Some(parent) = parent {
|
||||||
|
// *node += *parent;
|
||||||
|
// } else {
|
||||||
|
// }
|
||||||
|
// PassReturn {
|
||||||
|
// progress: true,
|
||||||
|
// mark_dirty: true,
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// struct SubtractPass;
|
||||||
|
// impl Pass for SubtractPass {
|
||||||
|
// fn pass_id(&self) -> PassId {
|
||||||
|
// PassId(1)
|
||||||
|
// }
|
||||||
|
|
||||||
|
// fn dependancies(&self) -> &'static [PassId] {
|
||||||
|
// &[]
|
||||||
|
// }
|
||||||
|
|
||||||
|
// fn dependants(&self) -> &'static [PassId] {
|
||||||
|
// &[PassId(0)]
|
||||||
|
// }
|
||||||
|
|
||||||
|
// fn mask(&self) -> MemberMask {
|
||||||
|
// MemberMask(0)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// impl DownwardPass<i32> for SubtractPass {
|
||||||
|
// fn pass(&self, node: &mut i32, parent: Option<&mut i32>, _: &SendAnyMap) -> PassReturn {
|
||||||
|
// if let Some(parent) = parent {
|
||||||
|
// *node -= *parent;
|
||||||
|
// } else {
|
||||||
|
// }
|
||||||
|
// PassReturn {
|
||||||
|
// progress: true,
|
||||||
|
// mark_dirty: true,
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// let add_pass = AnyPass::Downward(&AddPass);
|
||||||
|
// let subtract_pass = AnyPass::Downward(&SubtractPass);
|
||||||
|
// let passes = vec![&add_pass, &subtract_pass];
|
||||||
|
// let dirty_nodes: DirtyNodeStates = DirtyNodeStates::default();
|
||||||
|
// dirty_nodes.insert(PassId(1), tree.root_id());
|
||||||
|
// resolve_passes(&mut tree, dirty_nodes, passes, SendAnyMap::new());
|
||||||
|
|
||||||
|
// // Tree before:
|
||||||
|
// // 1=\
|
||||||
|
// // 1=\
|
||||||
|
// // 1
|
||||||
|
// // 1=\
|
||||||
|
// // 1
|
||||||
|
// // Tree after subtract:
|
||||||
|
// // 1=\
|
||||||
|
// // 0=\
|
||||||
|
// // 1
|
||||||
|
// // 0=\
|
||||||
|
// // 1
|
||||||
|
// // Tree after add:
|
||||||
|
// // 1=\
|
||||||
|
// // 1=\
|
||||||
|
// // 2
|
||||||
|
// // 1=\
|
||||||
|
// // 2
|
||||||
|
// assert_eq!(tree.get(tree.root_id()).unwrap(), &1);
|
||||||
|
// assert_eq!(tree.get(child1).unwrap(), &1);
|
||||||
|
// assert_eq!(tree.get(grandchild1).unwrap(), &2);
|
||||||
|
// assert_eq!(tree.get(child2).unwrap(), &1);
|
||||||
|
// assert_eq!(tree.get(grandchild2).unwrap(), &2);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// #[test]
|
||||||
|
// fn up_pass() {
|
||||||
|
// // Tree before:
|
||||||
|
// // 0=\
|
||||||
|
// // 0=\
|
||||||
|
// // 1
|
||||||
|
// // 0=\
|
||||||
|
// // 1
|
||||||
|
// // Tree after:
|
||||||
|
// // 2=\
|
||||||
|
// // 1=\
|
||||||
|
// // 1
|
||||||
|
// // 1=\
|
||||||
|
// // 1
|
||||||
|
// let mut tree = Tree::new(0);
|
||||||
|
// let parent = tree.root_id();
|
||||||
|
// let child1 = tree.create_node(0);
|
||||||
|
// tree.add_child(parent, child1);
|
||||||
|
// let grandchild1 = tree.create_node(1);
|
||||||
|
// tree.add_child(child1, grandchild1);
|
||||||
|
// let child2 = tree.create_node(0);
|
||||||
|
// tree.add_child(parent, child2);
|
||||||
|
// let grandchild2 = tree.create_node(1);
|
||||||
|
// tree.add_child(child2, grandchild2);
|
||||||
|
|
||||||
|
// struct AddPass;
|
||||||
|
// impl Pass for AddPass {
|
||||||
|
// fn pass_id(&self) -> PassId {
|
||||||
|
// PassId(0)
|
||||||
|
// }
|
||||||
|
|
||||||
|
// fn dependancies(&self) -> &'static [PassId] {
|
||||||
|
// &[]
|
||||||
|
// }
|
||||||
|
|
||||||
|
// fn dependants(&self) -> &'static [PassId] {
|
||||||
|
// &[]
|
||||||
|
// }
|
||||||
|
|
||||||
|
// fn mask(&self) -> MemberMask {
|
||||||
|
// MemberMask(0)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// impl UpwardPass<i32> for AddPass {
|
||||||
|
// fn pass<'a>(
|
||||||
|
// &self,
|
||||||
|
// node: &mut i32,
|
||||||
|
// children: &mut dyn Iterator<Item = &'a mut i32>,
|
||||||
|
// _: &SendAnyMap,
|
||||||
|
// ) -> PassReturn {
|
||||||
|
// *node += children.map(|i| *i).sum::<i32>();
|
||||||
|
// PassReturn {
|
||||||
|
// progress: true,
|
||||||
|
// mark_dirty: true,
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// let add_pass = AnyPass::Upward(&AddPass);
|
||||||
|
// let passes = vec![&add_pass];
|
||||||
|
// let dirty_nodes: DirtyNodeStates = DirtyNodeStates::default();
|
||||||
|
// dirty_nodes.insert(PassId(0), grandchild1);
|
||||||
|
// dirty_nodes.insert(PassId(0), grandchild2);
|
||||||
|
// resolve_passes(&mut tree, dirty_nodes, passes, SendAnyMap::new());
|
||||||
|
|
||||||
|
// assert_eq!(tree.get(tree.root_id()).unwrap(), &2);
|
||||||
|
// assert_eq!(tree.get(child1).unwrap(), &1);
|
||||||
|
// assert_eq!(tree.get(grandchild1).unwrap(), &1);
|
||||||
|
// assert_eq!(tree.get(child2).unwrap(), &1);
|
||||||
|
// assert_eq!(tree.get(grandchild2).unwrap(), &1);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// #[test]
|
||||||
|
// fn dependant_up_pass() {
|
||||||
|
// // 0
|
||||||
|
// let mut tree = Tree::new(0);
|
||||||
|
// let parent = tree.root_id();
|
||||||
|
// // 1
|
||||||
|
// let child1 = tree.create_node(0);
|
||||||
|
// tree.add_child(parent, child1);
|
||||||
|
// // 2
|
||||||
|
// let grandchild1 = tree.create_node(1);
|
||||||
|
// tree.add_child(child1, grandchild1);
|
||||||
|
// // 3
|
||||||
|
// let child2 = tree.create_node(0);
|
||||||
|
// tree.add_child(parent, child2);
|
||||||
|
// // 4
|
||||||
|
// let grandchild2 = tree.create_node(1);
|
||||||
|
// tree.add_child(child2, grandchild2);
|
||||||
|
|
||||||
|
// struct AddPass;
|
||||||
|
// impl Pass for AddPass {
|
||||||
|
// fn pass_id(&self) -> PassId {
|
||||||
|
// PassId(0)
|
||||||
|
// }
|
||||||
|
|
||||||
|
// fn dependancies(&self) -> &'static [PassId] {
|
||||||
|
// &[PassId(1)]
|
||||||
|
// }
|
||||||
|
|
||||||
|
// fn dependants(&self) -> &'static [PassId] {
|
||||||
|
// &[]
|
||||||
|
// }
|
||||||
|
|
||||||
|
// fn mask(&self) -> MemberMask {
|
||||||
|
// MemberMask(0)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// impl UpwardPass<i32> for AddPass {
|
||||||
|
// fn pass<'a>(
|
||||||
|
// &self,
|
||||||
|
// node: &mut i32,
|
||||||
|
// children: &mut dyn Iterator<Item = &'a mut i32>,
|
||||||
|
// _: &SendAnyMap,
|
||||||
|
// ) -> PassReturn {
|
||||||
|
// *node += children.map(|i| *i).sum::<i32>();
|
||||||
|
// PassReturn {
|
||||||
|
// progress: true,
|
||||||
|
// mark_dirty: true,
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// struct SubtractPass;
|
||||||
|
// impl Pass for SubtractPass {
|
||||||
|
// fn pass_id(&self) -> PassId {
|
||||||
|
// PassId(1)
|
||||||
|
// }
|
||||||
|
|
||||||
|
// fn dependancies(&self) -> &'static [PassId] {
|
||||||
|
// &[]
|
||||||
|
// }
|
||||||
|
|
||||||
|
// fn dependants(&self) -> &'static [PassId] {
|
||||||
|
// &[PassId(0)]
|
||||||
|
// }
|
||||||
|
|
||||||
|
// fn mask(&self) -> MemberMask {
|
||||||
|
// MemberMask(0)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// impl UpwardPass<i32> for SubtractPass {
|
||||||
|
// fn pass<'a>(
|
||||||
|
// &self,
|
||||||
|
// node: &mut i32,
|
||||||
|
// children: &mut dyn Iterator<Item = &'a mut i32>,
|
||||||
|
// _: &SendAnyMap,
|
||||||
|
// ) -> PassReturn {
|
||||||
|
// *node -= children.map(|i| *i).sum::<i32>();
|
||||||
|
// PassReturn {
|
||||||
|
// progress: true,
|
||||||
|
// mark_dirty: true,
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// let add_pass = AnyPass::Upward(&AddPass);
|
||||||
|
// let subtract_pass = AnyPass::Upward(&SubtractPass);
|
||||||
|
// let passes = vec![&add_pass, &subtract_pass];
|
||||||
|
// let dirty_nodes: DirtyNodeStates = DirtyNodeStates::default();
|
||||||
|
// dirty_nodes.insert(PassId(1), grandchild1);
|
||||||
|
// dirty_nodes.insert(PassId(1), grandchild2);
|
||||||
|
// resolve_passes(&mut tree, dirty_nodes, passes, SendAnyMap::new());
|
||||||
|
|
||||||
|
// // Tree before:
|
||||||
|
// // 0=\
|
||||||
|
// // 0=\
|
||||||
|
// // 1
|
||||||
|
// // 0=\
|
||||||
|
// // 1
|
||||||
|
// // Tree after subtract:
|
||||||
|
// // 2=\
|
||||||
|
// // -1=\
|
||||||
|
// // 1
|
||||||
|
// // -1=\
|
||||||
|
// // 1
|
||||||
|
// // Tree after add:
|
||||||
|
// // 2=\
|
||||||
|
// // 0=\
|
||||||
|
// // 1
|
||||||
|
// // 0=\
|
||||||
|
// // 1
|
||||||
|
// assert_eq!(tree.get(tree.root_id()).unwrap(), &2);
|
||||||
|
// assert_eq!(tree.get(child1).unwrap(), &0);
|
||||||
|
// assert_eq!(tree.get(grandchild1).unwrap(), &1);
|
||||||
|
// assert_eq!(tree.get(child2).unwrap(), &0);
|
||||||
|
// assert_eq!(tree.get(grandchild2).unwrap(), &1);
|
||||||
|
// }
|
||||||
Reference in new issue
Block a user