Merge pull request #116585 from jinyangcruise/fix_symbol_jump
Fix symbol jump history navigation issue.
This commit is contained in:
commit
db25be3646
13 changed files with 183 additions and 32 deletions
|
|
@ -797,6 +797,7 @@
|
|||
<description>
|
||||
Returns [code]true[/code] if the caret is visible, [code]false[/code] otherwise. A caret will be considered hidden if it is outside the scrollable area when scrolling is enabled.
|
||||
[b]Note:[/b] [method is_caret_visible] does not account for a caret being off-screen if it is still within the scrollable area. It will return [code]true[/code] even if the caret is off-screen as long as it meets [TextEdit]'s own conditions for being visible. This includes uses of [member scroll_fit_content_width] and [member scroll_fit_content_height] that cause the [TextEdit] to expand beyond the viewport's bounds.
|
||||
[b]Note:[/b] This method does [i]not[/i] guarantee an accurate visibility check immediately after setting the caret position. The correct value may only be available in the next frame after the [TextEdit] has finished drawing. This also applies to any operation that causes the [TextEdit] to change in size.
|
||||
</description>
|
||||
</method>
|
||||
<method name="is_dragging_cursor" qualifiers="const">
|
||||
|
|
@ -840,6 +841,13 @@
|
|||
Returns [code]true[/code] if the gutter at the given index on the given line is clickable. See [method set_line_gutter_clickable].
|
||||
</description>
|
||||
</method>
|
||||
<method name="is_line_in_viewport" qualifiers="const">
|
||||
<return type="bool" />
|
||||
<param index="0" name="line" type="int" />
|
||||
<description>
|
||||
Returns [code]true[/code] if the given line is within the scope of the scrollable area of the viewport.
|
||||
</description>
|
||||
</method>
|
||||
<method name="is_line_wrapped" qualifiers="const">
|
||||
<return type="bool" />
|
||||
<param index="0" name="line" type="int" />
|
||||
|
|
|
|||
|
|
@ -1378,6 +1378,24 @@ void CodeTextEditor::toggle_inline_comment(const String &delimiter) {
|
|||
text_editor->end_complex_operation();
|
||||
}
|
||||
|
||||
void CodeTextEditor::adjust_viewport_to_caret() {
|
||||
call_on_all_layout_pending_finished(callable_mp((TextEdit *)text_editor, &TextEdit::adjust_viewport_to_caret).bind(0));
|
||||
}
|
||||
|
||||
void CodeTextEditor::center_viewport_to_caret() {
|
||||
call_on_all_layout_pending_finished(callable_mp((TextEdit *)text_editor, &TextEdit::center_viewport_to_caret).bind(0));
|
||||
}
|
||||
|
||||
void CodeTextEditor::center_viewport_to_caret_if_line_invisible(int p_line) {
|
||||
if (text_editor->is_layout_pending_in_tree()) {
|
||||
text_editor->call_on_all_layout_pending_finished(callable_mp(this, &CodeTextEditor::center_viewport_to_caret_if_line_invisible).bind(0));
|
||||
return;
|
||||
}
|
||||
if (!text_editor->is_line_in_viewport(p_line)) {
|
||||
text_editor->center_viewport_to_caret();
|
||||
}
|
||||
}
|
||||
|
||||
void CodeTextEditor::goto_line(int p_line, int p_column) {
|
||||
text_editor->remove_secondary_carets();
|
||||
text_editor->deselect();
|
||||
|
|
@ -1386,8 +1404,7 @@ void CodeTextEditor::goto_line(int p_line, int p_column) {
|
|||
text_editor->set_caret_column(p_column, false);
|
||||
text_editor->set_code_hint("");
|
||||
text_editor->cancel_code_completion();
|
||||
// Defer in case the CodeEdit was just created and needs to be resized.
|
||||
callable_mp((TextEdit *)text_editor, &TextEdit::adjust_viewport_to_caret).call_deferred(0);
|
||||
adjust_viewport_to_caret();
|
||||
}
|
||||
|
||||
void CodeTextEditor::goto_line_selection(int p_line, int p_begin, int p_end) {
|
||||
|
|
@ -1396,7 +1413,7 @@ void CodeTextEditor::goto_line_selection(int p_line, int p_begin, int p_end) {
|
|||
text_editor->select(p_line, p_begin, p_line, p_end);
|
||||
text_editor->set_code_hint("");
|
||||
text_editor->cancel_code_completion();
|
||||
callable_mp((TextEdit *)text_editor, &TextEdit::adjust_viewport_to_caret).call_deferred(0);
|
||||
adjust_viewport_to_caret();
|
||||
}
|
||||
|
||||
void CodeTextEditor::goto_line_centered(int p_line, int p_column) {
|
||||
|
|
@ -1407,7 +1424,7 @@ void CodeTextEditor::goto_line_centered(int p_line, int p_column) {
|
|||
text_editor->set_caret_column(p_column, false);
|
||||
text_editor->set_code_hint("");
|
||||
text_editor->cancel_code_completion();
|
||||
callable_mp((TextEdit *)text_editor, &TextEdit::center_viewport_to_caret).call_deferred(0);
|
||||
center_viewport_to_caret();
|
||||
}
|
||||
|
||||
void CodeTextEditor::set_executing_line(int p_line) {
|
||||
|
|
@ -1458,15 +1475,21 @@ void CodeTextEditor::set_edit_state(const Variant &p_state) {
|
|||
Dictionary state = p_state;
|
||||
|
||||
/* update the row first as it sets the column to 0 */
|
||||
text_editor->set_caret_line(state["row"]);
|
||||
text_editor->set_caret_column(state["column"]);
|
||||
if (int(state["scroll_position"]) == -1) {
|
||||
// Special case for previous state.
|
||||
text_editor->center_viewport_to_caret();
|
||||
if (state.get("ensure_caret_visible", false)) {
|
||||
text_editor->set_caret_line(state["row"], false);
|
||||
text_editor->set_caret_column(state["column"], false);
|
||||
center_viewport_to_caret_if_line_invisible(state["row"]);
|
||||
} else {
|
||||
text_editor->set_v_scroll(state["scroll_position"]);
|
||||
text_editor->set_caret_line(state["row"]);
|
||||
text_editor->set_caret_column(state["column"]);
|
||||
if (int(state["scroll_position"]) == -1) {
|
||||
// Special case for previous state.
|
||||
center_viewport_to_caret();
|
||||
} else {
|
||||
text_editor->set_v_scroll(state["scroll_position"]);
|
||||
}
|
||||
text_editor->set_h_scroll(state["h_scroll_position"]);
|
||||
}
|
||||
text_editor->set_h_scroll(state["h_scroll_position"]);
|
||||
|
||||
if (state.get("selection", false)) {
|
||||
text_editor->select(state["selection_from_line"], state["selection_from_column"], state["selection_to_line"], state["selection_to_column"]);
|
||||
|
|
|
|||
|
|
@ -256,6 +256,10 @@ public:
|
|||
/// by adding or removing comment delimiter
|
||||
void toggle_inline_comment(const String &delimiter);
|
||||
|
||||
void adjust_viewport_to_caret();
|
||||
void center_viewport_to_caret();
|
||||
void center_viewport_to_caret_if_line_invisible(int p_line);
|
||||
|
||||
void goto_line(int p_line, int p_column = 0);
|
||||
void goto_line_selection(int p_line, int p_begin, int p_end);
|
||||
void goto_line_centered(int p_line, int p_column = 0);
|
||||
|
|
|
|||
|
|
@ -203,12 +203,6 @@ void ScriptEditor::_goto_script_line(Ref<RefCounted> p_script, int p_line) {
|
|||
if (scr.is_valid() && (scr->has_source_code() || scr->get_path().is_resource_file())) {
|
||||
if (edit(p_script, p_line, 0)) {
|
||||
EditorNode::get_singleton()->push_item(p_script.ptr());
|
||||
|
||||
if (TextEditorBase *current = Object::cast_to<TextEditorBase>(_get_current_editor())) {
|
||||
current->goto_line_centered(p_line);
|
||||
}
|
||||
|
||||
_save_history();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -316,7 +310,9 @@ void ScriptEditor::_save_history() {
|
|||
Node *n = tab_container->get_current_tab_control();
|
||||
|
||||
if (Object::cast_to<TextEditorBase>(n)) {
|
||||
history.write[history_pos].state = Object::cast_to<TextEditorBase>(n)->get_navigation_state();
|
||||
Dictionary nav_state = Object::cast_to<TextEditorBase>(n)->get_navigation_state();
|
||||
nav_state["ensure_caret_visible"] = true;
|
||||
history.write[history_pos].state = nav_state;
|
||||
}
|
||||
if (Object::cast_to<EditorHelp>(n)) {
|
||||
history.write[history_pos].state = Object::cast_to<EditorHelp>(n)->get_scroll();
|
||||
|
|
@ -375,7 +371,9 @@ void ScriptEditor::_go_to_tab(int p_idx) {
|
|||
Node *n = tab_container->get_current_tab_control();
|
||||
|
||||
if (Object::cast_to<TextEditorBase>(n)) {
|
||||
history.write[history_pos].state = Object::cast_to<TextEditorBase>(n)->get_navigation_state();
|
||||
Dictionary nav_state = Object::cast_to<TextEditorBase>(n)->get_navigation_state();
|
||||
nav_state["ensure_caret_visible"] = true;
|
||||
history.write[history_pos].state = nav_state;
|
||||
}
|
||||
if (Object::cast_to<EditorHelp>(n)) {
|
||||
history.write[history_pos].state = Object::cast_to<EditorHelp>(n)->get_scroll();
|
||||
|
|
@ -2231,7 +2229,7 @@ bool ScriptEditor::edit(const Ref<Resource> &p_resource, int p_line, int p_col,
|
|||
}
|
||||
|
||||
if (p_line >= 0) {
|
||||
teb->goto_line(p_line, p_col);
|
||||
teb->goto_line_centered(p_line, p_col);
|
||||
}
|
||||
} else if (tab_container->get_current_tab() != i) {
|
||||
_go_to_tab(i);
|
||||
|
|
@ -2358,7 +2356,7 @@ bool ScriptEditor::edit(const Ref<Resource> &p_resource, int p_line, int p_col,
|
|||
|
||||
if (TextEditorBase *teb = Object::cast_to<TextEditorBase>(seb)) {
|
||||
if (p_line >= 0) {
|
||||
teb->goto_line(p_line, p_col);
|
||||
teb->goto_line_centered(p_line, p_col);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3442,7 +3440,9 @@ void ScriptEditor::_update_history_pos(int p_new_pos) {
|
|||
Node *n = tab_container->get_current_tab_control();
|
||||
|
||||
if (Object::cast_to<TextEditorBase>(n)) {
|
||||
history.write[history_pos].state = Object::cast_to<TextEditorBase>(n)->get_navigation_state();
|
||||
Dictionary nav_state = Object::cast_to<TextEditorBase>(n)->get_navigation_state();
|
||||
nav_state["ensure_caret_visible"] = true;
|
||||
history.write[history_pos].state = nav_state;
|
||||
}
|
||||
if (Object::cast_to<EditorHelp>(n)) {
|
||||
history.write[history_pos].state = Object::cast_to<EditorHelp>(n)->get_scroll();
|
||||
|
|
|
|||
|
|
@ -1161,11 +1161,18 @@ void ScriptTextEditor::_on_caret_moved() {
|
|||
if (code_editor->is_previewing_navigation_change()) {
|
||||
return;
|
||||
}
|
||||
if (is_layout_pending_in_tree()) {
|
||||
call_on_all_layout_pending_finished(callable_mp(this, &ScriptTextEditor::_on_caret_moved));
|
||||
return;
|
||||
}
|
||||
// When previous_line < 0, it means the user has just switched to this editor from a different one
|
||||
// (which already saved a state in the history). In this case, we should not save this editor's previous state.
|
||||
int current_line = code_editor->get_text_editor()->get_caret_line();
|
||||
if (Math::abs(current_line - previous_line) >= 10) {
|
||||
if (previous_line >= 0 && Math::abs(current_line - previous_line) >= 10) {
|
||||
Dictionary nav_state = get_navigation_state();
|
||||
nav_state["row"] = previous_line;
|
||||
nav_state["scroll_position"] = -1;
|
||||
nav_state["ensure_caret_visible"] = true;
|
||||
emit_signal(SNAME("request_save_previous_state"), nav_state);
|
||||
store_previous_state();
|
||||
}
|
||||
|
|
@ -1888,6 +1895,11 @@ void ScriptTextEditor::_notification(int p_what) {
|
|||
case NOTIFICATION_DRAG_END: {
|
||||
drag_info_label->hide();
|
||||
} break;
|
||||
case NOTIFICATION_VISIBILITY_CHANGED: {
|
||||
if (!is_visible()) {
|
||||
previous_line = -1;
|
||||
}
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ class ScriptTextEditor : public CodeEditorBase {
|
|||
Color marked_line_color = Color(1, 1, 1);
|
||||
Color warning_line_color = Color(1, 1, 1);
|
||||
Color folded_code_region_color = Color(1, 1, 1);
|
||||
int previous_line = 0;
|
||||
int previous_line = -1; // Previous caret line number when user continuously operates in this editor. Affects history state. Reset to -1 on editor switch.
|
||||
|
||||
PopupPanel *color_panel = nullptr;
|
||||
ColorPicker *color_picker = nullptr;
|
||||
|
|
|
|||
|
|
@ -94,6 +94,7 @@ void Container::_sort_children() {
|
|||
notification(NOTIFICATION_SORT_CHILDREN);
|
||||
emit_signal(SceneStringName(sort_children));
|
||||
pending_sort = false;
|
||||
layout_pending_finish();
|
||||
}
|
||||
|
||||
void Container::fit_child_in_rect(RequiredParam<Control> rp_child, const Rect2 &p_rect) {
|
||||
|
|
@ -140,6 +141,7 @@ void Container::queue_sort() {
|
|||
return;
|
||||
}
|
||||
|
||||
layout_pending_start();
|
||||
callable_mp(this, &Container::_sort_children).call_deferred();
|
||||
pending_sort = true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1752,6 +1752,55 @@ Size2 Control::get_custom_minimum_size() const {
|
|||
return data.custom_minimum_size;
|
||||
}
|
||||
|
||||
bool Control::is_layout_pending() const {
|
||||
ERR_MAIN_THREAD_GUARD_V(false);
|
||||
return data.layout_pending;
|
||||
}
|
||||
|
||||
bool Control::is_layout_pending_in_tree() const {
|
||||
ERR_MAIN_THREAD_GUARD_V(false);
|
||||
const Control *current_node = this;
|
||||
while (current_node != nullptr) {
|
||||
if (current_node->is_layout_pending()) {
|
||||
return true;
|
||||
}
|
||||
current_node = current_node->get_parent_control();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Control::layout_pending_start() {
|
||||
ERR_MAIN_THREAD_GUARD;
|
||||
data.layout_pending = true;
|
||||
}
|
||||
|
||||
void Control::layout_pending_finish() {
|
||||
ERR_MAIN_THREAD_GUARD;
|
||||
data.layout_pending = false;
|
||||
emit_signal(SNAME("_layout_pending_finished"));
|
||||
}
|
||||
|
||||
Control *Control::get_layout_pending_control_in_tree() const {
|
||||
Control *current_node = const_cast<Control *>(this);
|
||||
while (current_node != nullptr) {
|
||||
if (current_node->is_layout_pending()) {
|
||||
return current_node;
|
||||
}
|
||||
current_node = current_node->get_parent_control();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Control::call_on_all_layout_pending_finished(const Callable &p_callable) {
|
||||
Control *pending_control = get_layout_pending_control_in_tree();
|
||||
if (pending_control != nullptr) {
|
||||
Callable recheck = callable_mp(this, &Control::call_on_all_layout_pending_finished).bind(p_callable);
|
||||
pending_control->connect(SNAME("_layout_pending_finished"), recheck, CONNECT_ONE_SHOT | CONNECT_REFERENCE_COUNTED);
|
||||
} else {
|
||||
p_callable.call();
|
||||
}
|
||||
}
|
||||
|
||||
void Control::_update_minimum_size_cache() const {
|
||||
Size2 minsize = get_minimum_size();
|
||||
minsize = minsize.max(data.custom_minimum_size);
|
||||
|
|
@ -4059,6 +4108,7 @@ void Control::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("get_screen_position"), &Control::get_screen_position);
|
||||
ClassDB::bind_method(D_METHOD("get_rect"), &Control::get_rect);
|
||||
ClassDB::bind_method(D_METHOD("get_global_rect"), &Control::get_global_rect);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_focus_mode", "mode"), &Control::set_focus_mode);
|
||||
ClassDB::bind_method(D_METHOD("get_focus_mode"), &Control::get_focus_mode);
|
||||
ClassDB::bind_method(D_METHOD("get_focus_mode_with_override"), &Control::get_focus_mode_with_override);
|
||||
|
|
@ -4429,6 +4479,7 @@ void Control::_bind_methods() {
|
|||
BIND_ENUM_CONSTANT(TEXT_DIRECTION_RTL);
|
||||
|
||||
ADD_SIGNAL(MethodInfo("resized"));
|
||||
ADD_SIGNAL(MethodInfo("_layout_pending_finished"));
|
||||
ADD_SIGNAL(MethodInfo("gui_input", PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, InputEvent::get_class_static())));
|
||||
ADD_SIGNAL(MethodInfo("mouse_entered"));
|
||||
ADD_SIGNAL(MethodInfo("mouse_exited"));
|
||||
|
|
|
|||
|
|
@ -225,6 +225,8 @@ private:
|
|||
bool updating_last_minimum_size = false;
|
||||
bool block_minimum_size_adjust = false;
|
||||
|
||||
bool layout_pending = false;
|
||||
|
||||
bool size_warning = true;
|
||||
|
||||
// Container sizing.
|
||||
|
|
@ -554,6 +556,13 @@ public:
|
|||
void set_custom_minimum_size(const Size2 &p_custom);
|
||||
Size2 get_custom_minimum_size() const;
|
||||
|
||||
bool is_layout_pending() const;
|
||||
bool is_layout_pending_in_tree() const;
|
||||
void layout_pending_start();
|
||||
void layout_pending_finish();
|
||||
Control *get_layout_pending_control_in_tree() const;
|
||||
void call_on_all_layout_pending_finished(const Callable &p_callable);
|
||||
|
||||
// Container sizing.
|
||||
|
||||
void set_h_size_flags(BitField<SizeFlags> p_flags);
|
||||
|
|
|
|||
|
|
@ -271,7 +271,17 @@ void TabContainer::_on_theme_changed() {
|
|||
theme_changing = false;
|
||||
}
|
||||
|
||||
void TabContainer::_repaint_call_deferred() {
|
||||
layout_pending_start();
|
||||
callable_mp(this, &TabContainer::_repaint_internal).call_deferred();
|
||||
}
|
||||
|
||||
void TabContainer::_repaint() {
|
||||
layout_pending_start();
|
||||
_repaint_internal();
|
||||
}
|
||||
|
||||
void TabContainer::_repaint_internal() {
|
||||
Vector<Control *> controls = _get_tab_controls();
|
||||
int current = get_current_tab();
|
||||
|
||||
|
|
@ -315,6 +325,7 @@ void TabContainer::_repaint() {
|
|||
updating_visibility = false;
|
||||
|
||||
update_minimum_size();
|
||||
layout_pending_finish();
|
||||
}
|
||||
|
||||
void TabContainer::_update_margins() {
|
||||
|
|
@ -494,7 +505,7 @@ void TabContainer::_on_tab_hovered(int p_tab) {
|
|||
}
|
||||
|
||||
void TabContainer::_on_tab_changed(int p_tab) {
|
||||
callable_mp(this, &TabContainer::_repaint).call_deferred();
|
||||
_repaint_call_deferred();
|
||||
queue_redraw();
|
||||
queue_accessibility_update();
|
||||
|
||||
|
|
@ -503,7 +514,7 @@ void TabContainer::_on_tab_changed(int p_tab) {
|
|||
|
||||
void TabContainer::_on_tab_selected(int p_tab) {
|
||||
if (p_tab != get_previous_tab()) {
|
||||
callable_mp(this, &TabContainer::_repaint).call_deferred();
|
||||
_repaint_call_deferred();
|
||||
}
|
||||
|
||||
emit_signal(SNAME("tab_selected"), p_tab);
|
||||
|
|
@ -595,7 +606,7 @@ void TabContainer::add_child_notify(Node *p_child) {
|
|||
|
||||
// TabBar won't emit the "tab_changed" signal when not inside the tree.
|
||||
if (!is_inside_tree()) {
|
||||
callable_mp(this, &TabContainer::_repaint).call_deferred();
|
||||
_repaint_call_deferred();
|
||||
}
|
||||
notify_property_list_changed();
|
||||
}
|
||||
|
|
@ -657,7 +668,7 @@ void TabContainer::remove_child_notify(Node *p_child) {
|
|||
|
||||
// TabBar won't emit the "tab_changed" signal when not inside the tree.
|
||||
if (!is_inside_tree()) {
|
||||
callable_mp(this, &TabContainer::_repaint).call_deferred();
|
||||
_repaint_call_deferred();
|
||||
}
|
||||
notify_property_list_changed();
|
||||
}
|
||||
|
|
@ -774,7 +785,7 @@ void TabContainer::set_tabs_position(TabPosition p_tabs_position) {
|
|||
|
||||
tab_bar->set_tab_style_v_flip(tabs_position == POSITION_BOTTOM);
|
||||
|
||||
callable_mp(this, &TabContainer::_repaint).call_deferred();
|
||||
_repaint_call_deferred();
|
||||
queue_redraw();
|
||||
}
|
||||
|
||||
|
|
@ -806,7 +817,7 @@ void TabContainer::set_tabs_visible(bool p_visible) {
|
|||
tabs_visible = p_visible;
|
||||
tab_bar->set_visible(tabs_visible);
|
||||
|
||||
callable_mp(this, &TabContainer::_repaint).call_deferred();
|
||||
_repaint_call_deferred();
|
||||
queue_redraw();
|
||||
}
|
||||
|
||||
|
|
@ -947,7 +958,7 @@ void TabContainer::set_tab_hidden(int p_tab, bool p_hidden) {
|
|||
if (!get_clip_tabs()) {
|
||||
update_minimum_size();
|
||||
}
|
||||
callable_mp(this, &TabContainer::_repaint).call_deferred();
|
||||
_repaint_call_deferred();
|
||||
}
|
||||
|
||||
bool TabContainer::is_tab_hidden(int p_tab) const {
|
||||
|
|
|
|||
|
|
@ -127,7 +127,9 @@ private:
|
|||
Control *_as_tab_control(Node *p_child) const;
|
||||
Vector<Control *> _get_tab_controls() const;
|
||||
void _on_theme_changed();
|
||||
void _repaint_call_deferred();
|
||||
void _repaint();
|
||||
void _repaint_internal();
|
||||
void _refresh_tab_indices();
|
||||
void _refresh_tab_names();
|
||||
void _update_margins();
|
||||
|
|
|
|||
|
|
@ -839,7 +839,9 @@ void TextEdit::_notification(int p_what) {
|
|||
case NOTIFICATION_ENTER_TREE: {
|
||||
_update_caches();
|
||||
if (caret_pos_dirty) {
|
||||
callable_mp(this, &TextEdit::_emit_caret_changed).call_deferred();
|
||||
// No need to emit "caret_changed" signal (otherwise will save an unnecessary state to history),
|
||||
// so we use `_set_caret_pos_dirty()` instead of `_emit_caret_changed()`.
|
||||
callable_mp(this, &TextEdit::_set_caret_pos_dirty).call_deferred(false);
|
||||
}
|
||||
if (text_changed_dirty) {
|
||||
callable_mp(this, &TextEdit::_emit_text_changed).call_deferred();
|
||||
|
|
@ -6651,6 +6653,26 @@ int TextEdit::get_total_visible_line_count() const {
|
|||
}
|
||||
|
||||
// Auto adjust.
|
||||
bool TextEdit::is_line_in_viewport(int p_line) const {
|
||||
ERR_FAIL_INDEX_V(p_line, text.size(), 0);
|
||||
|
||||
int line_wrap = get_line_wrap_index_at_column(p_line, 0);
|
||||
|
||||
int first_vis_line = get_first_visible_line();
|
||||
int first_vis_wrap = first_visible_line_wrap_ofs;
|
||||
int last_vis_line = get_last_full_visible_line();
|
||||
int last_vis_wrap = get_last_full_visible_line_wrap_index();
|
||||
|
||||
if (p_line < first_vis_line || (p_line == first_vis_line && p_line < first_vis_wrap)) {
|
||||
// Caret is above screen.
|
||||
return false;
|
||||
} else if (p_line > last_vis_line || (p_line == last_vis_line && line_wrap > last_vis_wrap)) {
|
||||
// Caret is below screen.
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void TextEdit::adjust_viewport_to_caret(int p_caret) {
|
||||
ERR_FAIL_INDEX(p_caret, carets.size());
|
||||
|
||||
|
|
@ -7460,6 +7482,7 @@ void TextEdit::_bind_methods() {
|
|||
// Visible lines.
|
||||
ClassDB::bind_method(D_METHOD("set_line_as_first_visible", "line", "wrap_index"), &TextEdit::set_line_as_first_visible, DEFVAL(0));
|
||||
ClassDB::bind_method(D_METHOD("get_first_visible_line"), &TextEdit::get_first_visible_line);
|
||||
ClassDB::bind_method(D_METHOD("is_line_in_viewport", "line"), &TextEdit::is_line_in_viewport);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_line_as_center_visible", "line", "wrap_index"), &TextEdit::set_line_as_center_visible, DEFVAL(0));
|
||||
|
||||
|
|
@ -8243,6 +8266,10 @@ int TextEdit::_get_char_pos_for_line(int p_px, int p_line, int p_wrap_index) con
|
|||
}
|
||||
|
||||
/* Caret */
|
||||
void TextEdit::_set_caret_pos_dirty(bool p_dirty) {
|
||||
caret_pos_dirty = p_dirty;
|
||||
}
|
||||
|
||||
void TextEdit::_caret_changed(int p_caret) {
|
||||
queue_redraw();
|
||||
|
||||
|
|
|
|||
|
|
@ -457,6 +457,7 @@ private:
|
|||
|
||||
bool setting_caret_line = false;
|
||||
bool caret_pos_dirty = false;
|
||||
void _set_caret_pos_dirty(bool p_dirty);
|
||||
|
||||
int multicaret_edit_count = 0;
|
||||
bool multicaret_edit_merge_queued = false;
|
||||
|
|
@ -1093,6 +1094,7 @@ public:
|
|||
int get_total_visible_line_count() const;
|
||||
|
||||
// Auto Adjust
|
||||
bool is_line_in_viewport(int p_line) const;
|
||||
void adjust_viewport_to_caret(int p_caret = 0);
|
||||
void center_viewport_to_caret(int p_caret = 0);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue