diff options
Diffstat (limited to 'scene/gui')
-rw-r--r-- | scene/gui/base_button.cpp | 19 | ||||
-rw-r--r-- | scene/gui/base_button.h | 5 | ||||
-rw-r--r-- | scene/gui/code_edit.cpp | 19 | ||||
-rw-r--r-- | scene/gui/code_edit.h | 1 | ||||
-rw-r--r-- | scene/gui/color_mode.cpp | 8 | ||||
-rw-r--r-- | scene/gui/flow_container.cpp | 41 | ||||
-rw-r--r-- | scene/gui/flow_container.h | 13 | ||||
-rw-r--r-- | scene/gui/scroll_container.cpp | 107 | ||||
-rw-r--r-- | scene/gui/tab_container.cpp | 8 | ||||
-rw-r--r-- | scene/gui/tab_container.h | 2 | ||||
-rw-r--r-- | scene/gui/text_edit.cpp | 30 | ||||
-rw-r--r-- | scene/gui/text_edit.h | 1 |
12 files changed, 198 insertions, 56 deletions
diff --git a/scene/gui/base_button.cpp b/scene/gui/base_button.cpp index 552345e4fe..1082fc4d6d 100644 --- a/scene/gui/base_button.cpp +++ b/scene/gui/base_button.cpp @@ -127,6 +127,7 @@ void BaseButton::_notification(int p_what) { status.hovering = false; status.press_attempt = false; status.pressing_inside = false; + status.shortcut_press = false; } break; } } @@ -160,6 +161,7 @@ void BaseButton::on_action_event(Ref<InputEvent> p_event) { if (action_mode == ACTION_MODE_BUTTON_PRESS) { status.press_attempt = false; status.pressing_inside = false; + status.shortcut_press = false; } status.pressed = !status.pressed; _unpress_group(); @@ -185,6 +187,7 @@ void BaseButton::on_action_event(Ref<InputEvent> p_event) { } status.press_attempt = false; status.pressing_inside = false; + status.shortcut_press = false; emit_signal(SNAME("button_up")); } @@ -209,6 +212,7 @@ void BaseButton::set_disabled(bool p_disabled) { } status.press_attempt = false; status.pressing_inside = false; + status.shortcut_press = false; } queue_redraw(); } @@ -284,7 +288,7 @@ BaseButton::DrawMode BaseButton::get_draw_mode() const { pressing = status.pressed; } - if (pressing) { + if ((shortcut_feedback || !status.shortcut_press) && pressing) { return DRAW_PRESSED; } else { return DRAW_NORMAL; @@ -350,6 +354,7 @@ void BaseButton::shortcut_input(const Ref<InputEvent> &p_event) { ERR_FAIL_COND(p_event.is_null()); if (!is_disabled() && is_visible_in_tree() && !p_event->is_echo() && shortcut.is_valid() && shortcut->matches_event(p_event)) { + status.shortcut_press = true; on_action_event(p_event); accept_event(); } @@ -389,6 +394,14 @@ bool BaseButton::_was_pressed_by_mouse() const { return was_mouse_pressed; } +void BaseButton::set_shortcut_feedback(bool p_feedback) { + shortcut_feedback = p_feedback; +} + +bool BaseButton::is_shortcut_feedback() const { + return shortcut_feedback; +} + void BaseButton::_bind_methods() { ClassDB::bind_method(D_METHOD("set_pressed", "pressed"), &BaseButton::set_pressed); ClassDB::bind_method(D_METHOD("is_pressed"), &BaseButton::is_pressed); @@ -414,6 +427,9 @@ void BaseButton::_bind_methods() { ClassDB::bind_method(D_METHOD("set_button_group", "button_group"), &BaseButton::set_button_group); ClassDB::bind_method(D_METHOD("get_button_group"), &BaseButton::get_button_group); + ClassDB::bind_method(D_METHOD("set_shortcut_feedback", "enabled"), &BaseButton::set_shortcut_feedback); + ClassDB::bind_method(D_METHOD("is_shortcut_feedback"), &BaseButton::is_shortcut_feedback); + GDVIRTUAL_BIND(_pressed); GDVIRTUAL_BIND(_toggled, "button_pressed"); @@ -430,6 +446,7 @@ void BaseButton::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "button_mask", PROPERTY_HINT_FLAGS, "Mouse Left, Mouse Right, Mouse Middle"), "set_button_mask", "get_button_mask"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "keep_pressed_outside"), "set_keep_pressed_outside", "is_keep_pressed_outside"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shortcut", PROPERTY_HINT_RESOURCE_TYPE, "Shortcut"), "set_shortcut", "get_shortcut"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shortcut_feedback"), "set_shortcut_feedback", "is_shortcut_feedback"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "button_group", PROPERTY_HINT_RESOURCE_TYPE, "ButtonGroup"), "set_button_group", "get_button_group"); BIND_ENUM_CONSTANT(DRAW_NORMAL); diff --git a/scene/gui/base_button.h b/scene/gui/base_button.h index 7839239800..3acf535f54 100644 --- a/scene/gui/base_button.h +++ b/scene/gui/base_button.h @@ -53,6 +53,7 @@ private: bool keep_pressed_outside = false; Ref<Shortcut> shortcut; ObjectID shortcut_context; + bool shortcut_feedback = true; ActionMode action_mode = ACTION_MODE_BUTTON_RELEASE; struct Status { @@ -60,6 +61,7 @@ private: bool hovering = false; bool press_attempt = false; bool pressing_inside = false; + bool shortcut_press = false; bool disabled = false; @@ -131,6 +133,9 @@ public: void set_button_group(const Ref<ButtonGroup> &p_group); Ref<ButtonGroup> get_button_group() const; + void set_shortcut_feedback(bool p_feedback); + bool is_shortcut_feedback() const; + BaseButton(); ~BaseButton(); }; diff --git a/scene/gui/code_edit.cpp b/scene/gui/code_edit.cpp index f61fa29a33..5f8f25154c 100644 --- a/scene/gui/code_edit.cpp +++ b/scene/gui/code_edit.cpp @@ -138,7 +138,7 @@ void CodeEdit::_notification(int p_what) { code_completion_scroll_rect.position = code_completion_rect.position + Vector2(code_completion_rect.size.width, 0); code_completion_scroll_rect.size = Vector2(scroll_width, code_completion_rect.size.height); - code_completion_line_ofs = CLAMP(code_completion_current_selected - lines / 2, 0, code_completion_options_count - lines); + code_completion_line_ofs = CLAMP((code_completion_force_item_center < 0 ? code_completion_current_selected : code_completion_force_item_center) - lines / 2, 0, code_completion_options_count - lines); RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(code_completion_rect.position.x, code_completion_rect.position.y + (code_completion_current_selected - code_completion_line_ofs) * row_height), Size2(code_completion_rect.size.width, row_height)), code_completion_selected_color); for (int i = 0; i < lines; i++) { @@ -281,16 +281,22 @@ void CodeEdit::gui_input(const Ref<InputEvent> &p_gui_input) { case MouseButton::WHEEL_UP: { if (code_completion_current_selected > 0) { code_completion_current_selected--; + code_completion_force_item_center = -1; queue_redraw(); } } break; case MouseButton::WHEEL_DOWN: { if (code_completion_current_selected < code_completion_options.size() - 1) { code_completion_current_selected++; + code_completion_force_item_center = -1; queue_redraw(); } } break; case MouseButton::LEFT: { + if (code_completion_force_item_center == -1) { + code_completion_force_item_center = code_completion_current_selected; + } + code_completion_current_selected = CLAMP(code_completion_line_ofs + (mb->get_position().y - code_completion_rect.position.y) / get_line_height(), 0, code_completion_options.size() - 1); if (mb->is_double_click()) { confirm_code_completion(); @@ -300,6 +306,7 @@ void CodeEdit::gui_input(const Ref<InputEvent> &p_gui_input) { default: break; } + return; } else if (code_completion_active && code_completion_scroll_rect.has_point(mb->get_position())) { if (mb->get_button_index() != MouseButton::LEFT) { @@ -448,6 +455,7 @@ void CodeEdit::gui_input(const Ref<InputEvent> &p_gui_input) { } else { code_completion_current_selected = code_completion_options.size() - 1; } + code_completion_force_item_center = -1; queue_redraw(); accept_event(); return; @@ -458,30 +466,35 @@ void CodeEdit::gui_input(const Ref<InputEvent> &p_gui_input) { } else { code_completion_current_selected = 0; } + code_completion_force_item_center = -1; queue_redraw(); accept_event(); return; } if (k->is_action("ui_page_up", true)) { code_completion_current_selected = MAX(0, code_completion_current_selected - code_completion_max_lines); + code_completion_force_item_center = -1; queue_redraw(); accept_event(); return; } if (k->is_action("ui_page_down", true)) { code_completion_current_selected = MIN(code_completion_options.size() - 1, code_completion_current_selected + code_completion_max_lines); + code_completion_force_item_center = -1; queue_redraw(); accept_event(); return; } if (k->is_action("ui_home", true)) { code_completion_current_selected = 0; + code_completion_force_item_center = -1; queue_redraw(); accept_event(); return; } if (k->is_action("ui_end", true)) { code_completion_current_selected = code_completion_options.size() - 1; + code_completion_force_item_center = -1; queue_redraw(); accept_event(); return; @@ -1978,6 +1991,7 @@ void CodeEdit::set_code_completion_selected_index(int p_index) { } ERR_FAIL_INDEX(p_index, code_completion_options.size()); code_completion_current_selected = p_index; + code_completion_force_item_center = -1; queue_redraw(); } @@ -2808,6 +2822,7 @@ void CodeEdit::_update_scroll_selected_line(float p_mouse_y) { percent = CLAMP(percent, 0.0f, 1.0f); code_completion_current_selected = (int)(percent * (code_completion_options.size() - 1)); + code_completion_force_item_center = -1; } void CodeEdit::_filter_code_completion_candidates_impl() { @@ -2867,6 +2882,7 @@ void CodeEdit::_filter_code_completion_candidates_impl() { code_completion_longest_line = MIN(max_width, code_completion_max_width * font_size); code_completion_current_selected = 0; + code_completion_force_item_center = -1; code_completion_active = true; queue_redraw(); return; @@ -3123,6 +3139,7 @@ void CodeEdit::_filter_code_completion_candidates_impl() { code_completion_longest_line = MIN(max_width, code_completion_max_width * font_size); code_completion_current_selected = 0; + code_completion_force_item_center = -1; code_completion_active = true; queue_redraw(); } diff --git a/scene/gui/code_edit.h b/scene/gui/code_edit.h index 09c7ef80bf..cbbc13480e 100644 --- a/scene/gui/code_edit.h +++ b/scene/gui/code_edit.h @@ -214,6 +214,7 @@ private: Vector<ScriptLanguage::CodeCompletionOption> code_completion_options; int code_completion_line_ofs = 0; int code_completion_current_selected = 0; + int code_completion_force_item_center = -1; int code_completion_longest_line = 0; Rect2i code_completion_rect; Rect2i code_completion_scroll_rect; diff --git a/scene/gui/color_mode.cpp b/scene/gui/color_mode.cpp index a063cd344a..308fe057c5 100644 --- a/scene/gui/color_mode.cpp +++ b/scene/gui/color_mode.cpp @@ -158,8 +158,7 @@ void ColorModeHSV::slider_draw(int p_which) { right_color.a = 1; } else if (p_which == 0) { Ref<Texture2D> hue = color_picker->get_theme_icon(SNAME("color_hue"), SNAME("ColorPicker")); - slider->draw_set_transform(Point2(), -Math_PI / 2, Size2(1.0, 1.0)); - slider->draw_texture_rect(hue, Rect2(Vector2(margin * -1, 0), Vector2(margin, size.x)), false); + slider->draw_texture_rect(hue, Rect2(Vector2(), Vector2(size.x, margin)), false); return; } else { Color s_col; @@ -289,9 +288,8 @@ void ColorModeOKHSL::slider_draw(int p_which) { const real_t margin = 16 * color_picker->get_theme_default_base_scale(); if (p_which == 0) { // H - Ref<Texture2D> hue = color_picker->get_theme_icon(SNAME("color_hue"), SNAME("ColorPicker")); - slider->draw_set_transform(Point2(), -Math_PI / 2, Size2(1.0, 1.0)); - slider->draw_texture_rect(hue, Rect2(Vector2(margin * -1, 0), Vector2(margin, size.x)), false); + Ref<Texture2D> hue = color_picker->get_theme_icon(SNAME("color_okhsl_hue"), SNAME("ColorPicker")); + slider->draw_texture_rect(hue, Rect2(Vector2(), Vector2(size.x, margin)), false); return; } diff --git a/scene/gui/flow_container.cpp b/scene/gui/flow_container.cpp index b0d15aa7f4..44c5ec62f8 100644 --- a/scene/gui/flow_container.cpp +++ b/scene/gui/flow_container.cpp @@ -152,6 +152,28 @@ void FlowContainer::_resort() { line_data = lines_data[current_line_idx]; } + // The first child of each line adds the offset caused by the alignment, + // but only if the line doesn't contain a child that expands. + if (child_idx_in_line == 0 && Math::is_equal_approx(line_data.stretch_ratio_total, 0)) { + int alignment_ofs = 0; + switch (alignment) { + case ALIGNMENT_CENTER: + alignment_ofs = line_data.stretch_avail / 2; + break; + case ALIGNMENT_END: + alignment_ofs = line_data.stretch_avail; + break; + default: + break; + } + + if (vertical) { /* VERTICAL */ + ofs.y += alignment_ofs; + } else { /* HORIZONTAL */ + ofs.x += alignment_ofs; + } + } + if (vertical) { /* VERTICAL */ if (child->get_h_size_flags() & (SIZE_FILL | SIZE_SHRINK_CENTER | SIZE_SHRINK_END)) { child_size.width = line_data.min_line_height; @@ -282,6 +304,18 @@ int FlowContainer::get_line_count() const { return cached_line_count; } +void FlowContainer::set_alignment(AlignmentMode p_alignment) { + if (alignment == p_alignment) { + return; + } + alignment = p_alignment; + _resort(); +} + +FlowContainer::AlignmentMode FlowContainer::get_alignment() const { + return alignment; +} + void FlowContainer::set_vertical(bool p_vertical) { ERR_FAIL_COND_MSG(is_fixed, "Can't change orientation of " + get_class() + "."); vertical = p_vertical; @@ -300,8 +334,15 @@ FlowContainer::FlowContainer(bool p_vertical) { void FlowContainer::_bind_methods() { ClassDB::bind_method(D_METHOD("get_line_count"), &FlowContainer::get_line_count); + ClassDB::bind_method(D_METHOD("set_alignment", "alignment"), &FlowContainer::set_alignment); + ClassDB::bind_method(D_METHOD("get_alignment"), &FlowContainer::get_alignment); ClassDB::bind_method(D_METHOD("set_vertical", "vertical"), &FlowContainer::set_vertical); ClassDB::bind_method(D_METHOD("is_vertical"), &FlowContainer::is_vertical); + BIND_ENUM_CONSTANT(ALIGNMENT_BEGIN); + BIND_ENUM_CONSTANT(ALIGNMENT_CENTER); + BIND_ENUM_CONSTANT(ALIGNMENT_END); + + ADD_PROPERTY(PropertyInfo(Variant::INT, "alignment", PROPERTY_HINT_ENUM, "Begin,Center,End"), "set_alignment", "get_alignment"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "vertical"), "set_vertical", "is_vertical"); } diff --git a/scene/gui/flow_container.h b/scene/gui/flow_container.h index 536df27ad6..6a61e9b904 100644 --- a/scene/gui/flow_container.h +++ b/scene/gui/flow_container.h @@ -36,11 +36,19 @@ class FlowContainer : public Container { GDCLASS(FlowContainer, Container); +public: + enum AlignmentMode { + ALIGNMENT_BEGIN, + ALIGNMENT_CENTER, + ALIGNMENT_END + }; + private: int cached_size = 0; int cached_line_count = 0; bool vertical = false; + AlignmentMode alignment = ALIGNMENT_BEGIN; struct ThemeCache { int h_separation = 0; @@ -61,6 +69,9 @@ protected: public: int get_line_count() const; + void set_alignment(AlignmentMode p_alignment); + AlignmentMode get_alignment() const; + void set_vertical(bool p_vertical); bool is_vertical() const; @@ -88,4 +99,6 @@ public: FlowContainer(true) { is_fixed = true; } }; +VARIANT_ENUM_CAST(FlowContainer::AlignmentMode); + #endif // FLOW_CONTAINER_H diff --git a/scene/gui/scroll_container.cpp b/scene/gui/scroll_container.cpp index a6aa4707ff..ec34a8d26d 100644 --- a/scene/gui/scroll_container.cpp +++ b/scene/gui/scroll_container.cpp @@ -107,45 +107,65 @@ void ScrollContainer::gui_input(const Ref<InputEvent> &p_gui_input) { double prev_v_scroll = v_scroll->get_value(); double prev_h_scroll = h_scroll->get_value(); + bool h_scroll_enabled = horizontal_scroll_mode != SCROLL_MODE_DISABLED; + bool v_scroll_enabled = vertical_scroll_mode != SCROLL_MODE_DISABLED; Ref<InputEventMouseButton> mb = p_gui_input; if (mb.is_valid()) { - if (mb->get_button_index() == MouseButton::WHEEL_UP && mb->is_pressed()) { - // only horizontal is enabled, scroll horizontally - if (h_scroll->is_visible() && (!v_scroll->is_visible() || mb->is_shift_pressed())) { - h_scroll->set_value(h_scroll->get_value() - h_scroll->get_page() / 8 * mb->get_factor()); - } else if (v_scroll->is_visible_in_tree()) { - v_scroll->set_value(v_scroll->get_value() - v_scroll->get_page() / 8 * mb->get_factor()); + if (mb->is_pressed()) { + bool scroll_value_modified = false; + + bool v_scroll_hidden = !v_scroll->is_visible() && vertical_scroll_mode != SCROLL_MODE_SHOW_NEVER; + if (mb->get_button_index() == MouseButton::WHEEL_UP) { + // By default, the vertical orientation takes precedence. This is an exception. + if ((h_scroll_enabled && mb->is_shift_pressed()) || v_scroll_hidden) { + h_scroll->set_value(prev_h_scroll - h_scroll->get_page() / 8 * mb->get_factor()); + scroll_value_modified = true; + } else if (v_scroll_enabled) { + v_scroll->set_value(prev_v_scroll - v_scroll->get_page() / 8 * mb->get_factor()); + scroll_value_modified = true; + } } - } - - if (mb->get_button_index() == MouseButton::WHEEL_DOWN && mb->is_pressed()) { - // only horizontal is enabled, scroll horizontally - if (h_scroll->is_visible() && (!v_scroll->is_visible() || mb->is_shift_pressed())) { - h_scroll->set_value(h_scroll->get_value() + h_scroll->get_page() / 8 * mb->get_factor()); - } else if (v_scroll->is_visible()) { - v_scroll->set_value(v_scroll->get_value() + v_scroll->get_page() / 8 * mb->get_factor()); + if (mb->get_button_index() == MouseButton::WHEEL_DOWN) { + if ((h_scroll_enabled && mb->is_shift_pressed()) || v_scroll_hidden) { + h_scroll->set_value(prev_h_scroll + h_scroll->get_page() / 8 * mb->get_factor()); + scroll_value_modified = true; + } else if (v_scroll_enabled) { + v_scroll->set_value(prev_v_scroll + v_scroll->get_page() / 8 * mb->get_factor()); + scroll_value_modified = true; + } } - } - if (mb->get_button_index() == MouseButton::WHEEL_LEFT && mb->is_pressed()) { - if (h_scroll->is_visible_in_tree()) { - h_scroll->set_value(h_scroll->get_value() - h_scroll->get_page() * mb->get_factor() / 8); + bool h_scroll_hidden = !h_scroll->is_visible() && horizontal_scroll_mode != SCROLL_MODE_SHOW_NEVER; + if (mb->get_button_index() == MouseButton::WHEEL_LEFT) { + // By default, the horizontal orientation takes precedence. This is an exception. + if ((v_scroll_enabled && mb->is_shift_pressed()) || h_scroll_hidden) { + v_scroll->set_value(prev_v_scroll - v_scroll->get_page() / 8 * mb->get_factor()); + scroll_value_modified = true; + } else if (h_scroll_enabled) { + h_scroll->set_value(prev_h_scroll - h_scroll->get_page() / 8 * mb->get_factor()); + scroll_value_modified = true; + } } - } - - if (mb->get_button_index() == MouseButton::WHEEL_RIGHT && mb->is_pressed()) { - if (h_scroll->is_visible_in_tree()) { - h_scroll->set_value(h_scroll->get_value() + h_scroll->get_page() * mb->get_factor() / 8); + if (mb->get_button_index() == MouseButton::WHEEL_RIGHT) { + if ((v_scroll_enabled && mb->is_shift_pressed()) || h_scroll_hidden) { + v_scroll->set_value(prev_v_scroll + v_scroll->get_page() / 8 * mb->get_factor()); + scroll_value_modified = true; + } else if (h_scroll_enabled) { + h_scroll->set_value(prev_h_scroll + h_scroll->get_page() / 8 * mb->get_factor()); + scroll_value_modified = true; + } } - } - if (v_scroll->get_value() != prev_v_scroll || h_scroll->get_value() != prev_h_scroll) { - accept_event(); //accept event if scroll changed + if (scroll_value_modified && (v_scroll->get_value() != prev_v_scroll || h_scroll->get_value() != prev_h_scroll)) { + accept_event(); // Accept event if scroll changed. + return; + } } - if (!DisplayServer::get_singleton()->screen_is_touchscreen(DisplayServer::get_singleton()->window_get_current_screen(get_viewport()->get_window_id()))) { + bool screen_is_touchscreen = DisplayServer::get_singleton()->screen_is_touchscreen(DisplayServer::get_singleton()->window_get_current_screen(get_viewport()->get_window_id())); + if (!screen_is_touchscreen) { return; } @@ -161,8 +181,8 @@ void ScrollContainer::gui_input(const Ref<InputEvent> &p_gui_input) { drag_speed = Vector2(); drag_accum = Vector2(); last_drag_accum = Vector2(); - drag_from = Vector2(h_scroll->get_value(), v_scroll->get_value()); - drag_touching = DisplayServer::get_singleton()->screen_is_touchscreen(DisplayServer::get_singleton()->window_get_current_screen(get_viewport()->get_window_id())); + drag_from = Vector2(prev_h_scroll, prev_v_scroll); + drag_touching = screen_is_touchscreen; drag_touching_deaccel = false; beyond_deadzone = false; time_since_motion = 0; @@ -180,6 +200,7 @@ void ScrollContainer::gui_input(const Ref<InputEvent> &p_gui_input) { } } } + return; } Ref<InputEventMouseMotion> mm = p_gui_input; @@ -189,22 +210,22 @@ void ScrollContainer::gui_input(const Ref<InputEvent> &p_gui_input) { Vector2 motion = mm->get_relative(); drag_accum -= motion; - if (beyond_deadzone || (horizontal_scroll_mode != SCROLL_MODE_DISABLED && Math::abs(drag_accum.x) > deadzone) || (vertical_scroll_mode != SCROLL_MODE_DISABLED && Math::abs(drag_accum.y) > deadzone)) { + if (beyond_deadzone || (h_scroll_enabled && Math::abs(drag_accum.x) > deadzone) || (v_scroll_enabled && Math::abs(drag_accum.y) > deadzone)) { if (!beyond_deadzone) { propagate_notification(NOTIFICATION_SCROLL_BEGIN); emit_signal(SNAME("scroll_started")); beyond_deadzone = true; - // resetting drag_accum here ensures smooth scrolling after reaching deadzone + // Resetting drag_accum here ensures smooth scrolling after reaching deadzone. drag_accum = -motion; } Vector2 diff = drag_from + drag_accum; - if (horizontal_scroll_mode != SCROLL_MODE_DISABLED) { + if (h_scroll_enabled) { h_scroll->set_value(diff.x); } else { drag_accum.x = 0; } - if (vertical_scroll_mode != SCROLL_MODE_DISABLED) { + if (v_scroll_enabled) { v_scroll->set_value(diff.y); } else { drag_accum.y = 0; @@ -212,20 +233,26 @@ void ScrollContainer::gui_input(const Ref<InputEvent> &p_gui_input) { time_since_motion = 0; } } + + if (v_scroll->get_value() != prev_v_scroll || h_scroll->get_value() != prev_h_scroll) { + accept_event(); // Accept event if scroll changed. + } + return; } Ref<InputEventPanGesture> pan_gesture = p_gui_input; if (pan_gesture.is_valid()) { - if (h_scroll->is_visible_in_tree()) { - h_scroll->set_value(h_scroll->get_value() + h_scroll->get_page() * pan_gesture->get_delta().x / 8); + if (h_scroll_enabled) { + h_scroll->set_value(prev_h_scroll + h_scroll->get_page() * pan_gesture->get_delta().x / 8); } - if (v_scroll->is_visible_in_tree()) { - v_scroll->set_value(v_scroll->get_value() + v_scroll->get_page() * pan_gesture->get_delta().y / 8); + if (v_scroll_enabled) { + v_scroll->set_value(prev_v_scroll + v_scroll->get_page() * pan_gesture->get_delta().y / 8); } - } - if (v_scroll->get_value() != prev_v_scroll || h_scroll->get_value() != prev_h_scroll) { - accept_event(); //accept event if scroll changed + if (v_scroll->get_value() != prev_v_scroll || h_scroll->get_value() != prev_h_scroll) { + accept_event(); // Accept event if scroll changed. + } + return; } } diff --git a/scene/gui/tab_container.cpp b/scene/gui/tab_container.cpp index ab4808d312..9105267ad3 100644 --- a/scene/gui/tab_container.cpp +++ b/scene/gui/tab_container.cpp @@ -345,7 +345,7 @@ Vector<Control *> TabContainer::_get_tab_controls() const { Vector<Control *> controls; for (int i = 0; i < get_child_count(); i++) { Control *control = Object::cast_to<Control>(get_child(i)); - if (!control || control->is_set_as_top_level() || control == tab_bar || control == child_removing) { + if (!control || control->is_set_as_top_level() || control == tab_bar || children_removing.has(control)) { continue; } @@ -584,10 +584,10 @@ void TabContainer::remove_child_notify(Node *p_child) { int idx = get_tab_idx_from_control(c); - // Before this, the tab control has not changed; after this, the tab control has changed. - child_removing = p_child; + // As the child hasn't been removed yet, keep track of it so when the "tab_changed" signal is fired it can be ignored. + children_removing.push_back(c); tab_bar->remove_tab(idx); - child_removing = nullptr; + children_removing.erase(c); _update_margins(); if (get_tab_count() == 0) { diff --git a/scene/gui/tab_container.h b/scene/gui/tab_container.h index b552aa459b..60961e02d3 100644 --- a/scene/gui/tab_container.h +++ b/scene/gui/tab_container.h @@ -46,7 +46,7 @@ class TabContainer : public Container { bool drag_to_rearrange_enabled = false; bool use_hidden_tabs_for_min_size = false; bool theme_changing = false; - Node *child_removing = nullptr; + Vector<Control *> children_removing; struct ThemeCache { int side_margin = 0; diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index 144aa2a1ef..1b8444abf4 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -833,7 +833,7 @@ void TextEdit::_notification(int p_what) { continue; } - // If we've changed colour we are at the start of a new section, therefore we need to go back to the end + // If we've changed color we are at the start of a new section, therefore we need to go back to the end // of the previous section to draw it, we'll also add the character back on. if (color != previous_color) { characters--; @@ -2051,7 +2051,8 @@ void TextEdit::gui_input(const Ref<InputEvent> &p_gui_input) { } if (is_shortcut_keys_enabled()) { - // SELECT ALL, SELECT WORD UNDER CARET, ADD SELECTION FOR NEXT OCCURRENCE, CUT, COPY, PASTE. + // SELECT ALL, SELECT WORD UNDER CARET, ADD SELECTION FOR NEXT OCCURRENCE, + // CLEAR CARETS AND SELECTIONS, CUT, COPY, PASTE. if (k->is_action("ui_text_select_all", true)) { select_all(); accept_event(); @@ -2067,6 +2068,13 @@ void TextEdit::gui_input(const Ref<InputEvent> &p_gui_input) { accept_event(); return; } + if (k->is_action("ui_text_clear_carets_and_selection", true)) { + // Since the default shortcut is ESC, accepts the event only if it's actually performed. + if (_clear_carets_and_selection()) { + accept_event(); + return; + } + } if (k->is_action("ui_cut", true)) { cut(); accept_event(); @@ -2651,7 +2659,7 @@ void TextEdit::_do_backspace(bool p_word, bool p_all_to_left) { set_caret_line(get_caret_line(caret_idx), false, true, 0, caret_idx); set_caret_column(column, caret_idx == 0, caret_idx); - // Now we can clean up the overlaping caret. + // Now we can clean up the overlapping caret. if (overlapping_caret_index != -1) { backspace(overlapping_caret_index); i++; @@ -2819,6 +2827,20 @@ void TextEdit::_move_caret_document_end(bool p_select) { } } +bool TextEdit::_clear_carets_and_selection() { + if (get_caret_count() > 1) { + remove_secondary_carets(); + return true; + } + + if (has_selection()) { + deselect(); + return true; + } + + return false; +} + void TextEdit::_get_above_below_caret_line_column(int p_old_line, int p_old_wrap_index, int p_old_column, bool p_below, int &p_new_line, int &p_new_column, int p_last_fit_x) const { if (p_last_fit_x == -1) { p_last_fit_x = _get_column_x_offset_for_line(p_old_column, p_old_line, p_old_column); @@ -6538,7 +6560,7 @@ void TextEdit::_cut_internal(int p_caret) { int indent_level = get_indent_level(cl); double hscroll = get_h_scroll(); - // Check for overlaping carets. + // Check for overlapping carets. // We don't need to worry about selections as that is caught before this entire section. for (int j = i - 1; j >= 0; j--) { if (get_caret_line(caret_edit_order[j]) == cl) { diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h index 935f2a7ce8..92acbaf521 100644 --- a/scene/gui/text_edit.h +++ b/scene/gui/text_edit.h @@ -597,6 +597,7 @@ private: void _delete(bool p_word = false, bool p_all_to_right = false); void _move_caret_document_start(bool p_select); void _move_caret_document_end(bool p_select); + bool _clear_carets_and_selection(); // Used in add_caret_at_carets void _get_above_below_caret_line_column(int p_old_line, int p_old_wrap_index, int p_old_column, bool p_below, int &p_new_line, int &p_new_column, int p_last_fit_x = -1) const; |