vizia_core/systems/
binding.rs
1use crate::{binding::StoreId, model::ModelOrView, prelude::*};
2use hashbrown::{HashMap, HashSet};
3use std::any::TypeId;
4
5pub(crate) fn binding_system(cx: &mut Context) {
6 let mut observers: HashMap<Entity, (Entity, TypeId, StoreId)> = HashMap::new();
7
8 for (entity, stores) in cx.stores.iter_mut() {
9 for (store_id, store) in stores.iter() {
10 let model_id = store.source();
11
12 observers.extend(
13 store.observers().iter().map(|e| (*e, (*entity, model_id, store_id.clone()))),
14 );
15 }
16 }
17
18 if !observers.is_empty() {
19 let ordered_observers = cx
21 .tree
22 .into_iter()
23 .filter_map(|ent| observers.get(&ent).map(|e| (ent, e.clone())))
24 .collect::<Vec<_>>();
25
26 let mut updated_stores: HashSet<StoreId> = HashSet::new();
27
28 for (observer, (source, model_id, store_id)) in ordered_observers.into_iter() {
30 if !cx.entity_manager.is_alive(observer) {
32 continue;
33 }
34
35 if updated_stores.contains(&store_id) {
36 update_binding(cx, observer);
37 } else if let Some(store) =
38 cx.stores.get_mut(&source).and_then(|stores| stores.get_mut(&store_id))
39 {
40 let view = cx
41 .views
42 .get(&source)
43 .filter(|view| view.id() == model_id)
44 .map(|view| ModelOrView::View(view.as_ref()));
45
46 let model_or_view = if view.is_some() {
47 view
48 } else {
49 cx.models
50 .get(&source)
51 .and_then(|models| models.get(&model_id))
52 .map(|model| ModelOrView::Model(model.as_ref()))
53 };
54
55 if let Some(model_or_view) = model_or_view {
56 if store.update(model_or_view) {
57 updated_stores.insert(store_id);
58 update_binding(cx, observer);
59 }
60 }
61 }
62 }
63 }
64}
65
66fn update_binding(cx: &mut Context, observer: Entity) {
67 if let Some(mut binding) = cx.bindings.remove(&observer) {
68 cx.with_current(observer, |cx| {
69 binding.update(cx);
70 });
71 cx.bindings.insert(observer, binding);
72 }
73}