use std::cell::RefCell;
use std::rc::Rc;
use crate::{Composer, ComposerCore};
thread_local! {
static COMPOSER_STACK: RefCell<Vec<Rc<ComposerCore>>> = const { RefCell::new(Vec::new()) };
}
#[must_use = "ComposerScopeGuard pops the composer stack on drop"]
pub struct ComposerScopeGuard;
impl Drop for ComposerScopeGuard {
fn drop(&mut self) {
COMPOSER_STACK.with(|stack| {
let mut stack = stack.borrow_mut();
stack.pop();
});
}
}
pub fn enter(composer: &Composer) -> ComposerScopeGuard {
COMPOSER_STACK.with(|stack| {
stack.borrow_mut().push(composer.clone_core());
});
ComposerScopeGuard
}
pub fn with_composer<R>(f: impl FnOnce(&Composer) -> R) -> R {
COMPOSER_STACK.with(|stack| {
let core = stack
.borrow()
.last()
.expect("with_composer: no active composer")
.clone();
let composer = Composer::from_core(core);
f(&composer)
})
}
pub fn try_with_composer<R>(f: impl FnOnce(&Composer) -> R) -> Option<R> {
COMPOSER_STACK.with(|stack| {
let core = stack.borrow().last()?.clone();
let composer = Composer::from_core(core);
Some(f(&composer))
})
}