vertigo/computed/dependencies/
mod.rs

1use std::collections::BTreeSet;
2
3use crate::{Context, GraphId};
4
5use super::graph_id::GraphIdKind;
6
7mod external_connections;
8mod graph;
9mod graph_connections;
10mod graph_one_to_many;
11pub mod hook;
12mod refresh;
13mod transaction_state;
14
15use {graph::Graph, hook::Hooks, transaction_state::TransactionState};
16
17/// A graph of values and clients that can automatically compute what to refresh after one value change.
18///
19/// A [Driver](struct.Driver.html) object wraps dependency graph, so you do not need to use this under normal circumstances.
20///
21/// - Dependency graph holds values, computed values ([computeds](struct.Computed.html)) and clients (render functions).
22/// - Upon changing some value all dependent computeds get computed, and all dependent clients get rendered.
23/// - Render function (a component) takes a computed state provided by the graph and returns a rendered element ([DomElement](struct.DomElement.html)).
24/// - Upon change in VDOM the real DOM is also updated.
25/// - Components can provide the DOM with functions that get fired on events like [on_click](struct.DomElement.html#structfield.on_click), which may modify the state, thus triggering necessary computing once again.
26pub struct Dependencies {
27    pub(crate) graph: Graph,
28    transaction_state: TransactionState,
29    pub(crate) hooks: Hooks,
30}
31
32impl Default for Dependencies {
33    fn default() -> Self {
34        Self {
35            graph: Graph::new(),
36            transaction_state: TransactionState::new(),
37            hooks: Hooks::new(),
38        }
39    }
40}
41
42impl Dependencies {
43    pub fn transaction<R, F: FnOnce(&Context) -> R>(&self, func: F) -> R {
44        self.transaction_state.up();
45
46        let context = Context::new();
47        let result = func(&context);
48        let _ = context;
49
50        let edges_values = self.transaction_state.down();
51
52        let Some(client_ids) = edges_values else {
53            return result;
54        };
55
56        for id in client_ids {
57            self.graph.refresh.refresh(&id);
58        }
59
60        self.transaction_state.move_to_idle();
61        self.hooks.fire_end();
62
63        result
64    }
65
66    pub(crate) fn report_set(&self, value_id: GraphId) {
67        let mut client = BTreeSet::new();
68
69        for id in self.graph.connections.get_all_deps(value_id) {
70            match id.get_type() {
71                GraphIdKind::Value => {
72                    unreachable!();
73                }
74                GraphIdKind::Computed => {
75                    self.graph.refresh.clear_cache(&id);
76                }
77                GraphIdKind::Client => {
78                    client.insert(id);
79                }
80            }
81        }
82
83        self.transaction_state.add_clients_to_refresh(client);
84    }
85}