add a simple counter
This commit is contained in:
parent
cabacd32e2
commit
b2b8a6e0d2
4 changed files with 208 additions and 2 deletions
BIN
res/font.ttf
Normal file
BIN
res/font.ttf
Normal file
Binary file not shown.
47
src/button.rs
Normal file
47
src/button.rs
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
use sfml::{graphics::{CircleShape, Color, Drawable, Font, Shape, Text, Transformable}, system::Vector2f};
|
||||||
|
|
||||||
|
pub struct Button<'a> {
|
||||||
|
background: CircleShape<'a>,
|
||||||
|
text: Text<'a>,
|
||||||
|
pub exec: Box<dyn Fn(u32) -> u32>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Button<'a> {
|
||||||
|
pub fn new(text: String, font: &'a Font, pos: Vector2f, exec: Box<dyn Fn(u32) -> u32>) -> Self {
|
||||||
|
let mut background = CircleShape::new(20., 20);
|
||||||
|
background.set_origin((20., 20.));
|
||||||
|
background.set_position(pos);
|
||||||
|
background.set_fill_color(Color::GREEN);
|
||||||
|
|
||||||
|
let mut text = Text::new(&text, font, 32);
|
||||||
|
text.set_position(background.position());
|
||||||
|
text.set_fill_color(Color::BLACK);
|
||||||
|
let bounds = text.local_bounds();
|
||||||
|
text.set_origin((
|
||||||
|
bounds.left + bounds.width / 2.,
|
||||||
|
bounds.top + bounds.height / 2.,
|
||||||
|
));
|
||||||
|
|
||||||
|
Button {
|
||||||
|
background,
|
||||||
|
text,
|
||||||
|
exec
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn contains(&self, x: i32, y: i32) -> bool {
|
||||||
|
self.background.global_bounds().contains(Vector2f::new(x as f32, y as f32))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'d> Drawable for Button<'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.text.draw(target, states);
|
||||||
|
}
|
||||||
|
}
|
||||||
124
src/counter.rs
Normal file
124
src/counter.rs
Normal file
|
|
@ -0,0 +1,124 @@
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
39
src/main.rs
39
src/main.rs
|
|
@ -1,3 +1,38 @@
|
||||||
fn main() {
|
use sfml::{graphics::{Color, Font, RenderTarget, RenderWindow}, window::{mouse, Event, Key, Style}, SfResult};
|
||||||
println!("Hello, world!");
|
|
||||||
|
mod counter;
|
||||||
|
use counter::Counter;
|
||||||
|
|
||||||
|
mod button;
|
||||||
|
|
||||||
|
fn main() -> SfResult<()>{
|
||||||
|
let font = Font::from_file("res/font.ttf").unwrap();
|
||||||
|
let mut c1 = Counter::new(0, &font);
|
||||||
|
|
||||||
|
let mut window = RenderWindow::new((800, 600), "Multi Counter", Style::CLOSE, &Default::default())?;
|
||||||
|
window.set_framerate_limit(60);
|
||||||
|
|
||||||
|
while window.is_open() {
|
||||||
|
while let Some(event) = window.poll_event() {
|
||||||
|
match event {
|
||||||
|
Event::Closed => window.close(),
|
||||||
|
Event::KeyPressed { code, .. } => match code {
|
||||||
|
Key::Left => c1.dec(),
|
||||||
|
Key::Right => c1.inc(),
|
||||||
|
Key::Space => c1.reset(),
|
||||||
|
_ => {}
|
||||||
|
},
|
||||||
|
Event::MouseButtonPressed { button, x, y } => if button == mouse::Button::Left {
|
||||||
|
c1.handle_mouse(x, y);
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
window.clear(Color::BLACK);
|
||||||
|
window.draw(&c1);
|
||||||
|
window.display();
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue