From fc99b6ec4601bfc6f319d6547dd810e564eaac4c Mon Sep 17 00:00:00 2001 From: Mounir Tohami <53877170+WhalesState@users.noreply.github.com> Date: Sat, 28 Sep 2024 03:08:54 +0000 Subject: [PATCH] Fix most of `TextEdit` visual issues. --- scene/gui/text_edit.cpp | 234 ++++++++++++++++++++-------------------- 1 file changed, 120 insertions(+), 114 deletions(-) diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index 687ca4d4d423..fa0a69db3004 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -605,6 +605,9 @@ void TextEdit::_notification(int p_what) { first_draw = false; } + Ref style = editable ? theme_cache.style_normal : theme_cache.style_readonly; + style->draw(get_canvas_item(), Rect2(Point2(), get_size())); + /* Prevent the resource getting lost between the editor and game. */ if (Engine::get_singleton()->is_editor_hint()) { if (syntax_highlighter.is_valid() && syntax_highlighter->get_text_edit() != this) { @@ -620,22 +623,20 @@ void TextEdit::_notification(int p_what) { _update_scrollbars(); + if (v_scroll->is_visible_in_tree()) { + size.width -= v_scroll->get_combined_minimum_size().width; + } + if (h_scroll->is_visible_in_tree()) { + size.height -= h_scroll->get_combined_minimum_size().height; + } + RID ci = get_canvas_item(); - int xmargin_beg = theme_cache.style_normal->get_margin(SIDE_LEFT) + gutters_width + gutter_padding; + int xmargin_beg = style->get_margin(SIDE_LEFT) + gutters_width + gutter_padding; + int xmargin_end = size.width - style->get_margin(SIDE_RIGHT); - int xmargin_end = size.width - theme_cache.style_normal->get_margin(SIDE_RIGHT); - if (draw_minimap) { - xmargin_end -= minimap_width; - } - // Let's do it easy for now. - theme_cache.style_normal->draw(ci, Rect2(Point2(), size)); if (!editable) { - theme_cache.style_readonly->draw(ci, Rect2(Point2(), size)); draw_caret = is_drawing_caret_when_editable_disabled(); } - if (has_focus()) { - theme_cache.style_focus->draw(ci, Rect2(Point2(), size)); - } int visible_rows = get_visible_line_count() + 1; @@ -814,6 +815,7 @@ void TextEdit::_notification(int p_what) { // Draw minimap. if (draw_minimap) { + xmargin_end -= minimap_width; int minimap_visible_lines = get_minimap_visible_lines(); int minimap_line_height = (minimap_char_size.y + minimap_line_spacing); int tab_size = text.get_tab_size(); @@ -822,6 +824,7 @@ void TextEdit::_notification(int p_what) { int viewport_height = (draw_amount - 1) * minimap_line_height; int control_height = _get_control_height() - viewport_height; int viewport_offset_y = round(get_scroll_pos_for_line(first_vis_line + 1) * control_height) / ((v_scroll->get_max() <= minimap_visible_lines) ? (minimap_visible_lines - draw_amount) : (v_scroll->get_max() - draw_amount)); + viewport_offset_y += style->get_margin(SIDE_TOP); // Calculate the first line. int num_lines_before = round((viewport_offset_y) / minimap_line_height); @@ -845,9 +848,9 @@ void TextEdit::_notification(int p_what) { } if (rtl) { - RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(size.width - (xmargin_end + 2) - minimap_width, viewport_offset_y, minimap_width, viewport_height), viewport_color); + RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(size.width - xmargin_end, viewport_offset_y, minimap_width, viewport_height), viewport_color); } else { - RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2((xmargin_end + 2), viewport_offset_y, minimap_width, viewport_height), viewport_color); + RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(xmargin_end, viewport_offset_y, minimap_width, viewport_height), viewport_color); } for (int i = 0; i < minimap_draw_amount; i++) { @@ -906,22 +909,22 @@ void TextEdit::_notification(int p_what) { if (highlight_current_line && highlighted_lines.has(Pair(minimap_line, line_wrap_index))) { if (rtl) { - RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(size.width - (xmargin_end + 2) - minimap_width, i * 3, minimap_width, 2), theme_cache.current_line_color); + RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(size.width - xmargin_end, (i * minimap_line_height) + style->get_margin(SIDE_TOP), minimap_width, minimap_char_size.y), theme_cache.current_line_color); } else { - RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2((xmargin_end + 2), i * 3, minimap_width, 2), theme_cache.current_line_color); + RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(xmargin_end, (i * minimap_line_height) + style->get_margin(SIDE_TOP), minimap_width, minimap_char_size.y), theme_cache.current_line_color); } } else if (line_background_color.a > 0) { if (rtl) { - RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(size.width - (xmargin_end + 2) - minimap_width, i * 3, minimap_width, 2), line_background_color); + RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(size.width - xmargin_end, (i * minimap_line_height) + style->get_margin(SIDE_TOP), minimap_width, minimap_char_size.y), line_background_color); } else { - RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2((xmargin_end + 2), i * 3, minimap_width, 2), line_background_color); + RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(xmargin_end, (i * minimap_line_height) + style->get_margin(SIDE_TOP), minimap_width, minimap_char_size.y), line_background_color); } } Color next_color = current_color; int characters = 0; int tab_alignment = 0; - int xpos = xmargin_end + 2 + indent_px; + int xpos = xmargin_end + indent_px; for (int j = 0; j < str.length(); j++) { bool next_is_whitespace = false; bool next_is_tab = false; @@ -964,9 +967,9 @@ void TextEdit::_notification(int p_what) { if (characters > 0) { if (rtl) { - RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(size.width - xpos - minimap_char_size.x * characters, minimap_line_height * i), Point2(minimap_char_size.x * characters, minimap_char_size.y)), current_color); + RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(size.width - xpos - minimap_char_size.x * characters, (minimap_line_height * i) + style->get_margin(SIDE_TOP)), Point2(minimap_char_size.x * characters, minimap_char_size.y)), current_color); } else { - RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(xpos, minimap_line_height * i), Point2(minimap_char_size.x * characters, minimap_char_size.y)), current_color); + RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(xpos, (minimap_line_height * i) + style->get_margin(SIDE_TOP)), Point2(minimap_char_size.x * characters, minimap_char_size.y)), current_color); } } @@ -997,13 +1000,8 @@ void TextEdit::_notification(int p_what) { int top_limit_y = 0; int bottom_limit_y = get_size().height; - if (!editable) { - top_limit_y += theme_cache.style_readonly->get_margin(SIDE_TOP); - bottom_limit_y -= theme_cache.style_readonly->get_margin(SIDE_BOTTOM); - } else { - top_limit_y += theme_cache.style_normal->get_margin(SIDE_TOP); - bottom_limit_y -= theme_cache.style_normal->get_margin(SIDE_BOTTOM); - } + top_limit_y += style->get_margin(SIDE_TOP); + bottom_limit_y -= style->get_margin(SIDE_BOTTOM); // Draw main text. line_drawing_cache.clear(); @@ -1053,17 +1051,8 @@ void TextEdit::_notification(int p_what) { const String &str = wrap_rows[line_wrap_index]; int char_margin = xmargin_beg - first_visible_col; - int ofs_x = 0; - int ofs_y = 0; - if (!editable) { - ofs_x = theme_cache.style_readonly->get_offset().x / 2; - ofs_x -= theme_cache.style_normal->get_offset().x / 2; - ofs_y = theme_cache.style_readonly->get_offset().y / 2; - } else { - ofs_y = theme_cache.style_normal->get_offset().y / 2; - } - - ofs_y += i * row_height + theme_cache.line_spacing / 2; + int ofs_y = style->get_margin(SIDE_TOP); + ofs_y += i * row_height; ofs_y -= first_visible_line_wrap_ofs * row_height; ofs_y -= _get_v_scroll_offset() * row_height; @@ -1082,18 +1071,18 @@ void TextEdit::_notification(int p_what) { if (text.get_line_background_color(line).a > 0.0) { if (rtl) { - RS::get_singleton()->canvas_item_add_rect(ci, Rect2(size.width - ofs_x - xmargin_end, ofs_y, xmargin_end - xmargin_beg, row_height), text.get_line_background_color(line)); + RS::get_singleton()->canvas_item_add_rect(ci, Rect2(size.width - xmargin_end, ofs_y, xmargin_end - xmargin_beg, row_height), text.get_line_background_color(line)); } else { - RS::get_singleton()->canvas_item_add_rect(ci, Rect2(xmargin_beg + ofs_x, ofs_y, xmargin_end - xmargin_beg, row_height), text.get_line_background_color(line)); + RS::get_singleton()->canvas_item_add_rect(ci, Rect2(xmargin_beg, ofs_y, xmargin_end - xmargin_beg, row_height), text.get_line_background_color(line)); } } // Draw current line highlight. if (highlight_current_line && highlighted_lines.has(Pair(line, line_wrap_index))) { if (rtl) { - RS::get_singleton()->canvas_item_add_rect(ci, Rect2(size.width - ofs_x - xmargin_end, ofs_y, xmargin_end, row_height), theme_cache.current_line_color); + RS::get_singleton()->canvas_item_add_rect(ci, Rect2(size.width - xmargin_end, ofs_y, xmargin_end - xmargin_beg, row_height), theme_cache.current_line_color); } else { - RS::get_singleton()->canvas_item_add_rect(ci, Rect2(ofs_x, ofs_y, xmargin_end, row_height), theme_cache.current_line_color); + RS::get_singleton()->canvas_item_add_rect(ci, Rect2(xmargin_beg, ofs_y, xmargin_end - xmargin_beg, row_height), theme_cache.current_line_color); } } @@ -1102,7 +1091,7 @@ void TextEdit::_notification(int p_what) { cache_entry.y_offset = ofs_y; - int gutter_offset = theme_cache.style_normal->get_margin(SIDE_LEFT); + int gutter_offset = style->get_margin(SIDE_LEFT); for (int g = 0; g < gutters.size(); g++) { const GutterInfo &gutter = gutters[g]; @@ -1123,9 +1112,9 @@ void TextEdit::_notification(int p_what) { int yofs = ofs_y + (row_height - tl->get_size().y) / 2; if (theme_cache.outline_size > 0 && theme_cache.outline_color.a > 0) { - tl->draw_outline(ci, Point2(gutter_offset + ofs_x, yofs), theme_cache.outline_size, theme_cache.outline_color); + tl->draw_outline(ci, Point2(gutter_offset, yofs), theme_cache.outline_size, theme_cache.outline_color); } - tl->draw(ci, Point2(gutter_offset + ofs_x, yofs), get_line_gutter_item_color(line, g)); + tl->draw(ci, Point2(gutter_offset, yofs), get_line_gutter_item_color(line, g)); } break; case GUTTER_TYPE_ICON: { const Ref icon = get_line_gutter_icon(line, g); @@ -1200,7 +1189,7 @@ void TextEdit::_notification(int p_what) { } for (int j = 0; j < sel.size(); j++) { - Rect2 rect = Rect2(sel[j].x + char_margin + ofs_x, ofs_y, Math::ceil(sel[j].y) - sel[j].x, row_height); + Rect2 rect = Rect2(sel[j].x + char_margin, ofs_y, Math::ceil(sel[j].y) - sel[j].x, row_height); if (rect.position.x + rect.size.x <= xmargin_beg || rect.position.x > xmargin_end) { continue; } @@ -1223,7 +1212,7 @@ void TextEdit::_notification(int p_what) { while (search_text_col != -1) { const Vector sel = TS->shaped_text_get_selection(rid, search_text_col + start, search_text_col + search_text_len + start); for (int j = 0; j < sel.size(); j++) { - Rect2 rect = Rect2(sel[j].x + char_margin + ofs_x, ofs_y, sel[j].y - sel[j].x, row_height); + Rect2 rect = Rect2(sel[j].x + char_margin, ofs_y, sel[j].y - sel[j].x, row_height); if (rect.position.x + rect.size.x <= xmargin_beg || rect.position.x > xmargin_end) { continue; } @@ -1247,7 +1236,7 @@ void TextEdit::_notification(int p_what) { while (highlighted_text_col != -1) { const Vector sel = TS->shaped_text_get_selection(rid, highlighted_text_col + start, highlighted_text_col + highlighted_text_len + start); for (int j = 0; j < sel.size(); j++) { - Rect2 rect = Rect2(sel[j].x + char_margin + ofs_x, ofs_y, sel[j].y - sel[j].x, row_height); + Rect2 rect = Rect2(sel[j].x + char_margin, ofs_y, sel[j].y - sel[j].x, row_height); if (rect.position.x + rect.size.x <= xmargin_beg || rect.position.x > xmargin_end) { continue; } @@ -1272,7 +1261,7 @@ void TextEdit::_notification(int p_what) { while (lookup_symbol_word_col != -1) { const Vector sel = TS->shaped_text_get_selection(rid, lookup_symbol_word_col + start, lookup_symbol_word_col + lookup_symbol_word_len + start); for (int j = 0; j < sel.size(); j++) { - Rect2 rect = Rect2(sel[j].x + char_margin + ofs_x, ofs_y + (theme_cache.line_spacing / 2), sel[j].y - sel[j].x, row_height); + Rect2 rect = Rect2(sel[j].x + char_margin, ofs_y + (theme_cache.line_spacing / 2), sel[j].y - sel[j].x, row_height); if (rect.position.x + rect.size.x <= xmargin_beg || rect.position.x > xmargin_end) { continue; } @@ -1308,7 +1297,7 @@ void TextEdit::_notification(int p_what) { for (int k = 0; k < glyphs[j].repeat; k++) { if ((char_ofs + char_margin) >= xmargin_beg && (char_ofs + glyphs[j].advance + char_margin) <= xmargin_end) { if (glyphs[j].font_rid != RID()) { - TS->font_draw_glyph_outline(glyphs[j].font_rid, ci, glyphs[j].font_size, theme_cache.outline_size, Vector2(char_margin + char_ofs + ofs_x + glyphs[j].x_off, ofs_y + glyphs[j].y_off), glyphs[j].index, theme_cache.outline_color); + TS->font_draw_glyph_outline(glyphs[j].font_rid, ci, glyphs[j].font_size, theme_cache.outline_size, Vector2(char_margin + char_ofs + glyphs[j].x_off, ofs_y + glyphs[j].y_off), glyphs[j].index, theme_cache.outline_color); } } char_ofs += glyphs[j].advance; @@ -1343,7 +1332,7 @@ void TextEdit::_notification(int p_what) { } } - float char_pos = char_ofs + char_margin + ofs_x; + float char_pos = char_ofs + char_margin; if (char_pos >= xmargin_beg) { if (highlight_matching_braces_enabled) { for (int c = 0; c < get_caret_count(); c++) { @@ -1382,10 +1371,10 @@ void TextEdit::_notification(int p_what) { for (int k = 0; k < glyphs[j].repeat; k++) { if (!clipped && (char_ofs + char_margin) >= xmargin_beg && (char_ofs + glyphs[j].advance + char_margin) <= xmargin_end) { if (glyphs[j].font_rid != RID()) { - TS->font_draw_glyph(glyphs[j].font_rid, ci, glyphs[j].font_size, Vector2(char_margin + char_ofs + ofs_x + glyphs[j].x_off, ofs_y + glyphs[j].y_off), glyphs[j].index, gl_color); + TS->font_draw_glyph(glyphs[j].font_rid, ci, glyphs[j].font_size, Vector2(char_margin + char_ofs + glyphs[j].x_off, ofs_y + glyphs[j].y_off), glyphs[j].index, gl_color); had_glyphs_drawn = true; } else if (((glyphs[j].flags & TextServer::GRAPHEME_IS_VIRTUAL) != TextServer::GRAPHEME_IS_VIRTUAL) && ((glyphs[j].flags & TextServer::GRAPHEME_IS_EMBEDDED_OBJECT) != TextServer::GRAPHEME_IS_EMBEDDED_OBJECT)) { - TS->draw_hex_code_box(ci, glyphs[j].font_size, Vector2(char_margin + char_ofs + ofs_x + glyphs[j].x_off, ofs_y + glyphs[j].y_off), glyphs[j].index, gl_color); + TS->draw_hex_code_box(ci, glyphs[j].font_size, Vector2(char_margin + char_ofs + glyphs[j].x_off, ofs_y + glyphs[j].y_off), glyphs[j].index, gl_color); had_glyphs_drawn = true; } } @@ -1411,7 +1400,7 @@ void TextEdit::_notification(int p_what) { // is_line_folded if (line_wrap_index == line_wrap_amount && line < text.size() - 1 && _is_line_hidden(line + 1)) { - int xofs = char_ofs + char_margin + ofs_x + (_get_folded_eol_icon()->get_width() / 2); + int xofs = char_ofs + char_margin + (_get_folded_eol_icon()->get_width() / 2); if (xofs >= xmargin_beg && xofs < xmargin_end) { int yofs = (text_height - _get_folded_eol_icon()->get_height()) / 2 - ldata->get_line_ascent(line_wrap_index); Color eol_color = _get_code_folding_color(); @@ -1439,7 +1428,7 @@ void TextEdit::_notification(int p_what) { int h = theme_cache.font->get_height(theme_cache.font_size); if (rtl) { ts_caret.l_dir = TextServer::DIRECTION_RTL; - ts_caret.l_caret = Rect2(Vector2(xmargin_end - char_margin + ofs_x, -h / 2), Size2(caret_width * 4, h)); + ts_caret.l_caret = Rect2(Vector2(xmargin_end - char_margin, -h / 2), Size2(caret_width * 4, h)); } else { ts_caret.l_dir = TextServer::DIRECTION_LTR; ts_caret.l_caret = Rect2(Vector2(char_ofs, -h / 2), Size2(caret_width * 4, h)); @@ -1447,9 +1436,9 @@ void TextEdit::_notification(int p_what) { } 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())) { - carets.write[c].draw_pos.x = char_margin + ofs_x + ts_caret.l_caret.position.x; + carets.write[c].draw_pos.x = char_margin + ts_caret.l_caret.position.x; } else { - carets.write[c].draw_pos.x = char_margin + ofs_x + ts_caret.t_caret.position.x; + carets.write[c].draw_pos.x = char_margin + ts_caret.t_caret.position.x; } if (get_caret_draw_pos(c).x >= xmargin_beg && get_caret_draw_pos(c).x < xmargin_end) { @@ -1467,12 +1456,12 @@ void TextEdit::_notification(int p_what) { ts_caret.t_caret.position.y = -TS->shaped_text_get_ascent(rid); ts_caret.t_caret.size.y = h; } - ts_caret.t_caret.position += Vector2(char_margin + ofs_x, ofs_y); + ts_caret.t_caret.position += Vector2(char_margin, ofs_y); draw_rect(ts_caret.t_caret, theme_cache.caret_color, overtype_mode); if (ts_caret.l_caret != Rect2() && ts_caret.l_dir != ts_caret.t_dir) { // Draw split caret (leading part). - ts_caret.l_caret.position += Vector2(char_margin + ofs_x, ofs_y); + ts_caret.l_caret.position += Vector2(char_margin, ofs_y); ts_caret.l_caret.size.x = caret_width; RS::get_singleton()->canvas_item_add_rect(ci, ts_caret.l_caret, theme_cache.caret_color); // Draw extra direction marker on top of split caret. @@ -1499,7 +1488,7 @@ void TextEdit::_notification(int p_what) { } else { ts_caret.l_caret.size.x = 3 * caret_width; } - ts_caret.l_caret.position += Vector2(char_margin + ofs_x, ofs_y); + ts_caret.l_caret.position += Vector2(char_margin, ofs_y); if (ts_caret.l_dir == TextServer::DIRECTION_RTL) { ts_caret.l_caret.position.x -= ts_caret.l_caret.size.x; } @@ -1510,26 +1499,26 @@ void TextEdit::_notification(int p_what) { if (ts_caret.l_caret != Rect2() && ts_caret.l_dir == TextServer::DIRECTION_AUTO) { // Draw extra marker on top of mid caret. Rect2 trect = Rect2(ts_caret.l_caret.position.x - 2.5 * caret_width, ts_caret.l_caret.position.y, 6 * caret_width, caret_width); - trect.position += Vector2(char_margin + ofs_x, ofs_y); + trect.position += Vector2(char_margin, ofs_y); RS::get_singleton()->canvas_item_add_rect(ci, trect, theme_cache.caret_color); } else if (ts_caret.l_caret != Rect2() && ts_caret.t_caret != Rect2() && ts_caret.l_dir != ts_caret.t_dir) { // Draw extra direction marker on top of split caret. float d = (ts_caret.l_dir == TextServer::DIRECTION_LTR) ? 0.5 : -3; Rect2 trect = Rect2(ts_caret.l_caret.position.x + d * caret_width, ts_caret.l_caret.position.y + ts_caret.l_caret.size.y - caret_width, 3 * caret_width, caret_width); - trect.position += Vector2(char_margin + ofs_x, ofs_y); + trect.position += Vector2(char_margin, ofs_y); RS::get_singleton()->canvas_item_add_rect(ci, trect, theme_cache.caret_color); d = (ts_caret.t_dir == TextServer::DIRECTION_LTR) ? 0.5 : -3; trect = Rect2(ts_caret.t_caret.position.x + d * caret_width, ts_caret.t_caret.position.y, 3 * caret_width, caret_width); - trect.position += Vector2(char_margin + ofs_x, ofs_y); + trect.position += Vector2(char_margin, ofs_y); RS::get_singleton()->canvas_item_add_rect(ci, trect, theme_cache.caret_color); } - ts_caret.l_caret.position += Vector2(char_margin + ofs_x, ofs_y); + ts_caret.l_caret.position += Vector2(char_margin, ofs_y); ts_caret.l_caret.size.x = caret_width; RS::get_singleton()->canvas_item_add_rect(ci, ts_caret.l_caret, theme_cache.caret_color); - ts_caret.t_caret.position += Vector2(char_margin + ofs_x, ofs_y); + ts_caret.t_caret.position += Vector2(char_margin, ofs_y); ts_caret.t_caret.size.x = caret_width; RS::get_singleton()->canvas_item_add_rect(ci, ts_caret.t_caret, theme_cache.caret_color); @@ -1542,7 +1531,7 @@ void TextEdit::_notification(int p_what) { // IME Intermediate text range. const Vector sel = TS->shaped_text_get_selection(rid, get_caret_column(c), get_caret_column(c) + ime_text.length()); for (int j = 0; j < sel.size(); j++) { - Rect2 rect = Rect2(sel[j].x + char_margin + ofs_x, ofs_y, sel[j].y - sel[j].x, text_height); + Rect2 rect = Rect2(sel[j].x + char_margin, ofs_y, sel[j].y - sel[j].x, text_height); if (rect.position.x + rect.size.x <= xmargin_beg || rect.position.x > xmargin_end) { continue; } @@ -1561,7 +1550,7 @@ void TextEdit::_notification(int p_what) { // IME caret. const Vector sel = TS->shaped_text_get_selection(rid, get_caret_column(c) + ime_selection.x, get_caret_column(c) + ime_selection.x + ime_selection.y); for (int j = 0; j < sel.size(); j++) { - Rect2 rect = Rect2(sel[j].x + char_margin + ofs_x, ofs_y, sel[j].y - sel[j].x, text_height); + Rect2 rect = Rect2(sel[j].x + char_margin, ofs_y, sel[j].y - sel[j].x, text_height); if (rect.position.x + rect.size.x <= xmargin_beg || rect.position.x > xmargin_end) { continue; } @@ -1587,6 +1576,7 @@ void TextEdit::_notification(int p_what) { } if (has_focus()) { + theme_cache.style_focus->draw(get_canvas_item(), Rect2(Point2(), get_size())); _update_ime_window_position(); } } break; @@ -1833,8 +1823,9 @@ void TextEdit::gui_input(const Ref &p_gui_input) { int line = pos.y; int col = pos.x; + Ref style = editable ? theme_cache.style_normal : theme_cache.style_readonly; // Gutters. - int left_margin = theme_cache.style_normal->get_margin(SIDE_LEFT); + int left_margin = style->get_margin(SIDE_LEFT); for (int i = 0; i < gutters.size(); i++) { if (!gutters[i].draw || gutters[i].width <= 0) { continue; @@ -2057,8 +2048,8 @@ void TextEdit::gui_input(const Ref &p_gui_input) { // Check if user is hovering a different gutter, and update if yes. Vector2i current_hovered_gutter = Vector2i(-1, -1); - - int left_margin = theme_cache.style_normal->get_margin(SIDE_LEFT); + Ref style = editable ? theme_cache.style_normal : theme_cache.style_readonly; + int left_margin = style->get_margin(SIDE_LEFT); if (mpos.x <= left_margin + gutters_width + gutter_padding) { int hovered_row = get_line_column_at_pos(mpos).y; for (int i = 0; i < gutters.size(); i++) { @@ -2958,7 +2949,7 @@ void TextEdit::_close_ime_window() { void TextEdit::_update_ime_window_position() { DisplayServer::WindowID wid = get_window() ? get_window()->get_window_id() : DisplayServer::INVALID_WINDOW_ID; - if (wid == DisplayServer::INVALID_WINDOW_ID || !DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_IME) || !DisplayServer::get_singleton()->window_is_focused(wid)) { + if (wid == DisplayServer::INVALID_WINDOW_ID || !DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_IME)) { return; } DisplayServer::get_singleton()->window_set_ime_active(true, wid); @@ -3011,12 +3002,17 @@ void TextEdit::_show_virtual_keyboard() { /* General overrides. */ Size2 TextEdit::get_minimum_size() const { - Size2 size = theme_cache.style_normal->get_minimum_size(); + Ref style = editable ? theme_cache.style_normal : theme_cache.style_readonly; + Size2 size = style->get_minimum_size(); if (fit_content_height) { - size.y += content_size_cache.y; + size.height += content_size_cache.height; + } else if (v_scroll->is_visible_in_tree()) { + size.width += v_scroll->get_combined_minimum_size().width; } if (fit_content_width) { - size.x += content_size_cache.x; + size.width += content_size_cache.width; + } else if (h_scroll->is_visible_in_tree()) { + size.height += h_scroll->get_combined_minimum_size().height; } return size; } @@ -3105,8 +3101,9 @@ void TextEdit::drop_data(const Point2 &p_point, const Variant &p_data) { Control::CursorShape TextEdit::get_cursor_shape(const Point2 &p_pos) const { Point2i pos = get_line_column_at_pos(p_pos); int row = pos.y; + Ref style = editable ? theme_cache.style_normal : theme_cache.style_readonly; - int left_margin = theme_cache.style_normal->get_margin(SIDE_LEFT); + int left_margin = style->get_margin(SIDE_LEFT); int gutter = left_margin + gutters_width; if (p_pos.x < gutter) { for (int i = 0; i < gutters.size(); i++) { @@ -3124,7 +3121,7 @@ Control::CursorShape TextEdit::get_cursor_shape(const Point2 &p_pos) const { return CURSOR_ARROW; } - int xmargin_end = get_size().width - theme_cache.style_normal->get_margin(SIDE_RIGHT); + int xmargin_end = get_size().width - style->get_margin(SIDE_RIGHT); if (draw_minimap && p_pos.x > xmargin_end - minimap_width && p_pos.x <= xmargin_end) { return CURSOR_ARROW; } @@ -4395,11 +4392,8 @@ String TextEdit::get_word_at_pos(const Vector2 &p_pos) const { } Point2i TextEdit::get_line_column_at_pos(const Point2i &p_pos, bool p_allow_out_of_bounds) const { - float rows = p_pos.y - theme_cache.style_normal->get_margin(SIDE_TOP); - if (!editable) { - rows -= theme_cache.style_readonly->get_offset().y / 2; - rows += theme_cache.style_normal->get_offset().y / 2; - } + Ref style = editable ? theme_cache.style_normal : theme_cache.style_readonly; + float rows = p_pos.y - style->get_margin(SIDE_TOP); rows /= get_line_height(); rows += _get_v_scroll_offset(); int first_vis_line = get_first_visible_line(); @@ -4427,12 +4421,8 @@ Point2i TextEdit::get_line_column_at_pos(const Point2i &p_pos, bool p_allow_out_ return Point2i(text[row].length(), row); } - int colx = p_pos.x - (theme_cache.style_normal->get_margin(SIDE_LEFT) + gutters_width + gutter_padding); + int colx = p_pos.x - (style->get_margin(SIDE_LEFT) + gutters_width + gutter_padding); colx += first_visible_col; - if (!editable) { - colx -= theme_cache.style_readonly->get_offset().x / 2; - colx += theme_cache.style_normal->get_offset().x / 2; - } 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; @@ -4483,9 +4473,10 @@ Rect2i TextEdit::get_rect_at_line_column(int p_line, int p_column) const { return Rect2i(-1, -1, 0, 0); } + Ref style = editable ? theme_cache.style_normal : theme_cache.style_readonly; Point2i pos, size; pos.y = cache_entry.y_offset + get_line_height() * wrap_index; - pos.x = get_total_gutter_width() + theme_cache.style_normal->get_margin(SIDE_LEFT) - get_h_scroll(); + pos.x = get_total_gutter_width() + style->get_margin(SIDE_LEFT) - get_h_scroll(); RID text_rid = text.get_line_data(p_line)->get_line_rid(wrap_index); Vector2 col_bounds = TS->shaped_text_get_grapheme_bounds(text_rid, p_column); @@ -4515,6 +4506,7 @@ int TextEdit::get_minimap_line_at_pos(const Point2i &p_pos) const { int viewport_height = (draw_amount - 1) * minimap_line_height; int control_height = _get_control_height() - viewport_height; int viewport_offset_y = round(get_scroll_pos_for_line(first_vis_line + 1) * control_height) / ((v_scroll->get_max() <= minimap_visible_lines) ? (minimap_visible_lines - draw_amount) : (v_scroll->get_max() - draw_amount)); + viewport_offset_y += editable ? theme_cache.style_normal->get_margin(SIDE_TOP) : theme_cache.style_readonly->get_margin(SIDE_TOP); // Calculate the first line. int num_lines_before = round((viewport_offset_y) / minimap_line_height); @@ -6006,7 +5998,8 @@ void TextEdit::adjust_viewport_to_caret(int p_caret) { set_line_as_last_visible(cur_line, cur_wrap); } - int visible_width = get_size().width - theme_cache.style_normal->get_minimum_size().width - gutters_width - gutter_padding; + Ref style = editable ? theme_cache.style_normal : theme_cache.style_readonly; + int visible_width = get_size().width - style->get_minimum_size().width - gutters_width - gutter_padding; if (draw_minimap) { visible_width -= minimap_width; } @@ -6060,7 +6053,8 @@ void TextEdit::center_viewport_to_caret(int p_caret) { minimap_clicked = false; set_line_as_center_visible(get_caret_line(p_caret), get_caret_wrap_index(p_caret)); - int visible_width = get_size().width - theme_cache.style_normal->get_minimum_size().width - gutters_width - gutter_padding; + Ref style = editable ? theme_cache.style_normal : theme_cache.style_readonly; + int visible_width = get_size().width - style->get_minimum_size().width - gutters_width - gutter_padding; if (draw_minimap) { visible_width -= minimap_width; } @@ -7887,7 +7881,8 @@ bool TextEdit::_selection_contains(int p_caret, int p_line, int p_column, bool p /* Line Wrapping */ void TextEdit::_update_wrap_at_column(bool p_force) { - int new_wrap_at = get_size().width - theme_cache.style_normal->get_minimum_size().width - gutters_width - gutter_padding; + Ref style = editable ? theme_cache.style_normal : theme_cache.style_readonly; + int new_wrap_at = get_size().width - style->get_minimum_size().width - gutters_width - gutter_padding; if (draw_minimap) { new_wrap_at -= minimap_width; } @@ -7937,14 +7932,6 @@ void TextEdit::_update_wrap_at_column(bool p_force) { /* Viewport. */ void TextEdit::_update_scrollbars() { Size2 size = get_size(); - Size2 hmin = h_scroll->get_combined_minimum_size(); - Size2 vmin = v_scroll->get_combined_minimum_size(); - - v_scroll->set_begin(Point2(size.width - vmin.width, theme_cache.style_normal->get_margin(SIDE_TOP))); - v_scroll->set_end(Point2(size.width, size.height - theme_cache.style_normal->get_margin(SIDE_TOP) - theme_cache.style_normal->get_margin(SIDE_BOTTOM))); - - h_scroll->set_begin(Point2(0, size.height - hmin.height)); - h_scroll->set_end(Point2(size.width - vmin.width, size.height)); bool draw_placeholder = _using_placeholder(); @@ -7954,22 +7941,18 @@ void TextEdit::_update_scrollbars() { total_rows += visible_rows - 1; } - int visible_width = size.width - theme_cache.style_normal->get_minimum_size().width; - int total_width = (draw_placeholder ? placeholder_max_width : text.get_max_width()) + gutters_width + gutter_padding; - - if (draw_minimap) { - total_width += minimap_width; - } + updating_scrolls = true; - content_size_cache = Vector2i(total_width + 10, MAX(total_rows, 1) * get_line_height()); - if (fit_content_height || fit_content_width) { - update_minimum_size(); - } + Ref style = editable ? theme_cache.style_normal : theme_cache.style_readonly; + int visible_width = size.width - style->get_minimum_size().width; + int total_width = (draw_placeholder ? placeholder_max_width : text.get_max_width()) + gutters_width + gutter_padding; - updating_scrolls = true; + int hmin = h_scroll->get_combined_minimum_size().height; + int vmin = v_scroll->get_combined_minimum_size().width; if (!fit_content_height && total_rows > visible_rows) { v_scroll->show(); + total_width += vmin; v_scroll->set_max(total_rows + _get_visible_lines_offset()); v_scroll->set_page(visible_rows + _get_visible_lines_offset()); set_v_scroll(get_v_scroll()); @@ -7982,6 +7965,10 @@ void TextEdit::_update_scrollbars() { v_scroll->hide(); } + if (draw_minimap) { + total_width += minimap_width; + } + if (total_width > visible_width) { h_scroll->show(); h_scroll->set_max(total_width); @@ -8000,12 +7987,29 @@ void TextEdit::_update_scrollbars() { h_scroll->hide(); } + h_scroll->set_begin(Point2(style->get_margin(SIDE_LEFT), size.height - style->get_margin(SIDE_BOTTOM) - hmin)); + v_scroll->set_begin(Point2(size.width - style->get_margin(SIDE_RIGHT) - vmin, style->get_margin(SIDE_TOP))); + + Point2 h_scroll_end = Point2(size.width - style->get_margin(SIDE_RIGHT), size.height - style->get_margin(SIDE_BOTTOM)); + Point2 v_scroll_end = Point2(size.width - style->get_margin(SIDE_RIGHT), size.height - style->get_margin(SIDE_BOTTOM)); + if (h_scroll->is_visible_in_tree() && v_scroll->is_visible_in_tree()) { + h_scroll_end.width -= vmin; + v_scroll_end.height -= hmin; + } + h_scroll->set_end(h_scroll_end); + v_scroll->set_end(v_scroll_end); + + content_size_cache = Vector2i(total_width + 10, MAX(total_rows, 1) * get_line_height()); + if (fit_content_height || fit_content_width) { + update_minimum_size(); + } + updating_scrolls = false; } int TextEdit::_get_control_height() const { - int control_height = get_size().height; - control_height -= theme_cache.style_normal->get_minimum_size().height; + Ref style = editable ? theme_cache.style_normal : theme_cache.style_readonly; + int control_height = get_size().height - style->get_minimum_size().height; if (h_scroll->is_visible_in_tree()) { control_height -= h_scroll->get_size().height; } @@ -8167,7 +8171,8 @@ void TextEdit::_scroll_lines_down() { void TextEdit::_update_minimap_hover() { const Point2 mp = get_local_mouse_pos(); - const int xmargin_end = get_size().width - theme_cache.style_normal->get_margin(SIDE_RIGHT); + Ref style = editable ? theme_cache.style_normal : theme_cache.style_readonly; + const int xmargin_end = get_size().width - style->get_margin(SIDE_RIGHT); bool hovering_sidebar = mp.x > xmargin_end - minimap_width && mp.x < xmargin_end; if (!hovering_sidebar) { @@ -8193,8 +8198,9 @@ void TextEdit::_update_minimap_hover() { void TextEdit::_update_minimap_click() { Point2 mp = get_local_mouse_pos(); + Ref style = editable ? theme_cache.style_normal : theme_cache.style_readonly; - int xmargin_end = get_size().width - theme_cache.style_normal->get_margin(SIDE_RIGHT); + int xmargin_end = get_size().width - style->get_margin(SIDE_RIGHT); if (!dragging_minimap && (mp.x < xmargin_end - minimap_width || mp.x > xmargin_end)) { minimap_clicked = false; return; @@ -8204,7 +8210,7 @@ void TextEdit::_update_minimap_click() { int row = get_minimap_line_at_pos(mp); - if (row >= get_first_visible_line() && (row < get_last_full_visible_line() || row >= (text.size() - 1))) { + if (row >= get_first_visible_line() && (row <= get_last_full_visible_line() || row >= (text.size() - 1))) { minimap_scroll_ratio = v_scroll->get_as_ratio(); minimap_scroll_click_pos = mp.y; can_drag_minimap = true;