use gpui_kit::{
AnyElement, App, AppContext as _, Context, Div, Entity, FocusHandle, InteractiveElement as _,
IntoElement, ParentElement as _, Render, Stateful, Styled as _, Subscription, Window,
base::{Root, RootPlugin, TooltipOverlay},
div,
};
use crate::{ActiveTheme as _, Theme, TooltipHost};
pub(crate) fn init(cx: &mut App) {
Root::register_plugin(cx, RootLayer::new);
}
pub(crate) struct RootLayer {
focus: FocusHandle,
tooltip_overlay: Entity<TooltipOverlay>,
_appearance: Subscription,
}
impl RootLayer {
fn new(window: &mut Window, cx: &mut Context<Self>) -> Self {
let tooltip_overlay =
cx.new(|_| TooltipOverlay::new().render_with(crate::tooltip::render_surface));
TooltipHost::register(window, &tooltip_overlay, cx);
Theme::sync_system_appearance(Some(window), cx);
let appearance = window.observe_window_appearance(|window, cx| {
Theme::sync_system_appearance(Some(window), cx);
});
Self {
focus: cx.focus_handle(),
tooltip_overlay,
_appearance: appearance,
}
}
}
impl RootPlugin for RootLayer {
fn prepare(&mut self, window: &mut Window, cx: &mut Context<Self>) {
window.set_rem_size(Theme::global(cx).ui_font_size);
if window.focused(cx).is_none() {
window.focus(&self.focus, cx);
}
}
fn style(&self, surface: &mut Stateful<Div>, _: &mut Window, _: &mut App) {
let taken = std::mem::replace(surface, div().id("placeholder"));
*surface = taken.track_focus(&self.focus);
}
fn decorate(
&self,
surface: AnyElement,
_: &Root,
_: &mut Window,
cx: &mut App,
) -> impl IntoElement {
let tokens = cx.theme();
div()
.size_full()
.font_family(tokens.font_family().clone())
.bg(tokens.background())
.text_color(tokens.foreground())
.child(surface)
}
}
impl Render for RootLayer {
fn render(&mut self, _: &mut Window, _: &mut Context<Self>) -> impl IntoElement {
self.tooltip_overlay.clone()
}
}