summaryrefslogtreecommitdiff
path: root/scene
diff options
context:
space:
mode:
authorPaulb23 <p_batty@hotmail.co.uk>2021-07-09 11:52:49 +0100
committerPaulb23 <p_batty@hotmail.co.uk>2021-08-12 09:29:16 +0100
commit7e70f9e0b9696fab55e2d0570c6bdc8b07c14462 (patch)
tree7a5dba0fad93df8d9e3d8c44d7111949d756299b /scene
parentd5dcaee4c5b41faca64f02888b152f7f05c4a20b (diff)
Expose and cleanup TextEdit line wrap API
Diffstat (limited to 'scene')
-rw-r--r--scene/gui/code_edit.cpp8
-rw-r--r--scene/gui/text_edit.cpp306
-rw-r--r--scene/gui/text_edit.h59
3 files changed, 202 insertions, 171 deletions
diff --git a/scene/gui/code_edit.cpp b/scene/gui/code_edit.cpp
index 1e2d601bde..6528e90f30 100644
--- a/scene/gui/code_edit.cpp
+++ b/scene/gui/code_edit.cpp
@@ -295,8 +295,8 @@ void CodeEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
if (mb->get_button_index() == MOUSE_BUTTON_LEFT) {
if (is_line_folded(line)) {
- int wrap_index = get_line_wrap_index_at_col(line, col);
- if (wrap_index == times_line_wraps(line)) {
+ int wrap_index = get_line_wrap_index_at_column(line, col);
+ if (wrap_index == get_line_wrap_count(line)) {
int eol_icon_width = cache.folded_eol_icon->get_width();
int left_margin = get_total_gutter_width() + eol_icon_width + get_line_width(line, wrap_index) - get_h_scroll();
if (mpos.x > left_margin && mpos.x <= left_margin + eol_icon_width + 3) {
@@ -531,8 +531,8 @@ Control::CursorShape CodeEdit::get_cursor_shape(const Point2 &p_pos) const {
_get_mouse_pos(p_pos, line, col);
if (is_line_folded(line)) {
- int wrap_index = get_line_wrap_index_at_col(line, col);
- if (wrap_index == times_line_wraps(line)) {
+ int wrap_index = get_line_wrap_index_at_column(line, col);
+ if (wrap_index == get_line_wrap_count(line)) {
int eol_icon_width = cache.folded_eol_icon->get_width();
int left_margin = get_total_gutter_width() + eol_icon_width + get_line_width(line, wrap_index) - get_h_scroll();
if (p_pos.x > left_margin && p_pos.x <= left_margin + eol_icon_width + 3) {
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index 8e624140f2..e77c8188cc 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -295,7 +295,7 @@ void TextEdit::_update_scrollbars() {
v_scroll->hide();
}
- if (total_width > visible_width && !is_wrap_enabled()) {
+ if (total_width > visible_width && get_line_wrapping_mode() == LineWrappingMode::LINE_WRAPPING_NONE) {
h_scroll->show();
h_scroll->set_max(total_width);
h_scroll->set_page(visible_width);
@@ -495,11 +495,11 @@ void TextEdit::_notification(int p_what) {
if (text_changed_dirty) {
MessageQueue::get_singleton()->push_call(this, "_text_changed_emit");
}
- _update_wrap_at(true);
+ _update_wrap_at_column(true);
} break;
case NOTIFICATION_RESIZED: {
_update_scrollbars();
- _update_wrap_at();
+ _update_wrap_at_column();
} break;
case NOTIFICATION_VISIBILITY_CHANGED: {
if (is_visible()) {
@@ -511,7 +511,7 @@ void TextEdit::_notification(int p_what) {
case NOTIFICATION_TRANSLATION_CHANGED:
case NOTIFICATION_THEME_CHANGED: {
_update_caches();
- _update_wrap_at(true);
+ _update_wrap_at_column(true);
} break;
case NOTIFICATION_WM_WINDOW_FOCUS_IN: {
window_has_focus = true;
@@ -748,7 +748,7 @@ void TextEdit::_notification(int p_what) {
int first_visible_line = get_first_visible_line() - 1;
int draw_amount = visible_rows + (smooth_scroll_enabled ? 1 : 0);
- draw_amount += times_line_wraps(first_visible_line + 1);
+ draw_amount += get_line_wrap_count(first_visible_line + 1);
// minimap
if (draw_minimap) {
@@ -769,7 +769,7 @@ void TextEdit::_notification(int p_what) {
minimap_line -= num_lines_from_rows(first_visible_line, 0, -num_lines_before, wi);
minimap_line -= (minimap_line > 0 && smooth_scroll_enabled ? 1 : 0);
}
- int minimap_draw_amount = minimap_visible_lines + times_line_wraps(minimap_line + 1);
+ int minimap_draw_amount = minimap_visible_lines + get_line_wrap_count(minimap_line + 1);
// draw the minimap
Color viewport_color = (cache.background_color.get_v() < 0.5) ? Color(1, 1, 1, 0.1) : Color(0, 0, 0, 0.1);
@@ -805,8 +805,8 @@ void TextEdit::_notification(int p_what) {
current_color = cache.font_readonly_color;
}
- Vector<String> wrap_rows = get_wrap_rows_text(minimap_line);
- int line_wrap_amount = times_line_wraps(minimap_line);
+ Vector<String> wrap_rows = get_line_wrapped_text(minimap_line);
+ int line_wrap_amount = get_line_wrap_count(minimap_line);
int last_wrap_column = 0;
for (int line_wrap_index = 0; line_wrap_index < line_wrap_amount + 1; line_wrap_index++) {
@@ -819,7 +819,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;
- if (indent_px >= wrap_at) {
+ if (indent_px >= wrap_at_column) {
indent_px = 0;
}
indent_px = minimap_char_size.x * indent_px;
@@ -947,8 +947,8 @@ void TextEdit::_notification(int p_what) {
const Ref<TextParagraph> ldata = text.get_line_data(line);
- Vector<String> wrap_rows = get_wrap_rows_text(line);
- int line_wrap_amount = times_line_wraps(line);
+ Vector<String> wrap_rows = get_line_wrapped_text(line);
+ int line_wrap_amount = get_line_wrap_count(line);
for (int line_wrap_index = 0; line_wrap_index <= line_wrap_amount; line_wrap_index++) {
if (line_wrap_index != 0) {
@@ -1659,8 +1659,8 @@ void TextEdit::_move_caret_up(bool p_select) {
set_caret_column(0);
} else {
int new_line = caret.line - num_lines_from(caret.line - 1, -1);
- if (line_wraps(new_line)) {
- set_caret_line(new_line, true, false, times_line_wraps(new_line));
+ if (is_line_wrapped(new_line)) {
+ set_caret_line(new_line, true, false, get_line_wrap_count(new_line));
} else {
set_caret_line(new_line, true, false);
}
@@ -1679,7 +1679,7 @@ void TextEdit::_move_caret_down(bool p_select) {
}
int cur_wrap_index = get_caret_wrap_index();
- if (cur_wrap_index < times_line_wraps(caret.line)) {
+ if (cur_wrap_index < get_line_wrap_count(caret.line)) {
set_caret_line(caret.line, true, false, cur_wrap_index + 1);
} else if (caret.line == get_last_unhidden_line()) {
set_caret_column(text[caret.line].length());
@@ -1701,7 +1701,7 @@ void TextEdit::_move_caret_to_line_start(bool p_select) {
}
// Move caret column to start of wrapped row and then to start of text.
- Vector<String> rows = get_wrap_rows_text(caret.line);
+ Vector<String> rows = get_line_wrapped_text(caret.line);
int wi = get_caret_wrap_index();
int row_start_col = 0;
for (int i = 0; i < wi; i++) {
@@ -1740,7 +1740,7 @@ void TextEdit::_move_caret_to_line_end(bool p_select) {
}
// Move caret column to end of wrapped row and then to end of text.
- Vector<String> rows = get_wrap_rows_text(caret.line);
+ Vector<String> rows = get_line_wrapped_text(caret.line);
int wi = get_caret_wrap_index();
int row_end_col = -1;
for (int i = 0; i < wi + 1; i++) {
@@ -1929,7 +1929,7 @@ void TextEdit::_get_mouse_pos(const Point2i &p_mouse, int &r_row, int &r_col) co
int row = first_vis_line + Math::floor(rows);
int wrap_index = 0;
- if (is_wrap_enabled() || is_hiding_enabled()) {
+ if (get_line_wrapping_mode() != LineWrappingMode::LINE_WRAPPING_NONE || is_hiding_enabled()) {
int f_ofs = num_lines_from_rows(first_vis_line, caret.wrap_ofs, rows + (1 * SGN(rows)), wrap_index) - 1;
if (rows < 0) {
row = first_vis_line - f_ofs;
@@ -1951,9 +1951,9 @@ void TextEdit::_get_mouse_pos(const Point2i &p_mouse, int &r_row, int &r_col) co
int colx = p_mouse.x - (cache.style_normal->get_margin(SIDE_LEFT) + gutters_width + gutter_padding);
colx += caret.x_ofs;
col = get_char_pos_for_line(colx, row, wrap_index);
- if (is_wrap_enabled() && wrap_index < times_line_wraps(row)) {
+ if (get_line_wrapping_mode() != LineWrappingMode::LINE_WRAPPING_NONE && wrap_index < get_line_wrap_count(row)) {
// Move back one if we are at the end of the row.
- Vector<String> rows2 = get_wrap_rows_text(row);
+ Vector<String> rows2 = get_line_wrapped_text(row);
int row_end_col = 0;
for (int i = 0; i < wrap_index + 1; i++) {
row_end_col += rows2[i].length();
@@ -1985,7 +1985,7 @@ void TextEdit::_get_minimap_mouse_row(const Point2i &p_mouse, int &r_row) const
int visible_rows = get_visible_rows() + 1;
int first_visible_line = get_first_visible_line() - 1;
int draw_amount = visible_rows + (smooth_scroll_enabled ? 1 : 0);
- draw_amount += times_line_wraps(first_visible_line + 1);
+ draw_amount += get_line_wrap_count(first_visible_line + 1);
int minimap_line_height = (minimap_char_size.y + minimap_line_spacing);
// calculate viewport size and y offset
@@ -2007,7 +2007,7 @@ void TextEdit::_get_minimap_mouse_row(const Point2i &p_mouse, int &r_row) const
int row = minimap_line + Math::floor(rows);
int wrap_index = 0;
- if (is_wrap_enabled() || is_hiding_enabled()) {
+ if (get_line_wrapping_mode() != LineWrappingMode::LINE_WRAPPING_NONE || is_hiding_enabled()) {
int f_ofs = num_lines_from_rows(minimap_line, caret.wrap_ofs, rows + (1 * SGN(rows)), wrap_index) - 1;
if (rows < 0) {
row = minimap_line - f_ofs;
@@ -2894,7 +2894,7 @@ int TextEdit::_get_minimap_visible_rows() const {
int TextEdit::get_total_visible_rows() const {
// Returns the total amount of rows we need in the editor.
// This skips hidden lines and counts each wrapping of a line.
- if (!is_hiding_enabled() && !is_wrap_enabled()) {
+ if (!is_hiding_enabled() && get_line_wrapping_mode() == LineWrappingMode::LINE_WRAPPING_NONE) {
return text.size();
}
@@ -2902,35 +2902,12 @@ int TextEdit::get_total_visible_rows() const {
for (int i = 0; i < text.size(); i++) {
if (!text.is_hidden(i)) {
total_rows++;
- total_rows += times_line_wraps(i);
+ total_rows += get_line_wrap_count(i);
}
}
return total_rows;
}
-void TextEdit::_update_wrap_at(bool p_force) {
- int new_wrap_at = get_size().width - cache.style_normal->get_minimum_size().width - gutters_width - gutter_padding;
- if (draw_minimap) {
- new_wrap_at -= minimap_width;
- }
- if (v_scroll->is_visible_in_tree()) {
- new_wrap_at -= v_scroll->get_combined_minimum_size().width;
- }
- new_wrap_at -= wrap_right_offset; // Give it a little more space.
-
- if ((wrap_at != new_wrap_at) || p_force) {
- wrap_at = new_wrap_at;
- if (wrap_enabled) {
- text.set_width(wrap_at);
- } else {
- text.set_width(-1);
- }
- text.invalidate_all_lines();
- }
-
- _update_caret_wrap_offset();
-}
-
void TextEdit::adjust_viewport_to_caret() {
// Make sure Caret is visible on the screen.
scrolling = false;
@@ -2958,7 +2935,7 @@ void TextEdit::adjust_viewport_to_caret() {
}
visible_width -= 20; // Give it a little more space.
- if (!is_wrap_enabled()) {
+ if (get_line_wrapping_mode() == LineWrappingMode::LINE_WRAPPING_NONE) {
// Adjust x offset.
Vector2i caret_pos;
@@ -3007,7 +2984,7 @@ void TextEdit::center_viewport_to_caret() {
}
visible_width -= 20; // Give it a little more space.
- if (is_wrap_enabled()) {
+ if (get_line_wrapping_mode() != LineWrappingMode::LINE_WRAPPING_NONE) {
// Center x offset.
Vector2i caret_pos;
@@ -3045,74 +3022,6 @@ void TextEdit::center_viewport_to_caret() {
update();
}
-void TextEdit::_update_caret_wrap_offset() {
- int first_vis_line = get_first_visible_line();
- if (line_wraps(first_vis_line)) {
- caret.wrap_ofs = MIN(caret.wrap_ofs, times_line_wraps(first_vis_line));
- } else {
- caret.wrap_ofs = 0;
- }
- set_line_as_first_visible(caret.line_ofs, caret.wrap_ofs);
-}
-
-bool TextEdit::line_wraps(int line) const {
- ERR_FAIL_INDEX_V(line, text.size(), 0);
- if (!is_wrap_enabled()) {
- return false;
- }
- return text.get_line_wrap_amount(line) > 0;
-}
-
-int TextEdit::times_line_wraps(int line) const {
- ERR_FAIL_INDEX_V(line, text.size(), 0);
-
- if (!line_wraps(line)) {
- return 0;
- }
-
- return text.get_line_wrap_amount(line);
-}
-
-Vector<String> TextEdit::get_wrap_rows_text(int p_line) const {
- ERR_FAIL_INDEX_V(p_line, text.size(), Vector<String>());
-
- Vector<String> lines;
- if (!line_wraps(p_line)) {
- lines.push_back(text[p_line]);
- return lines;
- }
-
- const String &line_text = text[p_line];
- Vector<Vector2i> line_ranges = text.get_line_wrap_ranges(p_line);
- for (int i = 0; i < line_ranges.size(); i++) {
- lines.push_back(line_text.substr(line_ranges[i].x, line_ranges[i].y - line_ranges[i].x));
- }
-
- return lines;
-}
-
-int TextEdit::get_line_wrap_index_at_col(int p_line, int p_column) const {
- ERR_FAIL_INDEX_V(p_line, text.size(), 0);
-
- if (!line_wraps(p_line)) {
- return 0;
- }
-
- // Loop through wraps in the line text until we get to the column.
- int wrap_index = 0;
- int col = 0;
- Vector<String> rows = get_wrap_rows_text(p_line);
- for (int i = 0; i < rows.size(); i++) {
- wrap_index = i;
- String s = rows[wrap_index];
- col += s.length();
- if (col > p_column) {
- break;
- }
- }
- return wrap_index;
-}
-
TextEdit::SelectionMode TextEdit::get_selection_mode() const {
return selection.selecting_mode;
}
@@ -3158,14 +3067,14 @@ void TextEdit::_scroll_moved(double p_to_val) {
for (n_line = 0; n_line < text.size(); n_line++) {
if (!is_line_hidden(n_line)) {
sc++;
- sc += times_line_wraps(n_line);
+ sc += get_line_wrap_count(n_line);
if (sc > v_scroll_i) {
break;
}
}
}
n_line = MIN(n_line, text.size() - 1);
- int line_wrap_amount = times_line_wraps(n_line);
+ int line_wrap_amount = get_line_wrap_count(n_line);
int wi = line_wrap_amount - (sc - v_scroll_i - 1);
wi = CLAMP(wi, 0, line_wrap_amount);
@@ -3460,17 +3369,6 @@ bool TextEdit::is_readonly() const {
return readonly;
}
-void TextEdit::set_wrap_enabled(bool p_wrap_enabled) {
- if (wrap_enabled != p_wrap_enabled) {
- wrap_enabled = p_wrap_enabled;
- _update_wrap_at(true);
- }
-}
-
-bool TextEdit::is_wrap_enabled() const {
- return wrap_enabled;
-}
-
void TextEdit::_update_caches() {
/* Caret */
caret_color = get_theme_color(SNAME("caret_color"));
@@ -3661,8 +3559,8 @@ void TextEdit::set_caret_line(int p_line, bool p_adjust_viewport, bool p_can_be_
caret.line = p_line;
int n_col = get_char_pos_for_line(caret.last_fit_x, p_line, p_wrap_index);
- if (n_col != 0 && is_wrap_enabled() && p_wrap_index < times_line_wraps(p_line)) {
- Vector<String> rows = get_wrap_rows_text(p_line);
+ if (n_col != 0 && get_line_wrapping_mode() != LineWrappingMode::LINE_WRAPPING_NONE && p_wrap_index < get_line_wrap_count(p_line)) {
+ Vector<String> rows = get_line_wrapped_text(p_line);
int row_end_col = 0;
for (int i = 0; i < p_wrap_index + 1; i++) {
row_end_col += rows[i].length();
@@ -3720,7 +3618,77 @@ int TextEdit::get_caret_column() const {
}
int TextEdit::get_caret_wrap_index() const {
- return get_line_wrap_index_at_col(caret.line, caret.column);
+ return get_line_wrap_index_at_column(caret.line, caret.column);
+}
+
+/* line wrapping. */
+void TextEdit::set_line_wrapping_mode(LineWrappingMode p_wrapping_mode) {
+ if (line_wrapping_mode != p_wrapping_mode) {
+ line_wrapping_mode = p_wrapping_mode;
+ _update_wrap_at_column(true);
+ }
+}
+
+TextEdit::LineWrappingMode TextEdit::get_line_wrapping_mode() const {
+ return line_wrapping_mode;
+}
+
+bool TextEdit::is_line_wrapped(int p_line) const {
+ ERR_FAIL_INDEX_V(p_line, text.size(), 0);
+ if (get_line_wrapping_mode() == LineWrappingMode::LINE_WRAPPING_NONE) {
+ return false;
+ }
+ return text.get_line_wrap_amount(p_line) > 0;
+}
+
+int TextEdit::get_line_wrap_count(int p_line) const {
+ ERR_FAIL_INDEX_V(p_line, text.size(), 0);
+
+ if (!is_line_wrapped(p_line)) {
+ return 0;
+ }
+
+ return text.get_line_wrap_amount(p_line);
+}
+
+int TextEdit::get_line_wrap_index_at_column(int p_line, int p_column) const {
+ ERR_FAIL_INDEX_V(p_line, text.size(), 0);
+
+ if (!is_line_wrapped(p_line)) {
+ return 0;
+ }
+
+ /* Loop through wraps in the line text until we get to the column. */
+ int wrap_index = 0;
+ int col = 0;
+ Vector<String> lines = get_line_wrapped_text(p_line);
+ for (int i = 0; i < lines.size(); i++) {
+ wrap_index = i;
+ String s = lines[wrap_index];
+ col += s.length();
+ if (col > p_column) {
+ break;
+ }
+ }
+ return wrap_index;
+}
+
+Vector<String> TextEdit::get_line_wrapped_text(int p_line) const {
+ ERR_FAIL_INDEX_V(p_line, text.size(), Vector<String>());
+
+ Vector<String> lines;
+ if (!is_line_wrapped(p_line)) {
+ lines.push_back(text[p_line]);
+ return lines;
+ }
+
+ const String &line_text = text[p_line];
+ Vector<Vector2i> line_ranges = text.get_line_wrap_ranges(p_line);
+ for (int i = 0; i < line_ranges.size(); i++) {
+ lines.push_back(line_text.substr(line_ranges[i].x, line_ranges[i].y - line_ranges[i].x));
+ }
+
+ return lines;
}
/* Syntax Highlighting. */
@@ -4384,7 +4352,7 @@ int TextEdit::num_lines_from_rows(int p_line_from, int p_wrap_index_from, int vi
wrap_index = 0;
ERR_FAIL_INDEX_V(p_line_from, text.size(), ABS(visible_amount));
- if (!is_hiding_enabled() && !is_wrap_enabled()) {
+ if (!is_hiding_enabled() && get_line_wrapping_mode() == LineWrappingMode::LINE_WRAPPING_NONE) {
return ABS(visible_amount);
}
@@ -4400,22 +4368,22 @@ int TextEdit::num_lines_from_rows(int p_line_from, int p_wrap_index_from, int vi
num_total++;
if (!is_line_hidden(i)) {
num_visible++;
- num_visible += times_line_wraps(i);
+ num_visible += get_line_wrap_count(i);
}
if (num_visible >= visible_amount) {
break;
}
}
- wrap_index = times_line_wraps(MIN(i, text.size() - 1)) - MAX(0, num_visible - visible_amount);
+ wrap_index = get_line_wrap_count(MIN(i, text.size() - 1)) - MAX(0, num_visible - visible_amount);
} else {
visible_amount = ABS(visible_amount);
int i;
- num_visible -= times_line_wraps(p_line_from) - p_wrap_index_from;
+ num_visible -= get_line_wrap_count(p_line_from) - p_wrap_index_from;
for (i = p_line_from; i >= 0; i--) {
num_total++;
if (!is_line_hidden(i)) {
num_visible++;
- num_visible += times_line_wraps(i);
+ num_visible += get_line_wrap_count(i);
}
if (num_visible >= visible_amount) {
break;
@@ -4709,7 +4677,7 @@ void TextEdit::tag_saved_version() {
}
double TextEdit::get_scroll_pos_for_line(int p_line, int p_wrap_index) const {
- if (!is_wrap_enabled() && !is_hiding_enabled()) {
+ if (get_line_wrapping_mode() == LineWrappingMode::LINE_WRAPPING_NONE && !is_hiding_enabled()) {
return p_line;
}
@@ -4719,7 +4687,7 @@ double TextEdit::get_scroll_pos_for_line(int p_line, int p_wrap_index) const {
for (int i = 0; i < to; i++) {
if (!text.is_hidden(i)) {
new_line_scroll_pos++;
- new_line_scroll_pos += times_line_wraps(i);
+ new_line_scroll_pos += get_line_wrap_count(i);
}
}
new_line_scroll_pos += p_wrap_index;
@@ -4918,7 +4886,7 @@ void TextEdit::insert_at(const String &p_text, int at) {
void TextEdit::set_draw_minimap(bool p_draw) {
if (draw_minimap != p_draw) {
draw_minimap = p_draw;
- _update_wrap_at();
+ _update_wrap_at_column();
}
update();
}
@@ -4930,7 +4898,7 @@ bool TextEdit::is_drawing_minimap() const {
void TextEdit::set_minimap_width(int p_minimap_width) {
if (minimap_width != p_minimap_width) {
minimap_width = p_minimap_width;
- _update_wrap_at();
+ _update_wrap_at_column();
}
update();
}
@@ -5197,7 +5165,6 @@ void TextEdit::_get_property_list(List<PropertyInfo> *p_list) const {
void TextEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("_gui_input"), &TextEdit::_gui_input);
ClassDB::bind_method(D_METHOD("_text_changed_emit"), &TextEdit::_text_changed_emit);
- ClassDB::bind_method(D_METHOD("_update_wrap_at", "force"), &TextEdit::_update_wrap_at, DEFVAL(false));
BIND_ENUM_CONSTANT(SEARCH_MATCH_CASE);
BIND_ENUM_CONSTANT(SEARCH_WHOLE_WORDS);
@@ -5248,8 +5215,6 @@ void TextEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_readonly", "enable"), &TextEdit::set_readonly);
ClassDB::bind_method(D_METHOD("is_readonly"), &TextEdit::is_readonly);
- ClassDB::bind_method(D_METHOD("set_wrap_enabled", "enable"), &TextEdit::set_wrap_enabled);
- ClassDB::bind_method(D_METHOD("is_wrap_enabled"), &TextEdit::is_wrap_enabled);
ClassDB::bind_method(D_METHOD("set_context_menu_enabled", "enable"), &TextEdit::set_context_menu_enabled);
ClassDB::bind_method(D_METHOD("is_context_menu_enabled"), &TextEdit::is_context_menu_enabled);
ClassDB::bind_method(D_METHOD("set_shortcut_keys_enabled", "enable"), &TextEdit::set_shortcut_keys_enabled);
@@ -5339,6 +5304,22 @@ void TextEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_caret_wrap_index"), &TextEdit::get_caret_wrap_index);
+ /* line wrapping. */
+ BIND_ENUM_CONSTANT(LINE_WRAPPING_NONE);
+ BIND_ENUM_CONSTANT(LINE_WRAPPING_BOUNDARY);
+
+ // internal.
+ ClassDB::bind_method(D_METHOD("_update_wrap_at_column", "force"), &TextEdit::_update_wrap_at_column, DEFVAL(false));
+
+ ClassDB::bind_method(D_METHOD("set_line_wrapping_mode", "mode"), &TextEdit::set_line_wrapping_mode);
+ ClassDB::bind_method(D_METHOD("get_line_wrapping_mode"), &TextEdit::get_line_wrapping_mode);
+
+ ClassDB::bind_method(D_METHOD("is_line_wrapped", "line"), &TextEdit::is_line_wrapped);
+ ClassDB::bind_method(D_METHOD("get_line_wrap_count", "line"), &TextEdit::get_line_wrap_count);
+ ClassDB::bind_method(D_METHOD("get_line_wrap_index_at_column", "line", "column"), &TextEdit::get_line_wrap_index_at_column);
+
+ ClassDB::bind_method(D_METHOD("get_line_wrapped_text", "line"), &TextEdit::get_line_wrapped_text);
+
/* Syntax Highlighting. */
ClassDB::bind_method(D_METHOD("set_syntax_highlighter", "syntax_highlighter"), &TextEdit::set_syntax_highlighter);
ClassDB::bind_method(D_METHOD("get_syntax_highlighter"), &TextEdit::get_syntax_highlighter);
@@ -5420,7 +5401,7 @@ void TextEdit::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "selecting_enabled"), "set_selecting_enabled", "is_selecting_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "smooth_scrolling"), "set_smooth_scroll_enable", "is_smooth_scroll_enabled");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "v_scroll_speed"), "set_v_scroll_speed", "get_v_scroll_speed");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "wrap_enabled"), "set_wrap_enabled", "is_wrap_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "wrap_mode", PROPERTY_HINT_ENUM, "None,Boundary"), "set_line_wrapping_mode", "get_line_wrapping_mode");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "scroll_vertical"), "set_v_scroll", "get_v_scroll");
ADD_PROPERTY(PropertyInfo(Variant::INT, "scroll_horizontal"), "set_h_scroll", "get_h_scroll");
@@ -5716,6 +5697,41 @@ void TextEdit::_toggle_draw_caret() {
}
}
+/* Line Wrapping */
+void TextEdit::_update_wrap_at_column(bool p_force) {
+ int new_wrap_at = get_size().width - cache.style_normal->get_minimum_size().width - gutters_width - gutter_padding;
+ if (draw_minimap) {
+ new_wrap_at -= minimap_width;
+ }
+ if (v_scroll->is_visible_in_tree()) {
+ new_wrap_at -= v_scroll->get_combined_minimum_size().width;
+ }
+ /* Give it a little more space. */
+ new_wrap_at -= wrap_right_offset;
+
+ if ((wrap_at_column != new_wrap_at) || p_force) {
+ wrap_at_column = new_wrap_at;
+ if (line_wrapping_mode) {
+ text.set_width(wrap_at_column);
+ } else {
+ text.set_width(-1);
+ }
+ text.invalidate_all_lines();
+ }
+
+ _update_caret_wrap_offset();
+}
+
+void TextEdit::_update_caret_wrap_offset() {
+ int first_vis_line = get_first_visible_line();
+ if (is_line_wrapped(first_vis_line)) {
+ caret.wrap_ofs = MIN(caret.wrap_ofs, get_line_wrap_count(first_vis_line));
+ } else {
+ caret.wrap_ofs = 0;
+ }
+ set_line_as_first_visible(caret.line_ofs, caret.wrap_ofs);
+}
+
TextEdit::TextEdit() {
clear();
set_focus_mode(FOCUS_ALL);
diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h
index 816718a0a3..9eb83981eb 100644
--- a/scene/gui/text_edit.h
+++ b/scene/gui/text_edit.h
@@ -48,12 +48,6 @@ public:
CARET_TYPE_BLOCK
};
- enum GutterType {
- GUTTER_TYPE_STRING,
- GUTTER_TYPE_ICON,
- GUTTER_TYPE_CUSTOM
- };
-
/* Selection */
enum SelectionMode {
SELECTION_MODE_NONE,
@@ -63,6 +57,19 @@ public:
SELECTION_MODE_LINE
};
+ /* Line Wrapping.*/
+ enum LineWrappingMode {
+ LINE_WRAPPING_NONE,
+ LINE_WRAPPING_BOUNDARY
+ };
+
+ /* Gutters. */
+ enum GutterType {
+ GUTTER_TYPE_STRING,
+ GUTTER_TYPE_ICON,
+ GUTTER_TYPE_CUSTOM
+ };
+
private:
struct GutterInfo {
GutterType type = GutterType::GUTTER_TYPE_STRING;
@@ -183,7 +190,7 @@ private:
/* Text manipulation */
String cut_copy_line = "";
- /* Caret */
+ /* Caret. */
struct Caret {
Point2 draw_pos;
bool visible = false;
@@ -217,6 +224,7 @@ private:
void _reset_caret_blink_timer();
void _toggle_draw_caret();
+ /* Selection. */
struct Selection {
SelectionMode selecting_mode = SelectionMode::SELECTION_MODE_NONE;
int selecting_line = 0;
@@ -236,6 +244,17 @@ private:
bool shiftclick_left = false;
} selection;
+ /* line wrapping. */
+ LineWrappingMode line_wrapping_mode = LineWrappingMode::LINE_WRAPPING_NONE;
+
+ int wrap_at_column = 0;
+ int wrap_right_offset = 10;
+
+ void _update_wrap_at_column(bool p_force = false);
+
+ void _update_caret_wrap_offset();
+
+ /* Syntax highlighting. */
Map<int, Dictionary> syntax_highlighting_cache;
struct TextOperation {
@@ -295,10 +314,6 @@ private:
bool window_has_focus = true;
- bool wrap_enabled = false;
- int wrap_at = 0;
- int wrap_right_offset = 10;
-
bool first_draw = true;
bool draw_tabs = false;
bool draw_spaces = false;
@@ -362,10 +377,6 @@ private:
int _get_minimap_visible_rows() const;
- void _update_caret_wrap_offset();
- void _update_wrap_at(bool p_force = false);
- Vector<String> get_wrap_rows_text(int p_line) const;
-
double get_scroll_pos_for_line(int p_line, int p_wrap_index = 0) const;
void set_line_as_first_visible(int p_line, int p_wrap_index = 0);
void set_line_as_center_visible(int p_line, int p_wrap_index = 0);
@@ -537,6 +548,16 @@ public:
int get_caret_wrap_index() const;
+ /* line wrapping. */
+ void set_line_wrapping_mode(LineWrappingMode p_wrapping_mode);
+ LineWrappingMode get_line_wrapping_mode() const;
+
+ bool is_line_wrapped(int p_line) const;
+ int get_line_wrap_count(int p_line) const;
+ int get_line_wrap_index_at_column(int p_line, int p_column) const;
+
+ Vector<String> get_line_wrapped_text(int p_line) const;
+
/* Syntax Highlighting. */
Ref<SyntaxHighlighter> get_syntax_highlighter();
void set_syntax_highlighter(Ref<SyntaxHighlighter> p_syntax_highlighter);
@@ -664,7 +685,6 @@ public:
void insert_at(const String &p_text, int at);
int get_line_count() const;
int get_line_width(int p_line, int p_wrap_offset = -1) const;
- int get_line_wrap_index_at_col(int p_line, int p_column) const;
void set_line_as_hidden(int p_line, bool p_hidden);
bool is_line_hidden(int p_line) const;
@@ -698,11 +718,6 @@ public:
void set_readonly(bool p_readonly);
bool is_readonly() const;
- void set_wrap_enabled(bool p_wrap_enabled);
- bool is_wrap_enabled() const;
- bool line_wraps(int line) const;
- int times_line_wraps(int line) const;
-
void clear();
void delete_selection();
@@ -799,8 +814,8 @@ public:
~TextEdit();
};
-
VARIANT_ENUM_CAST(TextEdit::CaretType);
+VARIANT_ENUM_CAST(TextEdit::LineWrappingMode);
VARIANT_ENUM_CAST(TextEdit::SelectionMode);
VARIANT_ENUM_CAST(TextEdit::GutterType);
VARIANT_ENUM_CAST(TextEdit::MenuItems);