makepad_widgets/
data_binding.rs1use crate::{
2 makepad_platform::*,
3 widget::*,
4};
5
6pub struct DataBindingStore {
7 pub nodes: Vec<LiveNode>,
8 mutated_by: Vec<WidgetUid>,
9}
10
11impl DataBindingStore {
12 pub fn new() -> Self {
13 let mut nodes = Vec::new();
14 nodes.open_object(LiveId(0));
15 nodes.close();
16 Self {
17 nodes,
18 mutated_by: Vec::new(),
19 }
20 }
21
22 pub fn set_mutated_by(&mut self, uid: WidgetUid) {
23 if !self.mutated_by.contains(&uid) {
24 self.mutated_by.push(uid);
25 }
26 }
27}
28
29enum Direction {
30 DataToWidgets,
31 WidgetsToData
32}
33
34pub struct DataBindingMap<'a> {
35 pub store: &'a mut DataBindingStore,
36 pub debug_missing: bool,
37 pub cx: &'a mut Cx,
38 direction: Direction,
39 pub actions: &'a WidgetActions,
40 pub ui: &'a WidgetRef,
41}
42
43impl DataBindingStore {
44 pub fn data_to_widgets<'a>(&'a mut self, cx: &'a mut Cx, actions: &'a WidgetActions, ui: &'a WidgetRef) -> DataBindingMap {
45 DataBindingMap {
46 debug_missing: false,
47 direction: Direction::DataToWidgets,
48 store: self,
49 cx,
50 ui,
51 actions
52 }
53 }
54
55 pub fn widgets_to_data<'a>(&'a mut self, cx: &'a mut Cx, actions: &'a WidgetActions, ui: &'a WidgetRef) -> DataBindingMap {
56 DataBindingMap {
57 debug_missing: false,
58 direction: Direction::WidgetsToData,
59 store: self,
60 cx,
61 ui,
62 actions
63 }
64 }
65}
66
67impl<'a> DataBindingMap<'a> {
68 pub fn with_debug_missing(mut self) -> Self {
69 self.debug_missing = true;
70 self
71 }
72
73 pub fn is_data_to_widgets(&self) -> bool {
74 if let Direction::DataToWidgets = self.direction {true}else {false}
75 }
76
77 pub fn is_widgets_to_data(&self) -> bool {
78 if let Direction::WidgetsToData = self.direction {true}else {false}
79 }
80
81 pub fn bind(&mut self, data_id: &[LiveId], widgets: &[&[LiveId]]) {
82 if self.is_data_to_widgets() {
84 let mut any_found = false;
85 for widget in self.ui.widgets(widgets).iter() {
86 any_found = true;
87 let uid = widget.widget_uid();
88 if !self.store.mutated_by.contains(&uid) {
89 widget.data_to_widget(self.cx, &self.store.nodes, data_id);
90 }
91 }
92 if !any_found && self.debug_missing {
93 log!("No widgets found for databinding {:?}", widgets);
94 }
95 }
96 else {
97 if self.actions.len() == 0 {
98 return
99 }
100 for widget in self.ui.widgets(widgets).iter() {
101 if widget.widget_to_data(self.cx, self.actions, &mut self.store.nodes, data_id) {
102 self.store.set_mutated_by(widget.widget_uid());
103 }
104 }
105 }
106 }
107
108 pub fn apply<F>(&mut self, data: &[LiveId], widget_val: &[&[LiveId]; 2], map: F)
109 where F: FnOnce(LiveValue) -> LiveValue {
110 if self.is_data_to_widgets() {
111 if let Some(v) = self.store.nodes.read_field_value(data) {
112 let mut ui_nodes = LiveNodeVec::new();
113 ui_nodes.write_field_value(widget_val[1], map(v.clone()));
114 let widgets = self.ui.widgets(&[widget_val[0]]);
115 for widget in widgets.iter(){
116 widget.apply_over(self.cx, &ui_nodes)
117 }
118 }
122 }
123 }
124}
125