1/**************************************************************************/
2/* code_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 CODE_EDIT_H
32#define CODE_EDIT_H
33
34#include "core/object/script_language.h"
35#include "scene/gui/text_edit.h"
36
37class CodeEdit : public TextEdit {
38 GDCLASS(CodeEdit, TextEdit)
39
40public:
41 // Keep enums in sync with:
42 // core/object/script_language.h - ScriptLanguage::CodeCompletionKind
43 enum CodeCompletionKind {
44 KIND_CLASS,
45 KIND_FUNCTION,
46 KIND_SIGNAL,
47 KIND_VARIABLE,
48 KIND_MEMBER,
49 KIND_ENUM,
50 KIND_CONSTANT,
51 KIND_NODE_PATH,
52 KIND_FILE_PATH,
53 KIND_PLAIN_TEXT,
54 };
55
56 // core/object/script_language.h - ScriptLanguage::CodeCompletionLocation
57 enum CodeCompletionLocation {
58 LOCATION_LOCAL = 0,
59 LOCATION_PARENT_MASK = 1 << 8,
60 LOCATION_OTHER_USER_CODE = 1 << 9,
61 LOCATION_OTHER = 1 << 10,
62 };
63
64private:
65 /* Indent management */
66 int indent_size = 4;
67 String indent_text = "\t";
68
69 bool auto_indent = false;
70 HashSet<char32_t> auto_indent_prefixes;
71
72 bool indent_using_spaces = false;
73 int _calculate_spaces_till_next_left_indent(int p_column) const;
74 int _calculate_spaces_till_next_right_indent(int p_column) const;
75
76 void _new_line(bool p_split_current_line = true, bool p_above = false);
77
78 /* Auto brace completion */
79 bool auto_brace_completion_enabled = false;
80
81 /* BracePair open_key must be uniquie and ordered by length. */
82 struct BracePair {
83 String open_key = "";
84 String close_key = "";
85 };
86 Vector<BracePair> auto_brace_completion_pairs;
87
88 int _get_auto_brace_pair_open_at_pos(int p_line, int p_col);
89 int _get_auto_brace_pair_close_at_pos(int p_line, int p_col);
90
91 /* Main Gutter */
92 enum MainGutterType {
93 MAIN_GUTTER_BREAKPOINT = 0x01,
94 MAIN_GUTTER_BOOKMARK = 0x02,
95 MAIN_GUTTER_EXECUTING = 0x04
96 };
97
98 int main_gutter = -1;
99 void _update_draw_main_gutter();
100 void _main_gutter_draw_callback(int p_line, int p_gutter, const Rect2 &p_region);
101
102 // breakpoints
103 HashMap<int, bool> breakpointed_lines;
104 bool draw_breakpoints = false;
105
106 // bookmarks
107 bool draw_bookmarks = false;
108
109 // executing lines
110 bool draw_executing_lines = false;
111
112 /* Line numbers */
113 int line_number_gutter = -1;
114 int line_number_digits = 1;
115 String line_number_padding = " ";
116 void _line_number_draw_callback(int p_line, int p_gutter, const Rect2 &p_region);
117
118 /* Fold Gutter */
119 int fold_gutter = -1;
120 bool draw_fold_gutter = false;
121 void _fold_gutter_draw_callback(int p_line, int p_gutter, Rect2 p_region);
122
123 void _gutter_clicked(int p_line, int p_gutter);
124 void _update_gutter_indexes();
125
126 /* Line Folding */
127 bool line_folding_enabled = false;
128 String code_region_start_string;
129 String code_region_end_string;
130 String code_region_start_tag = "region";
131 String code_region_end_tag = "endregion";
132 void _update_code_region_tags();
133
134 /* Delimiters */
135 enum DelimiterType {
136 TYPE_STRING,
137 TYPE_COMMENT,
138 };
139
140 struct Delimiter {
141 DelimiterType type;
142 String start_key = "";
143 String end_key = "";
144 bool line_only = true;
145 };
146 bool setting_delimiters = false;
147 Vector<Delimiter> delimiters;
148 /*
149 * Vector entry per line, contains a Map of column numbers to delimiter index, -1 marks the end of a region.
150 * e.g the following text will be stored as so:
151 *
152 * 0: nothing here
153 * 1:
154 * 2: # test
155 * 3: "test" text "multiline
156 * 4:
157 * 5: test
158 * 6: string"
159 *
160 * Vector [
161 * 0 = []
162 * 1 = []
163 * 2 = [
164 * 1 = 1
165 * 6 = -1
166 * ]
167 * 3 = [
168 * 1 = 0
169 * 6 = -1
170 * 13 = 0
171 * ]
172 * 4 = [
173 * 0 = 0
174 * ]
175 * 5 = [
176 * 5 = 0
177 * ]
178 * 6 = [
179 * 7 = -1
180 * ]
181 * ]
182 */
183 Vector<RBMap<int, int>> delimiter_cache;
184
185 void _update_delimiter_cache(int p_from_line = 0, int p_to_line = -1);
186 int _is_in_delimiter(int p_line, int p_column, DelimiterType p_type) const;
187
188 void _add_delimiter(const String &p_start_key, const String &p_end_key, bool p_line_only, DelimiterType p_type);
189 void _remove_delimiter(const String &p_start_key, DelimiterType p_type);
190 bool _has_delimiter(const String &p_start_key, DelimiterType p_type) const;
191
192 void _set_delimiters(const TypedArray<String> &p_delimiters, DelimiterType p_type);
193 void _clear_delimiters(DelimiterType p_type);
194 TypedArray<String> _get_delimiters(DelimiterType p_type) const;
195
196 /* Code Hint */
197 String code_hint = "";
198
199 bool code_hint_draw_below = true;
200 int code_hint_xpos = -0xFFFF;
201
202 /* Code Completion */
203 bool code_completion_enabled = false;
204 bool code_completion_forced = false;
205
206 bool code_completion_active = false;
207 bool is_code_completion_scroll_hovered = false;
208 bool is_code_completion_scroll_pressed = false;
209 bool is_code_completion_drag_started = false;
210 Vector<ScriptLanguage::CodeCompletionOption> code_completion_options;
211 int code_completion_line_ofs = 0;
212 int code_completion_current_selected = 0;
213 int code_completion_force_item_center = -1;
214 int code_completion_longest_line = 0;
215 Rect2i code_completion_rect;
216 Rect2i code_completion_scroll_rect;
217
218 HashSet<char32_t> code_completion_prefixes;
219 List<ScriptLanguage::CodeCompletionOption> code_completion_option_submitted;
220 List<ScriptLanguage::CodeCompletionOption> code_completion_option_sources;
221 String code_completion_base;
222
223 void _update_scroll_selected_line(float p_mouse_y);
224 void _filter_code_completion_candidates_impl();
225
226 /* Line length guidelines */
227 TypedArray<int> line_length_guideline_columns;
228
229 /* Symbol lookup */
230 bool symbol_lookup_on_click_enabled = false;
231
232 String symbol_lookup_new_word = "";
233 String symbol_lookup_word = "";
234 Point2i symbol_lookup_pos;
235
236 /* Visual */
237 struct ThemeCache {
238 /* Gutters */
239 Color code_folding_color = Color(1, 1, 1);
240 Color folded_code_region_color = Color(1, 1, 1);
241 Ref<Texture2D> can_fold_icon;
242 Ref<Texture2D> folded_icon;
243 Ref<Texture2D> can_fold_code_region_icon;
244 Ref<Texture2D> folded_code_region_icon;
245 Ref<Texture2D> folded_eol_icon;
246
247 Color breakpoint_color = Color(1, 1, 1);
248 Ref<Texture2D> breakpoint_icon = Ref<Texture2D>();
249
250 Color bookmark_color = Color(1, 1, 1);
251 Ref<Texture2D> bookmark_icon = Ref<Texture2D>();
252
253 Color executing_line_color = Color(1, 1, 1);
254 Ref<Texture2D> executing_line_icon = Ref<Texture2D>();
255
256 Color line_number_color = Color(1, 1, 1);
257
258 /* Code Completion */
259 Ref<StyleBox> code_completion_style;
260 int code_completion_icon_separation = 0;
261
262 int code_completion_max_width = 0;
263 int code_completion_max_lines = 7;
264 int code_completion_scroll_width = 0;
265 Color code_completion_scroll_color = Color(0, 0, 0, 0);
266 Color code_completion_scroll_hovered_color = Color(0, 0, 0, 0);
267 Color code_completion_background_color = Color(0, 0, 0, 0);
268 Color code_completion_selected_color = Color(0, 0, 0, 0);
269 Color code_completion_existing_color = Color(0, 0, 0, 0);
270
271 /* Code hint */
272 Ref<StyleBox> code_hint_style;
273 Color code_hint_color;
274
275 /* Line length guideline */
276 Color line_length_guideline_color;
277
278 /* Other visuals */
279 Ref<StyleBox> style_normal;
280
281 Color brace_mismatch_color;
282
283 Ref<Font> font;
284 int font_size = 16;
285 int line_spacing = 1;
286 } theme_cache;
287
288 virtual Color _get_brace_mismatch_color() const override;
289 virtual Color _get_code_folding_color() const override;
290 virtual Ref<Texture2D> _get_folded_eol_icon() const override;
291
292 /* Callbacks */
293 int lines_edited_changed = 0;
294 int lines_edited_from = -1;
295 int lines_edited_to = -1;
296
297 void _lines_edited_from(int p_from_line, int p_to_line);
298 void _text_set();
299 void _text_changed();
300
301protected:
302 void _notification(int p_what);
303 static void _bind_methods();
304
305#ifndef DISABLE_DEPRECATED
306 String _get_text_for_symbol_lookup_bind_compat_73196();
307 static void _bind_compatibility_methods();
308#endif
309
310 /* Text manipulation */
311
312 // Overridable actions
313 virtual void _handle_unicode_input_internal(const uint32_t p_unicode, int p_caret) override;
314 virtual void _backspace_internal(int p_caret) override;
315
316 GDVIRTUAL1(_confirm_code_completion, bool)
317 GDVIRTUAL1(_request_code_completion, bool)
318 GDVIRTUAL1RC(TypedArray<Dictionary>, _filter_code_completion_candidates, TypedArray<Dictionary>)
319
320public:
321 /* General overrides */
322 virtual void gui_input(const Ref<InputEvent> &p_gui_input) override;
323 virtual CursorShape get_cursor_shape(const Point2 &p_pos = Point2i()) const override;
324
325 /* Indent management */
326 void set_indent_size(const int p_size);
327 int get_indent_size() const;
328
329 void set_indent_using_spaces(const bool p_use_spaces);
330 bool is_indent_using_spaces() const;
331
332 void set_auto_indent_enabled(bool p_enabled);
333 bool is_auto_indent_enabled() const;
334
335 void set_auto_indent_prefixes(const TypedArray<String> &p_prefixes);
336 TypedArray<String> get_auto_indent_prefixes() const;
337
338 void do_indent();
339
340 void indent_lines();
341 void unindent_lines();
342
343 void convert_indent(int p_from_line = -1, int p_to_line = -1);
344
345 /* Auto brace completion */
346 void set_auto_brace_completion_enabled(bool p_enabled);
347 bool is_auto_brace_completion_enabled() const;
348
349 void set_highlight_matching_braces_enabled(bool p_enabled);
350 bool is_highlight_matching_braces_enabled() const;
351
352 void add_auto_brace_completion_pair(const String &p_open_key, const String &p_close_key);
353 void set_auto_brace_completion_pairs(const Dictionary &p_auto_brace_completion_pairs);
354 Dictionary get_auto_brace_completion_pairs() const;
355
356 bool has_auto_brace_completion_open_key(const String &p_open_key) const;
357 bool has_auto_brace_completion_close_key(const String &p_close_key) const;
358
359 String get_auto_brace_completion_close_key(const String &p_open_key) const;
360
361 /* Main Gutter */
362 void set_draw_breakpoints_gutter(bool p_draw);
363 bool is_drawing_breakpoints_gutter() const;
364
365 void set_draw_bookmarks_gutter(bool p_draw);
366 bool is_drawing_bookmarks_gutter() const;
367
368 void set_draw_executing_lines_gutter(bool p_draw);
369 bool is_drawing_executing_lines_gutter() const;
370
371 // breakpoints
372 void set_line_as_breakpoint(int p_line, bool p_breakpointed);
373 bool is_line_breakpointed(int p_line) const;
374 void clear_breakpointed_lines();
375 PackedInt32Array get_breakpointed_lines() const;
376
377 // bookmarks
378 void set_line_as_bookmarked(int p_line, bool p_bookmarked);
379 bool is_line_bookmarked(int p_line) const;
380 void clear_bookmarked_lines();
381 PackedInt32Array get_bookmarked_lines() const;
382
383 // executing lines
384 void set_line_as_executing(int p_line, bool p_executing);
385 bool is_line_executing(int p_line) const;
386 void clear_executing_lines();
387 PackedInt32Array get_executing_lines() const;
388
389 /* Line numbers */
390 void set_draw_line_numbers(bool p_draw);
391 bool is_draw_line_numbers_enabled() const;
392 void set_line_numbers_zero_padded(bool p_zero_padded);
393 bool is_line_numbers_zero_padded() const;
394
395 /* Fold gutter */
396 void set_draw_fold_gutter(bool p_draw);
397 bool is_drawing_fold_gutter() const;
398
399 /* Line Folding */
400 void set_line_folding_enabled(bool p_enabled);
401 bool is_line_folding_enabled() const;
402
403 bool can_fold_line(int p_line) const;
404
405 void fold_line(int p_line);
406 void unfold_line(int p_line);
407 void fold_all_lines();
408 void unfold_all_lines();
409 void toggle_foldable_line(int p_line);
410
411 bool is_line_folded(int p_line) const;
412 TypedArray<int> get_folded_lines() const;
413
414 /* Code region */
415 void create_code_region();
416 String get_code_region_start_tag() const;
417 String get_code_region_end_tag() const;
418 void set_code_region_tags(const String &p_start = "region", const String &p_end = "endregion");
419 bool is_line_code_region_start(int p_line) const;
420 bool is_line_code_region_end(int p_line) const;
421
422 /* Delimiters */
423 void add_string_delimiter(const String &p_start_key, const String &p_end_key, bool p_line_only = false);
424 void remove_string_delimiter(const String &p_start_key);
425 bool has_string_delimiter(const String &p_start_key) const;
426
427 void set_string_delimiters(const TypedArray<String> &p_string_delimiters);
428 void clear_string_delimiters();
429 TypedArray<String> get_string_delimiters() const;
430
431 int is_in_string(int p_line, int p_column = -1) const;
432
433 void add_comment_delimiter(const String &p_start_key, const String &p_end_key, bool p_line_only = false);
434 void remove_comment_delimiter(const String &p_start_key);
435 bool has_comment_delimiter(const String &p_start_key) const;
436
437 void set_comment_delimiters(const TypedArray<String> &p_comment_delimiters);
438 void clear_comment_delimiters();
439 TypedArray<String> get_comment_delimiters() const;
440
441 int is_in_comment(int p_line, int p_column = -1) const;
442
443 String get_delimiter_start_key(int p_delimiter_idx) const;
444 String get_delimiter_end_key(int p_delimiter_idx) const;
445
446 Point2 get_delimiter_start_position(int p_line, int p_column) const;
447 Point2 get_delimiter_end_position(int p_line, int p_column) const;
448
449 /* Code hint */
450 void set_code_hint(const String &p_hint);
451 void set_code_hint_draw_below(bool p_below);
452
453 /* Code Completion */
454 void set_code_completion_enabled(bool p_enable);
455 bool is_code_completion_enabled() const;
456
457 void set_code_completion_prefixes(const TypedArray<String> &p_prefixes);
458 TypedArray<String> get_code_completion_prefixes() const;
459
460 String get_text_for_code_completion() const;
461
462 void request_code_completion(bool p_force = false);
463
464 void add_code_completion_option(CodeCompletionKind p_type, const String &p_display_text, const String &p_insert_text, const Color &p_text_color = Color(1, 1, 1), const Ref<Resource> &p_icon = Ref<Resource>(), const Variant &p_value = Variant::NIL, int p_location = LOCATION_OTHER);
465 void update_code_completion_options(bool p_forced = false);
466
467 TypedArray<Dictionary> get_code_completion_options() const;
468 Dictionary get_code_completion_option(int p_index) const;
469
470 int get_code_completion_selected_index() const;
471 void set_code_completion_selected_index(int p_index);
472
473 void confirm_code_completion(bool p_replace = false);
474 void cancel_code_completion();
475
476 /* Line length guidelines */
477 void set_line_length_guidelines(TypedArray<int> p_guideline_columns);
478 TypedArray<int> get_line_length_guidelines() const;
479
480 /* Symbol lookup */
481 void set_symbol_lookup_on_click_enabled(bool p_enabled);
482 bool is_symbol_lookup_on_click_enabled() const;
483
484 String get_text_for_symbol_lookup() const;
485 String get_text_with_cursor_char(int p_line, int p_column) const;
486
487 void set_symbol_lookup_word_as_valid(bool p_valid);
488
489 CodeEdit();
490 ~CodeEdit();
491};
492
493VARIANT_ENUM_CAST(CodeEdit::CodeCompletionKind);
494VARIANT_ENUM_CAST(CodeEdit::CodeCompletionLocation);
495
496// The custom comparer which will sort completion options.
497struct CodeCompletionOptionCompare {
498 _FORCE_INLINE_ bool operator()(const ScriptLanguage::CodeCompletionOption &l, const ScriptLanguage::CodeCompletionOption &r) const;
499};
500
501#endif // CODE_EDIT_H
502