From 9116e13ef6c0c33538c62e3e395c8626243c510d Mon Sep 17 00:00:00 2001 From: nilskch Date: Sat, 21 Sep 2024 20:57:35 +0100 Subject: [PATCH 01/28] show errors in project panel --- crates/project_panel/src/project_panel.rs | 44 +++++++++++++++++++++-- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/crates/project_panel/src/project_panel.rs b/crates/project_panel/src/project_panel.rs index cd4196dbc67b1..19465bc51f090 100644 --- a/crates/project_panel/src/project_panel.rs +++ b/crates/project_panel/src/project_panel.rs @@ -82,6 +82,7 @@ pub struct ProjectPanel { show_scrollbar: bool, scrollbar_drag_thumb_offset: Rc>>, hide_scrollbar_task: Option>, + diagnostic_error_colors: HashMap, } #[derive(Clone, Debug)] @@ -237,6 +238,12 @@ impl ProjectPanel { project::Event::ActivateProjectPanel => { cx.emit(PanelEvent::Activate); } + project::Event::DiskBasedDiagnosticsFinished { .. } + | project::Event::DiagnosticsUpdated { .. } => { + this.update_diagnostics(cx); + this.update_visible_entries(None, cx); + cx.notify(); + } project::Event::WorktreeRemoved(id) => { this.expanded_dir_ids.remove(id); this.update_visible_entries(None, cx); @@ -312,6 +319,7 @@ impl ProjectPanel { show_scrollbar: !Self::should_autohide_scrollbar(cx), hide_scrollbar_task: None, scrollbar_drag_thumb_offset: Default::default(), + diagnostic_error_colors: Default::default(), }; this.update_visible_entries(None, cx); @@ -433,6 +441,32 @@ impl ProjectPanel { }) } + fn update_diagnostics(&mut self, cx: &mut ViewContext) { + self.diagnostic_error_colors = self + .project + .read(cx) + .diagnostic_summaries(false, cx) + .filter_map(|(path, _, diagnostic_summary)| { + if diagnostic_summary.error_count > 0 { + Some((path, Color::Error)) + } else { + None + } + }) + .flat_map(|(project_path, color)| { + let mut path_buf = PathBuf::new(); + project_path + .path + .components() + .map(|component| { + path_buf.push(component); + (path_buf.clone(), color) + }) + .collect::>() + }) + .collect(); + } + fn serialize(&mut self, cx: &mut ViewContext) { let width = self.width; self.pending_serialization = cx.background_executor().spawn( @@ -2195,8 +2229,14 @@ impl ProjectPanel { .selection .map_or(false, |selection| selection.entry_id == entry_id); let width = self.size(cx); - let filename_text_color = - entry_git_aware_label_color(details.git_status, details.is_ignored, is_marked); + let filename_text_color = if let Some(color) = self + .diagnostic_error_colors + .get(&details.path.to_path_buf()) + { + color.clone() + } else { + entry_git_aware_label_color(details.git_status, details.is_ignored, is_marked) + }; let file_name = details.filename.clone(); let mut icon = details.icon.clone(); if settings.file_icons && show_editor && details.kind.is_file() { From 993c727a1e9eab97068d2462c8c27814959defde Mon Sep 17 00:00:00 2001 From: nilskch Date: Sat, 21 Sep 2024 22:19:34 +0100 Subject: [PATCH 02/28] color root directory as well --- crates/project_panel/src/project_panel.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/project_panel/src/project_panel.rs b/crates/project_panel/src/project_panel.rs index 19465bc51f090..cc6e758c3ceec 100644 --- a/crates/project_panel/src/project_panel.rs +++ b/crates/project_panel/src/project_panel.rs @@ -462,6 +462,7 @@ impl ProjectPanel { path_buf.push(component); (path_buf.clone(), color) }) + .chain(std::iter::once((PathBuf::from(""), color))) .collect::>() }) .collect(); From 09bb386fba51976083eb68748af03d511fd1e118 Mon Sep 17 00:00:00 2001 From: nilskch Date: Sat, 21 Sep 2024 22:35:44 +0100 Subject: [PATCH 03/28] fix clippy --- crates/project_panel/src/project_panel.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/project_panel/src/project_panel.rs b/crates/project_panel/src/project_panel.rs index cc6e758c3ceec..a25eab5d9b92f 100644 --- a/crates/project_panel/src/project_panel.rs +++ b/crates/project_panel/src/project_panel.rs @@ -2234,7 +2234,7 @@ impl ProjectPanel { .diagnostic_error_colors .get(&details.path.to_path_buf()) { - color.clone() + *color } else { entry_git_aware_label_color(details.git_status, details.is_ignored, is_marked) }; From 5dd0f944bab40b371387fccf085ba49fe107d57b Mon Sep 17 00:00:00 2001 From: nilskch Date: Mon, 23 Sep 2024 20:11:44 +0100 Subject: [PATCH 04/28] add configuration for diagnostic errors --- assets/settings/default.json | 4 ++- crates/project_panel/src/project_panel.rs | 29 ++++++++++--------- .../src/project_panel_settings.rs | 5 ++++ 3 files changed, 24 insertions(+), 14 deletions(-) diff --git a/assets/settings/default.json b/assets/settings/default.json index 8424c5733d81b..a4a949234dc76 100644 --- a/assets/settings/default.json +++ b/assets/settings/default.json @@ -357,7 +357,9 @@ /// /// Default: always "show": "always" - } + }, + /// Whether to highlight errors in the project panel. + "show_diagnostic_errors": true }, "outline_panel": { // Whether to show the outline panel button in the status bar diff --git a/crates/project_panel/src/project_panel.rs b/crates/project_panel/src/project_panel.rs index a25eab5d9b92f..cc3e4f04fb64b 100644 --- a/crates/project_panel/src/project_panel.rs +++ b/crates/project_panel/src/project_panel.rs @@ -82,7 +82,7 @@ pub struct ProjectPanel { show_scrollbar: bool, scrollbar_drag_thumb_offset: Rc>>, hide_scrollbar_task: Option>, - diagnostic_error_colors: HashMap, + diagnostic_error_paths: HashSet, } #[derive(Clone, Debug)] @@ -114,6 +114,7 @@ struct EntryDetails { is_editing: bool, is_processing: bool, is_cut: bool, + is_diagnostic_error: bool, git_status: Option, is_private: bool, worktree_id: WorktreeId, @@ -319,7 +320,7 @@ impl ProjectPanel { show_scrollbar: !Self::should_autohide_scrollbar(cx), hide_scrollbar_task: None, scrollbar_drag_thumb_offset: Default::default(), - diagnostic_error_colors: Default::default(), + diagnostic_error_paths: Default::default(), }; this.update_visible_entries(None, cx); @@ -442,27 +443,27 @@ impl ProjectPanel { } fn update_diagnostics(&mut self, cx: &mut ViewContext) { - self.diagnostic_error_colors = self + self.diagnostic_error_paths = self .project .read(cx) .diagnostic_summaries(false, cx) .filter_map(|(path, _, diagnostic_summary)| { if diagnostic_summary.error_count > 0 { - Some((path, Color::Error)) + Some(path) } else { None } }) - .flat_map(|(project_path, color)| { + .flat_map(|project_path| { let mut path_buf = PathBuf::new(); project_path .path .components() .map(|component| { path_buf.push(component); - (path_buf.clone(), color) + path_buf.clone() }) - .chain(std::iter::once((PathBuf::from(""), color))) + .chain(std::iter::once(PathBuf::from(""))) .collect::>() }) .collect(); @@ -2059,12 +2060,13 @@ impl ProjectPanel { } let end_ix = range.end.min(ix + visible_worktree_entries.len()); - let (git_status_setting, show_file_icons, show_folder_icons) = { + let (git_status_setting, show_file_icons, show_folder_icons, show_diagnostic_errors) = { let settings = ProjectPanelSettings::get_global(cx); ( settings.git_status, settings.file_icons, settings.folder_icons, + settings.show_diagnostic_errors, ) }; if let Some(worktree) = self.project.read(cx).worktree_for_id(*worktree_id, cx) { @@ -2141,6 +2143,10 @@ impl ProjectPanel { .clipboard .as_ref() .map_or(false, |e| e.is_cut() && e.items().contains(&selection)), + is_diagnostic_error: show_diagnostic_errors + && self + .diagnostic_error_paths + .contains(&entry.path.to_path_buf()), git_status: status, is_private: entry.is_private, worktree_id: *worktree_id, @@ -2230,11 +2236,8 @@ impl ProjectPanel { .selection .map_or(false, |selection| selection.entry_id == entry_id); let width = self.size(cx); - let filename_text_color = if let Some(color) = self - .diagnostic_error_colors - .get(&details.path.to_path_buf()) - { - *color + let filename_text_color = if details.is_diagnostic_error { + Color::Error } else { entry_git_aware_label_color(details.git_status, details.is_ignored, is_marked) }; diff --git a/crates/project_panel/src/project_panel_settings.rs b/crates/project_panel/src/project_panel_settings.rs index 4d73ae92456da..a16c2e9dab149 100644 --- a/crates/project_panel/src/project_panel_settings.rs +++ b/crates/project_panel/src/project_panel_settings.rs @@ -22,6 +22,7 @@ pub struct ProjectPanelSettings { pub auto_reveal_entries: bool, pub auto_fold_dirs: bool, pub scrollbar: ScrollbarSettings, + pub show_diagnostic_errors: bool, } /// When to show the scrollbar in the project panel. @@ -96,6 +97,10 @@ pub struct ProjectPanelSettingsContent { pub auto_fold_dirs: Option, /// Scrollbar-related settings pub scrollbar: Option, + /// Whether to highlight errors in the project panel. + /// + /// Default: true + pub show_diagnostic_errors: Option, } impl Settings for ProjectPanelSettings { From bc64eb2e884b3caf4d153a29d97d2c3dc24d63d9 Mon Sep 17 00:00:00 2001 From: nilskch Date: Mon, 23 Sep 2024 21:17:25 +0100 Subject: [PATCH 05/28] some optimizations --- crates/project_panel/src/project_panel.rs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/crates/project_panel/src/project_panel.rs b/crates/project_panel/src/project_panel.rs index cc3e4f04fb64b..59000f4e8daed 100644 --- a/crates/project_panel/src/project_panel.rs +++ b/crates/project_panel/src/project_panel.rs @@ -241,9 +241,11 @@ impl ProjectPanel { } project::Event::DiskBasedDiagnosticsFinished { .. } | project::Event::DiagnosticsUpdated { .. } => { - this.update_diagnostics(cx); - this.update_visible_entries(None, cx); - cx.notify(); + if ProjectPanelSettings::get_global(cx).show_diagnostic_errors { + this.update_diagnostics(cx); + this.update_visible_entries(None, cx); + cx.notify(); + } } project::Event::WorktreeRemoved(id) => { this.expanded_dir_ids.remove(id); @@ -287,9 +289,12 @@ impl ProjectPanel { .detach(); let mut project_panel_settings = *ProjectPanelSettings::get_global(cx); - cx.observe_global::(move |_, cx| { + cx.observe_global::(move |this, cx| { let new_settings = *ProjectPanelSettings::get_global(cx); if project_panel_settings != new_settings { + if new_settings.show_diagnostic_errors { + this.update_diagnostics(cx); + } project_panel_settings = new_settings; cx.notify(); } From 18085fab550428013de78edc1effcab3ceffc37e Mon Sep 17 00:00:00 2001 From: nilskch Date: Mon, 23 Sep 2024 21:23:53 +0100 Subject: [PATCH 06/28] nit --- crates/project_panel/src/project_panel.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/crates/project_panel/src/project_panel.rs b/crates/project_panel/src/project_panel.rs index 59000f4e8daed..a052809345b4c 100644 --- a/crates/project_panel/src/project_panel.rs +++ b/crates/project_panel/src/project_panel.rs @@ -292,7 +292,9 @@ impl ProjectPanel { cx.observe_global::(move |this, cx| { let new_settings = *ProjectPanelSettings::get_global(cx); if project_panel_settings != new_settings { - if new_settings.show_diagnostic_errors { + if new_settings.show_diagnostic_errors + && !project_panel_settings.show_diagnostic_errors + { this.update_diagnostics(cx); } project_panel_settings = new_settings; From 4bebe918df6fee0263a526fdb2d13350e0a2953d Mon Sep 17 00:00:00 2001 From: nilskch Date: Mon, 23 Sep 2024 21:28:09 +0100 Subject: [PATCH 07/28] docs nit --- assets/settings/default.json | 2 +- crates/project_panel/src/project_panel_settings.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/settings/default.json b/assets/settings/default.json index a4a949234dc76..eb647925a7425 100644 --- a/assets/settings/default.json +++ b/assets/settings/default.json @@ -358,7 +358,7 @@ /// Default: always "show": "always" }, - /// Whether to highlight errors in the project panel. + /// Whether to show errors in the project panel. "show_diagnostic_errors": true }, "outline_panel": { diff --git a/crates/project_panel/src/project_panel_settings.rs b/crates/project_panel/src/project_panel_settings.rs index a16c2e9dab149..0c240db7bccb0 100644 --- a/crates/project_panel/src/project_panel_settings.rs +++ b/crates/project_panel/src/project_panel_settings.rs @@ -97,7 +97,7 @@ pub struct ProjectPanelSettingsContent { pub auto_fold_dirs: Option, /// Scrollbar-related settings pub scrollbar: Option, - /// Whether to highlight errors in the project panel. + /// Whether to show errors in the project panel. /// /// Default: true pub show_diagnostic_errors: Option, From 0761d360b0b1d1e85750ec936e6baf4e02927c22 Mon Sep 17 00:00:00 2001 From: nilskch Date: Mon, 23 Sep 2024 21:39:42 +0100 Subject: [PATCH 08/28] final cleanup --- crates/project_panel/src/project_panel.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/project_panel/src/project_panel.rs b/crates/project_panel/src/project_panel.rs index a052809345b4c..70cb706ef62f0 100644 --- a/crates/project_panel/src/project_panel.rs +++ b/crates/project_panel/src/project_panel.rs @@ -243,7 +243,6 @@ impl ProjectPanel { | project::Event::DiagnosticsUpdated { .. } => { if ProjectPanelSettings::get_global(cx).show_diagnostic_errors { this.update_diagnostics(cx); - this.update_visible_entries(None, cx); cx.notify(); } } From d1b32171e0e6f82d4bb32d6501a50d8068447183 Mon Sep 17 00:00:00 2001 From: Nils Koch Date: Tue, 24 Sep 2024 17:31:33 +0100 Subject: [PATCH 09/28] Update crates/project_panel/src/project_panel_settings.rs Co-authored-by: Thorsten Ball --- crates/project_panel/src/project_panel_settings.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/project_panel/src/project_panel_settings.rs b/crates/project_panel/src/project_panel_settings.rs index 0c240db7bccb0..3e7e29acc18ac 100644 --- a/crates/project_panel/src/project_panel_settings.rs +++ b/crates/project_panel/src/project_panel_settings.rs @@ -97,7 +97,7 @@ pub struct ProjectPanelSettingsContent { pub auto_fold_dirs: Option, /// Scrollbar-related settings pub scrollbar: Option, - /// Whether to show errors in the project panel. + /// Whether to mark the files containing diagnostic errors in the project panel. /// /// Default: true pub show_diagnostic_errors: Option, From eaa0937005a1886f6ee1de40d783d9526ebbae93 Mon Sep 17 00:00:00 2001 From: nilskch Date: Tue, 24 Sep 2024 20:11:36 +0100 Subject: [PATCH 10/28] add warnings to project panel --- Cargo.lock | 1 + assets/settings/default.json | 6 +- crates/project_panel/Cargo.toml | 2 + crates/project_panel/src/project_panel.rs | 105 ++++++++++++------ .../src/project_panel_settings.rs | 23 +++- crates/ui/src/styles/color.rs | 2 +- 6 files changed, 100 insertions(+), 39 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c0f6751b895e2..e95d81c8cb5fe 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8506,6 +8506,7 @@ dependencies = [ "gpui", "indexmap 1.9.3", "language", + "log", "menu", "pretty_assertions", "project", diff --git a/assets/settings/default.json b/assets/settings/default.json index eb647925a7425..4f9b19ea13725 100644 --- a/assets/settings/default.json +++ b/assets/settings/default.json @@ -358,8 +358,10 @@ /// Default: always "show": "always" }, - /// Whether to show errors in the project panel. - "show_diagnostic_errors": true + /// Which files to mark containing diagnostic errors/warnings in the project panel. + /// + /// Default: "errors" + "show_diagnostics": "errors" }, "outline_panel": { // Whether to show the outline panel button in the status bar diff --git a/crates/project_panel/Cargo.toml b/crates/project_panel/Cargo.toml index 11c7364e58f2f..5b1186949dbe6 100644 --- a/crates/project_panel/Cargo.toml +++ b/crates/project_panel/Cargo.toml @@ -36,6 +36,8 @@ util.workspace = true client.workspace = true worktree.workspace = true workspace.workspace = true +language.workspace = true +log.workspace = true [dev-dependencies] client = { workspace = true, features = ["test-support"] } diff --git a/crates/project_panel/src/project_panel.rs b/crates/project_panel/src/project_panel.rs index 70cb706ef62f0..307d851bdd6bb 100644 --- a/crates/project_panel/src/project_panel.rs +++ b/crates/project_panel/src/project_panel.rs @@ -1,6 +1,7 @@ mod project_panel_settings; mod scrollbar; use client::{ErrorCode, ErrorExt}; +use language::DiagnosticSeverity; use scrollbar::ProjectPanelScrollbar; use settings::{Settings, SettingsStore}; @@ -29,7 +30,9 @@ use project::{ relativize_path, Entry, EntryKind, Fs, Project, ProjectEntryId, ProjectPath, Worktree, WorktreeId, }; -use project_panel_settings::{ProjectPanelDockPosition, ProjectPanelSettings, ShowScrollbar}; +use project_panel_settings::{ + ProjectPanelDockPosition, ProjectPanelSettings, ShowDiagnostics, ShowScrollbar, +}; use serde::{Deserialize, Serialize}; use std::{ cell::{Cell, OnceCell}, @@ -82,7 +85,7 @@ pub struct ProjectPanel { show_scrollbar: bool, scrollbar_drag_thumb_offset: Rc>>, hide_scrollbar_task: Option>, - diagnostic_error_paths: HashSet, + diagnostics: HashMap<(WorktreeId, PathBuf), DiagnosticSeverity>, } #[derive(Clone, Debug)] @@ -114,7 +117,7 @@ struct EntryDetails { is_editing: bool, is_processing: bool, is_cut: bool, - is_diagnostic_error: bool, + diagnostics_color: Option, git_status: Option, is_private: bool, worktree_id: WorktreeId, @@ -241,7 +244,8 @@ impl ProjectPanel { } project::Event::DiskBasedDiagnosticsFinished { .. } | project::Event::DiagnosticsUpdated { .. } => { - if ProjectPanelSettings::get_global(cx).show_diagnostic_errors { + if ProjectPanelSettings::get_global(cx).show_diagnostics != ShowDiagnostics::Off + { this.update_diagnostics(cx); cx.notify(); } @@ -291,10 +295,12 @@ impl ProjectPanel { cx.observe_global::(move |this, cx| { let new_settings = *ProjectPanelSettings::get_global(cx); if project_panel_settings != new_settings { - if new_settings.show_diagnostic_errors - && !project_panel_settings.show_diagnostic_errors - { - this.update_diagnostics(cx); + if new_settings.show_diagnostics != project_panel_settings.show_diagnostics { + if new_settings.show_diagnostics != ShowDiagnostics::Off { + this.update_diagnostics(cx); + } else { + this.diagnostics = Default::default(); + } } project_panel_settings = new_settings; cx.notify(); @@ -326,7 +332,7 @@ impl ProjectPanel { show_scrollbar: !Self::should_autohide_scrollbar(cx), hide_scrollbar_task: None, scrollbar_drag_thumb_offset: Default::default(), - diagnostic_error_paths: Default::default(), + diagnostics: Default::default(), }; this.update_visible_entries(None, cx); @@ -449,30 +455,53 @@ impl ProjectPanel { } fn update_diagnostics(&mut self, cx: &mut ViewContext) { - self.diagnostic_error_paths = self - .project + let show_warnings = + ProjectPanelSettings::get_global(cx).show_diagnostics == ShowDiagnostics::All; + self.diagnostics = Default::default(); + self.project .read(cx) .diagnostic_summaries(false, cx) .filter_map(|(path, _, diagnostic_summary)| { if diagnostic_summary.error_count > 0 { - Some(path) + Some((path, DiagnosticSeverity::ERROR)) + } else if show_warnings && diagnostic_summary.warning_count > 0 { + Some((path, DiagnosticSeverity::WARNING)) } else { None } }) - .flat_map(|project_path| { - let mut path_buf = PathBuf::new(); - project_path - .path - .components() - .map(|component| { - path_buf.push(component); - path_buf.clone() - }) - .chain(std::iter::once(PathBuf::from(""))) - .collect::>() + .for_each(|(project_path, diagnostic_severity)| { + let mut path_buffer = PathBuf::new(); + self.update_highest_diagnostic_severity( + &project_path, + path_buffer.clone(), + diagnostic_severity, + ); + + for component in project_path.path.components() { + path_buffer.push(component); + self.update_highest_diagnostic_severity( + &project_path, + path_buffer.clone(), + diagnostic_severity, + ); + } + }); + } + + fn update_highest_diagnostic_severity( + &mut self, + project_path: &ProjectPath, + path_buffer: PathBuf, + diagnostic_severity: DiagnosticSeverity, + ) { + self.diagnostics + .entry((project_path.worktree_id, path_buffer.clone())) + .and_modify(|max_diagnostic_severity| { + *max_diagnostic_severity = + std::cmp::min(*max_diagnostic_severity, diagnostic_severity); }) - .collect(); + .or_insert(diagnostic_severity); } fn serialize(&mut self, cx: &mut ViewContext) { @@ -2066,13 +2095,13 @@ impl ProjectPanel { } let end_ix = range.end.min(ix + visible_worktree_entries.len()); - let (git_status_setting, show_file_icons, show_folder_icons, show_diagnostic_errors) = { + let (git_status_setting, show_file_icons, show_folder_icons, show_diagnostics) = { let settings = ProjectPanelSettings::get_global(cx); ( settings.git_status, settings.file_icons, settings.folder_icons, - settings.show_diagnostic_errors, + settings.show_diagnostics != ShowDiagnostics::Off, ) }; if let Some(worktree) = self.project.read(cx).worktree_for_id(*worktree_id, cx) { @@ -2133,6 +2162,19 @@ impl ProjectPanel { worktree_id: snapshot.id(), entry_id: entry.id, }; + + let diagnostics_color = if show_diagnostics { + self.diagnostics + .get(&(*worktree_id, entry.path.to_path_buf())) + .and_then(|diagnostic_severity| match *diagnostic_severity { + DiagnosticSeverity::ERROR => Some(Color::Error), + DiagnosticSeverity::WARNING => Some(Color::Warning), + _ => None, + }) + } else { + None + }; + let mut details = EntryDetails { filename, icon, @@ -2149,10 +2191,7 @@ impl ProjectPanel { .clipboard .as_ref() .map_or(false, |e| e.is_cut() && e.items().contains(&selection)), - is_diagnostic_error: show_diagnostic_errors - && self - .diagnostic_error_paths - .contains(&entry.path.to_path_buf()), + diagnostics_color, git_status: status, is_private: entry.is_private, worktree_id: *worktree_id, @@ -2242,8 +2281,10 @@ impl ProjectPanel { .selection .map_or(false, |selection| selection.entry_id == entry_id); let width = self.size(cx); - let filename_text_color = if details.is_diagnostic_error { - Color::Error + let filename_text_color = if settings.show_diagnostics != ShowDiagnostics::Off + && details.diagnostics_color.is_some() + { + details.diagnostics_color.unwrap() } else { entry_git_aware_label_color(details.git_status, details.is_ignored, is_marked) }; diff --git a/crates/project_panel/src/project_panel_settings.rs b/crates/project_panel/src/project_panel_settings.rs index 3e7e29acc18ac..d5e466e31d89f 100644 --- a/crates/project_panel/src/project_panel_settings.rs +++ b/crates/project_panel/src/project_panel_settings.rs @@ -22,7 +22,7 @@ pub struct ProjectPanelSettings { pub auto_reveal_entries: bool, pub auto_fold_dirs: bool, pub scrollbar: ScrollbarSettings, - pub show_diagnostic_errors: bool, + pub show_diagnostics: ShowDiagnostics, } /// When to show the scrollbar in the project panel. @@ -54,6 +54,21 @@ pub struct ScrollbarSettingsContent { pub show: Option, } +/// Which files to mark containing diagnostic errors/warnings in the project panel. +/// +/// Default: errors +#[derive(Copy, Clone, Debug, Default, Serialize, Deserialize, JsonSchema, PartialEq, Eq)] +#[serde(rename_all = "snake_case")] +pub enum ShowDiagnostics { + /// Never mark the diagnostic errors/warnings in the project panel. + Off, + /// Mark files containing diagnostic errors or warnings in the project panel. + All, + #[default] + /// Mark files containing diagnostic errors in the project panel. + Errors, +} + #[derive(Clone, Default, Serialize, Deserialize, JsonSchema, Debug)] pub struct ProjectPanelSettingsContent { /// Whether to show the project panel button in the status bar. @@ -97,10 +112,10 @@ pub struct ProjectPanelSettingsContent { pub auto_fold_dirs: Option, /// Scrollbar-related settings pub scrollbar: Option, - /// Whether to mark the files containing diagnostic errors in the project panel. + /// Which files to mark containing diagnostic errors/warnings in the project panel. /// - /// Default: true - pub show_diagnostic_errors: Option, + /// Default: errors + pub show_diagnostics: Option, } impl Settings for ProjectPanelSettings { diff --git a/crates/ui/src/styles/color.rs b/crates/ui/src/styles/color.rs index b35728e478fb5..78c082ea159d3 100644 --- a/crates/ui/src/styles/color.rs +++ b/crates/ui/src/styles/color.rs @@ -2,7 +2,7 @@ use gpui::{Hsla, WindowContext}; use theme::ActiveTheme; /// Sets a color that has a consistent meaning across all themes. -#[derive(Debug, Default, PartialEq, Copy, Clone)] +#[derive(Debug, Default, Eq, PartialEq, Copy, Clone)] pub enum Color { #[default] Default, From cddc98e17973ec9e064e13a3db9f935e8a952832 Mon Sep 17 00:00:00 2001 From: nilskch Date: Tue, 24 Sep 2024 20:35:59 +0100 Subject: [PATCH 11/28] rename var --- crates/project_panel/src/project_panel.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/project_panel/src/project_panel.rs b/crates/project_panel/src/project_panel.rs index 307d851bdd6bb..e2f0b595e8a97 100644 --- a/crates/project_panel/src/project_panel.rs +++ b/crates/project_panel/src/project_panel.rs @@ -497,9 +497,9 @@ impl ProjectPanel { ) { self.diagnostics .entry((project_path.worktree_id, path_buffer.clone())) - .and_modify(|max_diagnostic_severity| { - *max_diagnostic_severity = - std::cmp::min(*max_diagnostic_severity, diagnostic_severity); + .and_modify(|strongest_diagnostic_severity| { + *strongest_diagnostic_severity = + std::cmp::min(*strongest_diagnostic_severity, diagnostic_severity); }) .or_insert(diagnostic_severity); } From 53f07c553c84a6a908fb0164afcd4d46e834a17a Mon Sep 17 00:00:00 2001 From: nilskch Date: Tue, 24 Sep 2024 22:14:03 +0100 Subject: [PATCH 12/28] cleanup --- assets/settings/default.json | 2 +- crates/project_panel/src/project_panel.rs | 14 +++++++------- crates/project_panel/src/project_panel_settings.rs | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/assets/settings/default.json b/assets/settings/default.json index 4f9b19ea13725..8e49ad73716b6 100644 --- a/assets/settings/default.json +++ b/assets/settings/default.json @@ -358,7 +358,7 @@ /// Default: always "show": "always" }, - /// Which files to mark containing diagnostic errors/warnings in the project panel. + /// Which files containing diagnostic errors/warnings to mark in the project panel. /// /// Default: "errors" "show_diagnostics": "errors" diff --git a/crates/project_panel/src/project_panel.rs b/crates/project_panel/src/project_panel.rs index e2f0b595e8a97..6a3e7bbc3e284 100644 --- a/crates/project_panel/src/project_panel.rs +++ b/crates/project_panel/src/project_panel.rs @@ -2281,13 +2281,13 @@ impl ProjectPanel { .selection .map_or(false, |selection| selection.entry_id == entry_id); let width = self.size(cx); - let filename_text_color = if settings.show_diagnostics != ShowDiagnostics::Off - && details.diagnostics_color.is_some() - { - details.diagnostics_color.unwrap() - } else { - entry_git_aware_label_color(details.git_status, details.is_ignored, is_marked) - }; + let filename_text_color = details + .diagnostics_color + .unwrap_or(entry_git_aware_label_color( + details.git_status, + details.is_ignored, + is_marked, + )); let file_name = details.filename.clone(); let mut icon = details.icon.clone(); if settings.file_icons && show_editor && details.kind.is_file() { diff --git a/crates/project_panel/src/project_panel_settings.rs b/crates/project_panel/src/project_panel_settings.rs index d5e466e31d89f..2fb529aa75fc9 100644 --- a/crates/project_panel/src/project_panel_settings.rs +++ b/crates/project_panel/src/project_panel_settings.rs @@ -54,7 +54,7 @@ pub struct ScrollbarSettingsContent { pub show: Option, } -/// Which files to mark containing diagnostic errors/warnings in the project panel. +/// Which files containing diagnostic errors/warnings to mark in the project panel. /// /// Default: errors #[derive(Copy, Clone, Debug, Default, Serialize, Deserialize, JsonSchema, PartialEq, Eq)] @@ -112,7 +112,7 @@ pub struct ProjectPanelSettingsContent { pub auto_fold_dirs: Option, /// Scrollbar-related settings pub scrollbar: Option, - /// Which files to mark containing diagnostic errors/warnings in the project panel. + /// Which files containing diagnostic errors/warnings to mark in the project panel. /// /// Default: errors pub show_diagnostics: Option, From 108ccf2df9f194ad5e416a37dd899fa75e62a1a9 Mon Sep 17 00:00:00 2001 From: nilskch Date: Tue, 24 Sep 2024 23:42:02 +0100 Subject: [PATCH 13/28] remove log dependency again --- Cargo.lock | 1 - crates/project_panel/Cargo.toml | 1 - 2 files changed, 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e95d81c8cb5fe..c0f6751b895e2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8506,7 +8506,6 @@ dependencies = [ "gpui", "indexmap 1.9.3", "language", - "log", "menu", "pretty_assertions", "project", diff --git a/crates/project_panel/Cargo.toml b/crates/project_panel/Cargo.toml index 5b1186949dbe6..d53d9116223bf 100644 --- a/crates/project_panel/Cargo.toml +++ b/crates/project_panel/Cargo.toml @@ -37,7 +37,6 @@ client.workspace = true worktree.workspace = true workspace.workspace = true language.workspace = true -log.workspace = true [dev-dependencies] client = { workspace = true, features = ["test-support"] } From 492de1f32e51ab80b70eeb305cfdcc0bff005383 Mon Sep 17 00:00:00 2001 From: nilskch Date: Wed, 25 Sep 2024 20:43:50 +0100 Subject: [PATCH 14/28] test design with additional icons --- assets/icons/dot.svg | 3 ++ crates/editor/src/items.rs | 38 ++++++++++++++++ crates/project_panel/src/project_panel.rs | 53 +++++++++++++++-------- crates/ui/src/components/icon.rs | 1 + 4 files changed, 78 insertions(+), 17 deletions(-) create mode 100644 assets/icons/dot.svg diff --git a/assets/icons/dot.svg b/assets/icons/dot.svg new file mode 100644 index 0000000000000..4fef3328fbee4 --- /dev/null +++ b/assets/icons/dot.svg @@ -0,0 +1,3 @@ + + + diff --git a/crates/editor/src/items.rs b/crates/editor/src/items.rs index 1d301f2ee68cd..0346a83f64928 100644 --- a/crates/editor/src/items.rs +++ b/crates/editor/src/items.rs @@ -18,6 +18,7 @@ use gpui::{ use language::{ proto::serialize_anchor as serialize_text_anchor, Bias, Buffer, CharKind, Point, SelectionGoal, }; +use lsp::DiagnosticSeverity; use multi_buffer::AnchorRangeExt; use project::{ project_settings::ProjectSettings, search::SearchQuery, FormatTrigger, Item as _, Project, @@ -1481,6 +1482,43 @@ pub fn entry_label_color(selected: bool) -> Color { } } +pub fn entry_diagnostic_and_git_aware_extra_icon_name( + diagnostic_severity: Option<&DiagnosticSeverity>, + git_status: Option, + ignored: bool, +) -> Option { + if let Some(diagnostic_severity) = diagnostic_severity { + if *diagnostic_severity == DiagnosticSeverity::ERROR { + return Some(IconName::XCircle); + } + if *diagnostic_severity == DiagnosticSeverity::WARNING { + return Some(IconName::Warning); + } + } + if !ignored && git_status.is_some() { + Some(IconName::Dot) + } else { + None + } +} + +pub fn entry_diagnostic_and_git_aware_label_color( + diagnostic_severity: Option<&DiagnosticSeverity>, + git_status: Option, + ignored: bool, + selected: bool, +) -> Color { + if let Some(diagnostic_severity) = diagnostic_severity { + if *diagnostic_severity == DiagnosticSeverity::ERROR { + return Color::Error; + } + if *diagnostic_severity == DiagnosticSeverity::WARNING { + return Color::Warning; + } + } + entry_git_aware_label_color(git_status, ignored, selected) +} + pub fn entry_git_aware_label_color( git_status: Option, ignored: bool, diff --git a/crates/project_panel/src/project_panel.rs b/crates/project_panel/src/project_panel.rs index 6a3e7bbc3e284..86ee8180c73ce 100644 --- a/crates/project_panel/src/project_panel.rs +++ b/crates/project_panel/src/project_panel.rs @@ -7,7 +7,9 @@ use settings::{Settings, SettingsStore}; use db::kvp::KEY_VALUE_STORE; use editor::{ - items::entry_git_aware_label_color, + items::{ + entry_diagnostic_and_git_aware_extra_icon_name, entry_diagnostic_and_git_aware_label_color, + }, scroll::{Autoscroll, ScrollbarAutoHide}, Editor, }; @@ -117,7 +119,8 @@ struct EntryDetails { is_editing: bool, is_processing: bool, is_cut: bool, - diagnostics_color: Option, + filename_text_color: Color, + extra_icon_name: Option, git_status: Option, is_private: bool, worktree_id: WorktreeId, @@ -2163,18 +2166,28 @@ impl ProjectPanel { entry_id: entry.id, }; - let diagnostics_color = if show_diagnostics { + let is_marked = self.marked_entries.contains(&selection); + + let diagnostic_severity = if show_diagnostics { self.diagnostics .get(&(*worktree_id, entry.path.to_path_buf())) - .and_then(|diagnostic_severity| match *diagnostic_severity { - DiagnosticSeverity::ERROR => Some(Color::Error), - DiagnosticSeverity::WARNING => Some(Color::Warning), - _ => None, - }) } else { None }; + let filename_text_color = entry_diagnostic_and_git_aware_label_color( + diagnostic_severity, + status, + entry.is_ignored, + is_marked, + ); + + let extra_icon_name = entry_diagnostic_and_git_aware_extra_icon_name( + diagnostic_severity, + status, + entry.is_ignored, + ); + let mut details = EntryDetails { filename, icon, @@ -2184,14 +2197,15 @@ impl ProjectPanel { is_ignored: entry.is_ignored, is_expanded, is_selected: self.selection == Some(selection), - is_marked: self.marked_entries.contains(&selection), + is_marked, is_editing: false, is_processing: false, is_cut: self .clipboard .as_ref() .map_or(false, |e| e.is_cut() && e.items().contains(&selection)), - diagnostics_color, + filename_text_color, + extra_icon_name, git_status: status, is_private: entry.is_private, worktree_id: *worktree_id, @@ -2281,13 +2295,7 @@ impl ProjectPanel { .selection .map_or(false, |selection| selection.entry_id == entry_id); let width = self.size(cx); - let filename_text_color = details - .diagnostics_color - .unwrap_or(entry_git_aware_label_color( - details.git_status, - details.is_ignored, - is_marked, - )); + let filename_text_color = details.filename_text_color; let file_name = details.filename.clone(); let mut icon = details.icon.clone(); if settings.file_icons && show_editor && details.kind.is_file() { @@ -2311,6 +2319,8 @@ impl ProjectPanel { active_selection: selection, marked_selections: selections, }; + let extra_icon_name = details.extra_icon_name; + div() .id(entry_id.to_proto() as usize) .on_drag_move::(cx.listener( @@ -2487,6 +2497,15 @@ impl ProjectPanel { } .ml_1(), ) + .child(if let Some(icon_name) = extra_icon_name { + h_flex().child( + Icon::new(icon_name) + .size(IconSize::XSmall) + .color(filename_text_color), + ) + } else { + div() + }) // TODO(nilskch) .on_click(cx.listener(move |this, event: &gpui::ClickEvent, cx| { if event.down.button == MouseButton::Right || event.down.first_mouse { return; diff --git a/crates/ui/src/components/icon.rs b/crates/ui/src/components/icon.rs index 323181e84156f..81d77e6359c33 100644 --- a/crates/ui/src/components/icon.rs +++ b/crates/ui/src/components/icon.rs @@ -170,6 +170,7 @@ pub enum IconName { DatabaseZap, Delete, Disconnected, + Dot, Download, Ellipsis, EllipsisVertical, From 15c44956149a173b877057289bb32f99445d453b Mon Sep 17 00:00:00 2001 From: nilskch Date: Wed, 25 Sep 2024 21:19:38 +0100 Subject: [PATCH 15/28] cleanup --- crates/project_panel/src/project_panel.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/project_panel/src/project_panel.rs b/crates/project_panel/src/project_panel.rs index fa12d63d307d3..94ec4b4521e32 100644 --- a/crates/project_panel/src/project_panel.rs +++ b/crates/project_panel/src/project_panel.rs @@ -2501,14 +2501,14 @@ impl ProjectPanel { .ml_1(), ) .child(if let Some(icon_name) = extra_icon_name { - h_flex().child( + h_flex().size(IconSize::default().rems()).child( Icon::new(icon_name) .size(IconSize::XSmall) .color(filename_text_color), ) } else { div() - }) // TODO(nilskch) + }) .on_click(cx.listener(move |this, event: &gpui::ClickEvent, cx| { if event.down.button == MouseButton::Right || event.down.first_mouse { return; From edbb6c6ca0c452c59c3dd5442d4ba4964e79c049 Mon Sep 17 00:00:00 2001 From: nilskch Date: Thu, 26 Sep 2024 19:47:12 +0100 Subject: [PATCH 16/28] implement feedback --- assets/icons/dot.svg | 3 - assets/settings/default.json | 10 +- crates/editor/src/items.rs | 39 ++----- crates/project_panel/src/project_panel.rs | 126 +++++++++++----------- crates/ui/src/components/icon.rs | 1 - 5 files changed, 77 insertions(+), 102 deletions(-) delete mode 100644 assets/icons/dot.svg diff --git a/assets/icons/dot.svg b/assets/icons/dot.svg deleted file mode 100644 index 4fef3328fbee4..0000000000000 --- a/assets/icons/dot.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/settings/default.json b/assets/settings/default.json index d1ed26937fe3a..59b252f77d294 100644 --- a/assets/settings/default.json +++ b/assets/settings/default.json @@ -361,9 +361,15 @@ "show": "always" }, /// Which files containing diagnostic errors/warnings to mark in the project panel. + /// This setting can take the following three values: /// - /// Default: "errors" - "show_diagnostics": "errors" + /// 1. Do not mark any files: + /// "off" + /// 2. Only mark files with errors: + /// "errors" + /// 3. Mark files with errors and warnings: + /// "all" + "show_diagnostics": "all" }, "outline_panel": { // Whether to show the outline panel button in the status bar diff --git a/crates/editor/src/items.rs b/crates/editor/src/items.rs index 27e8b9f4e0016..fc37d4fd60d89 100644 --- a/crates/editor/src/items.rs +++ b/crates/editor/src/items.rs @@ -1482,41 +1482,20 @@ pub fn entry_label_color(selected: bool) -> Color { } } -pub fn entry_diagnostic_and_git_aware_extra_icon_name( - diagnostic_severity: Option<&DiagnosticSeverity>, - git_status: Option, - ignored: bool, -) -> Option { - if let Some(diagnostic_severity) = diagnostic_severity { - if *diagnostic_severity == DiagnosticSeverity::ERROR { - return Some(IconName::XCircle); - } - if *diagnostic_severity == DiagnosticSeverity::WARNING { - return Some(IconName::Warning); - } - } - if !ignored && git_status.is_some() { - Some(IconName::Dot) - } else { - None - } -} - -pub fn entry_diagnostic_and_git_aware_label_color( +pub fn entry_text_color_and_extra_icon_name( diagnostic_severity: Option<&DiagnosticSeverity>, git_status: Option, ignored: bool, selected: bool, -) -> Color { - if let Some(diagnostic_severity) = diagnostic_severity { - if *diagnostic_severity == DiagnosticSeverity::ERROR { - return Color::Error; - } - if *diagnostic_severity == DiagnosticSeverity::WARNING { - return Color::Warning; - } +) -> (Color, Option) { + match diagnostic_severity { + Some(&DiagnosticSeverity::ERROR) => (Color::Error, Some(IconName::XCircle)), + Some(&DiagnosticSeverity::WARNING) => (Color::Warning, Some(IconName::Warning)), + _ => ( + entry_git_aware_label_color(git_status, ignored, selected), + None, + ), } - entry_git_aware_label_color(git_status, ignored, selected) } pub fn entry_git_aware_label_color( diff --git a/crates/project_panel/src/project_panel.rs b/crates/project_panel/src/project_panel.rs index 94ec4b4521e32..11c8c95079a9c 100644 --- a/crates/project_panel/src/project_panel.rs +++ b/crates/project_panel/src/project_panel.rs @@ -7,9 +7,7 @@ use settings::{Settings, SettingsStore}; use db::kvp::KEY_VALUE_STORE; use editor::{ - items::{ - entry_diagnostic_and_git_aware_extra_icon_name, entry_diagnostic_and_git_aware_label_color, - }, + items::entry_text_color_and_extra_icon_name, scroll::{Autoscroll, ScrollbarAutoHide}, Editor, }; @@ -298,14 +296,8 @@ impl ProjectPanel { cx.observe_global::(move |this, cx| { let new_settings = *ProjectPanelSettings::get_global(cx); if project_panel_settings != new_settings { - if new_settings.show_diagnostics != project_panel_settings.show_diagnostics { - if new_settings.show_diagnostics != ShowDiagnostics::Off { - this.update_diagnostics(cx); - } else { - this.diagnostics = Default::default(); - } - } project_panel_settings = new_settings; + this.update_diagnostics(cx); cx.notify(); } }) @@ -458,47 +450,55 @@ impl ProjectPanel { } fn update_diagnostics(&mut self, cx: &mut ViewContext) { - let show_warnings = - ProjectPanelSettings::get_global(cx).show_diagnostics == ShowDiagnostics::All; - self.diagnostics = Default::default(); - self.project - .read(cx) - .diagnostic_summaries(false, cx) - .filter_map(|(path, _, diagnostic_summary)| { - if diagnostic_summary.error_count > 0 { - Some((path, DiagnosticSeverity::ERROR)) - } else if show_warnings && diagnostic_summary.warning_count > 0 { - Some((path, DiagnosticSeverity::WARNING)) - } else { - None - } - }) - .for_each(|(project_path, diagnostic_severity)| { - let mut path_buffer = PathBuf::new(); - self.update_highest_diagnostic_severity( - &project_path, - path_buffer.clone(), - diagnostic_severity, - ); + let mut diagnostics: HashMap<(WorktreeId, PathBuf), DiagnosticSeverity> = + Default::default(); + let show_diagnostics_setting = ProjectPanelSettings::get_global(cx).show_diagnostics; - for component in project_path.path.components() { - path_buffer.push(component); - self.update_highest_diagnostic_severity( + if show_diagnostics_setting != ShowDiagnostics::Off { + self.project + .read(cx) + .diagnostic_summaries(false, cx) + .filter_map(|(path, _, diagnostic_summary)| { + if diagnostic_summary.error_count > 0 { + Some((path, DiagnosticSeverity::ERROR)) + } else if show_diagnostics_setting == ShowDiagnostics::All + && diagnostic_summary.warning_count > 0 + { + Some((path, DiagnosticSeverity::WARNING)) + } else { + None + } + }) + .for_each(|(project_path, diagnostic_severity)| { + let mut path_buffer = PathBuf::new(); + Self::update_strongest_diagnostic_severity( + &mut diagnostics, &project_path, path_buffer.clone(), diagnostic_severity, ); - } - }); + + for component in project_path.path.components() { + path_buffer.push(component); + Self::update_strongest_diagnostic_severity( + &mut diagnostics, + &project_path, + path_buffer.clone(), + diagnostic_severity, + ); + } + }); + } + self.diagnostics = diagnostics; } - fn update_highest_diagnostic_severity( - &mut self, + fn update_strongest_diagnostic_severity( + diagnostics: &mut HashMap<(WorktreeId, PathBuf), DiagnosticSeverity>, project_path: &ProjectPath, path_buffer: PathBuf, diagnostic_severity: DiagnosticSeverity, ) { - self.diagnostics + diagnostics .entry((project_path.worktree_id, path_buffer.clone())) .and_modify(|strongest_diagnostic_severity| { *strongest_diagnostic_severity = @@ -2101,13 +2101,12 @@ impl ProjectPanel { } let end_ix = range.end.min(ix + visible_worktree_entries.len()); - let (git_status_setting, show_file_icons, show_folder_icons, show_diagnostics) = { + let (git_status_setting, show_file_icons, show_folder_icons) = { let settings = ProjectPanelSettings::get_global(cx); ( settings.git_status, settings.file_icons, settings.folder_icons, - settings.show_diagnostics != ShowDiagnostics::Off, ) }; if let Some(worktree) = self.project.read(cx).worktree_for_id(*worktree_id, cx) { @@ -2171,25 +2170,17 @@ impl ProjectPanel { let is_marked = self.marked_entries.contains(&selection); - let diagnostic_severity = if show_diagnostics { - self.diagnostics - .get(&(*worktree_id, entry.path.to_path_buf())) - } else { - None - }; - - let filename_text_color = entry_diagnostic_and_git_aware_label_color( - diagnostic_severity, - status, - entry.is_ignored, - is_marked, - ); + let diagnostic_severity = self + .diagnostics + .get(&(*worktree_id, entry.path.to_path_buf())); - let extra_icon_name = entry_diagnostic_and_git_aware_extra_icon_name( - diagnostic_severity, - status, - entry.is_ignored, - ); + let (filename_text_color, extra_icon_name) = + entry_text_color_and_extra_icon_name( + diagnostic_severity, + status, + entry.is_ignored, + is_marked, + ); let mut details = EntryDetails { filename, @@ -2500,12 +2491,15 @@ impl ProjectPanel { } .ml_1(), ) - .child(if let Some(icon_name) = extra_icon_name { - h_flex().size(IconSize::default().rems()).child( - Icon::new(icon_name) - .size(IconSize::XSmall) - .color(filename_text_color), - ) + .end_slot(if let Some(icon_name) = extra_icon_name { + h_flex() + .size(IconSize::default().rems()) + .opacity(0.7) + .child( + Icon::new(icon_name) + .size(IconSize::XSmall) + .color(filename_text_color), + ) } else { div() }) diff --git a/crates/ui/src/components/icon.rs b/crates/ui/src/components/icon.rs index 81d77e6359c33..323181e84156f 100644 --- a/crates/ui/src/components/icon.rs +++ b/crates/ui/src/components/icon.rs @@ -170,7 +170,6 @@ pub enum IconName { DatabaseZap, Delete, Disconnected, - Dot, Download, Ellipsis, EllipsisVertical, From dcec8e3b8eaa3da4f4d5cd80cdf96c17e77e9356 Mon Sep 17 00:00:00 2001 From: nilskch Date: Thu, 26 Sep 2024 19:50:43 +0100 Subject: [PATCH 17/28] fix default value in docs --- crates/project_panel/src/project_panel_settings.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/project_panel/src/project_panel_settings.rs b/crates/project_panel/src/project_panel_settings.rs index 2fb529aa75fc9..69e41a132d52f 100644 --- a/crates/project_panel/src/project_panel_settings.rs +++ b/crates/project_panel/src/project_panel_settings.rs @@ -56,7 +56,7 @@ pub struct ScrollbarSettingsContent { /// Which files containing diagnostic errors/warnings to mark in the project panel. /// -/// Default: errors +/// Default: all #[derive(Copy, Clone, Debug, Default, Serialize, Deserialize, JsonSchema, PartialEq, Eq)] #[serde(rename_all = "snake_case")] pub enum ShowDiagnostics { @@ -114,7 +114,7 @@ pub struct ProjectPanelSettingsContent { pub scrollbar: Option, /// Which files containing diagnostic errors/warnings to mark in the project panel. /// - /// Default: errors + /// Default: all pub show_diagnostics: Option, } From 96e653636135351bc5da977e0727a8dd7321070c Mon Sep 17 00:00:00 2001 From: nilskch Date: Thu, 26 Sep 2024 19:53:56 +0100 Subject: [PATCH 18/28] cleanup --- crates/project_panel/src/project_panel_settings.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/project_panel/src/project_panel_settings.rs b/crates/project_panel/src/project_panel_settings.rs index 69e41a132d52f..beab8f028e906 100644 --- a/crates/project_panel/src/project_panel_settings.rs +++ b/crates/project_panel/src/project_panel_settings.rs @@ -62,11 +62,11 @@ pub struct ScrollbarSettingsContent { pub enum ShowDiagnostics { /// Never mark the diagnostic errors/warnings in the project panel. Off, - /// Mark files containing diagnostic errors or warnings in the project panel. - All, - #[default] /// Mark files containing diagnostic errors in the project panel. Errors, + #[default] + /// Mark files containing diagnostic errors or warnings in the project panel. + All, } #[derive(Clone, Default, Serialize, Deserialize, JsonSchema, Debug)] From 370362adbc06cb0c46a244fbd4fb1bf0981112d8 Mon Sep 17 00:00:00 2001 From: nilskch Date: Tue, 15 Oct 2024 21:46:28 +0100 Subject: [PATCH 19/28] implement new design --- assets/icons/indicator_warning.svg | 3 + assets/icons/triangle.svg | 3 + assets/icons/x.svg | 3 + crates/editor/src/items.rs | 30 ++++++---- crates/project_panel/src/project_panel.rs | 72 +++++++++++++---------- crates/ui/src/components/icon.rs | 7 ++- 6 files changed, 72 insertions(+), 46 deletions(-) create mode 100644 assets/icons/indicator_warning.svg create mode 100644 assets/icons/triangle.svg create mode 100644 assets/icons/x.svg diff --git a/assets/icons/indicator_warning.svg b/assets/icons/indicator_warning.svg new file mode 100644 index 0000000000000..785efe369875f --- /dev/null +++ b/assets/icons/indicator_warning.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/icons/triangle.svg b/assets/icons/triangle.svg new file mode 100644 index 0000000000000..8c44b91b78d30 --- /dev/null +++ b/assets/icons/triangle.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/icons/x.svg b/assets/icons/x.svg new file mode 100644 index 0000000000000..d090cb55bfebb --- /dev/null +++ b/assets/icons/x.svg @@ -0,0 +1,3 @@ + + + diff --git a/crates/editor/src/items.rs b/crates/editor/src/items.rs index fc37d4fd60d89..d9dcb7893a01a 100644 --- a/crates/editor/src/items.rs +++ b/crates/editor/src/items.rs @@ -39,7 +39,7 @@ use std::{ }; use text::{BufferId, Selection}; use theme::{Theme, ThemeSettings}; -use ui::{h_flex, prelude::*, Label}; +use ui::{h_flex, prelude::*, IconDecoration, Label}; use util::{paths::PathExt, ResultExt, TryFutureExt}; use workspace::item::{BreadcrumbText, FollowEvent}; use workspace::{ @@ -1482,19 +1482,23 @@ pub fn entry_label_color(selected: bool) -> Color { } } -pub fn entry_text_color_and_extra_icon_name( - diagnostic_severity: Option<&DiagnosticSeverity>, - git_status: Option, - ignored: bool, - selected: bool, -) -> (Color, Option) { +pub fn entry_diagnostic_aware_icon_name_and_color( + diagnostic_severity: Option, +) -> Option<(IconName, Color)> { + match diagnostic_severity { + Some(DiagnosticSeverity::ERROR) => Some((IconName::X, Color::Error)), + Some(DiagnosticSeverity::WARNING) => Some((IconName::Triangle, Color::Warning)), + _ => None, + } +} + +pub fn entry_diagnostic_aware_decoration_and_color( + diagnostic_severity: Option, +) -> Option<(IconDecoration, Color)> { match diagnostic_severity { - Some(&DiagnosticSeverity::ERROR) => (Color::Error, Some(IconName::XCircle)), - Some(&DiagnosticSeverity::WARNING) => (Color::Warning, Some(IconName::Warning)), - _ => ( - entry_git_aware_label_color(git_status, ignored, selected), - None, - ), + Some(DiagnosticSeverity::ERROR) => Some((IconDecoration::X, Color::Error)), + Some(DiagnosticSeverity::WARNING) => Some((IconDecoration::Warning, Color::Warning)), + _ => None, } } diff --git a/crates/project_panel/src/project_panel.rs b/crates/project_panel/src/project_panel.rs index c4455e406ba17..4df602b7089b9 100644 --- a/crates/project_panel/src/project_panel.rs +++ b/crates/project_panel/src/project_panel.rs @@ -7,7 +7,10 @@ use settings::{Settings, SettingsStore}; use db::kvp::KEY_VALUE_STORE; use editor::{ - items::entry_text_color_and_extra_icon_name, + items::{ + entry_diagnostic_aware_decoration_and_color, entry_diagnostic_aware_icon_name_and_color, + entry_git_aware_label_color, + }, scroll::{Autoscroll, ScrollbarAutoHide}, Editor, EditorEvent, EditorSettings, ShowScrollbar, }; @@ -32,7 +35,7 @@ use project::{ relativize_path, Entry, EntryKind, Fs, Project, ProjectEntryId, ProjectPath, Worktree, WorktreeId, }; -use project_panel_settings::{ProjectPanelDockPosition, ProjectPanelSettings}; +use project_panel_settings::{ProjectPanelDockPosition, ProjectPanelSettings, ShowDiagnostics}; use serde::{Deserialize, Serialize}; use std::{ cell::{Cell, OnceCell}, @@ -45,7 +48,9 @@ use std::{ time::Duration, }; use theme::ThemeSettings; -use ui::{prelude::*, v_flex, ContextMenu, Icon, KeyBinding, Label, ListItem, Tooltip}; +use ui::{ + prelude::*, v_flex, ContextMenu, DecoratedIcon, Icon, KeyBinding, Label, ListItem, Tooltip, +}; use util::{maybe, ResultExt, TryFutureExt}; use workspace::{ dock::{DockPosition, Panel, PanelEvent}, @@ -122,7 +127,7 @@ struct EntryDetails { is_processing: bool, is_cut: bool, filename_text_color: Color, - extra_icon_name: Option, + diagnostic_severity: Option, git_status: Option, is_private: bool, worktree_id: WorktreeId, @@ -2284,15 +2289,11 @@ impl ProjectPanel { let diagnostic_severity = self .diagnostics - .get(&(*worktree_id, entry.path.to_path_buf())); + .get(&(*worktree_id, entry.path.to_path_buf())) + .cloned(); - let (filename_text_color, extra_icon_name) = - entry_text_color_and_extra_icon_name( - diagnostic_severity, - status, - entry.is_ignored, - is_marked, - ); + let filename_text_color = + entry_git_aware_label_color(status, entry.is_ignored, is_marked); let mut details = EntryDetails { filename, @@ -2311,7 +2312,7 @@ impl ProjectPanel { .as_ref() .map_or(false, |e| e.is_cut() && e.items().contains(&selection)), filename_text_color, - extra_icon_name, + diagnostic_severity, git_status: status, is_private: entry.is_private, worktree_id: *worktree_id, @@ -2401,7 +2402,6 @@ impl ProjectPanel { .selection .map_or(false, |selection| selection.entry_id == entry_id); let width = self.size(cx); - let filename_text_color = details.filename_text_color; let file_name = details.filename.clone(); let mut icon = details.icon.clone(); if settings.file_icons && show_editor && details.kind.is_file() { @@ -2411,6 +2411,9 @@ impl ProjectPanel { } } + let filename_text_color = details.filename_text_color; + let diagnostic_severity = details.diagnostic_severity; + let canonical_path = details .canonical_path .as_ref() @@ -2425,7 +2428,6 @@ impl ProjectPanel { active_selection: selection, marked_selections: selections, }; - let extra_icon_name = details.extra_icon_name; div() .id(entry_id.to_proto() as usize) @@ -2516,12 +2518,30 @@ impl ProjectPanel { ) }) .child(if let Some(icon) = &icon { - h_flex().child(Icon::from_path(icon.to_string()).color(filename_text_color)) + let icon = Icon::from_path(icon.to_string()); + if let Some((decoration, decoration_color)) = + entry_diagnostic_aware_decoration_and_color(diagnostic_severity) + { + h_flex().child( + DecoratedIcon::new(icon.color(Color::Muted), decoration) + .decoration_color(decoration_color), + ) + } else { + h_flex().child(icon.color(filename_text_color)) + } } else { - h_flex() - .size(IconSize::default().rems()) - .invisible() - .flex_none() + if let Some((icon_name, color)) = + entry_diagnostic_aware_icon_name_and_color(diagnostic_severity) + { + h_flex() + .size(IconSize::default().rems()) + .child(Icon::new(icon_name).color(color).size(IconSize::Small)) + } else { + h_flex() + .size(IconSize::default().rems()) + .invisible() + .flex_none() + } }) .child( if let (Some(editor), true) = (Some(&self.filename_editor), show_editor) { @@ -2594,18 +2614,6 @@ impl ProjectPanel { } .ml_1(), ) - .end_slot(if let Some(icon_name) = extra_icon_name { - h_flex() - .size(IconSize::default().rems()) - .opacity(0.7) - .child( - Icon::new(icon_name) - .size(IconSize::XSmall) - .color(filename_text_color), - ) - } else { - div() - }) .on_click(cx.listener(move |this, event: &gpui::ClickEvent, cx| { if event.down.button == MouseButton::Right || event.down.first_mouse { return; diff --git a/crates/ui/src/components/icon.rs b/crates/ui/src/components/icon.rs index 8d374ef67ca41..82df7d1f0a7f5 100644 --- a/crates/ui/src/components/icon.rs +++ b/crates/ui/src/components/icon.rs @@ -52,6 +52,7 @@ impl RenderOnce for AnyIcon { pub enum IconDecoration { Strikethrough, IndicatorDot, + Warning, X, } @@ -206,6 +207,7 @@ pub enum IconName { HistoryRerun, Indicator, IndicatorX, + IndicatorWarning, InlayHint, Library, LineHeight, @@ -276,6 +278,7 @@ pub enum IconName { Terminal, Trash, TrashAlt, + Triangle, TriangleRight, Undo, Unpin, @@ -284,13 +287,14 @@ pub enum IconName { Visible, Warning, WholeWord, + X, XCircle, ZedAssistant, ZedAssistantFilled, ZedXCopilot, } -#[derive(IntoElement)] +#[derive(Debug, IntoElement)] pub struct Icon { path: SharedString, color: Color, @@ -393,6 +397,7 @@ impl RenderOnce for DecoratedIcon { IconDecoration::Strikethrough => IconName::Strikethrough, IconDecoration::IndicatorDot => IconName::Indicator, IconDecoration::X => IconName::IndicatorX, + IconDecoration::Warning => IconName::IndicatorWarning, }; let decoration_svg = |icon: IconName| { From c22e70f47e122e1a0d34d210b34535f7cc5165a0 Mon Sep 17 00:00:00 2001 From: nilskch Date: Tue, 15 Oct 2024 22:18:54 +0100 Subject: [PATCH 20/28] make warning icon smaller --- assets/icons/indicator_warning.svg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/icons/indicator_warning.svg b/assets/icons/indicator_warning.svg index 785efe369875f..607b2a005e5ec 100644 --- a/assets/icons/indicator_warning.svg +++ b/assets/icons/indicator_warning.svg @@ -1,3 +1,3 @@ - + From 3b2c9903fe77cff227666a6d534a1b49943eb06b Mon Sep 17 00:00:00 2001 From: nilskch Date: Wed, 16 Oct 2024 07:14:08 +0100 Subject: [PATCH 21/28] cleanuo --- crates/editor/src/items.rs | 2 +- crates/project_panel/src/project_panel.rs | 7 +++---- crates/ui/src/components/icon.rs | 2 +- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/crates/editor/src/items.rs b/crates/editor/src/items.rs index d9dcb7893a01a..5f631e1bfaae2 100644 --- a/crates/editor/src/items.rs +++ b/crates/editor/src/items.rs @@ -1492,7 +1492,7 @@ pub fn entry_diagnostic_aware_icon_name_and_color( } } -pub fn entry_diagnostic_aware_decoration_and_color( +pub fn entry_diagnostic_aware_icon_decoration_and_color( diagnostic_severity: Option, ) -> Option<(IconDecoration, Color)> { match diagnostic_severity { diff --git a/crates/project_panel/src/project_panel.rs b/crates/project_panel/src/project_panel.rs index 4df602b7089b9..278de6d0c32ef 100644 --- a/crates/project_panel/src/project_panel.rs +++ b/crates/project_panel/src/project_panel.rs @@ -8,8 +8,8 @@ use settings::{Settings, SettingsStore}; use db::kvp::KEY_VALUE_STORE; use editor::{ items::{ - entry_diagnostic_aware_decoration_and_color, entry_diagnostic_aware_icon_name_and_color, - entry_git_aware_label_color, + entry_diagnostic_aware_icon_decoration_and_color, + entry_diagnostic_aware_icon_name_and_color, entry_git_aware_label_color, }, scroll::{Autoscroll, ScrollbarAutoHide}, Editor, EditorEvent, EditorSettings, ShowScrollbar, @@ -2428,7 +2428,6 @@ impl ProjectPanel { active_selection: selection, marked_selections: selections, }; - div() .id(entry_id.to_proto() as usize) .on_drag_move::(cx.listener( @@ -2520,7 +2519,7 @@ impl ProjectPanel { .child(if let Some(icon) = &icon { let icon = Icon::from_path(icon.to_string()); if let Some((decoration, decoration_color)) = - entry_diagnostic_aware_decoration_and_color(diagnostic_severity) + entry_diagnostic_aware_icon_decoration_and_color(diagnostic_severity) { h_flex().child( DecoratedIcon::new(icon.color(Color::Muted), decoration) diff --git a/crates/ui/src/components/icon.rs b/crates/ui/src/components/icon.rs index 82df7d1f0a7f5..3eb6bb4ca857b 100644 --- a/crates/ui/src/components/icon.rs +++ b/crates/ui/src/components/icon.rs @@ -294,7 +294,7 @@ pub enum IconName { ZedXCopilot, } -#[derive(Debug, IntoElement)] +#[derive(IntoElement)] pub struct Icon { path: SharedString, color: Color, From 009db720ab59273ea8ceeb6f123e97a7505a10f5 Mon Sep 17 00:00:00 2001 From: Thorsten Ball Date: Thu, 7 Nov 2024 18:56:30 +0100 Subject: [PATCH 22/28] project panel: Make diagnostic error status overwrite git status Co-authored by: Danilo Leal Co-authored by: Peter Tripp --- crates/project_panel/src/project_panel.rs | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/crates/project_panel/src/project_panel.rs b/crates/project_panel/src/project_panel.rs index 2c332c6c3a642..4c1346d080dca 100644 --- a/crates/project_panel/src/project_panel.rs +++ b/crates/project_panel/src/project_panel.rs @@ -34,7 +34,9 @@ use project::{ relativize_path, Entry, EntryKind, Fs, Project, ProjectEntryId, ProjectPath, Worktree, WorktreeId, }; -use project_panel_settings::{ProjectPanelDockPosition, ProjectPanelSettings, ShowIndentGuides, ShowDiagnostics}; +use project_panel_settings::{ + ProjectPanelDockPosition, ProjectPanelSettings, ShowDiagnostics, ShowIndentGuides, +}; use serde::{Deserialize, Serialize}; use smallvec::SmallVec; use std::{ @@ -48,8 +50,8 @@ use std::{ }; use theme::ThemeSettings; use ui::{ - prelude::*, v_flex, ContextMenu, Icon, IndentGuideColors, IndentGuideLayout, KeyBinding, Label, DecoratedIcon, - ListItem, Tooltip, + prelude::*, v_flex, ContextMenu, DecoratedIcon, Icon, IndentGuideColors, IndentGuideLayout, + KeyBinding, Label, ListItem, Tooltip, }; use util::{maybe, ResultExt, TryFutureExt}; use workspace::{ @@ -2416,8 +2418,14 @@ impl ProjectPanel { .get(&(*worktree_id, entry.path.to_path_buf())) .cloned(); - let filename_text_color = - entry_git_aware_label_color(status, entry.is_ignored, is_marked); + let filename_text_color = if entry.kind.is_file() + && diagnostic_severity + .map_or(false, |severity| severity == DiagnosticSeverity::ERROR) + { + Color::Error + } else { + entry_git_aware_label_color(status, entry.is_ignored, is_marked) + }; let mut details = EntryDetails { filename, From fc1582525045c8526a7e0bd96e0f92e76e524a36 Mon Sep 17 00:00:00 2001 From: Danilo Leal <67129314+danilo-leal@users.noreply.github.com> Date: Sun, 10 Nov 2024 13:12:04 -0300 Subject: [PATCH 23/28] Checkpoint: Create a dedicated icon for panel diagnostic display --- assets/icons/indicator_warning.svg | 2 +- assets/icons/indicator_x.svg | 2 +- assets/icons/warning_knockout.svg | 3 + assets/icons/x_knockout.svg | 10 +++ crates/project_panel/src/project_panel.rs | 34 +++++++--- crates/ui/src/components/icon.rs | 75 +++++++++++++++++++++++ 6 files changed, 114 insertions(+), 12 deletions(-) create mode 100644 assets/icons/warning_knockout.svg create mode 100644 assets/icons/x_knockout.svg diff --git a/assets/icons/indicator_warning.svg b/assets/icons/indicator_warning.svg index 607b2a005e5ec..c4aef51f7f57a 100644 --- a/assets/icons/indicator_warning.svg +++ b/assets/icons/indicator_warning.svg @@ -1,3 +1,3 @@ - + diff --git a/assets/icons/indicator_x.svg b/assets/icons/indicator_x.svg index d812c40fd2742..7b6fcc825b021 100644 --- a/assets/icons/indicator_x.svg +++ b/assets/icons/indicator_x.svg @@ -1,3 +1,3 @@ - + diff --git a/assets/icons/warning_knockout.svg b/assets/icons/warning_knockout.svg new file mode 100644 index 0000000000000..b72cba79467d1 --- /dev/null +++ b/assets/icons/warning_knockout.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/icons/x_knockout.svg b/assets/icons/x_knockout.svg new file mode 100644 index 0000000000000..76acb7b228218 --- /dev/null +++ b/assets/icons/x_knockout.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/crates/project_panel/src/project_panel.rs b/crates/project_panel/src/project_panel.rs index afb3e41490f4a..aee01e7c52a45 100644 --- a/crates/project_panel/src/project_panel.rs +++ b/crates/project_panel/src/project_panel.rs @@ -3,7 +3,6 @@ mod project_panel_settings; use client::{ErrorCode, ErrorExt}; use language::DiagnosticSeverity; use settings::{Settings, SettingsStore}; -use ui::{Scrollbar, ScrollbarState}; use db::kvp::KEY_VALUE_STORE; use editor::{ @@ -50,8 +49,8 @@ use std::{ }; use theme::ThemeSettings; use ui::{ - prelude::*, v_flex, ContextMenu, DecoratedIcon, Icon, IndentGuideColors, IndentGuideLayout, - KeyBinding, Label, ListItem, Tooltip, + prelude::*, v_flex, ContextMenu, DiagnosticIcon, Icon, IconWithIndicator, IndentGuideColors, + IndentGuideLayout, Indicator, KeyBinding, Label, ListItem, Scrollbar, ScrollbarState, Tooltip, }; use util::{maybe, ResultExt, TryFutureExt}; use workspace::{ @@ -2791,16 +2790,31 @@ impl ProjectPanel { ) }) .child(if let Some(icon) = &icon { - let icon = Icon::from_path(icon.to_string()); - if let Some((decoration, decoration_color)) = + // Check if there's a diagnostic severity and get the decoration color + if let Some((_, decoration_color)) = entry_diagnostic_aware_icon_decoration_and_color(diagnostic_severity) { - h_flex().child( - DecoratedIcon::new(icon.color(Color::Muted), decoration) - .decoration_color(decoration_color), - ) + // Determine if the diagnostic is a warning + let is_warning = diagnostic_severity + .map(|severity| matches!(severity, DiagnosticSeverity::WARNING)) + .unwrap_or(false); + div().child(if kind.is_file() { + DiagnosticIcon::new( + Icon::from_path(icon.clone()).color(Color::Muted), + is_warning, + ) + .decoration_color(decoration_color) + .into_any_element() + } else { + IconWithIndicator::new( + Icon::from_path(icon.clone()).color(Color::Muted), + Some(Indicator::dot().color(decoration_color)), + ) + .into_any_element() + }) } else { - h_flex().child(icon.color(filename_text_color)) + h_flex() + .child(Icon::from_path(icon.to_string()).color(filename_text_color)) } } else { if let Some((icon_name, color)) = diff --git a/crates/ui/src/components/icon.rs b/crates/ui/src/components/icon.rs index 4369a6ab0318a..2cb6efcad5c42 100644 --- a/crates/ui/src/components/icon.rs +++ b/crates/ui/src/components/icon.rs @@ -295,9 +295,11 @@ pub enum IconName { Visible, Wand, Warning, + WarningKnockout, WholeWord, X, XCircle, + XKnockout, ZedAssistant, ZedAssistantFilled, ZedXCopilot, @@ -446,6 +448,79 @@ impl RenderOnce for DecoratedIcon { } } +#[derive(IntoElement)] +pub struct DiagnosticIcon { + icon: Icon, + is_warning: bool, + decoration_color: Color, + parent_background: Option, +} + +impl DiagnosticIcon { + pub fn new(icon: Icon, is_warning: bool) -> Self { + Self { + icon, + is_warning, + decoration_color: Color::Default, + parent_background: None, + } + } + + pub fn decoration_color(mut self, color: Color) -> Self { + self.decoration_color = color; + self + } + + pub fn parent_background(mut self, background: Option) -> Self { + self.parent_background = background; + self + } +} + +impl RenderOnce for DiagnosticIcon { + fn render(self, cx: &mut WindowContext) -> impl IntoElement { + let background = self + .parent_background + .unwrap_or_else(|| cx.theme().colors().panel_background); + + let diagnostic_icon_size = IconSize::Small.rems(); + + // Use a different icon depending on whether the diagnostic is an error or warning + let (diagnostic_icon, knockout_icon) = if self.is_warning { + (IconName::IndicatorWarning, IconName::WarningKnockout) + } else { + (IconName::IndicatorX, IconName::XKnockout) + }; + + let decoration_svg = |icon: IconName| { + svg() + .absolute() + .bottom(-rems_from_px(1.5)) + .right(-rems_from_px(1.5)) + .path(icon.path()) + .size(diagnostic_icon_size) + .text_color(self.decoration_color.color(cx)) + }; + + let decoration_knockout = |icon: IconName| { + svg() + .absolute() + .bottom(-rems_from_px(3.)) + .right(-rems_from_px(3.)) + .path(icon.path()) + .size(diagnostic_icon_size + rems_from_px(1.)) + .text_color(background) + }; + + div() + .relative() + .size(self.icon.size) + .child(self.icon) + .child(decoration_knockout(knockout_icon)) + .child(decoration_svg(diagnostic_icon)) + } +} + #[derive(IntoElement)] pub struct IconWithIndicator { icon: Icon, From a2b51d36e8610860cb23125659ece7cabb4f0548 Mon Sep 17 00:00:00 2001 From: Danilo Leal <67129314+danilo-leal@users.noreply.github.com> Date: Mon, 11 Nov 2024 19:37:06 -0300 Subject: [PATCH 24/28] Use the new `DecoratedIcon` component --- crates/editor/src/items.rs | 8 ++--- crates/project_panel/src/project_panel.rs | 41 +++++++++++++++-------- crates/ui/src/components/icon.rs | 2 ++ 3 files changed, 33 insertions(+), 18 deletions(-) diff --git a/crates/editor/src/items.rs b/crates/editor/src/items.rs index d00c72693945d..1f027ba29e4c2 100644 --- a/crates/editor/src/items.rs +++ b/crates/editor/src/items.rs @@ -40,7 +40,7 @@ use std::{ }; use text::{BufferId, Selection}; use theme::{Theme, ThemeSettings}; -use ui::{h_flex, prelude::*, IconDecoration, Label}; +use ui::{h_flex, prelude::*, IconDecorationKind, Label}; use util::{paths::PathExt, ResultExt, TryFutureExt}; use workspace::item::{BreadcrumbText, FollowEvent}; use workspace::{ @@ -1528,10 +1528,10 @@ pub fn entry_diagnostic_aware_icon_name_and_color( pub fn entry_diagnostic_aware_icon_decoration_and_color( diagnostic_severity: Option, -) -> Option<(IconDecoration, Color)> { +) -> Option<(IconDecorationKind, Color)> { match diagnostic_severity { - Some(DiagnosticSeverity::ERROR) => Some((IconDecoration::X, Color::Error)), - Some(DiagnosticSeverity::WARNING) => Some((IconDecoration::Warning, Color::Warning)), + Some(DiagnosticSeverity::ERROR) => Some((IconDecorationKind::X, Color::Error)), + Some(DiagnosticSeverity::WARNING) => Some((IconDecorationKind::Triangle, Color::Warning)), _ => None, } } diff --git a/crates/project_panel/src/project_panel.rs b/crates/project_panel/src/project_panel.rs index 7f5d18cc65b9c..e2f42b4e2232a 100644 --- a/crates/project_panel/src/project_panel.rs +++ b/crates/project_panel/src/project_panel.rs @@ -49,8 +49,9 @@ use std::{ }; use theme::ThemeSettings; use ui::{ - prelude::*, v_flex, ContextMenu, DiagnosticIcon, Icon, IconWithIndicator, IndentGuideColors, - IndentGuideLayout, Indicator, KeyBinding, Label, ListItem, Scrollbar, ScrollbarState, Tooltip, + prelude::*, v_flex, ContextMenu, DecoratedIcon, Icon, IconDecoration, IconDecorationKind, + IconWithIndicator, IndentGuideColors, IndentGuideLayout, Indicator, KeyBinding, Label, + ListItem, Scrollbar, ScrollbarState, Tooltip, }; use util::{maybe, ResultExt, TryFutureExt}; use workspace::{ @@ -2779,20 +2780,32 @@ impl ProjectPanel { let is_warning = diagnostic_severity .map(|severity| matches!(severity, DiagnosticSeverity::WARNING)) .unwrap_or(false); - div().child(if kind.is_file() { - DiagnosticIcon::new( + div().child( + DecoratedIcon::new( Icon::from_path(icon.clone()).color(Color::Muted), - is_warning, - ) - .decoration_color(decoration_color) - .into_any_element() - } else { - IconWithIndicator::new( - Icon::from_path(icon.clone()).color(Color::Muted), - Some(Indicator::dot().color(decoration_color)), + Some( + IconDecoration::new( + if kind.is_file() { + if is_warning { + IconDecorationKind::Triangle + } else { + IconDecorationKind::X + } + } else { + IconDecorationKind::Dot + }, + cx.theme().colors().surface_background, + cx, + ) + .color(decoration_color.color(cx)) + .position(Point { + x: px(-2.), + y: px(-2.), + }), + ), ) - .into_any_element() - }) + .into_any_element(), + ) } else { h_flex() .child(Icon::from_path(icon.to_string()).color(filename_text_color)) diff --git a/crates/ui/src/components/icon.rs b/crates/ui/src/components/icon.rs index 89763c3a421ec..a594784b0c032 100644 --- a/crates/ui/src/components/icon.rs +++ b/crates/ui/src/components/icon.rs @@ -273,6 +273,7 @@ pub enum IconName { Terminal, Trash, TrashAlt, + Triangle, TriangleRight, Undo, Unpin, @@ -286,6 +287,7 @@ pub enum IconName { ZedAssistant, ZedAssistantFilled, ZedXCopilot, + X, } impl From for Icon { From 73d1334efcd780de3f23cc309306aaec66f85687 Mon Sep 17 00:00:00 2001 From: Danilo Leal <67129314+danilo-leal@users.noreply.github.com> Date: Mon, 11 Nov 2024 20:39:23 -0300 Subject: [PATCH 25/28] Organize colors used for each state and scenario --- crates/project_panel/src/project_panel.rs | 54 +++++++++++++++++------ 1 file changed, 40 insertions(+), 14 deletions(-) diff --git a/crates/project_panel/src/project_panel.rs b/crates/project_panel/src/project_panel.rs index e2f42b4e2232a..cfced9921d8a7 100644 --- a/crates/project_panel/src/project_panel.rs +++ b/crates/project_panel/src/project_panel.rs @@ -21,7 +21,7 @@ use git::repository::GitFileStatus; use gpui::{ actions, anchored, deferred, div, impl_actions, point, px, size, uniform_list, Action, AnyElement, AppContext, AssetSource, AsyncWindowContext, Bounds, ClipboardItem, DismissEvent, - Div, DragMoveEvent, EventEmitter, ExternalPaths, FocusHandle, FocusableView, + Div, DragMoveEvent, EventEmitter, ExternalPaths, FocusHandle, FocusableView, Hsla, InteractiveElement, KeyContext, ListHorizontalSizingBehavior, ListSizingBehavior, Model, MouseButton, MouseDownEvent, ParentElement, Pixels, Point, PromptLevel, Render, ScrollStrategy, Stateful, Styled, Subscription, Task, UniformListScrollHandle, View, ViewContext, @@ -50,8 +50,8 @@ use std::{ use theme::ThemeSettings; use ui::{ prelude::*, v_flex, ContextMenu, DecoratedIcon, Icon, IconDecoration, IconDecorationKind, - IconWithIndicator, IndentGuideColors, IndentGuideLayout, Indicator, KeyBinding, Label, - ListItem, Scrollbar, ScrollbarState, Tooltip, + IndentGuideColors, IndentGuideLayout, KeyBinding, Label, ListItem, Scrollbar, ScrollbarState, + Tooltip, }; use util::{maybe, ResultExt, TryFutureExt}; use workspace::{ @@ -243,6 +243,26 @@ struct DraggedProjectEntryView { selections: Arc>, } +struct ItemColors { + default: Hsla, + hover: Hsla, + drag_over: Hsla, + selected: Hsla, + marked_active: Hsla, +} + +fn get_item_color(cx: &ViewContext) -> ItemColors { + let colors = cx.theme().colors(); + + ItemColors { + default: colors.surface_background, + hover: colors.ghost_element_hover, + drag_over: colors.drop_target_background, + selected: colors.surface_background, + marked_active: colors.ghost_element_selected, + } +} + impl ProjectPanel { fn new(workspace: &mut Workspace, cx: &mut ViewContext) -> View { let project = workspace.project().clone(); @@ -2576,16 +2596,20 @@ impl ProjectPanel { let kind = details.kind; let settings = ProjectPanelSettings::get_global(cx); let show_editor = details.is_editing && !details.is_processing; + let selection = SelectedEntry { worktree_id: details.worktree_id, entry_id, }; + let is_marked = self.marked_entries.contains(&selection); let is_active = self .selection .map_or(false, |selection| selection.entry_id == entry_id); + let width = self.size(cx); let file_name = details.filename.clone(); + let mut icon = details.icon.clone(); if settings.file_icons && show_editor && details.kind.is_file() { let filename = self.filename_editor.read(cx).text(cx); @@ -2596,6 +2620,7 @@ impl ProjectPanel { let filename_text_color = details.filename_text_color; let diagnostic_severity = details.diagnostic_severity; + let item_colors = get_item_color(cx); let canonical_path = details .canonical_path @@ -2676,9 +2701,7 @@ impl ProjectPanel { selections: selection.marked_selections.clone(), }) }) - .drag_over::(|style, _, cx| { - style.bg(cx.theme().colors().drop_target_background) - }) + .drag_over::(move |style, _, _| style.bg(item_colors.drag_over)) .on_drop(cx.listener(move |this, selections: &DraggedSelection, cx| { this.hover_scroll_task.take(); this.drag_onto(selections, entry_id, kind.is_file(), cx); @@ -2794,7 +2817,11 @@ impl ProjectPanel { } else { IconDecorationKind::Dot }, - cx.theme().colors().surface_background, + if is_marked || is_active { + item_colors.selected + } else { + item_colors.default + }, cx, ) .color(decoration_color.color(cx)) @@ -2807,8 +2834,7 @@ impl ProjectPanel { .into_any_element(), ) } else { - h_flex() - .child(Icon::from_path(icon.to_string()).color(filename_text_color)) + h_flex().child(Icon::from_path(icon.to_string()).color(Color::Muted)) } } else { if let Some((icon_name, color)) = @@ -2912,14 +2938,14 @@ impl ProjectPanel { if is_active { style } else { - let hover_color = cx.theme().colors().ghost_element_hover; - style.bg(hover_color).border_color(hover_color) + style.bg(item_colors.hover).border_color(item_colors.hover) } }) .when(is_marked || is_active, |this| { - let colors = cx.theme().colors(); - this.when(is_marked, |this| this.bg(colors.ghost_element_selected)) - .border_color(colors.ghost_element_selected) + this.when(is_marked, |this| { + this.bg(item_colors.marked_active) + .border_color(item_colors.marked_active) + }) }) .when( !self.mouse_down && is_active && self.focus_handle.contains_focused(cx), From 88573c5ef02634d847461639170e4e668d4d525f Mon Sep 17 00:00:00 2001 From: Danilo Leal <67129314+danilo-leal@users.noreply.github.com> Date: Tue, 12 Nov 2024 10:22:49 -0300 Subject: [PATCH 26/28] Remove unused SVGs --- assets/icons/indicator_warning.svg | 3 --- assets/icons/indicator_x.svg | 3 --- assets/icons/warning_knockout.svg | 3 --- assets/icons/x_knockout.svg | 10 ---------- 4 files changed, 19 deletions(-) delete mode 100644 assets/icons/indicator_warning.svg delete mode 100644 assets/icons/indicator_x.svg delete mode 100644 assets/icons/warning_knockout.svg delete mode 100644 assets/icons/x_knockout.svg diff --git a/assets/icons/indicator_warning.svg b/assets/icons/indicator_warning.svg deleted file mode 100644 index c4aef51f7f57a..0000000000000 --- a/assets/icons/indicator_warning.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/icons/indicator_x.svg b/assets/icons/indicator_x.svg deleted file mode 100644 index 7b6fcc825b021..0000000000000 --- a/assets/icons/indicator_x.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/icons/warning_knockout.svg b/assets/icons/warning_knockout.svg deleted file mode 100644 index b72cba79467d1..0000000000000 --- a/assets/icons/warning_knockout.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/icons/x_knockout.svg b/assets/icons/x_knockout.svg deleted file mode 100644 index 76acb7b228218..0000000000000 --- a/assets/icons/x_knockout.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - From 06cb366a61ea8938818c4c138f101430561731f6 Mon Sep 17 00:00:00 2001 From: Danilo Leal <67129314+danilo-leal@users.noreply.github.com> Date: Tue, 12 Nov 2024 11:22:39 -0300 Subject: [PATCH 27/28] Iterate on the setting's writing --- crates/project_panel/src/project_panel_settings.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/project_panel/src/project_panel_settings.rs b/crates/project_panel/src/project_panel_settings.rs index 00e8c967618d0..b9e6ac325d592 100644 --- a/crates/project_panel/src/project_panel_settings.rs +++ b/crates/project_panel/src/project_panel_settings.rs @@ -61,7 +61,7 @@ pub struct ScrollbarSettingsContent { pub show: Option>, } -/// Which files containing diagnostic errors/warnings to mark in the project panel. +/// Whether to indicate diagnostic errors and/or warnings in project panel items. /// /// Default: all #[derive(Copy, Clone, Debug, Default, Serialize, Deserialize, JsonSchema, PartialEq, Eq)] @@ -69,7 +69,7 @@ pub struct ScrollbarSettingsContent { pub enum ShowDiagnostics { /// Never mark the diagnostic errors/warnings in the project panel. Off, - /// Mark files containing diagnostic errors in the project panel. + /// Mark files containing only diagnostic errors in the project panel. Errors, #[default] /// Mark files containing diagnostic errors or warnings in the project panel. From 2f3b8f31170373f775c6d410f959d9003d87aab7 Mon Sep 17 00:00:00 2001 From: Danilo Leal <67129314+danilo-leal@users.noreply.github.com> Date: Tue, 12 Nov 2024 11:41:56 -0300 Subject: [PATCH 28/28] Iterate on the triangle knockout icon --- assets/icons/knockouts/triangle_bg.svg | 9 ++++++++- assets/icons/knockouts/triangle_fg.svg | 2 +- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/assets/icons/knockouts/triangle_bg.svg b/assets/icons/knockouts/triangle_bg.svg index b0c5ae6e77931..990b439952149 100644 --- a/assets/icons/knockouts/triangle_bg.svg +++ b/assets/icons/knockouts/triangle_bg.svg @@ -1,3 +1,10 @@ - + + + + + + + + diff --git a/assets/icons/knockouts/triangle_fg.svg b/assets/icons/knockouts/triangle_fg.svg index f8f8b8c2bcddf..e3b31446b3508 100644 --- a/assets/icons/knockouts/triangle_fg.svg +++ b/assets/icons/knockouts/triangle_fg.svg @@ -1,3 +1,3 @@ - +