Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added visual indentation line guides for text editors #38833

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions editor/code_editor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -885,6 +885,8 @@ void CodeTextEditor::update_editor_settings() {
text_editor->set_auto_indent(EditorSettings::get_singleton()->get("text_editor/indent/auto_indent"));
text_editor->set_draw_tabs(EditorSettings::get_singleton()->get("text_editor/indent/draw_tabs"));
text_editor->set_draw_spaces(EditorSettings::get_singleton()->get("text_editor/indent/draw_spaces"));
text_editor->set_draw_indent_guides(EditorSettings::get_singleton()->get("text_editor/indent/draw_indent_guides"));
text_editor->set_highlight_active_indent_guide(EditorSettings::get_singleton()->get("text_editor/indent/highlight_active_indent_guide"));
text_editor->set_smooth_scroll_enabled(EditorSettings::get_singleton()->get("text_editor/navigation/smooth_scrolling"));
text_editor->set_v_scroll_speed(EditorSettings::get_singleton()->get("text_editor/navigation/v_scroll_speed"));
text_editor->set_draw_minimap(EditorSettings::get_singleton()->get("text_editor/navigation/show_minimap"));
Expand Down
4 changes: 4 additions & 0 deletions editor/editor_settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -433,6 +433,8 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
_initial_set("text_editor/indent/auto_indent", true);
_initial_set("text_editor/indent/convert_indent_on_save", true);
_initial_set("text_editor/indent/draw_tabs", true);
_initial_set("text_editor/indent/draw_indent_guides", true);
_initial_set("text_editor/indent/highlight_active_indent_guide", true);
_initial_set("text_editor/indent/draw_spaces", false);

// Navigation
Expand Down Expand Up @@ -678,6 +680,8 @@ void EditorSettings::_load_default_text_editor_theme() {
_initial_set("text_editor/highlighting/brace_mismatch_color", Color(1, 0.2, 0.2));
_initial_set("text_editor/highlighting/current_line_color", Color(0.3, 0.5, 0.8, 0.15));
_initial_set("text_editor/highlighting/line_length_guideline_color", Color(0.3, 0.5, 0.8, 0.1));
_initial_set("text_editor/highlighting/indent_guide_color", Color(0.8, 0.8, 0.8, 0.1));
_initial_set("text_editor/highlighting/indent_active_guide_color", Color(0.8, 0.8, 0.8, 0.25));
_initial_set("text_editor/highlighting/word_highlighted_color", Color(0.8, 0.9, 0.9, 0.15));
_initial_set("text_editor/highlighting/number_color", Color(0.92, 0.58, 0.2));
_initial_set("text_editor/highlighting/function_color", Color(0.4, 0.64, 0.81));
Expand Down
4 changes: 4 additions & 0 deletions editor/editor_themes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1179,6 +1179,8 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
const Color brace_mismatch_color = error_color;
const Color current_line_color = alpha1;
const Color line_length_guideline_color = dark_theme ? base_color : background_color;
const Color indent_guide_color = mono_color * Color(1, 1, 1, 0.3);
const Color indent_active_guide_color = mono_color * Color(1, 1, 1, 0.6);
const Color word_highlighted_color = alpha1;
const Color number_color = basetype_color.lerp(mono_color, dark_theme ? 0.5 : 0.3);
const Color function_color = main_color;
Expand Down Expand Up @@ -1217,6 +1219,8 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
setting->set_initial_value("text_editor/highlighting/brace_mismatch_color", brace_mismatch_color, true);
setting->set_initial_value("text_editor/highlighting/current_line_color", current_line_color, true);
setting->set_initial_value("text_editor/highlighting/line_length_guideline_color", line_length_guideline_color, true);
setting->set_initial_value("text_editor/highlighting/indent_guide_color", indent_guide_color, true);
setting->set_initial_value("text_editor/highlighting/indent_active_guide_color", indent_active_guide_color, true);
setting->set_initial_value("text_editor/highlighting/word_highlighted_color", word_highlighted_color, true);
setting->set_initial_value("text_editor/highlighting/number_color", number_color, true);
setting->set_initial_value("text_editor/highlighting/function_color", function_color, true);
Expand Down
4 changes: 4 additions & 0 deletions editor/plugins/script_text_editor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,8 @@ void ScriptTextEditor::_load_theme_settings() {
Color brace_mismatch_color = EDITOR_GET("text_editor/highlighting/brace_mismatch_color");
Color current_line_color = EDITOR_GET("text_editor/highlighting/current_line_color");
Color line_length_guideline_color = EDITOR_GET("text_editor/highlighting/line_length_guideline_color");
Color indent_guide_color = EDITOR_GET("text_editor/highlighting/indent_guide_color");
Color indent_active_guide_color = EDITOR_GET("text_editor/highlighting/indent_active_guide_color");
Color word_highlighted_color = EDITOR_GET("text_editor/highlighting/word_highlighted_color");
Color number_color = EDITOR_GET("text_editor/highlighting/number_color");
Color function_color = EDITOR_GET("text_editor/highlighting/function_color");
Expand Down Expand Up @@ -244,6 +246,8 @@ void ScriptTextEditor::_load_theme_settings() {
text_edit->add_theme_color_override("brace_mismatch_color", brace_mismatch_color);
text_edit->add_theme_color_override("current_line_color", current_line_color);
text_edit->add_theme_color_override("line_length_guideline_color", line_length_guideline_color);
text_edit->add_theme_color_override("indent_guide_color", indent_guide_color);
text_edit->add_theme_color_override("indent_active_guide_color", indent_active_guide_color);
text_edit->add_theme_color_override("word_highlighted_color", word_highlighted_color);
text_edit->add_theme_color_override("number_color", number_color);
text_edit->add_theme_color_override("function_color", function_color);
Expand Down
4 changes: 4 additions & 0 deletions editor/plugins/shader_editor_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@ void ShaderTextEditor::_load_theme_settings() {
Color brace_mismatch_color = EDITOR_GET("text_editor/highlighting/brace_mismatch_color");
Color current_line_color = EDITOR_GET("text_editor/highlighting/current_line_color");
Color line_length_guideline_color = EDITOR_GET("text_editor/highlighting/line_length_guideline_color");
Color indent_guide_color = EDITOR_GET("text_editor/highlighting/indent_guide_color");
Color indent_active_guide_color = EDITOR_GET("text_editor/highlighting/indent_active_guide_color");
Color word_highlighted_color = EDITOR_GET("text_editor/highlighting/word_highlighted_color");
Color number_color = EDITOR_GET("text_editor/highlighting/number_color");
Color function_color = EDITOR_GET("text_editor/highlighting/function_color");
Expand Down Expand Up @@ -130,6 +132,8 @@ void ShaderTextEditor::_load_theme_settings() {
get_text_edit()->add_theme_color_override("brace_mismatch_color", brace_mismatch_color);
get_text_edit()->add_theme_color_override("current_line_color", current_line_color);
get_text_edit()->add_theme_color_override("line_length_guideline_color", line_length_guideline_color);
get_text_edit()->add_theme_color_override("indent_guide_color", indent_guide_color);
get_text_edit()->add_theme_color_override("indent_active_guide_color", indent_active_guide_color);
get_text_edit()->add_theme_color_override("word_highlighted_color", word_highlighted_color);
get_text_edit()->add_theme_color_override("number_color", number_color);
get_text_edit()->add_theme_color_override("function_color", function_color);
Expand Down
4 changes: 4 additions & 0 deletions editor/plugins/text_editor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ void TextEditor::_load_theme_settings() {
Color brace_mismatch_color = EDITOR_GET("text_editor/highlighting/brace_mismatch_color");
Color current_line_color = EDITOR_GET("text_editor/highlighting/current_line_color");
Color line_length_guideline_color = EDITOR_GET("text_editor/highlighting/line_length_guideline_color");
Color indent_guide_color = EDITOR_GET("text_editor/highlighting/indent_guide_color");
Color indent_active_guide_color = EDITOR_GET("text_editor/highlighting/indent_active_guide_color");
Color word_highlighted_color = EDITOR_GET("text_editor/highlighting/word_highlighted_color");
Color number_color = EDITOR_GET("text_editor/highlighting/number_color");
Color function_color = EDITOR_GET("text_editor/highlighting/function_color");
Expand Down Expand Up @@ -121,6 +123,8 @@ void TextEditor::_load_theme_settings() {
text_edit->add_theme_color_override("brace_mismatch_color", brace_mismatch_color);
text_edit->add_theme_color_override("current_line_color", current_line_color);
text_edit->add_theme_color_override("line_length_guideline_color", line_length_guideline_color);
text_edit->add_theme_color_override("indent_guide_color", indent_guide_color);
text_edit->add_theme_color_override("indent_active_guide_color", indent_active_guide_color);
text_edit->add_theme_color_override("word_highlighted_color", word_highlighted_color);
text_edit->add_theme_color_override("number_color", number_color);
text_edit->add_theme_color_override("function_color", function_color);
Expand Down
101 changes: 87 additions & 14 deletions scene/gui/text_edit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1055,8 +1055,13 @@ void TextEdit::_notification(int p_what) {
}
}

// draw main text
// Find which 'fold' the cursor line is a part of
int selected_line_parent_fold_start_line = get_line_parent_fold(cursor_get_line());
int selected_line_parent_fold_last_line = get_fold_last_line(selected_line_parent_fold_start_line);

// Draw main text.
int line = first_visible_line;

for (int i = 0; i < draw_amount; i++) {
line++;

Expand Down Expand Up @@ -1123,6 +1128,30 @@ void TextEdit::_notification(int p_what) {
ofs_y -= cursor.wrap_ofs * get_row_height();
ofs_y -= get_v_scroll_offset() * get_row_height();

// Draw indent guides
if (draw_indent_guides && get_indent_level(line) != 0) {
// "Indent Count" is just the number of spaces in the indent (indent level) / the number of spaces per indent (indent size)
int indent_count = get_indent_level(line) / indent_size;

for (int indent_idx = 0; indent_idx < indent_count; indent_idx++) {
Color line_color = cache.indent_guide_color;

if (highlight_active_indent_guide &&
indent_idx == get_indent_level(cursor_get_line()) / indent_size - 1 &&
line >= selected_line_parent_fold_start_line &&
line <= selected_line_parent_fold_last_line) {
// Make the line more prominent for the selected code block
line_color = cache.indent_active_guide_color;
}

draw_line(
Point2(indent_idx * indent_size * cache.font->get_char_size(' ').width + xmargin_beg, ofs_y),
Point2(indent_idx * indent_size * cache.font->get_char_size(' ').width + xmargin_beg, ofs_y + get_row_height()),
line_color,
1);
}
}

// Check if line contains highlighted word.
int highlighted_text_col = -1;
int search_text_col = -1;
Expand Down Expand Up @@ -1482,6 +1511,7 @@ void TextEdit::_notification(int p_what) {
} else if (draw_tabs && str[j] == '\t') {
int yofs = (get_row_height() - cache.tab_icon->get_height()) / 2;
cache.tab_icon->draw(ci, Point2(char_ofs + char_margin + ofs_x, ofs_y + yofs), in_selection && override_selected_font_color ? cache.font_color_selected : color);
//draw_line(Point2(char_ofs + char_margin + ofs_x, ofs_y + get_row_height()), Point2(char_ofs + char_margin + ofs_x, ofs_y), Color(1, 1, 1, 0.1), 1);
}

if (draw_spaces && str[j] == ' ') {
Expand Down Expand Up @@ -5010,6 +5040,8 @@ void TextEdit::_update_caches() {
cache.mark_color = get_theme_color("mark_color");
cache.current_line_color = get_theme_color("current_line_color");
cache.line_length_guideline_color = get_theme_color("line_length_guideline_color");
cache.indent_guide_color = get_theme_color("indent_guide_color");
cache.indent_active_guide_color = get_theme_color("indent_active_guide_color");
cache.bookmark_color = get_theme_color("bookmark_color");
cache.breakpoint_color = get_theme_color("breakpoint_color");
cache.executing_line_color = get_theme_color("executing_line_color");
Expand Down Expand Up @@ -5930,19 +5962,8 @@ void TextEdit::fold_line(int p_line) {
}

// Hide lines below this one.
int start_indent = get_indent_level(p_line);
int last_line = start_indent;
for (int i = p_line + 1; i < text.size(); i++) {
if (text[i].strip_edges().size() != 0) {
if (is_line_comment(i)) {
continue;
} else if (get_indent_level(i) > start_indent) {
last_line = i;
} else {
break;
}
}
}
int last_line = get_fold_last_line(p_line);

for (int i = p_line + 1; i <= last_line; i++) {
set_line_as_hidden(i, true);
}
Expand Down Expand Up @@ -6002,6 +6023,38 @@ void TextEdit::toggle_fold_line(int p_line) {
}
}

// Returns the first line above p_line which would 'fold' p_line and hide it
int TextEdit::get_line_parent_fold(int p_line) {
int indent_count = get_indent_level(p_line) / indent_size;

// Work backwards from the line to find the line that 1) can fold and b) is dedented compared to p_line
for (int line = p_line - 1; line >= 0; line--) {
if (can_fold(line) && get_indent_level(line) / indent_size < indent_count) {
return line;
}
}
return 0;
}

int TextEdit::get_fold_last_line(int p_start_line) {
int start_indent = get_indent_level(p_start_line);
int last_line = p_start_line;

for (int i = p_start_line + 1; i < text.size(); i++) {
if (text[i].strip_edges().size() != 0) {
if (is_line_comment(i)) {
continue;
} else if (get_indent_level(i) > start_indent) {
last_line = i;
} else {
break;
}
}
}

return last_line;
}

int TextEdit::get_line_count() const {
return text.size();
}
Expand Down Expand Up @@ -6207,6 +6260,24 @@ bool TextEdit::is_drawing_spaces() const {
return draw_spaces;
}

void TextEdit::set_draw_indent_guides(bool p_draw) {
draw_indent_guides = p_draw;
update();
}

bool TextEdit::is_drawing_indent_guides(bool p_draw) {
return draw_indent_guides;
}

void TextEdit::set_highlight_active_indent_guide(bool p_draw) {
highlight_active_indent_guide = p_draw;
update();
}

bool TextEdit::get_highlight_active_indent_guide() {
return highlight_active_indent_guide;
}

void TextEdit::set_override_selected_font_color(bool p_override_selected_font_color) {
override_selected_font_color = p_override_selected_font_color;
}
Expand Down Expand Up @@ -7163,6 +7234,8 @@ TextEdit::TextEdit() {
setting_row = false;
draw_tabs = false;
draw_spaces = false;
draw_indent_guides = false;
highlight_active_indent_guide = false;
override_selected_font_color = false;
draw_caret = true;
max_chars = 0;
Expand Down
10 changes: 10 additions & 0 deletions scene/gui/text_edit.h
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,8 @@ class TextEdit : public Control {
Color code_folding_color;
Color current_line_color;
Color line_length_guideline_color;
Color indent_guide_color;
Color indent_active_guide_color;
Color brace_mismatch_color;
Color word_highlighted_color;
Color search_result_color;
Expand Down Expand Up @@ -357,6 +359,8 @@ class TextEdit : public Control {
bool setting_row;
bool draw_tabs;
bool draw_spaces;
bool draw_indent_guides;
bool highlight_active_indent_guide;
bool override_selected_font_color;
bool cursor_changed_dirty;
bool text_changed_dirty;
Expand Down Expand Up @@ -616,6 +620,8 @@ class TextEdit : public Control {
void fold_line(int p_line);
void unfold_line(int p_line);
void toggle_fold_line(int p_line);
int get_line_parent_fold(int p_line);
int get_fold_last_line(int p_start_line);

String get_text();
String get_line(int line) const;
Expand Down Expand Up @@ -717,6 +723,10 @@ class TextEdit : public Control {
bool is_drawing_tabs() const;
void set_draw_spaces(bool p_draw);
bool is_drawing_spaces() const;
void set_draw_indent_guides(bool p_draw);
bool is_drawing_indent_guides(bool p_draw);
void set_highlight_active_indent_guide(bool p_draw);
bool get_highlight_active_indent_guide();
void set_override_selected_font_color(bool p_override_selected_font_color);
bool is_overriding_selected_font_color() const;

Expand Down