faststep 0.1.0

UIKit-inspired embedded UI framework built on embedded-graphics
Documentation
use embedded_graphics::primitives::Rectangle;

/// Redraw request emitted by a view update or interaction.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum ViewRedraw {
    /// No redraw is needed.
    None,
    /// Only the given area should be redrawn.
    Dirty(Rectangle),
    /// The full frame should be redrawn.
    Full,
}

impl ViewRedraw {
    /// Merges two redraw requests into the smallest safe superset.
    pub fn merge(self, other: Self) -> Self {
        match (self, other) {
            (Self::Full, _) | (_, Self::Full) => Self::Full,
            (Self::Dirty(left), Self::Dirty(right)) => Self::Dirty(union_rect(left, right)),
            (Self::Dirty(area), Self::None) | (Self::None, Self::Dirty(area)) => Self::Dirty(area),
            _ => Self::None,
        }
    }
}

/// Result of a view update or touch event.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct ViewEvent<Message> {
    /// Redraw requested by the view.
    pub redraw: ViewRedraw,
    /// Whether the event was captured by the view.
    pub captured: bool,
    /// Optional application message emitted by the view.
    pub message: Option<Message>,
}

impl<Message> ViewEvent<Message> {
    /// Returns a no-op event.
    pub const fn none() -> Self {
        Self {
            redraw: ViewRedraw::None,
            captured: false,
            message: None,
        }
    }

    /// Creates an event that only requests a redraw.
    pub const fn redraw(redraw: ViewRedraw) -> Self {
        Self {
            redraw,
            captured: false,
            message: None,
        }
    }

    /// Sets whether the originating event was captured.
    pub const fn captured(mut self, captured: bool) -> Self {
        self.captured = captured;
        self
    }

    /// Attaches an application message to the event.
    pub fn message(mut self, message: Message) -> Self {
        self.message = Some(message);
        self
    }
}

fn union_rect(left: Rectangle, right: Rectangle) -> Rectangle {
    let left_x = left.top_left.x.min(right.top_left.x);
    let top_y = left.top_left.y.min(right.top_left.y);
    let left_bottom = left.bottom_right().unwrap_or(left.top_left);
    let right_bottom = right.bottom_right().unwrap_or(right.top_left);
    let right_x = left_bottom.x.max(right_bottom.x);
    let bottom_y = left_bottom.y.max(right_bottom.y);
    Rectangle::with_corners(
        embedded_graphics::prelude::Point::new(left_x, top_y),
        embedded_graphics::prelude::Point::new(right_x, bottom_y),
    )
}