1
0
mirror of https://github.com/godotengine/godot.git synced 2025-11-14 13:41:12 +00:00

Merge pull request #102514 from bruvzg/ts_wrp_indent

[TextEdit] Improve wrapped line indent handling.
This commit is contained in:
Thaddeus Crews
2025-03-05 12:07:52 -06:00
3 changed files with 94 additions and 19 deletions

View File

@@ -895,6 +895,12 @@ void TextEdit::_notification(int p_what) {
int line_wrap_amount = get_line_wrap_count(minimap_line);
int last_wrap_column = 0;
int first_indent_line = 0;
float wrap_indent_line = 0.0;
if (text.is_indent_wrapped_lines()) {
wrap_indent_line = _get_wrapped_indent_level(minimap_line, first_indent_line);
wrap_indent_line = MIN(wrap_indent_line, (minimap_width / minimap_char_size.x) * 0.6);
}
for (int line_wrap_index = 0; line_wrap_index < line_wrap_amount + 1; line_wrap_index++) {
if (line_wrap_index != 0) {
i++;
@@ -904,7 +910,7 @@ void TextEdit::_notification(int p_what) {
}
const String &str = wrap_rows[line_wrap_index];
int indent_px = line_wrap_index != 0 ? get_indent_level(minimap_line) : 0;
int indent_px = line_wrap_index > first_indent_line ? wrap_indent_line : 0.0;
if (indent_px >= wrap_at_column) {
indent_px = 0;
}
@@ -1052,6 +1058,12 @@ void TextEdit::_notification(int p_what) {
const Vector<String> wrap_rows = draw_placeholder ? placeholder_wrapped_rows : get_line_wrapped_text(line);
int line_wrap_amount = draw_placeholder ? placeholder_wrapped_rows.size() - 1 : get_line_wrap_count(line);
int first_indent_line = 0;
float wrap_indent_line = 0.0;
if (text.is_indent_wrapped_lines()) {
wrap_indent_line = _get_wrapped_indent_level(line, first_indent_line) * theme_cache.font->get_char_size(' ', theme_cache.font_size).width;
wrap_indent_line = MIN(wrap_indent_line, wrap_at_column * 0.6);
}
for (int line_wrap_index = 0; line_wrap_index <= line_wrap_amount; line_wrap_index++) {
if (line_wrap_index != 0) {
i++;
@@ -1183,7 +1195,7 @@ void TextEdit::_notification(int p_what) {
// Draw line.
RID rid = ldata->get_line_rid(line_wrap_index);
float text_height = TS->shaped_text_get_size(rid).y;
float wrap_indent = (text.is_indent_wrapped_lines() && line_wrap_index > 0) ? get_indent_level(line) * theme_cache.font->get_char_size(' ', theme_cache.font_size).width : 0.0;
float wrap_indent = line_wrap_index > first_indent_line ? wrap_indent_line : 0.0;
if (rtl) {
char_margin = size.width - char_margin - (TS->shaped_text_get_size(rid).x + wrap_indent);
@@ -3565,6 +3577,32 @@ int TextEdit::get_line_height() const {
return MAX(text.get_line_height() + theme_cache.line_spacing, 1);
}
int TextEdit::_get_wrapped_indent_level(int p_line, int &r_first_wrap) const {
ERR_FAIL_INDEX_V(p_line, text.size(), 0);
const Vector<Vector2i> wr = text.get_line_wrap_ranges(p_line);
r_first_wrap = 0;
int tab_count = 0;
int whitespace_count = 0;
int line_length = text[p_line].size();
for (int i = 0; i < line_length - 1; i++) {
if (r_first_wrap < wr.size() && i >= wr[r_first_wrap].y) {
tab_count = 0;
whitespace_count = 0;
r_first_wrap++;
}
if (text[p_line][i] == '\t') {
tab_count++;
} else if (text[p_line][i] == ' ') {
whitespace_count++;
} else {
break;
}
}
return tab_count * text.get_tab_size() + whitespace_count;
}
int TextEdit::get_indent_level(int p_line) const {
ERR_FAIL_INDEX_V(p_line, text.size(), 0);
@@ -4488,7 +4526,13 @@ Point2i TextEdit::get_line_column_at_pos(const Point2i &p_pos, bool p_clamp_line
}
RID text_rid = text.get_line_data(row)->get_line_rid(wrap_index);
float wrap_indent = (text.is_indent_wrapped_lines() && wrap_index > 0) ? get_indent_level(row) * theme_cache.font->get_char_size(' ', theme_cache.font_size).width : 0.0;
int first_indent_line = 0;
float wrap_indent_line = 0.0;
if (text.is_indent_wrapped_lines()) {
wrap_indent_line = _get_wrapped_indent_level(row, first_indent_line) * theme_cache.font->get_char_size(' ', theme_cache.font_size).width;
wrap_indent_line = MIN(wrap_indent_line, wrap_at_column * 0.6);
}
float wrap_indent = wrap_index > first_indent_line ? wrap_indent_line : 0.0;
if (is_layout_rtl()) {
colx = TS->shaped_text_get_size(text_rid).x - colx + wrap_indent;
} else {
@@ -7590,7 +7634,13 @@ int TextEdit::_get_char_pos_for_line(int p_px, int p_line, int p_wrap_index) con
p_wrap_index = MIN(p_wrap_index, text.get_line_data(p_line)->get_line_count() - 1);
RID text_rid = text.get_line_data(p_line)->get_line_rid(p_wrap_index);
float wrap_indent = (text.is_indent_wrapped_lines() && p_wrap_index > 0) ? get_indent_level(p_line) * theme_cache.font->get_char_size(' ', theme_cache.font_size).width : 0.0;
int first_indent_line = 0;
float wrap_indent_line = 0.0;
if (text.is_indent_wrapped_lines()) {
wrap_indent_line = _get_wrapped_indent_level(p_line, first_indent_line) * theme_cache.font->get_char_size(' ', theme_cache.font_size).width;
wrap_indent_line = MIN(wrap_indent_line, wrap_at_column * 0.6);
}
float wrap_indent = p_wrap_index > first_indent_line ? wrap_indent_line : 0.0;
if (is_layout_rtl()) {
p_px = TS->shaped_text_get_size(text_rid).x - p_px + wrap_indent;
} else {
@@ -7659,7 +7709,13 @@ int TextEdit::_get_column_x_offset_for_line(int p_char, int p_line, int p_column
}
RID text_rid = text.get_line_data(p_line)->get_line_rid(row);
float wrap_indent = (text.is_indent_wrapped_lines() && row > 0) ? get_indent_level(p_line) * theme_cache.font->get_char_size(' ', theme_cache.font_size).width : 0.0;
int first_indent_line = 0;
float wrap_indent_line = 0.0;
if (text.is_indent_wrapped_lines()) {
wrap_indent_line = _get_wrapped_indent_level(p_line, first_indent_line) * theme_cache.font->get_char_size(' ', theme_cache.font_size).width;
wrap_indent_line = MIN(wrap_indent_line, wrap_at_column * 0.6);
}
float wrap_indent = row > first_indent_line ? wrap_indent_line : 0.0;
CaretInfo ts_caret = TS->shaped_text_get_carets(text_rid, p_column);
if ((ts_caret.l_caret != Rect2() && (ts_caret.l_dir == TextServer::DIRECTION_AUTO || ts_caret.l_dir == (TextServer::Direction)input_direction)) || (ts_caret.t_caret == Rect2())) {
return ts_caret.l_caret.position.x + (is_layout_rtl() ? -wrap_indent : wrap_indent);

View File

@@ -695,6 +695,8 @@ protected:
void _unhide_all_lines();
virtual void _unhide_carets();
int _get_wrapped_indent_level(int p_line, int &r_first_wrap) const;
// Symbol lookup.
String lookup_symbol_word;
void _set_symbol_lookup_word(const String &p_symbol);

View File

@@ -803,25 +803,36 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks_adv(const RID &p_shaped
int last_safe_break = -1;
int word_count = 0;
int chunk = 0;
int prev_chunk = -1;
bool trim_next = false;
int l_size = shaped_text_get_glyph_count(p_shaped);
const Glyph *l_gl = const_cast<TextServer *>(this)->shaped_text_sort_logical(p_shaped);
int indent_end = 0;
double indent = 0.0;
if (p_break_flags.has_flag(BREAK_TRIM_INDENT)) {
for (int i = 0; i < l_size; i++) {
if ((l_gl[i].flags & GRAPHEME_IS_TAB) == GRAPHEME_IS_TAB || (l_gl[i].flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE) {
indent += l_gl[i].advance * l_gl[i].repeat;
} else {
break;
}
}
}
for (int i = 0; i < l_size; i++) {
double l_width = p_width[chunk];
if (l_width > indent) {
if (p_break_flags.has_flag(BREAK_TRIM_INDENT) && chunk != prev_chunk) {
indent = 0.0;
for (int j = indent_end; j < l_size; j++) {
if ((l_gl[j].flags & GRAPHEME_IS_TAB) == GRAPHEME_IS_TAB || (l_gl[j].flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE) {
if (indent + l_gl[j].advance * l_gl[j].repeat > l_width) {
indent = 0.0;
}
indent += l_gl[j].advance * l_gl[j].repeat;
indent_end = l_gl[j].end;
} else {
break;
}
}
indent = MIN(indent, 0.6 * l_width);
prev_chunk = chunk;
}
if (l_width > indent && i > indent_end) {
l_width -= indent;
}
if (l_gl[i].start < p_start) {
@@ -982,15 +993,21 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks(const RID &p_shaped, do
int l_size = shaped_text_get_glyph_count(p_shaped);
const Glyph *l_gl = const_cast<TextServer *>(this)->shaped_text_sort_logical(p_shaped);
int indent_end = 0;
double indent = 0.0;
if (p_break_flags.has_flag(BREAK_TRIM_INDENT)) {
for (int i = 0; i < l_size; i++) {
if ((l_gl[i].flags & GRAPHEME_IS_TAB) == GRAPHEME_IS_TAB || (l_gl[i].flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE) {
if (indent + l_gl[i].advance * l_gl[i].repeat > p_width) {
indent = 0.0;
}
indent += l_gl[i].advance * l_gl[i].repeat;
indent_end = l_gl[i].end;
} else {
break;
}
}
indent = MIN(indent, 0.6 * p_width);
}
double l_width = p_width;
@@ -1018,7 +1035,7 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks(const RID &p_shaped, do
if (last_end <= l_gl[start_pos].start) {
lines.push_back(l_gl[start_pos].start);
lines.push_back(l_gl[end_pos].end);
if (p_width > indent) {
if (p_width > indent && i > indent_end) {
l_width = p_width - indent;
}
cur_safe_brk = last_safe_break;
@@ -1029,7 +1046,7 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks(const RID &p_shaped, do
if (last_end <= line_start) {
lines.push_back(line_start);
lines.push_back(l_gl[last_safe_break].end);
if (p_width > indent) {
if (p_width > indent && i > indent_end) {
l_width = p_width - indent;
}
last_end = l_gl[last_safe_break].end;
@@ -1062,7 +1079,7 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks(const RID &p_shaped, do
if (last_end <= l_gl[start_pos].start) {
lines.push_back(l_gl[start_pos].start);
lines.push_back(l_gl[end_pos].end);
if (p_width > indent) {
if (p_width > indent && i > indent_end) {
l_width = p_width - indent;
}
last_end = l_gl[i].end;
@@ -1072,7 +1089,7 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks(const RID &p_shaped, do
if (last_end <= line_start) {
lines.push_back(line_start);
lines.push_back(l_gl[i].end);
if (p_width > indent) {
if (p_width > indent && i > indent_end) {
l_width = p_width - indent;
}
last_end = l_gl[i].end;