vizia_core/context/
resource.rs

1use hashbrown::{hash_map::Entry, HashSet};
2
3use vizia_storage::Tree;
4
5use crate::{
6    entity::Entity,
7    resource::{ImageOrSvg, ImageRetentionPolicy, ResourceManager, StoredImage},
8    style::Style,
9};
10
11use super::{Context, ContextProxy, EventProxy};
12
13/// A context used when loading images.
14pub struct ResourceContext<'a> {
15    pub(crate) current: Entity,
16    pub(crate) event_proxy: &'a Option<Box<dyn EventProxy>>,
17    pub(crate) resource_manager: &'a mut ResourceManager,
18    pub(crate) style: &'a mut Style,
19    pub(crate) tree: &'a Tree<Entity>,
20}
21
22impl<'a> ResourceContext<'a> {
23    /// Creates a new [ResourceContext].
24    pub(crate) fn new(cx: &'a mut Context) -> Self {
25        Self {
26            current: cx.current,
27            event_proxy: &cx.event_proxy,
28            resource_manager: &mut cx.resource_manager,
29            style: &mut cx.style,
30            tree: &cx.tree,
31        }
32    }
33
34    /// Executes the given closure in a spawned thread.
35    pub fn spawn<F>(&self, target: F)
36    where
37        F: 'static + Send + FnOnce(&mut ContextProxy),
38    {
39        let mut cxp = ContextProxy {
40            current: self.current,
41            event_proxy: self.event_proxy.as_ref().map(|p| p.make_clone()),
42        };
43
44        std::thread::spawn(move || target(&mut cxp));
45    }
46
47    /// Loads the provided image into the resource manager.
48    pub fn load_image(
49        &mut self,
50        path: String,
51        image: skia_safe::Image,
52        policy: ImageRetentionPolicy,
53    ) {
54        let id = if let Some(image_id) = self.resource_manager.image_ids.get(&path) {
55            *image_id
56        } else {
57            self.resource_manager.image_id_manager.create()
58        };
59
60        match self.resource_manager.images.entry(id) {
61            Entry::Occupied(mut occ) => {
62                occ.get_mut().image = ImageOrSvg::Image(image);
63                occ.get_mut().dirty = true;
64                occ.get_mut().retention_policy = policy;
65            }
66            Entry::Vacant(vac) => {
67                vac.insert(StoredImage {
68                    image: ImageOrSvg::Image(image),
69                    retention_policy: policy,
70                    used: true,
71                    dirty: false,
72                    observers: HashSet::new(),
73                });
74            }
75        }
76        self.style.needs_relayout();
77    }
78}