floem/views/
value_container.rs1use std::any::Any;
2
3use floem_reactive::{Effect, RwSignal, SignalGet, SignalUpdate, UpdaterEffect};
4
5use crate::{
6 context::UpdateCx,
7 id::ViewId,
8 view::{IntoView, View},
9};
10
11pub struct ValueContainer<T> {
13 id: ViewId,
14 on_update: Option<Box<dyn Fn(T)>>,
15}
16
17pub fn create_value_container_signals<T>(
23 producer: impl Fn() -> T + 'static,
24) -> (RwSignal<T>, RwSignal<T>)
25where
26 T: Clone + 'static,
27{
28 let initial_value = producer();
29
30 let inbound_signal = RwSignal::new(initial_value.clone());
31 Effect::new(move |_| {
32 let checked = producer();
33 inbound_signal.set(checked);
34 });
35
36 let outbound_signal = RwSignal::new(initial_value.clone());
37 Effect::new(move |_| {
38 let checked = outbound_signal.get();
39 inbound_signal.set(checked);
40 });
41
42 (inbound_signal, outbound_signal)
43}
44
45pub fn value_container<T: 'static, V: IntoView + 'static>(
51 child: V,
52 value_update: impl Fn() -> T + 'static,
53) -> ValueContainer<T> {
54 let id = ViewId::new();
55 let child = child.into_view();
56 id.set_children([child]);
57 UpdaterEffect::new(value_update, move |new_value| id.update_state(new_value));
58 ValueContainer {
59 id,
60 on_update: None,
61 }
62}
63
64impl<T> ValueContainer<T> {
65 pub fn on_update(mut self, action: impl Fn(T) + 'static) -> Self {
66 self.on_update = Some(Box::new(action));
67 self
68 }
69}
70
71impl<T: 'static> View for ValueContainer<T> {
72 fn id(&self) -> ViewId {
73 self.id
74 }
75
76 fn update(&mut self, _cx: &mut UpdateCx, state: Box<dyn Any>) {
77 if let Ok(state) = state.downcast::<T>() {
78 if let Some(on_update) = self.on_update.as_ref() {
79 on_update(*state);
80 }
81 }
82 }
83}