Skip to main content

base_ui/widget/widgets/
button.rs

1use crate::animation::animation::{ Animation, Vec2Animation, FadeAnimation };
2use crate::widget::Widget;
3use crate::graphics::Renderer;
4use crate::style::color::Color;
5use log::{ debug, info };
6use std::sync::Arc;
7use std::cell::RefCell;
8
9pub struct Button {
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    border_color: Color,
19    border_width: f32, // 외곽선 두께
20    padding: f32, // 텍스트와 버튼 경계 사이의 여백
21    is_pressed: bool,
22    on_click: Option<Arc<RefCell<dyn FnMut() + 'static>>>,
23    pressed_background_color: Color,
24    pressed_border_color: Color,
25    pressed_text_color: Color,
26    is_hovered: bool,
27    hover_background_color: Color,
28    hover_border_color: Color,
29    hover_text_color: Color,
30    on_hover: Option<Arc<RefCell<dyn FnMut(bool) + 'static>>>,
31    position_animation: Option<Vec2Animation>,
32    fade_animation: Option<FadeAnimation>,
33    opacity: f32,
34}
35
36impl Button {
37    pub fn new(text: &str, renderer: &Renderer) -> Self {
38        debug!("Creating new Button with text: '{}'", text);
39        let background_color = Color::new(0.7, 0.7, 0.7, 1.0);
40        let border_color = Color::new(0.3, 0.3, 0.3, 1.0);
41        let text_color = Color::new(0.0, 0.0, 0.0, 1.0);
42
43        let mut btn = Self {
44            x: 0.0,
45            y: 0.0,
46            width: 0.0,
47            height: 0.0,
48            text: text.to_string(),
49            font_size: 32.0,
50            background_color,
51            text_color,
52            border_color,
53            border_width: 2.0, // 기본 테두리 두께
54            padding: 10.0, // 기본 패딩
55            is_pressed: false,
56            on_click: None,
57            pressed_background_color: Color::new(0.6, 0.6, 0.6, 1.0),
58            pressed_border_color: Color::new(0.2, 0.2, 0.2, 1.0),
59            pressed_text_color: Color::new(0.0, 0.0, 0.0, 1.0),
60            is_hovered: false,
61            hover_background_color: Color::new(0.8, 0.8, 0.8, 1.0),
62            hover_border_color: Color::new(0.4, 0.4, 0.4, 1.0),
63            hover_text_color: Color::new(0.0, 0.0, 0.0, 1.0),
64            on_hover: None,
65            position_animation: None,
66            fade_animation: None,
67            opacity: 1.0,
68        };
69        btn.update_size(renderer);
70        info!("Button created with size: {}x{}", btn.width, btn.height);
71        btn
72    }
73
74    fn update_size(&mut self, renderer: &Renderer) {
75        let (text_width, text_height) = renderer
76            .text_renderer()
77            .font_renderer()
78            .calculate_text_size(&self.text, self.font_size);
79
80        // 텍스트 크기에 패딩을 추가하여 버튼 크기 설정
81        self.width = text_width + self.padding * 2.0;
82        self.height = text_height + self.padding * 2.0;
83        debug!("Button size updated: {}x{}", self.width, self.height);
84    }
85
86    pub fn set_text(&mut self, text: &str, renderer: &Renderer) {
87        debug!("Button text changing from '{}' to '{}'", self.text, text);
88        self.text = text.to_string();
89        self.update_size(renderer);
90    }
91
92    pub fn set_font_size(&mut self, size: f32, renderer: &Renderer) {
93        debug!("Button font size changing from {} to {}", self.font_size, size);
94        self.font_size = size;
95        self.update_size(renderer);
96    }
97
98    pub fn set_background_color(&mut self, color: Color) {
99        self.background_color = color;
100    }
101
102    pub fn set_text_color(&mut self, color: Color) {
103        self.text_color = color;
104    }
105
106    pub fn set_border_color(&mut self, color: Color) {
107        self.border_color = color;
108    }
109
110    pub fn set_border_width(&mut self, width: f32) {
111        self.border_width = width;
112    }
113
114    pub fn set_padding(&mut self, padding: f32, renderer: &Renderer) {
115        self.padding = padding;
116        self.update_size(renderer);
117    }
118
119    // 클릭 이벤트 핸들러 설정
120    pub fn set_on_click<F>(&mut self, callback: F) where F: FnMut() + 'static {
121        self.on_click = Some(Arc::new(RefCell::new(callback)));
122    }
123
124    // pressed 상태의 배경색 설정
125    pub fn set_pressed_background_color(&mut self, color: Color) {
126        self.pressed_background_color = color;
127    }
128
129    // pressed 상태의 테두리 색상 설정
130    pub fn set_pressed_border_color(&mut self, color: Color) {
131        self.pressed_border_color = color;
132    }
133
134    // pressed 상태의 텍스트 색상 설정
135    pub fn set_pressed_text_color(&mut self, color: Color) {
136        self.pressed_text_color = color;
137    }
138
139    // hover 상태의 배경색 설정
140    pub fn set_hover_background_color(&mut self, color: Color) {
141        self.hover_background_color = color;
142    }
143
144    // hover 상태의 테두리 색상 설정
145    pub fn set_hover_border_color(&mut self, color: Color) {
146        self.hover_border_color = color;
147    }
148
149    // hover 상태의 텍스트 색상 설정
150    pub fn set_hover_text_color(&mut self, color: Color) {
151        self.hover_text_color = color;
152    }
153
154    // hover 이벤트 핸들러 설정
155    pub fn set_on_hover<F>(&mut self, callback: F) where F: FnMut(bool) + 'static {
156        self.on_hover = Some(Arc::new(RefCell::new(callback)));
157    }
158
159    // hover 상태 업데이트
160    pub fn update_hover(&mut self, x: f32, y: f32) {
161        let was_hovered = self.is_hovered;
162        self.is_hovered = self.contains_point(x, y);
163
164        // hover 상태가 변경되었을 때만 콜백 호출
165        if was_hovered != self.is_hovered {
166            if let Some(callback) = &self.on_hover {
167                callback.borrow_mut()(self.is_hovered);
168            }
169        }
170    }
171
172    pub fn has_fade_animation(&self) -> bool {
173        self.fade_animation.is_some()
174    }
175}
176
177impl Widget for Button {
178    fn get_position(&self) -> (f32, f32) {
179        (self.x, self.y)
180    }
181
182    fn get_size(&self) -> (f32, f32) {
183        (self.width, self.height)
184    }
185
186    fn get_background_color(&self) -> Color {
187        self.background_color
188    }
189
190    fn get_text_color(&self) -> Color {
191        self.text_color
192    }
193
194    fn get_hover_background_color(&self) -> Color {
195        self.hover_background_color
196    }
197
198    fn get_hover_text_color(&self) -> Color {
199        self.hover_text_color
200    }
201
202    fn get_opacity(&self) -> f32 {
203        self.opacity
204    }
205
206    fn get_is_hovered(&self) -> bool {
207        self.is_hovered
208    }
209
210    fn get_is_pressed(&self) -> bool {
211        self.is_pressed
212    }
213
214    fn draw(&self, renderer: &mut Renderer, screen_width: f32, screen_height: f32) {
215        let (bg, border, text) = if self.is_pressed {
216            (self.pressed_background_color, self.pressed_border_color, self.pressed_text_color)
217        } else if self.is_hovered {
218            (self.hover_background_color, self.hover_border_color, self.hover_text_color)
219        } else {
220            (self.background_color, self.border_color, self.text_color)
221        };
222
223        let current_background = bg * self.opacity;
224        let current_border = border * self.opacity;
225        let current_text = text * self.opacity;
226
227        // 렌더링...
228        if self.border_width > 0.0 {
229            renderer.draw_rect(
230                self.x - self.border_width,
231                self.y - self.border_width,
232                self.width + self.border_width * 2.0,
233                self.height + self.border_width * 2.0,
234                current_border.to_array()
235            );
236        }
237
238        renderer.draw_rect(self.x, self.y, self.width, self.height, current_background.to_array());
239
240        // ... 나머지 텍스트 렌더링 코드는 current_text 사용
241        let (text_width, text_height) = renderer
242            .text_renderer()
243            .font_renderer()
244            .calculate_text_size(&self.text, self.font_size);
245
246        let text_x = self.x + (self.width - text_width) / 2.0;
247        let text_y = self.y + (self.height - text_height) / 2.0;
248
249        renderer
250            .text_renderer_mut()
251            .render_text(
252                &self.text,
253                text_x,
254                text_y,
255                self.font_size,
256                screen_width,
257                screen_height,
258                current_text.to_array()
259            );
260    }
261
262    fn set_size(&mut self, width: f32, height: f32) {
263        self.width = width;
264        self.height = height;
265    }
266
267    fn position(&self) -> (f32, f32) {
268        (self.x, self.y)
269    }
270
271    fn size(&self) -> (f32, f32) {
272        (self.width, self.height)
273    }
274
275    fn set_position(&mut self, x: f32, y: f32) {
276        self.x = x;
277        self.y = y;
278    }
279
280    fn on_mouse_press(&mut self, _x: f32, _y: f32) -> bool {
281        if self.contains_point(_x, _y) {
282            self.is_pressed = true;
283            true
284        } else {
285            false
286        }
287    }
288
289    fn on_mouse_release(&mut self, x: f32, y: f32) -> bool {
290        if self.is_pressed {
291            self.is_pressed = false;
292            if self.contains_point(x, y) {
293                // 클릭 이벤트 발생
294                if let Some(callback) = &self.on_click {
295                    callback.borrow_mut()();
296                }
297                return true;
298            }
299        }
300        false
301    }
302
303    fn set_on_click<F>(&mut self, callback: F) where F: FnMut() + 'static {
304        self.on_click = Some(Arc::new(RefCell::new(callback)));
305    }
306
307    fn set_on_hover<F>(&mut self, callback: F) where F: FnMut(bool) + 'static {
308        self.on_hover = Some(Arc::new(RefCell::new(callback)));
309    }
310
311    fn set_position_animation(&mut self, animation: Vec2Animation) {
312        self.position_animation = Some(animation);
313    }
314
315    fn set_fade_animation(&mut self, animation: FadeAnimation) {
316        self.fade_animation = Some(animation);
317    }
318
319    fn update_animations(&mut self, delta_time: f32) {
320        // Update position animation
321        if let Some(ref mut anim) = self.position_animation {
322            anim.update(delta_time);
323            let pos = anim.value();
324            self.x = pos.x;
325            self.y = pos.y;
326
327            if anim.is_finished() {
328                self.position_animation = None;
329            }
330        }
331
332        // Update fade animation
333        if let Some(ref mut anim) = self.fade_animation {
334            anim.update(delta_time);
335            self.opacity = anim.value();
336
337            if anim.is_finished() {
338                self.fade_animation = None;
339            }
340        }
341    }
342}