1 | /**************************************************************************/ |
2 | /* text_edit.h */ |
3 | /**************************************************************************/ |
4 | /* This file is part of: */ |
5 | /* GODOT ENGINE */ |
6 | /* https://godotengine.org */ |
7 | /**************************************************************************/ |
8 | /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ |
9 | /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ |
10 | /* */ |
11 | /* Permission is hereby granted, free of charge, to any person obtaining */ |
12 | /* a copy of this software and associated documentation files (the */ |
13 | /* "Software"), to deal in the Software without restriction, including */ |
14 | /* without limitation the rights to use, copy, modify, merge, publish, */ |
15 | /* distribute, sublicense, and/or sell copies of the Software, and to */ |
16 | /* permit persons to whom the Software is furnished to do so, subject to */ |
17 | /* the following conditions: */ |
18 | /* */ |
19 | /* The above copyright notice and this permission notice shall be */ |
20 | /* included in all copies or substantial portions of the Software. */ |
21 | /* */ |
22 | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ |
23 | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ |
24 | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ |
25 | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ |
26 | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ |
27 | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ |
28 | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ |
29 | /**************************************************************************/ |
30 | |
31 | #ifndef TEXT_EDIT_H |
32 | #define TEXT_EDIT_H |
33 | |
34 | #include "scene/gui/control.h" |
35 | #include "scene/gui/popup_menu.h" |
36 | #include "scene/gui/scroll_bar.h" |
37 | #include "scene/main/timer.h" |
38 | #include "scene/resources/syntax_highlighter.h" |
39 | #include "scene/resources/text_paragraph.h" |
40 | |
41 | class TextEdit : public Control { |
42 | GDCLASS(TextEdit, Control); |
43 | |
44 | friend class CodeHighlighter; |
45 | |
46 | public: |
47 | /* Edit Actions. */ |
48 | enum EditAction { |
49 | ACTION_NONE, |
50 | ACTION_TYPING, |
51 | ACTION_BACKSPACE, |
52 | ACTION_DELETE, |
53 | }; |
54 | |
55 | /* Caret. */ |
56 | enum CaretType { |
57 | CARET_TYPE_LINE, |
58 | CARET_TYPE_BLOCK |
59 | }; |
60 | |
61 | /* Selection */ |
62 | enum SelectionMode { |
63 | SELECTION_MODE_NONE, |
64 | SELECTION_MODE_SHIFT, |
65 | SELECTION_MODE_POINTER, |
66 | SELECTION_MODE_WORD, |
67 | SELECTION_MODE_LINE |
68 | }; |
69 | |
70 | /* Line Wrapping.*/ |
71 | enum LineWrappingMode { |
72 | LINE_WRAPPING_NONE, |
73 | LINE_WRAPPING_BOUNDARY |
74 | }; |
75 | |
76 | /* Gutters. */ |
77 | enum GutterType { |
78 | GUTTER_TYPE_STRING, |
79 | GUTTER_TYPE_ICON, |
80 | GUTTER_TYPE_CUSTOM |
81 | }; |
82 | |
83 | /* Context Menu. */ |
84 | enum { |
85 | , |
86 | , |
87 | , |
88 | , |
89 | , |
90 | , |
91 | , |
92 | , |
93 | , |
94 | , |
95 | , |
96 | , |
97 | , |
98 | , |
99 | , |
100 | , |
101 | , |
102 | , |
103 | , |
104 | , |
105 | , |
106 | , |
107 | , |
108 | , |
109 | , |
110 | , |
111 | , |
112 | , |
113 | , |
114 | , |
115 | |
116 | |
117 | }; |
118 | |
119 | /* Search. */ |
120 | enum SearchFlags { |
121 | SEARCH_MATCH_CASE = 1, |
122 | SEARCH_WHOLE_WORDS = 2, |
123 | SEARCH_BACKWARDS = 4 |
124 | }; |
125 | |
126 | private: |
127 | struct GutterInfo { |
128 | GutterType type = GutterType::GUTTER_TYPE_STRING; |
129 | String name = "" ; |
130 | int width = 24; |
131 | bool draw = true; |
132 | bool clickable = false; |
133 | bool overwritable = false; |
134 | |
135 | Callable custom_draw_callback; |
136 | }; |
137 | |
138 | class Text { |
139 | public: |
140 | struct Gutter { |
141 | Variant metadata; |
142 | bool clickable = false; |
143 | |
144 | Ref<Texture2D> icon = Ref<Texture2D>(); |
145 | String text = "" ; |
146 | Color color = Color(1, 1, 1); |
147 | }; |
148 | |
149 | struct Line { |
150 | Vector<Gutter> gutters; |
151 | |
152 | String data; |
153 | Array bidi_override; |
154 | Ref<TextParagraph> data_buf; |
155 | |
156 | Color background_color = Color(0, 0, 0, 0); |
157 | bool hidden = false; |
158 | int height = 0; |
159 | int width = 0; |
160 | |
161 | Line() { |
162 | data_buf.instantiate(); |
163 | } |
164 | }; |
165 | |
166 | private: |
167 | bool is_dirty = false; |
168 | bool tab_size_dirty = false; |
169 | |
170 | mutable Vector<Line> text; |
171 | Ref<Font> font; |
172 | int font_size = -1; |
173 | int font_height = 0; |
174 | |
175 | String language; |
176 | TextServer::Direction direction = TextServer::DIRECTION_AUTO; |
177 | BitField<TextServer::LineBreakFlag> brk_flags = TextServer::BREAK_MANDATORY; |
178 | bool draw_control_chars = false; |
179 | |
180 | int line_height = -1; |
181 | int max_width = -1; |
182 | int width = -1; |
183 | |
184 | int tab_size = 4; |
185 | int gutter_count = 0; |
186 | |
187 | void _calculate_line_height(); |
188 | void _calculate_max_line_width(); |
189 | |
190 | public: |
191 | void set_tab_size(int p_tab_size); |
192 | int get_tab_size() const; |
193 | void set_font(const Ref<Font> &p_font); |
194 | void set_font_size(int p_font_size); |
195 | void set_direction_and_language(TextServer::Direction p_direction, const String &p_language); |
196 | void set_draw_control_chars(bool p_enabled); |
197 | |
198 | int get_line_height() const; |
199 | int get_line_width(int p_line, int p_wrap_index = -1) const; |
200 | int get_max_width() const; |
201 | |
202 | void set_width(float p_width); |
203 | float get_width() const; |
204 | void set_brk_flags(BitField<TextServer::LineBreakFlag> p_flags); |
205 | BitField<TextServer::LineBreakFlag> get_brk_flags() const; |
206 | int get_line_wrap_amount(int p_line) const; |
207 | |
208 | Vector<Vector2i> get_line_wrap_ranges(int p_line) const; |
209 | const Ref<TextParagraph> get_line_data(int p_line) const; |
210 | |
211 | void set(int p_line, const String &p_text, const Array &p_bidi_override); |
212 | void set_hidden(int p_line, bool p_hidden) { |
213 | if (text[p_line].hidden == p_hidden) { |
214 | return; |
215 | } |
216 | text.write[p_line].hidden = p_hidden; |
217 | if (!p_hidden && text[p_line].width > max_width) { |
218 | max_width = text[p_line].width; |
219 | } else if (p_hidden && text[p_line].width == max_width) { |
220 | _calculate_max_line_width(); |
221 | } |
222 | } |
223 | bool is_hidden(int p_line) const { return text[p_line].hidden; } |
224 | void insert(int p_at, const Vector<String> &p_text, const Vector<Array> &p_bidi_override); |
225 | void remove_range(int p_from_line, int p_to_line); |
226 | int size() const { return text.size(); } |
227 | void clear(); |
228 | |
229 | void invalidate_cache(int p_line, int p_column = -1, bool p_text_changed = false, const String &p_ime_text = String(), const Array &p_bidi_override = Array()); |
230 | void invalidate_font(); |
231 | void invalidate_all(); |
232 | void invalidate_all_lines(); |
233 | |
234 | _FORCE_INLINE_ const String &operator[](int p_line) const; |
235 | |
236 | /* Gutters. */ |
237 | void add_gutter(int p_at); |
238 | void remove_gutter(int p_gutter); |
239 | void move_gutters(int p_from_line, int p_to_line); |
240 | |
241 | void set_line_gutter_metadata(int p_line, int p_gutter, const Variant &p_metadata) { text.write[p_line].gutters.write[p_gutter].metadata = p_metadata; } |
242 | const Variant &get_line_gutter_metadata(int p_line, int p_gutter) const { return text[p_line].gutters[p_gutter].metadata; } |
243 | |
244 | void set_line_gutter_text(int p_line, int p_gutter, const String &p_text) { text.write[p_line].gutters.write[p_gutter].text = p_text; } |
245 | const String &get_line_gutter_text(int p_line, int p_gutter) const { return text[p_line].gutters[p_gutter].text; } |
246 | |
247 | void set_line_gutter_icon(int p_line, int p_gutter, const Ref<Texture2D> &p_icon) { text.write[p_line].gutters.write[p_gutter].icon = p_icon; } |
248 | const Ref<Texture2D> &get_line_gutter_icon(int p_line, int p_gutter) const { return text[p_line].gutters[p_gutter].icon; } |
249 | |
250 | void set_line_gutter_item_color(int p_line, int p_gutter, const Color &p_color) { text.write[p_line].gutters.write[p_gutter].color = p_color; } |
251 | const Color &get_line_gutter_item_color(int p_line, int p_gutter) const { return text[p_line].gutters[p_gutter].color; } |
252 | |
253 | void set_line_gutter_clickable(int p_line, int p_gutter, bool p_clickable) { text.write[p_line].gutters.write[p_gutter].clickable = p_clickable; } |
254 | bool is_line_gutter_clickable(int p_line, int p_gutter) const { return text[p_line].gutters[p_gutter].clickable; } |
255 | |
256 | /* Line style. */ |
257 | void set_line_background_color(int p_line, const Color &p_color) { text.write[p_line].background_color = p_color; } |
258 | const Color get_line_background_color(int p_line) const { return text[p_line].background_color; } |
259 | }; |
260 | |
261 | /* Text */ |
262 | Text text; |
263 | |
264 | bool setting_text = false; |
265 | |
266 | bool alt_start = false; |
267 | uint32_t alt_code = 0; |
268 | |
269 | // Text properties. |
270 | String ime_text = "" ; |
271 | Point2 ime_selection; |
272 | |
273 | // Placeholder |
274 | String placeholder_text = "" ; |
275 | Array placeholder_bidi_override; |
276 | Ref<TextParagraph> placeholder_data_buf; |
277 | int placeholder_line_height = -1; |
278 | int placeholder_max_width = -1; |
279 | |
280 | Vector<String> placeholder_wraped_rows; |
281 | |
282 | void _update_placeholder(); |
283 | |
284 | /* Initialize to opposite first, so we get past the early-out in set_editable. */ |
285 | bool editable = false; |
286 | |
287 | TextDirection text_direction = TEXT_DIRECTION_AUTO; |
288 | TextDirection input_direction = TEXT_DIRECTION_LTR; |
289 | |
290 | String language = "" ; |
291 | |
292 | TextServer::StructuredTextParser st_parser = TextServer::STRUCTURED_TEXT_DEFAULT; |
293 | Array st_args; |
294 | |
295 | void _clear(); |
296 | void _update_caches(); |
297 | |
298 | // User control. |
299 | bool overtype_mode = false; |
300 | bool = true; |
301 | bool shortcut_keys_enabled = true; |
302 | bool virtual_keyboard_enabled = true; |
303 | bool middle_mouse_paste_enabled = true; |
304 | |
305 | // Overridable actions. |
306 | String cut_copy_line = "" ; |
307 | |
308 | // Context menu. |
309 | PopupMenu * = nullptr; |
310 | PopupMenu * = nullptr; |
311 | PopupMenu * = nullptr; |
312 | |
313 | Key (const String &p_action); |
314 | void (); |
315 | void (); |
316 | |
317 | /* Versioning */ |
318 | struct Caret; |
319 | struct TextOperation { |
320 | enum Type { |
321 | TYPE_NONE, |
322 | TYPE_INSERT, |
323 | TYPE_REMOVE |
324 | }; |
325 | Vector<Caret> start_carets; |
326 | Vector<Caret> end_carets; |
327 | |
328 | Type type = TYPE_NONE; |
329 | int from_line = 0; |
330 | int from_column = 0; |
331 | int to_line = 0; |
332 | int to_column = 0; |
333 | String text; |
334 | uint32_t prev_version = 0; |
335 | uint32_t version = 0; |
336 | bool chain_forward = false; |
337 | bool chain_backward = false; |
338 | }; |
339 | |
340 | bool undo_enabled = true; |
341 | int undo_stack_max_size = 50; |
342 | |
343 | EditAction current_action = EditAction::ACTION_NONE; |
344 | bool pending_action_end = false; |
345 | bool in_action = false; |
346 | |
347 | int complex_operation_count = 0; |
348 | bool next_operation_is_complex = false; |
349 | |
350 | TextOperation current_op; |
351 | List<TextOperation> undo_stack; |
352 | List<TextOperation>::Element *undo_stack_pos = nullptr; |
353 | |
354 | Timer *idle_detect = nullptr; |
355 | |
356 | uint32_t version = 0; |
357 | uint32_t saved_version = 0; |
358 | |
359 | void _push_current_op(); |
360 | void _do_text_op(const TextOperation &p_op, bool p_reverse); |
361 | void _clear_redo(); |
362 | |
363 | /* Search */ |
364 | String search_text = "" ; |
365 | uint32_t search_flags = 0; |
366 | |
367 | int _get_column_pos_of_word(const String &p_key, const String &p_search, uint32_t p_search_flags, int p_from_column) const; |
368 | |
369 | /* Tooltip. */ |
370 | Callable tooltip_callback; |
371 | |
372 | /* Mouse */ |
373 | struct LineDrawingCache { |
374 | int y_offset = 0; |
375 | Vector<int> first_visible_chars; |
376 | Vector<int> last_visible_chars; |
377 | }; |
378 | |
379 | HashMap<int, LineDrawingCache> line_drawing_cache; |
380 | |
381 | int _get_char_pos_for_line(int p_px, int p_line, int p_wrap_index = 0) const; |
382 | |
383 | /* Caret. */ |
384 | struct Selection { |
385 | bool active = false; |
386 | bool shiftclick_left = false; |
387 | |
388 | int selecting_line = 0; |
389 | int selecting_column = 0; |
390 | int selected_word_beg = 0; |
391 | int selected_word_end = 0; |
392 | int selected_word_origin = 0; |
393 | |
394 | int from_line = 0; |
395 | int from_column = 0; |
396 | int to_line = 0; |
397 | int to_column = 0; |
398 | }; |
399 | |
400 | struct Caret { |
401 | Selection selection; |
402 | |
403 | Point2 draw_pos; |
404 | bool visible = false; |
405 | int last_fit_x = 0; |
406 | int line = 0; |
407 | int column = 0; |
408 | }; |
409 | |
410 | // Vector containing all the carets, index '0' is the "main caret" and should never be removed. |
411 | Vector<Caret> carets; |
412 | Vector<int> caret_index_edit_order; |
413 | |
414 | bool setting_caret_line = false; |
415 | bool caret_pos_dirty = false; |
416 | bool caret_index_edit_dirty = true; |
417 | |
418 | CaretType caret_type = CaretType::CARET_TYPE_LINE; |
419 | |
420 | bool draw_caret = true; |
421 | bool draw_caret_when_editable_disabled = false; |
422 | |
423 | bool caret_blink_enabled = false; |
424 | Timer *caret_blink_timer = nullptr; |
425 | |
426 | bool move_caret_on_right_click = true; |
427 | |
428 | bool caret_mid_grapheme_enabled = false; |
429 | |
430 | bool multi_carets_enabled = true; |
431 | |
432 | bool drag_action = false; |
433 | bool drag_caret_force_displayed = false; |
434 | |
435 | void _emit_caret_changed(); |
436 | |
437 | void _reset_caret_blink_timer(); |
438 | void _toggle_draw_caret(); |
439 | |
440 | int _get_column_x_offset_for_line(int p_char, int p_line, int p_column) const; |
441 | |
442 | /* Selection. */ |
443 | SelectionMode selecting_mode = SelectionMode::SELECTION_MODE_NONE; |
444 | |
445 | bool selecting_enabled = true; |
446 | bool deselect_on_focus_loss_enabled = true; |
447 | bool drag_and_drop_selection_enabled = true; |
448 | |
449 | bool use_selected_font_color = false; |
450 | |
451 | bool selection_drag_attempt = false; |
452 | bool dragging_selection = false; |
453 | |
454 | Timer *click_select_held = nullptr; |
455 | uint64_t last_dblclk = 0; |
456 | Vector2 last_dblclk_pos; |
457 | void _click_selection_held(); |
458 | |
459 | void _update_selection_mode_pointer(); |
460 | void _update_selection_mode_word(); |
461 | void _update_selection_mode_line(); |
462 | |
463 | void _pre_shift_selection(int p_caret); |
464 | void _post_shift_selection(int p_caret); |
465 | |
466 | /* Line wrapping. */ |
467 | LineWrappingMode line_wrapping_mode = LineWrappingMode::LINE_WRAPPING_NONE; |
468 | TextServer::AutowrapMode autowrap_mode = TextServer::AUTOWRAP_WORD_SMART; |
469 | |
470 | int wrap_at_column = 0; |
471 | int wrap_right_offset = 10; |
472 | |
473 | void _update_wrap_at_column(bool p_force = false); |
474 | |
475 | /* Viewport. */ |
476 | HScrollBar *h_scroll = nullptr; |
477 | VScrollBar *v_scroll = nullptr; |
478 | |
479 | float content_height_cache = 0.0; |
480 | bool fit_content_height = false; |
481 | bool scroll_past_end_of_file_enabled = false; |
482 | |
483 | // Smooth scrolling. |
484 | bool smooth_scroll_enabled = false; |
485 | float target_v_scroll = 0.0; |
486 | float v_scroll_speed = 80.0; |
487 | |
488 | // Scrolling. |
489 | int first_visible_line = 0; |
490 | int first_visible_line_wrap_ofs = 0; |
491 | int first_visible_col = 0; |
492 | |
493 | bool scrolling = false; |
494 | bool updating_scrolls = false; |
495 | |
496 | void _update_scrollbars(); |
497 | int _get_control_height() const; |
498 | |
499 | void _v_scroll_input(); |
500 | void _scroll_moved(double p_to_val); |
501 | |
502 | double _get_visible_lines_offset() const; |
503 | double _get_v_scroll_offset() const; |
504 | |
505 | void _scroll_up(real_t p_delta); |
506 | void _scroll_down(real_t p_delta); |
507 | |
508 | void _scroll_lines_up(); |
509 | void _scroll_lines_down(); |
510 | |
511 | // Minimap. |
512 | bool draw_minimap = false; |
513 | |
514 | int minimap_width = 80; |
515 | Point2 minimap_char_size = Point2(1, 2); |
516 | int minimap_line_spacing = 1; |
517 | |
518 | // Minimap scroll. |
519 | bool minimap_clicked = false; |
520 | bool hovering_minimap = false; |
521 | bool dragging_minimap = false; |
522 | bool can_drag_minimap = false; |
523 | |
524 | double minimap_scroll_ratio = 0.0; |
525 | double minimap_scroll_click_pos = 0.0; |
526 | |
527 | void _update_minimap_hover(); |
528 | void _update_minimap_click(); |
529 | void _update_minimap_drag(); |
530 | |
531 | /* Gutters. */ |
532 | Vector<GutterInfo> gutters; |
533 | int gutters_width = 0; |
534 | int gutter_padding = 0; |
535 | Vector2i hovered_gutter = Vector2i(-1, -1); // X = gutter index, Y = row. |
536 | |
537 | void _update_gutter_width(); |
538 | |
539 | /* Syntax highlighting. */ |
540 | Ref<SyntaxHighlighter> syntax_highlighter; |
541 | |
542 | Dictionary _get_line_syntax_highlighting(int p_line); |
543 | |
544 | /* Visual. */ |
545 | struct ThemeCache { |
546 | float base_scale = 1.0; |
547 | |
548 | /* Search */ |
549 | Color search_result_color = Color(1, 1, 1); |
550 | Color search_result_border_color = Color(1, 1, 1); |
551 | |
552 | /* Caret */ |
553 | int caret_width = 1; |
554 | Color caret_color = Color(1, 1, 1); |
555 | Color caret_background_color = Color(0, 0, 0); |
556 | |
557 | /* Selection */ |
558 | Color font_selected_color = Color(0, 0, 0, 0); |
559 | Color selection_color = Color(1, 1, 1); |
560 | |
561 | /* Other visuals */ |
562 | Ref<StyleBox> style_normal; |
563 | Ref<StyleBox> style_focus; |
564 | Ref<StyleBox> style_readonly; |
565 | |
566 | Ref<Texture2D> tab_icon; |
567 | Ref<Texture2D> space_icon; |
568 | |
569 | Ref<Font> font; |
570 | int font_size = 16; |
571 | Color font_color = Color(1, 1, 1); |
572 | Color font_readonly_color = Color(1, 1, 1); |
573 | Color font_placeholder_color = Color(1, 1, 1, 0.6); |
574 | |
575 | int outline_size = 0; |
576 | Color outline_color = Color(1, 1, 1); |
577 | |
578 | int line_spacing = 1; |
579 | |
580 | Color background_color = Color(1, 1, 1); |
581 | Color current_line_color = Color(1, 1, 1); |
582 | Color word_highlighted_color = Color(1, 1, 1); |
583 | } theme_cache; |
584 | |
585 | bool window_has_focus = true; |
586 | bool first_draw = true; |
587 | |
588 | bool highlight_current_line = false; |
589 | bool highlight_all_occurrences = false; |
590 | bool draw_control_chars = false; |
591 | bool draw_tabs = false; |
592 | bool draw_spaces = false; |
593 | |
594 | /*** Super internal Core API. Everything builds on it. ***/ |
595 | bool text_changed_dirty = false; |
596 | void _text_changed_emit(); |
597 | |
598 | void _insert_text(int p_line, int p_char, const String &p_text, int *r_end_line = nullptr, int *r_end_char = nullptr); |
599 | void _remove_text(int p_from_line, int p_from_column, int p_to_line, int p_to_column); |
600 | |
601 | void _base_insert_text(int p_line, int p_char, const String &p_text, int &r_end_line, int &r_end_column); |
602 | String _base_get_text(int p_from_line, int p_from_column, int p_to_line, int p_to_column) const; |
603 | void _base_remove_text(int p_from_line, int p_from_column, int p_to_line, int p_to_column); |
604 | |
605 | /* Input actions. */ |
606 | void _swap_current_input_direction(); |
607 | void _new_line(bool p_split_current = true, bool p_above = false); |
608 | void _move_caret_left(bool p_select, bool p_move_by_word = false); |
609 | void _move_caret_right(bool p_select, bool p_move_by_word = false); |
610 | void _move_caret_up(bool p_select); |
611 | void _move_caret_down(bool p_select); |
612 | void _move_caret_to_line_start(bool p_select); |
613 | void _move_caret_to_line_end(bool p_select); |
614 | void _move_caret_page_up(bool p_select); |
615 | void _move_caret_page_down(bool p_select); |
616 | void _do_backspace(bool p_word = false, bool p_all_to_left = false); |
617 | void _delete(bool p_word = false, bool p_all_to_right = false); |
618 | void _move_caret_document_start(bool p_select); |
619 | void _move_caret_document_end(bool p_select); |
620 | bool _clear_carets_and_selection(); |
621 | |
622 | // Used in add_caret_at_carets |
623 | void _get_above_below_caret_line_column(int p_old_line, int p_old_wrap_index, int p_old_column, bool p_below, int &p_new_line, int &p_new_column, int p_last_fit_x = -1) const; |
624 | |
625 | protected: |
626 | void _notification(int p_what); |
627 | static void _bind_methods(); |
628 | |
629 | virtual void _update_theme_item_cache() override; |
630 | |
631 | /* Internal API for CodeEdit, pending public API. */ |
632 | // Brace matching. |
633 | struct BraceMatchingData { |
634 | int open_match_line = -1; |
635 | int open_match_column = -1; |
636 | bool open_matching = false; |
637 | bool open_mismatch = false; |
638 | int close_match_line = -1; |
639 | int close_match_column = -1; |
640 | bool close_matching = false; |
641 | bool close_mismatch = false; |
642 | }; |
643 | |
644 | bool highlight_matching_braces_enabled = false; |
645 | |
646 | // Line hiding. |
647 | bool hiding_enabled = false; |
648 | |
649 | void _set_hiding_enabled(bool p_enabled); |
650 | bool _is_hiding_enabled() const; |
651 | |
652 | void _set_line_as_hidden(int p_line, bool p_hidden); |
653 | bool _is_line_hidden(int p_line) const; |
654 | |
655 | void _unhide_all_lines(); |
656 | |
657 | // Symbol lookup. |
658 | String lookup_symbol_word; |
659 | void _set_symbol_lookup_word(const String &p_symbol); |
660 | |
661 | // Theme items. |
662 | virtual Color _get_brace_mismatch_color() const { return Color(); }; |
663 | virtual Color _get_code_folding_color() const { return Color(); }; |
664 | virtual Ref<Texture2D> _get_folded_eol_icon() const { return Ref<Texture2D>(); }; |
665 | |
666 | /* Text manipulation */ |
667 | |
668 | // Overridable actions |
669 | virtual void _handle_unicode_input_internal(const uint32_t p_unicode, int p_caret); |
670 | virtual void _backspace_internal(int p_caret); |
671 | |
672 | virtual void _cut_internal(int p_caret); |
673 | virtual void _copy_internal(int p_caret); |
674 | virtual void _paste_internal(int p_caret); |
675 | virtual void _paste_primary_clipboard_internal(int p_caret); |
676 | |
677 | GDVIRTUAL2(_handle_unicode_input, int, int) |
678 | GDVIRTUAL1(_backspace, int) |
679 | GDVIRTUAL1(_cut, int) |
680 | GDVIRTUAL1(_copy, int) |
681 | GDVIRTUAL1(_paste, int) |
682 | GDVIRTUAL1(_paste_primary_clipboard, int) |
683 | |
684 | public: |
685 | /* General overrides. */ |
686 | virtual void unhandled_key_input(const Ref<InputEvent> &p_event) override; |
687 | virtual void gui_input(const Ref<InputEvent> &p_gui_input) override; |
688 | bool alt_input(const Ref<InputEvent> &p_gui_input); |
689 | virtual Size2 get_minimum_size() const override; |
690 | virtual bool is_text_field() const override; |
691 | virtual CursorShape get_cursor_shape(const Point2 &p_pos = Point2i()) const override; |
692 | virtual Variant get_drag_data(const Point2 &p_point) override; |
693 | virtual bool can_drop_data(const Point2 &p_point, const Variant &p_data) const override; |
694 | virtual void drop_data(const Point2 &p_point, const Variant &p_data) override; |
695 | virtual String get_tooltip(const Point2 &p_pos) const override; |
696 | void set_tooltip_request_func(const Callable &p_tooltip_callback); |
697 | |
698 | /* Text */ |
699 | // Text properties. |
700 | bool has_ime_text() const; |
701 | |
702 | void set_editable(const bool p_editable); |
703 | bool is_editable() const; |
704 | |
705 | void set_text_direction(TextDirection p_text_direction); |
706 | TextDirection get_text_direction() const; |
707 | |
708 | void set_language(const String &p_language); |
709 | String get_language() const; |
710 | |
711 | void set_structured_text_bidi_override(TextServer::StructuredTextParser p_parser); |
712 | TextServer::StructuredTextParser get_structured_text_bidi_override() const; |
713 | void set_structured_text_bidi_override_options(Array p_args); |
714 | Array get_structured_text_bidi_override_options() const; |
715 | |
716 | void set_tab_size(const int p_size); |
717 | int get_tab_size() const; |
718 | |
719 | // User controls |
720 | void set_overtype_mode_enabled(const bool p_enabled); |
721 | bool is_overtype_mode_enabled() const; |
722 | |
723 | void (bool p_enabled); |
724 | bool () const; |
725 | |
726 | void set_shortcut_keys_enabled(bool p_enabled); |
727 | bool is_shortcut_keys_enabled() const; |
728 | |
729 | void set_virtual_keyboard_enabled(bool p_enabled); |
730 | bool is_virtual_keyboard_enabled() const; |
731 | |
732 | void set_middle_mouse_paste_enabled(bool p_enabled); |
733 | bool is_middle_mouse_paste_enabled() const; |
734 | |
735 | // Text manipulation |
736 | void clear(); |
737 | |
738 | void set_text(const String &p_text); |
739 | String get_text() const; |
740 | |
741 | int get_line_count() const; |
742 | |
743 | void set_placeholder(const String &p_text); |
744 | String get_placeholder() const; |
745 | |
746 | void set_line(int p_line, const String &p_new_text); |
747 | String get_line(int p_line) const; |
748 | |
749 | int get_line_width(int p_line, int p_wrap_index = -1) const; |
750 | int get_line_height() const; |
751 | |
752 | int get_indent_level(int p_line) const; |
753 | int get_first_non_whitespace_column(int p_line) const; |
754 | |
755 | void swap_lines(int p_from_line, int p_to_line); |
756 | |
757 | void insert_line_at(int p_at, const String &p_text); |
758 | void insert_text_at_caret(const String &p_text, int p_caret = -1); |
759 | |
760 | void remove_text(int p_from_line, int p_from_column, int p_to_line, int p_to_column); |
761 | |
762 | int get_last_unhidden_line() const; |
763 | int get_next_visible_line_offset_from(int p_line_from, int p_visible_amount) const; |
764 | Point2i get_next_visible_line_index_offset_from(int p_line_from, int p_wrap_index_from, int p_visible_amount) const; |
765 | |
766 | // Overridable actions |
767 | void handle_unicode_input(const uint32_t p_unicode, int p_caret = -1); |
768 | void backspace(int p_caret = -1); |
769 | |
770 | void cut(int p_caret = -1); |
771 | void copy(int p_caret = -1); |
772 | void paste(int p_caret = -1); |
773 | void paste_primary_clipboard(int p_caret = -1); |
774 | |
775 | // Context menu. |
776 | PopupMenu *() const; |
777 | bool () const; |
778 | void (int p_option); |
779 | |
780 | /* Versioning */ |
781 | void start_action(EditAction p_action); |
782 | void end_action(); |
783 | EditAction get_current_action() const; |
784 | |
785 | void begin_complex_operation(); |
786 | void end_complex_operation(); |
787 | |
788 | bool has_undo() const; |
789 | bool has_redo() const; |
790 | void undo(); |
791 | void redo(); |
792 | void clear_undo_history(); |
793 | |
794 | bool is_insert_text_operation() const; |
795 | |
796 | void tag_saved_version(); |
797 | |
798 | uint32_t get_version() const; |
799 | uint32_t get_saved_version() const; |
800 | |
801 | /* Search */ |
802 | void set_search_text(const String &p_search_text); |
803 | void set_search_flags(uint32_t p_flags); |
804 | |
805 | Point2i search(const String &p_key, uint32_t p_search_flags, int p_from_line, int p_from_column) const; |
806 | |
807 | /* Mouse */ |
808 | Point2 get_local_mouse_pos() const; |
809 | |
810 | String get_word_at_pos(const Vector2 &p_pos) const; |
811 | |
812 | Point2i get_line_column_at_pos(const Point2i &p_pos, bool p_allow_out_of_bounds = true) const; |
813 | Point2i get_pos_at_line_column(int p_line, int p_column) const; |
814 | Rect2i get_rect_at_line_column(int p_line, int p_column) const; |
815 | |
816 | int get_minimap_line_at_pos(const Point2i &p_pos) const; |
817 | |
818 | bool is_dragging_cursor() const; |
819 | bool is_mouse_over_selection(bool p_edges = true, int p_caret = -1) const; |
820 | |
821 | /* Caret */ |
822 | void set_caret_type(CaretType p_type); |
823 | CaretType get_caret_type() const; |
824 | |
825 | void set_caret_blink_enabled(const bool p_enabled); |
826 | bool is_caret_blink_enabled() const; |
827 | |
828 | void set_caret_blink_interval(const float p_interval); |
829 | float get_caret_blink_interval() const; |
830 | |
831 | void set_draw_caret_when_editable_disabled(bool p_enable); |
832 | bool is_drawing_caret_when_editable_disabled() const; |
833 | |
834 | void set_move_caret_on_right_click_enabled(const bool p_enabled); |
835 | bool is_move_caret_on_right_click_enabled() const; |
836 | |
837 | void set_caret_mid_grapheme_enabled(const bool p_enabled); |
838 | bool is_caret_mid_grapheme_enabled() const; |
839 | |
840 | void set_multiple_carets_enabled(bool p_enabled); |
841 | bool is_multiple_carets_enabled() const; |
842 | |
843 | int add_caret(int p_line, int p_col); |
844 | void remove_caret(int p_caret); |
845 | void remove_secondary_carets(); |
846 | void merge_overlapping_carets(); |
847 | int get_caret_count() const; |
848 | void add_caret_at_carets(bool p_below); |
849 | |
850 | Vector<int> get_caret_index_edit_order(); |
851 | void adjust_carets_after_edit(int p_caret, int p_from_line, int p_from_col, int p_to_line, int p_to_col); |
852 | |
853 | bool is_caret_visible(int p_caret = 0) const; |
854 | Point2 get_caret_draw_pos(int p_caret = 0) const; |
855 | |
856 | 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); |
857 | int get_caret_line(int p_caret = 0) const; |
858 | |
859 | void set_caret_column(int p_col, bool p_adjust_viewport = true, int p_caret = 0); |
860 | int get_caret_column(int p_caret = 0) const; |
861 | |
862 | int get_caret_wrap_index(int p_caret = 0) const; |
863 | |
864 | String get_word_under_caret(int p_caret = -1) const; |
865 | |
866 | /* Selection. */ |
867 | void set_selecting_enabled(const bool p_enabled); |
868 | bool is_selecting_enabled() const; |
869 | |
870 | void set_deselect_on_focus_loss_enabled(const bool p_enabled); |
871 | bool is_deselect_on_focus_loss_enabled() const; |
872 | |
873 | void set_drag_and_drop_selection_enabled(const bool p_enabled); |
874 | bool is_drag_and_drop_selection_enabled() const; |
875 | |
876 | void set_selection_mode(SelectionMode p_mode, int p_line = -1, int p_column = -1, int p_caret = 0); |
877 | SelectionMode get_selection_mode() const; |
878 | |
879 | void select_all(); |
880 | void select_word_under_caret(int p_caret = -1); |
881 | void add_selection_for_next_occurrence(); |
882 | void select(int p_from_line, int p_from_column, int p_to_line, int p_to_column, int p_caret = 0); |
883 | |
884 | bool has_selection(int p_caret = -1) const; |
885 | |
886 | String get_selected_text(int p_caret = -1); |
887 | |
888 | int get_selection_line(int p_caret = 0) const; |
889 | int get_selection_column(int p_caret = 0) const; |
890 | |
891 | int get_selection_from_line(int p_caret = 0) const; |
892 | int get_selection_from_column(int p_caret = 0) const; |
893 | int get_selection_to_line(int p_caret = 0) const; |
894 | int get_selection_to_column(int p_caret = 0) const; |
895 | |
896 | void deselect(int p_caret = -1); |
897 | void delete_selection(int p_caret = -1); |
898 | |
899 | /* Line wrapping. */ |
900 | void set_line_wrapping_mode(LineWrappingMode p_wrapping_mode); |
901 | LineWrappingMode get_line_wrapping_mode() const; |
902 | |
903 | void set_autowrap_mode(TextServer::AutowrapMode p_mode); |
904 | TextServer::AutowrapMode get_autowrap_mode() const; |
905 | |
906 | bool is_line_wrapped(int p_line) const; |
907 | int get_line_wrap_count(int p_line) const; |
908 | int get_line_wrap_index_at_column(int p_line, int p_column) const; |
909 | |
910 | Vector<String> get_line_wrapped_text(int p_line) const; |
911 | |
912 | /* Viewport. */ |
913 | // Scrolling. |
914 | void set_smooth_scroll_enabled(const bool p_enabled); |
915 | bool is_smooth_scroll_enabled() const; |
916 | |
917 | void set_scroll_past_end_of_file_enabled(const bool p_enabled); |
918 | bool is_scroll_past_end_of_file_enabled() const; |
919 | |
920 | VScrollBar *get_v_scroll_bar() const; |
921 | HScrollBar *get_h_scroll_bar() const; |
922 | |
923 | void set_v_scroll(double p_scroll); |
924 | double get_v_scroll() const; |
925 | |
926 | void set_h_scroll(int p_scroll); |
927 | int get_h_scroll() const; |
928 | |
929 | void set_v_scroll_speed(float p_speed); |
930 | float get_v_scroll_speed() const; |
931 | |
932 | void set_fit_content_height_enabled(const bool p_enabled); |
933 | bool is_fit_content_height_enabled() const; |
934 | |
935 | double get_scroll_pos_for_line(int p_line, int p_wrap_index = 0) const; |
936 | |
937 | // Visible lines. |
938 | void set_line_as_first_visible(int p_line, int p_wrap_index = 0); |
939 | int get_first_visible_line() const; |
940 | |
941 | void set_line_as_center_visible(int p_line, int p_wrap_index = 0); |
942 | |
943 | void set_line_as_last_visible(int p_line, int p_wrap_index = 0); |
944 | int get_last_full_visible_line() const; |
945 | int get_last_full_visible_line_wrap_index() const; |
946 | |
947 | int get_visible_line_count() const; |
948 | int get_visible_line_count_in_range(int p_from, int p_to) const; |
949 | int get_total_visible_line_count() const; |
950 | |
951 | // Auto Adjust |
952 | void adjust_viewport_to_caret(int p_caret = 0); |
953 | void center_viewport_to_caret(int p_caret = 0); |
954 | |
955 | // Minimap |
956 | void set_draw_minimap(bool p_enabled); |
957 | bool is_drawing_minimap() const; |
958 | |
959 | void set_minimap_width(int p_minimap_width); |
960 | int get_minimap_width() const; |
961 | |
962 | int get_minimap_visible_lines() const; |
963 | |
964 | /* Gutters. */ |
965 | void add_gutter(int p_at = -1); |
966 | void remove_gutter(int p_gutter); |
967 | int get_gutter_count() const; |
968 | |
969 | void set_gutter_name(int p_gutter, const String &p_name); |
970 | String get_gutter_name(int p_gutter) const; |
971 | |
972 | void set_gutter_type(int p_gutter, GutterType p_type); |
973 | GutterType get_gutter_type(int p_gutter) const; |
974 | |
975 | void set_gutter_width(int p_gutter, int p_width); |
976 | int get_gutter_width(int p_gutter) const; |
977 | int get_total_gutter_width() const; |
978 | |
979 | void set_gutter_draw(int p_gutter, bool p_draw); |
980 | bool is_gutter_drawn(int p_gutter) const; |
981 | |
982 | void set_gutter_clickable(int p_gutter, bool p_clickable); |
983 | bool is_gutter_clickable(int p_gutter) const; |
984 | |
985 | void set_gutter_overwritable(int p_gutter, bool p_overwritable); |
986 | bool is_gutter_overwritable(int p_gutter) const; |
987 | |
988 | void merge_gutters(int p_from_line, int p_to_line); |
989 | |
990 | void set_gutter_custom_draw(int p_gutter, const Callable &p_draw_callback); |
991 | |
992 | // Line gutters. |
993 | void set_line_gutter_metadata(int p_line, int p_gutter, const Variant &p_metadata); |
994 | Variant get_line_gutter_metadata(int p_line, int p_gutter) const; |
995 | |
996 | void set_line_gutter_text(int p_line, int p_gutter, const String &p_text); |
997 | String get_line_gutter_text(int p_line, int p_gutter) const; |
998 | |
999 | void set_line_gutter_icon(int p_line, int p_gutter, const Ref<Texture2D> &p_icon); |
1000 | Ref<Texture2D> get_line_gutter_icon(int p_line, int p_gutter) const; |
1001 | |
1002 | void set_line_gutter_item_color(int p_line, int p_gutter, const Color &p_color); |
1003 | Color get_line_gutter_item_color(int p_line, int p_gutter) const; |
1004 | |
1005 | void set_line_gutter_clickable(int p_line, int p_gutter, bool p_clickable); |
1006 | bool is_line_gutter_clickable(int p_line, int p_gutter) const; |
1007 | |
1008 | // Line style |
1009 | void set_line_background_color(int p_line, const Color &p_color); |
1010 | Color get_line_background_color(int p_line) const; |
1011 | |
1012 | /* Syntax Highlighting. */ |
1013 | void set_syntax_highlighter(Ref<SyntaxHighlighter> p_syntax_highlighter); |
1014 | Ref<SyntaxHighlighter> get_syntax_highlighter() const; |
1015 | |
1016 | /* Visual. */ |
1017 | void set_highlight_current_line(bool p_enabled); |
1018 | bool is_highlight_current_line_enabled() const; |
1019 | |
1020 | void set_highlight_all_occurrences(const bool p_enabled); |
1021 | bool is_highlight_all_occurrences_enabled() const; |
1022 | |
1023 | void set_draw_control_chars(bool p_enabled); |
1024 | bool get_draw_control_chars() const; |
1025 | |
1026 | void set_draw_tabs(bool p_enabled); |
1027 | bool is_drawing_tabs() const; |
1028 | |
1029 | void set_draw_spaces(bool p_enabled); |
1030 | bool is_drawing_spaces() const; |
1031 | |
1032 | TextEdit(const String &p_placeholder = String()); |
1033 | }; |
1034 | |
1035 | VARIANT_ENUM_CAST(TextEdit::EditAction); |
1036 | VARIANT_ENUM_CAST(TextEdit::CaretType); |
1037 | VARIANT_ENUM_CAST(TextEdit::LineWrappingMode); |
1038 | VARIANT_ENUM_CAST(TextEdit::SelectionMode); |
1039 | VARIANT_ENUM_CAST(TextEdit::GutterType); |
1040 | VARIANT_ENUM_CAST(TextEdit::MenuItems); |
1041 | VARIANT_ENUM_CAST(TextEdit::SearchFlags); |
1042 | |
1043 | #endif // TEXT_EDIT_H |
1044 | |