use std::cell::RefCell;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum MouseButton {
#[default]
None,
Left,
Middle,
Right,
Back,
Forward,
}
impl MouseButton {
pub fn as_str(&self) -> &'static str {
match self {
MouseButton::None => "none",
MouseButton::Left => "left",
MouseButton::Middle => "middle",
MouseButton::Right => "right",
MouseButton::Back => "back",
MouseButton::Forward => "forward",
}
}
}
pub struct Mouse {
x: RefCell<f64>,
y: RefCell<f64>,
button: RefCell<MouseButton>,
pressed_buttons: RefCell<Vec<MouseButton>>,
}
impl std::fmt::Debug for Mouse {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Mouse")
.field("x", &self.x.borrow())
.field("y", &self.y.borrow())
.field("button", &self.button.borrow())
.field("pressed_count", &self.pressed_buttons.borrow().len())
.finish()
}
}
impl Mouse {
pub fn new() -> Self {
Self {
x: RefCell::new(0.0),
y: RefCell::new(0.0),
button: RefCell::new(MouseButton::None),
pressed_buttons: RefCell::new(Vec::new()),
}
}
pub fn current_x(&self) -> f64 {
*self.x.borrow()
}
pub fn current_y(&self) -> f64 {
*self.y.borrow()
}
pub fn current_button(&self) -> MouseButton {
*self.button.borrow()
}
pub fn set_position(&self, x: f64, y: f64) {
*self.x.borrow_mut() = x;
*self.y.borrow_mut() = y;
}
pub fn set_button(&self, b: MouseButton) {
*self.button.borrow_mut() = b;
}
pub fn press_button(&self, b: MouseButton) {
let mut pressed = self.pressed_buttons.borrow_mut();
if !pressed.contains(&b) {
pressed.push(b);
}
}
pub fn release_button(&self, b: MouseButton) {
self.pressed_buttons.borrow_mut().retain(|x| *x != b);
}
pub fn is_button_pressed(&self, b: MouseButton) -> bool {
self.pressed_buttons.borrow().contains(&b)
}
pub fn pressed_button_count(&self) -> usize {
self.pressed_buttons.borrow().len()
}
pub fn reset(&self) {
*self.x.borrow_mut() = 0.0;
*self.y.borrow_mut() = 0.0;
*self.button.borrow_mut() = MouseButton::None;
self.pressed_buttons.borrow_mut().clear();
}
}
impl Default for Mouse {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn new_defaults() {
let m = Mouse::new();
assert_eq!(m.current_x(), 0.0);
assert_eq!(m.current_y(), 0.0);
assert_eq!(m.current_button(), MouseButton::None);
assert_eq!(m.pressed_button_count(), 0);
}
#[test]
fn set_position() {
let m = Mouse::new();
m.set_position(10.0, 20.0);
assert_eq!(m.current_x(), 10.0);
assert_eq!(m.current_y(), 20.0);
}
#[test]
fn set_button() {
let m = Mouse::new();
m.set_button(MouseButton::Right);
assert_eq!(m.current_button(), MouseButton::Right);
}
#[test]
fn press_release_button() {
let m = Mouse::new();
m.press_button(MouseButton::Left);
assert!(m.is_button_pressed(MouseButton::Left));
assert!(!m.is_button_pressed(MouseButton::Right));
m.release_button(MouseButton::Left);
assert!(!m.is_button_pressed(MouseButton::Left));
}
#[test]
fn multi_button_pressed() {
let m = Mouse::new();
m.press_button(MouseButton::Left);
m.press_button(MouseButton::Right);
assert_eq!(m.pressed_button_count(), 2);
}
#[test]
fn duplicate_press_no_dup() {
let m = Mouse::new();
m.press_button(MouseButton::Left);
m.press_button(MouseButton::Left);
assert_eq!(m.pressed_button_count(), 1);
}
#[test]
fn reset_clears_all() {
let m = Mouse::new();
m.set_position(10.0, 20.0);
m.press_button(MouseButton::Left);
m.reset();
assert_eq!(m.current_x(), 0.0);
assert_eq!(m.pressed_button_count(), 0);
}
}