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::{
|
use gpui::{
|
||||||
px, App, AppContext as _, ClickEvent, Context, Entity, Focusable, InteractiveElement,
|
App, AppContext as _, ClickEvent, Context, Entity, Focusable, InteractiveElement, IntoElement,
|
||||||
IntoElement, ParentElement as _, Render, Styled, Window,
|
ParentElement as _, Render, Styled, Window, px,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::section;
|
use crate::section;
|
||||||
use gpui_component::{
|
use gpui_component::{
|
||||||
|
Sizable,
|
||||||
button::Button,
|
button::Button,
|
||||||
h_flex,
|
h_flex,
|
||||||
input::{InputState, TextInput},
|
input::{InputState, TextInput},
|
||||||
v_flex, Sizable,
|
v_flex,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn init(_: &mut App) {}
|
pub fn init(_: &mut App) {}
|
||||||
|
|
@ -17,6 +18,7 @@ pub struct TextareaStory {
|
||||||
textarea: Entity<InputState>,
|
textarea: Entity<InputState>,
|
||||||
textarea_auto_grow: Entity<InputState>,
|
textarea_auto_grow: Entity<InputState>,
|
||||||
textarea_no_wrap: Entity<InputState>,
|
textarea_no_wrap: Entity<InputState>,
|
||||||
|
textarea_auto_grow_no_wrap: Entity<InputState>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl super::Story for TextareaStory {
|
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| {
|
let textarea_no_wrap = cx.new(|cx| {
|
||||||
InputState::new(window, cx)
|
InputState::new(window, cx)
|
||||||
.multi_line()
|
.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")
|
.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 {
|
Self {
|
||||||
textarea,
|
textarea,
|
||||||
textarea_auto_grow,
|
textarea_auto_grow,
|
||||||
textarea_no_wrap,
|
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(
|
.child(
|
||||||
section("No Wrap")
|
section("No Wrap")
|
||||||
.max_w_md()
|
.max_w_md()
|
||||||
.child(TextInput::new(&self.textarea_no_wrap).h(px(200.))),
|
.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);
|
last_layout.lines = Rc::new(lines);
|
||||||
|
|
||||||
let total_wrapped_lines = state.text_wrapper.len();
|
let total_wrapped_lines = state.text_wrapper.len();
|
||||||
let empty_bottom_height = if state.mode.is_auto_grow() || state.mode.is_single_line() {
|
let empty_bottom_height = if state.mode.is_code_editor() {
|
||||||
px(0.)
|
|
||||||
} else {
|
|
||||||
bounds
|
bounds
|
||||||
.size
|
.size
|
||||||
.height
|
.height
|
||||||
.half()
|
.half()
|
||||||
.max(BOTTOM_MARGIN_ROWS * line_height)
|
.max(BOTTOM_MARGIN_ROWS * line_height)
|
||||||
|
} else {
|
||||||
|
px(0.)
|
||||||
};
|
};
|
||||||
|
|
||||||
let scroll_size = size(
|
let scroll_size = size(
|
||||||
|
|
@ -1283,9 +1283,7 @@ impl Element for TextElement {
|
||||||
state.set_input_bounds(input_bounds, cx);
|
state.set_input_bounds(input_bounds, cx);
|
||||||
state.last_selected_range = Some(selected_range);
|
state.last_selected_range = Some(selected_range);
|
||||||
state.scroll_size = prepaint.scroll_size;
|
state.scroll_size = prepaint.scroll_size;
|
||||||
state
|
state.update_scroll_offset(Some(prepaint.cursor_scroll_offset), cx);
|
||||||
.scroll_handle
|
|
||||||
.set_offset(prepaint.cursor_scroll_offset);
|
|
||||||
state.deferred_scroll_offset = None;
|
state.deferred_scroll_offset = None;
|
||||||
|
|
||||||
cx.notify();
|
cx.notify();
|
||||||
|
|
|
||||||
|
|
@ -1456,7 +1456,11 @@ impl InputState {
|
||||||
self.diagnostic_popover = None;
|
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 mut offset = offset.unwrap_or(self.scroll_handle.offset());
|
||||||
|
|
||||||
let safe_y_range =
|
let safe_y_range =
|
||||||
|
|
@ -1516,7 +1520,11 @@ impl InputState {
|
||||||
|
|
||||||
// Check if row_offset_y is out of the viewport
|
// Check if row_offset_y is out of the viewport
|
||||||
// If row offset is not in the viewport, scroll to make it visible
|
// 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 {
|
if row_offset_y - edge_height < -scroll_offset.y {
|
||||||
// Scroll up
|
// Scroll up
|
||||||
scroll_offset.y = -row_offset_y + edge_height;
|
scroll_offset.y = -row_offset_y + edge_height;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue