Adjust scrollbar settings to be expandable (#2507)

Mikayla Maki created

Note that this PR cannot be cherrypicked into preview, as it relies on
the new settings infrastructure.

Switches settings from `show_scrollbars: "auto"` to `scrollbar: {show:
"auto", git_diffs: true}`.

fixes
https://linear.app/zed-industries/issue/Z-1650/scroll-bar-feature-settings

Release Notes:

- Changed scrollbar settings from `show_scrollbars: "auto"` to
`scrollbar: {show: "auto", git_diffs: true}`. (preview only)

Change summary

assets/settings/default.json         | 31 +++++++++++++++++------------
crates/editor/src/editor.rs          |  6 -----
crates/editor/src/editor_settings.rs | 18 ++++++++++++++--
crates/editor/src/element.rs         | 21 +++++++++++--------
4 files changed, 45 insertions(+), 31 deletions(-)

Detailed changes

assets/settings/default.json 🔗

@@ -52,19 +52,24 @@
   // 3. Draw all invisible symbols:
   //   "all"
   "show_whitespaces": "selection",
-  // Whether to show the scrollbar in the editor.
-  // This setting can take four values:
-  //
-  // 1. Show the scrollbar if there's important information or
-  //    follow the system's configured behavior (default):
-  //   "auto"
-  // 2. Match the system's configured behavior:
-  //    "system"
-  // 3. Always show the scrollbar:
-  //    "always"
-  // 4. Never show the scrollbar:
-  //    "never"
-  "show_scrollbars": "auto",
+  // Scrollbar related settings
+  "scrollbar": {
+      // When to show the scrollbar in the editor.
+      // This setting can take four values:
+      //
+      // 1. Show the scrollbar if there's important information or
+      //    follow the system's configured behavior (default):
+      //   "auto"
+      // 2. Match the system's configured behavior:
+      //    "system"
+      // 3. Always show the scrollbar:
+      //    "always"
+      // 4. Never show the scrollbar:
+      //    "never"
+      "show": "auto",
+      // Whether to show git diff indicators in the scrollbar.
+      "git_diff": true
+  },
   // Whether the screen sharing icon is shown in the os status bar.
   "show_call_status_icon": true,
   // Whether to use language servers to provide code intelligence.

crates/editor/src/editor.rs 🔗

@@ -533,12 +533,6 @@ pub struct EditorSnapshot {
     ongoing_scroll: OngoingScroll,
 }
 
-impl EditorSnapshot {
-    fn has_scrollbar_info(&self, is_singleton: bool) -> bool {
-        is_singleton && self.buffer_snapshot.has_git_diffs()
-    }
-}
-
 #[derive(Clone, Debug)]
 struct SelectionHistoryEntry {
     selections: Arc<[Selection<Anchor>]>,

crates/editor/src/editor_settings.rs 🔗

@@ -7,12 +7,18 @@ pub struct EditorSettings {
     pub cursor_blink: bool,
     pub hover_popover_enabled: bool,
     pub show_completions_on_input: bool,
-    pub show_scrollbars: ShowScrollbars,
+    pub scrollbar: Scrollbar,
+}
+
+#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
+pub struct Scrollbar {
+    pub show: ShowScrollbar,
+    pub git_diff: bool,
 }
 
 #[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
 #[serde(rename_all = "snake_case")]
-pub enum ShowScrollbars {
+pub enum ShowScrollbar {
     Auto,
     System,
     Always,
@@ -24,7 +30,13 @@ pub struct EditorSettingsContent {
     pub cursor_blink: Option<bool>,
     pub hover_popover_enabled: Option<bool>,
     pub show_completions_on_input: Option<bool>,
-    pub show_scrollbars: Option<ShowScrollbars>,
+    pub scrollbar: Option<ScrollbarContent>,
+}
+
+#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
+pub struct ScrollbarContent {
+    pub show: Option<ShowScrollbar>,
+    pub git_diff: Option<bool>,
 }
 
 impl Setting for EditorSettings {

crates/editor/src/element.rs 🔗

@@ -5,7 +5,7 @@ use super::{
 };
 use crate::{
     display_map::{BlockStyle, DisplaySnapshot, FoldStatus, TransformBlock},
-    editor_settings::ShowScrollbars,
+    editor_settings::ShowScrollbar,
     git::{diff_hunk_to_display, DisplayDiffHunk},
     hover_popover::{
         hide_hover, hover_at, HOVER_POPOVER_GAP, MIN_POPOVER_CHARACTER_WIDTH,
@@ -1052,7 +1052,7 @@ impl EditorElement {
                 ..Default::default()
             });
 
-            if layout.is_singleton {
+            if layout.is_singleton && settings::get::<EditorSettings>(cx).scrollbar.git_diff {
                 let diff_style = theme::current(cx).editor.diff.clone();
                 for hunk in layout
                     .position_map
@@ -2067,14 +2067,17 @@ impl Element<Editor> for EditorElement {
             ));
         }
 
-        let show_scrollbars = match settings::get::<EditorSettings>(cx).show_scrollbars {
-            ShowScrollbars::Auto => {
-                snapshot.has_scrollbar_info(is_singleton)
-                    || editor.scroll_manager.scrollbars_visible()
+        let scrollbar_settings = &settings::get::<EditorSettings>(cx).scrollbar;
+        let show_scrollbars = match scrollbar_settings.show {
+            ShowScrollbar::Auto => {
+                // Git
+                (is_singleton && scrollbar_settings.git_diff && snapshot.buffer_snapshot.has_git_diffs())
+                // Scrollmanager
+                || editor.scroll_manager.scrollbars_visible()
             }
-            ShowScrollbars::System => editor.scroll_manager.scrollbars_visible(),
-            ShowScrollbars::Always => true,
-            ShowScrollbars::Never => false,
+            ShowScrollbar::System => editor.scroll_manager.scrollbars_visible(),
+            ShowScrollbar::Always => true,
+            ShowScrollbar::Never => false,
         };
 
         let include_root = editor