summaryrefslogblamecommitdiffstats
path: root/pure/src/widget/text.rs
blob: e3a7d299afdf2fe6b7d1bf7445a409e3a1cb0d12 (plain) (tree)















































































































































































                                                                             








                                                                         
use crate::{Element, Tree, Widget};

use iced_native::alignment;
use iced_native::layout::{self, Layout};
use iced_native::renderer;
use iced_native::text;
use iced_native::{Color, Hasher, Length, Point, Rectangle, Size};

use std::any::{self, Any};

pub struct Text<Renderer>
where
    Renderer: text::Renderer,
{
    content: String,
    size: Option<u16>,
    color: Option<Color>,
    font: Renderer::Font,
    width: Length,
    height: Length,
    horizontal_alignment: alignment::Horizontal,
    vertical_alignment: alignment::Vertical,
}

impl<Renderer: text::Renderer> Text<Renderer> {
    /// Create a new fragment of [`Text`] with the given contents.
    pub fn new<T: Into<String>>(label: T) -> Self {
        Text {
            content: label.into(),
            size: None,
            color: None,
            font: Default::default(),
            width: Length::Shrink,
            height: Length::Shrink,
            horizontal_alignment: alignment::Horizontal::Left,
            vertical_alignment: alignment::Vertical::Top,
        }
    }

    /// Sets the size of the [`Text`].
    pub fn size(mut self, size: u16) -> Self {
        self.size = Some(size);
        self
    }

    /// Sets the [`Color`] of the [`Text`].
    pub fn color<C: Into<Color>>(mut self, color: C) -> Self {
        self.color = Some(color.into());
        self
    }

    /// Sets the [`Font`] of the [`Text`].
    ///
    /// [`Font`]: Renderer::Font
    pub fn font(mut self, font: impl Into<Renderer::Font>) -> Self {
        self.font = font.into();
        self
    }

    /// Sets the width of the [`Text`] boundaries.
    pub fn width(mut self, width: Length) -> Self {
        self.width = width;
        self
    }

    /// Sets the height of the [`Text`] boundaries.
    pub fn height(mut self, height: Length) -> Self {
        self.height = height;
        self
    }

    /// Sets the [`HorizontalAlignment`] of the [`Text`].
    pub fn horizontal_alignment(
        mut self,
        alignment: alignment::Horizontal,
    ) -> Self {
        self.horizontal_alignment = alignment;
        self
    }

    /// Sets the [`VerticalAlignment`] of the [`Text`].
    pub fn vertical_alignment(
        mut self,
        alignment: alignment::Vertical,
    ) -> Self {
        self.vertical_alignment = alignment;
        self
    }
}

impl<Message, Renderer> Widget<Message, Renderer> for Text<Renderer>
where
    Renderer: text::Renderer,
{
    fn tag(&self) -> any::TypeId {
        any::TypeId::of::<()>()
    }

    fn state(&self) -> Box<dyn Any> {
        Box::new(())
    }

    fn children(&self) -> &[Element<Message, Renderer>] {
        &[]
    }

    fn width(&self) -> Length {
        self.width
    }

    fn height(&self) -> Length {
        self.height
    }

    fn layout(
        &self,
        renderer: &Renderer,
        limits: &layout::Limits,
    ) -> layout::Node {
        let limits = limits.width(self.width).height(self.height);

        let size = self.size.unwrap_or(renderer.default_size());

        let bounds = limits.max();

        let (width, height) =
            renderer.measure(&self.content, size, self.font.clone(), bounds);

        let size = limits.resolve(Size::new(width, height));

        layout::Node::new(size)
    }

    fn draw(
        &self,
        _tree: &Tree<Message, Renderer>,
        renderer: &mut Renderer,
        style: &renderer::Style,
        layout: Layout<'_>,
        _cursor_position: Point,
        _viewport: &Rectangle,
    ) {
        iced_native::widget::text::draw(
            renderer,
            style,
            layout,
            &self.content,
            self.font.clone(),
            self.size,
            self.color,
            self.horizontal_alignment,
            self.vertical_alignment,
        );
    }

    fn hash_layout(&self, state: &mut Hasher) {
        use std::hash::Hash;

        struct Marker;
        std::any::TypeId::of::<Marker>().hash(state);

        self.content.hash(state);
        self.size.hash(state);
        self.width.hash(state);
        self.height.hash(state);
    }
}

impl<Message, Renderer> Into<Element<Message, Renderer>> for Text<Renderer>
where
    Renderer: text::Renderer + 'static,
{
    fn into(self) -> Element<Message, Renderer> {
        Element::new(self)
    }
}

impl<Message, Renderer> Into<Element<Message, Renderer>> for &'static str
where
    Renderer: text::Renderer + 'static,
{
    fn into(self) -> Element<Message, Renderer> {
        Text::new(self).into()
    }
}