pub use truce_gui_types::interaction::*;
#[cfg(not(target_os = "ios"))]
const DOUBLE_CLICK_MS: u128 = 300;
#[cfg(not(target_os = "ios"))]
const DOUBLE_CLICK_SLOP: f32 = 4.0;
#[cfg(not(target_os = "ios"))]
const WHEEL_LINE_PX: f32 = 20.0;
#[cfg(not(target_os = "ios"))]
#[cfg(not(target_os = "ios"))]
#[allow(clippy::struct_field_names)]
#[derive(Default)]
pub struct BaseviewTranslator {
last_cursor: (f32, f32),
last_click_time: Option<std::time::Instant>,
last_click_pos: (f32, f32),
}
#[cfg(not(target_os = "ios"))]
impl BaseviewTranslator {
#[must_use]
pub fn last_cursor(&self) -> (f32, f32) {
self.last_cursor
}
pub fn translate(&mut self, event: &baseview::Event) -> Option<InputEvent> {
let baseview::Event::Mouse(m) = event else {
return None;
};
match m {
baseview::MouseEvent::CursorMoved { position, .. } => {
#[allow(clippy::cast_possible_truncation)]
let x = position.x as f32;
#[allow(clippy::cast_possible_truncation)]
let y = position.y as f32;
self.last_cursor = (x, y);
Some(InputEvent::MouseMove {
pointer_id: truce_gui_types::interaction::SINGLE_POINTER,
x,
y,
})
}
baseview::MouseEvent::ButtonPressed { button, .. } => {
let mb = map_button(*button)?;
let (x, y) = self.last_cursor;
if mb == MouseButton::Left {
let now = std::time::Instant::now();
let is_double = self.last_click_time.is_some_and(|t| {
now.duration_since(t).as_millis() < DOUBLE_CLICK_MS
&& (x - self.last_click_pos.0).abs() < DOUBLE_CLICK_SLOP
&& (y - self.last_click_pos.1).abs() < DOUBLE_CLICK_SLOP
});
self.last_click_time = Some(now);
self.last_click_pos = (x, y);
if is_double {
self.last_click_time = None;
return Some(InputEvent::MouseDoubleClick { x, y });
}
}
Some(InputEvent::MouseDown {
pointer_id: truce_gui_types::interaction::SINGLE_POINTER,
x,
y,
button: mb,
})
}
baseview::MouseEvent::ButtonReleased { button, .. } => {
let mb = map_button(*button)?;
let (x, y) = self.last_cursor;
Some(InputEvent::MouseUp {
pointer_id: truce_gui_types::interaction::SINGLE_POINTER,
x,
y,
button: mb,
})
}
baseview::MouseEvent::WheelScrolled { delta, .. } => {
let dy = match delta {
baseview::ScrollDelta::Lines { y, .. } => y * WHEEL_LINE_PX,
baseview::ScrollDelta::Pixels { y, .. } => *y,
};
let (x, y) = self.last_cursor;
Some(InputEvent::Scroll { x, y, dy })
}
baseview::MouseEvent::CursorLeft => Some(InputEvent::MouseLeave),
_ => None,
}
}
}
#[cfg(not(target_os = "ios"))]
fn map_button(b: baseview::MouseButton) -> Option<MouseButton> {
match b {
baseview::MouseButton::Left => Some(MouseButton::Left),
baseview::MouseButton::Right => Some(MouseButton::Right),
baseview::MouseButton::Middle => Some(MouseButton::Middle),
_ => None,
}
}