diff --git a/crates/editor/src/actions.rs b/crates/editor/src/actions.rs index 827c9067e3..2ed935eb34 100644 --- a/crates/editor/src/actions.rs +++ b/crates/editor/src/actions.rs @@ -918,6 +918,8 @@ actions!( AlignSelections, /// Saves the current location to navigation history. SaveLocation, + /// Toggles breadcrumbs display. + ToggleBreadcrumb, ] ); diff --git a/crates/editor/src/config.rs b/crates/editor/src/config.rs index 02256fe87d..9b5df0b867 100644 --- a/crates/editor/src/config.rs +++ b/crates/editor/src/config.rs @@ -138,6 +138,31 @@ impl Editor { } } + pub fn breadcrumbs_visible(&self) -> bool { + self.breadcrumbs_visibility.visible() + } + + fn set_breadcrumbs_visibility( + &mut self, + breadcrumbs_visibility: BreadcrumbsVisibility, + cx: &mut Context, + ) { + if self.breadcrumbs_visibility != breadcrumbs_visibility { + self.breadcrumbs_visibility = breadcrumbs_visibility; + cx.emit(EditorEvent::BreadcrumbsChanged); + cx.notify(); + } + } + + pub fn toggle_breadcrumb( + &mut self, + _: &ToggleBreadcrumb, + _: &mut Window, + cx: &mut Context, + ) { + self.set_breadcrumbs_visibility(self.breadcrumbs_visibility.toggle_visibility(), cx); + } + pub fn disable_scrollbars_and_minimap(&mut self, window: &mut Window, cx: &mut Context) { self.set_show_scrollbars(false, cx); self.set_minimap_visibility(MinimapVisibility::Disabled, window, cx); diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 0ced11ed2e..c4cab9a8eb 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -705,6 +705,40 @@ impl MinimapVisibility { } } +#[derive(Clone, Copy, PartialEq, Eq)] +struct BreadcrumbsVisibility { + setting_configuration: bool, + toggle_override: bool, +} + +impl BreadcrumbsVisibility { + fn from_settings(cx: &App) -> Self { + Self::new(EditorSettings::get_global(cx).toolbar.breadcrumbs) + } + + fn new(setting_configuration: bool) -> Self { + Self { + setting_configuration, + toggle_override: false, + } + } + + fn settings_visibility(&self) -> bool { + self.setting_configuration + } + + fn visible(&self) -> bool { + self.setting_configuration ^ self.toggle_override + } + + fn toggle_visibility(&self) -> Self { + Self { + setting_configuration: self.setting_configuration, + toggle_override: !self.toggle_override, + } + } +} + #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum BufferSerialization { All, @@ -931,7 +965,7 @@ pub struct Editor { hovered_cursors: HashMap>, pub show_local_selections: bool, mode: EditorMode, - show_breadcrumbs: bool, + breadcrumbs_visibility: BreadcrumbsVisibility, show_gutter: bool, show_scrollbars: ScrollbarAxes, minimap_visibility: MinimapVisibility, @@ -2130,7 +2164,7 @@ impl Editor { }, minimap_visibility: MinimapVisibility::for_mode(&mode, cx), offset_content: !matches!(mode, EditorMode::SingleLine), - show_breadcrumbs: EditorSettings::get_global(cx).toolbar.breadcrumbs, + breadcrumbs_visibility: BreadcrumbsVisibility::from_settings(cx), show_gutter: full_mode, show_line_numbers: (!full_mode).then_some(false), use_relative_line_numbers: None, @@ -9467,12 +9501,17 @@ impl Editor { self.refresh_inline_values(cx); let old_cursor_shape = self.cursor_shape; - let old_show_breadcrumbs = self.show_breadcrumbs; + let old_breadcrumbs_visible = self.breadcrumbs_visible(); { let editor_settings = EditorSettings::get_global(cx); self.scroll_manager.vertical_scroll_margin = editor_settings.vertical_scroll_margin; - self.show_breadcrumbs = editor_settings.toolbar.breadcrumbs; + if self.breadcrumbs_visibility.settings_visibility() + != editor_settings.toolbar.breadcrumbs + { + self.breadcrumbs_visibility = + BreadcrumbsVisibility::new(editor_settings.toolbar.breadcrumbs); + } self.cursor_shape = editor_settings.cursor_shape.unwrap_or_default(); } @@ -9480,7 +9519,7 @@ impl Editor { cx.emit(EditorEvent::CursorShapeChanged); } - if old_show_breadcrumbs != self.show_breadcrumbs { + if old_breadcrumbs_visible != self.breadcrumbs_visible() { cx.emit(EditorEvent::BreadcrumbsChanged); } diff --git a/crates/editor/src/editor_tests.rs b/crates/editor/src/editor_tests.rs index 3eca954d6d..c90e54d0c6 100644 --- a/crates/editor/src/editor_tests.rs +++ b/crates/editor/src/editor_tests.rs @@ -70,7 +70,7 @@ use util::{ }; use workspace::{ CloseActiveItem, CloseAllItems, CloseOtherItems, MultiWorkspace, NavigationEntry, OpenOptions, - ViewId, + ToolbarItemLocation, ViewId, item::{FollowEvent, FollowableItem, Item, ItemHandle, SaveOptions}, register_project_item, }; @@ -917,6 +917,49 @@ fn test_clone(cx: &mut TestAppContext) { ); } +#[gpui::test] +fn test_toggle_breadcrumb_does_not_change_settings(cx: &mut TestAppContext) { + init_test(cx, |_| {}); + update_test_editor_settings(cx, &|settings| { + settings.toolbar.get_or_insert_default().breadcrumbs = Some(true); + }); + + let editor = cx.add_window(|window, cx| { + let buffer = MultiBuffer::build_simple("hello", cx); + build_editor(buffer, window, cx) + }); + + _ = editor.update(cx, |editor, window, cx| { + assert!(EditorSettings::get_global(cx).toolbar.breadcrumbs); + assert_eq!( + editor.breadcrumb_location(cx), + ToolbarItemLocation::PrimaryLeft + ); + + editor.toggle_breadcrumb(&ToggleBreadcrumb, window, cx); + assert!(EditorSettings::get_global(cx).toolbar.breadcrumbs); + assert_eq!(editor.breadcrumb_location(cx), ToolbarItemLocation::Hidden); + }); + + // Changing unrelated settings should not affect breadcrumbs visibility. + update_test_editor_settings(cx, &|settings| { + settings.vertical_scroll_margin = Some(4.0); + }); + cx.run_until_parked(); + + _ = editor.update(cx, |editor, window, cx| { + assert!(EditorSettings::get_global(cx).toolbar.breadcrumbs); + assert_eq!(editor.breadcrumb_location(cx), ToolbarItemLocation::Hidden); + + editor.toggle_breadcrumb(&ToggleBreadcrumb, window, cx); + assert!(EditorSettings::get_global(cx).toolbar.breadcrumbs); + assert_eq!( + editor.breadcrumb_location(cx), + ToolbarItemLocation::PrimaryLeft + ); + }); +} + #[gpui::test] async fn test_navigation_history(cx: &mut TestAppContext) { init_test(cx, |_| {}); diff --git a/crates/editor/src/element.rs b/crates/editor/src/element.rs index dbba534c6f..0ac3b2691d 100644 --- a/crates/editor/src/element.rs +++ b/crates/editor/src/element.rs @@ -421,6 +421,7 @@ impl EditorElement { register_action(editor, window, Editor::open_excerpts_in_split); register_action(editor, window, Editor::toggle_soft_wrap); register_action(editor, window, Editor::toggle_tab_bar); + register_action(editor, window, Editor::toggle_breadcrumb); register_action(editor, window, Editor::toggle_line_numbers); register_action(editor, window, Editor::toggle_relative_line_numbers); register_action(editor, window, Editor::toggle_indent_guides); diff --git a/crates/editor/src/items.rs b/crates/editor/src/items.rs index 89f323ab14..9d5ad821ed 100644 --- a/crates/editor/src/items.rs +++ b/crates/editor/src/items.rs @@ -1029,7 +1029,7 @@ impl Item for Editor { } fn breadcrumb_location(&self, cx: &App) -> ToolbarItemLocation { - if self.show_breadcrumbs && self.buffer().read(cx).is_singleton() { + if self.breadcrumbs_visible() && self.buffer().read(cx).is_singleton() { ToolbarItemLocation::PrimaryLeft } else { ToolbarItemLocation::Hidden