Browse Source

Merge pull request #100329 from eviltrout/add-custom-line-offset

Add `get_selection_line_offset` to `RichTextLabel`
Rémi Verschelde 9 months ago
parent
commit
c1f65b429d
3 changed files with 36 additions and 19 deletions
  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

@@ -199,6 +199,12 @@
 				Returns the current selection first character index if a selection is active, [code]-1[/code] otherwise. Does not include BBCodes.
 				Returns the current selection first character index if a selection is active, [code]-1[/code] otherwise. Does not include BBCodes.
 			</description>
 			</description>
 		</method>
 		</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">
 		<method name="get_selection_to" qualifiers="const">
 			<return type="int" />
 			<return type="int" />
 			<description>
 			<description>

+ 29 - 19
scene/gui/rich_text_label.cpp

@@ -5459,25 +5459,8 @@ void RichTextLabel::append_text(const String &p_bbcode) {
 }
 }
 
 
 void RichTextLabel::scroll_to_selection() {
 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);
 		vscroll->set_value(line_offset);
 	}
 	}
 }
 }
@@ -6013,6 +5996,32 @@ int RichTextLabel::get_selection_to() const {
 	return selection.to_frame->lines[selection.to_line].char_offset + selection.to_char - 1;
 	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) {
 void RichTextLabel::set_text(const String &p_bbcode) {
 	// Allow clearing the tag stack.
 	// Allow clearing the tag stack.
 	if (!p_bbcode.is_empty() && text == p_bbcode) {
 	if (!p_bbcode.is_empty() && text == p_bbcode) {
@@ -6447,6 +6456,7 @@ void RichTextLabel::_bind_methods() {
 
 
 	ClassDB::bind_method(D_METHOD("get_selection_from"), &RichTextLabel::get_selection_from);
 	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_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("select_all"), &RichTextLabel::select_all);
 	ClassDB::bind_method(D_METHOD("get_selected_text"), &RichTextLabel::get_selected_text);
 	ClassDB::bind_method(D_METHOD("get_selected_text"), &RichTextLabel::get_selected_text);

+ 1 - 0
scene/gui/rich_text_label.h

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