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