1use crate::{ProjectDiagnosticsEditor, ToggleDiagnosticsRefresh};
2use gpui::{Context, Entity, EventEmitter, ParentElement, Render, WeakEntity, Window};
3use ui::prelude::*;
4use ui::{IconButton, IconButtonShape, IconName, Tooltip};
5use workspace::{ToolbarItemEvent, ToolbarItemLocation, ToolbarItemView, item::ItemHandle};
6
7pub struct ToolbarControls {
8 editor: Option<WeakEntity<ProjectDiagnosticsEditor>>,
9}
10
11impl Render for ToolbarControls {
12 fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
13 let mut include_warnings = false;
14 let mut has_stale_excerpts = false;
15 let mut is_updating = false;
16
17 if let Some(editor) = self.diagnostics() {
18 let diagnostics = editor.read(cx);
19 include_warnings = diagnostics.include_warnings;
20 has_stale_excerpts = !diagnostics.paths_to_update.is_empty();
21 is_updating = diagnostics.update_excerpts_task.is_some()
22 || diagnostics
23 .project
24 .read(cx)
25 .language_servers_running_disk_based_diagnostics(cx)
26 .next()
27 .is_some();
28 }
29
30 let tooltip = if include_warnings {
31 "Exclude Warnings"
32 } else {
33 "Include Warnings"
34 };
35
36 let warning_color = if include_warnings {
37 Color::Warning
38 } else {
39 Color::Muted
40 };
41
42 h_flex()
43 .gap_1()
44 .map(|div| {
45 if is_updating {
46 div.child(
47 IconButton::new("stop-updating", IconName::Stop)
48 .icon_color(Color::Info)
49 .shape(IconButtonShape::Square)
50 .tooltip(Tooltip::for_action_title(
51 "Stop diagnostics update",
52 &ToggleDiagnosticsRefresh,
53 ))
54 .on_click(cx.listener(move |toolbar_controls, _, _, cx| {
55 if let Some(diagnostics) = toolbar_controls.diagnostics() {
56 diagnostics.update(cx, |diagnostics, cx| {
57 diagnostics.update_excerpts_task = None;
58 cx.notify();
59 });
60 }
61 })),
62 )
63 } else {
64 div.child(
65 IconButton::new("refresh-diagnostics", IconName::ArrowCircle)
66 .icon_color(Color::Info)
67 .shape(IconButtonShape::Square)
68 .disabled(!has_stale_excerpts)
69 .tooltip(Tooltip::for_action_title(
70 "Refresh diagnostics",
71 &ToggleDiagnosticsRefresh,
72 ))
73 .on_click(cx.listener({
74 move |toolbar_controls, _, window, cx| {
75 if let Some(diagnostics) = toolbar_controls.diagnostics() {
76 diagnostics.update(cx, move |diagnostics, cx| {
77 diagnostics.update_all_excerpts(window, cx);
78 });
79 }
80 }
81 })),
82 )
83 }
84 })
85 .child(
86 IconButton::new("toggle-warnings", IconName::Warning)
87 .icon_color(warning_color)
88 .shape(IconButtonShape::Square)
89 .tooltip(Tooltip::text(tooltip))
90 .on_click(cx.listener(|this, _, window, cx| {
91 if let Some(editor) = this.diagnostics() {
92 editor.update(cx, |editor, cx| {
93 editor.toggle_warnings(&Default::default(), window, cx);
94 });
95 }
96 })),
97 )
98 }
99}
100
101impl EventEmitter<ToolbarItemEvent> for ToolbarControls {}
102
103impl ToolbarItemView for ToolbarControls {
104 fn set_active_pane_item(
105 &mut self,
106 active_pane_item: Option<&dyn ItemHandle>,
107 _window: &mut Window,
108 _: &mut Context<Self>,
109 ) -> ToolbarItemLocation {
110 if let Some(pane_item) = active_pane_item.as_ref() {
111 if let Some(editor) = pane_item.downcast::<ProjectDiagnosticsEditor>() {
112 self.editor = Some(editor.downgrade());
113 ToolbarItemLocation::PrimaryRight
114 } else {
115 ToolbarItemLocation::Hidden
116 }
117 } else {
118 ToolbarItemLocation::Hidden
119 }
120 }
121}
122
123impl Default for ToolbarControls {
124 fn default() -> Self {
125 Self::new()
126 }
127}
128
129impl ToolbarControls {
130 pub fn new() -> Self {
131 ToolbarControls { editor: None }
132 }
133
134 fn diagnostics(&self) -> Option<Entity<ProjectDiagnosticsEditor>> {
135 self.editor.as_ref()?.upgrade()
136 }
137}