1use super::traits::*;
2use super::releasable::*;
3use super::binding_context::*;
4
5use std::sync::*;
6
7struct BoundValue<Value> {
11 value: Value,
13
14 when_changed: Vec<ReleasableNotifiable>
16}
17
18impl<Value: Clone+PartialEq> BoundValue<Value> {
19 pub fn new(val: Value) -> BoundValue<Value> {
23 BoundValue {
24 value: val,
25 when_changed: vec![]
26 }
27 }
28
29 pub fn set_without_notifying(&mut self, new_value: Value) -> bool {
33 let changed = self.value != new_value;
34
35 self.value = new_value;
36
37 changed
38 }
39
40 pub fn get_notifiable_items(&self) -> Vec<ReleasableNotifiable> {
44 self.when_changed
45 .iter()
46 .map(|item| item.clone_for_inspection())
47 .collect()
48 }
49
50 pub fn filter_unused_notifications(&mut self) {
54 self.when_changed.retain(|releasable| releasable.is_in_use());
55 }
56
57 fn get(&self) -> Value {
61 self.value.clone()
62 }
63
64 fn get_mut(&mut self) -> &mut Value {
68 &mut self.value
69 }
70
71 fn when_changed(&mut self, what: Arc<dyn Notifiable>) -> Box<dyn Releasable> {
75 let releasable = ReleasableNotifiable::new(what);
76 self.when_changed.push(releasable.clone_as_owned());
77
78 self.filter_unused_notifications();
79
80 Box::new(releasable)
81 }
82}
83
84impl<Value: Default + Clone + PartialEq> Default for BoundValue<Value> {
85 fn default() -> Self {
86 BoundValue::new(Value::default())
87 }
88}
89
90impl<Value: std::fmt::Debug> std::fmt::Debug for BoundValue<Value> {
91 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
92 self.value.fmt(f)
93 }
94}
95
96impl<Value: PartialEq> PartialEq for BoundValue<Value> {
97 fn eq(&self, other: &Self) -> bool {
98 self.value.eq(&other.value)
99 }
100}
101#[derive(Clone)]
105pub struct Binding<Value> {
106 value: Arc<Mutex<BoundValue<Value>>>
108}
109
110impl<Value: Default + Clone + PartialEq> Default for Binding<Value> {
111 fn default() -> Self {
112 Binding::new(Value::default())
113 }
114}
115
116impl<Value: std::fmt::Debug> std::fmt::Debug for Binding<Value> {
117 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
118 self.value.fmt(f)
119 }
120}
121
122impl<Value: PartialEq> PartialEq for Binding<Value> {
123 fn eq(&self, other: &Self) -> bool {
124 self.value.lock().unwrap().eq(&other.value.lock().unwrap())
125 }
126}
127
128impl<Value: Clone+PartialEq> Binding<Value> {
129 pub fn new(value: Value) -> Binding<Value> {
130 Binding {
131 value: Arc::new(Mutex::new(BoundValue::new(value)))
132 }
133 }
134}
135
136impl<Value: 'static+Clone+PartialEq+Send> Changeable for Binding<Value> {
137 fn when_changed(&self, what: Arc<dyn Notifiable>) -> Box<dyn Releasable> {
138 self.value.lock().unwrap().when_changed(what)
139 }
140}
141
142impl<Value: 'static+Clone+PartialEq+Send> Bound<Value> for Binding<Value> {
143 fn get(&self) -> Value {
144 BindingContext::add_dependency(self.clone());
145
146 self.value.lock().unwrap().get()
147 }
148}
149
150impl<Value: 'static+Clone+PartialEq+Send> MutableBound<Value> for Binding<Value> {
151 fn set(&self, new_value: Value) {
152 let notifications = {
154 let mut cell = self.value.lock().unwrap();
155 let changed = cell.set_without_notifying(new_value);
156
157 if changed {
158 cell.get_notifiable_items()
159 } else {
160 vec![]
161 }
162 };
163
164 let mut needs_filtering = false;
166
167 for to_notify in notifications {
168 needs_filtering = !to_notify.mark_as_changed() || needs_filtering;
169 }
170
171 if needs_filtering {
172 let mut cell = self.value.lock().unwrap();
173 cell.filter_unused_notifications();
174 }
175 }
176}
177
178impl<Value: 'static + Clone + PartialEq + Send> WithBound<Value> for Binding<Value> {
179 fn with_ref<F, T>(&self, f: F) -> T
180 where
181 F: FnOnce(&Value) -> T,
182 {
183 f(&self.value.lock().unwrap().value)
184 }
185 fn with_mut<F>(&self, f: F)
186 where
187 F: FnOnce(&mut Value) -> bool,
188 {
189 let notifications = {
190 let mut v = self.value.lock().unwrap();
191 let changed = f(v.get_mut());
192
193 if changed {
194 v.get_notifiable_items()
195 } else {
196 vec![]
197 }
198 };
199
200 let mut needs_filtering = false;
202
203 for to_notify in notifications {
204 needs_filtering = !to_notify.mark_as_changed() || needs_filtering;
205 }
206
207 if needs_filtering {
208 let mut cell = self.value.lock().unwrap();
209 cell.filter_unused_notifications();
210 }
211 }
212
213}
214
215impl<Value: 'static+Clone+PartialEq+Send> From<Value> for Binding<Value> {
216 #[inline]
217 fn from(val: Value) -> Binding<Value> {
218 Binding::new(val)
219 }
220}
221
222impl<'a, Value: 'static+Clone+PartialEq+Send> From<&'a Binding<Value>> for Binding<Value> {
223 #[inline]
224 fn from(val: &'a Binding<Value>) -> Binding<Value> {
225 Binding::clone(val)
226 }
227}
228
229impl<'a, Value: 'static+Clone+PartialEq+Send> From<&'a Value> for Binding<Value> {
230 #[inline]
231 fn from(val: &'a Value) -> Binding<Value> {
232 Binding::new(val.clone())
233 }
234}