standard-plugin-sdk 0.1.2

Write Standard Code plugins in Rust: wasm components against standard:plugin@2.0.0
Documentation
//! A stage in the graphics model drawn with the shape helpers: a panel, an
//! orbiting dot, a sweeping line, a progress bar and a label. It animates at
//! the viewer's paced rate on mains power and once a second when saving
//! power, and follows the viewer's theme colours.
//!
//! Manifest surfaces: `[{ "id": "stage", "anchor": "stage", "model": "pixels" }]`.
#![no_std]

use standard_plugin::prelude::*;
use standard_plugin::{Power, libm, view};

#[standard_plugin::ui]
struct ShapesStage {
    stage: Surface<Pixels>,
}

impl UiPlugin for ShapesStage {
    fn activate(_cx: &mut Context) -> Self {
        Self {
            stage: Surface::new("stage"),
        }
    }

    fn frame(&mut self, frame: &Frame) {
        let (w, h) = self.stage.size();
        if w == 0 || h == 0 {
            // No pixel geometry yet: a resize will follow.
            return;
        }
        let theme = view::theme();
        let (fg, bg, accent) = (
            Rgba::hex(theme.fg),
            Rgba::hex(theme.bg),
            Rgba::hex(theme.accent),
        );
        let t = (frame.now_ms() % 4000) as f32 / 4000.0;

        // A full repaint: nothing is carried forward from the last frame.
        self.stage.clear(bg);
        let panel = Area::new(8, 8, w.saturating_sub(16), h.saturating_sub(16));
        self.stage
            .fill_rounded_rect(panel, 12, Rgba::hex(theme.recede_bg));
        self.stage
            .rounded_rect(panel, 12, Rgba::hex(theme.recede_fg));

        let (cx, cy) = (w as f32 / 2.0, h as f32 / 2.0);
        let radius = (w.min(h) / 4) as f32;
        let angle = t * core::f32::consts::TAU;
        // `no_std` has no `f32::sin`: the SDK re-exports `libm`. The dot
        // moves between pixels; the shapes antialias it there.
        let dot = (
            cx + radius * libm::cosf(angle),
            cy + radius * libm::sinf(angle),
        );
        self.stage
            .circle((cx, cy), radius, Rgba::hex(theme.recede_fg));
        self.stage
            .line((cx as i32, cy as i32), (dot.0 as i32, dot.1 as i32), accent);
        self.stage.fill_circle(dot, 6.0, accent);

        let bar = Area::new(24, h as i32 - 40, w.saturating_sub(48), 8);
        self.stage
            .bar(bar, t, accent, Rgba::hex(theme.recede_fg).with_alpha(96));
        self.stage.label(24, 24, "shapes", fg);
        let _ = self.stage.commit();

        match frame.power() {
            Power::Mains => frame.request_frame(),
            Power::SavePower => frame.wake_after(1000),
        }
    }
}