Port widgets to the new system
This commit is contained in:
1 parent
c2b873c650
commit
efa7305794
18 files changed
+286
-240
No files matched your search
@@ -9,7 +9,7 @@ use shipyard::Component;
|
|||||||
use crate::{
|
use crate::{
|
||||||
node::{FromAnyValue, NodeType},
|
node::{FromAnyValue, NodeType},
|
||||||
node_ref::AttributeMask,
|
node_ref::AttributeMask,
|
||||||
prelude::{NodeImmutable, NodeMut, RealDom},
|
prelude::{NodeImmutable, NodeMut},
|
||||||
tree::TreeMut,
|
tree::TreeMut,
|
||||||
NodeId,
|
NodeId,
|
||||||
};
|
};
|
||||||
@@ -27,11 +27,15 @@ impl<V: FromAnyValue + Send + Sync> Default for CustomElementRegistry<V> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<V: FromAnyValue + Send + Sync> CustomElementRegistry<V> {
|
impl<V: FromAnyValue + Send + Sync> CustomElementRegistry<V> {
|
||||||
pub fn register<W: CustomElement<V>>(&mut self) {
|
pub fn register<F, U>(&mut self)
|
||||||
|
where
|
||||||
|
F: CustomElementFactory<U, V>,
|
||||||
|
U: CustomElementUpdater<V>,
|
||||||
|
{
|
||||||
self.builders.insert(
|
self.builders.insert(
|
||||||
(W::NAME, W::NAMESPACE),
|
(F::NAME, F::NAMESPACE),
|
||||||
CustomElementBuilder {
|
CustomElementBuilder {
|
||||||
create: |dom| Box::new(W::create(dom)),
|
create: |node| Box::new(F::create(node)),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -44,10 +48,7 @@ impl<V: FromAnyValue + Send + Sync> CustomElementRegistry<V> {
|
|||||||
};
|
};
|
||||||
if let Some((tag, ns)) = element_tag {
|
if let Some((tag, ns)) = element_tag {
|
||||||
if let Some(builder) = self.builders.get(&(tag.as_str(), ns.as_deref())) {
|
if let Some(builder) = self.builders.get(&(tag.as_str(), ns.as_deref())) {
|
||||||
let boxed_widget = {
|
let boxed_widget = { (builder.create)(node.reborrow()) };
|
||||||
let dom = node.real_dom_mut();
|
|
||||||
(builder.create)(dom)
|
|
||||||
};
|
|
||||||
|
|
||||||
let shadow_roots = boxed_widget.roots();
|
let shadow_roots = boxed_widget.roots();
|
||||||
|
|
||||||
@@ -69,7 +70,7 @@ impl<V: FromAnyValue + Send + Sync> CustomElementRegistry<V> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct CustomElementBuilder<V: FromAnyValue + Send + Sync> {
|
struct CustomElementBuilder<V: FromAnyValue + Send + Sync> {
|
||||||
create: fn(&mut RealDom<V>) -> Box<dyn CustomElementUpdater<V>>,
|
create: fn(NodeMut<V>) -> Box<dyn CustomElementUpdater<V>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A controlled element that renders to a shadow DOM
|
/// A controlled element that renders to a shadow DOM
|
||||||
@@ -81,7 +82,7 @@ pub trait CustomElement<V: FromAnyValue + Send + Sync = ()>: Send + Sync + 'stat
|
|||||||
const NAMESPACE: Option<&'static str> = None;
|
const NAMESPACE: Option<&'static str> = None;
|
||||||
|
|
||||||
/// Create a new widget *without mounting* it.
|
/// Create a new widget *without mounting* it.
|
||||||
fn create(dom: &mut RealDom<V>) -> Self;
|
fn create(node: NodeMut<V>) -> Self;
|
||||||
|
|
||||||
/// The root node of the widget. This must be static once the element is created.
|
/// The root node of the widget. This must be static once the element is created.
|
||||||
fn roots(&self) -> Vec<NodeId>;
|
fn roots(&self) -> Vec<NodeId>;
|
||||||
@@ -96,7 +97,7 @@ pub trait CustomElement<V: FromAnyValue + Send + Sync = ()>: Send + Sync + 'stat
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// A factory for creating widgets
|
/// A factory for creating widgets
|
||||||
trait ElementFactory<W: CustomElementUpdater<V>, V: FromAnyValue + Send + Sync = ()>:
|
pub trait CustomElementFactory<W: CustomElementUpdater<V>, V: FromAnyValue + Send + Sync = ()>:
|
||||||
Send + Sync + 'static
|
Send + Sync + 'static
|
||||||
{
|
{
|
||||||
/// The tag the widget is registered under.
|
/// The tag the widget is registered under.
|
||||||
@@ -106,21 +107,21 @@ trait ElementFactory<W: CustomElementUpdater<V>, V: FromAnyValue + Send + Sync =
|
|||||||
const NAMESPACE: Option<&'static str> = None;
|
const NAMESPACE: Option<&'static str> = None;
|
||||||
|
|
||||||
/// Create a new widget.
|
/// Create a new widget.
|
||||||
fn create(dom: &mut RealDom<V>) -> W;
|
fn create(dom: NodeMut<V>) -> W;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<W: CustomElement<V>, V: FromAnyValue + Send + Sync> ElementFactory<W, V> for W {
|
impl<W: CustomElement<V>, V: FromAnyValue + Send + Sync> CustomElementFactory<W, V> for W {
|
||||||
const NAME: &'static str = W::NAME;
|
const NAME: &'static str = W::NAME;
|
||||||
|
|
||||||
const NAMESPACE: Option<&'static str> = W::NAMESPACE;
|
const NAMESPACE: Option<&'static str> = W::NAMESPACE;
|
||||||
|
|
||||||
fn create(dom: &mut RealDom<V>) -> Self {
|
fn create(node: NodeMut<V>) -> Self {
|
||||||
Self::create(dom)
|
Self::create(node)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A trait for updating widgets
|
/// A trait for updating widgets
|
||||||
trait CustomElementUpdater<V: FromAnyValue + Send + Sync = ()>: Send + Sync + 'static {
|
pub trait CustomElementUpdater<V: FromAnyValue + Send + Sync = ()>: Send + Sync + 'static {
|
||||||
/// Called when the attributes of the widget are changed.
|
/// Called when the attributes of the widget are changed.
|
||||||
fn attributes_changed(&mut self, light_root: NodeMut<V>, attributes: &AttributeMask);
|
fn attributes_changed(&mut self, light_root: NodeMut<V>, attributes: &AttributeMask);
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,10 @@ use std::collections::VecDeque;
|
|||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
use std::sync::{Arc, RwLock};
|
use std::sync::{Arc, RwLock};
|
||||||
|
|
||||||
use crate::custom_element::{CustomElement, CustomElementManager, CustomElementRegistry};
|
use crate::custom_element::{
|
||||||
|
CustomElement, CustomElementFactory, CustomElementManager, CustomElementRegistry,
|
||||||
|
CustomElementUpdater,
|
||||||
|
};
|
||||||
use crate::node::{
|
use crate::node::{
|
||||||
ElementNode, FromAnyValue, NodeType, OwnedAttributeDiscription, OwnedAttributeValue, TextNode,
|
ElementNode, FromAnyValue, NodeType, OwnedAttributeDiscription, OwnedAttributeValue, TextNode,
|
||||||
};
|
};
|
||||||
@@ -478,7 +481,16 @@ impl<V: FromAnyValue + Send + Sync> RealDom<V> {
|
|||||||
|
|
||||||
/// Registers a new custom element.
|
/// Registers a new custom element.
|
||||||
pub fn register_custom_element<E: CustomElement<V>>(&mut self) {
|
pub fn register_custom_element<E: CustomElement<V>>(&mut self) {
|
||||||
self.custom_elements.write().unwrap().register::<E>()
|
self.register_custom_element_factory::<E, E>()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Registers a new custom element with a custom factory.
|
||||||
|
pub fn register_custom_element_factory<F, U>(&mut self)
|
||||||
|
where
|
||||||
|
F: CustomElementFactory<U, V>,
|
||||||
|
U: CustomElementUpdater<V>,
|
||||||
|
{
|
||||||
|
self.custom_elements.write().unwrap().register::<F, U>()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -678,6 +690,14 @@ impl<'a, V: FromAnyValue + Send + Sync> NodeImmutable<V> for NodeMut<'a, V> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, V: FromAnyValue + Send + Sync> NodeMut<'a, V> {
|
impl<'a, V: FromAnyValue + Send + Sync> NodeMut<'a, V> {
|
||||||
|
/// Reborrow the node mutably
|
||||||
|
pub fn reborrow(&mut self) -> NodeMut<'_, V> {
|
||||||
|
NodeMut {
|
||||||
|
id: self.id,
|
||||||
|
dom: self.dom,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Get the real dom this node was created in mutably
|
/// Get the real dom this node was created in mutably
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn real_dom_mut(&mut self) -> &mut RealDom<V> {
|
pub fn real_dom_mut(&mut self) -> &mut RealDom<V> {
|
||||||
|
|||||||
@@ -179,7 +179,8 @@ struct CustomElementWithSlot {
|
|||||||
impl CustomElement for CustomElementWithSlot {
|
impl CustomElement for CustomElementWithSlot {
|
||||||
const NAME: &'static str = "customelementslot";
|
const NAME: &'static str = "customelementslot";
|
||||||
|
|
||||||
fn create(dom: &mut RealDom<()>) -> Self {
|
fn create(mut node: NodeMut<()>) -> Self {
|
||||||
|
let dom = node.real_dom_mut();
|
||||||
let child = dom.create_node(ElementNode {
|
let child = dom.create_node(ElementNode {
|
||||||
tag: "div".into(),
|
tag: "div".into(),
|
||||||
namespace: None,
|
namespace: None,
|
||||||
@@ -227,7 +228,8 @@ struct CustomElementWithNoSlot {
|
|||||||
impl CustomElement for CustomElementWithNoSlot {
|
impl CustomElement for CustomElementWithNoSlot {
|
||||||
const NAME: &'static str = "customelementnoslot";
|
const NAME: &'static str = "customelementnoslot";
|
||||||
|
|
||||||
fn create(dom: &mut RealDom<()>) -> Self {
|
fn create(mut node: NodeMut<()>) -> Self {
|
||||||
|
let dom = node.real_dom_mut();
|
||||||
let root = dom.create_node(ElementNode {
|
let root = dom.create_node(ElementNode {
|
||||||
tag: "div".into(),
|
tag: "div".into(),
|
||||||
namespace: None,
|
namespace: None,
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ impl Driver for Counter {
|
|||||||
_: bool,
|
_: bool,
|
||||||
) {
|
) {
|
||||||
match event_type {
|
match event_type {
|
||||||
"oninput" => {
|
"input" => {
|
||||||
// when the button is clicked, increment the counter
|
// when the button is clicked, increment the counter
|
||||||
if let EventData::Form(input_event) = &*event {
|
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>() {
|
||||||
|
|||||||
@@ -183,7 +183,7 @@ impl FocusState {
|
|||||||
|
|
||||||
if forward {
|
if forward {
|
||||||
// find the closest focusable element after the current level
|
// find the closest focusable element after the current level
|
||||||
rdom.traverse_depth_first(|n| {
|
rdom.traverse_depth_first(true, |n| {
|
||||||
let node_level = n.get::<Focus>().unwrap().level;
|
let node_level = n.get::<Focus>().unwrap().level;
|
||||||
if node_level != *focus_level
|
if node_level != *focus_level
|
||||||
&& node_level.focusable()
|
&& node_level.focusable()
|
||||||
@@ -200,7 +200,7 @@ impl FocusState {
|
|||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
// find the closest focusable element before the current level
|
// find the closest focusable element before the current level
|
||||||
rdom.traverse_depth_first(|n| {
|
rdom.traverse_depth_first(true, |n| {
|
||||||
let node_level = n.get::<Focus>().unwrap().level;
|
let node_level = n.get::<Focus>().unwrap().level;
|
||||||
if node_level != *focus_level
|
if node_level != *focus_level
|
||||||
&& node_level.focusable()
|
&& node_level.focusable()
|
||||||
|
|||||||
+12
-30
@@ -25,7 +25,7 @@ use taffy::{prelude::Layout, Taffy};
|
|||||||
|
|
||||||
use crate::focus::{Focus, Focused};
|
use crate::focus::{Focus, Focused};
|
||||||
use crate::layout::TaffyLayout;
|
use crate::layout::TaffyLayout;
|
||||||
use crate::{layout_to_screen_space, FocusState};
|
use crate::{get_abs_layout, layout_to_screen_space, FocusState};
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct Event {
|
pub struct Event {
|
||||||
@@ -323,7 +323,7 @@ impl InnerInputState {
|
|||||||
if old_pos != Some(new_pos) {
|
if old_pos != Some(new_pos) {
|
||||||
let mut will_bubble = FxHashSet::default();
|
let mut will_bubble = FxHashSet::default();
|
||||||
for node in dom.get_listening_sorted("mousemove") {
|
for node in dom.get_listening_sorted("mousemove") {
|
||||||
let node_layout = get_abs_layout(node, dom, layout);
|
let node_layout = get_abs_layout(node, layout);
|
||||||
let previously_contained = old_pos
|
let previously_contained = old_pos
|
||||||
.filter(|pos| layout_contains_point(&node_layout, *pos))
|
.filter(|pos| layout_contains_point(&node_layout, *pos))
|
||||||
.is_some();
|
.is_some();
|
||||||
@@ -347,7 +347,7 @@ impl InnerInputState {
|
|||||||
// mouseenter
|
// mouseenter
|
||||||
let mut will_bubble = FxHashSet::default();
|
let mut will_bubble = FxHashSet::default();
|
||||||
for node in dom.get_listening_sorted("mouseenter") {
|
for node in dom.get_listening_sorted("mouseenter") {
|
||||||
let node_layout = get_abs_layout(node, dom, layout);
|
let node_layout = get_abs_layout(node, layout);
|
||||||
let previously_contained = old_pos
|
let previously_contained = old_pos
|
||||||
.filter(|pos| layout_contains_point(&node_layout, *pos))
|
.filter(|pos| layout_contains_point(&node_layout, *pos))
|
||||||
.is_some();
|
.is_some();
|
||||||
@@ -370,7 +370,7 @@ impl InnerInputState {
|
|||||||
// mouseover
|
// mouseover
|
||||||
let mut will_bubble = FxHashSet::default();
|
let mut will_bubble = FxHashSet::default();
|
||||||
for node in dom.get_listening_sorted("mouseover") {
|
for node in dom.get_listening_sorted("mouseover") {
|
||||||
let node_layout = get_abs_layout(node, dom, layout);
|
let node_layout = get_abs_layout(node, layout);
|
||||||
let previously_contained = old_pos
|
let previously_contained = old_pos
|
||||||
.filter(|pos| layout_contains_point(&node_layout, *pos))
|
.filter(|pos| layout_contains_point(&node_layout, *pos))
|
||||||
.is_some();
|
.is_some();
|
||||||
@@ -393,7 +393,7 @@ impl InnerInputState {
|
|||||||
if was_pressed {
|
if was_pressed {
|
||||||
let mut will_bubble = FxHashSet::default();
|
let mut will_bubble = FxHashSet::default();
|
||||||
for node in dom.get_listening_sorted("mousedown") {
|
for node in dom.get_listening_sorted("mousedown") {
|
||||||
let node_layout = get_abs_layout(node, dom, layout);
|
let node_layout = get_abs_layout(node, layout);
|
||||||
let currently_contains = layout_contains_point(&node_layout, new_pos);
|
let currently_contains = layout_contains_point(&node_layout, new_pos);
|
||||||
|
|
||||||
if currently_contains {
|
if currently_contains {
|
||||||
@@ -414,7 +414,7 @@ impl InnerInputState {
|
|||||||
if was_released {
|
if was_released {
|
||||||
let mut will_bubble = FxHashSet::default();
|
let mut will_bubble = FxHashSet::default();
|
||||||
for node in dom.get_listening_sorted("mouseup") {
|
for node in dom.get_listening_sorted("mouseup") {
|
||||||
let node_layout = get_abs_layout(node, dom, layout);
|
let node_layout = get_abs_layout(node, layout);
|
||||||
let currently_contains = layout_contains_point(&node_layout, new_pos);
|
let currently_contains = layout_contains_point(&node_layout, new_pos);
|
||||||
|
|
||||||
if currently_contains {
|
if currently_contains {
|
||||||
@@ -436,7 +436,7 @@ impl InnerInputState {
|
|||||||
if mouse_data.trigger_button() == Some(DioxusMouseButton::Primary) && was_released {
|
if mouse_data.trigger_button() == Some(DioxusMouseButton::Primary) && was_released {
|
||||||
let mut will_bubble = FxHashSet::default();
|
let mut will_bubble = FxHashSet::default();
|
||||||
for node in dom.get_listening_sorted("click") {
|
for node in dom.get_listening_sorted("click") {
|
||||||
let node_layout = get_abs_layout(node, dom, layout);
|
let node_layout = get_abs_layout(node, layout);
|
||||||
let currently_contains = layout_contains_point(&node_layout, new_pos);
|
let currently_contains = layout_contains_point(&node_layout, new_pos);
|
||||||
|
|
||||||
if currently_contains {
|
if currently_contains {
|
||||||
@@ -459,7 +459,7 @@ impl InnerInputState {
|
|||||||
{
|
{
|
||||||
let mut will_bubble = FxHashSet::default();
|
let mut will_bubble = FxHashSet::default();
|
||||||
for node in dom.get_listening_sorted("contextmenu") {
|
for node in dom.get_listening_sorted("contextmenu") {
|
||||||
let node_layout = get_abs_layout(node, dom, layout);
|
let node_layout = get_abs_layout(node, layout);
|
||||||
let currently_contains = layout_contains_point(&node_layout, new_pos);
|
let currently_contains = layout_contains_point(&node_layout, new_pos);
|
||||||
|
|
||||||
if currently_contains {
|
if currently_contains {
|
||||||
@@ -482,7 +482,7 @@ impl InnerInputState {
|
|||||||
if was_scrolled {
|
if was_scrolled {
|
||||||
let mut will_bubble = FxHashSet::default();
|
let mut will_bubble = FxHashSet::default();
|
||||||
for node in dom.get_listening_sorted("wheel") {
|
for node in dom.get_listening_sorted("wheel") {
|
||||||
let node_layout = get_abs_layout(node, dom, layout);
|
let node_layout = get_abs_layout(node, layout);
|
||||||
|
|
||||||
let currently_contains = layout_contains_point(&node_layout, new_pos);
|
let currently_contains = layout_contains_point(&node_layout, new_pos);
|
||||||
|
|
||||||
@@ -505,7 +505,7 @@ impl InnerInputState {
|
|||||||
// mouseleave
|
// mouseleave
|
||||||
let mut will_bubble = FxHashSet::default();
|
let mut will_bubble = FxHashSet::default();
|
||||||
for node in dom.get_listening_sorted("mouseleave") {
|
for node in dom.get_listening_sorted("mouseleave") {
|
||||||
let node_layout = get_abs_layout(node, dom, layout);
|
let node_layout = get_abs_layout(node, layout);
|
||||||
let previously_contained = old_pos
|
let previously_contained = old_pos
|
||||||
.filter(|pos| layout_contains_point(&node_layout, *pos))
|
.filter(|pos| layout_contains_point(&node_layout, *pos))
|
||||||
.is_some();
|
.is_some();
|
||||||
@@ -528,7 +528,7 @@ impl InnerInputState {
|
|||||||
// mouseout
|
// mouseout
|
||||||
let mut will_bubble = FxHashSet::default();
|
let mut will_bubble = FxHashSet::default();
|
||||||
for node in dom.get_listening_sorted("mouseout") {
|
for node in dom.get_listening_sorted("mouseout") {
|
||||||
let node_layout = get_abs_layout(node, dom, layout);
|
let node_layout = get_abs_layout(node, layout);
|
||||||
let previously_contained = old_pos
|
let previously_contained = old_pos
|
||||||
.filter(|pos| layout_contains_point(&node_layout, *pos))
|
.filter(|pos| layout_contains_point(&node_layout, *pos))
|
||||||
.is_some();
|
.is_some();
|
||||||
@@ -550,7 +550,7 @@ impl InnerInputState {
|
|||||||
// update focus
|
// update focus
|
||||||
if was_released {
|
if was_released {
|
||||||
let mut focus_id = None;
|
let mut focus_id = None;
|
||||||
dom.traverse_depth_first(|node| {
|
dom.traverse_depth_first(true, |node| {
|
||||||
let node_layout = layout
|
let node_layout = layout
|
||||||
.layout(node.get::<TaffyLayout>().unwrap().node.unwrap())
|
.layout(node.get::<TaffyLayout>().unwrap().node.unwrap())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@@ -572,24 +572,6 @@ impl InnerInputState {
|
|||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_abs_layout(node: NodeRef, dom: &RealDom, taffy: &Taffy) -> Layout {
|
|
||||||
let mut node_layout = *taffy
|
|
||||||
.layout(node.get::<TaffyLayout>().unwrap().node.unwrap())
|
|
||||||
.unwrap();
|
|
||||||
let mut current = node;
|
|
||||||
|
|
||||||
while let Some(parent) = current.parent_id() {
|
|
||||||
let parent = dom.get(parent).unwrap();
|
|
||||||
current = parent;
|
|
||||||
let parent_layout = taffy
|
|
||||||
.layout(parent.get::<TaffyLayout>().unwrap().node.unwrap())
|
|
||||||
.unwrap();
|
|
||||||
node_layout.location.x += parent_layout.location.x;
|
|
||||||
node_layout.location.y += parent_layout.location.y;
|
|
||||||
}
|
|
||||||
node_layout
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct RinkInputHandler {
|
pub struct RinkInputHandler {
|
||||||
state: Rc<RefCell<InnerInputState>>,
|
state: Rc<RefCell<InnerInputState>>,
|
||||||
queued_events: Rc<RefCell<Vec<EventCore>>>,
|
queued_events: Rc<RefCell<Vec<EventCore>>>,
|
||||||
|
|||||||
@@ -25,12 +25,6 @@ impl<T> PossiblyUninitalized<T> {
|
|||||||
_ => panic!("uninitalized"),
|
_ => panic!("uninitalized"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn ok(self) -> Option<T> {
|
|
||||||
match self {
|
|
||||||
Self::Initialized(i) => Some(i),
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
impl<T> Default for PossiblyUninitalized<T> {
|
impl<T> Default for PossiblyUninitalized<T> {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
@@ -54,6 +48,9 @@ impl State for TaffyLayout {
|
|||||||
.with_attrs(AttributeMaskBuilder::Some(SORTED_LAYOUT_ATTRS))
|
.with_attrs(AttributeMaskBuilder::Some(SORTED_LAYOUT_ATTRS))
|
||||||
.with_text();
|
.with_text();
|
||||||
|
|
||||||
|
// The layout state should be effected by the shadow dom
|
||||||
|
const TRAVERSE_SHADOW_DOM: bool = true;
|
||||||
|
|
||||||
fn update<'a>(
|
fn update<'a>(
|
||||||
&mut self,
|
&mut self,
|
||||||
node_view: NodeView,
|
node_view: NodeView,
|
||||||
|
|||||||
+41
-10
@@ -6,7 +6,7 @@ use crossterm::{
|
|||||||
execute,
|
execute,
|
||||||
terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
|
terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
|
||||||
};
|
};
|
||||||
use dioxus_native_core::prelude::*;
|
use dioxus_native_core::{prelude::*, tree::TreeRef};
|
||||||
use dioxus_native_core::{real_dom::RealDom, FxDashSet, NodeId, SendAnyMap};
|
use dioxus_native_core::{real_dom::RealDom, FxDashSet, NodeId, SendAnyMap};
|
||||||
use focus::FocusState;
|
use focus::FocusState;
|
||||||
use futures::{channel::mpsc::UnboundedSender, pin_mut, Future, StreamExt};
|
use futures::{channel::mpsc::UnboundedSender, pin_mut, Future, StreamExt};
|
||||||
@@ -262,7 +262,7 @@ pub fn render<R: Driver>(
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
Some(evt) = event_reciever.next() => {
|
Some(evt) = event_reciever.next() => {
|
||||||
event_recieved=Some(evt);
|
event_recieved = Some(evt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -342,19 +342,50 @@ pub trait Driver {
|
|||||||
/// Before sending the event to drivers, we need to bubble it up the tree to any widgets that are listening
|
/// Before sending the event to drivers, we need to bubble it up the tree to any widgets that are listening
|
||||||
fn bubble_event_to_widgets(rdom: &mut RealDom, event: &Event) {
|
fn bubble_event_to_widgets(rdom: &mut RealDom, event: &Event) {
|
||||||
let id = event.id;
|
let id = event.id;
|
||||||
let mut node = Some(rdom.get_mut(id).unwrap());
|
let mut node = Some(id);
|
||||||
|
|
||||||
|
while let Some(node_id) = node {
|
||||||
|
let parent_id = {
|
||||||
|
let tree = rdom.tree_ref();
|
||||||
|
tree.parent_id_advanced(node_id, true)
|
||||||
|
};
|
||||||
|
|
||||||
while let Some(mut node_mut) = node {
|
|
||||||
let parent_id = node_mut.parent_id();
|
|
||||||
if let Some(mut widget) = node_mut
|
|
||||||
.get_mut::<RinkWidgetTraitObject>()
|
|
||||||
.map(|w| w.clone())
|
|
||||||
{
|
{
|
||||||
widget.handle_event(event, &mut node_mut)
|
// println!("@ bubbling event to node {:?}", node_id);
|
||||||
|
let mut node_mut = rdom.get_mut(node_id).unwrap();
|
||||||
|
if let Some(mut widget) = node_mut
|
||||||
|
.get_mut::<RinkWidgetTraitObject>()
|
||||||
|
.map(|w| w.clone())
|
||||||
|
{
|
||||||
|
widget.handle_event(event, node_mut)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !event.bubbles {
|
if !event.bubbles {
|
||||||
|
// println!("event does not bubble");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
node = parent_id.map(|id| rdom.get_mut(id).unwrap());
|
node = parent_id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn get_abs_layout(node: NodeRef, taffy: &Taffy) -> Layout {
|
||||||
|
let mut node_layout = *taffy
|
||||||
|
.layout(node.get::<TaffyLayout>().unwrap().node.unwrap())
|
||||||
|
.unwrap();
|
||||||
|
let mut current = node;
|
||||||
|
|
||||||
|
let dom = node.real_dom();
|
||||||
|
let tree = dom.tree_ref();
|
||||||
|
|
||||||
|
while let Some(parent) = tree.parent_id_advanced(current.id(), true) {
|
||||||
|
let parent = dom.get(parent).unwrap();
|
||||||
|
current = parent;
|
||||||
|
let parent_layout = taffy
|
||||||
|
.layout(parent.get::<TaffyLayout>().unwrap().node.unwrap())
|
||||||
|
.unwrap();
|
||||||
|
node_layout.location.x += parent_layout.location.x;
|
||||||
|
node_layout.location.y += parent_layout.location.y;
|
||||||
|
}
|
||||||
|
node_layout
|
||||||
|
}
|
||||||
@@ -8,7 +8,7 @@ use taffy::{
|
|||||||
Taffy,
|
Taffy,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{layout::TaffyLayout, layout_to_screen_space};
|
use crate::{get_abs_layout, layout_to_screen_space};
|
||||||
|
|
||||||
/// Allows querying the layout of nodes after rendering. It will only provide a correct value after a node is rendered.
|
/// Allows querying the layout of nodes after rendering. It will only provide a correct value after a node is rendered.
|
||||||
/// Provided as a root context for all tui applictions.
|
/// Provided as a root context for all tui applictions.
|
||||||
@@ -95,21 +95,8 @@ impl<'a> ElementRef<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn get_layout(node: NodeRef, stretch: &Taffy) -> Option<Layout> {
|
pub(crate) fn get_layout(node: NodeRef, stretch: &Taffy) -> Option<Layout> {
|
||||||
let layout = stretch
|
let layout = get_abs_layout(node, stretch);
|
||||||
.layout(node.get::<TaffyLayout>().unwrap().node.ok()?)
|
let pos = layout.location;
|
||||||
.ok()?;
|
|
||||||
|
|
||||||
let mut current_node_id = node.parent_id();
|
|
||||||
let mut pos = layout.location;
|
|
||||||
let rdom = node.real_dom();
|
|
||||||
while let Some(node) = current_node_id.and_then(|id| rdom.get(id)) {
|
|
||||||
let current_layout = stretch
|
|
||||||
.layout(node.get::<TaffyLayout>().unwrap().node.ok()?)
|
|
||||||
.ok()?;
|
|
||||||
pos.x += current_layout.location.x;
|
|
||||||
pos.y += current_layout.location.y;
|
|
||||||
current_node_id = node.parent_id();
|
|
||||||
}
|
|
||||||
|
|
||||||
Some(Layout {
|
Some(Layout {
|
||||||
order: layout.order,
|
order: layout.order,
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use dioxus_native_core::prelude::*;
|
use dioxus_native_core::{prelude::*, tree::TreeRef};
|
||||||
use std::io::Stdout;
|
use std::io::Stdout;
|
||||||
use taffy::{
|
use taffy::{
|
||||||
geometry::Point,
|
geometry::Point,
|
||||||
@@ -83,7 +83,10 @@ pub(crate) fn render_vnode(
|
|||||||
frame.render_widget(WidgetWithContext::new(node, cfg), area);
|
frame.render_widget(WidgetWithContext::new(node, cfg), area);
|
||||||
}
|
}
|
||||||
|
|
||||||
for c in node.children() {
|
let node_id = node.id();
|
||||||
|
let rdom = node.real_dom();
|
||||||
|
for child_id in rdom.tree_ref().children_ids_advanced(node_id, true) {
|
||||||
|
let c = rdom.get(child_id).unwrap();
|
||||||
render_vnode(frame, layout, c, cfg, location);
|
render_vnode(frame, layout, c, cfg, location);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,14 +2,14 @@ use std::collections::HashMap;
|
|||||||
|
|
||||||
use dioxus_html::input_data::keyboard_types::Key;
|
use dioxus_html::input_data::keyboard_types::Key;
|
||||||
use dioxus_native_core::{
|
use dioxus_native_core::{
|
||||||
|
custom_element::CustomElement,
|
||||||
node::OwnedAttributeDiscription,
|
node::OwnedAttributeDiscription,
|
||||||
node_ref::AttributeMask,
|
node_ref::AttributeMask,
|
||||||
prelude::NodeType,
|
prelude::NodeType,
|
||||||
real_dom::{ElementNodeMut, NodeImmutable, NodeTypeMut, RealDom},
|
real_dom::{ElementNodeMut, NodeImmutable, NodeMut, NodeTypeMut, RealDom},
|
||||||
utils::widget_watcher::Widget,
|
|
||||||
NodeId,
|
NodeId,
|
||||||
};
|
};
|
||||||
use shipyard::UniqueViewMut;
|
use shipyard::UniqueView;
|
||||||
|
|
||||||
use crate::FormData;
|
use crate::FormData;
|
||||||
|
|
||||||
@@ -17,7 +17,6 @@ use super::{RinkWidget, WidgetContext};
|
|||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub(crate) struct Button {
|
pub(crate) struct Button {
|
||||||
div_id: NodeId,
|
|
||||||
text_id: NodeId,
|
text_id: NodeId,
|
||||||
value: String,
|
value: String,
|
||||||
}
|
}
|
||||||
@@ -88,14 +87,14 @@ impl Button {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn switch(&mut self, ctx: &mut WidgetContext) {
|
fn switch(&mut self, ctx: &mut WidgetContext, node: NodeMut) {
|
||||||
let data = FormData {
|
let data = FormData {
|
||||||
value: self.value.to_string(),
|
value: self.value.to_string(),
|
||||||
values: HashMap::new(),
|
values: HashMap::new(),
|
||||||
files: None,
|
files: None,
|
||||||
};
|
};
|
||||||
ctx.send(crate::Event {
|
ctx.send(crate::Event {
|
||||||
id: self.div_id,
|
id: node.id(),
|
||||||
name: "input",
|
name: "input",
|
||||||
data: crate::EventData::Form(data),
|
data: crate::EventData::Form(data),
|
||||||
bubbles: true,
|
bubbles: true,
|
||||||
@@ -103,10 +102,14 @@ impl Button {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Widget for Button {
|
impl CustomElement for Button {
|
||||||
const NAME: &'static str = "input";
|
const NAME: &'static str = "input";
|
||||||
|
|
||||||
fn create(root: &mut dioxus_native_core::real_dom::NodeMut<()>) -> Self {
|
fn roots(&self) -> Vec<NodeId> {
|
||||||
|
vec![self.text_id]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create(mut root: dioxus_native_core::real_dom::NodeMut) -> Self {
|
||||||
let node_type = root.node_type();
|
let node_type = root.node_type();
|
||||||
let NodeType::Element(el) = &*node_type else { panic!("input must be an element") };
|
let NodeType::Element(el) = &*node_type else { panic!("input must be an element") };
|
||||||
|
|
||||||
@@ -127,11 +130,8 @@ impl Widget for Button {
|
|||||||
|
|
||||||
root.add_event_listener("keydown");
|
root.add_event_listener("keydown");
|
||||||
root.add_event_listener("click");
|
root.add_event_listener("click");
|
||||||
let div_id = root.id();
|
|
||||||
root.add_child(text_id);
|
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
div_id,
|
|
||||||
text_id,
|
text_id,
|
||||||
value: value.unwrap_or_default(),
|
value: value.unwrap_or_default(),
|
||||||
}
|
}
|
||||||
@@ -139,7 +139,7 @@ impl Widget for Button {
|
|||||||
|
|
||||||
fn attributes_changed(
|
fn attributes_changed(
|
||||||
&mut self,
|
&mut self,
|
||||||
mut root: dioxus_native_core::real_dom::NodeMut<()>,
|
mut root: dioxus_native_core::real_dom::NodeMut,
|
||||||
attributes: &dioxus_native_core::node_ref::AttributeMask,
|
attributes: &dioxus_native_core::node_ref::AttributeMask,
|
||||||
) {
|
) {
|
||||||
match attributes {
|
match attributes {
|
||||||
@@ -175,16 +175,18 @@ impl RinkWidget for Button {
|
|||||||
fn handle_event(
|
fn handle_event(
|
||||||
&mut self,
|
&mut self,
|
||||||
event: &crate::Event,
|
event: &crate::Event,
|
||||||
node: &mut dioxus_native_core::real_dom::NodeMut,
|
mut node: dioxus_native_core::real_dom::NodeMut,
|
||||||
) {
|
) {
|
||||||
let mut ctx: UniqueViewMut<WidgetContext> = node
|
let mut ctx: WidgetContext = {
|
||||||
.real_dom_mut()
|
node.real_dom_mut()
|
||||||
.raw_world_mut()
|
.raw_world_mut()
|
||||||
.borrow()
|
.borrow::<UniqueView<WidgetContext>>()
|
||||||
.expect("expected widget context");
|
.expect("expected widget context")
|
||||||
|
.clone()
|
||||||
|
};
|
||||||
|
|
||||||
match event.name {
|
match event.name {
|
||||||
"click" => self.switch(&mut ctx),
|
"click" => self.switch(&mut ctx, node),
|
||||||
"keydown" => {
|
"keydown" => {
|
||||||
if let crate::EventData::Keyboard(data) = &event.data {
|
if let crate::EventData::Keyboard(data) = &event.data {
|
||||||
if !data.is_auto_repeating()
|
if !data.is_auto_repeating()
|
||||||
@@ -194,7 +196,7 @@ impl RinkWidget for Button {
|
|||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
self.switch(&mut ctx);
|
self.switch(&mut ctx, node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,11 +2,11 @@ use std::collections::HashMap;
|
|||||||
|
|
||||||
use dioxus_html::input_data::keyboard_types::Key;
|
use dioxus_html::input_data::keyboard_types::Key;
|
||||||
use dioxus_native_core::{
|
use dioxus_native_core::{
|
||||||
|
custom_element::CustomElement,
|
||||||
node::OwnedAttributeDiscription,
|
node::OwnedAttributeDiscription,
|
||||||
node_ref::AttributeMask,
|
node_ref::AttributeMask,
|
||||||
prelude::NodeType,
|
prelude::NodeType,
|
||||||
real_dom::{ElementNodeMut, NodeImmutable, NodeMut, NodeTypeMut},
|
real_dom::{ElementNodeMut, NodeImmutable, NodeMut, NodeTypeMut},
|
||||||
utils::widget_watcher::Widget,
|
|
||||||
NodeId,
|
NodeId,
|
||||||
};
|
};
|
||||||
use shipyard::UniqueView;
|
use shipyard::UniqueView;
|
||||||
@@ -91,7 +91,7 @@ impl CheckBox {
|
|||||||
== "true";
|
== "true";
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_value(&self, root: &mut NodeMut) {
|
fn write_value(&self, mut root: NodeMut) {
|
||||||
let single_char = {
|
let single_char = {
|
||||||
let node_type = root.node_type_mut();
|
let node_type = root.node_type_mut();
|
||||||
let NodeTypeMut::Element( el) = node_type else { panic!("input must be an element") };
|
let NodeTypeMut::Element( el) = node_type else { panic!("input must be an element") };
|
||||||
@@ -117,7 +117,7 @@ impl CheckBox {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn switch(&mut self, node: &mut NodeMut) {
|
fn switch(&mut self, mut node: NodeMut) {
|
||||||
let new_state = !self.checked;
|
let new_state = !self.checked;
|
||||||
|
|
||||||
let data = FormData {
|
let data = FormData {
|
||||||
@@ -147,10 +147,14 @@ impl CheckBox {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Widget for CheckBox {
|
impl CustomElement for CheckBox {
|
||||||
const NAME: &'static str = "input";
|
const NAME: &'static str = "input";
|
||||||
|
|
||||||
fn create(root: &mut dioxus_native_core::real_dom::NodeMut<()>) -> Self {
|
fn roots(&self) -> Vec<NodeId> {
|
||||||
|
vec![self.text_id]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create(mut root: dioxus_native_core::real_dom::NodeMut) -> Self {
|
||||||
let node_type = root.node_type();
|
let node_type = root.node_type();
|
||||||
let NodeType::Element(el) = &*node_type else { panic!("input must be an element") };
|
let NodeType::Element(el) = &*node_type else { panic!("input must be an element") };
|
||||||
|
|
||||||
@@ -172,7 +176,6 @@ impl Widget for CheckBox {
|
|||||||
root.add_event_listener("click");
|
root.add_event_listener("click");
|
||||||
root.add_event_listener("keydown");
|
root.add_event_listener("keydown");
|
||||||
let div_id = root.id();
|
let div_id = root.id();
|
||||||
root.add_child(text_id);
|
|
||||||
|
|
||||||
let myself = Self {
|
let myself = Self {
|
||||||
div_id,
|
div_id,
|
||||||
@@ -187,7 +190,7 @@ impl Widget for CheckBox {
|
|||||||
|
|
||||||
fn attributes_changed(
|
fn attributes_changed(
|
||||||
&mut self,
|
&mut self,
|
||||||
mut root: dioxus_native_core::real_dom::NodeMut<()>,
|
mut root: dioxus_native_core::real_dom::NodeMut,
|
||||||
attributes: &dioxus_native_core::node_ref::AttributeMask,
|
attributes: &dioxus_native_core::node_ref::AttributeMask,
|
||||||
) {
|
) {
|
||||||
match attributes {
|
match attributes {
|
||||||
@@ -199,7 +202,7 @@ impl Widget for CheckBox {
|
|||||||
self.update_size_attr(&mut el);
|
self.update_size_attr(&mut el);
|
||||||
self.update_checked_attr(&el);
|
self.update_checked_attr(&el);
|
||||||
}
|
}
|
||||||
self.write_value(&mut root);
|
self.write_value(root);
|
||||||
}
|
}
|
||||||
AttributeMask::Some(attrs) => {
|
AttributeMask::Some(attrs) => {
|
||||||
{
|
{
|
||||||
@@ -216,7 +219,7 @@ impl Widget for CheckBox {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if attrs.contains("checked") {
|
if attrs.contains("checked") {
|
||||||
self.write_value(&mut root);
|
self.write_value(root);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -224,11 +227,7 @@ impl Widget for CheckBox {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl RinkWidget for CheckBox {
|
impl RinkWidget for CheckBox {
|
||||||
fn handle_event(
|
fn handle_event(&mut self, event: &crate::Event, node: dioxus_native_core::real_dom::NodeMut) {
|
||||||
&mut self,
|
|
||||||
event: &crate::Event,
|
|
||||||
node: &mut dioxus_native_core::real_dom::NodeMut,
|
|
||||||
) {
|
|
||||||
match event.name {
|
match event.name {
|
||||||
"click" => self.switch(node),
|
"click" => self.switch(node),
|
||||||
"keydown" => {
|
"keydown" => {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use dioxus_native_core::{
|
use dioxus_native_core::{
|
||||||
node::OwnedAttributeDiscription, prelude::NodeType, real_dom::NodeImmutable,
|
custom_element::CustomElement, node::OwnedAttributeDiscription, prelude::NodeType,
|
||||||
utils::widget_watcher::Widget,
|
real_dom::NodeImmutable,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
@@ -18,10 +18,32 @@ pub(crate) enum Input {
|
|||||||
Slider(Slider),
|
Slider(Slider),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Widget for Input {
|
impl CustomElement for Input {
|
||||||
const NAME: &'static str = "input";
|
const NAME: &'static str = "input";
|
||||||
|
|
||||||
fn create(root: &mut dioxus_native_core::real_dom::NodeMut<()>) -> Self {
|
fn roots(&self) -> Vec<dioxus_native_core::NodeId> {
|
||||||
|
match self {
|
||||||
|
Input::Button(button) => button.roots(),
|
||||||
|
Input::CheckBox(checkbox) => checkbox.roots(),
|
||||||
|
Input::TextBox(textbox) => textbox.roots(),
|
||||||
|
Input::Password(password) => password.roots(),
|
||||||
|
Input::Number(number) => number.roots(),
|
||||||
|
Input::Slider(slider) => slider.roots(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn slot(&self) -> Option<dioxus_native_core::NodeId> {
|
||||||
|
match self {
|
||||||
|
Input::Button(button) => button.slot(),
|
||||||
|
Input::CheckBox(checkbox) => checkbox.slot(),
|
||||||
|
Input::TextBox(textbox) => textbox.slot(),
|
||||||
|
Input::Password(password) => password.slot(),
|
||||||
|
Input::Number(number) => number.slot(),
|
||||||
|
Input::Slider(slider) => slider.slot(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create(mut root: dioxus_native_core::real_dom::NodeMut) -> Self {
|
||||||
{
|
{
|
||||||
// currently widgets are not allowed to have children
|
// currently widgets are not allowed to have children
|
||||||
let children = root.child_ids();
|
let children = root.child_ids();
|
||||||
@@ -42,7 +64,10 @@ impl Widget for Input {
|
|||||||
namespace: None,
|
namespace: None,
|
||||||
})
|
})
|
||||||
.and_then(|value| value.as_text());
|
.and_then(|value| value.as_text());
|
||||||
match input_type {
|
match input_type
|
||||||
|
.map(|type_| type_.trim().to_lowercase())
|
||||||
|
.as_deref()
|
||||||
|
{
|
||||||
Some("button") => {
|
Some("button") => {
|
||||||
drop(node_type);
|
drop(node_type);
|
||||||
Input::Button(Button::create(root))
|
Input::Button(Button::create(root))
|
||||||
@@ -76,7 +101,7 @@ impl Widget for Input {
|
|||||||
|
|
||||||
fn attributes_changed(
|
fn attributes_changed(
|
||||||
&mut self,
|
&mut self,
|
||||||
root: dioxus_native_core::real_dom::NodeMut<()>,
|
root: dioxus_native_core::real_dom::NodeMut,
|
||||||
attributes: &dioxus_native_core::node_ref::AttributeMask,
|
attributes: &dioxus_native_core::node_ref::AttributeMask,
|
||||||
) {
|
) {
|
||||||
match self {
|
match self {
|
||||||
@@ -103,11 +128,7 @@ impl Widget for Input {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl RinkWidget for Input {
|
impl RinkWidget for Input {
|
||||||
fn handle_event(
|
fn handle_event(&mut self, event: &crate::Event, node: dioxus_native_core::real_dom::NodeMut) {
|
||||||
&mut self,
|
|
||||||
event: &crate::Event,
|
|
||||||
node: &mut dioxus_native_core::real_dom::NodeMut,
|
|
||||||
) {
|
|
||||||
match self {
|
match self {
|
||||||
Input::Button(button) => {
|
Input::Button(button) => {
|
||||||
button.handle_event(event, node);
|
button.handle_event(event, node);
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ mod textbox;
|
|||||||
use std::sync::{Arc, RwLock};
|
use std::sync::{Arc, RwLock};
|
||||||
|
|
||||||
use dioxus_native_core::{
|
use dioxus_native_core::{
|
||||||
real_dom::RealDom,
|
custom_element::{CustomElement, CustomElementUpdater},
|
||||||
utils::widget_watcher::{Widget, WidgetFactory, WidgetUpdater, WidgetWatcher},
|
real_dom::{NodeMut, RealDom},
|
||||||
};
|
};
|
||||||
use futures_channel::mpsc::UnboundedSender;
|
use futures_channel::mpsc::UnboundedSender;
|
||||||
use shipyard::{Component, Unique};
|
use shipyard::{Component, Unique};
|
||||||
@@ -21,42 +21,64 @@ pub(crate) fn register_widgets(rdom: &mut RealDom, sender: UnboundedSender<Event
|
|||||||
// inject the widget context
|
// inject the widget context
|
||||||
rdom.raw_world().add_unique(WidgetContext { sender });
|
rdom.raw_world().add_unique(WidgetContext { sender });
|
||||||
|
|
||||||
// create the widget watcher
|
rdom.register_custom_element::<RinkWidgetWrapper<input::Input>>();
|
||||||
let mut widget_watcher = WidgetWatcher::default();
|
|
||||||
|
|
||||||
widget_watcher
|
|
||||||
.register_widget::<RinkWidgetTraitObjectFactory<input::Input>, RinkWidgetTraitObject>();
|
|
||||||
|
|
||||||
widget_watcher.attach(rdom);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
trait RinkWidget: Sync + Send + Widget + 'static {
|
trait RinkWidget: Sync + Send + CustomElement + 'static {
|
||||||
fn handle_event(&mut self, event: &Event, node: &mut dioxus_native_core::real_dom::NodeMut);
|
fn handle_event(&mut self, event: &Event, node: dioxus_native_core::real_dom::NodeMut);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait RinkWidgetResponder: WidgetUpdater {
|
pub trait RinkWidgetResponder: CustomElementUpdater {
|
||||||
fn handle_event(&mut self, event: &Event, node: &mut dioxus_native_core::real_dom::NodeMut);
|
fn handle_event(&mut self, event: &Event, node: dioxus_native_core::real_dom::NodeMut);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<W: RinkWidget> RinkWidgetResponder for W {
|
impl<W: RinkWidget> RinkWidgetResponder for W {
|
||||||
fn handle_event(&mut self, event: &Event, node: &mut dioxus_native_core::real_dom::NodeMut) {
|
fn handle_event(&mut self, event: &Event, node: dioxus_native_core::real_dom::NodeMut) {
|
||||||
RinkWidget::handle_event(self, event, node)
|
RinkWidget::handle_event(self, event, node)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct RinkWidgetTraitObjectFactory<W: RinkWidget> {
|
struct RinkWidgetWrapper<W: RinkWidget> {
|
||||||
|
inner: RinkWidgetTraitObject,
|
||||||
_marker: std::marker::PhantomData<W>,
|
_marker: std::marker::PhantomData<W>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<W: RinkWidget> WidgetFactory<RinkWidgetTraitObject> for RinkWidgetTraitObjectFactory<W> {
|
impl<W: RinkWidget> CustomElement for RinkWidgetWrapper<W> {
|
||||||
const NAME: &'static str = W::NAME;
|
const NAME: &'static str = W::NAME;
|
||||||
|
|
||||||
fn create(node: &mut dioxus_native_core::real_dom::NodeMut) -> RinkWidgetTraitObject {
|
const NAMESPACE: Option<&'static str> = W::NAMESPACE;
|
||||||
|
|
||||||
|
fn create(mut node: NodeMut) -> Self {
|
||||||
let myself = RinkWidgetTraitObject {
|
let myself = RinkWidgetTraitObject {
|
||||||
widget: Arc::new(RwLock::new(W::create(node))),
|
widget: Arc::new(RwLock::new(W::create(node.reborrow()))),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Insert the widget as an arbitrary data node so that it can be recognized when bubbling events
|
||||||
node.insert(myself.clone());
|
node.insert(myself.clone());
|
||||||
myself
|
|
||||||
|
RinkWidgetWrapper {
|
||||||
|
inner: myself,
|
||||||
|
_marker: std::marker::PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn attributes_changed(
|
||||||
|
&mut self,
|
||||||
|
root: dioxus_native_core::real_dom::NodeMut,
|
||||||
|
attributes: &dioxus_native_core::node_ref::AttributeMask,
|
||||||
|
) {
|
||||||
|
let mut widget = self.inner.widget.write().unwrap();
|
||||||
|
widget.attributes_changed(root, attributes);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn roots(&self) -> Vec<dioxus_native_core::NodeId> {
|
||||||
|
let widget = self.inner.widget.read().unwrap();
|
||||||
|
widget.roots()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn slot(&self) -> Option<dioxus_native_core::NodeId> {
|
||||||
|
let widget = self.inner.widget.read().unwrap();
|
||||||
|
widget.slot()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,25 +87,35 @@ pub(crate) struct RinkWidgetTraitObject {
|
|||||||
widget: Arc<RwLock<dyn RinkWidgetResponder + Send + Sync>>,
|
widget: Arc<RwLock<dyn RinkWidgetResponder + Send + Sync>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WidgetUpdater for RinkWidgetTraitObject {
|
impl CustomElementUpdater for RinkWidgetTraitObject {
|
||||||
fn attributes_changed(
|
fn attributes_changed(
|
||||||
&mut self,
|
&mut self,
|
||||||
root: dioxus_native_core::real_dom::NodeMut,
|
light_root: dioxus_native_core::real_dom::NodeMut,
|
||||||
attributes: &dioxus_native_core::node_ref::AttributeMask,
|
attributes: &dioxus_native_core::node_ref::AttributeMask,
|
||||||
) {
|
) {
|
||||||
let mut widget = self.widget.write().unwrap();
|
let mut widget = self.widget.write().unwrap();
|
||||||
widget.attributes_changed(root, attributes);
|
widget.attributes_changed(light_root, attributes);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn roots(&self) -> Vec<dioxus_native_core::NodeId> {
|
||||||
|
let widget = self.widget.read().unwrap();
|
||||||
|
widget.roots()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn slot(&self) -> Option<dioxus_native_core::NodeId> {
|
||||||
|
let widget = self.widget.read().unwrap();
|
||||||
|
widget.slot()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RinkWidgetResponder for RinkWidgetTraitObject {
|
impl RinkWidgetResponder for RinkWidgetTraitObject {
|
||||||
fn handle_event(&mut self, event: &Event, node: &mut dioxus_native_core::real_dom::NodeMut) {
|
fn handle_event(&mut self, event: &Event, node: dioxus_native_core::real_dom::NodeMut) {
|
||||||
let mut widget = self.widget.write().unwrap();
|
let mut widget = self.widget.write().unwrap();
|
||||||
widget.handle_event(event, node);
|
widget.handle_event(event, node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Unique)]
|
#[derive(Unique, Clone)]
|
||||||
pub(crate) struct WidgetContext {
|
pub(crate) struct WidgetContext {
|
||||||
sender: UnboundedSender<Event>,
|
sender: UnboundedSender<Event>,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,14 +3,12 @@ use std::{collections::HashMap, io::stdout};
|
|||||||
use crossterm::{cursor::MoveTo, execute};
|
use crossterm::{cursor::MoveTo, execute};
|
||||||
use dioxus_html::{input_data::keyboard_types::Key, KeyboardData, MouseData};
|
use dioxus_html::{input_data::keyboard_types::Key, KeyboardData, MouseData};
|
||||||
use dioxus_native_core::{
|
use dioxus_native_core::{
|
||||||
|
custom_element::CustomElement,
|
||||||
node::OwnedAttributeDiscription,
|
node::OwnedAttributeDiscription,
|
||||||
node_ref::AttributeMask,
|
node_ref::AttributeMask,
|
||||||
prelude::{ElementNode, NodeType},
|
prelude::{ElementNode, NodeType},
|
||||||
real_dom::{ElementNodeMut, NodeImmutable, NodeMut, NodeTypeMut, RealDom},
|
real_dom::{ElementNodeMut, NodeImmutable, NodeMut, NodeTypeMut, RealDom},
|
||||||
utils::{
|
utils::cursor::{Cursor, Pos},
|
||||||
cursor::{Cursor, Pos},
|
|
||||||
widget_watcher::Widget,
|
|
||||||
},
|
|
||||||
NodeId,
|
NodeId,
|
||||||
};
|
};
|
||||||
use shipyard::UniqueView;
|
use shipyard::UniqueView;
|
||||||
@@ -169,7 +167,7 @@ impl Number {
|
|||||||
self.text = (num - 1.0).to_string();
|
self.text = (num - 1.0).to_string();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_keydown(&mut self, root: &mut NodeMut, data: &KeyboardData) {
|
fn handle_keydown(&mut self, mut root: NodeMut, data: &KeyboardData) {
|
||||||
let key = data.key();
|
let key = data.key();
|
||||||
let is_text = match key.clone() {
|
let is_text = match key.clone() {
|
||||||
Key::ArrowLeft | Key::ArrowRight | Key::Backspace => true,
|
Key::ArrowLeft | Key::ArrowRight | Key::Backspace => true,
|
||||||
@@ -235,14 +233,11 @@ impl Number {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_mousemove(&mut self, root: &mut NodeMut, data: &MouseData) {
|
fn handle_mousemove(&mut self, mut root: NodeMut, data: &MouseData) {
|
||||||
if self.dragging {
|
if self.dragging {
|
||||||
let id = root.id();
|
let id = root.id();
|
||||||
let offset = data.element_coordinates();
|
let offset = data.element_coordinates();
|
||||||
let mut new = Pos::new(offset.x as usize, offset.y as usize);
|
let mut new = Pos::new(offset.x as usize, offset.y as usize);
|
||||||
if self.border {
|
|
||||||
new.col = new.col.saturating_sub(1);
|
|
||||||
}
|
|
||||||
// textboxs are only one line tall
|
// textboxs are only one line tall
|
||||||
new.row = 0;
|
new.row = 0;
|
||||||
|
|
||||||
@@ -254,12 +249,9 @@ impl Number {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_mousedown(&mut self, root: &mut NodeMut, data: &MouseData) {
|
fn handle_mousedown(&mut self, mut root: NodeMut, data: &MouseData) {
|
||||||
let offset = data.element_coordinates();
|
let offset = data.element_coordinates();
|
||||||
let mut new = Pos::new(offset.x as usize, offset.y as usize);
|
let mut new = Pos::new(offset.x as usize, offset.y as usize);
|
||||||
if self.border {
|
|
||||||
new.col = new.col.saturating_sub(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// textboxs are only one line tall
|
// textboxs are only one line tall
|
||||||
new.row = 0;
|
new.row = 0;
|
||||||
@@ -297,10 +289,14 @@ impl Number {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Widget for Number {
|
impl CustomElement for Number {
|
||||||
const NAME: &'static str = "input";
|
const NAME: &'static str = "input";
|
||||||
|
|
||||||
fn create(root: &mut dioxus_native_core::real_dom::NodeMut<()>) -> Self {
|
fn roots(&self) -> Vec<NodeId> {
|
||||||
|
vec![self.div_wrapper]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create(mut root: dioxus_native_core::real_dom::NodeMut) -> Self {
|
||||||
let node_type = root.node_type();
|
let node_type = root.node_type();
|
||||||
let NodeType::Element(el) = &*node_type else { panic!("input must be an element") };
|
let NodeType::Element(el) = &*node_type else { panic!("input must be an element") };
|
||||||
|
|
||||||
@@ -364,8 +360,6 @@ impl Widget for Number {
|
|||||||
root.add_event_listener("keydown");
|
root.add_event_listener("keydown");
|
||||||
root.add_event_listener("focusout");
|
root.add_event_listener("focusout");
|
||||||
|
|
||||||
root.add_child(div_wrapper_id);
|
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
pre_cursor_text: pre_text_id,
|
pre_cursor_text: pre_text_id,
|
||||||
highlighted_text: highlighted_text_id,
|
highlighted_text: highlighted_text_id,
|
||||||
@@ -379,7 +373,7 @@ impl Widget for Number {
|
|||||||
|
|
||||||
fn attributes_changed(
|
fn attributes_changed(
|
||||||
&mut self,
|
&mut self,
|
||||||
mut root: dioxus_native_core::real_dom::NodeMut<()>,
|
mut root: dioxus_native_core::real_dom::NodeMut,
|
||||||
attributes: &dioxus_native_core::node_ref::AttributeMask,
|
attributes: &dioxus_native_core::node_ref::AttributeMask,
|
||||||
) {
|
) {
|
||||||
match attributes {
|
match attributes {
|
||||||
@@ -418,11 +412,7 @@ impl Widget for Number {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl RinkWidget for Number {
|
impl RinkWidget for Number {
|
||||||
fn handle_event(
|
fn handle_event(&mut self, event: &crate::Event, node: dioxus_native_core::real_dom::NodeMut) {
|
||||||
&mut self,
|
|
||||||
event: &crate::Event,
|
|
||||||
node: &mut dioxus_native_core::real_dom::NodeMut,
|
|
||||||
) {
|
|
||||||
match event.name {
|
match event.name {
|
||||||
"keydown" => {
|
"keydown" => {
|
||||||
if let EventData::Keyboard(data) = &event.data {
|
if let EventData::Keyboard(data) = &event.data {
|
||||||
|
|||||||
@@ -3,14 +3,12 @@ use std::{collections::HashMap, io::stdout};
|
|||||||
use crossterm::{cursor::MoveTo, execute};
|
use crossterm::{cursor::MoveTo, execute};
|
||||||
use dioxus_html::{input_data::keyboard_types::Key, KeyboardData, MouseData};
|
use dioxus_html::{input_data::keyboard_types::Key, KeyboardData, MouseData};
|
||||||
use dioxus_native_core::{
|
use dioxus_native_core::{
|
||||||
|
custom_element::CustomElement,
|
||||||
node::OwnedAttributeDiscription,
|
node::OwnedAttributeDiscription,
|
||||||
node_ref::AttributeMask,
|
node_ref::AttributeMask,
|
||||||
prelude::{ElementNode, NodeType},
|
prelude::{ElementNode, NodeType},
|
||||||
real_dom::{ElementNodeMut, NodeImmutable, NodeMut, NodeTypeMut, RealDom},
|
real_dom::{ElementNodeMut, NodeImmutable, NodeMut, NodeTypeMut, RealDom},
|
||||||
utils::{
|
utils::cursor::{Cursor, Pos},
|
||||||
cursor::{Cursor, Pos},
|
|
||||||
widget_watcher::Widget,
|
|
||||||
},
|
|
||||||
NodeId,
|
NodeId,
|
||||||
};
|
};
|
||||||
use shipyard::UniqueView;
|
use shipyard::UniqueView;
|
||||||
@@ -159,7 +157,7 @@ impl Password {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_keydown(&mut self, root: &mut NodeMut, data: &KeyboardData) {
|
fn handle_keydown(&mut self, mut root: NodeMut, data: &KeyboardData) {
|
||||||
let key = data.key();
|
let key = data.key();
|
||||||
let modifiers = data.modifiers();
|
let modifiers = data.modifiers();
|
||||||
let code = data.code();
|
let code = data.code();
|
||||||
@@ -203,14 +201,11 @@ impl Password {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_mousemove(&mut self, root: &mut NodeMut, data: &MouseData) {
|
fn handle_mousemove(&mut self, mut root: NodeMut, data: &MouseData) {
|
||||||
if self.dragging {
|
if self.dragging {
|
||||||
let id = root.id();
|
let id = root.id();
|
||||||
let offset = data.element_coordinates();
|
let offset = data.element_coordinates();
|
||||||
let mut new = Pos::new(offset.x as usize, offset.y as usize);
|
let mut new = Pos::new(offset.x as usize, offset.y as usize);
|
||||||
if self.border {
|
|
||||||
new.col = new.col.saturating_sub(1);
|
|
||||||
}
|
|
||||||
// textboxs are only one line tall
|
// textboxs are only one line tall
|
||||||
new.row = 0;
|
new.row = 0;
|
||||||
|
|
||||||
@@ -222,12 +217,9 @@ impl Password {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_mousedown(&mut self, root: &mut NodeMut, data: &MouseData) {
|
fn handle_mousedown(&mut self, mut root: NodeMut, data: &MouseData) {
|
||||||
let offset = data.element_coordinates();
|
let offset = data.element_coordinates();
|
||||||
let mut new = Pos::new(offset.x as usize, offset.y as usize);
|
let mut new = Pos::new(offset.x as usize, offset.y as usize);
|
||||||
if self.border {
|
|
||||||
new.col = new.col.saturating_sub(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// textboxs are only one line tall
|
// textboxs are only one line tall
|
||||||
new.row = 0;
|
new.row = 0;
|
||||||
@@ -265,10 +257,14 @@ impl Password {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Widget for Password {
|
impl CustomElement for Password {
|
||||||
const NAME: &'static str = "input";
|
const NAME: &'static str = "input";
|
||||||
|
|
||||||
fn create(root: &mut dioxus_native_core::real_dom::NodeMut<()>) -> Self {
|
fn roots(&self) -> Vec<NodeId> {
|
||||||
|
vec![self.div_wrapper]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create(mut root: dioxus_native_core::real_dom::NodeMut) -> Self {
|
||||||
let node_type = root.node_type();
|
let node_type = root.node_type();
|
||||||
let NodeType::Element(el) = &*node_type else { panic!("input must be an element") };
|
let NodeType::Element(el) = &*node_type else { panic!("input must be an element") };
|
||||||
|
|
||||||
@@ -332,8 +328,6 @@ impl Widget for Password {
|
|||||||
root.add_event_listener("keydown");
|
root.add_event_listener("keydown");
|
||||||
root.add_event_listener("focusout");
|
root.add_event_listener("focusout");
|
||||||
|
|
||||||
root.add_child(div_wrapper_id);
|
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
pre_cursor_text: pre_text_id,
|
pre_cursor_text: pre_text_id,
|
||||||
highlighted_text: highlighted_text_id,
|
highlighted_text: highlighted_text_id,
|
||||||
@@ -347,7 +341,7 @@ impl Widget for Password {
|
|||||||
|
|
||||||
fn attributes_changed(
|
fn attributes_changed(
|
||||||
&mut self,
|
&mut self,
|
||||||
mut root: dioxus_native_core::real_dom::NodeMut<()>,
|
mut root: dioxus_native_core::real_dom::NodeMut,
|
||||||
attributes: &dioxus_native_core::node_ref::AttributeMask,
|
attributes: &dioxus_native_core::node_ref::AttributeMask,
|
||||||
) {
|
) {
|
||||||
match attributes {
|
match attributes {
|
||||||
@@ -386,11 +380,7 @@ impl Widget for Password {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl RinkWidget for Password {
|
impl RinkWidget for Password {
|
||||||
fn handle_event(
|
fn handle_event(&mut self, event: &crate::Event, node: dioxus_native_core::real_dom::NodeMut) {
|
||||||
&mut self,
|
|
||||||
event: &crate::Event,
|
|
||||||
node: &mut dioxus_native_core::real_dom::NodeMut,
|
|
||||||
) {
|
|
||||||
match event.name {
|
match event.name {
|
||||||
"keydown" => {
|
"keydown" => {
|
||||||
if let EventData::Keyboard(data) = &event.data {
|
if let EventData::Keyboard(data) = &event.data {
|
||||||
|
|||||||
@@ -2,11 +2,11 @@ use std::collections::HashMap;
|
|||||||
|
|
||||||
use dioxus_html::{input_data::keyboard_types::Key, KeyboardData, MouseData};
|
use dioxus_html::{input_data::keyboard_types::Key, KeyboardData, MouseData};
|
||||||
use dioxus_native_core::{
|
use dioxus_native_core::{
|
||||||
|
custom_element::CustomElement,
|
||||||
node::{OwnedAttributeDiscription, OwnedAttributeValue},
|
node::{OwnedAttributeDiscription, OwnedAttributeValue},
|
||||||
node_ref::AttributeMask,
|
node_ref::AttributeMask,
|
||||||
prelude::{ElementNode, NodeType},
|
prelude::{ElementNode, NodeType},
|
||||||
real_dom::{ElementNodeMut, NodeImmutable, NodeMut, NodeTypeMut, RealDom},
|
real_dom::{ElementNodeMut, NodeImmutable, NodeMut, NodeTypeMut, RealDom},
|
||||||
utils::widget_watcher::Widget,
|
|
||||||
NodeId,
|
NodeId,
|
||||||
};
|
};
|
||||||
use shipyard::UniqueView;
|
use shipyard::UniqueView;
|
||||||
@@ -205,7 +205,7 @@ impl Slider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_keydown(&mut self, root: &mut NodeMut, data: &KeyboardData) {
|
fn handle_keydown(&mut self, mut root: NodeMut, data: &KeyboardData) {
|
||||||
let key = data.key();
|
let key = data.key();
|
||||||
|
|
||||||
let step = self.step();
|
let step = self.step();
|
||||||
@@ -227,7 +227,7 @@ impl Slider {
|
|||||||
self.write_value(rdom, id);
|
self.write_value(rdom, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_mousemove(&mut self, root: &mut NodeMut, data: &MouseData) {
|
fn handle_mousemove(&mut self, mut root: NodeMut, data: &MouseData) {
|
||||||
if !data.held_buttons().is_empty() {
|
if !data.held_buttons().is_empty() {
|
||||||
let id = root.id();
|
let id = root.id();
|
||||||
let rdom = root.real_dom_mut();
|
let rdom = root.real_dom_mut();
|
||||||
@@ -250,10 +250,14 @@ impl Slider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Widget for Slider {
|
impl CustomElement for Slider {
|
||||||
const NAME: &'static str = "input";
|
const NAME: &'static str = "input";
|
||||||
|
|
||||||
fn create(root: &mut dioxus_native_core::real_dom::NodeMut<()>) -> Self {
|
fn roots(&self) -> Vec<NodeId> {
|
||||||
|
vec![self.div_wrapper]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create(mut root: dioxus_native_core::real_dom::NodeMut) -> Self {
|
||||||
let node_type = root.node_type();
|
let node_type = root.node_type();
|
||||||
let NodeType::Element(el) = &*node_type else { panic!("input must be an element") };
|
let NodeType::Element(el) = &*node_type else { panic!("input must be an element") };
|
||||||
|
|
||||||
@@ -364,12 +368,10 @@ impl Widget for Slider {
|
|||||||
div_wrapper.add_child(cursor_span_id);
|
div_wrapper.add_child(cursor_span_id);
|
||||||
div_wrapper.add_child(post_cursor_div_id);
|
div_wrapper.add_child(post_cursor_div_id);
|
||||||
|
|
||||||
div_wrapper.add_event_listener("mousemove");
|
root.add_event_listener("mousemove");
|
||||||
div_wrapper.add_event_listener("mousedown");
|
root.add_event_listener("mousedown");
|
||||||
root.add_event_listener("keydown");
|
root.add_event_listener("keydown");
|
||||||
|
|
||||||
root.add_child(div_wrapper_id);
|
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
pre_cursor_div: pre_cursor_div_id,
|
pre_cursor_div: pre_cursor_div_id,
|
||||||
post_cursor_div: post_cursor_div_id,
|
post_cursor_div: post_cursor_div_id,
|
||||||
@@ -381,7 +383,7 @@ impl Widget for Slider {
|
|||||||
|
|
||||||
fn attributes_changed(
|
fn attributes_changed(
|
||||||
&mut self,
|
&mut self,
|
||||||
mut root: dioxus_native_core::real_dom::NodeMut<()>,
|
mut root: dioxus_native_core::real_dom::NodeMut,
|
||||||
attributes: &dioxus_native_core::node_ref::AttributeMask,
|
attributes: &dioxus_native_core::node_ref::AttributeMask,
|
||||||
) {
|
) {
|
||||||
match attributes {
|
match attributes {
|
||||||
@@ -428,11 +430,7 @@ impl Widget for Slider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl RinkWidget for Slider {
|
impl RinkWidget for Slider {
|
||||||
fn handle_event(
|
fn handle_event(&mut self, event: &crate::Event, node: dioxus_native_core::real_dom::NodeMut) {
|
||||||
&mut self,
|
|
||||||
event: &crate::Event,
|
|
||||||
node: &mut dioxus_native_core::real_dom::NodeMut,
|
|
||||||
) {
|
|
||||||
match event.name {
|
match event.name {
|
||||||
"keydown" => {
|
"keydown" => {
|
||||||
if let EventData::Keyboard(data) = &event.data {
|
if let EventData::Keyboard(data) = &event.data {
|
||||||
|
|||||||
@@ -3,14 +3,12 @@ use std::{collections::HashMap, io::stdout};
|
|||||||
use crossterm::{cursor::MoveTo, execute};
|
use crossterm::{cursor::MoveTo, execute};
|
||||||
use dioxus_html::{input_data::keyboard_types::Key, KeyboardData, MouseData};
|
use dioxus_html::{input_data::keyboard_types::Key, KeyboardData, MouseData};
|
||||||
use dioxus_native_core::{
|
use dioxus_native_core::{
|
||||||
|
custom_element::CustomElement,
|
||||||
node::OwnedAttributeDiscription,
|
node::OwnedAttributeDiscription,
|
||||||
node_ref::AttributeMask,
|
node_ref::AttributeMask,
|
||||||
prelude::{ElementNode, NodeType},
|
prelude::{ElementNode, NodeType},
|
||||||
real_dom::{ElementNodeMut, NodeImmutable, NodeMut, NodeTypeMut, RealDom},
|
real_dom::{ElementNodeMut, NodeImmutable, NodeMut, NodeTypeMut, RealDom},
|
||||||
utils::{
|
utils::cursor::{Cursor, Pos},
|
||||||
cursor::{Cursor, Pos},
|
|
||||||
widget_watcher::Widget,
|
|
||||||
},
|
|
||||||
NodeId,
|
NodeId,
|
||||||
};
|
};
|
||||||
use shipyard::UniqueView;
|
use shipyard::UniqueView;
|
||||||
@@ -159,7 +157,7 @@ impl TextBox {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_keydown(&mut self, root: &mut NodeMut, data: &KeyboardData) {
|
fn handle_keydown(&mut self, mut root: NodeMut, data: &KeyboardData) {
|
||||||
let key = data.key();
|
let key = data.key();
|
||||||
let modifiers = data.modifiers();
|
let modifiers = data.modifiers();
|
||||||
let code = data.code();
|
let code = data.code();
|
||||||
@@ -203,14 +201,12 @@ impl TextBox {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_mousemove(&mut self, root: &mut NodeMut, data: &MouseData) {
|
fn handle_mousemove(&mut self, mut root: NodeMut, data: &MouseData) {
|
||||||
if self.dragging {
|
if self.dragging {
|
||||||
let id = root.id();
|
let id = root.id();
|
||||||
let offset = data.element_coordinates();
|
let offset = data.element_coordinates();
|
||||||
let mut new = Pos::new(offset.x as usize, offset.y as usize);
|
let mut new = Pos::new(offset.x as usize, offset.y as usize);
|
||||||
if self.border {
|
|
||||||
new.col = new.col.saturating_sub(1);
|
|
||||||
}
|
|
||||||
// textboxs are only one line tall
|
// textboxs are only one line tall
|
||||||
new.row = 0;
|
new.row = 0;
|
||||||
|
|
||||||
@@ -222,12 +218,9 @@ impl TextBox {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_mousedown(&mut self, root: &mut NodeMut, data: &MouseData) {
|
fn handle_mousedown(&mut self, mut root: NodeMut, data: &MouseData) {
|
||||||
let offset = data.element_coordinates();
|
let offset = data.element_coordinates();
|
||||||
let mut new = Pos::new(offset.x as usize, offset.y as usize);
|
let mut new = Pos::new(offset.x as usize, offset.y as usize);
|
||||||
if self.border {
|
|
||||||
new.col = new.col.saturating_sub(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// textboxs are only one line tall
|
// textboxs are only one line tall
|
||||||
new.row = 0;
|
new.row = 0;
|
||||||
@@ -265,10 +258,14 @@ impl TextBox {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Widget for TextBox {
|
impl CustomElement for TextBox {
|
||||||
const NAME: &'static str = "input";
|
const NAME: &'static str = "input";
|
||||||
|
|
||||||
fn create(root: &mut dioxus_native_core::real_dom::NodeMut<()>) -> Self {
|
fn roots(&self) -> Vec<NodeId> {
|
||||||
|
vec![self.div_wrapper]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create(mut root: dioxus_native_core::real_dom::NodeMut) -> Self {
|
||||||
let node_type = root.node_type();
|
let node_type = root.node_type();
|
||||||
let NodeType::Element(el) = &*node_type else { panic!("input must be an element") };
|
let NodeType::Element(el) = &*node_type else { panic!("input must be an element") };
|
||||||
|
|
||||||
@@ -332,8 +329,6 @@ impl Widget for TextBox {
|
|||||||
root.add_event_listener("keydown");
|
root.add_event_listener("keydown");
|
||||||
root.add_event_listener("focusout");
|
root.add_event_listener("focusout");
|
||||||
|
|
||||||
root.add_child(div_wrapper_id);
|
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
pre_cursor_text: pre_text_id,
|
pre_cursor_text: pre_text_id,
|
||||||
highlighted_text: highlighted_text_id,
|
highlighted_text: highlighted_text_id,
|
||||||
@@ -347,7 +342,7 @@ impl Widget for TextBox {
|
|||||||
|
|
||||||
fn attributes_changed(
|
fn attributes_changed(
|
||||||
&mut self,
|
&mut self,
|
||||||
mut root: dioxus_native_core::real_dom::NodeMut<()>,
|
mut root: dioxus_native_core::real_dom::NodeMut,
|
||||||
attributes: &dioxus_native_core::node_ref::AttributeMask,
|
attributes: &dioxus_native_core::node_ref::AttributeMask,
|
||||||
) {
|
) {
|
||||||
match attributes {
|
match attributes {
|
||||||
@@ -386,11 +381,7 @@ impl Widget for TextBox {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl RinkWidget for TextBox {
|
impl RinkWidget for TextBox {
|
||||||
fn handle_event(
|
fn handle_event(&mut self, event: &crate::Event, node: NodeMut) {
|
||||||
&mut self,
|
|
||||||
event: &crate::Event,
|
|
||||||
node: &mut dioxus_native_core::real_dom::NodeMut,
|
|
||||||
) {
|
|
||||||
match event.name {
|
match event.name {
|
||||||
"keydown" => {
|
"keydown" => {
|
||||||
if let EventData::Keyboard(data) = &event.data {
|
if let EventData::Keyboard(data) = &event.data {
|
||||||
|
|||||||
Reference in new issue
Block a user