freya_core/states/
image.rs1use 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}