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}