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