floem/views/editor/
listener.rs

1use floem_reactive::{RwSignal, Scope, SignalGet, SignalUpdate};
2
3/// A signal listener that receives 'events' from the outside and runs the callback.
4///
5/// This is implemented using effects and normal rw signals. This should be used when it doesn't
6/// make sense to think of it as 'storing' a value, like an `RwSignal` would typically be used for.
7///
8/// Copied/Cloned listeners refer to the same listener.
9#[derive(Debug)]
10pub struct Listener<T: 'static> {
11    cx: Scope,
12    val: RwSignal<Option<T>>,
13}
14
15impl<T: Clone + 'static> Listener<T> {
16    pub fn new(cx: Scope, on_val: impl Fn(T) + 'static) -> Listener<T> {
17        let val = cx.create_rw_signal(None);
18
19        let listener = Listener { val, cx };
20        listener.listen(on_val);
21
22        listener
23    }
24
25    /// Construct a listener when you can't yet give it a callback.
26    ///
27    /// Call `listen` to set a callback.
28    pub fn new_empty(cx: Scope) -> Listener<T> {
29        let val = cx.create_rw_signal(None);
30        Listener { val, cx }
31    }
32
33    pub fn scope(&self) -> Scope {
34        self.cx
35    }
36
37    /// Listen for values sent to this listener.
38    pub fn listen(self, on_val: impl Fn(T) + 'static) {
39        self.listen_with(self.cx, on_val)
40    }
41
42    /// Listen for values sent to this listener.
43    ///
44    /// Allows creating the effect with a custom scope, letting it be disposed of.
45    pub fn listen_with(self, cx: Scope, on_val: impl Fn(T) + 'static) {
46        let val = self.val;
47
48        cx.create_effect(move |_| {
49            // TODO(minor): Signals could have a `take` method to avoid cloning.
50            if let Some(cmd) = val.get() {
51                on_val(cmd);
52            }
53        });
54    }
55
56    /// Send a value to the listener.
57    pub fn send(&self, v: T) {
58        self.val.set(Some(v));
59    }
60}
61
62impl<T: 'static> Copy for Listener<T> {}
63
64impl<T: 'static> Clone for Listener<T> {
65    fn clone(&self) -> Self {
66        *self
67    }
68}