kano_tui/
node.rs

1use std::{
2    cell::RefCell,
3    fmt::Debug,
4    rc::{Rc, Weak},
5};
6
7use ratatui::{widgets::Paragraph, Frame};
8
9use crate::component::ComponentData;
10
11thread_local! {
12    pub(crate) static NEXT_NODE_ID: RefCell<u64> = RefCell::new(0);
13}
14
15pub(crate) fn new_node_id() -> u64 {
16    NEXT_NODE_ID.with_borrow_mut(|next| {
17        let id = *next;
18        *next += 1;
19        id
20    })
21}
22
23#[derive(Debug)]
24pub struct Node {
25    pub id: u64,
26    pub kind: NodeKind,
27    pub parent: Option<Weak<RefCell<Node>>>,
28    pub first_child: Option<NodeRef>,
29    pub next_sibling: Option<NodeRef>,
30}
31
32#[derive(Debug, Clone)]
33pub enum NodeKind {
34    Empty,
35    Text(String),
36    Component(Rc<ComponentData>),
37}
38
39#[derive(Clone, Debug)]
40pub struct NodeRef(pub Rc<RefCell<Node>>);
41
42impl NodeRef {
43    pub fn render(self, frame: &mut Frame, area: ratatui::prelude::Rect) {
44        let node = self.0.borrow();
45        match &node.kind {
46            NodeKind::Empty => {}
47            NodeKind::Text(text) => frame.render_widget(Paragraph::new(text.as_str()), area),
48            NodeKind::Component(data) => {
49                data.render(self.clone(), frame, area);
50            }
51        }
52    }
53
54    pub fn id(&self) -> u64 {
55        self.0.borrow().id
56    }
57
58    pub fn parent(&self) -> Option<NodeRef> {
59        let parent = self.0.borrow().parent.clone();
60        parent
61            .map(|parent| parent.upgrade().expect("Parent garbage collected"))
62            .map(|rc| Self(rc))
63    }
64
65    pub fn first_child(&self) -> Option<NodeRef> {
66        self.0.borrow().first_child.clone()
67    }
68
69    pub fn next_sibling(&self) -> Option<NodeRef> {
70        self.0.borrow().next_sibling.clone()
71    }
72
73    pub fn append_sibling(&self, kind: NodeKind) {
74        let mut self_borrow = self.0.borrow_mut();
75
76        let new_node = Rc::new(RefCell::new(Node {
77            id: new_node_id(),
78            kind,
79            parent: self_borrow.parent.clone(),
80            first_child: None,
81            next_sibling: self_borrow.next_sibling.clone(),
82        }));
83
84        self_borrow.next_sibling = Some(NodeRef(new_node));
85    }
86}