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