elvis_shared/tree/
node.rs

1use std::cell::RefCell;
2use std::rc::{Rc, Weak};
3use std::{
4    collections::{hash_map::DefaultHasher, HashMap},
5    hash::Hasher,
6};
7
8fn hash(tag: &str, s: &[u8]) -> String {
9    let mut hasher = DefaultHasher::new();
10    hasher.write(s);
11
12    let res = format!("{:x}", hasher.finish());
13    format!("{}-{}", &tag, &res[(res.len() - 6)..])
14}
15
16/// Virtual UI Node
17#[derive(Clone, Debug, Default)]
18pub struct Node {
19    /// Node attributes
20    pub attrs: HashMap<String, String>,
21    /// Node children
22    pub children: Vec<Rc<RefCell<Node>>>,
23    /// Node tag
24    pub tag: String,
25    /// Node parent
26    pub pre: Option<Weak<RefCell<Node>>>,
27}
28
29impl Node {
30    /// Drain tree if not the root
31    pub fn drain(t: Rc<RefCell<Node>>) {
32        if let Some(pre) = &t.borrow().pre {
33            let u = pre.upgrade().expect("drain child failed");
34            u.borrow_mut().remove(t.clone());
35            u.borrow_mut().update();
36        }
37    }
38
39    /// The path of current node
40    pub fn idx(&mut self, path: &mut Vec<u8>) {
41        let h = hash(&self.tag, &path);
42        self.attrs.entry("id".into()).or_insert(h);
43
44        path.push(0);
45        for t in self.children.iter() {
46            t.borrow_mut().idx(path);
47            if let Some(last) = path.last_mut() {
48                *last += 1;
49            }
50        }
51    }
52
53    /// Locate tree
54    pub fn locate(&self, mut path: Vec<usize>) -> Vec<usize> {
55        if let Some(pre) = &self.pre {
56            let u = pre.upgrade().expect("locate widget failed");
57            for (i, t) in u.borrow().children.iter().enumerate() {
58                if t.borrow().eq(self) {
59                    path.push(i);
60                    return u.borrow().locate(path);
61                }
62            }
63        }
64
65        path
66    }
67
68    /// Generate a `Rc<RefCell<Node>>`
69    pub fn new(
70        attrs: HashMap<String, String>,
71        children: Vec<Rc<RefCell<Node>>>,
72        pre: Option<Weak<RefCell<Node>>>,
73        tag: String,
74    ) -> Rc<RefCell<Node>> {
75        let t = Node {
76            attrs,
77            children,
78            pre,
79            tag,
80        };
81
82        Rc::new(RefCell::new(t))
83    }
84
85    /// Add second tree to the first one.
86    pub fn push(r: Rc<RefCell<Node>>, c: Rc<RefCell<Node>>) {
87        let pre = Rc::downgrade(&r);
88        c.borrow_mut().pre = Some(pre.clone());
89
90        pre.upgrade()
91            .expect("push child to tree failed")
92            .borrow_mut()
93            .children
94            .push(c);
95
96        r.borrow_mut().update();
97    }
98
99    /// Delete spefic child using rc
100    pub fn remove(&mut self, c: Rc<RefCell<Node>>) {
101        self.children.retain(|x| x != &c);
102        self.update();
103    }
104
105    /// Replace current tree
106    pub fn replace(&mut self, mut t: Node) {
107        t.pre = self.pre.clone();
108        std::mem::swap(self, &mut t);
109
110        t.update();
111    }
112
113    /// Update tree
114    pub fn update(&mut self) {}
115}
116
117impl PartialEq for Node {
118    fn eq(&self, other: &Self) -> bool {
119        let res = self.attrs.eq(&other.attrs) && self.tag.eq(&other.tag);
120
121        for (p, q) in self.children.iter().enumerate() {
122            if !q.eq(&other.children[p]) {
123                return false;
124            }
125        }
126
127        res
128    }
129}