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
31struct SuspendedComposers(Vec<Rc<ComposerCore>>);
32
33impl Drop for SuspendedComposers {
34 fn drop(&mut self) {
35 let suspended = std::mem::take(&mut self.0);
36 COMPOSER_STACK.with(|stack| *stack.borrow_mut() = suspended);
37 }
38}
39
40pub(crate) fn without_composer<R>(f: impl FnOnce() -> R) -> R {
41 let _suspended =
42 SuspendedComposers(COMPOSER_STACK.with(|stack| std::mem::take(&mut *stack.borrow_mut())));
43 f()
44}
45
46pub fn with_composer<R>(f: impl FnOnce(&Composer) -> R) -> R {
51 COMPOSER_STACK.with(|stack| {
52 let core = stack
53 .borrow()
54 .last()
55 .expect("with_composer: no active composer")
56 .clone();
57 let composer = Composer::from_core(core);
58 f(&composer)
59 })
60}
61
62pub fn current_composer() -> Option<Composer> {
64 COMPOSER_STACK.with(|stack| {
65 let core = stack.borrow().last()?.clone();
66 Some(Composer::from_core(core))
67 })
68}
69
70pub fn note_nested_slots_host(host: &std::rc::Rc<crate::SlotsHost>) {
71 let Some(composer) = current_composer() else {
72 return;
73 };
74 let holder = composer.active_slots_host();
75 if std::rc::Rc::ptr_eq(&holder, host) {
76 return;
77 }
78 holder.note_nested_host(host);
79}
80
81pub fn try_with_composer<R>(f: impl FnOnce(&Composer) -> R) -> Option<R> {
84 current_composer().map(|composer| f(&composer))
85}