You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-13 13:31:48 +00:00
Merge pull request #102514 from bruvzg/ts_wrp_indent
[TextEdit] Improve wrapped line indent handling.
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
double l_width = p_width[chunk];
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
for (int i = 0; i < l_size; i++) {
|
||||
double l_width = p_width[chunk];
|
||||
if (l_width > indent) {
|
||||
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;
|
||||
|
||||
Reference in New Issue
Block a user