1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
use std::collections::{HashSet, HashMap};
use crate::components::{Popover, Popup};

#[derive(Debug, Clone)]
pub enum NodeType {
    Normal(String),
    SelfClosing(String),
    Comment(String)
}

#[derive(Debug, Clone)]
pub struct Node {
    pub node_type: NodeType,
    pub text: Option<String>,
    pub children: Vec<Node>,
    pub class_list: HashSet<String>,
    pub node_style: Vec<(String, String)>,
    pub attributes: HashMap<String, String>,
    pub popover: Box<Option<Popover>>,
    pub popup: Box<Option<Popup>>,
}

impl Default for Node {
    fn default() -> Self {
        let mut class_list = HashSet::new();
        class_list.insert("view".to_string());
        Node {
            node_type: NodeType::Normal("div".to_string()),
            text: None,
            children: vec![],
            class_list,
            node_style: vec![],
            attributes: HashMap::new(),
            popover: Box::new(None),
            popup: Box::new(None),
        }
    }
}

impl Node {
    pub fn get_popovers(&self) -> Vec<Popover> {
        let mut popovers: Vec<Popover> = vec![];

        if let Some(popover) = self.popover.clone().take() {
            popovers.push(popover)
        }
        self.children.iter()
            .for_each(|child| {
                child.get_popovers().iter()
                    .for_each(|popover| popovers.push(popover.clone()))
            });
        popovers
    }

    pub fn get_popups(&self) -> Vec<Popup> {
        let mut popups: Vec<Popup> = vec![];

        if let Some(popup) = self.popup.clone().take() {
            popups.push(popup)
        }
        self.children.iter()
            .for_each(|child| {
                child.get_popups().iter()
                    .for_each(|popup| popups.push(popup.clone()))
            });
        popups
    }

    pub fn get_html(&self) -> String {
        let classes: Vec<String> = self.class_list.iter()
            .map(|class_name| format!("{}", class_name))
            .collect();
        let attributes: Vec<String> = self.attributes.iter()
            .map(|(name, value)| format!("{}=\"{}\"", name, value))
            .collect();
        let style: Vec<String> = self.node_style.iter()
            .map(|(name, value)| format!("{}: {};", name, value))
            .collect();
        let content: Vec<String> = self.children.iter()
            .map(|child| child.get_html())
            .collect();
        match self.node_type.clone() {
            NodeType::Normal(tag_name) => format!(
                "<{tag} class=\"{class_list}\" {attributes} style=\"{view_style}\">{children}</{tag}>",
                tag = tag_name,
                class_list = classes.join(" "),
                attributes = attributes.join(" "),
                view_style = style.join(""),
                children = match self.text.clone() {
                    None => content.join(""),
                    Some(text) => text
                }
            ),
            NodeType::SelfClosing(tag_name) => format!(
                "<{tag} class=\"{class_list}\" {attributes} style=\"{view_style}\" />",
                tag = tag_name,
                class_list = classes.join(" "),
                attributes = attributes.join(" "),
                view_style = style.join("")
            ),
            NodeType::Comment(comment) => format!(
                "<!--{comment}-->",
                comment = comment
            )
        }
    }
}

pub trait NodeContainer {
    fn get_node(&mut self) -> &mut Node;
}