use sfml::{ graphics::{Color, Drawable, Font, RectangleShape, Shape, Text, Transformable}, system::Vector2f, }; use crate::{button::Button, constants::{button::{FONT_SIZE_BIG, FONT_SIZE_SMALL, RADIUS_BIG, RADIUS_SMALL}, common::WINDOW_SIZE_F, counter::{DEFAULT_BG_COLOR, DEFAULT_OUTLINE_COLOR, DEFAULT_OUTLINE_THICKNESS, FONT_SIZE, HOFFSET_PERC, SIZE, VOFFSET_PERC}}}; 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(SIZE); background.set_fill_color(DEFAULT_BG_COLOR); background.set_outline_color(DEFAULT_OUTLINE_COLOR); background.set_outline_thickness(DEFAULT_OUTLINE_THICKNESS); background.set_position((WINDOW_SIZE_F.0/2., WINDOW_SIZE_F.1/2.)); 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, FONT_SIZE); count_str.set_fill_color(Color::BLACK); count_str.set_position((WINDOW_SIZE_F.0/2., WINDOW_SIZE_F.1/2.)); 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, FONT_SIZE_BIG, Vector2f::new( background.position().x - HOFFSET_PERC*background.size().x, background.position().y, ), RADIUS_BIG ); let inc_button = Button::new( "+".to_string(), font, FONT_SIZE_BIG, Vector2f::new( background.position().x + HOFFSET_PERC*background.size().x, background.position().y, ), RADIUS_BIG ); let reset_button = Button::new( "R".to_string(), font, FONT_SIZE_SMALL, Vector2f::new( background.position().x, background.position().y + (1. - VOFFSET_PERC)*background.size().y/2. ), RADIUS_SMALL ); Counter { count, count_str, background, dec_button, inc_button, reset_button, } } pub fn inc(&mut self) { if self.count < u32::MAX { self.count += 1; } self.update(); } pub fn dec(&mut self) { if self.count > 0 { self.count -= 1; } self.update(); } pub fn reset(&mut self) { self.count = 0; 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, m_pos: impl Into) { let m_pos = m_pos.into(); if self.dec_button.contains(m_pos) { self.dec(); } if self.inc_button.contains(m_pos) { self.inc(); } if self.reset_button.contains(m_pos) { self.reset(); } } } 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); self.reset_button.draw(target, states); } }