loaded_source_list.rs

 1use gpui::{AnyElement, Empty, Entity, FocusHandle, Focusable, ListState, Subscription, list};
 2use project::debugger::session::{Session, SessionEvent};
 3use ui::prelude::*;
 4use util::maybe;
 5
 6pub(crate) struct LoadedSourceList {
 7    list: ListState,
 8    invalidate: bool,
 9    focus_handle: FocusHandle,
10    _subscription: Subscription,
11    session: Entity<Session>,
12}
13
14impl LoadedSourceList {
15    pub fn new(session: Entity<Session>, cx: &mut Context<Self>) -> Self {
16        let focus_handle = cx.focus_handle();
17        let list = ListState::new(0, gpui::ListAlignment::Top, px(1000.));
18
19        let _subscription = cx.subscribe(&session, |this, _, event, cx| match event {
20            SessionEvent::Stopped(_) | SessionEvent::LoadedSources => {
21                this.invalidate = true;
22                cx.notify();
23            }
24            _ => {}
25        });
26
27        Self {
28            list,
29            session,
30            focus_handle,
31            _subscription,
32            invalidate: true,
33        }
34    }
35
36    fn render_entry(&mut self, ix: usize, cx: &mut Context<Self>) -> AnyElement {
37        let Some(source) = maybe!({
38            self.session
39                .update(cx, |state, cx| state.loaded_sources(cx).get(ix).cloned())
40        }) else {
41            return Empty.into_any();
42        };
43
44        v_flex()
45            .rounded_md()
46            .w_full()
47            .group("")
48            .p_1()
49            .hover(|s| s.bg(cx.theme().colors().element_hover))
50            .child(
51                h_flex()
52                    .gap_0p5()
53                    .text_ui_sm(cx)
54                    .when_some(source.name.clone(), |this, name| this.child(name)),
55            )
56            .child(
57                h_flex()
58                    .text_ui_xs(cx)
59                    .text_color(cx.theme().colors().text_muted)
60                    .when_some(source.path, |this, path| this.child(path)),
61            )
62            .into_any()
63    }
64}
65
66impl Focusable for LoadedSourceList {
67    fn focus_handle(&self, _: &gpui::App) -> gpui::FocusHandle {
68        self.focus_handle.clone()
69    }
70}
71
72impl Render for LoadedSourceList {
73    fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
74        if self.invalidate {
75            let len = self
76                .session
77                .update(cx, |session, cx| session.loaded_sources(cx).len());
78            self.list.reset(len);
79            self.invalidate = false;
80            cx.notify();
81        }
82
83        div()
84            .track_focus(&self.focus_handle)
85            .size_full()
86            .p_1()
87            .child(
88                list(
89                    self.list.clone(),
90                    cx.processor(|this, ix, _window, cx| this.render_entry(ix, cx)),
91                )
92                .size_full(),
93            )
94    }
95}