Quellcode durchsuchen

[TextEdit] Update syntax highlighting when IME composition string is updated.

Pāvels Nadtočajevs vor 6 Monaten
Ursprung
Commit
7da0767f35

+ 7 - 0
doc/classes/TextEdit.xml

@@ -419,6 +419,13 @@
 				Returns the width in pixels of the [param wrap_index] on [param line].
 			</description>
 		</method>
+		<method name="get_line_with_ime" qualifiers="const">
+			<return type="String" />
+			<param index="0" name="line" type="int" />
+			<description>
+				Returns line text as it is currently displayed, including IME composition string.
+			</description>
+		</method>
 		<method name="get_line_wrap_count" qualifiers="const">
 			<return type="int" />
 			<param index="0" name="line" type="int" />

+ 1 - 1
modules/gdscript/editor/gdscript_highlighter.cpp

@@ -94,7 +94,7 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting_impl(int p_l
 		in_region = color_region_cache[p_line - 1];
 	}
 
-	const String &str = text_edit->get_line(p_line);
+	const String &str = text_edit->get_line_with_ime(p_line);
 	const int line_length = str.length();
 	Color prev_color;
 

+ 50 - 26
scene/gui/text_edit.cpp

@@ -186,7 +186,15 @@ _FORCE_INLINE_ String TextEdit::Text::operator[](int p_line) const {
 	return text[p_line].data;
 }
 
