diff --git a/crates/editor/src/editor_settings.rs b/crates/editor/src/editor_settings.rs index 0b570e6466c69d66744179e9f7ceb2a99f35d203..37f7e80e65ab4210ab4d8a127dba3a35cf7cbac2 100644 --- a/crates/editor/src/editor_settings.rs +++ b/crates/editor/src/editor_settings.rs @@ -305,7 +305,7 @@ pub struct ScrollbarContent { } /// Gutter related settings -#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)] +#[derive(Copy, Clone, Debug, Default, Serialize, Deserialize, JsonSchema, PartialEq, Eq)] pub struct GutterContent { /// Whether to show line numbers in the gutter. /// diff --git a/crates/editor/src/editor_settings_controls.rs b/crates/editor/src/editor_settings_controls.rs index 7deb85413bb30c4a4ffce9dc6e4d4894bd7e9f30..09f01837eecab58474a9a86f1fc8a8cc8d9449c2 100644 --- a/crates/editor/src/editor_settings_controls.rs +++ b/crates/editor/src/editor_settings_controls.rs @@ -9,6 +9,8 @@ use ui::{ SettingsGroup, }; +use crate::EditorSettings; + #[derive(IntoElement)] pub struct EditorSettingsControls {} @@ -34,6 +36,15 @@ impl RenderOnce for EditorSettingsControls { .child(BufferFontLigaturesControl), ) .child(SettingsGroup::new("Editor").child(InlineGitBlameControl)) + .child( + SettingsGroup::new("Gutter").child( + h_flex() + .gap_2() + .justify_between() + .child(LineNumbersControl) + .child(RelativeLineNumbersControl), + ), + ) } } @@ -315,3 +326,102 @@ impl RenderOnce for InlineGitBlameControl { ) } } + +#[derive(IntoElement)] +struct LineNumbersControl; + +impl EditableSettingControl for LineNumbersControl { + type Value = bool; + type Settings = EditorSettings; + + fn name(&self) -> SharedString { + "Line Numbers".into() + } + + fn read(cx: &AppContext) -> Self::Value { + let settings = EditorSettings::get_global(cx); + settings.gutter.line_numbers + } + + fn apply( + settings: &mut ::FileContent, + value: Self::Value, + _cx: &AppContext, + ) { + if let Some(gutter) = settings.gutter.as_mut() { + gutter.line_numbers = Some(value); + } else { + settings.gutter = Some(crate::editor_settings::GutterContent { + line_numbers: Some(value), + ..Default::default() + }); + } + } +} + +impl RenderOnce for LineNumbersControl { + fn render(self, cx: &mut WindowContext) -> impl IntoElement { + let value = Self::read(cx); + + CheckboxWithLabel::new( + "line-numbers", + Label::new(self.name()), + value.into(), + |selection, cx| { + Self::write( + match selection { + Selection::Selected => true, + Selection::Unselected | Selection::Indeterminate => false, + }, + cx, + ); + }, + ) + } +} + +#[derive(IntoElement)] +struct RelativeLineNumbersControl; + +impl EditableSettingControl for RelativeLineNumbersControl { + type Value = bool; + type Settings = EditorSettings; + + fn name(&self) -> SharedString { + "Relative Line Numbers".into() + } + + fn read(cx: &AppContext) -> Self::Value { + let settings = EditorSettings::get_global(cx); + settings.relative_line_numbers + } + + fn apply( + settings: &mut ::FileContent, + value: Self::Value, + _cx: &AppContext, + ) { + settings.relative_line_numbers = Some(value); + } +} + +impl RenderOnce for RelativeLineNumbersControl { + fn render(self, cx: &mut WindowContext) -> impl IntoElement { + let value = Self::read(cx); + + DropdownMenu::new( + "relative-line-numbers", + if value { "Relative" } else { "Ascending" }, + ContextMenu::build(cx, |menu, _cx| { + menu.custom_entry( + |_cx| Label::new("Ascending").into_any_element(), + move |cx| Self::write(false, cx), + ) + .custom_entry( + |_cx| Label::new("Relative").into_any_element(), + move |cx| Self::write(true, cx), + ) + }), + ) + } +}