diff options
author | ConteZero <one@contezero.com> | 2021-10-28 09:07:18 +0200 |
---|---|---|
committer | ConteZero <one@contezero.com> | 2021-11-15 17:10:56 +0100 |
commit | 2b1787b446edb31e4e6812552e556a4df412fe27 (patch) | |
tree | f6e42d52f06a8e0e6bafdd20a54fd03105193b3c /scene | |
parent | b6c002f32d3ee01f227dbaaf15caf5ce378f2fb6 (diff) |
Fix drag and drop on LineEdit
Diffstat (limited to 'scene')
-rw-r--r-- | scene/gui/control.cpp | 5 | ||||
-rw-r--r-- | scene/gui/control.h | 1 | ||||
-rw-r--r-- | scene/gui/line_edit.cpp | 80 | ||||
-rw-r--r-- | scene/gui/line_edit.h | 3 | ||||
-rw-r--r-- | scene/main/viewport.cpp | 11 | ||||
-rw-r--r-- | scene/main/viewport.h | 2 |
6 files changed, 89 insertions, 13 deletions
diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index 582c8e5860..fdf10e2f42 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -810,6 +810,10 @@ void Control::set_drag_preview(Control *p_control) { get_viewport()->_gui_set_drag_preview(this, p_control); } +bool Control::is_drag_successful() const { + return is_inside_tree() && get_viewport()->gui_is_drag_successful(); +} + void Control::_call_gui_input(const Ref<InputEvent> &p_event) { emit_signal(SceneStringNames::get_singleton()->gui_input, p_event); //signal should be first, so it's possible to override an event (and then accept it) if (!is_inside_tree() || get_viewport()->is_input_handled()) { @@ -2964,6 +2968,7 @@ void Control::_bind_methods() { ClassDB::bind_method(D_METHOD("set_drag_forwarding", "target"), &Control::set_drag_forwarding); ClassDB::bind_method(D_METHOD("set_drag_preview", "control"), &Control::set_drag_preview); + ClassDB::bind_method(D_METHOD("is_drag_successful"), &Control::is_drag_successful); ClassDB::bind_method(D_METHOD("warp_mouse", "to_position"), &Control::warp_mouse); diff --git a/scene/gui/control.h b/scene/gui/control.h index 02ab336ef0..2eb714eae6 100644 --- a/scene/gui/control.h +++ b/scene/gui/control.h @@ -357,6 +357,7 @@ public: virtual void drop_data(const Point2 &p_point, const Variant &p_data); void set_drag_preview(Control *p_control); void force_drag(const Variant &p_data, Control *p_control); + bool is_drag_successful() const; void set_custom_minimum_size(const Size2 &p_custom); Size2 get_custom_minimum_size() const; diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp index 124d5c7821..4a85cf2c45 100644 --- a/scene/gui/line_edit.cpp +++ b/scene/gui/line_edit.cpp @@ -268,7 +268,9 @@ void LineEdit::gui_input(const Ref<InputEvent> &p_event) { return; } - shift_selection_check_pre(b->is_shift_pressed()); + if (b->is_shift_pressed()) { + shift_selection_check_pre(true); + } set_caret_at_pixel_pos(b->get_position().x); @@ -345,6 +347,9 @@ void LineEdit::gui_input(const Ref<InputEvent> &p_event) { } selection.creating = false; selection.double_click = false; + if (!drag_action) { + selection.drag_attempt = false; + } show_virtual_keyboard(); } @@ -369,6 +374,11 @@ void LineEdit::gui_input(const Ref<InputEvent> &p_event) { selection_fill_at_caret(); } } + + 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); + } } Ref<InputEventKey> k = p_event; @@ -569,21 +579,44 @@ bool LineEdit::can_drop_data(const Point2 &p_point, const Variant &p_data) const return drop_override; } - return p_data.get_type() == Variant::STRING; + return is_editable() && p_data.get_type() == Variant::STRING; } void LineEdit::drop_data(const Point2 &p_point, const Variant &p_data) { Control::drop_data(p_point, p_data); - if (p_data.get_type() == Variant::STRING) { + if (p_data.get_type() == Variant::STRING && is_editable()) { set_caret_at_pixel_pos(p_point.x); + int caret_column_tmp = caret_column; + if (selection.drag_attempt) { + selection.drag_attempt = false; + if (caret_column < selection.begin || caret_column > selection.end) { + if (caret_column_tmp > selection.end) { + caret_column_tmp = caret_column_tmp - (selection.end - selection.begin); + } + selection_delete(); - text = text.left(selection.begin) + text.substr(selection.end); - _shape(); - - insert_text_at_caret(p_data); - selection.begin = caret_column - (selection.end - selection.begin); - selection.end = caret_column; + 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); + grab_focus(); + } else { + insert_text_at_caret(p_data); + grab_focus(); + } + select(caret_column_tmp, caret_column); + if (!text_changed_dirty) { + if (is_inside_tree()) { + MessageQueue::get_singleton()->push_call(this, "_text_changed"); + } + text_changed_dirty = true; + } + update(); } } @@ -803,7 +836,7 @@ void LineEdit::_notification(int p_what) { // Draw carets. ofs.x = x_ofs + scroll_offset; - if (draw_caret) { + if (draw_caret || drag_caret_force_displayed) { if (ime_text.length() == 0) { // Normal caret. CaretInfo caret = TS->shaped_text_get_carets(text_rid, caret_column); @@ -921,7 +954,7 @@ void LineEdit::_notification(int p_what) { DisplayServer::get_singleton()->virtual_keyboard_hide(); } - if (deselect_on_focus_loss_enabled) { + if (deselect_on_focus_loss_enabled && !selection.drag_attempt) { deselect(); } } break; @@ -935,6 +968,25 @@ void LineEdit::_notification(int p_what) { update(); } } break; + case Control::NOTIFICATION_DRAG_BEGIN: { + drag_action = true; + } break; + case Control::NOTIFICATION_DRAG_END: { + if (is_drag_successful()) { + if (selection.drag_attempt) { + selection.drag_attempt = false; + if (is_editable()) { + selection_delete(); + } else if (deselect_on_focus_loss_enabled) { + deselect(); + } + } + } else { + selection.drag_attempt = false; + } + drag_action = false; + drag_caret_force_displayed = false; + } break; } } @@ -999,6 +1051,9 @@ void LineEdit::undo() { } else if (undo_stack_pos == undo_stack.front()) { return; } + + deselect(); + undo_stack_pos = undo_stack_pos->prev(); TextOperation op = undo_stack_pos->get(); text = op.text; @@ -1020,6 +1075,9 @@ void LineEdit::redo() { if (undo_stack_pos == undo_stack.back()) { return; } + + deselect(); + undo_stack_pos = undo_stack_pos->next(); TextOperation op = undo_stack_pos->get(); text = op.text; diff --git a/scene/gui/line_edit.h b/scene/gui/line_edit.h index 134d5f8f76..221dd9eb2e 100644 --- a/scene/gui/line_edit.h +++ b/scene/gui/line_edit.h @@ -129,6 +129,9 @@ private: bool middle_mouse_paste_enabled = true; + bool drag_action = false; + bool drag_caret_force_displayed = false; + Ref<Texture2D> right_icon; bool flat = false; diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index 1ecc3c762a..48a672b310 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -1515,8 +1515,9 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { if (gui.drag_data.get_type() != Variant::NIL && mb->get_button_index() == MouseButton::LEFT) { // Alternate drop use (when using force_drag(), as proposed by #5342). + gui.drag_successful = false; if (gui.mouse_focus) { - _gui_drop(gui.mouse_focus, pos, false); + gui.drag_successful = _gui_drop(gui.mouse_focus, pos, false); } gui.drag_data = Variant(); @@ -1534,8 +1535,9 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { _gui_cancel_tooltip(); } else { if (gui.drag_data.get_type() != Variant::NIL && mb->get_button_index() == MouseButton::LEFT) { + gui.drag_successful = false; if (gui.drag_mouse_over) { - _gui_drop(gui.drag_mouse_over, gui.drag_mouse_over_pos, false); + gui.drag_successful = _gui_drop(gui.drag_mouse_over, gui.drag_mouse_over_pos, false); } Control *drag_preview = _gui_get_drag_preview(); @@ -2895,6 +2897,10 @@ bool Viewport::gui_is_dragging() const { return gui.dragging; } +bool Viewport::gui_is_drag_successful() const { + return gui.drag_successful; +} + void Viewport::set_input_as_handled() { _drop_physics_mouseover(); @@ -3534,6 +3540,7 @@ void Viewport::_bind_methods() { ClassDB::bind_method(D_METHOD("gui_get_drag_data"), &Viewport::gui_get_drag_data); ClassDB::bind_method(D_METHOD("gui_is_dragging"), &Viewport::gui_is_dragging); + ClassDB::bind_method(D_METHOD("gui_is_drag_successful"), &Viewport::gui_is_drag_successful); ClassDB::bind_method(D_METHOD("set_disable_input", "disable"), &Viewport::set_disable_input); ClassDB::bind_method(D_METHOD("is_input_disabled"), &Viewport::is_input_disabled); diff --git a/scene/main/viewport.h b/scene/main/viewport.h index 5320aea02a..11b76b32eb 100644 --- a/scene/main/viewport.h +++ b/scene/main/viewport.h @@ -348,6 +348,7 @@ private: List<Control *> roots; int canvas_sort_index = 0; //for sorting items with canvas as root bool dragging = false; + bool drag_successful = false; bool embed_subwindows_hint = false; bool embedding_subwindows = false; @@ -556,6 +557,7 @@ public: bool is_handling_input_locally() const; bool gui_is_dragging() const; + bool gui_is_drag_successful() const; Control *gui_find_control(const Point2 &p_global); |