make tui agnostic over framework

This commit is contained in:
Evan Almloff committed 2023-02-06 21:28:48 -06:00
1 parent 05b968e8e4
commit c805bc25af
18 files changed
+262 -257

No files matched your search

+83 -89
View File
@@ -1,7 +1,6 @@
use crossterm::event::{
Event as TermEvent, KeyCode as TermKeyCode, KeyModifiers, MouseButton, MouseEventKind,
};
use dioxus_core::*;
use dioxus_native_core::real_dom::NodeImmutable;
use dioxus_native_core::{NodeId, NodeRef, RealDom};
use rustc_hash::{FxHashMap, FxHashSet};
@@ -13,9 +12,8 @@ use dioxus_html::geometry::{
use dioxus_html::input_data::keyboard_types::{Code, Key, Location, Modifiers};
use dioxus_html::input_data::MouseButtonSet as DioxusMouseButtons;
use dioxus_html::input_data::{MouseButton as DioxusMouseButton, MouseButtonSet};
use dioxus_html::{event_bubbles, FocusData, KeyboardData, MouseData, WheelData};
use dioxus_html::{event_bubbles, EventData, FocusData, KeyboardData, MouseData, WheelData};
use std::{
any::Any,
cell::{RefCell, RefMut},
rc::Rc,
time::{Duration, Instant},
@@ -28,9 +26,9 @@ use crate::layout::TaffyLayout;
use crate::{layout_to_screen_space, FocusState};
pub(crate) struct Event {
pub id: ElementId,
pub id: NodeId,
pub name: &'static str,
pub data: Rc<dyn Any>,
pub data: Rc<EventData>,
pub bubbles: bool,
}
@@ -71,24 +69,6 @@ pub(crate) struct Event {
type EventCore = (&'static str, EventData);
#[derive(Debug)]
enum EventData {
Mouse(MouseData),
Wheel(WheelData),
Screen((u16, u16)),
Keyboard(KeyboardData),
}
impl EventData {
fn into_any(self) -> Rc<dyn Any + Send + Sync> {
match self {
Self::Mouse(m) => Rc::new(m),
Self::Wheel(w) => Rc::new(w),
Self::Screen(s) => Rc::new(s),
Self::Keyboard(k) => Rc::new(k),
}
}
}
const MAX_REPEAT_TIME: Duration = Duration::from_millis(100);
pub struct InnerInputState {
@@ -101,14 +81,14 @@ pub struct InnerInputState {
}
impl InnerInputState {
fn new() -> Self {
fn create(rdom: &mut RealDom) -> Self {
Self {
mouse: None,
wheel: None,
last_key_pressed: None,
screen: None,
// subscribers: Vec::new(),
focus_state: FocusState::default(),
focus_state: FocusState::create(rdom),
}
}
@@ -149,7 +129,6 @@ impl InnerInputState {
*m = new_mouse_data;
}
EventData::Wheel(ref w) => self.wheel = Some(w.clone()),
EventData::Screen(ref s) => self.screen = Some(*s),
EventData::Keyboard(ref mut k) => {
let is_repeating = self
.last_key_pressed
@@ -166,6 +145,7 @@ impl InnerInputState {
self.last_key_pressed = Some((k.clone(), Instant::now()));
}
_ => {}
}
}
@@ -202,31 +182,27 @@ impl InnerInputState {
// elements with listeners will always have a element id
if let Some(id) = self.focus_state.last_focused_id {
let element = dom.get(id).unwrap();
if let Some(id) = element.node_data().element_id {
resolved_events.push(Event {
name: "focus",
id,
data: Rc::new(FocusData {}),
bubbles: event_bubbles("focus"),
});
resolved_events.push(Event {
name: "focusin",
id,
data: Rc::new(FocusData {}),
bubbles: event_bubbles("focusin"),
});
}
resolved_events.push(Event {
name: "focus",
id,
data: Rc::new(EventData::Focus(FocusData {})),
bubbles: event_bubbles("focus"),
});
resolved_events.push(Event {
name: "focusin",
id,
data: Rc::new(EventData::Focus(FocusData {})),
bubbles: event_bubbles("focusin"),
});
}
if let Some(id) = old_focus {
let element = dom.get(id).unwrap();
if let Some(id) = element.node_data().element_id {
resolved_events.push(Event {
name: "focusout",
id,
data: Rc::new(FocusData {}),
bubbles: event_bubbles("focusout"),
});
}
resolved_events.push(Event {
name: "focusout",
id,
data: Rc::new(EventData::Focus(FocusData {})),
bubbles: event_bubbles("focusout"),
});
}
}
@@ -260,29 +236,27 @@ impl InnerInputState {
fn try_create_event(
name: &'static str,
data: Rc<dyn Any>,
data: Rc<EventData>,
will_bubble: &mut FxHashSet<NodeId>,
resolved_events: &mut Vec<Event>,
node: NodeRef,
dom: &RealDom,
) {
// only trigger event if the event was not triggered already by a child
let id = node.node_data().node_id;
let id = node.id();
if will_bubble.insert(id) {
let mut parent = Some(node);
while let Some(current_parent) = parent {
let parent_id = current_parent.node_data().node_id;
let parent_id = current_parent.id();
will_bubble.insert(parent_id);
parent = current_parent.parent_id().and_then(|id| dom.get(id));
}
if let Some(id) = node.mounted_id() {
resolved_events.push(Event {
name,
id,
data,
bubbles: event_bubbles(name),
})
}
resolved_events.push(Event {
name,
id,
data,
bubbles: event_bubbles(name),
})
}
}
@@ -346,7 +320,10 @@ impl InnerInputState {
if currently_contains && previously_contained {
try_create_event(
"mousemove",
Rc::new(prepare_mouse_data(mouse_data, &node_layout)),
Rc::new(EventData::Mouse(prepare_mouse_data(
mouse_data,
&node_layout,
))),
&mut will_bubble,
resolved_events,
node,
@@ -370,7 +347,7 @@ impl InnerInputState {
if currently_contains && !previously_contained {
try_create_event(
"mouseenter",
Rc::new(mouse_data.clone()),
Rc::new(dioxus_html::EventData::Mouse(mouse_data.clone())),
&mut will_bubble,
resolved_events,
node,
@@ -393,7 +370,10 @@ impl InnerInputState {
if currently_contains && !previously_contained {
try_create_event(
"mouseover",
Rc::new(prepare_mouse_data(mouse_data, &node_layout)),
Rc::new(EventData::Mouse(prepare_mouse_data(
mouse_data,
&node_layout,
))),
&mut will_bubble,
resolved_events,
node,
@@ -413,7 +393,10 @@ impl InnerInputState {
if currently_contains {
try_create_event(
"mousedown",
Rc::new(prepare_mouse_data(mouse_data, &node_layout)),
Rc::new(EventData::Mouse(prepare_mouse_data(
mouse_data,
&node_layout,
))),
&mut will_bubble,
resolved_events,
node,
@@ -434,7 +417,10 @@ impl InnerInputState {
if currently_contains {
try_create_event(
"mouseup",
Rc::new(prepare_mouse_data(mouse_data, &node_layout)),
Rc::new(EventData::Mouse(prepare_mouse_data(
mouse_data,
&node_layout,
))),
&mut will_bubble,
resolved_events,
node,
@@ -456,7 +442,10 @@ impl InnerInputState {
if currently_contains {
try_create_event(
"click",
Rc::new(prepare_mouse_data(mouse_data, &node_layout)),
Rc::new(EventData::Mouse(prepare_mouse_data(
mouse_data,
&node_layout,
))),
&mut will_bubble,
resolved_events,
node,
@@ -479,7 +468,10 @@ impl InnerInputState {
if currently_contains {
try_create_event(
"contextmenu",
Rc::new(prepare_mouse_data(mouse_data, &node_layout)),
Rc::new(EventData::Mouse(prepare_mouse_data(
mouse_data,
&node_layout,
))),
&mut will_bubble,
resolved_events,
node,
@@ -503,7 +495,7 @@ impl InnerInputState {
if currently_contains {
try_create_event(
"wheel",
Rc::new(w.clone()),
Rc::new(EventData::Wheel(w.clone())),
&mut will_bubble,
resolved_events,
node,
@@ -528,7 +520,10 @@ impl InnerInputState {
if !currently_contains && previously_contained {
try_create_event(
"mouseleave",
Rc::new(prepare_mouse_data(mouse_data, &node_layout)),
Rc::new(EventData::Mouse(prepare_mouse_data(
mouse_data,
&node_layout,
))),
&mut will_bubble,
resolved_events,
node,
@@ -551,7 +546,10 @@ impl InnerInputState {
if !currently_contains && previously_contained {
try_create_event(
"mouseout",
Rc::new(prepare_mouse_data(mouse_data, &node_layout)),
Rc::new(EventData::Mouse(prepare_mouse_data(
mouse_data,
&node_layout,
))),
&mut will_bubble,
resolved_events,
node,
@@ -571,7 +569,7 @@ impl InnerInputState {
let currently_contains = layout_contains_point(node_layout, new_pos);
if currently_contains && node.get::<Focus>().unwrap().level.focusable() {
focus_id = Some(node.node_data().node_id);
focus_id = Some(node.id());
}
});
if let Some(id) = focus_id {
@@ -612,7 +610,9 @@ pub struct RinkInputHandler {
impl RinkInputHandler {
/// global context that handles events
/// limitations: GUI key modifier is never detected, key up events are not detected, and only two mouse buttons may be pressed at once
pub fn new() -> (
pub fn craete(
rdom: &mut RealDom,
) -> (
Self,
Rc<RefCell<InnerInputState>>,
impl FnMut(crossterm::event::Event),
@@ -628,7 +628,7 @@ impl RinkInputHandler {
}
};
let state = Rc::new(RefCell::new(InnerInputState::new()));
let state = Rc::new(RefCell::new(InnerInputState::create(rdom)));
(
Self {
@@ -640,10 +640,6 @@ impl RinkInputHandler {
)
}
pub(crate) fn prune(&self, mutations: &dioxus_core::Mutations, rdom: &RealDom) {
self.state.borrow_mut().focus_state.prune(mutations, rdom);
}
pub(crate) fn get_events(&self, layout: &Taffy, dom: &mut RealDom) -> Vec<Event> {
let mut resolved_events = Vec::new();
@@ -675,14 +671,14 @@ impl RinkInputHandler {
]
.contains(&e.0)
})
.map(|evt| (evt.0, evt.1.into_any()));
.map(|evt| (evt.0, evt.1));
let mut hm: FxHashMap<&'static str, Vec<Rc<dyn Any + Send + Sync>>> = FxHashMap::default();
let mut hm: FxHashMap<&'static str, Vec<Rc<EventData>>> = FxHashMap::default();
for (event, data) in events {
if let Some(v) = hm.get_mut(event) {
v.push(data);
v.push(Rc::new(data));
} else {
hm.insert(event, vec![data]);
hm.insert(event, vec![Rc::new(data)]);
}
}
for (event, datas) in hm {
@@ -690,14 +686,12 @@ impl RinkInputHandler {
for data in &datas {
let focused = node.get::<Focused>();
if focused.is_some() && focused.unwrap().0 {
if let Some(id) = node.mounted_id() {
resolved_events.push(Event {
name: event,
id,
data: data.clone(),
bubbles: event_bubbles(event),
});
}
resolved_events.push(Event {
name: event,
id: node.id(),
data: data.clone(),
bubbles: event_bubbles(event),
});
}
}
}
@@ -779,7 +773,7 @@ fn get_event(evt: TermEvent) -> Option<(&'static str, EventData)> {
MouseEventKind::ScrollUp => ("wheel", get_wheel_data(true)),
}
}
TermEvent::Resize(x, y) => ("resize", EventData::Screen((x, y))),
_ => return None,
};
Some((name, data))