input: Fix may flash scroll when move cursor in auto grow mode. (#1419)
This commit is contained in:
parent
b80fca28c1
commit
6dd857a7f7
3 changed files with 45 additions and 19 deletions
|
|
@ -1,14 +1,15 @@
|
|||
use gpui::{
|
||||
px, App, AppContext as _, ClickEvent, Context, Entity, Focusable, InteractiveElement,
|
||||
IntoElement, ParentElement as _, Render, Styled, Window,
|
||||
App, AppContext as _, ClickEvent, Context, Entity, Focusable, InteractiveElement, IntoElement,
|
||||
ParentElement as _, Render, Styled, Window, px,
|
||||
};
|
||||
|
||||
use crate::section;
|
||||
use gpui_component::{
|
||||
Sizable,
|
||||
button::Button,
|
||||
h_flex,
|
||||
input::{InputState, TextInput},
|
||||
v_flex, Sizable,
|
||||
v_flex,
|
||||
};
|
||||
|
||||
pub fn init(_: &mut App) {}
|
||||
|
|
@ -17,6 +18,7 @@ pub struct TextareaStory {
|
|||
textarea: Entity<InputState>,
|
||||
textarea_auto_grow: Entity<InputState>,
|
||||
textarea_no_wrap: Entity<InputState>,
|
||||
textarea_auto_grow_no_wrap: Entity<InputState>,
|
||||
}
|
||||
|
||||
impl super::Story for TextareaStory {
|
||||
|
|
@ -73,13 +75,6 @@ impl TextareaStory {
|
|||
)
|
||||
});
|
||||
|
||||
let textarea_auto_grow = cx.new(|cx| {
|
||||
InputState::new(window, cx)
|
||||
.auto_grow(1, 5)
|
||||
.placeholder("Enter text here...")
|
||||
.default_value("Hello 世界,this is GPUI component.")
|
||||
});
|
||||
|
||||
let textarea_no_wrap = cx.new(|cx| {
|
||||
InputState::new(window, cx)
|
||||
.multi_line()
|
||||
|
|
@ -88,10 +83,26 @@ impl TextareaStory {
|
|||
.default_value("This is a very long line of text to test if the horizontal scrolling function is working properly, and it should not wrap automatically but display a horizontal scrollbar.\nThe second line is also very long text, used to test the horizontal scrolling effect under multiple lines, and you can input more content to test.\nThe third line: Here you can input other long text content that requires horizontal scrolling.\n")
|
||||
});
|
||||
|
||||
let textarea_auto_grow = cx.new(|cx| {
|
||||
InputState::new(window, cx)
|
||||
.auto_grow(1, 5)
|
||||
.placeholder("Enter text here...")
|
||||
.default_value("Hello 世界, this is a very long line of text to test if the horizontal scrolling function is working properly, and it should not wrap automatically but display a horizontal scrollbar.\nThe second line is also very long text, used to test the horizontal scrolling effect under multiple lines, and you can input more content to test.\nThe third line: Here you can input other long text content that requires horizontal scrolling.\n")
|
||||
});
|
||||
|
||||
let textarea_auto_grow_no_wrap = cx.new(|cx| {
|
||||
InputState::new(window, cx)
|
||||
.auto_grow(1, 5)
|
||||
.soft_wrap(false)
|
||||
.placeholder("Enter text here...")
|
||||
.default_value("Hello 世界,this is GPUI component.")
|
||||
});
|
||||
|
||||
Self {
|
||||
textarea,
|
||||
textarea_auto_grow,
|
||||
textarea_no_wrap,
|
||||
textarea_auto_grow_no_wrap,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -166,11 +177,20 @@ impl Render for TextareaStory {
|
|||
),
|
||||
),
|
||||
)
|
||||
.child(section("Textarea Auto Grow").child(TextInput::new(&self.textarea_auto_grow)))
|
||||
.child(
|
||||
section("No Wrap")
|
||||
.max_w_md()
|
||||
.child(TextInput::new(&self.textarea_no_wrap).h(px(200.))),
|
||||
)
|
||||
.child(
|
||||
section("Auto Grow")
|
||||
.max_w_md()
|
||||
.child(TextInput::new(&self.textarea_auto_grow)),
|
||||
)
|
||||
.child(
|
||||
section("Auto Grow with No Wrap")
|
||||
.max_w_md()
|
||||
.child(TextInput::new(&self.textarea_auto_grow_no_wrap)),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -974,14 +974,14 @@ impl Element for TextElement {
|
|||
last_layout.lines = Rc::new(lines);
|
||||
|
||||
let total_wrapped_lines = state.text_wrapper.len();
|
||||
let empty_bottom_height = if state.mode.is_auto_grow() || state.mode.is_single_line() {
|
||||
px(0.)
|
||||
} else {
|
||||
let empty_bottom_height = if state.mode.is_code_editor() {
|
||||
bounds
|
||||
.size
|
||||
.height
|
||||
.half()
|
||||
.max(BOTTOM_MARGIN_ROWS * line_height)
|
||||
} else {
|
||||
px(0.)
|
||||
};
|
||||
|
||||
let scroll_size = size(
|
||||
|
|
@ -1283,9 +1283,7 @@ impl Element for TextElement {
|
|||
state.set_input_bounds(input_bounds, cx);
|
||||
state.last_selected_range = Some(selected_range);
|
||||
state.scroll_size = prepaint.scroll_size;
|
||||
state
|
||||
.scroll_handle
|
||||
.set_offset(prepaint.cursor_scroll_offset);
|
||||
state.update_scroll_offset(Some(prepaint.cursor_scroll_offset), cx);
|
||||
state.deferred_scroll_offset = None;
|
||||
|
||||
cx.notify();
|
||||
|
|
|
|||
|
|
@ -1456,7 +1456,11 @@ impl InputState {
|
|||
self.diagnostic_popover = None;
|
||||
}
|
||||
|
||||
fn update_scroll_offset(&mut self, offset: Option<Point<Pixels>>, cx: &mut Context<Self>) {
|
||||
pub(super) fn update_scroll_offset(
|
||||
&mut self,
|
||||
offset: Option<Point<Pixels>>,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
let mut offset = offset.unwrap_or(self.scroll_handle.offset());
|
||||
|
||||
let safe_y_range =
|
||||
|
|
@ -1516,7 +1520,11 @@ impl InputState {
|
|||
|
||||
// Check if row_offset_y is out of the viewport
|
||||
// If row offset is not in the viewport, scroll to make it visible
|
||||
let edge_height = 3 * line_height;
|
||||
let edge_height = if self.mode.is_code_editor() {
|
||||
3 * line_height
|
||||
} else {
|
||||
line_height
|
||||
};
|
||||
if row_offset_y - edge_height < -scroll_offset.y {
|
||||
// Scroll up
|
||||
scroll_offset.y = -row_offset_y + edge_height;
|
||||
|
|
|
|||
Loading…
Reference in a new issue