1use crate::animation::animation::{ Animation, Vec2Animation, FadeAnimation };
2use crate::style::color::Color;
3use crate::widget::Widget;
4use crate::graphics::Renderer;
5use log::{ debug, info };
6use std::sync::Arc;
7use std::cell::RefCell;
8
9pub struct TextView {
10 x: f32,
11 y: f32,
12 width: f32,
13 height: f32,
14 text: String,
15 font_size: f32,
16 background_color: Color,
17 text_color: Color,
18 is_hovered: bool,
19 hover_background_color: Color,
20 hover_text_color: Color,
21 on_hover: Option<Arc<RefCell<dyn FnMut(bool) + 'static>>>,
22 is_pressed: bool,
23 on_click: Option<Arc<RefCell<dyn FnMut() + 'static>>>,
24 position_animation: Option<Vec2Animation>,
25 fade_animation: Option<FadeAnimation>,
26 opacity: f32,
27}
28
29impl TextView {
30 pub fn new(text: &str, renderer: &Renderer) -> Self {
31 debug!("Creating new TextView with text: '{}'", text);
32 let background_color = Color::new(1.0, 1.0, 1.0, 0.5);
33 let text_color = Color::new(0.0, 0.0, 0.0, 1.0);
34
35 let mut tv = Self {
36 x: 0.0,
37 y: 0.0,
38 width: 0.0,
39 height: 0.0,
40 text: text.to_string(),
41 font_size: 32.0,
42 background_color,
43 text_color,
44 is_hovered: false,
45 hover_background_color: Color::new(0.9, 0.9, 0.9, 0.7),
46 hover_text_color: Color::new(0.0, 0.0, 0.0, 1.0),
47 on_hover: None,
48 is_pressed: false,
49 on_click: None,
50 position_animation: None,
51 fade_animation: None,
52 opacity: 1.0,
53 };
54 tv.update_size(renderer);
55 info!("TextView created with size: {}x{}", tv.width, tv.height);
56 tv
57 }
58
59 pub fn with_style(
60 text: String,
61 font_size: f32,
62 background_color: Color,
63 text_color: Color,
64 hover_background_color: Color,
65 hover_text_color: Color,
66 renderer: &Renderer
67 ) -> Self {
68 let mut tv = Self {
69 x: 0.0,
70 y: 0.0,
71 width: 0.0,
72 height: 0.0,
73 text,
74 font_size,
75 background_color,
76 text_color,
77 hover_background_color,
78 hover_text_color,
79 is_hovered: false,
80 opacity: 1.0,
81 on_hover: None,
82 is_pressed: false,
83 on_click: None,
84 position_animation: None,
85 fade_animation: None,
86 };
87 tv.update_size(renderer);
88 tv
89 }
90
91 fn update_size(&mut self, renderer: &Renderer) {
92 let (width, height) = renderer
93 .text_renderer()
94 .font_renderer()
95 .calculate_text_size(&self.text, self.font_size);
96 self.width = width + 20.0; self.height = height + 10.0;
98 debug!("TextView size updated: {}x{}", self.width, self.height);
99 }
100
101 pub fn set_text(&mut self, text: &str, renderer: &Renderer) {
102 debug!("TextView text changing from '{}' to '{}'", self.text, text);
103 self.text = text.to_string();
104 self.update_size(renderer);
105 }
106
107 pub fn set_font_size(&mut self, size: f32, renderer: &Renderer) {
108 debug!("TextView font size changing from {} to {}", self.font_size, size);
109 self.font_size = size;
110 self.update_size(renderer);
111 }
112
113 pub fn set_background_color(&mut self, color: Color) {
114 self.background_color = color;
115 }
116
117 pub fn set_text_color(&mut self, color: Color) {
118 self.text_color = color;
119 }
120
121 pub fn set_position(&mut self, x: f32, y: f32) {
122 self.x = x;
123 self.y = y;
124 }
125
126 pub fn set_hover_background_color(&mut self, color: Color) {
127 self.hover_background_color = color;
128 }
129
130 pub fn set_hover_text_color(&mut self, color: Color) {
131 self.hover_text_color = color;
132 }
133
134 pub fn update_hover(&mut self, x: f32, y: f32) {
135 let was_hovered = self.is_hovered;
136 self.is_hovered = self.contains_point(x, y);
137
138 if was_hovered != self.is_hovered {
139 if let Some(callback) = &self.on_hover {
140 callback.borrow_mut()(self.is_hovered);
141 }
142 }
143 }
144
145 pub fn has_fade_animation(&self) -> bool {
146 self.fade_animation.is_some()
147 }
148
149 pub fn has_position_animation(&self) -> bool {
150 self.position_animation.is_some()
151 }
152}
153
154impl Widget for TextView {
155 fn get_position(&self) -> (f32, f32) {
156 (self.x, self.y)
157 }
158
159 fn get_size(&self) -> (f32, f32) {
160 (self.width, self.height)
161 }
162
163 fn get_background_color(&self) -> Color {
164 self.background_color
165 }
166
167 fn get_text_color(&self) -> Color {
168 self.text_color
169 }
170
171 fn get_hover_background_color(&self) -> Color {
172 self.hover_background_color
173 }
174
175 fn get_hover_text_color(&self) -> Color {
176 self.hover_text_color
177 }
178
179 fn get_opacity(&self) -> f32 {
180 self.opacity
181 }
182
183 fn get_is_hovered(&self) -> bool {
184 self.is_hovered
185 }
186
187 fn get_is_pressed(&self) -> bool {
188 self.is_pressed
189 }
190
191 fn draw(&self, renderer: &mut Renderer, screen_width: f32, screen_height: f32) {
192 let current_background =
193 (if self.is_hovered { self.hover_background_color } else { self.background_color }) *
194 self.opacity;
195
196 let current_text =
197 (if self.is_hovered { self.hover_text_color } else { self.text_color }) * self.opacity;
198
199 renderer.draw_rect(self.x, self.y, self.width, self.height, current_background.to_array());
200
201 renderer
202 .text_renderer_mut()
203 .render_text(
204 &self.text,
205 self.x + 10.0,
206 self.y + 5.0,
207 self.font_size,
208 screen_width,
209 screen_height,
210 current_text.to_array()
211 );
212 }
213
214 fn set_size(&mut self, width: f32, height: f32) {
215 self.width = width;
216 self.height = height;
217 }
218
219 fn position(&self) -> (f32, f32) {
220 (self.x, self.y)
221 }
222
223 fn size(&self) -> (f32, f32) {
224 (self.width, self.height)
225 }
226
227 fn set_position(&mut self, x: f32, y: f32) {
228 self.x = x;
229 self.y = y;
230 }
231
232 fn on_mouse_press(&mut self, x: f32, y: f32) -> bool {
233 if self.contains_point(x, y) {
234 self.is_pressed = true;
235 true
236 } else {
237 false
238 }
239 }
240
241 fn on_mouse_release(&mut self, x: f32, y: f32) -> bool {
242 if self.is_pressed {
243 self.is_pressed = false;
244 if self.contains_point(x, y) {
245 if let Some(callback) = &self.on_click {
246 callback.borrow_mut()();
247 }
248 return true;
249 }
250 }
251 false
252 }
253
254 fn set_on_click<F>(&mut self, callback: F) where F: FnMut() + 'static {
255 self.on_click = Some(Arc::new(RefCell::new(callback)));
256 }
257
258 fn set_on_hover<F>(&mut self, callback: F) where F: FnMut(bool) + 'static {
259 self.on_hover = Some(Arc::new(RefCell::new(callback)));
260 }
261
262 fn set_position_animation(&mut self, animation: Vec2Animation) {
263 self.position_animation = Some(animation);
264 }
265
266 fn animate_fade(&mut self, start: f32, end: f32, duration: f32) {
267 self.set_fade_animation(FadeAnimation::new(start, end, duration));
268 }
269
270 fn set_fade_animation(&mut self, animation: FadeAnimation) {
271 self.fade_animation = Some(animation);
272 }
273
274 fn update_animations(&mut self, delta_time: f32) {
275 if let Some(ref mut anim) = self.position_animation {
276 anim.update(delta_time);
277 let pos = anim.value();
278 self.x = pos.x;
279 self.y = pos.y;
280
281 if anim.is_finished() {
282 self.position_animation = None;
283 }
284 }
285
286 if let Some(ref mut anim) = self.fade_animation {
287 anim.update(delta_time);
288 self.opacity = anim.value();
289
290 if anim.is_finished() {
291 self.fade_animation = None;
292 }
293 }
294 }
295}