layout.rs 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. use std::cell::RefCell;
  2. use std::rc::Rc;
  3. use dioxus_core::*;
  4. use dioxus_native_core::layout_attributes::apply_layout_attributes;
  5. use dioxus_native_core::node_ref::{AttributeMask, NodeMask, NodeView};
  6. use dioxus_native_core::state::ChildDepState;
  7. use dioxus_native_core_macro::sorted_str_slice;
  8. use stretch2::prelude::*;
  9. #[derive(Debug, Clone, Copy, PartialEq)]
  10. pub(crate) enum PossiblyUninitalized<T> {
  11. Uninitalized,
  12. Initialized(T),
  13. }
  14. impl<T> PossiblyUninitalized<T> {
  15. pub fn unwrap(self) -> T {
  16. match self {
  17. Self::Initialized(i) => i,
  18. _ => panic!(),
  19. }
  20. }
  21. }
  22. impl<T> Default for PossiblyUninitalized<T> {
  23. fn default() -> Self {
  24. Self::Uninitalized
  25. }
  26. }
  27. #[derive(Clone, PartialEq, Default, Debug)]
  28. pub(crate) struct StretchLayout {
  29. pub style: Style,
  30. pub node: PossiblyUninitalized<Node>,
  31. }
  32. impl ChildDepState for StretchLayout {
  33. type Ctx = Rc<RefCell<Stretch>>;
  34. type DepState = Self;
  35. // todo: update mask
  36. const NODE_MASK: NodeMask = NodeMask::new(
  37. AttributeMask::Static(SORTED_LAYOUT_ATTRS),
  38. false,
  39. false,
  40. true,
  41. );
  42. /// Setup the layout
  43. fn reduce<'a>(
  44. &mut self,
  45. node: NodeView,
  46. children: impl Iterator<Item = &'a Self::DepState>,
  47. ctx: &Self::Ctx,
  48. ) -> bool
  49. where
  50. Self::DepState: 'a,
  51. {
  52. let mut changed = false;
  53. let mut stretch = ctx.borrow_mut();
  54. let mut style = Style::default();
  55. if let Some(text) = node.text() {
  56. let char_len = text.chars().count();
  57. style = Style {
  58. size: Size {
  59. // characters are 1 point tall
  60. height: Dimension::Points(1.0),
  61. // text is as long as it is declared
  62. width: Dimension::Points(char_len as f32),
  63. },
  64. ..Default::default()
  65. };
  66. if let PossiblyUninitalized::Initialized(n) = self.node {
  67. if self.style != style {
  68. stretch.set_style(n, style).unwrap();
  69. }
  70. } else {
  71. self.node =
  72. PossiblyUninitalized::Initialized(stretch.new_node(style, &[]).unwrap());
  73. }
  74. } else {
  75. // gather up all the styles from the attribute list
  76. for &Attribute { name, value, .. } in node.attributes() {
  77. assert!(SORTED_LAYOUT_ATTRS.binary_search(&name).is_ok());
  78. apply_layout_attributes(name, value, &mut style);
  79. }
  80. // the root node fills the entire area
  81. if node.id() == ElementId(0) {
  82. apply_layout_attributes("width", "100%", &mut style);
  83. apply_layout_attributes("height", "100%", &mut style);
  84. }
  85. // Set all direct nodes as our children
  86. let mut child_layout = vec![];
  87. for l in children {
  88. child_layout.push(l.node.unwrap());
  89. }
  90. if let PossiblyUninitalized::Initialized(n) = self.node {
  91. if self.style != style {
  92. stretch.set_style(n, style).unwrap();
  93. }
  94. if stretch.children(n).unwrap() != child_layout {
  95. stretch.set_children(n, &child_layout).unwrap();
  96. }
  97. } else {
  98. self.node = PossiblyUninitalized::Initialized(
  99. stretch.new_node(style, &child_layout).unwrap(),
  100. );
  101. }
  102. }
  103. if self.style != style {
  104. changed = true;
  105. self.style = style;
  106. }
  107. changed
  108. }
  109. }
  110. // these are the attributes in layout_attiributes in native-core
  111. const SORTED_LAYOUT_ATTRS: &'static [&'static str] = &sorted_str_slice!([
  112. "align-content",
  113. "align-items",
  114. "align-self",
  115. "animation",
  116. "animation-delay",
  117. "animation-direction",
  118. "animation-duration",
  119. "animation-fill-mode",
  120. "animation-iteration-count",
  121. "animation-name",
  122. "animation-play-state",
  123. "animation-timing-function",
  124. "backface-visibility",
  125. "border",
  126. "border-bottom",
  127. "border-bottom-color",
  128. "border-bottom-left-radius",
  129. "border-bottom-right-radius",
  130. "border-bottom-style",
  131. "border-bottom-width",
  132. "border-collapse",
  133. "border-color",
  134. "border-image",
  135. "border-image-outset",
  136. "border-image-repeat",
  137. "border-image-slice",
  138. "border-image-source",
  139. "border-image-width",
  140. "border-left",
  141. "border-left-color",
  142. "border-left-style",
  143. "border-left-width",
  144. "border-radius",
  145. "border-right",
  146. "border-right-color",
  147. "border-right-style",
  148. "border-right-width",
  149. "border-spacing",
  150. "border-style",
  151. "border-top",
  152. "border-top-color",
  153. "border-top-left-radius",
  154. "border-top-right-radius",
  155. "border-top-style",
  156. "border-top-width",
  157. "border-width",
  158. "bottom",
  159. "box-shadow",
  160. "box-sizing",
  161. "caption-side",
  162. "clear",
  163. "clip",
  164. "column-count",
  165. "column-fill",
  166. "column-gap",
  167. "column-rule",
  168. "column-rule-color",
  169. "column-rule-style",
  170. "column-rule-width",
  171. "column-span",
  172. "column-width",
  173. "columns",
  174. "content",
  175. "counter-increment",
  176. "counter-reset",
  177. "cursor",
  178. "direction",
  179. "ltr",
  180. "rtl",
  181. "display",
  182. "empty-cells",
  183. "flex",
  184. "flex-basis",
  185. "flex-direction",
  186. "flex-flow",
  187. "flex-grow",
  188. "flex-shrink",
  189. "flex-wrap",
  190. "float",
  191. "height",
  192. "justify-content",
  193. "flex-start",
  194. "flex-end",
  195. "center",
  196. "space-between",
  197. "space-around",
  198. "space-evenly",
  199. "left",
  200. "letter-spacing",
  201. "line-height",
  202. "list-style",
  203. "list-style-image",
  204. "list-style-position",
  205. "list-style-type",
  206. "margin",
  207. "margin-bottom",
  208. "margin-left",
  209. "margin-right",
  210. "margin-top",
  211. "max-height",
  212. "max-width",
  213. "min-height",
  214. "min-width",
  215. "opacity",
  216. "order",
  217. "outline",
  218. "outline-color",
  219. "outline-offset",
  220. "outline-style",
  221. "outline-width",
  222. "overflow",
  223. "overflow-x",
  224. "overflow-y",
  225. "padding",
  226. "padding-bottom",
  227. "padding-left",
  228. "padding-right",
  229. "padding-top",
  230. "page-break-after",
  231. "page-break-before",
  232. "page-break-inside",
  233. "perspective",
  234. "perspective-origin",
  235. "position",
  236. "static",
  237. "relative",
  238. "fixed",
  239. "absolute",
  240. "sticky",
  241. "pointer-events",
  242. "quotes",
  243. "resize",
  244. "right",
  245. "tab-size",
  246. "table-layout",
  247. "top",
  248. "transform",
  249. "transform-origin",
  250. "transform-style",
  251. "transition",
  252. "transition-delay",
  253. "transition-duration",
  254. "transition-property",
  255. "transition-timing-function",
  256. "vertical-align",
  257. "visibility",
  258. "white-space",
  259. "width",
  260. "word-break",
  261. "word-spacing",
  262. "word-wrap",
  263. "z-index"
  264. ]);