1use glam::Vec2;
2use ori_graphics::{Rect, TextSection};
3use ori_macro::Build;
4
5use crate::{BoxConstraints, Context, DrawContext, LayoutContext, Style, View};
6
7#[derive(Clone, Debug, Build)]
8pub struct Text {
9 #[prop]
10 text: String,
11}
12
13impl Default for Text {
14 fn default() -> Self {
15 Self {
16 text: String::new(),
17 }
18 }
19}
20
21impl Text {
22 pub fn new(text: impl Into<String>) -> Self {
23 Self { text: text.into() }
24 }
25
26 pub fn text(mut self, text: impl Into<String>) -> Self {
28 self.text = text.into();
29 self
30 }
31}
32
33impl View for Text {
34 type State = f32;
35
36 fn build(&self) -> Self::State {
37 0.0
38 }
39
40 fn style(&self) -> Style {
41 Style::new("text")
42 }
43
44 fn layout(&self, state: &mut Self::State, cx: &mut LayoutContext, bc: BoxConstraints) -> Vec2 {
45 let font_size = cx.style_range("font-size", 0.0..bc.max.y);
46 *state = font_size;
47
48 let bc = cx.style_constraints(bc);
49
50 let section = TextSection {
51 rect: Rect::min_size(Vec2::ZERO, bc.max),
52 scale: font_size,
53 h_align: cx.style("text-align"),
54 v_align: cx.style("text-valign"),
55 wrap: cx.style("text-wrap"),
56 text: self.text.clone(),
57 font: cx.style("font"),
58 color: cx.style("color"),
59 };
60
61 let bounds = cx.messure_text(§ion).unwrap_or_default();
62 bc.constrain(bounds.size())
63 }
64
65 fn draw(&self, state: &mut Self::State, cx: &mut DrawContext) {
66 let section = TextSection {
67 rect: cx.rect().ceil(),
68 scale: *state,
69 h_align: cx.style("text-align"),
70 v_align: cx.style("text-valign"),
71 wrap: cx.style("text-wrap"),
72 text: self.text.clone(),
73 font: cx.style("font"),
74 color: cx.style("color"),
75 };
76
77 cx.draw(section);
78 }
79}