1use alloc::{boxed::Box, collections::btree_map::BTreeMap, string::String, vec::Vec};
2use core::{
3 fmt,
4 hash::{Hash, Hasher},
5};
6
7use azul_css::{
8 css::{Css, CssPath},
9 props::{
10 basic::{StyleFontFamily, StyleFontFamilyVec, StyleFontSize},
11 property::{
12 BoxDecorationBreakValue, BreakInsideValue, CaretAnimationDurationValue,
13 CaretColorValue, ColumnCountValue, ColumnFillValue, ColumnRuleColorValue,
14 ColumnRuleStyleValue, ColumnRuleWidthValue, ColumnSpanValue, ColumnWidthValue,
15 ContentValue, CounterIncrementValue, CounterResetValue, CssProperty, CssPropertyType,
16 RelayoutScope,
17 FlowFromValue, FlowIntoValue, LayoutAlignContentValue, LayoutAlignItemsValue,
18 LayoutAlignSelfValue, LayoutBorderBottomWidthValue, LayoutBorderLeftWidthValue,
19 LayoutBorderRightWidthValue, LayoutBorderTopWidthValue, LayoutBoxSizingValue,
20 LayoutClearValue, LayoutColumnGapValue, LayoutDisplayValue, LayoutFlexBasisValue,
21 LayoutFlexDirectionValue, LayoutFlexGrowValue, LayoutFlexShrinkValue,
22 LayoutFlexWrapValue, LayoutFloatValue, LayoutGapValue, LayoutGridAutoColumnsValue,
23 LayoutGridAutoFlowValue, LayoutGridAutoRowsValue, LayoutGridColumnValue,
24 LayoutGridRowValue, LayoutGridTemplateColumnsValue, LayoutGridTemplateRowsValue,
25 LayoutHeightValue, LayoutInsetBottomValue, LayoutJustifyContentValue,
26 LayoutJustifyItemsValue, LayoutJustifySelfValue, LayoutLeftValue,
27 LayoutMarginBottomValue, LayoutMarginLeftValue, LayoutMarginRightValue,
28 LayoutMarginTopValue, LayoutMaxHeightValue, LayoutMaxWidthValue, LayoutMinHeightValue,
29 LayoutMinWidthValue, LayoutOverflowValue, LayoutPaddingBottomValue,
30 LayoutPaddingLeftValue, LayoutPaddingRightValue, LayoutPaddingTopValue,
31 LayoutPositionValue, LayoutRightValue, LayoutRowGapValue, LayoutScrollbarWidthValue,
32 LayoutTextJustifyValue, LayoutTopValue, LayoutWidthValue, LayoutWritingModeValue,
33 LayoutZIndexValue, OrphansValue, PageBreakValue, ScrollbarStyleValue,
34 SelectionBackgroundColorValue, SelectionColorValue, ShapeImageThresholdValue,
35 ShapeMarginValue, ShapeOutsideValue, StringSetValue, StyleBackfaceVisibilityValue,
36 StyleBackgroundContentVecValue, StyleBackgroundPositionVecValue,
37 StyleBackgroundRepeatVecValue, StyleBackgroundSizeVecValue,
38 StyleBorderBottomColorValue, StyleBorderBottomLeftRadiusValue,
39 StyleBorderBottomRightRadiusValue, StyleBorderBottomStyleValue,
40 StyleBorderLeftColorValue, StyleBorderLeftStyleValue, StyleBorderRightColorValue,
41 StyleBorderRightStyleValue, StyleBorderTopColorValue, StyleBorderTopLeftRadiusValue,
42 StyleBorderTopRightRadiusValue, StyleBorderTopStyleValue, StyleBoxShadowValue,
43 StyleCursorValue, StyleDirectionValue, StyleFilterVecValue, StyleFontFamilyVecValue,
44 StyleFontSizeValue, StyleFontValue, StyleHyphensValue, StyleLetterSpacingValue,
45 StyleLineHeightValue, StyleMixBlendModeValue, StyleOpacityValue,
46 StylePerspectiveOriginValue, StyleScrollbarColorValue, StyleTabSizeValue,
47 StyleTextAlignValue, StyleTextColorValue, StyleTransformOriginValue,
48 StyleTransformVecValue, StyleVisibilityValue, StyleWhiteSpaceValue,
49 StyleWordSpacingValue, WidowsValue,
50 },
51 style::StyleTextColor,
52 },
53 AzString,
54};
55
56use crate::{
57 callbacks::Update,
58 dom::{Dom, DomId, NodeData, NodeDataVec, OptionTabIndex, TabIndex, TagId},
59 id::{
60 Node, NodeDataContainer, NodeDataContainerRef, NodeDataContainerRefMut, NodeHierarchy,
61 NodeId,
62 },
63 menu::Menu,
64 prop_cache::{CssPropertyCache, CssPropertyCachePtr},
65 refany::RefAny,
66 resources::{Au, ImageCache, ImageRef, ImmediateFontId, RendererResources},
67 style::{
68 construct_html_cascade_tree, matches_html_element, rule_ends_with, CascadeInfo,
69 CascadeInfoVec,
70 },
71 FastBTreeSet, FastHashMap,
72};
73
74#[repr(C)]
75#[derive(Debug, Clone, PartialEq, Hash, PartialOrd, Eq, Ord)]
76pub struct ChangedCssProperty {
77 pub previous_state: StyledNodeState,
78 pub previous_prop: CssProperty,
79 pub current_state: StyledNodeState,
80 pub current_prop: CssProperty,
81}
82
83impl_option!(
84 ChangedCssProperty,
85 OptionChangedCssProperty,
86 copy = false,
87 [Debug, Clone, PartialEq, Hash, PartialOrd, Eq, Ord]
88);
89
90impl_vec!(ChangedCssProperty, ChangedCssPropertyVec, ChangedCssPropertyVecDestructor, ChangedCssPropertyVecDestructorType, ChangedCssPropertyVecSlice, OptionChangedCssProperty);
91impl_vec_debug!(ChangedCssProperty, ChangedCssPropertyVec);
92impl_vec_partialord!(ChangedCssProperty, ChangedCssPropertyVec);
93impl_vec_clone!(
94 ChangedCssProperty,
95 ChangedCssPropertyVec,
96 ChangedCssPropertyVecDestructor
97);
98impl_vec_partialeq!(ChangedCssProperty, ChangedCssPropertyVec);
99
100#[derive(Debug, Clone, PartialEq)]
102pub struct FocusChange {
103 pub lost_focus: Option<NodeId>,
105 pub gained_focus: Option<NodeId>,
107}
108
109#[derive(Debug, Clone, PartialEq)]
111pub struct HoverChange {
112 pub left_nodes: Vec<NodeId>,
114 pub entered_nodes: Vec<NodeId>,
116}
117
118#[derive(Debug, Clone, PartialEq)]
120pub struct ActiveChange {
121 pub deactivated: Vec<NodeId>,
123 pub activated: Vec<NodeId>,
125}
126
127#[derive(Debug, Clone, Default)]
129pub struct RestyleResult {
130 pub changed_nodes: BTreeMap<NodeId, Vec<ChangedCssProperty>>,
132 pub needs_layout: bool,
134 pub needs_display_list: bool,
136 pub gpu_only_changes: bool,
139 pub max_relayout_scope: RelayoutScope,
150}
151
152impl RestyleResult {
153 pub fn has_changes(&self) -> bool {
155 !self.changed_nodes.is_empty()
156 }
157
158 pub fn merge(&mut self, other: RestyleResult) {
160 for (node_id, changes) in other.changed_nodes {
161 self.changed_nodes.entry(node_id).or_default().extend(changes);
162 }
163 self.needs_layout = self.needs_layout || other.needs_layout;
164 self.needs_display_list = self.needs_display_list || other.needs_display_list;
165 self.gpu_only_changes = self.gpu_only_changes && other.gpu_only_changes;
166 if other.max_relayout_scope > self.max_relayout_scope {
168 self.max_relayout_scope = other.max_relayout_scope;
169 }
170 }
171}
172
173#[repr(C, u8)]
174#[derive(Debug, Clone, PartialEq, Hash, PartialOrd, Eq, Ord)]
175pub enum CssPropertySource {
176 Css(CssPath),
177 Inline,
178}
179
180#[repr(C)]
185#[derive(Clone, Copy, PartialEq, Hash, PartialOrd, Eq, Ord, Default)]
186pub struct StyledNodeState {
187 pub hover: bool,
189 pub active: bool,
191 pub focused: bool,
193 pub disabled: bool,
195 pub checked: bool,
197 pub focus_within: bool,
199 pub visited: bool,
201 pub backdrop: bool,
203 pub dragging: bool,
205 pub drag_over: bool,
207}
208
209impl core::fmt::Debug for StyledNodeState {
210 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
211 let mut v = Vec::new();
212 if self.hover {
213 v.push("hover");
214 }
215 if self.active {
216 v.push("active");
217 }
218 if self.focused {
219 v.push("focused");
220 }
221 if self.disabled {
222 v.push("disabled");
223 }
224 if self.checked {
225 v.push("checked");
226 }
227 if self.focus_within {
228 v.push("focus_within");
229 }
230 if self.visited {
231 v.push("visited");
232 }
233 if self.backdrop {
234 v.push("backdrop");
235 }
236 if self.dragging {
237 v.push("dragging");
238 }
239 if self.drag_over {
240 v.push("drag_over");
241 }
242 if v.is_empty() {
243 v.push("normal");
244 }
245 write!(f, "{:?}", v)
246 }
247}
248
249impl StyledNodeState {
250 pub const fn new() -> Self {
252 StyledNodeState {
253 hover: false,
254 active: false,
255 focused: false,
256 disabled: false,
257 checked: false,
258 focus_within: false,
259 visited: false,
260 backdrop: false,
261 dragging: false,
262 drag_over: false,
263 }
264 }
265
266 pub fn has_state(&self, state_type: u8) -> bool {
268 match state_type {
269 0 => true, 1 => self.hover,
271 2 => self.active,
272 3 => self.focused,
273 4 => self.disabled,
274 5 => self.checked,
275 6 => self.focus_within,
276 7 => self.visited,
277 8 => self.backdrop,
278 9 => self.dragging,
279 10 => self.drag_over,
280 _ => false,
281 }
282 }
283
284 pub fn is_normal(&self) -> bool {
286 !self.hover
287 && !self.active
288 && !self.focused
289 && !self.disabled
290 && !self.checked
291 && !self.focus_within
292 && !self.visited
293 && !self.backdrop
294 && !self.dragging
295 && !self.drag_over
296 }
297
298 pub fn to_pseudo_state_flags(&self) -> azul_css::dynamic_selector::PseudoStateFlags {
300 azul_css::dynamic_selector::PseudoStateFlags {
301 hover: self.hover,
302 active: self.active,
303 focused: self.focused,
304 disabled: self.disabled,
305 checked: self.checked,
306 focus_within: self.focus_within,
307 visited: self.visited,
308 backdrop: self.backdrop,
309 dragging: self.dragging,
310 drag_over: self.drag_over,
311 }
312 }
313
314 pub fn from_pseudo_state_flags(flags: &azul_css::dynamic_selector::PseudoStateFlags) -> Self {
316 StyledNodeState {
317 hover: flags.hover,
318 active: flags.active,
319 focused: flags.focused,
320 disabled: flags.disabled,
321 checked: flags.checked,
322 focus_within: flags.focus_within,
323 visited: flags.visited,
324 backdrop: flags.backdrop,
325 dragging: flags.dragging,
326 drag_over: flags.drag_over,
327 }
328 }
329}
330
331#[repr(C)]
333#[derive(Debug, Default, Clone, PartialEq, PartialOrd)]
334pub struct StyledNode {
335 pub styled_node_state: StyledNodeState,
337}
338
339impl_option!(
340 StyledNode,
341 OptionStyledNode,
342 copy = false,
343 [Debug, Clone, PartialEq, PartialOrd]
344);
345
346impl_vec!(StyledNode, StyledNodeVec, StyledNodeVecDestructor, StyledNodeVecDestructorType, StyledNodeVecSlice, OptionStyledNode);
347impl_vec_mut!(StyledNode, StyledNodeVec);
348impl_vec_debug!(StyledNode, StyledNodeVec);
349impl_vec_partialord!(StyledNode, StyledNodeVec);
350impl_vec_clone!(StyledNode, StyledNodeVec, StyledNodeVecDestructor);
351impl_vec_partialeq!(StyledNode, StyledNodeVec);
352
353impl StyledNodeVec {
354 pub fn as_container<'a>(&'a self) -> NodeDataContainerRef<'a, StyledNode> {
356 NodeDataContainerRef {
357 internal: self.as_ref(),
358 }
359 }
360 pub fn as_container_mut<'a>(&'a mut self) -> NodeDataContainerRefMut<'a, StyledNode> {
362 NodeDataContainerRefMut {
363 internal: self.as_mut(),
364 }
365 }
366}
367
368#[test]
369fn test_it() {
370 let s = "
371 html, body, p {
372 margin: 0;
373 padding: 0;
374 }
375 #div1 {
376 border: solid black;
377 height: 2in;
378 position: absolute;
379 top: 1in;
380 width: 3in;
381 }
382 div div {
383 background: blue;
384 height: 1in;
385 position: fixed;
386 width: 1in;
387 }
388 ";
389
390 let css = azul_css::parser2::new_from_str(s);
391 let _styled_dom = Dom::create_body()
392 .with_children(
393 vec![Dom::create_div()
394 .with_ids_and_classes(
395 vec![crate::dom::IdOrClass::Id("div1".to_string().into())].into(),
396 )
397 .with_children(vec![Dom::create_div()].into())]
398 .into(),
399 )
400 .style(css.0);
401}
402
403#[derive(Copy, Clone, Hash, PartialEq, Eq, Ord, PartialOrd)]
405pub struct StyleFontFamilyHash(pub u64);
406
407impl ::core::fmt::Debug for StyleFontFamilyHash {
408 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
409 write!(f, "StyleFontFamilyHash({})", self.0)
410 }
411}
412
413impl StyleFontFamilyHash {
414 pub fn new(family: &StyleFontFamily) -> Self {
416 use highway::{HighwayHash, HighwayHasher, Key};
417 let mut hasher = HighwayHasher::new(Key([0; 4]));
418 family.hash(&mut hasher);
419 Self(hasher.finalize64())
420 }
421}
422
423#[derive(Copy, Clone, Hash, PartialEq, Eq, Ord, PartialOrd)]
425pub struct StyleFontFamiliesHash(pub u64);
426
427impl ::core::fmt::Debug for StyleFontFamiliesHash {
428 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
429 write!(f, "StyleFontFamiliesHash({})", self.0)
430 }
431}
432
433impl StyleFontFamiliesHash {
434 pub fn new(families: &[StyleFontFamily]) -> Self {
436 use highway::{HighwayHash, HighwayHasher, Key};
437 let mut hasher = HighwayHasher::new(Key([0; 4]));
438 for f in families.iter() {
439 f.hash(&mut hasher);
440 }
441 Self(hasher.finalize64())
442 }
443}
444
445#[derive(Copy, Clone, PartialEq, Eq, Ord, PartialOrd, Hash)]
487#[repr(C)]
488pub struct NodeHierarchyItemId {
489 inner: usize,
492}
493
494impl fmt::Debug for NodeHierarchyItemId {
495 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
496 match self.into_crate_internal() {
497 Some(n) => write!(f, "Some(NodeId({}))", n),
498 None => write!(f, "None"),
499 }
500 }
501}
502
503impl fmt::Display for NodeHierarchyItemId {
504 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
505 write!(f, "{:?}", self)
506 }
507}
508
509impl NodeHierarchyItemId {
510 pub const NONE: NodeHierarchyItemId = NodeHierarchyItemId { inner: 0 };
512
513 #[inline]
520 pub const fn from_raw(value: usize) -> Self {
521 Self { inner: value }
522 }
523
524 #[inline]
530 pub const fn into_raw(&self) -> usize {
531 self.inner
532 }
533}
534
535impl_option!(
536 NodeHierarchyItemId,
537 OptionNodeHierarchyItemId,
538 [Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash]
539);
540
541impl_vec!(NodeHierarchyItemId, NodeHierarchyItemIdVec, NodeHierarchyItemIdVecDestructor, NodeHierarchyItemIdVecDestructorType, NodeHierarchyItemIdVecSlice, OptionNodeHierarchyItemId);
542impl_vec_mut!(NodeHierarchyItemId, NodeHierarchyItemIdVec);
543impl_vec_debug!(NodeHierarchyItemId, NodeHierarchyItemIdVec);
544impl_vec_ord!(NodeHierarchyItemId, NodeHierarchyItemIdVec);
545impl_vec_eq!(NodeHierarchyItemId, NodeHierarchyItemIdVec);
546impl_vec_hash!(NodeHierarchyItemId, NodeHierarchyItemIdVec);
547impl_vec_partialord!(NodeHierarchyItemId, NodeHierarchyItemIdVec);
548impl_vec_clone!(NodeHierarchyItemId, NodeHierarchyItemIdVec, NodeHierarchyItemIdVecDestructor);
549impl_vec_partialeq!(NodeHierarchyItemId, NodeHierarchyItemIdVec);
550
551impl NodeHierarchyItemId {
552 #[inline]
554 pub const fn into_crate_internal(&self) -> Option<NodeId> {
555 NodeId::from_usize(self.inner)
556 }
557
558 #[inline]
560 pub const fn from_crate_internal(t: Option<NodeId>) -> Self {
561 Self {
562 inner: NodeId::into_raw(&t),
563 }
564 }
565}
566
567impl From<Option<NodeId>> for NodeHierarchyItemId {
568 #[inline]
569 fn from(opt: Option<NodeId>) -> Self {
570 NodeHierarchyItemId::from_crate_internal(opt)
571 }
572}
573
574impl From<NodeHierarchyItemId> for Option<NodeId> {
575 #[inline]
576 fn from(id: NodeHierarchyItemId) -> Self {
577 id.into_crate_internal()
578 }
579}
580
581#[derive(Debug, Copy, Clone, PartialEq, Eq, Ord, PartialOrd, Hash)]
582#[repr(C)]
583pub struct NodeHierarchyItem {
584 pub parent: usize,
585 pub previous_sibling: usize,
586 pub next_sibling: usize,
587 pub last_child: usize,
588}
589
590impl_option!(
591 NodeHierarchyItem,
592 OptionNodeHierarchyItem,
593 [Debug, Copy, Clone, PartialEq, Eq, Ord, PartialOrd, Hash]
594);
595
596impl NodeHierarchyItem {
597 pub const fn zeroed() -> Self {
599 Self {
600 parent: 0,
601 previous_sibling: 0,
602 next_sibling: 0,
603 last_child: 0,
604 }
605 }
606}
607
608impl From<Node> for NodeHierarchyItem {
609 fn from(node: Node) -> NodeHierarchyItem {
610 NodeHierarchyItem {
611 parent: NodeId::into_raw(&node.parent),
612 previous_sibling: NodeId::into_raw(&node.previous_sibling),
613 next_sibling: NodeId::into_raw(&node.next_sibling),
614 last_child: NodeId::into_raw(&node.last_child),
615 }
616 }
617}
618
619impl NodeHierarchyItem {
620 pub fn parent_id(&self) -> Option<NodeId> {
622 NodeId::from_usize(self.parent)
623 }
624 pub fn previous_sibling_id(&self) -> Option<NodeId> {
626 NodeId::from_usize(self.previous_sibling)
627 }
628 pub fn next_sibling_id(&self) -> Option<NodeId> {
630 NodeId::from_usize(self.next_sibling)
631 }
632 pub fn first_child_id(&self, current_node_id: NodeId) -> Option<NodeId> {
634 self.last_child_id().map(|_| current_node_id + 1)
635 }
636 pub fn last_child_id(&self) -> Option<NodeId> {
638 NodeId::from_usize(self.last_child)
639 }
640}
641
642impl_vec!(NodeHierarchyItem, NodeHierarchyItemVec, NodeHierarchyItemVecDestructor, NodeHierarchyItemVecDestructorType, NodeHierarchyItemVecSlice, OptionNodeHierarchyItem);
643impl_vec_mut!(NodeHierarchyItem, NodeHierarchyItemVec);
644impl_vec_debug!(AzNode, NodeHierarchyItemVec);
645impl_vec_partialord!(AzNode, NodeHierarchyItemVec);
646impl_vec_clone!(
647 NodeHierarchyItem,
648 NodeHierarchyItemVec,
649 NodeHierarchyItemVecDestructor
650);
651impl_vec_partialeq!(AzNode, NodeHierarchyItemVec);
652
653impl NodeHierarchyItemVec {
654 pub fn as_container<'a>(&'a self) -> NodeDataContainerRef<'a, NodeHierarchyItem> {
656 NodeDataContainerRef {
657 internal: self.as_ref(),
658 }
659 }
660 pub fn as_container_mut<'a>(&'a mut self) -> NodeDataContainerRefMut<'a, NodeHierarchyItem> {
662 NodeDataContainerRefMut {
663 internal: self.as_mut(),
664 }
665 }
666}
667
668impl<'a> NodeDataContainerRef<'a, NodeHierarchyItem> {
669 #[inline]
671 pub fn subtree_len(&self, parent_id: NodeId) -> usize {
672 let self_item_index = parent_id.index();
673 let next_item_index = match self[parent_id].next_sibling_id() {
674 None => self.len(),
675 Some(s) => s.index(),
676 };
677 next_item_index - self_item_index - 1
678 }
679}
680
681#[derive(Copy, Clone, PartialEq, Eq, Ord, PartialOrd, Hash)]
682#[repr(C)]
683pub struct ParentWithNodeDepth {
684 pub depth: usize,
685 pub node_id: NodeHierarchyItemId,
686}
687
688impl_option!(
689 ParentWithNodeDepth,
690 OptionParentWithNodeDepth,
691 [Copy, Clone, PartialEq, Eq, Ord, PartialOrd, Hash]
692);
693
694impl core::fmt::Debug for ParentWithNodeDepth {
695 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
696 write!(
697 f,
698 "{{ depth: {}, node: {:?} }}",
699 self.depth,
700 self.node_id.into_crate_internal()
701 )
702 }
703}
704
705impl_vec!(ParentWithNodeDepth, ParentWithNodeDepthVec, ParentWithNodeDepthVecDestructor, ParentWithNodeDepthVecDestructorType, ParentWithNodeDepthVecSlice, OptionParentWithNodeDepth);
706impl_vec_mut!(ParentWithNodeDepth, ParentWithNodeDepthVec);
707impl_vec_debug!(ParentWithNodeDepth, ParentWithNodeDepthVec);
708impl_vec_partialord!(ParentWithNodeDepth, ParentWithNodeDepthVec);
709impl_vec_clone!(
710 ParentWithNodeDepth,
711 ParentWithNodeDepthVec,
712 ParentWithNodeDepthVecDestructor
713);
714impl_vec_partialeq!(ParentWithNodeDepth, ParentWithNodeDepthVec);
715
716#[derive(Debug, Clone, PartialEq, Eq, Ord, PartialOrd)]
717#[repr(C)]
718pub struct TagIdToNodeIdMapping {
719 pub tag_id: TagId,
721 pub node_id: NodeHierarchyItemId,
723 pub tab_index: OptionTabIndex,
725}
726
727impl_option!(
728 TagIdToNodeIdMapping,
729 OptionTagIdToNodeIdMapping,
730 copy = false,
731 [Debug, Clone, PartialEq, Eq, Ord, PartialOrd]
732);
733
734impl_vec!(TagIdToNodeIdMapping, TagIdToNodeIdMappingVec, TagIdToNodeIdMappingVecDestructor, TagIdToNodeIdMappingVecDestructorType, TagIdToNodeIdMappingVecSlice, OptionTagIdToNodeIdMapping);
735impl_vec_mut!(TagIdToNodeIdMapping, TagIdToNodeIdMappingVec);
736impl_vec_debug!(TagIdToNodeIdMapping, TagIdToNodeIdMappingVec);
737impl_vec_partialord!(TagIdToNodeIdMapping, TagIdToNodeIdMappingVec);
738impl_vec_clone!(
739 TagIdToNodeIdMapping,
740 TagIdToNodeIdMappingVec,
741 TagIdToNodeIdMappingVecDestructor
742);
743impl_vec_partialeq!(TagIdToNodeIdMapping, TagIdToNodeIdMappingVec);
744
745#[derive(Debug, Clone, PartialEq, PartialOrd)]
746#[repr(C)]
747pub struct ContentGroup {
748 pub root: NodeHierarchyItemId,
751 pub children: ContentGroupVec,
753}
754
755impl_option!(
756 ContentGroup,
757 OptionContentGroup,
758 copy = false,
759 [Debug, Clone, PartialEq, PartialOrd]
760);
761
762impl_vec!(ContentGroup, ContentGroupVec, ContentGroupVecDestructor, ContentGroupVecDestructorType, ContentGroupVecSlice, OptionContentGroup);
763impl_vec_mut!(ContentGroup, ContentGroupVec);
764impl_vec_debug!(ContentGroup, ContentGroupVec);
765impl_vec_partialord!(ContentGroup, ContentGroupVec);
766impl_vec_clone!(ContentGroup, ContentGroupVec, ContentGroupVecDestructor);
767impl_vec_partialeq!(ContentGroup, ContentGroupVec);
768
769#[derive(Debug, PartialEq, Clone)]
770#[repr(C)]
771pub struct StyledDom {
772 pub root: NodeHierarchyItemId,
773 pub node_hierarchy: NodeHierarchyItemVec,
774 pub node_data: NodeDataVec,
775 pub styled_nodes: StyledNodeVec,
776 pub cascade_info: CascadeInfoVec,
777 pub nodes_with_window_callbacks: NodeHierarchyItemIdVec,
778 pub nodes_with_not_callbacks: NodeHierarchyItemIdVec,
779 pub nodes_with_datasets: NodeHierarchyItemIdVec,
780 pub tag_ids_to_node_ids: TagIdToNodeIdMappingVec,
781 pub non_leaf_nodes: ParentWithNodeDepthVec,
782 pub css_property_cache: CssPropertyCachePtr,
783 pub dom_id: DomId,
785}
786impl_option!(
787 StyledDom,
788 OptionStyledDom,
789 copy = false,
790 [Debug, Clone, PartialEq]
791);
792
793impl Default for StyledDom {
794 fn default() -> Self {
795 let root_node: NodeHierarchyItem = Node::ROOT.into();
796 let root_node_id: NodeHierarchyItemId =
797 NodeHierarchyItemId::from_crate_internal(Some(NodeId::ZERO));
798 Self {
799 root: root_node_id,
800 node_hierarchy: vec![root_node].into(),
801 node_data: vec![NodeData::create_body()].into(),
802 styled_nodes: vec![StyledNode::default()].into(),
803 cascade_info: vec![CascadeInfo {
804 index_in_parent: 0,
805 is_last_child: true,
806 }]
807 .into(),
808 tag_ids_to_node_ids: Vec::new().into(),
809 non_leaf_nodes: vec![ParentWithNodeDepth {
810 depth: 0,
811 node_id: root_node_id,
812 }]
813 .into(),
814 nodes_with_window_callbacks: Vec::new().into(),
815 nodes_with_not_callbacks: Vec::new().into(),
816 nodes_with_datasets: Vec::new().into(),
817 css_property_cache: CssPropertyCachePtr::new(CssPropertyCache::empty(1)),
818 dom_id: DomId::ROOT_ID,
819 }
820 }
821}
822
823impl StyledDom {
824 pub fn create(dom: &mut Dom, mut css: Css) -> Self {
831 use core::mem;
832
833 use crate::dom::EventFilter;
834
835 let mut swap_dom = Dom::create_body();
836
837 mem::swap(dom, &mut swap_dom);
838
839 let compact_dom: CompactDom = swap_dom.into();
840 let non_leaf_nodes = compact_dom
841 .node_hierarchy
842 .as_ref()
843 .get_parents_sorted_by_depth();
844 let node_hierarchy: NodeHierarchyItemVec = compact_dom
845 .node_hierarchy
846 .as_ref()
847 .internal
848 .iter()
849 .map(|i| (*i).into())
850 .collect::<Vec<NodeHierarchyItem>>()
851 .into();
852
853 let mut styled_nodes = vec![
854 StyledNode {
855 styled_node_state: StyledNodeState::new()
856 };
857 compact_dom.len()
858 ];
859
860 let mut css_property_cache = CssPropertyCache::empty(compact_dom.node_data.len());
864
865 let html_tree =
866 construct_html_cascade_tree(
867 &compact_dom.node_hierarchy.as_ref(),
868 &non_leaf_nodes[..],
869 &compact_dom.node_data.as_ref(),
870 );
871
872 let non_leaf_nodes = non_leaf_nodes
873 .iter()
874 .map(|(depth, node_id)| ParentWithNodeDepth {
875 depth: *depth,
876 node_id: NodeHierarchyItemId::from_crate_internal(Some(*node_id)),
877 })
878 .collect::<Vec<_>>();
879
880 let non_leaf_nodes: ParentWithNodeDepthVec = non_leaf_nodes.into();
881
882 let tag_ids = css_property_cache.restyle(
884 &mut css,
885 &compact_dom.node_data.as_ref(),
886 &node_hierarchy,
887 &non_leaf_nodes,
888 &html_tree.as_ref(),
889 );
890
891 css_property_cache.apply_ua_css(compact_dom.node_data.as_ref().internal);
895
896 css_property_cache.compute_inherited_values(
900 node_hierarchy.as_container().internal,
901 compact_dom.node_data.as_ref().internal,
902 );
903
904 let compact = css_property_cache.build_compact_cache(
919 compact_dom.node_data.as_ref().internal,
920 );
921 css_property_cache.compact_cache = Some(compact);
922
923 let nodes_with_window_callbacks = compact_dom
926 .node_data
927 .as_ref()
928 .internal
929 .iter()
930 .enumerate()
931 .filter_map(|(node_id, c)| {
932 let node_has_none_callbacks = c.get_callbacks().iter().any(|cb| match cb.event {
933 EventFilter::Window(_) => true,
934 _ => false,
935 });
936 if node_has_none_callbacks {
937 Some(NodeHierarchyItemId::from_crate_internal(Some(NodeId::new(
938 node_id,
939 ))))
940 } else {
941 None
942 }
943 })
944 .collect::<Vec<_>>();
945
946 let nodes_with_not_callbacks = compact_dom
947 .node_data
948 .as_ref()
949 .internal
950 .iter()
951 .enumerate()
952 .filter_map(|(node_id, c)| {
953 let node_has_none_callbacks = c.get_callbacks().iter().any(|cb| match cb.event {
954 EventFilter::Not(_) => true,
955 _ => false,
956 });
957 if node_has_none_callbacks {
958 Some(NodeHierarchyItemId::from_crate_internal(Some(NodeId::new(
959 node_id,
960 ))))
961 } else {
962 None
963 }
964 })
965 .collect::<Vec<_>>();
966
967 let nodes_with_datasets = compact_dom
969 .node_data
970 .as_ref()
971 .internal
972 .iter()
973 .enumerate()
974 .filter_map(|(node_id, c)| {
975 if !c.get_callbacks().is_empty() || c.get_dataset().is_some() {
976 Some(NodeHierarchyItemId::from_crate_internal(Some(NodeId::new(
977 node_id,
978 ))))
979 } else {
980 None
981 }
982 })
983 .collect::<Vec<_>>();
984
985 let mut styled_dom = StyledDom {
986 root: NodeHierarchyItemId::from_crate_internal(Some(compact_dom.root)),
987 node_hierarchy,
988 node_data: compact_dom.node_data.internal.into(),
989 cascade_info: html_tree.internal.into(),
990 styled_nodes: styled_nodes.into(),
991 tag_ids_to_node_ids: tag_ids.into(),
992 nodes_with_window_callbacks: nodes_with_window_callbacks.into(),
993 nodes_with_not_callbacks: nodes_with_not_callbacks.into(),
994 nodes_with_datasets: nodes_with_datasets.into(),
995 non_leaf_nodes,
996 css_property_cache: CssPropertyCachePtr::new(css_property_cache),
997 dom_id: DomId::ROOT_ID, };
999
1000 #[cfg(feature = "table_layout")]
1004 if let Err(e) = crate::dom_table::generate_anonymous_table_elements(&mut styled_dom) {
1005 eprintln!(
1006 "Warning: Failed to generate anonymous table elements: {:?}",
1007 e
1008 );
1009 }
1010
1011 styled_dom
1012 }
1013
1014 pub fn append_child(&mut self, mut other: Self) {
1017 let self_len = self.node_hierarchy.as_ref().len();
1019 let other_len = other.node_hierarchy.as_ref().len();
1020 let self_root_id = self.root.into_crate_internal().unwrap_or(NodeId::ZERO);
1021 let other_root_id = other.root.into_crate_internal().unwrap_or(NodeId::ZERO);
1022
1023 let current_root_children_count = self_root_id
1025 .az_children(&self.node_hierarchy.as_container())
1026 .count();
1027
1028 other.cascade_info.as_mut()[other_root_id.index()].index_in_parent =
1029 current_root_children_count as u32;
1030 other.cascade_info.as_mut()[other_root_id.index()].is_last_child = true;
1031
1032 self.cascade_info.append(&mut other.cascade_info);
1033
1034 for other in other.node_hierarchy.as_mut().iter_mut() {
1037 if other.parent != 0 {
1038 other.parent += self_len;
1039 }
1040 if other.previous_sibling != 0 {
1041 other.previous_sibling += self_len;
1042 }
1043 if other.next_sibling != 0 {
1044 other.next_sibling += self_len;
1045 }
1046 if other.last_child != 0 {
1047 other.last_child += self_len;
1048 }
1049 }
1050
1051 other.node_hierarchy.as_container_mut()[other_root_id].parent =
1052 NodeId::into_raw(&Some(self_root_id));
1053 let current_last_child = self.node_hierarchy.as_container()[self_root_id].last_child_id();
1054 other.node_hierarchy.as_container_mut()[other_root_id].previous_sibling =
1055 NodeId::into_raw(¤t_last_child);
1056 if let Some(current_last) = current_last_child {
1057 if self.node_hierarchy.as_container_mut()[current_last]
1058 .next_sibling_id()
1059 .is_some()
1060 {
1061 self.node_hierarchy.as_container_mut()[current_last].next_sibling +=
1062 other_root_id.index() + other_len;
1063 } else {
1064 self.node_hierarchy.as_container_mut()[current_last].next_sibling =
1065 NodeId::into_raw(&Some(NodeId::new(self_len + other_root_id.index())));
1066 }
1067 }
1068 self.node_hierarchy.as_container_mut()[self_root_id].last_child =
1069 NodeId::into_raw(&Some(NodeId::new(self_len + other_root_id.index())));
1070
1071 self.node_hierarchy.append(&mut other.node_hierarchy);
1072 self.node_data.append(&mut other.node_data);
1073 self.styled_nodes.append(&mut other.styled_nodes);
1074 self.get_css_property_cache_mut()
1075 .append(other.get_css_property_cache_mut());
1076
1077 for tag_id_node_id in other.tag_ids_to_node_ids.iter_mut() {
1080 tag_id_node_id.node_id.inner += self_len;
1081 }
1082
1083 self.tag_ids_to_node_ids
1084 .append(&mut other.tag_ids_to_node_ids);
1085
1086 for nid in other.nodes_with_window_callbacks.iter_mut() {
1087 nid.inner += self_len;
1088 }
1089 self.nodes_with_window_callbacks
1090 .append(&mut other.nodes_with_window_callbacks);
1091
1092 for nid in other.nodes_with_not_callbacks.iter_mut() {
1093 nid.inner += self_len;
1094 }
1095 self.nodes_with_not_callbacks
1096 .append(&mut other.nodes_with_not_callbacks);
1097
1098 for nid in other.nodes_with_datasets.iter_mut() {
1099 nid.inner += self_len;
1100 }
1101 self.nodes_with_datasets
1102 .append(&mut other.nodes_with_datasets);
1103
1104 if other_len != 1 {
1107 for other_non_leaf_node in other.non_leaf_nodes.iter_mut() {
1108 other_non_leaf_node.node_id.inner += self_len;
1109 other_non_leaf_node.depth += 1;
1110 }
1111 self.non_leaf_nodes.append(&mut other.non_leaf_nodes);
1112 self.non_leaf_nodes.sort_by(|a, b| a.depth.cmp(&b.depth));
1113 }
1114 }
1115
1116 pub fn append_child_with_index(&mut self, mut other: Self, child_index: usize) {
1119 let self_len = self.node_hierarchy.as_ref().len();
1121 let other_len = other.node_hierarchy.as_ref().len();
1122 let self_root_id = self.root.into_crate_internal().unwrap_or(NodeId::ZERO);
1123 let other_root_id = other.root.into_crate_internal().unwrap_or(NodeId::ZERO);
1124
1125 other.cascade_info.as_mut()[other_root_id.index()].index_in_parent = child_index as u32;
1127 other.cascade_info.as_mut()[other_root_id.index()].is_last_child = true;
1128
1129 self.cascade_info.append(&mut other.cascade_info);
1130
1131 for other in other.node_hierarchy.as_mut().iter_mut() {
1133 if other.parent != 0 {
1134 other.parent += self_len;
1135 }
1136 if other.previous_sibling != 0 {
1137 other.previous_sibling += self_len;
1138 }
1139 if other.next_sibling != 0 {
1140 other.next_sibling += self_len;
1141 }
1142 if other.last_child != 0 {
1143 other.last_child += self_len;
1144 }
1145 }
1146
1147 other.node_hierarchy.as_container_mut()[other_root_id].parent =
1148 NodeId::into_raw(&Some(self_root_id));
1149 let current_last_child = self.node_hierarchy.as_container()[self_root_id].last_child_id();
1150 other.node_hierarchy.as_container_mut()[other_root_id].previous_sibling =
1151 NodeId::into_raw(¤t_last_child);
1152 if let Some(current_last) = current_last_child {
1153 if self.node_hierarchy.as_container_mut()[current_last]
1154 .next_sibling_id()
1155 .is_some()
1156 {
1157 self.node_hierarchy.as_container_mut()[current_last].next_sibling +=
1158 other_root_id.index() + other_len;
1159 } else {
1160 self.node_hierarchy.as_container_mut()[current_last].next_sibling =
1161 NodeId::into_raw(&Some(NodeId::new(self_len + other_root_id.index())));
1162 }
1163 }
1164 self.node_hierarchy.as_container_mut()[self_root_id].last_child =
1165 NodeId::into_raw(&Some(NodeId::new(self_len + other_root_id.index())));
1166
1167 self.node_hierarchy.append(&mut other.node_hierarchy);
1168 self.node_data.append(&mut other.node_data);
1169 self.styled_nodes.append(&mut other.styled_nodes);
1170 self.get_css_property_cache_mut()
1171 .append(other.get_css_property_cache_mut());
1172
1173 for tag_id_node_id in other.tag_ids_to_node_ids.iter_mut() {
1176 tag_id_node_id.node_id.inner += self_len;
1177 }
1178
1179 self.tag_ids_to_node_ids
1180 .append(&mut other.tag_ids_to_node_ids);
1181
1182 for nid in other.nodes_with_window_callbacks.iter_mut() {
1183 nid.inner += self_len;
1184 }
1185 self.nodes_with_window_callbacks
1186 .append(&mut other.nodes_with_window_callbacks);
1187
1188 for nid in other.nodes_with_not_callbacks.iter_mut() {
1189 nid.inner += self_len;
1190 }
1191 self.nodes_with_not_callbacks
1192 .append(&mut other.nodes_with_not_callbacks);
1193
1194 for nid in other.nodes_with_datasets.iter_mut() {
1195 nid.inner += self_len;
1196 }
1197 self.nodes_with_datasets
1198 .append(&mut other.nodes_with_datasets);
1199
1200 if other_len != 1 {
1203 for other_non_leaf_node in other.non_leaf_nodes.iter_mut() {
1204 other_non_leaf_node.node_id.inner += self_len;
1205 other_non_leaf_node.depth += 1;
1206 }
1207 self.non_leaf_nodes.append(&mut other.non_leaf_nodes);
1208 }
1210 }
1211
1212 pub fn finalize_non_leaf_nodes(&mut self) {
1215 self.non_leaf_nodes.sort_by(|a, b| a.depth.cmp(&b.depth));
1216 }
1217
1218 pub fn with_child(mut self, other: Self) -> Self {
1220 self.append_child(other);
1221 self
1222 }
1223
1224 pub fn set_context_menu(&mut self, context_menu: Menu) {
1226 if let Some(root_id) = self.root.into_crate_internal() {
1227 self.node_data.as_container_mut()[root_id].set_context_menu(context_menu);
1228 }
1229 }
1230
1231 pub fn with_context_menu(mut self, context_menu: Menu) -> Self {
1233 self.set_context_menu(context_menu);
1234 self
1235 }
1236
1237 pub fn set_menu_bar(&mut self, menu_bar: Menu) {
1239 if let Some(root_id) = self.root.into_crate_internal() {
1240 self.node_data.as_container_mut()[root_id].set_menu_bar(menu_bar);
1241 }
1242 }
1243
1244 pub fn with_menu_bar(mut self, menu_bar: Menu) -> Self {
1246 self.set_menu_bar(menu_bar);
1247 self
1248 }
1249
1250 pub fn restyle(&mut self, mut css: Css) {
1252 let new_tag_ids = self.css_property_cache.downcast_mut().restyle(
1253 &mut css,
1254 &self.node_data.as_container(),
1255 &self.node_hierarchy,
1256 &self.non_leaf_nodes,
1257 &self.cascade_info.as_container(),
1258 );
1259
1260 self.css_property_cache
1262 .downcast_mut()
1263 .apply_ua_css(self.node_data.as_container().internal);
1264
1265 self.css_property_cache
1267 .downcast_mut()
1268 .compute_inherited_values(
1269 self.node_hierarchy.as_container().internal,
1270 self.node_data.as_container().internal,
1271 );
1272
1273 self.tag_ids_to_node_ids = new_tag_ids.into();
1274 }
1275
1276 #[inline]
1278 pub fn node_count(&self) -> usize {
1279 self.node_data.len()
1280 }
1281
1282 #[inline]
1284 pub fn get_css_property_cache<'a>(&'a self) -> &'a CssPropertyCache {
1285 &*self.css_property_cache.ptr
1286 }
1287
1288 #[inline]
1290 pub fn get_css_property_cache_mut<'a>(&'a mut self) -> &'a mut CssPropertyCache {
1291 &mut *self.css_property_cache.ptr
1292 }
1293
1294 #[inline]
1296 pub fn get_styled_node_state(&self, node_id: &NodeId) -> StyledNodeState {
1297 self.styled_nodes.as_container()[*node_id]
1298 .styled_node_state
1299 .clone()
1300 }
1301
1302 pub fn scan_for_image_keys(&self, css_image_cache: &ImageCache) -> FastBTreeSet<ImageRef> {
1304 use azul_css::props::style::StyleBackgroundContentVec;
1305
1306 use crate::{dom::NodeType::*, resources::OptionImageMask};
1307
1308 #[derive(Default)]
1309 struct ScanImageVec {
1310 node_type_image: Option<ImageRef>,
1311 background_image: Vec<ImageRef>,
1312 clip_mask: Option<ImageRef>,
1313 }
1314
1315 let default_backgrounds: StyleBackgroundContentVec = Vec::new().into();
1316
1317 let images = self
1318 .node_data
1319 .as_container()
1320 .internal
1321 .iter()
1322 .enumerate()
1323 .map(|(node_id, node_data)| {
1324 let node_id = NodeId::new(node_id);
1325 let mut v = ScanImageVec::default();
1326
1327 if let Image(id) = node_data.get_node_type() {
1329 v.node_type_image = Some(id.clone());
1330 }
1331
1332 let opt_background_image = self.get_css_property_cache().get_background_content(
1334 &node_data,
1335 &node_id,
1336 &self.styled_nodes.as_container()[node_id].styled_node_state,
1337 );
1338
1339 if let Some(style_backgrounds) = opt_background_image {
1340 v.background_image = style_backgrounds
1341 .get_property()
1342 .unwrap_or(&default_backgrounds)
1343 .iter()
1344 .filter_map(|bg| {
1345 use azul_css::props::style::StyleBackgroundContent::*;
1346 let css_image_id = match bg {
1347 Image(i) => i,
1348 _ => return None,
1349 };
1350 let image_ref = css_image_cache.get_css_image_id(css_image_id)?;
1351 Some(image_ref.clone())
1352 })
1353 .collect();
1354 }
1355
1356 if let Some(clip_mask) = node_data.get_clip_mask() {
1358 v.clip_mask = Some(clip_mask.image.clone());
1359 }
1360
1361 v
1362 })
1363 .collect::<Vec<_>>();
1364
1365 let mut set = FastBTreeSet::new();
1366
1367 for scan_image in images.into_iter() {
1368 if let Some(n) = scan_image.node_type_image {
1369 set.insert(n);
1370 }
1371 if let Some(n) = scan_image.clip_mask {
1372 set.insert(n);
1373 }
1374 for bg in scan_image.background_image {
1375 set.insert(bg);
1376 }
1377 }
1378
1379 set
1380 }
1381
1382 #[must_use]
1384 pub fn restyle_nodes_hover(
1385 &mut self,
1386 nodes: &[NodeId],
1387 new_hover_state: bool,
1388 ) -> BTreeMap<NodeId, Vec<ChangedCssProperty>> {
1389 let old_node_states = nodes
1391 .iter()
1392 .map(|nid| {
1393 self.styled_nodes.as_container()[*nid]
1394 .styled_node_state
1395 .clone()
1396 })
1397 .collect::<Vec<_>>();
1398
1399 for nid in nodes.iter() {
1400 self.styled_nodes.as_container_mut()[*nid]
1401 .styled_node_state
1402 .hover = new_hover_state;
1403 }
1404
1405 let css_property_cache = self.get_css_property_cache();
1406 let styled_nodes = self.styled_nodes.as_container();
1407 let node_data = self.node_data.as_container();
1408
1409 let default_map = BTreeMap::default();
1410
1411 let v = nodes
1413 .iter()
1414 .zip(old_node_states.iter())
1415 .filter_map(|(node_id, old_node_state)| {
1416 let mut keys_normal: Vec<_> = css_property_cache
1417 .css_hover_props
1418 .get(node_id.index())
1419 .unwrap_or(&default_map)
1420 .keys()
1421 .collect();
1422 let mut keys_inherited: Vec<_> = css_property_cache
1423 .cascaded_hover_props
1424 .get(node_id.index())
1425 .unwrap_or(&default_map)
1426 .keys()
1427 .collect();
1428 let keys_inline: Vec<CssPropertyType> = {
1429 use azul_css::dynamic_selector::{DynamicSelector, PseudoStateType};
1430 node_data[*node_id]
1431 .css_props
1432 .iter()
1433 .filter_map(|prop| {
1434 let is_hover = prop.apply_if.as_slice().iter().any(|c| {
1435 matches!(c, DynamicSelector::PseudoState(PseudoStateType::Hover))
1436 });
1437 if is_hover {
1438 Some(prop.property.get_type())
1439 } else {
1440 None
1441 }
1442 })
1443 .collect()
1444 };
1445 let mut keys_inline_ref = keys_inline.iter().map(|r| r).collect();
1446
1447 keys_normal.append(&mut keys_inherited);
1448 keys_normal.append(&mut keys_inline_ref);
1449
1450 let node_properties_that_could_have_changed = keys_normal;
1451
1452 if node_properties_that_could_have_changed.is_empty() {
1453 return None;
1454 }
1455
1456 let new_node_state = &styled_nodes[*node_id].styled_node_state;
1457 let node_data = &node_data[*node_id];
1458
1459 let changes = node_properties_that_could_have_changed
1460 .into_iter()
1461 .filter_map(|prop| {
1462 let old = css_property_cache.get_property(
1464 node_data,
1465 node_id,
1466 old_node_state,
1467 prop,
1468 );
1469 let new = css_property_cache.get_property(
1470 node_data,
1471 node_id,
1472 new_node_state,
1473 prop,
1474 );
1475 if old == new {
1476 None
1477 } else {
1478 Some(ChangedCssProperty {
1479 previous_state: old_node_state.clone(),
1480 previous_prop: match old {
1481 None => CssProperty::auto(*prop),
1482 Some(s) => s.clone(),
1483 },
1484 current_state: new_node_state.clone(),
1485 current_prop: match new {
1486 None => CssProperty::auto(*prop),
1487 Some(s) => s.clone(),
1488 },
1489 })
1490 }
1491 })
1492 .collect::<Vec<_>>();
1493
1494 if changes.is_empty() {
1495 None
1496 } else {
1497 Some((*node_id, changes))
1498 }
1499 })
1500 .collect::<Vec<_>>();
1501
1502 v.into_iter().collect()
1503 }
1504
1505 #[must_use]
1507 pub fn restyle_nodes_active(
1508 &mut self,
1509 nodes: &[NodeId],
1510 new_active_state: bool,
1511 ) -> BTreeMap<NodeId, Vec<ChangedCssProperty>> {
1512 let old_node_states = nodes
1514 .iter()
1515 .map(|nid| {
1516 self.styled_nodes.as_container()[*nid]
1517 .styled_node_state
1518 .clone()
1519 })
1520 .collect::<Vec<_>>();
1521
1522 for nid in nodes.iter() {
1523 self.styled_nodes.as_container_mut()[*nid]
1524 .styled_node_state
1525 .active = new_active_state;
1526 }
1527
1528 let css_property_cache = self.get_css_property_cache();
1529 let styled_nodes = self.styled_nodes.as_container();
1530 let node_data = self.node_data.as_container();
1531
1532 let default_map = BTreeMap::default();
1533
1534 let v = nodes
1536 .iter()
1537 .zip(old_node_states.iter())
1538 .filter_map(|(node_id, old_node_state)| {
1539 let mut keys_normal: Vec<_> = css_property_cache
1540 .css_active_props
1541 .get(node_id.index())
1542 .unwrap_or(&default_map)
1543 .keys()
1544 .collect();
1545
1546 let mut keys_inherited: Vec<_> = css_property_cache
1547 .cascaded_active_props
1548 .get(node_id.index())
1549 .unwrap_or(&default_map)
1550 .keys()
1551 .collect();
1552
1553 let keys_inline: Vec<CssPropertyType> = {
1554 use azul_css::dynamic_selector::{DynamicSelector, PseudoStateType};
1555 node_data[*node_id]
1556 .css_props
1557 .iter()
1558 .filter_map(|prop| {
1559 let is_active = prop.apply_if.as_slice().iter().any(|c| {
1560 matches!(c, DynamicSelector::PseudoState(PseudoStateType::Active))
1561 });
1562 if is_active {
1563 Some(prop.property.get_type())
1564 } else {
1565 None
1566 }
1567 })
1568 .collect()
1569 };
1570 let mut keys_inline_ref = keys_inline.iter().map(|r| r).collect();
1571
1572 keys_normal.append(&mut keys_inherited);
1573 keys_normal.append(&mut keys_inline_ref);
1574
1575 let node_properties_that_could_have_changed = keys_normal;
1576
1577 if node_properties_that_could_have_changed.is_empty() {
1578 return None;
1579 }
1580
1581 let new_node_state = &styled_nodes[*node_id].styled_node_state;
1582 let node_data = &node_data[*node_id];
1583
1584 let changes = node_properties_that_could_have_changed
1585 .into_iter()
1586 .filter_map(|prop| {
1587 let old = css_property_cache.get_property(
1589 node_data,
1590 node_id,
1591 old_node_state,
1592 prop,
1593 );
1594 let new = css_property_cache.get_property(
1595 node_data,
1596 node_id,
1597 new_node_state,
1598 prop,
1599 );
1600 if old == new {
1601 None
1602 } else {
1603 Some(ChangedCssProperty {
1604 previous_state: old_node_state.clone(),
1605 previous_prop: match old {
1606 None => CssProperty::auto(*prop),
1607 Some(s) => s.clone(),
1608 },
1609 current_state: new_node_state.clone(),
1610 current_prop: match new {
1611 None => CssProperty::auto(*prop),
1612 Some(s) => s.clone(),
1613 },
1614 })
1615 }
1616 })
1617 .collect::<Vec<_>>();
1618
1619 if changes.is_empty() {
1620 None
1621 } else {
1622 Some((*node_id, changes))
1623 }
1624 })
1625 .collect::<Vec<_>>();
1626
1627 v.into_iter().collect()
1628 }
1629
1630 #[must_use]
1632 pub fn restyle_nodes_focus(
1633 &mut self,
1634 nodes: &[NodeId],
1635 new_focus_state: bool,
1636 ) -> BTreeMap<NodeId, Vec<ChangedCssProperty>> {
1637
1638 let old_node_states = nodes
1640 .iter()
1641 .map(|nid| {
1642 let state = self.styled_nodes.as_container()[*nid]
1643 .styled_node_state
1644 .clone();
1645 state
1646 })
1647 .collect::<Vec<_>>();
1648
1649 for nid in nodes.iter() {
1650 self.styled_nodes.as_container_mut()[*nid]
1651 .styled_node_state
1652 .focused = new_focus_state;
1653 }
1654
1655 let css_property_cache = self.get_css_property_cache();
1656 let styled_nodes = self.styled_nodes.as_container();
1657 let node_data = self.node_data.as_container();
1658
1659 let default_map = BTreeMap::default();
1660
1661 let v = nodes
1663 .iter()
1664 .zip(old_node_states.iter())
1665 .filter_map(|(node_id, old_node_state)| {
1666 let mut keys_normal: Vec<_> = css_property_cache
1667 .css_focus_props
1668 .get(node_id.index())
1669 .unwrap_or(&default_map)
1670 .keys()
1671 .collect();
1672
1673
1674 let mut keys_inherited: Vec<_> = css_property_cache
1675 .cascaded_focus_props
1676 .get(node_id.index())
1677 .unwrap_or(&default_map)
1678 .keys()
1679 .collect();
1680
1681
1682 let keys_inline: Vec<CssPropertyType> = {
1683 use azul_css::dynamic_selector::{DynamicSelector, PseudoStateType};
1684 node_data[*node_id]
1685 .css_props
1686 .iter()
1687 .filter_map(|prop| {
1688 let is_focus = prop.apply_if.as_slice().iter().any(|c| {
1689 matches!(c, DynamicSelector::PseudoState(PseudoStateType::Focus))
1690 });
1691 if is_focus {
1692 Some(prop.property.get_type())
1693 } else {
1694 None
1695 }
1696 })
1697 .collect()
1698 };
1699 let mut keys_inline_ref = keys_inline.iter().map(|r| r).collect();
1700
1701 keys_normal.append(&mut keys_inherited);
1702 keys_normal.append(&mut keys_inline_ref);
1703
1704 let node_properties_that_could_have_changed = keys_normal;
1705
1706
1707 if node_properties_that_could_have_changed.is_empty() {
1708 return None;
1709 }
1710
1711 let new_node_state = &styled_nodes[*node_id].styled_node_state;
1712 let node_data = &node_data[*node_id];
1713
1714 let changes = node_properties_that_could_have_changed
1715 .into_iter()
1716 .filter_map(|prop| {
1717 let old = css_property_cache.get_property(
1719 node_data,
1720 node_id,
1721 old_node_state,
1722 prop,
1723 );
1724 let new = css_property_cache.get_property(
1725 node_data,
1726 node_id,
1727 new_node_state,
1728 prop,
1729 );
1730 if old == new {
1731 None
1732 } else {
1733 Some(ChangedCssProperty {
1734 previous_state: old_node_state.clone(),
1735 previous_prop: match old {
1736 None => CssProperty::auto(*prop),
1737 Some(s) => s.clone(),
1738 },
1739 current_state: new_node_state.clone(),
1740 current_prop: match new {
1741 None => CssProperty::auto(*prop),
1742 Some(s) => s.clone(),
1743 },
1744 })
1745 }
1746 })
1747 .collect::<Vec<_>>();
1748
1749 if changes.is_empty() {
1750 None
1751 } else {
1752 Some((*node_id, changes))
1753 }
1754 })
1755 .collect::<Vec<_>>();
1756
1757 v.into_iter().collect()
1758 }
1759
1760 #[must_use]
1774 pub fn restyle_on_state_change(
1775 &mut self,
1776 focus_changes: Option<FocusChange>,
1777 hover_changes: Option<HoverChange>,
1778 active_changes: Option<ActiveChange>,
1779 ) -> RestyleResult {
1780
1781 let mut result = RestyleResult::default();
1782 result.gpu_only_changes = true; let mut process_changes = |changes: BTreeMap<NodeId, Vec<ChangedCssProperty>>| {
1786 for (node_id, props) in changes {
1787 for change in &props {
1788 let prop_type = change.current_prop.get_type();
1789
1790 let scope = prop_type.relayout_scope(true);
1797
1798 if scope > result.max_relayout_scope {
1800 result.max_relayout_scope = scope;
1801 }
1802
1803 if scope != RelayoutScope::None {
1805 result.needs_layout = true;
1806 result.gpu_only_changes = false;
1807 }
1808
1809 if !prop_type.is_gpu_only_property() {
1811 result.gpu_only_changes = false;
1812 }
1813
1814 result.needs_display_list = true;
1816 }
1817
1818 result.changed_nodes.entry(node_id).or_default().extend(props);
1819 }
1820 };
1821
1822 if let Some(focus) = focus_changes {
1824 if let Some(old) = focus.lost_focus {
1825 let changes = self.restyle_nodes_focus(&[old], false);
1826 process_changes(changes);
1827 }
1828 if let Some(new) = focus.gained_focus {
1829 let changes = self.restyle_nodes_focus(&[new], true);
1830 process_changes(changes);
1831 }
1832 }
1833
1834 if let Some(hover) = hover_changes {
1836 if !hover.left_nodes.is_empty() {
1837 let changes = self.restyle_nodes_hover(&hover.left_nodes, false);
1838 process_changes(changes);
1839 }
1840 if !hover.entered_nodes.is_empty() {
1841 let changes = self.restyle_nodes_hover(&hover.entered_nodes, true);
1842 process_changes(changes);
1843 }
1844 }
1845
1846 if let Some(active) = active_changes {
1848 if !active.deactivated.is_empty() {
1849 let changes = self.restyle_nodes_active(&active.deactivated, false);
1850 process_changes(changes);
1851 }
1852 if !active.activated.is_empty() {
1853 let changes = self.restyle_nodes_active(&active.activated, true);
1854 process_changes(changes);
1855 }
1856 }
1857
1858 if result.changed_nodes.is_empty() {
1860 result.needs_display_list = false;
1861 result.gpu_only_changes = false;
1862 }
1863
1864 if result.needs_layout {
1866 result.needs_display_list = true;
1867 result.gpu_only_changes = false;
1868 }
1869
1870 result
1871 }
1872
1873 #[must_use]
1876 pub fn restyle_user_property(
1877 &mut self,
1878 node_id: &NodeId,
1879 new_properties: &[CssProperty],
1880 ) -> BTreeMap<NodeId, Vec<ChangedCssProperty>> {
1881 let mut map = BTreeMap::default();
1882
1883 if new_properties.is_empty() {
1884 return map;
1885 }
1886
1887 let node_data = self.node_data.as_container();
1888 let node_data = &node_data[*node_id];
1889
1890 let node_states = &self.styled_nodes.as_container();
1891 let old_node_state = &node_states[*node_id].styled_node_state;
1892
1893 let changes: Vec<ChangedCssProperty> = {
1894 let css_property_cache = self.get_css_property_cache();
1895
1896 new_properties
1897 .iter()
1898 .filter_map(|new_prop| {
1899 let old_prop = css_property_cache.get_property(
1900 node_data,
1901 node_id,
1902 old_node_state,
1903 &new_prop.get_type(),
1904 );
1905
1906 let old_prop = match old_prop {
1907 None => CssProperty::auto(new_prop.get_type()),
1908 Some(s) => s.clone(),
1909 };
1910
1911 if old_prop == *new_prop {
1912 None
1913 } else {
1914 Some(ChangedCssProperty {
1915 previous_state: old_node_state.clone(),
1916 previous_prop: old_prop,
1917 current_state: old_node_state.clone(),
1919 current_prop: new_prop.clone(),
1920 })
1921 }
1922 })
1923 .collect()
1924 };
1925
1926 let css_property_cache_mut = self.get_css_property_cache_mut();
1927
1928 for new_prop in new_properties.iter() {
1929 if new_prop.is_initial() {
1930 let map = &mut css_property_cache_mut
1931 .user_overridden_properties[node_id.index()];
1932 map.remove(&new_prop.get_type());
1934 } else {
1935 css_property_cache_mut
1936 .user_overridden_properties[node_id.index()]
1937 .insert(new_prop.get_type(), new_prop.clone());
1938 }
1939 }
1940
1941 if !changes.is_empty() {
1942 map.insert(*node_id, changes);
1943 }
1944
1945 map
1946 }
1947
1948 pub fn scan_for_iframe_callbacks(&self) -> Vec<NodeId> {
1950 use crate::dom::NodeType;
1951 self.node_data
1952 .as_ref()
1953 .iter()
1954 .enumerate()
1955 .filter_map(|(node_id, node_data)| match node_data.get_node_type() {
1956 NodeType::IFrame(_) => Some(NodeId::new(node_id)),
1957 _ => None,
1958 })
1959 .collect()
1960 }
1961
1962 pub fn scan_for_gltexture_callbacks(&self) -> Vec<NodeId> {
1964 use crate::dom::NodeType;
1965 self.node_data
1966 .as_ref()
1967 .iter()
1968 .enumerate()
1969 .filter_map(|(node_id, node_data)| {
1970 use crate::resources::DecodedImage;
1971 match node_data.get_node_type() {
1972 NodeType::Image(image_ref) => {
1973 if let DecodedImage::Callback(_) = image_ref.get_data() {
1974 Some(NodeId::new(node_id))
1975 } else {
1976 None
1977 }
1978 }
1979 _ => None,
1980 }
1981 })
1982 .collect()
1983 }
1984
1985 pub fn get_html_string(&self, custom_head: &str, custom_body: &str, test_mode: bool) -> String {
1995 let css_property_cache = self.get_css_property_cache();
1996
1997 let mut output = String::new();
1998
1999 let mut should_print_close_tag_after_node = BTreeMap::new();
2001
2002 let should_print_close_tag_debug = self
2003 .non_leaf_nodes
2004 .iter()
2005 .filter_map(|p| {
2006 let parent_node_id = p.node_id.into_crate_internal()?;
2007 let mut total_last_child = None;
2008 recursive_get_last_child(
2009 parent_node_id,
2010 &self.node_hierarchy.as_ref(),
2011 &mut total_last_child,
2012 );
2013 let total_last_child = total_last_child?;
2014 Some((parent_node_id, (total_last_child, p.depth)))
2015 })
2016 .collect::<BTreeMap<_, _>>();
2017
2018 for (parent_id, (last_child, parent_depth)) in should_print_close_tag_debug {
2019 should_print_close_tag_after_node
2020 .entry(last_child)
2021 .or_insert_with(|| Vec::new())
2022 .push((parent_id, parent_depth));
2023 }
2024
2025 let mut all_node_depths = self
2026 .non_leaf_nodes
2027 .iter()
2028 .filter_map(|p| {
2029 let parent_node_id = p.node_id.into_crate_internal()?;
2030 Some((parent_node_id, p.depth))
2031 })
2032 .collect::<BTreeMap<_, _>>();
2033
2034 for (parent_node_id, parent_depth) in self
2035 .non_leaf_nodes
2036 .iter()
2037 .filter_map(|p| Some((p.node_id.into_crate_internal()?, p.depth)))
2038 {
2039 for child_id in parent_node_id.az_children(&self.node_hierarchy.as_container()) {
2040 all_node_depths.insert(child_id, parent_depth + 1);
2041 }
2042 }
2043
2044 for node_id in self.node_hierarchy.as_container().linear_iter() {
2045 let depth = all_node_depths[&node_id];
2046
2047 let node_data = &self.node_data.as_container()[node_id];
2048 let node_state = &self.styled_nodes.as_container()[node_id].styled_node_state;
2049 let tabs = String::from(" ").repeat(depth);
2050
2051 output.push_str("\r\n");
2052 output.push_str(&tabs);
2053 output.push_str(&node_data.debug_print_start(css_property_cache, &node_id, node_state));
2054
2055 if let Some(content) = node_data.get_node_type().format().as_ref() {
2056 output.push_str(content);
2057 }
2058
2059 let node_has_children = self.node_hierarchy.as_container()[node_id]
2060 .first_child_id(node_id)
2061 .is_some();
2062 if !node_has_children {
2063 let node_data = &self.node_data.as_container()[node_id];
2064 output.push_str(&node_data.debug_print_end());
2065 }
2066
2067 if let Some(close_tag_vec) = should_print_close_tag_after_node.get(&node_id) {
2068 let mut close_tag_vec = close_tag_vec.clone();
2069 close_tag_vec.sort_by(|a, b| b.1.cmp(&a.1)); for (close_tag_parent_id, close_tag_depth) in close_tag_vec {
2071 let node_data = &self.node_data.as_container()[close_tag_parent_id];
2072 let tabs = String::from(" ").repeat(close_tag_depth);
2073 output.push_str("\r\n");
2074 output.push_str(&tabs);
2075 output.push_str(&node_data.debug_print_end());
2076 }
2077 }
2078 }
2079
2080 if !test_mode {
2081 format!(
2082 "
2083 <html>
2084 <head>
2085 <style>* {{ margin:0px; padding:0px; }}</style>
2086 {custom_head}
2087 </head>
2088 {output}
2089 {custom_body}
2090 </html>
2091 "
2092 )
2093 } else {
2094 output
2095 }
2096 }
2097
2098 pub fn get_subtree(&self, parent: NodeId) -> Vec<NodeId> {
2100 let mut total_last_child = None;
2101 recursive_get_last_child(parent, &self.node_hierarchy.as_ref(), &mut total_last_child);
2102 if let Some(last) = total_last_child {
2103 (parent.index()..=last.index())
2104 .map(|id| NodeId::new(id))
2105 .collect()
2106 } else {
2107 Vec::new()
2108 }
2109 }
2110
2111 pub fn get_subtree_parents(&self, parent: NodeId) -> Vec<NodeId> {
2114 let mut total_last_child = None;
2115 recursive_get_last_child(parent, &self.node_hierarchy.as_ref(), &mut total_last_child);
2116 if let Some(last) = total_last_child {
2117 (parent.index()..=last.index())
2118 .filter_map(|id| {
2119 if self.node_hierarchy.as_ref()[id].last_child_id().is_some() {
2120 Some(NodeId::new(id))
2121 } else {
2122 None
2123 }
2124 })
2125 .collect()
2126 } else {
2127 Vec::new()
2128 }
2129 }
2130
2131 pub fn get_rects_in_rendering_order(&self) -> ContentGroup {
2133 Self::determine_rendering_order(
2134 &self.non_leaf_nodes.as_ref(),
2135 &self.node_hierarchy.as_container(),
2136 &self.styled_nodes.as_container(),
2137 &self.node_data.as_container(),
2138 &self.get_css_property_cache(),
2139 )
2140 }
2141
2142 fn determine_rendering_order<'a>(
2145 non_leaf_nodes: &[ParentWithNodeDepth],
2146 node_hierarchy: &NodeDataContainerRef<'a, NodeHierarchyItem>,
2147 styled_nodes: &NodeDataContainerRef<StyledNode>,
2148 node_data_container: &NodeDataContainerRef<NodeData>,
2149 css_property_cache: &CssPropertyCache,
2150 ) -> ContentGroup {
2151 let children_sorted = non_leaf_nodes
2152 .iter()
2153 .filter_map(|parent| {
2154 Some((
2155 parent.node_id,
2156 sort_children_by_position(
2157 parent.node_id.into_crate_internal()?,
2158 node_hierarchy,
2159 styled_nodes,
2160 node_data_container,
2161 css_property_cache,
2162 ),
2163 ))
2164 })
2165 .collect::<Vec<_>>();
2166
2167 let children_sorted: BTreeMap<NodeHierarchyItemId, Vec<NodeHierarchyItemId>> =
2168 children_sorted.into_iter().collect();
2169
2170 let mut root_content_group = ContentGroup {
2171 root: NodeHierarchyItemId::from_crate_internal(Some(NodeId::ZERO)),
2172 children: Vec::new().into(),
2173 };
2174
2175 fill_content_group_children(&mut root_content_group, &children_sorted);
2176
2177 root_content_group
2178 }
2179
2180 pub fn swap_with_default(&mut self) -> Self {
2182 let mut new = Self::default();
2183 core::mem::swap(self, &mut new);
2184 new
2185 }
2186
2187 }
2190
2191#[derive(Debug, PartialEq, PartialOrd, Eq)]
2193pub struct CompactDom {
2194 pub node_hierarchy: NodeHierarchy,
2196 pub node_data: NodeDataContainer<NodeData>,
2198 pub root: NodeId,
2200}
2201
2202impl CompactDom {
2203 #[inline(always)]
2205 pub fn len(&self) -> usize {
2206 self.node_hierarchy.as_ref().len()
2207 }
2208}
2209
2210impl From<Dom> for CompactDom {
2211 fn from(dom: Dom) -> Self {
2212 convert_dom_into_compact_dom(dom)
2213 }
2214}
2215
2216pub fn convert_dom_into_compact_dom(mut dom: Dom) -> CompactDom {
2218 fn convert_dom_into_compact_dom_internal(
2220 dom: &mut Dom,
2221 node_hierarchy: &mut [Node],
2222 node_data: &mut Vec<NodeData>,
2223 parent_node_id: NodeId,
2224 node: Node,
2225 cur_node_id: &mut usize,
2226 ) {
2227 node_hierarchy[parent_node_id.index()] = node.clone();
2238
2239 let copy = dom.root.copy_special();
2240
2241 node_data[parent_node_id.index()] = copy;
2242
2243 *cur_node_id += 1;
2244
2245 let mut previous_sibling_id = None;
2246 let children_len = dom.children.len();
2247 for (child_index, child_dom) in dom.children.as_mut().iter_mut().enumerate() {
2248 let child_node_id = NodeId::new(*cur_node_id);
2249 let is_last_child = (child_index + 1) == children_len;
2250 let child_dom_is_empty = child_dom.children.is_empty();
2251 let child_node = Node {
2252 parent: Some(parent_node_id),
2253 previous_sibling: previous_sibling_id,
2254 next_sibling: if is_last_child {
2255 None
2256 } else {
2257 Some(child_node_id + child_dom.estimated_total_children + 1)
2258 },
2259 last_child: if child_dom_is_empty {
2260 None
2261 } else {
2262 Some(child_node_id + child_dom.estimated_total_children)
2263 },
2264 };
2265 previous_sibling_id = Some(child_node_id);
2266 convert_dom_into_compact_dom_internal(
2268 child_dom,
2269 node_hierarchy,
2270 node_data,
2271 child_node_id,
2272 child_node,
2273 cur_node_id,
2274 );
2275 }
2276 }
2277
2278 const DEFAULT_NODE_DATA: NodeData = NodeData::create_div();
2280
2281 let sum_nodes = dom.fixup_children_estimated();
2282
2283 let mut node_hierarchy = vec![Node::ROOT; sum_nodes + 1];
2284 let mut node_data = vec![NodeData::create_div(); sum_nodes + 1];
2285 let mut cur_node_id = 0;
2286
2287 let root_node_id = NodeId::ZERO;
2288 let root_node = Node {
2289 parent: None,
2290 previous_sibling: None,
2291 next_sibling: None,
2292 last_child: if dom.children.is_empty() {
2293 None
2294 } else {
2295 Some(root_node_id + dom.estimated_total_children)
2296 },
2297 };
2298
2299 convert_dom_into_compact_dom_internal(
2300 &mut dom,
2301 &mut node_hierarchy,
2302 &mut node_data,
2303 root_node_id,
2304 root_node,
2305 &mut cur_node_id,
2306 );
2307
2308 CompactDom {
2309 node_hierarchy: NodeHierarchy {
2310 internal: node_hierarchy,
2311 },
2312 node_data: NodeDataContainer {
2313 internal: node_data,
2314 },
2315 root: root_node_id,
2316 }
2317}
2318
2319fn fill_content_group_children(
2320 group: &mut ContentGroup,
2321 children_sorted: &BTreeMap<NodeHierarchyItemId, Vec<NodeHierarchyItemId>>,
2322) {
2323 if let Some(c) = children_sorted.get(&group.root) {
2324 group.children = c
2326 .iter()
2327 .map(|child| ContentGroup {
2328 root: *child,
2329 children: Vec::new().into(),
2330 })
2331 .collect::<Vec<ContentGroup>>()
2332 .into();
2333
2334 for c in group.children.as_mut() {
2335 fill_content_group_children(c, children_sorted);
2336 }
2337 }
2338}
2339
2340fn sort_children_by_position<'a>(
2341 parent: NodeId,
2342 node_hierarchy: &NodeDataContainerRef<'a, NodeHierarchyItem>,
2343 rectangles: &NodeDataContainerRef<StyledNode>,
2344 node_data_container: &NodeDataContainerRef<NodeData>,
2345 css_property_cache: &CssPropertyCache,
2346) -> Vec<NodeHierarchyItemId> {
2347 use azul_css::props::layout::LayoutPosition::*;
2348
2349 let children_positions = parent
2350 .az_children(node_hierarchy)
2351 .map(|nid| {
2352 let position = css_property_cache
2353 .get_position(
2354 &node_data_container[nid],
2355 &nid,
2356 &rectangles[nid].styled_node_state,
2357 )
2358 .and_then(|p| p.clone().get_property_or_default())
2359 .unwrap_or_default();
2360 let id = NodeHierarchyItemId::from_crate_internal(Some(nid));
2361 (id, position)
2362 })
2363 .collect::<Vec<_>>();
2364
2365 let mut not_absolute_children = children_positions
2366 .iter()
2367 .filter_map(|(node_id, position)| {
2368 if *position != Absolute {
2369 Some(*node_id)
2370 } else {
2371 None
2372 }
2373 })
2374 .collect::<Vec<_>>();
2375
2376 let mut absolute_children = children_positions
2377 .iter()
2378 .filter_map(|(node_id, position)| {
2379 if *position == Absolute {
2380 Some(*node_id)
2381 } else {
2382 None
2383 }
2384 })
2385 .collect::<Vec<_>>();
2386
2387 not_absolute_children.append(&mut absolute_children);
2389 not_absolute_children
2390}
2391
2392fn recursive_get_last_child(
2395 node_id: NodeId,
2396 node_hierarchy: &[NodeHierarchyItem],
2397 target: &mut Option<NodeId>,
2398) {
2399 match node_hierarchy[node_id.index()].last_child_id() {
2400 None => return,
2401 Some(s) => {
2402 *target = Some(s);
2403 recursive_get_last_child(s, node_hierarchy, target);
2404 }
2405 }
2406}
2407
2408pub fn is_before_in_document_order(
2422 hierarchy: &NodeHierarchyItemVec,
2423 node_a: NodeId,
2424 node_b: NodeId,
2425) -> bool {
2426 if node_a == node_b {
2427 return false;
2428 }
2429
2430 let hierarchy = hierarchy.as_container();
2431
2432 let path_a = get_path_to_root(&hierarchy, node_a);
2434 let path_b = get_path_to_root(&hierarchy, node_b);
2435
2436 let min_len = path_a.len().min(path_b.len());
2438
2439 for i in 0..min_len {
2440 if path_a[i] != path_b[i] {
2441 let child_towards_a = path_a[i];
2443 let child_towards_b = path_b[i];
2444
2445 return child_towards_a.index() < child_towards_b.index();
2448 }
2449 }
2450
2451 path_a.len() < path_b.len()
2453}
2454
2455fn get_path_to_root(
2457 hierarchy: &NodeDataContainerRef<'_, NodeHierarchyItem>,
2458 node: NodeId,
2459) -> Vec<NodeId> {
2460 let mut path = Vec::new();
2461 let mut current = Some(node);
2462
2463 while let Some(node_id) = current {
2464 path.push(node_id);
2465 current = hierarchy.get(node_id).and_then(|h| h.parent_id());
2466 }
2467
2468 path.reverse();
2470 path
2471}
2472
2473pub fn collect_nodes_in_document_order(
2486 hierarchy: &NodeHierarchyItemVec,
2487 start_node: NodeId,
2488 end_node: NodeId,
2489) -> Vec<NodeId> {
2490 if start_node == end_node {
2491 return vec![start_node];
2492 }
2493
2494 let hierarchy_container = hierarchy.as_container();
2495 let hierarchy_slice = hierarchy.as_ref();
2496
2497 let mut result = Vec::new();
2498 let mut in_range = false;
2499
2500 let mut stack: Vec<NodeId> = vec![NodeId::ZERO]; while let Some(current) = stack.pop() {
2505 if current == start_node {
2507 in_range = true;
2508 }
2509
2510 if in_range {
2512 result.push(current);
2513 }
2514
2515 if current == end_node {
2517 break;
2518 }
2519
2520 if let Some(item) = hierarchy_container.get(current) {
2523 if let Some(first_child) = item.first_child_id(current) {
2525 let mut children = Vec::new();
2527 let mut child = Some(first_child);
2528 while let Some(child_id) = child {
2529 children.push(child_id);
2530 child = hierarchy_container.get(child_id).and_then(|h| h.next_sibling_id());
2531 }
2532 for child_id in children.into_iter().rev() {
2534 stack.push(child_id);
2535 }
2536 }
2537 }
2538 }
2539
2540 result
2541}