2014-02-09 22:10:30 -03:00
/**************************************************************************/
/* line_edit.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
2018-01-05 00:50:27 +01:00
2014-02-09 22:10:30 -03:00
# include "line_edit.h"
2025-10-01 11:14:22 -03:00
# include "line_edit.compat.inc"
2019-04-05 14:06:16 +02:00
2025-09-24 16:26:48 +02:00
# include "core/config/project_settings.h"
2020-12-07 21:32:00 +10:00
# include "core/input/input_map.h"
2018-09-11 18:13:45 +02:00
# include "core/os/keyboard.h"
# include "core/os/os.h"
2025-05-03 11:33:24 +03:00
# include "core/string/alt_codes.h"
2025-03-21 16:42:23 +02:00
# include "core/string/translation_server.h"
2023-09-08 21:00:10 +02:00
# include "scene/gui/label.h"
# include "scene/main/window.h"
# include "scene/theme/theme_db.h"
2024-03-11 20:27:45 -07:00
# include "servers/display/display_server.h"
# include "servers/text/text_server.h"
2023-09-08 21:00:10 +02:00
2016-06-21 14:38:35 +01:00
# ifdef TOOLS_ENABLED
2025-06-10 16:47:26 +02:00
# include "editor/settings/editor_settings.h"
2016-06-21 14:38:35 +01:00
# endif
2016-06-18 16:15:26 +02:00
2025-10-01 11:14:22 -03:00
void LineEdit : : edit ( bool p_hide_focus ) {
_edit ( true , p_hide_focus ) ;
2025-05-05 20:21:43 -04:00
}
2025-10-01 11:14:22 -03:00
void LineEdit : : _edit ( bool p_show_virtual_keyboard , bool p_hide_focus ) {
2024-09-10 13:43:31 +00:00
if ( ! is_inside_tree ( ) ) {
return ;
}
if ( ! has_focus ( ) ) {
2025-10-01 11:14:22 -03:00
grab_focus ( p_hide_focus ) ;
2024-10-04 10:37:33 +00:00
return ;
2024-09-10 13:43:31 +00:00
}
if ( ! editable | | editing ) {
return ;
}
2024-10-04 10:37:33 +00:00
if ( select_all_on_focus ) {
if ( Input : : get_singleton ( ) - > is_mouse_button_pressed ( MouseButton : : LEFT ) ) {
// Select all when the mouse button is up.
pending_select_all_on_focus = true ;
} else {
select_all ( ) ;
}
}
2024-09-10 13:43:31 +00:00
editing = true ;
_validate_caret_can_draw ( ) ;
2025-05-17 15:44:34 +02:00
if ( p_show_virtual_keyboard & & ! pending_select_all_on_focus ) {
2025-05-05 20:21:43 -04:00
show_virtual_keyboard ( ) ;
}
2024-09-10 13:43:31 +00:00
queue_redraw ( ) ;
}
2024-10-04 10:37:33 +00:00
void LineEdit : : unedit ( ) {
2024-09-10 13:43:31 +00:00
if ( ! editing ) {
return ;
}
editing = false ;
_validate_caret_can_draw ( ) ;
2024-09-05 10:52:29 +03:00
apply_ime ( ) ;
2024-09-10 13:43:31 +00:00
set_caret_column ( caret_column ) ; // Update scroll_offset.
if ( DisplayServer : : get_singleton ( ) - > has_feature ( DisplayServer : : FEATURE_VIRTUAL_KEYBOARD ) & & virtual_keyboard_enabled ) {
DisplayServer : : get_singleton ( ) - > virtual_keyboard_hide ( ) ;
}
if ( deselect_on_focus_loss_enabled & & ! selection . drag_attempt ) {
deselect ( ) ;
}
}
bool LineEdit : : is_editing ( ) const {
return editing ;
}
2025-01-02 23:41:27 +02:00
void LineEdit : : set_keep_editing_on_text_submit ( bool p_enabled ) {
keep_editing_on_text_submit = p_enabled ;
}
bool LineEdit : : is_editing_kept_on_text_submit ( ) const {
return keep_editing_on_text_submit ;
}
2024-09-05 10:52:29 +03:00
void LineEdit : : _close_ime_window ( ) {
DisplayServer : : WindowID wid = get_window ( ) ? get_window ( ) - > get_window_id ( ) : DisplayServer : : INVALID_WINDOW_ID ;
if ( wid = = DisplayServer : : INVALID_WINDOW_ID | | ! DisplayServer : : get_singleton ( ) - > has_feature ( DisplayServer : : FEATURE_IME ) ) {
return ;
}
DisplayServer : : get_singleton ( ) - > window_set_ime_position ( Point2 ( ) , wid ) ;
DisplayServer : : get_singleton ( ) - > window_set_ime_active ( false , wid ) ;
}
void LineEdit : : _update_ime_window_position ( ) {
DisplayServer : : WindowID wid = get_window ( ) ? get_window ( ) - > get_window_id ( ) : DisplayServer : : INVALID_WINDOW_ID ;
2024-09-25 08:52:27 -05:00
if ( wid = = DisplayServer : : INVALID_WINDOW_ID | | ! DisplayServer : : get_singleton ( ) - > has_feature ( DisplayServer : : FEATURE_IME ) ) {
2024-09-05 10:52:29 +03:00
return ;
}
DisplayServer : : get_singleton ( ) - > window_set_ime_active ( true , wid ) ;
Point2 pos = Point2 ( get_caret_pixel_pos ( ) . x , ( get_size ( ) . y + theme_cache . font - > get_height ( theme_cache . font_size ) ) / 2 ) + get_global_position ( ) ;
if ( get_window ( ) - > get_embedder ( ) ) {
pos + = get_viewport ( ) - > get_popup_base_transform ( ) . get_origin ( ) ;
}
2025-06-11 17:43:21 +02:00
// Take into account the window's transform.
pos = get_window ( ) - > get_screen_transform ( ) . xform ( pos ) ;
2024-09-05 10:52:29 +03:00
// The window will move to the updated position the next time the IME is updated, not immediately.
DisplayServer : : get_singleton ( ) - > window_set_ime_position ( pos , wid ) ;
}
bool LineEdit : : has_ime_text ( ) const {
return ! ime_text . is_empty ( ) ;
}
void LineEdit : : cancel_ime ( ) {
if ( ! has_ime_text ( ) ) {
2024-11-06 09:47:08 +02:00
_close_ime_window ( ) ;
2024-09-05 10:52:29 +03:00
return ;
}
ime_text = String ( ) ;
ime_selection = Vector2i ( ) ;
alt_start = false ;
alt_start_no_hold = false ;
_close_ime_window ( ) ;
_shape ( ) ;
}
void LineEdit : : apply_ime ( ) {
if ( ! has_ime_text ( ) ) {
2024-11-06 09:47:08 +02:00
_close_ime_window ( ) ;
2024-09-05 10:52:29 +03:00
return ;
}
// Force apply the current IME text.
if ( alt_start | | alt_start_no_hold ) {
cancel_ime ( ) ;
if ( ( alt_code > 0x31 & & alt_code < 0xd800 ) | | ( alt_code > 0xdfff & & alt_code < = 0x10ffff ) ) {
char32_t ucodestr [ 2 ] = { ( char32_t ) alt_code , 0 } ;
insert_text_at_caret ( ucodestr ) ;
}
} else {
String insert_ime_text = ime_text ;
cancel_ime ( ) ;
insert_text_at_caret ( insert_ime_text ) ;
}
}
2020-12-07 21:32:00 +10:00
void LineEdit : : _swap_current_input_direction ( ) {
if ( input_direction = = TEXT_DIRECTION_LTR ) {
input_direction = TEXT_DIRECTION_RTL ;
} else {
input_direction = TEXT_DIRECTION_LTR ;
}
2021-03-28 19:31:25 +01:00
set_caret_column ( get_caret_column ( ) ) ;
2020-12-07 21:32:00 +10:00
}
2021-03-28 19:31:25 +01:00
void LineEdit : : _move_caret_left ( bool p_select , bool p_move_by_word ) {
2020-12-07 21:32:00 +10:00
if ( selection . enabled & & ! p_select ) {
2021-03-28 19:31:25 +01:00
set_caret_column ( selection . begin ) ;
2020-12-07 21:32:00 +10:00
deselect ( ) ;
return ;
}
shift_selection_check_pre ( p_select ) ;
if ( p_move_by_word ) {
2021-03-28 19:31:25 +01:00
int cc = caret_column ;
2020-12-07 21:32:00 +10:00
2021-08-28 00:19:51 +03:00
PackedInt32Array words = TS - > shaped_text_get_word_breaks ( text_rid ) ;
2024-08-24 12:28:18 -04:00
if ( words . is_empty ( ) | | cc < = words [ 0 ] ) {
// Move to the start when there are no more words.
cc = 0 ;
} else {
for ( int i = words . size ( ) - 2 ; i > = 0 ; i = i - 2 ) {
if ( words [ i ] < cc ) {
cc = words [ i ] ;
break ;
}
2020-12-07 21:32:00 +10:00
}
}
2021-03-28 19:31:25 +01:00
set_caret_column ( cc ) ;
2020-12-07 21:32:00 +10:00
} else {
2021-03-28 19:31:25 +01:00
if ( caret_mid_grapheme_enabled ) {
set_caret_column ( get_caret_column ( ) - 1 ) ;
2020-12-07 21:32:00 +10:00
} else {
2023-08-15 11:42:40 +03:00
set_caret_column ( TS - > shaped_text_prev_character_pos ( text_rid , get_caret_column ( ) ) ) ;
2020-12-07 21:32:00 +10:00
}
}
shift_selection_check_post ( p_select ) ;
2023-01-31 20:56:06 +01:00
_reset_caret_blink_timer ( ) ;
2020-12-07 21:32:00 +10:00
}
2021-03-28 19:31:25 +01:00
void LineEdit : : _move_caret_right ( bool p_select , bool p_move_by_word ) {
2020-12-07 21:32:00 +10:00
if ( selection . enabled & & ! p_select ) {
2021-03-28 19:31:25 +01:00
set_caret_column ( selection . end ) ;
2020-12-07 21:32:00 +10:00
deselect ( ) ;
return ;
}
shift_selection_check_pre ( p_select ) ;
if ( p_move_by_word ) {
2021-03-28 19:31:25 +01:00
int cc = caret_column ;
2020-12-07 21:32:00 +10:00
2021-08-28 00:19:51 +03:00
PackedInt32Array words = TS - > shaped_text_get_word_breaks ( text_rid ) ;
2024-08-24 12:28:18 -04:00
if ( words . is_empty ( ) | | cc > = words [ words . size ( ) - 1 ] ) {
// Move to the end when there are no more words.
cc = text . length ( ) ;
} else {
for ( int i = 1 ; i < words . size ( ) ; i = i + 2 ) {
if ( words [ i ] > cc ) {
cc = words [ i ] ;
break ;
}
2020-12-07 21:32:00 +10:00
}
}
2021-03-28 19:31:25 +01:00
set_caret_column ( cc ) ;
2020-12-07 21:32:00 +10:00
} else {
2021-03-28 19:31:25 +01:00
if ( caret_mid_grapheme_enabled ) {
set_caret_column ( get_caret_column ( ) + 1 ) ;
2020-12-07 21:32:00 +10:00
} else {
2023-08-15 11:42:40 +03:00
set_caret_column ( TS - > shaped_text_next_character_pos ( text_rid , get_caret_column ( ) ) ) ;
2020-12-07 21:32:00 +10:00
}
}
shift_selection_check_post ( p_select ) ;
2023-01-31 20:56:06 +01:00
_reset_caret_blink_timer ( ) ;
2020-12-07 21:32:00 +10:00
}
2021-03-28 19:31:25 +01:00
void LineEdit : : _move_caret_start ( bool p_select ) {
2020-12-07 21:32:00 +10:00
shift_selection_check_pre ( p_select ) ;
2021-03-28 19:31:25 +01:00
set_caret_column ( 0 ) ;
2020-12-07 21:32:00 +10:00
shift_selection_check_post ( p_select ) ;
}
2021-03-28 19:31:25 +01:00
void LineEdit : : _move_caret_end ( bool p_select ) {
2020-12-07 21:32:00 +10:00
shift_selection_check_pre ( p_select ) ;
2021-03-28 19:31:25 +01:00
set_caret_column ( text . length ( ) ) ;
2020-12-07 21:32:00 +10:00
shift_selection_check_post ( p_select ) ;
}
void LineEdit : : _backspace ( bool p_word , bool p_all_to_left ) {
if ( ! editable ) {
return ;
}
2024-02-18 11:58:37 +04:00
if ( selection . enabled ) {
selection_delete ( ) ;
return ;
}
if ( caret_column = = 0 ) {
return ; // Nothing to do.
}
2020-12-07 21:32:00 +10:00
if ( p_all_to_left ) {
2024-02-07 16:11:48 +04:00
text = text . substr ( caret_column ) ;
_shape ( ) ;
set_caret_column ( 0 ) ;
2020-12-07 21:32:00 +10:00
_text_changed ( ) ;
return ;
}
if ( p_word ) {
2021-03-28 19:31:25 +01:00
int cc = caret_column ;
2020-12-07 21:32:00 +10:00
2021-08-28 00:19:51 +03:00
PackedInt32Array words = TS - > shaped_text_get_word_breaks ( text_rid ) ;
2024-08-24 12:28:18 -04:00
if ( words . is_empty ( ) | | cc < = words [ 0 ] ) {
// Delete to the start when there are no more words.
cc = 0 ;
} else {
for ( int i = words . size ( ) - 2 ; i > = 0 ; i = i - 2 ) {
if ( words [ i ] < cc ) {
cc = words [ i ] ;
break ;
}
2020-12-07 21:32:00 +10:00
}
}
2021-03-28 19:31:25 +01:00
delete_text ( cc , caret_column ) ;
2020-12-07 21:32:00 +10:00
2021-03-28 19:31:25 +01:00
set_caret_column ( cc ) ;
2020-12-07 21:32:00 +10:00
} else {
delete_char ( ) ;
}
}
void LineEdit : : _delete ( bool p_word , bool p_all_to_right ) {
if ( ! editable ) {
return ;
}
if ( selection . enabled ) {
selection_delete ( ) ;
return ;
}
2024-02-18 11:58:37 +04:00
if ( caret_column = = text . length ( ) ) {
2020-12-07 21:32:00 +10:00
return ; // Nothing to do.
}
2024-02-18 11:58:37 +04:00
if ( p_all_to_right ) {
text = text . substr ( 0 , caret_column ) ;
_shape ( ) ;
_text_changed ( ) ;
return ;
}
2020-12-07 21:32:00 +10:00
if ( p_word ) {
2021-03-28 19:31:25 +01:00
int cc = caret_column ;
2021-08-28 00:19:51 +03:00
PackedInt32Array words = TS - > shaped_text_get_word_breaks ( text_rid ) ;
2024-08-24 12:28:18 -04:00
if ( words . is_empty ( ) | | cc > = words [ words . size ( ) - 1 ] ) {
// Delete to the end when there are no more words.
cc = text . length ( ) ;
} else {
for ( int i = 1 ; i < words . size ( ) ; i = i + 2 ) {
if ( words [ i ] > cc ) {
cc = words [ i ] ;
break ;
}
2020-12-07 21:32:00 +10:00
}
}
2021-03-28 19:31:25 +01:00
delete_text ( caret_column , cc ) ;
2021-04-03 21:23:18 +10:00
set_caret_column ( caret_column ) ;
2020-12-07 21:32:00 +10:00
} else {
2021-03-28 19:31:25 +01:00
if ( caret_mid_grapheme_enabled ) {
set_caret_column ( caret_column + 1 ) ;
2020-12-07 21:32:00 +10:00
delete_char ( ) ;
} else {
2021-03-28 19:31:25 +01:00
int cc = caret_column ;
2023-08-15 11:42:40 +03:00
set_caret_column ( TS - > shaped_text_next_character_pos ( text_rid , caret_column ) ) ;
2021-03-28 19:31:25 +01:00
delete_text ( cc , caret_column ) ;
2020-12-07 21:32:00 +10:00
}
}
}
2024-11-22 21:27:36 +07:00
Point2 LineEdit : : _get_right_icon_size ( Ref < Texture2D > p_right_icon ) const {
Size2 icon_size ;
if ( p_right_icon . is_null ( ) ) {
return icon_size ;
}
switch ( icon_expand_mode ) {
default :
case LineEdit : : EXPAND_MODE_ORIGINAL_SIZE :
icon_size = p_right_icon - > get_size ( ) ;
break ;
case LineEdit : : EXPAND_MODE_FIT_TO_TEXT : {
real_t height = theme_cache . font - > get_height ( theme_cache . font_size ) ;
icon_size = Size2 ( height , height ) ;
} break ;
case LineEdit : : EXPAND_MODE_FIT_TO_LINE_EDIT : {
icon_size = p_right_icon - > get_size ( ) ;
Point2 size = get_size ( ) ;
float icon_width = icon_size . width * size . height / icon_size . height ;
float icon_height = size . height ;
if ( icon_width > size . width ) {
icon_width = size . width ;
icon_height = icon_size . height * icon_width / icon_size . width ;
}
icon_size = Size2 ( icon_width , icon_height ) * right_icon_scale ;
} break ;
}
return icon_size ;
}
2022-01-11 15:59:52 +02:00
void LineEdit : : unhandled_key_input ( const Ref < InputEvent > & p_event ) {
2024-09-10 13:43:31 +00:00
// Return to prevent editing if just focused.
if ( ! editing ) {
return ;
}
2022-01-11 15:59:52 +02:00
Ref < InputEventKey > k = p_event ;
if ( k . is_valid ( ) ) {
if ( ! k - > is_pressed ( ) ) {
return ;
}
// Handle Unicode (with modifiers active, process after shortcuts).
if ( has_focus ( ) & & editable & & ( k - > get_unicode ( ) > = 32 ) ) {
selection_delete ( ) ;
char32_t ucodestr [ 2 ] = { ( char32_t ) k - > get_unicode ( ) , 0 } ;
int prev_len = text . length ( ) ;
insert_text_at_caret ( ucodestr ) ;
if ( text . length ( ) ! = prev_len ) {
_text_changed ( ) ;
}
accept_event ( ) ;
}
}
}
2021-08-22 12:37:22 -03:00
void LineEdit : : gui_input ( const Ref < InputEvent > & p_event ) {
2021-04-05 08:52:21 +02:00
ERR_FAIL_COND ( p_event . is_null ( ) ) ;
2017-05-20 12:38:03 -03:00
Ref < InputEventMouseButton > b = p_event ;
2016-03-09 00:00:52 +01:00
2024-09-05 10:52:29 +03:00
if ( b . is_valid ( ) ) {
2024-09-10 13:43:31 +00:00
if ( b - > is_pressed ( ) & & b - > get_button_index ( ) = = MouseButton : : RIGHT ) {
2024-09-05 10:52:29 +03:00
apply_ime ( ) ;
2024-09-10 13:43:31 +00:00
if ( editable & & ! selection . enabled ) {
set_caret_at_pixel_pos ( b - > get_position ( ) . x ) ;
}
if ( context_menu_enabled ) {
_update_context_menu ( ) ;
2025-03-05 15:41:12 -05:00
menu - > set_position ( get_screen_transform ( ) . xform ( get_local_mouse_position ( ) ) ) ;
2024-09-10 13:43:31 +00:00
menu - > reset_size ( ) ;
menu - > popup ( ) ;
}
if ( editable & & ! editing ) {
2025-10-01 11:14:22 -03:00
edit ( true ) ;
2024-10-04 10:37:33 +00:00
emit_signal ( SNAME ( " editing_toggled " ) , true ) ;
2024-09-10 13:43:31 +00:00
}
2019-08-04 15:35:50 +02:00
accept_event ( ) ;
2017-05-20 12:38:03 -03:00
return ;
}
2016-05-16 20:25:17 -03:00
2024-09-10 13:43:31 +00:00
if ( editable & & is_middle_mouse_paste_enabled ( ) & & b - > is_pressed ( ) & & b - > get_button_index ( ) = = MouseButton : : MIDDLE & & DisplayServer : : get_singleton ( ) - > has_feature ( DisplayServer : : FEATURE_CLIPBOARD_PRIMARY ) ) {
2024-09-05 10:52:29 +03:00
apply_ime ( ) ;
2021-10-12 09:43:50 +02:00
String paste_buffer = DisplayServer : : get_singleton ( ) - > clipboard_get_primary ( ) . strip_escapes ( ) ;
deselect ( ) ;
set_caret_at_pixel_pos ( b - > get_position ( ) . x ) ;
2024-09-10 13:43:31 +00:00
if ( ! editing ) {
2025-10-01 11:14:22 -03:00
edit ( true ) ;
2024-10-04 10:37:33 +00:00
emit_signal ( SNAME ( " editing_toggled " ) , true ) ;
2024-09-10 13:43:31 +00:00
}
2021-10-12 09:43:50 +02:00
if ( ! paste_buffer . is_empty ( ) ) {
insert_text_at_caret ( paste_buffer ) ;
if ( ! text_changed_dirty ) {
if ( is_inside_tree ( ) ) {
2023-12-18 15:46:56 +01:00
callable_mp ( this , & LineEdit : : _text_changed ) . call_deferred ( ) ;
2021-10-12 09:43:50 +02:00
}
text_changed_dirty = true ;
}
}
2023-01-30 08:03:34 -05:00
accept_event ( ) ;
2021-10-12 09:43:50 +02:00
return ;
}
2021-08-13 16:31:57 -05:00
if ( b - > get_button_index ( ) ! = MouseButton : : LEFT ) {
2017-05-20 12:38:03 -03:00
return ;
2020-05-14 16:41:43 +02:00
}
2016-03-09 00:00:52 +01:00
2024-09-10 13:43:31 +00:00
if ( editing ) {
_reset_caret_blink_timer ( ) ;
}
2017-05-20 12:38:03 -03:00
if ( b - > is_pressed ( ) ) {
2024-09-05 10:52:29 +03:00
apply_ime ( ) ;
2023-03-08 23:00:27 +01:00
accept_event ( ) ; // Don't pass event further when clicked on text field.
2024-09-10 13:43:31 +00:00
if ( editable & & ! text . is_empty ( ) & & _is_over_clear_button ( b - > get_position ( ) ) ) {
2018-07-26 13:45:38 +02:00
clear_button_status . press_attempt = true ;
clear_button_status . pressing_inside = true ;
2022-08-13 23:21:24 +02:00
queue_redraw ( ) ;
2018-07-26 13:45:38 +02:00
return ;
}
2021-10-28 09:07:18 +02:00
if ( b - > is_shift_pressed ( ) ) {
shift_selection_check_pre ( true ) ;
}
2016-06-18 16:14:43 +02:00
2021-03-28 19:31:25 +01:00
set_caret_at_pixel_pos ( b - > get_position ( ) . x ) ;
2016-03-09 00:00:52 +01:00
2021-04-24 14:33:50 -06:00
if ( b - > is_shift_pressed ( ) ) {
2021-03-28 19:31:25 +01:00
selection_fill_at_caret ( ) ;
2017-05-20 12:38:03 -03:00
selection . creating = true ;
2014-02-09 22:10:30 -03:00
2017-05-20 12:38:03 -03:00
} else {
2025-09-25 12:05:48 +04:00
if ( selecting_enabled & & ! text . is_empty ( ) ) {
2021-09-23 18:54:14 +02:00
const int triple_click_timeout = 600 ;
const int triple_click_tolerance = 5 ;
const bool is_triple_click = ! b - > is_double_click ( ) & & ( OS : : get_singleton ( ) - > get_ticks_msec ( ) - last_dblclk ) < triple_click_timeout & & b - > get_position ( ) . distance_to ( last_dblclk_pos ) < triple_click_tolerance ;
2025-09-25 12:05:48 +04:00
if ( is_triple_click ) {
2021-02-28 16:52:04 -03:00
// Triple-click select all.
selection . enabled = true ;
selection . begin = 0 ;
selection . end = text . length ( ) ;
2021-04-13 04:25:44 -04:00
selection . double_click = true ;
2021-09-23 18:54:14 +02:00
last_dblclk = 0 ;
2022-06-10 00:02:48 +02:00
set_caret_column ( selection . begin ) ;
2021-10-20 21:25:09 +02:00
if ( ! pass & & DisplayServer : : get_singleton ( ) - > has_feature ( DisplayServer : : FEATURE_CLIPBOARD_PRIMARY ) ) {
2021-10-12 09:43:50 +02:00
DisplayServer : : get_singleton ( ) - > clipboard_set_primary ( text ) ;
}
2025-03-21 16:42:23 +02:00
queue_accessibility_update ( ) ;
2021-04-13 04:25:44 -04:00
} else if ( b - > is_double_click ( ) ) {
2021-02-28 16:52:04 -03:00
// Double-click select word.
2021-09-23 18:54:14 +02:00
last_dblclk = OS : : get_singleton ( ) - > get_ticks_msec ( ) ;
last_dblclk_pos = b - > get_position ( ) ;
2021-08-28 00:19:51 +03:00
PackedInt32Array words = TS - > shaped_text_get_word_breaks ( text_rid ) ;
for ( int i = 0 ; i < words . size ( ) ; i = i + 2 ) {
2025-08-12 12:52:45 +03:00
if ( words [ i ] < = caret_column & & words [ i + 1 ] > = caret_column ) {
2021-02-28 16:52:04 -03:00
selection . enabled = true ;
2021-08-28 00:19:51 +03:00
selection . begin = words [ i ] ;
selection . end = words [ i + 1 ] ;
2021-04-13 04:25:44 -04:00
selection . double_click = true ;
2023-12-05 20:57:41 +01:00
selection . creating = true ;
selection . start_column = caret_column ;
2022-06-10 00:02:48 +02:00
set_caret_column ( selection . end ) ;
2025-03-21 16:42:23 +02:00
queue_accessibility_update ( ) ;
2021-02-28 16:52:04 -03:00
break ;
}
}
2021-10-20 21:25:09 +02:00
if ( ! pass & & DisplayServer : : get_singleton ( ) - > has_feature ( DisplayServer : : FEATURE_CLIPBOARD_PRIMARY ) ) {
2023-03-30 17:07:28 +02:00
DisplayServer : : get_singleton ( ) - > clipboard_set_primary ( get_selected_text ( ) ) ;
2021-10-12 09:43:50 +02:00
}
2021-02-28 16:52:04 -03:00
}
2017-05-20 12:38:03 -03:00
}
2016-06-18 16:14:43 +02:00
2017-05-20 12:38:03 -03:00
selection . drag_attempt = false ;
2023-07-16 20:32:00 -04:00
if ( ! selection . double_click ) {
bool is_inside_sel = selection . enabled & & caret_column > = selection . begin & & caret_column < = selection . end ;
2025-05-18 18:26:34 +02:00
if ( ! pass & & drag_and_drop_selection_enabled & & is_inside_sel ) {
2023-07-16 20:32:00 -04:00
selection . drag_attempt = true ;
} else {
deselect ( ) ;
selection . start_column = caret_column ;
selection . creating = true ;
}
2014-02-09 22:10:30 -03:00
}
2017-05-20 12:38:03 -03:00
}
2016-03-09 00:00:52 +01:00
2024-09-10 13:43:31 +00:00
if ( editable & & ! editing ) {
2025-10-01 11:14:22 -03:00
edit ( true ) ;
2024-10-04 10:37:33 +00:00
emit_signal ( SNAME ( " editing_toggled " ) , true ) ;
2024-09-10 13:43:31 +00:00
return ;
}
2016-03-09 00:00:52 +01:00
2017-05-20 12:38:03 -03:00
} else {
2021-08-13 16:31:57 -05:00
if ( selection . enabled & & ! pass & & b - > get_button_index ( ) = = MouseButton : : LEFT & & DisplayServer : : get_singleton ( ) - > has_feature ( DisplayServer : : FEATURE_CLIPBOARD_PRIMARY ) ) {
2023-03-30 17:07:28 +02:00
DisplayServer : : get_singleton ( ) - > clipboard_set_primary ( get_selected_text ( ) ) ;
2021-10-12 09:43:50 +02:00
}
2024-09-10 13:43:31 +00:00
if ( editable & & ! text . is_empty ( ) & & clear_button_enabled ) {
2018-07-26 13:45:38 +02:00
bool press_attempt = clear_button_status . press_attempt ;
clear_button_status . press_attempt = false ;
if ( press_attempt & & clear_button_status . pressing_inside & & _is_over_clear_button ( b - > get_position ( ) ) ) {
clear ( ) ;
return ;
}
}
2021-04-13 04:25:44 -04:00
if ( ( ! selection . creating ) & & ( ! selection . double_click ) ) {
2017-12-17 15:40:44 -02:00
deselect ( ) ;
2014-02-09 22:10:30 -03:00
}
2017-05-20 12:38:03 -03:00
selection . creating = false ;
2021-04-13 04:25:44 -04:00
selection . double_click = false ;
2021-10-28 09:07:18 +02:00
if ( ! drag_action ) {
selection . drag_attempt = false ;
}
2016-03-09 00:00:52 +01:00
2022-10-16 20:37:35 +08:00
if ( pending_select_all_on_focus ) {
select_all ( ) ;
pending_select_all_on_focus = false ;
}
2024-10-09 16:32:52 +05:30
if ( editable ) {
show_virtual_keyboard ( ) ;
}
2017-05-20 12:38:03 -03:00
}
2016-03-09 00:00:52 +01:00
2022-08-13 23:21:24 +02:00
queue_redraw ( ) ;
2023-01-30 08:03:34 -05:00
return ;
2017-05-20 12:38:03 -03:00
}
2016-03-09 00:00:52 +01:00
2017-05-20 12:38:03 -03:00
Ref < InputEventMouseMotion > m = p_event ;
2016-03-09 00:00:52 +01:00
2017-05-20 12:38:03 -03:00
if ( m . is_valid ( ) ) {
2024-09-10 13:43:31 +00:00
if ( editable & & ! text . is_empty ( ) & & clear_button_enabled ) {
2018-07-26 13:45:38 +02:00
bool last_press_inside = clear_button_status . pressing_inside ;
clear_button_status . pressing_inside = clear_button_status . press_attempt & & _is_over_clear_button ( m - > get_position ( ) ) ;
if ( last_press_inside ! = clear_button_status . pressing_inside ) {
2022-08-13 23:21:24 +02:00
queue_redraw ( ) ;
2018-07-26 13:45:38 +02:00
}
}
2023-01-08 00:55:54 +01:00
if ( m - > get_button_mask ( ) . has_flag ( MouseButtonMask : : LEFT ) ) {
2017-05-20 12:38:03 -03:00
if ( selection . creating ) {
2021-03-28 19:31:25 +01:00
set_caret_at_pixel_pos ( m - > get_position ( ) . x ) ;
selection_fill_at_caret ( ) ;
2023-12-05 20:57:41 +01:00
if ( selection . double_click ) {
// Expand selection to whole words.
PackedInt32Array words = TS - > shaped_text_get_word_breaks ( text_rid ) ;
for ( int i = 0 ; i < words . size ( ) ; i = i + 2 ) {
2025-08-12 12:52:45 +03:00
if ( words [ i ] < = selection . begin & & words [ i + 1 ] > = selection . begin ) {
2023-12-05 20:57:41 +01:00
selection . begin = words [ i ] ;
}
2025-08-12 12:52:45 +03:00
if ( words [ i ] < = selection . end & & words [ i + 1 ] > = selection . end ) {
2023-12-05 20:57:41 +01:00
selection . end = words [ i + 1 ] ;
selection . enabled = true ;
break ;
}
}
if ( caret_column < selection . start_column ) {
set_caret_column ( selection . begin ) ;
} else {
set_caret_column ( selection . end ) ;
}
}
2017-05-20 12:38:03 -03:00
}
}
2021-10-28 09:07:18 +02:00
if ( drag_action & & can_drop_data ( m - > get_position ( ) , get_viewport ( ) - > gui_get_drag_data ( ) ) ) {
drag_caret_force_displayed = true ;
set_caret_at_pixel_pos ( m - > get_position ( ) . x ) ;
}
2023-01-30 08:03:34 -05:00
return ;
2017-05-20 12:38:03 -03:00
}
2016-03-09 00:00:52 +01:00
2017-05-20 12:38:03 -03:00
Ref < InputEventKey > k = p_event ;
2014-02-09 22:10:30 -03:00
2024-09-10 13:43:31 +00:00
if ( k . is_null ( ) ) {
return ;
}
2021-11-29 16:24:02 +02:00
2024-09-10 13:43:31 +00:00
if ( editable & & ! editing & & k - > is_action_pressed ( " ui_text_submit " , false ) ) {
2024-10-04 10:37:33 +00:00
edit ( ) ;
emit_signal ( SNAME ( " editing_toggled " ) , true ) ;
accept_event ( ) ;
2024-09-10 13:43:31 +00:00
return ;
}
2023-01-30 08:03:34 -05:00
2024-11-29 09:04:04 +01:00
// Open context menu.
if ( context_menu_enabled ) {
if ( k - > is_action ( " ui_menu " , true ) ) {
_update_context_menu ( ) ;
Point2 pos = Point2 ( get_caret_pixel_pos ( ) . x , ( get_size ( ) . y + theme_cache . font - > get_height ( theme_cache . font_size ) ) / 2 ) ;
2025-03-05 15:41:12 -05:00
menu - > set_position ( get_screen_transform ( ) . xform ( pos ) ) ;
2024-11-29 09:04:04 +01:00
menu - > reset_size ( ) ;
menu - > popup ( ) ;
menu - > grab_focus ( ) ;
accept_event ( ) ;
return ;
}
}
if ( is_shortcut_keys_enabled ( ) ) {
if ( k - > is_action ( " ui_copy " , true ) ) {
copy_text ( ) ;
accept_event ( ) ;
return ;
}
if ( k - > is_action ( " ui_text_select_all " , true ) ) {
select ( ) ;
accept_event ( ) ;
return ;
}
if ( k - > is_action ( " ui_cut " , true ) ) {
if ( editable ) {
cut_text ( ) ;
} else {
copy_text ( ) ;
}
accept_event ( ) ;
return ;
}
}
2024-09-10 13:43:31 +00:00
if ( ! editing ) {
return ;
}
2019-05-06 22:59:34 +03:00
2024-06-22 15:16:11 +03:00
// Start Unicode Alt input (hold).
2024-09-05 10:52:29 +03:00
if ( k - > is_alt_pressed ( ) & & k - > get_keycode ( ) = = Key : : KP_ADD & & ! alt_start & & ! alt_start_no_hold ) {
if ( selection . enabled ) {
selection_delete ( ) ;
2019-05-06 22:59:34 +03:00
}
2024-09-05 10:52:29 +03:00
alt_start = true ;
alt_code = 0 ;
2024-06-22 15:16:11 +03:00
alt_mode = ALT_INPUT_UNICODE ;
2024-09-05 10:52:29 +03:00
ime_text = " u " ;
ime_selection = Vector2i ( 0 , - 1 ) ;
_shape ( ) ;
queue_redraw ( ) ;
accept_event ( ) ;
2024-09-10 13:43:31 +00:00
return ;
}
2017-05-20 12:38:03 -03:00
2024-09-05 10:52:29 +03:00
// Start Unicode input (press).
if ( k - > is_action ( " ui_unicode_start " , true ) & & ! alt_start & & ! alt_start_no_hold ) {
if ( selection . enabled ) {
selection_delete ( ) ;
}
alt_start_no_hold = true ;
alt_code = 0 ;
2024-06-22 15:16:11 +03:00
alt_mode = ALT_INPUT_UNICODE ;
2024-09-05 10:52:29 +03:00
ime_text = " u " ;
ime_selection = Vector2i ( 0 , - 1 ) ;
_shape ( ) ;
queue_redraw ( ) ;
accept_event ( ) ;
return ;
}
2024-06-22 15:16:11 +03:00
// Start OEM Alt input (hold).
if ( k - > is_alt_pressed ( ) & & k - > get_keycode ( ) > = Key : : KP_1 & & k - > get_keycode ( ) < = Key : : KP_9 & & ! alt_start & & ! alt_start_no_hold ) {
if ( selection . enabled ) {
selection_delete ( ) ;
}
alt_start = true ;
alt_code = ( uint32_t ) ( k - > get_keycode ( ) - Key : : KP_0 ) ;
alt_mode = ALT_INPUT_OEM ;
ime_text = vformat ( " o%s " , String : : num_int64 ( alt_code , 10 ) ) ;
ime_selection = Vector2i ( 0 , - 1 ) ;
_shape ( ) ;
queue_redraw ( ) ;
accept_event ( ) ;
return ;
}
// Start Windows Alt input (hold).
if ( k - > is_alt_pressed ( ) & & k - > get_keycode ( ) = = Key : : KP_0 & & ! alt_start & & ! alt_start_no_hold ) {
if ( selection . enabled ) {
selection_delete ( ) ;
}
alt_start = true ;
alt_mode = ALT_INPUT_WIN ;
alt_code = 0 ;
ime_text = " w " ;
ime_selection = Vector2i ( 0 , - 1 ) ;
_shape ( ) ;
queue_redraw ( ) ;
accept_event ( ) ;
return ;
}
2024-09-05 10:52:29 +03:00
// Update Unicode input.
if ( k - > is_pressed ( ) & & ( ( k - > is_alt_pressed ( ) & & alt_start ) | | alt_start_no_hold ) ) {
if ( k - > get_keycode ( ) > = Key : : KEY_0 & & k - > get_keycode ( ) < = Key : : KEY_9 ) {
2024-06-22 15:16:11 +03:00
if ( alt_mode = = ALT_INPUT_UNICODE ) {
alt_code = alt_code < < 4 ;
} else {
alt_code = alt_code * 10 ;
}
2024-09-05 10:52:29 +03:00
alt_code + = ( uint32_t ) ( k - > get_keycode ( ) - Key : : KEY_0 ) ;
} else if ( k - > get_keycode ( ) > = Key : : KP_0 & & k - > get_keycode ( ) < = Key : : KP_9 ) {
2024-06-22 15:16:11 +03:00
if ( alt_mode = = ALT_INPUT_UNICODE ) {
alt_code = alt_code < < 4 ;
} else {
alt_code = alt_code * 10 ;
}
2024-09-05 10:52:29 +03:00
alt_code + = ( uint32_t ) ( k - > get_keycode ( ) - Key : : KP_0 ) ;
2024-06-22 15:16:11 +03:00
} else if ( alt_mode = = ALT_INPUT_UNICODE & & k - > get_keycode ( ) > = Key : : A & & k - > get_keycode ( ) < = Key : : F ) {
2024-09-05 10:52:29 +03:00
alt_code = alt_code < < 4 ;
alt_code + = ( uint32_t ) ( k - > get_keycode ( ) - Key : : A ) + 10 ;
} else if ( ( Key ) k - > get_unicode ( ) > = Key : : KEY_0 & & ( Key ) k - > get_unicode ( ) < = Key : : KEY_9 ) {
2024-06-22 15:16:11 +03:00
if ( alt_mode = = ALT_INPUT_UNICODE ) {
alt_code = alt_code < < 4 ;
} else {
alt_code = alt_code * 10 ;
}
2024-09-05 10:52:29 +03:00
alt_code + = ( uint32_t ) ( ( Key ) k - > get_unicode ( ) - Key : : KEY_0 ) ;
2024-06-22 15:16:11 +03:00
} else if ( alt_mode = = ALT_INPUT_UNICODE & & ( Key ) k - > get_unicode ( ) > = Key : : A & & ( Key ) k - > get_unicode ( ) < = Key : : F ) {
2024-09-05 10:52:29 +03:00
alt_code = alt_code < < 4 ;
alt_code + = ( uint32_t ) ( ( Key ) k - > get_unicode ( ) - Key : : A ) + 10 ;
} else if ( k - > get_physical_keycode ( ) > = Key : : KEY_0 & & k - > get_physical_keycode ( ) < = Key : : KEY_9 ) {
2024-06-22 15:16:11 +03:00
if ( alt_mode = = ALT_INPUT_UNICODE ) {
alt_code = alt_code < < 4 ;
} else {
alt_code = alt_code * 10 ;
}
2024-09-05 10:52:29 +03:00
alt_code + = ( uint32_t ) ( k - > get_physical_keycode ( ) - Key : : KEY_0 ) ;
}
if ( k - > get_keycode ( ) = = Key : : BACKSPACE ) {
2024-06-22 15:16:11 +03:00
if ( alt_mode = = ALT_INPUT_UNICODE ) {
alt_code = alt_code > > 4 ;
} else {
alt_code = alt_code / 10 ;
}
2024-09-05 10:52:29 +03:00
}
if ( alt_code > 0x10ffff ) {
alt_code = 0x10ffff ;
}
if ( alt_code > 0 ) {
2024-06-22 15:16:11 +03:00
if ( alt_mode = = ALT_INPUT_UNICODE ) {
ime_text = vformat ( " u%s " , String : : num_int64 ( alt_code , 16 , true ) ) ;
} else if ( alt_mode = = ALT_INPUT_OEM ) {
ime_text = vformat ( " o%s " , String : : num_int64 ( alt_code , 10 ) ) ;
} else if ( alt_mode = = ALT_INPUT_WIN ) {
ime_text = vformat ( " w%s " , String : : num_int64 ( alt_code , 10 ) ) ;
}
2024-09-10 13:43:31 +00:00
} else {
2024-06-22 15:16:11 +03:00
if ( alt_mode = = ALT_INPUT_UNICODE ) {
ime_text = " u " ;
} else if ( alt_mode = = ALT_INPUT_OEM ) {
ime_text = " o " ;
} else if ( alt_mode = = ALT_INPUT_WIN ) {
ime_text = " w " ;
}
2024-09-05 10:52:29 +03:00
}
ime_selection = Vector2i ( 0 , - 1 ) ;
_shape ( ) ;
queue_redraw ( ) ;
accept_event ( ) ;
return ;
}
// Submit Unicode input.
if ( ( ! k - > is_pressed ( ) & & alt_start & & k - > get_keycode ( ) = = Key : : ALT ) | | ( alt_start_no_hold & & ( k - > is_action ( " ui_text_submit " , true ) | | k - > is_action ( " ui_accept " , true ) ) ) ) {
alt_start = false ;
alt_start_no_hold = false ;
2025-10-03 00:38:47 -04:00
int prev_len = text . length ( ) ;
2024-06-22 15:16:11 +03:00
if ( ( alt_code > 0x31 & & alt_code < 0xd800 ) | | ( alt_code > 0xdfff ) ) {
2024-09-05 10:52:29 +03:00
ime_text = String ( ) ;
ime_selection = Vector2i ( ) ;
2024-06-22 15:16:11 +03:00
if ( alt_mode = = ALT_INPUT_UNICODE ) {
if ( ( alt_code > 0x31 & & alt_code < 0xd800 ) | | ( alt_code > 0xdfff ) ) {
char32_t ucodestr [ 2 ] = { ( char32_t ) alt_code , 0 } ;
insert_text_at_caret ( ucodestr ) ;
}
} else if ( alt_mode = = ALT_INPUT_OEM ) {
if ( alt_code > 0x00 & & alt_code < = 0xff ) {
char32_t ucodestr [ 2 ] = { alt_code_oem437 [ alt_code ] , 0 } ;
insert_text_at_caret ( ucodestr ) ;
} else if ( ( alt_code > 0xff & & alt_code < 0xd800 ) | | ( alt_code > 0xdfff ) ) {
char32_t ucodestr [ 2 ] = { ( char32_t ) alt_code , 0 } ;
insert_text_at_caret ( ucodestr ) ;
}
} else if ( alt_mode = = ALT_INPUT_WIN ) {
if ( alt_code > 0x00 & & alt_code < = 0xff ) {
char32_t ucodestr [ 2 ] = { alt_code_cp1252 [ alt_code ] , 0 } ;
insert_text_at_caret ( ucodestr ) ;
} else if ( ( alt_code > 0xff & & alt_code < 0xd800 ) | | ( alt_code > 0xdfff ) ) {
char32_t ucodestr [ 2 ] = { ( char32_t ) alt_code , 0 } ;
insert_text_at_caret ( ucodestr ) ;
}
}
alt_mode = ALT_INPUT_NONE ;
2025-10-03 00:38:47 -04:00
// Mirror paste behavior: defer _text_changed once per frame while emitting text_changed signal.
if ( ! text_changed_dirty ) {
if ( is_inside_tree ( ) & & text . length ( ) ! = prev_len ) {
callable_mp ( this , & LineEdit : : _text_changed ) . call_deferred ( ) ;
}
text_changed_dirty = true ;
}
2024-09-05 10:52:29 +03:00
} else {
ime_text = String ( ) ;
ime_selection = Vector2i ( ) ;
_shape ( ) ;
2020-12-07 21:32:00 +10:00
}
2024-09-05 10:52:29 +03:00
queue_redraw ( ) ;
accept_event ( ) ;
return ;
2024-09-10 13:43:31 +00:00
}
2024-09-05 10:52:29 +03:00
// Cancel Unicode input.
if ( alt_start_no_hold & & k - > is_action ( " ui_cancel " , true ) ) {
alt_start = false ;
alt_start_no_hold = false ;
2024-06-22 15:16:11 +03:00
alt_mode = ALT_INPUT_NONE ;
2024-09-05 10:52:29 +03:00
ime_text = String ( ) ;
ime_selection = Vector2i ( ) ;
_shape ( ) ;
queue_redraw ( ) ;
accept_event ( ) ;
return ;
}
if ( ! k - > is_pressed ( ) ) {
return ;
}
2024-09-10 13:43:31 +00:00
// Default is ENTER and KP_ENTER. Cannot use ui_accept as default includes SPACE.
if ( k - > is_action_pressed ( " ui_text_submit " ) ) {
2024-11-02 16:15:39 +01:00
emit_signal ( SceneStringName ( text_submitted ) , text ) ;
2016-06-18 16:15:26 +02:00
2025-01-02 23:41:27 +02:00
if ( editing & & ! keep_editing_on_text_submit ) {
2024-10-04 10:37:33 +00:00
unedit ( ) ;
emit_signal ( SNAME ( " editing_toggled " ) , false ) ;
2025-05-22 22:10:16 +02:00
if ( DisplayServer : : get_singleton ( ) - > has_feature ( DisplayServer : : FEATURE_VIRTUAL_KEYBOARD ) & & virtual_keyboard_enabled ) {
DisplayServer : : get_singleton ( ) - > virtual_keyboard_hide ( ) ;
}
2024-09-10 13:43:31 +00:00
}
2016-06-18 16:15:26 +02:00
2024-09-10 13:43:31 +00:00
accept_event ( ) ;
return ;
}
2014-02-09 22:10:30 -03:00
2024-09-10 13:43:31 +00:00
if ( k - > is_action ( " ui_cancel " ) ) {
if ( editing ) {
2024-10-04 10:37:33 +00:00
unedit ( ) ;
emit_signal ( SNAME ( " editing_toggled " ) , false ) ;
2020-12-07 21:32:00 +10:00
}
2024-09-10 13:43:31 +00:00
accept_event ( ) ;
return ;
}
if ( is_shortcut_keys_enabled ( ) ) {
if ( k - > is_action ( " ui_paste " , true ) ) {
paste_text ( ) ;
2020-12-07 21:32:00 +10:00
accept_event ( ) ;
return ;
}
2024-09-10 13:43:31 +00:00
// Undo / Redo
if ( k - > is_action ( " ui_undo " , true ) ) {
undo ( ) ;
2020-12-07 21:32:00 +10:00
accept_event ( ) ;
return ;
}
2014-02-09 22:10:30 -03:00
2024-09-10 13:43:31 +00:00
if ( k - > is_action ( " ui_redo " , true ) ) {
redo ( ) ;
2020-12-07 21:32:00 +10:00
accept_event ( ) ;
return ;
}
2024-09-10 13:43:31 +00:00
}
2016-01-07 21:38:38 +01:00
2024-09-10 13:43:31 +00:00
// BACKSPACE
if ( k - > is_action ( " ui_text_backspace_all_to_left " , true ) ) {
_backspace ( false , true ) ;
accept_event ( ) ;
return ;
}
if ( k - > is_action ( " ui_text_backspace_word " , true ) ) {
_backspace ( true ) ;
accept_event ( ) ;
return ;
}
if ( k - > is_action ( " ui_text_backspace " , true ) ) {
_backspace ( ) ;
accept_event ( ) ;
return ;
}
2017-05-20 12:38:03 -03:00
2024-09-10 13:43:31 +00:00
// DELETE
if ( k - > is_action ( " ui_text_delete_all_to_right " , true ) ) {
_delete ( false , true ) ;
accept_event ( ) ;
return ;
}
if ( k - > is_action ( " ui_text_delete_word " , true ) ) {
_delete ( true ) ;
accept_event ( ) ;
return ;
}
if ( k - > is_action ( " ui_text_delete " , true ) ) {
_delete ( ) ;
accept_event ( ) ;
return ;
}
2014-02-09 22:10:30 -03:00
2024-09-10 13:43:31 +00:00
// Cursor Movement
k = k - > duplicate ( ) ;
bool shift_pressed = k - > is_shift_pressed ( ) ;
// Remove shift or else actions will not match. Use above variable for selection.
k - > set_shift_pressed ( false ) ;
if ( k - > is_action ( " ui_text_caret_word_left " , true ) ) {
_move_caret_left ( shift_pressed , true ) ;
accept_event ( ) ;
return ;
}
if ( k - > is_action ( " ui_text_caret_left " , true ) ) {
_move_caret_left ( shift_pressed ) ;
accept_event ( ) ;
return ;
}
if ( k - > is_action ( " ui_text_caret_word_right " , true ) ) {
_move_caret_right ( shift_pressed , true ) ;
accept_event ( ) ;
return ;
}
if ( k - > is_action ( " ui_text_caret_right " , true ) ) {
_move_caret_right ( shift_pressed , false ) ;
accept_event ( ) ;
return ;
}
// Up = Home, Down = End
if ( k - > is_action ( " ui_text_caret_up " , true ) | | k - > is_action ( " ui_text_caret_line_start " , true ) | | k - > is_action ( " ui_text_caret_page_up " , true ) ) {
_move_caret_start ( shift_pressed ) ;
accept_event ( ) ;
return ;
}
if ( k - > is_action ( " ui_text_caret_down " , true ) | | k - > is_action ( " ui_text_caret_line_end " , true ) | | k - > is_action ( " ui_text_caret_page_down " , true ) ) {
_move_caret_end ( shift_pressed ) ;
accept_event ( ) ;
return ;
}
// Misc
if ( k - > is_action ( " ui_swap_input_direction " , true ) ) {
_swap_current_input_direction ( ) ;
accept_event ( ) ;
return ;
}
_reset_caret_blink_timer ( ) ;
// Allow unicode handling if:
// * No Modifiers are pressed (except shift)
bool allow_unicode_handling = ! ( k - > is_ctrl_pressed ( ) | | k - > is_alt_pressed ( ) | | k - > is_meta_pressed ( ) ) ;
if ( allow_unicode_handling & & editable & & k - > get_unicode ( ) > = 32 ) {
// Handle Unicode if no modifiers are active.
selection_delete ( ) ;
char32_t ucodestr [ 2 ] = { ( char32_t ) k - > get_unicode ( ) , 0 } ;
int prev_len = text . length ( ) ;
insert_text_at_caret ( ucodestr ) ;
if ( text . length ( ) ! = prev_len ) {
if ( ! text_changed_dirty ) {
if ( is_inside_tree ( ) ) {
callable_mp ( this , & LineEdit : : _text_changed ) . call_deferred ( ) ;
2023-12-22 23:42:24 +02:00
}
2024-09-10 13:43:31 +00:00
text_changed_dirty = true ;
2014-02-09 22:10:30 -03:00
}
2017-05-20 12:38:03 -03:00
}
2024-09-10 13:43:31 +00:00
accept_event ( ) ;
return ;
2014-02-09 22:10:30 -03:00
}
}
2021-11-24 20:58:47 -06:00
void LineEdit : : set_horizontal_alignment ( HorizontalAlignment p_alignment ) {
ERR_FAIL_INDEX ( ( int ) p_alignment , 4 ) ;
2022-03-16 15:50:48 +08:00
if ( alignment = = p_alignment ) {
return ;
2020-09-09 16:00:32 +03:00
}
2022-03-16 15:50:48 +08:00
alignment = p_alignment ;
_shape ( ) ;
2022-08-13 23:21:24 +02:00
queue_redraw ( ) ;
2015-08-15 07:47:22 +01:00
}
2021-11-24 20:58:47 -06:00
HorizontalAlignment LineEdit : : get_horizontal_alignment ( ) const {
return alignment ;
2015-08-15 07:47:22 +01:00
}
2014-02-09 22:10:30 -03:00
Variant LineEdit : : get_drag_data ( const Point2 & p_point ) {
2023-03-20 00:38:00 +01:00
Variant ret = Control : : get_drag_data ( p_point ) ;
if ( ret ! = Variant ( ) ) {
return ret ;
}
2014-02-09 22:10:30 -03:00
if ( selection . drag_attempt & & selection . enabled ) {
2023-03-30 17:07:28 +02:00
String t = get_selected_text ( ) ;
2014-02-09 22:10:30 -03:00
Label * l = memnew ( Label ) ;
l - > set_text ( t ) ;
2025-04-22 11:57:16 +03:00
l - > set_focus_mode ( FOCUS_ACCESSIBILITY ) ;
2024-09-19 08:14:00 +08:00
l - > set_auto_translate_mode ( AUTO_TRANSLATE_MODE_DISABLED ) ; // Don't translate user input.
2014-02-09 22:10:30 -03:00
set_drag_preview ( l ) ;
return t ;
}
return Variant ( ) ;
}
2020-05-14 14:29:06 +02:00
2014-02-09 22:10:30 -03:00
bool LineEdit : : can_drop_data ( const Point2 & p_point , const Variant & p_data ) const {
2020-12-13 20:16:56 +01:00
bool drop_override = Control : : can_drop_data ( p_point , p_data ) ; // In case user wants to drop custom data.
if ( drop_override ) {
return drop_override ;
}
2023-12-28 14:44:23 -08:00
return is_editable ( ) & & p_data . is_string ( ) ;
2014-02-09 22:10:30 -03:00
}
2020-05-14 14:29:06 +02:00
2014-02-09 22:10:30 -03:00
void LineEdit : : drop_data ( const Point2 & p_point , const Variant & p_data ) {
2020-12-13 20:16:56 +01:00
Control : : drop_data ( p_point , p_data ) ;
2023-12-28 14:44:23 -08:00
if ( p_data . is_string ( ) & & is_editable ( ) ) {
2024-09-05 10:52:29 +03:00
apply_ime ( ) ;
2025-04-10 11:21:05 -05:00
if ( p_point ! = Vector2 ( Math : : INF , Math : : INF ) ) {
2025-03-21 16:42:23 +02:00
set_caret_at_pixel_pos ( p_point . x ) ;
}
2021-10-28 09:07:18 +02:00
int caret_column_tmp = caret_column ;
2021-11-24 22:22:40 +01:00
bool is_inside_sel = selection . enabled & & caret_column > = selection . begin & & caret_column < = selection . end ;
2023-06-08 23:24:00 +02:00
if ( Input : : get_singleton ( ) - > is_key_pressed ( Key : : CMD_OR_CTRL ) ) {
2021-11-24 22:22:40 +01:00
is_inside_sel = selection . enabled & & caret_column > selection . begin & & caret_column < selection . end ;
}
2021-10-28 09:07:18 +02:00
if ( selection . drag_attempt ) {
selection . drag_attempt = false ;
2021-11-24 22:22:40 +01:00
if ( ! is_inside_sel ) {
2023-06-08 23:24:00 +02:00
if ( ! Input : : get_singleton ( ) - > is_key_pressed ( Key : : CMD_OR_CTRL ) ) {
2021-11-24 22:22:40 +01:00
if ( caret_column_tmp > selection . end ) {
caret_column_tmp = caret_column_tmp - ( selection . end - selection . begin ) ;
}
selection_delete ( ) ;
2021-10-28 09:07:18 +02:00
}
2015-08-15 07:47:22 +01:00
2021-10-28 09:07:18 +02:00
set_caret_column ( caret_column_tmp ) ;
insert_text_at_caret ( p_data ) ;
}
} else if ( selection . enabled & & caret_column > = selection . begin & & caret_column < = selection . end ) {
caret_column_tmp = selection . begin ;
selection_delete ( ) ;
set_caret_column ( caret_column_tmp ) ;
insert_text_at_caret ( p_data ) ;
2025-10-01 11:14:22 -03:00
grab_focus ( true ) ;
2021-10-28 09:07:18 +02:00
} else {
insert_text_at_caret ( p_data ) ;
2025-10-01 11:14:22 -03:00
grab_focus ( true ) ;
2021-10-28 09:07:18 +02:00
}
select ( caret_column_tmp , caret_column ) ;
if ( ! text_changed_dirty ) {
if ( is_inside_tree ( ) ) {
2023-12-18 15:46:56 +01:00
callable_mp ( this , & LineEdit : : _text_changed ) . call_deferred ( ) ;
2021-10-28 09:07:18 +02:00
}
text_changed_dirty = true ;
}
2025-03-21 16:42:23 +02:00
queue_accessibility_update ( ) ;
2022-08-13 23:21:24 +02:00
queue_redraw ( ) ;
2014-02-09 22:10:30 -03:00
}
}
2018-07-26 13:45:38 +02:00
Control : : CursorShape LineEdit : : get_cursor_shape ( const Point2 & p_pos ) const {
2021-05-07 17:39:55 +02:00
if ( ( ! text . is_empty ( ) & & is_editable ( ) & & _is_over_clear_button ( p_pos ) ) | | ( ! is_editable ( ) & & ( ! is_selecting_enabled ( ) | | text . is_empty ( ) ) ) ) {
2018-07-26 13:45:38 +02:00
return CURSOR_ARROW ;
}
return Control : : get_cursor_shape ( p_pos ) ;
}
bool LineEdit : : _is_over_clear_button ( const Point2 & p_pos ) const {
if ( ! clear_button_enabled | | ! has_point ( p_pos ) ) {
return false ;
}
2022-08-31 15:02:40 +03:00
Ref < Texture2D > icon = theme_cache . clear_icon ;
2025-08-05 19:29:22 +02:00
return is_layout_rtl ( ) ? p_pos . x < theme_cache . normal - > get_margin ( SIDE_LEFT ) + icon - > get_width ( ) : p_pos . x > get_size ( ) . width - icon - > get_width ( ) - theme_cache . normal - > get_margin ( SIDE_RIGHT ) ;
2018-07-26 13:45:38 +02:00
}
2022-08-31 15:02:40 +03:00
void LineEdit : : _update_theme_item_cache ( ) {
Control : : _update_theme_item_cache ( ) ;
theme_cache . base_scale = get_theme_default_base_scale ( ) ;
}
2025-03-21 16:42:23 +02:00
void LineEdit : : _accessibility_action_set_selection ( const Variant & p_data ) {
Dictionary new_selection = p_data ;
int sel_start_pos = new_selection [ " start_char " ] ;
int sel_end_pos = new_selection [ " end_char " ] ;
select ( sel_start_pos , sel_end_pos ) ;
}
void LineEdit : : _accessibility_action_replace_selected ( const Variant & p_data ) {
String new_text = p_data ;
insert_text_at_caret ( new_text ) ;
}
void LineEdit : : _accessibility_action_set_value ( const Variant & p_data ) {
String new_text = p_data ;
set_text ( new_text ) ;
}
void LineEdit : : _accessibility_action_menu ( const Variant & p_data ) {
_update_context_menu ( ) ;
Point2 pos = Point2 ( get_caret_pixel_pos ( ) . x , ( get_size ( ) . y + theme_cache . font - > get_height ( theme_cache . font_size ) ) / 2 ) ;
menu - > set_position ( get_screen_position ( ) + pos ) ;
menu - > reset_size ( ) ;
menu - > popup ( ) ;
menu - > grab_focus ( ) ;
}
2014-02-09 22:10:30 -03:00
void LineEdit : : _notification ( int p_what ) {
switch ( p_what ) {
2016-06-21 14:38:35 +01:00
# ifdef TOOLS_ENABLED
case NOTIFICATION_ENTER_TREE : {
2023-11-29 16:54:34 +01:00
if ( Engine : : get_singleton ( ) - > is_editor_hint ( ) & & ! is_part_of_edited_scene ( ) ) {
2022-03-06 21:39:19 +01:00
set_caret_blink_enabled ( EDITOR_GET ( " text_editor/appearance/caret/caret_blink " ) ) ;
2022-08-13 14:52:35 +02:00
set_caret_blink_interval ( EDITOR_GET ( " text_editor/appearance/caret/caret_blink_interval " ) ) ;
2016-03-09 00:00:52 +01:00
2020-02-21 18:28:45 +01:00
if ( ! EditorSettings : : get_singleton ( ) - > is_connected ( " settings_changed " , callable_mp ( this , & LineEdit : : _editor_settings_changed ) ) ) {
EditorSettings : : get_singleton ( ) - > connect ( " settings_changed " , callable_mp ( this , & LineEdit : : _editor_settings_changed ) ) ;
2016-06-30 15:12:14 +01:00
}
2016-06-21 14:38:35 +01:00
}
} break ;
# endif
2025-03-21 16:42:23 +02:00
case NOTIFICATION_EXIT_TREE :
case NOTIFICATION_ACCESSIBILITY_INVALIDATE : {
accessibility_text_root_element = RID ( ) ;
} break ;
case NOTIFICATION_ACCESSIBILITY_UPDATE : {
RID ae = get_accessibility_element ( ) ;
ERR_FAIL_COND ( ae . is_null ( ) ) ;
DisplayServer : : get_singleton ( ) - > accessibility_update_set_role ( ae , DisplayServer : : AccessibilityRole : : ROLE_TEXT_FIELD ) ;
bool using_placeholder = text . is_empty ( ) & & ime_text . is_empty ( ) ;
if ( using_placeholder & & ! placeholder . is_empty ( ) ) {
DisplayServer : : get_singleton ( ) - > accessibility_update_set_placeholder ( ae , atr ( placeholder ) ) ;
}
if ( ! placeholder . is_empty ( ) & & get_accessibility_name ( ) . is_empty ( ) ) {
DisplayServer : : get_singleton ( ) - > accessibility_update_set_name ( ae , atr ( placeholder ) ) ;
}
DisplayServer : : get_singleton ( ) - > accessibility_update_set_flag ( ae , DisplayServer : : AccessibilityFlags : : FLAG_READONLY , ! editable ) ;
DisplayServer : : get_singleton ( ) - > accessibility_update_add_action ( ae , DisplayServer : : AccessibilityAction : : ACTION_SET_TEXT_SELECTION , callable_mp ( this , & LineEdit : : _accessibility_action_set_selection ) ) ;
DisplayServer : : get_singleton ( ) - > accessibility_update_add_action ( ae , DisplayServer : : AccessibilityAction : : ACTION_REPLACE_SELECTED_TEXT , callable_mp ( this , & LineEdit : : _accessibility_action_replace_selected ) ) ;
DisplayServer : : get_singleton ( ) - > accessibility_update_add_action ( ae , DisplayServer : : AccessibilityAction : : ACTION_SET_VALUE , callable_mp ( this , & LineEdit : : _accessibility_action_set_value ) ) ;
DisplayServer : : get_singleton ( ) - > accessibility_update_add_action ( ae , DisplayServer : : AccessibilityAction : : ACTION_SHOW_CONTEXT_MENU , callable_mp ( this , & LineEdit : : _accessibility_action_menu ) ) ;
2025-09-10 15:14:18 +08:00
const String & lang = language . is_empty ( ) ? _get_locale ( ) : language ;
DisplayServer : : get_singleton ( ) - > accessibility_update_set_language ( ae , lang ) ;
2025-03-21 16:42:23 +02:00
bool rtl = is_layout_rtl ( ) ;
Ref < StyleBox > style = theme_cache . normal ;
Ref < Font > font = theme_cache . font ;
Size2 size = get_size ( ) ;
int x_ofs = 0 ;
float text_width = TS - > shaped_text_get_size ( text_rid ) . x ;
float text_height = TS - > shaped_text_get_size ( text_rid ) . y ;
int y_area = size . height - style - > get_minimum_size ( ) . height ;
int y_ofs = style - > get_offset ( ) . y + ( y_area - text_height ) / 2 ;
switch ( alignment ) {
case HORIZONTAL_ALIGNMENT_FILL :
case HORIZONTAL_ALIGNMENT_LEFT : {
if ( rtl ) {
x_ofs = MAX ( style - > get_margin ( SIDE_LEFT ) , int ( size . width - Math : : ceil ( style - > get_margin ( SIDE_RIGHT ) + ( text_width ) ) ) ) ;
} else {
2025-08-05 19:29:22 +02:00
x_ofs = style - > get_margin ( SIDE_LEFT ) ;
2025-03-21 16:42:23 +02:00
}
} break ;
case HORIZONTAL_ALIGNMENT_CENTER : {
if ( ! Math : : is_zero_approx ( scroll_offset ) ) {
2025-08-05 19:29:22 +02:00
x_ofs = style - > get_margin ( SIDE_LEFT ) ;
2025-03-21 16:42:23 +02:00
} else {
2025-08-04 23:45:31 +02:00
int total_margin = style - > get_margin ( SIDE_LEFT ) + style - > get_margin ( SIDE_RIGHT ) ;
int centered = int ( ( size . width - total_margin - text_width ) ) / 2 ;
x_ofs = style - > get_margin ( SIDE_LEFT ) + MAX ( 0 , centered ) ;
2025-03-21 16:42:23 +02:00
}
} break ;
case HORIZONTAL_ALIGNMENT_RIGHT : {
if ( rtl ) {
2025-08-05 19:29:22 +02:00
x_ofs = style - > get_margin ( SIDE_LEFT ) ;
2025-03-21 16:42:23 +02:00
} else {
x_ofs = MAX ( style - > get_margin ( SIDE_LEFT ) , int ( size . width - Math : : ceil ( style - > get_margin ( SIDE_RIGHT ) + ( text_width ) ) ) ) ;
}
} break ;
}
bool display_clear_icon = ! using_placeholder & & is_editable ( ) & & clear_button_enabled ;
if ( right_icon . is_valid ( ) | | display_clear_icon ) {
Ref < Texture2D > r_icon = display_clear_icon ? theme_cache . clear_icon : right_icon ;
2024-11-22 21:27:36 +07:00
Point2 right_icon_size = _get_right_icon_size ( r_icon ) ;
2025-03-21 16:42:23 +02:00
if ( alignment = = HORIZONTAL_ALIGNMENT_CENTER ) {
if ( Math : : is_zero_approx ( scroll_offset ) ) {
2025-08-04 23:45:31 +02:00
int total_margin = style - > get_margin ( SIDE_LEFT ) + style - > get_margin ( SIDE_RIGHT ) ;
2024-11-22 21:27:36 +07:00
int center = int ( size . width - total_margin - text_width - right_icon_size . width ) / 2 ;
2025-08-04 23:45:31 +02:00
x_ofs = style - > get_margin ( SIDE_LEFT ) + MAX ( 0 , center ) ;
2025-03-21 16:42:23 +02:00
}
2025-08-05 19:29:22 +02:00
if ( rtl ) {
2024-11-22 21:27:36 +07:00
x_ofs + = right_icon_size . width ;
2025-08-05 19:29:22 +02:00
}
2025-03-21 16:42:23 +02:00
} else {
2025-08-05 19:29:22 +02:00
if ( rtl ) {
2024-11-22 21:27:36 +07:00
x_ofs = MAX ( style - > get_margin ( SIDE_LEFT ) + right_icon_size . width , x_ofs ) ;
2025-08-05 19:29:22 +02:00
} else {
2024-11-22 21:27:36 +07:00
x_ofs = MAX ( style - > get_margin ( SIDE_LEFT ) , x_ofs - right_icon_size . width - style - > get_margin ( SIDE_RIGHT ) ) ;
2025-08-05 19:29:22 +02:00
}
2025-03-21 16:42:23 +02:00
}
}
float text_off_x = x_ofs + scroll_offset ;
if ( accessibility_text_root_element . is_null ( ) ) {
2025-12-02 14:54:14 -05:00
accessibility_text_root_element = DisplayServer : : get_singleton ( ) - > accessibility_create_sub_text_edit_elements ( ae , using_placeholder ? RID ( ) : text_rid , text_height , - 1 , true ) ;
2025-03-21 16:42:23 +02:00
}
Transform2D text_xform ;
text_xform . set_origin ( Vector2i ( text_off_x , y_ofs ) ) ;
DisplayServer : : get_singleton ( ) - > accessibility_update_set_transform ( accessibility_text_root_element , text_xform ) ;
if ( selection . enabled ) {
DisplayServer : : get_singleton ( ) - > accessibility_update_set_text_selection ( ae , accessibility_text_root_element , selection . begin , accessibility_text_root_element , selection . end ) ;
} else {
DisplayServer : : get_singleton ( ) - > accessibility_update_set_text_selection ( ae , accessibility_text_root_element , caret_column , accessibility_text_root_element , caret_column ) ;
}
} break ;
2022-02-15 18:06:48 +01:00
2014-02-09 22:10:30 -03:00
case NOTIFICATION_RESIZED : {
2020-09-09 16:00:32 +03:00
_fit_to_width ( ) ;
2022-07-06 11:57:06 +03:00
scroll_offset = 0.0 ;
2021-03-28 19:31:25 +01:00
set_caret_column ( get_caret_column ( ) ) ;
2020-09-09 16:00:32 +03:00
} break ;
2022-02-15 18:06:48 +01:00
2020-09-09 16:00:32 +03:00
case NOTIFICATION_LAYOUT_DIRECTION_CHANGED :
case NOTIFICATION_THEME_CHANGED : {
_shape ( ) ;
2022-08-13 23:21:24 +02:00
queue_redraw ( ) ;
2014-02-09 22:10:30 -03:00
} break ;
2022-02-15 18:06:48 +01:00
2019-06-22 14:42:36 +02:00
case NOTIFICATION_TRANSLATION_CHANGED : {
2021-05-27 14:31:33 -03:00
placeholder_translated = atr ( placeholder ) ;
2020-09-09 16:00:32 +03:00
_shape ( ) ;
2022-08-13 23:21:24 +02:00
queue_redraw ( ) ;
2019-06-22 14:42:36 +02:00
} break ;
2022-02-15 18:06:48 +01:00
2020-06-29 20:47:18 -03:00
case NOTIFICATION_WM_WINDOW_FOCUS_IN : {
2016-06-21 00:16:18 +01:00
window_has_focus = true ;
2022-10-09 16:51:01 +08:00
_validate_caret_can_draw ( ) ;
2022-08-13 23:21:24 +02:00
queue_redraw ( ) ;
2016-06-21 00:16:18 +01:00
} break ;
2022-02-15 18:06:48 +01:00
2020-06-29 20:47:18 -03:00
case NOTIFICATION_WM_WINDOW_FOCUS_OUT : {
2016-06-21 00:16:18 +01:00
window_has_focus = false ;
2022-10-09 16:51:01 +08:00
_validate_caret_can_draw ( ) ;
2022-08-13 23:21:24 +02:00
queue_redraw ( ) ;
2016-06-21 00:16:18 +01:00
} break ;
2022-02-15 18:06:48 +01:00
2022-07-04 23:17:34 +02:00
case NOTIFICATION_INTERNAL_PROCESS : {
2022-10-09 16:51:01 +08:00
if ( caret_blink_enabled & & caret_can_draw ) {
2022-07-04 23:17:34 +02:00
caret_blink_timer + = get_process_delta_time ( ) ;
2022-08-13 14:52:35 +02:00
if ( caret_blink_timer > = caret_blink_interval ) {
2022-07-04 23:17:34 +02:00
caret_blink_timer = 0.0 ;
_toggle_draw_caret ( ) ;
}
}
} break ;
2014-02-09 22:10:30 -03:00
case NOTIFICATION_DRAW : {
int width , height ;
2020-09-09 16:00:32 +03:00
bool rtl = is_layout_rtl ( ) ;
2016-03-09 00:00:52 +01:00
2014-02-09 22:10:30 -03:00
Size2 size = get_size ( ) ;
width = size . width ;
height = size . height ;
2016-03-09 00:00:52 +01:00
2014-02-09 22:10:30 -03:00
RID ci = get_canvas_item ( ) ;
2016-03-09 00:00:52 +01:00
2022-08-31 15:02:40 +03:00
Ref < StyleBox > style = theme_cache . normal ;
2017-07-14 23:40:17 -05:00
if ( ! is_editable ( ) ) {
2022-08-31 15:02:40 +03:00
style = theme_cache . read_only ;
2017-07-14 23:40:17 -05:00
}
2022-08-31 15:02:40 +03:00
Ref < Font > font = theme_cache . font ;
2014-02-09 22:10:30 -03:00
2021-10-26 09:40:11 +03:00
if ( ! flat ) {
style - > draw ( ci , Rect2 ( Point2 ( ) , size ) ) ;
}
2014-02-09 22:10:30 -03:00
2025-09-24 16:26:48 +02:00
if ( has_focus ( Engine : : get_singleton ( ) - > is_editor_hint ( ) | | GLOBAL_GET_CACHED ( int , " gui/common/show_focus_state_on_pointer_event " ) ! = 1 ) ) {
2022-08-31 15:02:40 +03:00
theme_cache . focus - > draw ( ci , Rect2 ( Point2 ( ) , size ) ) ;
2014-02-09 22:10:30 -03:00
}
2015-08-15 07:47:22 +01:00
int x_ofs = 0 ;
2020-12-15 12:04:21 +00:00
bool using_placeholder = text . is_empty ( ) & & ime_text . is_empty ( ) ;
2020-09-09 16:00:32 +03:00
float text_width = TS - > shaped_text_get_size ( text_rid ) . x ;
2022-05-09 12:47:10 +03:00
float text_height = TS - > shaped_text_get_size ( text_rid ) . y ;
2015-08-15 07:47:22 +01:00
2021-11-24 20:58:47 -06:00
switch ( alignment ) {
case HORIZONTAL_ALIGNMENT_FILL :
case HORIZONTAL_ALIGNMENT_LEFT : {
2020-09-09 16:00:32 +03:00
if ( rtl ) {
2022-12-06 16:38:41 +01:00
x_ofs = MAX ( style - > get_margin ( SIDE_LEFT ) , int ( size . width - Math : : ceil ( style - > get_margin ( SIDE_RIGHT ) + ( text_width ) ) ) ) ;
2020-09-09 16:00:32 +03:00
} else {
2025-08-05 19:29:22 +02:00
x_ofs = style - > get_margin ( SIDE_LEFT ) ;
2020-09-09 16:00:32 +03:00
}
2015-08-15 07:47:22 +01:00
} break ;
2021-11-24 20:58:47 -06:00
case HORIZONTAL_ALIGNMENT_CENTER : {
2022-07-06 11:57:06 +03:00
if ( ! Math : : is_zero_approx ( scroll_offset ) ) {
2025-08-05 19:29:22 +02:00
x_ofs = style - > get_margin ( SIDE_LEFT ) ;
2020-05-14 16:41:43 +02:00
} else {
2025-08-04 23:45:31 +02:00
int total_margin = style - > get_margin ( SIDE_LEFT ) + style - > get_margin ( SIDE_RIGHT ) ;
int centered = int ( ( size . width - total_margin - text_width ) ) / 2 ;
x_ofs = style - > get_margin ( SIDE_LEFT ) + MAX ( 0 , centered ) ;
2020-05-14 16:41:43 +02:00
}
2015-08-15 07:47:22 +01:00
} break ;
2021-11-24 20:58:47 -06:00
case HORIZONTAL_ALIGNMENT_RIGHT : {
2020-09-09 16:00:32 +03:00
if ( rtl ) {
2025-08-05 19:29:22 +02:00
x_ofs = style - > get_margin ( SIDE_LEFT ) ;
2020-09-09 16:00:32 +03:00
} else {
2022-12-06 16:38:41 +01:00
x_ofs = MAX ( style - > get_margin ( SIDE_LEFT ) , int ( size . width - Math : : ceil ( style - > get_margin ( SIDE_RIGHT ) + ( text_width ) ) ) ) ;
2020-09-09 16:00:32 +03:00
}
2015-08-15 07:47:22 +01:00
} break ;
}
2020-12-22 16:24:29 +00:00
int ofs_max = width - style - > get_margin ( SIDE_RIGHT ) ;
2016-03-09 00:00:52 +01:00
2014-02-09 22:10:30 -03:00
int y_area = height - style - > get_minimum_size ( ) . height ;
2020-09-09 16:00:32 +03:00
int y_ofs = style - > get_offset ( ) . y + ( y_area - text_height ) / 2 ;
2016-03-09 00:00:52 +01:00
2022-08-31 15:02:40 +03:00
Color selection_color = theme_cache . selection_color ;
Color font_color ;
if ( is_editable ( ) ) {
font_color = theme_cache . font_color ;
} else {
font_color = theme_cache . font_uneditable_color ;
}
Color font_selected_color = theme_cache . font_selected_color ;
Color caret_color = theme_cache . caret_color ;
2016-03-09 00:00:52 +01:00
2019-09-08 22:46:57 -03:00
// Draw placeholder color.
2020-05-14 16:41:43 +02:00
if ( using_placeholder ) {
2022-08-31 15:02:40 +03:00
font_color = theme_cache . font_placeholder_color ;
2020-05-14 16:41:43 +02:00
}
2016-06-27 19:47:40 +08:00
2018-07-26 13:45:38 +02:00
bool display_clear_icon = ! using_placeholder & & is_editable ( ) & & clear_button_enabled ;
2018-08-11 12:04:19 +02:00
if ( right_icon . is_valid ( ) | | display_clear_icon ) {
2022-08-31 15:02:40 +03:00
Ref < Texture2D > r_icon = display_clear_icon ? theme_cache . clear_icon : right_icon ;
2024-11-22 21:27:36 +07:00
Point2 right_icon_size = _get_right_icon_size ( r_icon ) ;
2019-06-21 18:16:38 -05:00
Color color_icon ( 1 , 1 , 1 , ! is_editable ( ) ? .5 * .9 : .9 ) ;
2018-07-26 13:45:38 +02:00
if ( display_clear_icon ) {
if ( clear_button_status . press_attempt & & clear_button_status . pressing_inside ) {
2022-08-31 15:02:40 +03:00
color_icon = theme_cache . clear_button_color_pressed ;
2018-07-26 13:45:38 +02:00
} else {
2022-08-31 15:02:40 +03:00
color_icon = theme_cache . clear_button_color ;
2018-07-26 13:45:38 +02:00
}
}
2019-09-08 22:46:57 -03:00
2024-11-22 21:27:36 +07:00
Point2 icon_pos = Point2 ( width - right_icon_size . width - style - > get_margin ( SIDE_RIGHT ) , height / 2 - right_icon_size . height / 2 ) ;
2025-08-05 19:29:22 +02:00
if ( rtl ) {
icon_pos . x = style - > get_margin ( SIDE_LEFT ) ;
}
2024-11-22 21:27:36 +07:00
Rect2 icon_region = Rect2 ( icon_pos , right_icon_size ) ;
draw_texture_rect ( r_icon , icon_region , false , color_icon ) ;
2018-07-26 13:45:38 +02:00
2021-11-24 20:58:47 -06:00
if ( alignment = = HORIZONTAL_ALIGNMENT_CENTER ) {
2022-07-06 11:57:06 +03:00
if ( Math : : is_zero_approx ( scroll_offset ) ) {
2025-08-04 23:45:31 +02:00
int total_margin = style - > get_margin ( SIDE_LEFT ) + style - > get_margin ( SIDE_RIGHT ) ;
2024-11-22 21:27:36 +07:00
int center = int ( size . width - total_margin - text_width - right_icon_size . width ) / 2 ;
2025-08-04 23:45:31 +02:00
x_ofs = style - > get_margin ( SIDE_LEFT ) + MAX ( 0 , center ) ;
2018-07-26 13:45:38 +02:00
}
2025-08-05 19:29:22 +02:00
if ( rtl ) {
2024-11-22 21:27:36 +07:00
x_ofs + = right_icon_size . width ;
2025-08-05 19:29:22 +02:00
}
2018-07-26 13:45:38 +02:00
} else {
2025-08-05 19:29:22 +02:00
if ( rtl ) {
2024-11-22 21:27:36 +07:00
x_ofs = MAX ( style - > get_margin ( SIDE_LEFT ) + right_icon_size . width , x_ofs ) ;
2025-08-05 19:29:22 +02:00
} else {
2024-11-22 21:27:36 +07:00
x_ofs = MAX ( style - > get_margin ( SIDE_LEFT ) , x_ofs - right_icon_size . width - style - > get_margin ( SIDE_RIGHT ) ) ;
2025-08-05 19:29:22 +02:00
}
2018-07-26 13:45:38 +02:00
}
2019-04-21 13:55:40 -03:00
2025-08-05 19:29:22 +02:00
if ( ! rtl ) {
2024-11-22 21:27:36 +07:00
ofs_max - = right_icon_size . width ;
2025-08-05 19:29:22 +02:00
}
2017-07-18 14:35:37 -05:00
}
2020-09-09 16:00:32 +03:00
// Draw selections rects.
Vector2 ofs = Point2 ( x_ofs + scroll_offset , y_ofs ) ;
if ( selection . enabled ) {
Vector < Vector2 > sel = TS - > shaped_text_get_selection ( text_rid , selection . begin , selection . end ) ;
for ( int i = 0 ; i < sel . size ( ) ; i + + ) {
Rect2 rect = Rect2 ( sel [ i ] . x + ofs . x , ofs . y , sel [ i ] . y - sel [ i ] . x , text_height ) ;
if ( rect . position . x + rect . size . x < = x_ofs | | rect . position . x > ofs_max ) {
continue ;
}
if ( rect . position . x < x_ofs ) {
rect . size . x - = ( x_ofs - rect . position . x ) ;
rect . position . x = x_ofs ;
2025-03-19 10:50:47 +01:00
}
if ( rect . position . x + rect . size . x > ofs_max ) {
2020-09-09 16:00:32 +03:00
rect . size . x = ofs_max - rect . position . x ;
}
RenderingServer : : get_singleton ( ) - > canvas_item_add_rect ( ci , rect , selection_color ) ;
2020-05-14 16:41:43 +02:00
}
2020-09-09 16:00:32 +03:00
}
2025-03-21 16:42:23 +02:00
2021-08-28 00:19:51 +03:00
const Glyph * glyphs = TS - > shaped_text_get_glyphs ( text_rid ) ;
int gl_size = TS - > shaped_text_get_glyph_count ( text_rid ) ;
2020-09-09 16:00:32 +03:00
// Draw text.
ofs . y + = TS - > shaped_text_get_ascent ( text_rid ) ;
2022-08-31 15:02:40 +03:00
Color font_outline_color = theme_cache . font_outline_color ;
int outline_size = theme_cache . font_outline_size ;
2020-12-25 23:45:28 +02:00
if ( outline_size > 0 & & font_outline_color . a > 0 ) {
Vector2 oofs = ofs ;
for ( int i = 0 ; i < gl_size ; i + + ) {
for ( int j = 0 ; j < glyphs [ i ] . repeat ; j + + ) {
2025-03-19 14:18:09 -05:00
if ( std : : ceil ( oofs . x ) > = x_ofs & & ( oofs . x + glyphs [ i ] . advance ) < = ofs_max ) {
2020-12-25 23:45:28 +02:00
if ( glyphs [ i ] . font_rid ! = RID ( ) ) {
TS - > font_draw_glyph_outline ( glyphs [ i ] . font_rid , ci , glyphs [ i ] . font_size , outline_size , oofs + Vector2 ( glyphs [ i ] . x_off , glyphs [ i ] . y_off ) , glyphs [ i ] . index , font_outline_color ) ;
}
}
oofs . x + = glyphs [ i ] . advance ;
}
if ( oofs . x > = ofs_max ) {
break ;
}
}
}
2020-12-01 15:03:31 +02:00
for ( int i = 0 ; i < gl_size ; i + + ) {
2020-09-09 16:00:32 +03:00
bool selected = selection . enabled & & glyphs [ i ] . start > = selection . begin & & glyphs [ i ] . end < = selection . end ;
for ( int j = 0 ; j < glyphs [ i ] . repeat ; j + + ) {
2025-03-19 14:18:09 -05:00
if ( std : : ceil ( ofs . x ) > = x_ofs & & ( ofs . x + glyphs [ i ] . advance ) < = ofs_max ) {
2020-09-09 16:00:32 +03:00
if ( glyphs [ i ] . font_rid ! = RID ( ) ) {
2020-12-08 13:11:45 +00:00
TS - > font_draw_glyph ( glyphs [ i ] . font_rid , ci , glyphs [ i ] . font_size , ofs + Vector2 ( glyphs [ i ] . x_off , glyphs [ i ] . y_off ) , glyphs [ i ] . index , selected ? font_selected_color : font_color ) ;
2023-04-12 10:08:51 +03:00
} else if ( ( ( glyphs [ i ] . flags & TextServer : : GRAPHEME_IS_VIRTUAL ) ! = TextServer : : GRAPHEME_IS_VIRTUAL ) & & ( ( glyphs [ i ] . flags & TextServer : : GRAPHEME_IS_EMBEDDED_OBJECT ) ! = TextServer : : GRAPHEME_IS_EMBEDDED_OBJECT ) ) {
2020-12-08 13:11:45 +00:00
TS - > draw_hex_code_box ( ci , glyphs [ i ] . font_size , ofs + Vector2 ( glyphs [ i ] . x_off , glyphs [ i ] . y_off ) , glyphs [ i ] . index , selected ? font_selected_color : font_color ) ;
2017-08-07 14:09:56 +03:00
}
}
2020-09-09 16:00:32 +03:00
ofs . x + = glyphs [ i ] . advance ;
2017-08-07 14:09:56 +03:00
}
2020-09-09 16:00:32 +03:00
if ( ofs . x > = ofs_max ) {
2014-02-09 22:10:30 -03:00
break ;
2020-05-14 16:41:43 +02:00
}
2014-02-09 22:10:30 -03:00
}
2020-09-09 16:00:32 +03:00
// Draw carets.
ofs . x = x_ofs + scroll_offset ;
2022-10-09 16:51:01 +08:00
if ( ( caret_can_draw & & draw_caret ) | | drag_caret_force_displayed ) {
2022-03-03 00:15:48 +01:00
// Prevent carets from disappearing at theme scales below 1.0 (if the caret width is 1).
2022-08-31 15:02:40 +03:00
const int caret_width = theme_cache . caret_width * MAX ( 1 , theme_cache . base_scale ) ;
2021-11-13 23:06:47 +01:00
2022-12-11 01:21:22 +02:00
if ( ime_text . is_empty ( ) | | ime_selection . y = = 0 ) {
2020-09-09 16:00:32 +03:00
// Normal caret.
2022-12-11 01:21:22 +02:00
CaretInfo caret = TS - > shaped_text_get_carets ( text_rid , ime_text . is_empty ( ) ? caret_column : caret_column + ime_selection . x ) ;
2022-11-08 15:15:13 +02:00
if ( using_placeholder | | ( caret . l_caret = = Rect2 ( ) & & caret . t_caret = = Rect2 ( ) ) ) {
2020-09-09 16:00:32 +03:00
// No carets, add one at the start.
2022-08-31 15:02:40 +03:00
int h = theme_cache . font - > get_height ( theme_cache . font_size ) ;
2020-09-09 16:00:32 +03:00
int y = style - > get_offset ( ) . y + ( y_area - h ) / 2 ;
2022-11-08 15:15:13 +02:00
caret . l_dir = ( rtl ) ? TextServer : : DIRECTION_RTL : TextServer : : DIRECTION_LTR ;
switch ( alignment ) {
case HORIZONTAL_ALIGNMENT_FILL :
case HORIZONTAL_ALIGNMENT_LEFT : {
if ( rtl ) {
caret . l_caret = Rect2 ( Vector2 ( ofs_max , y ) , Size2 ( caret_width , h ) ) ;
} else {
caret . l_caret = Rect2 ( Vector2 ( style - > get_offset ( ) . x , y ) , Size2 ( caret_width , h ) ) ;
}
} break ;
case HORIZONTAL_ALIGNMENT_CENTER : {
2025-08-04 23:45:31 +02:00
int icon_width = 0 ;
if ( right_icon . is_valid ( ) ) {
icon_width = right_icon - > get_width ( ) ;
}
int total_margin = style - > get_margin ( SIDE_LEFT ) + style - > get_margin ( SIDE_RIGHT ) ;
int center = int ( size . width - total_margin - icon_width ) / 2 ;
caret . l_caret = Rect2 ( Vector2 ( style - > get_margin ( SIDE_LEFT ) + MAX ( 0 , center ) , y ) , Size2 ( caret_width , h ) ) ;
2022-11-08 15:15:13 +02:00
} break ;
case HORIZONTAL_ALIGNMENT_RIGHT : {
if ( rtl ) {
2025-08-05 19:29:22 +02:00
caret . l_caret = Rect2 ( Vector2 ( x_ofs , y ) , Size2 ( caret_width , h ) ) ;
2022-11-08 15:15:13 +02:00
} else {
caret . l_caret = Rect2 ( Vector2 ( ofs_max , y ) , Size2 ( caret_width , h ) ) ;
}
} break ;
2020-05-14 16:41:43 +02:00
}
2022-12-11 01:21:22 +02:00
2021-08-28 00:19:51 +03:00
RenderingServer : : get_singleton ( ) - > canvas_item_add_rect ( ci , caret . l_caret , caret_color ) ;
2020-09-09 16:00:32 +03:00
} else {
2021-08-28 00:19:51 +03:00
if ( caret . l_caret ! = Rect2 ( ) & & caret . l_dir = = TextServer : : DIRECTION_AUTO ) {
2020-09-09 16:00:32 +03:00
// Draw extra marker on top of mid caret.
2022-10-06 14:30:50 +03:00
Rect2 trect = Rect2 ( caret . l_caret . position . x - 2.5 * caret_width , caret . l_caret . position . y , 6 * caret_width , caret_width ) ;
trect . position + = ofs ;
RenderingServer : : get_singleton ( ) - > canvas_item_add_rect ( ci , trect , caret_color ) ;
} else if ( caret . l_caret ! = Rect2 ( ) & & caret . t_caret ! = Rect2 ( ) & & caret . l_dir ! = caret . t_dir ) {
// Draw extra direction marker on top of split caret.
float d = ( caret . l_dir = = TextServer : : DIRECTION_LTR ) ? 0.5 : - 3 ;
Rect2 trect = Rect2 ( caret . l_caret . position . x + d * caret_width , caret . l_caret . position . y + caret . l_caret . size . y - caret_width , 3 * caret_width , caret_width ) ;
trect . position + = ofs ;
RenderingServer : : get_singleton ( ) - > canvas_item_add_rect ( ci , trect , caret_color ) ;
d = ( caret . t_dir = = TextServer : : DIRECTION_LTR ) ? 0.5 : - 3 ;
trect = Rect2 ( caret . t_caret . position . x + d * caret_width , caret . t_caret . position . y , 3 * caret_width , caret_width ) ;
2020-09-09 16:00:32 +03:00
trect . position + = ofs ;
2021-03-28 19:31:25 +01:00
RenderingServer : : get_singleton ( ) - > canvas_item_add_rect ( ci , trect , caret_color ) ;
2020-05-14 16:41:43 +02:00
}
2017-08-07 14:09:56 +03:00
2021-08-28 00:19:51 +03:00
caret . l_caret . position + = ofs ;
caret . l_caret . size . x = caret_width ;
RenderingServer : : get_singleton ( ) - > canvas_item_add_rect ( ci , caret . l_caret , caret_color ) ;
2017-08-07 14:09:56 +03:00
2021-08-28 00:19:51 +03:00
caret . t_caret . position + = ofs ;
caret . t_caret . size . x = caret_width ;
2017-08-07 14:09:56 +03:00
2021-08-28 00:19:51 +03:00
RenderingServer : : get_singleton ( ) - > canvas_item_add_rect ( ci , caret . t_caret , caret_color ) ;
2017-08-07 14:09:56 +03:00
}
2022-12-11 01:21:22 +02:00
}
if ( ! ime_text . is_empty ( ) ) {
2020-09-09 16:00:32 +03:00
{
2021-03-12 19:05:16 +05:30
// IME intermediate text range.
2021-03-28 19:31:25 +01:00
Vector < Vector2 > sel = TS - > shaped_text_get_selection ( text_rid , caret_column , caret_column + ime_text . length ( ) ) ;
2020-09-09 16:00:32 +03:00
for ( int i = 0 ; i < sel . size ( ) ; i + + ) {
Rect2 rect = Rect2 ( sel [ i ] . x + ofs . x , ofs . y , sel [ i ] . y - sel [ i ] . x , text_height ) ;
if ( rect . position . x + rect . size . x < = x_ofs | | rect . position . x > ofs_max ) {
continue ;
}
if ( rect . position . x < x_ofs ) {
rect . size . x - = ( x_ofs - rect . position . x ) ;
rect . position . x = x_ofs ;
} else if ( rect . position . x + rect . size . x > ofs_max ) {
rect . size . x = ofs_max - rect . position . x ;
}
rect . size . y = caret_width ;
2021-03-28 19:31:25 +01:00
RenderingServer : : get_singleton ( ) - > canvas_item_add_rect ( ci , rect , caret_color ) ;
2020-09-09 16:00:32 +03:00
}
}
{
// IME caret.
2022-12-11 01:21:22 +02:00
if ( ime_selection . y > 0 ) {
Vector < Vector2 > sel = TS - > shaped_text_get_selection ( text_rid , caret_column + ime_selection . x , caret_column + ime_selection . x + ime_selection . y ) ;
for ( int i = 0 ; i < sel . size ( ) ; i + + ) {
Rect2 rect = Rect2 ( sel [ i ] . x + ofs . x , ofs . y , sel [ i ] . y - sel [ i ] . x , text_height ) ;
if ( rect . position . x + rect . size . x < = x_ofs | | rect . position . x > ofs_max ) {
continue ;
}
if ( rect . position . x < x_ofs ) {
rect . size . x - = ( x_ofs - rect . position . x ) ;
rect . position . x = x_ofs ;
} else if ( rect . position . x + rect . size . x > ofs_max ) {
rect . size . x = ofs_max - rect . position . x ;
}
rect . size . y = caret_width * 3 ;
RenderingServer : : get_singleton ( ) - > canvas_item_add_rect ( ci , rect , caret_color ) ;
2020-09-09 16:00:32 +03:00
}
2019-12-01 14:27:39 +00:00
}
}
2017-08-07 14:09:56 +03:00
}
2016-06-21 00:05:52 +01:00
}
2017-06-25 23:50:45 +08:00
2024-09-10 13:43:31 +00:00
if ( editing ) {
2024-09-05 10:52:29 +03:00
_update_ime_window_position ( ) ;
2017-06-25 23:50:45 +08:00
}
2014-02-09 22:10:30 -03:00
} break ;
2022-02-15 18:06:48 +01:00
2014-02-09 22:10:30 -03:00
case NOTIFICATION_FOCUS_ENTER : {
2024-09-10 13:43:31 +00:00
// Only allow editing if the LineEdit is not focused with arrow keys.
if ( ! ( Input : : get_singleton ( ) - > is_action_pressed ( " ui_up " ) | | Input : : get_singleton ( ) - > is_action_pressed ( " ui_down " ) | | Input : : get_singleton ( ) - > is_action_pressed ( " ui_left " ) | | Input : : get_singleton ( ) - > is_action_pressed ( " ui_right " ) ) ) {
2025-05-05 20:21:43 -04:00
_edit ( virtual_keyboard_show_on_focus ) ;
2024-10-04 10:37:33 +00:00
emit_signal ( SNAME ( " editing_toggled " ) , true ) ;
2020-03-07 18:02:54 +02:00
}
2014-02-09 22:10:30 -03:00
} break ;
2022-02-15 18:06:48 +01:00
2014-02-09 22:10:30 -03:00
case NOTIFICATION_FOCUS_EXIT : {
2024-09-10 13:43:31 +00:00
if ( editing ) {
2024-10-04 10:37:33 +00:00
unedit ( ) ;
emit_signal ( SNAME ( " editing_toggled " ) , false ) ;
2021-10-21 23:02:46 +02:00
}
2014-02-09 22:10:30 -03:00
} break ;
2022-02-15 18:06:48 +01:00
2018-11-23 14:07:48 +02:00
case MainLoop : : NOTIFICATION_OS_IME_UPDATE : {
2024-09-10 13:43:31 +00:00
if ( editing ) {
2025-02-20 08:23:22 +02:00
const String & new_ime_text = DisplayServer : : get_singleton ( ) - > ime_get_text ( ) ;
const Vector2i & new_ime_selection = DisplayServer : : get_singleton ( ) - > ime_get_selection ( ) ;
if ( ime_text = = new_ime_text & & ime_selection = = new_ime_selection ) {
break ;
}
2025-10-20 20:25:59 -04:00
if ( ! window_has_focus & & ! new_ime_text . is_empty ( ) ) {
break ;
}
2025-02-20 08:23:22 +02:00
ime_text = new_ime_text ;
ime_selection = new_ime_selection ;
2022-12-11 01:21:22 +02:00
if ( ! ime_text . is_empty ( ) ) {
selection_delete ( ) ;
}
2020-09-09 16:00:32 +03:00
_shape ( ) ;
2023-03-08 23:00:27 +01:00
set_caret_column ( caret_column ) ; // Update scroll_offset.
2019-01-08 22:52:56 +02:00
}
2018-11-23 14:07:48 +02:00
} break ;
2022-02-15 18:06:48 +01:00
case NOTIFICATION_DRAG_BEGIN : {
2021-10-28 09:07:18 +02:00
drag_action = true ;
} break ;
2022-02-15 18:06:48 +01:00
case NOTIFICATION_DRAG_END : {
2021-10-28 09:07:18 +02:00
if ( is_drag_successful ( ) ) {
if ( selection . drag_attempt ) {
selection . drag_attempt = false ;
2023-06-08 23:24:00 +02:00
if ( is_editable ( ) & & ! Input : : get_singleton ( ) - > is_key_pressed ( Key : : CMD_OR_CTRL ) ) {
2021-10-28 09:07:18 +02:00
selection_delete ( ) ;
} else if ( deselect_on_focus_loss_enabled ) {
deselect ( ) ;
}
}
} else {
selection . drag_attempt = false ;
}
drag_action = false ;
drag_caret_force_displayed = false ;
2025-06-02 17:37:23 +02:00
queue_redraw ( ) ;
} break ;
case NOTIFICATION_MOUSE_EXIT : {
if ( drag_caret_force_displayed ) {
drag_caret_force_displayed = false ;
queue_redraw ( ) ;
}
2021-10-28 09:07:18 +02:00
} break ;
2014-02-09 22:10:30 -03:00
}
}
void LineEdit : : copy_text ( ) {
2018-08-24 04:35:46 -05:00
if ( selection . enabled & & ! pass ) {
2023-03-30 17:07:28 +02:00
DisplayServer : : get_singleton ( ) - > clipboard_set ( get_selected_text ( ) ) ;
2014-02-09 22:10:30 -03:00
}
}
void LineEdit : : cut_text ( ) {
2020-12-07 21:32:00 +10:00
if ( editable & & selection . enabled & & ! pass ) {
2023-03-30 17:07:28 +02:00
DisplayServer : : get_singleton ( ) - > clipboard_set ( get_selected_text ( ) ) ;
2014-02-09 22:10:30 -03:00
selection_delete ( ) ;
}
}
void LineEdit : : paste_text ( ) {
2020-12-07 21:32:00 +10:00
if ( ! editable ) {
return ;
}
2019-05-31 15:27:53 +02:00
// Strip escape characters like \n and \t as they can't be displayed on LineEdit.
2020-03-03 10:36:29 -03:00
String paste_buffer = DisplayServer : : get_singleton ( ) - > clipboard_get ( ) . strip_escapes ( ) ;
2016-03-09 00:00:52 +01:00
2021-12-09 03:42:46 -06:00
if ( ! paste_buffer . is_empty ( ) ) {
2020-01-10 21:07:00 +01:00
int prev_len = text . length ( ) ;
2020-05-14 16:41:43 +02:00
if ( selection . enabled ) {
2014-02-09 22:10:30 -03:00
selection_delete ( ) ;
2020-05-14 16:41:43 +02:00
}
2021-03-28 19:31:25 +01:00
insert_text_at_caret ( paste_buffer ) ;
2014-02-09 22:10:30 -03:00
2018-02-05 16:22:34 +01:00
if ( ! text_changed_dirty ) {
2020-01-10 21:07:00 +01:00
if ( is_inside_tree ( ) & & text . length ( ) ! = prev_len ) {
2023-12-18 15:46:56 +01:00
callable_mp ( this , & LineEdit : : _text_changed ) . call_deferred ( ) ;
2018-02-05 16:22:34 +01:00
}
text_changed_dirty = true ;
}
2014-02-09 22:10:30 -03:00
}
2016-05-16 20:25:17 -03:00
}
2021-08-17 11:41:46 +08:00
bool LineEdit : : has_undo ( ) const {
if ( undo_stack_pos = = nullptr ) {
return undo_stack . size ( ) > 1 ;
}
return undo_stack_pos ! = undo_stack . front ( ) ;
}
bool LineEdit : : has_redo ( ) const {
return undo_stack_pos ! = nullptr & & undo_stack_pos ! = undo_stack . back ( ) ;
}
2016-05-16 20:25:17 -03:00
void LineEdit : : undo ( ) {
2020-12-07 21:32:00 +10:00
if ( ! editable ) {
return ;
}
2023-12-12 17:51:53 +00:00
if ( ! has_undo ( ) ) {
return ;
}
2020-04-02 01:20:12 +02:00
if ( undo_stack_pos = = nullptr ) {
2017-10-29 23:14:33 +00:00
undo_stack_pos = undo_stack . back ( ) ;
2016-05-16 20:25:17 -03:00
}
2021-10-28 09:07:18 +02:00
deselect ( ) ;
2017-10-29 23:14:33 +00:00
undo_stack_pos = undo_stack_pos - > prev ( ) ;
TextOperation op = undo_stack_pos - > get ( ) ;
text = op . text ;
2020-11-11 09:26:55 +01:00
scroll_offset = op . scroll_offset ;
2019-04-21 10:51:10 +02:00
2020-09-09 16:00:32 +03:00
_shape ( ) ;
2024-01-09 17:14:55 +00:00
set_caret_column ( op . caret_column ) ;
2017-10-29 23:14:33 +00:00
_emit_text_change ( ) ;
}
2016-05-16 20:25:17 -03:00
2017-10-29 23:14:33 +00:00
void LineEdit : : redo ( ) {
2020-12-07 21:32:00 +10:00
if ( ! editable ) {
return ;
}
2023-12-12 17:51:53 +00:00
if ( ! has_redo ( ) ) {
2017-10-29 23:14:33 +00:00
return ;
}
2021-10-28 09:07:18 +02:00
deselect ( ) ;
2017-10-29 23:14:33 +00:00
undo_stack_pos = undo_stack_pos - > next ( ) ;
TextOperation op = undo_stack_pos - > get ( ) ;
text = op . text ;
2020-11-11 09:26:55 +01:00
scroll_offset = op . scroll_offset ;
2019-04-21 10:51:10 +02:00
2020-09-09 16:00:32 +03:00
_shape ( ) ;
2024-01-09 17:14:55 +00:00
set_caret_column ( op . caret_column ) ;
2017-10-29 23:14:33 +00:00
_emit_text_change ( ) ;
2014-02-09 22:10:30 -03:00
}
void LineEdit : : shift_selection_check_pre ( bool p_shift ) {
2016-06-18 16:14:43 +02:00
if ( ! selection . enabled & & p_shift ) {
2021-03-28 19:31:25 +01:00
selection . start_column = caret_column ;
2014-02-09 22:10:30 -03:00
}
2020-05-14 16:41:43 +02:00
if ( ! p_shift ) {
2017-12-17 15:40:44 -02:00
deselect ( ) ;
2020-05-14 16:41:43 +02:00
}
2014-02-09 22:10:30 -03:00
}
void LineEdit : : shift_selection_check_post ( bool p_shift ) {
2020-05-14 16:41:43 +02:00
if ( p_shift ) {
2021-03-28 19:31:25 +01:00
selection_fill_at_caret ( ) ;
2020-05-14 16:41:43 +02:00
}
2014-02-09 22:10:30 -03:00
}
2021-03-28 19:31:25 +01:00
void LineEdit : : set_caret_at_pixel_pos ( int p_x ) {
2022-08-31 15:02:40 +03:00
Ref < StyleBox > style = theme_cache . normal ;
2020-09-09 16:00:32 +03:00
bool rtl = is_layout_rtl ( ) ;
2015-08-15 07:47:22 +01:00
2020-09-09 16:00:32 +03:00
int x_ofs = 0 ;
float text_width = TS - > shaped_text_get_size ( text_rid ) . x ;
2021-11-24 20:58:47 -06:00
switch ( alignment ) {
case HORIZONTAL_ALIGNMENT_FILL :
case HORIZONTAL_ALIGNMENT_LEFT : {
2020-09-09 16:00:32 +03:00
if ( rtl ) {
2020-12-22 16:24:29 +00:00
x_ofs = MAX ( style - > get_margin ( SIDE_LEFT ) , int ( get_size ( ) . width - style - > get_margin ( SIDE_RIGHT ) - ( text_width ) ) ) ;
2020-09-09 16:00:32 +03:00
} else {
2025-08-05 19:29:22 +02:00
x_ofs = style - > get_margin ( SIDE_LEFT ) ;
2020-09-09 16:00:32 +03:00
}
2015-08-15 07:47:22 +01:00
} break ;
2021-11-24 20:58:47 -06:00
case HORIZONTAL_ALIGNMENT_CENTER : {
2022-07-06 11:57:06 +03:00
if ( ! Math : : is_zero_approx ( scroll_offset ) ) {
2025-08-05 19:29:22 +02:00
x_ofs = style - > get_margin ( SIDE_LEFT ) ;
2020-05-14 16:41:43 +02:00
} else {
2025-08-04 23:45:31 +02:00
int total_margin = style - > get_margin ( SIDE_LEFT ) + style - > get_margin ( SIDE_RIGHT ) ;
int centered = int ( ( get_size ( ) . width - total_margin - text_width ) ) / 2 ;
x_ofs = style - > get_margin ( SIDE_LEFT ) + MAX ( 0 , centered ) ;
2020-05-14 16:41:43 +02:00
}
2015-08-15 07:47:22 +01:00
} break ;
2021-11-24 20:58:47 -06:00
case HORIZONTAL_ALIGNMENT_RIGHT : {
2020-09-09 16:00:32 +03:00
if ( rtl ) {
2025-08-05 19:29:22 +02:00
x_ofs = style - > get_margin ( SIDE_LEFT ) ;
2020-09-09 16:00:32 +03:00
} else {
2020-12-22 16:24:29 +00:00
x_ofs = MAX ( style - > get_margin ( SIDE_LEFT ) , int ( get_size ( ) . width - style - > get_margin ( SIDE_RIGHT ) - ( text_width ) ) ) ;
2020-05-14 16:41:43 +02:00
}
2015-08-15 07:47:22 +01:00
} break ;
}
2020-12-15 12:04:21 +00:00
bool using_placeholder = text . is_empty ( ) & & ime_text . is_empty ( ) ;
2020-09-09 16:00:32 +03:00
bool display_clear_icon = ! using_placeholder & & is_editable ( ) & & clear_button_enabled ;
if ( right_icon . is_valid ( ) | | display_clear_icon ) {
2022-08-31 15:02:40 +03:00
Ref < Texture2D > r_icon = display_clear_icon ? theme_cache . clear_icon : right_icon ;
2024-11-22 21:27:36 +07:00
Point2 right_icon_size = _get_right_icon_size ( r_icon ) ;
2021-11-24 20:58:47 -06:00
if ( alignment = = HORIZONTAL_ALIGNMENT_CENTER ) {
2022-07-06 11:57:06 +03:00
if ( Math : : is_zero_approx ( scroll_offset ) ) {
2025-08-04 23:45:31 +02:00
int total_margin = style - > get_margin ( SIDE_LEFT ) + style - > get_margin ( SIDE_RIGHT ) ;
2024-11-22 21:27:36 +07:00
int center = int ( get_size ( ) . width - total_margin - text_width - right_icon_size . width ) / 2 ;
2025-08-04 23:45:31 +02:00
x_ofs = style - > get_margin ( SIDE_LEFT ) + MAX ( 0 , center ) ;
2020-09-09 16:00:32 +03:00
}
2025-08-05 19:29:22 +02:00
if ( rtl ) {
2024-11-22 21:27:36 +07:00
x_ofs + = right_icon_size . width ;
2025-08-05 19:29:22 +02:00
}
2020-09-09 16:00:32 +03:00
} else {
2025-08-05 19:29:22 +02:00
if ( rtl ) {
2024-11-22 21:27:36 +07:00
x_ofs = MAX ( style - > get_margin ( SIDE_LEFT ) + right_icon_size . width , x_ofs ) ;
2025-08-05 19:29:22 +02:00
} else {
2024-11-22 21:27:36 +07:00
x_ofs = MAX ( style - > get_margin ( SIDE_LEFT ) , x_ofs - right_icon_size . width - style - > get_margin ( SIDE_RIGHT ) ) ;
2025-08-05 19:29:22 +02:00
}
2014-02-09 22:10:30 -03:00
}
}
2016-03-09 00:00:52 +01:00
2025-03-19 14:18:09 -05:00
int ofs = std : : ceil ( TS - > shaped_text_hit_test_position ( text_rid , p_x - x_ofs - scroll_offset ) ) ;
2025-08-07 22:40:30 +03:00
if ( ofs = = - 1 ) {
return ;
}
2023-08-15 11:42:40 +03:00
if ( ! caret_mid_grapheme_enabled ) {
ofs = TS - > shaped_text_closest_character_pos ( text_rid , ofs ) ;
}
2021-03-28 19:31:25 +01:00
set_caret_column ( ofs ) ;
2014-02-09 22:10:30 -03:00
}
2022-07-06 11:57:06 +03:00
Vector2 LineEdit : : get_caret_pixel_pos ( ) {
2022-08-31 15:02:40 +03:00
Ref < StyleBox > style = theme_cache . normal ;
2020-09-09 16:00:32 +03:00
bool rtl = is_layout_rtl ( ) ;
2019-06-22 20:22:52 +02:00
2020-09-09 16:00:32 +03:00
int x_ofs = 0 ;
float text_width = TS - > shaped_text_get_size ( text_rid ) . x ;
2021-11-24 20:58:47 -06:00
switch ( alignment ) {
case HORIZONTAL_ALIGNMENT_FILL :
case HORIZONTAL_ALIGNMENT_LEFT : {
2020-09-09 16:00:32 +03:00
if ( rtl ) {
2020-12-22 16:24:29 +00:00
x_ofs = MAX ( style - > get_margin ( SIDE_LEFT ) , int ( get_size ( ) . width - style - > get_margin ( SIDE_RIGHT ) - ( text_width ) ) ) ;
2020-09-09 16:00:32 +03:00
} else {
2025-08-05 19:29:22 +02:00
x_ofs = style - > get_margin ( SIDE_LEFT ) ;
2020-09-09 16:00:32 +03:00
}
2019-06-22 20:22:52 +02:00
} break ;
2021-11-24 20:58:47 -06:00
case HORIZONTAL_ALIGNMENT_CENTER : {
2022-07-06 11:57:06 +03:00
if ( ! Math : : is_zero_approx ( scroll_offset ) ) {
2025-08-05 19:29:22 +02:00
x_ofs = style - > get_margin ( SIDE_LEFT ) ;
2020-05-14 16:41:43 +02:00
} else {
2025-08-04 23:45:31 +02:00
int total_margin = style - > get_margin ( SIDE_LEFT ) + style - > get_margin ( SIDE_RIGHT ) ;
int centered = int ( ( get_size ( ) . width - total_margin - text_width ) ) / 2 ;
x_ofs = style - > get_margin ( SIDE_LEFT ) + MAX ( 0 , centered ) ;
2020-05-14 16:41:43 +02:00
}
2019-06-22 20:22:52 +02:00
} break ;
2021-11-24 20:58:47 -06:00
case HORIZONTAL_ALIGNMENT_RIGHT : {
2020-09-09 16:00:32 +03:00
if ( rtl ) {
2025-08-05 19:29:22 +02:00
x_ofs = style - > get_margin ( SIDE_LEFT ) ;
2020-09-09 16:00:32 +03:00
} else {
2020-12-22 16:24:29 +00:00
x_ofs = MAX ( style - > get_margin ( SIDE_LEFT ) , int ( get_size ( ) . width - style - > get_margin ( SIDE_RIGHT ) - ( text_width ) ) ) ;
2020-05-14 16:41:43 +02:00
}
2019-06-22 20:22:52 +02:00
} break ;
}
2020-12-15 12:04:21 +00:00
bool using_placeholder = text . is_empty ( ) & & ime_text . is_empty ( ) ;
2020-09-09 16:00:32 +03:00
bool display_clear_icon = ! using_placeholder & & is_editable ( ) & & clear_button_enabled ;
if ( right_icon . is_valid ( ) | | display_clear_icon ) {
2022-08-31 15:02:40 +03:00
Ref < Texture2D > r_icon = display_clear_icon ? theme_cache . clear_icon : right_icon ;
2024-11-22 21:27:36 +07:00
Point2 right_icon_size = _get_right_icon_size ( r_icon ) ;
2021-11-24 20:58:47 -06:00
if ( alignment = = HORIZONTAL_ALIGNMENT_CENTER ) {
2022-07-06 11:57:06 +03:00
if ( Math : : is_zero_approx ( scroll_offset ) ) {
2025-08-04 23:45:31 +02:00
int total_margin = style - > get_margin ( SIDE_LEFT ) + style - > get_margin ( SIDE_RIGHT ) ;
2024-11-22 21:27:36 +07:00
int center = int ( get_size ( ) . width - total_margin - text_width - right_icon_size . width ) / 2 ;
2025-08-04 23:45:31 +02:00
x_ofs = style - > get_margin ( SIDE_LEFT ) + MAX ( 0 , center ) ;
2020-09-09 16:00:32 +03:00
}
2025-08-05 19:29:22 +02:00
if ( rtl ) {
2024-11-22 21:27:36 +07:00
x_ofs + = right_icon_size . width ;
2025-08-05 19:29:22 +02:00
}
2020-09-09 16:00:32 +03:00
} else {
2025-08-05 19:29:22 +02:00
if ( rtl ) {
2024-11-22 21:27:36 +07:00
x_ofs = MAX ( style - > get_margin ( SIDE_LEFT ) + right_icon_size . width , x_ofs ) ;
2025-08-05 19:29:22 +02:00
} else {
2024-11-22 21:27:36 +07:00
x_ofs = MAX ( style - > get_margin ( SIDE_LEFT ) , x_ofs - right_icon_size . width - style - > get_margin ( SIDE_RIGHT ) ) ;
2025-08-05 19:29:22 +02:00
}
2020-09-09 16:00:32 +03:00
}
}
2022-07-06 11:57:06 +03:00
Vector2 ret ;
2021-08-28 00:19:51 +03:00
CaretInfo caret ;
2020-09-09 16:00:32 +03:00
// Get position of the start of caret.
2024-09-10 13:43:31 +00:00
if ( ! ime_text . is_empty ( ) & & ime_selection . x ! = 0 ) {
2021-08-28 00:19:51 +03:00
caret = TS - > shaped_text_get_carets ( text_rid , caret_column + ime_selection . x ) ;
2020-09-09 16:00:32 +03:00
} else {
2021-08-28 00:19:51 +03:00
caret = TS - > shaped_text_get_carets ( text_rid , caret_column ) ;
2020-09-09 16:00:32 +03:00
}
2021-08-28 00:19:51 +03:00
if ( ( caret . l_caret ! = Rect2 ( ) & & ( caret . l_dir = = TextServer : : DIRECTION_AUTO | | caret . l_dir = = ( TextServer : : Direction ) input_direction ) ) | | ( caret . t_caret = = Rect2 ( ) ) ) {
ret . x = x_ofs + caret . l_caret . position . x + scroll_offset ;
2020-09-09 16:00:32 +03:00
} else {
2021-08-28 00:19:51 +03:00
ret . x = x_ofs + caret . t_caret . position . x + scroll_offset ;
2020-09-09 16:00:32 +03:00
}
// Get position of the end of caret.
2024-09-10 13:43:31 +00:00
if ( ! ime_text . is_empty ( ) ) {
2020-09-09 16:00:32 +03:00
if ( ime_selection . y ! = 0 ) {
2021-08-28 00:19:51 +03:00
caret = TS - > shaped_text_get_carets ( text_rid , caret_column + ime_selection . x + ime_selection . y ) ;
2020-09-09 16:00:32 +03:00
} else {
2021-08-28 00:19:51 +03:00
caret = TS - > shaped_text_get_carets ( text_rid , caret_column + ime_text . size ( ) ) ;
2020-09-09 16:00:32 +03:00
}
2021-08-28 00:19:51 +03:00
if ( ( caret . l_caret ! = Rect2 ( ) & & ( caret . l_dir = = TextServer : : DIRECTION_AUTO | | caret . l_dir = = ( TextServer : : Direction ) input_direction ) ) | | ( caret . t_caret = = Rect2 ( ) ) ) {
ret . y = x_ofs + caret . l_caret . position . x + scroll_offset ;
2020-09-09 16:00:32 +03:00
} else {
2021-08-28 00:19:51 +03:00
ret . y = x_ofs + caret . t_caret . position . x + scroll_offset ;
2019-06-22 20:22:52 +02:00
}
2020-09-09 16:00:32 +03:00
} else {
ret . y = ret . x ;
2019-06-22 20:22:52 +02:00
}
2020-09-09 16:00:32 +03:00
return ret ;
}
2021-03-28 19:31:25 +01:00
void LineEdit : : set_caret_mid_grapheme_enabled ( const bool p_enabled ) {
caret_mid_grapheme_enabled = p_enabled ;
2020-09-09 16:00:32 +03:00
}
2021-03-28 19:31:25 +01:00
bool LineEdit : : is_caret_mid_grapheme_enabled ( ) const {
return caret_mid_grapheme_enabled ;
2019-06-22 20:22:52 +02:00
}
2021-03-28 19:31:25 +01:00
bool LineEdit : : is_caret_blink_enabled ( ) const {
2016-06-21 00:05:52 +01:00
return caret_blink_enabled ;
}
2021-03-28 19:31:25 +01:00
void LineEdit : : set_caret_blink_enabled ( const bool p_enabled ) {
2022-10-09 16:51:01 +08:00
if ( caret_blink_enabled = = p_enabled ) {
return ;
}
2016-06-21 00:05:52 +01:00
caret_blink_enabled = p_enabled ;
2022-07-04 23:17:34 +02:00
set_process_internal ( p_enabled ) ;
2019-09-04 13:06:15 +02:00
2022-10-09 16:51:01 +08:00
draw_caret = ! caret_blink_enabled ;
if ( caret_blink_enabled ) {
caret_blink_timer = 0.0 ;
2016-06-21 00:05:52 +01:00
}
2022-10-09 16:51:01 +08:00
queue_redraw ( ) ;
2021-03-03 20:51:35 -03:00
notify_property_list_changed ( ) ;
2016-06-21 00:05:52 +01:00
}
2021-03-28 19:31:25 +01:00
bool LineEdit : : is_caret_force_displayed ( ) const {
2020-06-21 19:15:57 +02:00
return caret_force_displayed ;
}
2021-03-28 19:31:25 +01:00
void LineEdit : : set_caret_force_displayed ( const bool p_enabled ) {
2022-10-09 16:51:01 +08:00
if ( caret_force_displayed = = p_enabled ) {
return ;
}
2020-06-21 19:15:57 +02:00
caret_force_displayed = p_enabled ;
2022-10-09 16:51:01 +08:00
_validate_caret_can_draw ( ) ;
2022-08-13 23:21:24 +02:00
queue_redraw ( ) ;
2020-06-21 19:15:57 +02:00
}
2022-08-13 14:52:35 +02:00
float LineEdit : : get_caret_blink_interval ( ) const {
return caret_blink_interval ;
2016-06-21 00:05:52 +01:00
}
2022-08-13 14:52:35 +02:00
void LineEdit : : set_caret_blink_interval ( const float p_interval ) {
ERR_FAIL_COND ( p_interval < = 0 ) ;
caret_blink_interval = p_interval ;
2016-06-21 00:05:52 +01:00
}
void LineEdit : : _reset_caret_blink_timer ( ) {
if ( caret_blink_enabled ) {
draw_caret = true ;
2022-10-09 16:51:01 +08:00
if ( caret_can_draw ) {
2022-07-04 23:17:34 +02:00
caret_blink_timer = 0.0 ;
2022-08-13 23:21:24 +02:00
queue_redraw ( ) ;
2019-09-04 13:06:15 +02:00
}
2016-06-21 00:05:52 +01:00
}
}
void LineEdit : : _toggle_draw_caret ( ) {
draw_caret = ! draw_caret ;
2022-10-09 16:51:01 +08:00
if ( is_visible_in_tree ( ) & & caret_can_draw ) {
2022-08-13 23:21:24 +02:00
queue_redraw ( ) ;
2016-06-21 00:05:52 +01:00
}
}
2022-10-09 16:51:01 +08:00
void LineEdit : : _validate_caret_can_draw ( ) {
if ( caret_blink_enabled ) {
draw_caret = true ;
caret_blink_timer = 0.0 ;
}
2025-03-03 15:58:58 +01:00
caret_can_draw = ( caret_force_displayed & & ! is_part_of_edited_scene ( ) ) | | ( editing & & ( window_has_focus | | ( menu & & menu - > has_focus ( ) ) ) & & has_focus ( ) ) ;
2022-10-09 16:51:01 +08:00
}
2014-02-09 22:10:30 -03:00
void LineEdit : : delete_char ( ) {
2024-09-10 13:43:31 +00:00
if ( text . is_empty ( ) | | caret_column = = 0 ) {
2014-02-09 22:10:30 -03:00
return ;
2020-05-14 16:41:43 +02:00
}
2025-04-22 10:02:07 -05:00
int delete_char_offset = 1 ;
if ( ! caret_mid_grapheme_enabled & & backspace_deletes_composite_character_enabled ) {
delete_char_offset = caret_column - get_previous_composite_character_column ( caret_column ) ;
}
text = text . left ( caret_column - delete_char_offset ) + text . substr ( caret_column ) ;
2020-09-09 16:00:32 +03:00
_shape ( ) ;
2016-03-09 00:00:52 +01:00
2025-04-22 10:02:07 -05:00
set_caret_column ( get_caret_column ( ) - delete_char_offset ) ;
2016-03-09 00:00:52 +01:00
2016-09-06 20:34:24 -03:00
_text_changed ( ) ;
2014-02-09 22:10:30 -03:00
}
2016-06-18 16:15:26 +02:00
void LineEdit : : delete_text ( int p_from_column , int p_to_column ) {
2020-06-06 17:39:53 +02:00
ERR_FAIL_COND_MSG ( p_from_column < 0 | | p_from_column > p_to_column | | p_to_column > text . length ( ) ,
vformat ( " Positional parameters (from: %d, to: %d) are inverted or outside the text length (%d). " , p_from_column , p_to_column , text . length ( ) ) ) ;
2016-06-18 16:15:26 +02:00
2021-11-11 09:08:08 +01:00
text = text . left ( p_from_column ) + text . substr ( p_to_column ) ;
2020-09-09 16:00:32 +03:00
_shape ( ) ;
2023-09-08 08:58:51 +03:00
set_caret_column ( caret_column - CLAMP ( caret_column - p_from_column , 0 , p_to_column - p_from_column ) ) ;
2019-12-01 13:54:09 +00:00
2018-02-05 16:22:34 +01:00
if ( ! text_changed_dirty ) {
if ( is_inside_tree ( ) ) {
2023-12-18 15:46:56 +01:00
callable_mp ( this , & LineEdit : : _text_changed ) . call_deferred ( ) ;
2018-02-05 16:22:34 +01:00
}
text_changed_dirty = true ;
}
2016-06-18 16:15:26 +02:00
}
2014-02-09 22:10:30 -03:00
void LineEdit : : set_text ( String p_text ) {
clear_internal ( ) ;
2021-03-28 19:31:25 +01:00
insert_text_at_caret ( p_text ) ;
2021-04-08 23:43:50 +08:00
_create_undo_state ( ) ;
2020-01-15 09:42:06 +08:00
2022-08-13 23:21:24 +02:00
queue_redraw ( ) ;
2021-03-28 19:31:25 +01:00
caret_column = 0 ;
2022-07-06 11:57:06 +03:00
scroll_offset = 0.0 ;
2014-02-09 22:10:30 -03:00
}
2023-06-10 21:29:24 +02:00
void LineEdit : : set_text_with_selection ( const String & p_text ) {
Selection selection_copy = selection ;
clear_internal ( ) ;
insert_text_at_caret ( p_text ) ;
_create_undo_state ( ) ;
int tlen = text . length ( ) ;
selection = selection_copy ;
selection . begin = MIN ( selection . begin , tlen ) ;
selection . end = MIN ( selection . end , tlen ) ;
selection . start_column = MIN ( selection . start_column , tlen ) ;
queue_redraw ( ) ;
}
2020-09-09 16:00:32 +03:00
void LineEdit : : set_text_direction ( Control : : TextDirection p_text_direction ) {
ERR_FAIL_COND ( ( int ) p_text_direction < - 1 | | ( int ) p_text_direction > 3 ) ;
if ( text_direction ! = p_text_direction ) {
text_direction = p_text_direction ;
if ( text_direction ! = TEXT_DIRECTION_AUTO & & text_direction ! = TEXT_DIRECTION_INHERITED ) {
input_direction = text_direction ;
}
_shape ( ) ;
2021-07-16 18:36:05 -03:00
if ( menu_dir ) {
menu_dir - > set_item_checked ( menu_dir - > get_item_index ( MENU_DIR_INHERITED ) , text_direction = = TEXT_DIRECTION_INHERITED ) ;
menu_dir - > set_item_checked ( menu_dir - > get_item_index ( MENU_DIR_AUTO ) , text_direction = = TEXT_DIRECTION_AUTO ) ;
menu_dir - > set_item_checked ( menu_dir - > get_item_index ( MENU_DIR_LTR ) , text_direction = = TEXT_DIRECTION_LTR ) ;
menu_dir - > set_item_checked ( menu_dir - > get_item_index ( MENU_DIR_RTL ) , text_direction = = TEXT_DIRECTION_RTL ) ;
}
2022-08-13 23:21:24 +02:00
queue_redraw ( ) ;
2020-09-09 16:00:32 +03:00
}
}
Control : : TextDirection LineEdit : : get_text_direction ( ) const {
return text_direction ;
}
void LineEdit : : set_language ( const String & p_language ) {
if ( language ! = p_language ) {
language = p_language ;
_shape ( ) ;
2022-08-13 23:21:24 +02:00
queue_redraw ( ) ;
2020-09-09 16:00:32 +03:00
}
}
String LineEdit : : get_language ( ) const {
return language ;
}
void LineEdit : : set_draw_control_chars ( bool p_draw_control_chars ) {
if ( draw_control_chars ! = p_draw_control_chars ) {
draw_control_chars = p_draw_control_chars ;
2021-07-16 18:36:05 -03:00
if ( menu & & menu - > get_item_index ( MENU_DISPLAY_UCC ) > = 0 ) {
menu - > set_item_checked ( menu - > get_item_index ( MENU_DISPLAY_UCC ) , draw_control_chars ) ;
}
2020-09-09 16:00:32 +03:00
_shape ( ) ;
2022-08-13 23:21:24 +02:00
queue_redraw ( ) ;
2020-09-09 16:00:32 +03:00
}
}
bool LineEdit : : get_draw_control_chars ( ) const {
return draw_control_chars ;
}
2022-04-19 13:27:18 +03:00
void LineEdit : : set_structured_text_bidi_override ( TextServer : : StructuredTextParser p_parser ) {
2020-09-09 16:00:32 +03:00
if ( st_parser ! = p_parser ) {
st_parser = p_parser ;
_shape ( ) ;
2022-08-13 23:21:24 +02:00
queue_redraw ( ) ;
2020-09-09 16:00:32 +03:00
}
}
2022-04-19 13:27:18 +03:00
TextServer : : StructuredTextParser LineEdit : : get_structured_text_bidi_override ( ) const {
2020-09-09 16:00:32 +03:00
return st_parser ;
}
2025-09-26 09:21:14 -07:00
void LineEdit : : set_structured_text_bidi_override_options ( const Array & p_args ) {
st_args = Array ( p_args ) ;
2020-09-09 16:00:32 +03:00
_shape ( ) ;
2022-08-13 23:21:24 +02:00
queue_redraw ( ) ;
2020-09-09 16:00:32 +03:00
}
Array LineEdit : : get_structured_text_bidi_override_options ( ) const {
2025-09-26 09:21:14 -07:00
return Array ( st_args ) ;
2020-09-09 16:00:32 +03:00
}
2014-02-09 22:10:30 -03:00
void LineEdit : : clear ( ) {
2024-12-11 14:16:36 +01:00
bool was_empty = text . is_empty ( ) ;
2014-02-09 22:10:30 -03:00
clear_internal ( ) ;
2024-12-11 14:16:36 +01:00
_clear_redo ( ) ;
if ( ! was_empty ) {
_emit_text_change ( ) ;
}
2021-01-18 20:08:42 +03:00
// This should reset virtual keyboard state if needed.
2024-09-10 13:43:31 +00:00
if ( editing ) {
2021-01-18 20:08:42 +03:00
show_virtual_keyboard ( ) ;
}
}
void LineEdit : : show_virtual_keyboard ( ) {
2024-09-05 10:52:29 +03:00
_update_ime_window_position ( ) ;
2021-01-18 20:08:42 +03:00
if ( DisplayServer : : get_singleton ( ) - > has_feature ( DisplayServer : : FEATURE_VIRTUAL_KEYBOARD ) & & virtual_keyboard_enabled ) {
if ( selection . enabled ) {
2022-07-07 14:20:10 -04:00
DisplayServer : : get_singleton ( ) - > virtual_keyboard_show ( text , get_global_rect ( ) , DisplayServer : : VirtualKeyboardType ( virtual_keyboard_type ) , max_length , selection . begin , selection . end ) ;
2021-01-18 20:08:42 +03:00
} else {
2022-07-07 14:20:10 -04:00
DisplayServer : : get_singleton ( ) - > virtual_keyboard_show ( text , get_global_rect ( ) , DisplayServer : : VirtualKeyboardType ( virtual_keyboard_type ) , max_length , caret_column ) ;
2021-01-18 20:08:42 +03:00
}
}
2014-02-09 22:10:30 -03:00
}
String LineEdit : : get_text ( ) const {
return text ;
}
2016-06-27 19:47:40 +08:00
void LineEdit : : set_placeholder ( String p_text ) {
2022-03-16 15:50:48 +08:00
if ( placeholder = = p_text ) {
return ;
}
2019-06-22 14:42:36 +02:00
placeholder = p_text ;
2021-05-27 14:31:33 -03:00
placeholder_translated = atr ( placeholder ) ;
2020-09-09 16:00:32 +03:00
_shape ( ) ;
2022-08-13 23:21:24 +02:00
queue_redraw ( ) ;
2016-06-27 19:47:40 +08:00
}
String LineEdit : : get_placeholder ( ) const {
return placeholder ;
}
2021-03-28 19:31:25 +01:00
void LineEdit : : set_caret_column ( int p_column ) {
if ( p_column > ( int ) text . length ( ) ) {
p_column = text . length ( ) ;
2020-05-14 16:41:43 +02:00
}
2016-03-09 00:00:52 +01:00
2021-03-28 19:31:25 +01:00
if ( p_column < 0 ) {
p_column = 0 ;
2020-05-14 16:41:43 +02:00
}
2016-03-09 00:00:52 +01:00
2021-03-28 19:31:25 +01:00
caret_column = p_column ;
2016-03-09 00:00:52 +01:00
2025-03-21 16:42:23 +02:00
queue_accessibility_update ( ) ;
2020-09-09 16:00:32 +03:00
// Fit to window.
2014-11-05 21:20:42 -03:00
if ( ! is_inside_tree ( ) ) {
2022-07-06 11:57:06 +03:00
scroll_offset = 0.0 ;
2014-02-09 22:10:30 -03:00
return ;
}
2016-03-09 00:00:52 +01:00
2022-08-31 15:02:40 +03:00
Ref < StyleBox > style = theme_cache . normal ;
2020-09-09 16:00:32 +03:00
bool rtl = is_layout_rtl ( ) ;
2016-03-09 00:00:52 +01:00
2020-09-09 16:00:32 +03:00
int x_ofs = 0 ;
float text_width = TS - > shaped_text_get_size ( text_rid ) . x ;
2021-11-24 20:58:47 -06:00
switch ( alignment ) {
case HORIZONTAL_ALIGNMENT_FILL :
case HORIZONTAL_ALIGNMENT_LEFT : {
2020-09-09 16:00:32 +03:00
if ( rtl ) {
2020-12-22 16:24:29 +00:00
x_ofs = MAX ( style - > get_margin ( SIDE_LEFT ) , int ( get_size ( ) . width - style - > get_margin ( SIDE_RIGHT ) - ( text_width ) ) ) ;
2020-09-09 16:00:32 +03:00
} else {
2025-08-05 19:29:22 +02:00
x_ofs = style - > get_margin ( SIDE_LEFT ) ;
2020-09-09 16:00:32 +03:00
}
} break ;
2021-11-24 20:58:47 -06:00
case HORIZONTAL_ALIGNMENT_CENTER : {
2022-07-06 11:57:06 +03:00
if ( ! Math : : is_zero_approx ( scroll_offset ) ) {
2025-08-05 19:29:22 +02:00
x_ofs = style - > get_margin ( SIDE_LEFT ) ;
2020-09-09 16:00:32 +03:00
} else {
2025-08-04 23:45:31 +02:00
int total_margin = style - > get_margin ( SIDE_LEFT ) + style - > get_margin ( SIDE_RIGHT ) ;
int centered = int ( ( get_size ( ) . width - total_margin - text_width ) ) / 2 ;
x_ofs = style - > get_margin ( SIDE_LEFT ) + MAX ( 0 , centered ) ;
2020-09-09 16:00:32 +03:00
}
} break ;
2021-11-24 20:58:47 -06:00
case HORIZONTAL_ALIGNMENT_RIGHT : {
2020-09-09 16:00:32 +03:00
if ( rtl ) {
2025-08-05 19:29:22 +02:00
x_ofs = style - > get_margin ( SIDE_LEFT ) ;
2020-09-09 16:00:32 +03:00
} else {
2020-12-22 16:24:29 +00:00
x_ofs = MAX ( style - > get_margin ( SIDE_LEFT ) , int ( get_size ( ) . width - style - > get_margin ( SIDE_RIGHT ) - ( text_width ) ) ) ;
2020-09-09 16:00:32 +03:00
}
} break ;
}
2015-09-02 12:36:52 +01:00
2020-12-22 16:24:29 +00:00
int ofs_max = get_size ( ) . width - style - > get_margin ( SIDE_RIGHT ) ;
2020-12-15 12:04:21 +00:00
bool using_placeholder = text . is_empty ( ) & & ime_text . is_empty ( ) ;
2020-09-09 16:00:32 +03:00
bool display_clear_icon = ! using_placeholder & & is_editable ( ) & & clear_button_enabled ;
if ( right_icon . is_valid ( ) | | display_clear_icon ) {
2022-08-31 15:02:40 +03:00
Ref < Texture2D > r_icon = display_clear_icon ? theme_cache . clear_icon : right_icon ;
2024-11-22 21:27:36 +07:00
Point2 right_icon_size = _get_right_icon_size ( r_icon ) ;
2021-11-24 20:58:47 -06:00
if ( alignment = = HORIZONTAL_ALIGNMENT_CENTER ) {
2022-07-06 11:57:06 +03:00
if ( Math : : is_zero_approx ( scroll_offset ) ) {
2025-08-04 23:45:31 +02:00
int total_margin = style - > get_margin ( SIDE_LEFT ) + style - > get_margin ( SIDE_RIGHT ) ;
2024-11-22 21:27:36 +07:00
int center = int ( get_size ( ) . width - total_margin - text_width - right_icon_size . width ) / 2 ;
2025-08-04 23:45:31 +02:00
x_ofs = style - > get_margin ( SIDE_LEFT ) + MAX ( 0 , center ) ;
2015-09-02 12:36:52 +01:00
}
2025-08-05 19:29:22 +02:00
if ( rtl ) {
2024-11-22 21:27:36 +07:00
x_ofs + = right_icon_size . width ;
2025-08-05 19:29:22 +02:00
}
2020-09-09 16:00:32 +03:00
} else {
2025-08-05 19:29:22 +02:00
if ( rtl ) {
2024-11-22 21:27:36 +07:00
x_ofs = MAX ( style - > get_margin ( SIDE_LEFT ) + right_icon_size . width , x_ofs ) ;
2025-08-05 19:29:22 +02:00
} else {
if ( rtl ) {
2024-11-22 21:27:36 +07:00
x_ofs = MAX ( style - > get_margin ( SIDE_LEFT ) + right_icon_size . width , x_ofs ) ;
2025-08-05 19:29:22 +02:00
} else {
2024-11-22 21:27:36 +07:00
x_ofs = MAX ( style - > get_margin ( SIDE_LEFT ) , x_ofs - right_icon_size . width - style - > get_margin ( SIDE_RIGHT ) ) ;
2025-08-05 19:29:22 +02:00
}
}
}
if ( ! rtl ) {
2024-11-22 21:27:36 +07:00
ofs_max - = right_icon_size . width ;
2014-02-09 22:10:30 -03:00
}
2020-09-09 16:00:32 +03:00
}
2016-03-09 00:00:52 +01:00
2021-03-12 19:05:16 +05:30
// Note: Use two coordinates to fit IME input range.
2022-07-06 11:57:06 +03:00
Vector2 primary_caret_offset = get_caret_pixel_pos ( ) ;
2020-09-09 16:00:32 +03:00
2022-07-06 11:57:06 +03:00
if ( MIN ( primary_caret_offset . x , primary_caret_offset . y ) < = x_ofs ) {
scroll_offset + = x_ofs - MIN ( primary_caret_offset . x , primary_caret_offset . y ) ;
} else if ( MAX ( primary_caret_offset . x , primary_caret_offset . y ) > = ofs_max ) {
scroll_offset + = ofs_max - MAX ( primary_caret_offset . x , primary_caret_offset . y ) ;
2014-02-09 22:10:30 -03:00
}
2024-01-03 00:28:42 +00:00
// Scroll to show as much text as possible
if ( text_width + scroll_offset + x_ofs < ofs_max ) {
scroll_offset = ofs_max - x_ofs - text_width ;
}
2020-09-09 16:00:32 +03:00
scroll_offset = MIN ( 0 , scroll_offset ) ;
2025-03-21 16:42:23 +02:00
queue_accessibility_update ( ) ;
2022-08-13 23:21:24 +02:00
queue_redraw ( ) ;
2014-02-09 22:10:30 -03:00
}
2021-03-28 19:31:25 +01:00
int LineEdit : : get_caret_column ( ) const {
return caret_column ;
2014-02-09 22:10:30 -03:00
}
2025-04-22 10:02:07 -05:00
int LineEdit : : get_next_composite_character_column ( int p_column ) const {
ERR_FAIL_INDEX_V ( p_column , text . length ( ) + 1 , - 1 ) ;
if ( p_column = = text . length ( ) ) {
return p_column ;
} else {
return TS - > shaped_text_next_character_pos ( text_rid , p_column ) ;
}
}
int LineEdit : : get_previous_composite_character_column ( int p_column ) const {
ERR_FAIL_INDEX_V ( p_column , text . length ( ) + 1 , - 1 ) ;
if ( p_column = = 0 ) {
return 0 ;
} else {
return TS - > shaped_text_prev_character_pos ( text_rid , p_column ) ;
}
}
2022-07-06 11:57:06 +03:00
void LineEdit : : set_scroll_offset ( float p_pos ) {
2020-11-11 09:26:55 +01:00
scroll_offset = p_pos ;
2022-07-06 11:57:06 +03:00
if ( scroll_offset < 0.0 ) {
scroll_offset = 0.0 ;
2020-05-14 16:41:43 +02:00
}
2014-02-09 22:10:30 -03:00
}
2022-07-06 11:57:06 +03:00
float LineEdit : : get_scroll_offset ( ) const {
2020-11-11 09:26:55 +01:00
return scroll_offset ;
}
2021-03-28 19:31:25 +01:00
void LineEdit : : insert_text_at_caret ( String p_text ) {
2021-07-06 12:49:27 +02:00
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 ) {
2021-07-17 18:22:52 -03:00
emit_signal ( SNAME ( " text_change_rejected " ) , p_text . substr ( available_chars ) ) ;
2021-07-06 12:49:27 +02:00
p_text = p_text . substr ( 0 , available_chars ) ;
2020-09-09 16:00:32 +03:00
}
2014-02-09 22:10:30 -03:00
}
2021-07-06 12:49:27 +02:00
String pre = text . substr ( 0 , caret_column ) ;
2025-02-26 11:41:11 +01:00
String post = text . substr ( caret_column ) ;
2021-07-06 12:49:27 +02:00
text = pre + p_text + post ;
_shape ( ) ;
2021-08-28 00:19:51 +03:00
TextServer : : Direction dir = TS - > shaped_text_get_dominant_direction_in_range ( text_rid , caret_column , caret_column + p_text . length ( ) ) ;
2021-07-06 12:49:27 +02:00
if ( dir ! = TextServer : : DIRECTION_AUTO ) {
input_direction = ( TextDirection ) dir ;
}
set_caret_column ( caret_column + p_text . length ( ) ) ;
2023-01-26 09:09:53 +02:00
if ( ! ime_text . is_empty ( ) ) {
_shape ( ) ;
}
2014-02-09 22:10:30 -03:00
}
void LineEdit : : clear_internal ( ) {
2019-03-31 16:32:24 +01:00
deselect ( ) ;
2017-10-29 23:14:33 +00:00
_clear_undo_stack ( ) ;
2021-03-28 19:31:25 +01:00
caret_column = 0 ;
2022-07-06 11:57:06 +03:00
scroll_offset = 0.0 ;
2014-02-09 22:10:30 -03:00
undo_text = " " ;
text = " " ;
2020-09-09 16:00:32 +03:00
_shape ( ) ;
2022-08-13 23:21:24 +02:00
queue_redraw ( ) ;
2014-02-09 22:10:30 -03:00
}
Size2 LineEdit : : get_minimum_size ( ) const {
2022-08-31 15:02:40 +03:00
Ref < Font > font = theme_cache . font ;
int font_size = theme_cache . font_size ;
2016-03-09 00:00:52 +01:00
2019-09-24 23:21:35 -03:00
Size2 min_size ;
2016-09-06 20:34:24 -03:00
2019-09-08 22:46:57 -03:00
// Minimum size of text.
2024-09-10 13:43:31 +00:00
// W is wider than M in most fonts, Using M may result in hiding the last digit when using float values in SpinBox, ie. ColorPicker RAW values.
float em_space_size = font - > get_char_size ( ' W ' , font_size ) . x ;
2022-08-31 15:02:40 +03:00
min_size . width = theme_cache . minimum_character_width * em_space_size ;
2016-09-06 20:34:24 -03:00
if ( expand_to_text_length ) {
2023-05-26 15:51:32 +07:00
// Ensure some space for the caret when placed at the end.
min_size . width = MAX ( min_size . width , full_width + theme_cache . caret_width ) ;
2016-09-06 20:34:24 -03:00
}
2022-05-09 12:47:10 +03:00
min_size . height = MAX ( TS - > shaped_text_get_size ( text_rid ) . y , font - > get_height ( font_size ) ) ;
2019-09-24 23:21:35 -03:00
// Take icons into account.
2022-06-05 15:13:19 -03:00
int icon_max_width = 0 ;
if ( right_icon . is_valid ( ) ) {
2024-11-22 21:27:36 +07:00
Point2 right_icon_size = _get_right_icon_size ( right_icon ) ;
min_size . height = MAX ( min_size . height , right_icon_size . height ) ;
icon_max_width = right_icon_size . width ;
2022-06-05 15:13:19 -03:00
}
if ( clear_button_enabled ) {
2024-11-22 21:27:36 +07:00
Point2 right_icon_size = _get_right_icon_size ( theme_cache . clear_icon ) ;
min_size . height = MAX ( min_size . height , right_icon_size . height ) ;
icon_max_width = MAX ( icon_max_width , right_icon_size . width ) ;
2019-09-24 23:21:35 -03:00
}
2022-06-05 15:13:19 -03:00
min_size . width + = icon_max_width ;
2016-09-06 20:34:24 -03:00
2024-04-29 14:43:16 -04:00
Size2 style_min_size = theme_cache . normal - > get_minimum_size ( ) . max ( theme_cache . read_only - > get_minimum_size ( ) ) ;
return style_min_size + min_size ;
2014-02-09 22:10:30 -03:00
}
2017-12-17 15:40:44 -02:00
void LineEdit : : deselect ( ) {
2014-02-09 22:10:30 -03:00
selection . begin = 0 ;
selection . end = 0 ;
2021-03-28 19:31:25 +01:00
selection . start_column = 0 ;
2014-02-09 22:10:30 -03:00
selection . enabled = false ;
selection . creating = false ;
2021-04-13 04:25:44 -04:00
selection . double_click = false ;
2025-03-21 16:42:23 +02:00
queue_accessibility_update ( ) ;
2022-08-13 23:21:24 +02:00
queue_redraw ( ) ;
2014-02-09 22:10:30 -03:00
}
2021-09-24 11:00:45 +03:00
bool LineEdit : : has_selection ( ) const {
return selection . enabled ;
}
2023-03-30 17:07:28 +02:00
String LineEdit : : get_selected_text ( ) {
if ( selection . enabled ) {
return text . substr ( selection . begin , selection . end - selection . begin ) ;
} else {
return String ( ) ;
}
}
2021-09-24 11:00:45 +03:00
int LineEdit : : get_selection_from_column ( ) const {
ERR_FAIL_COND_V ( ! selection . enabled , - 1 ) ;
return selection . begin ;
}
int LineEdit : : get_selection_to_column ( ) const {
ERR_FAIL_COND_V ( ! selection . enabled , - 1 ) ;
return selection . end ;
}
2014-02-09 22:10:30 -03:00
void LineEdit : : selection_delete ( ) {
2020-05-14 16:41:43 +02:00
if ( selection . enabled ) {
2016-06-18 16:15:26 +02:00
delete_text ( selection . begin , selection . end ) ;
2020-05-14 16:41:43 +02:00
}
2016-03-09 00:00:52 +01:00
2017-12-17 15:40:44 -02:00
deselect ( ) ;
2014-02-09 22:10:30 -03:00
}
void LineEdit : : set_max_length ( int p_max_length ) {
ERR_FAIL_COND ( p_max_length < 0 ) ;
max_length = p_max_length ;
set_text ( text ) ;
}
int LineEdit : : get_max_length ( ) const {
return max_length ;
}
2021-03-28 19:31:25 +01:00
void LineEdit : : selection_fill_at_caret ( ) {
2020-05-14 16:41:43 +02:00
if ( ! selecting_enabled ) {
2019-08-07 17:09:46 -07:00
return ;
2020-05-14 16:41:43 +02:00
}
2016-03-09 00:00:52 +01:00
2021-03-28 19:31:25 +01:00
selection . begin = caret_column ;
selection . end = selection . start_column ;
2016-03-09 00:00:52 +01:00
2014-02-09 22:10:30 -03:00
if ( selection . end < selection . begin ) {
2019-01-14 20:04:47 -02:00
int aux = selection . end ;
2014-02-09 22:10:30 -03:00
selection . end = selection . begin ;
selection . begin = aux ;
}
2016-03-09 00:00:52 +01:00
2014-02-09 22:10:30 -03:00
selection . enabled = ( selection . begin ! = selection . end ) ;
2025-03-21 16:42:23 +02:00
queue_accessibility_update ( ) ;
2014-02-09 22:10:30 -03:00
}
void LineEdit : : select_all ( ) {
2020-05-14 16:41:43 +02:00
if ( ! selecting_enabled ) {
2019-08-07 17:09:46 -07:00
return ;
2020-05-14 16:41:43 +02:00
}
2016-03-09 00:00:52 +01:00
2024-09-10 13:43:31 +00:00
if ( text . is_empty ( ) ) {
set_caret_column ( 0 ) ;
2014-02-09 22:10:30 -03:00
return ;
2020-05-14 16:41:43 +02:00
}
2016-03-09 00:00:52 +01:00
2014-02-09 22:10:30 -03:00
selection . begin = 0 ;
selection . end = text . length ( ) ;
selection . enabled = true ;
2025-03-21 16:42:23 +02:00
queue_accessibility_update ( ) ;
2022-08-13 23:21:24 +02:00
queue_redraw ( ) ;
2014-02-09 22:10:30 -03:00
}
2018-04-28 20:24:48 +02:00
2014-02-09 22:10:30 -03:00
void LineEdit : : set_editable ( bool p_editable ) {
2020-05-14 16:41:43 +02:00
if ( editable = = p_editable ) {
2019-04-21 20:09:52 -03:00
return ;
2020-05-14 16:41:43 +02:00
}
2019-04-21 20:09:52 -03:00
2014-02-09 22:10:30 -03:00
editable = p_editable ;
2024-09-10 13:43:31 +00:00
if ( ! editable & & editing ) {
2024-10-04 10:37:33 +00:00
unedit ( ) ;
emit_signal ( SNAME ( " editing_toggled " ) , false ) ;
2024-09-10 13:43:31 +00:00
}
2022-10-09 16:51:01 +08:00
_validate_caret_can_draw ( ) ;
2019-04-21 20:09:52 -03:00
2021-12-06 14:02:34 +01:00
update_minimum_size ( ) ;
2025-03-21 16:42:23 +02:00
queue_accessibility_update ( ) ;
2022-08-13 23:21:24 +02:00
queue_redraw ( ) ;
2014-02-09 22:10:30 -03:00
}
bool LineEdit : : is_editable ( ) const {
return editable ;
}
void LineEdit : : set_secret ( bool p_secret ) {
2022-03-16 15:50:48 +08:00
if ( pass = = p_secret ) {
return ;
2020-09-09 16:00:32 +03:00
}
2022-03-16 15:50:48 +08:00
pass = p_secret ;
_shape ( ) ;
2025-06-05 10:01:11 +02:00
set_caret_column ( caret_column ) ; // Update scroll_offset.
2022-08-13 23:21:24 +02:00
queue_redraw ( ) ;
2014-02-09 22:10:30 -03:00
}
2018-04-28 20:24:48 +02:00
2014-02-09 22:10:30 -03:00
bool LineEdit : : is_secret ( ) const {
return pass ;
}
2018-04-28 20:24:48 +02:00
void LineEdit : : set_secret_character ( const String & p_string ) {
2023-10-01 13:39:13 +03:00
String c = p_string ;
if ( c . length ( ) > 1 ) {
WARN_PRINT ( " Secret character must be exactly one character long ( " + itos ( c . length ( ) ) + " characters given). " ) ;
c = c . left ( 1 ) ;
}
if ( secret_character = = c ) {
2022-03-16 15:50:48 +08:00
return ;
2020-09-09 16:00:32 +03:00
}
2023-10-01 13:39:13 +03:00
secret_character = c ;
2022-03-16 15:50:48 +08:00
_shape ( ) ;
2025-06-05 10:01:11 +02:00
set_caret_column ( caret_column ) ; // Update scroll_offset.
2022-08-13 23:21:24 +02:00
queue_redraw ( ) ;
2018-04-28 20:24:48 +02:00
}
String LineEdit : : get_secret_character ( ) const {
return secret_character ;
}
2014-02-09 22:10:30 -03:00
void LineEdit : : select ( int p_from , int p_to ) {
2020-05-14 16:41:43 +02:00
if ( ! selecting_enabled ) {
2019-08-07 17:09:46 -07:00
return ;
2020-05-14 16:41:43 +02:00
}
2014-02-09 22:10:30 -03:00
2014-02-27 22:16:00 +08:00
if ( p_from = = 0 & & p_to = = 0 ) {
2017-12-17 15:40:44 -02:00
deselect ( ) ;
2014-02-27 22:16:00 +08:00
return ;
}
2014-02-09 22:10:30 -03:00
int len = text . length ( ) ;
2020-05-14 16:41:43 +02:00
if ( p_from < 0 ) {
2014-02-09 22:10:30 -03:00
p_from = 0 ;
2020-05-14 16:41:43 +02:00
}
if ( p_from > len ) {
2014-02-09 22:10:30 -03:00
p_from = len ;
2020-05-14 16:41:43 +02:00
}
if ( p_to < 0 | | p_to > len ) {
2014-02-09 22:10:30 -03:00
p_to = len ;
2020-05-14 16:41:43 +02:00
}
2017-03-05 16:44:50 +01:00
2020-05-14 16:41:43 +02:00
if ( p_from > = p_to ) {
2014-02-09 22:10:30 -03:00
return ;
2020-05-14 16:41:43 +02:00
}
2014-02-09 22:10:30 -03:00
selection . enabled = true ;
selection . begin = p_from ;
selection . end = p_to ;
selection . creating = false ;
2021-04-13 04:25:44 -04:00
selection . double_click = false ;
2025-03-21 16:42:23 +02:00
queue_accessibility_update ( ) ;
2022-08-13 23:21:24 +02:00
queue_redraw ( ) ;
2014-02-09 22:10:30 -03:00
}
2015-10-17 10:29:54 -03:00
bool LineEdit : : is_text_field ( ) const {
return true ;
}
2014-02-09 22:10:30 -03:00
2016-05-16 20:25:17 -03:00
void LineEdit : : menu_option ( int p_option ) {
2025-10-03 00:38:47 -04:00
int prev_len = text . length ( ) ;
bool inserted_control_char = false ;
2016-05-16 20:25:17 -03:00
switch ( p_option ) {
case MENU_CUT : {
2016-09-19 14:17:48 +02:00
if ( editable ) {
cut_text ( ) ;
}
2016-05-16 20:25:17 -03:00
} break ;
case MENU_COPY : {
copy_text ( ) ;
} break ;
case MENU_PASTE : {
2016-09-19 14:17:48 +02:00
if ( editable ) {
paste_text ( ) ;
}
2016-05-16 20:25:17 -03:00
} break ;
case MENU_CLEAR : {
2016-09-19 14:17:48 +02:00
if ( editable ) {
clear ( ) ;
}
2016-05-16 20:25:17 -03:00
} break ;
case MENU_SELECT_ALL : {
select_all ( ) ;
} break ;
case MENU_UNDO : {
2017-07-17 20:00:01 +07:00
if ( editable ) {
undo ( ) ;
}
2016-05-16 20:25:17 -03:00
} break ;
2017-10-29 23:14:33 +00:00
case MENU_REDO : {
if ( editable ) {
redo ( ) ;
}
2020-09-09 16:00:32 +03:00
} break ;
case MENU_DIR_INHERITED : {
set_text_direction ( TEXT_DIRECTION_INHERITED ) ;
} break ;
case MENU_DIR_AUTO : {
set_text_direction ( TEXT_DIRECTION_AUTO ) ;
} break ;
case MENU_DIR_LTR : {
set_text_direction ( TEXT_DIRECTION_LTR ) ;
} break ;
case MENU_DIR_RTL : {
set_text_direction ( TEXT_DIRECTION_RTL ) ;
} break ;
case MENU_DISPLAY_UCC : {
set_draw_control_chars ( ! get_draw_control_chars ( ) ) ;
} break ;
case MENU_INSERT_LRM : {
if ( editable ) {
2021-03-28 19:31:25 +01:00
insert_text_at_caret ( String : : chr ( 0x200E ) ) ;
2025-10-03 00:38:47 -04:00
inserted_control_char = true ;
2020-09-09 16:00:32 +03:00
}
} break ;
case MENU_INSERT_RLM : {
if ( editable ) {
2021-03-28 19:31:25 +01:00
insert_text_at_caret ( String : : chr ( 0x200F ) ) ;
2025-10-03 00:38:47 -04:00
inserted_control_char = true ;
2020-09-09 16:00:32 +03:00
}
} break ;
case MENU_INSERT_LRE : {
if ( editable ) {
2021-03-28 19:31:25 +01:00
insert_text_at_caret ( String : : chr ( 0x202A ) ) ;
2025-10-03 00:38:47 -04:00
inserted_control_char = true ;
2020-09-09 16:00:32 +03:00
}
} break ;
case MENU_INSERT_RLE : {
if ( editable ) {
2021-03-28 19:31:25 +01:00
insert_text_at_caret ( String : : chr ( 0x202B ) ) ;
2025-10-03 00:38:47 -04:00
inserted_control_char = true ;
2020-09-09 16:00:32 +03:00
}
} break ;
case MENU_INSERT_LRO : {
if ( editable ) {
2021-03-28 19:31:25 +01:00
insert_text_at_caret ( String : : chr ( 0x202D ) ) ;
2025-10-03 00:38:47 -04:00
inserted_control_char = true ;
2020-09-09 16:00:32 +03:00
}
} break ;
case MENU_INSERT_RLO : {
if ( editable ) {
2021-03-28 19:31:25 +01:00
insert_text_at_caret ( String : : chr ( 0x202E ) ) ;
2025-10-03 00:38:47 -04:00
inserted_control_char = true ;
2020-09-09 16:00:32 +03:00
}
} break ;
case MENU_INSERT_PDF : {
if ( editable ) {
2021-03-28 19:31:25 +01:00
insert_text_at_caret ( String : : chr ( 0x202C ) ) ;
2025-10-03 00:38:47 -04:00
inserted_control_char = true ;
2020-09-09 16:00:32 +03:00
}
} break ;
case MENU_INSERT_ALM : {
if ( editable ) {
2021-03-28 19:31:25 +01:00
insert_text_at_caret ( String : : chr ( 0x061C ) ) ;
2025-10-03 00:38:47 -04:00
inserted_control_char = true ;
2020-09-09 16:00:32 +03:00
}
} break ;
case MENU_INSERT_LRI : {
if ( editable ) {
2021-03-28 19:31:25 +01:00
insert_text_at_caret ( String : : chr ( 0x2066 ) ) ;
2025-10-03 00:38:47 -04:00
inserted_control_char = true ;
2020-09-09 16:00:32 +03:00
}
} break ;
case MENU_INSERT_RLI : {
if ( editable ) {
2021-03-28 19:31:25 +01:00
insert_text_at_caret ( String : : chr ( 0x2067 ) ) ;
2025-10-03 00:38:47 -04:00
inserted_control_char = true ;
2020-09-09 16:00:32 +03:00
}
} break ;
case MENU_INSERT_FSI : {
if ( editable ) {
2021-03-28 19:31:25 +01:00
insert_text_at_caret ( String : : chr ( 0x2068 ) ) ;
2025-10-03 00:38:47 -04:00
inserted_control_char = true ;
2020-09-09 16:00:32 +03:00
}
} break ;
case MENU_INSERT_PDI : {
if ( editable ) {
2021-03-28 19:31:25 +01:00
insert_text_at_caret ( String : : chr ( 0x2069 ) ) ;
2025-10-03 00:38:47 -04:00
inserted_control_char = true ;
2020-09-09 16:00:32 +03:00
}
} break ;
case MENU_INSERT_ZWJ : {
if ( editable ) {
2021-03-28 19:31:25 +01:00
insert_text_at_caret ( String : : chr ( 0x200D ) ) ;
2025-10-03 00:38:47 -04:00
inserted_control_char = true ;
2020-09-09 16:00:32 +03:00
}
} break ;
case MENU_INSERT_ZWNJ : {
if ( editable ) {
2021-03-28 19:31:25 +01:00
insert_text_at_caret ( String : : chr ( 0x200C ) ) ;
2025-10-03 00:38:47 -04:00
inserted_control_char = true ;
2020-09-09 16:00:32 +03:00
}
} break ;
case MENU_INSERT_WJ : {
if ( editable ) {
2021-03-28 19:31:25 +01:00
insert_text_at_caret ( String : : chr ( 0x2060 ) ) ;
2025-10-03 00:38:47 -04:00
inserted_control_char = true ;
2020-09-09 16:00:32 +03:00
}
} break ;
case MENU_INSERT_SHY : {
if ( editable ) {
2021-03-28 19:31:25 +01:00
insert_text_at_caret ( String : : chr ( 0x00AD ) ) ;
2025-10-03 00:38:47 -04:00
inserted_control_char = true ;
2020-09-09 16:00:32 +03:00
}
2025-01-02 13:27:35 +02:00
} break ;
case MENU_EMOJI_AND_SYMBOL : {
show_emoji_and_symbol_picker ( ) ;
} break ;
2016-05-16 20:25:17 -03:00
}
2025-10-03 00:38:47 -04:00
// Mirror paste/drag behavior, emit text_changed signal if a control character was inserted.
if ( inserted_control_char & & ! text_changed_dirty ) {
if ( is_inside_tree ( ) & & text . length ( ) ! = prev_len ) {
callable_mp ( this , & LineEdit : : _text_changed ) . call_deferred ( ) ;
}
text_changed_dirty = true ;
}
2016-05-16 20:25:17 -03:00
}
2017-11-09 15:46:29 -05:00
void LineEdit : : set_context_menu_enabled ( bool p_enable ) {
context_menu_enabled = p_enable ;
}
bool LineEdit : : is_context_menu_enabled ( ) {
return context_menu_enabled ;
}
2025-01-02 13:27:35 +02:00
void LineEdit : : show_emoji_and_symbol_picker ( ) {
_update_ime_window_position ( ) ;
DisplayServer : : get_singleton ( ) - > show_emoji_and_symbol_picker ( ) ;
}
void LineEdit : : set_emoji_menu_enabled ( bool p_enabled ) {
if ( emoji_menu_enabled ! = p_enabled ) {
emoji_menu_enabled = p_enabled ;
}
}
bool LineEdit : : is_emoji_menu_enabled ( ) const {
return emoji_menu_enabled ;
}
2025-04-22 10:02:07 -05:00
void LineEdit : : set_backspace_deletes_composite_character_enabled ( bool p_enabled ) {
backspace_deletes_composite_character_enabled = p_enabled ;
}
bool LineEdit : : is_backspace_deletes_composite_character_enabled ( ) const {
return backspace_deletes_composite_character_enabled ;
}
2021-07-16 18:36:05 -03:00
bool LineEdit : : is_menu_visible ( ) const {
return menu & & menu - > is_visible ( ) ;
}
2016-05-16 20:25:17 -03:00
PopupMenu * LineEdit : : get_menu ( ) const {
2023-01-26 20:59:41 +03:00
if ( ! menu ) {
const_cast < LineEdit * > ( this ) - > _generate_context_menu ( ) ;
}
2016-05-16 20:25:17 -03:00
return menu ;
}
2016-06-21 14:38:35 +01:00
void LineEdit : : _editor_settings_changed ( ) {
2018-04-29 19:49:26 +02:00
# ifdef TOOLS_ENABLED
2022-11-23 00:14:08 +01:00
if ( ! EditorSettings : : get_singleton ( ) - > check_changed_settings_in_group ( " text_editor/appearance/caret " ) ) {
return ;
}
2022-03-06 21:39:19 +01:00
set_caret_blink_enabled ( EDITOR_GET ( " text_editor/appearance/caret/caret_blink " ) ) ;
2022-08-13 14:52:35 +02:00
set_caret_blink_interval ( EDITOR_GET ( " text_editor/appearance/caret/caret_blink_interval " ) ) ;
2016-06-21 14:38:35 +01:00
# endif
2018-04-29 19:49:26 +02:00
}
2016-06-21 14:38:35 +01:00
2021-03-28 19:31:25 +01:00
void LineEdit : : set_expand_to_text_length_enabled ( bool p_enabled ) {
2016-09-07 08:52:42 +02:00
expand_to_text_length = p_enabled ;
2021-12-06 14:02:34 +01:00
update_minimum_size ( ) ;
2021-03-28 19:31:25 +01:00
set_caret_column ( caret_column ) ;
2016-09-06 20:34:24 -03:00
}
2021-03-28 19:31:25 +01:00
bool LineEdit : : is_expand_to_text_length_enabled ( ) const {
2016-09-06 20:34:24 -03:00
return expand_to_text_length ;
}
2018-07-26 13:45:38 +02:00
void LineEdit : : set_clear_button_enabled ( bool p_enabled ) {
2020-01-15 09:42:06 +08:00
if ( clear_button_enabled = = p_enabled ) {
return ;
}
2018-07-26 13:45:38 +02:00
clear_button_enabled = p_enabled ;
2020-09-09 16:00:32 +03:00
_fit_to_width ( ) ;
2021-12-06 14:02:34 +01:00
update_minimum_size ( ) ;
2022-08-13 23:21:24 +02:00
queue_redraw ( ) ;
2018-07-26 13:45:38 +02:00
}
bool LineEdit : : is_clear_button_enabled ( ) const {
return clear_button_enabled ;
}
2019-08-07 17:09:46 -07:00
void LineEdit : : set_shortcut_keys_enabled ( bool p_enabled ) {
shortcut_keys_enabled = p_enabled ;
}
bool LineEdit : : is_shortcut_keys_enabled ( ) const {
return shortcut_keys_enabled ;
}
2020-07-22 08:04:48 +02:00
void LineEdit : : set_virtual_keyboard_enabled ( bool p_enable ) {
virtual_keyboard_enabled = p_enable ;
}
bool LineEdit : : is_virtual_keyboard_enabled ( ) const {
return virtual_keyboard_enabled ;
}
2025-05-05 20:21:43 -04:00
void LineEdit : : set_virtual_keyboard_show_on_focus ( bool p_show_on_focus ) {
virtual_keyboard_show_on_focus = p_show_on_focus ;
}
bool LineEdit : : get_virtual_keyboard_show_on_focus ( ) const {
return virtual_keyboard_show_on_focus ;
}
2022-07-07 14:20:10 -04:00
void LineEdit : : set_virtual_keyboard_type ( VirtualKeyboardType p_type ) {
virtual_keyboard_type = p_type ;
}
LineEdit : : VirtualKeyboardType LineEdit : : get_virtual_keyboard_type ( ) const {
return virtual_keyboard_type ;
}
2021-10-12 09:43:50 +02:00
void LineEdit : : set_middle_mouse_paste_enabled ( bool p_enabled ) {
middle_mouse_paste_enabled = p_enabled ;
}
bool LineEdit : : is_middle_mouse_paste_enabled ( ) const {
return middle_mouse_paste_enabled ;
}
2019-08-07 17:09:46 -07:00
void LineEdit : : set_selecting_enabled ( bool p_enabled ) {
2022-03-16 15:50:48 +08:00
if ( selecting_enabled = = p_enabled ) {
return ;
}
2019-08-07 17:09:46 -07:00
selecting_enabled = p_enabled ;
2020-05-14 16:41:43 +02:00
if ( ! selecting_enabled ) {
2019-08-07 17:09:46 -07:00
deselect ( ) ;
2020-05-14 16:41:43 +02:00
}
2019-08-07 17:09:46 -07:00
}
bool LineEdit : : is_selecting_enabled ( ) const {
return selecting_enabled ;
}
2021-10-21 23:02:46 +02:00
void LineEdit : : set_deselect_on_focus_loss_enabled ( const bool p_enabled ) {
2022-03-16 15:50:48 +08:00
if ( deselect_on_focus_loss_enabled = = p_enabled ) {
return ;
}
2021-10-21 23:02:46 +02:00
deselect_on_focus_loss_enabled = p_enabled ;
if ( p_enabled & & selection . enabled & & ! has_focus ( ) ) {
deselect ( ) ;
}
}
bool LineEdit : : is_deselect_on_focus_loss_enabled ( ) const {
return deselect_on_focus_loss_enabled ;
}
2023-07-16 20:32:00 -04:00
void LineEdit : : set_drag_and_drop_selection_enabled ( const bool p_enabled ) {
drag_and_drop_selection_enabled = p_enabled ;
}
bool LineEdit : : is_drag_and_drop_selection_enabled ( ) const {
return drag_and_drop_selection_enabled ;
}
2024-06-17 18:43:02 -07:00
void LineEdit : : _texture_changed ( ) {
_fit_to_width ( ) ;
update_minimum_size ( ) ;
queue_redraw ( ) ;
}
2019-06-11 15:43:37 -03:00
void LineEdit : : set_right_icon ( const Ref < Texture2D > & p_icon ) {
2018-08-11 12:04:19 +02:00
if ( right_icon = = p_icon ) {
return ;
}
2024-06-17 18:43:02 -07:00
if ( right_icon . is_valid ( ) ) {
right_icon - > disconnect_changed ( callable_mp ( this , & LineEdit : : _texture_changed ) ) ;
}
2018-08-11 12:04:19 +02:00
right_icon = p_icon ;
2024-06-17 18:43:02 -07:00
if ( right_icon . is_valid ( ) ) {
right_icon - > connect_changed ( callable_mp ( this , & LineEdit : : _texture_changed ) ) ;
}
2020-09-09 16:00:32 +03:00
_fit_to_width ( ) ;
2021-12-06 14:02:34 +01:00
update_minimum_size ( ) ;
2022-08-13 23:21:24 +02:00
queue_redraw ( ) ;
2018-08-11 12:04:19 +02:00
}
2019-06-11 15:43:37 -03:00
Ref < Texture2D > LineEdit : : get_right_icon ( ) {
2019-09-08 22:46:57 -03:00
return right_icon ;
}
2016-09-06 20:34:24 -03:00
2024-11-22 21:27:36 +07:00
void LineEdit : : set_icon_expand_mode ( ExpandMode p_mode ) {
if ( icon_expand_mode = = p_mode ) {
return ;
}
icon_expand_mode = p_mode ;
queue_redraw ( ) ;
update_minimum_size ( ) ;
notify_property_list_changed ( ) ;
}
LineEdit : : ExpandMode LineEdit : : get_icon_expand_mode ( ) const {
return icon_expand_mode ;
}
void LineEdit : : set_right_icon_scale ( float p_scale ) {
if ( right_icon_scale = = p_scale ) {
return ;
}
right_icon_scale = p_scale ;
queue_redraw ( ) ;
update_minimum_size ( ) ;
}
float LineEdit : : get_right_icon_scale ( ) const {
return right_icon_scale ;
}
2021-10-26 09:40:11 +03:00
void LineEdit : : set_flat ( bool p_enabled ) {
if ( flat ! = p_enabled ) {
flat = p_enabled ;
2022-08-13 23:21:24 +02:00
queue_redraw ( ) ;
2021-10-26 09:40:11 +03:00
}
}
bool LineEdit : : is_flat ( ) const {
return flat ;
}
2022-10-16 20:37:35 +08:00
void LineEdit : : set_select_all_on_focus ( bool p_enabled ) {
select_all_on_focus = p_enabled ;
}
bool LineEdit : : is_select_all_on_focus ( ) const {
return select_all_on_focus ;
}
void LineEdit : : clear_pending_select_all_on_focus ( ) {
pending_select_all_on_focus = false ;
}
2019-09-08 22:46:57 -03:00
void LineEdit : : _text_changed ( ) {
2017-10-29 23:14:33 +00:00
_emit_text_change ( ) ;
_clear_redo ( ) ;
}
void LineEdit : : _emit_text_change ( ) {
2024-05-14 11:42:00 +02:00
emit_signal ( SceneStringName ( text_changed ) , text ) ;
2018-02-05 16:22:34 +01:00
text_changed_dirty = false ;
2016-09-06 20:34:24 -03:00
}
2024-09-10 13:43:31 +00:00
2024-02-17 19:03:21 +01:00
PackedStringArray LineEdit : : get_configuration_warnings ( ) const {
PackedStringArray warnings = Control : : get_configuration_warnings ( ) ;
2023-09-16 15:24:08 +08:00
if ( secret_character . length ( ) > 1 ) {
warnings . push_back ( " Secret Character property supports only one character. Extra characters will be ignored. " ) ;
}
return warnings ;
}
2016-09-06 20:34:24 -03:00
2020-09-09 16:00:32 +03:00
void LineEdit : : _shape ( ) {
2022-10-14 12:57:20 +03:00
const Ref < Font > & font = theme_cache . font ;
int font_size = theme_cache . font_size ;
if ( font . is_null ( ) ) {
return ;
}
2020-09-09 16:00:32 +03:00
Size2 old_size = TS - > shaped_text_get_size ( text_rid ) ;
TS - > shaped_text_clear ( text_rid ) ;
String t ;
2024-09-10 13:43:31 +00:00
if ( text . is_empty ( ) & & ime_text . is_empty ( ) ) {
2020-09-09 16:00:32 +03:00
t = placeholder_translated ;
} else if ( pass ) {
2024-09-10 13:43:31 +00:00
String s = secret_character . is_empty ( ) ? U " • " : secret_character . left ( 1 ) ;
2023-10-01 13:39:13 +03:00
t = s . repeat ( text . length ( ) + ime_text . length ( ) ) ;
2020-09-09 16:00:32 +03:00
} else {
2024-09-10 13:43:31 +00:00
if ( ! ime_text . is_empty ( ) ) {
2025-02-26 11:41:11 +01:00
t = text . substr ( 0 , caret_column ) + ime_text + text . substr ( caret_column ) ;
2020-09-09 16:00:32 +03:00
} else {
t = text ;
2020-01-29 14:46:49 -05:00
}
}
2020-09-09 16:00:32 +03:00
if ( text_direction = = Control : : TEXT_DIRECTION_INHERITED ) {
TS - > shaped_text_set_direction ( text_rid , is_layout_rtl ( ) ? TextServer : : DIRECTION_RTL : TextServer : : DIRECTION_LTR ) ;
} else {
TS - > shaped_text_set_direction ( text_rid , ( TextServer : : Direction ) text_direction ) ;
}
TS - > shaped_text_set_preserve_control ( text_rid , draw_control_chars ) ;
2025-09-10 15:14:18 +08:00
const String & lang = language . is_empty ( ) ? _get_locale ( ) : language ;
TS - > shaped_text_add_string ( text_rid , t , font - > get_rids ( ) , font_size , font - > get_opentype_features ( ) , lang ) ;
2020-09-09 16:00:32 +03:00
TS - > shaped_text_set_bidi_override ( text_rid , structured_text_parser ( st_parser , st_args , t ) ) ;
full_width = TS - > shaped_text_get_size ( text_rid ) . x ;
_fit_to_width ( ) ;
Size2 size = TS - > shaped_text_get_size ( text_rid ) ;
if ( ( expand_to_text_length & & old_size . x ! = size . x ) | | ( old_size . y ! = size . y ) ) {
2021-12-06 14:02:34 +01:00
update_minimum_size ( ) ;
2020-09-09 16:00:32 +03:00
}
2025-03-21 16:42:23 +02:00
if ( accessibility_text_root_element . is_valid ( ) ) {
DisplayServer : : get_singleton ( ) - > accessibility_free_element ( accessibility_text_root_element ) ;
accessibility_text_root_element = RID ( ) ;
}
queue_accessibility_update ( ) ;
2020-01-29 14:46:49 -05:00
}
2020-09-09 16:00:32 +03:00
void LineEdit : : _fit_to_width ( ) {
2021-11-24 20:58:47 -06:00
if ( alignment = = HORIZONTAL_ALIGNMENT_FILL ) {
2022-08-31 15:02:40 +03:00
Ref < StyleBox > style = theme_cache . normal ;
2020-12-22 16:24:29 +00:00
int t_width = get_size ( ) . width - style - > get_margin ( SIDE_RIGHT ) - style - > get_margin ( SIDE_LEFT ) ;
2020-12-15 12:04:21 +00:00
bool using_placeholder = text . is_empty ( ) & & ime_text . is_empty ( ) ;
2020-09-09 16:00:32 +03:00
bool display_clear_icon = ! using_placeholder & & is_editable ( ) & & clear_button_enabled ;
if ( right_icon . is_valid ( ) | | display_clear_icon ) {
2022-08-31 15:02:40 +03:00
Ref < Texture2D > r_icon = display_clear_icon ? theme_cache . clear_icon : right_icon ;
2024-11-22 21:27:36 +07:00
Point2 right_icon_size = _get_right_icon_size ( r_icon ) ;
t_width - = right_icon_size . width ;
2019-06-22 14:42:36 +02:00
}
2020-09-09 16:00:32 +03:00
TS - > shaped_text_fit_to_width ( text_rid , MAX ( t_width , full_width ) ) ;
2019-06-22 14:42:36 +02:00
}
}
2017-10-29 23:14:33 +00:00
void LineEdit : : _clear_redo ( ) {
_create_undo_state ( ) ;
2020-04-02 01:20:12 +02:00
if ( undo_stack_pos = = nullptr ) {
2017-10-29 23:14:33 +00:00
return ;
}
undo_stack_pos = undo_stack_pos - > next ( ) ;
while ( undo_stack_pos ) {
List < TextOperation > : : Element * elem = undo_stack_pos ;
undo_stack_pos = undo_stack_pos - > next ( ) ;
undo_stack . erase ( elem ) ;
}
_create_undo_state ( ) ;
}
void LineEdit : : _clear_undo_stack ( ) {
undo_stack . clear ( ) ;
2020-04-02 01:20:12 +02:00
undo_stack_pos = nullptr ;
2017-10-29 23:14:33 +00:00
_create_undo_state ( ) ;
}
void LineEdit : : _create_undo_state ( ) {
TextOperation op ;
op . text = text ;
2021-03-28 19:31:25 +01:00
op . caret_column = caret_column ;
2020-11-11 09:26:55 +01:00
op . scroll_offset = scroll_offset ;
2017-10-29 23:14:33 +00:00
undo_stack . push_back ( op ) ;
}
2021-08-13 16:31:57 -05:00
Key LineEdit : : _get_menu_action_accelerator ( const String & p_action ) {
2020-12-07 21:32:00 +10:00
const List < Ref < InputEvent > > * events = InputMap : : get_singleton ( ) - > action_get_events ( p_action ) ;
if ( ! events ) {
2021-08-13 16:31:57 -05:00
return Key : : NONE ;
2020-12-07 21:32:00 +10:00
}
// Use first event in the list for the accelerator.
const List < Ref < InputEvent > > : : Element * first_event = events - > front ( ) ;
if ( ! first_event ) {
2021-08-13 16:31:57 -05:00
return Key : : NONE ;
2020-12-07 21:32:00 +10:00
}
const Ref < InputEventKey > event = first_event - > get ( ) ;
if ( event . is_null ( ) ) {
2021-08-13 16:31:57 -05:00
return Key : : NONE ;
2020-12-07 21:32:00 +10:00
}
2023-03-08 23:00:27 +01:00
// Use physical keycode if non-zero.
2021-08-13 16:31:57 -05:00
if ( event - > get_physical_keycode ( ) ! = Key : : NONE ) {
2020-12-07 21:32:00 +10:00
return event - > get_physical_keycode_with_modifiers ( ) ;
} else {
return event - > get_keycode_with_modifiers ( ) ;
}
}
2023-01-26 20:59:41 +03:00
void LineEdit : : _generate_context_menu ( ) {
menu = memnew ( PopupMenu ) ;
add_child ( menu , false , INTERNAL_MODE_FRONT ) ;
menu_dir = memnew ( PopupMenu ) ;
2023-12-15 20:56:06 -03:00
menu_dir - > add_radio_check_item ( ETR ( " Same as Layout Direction " ) , MENU_DIR_INHERITED ) ;
menu_dir - > add_radio_check_item ( ETR ( " Auto-Detect Direction " ) , MENU_DIR_AUTO ) ;
menu_dir - > add_radio_check_item ( ETR ( " Left-to-Right " ) , MENU_DIR_LTR ) ;
menu_dir - > add_radio_check_item ( ETR ( " Right-to-Left " ) , MENU_DIR_RTL ) ;
2023-01-26 20:59:41 +03:00
menu_ctl = memnew ( PopupMenu ) ;
2023-12-15 20:56:06 -03:00
menu_ctl - > add_item ( ETR ( " Left-to-Right Mark (LRM) " ) , MENU_INSERT_LRM ) ;
menu_ctl - > add_item ( ETR ( " Right-to-Left Mark (RLM) " ) , MENU_INSERT_RLM ) ;
menu_ctl - > add_item ( ETR ( " Start of Left-to-Right Embedding (LRE) " ) , MENU_INSERT_LRE ) ;
menu_ctl - > add_item ( ETR ( " Start of Right-to-Left Embedding (RLE) " ) , MENU_INSERT_RLE ) ;
menu_ctl - > add_item ( ETR ( " Start of Left-to-Right Override (LRO) " ) , MENU_INSERT_LRO ) ;
menu_ctl - > add_item ( ETR ( " Start of Right-to-Left Override (RLO) " ) , MENU_INSERT_RLO ) ;
menu_ctl - > add_item ( ETR ( " Pop Direction Formatting (PDF) " ) , MENU_INSERT_PDF ) ;
2023-01-26 20:59:41 +03:00
menu_ctl - > add_separator ( ) ;
2023-12-15 20:56:06 -03:00
menu_ctl - > add_item ( ETR ( " Arabic Letter Mark (ALM) " ) , MENU_INSERT_ALM ) ;
menu_ctl - > add_item ( ETR ( " Left-to-Right Isolate (LRI) " ) , MENU_INSERT_LRI ) ;
menu_ctl - > add_item ( ETR ( " Right-to-Left Isolate (RLI) " ) , MENU_INSERT_RLI ) ;
menu_ctl - > add_item ( ETR ( " First Strong Isolate (FSI) " ) , MENU_INSERT_FSI ) ;
menu_ctl - > add_item ( ETR ( " Pop Direction Isolate (PDI) " ) , MENU_INSERT_PDI ) ;
2023-01-26 20:59:41 +03:00
menu_ctl - > add_separator ( ) ;
2023-12-15 20:56:06 -03:00
menu_ctl - > add_item ( ETR ( " Zero-Width Joiner (ZWJ) " ) , MENU_INSERT_ZWJ ) ;
menu_ctl - > add_item ( ETR ( " Zero-Width Non-Joiner (ZWNJ) " ) , MENU_INSERT_ZWNJ ) ;
menu_ctl - > add_item ( ETR ( " Word Joiner (WJ) " ) , MENU_INSERT_WJ ) ;
menu_ctl - > add_item ( ETR ( " Soft Hyphen (SHY) " ) , MENU_INSERT_SHY ) ;
2025-01-02 13:27:35 +02:00
if ( DisplayServer : : get_singleton ( ) - > has_feature ( DisplayServer : : FEATURE_EMOJI_AND_SYMBOL_PICKER ) ) {
menu - > add_item ( ETR ( " Emoji & Symbols " ) , MENU_EMOJI_AND_SYMBOL ) ;
menu - > add_separator ( ) ;
}
2023-12-15 20:56:06 -03:00
menu - > add_item ( ETR ( " Cut " ) , MENU_CUT ) ;
menu - > add_item ( ETR ( " Copy " ) , MENU_COPY ) ;
menu - > add_item ( ETR ( " Paste " ) , MENU_PASTE ) ;
2023-01-26 20:59:41 +03:00
menu - > add_separator ( ) ;
2023-12-15 20:56:06 -03:00
menu - > add_item ( ETR ( " Select All " ) , MENU_SELECT_ALL ) ;
menu - > add_item ( ETR ( " Clear " ) , MENU_CLEAR ) ;
2023-01-26 20:59:41 +03:00
menu - > add_separator ( ) ;
2023-12-15 20:56:06 -03:00
menu - > add_item ( ETR ( " Undo " ) , MENU_UNDO ) ;
menu - > add_item ( ETR ( " Redo " ) , MENU_REDO ) ;
2023-01-26 20:59:41 +03:00
menu - > add_separator ( ) ;
2023-12-15 20:56:06 -03:00
menu - > add_submenu_node_item ( ETR ( " Text Writing Direction " ) , menu_dir , MENU_SUBMENU_TEXT_DIR ) ;
2023-01-26 20:59:41 +03:00
menu - > add_separator ( ) ;
2023-12-15 20:56:06 -03:00
menu - > add_check_item ( ETR ( " Display Control Characters " ) , MENU_DISPLAY_UCC ) ;
menu - > add_submenu_node_item ( ETR ( " Insert Control Character " ) , menu_ctl , MENU_SUBMENU_INSERT_UCC ) ;
2023-01-26 20:59:41 +03:00
2024-05-14 14:13:31 +02:00
menu - > connect ( SceneStringName ( id_pressed ) , callable_mp ( this , & LineEdit : : menu_option ) ) ;
menu_dir - > connect ( SceneStringName ( id_pressed ) , callable_mp ( this , & LineEdit : : menu_option ) ) ;
menu_ctl - > connect ( SceneStringName ( id_pressed ) , callable_mp ( this , & LineEdit : : menu_option ) ) ;
2023-01-26 20:59:41 +03:00
2024-05-13 16:56:03 +02:00
menu - > connect ( SceneStringName ( focus_entered ) , callable_mp ( this , & LineEdit : : _validate_caret_can_draw ) ) ;
menu - > connect ( SceneStringName ( focus_exited ) , callable_mp ( this , & LineEdit : : _validate_caret_can_draw ) ) ;
2023-01-26 20:59:41 +03:00
}
void LineEdit : : _update_context_menu ( ) {
if ( ! menu ) {
_generate_context_menu ( ) ;
}
int idx = - 1 ;
# define MENU_ITEM_ACTION_DISABLED(m_menu, m_id, m_action, m_disabled) \
idx = m_menu - > get_item_index ( m_id ) ; \
if ( idx > = 0 ) { \
m_menu - > set_item_accelerator ( idx , shortcut_keys_enabled ? _get_menu_action_accelerator ( m_action ) : Key : : NONE ) ; \
m_menu - > set_item_disabled ( idx , m_disabled ) ; \
}
# define MENU_ITEM_ACTION(m_menu, m_id, m_action) \
idx = m_menu - > get_item_index ( m_id ) ; \
if ( idx > = 0 ) { \
m_menu - > set_item_accelerator ( idx , shortcut_keys_enabled ? _get_menu_action_accelerator ( m_action ) : Key : : NONE ) ; \
}
# define MENU_ITEM_DISABLED(m_menu, m_id, m_disabled) \
idx = m_menu - > get_item_index ( m_id ) ; \
if ( idx > = 0 ) { \
m_menu - > set_item_disabled ( idx , m_disabled ) ; \
}
# define MENU_ITEM_CHECKED(m_menu, m_id, m_checked) \
idx = m_menu - > get_item_index ( m_id ) ; \
if ( idx > = 0 ) { \
m_menu - > set_item_checked ( idx , m_checked ) ; \
}
2025-01-02 13:27:35 +02:00
if ( DisplayServer : : get_singleton ( ) - > has_feature ( DisplayServer : : FEATURE_EMOJI_AND_SYMBOL_PICKER ) ) {
MENU_ITEM_DISABLED ( menu , MENU_EMOJI_AND_SYMBOL , ! editable | | ! emoji_menu_enabled )
}
2023-01-26 20:59:41 +03:00
MENU_ITEM_ACTION_DISABLED ( menu , MENU_CUT , " ui_cut " , ! editable )
MENU_ITEM_ACTION ( menu , MENU_COPY , " ui_copy " )
MENU_ITEM_ACTION_DISABLED ( menu , MENU_PASTE , " ui_paste " , ! editable )
MENU_ITEM_ACTION_DISABLED ( menu , MENU_SELECT_ALL , " ui_text_select_all " , ! selecting_enabled )
MENU_ITEM_DISABLED ( menu , MENU_CLEAR , ! editable )
MENU_ITEM_ACTION_DISABLED ( menu , MENU_UNDO , " ui_undo " , ! editable | | ! has_undo ( ) )
MENU_ITEM_ACTION_DISABLED ( menu , MENU_REDO , " ui_redo " , ! editable | | ! has_redo ( ) )
MENU_ITEM_CHECKED ( menu_dir , MENU_DIR_INHERITED , text_direction = = TEXT_DIRECTION_INHERITED )
MENU_ITEM_CHECKED ( menu_dir , MENU_DIR_AUTO , text_direction = = TEXT_DIRECTION_AUTO )
MENU_ITEM_CHECKED ( menu_dir , MENU_DIR_LTR , text_direction = = TEXT_DIRECTION_LTR )
MENU_ITEM_CHECKED ( menu_dir , MENU_DIR_RTL , text_direction = = TEXT_DIRECTION_RTL )
MENU_ITEM_CHECKED ( menu , MENU_DISPLAY_UCC , draw_control_chars )
MENU_ITEM_DISABLED ( menu , MENU_SUBMENU_INSERT_UCC , ! editable )
# undef MENU_ITEM_ACTION_DISABLED
# undef MENU_ITEM_ACTION
# undef MENU_ITEM_DISABLED
# undef MENU_ITEM_CHECKED
}
2022-08-12 23:57:11 +03:00
void LineEdit : : _validate_property ( PropertyInfo & p_property ) const {
2025-06-12 12:54:19 +08:00
if ( ! Engine : : get_singleton ( ) - > is_editor_hint ( ) ) {
return ;
}
2022-08-13 14:52:35 +02:00
if ( ! caret_blink_enabled & & p_property . name = = " caret_blink_interval " ) {
2022-08-12 23:57:11 +03:00
p_property . usage = PROPERTY_USAGE_NO_EDITOR ;
2024-11-22 21:27:36 +07:00
} else if ( icon_expand_mode ! = EXPAND_MODE_FIT_TO_LINE_EDIT & & p_property . name = = " right_icon_scale " ) {
p_property . usage = PROPERTY_USAGE_NO_EDITOR ;
2021-03-03 20:51:35 -03:00
}
}
2014-02-09 22:10:30 -03:00
void LineEdit : : _bind_methods ( ) {
2024-09-05 10:52:29 +03:00
ClassDB : : bind_method ( D_METHOD ( " has_ime_text " ) , & LineEdit : : has_ime_text ) ;
ClassDB : : bind_method ( D_METHOD ( " cancel_ime " ) , & LineEdit : : cancel_ime ) ;
ClassDB : : bind_method ( D_METHOD ( " apply_ime " ) , & LineEdit : : apply_ime ) ;
2021-11-24 20:58:47 -06:00
ClassDB : : bind_method ( D_METHOD ( " set_horizontal_alignment " , " alignment " ) , & LineEdit : : set_horizontal_alignment ) ;
ClassDB : : bind_method ( D_METHOD ( " get_horizontal_alignment " ) , & LineEdit : : get_horizontal_alignment ) ;
2017-02-13 12:47:24 +01:00
2025-10-01 11:14:22 -03:00
ClassDB : : bind_method ( D_METHOD ( " edit " , " hide_focus " ) , & LineEdit : : edit , DEFVAL ( false ) ) ;
2024-10-04 10:37:33 +00:00
ClassDB : : bind_method ( D_METHOD ( " unedit " ) , & LineEdit : : unedit ) ;
2024-09-10 13:43:31 +00:00
ClassDB : : bind_method ( D_METHOD ( " is_editing " ) , & LineEdit : : is_editing ) ;
2025-01-02 23:41:27 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_keep_editing_on_text_submit " , " enable " ) , & LineEdit : : set_keep_editing_on_text_submit ) ;
ClassDB : : bind_method ( D_METHOD ( " is_editing_kept_on_text_submit " ) , & LineEdit : : is_editing_kept_on_text_submit ) ;
2017-02-13 12:47:24 +01:00
ClassDB : : bind_method ( D_METHOD ( " clear " ) , & LineEdit : : clear ) ;
2017-12-17 15:40:44 -02:00
ClassDB : : bind_method ( D_METHOD ( " select " , " from " , " to " ) , & LineEdit : : select , DEFVAL ( 0 ) , DEFVAL ( - 1 ) ) ;
2017-02-13 12:47:24 +01:00
ClassDB : : bind_method ( D_METHOD ( " select_all " ) , & LineEdit : : select_all ) ;
2017-12-17 15:40:44 -02:00
ClassDB : : bind_method ( D_METHOD ( " deselect " ) , & LineEdit : : deselect ) ;
2024-09-19 01:15:12 +03:00
ClassDB : : bind_method ( D_METHOD ( " has_undo " ) , & LineEdit : : has_undo ) ;
ClassDB : : bind_method ( D_METHOD ( " has_redo " ) , & LineEdit : : has_redo ) ;
2021-09-24 11:00:45 +03:00
ClassDB : : bind_method ( D_METHOD ( " has_selection " ) , & LineEdit : : has_selection ) ;
2023-03-30 17:07:28 +02:00
ClassDB : : bind_method ( D_METHOD ( " get_selected_text " ) , & LineEdit : : get_selected_text ) ;
2021-09-24 11:00:45 +03:00
ClassDB : : bind_method ( D_METHOD ( " get_selection_from_column " ) , & LineEdit : : get_selection_from_column ) ;
ClassDB : : bind_method ( D_METHOD ( " get_selection_to_column " ) , & LineEdit : : get_selection_to_column ) ;
2017-02-13 12:47:24 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_text " , " text " ) , & LineEdit : : set_text ) ;
ClassDB : : bind_method ( D_METHOD ( " get_text " ) , & LineEdit : : get_text ) ;
2020-09-09 16:00:32 +03:00
ClassDB : : bind_method ( D_METHOD ( " get_draw_control_chars " ) , & LineEdit : : get_draw_control_chars ) ;
ClassDB : : bind_method ( D_METHOD ( " set_draw_control_chars " , " enable " ) , & LineEdit : : set_draw_control_chars ) ;
ClassDB : : bind_method ( D_METHOD ( " set_text_direction " , " direction " ) , & LineEdit : : set_text_direction ) ;
ClassDB : : bind_method ( D_METHOD ( " get_text_direction " ) , & LineEdit : : get_text_direction ) ;
ClassDB : : bind_method ( D_METHOD ( " set_language " , " language " ) , & LineEdit : : set_language ) ;
ClassDB : : bind_method ( D_METHOD ( " get_language " ) , & LineEdit : : get_language ) ;
ClassDB : : bind_method ( D_METHOD ( " set_structured_text_bidi_override " , " parser " ) , & LineEdit : : set_structured_text_bidi_override ) ;
ClassDB : : bind_method ( D_METHOD ( " get_structured_text_bidi_override " ) , & LineEdit : : get_structured_text_bidi_override ) ;
ClassDB : : bind_method ( D_METHOD ( " set_structured_text_bidi_override_options " , " args " ) , & LineEdit : : set_structured_text_bidi_override_options ) ;
ClassDB : : bind_method ( D_METHOD ( " get_structured_text_bidi_override_options " ) , & LineEdit : : get_structured_text_bidi_override_options ) ;
2017-02-13 12:47:24 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_placeholder " , " text " ) , & LineEdit : : set_placeholder ) ;
ClassDB : : bind_method ( D_METHOD ( " get_placeholder " ) , & LineEdit : : get_placeholder ) ;
2021-03-28 19:31:25 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_caret_column " , " position " ) , & LineEdit : : set_caret_column ) ;
ClassDB : : bind_method ( D_METHOD ( " get_caret_column " ) , & LineEdit : : get_caret_column ) ;
2025-04-22 10:02:07 -05:00
ClassDB : : bind_method ( D_METHOD ( " get_next_composite_character_column " , " column " ) , & LineEdit : : get_next_composite_character_column ) ;
ClassDB : : bind_method ( D_METHOD ( " get_previous_composite_character_column " , " column " ) , & LineEdit : : get_previous_composite_character_column ) ;
2020-11-11 09:26:55 +01:00
ClassDB : : bind_method ( D_METHOD ( " get_scroll_offset " ) , & LineEdit : : get_scroll_offset ) ;
2021-03-28 19:31:25 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_expand_to_text_length_enabled " , " enabled " ) , & LineEdit : : set_expand_to_text_length_enabled ) ;
ClassDB : : bind_method ( D_METHOD ( " is_expand_to_text_length_enabled " ) , & LineEdit : : is_expand_to_text_length_enabled ) ;
ClassDB : : bind_method ( D_METHOD ( " set_caret_blink_enabled " , " enabled " ) , & LineEdit : : set_caret_blink_enabled ) ;
ClassDB : : bind_method ( D_METHOD ( " is_caret_blink_enabled " ) , & LineEdit : : is_caret_blink_enabled ) ;
ClassDB : : bind_method ( D_METHOD ( " set_caret_mid_grapheme_enabled " , " enabled " ) , & LineEdit : : set_caret_mid_grapheme_enabled ) ;
ClassDB : : bind_method ( D_METHOD ( " is_caret_mid_grapheme_enabled " ) , & LineEdit : : is_caret_mid_grapheme_enabled ) ;
ClassDB : : bind_method ( D_METHOD ( " set_caret_force_displayed " , " enabled " ) , & LineEdit : : set_caret_force_displayed ) ;
ClassDB : : bind_method ( D_METHOD ( " is_caret_force_displayed " ) , & LineEdit : : is_caret_force_displayed ) ;
2022-08-13 14:52:35 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_caret_blink_interval " , " interval " ) , & LineEdit : : set_caret_blink_interval ) ;
ClassDB : : bind_method ( D_METHOD ( " get_caret_blink_interval " ) , & LineEdit : : get_caret_blink_interval ) ;
2017-02-13 12:47:24 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_max_length " , " chars " ) , & LineEdit : : set_max_length ) ;
ClassDB : : bind_method ( D_METHOD ( " get_max_length " ) , & LineEdit : : get_max_length ) ;
2021-03-28 19:31:25 +01:00
ClassDB : : bind_method ( D_METHOD ( " insert_text_at_caret " , " text " ) , & LineEdit : : insert_text_at_caret ) ;
ClassDB : : bind_method ( D_METHOD ( " delete_char_at_caret " ) , & LineEdit : : delete_char ) ;
2020-06-06 17:39:53 +02:00
ClassDB : : bind_method ( D_METHOD ( " delete_text " , " from_column " , " to_column " ) , & LineEdit : : delete_text ) ;
2017-02-13 12:47:24 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_editable " , " enabled " ) , & LineEdit : : set_editable ) ;
ClassDB : : bind_method ( D_METHOD ( " is_editable " ) , & LineEdit : : is_editable ) ;
ClassDB : : bind_method ( D_METHOD ( " set_secret " , " enabled " ) , & LineEdit : : set_secret ) ;
ClassDB : : bind_method ( D_METHOD ( " is_secret " ) , & LineEdit : : is_secret ) ;
2018-04-28 20:24:48 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_secret_character " , " character " ) , & LineEdit : : set_secret_character ) ;
ClassDB : : bind_method ( D_METHOD ( " get_secret_character " ) , & LineEdit : : get_secret_character ) ;
2017-02-13 12:47:24 +01:00
ClassDB : : bind_method ( D_METHOD ( " menu_option " , " option " ) , & LineEdit : : menu_option ) ;
2024-07-17 12:14:00 +02:00
// TODO: Properly handle popups when advanced GUI is disabled.
# ifndef ADVANCED_GUI_DISABLED
2017-08-09 13:19:41 +02:00
ClassDB : : bind_method ( D_METHOD ( " get_menu " ) , & LineEdit : : get_menu ) ;
2024-07-17 12:14:00 +02:00
# endif // ADVANCED_GUI_DISABLED
2021-07-16 18:36:05 -03:00
ClassDB : : bind_method ( D_METHOD ( " is_menu_visible " ) , & LineEdit : : is_menu_visible ) ;
2017-11-09 15:46:29 -05:00
ClassDB : : bind_method ( D_METHOD ( " set_context_menu_enabled " , " enable " ) , & LineEdit : : set_context_menu_enabled ) ;
ClassDB : : bind_method ( D_METHOD ( " is_context_menu_enabled " ) , & LineEdit : : is_context_menu_enabled ) ;
2025-01-02 13:27:35 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_emoji_menu_enabled " , " enable " ) , & LineEdit : : set_emoji_menu_enabled ) ;
ClassDB : : bind_method ( D_METHOD ( " is_emoji_menu_enabled " ) , & LineEdit : : is_emoji_menu_enabled ) ;
2025-04-22 10:02:07 -05:00
ClassDB : : bind_method ( D_METHOD ( " set_backspace_deletes_composite_character_enabled " , " enable " ) , & LineEdit : : set_backspace_deletes_composite_character_enabled ) ;
ClassDB : : bind_method ( D_METHOD ( " is_backspace_deletes_composite_character_enabled " ) , & LineEdit : : is_backspace_deletes_composite_character_enabled ) ;
2020-07-22 08:04:48 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_virtual_keyboard_enabled " , " enable " ) , & LineEdit : : set_virtual_keyboard_enabled ) ;
ClassDB : : bind_method ( D_METHOD ( " is_virtual_keyboard_enabled " ) , & LineEdit : : is_virtual_keyboard_enabled ) ;
2025-05-05 20:21:43 -04:00
ClassDB : : bind_method ( D_METHOD ( " set_virtual_keyboard_show_on_focus " , " show_on_focus " ) , & LineEdit : : set_virtual_keyboard_show_on_focus ) ;
ClassDB : : bind_method ( D_METHOD ( " get_virtual_keyboard_show_on_focus " ) , & LineEdit : : get_virtual_keyboard_show_on_focus ) ;
2022-07-07 14:20:10 -04:00
ClassDB : : bind_method ( D_METHOD ( " set_virtual_keyboard_type " , " type " ) , & LineEdit : : set_virtual_keyboard_type ) ;
ClassDB : : bind_method ( D_METHOD ( " get_virtual_keyboard_type " ) , & LineEdit : : get_virtual_keyboard_type ) ;
2018-07-26 13:45:38 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_clear_button_enabled " , " enable " ) , & LineEdit : : set_clear_button_enabled ) ;
ClassDB : : bind_method ( D_METHOD ( " is_clear_button_enabled " ) , & LineEdit : : is_clear_button_enabled ) ;
2019-08-07 17:09:46 -07:00
ClassDB : : bind_method ( D_METHOD ( " set_shortcut_keys_enabled " , " enable " ) , & LineEdit : : set_shortcut_keys_enabled ) ;
ClassDB : : bind_method ( D_METHOD ( " is_shortcut_keys_enabled " ) , & LineEdit : : is_shortcut_keys_enabled ) ;
2021-10-12 09:43:50 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_middle_mouse_paste_enabled " , " enable " ) , & LineEdit : : set_middle_mouse_paste_enabled ) ;
ClassDB : : bind_method ( D_METHOD ( " is_middle_mouse_paste_enabled " ) , & LineEdit : : is_middle_mouse_paste_enabled ) ;
2019-08-07 17:09:46 -07:00
ClassDB : : bind_method ( D_METHOD ( " set_selecting_enabled " , " enable " ) , & LineEdit : : set_selecting_enabled ) ;
ClassDB : : bind_method ( D_METHOD ( " is_selecting_enabled " ) , & LineEdit : : is_selecting_enabled ) ;
2021-10-21 23:02:46 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_deselect_on_focus_loss_enabled " , " enable " ) , & LineEdit : : set_deselect_on_focus_loss_enabled ) ;
ClassDB : : bind_method ( D_METHOD ( " is_deselect_on_focus_loss_enabled " ) , & LineEdit : : is_deselect_on_focus_loss_enabled ) ;
2023-07-16 20:32:00 -04:00
ClassDB : : bind_method ( D_METHOD ( " set_drag_and_drop_selection_enabled " , " enable " ) , & LineEdit : : set_drag_and_drop_selection_enabled ) ;
ClassDB : : bind_method ( D_METHOD ( " is_drag_and_drop_selection_enabled " ) , & LineEdit : : is_drag_and_drop_selection_enabled ) ;
2019-09-08 22:46:57 -03:00
ClassDB : : bind_method ( D_METHOD ( " set_right_icon " , " icon " ) , & LineEdit : : set_right_icon ) ;
ClassDB : : bind_method ( D_METHOD ( " get_right_icon " ) , & LineEdit : : get_right_icon ) ;
2024-11-22 21:27:36 +07:00
ClassDB : : bind_method ( D_METHOD ( " set_icon_expand_mode " , " mode " ) , & LineEdit : : set_icon_expand_mode ) ;
ClassDB : : bind_method ( D_METHOD ( " get_icon_expand_mode " ) , & LineEdit : : get_icon_expand_mode ) ;
ClassDB : : bind_method ( D_METHOD ( " set_right_icon_scale " , " scale " ) , & LineEdit : : set_right_icon_scale ) ;
ClassDB : : bind_method ( D_METHOD ( " get_right_icon_scale " ) , & LineEdit : : get_right_icon_scale ) ;
2021-10-26 09:40:11 +03:00
ClassDB : : bind_method ( D_METHOD ( " set_flat " , " enabled " ) , & LineEdit : : set_flat ) ;
ClassDB : : bind_method ( D_METHOD ( " is_flat " ) , & LineEdit : : is_flat ) ;
2022-10-16 20:37:35 +08:00
ClassDB : : bind_method ( D_METHOD ( " set_select_all_on_focus " , " enabled " ) , & LineEdit : : set_select_all_on_focus ) ;
ClassDB : : bind_method ( D_METHOD ( " is_select_all_on_focus " ) , & LineEdit : : is_select_all_on_focus ) ;
2017-03-05 16:44:50 +01:00
2018-01-09 16:39:43 +01:00
ADD_SIGNAL ( MethodInfo ( " text_changed " , PropertyInfo ( Variant : : STRING , " new_text " ) ) ) ;
2021-07-06 12:49:27 +02:00
ADD_SIGNAL ( MethodInfo ( " text_change_rejected " , PropertyInfo ( Variant : : STRING , " rejected_substring " ) ) ) ;
2021-06-16 09:43:34 -07:00
ADD_SIGNAL ( MethodInfo ( " text_submitted " , PropertyInfo ( Variant : : STRING , " new_text " ) ) ) ;
2024-09-10 13:43:31 +00:00
ADD_SIGNAL ( MethodInfo ( " editing_toggled " , PropertyInfo ( Variant : : BOOL , " toggled_on " ) ) ) ;
2014-02-09 22:10:30 -03:00
2017-08-20 17:45:01 +02:00
BIND_ENUM_CONSTANT ( MENU_CUT ) ;
BIND_ENUM_CONSTANT ( MENU_COPY ) ;
BIND_ENUM_CONSTANT ( MENU_PASTE ) ;
BIND_ENUM_CONSTANT ( MENU_CLEAR ) ;
BIND_ENUM_CONSTANT ( MENU_SELECT_ALL ) ;
BIND_ENUM_CONSTANT ( MENU_UNDO ) ;
2017-10-29 23:14:33 +00:00
BIND_ENUM_CONSTANT ( MENU_REDO ) ;
2023-01-26 20:59:41 +03:00
BIND_ENUM_CONSTANT ( MENU_SUBMENU_TEXT_DIR ) ;
2020-09-09 16:00:32 +03:00
BIND_ENUM_CONSTANT ( MENU_DIR_INHERITED ) ;
BIND_ENUM_CONSTANT ( MENU_DIR_AUTO ) ;
BIND_ENUM_CONSTANT ( MENU_DIR_LTR ) ;
BIND_ENUM_CONSTANT ( MENU_DIR_RTL ) ;
BIND_ENUM_CONSTANT ( MENU_DISPLAY_UCC ) ;
2023-01-26 20:59:41 +03:00
BIND_ENUM_CONSTANT ( MENU_SUBMENU_INSERT_UCC ) ;
2020-09-09 16:00:32 +03:00
BIND_ENUM_CONSTANT ( MENU_INSERT_LRM ) ;
BIND_ENUM_CONSTANT ( MENU_INSERT_RLM ) ;
BIND_ENUM_CONSTANT ( MENU_INSERT_LRE ) ;
BIND_ENUM_CONSTANT ( MENU_INSERT_RLE ) ;
BIND_ENUM_CONSTANT ( MENU_INSERT_LRO ) ;
BIND_ENUM_CONSTANT ( MENU_INSERT_RLO ) ;
BIND_ENUM_CONSTANT ( MENU_INSERT_PDF ) ;
BIND_ENUM_CONSTANT ( MENU_INSERT_ALM ) ;
BIND_ENUM_CONSTANT ( MENU_INSERT_LRI ) ;
BIND_ENUM_CONSTANT ( MENU_INSERT_RLI ) ;
BIND_ENUM_CONSTANT ( MENU_INSERT_FSI ) ;
BIND_ENUM_CONSTANT ( MENU_INSERT_PDI ) ;
BIND_ENUM_CONSTANT ( MENU_INSERT_ZWJ ) ;
BIND_ENUM_CONSTANT ( MENU_INSERT_ZWNJ ) ;
BIND_ENUM_CONSTANT ( MENU_INSERT_WJ ) ;
BIND_ENUM_CONSTANT ( MENU_INSERT_SHY ) ;
2025-01-02 13:27:35 +02:00
BIND_ENUM_CONSTANT ( MENU_EMOJI_AND_SYMBOL ) ;
2017-08-20 17:45:01 +02:00
BIND_ENUM_CONSTANT ( MENU_MAX ) ;
2016-05-16 20:25:17 -03:00
2022-07-07 14:20:10 -04:00
BIND_ENUM_CONSTANT ( KEYBOARD_TYPE_DEFAULT ) ;
BIND_ENUM_CONSTANT ( KEYBOARD_TYPE_MULTILINE ) ;
BIND_ENUM_CONSTANT ( KEYBOARD_TYPE_NUMBER ) ;
BIND_ENUM_CONSTANT ( KEYBOARD_TYPE_NUMBER_DECIMAL ) ;
BIND_ENUM_CONSTANT ( KEYBOARD_TYPE_PHONE ) ;
BIND_ENUM_CONSTANT ( KEYBOARD_TYPE_EMAIL_ADDRESS ) ;
BIND_ENUM_CONSTANT ( KEYBOARD_TYPE_PASSWORD ) ;
BIND_ENUM_CONSTANT ( KEYBOARD_TYPE_URL ) ;
2024-11-22 21:27:36 +07:00
BIND_ENUM_CONSTANT ( EXPAND_MODE_ORIGINAL_SIZE ) ;
BIND_ENUM_CONSTANT ( EXPAND_MODE_FIT_TO_TEXT ) ;
BIND_ENUM_CONSTANT ( EXPAND_MODE_FIT_TO_LINE_EDIT ) ;
2018-11-08 11:30:02 -03:00
ADD_PROPERTY ( PropertyInfo ( Variant : : STRING , " text " ) , " set_text " , " get_text " ) ;
2022-01-30 17:56:23 +00:00
ADD_PROPERTY ( PropertyInfo ( Variant : : STRING , " placeholder_text " ) , " set_placeholder " , " get_placeholder " ) ;
2021-11-24 20:58:47 -06:00
ADD_PROPERTY ( PropertyInfo ( Variant : : INT , " alignment " , PROPERTY_HINT_ENUM , " Left,Center,Right,Fill " ) , " set_horizontal_alignment " , " get_horizontal_alignment " ) ;
2021-07-06 12:49:27 +02:00
ADD_PROPERTY ( PropertyInfo ( Variant : : INT , " max_length " , PROPERTY_HINT_RANGE , " 0,1000,1,or_greater " ) , " set_max_length " , " get_max_length " ) ;
2018-11-08 11:30:02 -03:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " editable " ) , " set_editable " , " is_editable " ) ;
2025-01-02 23:41:27 +02:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " keep_editing_on_text_submit " ) , " set_keep_editing_on_text_submit " , " is_editing_kept_on_text_submit " ) ;
2021-03-28 19:31:25 +01:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " expand_to_text_length " ) , " set_expand_to_text_length_enabled " , " is_expand_to_text_length_enabled " ) ;
2018-01-12 00:35:12 +02:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " context_menu_enabled " ) , " set_context_menu_enabled " , " is_context_menu_enabled " ) ;
2025-01-02 13:27:35 +02:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " emoji_menu_enabled " ) , " set_emoji_menu_enabled " , " is_emoji_menu_enabled " ) ;
2025-04-22 10:02:07 -05:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " backspace_deletes_composite_character_enabled " ) , " set_backspace_deletes_composite_character_enabled " , " is_backspace_deletes_composite_character_enabled " ) ;
2018-07-26 13:45:38 +02:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " clear_button_enabled " ) , " set_clear_button_enabled " , " is_clear_button_enabled " ) ;
2019-08-07 17:09:46 -07:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " shortcut_keys_enabled " ) , " set_shortcut_keys_enabled " , " is_shortcut_keys_enabled " ) ;
2021-10-12 09:43:50 +02:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " middle_mouse_paste_enabled " ) , " set_middle_mouse_paste_enabled " , " is_middle_mouse_paste_enabled " ) ;
2019-08-07 17:09:46 -07:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " selecting_enabled " ) , " set_selecting_enabled " , " is_selecting_enabled " ) ;
2021-10-21 23:02:46 +02:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " deselect_on_focus_loss_enabled " ) , " set_deselect_on_focus_loss_enabled " , " is_deselect_on_focus_loss_enabled " ) ;
2023-07-16 20:32:00 -04:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " drag_and_drop_selection_enabled " ) , " set_drag_and_drop_selection_enabled " , " is_drag_and_drop_selection_enabled " ) ;
2021-10-26 09:40:11 +03:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " flat " ) , " set_flat " , " is_flat " ) ;
2020-09-09 16:00:32 +03:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " draw_control_chars " ) , " set_draw_control_chars " , " get_draw_control_chars " ) ;
2022-10-16 20:37:35 +08:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " select_all_on_focus " ) , " set_select_all_on_focus " , " is_select_all_on_focus " ) ;
2022-05-09 12:47:10 +03:00
2025-10-02 10:07:25 +03:00
ADD_GROUP ( " Virtual Keyboard " , " virtual_keyboard_ " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " virtual_keyboard_enabled " , PROPERTY_HINT_GROUP_ENABLE ) , " set_virtual_keyboard_enabled " , " is_virtual_keyboard_enabled " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " virtual_keyboard_show_on_focus " ) , " set_virtual_keyboard_show_on_focus " , " get_virtual_keyboard_show_on_focus " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : INT , " virtual_keyboard_type " , PROPERTY_HINT_ENUM , " Default,Multiline,Number,Decimal,Phone,Email,Password,URL " ) , " set_virtual_keyboard_type " , " get_virtual_keyboard_type " ) ;
2017-01-04 01:16:14 -03:00
ADD_GROUP ( " Caret " , " caret_ " ) ;
2021-03-28 19:31:25 +01:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " caret_blink " ) , " set_caret_blink_enabled " , " is_caret_blink_enabled " ) ;
2022-08-13 14:52:35 +02:00
ADD_PROPERTY ( PropertyInfo ( Variant : : FLOAT , " caret_blink_interval " , PROPERTY_HINT_RANGE , " 0.1,10,0.01 " ) , " set_caret_blink_interval " , " get_caret_blink_interval " ) ;
2021-07-06 12:49:27 +02:00
ADD_PROPERTY ( PropertyInfo ( Variant : : INT , " caret_column " , PROPERTY_HINT_RANGE , " 0,1000,1,or_greater " ) , " set_caret_column " , " get_caret_column " ) ;
2021-03-28 19:31:25 +01:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " caret_force_displayed " ) , " set_caret_force_displayed " , " is_caret_force_displayed " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " caret_mid_grapheme " ) , " set_caret_mid_grapheme_enabled " , " is_caret_mid_grapheme_enabled " ) ;
2022-05-09 12:47:10 +03:00
2025-04-20 19:05:59 -07:00
ADD_GROUP ( " Secret " , " secret " ) ;
2025-06-16 19:47:24 +08:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " secret " , PROPERTY_HINT_GROUP_ENABLE ) , " set_secret " , " is_secret " ) ;
2023-10-04 22:41:45 +03:00
ADD_PROPERTY ( PropertyInfo ( Variant : : STRING , " secret_character " ) , " set_secret_character " , " get_secret_character " ) ;
2022-05-09 12:47:10 +03:00
ADD_GROUP ( " BiDi " , " " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : INT , " text_direction " , PROPERTY_HINT_ENUM , " Auto,Left-to-Right,Right-to-Left,Inherited " ) , " set_text_direction " , " get_text_direction " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : STRING , " language " , PROPERTY_HINT_LOCALE_ID , " " ) , " set_language " , " get_language " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : INT , " structured_text_bidi_override " , PROPERTY_HINT_ENUM , " Default,URI,File,Email,List,None,Custom " ) , " set_structured_text_bidi_override " , " get_structured_text_bidi_override " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : ARRAY , " structured_text_bidi_override_options " ) , " set_structured_text_bidi_override_options " , " get_structured_text_bidi_override_options " ) ;
2023-09-08 21:00:10 +02:00
2024-11-22 21:27:36 +07:00
ADD_GROUP ( " Icon " , " " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : OBJECT , " right_icon " , PROPERTY_HINT_RESOURCE_TYPE , " Texture2D " ) , " set_right_icon " , " get_right_icon " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : INT , " icon_expand_mode " , PROPERTY_HINT_ENUM , " Original,Fit to Text,Fit to LineEdit " ) , " set_icon_expand_mode " , " get_icon_expand_mode " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : FLOAT , " right_icon_scale " , PROPERTY_HINT_RANGE , " 0.1,1.0,0.01 " ) , " set_right_icon_scale " , " get_right_icon_scale " ) ;
2023-09-08 21:00:10 +02:00
BIND_THEME_ITEM ( Theme : : DATA_TYPE_STYLEBOX , LineEdit , normal ) ;
BIND_THEME_ITEM ( Theme : : DATA_TYPE_STYLEBOX , LineEdit , read_only ) ;
BIND_THEME_ITEM ( Theme : : DATA_TYPE_STYLEBOX , LineEdit , focus ) ;
BIND_THEME_ITEM ( Theme : : DATA_TYPE_FONT , LineEdit , font ) ;
BIND_THEME_ITEM ( Theme : : DATA_TYPE_FONT_SIZE , LineEdit , font_size ) ;
BIND_THEME_ITEM ( Theme : : DATA_TYPE_COLOR , LineEdit , font_color ) ;
BIND_THEME_ITEM ( Theme : : DATA_TYPE_COLOR , LineEdit , font_uneditable_color ) ;
BIND_THEME_ITEM ( Theme : : DATA_TYPE_COLOR , LineEdit , font_selected_color ) ;
BIND_THEME_ITEM_CUSTOM ( Theme : : DATA_TYPE_CONSTANT , LineEdit , font_outline_size , " outline_size " ) ;
BIND_THEME_ITEM ( Theme : : DATA_TYPE_COLOR , LineEdit , font_outline_color ) ;
BIND_THEME_ITEM ( Theme : : DATA_TYPE_COLOR , LineEdit , font_placeholder_color ) ;
BIND_THEME_ITEM ( Theme : : DATA_TYPE_CONSTANT , LineEdit , caret_width ) ;
BIND_THEME_ITEM ( Theme : : DATA_TYPE_COLOR , LineEdit , caret_color ) ;
BIND_THEME_ITEM ( Theme : : DATA_TYPE_CONSTANT , LineEdit , minimum_character_width ) ;
BIND_THEME_ITEM ( Theme : : DATA_TYPE_COLOR , LineEdit , selection_color ) ;
BIND_THEME_ITEM_CUSTOM ( Theme : : DATA_TYPE_ICON , LineEdit , clear_icon , " clear " ) ;
BIND_THEME_ITEM ( Theme : : DATA_TYPE_COLOR , LineEdit , clear_button_color ) ;
BIND_THEME_ITEM ( Theme : : DATA_TYPE_COLOR , LineEdit , clear_button_color_pressed ) ;
2025-03-06 15:42:10 -03:00
ADD_CLASS_DEPENDENCY ( " PopupMenu " ) ;
2014-02-09 22:10:30 -03:00
}
2022-03-04 09:18:44 +01:00
LineEdit : : LineEdit ( const String & p_placeholder ) {
2021-07-16 18:36:05 -03:00
text_rid = TS - > create_shaped_text ( ) ;
_create_undo_state ( ) ;
deselect ( ) ;
set_focus_mode ( FOCUS_ALL ) ;
set_default_cursor_shape ( CURSOR_IBEAM ) ;
set_mouse_filter ( MOUSE_FILTER_STOP ) ;
2022-01-11 15:59:52 +02:00
set_process_unhandled_key_input ( true ) ;
2021-07-16 18:36:05 -03:00
set_caret_blink_enabled ( false ) ;
2022-03-04 09:18:44 +01:00
set_placeholder ( p_placeholder ) ;
2023-01-21 12:25:29 +01:00
set_editable ( true ) ; // Initialize to opposite first, so we get past the early-out in set_editable.
2014-02-09 22:10:30 -03:00
}
LineEdit : : ~ LineEdit ( ) {
2022-02-13 14:41:29 +02:00
TS - > free_rid ( text_rid ) ;
2014-02-09 22:10:30 -03:00
}