123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290 |
- use std::cell::RefCell;
- use std::rc::Rc;
- use dioxus_core::*;
- use dioxus_native_core::layout_attributes::apply_layout_attributes;
- use dioxus_native_core::node_ref::{AttributeMask, NodeMask, NodeView};
- use dioxus_native_core::real_dom::OwnedAttributeView;
- use dioxus_native_core::state::ChildDepState;
- use dioxus_native_core_macro::sorted_str_slice;
- use taffy::prelude::*;
- #[derive(Debug, Clone, Copy, PartialEq)]
- pub(crate) enum PossiblyUninitalized<T> {
- Uninitalized,
- Initialized(T),
- }
- impl<T> PossiblyUninitalized<T> {
- pub fn unwrap(self) -> T {
- match self {
- Self::Initialized(i) => i,
- _ => panic!(),
- }
- }
- pub fn ok(self) -> Option<T> {
- match self {
- Self::Initialized(i) => Some(i),
- _ => None,
- }
- }
- }
- impl<T> Default for PossiblyUninitalized<T> {
- fn default() -> Self {
- Self::Uninitalized
- }
- }
- #[derive(Clone, PartialEq, Default, Debug)]
- pub(crate) struct TaffyLayout {
- pub style: Style,
- pub node: PossiblyUninitalized<Node>,
- }
- impl ChildDepState for TaffyLayout {
- type Ctx = Rc<RefCell<Taffy>>;
- type DepState = Self;
- // use tag to force this to be called when a node is built
- const NODE_MASK: NodeMask =
- NodeMask::new_with_attrs(AttributeMask::Static(SORTED_LAYOUT_ATTRS))
- .with_text()
- .with_tag();
- /// Setup the layout
- fn reduce<'a>(
- &mut self,
- node: NodeView,
- children: impl Iterator<Item = &'a Self::DepState>,
- ctx: &Self::Ctx,
- ) -> bool
- where
- Self::DepState: 'a,
- {
- let mut changed = false;
- let mut taffy = ctx.borrow_mut();
- let mut style = Style::default();
- if let Some(text) = node.text() {
- let char_len = text.chars().count();
- style = Style {
- size: Size {
- // characters are 1 point tall
- height: Dimension::Points(1.0),
- // text is as long as it is declared
- width: Dimension::Points(char_len as f32),
- },
- ..Default::default()
- };
- if let PossiblyUninitalized::Initialized(n) = self.node {
- if self.style != style {
- taffy.set_style(n, style).unwrap();
- }
- } else {
- self.node = PossiblyUninitalized::Initialized(taffy.new_node(style, &[]).unwrap());
- changed = true;
- }
- } else {
- // gather up all the styles from the attribute list
- if let Some(attributes) = node.attributes() {
- for OwnedAttributeView {
- attribute, value, ..
- } in attributes
- {
- assert!(SORTED_LAYOUT_ATTRS
- .binary_search(&attribute.name.as_ref())
- .is_ok());
- if let Some(text) = value.as_text() {
- apply_layout_attributes(&attribute.name, text, &mut style);
- }
- }
- }
- // the root node fills the entire area
- if node.id() == ElementId(0) {
- apply_layout_attributes("width", "100%", &mut style);
- apply_layout_attributes("height", "100%", &mut style);
- }
- // Set all direct nodes as our children
- let mut child_layout = vec![];
- for l in children {
- child_layout.push(l.node.unwrap());
- }
- if let PossiblyUninitalized::Initialized(n) = self.node {
- if self.style != style {
- taffy.set_style(n, style).unwrap();
- }
- if taffy.children(n).unwrap() != child_layout {
- taffy.set_children(n, &child_layout).unwrap();
- }
- } else {
- self.node = PossiblyUninitalized::Initialized(
- taffy.new_node(style, &child_layout).unwrap(),
- );
- changed = true;
- }
- }
- if self.style != style {
- changed = true;
- self.style = style;
- }
- changed
- }
- }
- // these are the attributes in layout_attiributes in native-core
- const SORTED_LAYOUT_ATTRS: &[&str] = &sorted_str_slice!([
- "align-content",
- "align-items",
- "align-self",
- "animation",
- "animation-delay",
- "animation-direction",
- "animation-duration",
- "animation-fill-mode",
- "animation-iteration-count",
- "animation-name",
- "animation-play-state",
- "animation-timing-function",
- "backface-visibility",
- "border",
- "border-bottom",
- "border-bottom-color",
- "border-bottom-left-radius",
- "border-bottom-right-radius",
- "border-bottom-style",
- "border-bottom-width",
- "border-collapse",
- "border-color",
- "border-image",
- "border-image-outset",
- "border-image-repeat",
- "border-image-slice",
- "border-image-source",
- "border-image-width",
- "border-left",
- "border-left-color",
- "border-left-style",
- "border-left-width",
- "border-radius",
- "border-right",
- "border-right-color",
- "border-right-style",
- "border-right-width",
- "border-spacing",
- "border-style",
- "border-top",
- "border-top-color",
- "border-top-left-radius",
- "border-top-right-radius",
- "border-top-style",
- "border-top-width",
- "border-width",
- "bottom",
- "box-shadow",
- "box-sizing",
- "caption-side",
- "clear",
- "clip",
- "column-count",
- "column-fill",
- "column-gap",
- "column-rule",
- "column-rule-color",
- "column-rule-style",
- "column-rule-width",
- "column-span",
- "column-width",
- "columns",
- "content",
- "counter-increment",
- "counter-reset",
- "cursor",
- "direction",
- "ltr",
- "rtl",
- "display",
- "empty-cells",
- "flex",
- "flex-basis",
- "flex-direction",
- "flex-flow",
- "flex-grow",
- "flex-shrink",
- "flex-wrap",
- "float",
- "height",
- "justify-content",
- "flex-start",
- "flex-end",
- "center",
- "space-between",
- "space-around",
- "space-evenly",
- "left",
- "letter-spacing",
- "line-height",
- "list-style",
- "list-style-image",
- "list-style-position",
- "list-style-type",
- "margin",
- "margin-bottom",
- "margin-left",
- "margin-right",
- "margin-top",
- "max-height",
- "max-width",
- "min-height",
- "min-width",
- "opacity",
- "order",
- "outline",
- "outline-color",
- "outline-offset",
- "outline-style",
- "outline-width",
- "overflow",
- "overflow-x",
- "overflow-y",
- "padding",
- "padding-bottom",
- "padding-left",
- "padding-right",
- "padding-top",
- "page-break-after",
- "page-break-before",
- "page-break-inside",
- "perspective",
- "perspective-origin",
- "position",
- "static",
- "relative",
- "fixed",
- "absolute",
- "sticky",
- "pointer-events",
- "quotes",
- "resize",
- "right",
- "tab-size",
- "table-layout",
- "top",
- "transform",
- "transform-origin",
- "transform-style",
- "transition",
- "transition-delay",
- "transition-duration",
- "transition-property",
- "transition-timing-function",
- "vertical-align",
- "visibility",
- "white-space",
- "width",
- "word-break",
- "word-spacing",
- "word-wrap",
- "z-index"
- ]);
|