faststep 0.1.0

UIKit-inspired embedded UI framework built on embedded-graphics
Documentation
use embedded_graphics::{
    mono_font::{
        MonoFont,
        ascii::{FONT_6X10, FONT_7X14, FONT_9X18_BOLD, FONT_10X20},
    },
    pixelcolor::Rgb565,
};

use crate::EdgeInsets;

/// Supported bundled mono font roles for text views.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum TextFont {
    /// Small supporting text.
    Caption,
    /// Standard body text.
    Body,
    /// Emphasized body text.
    BodyStrong,
    /// Large title text.
    Title,
}

impl TextFont {
    pub(super) fn mono(self) -> &'static MonoFont<'static> {
        match self {
            Self::Caption => &FONT_6X10,
            Self::Body => &FONT_7X14,
            Self::BodyStrong => &FONT_9X18_BOLD,
            Self::Title => &FONT_10X20,
        }
    }

    pub(super) fn advance(self) -> i32 {
        let font = self.mono();
        (font.character_size.width + font.character_spacing) as i32
    }

    pub(super) fn line_height(self) -> i32 {
        self.mono().character_size.height as i32
    }
}

/// Style for one text run.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct TextRunStyle {
    /// Font role used for the run.
    pub font: TextFont,
    /// Foreground color.
    pub color: Rgb565,
}

impl TextRunStyle {
    /// Creates an explicit run style.
    pub const fn new(font: TextFont, color: Rgb565) -> Self {
        Self { font, color }
    }

    /// Creates a caption run style.
    pub const fn caption(color: Rgb565) -> Self {
        Self::new(TextFont::Caption, color)
    }

    /// Creates a body run style.
    pub const fn body(color: Rgb565) -> Self {
        Self::new(TextFont::Body, color)
    }

    /// Creates an emphasized body run style.
    pub const fn body_strong(color: Rgb565) -> Self {
        Self::new(TextFont::BodyStrong, color)
    }

    /// Creates a title run style.
    pub const fn title(color: Rgb565) -> Self {
        Self::new(TextFont::Title, color)
    }
}

/// One styled segment of rich text.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct TextSpan<'a> {
    /// Text content for this span.
    pub text: &'a str,
    /// Visual style for this span.
    pub style: TextRunStyle,
}

impl<'a> TextSpan<'a> {
    /// Creates a styled text span.
    pub const fn new(text: &'a str, style: TextRunStyle) -> Self {
        Self { text, style }
    }
}

/// Horizontal text alignment.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum TextAlignment {
    /// Align to the leading edge.
    Leading,
    /// Center horizontally.
    Center,
    /// Align to the trailing edge.
    Trailing,
}

/// Vertical text alignment.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum TextVerticalAlignment {
    /// Align to the top edge.
    Top,
    /// Center vertically.
    Center,
    /// Align to the bottom edge.
    Bottom,
}

/// Wrapping mode for text layout.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum TextWrap {
    /// Keep all text on one line.
    SingleLine,
    /// Wrap content across multiple lines.
    Multiline,
}

/// Shared container style for [`crate::TextView`] and [`crate::RichTextView`].
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct TextViewStyle {
    /// Horizontal alignment for rendered lines.
    pub alignment: TextAlignment,
    /// Vertical alignment for the rendered block.
    pub vertical_alignment: TextVerticalAlignment,
    /// Wrapping behavior.
    pub wrap: TextWrap,
    /// Extra spacing inserted between lines.
    pub line_spacing: u32,
    /// Content padding.
    pub insets: EdgeInsets,
    /// Optional background fill for the shell.
    pub background: Option<Rgb565>,
    /// Optional border color for the shell.
    pub border: Option<Rgb565>,
    /// Border width in pixels.
    pub border_width: u32,
    /// Corner radius for the shell.
    pub corner_radius: u32,
}

impl TextViewStyle {
    /// Creates the default text view style.
    pub const fn new() -> Self {
        Self {
            alignment: TextAlignment::Leading,
            vertical_alignment: TextVerticalAlignment::Top,
            wrap: TextWrap::SingleLine,
            line_spacing: 4,
            insets: EdgeInsets::all(0),
            background: None,
            border: None,
            border_width: 0,
            corner_radius: 0,
        }
    }

    /// Sets horizontal alignment.
    pub fn with_alignment(mut self, alignment: TextAlignment) -> Self {
        self.alignment = alignment;
        self
    }

    /// Sets vertical alignment.
    pub fn with_vertical_alignment(mut self, alignment: TextVerticalAlignment) -> Self {
        self.vertical_alignment = alignment;
        self
    }

    /// Sets wrapping behavior.
    pub fn with_wrap(mut self, wrap: TextWrap) -> Self {
        self.wrap = wrap;
        self
    }

    /// Sets extra line spacing.
    pub fn with_line_spacing(mut self, line_spacing: u32) -> Self {
        self.line_spacing = line_spacing;
        self
    }

    /// Sets content padding.
    pub fn with_insets(mut self, insets: EdgeInsets) -> Self {
        self.insets = insets;
        self
    }

    /// Sets the shell background color.
    pub fn with_background(mut self, background: Rgb565) -> Self {
        self.background = Some(background);
        self
    }

    /// Sets shell border color and width.
    pub fn with_border(mut self, border: Rgb565, border_width: u32) -> Self {
        self.border = Some(border);
        self.border_width = border_width;
        self
    }

    /// Sets the shell corner radius.
    pub fn with_corner_radius(mut self, corner_radius: u32) -> Self {
        self.corner_radius = corner_radius;
        self
    }
}

impl Default for TextViewStyle {
    fn default() -> Self {
        Self::new()
    }
}