1use jag_draw::{Color, Rect};
4use jag_surface::Canvas;
5
6use crate::event::{
7 EventHandler, EventResult, KeyboardEvent, MouseClickEvent, MouseMoveEvent, ScrollEvent,
8};
9use crate::focus::FocusId;
10
11use super::Element;
12
13pub struct Text {
15 pub content: String,
16 pub pos: [f32; 2],
17 pub size: f32,
18 pub color: Color,
19}
20
21impl Text {
22 pub fn new(content: impl Into<String>, size: f32) -> Self {
26 Self {
27 content: content.into(),
28 pos: [0.0, 0.0],
29 size,
30 color: Color::from_srgba_u8([255, 255, 255, 255]),
31 }
32 }
33}
34
35impl Element for Text {
40 fn rect(&self) -> Rect {
41 let approx_w = self.content.len() as f32 * self.size * 0.5;
44 Rect {
45 x: self.pos[0],
46 y: self.pos[1] - self.size,
47 w: approx_w,
48 h: self.size,
49 }
50 }
51
52 fn set_rect(&mut self, rect: Rect) {
53 self.pos = [rect.x, rect.y + rect.h];
54 }
55
56 fn render(&self, canvas: &mut Canvas, z: i32) {
57 canvas.draw_text_run_weighted(
58 self.pos,
59 self.content.clone(),
60 self.size,
61 400.0,
62 self.color,
63 z,
64 );
65 }
66
67 fn focus_id(&self) -> Option<FocusId> {
68 None
69 }
70}
71
72impl EventHandler for Text {
77 fn handle_mouse_click(&mut self, _event: &MouseClickEvent) -> EventResult {
78 EventResult::Ignored
79 }
80
81 fn handle_keyboard(&mut self, _event: &KeyboardEvent) -> EventResult {
82 EventResult::Ignored
83 }
84
85 fn handle_mouse_move(&mut self, _event: &MouseMoveEvent) -> EventResult {
86 EventResult::Ignored
87 }
88
89 fn handle_scroll(&mut self, _event: &ScrollEvent) -> EventResult {
90 EventResult::Ignored
91 }
92
93 fn is_focused(&self) -> bool {
94 false
95 }
96
97 fn set_focused(&mut self, _focused: bool) {
98 }
100
101 fn contains_point(&self, x: f32, y: f32) -> bool {
102 let r = self.rect();
103 x >= r.x && x <= r.x + r.w && y >= r.y && y <= r.y + r.h
104 }
105}
106
107#[cfg(test)]
112mod tests {
113 use super::*;
114
115 #[test]
116 fn text_new() {
117 let t = Text::new("Hello", 16.0);
118 assert_eq!(t.content, "Hello");
119 assert_eq!(t.size, 16.0);
120 assert_eq!(t.pos, [0.0, 0.0]);
121 }
122
123 #[test]
124 fn text_is_not_focusable() {
125 let t = Text::new("No focus", 12.0);
126 assert!(t.focus_id().is_none());
127 assert!(!t.is_focused());
128 }
129
130 #[test]
131 fn text_set_rect_updates_pos() {
132 let mut t = Text::new("Pos", 14.0);
133 t.set_rect(Rect {
134 x: 10.0,
135 y: 20.0,
136 w: 100.0,
137 h: 14.0,
138 });
139 assert_eq!(t.pos[0], 10.0);
140 assert!((t.pos[1] - 34.0).abs() < f32::EPSILON);
142 }
143}