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<'a>(&self) -> Option<&'a 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        let prev_type = self.node_type.get();
271        if prev_type != node_type {
272            if prev_type == NodeType::Text {
273                *self.measure_cache.get() = None;
274                *self.baseline_cache.get() = None;
275            }
276            self.node_type.replace(node_type);
277        }
278        if node_type == NodeType::Text && node_type != prev_type {
279            *self.measure_cache.get() = Some(Box::new(LruCache::new(CACHE_SIZE)));
280            *self.baseline_cache.get() = Some(Box::new(LruCache::new(CACHE_SIZE)));
281        }
282    }
283
284    #[inline(always)]
285    pub(crate) unsafe fn measure_cache(&self) -> Option<&mut MeasureCache> {
286        if self.node_type() != NodeType::Text {
287            return None;
288        }
289        (*self.measure_cache.get()).as_deref_mut()
290    }
291
292    pub(crate) unsafe fn clear_measure_cache(&self) {
293        if let Some(cache) = self.measure_cache() {
294            cache.clear();
295        }
296    }
297
298    #[inline(always)]
299    pub(crate) unsafe fn baseline_cache(&self) -> Option<&mut BaselineCache> {
300        if self.node_type() != NodeType::Text {
301            return None;
302        }
303        (*self.baseline_cache.get()).as_deref_mut()
304    }
305
306    pub(crate) unsafe fn clear_baseline_cache(&self) {
307        if let Some(cache) = self.baseline_cache() {
308            cache.clear();
309        }
310    }
311    pub(crate) fn node_type(&self) -> NodeType {
312        self.node_type.get()
313    }
314    pub(crate) unsafe fn baseline_func(&self) -> Option<&BaselineFn<Len>> {
315        (*self.baseline_func.get()).as_deref()
316    }
317    pub unsafe fn set_baseline_func(&self, baseline_func: Option<Box<BaselineFn<Len>>>) {
318        drop(std::mem::replace(
319            &mut *self.baseline_func.get(),
320            baseline_func,
321        ));
322    }
323    pub unsafe fn has_baseline_func(&self) -> bool {
324        (*self.baseline_func.get()).is_some()
325    }
326    pub(crate) unsafe fn measure_func(&self) -> Option<&MeasureFn<Len>> {
327        (*self.measure_func.get()).as_deref()
328    }
329    pub fn set_measure_func(&self, measure_func: Option<Box<MeasureFn<Len>>>) {
330        drop(std::mem::replace(
331            unsafe { &mut *self.measure_func.get() },
332            measure_func,
333        ));
334    }
335    pub fn has_measure_func(&self) -> bool {
336        unsafe { (*self.measure_func.get()).is_some() }
337    }
338    pub(crate) fn resolve_calc(&self) -> Option<&ResolveCalcFn<Len>> {
339        unsafe { (*self.resolve_calc.get()).as_deref() }
340    }
341    pub fn set_resolve_calc(&self, resolve_calc: Option<Box<ResolveCalcFn<Len>>>) {
342        drop(std::mem::replace(
343            unsafe { &mut *self.resolve_calc.get() },
344            resolve_calc,
345        ))
346    }
347    pub fn set_dirty_callback(&self, dirty_callback: Option<Box<DirtyCallbackFn>>) {
348        drop(std::mem::replace(
349            unsafe { &mut *self.dirty_callback.get() },
350            dirty_callback,
351        ));
352    }
353    pub fn has_dirty_callback(&self) -> bool {
354        unsafe { (*self.dirty_callback.get()).is_some() }
355    }
356    pub(crate) fn dirty_callback(&self) -> Option<&DirtyCallbackFn> {
357        unsafe { (*self.dirty_callback.get()).as_deref() }
358    }
359    pub fn external_host(&self) -> Option<ExternalHostPtr> {
360        if self.external_host.get().is_null() {
361            None
362        } else {
363            Some(self.external_host.get())
364        }
365    }
366    pub fn set_external_host(&self, external_host: Option<ExternalHostPtr>) {
367        if let Some(external_host) = external_host {
368            self.external_host.replace(external_host);
369        } else {
370            self.external_host.replace(std::ptr::null_mut());
371        }
372    }
373    pub(crate) fn is_dirty(&self) -> bool {
374        self.is_dirty.get()
375    }
376    pub(crate) fn clear_dirty(&self) {
377        self.is_dirty.set(false)
378    }
379    pub(crate) unsafe fn clear_dirty_recursive(&self) {
380        if self.is_dirty() {
381            self.clear_dirty();
382            self.children()
383                .iter()
384                .for_each(|child| child.clear_dirty_recursive());
385        }
386    }
387    pub unsafe fn mark_self_dirty(&self) {
388        if self.is_dirty() {
389            return;
390        }
391        self.is_dirty.set(true);
392        if self.node_type() == NodeType::Text {
393            self.clear_measure_cache();
394            self.clear_baseline_cache();
395        }
396        if let Some(dirty_callback) = self.dirty_callback() {
397            dirty_callback(convert_node_ref_to_ptr(self))
398        }
399        self.layout_node.mark_dirty(self);
400    }
401    pub unsafe fn mark_dirty_propagate_to_descendants(&self) {
402        self.mark_self_dirty();
403        unsafe {
404            self.children
405                .borrow()
406                .iter()
407                .for_each(|node| (**node).mark_dirty_propagate_to_descendants())
408        }
409    }
410    pub unsafe fn mark_dirty_propagate(&self) {
411        if !self.is_dirty() {
412            self.mark_self_dirty();
413            if let Some(parent) = self.parent() {
414                parent.mark_dirty_propagate()
415            }
416        }
417    }
418    pub fn dry_layout(
419        &self,
420        available_size: OptionSize<Len>,
421        viewport_size: float_pigment_layout::Size<Len>,
422    ) {
423        // FIXME
424        self.layout_node.update_with_containing_size(
425            &mut Env {
426                screen_width: viewport_size.width,
427                screen_height: viewport_size.height,
428            },
429            self,
430            available_size,
431            available_size,
432        );
433    }
434    pub unsafe fn layout(
435        &self,
436        available_size: OptionSize<Len>,
437        viewport_size: float_pigment_layout::Size<Len>,
438    ) {
439        // FIXME
440        self.layout_node.update_with_containing_size(
441            &mut Env {
442                screen_width: viewport_size.width,
443                screen_height: viewport_size.height,
444            },
445            self,
446            available_size,
447            available_size,
448        );
449        self.clear_dirty_recursive();
450    }
451
452    pub unsafe fn layout_with_containing_size(
453        &self,
454        available_size: OptionSize<Len>,
455        viewport_size: float_pigment_layout::Size<Len>,
456        containing_size: OptionSize<Len>,
457    ) {
458        self.layout_node.update_with_containing_size(
459            &mut Env {
460                screen_width: viewport_size.width,
461                screen_height: viewport_size.height,
462            },
463            self,
464            available_size,
465            containing_size,
466        );
467        self.clear_dirty_recursive();
468    }
469
470    pub fn layout_position(&self) -> LayoutPosition {
471        let layout = self.layout_node.result();
472        LayoutPosition {
473            left: layout.origin.x,
474            top: layout.origin.y,
475            width: layout.size.width,
476            height: layout.size.height,
477        }
478    }
479}
480
481impl Default for Node {
482    fn default() -> Self {
483        Self::new()
484    }
485}
486pub trait ChildOperation {
487    unsafe fn get_child_at(&self, idx: usize) -> Option<&Node>;
488    unsafe fn get_child_ptr_at(&self, idx: usize) -> Option<NodePtr>;
489    unsafe fn get_child_index(&self, child: NodePtr) -> Option<usize>;
490    unsafe fn append_child(&self, child: NodePtr);
491    unsafe fn insert_child_at(&self, child: NodePtr, idx: usize);
492    unsafe fn insert_child_before(&self, child: NodePtr, pivot: NodePtr);
493    unsafe fn remove_child(&self, child: NodePtr);
494    unsafe fn remove_child_at(&self, idx: usize);
495    unsafe fn remove_all_children(&self);
496    unsafe fn for_each_child_node<'a, 'b: 'a, F>(&'b self, func: F)
497    where
498        F: FnMut(&'a Self, usize);
499}
500
501impl ChildOperation for Node {
502    unsafe fn get_child_at(&self, idx: usize) -> Option<&Node> {
503        self.children().get(idx).copied()
504    }
505    unsafe fn get_child_ptr_at(&self, idx: usize) -> Option<NodePtr> {
506        self.children.borrow().get(idx).copied()
507    }
508    unsafe fn get_child_index(&self, child: NodePtr) -> Option<usize> {
509        self.children()
510            .iter()
511            .position(|node| ptr::eq(*node, child))
512    }
513    #[allow(clippy::not_unsafe_ptr_arg_deref)]
514    unsafe fn append_child(&self, child: NodePtr) {
515        if let Some(prev_parent) = (*child).parent() {
516            prev_parent.remove_child(child);
517        }
518        (*child).set_parent(Some(convert_node_ref_to_ptr(self)));
519        self.children.borrow_mut().push(child);
520        self.mark_dirty_propagate()
521    }
522    #[allow(clippy::not_unsafe_ptr_arg_deref)]
523    unsafe fn insert_child_at(&self, child: NodePtr, idx: usize) {
524        if let Some(prev_parent) = (*child).parent() {
525            prev_parent.remove_child(child);
526        }
527        (*child).set_parent(Some(convert_node_ref_to_ptr(self)));
528        self.children.borrow_mut().insert(idx, child);
529        self.mark_dirty_propagate()
530    }
531    #[allow(clippy::not_unsafe_ptr_arg_deref)]
532    unsafe fn insert_child_before(&self, child: NodePtr, pivot: NodePtr) {
533        if let Some(prev_parent) = (*child).parent() {
534            prev_parent.remove_child(child);
535        }
536        (*child).set_parent(Some(convert_node_ref_to_ptr(self)));
537        let idx = self
538            .children
539            .borrow()
540            .iter()
541            .position(|node| std::ptr::eq(*node, pivot));
542        if let Some(idx) = idx {
543            self.children.borrow_mut().insert(idx, child)
544        }
545        self.mark_dirty_propagate();
546    }
547    unsafe fn remove_child(&self, child: NodePtr) {
548        if self.children_len() == 0 {
549            return;
550        }
551        let child_idx_opt = self
552            .children
553            .borrow()
554            .iter()
555            .position(|node| std::ptr::eq(*node, child));
556        if let Some(child_idx) = child_idx_opt {
557            let node = {
558                let mut children = self.children.borrow_mut();
559                let node = children[child_idx];
560                children.remove(child_idx);
561                node
562            };
563            (*node).set_parent(None);
564        }
565
566        self.mark_dirty_propagate();
567    }
568    unsafe fn remove_child_at(&self, idx: usize) {
569        let len = self.children_len();
570        if len == 0 || idx >= len {
571            return;
572        }
573        if let Some(node) = self.children.borrow().get(idx) {
574            (**node).set_parent(None);
575        }
576        self.children.borrow_mut().remove(idx);
577        self.mark_dirty_propagate();
578    }
579    unsafe fn remove_all_children(&self) {
580        self.for_each_child_node(|node, _| {
581            (*node).set_parent(None);
582        });
583        self.children.borrow_mut().clear();
584        self.mark_dirty_propagate()
585    }
586    unsafe fn for_each_child_node<'a, 'b: 'a, F>(&'b self, func: F)
587    where
588        F: FnMut(&'a Self, usize),
589    {
590        let mut func = func;
591        self.children
592            .borrow_mut()
593            .iter_mut()
594            .enumerate()
595            .for_each(|(idx, node)| func(&**node, idx))
596    }
597}
598
599pub trait StyleSetter {
600    unsafe fn set_display(&self, value: Display);
601    unsafe fn set_box_sizing(&self, value: BoxSizing);
602    unsafe fn set_direction(&self, value: Direction);
603    unsafe fn set_writing_mode(&self, value: WritingMode);
604    unsafe fn set_position(&self, value: Position);
605    unsafe fn set_left(&self, value: Length);
606    unsafe fn set_top(&self, value: Length);
607    unsafe fn set_right(&self, value: Length);
608    unsafe fn set_bottom(&self, value: Length);
609    unsafe fn set_overflow_x(&self, value: Overflow);
610    unsafe fn set_overflow_y(&self, value: Overflow);
611    unsafe fn set_width(&self, value: Length);
612    unsafe fn set_height(&self, value: Length);
613    unsafe fn set_min_width(&self, value: Length);
614    unsafe fn set_min_height(&self, value: Length);
615    unsafe fn set_max_width(&self, value: Length);
616    unsafe fn set_max_height(&self, value: Length);
617    unsafe fn set_margin(&self, value: Length);
618    unsafe fn set_margin_left(&self, value: Length);
619    unsafe fn set_margin_top(&self, value: Length);
620    unsafe fn set_margin_right(&self, value: Length);
621    unsafe fn set_margin_bottom(&self, value: Length);
622    unsafe fn set_padding(&self, value: Length);
623    unsafe fn set_padding_left(&self, value: Length);
624    unsafe fn set_padding_top(&self, value: Length);
625    unsafe fn set_padding_right(&self, value: Length);
626    unsafe fn set_padding_bottom(&self, value: Length);
627    unsafe fn set_border(&self, value: Length);
628    unsafe fn set_border_left(&self, value: Length);
629    unsafe fn set_border_top(&self, value: Length);
630    unsafe fn set_border_right(&self, value: Length);
631    unsafe fn set_border_bottom(&self, value: Length);
632    unsafe fn set_flex_grow(&self, value: f32);
633    unsafe fn set_flex_shrink(&self, value: f32);
634    unsafe fn set_flex_basis(&self, value: Length);
635    unsafe fn set_flex_direction(&self, value: FlexDirection);
636    unsafe fn set_flex_wrap(&self, value: FlexWrap);
637    unsafe fn set_justify_content(&self, value: JustifyContent);
638    unsafe fn set_align_content(&self, value: AlignContent);
639    unsafe fn set_align_items(&self, value: AlignItems);
640    unsafe fn set_align_self(&self, value: AlignSelf);
641    unsafe fn set_aspect_ratio(&self, value: Option<f32>);
642    unsafe fn set_order(&self, value: i32);
643    unsafe fn set_text_align(&self, value: TextAlign);
644    unsafe fn set_row_gap(&self, value: Length);
645    unsafe fn set_column_gap(&self, value: Length);
646}
647
648impl StyleSetter for Node {
649    unsafe fn set_flex_direction(&self, flex_direction: FlexDirection) {
650        if self.style_manager_mut().set_flex_direction(flex_direction) {
651            self.mark_dirty_propagate();
652        }
653    }
654    unsafe fn set_direction(&self, direction: Direction) {
655        if self.style_manager_mut().set_direction(direction) {
656            self.mark_dirty_propagate();
657        }
658    }
659    unsafe fn set_align_content(&self, align_content: AlignContent) {
660        if self.style_manager_mut().set_align_content(align_content) {
661            self.mark_dirty_propagate();
662        }
663    }
664    unsafe fn set_align_items(&self, align_items: AlignItems) {
665        if self.style_manager_mut().set_align_items(align_items) {
666            self.mark_dirty_propagate();
667        }
668    }
669    unsafe fn set_align_self(&self, align_self: AlignSelf) {
670        if self.style_manager_mut().set_align_self(align_self) {
671            self.mark_dirty_propagate();
672        }
673    }
674    unsafe fn set_aspect_ratio(&self, aspect_ratio: Option<f32>) {
675        if self.style_manager_mut().set_aspect_ratio(aspect_ratio) {
676            self.mark_dirty_propagate();
677        }
678    }
679    unsafe fn set_border(&self, border: Length) {
680        let top_changed = self.style_manager_mut().set_border_top(border);
681        let right_changed = self.style_manager_mut().set_border_right(border);
682        let bottom_changed = self.style_manager_mut().set_border_bottom(border);
683        let left_changed = self.style_manager_mut().set_border_left(border);
684        if top_changed || right_changed || bottom_changed || left_changed {
685            self.mark_dirty_propagate();
686        }
687    }
688    unsafe fn set_border_left(&self, border_left: Length) {
689        if self.style_manager_mut().set_border_left(border_left) {
690            self.mark_dirty_propagate();
691        }
692    }
693    unsafe fn set_border_right(&self, border_right: Length) {
694        if self.style_manager_mut().set_border_right(border_right) {
695            self.mark_dirty_propagate();
696        }
697    }
698    unsafe fn set_border_top(&self, border_top: Length) {
699        if self.style_manager_mut().set_border_top(border_top) {
700            self.mark_dirty_propagate();
701        }
702    }
703    unsafe fn set_border_bottom(&self, border_bottom: Length) {
704        if self.style_manager_mut().set_border_bottom(border_bottom) {
705            self.mark_dirty_propagate();
706        }
707    }
708    unsafe fn set_box_sizing(&self, box_sizing: BoxSizing) {
709        if self.style_manager_mut().set_box_sizing(box_sizing) {
710            self.mark_dirty_propagate();
711        }
712    }
713    unsafe fn set_display(&self, display: Display) {
714        if self.style_manager_mut().set_display(display) {
715            self.mark_dirty_propagate();
716        }
717    }
718    unsafe fn set_height(&self, height: Length) {
719        if self.style_manager_mut().set_height(height) {
720            self.mark_dirty_propagate();
721        }
722    }
723    unsafe fn set_width(&self, width: Length) {
724        if self.style_manager_mut().set_width(width) {
725            self.mark_dirty_propagate();
726        }
727    }
728    unsafe fn set_left(&self, left: Length) {
729        if self.style_manager_mut().set_left(left) {
730            self.mark_dirty_propagate();
731        }
732    }
733    unsafe fn set_right(&self, right: Length) {
734        if self.style_manager_mut().set_right(right) {
735            self.mark_dirty_propagate();
736        }
737    }
738    unsafe fn set_top(&self, top: Length) {
739        if self.style_manager_mut().set_top(top) {
740            self.mark_dirty_propagate();
741        }
742    }
743    unsafe fn set_bottom(&self, bottom: Length) {
744        if self.style_manager_mut().set_bottom(bottom) {
745            self.mark_dirty_propagate();
746        }
747    }
748    unsafe fn set_flex_shrink(&self, flex_shrink: f32) {
749        if self.style_manager_mut().set_flex_shrink(flex_shrink) {
750            self.mark_dirty_propagate();
751        }
752    }
753    unsafe fn set_flex_grow(&self, flex_grow: f32) {
754        if self.style_manager_mut().set_flex_grow(flex_grow) {
755            self.mark_dirty_propagate();
756        }
757    }
758    unsafe fn set_flex_wrap(&self, flex_wrap: FlexWrap) {
759        if self.style_manager_mut().set_flex_wrap(flex_wrap) {
760            self.mark_dirty_propagate();
761        }
762    }
763    unsafe fn set_flex_basis(&self, flex_basis: Length) {
764        if self.style_manager_mut().set_flex_basis(flex_basis) {
765            self.mark_dirty_propagate();
766        }
767    }
768    unsafe fn set_justify_content(&self, justify_content: JustifyContent) {
769        if self
770            .style_manager_mut()
771            .set_justify_content(justify_content)
772        {
773            self.mark_dirty_propagate();
774        }
775    }
776    unsafe fn set_position(&self, position: Position) {
777        if self.style_manager_mut().set_position(position) {
778            self.mark_dirty_propagate();
779        }
780    }
781    unsafe fn set_overflow_x(&self, overflow_x: Overflow) {
782        if self.style_manager_mut().set_overflow_x(overflow_x) {
783            self.mark_dirty_propagate();
784        }
785    }
786    unsafe fn set_overflow_y(&self, overflow_y: Overflow) {
787        if self.style_manager_mut().set_overflow_y(overflow_y) {
788            self.mark_dirty_propagate();
789        }
790    }
791    unsafe fn set_writing_mode(&self, writing_mode: WritingMode) {
792        if self.style_manager_mut().set_writing_mode(writing_mode) {
793            self.mark_dirty_propagate();
794        }
795    }
796    unsafe fn set_margin(&self, margin: Length) {
797        let top_changed = self.style_manager_mut().set_margin_top(margin);
798        let right_changed = self.style_manager_mut().set_margin_right(margin);
799        let bottom_changed = self.style_manager_mut().set_margin_bottom(margin);
800        let left_changed = self.style_manager_mut().set_margin_left(margin);
801        if top_changed || bottom_changed || right_changed || left_changed {
802            self.mark_dirty_propagate();
803        }
804    }
805    unsafe fn set_margin_bottom(&self, margin_bottom: Length) {
806        if self.style_manager_mut().set_margin_bottom(margin_bottom) {
807            self.mark_dirty_propagate();
808        }
809    }
810    unsafe fn set_margin_left(&self, margin_left: Length) {
811        if self.style_manager_mut().set_margin_left(margin_left) {
812            self.mark_dirty_propagate();
813        }
814    }
815    unsafe fn set_margin_right(&self, margin_right: Length) {
816        if self.style_manager_mut().set_margin_right(margin_right) {
817            self.mark_dirty_propagate();
818        }
819    }
820    unsafe fn set_margin_top(&self, margin_top: Length) {
821        if self.style_manager_mut().set_margin_top(margin_top) {
822            self.mark_dirty_propagate();
823        }
824    }
825    unsafe fn set_max_height(&self, max_height: Length) {
826        if self.style_manager_mut().set_max_height(max_height) {
827            self.mark_dirty_propagate();
828        }
829    }
830    unsafe fn set_max_width(&self, max_width: Length) {
831        if self.style_manager_mut().set_max_width(max_width) {
832            self.mark_dirty_propagate();
833        }
834    }
835    unsafe fn set_min_height(&self, min_height: Length) {
836        if self.style_manager_mut().set_min_height(min_height) {
837            self.mark_dirty_propagate();
838        }
839    }
840
841    unsafe fn set_min_width(&self, min_width: Length) {
842        if self.style_manager_mut().set_min_width(min_width) {
843            self.mark_dirty_propagate();
844        }
845    }
846    unsafe fn set_padding(&self, padding: Length) {
847        let top_changed = self.style_manager_mut().set_padding_top(padding);
848        let right_changed = self.style_manager_mut().set_padding_right(padding);
849        let bottom_changed = self.style_manager_mut().set_padding_bottom(padding);
850        let left_changed = self.style_manager_mut().set_padding_left(padding);
851        if top_changed || bottom_changed || left_changed || right_changed {
852            self.mark_dirty_propagate();
853        }
854    }
855    unsafe fn set_padding_left(&self, padding_left: Length) {
856        if self.style_manager_mut().set_padding_left(padding_left) {
857            self.mark_dirty_propagate();
858        }
859    }
860    unsafe fn set_padding_right(&self, padding_right: Length) {
861        if self.style_manager_mut().set_padding_right(padding_right) {
862            self.mark_dirty_propagate();
863        }
864    }
865    unsafe fn set_padding_top(&self, padding_top: Length) {
866        if self.style_manager_mut().set_padding_top(padding_top) {
867            self.mark_dirty_propagate();
868        }
869    }
870    unsafe fn set_padding_bottom(&self, padding_bottom: Length) {
871        if self.style_manager_mut().set_padding_bottom(padding_bottom) {
872            self.mark_dirty_propagate();
873        }
874    }
875    unsafe fn set_order(&self, order: i32) {
876        if self.style_manager_mut().set_order(order) {
877            self.mark_dirty_propagate();
878        }
879    }
880    unsafe fn set_text_align(&self, text_align: TextAlign) {
881        if self.style_manager_mut().set_text_align(text_align) {
882            self.mark_dirty_propagate();
883        }
884    }
885    unsafe fn set_row_gap(&self, value: Length) {
886        if self.style_manager_mut().set_row_gap(value) {
887            self.mark_dirty_propagate();
888        }
889    }
890    unsafe fn set_column_gap(&self, value: Length) {
891        if self.style_manager_mut().set_column_gap(value) {
892            self.mark_dirty_propagate();
893        }
894    }
895}
896
897#[cfg(test)]
898mod test {
899    use crate::node::NodePtr;
900
901    use super::*;
902    fn new_node<'a>() -> (&'a Node, NodePtr) {
903        let node_ptr = Node::new_ptr();
904        (unsafe { get_ref_from_node_ptr(node_ptr) }, node_ptr)
905    }
906    #[test]
907    fn append_child() {
908        let (node_a, node_a_ptr) = new_node();
909        let (node_b, node_b_ptr) = new_node();
910        unsafe {
911            node_a.append_child(node_b_ptr);
912            assert!(std::ptr::eq(node_a, node_b.parent().unwrap()));
913            assert!(std::ptr::eq(node_a.get_child_at(0).unwrap(), node_b));
914            drop(Box::from_raw(node_a_ptr));
915            drop(Box::from_raw(node_b_ptr));
916        }
917    }
918    #[test]
919    fn insert_child_at() {
920        let (node_a, node_a_ptr) = new_node();
921        let (node_b, node_b_ptr) = new_node();
922        let (node_c, node_c_ptr) = new_node();
923        unsafe {
924            node_a.insert_child_at(node_b_ptr, 0);
925            node_a.insert_child_at(node_c_ptr, 0);
926            assert!(std::ptr::eq(node_a, node_b.parent().unwrap()));
927            assert!(std::ptr::eq(node_a, node_c.parent().unwrap()));
928            assert!(std::ptr::eq(node_a.get_child_at(0).unwrap(), node_c));
929            assert!(std::ptr::eq(node_a.get_child_at(1).unwrap(), node_b));
930            drop(Box::from_raw(node_a_ptr));
931            drop(Box::from_raw(node_b_ptr));
932            drop(Box::from_raw(node_c_ptr));
933        }
934    }
935
936    #[test]
937    fn remove_child() {
938        let (node_a, node_a_ptr) = new_node();
939        let (node_b, node_b_ptr) = new_node();
940        unsafe {
941            node_a.insert_child_at(node_b_ptr, 0);
942            assert!(std::ptr::eq(node_a, node_b.parent().unwrap()));
943            assert!(std::ptr::eq(node_a.get_child_at(0).unwrap(), node_b));
944            node_a.remove_child(node_b_ptr);
945            assert!(node_b.parent().is_none());
946            assert_eq!(node_a.children_len(), 0usize);
947            drop(Box::from_raw(node_a_ptr));
948            drop(Box::from_raw(node_b_ptr));
949        }
950    }
951
952    #[test]
953    fn remove_child_at() {
954        let (node_a, node_a_ptr) = new_node();
955        let (node_b, node_b_ptr) = new_node();
956        unsafe {
957            node_a.insert_child_at(node_b_ptr, 0);
958            assert!(std::ptr::eq(node_a, node_b.parent().unwrap()));
959            assert!(std::ptr::eq(node_a.get_child_at(0).unwrap(), node_b));
960            node_a.remove_child_at(0);
961            assert_eq!(node_a.children_len(), 0usize);
962            assert!(node_b.parent().is_none());
963            drop(Box::from_raw(node_a_ptr));
964            drop(Box::from_raw(node_b_ptr));
965        }
966    }
967}