ferroui_base/controls/
name_scope_locator.rs1use super::NameScopeRef;
2use crate::reactive::{Disposable, IDisposable, IObservable, IObserver};
3use crate::utilities::SynchronousCompletionAsyncResult;
4use crate::{FerroObject, Ref};
5use std::cell::RefCell;
6use std::rc::Rc;
7
8type FindResult = Option<Ref<FerroObject>>;
9
10pub struct NameScopeLocator;
12
13impl NameScopeLocator {
14 pub fn track(scope: &NameScopeRef, name: &str) -> Rc<dyn IObservable<FindResult>> {
18 let task = scope.find_async(name);
19 let state = if task.is_completed() { State::Value(task.get_result()) } else { State::Pending(task) };
20 Rc::new(NeverEndingSynchronousCompletionAsyncResultObservable { state: RefCell::new(state) })
21 }
22}
23
24enum State {
25 Value(FindResult),
26 Pending(SynchronousCompletionAsyncResult<FindResult>),
27}
28
29struct NeverEndingSynchronousCompletionAsyncResultObservable {
32 state: RefCell<State>,
33}
34
35impl IObservable<FindResult> for NeverEndingSynchronousCompletionAsyncResultObservable {
36 fn subscribe(&self, observer: Rc<dyn IObserver<FindResult>>) -> Rc<dyn IDisposable> {
37 let pending = {
38 let mut state = self.state.borrow_mut();
39 if let State::Pending(task) = &*state {
40 if task.is_completed() {
41 let result = task.get_result();
42 *state = State::Value(result);
43 }
44 }
45 match &*state {
46 State::Pending(task) => Ok(task.clone()),
47 State::Value(value) => Err(value.clone()),
48 }
49 };
50
51 match pending {
52 Ok(task) => {
53 let result = task.clone();
54 task.on_completed(move || observer.on_next(result.get_result()));
55 }
56 Err(value) => observer.on_next(value),
57 }
58
59 Disposable::empty()
60 }
61}