freya_core/states/
viewport.rs1use freya_native_core::{
2 attributes::AttributeName,
3 exports::shipyard::Component,
4 node_ref::NodeView,
5 prelude::{
6 AttributeMaskBuilder,
7 Dependancy,
8 NodeMaskBuilder,
9 State,
10 },
11 NodeId,
12 SendAnyMap,
13};
14use freya_native_core_macro::partial_derive_state;
15
16use crate::{
17 custom_attributes::CustomAttributeValues,
18 parsing::{
19 Parse,
20 ParseAttribute,
21 ParseError,
22 },
23 values::OverflowMode,
24};
25
26#[derive(Default, PartialEq, Clone, Debug, Component)]
27pub struct ViewportState {
28 pub viewports: Vec<NodeId>,
29 pub node_id: NodeId,
30 pub overflow: OverflowMode,
31}
32
33impl ParseAttribute for ViewportState {
34 fn parse_attribute(
35 &mut self,
36 attr: freya_native_core::prelude::OwnedAttributeView<CustomAttributeValues>,
37 ) -> Result<(), ParseError> {
38 #[allow(clippy::single_match)]
39 match attr.attribute {
40 AttributeName::Overflow => {
41 if let Some(value) = attr.value.as_text() {
42 self.overflow = OverflowMode::parse(value).map_err(|_| ParseError)?;
43 }
44 }
45 _ => {}
46 }
47
48 Ok(())
49 }
50}
51
52#[partial_derive_state]
53impl State<CustomAttributeValues> for ViewportState {
54 type ParentDependencies = (Self,);
55
56 type ChildDependencies = ();
57
58 type NodeDependencies = ();
59
60 const NODE_MASK: NodeMaskBuilder<'static> = NodeMaskBuilder::new()
61 .with_attrs(AttributeMaskBuilder::Some(&[AttributeName::Overflow]))
62 .with_tag();
63
64 fn update<'a>(
65 &mut self,
66 node_view: NodeView<CustomAttributeValues>,
67 _node: <Self::NodeDependencies as Dependancy>::ElementBorrowed<'a>,
68 parent: Option<<Self::ParentDependencies as Dependancy>::ElementBorrowed<'a>>,
69 _children: Vec<<Self::ChildDependencies as Dependancy>::ElementBorrowed<'a>>,
70 _context: &SendAnyMap,
71 ) -> bool {
72 if !node_view.node_type().is_visible_element() {
73 return false;
74 }
75
76 let mut viewports_state = ViewportState {
77 node_id: node_view.node_id(),
78 ..Default::default()
79 };
80
81 if let Some(attributes) = node_view.attributes() {
82 for attr in attributes {
83 viewports_state.parse_safe(attr)
84 }
85 }
86
87 if let Some((parent,)) = parent {
88 viewports_state.viewports.extend(parent.viewports.clone());
89 if parent.overflow == OverflowMode::Clip {
90 viewports_state.viewports.push(parent.node_id);
91 }
92 }
93
94 let changed = &viewports_state != self;
95 *self = viewports_state;
96 changed
97 }
98}