diff --git a/crates/editor/src/element.rs b/crates/editor/src/element.rs index 0f20ac626eee94e2a3ea7022f88a7249e9e763c1..e44f3b1893c36546e5750a2f1ba39ebd5a87ef47 100644 --- a/crates/editor/src/element.rs +++ b/crates/editor/src/element.rs @@ -1461,7 +1461,7 @@ impl EditorElement { window: &mut Window, cx: &mut App, ) -> Option { - if !snapshot.mode.is_full() || !self.editor.read(cx).show_scrollbars { + if !self.editor.read(cx).show_scrollbars || self.style.scrollbar_width.is_zero() { return None; } @@ -1604,6 +1604,7 @@ impl EditorElement { minimap_line_height, scroll_position, minimap_scroll_top, + show_thumb, ); minimap_editor.update(cx, |editor, cx| { @@ -1633,7 +1634,6 @@ impl EditorElement { Some(MinimapLayout { minimap, thumb_layout: layout, - show_thumb, thumb_border_style: minimap_settings.thumb_border, minimap_line_height, minimap_scroll_top, @@ -5236,8 +5236,6 @@ impl EditorElement { for (scrollbar_layout, axis) in scrollbars_layout.iter_scrollbars() { let hitbox = &scrollbar_layout.hitbox; - let thumb_bounds = scrollbar_layout.thumb_bounds(); - if scrollbars_layout.visible { let scrollbar_edges = match axis { ScrollbarAxis::Horizontal => Edges { @@ -5279,26 +5277,31 @@ impl EditorElement { } } - let scrollbar_thumb_color = match scrollbar_layout.thumb_state { - ScrollbarThumbState::Dragging => { - cx.theme().colors().scrollbar_thumb_active_background - } - ScrollbarThumbState::Hovered => { - cx.theme().colors().scrollbar_thumb_hover_background - } - ScrollbarThumbState::Idle => cx.theme().colors().scrollbar_thumb_background, - }; - window.paint_quad(quad( - thumb_bounds, - Corners::default(), - scrollbar_thumb_color, - scrollbar_edges, - cx.theme().colors().scrollbar_thumb_border, - BorderStyle::Solid, - )); + if let Some(thumb_bounds) = scrollbar_layout.thumb_bounds { + let scrollbar_thumb_color = match scrollbar_layout.thumb_state { + ScrollbarThumbState::Dragging => { + cx.theme().colors().scrollbar_thumb_active_background + } + ScrollbarThumbState::Hovered => { + cx.theme().colors().scrollbar_thumb_hover_background + } + ScrollbarThumbState::Idle => { + cx.theme().colors().scrollbar_thumb_background + } + }; + window.paint_quad(quad( + thumb_bounds, + Corners::default(), + scrollbar_thumb_color, + scrollbar_edges, + cx.theme().colors().scrollbar_thumb_border, + BorderStyle::Solid, + )); + + window.set_cursor_style(CursorStyle::Arrow, Some(&hitbox)); + } }) } - window.set_cursor_style(CursorStyle::Arrow, Some(&hitbox)); } window.on_mouse_event({ @@ -5343,7 +5346,10 @@ impl EditorElement { cx.stop_propagation(); } else if let Some((layout, axis)) = scrollbars_layout.get_hovered_axis(window) { - if layout.thumb_bounds().contains(&event.position) { + if layout + .thumb_bounds + .is_some_and(|bounds| bounds.contains(&event.position)) + { editor .scroll_manager .set_hovered_scroll_thumb_axis(axis, cx); @@ -5398,10 +5404,13 @@ impl EditorElement { hitbox, visible_range, text_unit_size, + thumb_bounds, .. } = scrollbar_layout; - let thumb_bounds = scrollbar_layout.thumb_bounds(); + let Some(thumb_bounds) = thumb_bounds else { + return; + }; editor.update(cx, |editor, cx| { editor @@ -5731,12 +5740,11 @@ impl EditorElement { fn paint_minimap(&self, layout: &mut EditorLayout, window: &mut Window, cx: &mut App) { if let Some(mut layout) = layout.minimap.take() { let minimap_hitbox = layout.thumb_layout.hitbox.clone(); - let thumb_bounds = layout.thumb_layout.thumb_bounds(); window.paint_layer(layout.thumb_layout.hitbox.bounds, |window| { window.with_element_namespace("minimap", |window| { layout.minimap.paint(window, cx); - if layout.show_thumb { + if let Some(thumb_bounds) = layout.thumb_layout.thumb_bounds { let minimap_thumb_border = match layout.thumb_border_style { MinimapThumbBorder::Full => Edges::all(ScrollbarLayout::BORDER_WIDTH), MinimapThumbBorder::LeftOnly => Edges { @@ -5853,6 +5861,10 @@ impl EditorElement { let event_position = event.position; + let Some(thumb_bounds) = layout.thumb_layout.thumb_bounds else { + return; + }; + editor.update(cx, |editor, cx| { if !thumb_bounds.contains(&event_position) { let click_position = @@ -8426,6 +8438,7 @@ impl EditorScrollbars { glyph_grid_cell.along(axis), content_offset.along(axis), scroll_position.along(axis), + show_scrollbars, thumb_state, axis, ) @@ -8460,10 +8473,8 @@ struct ScrollbarLayout { hitbox: Hitbox, visible_range: Range, text_unit_size: Pixels, - content_offset: Pixels, - thumb_size: Pixels, + thumb_bounds: Option>, thumb_state: ScrollbarThumbState, - axis: ScrollbarAxis, } impl ScrollbarLayout { @@ -8479,6 +8490,7 @@ impl ScrollbarLayout { glyph_space: Pixels, content_offset: Pixels, scroll_position: f32, + show_thumb: bool, thumb_state: ScrollbarThumbState, axis: ScrollbarAxis, ) -> Self { @@ -8495,6 +8507,7 @@ impl ScrollbarLayout { glyph_space, content_offset, scroll_position, + show_thumb, thumb_state, axis, ) @@ -8507,6 +8520,7 @@ impl ScrollbarLayout { minimap_line_height: Pixels, scroll_position: f32, minimap_scroll_top: f32, + show_thumb: bool, ) -> Self { // The scrollbar thumb size is calculated as // (visible_content/total_content) × scrollbar_track_length. @@ -8535,6 +8549,7 @@ impl ScrollbarLayout { minimap_line_height, track_top_offset, scroll_position, + show_thumb, ScrollbarThumbState::Idle, ScrollbarAxis::Vertical, ) @@ -8548,6 +8563,7 @@ impl ScrollbarLayout { glyph_space: Pixels, content_offset: Pixels, scroll_position: f32, + show_thumb: bool, thumb_state: ScrollbarThumbState, axis: ScrollbarAxis, ) -> Self { @@ -8559,36 +8575,54 @@ impl ScrollbarLayout { let thumb_size = (track_length * thumb_percentage) .max(ScrollbarLayout::MIN_THUMB_SIZE) .min(track_length); - let text_unit_size = - (track_length - thumb_size) / (total_text_units - text_units_per_page).max(0.); + + let text_unit_divisor = (total_text_units - text_units_per_page).max(0.); + + let content_larger_than_viewport = text_unit_divisor > 0.; + + let text_unit_size = if content_larger_than_viewport { + (track_length - thumb_size) / text_unit_divisor + } else { + glyph_space + }; + + let thumb_bounds = (show_thumb && content_larger_than_viewport).then(|| { + Self::thumb_bounds( + &scrollbar_track_hitbox, + content_offset, + visible_range.start, + text_unit_size, + thumb_size, + axis, + ) + }); ScrollbarLayout { hitbox: scrollbar_track_hitbox, visible_range, text_unit_size, - content_offset, - thumb_size, + thumb_bounds, thumb_state, - axis, } } - fn thumb_bounds(&self) -> Bounds { - let scrollbar_track = &self.hitbox.bounds; + fn thumb_bounds( + scrollbar_track: &Hitbox, + content_offset: Pixels, + visible_range_start: f32, + text_unit_size: Pixels, + thumb_size: Pixels, + axis: ScrollbarAxis, + ) -> Bounds { + let thumb_origin = scrollbar_track.origin.apply_along(axis, |origin| { + origin + content_offset + visible_range_start * text_unit_size + }); Bounds::new( - scrollbar_track - .origin - .apply_along(self.axis, |origin| self.thumb_origin(origin)), - scrollbar_track - .size - .apply_along(self.axis, |_| self.thumb_size), + thumb_origin, + scrollbar_track.size.apply_along(axis, |_| thumb_size), ) } - fn thumb_origin(&self, origin: Pixels) -> Pixels { - origin + self.content_offset + self.visible_range.start * self.text_unit_size - } - fn marker_quads_for_ranges( &self, row_ranges: impl IntoIterator>, @@ -8677,7 +8711,6 @@ struct MinimapLayout { pub minimap_scroll_top: f32, pub minimap_line_height: Pixels, pub thumb_border_style: MinimapThumbBorder, - pub show_thumb: bool, pub max_scroll_top: f32, }