create driven example for tui renderer
This commit is contained in:
1 parent
c805bc25af
commit
71e34452da
10 files changed
+276
-34
No files matched your search
@@ -2,7 +2,10 @@ use dioxus_core::{BorrowedAttributeValue, ElementId, Mutations, TemplateNode};
|
|||||||
use rustc_hash::{FxHashMap, FxHashSet};
|
use rustc_hash::{FxHashMap, FxHashSet};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
node::{ElementNode, FromAnyValue, NodeType, OwnedAttributeDiscription, OwnedAttributeValue},
|
node::{
|
||||||
|
ElementNode, FromAnyValue, NodeType, OwnedAttributeDiscription, OwnedAttributeValue,
|
||||||
|
TextNode,
|
||||||
|
},
|
||||||
prelude::NodeImmutable,
|
prelude::NodeImmutable,
|
||||||
real_dom::NodeTypeMut,
|
real_dom::NodeTypeMut,
|
||||||
NodeId, NodeMut, RealDom,
|
NodeId, NodeMut, RealDom,
|
||||||
@@ -83,7 +86,10 @@ impl DioxusState {
|
|||||||
self.stack.push(node_id);
|
self.stack.push(node_id);
|
||||||
}
|
}
|
||||||
CreateTextNode { value, id } => {
|
CreateTextNode { value, id } => {
|
||||||
let node_data = NodeType::Text(value.to_string());
|
let node_data = NodeType::Text(TextNode {
|
||||||
|
listeners: FxHashSet::default(),
|
||||||
|
text: value.to_string(),
|
||||||
|
});
|
||||||
let node = rdom.create_node(node_data);
|
let node = rdom.create_node(node_data);
|
||||||
let node_id = node.id();
|
let node_id = node.id();
|
||||||
self.set_element_id(node, id);
|
self.set_element_id(node, id);
|
||||||
@@ -97,7 +103,10 @@ impl DioxusState {
|
|||||||
if let NodeTypeMut::Text(text) = node.node_type_mut() {
|
if let NodeTypeMut::Text(text) = node.node_type_mut() {
|
||||||
*text = value.to_string();
|
*text = value.to_string();
|
||||||
} else {
|
} else {
|
||||||
node.set_type(NodeType::Text(value.to_string()));
|
node.set_type(NodeType::Text(TextNode {
|
||||||
|
text: value.to_string(),
|
||||||
|
listeners: FxHashSet::default(),
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LoadTemplate { name, index, id } => {
|
LoadTemplate { name, index, id } => {
|
||||||
@@ -153,14 +162,12 @@ impl DioxusState {
|
|||||||
element.remove_attributes(&OwnedAttributeDiscription {
|
element.remove_attributes(&OwnedAttributeDiscription {
|
||||||
name: name.to_string(),
|
name: name.to_string(),
|
||||||
namespace: ns.map(|s| s.to_string()),
|
namespace: ns.map(|s| s.to_string()),
|
||||||
volatile: false,
|
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
element.set_attribute(
|
element.set_attribute(
|
||||||
OwnedAttributeDiscription {
|
OwnedAttributeDiscription {
|
||||||
name: name.to_string(),
|
name: name.to_string(),
|
||||||
namespace: ns.map(|s| s.to_string()),
|
namespace: ns.map(|s| s.to_string()),
|
||||||
volatile: false,
|
|
||||||
},
|
},
|
||||||
OwnedAttributeValue::from(value),
|
OwnedAttributeValue::from(value),
|
||||||
);
|
);
|
||||||
@@ -219,7 +226,6 @@ fn create_template_node(rdom: &mut RealDom, node: &TemplateNode) -> NodeId {
|
|||||||
OwnedAttributeDiscription {
|
OwnedAttributeDiscription {
|
||||||
namespace: namespace.map(|s| s.to_string()),
|
namespace: namespace.map(|s| s.to_string()),
|
||||||
name: name.to_string(),
|
name: name.to_string(),
|
||||||
volatile: false,
|
|
||||||
},
|
},
|
||||||
OwnedAttributeValue::Text(value.to_string()),
|
OwnedAttributeValue::Text(value.to_string()),
|
||||||
)),
|
)),
|
||||||
@@ -235,9 +241,16 @@ fn create_template_node(rdom: &mut RealDom, node: &TemplateNode) -> NodeId {
|
|||||||
}
|
}
|
||||||
node_id
|
node_id
|
||||||
}
|
}
|
||||||
TemplateNode::Text { text } => rdom.create_node(NodeType::Text(text.to_string())).id(),
|
TemplateNode::Text { text } => rdom
|
||||||
|
.create_node(NodeType::Text(TextNode {
|
||||||
|
text: text.to_string(),
|
||||||
|
..Default::default()
|
||||||
|
}))
|
||||||
|
.id(),
|
||||||
TemplateNode::Dynamic { .. } => rdom.create_node(NodeType::Placeholder).id(),
|
TemplateNode::Dynamic { .. } => rdom.create_node(NodeType::Placeholder).id(),
|
||||||
TemplateNode::DynamicText { .. } => rdom.create_node(NodeType::Text(String::new())).id(),
|
TemplateNode::DynamicText { .. } => {
|
||||||
|
rdom.create_node(NodeType::Text(TextNode::default())).id()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -35,10 +35,8 @@ pub type FxDashMap<K, V> = dashmap::DashMap<K, V, BuildHasherDefault<FxHasher>>;
|
|||||||
pub type FxDashSet<K> = dashmap::DashSet<K, BuildHasherDefault<FxHasher>>;
|
pub type FxDashSet<K> = dashmap::DashSet<K, BuildHasherDefault<FxHasher>>;
|
||||||
pub type SendAnyMap = anymap::Map<dyn Any + Send + Sync + 'static>;
|
pub type SendAnyMap = anymap::Map<dyn Any + Send + Sync + 'static>;
|
||||||
|
|
||||||
pub trait Renderer<V: FromAnyValue + Send + Sync, E> {
|
pub trait Renderer<E, V: FromAnyValue + Send + Sync = ()> {
|
||||||
fn render(&mut self, root: NodeMut<V>);
|
fn render(&mut self, root: NodeMut<V>);
|
||||||
fn handle_event(&mut self, node: NodeMut<V>, event: &str, value: E);
|
fn handle_event(&mut self, node: NodeMut<V>, event: &str, value: E, bubbles: bool);
|
||||||
fn poll_async(&mut self) -> Pin<Box<dyn Future<Output = ()> + Send>> {
|
fn poll_async(&mut self) -> Pin<Box<dyn Future<Output = ()> + Send>>;
|
||||||
Box::pin(async {})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
use rustc_hash::{FxHashMap, FxHashSet};
|
use rustc_hash::{FxHashMap, FxHashSet};
|
||||||
use std::{any::Any, fmt::Debug};
|
use std::{any::Any, fmt::Debug};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone, Default)]
|
||||||
pub struct ElementNode<V: FromAnyValue = ()> {
|
pub struct ElementNode<V: FromAnyValue = ()> {
|
||||||
pub tag: String,
|
pub tag: String,
|
||||||
pub namespace: Option<String>,
|
pub namespace: Option<String>,
|
||||||
@@ -9,10 +9,25 @@ pub struct ElementNode<V: FromAnyValue = ()> {
|
|||||||
pub listeners: FxHashSet<String>,
|
pub listeners: FxHashSet<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Default)]
|
||||||
|
pub struct TextNode {
|
||||||
|
pub text: String,
|
||||||
|
pub listeners: FxHashSet<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TextNode {
|
||||||
|
pub fn new(text: String) -> Self {
|
||||||
|
Self {
|
||||||
|
text,
|
||||||
|
listeners: Default::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A type of node with data specific to the node type. The types are a subset of the [VNode] types.
|
/// A type of node with data specific to the node type. The types are a subset of the [VNode] types.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum NodeType<V: FromAnyValue = ()> {
|
pub enum NodeType<V: FromAnyValue = ()> {
|
||||||
Text(String),
|
Text(TextNode),
|
||||||
Element(ElementNode<V>),
|
Element(ElementNode<V>),
|
||||||
Placeholder,
|
Placeholder,
|
||||||
}
|
}
|
||||||
@@ -21,7 +36,6 @@ pub enum NodeType<V: FromAnyValue = ()> {
|
|||||||
pub struct OwnedAttributeDiscription {
|
pub struct OwnedAttributeDiscription {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub namespace: Option<String>,
|
pub namespace: Option<String>,
|
||||||
pub volatile: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An attribute on a DOM node, such as `id="my-thing"` or
|
/// An attribute on a DOM node, such as `id="my-thing"` or
|
||||||
|
|||||||
@@ -73,10 +73,11 @@ impl<'a, V: FromAnyValue> NodeView<'a, V> {
|
|||||||
self.mask
|
self.mask
|
||||||
.text
|
.text
|
||||||
.then_some(match &self.inner {
|
.then_some(match &self.inner {
|
||||||
NodeType::Text(text) => Some(&**text),
|
NodeType::Text(text) => Some(&text.text),
|
||||||
_ => None,
|
_ => None,
|
||||||
})
|
})
|
||||||
.flatten()
|
.flatten()
|
||||||
|
.map(|x| &**x)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the listeners if it is enabled in the mask
|
/// Get the listeners if it is enabled in the mask
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ use std::rc::Rc;
|
|||||||
use std::sync::RwLock;
|
use std::sync::RwLock;
|
||||||
|
|
||||||
use crate::node::{
|
use crate::node::{
|
||||||
ElementNode, FromAnyValue, NodeType, OwnedAttributeDiscription, OwnedAttributeValue,
|
ElementNode, FromAnyValue, NodeType, OwnedAttributeDiscription, OwnedAttributeValue, TextNode,
|
||||||
};
|
};
|
||||||
use crate::node_ref::{NodeMask, NodeMaskBuilder};
|
use crate::node_ref::{NodeMask, NodeMaskBuilder};
|
||||||
use crate::node_watcher::NodeWatcher;
|
use crate::node_watcher::NodeWatcher;
|
||||||
@@ -487,6 +487,19 @@ impl<'a, V: FromAnyValue + Send + Sync> NodeMut<'a, V> {
|
|||||||
|
|
||||||
pub fn remove(&mut self) {
|
pub fn remove(&mut self) {
|
||||||
let id = self.id();
|
let id = self.id();
|
||||||
|
if let NodeType::Element(ElementNode { listeners, .. })
|
||||||
|
| NodeType::Text(TextNode { listeners, .. }) =
|
||||||
|
self.dom.get_state_mut_raw::<NodeType<V>>(id).unwrap()
|
||||||
|
{
|
||||||
|
let listeners = std::mem::take(listeners);
|
||||||
|
for event in listeners {
|
||||||
|
self.dom
|
||||||
|
.nodes_listening
|
||||||
|
.get_mut(&event)
|
||||||
|
.unwrap()
|
||||||
|
.remove(&id);
|
||||||
|
}
|
||||||
|
}
|
||||||
self.mark_removed();
|
self.mark_removed();
|
||||||
if let Some(parent_id) = self.real_dom_mut().tree.parent_id(id) {
|
if let Some(parent_id) = self.real_dom_mut().tree.parent_id(id) {
|
||||||
self.real_dom_mut()
|
self.real_dom_mut()
|
||||||
@@ -519,7 +532,9 @@ impl<'a, V: FromAnyValue + Send + Sync> NodeMut<'a, V> {
|
|||||||
pub fn add_event_listener(&mut self, event: &str) {
|
pub fn add_event_listener(&mut self, event: &str) {
|
||||||
let id = self.id();
|
let id = self.id();
|
||||||
let node_type: &mut NodeType<V> = self.dom.tree.get_mut(self.id).unwrap();
|
let node_type: &mut NodeType<V> = self.dom.tree.get_mut(self.id).unwrap();
|
||||||
if let NodeType::Element(ElementNode { listeners, .. }) = node_type {
|
if let NodeType::Element(ElementNode { listeners, .. })
|
||||||
|
| NodeType::Text(TextNode { listeners, .. }) = node_type
|
||||||
|
{
|
||||||
self.dom
|
self.dom
|
||||||
.dirty_nodes
|
.dirty_nodes
|
||||||
.mark_dirty(self.id, NodeMaskBuilder::new().with_listeners().build());
|
.mark_dirty(self.id, NodeMaskBuilder::new().with_listeners().build());
|
||||||
@@ -540,7 +555,9 @@ impl<'a, V: FromAnyValue + Send + Sync> NodeMut<'a, V> {
|
|||||||
pub fn remove_event_listener(&mut self, event: &str) {
|
pub fn remove_event_listener(&mut self, event: &str) {
|
||||||
let id = self.id();
|
let id = self.id();
|
||||||
let node_type: &mut NodeType<V> = self.dom.tree.get_mut(self.id).unwrap();
|
let node_type: &mut NodeType<V> = self.dom.tree.get_mut(self.id).unwrap();
|
||||||
if let NodeType::Element(ElementNode { listeners, .. }) = node_type {
|
if let NodeType::Element(ElementNode { listeners, .. })
|
||||||
|
| NodeType::Text(TextNode { listeners, .. }) = node_type
|
||||||
|
{
|
||||||
self.dom
|
self.dom
|
||||||
.dirty_nodes
|
.dirty_nodes
|
||||||
.mark_dirty(self.id, NodeMaskBuilder::new().with_listeners().build());
|
.mark_dirty(self.id, NodeMaskBuilder::new().with_listeners().build());
|
||||||
@@ -579,7 +596,7 @@ impl<'a, V: FromAnyValue + Send + Sync> NodeMut<'a, V> {
|
|||||||
NodeType::Text(text) => {
|
NodeType::Text(text) => {
|
||||||
dirty_nodes.mark_dirty(self.id, NodeMaskBuilder::new().with_text().build());
|
dirty_nodes.mark_dirty(self.id, NodeMaskBuilder::new().with_text().build());
|
||||||
|
|
||||||
NodeTypeMut::Text(text)
|
NodeTypeMut::Text(&mut text.text)
|
||||||
}
|
}
|
||||||
NodeType::Placeholder => NodeTypeMut::Placeholder,
|
NodeType::Placeholder => NodeTypeMut::Placeholder,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -262,12 +262,7 @@ pub struct TreeStateViewEntry<'a, 'b> {
|
|||||||
impl<'a, 'b> AnyMapLike<'a> for TreeStateViewEntry<'a, 'b> {
|
impl<'a, 'b> AnyMapLike<'a> for TreeStateViewEntry<'a, 'b> {
|
||||||
fn get<T: Any + Sync + Send>(self) -> Option<&'a T> {
|
fn get<T: Any + Sync + Send>(self) -> Option<&'a T> {
|
||||||
let slab = self.view.get_slab();
|
let slab = self.view.get_slab();
|
||||||
dbg!(slab.is_some());
|
slab.and_then(|slab| slab.get(self.id))
|
||||||
slab.and_then(|slab| {
|
|
||||||
let r = slab.get(self.id);
|
|
||||||
dbg!(r.is_some());
|
|
||||||
r
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,208 @@
|
|||||||
|
use dioxus_html::EventData;
|
||||||
|
use dioxus_native_core::{
|
||||||
|
node::{OwnedAttributeDiscription, OwnedAttributeValue, TextNode},
|
||||||
|
prelude::*,
|
||||||
|
real_dom::{NodeImmutable, NodeTypeMut},
|
||||||
|
NodeId, Renderer,
|
||||||
|
};
|
||||||
|
use dioxus_tui::{self, render, Config};
|
||||||
|
use std::sync::{Arc, RwLock};
|
||||||
|
use std::{rc::Rc, sync::Mutex};
|
||||||
|
use taffy::Taffy;
|
||||||
|
|
||||||
|
struct Test([[usize; 10]; 10]);
|
||||||
|
|
||||||
|
impl Renderer<Rc<EventData>> for Test {
|
||||||
|
fn render(&mut self, mut root: dioxus_native_core::NodeMut) {
|
||||||
|
// Set the root node to be a flexbox with a column direction.
|
||||||
|
if let NodeTypeMut::Element(mut el) = root.node_type_mut() {
|
||||||
|
el.set_attribute(
|
||||||
|
OwnedAttributeDiscription {
|
||||||
|
name: "display".into(),
|
||||||
|
namespace: None,
|
||||||
|
},
|
||||||
|
OwnedAttributeValue::Text("flex".into()),
|
||||||
|
);
|
||||||
|
el.set_attribute(
|
||||||
|
OwnedAttributeDiscription {
|
||||||
|
name: "flex-direction".into(),
|
||||||
|
namespace: None,
|
||||||
|
},
|
||||||
|
OwnedAttributeValue::Text("column".into()),
|
||||||
|
);
|
||||||
|
el.set_attribute(
|
||||||
|
OwnedAttributeDiscription {
|
||||||
|
name: "width".into(),
|
||||||
|
namespace: None,
|
||||||
|
},
|
||||||
|
OwnedAttributeValue::Text("100%".into()),
|
||||||
|
);
|
||||||
|
el.set_attribute(
|
||||||
|
OwnedAttributeDiscription {
|
||||||
|
name: "height".into(),
|
||||||
|
namespace: None,
|
||||||
|
},
|
||||||
|
OwnedAttributeValue::Text("100%".into()),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let root_id = root.id();
|
||||||
|
// Remove old grid. Frameworks should retain the grid and only update the values.
|
||||||
|
let children_ids = root.child_ids().map(|ids| ids.to_vec());
|
||||||
|
let rdom = root.real_dom_mut();
|
||||||
|
if let Some(children) = children_ids {
|
||||||
|
for child in children {
|
||||||
|
rdom.get_mut(child).unwrap().remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// create the grid
|
||||||
|
for (x, row) in self.0.iter().copied().enumerate() {
|
||||||
|
let row_node = rdom
|
||||||
|
.create_node(NodeType::Element(ElementNode {
|
||||||
|
tag: "div".to_string(),
|
||||||
|
attributes: [
|
||||||
|
(
|
||||||
|
OwnedAttributeDiscription {
|
||||||
|
name: "display".into(),
|
||||||
|
namespace: None,
|
||||||
|
},
|
||||||
|
OwnedAttributeValue::Text("flex".into()),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
OwnedAttributeDiscription {
|
||||||
|
name: "flex-direction".into(),
|
||||||
|
namespace: None,
|
||||||
|
},
|
||||||
|
OwnedAttributeValue::Text("row".into()),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
OwnedAttributeDiscription {
|
||||||
|
name: "width".into(),
|
||||||
|
namespace: None,
|
||||||
|
},
|
||||||
|
OwnedAttributeValue::Text("100%".into()),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
OwnedAttributeDiscription {
|
||||||
|
name: "height".into(),
|
||||||
|
namespace: None,
|
||||||
|
},
|
||||||
|
OwnedAttributeValue::Text("100%".into()),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
.into_iter()
|
||||||
|
.collect(),
|
||||||
|
..Default::default()
|
||||||
|
}))
|
||||||
|
.id();
|
||||||
|
for (y, count) in row.iter().copied().enumerate() {
|
||||||
|
let node = rdom
|
||||||
|
.create_node(NodeType::Text(TextNode::new(count.to_string())))
|
||||||
|
.id();
|
||||||
|
let mut button = rdom.create_node(NodeType::Element(ElementNode {
|
||||||
|
tag: "div".to_string(),
|
||||||
|
attributes: [
|
||||||
|
(
|
||||||
|
OwnedAttributeDiscription {
|
||||||
|
name: "background-color".into(),
|
||||||
|
namespace: None,
|
||||||
|
},
|
||||||
|
OwnedAttributeValue::Text(format!(
|
||||||
|
"rgb({}, {}, {})",
|
||||||
|
count * 10,
|
||||||
|
0,
|
||||||
|
(x + y) * 10,
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
OwnedAttributeDiscription {
|
||||||
|
name: "width".into(),
|
||||||
|
namespace: None,
|
||||||
|
},
|
||||||
|
OwnedAttributeValue::Text("100%".into()),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
OwnedAttributeDiscription {
|
||||||
|
name: "height".into(),
|
||||||
|
namespace: None,
|
||||||
|
},
|
||||||
|
OwnedAttributeValue::Text("100%".into()),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
OwnedAttributeDiscription {
|
||||||
|
name: "display".into(),
|
||||||
|
namespace: None,
|
||||||
|
},
|
||||||
|
OwnedAttributeValue::Text("flex".into()),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
OwnedAttributeDiscription {
|
||||||
|
name: "flex-direction".into(),
|
||||||
|
namespace: None,
|
||||||
|
},
|
||||||
|
OwnedAttributeValue::Text("row".into()),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
OwnedAttributeDiscription {
|
||||||
|
name: "justify-content".into(),
|
||||||
|
namespace: None,
|
||||||
|
},
|
||||||
|
OwnedAttributeValue::Text("center".into()),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
OwnedAttributeDiscription {
|
||||||
|
name: "align-items".into(),
|
||||||
|
namespace: None,
|
||||||
|
},
|
||||||
|
OwnedAttributeValue::Text("center".into()),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
.into_iter()
|
||||||
|
.collect(),
|
||||||
|
..Default::default()
|
||||||
|
}));
|
||||||
|
button.add_event_listener("click");
|
||||||
|
button.add_event_listener("wheel");
|
||||||
|
button.add_child(node);
|
||||||
|
let button_id = button.id();
|
||||||
|
rdom.get_mut(row_node).unwrap().add_child(button_id);
|
||||||
|
}
|
||||||
|
rdom.get_mut(root_id).unwrap().add_child(row_node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_event(
|
||||||
|
&mut self,
|
||||||
|
node: dioxus_native_core::NodeMut<()>,
|
||||||
|
event: &str,
|
||||||
|
value: Rc<EventData>,
|
||||||
|
bubbles: bool,
|
||||||
|
) {
|
||||||
|
if let Some(parent) = node.parent() {
|
||||||
|
let child_number = parent
|
||||||
|
.child_ids()
|
||||||
|
.unwrap()
|
||||||
|
.iter()
|
||||||
|
.position(|id| *id == node.id())
|
||||||
|
.unwrap();
|
||||||
|
if let Some(parents_parent) = parent.parent() {
|
||||||
|
let parents_child_number = parents_parent
|
||||||
|
.child_ids()
|
||||||
|
.unwrap()
|
||||||
|
.iter()
|
||||||
|
.position(|id| *id == parent.id())
|
||||||
|
.unwrap();
|
||||||
|
self.0[parents_child_number][child_number] += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn poll_async(&mut self) -> std::pin::Pin<Box<dyn futures::Future<Output = ()> + Send>> {
|
||||||
|
Box::pin(async move { tokio::time::sleep(std::time::Duration::from_millis(1000)).await })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
render(Config::new(), |_, _, _| Test(Default::default())).unwrap();
|
||||||
|
}
|
||||||
@@ -75,7 +75,6 @@ pub struct InnerInputState {
|
|||||||
mouse: Option<MouseData>,
|
mouse: Option<MouseData>,
|
||||||
wheel: Option<WheelData>,
|
wheel: Option<WheelData>,
|
||||||
last_key_pressed: Option<(KeyboardData, Instant)>,
|
last_key_pressed: Option<(KeyboardData, Instant)>,
|
||||||
screen: Option<(u16, u16)>,
|
|
||||||
pub(crate) focus_state: FocusState,
|
pub(crate) focus_state: FocusState,
|
||||||
// subscribers: Vec<Rc<dyn Fn() + 'static>>,
|
// subscribers: Vec<Rc<dyn Fn() + 'static>>,
|
||||||
}
|
}
|
||||||
@@ -86,7 +85,6 @@ impl InnerInputState {
|
|||||||
mouse: None,
|
mouse: None,
|
||||||
wheel: None,
|
wheel: None,
|
||||||
last_key_pressed: None,
|
last_key_pressed: None,
|
||||||
screen: None,
|
|
||||||
// subscribers: Vec::new(),
|
// subscribers: Vec::new(),
|
||||||
focus_state: FocusState::create(rdom),
|
focus_state: FocusState::create(rdom),
|
||||||
}
|
}
|
||||||
@@ -181,7 +179,6 @@ impl InnerInputState {
|
|||||||
if old_focus != self.focus_state.last_focused_id {
|
if old_focus != self.focus_state.last_focused_id {
|
||||||
// elements with listeners will always have a element id
|
// elements with listeners will always have a element id
|
||||||
if let Some(id) = self.focus_state.last_focused_id {
|
if let Some(id) = self.focus_state.last_focused_id {
|
||||||
let element = dom.get(id).unwrap();
|
|
||||||
resolved_events.push(Event {
|
resolved_events.push(Event {
|
||||||
name: "focus",
|
name: "focus",
|
||||||
id,
|
id,
|
||||||
@@ -196,7 +193,6 @@ impl InnerInputState {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
if let Some(id) = old_focus {
|
if let Some(id) = old_focus {
|
||||||
let element = dom.get(id).unwrap();
|
|
||||||
resolved_events.push(Event {
|
resolved_events.push(Event {
|
||||||
name: "focusout",
|
name: "focusout",
|
||||||
id,
|
id,
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ impl TuiContext {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render<R: Renderer<(), Rc<EventData>>>(
|
pub fn render<R: Renderer<Rc<EventData>>>(
|
||||||
cfg: Config,
|
cfg: Config,
|
||||||
f: impl FnOnce(&Arc<RwLock<RealDom>>, &Arc<Mutex<Taffy>>, UnboundedSender<InputEvent>) -> R,
|
f: impl FnOnce(&Arc<RwLock<RealDom>>, &Arc<Mutex<Taffy>>, UnboundedSender<InputEvent>) -> R,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
@@ -271,7 +271,7 @@ pub fn render<R: Renderer<(), Rc<EventData>>>(
|
|||||||
|
|
||||||
for e in evts {
|
for e in evts {
|
||||||
let node = rdom.get_mut(e.id).unwrap();
|
let node = rdom.get_mut(e.id).unwrap();
|
||||||
renderer.handle_event(node, e.name, e.data);
|
renderer.handle_event(node, e.name, e.data, e.bubbles);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let mut rdom = rdom.write().unwrap();
|
let mut rdom = rdom.write().unwrap();
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ pub(crate) fn render_vnode(
|
|||||||
}
|
}
|
||||||
|
|
||||||
let label = Label {
|
let label = Label {
|
||||||
text,
|
text: &text.text,
|
||||||
style: node.get::<StyleModifier>().unwrap().core,
|
style: node.get::<StyleModifier>().unwrap().core,
|
||||||
};
|
};
|
||||||
let area = Rect::new(x, y, width, height);
|
let area = Rect::new(x, y, width, height);
|
||||||
|
|||||||
Reference in new issue
Block a user