Skip to main content

float_pigment_forest/
node.rs

1use crate::{env::Env, layout::LayoutPosition, style::StyleManager};
2use float_pigment_css::typing::{
3    AlignContent, AlignItems, AlignSelf, BoxSizing, Direction, FlexDirection, FlexWrap,
4    GridAutoFlow, JustifyContent, JustifyItems, JustifySelf, Overflow, Position, TextAlign,
5    WritingMode,
6};
7
8use float_pigment_css::{length_num::*, typing::Display};
9use float_pigment_layout::{ComputedStyle, DefLength, LayoutNode};
10pub use float_pigment_layout::{OptionNum, OptionSize, Size};
11use lru::LruCache;
12
13use std::{
14    cell::{Cell, Ref, RefCell, RefMut, UnsafeCell},
15    ptr::{self},
16};
17
18pub type Len = float_pigment_css::fixed::FixedI32<float_pigment_css::fixed::types::extra::U10>;
19pub type Length = DefLength<Len>;
20pub type LayoutGridTemplate = float_pigment_layout::LayoutGridTemplate<Len>;
21pub type LayoutGridAuto = float_pigment_layout::LayoutGridAuto<Len>;
22pub type NodeId = usize;
23pub type NodePtr = *mut Node;
24
25#[inline(always)]
26pub fn convert_node_ref_to_ptr(node: &Node) -> NodePtr {
27    node as *const Node as *mut Node
28}
29
30#[inline(always)]
31#[allow(clippy::missing_safety_doc)]
32pub unsafe fn get_ref_from_node_ptr(node_ptr: NodePtr) -> &'static Node {
33    &*node_ptr
34}
35
36pub type ExternalHostPtr = *mut ();
37
38pub(crate) type MeasureMinWidth = Len;
39pub(crate) type MeasureMinHeight = Len;
40pub(crate) type MeasureMaxWidth = Len;
41pub(crate) type MeasureMaxHeight = Len;
42pub(crate) type MeasureMaxContentWidth = Len;
43pub(crate) type MeasureMaxContentHeight = Len;
44
45pub(crate) type MeasureFn<L> = dyn Fn(
46    NodePtr,
47    MeasureMaxWidth,
48    MeasureMode,
49    MeasureMaxHeight,
50    MeasureMode,
51    MeasureMinWidth,
52    MeasureMinHeight,
53    MeasureMaxContentWidth,
54    MeasureMaxContentHeight,
55) -> Size<L>;
56
57pub(crate) type BaselineFn<L> = dyn Fn(NodePtr, L, L) -> L;
58pub(crate) type ResolveCalcFn<L> = dyn Fn(i32, L) -> L;
59pub(crate) type DirtyCallbackFn = dyn Fn(NodePtr);
60
61pub(crate) type MeasureCacheKeyMinSize = OptionSize<<Len as LengthNum>::Hashable>;
62pub(crate) type MeasureCacheKeyMaxSize = OptionSize<<Len as LengthNum>::Hashable>;
63pub(crate) type MeasureCacheKeyMaxContent = OptionSize<<Len as LengthNum>::Hashable>;
64pub(crate) type MeasureCache = LruCache<
65    (
66        MeasureCacheKeyMinSize,
67        MeasureCacheKeyMaxSize,
68        MeasureCacheKeyMaxContent,
69    ),
70    Size<Len>,
71>;
72pub(crate) type BaselineCache = LruCache<Size<<Len as LengthNum>::Hashable>, Len>;
73
74const CACHE_SIZE: usize = 3;
75
76#[repr(C)]
77#[derive(Copy, Clone)]
78pub enum MeasureMode {
79    Undefined,
80    Exactly,
81    AtMost,
82}
83
84#[derive(Copy, Clone, Debug)]
85pub struct DumpOptions {
86    pub recursive: bool,
87    pub layout: bool,
88    pub style: DumpStyleMode,
89}
90
91#[derive(Copy, Clone, Debug)]
92pub enum DumpStyleMode {
93    None,
94    Full,
95    Mutation,
96}
97
98pub trait DumpNode {
99    unsafe fn dump_to_html(&self, options: DumpOptions, current_depth: u8) -> String;
100}
101
102impl DumpNode for Node {
103    unsafe fn dump_to_html(&self, options: DumpOptions, current_depth: u8) -> String {
104        let layout = options.layout.then_some(format!(
105            "left: {}, top: {}, width: {}, height: {}",
106            self.layout_position().left,
107            self.layout_position().top,
108            self.layout_position().width,
109            self.layout_position().height,
110        ));
111        let style = match options.style {
112            DumpStyleMode::None => None,
113            DumpStyleMode::Mutation => Some(self.style_manager().mutation_to_string()),
114            DumpStyleMode::Full => Some(self.style_manager().style_to_string()),
115        };
116        let children = (options.recursive && !self.children().is_empty()).then_some({
117            let mut children_str = String::new();
118            children_str.push('\n');
119            self.children().iter().for_each(|child| {
120                let child_str = child.dump_to_html(options, current_depth + 1);
121                let tabs = (0..current_depth).map(|_| " ").collect::<String>();
122                children_str.push_str(&tabs);
123                children_str.push_str(&child_str);
124            });
125            children_str.push('\n');
126            children_str.to_string()
127        });
128        let mut tag: String = match self.style_manager().display() {
129            Display::None => "None".into(),
130            Display::Block => "Block".into(),
131            Display::Flex => "Flex".into(),
132            Display::Inline => "Inline".into(),
133            Display::InlineBlock => "InlineBlock".into(),
134            Display::FlowRoot => "FlowRoot".into(),
135            Display::Grid => "Grid".into(),
136            Display::InlineFlex => "InlineFlex".into(),
137            Display::InlineGrid => "InlineGrid".into(),
138        };
139        if self.has_measure_func() {
140            tag = format!("Measurable{tag}");
141        }
142        if let Some(children) = children {
143            if let Some(style) = style {
144                format!(
145                    "<{}#{:p} layout=\"{}\", style=\"{}\">{}",
146                    tag,
147                    self,
148                    layout.unwrap_or_default(),
149                    style,
150                    children,
151                )
152            } else {
153                format!(
154                    "<{}#{:p} layout=\"{}\">{}",
155                    tag,
156                    self,
157                    layout.unwrap_or_default(),
158                    children,
159                )
160            }
161        } else if let Some(style) = style {
162            format!(
163                "<{}#{:p} layout=\"{}\", style=\"{}\"/>\n",
164                tag,
165                self,
166                layout.unwrap_or_default(),
167                style,
168            )
169        } else {
170            format!(
171                "<{}#{:p} layout=\"{}\"/>\n",
172                tag,
173                self,
174                layout.unwrap_or_default(),
175            )
176        }
177    }
178}
179#[repr(C)]
180#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
181pub enum NodeType {
182    Normal,
183    Text,
184    #[allow(unused)]
185    Image,
186}
187
188#[repr(C)]
189#[derive(Debug)]
190pub struct Node {
191    node_type: Cell<NodeType>,
192    is_dirty: Cell<bool>,
193    external_host: Cell<ExternalHostPtr>,
194    parent: Cell<NodePtr>,
195    children: RefCell<Vec<NodePtr>>,
196    style_manager: RefCell<StyleManager>,
197    pub(crate) layout_node: LayoutNode<Node>,
198    measure_cache: UnsafeCell<Option<Box<MeasureCache>>>,
199    baseline_cache: UnsafeCell<Option<Box<BaselineCache>>>,
200    baseline_func: UnsafeCell<Option<Box<BaselineFn<Len>>>>,
201    measure_func: UnsafeCell<Option<Box<MeasureFn<Len>>>>,
202    resolve_calc: UnsafeCell<Option<Box<ResolveCalcFn<Len>>>>,
203    dirty_callback: UnsafeCell<Option<Box<DirtyCallbackFn>>>,
204}
205
206impl Node {
207    pub fn new() -> Self {
208        Self {
209            node_type: Cell::new(NodeType::Normal),
210            external_host: Cell::new(std::ptr::null_mut()),
211            children: RefCell::new(Vec::with_capacity(0)),
212            parent: Cell::new(std::ptr::null_mut()),
213            style_manager: RefCell::new(StyleManager::new()),
214            layout_node: LayoutNode::new(),
215            is_dirty: Cell::new(true),
216            baseline_func: UnsafeCell::new(None),
217            measure_func: UnsafeCell::new(None),
218            resolve_calc: UnsafeCell::new(None),
219            dirty_callback: UnsafeCell::new(None),
220            measure_cache: UnsafeCell::new(None),
221            baseline_cache: UnsafeCell::new(None),
222        }
223    }
224    pub fn new_typed(node_type: NodeType) -> Self {
225        let ret = Self::new();
226        ret.node_type.set(node_type);
227        ret
228    }
229    pub fn new_ptr() -> NodePtr {
230        let self_node = Box::new(Self::new());
231        Box::into_raw(self_node)
232    }
233    pub unsafe fn parent<'a>(&self) -> Option<&'a Node> {
234        if self.parent.get().is_null() {
235            None
236        } else {
237            Some(&*self.parent.get())
238        }
239    }
240    pub fn set_parent(&self, parent: Option<NodePtr>) {
241        if let Some(parent) = parent {
242            self.parent.replace(parent);
243        } else {
244            self.parent.replace(std::ptr::null_mut());
245        }
246    }
247    pub fn parent_ptr(&self) -> Option<NodePtr> {
248        if self.parent.get().is_null() {
249            None
250        } else {
251            Some(self.parent.get())
252        }
253    }
254    pub unsafe fn children(&self) -> Vec<&Node> {
255        self.children
256            .borrow()
257            .iter()
258            .map(|node| &**node)
259            .collect::<Vec<_>>()
260    }
261    pub fn children_len(&self) -> usize {
262        self.children.borrow().len()
263    }
264    pub(crate) fn style_manager(&self) -> Ref<'_, StyleManager> {
265        self.style_manager.borrow()
266    }
267    pub(crate) fn style_manager_mut(&self) -> RefMut<'_, StyleManager> {
268        self.style_manager.borrow_mut()
269    }
270    pub(crate) fn computed_style(&self) -> ComputedStyle<Len> {
271        self.layout_node.computed_style()
272    }
273    pub unsafe fn set_node_type(&self, node_type: NodeType) {
274        let prev_type = self.node_type.get();
275        if prev_type != node_type {
276            if prev_type == NodeType::Text {
277                *self.measure_cache.get() = None;
278                *self.baseline_cache.get() = None;
279            }
280            self.node_type.replace(node_type);
281        }
282        if node_type == NodeType::Text && node_type != prev_type {
283            *self.measure_cache.get() = Some(Box::new(LruCache::new(CACHE_SIZE)));
284            *self.baseline_cache.get() = Some(Box::new(LruCache::new(CACHE_SIZE)));
285        }
286    }
287    #[allow(clippy::mut_from_ref)]
288    #[inline(always)]
289    pub(crate) unsafe fn measure_cache(&self) -> Option<&mut MeasureCache> {
290        if self.node_type() != NodeType::Text {
291            return None;
292        }
293        (*self.measure_cache.get()).as_deref_mut()
294    }
295
296    pub(crate) unsafe fn clear_measure_cache(&self) {
297        if let Some(cache) = self.measure_cache() {
298            cache.clear();
299        }
300    }
301
302    #[allow(clippy::mut_from_ref)]
303    #[inline(always)]
304    pub(crate) unsafe fn baseline_cache(&self) -> Option<&mut BaselineCache> {
305        if self.node_type() != NodeType::Text {
306            return None;
307        }
308        (*self.baseline_cache.get()).as_deref_mut()
309    }
310
311    pub(crate) unsafe fn clear_baseline_cache(&self) {
312        if let Some(cache) = self.baseline_cache() {
313            cache.clear();
314        }
315    }
316    pub(crate) fn node_type(&self) -> NodeType {
317        self.node_type.get()
318    }
319    pub(crate) unsafe fn baseline_func(&self) -> Option<&BaselineFn<Len>> {
320        (*self.baseline_func.get()).as_deref()
321    }
322    pub fn set_baseline_func(&self, baseline_func: Option<Box<BaselineFn<Len>>>) {
323        drop(std::mem::replace(
324            unsafe { &mut *self.baseline_func.get() },
325            baseline_func,
326        ));
327    }
328    pub unsafe fn has_baseline_func(&self) -> bool {
329        (*self.baseline_func.get()).is_some()
330    }
331    pub(crate) unsafe fn measure_func(&self) -> Option<&MeasureFn<Len>> {
332        (*self.measure_func.get()).as_deref()
333    }
334    pub fn set_measure_func(&self, measure_func: Option<Box<MeasureFn<Len>>>) {
335        drop(std::mem::replace(
336            unsafe { &mut *self.measure_func.get() },
337            measure_func,
338        ));
339    }
340    pub fn has_measure_func(&self) -> bool {
341        unsafe { (*self.measure_func.get()).is_some() }
342    }
343    pub(crate) fn resolve_calc(&self) -> Option<&ResolveCalcFn<Len>> {
344        unsafe { (*self.resolve_calc.get()).as_deref() }
345    }
346    pub fn set_resolve_calc(&self, resolve_calc: Option<Box<ResolveCalcFn<Len>>>) {
347        drop(std::mem::replace(
348            unsafe { &mut *self.resolve_calc.get() },
349            resolve_calc,
350        ))
351    }
352    pub fn set_dirty_callback(&self, dirty_callback: Option<Box<DirtyCallbackFn>>) {
353        drop(std::mem::replace(
354            unsafe { &mut *self.dirty_callback.get() },
355            dirty_callback,
356        ));
357    }
358    pub fn has_dirty_callback(&self) -> bool {
359        unsafe { (*self.dirty_callback.get()).is_some() }
360    }
361    pub(crate) fn dirty_callback(&self) -> Option<&DirtyCallbackFn> {
362        unsafe { (*self.dirty_callback.get()).as_deref() }
363    }
364    pub fn external_host(&self) -> Option<ExternalHostPtr> {
365        if self.external_host.get().is_null() {
366            None
367        } else {
368            Some(self.external_host.get())
369        }
370    }
371    pub fn set_external_host(&self, external_host: Option<ExternalHostPtr>) {
372        if let Some(external_host) = external_host {
373            self.external_host.replace(external_host);
374        } else {
375            self.external_host.replace(std::ptr::null_mut());
376        }
377    }
378    pub(crate) fn is_dirty(&self) -> bool {
379        self.is_dirty.get()
380    }
381    pub(crate) fn clear_dirty(&self) {
382        self.is_dirty.set(false)
383    }
384    pub(crate) unsafe fn clear_dirty_recursive(&self) {
385        if self.is_dirty() {
386            self.clear_dirty();
387            self.children()
388                .iter()
389                .for_each(|child| child.clear_dirty_recursive());
390        }
391    }
392    pub unsafe fn mark_self_dirty(&self) {
393        if self.is_dirty() {
394            return;
395        }
396        self.is_dirty.set(true);
397        if self.node_type() == NodeType::Text {
398            self.clear_measure_cache();
399            self.clear_baseline_cache();
400        }
401        if let Some(dirty_callback) = self.dirty_callback() {
402            dirty_callback(convert_node_ref_to_ptr(self))
403        }
404        self.layout_node.mark_dirty(self);
405    }
406    pub unsafe fn mark_dirty_propagate_to_descendants(&self) {
407        self.mark_self_dirty();
408        unsafe {
409            self.children
410                .borrow()
411                .iter()
412                .for_each(|node| (**node).mark_dirty_propagate_to_descendants())
413        }
414    }
415    pub unsafe fn mark_dirty_propagate(&self) {
416        if !self.is_dirty() {
417            self.mark_self_dirty();
418            if let Some(parent) = self.parent() {
419                parent.mark_dirty_propagate()
420            }
421        }
422    }
423    pub fn dry_layout(
424        &self,
425        available_size: OptionSize<Len>,
426        viewport_size: float_pigment_layout::Size<Len>,
427    ) {
428        // FIXME
429        self.layout_node.update_with_containing_size(
430            &mut Env {
431                screen_width: viewport_size.width,
432                screen_height: viewport_size.height,
433            },
434            self,
435            available_size,
436            available_size,
437        );
438    }
439    pub unsafe fn layout(
440        &self,
441        available_size: OptionSize<Len>,
442        viewport_size: float_pigment_layout::Size<Len>,
443    ) {
444        // FIXME
445        self.layout_node.update_with_containing_size(
446            &mut Env {
447                screen_width: viewport_size.width,
448                screen_height: viewport_size.height,
449            },
450            self,
451            available_size,
452            available_size,
453        );
454        self.clear_dirty_recursive();
455    }
456
457    pub unsafe fn layout_with_containing_size(
458        &self,
459        available_size: OptionSize<Len>,
460        viewport_size: float_pigment_layout::Size<Len>,
461        containing_size: OptionSize<Len>,
462    ) {
463        self.layout_node.update_with_containing_size(
464            &mut Env {
465                screen_width: viewport_size.width,
466                screen_height: viewport_size.height,
467            },
468            self,
469            available_size,
470            containing_size,
471        );
472        self.clear_dirty_recursive();
473    }
474
475    pub fn layout_position(&self) -> LayoutPosition {
476        let layout = self.layout_node.result();
477        LayoutPosition {
478            left: layout.origin.x,
479            top: layout.origin.y,
480            width: layout.size.width,
481            height: layout.size.height,
482        }
483    }
484}
485
486impl Default for Node {
487    fn default() -> Self {
488        Self::new()
489    }
490}
491pub trait ChildOperation {
492    unsafe fn get_child_at(&self, idx: usize) -> Option<&Node>;
493    unsafe fn get_child_ptr_at(&self, idx: usize) -> Option<NodePtr>;
494    unsafe fn get_child_index(&self, child: NodePtr) -> Option<usize>;
495    unsafe fn append_child(&self, child: NodePtr);
496    unsafe fn insert_child_at(&self, child: NodePtr, idx: usize);
497    unsafe fn insert_child_before(&self, child: NodePtr, pivot: NodePtr);
498    unsafe fn remove_child(&self, child: NodePtr);
499    unsafe fn remove_child_at(&self, idx: usize);
500    unsafe fn remove_all_children(&self);
501    unsafe fn for_each_child_node<'a, 'b: 'a, F>(&'b self, func: F)
502    where
503        F: FnMut(&'a Self, usize);
504}
505
506impl ChildOperation for Node {
507    unsafe fn get_child_at(&self, idx: usize) -> Option<&Node> {
508        self.children().get(idx).copied()
509    }
510    unsafe fn get_child_ptr_at(&self, idx: usize) -> Option<NodePtr> {
511        self.children.borrow().get(idx).copied()
512    }
513    unsafe fn get_child_index(&self, child: NodePtr) -> Option<usize> {
514        self.children()
515            .iter()
516            .position(|node| ptr::eq(*node, child))
517    }
518    #[allow(clippy::not_unsafe_ptr_arg_deref)]
519    unsafe fn append_child(&self, child: NodePtr) {
520        if let Some(prev_parent) = (*child).parent() {
521            prev_parent.remove_child(child);
522        }
523        (*child).set_parent(Some(convert_node_ref_to_ptr(self)));
524        self.children.borrow_mut().push(child);
525        self.mark_dirty_propagate()
526    }
527    #[allow(clippy::not_unsafe_ptr_arg_deref)]
528    unsafe fn insert_child_at(&self, child: NodePtr, idx: usize) {
529        if let Some(prev_parent) = (*child).parent() {
530            prev_parent.remove_child(child);
531        }
532        (*child).set_parent(Some(convert_node_ref_to_ptr(self)));
533        self.children.borrow_mut().insert(idx, child);
534        self.mark_dirty_propagate()
535    }
536    #[allow(clippy::not_unsafe_ptr_arg_deref)]
537    unsafe fn insert_child_before(&self, child: NodePtr, pivot: NodePtr) {
538        if let Some(prev_parent) = (*child).parent() {
539            prev_parent.remove_child(child);
540        }
541        (*child).set_parent(Some(convert_node_ref_to_ptr(self)));
542        let idx = self
543            .children
544            .borrow()
545            .iter()
546            .position(|node| std::ptr::eq(*node, pivot));
547        if let Some(idx) = idx {
548            self.children.borrow_mut().insert(idx, child)
549        }
550        self.mark_dirty_propagate();
551    }
552    unsafe fn remove_child(&self, child: NodePtr) {
553        if self.children_len() == 0 {
554            return;
555        }
556        let child_idx_opt = self
557            .children
558            .borrow()
559            .iter()
560            .position(|node| std::ptr::eq(*node, child));
561        if let Some(child_idx) = child_idx_opt {
562            let node = {
563                let mut children = self.children.borrow_mut();
564                let node = children[child_idx];
565                children.remove(child_idx);
566                node
567            };
568            (*node).set_parent(None);
569        }
570
571        self.mark_dirty_propagate();
572    }
573    unsafe fn remove_child_at(&self, idx: usize) {
574        let len = self.children_len();
575        if len == 0 || idx >= len {
576            return;
577        }
578        if let Some(node) = self.children.borrow().get(idx) {
579            (**node).set_parent(None);
580        }
581        self.children.borrow_mut().remove(idx);
582        self.mark_dirty_propagate();
583    }
584    unsafe fn remove_all_children(&self) {
585        self.for_each_child_node(|node, _| {
586            (*node).set_parent(None);
587        });
588        self.children.borrow_mut().clear();
589        self.mark_dirty_propagate()
590    }
591    unsafe fn for_each_child_node<'a, 'b: 'a, F>(&'b self, func: F)
592    where
593        F: FnMut(&'a Self, usize),
594    {
595        let mut func = func;
596        self.children
597            .borrow_mut()
598            .iter_mut()
599            .enumerate()
600            .for_each(|(idx, node)| func(&**node, idx))
601    }
602}
603
604pub trait StyleSetter {
605    unsafe fn set_display(&self, value: Display);
606    unsafe fn set_box_sizing(&self, value: BoxSizing);
607    unsafe fn set_direction(&self, value: Direction);
608    unsafe fn set_writing_mode(&self, value: WritingMode);
609    unsafe fn set_position(&self, value: Position);
610    unsafe fn set_left(&self, value: Length);
611    unsafe fn set_top(&self, value: Length);
612    unsafe fn set_right(&self, value: Length);
613    unsafe fn set_bottom(&self, value: Length);
614    unsafe fn set_overflow_x(&self, value: Overflow);
615    unsafe fn set_overflow_y(&self, value: Overflow);
616    unsafe fn set_width(&self, value: Length);
617    unsafe fn set_height(&self, value: Length);
618    unsafe fn set_min_width(&self, value: Length);
619    unsafe fn set_min_height(&self, value: Length);
620    unsafe fn set_max_width(&self, value: Length);
621    unsafe fn set_max_height(&self, value: Length);
622    unsafe fn set_margin(&self, value: Length);
623    unsafe fn set_margin_left(&self, value: Length);
624    unsafe fn set_margin_top(&self, value: Length);
625    unsafe fn set_margin_right(&self, value: Length);
626    unsafe fn set_margin_bottom(&self, value: Length);
627    unsafe fn set_padding(&self, value: Length);
628    unsafe fn set_padding_left(&self, value: Length);
629    unsafe fn set_padding_top(&self, value: Length);
630    unsafe fn set_padding_right(&self, value: Length);
631    unsafe fn set_padding_bottom(&self, value: Length);
632    unsafe fn set_border(&self, value: Length);
633    unsafe fn set_border_left(&self, value: Length);
634    unsafe fn set_border_top(&self, value: Length);
635    unsafe fn set_border_right(&self, value: Length);
636    unsafe fn set_border_bottom(&self, value: Length);
637    unsafe fn set_flex_grow(&self, value: f32);
638    unsafe fn set_flex_shrink(&self, value: f32);
639    unsafe fn set_flex_basis(&self, value: Length);
640    unsafe fn set_flex_direction(&self, value: FlexDirection);
641    unsafe fn set_flex_wrap(&self, value: FlexWrap);
642    unsafe fn set_justify_content(&self, value: JustifyContent);
643    unsafe fn set_align_content(&self, value: AlignContent);
644    unsafe fn set_align_items(&self, value: AlignItems);
645    unsafe fn set_align_self(&self, value: AlignSelf);
646    unsafe fn set_justify_items(&self, value: JustifyItems);
647    unsafe fn set_justify_self(&self, value: JustifySelf);
648    unsafe fn set_aspect_ratio(&self, value: Option<f32>);
649    unsafe fn set_order(&self, value: i32);
650    unsafe fn set_text_align(&self, value: TextAlign);
651    unsafe fn set_row_gap(&self, value: Length);
652    unsafe fn set_column_gap(&self, value: Length);
653    unsafe fn set_grid_template_rows(&self, value: LayoutGridTemplate);
654    unsafe fn set_grid_template_columns(&self, value: LayoutGridTemplate);
655    unsafe fn set_grid_auto_flow(&self, value: GridAutoFlow);
656    unsafe fn set_grid_auto_rows(&self, value: LayoutGridAuto);
657    unsafe fn set_grid_auto_columns(&self, value: LayoutGridAuto);
658}
659
660impl StyleSetter for Node {
661    unsafe fn set_flex_direction(&self, flex_direction: FlexDirection) {
662        if self.style_manager_mut().set_flex_direction(flex_direction) {
663            self.mark_dirty_propagate();
664        }
665    }
666    unsafe fn set_direction(&self, direction: Direction) {
667        if self.style_manager_mut().set_direction(direction) {
668            self.mark_dirty_propagate();
669        }
670    }
671    unsafe fn set_align_content(&self, align_content: AlignContent) {
672        if self.style_manager_mut().set_align_content(align_content) {
673            self.mark_dirty_propagate();
674        }
675    }
676    unsafe fn set_align_items(&self, align_items: AlignItems) {
677        if self.style_manager_mut().set_align_items(align_items) {
678            self.mark_dirty_propagate();
679        }
680    }
681    unsafe fn set_align_self(&self, align_self: AlignSelf) {
682        if self.style_manager_mut().set_align_self(align_self) {
683            self.mark_dirty_propagate();
684        }
685    }
686    unsafe fn set_justify_items(&self, justify_items: JustifyItems) {
687        if self.style_manager_mut().set_justify_items(justify_items) {
688            self.mark_dirty_propagate();
689        }
690    }
691    unsafe fn set_justify_self(&self, justify_self: JustifySelf) {
692        if self.style_manager_mut().set_justify_self(justify_self) {
693            self.mark_dirty_propagate();
694        }
695    }
696    unsafe fn set_aspect_ratio(&self, aspect_ratio: Option<f32>) {
697        if self.style_manager_mut().set_aspect_ratio(aspect_ratio) {
698            self.mark_dirty_propagate();
699        }
700    }
701    unsafe fn set_border(&self, border: Length) {
702        let top_changed = self.style_manager_mut().set_border_top(border);
703        let right_changed = self.style_manager_mut().set_border_right(border);
704        let bottom_changed = self.style_manager_mut().set_border_bottom(border);
705        let left_changed = self.style_manager_mut().set_border_left(border);
706        if top_changed || right_changed || bottom_changed || left_changed {
707            self.mark_dirty_propagate();
708        }
709    }
710    unsafe fn set_border_left(&self, border_left: Length) {
711        if self.style_manager_mut().set_border_left(border_left) {
712            self.mark_dirty_propagate();
713        }
714    }
715    unsafe fn set_border_right(&self, border_right: Length) {
716        if self.style_manager_mut().set_border_right(border_right) {
717            self.mark_dirty_propagate();
718        }
719    }
720    unsafe fn set_border_top(&self, border_top: Length) {
721        if self.style_manager_mut().set_border_top(border_top) {
722            self.mark_dirty_propagate();
723        }
724    }
725    unsafe fn set_border_bottom(&self, border_bottom: Length) {
726        if self.style_manager_mut().set_border_bottom(border_bottom) {
727            self.mark_dirty_propagate();
728        }
729    }
730    unsafe fn set_box_sizing(&self, box_sizing: BoxSizing) {
731        if self.style_manager_mut().set_box_sizing(box_sizing) {
732            self.mark_dirty_propagate();
733        }
734    }
735    unsafe fn set_display(&self, display: Display) {
736        if self.style_manager_mut().set_display(display) {
737            self.mark_dirty_propagate();
738        }
739    }
740    unsafe fn set_height(&self, height: Length) {
741        if self.style_manager_mut().set_height(height) {
742            self.mark_dirty_propagate();
743        }
744    }
745    unsafe fn set_width(&self, width: Length) {
746        if self.style_manager_mut().set_width(width) {
747            self.mark_dirty_propagate();
748        }
749    }
750    unsafe fn set_left(&self, left: Length) {
751        if self.style_manager_mut().set_left(left) {
752            self.mark_dirty_propagate();
753        }
754    }
755    unsafe fn set_right(&self, right: Length) {
756        if self.style_manager_mut().set_right(right) {
757            self.mark_dirty_propagate();
758        }
759    }
760    unsafe fn set_top(&self, top: Length) {
761        if self.style_manager_mut().set_top(top) {
762            self.mark_dirty_propagate();
763        }
764    }
765    unsafe fn set_bottom(&self, bottom: Length) {
766        if self.style_manager_mut().set_bottom(bottom) {
767            self.mark_dirty_propagate();
768        }
769    }
770    unsafe fn set_flex_shrink(&self, flex_shrink: f32) {
771        if self.style_manager_mut().set_flex_shrink(flex_shrink) {
772            self.mark_dirty_propagate();
773        }
774    }
775    unsafe fn set_flex_grow(&self, flex_grow: f32) {
776        if self.style_manager_mut().set_flex_grow(flex_grow) {
777            self.mark_dirty_propagate();
778        }
779    }
780    unsafe fn set_flex_wrap(&self, flex_wrap: FlexWrap) {
781        if self.style_manager_mut().set_flex_wrap(flex_wrap) {
782            self.mark_dirty_propagate();
783        }
784    }
785    unsafe fn set_flex_basis(&self, flex_basis: Length) {
786        if self.style_manager_mut().set_flex_basis(flex_basis) {
787            self.mark_dirty_propagate();
788        }
789    }
790    unsafe fn set_justify_content(&self, justify_content: JustifyContent) {
791        if self
792            .style_manager_mut()
793            .set_justify_content(justify_content)
794        {
795            self.mark_dirty_propagate();
796        }
797    }
798    unsafe fn set_position(&self, position: Position) {
799        if self.style_manager_mut().set_position(position) {
800            self.mark_dirty_propagate();
801        }
802    }
803    unsafe fn set_overflow_x(&self, overflow_x: Overflow) {
804        if self.style_manager_mut().set_overflow_x(overflow_x) {
805            self.mark_dirty_propagate();
806        }
807    }
808    unsafe fn set_overflow_y(&self, overflow_y: Overflow) {
809        if self.style_manager_mut().set_overflow_y(overflow_y) {
810            self.mark_dirty_propagate();
811        }
812    }
813    unsafe fn set_writing_mode(&self, writing_mode: WritingMode) {
814        if self.style_manager_mut().set_writing_mode(writing_mode) {
815            self.mark_dirty_propagate();
816        }
817    }
818    unsafe fn set_margin(&self, margin: Length) {
819        let top_changed = self.style_manager_mut().set_margin_top(margin);
820        let right_changed = self.style_manager_mut().set_margin_right(margin);
821        let bottom_changed = self.style_manager_mut().set_margin_bottom(margin);
822        let left_changed = self.style_manager_mut().set_margin_left(margin);
823        if top_changed || bottom_changed || right_changed || left_changed {
824            self.mark_dirty_propagate();
825        }
826    }
827    unsafe fn set_margin_bottom(&self, margin_bottom: Length) {
828        if self.style_manager_mut().set_margin_bottom(margin_bottom) {
829            self.mark_dirty_propagate();
830        }
831    }
832    unsafe fn set_margin_left(&self, margin_left: Length) {
833        if self.style_manager_mut().set_margin_left(margin_left) {
834            self.mark_dirty_propagate();
835        }
836    }
837    unsafe fn set_margin_right(&self, margin_right: Length) {
838        if self.style_manager_mut().set_margin_right(margin_right) {
839            self.mark_dirty_propagate();
840        }
841    }
842    unsafe fn set_margin_top(&self, margin_top: Length) {
843        if self.style_manager_mut().set_margin_top(margin_top) {
844            self.mark_dirty_propagate();
845        }
846    }
847    unsafe fn set_max_height(&self, max_height: Length) {
848        if self.style_manager_mut().set_max_height(max_height) {
849            self.mark_dirty_propagate();
850        }
851    }
852    unsafe fn set_max_width(&self, max_width: Length) {
853        if self.style_manager_mut().set_max_width(max_width) {
854            self.mark_dirty_propagate();
855        }
856    }
857    unsafe fn set_min_height(&self, min_height: Length) {
858        if self.style_manager_mut().set_min_height(min_height) {
859            self.mark_dirty_propagate();
860        }
861    }
862
863    unsafe fn set_min_width(&self, min_width: Length) {
864        if self.style_manager_mut().set_min_width(min_width) {
865            self.mark_dirty_propagate();
866        }
867    }
868    unsafe fn set_padding(&self, padding: Length) {
869        let top_changed = self.style_manager_mut().set_padding_top(padding);
870        let right_changed = self.style_manager_mut().set_padding_right(padding);
871        let bottom_changed = self.style_manager_mut().set_padding_bottom(padding);
872        let left_changed = self.style_manager_mut().set_padding_left(padding);
873        if top_changed || bottom_changed || left_changed || right_changed {
874            self.mark_dirty_propagate();
875        }
876    }
877    unsafe fn set_padding_left(&self, padding_left: Length) {
878        if self.style_manager_mut().set_padding_left(padding_left) {
879            self.mark_dirty_propagate();
880        }
881    }
882    unsafe fn set_padding_right(&self, padding_right: Length) {
883        if self.style_manager_mut().set_padding_right(padding_right) {
884            self.mark_dirty_propagate();
885        }
886    }
887    unsafe fn set_padding_top(&self, padding_top: Length) {
888        if self.style_manager_mut().set_padding_top(padding_top) {
889            self.mark_dirty_propagate();
890        }
891    }
892    unsafe fn set_padding_bottom(&self, padding_bottom: Length) {
893        if self.style_manager_mut().set_padding_bottom(padding_bottom) {
894            self.mark_dirty_propagate();
895        }
896    }
897    unsafe fn set_order(&self, order: i32) {
898        if self.style_manager_mut().set_order(order) {
899            self.mark_dirty_propagate();
900        }
901    }
902    unsafe fn set_text_align(&self, text_align: TextAlign) {
903        if self.style_manager_mut().set_text_align(text_align) {
904            self.mark_dirty_propagate();
905        }
906    }
907    unsafe fn set_row_gap(&self, value: Length) {
908        if self.style_manager_mut().set_row_gap(value) {
909            self.mark_dirty_propagate();
910        }
911    }
912    unsafe fn set_column_gap(&self, value: Length) {
913        if self.style_manager_mut().set_column_gap(value) {
914            self.mark_dirty_propagate();
915        }
916    }
917    unsafe fn set_grid_template_rows(&self, value: LayoutGridTemplate) {
918        if self.style_manager_mut().set_grid_template_rows(value) {
919            self.mark_dirty_propagate();
920        }
921    }
922    unsafe fn set_grid_template_columns(&self, value: LayoutGridTemplate) {
923        if self.style_manager_mut().set_grid_template_columns(value) {
924            self.mark_dirty_propagate();
925        }
926    }
927    unsafe fn set_grid_auto_flow(&self, value: GridAutoFlow) {
928        if self.style_manager_mut().set_grid_auto_flow(value) {
929            self.mark_dirty_propagate();
930        }
931    }
932    unsafe fn set_grid_auto_rows(&self, value: LayoutGridAuto) {
933        if self.style_manager_mut().set_grid_auto_rows(value) {
934            self.mark_dirty_propagate();
935        }
936    }
937    unsafe fn set_grid_auto_columns(&self, value: LayoutGridAuto) {
938        if self.style_manager_mut().set_grid_auto_columns(value) {
939            self.mark_dirty_propagate();
940        }
941    }
942}
943
944#[cfg(test)]
945mod test {
946    use crate::node::NodePtr;
947
948    use super::*;
949    fn new_node<'a>() -> (&'a Node, NodePtr) {
950        let node_ptr = Node::new_ptr();
951        (unsafe { get_ref_from_node_ptr(node_ptr) }, node_ptr)
952    }
953    #[test]
954    fn append_child() {
955        let (node_a, node_a_ptr) = new_node();
956        let (node_b, node_b_ptr) = new_node();
957        unsafe {
958            node_a.append_child(node_b_ptr);
959            assert!(std::ptr::eq(node_a, node_b.parent().unwrap()));
960            assert!(std::ptr::eq(node_a.get_child_at(0).unwrap(), node_b));
961            drop(Box::from_raw(node_a_ptr));
962            drop(Box::from_raw(node_b_ptr));
963        }
964    }
965    #[test]
966    fn insert_child_at() {
967        let (node_a, node_a_ptr) = new_node();
968        let (node_b, node_b_ptr) = new_node();
969        let (node_c, node_c_ptr) = new_node();
970        unsafe {
971            node_a.insert_child_at(node_b_ptr, 0);
972            node_a.insert_child_at(node_c_ptr, 0);
973            assert!(std::ptr::eq(node_a, node_b.parent().unwrap()));
974            assert!(std::ptr::eq(node_a, node_c.parent().unwrap()));
975            assert!(std::ptr::eq(node_a.get_child_at(0).unwrap(), node_c));
976            assert!(std::ptr::eq(node_a.get_child_at(1).unwrap(), node_b));
977            drop(Box::from_raw(node_a_ptr));
978            drop(Box::from_raw(node_b_ptr));
979            drop(Box::from_raw(node_c_ptr));
980        }
981    }
982
983    #[test]
984    fn remove_child() {
985        let (node_a, node_a_ptr) = new_node();
986        let (node_b, node_b_ptr) = new_node();
987        unsafe {
988            node_a.insert_child_at(node_b_ptr, 0);
989            assert!(std::ptr::eq(node_a, node_b.parent().unwrap()));
990            assert!(std::ptr::eq(node_a.get_child_at(0).unwrap(), node_b));
991            node_a.remove_child(node_b_ptr);
992            assert!(node_b.parent().is_none());
993            assert_eq!(node_a.children_len(), 0usize);
994            drop(Box::from_raw(node_a_ptr));
995            drop(Box::from_raw(node_b_ptr));
996        }
997    }
998
999    #[test]
1000    fn remove_child_at() {
1001        let (node_a, node_a_ptr) = new_node();
1002        let (node_b, node_b_ptr) = new_node();
1003        unsafe {
1004            node_a.insert_child_at(node_b_ptr, 0);
1005            assert!(std::ptr::eq(node_a, node_b.parent().unwrap()));
1006            assert!(std::ptr::eq(node_a.get_child_at(0).unwrap(), node_b));
1007            node_a.remove_child_at(0);
1008            assert_eq!(node_a.children_len(), 0usize);
1009            assert!(node_b.parent().is_none());
1010            drop(Box::from_raw(node_a_ptr));
1011            drop(Box::from_raw(node_b_ptr));
1012        }
1013    }
1014}