cranpose_core/
composer_context.rs1use std::{cell::RefCell, rc::Rc};
2
3use crate::{Composer, ComposerCore};
4
5thread_local! {
7 static COMPOSER_STACK: RefCell<Vec<Rc<ComposerCore>>> = const { RefCell::new(Vec::new()) };
8}
9
10#[must_use = "ComposerScopeGuard pops the composer stack on drop"]
12pub struct ComposerScopeGuard;
13
14impl Drop for ComposerScopeGuard {
15 fn drop(&mut self) {
16 COMPOSER_STACK.with(|stack| {
17 let mut stack = stack.borrow_mut();
18 stack.pop();
19 });
20 }
21}
22
23pub fn enter(composer: &Composer) -> ComposerScopeGuard {
26 COMPOSER_STACK.with(|stack| {
27 stack.borrow_mut().push(composer.clone_core());
28 });
29 ComposerScopeGuard
30}
31
32pub fn with_composer<R>(f: impl FnOnce(&Composer) -> R) -> R {
37 COMPOSER_STACK.with(|stack| {
38 let core = stack
39 .borrow()
40 .last()
41 .expect("with_composer: no active composer")
42 .clone();
43 let composer = Composer::from_core(core);
44 f(&composer)
45 })
46}
47
48pub fn current_composer() -> Option<Composer> {
50 COMPOSER_STACK.with(|stack| {
51 let core = stack.borrow().last()?.clone();
52 Some(Composer::from_core(core))
53 })
54}
55
56pub fn note_nested_slots_host(host: &std::rc::Rc<crate::SlotsHost>) {
57 let Some(composer) = current_composer() else {
58 return;
59 };
60 let holder = composer.active_slots_host();
61 if std::rc::Rc::ptr_eq(&holder, host) {
62 return;
63 }
64 holder.note_nested_host(host);
65}
66
67pub fn try_with_composer<R>(f: impl FnOnce(&Composer) -> R) -> Option<R> {
70 current_composer().map(|composer| f(&composer))
71}