diff --git a/assets/settings/default.json b/assets/settings/default.json index c413db5788a0f15e417a4c299f3be123a24dfa5c..9ae5c916b5cfb419e2a4e78d6641737fa55f0c75 100644 --- a/assets/settings/default.json +++ b/assets/settings/default.json @@ -71,15 +71,17 @@ // "never" "show": "auto", // Whether to show git diff indicators in the scrollbar. - "git_diff": true + "git_diff": true, + // Whether to show selections in the scrollbar. + "selections": true }, // Inlay hint related settings "inlay_hints": { // Global switch to toggle hints on and off, switched off by default. - "enabled": false, + "enabled": false, // Toggle certain types of hints on and off, all switched on by default. "show_type_hints": true, - "show_parameter_hints": true, + "show_parameter_hints": true, // Corresponds to null/None LSP hint type value. "show_other_hints": true }, diff --git a/crates/editor/src/editor_settings.rs b/crates/editor/src/editor_settings.rs index 387d4d2c340d2a3bb5b648d8232880de2d8f7fe1..f4499b5651cc158c66df3faad7f0ecf707e01bb6 100644 --- a/crates/editor/src/editor_settings.rs +++ b/crates/editor/src/editor_settings.rs @@ -15,6 +15,7 @@ pub struct EditorSettings { pub struct Scrollbar { pub show: ShowScrollbar, pub git_diff: bool, + pub selections: bool, } #[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)] @@ -39,6 +40,7 @@ pub struct EditorSettingsContent { pub struct ScrollbarContent { pub show: Option, pub git_diff: Option, + pub selections: Option, } impl Setting for EditorSettings { diff --git a/crates/editor/src/element.rs b/crates/editor/src/element.rs index d1e6f29bbebabf22e0f657a85a16dc6ee8fcc8be..e96f1efe9263f274d66355297e01441ce7474f03 100644 --- a/crates/editor/src/element.rs +++ b/crates/editor/src/element.rs @@ -1008,6 +1008,7 @@ impl EditorElement { bounds: RectF, layout: &mut LayoutState, cx: &mut ViewContext, + editor: &Editor, ) { enum ScrollbarMouseHandlers {} if layout.mode != EditorMode::Full { @@ -1050,9 +1051,74 @@ impl EditorElement { background: style.track.background_color, ..Default::default() }); + let scrollbar_settings = settings::get::(cx).scrollbar; + let theme = theme::current(cx); + let scrollbar_theme = &theme.editor.scrollbar; + if layout.is_singleton && scrollbar_settings.selections { + let start_anchor = Anchor::min(); + let end_anchor = Anchor::max(); + let mut start_row = None; + let mut end_row = None; + let color = scrollbar_theme.selections; + let border = Border { + width: 1., + color: style.thumb.border.color, + overlay: false, + top: false, + right: true, + bottom: false, + left: true, + }; + let mut push_region = |start, end| { + if let (Some(start_display), Some(end_display)) = (start, end) { + let start_y = y_for_row(start_display as f32); + let mut end_y = y_for_row(end_display as f32); + if end_y - start_y < 1. { + end_y = start_y + 1.; + } + let bounds = RectF::from_points(vec2f(left, start_y), vec2f(right, end_y)); + + scene.push_quad(Quad { + bounds, + background: Some(color), + border, + corner_radius: style.thumb.corner_radius, + }) + } + }; + for (row, _) in &editor.background_highlights_in_range( + start_anchor..end_anchor, + &layout.position_map.snapshot, + &theme, + ) { + let start_display = row.start; + let end_display = row.end; + + if start_row.is_none() { + assert_eq!(end_row, None); + start_row = Some(start_display.row()); + end_row = Some(end_display.row()); + continue; + } + if let Some(current_end) = end_row.as_mut() { + if start_display.row() > *current_end + 1 { + push_region(start_row, end_row); + start_row = Some(start_display.row()); + end_row = Some(end_display.row()); + } else { + // Merge two hunks. + *current_end = end_display.row(); + } + } else { + unreachable!(); + } + } + // We might still have a hunk that was not rendered (if there was a search hit on the last line) + push_region(start_row, end_row); + } - if layout.is_singleton && settings::get::(cx).scrollbar.git_diff { - let diff_style = theme::current(cx).editor.scrollbar.git.clone(); + if layout.is_singleton && scrollbar_settings.git_diff { + let diff_style = scrollbar_theme.git.clone(); for hunk in layout .position_map .snapshot @@ -2368,7 +2434,7 @@ impl Element for EditorElement { if !layout.blocks.is_empty() { self.paint_blocks(scene, bounds, visible_bounds, layout, editor, cx); } - self.paint_scrollbar(scene, bounds, layout, cx); + self.paint_scrollbar(scene, bounds, layout, cx, &editor); scene.pop_layer(); scene.pop_layer(); diff --git a/crates/theme/src/theme.rs b/crates/theme/src/theme.rs index 55884b80447968db22d0877bb91cffc47533e3f2..1949a5d9bb309767a52286aacf28cba03840556d 100644 --- a/crates/theme/src/theme.rs +++ b/crates/theme/src/theme.rs @@ -722,6 +722,7 @@ pub struct Scrollbar { pub width: f32, pub min_height_factor: f32, pub git: GitDiffColors, + pub selections: Color, } #[derive(Clone, Deserialize, Default, JsonSchema)] diff --git a/styles/src/style_tree/editor.ts b/styles/src/style_tree/editor.ts index a2fec116420a44443cc3984d8bd55851e0cef68d..48a2fd33e2e5fbd2380dea6f71fe1abac00c4a63 100644 --- a/styles/src/style_tree/editor.ts +++ b/styles/src/style_tree/editor.ts @@ -304,6 +304,7 @@ export default function editor(): any { ? with_opacity(theme.ramps.green(0.5).hex(), 0.8) : with_opacity(theme.ramps.green(0.4).hex(), 0.8), }, + selections: foreground(layer, "accent") }, composition_mark: { underline: {