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 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 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}