1use gpui::{
2 Anchor, App, Entity, IntoElement, ParentElement, Pixels, RenderOnce, Styled, Window, div,
3 prelude::FluentBuilder as _, px,
4};
5use std::time::Duration;
6
7use crate::monitor::FpsMonitor;
8
9const MARGIN: Pixels = px(12.);
11
12#[derive(IntoElement)]
34pub struct FpsOverlay {
35 monitor: Entity<FpsMonitor>,
36 anchor: Anchor,
37 frame_budget: Option<Duration>,
38}
39
40impl FpsOverlay {
41 pub fn new(monitor: &Entity<FpsMonitor>) -> Self {
42 Self {
43 monitor: monitor.clone(),
44 anchor: Anchor::TopRight,
45 frame_budget: None,
46 }
47 }
48
49 pub fn anchor(mut self, anchor: Anchor) -> Self {
51 self.anchor = anchor;
52 self
53 }
54
55 pub fn frame_budget(mut self, budget: Duration) -> Self {
57 self.frame_budget = Some(budget);
58 self
59 }
60}
61
62impl RenderOnce for FpsOverlay {
63 fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
64 if let Some(budget) = self.frame_budget {
65 self.monitor
66 .update(cx, |monitor, _| monitor.set_frame_budget(budget));
67 }
68 let margin = MARGIN;
69
70 div()
75 .absolute()
76 .flex()
77 .map(|this| match self.anchor {
78 Anchor::TopLeft => this.top(margin).left(margin),
79 Anchor::TopRight => this.top(margin).right(margin),
80 Anchor::BottomLeft => this.bottom(margin).left(margin),
81 Anchor::BottomRight => this.bottom(margin).right(margin),
82 Anchor::TopCenter => this.top(margin).left_0().right_0().justify_center(),
83 Anchor::BottomCenter => this.bottom(margin).left_0().right_0().justify_center(),
84 Anchor::LeftCenter => this.left(margin).top_0().bottom_0().items_center(),
85 Anchor::RightCenter => this.right(margin).top_0().bottom_0().items_center(),
86 })
87 .child(self.monitor)
88 }
89}