Reintroduce LSP diagnostic/status message (#3728)

Julia created

Release Notes:

- N/A

Change summary

crates/activity_indicator2/src/activity_indicator.rs |  4 
crates/diagnostics2/src/items.rs                     | 65 ++++++++-----
crates/workspace2/src/pane.rs                        | 17 +++
crates/workspace2/src/status_bar.rs                  |  9 +
4 files changed, 67 insertions(+), 28 deletions(-)

Detailed changes

crates/activity_indicator2/src/activity_indicator.rs πŸ”—

@@ -10,7 +10,7 @@ use language::{LanguageRegistry, LanguageServerBinaryStatus};
 use project::{LanguageServerProgress, Project};
 use smallvec::SmallVec;
 use std::{cmp::Reverse, fmt::Write, sync::Arc};
-use ui::h_stack;
+use ui::{h_stack, Label};
 use util::ResultExt;
 use workspace::{item::ItemHandle, StatusItemView, Workspace};
 
@@ -324,7 +324,7 @@ impl Render for ActivityIndicator {
 
         result
             .children(content.icon.map(|icon| svg().path(icon)))
-            .child(SharedString::from(content.message))
+            .child(Label::new(SharedString::from(content.message)))
     }
 }
 

crates/diagnostics2/src/items.rs πŸ”—

@@ -1,16 +1,15 @@
 use collections::HashSet;
-use editor::{Editor, GoToDiagnostic};
+use editor::Editor;
 use gpui::{
-    rems, Div, EventEmitter, InteractiveElement, ParentElement, Render, Stateful,
-    StatefulInteractiveElement, Styled, Subscription, View, ViewContext, WeakView,
+    rems, Div, EventEmitter, IntoElement, ParentElement, Render, Styled, Subscription, View,
+    ViewContext, WeakView,
 };
 use language::Diagnostic;
 use lsp::LanguageServerId;
-use theme::ActiveTheme;
-use ui::{h_stack, Color, Icon, IconElement, Label, Tooltip};
+use ui::{h_stack, prelude::*, Button, ButtonLike, Color, Icon, IconElement, Label, Tooltip};
 use workspace::{item::ItemHandle, StatusItemView, ToolbarItemEvent, Workspace};
 
-use crate::ProjectDiagnosticsEditor;
+use crate::{Deploy, ProjectDiagnosticsEditor};
 
 pub struct DiagnosticIndicator {
     summary: project::DiagnosticSummary,
@@ -22,7 +21,7 @@ pub struct DiagnosticIndicator {
 }
 
 impl Render for DiagnosticIndicator {
-    type Element = Stateful<Div>;
+    type Element = Div;
 
     fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
         let diagnostic_indicator = match (self.summary.error_count, self.summary.warning_count) {
@@ -43,26 +42,40 @@ impl Render for DiagnosticIndicator {
                 .child(Label::new(warning_count.to_string())),
         };
 
+        let status = if !self.in_progress_checks.is_empty() {
+            Some(Label::new("Checking…").into_any_element())
+        } else if let Some(diagnostic) = &self.current_diagnostic {
+            let message = diagnostic.message.split('\n').next().unwrap().to_string();
+            Some(
+                Button::new("diagnostic_message", message)
+                    .tooltip(|cx| {
+                        Tooltip::for_action("Next Diagnostic", &editor::GoToDiagnostic, cx)
+                    })
+                    .on_click(cx.listener(|this, _, cx| {
+                        this.go_to_next_diagnostic(cx);
+                    }))
+                    .into_any_element(),
+            )
+        } else {
+            None
+        };
+
         h_stack()
-            .id("diagnostic-indicator")
-            .on_action(cx.listener(Self::go_to_next_diagnostic))
-            .rounded_md()
-            .flex_none()
             .h(rems(1.375))
-            .px_1()
-            .cursor_pointer()
-            .bg(cx.theme().colors().ghost_element_background)
-            .hover(|style| style.bg(cx.theme().colors().ghost_element_hover))
-            .active(|style| style.bg(cx.theme().colors().ghost_element_active))
-            .tooltip(|cx| Tooltip::text("Project Diagnostics", cx))
-            .on_click(cx.listener(|this, _, cx| {
-                if let Some(workspace) = this.workspace.upgrade() {
-                    workspace.update(cx, |workspace, cx| {
-                        ProjectDiagnosticsEditor::deploy(workspace, &Default::default(), cx)
-                    })
-                }
-            }))
-            .child(diagnostic_indicator)
+            .gap_2()
+            .child(
+                ButtonLike::new("diagnostic-indicator")
+                    .child(diagnostic_indicator)
+                    .tooltip(|cx| Tooltip::for_action("Project Diagnostics", &Deploy, cx))
+                    .on_click(cx.listener(|this, _, cx| {
+                        if let Some(workspace) = this.workspace.upgrade() {
+                            workspace.update(cx, |workspace, cx| {
+                                ProjectDiagnosticsEditor::deploy(workspace, &Default::default(), cx)
+                            })
+                        }
+                    })),
+            )
+            .children(status)
     }
 }
 
@@ -104,7 +117,7 @@ impl DiagnosticIndicator {
         }
     }
 
-    fn go_to_next_diagnostic(&mut self, _: &GoToDiagnostic, cx: &mut ViewContext<Self>) {
+    fn go_to_next_diagnostic(&mut self, cx: &mut ViewContext<Self>) {
         if let Some(editor) = self.active_editor.as_ref().and_then(|e| e.upgrade()) {
             editor.update(cx, |editor, cx| {
                 editor.go_to_diagnostic_impl(editor::Direction::Next, cx);

crates/workspace2/src/pane.rs πŸ”—

@@ -789,6 +789,7 @@ impl Pane {
             }
 
             self.update_toolbar(cx);
+            self.update_status_bar(cx);
 
             if focus_item {
                 self.focus_active_item(cx);
@@ -1450,6 +1451,22 @@ impl Pane {
         });
     }
 
+    fn update_status_bar(&mut self, cx: &mut ViewContext<Self>) {
+        let workspace = self.workspace.clone();
+        let pane = cx.view().clone();
+
+        cx.window_context().defer(move |cx| {
+            let Ok(status_bar) = workspace.update(cx, |workspace, _| workspace.status_bar.clone())
+            else {
+                return;
+            };
+
+            status_bar.update(cx, move |status_bar, cx| {
+                status_bar.set_active_pane(&pane, cx);
+            });
+        });
+    }
+
     fn render_tab(
         &self,
         ix: usize,

crates/workspace2/src/status_bar.rs πŸ”—

@@ -83,6 +83,9 @@ impl StatusBar {
     where
         T: 'static + StatusItemView,
     {
+        let active_pane_item = self.active_pane.read(cx).active_item();
+        item.set_active_pane_item(active_pane_item.as_deref(), cx);
+
         self.left_items.push(Box::new(item));
         cx.notify();
     }
@@ -119,6 +122,9 @@ impl StatusBar {
     ) where
         T: 'static + StatusItemView,
     {
+        let active_pane_item = self.active_pane.read(cx).active_item();
+        item.set_active_pane_item(active_pane_item.as_deref(), cx);
+
         if position < self.left_items.len() {
             self.left_items.insert(position + 1, Box::new(item))
         } else {
@@ -141,6 +147,9 @@ impl StatusBar {
     where
         T: 'static + StatusItemView,
     {
+        let active_pane_item = self.active_pane.read(cx).active_item();
+        item.set_active_pane_item(active_pane_item.as_deref(), cx);
+
         self.right_items.push(Box::new(item));
         cx.notify();
     }