Skip to main content

floem/views/
dyn_view.rs

1use floem_reactive::{Scope, UpdaterEffect};
2
3use crate::{
4    view::ViewId,
5    view::{IntoView, View},
6};
7
8/// A container for a dynamically updating View. See [`dyn_view`]
9pub struct DynamicView {
10    id: ViewId,
11    child_scope: Scope,
12}
13
14/// A container for a dynamically updating View
15pub fn dyn_view<VF, IV>(view_fn: VF) -> DynamicView
16where
17    VF: Fn() -> IV + 'static,
18    IV: IntoView,
19{
20    let id = ViewId::new();
21    let view_fn = Box::new(Scope::current().enter_child(move |_| view_fn().into_any()));
22
23    let (child, child_scope) = UpdaterEffect::new(
24        move || view_fn(()),
25        move |(new_view, new_scope)| {
26            let current_children = id.children();
27            id.set_children([new_view]);
28            id.update_state((current_children, new_scope));
29        },
30    );
31
32    id.set_children([child]);
33    DynamicView { id, child_scope }
34}
35
36impl View for DynamicView {
37    fn id(&self) -> ViewId {
38        self.id
39    }
40
41    fn update(&mut self, cx: &mut crate::context::UpdateCx, state: Box<dyn std::any::Any>) {
42        if let Ok(val) = state.downcast::<(Vec<ViewId>, Scope)>() {
43            let old_child_scope = self.child_scope;
44            let (old_children, child_scope) = *val;
45            self.child_scope = child_scope;
46            for child in old_children {
47                cx.window_state.remove_view(child);
48            }
49            old_child_scope.dispose();
50            self.id.request_all();
51        }
52    }
53}