-void TextEdit::Text::invalidate_cache(int p_line, int p_column, bool p_text_changed, const String &p_ime_text, const Array &p_bidi_override) {
+_FORCE_INLINE_ const String &TextEdit::Text::get_text_with_ime(int p_line) const {
+	if (!text[p_line].ime_data.is_empty()) {
+		return text[p_line].ime_data;
+	} else {
+		return text[p_line].data;
+	}
+}
+
+void TextEdit::Text::invalidate_cache(int p_line, bool p_text_changed) {
 	ERR_FAIL_INDEX(p_line, text.size());
 
 	if (font.is_null()) {
@@ -209,20 +217,14 @@ void TextEdit::Text::invalidate_cache(int p_line, int p_column, bool p_text_chan
 	text_line.data_buf->set_preserve_control(draw_control_chars);
 	text_line.data_buf->set_custom_punctuation(get_enabled_word_separators());
 
-	if (p_ime_text.length() > 0) {
-		if (p_text_changed) {
-			text_line.data_buf->add_string(p_ime_text, font, font_size, language);
-		}
-		if (!p_bidi_override.is_empty()) {
-			TS->shaped_text_set_bidi_override(text_line.data_buf->get_rid(), p_bidi_override);
-		}
-	} else {
-		if (p_text_changed) {
-			text_line.data_buf->add_string(text_line.data, font, font_size, language);
-		}
-		if (!text_line.bidi_override.is_empty()) {
-			TS->shaped_text_set_bidi_override(text_line.data_buf->get_rid(), text_line.bidi_override);
-		}
+	const String &text_with_ime = (!text_line.ime_data.is_empty()) ? text_line.ime_data : text_line.data;
+	const Array &bidi_override_with_ime = (!text_line.ime_data.is_empty()) ? text_line.ime_bidi_override : text_line.bidi_override;
+
+	if (p_text_changed) {
+		text_line.data_buf->add_string(text_with_ime, font, font_size, language);
+	}
+	if (bidi_override_with_ime.is_empty()) {
+		TS->shaped_text_set_bidi_override(text_line.data_buf->get_rid(), bidi_override_with_ime);
 	}
 
 	if (!p_text_changed) {
@@ -286,7 +288,7 @@ void TextEdit::Text::invalidate_all_lines() {
 				text[i].data_buf->tab_align(tabs);
 			}
 		}
-		invalidate_cache(i, -1, false);
+		invalidate_cache(i, false);
 	}
 	tab_size_dirty = false;
 }
@@ -304,7 +306,7 @@ void TextEdit::Text::invalidate_font() {
 	}
 
 	for (int i = 0; i < text.size(); i++) {
-		invalidate_cache(i, -1, false);
+		invalidate_cache(i, false);
 	}
 	is_dirty = false;
 }
@@ -322,7 +324,7 @@ void TextEdit::Text::invalidate_all() {
 	}
 
 	for (int i = 0; i < text.size(); i++) {
-		invalidate_cache(i, -1, true);
+		invalidate_cache(i, true);
 	}
 	is_dirty = false;
 }
@@ -336,9 +338,8 @@ void TextEdit::Text::clear() {
 
 	Line line;
 	line.gutters.resize(gutter_count);
-	line.data = "";
 	text.insert(0, line);
-	invalidate_cache(0, -1, true);
+	invalidate_cache(0, true);
 }
 
 int TextEdit::Text::get_total_visible_line_count() const {
@@ -349,8 +350,18 @@ void TextEdit::Text::set(int p_line, const String &p_text, const Array &p_bidi_o
 	ERR_FAIL_INDEX(p_line, text.size());
 
 	text.write[p_line].data = p_text;
+	text.write[p_line].ime_data = String();
 	text.write[p_line].bidi_override = p_bidi_override;
-	invalidate_cache(p_line, -1, true);
+	text.write[p_line].ime_bidi_override.clear();
+	invalidate_cache(p_line, true);
+}
+
+void TextEdit::Text::set_ime(int p_line, const String &p_text, const Array &p_bidi_override) {
+	ERR_FAIL_INDEX(p_line, text.size());
+
+	text.write[p_line].ime_data = p_text;
+	text.write[p_line].ime_bidi_override = p_bidi_override;
+	invalidate_cache(p_line, true);
 }
 
 void TextEdit::Text::set_hidden(int p_line, bool p_hidden) {
@@ -405,7 +416,7 @@ void TextEdit::Text::insert(int p_at, const Vector<String> &p_text, const Vector
 		line.data = p_text[i];
 		line.bidi_override = p_bidi_override[i];
 		text.write[p_at + i] = line;
-		invalidate_cache(p_at + i, -1, true);
+		invalidate_cache(p_at + i, true);
 	}
 }
 
@@ -2967,15 +2978,20 @@ void TextEdit::_update_ime_text() {
 	if (has_ime_text()) {
 		// Update text to visually include IME text.
 		for (int i = 0; i < get_caret_count(); i++) {
-			String text_with_ime = text[get_caret_line(i)].substr(0, get_caret_column(i)) + ime_text + text[get_caret_line(i)].substr(get_caret_column(i), text[get_caret_line(i)].length());
-			text.invalidate_cache(get_caret_line(i), get_caret_column(i), true, text_with_ime, structured_text_parser(st_parser, st_args, text_with_ime));
+			int l = get_caret_line(i);
+			String text_with_ime = text[l].substr(0, get_caret_column(i)) + ime_text + text[l].substr(get_caret_column(i));
+			text.set_ime(l, text_with_ime, structured_text_parser(st_parser, st_args, text_with_ime));
+			emit_signal(SNAME("lines_edited_from"), l, l);
 		}
 	} else {
 		// Reset text.
 		for (int i = 0; i < get_caret_count(); i++) {
-			text.invalidate_cache(get_caret_line(i), get_caret_column(i), true);
+			int l = get_caret_line(i);
+			text.set_ime(l, String(), Array());
+			emit_signal(SNAME("lines_edited_from"), l, l);
 		}
 	}
+	_clear_syntax_highlighting_cache();
 	queue_redraw();
 }
 
@@ -3513,11 +3529,18 @@ void TextEdit::set_line(int p_line, const String &p_new_text) {
 
 String TextEdit::get_line(int p_line) const {
 	if (p_line < 0 || p_line >= text.size()) {
-		return "";
+		return String();
 	}
 	return text[p_line];
 }
 
+String TextEdit::get_line_with_ime(int p_line) const {
+	if (p_line < 0 || p_line >= text.size()) {
+		return String();
+	}
+	return text.get_text_with_ime(p_line);
+}
+
 int TextEdit::get_line_width(int p_line, int p_wrap_index) const {
 	ERR_FAIL_INDEX_V(p_line, text.size(), 0);
 	ERR_FAIL_COND_V(p_wrap_index > get_line_wrap_count(p_line), 0);
@@ -6540,6 +6563,7 @@ void TextEdit::_bind_methods() {
 
 	ClassDB::bind_method(D_METHOD("set_line", "line", "new_text"), &TextEdit::set_line);
 	ClassDB::bind_method(D_METHOD("get_line", "line"), &TextEdit::get_line);
+	ClassDB::bind_method(D_METHOD("get_line_with_ime", "line"), &TextEdit::get_line_with_ime);
 
 	ClassDB::bind_method(D_METHOD("get_line_width", "line", "wrap_index"), &TextEdit::get_line_width, DEFVAL(-1));
 	ClassDB::bind_method(D_METHOD("get_line_height"), &TextEdit::get_line_height);

+ 7 - 1
scene/gui/text_edit.h

@@ -152,6 +152,9 @@ private:
 			Array bidi_override;
 			Ref<TextParagraph> data_buf;
 
+			String ime_data;
+			Array ime_bidi_override;
+
 			Color background_color = Color(0, 0, 0, 0);
 			bool hidden = false;
 			int line_count = 0;
@@ -228,6 +231,7 @@ private:
 		const Ref<TextParagraph> get_line_data(int p_line) const;
 
 		void set(int p_line, const String &p_text, const Array &p_bidi_override);
+		void set_ime(int p_line, const String &p_text, const Array &p_bidi_override);
 		void set_hidden(int p_line, bool p_hidden);
 		bool is_hidden(int p_line) const;
 		void insert(int p_at, const Vector<String> &p_text, const Vector<Array> &p_bidi_override);
@@ -235,12 +239,13 @@ private:
 		int size() const { return text.size(); }
 		void clear();
 
-		void invalidate_cache(int p_line, int p_column = -1, bool p_text_changed = false, const String &p_ime_text = String(), const Array &p_bidi_override = Array());
+		void invalidate_cache(int p_line, bool p_text_changed = false);
 		void invalidate_font();
 		void invalidate_all();
 		void invalidate_all_lines();
 
 		_FORCE_INLINE_ String operator[](int p_line) const;
+		_FORCE_INLINE_ const String &get_text_with_ime(int p_line) const;
 
 		/* Gutters. */
 		void add_gutter(int p_at);
@@ -794,6 +799,7 @@ public:
 
 	void set_line(int p_line, const String &p_new_text);
 	String get_line(int p_line) const;
+	String get_line_with_ime(int p_line) const;
 
 	int get_line_width(int p_line, int p_wrap_index = -1) const;
 	int get_line_height() const;

+ 1 - 1
scene/resources/syntax_highlighter.cpp

@@ -144,7 +144,7 @@ Dictionary CodeHighlighter::_get_line_syntax_highlighting_impl(int p_line) {
 		in_region = color_region_cache[p_line - 1];
 	}
 
-	const String &str = text_edit->get_line(p_line);
+	const String &str = text_edit->get_line_with_ime(p_line);
 	const int line_length = str.length();
 	Color prev_color;