faststep 0.1.0

UIKit-inspired embedded UI framework built on embedded-graphics
Documentation
#[path = "support/mod.rs"]
mod support;

use core::convert::Infallible;

use embedded_graphics::{
    Drawable,
    draw_target::DrawTarget,
    pixelcolor::Rgb565,
    prelude::{Point, Primitive},
    primitives::PrimitiveStyle,
};
use faststep::{
    ChildView, FsTheme, I18n, TouchEvent, TouchPhase, UiRuntimeDriver, UiRuntimePresenter,
    UiSystem, UiView, ViewEnvironment, ViewEvent, ViewKind, ViewRedraw, ViewRegistration,
    run_ui_system,
};

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
enum RootId {
    Surface,
}

struct RootView;

impl UiView<'static, RootId, (), 1> for RootView {
    fn configure(&mut self, registration: &mut ViewRegistration<'static, RootId, 1>) {
        let _ = registration.add_child(
            ChildView::new(RootId::Surface, registration.frame()).with_kind(ViewKind::Custom),
        );
    }

    fn handle_touch(
        &mut self,
        _touch: TouchEvent,
        _registration: &ViewRegistration<'static, RootId, 1>,
        _env: &ViewEnvironment<'_, 'static>,
    ) -> ViewEvent<()> {
        ViewEvent::redraw(ViewRedraw::Full)
    }

    fn draw<D>(
        &self,
        display: &mut D,
        registration: &ViewRegistration<'static, RootId, 1>,
        _env: &ViewEnvironment<'_, 'static>,
    ) where
        D: DrawTarget<Color = Rgb565>,
    {
        registration
            .frame()
            .into_styled(PrimitiveStyle::with_fill(Rgb565::new(31, 63, 31)))
            .draw(display)
            .ok();
    }
}

struct NoopDriver;

impl UiRuntimeDriver for NoopDriver {
    type Error = Infallible;

    fn idle_poll_ms(&self) -> u32 {
        16
    }
    fn active_poll_ms(&self) -> u32 {
        8
    }
    fn needs_active_poll(&self) -> bool {
        false
    }
    fn delay_ms(&mut self, _delay_ms: u32) {}
    fn now_ms(&self) -> u32 {
        0
    }

    fn poll_touch(&mut self, _now_ms: u32) -> Result<Option<TouchEvent>, Self::Error> {
        Ok(Some(TouchEvent::new(
            Point::new(12, 12),
            TouchPhase::End,
            1,
        )))
    }
}

struct ImmediatePresenter;

impl UiRuntimePresenter<'static, support::NullDisplay, RootView, RootId, (), 1>
    for ImmediatePresenter
{
    type Pending = ViewRedraw;
    type Error = Infallible;

    fn idle_pending(&self) -> Self::Pending {
        ViewRedraw::None
    }

    fn merge_pending(&self, current: Self::Pending, next: Self::Pending) -> Self::Pending {
        current.merge(next)
    }

    fn pending_for_event(&mut self, event: ViewEvent<()>) -> Self::Pending {
        event.redraw
    }

    fn should_present(
        &mut self,
        pending: Self::Pending,
        _since_present_ms: u32,
        _system: &UiSystem<'static, support::NullDisplay, RootView, RootId, (), 1>,
    ) -> bool {
        !matches!(pending, ViewRedraw::None)
    }

    fn present(
        &mut self,
        pending: Self::Pending,
        system: &mut UiSystem<'static, support::NullDisplay, RootView, RootId, (), 1>,
    ) -> Result<(), Self::Error> {
        let _ = system.draw_redraw(pending);
        Ok(())
    }
}

fn main() {
    let display = support::NullDisplay::new(support::bounds(320, 240));
    let root = RootView;
    let theme: FsTheme = support::theme();
    let i18n: I18n<'static> = support::i18n();
    let driver = NoopDriver;
    let presenter = ImmediatePresenter;

    if false {
        let _ = run_ui_system(display, root, theme, i18n, driver, presenter);
    }
}