use crate::{ConstInit, EventTimestamp, NonZeroU8, f32bits_niche, unwrap};
#[doc = crate::_tags!(event interaction)]
#[doc = crate::_doc_location!("ui/event")]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct EventMouse {
pub timestamp: Option<EventTimestamp>,
pub x: i32,
pub y: i32,
pub button: Option<EventButton>,
pub state: EventButtonState,
pub buttons: u8,
}
#[doc = crate::_tags!(event interaction)]
#[doc = crate::_doc_location!("ui/event")]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct EventPointer {
pub timestamp: Option<EventTimestamp>,
pub kind: EventPointerType,
pub id: u32,
pub x: i32,
pub y: i32,
pub dx: i32,
pub dy: i32,
pressure: f32bits_niche,
pub tilt_x: i8,
pub tilt_y: i8,
pub twist: u16,
pub button: Option<EventButton>,
pub state: EventButtonState,
}
#[rustfmt::skip]
impl EventPointer {
pub const fn get_pressure(&self) -> f32 { self.pressure.as_float() }
pub const fn set_pressure(&mut self, pressure: f32) {
self.pressure = f32bits_niche::new(pressure);
}
}
#[doc = crate::_tags!(event interaction)]
#[doc = crate::_doc_location!("ui/event")]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum EventPointerType {
Mouse,
Touch,
Pen,
}
#[doc = crate::_tags!(event interaction)]
#[doc = crate::_doc_location!("ui/event")]
#[repr(u8)]
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
pub enum EventButton {
#[default]
Left,
Right,
Middle,
Other(NonZeroU8),
}
impl EventButton {
pub const fn new(number: u8) -> Option<Self> {
match number {
1 => Some(Self::Left),
2 => Some(Self::Middle),
3 => Some(Self::Right),
_ => Some(Self::Other(unwrap![some? NonZeroU8::new(number)])),
}
}
#[inline(always)]
pub const fn primary_from_mask(mask: u8) -> Option<EventButton> {
match mask {
1 => Some(EventButton::Left),
2 => Some(EventButton::Right),
4 => Some(EventButton::Middle),
_ => None,
}
}
}
#[doc = crate::_tags!(event interaction)]
#[doc = crate::_doc_location!("ui/event")]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum EventButtonState {
Pressed,
Released,
Moved,
}
#[doc = crate::_tags!(event interaction)]
#[doc = crate::_doc_location!("ui/event")]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct EventWheel {
pub delta_x: i32,
pub delta_y: i32,
pub x: i32,
pub y: i32,
pub timestamp: Option<EventTimestamp>,
}
#[rustfmt::skip]
mod init {
use super::*;
impl ConstInit for EventMouse {
const INIT: Self = Self {
x: 0, y: 0, button: None, state: EventButtonState::INIT, buttons: 0, timestamp: None,
};
}
impl ConstInit for EventPointer {
const INIT: Self = Self {
kind: EventPointerType::INIT, id: 0, x: 0, y: 0, dx: 0, dy: 0,
pressure: f32bits_niche::INIT, tilt_x: 0, tilt_y: 0, twist: 0, button: None,
state: EventButtonState::INIT, timestamp: None,
};
}
impl ConstInit for EventPointerType { const INIT: Self = Self::Mouse; }
impl ConstInit for EventButton { const INIT: Self = Self::Left; }
impl ConstInit for EventButtonState { const INIT: Self = Self::Pressed; }
impl ConstInit for EventWheel {
const INIT: Self = Self { delta_x: 0, delta_y: 0, x: 0, y: 0, timestamp: None };
}
}
#[rustfmt::skip]
#[cfg(all(feature = "js", not(windows)))]
mod impl_js {
use super::*;
use crate::{is, js_number, WebEventKind, WebEventMouse, JsInstant};
impl EventMouse {
pub const fn from_js(js: WebEventMouse) -> EventMouse {
EventMouse {
x: js.x as i32,
y: js.y as i32,
button: EventButton::from_js(js.button),
state: EventButtonState::from_js(js.etype),
buttons: js.buttons,
timestamp: Some(EventTimestamp::from_js(js.timestamp)),
}
}
}
impl EventMouse {
pub const fn to_js(self) -> WebEventMouse {
WebEventMouse {
x: self.x as js_number,
y: self.y as js_number,
button: is![let Some(b) = self.button, b.to_js(), 255], buttons: self.buttons, etype: self.state.to_js_as_mouse(),
timestamp: is![let Some(t) = self.timestamp, t.to_js(), JsInstant { ms: 0.0 }],
}
}
}
impl From<WebEventMouse> for EventMouse {
fn from(from: WebEventMouse) -> Self { Self::from_js(from) }
}
impl From<EventMouse> for WebEventMouse {
fn from(from: EventMouse) -> Self { from.to_js() }
}
impl EventButton {
pub const fn from_js(js_button: u8) -> Option<Self> {
match js_button {
0 => Some(EventButton::Left),
1 => Some(EventButton::Middle),
2 => Some(EventButton::Right),
255 => None, n => Some(EventButton::Other(NonZeroU8::new(n).unwrap())),
}
}
pub const fn to_js(self) -> u8 {
match self {
EventButton::Left => 0,
EventButton::Right => 1,
EventButton::Middle => 2,
EventButton::Other(n) => n.get(),
}
}
}
impl EventButtonState {
pub const fn from_js(js_event: WebEventKind) -> Self {
use {WebEventKind as J, EventButtonState as E};
match js_event {
J::Click | J::MouseDown | J::PointerDown => E::Pressed,
J::MouseUp | J::PointerUp => E::Released,
_ => E::Moved,
}
}
pub const fn to_js_as_mouse(self) -> WebEventKind {
use {WebEventKind as J, EventButtonState as E};
match self {
E::Pressed => J::MouseDown,
E::Released => J::MouseUp,
E::Moved => J::MouseMove,
}
}
pub const fn to_js_as_pointer(self) -> WebEventKind {
use {WebEventKind as J, EventButtonState as E};
match self {
E::Pressed => J::PointerDown,
E::Released => J::PointerUp,
E::Moved => J::PointerMove,
}
}
}
}