Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 58 additions & 6 deletions crates/base/src/input/base/element.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use smallvec::SmallVec;
use std::{ops::Range, rc::Rc};

use crate::{
Scrollbar,
Scrollbar, ScrollbarPlacement,
input::{RopeExt as _, blink_cursor::CURSOR_WIDTH, display_map::LineLayout},
};

Expand Down Expand Up @@ -138,6 +138,7 @@ pub(super) struct EditorScrollbarSnapshot {
layout: EditorScrollbarLayout,
cursor_scroll_offset: Point<Pixels>,
soft_wrap: bool,
placement: ScrollbarPlacement,
}

impl EditorScrollbarSnapshot {
Expand All @@ -154,9 +155,11 @@ impl EditorScrollbarSnapshot {
last_layout.line_number_width,
scroll_size,
state.editor_paddings,
state.scrollbar_placement,
),
cursor_scroll_offset,
soft_wrap: state.soft_wrap,
placement: state.scrollbar_placement,
}
}
}
Expand All @@ -167,8 +170,11 @@ impl EditorScrollbarLayout {
line_number_width: Pixels,
scroll_size: Size<Pixels>,
paddings: Edges<Pixels>,
placement: ScrollbarPlacement,
) -> Self {
let left = if line_number_width == px(0.) {
let left = if placement.is_left() {
-paddings.left
} else if line_number_width == px(0.) {
px(0.)
} else {
paddings.left + line_number_width - LINE_NUMBER_RIGHT_MARGIN
Expand Down Expand Up @@ -262,6 +268,7 @@ impl<M: InputModeKind> Element for EditorScrollbar<M> {
} else {
Scrollbar::vertical(&scroll_handle)
}
.placement(snapshot.placement)
.viewport_bounds(snapshot.layout.bounds)
.scroll_size(snapshot.layout.scroll_size)
.into_any_element();
Expand Down Expand Up @@ -4811,17 +4818,27 @@ mod tests {
left: px(7.),
};

let layout =
EditorScrollbarLayout::new(input_bounds, px(40.), size(px(1000.), px(200.)), paddings);
let layout = EditorScrollbarLayout::new(
input_bounds,
px(40.),
size(px(1000.), px(200.)),
paddings,
ScrollbarPlacement::BottomRight,
);

assert_eq!(
layout.bounds,
Bounds::new(point(px(51.), px(18.)), size(px(262.), px(87.)))
);
assert_eq!(layout.scroll_size, size(px(972.), px(200.)));

let layout_without_gutter =
EditorScrollbarLayout::new(input_bounds, px(0.), size(px(500.), px(120.)), paddings);
let layout_without_gutter = EditorScrollbarLayout::new(
input_bounds,
px(0.),
size(px(500.), px(120.)),
paddings,
ScrollbarPlacement::BottomRight,
);

assert_eq!(
layout_without_gutter.bounds,
Expand All @@ -4830,6 +4847,41 @@ mod tests {
assert_eq!(layout_without_gutter.scroll_size, size(px(513.), px(120.)));
}

#[test]
fn test_editor_scrollbar_layout_on_the_left_covers_the_gutter() {
let input_bounds = Bounds::new(point(px(10.), px(20.)), size(px(300.), px(80.)));
let paddings = Edges {
top: px(2.),
right: px(3.),
bottom: px(5.),
left: px(7.),
};

let layout = EditorScrollbarLayout::new(
input_bounds,
px(40.),
size(px(1000.), px(200.)),
paddings,
ScrollbarPlacement::BottomLeft,
);

assert_eq!(
layout.bounds,
Bounds::new(point(px(3.), px(18.)), size(px(310.), px(87.)))
);
assert_eq!(layout.scroll_size, size(px(1020.), px(200.)));
assert_eq!(
EditorScrollbarLayout::new(
input_bounds,
px(40.),
size(px(1000.), px(200.)),
paddings,
ScrollbarPlacement::TopLeft,
),
layout
);
}

#[test]
fn test_editor_gutter_covers_the_complete_fixed_column() {
let input_bounds = Bounds::new(point(px(10.), px(20.)), size(px(300.), px(80.)));
Expand Down
23 changes: 23 additions & 0 deletions crates/base/src/input/base/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ use super::{
mode::LayoutMode,
undo_manager::{EditIntent, UndoManager},
};
use crate::ScrollbarPlacement;
use crate::actions::{SelectDown, SelectLeft, SelectRight, SelectUp};
use crate::input::blink_cursor::CURSOR_WIDTH;
use crate::input::movement::MoveDirection;
Expand Down Expand Up @@ -430,6 +431,7 @@ pub struct InputBaseState<M: InputModeKind> {
/// The size of the scrollable content.
pub(crate) scroll_size: gpui::Size<Pixels>,
pub(super) editor_scrollbar_snapshot: Cell<Option<EditorScrollbarSnapshot>>,
pub(super) scrollbar_placement: ScrollbarPlacement,
/// The unwrapped width of the longest line and what it was measured for.
pub(super) longest_line_width: Cell<Option<(LongestLineKey, Pixels)>>,
pub(super) editor_paddings: Edges<Pixels>,
Expand Down Expand Up @@ -765,6 +767,7 @@ impl<M: InputModeKind> InputBaseState<M> {
scroll_handle: ScrollHandle::new(),
scroll_size: gpui::size(px(0.), px(0.)),
editor_scrollbar_snapshot: Cell::new(None),
scrollbar_placement: ScrollbarPlacement::default(),
longest_line_width: Cell::new(None),
editor_paddings: Edges::default(),
deferred_scroll_offset: None,
Expand Down Expand Up @@ -10667,6 +10670,26 @@ impl<M: crate::input::MultiLineMode> InputBaseState<M> {
cx.notify();
}

/// The placement of the scrollbars, default is [`ScrollbarPlacement::BottomRight`].
///
/// On the left, the vertical scrollbar sits on the input's left edge, over
/// the line numbers. At the top, the horizontal scrollbar overlays the
/// first line, as at the bottom it overlays the last.
pub fn scrollbar_placement(mut self, placement: ScrollbarPlacement) -> Self {
self.scrollbar_placement = placement;
self
}

/// See [`InputBaseState::scrollbar_placement`].
pub fn set_scrollbar_placement(
&mut self,
placement: ScrollbarPlacement,
cx: &mut Context<Self>,
) {
self.scrollbar_placement = placement;
cx.notify();
}

/// Set the soft wrap mode, default is true.
#[doc(hidden)]
pub fn soft_wrap(mut self, wrap: bool) -> Self {
Expand Down
2 changes: 1 addition & 1 deletion crates/base/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ pub use scroll_bounce::{ScrollBounce, ScrollBounceMotion};
pub use scrollable_mask::ScrollableMask;
pub use scrollbar::{
Scrollbar, ScrollbarAxis, ScrollbarEntrance, ScrollbarHandle, ScrollbarMode, ScrollbarMotion,
ScrollbarStyles, ScrollbarThumbStyle, ScrollbarTrackStyle,
ScrollbarPlacement, ScrollbarStyles, ScrollbarThumbStyle, ScrollbarTrackStyle,
};
pub use select::Select;
pub use selectable_text::SelectableText;
Expand Down
Loading
Loading