Render diagnostic status bar icon with icons

Max Brunsfeld created

Change summary

crates/diagnostics/src/diagnostics.rs | 93 ++++++++++++++++++----------
crates/diagnostics/src/items.rs       | 25 +++----
crates/zed/assets/themes/_base.toml   |  4 
3 files changed, 72 insertions(+), 50 deletions(-)

Detailed changes

crates/diagnostics/src/diagnostics.rs 🔗

@@ -10,8 +10,9 @@ use editor::{
     Autoscroll, BuildSettings, Editor, ExcerptId, ExcerptProperties, MultiBuffer, ToOffset,
 };
 use gpui::{
-    action, elements::*, keymap::Binding, AnyViewHandle, AppContext, Entity, ModelHandle,
-    MutableAppContext, RenderContext, Task, View, ViewContext, ViewHandle, WeakViewHandle,
+    action, elements::*, fonts::TextStyle, keymap::Binding, AnyViewHandle, AppContext, Entity,
+    ModelHandle, MutableAppContext, RenderContext, Task, View, ViewContext, ViewHandle,
+    WeakViewHandle,
 };
 use language::{
     Bias, Buffer, Diagnostic, DiagnosticEntry, DiagnosticSeverity, Point, Selection, SelectionGoal,
@@ -131,9 +132,10 @@ impl ProjectDiagnosticsEditor {
         let project = model.read(cx).project.clone();
         cx.subscribe(&project, |this, _, event, cx| match event {
             project::Event::DiskBasedDiagnosticsFinished => {
+                this.summary = this.model.read(cx).project.read(cx).diagnostic_summary(cx);
                 let paths = mem::take(&mut this.paths_to_update);
                 this.update_excerpts(paths, cx);
-                cx.emit(Event::TitleChanged)
+                cx.emit(Event::TitleChanged);
             }
             project::Event::DiagnosticsUpdated(path) => {
                 this.paths_to_update.insert(path.clone());
@@ -557,37 +559,11 @@ impl workspace::ItemView for ProjectDiagnosticsEditor {
     }
 
     fn tab_content(&self, style: &theme::Tab, _: &AppContext) -> ElementBox {
-        let theme = &self.settings.borrow().theme.project_diagnostics;
-        let icon_width = theme.tab_icon_width;
-        let icon_spacing = theme.tab_icon_spacing;
-        let summary_spacing = theme.tab_summary_spacing;
-        Flex::row()
-            .with_children([
-                Svg::new("icons/diagnostic-summary-error.svg")
-                    .with_color(style.label.text.color)
-                    .constrained()
-                    .with_width(icon_width)
-                    .aligned()
-                    .contained()
-                    .with_margin_right(icon_spacing)
-                    .named("no-icon"),
-                Label::new(self.summary.error_count.to_string(), style.label.clone())
-                    .aligned()
-                    .boxed(),
-                Svg::new("icons/diagnostic-summary-warning.svg")
-                    .with_color(style.label.text.color)
-                    .constrained()
-                    .with_width(icon_width)
-                    .aligned()
-                    .contained()
-                    .with_margin_left(summary_spacing)
-                    .with_margin_right(icon_spacing)
-                    .named("warn-icon"),
-                Label::new(self.summary.warning_count.to_string(), style.label.clone())
-                    .aligned()
-                    .boxed(),
-            ])
-            .boxed()
+        render_summary(
+            &self.summary,
+            &style.label.text,
+            &self.settings.borrow().theme.project_diagnostics,
+        )
     }
 
     fn project_path(&self, _: &AppContext) -> Option<project::ProjectPath> {
@@ -786,6 +762,55 @@ fn context_header_renderer(build_settings: BuildSettings) -> RenderBlock {
     })
 }
 
+pub(crate) fn render_summary(
+    summary: &DiagnosticSummary,
+    text_style: &TextStyle,
+    theme: &theme::ProjectDiagnostics,
+) -> ElementBox {
+    let icon_width = theme.tab_icon_width;
+    let icon_spacing = theme.tab_icon_spacing;
+    let summary_spacing = theme.tab_summary_spacing;
+    Flex::row()
+        .with_children([
+            Svg::new("icons/diagnostic-summary-error.svg")
+                .with_color(text_style.color)
+                .constrained()
+                .with_width(icon_width)
+                .aligned()
+                .contained()
+                .with_margin_right(icon_spacing)
+                .named("no-icon"),
+            Label::new(
+                summary.error_count.to_string(),
+                LabelStyle {
+                    text: text_style.clone(),
+                    highlight_text: None,
+                },
+            )
+            .aligned()
+            .boxed(),
+            Svg::new("icons/diagnostic-summary-warning.svg")
+                .with_color(text_style.color)
+                .constrained()
+                .with_width(icon_width)
+                .aligned()
+                .contained()
+                .with_margin_left(summary_spacing)
+                .with_margin_right(icon_spacing)
+                .named("warn-icon"),
+            Label::new(
+                summary.warning_count.to_string(),
+                LabelStyle {
+                    text: text_style.clone(),
+                    highlight_text: None,
+                },
+            )
+            .aligned()
+            .boxed(),
+        ])
+        .boxed()
+}
+
 fn compare_diagnostics<L: language::ToOffset, R: language::ToOffset>(
     lhs: &DiagnosticEntry<L>,
     rhs: &DiagnosticEntry<R>,

crates/diagnostics/src/items.rs 🔗

@@ -1,9 +1,9 @@
+use crate::render_summary;
 use gpui::{
     elements::*, platform::CursorStyle, Entity, ModelHandle, RenderContext, View, ViewContext,
 };
 use postage::watch;
 use project::Project;
-use std::fmt::Write;
 use workspace::{Settings, StatusItemView};
 
 pub struct DiagnosticSummary {
@@ -20,7 +20,6 @@ impl DiagnosticSummary {
     ) -> Self {
         cx.subscribe(project, |this, project, event, cx| match event {
             project::Event::DiskBasedDiagnosticsUpdated => {
-                this.summary = project.read(cx).diagnostic_summary(cx);
                 cx.notify();
             }
             project::Event::DiskBasedDiagnosticsStarted => {
@@ -28,6 +27,7 @@ impl DiagnosticSummary {
                 cx.notify();
             }
             project::Event::DiskBasedDiagnosticsFinished => {
+                this.summary = project.read(cx).diagnostic_summary(cx);
                 this.in_progress = false;
                 cx.notify();
             }
@@ -55,21 +55,20 @@ impl View for DiagnosticSummary {
         enum Tag {}
 
         let theme = &self.settings.borrow().theme.project_diagnostics;
-        let mut message = String::new();
-        if self.in_progress {
-            message.push_str("Checking... ");
-        }
-        write!(
-            message,
-            "Errors: {}, Warnings: {}",
-            self.summary.error_count, self.summary.warning_count
-        )
-        .unwrap();
+
+        let in_progress = self.in_progress;
         MouseEventHandler::new::<Tag, _, _, _>(0, cx, |_, _| {
-            Label::new(message, theme.status_bar_item.text.clone())
+            if in_progress {
+                Label::new(
+                    "Checking... ".to_string(),
+                    theme.status_bar_item.text.clone(),
+                )
                 .contained()
                 .with_style(theme.status_bar_item.container)
                 .boxed()
+            } else {
+                render_summary(&self.summary, &theme.status_bar_item.text, &theme)
+            }
         })
         .with_cursor_style(CursorStyle::PointingHand)
         .on_click(|cx| cx.dispatch_action(crate::Deploy))

crates/zed/assets/themes/_base.toml 🔗

@@ -77,11 +77,9 @@ border = { width = 1, color = "$border.0", left = true }
 [workspace.status_bar]
 padding = { left = 6, right = 6 }
 height = 24
+item_spacing = 24
 cursor_position = "$text.2"
 diagnostic_message = "$text.2"
-diagnostic_icon_size = 18
-diagnostic_icon_spacing = 8
-diagnostic_icon_color = "$text.2.color"
 
 [panel]
 padding = { top = 12, left = 12, bottom = 12, right = 12 }