1use floem_reactive::{Scope, UpdaterEffect};
2
3use crate::{
4 view::ViewId,
5 view::{IntoView, View},
6};
7
8pub struct DynamicView {
10 id: ViewId,
11 child_scope: Scope,
12}
13
14pub 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}