utils.rs 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. use crate::{
  2. real_dom::{NodeType, RealDom},
  3. state::State,
  4. };
  5. use dioxus_core::{DomEdit, ElementId, Mutations};
  6. pub enum ElementProduced {
  7. Progressed(ElementId),
  8. Looped(ElementId),
  9. }
  10. impl ElementProduced {
  11. pub fn id(&self) -> ElementId {
  12. match self {
  13. ElementProduced::Progressed(id) => *id,
  14. ElementProduced::Looped(id) => *id,
  15. }
  16. }
  17. }
  18. #[derive(Debug)]
  19. enum NodePosition {
  20. AtNode,
  21. InChild(usize),
  22. }
  23. impl NodePosition {
  24. fn map(&self, mut f: impl FnMut(usize) -> usize) -> Self {
  25. match self {
  26. Self::AtNode => Self::AtNode,
  27. Self::InChild(i) => Self::InChild(f(*i)),
  28. }
  29. }
  30. fn get_or_insert(&mut self, child_idx: usize) -> usize {
  31. match self {
  32. Self::AtNode => {
  33. *self = Self::InChild(child_idx);
  34. child_idx
  35. }
  36. Self::InChild(i) => *i,
  37. }
  38. }
  39. }
  40. /// The focus system needs a iterator that can persist through changes in the [VirtualDom].
  41. /// Iterate through it with [ElementIter::next] [ElementIter::prev], and update it with [ElementIter::update] (with data from [`VirtualDom::work_with_deadline`]).
  42. /// The iterator loops around when it reaches the end or the beginning.
  43. pub struct PersistantElementIter {
  44. // stack of elements and fragments
  45. stack: smallvec::SmallVec<[(ElementId, NodePosition); 5]>,
  46. }
  47. impl Default for PersistantElementIter {
  48. fn default() -> Self {
  49. PersistantElementIter {
  50. stack: smallvec::smallvec![(ElementId(0), NodePosition::AtNode)],
  51. }
  52. }
  53. }
  54. impl PersistantElementIter {
  55. pub fn new() -> Self {
  56. Self::default()
  57. }
  58. /// remove stale element refreneces
  59. /// returns true if the focused element is removed
  60. pub fn prune<S: State>(&mut self, mutations: &Mutations, rdom: &RealDom<S>) -> bool {
  61. let mut changed = false;
  62. let ids_removed: Vec<_> = mutations
  63. .edits
  64. .iter()
  65. .filter_map(|e| {
  66. if let DomEdit::Remove { root } = e {
  67. Some(*root)
  68. } else {
  69. None
  70. }
  71. })
  72. .collect();
  73. // if any element is removed in the chain, remove it and its children from the stack
  74. if let Some(r) = self
  75. .stack
  76. .iter()
  77. .position(|(el_id, _)| ids_removed.iter().any(|id| el_id.as_u64() == *id))
  78. {
  79. self.stack.truncate(r);
  80. changed = true;
  81. }
  82. // if a child is removed or inserted before or at the current element, update the child index
  83. for (el_id, child_idx) in self.stack.iter_mut() {
  84. if let NodePosition::InChild(child_idx) = child_idx {
  85. if let NodeType::Element { children, .. } = &rdom[*el_id].node_type {
  86. for m in &mutations.edits {
  87. match m {
  88. DomEdit::Remove { root } => {
  89. if children
  90. .iter()
  91. .take(*child_idx + 1)
  92. .any(|c| c.as_u64() == *root)
  93. {
  94. *child_idx -= 1;
  95. }
  96. }
  97. DomEdit::InsertBefore { root, n } => {
  98. if children
  99. .iter()
  100. .take(*child_idx + 1)
  101. .any(|c| c.as_u64() == *root)
  102. {
  103. *child_idx += *n as usize;
  104. }
  105. }
  106. DomEdit::InsertAfter { root, n } => {
  107. if children
  108. .iter()
  109. .take(*child_idx)
  110. .any(|c| c.as_u64() == *root)
  111. {
  112. *child_idx += *n as usize;
  113. }
  114. }
  115. _ => (),
  116. }
  117. }
  118. }
  119. }
  120. }
  121. changed
  122. }
  123. /// get the next element
  124. pub fn next<S: State>(&mut self, rdom: &RealDom<S>) -> ElementProduced {
  125. if self.stack.is_empty() {
  126. let id = ElementId(0);
  127. let new = (id, NodePosition::AtNode);
  128. self.stack.push(new);
  129. ElementProduced::Looped(id)
  130. } else {
  131. let (last, o_child_idx) = self.stack.last_mut().unwrap();
  132. let node = &rdom[*last];
  133. match &node.node_type {
  134. NodeType::Element { children, .. } => {
  135. *o_child_idx = o_child_idx.map(|i| i + 1);
  136. // if we have children, go to the next child
  137. let child_idx = o_child_idx.get_or_insert(0);
  138. if child_idx >= children.len() {
  139. self.pop();
  140. self.next(rdom)
  141. } else {
  142. let id = children[child_idx];
  143. if let NodeType::Element { .. } = &rdom[id].node_type {
  144. self.stack.push((id, NodePosition::AtNode));
  145. }
  146. ElementProduced::Progressed(id)
  147. }
  148. }
  149. NodeType::Text { .. } | NodeType::Placeholder { .. } => {
  150. // we are at a leaf, so we are done
  151. ElementProduced::Progressed(self.pop())
  152. }
  153. }
  154. }
  155. }
  156. /// get the previous element
  157. pub fn prev<S: State>(&mut self, rdom: &RealDom<S>) -> ElementProduced {
  158. // recursively add the last child element to the stack
  159. fn push_back<S: State>(
  160. stack: &mut smallvec::SmallVec<[(ElementId, NodePosition); 5]>,
  161. new_node: ElementId,
  162. rdom: &RealDom<S>,
  163. ) -> ElementId {
  164. match &rdom[new_node].node_type {
  165. NodeType::Element { children, .. } => {
  166. if children.is_empty() {
  167. new_node
  168. } else {
  169. stack.push((new_node, NodePosition::InChild(children.len() - 1)));
  170. push_back(stack, *children.last().unwrap(), rdom)
  171. }
  172. }
  173. _ => new_node,
  174. }
  175. }
  176. if self.stack.is_empty() {
  177. let new_node = ElementId(0);
  178. ElementProduced::Looped(push_back(&mut self.stack, new_node, rdom))
  179. } else {
  180. let (last, o_child_idx) = self.stack.last_mut().unwrap();
  181. let node = &rdom[*last];
  182. match &node.node_type {
  183. NodeType::Element { children, .. } => {
  184. // if we have children, go to the next child
  185. if let NodePosition::InChild(0) = o_child_idx {
  186. ElementProduced::Progressed(self.pop())
  187. } else {
  188. *o_child_idx = o_child_idx.map(|i| i - 1);
  189. if let NodePosition::InChild(child_idx) = o_child_idx {
  190. if *child_idx >= children.len() || children.len() == 0 {
  191. self.pop();
  192. self.prev(rdom)
  193. } else {
  194. let new_node = children[*child_idx];
  195. ElementProduced::Progressed(push_back(
  196. &mut self.stack,
  197. new_node,
  198. rdom,
  199. ))
  200. }
  201. } else {
  202. self.pop();
  203. self.prev(rdom)
  204. }
  205. }
  206. }
  207. NodeType::Text { .. } | NodeType::Placeholder { .. } => {
  208. // we are at a leaf, so we are done
  209. ElementProduced::Progressed(self.pop())
  210. }
  211. }
  212. }
  213. }
  214. fn pop(&mut self) -> ElementId {
  215. self.stack.pop().unwrap().0
  216. }
  217. }