From e8a435c8cdc5778ebae5e66d983a7bc720f81e85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Rutkowski?= Date: Thu, 26 Jul 2018 13:45:38 +0200 Subject: Add clear text button to LineEdit - Add pressed state to clear button - Enable clear button on all inputs with search icon - Remove duplicate clear buttons - Fix rendering of icon for center and right alignments - Add clear button to more search fields - Add clear icon to default theme - Add method to control enabled state of clear button - Add property to enable clear button from inspector --- scene/gui/line_edit.cpp | 80 +++++++++++++++++++++++++++++++++++++++++++++---- scene/gui/line_edit.h | 14 +++++++++ 2 files changed, 89 insertions(+), 5 deletions(-) (limited to 'scene/gui') diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp index 6258f32bf3..e723262c85 100644 --- a/scene/gui/line_edit.cpp +++ b/scene/gui/line_edit.cpp @@ -66,6 +66,12 @@ void LineEdit::_gui_input(Ref p_event) { _reset_caret_blink_timer(); if (b->is_pressed()) { + if (!text.empty() && is_editable() && _is_over_clear_button(b->get_position())) { + clear_button_status.press_attempt = true; + clear_button_status.pressing_inside = true; + return; + } + shift_selection_check_pre(b->get_shift()); set_cursor_at_pixel_pos(b->get_position().x); @@ -102,6 +108,15 @@ void LineEdit::_gui_input(Ref p_event) { } else { + if (!text.empty() && is_editable() && clear_button_enabled) { + 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; + } + } + if ((!selection.creating) && (!selection.doubleclick)) { deselect(); } @@ -119,6 +134,14 @@ void LineEdit::_gui_input(Ref p_event) { if (m.is_valid()) { + if (!text.empty() && is_editable() && clear_button_enabled) { + 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) { + update(); + } + } + if (m->get_button_mask() & BUTTON_LEFT) { if (selection.creating) { @@ -550,6 +573,25 @@ void LineEdit::drop_data(const Point2 &p_point, const Variant &p_data) { } } +Control::CursorShape LineEdit::get_cursor_shape(const Point2 &p_pos) const { + if (!text.empty() && is_editable() && _is_over_clear_button(p_pos)) { + 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; + } + Ref icon = Control::get_icon("clear"); + int x_ofs = get_stylebox("normal")->get_offset().x; + if (p_pos.x > get_size().width - icon->get_width() - x_ofs) { + return true; + } + return false; +} + void LineEdit::_notification(int p_what) { switch (p_what) { @@ -657,10 +699,26 @@ void LineEdit::_notification(int p_what) { font_color.a *= placeholder_alpha; font_color.a *= disabled_alpha; - if (has_icon("right_icon")) { - Ref r_icon = Control::get_icon("right_icon"); - ofs_max -= r_icon->get_width(); - r_icon->draw(ci, Point2(width - r_icon->get_width() - x_ofs, height / 2 - r_icon->get_height() / 2), Color(1, 1, 1, disabled_alpha * .9)); + bool display_clear_icon = !using_placeholder && is_editable() && clear_button_enabled; + if (has_icon("right_icon") || display_clear_icon) { + Ref r_icon = Control::get_icon(display_clear_icon ? "clear" : "right_icon"); + Color color_icon(1, 1, 1, disabled_alpha * .9); + if (display_clear_icon) { + if (clear_button_status.press_attempt && clear_button_status.pressing_inside) { + color_icon = get_color("clear_button_color_pressed"); + } else { + color_icon = get_color("clear_button_color"); + } + } + r_icon->draw(ci, Point2(width - r_icon->get_width() - style->get_margin(MARGIN_RIGHT), height / 2 - r_icon->get_height() / 2), color_icon); + + if (align == ALIGN_CENTER) { + if (window_pos == 0) { + x_ofs = MAX(style->get_margin(MARGIN_LEFT), int(size.width - cached_text_width - r_icon->get_width() - style->get_margin(MARGIN_RIGHT) * 2) / 2); + } + } else { + x_ofs = MAX(style->get_margin(MARGIN_LEFT), x_ofs - r_icon->get_width() - style->get_margin(MARGIN_RIGHT)); + } } int caret_height = font->get_height() > y_area ? y_area : font->get_height(); @@ -1385,10 +1443,18 @@ void LineEdit::set_expand_to_text_length(bool p_enabled) { } bool LineEdit::get_expand_to_text_length() const { - return expand_to_text_length; } +void LineEdit::set_clear_button_enabled(bool p_enabled) { + clear_button_enabled = p_enabled; + update(); +} + +bool LineEdit::is_clear_button_enabled() const { + return clear_button_enabled; +} + void LineEdit::_ime_text_callback(void *p_self, String p_text, Point2 p_selection) { LineEdit *self = (LineEdit *)p_self; self->ime_text = p_text; @@ -1481,6 +1547,8 @@ void LineEdit::_bind_methods() { ClassDB::bind_method(D_METHOD("get_menu"), &LineEdit::get_menu); 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); + 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); ADD_SIGNAL(MethodInfo("text_changed", PropertyInfo(Variant::STRING, "new_text"))); ADD_SIGNAL(MethodInfo("text_entered", PropertyInfo(Variant::STRING, "new_text"))); @@ -1508,6 +1576,7 @@ void LineEdit::_bind_methods() { ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "expand_to_text_length"), "set_expand_to_text_length", "get_expand_to_text_length"); ADD_PROPERTY(PropertyInfo(Variant::INT, "focus_mode", PROPERTY_HINT_ENUM, "None,Click,All"), "set_focus_mode", "get_focus_mode"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "context_menu_enabled"), "set_context_menu_enabled", "is_context_menu_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "clear_button_enabled"), "set_clear_button_enabled", "is_clear_button_enabled"); ADD_GROUP("Placeholder", "placeholder_"); ADD_PROPERTYNZ(PropertyInfo(Variant::STRING, "placeholder_text"), "set_placeholder", "get_placeholder"); ADD_PROPERTYNZ(PropertyInfo(Variant::REAL, "placeholder_alpha", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_placeholder_alpha", "get_placeholder_alpha"); @@ -1532,6 +1601,7 @@ LineEdit::LineEdit() { secret_character = "*"; text_changed_dirty = false; placeholder_alpha = 0.6; + clear_button_enabled = false; deselect(); set_focus_mode(FOCUS_ALL); diff --git a/scene/gui/line_edit.h b/scene/gui/line_edit.h index e9314ba8dd..d3cdb41903 100644 --- a/scene/gui/line_edit.h +++ b/scene/gui/line_edit.h @@ -87,6 +87,8 @@ private: int cached_width; int cached_placeholder_width; + bool clear_button_enabled; + struct Selection { int begin; @@ -105,6 +107,13 @@ private: List undo_stack; List::Element *undo_stack_pos; + struct ClearButtonStatus { + bool press_attempt; + bool pressing_inside; + } clear_button_status; + + bool _is_over_clear_button(const Point2 &p_pos) const; + void _clear_undo_stack(); void _clear_redo(); void _create_undo_state(); @@ -150,6 +159,8 @@ public: virtual bool can_drop_data(const Point2 &p_point, const Variant &p_data) const; virtual void drop_data(const Point2 &p_point, const Variant &p_data); + virtual CursorShape get_cursor_shape(const Point2 &p_pos) const; + void menu_option(int p_option); void set_context_menu_enabled(bool p_enable); bool is_context_menu_enabled(); @@ -201,6 +212,9 @@ public: void set_expand_to_text_length(bool p_enabled); bool get_expand_to_text_length() const; + void set_clear_button_enabled(bool p_enabled); + bool is_clear_button_enabled() const; + virtual bool is_text_field() const; LineEdit(); ~LineEdit(); -- cgit v1.2.3