ferroui_base/controls/
child_name_scope.rs1use super::{INameScope, NameScope, NameScopeError, NameScopeRef};
2use crate::utilities::{SynchronousCompletionAsyncResult, SynchronousCompletionAsyncResultSource};
3use crate::{FerroObject, Ref};
4
5type FindResult = Option<Ref<FerroObject>>;
6
7pub struct ChildNameScope {
10 parent_scope: NameScopeRef,
11 inner: NameScope,
12}
13
14impl ChildNameScope {
15 pub fn new(parent_scope: NameScopeRef) -> Self {
16 Self { parent_scope, inner: NameScope::new() }
17 }
18
19 fn do_find_async(&self, name: &str) -> SynchronousCompletionAsyncResult<FindResult> {
20 let src = SynchronousCompletionAsyncResultSource::<FindResult>::new();
21
22 fn parent_search(
23 parent_scope: &NameScopeRef,
24 name: &str,
25 src: SynchronousCompletionAsyncResultSource<FindResult>,
26 ) {
27 let parent_search = parent_scope.find_async(name);
28 if parent_search.is_completed() {
29 src.set_result(parent_search.get_result());
30 } else {
31 let search = parent_search.clone();
32 parent_search.on_completed(move || src.set_result(search.get_result()));
33 }
34 }
35
36 if !self.inner.is_completed() {
37 let inner_search = self.inner.find_async(name);
39 let search = inner_search.clone();
40 let src = src.clone();
41 let parent_scope = self.parent_scope.clone();
42 let name = name.to_string();
43 inner_search.on_completed(move || {
44 let value = search.get_result();
45 if value.is_some() {
46 src.set_result(value);
47 } else {
48 parent_search(&parent_scope, &name, src);
49 }
50 });
51 } else {
52 parent_search(&self.parent_scope, name, src.clone());
53 }
54
55 src.async_result()
56 }
57}
58
59impl INameScope for ChildNameScope {
60 fn try_register(&self, name: &str, element: Ref<FerroObject>) -> Result<(), NameScopeError> {
61 self.inner.try_register(name, element)
62 }
63
64 fn find_async(&self, name: &str) -> SynchronousCompletionAsyncResult<FindResult> {
65 let found = self.find(name);
66 if found.is_some() {
67 return SynchronousCompletionAsyncResult::new(found);
68 }
69 if self.is_completed() {
71 return SynchronousCompletionAsyncResult::new(None);
72 }
73 self.do_find_async(name)
74 }
75
76 fn find(&self, name: &str) -> FindResult {
77 let found = self.inner.find(name);
78 if found.is_some() {
79 return found;
80 }
81 if self.inner.is_completed() {
82 return self.parent_scope.find(name);
83 }
84 None
85 }
86
87 fn complete(&self) {
88 self.inner.complete()
89 }
90
91 fn is_completed(&self) -> bool {
92 self.inner.is_completed() && self.parent_scope.is_completed()
93 }
94
95 fn attached_to(&self, owner: &Ref<FerroObject>) {
96 self.inner.attached_to(owner)
97 }
98
99 fn detached_from(&self, owner: &Ref<FerroObject>) {
100 self.inner.detached_from(owner)
101 }
102}