ferroui_view/
control_flow.rs1use crate::element::{AnyValueEq, DynamicChildren, Element, IntoElement, Key};
11use crate::reactive::{memo, signal, Signal};
12use ferroui_base::{ObjectType, Ref};
13use std::rc::Rc;
14
15pub fn for_each<T, I, K, E>(
24 each: impl Fn() -> I + 'static,
25 key: impl Fn(&T) -> K + 'static,
26 view: impl Fn(T) -> E + 'static,
27) -> Element
28where
29 I: IntoIterator<Item = T>,
30 T: Clone + PartialEq + 'static,
31 K: Into<Key>,
32 E: IntoElement,
33{
34 let view = Rc::new(view);
35 Element::Dynamic(DynamicChildren {
36 render: Rc::new(move || {
37 each()
38 .into_iter()
39 .map(|item| {
40 let key = key(&item).into();
41 let value: Rc<dyn AnyValueEq> = Rc::new(item.clone());
42 let view = view.clone();
43 let render: Rc<dyn Fn() -> Element> = Rc::new(move || view(item.clone()).into_element());
44 (Some(key), Some(value), render)
45 })
46 .collect()
47 }),
48 })
49}
50
51pub fn show<E: IntoElement>(when: impl Fn() -> bool + 'static, then: impl Fn() -> E + 'static) -> Element {
54 show_else(when, then, || Element::Empty)
55}
56
57pub fn show_else<E: IntoElement, O: IntoElement>(
60 when: impl Fn() -> bool + 'static,
61 then: impl Fn() -> E + 'static,
62 otherwise: impl Fn() -> O + 'static,
63) -> Element {
64 let condition = memo(move |_| when());
65 let then: Rc<dyn Fn() -> Element> = Rc::new(move || then().into_element());
66 let otherwise: Rc<dyn Fn() -> Element> = Rc::new(move || otherwise().into_element());
67 Element::Dynamic(DynamicChildren {
68 render: Rc::new(move || {
69 let render = if condition.get() { then.clone() } else { otherwise.clone() };
70 vec![(None, None, render)]
71 }),
72 })
73}
74
75pub fn dynamic<E: IntoElement>(render: impl Fn() -> E + 'static) -> Element {
80 Element::Dynamic(DynamicChildren {
81 render: Rc::new(move || {
82 let element = render().into_element();
83 let children = match element {
84 Element::Fragment(items) => items,
85 Element::Empty => Vec::new(),
86 element => vec![element],
87 };
88 children
89 .into_iter()
90 .map(|child| {
91 let key = child.key().cloned();
92 let render: Rc<dyn Fn() -> Element> = Rc::new(move || child.clone());
93 (key, None, render)
94 })
95 .collect()
96 }),
97 })
98}
99
100pub struct NodeRef<T: ObjectType> {
103 control: Signal<Option<Ref<T>>>,
104}
105
106impl<T: ObjectType> Clone for NodeRef<T> {
107 fn clone(&self) -> Self {
108 *self
109 }
110}
111
112impl<T: ObjectType> Copy for NodeRef<T> {}
113
114impl<T: ObjectType> NodeRef<T> {
115 pub fn new() -> Self {
117 Self { control: signal(None) }
118 }
119
120 pub fn get(&self) -> Option<Ref<T>> {
122 self.control.get()
123 }
124
125 pub fn get_untracked(&self) -> Option<Ref<T>> {
127 self.control.get_untracked()
128 }
129
130 pub(crate) fn set(&self, control: Ref<T>) {
131 self.control.set(Some(control));
132 }
133}
134
135impl<T: ObjectType> Default for NodeRef<T> {
136 fn default() -> Self {
137 Self::new()
138 }
139}