faststep 0.1.0

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

use crate::Localized;

/// Semantic classification for a registered child view.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum ViewKind {
    /// A custom application-defined view.
    Custom,
    /// An image-oriented leaf view.
    Image,
    /// A text-oriented leaf view.
    Text,
    /// A scroll container.
    Scroll,
    /// A stack-based navigation container.
    Stack,
    /// A tab-based navigation container.
    Tab,
    /// A split layout container.
    Split,
    /// An alert or modal host.
    AlertHost,
    /// A list view backed by a data source.
    List,
}

/// Common properties attached to a registered view.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct ViewProperties<'a> {
    /// Optional localized title for the view.
    pub title: Option<Localized<'a>>,
    /// Alpha applied by the host view or renderer.
    pub alpha: u8,
    /// Whether the view should be treated as hidden.
    pub hidden: bool,
    /// Whether drawing should be clipped to the view bounds.
    pub clips_to_bounds: bool,
    /// Whether the view should receive user interaction.
    pub user_interaction_enabled: bool,
}

impl Default for ViewProperties<'_> {
    fn default() -> Self {
        Self {
            title: None,
            alpha: 255,
            hidden: false,
            clips_to_bounds: false,
            user_interaction_enabled: true,
        }
    }
}

/// A child view registered by a parent [`crate::UiView`].
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct ChildView<'a, ViewId> {
    /// Application-defined child identifier.
    pub id: ViewId,
    /// Semantic type used by higher-level tooling or presenters.
    pub kind: ViewKind,
    /// Child frame in parent coordinates.
    pub frame: Rectangle,
    /// Child properties advertised by the parent.
    pub properties: ViewProperties<'a>,
}

impl<'a, ViewId> ChildView<'a, ViewId> {
    /// Creates a custom child view registration.
    pub const fn new(id: ViewId, frame: Rectangle) -> Self {
        Self {
            id,
            kind: ViewKind::Custom,
            frame,
            properties: ViewProperties {
                title: None,
                alpha: 255,
                hidden: false,
                clips_to_bounds: false,
                user_interaction_enabled: true,
            },
        }
    }

    /// Marks the child as a specific view kind.
    pub const fn with_kind(mut self, kind: ViewKind) -> Self {
        self.kind = kind;
        self
    }

    /// Sets the child title.
    pub const fn with_title(mut self, title: Localized<'a>) -> Self {
        self.properties.title = Some(title);
        self
    }

    /// Sets the child alpha.
    pub const fn with_alpha(mut self, alpha: u8) -> Self {
        self.properties.alpha = alpha;
        self
    }

    /// Marks the child as hidden or visible.
    pub const fn with_hidden(mut self, hidden: bool) -> Self {
        self.properties.hidden = hidden;
        self
    }

    /// Enables or disables clipping for this child.
    pub const fn with_clipping(mut self, clips_to_bounds: bool) -> Self {
        self.properties.clips_to_bounds = clips_to_bounds;
        self
    }
}

/// Mutable registration object passed to [`crate::UiView::configure`].
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ViewRegistration<'a, ViewId, const N: usize> {
    frame: Rectangle,
    properties: ViewProperties<'a>,
    children: Vec<ChildView<'a, ViewId>, N>,
}

impl<'a, ViewId, const N: usize> ViewRegistration<'a, ViewId, N> {
    /// Creates a registration rooted at the given frame.
    pub fn new(frame: Rectangle) -> Self {
        Self {
            frame,
            properties: ViewProperties::default(),
            children: Vec::new(),
        }
    }

    /// Returns the current root frame for the view.
    pub const fn frame(&self) -> Rectangle {
        self.frame
    }

    /// Updates the root frame for the view.
    pub fn set_frame(&mut self, frame: Rectangle) {
        self.frame = frame;
    }

    /// Returns the accumulated properties for the registered view.
    pub const fn properties(&self) -> &ViewProperties<'a> {
        &self.properties
    }

    /// Sets the view title.
    pub fn set_title(&mut self, title: Localized<'a>) {
        self.properties.title = Some(title);
    }

    /// Sets the alpha value used for the view.
    pub fn set_alpha(&mut self, alpha: u8) {
        self.properties.alpha = alpha;
    }

    /// Marks the registered view as hidden or visible.
    pub fn set_hidden(&mut self, hidden: bool) {
        self.properties.hidden = hidden;
    }

    /// Enables or disables clipping to bounds.
    pub fn set_clips_to_bounds(&mut self, clips_to_bounds: bool) {
        self.properties.clips_to_bounds = clips_to_bounds;
    }

    /// Enables or disables touch handling for the view.
    pub fn set_user_interaction_enabled(&mut self, enabled: bool) {
        self.properties.user_interaction_enabled = enabled;
    }

    /// Removes all previously registered child views.
    pub fn clear_children(&mut self) {
        self.children.clear();
    }

    /// Registers one child view.
    pub fn add_child(&mut self, child: ChildView<'a, ViewId>) -> Result<(), ChildView<'a, ViewId>> {
        self.children.push(child)
    }

    /// Returns the registered children as a slice.
    pub fn children(&self) -> &[ChildView<'a, ViewId>] {
        self.children.as_slice()
    }
}