@@ -1,4 +1,5 @@
pub mod items;
+mod toolbar_controls;
use anyhow::Result;
use collections::{BTreeSet, HashSet};
@@ -30,18 +31,20 @@ use std::{
sync::Arc,
};
use theme::ThemeSettings;
+pub use toolbar_controls::ToolbarControls;
use util::TryFutureExt;
use workspace::{
item::{BreadcrumbText, Item, ItemEvent, ItemHandle},
ItemNavHistory, Pane, PaneBackdrop, ToolbarItemLocation, Workspace,
};
-actions!(diagnostics, [Deploy]);
+actions!(diagnostics, [Deploy, ToggleWarnings]);
const CONTEXT_LINE_COUNT: u32 = 1;
pub fn init(cx: &mut AppContext) {
cx.add_action(ProjectDiagnosticsEditor::deploy);
+ cx.add_action(ProjectDiagnosticsEditor::toggle_warnings);
items::init(cx);
}
@@ -55,6 +58,7 @@ struct ProjectDiagnosticsEditor {
excerpts: ModelHandle<MultiBuffer>,
path_states: Vec<PathState>,
paths_to_update: BTreeSet<(ProjectPath, LanguageServerId)>,
+ include_warnings: bool,
}
struct PathState {
@@ -187,6 +191,7 @@ impl ProjectDiagnosticsEditor {
editor,
path_states: Default::default(),
paths_to_update,
+ include_warnings: true,
};
this.update_excerpts(None, cx);
this
@@ -204,6 +209,18 @@ impl ProjectDiagnosticsEditor {
}
}
+ fn toggle_warnings(&mut self, _: &ToggleWarnings, cx: &mut ViewContext<Self>) {
+ self.include_warnings = !self.include_warnings;
+ self.paths_to_update = self
+ .project
+ .read(cx)
+ .diagnostic_summaries(cx)
+ .map(|(path, server_id, _)| (path, server_id))
+ .collect();
+ self.update_excerpts(None, cx);
+ cx.notify();
+ }
+
fn update_excerpts(
&mut self,
language_server_id: Option<LanguageServerId>,
@@ -277,14 +294,18 @@ impl ProjectDiagnosticsEditor {
let mut blocks_to_add = Vec::new();
let mut blocks_to_remove = HashSet::default();
let mut first_excerpt_id = None;
+ let max_severity = if self.include_warnings {
+ DiagnosticSeverity::WARNING
+ } else {
+ DiagnosticSeverity::ERROR
+ };
let excerpts_snapshot = self.excerpts.update(cx, |excerpts, excerpts_cx| {
let mut old_groups = path_state.diagnostic_groups.iter().enumerate().peekable();
let mut new_groups = snapshot
.diagnostic_groups(language_server_id)
.into_iter()
.filter(|(_, group)| {
- group.entries[group.primary_ix].diagnostic.severity
- <= DiagnosticSeverity::WARNING
+ group.entries[group.primary_ix].diagnostic.severity <= max_severity
})
.peekable();
loop {
@@ -0,0 +1,115 @@
+use crate::{ProjectDiagnosticsEditor, ToggleWarnings};
+use gpui::{
+ elements::*,
+ platform::{CursorStyle, MouseButton},
+ Action, Entity, EventContext, View, ViewContext, WeakViewHandle,
+};
+use workspace::{item::ItemHandle, ToolbarItemLocation, ToolbarItemView};
+
+pub struct ToolbarControls {
+ editor: Option<WeakViewHandle<ProjectDiagnosticsEditor>>,
+}
+
+impl Entity for ToolbarControls {
+ type Event = ();
+}
+
+impl View for ToolbarControls {
+ fn ui_name() -> &'static str {
+ "ToolbarControls"
+ }
+
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
+ let include_warnings = self
+ .editor
+ .as_ref()
+ .and_then(|editor| editor.upgrade(cx))
+ .map(|editor| editor.read(cx).include_warnings)
+ .unwrap_or(false);
+ let tooltip = if include_warnings {
+ "Exclude Warnings".into()
+ } else {
+ "Include Warnings".into()
+ };
+ Flex::row()
+ .with_child(render_toggle_button(
+ 0,
+ "icons/warning.svg",
+ include_warnings,
+ (tooltip, Some(Box::new(ToggleWarnings))),
+ cx,
+ move |this, cx| {
+ if let Some(editor) = this.editor.and_then(|editor| editor.upgrade(cx)) {
+ editor.update(cx, |editor, cx| {
+ editor.toggle_warnings(&Default::default(), cx)
+ });
+ }
+ },
+ ))
+ .into_any()
+ }
+}
+
+impl ToolbarItemView for ToolbarControls {
+ fn set_active_pane_item(
+ &mut self,
+ active_pane_item: Option<&dyn ItemHandle>,
+ _: &mut ViewContext<Self>,
+ ) -> ToolbarItemLocation {
+ if let Some(pane_item) = active_pane_item.as_ref() {
+ if let Some(editor) = pane_item.downcast::<ProjectDiagnosticsEditor>() {
+ self.editor = Some(editor.downgrade());
+ ToolbarItemLocation::PrimaryRight { flex: None }
+ } else {
+ ToolbarItemLocation::Hidden
+ }
+ } else {
+ ToolbarItemLocation::Hidden
+ }
+ }
+}
+
+impl ToolbarControls {
+ pub fn new() -> Self {
+ ToolbarControls { editor: None }
+ }
+}
+
+fn render_toggle_button<
+ F: 'static + Fn(&mut ToolbarControls, &mut EventContext<ToolbarControls>),
+>(
+ index: usize,
+ icon: &'static str,
+ toggled: bool,
+ tooltip: (String, Option<Box<dyn Action>>),
+ cx: &mut ViewContext<ToolbarControls>,
+ on_click: F,
+) -> AnyElement<ToolbarControls> {
+ enum Button {}
+
+ let theme = theme::current(cx);
+ let (tooltip_text, action) = tooltip;
+
+ MouseEventHandler::new::<Button, _>(index, cx, |mouse_state, _| {
+ let style = theme
+ .workspace
+ .toolbar
+ .toggleable_tool
+ .in_state(toggled)
+ .style_for(mouse_state);
+ Svg::new(icon)
+ .with_color(style.color)
+ .constrained()
+ .with_width(style.icon_width)
+ .aligned()
+ .constrained()
+ .with_width(style.button_width)
+ .with_height(style.button_width)
+ .contained()
+ .with_style(style.container)
+ })
+ .with_cursor_style(CursorStyle::PointingHand)
+ .on_click(MouseButton::Left, move |_, view, cx| on_click(view, cx))
+ .with_tooltip::<Button>(index, tooltip_text, action, theme.tooltip.clone(), cx)
+ .into_any_named("quick action bar button")
+}
@@ -275,6 +275,10 @@ pub fn initialize_workspace(
QuickActionBar::new(buffer_search_bar, workspace)
});
toolbar.add_item(quick_action_bar, cx);
+ let diagnostic_editor_controls = cx.add_view(|_| {
+ diagnostics::ToolbarControls::new()
+ });
+ toolbar.add_item(diagnostic_editor_controls, cx);
let project_search_bar = cx.add_view(|_| ProjectSearchBar::new());
toolbar.add_item(project_search_bar, cx);
let submit_feedback_button =