toolbar_controls.rs

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