driven.rs 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. use dioxus_html::EventData;
  2. use dioxus_native_core::{
  3. node::{OwnedAttributeDiscription, OwnedAttributeValue, TextNode},
  4. prelude::*,
  5. real_dom::{NodeImmutable, NodeTypeMut},
  6. NodeId,
  7. };
  8. use dioxus_tui::{self, render, Config, Renderer};
  9. use rustc_hash::FxHashSet;
  10. use std::rc::Rc;
  11. use std::sync::{Arc, RwLock};
  12. const SIZE: usize = 10;
  13. struct Test {
  14. node_states: [[usize; SIZE]; SIZE],
  15. dirty: FxHashSet<(usize, usize)>,
  16. }
  17. impl Default for Test {
  18. fn default() -> Self {
  19. Self {
  20. node_states: [[0; SIZE]; SIZE],
  21. dirty: FxHashSet::default(),
  22. }
  23. }
  24. }
  25. impl Test {
  26. fn create(mut root: NodeMut) -> Self {
  27. let myself = Self::default();
  28. // Set the root node to be a flexbox with a column direction.
  29. if let NodeTypeMut::Element(mut el) = root.node_type_mut() {
  30. el.set_attribute(
  31. OwnedAttributeDiscription {
  32. name: "display".into(),
  33. namespace: None,
  34. },
  35. OwnedAttributeValue::Text("flex".into()),
  36. );
  37. el.set_attribute(
  38. OwnedAttributeDiscription {
  39. name: "flex-direction".into(),
  40. namespace: None,
  41. },
  42. OwnedAttributeValue::Text("column".into()),
  43. );
  44. el.set_attribute(
  45. OwnedAttributeDiscription {
  46. name: "width".into(),
  47. namespace: None,
  48. },
  49. OwnedAttributeValue::Text("100%".into()),
  50. );
  51. el.set_attribute(
  52. OwnedAttributeDiscription {
  53. name: "height".into(),
  54. namespace: None,
  55. },
  56. OwnedAttributeValue::Text("100%".into()),
  57. );
  58. }
  59. let root_id = root.id();
  60. let rdom = root.real_dom_mut();
  61. // create the grid
  62. for (x, row) in myself.node_states.iter().copied().enumerate() {
  63. let row_node = rdom
  64. .create_node(NodeType::Element(ElementNode {
  65. tag: "div".to_string(),
  66. attributes: [
  67. (
  68. OwnedAttributeDiscription {
  69. name: "display".into(),
  70. namespace: None,
  71. },
  72. OwnedAttributeValue::Text("flex".into()),
  73. ),
  74. (
  75. OwnedAttributeDiscription {
  76. name: "flex-direction".into(),
  77. namespace: None,
  78. },
  79. OwnedAttributeValue::Text("row".into()),
  80. ),
  81. (
  82. OwnedAttributeDiscription {
  83. name: "width".into(),
  84. namespace: None,
  85. },
  86. OwnedAttributeValue::Text("100%".into()),
  87. ),
  88. (
  89. OwnedAttributeDiscription {
  90. name: "height".into(),
  91. namespace: None,
  92. },
  93. OwnedAttributeValue::Text("100%".into()),
  94. ),
  95. ]
  96. .into_iter()
  97. .collect(),
  98. ..Default::default()
  99. }))
  100. .id();
  101. for (y, count) in row.iter().copied().enumerate() {
  102. let node = rdom
  103. .create_node(NodeType::Text(TextNode::new(count.to_string())))
  104. .id();
  105. let mut button = rdom.create_node(NodeType::Element(ElementNode {
  106. tag: "div".to_string(),
  107. attributes: [
  108. (
  109. OwnedAttributeDiscription {
  110. name: "background-color".into(),
  111. namespace: None,
  112. },
  113. OwnedAttributeValue::Text(format!(
  114. "rgb({}, {}, {})",
  115. count * 10,
  116. 0,
  117. (x + y) * 10,
  118. )),
  119. ),
  120. (
  121. OwnedAttributeDiscription {
  122. name: "width".into(),
  123. namespace: None,
  124. },
  125. OwnedAttributeValue::Text("100%".into()),
  126. ),
  127. (
  128. OwnedAttributeDiscription {
  129. name: "height".into(),
  130. namespace: None,
  131. },
  132. OwnedAttributeValue::Text("100%".into()),
  133. ),
  134. (
  135. OwnedAttributeDiscription {
  136. name: "display".into(),
  137. namespace: None,
  138. },
  139. OwnedAttributeValue::Text("flex".into()),
  140. ),
  141. (
  142. OwnedAttributeDiscription {
  143. name: "flex-direction".into(),
  144. namespace: None,
  145. },
  146. OwnedAttributeValue::Text("row".into()),
  147. ),
  148. (
  149. OwnedAttributeDiscription {
  150. name: "justify-content".into(),
  151. namespace: None,
  152. },
  153. OwnedAttributeValue::Text("center".into()),
  154. ),
  155. (
  156. OwnedAttributeDiscription {
  157. name: "align-items".into(),
  158. namespace: None,
  159. },
  160. OwnedAttributeValue::Text("center".into()),
  161. ),
  162. ]
  163. .into_iter()
  164. .collect(),
  165. ..Default::default()
  166. }));
  167. button.add_event_listener("click");
  168. button.add_event_listener("wheel");
  169. button.add_child(node);
  170. let button_id = button.id();
  171. rdom.get_mut(row_node).unwrap().add_child(button_id);
  172. }
  173. rdom.get_mut(root_id).unwrap().add_child(row_node);
  174. }
  175. myself
  176. }
  177. }
  178. impl Renderer for Test {
  179. fn render(&mut self, rdom: &Arc<RwLock<RealDom>>) {
  180. let mut rdom = rdom.write().unwrap();
  181. let root_id = rdom.root_id();
  182. let mut root = rdom.get_mut(root_id).unwrap();
  183. for (x, y) in self.dirty.drain() {
  184. let row_id = root.child_ids()[x];
  185. let rdom = root.real_dom_mut();
  186. let row = rdom.get(row_id).unwrap();
  187. let node_id = row.child_ids()[y];
  188. let mut node = rdom.get_mut(node_id).unwrap();
  189. if let NodeTypeMut::Element(mut el) = node.node_type_mut() {
  190. el.set_attribute(
  191. OwnedAttributeDiscription {
  192. name: "background-color".into(),
  193. namespace: None,
  194. },
  195. OwnedAttributeValue::Text(format!(
  196. "rgb({}, {}, {})",
  197. self.node_states[x][y] * 10,
  198. 0,
  199. (x + y) * 10,
  200. )),
  201. );
  202. }
  203. let text_id = *node.child_ids().first().unwrap();
  204. let mut text = rdom.get_mut(text_id).unwrap();
  205. let type_mut = text.node_type_mut();
  206. if let NodeTypeMut::Text(mut text) = type_mut {
  207. *text = self.node_states[x][y].to_string();
  208. }
  209. }
  210. }
  211. fn handle_event(
  212. &mut self,
  213. rdom: &Arc<RwLock<RealDom>>,
  214. id: NodeId,
  215. _: &str,
  216. _: Rc<EventData>,
  217. _: bool,
  218. ) {
  219. let rdom = rdom.read().unwrap();
  220. let node = rdom.get(id).unwrap();
  221. if let Some(parent) = node.parent() {
  222. let child_number = parent
  223. .child_ids()
  224. .iter()
  225. .position(|id| *id == node.id())
  226. .unwrap();
  227. if let Some(parents_parent) = parent.parent() {
  228. let parents_child_number = parents_parent
  229. .child_ids()
  230. .iter()
  231. .position(|id| *id == parent.id())
  232. .unwrap();
  233. self.node_states[parents_child_number][child_number] += 1;
  234. self.dirty.insert((parents_child_number, child_number));
  235. }
  236. }
  237. }
  238. fn poll_async(&mut self) -> std::pin::Pin<Box<dyn futures::Future<Output = ()> + '_>> {
  239. Box::pin(async move { tokio::time::sleep(std::time::Duration::from_millis(1000)).await })
  240. }
  241. }
  242. fn main() {
  243. render(Config::new(), |rdom, _, _| {
  244. let mut rdom = rdom.write().unwrap();
  245. let root = rdom.root_id();
  246. Test::create(rdom.get_mut(root).unwrap())
  247. })
  248. .unwrap();
  249. }