1use gpui_kit::{
4 AnyElement, App, Bounds, Element, ElementId, GlobalElementId, InspectorElementId, IntoElement,
5 LayoutId, Pixels, SharedString, Window,
6};
7
8use super::Theme;
9
10pub struct ThemeScope {
20 key: SharedString,
21 child: AnyElement,
22}
23
24impl ThemeScope {
25 pub fn new(key: impl Into<SharedString>, child: impl IntoElement) -> Self {
28 Self {
29 key: key.into(),
30 child: child.into_any_element(),
31 }
32 }
33}
34
35fn within<R>(key: &str, cx: &mut App, f: impl FnOnce(&mut App) -> R) -> R {
38 let theme = Theme::global(cx);
39 let index = theme.scope_index(key);
40 let outer = theme
41 .active_scope
42 .replace(index.or(theme.active_scope.get()));
43 let result = f(cx);
44 Theme::global(cx).active_scope.set(outer);
45 result
46}
47
48impl IntoElement for ThemeScope {
49 type Element = Self;
50
51 fn into_element(self) -> Self::Element {
52 self
53 }
54}
55
56impl Element for ThemeScope {
57 type RequestLayoutState = ();
58 type PrepaintState = ();
59
60 fn id(&self) -> Option<ElementId> {
61 None
62 }
63
64 fn source_location(&self) -> Option<&'static core::panic::Location<'static>> {
65 None
66 }
67
68 fn request_layout(
69 &mut self,
70 _id: Option<&GlobalElementId>,
71 _inspector_id: Option<&InspectorElementId>,
72 window: &mut Window,
73 cx: &mut App,
74 ) -> (LayoutId, ()) {
75 let child = &mut self.child;
76 let layout = within(&self.key, cx, |cx| child.request_layout(window, cx));
77 (layout, ())
78 }
79
80 fn prepaint(
81 &mut self,
82 _id: Option<&GlobalElementId>,
83 _inspector_id: Option<&InspectorElementId>,
84 _bounds: Bounds<Pixels>,
85 _request_layout: &mut (),
86 window: &mut Window,
87 cx: &mut App,
88 ) {
89 let child = &mut self.child;
90 within(&self.key, cx, |cx| child.prepaint(window, cx));
91 }
92
93 fn paint(
94 &mut self,
95 _id: Option<&GlobalElementId>,
96 _inspector_id: Option<&InspectorElementId>,
97 _bounds: Bounds<Pixels>,
98 _request_layout: &mut (),
99 _prepaint: &mut (),
100 window: &mut Window,
101 cx: &mut App,
102 ) {
103 let child = &mut self.child;
104 within(&self.key, cx, |cx| child.paint(window, cx));
105 }
106}