use crate::Event;
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
pub struct Modifiers {
pub ctrl: bool,
pub alt: bool,
pub shift: bool,
pub logo: bool,
}
#[derive(Debug, Clone)]
pub struct Keyboard<Key, Mods>
where
Key: Copy + PartialEq,
Mods: Copy + Default,
{
modifiers: Mods,
keys_down: Vec<Key>,
keys_pressed: Vec<Key>,
keys_released: Vec<Key>,
text_buffer: String,
}
impl<Key, Mods> Default for Keyboard<Key, Mods>
where
Key: Copy + PartialEq,
Mods: Copy + Default,
{
fn default() -> Self {
Keyboard {
modifiers: Default::default(),
keys_down: Vec::with_capacity(4),
keys_pressed: Vec::with_capacity(4),
keys_released: Vec::with_capacity(4),
text_buffer: String::with_capacity(16),
}
}
}
impl<Key, Mods> Keyboard<Key, Mods>
where
Key: Copy + PartialEq,
Mods: Copy + Default,
{
pub fn new() -> Self {
Default::default()
}
pub fn modifiers(&self) -> Mods {
self.modifiers
}
pub fn down(&self, key: Key) -> bool {
self.keys_down.iter().any(|&k| k == key)
}
pub fn pressed(&self, key: Key) -> bool {
self.keys_pressed.iter().any(|&k| k == key)
}
pub fn released(&self, key: Key) -> bool {
self.keys_released.iter().any(|&k| k == key)
}
pub fn text(&self) -> &str {
&self.text_buffer
}
pub fn clear_presses(&mut self) -> &mut Self {
self.keys_pressed.clear();
self.keys_released.clear();
self.text_buffer.clear();
self
}
pub fn press(&mut self, key: Key) -> &mut Self {
if !self.down(key) {
self.keys_down.push(key);
}
if !self.pressed(key) {
self.keys_pressed.push(key);
}
self
}
pub fn release(&mut self, key: Key) -> &mut Self {
self.keys_down.retain(|&k| k != key);
if !self.released(key) {
self.keys_released.push(key);
}
self
}
pub fn set_modifiers(&mut self, modifiers: Mods) -> &mut Self {
self.modifiers = modifiers;
self
}
pub fn receive_text(&mut self, text: &str) -> &mut Self {
self.text_buffer.push_str(text);
self
}
pub fn receive_char(&mut self, ch: char) -> &mut Self {
self.text_buffer.push(ch);
self
}
pub fn handle_event<E: Event<Self>>(&mut self, event: &E) -> &mut Self {
event.handle(self);
self
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn key_not_pressed_or_released_by_default() {
let keyboard: Keyboard<usize, Modifiers> = Keyboard::new();
assert!(!keyboard.down(10));
assert!(!keyboard.pressed(10));
assert!(!keyboard.released(10));
}
#[test]
fn key_down_when_pressed() {
let mut keyboard: Keyboard<usize, Modifiers> = Keyboard::new();
keyboard.press(10);
assert!(keyboard.down(10));
}
#[test]
fn key_not_down_when_released() {
let mut keyboard: Keyboard<usize, Modifiers> = Keyboard::new();
keyboard.press(10).release(10);
assert!(!keyboard.down(10));
}
#[test]
fn key_pressed_after_pressing() {
let mut keyboard: Keyboard<usize, Modifiers> = Keyboard::new();
keyboard.press(10);
assert!(keyboard.pressed(10));
}
#[test]
fn key_released_after_releasing() {
let mut keyboard: Keyboard<usize, Modifiers> = Keyboard::new();
keyboard.release(10);
assert!(keyboard.released(10));
}
#[test]
fn key_can_be_pressed_and_released_on_same_frame() {
let mut keyboard: Keyboard<usize, Modifiers> = Keyboard::new();
keyboard.press(10).release(10);
assert!(keyboard.pressed(10));
assert!(keyboard.released(10));
}
#[test]
fn key_pressed_resets_at_start_of_frame() {
let mut keyboard: Keyboard<usize, Modifiers> = Keyboard::new();
keyboard.press(10);
keyboard.clear_presses();
assert!(!keyboard.pressed(10));
}
#[test]
fn key_released_resets_at_start_of_frame() {
let mut keyboard: Keyboard<usize, Modifiers> = Keyboard::new();
keyboard.release(10);
keyboard.clear_presses();
assert!(!keyboard.pressed(10));
}
#[test]
fn key_down_persists_across_frames() {
let mut keyboard: Keyboard<usize, Modifiers> = Keyboard::new();
keyboard.press(10);
keyboard.clear_presses();
assert!(keyboard.down(10));
}
#[test]
fn modifiers_empty_by_default() {
let keyboard: Keyboard<usize, Modifiers> = Keyboard::new();
assert_eq!(keyboard.modifiers(), Modifiers::default());
}
#[test]
fn can_set_modifiers() {
let mut keyboard: Keyboard<usize, Modifiers> = Keyboard::new();
keyboard.set_modifiers(Modifiers {
ctrl: true,
alt: true,
shift: true,
logo: true,
});
assert_eq!(
keyboard.modifiers(),
Modifiers {
ctrl: true,
alt: true,
shift: true,
logo: true,
}
)
}
#[test]
fn modifiers_persisit_over_frames() {
let mut keyboard: Keyboard<usize, Modifiers> = Keyboard::new();
keyboard.set_modifiers(Modifiers {
ctrl: true,
alt: true,
shift: true,
logo: true,
});
keyboard.clear_presses();
assert_eq!(
keyboard.modifiers(),
Modifiers {
ctrl: true,
alt: true,
shift: true,
logo: true,
}
)
}
}