diff --git a/doc/classes/ScrollContainer.xml b/doc/classes/ScrollContainer.xml index f543c50334c..eadc41f3aa2 100644 --- a/doc/classes/ScrollContainer.xml +++ b/doc/classes/ScrollContainer.xml @@ -9,6 +9,15 @@ + + + + + + + Ensures the given [code]control[/code] is visible (must be a direct or indirect child of the ScrollContainer). Used by [member follow_focus]. + + diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp index 176cb1703f2..7a7050e2d35 100644 --- a/editor/project_manager.cpp +++ b/editor/project_manager.cpp @@ -1442,16 +1442,7 @@ Vector ProjectList::get_selected_projects() const { void ProjectList::ensure_project_visible(int p_index) { const Item &item = _projects[p_index]; - - int item_top = item.control->get_position().y; - int item_bottom = item.control->get_position().y + item.control->get_size().y; - - if (item_top < get_v_scroll()) { - set_v_scroll(item_top); - - } else if (item_bottom > get_v_scroll() + get_size().y) { - set_v_scroll(item_bottom - get_size().y); - } + ensure_control_visible(item.control); } int ProjectList::get_single_selected_index() const { diff --git a/scene/gui/scroll_container.cpp b/scene/gui/scroll_container.cpp index 5b414f48000..bdee066d579 100644 --- a/scene/gui/scroll_container.cpp +++ b/scene/gui/scroll_container.cpp @@ -230,28 +230,25 @@ void ScrollContainer::_update_scrollbar_position() { v_scroll->raise(); } -void ScrollContainer::_ensure_focused_visible(Control *p_control) { - if (!follow_focus) { - return; +void ScrollContainer::_gui_focus_changed(Control *p_control) { + if (follow_focus && is_a_parent_of(p_control)) { + ensure_control_visible(p_control); } +} - if (is_a_parent_of(p_control)) { - Rect2 global_rect = get_global_rect(); - Rect2 other_rect = p_control->get_global_rect(); - float right_margin = 0; - if (v_scroll->is_visible()) { - right_margin += v_scroll->get_size().x; - } - float bottom_margin = 0; - if (h_scroll->is_visible()) { - bottom_margin += h_scroll->get_size().y; - } +void ScrollContainer::ensure_control_visible(Control *p_control) { + ERR_FAIL_COND_MSG(!is_a_parent_of(p_control), "Must be a parent of the control."); - float diff = MAX(MIN(other_rect.position.y, global_rect.position.y), other_rect.position.y + other_rect.size.y - global_rect.size.y + bottom_margin); - set_v_scroll(get_v_scroll() + (diff - global_rect.position.y)); - diff = MAX(MIN(other_rect.position.x, global_rect.position.x), other_rect.position.x + other_rect.size.x - global_rect.size.x + right_margin); - set_h_scroll(get_h_scroll() + (diff - global_rect.position.x)); - } + Rect2 global_rect = get_global_rect(); + Rect2 other_rect = p_control->get_global_rect(); + float right_margin = v_scroll->is_visible() ? v_scroll->get_size().x : 0.0f; + float bottom_margin = h_scroll->is_visible() ? h_scroll->get_size().y : 0.0f; + + Vector2 diff = Vector2(MAX(MIN(other_rect.position.x, global_rect.position.x), other_rect.position.x + other_rect.size.x - global_rect.size.x + right_margin), + MAX(MIN(other_rect.position.y, global_rect.position.y), other_rect.position.y + other_rect.size.y - global_rect.size.y + bottom_margin)); + + set_h_scroll(get_h_scroll() + (diff.x - global_rect.position.x)); + set_v_scroll(get_v_scroll() + (diff.y - global_rect.position.y)); } void ScrollContainer::_notification(int p_what) { @@ -260,7 +257,7 @@ void ScrollContainer::_notification(int p_what) { }; if (p_what == NOTIFICATION_READY) { - get_viewport()->connect("gui_focus_changed", this, "_ensure_focused_visible"); + get_viewport()->connect("gui_focus_changed", this, "_gui_focus_changed"); } if (p_what == NOTIFICATION_SORT_CHILDREN) { @@ -560,12 +557,12 @@ VScrollBar *ScrollContainer::get_v_scrollbar() { void ScrollContainer::_bind_methods() { ClassDB::bind_method(D_METHOD("_scroll_moved"), &ScrollContainer::_scroll_moved); ClassDB::bind_method(D_METHOD("_gui_input"), &ScrollContainer::_gui_input); + ClassDB::bind_method(D_METHOD("_gui_focus_changed"), &ScrollContainer::_gui_focus_changed); ClassDB::bind_method(D_METHOD("set_enable_h_scroll", "enable"), &ScrollContainer::set_enable_h_scroll); ClassDB::bind_method(D_METHOD("is_h_scroll_enabled"), &ScrollContainer::is_h_scroll_enabled); ClassDB::bind_method(D_METHOD("set_enable_v_scroll", "enable"), &ScrollContainer::set_enable_v_scroll); ClassDB::bind_method(D_METHOD("is_v_scroll_enabled"), &ScrollContainer::is_v_scroll_enabled); ClassDB::bind_method(D_METHOD("_update_scrollbar_position"), &ScrollContainer::_update_scrollbar_position); - ClassDB::bind_method(D_METHOD("_ensure_focused_visible"), &ScrollContainer::_ensure_focused_visible); ClassDB::bind_method(D_METHOD("set_h_scroll", "value"), &ScrollContainer::set_h_scroll); ClassDB::bind_method(D_METHOD("get_h_scroll"), &ScrollContainer::get_h_scroll); ClassDB::bind_method(D_METHOD("set_v_scroll", "value"), &ScrollContainer::set_v_scroll); @@ -577,6 +574,7 @@ void ScrollContainer::_bind_methods() { ClassDB::bind_method(D_METHOD("get_h_scrollbar"), &ScrollContainer::get_h_scrollbar); ClassDB::bind_method(D_METHOD("get_v_scrollbar"), &ScrollContainer::get_v_scrollbar); + ClassDB::bind_method(D_METHOD("ensure_control_visible", "control"), &ScrollContainer::ensure_control_visible); ADD_SIGNAL(MethodInfo("scroll_started")); ADD_SIGNAL(MethodInfo("scroll_ended")); diff --git a/scene/gui/scroll_container.h b/scene/gui/scroll_container.h index 315a04b7394..0eb6f08652a 100644 --- a/scene/gui/scroll_container.h +++ b/scene/gui/scroll_container.h @@ -69,13 +69,13 @@ protected: Size2 get_minimum_size() const; void _gui_input(const Ref &p_gui_input); + void _gui_focus_changed(Control *p_control); void _notification(int p_what); void _scroll_moved(float); static void _bind_methods(); void _update_scrollbar_position(); - void _ensure_focused_visible(Control *p_node); public: int get_v_scroll() const; @@ -98,6 +98,7 @@ public: HScrollBar *get_h_scrollbar(); VScrollBar *get_v_scrollbar(); + void ensure_control_visible(Control *p_control); virtual bool clips_input() const;