LineEdit: Respect max_length
by truncating text to append
When appending text (either via `set_text()` or by pasting from clipboard),
if the input would make the `LineEdit` exceed its configured `max_length`,
the input text is truncated to fit. The discard part is passed as a parameter
in the `text_change_rejected` signal.
Fixes #33321.
Fixes #41278.
Also cleaned up unimplemented `max_chars` property in `TextEdit`.
Co-authored-by: Tony-Goat <70238376+Tony-Goat@users.noreply.github.com>
(cherry picked from commit 9a1ce8e6c3
)
This commit is contained in:
parent
e6f420aabf
commit
32f5bee985
4 changed files with 29 additions and 25 deletions
|
@ -145,6 +145,17 @@
|
||||||
<member name="focus_mode" type="int" setter="set_focus_mode" getter="get_focus_mode" override="true" enum="Control.FocusMode" default="2" />
|
<member name="focus_mode" type="int" setter="set_focus_mode" getter="get_focus_mode" override="true" enum="Control.FocusMode" default="2" />
|
||||||
<member name="max_length" type="int" setter="set_max_length" getter="get_max_length" default="0">
|
<member name="max_length" type="int" setter="set_max_length" getter="get_max_length" default="0">
|
||||||
Maximum amount of characters that can be entered inside the [LineEdit]. If [code]0[/code], there is no limit.
|
Maximum amount of characters that can be entered inside the [LineEdit]. If [code]0[/code], there is no limit.
|
||||||
|
When a limit is defined, characters that would exceed [member max_length] are truncated. This happens both for existing [member text] contents when setting the max length, or for new text inserted in the [LineEdit], including pasting. If any input text is truncated, the [signal text_change_rejected] signal is emitted with the truncated substring as parameter.
|
||||||
|
[b]Example:[/b]
|
||||||
|
[codeblock]
|
||||||
|
text = "Hello world"
|
||||||
|
max_length = 5
|
||||||
|
# `text` becomes "Hello".
|
||||||
|
max_length = 10
|
||||||
|
text += " goodbye"
|
||||||
|
# `text` becomes "Hello good".
|
||||||
|
# `text_change_rejected` is emitted with "bye" as parameter.
|
||||||
|
[/codeblock]
|
||||||
</member>
|
</member>
|
||||||
<member name="mouse_default_cursor_shape" type="int" setter="set_default_cursor_shape" getter="get_default_cursor_shape" override="true" enum="Control.CursorShape" default="1" />
|
<member name="mouse_default_cursor_shape" type="int" setter="set_default_cursor_shape" getter="get_default_cursor_shape" override="true" enum="Control.CursorShape" default="1" />
|
||||||
<member name="placeholder_alpha" type="float" setter="set_placeholder_alpha" getter="get_placeholder_alpha" default="0.6">
|
<member name="placeholder_alpha" type="float" setter="set_placeholder_alpha" getter="get_placeholder_alpha" default="0.6">
|
||||||
|
@ -178,8 +189,10 @@
|
||||||
</members>
|
</members>
|
||||||
<signals>
|
<signals>
|
||||||
<signal name="text_change_rejected">
|
<signal name="text_change_rejected">
|
||||||
|
<argument index="0" name="rejected_substring" type="String">
|
||||||
|
</argument>
|
||||||
<description>
|
<description>
|
||||||
Emitted when trying to append text that would overflow the [member max_length].
|
Emitted when appending text that overflows the [member max_length]. The appended text is truncated to fit [member max_length], and the part that couldn't fit is passed as the [code]rejected_substring[/code] argument.
|
||||||
</description>
|
</description>
|
||||||
</signal>
|
</signal>
|
||||||
<signal name="text_changed">
|
<signal name="text_changed">
|
||||||
|
|
|
@ -1389,15 +1389,19 @@ int LineEdit::get_scroll_offset() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void LineEdit::append_at_cursor(String p_text) {
|
void LineEdit::append_at_cursor(String p_text) {
|
||||||
if ((max_length <= 0) || (text.length() + p_text.length() <= max_length)) {
|
if (max_length > 0) {
|
||||||
|
// Truncate text to append to fit in max_length, if needed.
|
||||||
|
int available_chars = max_length - text.length();
|
||||||
|
if (p_text.length() > available_chars) {
|
||||||
|
emit_signal("text_change_rejected", p_text.substr(available_chars));
|
||||||
|
p_text = p_text.substr(0, available_chars);
|
||||||
|
}
|
||||||
|
}
|
||||||
String pre = text.substr(0, cursor_pos);
|
String pre = text.substr(0, cursor_pos);
|
||||||
String post = text.substr(cursor_pos, text.length() - cursor_pos);
|
String post = text.substr(cursor_pos, text.length() - cursor_pos);
|
||||||
text = pre + p_text + post;
|
text = pre + p_text + post;
|
||||||
update_cached_width();
|
update_cached_width();
|
||||||
set_cursor_position(cursor_pos + p_text.length());
|
set_cursor_position(cursor_pos + p_text.length());
|
||||||
} else {
|
|
||||||
emit_signal("text_change_rejected");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LineEdit::clear_internal() {
|
void LineEdit::clear_internal() {
|
||||||
|
@ -1845,7 +1849,7 @@ void LineEdit::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("get_right_icon"), &LineEdit::get_right_icon);
|
ClassDB::bind_method(D_METHOD("get_right_icon"), &LineEdit::get_right_icon);
|
||||||
|
|
||||||
ADD_SIGNAL(MethodInfo("text_changed", PropertyInfo(Variant::STRING, "new_text")));
|
ADD_SIGNAL(MethodInfo("text_changed", PropertyInfo(Variant::STRING, "new_text")));
|
||||||
ADD_SIGNAL(MethodInfo("text_change_rejected"));
|
ADD_SIGNAL(MethodInfo("text_change_rejected", PropertyInfo(Variant::STRING, "rejected_substring")));
|
||||||
ADD_SIGNAL(MethodInfo("text_entered", PropertyInfo(Variant::STRING, "new_text")));
|
ADD_SIGNAL(MethodInfo("text_entered", PropertyInfo(Variant::STRING, "new_text")));
|
||||||
|
|
||||||
BIND_ENUM_CONSTANT(ALIGN_LEFT);
|
BIND_ENUM_CONSTANT(ALIGN_LEFT);
|
||||||
|
@ -1864,7 +1868,7 @@ void LineEdit::_bind_methods() {
|
||||||
|
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::STRING, "text"), "set_text", "get_text");
|
ADD_PROPERTY(PropertyInfo(Variant::STRING, "text"), "set_text", "get_text");
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "align", PROPERTY_HINT_ENUM, "Left,Center,Right,Fill"), "set_align", "get_align");
|
ADD_PROPERTY(PropertyInfo(Variant::INT, "align", PROPERTY_HINT_ENUM, "Left,Center,Right,Fill"), "set_align", "get_align");
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "max_length"), "set_max_length", "get_max_length");
|
ADD_PROPERTY(PropertyInfo(Variant::INT, "max_length", PROPERTY_HINT_RANGE, "0,1000,1,or_greater"), "set_max_length", "get_max_length");
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "editable"), "set_editable", "is_editable");
|
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "editable"), "set_editable", "is_editable");
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "secret"), "set_secret", "is_secret");
|
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "secret"), "set_secret", "is_secret");
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::STRING, "secret_character"), "set_secret_character", "get_secret_character");
|
ADD_PROPERTY(PropertyInfo(Variant::STRING, "secret_character"), "set_secret_character", "get_secret_character");
|
||||||
|
@ -1881,7 +1885,7 @@ void LineEdit::_bind_methods() {
|
||||||
ADD_GROUP("Caret", "caret_");
|
ADD_GROUP("Caret", "caret_");
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "caret_blink"), "cursor_set_blink_enabled", "cursor_get_blink_enabled");
|
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "caret_blink"), "cursor_set_blink_enabled", "cursor_get_blink_enabled");
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "caret_blink_speed", PROPERTY_HINT_RANGE, "0.1,10,0.01"), "cursor_set_blink_speed", "cursor_get_blink_speed");
|
ADD_PROPERTY(PropertyInfo(Variant::REAL, "caret_blink_speed", PROPERTY_HINT_RANGE, "0.1,10,0.01"), "cursor_set_blink_speed", "cursor_get_blink_speed");
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "caret_position"), "set_cursor_position", "get_cursor_position");
|
ADD_PROPERTY(PropertyInfo(Variant::INT, "caret_position", PROPERTY_HINT_RANGE, "0,1000,1,or_greater"), "set_cursor_position", "get_cursor_position");
|
||||||
}
|
}
|
||||||
|
|
||||||
LineEdit::LineEdit() {
|
LineEdit::LineEdit() {
|
||||||
|
|
|
@ -5040,14 +5040,6 @@ bool TextEdit::is_wrap_enabled() const {
|
||||||
return wrap_enabled;
|
return wrap_enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextEdit::set_max_chars(int p_max_chars) {
|
|
||||||
max_chars = p_max_chars;
|
|
||||||
}
|
|
||||||
|
|
||||||
int TextEdit::get_max_chars() const {
|
|
||||||
return max_chars;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TextEdit::_reset_caret_blink_timer() {
|
void TextEdit::_reset_caret_blink_timer() {
|
||||||
if (caret_blink_enabled) {
|
if (caret_blink_enabled) {
|
||||||
draw_caret = true;
|
draw_caret = true;
|
||||||
|
@ -7216,7 +7208,6 @@ TextEdit::TextEdit() {
|
||||||
draw_spaces = false;
|
draw_spaces = false;
|
||||||
override_selected_font_color = false;
|
override_selected_font_color = false;
|
||||||
draw_caret = true;
|
draw_caret = true;
|
||||||
max_chars = 0;
|
|
||||||
clear();
|
clear();
|
||||||
wrap_enabled = false;
|
wrap_enabled = false;
|
||||||
wrap_at = 0;
|
wrap_at = 0;
|
||||||
|
|
|
@ -336,7 +336,6 @@ private:
|
||||||
uint32_t version;
|
uint32_t version;
|
||||||
uint32_t saved_version;
|
uint32_t saved_version;
|
||||||
|
|
||||||
int max_chars;
|
|
||||||
bool readonly;
|
bool readonly;
|
||||||
bool syntax_coloring;
|
bool syntax_coloring;
|
||||||
bool indent_using_spaces;
|
bool indent_using_spaces;
|
||||||
|
@ -670,9 +669,6 @@ public:
|
||||||
void set_readonly(bool p_readonly);
|
void set_readonly(bool p_readonly);
|
||||||
bool is_readonly() const;
|
bool is_readonly() const;
|
||||||
|
|
||||||
void set_max_chars(int p_max_chars);
|
|
||||||
int get_max_chars() const;
|
|
||||||
|
|
||||||
void set_wrap_enabled(bool p_wrap_enabled);
|
void set_wrap_enabled(bool p_wrap_enabled);
|
||||||
bool is_wrap_enabled() const;
|
bool is_wrap_enabled() const;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue