pixel_widgets/widget/
text.rs

1use std::borrow::Cow;
2
3use crate::draw::Primitive;
4use crate::event::Event;
5use crate::layout::{Rectangle, Size};
6use crate::node::{IntoNode, Node};
7use crate::style::Stylesheet;
8use crate::text;
9use crate::widget::*;
10
11/// Widget that renders a paragraph of text.
12#[derive(Default)]
13pub struct Text {
14    text: String,
15}
16
17impl Text {
18    /// Constructs a new `Text`
19    pub fn new<S: Into<String>>(text: S) -> Self {
20        Self { text: text.into() }
21    }
22
23    /// Sets the text value.
24    pub fn val(mut self, text: impl Into<String>) -> Self {
25        self.text = text.into();
26        self
27    }
28}
29
30impl<'a, T> Widget<'a, T> for Text {
31    type State = ();
32
33    fn mount(&self) {}
34
35    fn widget(&self) -> &'static str {
36        "text"
37    }
38
39    fn len(&self) -> usize {
40        0
41    }
42
43    fn visit_children(&mut self, _: &mut dyn FnMut(&mut dyn GenericNode<'a, T>)) {}
44
45    fn size(&self, _: &(), style: &Stylesheet) -> (Size, Size) {
46        let width = style.width;
47        let height = style.height;
48        let text = text::Text {
49            text: Cow::Borrowed(self.text.as_str()),
50            font: style.font.clone(),
51            size: style.text_size,
52            wrap: style.text_wrap,
53            color: style.color,
54        };
55        let content = match (width, height) {
56            (Size::Shrink, Size::Shrink) => {
57                let measured = text.measure(None);
58                (Size::Exact(measured.width()), Size::Exact(measured.height()))
59            }
60            (Size::Shrink, height) => {
61                let measured = text.measure(None);
62                (Size::Exact(measured.width()), height)
63            }
64            (Size::Exact(size), Size::Shrink) => {
65                let measured = text.measure(Some(Rectangle::from_wh(size, std::f32::INFINITY)));
66                (Size::Exact(size), Size::Exact(measured.height()))
67            }
68            (width, height) => (width, height),
69        };
70        style
71            .background
72            .resolve_size((style.width, style.height), content, style.padding)
73    }
74
75    fn event(&mut self, _: &mut (), _: Rectangle, _: Rectangle, _: &Stylesheet, _: Event, _: &mut Context<T>) {}
76
77    fn draw(&mut self, _: &mut (), layout: Rectangle, _: Rectangle, style: &Stylesheet) -> Vec<Primitive<'a>> {
78        let mut result = Vec::new();
79        result.extend(style.background.render(layout));
80        result.push(Primitive::DrawText(
81            text::Text {
82                text: Cow::Owned(self.text.clone()),
83                font: style.font.clone(),
84                size: style.text_size,
85                wrap: style.text_wrap,
86                color: style.color,
87            },
88            style.background.content_rect(layout, style.padding),
89        ));
90        result
91    }
92}
93
94impl<'a, T: 'a> IntoNode<'a, T> for Text {
95    fn into_node(self) -> Node<'a, T> {
96        Node::from_widget(self)
97    }
98}
99
100impl<'a, T: 'a, S: 'a + Into<String>> IntoNode<'a, T> for S {
101    fn into_node(self) -> Node<'a, T> {
102        Node::from_widget(Text::new(self))
103    }
104}