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