Explorar el Código

Adds `get_selection_line_offset` to `RichTextLabel`

This new method allow you to get the line offset of the current
selection (returns -1 if nothing is selected.)

This is useful if you want to pop up a control or menu above the
currently selected text. Previously there was no accurate way to get
this information.

The logic is moved from the implementation of `scroll_to_selection`
verbatim, and that method has been adjusted to avoid repetition.
Robin Ward hace 10 meses
padre
commit
b3e970dde8
Se han modificado 3 ficheros con 36 adiciones y 19 borrados
  1. 6 0
      doc/classes/RichTextLabel.xml
  2. 29 19
      scene/gui/rich_text_label.cpp
  3. 1 0
      scene/gui/rich_text_label.h

+ 6 - 0
doc/classes/RichTextLabel.xml

@@ -190,6 +190,12 @@
 				Returns the current selection first character index if a selection is active, [code]-1[/code] otherwise. Does not include BBCodes.
 			</description>
 		</method>
+		<method name="get_selection_line_offset" qualifiers="const">
+			<return type="float" />
+			<description>
+				Returns the current selection vertical line offset if a selection is active, [code]-1.0[/code] otherwise.
+			</description>
+		</method>
 		<method name="get_selection_to" qualifiers="const">
 			<return type="int" />
 			<description>

+ 29 - 19
scene/gui/rich_text_label.cpp

@@ -5449,25 +5449,8 @@ void RichTextLabel::append_text(const String &p_bbcode) {
 }
 
 void RichTextLabel::scroll_to_selection() {
-	if (selection.active && selection.from_frame && selection.from_line >= 0 && selection.from_line < (int)selection.from_frame->lines.size()) {
-		// Selected frame paragraph offset.
-		float line_offset = selection.from_frame->lines[selection.from_line].offset.y;
-
-		// Add wrapped line offset.
-		for (int i = 0; i < selection.from_frame->lines[selection.from_line].text_buf->get_line_count(); i++) {
-			Vector2i range = selection.from_frame->lines[selection.from_line].text_buf->get_line_range(i);
-			if (range.x <= selection.from_char && range.y >= selection.from_char) {
-				break;
-			}
-			line_offset += selection.from_frame->lines[selection.from_line].text_buf->get_line_ascent(i) + selection.from_frame->lines[selection.from_line].text_buf->get_line_descent(i) + theme_cache.line_separation;
-		}
-
-		// Add nested frame (e.g. table cell) offset.
-		ItemFrame *it = selection.from_frame;
-		while (it->parent_frame != nullptr) {
-			line_offset += it->parent_frame->lines[it->line].offset.y;
-			it = it->parent_frame;
-		}
+	float line_offset = get_selection_line_offset();
+	if (line_offset != -1.0) {
 		vscroll->set_value(line_offset);
 	}
 }
@@ -5978,6 +5961,32 @@ int RichTextLabel::get_selection_to() const {
 	return selection.to_frame->lines[selection.to_line].char_offset + selection.to_char - 1;
 }
 
+float RichTextLabel::get_selection_line_offset() const {
+	if (selection.active && selection.from_frame && selection.from_line >= 0 && selection.from_line < (int)selection.from_frame->lines.size()) {
+		// Selected frame paragraph offset.
+		float line_offset = selection.from_frame->lines[selection.from_line].offset.y;
+
+		// Add wrapped line offset.
+		for (int i = 0; i < selection.from_frame->lines[selection.from_line].text_buf->get_line_count(); i++) {
+			Vector2i range = selection.from_frame->lines[selection.from_line].text_buf->get_line_range(i);
+			if (range.x <= selection.from_char && range.y >= selection.from_char) {
+				break;
+			}
+			line_offset += selection.from_frame->lines[selection.from_line].text_buf->get_line_ascent(i) + selection.from_frame->lines[selection.from_line].text_buf->get_line_descent(i) + theme_cache.line_separation;
+		}
+
+		// Add nested frame (e.g. table cell) offset.
+		ItemFrame *it = selection.from_frame;
+		while (it->parent_frame != nullptr) {
+			line_offset += it->parent_frame->lines[it->line].offset.y;
+			it = it->parent_frame;
+		}
+		return line_offset;
+	}
+
+	return -1.0;
+}
+
 void RichTextLabel::set_text(const String &p_bbcode) {
 	// Allow clearing the tag stack.
 	if (!p_bbcode.is_empty() && text == p_bbcode) {
@@ -6412,6 +6421,7 @@ void RichTextLabel::_bind_methods() {
 
 	ClassDB::bind_method(D_METHOD("get_selection_from"), &RichTextLabel::get_selection_from);
 	ClassDB::bind_method(D_METHOD("get_selection_to"), &RichTextLabel::get_selection_to);
+	ClassDB::bind_method(D_METHOD("get_selection_line_offset"), &RichTextLabel::get_selection_line_offset);
 
 	ClassDB::bind_method(D_METHOD("select_all"), &RichTextLabel::select_all);
 	ClassDB::bind_method(D_METHOD("get_selected_text"), &RichTextLabel::get_selected_text);

+ 1 - 0
scene/gui/rich_text_label.h

@@ -787,6 +787,7 @@ public:
 	bool is_selection_enabled() const;
 	int get_selection_from() const;
 	int get_selection_to() const;
+	float get_selection_line_offset() const;
 	String get_selected_text() const;
 	void select_all();
 	void selection_copy();