use gpui_kit::{
AnyElement, App, Bounds, Element, ElementId, GlobalElementId, InspectorElementId, IntoElement,
LayoutId, Pixels, SharedString, Window,
};
use super::Theme;
pub struct ThemeScope {
key: SharedString,
child: AnyElement,
}
impl ThemeScope {
pub fn new(key: impl Into<SharedString>, child: impl IntoElement) -> Self {
Self {
key: key.into(),
child: child.into_any_element(),
}
}
}
fn within<R>(key: &str, cx: &mut App, f: impl FnOnce(&mut App) -> R) -> R {
let theme = Theme::global(cx);
let index = theme.scope_index(key);
let outer = theme
.active_scope
.replace(index.or(theme.active_scope.get()));
let result = f(cx);
Theme::global(cx).active_scope.set(outer);
result
}
impl IntoElement for ThemeScope {
type Element = Self;
fn into_element(self) -> Self::Element {
self
}
}
impl Element for ThemeScope {
type RequestLayoutState = ();
type PrepaintState = ();
fn id(&self) -> Option<ElementId> {
None
}
fn source_location(&self) -> Option<&'static core::panic::Location<'static>> {
None
}
fn request_layout(
&mut self,
_id: Option<&GlobalElementId>,
_inspector_id: Option<&InspectorElementId>,
window: &mut Window,
cx: &mut App,
) -> (LayoutId, ()) {
let child = &mut self.child;
let layout = within(&self.key, cx, |cx| child.request_layout(window, cx));
(layout, ())
}
fn prepaint(
&mut self,
_id: Option<&GlobalElementId>,
_inspector_id: Option<&InspectorElementId>,
_bounds: Bounds<Pixels>,
_request_layout: &mut (),
window: &mut Window,
cx: &mut App,
) {
let child = &mut self.child;
within(&self.key, cx, |cx| child.prepaint(window, cx));
}
fn paint(
&mut self,
_id: Option<&GlobalElementId>,
_inspector_id: Option<&InspectorElementId>,
_bounds: Bounds<Pixels>,
_request_layout: &mut (),
_prepaint: &mut (),
window: &mut Window,
cx: &mut App,
) {
let child = &mut self.child;
within(&self.key, cx, |cx| child.paint(window, cx));
}
}