use crate::*;
use std::collections::{BTreeSet, HashMap};
#[derive(Clone, Debug, PartialEq, Default)]
pub struct KeyModifiers {
pub shift: bool,
pub control: bool,
pub alt: bool,
pub logo: bool,
}
#[derive(Clone, Debug, PartialEq)]
pub enum PointerInputType {
Mouse,
Touch,
XR,
}
impl PointerInputType {
pub fn is_touch(&self) -> bool {
*self == PointerInputType::Touch
}
pub fn is_mouse(&self) -> bool {
*self == PointerInputType::Mouse
}
pub fn is_xr(&self) -> bool {
*self == PointerInputType::XR
}
pub fn has_hovers(&self) -> bool {
*self == PointerInputType::Mouse || *self == PointerInputType::XR
}
}
impl Default for PointerInputType {
fn default() -> Self {
Self::Mouse
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum MouseButton {
Left,
Right,
Other,
}
impl Default for MouseButton {
fn default() -> Self {
Self::Left
}
}
#[derive(Clone, Default, Debug, PartialEq)]
pub struct PointerDownEvent {
pub window_id: usize,
pub abs: Vec2,
pub rel: Vec2,
pub rect: Rect,
pub digit: usize,
pub button: MouseButton,
pub tap_count: u32,
pub(crate) handled: bool,
pub input_type: PointerInputType,
pub modifiers: KeyModifiers,
pub time: f64,
}
#[derive(Clone, Default, Debug, PartialEq)]
pub struct PointerMoveEvent {
pub window_id: usize,
pub abs: Vec2,
pub abs_start: Vec2,
pub rel: Vec2,
pub rel_start: Vec2,
pub rect: Rect,
pub is_over: bool,
pub digit: usize,
pub input_type: PointerInputType,
pub modifiers: KeyModifiers,
pub time: f64,
}
impl PointerMoveEvent {
pub fn move_distance(&self) -> f32 {
((self.abs_start.x - self.abs.x).powf(2.) + (self.abs_start.y - self.abs.y).powf(2.)).sqrt()
}
}
#[derive(Clone, Default, Debug, PartialEq)]
pub struct PointerUpEvent {
pub window_id: usize,
pub abs: Vec2,
pub abs_start: Vec2,
pub rel: Vec2,
pub rel_start: Vec2,
pub rect: Rect,
pub digit: usize,
pub button: MouseButton,
pub is_over: bool,
pub input_type: PointerInputType,
pub modifiers: KeyModifiers,
pub time: f64,
}
#[derive(Clone, Debug, PartialEq)]
pub enum HoverState {
In,
Over,
Out,
}
impl Default for HoverState {
fn default() -> HoverState {
HoverState::Over
}
}
#[derive(Clone, Default, Debug, PartialEq)]
pub struct PointerHoverEvent {
pub window_id: usize,
pub digit: usize,
pub abs: Vec2,
pub rel: Vec2,
pub rect: Rect,
pub any_down: bool,
pub(crate) handled: bool,
pub hover_state: HoverState,
pub modifiers: KeyModifiers,
pub time: f64,
}
#[derive(Clone, Default, Debug, PartialEq)]
pub struct PointerScrollEvent {
pub window_id: usize,
pub digit: usize,
pub abs: Vec2,
pub rel: Vec2,
pub rect: Rect,
pub scroll: Vec2,
pub input_type: PointerInputType,
pub handled_x: bool,
pub handled_y: bool,
pub modifiers: KeyModifiers,
pub time: f64,
}
#[derive(Clone, Default, Debug, PartialEq)]
pub struct WindowGeomChangeEvent {
pub window_id: usize,
pub old_geom: WindowGeom,
pub new_geom: WindowGeom,
}
#[derive(Clone, Debug, PartialEq)]
pub struct TimerEvent {
pub timer_id: u64,
}
#[derive(Clone, Debug, PartialEq)]
pub struct SignalEvent {
pub signals: HashMap<Signal, BTreeSet<StatusId>>,
}
#[derive(Clone, Debug, PartialEq)]
pub struct KeyEvent {
pub key_code: KeyCode,
pub is_repeat: bool,
pub modifiers: KeyModifiers,
pub time: f64,
}
#[derive(Clone, Debug, PartialEq)]
pub struct KeyFocusEvent {
pub(crate) prev: Option<ComponentId>,
pub(crate) focus: Option<ComponentId>,
}
#[derive(Clone, Debug, PartialEq)]
pub struct FileDragUpdateEvent {
pub abs: Vec2,
}
#[derive(Clone, Debug, PartialEq)]
pub struct TextInputEvent {
pub input: String,
pub replace_last: bool,
pub was_paste: bool,
}
#[derive(Clone, Debug, PartialEq)]
pub struct WindowCloseRequestedEvent {
pub window_id: usize,
pub accept_close: bool,
}
#[derive(Clone, Debug, PartialEq)]
pub struct WindowClosedEvent {
pub window_id: usize,
}
#[derive(Clone, Debug, PartialEq)]
pub struct WindowResizeLoopEvent {
pub was_started: bool,
pub window_id: usize,
}
#[derive(Clone, Debug, PartialEq)]
pub enum WindowDragQueryResponse {
NoAnswer,
Client,
Caption,
SysMenu, }
#[derive(Clone, Debug, PartialEq)]
pub struct WindowDragQueryEvent {
pub window_id: usize,
pub abs: Vec2,
pub response: WindowDragQueryResponse,
}
#[derive(Clone, Debug, PartialEq)]
pub struct WebSocketMessageEvent {
pub url: String,
pub result: Result<Vec<u8>, String>,
}
#[derive(Clone, Debug)]
pub struct UserFile {
pub basename: String,
pub file: UniversalFile,
}
impl PartialEq for UserFile {
fn eq(&self, other: &Self) -> bool {
self.basename == other.basename
}
}
#[derive(Clone, Debug)]
pub struct WebRustCallEvent {
pub name: String,
pub params: Vec<ZapParam>,
pub callback_id: u32,
}
#[derive(Clone, Debug, PartialEq)]
pub struct AppOpenFilesEvent {
pub user_files: Vec<UserFile>,
}
#[derive(Debug, Clone)]
pub enum SystemEvent {
WebRustCall(Option<WebRustCallEvent>),
Draw,
Paint,
WindowSetHoverCursor(MouseCursor),
#[cfg(feature = "cef")]
CefDoMessageLoopWork,
}
#[derive(Clone, Debug)]
pub enum Event {
None,
Construct,
AppFocus,
AppFocusLost,
NextFrame,
WindowDragQuery(WindowDragQueryEvent),
WindowCloseRequested(WindowCloseRequestedEvent),
WindowClosed(WindowClosedEvent),
WindowGeomChange(WindowGeomChangeEvent),
WindowResizeLoop(WindowResizeLoopEvent),
PointerDown(PointerDownEvent),
PointerMove(PointerMoveEvent),
PointerHover(PointerHoverEvent),
PointerUp(PointerUpEvent),
PointerScroll(PointerScrollEvent),
Timer(TimerEvent),
Signal(SignalEvent),
Command(CommandId),
KeyFocus(KeyFocusEvent),
KeyFocusLost(KeyFocusEvent),
KeyDown(KeyEvent),
KeyUp(KeyEvent),
TextInput(TextInputEvent),
TextCopy,
WebSocketMessage(WebSocketMessageEvent),
AppOpenFiles(AppOpenFilesEvent),
FileDragBegin,
FileDragUpdate(FileDragUpdateEvent),
FileDragCancel,
SystemEvent(SystemEvent),
}
impl Default for Event {
fn default() -> Event {
Event::None
}
}
impl Event {
#[must_use]
pub fn hits_pointer(&mut self, cx: &mut Cx, component_id: ComponentId, rect: Option<Rect>) -> Event {
if let Some(rect) = rect {
match self {
Event::PointerScroll(pe) => {
if rect.contains(pe.abs) {
return Event::PointerScroll(PointerScrollEvent { rel: pe.abs - rect.pos, rect, ..pe.clone() });
}
}
Event::PointerHover(pe) => {
if cx.pointers[pe.digit]._over_last == Some(component_id) {
let mut any_down = false;
for pointer in &cx.pointers {
if pointer.captured == Some(component_id) {
any_down = true;
break;
}
}
if !pe.handled && rect.contains(pe.abs) {
pe.handled = true;
if let HoverState::Out = pe.hover_state {
} else {
cx.pointers[pe.digit].over_last = Some(component_id);
}
return Event::PointerHover(PointerHoverEvent {
rel: pe.abs - rect.pos,
rect,
any_down,
..pe.clone()
});
} else {
return Event::PointerHover(PointerHoverEvent {
rel: pe.abs - rect.pos,
rect,
any_down,
hover_state: HoverState::Out,
..pe.clone()
});
}
} else if !pe.handled && rect.contains(pe.abs) {
let mut any_down = false;
for pointer in &cx.pointers {
if pointer.captured == Some(component_id) {
any_down = true;
break;
}
}
cx.pointers[pe.digit].over_last = Some(component_id);
pe.handled = true;
return Event::PointerHover(PointerHoverEvent {
rel: pe.abs - rect.pos,
rect,
any_down,
hover_state: HoverState::In,
..pe.clone()
});
}
}
Event::PointerMove(pe) => {
if cx.pointers[pe.digit].captured == Some(component_id) {
let abs_start = cx.pointers[pe.digit].down_abs_start;
let rel_start = cx.pointers[pe.digit].down_rel_start;
return Event::PointerMove(PointerMoveEvent {
abs_start,
rel: pe.abs - rect.pos,
rel_start,
rect,
is_over: rect.contains(pe.abs),
..pe.clone()
});
}
}
Event::PointerDown(pe) => {
if !pe.handled && rect.contains(pe.abs) {
for pointer in &cx.pointers {
if pointer.captured == Some(component_id) {
return Event::None;
}
}
cx.pointers[pe.digit].captured = Some(component_id);
let rel = pe.abs - rect.pos;
cx.pointers[pe.digit].down_abs_start = pe.abs;
cx.pointers[pe.digit].down_rel_start = rel;
pe.handled = true;
return Event::PointerDown(PointerDownEvent { rel, rect, ..pe.clone() });
}
}
Event::PointerUp(pe) => {
if cx.pointers[pe.digit].captured == Some(component_id) {
cx.pointers[pe.digit].captured = None;
let abs_start = cx.pointers[pe.digit].down_abs_start;
let rel_start = cx.pointers[pe.digit].down_rel_start;
return Event::PointerUp(PointerUpEvent {
is_over: rect.contains(pe.abs),
abs_start,
rel_start,
rel: pe.abs - rect.pos,
rect,
..pe.clone()
});
}
}
_ => (),
};
}
Event::None
}
#[must_use]
pub fn hits_keyboard(&mut self, cx: &mut Cx, component_id: ComponentId) -> Event {
match self {
Event::KeyFocus(kf) => {
if kf.prev == Some(component_id) {
return Event::KeyFocusLost(kf.clone());
} else if kf.focus == Some(component_id) {
return Event::KeyFocus(kf.clone());
}
}
Event::KeyDown(_) => {
if cx.key_focus == Some(component_id) {
return self.clone();
}
}
Event::KeyUp(_) => {
if cx.key_focus == Some(component_id) {
return self.clone();
}
}
Event::TextInput(_) => {
if cx.key_focus == Some(component_id) {
return self.clone();
}
}
Event::TextCopy => {
if cx.key_focus == Some(component_id) {
return Event::TextCopy;
}
}
_ => (),
}
Event::None
}
}
#[derive(Hash, Eq, PartialEq, Clone, Copy, Debug, Default)]
pub struct Signal {
pub signal_id: usize,
}
pub type StatusId = LocationHash;
#[derive(Clone, Debug, Default)]
pub struct Timer {
pub timer_id: u64,
}
impl Timer {
pub fn empty() -> Timer {
Timer { timer_id: 0 }
}
pub fn is_timer(&mut self, te: &TimerEvent) -> bool {
te.timer_id == self.timer_id
}
}
#[derive(Clone, Copy, PartialEq, Debug)]
pub enum KeyCode {
Escape,
Backtick,
Key0,
Key1,
Key2,
Key3,
Key4,
Key5,
Key6,
Key7,
Key8,
Key9,
Minus,
Equals,
Backspace,
Tab,
KeyQ,
KeyW,
KeyE,
KeyR,
KeyT,
KeyY,
KeyU,
KeyI,
KeyO,
KeyP,
LBracket,
RBracket,
Return,
KeyA,
KeyS,
KeyD,
KeyF,
KeyG,
KeyH,
KeyJ,
KeyK,
KeyL,
Semicolon,
Quote,
Backslash,
KeyZ,
KeyX,
KeyC,
KeyV,
KeyB,
KeyN,
KeyM,
Comma,
Period,
Slash,
Control,
Alt,
Shift,
Logo,
Space,
Capslock,
F1,
F2,
F3,
F4,
F5,
F6,
F7,
F8,
F9,
F10,
F11,
F12,
PrintScreen,
Scrolllock,
Pause,
Insert,
Delete,
Home,
End,
PageUp,
PageDown,
Numpad0,
Numpad1,
Numpad2,
Numpad3,
Numpad4,
Numpad5,
Numpad6,
Numpad7,
Numpad8,
Numpad9,
NumpadEquals,
NumpadSubtract,
NumpadAdd,
NumpadDecimal,
NumpadMultiply,
NumpadDivide,
Numlock,
NumpadEnter,
ArrowUp,
ArrowDown,
ArrowLeft,
ArrowRight,
Unknown,
}
impl Default for KeyCode {
fn default() -> Self {
KeyCode::Unknown
}
}