mirror of
https://github.com/zed-industries/zed.git
synced 2024-09-21 03:18:47 +03:00
editor: Add scroll_beyond_last_line setting (#11155)
Add `scroll_beyond_last_line` setting with 3 options: - `one_page`: The default (current) behaviour of scrolling one more page beyond the last line. <img width="568" alt="SCR-20240429-sxry" src="https://github.com/zed-industries/zed/assets/126383/1effbee9-759f-4858-9022-83bbb208ef82"> - `off`: No scrolling beyond the last line. <img width="568" alt="SCR-20240429-syhv" src="https://github.com/zed-industries/zed/assets/126383/5391b1d7-918d-43f3-8a6f-7642ef32d174"> - `vertical_scroll_margin`: Scroll beyond the last line by the same number of lines as `vertical_scroll_margin`. Matches the behaviour of keyboard scrolling. <img width="568" alt="SCR-20240429-sypc" src="https://github.com/zed-industries/zed/assets/126383/bb9cc928-e515-4503-88f7-e434c45d742f"> Release Notes: - Added `scroll_beyond_last_line` setting ([#4962](https://github.com/zed-industries/zed/issues/4962)).
This commit is contained in:
parent
40eb84109d
commit
6eb537643a
@ -255,6 +255,8 @@
|
|||||||
/// 2. "indent_aware"
|
/// 2. "indent_aware"
|
||||||
"background_coloring": "disabled"
|
"background_coloring": "disabled"
|
||||||
},
|
},
|
||||||
|
// Whether the editor will scroll beyond the last line.
|
||||||
|
"scroll_beyond_last_line": "one_page",
|
||||||
// The number of lines to keep above/below the cursor when scrolling.
|
// The number of lines to keep above/below the cursor when scrolling.
|
||||||
"vertical_scroll_margin": 3,
|
"vertical_scroll_margin": 3,
|
||||||
// Scroll sensitivity multiplier. This multiplier is applied
|
// Scroll sensitivity multiplier. This multiplier is applied
|
||||||
|
@ -15,6 +15,7 @@ pub struct EditorSettings {
|
|||||||
pub toolbar: Toolbar,
|
pub toolbar: Toolbar,
|
||||||
pub scrollbar: Scrollbar,
|
pub scrollbar: Scrollbar,
|
||||||
pub gutter: Gutter,
|
pub gutter: Gutter,
|
||||||
|
pub scroll_beyond_last_line: ScrollBeyondLastLine,
|
||||||
pub vertical_scroll_margin: f32,
|
pub vertical_scroll_margin: f32,
|
||||||
pub scroll_sensitivity: f32,
|
pub scroll_sensitivity: f32,
|
||||||
pub relative_line_numbers: bool,
|
pub relative_line_numbers: bool,
|
||||||
@ -116,6 +117,22 @@ pub enum MultiCursorModifier {
|
|||||||
CmdOrCtrl,
|
CmdOrCtrl,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Whether the editor will scroll beyond the last line.
|
||||||
|
///
|
||||||
|
/// Default: one_page
|
||||||
|
#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
|
||||||
|
#[serde(rename_all = "snake_case")]
|
||||||
|
pub enum ScrollBeyondLastLine {
|
||||||
|
/// The editor will not scroll beyond the last line.
|
||||||
|
Off,
|
||||||
|
|
||||||
|
/// The editor will scroll beyond the last line by one page.
|
||||||
|
OnePage,
|
||||||
|
|
||||||
|
/// The editor will scroll beyond the last line by the same number of lines as vertical_scroll_margin.
|
||||||
|
VerticalScrollMargin,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Default, Serialize, Deserialize, JsonSchema)]
|
#[derive(Clone, Default, Serialize, Deserialize, JsonSchema)]
|
||||||
pub struct EditorSettingsContent {
|
pub struct EditorSettingsContent {
|
||||||
/// Whether the cursor blinks in the editor.
|
/// Whether the cursor blinks in the editor.
|
||||||
@ -158,6 +175,10 @@ pub struct EditorSettingsContent {
|
|||||||
pub scrollbar: Option<ScrollbarContent>,
|
pub scrollbar: Option<ScrollbarContent>,
|
||||||
/// Gutter related settings
|
/// Gutter related settings
|
||||||
pub gutter: Option<GutterContent>,
|
pub gutter: Option<GutterContent>,
|
||||||
|
/// Whether the editor will scroll beyond the last line.
|
||||||
|
///
|
||||||
|
/// Default: one_page
|
||||||
|
pub scroll_beyond_last_line: Option<ScrollBeyondLastLine>,
|
||||||
/// The number of lines to keep above/below the cursor when auto-scrolling.
|
/// The number of lines to keep above/below the cursor when auto-scrolling.
|
||||||
///
|
///
|
||||||
/// Default: 3.
|
/// Default: 3.
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
use crate::editor_settings::ScrollBeyondLastLine;
|
||||||
use crate::{
|
use crate::{
|
||||||
blame_entry_tooltip::{blame_entry_relative_timestamp, BlameEntryTooltip},
|
blame_entry_tooltip::{blame_entry_relative_timestamp, BlameEntryTooltip},
|
||||||
display_map::{
|
display_map::{
|
||||||
@ -1089,11 +1090,17 @@ impl EditorElement {
|
|||||||
point(bounds.lower_right().x, bounds.lower_left().y),
|
point(bounds.lower_right().x, bounds.lower_left().y),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let settings = EditorSettings::get_global(cx);
|
||||||
|
let scroll_beyond_last_line: f32 = match settings.scroll_beyond_last_line {
|
||||||
|
ScrollBeyondLastLine::OnePage => rows_per_page,
|
||||||
|
ScrollBeyondLastLine::Off => 1.0,
|
||||||
|
ScrollBeyondLastLine::VerticalScrollMargin => 1.0 + settings.vertical_scroll_margin,
|
||||||
|
};
|
||||||
|
let total_rows = snapshot.max_point().row().as_f32() + scroll_beyond_last_line;
|
||||||
let height = bounds.size.height;
|
let height = bounds.size.height;
|
||||||
let total_rows = snapshot.max_point().row().as_f32() + rows_per_page;
|
|
||||||
let px_per_row = height / total_rows;
|
let px_per_row = height / total_rows;
|
||||||
let thumb_height = (rows_per_page * px_per_row).max(ScrollbarLayout::MIN_THUMB_HEIGHT);
|
let thumb_height = (rows_per_page * px_per_row).max(ScrollbarLayout::MIN_THUMB_HEIGHT);
|
||||||
let row_height = (height - thumb_height) / snapshot.max_point().row().as_f32();
|
let row_height = (height - thumb_height) / (total_rows - rows_per_page).max(0.0);
|
||||||
|
|
||||||
Some(ScrollbarLayout {
|
Some(ScrollbarLayout {
|
||||||
hitbox: cx.insert_hitbox(track_bounds, false),
|
hitbox: cx.insert_hitbox(track_bounds, false),
|
||||||
@ -4805,9 +4812,22 @@ impl Element for EditorElement {
|
|||||||
cx,
|
cx,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let settings = EditorSettings::get_global(cx);
|
||||||
|
let scroll_max_row = max_row.as_f32();
|
||||||
|
let scroll_max_row = match settings.scroll_beyond_last_line {
|
||||||
|
ScrollBeyondLastLine::OnePage => scroll_max_row,
|
||||||
|
ScrollBeyondLastLine::Off => {
|
||||||
|
(scroll_max_row - height_in_lines + 1.0).max(0.0)
|
||||||
|
}
|
||||||
|
ScrollBeyondLastLine::VerticalScrollMargin => (scroll_max_row
|
||||||
|
- height_in_lines
|
||||||
|
+ 1.0
|
||||||
|
+ settings.vertical_scroll_margin)
|
||||||
|
.max(0.0),
|
||||||
|
};
|
||||||
let scroll_max = point(
|
let scroll_max = point(
|
||||||
((scroll_width - text_hitbox.size.width) / em_width).max(0.0),
|
((scroll_width - text_hitbox.size.width) / em_width).max(0.0),
|
||||||
max_row.as_f32(),
|
scroll_max_row,
|
||||||
);
|
);
|
||||||
|
|
||||||
self.editor.update(cx, |editor, cx| {
|
self.editor.update(cx, |editor, cx| {
|
||||||
|
@ -2,6 +2,7 @@ mod actions;
|
|||||||
pub(crate) mod autoscroll;
|
pub(crate) mod autoscroll;
|
||||||
pub(crate) mod scroll_amount;
|
pub(crate) mod scroll_amount;
|
||||||
|
|
||||||
|
use crate::editor_settings::ScrollBeyondLastLine;
|
||||||
use crate::{
|
use crate::{
|
||||||
display_map::{DisplaySnapshot, ToDisplayPoint},
|
display_map::{DisplaySnapshot, ToDisplayPoint},
|
||||||
hover_popover::hide_hover,
|
hover_popover::hide_hover,
|
||||||
@ -199,8 +200,20 @@ impl ScrollManager {
|
|||||||
0,
|
0,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
let scroll_top = scroll_position.y;
|
||||||
|
let scroll_top = match EditorSettings::get_global(cx).scroll_beyond_last_line {
|
||||||
|
ScrollBeyondLastLine::OnePage => scroll_top,
|
||||||
|
ScrollBeyondLastLine::Off => scroll_top
|
||||||
|
.min((map.max_buffer_row().as_f32()) - self.visible_line_count.unwrap() + 1.0),
|
||||||
|
ScrollBeyondLastLine::VerticalScrollMargin => scroll_top.min(
|
||||||
|
(map.max_buffer_row().as_f32()) - self.visible_line_count.unwrap()
|
||||||
|
+ 1.0
|
||||||
|
+ self.vertical_scroll_margin,
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
let scroll_top_buffer_point =
|
let scroll_top_buffer_point =
|
||||||
DisplayPoint::new(DisplayRow(scroll_position.y as u32), 0).to_point(&map);
|
DisplayPoint::new(DisplayRow(scroll_top as u32), 0).to_point(&map);
|
||||||
let top_anchor = map
|
let top_anchor = map
|
||||||
.buffer_snapshot
|
.buffer_snapshot
|
||||||
.anchor_at(scroll_top_buffer_point, Bias::Right);
|
.anchor_at(scroll_top_buffer_point, Bias::Right);
|
||||||
@ -210,7 +223,7 @@ impl ScrollManager {
|
|||||||
anchor: top_anchor,
|
anchor: top_anchor,
|
||||||
offset: point(
|
offset: point(
|
||||||
scroll_position.x.max(0.),
|
scroll_position.x.max(0.),
|
||||||
scroll_position.y - top_anchor.to_display_point(&map).row().as_f32(),
|
scroll_top - top_anchor.to_display_point(&map).row().as_f32(),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
scroll_top_buffer_point.row,
|
scroll_top_buffer_point.row,
|
||||||
|
Loading…
Reference in New Issue
Block a user