multi-counter/src/counter.rs
2025-09-28 23:43:29 +02:00

124 lines
3.6 KiB
Rust

use sfml::{
graphics::{Color, Drawable, Font, RectangleShape, Shape, Text, Transformable},
system::Vector2f,
};
use crate::button::Button;
pub struct Counter<'a> {
count: u32,
count_str: Text<'a>,
background: RectangleShape<'a>,
dec_button: Button<'a>,
inc_button: Button<'a>,
reset_button: Button<'a>,
}
impl<'a> Counter<'a> {
pub fn new(count: u32, font: &'a Font) -> Self {
let mut background = RectangleShape::with_size(Vector2f::new(200., 70.));
background.set_fill_color(Color::YELLOW);
background.set_outline_color(Color::BLUE);
background.set_outline_thickness(10.);
background.set_position((400., 300.));
let bounds = background.local_bounds();
background.set_origin((
bounds.left + bounds.width / 2.,
bounds.top + bounds.height / 2.,
));
let mut count_str = Text::new(&count.to_string(), font, 32);
count_str.set_fill_color(Color::BLACK);
count_str.set_position((400., 300.));
let bounds = count_str.local_bounds();
count_str.set_origin((
bounds.left + bounds.width / 2.,
bounds.top + bounds.height / 2.,
));
let dec_button = Button::new(
"-".to_string(),
font,
Vector2f::new(
background.position().x - 70.,
background.position().y,
),
Box::new(|count| if count == 0 { 0 } else { count - 1 }),
);
let inc_button = Button::new(
"+".to_string(),
font,
Vector2f::new(
background.position().x + 70.,
background.position().y,
),
Box::new(|count| if count == u32::MAX { 0 } else { count + 1 }),
);
let reset_button = Button::new(
"R".to_string(),
font,
Vector2f::new(0., 0.),
Box::new(|_count| 0),
);
Counter {
count,
count_str,
background,
dec_button,
inc_button,
reset_button,
}
}
pub fn inc(&mut self) {
self.count = (self.inc_button.exec)(self.count);
self.update();
}
pub fn dec(&mut self) {
self.count = (self.dec_button.exec)(self.count);
self.update();
}
pub fn reset(&mut self) {
self.count = (self.reset_button.exec)(self.count);
self.update();
}
fn update(&mut self) {
self.count_str.set_string(&self.count.to_string());
let digits = self.count.checked_ilog10().unwrap_or(0);
if self.count % (10 * if digits == 0 { 1 } else { digits }) == 0 {
let bounds = self.count_str.local_bounds();
self.count_str.set_origin((
bounds.left + bounds.width / 2.,
bounds.top + bounds.height / 2.,
));
}
}
pub fn handle_mouse(&mut self, x: i32, y: i32) {
if self.dec_button.contains(x, y) {
self.dec();
}
if self.inc_button.contains(x, y) {
self.inc();
}
}
}
impl<'d> Drawable for Counter<'d> {
fn draw<'a: 'shader, 'texture, 'shader, 'shader_texture>(
&'a self,
target: &mut dyn sfml::graphics::RenderTarget,
states: &sfml::graphics::RenderStates<'texture, 'shader, 'shader_texture>,
) {
self.background.draw(target, states);
self.count_str.draw(target, states);
self.dec_button.draw(target, states);
self.inc_button.draw(target, states);
}
}