input: Keep more empty space at top or bottom of the Editor. (#1256)
<img width="727" height="586" alt="image" src="https://github.com/user-attachments/assets/2eb27326-831c-40fc-b0c8-48e6ab6ac67f" /> - Fix to keep 3 lines on top when move vertical. - Improve to keep 1 line edge for cursor, when editor is too small.
This commit is contained in:
parent
35568124bf
commit
478db2785a
1 changed files with 30 additions and 20 deletions
|
|
@ -2,9 +2,9 @@ use std::{ops::Range, rc::Rc};
|
||||||
|
|
||||||
use gpui::{
|
use gpui::{
|
||||||
fill, point, px, relative, size, App, Bounds, Corners, Element, ElementId, ElementInputHandler,
|
fill, point, px, relative, size, App, Bounds, Corners, Element, ElementId, ElementInputHandler,
|
||||||
Entity, GlobalElementId, HighlightStyle, IntoElement, LayoutId, MouseButton, MouseMoveEvent,
|
Entity, GlobalElementId, Half, HighlightStyle, IntoElement, LayoutId, MouseButton,
|
||||||
Path, Pixels, Point, SharedString, Size, Style, TextAlign, TextRun, UnderlineStyle, Window,
|
MouseMoveEvent, Path, Pixels, Point, SharedString, Size, Style, TextAlign, TextRun,
|
||||||
WrappedLine,
|
UnderlineStyle, Window, WrappedLine,
|
||||||
};
|
};
|
||||||
use rope::Rope;
|
use rope::Rope;
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
|
|
@ -16,8 +16,8 @@ use crate::{
|
||||||
|
|
||||||
use super::{mode::InputMode, InputState, LastLayout};
|
use super::{mode::InputMode, InputState, LastLayout};
|
||||||
|
|
||||||
|
const BOTTOM_MARGIN_ROWS: usize = 3;
|
||||||
pub(super) const RIGHT_MARGIN: Pixels = px(10.);
|
pub(super) const RIGHT_MARGIN: Pixels = px(10.);
|
||||||
const BOTTOM_MARGIN_ROWS: usize = 1;
|
|
||||||
pub(super) const LINE_NUMBER_RIGHT_MARGIN: Pixels = px(10.);
|
pub(super) const LINE_NUMBER_RIGHT_MARGIN: Pixels = px(10.);
|
||||||
|
|
||||||
pub(super) struct TextElement {
|
pub(super) struct TextElement {
|
||||||
|
|
@ -86,11 +86,14 @@ impl TextElement {
|
||||||
let mut cursor_bounds = None;
|
let mut cursor_bounds = None;
|
||||||
|
|
||||||
// If the input has a fixed height (Otherwise is auto-grow), we need to add a bottom margin to the input.
|
// If the input has a fixed height (Otherwise is auto-grow), we need to add a bottom margin to the input.
|
||||||
let bottom_margin = if state.mode.is_auto_grow() {
|
let top_bottom_margin = if state.mode.is_auto_grow() {
|
||||||
px(0.) + line_height
|
line_height
|
||||||
|
} else if visible_range.len() < BOTTOM_MARGIN_ROWS * 8 {
|
||||||
|
line_height
|
||||||
} else {
|
} else {
|
||||||
BOTTOM_MARGIN_ROWS * line_height + line_height
|
BOTTOM_MARGIN_ROWS * line_height
|
||||||
};
|
};
|
||||||
|
|
||||||
// The cursor corresponds to the current cursor position in the text no only the line.
|
// The cursor corresponds to the current cursor position in the text no only the line.
|
||||||
let mut cursor_pos = None;
|
let mut cursor_pos = None;
|
||||||
let mut cursor_start = None;
|
let mut cursor_start = None;
|
||||||
|
|
@ -176,17 +179,19 @@ impl TextElement {
|
||||||
} else {
|
} else {
|
||||||
scroll_offset.x
|
scroll_offset.x
|
||||||
};
|
};
|
||||||
scroll_offset.y = if scroll_offset.y + cursor_pos.y + line_height
|
|
||||||
> bounds.size.height - bottom_margin
|
// If we change the scroll_offset.y, GPUI will render and trigger the next run loop.
|
||||||
{
|
// So, here we just adjust offset by `line_height` for move smooth.
|
||||||
// cursor is out of bottom
|
scroll_offset.y =
|
||||||
bounds.size.height - bottom_margin - cursor_pos.y
|
if scroll_offset.y + cursor_pos.y > bounds.size.height - top_bottom_margin {
|
||||||
} else if scroll_offset.y + cursor_pos.y < px(0.) {
|
// cursor is out of bottom
|
||||||
// cursor is out of top
|
scroll_offset.y - line_height
|
||||||
scroll_offset.y - cursor_pos.y
|
} else if scroll_offset.y + cursor_pos.y < top_bottom_margin {
|
||||||
} else {
|
// cursor is out of top
|
||||||
scroll_offset.y
|
(scroll_offset.y + line_height).min(px(0.))
|
||||||
};
|
} else {
|
||||||
|
scroll_offset.y
|
||||||
|
};
|
||||||
|
|
||||||
if state.selection_reversed {
|
if state.selection_reversed {
|
||||||
if scroll_offset.x + cursor_start.x < px(0.) {
|
if scroll_offset.x + cursor_start.x < px(0.) {
|
||||||
|
|
@ -727,14 +732,19 @@ impl Element for TextElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
let total_wrapped_lines = state.text_wrapper.len();
|
let total_wrapped_lines = state.text_wrapper.len();
|
||||||
|
let empty_bottom_height = bounds
|
||||||
|
.size
|
||||||
|
.height
|
||||||
|
.half()
|
||||||
|
.max(BOTTOM_MARGIN_ROWS * line_height);
|
||||||
let scroll_size = size(
|
let scroll_size = size(
|
||||||
if longest_line_width + line_number_width + RIGHT_MARGIN > bounds.size.width {
|
if longest_line_width + line_number_width + RIGHT_MARGIN > bounds.size.width {
|
||||||
longest_line_width + line_number_width + RIGHT_MARGIN
|
longest_line_width + line_number_width + RIGHT_MARGIN
|
||||||
} else {
|
} else {
|
||||||
longest_line_width
|
longest_line_width
|
||||||
},
|
},
|
||||||
(total_wrapped_lines as f32 * line_height).max(bounds.size.height),
|
(total_wrapped_lines as f32 * line_height + empty_bottom_height)
|
||||||
|
.max(bounds.size.height),
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut last_layout = LastLayout {
|
let mut last_layout = LastLayout {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue