duat_core/widgets/
notifier.rs1use std::{
11 marker::PhantomData,
12 sync::atomic::{AtomicBool, Ordering},
13};
14
15use super::{CheckerFn, Widget, WidgetCfg};
16use crate::{
17 context::{self, Notifications},
18 hooks::{self, KeySent},
19 text::Text,
20 ui::{PushSpecs, Ui},
21};
22
23pub struct Notifier<U> {
35 notifications: Notifications,
36 text: Text,
37 _ghost: PhantomData<U>,
38}
39
40static CLEAR_NOTIFS: AtomicBool = AtomicBool::new(false);
41
42impl<U: Ui> Widget<U> for Notifier<U> {
43 type Cfg = NotificationsCfg<U>;
44
45 fn cfg() -> Self::Cfg {
46 NotificationsCfg(None, PhantomData)
47 }
48
49 fn update(&mut self, _area: &<U as Ui>::Area) {
50 let clear_notifs = CLEAR_NOTIFS.swap(false, Ordering::Relaxed);
51 if self.notifications.has_changed() {
52 let notifications = self.notifications.read();
53 self.text = notifications.last().cloned().unwrap_or_default()
54 } else if clear_notifs {
55 self.text = Text::new()
56 }
57 }
58
59 fn text(&self) -> &Text {
60 &self.text
61 }
62
63 fn text_mut(&mut self) -> &mut Text {
64 &mut self.text
65 }
66
67 fn once() -> Result<(), Text> {
68 hooks::add_grouped::<KeySent>("RemoveNotificationsOnInput", |_| {
69 CLEAR_NOTIFS.store(true, Ordering::Relaxed);
70 });
71 Ok(())
72 }
73}
74
75#[doc(hidden)]
87pub struct NotificationsCfg<U>(Option<(u16, u16)>, PhantomData<U>);
88
89impl<U> NotificationsCfg<U> {
90 pub fn left_with_ratio(self, den: u16, div: u16) -> Self {
97 Self(Some((den, div)), PhantomData)
98 }
99}
100
101impl<U: Ui> WidgetCfg<U> for NotificationsCfg<U> {
102 type Widget = Notifier<U>;
103
104 fn build(self, _: bool) -> (Self::Widget, impl CheckerFn, PushSpecs) {
105 let widget = Notifier {
106 notifications: context::notifications(),
107 text: Text::new(),
108 _ghost: PhantomData,
109 };
110
111 let checker = {
112 let checker = widget.notifications.checker();
113 move || checker() || CLEAR_NOTIFS.load(Ordering::Relaxed)
114 };
115
116 let specs = if let Some((den, div)) = self.0 {
117 PushSpecs::left().with_hor_ratio(den, div)
118 } else {
119 PushSpecs::below().with_ver_len(1.0)
120 };
121
122 (widget, checker, specs)
123 }
124}