toolbar_controls.rs

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