items.rs

  1use gpui::{
  2    elements::*, platform::CursorStyle, serde_json, Entity, ModelHandle, RenderContext, View,
  3    ViewContext,
  4};
  5use project::Project;
  6use settings::Settings;
  7use workspace::StatusItemView;
  8
  9pub struct DiagnosticSummary {
 10    summary: project::DiagnosticSummary,
 11    in_progress: bool,
 12}
 13
 14impl DiagnosticSummary {
 15    pub fn new(project: &ModelHandle<Project>, cx: &mut ViewContext<Self>) -> Self {
 16        cx.subscribe(project, |this, project, event, cx| match event {
 17            project::Event::DiskBasedDiagnosticsUpdated => {
 18                cx.notify();
 19            }
 20            project::Event::DiskBasedDiagnosticsStarted => {
 21                this.in_progress = true;
 22                cx.notify();
 23            }
 24            project::Event::DiskBasedDiagnosticsFinished => {
 25                this.summary = project.read(cx).diagnostic_summary(cx);
 26                this.in_progress = false;
 27                cx.notify();
 28            }
 29            _ => {}
 30        })
 31        .detach();
 32        Self {
 33            summary: project.read(cx).diagnostic_summary(cx),
 34            in_progress: project.read(cx).is_running_disk_based_diagnostics(),
 35        }
 36    }
 37}
 38
 39impl Entity for DiagnosticSummary {
 40    type Event = ();
 41}
 42
 43impl View for DiagnosticSummary {
 44    fn ui_name() -> &'static str {
 45        "DiagnosticSummary"
 46    }
 47
 48    fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox {
 49        enum Tag {}
 50
 51        let in_progress = self.in_progress;
 52        MouseEventHandler::new::<Tag, _, _>(0, cx, |state, cx| {
 53            let style = &cx
 54                .global::<Settings>()
 55                .theme
 56                .workspace
 57                .status_bar
 58                .diagnostics;
 59            let summary_style = if self.summary.error_count > 0 {
 60                if state.hovered {
 61                    &style.summary_error_hover
 62                } else {
 63                    &style.summary_error
 64                }
 65            } else if self.summary.warning_count > 0 {
 66                if state.hovered {
 67                    &style.summary_warning_hover
 68                } else {
 69                    &style.summary_warning
 70                }
 71            } else if state.hovered {
 72                &style.summary_ok_hover
 73            } else {
 74                &style.summary_ok
 75            };
 76
 77            let mut row = Flex::row();
 78            if self.summary.error_count > 0 {
 79                row.add_children([
 80                    Svg::new("icons/error-solid-14.svg")
 81                        .with_color(style.icon_color_error)
 82                        .constrained()
 83                        .with_width(style.icon_width)
 84                        .aligned()
 85                        .contained()
 86                        .with_margin_right(style.icon_spacing)
 87                        .named("error-icon"),
 88                    Label::new(
 89                        self.summary.error_count.to_string(),
 90                        summary_style.text.clone(),
 91                    )
 92                    .aligned()
 93                    .boxed(),
 94                ]);
 95            }
 96
 97            if self.summary.warning_count > 0 {
 98                row.add_children([
 99                    Svg::new("icons/warning-solid-14.svg")
100                        .with_color(style.icon_color_warning)
101                        .constrained()
102                        .with_width(style.icon_width)
103                        .aligned()
104                        .contained()
105                        .with_margin_right(style.icon_spacing)
106                        .with_margin_left(if self.summary.error_count > 0 {
107                            style.summary_spacing
108                        } else {
109                            0.
110                        })
111                        .named("warning-icon"),
112                    Label::new(
113                        self.summary.warning_count.to_string(),
114                        summary_style.text.clone(),
115                    )
116                    .aligned()
117                    .boxed(),
118                ]);
119            }
120
121            if self.summary.error_count == 0 && self.summary.warning_count == 0 {
122                row.add_child(
123                    Svg::new("icons/no-error-solid-14.svg")
124                        .with_color(style.icon_color_ok)
125                        .constrained()
126                        .with_width(style.icon_width)
127                        .aligned()
128                        .named("ok-icon"),
129                );
130            }
131
132            row.constrained()
133                .with_height(style.height)
134                .contained()
135                .with_style(summary_style.container)
136                .boxed()
137        })
138        .with_cursor_style(CursorStyle::PointingHand)
139        .on_click(|cx| cx.dispatch_action(crate::Deploy))
140        .boxed()
141    }
142
143    fn debug_json(&self, _: &gpui::AppContext) -> serde_json::Value {
144        serde_json::json!({ "summary": self.summary })
145    }
146}
147
148impl StatusItemView for DiagnosticSummary {
149    fn set_active_pane_item(
150        &mut self,
151        _: Option<&dyn workspace::ItemHandle>,
152        _: &mut ViewContext<Self>,
153    ) {
154    }
155}