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 FingerInputType {
Mouse,
Touch,
XR,
}
impl FingerInputType {
pub fn is_touch(&self) -> bool {
*self == FingerInputType::Touch
}
pub fn is_mouse(&self) -> bool {
*self == FingerInputType::Mouse
}
pub fn is_xr(&self) -> bool {
*self == FingerInputType::XR
}
pub fn has_hovers(&self) -> bool {
*self == FingerInputType::Mouse || *self == FingerInputType::XR
}
}
impl Default for FingerInputType {
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 FingerDownEvent {
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: FingerInputType,
pub modifiers: KeyModifiers,
pub time: f64,
}
#[derive(Clone, Default, Debug, PartialEq)]
pub struct FingerMoveEvent {
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: FingerInputType,
pub modifiers: KeyModifiers,
pub time: f64,
}
impl FingerMoveEvent {
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 FingerUpEvent {
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: FingerInputType,
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 FingerHoverEvent {
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 FingerScrollEvent {
pub window_id: usize,
pub digit: usize,
pub abs: Vec2,
pub rel: Vec2,
pub rect: Rect,
pub scroll: Vec2,
pub input_type: FingerInputType,
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<WrfParam>,
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),
FingerDown(FingerDownEvent),
FingerMove(FingerMoveEvent),
FingerHover(FingerHoverEvent),
FingerUp(FingerUpEvent),
FingerScroll(FingerScrollEvent),
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
}
}
#[derive(Clone, Copy, Debug)]
pub struct Margin {
pub l: f32,
pub t: f32,
pub r: f32,
pub b: f32,
}
impl Margin {
pub const ZERO: Margin = Margin { l: 0.0, t: 0.0, r: 0.0, b: 0.0 };
pub const DEFAULT: Margin = Margin::ZERO;
pub const fn all(v: f32) -> Margin {
Margin { l: v, t: v, r: v, b: v }
}
pub const fn left(v: f32) -> Margin {
Margin { l: v, ..Margin::ZERO }
}
pub const fn top(v: f32) -> Margin {
Margin { t: v, ..Margin::ZERO }
}
pub const fn right(v: f32) -> Margin {
Margin { r: v, ..Margin::ZERO }
}
pub const fn bottom(v: f32) -> Margin {
Margin { b: v, ..Margin::ZERO }
}
}
impl Default for Margin {
fn default() -> Self {
Margin::DEFAULT
}
}
#[derive(Clone, Debug, Default)]
pub struct HitOpt {
pub use_multi_touch: bool,
pub margin: Option<Margin>,
}
impl Event {
#[must_use]
pub fn hits(&mut self, cx: &mut Cx, component_base: &ComponentBase, opt: HitOpt) -> Event {
let area = component_base.area;
let id = component_base.id;
if area.is_empty() || !area.is_valid(cx) {
return Event::None;
}
match self {
Event::KeyFocus(kf) => {
if id == kf.prev {
return Event::KeyFocusLost(kf.clone());
} else if id == kf.focus {
return Event::KeyFocus(kf.clone());
}
}
Event::KeyDown(_) => {
if id == cx.key_focus {
return self.clone();
}
}
Event::KeyUp(_) => {
if id == cx.key_focus {
return self.clone();
}
}
Event::TextInput(_) => {
if id == cx.key_focus {
return self.clone();
}
}
Event::TextCopy => {
if id == cx.key_focus {
return Event::TextCopy;
}
}
Event::FingerScroll(fe) => {
let rect = area.get_rect_for_first_instance(cx);
if rect_contains_with_margin(&rect, fe.abs, &opt.margin) {
return Event::FingerScroll(FingerScrollEvent { rel: fe.abs - rect.pos, rect, ..fe.clone() });
}
}
Event::FingerHover(fe) => {
let rect = area.get_rect_for_first_instance(cx);
if cx.fingers[fe.digit]._over_last == id {
let mut any_down = false;
for finger in &cx.fingers {
if finger.captured == id {
any_down = true;
break;
}
}
if !fe.handled && rect_contains_with_margin(&rect, fe.abs, &opt.margin) {
fe.handled = true;
if let HoverState::Out = fe.hover_state {
} else {
cx.fingers[fe.digit].over_last = id;
}
return Event::FingerHover(FingerHoverEvent { rel: fe.abs - rect.pos, rect, any_down, ..fe.clone() });
} else {
return Event::FingerHover(FingerHoverEvent {
rel: fe.abs - rect.pos,
rect,
any_down,
hover_state: HoverState::Out,
..fe.clone()
});
}
} else if !fe.handled && rect_contains_with_margin(&rect, fe.abs, &opt.margin) {
let mut any_down = false;
for finger in &cx.fingers {
if finger.captured == id {
any_down = true;
break;
}
}
cx.fingers[fe.digit].over_last = id;
fe.handled = true;
return Event::FingerHover(FingerHoverEvent {
rel: fe.abs - rect.pos,
rect,
any_down,
hover_state: HoverState::In,
..fe.clone()
});
}
}
Event::FingerMove(fe) => {
if cx.fingers[fe.digit].captured == id {
let abs_start = cx.fingers[fe.digit].down_abs_start;
let rel_start = cx.fingers[fe.digit].down_rel_start;
let rect = area.get_rect_for_first_instance(cx);
return Event::FingerMove(FingerMoveEvent {
abs_start,
rel: fe.abs - rect.pos,
rel_start,
rect,
is_over: rect_contains_with_margin(&rect, fe.abs, &opt.margin),
..fe.clone()
});
}
}
Event::FingerDown(fe) => {
if !fe.handled {
let rect = area.get_rect_for_first_instance(cx);
if rect_contains_with_margin(&rect, fe.abs, &opt.margin) {
if !opt.use_multi_touch {
for finger in &cx.fingers {
if finger.captured == id {
return Event::None;
}
}
}
cx.fingers[fe.digit].captured = id;
let rel = fe.abs - rect.pos;
cx.fingers[fe.digit].down_abs_start = fe.abs;
cx.fingers[fe.digit].down_rel_start = rel;
fe.handled = true;
return Event::FingerDown(FingerDownEvent { rel, rect, ..fe.clone() });
}
}
}
Event::FingerUp(fe) => {
if cx.fingers[fe.digit].captured == id {
cx.fingers[fe.digit].captured = None;
let abs_start = cx.fingers[fe.digit].down_abs_start;
let rel_start = cx.fingers[fe.digit].down_rel_start;
let rect = area.get_rect_for_first_instance(cx);
return Event::FingerUp(FingerUpEvent {
is_over: rect.contains(fe.abs),
abs_start,
rel_start,
rel: fe.abs - rect.pos,
rect,
..fe.clone()
});
}
}
_ => (),
};
Event::None
}
}
fn rect_contains_with_margin(rect: &Rect, pos: Vec2, margin: &Option<Margin>) -> bool {
if let Some(margin) = margin {
pos.x >= rect.pos.x - margin.l
&& pos.x <= rect.pos.x + rect.size.x + margin.r
&& pos.y >= rect.pos.y - margin.t
&& pos.y <= rect.pos.y + rect.size.y + margin.b
} else {
rect.contains(pos)
}
}
#[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
}
}