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
114
115
116
117
118
119
120
121
122
123
124
125
use crate::{
    makepad_platform::*,
    widget::*,
};

pub struct DataBindingStore {
    pub nodes: Vec<LiveNode>,
    mutated_by: Vec<WidgetUid>,
}

impl DataBindingStore {
    pub fn new() -> Self {
        let mut nodes = Vec::new();
        nodes.open_object(LiveId(0));
        nodes.close();
        Self {
            nodes,
            mutated_by: Vec::new(),
        }
    }
    
    pub fn set_mutated_by(&mut self, uid: WidgetUid) {
        if !self.mutated_by.contains(&uid) {
            self.mutated_by.push(uid);
        }
    }
}

enum Direction {
    DataToWidgets,
    WidgetsToData
}

pub struct DataBindingMap<'a> {
    pub store: &'a mut DataBindingStore,
    pub debug_missing: bool,
    pub cx: &'a mut Cx,
    direction: Direction,
    pub actions: &'a WidgetActions,
    pub ui: &'a WidgetRef,
}

impl DataBindingStore {
    pub fn data_to_widgets<'a>(&'a mut self, cx: &'a mut Cx, actions: &'a WidgetActions, ui: &'a WidgetRef) -> DataBindingMap {
        DataBindingMap {
            debug_missing: false,
            direction: Direction::DataToWidgets,
            store: self,
            cx,
            ui,
            actions
        }
    }
    
    pub fn widgets_to_data<'a>(&'a mut self, cx: &'a mut Cx, actions: &'a WidgetActions, ui: &'a WidgetRef) -> DataBindingMap {
        DataBindingMap {
            debug_missing: false,
            direction: Direction::WidgetsToData,
            store: self,
            cx,
            ui,
            actions
        }
    }
}

impl<'a> DataBindingMap<'a> {
    pub fn with_debug_missing(mut self) -> Self {
        self.debug_missing = true;
        self
    }
    
    pub fn is_data_to_widgets(&self) -> bool {
        if let Direction::DataToWidgets = self.direction {true}else {false}
    }
    
    pub fn is_widgets_to_data(&self) -> bool {
        if let Direction::WidgetsToData = self.direction {true}else {false}
    }
    
    pub fn bind(&mut self, data_id: &[LiveId], widgets: &[&[LiveId]]) {
        // alright so. we have a direction.
        if self.is_data_to_widgets() {
            let mut any_found = false;
            for widget in self.ui.widgets(widgets).iter() {
                any_found = true;
                let uid = widget.widget_uid();
                if !self.store.mutated_by.contains(&uid) {
                    widget.data_to_widget(self.cx, &self.store.nodes, data_id);
                }
            }
            if !any_found && self.debug_missing {
                log!("No widgets found for databinding {:?}", widgets);
            }
        }
        else {
            if self.actions.len() == 0 {
                return
            }
            for widget in self.ui.widgets(widgets).iter() {
                if widget.widget_to_data(self.cx, self.actions, &mut self.store.nodes, data_id) {
                    self.store.set_mutated_by(widget.widget_uid());
                }
            }
        }
    }
    
    pub fn apply<F>(&mut self, data: &[LiveId], widget_val: &[&[LiveId]; 2], map: F)
    where F: FnOnce(LiveValue) -> LiveValue {
        if self.is_data_to_widgets() {
            if let Some(v) = self.store.nodes.read_field_value(data) {
                let mut ui_nodes = LiveNodeVec::new();
                ui_nodes.write_field_value(widget_val[1], map(v.clone()));
                let widgets = self.ui.widgets(&[widget_val[0]]);
                for widget in widgets.iter(){
                    widget.apply_over(self.cx, &ui_nodes)
                }
                /*else if self.debug_missing {
                    log!("Databinding apply cannot find widget {:?}", widget_val[0]);
                }*/
            }
        }
    }
}