浏览代码

Merge pull request #48770 from LightningAA/scrollcontainer-ensure-item-visible-4.0

ScrollContainer: Expose `_ensure_focused_visible` to the scripting API and rename it to `ensure_control_visible`
Rémi Verschelde 4 年之前
父节点
当前提交
4c1d555b9a
共有 4 个文件被更改,包括 30 次插入35 次删除
  1. 9 0
      doc/classes/ScrollContainer.xml
  2. 1 10
      editor/project_manager.cpp
  3. 18 24
      scene/gui/scroll_container.cpp
  4. 2 1
      scene/gui/scroll_container.h

+ 9 - 0
doc/classes/ScrollContainer.xml

@@ -11,6 +11,15 @@
 	<tutorials>
 	</tutorials>
 	<methods>
+		<method name="ensure_control_visible">
+			<return type="void">
+			</return>
+			<argument index="0" name="control" type="Control">
+			</argument>
+			<description>
+				Ensures the given [code]control[/code] is visible (must be a direct or indirect child of the ScrollContainer). Used by [member follow_focus].
+			</description>
+		</method>
 		<method name="get_h_scrollbar">
 			<return type="HScrollBar">
 			</return>

+ 1 - 10
editor/project_manager.cpp

@@ -1484,16 +1484,7 @@ Vector<ProjectList::Item> 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 {

+ 18 - 24
scene/gui/scroll_container.cpp

@@ -238,32 +238,25 @@ void ScrollContainer::_update_scrollbar_position() {
 	_updating_scrollbars = false;
 }
 
-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.0;
-		if (v_scroll->is_visible()) {
-			right_margin += v_scroll->get_size().x;
-		}
-		float bottom_margin = 0.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));
-		if (is_layout_rtl()) {
-			diff = MAX(MIN(other_rect.position.x, global_rect.position.x), other_rect.position.x + other_rect.size.x - global_rect.size.x);
-		} else {
-			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 + (!is_layout_rtl() ? right_margin : 0.0f)),
+			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::_update_dimensions() {
@@ -334,7 +327,7 @@ void ScrollContainer::_notification(int p_what) {
 	};
 
 	if (p_what == NOTIFICATION_READY) {
-		get_viewport()->connect("gui_focus_changed", callable_mp(this, &ScrollContainer::_ensure_focused_visible));
+		get_viewport()->connect("gui_focus_changed", callable_mp(this, &ScrollContainer::_gui_focus_changed));
 		_update_dimensions();
 	}
 
@@ -608,6 +601,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"));

+ 2 - 1
scene/gui/scroll_container.h

@@ -69,6 +69,7 @@ protected:
 	Size2 get_minimum_size() const override;
 
 	void _gui_input(const Ref<InputEvent> &p_gui_input);
+	void _gui_focus_changed(Control *p_control);
 	void _update_dimensions();
 	void _notification(int p_what);
 
@@ -77,7 +78,6 @@ protected:
 
 	bool _updating_scrollbars = false;
 	void _update_scrollbar_position();
-	void _ensure_focused_visible(Control *p_node);
 
 public:
 	void set_h_scroll(int p_pos);
@@ -106,6 +106,7 @@ public:
 
 	HScrollBar *get_h_scrollbar();
 	VScrollBar *get_v_scrollbar();
+	void ensure_control_visible(Control *p_control);
 
 	virtual bool clips_input() const override;