Skip to main content

clock_card/
clock_card.rs

1//! A sidebar card: the time since the viewer started and a bar of the
2//! seconds. It repaints once a second and only while the card is visible.
3//!
4//! Manifest (`bundle/standard-plugin.json`):
5//!
6//! ```json
7//! {
8//!   "apiVersion": 2, "kind": "ui", "id": "clock-card", "version": "0.1.0",
9//!   "module": "clock_card.wasm",
10//!   "surfaces": [{ "id": "card", "anchor": "sidebar.card", "model": "cells", "height": 2 }],
11//!   "grants": {}
12//! }
13//! ```
14#![no_std]
15
16use standard_plugin::prelude::*;
17
18#[standard_plugin::ui]
19struct ClockCard {
20    card: Surface<Cells>,
21    shown: Option<u64>,
22}
23
24impl UiPlugin for ClockCard {
25    fn activate(_cx: &mut Context) -> Self {
26        Self {
27            card: Surface::new("card"),
28            shown: None,
29        }
30    }
31
32    fn frame(&mut self, frame: &Frame) {
33        let second = frame.now_ms() / 1000;
34        if self.shown != Some(second) {
35            self.shown = Some(second);
36            let (cols, _) = self.card.size();
37            let time = format!(
38                "{:02}:{:02}:{:02}",
39                second / 3600 % 24,
40                second / 60 % 60,
41                second % 60
42            );
43            self.card.text(0, 0, &time, Style::fg(Colour::FG).bold());
44            let fraction = (second % 60) as f32 / 60.0;
45            let track = Style::fg(Colour::RECEDE_FG);
46            self.card.bar(
47                Area::new(0, 1, cols, 1),
48                fraction,
49                Style::fg(Colour::ACCENT),
50                track,
51            );
52            // Publishes only the cells that changed.
53            let _ = self.card.commit();
54        }
55        // The next second boundary: an idle viewer wakes once a second.
56        frame.wake_at((second + 1) * 1000);
57    }
58
59    fn event(&mut self, event: Event, _cx: &mut Context) {
60        if let Event::Resize { .. } = event {
61            // The card has a new, empty buffer: repaint on the next frame.
62            self.shown = None;
63        }
64    }
65}