make the real dom generic over custom types
This commit is contained in:
1 parent
dde4fb31b2
commit
bf20b66b38
5 files changed
+99
-44
No files matched your search
@@ -5,7 +5,7 @@ use std::fmt::Debug;
|
||||
|
||||
/// The node is stored client side and stores only basic data about the node.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Node<S: State, V: FromAnyValue = ()> {
|
||||
pub struct Node<S: State<V>, V: FromAnyValue + 'static = ()> {
|
||||
/// The transformed state of the node.
|
||||
pub state: S,
|
||||
/// The raw data for the node
|
||||
@@ -37,7 +37,7 @@ pub enum NodeType<V: FromAnyValue = ()> {
|
||||
Placeholder,
|
||||
}
|
||||
|
||||
impl<S: State, V: FromAnyValue> Node<S, V> {
|
||||
impl<S: State<V>, V: FromAnyValue> Node<S, V> {
|
||||
pub(crate) fn new(node_type: NodeType<V>) -> Self {
|
||||
Node {
|
||||
state: S::default(),
|
||||
@@ -83,7 +83,7 @@ pub enum OwnedAttributeValue<V: FromAnyValue = ()> {
|
||||
None,
|
||||
}
|
||||
|
||||
pub trait FromAnyValue {
|
||||
pub trait FromAnyValue: Clone {
|
||||
fn from_any_value(value: &dyn AnyValue) -> Self;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ use rustc_hash::{FxHashMap, FxHashSet};
|
||||
use std::fmt::Debug;
|
||||
use std::ops::{Deref, DerefMut, Index, IndexMut};
|
||||
|
||||
use crate::node::{Node, NodeType, OwnedAttributeDiscription, OwnedAttributeValue};
|
||||
use crate::node::{FromAnyValue, Node, NodeType, OwnedAttributeDiscription, OwnedAttributeValue};
|
||||
use crate::node_ref::{AttributeMask, NodeMask};
|
||||
use crate::passes::DirtyNodeStates;
|
||||
use crate::state::State;
|
||||
@@ -25,9 +25,12 @@ fn mark_dirty(
|
||||
/// A Dom that can sync with the VirtualDom mutations intended for use in lazy renderers.
|
||||
/// The render state passes from parent to children and or accumulates state from children to parents.
|
||||
/// To get started implement [crate::state::ParentDepState], [crate::state::NodeDepState], or [crate::state::ChildDepState] and call [RealDom::apply_mutations] to update the dom and [RealDom::update_state] to update the state of the nodes.
|
||||
///
|
||||
/// # Custom values
|
||||
/// To allow custom values to be passed into attributes implement FromAnyValue on a type that can represent your custom value and specify the V generic to be that type. If you have many different custom values, it can be useful to use a enum type to represent the varients.
|
||||
#[derive(Debug)]
|
||||
pub struct RealDom<S: State> {
|
||||
pub tree: Tree<Node<S>>,
|
||||
pub struct RealDom<S: State<V>, V: FromAnyValue + 'static = ()> {
|
||||
pub tree: Tree<Node<S, V>>,
|
||||
/// a map from element id to real node id
|
||||
node_id_mapping: Vec<Option<RealNodeId>>,
|
||||
nodes_listening: FxHashMap<String, FxHashSet<RealNodeId>>,
|
||||
@@ -36,14 +39,14 @@ pub struct RealDom<S: State> {
|
||||
root_initialized: bool,
|
||||
}
|
||||
|
||||
impl<S: State> Default for RealDom<S> {
|
||||
impl<S: State<V>, V: FromAnyValue> Default for RealDom<S, V> {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: State> RealDom<S> {
|
||||
pub fn new() -> RealDom<S> {
|
||||
impl<S: State<V>, V: FromAnyValue> RealDom<S, V> {
|
||||
pub fn new() -> RealDom<S, V> {
|
||||
let mut root = Node::new(NodeType::Element {
|
||||
tag: "Root".to_string(),
|
||||
namespace: Some("Root".to_string()),
|
||||
@@ -91,7 +94,7 @@ impl<S: State> RealDom<S> {
|
||||
current
|
||||
}
|
||||
|
||||
fn create_node(&mut self, node: Node<S>) -> RealNodeId {
|
||||
fn create_node(&mut self, node: Node<S, V>) -> RealNodeId {
|
||||
let node_id = self.tree.create_node(node);
|
||||
let node = self.tree.get_mut(node_id).unwrap();
|
||||
node.node_data.node_id = node_id;
|
||||
@@ -349,7 +352,7 @@ impl<S: State> RealDom<S> {
|
||||
|
||||
/// Find all nodes that are listening for an event, sorted by there height in the dom progressing starting at the bottom and progressing up.
|
||||
/// This can be useful to avoid creating duplicate events.
|
||||
pub fn get_listening_sorted(&self, event: &'static str) -> Vec<&Node<S>> {
|
||||
pub fn get_listening_sorted(&self, event: &'static str) -> Vec<&Node<S, V>> {
|
||||
if let Some(nodes) = self.nodes_listening.get(event) {
|
||||
let mut listening: Vec<_> = nodes.iter().map(|id| &self[*id]).collect();
|
||||
listening.sort_by(|n1, n2| {
|
||||
@@ -396,9 +399,9 @@ impl<S: State> RealDom<S> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: State + Sync> RealDom<S>
|
||||
impl<S: State<V> + Sync, V: FromAnyValue> RealDom<S, V>
|
||||
where
|
||||
Tree<Node<S>>: Sync + Send,
|
||||
Tree<Node<S, V>>: Sync + Send,
|
||||
{
|
||||
/// Update the state of the dom, after appling some mutations. This will keep the nodes in the dom up to date with their VNode counterparts.
|
||||
/// This will resolve the state in parallel
|
||||
@@ -411,43 +414,43 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: State> Deref for RealDom<S> {
|
||||
type Target = Tree<Node<S>>;
|
||||
impl<S: State<V>, V: FromAnyValue> Deref for RealDom<S, V> {
|
||||
type Target = Tree<Node<S, V>>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.tree
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: State> DerefMut for RealDom<S> {
|
||||
impl<S: State<V>, V: FromAnyValue> DerefMut for RealDom<S, V> {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.tree
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: State> Index<ElementId> for RealDom<S> {
|
||||
type Output = Node<S>;
|
||||
impl<S: State<V>, V: FromAnyValue> Index<ElementId> for RealDom<S, V> {
|
||||
type Output = Node<S, V>;
|
||||
|
||||
fn index(&self, id: ElementId) -> &Self::Output {
|
||||
self.tree.get(self.element_to_node_id(id)).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: State> Index<RealNodeId> for RealDom<S> {
|
||||
type Output = Node<S>;
|
||||
impl<S: State<V>, V: FromAnyValue> Index<RealNodeId> for RealDom<S, V> {
|
||||
type Output = Node<S, V>;
|
||||
|
||||
fn index(&self, idx: RealNodeId) -> &Self::Output {
|
||||
self.tree.get(idx).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: State> IndexMut<ElementId> for RealDom<S> {
|
||||
impl<S: State<V>, V: FromAnyValue> IndexMut<ElementId> for RealDom<S, V> {
|
||||
fn index_mut(&mut self, id: ElementId) -> &mut Self::Output {
|
||||
self.tree.get_mut(self.element_to_node_id(id)).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: State> IndexMut<RealNodeId> for RealDom<S> {
|
||||
impl<S: State<V>, V: FromAnyValue> IndexMut<RealNodeId> for RealDom<S, V> {
|
||||
fn index_mut(&mut self, idx: RealNodeId) -> &mut Self::Output {
|
||||
self.tree.get_mut(idx).unwrap()
|
||||
}
|
||||
|
||||
@@ -210,14 +210,14 @@ pub trait NodeDepState<V: FromAnyValue = ()> {
|
||||
}
|
||||
|
||||
/// Do not implement this trait. It is only meant to be derived and used through [crate::real_dom::RealDom].
|
||||
pub trait State: Default + Clone + 'static {
|
||||
pub trait State<V: FromAnyValue + 'static>: Default + Clone + 'static {
|
||||
#[doc(hidden)]
|
||||
const PASSES: &'static [AnyPass<Node<Self>>];
|
||||
const PASSES: &'static [AnyPass<Node<Self, V>>];
|
||||
#[doc(hidden)]
|
||||
const MASKS: &'static [NodeMask];
|
||||
|
||||
#[doc(hidden)]
|
||||
fn update<T: TreeView<Node<Self>> + Sync + Send>(
|
||||
fn update<T: TreeView<Node<Self, V>> + Sync + Send>(
|
||||
dirty: DirtyNodeStates,
|
||||
tree: &mut T,
|
||||
ctx: SendAnyMap,
|
||||
@@ -227,7 +227,7 @@ pub trait State: Default + Clone + 'static {
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
fn update_single_threaded<T: TreeView<Node<Self>>>(
|
||||
fn update_single_threaded<T: TreeView<Node<Self, V>>>(
|
||||
dirty: DirtyNodeStates,
|
||||
tree: &mut T,
|
||||
ctx: SendAnyMap,
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
use crate::{node::NodeType, real_dom::RealDom, state::State, tree::TreeView, NodeId, RealNodeId};
|
||||
use crate::{
|
||||
node::{FromAnyValue, NodeType},
|
||||
real_dom::RealDom,
|
||||
state::State,
|
||||
tree::TreeView,
|
||||
NodeId, RealNodeId,
|
||||
};
|
||||
use dioxus_core::{Mutation, Mutations};
|
||||
use std::fmt::Debug;
|
||||
|
||||
@@ -67,7 +73,11 @@ impl PersistantElementIter {
|
||||
|
||||
/// remove stale element refreneces
|
||||
/// returns true if the focused element is removed
|
||||
pub fn prune<S: State>(&mut self, mutations: &Mutations, rdom: &RealDom<S>) -> bool {
|
||||
pub fn prune<S: State<V>, V: FromAnyValue>(
|
||||
&mut self,
|
||||
mutations: &Mutations,
|
||||
rdom: &RealDom<S, V>,
|
||||
) -> bool {
|
||||
let mut changed = false;
|
||||
let ids_removed: Vec<_> = mutations
|
||||
.edits
|
||||
@@ -124,7 +134,7 @@ impl PersistantElementIter {
|
||||
}
|
||||
|
||||
/// get the next element
|
||||
pub fn next<S: State>(&mut self, rdom: &RealDom<S>) -> ElementProduced {
|
||||
pub fn next<S: State<V>, V: FromAnyValue>(&mut self, rdom: &RealDom<S, V>) -> ElementProduced {
|
||||
if self.stack.is_empty() {
|
||||
let id = NodeId(0);
|
||||
let new = (id, NodePosition::AtNode);
|
||||
@@ -160,12 +170,12 @@ impl PersistantElementIter {
|
||||
}
|
||||
|
||||
/// get the previous element
|
||||
pub fn prev<S: State>(&mut self, rdom: &RealDom<S>) -> ElementProduced {
|
||||
pub fn prev<S: State<V>, V: FromAnyValue>(&mut self, rdom: &RealDom<S, V>) -> ElementProduced {
|
||||
// recursively add the last child element to the stack
|
||||
fn push_back<S: State>(
|
||||
fn push_back<S: State<V>, V: FromAnyValue>(
|
||||
stack: &mut smallvec::SmallVec<[(RealNodeId, NodePosition); 5]>,
|
||||
new_node: RealNodeId,
|
||||
rdom: &RealDom<S>,
|
||||
rdom: &RealDom<S, V>,
|
||||
) -> RealNodeId {
|
||||
match &rdom[new_node].node_data.node_type {
|
||||
NodeType::Element { .. } => {
|
||||
@@ -228,7 +238,7 @@ impl PersistantElementIter {
|
||||
|
||||
#[derive(Default, Clone, Debug)]
|
||||
struct Empty {}
|
||||
impl State for Empty {
|
||||
impl State<()> for Empty {
|
||||
const PASSES: &'static [crate::AnyPass<crate::node::Node<Self, ()>>] = &[];
|
||||
|
||||
const MASKS: &'static [crate::NodeMask] = &[];
|
||||
|
||||
Reference in new issue
Block a user