#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[allow(unused)]
use super::{EventMgr, EventState, GrabMode, Response}; use super::{MouseButton, UpdateId, VirtualKeyCode};
use crate::geom::{Coord, DVec2, Offset};
#[allow(unused)] use crate::Widget;
use crate::{dir::Direction, WidgetId, WindowId};
#[non_exhaustive]
#[derive(Clone, Debug, PartialEq)]
pub enum Event {
None,
Command(Command),
ReceivedCharacter(char),
Scroll(ScrollDelta),
Pan {
alpha: DVec2,
delta: DVec2,
},
PressStart {
source: PressSource,
start_id: Option<WidgetId>,
coord: Coord,
},
PressMove {
source: PressSource,
cur_id: Option<WidgetId>,
coord: Coord,
delta: Offset,
},
PressEnd {
source: PressSource,
end_id: Option<WidgetId>,
coord: Coord,
success: bool,
},
TimerUpdate(u64),
Update { id: UpdateId, payload: u64 },
PopupRemoved(WindowId),
NavFocus(bool),
MouseHover,
LostNavFocus,
LostMouseHover,
LostCharFocus,
LostSelFocus,
}
impl std::ops::Add<Offset> for Event {
type Output = Self;
#[inline]
fn add(mut self, offset: Offset) -> Event {
self += offset;
self
}
}
impl std::ops::AddAssign<Offset> for Event {
fn add_assign(&mut self, offset: Offset) {
match self {
Event::PressStart { coord, .. } => {
*coord += offset;
}
Event::PressMove { coord, .. } => {
*coord += offset;
}
Event::PressEnd { coord, .. } => {
*coord += offset;
}
_ => (),
}
}
}
impl Event {
pub fn on_activate<F: FnOnce(&mut EventMgr) -> Response>(
self,
mgr: &mut EventMgr,
id: WidgetId,
f: F,
) -> Response {
match self {
Event::Command(cmd) if cmd.is_activate() => f(mgr),
Event::PressStart { source, coord, .. } if source.is_primary() => {
mgr.grab_press(id, source, coord, GrabMode::Grab, None);
Response::Used
}
Event::PressMove { source, cur_id, .. } => {
let target = if id == cur_id { cur_id } else { None };
mgr.set_grab_depress(source, target);
Response::Used
}
Event::PressEnd {
end_id, success, ..
} if success && id == end_id => f(mgr),
Event::PressEnd { .. } => Response::Used,
_ => Response::Unused,
}
}
pub fn pass_when_disabled(&self) -> bool {
use Event::*;
match self {
None | Command(_) => false,
ReceivedCharacter(_) | Scroll(_) | Pan { .. } => false,
PressStart { .. } | PressMove { .. } | PressEnd { .. } => false,
TimerUpdate(_) | Update { .. } | PopupRemoved(_) => true,
NavFocus(_) | MouseHover => false,
LostNavFocus | LostMouseHover | LostCharFocus | LostSelFocus => true,
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum Command {
Escape,
Activate,
Enter,
Space,
Tab,
ViewUp,
ViewDown,
Left,
Right,
Up,
Down,
WordLeft,
WordRight,
Home,
End,
DocHome,
DocEnd,
PageUp,
PageDown,
Snapshot,
ScrollLock,
Pause,
Insert,
Delete,
DelBack,
DelWord,
DelWordBack,
Deselect,
SelectAll,
Find,
FindReplace,
FindNext,
FindPrev,
Bold,
Italic,
Underline,
Link,
Cut,
Copy,
Paste,
Undo,
Redo,
New,
Open,
Save,
Print,
NavNext,
NavPrev,
NavParent,
NavDown,
TabNew,
TabNext,
TabPrev,
Help,
Rename,
Refresh,
Spelling,
Menu,
Fullscreen,
Close,
Exit,
}
impl Command {
pub fn new(vkey: VirtualKeyCode) -> Option<Self> {
use VirtualKeyCode::*;
Some(match vkey {
Escape => Command::Escape,
Snapshot => Command::Snapshot,
Scroll => Command::ScrollLock,
Space => Command::Space,
Pause => Command::Pause,
Insert => Command::Insert,
Home => Command::Home,
Delete => Command::Delete,
End => Command::End,
PageDown => Command::PageDown,
PageUp => Command::PageUp,
Left => Command::Left,
Up => Command::Up,
Right => Command::Right,
Down => Command::Down,
Back => Command::DelBack,
Return => Command::Enter,
NavigateForward => Command::NavNext,
NavigateBackward => Command::NavPrev,
NumpadEnter => Command::Enter,
Tab => Command::Tab,
Cut => Command::Cut,
Copy => Command::Copy,
Paste => Command::Paste,
_ => return None,
})
}
pub fn is_activate(self) -> bool {
use Command::*;
matches!(self, Activate | Enter | Space)
}
pub fn suitable_for_sel_focus(self) -> bool {
use Command::*;
matches!(self, Escape | Cut | Copy | Deselect)
}
pub fn as_direction(self) -> Option<Direction> {
match self {
Command::Left => Some(Direction::Left),
Command::Right => Some(Direction::Right),
Command::Up => Some(Direction::Up),
Command::Down => Some(Direction::Down),
_ => None,
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum PressSource {
Mouse(MouseButton, u32),
Touch(u64),
}
impl PressSource {
#[inline]
pub fn is_primary(self) -> bool {
match self {
PressSource::Mouse(button, _) => button == MouseButton::Left,
PressSource::Touch(_) => true,
}
}
#[inline]
pub fn is_touch(self) -> bool {
matches!(self, PressSource::Touch(_))
}
#[inline]
pub fn repetitions(self) -> u32 {
match self {
PressSource::Mouse(_, repetitions) => repetitions,
PressSource::Touch(_) => 1,
}
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum ScrollDelta {
LineDelta(f32, f32),
PixelDelta(Offset),
}