euv_core/reactive/
impl.rs1use crate::*;
2
3impl<T> SignalInner<T>
5where
6 T: Clone,
7{
8 pub fn new(value: T) -> Self {
10 let inner: SignalInner<T> = SignalInner {
11 value,
12 listeners: Vec::new(),
13 };
14 inner
15 }
16}
17
18impl<T> SignalInner<T>
20where
21 T: Clone,
22{
23 pub fn notify(&mut self) {
25 for listener in self.get_listeners() {
26 let mut borrowed = listener.borrow_mut();
27 borrowed();
28 }
29 }
30}
31
32impl<T> Signal<T>
34where
35 T: Clone + PartialEq,
36{
37 pub fn from_inner(inner: *mut SignalInner<T>) -> Self {
44 Signal { inner }
45 }
46
47 #[allow(clippy::mut_from_ref)]
54 fn get_inner_mut(&self) -> &mut SignalInner<T> {
55 unsafe { &mut *self.inner }
56 }
57
58 pub fn get(&self) -> T {
60 self.get_inner_mut().get_value().clone()
61 }
62
63 pub fn try_get(&self) -> Option<T> {
69 Some(self.get_inner_mut().get_value().clone())
70 }
71
72 pub fn subscribe<F>(&self, callback: F)
74 where
75 F: FnMut() + 'static,
76 {
77 self.get_inner_mut()
78 .get_mut_listeners()
79 .push(Rc::new(RefCell::new(callback)));
80 }
81
82 pub fn set(&self, value: T) {
88 let inner: &mut SignalInner<T> = self.get_inner_mut();
89 if inner.get_value() == &value {
90 return;
91 }
92 let listeners: ListenerList = {
93 inner.set_value(value);
94 inner.get_listeners().iter().map(Rc::clone).collect()
95 };
96 for listener in &listeners {
97 let mut borrowed = listener.borrow_mut();
98 borrowed();
99 }
100 schedule_signal_update();
101 }
102
103 pub fn try_set(&self, value: T) -> bool {
114 let inner: &mut SignalInner<T> = self.get_inner_mut();
115 if inner.get_value() == &value {
116 return false;
117 }
118 let listeners: ListenerList = {
119 inner.set_value(value);
120 inner.get_listeners().iter().map(Rc::clone).collect()
121 };
122 for listener in &listeners {
123 listener.borrow_mut()();
124 }
125 schedule_signal_update();
126 true
127 }
128}
129
130impl<T> Deref for Signal<T>
132where
133 T: Clone + PartialEq,
134{
135 type Target = T;
136
137 fn deref(&self) -> &Self::Target {
138 panic!("Signal does not support direct dereference; use .get() instead");
139 }
140}
141
142impl<T> DerefMut for Signal<T>
144where
145 T: Clone + PartialEq,
146{
147 fn deref_mut(&mut self) -> &mut Self::Target {
148 panic!("Signal does not support direct dereference; use .set() instead");
149 }
150}
151
152impl<T> Clone for Signal<T>
154where
155 T: Clone + PartialEq,
156{
157 fn clone(&self) -> Self {
158 *self
159 }
160}
161
162impl<T> Copy for Signal<T> where T: Clone + PartialEq {}
166
167impl IntoReactiveValue for String {
169 fn into_reactive_value(self) -> AttributeValue {
170 AttributeValue::Text(self)
171 }
172}
173
174impl IntoReactiveValue for &str {
176 fn into_reactive_value(self) -> AttributeValue {
177 AttributeValue::Text(self.to_string())
178 }
179}
180
181impl IntoReactiveValue for Signal<String> {
183 fn into_reactive_value(self) -> AttributeValue {
184 AttributeValue::Signal(self)
185 }
186}
187
188impl IntoReactiveValue for Signal<bool> {
193 fn into_reactive_value(self) -> AttributeValue {
194 bool_signal_to_string_attribute_value(self)
195 }
196}
197
198impl IntoReactiveValue for crate::vdom::CssClass {
200 fn into_reactive_value(self) -> AttributeValue {
201 AttributeValue::Css(self)
202 }
203}
204
205impl IntoReactiveValue for &'static crate::vdom::CssClass {
207 fn into_reactive_value(self) -> AttributeValue {
208 AttributeValue::Css(self.clone())
209 }
210}
211
212impl<F> IntoCallbackAttribute for F
214where
215 F: FnMut(NativeEvent) + 'static,
216{
217 fn into_callback_attribute(self) -> AttributeValue {
218 AttributeValue::Event(NativeEventHandler::new(
219 NativeEventName::Other("callback".to_string()),
220 self,
221 ))
222 }
223}
224
225impl IntoCallbackAttribute for NativeEventHandler {
227 fn into_callback_attribute(self) -> AttributeValue {
228 AttributeValue::Event(self)
229 }
230}
231
232impl IntoCallbackAttribute for Option<NativeEventHandler> {
234 fn into_callback_attribute(self) -> AttributeValue {
235 match self {
236 Some(handler) => AttributeValue::Event(handler),
237 None => AttributeValue::Text(String::new()),
238 }
239 }
240}
241
242impl HookContext {
244 pub fn from_inner(inner: *mut HookContextInner) -> Self {
251 HookContext { inner }
252 }
253
254 #[allow(clippy::mut_from_ref)]
261 fn get_inner_mut(&self) -> &mut HookContextInner {
262 unsafe { &mut *self.inner }
263 }
264
265 pub fn get_hook_index(&self) -> usize {
267 *self.get_inner_mut().get_hook_index()
268 }
269
270 pub fn set_hook_index(&mut self, index: usize) {
272 self.get_inner_mut().set_hook_index(index);
273 }
274
275 pub fn get_hooks(&self) -> &Vec<Box<dyn Any>> {
277 self.get_inner_mut().get_hooks()
278 }
279
280 pub fn get_mut_hooks(&mut self) -> &mut Vec<Box<dyn Any>> {
282 self.get_inner_mut().get_mut_hooks()
283 }
284
285 pub fn reset_hook_index(&mut self) {
287 self.set_hook_index(0_usize);
288 }
289}
290
291impl Clone for HookContext {
293 fn clone(&self) -> Self {
294 *self
295 }
296}
297
298impl Copy for HookContext {}
302
303impl Default for HookContext {
305 fn default() -> Self {
306 let boxed: Box<HookContextInner> = Box::default();
307 HookContext::from_inner(Box::leak(boxed) as *mut HookContextInner)
308 }
309}
310
311impl HookContextInner {
313 pub const fn new() -> Self {
315 HookContextInner {
316 hooks: Vec::new(),
317 hook_index: 0_usize,
318 }
319 }
320}
321
322impl Default for HookContextInner {
324 fn default() -> Self {
325 Self::new()
326 }
327}
328
329unsafe impl Sync for HookContextCell {}