frui_widgets 0.0.1

Essential widgets for Frui UI framework
Documentation
use frui::{app::TEXT_FACTORY, prelude::*};

use druid_shell::piet::{
    kurbo::Point, Color, FontFamily, FontWeight, PietTextLayout, Text as TextExt, TextLayout,
    TextLayoutBuilder,
};

#[derive(LeafWidget)]
pub struct Text<S: AsRef<str>> {
    text: S,
    font_size: f64,
    font_color: Color,
    font_weight: FontWeight,
    font_family: FontFamily,
}

impl<S: AsRef<str>> Text<S> {
    pub fn new(string: S) -> Self {
        Self {
            text: string,
            font_size: 16.,
            font_color: Color::WHITE,
            font_weight: FontWeight::default(),
            font_family: FontFamily::default(),
        }
    }

    pub fn size(mut self, size: f64) -> Self {
        self.font_size = size;
        self
    }

    pub fn color(mut self, color: Color) -> Self {
        self.font_color = color;
        self
    }

    pub fn weight(mut self, weight: FontWeight) -> Self {
        self.font_weight = weight;
        self
    }

    pub fn family(mut self, family: FontFamily) -> Self {
        self.font_family = family;
        self
    }
}

#[cfg(not(feature = "miri"))]
impl<S: AsRef<str>> RenderState for Text<S> {
    type State = PietTextLayout;

    fn create_state(&self) -> Self::State {
        TEXT_FACTORY.with(|f| f.get().new_text_layout("").build().unwrap())
    }
}

#[cfg(not(feature = "miri"))]
impl<S: AsRef<str>> LeafWidget for Text<S> {
    fn layout(&self, ctx: RenderContext<Self>, constraints: Constraints) -> Size {
        let max_width = constraints.max().width;

        *ctx.rstate_mut() = TEXT_FACTORY.with(|f| {
            f.get()
                .new_text_layout(self.text.as_ref().to_owned())
                .font(self.font_family.clone(), self.font_size)
                .text_color(self.font_color.clone())
                .range_attribute(.., self.font_weight)
                .max_width(max_width)
                .build()
                .unwrap()
        });

        let text_size = ctx.rstate().size();

        Size {
            width: text_size.width,
            height: text_size.height,
        }
    }

    fn paint(&self, ctx: RenderContext<Self>, canvas: &mut PaintContext, offset: &Offset) {
        PietRenderContext::draw_text(
            canvas,
            &ctx.rstate(),
            Point {
                x: offset.x,
                y: offset.y,
            },
        );
    }
}

#[cfg(feature = "miri")]
impl<S: AsRef<str>> LeafWidget for Text<S> {
    fn layout(&self, _: RenderContext<Self>, constraints: Constraints) -> Size {
        Size {
            width: constraints.max().width,
            height: constraints.max().height,
        }
    }

    fn paint(&self, _: RenderContext<Self>, _: &mut PaintContext, _: &Offset) {}
}