Maybe it's a really stupid question, but I can't find the answer on Google.
There is a node in Godot - TextEdit. It has several enums. One of them is called MenuItems. One of these is MENU_CLEAR and "= 3" in grey. The description for it states: "Erases the whole TextEdit text."
My question is: how do I use this info to clear the whole TextEdit text?
I tried simply accessing it with
$TextEdit.MENU_CLEAR -> nothing
I tried going the long way
$TextEdit.MenuItems.MENU_CLEAR -> nothing
I tried putting it as a function call
$TextEdit.MENU_CLEAR() -> nothing
However, if I try to print it, I get it's number
print($TextEdit.MENU_CLEAR) -> "3"
The description of MENU_CLEAR, at least for me, implies there is a function somewhere there, that should be executed once I make a call to MENU_CLEAR. But I do something wrong. Pls, help
Edit1: Here's my piece of code (just checking what works, running everything after IF one line at a time):
if $TextEdit.get_line_count() > 6:
$TextEdit.text = ""
$TextEdit.menu_option($TextEdit.MENU_CLEAR)
Here's what I want to do:
if $TextEdit.get_line_count() > 6:
$TextEdit.select(1, 0, 1, 0) #selects the oldest line
$TextEdit.menu_option($TextEdit.MENU_CUT) #deletes it
Here's the screenshot of what I get now See the slider on the right side And here's what I want it to be Just 6 lines So there should always be only 6 lines at once on the screen, and the old lines should be deleted. That's where I encountered problems with enums, and that was the reason for the post. P.S. Read only is set to false
I would use $TextEdit.text = ""
to clear all the text.
To address your question. The MENU_CLEAR
is a constant. It has the value 3
. By itself it does nothing a 3
would not do.
However, enum
(which are lists of constants with a name) are defined because something uses them. To find out what, I suggest you search for the name of the enum
(which is MenuItems
in this case) in the documentation (in particular on the same class).
In this case we find the menu_option
method. From the documentation:
void menu_option ( int option )
Triggers a right-click menu action by the specified index. See
MenuItems
for a list of available indexes.
Thus, you would use it like this:
$TextEdit.menu_option(TextEdit.MENU_CLEAR)
Yes, this also works:
$TextEdit.menu_option($TextEdit.MENU_CLEAR)
Or you can do it like this (which is the same thing, except it less clear what it means):
$TextEdit.menu_option(3)
Let us say we want to remove lines at the start. The number of lines we will remove will be lines_to_remove
(e.g. 1
).
We can do this using menu_option
. Like this:
Select the lines we want to remove. In other words, select form the start of the first line (0
), to the start of the first line that will stay (lines_to_remove
):
$TextEdit.select(0, 0, lines_to_remove, 0)
Clear cut:
$TextEdit.menu_option(TextEdit.MENU_CUT)
This will remove the selected text. However, it will also set the clipboard.
Alternatively, we can manipulate text
. For example:
var lines:Array = $TextEdit.text.split("\n")
var new_text := ""
for index in lines.size() - lines_to_remove:
if index > 0:
new_text += "\n"
new_text += str(lines[index + lines_to_remove])
$TextEdit.text = new_text
Here I get the text $TextEdit.text
and split it by the new line, which gives me an Array
. Then I concatenate the elements form the Array
that I want to keep (i.e. skipping the ones I want to remove), And set the result back to $TextEdit.text
.
Regardless of the approach you will find that the cursor will be placed at the start of the text.
So, we are going to store the position before manipulating the text:
var cursor_line:int = $TextEdit.cursor_get_line()
var cursor_column:int = $TextEdit.cursor_get_column()
And then set it back... Well, actually we want to subtract the number of lines we removed and then set it back:
cursor_line -= lines_to_remove
$TextEdit.cursor_set_line(cursor_line)
$TextEdit.cursor_set_column(cursor_column)
If this resulted in a negative cursor_line
, it will be placed on the first line. I suppose I could check and set both cursor_line
and cursor_column
to zero in that case, but it has not been a problem while trying this out.
Now, if you want to make sure you have at most a give number of lines (e.g. six lines). We can read how many lines we have, subtract the maximum you allow, and if the result is positive, that is how many lines have to remove:
var target_number_of_lines := 6
var lines_to_remove:int = $TextEdit.get_line_count() - target_number_of_lines
if lines_to_remove > 0:
pass # rest of the code here
Why would you need to do this instead of just removing the first line? Because the user might paste multiple lines at once. Speaking of which, this is intended to run on the "text_changed"
signal (although it would also work on _process
):
func _on_TextEdit_text_changed() -> void:
var target_number_of_lines := 6
var lines_to_remove:int = $TextEdit.get_line_count() - target_number_of_lines
if lines_to_remove > 0:
var cursor_line:int = $TextEdit.cursor_get_line()
var cursor_column:int = $TextEdit.cursor_get_column()
$TextEdit.select(0, 0, lines_to_remove, 0)
$TextEdit.menu_option(TextEdit.MENU_CUT)
cursor_line -= lines_to_remove
$TextEdit.cursor_set_line(cursor_line)
$TextEdit.cursor_set_column(cursor_column)
Since this version is cutting the text, it writes the clipboard.
Manipulating the text
property also works (and does not write the clipboard). This is the code:
func _on_TextEdit_text_changed() -> void:
var target_number_of_lines := 6
var lines_to_remove:int = $TextEdit.get_line_count() - target_number_of_lines
if lines_to_remove > 0:
var cursor_line:int = $TextEdit.cursor_get_line()
var cursor_column:int = $TextEdit.cursor_get_column()
var lines:Array = $TextEdit.text.split("\n")
var new_text := ""
for index in lines.size() - lines_to_remove:
if index > 0:
new_text += "\n"
new_text += str(lines[index + lines_to_remove])
$TextEdit.text = new_text
cursor_line -= lines_to_remove
$TextEdit.cursor_set_line(cursor_line)
$TextEdit.cursor_set_column(cursor_column)