#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use super::{EventCx, IsUsed, Unused, Used};
#[allow(unused)] use super::{EventState, GrabMode};
use super::{Key, KeyCode, KeyEvent, Press};
use crate::geom::{DVec2, Offset};
use crate::{dir::Direction, WidgetId, WindowId};
#[allow(unused)] use crate::{Events, Popup};
#[non_exhaustive]
#[derive(Clone, Debug, PartialEq)]
pub enum Event {
Command(Command, Option<KeyCode>),
Key(KeyEvent, bool),
Scroll(ScrollDelta),
Pan {
alpha: DVec2,
delta: DVec2,
},
CursorMove { press: Press },
PressStart { press: Press },
PressMove { press: Press, delta: Offset },
PressEnd { press: Press, success: bool },
TimerUpdate(u64),
#[cfg_attr(not(feature = "internal_doc"), doc(hidden))]
#[cfg_attr(doc_cfg, doc(cfg(internal_doc)))]
PopupClosed(WindowId),
NavFocus(FocusSource),
MouseHover(bool),
LostNavFocus,
LostKeyFocus,
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::CursorMove { ref mut press } => {
press.coord += offset;
}
Event::PressStart { ref mut press, .. } => {
press.coord += offset;
}
Event::PressMove { ref mut press, .. } => {
press.coord += offset;
}
Event::PressEnd { ref mut press, .. } => {
press.coord += offset;
}
_ => (),
}
}
}
impl Event {
pub fn on_activate<F: FnOnce(&mut EventCx) -> IsUsed>(
self,
cx: &mut EventCx,
id: WidgetId,
f: F,
) -> IsUsed {
match self {
Event::Command(cmd, code) if cmd.is_activate() => {
if let Some(code) = code {
cx.depress_with_key(id, code);
}
f(cx)
}
Event::PressStart { press, .. } if press.is_primary() => press.grab(id).with_cx(cx),
Event::PressEnd { press, success } => {
if success && id == press.id {
f(cx)
} else {
Used
}
}
_ => Unused,
}
}
pub fn pass_when_disabled(&self) -> bool {
use Event::*;
match self {
Command(_, _) => false,
Key(_, _) | Scroll(_) | Pan { .. } => false,
CursorMove { .. } | PressStart { .. } | PressMove { .. } | PressEnd { .. } => false,
TimerUpdate(_) | PopupClosed(_) => true,
NavFocus { .. } | MouseHover(_) => false,
LostNavFocus | LostKeyFocus | LostSelFocus => true,
}
}
pub fn is_reusable(&self) -> bool {
use Event::*;
match self {
Key(_, _) => false,
Command(_, _) | Scroll(_) | Pan { .. } => true,
CursorMove { .. } | PressStart { .. } => true,
PressMove { .. } | PressEnd { .. } => false,
TimerUpdate(_) | PopupClosed(_) => false,
NavFocus { .. } | MouseHover(_) | LostNavFocus => false,
LostKeyFocus | LostSelFocus => false,
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[non_exhaustive]
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,
FindPrevious,
Bold,
Italic,
Underline,
Link,
Cut,
Copy,
Paste,
Undo,
Redo,
New,
Open,
Save,
Print,
NavNext,
NavPrevious,
NavParent,
NavDown,
TabNew,
TabNext,
TabPrevious,
Help,
Rename,
Refresh,
Debug,
SpellCheck,
ContextMenu,
Menu,
Fullscreen,
Close,
Exit,
}
impl Command {
pub fn new(key: &Key) -> Option<Self> {
Some(match key {
Key::ScrollLock => Command::ScrollLock,
Key::Enter => Command::Enter,
Key::Tab => Command::Tab,
Key::Space => Command::Space,
Key::ArrowDown => Command::Down,
Key::ArrowLeft => Command::Left,
Key::ArrowRight => Command::Right,
Key::ArrowUp => Command::Up,
Key::End => Command::End,
Key::Home => Command::Home,
Key::PageDown => Command::PageDown,
Key::PageUp => Command::PageUp,
Key::Backspace => Command::DelBack,
Key::Clear => Command::Deselect,
Key::Copy => Command::Copy,
Key::Cut => Command::Cut,
Key::Delete => Command::Delete,
Key::Insert => Command::Insert,
Key::Paste => Command::Paste,
Key::Redo | Key::Again => Command::Redo,
Key::Undo => Command::Undo,
Key::ContextMenu => Command::ContextMenu,
Key::Escape => Command::Escape,
Key::Execute => Command::Activate,
Key::Find => Command::Find,
Key::Help => Command::Help,
Key::Pause => Command::Pause,
Key::Select => Command::SelectAll,
Key::PrintScreen => Command::Snapshot,
Key::New => Command::New,
Key::Open => Command::Open,
Key::Print => Command::Print,
Key::Save => Command::Save,
Key::SpellCheck => Command::SpellCheck,
Key::BrowserBack | Key::GoBack => Command::NavPrevious,
Key::BrowserForward => Command::NavNext,
Key::BrowserRefresh => Command::Refresh,
Key::Exit => Command::Exit,
_ => 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, PartialOrd, Ord, Hash)]
pub enum FocusSource {
Pointer,
Key,
Synthetic,
}
impl FocusSource {
pub fn key_or_synthetic(self) -> bool {
match self {
FocusSource::Pointer => false,
FocusSource::Key | FocusSource::Synthetic => true,
}
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum ScrollDelta {
LineDelta(f32, f32),
PixelDelta(Offset),
}