use crate::interaction::{InteractionController, InteractionType};
#[derive(Default)]
pub struct State {
interaction_time: u32,
was_released: bool,
}
#[derive(Clone, Copy)]
pub struct SingleTouch {
ignore_time: u32,
max_time: u32,
interacted_before_release: bool,
}
impl SingleTouch {
pub const fn new(ignore: u32, max: u32) -> Self {
Self {
ignore_time: ignore,
max_time: max,
interacted_before_release: false,
}
}
}
impl InteractionController for SingleTouch {
type Input = bool;
type State = State;
fn reset(&self, state: &mut Self::State) {
state.interaction_time = 0;
}
fn fill_area_width(&self, state: &Self::State, max: u32) -> u32 {
if self.ignore_time <= state.interaction_time && state.interaction_time < self.max_time {
let time = (state.interaction_time - self.ignore_time) as f32
/ ((self.max_time - self.ignore_time) as f32 * 0.9);
((time * (max - 1) as f32) as u32).max(0)
} else {
0
}
}
fn update(&mut self, state: &mut Self::State, action: Self::Input) -> Option<InteractionType> {
if !state.was_released {
if action {
return None;
}
state.was_released = true;
}
if action {
if state.interaction_time < self.max_time {
state.interaction_time = state.interaction_time.saturating_add(1);
None
} else {
state.interaction_time = 0;
self.interacted_before_release = true;
Some(InteractionType::Select)
}
} else {
let time = core::mem::replace(&mut state.interaction_time, 0);
if 0 < time && time < self.max_time && !self.interacted_before_release {
Some(InteractionType::Next)
} else {
self.interacted_before_release = false;
None
}
}
}
}
#[cfg(test)]
mod test {
use crate::interaction::{single_touch::SingleTouch, InteractionController, InteractionType};
#[test]
fn test_interaction() {
let controller = SingleTouch::new(1, 5);
let mut controller_state = <SingleTouch as InteractionController>::State::default();
let expectations: [&[_]; 6] = [
&[(5, false, None)],
&[
(1, true, None),
(1, false, None),
(1, true, None),
(1, false, None),
(1, true, None),
(1, false, None),
],
&[(2, true, None), (1, false, Some(InteractionType::Next))],
&[(3, true, None), (1, false, Some(InteractionType::Next))],
&[(4, true, None), (1, false, Some(InteractionType::Next))],
&[
(4, true, None),
(1, true, Some(InteractionType::Select)),
(10, true, None),
(1, false, None),
],
];
for (row, &inputs) in expectations.iter().enumerate() {
controller.reset(&mut controller_state);
let mut sample = 0;
for (repeat, input, expectation) in inputs.iter() {
for _ in 0..*repeat {
let ret = controller.update(&mut controller_state, *input);
assert_eq!(
ret, *expectation,
"Mismatch at row {}, sample {}",
row, sample
);
sample += 1;
}
}
}
}
}