fix dioxus-tui events
This commit is contained in:
1 parent
0ab7a02777
commit
d06e64e5ad
19 files changed
+221
-21
No files matched your search
@@ -14,9 +14,7 @@ fn miri_rollover() {
|
||||
for _ in 0..3 {
|
||||
dom.handle_event(
|
||||
"click",
|
||||
Rc::new(PlatformEventData::new(Box::new(
|
||||
SerializedMouseData::default(),
|
||||
))),
|
||||
Rc::new(PlatformEventData::new(Box::<SerializedMouseData>::default())),
|
||||
ElementId(2),
|
||||
true,
|
||||
);
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
use std::{
|
||||
any::Any,
|
||||
fmt::{Display, Formatter},
|
||||
rc::Rc,
|
||||
};
|
||||
|
||||
use dioxus_core::{ElementId, Mutations, VirtualDom};
|
||||
@@ -30,7 +29,7 @@ pub(crate) fn find_mount_events(mutations: &Mutations) -> Vec<ElementId> {
|
||||
// We need to queue the mounted events to give rink time to rendere and resolve the layout of elements after they are created
|
||||
pub(crate) fn create_mounted_events(
|
||||
vdom: &VirtualDom,
|
||||
events: &mut Vec<(ElementId, &'static str, Rc<dyn Any>, bool)>,
|
||||
events: &mut Vec<(ElementId, &'static str, Box<dyn Any>, bool)>,
|
||||
mount_events: impl Iterator<Item = (ElementId, NodeId)>,
|
||||
) {
|
||||
let query: Query = vdom
|
||||
@@ -42,11 +41,12 @@ pub(crate) fn create_mounted_events(
|
||||
query: query.clone(),
|
||||
id: node_id,
|
||||
};
|
||||
events.push((id, "mounted", Rc::new(MountedData::new(element)), false));
|
||||
events.push((id, "mounted", Box::new(MountedData::new(element)), false));
|
||||
}
|
||||
}
|
||||
|
||||
struct TuiElement {
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct TuiElement {
|
||||
query: Query,
|
||||
id: NodeId,
|
||||
}
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
use core::panic;
|
||||
|
||||
use dioxus_html::*;
|
||||
|
||||
use crate::element::TuiElement;
|
||||
|
||||
fn downcast(event: &PlatformEventData) -> plasmo::EventData {
|
||||
event
|
||||
.downcast::<plasmo::EventData>()
|
||||
.expect("event should be of type EventData")
|
||||
.clone()
|
||||
}
|
||||
|
||||
pub(crate) struct SerializedHtmlEventConverter;
|
||||
|
||||
impl HtmlEventConverter for SerializedHtmlEventConverter {
|
||||
fn convert_animation_data(&self, _: &PlatformEventData) -> AnimationData {
|
||||
panic!("animation events not supported")
|
||||
}
|
||||
|
||||
fn convert_clipboard_data(&self, _: &PlatformEventData) -> ClipboardData {
|
||||
panic!("clipboard events not supported")
|
||||
}
|
||||
|
||||
fn convert_composition_data(&self, _: &PlatformEventData) -> CompositionData {
|
||||
panic!("composition events not supported")
|
||||
}
|
||||
|
||||
fn convert_drag_data(&self, _: &PlatformEventData) -> DragData {
|
||||
panic!("drag events not supported")
|
||||
}
|
||||
|
||||
fn convert_focus_data(&self, event: &PlatformEventData) -> FocusData {
|
||||
if let plasmo::EventData::Focus(event) = downcast(event) {
|
||||
FocusData::new(event)
|
||||
} else {
|
||||
panic!("event should be of type Focus")
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_form_data(&self, event: &PlatformEventData) -> FormData {
|
||||
if let plasmo::EventData::Form(event) = downcast(event) {
|
||||
FormData::new(event)
|
||||
} else {
|
||||
panic!("event should be of type Form")
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_image_data(&self, _: &PlatformEventData) -> ImageData {
|
||||
panic!("image events not supported")
|
||||
}
|
||||
|
||||
fn convert_keyboard_data(&self, event: &PlatformEventData) -> KeyboardData {
|
||||
if let plasmo::EventData::Keyboard(event) = downcast(event) {
|
||||
KeyboardData::new(event)
|
||||
} else {
|
||||
panic!("event should be of type Keyboard")
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_media_data(&self, _: &PlatformEventData) -> MediaData {
|
||||
panic!("media events not supported")
|
||||
}
|
||||
|
||||
fn convert_mounted_data(&self, event: &PlatformEventData) -> MountedData {
|
||||
event.downcast::<TuiElement>().cloned().unwrap().into()
|
||||
}
|
||||
|
||||
fn convert_mouse_data(&self, event: &PlatformEventData) -> MouseData {
|
||||
if let plasmo::EventData::Mouse(event) = downcast(event) {
|
||||
MouseData::new(event)
|
||||
} else {
|
||||
panic!("event should be of type Mouse")
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_pointer_data(&self, _: &PlatformEventData) -> PointerData {
|
||||
panic!("pointer events not supported")
|
||||
}
|
||||
|
||||
fn convert_scroll_data(&self, _: &PlatformEventData) -> ScrollData {
|
||||
panic!("scroll events not supported")
|
||||
}
|
||||
|
||||
fn convert_selection_data(&self, _: &PlatformEventData) -> SelectionData {
|
||||
panic!("selection events not supported")
|
||||
}
|
||||
|
||||
fn convert_toggle_data(&self, _: &PlatformEventData) -> ToggleData {
|
||||
panic!("toggle events not supported")
|
||||
}
|
||||
|
||||
fn convert_touch_data(&self, _: &PlatformEventData) -> TouchData {
|
||||
panic!("touch events not supported")
|
||||
}
|
||||
|
||||
fn convert_transition_data(&self, _: &PlatformEventData) -> TransitionData {
|
||||
panic!("transition events not supported")
|
||||
}
|
||||
|
||||
fn convert_wheel_data(&self, event: &PlatformEventData) -> WheelData {
|
||||
if let plasmo::EventData::Wheel(event) = downcast(event) {
|
||||
WheelData::new(event)
|
||||
} else {
|
||||
panic!("event should be of type Wheel")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
mod element;
|
||||
mod events;
|
||||
|
||||
use std::{
|
||||
any::Any,
|
||||
@@ -8,6 +9,7 @@ use std::{
|
||||
};
|
||||
|
||||
use dioxus_core::{Component, ElementId, VirtualDom};
|
||||
use dioxus_html::PlatformEventData;
|
||||
use dioxus_native_core::dioxus::{DioxusState, NodeImmutableDioxusExt};
|
||||
use dioxus_native_core::prelude::*;
|
||||
|
||||
@@ -24,6 +26,8 @@ pub fn launch_cfg(app: Component<()>, cfg: Config) {
|
||||
}
|
||||
|
||||
pub fn launch_cfg_with_props<Props: 'static>(app: Component<Props>, props: Props, cfg: Config) {
|
||||
dioxus_html::set_event_converter(Box::new(events::SerializedHtmlEventConverter));
|
||||
|
||||
render(cfg, |rdom, taffy, event_tx| {
|
||||
let dioxus_state = {
|
||||
let mut rdom = rdom.write().unwrap();
|
||||
@@ -81,7 +85,7 @@ struct DioxusRenderer {
|
||||
vdom: VirtualDom,
|
||||
dioxus_state: Rc<RwLock<DioxusState>>,
|
||||
// Events that are queued up to be sent to the vdom next time the vdom is polled
|
||||
queued_events: Vec<(ElementId, &'static str, Rc<dyn Any>, bool)>,
|
||||
queued_events: Vec<(ElementId, &'static str, Box<dyn Any>, bool)>,
|
||||
#[cfg(all(feature = "hot-reload", debug_assertions))]
|
||||
hot_reload_rx: tokio::sync::mpsc::UnboundedReceiver<dioxus_hot_reload::HotReloadMsg>,
|
||||
}
|
||||
@@ -122,15 +126,19 @@ impl Driver for DioxusRenderer {
|
||||
let id = { rdom.read().unwrap().get(id).unwrap().mounted_id() };
|
||||
if let Some(id) = id {
|
||||
let inner_value = value.deref().clone();
|
||||
let boxed_event = Box::new(inner_value);
|
||||
let platform_event = PlatformEventData::new(boxed_event);
|
||||
self.vdom
|
||||
.handle_event(event, inner_value.into_any(), id, bubbles);
|
||||
.handle_event(event, Rc::new(platform_event), id, bubbles);
|
||||
}
|
||||
}
|
||||
|
||||
fn poll_async(&mut self) -> std::pin::Pin<Box<dyn futures::Future<Output = ()> + '_>> {
|
||||
// Add any queued events
|
||||
for (id, event, value, bubbles) in self.queued_events.drain(..) {
|
||||
self.vdom.handle_event(event, value, id, bubbles);
|
||||
let platform_event = PlatformEventData::new(value);
|
||||
self.vdom
|
||||
.handle_event(event, Rc::new(platform_event), id, bubbles);
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "hot-reload", debug_assertions))]
|
||||
|
||||
@@ -7,18 +7,29 @@ pub struct AnimationData {
|
||||
}
|
||||
|
||||
impl AnimationData {
|
||||
/// Create a new AnimationData
|
||||
pub fn new(inner: impl HasAnimationData + 'static) -> Self {
|
||||
Self {
|
||||
inner: Box::new(inner),
|
||||
}
|
||||
}
|
||||
|
||||
/// The name of the animation
|
||||
pub fn animation_name(&self) -> String {
|
||||
self.inner.animation_name()
|
||||
}
|
||||
|
||||
/// The name of the pseudo-element the animation runs on
|
||||
pub fn pseudo_element(&self) -> String {
|
||||
self.inner.pseudo_element()
|
||||
}
|
||||
|
||||
/// The amount of time the animation has been running
|
||||
pub fn elapsed_time(&self) -> f32 {
|
||||
self.inner.elapsed_time()
|
||||
}
|
||||
|
||||
/// Downcast this event to a concrete event type
|
||||
pub fn downcast<T: 'static>(&self) -> Option<&T> {
|
||||
self.inner.as_ref().as_any().downcast_ref::<T>()
|
||||
}
|
||||
|
||||
@@ -25,12 +25,14 @@ impl PartialEq for ClipboardData {
|
||||
}
|
||||
|
||||
impl ClipboardData {
|
||||
/// Create a new ClipboardData
|
||||
pub fn new(inner: impl HasClipboardData) -> Self {
|
||||
Self {
|
||||
inner: Box::new(inner),
|
||||
}
|
||||
}
|
||||
|
||||
/// Downcast this event to a concrete event type
|
||||
pub fn downcast<T: 'static>(&self) -> Option<&T> {
|
||||
self.inner.as_ref().as_any().downcast_ref::<T>()
|
||||
}
|
||||
|
||||
@@ -27,6 +27,14 @@ impl PartialEq for CompositionData {
|
||||
}
|
||||
|
||||
impl CompositionData {
|
||||
/// Create a new CompositionData
|
||||
pub fn new(inner: impl HasCompositionData + 'static) -> Self {
|
||||
Self {
|
||||
inner: Box::new(inner),
|
||||
}
|
||||
}
|
||||
|
||||
/// The characters generated by the input method that raised the event
|
||||
pub fn data(&self) -> String {
|
||||
self.inner.data()
|
||||
}
|
||||
|
||||
@@ -44,6 +44,13 @@ impl PartialEq for DragData {
|
||||
}
|
||||
|
||||
impl DragData {
|
||||
/// Create a new DragData
|
||||
pub fn new(inner: impl HasDragData + 'static) -> Self {
|
||||
Self {
|
||||
inner: Box::new(inner),
|
||||
}
|
||||
}
|
||||
|
||||
/// Downcast this event data to a specific type
|
||||
pub fn downcast<T: 'static>(&self) -> Option<&T> {
|
||||
self.inner.as_any().downcast_ref::<T>()
|
||||
|
||||
@@ -25,6 +25,13 @@ impl PartialEq for FocusData {
|
||||
}
|
||||
|
||||
impl FocusData {
|
||||
/// Create a new FocusData
|
||||
pub fn new(inner: impl HasFocusData + 'static) -> Self {
|
||||
Self {
|
||||
inner: Box::new(inner),
|
||||
}
|
||||
}
|
||||
|
||||
/// Downcast this event data to a specific type
|
||||
pub fn downcast<T: 'static>(&self) -> Option<&T> {
|
||||
self.inner.as_any().downcast_ref::<T>()
|
||||
|
||||
@@ -46,6 +46,13 @@ impl PartialEq for KeyboardData {
|
||||
}
|
||||
|
||||
impl KeyboardData {
|
||||
/// Create a new KeyboardData
|
||||
pub fn new(inner: impl HasKeyboardData + 'static) -> Self {
|
||||
Self {
|
||||
inner: Box::new(inner),
|
||||
}
|
||||
}
|
||||
|
||||
/// The value of the key pressed by the user, taking into consideration the state of modifier keys such as Shift as well as the keyboard locale and layout.
|
||||
pub fn key(&self) -> Key {
|
||||
self.inner.key()
|
||||
|
||||
@@ -24,6 +24,13 @@ impl PartialEq for MediaData {
|
||||
}
|
||||
|
||||
impl MediaData {
|
||||
/// Create a new MediaData
|
||||
pub fn new(inner: impl HasMediaData + 'static) -> Self {
|
||||
Self {
|
||||
inner: Box::new(inner),
|
||||
}
|
||||
}
|
||||
|
||||
/// Downcast this event to a concrete event type
|
||||
pub fn downcast<T: 'static>(&self) -> Option<&T> {
|
||||
self.inner.as_any().downcast_ref::<T>()
|
||||
|
||||
@@ -13,6 +13,13 @@ impl<E: HasScrollData> From<E> for ScrollData {
|
||||
}
|
||||
|
||||
impl ScrollData {
|
||||
/// Create a new ScrollData
|
||||
pub fn new(inner: impl HasScrollData + 'static) -> Self {
|
||||
Self {
|
||||
inner: Box::new(inner),
|
||||
}
|
||||
}
|
||||
|
||||
/// Downcast this event to a concrete event type
|
||||
pub fn downcast<T: 'static>(&self) -> Option<&T> {
|
||||
self.inner.as_any().downcast_ref::<T>()
|
||||
|
||||
@@ -7,6 +7,13 @@ pub struct SelectionData {
|
||||
}
|
||||
|
||||
impl SelectionData {
|
||||
/// Create a new SelectionData
|
||||
pub fn new(inner: impl HasSelectionData + 'static) -> Self {
|
||||
Self {
|
||||
inner: Box::new(inner),
|
||||
}
|
||||
}
|
||||
|
||||
/// Downcast this event to a concrete event type
|
||||
pub fn downcast<T: 'static>(&self) -> Option<&T> {
|
||||
self.inner.as_any().downcast_ref::<T>()
|
||||
|
||||
@@ -25,6 +25,13 @@ impl PartialEq for ToggleData {
|
||||
}
|
||||
|
||||
impl ToggleData {
|
||||
/// Create a new ToggleData
|
||||
pub fn new(inner: impl HasToggleData + 'static) -> Self {
|
||||
Self {
|
||||
inner: Box::new(inner),
|
||||
}
|
||||
}
|
||||
|
||||
/// Downcast this event to a concrete event type
|
||||
pub fn downcast<T: 'static>(&self) -> Option<&T> {
|
||||
self.inner.as_any().downcast_ref::<T>()
|
||||
|
||||
@@ -32,6 +32,13 @@ impl PartialEq for TouchData {
|
||||
}
|
||||
|
||||
impl TouchData {
|
||||
/// Create a new TouchData
|
||||
pub fn new(inner: impl HasTouchData + 'static) -> Self {
|
||||
Self {
|
||||
inner: Box::new(inner),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns true if the "ALT" key was down when the touch event was fired.
|
||||
pub fn alt_key(&self) -> bool {
|
||||
self.inner.alt_key()
|
||||
|
||||
@@ -31,6 +31,13 @@ impl PartialEq for TransitionData {
|
||||
}
|
||||
|
||||
impl TransitionData {
|
||||
/// Create a new TransitionData
|
||||
pub fn new(inner: impl HasTransitionData + 'static) -> Self {
|
||||
Self {
|
||||
inner: Box::new(inner),
|
||||
}
|
||||
}
|
||||
|
||||
/// Downcast this event to a concrete event type
|
||||
pub fn downcast<T: 'static>(&self) -> Option<&T> {
|
||||
self.inner.as_any().downcast_ref::<T>()
|
||||
|
||||
@@ -30,6 +30,13 @@ impl PartialEq for WheelData {
|
||||
}
|
||||
|
||||
impl WheelData {
|
||||
/// Create a new WheelData
|
||||
pub fn new(inner: impl HasWheelData + 'static) -> Self {
|
||||
Self {
|
||||
inner: Box::new(inner),
|
||||
}
|
||||
}
|
||||
|
||||
/// The amount of wheel movement
|
||||
#[allow(deprecated)]
|
||||
pub fn delta(&self) -> WheelDelta {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use dioxus_html::HasFormData;
|
||||
use dioxus_native_core::{
|
||||
prelude::*,
|
||||
real_dom::{NodeImmutable, NodeTypeMut},
|
||||
@@ -79,7 +80,7 @@ impl Driver for Counter {
|
||||
if event_type == "input" {
|
||||
// when the button is clicked, increment the counter
|
||||
if let EventData::Form(input_event) = &*event {
|
||||
if let Ok(value) = input_event.value.parse::<f64>() {
|
||||
if let Ok(value) = input_event.value().parse::<f64>() {
|
||||
self.count = value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,18 +57,18 @@ impl EventData {
|
||||
EventData::Keyboard(k) => Rc::new(k),
|
||||
EventData::Focus(f) => Rc::new(f),
|
||||
EventData::Wheel(w) => Rc::new(w),
|
||||
EventData::Form(f) => Rc::new(f.into_html()),
|
||||
EventData::Form(f) => Rc::new(f),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct FormData {
|
||||
pub value: String,
|
||||
pub(crate) value: String,
|
||||
|
||||
pub values: HashMap<String, Vec<String>>,
|
||||
pub(crate) values: HashMap<String, Vec<String>>,
|
||||
|
||||
pub files: Option<Files>,
|
||||
pub(crate) files: Option<Files>,
|
||||
}
|
||||
|
||||
impl HasFormData for FormData {
|
||||
@@ -85,12 +85,6 @@ impl HasFormData for FormData {
|
||||
}
|
||||
}
|
||||
|
||||
impl FormData {
|
||||
fn into_html(self) -> dioxus_html::FormData {
|
||||
dioxus_html::FormData::new(self)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct Files {
|
||||
files: FxHashMap<String, File>,
|
||||
|
||||
Reference in new issue
Block a user