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); } }