Skip to main content

aetna_core/state/
widget_state.rs

1//! Typed widget-state bucket accessors.
2
3use std::any::TypeId;
4
5use super::{UiState, WidgetState};
6
7impl UiState {
8    /// Look up the widget state of type `T` for `id`. Returns `None` if
9    /// no entry exists or the entry was inserted as a different type.
10    pub fn widget_state<T: WidgetState>(&self, id: &str) -> Option<&T> {
11        self.widget_states
12            .entries
13            .get(&(id.to_string(), TypeId::of::<T>()))
14            .and_then(|b| b.as_any().downcast_ref::<T>())
15    }
16
17    /// Get a mutable reference to the widget state of type `T` for
18    /// `id`, inserting `T::default()` if no entry exists. Use this in
19    /// the build closure of a stateful widget so the first call after
20    /// the node enters the tree produces a fresh state, and every
21    /// subsequent call returns the live one.
22    pub fn widget_state_mut<T: WidgetState + Default>(&mut self, id: &str) -> &mut T {
23        let key = (id.to_string(), TypeId::of::<T>());
24        let entry = self
25            .widget_states
26            .entries
27            .entry(key)
28            .or_insert_with(|| Box::new(T::default()));
29        entry
30            .as_any_mut()
31            .downcast_mut::<T>()
32            .expect("widget_state TypeId match guarantees downcast succeeds")
33    }
34
35    /// Drop the widget state of type `T` for `id`, if any.
36    pub fn clear_widget_state<T: WidgetState>(&mut self, id: &str) {
37        self.widget_states
38            .entries
39            .remove(&(id.to_string(), TypeId::of::<T>()));
40    }
41
42    /// Iterate `(id, type_name, debug_summary)` for every live widget
43    /// state. Used by the tree dump to surface per-widget state in the
44    /// agent loop's view.
45    pub fn widget_state_summary(&self, id: &str) -> Vec<(&'static str, String)> {
46        self.widget_states
47            .entries
48            .iter()
49            .filter(|((node_id, _), _)| node_id == id)
50            .map(|(_, b)| (b.type_name(), b.debug_summary()))
51            .collect()
52    }
53}