freya_core/states/
image.rs

1use std::sync::{
2    Arc,
3    Mutex,
4};
5
6use freya_native_core::{
7    attributes::AttributeName,
8    exports::shipyard::Component,
9    node::{
10        NodeType,
11        OwnedAttributeValue,
12    },
13    node_ref::NodeView,
14    prelude::{
15        AttributeMaskBuilder,
16        Dependancy,
17        NodeMaskBuilder,
18        State,
19    },
20    tags::TagName,
21    NodeId,
22    SendAnyMap,
23};
24use freya_native_core_macro::partial_derive_state;
25use torin::torin::Torin;
26
27use crate::{
28    custom_attributes::{
29        AttributesBytes,
30        CustomAttributeValues,
31        ImageReference,
32    },
33    dom::{
34        CompositorDirtyNodes,
35        ImageCacheKey,
36        ImagesCache,
37    },
38    parsing::{
39        Parse,
40        ParseAttribute,
41        ParseError,
42    },
43    values::{
44        AspectRatio,
45        ImageCover,
46        SamplingMode,
47    },
48};
49
50#[derive(Default, Debug, Clone, PartialEq, Component)]
51pub struct ImageState {
52    pub image_sampling: SamplingMode,
53    pub image_data: Option<AttributesBytes>,
54    pub image_cache_key: Option<ImageCacheKey>,
55    pub aspect_ratio: AspectRatio,
56    pub image_cover: ImageCover,
57    pub image_ref: Option<ImageReference>,
58}
59
60impl ParseAttribute for ImageState {
61    fn parse_attribute(
62        &mut self,
63        attr: freya_native_core::prelude::OwnedAttributeView<CustomAttributeValues>,
64    ) -> Result<(), ParseError> {
65        match attr.attribute {
66            AttributeName::Sampling => {
67                if let Some(value) = attr.value.as_text() {
68                    self.image_sampling = SamplingMode::parse(value)?;
69                }
70            }
71            AttributeName::ImageData => {
72                if let OwnedAttributeValue::Custom(CustomAttributeValues::Bytes(bytes)) = attr.value
73                {
74                    self.image_data = Some(bytes.clone());
75                }
76            }
77            AttributeName::ImageCacheKey => {
78                if let OwnedAttributeValue::Text(key) = attr.value {
79                    self.image_cache_key = Some(ImageCacheKey(key.clone()));
80                }
81            }
82            AttributeName::AspectRatio => {
83                if let Some(value) = attr.value.as_text() {
84                    self.aspect_ratio = AspectRatio::parse(value).map_err(|_| ParseError)?;
85                }
86            }
87            AttributeName::ImageCover => {
88                if let Some(value) = attr.value.as_text() {
89                    self.image_cover = ImageCover::parse(value).map_err(|_| ParseError)?;
90                }
91            }
92            AttributeName::ImageReference => {
93                if let OwnedAttributeValue::Custom(CustomAttributeValues::ImageReference(
94                    reference,
95                )) = attr.value
96                {
97                    self.image_ref = Some(reference.clone());
98                }
99            }
100            _ => {}
101        }
102
103        Ok(())
104    }
105}
106
107#[partial_derive_state]
108impl State<CustomAttributeValues> for ImageState {
109    type ParentDependencies = ();
110
111    type ChildDependencies = ();
112
113    type NodeDependencies = ();
114
115    const NODE_MASK: NodeMaskBuilder<'static> =
116        NodeMaskBuilder::new().with_attrs(AttributeMaskBuilder::Some(&[
117            AttributeName::Sampling,
118            AttributeName::ImageData,
119            AttributeName::ImageCacheKey,
120            AttributeName::AspectRatio,
121            AttributeName::ImageCover,
122            AttributeName::ImageReference,
123        ]));
124
125    fn allow_node(node_type: &NodeType<CustomAttributeValues>) -> bool {
126        node_type.tag() == Some(&TagName::Image)
127    }
128
129    fn update<'a>(
130        &mut self,
131        node_view: NodeView<CustomAttributeValues>,
132        _node: <Self::NodeDependencies as Dependancy>::ElementBorrowed<'a>,
133        _parent: Option<<Self::ParentDependencies as Dependancy>::ElementBorrowed<'a>>,
134        _children: Vec<<Self::ChildDependencies as Dependancy>::ElementBorrowed<'a>>,
135        context: &SendAnyMap,
136    ) -> bool {
137        let mut image = ImageState::default();
138
139        if let Some(attributes) = node_view.attributes() {
140            for attr in attributes {
141                image.parse_safe(attr)
142            }
143        }
144
145        let changed = &image != self;
146
147        if changed {
148            let compositor_dirty_nodes = context.get::<Arc<Mutex<CompositorDirtyNodes>>>().unwrap();
149            compositor_dirty_nodes
150                .lock()
151                .unwrap()
152                .invalidate(node_view.node_id());
153
154            if let Some(image_cache_key) = &self.image_cache_key {
155                let images_cache = context.get::<Arc<Mutex<ImagesCache>>>().unwrap();
156                images_cache.lock().unwrap().remove(image_cache_key);
157            }
158
159            let torin_layout = context.get::<Arc<Mutex<Torin<NodeId>>>>().unwrap();
160            torin_layout.lock().unwrap().invalidate(node_view.node_id());
161        }
162
163        *self = image;
164        changed
165    }
166}