Add mutliple Caret support to TextEdit

This commit is contained in:
Paulb23 2022-06-03 17:47:37 +01:00
parent 7dd3857f7e
commit 4a9d4e3dad
5 changed files with 2694 additions and 1339 deletions

View File

@ -609,7 +609,7 @@ Control::CursorShape CodeEdit::get_cursor_shape(const Point2 &p_pos) const {
/* Text manipulation */ /* Text manipulation */
// Overridable actions // Overridable actions
void CodeEdit::_handle_unicode_input_internal(const uint32_t p_unicode) { void CodeEdit::_handle_unicode_input_internal(const uint32_t p_unicode, int p_caret) {
bool had_selection = has_selection(); bool had_selection = has_selection();
String selection_text = (had_selection ? get_selected_text() : ""); String selection_text = (had_selection ? get_selected_text() : "");
@ -674,7 +674,7 @@ void CodeEdit::_handle_unicode_input_internal(const uint32_t p_unicode) {
} }
} }
void CodeEdit::_backspace_internal() { void CodeEdit::_backspace_internal(int p_caret) {
if (!is_editable()) { if (!is_editable()) {
return; return;
} }

View File

@ -261,8 +261,8 @@ protected:
/* Text manipulation */ /* Text manipulation */
// Overridable actions // Overridable actions
virtual void _handle_unicode_input_internal(const uint32_t p_unicode) override; virtual void _handle_unicode_input_internal(const uint32_t p_unicode, int p_caret) override;
virtual void _backspace_internal() override; virtual void _backspace_internal(int p_caret) override;
GDVIRTUAL1(_confirm_code_completion, bool) GDVIRTUAL1(_confirm_code_completion, bool)
GDVIRTUAL1(_request_code_completion, bool) GDVIRTUAL1(_request_code_completion, bool)

File diff suppressed because it is too large Load Diff

View File

@ -42,6 +42,14 @@ class TextEdit : public Control {
GDCLASS(TextEdit, Control); GDCLASS(TextEdit, Control);
public: public:
/* Edit Actions. */
enum EditAction {
ACTION_NONE,
ACTION_TYPING,
ACTION_BACKSPACE,
ACTION_DELETE,
};
/* Caret. */ /* Caret. */
enum CaretType { enum CaretType {
CARET_TYPE_LINE, CARET_TYPE_LINE,
@ -299,12 +307,15 @@ private:
Key _get_menu_action_accelerator(const String &p_action); Key _get_menu_action_accelerator(const String &p_action);
/* Versioning */ /* Versioning */
struct Caret;
struct TextOperation { struct TextOperation {
enum Type { enum Type {
TYPE_NONE, TYPE_NONE,
TYPE_INSERT, TYPE_INSERT,
TYPE_REMOVE TYPE_REMOVE
}; };
Vector<Caret> start_carets;
Vector<Caret> end_carets;
Type type = TYPE_NONE; Type type = TYPE_NONE;
int from_line = 0; int from_line = 0;
@ -321,6 +332,10 @@ private:
bool undo_enabled = true; bool undo_enabled = true;
int undo_stack_max_size = 50; int undo_stack_max_size = 50;
EditAction current_action = EditAction::ACTION_NONE;
bool pending_action_end = false;
bool in_action = false;
int complex_operation_count = 0; int complex_operation_count = 0;
bool next_operation_is_complex = false; bool next_operation_is_complex = false;
@ -385,10 +400,15 @@ private:
int last_fit_x = 0; int last_fit_x = 0;
int line = 0; int line = 0;
int column = 0; int column = 0;
} caret; };
// Vector containing all the carets, index '0' is the "main caret" and should never be removed.
Vector<Caret> carets;
Vector<int> caret_index_edit_order;
bool setting_caret_line = false; bool setting_caret_line = false;
bool caret_pos_dirty = false; bool caret_pos_dirty = false;
bool caret_index_edit_dirty = true;
Color caret_color = Color(1, 1, 1); Color caret_color = Color(1, 1, 1);
Color caret_background_color = Color(0, 0, 0); Color caret_background_color = Color(0, 0, 0);
@ -404,6 +424,8 @@ private:
bool caret_mid_grapheme_enabled = true; bool caret_mid_grapheme_enabled = true;
bool multi_carets_enabled = true;
bool drag_action = false; bool drag_action = false;
bool drag_caret_force_displayed = false; bool drag_caret_force_displayed = false;
@ -412,7 +434,7 @@ private:
void _reset_caret_blink_timer(); void _reset_caret_blink_timer();
void _toggle_draw_caret(); void _toggle_draw_caret();
int _get_column_x_offset_for_line(int p_char, int p_line) const; int _get_column_x_offset_for_line(int p_char, int p_line, int p_column) const;
/* Selection. */ /* Selection. */
SelectionMode selecting_mode = SelectionMode::SELECTION_MODE_NONE; SelectionMode selecting_mode = SelectionMode::SELECTION_MODE_NONE;
@ -437,8 +459,8 @@ private:
void _update_selection_mode_word(); void _update_selection_mode_word();
void _update_selection_mode_line(); void _update_selection_mode_line();
void _pre_shift_selection(); void _pre_shift_selection(int p_caret);
void _post_shift_selection(); void _post_shift_selection(int p_caret);
/* Line wrapping. */ /* Line wrapping. */
LineWrappingMode line_wrapping_mode = LineWrappingMode::LINE_WRAPPING_NONE; LineWrappingMode line_wrapping_mode = LineWrappingMode::LINE_WRAPPING_NONE;
@ -583,6 +605,17 @@ protected:
/* Internal API for CodeEdit, pending public API. */ /* Internal API for CodeEdit, pending public API. */
// brace matching // brace matching
struct BraceMatchingData {
int open_match_line = -1;
int open_match_column = -1;
bool open_matching = false;
bool open_mismatch = false;
int close_match_line = -1;
int close_match_column = -1;
bool close_matching = false;
bool close_mismatch = false;
};
bool highlight_matching_braces_enabled = false; bool highlight_matching_braces_enabled = false;
Color brace_mismatch_color; Color brace_mismatch_color;
@ -607,20 +640,20 @@ protected:
/* Text manipulation */ /* Text manipulation */
// Overridable actions // Overridable actions
virtual void _handle_unicode_input_internal(const uint32_t p_unicode); virtual void _handle_unicode_input_internal(const uint32_t p_unicode, int p_caret);
virtual void _backspace_internal(); virtual void _backspace_internal(int p_caret);
virtual void _cut_internal(); virtual void _cut_internal(int p_caret);
virtual void _copy_internal(); virtual void _copy_internal(int p_caret);
virtual void _paste_internal(); virtual void _paste_internal(int p_caret);
virtual void _paste_primary_clipboard_internal(); virtual void _paste_primary_clipboard_internal(int p_caret);
GDVIRTUAL1(_handle_unicode_input, int) GDVIRTUAL2(_handle_unicode_input, int, int)
GDVIRTUAL0(_backspace) GDVIRTUAL1(_backspace, int)
GDVIRTUAL0(_cut) GDVIRTUAL1(_cut, int)
GDVIRTUAL0(_copy) GDVIRTUAL1(_copy, int)
GDVIRTUAL0(_paste) GDVIRTUAL1(_paste, int)
GDVIRTUAL0(_paste_primary_clipboard) GDVIRTUAL1(_paste_primary_clipboard, int)
public: public:
/* General overrides. */ /* General overrides. */
@ -696,7 +729,7 @@ public:
void swap_lines(int p_from_line, int p_to_line); void swap_lines(int p_from_line, int p_to_line);
void insert_line_at(int p_at, const String &p_text); void insert_line_at(int p_at, const String &p_text);
void insert_text_at_caret(const String &p_text); void insert_text_at_caret(const String &p_text, int p_caret = -1);
void remove_text(int p_from_line, int p_from_column, int p_to_line, int p_to_column); void remove_text(int p_from_line, int p_from_column, int p_to_line, int p_to_column);
@ -705,13 +738,13 @@ public:
Point2i get_next_visible_line_index_offset_from(int p_line_from, int p_wrap_index_from, int p_visible_amount) const; Point2i get_next_visible_line_index_offset_from(int p_line_from, int p_wrap_index_from, int p_visible_amount) const;
// Overridable actions // Overridable actions
void handle_unicode_input(const uint32_t p_unicode); void handle_unicode_input(const uint32_t p_unicode, int p_caret = -1);
void backspace(); void backspace(int p_caret = -1);
void cut(); void cut(int p_caret = -1);
void copy(); void copy(int p_caret = -1);
void paste(); void paste(int p_caret = -1);
void paste_primary_clipboard(); void paste_primary_clipboard(int p_caret = -1);
// Context menu. // Context menu.
PopupMenu *get_menu() const; PopupMenu *get_menu() const;
@ -719,6 +752,10 @@ public:
void menu_option(int p_option); void menu_option(int p_option);
/* Versioning */ /* Versioning */
void start_action(EditAction p_action);
void end_action();
EditAction get_current_action() const;
void begin_complex_operation(); void begin_complex_operation();
void end_complex_operation(); void end_complex_operation();
@ -753,7 +790,7 @@ public:
int get_minimap_line_at_pos(const Point2i &p_pos) const; int get_minimap_line_at_pos(const Point2i &p_pos) const;
bool is_dragging_cursor() const; bool is_dragging_cursor() const;
bool is_mouse_over_selection(bool p_edges = true) const; bool is_mouse_over_selection(bool p_edges = true, int p_caret = -1) const;
/* Caret */ /* Caret */
void set_caret_type(CaretType p_type); void set_caret_type(CaretType p_type);
@ -771,18 +808,30 @@ public:
void set_caret_mid_grapheme_enabled(const bool p_enabled); void set_caret_mid_grapheme_enabled(const bool p_enabled);
bool is_caret_mid_grapheme_enabled() const; bool is_caret_mid_grapheme_enabled() const;
bool is_caret_visible() const; void set_multiple_carets_enabled(bool p_enabled);
Point2 get_caret_draw_pos() const; bool is_multiple_carets_enabled() const;
void set_caret_line(int p_line, bool p_adjust_viewport = true, bool p_can_be_hidden = true, int p_wrap_index = 0); int add_caret(int p_line, int p_col);
int get_caret_line() const; void remove_caret(int p_caret);
void remove_secondary_carets();
void merge_overlapping_carets();
int get_caret_count() const;
void set_caret_column(int p_col, bool p_adjust_viewport = true); Vector<int> get_caret_index_edit_order();
int get_caret_column() const; void adjust_carets_after_edit(int p_caret, int p_from_line, int p_from_col, int p_to_line, int p_to_col);
int get_caret_wrap_index() const; bool is_caret_visible(int p_caret = 0) const;
Point2 get_caret_draw_pos(int p_caret = 0) const;
String get_word_under_caret() const; void set_caret_line(int p_line, bool p_adjust_viewport = true, bool p_can_be_hidden = true, int p_wrap_index = 0, int p_caret = 0);
int get_caret_line(int p_caret = 0) const;
void set_caret_column(int p_col, bool p_adjust_viewport = true, int p_caret = 0);
int get_caret_column(int p_caret = 0) const;
int get_caret_wrap_index(int p_caret = 0) const;
String get_word_under_caret(int p_caret = -1) const;
/* Selection. */ /* Selection. */
void set_selecting_enabled(const bool p_enabled); void set_selecting_enabled(const bool p_enabled);
@ -797,27 +846,27 @@ public:
void set_override_selected_font_color(bool p_override_selected_font_color); void set_override_selected_font_color(bool p_override_selected_font_color);
bool is_overriding_selected_font_color() const; bool is_overriding_selected_font_color() const;
void set_selection_mode(SelectionMode p_mode, int p_line = -1, int p_column = -1); void set_selection_mode(SelectionMode p_mode, int p_line = -1, int p_column = -1, int p_caret = 0);
SelectionMode get_selection_mode() const; SelectionMode get_selection_mode() const;
void select_all(); void select_all();
void select_word_under_caret(); void select_word_under_caret(int p_caret = -1);
void select(int p_from_line, int p_from_column, int p_to_line, int p_to_column); void select(int p_from_line, int p_from_column, int p_to_line, int p_to_column, int p_caret = 0);
bool has_selection() const; bool has_selection(int p_caret = -1) const;
String get_selected_text() const; String get_selected_text(int p_caret = -1);
int get_selection_line() const; int get_selection_line(int p_caret = 0) const;
int get_selection_column() const; int get_selection_column(int p_caret = 0) const;
int get_selection_from_line() const; int get_selection_from_line(int p_caret = 0) const;
int get_selection_from_column() const; int get_selection_from_column(int p_caret = 0) const;
int get_selection_to_line() const; int get_selection_to_line(int p_caret = 0) const;
int get_selection_to_column() const; int get_selection_to_column(int p_caret = 0) const;
void deselect(); void deselect(int p_caret = -1);
void delete_selection(); void delete_selection(int p_caret = -1);
/* Line wrapping. */ /* Line wrapping. */
void set_line_wrapping_mode(LineWrappingMode p_wrapping_mode); void set_line_wrapping_mode(LineWrappingMode p_wrapping_mode);
@ -866,8 +915,8 @@ public:
int get_total_visible_line_count() const; int get_total_visible_line_count() const;
// Auto Adjust // Auto Adjust
void adjust_viewport_to_caret(); void adjust_viewport_to_caret(int p_caret = 0);
void center_viewport_to_caret(); void center_viewport_to_caret(int p_caret = 0);
// Minimap // Minimap
void set_draw_minimap(bool p_enabled); void set_draw_minimap(bool p_enabled);
@ -949,6 +998,7 @@ public:
TextEdit(const String &p_placeholder = String()); TextEdit(const String &p_placeholder = String());
}; };
VARIANT_ENUM_CAST(TextEdit::EditAction);
VARIANT_ENUM_CAST(TextEdit::CaretType); VARIANT_ENUM_CAST(TextEdit::CaretType);
VARIANT_ENUM_CAST(TextEdit::LineWrappingMode); VARIANT_ENUM_CAST(TextEdit::LineWrappingMode);
VARIANT_ENUM_CAST(TextEdit::SelectionMode); VARIANT_ENUM_CAST(TextEdit::SelectionMode);

File diff suppressed because it is too large Load Diff