返回 CodeWhale
motion.rs
1 //! Gallery: one state change caught at fixed moments. The gallery is static,
2 //! so each entry starts the motions at a base instant and paints a fixed
3 //! offset after it; nothing reads a clock while painting.
4
5 use std::sync::OnceLock;
6 use std::time::{Duration, Instant};
7
8 use ratatui::{buffer::Buffer, layout::Rect};
9
10 use super::Entry;
11 use crate::{MotionDemo, MotionMode, MotionPolicy, MotionSet, Paint, Spinner, Theme};
12
13 /// The instant every entry measures from. Read once, when the entries are
14 /// built, because an `Instant` cannot be made without the clock; only
15 /// differences from it are ever used.
16 fn base() -> Instant {
17 static BASE: OnceLock<Instant> = OnceLock::new();
18 *BASE.get_or_init(Instant::now)
19 }
20
21 /// Paint the demo `after` its state change to done, under `mode`.
22 fn frame(area: Rect, buf: &mut Buffer, theme: &Theme, mode: MotionMode, after: Duration) {
23 let (t0, policy) = (base(), MotionPolicy::new(mode, theme));
24 let mut motions = MotionSet::new();
25 MotionDemo::start(&mut motions, true, t0, policy);
26 MotionDemo::new(&motions, t0 + after, policy, true).paint(area, buf, theme);
27 }
28
29 fn working(area: Rect, buf: &mut Buffer, theme: &Theme) {
30 let policy = MotionPolicy::new(MotionMode::Full, theme);
31 MotionDemo::new(&MotionSet::new(), base(), policy, false).paint(area, buf, theme);
32 }
33
34 fn just_started(area: Rect, buf: &mut Buffer, theme: &Theme) {
35 frame(area, buf, theme, MotionMode::Full, Duration::ZERO);
36 }
37
38 fn mid_flight(area: Rect, buf: &mut Buffer, theme: &Theme) {
39 frame(
40 area,
41 buf,
42 theme,
43 MotionMode::Full,
44 Duration::from_millis(100),
45 );
46 }
47
48 fn settled(area: Rect, buf: &mut Buffer, theme: &Theme) {
49 frame(
50 area,
51 buf,
52 theme,
53 MotionMode::Full,
54 Duration::from_millis(500),
55 );
56 }
57
58 /// Reduced motion, 100 ms in: already the settled frame.
59 fn reduced(area: Rect, buf: &mut Buffer, theme: &Theme) {
60 frame(
61 area,
62 buf,
63 theme,
64 MotionMode::Reduced,
65 Duration::from_millis(100),
66 );
67 }
68
69 /// The spinner under each mode, 3 s into the same work: what `Reduced` and
70 /// `Still` hold still (kept from the first draft of this package).
71 fn modes(area: Rect, buf: &mut Buffer, theme: &Theme) {
72 for (i, (mode, label)) in [
73 (MotionMode::Full, "Working"),
74 (MotionMode::Reduced, "Reduced motion"),
75 (MotionMode::Still, "Still"),
76 ]
77 .into_iter()
78 .enumerate()
79 {
80 let row = Rect::new(area.x, area.y.saturating_add(i as u16), area.width, 1);
81 Spinner::new(label, Duration::from_secs(3), mode).paint(row.intersection(area), buf, theme);
82 }
83 }
84
85 pub(crate) fn entries() -> Vec<Entry> {
86 base();
87 [
88 ("motion-modes", modes as fn(Rect, &mut Buffer, &Theme)),
89 ("motion-working", working),
90 ("motion-started", just_started),
91 ("motion-mid-flight", mid_flight),
92 ("motion-settled", settled),
93 ("motion-reduced", reduced),
94 ]
95 .into_iter()
96 .map(|(name, draw)| Entry {
97 name,
98 width: 40,
99 height: 3,
100 draw,
101 })
102 .collect()
103 }
104
104 lines RUST