pg_sdl/widgets/
button.rs

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
15/// A button is a widget that it can be clicked.
16pub 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}