vizia_core/binding/
store.rs

1use hashbrown::HashSet;
2use std::any::TypeId;
3use std::hash::Hash;
4
5use crate::{model::ModelOrView, prelude::*};
6
7#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
8pub enum StoreId {
9    Source(TypeId),
10    Index(TypeId, usize),
11    Recursive(Box<(StoreId, StoreId)>),
12    Map(u64),
13}
14
15pub(crate) trait Store {
16    /// Updates the model data, returning true if the data changed.
17    fn update(&mut self, model: ModelOrView) -> bool;
18    /// Returns the set of observers for the store.
19    fn observers(&self) -> &HashSet<Entity>;
20    /// Adds an observer to the store.
21    fn add_observer(&mut self, observer: Entity);
22    /// Removes an observer from the store.
23    fn remove_observer(&mut self, observer: &Entity);
24    /// Returns the number of obersers for the store.
25    fn num_observers(&self) -> usize;
26    /// Returns true if the model or view is the source of the store.
27    fn source(&self) -> TypeId;
28
29    #[cfg(debug_assertions)]
30    fn name(&self) -> String;
31}
32
33pub(crate) struct BasicStore<L: Lens, T> {
34    pub lens: L,
35    pub old: Option<T>,
36    pub observers: HashSet<Entity>,
37}
38
39impl<L> Store for BasicStore<L, L::Target>
40where
41    L: Lens<Target: Data>,
42{
43    fn source(&self) -> TypeId {
44        TypeId::of::<L::Source>()
45    }
46
47    fn update(&mut self, model: ModelOrView) -> bool {
48        let Some(data) = model.downcast_ref::<L::Source>() else { return false };
49        let Some(new_data) = self.lens.view(data) else { return false };
50
51        if matches!(&self.old, Some(old) if old.same(&new_data)) {
52            return false;
53        }
54
55        self.old = Some(new_data.into_owned());
56
57        true
58    }
59
60    fn observers(&self) -> &HashSet<Entity> {
61        &self.observers
62    }
63
64    fn add_observer(&mut self, observer: Entity) {
65        self.observers.insert(observer);
66    }
67
68    fn remove_observer(&mut self, observer: &Entity) {
69        self.observers.remove(observer);
70    }
71
72    fn num_observers(&self) -> usize {
73        self.observers.len()
74    }
75
76    #[cfg(debug_assertions)]
77    fn name(&self) -> String {
78        format!("{:?}", self.lens)
79    }
80}