1use fret_core::{AppWindowId, Rect, Scene, UiServices};
2
3use crate::UiHost;
4use crate::tree::UiTree;
5
6pub struct UiFrameCx<'a, H: UiHost> {
7 pub ui: &'a mut UiTree<H>,
8 pub app: &'a mut H,
9 pub services: &'a mut dyn UiServices,
10 pub window: AppWindowId,
11 pub bounds: Rect,
12 pub scale_factor: f32,
13}
14
15pub type UiFrameContext<'a, H> = UiFrameCx<'a, H>;
16
17impl<'a, H: UiHost> UiFrameCx<'a, H> {
18 pub fn new(
19 ui: &'a mut UiTree<H>,
20 app: &'a mut H,
21 services: &'a mut dyn UiServices,
22 window: AppWindowId,
23 bounds: Rect,
24 scale_factor: f32,
25 ) -> Self {
26 Self {
27 ui,
28 app,
29 services,
30 window,
31 bounds,
32 scale_factor,
33 }
34 }
35
36 pub fn layout_all(&mut self) {
37 let span = tracing::trace_span!(
38 "fret_ui.layout_all",
39 window = ?self.window,
40 frame_id = self.app.frame_id().0,
41 );
42 let _guard = span.enter();
43 self.ui
44 .layout_all(self.app, self.services, self.bounds, self.scale_factor);
45
46 let occlusion_changed = self.app.with_global_mut_untracked(
47 crate::elements::ElementRuntime::new,
48 |runtime, _app| {
49 runtime
50 .for_window(self.window)
51 .is_some_and(|state| state.occlusion_insets_changed_this_frame())
52 },
53 );
54 if occlusion_changed && let Some(focus) = self.ui.focus() {
55 self.ui.scroll_node_into_view(self.app, focus);
56 }
57 }
58
59 pub fn paint_all(&mut self, scene: &mut Scene) {
60 let span = tracing::trace_span!(
61 "fret_ui.paint_all",
62 window = ?self.window,
63 frame_id = self.app.frame_id().0,
64 );
65 let _guard = span.enter();
66 self.ui.paint_all(
67 self.app,
68 self.services,
69 self.bounds,
70 scene,
71 self.scale_factor,
72 );
73 }
74}