diff --git a/crates/diagnostics/src/diagnostics.rs b/crates/diagnostics/src/diagnostics.rs index f6cc659818..c7f1f9b868 100644 --- a/crates/diagnostics/src/diagnostics.rs +++ b/crates/diagnostics/src/diagnostics.rs @@ -1,3 +1,5 @@ +pub mod items; + use anyhow::Result; use collections::{HashMap, HashSet}; use editor::{ @@ -16,13 +18,13 @@ use std::{cmp::Ordering, ops::Range, path::Path, sync::Arc}; use util::TryFutureExt; use workspace::Workspace; -action!(Toggle); +action!(Deploy); const CONTEXT_LINE_COUNT: u32 = 1; pub fn init(cx: &mut MutableAppContext) { - cx.add_bindings([Binding::new("alt-shift-D", Toggle, None)]); - cx.add_action(ProjectDiagnosticsEditor::toggle); + cx.add_bindings([Binding::new("alt-shift-D", Deploy, None)]); + cx.add_action(ProjectDiagnosticsEditor::deploy); } type Event = editor::Event; @@ -148,7 +150,7 @@ impl ProjectDiagnosticsEditor { self.editor.read(cx).text(cx) } - fn toggle(workspace: &mut Workspace, _: &Toggle, cx: &mut ViewContext) { + fn deploy(workspace: &mut Workspace, _: &Deploy, cx: &mut ViewContext) { let diagnostics = cx.add_model(|_| ProjectDiagnostics::new(workspace.project().clone())); workspace.add_item(diagnostics, cx); } diff --git a/crates/diagnostics/src/items.rs b/crates/diagnostics/src/items.rs new file mode 100644 index 0000000000..ae54b9879b --- /dev/null +++ b/crates/diagnostics/src/items.rs @@ -0,0 +1,71 @@ +use gpui::{ + elements::*, platform::CursorStyle, Entity, ModelHandle, RenderContext, View, ViewContext, +}; +use postage::watch; +use project::Project; +use workspace::{Settings, StatusItemView}; + +pub struct DiagnosticSummary { + settings: watch::Receiver, + summary: project::DiagnosticSummary, +} + +impl DiagnosticSummary { + pub fn new( + project: &ModelHandle, + settings: watch::Receiver, + cx: &mut ViewContext, + ) -> Self { + cx.subscribe(project, |this, project, event, cx| { + if let project::Event::DiskBasedDiagnosticsUpdated { .. } = event { + this.summary = project.read(cx).diagnostic_summary(cx); + cx.notify(); + } + }) + .detach(); + Self { + settings, + summary: project.read(cx).diagnostic_summary(cx), + } + } +} + +impl Entity for DiagnosticSummary { + type Event = (); +} + +impl View for DiagnosticSummary { + fn ui_name() -> &'static str { + "DiagnosticSummary" + } + + fn render(&mut self, cx: &mut RenderContext) -> ElementBox { + enum Tag {} + + let theme = &self.settings.borrow().theme.project_diagnostics; + MouseEventHandler::new::(0, cx, |_, _| { + Label::new( + format!( + "Errors: {}, Warnings: {}", + self.summary.error_count, self.summary.warning_count + ), + theme.status_bar_item.text.clone(), + ) + .contained() + .with_style(theme.status_bar_item.container) + .boxed() + }) + .with_cursor_style(CursorStyle::PointingHand) + .on_click(|cx| cx.dispatch_action(crate::Deploy)) + .boxed() + } +} + +impl StatusItemView for DiagnosticSummary { + fn set_active_pane_item( + &mut self, + _: Option<&dyn workspace::ItemViewHandle>, + _: &mut ViewContext, + ) { + } +} diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index 325ac682eb..c1da5aa842 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -539,6 +539,17 @@ impl Project { } } + pub fn diagnostic_summary(&self, cx: &AppContext) -> DiagnosticSummary { + let mut summary = DiagnosticSummary::default(); + for (_, path_summary) in self.diagnostic_summaries(cx) { + summary.error_count += path_summary.error_count; + summary.warning_count += path_summary.warning_count; + summary.info_count += path_summary.info_count; + summary.hint_count += path_summary.hint_count; + } + summary + } + pub fn diagnostic_summaries<'a>( &'a self, cx: &'a AppContext, diff --git a/crates/theme/src/theme.rs b/crates/theme/src/theme.rs index e91f0addb7..1ba2fc8faf 100644 --- a/crates/theme/src/theme.rs +++ b/crates/theme/src/theme.rs @@ -232,6 +232,7 @@ pub struct ProjectDiagnostics { #[serde(flatten)] pub container: ContainerStyle, pub empty_message: TextStyle, + pub status_bar_item: ContainedText, } #[derive(Clone, Deserialize, Default)] diff --git a/crates/zed/assets/themes/_base.toml b/crates/zed/assets/themes/_base.toml index 2fa2bde545..a8a5694978 100644 --- a/crates/zed/assets/themes/_base.toml +++ b/crates/zed/assets/themes/_base.toml @@ -185,7 +185,7 @@ corner_radius = 6 [project_panel] extends = "$panel" -padding.top = 6 # ($workspace.tab.height - $project_panel.entry.height) / 2 +padding.top = 6 # ($workspace.tab.height - $project_panel.entry.height) / 2 [project_panel.entry] text = "$text.1" @@ -273,3 +273,4 @@ header = { padding = { left = 10 }, background = "#ffffff08" } [project_diagnostics] background = "$surface.1" empty_message = "$text.0" +status_bar_item = { extends = "$text.2", margin.right = 10 } diff --git a/crates/zed/src/zed.rs b/crates/zed/src/zed.rs index 1483982b60..0004668939 100644 --- a/crates/zed/src/zed.rs +++ b/crates/zed/src/zed.rs @@ -88,12 +88,20 @@ pub fn build_workspace( .into(), ); - let diagnostic = + let diagnostic_message = cx.add_view(|_| editor::items::DiagnosticMessage::new(app_state.settings.clone())); + let diagnostic_summary = cx.add_view(|cx| { + diagnostics::items::DiagnosticSummary::new( + workspace.project(), + app_state.settings.clone(), + cx, + ) + }); let cursor_position = cx.add_view(|_| editor::items::CursorPosition::new(app_state.settings.clone())); workspace.status_bar().update(cx, |status_bar, cx| { - status_bar.add_left_item(diagnostic, cx); + status_bar.add_left_item(diagnostic_summary, cx); + status_bar.add_left_item(diagnostic_message, cx); status_bar.add_right_item(cursor_position, cx); });