title_bar.rs

 1use std::marker::PhantomData;
 2use std::sync::atomic::AtomicBool;
 3use std::sync::Arc;
 4
 5use crate::prelude::*;
 6use crate::{
 7    static_players_with_call_status, theme, Avatar, Button, Icon, IconButton, IconColor,
 8    PlayerStack, ToolDivider, TrafficLights,
 9};
10
11#[derive(Element)]
12pub struct TitleBar<V: 'static> {
13    view_type: PhantomData<V>,
14    is_active: Arc<AtomicBool>,
15}
16
17impl<V: 'static> TitleBar<V> {
18    pub fn new(cx: &mut ViewContext<V>) -> Self {
19        let is_active = Arc::new(AtomicBool::new(true));
20        let active = is_active.clone();
21
22        cx.observe_window_activation(move |_, is_active, cx| {
23            active.store(is_active, std::sync::atomic::Ordering::SeqCst);
24            cx.notify();
25        })
26        .detach();
27
28        Self {
29            view_type: PhantomData,
30            is_active,
31        }
32    }
33
34    fn render(&mut self, _: &mut V, cx: &mut ViewContext<V>) -> impl IntoElement<V> {
35        let theme = theme(cx);
36        let has_focus = cx.window_is_active();
37
38        let player_list = static_players_with_call_status().into_iter();
39
40        div()
41            .flex()
42            .items_center()
43            .justify_between()
44            .w_full()
45            .h_8()
46            .fill(theme.lowest.base.default.background)
47            .child(
48                div()
49                    .flex()
50                    .items_center()
51                    .h_full()
52                    .gap_4()
53                    .px_2()
54                    .child(TrafficLights::new().window_has_focus(has_focus))
55                    // === Project Info === //
56                    .child(
57                        div()
58                            .flex()
59                            .items_center()
60                            .gap_1()
61                            .child(Button::new("zed"))
62                            .child(Button::new("nate/gpui2-ui-components")),
63                    )
64                    .children(player_list.map(|p| PlayerStack::new(p))),
65            )
66            .child(
67                div()
68                    .flex()
69                    .items_center()
70                    .child(
71                        div()
72                            .px_2()
73                            .flex()
74                            .items_center()
75                            .gap_1()
76                            .child(IconButton::new(Icon::FolderX))
77                            .child(IconButton::new(Icon::Close)),
78                    )
79                    .child(ToolDivider::new())
80                    .child(
81                        div()
82                            .px_2()
83                            .flex()
84                            .items_center()
85                            .gap_1()
86                            .child(IconButton::new(Icon::Mic))
87                            .child(IconButton::new(Icon::AudioOn))
88                            .child(IconButton::new(Icon::Screen).color(IconColor::Accent)),
89                    )
90                    .child(
91                        div().px_2().flex().items_center().child(
92                            Avatar::new("https://avatars.githubusercontent.com/u/1714999?v=4")
93                                .shape(Shape::RoundedRectangle),
94                        ),
95                    ),
96            )
97    }
98}