use std::collections::BTreeMap;
use std::time::Duration;
use serde::{Deserialize, Serialize};
use super::action::Action;
use super::defaults::default_gesture_binding;
use super::gesture::GestureDirection;
pub const LONG_PRESS_THRESHOLD: Duration = Duration::from_millis(500);
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct LongPressBinding {
short: Action,
long: Action,
}
impl LongPressBinding {
#[must_use]
pub const fn new(short: Action, long: Action) -> Self {
Self { short, long }
}
#[must_use]
pub const fn short(&self) -> &Action {
&self.short
}
#[must_use]
pub const fn long(&self) -> &Action {
&self.long
}
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(untagged)]
pub enum Binding {
Single(Action),
Gesture(BTreeMap<GestureDirection, Action>),
LongPress(LongPressBinding),
}
impl Binding {
#[must_use]
pub fn click_action(&self) -> Action {
match self {
Binding::Single(action) => action.clone(),
Binding::Gesture(map) => map
.get(&GestureDirection::Click)
.cloned()
.unwrap_or(Action::None),
Binding::LongPress(binding) => binding.short().clone(),
}
}
#[must_use]
pub fn direction_action(&self, direction: GestureDirection) -> Option<&Action> {
match self {
Binding::Single(_) | Binding::LongPress(_) => None,
Binding::Gesture(map) => map.get(&direction),
}
}
#[must_use]
pub fn is_gesture(&self) -> bool {
matches!(self, Binding::Gesture(_))
}
pub fn upgrade_to_gesture(&mut self) {
let click = match self {
Binding::Single(action) => action.clone(),
Binding::LongPress(binding) => binding.short().clone(),
Binding::Gesture(_) => return,
};
*self = Binding::Gesture(BTreeMap::from([(GestureDirection::Click, click)]));
}
pub fn demote_to_single(&mut self, fallback: Action) {
if let Binding::Gesture(map) = self {
let click = map
.get(&GestureDirection::Click)
.cloned()
.unwrap_or(fallback);
*self = Binding::Single(click);
}
}
pub fn fill_gesture_defaults(&mut self) {
if let Binding::Gesture(map) = self {
for dir in GestureDirection::ALL {
map.entry(dir)
.or_insert_with(|| default_gesture_binding(dir));
}
}
}
}
impl From<Action> for Binding {
fn from(action: Action) -> Self {
Binding::Single(action)
}
}