mirror of
https://github.com/godotengine/godot.git
synced 2024-11-23 12:43:43 +00:00
Merge pull request #50122 from Paulb23/code_edit_auto_brace_completion
This commit is contained in:
commit
c620ede327
@ -1,8 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="CodeEdit" inherits="TextEdit" version="4.0">
|
||||
<brief_description>
|
||||
Multiline text control intended for editing code.
|
||||
</brief_description>
|
||||
<description>
|
||||
CodeEdit is a specialised [TextEdit] designed for editing plain text code files. It contains a bunch of features commonly found in code editors such as line numbers, line folding, code completion, indent management and string / comment management.
|
||||
[b]Note[/b]: By default [CodeEdit] always use left-to-right text direction to correctly display source code.
|
||||
</description>
|
||||
<tutorials>
|
||||
@ -30,6 +32,15 @@
|
||||
Override this method to define what happens when the user requests code completion. If [code]force[/code] is true, any checks should be bypassed.
|
||||
</description>
|
||||
</method>
|
||||
<method name="add_auto_brace_completion_pair">
|
||||
<return type="void" />
|
||||
<argument index="0" name="start_key" type="String" />
|
||||
<argument index="1" name="end_key" type="String" />
|
||||
<description>
|
||||
Adds a brace pair.
|
||||
Both the start and end keys must be symbols. Only the start key has to be unique.
|
||||
</description>
|
||||
</method>
|
||||
<method name="add_code_completion_option">
|
||||
<return type="void" />
|
||||
<argument index="0" name="type" type="int" enum="CodeEdit.CodeCompletionKind" />
|
||||
@ -81,11 +92,13 @@
|
||||
<method name="clear_bookmarked_lines">
|
||||
<return type="void" />
|
||||
<description>
|
||||
Clears all bookmarked lines.
|
||||
</description>
|
||||
</method>
|
||||
<method name="clear_breakpointed_lines">
|
||||
<return type="void" />
|
||||
<description>
|
||||
Clears all breakpointed lines.
|
||||
</description>
|
||||
</method>
|
||||
<method name="clear_comment_delimiters">
|
||||
@ -97,6 +110,7 @@
|
||||
<method name="clear_executing_lines">
|
||||
<return type="void" />
|
||||
<description>
|
||||
Clears all executed lines.
|
||||
</description>
|
||||
</method>
|
||||
<method name="clear_string_delimiters">
|
||||
@ -137,14 +151,23 @@
|
||||
Folds the given line, if possible (see [method can_fold_line]).
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_auto_brace_completion_close_key" qualifiers="const">
|
||||
<return type="String" />
|
||||
<argument index="0" name="open_key" type="String" />
|
||||
<description>
|
||||
Gets the matching auto brace close key for [code]open_key[/code].
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_bookmarked_lines" qualifiers="const">
|
||||
<return type="Array" />
|
||||
<description>
|
||||
Gets all bookmarked lines.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_breakpointed_lines" qualifiers="const">
|
||||
<return type="Array" />
|
||||
<description>
|
||||
Gets all breakpointed lines.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_code_completion_option" qualifiers="const">
|
||||
@ -205,6 +228,7 @@
|
||||
<method name="get_executing_lines" qualifiers="const">
|
||||
<return type="Array" />
|
||||
<description>
|
||||
Gets all executing lines.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_folded_lines" qualifiers="const">
|
||||
@ -219,6 +243,26 @@
|
||||
Returns the full text with char [code]0xFFFF[/code] at the caret location.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_text_for_symbol_lookup">
|
||||
<return type="String" />
|
||||
<description>
|
||||
Returns the full text with char [code]0xFFFF[/code] at the cursor location.
|
||||
</description>
|
||||
</method>
|
||||
<method name="has_auto_brace_completion_close_key" qualifiers="const">
|
||||
<return type="bool" />
|
||||
<argument index="0" name="close_key" type="String" />
|
||||
<description>
|
||||
Returns [code]true[/code] if close key [code]close_key[/code] exists.
|
||||
</description>
|
||||
</method>
|
||||
<method name="has_auto_brace_completion_open_key" qualifiers="const">
|
||||
<return type="bool" />
|
||||
<argument index="0" name="open_key" type="String" />
|
||||
<description>
|
||||
Returns [code]true[/code] if open key [code]open_key[/code] exists.
|
||||
</description>
|
||||
</method>
|
||||
<method name="has_comment_delimiter" qualifiers="const">
|
||||
<return type="bool" />
|
||||
<argument index="0" name="start_key" type="String" />
|
||||
@ -259,18 +303,21 @@
|
||||
<return type="bool" />
|
||||
<argument index="0" name="line" type="int" />
|
||||
<description>
|
||||
Returns whether the line at the specified index is bookmarked or not.
|
||||
</description>
|
||||
</method>
|
||||
<method name="is_line_breakpointed" qualifiers="const">
|
||||
<return type="bool" />
|
||||
<argument index="0" name="line" type="int" />
|
||||
<description>
|
||||
Returns whether the line at the specified index is breakpointed or not.
|
||||
</description>
|
||||
</method>
|
||||
<method name="is_line_executing" qualifiers="const">
|
||||
<return type="bool" />
|
||||
<argument index="0" name="line" type="int" />
|
||||
<description>
|
||||
Returns whether the line at the specified index is marked as executing or not.
|
||||
</description>
|
||||
</method>
|
||||
<method name="is_line_folded" qualifiers="const">
|
||||
@ -327,6 +374,7 @@
|
||||
<argument index="0" name="line" type="int" />
|
||||
<argument index="1" name="bookmarked" type="bool" />
|
||||
<description>
|
||||
Sets the line as bookmarked.
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_line_as_breakpoint">
|
||||
@ -334,6 +382,7 @@
|
||||
<argument index="0" name="line" type="int" />
|
||||
<argument index="1" name="breakpointed" type="bool" />
|
||||
<description>
|
||||
Sets the line as breakpointed.
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_line_as_executing">
|
||||
@ -341,6 +390,14 @@
|
||||
<argument index="0" name="line" type="int" />
|
||||
<argument index="1" name="executing" type="bool" />
|
||||
<description>
|
||||
Sets the line as executing.
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_symbol_lookup_word_as_valid">
|
||||
<return type="void" />
|
||||
<argument index="0" name="valid" type="bool" />
|
||||
<description>
|
||||
Sets the symbol emitted by [signal symbol_validate] as a valid lookup.
|
||||
</description>
|
||||
</method>
|
||||
<method name="toggle_foldable_line">
|
||||
@ -353,6 +410,7 @@
|
||||
<method name="unfold_all_lines">
|
||||
<return type="void" />
|
||||
<description>
|
||||
Unfolds all lines, folded or not.
|
||||
</description>
|
||||
</method>
|
||||
<method name="unfold_line">
|
||||
@ -378,6 +436,15 @@
|
||||
</method>
|
||||
</methods>
|
||||
<members>
|
||||
<member name="auto_brace_completion_enabled" type="bool" setter="set_auto_brace_completion_enabled" getter="is_auto_brace_completion_enabled" default="false">
|
||||
Sets whether brace pairs should be autocompleted.
|
||||
</member>
|
||||
<member name="auto_brace_completion_highlight_matching" type="bool" setter="set_highlight_matching_braces_enabled" getter="is_highlight_matching_braces_enabled" default="false">
|
||||
Highlight mismatching brace pairs.
|
||||
</member>
|
||||
<member name="auto_brace_completion_pairs" type="Dictionary" setter="set_auto_brace_completion_pairs" getter="get_auto_brace_completion_pairs" default="{"\"": "\"","'": "'","(": ")","[": "]","{": "}"}">
|
||||
Sets the brace pairs to be autocompleted.
|
||||
</member>
|
||||
<member name="code_completion_enabled" type="bool" setter="set_code_completion_enabled" getter="is_code_completion_enabled" default="false">
|
||||
Sets whether code completion is allowed.
|
||||
</member>
|
||||
@ -387,18 +454,26 @@
|
||||
<member name="delimiter_comments" type="String[]" setter="set_comment_delimiters" getter="get_comment_delimiters" default="[]">
|
||||
Sets the comment delimiters. All existing comment delimiters will be removed.
|
||||
</member>
|
||||
<member name="delimiter_strings" type="String[]" setter="set_string_delimiters" getter="get_string_delimiters" default="[]">
|
||||
<member name="delimiter_strings" type="String[]" setter="set_string_delimiters" getter="get_string_delimiters" default="["' '", "\" \""]">
|
||||
Sets the string delimiters. All existing string delimiters will be removed.
|
||||
</member>
|
||||
<member name="draw_bookmarks" type="bool" setter="set_draw_bookmarks_gutter" getter="is_drawing_bookmarks_gutter" default="false">
|
||||
<member name="gutters_draw_bookmarks" type="bool" setter="set_draw_bookmarks_gutter" getter="is_drawing_bookmarks_gutter" default="false">
|
||||
Sets if bookmarked should be drawn in the gutter. This gutter is shared with breakpoints and executing lines.
|
||||
</member>
|
||||
<member name="draw_breakpoints_gutter" type="bool" setter="set_draw_breakpoints_gutter" getter="is_drawing_breakpoints_gutter" default="false">
|
||||
<member name="gutters_draw_breakpoints_gutter" type="bool" setter="set_draw_breakpoints_gutter" getter="is_drawing_breakpoints_gutter" default="false">
|
||||
Sets if breakpoints should be drawn in the gutter. This gutter is shared with bookmarks and executing lines.
|
||||
</member>
|
||||
<member name="draw_executing_lines" type="bool" setter="set_draw_executing_lines_gutter" getter="is_drawing_executing_lines_gutter" default="false">
|
||||
<member name="gutters_draw_executing_lines" type="bool" setter="set_draw_executing_lines_gutter" getter="is_drawing_executing_lines_gutter" default="false">
|
||||
Sets if executing lines should be marked in the gutter. This gutter is shared with breakpoints and bookmarks lines.
|
||||
</member>
|
||||
<member name="draw_fold_gutter" type="bool" setter="set_draw_fold_gutter" getter="is_drawing_fold_gutter" default="false">
|
||||
<member name="gutters_draw_fold_gutter" type="bool" setter="set_draw_fold_gutter" getter="is_drawing_fold_gutter" default="false">
|
||||
Sets if foldable lines icons should be drawn in the gutter.
|
||||
</member>
|
||||
<member name="draw_line_numbers" type="bool" setter="set_draw_line_numbers" getter="is_draw_line_numbers_enabled" default="false">
|
||||
<member name="gutters_draw_line_numbers" type="bool" setter="set_draw_line_numbers" getter="is_draw_line_numbers_enabled" default="false">
|
||||
Sets if line numbers should be drawn in the gutter.
|
||||
</member>
|
||||
<member name="gutters_zero_pad_line_numbers" type="bool" setter="set_line_numbers_zero_padded" getter="is_line_numbers_zero_padded" default="false">
|
||||
Sets if line numbers drawn in the gutter are zero padded.
|
||||
</member>
|
||||
<member name="indent_automatic" type="bool" setter="set_auto_indent_enabled" getter="is_auto_indent_enabled" default="false">
|
||||
Sets whether automatic indent are enabled, this will add an extra indent if a prefix or brace is found.
|
||||
@ -413,18 +488,23 @@
|
||||
Use spaces instead of tabs for indentation.
|
||||
</member>
|
||||
<member name="layout_direction" type="int" setter="set_layout_direction" getter="get_layout_direction" override="true" enum="Control.LayoutDirection" default="2" />
|
||||
<member name="line_folding" type="bool" setter="set_line_folding_enabled" getter="is_line_folding_enabled" default="true">
|
||||
<member name="line_folding" type="bool" setter="set_line_folding_enabled" getter="is_line_folding_enabled" default="false">
|
||||
Sets whether line folding is allowed.
|
||||
</member>
|
||||
<member name="structured_text_bidi_override_options" type="Array" setter="set_structured_text_bidi_override_options" getter="get_structured_text_bidi_override_options" override="true" default="[]" />
|
||||
<member name="text_direction" type="int" setter="set_text_direction" getter="get_text_direction" override="true" enum="Control.TextDirection" default="1" />
|
||||
<member name="zero_pad_line_numbers" type="bool" setter="set_line_numbers_zero_padded" getter="is_line_numbers_zero_padded" default="false">
|
||||
<member name="line_length_guidelines" type="int[]" setter="set_line_length_guidelines" getter="get_line_length_guidelines" default="[]">
|
||||
Draws vertical lines at the provided columns. The first entry is considered a main hard guideline and is draw more prominently
|
||||
</member>
|
||||
<member name="structured_text_bidi_override_options" type="Array" setter="set_structured_text_bidi_override_options" getter="get_structured_text_bidi_override_options" override="true" default="[]" />
|
||||
<member name="symbol_lookup_on_click" type="bool" setter="set_symbol_lookup_on_click_enabled" getter="is_symbol_lookup_on_click_enabled" default="false">
|
||||
Set when a validated word from [signal symbol_validate] is clicked, the [signal symbol_lookup] should be emitted.
|
||||
</member>
|
||||
<member name="text_direction" type="int" setter="set_text_direction" getter="get_text_direction" override="true" enum="Control.TextDirection" default="1" />
|
||||
</members>
|
||||
<signals>
|
||||
<signal name="breakpoint_toggled">
|
||||
<argument index="0" name="line" type="int" />
|
||||
<description>
|
||||
Emitted when a breakpoint is added or removed from a line. If the line is moved via backspace a removed is emitted at the old line.
|
||||
</description>
|
||||
</signal>
|
||||
<signal name="request_code_completion">
|
||||
@ -432,114 +512,176 @@
|
||||
Emitted when the user requests code completion.
|
||||
</description>
|
||||
</signal>
|
||||
<signal name="symbol_lookup">
|
||||
<argument index="0" name="symbol" type="String" />
|
||||
<argument index="1" name="line" type="int" />
|
||||
<argument index="2" name="column" type="int" />
|
||||
<description>
|
||||
Emitted when the user has clicked on a valid symbol.
|
||||
</description>
|
||||
</signal>
|
||||
<signal name="symbol_validate">
|
||||
<argument index="0" name="symbol" type="String" />
|
||||
<description>
|
||||
Emitted when the user hovers over a symbol. The symbol should be validated and responded to, by calling [method set_symbol_lookup_word_as_valid].
|
||||
</description>
|
||||
</signal>
|
||||
</signals>
|
||||
<constants>
|
||||
<constant name="KIND_CLASS" value="0" enum="CodeCompletionKind">
|
||||
Marks the option as a class.
|
||||
</constant>
|
||||
<constant name="KIND_FUNCTION" value="1" enum="CodeCompletionKind">
|
||||
Marks the option as a function.
|
||||
</constant>
|
||||
<constant name="KIND_SIGNAL" value="2" enum="CodeCompletionKind">
|
||||
Marks the option as a Godot signal.
|
||||
</constant>
|
||||
<constant name="KIND_VARIABLE" value="3" enum="CodeCompletionKind">
|
||||
Marks the option as a variable.
|
||||
</constant>
|
||||
<constant name="KIND_MEMBER" value="4" enum="CodeCompletionKind">
|
||||
Marks the option as a member.
|
||||
</constant>
|
||||
<constant name="KIND_ENUM" value="5" enum="CodeCompletionKind">
|
||||
Marks the option as a enum entry.
|
||||
</constant>
|
||||
<constant name="KIND_CONSTANT" value="6" enum="CodeCompletionKind">
|
||||
Marks the option as a constant.
|
||||
</constant>
|
||||
<constant name="KIND_NODE_PATH" value="7" enum="CodeCompletionKind">
|
||||
Marks the option as a Godot node path.
|
||||
</constant>
|
||||
<constant name="KIND_FILE_PATH" value="8" enum="CodeCompletionKind">
|
||||
Marks the option as a file path.
|
||||
</constant>
|
||||
<constant name="KIND_PLAIN_TEXT" value="9" enum="CodeCompletionKind">
|
||||
Marks the option as unclassified or plain text.
|
||||
</constant>
|
||||
</constants>
|
||||
<theme_items>
|
||||
<theme_item name="background_color" type="Color" default="Color(0, 0, 0, 0)">
|
||||
Sets the background [Color].
|
||||
</theme_item>
|
||||
<theme_item name="bookmark" type="Texture2D">
|
||||
Sets a custom [Texture2D] to draw in the bookmark gutter for bookmarked lines.
|
||||
</theme_item>
|
||||
<theme_item name="bookmark_color" type="Color" default="Color(0.5, 0.64, 1, 0.8)">
|
||||
[Color] of the bookmark icon for bookmarked lines.
|
||||
</theme_item>
|
||||
<theme_item name="brace_mismatch_color" type="Color" default="Color(1, 0.2, 0.2, 1)">
|
||||
[Color] of the text to highlight mismatched braces.
|
||||
</theme_item>
|
||||
<theme_item name="breakpoint" type="Texture2D">
|
||||
Sets a custom [Texture2D] to draw in the breakpoint gutter for breakpointed lines.
|
||||
</theme_item>
|
||||
<theme_item name="breakpoint_color" type="Color" default="Color(0.9, 0.29, 0.3, 1)">
|
||||
[Color] of the breakpoint icon for bookmarked lines.
|
||||
</theme_item>
|
||||
<theme_item name="can_fold" type="Texture2D">
|
||||
Sets a custom [Texture2D] to draw in the line folding gutter when a line can be folded.
|
||||
</theme_item>
|
||||
<theme_item name="caret_background_color" type="Color" default="Color(0, 0, 0, 1)">
|
||||
[Color] of the text behind the caret when block caret is enabled.
|
||||
</theme_item>
|
||||
<theme_item name="caret_color" type="Color" default="Color(0.88, 0.88, 0.88, 1)">
|
||||
[Color] of the caret.
|
||||
</theme_item>
|
||||
<theme_item name="code_folding_color" type="Color" default="Color(0.8, 0.8, 0.8, 0.8)">
|
||||
[Color] for all icons related to line folding.
|
||||
</theme_item>
|
||||
<theme_item name="completion" type="StyleBox">
|
||||
[StyleBox] for the code completion popup.
|
||||
</theme_item>
|
||||
<theme_item name="completion_background_color" type="Color" default="Color(0.17, 0.16, 0.2, 1)">
|
||||
Sets the background [Color] for the code completion popup.
|
||||
</theme_item>
|
||||
<theme_item name="completion_existing_color" type="Color" default="Color(0.87, 0.87, 0.87, 0.13)">
|
||||
Background highlight [Color] for matching text in code completion options.
|
||||
</theme_item>
|
||||
<theme_item name="completion_font_color" type="Color" default="Color(0.67, 0.67, 0.67, 1)">
|
||||
Font [Color] for the code completion popup.
|
||||
</theme_item>
|
||||
<theme_item name="completion_lines" type="int" default="7">
|
||||
Max number of options to display in the code completion popup at any one time.
|
||||
</theme_item>
|
||||
<theme_item name="completion_max_width" type="int" default="50">
|
||||
Max width of options in the code completion popup. Options longer then this will be cut off.
|
||||
</theme_item>
|
||||
<theme_item name="completion_scroll_color" type="Color" default="Color(1, 1, 1, 1)">
|
||||
[Color] of the scrollbar in the code completion popup.
|
||||
</theme_item>
|
||||
<theme_item name="completion_scroll_width" type="int" default="3">
|
||||
Width of the scrollbar in the code completion popup.
|
||||
</theme_item>
|
||||
<theme_item name="completion_selected_color" type="Color" default="Color(0.26, 0.26, 0.27, 1)">
|
||||
Background highlight [Color] for the current selected option item in the code completion popup.
|
||||
</theme_item>
|
||||
<theme_item name="current_line_color" type="Color" default="Color(0.25, 0.25, 0.26, 0.8)">
|
||||
Background [Color] of the line containing the caret.
|
||||
</theme_item>
|
||||
<theme_item name="executing_line" type="Texture2D">
|
||||
Icon to draw in the executing gutter for executing lines.
|
||||
</theme_item>
|
||||
<theme_item name="executing_line_color" type="Color" default="Color(0.98, 0.89, 0.27, 1)">
|
||||
[Color] of the executing icon for executing lines.
|
||||
</theme_item>
|
||||
<theme_item name="focus" type="StyleBox">
|
||||
Sets the [StyleBox] when in focus.
|
||||
</theme_item>
|
||||
<theme_item name="folded" type="Texture2D">
|
||||
Sets a custom [Texture2D] to draw in the line folding gutter when a line is folded and can be unfolded.
|
||||
</theme_item>
|
||||
<theme_item name="folded_eol_icon" type="Texture2D">
|
||||
Sets a custom [Texture2D] to draw at the end of a folded line.
|
||||
</theme_item>
|
||||
<theme_item name="font" type="Font">
|
||||
Sets the default [Font].
|
||||
</theme_item>
|
||||
<theme_item name="font_color" type="Color" default="Color(0.88, 0.88, 0.88, 1)">
|
||||
Sets the font [Color].
|
||||
</theme_item>
|
||||
<theme_item name="font_outline_color" type="Color" default="Color(1, 1, 1, 1)">
|
||||
The tint of text outline of the [CodeEdit].
|
||||
</theme_item>
|
||||
<theme_item name="font_readonly_color" type="Color" default="Color(0.88, 0.88, 0.88, 0.5)">
|
||||
Sets the font [Color] when [member readonly] is enabled.
|
||||
</theme_item>
|
||||
<theme_item name="font_selected_color" type="Color" default="Color(0, 0, 0, 1)">
|
||||
Sets the [Color] of the selected text. [member override_selected_font_color] has to be enabled.
|
||||
</theme_item>
|
||||
<theme_item name="font_size" type="int">
|
||||
Font size of the [CodeEdit]'s text.
|
||||
Sets default font size.
|
||||
</theme_item>
|
||||
<theme_item name="line_length_guideline_color" type="Color" default="Color(0.3, 0.5, 0.8, 0.1)">
|
||||
[Color] of the main line length guideline, secondary guidelines will have 50% alpha applied.
|
||||
</theme_item>
|
||||
<theme_item name="line_number_color" type="Color" default="Color(0.67, 0.67, 0.67, 0.4)">
|
||||
Sets the [Color] of line numbers.
|
||||
</theme_item>
|
||||
<theme_item name="line_spacing" type="int" default="4">
|
||||
Sets the spacing between the lines.
|
||||
</theme_item>
|
||||
<theme_item name="normal" type="StyleBox">
|
||||
Sets the [StyleBox].
|
||||
</theme_item>
|
||||
<theme_item name="outline_size" type="int" default="0">
|
||||
The size of the text outline.
|
||||
</theme_item>
|
||||
<theme_item name="read_only" type="StyleBox">
|
||||
</theme_item>
|
||||
<theme_item name="safe_line_number_color" type="Color" default="Color(0.67, 0.78, 0.67, 0.6)">
|
||||
Sets the [StyleBox] when [member readonly] is enabled.
|
||||
</theme_item>
|
||||
<theme_item name="selection_color" type="Color" default="Color(0.49, 0.49, 0.49, 1)">
|
||||
Sets the highlight [Color] of text selections.
|
||||
</theme_item>
|
||||
<theme_item name="space" type="Texture2D">
|
||||
Sets a custom [Texture2D] for space text characters.
|
||||
</theme_item>
|
||||
<theme_item name="tab" type="Texture2D">
|
||||
Sets a custom [Texture2D] for tab text characters.
|
||||
</theme_item>
|
||||
<theme_item name="word_highlighted_color" type="Color" default="Color(0.8, 0.9, 0.9, 0.15)">
|
||||
Sets the highlight [Color] of multiple occurrences. [member highlight_all_occurrences] has to be enabled.
|
||||
</theme_item>
|
||||
</theme_items>
|
||||
</class>
|
||||
|
@ -16,6 +16,12 @@
|
||||
A virtual method that is called whenever backspace is triggered.
|
||||
</description>
|
||||
</method>
|
||||
<method name="_handle_unicode_input" qualifiers="virtual">
|
||||
<return type="void" />
|
||||
<argument index="0" name="unicode" type="int" />
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="add_gutter">
|
||||
<return type="void" />
|
||||
<argument index="0" name="at" type="int" default="-1" />
|
||||
@ -256,6 +262,11 @@
|
||||
Returns the [TextEdit]'s' tab size.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_total_gutter_width" qualifiers="const">
|
||||
<return type="int" />
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_visible_line_count" qualifiers="const">
|
||||
<return type="int" />
|
||||
<description>
|
||||
@ -281,6 +292,11 @@
|
||||
Returns [code]true[/code] if the caret is visible on the screen.
|
||||
</description>
|
||||
</method>
|
||||
<method name="is_dragging_cursor" qualifiers="const">
|
||||
<return type="bool" />
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="is_gutter_clickable" qualifiers="const">
|
||||
<return type="bool" />
|
||||
<argument index="0" name="gutter" type="int" />
|
||||
@ -654,18 +670,6 @@
|
||||
<description>
|
||||
</description>
|
||||
</signal>
|
||||
<signal name="symbol_lookup">
|
||||
<argument index="0" name="symbol" type="String" />
|
||||
<argument index="1" name="row" type="int" />
|
||||
<argument index="2" name="column" type="int" />
|
||||
<description>
|
||||
</description>
|
||||
</signal>
|
||||
<signal name="symbol_validate">
|
||||
<argument index="0" name="symbol" type="String" />
|
||||
<description>
|
||||
</description>
|
||||
</signal>
|
||||
<signal name="text_changed">
|
||||
<description>
|
||||
Emitted when the text changes.
|
||||
@ -790,8 +794,6 @@
|
||||
<theme_item name="background_color" type="Color" default="Color(0, 0, 0, 0)">
|
||||
Sets the background [Color] of this [TextEdit].
|
||||
</theme_item>
|
||||
<theme_item name="brace_mismatch_color" type="Color" default="Color(1, 0.2, 0.2, 1)">
|
||||
</theme_item>
|
||||
<theme_item name="caret_background_color" type="Color" default="Color(0, 0, 0, 1)">
|
||||
</theme_item>
|
||||
<theme_item name="caret_color" type="Color" default="Color(0.88, 0.88, 0.88, 1)">
|
||||
|
@ -951,14 +951,20 @@ void CodeTextEditor::update_editor_settings() {
|
||||
text_editor->set_line_folding_enabled(EditorSettings::get_singleton()->get("text_editor/appearance/code_folding"));
|
||||
text_editor->set_draw_fold_gutter(EditorSettings::get_singleton()->get("text_editor/appearance/code_folding"));
|
||||
text_editor->set_wrap_enabled(EditorSettings::get_singleton()->get("text_editor/appearance/word_wrap"));
|
||||
text_editor->set_show_line_length_guidelines(EditorSettings::get_singleton()->get("text_editor/appearance/show_line_length_guidelines"));
|
||||
text_editor->set_line_length_guideline_soft_column(EditorSettings::get_singleton()->get("text_editor/appearance/line_length_guideline_soft_column"));
|
||||
text_editor->set_line_length_guideline_hard_column(EditorSettings::get_singleton()->get("text_editor/appearance/line_length_guideline_hard_column"));
|
||||
text_editor->set_scroll_pass_end_of_file(EditorSettings::get_singleton()->get("text_editor/cursor/scroll_past_end_of_file"));
|
||||
text_editor->cursor_set_block_mode(EditorSettings::get_singleton()->get("text_editor/cursor/block_caret"));
|
||||
text_editor->cursor_set_blink_enabled(EditorSettings::get_singleton()->get("text_editor/cursor/caret_blink"));
|
||||
text_editor->cursor_set_blink_speed(EditorSettings::get_singleton()->get("text_editor/cursor/caret_blink_speed"));
|
||||
text_editor->set_auto_brace_completion(EditorSettings::get_singleton()->get("text_editor/completion/auto_brace_complete"));
|
||||
text_editor->set_auto_brace_completion_enabled(EditorSettings::get_singleton()->get("text_editor/completion/auto_brace_complete"));
|
||||
|
||||
if (EditorSettings::get_singleton()->get("text_editor/appearance/show_line_length_guidelines")) {
|
||||
TypedArray<int> guideline_cols;
|
||||
guideline_cols.append(EditorSettings::get_singleton()->get("text_editor/appearance/line_length_guideline_hard_column"));
|
||||
if (EditorSettings::get_singleton()->get("text_editor/appearance/line_length_guideline_soft_column") != guideline_cols[0]) {
|
||||
guideline_cols.append(EditorSettings::get_singleton()->get("text_editor/appearance/line_length_guideline_soft_column"));
|
||||
}
|
||||
text_editor->set_line_length_guidelines(guideline_cols);
|
||||
}
|
||||
}
|
||||
|
||||
void CodeTextEditor::set_find_replace_bar(FindReplaceBar *p_bar) {
|
||||
@ -1609,16 +1615,9 @@ void CodeTextEditor::_apply_settings_change() {
|
||||
} break;
|
||||
}
|
||||
|
||||
// Auto brace completion.
|
||||
text_editor->set_auto_brace_completion(
|
||||
EDITOR_GET("text_editor/completion/auto_brace_complete"));
|
||||
|
||||
code_complete_timer->set_wait_time(
|
||||
EDITOR_GET("text_editor/completion/code_complete_delay"));
|
||||
|
||||
// Call hint settings.
|
||||
text_editor->set_code_hint_draw_below(EDITOR_GET("text_editor/completion/put_callhint_tooltip_below_current_line"));
|
||||
|
||||
code_complete_timer->set_wait_time(EDITOR_GET("text_editor/completion/code_complete_delay"));
|
||||
idle->set_wait_time(EDITOR_GET("text_editor/completion/idle_parse_delay"));
|
||||
}
|
||||
|
||||
@ -1832,7 +1831,7 @@ CodeTextEditor::CodeTextEditor() {
|
||||
}
|
||||
|
||||
text_editor->set_draw_line_numbers(true);
|
||||
text_editor->set_brace_matching(true);
|
||||
text_editor->set_highlight_matching_braces_enabled(true);
|
||||
text_editor->set_auto_indent_enabled(true);
|
||||
|
||||
status_bar = memnew(HBoxContainer);
|
||||
|
@ -204,7 +204,13 @@ void ScriptTextEditor::_set_theme_for_script() {
|
||||
for (const String &string : strings) {
|
||||
String beg = string.get_slice(" ", 0);
|
||||
String end = string.get_slice_count(" ") > 1 ? string.get_slice(" ", 1) : String();
|
||||
text_edit->add_string_delimiter(beg, end, end == "");
|
||||
if (!text_edit->has_string_delimiter(beg)) {
|
||||
text_edit->add_string_delimiter(beg, end, end == "");
|
||||
}
|
||||
|
||||
if (!end.is_empty() && !text_edit->has_auto_brace_completion_open_key(beg)) {
|
||||
text_edit->add_auto_brace_completion_pair(beg, end);
|
||||
}
|
||||
}
|
||||
|
||||
List<String> comments;
|
||||
@ -214,6 +220,10 @@ void ScriptTextEditor::_set_theme_for_script() {
|
||||
String beg = comment.get_slice(" ", 0);
|
||||
String end = comment.get_slice_count(" ") > 1 ? comment.get_slice(" ", 1) : String();
|
||||
text_edit->add_comment_delimiter(beg, end, end == "");
|
||||
|
||||
if (!end.is_empty() && !text_edit->has_auto_brace_completion_open_key(beg)) {
|
||||
text_edit->add_auto_brace_completion_pair(beg, end);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -742,7 +752,7 @@ void ScriptTextEditor::_lookup_symbol(const String &p_symbol, int p_row, int p_c
|
||||
EditorNode::get_singleton()->load_resource(p_symbol);
|
||||
}
|
||||
|
||||
} else if (script->get_language()->lookup_code(code_editor->get_text_editor()->get_text_for_lookup_completion(), p_symbol, script->get_path(), base, result) == OK) {
|
||||
} else if (script->get_language()->lookup_code(code_editor->get_text_editor()->get_text_for_symbol_lookup(), p_symbol, script->get_path(), base, result) == OK) {
|
||||
_goto_line(p_row);
|
||||
|
||||
result.class_name = result.class_name.trim_prefix("_");
|
||||
@ -845,18 +855,17 @@ void ScriptTextEditor::_validate_symbol(const String &p_symbol) {
|
||||
}
|
||||
|
||||
ScriptLanguage::LookupResult result;
|
||||
if (ScriptServer::is_global_class(p_symbol) || p_symbol.is_resource_file() || script->get_language()->lookup_code(code_editor->get_text_editor()->get_text_for_lookup_completion(), p_symbol, script->get_path(), base, result) == OK || (ProjectSettings::get_singleton()->has_autoload(p_symbol) && ProjectSettings::get_singleton()->get_autoload(p_symbol).is_singleton)) {
|
||||
text_edit->set_highlighted_word(p_symbol);
|
||||
if (ScriptServer::is_global_class(p_symbol) || p_symbol.is_resource_file() || script->get_language()->lookup_code(code_editor->get_text_editor()->get_text_for_symbol_lookup(), p_symbol, script->get_path(), base, result) == OK || (ProjectSettings::get_singleton()->has_autoload(p_symbol) && ProjectSettings::get_singleton()->get_autoload(p_symbol).is_singleton)) {
|
||||
text_edit->set_symbol_lookup_word_as_valid(true);
|
||||
} else if (p_symbol.is_rel_path()) {
|
||||
String path = _get_absolute_path(p_symbol);
|
||||
if (FileAccess::exists(path)) {
|
||||
text_edit->set_highlighted_word(p_symbol);
|
||||
text_edit->set_symbol_lookup_word_as_valid(true);
|
||||
} else {
|
||||
text_edit->set_highlighted_word(String());
|
||||
text_edit->set_symbol_lookup_word_as_valid(false);
|
||||
}
|
||||
|
||||
} else {
|
||||
text_edit->set_highlighted_word(String());
|
||||
text_edit->set_symbol_lookup_word_as_valid(false);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1544,7 +1553,7 @@ void ScriptTextEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) {
|
||||
base = _find_node_for_script(base, base, script);
|
||||
}
|
||||
ScriptLanguage::LookupResult result;
|
||||
if (script->get_language()->lookup_code(code_editor->get_text_editor()->get_text_for_lookup_completion(), word_at_pos, script->get_path(), base, result) == OK) {
|
||||
if (script->get_language()->lookup_code(code_editor->get_text_editor()->get_text_for_symbol_lookup(), word_at_pos, script->get_path(), base, result) == OK) {
|
||||
open_docs = true;
|
||||
}
|
||||
}
|
||||
@ -1829,7 +1838,7 @@ ScriptTextEditor::ScriptTextEditor() {
|
||||
|
||||
code_editor->get_text_editor()->set_code_hint_draw_below(EditorSettings::get_singleton()->get("text_editor/completion/put_callhint_tooltip_below_current_line"));
|
||||
|
||||
code_editor->get_text_editor()->set_select_identifiers_on_hover(true);
|
||||
code_editor->get_text_editor()->set_symbol_lookup_on_click_enabled(true);
|
||||
code_editor->get_text_editor()->set_context_menu_enabled(false);
|
||||
|
||||
context_menu = memnew(PopupMenu);
|
||||
|
@ -158,6 +158,10 @@ void ShaderTextEditor::_load_theme_settings() {
|
||||
text_editor->add_comment_delimiter("/*", "*/", false);
|
||||
text_editor->add_comment_delimiter("//", "", true);
|
||||
|
||||
if (!text_editor->has_auto_brace_completion_open_key("/*")) {
|
||||
text_editor->add_auto_brace_completion_pair("/*", "*/");
|
||||
}
|
||||
|
||||
if (warnings_panel) {
|
||||
// Warnings panel
|
||||
warnings_panel->add_theme_font_override("normal_font", EditorNode::get_singleton()->get_gui_base()->get_theme_font(SNAME("main"), SNAME("EditorFonts")));
|
||||
@ -659,7 +663,7 @@ ShaderEditor::ShaderEditor(EditorNode *p_node) {
|
||||
|
||||
shader_editor->get_text_editor()->set_code_hint_draw_below(EditorSettings::get_singleton()->get("text_editor/completion/put_callhint_tooltip_below_current_line"));
|
||||
|
||||
shader_editor->get_text_editor()->set_select_identifiers_on_hover(true);
|
||||
shader_editor->get_text_editor()->set_symbol_lookup_on_click_enabled(true);
|
||||
shader_editor->get_text_editor()->set_context_menu_enabled(false);
|
||||
shader_editor->get_text_editor()->connect("gui_input", callable_mp(this, &ShaderEditor::_text_edit_gui_input));
|
||||
|
||||
|
@ -921,6 +921,10 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) {
|
||||
expression_box->add_comment_delimiter("/*", "*/", false);
|
||||
expression_box->add_comment_delimiter("//", "", true);
|
||||
|
||||
if (!expression_box->has_auto_brace_completion_open_key("/*")) {
|
||||
expression_box->add_auto_brace_completion_pair("/*", "*/");
|
||||
}
|
||||
|
||||
expression_box->set_text(expression);
|
||||
expression_box->set_context_menu_enabled(false);
|
||||
expression_box->set_draw_line_numbers(true);
|
||||
|
@ -72,13 +72,34 @@ void CodeEdit::_notification(int p_what) {
|
||||
code_completion_background_color = get_theme_color(SNAME("completion_background_color"));
|
||||
code_completion_selected_color = get_theme_color(SNAME("completion_selected_color"));
|
||||
code_completion_existing_color = get_theme_color(SNAME("completion_existing_color"));
|
||||
|
||||
line_length_guideline_color = get_theme_color(SNAME("line_length_guideline_color"));
|
||||
} break;
|
||||
case NOTIFICATION_DRAW: {
|
||||
RID ci = get_canvas_item();
|
||||
const Size2 size = get_size();
|
||||
const bool caret_visible = is_caret_visible();
|
||||
const bool rtl = is_layout_rtl();
|
||||
const int row_height = get_row_height();
|
||||
|
||||
if (line_length_guideline_columns.size() > 0) {
|
||||
const int xmargin_beg = cache.style_normal->get_margin(SIDE_LEFT) + get_total_gutter_width();
|
||||
const int xmargin_end = size.width - cache.style_normal->get_margin(SIDE_RIGHT) - (is_drawing_minimap() ? get_minimap_width() : 0);
|
||||
const int char_size = (int)cache.font->get_char_size('0', 0, cache.font_size).width;
|
||||
|
||||
for (int i = 0; i < line_length_guideline_columns.size(); i++) {
|
||||
const int xoffset = xmargin_beg + char_size * (int)line_length_guideline_columns[i] - get_h_scroll();
|
||||
if (xoffset > xmargin_beg && xoffset < xmargin_end) {
|
||||
Color guideline_color = (i == 0) ? line_length_guideline_color : line_length_guideline_color * Color(1, 1, 1, 0.5);
|
||||
if (rtl) {
|
||||
RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2(size.width - xoffset, 0), Point2(size.width - xoffset, size.height), guideline_color);
|
||||
continue;
|
||||
}
|
||||
RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2(xoffset, 0), Point2(xoffset, size.height), guideline_color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool code_completion_below = false;
|
||||
if (caret_visible && code_completion_active && code_completion_options.size() > 0) {
|
||||
Ref<StyleBox> csb = get_theme_stylebox(SNAME("completion"));
|
||||
@ -278,6 +299,39 @@ void CodeEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (mb->get_button_index() == MOUSE_BUTTON_LEFT) {
|
||||
if (mb->is_command_pressed() && symbol_lookup_word != String()) {
|
||||
Vector2i mpos = mb->get_position();
|
||||
if (is_layout_rtl()) {
|
||||
mpos.x = get_size().x - mpos.x;
|
||||
}
|
||||
int line, col;
|
||||
_get_mouse_pos(Point2i(mpos.x, mpos.y), line, col);
|
||||
|
||||
emit_signal(SNAME("symbol_lookup"), symbol_lookup_word, line, col);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ref<InputEventMouseMotion> mm = p_gui_input;
|
||||
if (mm.is_valid()) {
|
||||
Vector2i mpos = mm->get_position();
|
||||
if (is_layout_rtl()) {
|
||||
mpos.x = get_size().x - mpos.x;
|
||||
}
|
||||
|
||||
if (symbol_lookup_on_click_enabled) {
|
||||
if (mm->is_command_pressed() && mm->get_button_mask() == 0 && !is_dragging_cursor()) {
|
||||
symbol_lookup_new_word = get_word_at_pos(mpos);
|
||||
if (symbol_lookup_new_word != symbol_lookup_word) {
|
||||
emit_signal(SNAME("symbol_validate"), symbol_lookup_new_word);
|
||||
}
|
||||
} else {
|
||||
set_symbol_lookup_word_as_valid(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -288,6 +342,25 @@ void CodeEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Ctrl + Hover symbols */
|
||||
#ifdef OSX_ENABLED
|
||||
if (k->get_keycode() == KEY_META) {
|
||||
#else
|
||||
if (k->get_keycode() == KEY_CTRL) {
|
||||
#endif
|
||||
if (symbol_lookup_on_click_enabled) {
|
||||
if (k->is_pressed() && !is_dragging_cursor()) {
|
||||
symbol_lookup_new_word = get_word_at_pos(_get_local_mouse_pos());
|
||||
if (symbol_lookup_new_word != symbol_lookup_word) {
|
||||
emit_signal(SNAME("symbol_validate"), symbol_lookup_new_word);
|
||||
}
|
||||
} else {
|
||||
set_symbol_lookup_word_as_valid(false);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* If a modifier has been pressed, and nothing else, return. */
|
||||
if (!k->is_pressed() || k->get_keycode() == KEY_CTRL || k->get_keycode() == KEY_ALT || k->get_keycode() == KEY_SHIFT || k->get_keycode() == KEY_META) {
|
||||
return;
|
||||
@ -437,7 +510,12 @@ void CodeEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
|
||||
}
|
||||
}
|
||||
|
||||
/* General overrides */
|
||||
Control::CursorShape CodeEdit::get_cursor_shape(const Point2 &p_pos) const {
|
||||
if (symbol_lookup_word != String()) {
|
||||
return CURSOR_POINTING_HAND;
|
||||
}
|
||||
|
||||
if ((code_completion_active && code_completion_rect.has_point(p_pos)) || (is_readonly() && (!is_selecting_enabled() || get_line_count() == 0))) {
|
||||
return CURSOR_ARROW;
|
||||
}
|
||||
@ -459,6 +537,58 @@ Control::CursorShape CodeEdit::get_cursor_shape(const Point2 &p_pos) const {
|
||||
return TextEdit::get_cursor_shape(p_pos);
|
||||
}
|
||||
|
||||
void CodeEdit::handle_unicode_input(uint32_t p_unicode) {
|
||||
bool had_selection = is_selection_active();
|
||||
if (had_selection) {
|
||||
begin_complex_operation();
|
||||
delete_selection();
|
||||
}
|
||||
|
||||
// Remove the old character if in insert mode and no selection.
|
||||
if (is_insert_mode() && !had_selection) {
|
||||
begin_complex_operation();
|
||||
|
||||
// Make sure we don't try and remove empty space.
|
||||
if (cursor_get_column() < get_line(cursor_get_line()).length()) {
|
||||
_remove_text(cursor_get_line(), cursor_get_column(), cursor_get_line(), cursor_get_column() + 1);
|
||||
}
|
||||
}
|
||||
|
||||
const char32_t chr[2] = { (char32_t)p_unicode, 0 };
|
||||
|
||||
if (auto_brace_completion_enabled) {
|
||||
int cl = cursor_get_line();
|
||||
int cc = cursor_get_column();
|
||||
int caret_move_offset = 1;
|
||||
|
||||
int post_brace_pair = cc < get_line(cl).length() ? _get_auto_brace_pair_close_at_pos(cl, cc) : -1;
|
||||
|
||||
if (has_string_delimiter(chr) && cc > 0 && _is_char(get_line(cl)[cc - 1]) && post_brace_pair == -1) {
|
||||
insert_text_at_cursor(chr);
|
||||
} else if (cc < get_line(cl).length() && _is_char(get_line(cl)[cc])) {
|
||||
insert_text_at_cursor(chr);
|
||||
} else if (post_brace_pair != -1 && auto_brace_completion_pairs[post_brace_pair].close_key[0] == chr[0]) {
|
||||
caret_move_offset = auto_brace_completion_pairs[post_brace_pair].close_key.length();
|
||||
} else if (is_in_comment(cl, cc) != -1 || (is_in_string(cl, cc) != -1 && has_string_delimiter(chr))) {
|
||||
insert_text_at_cursor(chr);
|
||||
} else {
|
||||
insert_text_at_cursor(chr);
|
||||
|
||||
int pre_brace_pair = _get_auto_brace_pair_open_at_pos(cl, cc + 1);
|
||||
if (pre_brace_pair != -1) {
|
||||
insert_text_at_cursor(auto_brace_completion_pairs[pre_brace_pair].close_key);
|
||||
}
|
||||
}
|
||||
cursor_set_column(cc + caret_move_offset);
|
||||
} else {
|
||||
insert_text_at_cursor(chr);
|
||||
}
|
||||
|
||||
if ((is_insert_mode() && !had_selection) || (had_selection)) {
|
||||
end_complex_operation();
|
||||
}
|
||||
}
|
||||
|
||||
/* Indent management */
|
||||
void CodeEdit::set_indent_size(const int p_size) {
|
||||
ERR_FAIL_COND_MSG(p_size <= 0, "Indend size must be greater than 0.");
|
||||
@ -527,13 +657,13 @@ void CodeEdit::do_indent() {
|
||||
}
|
||||
|
||||
if (!indent_using_spaces) {
|
||||
_insert_text_at_cursor("\t");
|
||||
insert_text_at_cursor("\t");
|
||||
return;
|
||||
}
|
||||
|
||||
int spaces_to_add = _calculate_spaces_till_next_right_indent(cursor_get_column());
|
||||
if (spaces_to_add > 0) {
|
||||
_insert_text_at_cursor(String(" ").repeat(spaces_to_add));
|
||||
insert_text_at_cursor(String(" ").repeat(spaces_to_add));
|
||||
}
|
||||
}
|
||||
|
||||
@ -713,34 +843,6 @@ int CodeEdit::_calculate_spaces_till_next_right_indent(int p_column) const {
|
||||
return indent_size - p_column % indent_size;
|
||||
}
|
||||
|
||||
/* TODO: remove once brace completion is refactored. */
|
||||
static char32_t _get_right_pair_symbol(char32_t c) {
|
||||
if (c == '"') {
|
||||
return '"';
|
||||
}
|
||||
if (c == '\'') {
|
||||
return '\'';
|
||||
}
|
||||
if (c == '(') {
|
||||
return ')';
|
||||
}
|
||||
if (c == '[') {
|
||||
return ']';
|
||||
}
|
||||
if (c == '{') {
|
||||
return '}';
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool _is_pair_left_symbol(char32_t c) {
|
||||
return c == '"' ||
|
||||
c == '\'' ||
|
||||
c == '(' ||
|
||||
c == '[' ||
|
||||
c == '{';
|
||||
}
|
||||
|
||||
void CodeEdit::_new_line(bool p_split_current_line, bool p_above) {
|
||||
if (is_readonly()) {
|
||||
return;
|
||||
@ -803,9 +905,8 @@ void CodeEdit::_new_line(bool p_split_current_line, bool p_above) {
|
||||
if (should_indent) {
|
||||
ins += indent_text;
|
||||
|
||||
/* TODO: Change when brace completion is refactored. */
|
||||
char32_t closing_char = _get_right_pair_symbol(indent_char);
|
||||
if (closing_char != 0 && closing_char == line[cc]) {
|
||||
String closing_pair = get_auto_brace_completion_close_key(String::chr(indent_char));
|
||||
if (!closing_pair.is_empty() && line.find(closing_pair, cc) == cc) {
|
||||
/* No need to move the brace below if we are not taking the text with us. */
|
||||
if (p_split_current_line) {
|
||||
brace_indent = true;
|
||||
@ -873,12 +974,20 @@ void CodeEdit::backspace() {
|
||||
|
||||
merge_gutters(cl, prev_line);
|
||||
|
||||
/* TODO: Change when brace completion is refactored. */
|
||||
if (auto_brace_completion_enabled && cc > 0 && _is_pair_left_symbol(get_line(cl)[cc - 1])) {
|
||||
_consume_backspace_for_pair_symbol(prev_line, prev_column);
|
||||
cursor_set_line(prev_line, false, true);
|
||||
cursor_set_column(prev_column);
|
||||
return;
|
||||
if (auto_brace_completion_enabled && cc > 0) {
|
||||
int idx = _get_auto_brace_pair_open_at_pos(cl, cc);
|
||||
if (idx != -1) {
|
||||
prev_column = cc - auto_brace_completion_pairs[idx].open_key.length();
|
||||
|
||||
if (_get_auto_brace_pair_close_at_pos(cl, cc) == idx) {
|
||||
_remove_text(prev_line, prev_column, cl, cc + auto_brace_completion_pairs[idx].close_key.length());
|
||||
} else {
|
||||
_remove_text(prev_line, prev_column, cl, cc);
|
||||
}
|
||||
cursor_set_line(prev_line, false, true);
|
||||
cursor_set_column(prev_column);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* For space indentation we need to do a simple unindent if there are no chars to the left, acting in the */
|
||||
@ -896,6 +1005,93 @@ void CodeEdit::backspace() {
|
||||
cursor_set_column(prev_column);
|
||||
}
|
||||
|
||||
/* Auto brace completion */
|
||||
void CodeEdit::set_auto_brace_completion_enabled(bool p_enabled) {
|
||||
auto_brace_completion_enabled = p_enabled;
|
||||
}
|
||||
|
||||
bool CodeEdit::is_auto_brace_completion_enabled() const {
|
||||
return auto_brace_completion_enabled;
|
||||
}
|
||||
|
||||
void CodeEdit::set_highlight_matching_braces_enabled(bool p_enabled) {
|
||||
highlight_matching_braces_enabled = p_enabled;
|
||||
update();
|
||||
}
|
||||
|
||||
bool CodeEdit::is_highlight_matching_braces_enabled() const {
|
||||
return highlight_matching_braces_enabled;
|
||||
}
|
||||
|
||||
void CodeEdit::add_auto_brace_completion_pair(const String &p_open_key, const String &p_close_key) {
|
||||
ERR_FAIL_COND_MSG(p_open_key.is_empty(), "auto brace completion open key cannot be empty");
|
||||
ERR_FAIL_COND_MSG(p_close_key.is_empty(), "auto brace completion close key cannot be empty");
|
||||
|
||||
for (int i = 0; i < p_open_key.length(); i++) {
|
||||
ERR_FAIL_COND_MSG(!is_symbol(p_open_key[i]), "auto brace completion open key must be a symbol");
|
||||
}
|
||||
for (int i = 0; i < p_close_key.length(); i++) {
|
||||
ERR_FAIL_COND_MSG(!is_symbol(p_close_key[i]), "auto brace completion close key must be a symbol");
|
||||
}
|
||||
|
||||
int at = 0;
|
||||
for (int i = 0; i < auto_brace_completion_pairs.size(); i++) {
|
||||
ERR_FAIL_COND_MSG(auto_brace_completion_pairs[i].open_key == p_open_key, "auto brace completion open key '" + p_open_key + "' already exists.");
|
||||
if (p_open_key.length() < auto_brace_completion_pairs[i].open_key.length()) {
|
||||
at++;
|
||||
}
|
||||
}
|
||||
|
||||
BracePair brace_pair;
|
||||
brace_pair.open_key = p_open_key;
|
||||
brace_pair.close_key = p_close_key;
|
||||
auto_brace_completion_pairs.insert(at, brace_pair);
|
||||
}
|
||||
|
||||
void CodeEdit::set_auto_brace_completion_pairs(const Dictionary &p_auto_brace_completion_pairs) {
|
||||
auto_brace_completion_pairs.clear();
|
||||
|
||||
Array keys = p_auto_brace_completion_pairs.keys();
|
||||
for (int i = 0; i < keys.size(); i++) {
|
||||
add_auto_brace_completion_pair(keys[i], p_auto_brace_completion_pairs[keys[i]]);
|
||||
}
|
||||
}
|
||||
|
||||
Dictionary CodeEdit::get_auto_brace_completion_pairs() const {
|
||||
Dictionary brace_pairs;
|
||||
for (int i = 0; i < auto_brace_completion_pairs.size(); i++) {
|
||||
brace_pairs[auto_brace_completion_pairs[i].open_key] = auto_brace_completion_pairs[i].close_key;
|
||||
}
|
||||
return brace_pairs;
|
||||
}
|
||||
|
||||
bool CodeEdit::has_auto_brace_completion_open_key(const String &p_open_key) const {
|
||||
for (int i = 0; i < auto_brace_completion_pairs.size(); i++) {
|
||||
if (auto_brace_completion_pairs[i].open_key == p_open_key) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CodeEdit::has_auto_brace_completion_close_key(const String &p_close_key) const {
|
||||
for (int i = 0; i < auto_brace_completion_pairs.size(); i++) {
|
||||
if (auto_brace_completion_pairs[i].close_key == p_close_key) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
String CodeEdit::get_auto_brace_completion_close_key(const String &p_open_key) const {
|
||||
for (int i = 0; i < auto_brace_completion_pairs.size(); i++) {
|
||||
if (auto_brace_completion_pairs[i].open_key == p_open_key) {
|
||||
return auto_brace_completion_pairs[i].close_key;
|
||||
}
|
||||
}
|
||||
return String();
|
||||
}
|
||||
|
||||
/* Main Gutter */
|
||||
void CodeEdit::_update_draw_main_gutter() {
|
||||
set_gutter_draw(main_gutter, draw_breakpoints || draw_bookmarks || draw_executing_lines);
|
||||
@ -1700,35 +1896,40 @@ void CodeEdit::confirm_code_completion(bool p_replace) {
|
||||
insert_text_at_cursor(insert_text.substr(matching_chars));
|
||||
}
|
||||
|
||||
/* TODO: merge with autobrace completion, when in CodeEdit. */
|
||||
/* Handle merging of symbols eg strings, brackets. */
|
||||
const String line = get_line(caret_line);
|
||||
char32_t next_char = line[cursor_get_column()];
|
||||
char32_t last_completion_char = insert_text[insert_text.length() - 1];
|
||||
char32_t last_completion_char_display = display_text[display_text.length() - 1];
|
||||
|
||||
if ((last_completion_char == '"' || last_completion_char == '\'') && (last_completion_char == next_char || last_completion_char_display == next_char)) {
|
||||
int pre_brace_pair = cursor_get_column() > 0 ? _get_auto_brace_pair_open_at_pos(caret_line, cursor_get_column()) : -1;
|
||||
int post_brace_pair = cursor_get_column() < get_line(caret_line).length() ? _get_auto_brace_pair_close_at_pos(caret_line, cursor_get_column()) : -1;
|
||||
|
||||
if (post_brace_pair != -1 && (last_completion_char == next_char || last_completion_char_display == next_char)) {
|
||||
_remove_text(caret_line, cursor_get_column(), caret_line, cursor_get_column() + 1);
|
||||
}
|
||||
|
||||
if (last_completion_char == '(') {
|
||||
if (next_char == last_completion_char) {
|
||||
_remove_text(caret_line, cursor_get_column() - 1, caret_line, cursor_get_column());
|
||||
} else if (auto_brace_completion_enabled) {
|
||||
insert_text_at_cursor(")");
|
||||
cursor_set_column(cursor_get_column() - 1);
|
||||
}
|
||||
} else if (last_completion_char == ')' && next_char == '(') {
|
||||
_remove_text(caret_line, cursor_get_column() - 2, caret_line, cursor_get_column());
|
||||
if (line[cursor_get_column() + 1] != ')') {
|
||||
cursor_set_column(cursor_get_column() - 1);
|
||||
if (pre_brace_pair != -1 && pre_brace_pair != post_brace_pair && (last_completion_char == next_char || last_completion_char_display == next_char)) {
|
||||
_remove_text(caret_line, cursor_get_column(), caret_line, cursor_get_column() + 1);
|
||||
} else if (auto_brace_completion_enabled && pre_brace_pair != -1 && post_brace_pair == -1) {
|
||||
insert_text_at_cursor(auto_brace_completion_pairs[pre_brace_pair].close_key);
|
||||
cursor_set_column(cursor_get_column() - auto_brace_completion_pairs[pre_brace_pair].close_key.length());
|
||||
}
|
||||
|
||||
if (pre_brace_pair == -1 && post_brace_pair == -1 && cursor_get_column() > 0 && cursor_get_column() < get_line(caret_line).length()) {
|
||||
pre_brace_pair = _get_auto_brace_pair_open_at_pos(caret_line, cursor_get_column() + 1);
|
||||
if (pre_brace_pair == _get_auto_brace_pair_close_at_pos(caret_line, cursor_get_column() - 1)) {
|
||||
_remove_text(caret_line, cursor_get_column() - 2, caret_line, cursor_get_column());
|
||||
if (_get_auto_brace_pair_close_at_pos(caret_line, cursor_get_column() - 1) != pre_brace_pair) {
|
||||
cursor_set_column(cursor_get_column() - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
end_complex_operation();
|
||||
|
||||
cancel_code_completion();
|
||||
if (last_completion_char == '(') {
|
||||
if (code_completion_prefixes.has(String::chr(last_completion_char))) {
|
||||
request_code_completion();
|
||||
}
|
||||
}
|
||||
@ -1742,6 +1943,58 @@ void CodeEdit::cancel_code_completion() {
|
||||
update();
|
||||
}
|
||||
|
||||
/* Line length guidelines */
|
||||
void CodeEdit::set_line_length_guidelines(TypedArray<int> p_guideline_columns) {
|
||||
line_length_guideline_columns = p_guideline_columns;
|
||||
update();
|
||||
}
|
||||
|
||||
TypedArray<int> CodeEdit::get_line_length_guidelines() const {
|
||||
return line_length_guideline_columns;
|
||||
}
|
||||
|
||||
/* Symbol lookup */
|
||||
void CodeEdit::set_symbol_lookup_on_click_enabled(bool p_enabled) {
|
||||
symbol_lookup_on_click_enabled = p_enabled;
|
||||
set_symbol_lookup_word_as_valid(false);
|
||||
}
|
||||
|
||||
bool CodeEdit::is_symbol_lookup_on_click_enabled() const {
|
||||
return symbol_lookup_on_click_enabled;
|
||||
}
|
||||
|
||||
String CodeEdit::get_text_for_symbol_lookup() {
|
||||
int line, col;
|
||||
Point2i mp = _get_local_mouse_pos();
|
||||
_get_mouse_pos(mp, line, col);
|
||||
|
||||
StringBuilder lookup_text;
|
||||
const int text_size = get_line_count();
|
||||
for (int i = 0; i < text_size; i++) {
|
||||
String text = get_line(i);
|
||||
|
||||
if (i == line) {
|
||||
lookup_text += text.substr(0, col);
|
||||
/* Not unicode, represents the cursor. */
|
||||
lookup_text += String::chr(0xFFFF);
|
||||
lookup_text += text.substr(col, text.size());
|
||||
} else {
|
||||
lookup_text += text;
|
||||
}
|
||||
|
||||
if (i != text_size - 1) {
|
||||
lookup_text += "\n";
|
||||
}
|
||||
}
|
||||
return lookup_text.as_string();
|
||||
}
|
||||
|
||||
void CodeEdit::set_symbol_lookup_word_as_valid(bool p_valid) {
|
||||
symbol_lookup_word = p_valid ? symbol_lookup_new_word : "";
|
||||
symbol_lookup_new_word = "";
|
||||
_set_symbol_lookup_word(symbol_lookup_word);
|
||||
}
|
||||
|
||||
void CodeEdit::_bind_methods() {
|
||||
/* Indent management */
|
||||
ClassDB::bind_method(D_METHOD("set_indent_size", "size"), &CodeEdit::set_indent_size);
|
||||
@ -1762,6 +2015,22 @@ void CodeEdit::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("indent_lines"), &CodeEdit::indent_lines);
|
||||
ClassDB::bind_method(D_METHOD("unindent_lines"), &CodeEdit::unindent_lines);
|
||||
|
||||
/* Auto brace completion */
|
||||
ClassDB::bind_method(D_METHOD("set_auto_brace_completion_enabled", "enable"), &CodeEdit::set_auto_brace_completion_enabled);
|
||||
ClassDB::bind_method(D_METHOD("is_auto_brace_completion_enabled"), &CodeEdit::is_auto_brace_completion_enabled);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_highlight_matching_braces_enabled", "enable"), &CodeEdit::set_highlight_matching_braces_enabled);
|
||||
ClassDB::bind_method(D_METHOD("is_highlight_matching_braces_enabled"), &CodeEdit::is_highlight_matching_braces_enabled);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("add_auto_brace_completion_pair", "start_key", "end_key"), &CodeEdit::add_auto_brace_completion_pair);
|
||||
ClassDB::bind_method(D_METHOD("set_auto_brace_completion_pairs", "pairs"), &CodeEdit::set_auto_brace_completion_pairs);
|
||||
ClassDB::bind_method(D_METHOD("get_auto_brace_completion_pairs"), &CodeEdit::get_auto_brace_completion_pairs);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("has_auto_brace_completion_open_key", "open_key"), &CodeEdit::has_auto_brace_completion_open_key);
|
||||
ClassDB::bind_method(D_METHOD("has_auto_brace_completion_close_key", "close_key"), &CodeEdit::has_auto_brace_completion_close_key);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("get_auto_brace_completion_close_key", "open_key"), &CodeEdit::get_auto_brace_completion_close_key);
|
||||
|
||||
/* Main Gutter */
|
||||
ClassDB::bind_method(D_METHOD("_main_gutter_draw_callback"), &CodeEdit::_main_gutter_draw_callback);
|
||||
|
||||
@ -1890,20 +2159,36 @@ void CodeEdit::_bind_methods() {
|
||||
BIND_VMETHOD(MethodInfo("_request_code_completion", PropertyInfo(Variant::BOOL, "force")));
|
||||
BIND_VMETHOD(MethodInfo(Variant::ARRAY, "_filter_code_completion_candidates", PropertyInfo(Variant::ARRAY, "candidates")));
|
||||
|
||||
/* Line length guidelines */
|
||||
ClassDB::bind_method(D_METHOD("set_line_length_guidelines", "guideline_columns"), &CodeEdit::set_line_length_guidelines);
|
||||
ClassDB::bind_method(D_METHOD("get_line_length_guidelines"), &CodeEdit::get_line_length_guidelines);
|
||||
|
||||
/* Symbol lookup */
|
||||
ClassDB::bind_method(D_METHOD("set_symbol_lookup_on_click_enabled", "enable"), &CodeEdit::set_symbol_lookup_on_click_enabled);
|
||||
ClassDB::bind_method(D_METHOD("is_symbol_lookup_on_click_enabled"), &CodeEdit::is_symbol_lookup_on_click_enabled);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("get_text_for_symbol_lookup"), &CodeEdit::get_text_for_symbol_lookup);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_symbol_lookup_word_as_valid", "valid"), &CodeEdit::set_symbol_lookup_word_as_valid);
|
||||
|
||||
/* Inspector */
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "draw_breakpoints_gutter"), "set_draw_breakpoints_gutter", "is_drawing_breakpoints_gutter");
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "draw_bookmarks"), "set_draw_bookmarks_gutter", "is_drawing_bookmarks_gutter");
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "draw_executing_lines"), "set_draw_executing_lines_gutter", "is_drawing_executing_lines_gutter");
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "draw_line_numbers"), "set_draw_line_numbers", "is_draw_line_numbers_enabled");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "zero_pad_line_numbers"), "set_line_numbers_zero_padded", "is_line_numbers_zero_padded");
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "draw_fold_gutter"), "set_draw_fold_gutter", "is_drawing_fold_gutter");
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "symbol_lookup_on_click"), "set_symbol_lookup_on_click_enabled", "is_symbol_lookup_on_click_enabled");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "line_folding"), "set_line_folding_enabled", "is_line_folding_enabled");
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::PACKED_INT32_ARRAY, "line_length_guidelines"), "set_line_length_guidelines", "get_line_length_guidelines");
|
||||
|
||||
ADD_GROUP("Gutters", "gutters_");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "gutters_draw_breakpoints_gutter"), "set_draw_breakpoints_gutter", "is_drawing_breakpoints_gutter");
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "gutters_draw_bookmarks"), "set_draw_bookmarks_gutter", "is_drawing_bookmarks_gutter");
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "gutters_draw_executing_lines"), "set_draw_executing_lines_gutter", "is_drawing_executing_lines_gutter");
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "gutters_draw_line_numbers"), "set_draw_line_numbers", "is_draw_line_numbers_enabled");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "gutters_zero_pad_line_numbers"), "set_line_numbers_zero_padded", "is_line_numbers_zero_padded");
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "gutters_draw_fold_gutter"), "set_draw_fold_gutter", "is_drawing_fold_gutter");
|
||||
|
||||
ADD_GROUP("Delimiters", "delimiter_");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::PACKED_STRING_ARRAY, "delimiter_strings"), "set_string_delimiters", "get_string_delimiters");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::PACKED_STRING_ARRAY, "delimiter_comments"), "set_comment_delimiters", "get_comment_delimiters");
|
||||
@ -1918,11 +2203,74 @@ void CodeEdit::_bind_methods() {
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "indent_automatic"), "set_auto_indent_enabled", "is_auto_indent_enabled");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::PACKED_STRING_ARRAY, "indent_automatic_prefixes"), "set_auto_indent_prefixes", "get_auto_indent_prefixes");
|
||||
|
||||
ADD_GROUP("Auto brace completion", "auto_brace_completion_");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "auto_brace_completion_enabled"), "set_auto_brace_completion_enabled", "is_auto_brace_completion_enabled");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "auto_brace_completion_highlight_matching"), "set_highlight_matching_braces_enabled", "is_highlight_matching_braces_enabled");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "auto_brace_completion_pairs"), "set_auto_brace_completion_pairs", "get_auto_brace_completion_pairs");
|
||||
|
||||
/* Signals */
|
||||
/* Gutters */
|
||||
ADD_SIGNAL(MethodInfo("breakpoint_toggled", PropertyInfo(Variant::INT, "line")));
|
||||
|
||||
/* Code Completion */
|
||||
ADD_SIGNAL(MethodInfo("request_code_completion"));
|
||||
|
||||
/* Symbol lookup */
|
||||
ADD_SIGNAL(MethodInfo("symbol_lookup", PropertyInfo(Variant::STRING, "symbol"), PropertyInfo(Variant::INT, "line"), PropertyInfo(Variant::INT, "column")));
|
||||
ADD_SIGNAL(MethodInfo("symbol_validate", PropertyInfo(Variant::STRING, "symbol")));
|
||||
}
|
||||
|
||||
/* Auto brace completion */
|
||||
int CodeEdit::_get_auto_brace_pair_open_at_pos(int p_line, int p_col) {
|
||||
const String &line = get_line(p_line);
|
||||
|
||||
/* Should be fast enough, expecting low amount of pairs... */
|
||||
for (int i = 0; i < auto_brace_completion_pairs.size(); i++) {
|
||||
const String &open_key = auto_brace_completion_pairs[i].open_key;
|
||||
if (p_col - open_key.length() < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
bool is_match = true;
|
||||
for (int j = 0; j < open_key.length(); j++) {
|
||||
if (line[(p_col - 1) - j] != open_key[(open_key.length() - 1) - j]) {
|
||||
is_match = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_match) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int CodeEdit::_get_auto_brace_pair_close_at_pos(int p_line, int p_col) {
|
||||
const String &line = get_line(p_line);
|
||||
|
||||
/* Should be fast enough, expecting low amount of pairs... */
|
||||
for (int i = 0; i < auto_brace_completion_pairs.size(); i++) {
|
||||
if (p_col + auto_brace_completion_pairs[i].close_key.length() > line.length()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
bool is_match = true;
|
||||
for (int j = 0; j < auto_brace_completion_pairs[i].close_key.length(); j++) {
|
||||
if (line[p_col + j] != auto_brace_completion_pairs[i].close_key[j]) {
|
||||
is_match = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_match) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Gutters */
|
||||
void CodeEdit::_gutter_clicked(int p_line, int p_gutter) {
|
||||
if (p_gutter == main_gutter) {
|
||||
if (draw_breakpoints) {
|
||||
@ -2547,6 +2895,17 @@ CodeEdit::CodeEdit() {
|
||||
auto_indent_prefixes.insert('[');
|
||||
auto_indent_prefixes.insert('(');
|
||||
|
||||
/* Auto brace completion */
|
||||
add_auto_brace_completion_pair("(", ")");
|
||||
add_auto_brace_completion_pair("{", "}");
|
||||
add_auto_brace_completion_pair("[", "]");
|
||||
add_auto_brace_completion_pair("\"", "\"");
|
||||
add_auto_brace_completion_pair("\'", "\'");
|
||||
|
||||
/* Delimiter traking */
|
||||
add_string_delimiter("\"", "\"", false);
|
||||
add_string_delimiter("\'", "\'", false);
|
||||
|
||||
/* Text Direction */
|
||||
set_layout_direction(LAYOUT_DIRECTION_LTR);
|
||||
set_text_direction(TEXT_DIRECTION_LTR);
|
||||
|
@ -66,6 +66,19 @@ private:
|
||||
|
||||
void _new_line(bool p_split_current_line = true, bool p_above = false);
|
||||
|
||||
/* Auto brace completion */
|
||||
bool auto_brace_completion_enabled = false;
|
||||
|
||||
/* BracePair open_key must be uniquie and ordered by length. */
|
||||
struct BracePair {
|
||||
String open_key = "";
|
||||
String close_key = "";
|
||||
};
|
||||
Vector<BracePair> auto_brace_completion_pairs;
|
||||
|
||||
int _get_auto_brace_pair_open_at_pos(int p_line, int p_col);
|
||||
int _get_auto_brace_pair_close_at_pos(int p_line, int p_col);
|
||||
|
||||
/* Main Gutter */
|
||||
enum MainGutterType {
|
||||
MAIN_GUTTER_BREAKPOINT = 0x01,
|
||||
@ -112,7 +125,7 @@ private:
|
||||
void _update_gutter_indexes();
|
||||
|
||||
/* Line Folding */
|
||||
bool line_folding_enabled = true;
|
||||
bool line_folding_enabled = false;
|
||||
|
||||
/* Delimiters */
|
||||
enum DelimiterType {
|
||||
@ -210,6 +223,16 @@ private:
|
||||
|
||||
void _lines_edited_from(int p_from_line, int p_to_line);
|
||||
|
||||
/* Line length guidelines */
|
||||
TypedArray<int> line_length_guideline_columns;
|
||||
Color line_length_guideline_color;
|
||||
|
||||
/* Symbol lookup */
|
||||
bool symbol_lookup_on_click_enabled = false;
|
||||
|
||||
String symbol_lookup_new_word = "";
|
||||
String symbol_lookup_word = "";
|
||||
|
||||
protected:
|
||||
void _gui_input(const Ref<InputEvent> &p_gui_input) override;
|
||||
void _notification(int p_what);
|
||||
@ -217,7 +240,9 @@ protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
/* General overrides */
|
||||
virtual CursorShape get_cursor_shape(const Point2 &p_pos = Point2i()) const override;
|
||||
virtual void handle_unicode_input(uint32_t p_unicode) override;
|
||||
|
||||
/* Indent management */
|
||||
void set_indent_size(const int p_size);
|
||||
@ -240,6 +265,22 @@ public:
|
||||
|
||||
virtual void backspace() override;
|
||||
|
||||
/* Auto brace completion */
|
||||
void set_auto_brace_completion_enabled(bool p_enabled);
|
||||
bool is_auto_brace_completion_enabled() const;
|
||||
|
||||
void set_highlight_matching_braces_enabled(bool p_enabled);
|
||||
bool is_highlight_matching_braces_enabled() const;
|
||||
|
||||
void add_auto_brace_completion_pair(const String &p_open_key, const String &p_close_key);
|
||||
void set_auto_brace_completion_pairs(const Dictionary &p_auto_brace_completion_pairs);
|
||||
Dictionary get_auto_brace_completion_pairs() const;
|
||||
|
||||
bool has_auto_brace_completion_open_key(const String &p_open_key) const;
|
||||
bool has_auto_brace_completion_close_key(const String &p_close_key) const;
|
||||
|
||||
String get_auto_brace_completion_close_key(const String &p_open_key) const;
|
||||
|
||||
/* Main Gutter */
|
||||
void set_draw_breakpoints_gutter(bool p_draw);
|
||||
bool is_drawing_breakpoints_gutter() const;
|
||||
@ -347,6 +388,18 @@ public:
|
||||
void confirm_code_completion(bool p_replace = false);
|
||||
void cancel_code_completion();
|
||||
|
||||
/* Line length guidelines */
|
||||
void set_line_length_guidelines(TypedArray<int> p_guideline_columns);
|
||||
TypedArray<int> get_line_length_guidelines() const;
|
||||
|
||||
/* Symbol lookup */
|
||||
void set_symbol_lookup_on_click_enabled(bool p_enabled);
|
||||
bool is_symbol_lookup_on_click_enabled() const;
|
||||
|
||||
String get_text_for_symbol_lookup();
|
||||
|
||||
void set_symbol_lookup_word_as_valid(bool p_valid);
|
||||
|
||||
CodeEdit();
|
||||
~CodeEdit();
|
||||
};
|
||||
|
@ -63,45 +63,6 @@ static bool _is_char(char32_t c) {
|
||||
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_';
|
||||
}
|
||||
|
||||
static bool _is_pair_right_symbol(char32_t c) {
|
||||
return c == '"' ||
|
||||
c == '\'' ||
|
||||
c == ')' ||
|
||||
c == ']' ||
|
||||
c == '}';
|
||||
}
|
||||
|
||||
static bool _is_pair_left_symbol(char32_t c) {
|
||||
return c == '"' ||
|
||||
c == '\'' ||
|
||||
c == '(' ||
|
||||
c == '[' ||
|
||||
c == '{';
|
||||
}
|
||||
|
||||
static bool _is_pair_symbol(char32_t c) {
|
||||
return _is_pair_left_symbol(c) || _is_pair_right_symbol(c);
|
||||
}
|
||||
|
||||
static char32_t _get_right_pair_symbol(char32_t c) {
|
||||
if (c == '"') {
|
||||
return '"';
|
||||
}
|
||||
if (c == '\'') {
|
||||
return '\'';
|
||||
}
|
||||
if (c == '(') {
|
||||
return ')';
|
||||
}
|
||||
if (c == '[') {
|
||||
return ']';
|
||||
}
|
||||
if (c == '{') {
|
||||
return '}';
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TextEdit::Text::set_font(const Ref<Font> &p_font) {
|
||||
@ -633,29 +594,6 @@ void TextEdit::_notification(int p_what) {
|
||||
RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2i(), get_size()), cache.background_color);
|
||||
}
|
||||
|
||||
if (line_length_guidelines) {
|
||||
const int hard_x = xmargin_beg + (int)cache.font->get_char_size('0', 0, cache.font_size).width * line_length_guideline_hard_col - cursor.x_ofs;
|
||||
if (hard_x > xmargin_beg && hard_x < xmargin_end) {
|
||||
if (rtl) {
|
||||
RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2(size.width - hard_x, 0), Point2(size.width - hard_x, size.height), cache.line_length_guideline_color);
|
||||
} else {
|
||||
RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2(hard_x, 0), Point2(hard_x, size.height), cache.line_length_guideline_color);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw a "Soft" line length guideline, less visible than the hard line length guideline.
|
||||
// It's usually set to a lower column compared to the hard line length guideline.
|
||||
// Only drawn if its column differs from the hard line length guideline.
|
||||
const int soft_x = xmargin_beg + (int)cache.font->get_char_size('0', 0, cache.font_size).width * line_length_guideline_soft_col - cursor.x_ofs;
|
||||
if (hard_x != soft_x && soft_x > xmargin_beg && soft_x < xmargin_end) {
|
||||
if (rtl) {
|
||||
RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2(size.width - soft_x, 0), Point2(size.width - soft_x, size.height), cache.line_length_guideline_color * Color(1, 1, 1, 0.5));
|
||||
} else {
|
||||
RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2(soft_x, 0), Point2(soft_x, size.height), cache.line_length_guideline_color * Color(1, 1, 1, 0.5));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int brace_open_match_line = -1;
|
||||
int brace_open_match_column = -1;
|
||||
bool brace_open_matching = false;
|
||||
@ -665,7 +603,7 @@ void TextEdit::_notification(int p_what) {
|
||||
bool brace_close_matching = false;
|
||||
bool brace_close_mismatch = false;
|
||||
|
||||
if (brace_matching_enabled && cursor.line >= 0 && cursor.line < text.size() && cursor.column >= 0) {
|
||||
if (highlight_matching_braces_enabled && cursor.line >= 0 && cursor.line < text.size() && cursor.column >= 0) {
|
||||
if (cursor.column < text[cursor.line].length()) {
|
||||
// Check for open.
|
||||
char32_t c = text[cursor.line][cursor.column];
|
||||
@ -1239,11 +1177,11 @@ void TextEdit::_notification(int p_what) {
|
||||
}
|
||||
}
|
||||
|
||||
if (!clipped && select_identifiers_enabled && highlighted_word.length() != 0) { // Highlight word
|
||||
if (_is_char(highlighted_word[0]) || highlighted_word[0] == '.') {
|
||||
int highlighted_word_col = _get_column_pos_of_word(highlighted_word, str, SEARCH_MATCH_CASE | SEARCH_WHOLE_WORDS, 0);
|
||||
if (!clipped && lookup_symbol_word.length() != 0) { // Highlight word
|
||||
if (_is_char(lookup_symbol_word[0]) || lookup_symbol_word[0] == '.') {
|
||||
int highlighted_word_col = _get_column_pos_of_word(lookup_symbol_word, str, SEARCH_MATCH_CASE | SEARCH_WHOLE_WORDS, 0);
|
||||
while (highlighted_word_col != -1) {
|
||||
Vector<Vector2> sel = TS->shaped_text_get_selection(rid, highlighted_word_col + start, highlighted_word_col + highlighted_word.length() + start);
|
||||
Vector<Vector2> sel = TS->shaped_text_get_selection(rid, highlighted_word_col + start, highlighted_word_col + lookup_symbol_word.length() + start);
|
||||
for (int j = 0; j < sel.size(); j++) {
|
||||
Rect2 rect = Rect2(sel[j].x + char_margin + ofs_x, ofs_y, sel[j].y - sel[j].x, row_height);
|
||||
if (rect.position.x + rect.size.x <= xmargin_beg || rect.position.x > xmargin_end) {
|
||||
@ -1260,7 +1198,7 @@ void TextEdit::_notification(int p_what) {
|
||||
draw_rect(rect, cache.font_selected_color);
|
||||
}
|
||||
|
||||
highlighted_word_col = _get_column_pos_of_word(highlighted_word, str, SEARCH_MATCH_CASE | SEARCH_WHOLE_WORDS, highlighted_word_col + 1);
|
||||
highlighted_word_col = _get_column_pos_of_word(lookup_symbol_word, str, SEARCH_MATCH_CASE | SEARCH_WHOLE_WORDS, highlighted_word_col + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1308,7 +1246,7 @@ void TextEdit::_notification(int p_what) {
|
||||
|
||||
int char_pos = char_ofs + char_margin + ofs_x;
|
||||
if (char_pos >= xmargin_beg) {
|
||||
if (brace_matching_enabled) {
|
||||
if (highlight_matching_braces_enabled) {
|
||||
if ((brace_open_match_line == line && brace_open_match_column == glyphs[j].start) ||
|
||||
(cursor.column == glyphs[j].start && cursor.line == line && cursor_wrap_index == line_wrap_index && (brace_open_matching || brace_open_mismatch))) {
|
||||
if (brace_open_mismatch) {
|
||||
@ -1567,130 +1505,6 @@ void TextEdit::_notification(int p_what) {
|
||||
}
|
||||
}
|
||||
|
||||
void TextEdit::_consume_pair_symbol(char32_t ch) {
|
||||
int cursor_position_to_move = cursor_get_column() + 1;
|
||||
|
||||
char32_t ch_single[2] = { ch, 0 };
|
||||
char32_t ch_single_pair[2] = { _get_right_pair_symbol(ch), 0 };
|
||||
char32_t ch_pair[3] = { ch, _get_right_pair_symbol(ch), 0 };
|
||||
|
||||
if (is_selection_active()) {
|
||||
int new_column, new_line;
|
||||
|
||||
begin_complex_operation();
|
||||
_insert_text(get_selection_from_line(), get_selection_from_column(),
|
||||
ch_single,
|
||||
&new_line, &new_column);
|
||||
|
||||
int to_col_offset = 0;
|
||||
if (get_selection_from_line() == get_selection_to_line()) {
|
||||
to_col_offset = 1;
|
||||
}
|
||||
|
||||
_insert_text(get_selection_to_line(),
|
||||
get_selection_to_column() + to_col_offset,
|
||||
ch_single_pair,
|
||||
&new_line, &new_column);
|
||||
end_complex_operation();
|
||||
|
||||
cursor_set_line(get_selection_to_line());
|
||||
cursor_set_column(get_selection_to_column() + to_col_offset);
|
||||
|
||||
deselect();
|
||||
update();
|
||||
return;
|
||||
}
|
||||
|
||||
if ((ch == '\'' || ch == '"') &&
|
||||
cursor_get_column() > 0 && _is_text_char(text[cursor.line][cursor_get_column() - 1]) && !_is_pair_right_symbol(text[cursor.line][cursor_get_column()])) {
|
||||
insert_text_at_cursor(ch_single);
|
||||
cursor_set_column(cursor_position_to_move);
|
||||
return;
|
||||
}
|
||||
|
||||
if (cursor_get_column() < text[cursor.line].length()) {
|
||||
if (_is_text_char(text[cursor.line][cursor_get_column()])) {
|
||||
insert_text_at_cursor(ch_single);
|
||||
cursor_set_column(cursor_position_to_move);
|
||||
return;
|
||||
}
|
||||
if (_is_pair_right_symbol(ch) &&
|
||||
text[cursor.line][cursor_get_column()] == ch) {
|
||||
cursor_set_column(cursor_position_to_move);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
String line = text[cursor.line];
|
||||
|
||||
bool in_single_quote = false;
|
||||
bool in_double_quote = false;
|
||||
bool found_comment = false;
|
||||
|
||||
int c = 0;
|
||||
while (c < line.length()) {
|
||||
if (line[c] == '\\') {
|
||||
c++; // Skip quoted anything.
|
||||
|
||||
if (cursor.column == c) {
|
||||
break;
|
||||
}
|
||||
} else if (!in_single_quote && !in_double_quote && line[c] == '#') {
|
||||
found_comment = true;
|
||||
break;
|
||||
} else {
|
||||
if (line[c] == '\'' && !in_double_quote) {
|
||||
in_single_quote = !in_single_quote;
|
||||
} else if (line[c] == '"' && !in_single_quote) {
|
||||
in_double_quote = !in_double_quote;
|
||||
}
|
||||
}
|
||||
|
||||
c++;
|
||||
|
||||
if (cursor.column == c) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Do not need to duplicate quotes while in comments
|
||||
if (found_comment) {
|
||||
insert_text_at_cursor(ch_single);
|
||||
cursor_set_column(cursor_position_to_move);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Disallow inserting duplicated quotes while already in string
|
||||
if ((in_single_quote || in_double_quote) && (ch == '"' || ch == '\'')) {
|
||||
insert_text_at_cursor(ch_single);
|
||||
cursor_set_column(cursor_position_to_move);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
insert_text_at_cursor(ch_pair);
|
||||
cursor_set_column(cursor_position_to_move);
|
||||
}
|
||||
|
||||
void TextEdit::_consume_backspace_for_pair_symbol(int prev_line, int prev_column) {
|
||||
bool remove_right_symbol = false;
|
||||
|
||||
if (cursor.column < text[cursor.line].length() && cursor.column > 0) {
|
||||
char32_t left_char = text[cursor.line][cursor.column - 1];
|
||||
char32_t right_char = text[cursor.line][cursor.column];
|
||||
|
||||
if (right_char == _get_right_pair_symbol(left_char)) {
|
||||
remove_right_symbol = true;
|
||||
}
|
||||
}
|
||||
if (remove_right_symbol) {
|
||||
_remove_text(prev_line, prev_column, cursor.line, cursor.column + 1);
|
||||
} else {
|
||||
_remove_text(prev_line, prev_column, cursor.line, cursor.column);
|
||||
}
|
||||
}
|
||||
|
||||
void TextEdit::backspace() {
|
||||
ScriptInstance *si = get_script_instance();
|
||||
if (si && si->has_method("_backspace")) {
|
||||
@ -1719,14 +1533,7 @@ void TextEdit::backspace() {
|
||||
if (is_line_hidden(cursor.line)) {
|
||||
set_line_as_hidden(prev_line, true);
|
||||
}
|
||||
|
||||
if (auto_brace_completion_enabled &&
|
||||
cursor.column > 0 &&
|
||||
_is_pair_left_symbol(text[cursor.line][cursor.column - 1])) {
|
||||
_consume_backspace_for_pair_symbol(prev_line, prev_column);
|
||||
} else {
|
||||
_remove_text(prev_line, prev_column, cursor.line, cursor.column);
|
||||
}
|
||||
_remove_text(prev_line, prev_column, cursor.line, cursor.column);
|
||||
|
||||
cursor_set_line(prev_line, false, true);
|
||||
cursor_set_column(prev_column);
|
||||
@ -2101,6 +1908,7 @@ void TextEdit::delete_selection() {
|
||||
}
|
||||
|
||||
selection.active = false;
|
||||
selection.selecting_mode = SelectionMode::SELECTION_MODE_NONE;
|
||||
_remove_text(selection.from_line, selection.from_column, selection.to_line, selection.to_column);
|
||||
cursor_set_line(selection.from_line, false, false);
|
||||
cursor_set_column(selection.from_column);
|
||||
@ -2137,13 +1945,21 @@ void TextEdit::_move_cursor_document_end(bool p_select) {
|
||||
}
|
||||
}
|
||||
|
||||
void TextEdit::_handle_unicode_character(uint32_t unicode, bool p_had_selection) {
|
||||
if (p_had_selection) {
|
||||
void TextEdit::handle_unicode_input(uint32_t p_unicode) {
|
||||
ScriptInstance *si = get_script_instance();
|
||||
if (si && si->has_method("_handle_unicode_input")) {
|
||||
si->call("_handle_unicode_input", p_unicode);
|
||||
return;
|
||||
}
|
||||
|
||||
bool had_selection = selection.active;
|
||||
if (had_selection) {
|
||||
begin_complex_operation();
|
||||
delete_selection();
|
||||
}
|
||||
|
||||
// Remove the old character if in insert mode and no selection.
|
||||
if (insert_mode && !p_had_selection) {
|
||||
if (insert_mode && !had_selection) {
|
||||
begin_complex_operation();
|
||||
|
||||
// Make sure we don't try and remove empty space.
|
||||
@ -2152,15 +1968,10 @@ void TextEdit::_handle_unicode_character(uint32_t unicode, bool p_had_selection)
|
||||
}
|
||||
}
|
||||
|
||||
const char32_t chr[2] = { (char32_t)unicode, 0 };
|
||||
const char32_t chr[2] = { (char32_t)p_unicode, 0 };
|
||||
insert_text_at_cursor(chr);
|
||||
|
||||
if (auto_brace_completion_enabled && _is_pair_symbol(chr[0])) {
|
||||
_consume_pair_symbol(chr[0]);
|
||||
} else {
|
||||
_insert_text_at_cursor(chr);
|
||||
}
|
||||
|
||||
if ((insert_mode && !p_had_selection) || (selection.active != p_had_selection)) {
|
||||
if ((insert_mode && !had_selection) || (had_selection)) {
|
||||
end_complex_operation();
|
||||
}
|
||||
}
|
||||
@ -2301,6 +2112,10 @@ void TextEdit::_get_minimap_mouse_row(const Point2i &p_mouse, int &r_row) const
|
||||
r_row = row;
|
||||
}
|
||||
|
||||
bool TextEdit::is_dragging_cursor() const {
|
||||
return dragging_selection || dragging_minimap;
|
||||
}
|
||||
|
||||
void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
|
||||
ERR_FAIL_COND(p_gui_input.is_null());
|
||||
|
||||
@ -2478,14 +2293,6 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
|
||||
}
|
||||
} else {
|
||||
if (mb->get_button_index() == MOUSE_BUTTON_LEFT) {
|
||||
if (mb->is_command_pressed() && highlighted_word != String()) {
|
||||
int row, col;
|
||||
_get_mouse_pos(Point2i(mpos.x, mpos.y), row, col);
|
||||
|
||||
emit_signal(SNAME("symbol_lookup"), highlighted_word, row, col);
|
||||
return;
|
||||
}
|
||||
|
||||
dragging_minimap = false;
|
||||
dragging_selection = false;
|
||||
can_drag_minimap = false;
|
||||
@ -2520,18 +2327,6 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
|
||||
if (is_layout_rtl()) {
|
||||
mpos.x = get_size().x - mpos.x;
|
||||
}
|
||||
if (select_identifiers_enabled) {
|
||||
if (!dragging_minimap && !dragging_selection && mm->is_command_pressed() && mm->get_button_mask() == 0) {
|
||||
String new_word = get_word_at_pos(mpos);
|
||||
if (new_word != highlighted_word) {
|
||||
emit_signal(SNAME("symbol_validate"), new_word);
|
||||
}
|
||||
} else {
|
||||
if (highlighted_word != String()) {
|
||||
set_highlighted_word(String());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mm->get_button_mask() & MOUSE_BUTTON_MASK_LEFT && get_viewport()->gui_get_drag_data() == Variant()) { // Ignore if dragging.
|
||||
_reset_caret_blink_timer();
|
||||
@ -2566,23 +2361,6 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
|
||||
Ref<InputEventKey> k = p_gui_input;
|
||||
|
||||
if (k.is_valid()) {
|
||||
// Ctrl + Hover symbols
|
||||
#ifdef OSX_ENABLED
|
||||
if (k->get_keycode() == KEY_META) {
|
||||
#else
|
||||
if (k->get_keycode() == KEY_CTRL) {
|
||||
#endif
|
||||
if (select_identifiers_enabled) {
|
||||
if (k->is_pressed() && !dragging_minimap && !dragging_selection) {
|
||||
Point2 mp = _get_local_mouse_pos();
|
||||
emit_signal(SNAME("symbol_validate"), get_word_at_pos(mp));
|
||||
} else {
|
||||
set_highlighted_word(String());
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!k->is_pressed()) {
|
||||
return;
|
||||
}
|
||||
@ -2598,9 +2376,6 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
|
||||
// * No Modifiers are pressed (except shift)
|
||||
bool allow_unicode_handling = !(k->is_command_pressed() || k->is_ctrl_pressed() || k->is_alt_pressed() || k->is_meta_pressed());
|
||||
|
||||
// Save here for insert mode, just in case it is cleared in the following section.
|
||||
bool had_selection = selection.active;
|
||||
|
||||
selection.selecting_text = false;
|
||||
|
||||
// Check and handle all built in shortcuts.
|
||||
@ -2806,9 +2581,9 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle Unicode (if no modifiers active).
|
||||
if (allow_unicode_handling && !readonly && k->get_unicode() >= 32) {
|
||||
// Handle Unicode (if no modifiers active).
|
||||
_handle_unicode_character(k->get_unicode(), had_selection);
|
||||
handle_unicode_input(k->get_unicode());
|
||||
accept_event();
|
||||
return;
|
||||
}
|
||||
@ -3151,16 +2926,6 @@ void TextEdit::_remove_text(int p_from_line, int p_from_column, int p_to_line, i
|
||||
current_op = op;
|
||||
}
|
||||
|
||||
void TextEdit::_insert_text_at_cursor(const String &p_text) {
|
||||
int new_column, new_line;
|
||||
_insert_text(cursor.line, cursor.column, p_text, &new_line, &new_column);
|
||||
_update_scrollbars();
|
||||
cursor_set_line(new_line, false);
|
||||
cursor_set_column(new_column);
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
int TextEdit::get_char_count() {
|
||||
int totalsize = 0;
|
||||
|
||||
@ -3704,23 +3469,19 @@ int TextEdit::get_column_x_offset_for_line(int p_char, int p_line) const {
|
||||
|
||||
void TextEdit::insert_text_at_cursor(const String &p_text) {
|
||||
if (selection.active) {
|
||||
cursor_set_line(selection.from_line, false);
|
||||
cursor_set_column(selection.from_column);
|
||||
|
||||
_remove_text(selection.from_line, selection.from_column, selection.to_line, selection.to_column);
|
||||
selection.active = false;
|
||||
selection.selecting_mode = SelectionMode::SELECTION_MODE_NONE;
|
||||
delete_selection();
|
||||
}
|
||||
|
||||
_insert_text_at_cursor(p_text);
|
||||
int new_column, new_line;
|
||||
_insert_text(cursor.line, cursor.column, p_text, &new_line, &new_column);
|
||||
_update_scrollbars();
|
||||
|
||||
cursor_set_line(new_line, false);
|
||||
cursor_set_column(new_column);
|
||||
update();
|
||||
}
|
||||
|
||||
Control::CursorShape TextEdit::get_cursor_shape(const Point2 &p_pos) const {
|
||||
if (highlighted_word != String()) {
|
||||
return CURSOR_POINTING_HAND;
|
||||
}
|
||||
|
||||
int row, col;
|
||||
_get_mouse_pos(p_pos, row, col);
|
||||
|
||||
@ -3753,7 +3514,7 @@ void TextEdit::set_text(String p_text) {
|
||||
setting_text = true;
|
||||
if (!undo_enabled) {
|
||||
_clear();
|
||||
_insert_text_at_cursor(p_text);
|
||||
insert_text_at_cursor(p_text);
|
||||
}
|
||||
|
||||
if (undo_enabled) {
|
||||
@ -3762,7 +3523,7 @@ void TextEdit::set_text(String p_text) {
|
||||
|
||||
begin_complex_operation();
|
||||
_remove_text(0, 0, MAX(0, get_line_count() - 1), MAX(get_line(MAX(get_line_count() - 1, 0)).size() - 1, 0));
|
||||
_insert_text_at_cursor(p_text);
|
||||
insert_text_at_cursor(p_text);
|
||||
end_complex_operation();
|
||||
selection.active = false;
|
||||
}
|
||||
@ -3903,30 +3664,6 @@ bool TextEdit::get_draw_control_chars() const {
|
||||
return draw_control_chars;
|
||||
}
|
||||
|
||||
String TextEdit::get_text_for_lookup_completion() {
|
||||
int row, col;
|
||||
Point2i mp = _get_local_mouse_pos();
|
||||
_get_mouse_pos(mp, row, col);
|
||||
|
||||
String longthing;
|
||||
int len = text.size();
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (i == row) {
|
||||
longthing += text[i].substr(0, col);
|
||||
longthing += String::chr(0xFFFF); // Not unicode, represents the cursor.
|
||||
longthing += text[i].substr(col, text[i].size());
|
||||
} else {
|
||||
longthing += text[i];
|
||||
}
|
||||
|
||||
if (i != len - 1) {
|
||||
longthing += "\n";
|
||||
}
|
||||
}
|
||||
|
||||
return longthing;
|
||||
}
|
||||
|
||||
String TextEdit::get_line(int line) const {
|
||||
if (line < 0 || line >= text.size()) {
|
||||
return "";
|
||||
@ -4015,9 +3752,8 @@ void TextEdit::_update_caches() {
|
||||
cache.font_readonly_color = get_theme_color(SNAME("font_readonly_color"));
|
||||
cache.selection_color = get_theme_color(SNAME("selection_color"));
|
||||
cache.current_line_color = get_theme_color(SNAME("current_line_color"));
|
||||
cache.line_length_guideline_color = get_theme_color(SNAME("line_length_guideline_color"));
|
||||
cache.code_folding_color = get_theme_color(SNAME("code_folding_color"), SNAME("CodeEdit"));
|
||||
cache.brace_mismatch_color = get_theme_color(SNAME("brace_mismatch_color"));
|
||||
cache.brace_mismatch_color = get_theme_color(SNAME("brace_mismatch_color"), SNAME("CodeEdit"));
|
||||
cache.word_highlighted_color = get_theme_color(SNAME("word_highlighted_color"));
|
||||
cache.search_result_color = get_theme_color(SNAME("search_result_color"));
|
||||
cache.search_result_border_color = get_theme_color(SNAME("search_result_border_color"));
|
||||
@ -4364,7 +4100,7 @@ void TextEdit::paste() {
|
||||
clipboard += ins;
|
||||
}
|
||||
|
||||
_insert_text_at_cursor(clipboard);
|
||||
insert_text_at_cursor(clipboard);
|
||||
end_complex_operation();
|
||||
|
||||
update();
|
||||
@ -5324,21 +5060,6 @@ void TextEdit::insert_at(const String &p_text, int at) {
|
||||
}
|
||||
}
|
||||
|
||||
void TextEdit::set_show_line_length_guidelines(bool p_show) {
|
||||
line_length_guidelines = p_show;
|
||||
update();
|
||||
}
|
||||
|
||||
void TextEdit::set_line_length_guideline_soft_column(int p_column) {
|
||||
line_length_guideline_soft_col = p_column;
|
||||
update();
|
||||
}
|
||||
|
||||
void TextEdit::set_line_length_guideline_hard_column(int p_column) {
|
||||
line_length_guideline_hard_col = p_column;
|
||||
update();
|
||||
}
|
||||
|
||||
void TextEdit::set_draw_minimap(bool p_draw) {
|
||||
if (draw_minimap != p_draw) {
|
||||
draw_minimap = p_draw;
|
||||
@ -5515,19 +5236,11 @@ void TextEdit::menu_option(int p_option) {
|
||||
}
|
||||
}
|
||||
|
||||
void TextEdit::set_highlighted_word(const String &new_word) {
|
||||
highlighted_word = new_word;
|
||||
void TextEdit::_set_symbol_lookup_word(const String &p_symbol) {
|
||||
lookup_symbol_word = p_symbol;
|
||||
update();
|
||||
}
|
||||
|
||||
void TextEdit::set_select_identifiers_on_hover(bool p_enable) {
|
||||
select_identifiers_enabled = p_enable;
|
||||
}
|
||||
|
||||
bool TextEdit::is_selecting_identifiers_on_hover_enabled() const {
|
||||
return select_identifiers_enabled;
|
||||
}
|
||||
|
||||
void TextEdit::set_context_menu_enabled(bool p_enable) {
|
||||
context_menu_enabled = p_enable;
|
||||
}
|
||||
@ -5719,6 +5432,7 @@ void TextEdit::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("delete_selection"), &TextEdit::delete_selection);
|
||||
ClassDB::bind_method(D_METHOD("backspace"), &TextEdit::backspace);
|
||||
BIND_VMETHOD(MethodInfo("_backspace"));
|
||||
BIND_VMETHOD(MethodInfo("_handle_unicode_input", PropertyInfo(Variant::INT, "unicode")))
|
||||
|
||||
ClassDB::bind_method(D_METHOD("cut"), &TextEdit::cut);
|
||||
ClassDB::bind_method(D_METHOD("copy"), &TextEdit::copy);
|
||||
@ -5727,6 +5441,7 @@ void TextEdit::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("select", "from_line", "from_column", "to_line", "to_column"), &TextEdit::select);
|
||||
ClassDB::bind_method(D_METHOD("select_all"), &TextEdit::select_all);
|
||||
ClassDB::bind_method(D_METHOD("deselect"), &TextEdit::deselect);
|
||||
ClassDB::bind_method(D_METHOD("is_dragging_cursor"), &TextEdit::is_dragging_cursor);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("is_selection_active"), &TextEdit::is_selection_active);
|
||||
ClassDB::bind_method(D_METHOD("get_selection_from_line"), &TextEdit::get_selection_from_line);
|
||||
@ -5777,6 +5492,7 @@ void TextEdit::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("is_gutter_overwritable", "gutter"), &TextEdit::is_gutter_overwritable);
|
||||
ClassDB::bind_method(D_METHOD("merge_gutters", "from_line", "to_line"), &TextEdit::merge_gutters);
|
||||
ClassDB::bind_method(D_METHOD("set_gutter_custom_draw", "column", "object", "callback"), &TextEdit::set_gutter_custom_draw);
|
||||
ClassDB::bind_method(D_METHOD("get_total_gutter_width"), &TextEdit::get_total_gutter_width);
|
||||
|
||||
// Line gutters.
|
||||
ClassDB::bind_method(D_METHOD("set_line_gutter_metadata", "line", "gutter", "metadata"), &TextEdit::set_line_gutter_metadata);
|
||||
@ -5858,8 +5574,6 @@ void TextEdit::_bind_methods() {
|
||||
ADD_SIGNAL(MethodInfo("gutter_clicked", PropertyInfo(Variant::INT, "line"), PropertyInfo(Variant::INT, "gutter")));
|
||||
ADD_SIGNAL(MethodInfo("gutter_added"));
|
||||
ADD_SIGNAL(MethodInfo("gutter_removed"));
|
||||
ADD_SIGNAL(MethodInfo("symbol_lookup", PropertyInfo(Variant::STRING, "symbol"), PropertyInfo(Variant::INT, "row"), PropertyInfo(Variant::INT, "column")));
|
||||
ADD_SIGNAL(MethodInfo("symbol_validate", PropertyInfo(Variant::STRING, "symbol")));
|
||||
|
||||
BIND_ENUM_CONSTANT(MENU_CUT);
|
||||
BIND_ENUM_CONSTANT(MENU_COPY);
|
||||
|
@ -280,9 +280,6 @@ private:
|
||||
bool cursor_changed_dirty = false;
|
||||
bool text_changed_dirty = false;
|
||||
bool undo_enabled = true;
|
||||
bool line_length_guidelines = false;
|
||||
int line_length_guideline_soft_col = 80;
|
||||
int line_length_guideline_hard_col = 100;
|
||||
bool hiding_enabled = false;
|
||||
bool draw_minimap = false;
|
||||
int minimap_width = 80;
|
||||
@ -291,7 +288,6 @@ private:
|
||||
|
||||
bool highlight_all_occurrences = false;
|
||||
bool scroll_past_end_of_file_enabled = false;
|
||||
bool brace_matching_enabled = false;
|
||||
bool highlight_current_line = false;
|
||||
|
||||
String cut_copy_line;
|
||||
@ -309,7 +305,7 @@ private:
|
||||
float target_v_scroll = 0.0;
|
||||
float v_scroll_speed = 80.0;
|
||||
|
||||
String highlighted_word;
|
||||
String lookup_symbol_word;
|
||||
|
||||
uint64_t last_dblclk = 0;
|
||||
|
||||
@ -386,7 +382,6 @@ private:
|
||||
Size2 get_minimum_size() const override;
|
||||
int _get_control_height() const;
|
||||
|
||||
Point2 _get_local_mouse_pos() const;
|
||||
int _get_menu_action_accelerator(const String &p_action);
|
||||
|
||||
void _reset_caret_blink_timer();
|
||||
@ -431,10 +426,9 @@ private:
|
||||
void _delete(bool p_word = false, bool p_all_to_right = false);
|
||||
void _move_cursor_document_start(bool p_select);
|
||||
void _move_cursor_document_end(bool p_select);
|
||||
void _handle_unicode_character(uint32_t unicode, bool p_had_selection);
|
||||
|
||||
protected:
|
||||
bool auto_brace_completion_enabled = false;
|
||||
bool highlight_matching_braces_enabled = false;
|
||||
|
||||
struct Cache {
|
||||
Ref<Texture2D> tab_icon;
|
||||
@ -455,7 +449,6 @@ protected:
|
||||
Color selection_color;
|
||||
Color code_folding_color;
|
||||
Color current_line_color;
|
||||
Color line_length_guideline_color;
|
||||
Color brace_mismatch_color;
|
||||
Color word_highlighted_color;
|
||||
Color search_result_color;
|
||||
@ -470,19 +463,17 @@ protected:
|
||||
|
||||
void _insert_text(int p_line, int p_char, const String &p_text, int *r_end_line = nullptr, int *r_end_char = nullptr);
|
||||
void _remove_text(int p_from_line, int p_from_column, int p_to_line, int p_to_column);
|
||||
void _insert_text_at_cursor(const String &p_text);
|
||||
virtual void _gui_input(const Ref<InputEvent> &p_gui_input);
|
||||
void _notification(int p_what);
|
||||
|
||||
void _consume_pair_symbol(char32_t ch);
|
||||
void _consume_backspace_for_pair_symbol(int prev_line, int prev_column);
|
||||
|
||||
static void _bind_methods();
|
||||
|
||||
bool _set(const StringName &p_name, const Variant &p_value);
|
||||
bool _get(const StringName &p_name, Variant &r_ret) const;
|
||||
void _get_property_list(List<PropertyInfo> *p_list) const;
|
||||
|
||||
void _set_symbol_lookup_word(const String &p_symbol);
|
||||
|
||||
public:
|
||||
/* Syntax Highlighting. */
|
||||
Ref<SyntaxHighlighter> get_syntax_highlighter();
|
||||
@ -577,8 +568,10 @@ public:
|
||||
|
||||
virtual CursorShape get_cursor_shape(const Point2 &p_pos = Point2i()) const override;
|
||||
|
||||
Point2 _get_local_mouse_pos() const;
|
||||
void _get_mouse_pos(const Point2i &p_mouse, int &r_row, int &r_col) const;
|
||||
void _get_minimap_mouse_row(const Point2i &p_mouse, int &r_row) const;
|
||||
bool is_dragging_cursor() const;
|
||||
|
||||
//void delete_char();
|
||||
//void delete_line();
|
||||
@ -607,7 +600,6 @@ public:
|
||||
void set_structured_text_bidi_override_options(Array p_args);
|
||||
Array get_structured_text_bidi_override_options() const;
|
||||
|
||||
void set_highlighted_word(const String &new_word);
|
||||
void set_text(String p_text);
|
||||
void insert_text_at_cursor(const String &p_text);
|
||||
void insert_at(const String &p_text, int at);
|
||||
@ -635,13 +627,6 @@ public:
|
||||
scroll_past_end_of_file_enabled = p_enabled;
|
||||
update();
|
||||
}
|
||||
inline void set_auto_brace_completion(bool p_enabled) {
|
||||
auto_brace_completion_enabled = p_enabled;
|
||||
}
|
||||
inline void set_brace_matching(bool p_enabled) {
|
||||
brace_matching_enabled = p_enabled;
|
||||
update();
|
||||
}
|
||||
|
||||
void center_viewport_to_cursor();
|
||||
|
||||
@ -686,6 +671,7 @@ public:
|
||||
|
||||
void delete_selection();
|
||||
|
||||
virtual void handle_unicode_input(uint32_t p_unicode);
|
||||
virtual void backspace();
|
||||
void cut();
|
||||
void copy();
|
||||
@ -751,10 +737,6 @@ public:
|
||||
void set_highlight_current_line(bool p_enabled);
|
||||
bool is_highlight_current_line_enabled() const;
|
||||
|
||||
void set_show_line_length_guidelines(bool p_show);
|
||||
void set_line_length_guideline_soft_column(int p_column);
|
||||
void set_line_length_guideline_hard_column(int p_column);
|
||||
|
||||
void set_draw_minimap(bool p_draw);
|
||||
bool is_drawing_minimap() const;
|
||||
|
||||
@ -766,9 +748,6 @@ public:
|
||||
|
||||
void set_tooltip_request_func(Object *p_obj, const StringName &p_function, const Variant &p_udata);
|
||||
|
||||
void set_select_identifiers_on_hover(bool p_enable);
|
||||
bool is_selecting_identifiers_on_hover_enabled() const;
|
||||
|
||||
void set_context_menu_enabled(bool p_enable);
|
||||
bool is_context_menu_enabled();
|
||||
|
||||
@ -784,8 +763,6 @@ public:
|
||||
bool is_menu_visible() const;
|
||||
PopupMenu *get_menu() const;
|
||||
|
||||
String get_text_for_lookup_completion();
|
||||
|
||||
virtual bool is_text_field() const override;
|
||||
TextEdit();
|
||||
~TextEdit();
|
||||
|
@ -457,7 +457,6 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
|
||||
theme->set_color("current_line_color", "TextEdit", Color(0.25, 0.25, 0.26, 0.8));
|
||||
theme->set_color("caret_color", "TextEdit", control_font_color);
|
||||
theme->set_color("caret_background_color", "TextEdit", Color(0, 0, 0));
|
||||
theme->set_color("brace_mismatch_color", "TextEdit", Color(1, 0.2, 0.2));
|
||||
theme->set_color("word_highlighted_color", "TextEdit", Color(0.8, 0.9, 0.9, 0.15));
|
||||
|
||||
theme->set_constant("line_spacing", "TextEdit", 4 * scale);
|
||||
@ -502,8 +501,8 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
|
||||
theme->set_color("caret_background_color", "CodeEdit", Color(0, 0, 0));
|
||||
theme->set_color("brace_mismatch_color", "CodeEdit", Color(1, 0.2, 0.2));
|
||||
theme->set_color("line_number_color", "CodeEdit", Color(0.67, 0.67, 0.67, 0.4));
|
||||
theme->set_color("safe_line_number_color", "CodeEdit", Color(0.67, 0.78, 0.67, 0.6));
|
||||
theme->set_color("word_highlighted_color", "CodeEdit", Color(0.8, 0.9, 0.9, 0.15));
|
||||
theme->set_color("line_length_guideline_color", "CodeEdit", Color(0.3, 0.5, 0.8, 0.1));
|
||||
|
||||
theme->set_constant("completion_lines", "CodeEdit", 7);
|
||||
theme->set_constant("completion_max_width", "CodeEdit", 50);
|
||||
|
Loading…
Reference in New Issue
Block a user