1use crate::prelude::*;
2use crate::{
3 color::{darker, Colors},
4 input::{Input, KeyState},
5 text::TextDrawer,
6 widgets::Widget,
7 widgets::{HOVER, PUSH},
8};
9use sdl2::gfx::primitives::DrawRenderer;
10use sdl2::pixels::Color;
11use sdl2::rect::Rect;
12use sdl2::render::Canvas;
13use sdl2::video::Window;
14
15pub struct Button {
17 color: Color,
18 hovered_color: Color,
19 pushed_color: Color,
20 rect: Rect,
21 corner_radius: Option<u32>,
22 text: Option<Text>,
23 hovered: bool,
24 pub state: KeyState,
25}
26
27impl Button {
28 pub fn new(color: Color, rect: Rect, corner_radius: Option<u32>, text: Option<Text>) -> Self {
29 Self {
30 color,
31 hovered_color: darker(color, HOVER),
32 pushed_color: darker(color, PUSH),
33 rect,
34 corner_radius,
35 text,
36 hovered: false,
37 state: KeyState::new(),
38 }
39 }
40 pub fn set_text(&mut self, new_text: String) {
41 if let Some(text) = &mut self.text {
42 text.text = new_text;
43 } else {
44 panic!("Button has no text")
45 }
46 }
47}
48
49impl Widget for Button {
50 fn update(&mut self, input: &Input, _delta: f32) -> bool {
51 let mut changed = false;
52 self.state.update();
53
54 let hovered = self.rect.contains_point(input.mouse.position);
55 if hovered != self.hovered {
56 self.hovered = hovered;
57 changed = true;
58 }
59
60 if input.mouse.left_button.is_pressed() && self.hovered {
61 self.state.press();
62 changed = true;
63 } else if self.state.is_down() && input.mouse.left_button.is_released() {
64 self.state.release();
65 changed = true;
66 }
67
68 changed
69 }
70
71 fn draw(&self, canvas: &mut Canvas<Window>, text_drawer: &mut TextDrawer) {
72 let color = if self.state.is_pressed() | self.state.is_down() {
73 self.pushed_color
74 } else if self.hovered {
75 self.hovered_color
76 } else {
77 self.color
78 };
79
80 if let Some(radius) = self.corner_radius {
81 DrawRenderer::rounded_box(
82 canvas,
83 self.rect.left() as i16,
84 self.rect.top() as i16,
85 self.rect.right() as i16,
86 self.rect.bottom() as i16,
87 radius as i16,
88 color,
89 )
90 .expect("DrawRenderer failed");
91 DrawRenderer::rounded_rectangle(
92 canvas,
93 self.rect.left() as i16,
94 self.rect.top() as i16,
95 self.rect.right() as i16,
96 self.rect.bottom() as i16,
97 radius as i16,
98 Colors::BLACK,
99 )
100 .expect("DrawRenderer failed");
101 } else {
102 canvas.set_draw_color(color);
103 canvas.fill_rect(self.rect).unwrap();
104 canvas.set_draw_color(Colors::BLACK);
105 canvas.draw_rect(self.rect).unwrap();
106 }
107
108 if let Some(text) = &self.text {
109 text_drawer.draw(canvas, self.rect.center(), &text);
110 }
111 }
112}