sequoia_view/
dev_overlay.rs1use sequoia_layout::LayoutStyle;
2
3use crate::any::AnyView;
4use crate::runtime::Runtime;
5use crate::view::View;
6use crate::views::{Column, Row, Text, Unit};
7
8#[derive(Clone)]
9pub struct DevOverlay {
10 rt: Runtime,
11 tick: sequoia_reactive::Signal<u64>,
12 show_errors: sequoia_reactive::Signal<bool>,
13}
14
15impl DevOverlay {
16 pub fn new(rt: Runtime) -> Self {
17 Self {
18 rt,
19 tick: sequoia_reactive::Signal::new(0),
20 show_errors: sequoia_reactive::Signal::new(true),
21 }
22 }
23
24 pub fn summary_untracked(&self) -> String {
25 let s = self.rt.stats();
26 format!(
27 "el={} mounts={} rebuilds={} unmounts={} errors={}",
28 self.rt.element_count(),
29 s.mounts,
30 s.rebuilds,
31 s.unmounts,
32 s.errors
33 )
34 }
35}
36
37impl View for DevOverlay {
38 fn body(&self) -> impl View + 'static {
39 Unit
40 }
41
42 fn children_override(&self) -> Option<Vec<AnyView>> {
43 let _ = self.tick.get();
44 let show_errors = self.show_errors.get();
45 let s = self.rt.stats();
46 let header = Text::new(format!(
47 "el={} mounts={} rebuilds={} unmounts={} errors={}",
48 self.rt.element_count(),
49 s.mounts,
50 s.rebuilds,
51 s.unmounts,
52 s.errors
53 ))
54 .size(11.0);
55 let tick = self.tick.clone();
56 let refresh = RefreshBtn {
57 on_press: std::rc::Rc::new(move || tick.update(|n| *n += 1)),
58 };
59 let show = self.show_errors.clone();
60 let toggle = RefreshBtn {
61 on_press: std::rc::Rc::new(move || show.update(|v| *v = !*v)),
62 };
63 let mut col = Column::new()
64 .gap(6.0)
65 .child(header)
66 .child(Row::new().gap(8.0).child(refresh).child(toggle));
67 if show_errors {
68 for e in self.rt.errors().into_iter().rev().take(8) {
69 col = col.child(Text::new(format!("⚠ {}: {}", e.type_name, e.message)).size(11.0));
70 }
71 }
72 Some(vec![AnyView::new(col)])
73 }
74
75 fn layout_style(&self) -> LayoutStyle {
76 LayoutStyle::default()
77 }
78}
79
80#[derive(Clone)]
81struct RefreshBtn {
82 on_press: std::rc::Rc<dyn Fn()>,
83}
84
85impl View for RefreshBtn {
86 fn body(&self) -> impl View + 'static {
87 Unit
88 }
89
90 fn children_override(&self) -> Option<Vec<AnyView>> {
91 Some(vec![AnyView::new(Text::new("↻ refresh").size(11.0).bold())])
92 }
93
94 fn layout_style(&self) -> LayoutStyle {
95 LayoutStyle::default()
96 }
97
98 fn on_event(&self, event: &sequoia_input::Event, ctx: &mut crate::view::EventCtx) {
99 match event {
100 sequoia_input::Event::Pointer(sequoia_input::PointerEvent::Up {
101 button: sequoia_input::PointerButton::Left,
102 pos,
103 ..
104 }) if ctx.rect.contains(*pos) => {
105 (self.on_press)();
106 ctx.handled();
107 }
108 _ => {}
109 }
110 }
111}