summaryrefslogtreecommitdiff
path: root/scene/gui/line_edit.h
blob: e0a079b623d3cc17d23bd63018a03bf7b06a9a89 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
/*************************************************************************/
/*  line_edit.h                                                          */
/*************************************************************************/
/*                       This file is part of:                           */
/*                           GODOT ENGINE                                */
/*                      https://godotengine.org                          */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur.                 */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md).   */
/*                                                                       */
/* 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.                */
/*************************************************************************/

#ifndef LINE_EDIT_H
#define LINE_EDIT_H

#include "scene/gui/control.h"
#include "scene/gui/popup_menu.h"

class LineEdit : public Control {
	GDCLASS(LineEdit, Control);

public:
	enum MenuItems {
		MENU_CUT,
		MENU_COPY,
		MENU_PASTE,
		MENU_CLEAR,
		MENU_SELECT_ALL,
		MENU_UNDO,
		MENU_REDO,
		MENU_DIR_INHERITED,
		MENU_DIR_AUTO,
		MENU_DIR_LTR,
		MENU_DIR_RTL,
		MENU_DISPLAY_UCC,
		MENU_INSERT_LRM,
		MENU_INSERT_RLM,
		MENU_INSERT_LRE,
		MENU_INSERT_RLE,
		MENU_INSERT_LRO,
		MENU_INSERT_RLO,
		MENU_INSERT_PDF,
		MENU_INSERT_ALM,
		MENU_INSERT_LRI,
		MENU_INSERT_RLI,
		MENU_INSERT_FSI,
		MENU_INSERT_PDI,
		MENU_INSERT_ZWJ,
		MENU_INSERT_ZWNJ,
		MENU_INSERT_WJ,
		MENU_INSERT_SHY,
		MENU_MAX
	};

	enum VirtualKeyboardType {
		KEYBOARD_TYPE_DEFAULT,
		KEYBOARD_TYPE_MULTILINE,
		KEYBOARD_TYPE_NUMBER,
		KEYBOARD_TYPE_NUMBER_DECIMAL,
		KEYBOARD_TYPE_PHONE,
		KEYBOARD_TYPE_EMAIL_ADDRESS,
		KEYBOARD_TYPE_PASSWORD,
		KEYBOARD_TYPE_URL
	};

private:
	HorizontalAlignment alignment = HORIZONTAL_ALIGNMENT_LEFT;

	bool editable = false;
	bool pass = false;
	bool text_changed_dirty = false;

	bool alt_start = false;
	uint32_t alt_code = 0;

	String undo_text;
	String text;
	String placeholder;
	String placeholder_translated;
	String secret_character = U"•";
	String ime_text;
	Point2 ime_selection;

	RID text_rid;
	float full_width = 0.0;

	bool selecting_enabled = true;
	bool deselect_on_focus_loss_enabled = true;

	bool context_menu_enabled = true;
	PopupMenu *menu = nullptr;
	PopupMenu *menu_dir = nullptr;
	PopupMenu *menu_ctl = nullptr;

	bool caret_mid_grapheme_enabled = true;

	int caret_column = 0;
	float scroll_offset = 0.0;
	int max_length = 0; // 0 for no maximum.

	String language;
	TextDirection text_direction = TEXT_DIRECTION_AUTO;
	TextDirection input_direction = TEXT_DIRECTION_LTR;
	TextServer::StructuredTextParser st_parser = TextServer::STRUCTURED_TEXT_DEFAULT;
	Array st_args;
	bool draw_control_chars = false;

	bool expand_to_text_length = false;
	bool window_has_focus = true;

	bool clear_button_enabled = false;

	bool shortcut_keys_enabled = true;

	bool virtual_keyboard_enabled = true;
	VirtualKeyboardType virtual_keyboard_type = KEYBOARD_TYPE_DEFAULT;

	bool middle_mouse_paste_enabled = true;

	bool drag_action = false;
	bool drag_caret_force_displayed = false;

	Ref<Texture2D> right_icon;
	bool flat = false;

	struct Selection {
		int begin = 0;
		int end = 0;
		int start_column = 0;
		bool enabled = false;
		bool creating = false;
		bool double_click = false;
		bool drag_attempt = false;
	} selection;

	struct TextOperation {
		int caret_column = 0;
		float scroll_offset = 0.0;
		String text;
	};
	List<TextOperation> undo_stack;
	List<TextOperation>::Element *undo_stack_pos = nullptr;

	struct ClearButtonStatus {
		bool press_attempt = false;
		bool pressing_inside = false;
	} clear_button_status;

	uint64_t last_dblclk = 0;
	Vector2 last_dblclk_pos;

	bool caret_blink_enabled = false;
	bool caret_force_displayed = false;
	bool draw_caret = true;
	float caret_blink_interval = 0.65;
	double caret_blink_timer = 0.0;
	bool caret_blinking = false;

	bool pending_select_all_on_focus = false;
	bool select_all_on_focus = false;

	struct ThemeCache {
		Ref<StyleBox> normal;
		Ref<StyleBox> read_only;
		Ref<StyleBox> focus;

		Ref<Font> font;
		int font_size = 0;
		Color font_color;
		Color font_uneditable_color;
		Color font_selected_color;
		int font_outline_size;
		Color font_outline_color;
		Color font_placeholder_color;
		int caret_width = 0;
		Color caret_color;
		int minimum_character_width = 0;
		Color selection_color;

		Ref<Texture2D> clear_icon;
		Color clear_button_color;
		Color clear_button_color_pressed;

		float base_scale = 1.0;
	} theme_cache;

	void _clear_undo_stack();
	void _clear_redo();
	void _create_undo_state();

