Skip to main content

guise/reactive/
signal.rs

1//! `Signal` — an observable state cell backed by a gpui entity.
2
3use gpui::{App, AppContext, Entity};
4
5/// A clonable handle to a piece of reactive state. React's `useState` value:
6/// reading is cheap, writing notifies every observer (see [`super::watch`]).
7///
8/// All clones share one backing entity, so passing a `Signal` around — or
9/// providing it as context — gives every holder the same live value.
10pub struct Signal<T> {
11  entity: Entity<T>,
12}
13
14impl<T: 'static> Signal<T> {
15  /// Create a new signal holding `value`.
16  pub fn new(cx: &mut App, value: T) -> Self {
17    Signal {
18      entity: cx.new(|_cx| value),
19    }
20  }
21
22  /// The backing entity — pass to `cx.observe(...)` or [`super::watch`].
23  pub fn entity(&self) -> &Entity<T> {
24    &self.entity
25  }
26
27  /// Borrow the current value.
28  pub fn read<'a>(&self, cx: &'a App) -> &'a T {
29    self.entity.read(cx)
30  }
31
32  /// Clone out the current value.
33  pub fn get(&self, cx: &App) -> T
34  where
35    T: Clone,
36  {
37    self.entity.read(cx).clone()
38  }
39
40  /// Replace the value and notify observers.
41  pub fn set(&self, cx: &mut App, value: T) {
42    self.entity.update(cx, |slot, cx| {
43      *slot = value;
44      cx.notify();
45    });
46  }
47
48  /// Replace the value and notify observers, unless the new value equals
49  /// the current one — then nothing happens (no notify).
50  pub fn set_if_changed(&self, cx: &mut App, value: T)
51  where
52    T: PartialEq,
53  {
54    self.entity.update(cx, |slot, cx| {
55      if *slot != value {
56        *slot = value;
57        cx.notify();
58      }
59    });
60  }
61
62  /// Mutate the value in place and notify observers.
63  pub fn update(&self, cx: &mut App, f: impl FnOnce(&mut T)) {
64    self.entity.update(cx, |slot, cx| {
65      f(slot);
66      cx.notify();
67    });
68  }
69}
70
71impl<T> Clone for Signal<T> {
72  fn clone(&self) -> Self {
73    Signal {
74      entity: self.entity.clone(),
75    }
76  }
77}