dioxus/packages/tui/src/layout.rs
Demonthos 67a6fa9eb8
Implement new mutations with native core (#630)
* work on seperating tree struture from realdom

* intial update to new mutations

* handle height

* update to taffy 0.2

* add as_varient functions to OwnedAttributeValue

* make get node parent mut optionally return a parent

* work on upward pass

* add more code for parrellel passes

* make resolve passes public

* more work on parallel passes

* fix deadlock and add more tests

* move height into the tree instead of the realdom

* make passes exicute in parallel instead of executing invidual passes in parellel

* fix some warnings

* add up dependant test

* clean up examples

* work on intigrating state with passes

* update to new mutations

* work on implementing macro

* make the macro compile

* more progress on macro

* mark cloned nodes as dirty

* update persistant_iterator utility

* fix mask generation

* update tui with new mutations

* more progress updating tui

* some basic tui examples working

* don't push template nodes onto the stack

* update hover example

* update benchmark

* update more examples

* fix root node layout

* ignore out of bounds renders

* update color picker example

* update all events example

* update remaining examples

* update tests

* tests passing

* move persistant iterator test

* update examples

* fix gaps in layout

* fix formatting

* fix memory leak
2022-12-06 15:38:04 -08:00

284 lines
7.1 KiB
Rust

use std::sync::{Arc, Mutex};
use dioxus_native_core::layout_attributes::apply_layout_attributes;
use dioxus_native_core::node::OwnedAttributeView;
use dioxus_native_core::node_ref::{AttributeMask, NodeMask, NodeView};
use dioxus_native_core::state::ChildDepState;
use dioxus_native_core_macro::sorted_str_slice;
use taffy::prelude::*;
use crate::screen_to_layout_space;
#[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!("uninitalized"),
}
}
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 = Arc<Mutex<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,)>,
ctx: &Self::Ctx,
) -> bool
where
Self::DepState: 'a,
{
let mut changed = false;
let mut taffy = ctx.lock().expect("poisoned taffy");
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(screen_to_layout_space(1)),
// text is as long as it is declared
width: Dimension::Points(screen_to_layout_space(char_len as u16)),
},
..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_leaf(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);
}
}
}
// 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_with_children(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"
]);