	Key _get_menu_action_accelerator(const String &p_action);

	void _shape();
	void _fit_to_width();
	void _text_changed();
	void _emit_text_change();

	void shift_selection_check_pre(bool);
	void shift_selection_check_post(bool);

	void selection_fill_at_caret();
	void set_scroll_offset(float p_pos);
	float get_scroll_offset() const;

	void set_caret_at_pixel_pos(int p_x);
	Vector2 get_caret_pixel_pos();

	void _reset_caret_blink_timer();
	void _toggle_draw_caret();

	void clear_internal();

	void _editor_settings_changed();

	void _swap_current_input_direction();
	void _move_caret_left(bool p_select, bool p_move_by_word = false);
	void _move_caret_right(bool p_select, bool p_move_by_word = false);
	void _move_caret_start(bool p_select);
	void _move_caret_end(bool p_select);
	void _backspace(bool p_word = false, bool p_all_to_left = false);
	void _delete(bool p_word = false, bool p_all_to_right = false);

	void _ensure_menu();

protected:
	bool _is_over_clear_button(const Point2 &p_pos) const;
	virtual void _update_theme_item_cache() override;
	void _notification(int p_what);
	static void _bind_methods();
	virtual void unhandled_key_input(const Ref<InputEvent> &p_event) override;
	virtual void gui_input(const Ref<InputEvent> &p_event) override;

	void _validate_property(PropertyInfo &p_property) const;

public:
	void set_horizontal_alignment(HorizontalAlignment p_alignment);
	HorizontalAlignment get_horizontal_alignment() const;

	virtual Variant get_drag_data(const Point2 &p_point) override;
	virtual bool can_drop_data(const Point2 &p_point, const Variant &p_data) const override;
	virtual void drop_data(const Point2 &p_point, const Variant &p_data) override;

	virtual CursorShape get_cursor_shape(const Point2 &p_pos) const override;

	void menu_option(int p_option);
	void set_context_menu_enabled(bool p_enable);
	bool is_context_menu_enabled();
	PopupMenu *get_menu() const;
	bool is_menu_visible() const;

	void select(int p_from = 0, int p_to = -1);
	void select_all();
	void selection_delete();
	void deselect();
	bool has_selection() const;
	int get_selection_from_column() const;
	int get_selection_to_column() const;

	void delete_char();
	void delete_text(int p_from_column, int p_to_column);

	void set_text(String p_text);
	String get_text() const;

	void set_text_direction(TextDirection p_text_direction);
	TextDirection get_text_direction() const;

	void set_language(const String &p_language);
	String get_language() const;

	void set_draw_control_chars(bool p_draw_control_chars);
	bool get_draw_control_chars() const;

	void set_structured_text_bidi_override(TextServer::StructuredTextParser p_parser);
	TextServer::StructuredTextParser get_structured_text_bidi_override() const;

	void set_structured_text_bidi_override_options(Array p_args);
	Array get_structured_text_bidi_override_options() const;

	void set_placeholder(String p_text);
	String get_placeholder() const;

	void set_caret_column(int p_column);
	int get_caret_column() const;

	void set_max_length(int p_max_length);
	int get_max_length() const;

	void insert_text_at_caret(String p_text);
	void clear();

	void set_caret_mid_grapheme_enabled(const bool p_enabled);
	bool is_caret_mid_grapheme_enabled() const;

	bool is_caret_blink_enabled() const;
	void set_caret_blink_enabled(const bool p_enabled);

	float get_caret_blink_interval() const;
	void set_caret_blink_interval(const float p_interval);

	void set_caret_force_displayed(const bool p_enabled);
	bool is_caret_force_displayed() const;

	void copy_text();
	void cut_text();
	void paste_text();
	bool has_undo() const;
	bool has_redo() const;
	void undo();
	void redo();

	void set_editable(bool p_editable);
	bool is_editable() const;

	void set_secret(bool p_secret);
	bool is_secret() const;

	void set_secret_character(const String &p_string);
	String get_secret_character() const;

	virtual Size2 get_minimum_size() const override;

	void set_expand_to_text_length_enabled(bool p_enabled);
	bool is_expand_to_text_length_enabled() const;

	void set_clear_button_enabled(bool p_enabled);
	bool is_clear_button_enabled() const;

	void set_shortcut_keys_enabled(bool p_enabled);
	bool is_shortcut_keys_enabled() const;

	void set_virtual_keyboard_enabled(bool p_enable);
	bool is_virtual_keyboard_enabled() const;

	void set_virtual_keyboard_type(VirtualKeyboardType p_type);
	VirtualKeyboardType get_virtual_keyboard_type() const;

	void set_middle_mouse_paste_enabled(bool p_enabled);
	bool is_middle_mouse_paste_enabled() const;

	void set_selecting_enabled(bool p_enabled);
	bool is_selecting_enabled() const;

	void set_deselect_on_focus_loss_enabled(const bool p_enabled);
	bool is_deselect_on_focus_loss_enabled() const;

	void set_right_icon(const Ref<Texture2D> &p_icon);
	Ref<Texture2D> get_right_icon();

	void set_flat(bool p_enabled);
	bool is_flat() const;

	void set_select_all_on_focus(bool p_enabled);
	bool is_select_all_on_focus() const;
	void clear_pending_select_all_on_focus(); // For other controls, e.g. SpinBox.

	virtual bool is_text_field() const override;

	void show_virtual_keyboard();

	LineEdit(const String &p_placeholder = String());
	~LineEdit();
};

VARIANT_ENUM_CAST(LineEdit::MenuItems);
VARIANT_ENUM_CAST(LineEdit::VirtualKeyboardType);

#endif // LINE_EDIT_H