Checkpoint
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
use crate::{
|
||||
Active, Anonymous, AnyElement, AppContext, BorrowWindow, Bounds, Click, DispatchPhase, Element,
|
||||
ElementFocusability, ElementId, ElementIdentity, EventListeners, Focus, FocusHandle,
|
||||
FocusListeners, Focusable, GlobalElementId, Hover, Identified, Interactive, IntoAnyElement,
|
||||
ElementFocusability, ElementId, ElementIdentity, Focus, FocusHandle, FocusListeners, Focusable,
|
||||
GlobalElementId, Hover, Identified, Interactive, InteractiveState, IntoAnyElement,
|
||||
KeyDownEvent, KeyMatch, LayoutId, MouseClickEvent, MouseDownEvent, MouseMoveEvent,
|
||||
MouseUpEvent, NonFocusable, Overflow, ParentElement, Pixels, Point, ScrollWheelEvent,
|
||||
SharedString, Style, StyleRefinement, Styled, ViewContext,
|
||||
@@ -78,7 +78,7 @@ pub struct Div<
|
||||
focus_style: StyleRefinement,
|
||||
focus_in_style: StyleRefinement,
|
||||
in_focus_style: StyleRefinement,
|
||||
listeners: EventListeners<V>,
|
||||
interactive_state: InteractiveState<V>,
|
||||
}
|
||||
|
||||
pub fn div<V>() -> Div<V, Anonymous, NonFocusable>
|
||||
@@ -98,7 +98,7 @@ where
|
||||
focus_style: StyleRefinement::default(),
|
||||
focus_in_style: StyleRefinement::default(),
|
||||
in_focus_style: StyleRefinement::default(),
|
||||
listeners: EventListeners::default(),
|
||||
interactive_state: InteractiveState::default(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,7 +126,7 @@ where
|
||||
focus_style: self.focus_style,
|
||||
focus_in_style: self.focus_in_style,
|
||||
in_focus_style: self.in_focus_style,
|
||||
listeners: self.listeners,
|
||||
interactive_state: self.interactive_state,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -296,7 +296,7 @@ where
|
||||
pending_click: Arc<Mutex<Option<MouseDownEvent>>>,
|
||||
cx: &mut ViewContext<V>,
|
||||
) {
|
||||
let click_listeners = mem::take(&mut self.listeners.mouse_click);
|
||||
let click_listeners = mem::take(&mut self.interactive_state.mouse_click);
|
||||
|
||||
let mouse_down = pending_click.lock().clone();
|
||||
if let Some(mouse_down) = mouse_down {
|
||||
@@ -333,25 +333,25 @@ where
|
||||
})
|
||||
}
|
||||
|
||||
for listener in mem::take(&mut self.listeners.mouse_down) {
|
||||
for listener in mem::take(&mut self.interactive_state.mouse_down) {
|
||||
cx.on_mouse_event(move |state, event: &MouseDownEvent, phase, cx| {
|
||||
listener(state, event, &bounds, phase, cx);
|
||||
})
|
||||
}
|
||||
|
||||
for listener in mem::take(&mut self.listeners.mouse_up) {
|
||||
for listener in mem::take(&mut self.interactive_state.mouse_up) {
|
||||
cx.on_mouse_event(move |state, event: &MouseUpEvent, phase, cx| {
|
||||
listener(state, event, &bounds, phase, cx);
|
||||
})
|
||||
}
|
||||
|
||||
for listener in mem::take(&mut self.listeners.mouse_move) {
|
||||
for listener in mem::take(&mut self.interactive_state.mouse_move) {
|
||||
cx.on_mouse_event(move |state, event: &MouseMoveEvent, phase, cx| {
|
||||
listener(state, event, &bounds, phase, cx);
|
||||
})
|
||||
}
|
||||
|
||||
for listener in mem::take(&mut self.listeners.scroll_wheel) {
|
||||
for listener in mem::take(&mut self.interactive_state.scroll_wheel) {
|
||||
cx.on_mouse_event(move |state, event: &ScrollWheelEvent, phase, cx| {
|
||||
listener(state, event, &bounds, phase, cx);
|
||||
})
|
||||
@@ -378,7 +378,7 @@ where
|
||||
focus_style: self.focus_style,
|
||||
focus_in_style: self.focus_in_style,
|
||||
in_focus_style: self.in_focus_style,
|
||||
listeners: self.listeners,
|
||||
interactive_state: self.interactive_state,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -431,7 +431,7 @@ where
|
||||
self.with_element_id(cx, |this, global_id, cx| {
|
||||
let element_state = element_state.unwrap_or_default();
|
||||
|
||||
let mut key_listeners = mem::take(&mut this.listeners.key);
|
||||
let mut key_listeners = mem::take(&mut this.interactive_state.key);
|
||||
if let Some(global_id) = global_id {
|
||||
key_listeners.push((
|
||||
TypeId::of::<KeyDownEvent>(),
|
||||
@@ -457,7 +457,7 @@ where
|
||||
}
|
||||
});
|
||||
});
|
||||
this.listeners.key = key_listeners;
|
||||
this.interactive_state.key = key_listeners;
|
||||
|
||||
element_state
|
||||
})
|
||||
@@ -584,8 +584,8 @@ where
|
||||
F: ElementFocusability<V>,
|
||||
V: 'static + Send + Sync,
|
||||
{
|
||||
fn listeners(&mut self) -> &mut EventListeners<V> {
|
||||
&mut self.listeners
|
||||
fn interactive_state(&mut self) -> &mut InteractiveState<V> {
|
||||
&mut self.interactive_state
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use crate::{
|
||||
div, Active, Anonymous, AnyElement, BorrowWindow, Bounds, Click, Div, DivState, Element,
|
||||
ElementFocusability, ElementId, ElementIdentity, EventListeners, Focus, FocusListeners,
|
||||
Focusable, Hover, Identified, Interactive, IntoAnyElement, LayoutId, NonFocusable, Pixels,
|
||||
ElementFocusability, ElementId, ElementIdentity, Focus, FocusListeners, Focusable, Hover,
|
||||
Identified, Interactive, InteractiveState, IntoAnyElement, LayoutId, NonFocusable, Pixels,
|
||||
SharedString, StyleRefinement, Styled, ViewContext,
|
||||
};
|
||||
use futures::FutureExt;
|
||||
@@ -156,8 +156,8 @@ where
|
||||
I: ElementIdentity,
|
||||
F: ElementFocusability<V>,
|
||||
{
|
||||
fn listeners(&mut self) -> &mut EventListeners<V> {
|
||||
self.base.listeners()
|
||||
fn interactive_state(&mut self) -> &mut InteractiveState<V> {
|
||||
self.base.interactive_state()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use crate::{
|
||||
div, Active, Anonymous, AnyElement, Bounds, Click, Div, DivState, Element, ElementFocusability,
|
||||
ElementId, ElementIdentity, EventListeners, Focus, FocusListeners, Focusable, Hover,
|
||||
Identified, Interactive, IntoAnyElement, LayoutId, NonFocusable, Pixels, SharedString,
|
||||
ElementId, ElementIdentity, Focus, FocusListeners, Focusable, Hover, Identified, Interactive,
|
||||
InteractiveState, IntoAnyElement, LayoutId, NonFocusable, Pixels, SharedString,
|
||||
StyleRefinement, Styled, ViewContext,
|
||||
};
|
||||
use util::ResultExt;
|
||||
@@ -130,8 +130,8 @@ where
|
||||
I: ElementIdentity,
|
||||
F: ElementFocusability<V>,
|
||||
{
|
||||
fn listeners(&mut self) -> &mut EventListeners<V> {
|
||||
self.base.listeners()
|
||||
fn interactive_state(&mut self) -> &mut InteractiveState<V> {
|
||||
self.base.interactive_state()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,291 +0,0 @@
|
||||
use crate::{
|
||||
point, Action, Bounds, DispatchContext, DispatchPhase, FocusHandle, Keystroke, Modifiers,
|
||||
Pixels, Point, ViewContext,
|
||||
};
|
||||
use smallvec::SmallVec;
|
||||
use std::{
|
||||
any::{Any, TypeId},
|
||||
ops::Deref,
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct KeyDownEvent {
|
||||
pub keystroke: Keystroke,
|
||||
pub is_held: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct KeyUpEvent {
|
||||
pub keystroke: Keystroke,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct ModifiersChangedEvent {
|
||||
pub modifiers: Modifiers,
|
||||
}
|
||||
|
||||
impl Deref for ModifiersChangedEvent {
|
||||
type Target = Modifiers;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.modifiers
|
||||
}
|
||||
}
|
||||
|
||||
/// The phase of a touch motion event.
|
||||
/// Based on the winit enum of the same name.
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum TouchPhase {
|
||||
Started,
|
||||
Moved,
|
||||
Ended,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct MouseDownEvent {
|
||||
pub button: MouseButton,
|
||||
pub position: Point<Pixels>,
|
||||
pub modifiers: Modifiers,
|
||||
pub click_count: usize,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct MouseUpEvent {
|
||||
pub button: MouseButton,
|
||||
pub position: Point<Pixels>,
|
||||
pub modifiers: Modifiers,
|
||||
pub click_count: usize,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct MouseClickEvent {
|
||||
pub down: MouseDownEvent,
|
||||
pub up: MouseUpEvent,
|
||||
}
|
||||
|
||||
#[derive(Hash, PartialEq, Eq, Copy, Clone, Debug)]
|
||||
pub enum MouseButton {
|
||||
Left,
|
||||
Right,
|
||||
Middle,
|
||||
Navigate(NavigationDirection),
|
||||
}
|
||||
|
||||
impl MouseButton {
|
||||
pub fn all() -> Vec<Self> {
|
||||
vec![
|
||||
MouseButton::Left,
|
||||
MouseButton::Right,
|
||||
MouseButton::Middle,
|
||||
MouseButton::Navigate(NavigationDirection::Back),
|
||||
MouseButton::Navigate(NavigationDirection::Forward),
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for MouseButton {
|
||||
fn default() -> Self {
|
||||
Self::Left
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Hash, PartialEq, Eq, Copy, Clone, Debug)]
|
||||
pub enum NavigationDirection {
|
||||
Back,
|
||||
Forward,
|
||||
}
|
||||
|
||||
impl Default for NavigationDirection {
|
||||
fn default() -> Self {
|
||||
Self::Back
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct MouseMoveEvent {
|
||||
pub position: Point<Pixels>,
|
||||
pub pressed_button: Option<MouseButton>,
|
||||
pub modifiers: Modifiers,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ScrollWheelEvent {
|
||||
pub position: Point<Pixels>,
|
||||
pub delta: ScrollDelta,
|
||||
pub modifiers: Modifiers,
|
||||
pub touch_phase: TouchPhase,
|
||||
}
|
||||
|
||||
impl Deref for ScrollWheelEvent {
|
||||
type Target = Modifiers;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.modifiers
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum ScrollDelta {
|
||||
Pixels(Point<Pixels>),
|
||||
Lines(Point<f32>),
|
||||
}
|
||||
|
||||
impl Default for ScrollDelta {
|
||||
fn default() -> Self {
|
||||
Self::Lines(Default::default())
|
||||
}
|
||||
}
|
||||
|
||||
impl ScrollDelta {
|
||||
pub fn precise(&self) -> bool {
|
||||
match self {
|
||||
ScrollDelta::Pixels(_) => true,
|
||||
ScrollDelta::Lines(_) => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn pixel_delta(&self, line_height: Pixels) -> Point<Pixels> {
|
||||
match self {
|
||||
ScrollDelta::Pixels(delta) => *delta,
|
||||
ScrollDelta::Lines(delta) => point(line_height * delta.x, line_height * delta.y),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct MouseExitEvent {
|
||||
pub position: Point<Pixels>,
|
||||
pub pressed_button: Option<MouseButton>,
|
||||
pub modifiers: Modifiers,
|
||||
}
|
||||
|
||||
impl Deref for MouseExitEvent {
|
||||
type Target = Modifiers;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.modifiers
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum InputEvent {
|
||||
KeyDown(KeyDownEvent),
|
||||
KeyUp(KeyUpEvent),
|
||||
ModifiersChanged(ModifiersChangedEvent),
|
||||
MouseDown(MouseDownEvent),
|
||||
MouseUp(MouseUpEvent),
|
||||
MouseMoved(MouseMoveEvent),
|
||||
MouseExited(MouseExitEvent),
|
||||
ScrollWheel(ScrollWheelEvent),
|
||||
}
|
||||
|
||||
impl InputEvent {
|
||||
pub fn position(&self) -> Option<Point<Pixels>> {
|
||||
match self {
|
||||
InputEvent::KeyDown { .. } => None,
|
||||
InputEvent::KeyUp { .. } => None,
|
||||
InputEvent::ModifiersChanged { .. } => None,
|
||||
InputEvent::MouseDown(event) => Some(event.position),
|
||||
InputEvent::MouseUp(event) => Some(event.position),
|
||||
InputEvent::MouseMoved(event) => Some(event.position),
|
||||
InputEvent::MouseExited(event) => Some(event.position),
|
||||
InputEvent::ScrollWheel(event) => Some(event.position),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mouse_event<'a>(&'a self) -> Option<&'a dyn Any> {
|
||||
match self {
|
||||
InputEvent::KeyDown { .. } => None,
|
||||
InputEvent::KeyUp { .. } => None,
|
||||
InputEvent::ModifiersChanged { .. } => None,
|
||||
InputEvent::MouseDown(event) => Some(event),
|
||||
InputEvent::MouseUp(event) => Some(event),
|
||||
InputEvent::MouseMoved(event) => Some(event),
|
||||
InputEvent::MouseExited(event) => Some(event),
|
||||
InputEvent::ScrollWheel(event) => Some(event),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn keyboard_event<'a>(&'a self) -> Option<&'a dyn Any> {
|
||||
match self {
|
||||
InputEvent::KeyDown(event) => Some(event),
|
||||
InputEvent::KeyUp(event) => Some(event),
|
||||
InputEvent::ModifiersChanged(event) => Some(event),
|
||||
InputEvent::MouseDown(_) => None,
|
||||
InputEvent::MouseUp(_) => None,
|
||||
InputEvent::MouseMoved(_) => None,
|
||||
InputEvent::MouseExited(_) => None,
|
||||
InputEvent::ScrollWheel(_) => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct FocusEvent {
|
||||
pub blurred: Option<FocusHandle>,
|
||||
pub focused: Option<FocusHandle>,
|
||||
}
|
||||
|
||||
pub type MouseDownListener<V> = Arc<
|
||||
dyn Fn(&mut V, &MouseDownEvent, &Bounds<Pixels>, DispatchPhase, &mut ViewContext<V>)
|
||||
+ Send
|
||||
+ Sync
|
||||
+ 'static,
|
||||
>;
|
||||
pub type MouseUpListener<V> = Arc<
|
||||
dyn Fn(&mut V, &MouseUpEvent, &Bounds<Pixels>, DispatchPhase, &mut ViewContext<V>)
|
||||
+ Send
|
||||
+ Sync
|
||||
+ 'static,
|
||||
>;
|
||||
pub type MouseClickListener<V> =
|
||||
Arc<dyn Fn(&mut V, &MouseClickEvent, &mut ViewContext<V>) + Send + Sync + 'static>;
|
||||
|
||||
pub type MouseMoveListener<V> = Arc<
|
||||
dyn Fn(&mut V, &MouseMoveEvent, &Bounds<Pixels>, DispatchPhase, &mut ViewContext<V>)
|
||||
+ Send
|
||||
+ Sync
|
||||
+ 'static,
|
||||
>;
|
||||
|
||||
pub type ScrollWheelListener<V> = Arc<
|
||||
dyn Fn(&mut V, &ScrollWheelEvent, &Bounds<Pixels>, DispatchPhase, &mut ViewContext<V>)
|
||||
+ Send
|
||||
+ Sync
|
||||
+ 'static,
|
||||
>;
|
||||
|
||||
pub type KeyListener<V> = Arc<
|
||||
dyn Fn(
|
||||
&mut V,
|
||||
&dyn Any,
|
||||
&[&DispatchContext],
|
||||
DispatchPhase,
|
||||
&mut ViewContext<V>,
|
||||
) -> Option<Box<dyn Action>>
|
||||
+ Send
|
||||
+ Sync
|
||||
+ 'static,
|
||||
>;
|
||||
|
||||
pub struct EventListeners<V: 'static> {
|
||||
pub mouse_down: SmallVec<[MouseDownListener<V>; 2]>,
|
||||
pub mouse_up: SmallVec<[MouseUpListener<V>; 2]>,
|
||||
pub mouse_click: SmallVec<[MouseClickListener<V>; 2]>,
|
||||
pub mouse_move: SmallVec<[MouseMoveListener<V>; 2]>,
|
||||
pub scroll_wheel: SmallVec<[ScrollWheelListener<V>; 2]>,
|
||||
pub key: SmallVec<[(TypeId, KeyListener<V>); 32]>,
|
||||
}
|
||||
|
||||
impl<V> Default for EventListeners<V> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
mouse_down: SmallVec::new(),
|
||||
mouse_up: SmallVec::new(),
|
||||
mouse_click: SmallVec::new(),
|
||||
mouse_move: SmallVec::new(),
|
||||
scroll_wheel: SmallVec::new(),
|
||||
key: SmallVec::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,6 @@ mod assets;
|
||||
mod color;
|
||||
mod element;
|
||||
mod elements;
|
||||
mod events;
|
||||
mod executor;
|
||||
mod focus;
|
||||
mod geometry;
|
||||
@@ -33,7 +32,6 @@ pub use assets::*;
|
||||
pub use color::*;
|
||||
pub use element::*;
|
||||
pub use elements::*;
|
||||
pub use events::*;
|
||||
pub use executor::*;
|
||||
pub use focus::*;
|
||||
pub use geometry::*;
|
||||
|
||||
+312
-26
@@ -1,12 +1,17 @@
|
||||
use std::{any::TypeId, sync::Arc};
|
||||
use smallvec::SmallVec;
|
||||
|
||||
use crate::{
|
||||
DispatchPhase, Element, EventListeners, KeyDownEvent, KeyUpEvent, MouseButton, MouseClickEvent,
|
||||
MouseDownEvent, MouseMoveEvent, MouseUpEvent, ScrollWheelEvent, ViewContext,
|
||||
point, Action, Bounds, DispatchContext, DispatchPhase, Element, FocusHandle, Keystroke,
|
||||
Modifiers, Pixels, Point, ViewContext,
|
||||
};
|
||||
use std::{
|
||||
any::{Any, TypeId},
|
||||
ops::Deref,
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
pub trait Interactive: Element {
|
||||
fn listeners(&mut self) -> &mut EventListeners<Self::ViewState>;
|
||||
fn interactive_state(&mut self) -> &mut InteractiveState<Self::ViewState>;
|
||||
|
||||
fn on_mouse_down(
|
||||
mut self,
|
||||
@@ -19,16 +24,16 @@ pub trait Interactive: Element {
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
self.listeners()
|
||||
.mouse_down
|
||||
.push(Arc::new(move |view, event, bounds, phase, cx| {
|
||||
self.interactive_state().mouse_down.push(Arc::new(
|
||||
move |view, event, bounds, phase, cx| {
|
||||
if phase == DispatchPhase::Bubble
|
||||
&& event.button == button
|
||||
&& bounds.contains_point(&event.position)
|
||||
{
|
||||
handler(view, event, cx)
|
||||
}
|
||||
}));
|
||||
},
|
||||
));
|
||||
self
|
||||
}
|
||||
|
||||
@@ -43,7 +48,7 @@ pub trait Interactive: Element {
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
self.listeners()
|
||||
self.interactive_state()
|
||||
.mouse_up
|
||||
.push(Arc::new(move |view, event, bounds, phase, cx| {
|
||||
if phase == DispatchPhase::Bubble
|
||||
@@ -67,16 +72,16 @@ pub trait Interactive: Element {
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
self.listeners()
|
||||
.mouse_down
|
||||
.push(Arc::new(move |view, event, bounds, phase, cx| {
|
||||
self.interactive_state().mouse_down.push(Arc::new(
|
||||
move |view, event, bounds, phase, cx| {
|
||||
if phase == DispatchPhase::Capture
|
||||
&& event.button == button
|
||||
&& !bounds.contains_point(&event.position)
|
||||
{
|
||||
handler(view, event, cx)
|
||||
}
|
||||
}));
|
||||
},
|
||||
));
|
||||
self
|
||||
}
|
||||
|
||||
@@ -91,7 +96,7 @@ pub trait Interactive: Element {
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
self.listeners()
|
||||
self.interactive_state()
|
||||
.mouse_up
|
||||
.push(Arc::new(move |view, event, bounds, phase, cx| {
|
||||
if phase == DispatchPhase::Capture
|
||||
@@ -114,13 +119,13 @@ pub trait Interactive: Element {
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
self.listeners()
|
||||
.mouse_move
|
||||
.push(Arc::new(move |view, event, bounds, phase, cx| {
|
||||
self.interactive_state().mouse_move.push(Arc::new(
|
||||
move |view, event, bounds, phase, cx| {
|
||||
if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) {
|
||||
handler(view, event, cx);
|
||||
}
|
||||
}));
|
||||
},
|
||||
));
|
||||
self
|
||||
}
|
||||
|
||||
@@ -134,13 +139,13 @@ pub trait Interactive: Element {
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
self.listeners()
|
||||
.scroll_wheel
|
||||
.push(Arc::new(move |view, event, bounds, phase, cx| {
|
||||
self.interactive_state().scroll_wheel.push(Arc::new(
|
||||
move |view, event, bounds, phase, cx| {
|
||||
if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) {
|
||||
handler(view, event, cx);
|
||||
}
|
||||
}));
|
||||
},
|
||||
));
|
||||
self
|
||||
}
|
||||
|
||||
@@ -158,7 +163,7 @@ pub trait Interactive: Element {
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
self.listeners().key.push((
|
||||
self.interactive_state().key.push((
|
||||
TypeId::of::<KeyDownEvent>(),
|
||||
Arc::new(move |view, event, _, phase, cx| {
|
||||
let event = event.downcast_ref().unwrap();
|
||||
@@ -179,7 +184,7 @@ pub trait Interactive: Element {
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
self.listeners().key.push((
|
||||
self.interactive_state().key.push((
|
||||
TypeId::of::<KeyUpEvent>(),
|
||||
Arc::new(move |view, event, _, phase, cx| {
|
||||
let event = event.downcast_ref().unwrap();
|
||||
@@ -200,7 +205,7 @@ pub trait Interactive: Element {
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
self.listeners().key.push((
|
||||
self.interactive_state().key.push((
|
||||
TypeId::of::<A>(),
|
||||
Arc::new(move |view, event, _, phase, cx| {
|
||||
let event = event.downcast_ref().unwrap();
|
||||
@@ -223,9 +228,290 @@ pub trait Click: Interactive {
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
self.listeners()
|
||||
self.interactive_state()
|
||||
.mouse_click
|
||||
.push(Arc::new(move |view, event, cx| handler(view, event, cx)));
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct KeyDownEvent {
|
||||
pub keystroke: Keystroke,
|
||||
pub is_held: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct KeyUpEvent {
|
||||
pub keystroke: Keystroke,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct ModifiersChangedEvent {
|
||||
pub modifiers: Modifiers,
|
||||
}
|
||||
|
||||
impl Deref for ModifiersChangedEvent {
|
||||
type Target = Modifiers;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.modifiers
|
||||
}
|
||||
}
|
||||
|
||||
/// The phase of a touch motion event.
|
||||
/// Based on the winit enum of the same name.
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum TouchPhase {
|
||||
Started,
|
||||
Moved,
|
||||
Ended,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct MouseDownEvent {
|
||||
pub button: MouseButton,
|
||||
pub position: Point<Pixels>,
|
||||
pub modifiers: Modifiers,
|
||||
pub click_count: usize,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct MouseUpEvent {
|
||||
pub button: MouseButton,
|
||||
pub position: Point<Pixels>,
|
||||
pub modifiers: Modifiers,
|
||||
pub click_count: usize,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct MouseClickEvent {
|
||||
pub down: MouseDownEvent,
|
||||
pub up: MouseUpEvent,
|
||||
}
|
||||
|
||||
#[derive(Hash, PartialEq, Eq, Copy, Clone, Debug)]
|
||||
pub enum MouseButton {
|
||||
Left,
|
||||
Right,
|
||||
Middle,
|
||||
Navigate(NavigationDirection),
|
||||
}
|
||||
|
||||
impl MouseButton {
|
||||
pub fn all() -> Vec<Self> {
|
||||
vec![
|
||||
MouseButton::Left,
|
||||
MouseButton::Right,
|
||||
MouseButton::Middle,
|
||||
MouseButton::Navigate(NavigationDirection::Back),
|
||||
MouseButton::Navigate(NavigationDirection::Forward),
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for MouseButton {
|
||||
fn default() -> Self {
|
||||
Self::Left
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Hash, PartialEq, Eq, Copy, Clone, Debug)]
|
||||
pub enum NavigationDirection {
|
||||
Back,
|
||||
Forward,
|
||||
}
|
||||
|
||||
impl Default for NavigationDirection {
|
||||
fn default() -> Self {
|
||||
Self::Back
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct MouseMoveEvent {
|
||||
pub position: Point<Pixels>,
|
||||
pub pressed_button: Option<MouseButton>,
|
||||
pub modifiers: Modifiers,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ScrollWheelEvent {
|
||||
pub position: Point<Pixels>,
|
||||
pub delta: ScrollDelta,
|
||||
pub modifiers: Modifiers,
|
||||
pub touch_phase: TouchPhase,
|
||||
}
|
||||
|
||||
impl Deref for ScrollWheelEvent {
|
||||
type Target = Modifiers;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.modifiers
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum ScrollDelta {
|
||||
Pixels(Point<Pixels>),
|
||||
Lines(Point<f32>),
|
||||
}
|
||||
|
||||
impl Default for ScrollDelta {
|
||||
fn default() -> Self {
|
||||
Self::Lines(Default::default())
|
||||
}
|
||||
}
|
||||
|
||||
impl ScrollDelta {
|
||||
pub fn precise(&self) -> bool {
|
||||
match self {
|
||||
ScrollDelta::Pixels(_) => true,
|
||||
ScrollDelta::Lines(_) => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn pixel_delta(&self, line_height: Pixels) -> Point<Pixels> {
|
||||
match self {
|
||||
ScrollDelta::Pixels(delta) => *delta,
|
||||
ScrollDelta::Lines(delta) => point(line_height * delta.x, line_height * delta.y),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct MouseExitEvent {
|
||||
pub position: Point<Pixels>,
|
||||
pub pressed_button: Option<MouseButton>,
|
||||
pub modifiers: Modifiers,
|
||||
}
|
||||
|
||||
impl Deref for MouseExitEvent {
|
||||
type Target = Modifiers;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.modifiers
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum InputEvent {
|
||||
KeyDown(KeyDownEvent),
|
||||
KeyUp(KeyUpEvent),
|
||||
ModifiersChanged(ModifiersChangedEvent),
|
||||
MouseDown(MouseDownEvent),
|
||||
MouseUp(MouseUpEvent),
|
||||
MouseMoved(MouseMoveEvent),
|
||||
MouseExited(MouseExitEvent),
|
||||
ScrollWheel(ScrollWheelEvent),
|
||||
}
|
||||
|
||||
impl InputEvent {
|
||||
pub fn position(&self) -> Option<Point<Pixels>> {
|
||||
match self {
|
||||
InputEvent::KeyDown { .. } => None,
|
||||
InputEvent::KeyUp { .. } => None,
|
||||
InputEvent::ModifiersChanged { .. } => None,
|
||||
InputEvent::MouseDown(event) => Some(event.position),
|
||||
InputEvent::MouseUp(event) => Some(event.position),
|
||||
InputEvent::MouseMoved(event) => Some(event.position),
|
||||
InputEvent::MouseExited(event) => Some(event.position),
|
||||
InputEvent::ScrollWheel(event) => Some(event.position),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mouse_event<'a>(&'a self) -> Option<&'a dyn Any> {
|
||||
match self {
|
||||
InputEvent::KeyDown { .. } => None,
|
||||
InputEvent::KeyUp { .. } => None,
|
||||
InputEvent::ModifiersChanged { .. } => None,
|
||||
InputEvent::MouseDown(event) => Some(event),
|
||||
InputEvent::MouseUp(event) => Some(event),
|
||||
InputEvent::MouseMoved(event) => Some(event),
|
||||
InputEvent::MouseExited(event) => Some(event),
|
||||
InputEvent::ScrollWheel(event) => Some(event),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn keyboard_event<'a>(&'a self) -> Option<&'a dyn Any> {
|
||||
match self {
|
||||
InputEvent::KeyDown(event) => Some(event),
|
||||
InputEvent::KeyUp(event) => Some(event),
|
||||
InputEvent::ModifiersChanged(event) => Some(event),
|
||||
InputEvent::MouseDown(_) => None,
|
||||
InputEvent::MouseUp(_) => None,
|
||||
InputEvent::MouseMoved(_) => None,
|
||||
InputEvent::MouseExited(_) => None,
|
||||
InputEvent::ScrollWheel(_) => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct FocusEvent {
|
||||
pub blurred: Option<FocusHandle>,
|
||||
pub focused: Option<FocusHandle>,
|
||||
}
|
||||
|
||||
pub type MouseDownListener<V> = Arc<
|
||||
dyn Fn(&mut V, &MouseDownEvent, &Bounds<Pixels>, DispatchPhase, &mut ViewContext<V>)
|
||||
+ Send
|
||||
+ Sync
|
||||
+ 'static,
|
||||
>;
|
||||
pub type MouseUpListener<V> = Arc<
|
||||
dyn Fn(&mut V, &MouseUpEvent, &Bounds<Pixels>, DispatchPhase, &mut ViewContext<V>)
|
||||
+ Send
|
||||
+ Sync
|
||||
+ 'static,
|
||||
>;
|
||||
pub type MouseClickListener<V> =
|
||||
Arc<dyn Fn(&mut V, &MouseClickEvent, &mut ViewContext<V>) + Send + Sync + 'static>;
|
||||
|
||||
pub type MouseMoveListener<V> = Arc<
|
||||
dyn Fn(&mut V, &MouseMoveEvent, &Bounds<Pixels>, DispatchPhase, &mut ViewContext<V>)
|
||||
+ Send
|
||||
+ Sync
|
||||
+ 'static,
|
||||
>;
|
||||
|
||||
pub type ScrollWheelListener<V> = Arc<
|
||||
dyn Fn(&mut V, &ScrollWheelEvent, &Bounds<Pixels>, DispatchPhase, &mut ViewContext<V>)
|
||||
+ Send
|
||||
+ Sync
|
||||
+ 'static,
|
||||
>;
|
||||
|
||||
pub type KeyListener<V> = Arc<
|
||||
dyn Fn(
|
||||
&mut V,
|
||||
&dyn Any,
|
||||
&[&DispatchContext],
|
||||
DispatchPhase,
|
||||
&mut ViewContext<V>,
|
||||
) -> Option<Box<dyn Action>>
|
||||
+ Send
|
||||
+ Sync
|
||||
+ 'static,
|
||||
>;
|
||||
|
||||
pub struct InteractiveState<V: 'static> {
|
||||
pub mouse_down: SmallVec<[MouseDownListener<V>; 2]>,
|
||||
pub mouse_up: SmallVec<[MouseUpListener<V>; 2]>,
|
||||
pub mouse_click: SmallVec<[MouseClickListener<V>; 2]>,
|
||||
pub mouse_move: SmallVec<[MouseMoveListener<V>; 2]>,
|
||||
pub scroll_wheel: SmallVec<[ScrollWheelListener<V>; 2]>,
|
||||
pub key: SmallVec<[(TypeId, KeyListener<V>); 32]>,
|
||||
}
|
||||
|
||||
impl<V> Default for InteractiveState<V> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
mouse_down: SmallVec::new(),
|
||||
mouse_up: SmallVec::new(),
|
||||
mouse_click: SmallVec::new(),
|
||||
mouse_move: SmallVec::new(),
|
||||
scroll_wheel: SmallVec::new(),
|
||||
key: SmallVec::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user