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 parser::CssApiWrapper, AzString, Css, CssPath, CssProperty, CssPropertyType,
9 LayoutAlignContentValue, LayoutAlignItemsValue, LayoutBorderBottomWidthValue,
10 LayoutBorderLeftWidthValue, LayoutBorderRightWidthValue, LayoutBorderTopWidthValue,
11 LayoutBottomValue, LayoutBoxSizingValue, LayoutDisplayValue, LayoutFlexDirectionValue,
12 LayoutFlexGrowValue, LayoutFlexShrinkValue, LayoutFlexWrapValue, LayoutFloatValue,
13 LayoutHeightValue, LayoutJustifyContentValue, LayoutLeftValue, LayoutMarginBottomValue,
14 LayoutMarginLeftValue, LayoutMarginRightValue, LayoutMarginTopValue, LayoutMaxHeightValue,
15 LayoutMaxWidthValue, LayoutMinHeightValue, LayoutMinWidthValue, LayoutOverflowValue,
16 LayoutPaddingBottomValue, LayoutPaddingLeftValue, LayoutPaddingRightValue,
17 LayoutPaddingTopValue, LayoutPositionValue, LayoutRightValue, LayoutTopValue, LayoutWidthValue,
18 StyleBackfaceVisibilityValue, StyleBackgroundContentVecValue, StyleBackgroundPositionVecValue,
19 StyleBackgroundRepeatVecValue, StyleBackgroundSizeVecValue, StyleBorderBottomColorValue,
20 StyleBorderBottomLeftRadiusValue, StyleBorderBottomRightRadiusValue,
21 StyleBorderBottomStyleValue, StyleBorderLeftColorValue, StyleBorderLeftStyleValue,
22 StyleBorderRightColorValue, StyleBorderRightStyleValue, StyleBorderTopColorValue,
23 StyleBorderTopLeftRadiusValue, StyleBorderTopRightRadiusValue, StyleBorderTopStyleValue,
24 StyleBoxShadowValue, StyleCursorValue, StyleFilterVecValue, StyleFontFamily,
25 StyleFontFamilyVec, StyleFontFamilyVecValue, StyleFontSize, StyleFontSizeValue,
26 StyleLetterSpacingValue, StyleLineHeightValue, StyleMixBlendModeValue, StyleOpacityValue,
27 StylePerspectiveOriginValue, StyleTabWidthValue, StyleTextAlignValue, StyleTextColor,
28 StyleTextColorValue, StyleTransformOriginValue, StyleTransformVecValue, StyleWordSpacingValue,
29};
30
31use crate::{
32 app_resources::{Au, ImageCache, ImageRef, ImmediateFontId, RendererResources},
33 callbacks::{CallbackInfo, RefAny, Update},
34 dom::{
35 CompactDom, Dom, NodeData, NodeDataInlineCssProperty, NodeDataVec, OptionTabIndex,
36 TabIndex, TagId,
37 },
38 id_tree::{Node, NodeDataContainer, NodeDataContainerRef, NodeDataContainerRefMut, NodeId},
39 style::{
40 construct_html_cascade_tree, matches_html_element, rule_ends_with, CascadeInfo,
41 CascadeInfoVec,
42 },
43 window::Menu,
44 FastBTreeSet, FastHashMap,
45};
46
47#[repr(C)]
48#[derive(Debug, Clone, PartialEq, Hash, PartialOrd, Eq, Ord)]
49pub struct ChangedCssProperty {
50 pub previous_state: StyledNodeState,
51 pub previous_prop: CssProperty,
52 pub current_state: StyledNodeState,
53 pub current_prop: CssProperty,
54}
55
56impl_vec!(
57 ChangedCssProperty,
58 ChangedCssPropertyVec,
59 ChangedCssPropertyVecDestructor
60);
61impl_vec_debug!(ChangedCssProperty, ChangedCssPropertyVec);
62impl_vec_partialord!(ChangedCssProperty, ChangedCssPropertyVec);
63impl_vec_clone!(
64 ChangedCssProperty,
65 ChangedCssPropertyVec,
66 ChangedCssPropertyVecDestructor
67);
68impl_vec_partialeq!(ChangedCssProperty, ChangedCssPropertyVec);
69
70#[repr(C, u8)]
71#[derive(Debug, Clone, PartialEq, Hash, PartialOrd, Eq, Ord)]
72pub enum CssPropertySource {
73 Css(CssPath),
74 Inline,
75}
76
77#[repr(C)]
81#[derive(Clone, PartialEq, Hash, PartialOrd, Eq, Ord)]
82pub struct StyledNodeState {
83 pub normal: bool,
84 pub hover: bool,
85 pub active: bool,
86 pub focused: bool,
87}
88
89impl core::fmt::Debug for StyledNodeState {
90 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
91 let mut v = Vec::new();
92 if self.normal {
93 v.push("normal");
94 }
95 if self.hover {
96 v.push("hover");
97 }
98 if self.active {
99 v.push("active");
100 }
101 if self.focused {
102 v.push("focused");
103 }
104 write!(f, "{:?}", v)
105 }
106}
107
108impl Default for StyledNodeState {
109 fn default() -> StyledNodeState {
110 Self::new()
111 }
112}
113
114impl StyledNodeState {
115 pub const fn new() -> Self {
116 StyledNodeState {
117 normal: true,
118 hover: false,
119 active: false,
120 focused: false,
121 }
122 }
123}
124
125#[repr(C)]
127#[derive(Debug, Default, Clone, PartialEq, PartialOrd)]
128pub struct StyledNode {
129 pub state: StyledNodeState,
131 pub tag_id: OptionTagId,
135}
136
137impl_vec!(StyledNode, StyledNodeVec, StyledNodeVecDestructor);
138impl_vec_mut!(StyledNode, StyledNodeVec);
139impl_vec_debug!(StyledNode, StyledNodeVec);
140impl_vec_partialord!(StyledNode, StyledNodeVec);
141impl_vec_clone!(StyledNode, StyledNodeVec, StyledNodeVecDestructor);
142impl_vec_partialeq!(StyledNode, StyledNodeVec);
143
144impl StyledNodeVec {
145 pub fn as_container<'a>(&'a self) -> NodeDataContainerRef<'a, StyledNode> {
146 NodeDataContainerRef {
147 internal: self.as_ref(),
148 }
149 }
150 pub fn as_container_mut<'a>(&'a mut self) -> NodeDataContainerRefMut<'a, StyledNode> {
151 NodeDataContainerRefMut {
152 internal: self.as_mut(),
153 }
154 }
155}
156
157#[repr(C)]
158#[derive(Debug, PartialEq, Clone)]
159pub struct CssPropertyCachePtr {
160 pub ptr: Box<CssPropertyCache>,
161 pub run_destructor: bool,
162}
163
164impl CssPropertyCachePtr {
165 pub fn new(cache: CssPropertyCache) -> Self {
166 Self {
167 ptr: Box::new(cache),
168 run_destructor: true,
169 }
170 }
171 fn downcast_mut<'a>(&'a mut self) -> &'a mut CssPropertyCache {
172 &mut *self.ptr
173 }
174}
175
176impl Drop for CssPropertyCachePtr {
177 fn drop(&mut self) {
178 self.run_destructor = false;
179 }
180}
181
182#[derive(Debug, Default, Clone, PartialEq)]
194pub struct CssPropertyCache {
195 pub node_count: usize,
197
198 pub user_overridden_properties: BTreeMap<NodeId, BTreeMap<CssPropertyType, CssProperty>>,
200
201 pub cascaded_normal_props: BTreeMap<NodeId, BTreeMap<CssPropertyType, CssProperty>>,
203 pub cascaded_hover_props: BTreeMap<NodeId, BTreeMap<CssPropertyType, CssProperty>>,
204 pub cascaded_active_props: BTreeMap<NodeId, BTreeMap<CssPropertyType, CssProperty>>,
205 pub cascaded_focus_props: BTreeMap<NodeId, BTreeMap<CssPropertyType, CssProperty>>,
206
207 pub css_normal_props: BTreeMap<NodeId, BTreeMap<CssPropertyType, CssProperty>>,
209 pub css_hover_props: BTreeMap<NodeId, BTreeMap<CssPropertyType, CssProperty>>,
210 pub css_active_props: BTreeMap<NodeId, BTreeMap<CssPropertyType, CssProperty>>,
211 pub css_focus_props: BTreeMap<NodeId, BTreeMap<CssPropertyType, CssProperty>>,
212}
213
214impl CssPropertyCache {
215 #[must_use]
217 pub fn restyle(
218 &mut self,
219 css: &mut Css,
220 node_data: &NodeDataContainerRef<NodeData>,
221 node_hierarchy: &NodeHierarchyItemVec,
222 non_leaf_nodes: &ParentWithNodeDepthVec,
223 html_tree: &NodeDataContainerRef<CascadeInfo>,
224 ) -> Vec<TagIdToNodeIdMapping> {
225 use azul_css::{CssDeclaration, CssPathPseudoSelector::*, LayoutDisplay};
226
227 let css_is_empty = css.is_empty();
228
229 if !css_is_empty {
230 css.sort_by_specificity();
231
232 macro_rules! filter_rules {($expected_pseudo_selector:expr, $node_id:expr) => {{
233 css
234 .rules() .filter(|rule_block| rule_ends_with(&rule_block.path, $expected_pseudo_selector))
236 .filter(|rule_block| matches_html_element(
237 &rule_block.path,
238 $node_id,
239 &node_hierarchy.as_container(),
240 &node_data,
241 &html_tree,
242 $expected_pseudo_selector
243 ))
244 .flat_map(|matched_rule| {
246 matched_rule.declarations
247 .iter()
248 .filter_map(move |declaration| {
249 match declaration {
250 CssDeclaration::Static(s) => Some(s),
251 CssDeclaration::Dynamic(_d) => None, }
253 })
254 })
255 .map(|prop| prop.clone())
256 .collect::<Vec<CssProperty>>()
257 }};}
258
259 let css_normal_rules: NodeDataContainer<(NodeId, Vec<CssProperty>)> = node_data
269 .transform_nodeid_multithreaded_optional(|node_id| {
270 let r = filter_rules!(None, node_id);
271 if r.is_empty() {
272 None
273 } else {
274 Some((node_id, r))
275 }
276 });
277
278 let css_hover_rules: NodeDataContainer<(NodeId, Vec<CssProperty>)> = node_data
279 .transform_nodeid_multithreaded_optional(|node_id| {
280 let r = filter_rules!(Some(Hover), node_id);
281 if r.is_empty() {
282 None
283 } else {
284 Some((node_id, r))
285 }
286 });
287
288 let css_active_rules: NodeDataContainer<(NodeId, Vec<CssProperty>)> = node_data
289 .transform_nodeid_multithreaded_optional(|node_id| {
290 let r = filter_rules!(Some(Active), node_id);
291 if r.is_empty() {
292 None
293 } else {
294 Some((node_id, r))
295 }
296 });
297
298 let css_focus_rules: NodeDataContainer<(NodeId, Vec<CssProperty>)> = node_data
299 .transform_nodeid_multithreaded_optional(|node_id| {
300 let r = filter_rules!(Some(Focus), node_id);
301 if r.is_empty() {
302 None
303 } else {
304 Some((node_id, r))
305 }
306 });
307
308 self.css_normal_props = css_normal_rules
309 .internal
310 .into_iter()
311 .map(|(n, map)| {
312 (
313 n,
314 map.into_iter()
315 .map(|prop| (prop.get_type(), prop))
316 .collect(),
317 )
318 })
319 .collect();
320
321 self.css_hover_props = css_hover_rules
322 .internal
323 .into_iter()
324 .map(|(n, map)| {
325 (
326 n,
327 map.into_iter()
328 .map(|prop| (prop.get_type(), prop))
329 .collect(),
330 )
331 })
332 .collect();
333
334 self.css_active_props = css_active_rules
335 .internal
336 .into_iter()
337 .map(|(n, map)| {
338 (
339 n,
340 map.into_iter()
341 .map(|prop| (prop.get_type(), prop))
342 .collect(),
343 )
344 })
345 .collect();
346
347 self.css_focus_props = css_focus_rules
348 .internal
349 .into_iter()
350 .map(|(n, map)| {
351 (
352 n,
353 map.into_iter()
354 .map(|prop| (prop.get_type(), prop))
355 .collect(),
356 )
357 })
358 .collect();
359 }
360
361 for ParentWithNodeDepth { depth: _, node_id } in non_leaf_nodes.iter() {
364 let parent_id = match node_id.into_crate_internal() {
365 Some(s) => s,
366 None => continue,
367 };
368
369 macro_rules! inherit_props {
372 ($from_inherit_map:expr, $to_inherit_map:expr) => {
373 let parent_inheritable_css_props =
374 $from_inherit_map.get(&parent_id).and_then(|map| {
375 let parent_inherit_props = map
376 .iter()
377 .filter(|(css_prop_type, _)| css_prop_type.is_inheritable())
378 .map(|(css_prop_type, css_prop)| (*css_prop_type, css_prop.clone()))
379 .collect::<Vec<(CssPropertyType, CssProperty)>>();
380 if parent_inherit_props.is_empty() {
381 None
382 } else {
383 Some(parent_inherit_props)
384 }
385 });
386
387 match parent_inheritable_css_props {
388 Some(pi) => {
389 for child_id in parent_id.az_children(&node_hierarchy.as_container()) {
392 let child_map = $to_inherit_map
393 .entry(child_id)
394 .or_insert_with(|| BTreeMap::new());
395
396 for (inherited_rule_type, inherited_rule_value) in pi.iter() {
397 let _ = child_map
398 .entry(*inherited_rule_type)
399 .or_insert_with(|| inherited_rule_value.clone());
400 }
401 }
402 }
403 None => {}
404 }
405 };
406 }
407
408 macro_rules! inherit_inline_css_props {($filter_type:ident, $to_inherit_map:expr) => {
410 let parent_inheritable_css_props = &node_data[parent_id]
411 .inline_css_props
412 .iter()
413 .filter_map(|css_prop| if let NodeDataInlineCssProperty::$filter_type(p) = css_prop { Some(p) } else { None })
415 .filter(|css_prop| css_prop.get_type().is_inheritable())
417 .cloned()
418 .collect::<Vec<CssProperty>>();
419
420 if !parent_inheritable_css_props.is_empty() {
421 for child_id in parent_id.az_children(&node_hierarchy.as_container()) {
423 let child_map = $to_inherit_map.entry(child_id).or_insert_with(|| BTreeMap::new());
424 for inherited_rule in parent_inheritable_css_props.iter() {
425 let _ = child_map
426 .entry(inherited_rule.get_type())
427 .or_insert_with(|| inherited_rule.clone());
428 }
429 }
430 }
431
432 };}
433
434 inherit_inline_css_props!(Normal, self.cascaded_normal_props);
438 inherit_inline_css_props!(Hover, self.cascaded_hover_props);
439 inherit_inline_css_props!(Active, self.cascaded_active_props);
440 inherit_inline_css_props!(Focus, self.cascaded_focus_props);
441
442 if !css_is_empty {
444 inherit_props!(self.css_normal_props, self.cascaded_normal_props);
445 inherit_props!(self.css_hover_props, self.cascaded_hover_props);
446 inherit_props!(self.css_active_props, self.cascaded_active_props);
447 inherit_props!(self.css_focus_props, self.cascaded_focus_props);
448 }
449
450 inherit_props!(self.cascaded_normal_props, self.cascaded_normal_props);
452 inherit_props!(self.cascaded_hover_props, self.cascaded_hover_props);
453 inherit_props!(self.cascaded_active_props, self.cascaded_active_props);
454 inherit_props!(self.cascaded_focus_props, self.cascaded_focus_props);
455 }
456
457 let default_node_state = StyledNodeState::default();
460
461 node_data
470 .internal
471 .iter()
472 .enumerate()
473 .filter_map(|(node_id, node_data)| {
474 let node_id = NodeId::new(node_id);
475
476 let should_auto_insert_tabindex = node_data
477 .get_callbacks()
478 .iter()
479 .any(|cb| cb.event.is_focus_callback());
480
481 let tab_index = match node_data.get_tab_index() {
482 Some(s) => Some(*s),
483 None => {
484 if should_auto_insert_tabindex {
485 Some(TabIndex::Auto)
486 } else {
487 None
488 }
489 }
490 };
491
492 let mut node_should_have_tag = false;
493
494 loop {
497 let display = self
499 .get_display(&node_data, &node_id, &default_node_state)
500 .and_then(|p| p.get_property_or_default())
501 .unwrap_or_default();
502
503 if display == LayoutDisplay::None {
504 node_should_have_tag = false;
505 break;
506 }
507
508 if node_data.has_context_menu() {
509 node_should_have_tag = true;
510 break;
511 }
512
513 if tab_index.is_some() {
514 node_should_have_tag = true;
515 break;
516 }
517
518 if node_data.get_context_menu().is_some() {
520 node_should_have_tag = true;
521 break;
522 }
523
524 let node_has_hover_props =
526 node_data.inline_css_props.as_ref().iter().any(|p| match p {
527 NodeDataInlineCssProperty::Hover(_) => true,
528 _ => false,
529 }) || self.css_hover_props.get(&node_id).is_some()
530 || self.cascaded_hover_props.get(&node_id).is_some();
531
532 if node_has_hover_props {
533 node_should_have_tag = true;
534 break;
535 }
536
537 let node_has_active_props =
539 node_data.inline_css_props.as_ref().iter().any(|p| match p {
540 NodeDataInlineCssProperty::Active(_) => true,
541 _ => false,
542 }) || self.css_active_props.get(&node_id).is_some()
543 || self.cascaded_active_props.get(&node_id).is_some();
544
545 if node_has_active_props {
546 node_should_have_tag = true;
547 break;
548 }
549
550 let node_has_focus_props =
552 node_data.inline_css_props.as_ref().iter().any(|p| match p {
553 NodeDataInlineCssProperty::Focus(_) => true,
554 _ => false,
555 }) || self.css_focus_props.get(&node_id).is_some()
556 || self.cascaded_focus_props.get(&node_id).is_some();
557
558 if node_has_focus_props {
559 node_should_have_tag = true;
560 break;
561 }
562
563 let node_only_window_callbacks = node_data.get_callbacks().is_empty()
565 || node_data
566 .get_callbacks()
567 .iter()
568 .all(|cb| cb.event.is_window_callback());
569
570 if !node_only_window_callbacks {
571 node_should_have_tag = true;
572 break;
573 }
574
575 let node_has_non_default_cursor = self
577 .get_cursor(&node_data, &node_id, &default_node_state)
578 .is_some();
579
580 if node_has_non_default_cursor {
581 node_should_have_tag = true;
582 break;
583 }
584
585 break;
586 }
587
588 if !node_should_have_tag {
589 None
590 } else {
591 Some(TagIdToNodeIdMapping {
592 tag_id: AzTagId::from_crate_internal(TagId::unique()),
593 node_id: NodeHierarchyItemId::from_crate_internal(Some(node_id)),
594 tab_index: tab_index.into(),
595 parent_node_ids: {
596 let mut parents = Vec::new();
597 let mut cur_parent = node_hierarchy.as_container()[node_id].parent_id();
598 while let Some(c) = cur_parent.clone() {
599 parents.push(NodeHierarchyItemId::from_crate_internal(Some(c)));
600 cur_parent = node_hierarchy.as_container()[c].parent_id();
601 }
602 parents.reverse(); parents.into()
604 },
605 })
606 }
607 })
608 .collect()
609 }
610
611 pub fn get_computed_css_style_string(
612 &self,
613 node_data: &NodeData,
614 node_id: &NodeId,
615 node_state: &StyledNodeState,
616 ) -> String {
617 let mut s = String::new();
618 if let Some(p) = self.get_background_content(&node_data, node_id, node_state) {
619 s.push_str(&format!("background: {};", p.get_css_value_fmt()));
620 }
621 if let Some(p) = self.get_background_position(&node_data, node_id, node_state) {
622 s.push_str(&format!("background-position: {};", p.get_css_value_fmt()));
623 }
624 if let Some(p) = self.get_background_size(&node_data, node_id, node_state) {
625 s.push_str(&format!("background-size: {};", p.get_css_value_fmt()));
626 }
627 if let Some(p) = self.get_background_repeat(&node_data, node_id, node_state) {
628 s.push_str(&format!("background-repeat: {};", p.get_css_value_fmt()));
629 }
630 if let Some(p) = self.get_font_size(&node_data, node_id, node_state) {
631 s.push_str(&format!("font-size: {};", p.get_css_value_fmt()));
632 }
633 if let Some(p) = self.get_font_family(&node_data, node_id, node_state) {
634 s.push_str(&format!("font-family: {};", p.get_css_value_fmt()));
635 }
636 if let Some(p) = self.get_text_color(&node_data, node_id, node_state) {
637 s.push_str(&format!("color: {};", p.get_css_value_fmt()));
638 }
639 if let Some(p) = self.get_text_align(&node_data, node_id, node_state) {
640 s.push_str(&format!("text-align: {};", p.get_css_value_fmt()));
641 }
642 if let Some(p) = self.get_line_height(&node_data, node_id, node_state) {
643 s.push_str(&format!("line-height: {};", p.get_css_value_fmt()));
644 }
645 if let Some(p) = self.get_letter_spacing(&node_data, node_id, node_state) {
646 s.push_str(&format!("letter-spacing: {};", p.get_css_value_fmt()));
647 }
648 if let Some(p) = self.get_word_spacing(&node_data, node_id, node_state) {
649 s.push_str(&format!("word-spacing: {};", p.get_css_value_fmt()));
650 }
651 if let Some(p) = self.get_tab_width(&node_data, node_id, node_state) {
652 s.push_str(&format!("tab-width: {};", p.get_css_value_fmt()));
653 }
654 if let Some(p) = self.get_cursor(&node_data, node_id, node_state) {
655 s.push_str(&format!("cursor: {};", p.get_css_value_fmt()));
656 }
657 if let Some(p) = self.get_box_shadow_left(&node_data, node_id, node_state) {
658 s.push_str(&format!(
659 "-azul-box-shadow-left: {};",
660 p.get_css_value_fmt()
661 ));
662 }
663 if let Some(p) = self.get_box_shadow_right(&node_data, node_id, node_state) {
664 s.push_str(&format!(
665 "-azul-box-shadow-right: {};",
666 p.get_css_value_fmt()
667 ));
668 }
669 if let Some(p) = self.get_box_shadow_top(&node_data, node_id, node_state) {
670 s.push_str(&format!("-azul-box-shadow-top: {};", p.get_css_value_fmt()));
671 }
672 if let Some(p) = self.get_box_shadow_bottom(&node_data, node_id, node_state) {
673 s.push_str(&format!(
674 "-azul-box-shadow-bottom: {};",
675 p.get_css_value_fmt()
676 ));
677 }
678 if let Some(p) = self.get_border_top_color(&node_data, node_id, node_state) {
679 s.push_str(&format!("border-top-color: {};", p.get_css_value_fmt()));
680 }
681 if let Some(p) = self.get_border_left_color(&node_data, node_id, node_state) {
682 s.push_str(&format!("border-left-color: {};", p.get_css_value_fmt()));
683 }
684 if let Some(p) = self.get_border_right_color(&node_data, node_id, node_state) {
685 s.push_str(&format!("border-right-color: {};", p.get_css_value_fmt()));
686 }
687 if let Some(p) = self.get_border_bottom_color(&node_data, node_id, node_state) {
688 s.push_str(&format!("border-bottom-color: {};", p.get_css_value_fmt()));
689 }
690 if let Some(p) = self.get_border_top_style(&node_data, node_id, node_state) {
691 s.push_str(&format!("border-top-style: {};", p.get_css_value_fmt()));
692 }
693 if let Some(p) = self.get_border_left_style(&node_data, node_id, node_state) {
694 s.push_str(&format!("border-left-style: {};", p.get_css_value_fmt()));
695 }
696 if let Some(p) = self.get_border_right_style(&node_data, node_id, node_state) {
697 s.push_str(&format!("border-right-style: {};", p.get_css_value_fmt()));
698 }
699 if let Some(p) = self.get_border_bottom_style(&node_data, node_id, node_state) {
700 s.push_str(&format!("border-bottom-style: {};", p.get_css_value_fmt()));
701 }
702 if let Some(p) = self.get_border_top_left_radius(&node_data, node_id, node_state) {
703 s.push_str(&format!(
704 "border-top-left-radius: {};",
705 p.get_css_value_fmt()
706 ));
707 }
708 if let Some(p) = self.get_border_top_right_radius(&node_data, node_id, node_state) {
709 s.push_str(&format!(
710 "border-top-right-radius: {};",
711 p.get_css_value_fmt()
712 ));
713 }
714 if let Some(p) = self.get_border_bottom_left_radius(&node_data, node_id, node_state) {
715 s.push_str(&format!(
716 "border-bottom-left-radius: {};",
717 p.get_css_value_fmt()
718 ));
719 }
720 if let Some(p) = self.get_border_bottom_right_radius(&node_data, node_id, node_state) {
721 s.push_str(&format!(
722 "border-bottom-right-radius: {};",
723 p.get_css_value_fmt()
724 ));
725 }
726 if let Some(p) = self.get_opacity(&node_data, node_id, node_state) {
727 s.push_str(&format!("opacity: {};", p.get_css_value_fmt()));
728 }
729 if let Some(p) = self.get_transform(&node_data, node_id, node_state) {
730 s.push_str(&format!("transform: {};", p.get_css_value_fmt()));
731 }
732 if let Some(p) = self.get_transform_origin(&node_data, node_id, node_state) {
733 s.push_str(&format!("transform-origin: {};", p.get_css_value_fmt()));
734 }
735 if let Some(p) = self.get_perspective_origin(&node_data, node_id, node_state) {
736 s.push_str(&format!("perspective-origin: {};", p.get_css_value_fmt()));
737 }
738 if let Some(p) = self.get_backface_visibility(&node_data, node_id, node_state) {
739 s.push_str(&format!("backface-visibility: {};", p.get_css_value_fmt()));
740 }
741 if let Some(p) = self.get_display(&node_data, node_id, node_state) {
742 s.push_str(&format!("display: {};", p.get_css_value_fmt()));
743 }
744 if let Some(p) = self.get_float(&node_data, node_id, node_state) {
745 s.push_str(&format!("float: {};", p.get_css_value_fmt()));
746 }
747 if let Some(p) = self.get_box_sizing(&node_data, node_id, node_state) {
748 s.push_str(&format!("box-sizing: {};", p.get_css_value_fmt()));
749 }
750 if let Some(p) = self.get_width(&node_data, node_id, node_state) {
751 s.push_str(&format!("width: {};", p.get_css_value_fmt()));
752 }
753 if let Some(p) = self.get_height(&node_data, node_id, node_state) {
754 s.push_str(&format!("height: {};", p.get_css_value_fmt()));
755 }
756 if let Some(p) = self.get_min_width(&node_data, node_id, node_state) {
757 s.push_str(&format!("min-width: {};", p.get_css_value_fmt()));
758 }
759 if let Some(p) = self.get_min_height(&node_data, node_id, node_state) {
760 s.push_str(&format!("min-height: {};", p.get_css_value_fmt()));
761 }
762 if let Some(p) = self.get_max_width(&node_data, node_id, node_state) {
763 s.push_str(&format!("max-width: {};", p.get_css_value_fmt()));
764 }
765 if let Some(p) = self.get_max_height(&node_data, node_id, node_state) {
766 s.push_str(&format!("max-height: {};", p.get_css_value_fmt()));
767 }
768 if let Some(p) = self.get_position(&node_data, node_id, node_state) {
769 s.push_str(&format!("position: {};", p.get_css_value_fmt()));
770 }
771 if let Some(p) = self.get_top(&node_data, node_id, node_state) {
772 s.push_str(&format!("top: {};", p.get_css_value_fmt()));
773 }
774 if let Some(p) = self.get_bottom(&node_data, node_id, node_state) {
775 s.push_str(&format!("bottom: {};", p.get_css_value_fmt()));
776 }
777 if let Some(p) = self.get_right(&node_data, node_id, node_state) {
778 s.push_str(&format!("right: {};", p.get_css_value_fmt()));
779 }
780 if let Some(p) = self.get_left(&node_data, node_id, node_state) {
781 s.push_str(&format!("left: {};", p.get_css_value_fmt()));
782 }
783 if let Some(p) = self.get_padding_top(&node_data, node_id, node_state) {
784 s.push_str(&format!("padding-top: {};", p.get_css_value_fmt()));
785 }
786 if let Some(p) = self.get_padding_bottom(&node_data, node_id, node_state) {
787 s.push_str(&format!("padding-bottom: {};", p.get_css_value_fmt()));
788 }
789 if let Some(p) = self.get_padding_left(&node_data, node_id, node_state) {
790 s.push_str(&format!("padding-left: {};", p.get_css_value_fmt()));
791 }
792 if let Some(p) = self.get_padding_right(&node_data, node_id, node_state) {
793 s.push_str(&format!("padding-right: {};", p.get_css_value_fmt()));
794 }
795 if let Some(p) = self.get_margin_top(&node_data, node_id, node_state) {
796 s.push_str(&format!("margin-top: {};", p.get_css_value_fmt()));
797 }
798 if let Some(p) = self.get_margin_bottom(&node_data, node_id, node_state) {
799 s.push_str(&format!("margin-bottom: {};", p.get_css_value_fmt()));
800 }
801 if let Some(p) = self.get_margin_left(&node_data, node_id, node_state) {
802 s.push_str(&format!("margin-left: {};", p.get_css_value_fmt()));
803 }
804 if let Some(p) = self.get_margin_right(&node_data, node_id, node_state) {
805 s.push_str(&format!("margin-right: {};", p.get_css_value_fmt()));
806 }
807 if let Some(p) = self.get_border_top_width(&node_data, node_id, node_state) {
808 s.push_str(&format!("border-top-width: {};", p.get_css_value_fmt()));
809 }
810 if let Some(p) = self.get_border_left_width(&node_data, node_id, node_state) {
811 s.push_str(&format!("border-left-width: {};", p.get_css_value_fmt()));
812 }
813 if let Some(p) = self.get_border_right_width(&node_data, node_id, node_state) {
814 s.push_str(&format!("border-right-width: {};", p.get_css_value_fmt()));
815 }
816 if let Some(p) = self.get_border_bottom_width(&node_data, node_id, node_state) {
817 s.push_str(&format!("border-bottom-width: {};", p.get_css_value_fmt()));
818 }
819 if let Some(p) = self.get_overflow_x(&node_data, node_id, node_state) {
820 s.push_str(&format!("overflow-x: {};", p.get_css_value_fmt()));
821 }
822 if let Some(p) = self.get_overflow_y(&node_data, node_id, node_state) {
823 s.push_str(&format!("overflow-y: {};", p.get_css_value_fmt()));
824 }
825 if let Some(p) = self.get_flex_direction(&node_data, node_id, node_state) {
826 s.push_str(&format!("flex-direction: {};", p.get_css_value_fmt()));
827 }
828 if let Some(p) = self.get_flex_wrap(&node_data, node_id, node_state) {
829 s.push_str(&format!("flex-wrap: {};", p.get_css_value_fmt()));
830 }
831 if let Some(p) = self.get_flex_grow(&node_data, node_id, node_state) {
832 s.push_str(&format!("flex-grow: {};", p.get_css_value_fmt()));
833 }
834 if let Some(p) = self.get_flex_shrink(&node_data, node_id, node_state) {
835 s.push_str(&format!("flex-shrink: {};", p.get_css_value_fmt()));
836 }
837 if let Some(p) = self.get_justify_content(&node_data, node_id, node_state) {
838 s.push_str(&format!("justify-content: {};", p.get_css_value_fmt()));
839 }
840 if let Some(p) = self.get_align_items(&node_data, node_id, node_state) {
841 s.push_str(&format!("align-items: {};", p.get_css_value_fmt()));
842 }
843 if let Some(p) = self.get_align_content(&node_data, node_id, node_state) {
844 s.push_str(&format!("align-content: {};", p.get_css_value_fmt()));
845 }
846 s
847 }
848}
849
850#[derive(Copy, Clone, Hash, PartialEq, Eq, Ord, PartialOrd)]
852pub struct StyleFontFamilyHash(pub u64);
853
854impl ::core::fmt::Debug for StyleFontFamilyHash {
855 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
856 write!(f, "StyleFontFamilyHash({})", self.0)
857 }
858}
859
860impl StyleFontFamilyHash {
861 pub(crate) fn new(family: &StyleFontFamily) -> Self {
862 use highway::{HighwayHash, HighwayHasher, Key};
863 let mut hasher = HighwayHasher::new(Key([0; 4]));
864 family.hash(&mut hasher);
865 Self(hasher.finalize64())
866 }
867}
868
869#[derive(Copy, Clone, Hash, PartialEq, Eq, Ord, PartialOrd)]
871pub struct StyleFontFamiliesHash(pub u64);
872
873impl ::core::fmt::Debug for StyleFontFamiliesHash {
874 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
875 write!(f, "StyleFontFamiliesHash({})", self.0)
876 }
877}
878
879impl StyleFontFamiliesHash {
880 pub fn new(families: &[StyleFontFamily]) -> Self {
881 use highway::{HighwayHash, HighwayHasher, Key};
882 let mut hasher = HighwayHasher::new(Key([0; 4]));
883 for f in families.iter() {
884 f.hash(&mut hasher);
885 }
886 Self(hasher.finalize64())
887 }
888}
889
890impl CssPropertyCache {
891 pub fn empty(node_count: usize) -> Self {
892 Self {
893 node_count,
894 user_overridden_properties: BTreeMap::new(),
895
896 cascaded_normal_props: BTreeMap::new(),
897 cascaded_hover_props: BTreeMap::new(),
898 cascaded_active_props: BTreeMap::new(),
899 cascaded_focus_props: BTreeMap::new(),
900
901 css_normal_props: BTreeMap::new(),
902 css_hover_props: BTreeMap::new(),
903 css_active_props: BTreeMap::new(),
904 css_focus_props: BTreeMap::new(),
905 }
906 }
907
908 pub fn append(&mut self, other: &mut Self) {
909 macro_rules! append_css_property_vec {
910 ($field_name:ident) => {{
911 let mut s = BTreeMap::new();
912 core::mem::swap(&mut s, &mut other.$field_name);
913 for (node_id, property_map) in s.into_iter() {
914 self.$field_name
915 .insert(node_id + self.node_count, property_map);
916 }
917 }};
918 }
919
920 append_css_property_vec!(user_overridden_properties);
921 append_css_property_vec!(cascaded_normal_props);
922 append_css_property_vec!(cascaded_hover_props);
923 append_css_property_vec!(cascaded_active_props);
924 append_css_property_vec!(cascaded_focus_props);
925 append_css_property_vec!(css_normal_props);
926 append_css_property_vec!(css_hover_props);
927 append_css_property_vec!(css_active_props);
928 append_css_property_vec!(css_focus_props);
929
930 self.node_count += other.node_count;
931 }
932
933 pub fn is_horizontal_overflow_visible(
934 &self,
935 node_data: &NodeData,
936 node_id: &NodeId,
937 node_state: &StyledNodeState,
938 ) -> bool {
939 self.get_overflow_x(node_data, node_id, node_state)
940 .and_then(|p| p.get_property_or_default())
941 .unwrap_or_default()
942 .is_overflow_visible()
943 }
944
945 pub fn is_vertical_overflow_visible(
946 &self,
947 node_data: &NodeData,
948 node_id: &NodeId,
949 node_state: &StyledNodeState,
950 ) -> bool {
951 self.get_overflow_y(node_data, node_id, node_state)
952 .and_then(|p| p.get_property_or_default())
953 .unwrap_or_default()
954 .is_overflow_visible()
955 }
956
957 pub fn is_horizontal_overflow_hidden(
958 &self,
959 node_data: &NodeData,
960 node_id: &NodeId,
961 node_state: &StyledNodeState,
962 ) -> bool {
963 self.get_overflow_x(node_data, node_id, node_state)
964 .and_then(|p| p.get_property_or_default())
965 .unwrap_or_default()
966 .is_overflow_hidden()
967 }
968
969 pub fn is_vertical_overflow_hidden(
970 &self,
971 node_data: &NodeData,
972 node_id: &NodeId,
973 node_state: &StyledNodeState,
974 ) -> bool {
975 self.get_overflow_y(node_data, node_id, node_state)
976 .and_then(|p| p.get_property_or_default())
977 .unwrap_or_default()
978 .is_overflow_hidden()
979 }
980
981 pub fn get_text_color_or_default(
982 &self,
983 node_data: &NodeData,
984 node_id: &NodeId,
985 node_state: &StyledNodeState,
986 ) -> StyleTextColor {
987 use crate::ui_solver::DEFAULT_TEXT_COLOR;
988 self.get_text_color(node_data, node_id, node_state)
989 .and_then(|fs| fs.get_property().cloned())
990 .unwrap_or(DEFAULT_TEXT_COLOR)
991 }
992
993 pub fn get_font_id_or_default(
995 &self,
996 node_data: &NodeData,
997 node_id: &NodeId,
998 node_state: &StyledNodeState,
999 ) -> StyleFontFamilyVec {
1000 use crate::ui_solver::DEFAULT_FONT_ID;
1001 let default_font_id = vec![StyleFontFamily::System(AzString::from_const_str(
1002 DEFAULT_FONT_ID,
1003 ))]
1004 .into();
1005 let font_family_opt = self.get_font_family(node_data, node_id, node_state);
1006
1007 font_family_opt
1008 .as_ref()
1009 .and_then(|family| Some(family.get_property()?.clone()))
1010 .unwrap_or(default_font_id)
1011 }
1012
1013 pub fn get_font_size_or_default(
1014 &self,
1015 node_data: &NodeData,
1016 node_id: &NodeId,
1017 node_state: &StyledNodeState,
1018 ) -> StyleFontSize {
1019 use crate::ui_solver::DEFAULT_FONT_SIZE;
1020 self.get_font_size(node_data, node_id, node_state)
1021 .and_then(|fs| fs.get_property().cloned())
1022 .unwrap_or(DEFAULT_FONT_SIZE)
1023 }
1024
1025 pub fn has_border(
1026 &self,
1027 node_data: &NodeData,
1028 node_id: &NodeId,
1029 node_state: &StyledNodeState,
1030 ) -> bool {
1031 self.get_border_left_width(node_data, node_id, node_state)
1032 .is_some()
1033 || self
1034 .get_border_right_width(node_data, node_id, node_state)
1035 .is_some()
1036 || self
1037 .get_border_top_width(node_data, node_id, node_state)
1038 .is_some()
1039 || self
1040 .get_border_bottom_width(node_data, node_id, node_state)
1041 .is_some()
1042 }
1043
1044 pub fn has_box_shadow(
1045 &self,
1046 node_data: &NodeData,
1047 node_id: &NodeId,
1048 node_state: &StyledNodeState,
1049 ) -> bool {
1050 self.get_box_shadow_left(node_data, node_id, node_state)
1051 .is_some()
1052 || self
1053 .get_box_shadow_right(node_data, node_id, node_state)
1054 .is_some()
1055 || self
1056 .get_box_shadow_top(node_data, node_id, node_state)
1057 .is_some()
1058 || self
1059 .get_box_shadow_bottom(node_data, node_id, node_state)
1060 .is_some()
1061 }
1062
1063 pub fn get_property<'a>(
1064 &'a self,
1065 node_data: &'a NodeData,
1066 node_id: &NodeId,
1067 node_state: &StyledNodeState,
1068 css_property_type: &CssPropertyType,
1069 ) -> Option<&CssProperty> {
1070 if let Some(p) = self
1075 .user_overridden_properties
1076 .get(node_id)
1077 .and_then(|n| n.get(css_property_type))
1078 {
1079 return Some(p);
1080 }
1081
1082 if !(node_state.normal || node_state.active || node_state.hover || node_state.focused) {
1083 return None;
1084 }
1085
1086 if node_state.focused {
1089 if let Some(p) = self
1090 .css_focus_props
1091 .get(node_id)
1092 .and_then(|map| map.get(css_property_type))
1093 {
1094 return Some(p);
1095 }
1096
1097 if let Some(p) = node_data
1098 .inline_css_props
1099 .as_ref()
1100 .iter()
1101 .find_map(|css_prop| {
1102 if let NodeDataInlineCssProperty::Focus(p) = css_prop {
1103 if p.get_type() == *css_property_type {
1104 return Some(p);
1105 }
1106 }
1107 None
1108 })
1109 {
1110 return Some(p);
1111 }
1112
1113 if let Some(p) = self
1114 .cascaded_focus_props
1115 .get(node_id)
1116 .and_then(|map| map.get(css_property_type))
1117 {
1118 return Some(p);
1119 }
1120 }
1121
1122 if node_state.active {
1123 if let Some(p) = self
1124 .css_active_props
1125 .get(node_id)
1126 .and_then(|map| map.get(css_property_type))
1127 {
1128 return Some(p);
1129 }
1130
1131 if let Some(p) = node_data
1132 .inline_css_props
1133 .as_ref()
1134 .iter()
1135 .find_map(|css_prop| {
1136 if let NodeDataInlineCssProperty::Active(p) = css_prop {
1137 if p.get_type() == *css_property_type {
1138 return Some(p);
1139 }
1140 }
1141 None
1142 })
1143 {
1144 return Some(p);
1145 }
1146
1147 if let Some(p) = self
1148 .cascaded_active_props
1149 .get(node_id)
1150 .and_then(|map| map.get(css_property_type))
1151 {
1152 return Some(p);
1153 }
1154 }
1155
1156 if node_state.hover {
1157 if let Some(p) = self
1158 .css_hover_props
1159 .get(node_id)
1160 .and_then(|map| map.get(css_property_type))
1161 {
1162 return Some(p);
1163 }
1164
1165 if let Some(p) = node_data
1166 .inline_css_props
1167 .as_ref()
1168 .iter()
1169 .find_map(|css_prop| {
1170 if let NodeDataInlineCssProperty::Hover(p) = css_prop {
1171 if p.get_type() == *css_property_type {
1172 return Some(p);
1173 }
1174 }
1175 None
1176 })
1177 {
1178 return Some(p);
1179 }
1180
1181 if let Some(p) = self
1182 .cascaded_hover_props
1183 .get(node_id)
1184 .and_then(|map| map.get(css_property_type))
1185 {
1186 return Some(p);
1187 }
1188 }
1189
1190 if node_state.normal {
1191 if let Some(p) = self
1192 .css_normal_props
1193 .get(node_id)
1194 .and_then(|map| map.get(css_property_type))
1195 {
1196 return Some(p);
1197 }
1198
1199 if let Some(p) = node_data
1200 .inline_css_props
1201 .as_ref()
1202 .iter()
1203 .find_map(|css_prop| {
1204 if let NodeDataInlineCssProperty::Normal(p) = css_prop {
1205 if p.get_type() == *css_property_type {
1206 return Some(p);
1207 }
1208 }
1209 None
1210 })
1211 {
1212 return Some(p);
1213 }
1214
1215 if let Some(p) = self
1216 .cascaded_normal_props
1217 .get(node_id)
1218 .and_then(|map| map.get(css_property_type))
1219 {
1220 return Some(p);
1221 }
1222 }
1223
1224 None
1226 }
1227
1228 pub fn get_background_content<'a>(
1229 &'a self,
1230 node_data: &'a NodeData,
1231 node_id: &NodeId,
1232 node_state: &StyledNodeState,
1233 ) -> Option<&'a StyleBackgroundContentVecValue> {
1234 self.get_property(
1235 node_data,
1236 node_id,
1237 node_state,
1238 &CssPropertyType::BackgroundContent,
1239 )
1240 .and_then(|p| p.as_background_content())
1241 }
1242 pub fn get_background_position<'a>(
1243 &'a self,
1244 node_data: &'a NodeData,
1245 node_id: &NodeId,
1246 node_state: &StyledNodeState,
1247 ) -> Option<&'a StyleBackgroundPositionVecValue> {
1248 self.get_property(
1249 node_data,
1250 node_id,
1251 node_state,
1252 &CssPropertyType::BackgroundPosition,
1253 )
1254 .and_then(|p| p.as_background_position())
1255 }
1256 pub fn get_background_size<'a>(
1257 &'a self,
1258 node_data: &'a NodeData,
1259 node_id: &NodeId,
1260 node_state: &StyledNodeState,
1261 ) -> Option<&'a StyleBackgroundSizeVecValue> {
1262 self.get_property(
1263 node_data,
1264 node_id,
1265 node_state,
1266 &CssPropertyType::BackgroundSize,
1267 )
1268 .and_then(|p| p.as_background_size())
1269 }
1270 pub fn get_background_repeat<'a>(
1271 &'a self,
1272 node_data: &'a NodeData,
1273 node_id: &NodeId,
1274 node_state: &StyledNodeState,
1275 ) -> Option<&'a StyleBackgroundRepeatVecValue> {
1276 self.get_property(
1277 node_data,
1278 node_id,
1279 node_state,
1280 &CssPropertyType::BackgroundRepeat,
1281 )
1282 .and_then(|p| p.as_background_repeat())
1283 }
1284 pub fn get_font_size<'a>(
1285 &'a self,
1286 node_data: &'a NodeData,
1287 node_id: &NodeId,
1288 node_state: &StyledNodeState,
1289 ) -> Option<&'a StyleFontSizeValue> {
1290 self.get_property(node_data, node_id, node_state, &CssPropertyType::FontSize)
1291 .and_then(|p| p.as_font_size())
1292 }
1293 pub fn get_font_family<'a>(
1294 &'a self,
1295 node_data: &'a NodeData,
1296 node_id: &NodeId,
1297 node_state: &StyledNodeState,
1298 ) -> Option<&'a StyleFontFamilyVecValue> {
1299 self.get_property(node_data, node_id, node_state, &CssPropertyType::FontFamily)
1300 .and_then(|p| p.as_font_family())
1301 }
1302 pub fn get_text_color<'a>(
1303 &'a self,
1304 node_data: &'a NodeData,
1305 node_id: &NodeId,
1306 node_state: &StyledNodeState,
1307 ) -> Option<&'a StyleTextColorValue> {
1308 self.get_property(node_data, node_id, node_state, &CssPropertyType::TextColor)
1309 .and_then(|p| p.as_text_color())
1310 }
1311 pub fn get_text_align<'a>(
1312 &'a self,
1313 node_data: &'a NodeData,
1314 node_id: &NodeId,
1315 node_state: &StyledNodeState,
1316 ) -> Option<&'a StyleTextAlignValue> {
1317 self.get_property(node_data, node_id, node_state, &CssPropertyType::TextAlign)
1318 .and_then(|p| p.as_text_align())
1319 }
1320 pub fn get_line_height<'a>(
1321 &'a self,
1322 node_data: &'a NodeData,
1323 node_id: &NodeId,
1324 node_state: &StyledNodeState,
1325 ) -> Option<&'a StyleLineHeightValue> {
1326 self.get_property(node_data, node_id, node_state, &CssPropertyType::LineHeight)
1327 .and_then(|p| p.as_line_height())
1328 }
1329 pub fn get_letter_spacing<'a>(
1330 &'a self,
1331 node_data: &'a NodeData,
1332 node_id: &NodeId,
1333 node_state: &StyledNodeState,
1334 ) -> Option<&'a StyleLetterSpacingValue> {
1335 self.get_property(
1336 node_data,
1337 node_id,
1338 node_state,
1339 &CssPropertyType::LetterSpacing,
1340 )
1341 .and_then(|p| p.as_letter_spacing())
1342 }
1343 pub fn get_word_spacing<'a>(
1344 &'a self,
1345 node_data: &'a NodeData,
1346 node_id: &NodeId,
1347 node_state: &StyledNodeState,
1348 ) -> Option<&'a StyleWordSpacingValue> {
1349 self.get_property(
1350 node_data,
1351 node_id,
1352 node_state,
1353 &CssPropertyType::WordSpacing,
1354 )
1355 .and_then(|p| p.as_word_spacing())
1356 }
1357 pub fn get_tab_width<'a>(
1358 &'a self,
1359 node_data: &'a NodeData,
1360 node_id: &NodeId,
1361 node_state: &StyledNodeState,
1362 ) -> Option<&'a StyleTabWidthValue> {
1363 self.get_property(node_data, node_id, node_state, &CssPropertyType::TabWidth)
1364 .and_then(|p| p.as_tab_width())
1365 }
1366 pub fn get_cursor<'a>(
1367 &'a self,
1368 node_data: &'a NodeData,
1369 node_id: &NodeId,
1370 node_state: &StyledNodeState,
1371 ) -> Option<&'a StyleCursorValue> {
1372 self.get_property(node_data, node_id, node_state, &CssPropertyType::Cursor)
1373 .and_then(|p| p.as_cursor())
1374 }
1375 pub fn get_box_shadow_left<'a>(
1376 &'a self,
1377 node_data: &'a NodeData,
1378 node_id: &NodeId,
1379 node_state: &StyledNodeState,
1380 ) -> Option<&'a StyleBoxShadowValue> {
1381 self.get_property(
1382 node_data,
1383 node_id,
1384 node_state,
1385 &CssPropertyType::BoxShadowLeft,
1386 )
1387 .and_then(|p| p.as_box_shadow_left())
1388 }
1389 pub fn get_box_shadow_right<'a>(
1390 &'a self,
1391 node_data: &'a NodeData,
1392 node_id: &NodeId,
1393 node_state: &StyledNodeState,
1394 ) -> Option<&'a StyleBoxShadowValue> {
1395 self.get_property(
1396 node_data,
1397 node_id,
1398 node_state,
1399 &CssPropertyType::BoxShadowRight,
1400 )
1401 .and_then(|p| p.as_box_shadow_right())
1402 }
1403 pub fn get_box_shadow_top<'a>(
1404 &'a self,
1405 node_data: &'a NodeData,
1406 node_id: &NodeId,
1407 node_state: &StyledNodeState,
1408 ) -> Option<&'a StyleBoxShadowValue> {
1409 self.get_property(
1410 node_data,
1411 node_id,
1412 node_state,
1413 &CssPropertyType::BoxShadowTop,
1414 )
1415 .and_then(|p| p.as_box_shadow_top())
1416 }
1417 pub fn get_box_shadow_bottom<'a>(
1418 &'a self,
1419 node_data: &'a NodeData,
1420 node_id: &NodeId,
1421 node_state: &StyledNodeState,
1422 ) -> Option<&'a StyleBoxShadowValue> {
1423 self.get_property(
1424 node_data,
1425 node_id,
1426 node_state,
1427 &CssPropertyType::BoxShadowBottom,
1428 )
1429 .and_then(|p| p.as_box_shadow_bottom())
1430 }
1431 pub fn get_border_top_color<'a>(
1432 &'a self,
1433 node_data: &'a NodeData,
1434 node_id: &NodeId,
1435 node_state: &StyledNodeState,
1436 ) -> Option<&'a StyleBorderTopColorValue> {
1437 self.get_property(
1438 node_data,
1439 node_id,
1440 node_state,
1441 &CssPropertyType::BorderTopColor,
1442 )
1443 .and_then(|p| p.as_border_top_color())
1444 }
1445 pub fn get_border_left_color<'a>(
1446 &'a self,
1447 node_data: &'a NodeData,
1448 node_id: &NodeId,
1449 node_state: &StyledNodeState,
1450 ) -> Option<&'a StyleBorderLeftColorValue> {
1451 self.get_property(
1452 node_data,
1453 node_id,
1454 node_state,
1455 &CssPropertyType::BorderLeftColor,
1456 )
1457 .and_then(|p| p.as_border_left_color())
1458 }
1459 pub fn get_border_right_color<'a>(
1460 &'a self,
1461 node_data: &'a NodeData,
1462 node_id: &NodeId,
1463 node_state: &StyledNodeState,
1464 ) -> Option<&'a StyleBorderRightColorValue> {
1465 self.get_property(
1466 node_data,
1467 node_id,
1468 node_state,
1469 &CssPropertyType::BorderRightColor,
1470 )
1471 .and_then(|p| p.as_border_right_color())
1472 }
1473 pub fn get_border_bottom_color<'a>(
1474 &'a self,
1475 node_data: &'a NodeData,
1476 node_id: &NodeId,
1477 node_state: &StyledNodeState,
1478 ) -> Option<&'a StyleBorderBottomColorValue> {
1479 self.get_property(
1480 node_data,
1481 node_id,
1482 node_state,
1483 &CssPropertyType::BorderBottomColor,
1484 )
1485 .and_then(|p| p.as_border_bottom_color())
1486 }
1487 pub fn get_border_top_style<'a>(
1488 &'a self,
1489 node_data: &'a NodeData,
1490 node_id: &NodeId,
1491 node_state: &StyledNodeState,
1492 ) -> Option<&'a StyleBorderTopStyleValue> {
1493 self.get_property(
1494 node_data,
1495 node_id,
1496 node_state,
1497 &CssPropertyType::BorderTopStyle,
1498 )
1499 .and_then(|p| p.as_border_top_style())
1500 }
1501 pub fn get_border_left_style<'a>(
1502 &'a self,
1503 node_data: &'a NodeData,
1504 node_id: &NodeId,
1505 node_state: &StyledNodeState,
1506 ) -> Option<&'a StyleBorderLeftStyleValue> {
1507 self.get_property(
1508 node_data,
1509 node_id,
1510 node_state,
1511 &CssPropertyType::BorderLeftStyle,
1512 )
1513 .and_then(|p| p.as_border_left_style())
1514 }
1515 pub fn get_border_right_style<'a>(
1516 &'a self,
1517 node_data: &'a NodeData,
1518 node_id: &NodeId,
1519 node_state: &StyledNodeState,
1520 ) -> Option<&'a StyleBorderRightStyleValue> {
1521 self.get_property(
1522 node_data,
1523 node_id,
1524 node_state,
1525 &CssPropertyType::BorderRightStyle,
1526 )
1527 .and_then(|p| p.as_border_right_style())
1528 }
1529 pub fn get_border_bottom_style<'a>(
1530 &'a self,
1531 node_data: &'a NodeData,
1532 node_id: &NodeId,
1533 node_state: &StyledNodeState,
1534 ) -> Option<&'a StyleBorderBottomStyleValue> {
1535 self.get_property(
1536 node_data,
1537 node_id,
1538 node_state,
1539 &CssPropertyType::BorderBottomStyle,
1540 )
1541 .and_then(|p| p.as_border_bottom_style())
1542 }
1543 pub fn get_border_top_left_radius<'a>(
1544 &'a self,
1545 node_data: &'a NodeData,
1546 node_id: &NodeId,
1547 node_state: &StyledNodeState,
1548 ) -> Option<&'a StyleBorderTopLeftRadiusValue> {
1549 self.get_property(
1550 node_data,
1551 node_id,
1552 node_state,
1553 &CssPropertyType::BorderTopLeftRadius,
1554 )
1555 .and_then(|p| p.as_border_top_left_radius())
1556 }
1557 pub fn get_border_top_right_radius<'a>(
1558 &'a self,
1559 node_data: &'a NodeData,
1560 node_id: &NodeId,
1561 node_state: &StyledNodeState,
1562 ) -> Option<&'a StyleBorderTopRightRadiusValue> {
1563 self.get_property(
1564 node_data,
1565 node_id,
1566 node_state,
1567 &CssPropertyType::BorderTopRightRadius,
1568 )
1569 .and_then(|p| p.as_border_top_right_radius())
1570 }
1571 pub fn get_border_bottom_left_radius<'a>(
1572 &'a self,
1573 node_data: &'a NodeData,
1574 node_id: &NodeId,
1575 node_state: &StyledNodeState,
1576 ) -> Option<&'a StyleBorderBottomLeftRadiusValue> {
1577 self.get_property(
1578 node_data,
1579 node_id,
1580 node_state,
1581 &CssPropertyType::BorderBottomLeftRadius,
1582 )
1583 .and_then(|p| p.as_border_bottom_left_radius())
1584 }
1585 pub fn get_border_bottom_right_radius<'a>(
1586 &'a self,
1587 node_data: &'a NodeData,
1588 node_id: &NodeId,
1589 node_state: &StyledNodeState,
1590 ) -> Option<&'a StyleBorderBottomRightRadiusValue> {
1591 self.get_property(
1592 node_data,
1593 node_id,
1594 node_state,
1595 &CssPropertyType::BorderBottomRightRadius,
1596 )
1597 .and_then(|p| p.as_border_bottom_right_radius())
1598 }
1599 pub fn get_opacity<'a>(
1600 &'a self,
1601 node_data: &'a NodeData,
1602 node_id: &NodeId,
1603 node_state: &StyledNodeState,
1604 ) -> Option<&'a StyleOpacityValue> {
1605 self.get_property(node_data, node_id, node_state, &CssPropertyType::Opacity)
1606 .and_then(|p| p.as_opacity())
1607 }
1608 pub fn get_transform<'a>(
1609 &'a self,
1610 node_data: &'a NodeData,
1611 node_id: &NodeId,
1612 node_state: &StyledNodeState,
1613 ) -> Option<&'a StyleTransformVecValue> {
1614 self.get_property(node_data, node_id, node_state, &CssPropertyType::Transform)
1615 .and_then(|p| p.as_transform())
1616 }
1617 pub fn get_transform_origin<'a>(
1618 &'a self,
1619 node_data: &'a NodeData,
1620 node_id: &NodeId,
1621 node_state: &StyledNodeState,
1622 ) -> Option<&'a StyleTransformOriginValue> {
1623 self.get_property(
1624 node_data,
1625 node_id,
1626 node_state,
1627 &CssPropertyType::TransformOrigin,
1628 )
1629 .and_then(|p| p.as_transform_origin())
1630 }
1631 pub fn get_perspective_origin<'a>(
1632 &'a self,
1633 node_data: &'a NodeData,
1634 node_id: &NodeId,
1635 node_state: &StyledNodeState,
1636 ) -> Option<&'a StylePerspectiveOriginValue> {
1637 self.get_property(
1638 node_data,
1639 node_id,
1640 node_state,
1641 &CssPropertyType::PerspectiveOrigin,
1642 )
1643 .and_then(|p| p.as_perspective_origin())
1644 }
1645 pub fn get_backface_visibility<'a>(
1646 &'a self,
1647 node_data: &'a NodeData,
1648 node_id: &NodeId,
1649 node_state: &StyledNodeState,
1650 ) -> Option<&'a StyleBackfaceVisibilityValue> {
1651 self.get_property(
1652 node_data,
1653 node_id,
1654 node_state,
1655 &CssPropertyType::BackfaceVisibility,
1656 )
1657 .and_then(|p| p.as_backface_visibility())
1658 }
1659 pub fn get_display<'a>(
1660 &'a self,
1661 node_data: &'a NodeData,
1662 node_id: &NodeId,
1663 node_state: &StyledNodeState,
1664 ) -> Option<&'a LayoutDisplayValue> {
1665 self.get_property(node_data, node_id, node_state, &CssPropertyType::Display)
1666 .and_then(|p| p.as_display())
1667 }
1668 pub fn get_float<'a>(
1669 &'a self,
1670 node_data: &'a NodeData,
1671 node_id: &NodeId,
1672 node_state: &StyledNodeState,
1673 ) -> Option<&'a LayoutFloatValue> {
1674 self.get_property(node_data, node_id, node_state, &CssPropertyType::Float)
1675 .and_then(|p| p.as_float())
1676 }
1677 pub fn get_box_sizing<'a>(
1678 &'a self,
1679 node_data: &'a NodeData,
1680 node_id: &NodeId,
1681 node_state: &StyledNodeState,
1682 ) -> Option<&'a LayoutBoxSizingValue> {
1683 self.get_property(node_data, node_id, node_state, &CssPropertyType::BoxSizing)
1684 .and_then(|p| p.as_box_sizing())
1685 }
1686 pub fn get_width<'a>(
1687 &'a self,
1688 node_data: &'a NodeData,
1689 node_id: &NodeId,
1690 node_state: &StyledNodeState,
1691 ) -> Option<&'a LayoutWidthValue> {
1692 self.get_property(node_data, node_id, node_state, &CssPropertyType::Width)
1693 .and_then(|p| p.as_width())
1694 }
1695 pub fn get_height<'a>(
1696 &'a self,
1697 node_data: &'a NodeData,
1698 node_id: &NodeId,
1699 node_state: &StyledNodeState,
1700 ) -> Option<&'a LayoutHeightValue> {
1701 self.get_property(node_data, node_id, node_state, &CssPropertyType::Height)
1702 .and_then(|p| p.as_height())
1703 }
1704 pub fn get_min_width<'a>(
1705 &'a self,
1706 node_data: &'a NodeData,
1707 node_id: &NodeId,
1708 node_state: &StyledNodeState,
1709 ) -> Option<&'a LayoutMinWidthValue> {
1710 self.get_property(node_data, node_id, node_state, &CssPropertyType::MinWidth)
1711 .and_then(|p| p.as_min_width())
1712 }
1713 pub fn get_min_height<'a>(
1714 &'a self,
1715 node_data: &'a NodeData,
1716 node_id: &NodeId,
1717 node_state: &StyledNodeState,
1718 ) -> Option<&'a LayoutMinHeightValue> {
1719 self.get_property(node_data, node_id, node_state, &CssPropertyType::MinHeight)
1720 .and_then(|p| p.as_min_height())
1721 }
1722 pub fn get_max_width<'a>(
1723 &'a self,
1724 node_data: &'a NodeData,
1725 node_id: &NodeId,
1726 node_state: &StyledNodeState,
1727 ) -> Option<&'a LayoutMaxWidthValue> {
1728 self.get_property(node_data, node_id, node_state, &CssPropertyType::MaxWidth)
1729 .and_then(|p| p.as_max_width())
1730 }
1731 pub fn get_max_height<'a>(
1732 &'a self,
1733 node_data: &'a NodeData,
1734 node_id: &NodeId,
1735 node_state: &StyledNodeState,
1736 ) -> Option<&'a LayoutMaxHeightValue> {
1737 self.get_property(node_data, node_id, node_state, &CssPropertyType::MaxHeight)
1738 .and_then(|p| p.as_max_height())
1739 }
1740 pub fn get_position<'a>(
1741 &'a self,
1742 node_data: &'a NodeData,
1743 node_id: &NodeId,
1744 node_state: &StyledNodeState,
1745 ) -> Option<&'a LayoutPositionValue> {
1746 self.get_property(node_data, node_id, node_state, &CssPropertyType::Position)
1747 .and_then(|p| p.as_position())
1748 }
1749 pub fn get_top<'a>(
1750 &'a self,
1751 node_data: &'a NodeData,
1752 node_id: &NodeId,
1753 node_state: &StyledNodeState,
1754 ) -> Option<&'a LayoutTopValue> {
1755 self.get_property(node_data, node_id, node_state, &CssPropertyType::Top)
1756 .and_then(|p| p.as_top())
1757 }
1758 pub fn get_bottom<'a>(
1759 &'a self,
1760 node_data: &'a NodeData,
1761 node_id: &NodeId,
1762 node_state: &StyledNodeState,
1763 ) -> Option<&'a LayoutBottomValue> {
1764 self.get_property(node_data, node_id, node_state, &CssPropertyType::Bottom)
1765 .and_then(|p| p.as_bottom())
1766 }
1767 pub fn get_right<'a>(
1768 &'a self,
1769 node_data: &'a NodeData,
1770 node_id: &NodeId,
1771 node_state: &StyledNodeState,
1772 ) -> Option<&'a LayoutRightValue> {
1773 self.get_property(node_data, node_id, node_state, &CssPropertyType::Right)
1774 .and_then(|p| p.as_right())
1775 }
1776 pub fn get_left<'a>(
1777 &'a self,
1778 node_data: &'a NodeData,
1779 node_id: &NodeId,
1780 node_state: &StyledNodeState,
1781 ) -> Option<&'a LayoutLeftValue> {
1782 self.get_property(node_data, node_id, node_state, &CssPropertyType::Left)
1783 .and_then(|p| p.as_left())
1784 }
1785 pub fn get_padding_top<'a>(
1786 &'a self,
1787 node_data: &'a NodeData,
1788 node_id: &NodeId,
1789 node_state: &StyledNodeState,
1790 ) -> Option<&'a LayoutPaddingTopValue> {
1791 self.get_property(node_data, node_id, node_state, &CssPropertyType::PaddingTop)
1792 .and_then(|p| p.as_padding_top())
1793 }
1794 pub fn get_padding_bottom<'a>(
1795 &'a self,
1796 node_data: &'a NodeData,
1797 node_id: &NodeId,
1798 node_state: &StyledNodeState,
1799 ) -> Option<&'a LayoutPaddingBottomValue> {
1800 self.get_property(
1801 node_data,
1802 node_id,
1803 node_state,
1804 &CssPropertyType::PaddingBottom,
1805 )
1806 .and_then(|p| p.as_padding_bottom())
1807 }
1808 pub fn get_padding_left<'a>(
1809 &'a self,
1810 node_data: &'a NodeData,
1811 node_id: &NodeId,
1812 node_state: &StyledNodeState,
1813 ) -> Option<&'a LayoutPaddingLeftValue> {
1814 self.get_property(
1815 node_data,
1816 node_id,
1817 node_state,
1818 &CssPropertyType::PaddingLeft,
1819 )
1820 .and_then(|p| p.as_padding_left())
1821 }
1822 pub fn get_padding_right<'a>(
1823 &'a self,
1824 node_data: &'a NodeData,
1825 node_id: &NodeId,
1826 node_state: &StyledNodeState,
1827 ) -> Option<&'a LayoutPaddingRightValue> {
1828 self.get_property(
1829 node_data,
1830 node_id,
1831 node_state,
1832 &CssPropertyType::PaddingRight,
1833 )
1834 .and_then(|p| p.as_padding_right())
1835 }
1836 pub fn get_margin_top<'a>(
1837 &'a self,
1838 node_data: &'a NodeData,
1839 node_id: &NodeId,
1840 node_state: &StyledNodeState,
1841 ) -> Option<&'a LayoutMarginTopValue> {
1842 self.get_property(node_data, node_id, node_state, &CssPropertyType::MarginTop)
1843 .and_then(|p| p.as_margin_top())
1844 }
1845 pub fn get_margin_bottom<'a>(
1846 &'a self,
1847 node_data: &'a NodeData,
1848 node_id: &NodeId,
1849 node_state: &StyledNodeState,
1850 ) -> Option<&'a LayoutMarginBottomValue> {
1851 self.get_property(
1852 node_data,
1853 node_id,
1854 node_state,
1855 &CssPropertyType::MarginBottom,
1856 )
1857 .and_then(|p| p.as_margin_bottom())
1858 }
1859 pub fn get_margin_left<'a>(
1860 &'a self,
1861 node_data: &'a NodeData,
1862 node_id: &NodeId,
1863 node_state: &StyledNodeState,
1864 ) -> Option<&'a LayoutMarginLeftValue> {
1865 self.get_property(node_data, node_id, node_state, &CssPropertyType::MarginLeft)
1866 .and_then(|p| p.as_margin_left())
1867 }
1868 pub fn get_margin_right<'a>(
1869 &'a self,
1870 node_data: &'a NodeData,
1871 node_id: &NodeId,
1872 node_state: &StyledNodeState,
1873 ) -> Option<&'a LayoutMarginRightValue> {
1874 self.get_property(
1875 node_data,
1876 node_id,
1877 node_state,
1878 &CssPropertyType::MarginRight,
1879 )
1880 .and_then(|p| p.as_margin_right())
1881 }
1882 pub fn get_border_top_width<'a>(
1883 &'a self,
1884 node_data: &'a NodeData,
1885 node_id: &NodeId,
1886 node_state: &StyledNodeState,
1887 ) -> Option<&'a LayoutBorderTopWidthValue> {
1888 self.get_property(
1889 node_data,
1890 node_id,
1891 node_state,
1892 &CssPropertyType::BorderTopWidth,
1893 )
1894 .and_then(|p| p.as_border_top_width())
1895 }
1896 pub fn get_border_left_width<'a>(
1897 &'a self,
1898 node_data: &'a NodeData,
1899 node_id: &NodeId,
1900 node_state: &StyledNodeState,
1901 ) -> Option<&'a LayoutBorderLeftWidthValue> {
1902 self.get_property(
1903 node_data,
1904 node_id,
1905 node_state,
1906 &CssPropertyType::BorderLeftWidth,
1907 )
1908 .and_then(|p| p.as_border_left_width())
1909 }
1910 pub fn get_border_right_width<'a>(
1911 &'a self,
1912 node_data: &'a NodeData,
1913 node_id: &NodeId,
1914 node_state: &StyledNodeState,
1915 ) -> Option<&'a LayoutBorderRightWidthValue> {
1916 self.get_property(
1917 node_data,
1918 node_id,
1919 node_state,
1920 &CssPropertyType::BorderRightWidth,
1921 )
1922 .and_then(|p| p.as_border_right_width())
1923 }
1924 pub fn get_border_bottom_width<'a>(
1925 &'a self,
1926 node_data: &'a NodeData,
1927 node_id: &NodeId,
1928 node_state: &StyledNodeState,
1929 ) -> Option<&'a LayoutBorderBottomWidthValue> {
1930 self.get_property(
1931 node_data,
1932 node_id,
1933 node_state,
1934 &CssPropertyType::BorderBottomWidth,
1935 )
1936 .and_then(|p| p.as_border_bottom_width())
1937 }
1938 pub fn get_overflow_x<'a>(
1939 &'a self,
1940 node_data: &'a NodeData,
1941 node_id: &NodeId,
1942 node_state: &StyledNodeState,
1943 ) -> Option<&'a LayoutOverflowValue> {
1944 self.get_property(node_data, node_id, node_state, &CssPropertyType::OverflowX)
1945 .and_then(|p| p.as_overflow_x())
1946 }
1947 pub fn get_overflow_y<'a>(
1948 &'a self,
1949 node_data: &'a NodeData,
1950 node_id: &NodeId,
1951 node_state: &StyledNodeState,
1952 ) -> Option<&'a LayoutOverflowValue> {
1953 self.get_property(node_data, node_id, node_state, &CssPropertyType::OverflowY)
1954 .and_then(|p| p.as_overflow_y())
1955 }
1956 pub fn get_flex_direction<'a>(
1957 &'a self,
1958 node_data: &'a NodeData,
1959 node_id: &NodeId,
1960 node_state: &StyledNodeState,
1961 ) -> Option<&'a LayoutFlexDirectionValue> {
1962 self.get_property(
1963 node_data,
1964 node_id,
1965 node_state,
1966 &CssPropertyType::FlexDirection,
1967 )
1968 .and_then(|p| p.as_direction())
1969 }
1970 pub fn get_flex_wrap<'a>(
1971 &'a self,
1972 node_data: &'a NodeData,
1973 node_id: &NodeId,
1974 node_state: &StyledNodeState,
1975 ) -> Option<&'a LayoutFlexWrapValue> {
1976 self.get_property(node_data, node_id, node_state, &CssPropertyType::FlexWrap)
1977 .and_then(|p| p.as_flex_wrap())
1978 }
1979 pub fn get_flex_grow<'a>(
1980 &'a self,
1981 node_data: &'a NodeData,
1982 node_id: &NodeId,
1983 node_state: &StyledNodeState,
1984 ) -> Option<&'a LayoutFlexGrowValue> {
1985 self.get_property(node_data, node_id, node_state, &CssPropertyType::FlexGrow)
1986 .and_then(|p| p.as_flex_grow())
1987 }
1988 pub fn get_flex_shrink<'a>(
1989 &'a self,
1990 node_data: &'a NodeData,
1991 node_id: &NodeId,
1992 node_state: &StyledNodeState,
1993 ) -> Option<&'a LayoutFlexShrinkValue> {
1994 self.get_property(node_data, node_id, node_state, &CssPropertyType::FlexShrink)
1995 .and_then(|p| p.as_flex_shrink())
1996 }
1997 pub fn get_justify_content<'a>(
1998 &'a self,
1999 node_data: &'a NodeData,
2000 node_id: &NodeId,
2001 node_state: &StyledNodeState,
2002 ) -> Option<&'a LayoutJustifyContentValue> {
2003 self.get_property(
2004 node_data,
2005 node_id,
2006 node_state,
2007 &CssPropertyType::JustifyContent,
2008 )
2009 .and_then(|p| p.as_justify_content())
2010 }
2011 pub fn get_align_items<'a>(
2012 &'a self,
2013 node_data: &'a NodeData,
2014 node_id: &NodeId,
2015 node_state: &StyledNodeState,
2016 ) -> Option<&'a LayoutAlignItemsValue> {
2017 self.get_property(node_data, node_id, node_state, &CssPropertyType::AlignItems)
2018 .and_then(|p| p.as_align_items())
2019 }
2020 pub fn get_align_content<'a>(
2021 &'a self,
2022 node_data: &'a NodeData,
2023 node_id: &NodeId,
2024 node_state: &StyledNodeState,
2025 ) -> Option<&'a LayoutAlignContentValue> {
2026 self.get_property(
2027 node_data,
2028 node_id,
2029 node_state,
2030 &CssPropertyType::AlignContent,
2031 )
2032 .and_then(|p| p.as_align_content())
2033 }
2034 pub fn get_mix_blend_mode<'a>(
2035 &'a self,
2036 node_data: &'a NodeData,
2037 node_id: &NodeId,
2038 node_state: &StyledNodeState,
2039 ) -> Option<&'a StyleMixBlendModeValue> {
2040 self.get_property(
2041 node_data,
2042 node_id,
2043 node_state,
2044 &CssPropertyType::MixBlendMode,
2045 )
2046 .and_then(|p| p.as_mix_blend_mode())
2047 }
2048 pub fn get_filter<'a>(
2049 &'a self,
2050 node_data: &'a NodeData,
2051 node_id: &NodeId,
2052 node_state: &StyledNodeState,
2053 ) -> Option<&'a StyleFilterVecValue> {
2054 self.get_property(node_data, node_id, node_state, &CssPropertyType::Filter)
2055 .and_then(|p| p.as_filter())
2056 }
2057 pub fn get_backdrop_filter<'a>(
2058 &'a self,
2059 node_data: &'a NodeData,
2060 node_id: &NodeId,
2061 node_state: &StyledNodeState,
2062 ) -> Option<&'a StyleFilterVecValue> {
2063 self.get_property(node_data, node_id, node_state, &CssPropertyType::Filter)
2064 .and_then(|p| p.as_backdrop_filter())
2065 }
2066 pub fn get_text_shadow<'a>(
2067 &'a self,
2068 node_data: &'a NodeData,
2069 node_id: &NodeId,
2070 node_state: &StyledNodeState,
2071 ) -> Option<&'a StyleBoxShadowValue> {
2072 self.get_property(node_data, node_id, node_state, &CssPropertyType::TextShadow)
2073 .and_then(|p| p.as_text_shadow())
2074 }
2075}
2076
2077#[derive(Debug, Copy, Clone, PartialEq, Eq, Ord, PartialOrd, Hash)]
2078#[repr(C)]
2079pub struct DomId {
2080 pub inner: usize,
2081}
2082
2083impl fmt::Display for DomId {
2084 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2085 write!(f, "{}", self.inner)
2086 }
2087}
2088
2089impl DomId {
2090 pub const ROOT_ID: DomId = DomId { inner: 0 };
2091}
2092
2093impl Default for DomId {
2094 fn default() -> DomId {
2095 DomId::ROOT_ID
2096 }
2097}
2098
2099impl_option!(
2100 DomId,
2101 OptionDomId,
2102 [Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash]
2103);
2104
2105#[derive(Copy, Clone, PartialEq, Eq, Ord, PartialOrd, Hash)]
2106#[repr(C)]
2107pub struct NodeHierarchyItemId {
2108 pub inner: usize,
2109}
2110
2111impl fmt::Debug for NodeHierarchyItemId {
2112 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2113 match self.into_crate_internal() {
2114 Some(n) => write!(f, "Some(NodeId({}))", n),
2115 None => write!(f, "None"),
2116 }
2117 }
2118}
2119
2120impl fmt::Display for NodeHierarchyItemId {
2121 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2122 write!(f, "{:?}", self)
2123 }
2124}
2125
2126impl NodeHierarchyItemId {
2127 pub const NONE: NodeHierarchyItemId = NodeHierarchyItemId { inner: 0 };
2128}
2129
2130impl_option!(
2131 NodeHierarchyItemId,
2132 OptionNodeId,
2133 [Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash]
2134);
2135
2136impl_vec!(NodeHierarchyItemId, NodeIdVec, NodeIdVecDestructor);
2137impl_vec_mut!(NodeHierarchyItemId, NodeIdVec);
2138impl_vec_debug!(NodeHierarchyItemId, NodeIdVec);
2139impl_vec_ord!(NodeHierarchyItemId, NodeIdVec);
2140impl_vec_eq!(NodeHierarchyItemId, NodeIdVec);
2141impl_vec_hash!(NodeHierarchyItemId, NodeIdVec);
2142impl_vec_partialord!(NodeHierarchyItemId, NodeIdVec);
2143impl_vec_clone!(NodeHierarchyItemId, NodeIdVec, NodeIdVecDestructor);
2144impl_vec_partialeq!(NodeHierarchyItemId, NodeIdVec);
2145
2146impl NodeHierarchyItemId {
2147 #[inline]
2148 pub const fn into_crate_internal(&self) -> Option<NodeId> {
2149 NodeId::from_usize(self.inner)
2150 }
2151
2152 #[inline]
2153 pub const fn from_crate_internal(t: Option<NodeId>) -> Self {
2154 Self {
2155 inner: NodeId::into_usize(&t),
2156 }
2157 }
2158}
2159
2160#[derive(Debug, Copy, Clone, PartialEq, Eq, Ord, PartialOrd, Hash)]
2161#[repr(C)]
2162pub struct AzTagId {
2163 pub inner: u64,
2164}
2165
2166impl_option!(
2167 AzTagId,
2168 OptionTagId,
2169 [Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash]
2170);
2171
2172impl AzTagId {
2173 pub const fn into_crate_internal(&self) -> TagId {
2174 TagId(self.inner)
2175 }
2176 pub const fn from_crate_internal(t: TagId) -> Self {
2177 AzTagId { inner: t.0 }
2178 }
2179}
2180
2181#[derive(Debug, Copy, Clone, PartialEq, Eq, Ord, PartialOrd, Hash)]
2182#[repr(C)]
2183pub struct NodeHierarchyItem {
2184 pub parent: usize,
2185 pub previous_sibling: usize,
2186 pub next_sibling: usize,
2187 pub last_child: usize,
2188}
2189
2190impl NodeHierarchyItem {
2191 pub const fn zeroed() -> Self {
2192 Self {
2193 parent: 0,
2194 previous_sibling: 0,
2195 next_sibling: 0,
2196 last_child: 0,
2197 }
2198 }
2199}
2200
2201impl From<Node> for NodeHierarchyItem {
2202 fn from(node: Node) -> NodeHierarchyItem {
2203 NodeHierarchyItem {
2204 parent: NodeId::into_usize(&node.parent),
2205 previous_sibling: NodeId::into_usize(&node.previous_sibling),
2206 next_sibling: NodeId::into_usize(&node.next_sibling),
2207 last_child: NodeId::into_usize(&node.last_child),
2208 }
2209 }
2210}
2211
2212impl NodeHierarchyItem {
2213 pub fn parent_id(&self) -> Option<NodeId> {
2214 NodeId::from_usize(self.parent)
2215 }
2216 pub fn previous_sibling_id(&self) -> Option<NodeId> {
2217 NodeId::from_usize(self.previous_sibling)
2218 }
2219 pub fn next_sibling_id(&self) -> Option<NodeId> {
2220 NodeId::from_usize(self.next_sibling)
2221 }
2222 pub fn first_child_id(&self, current_node_id: NodeId) -> Option<NodeId> {
2223 self.last_child_id().map(|_| current_node_id + 1)
2224 }
2225 pub fn last_child_id(&self) -> Option<NodeId> {
2226 NodeId::from_usize(self.last_child)
2227 }
2228}
2229
2230impl_vec!(
2231 NodeHierarchyItem,
2232 NodeHierarchyItemVec,
2233 NodeHierarchyItemVecDestructor
2234);
2235impl_vec_mut!(NodeHierarchyItem, NodeHierarchyItemVec);
2236impl_vec_debug!(AzNode, NodeHierarchyItemVec);
2237impl_vec_partialord!(AzNode, NodeHierarchyItemVec);
2238impl_vec_clone!(
2239 NodeHierarchyItem,
2240 NodeHierarchyItemVec,
2241 NodeHierarchyItemVecDestructor
2242);
2243impl_vec_partialeq!(AzNode, NodeHierarchyItemVec);
2244
2245impl NodeHierarchyItemVec {
2246 pub fn as_container<'a>(&'a self) -> NodeDataContainerRef<'a, NodeHierarchyItem> {
2247 NodeDataContainerRef {
2248 internal: self.as_ref(),
2249 }
2250 }
2251 pub fn as_container_mut<'a>(&'a mut self) -> NodeDataContainerRefMut<'a, NodeHierarchyItem> {
2252 NodeDataContainerRefMut {
2253 internal: self.as_mut(),
2254 }
2255 }
2256}
2257
2258impl<'a> NodeDataContainerRef<'a, NodeHierarchyItem> {
2259 #[inline]
2260 pub fn subtree_len(&self, parent_id: NodeId) -> usize {
2261 let self_item_index = parent_id.index();
2262 let next_item_index = match self[parent_id].next_sibling_id() {
2263 None => self.len(),
2264 Some(s) => s.index(),
2265 };
2266 next_item_index - self_item_index - 1
2267 }
2268}
2269
2270#[derive(Copy, Clone, PartialEq, Eq, Ord, PartialOrd, Hash)]
2271#[repr(C)]
2272pub struct ParentWithNodeDepth {
2273 pub depth: usize,
2274 pub node_id: NodeHierarchyItemId,
2275}
2276
2277impl core::fmt::Debug for ParentWithNodeDepth {
2278 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
2279 write!(
2280 f,
2281 "{{ depth: {}, node: {:?} }}",
2282 self.depth,
2283 self.node_id.into_crate_internal()
2284 )
2285 }
2286}
2287
2288impl_vec!(
2289 ParentWithNodeDepth,
2290 ParentWithNodeDepthVec,
2291 ParentWithNodeDepthVecDestructor
2292);
2293impl_vec_mut!(ParentWithNodeDepth, ParentWithNodeDepthVec);
2294impl_vec_debug!(ParentWithNodeDepth, ParentWithNodeDepthVec);
2295impl_vec_partialord!(ParentWithNodeDepth, ParentWithNodeDepthVec);
2296impl_vec_clone!(
2297 ParentWithNodeDepth,
2298 ParentWithNodeDepthVec,
2299 ParentWithNodeDepthVecDestructor
2300);
2301impl_vec_partialeq!(ParentWithNodeDepth, ParentWithNodeDepthVec);
2302
2303#[derive(Debug, Clone, PartialEq, Eq, Ord, PartialOrd)]
2304#[repr(C)]
2305pub struct TagIdToNodeIdMapping {
2306 pub tag_id: AzTagId,
2308 pub node_id: NodeHierarchyItemId,
2310 pub tab_index: OptionTabIndex,
2312 pub parent_node_ids: NodeIdVec,
2314}
2315
2316impl_vec!(
2317 TagIdToNodeIdMapping,
2318 TagIdToNodeIdMappingVec,
2319 TagIdToNodeIdMappingVecDestructor
2320);
2321impl_vec_mut!(TagIdToNodeIdMapping, TagIdToNodeIdMappingVec);
2322impl_vec_debug!(TagIdToNodeIdMapping, TagIdToNodeIdMappingVec);
2323impl_vec_partialord!(TagIdToNodeIdMapping, TagIdToNodeIdMappingVec);
2324impl_vec_clone!(
2325 TagIdToNodeIdMapping,
2326 TagIdToNodeIdMappingVec,
2327 TagIdToNodeIdMappingVecDestructor
2328);
2329impl_vec_partialeq!(TagIdToNodeIdMapping, TagIdToNodeIdMappingVec);
2330
2331#[derive(Debug, Clone, PartialEq, PartialOrd)]
2332#[repr(C)]
2333pub struct ContentGroup {
2334 pub root: NodeHierarchyItemId,
2337 pub children: ContentGroupVec,
2339}
2340
2341impl_vec!(ContentGroup, ContentGroupVec, ContentGroupVecDestructor);
2342impl_vec_mut!(ContentGroup, ContentGroupVec);
2343impl_vec_debug!(ContentGroup, ContentGroupVec);
2344impl_vec_partialord!(ContentGroup, ContentGroupVec);
2345impl_vec_clone!(ContentGroup, ContentGroupVec, ContentGroupVecDestructor);
2346impl_vec_partialeq!(ContentGroup, ContentGroupVec);
2347
2348#[derive(Debug, PartialEq, Clone)]
2349#[repr(C)]
2350pub struct StyledDom {
2351 pub root: NodeHierarchyItemId,
2352 pub node_hierarchy: NodeHierarchyItemVec,
2353 pub node_data: NodeDataVec,
2354 pub styled_nodes: StyledNodeVec,
2355 pub cascade_info: CascadeInfoVec,
2356 pub nodes_with_window_callbacks: NodeIdVec,
2357 pub nodes_with_not_callbacks: NodeIdVec,
2358 pub nodes_with_datasets: NodeIdVec,
2359 pub tag_ids_to_node_ids: TagIdToNodeIdMappingVec,
2360 pub non_leaf_nodes: ParentWithNodeDepthVec,
2361 pub css_property_cache: CssPropertyCachePtr,
2362}
2363
2364impl Default for StyledDom {
2365 fn default() -> Self {
2366 let root_node: NodeHierarchyItem = Node::ROOT.into();
2367 let root_node_id: NodeHierarchyItemId =
2368 NodeHierarchyItemId::from_crate_internal(Some(NodeId::ZERO));
2369 Self {
2370 root: root_node_id,
2371 node_hierarchy: vec![root_node].into(),
2372 node_data: vec![NodeData::body()].into(),
2373 styled_nodes: vec![StyledNode::default()].into(),
2374 cascade_info: vec![CascadeInfo {
2375 index_in_parent: 0,
2376 is_last_child: true,
2377 }]
2378 .into(),
2379 tag_ids_to_node_ids: Vec::new().into(),
2380 non_leaf_nodes: vec![ParentWithNodeDepth {
2381 depth: 0,
2382 node_id: root_node_id,
2383 }]
2384 .into(),
2385 nodes_with_window_callbacks: Vec::new().into(),
2386 nodes_with_not_callbacks: Vec::new().into(),
2387 nodes_with_datasets: Vec::new().into(),
2388 css_property_cache: CssPropertyCachePtr::new(CssPropertyCache::empty(1)),
2389 }
2390 }
2391}
2392
2393impl StyledDom {
2394 pub fn new(dom: &mut Dom, mut css: CssApiWrapper) -> Self {
2399 use core::mem;
2400
2401 use crate::dom::EventFilter;
2402
2403 let mut swap_dom = Dom::body();
2404
2405 mem::swap(dom, &mut swap_dom);
2406
2407 let compact_dom: CompactDom = swap_dom.into();
2408 let non_leaf_nodes = compact_dom
2409 .node_hierarchy
2410 .as_ref()
2411 .get_parents_sorted_by_depth();
2412 let node_hierarchy: NodeHierarchyItemVec = compact_dom
2413 .node_hierarchy
2414 .as_ref()
2415 .internal
2416 .iter()
2417 .map(|i| (*i).into())
2418 .collect::<Vec<NodeHierarchyItem>>()
2419 .into();
2420
2421 let mut styled_nodes = vec![
2422 StyledNode {
2423 tag_id: OptionTagId::None,
2424 state: StyledNodeState::new()
2425 };
2426 compact_dom.len()
2427 ];
2428
2429 let mut css_property_cache = CssPropertyCache::empty(compact_dom.node_data.len());
2433
2434 let html_tree =
2435 construct_html_cascade_tree(&compact_dom.node_hierarchy.as_ref(), &non_leaf_nodes[..]);
2436
2437 let non_leaf_nodes = non_leaf_nodes
2438 .iter()
2439 .map(|(depth, node_id)| ParentWithNodeDepth {
2440 depth: *depth,
2441 node_id: NodeHierarchyItemId::from_crate_internal(Some(*node_id)),
2442 })
2443 .collect::<Vec<_>>();
2444
2445 let non_leaf_nodes: ParentWithNodeDepthVec = non_leaf_nodes.into();
2446
2447 let tag_ids = css_property_cache.restyle(
2449 &mut css.css,
2450 &compact_dom.node_data.as_ref(),
2451 &node_hierarchy,
2452 &non_leaf_nodes,
2453 &html_tree.as_ref(),
2454 );
2455
2456 tag_ids
2457 .iter()
2458 .filter_map(|tag_id_node_id_mapping| {
2459 tag_id_node_id_mapping
2460 .node_id
2461 .into_crate_internal()
2462 .map(|node_id| (node_id, tag_id_node_id_mapping.tag_id))
2463 })
2464 .for_each(|(nid, tag_id)| {
2465 styled_nodes[nid.index()].tag_id = OptionTagId::Some(tag_id);
2466 });
2467
2468 let nodes_with_window_callbacks = compact_dom
2471 .node_data
2472 .as_ref()
2473 .internal
2474 .iter()
2475 .enumerate()
2476 .filter_map(|(node_id, c)| {
2477 let node_has_none_callbacks = c.get_callbacks().iter().any(|cb| match cb.event {
2478 EventFilter::Window(_) => true,
2479 _ => false,
2480 });
2481 if node_has_none_callbacks {
2482 Some(NodeHierarchyItemId::from_crate_internal(Some(NodeId::new(
2483 node_id,
2484 ))))
2485 } else {
2486 None
2487 }
2488 })
2489 .collect::<Vec<_>>();
2490
2491 let nodes_with_not_callbacks = compact_dom
2492 .node_data
2493 .as_ref()
2494 .internal
2495 .iter()
2496 .enumerate()
2497 .filter_map(|(node_id, c)| {
2498 let node_has_none_callbacks = c.get_callbacks().iter().any(|cb| match cb.event {
2499 EventFilter::Not(_) => true,
2500 _ => false,
2501 });
2502 if node_has_none_callbacks {
2503 Some(NodeHierarchyItemId::from_crate_internal(Some(NodeId::new(
2504 node_id,
2505 ))))
2506 } else {
2507 None
2508 }
2509 })
2510 .collect::<Vec<_>>();
2511
2512 let nodes_with_datasets = compact_dom
2514 .node_data
2515 .as_ref()
2516 .internal
2517 .iter()
2518 .enumerate()
2519 .filter_map(|(node_id, c)| {
2520 if !c.get_callbacks().is_empty() || c.get_dataset().is_some() {
2521 Some(NodeHierarchyItemId::from_crate_internal(Some(NodeId::new(
2522 node_id,
2523 ))))
2524 } else {
2525 None
2526 }
2527 })
2528 .collect::<Vec<_>>();
2529
2530 StyledDom {
2531 root: NodeHierarchyItemId::from_crate_internal(Some(compact_dom.root)),
2532 node_hierarchy,
2533 node_data: compact_dom.node_data.internal.into(),
2534 cascade_info: html_tree.internal.into(),
2535 styled_nodes: styled_nodes.into(),
2536 tag_ids_to_node_ids: tag_ids.into(),
2537 nodes_with_window_callbacks: nodes_with_window_callbacks.into(),
2538 nodes_with_not_callbacks: nodes_with_not_callbacks.into(),
2539 nodes_with_datasets: nodes_with_datasets.into(),
2540 non_leaf_nodes,
2541 css_property_cache: CssPropertyCachePtr::new(css_property_cache),
2542 }
2543 }
2544
2545 pub fn append_child(&mut self, mut other: Self) {
2548 let self_len = self.node_hierarchy.as_ref().len();
2550 let other_len = other.node_hierarchy.as_ref().len();
2551 let self_tag_len = self.tag_ids_to_node_ids.as_ref().len();
2552 let self_root_id = self.root.into_crate_internal().unwrap_or(NodeId::ZERO);
2553 let other_root_id = other.root.into_crate_internal().unwrap_or(NodeId::ZERO);
2554
2555 let current_root_children_count = self_root_id
2557 .az_children(&self.node_hierarchy.as_container())
2558 .count();
2559
2560 other.cascade_info.as_mut()[other_root_id.index()].index_in_parent =
2561 current_root_children_count as u32;
2562 other.cascade_info.as_mut()[other_root_id.index()].is_last_child = true;
2563
2564 self.cascade_info.append(&mut other.cascade_info);
2565
2566 for other in other.node_hierarchy.as_mut().iter_mut() {
2568 other.parent += self_len;
2569 other.previous_sibling += if other.previous_sibling == 0 {
2570 0
2571 } else {
2572 self_len
2573 };
2574 other.next_sibling += if other.next_sibling == 0 { 0 } else { self_len };
2575 other.last_child += if other.last_child == 0 { 0 } else { self_len };
2576 }
2577
2578 other.node_hierarchy.as_container_mut()[other_root_id].parent =
2579 NodeId::into_usize(&Some(self_root_id));
2580 let current_last_child = self.node_hierarchy.as_container()[self_root_id].last_child_id();
2581 other.node_hierarchy.as_container_mut()[other_root_id].previous_sibling =
2582 NodeId::into_usize(¤t_last_child);
2583 if let Some(current_last) = current_last_child {
2584 if self.node_hierarchy.as_container_mut()[current_last]
2585 .next_sibling_id()
2586 .is_some()
2587 {
2588 self.node_hierarchy.as_container_mut()[current_last].next_sibling +=
2589 other_root_id.index() + 1;
2590 } else {
2591 self.node_hierarchy.as_container_mut()[current_last].next_sibling =
2592 self_len + other_root_id.index() + 1;
2593 }
2594 }
2595 self.node_hierarchy.as_container_mut()[self_root_id].last_child =
2596 self_len + other_root_id.index() + 1;
2597
2598 self.node_hierarchy.append(&mut other.node_hierarchy);
2599 self.node_data.append(&mut other.node_data);
2600 self.styled_nodes.append(&mut other.styled_nodes);
2601 self.get_css_property_cache_mut()
2602 .append(other.get_css_property_cache_mut());
2603
2604 for tag_id_node_id in other.tag_ids_to_node_ids.iter_mut() {
2605 tag_id_node_id.tag_id.inner += self_tag_len as u64;
2606 tag_id_node_id.node_id.inner += self_len;
2607 }
2608
2609 self.tag_ids_to_node_ids
2610 .append(&mut other.tag_ids_to_node_ids);
2611
2612 for nid in other.nodes_with_window_callbacks.iter_mut() {
2613 nid.inner += self_len;
2614 }
2615 self.nodes_with_window_callbacks
2616 .append(&mut other.nodes_with_window_callbacks);
2617
2618 for nid in other.nodes_with_not_callbacks.iter_mut() {
2619 nid.inner += self_len;
2620 }
2621 self.nodes_with_not_callbacks
2622 .append(&mut other.nodes_with_not_callbacks);
2623
2624 for nid in other.nodes_with_datasets.iter_mut() {
2625 nid.inner += self_len;
2626 }
2627 self.nodes_with_datasets
2628 .append(&mut other.nodes_with_datasets);
2629
2630 if other_len != 1 {
2633 for other_non_leaf_node in other.non_leaf_nodes.iter_mut() {
2634 other_non_leaf_node.node_id.inner += self_len;
2635 other_non_leaf_node.depth += 1;
2636 }
2637 self.non_leaf_nodes.append(&mut other.non_leaf_nodes);
2638 self.non_leaf_nodes.sort_by(|a, b| a.depth.cmp(&b.depth));
2639 }
2640 }
2641
2642 pub fn inject_scroll_bars(&mut self) {
2652 use azul_css::parser::CssApiWrapper;
2653
2654 let dom_to_inject = Dom::div()
2674 .with_inline_style("display:flex; flex-grow:1; flex-direction:column;".into())
2676 .with_children(vec![
2677
2678 Dom::div()
2679 .with_inline_style("display:flex; flex-grow:1; flex-direction:column-reverse;".into())
2681 .with_children(vec![
2682
2683 Dom::div()
2684 .with_inline_style("display:flex; flex-grow:1; flex-direction:row; height:15px; background:grey;".into())
2686 .with_children(vec![
2687 Dom::div(),
2688 Dom::div()
2690 .with_children(vec![
2692 Dom::div()
2693 ].into()),
2695 Dom::div()
2696 ].into()),
2698
2699 Dom::div()
2700 .with_inline_style("display:flex; flex-grow:1; flex-direction:row-reverse;".into())
2702 .with_children(vec![
2703
2704 Dom::div()
2705 .with_inline_style("display:flex; flex-grow:1; flex-direction:column; width:15px; background:grey;".into())
2707 .with_children(vec![
2708 Dom::div(),
2709 Dom::div()
2711 .with_children(vec![
2713 Dom::div()
2714 ].into()),
2716 Dom::div()
2717 ].into()),
2719
2720 Dom::div()
2721 .with_inline_style("display:flex; flex-grow:1; flex-direction:column;".into())
2723 .with_children(vec![
2724 Dom::div() ].into())
2726 ].into())
2727 ].into())
2728 ].into())
2729 .style(CssApiWrapper::empty());
2730
2731 let nodes_to_allocate =
2733 self.node_data.len() + (self.non_leaf_nodes.len() * dom_to_inject.node_data.len());
2734
2735 let mut new_styled_dom = StyledDom {
2738 root: self.root,
2739 node_hierarchy: vec![NodeHierarchyItem::zeroed(); nodes_to_allocate].into(),
2740 node_data: vec![NodeData::default(); nodes_to_allocate].into(),
2741 styled_nodes: vec![StyledNode::default(); nodes_to_allocate].into(),
2742 cascade_info: vec![CascadeInfo::default(); nodes_to_allocate].into(),
2743 nodes_with_window_callbacks: self.nodes_with_window_callbacks.clone(),
2744 nodes_with_not_callbacks: self.nodes_with_not_callbacks.clone(),
2745 nodes_with_datasets: self.nodes_with_datasets.clone(),
2746 tag_ids_to_node_ids: self.tag_ids_to_node_ids.clone(),
2747 non_leaf_nodes: self.non_leaf_nodes.clone(),
2748 css_property_cache: self.css_property_cache.clone(),
2749 };
2750
2751 let inject_as_id = 0;
2753
2754 #[cfg(feature = "std")]
2755 {
2756 println!(
2757 "inject scroll bars:\r\n{}",
2758 dom_to_inject.get_html_string("", "", true)
2759 );
2760 }
2761
2762 }
2764
2765 pub fn inject_menu_bar(mut self, menu_bar: &Menu) -> Self {
2767 use azul_css::parser::CssApiWrapper;
2768
2769 use crate::window::MenuItem;
2770
2771 let menu_dom = menu_bar
2772 .items
2773 .as_ref()
2774 .iter()
2775 .map(|mi| match mi {
2776 MenuItem::String(smi) => Dom::text(smi.label.clone().into_library_owned_string())
2777 .with_inline_style("font-family:sans-serif;".into()),
2778 MenuItem::Separator => {
2779 Dom::div().with_inline_style("padding:1px;background:grey;".into())
2780 }
2781 MenuItem::BreakLine => Dom::div(),
2782 })
2783 .collect::<Dom>()
2784 .with_inline_style(
2785 "
2786 height:20px;
2787 display:flex;
2788 flex-direction:row;"
2789 .into(),
2790 )
2791 .style(CssApiWrapper::empty());
2792
2793 let mut core_container = Dom::body().style(CssApiWrapper::empty());
2794 core_container.append_child(menu_dom);
2795 core_container.append_child(self);
2796 core_container
2797 }
2798
2799 pub fn with_child(&mut self, other: Self) -> Self {
2801 let mut s = self.swap_with_default();
2802 s.append_child(other);
2803 s
2804 }
2805
2806 pub fn restyle(&mut self, mut css: CssApiWrapper) {
2807 let new_tag_ids = self.css_property_cache.downcast_mut().restyle(
2808 &mut css.css,
2809 &self.node_data.as_container(),
2810 &self.node_hierarchy,
2811 &self.non_leaf_nodes,
2812 &self.cascade_info.as_container(),
2813 );
2814
2815 let mut styled_nodes_mut = self.styled_nodes.as_container_mut();
2817
2818 styled_nodes_mut
2819 .internal
2820 .iter_mut()
2821 .for_each(|styled_node| {
2822 styled_node.tag_id = None.into();
2823 });
2824
2825 new_tag_ids
2826 .iter()
2827 .filter_map(|tag_id_node_id_mapping| {
2828 tag_id_node_id_mapping
2829 .node_id
2830 .into_crate_internal()
2831 .map(|node_id| (node_id, tag_id_node_id_mapping.tag_id))
2832 })
2833 .for_each(|(nid, tag_id)| {
2834 styled_nodes_mut[nid].tag_id = Some(tag_id).into();
2835 });
2836
2837 self.tag_ids_to_node_ids = new_tag_ids.into();
2838 }
2839
2840 #[inline]
2843 pub fn insert_default_system_callbacks(&mut self, config: DefaultCallbacksCfg) {
2844 use crate::{
2845 callbacks::Callback,
2846 dom::{CallbackData, EventFilter, FocusEventFilter, HoverEventFilter},
2847 };
2848
2849 let scroll_refany = RefAny::new(DefaultScrollCallbackData {
2850 smooth_scroll: config.smooth_scroll,
2851 });
2852
2853 for n in self.node_data.iter_mut() {
2854 if !n
2856 .callbacks
2857 .iter()
2858 .any(|cb| cb.event == EventFilter::Hover(HoverEventFilter::Scroll))
2859 {
2860 n.callbacks.push(CallbackData {
2861 event: EventFilter::Hover(HoverEventFilter::Scroll),
2862 data: scroll_refany.clone(),
2863 callback: Callback {
2864 cb: default_on_scroll,
2865 },
2866 });
2867 }
2868 }
2869
2870 if !config.enable_autotab {
2871 return;
2872 }
2873
2874 let tab_data = RefAny::new(DefaultTabIndexCallbackData {});
2875 for focusable_node in self.tag_ids_to_node_ids.iter() {
2876 if focusable_node.tab_index.is_some() {
2877 let focusable_node_id = match focusable_node.node_id.into_crate_internal() {
2878 Some(s) => s,
2879 None => continue,
2880 };
2881
2882 let mut node_data = &mut self.node_data.as_container_mut()[focusable_node_id];
2883 if !node_data
2884 .callbacks
2885 .iter()
2886 .any(|cb| cb.event == EventFilter::Focus(FocusEventFilter::VirtualKeyDown))
2887 {
2888 node_data.callbacks.push(CallbackData {
2889 event: EventFilter::Focus(FocusEventFilter::VirtualKeyDown),
2890 data: tab_data.clone(),
2891 callback: Callback {
2892 cb: default_on_tabindex,
2893 },
2894 });
2895 }
2896 }
2897 }
2898 }
2899
2900 #[inline]
2901 pub fn node_count(&self) -> usize {
2902 self.node_data.len()
2903 }
2904
2905 #[inline]
2906 pub fn get_css_property_cache<'a>(&'a self) -> &'a CssPropertyCache {
2907 &*self.css_property_cache.ptr
2908 }
2909
2910 #[inline]
2911 pub fn get_css_property_cache_mut<'a>(&'a mut self) -> &'a mut CssPropertyCache {
2912 &mut *self.css_property_cache.ptr
2913 }
2914
2915 #[inline]
2916 pub fn get_styled_node_state(&self, node_id: &NodeId) -> StyledNodeState {
2917 self.styled_nodes.as_container()[*node_id].state.clone()
2918 }
2919
2920 pub fn scan_for_font_keys(
2922 &self,
2923 resources: &RendererResources,
2924 ) -> FastHashMap<ImmediateFontId, FastBTreeSet<Au>> {
2925 use crate::{app_resources::font_size_to_au, dom::NodeType::*};
2926
2927 let keys = self
2928 .node_data
2929 .as_ref()
2930 .iter()
2931 .enumerate()
2932 .filter_map(|(node_id, node_data)| {
2933 let node_id = NodeId::new(node_id);
2934 match node_data.get_node_type() {
2935 Text(_) => {
2936 let css_font_ids = self.get_css_property_cache().get_font_id_or_default(
2937 &node_data,
2938 &node_id,
2939 &self.styled_nodes.as_container()[node_id].state,
2940 );
2941
2942 let font_size = self.get_css_property_cache().get_font_size_or_default(
2943 &node_data,
2944 &node_id,
2945 &self.styled_nodes.as_container()[node_id].state,
2946 );
2947
2948 let style_font_families_hash =
2949 StyleFontFamiliesHash::new(css_font_ids.as_ref());
2950
2951 let existing_font_key = resources
2952 .get_font_family(&style_font_families_hash)
2953 .and_then(|font_family_hash| {
2954 resources
2955 .get_font_key(&font_family_hash)
2956 .map(|font_key| (font_family_hash, font_key))
2957 });
2958
2959 let font_id = match existing_font_key {
2960 Some((hash, key)) => ImmediateFontId::Resolved((*hash, *key)),
2961 None => ImmediateFontId::Unresolved(css_font_ids),
2962 };
2963
2964 Some((font_id, font_size_to_au(font_size)))
2965 }
2966 _ => None,
2967 }
2968 })
2969 .collect::<Vec<_>>();
2970
2971 let mut map = FastHashMap::default();
2972
2973 for (font_id, au) in keys.into_iter() {
2974 map.entry(font_id)
2975 .or_insert_with(|| FastBTreeSet::default())
2976 .insert(au);
2977 }
2978
2979 map
2980 }
2981
2982 pub fn scan_for_image_keys(&self, css_image_cache: &ImageCache) -> FastBTreeSet<ImageRef> {
2984 use azul_css::StyleBackgroundContentVec;
2985
2986 use crate::{app_resources::OptionImageMask, dom::NodeType::*};
2987
2988 #[derive(Default)]
2989 struct ScanImageVec {
2990 node_type_image: Option<ImageRef>,
2991 background_image: Vec<ImageRef>,
2992 clip_mask: Option<ImageRef>,
2993 }
2994
2995 let default_backgrounds: StyleBackgroundContentVec = Vec::new().into();
2996
2997 let images = self
2998 .node_data
2999 .as_container()
3000 .internal
3001 .iter()
3002 .enumerate()
3003 .map(|(node_id, node_data)| {
3004 let node_id = NodeId::new(node_id);
3005 let mut v = ScanImageVec::default();
3006
3007 if let Image(id) = node_data.get_node_type() {
3009 v.node_type_image = Some(id.clone());
3010 }
3011
3012 let opt_background_image = self.get_css_property_cache().get_background_content(
3014 &node_data,
3015 &node_id,
3016 &self.styled_nodes.as_container()[node_id].state,
3017 );
3018
3019 if let Some(style_backgrounds) = opt_background_image {
3020 v.background_image = style_backgrounds
3021 .get_property()
3022 .unwrap_or(&default_backgrounds)
3023 .iter()
3024 .filter_map(|bg| {
3025 use azul_css::StyleBackgroundContent::*;
3026 let css_image_id = match bg {
3027 Image(i) => i,
3028 _ => return None,
3029 };
3030 let image_ref = css_image_cache.get_css_image_id(css_image_id)?;
3031 Some(image_ref.clone())
3032 })
3033 .collect();
3034 }
3035
3036 if let Some(clip_mask) = node_data.get_clip_mask() {
3038 v.clip_mask = Some(clip_mask.image.clone());
3039 }
3040
3041 v
3042 })
3043 .collect::<Vec<_>>();
3044
3045 let mut set = FastBTreeSet::new();
3046
3047 for scan_image in images.into_iter() {
3048 if let Some(n) = scan_image.node_type_image {
3049 set.insert(n);
3050 }
3051 if let Some(n) = scan_image.clip_mask {
3052 set.insert(n);
3053 }
3054 for bg in scan_image.background_image {
3055 set.insert(bg);
3056 }
3057 }
3058
3059 set
3060 }
3061
3062 #[must_use]
3063 pub fn restyle_nodes_hover(
3064 &mut self,
3065 nodes: &[NodeId],
3066 new_hover_state: bool,
3067 ) -> BTreeMap<NodeId, Vec<ChangedCssProperty>> {
3068 let old_node_states = nodes
3070 .iter()
3071 .map(|nid| self.styled_nodes.as_container()[*nid].state.clone())
3072 .collect::<Vec<_>>();
3073
3074 for nid in nodes.iter() {
3075 self.styled_nodes.as_container_mut()[*nid].state.hover = new_hover_state;
3076 }
3077
3078 let css_property_cache = self.get_css_property_cache();
3079 let styled_nodes = self.styled_nodes.as_container();
3080 let node_data = self.node_data.as_container();
3081
3082 let default_map = BTreeMap::default();
3083
3084 let v = nodes
3086 .iter()
3087 .zip(old_node_states.iter())
3088 .filter_map(|(node_id, old_node_state)| {
3089 let mut keys_normal: Vec<_> = css_property_cache
3090 .css_hover_props
3091 .get(node_id)
3092 .unwrap_or(&default_map)
3093 .keys()
3094 .collect();
3095 let mut keys_inherited: Vec<_> = css_property_cache
3096 .cascaded_hover_props
3097 .get(node_id)
3098 .unwrap_or(&default_map)
3099 .keys()
3100 .collect();
3101 let keys_inline: Vec<CssPropertyType> = node_data[*node_id]
3102 .inline_css_props
3103 .iter()
3104 .filter_map(|prop| match prop {
3105 NodeDataInlineCssProperty::Hover(h) => Some(h.get_type()),
3106 _ => None,
3107 })
3108 .collect();
3109 let mut keys_inline_ref = keys_inline.iter().map(|r| r).collect();
3110
3111 keys_normal.append(&mut keys_inherited);
3112 keys_normal.append(&mut keys_inline_ref);
3113
3114 let node_properties_that_could_have_changed = keys_normal;
3115
3116 if node_properties_that_could_have_changed.is_empty() {
3117 return None;
3118 }
3119
3120 let new_node_state = &styled_nodes[*node_id].state;
3121 let node_data = &node_data[*node_id];
3122
3123 let changes = node_properties_that_could_have_changed
3124 .into_iter()
3125 .filter_map(|prop| {
3126 let old = css_property_cache.get_property(
3128 node_data,
3129 node_id,
3130 old_node_state,
3131 prop,
3132 );
3133 let new = css_property_cache.get_property(
3134 node_data,
3135 node_id,
3136 new_node_state,
3137 prop,
3138 );
3139 if old == new {
3140 None
3141 } else {
3142 Some(ChangedCssProperty {
3143 previous_state: old_node_state.clone(),
3144 previous_prop: match old {
3145 None => CssProperty::auto(*prop),
3146 Some(s) => s.clone(),
3147 },
3148 current_state: new_node_state.clone(),
3149 current_prop: match new {
3150 None => CssProperty::auto(*prop),
3151 Some(s) => s.clone(),
3152 },
3153 })
3154 }
3155 })
3156 .collect::<Vec<_>>();
3157
3158 if changes.is_empty() {
3159 None
3160 } else {
3161 Some((*node_id, changes))
3162 }
3163 })
3164 .collect::<Vec<_>>();
3165
3166 v.into_iter().collect()
3167 }
3168
3169 #[must_use]
3170 pub fn restyle_nodes_active(
3171 &mut self,
3172 nodes: &[NodeId],
3173 new_active_state: bool,
3174 ) -> BTreeMap<NodeId, Vec<ChangedCssProperty>> {
3175 let old_node_states = nodes
3177 .iter()
3178 .map(|nid| self.styled_nodes.as_container()[*nid].state.clone())
3179 .collect::<Vec<_>>();
3180
3181 for nid in nodes.iter() {
3182 self.styled_nodes.as_container_mut()[*nid].state.active = new_active_state;
3183 }
3184
3185 let css_property_cache = self.get_css_property_cache();
3186 let styled_nodes = self.styled_nodes.as_container();
3187 let node_data = self.node_data.as_container();
3188
3189 let default_map = BTreeMap::default();
3190
3191 let v = nodes
3193 .iter()
3194 .zip(old_node_states.iter())
3195 .filter_map(|(node_id, old_node_state)| {
3196 let mut keys_normal: Vec<_> = css_property_cache
3197 .css_active_props
3198 .get(node_id)
3199 .unwrap_or(&default_map)
3200 .keys()
3201 .collect();
3202
3203 let mut keys_inherited: Vec<_> = css_property_cache
3204 .cascaded_active_props
3205 .get(node_id)
3206 .unwrap_or(&default_map)
3207 .keys()
3208 .collect();
3209
3210 let keys_inline: Vec<CssPropertyType> = node_data[*node_id]
3211 .inline_css_props
3212 .iter()
3213 .filter_map(|prop| match prop {
3214 NodeDataInlineCssProperty::Active(h) => Some(h.get_type()),
3215 _ => None,
3216 })
3217 .collect();
3218 let mut keys_inline_ref = keys_inline.iter().map(|r| r).collect();
3219
3220 keys_normal.append(&mut keys_inherited);
3221 keys_normal.append(&mut keys_inline_ref);
3222
3223 let node_properties_that_could_have_changed = keys_normal;
3224
3225 if node_properties_that_could_have_changed.is_empty() {
3226 return None;
3227 }
3228
3229 let new_node_state = &styled_nodes[*node_id].state;
3230 let node_data = &node_data[*node_id];
3231
3232 let changes = node_properties_that_could_have_changed
3233 .into_iter()
3234 .filter_map(|prop| {
3235 let old = css_property_cache.get_property(
3237 node_data,
3238 node_id,
3239 old_node_state,
3240 prop,
3241 );
3242 let new = css_property_cache.get_property(
3243 node_data,
3244 node_id,
3245 new_node_state,
3246 prop,
3247 );
3248 if old == new {
3249 None
3250 } else {
3251 Some(ChangedCssProperty {
3252 previous_state: old_node_state.clone(),
3253 previous_prop: match old {
3254 None => CssProperty::auto(*prop),
3255 Some(s) => s.clone(),
3256 },
3257 current_state: new_node_state.clone(),
3258 current_prop: match new {
3259 None => CssProperty::auto(*prop),
3260 Some(s) => s.clone(),
3261 },
3262 })
3263 }
3264 })
3265 .collect::<Vec<_>>();
3266
3267 if changes.is_empty() {
3268 None
3269 } else {
3270 Some((*node_id, changes))
3271 }
3272 })
3273 .collect::<Vec<_>>();
3274
3275 v.into_iter().collect()
3276 }
3277
3278 #[must_use]
3279 pub fn restyle_nodes_focus(
3280 &mut self,
3281 nodes: &[NodeId],
3282 new_focus_state: bool,
3283 ) -> BTreeMap<NodeId, Vec<ChangedCssProperty>> {
3284 let old_node_states = nodes
3286 .iter()
3287 .map(|nid| self.styled_nodes.as_container()[*nid].state.clone())
3288 .collect::<Vec<_>>();
3289
3290 for nid in nodes.iter() {
3291 self.styled_nodes.as_container_mut()[*nid].state.focused = new_focus_state;
3292 }
3293
3294 let css_property_cache = self.get_css_property_cache();
3295 let styled_nodes = self.styled_nodes.as_container();
3296 let node_data = self.node_data.as_container();
3297
3298 let default_map = BTreeMap::default();
3299
3300 let v = nodes
3302 .iter()
3303 .zip(old_node_states.iter())
3304 .filter_map(|(node_id, old_node_state)| {
3305 let mut keys_normal: Vec<_> = css_property_cache
3306 .css_focus_props
3307 .get(node_id)
3308 .unwrap_or(&default_map)
3309 .keys()
3310 .collect();
3311
3312 let mut keys_inherited: Vec<_> = css_property_cache
3313 .cascaded_focus_props
3314 .get(node_id)
3315 .unwrap_or(&default_map)
3316 .keys()
3317 .collect();
3318
3319 let keys_inline: Vec<CssPropertyType> = node_data[*node_id]
3320 .inline_css_props
3321 .iter()
3322 .filter_map(|prop| match prop {
3323 NodeDataInlineCssProperty::Focus(h) => Some(h.get_type()),
3324 _ => None,
3325 })
3326 .collect();
3327 let mut keys_inline_ref = keys_inline.iter().map(|r| r).collect();
3328
3329 keys_normal.append(&mut keys_inherited);
3330 keys_normal.append(&mut keys_inline_ref);
3331
3332 let node_properties_that_could_have_changed = keys_normal;
3333
3334 if node_properties_that_could_have_changed.is_empty() {
3335 return None;
3336 }
3337
3338 let new_node_state = &styled_nodes[*node_id].state;
3339 let node_data = &node_data[*node_id];
3340
3341 let changes = node_properties_that_could_have_changed
3342 .into_iter()
3343 .filter_map(|prop| {
3344 let old = css_property_cache.get_property(
3346 node_data,
3347 node_id,
3348 old_node_state,
3349 prop,
3350 );
3351 let new = css_property_cache.get_property(
3352 node_data,
3353 node_id,
3354 new_node_state,
3355 prop,
3356 );
3357 if old == new {
3358 None
3359 } else {
3360 Some(ChangedCssProperty {
3361 previous_state: old_node_state.clone(),
3362 previous_prop: match old {
3363 None => CssProperty::auto(*prop),
3364 Some(s) => s.clone(),
3365 },
3366 current_state: new_node_state.clone(),
3367 current_prop: match new {
3368 None => CssProperty::auto(*prop),
3369 Some(s) => s.clone(),
3370 },
3371 })
3372 }
3373 })
3374 .collect::<Vec<_>>();
3375
3376 if changes.is_empty() {
3377 None
3378 } else {
3379 Some((*node_id, changes))
3380 }
3381 })
3382 .collect::<Vec<_>>();
3383
3384 v.into_iter().collect()
3385 }
3386
3387 #[must_use]
3389 pub fn restyle_user_property(
3390 &mut self,
3391 node_id: &NodeId,
3392 new_properties: &[CssProperty],
3393 ) -> BTreeMap<NodeId, Vec<ChangedCssProperty>> {
3394 let mut map = BTreeMap::default();
3395
3396 if new_properties.is_empty() {
3397 return map;
3398 }
3399
3400 let node_data = self.node_data.as_container();
3401 let node_data = &node_data[*node_id];
3402
3403 let node_states = &self.styled_nodes.as_container();
3404 let old_node_state = &node_states[*node_id].state;
3405
3406 let changes: Vec<ChangedCssProperty> = {
3407 let css_property_cache = self.get_css_property_cache();
3408
3409 new_properties
3410 .iter()
3411 .filter_map(|new_prop| {
3412 let old_prop = css_property_cache.get_property(
3413 node_data,
3414 node_id,
3415 old_node_state,
3416 &new_prop.get_type(),
3417 );
3418
3419 let old_prop = match old_prop {
3420 None => CssProperty::auto(new_prop.get_type()),
3421 Some(s) => s.clone(),
3422 };
3423
3424 if old_prop == *new_prop {
3425 None
3426 } else {
3427 Some(ChangedCssProperty {
3428 previous_state: old_node_state.clone(),
3429 previous_prop: old_prop,
3430 current_state: old_node_state.clone(),
3432 current_prop: new_prop.clone(),
3433 })
3434 }
3435 })
3436 .collect()
3437 };
3438
3439 let css_property_cache_mut = self.get_css_property_cache_mut();
3440
3441 for new_prop in new_properties.iter() {
3442 if new_prop.is_initial() {
3443 let mut should_remove_map = false;
3444 if let Some(map) = css_property_cache_mut
3445 .user_overridden_properties
3446 .get_mut(node_id)
3447 {
3448 map.remove(&new_prop.get_type());
3450 should_remove_map = map.is_empty();
3451 }
3452 if should_remove_map {
3453 css_property_cache_mut
3454 .user_overridden_properties
3455 .remove(node_id);
3456 }
3457 } else {
3458 css_property_cache_mut
3459 .user_overridden_properties
3460 .entry(*node_id)
3461 .or_insert_with(|| BTreeMap::new())
3462 .insert(new_prop.get_type(), new_prop.clone());
3463 }
3464 }
3465
3466 if !changes.is_empty() {
3467 map.insert(*node_id, changes);
3468 }
3469
3470 map
3471 }
3472
3473 pub fn scan_for_iframe_callbacks(&self) -> Vec<NodeId> {
3475 use crate::dom::NodeType;
3476 self.node_data
3477 .as_ref()
3478 .iter()
3479 .enumerate()
3480 .filter_map(|(node_id, node_data)| match node_data.get_node_type() {
3481 NodeType::IFrame(_) => Some(NodeId::new(node_id)),
3482 _ => None,
3483 })
3484 .collect()
3485 }
3486
3487 pub(crate) fn scan_for_gltexture_callbacks(&self) -> Vec<NodeId> {
3489 use crate::dom::NodeType;
3490 self.node_data
3491 .as_ref()
3492 .iter()
3493 .enumerate()
3494 .filter_map(|(node_id, node_data)| {
3495 use crate::app_resources::DecodedImage;
3496 match node_data.get_node_type() {
3497 NodeType::Image(image_ref) => {
3498 if let DecodedImage::Callback(_) = image_ref.get_data() {
3499 Some(NodeId::new(node_id))
3500 } else {
3501 None
3502 }
3503 }
3504 _ => None,
3505 }
3506 })
3507 .collect()
3508 }
3509
3510 pub fn get_html_string(&self, custom_head: &str, custom_body: &str, test_mode: bool) -> String {
3525 let css_property_cache = self.get_css_property_cache();
3526
3527 let mut output = String::new();
3528
3529 let mut should_print_close_tag_after_node = BTreeMap::new();
3531
3532 let should_print_close_tag_debug = self
3533 .non_leaf_nodes
3534 .iter()
3535 .filter_map(|p| {
3536 let parent_node_id = p.node_id.into_crate_internal()?;
3537 let mut total_last_child = None;
3538 recursive_get_last_child(
3539 parent_node_id,
3540 &self.node_hierarchy.as_ref(),
3541 &mut total_last_child,
3542 );
3543 let total_last_child = total_last_child?;
3544 Some((parent_node_id, (total_last_child, p.depth)))
3545 })
3546 .collect::<BTreeMap<_, _>>();
3547
3548 for (parent_id, (last_child, parent_depth)) in should_print_close_tag_debug {
3549 should_print_close_tag_after_node
3550 .entry(last_child)
3551 .or_insert_with(|| Vec::new())
3552 .push((parent_id, parent_depth));
3553 }
3554
3555 let mut all_node_depths = self
3556 .non_leaf_nodes
3557 .iter()
3558 .filter_map(|p| {
3559 let parent_node_id = p.node_id.into_crate_internal()?;
3560 Some((parent_node_id, p.depth))
3561 })
3562 .collect::<BTreeMap<_, _>>();
3563
3564 for (parent_node_id, parent_depth) in self
3565 .non_leaf_nodes
3566 .iter()
3567 .filter_map(|p| Some((p.node_id.into_crate_internal()?, p.depth)))
3568 {
3569 for child_id in parent_node_id.az_children(&self.node_hierarchy.as_container()) {
3570 all_node_depths.insert(child_id, parent_depth + 1);
3571 }
3572 }
3573
3574 for node_id in self.node_hierarchy.as_container().linear_iter() {
3575 let depth = all_node_depths[&node_id];
3576
3577 let node_data = &self.node_data.as_container()[node_id];
3578 let node_state = &self.styled_nodes.as_container()[node_id].state;
3579 let tabs = String::from(" ").repeat(depth);
3580
3581 output.push_str("\r\n");
3582 output.push_str(&tabs);
3583 output.push_str(&node_data.debug_print_start(css_property_cache, &node_id, node_state));
3584
3585 if let Some(content) = node_data.get_node_type().format().as_ref() {
3586 output.push_str(content);
3587 }
3588
3589 let node_has_children = self.node_hierarchy.as_container()[node_id]
3590 .first_child_id(node_id)
3591 .is_some();
3592 if !node_has_children {
3593 let node_data = &self.node_data.as_container()[node_id];
3594 output.push_str(&node_data.debug_print_end());
3595 }
3596
3597 if let Some(close_tag_vec) = should_print_close_tag_after_node.get(&node_id) {
3598 let mut close_tag_vec = close_tag_vec.clone();
3599 close_tag_vec.sort_by(|a, b| b.1.cmp(&a.1)); for (close_tag_parent_id, close_tag_depth) in close_tag_vec {
3601 let node_data = &self.node_data.as_container()[close_tag_parent_id];
3602 let tabs = String::from(" ").repeat(close_tag_depth);
3603 output.push_str("\r\n");
3604 output.push_str(&tabs);
3605 output.push_str(&node_data.debug_print_end());
3606 }
3607 }
3608 }
3609
3610 if !test_mode {
3611 format!(
3612 include_str!("./default.html"),
3613 custom_head = custom_head,
3614 output = output,
3615 custom_body = custom_body
3616 )
3617 } else {
3618 output
3619 }
3620 }
3621
3622 pub fn get_subtree(&self, parent: NodeId) -> Vec<NodeId> {
3624 let mut total_last_child = None;
3625 recursive_get_last_child(parent, &self.node_hierarchy.as_ref(), &mut total_last_child);
3626 if let Some(last) = total_last_child {
3627 (parent.index()..=last.index())
3628 .map(|id| NodeId::new(id))
3629 .collect()
3630 } else {
3631 Vec::new()
3632 }
3633 }
3634
3635 pub fn get_subtree_parents(&self, parent: NodeId) -> Vec<NodeId> {
3637 let mut total_last_child = None;
3638 recursive_get_last_child(parent, &self.node_hierarchy.as_ref(), &mut total_last_child);
3639 if let Some(last) = total_last_child {
3640 (parent.index()..=last.index())
3641 .filter_map(|id| {
3642 if self.node_hierarchy.as_ref()[id].last_child_id().is_some() {
3643 Some(NodeId::new(id))
3644 } else {
3645 None
3646 }
3647 })
3648 .collect()
3649 } else {
3650 Vec::new()
3651 }
3652 }
3653
3654 pub fn get_rects_in_rendering_order(&self) -> ContentGroup {
3655 Self::determine_rendering_order(
3656 &self.non_leaf_nodes.as_ref(),
3657 &self.node_hierarchy.as_container(),
3658 &self.styled_nodes.as_container(),
3659 &self.node_data.as_container(),
3660 &self.get_css_property_cache(),
3661 )
3662 }
3663
3664 fn determine_rendering_order<'a>(
3667 non_leaf_nodes: &[ParentWithNodeDepth],
3668 node_hierarchy: &NodeDataContainerRef<'a, NodeHierarchyItem>,
3669 styled_nodes: &NodeDataContainerRef<StyledNode>,
3670 node_data_container: &NodeDataContainerRef<NodeData>,
3671 css_property_cache: &CssPropertyCache,
3672 ) -> ContentGroup {
3673 let children_sorted = non_leaf_nodes
3674 .iter()
3675 .filter_map(|parent| {
3676 Some((
3677 parent.node_id,
3678 sort_children_by_position(
3679 parent.node_id.into_crate_internal()?,
3680 node_hierarchy,
3681 styled_nodes,
3682 node_data_container,
3683 css_property_cache,
3684 ),
3685 ))
3686 })
3687 .collect::<Vec<_>>();
3688
3689 let children_sorted: BTreeMap<NodeHierarchyItemId, Vec<NodeHierarchyItemId>> =
3690 children_sorted.into_iter().collect();
3691
3692 let mut root_content_group = ContentGroup {
3693 root: NodeHierarchyItemId::from_crate_internal(Some(NodeId::ZERO)),
3694 children: Vec::new().into(),
3695 };
3696
3697 fill_content_group_children(&mut root_content_group, &children_sorted);
3698
3699 root_content_group
3700 }
3701
3702 pub fn swap_with_default(&mut self) -> Self {
3703 let mut new = Self::default();
3704 core::mem::swap(self, &mut new);
3705 new
3706 }
3707
3708 pub fn set_menu_bar(&mut self, menu: Menu) {
3709 if let Some(root) = self.root.into_crate_internal() {
3710 self.node_data.as_mut()[root.index()].set_menu_bar(menu)
3711 }
3712 }
3713
3714 pub fn set_context_menu(&mut self, menu: Menu) {
3715 if let Some(root) = self.root.into_crate_internal() {
3716 self.node_data.as_mut()[root.index()].set_context_menu(menu);
3717
3718 let mut new_tags = self.tag_ids_to_node_ids.clone().into_library_owned_vec();
3720
3721 let tag_id = match self.styled_nodes.as_mut()[root.index()].tag_id {
3722 OptionTagId::Some(s) => s,
3723 OptionTagId::None => AzTagId::from_crate_internal(TagId::unique()),
3724 };
3725
3726 new_tags.push(TagIdToNodeIdMapping {
3727 tag_id,
3728 node_id: self.root,
3729 tab_index: OptionTabIndex::None,
3730 parent_node_ids: NodeIdVec::from_const_slice(&[]),
3731 });
3732
3733 self.styled_nodes.as_mut()[root.index()].tag_id = OptionTagId::Some(tag_id);
3734 self.tag_ids_to_node_ids = new_tags.into();
3735 }
3736 }
3737
3738 }
3741
3742#[derive(Debug, Clone, PartialEq)]
3743pub struct DefaultCallbacksCfg {
3744 pub smooth_scroll: bool,
3745 pub enable_autotab: bool,
3746}
3747
3748#[derive(Debug, Copy, Clone, PartialEq)]
3749pub struct DefaultScrollCallbackData {
3750 pub smooth_scroll: bool,
3751}
3752
3753#[derive(Debug, Copy, Clone, PartialEq)]
3754pub struct DefaultTabIndexCallbackData {}
3755
3756extern "C" fn default_on_tabindex(data: &mut RefAny, info: &mut CallbackInfo) -> Update {
3758 let mut data = match data.downcast_mut::<DefaultTabIndexCallbackData>() {
3759 Some(s) => s,
3760 None => return Update::DoNothing,
3761 };
3762
3763 Update::DoNothing
3764}
3765
3766extern "C" fn default_on_scroll(data: &mut RefAny, info: &mut CallbackInfo) -> Update {
3768 let mut data = match data.downcast_mut::<DefaultScrollCallbackData>() {
3769 Some(s) => s,
3770 None => return Update::DoNothing,
3771 };
3772
3773 let mouse_state = info.get_current_mouse_state();
3774
3775 let (scroll_x, scroll_y) = match (
3776 mouse_state.scroll_y.into_option(),
3777 mouse_state.scroll_x.into_option(),
3778 ) {
3779 (None, None) => return Update::DoNothing,
3780 (x, y) => (x.unwrap_or(0.0), y.unwrap_or(0.0)),
3781 };
3782
3783 let hit_node_id = info.get_hit_node();
3784
3785 let new_scroll_position = match info.get_scroll_position(hit_node_id) {
3786 Some(mut s) => {
3787 s.x += scroll_x;
3788 s.y += scroll_y;
3789 s
3790 }
3791 None => return Update::DoNothing,
3792 };
3793
3794 info.set_scroll_position(hit_node_id, new_scroll_position);
3795
3796 Update::DoNothing
3797}
3798
3799fn fill_content_group_children(
3800 group: &mut ContentGroup,
3801 children_sorted: &BTreeMap<NodeHierarchyItemId, Vec<NodeHierarchyItemId>>,
3802) {
3803 if let Some(c) = children_sorted.get(&group.root) {
3804 group.children = c
3806 .iter()
3807 .map(|child| ContentGroup {
3808 root: *child,
3809 children: Vec::new().into(),
3810 })
3811 .collect::<Vec<ContentGroup>>()
3812 .into();
3813
3814 for c in group.children.as_mut() {
3815 fill_content_group_children(c, children_sorted);
3816 }
3817 }
3818}
3819
3820fn sort_children_by_position<'a>(
3821 parent: NodeId,
3822 node_hierarchy: &NodeDataContainerRef<'a, NodeHierarchyItem>,
3823 rectangles: &NodeDataContainerRef<StyledNode>,
3824 node_data_container: &NodeDataContainerRef<NodeData>,
3825 css_property_cache: &CssPropertyCache,
3826) -> Vec<NodeHierarchyItemId> {
3827 use azul_css::LayoutPosition::*;
3828
3829 let children_positions = parent
3830 .az_children(node_hierarchy)
3831 .map(|nid| {
3832 let position = css_property_cache
3833 .get_position(&node_data_container[nid], &nid, &rectangles[nid].state)
3834 .and_then(|p| p.clone().get_property_or_default())
3835 .unwrap_or_default();
3836 let id = NodeHierarchyItemId::from_crate_internal(Some(nid));
3837 (id, position)
3838 })
3839 .collect::<Vec<_>>();
3840
3841 let mut not_absolute_children = children_positions
3842 .iter()
3843 .filter_map(|(node_id, position)| {
3844 if *position != Absolute {
3845 Some(*node_id)
3846 } else {
3847 None
3848 }
3849 })
3850 .collect::<Vec<_>>();
3851
3852 let mut absolute_children = children_positions
3853 .iter()
3854 .filter_map(|(node_id, position)| {
3855 if *position == Absolute {
3856 Some(*node_id)
3857 } else {
3858 None
3859 }
3860 })
3861 .collect::<Vec<_>>();
3862
3863 not_absolute_children.append(&mut absolute_children);
3865 not_absolute_children
3866}
3867
3868fn recursive_get_last_child(
3871 node_id: NodeId,
3872 node_hierarchy: &[NodeHierarchyItem],
3873 target: &mut Option<NodeId>,
3874) {
3875 match node_hierarchy[node_id.index()].last_child_id() {
3876 None => return,
3877 Some(s) => {
3878 *target = Some(s);
3879 recursive_get_last_child(s, node_hierarchy, target);
3880 }
3881 }
3882}