summaryrefslogtreecommitdiff
path: root/scene/gui
diff options
context:
space:
mode:
Diffstat (limited to 'scene/gui')
-rw-r--r--scene/gui/base_button.cpp6
-rw-r--r--scene/gui/button.cpp6
-rw-r--r--scene/gui/control.cpp24
-rw-r--r--scene/gui/graph_edit.cpp28
-rw-r--r--scene/gui/graph_edit.h5
-rw-r--r--scene/gui/line_edit.cpp203
-rw-r--r--scene/gui/line_edit.h6
-rw-r--r--scene/gui/rich_text_label.cpp6
-rw-r--r--scene/gui/spin_box.cpp2
-rw-r--r--scene/gui/subviewport_container.cpp41
-rw-r--r--scene/gui/subviewport_container.h3
-rw-r--r--scene/gui/text_edit.cpp209
-rw-r--r--scene/gui/text_edit.h5
-rw-r--r--scene/gui/view_panner.cpp84
-rw-r--r--scene/gui/view_panner.h16
15 files changed, 393 insertions, 251 deletions
diff --git a/scene/gui/base_button.cpp b/scene/gui/base_button.cpp
index 472299b135..c26a00221a 100644
--- a/scene/gui/base_button.cpp
+++ b/scene/gui/base_button.cpp
@@ -479,14 +479,16 @@ void BaseButton::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "disabled"), "set_disabled", "is_disabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "toggle_mode"), "set_toggle_mode", "is_toggle_mode");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shortcut_in_tooltip"), "set_shortcut_in_tooltip", "is_shortcut_in_tooltip_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "button_pressed"), "set_pressed", "is_pressed");
ADD_PROPERTY(PropertyInfo(Variant::INT, "action_mode", PROPERTY_HINT_ENUM, "Button Press,Button Release"), "set_action_mode", "get_action_mode");
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, "button_group", PROPERTY_HINT_RESOURCE_TYPE, "ButtonGroup"), "set_button_group", "get_button_group");
+
+ ADD_GROUP("Shortcut", "");
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");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shortcut_in_tooltip"), "set_shortcut_in_tooltip", "is_shortcut_in_tooltip_enabled");
BIND_ENUM_CONSTANT(DRAW_NORMAL);
BIND_ENUM_CONSTANT(DRAW_PRESSED);
diff --git a/scene/gui/button.cpp b/scene/gui/button.cpp
index 1e07a53642..2a8b1cd8c4 100644
--- a/scene/gui/button.cpp
+++ b/scene/gui/button.cpp
@@ -575,9 +575,13 @@ void Button::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::STRING, "text", PROPERTY_HINT_MULTILINE_TEXT), "set_text", "get_text");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "icon", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_button_icon", "get_button_icon");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "flat"), "set_flat", "is_flat");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "clip_text"), "set_clip_text", "get_clip_text");
+
+ ADD_GROUP("Text Behavior", "");
ADD_PROPERTY(PropertyInfo(Variant::INT, "alignment", PROPERTY_HINT_ENUM, "Left,Center,Right"), "set_text_alignment", "get_text_alignment");
ADD_PROPERTY(PropertyInfo(Variant::INT, "text_overrun_behavior", PROPERTY_HINT_ENUM, "Trim Nothing,Trim Characters,Trim Words,Ellipsis,Word Ellipsis"), "set_text_overrun_behavior", "get_text_overrun_behavior");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "clip_text"), "set_clip_text", "get_clip_text");
+
+ ADD_GROUP("Icon Behavior", "");
ADD_PROPERTY(PropertyInfo(Variant::INT, "icon_alignment", PROPERTY_HINT_ENUM, "Left,Center,Right"), "set_icon_alignment", "get_icon_alignment");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "expand_icon"), "set_expand_icon", "is_expand_icon");
diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp
index fead0878fb..f7c056316d 100644
--- a/scene/gui/control.cpp
+++ b/scene/gui/control.cpp
@@ -1387,13 +1387,7 @@ Point2 Control::get_global_position() const {
Point2 Control::get_screen_position() const {
ERR_FAIL_COND_V(!is_inside_tree(), Point2());
- Point2 global_pos = get_global_transform_with_canvas().get_origin();
- Window *w = Object::cast_to<Window>(get_viewport());
- if (w && !w->is_embedding_subwindows()) {
- global_pos += w->get_position();
- }
-
- return global_pos;
+ return get_screen_transform().get_origin();
}
void Control::_set_size(const Size2 &p_size) {
@@ -1444,24 +1438,20 @@ void Control::set_rect(const Rect2 &p_rect) {
}
Rect2 Control::get_rect() const {
- return Rect2(get_position(), get_size());
+ Transform2D xform = get_transform();
+ return Rect2(xform.get_origin(), xform.get_scale() * get_size());
}
Rect2 Control::get_global_rect() const {
- return Rect2(get_global_position(), get_size());
+ Transform2D xform = get_global_transform();
+ return Rect2(xform.get_origin(), xform.get_scale() * get_size());
}
Rect2 Control::get_screen_rect() const {
ERR_FAIL_COND_V(!is_inside_tree(), Rect2());
- Rect2 r(get_global_position(), get_size());
-
- Window *w = Object::cast_to<Window>(get_viewport());
- if (w && !w->is_embedding_subwindows()) {
- r.position += w->get_position();
- }
-
- return r;
+ Transform2D xform = get_screen_transform();
+ return Rect2(xform.get_origin(), xform.get_scale() * get_size());
}
Rect2 Control::get_anchorable_rect() const {
diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp
index 6c495ab2c9..af52f6664a 100644
--- a/scene/gui/graph_edit.cpp
+++ b/scene/gui/graph_edit.cpp
@@ -1380,34 +1380,15 @@ void GraphEdit::gui_input(const Ref<InputEvent> &p_ev) {
accept_event();
}
}
-
- Ref<InputEventMagnifyGesture> magnify_gesture = p_ev;
- if (magnify_gesture.is_valid()) {
- set_zoom_custom(zoom * magnify_gesture->get_factor(), magnify_gesture->get_position());
- }
-
- Ref<InputEventPanGesture> pan_gesture = p_ev;
- if (pan_gesture.is_valid()) {
- h_scroll->set_value(h_scroll->get_value() + h_scroll->get_page() * pan_gesture->get_delta().x / 8);
- v_scroll->set_value(v_scroll->get_value() + v_scroll->get_page() * pan_gesture->get_delta().y / 8);
- }
-}
-
-void GraphEdit::_scroll_callback(Vector2 p_scroll_vec, bool p_alt) {
- if (p_scroll_vec.x != 0) {
- h_scroll->set_value(h_scroll->get_value() + (h_scroll->get_page() * Math::abs(p_scroll_vec.x) / 8) * SIGN(p_scroll_vec.x));
- } else {
- v_scroll->set_value(v_scroll->get_value() + (v_scroll->get_page() * Math::abs(p_scroll_vec.y) / 8) * SIGN(p_scroll_vec.y));
- }
}
-void GraphEdit::_pan_callback(Vector2 p_scroll_vec) {
+void GraphEdit::_pan_callback(Vector2 p_scroll_vec, Ref<InputEvent> p_event) {
h_scroll->set_value(h_scroll->get_value() - p_scroll_vec.x);
v_scroll->set_value(v_scroll->get_value() - p_scroll_vec.y);
}
-void GraphEdit::_zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin, bool p_alt) {
- set_zoom_custom(p_scroll_vec.y < 0 ? zoom * zoom_step : zoom / zoom_step, p_origin);
+void GraphEdit::_zoom_callback(float p_zoom_factor, Vector2 p_origin, Ref<InputEvent> p_event) {
+ set_zoom_custom(zoom * p_zoom_factor, p_origin);
}
void GraphEdit::set_connection_activity(const StringName &p_from, int p_from_port, const StringName &p_to, int p_to_port, float p_activity) {
@@ -1502,6 +1483,7 @@ void GraphEdit::set_zoom_step(float p_zoom_step) {
}
zoom_step = p_zoom_step;
+ panner->set_scroll_zoom_factor(zoom_step);
}
float GraphEdit::get_zoom_step() const {
@@ -2421,7 +2403,7 @@ GraphEdit::GraphEdit() {
zoom_max = (1 * Math::pow(zoom_step, 4));
panner.instantiate();
- panner->set_callbacks(callable_mp(this, &GraphEdit::_scroll_callback), callable_mp(this, &GraphEdit::_pan_callback), callable_mp(this, &GraphEdit::_zoom_callback));
+ panner->set_callbacks(callable_mp(this, &GraphEdit::_pan_callback), callable_mp(this, &GraphEdit::_zoom_callback));
top_layer = memnew(GraphEditFilter(this));
add_child(top_layer, false, INTERNAL_MODE_BACK);
diff --git a/scene/gui/graph_edit.h b/scene/gui/graph_edit.h
index 030f40e370..dfe6b94906 100644
--- a/scene/gui/graph_edit.h
+++ b/scene/gui/graph_edit.h
@@ -129,9 +129,8 @@ private:
Ref<ViewPanner> panner;
bool warped_panning = true;
- void _scroll_callback(Vector2 p_scroll_vec, bool p_alt);
- void _pan_callback(Vector2 p_scroll_vec);
- void _zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin, bool p_alt);
+ void _pan_callback(Vector2 p_scroll_vec, Ref<InputEvent> p_event);
+ void _zoom_callback(float p_zoom_factor, Vector2 p_origin, Ref<InputEvent> p_event);
bool arrange_nodes_button_hidden = false;
diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp
index e2a5b0c8a3..dba08e16cb 100644
--- a/scene/gui/line_edit.cpp
+++ b/scene/gui/line_edit.cpp
@@ -247,7 +247,7 @@ void LineEdit::gui_input(const Ref<InputEvent> &p_event) {
return;
}
if (b->is_pressed() && b->get_button_index() == MouseButton::RIGHT && context_menu_enabled) {
- _ensure_menu();
+ _update_context_menu();
menu->set_position(get_screen_position() + get_local_mouse_position());
menu->reset_size();
menu->popup();
@@ -452,7 +452,7 @@ void LineEdit::gui_input(const Ref<InputEvent> &p_event) {
if (context_menu_enabled) {
if (k->is_action("ui_menu", true)) {
- _ensure_menu();
+ _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();
@@ -1724,6 +1724,10 @@ void LineEdit::insert_text_at_caret(String p_text) {
input_direction = (TextDirection)dir;
}
set_caret_column(caret_column + p_text.length());
+
+ if (!ime_text.is_empty()) {
+ _shape();
+ }
}
void LineEdit::clear_internal() {
@@ -2073,7 +2077,9 @@ bool LineEdit::is_menu_visible() const {
}
PopupMenu *LineEdit::get_menu() const {
- const_cast<LineEdit *>(this)->_ensure_menu();
+ if (!menu) {
+ const_cast<LineEdit *>(this)->_generate_context_menu();
+ }
return menu;
}
@@ -2331,6 +2337,115 @@ Key LineEdit::_get_menu_action_accelerator(const String &p_action) {
}
}
+void LineEdit::_generate_context_menu() {
+ menu = memnew(PopupMenu);
+ add_child(menu, false, INTERNAL_MODE_FRONT);
+
+ menu_dir = memnew(PopupMenu);
+ menu_dir->set_name("DirMenu");
+ menu_dir->add_radio_check_item(RTR("Same as Layout Direction"), MENU_DIR_INHERITED);
+ menu_dir->add_radio_check_item(RTR("Auto-Detect Direction"), MENU_DIR_AUTO);
+ menu_dir->add_radio_check_item(RTR("Left-to-Right"), MENU_DIR_LTR);
+ menu_dir->add_radio_check_item(RTR("Right-to-Left"), MENU_DIR_RTL);
+ menu->add_child(menu_dir, false, INTERNAL_MODE_FRONT);
+
+ menu_ctl = memnew(PopupMenu);
+ menu_ctl->set_name("CTLMenu");
+ menu_ctl->add_item(RTR("Left-to-Right Mark (LRM)"), MENU_INSERT_LRM);
+ menu_ctl->add_item(RTR("Right-to-Left Mark (RLM)"), MENU_INSERT_RLM);
+ menu_ctl->add_item(RTR("Start of Left-to-Right Embedding (LRE)"), MENU_INSERT_LRE);
+ menu_ctl->add_item(RTR("Start of Right-to-Left Embedding (RLE)"), MENU_INSERT_RLE);
+ menu_ctl->add_item(RTR("Start of Left-to-Right Override (LRO)"), MENU_INSERT_LRO);
+ menu_ctl->add_item(RTR("Start of Right-to-Left Override (RLO)"), MENU_INSERT_RLO);
+ menu_ctl->add_item(RTR("Pop Direction Formatting (PDF)"), MENU_INSERT_PDF);
+ menu_ctl->add_separator();
+ menu_ctl->add_item(RTR("Arabic Letter Mark (ALM)"), MENU_INSERT_ALM);
+ menu_ctl->add_item(RTR("Left-to-Right Isolate (LRI)"), MENU_INSERT_LRI);
+ menu_ctl->add_item(RTR("Right-to-Left Isolate (RLI)"), MENU_INSERT_RLI);
+ menu_ctl->add_item(RTR("First Strong Isolate (FSI)"), MENU_INSERT_FSI);
+ menu_ctl->add_item(RTR("Pop Direction Isolate (PDI)"), MENU_INSERT_PDI);
+ menu_ctl->add_separator();
+ menu_ctl->add_item(RTR("Zero-Width Joiner (ZWJ)"), MENU_INSERT_ZWJ);
+ menu_ctl->add_item(RTR("Zero-Width Non-Joiner (ZWNJ)"), MENU_INSERT_ZWNJ);
+ menu_ctl->add_item(RTR("Word Joiner (WJ)"), MENU_INSERT_WJ);
+ menu_ctl->add_item(RTR("Soft Hyphen (SHY)"), MENU_INSERT_SHY);
+ menu->add_child(menu_ctl, false, INTERNAL_MODE_FRONT);
+
+ menu->add_item(RTR("Cut"), MENU_CUT);
+ menu->add_item(RTR("Copy"), MENU_COPY);
+ menu->add_item(RTR("Paste"), MENU_PASTE);
+ menu->add_separator();
+ menu->add_item(RTR("Select All"), MENU_SELECT_ALL);
+ menu->add_item(RTR("Clear"), MENU_CLEAR);
+ menu->add_separator();
+ menu->add_item(RTR("Undo"), MENU_UNDO);
+ menu->add_item(RTR("Redo"), MENU_REDO);
+ menu->add_separator();
+ menu->add_submenu_item(RTR("Text Writing Direction"), "DirMenu", MENU_SUBMENU_TEXT_DIR);
+ menu->add_separator();
+ menu->add_check_item(RTR("Display Control Characters"), MENU_DISPLAY_UCC);
+ menu->add_submenu_item(RTR("Insert Control Character"), "CTLMenu", MENU_SUBMENU_INSERT_UCC);
+
+ menu->connect("id_pressed", callable_mp(this, &LineEdit::menu_option));
+ menu_dir->connect("id_pressed", callable_mp(this, &LineEdit::menu_option));
+ menu_ctl->connect("id_pressed", callable_mp(this, &LineEdit::menu_option));
+
+ menu->connect(SNAME("focus_entered"), callable_mp(this, &LineEdit::_validate_caret_can_draw));
+ menu->connect(SNAME("focus_exited"), callable_mp(this, &LineEdit::_validate_caret_can_draw));
+}
+
+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); \
+ }
+
+ 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
+}
+
void LineEdit::_validate_property(PropertyInfo &p_property) const {
if (!caret_blink_enabled && p_property.name == "caret_blink_interval") {
p_property.usage = PROPERTY_USAGE_NO_EDITOR;
@@ -2425,11 +2540,13 @@ void LineEdit::_bind_methods() {
BIND_ENUM_CONSTANT(MENU_SELECT_ALL);
BIND_ENUM_CONSTANT(MENU_UNDO);
BIND_ENUM_CONSTANT(MENU_REDO);
+ BIND_ENUM_CONSTANT(MENU_SUBMENU_TEXT_DIR);
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);
+ BIND_ENUM_CONSTANT(MENU_SUBMENU_INSERT_UCC);
BIND_ENUM_CONSTANT(MENU_INSERT_LRM);
BIND_ENUM_CONSTANT(MENU_INSERT_RLM);
BIND_ENUM_CONSTANT(MENU_INSERT_LRE);
@@ -2492,86 +2609,6 @@ void LineEdit::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "structured_text_bidi_override_options"), "set_structured_text_bidi_override_options", "get_structured_text_bidi_override_options");
}
-void LineEdit::_ensure_menu() {
- if (!menu) {
- menu = memnew(PopupMenu);
- add_child(menu, false, INTERNAL_MODE_FRONT);
-
- menu_dir = memnew(PopupMenu);
- menu_dir->set_name("DirMenu");
- menu_dir->add_radio_check_item(RTR("Same as Layout Direction"), MENU_DIR_INHERITED);
- menu_dir->add_radio_check_item(RTR("Auto-Detect Direction"), MENU_DIR_AUTO);
- menu_dir->add_radio_check_item(RTR("Left-to-Right"), MENU_DIR_LTR);
- menu_dir->add_radio_check_item(RTR("Right-to-Left"), MENU_DIR_RTL);
- menu->add_child(menu_dir, false, INTERNAL_MODE_FRONT);
-
- menu_ctl = memnew(PopupMenu);
- menu_ctl->set_name("CTLMenu");
- menu_ctl->add_item(RTR("Left-to-Right Mark (LRM)"), MENU_INSERT_LRM);
- menu_ctl->add_item(RTR("Right-to-Left Mark (RLM)"), MENU_INSERT_RLM);
- menu_ctl->add_item(RTR("Start of Left-to-Right Embedding (LRE)"), MENU_INSERT_LRE);
- menu_ctl->add_item(RTR("Start of Right-to-Left Embedding (RLE)"), MENU_INSERT_RLE);
- menu_ctl->add_item(RTR("Start of Left-to-Right Override (LRO)"), MENU_INSERT_LRO);
- menu_ctl->add_item(RTR("Start of Right-to-Left Override (RLO)"), MENU_INSERT_RLO);
- menu_ctl->add_item(RTR("Pop Direction Formatting (PDF)"), MENU_INSERT_PDF);
- menu_ctl->add_separator();
- menu_ctl->add_item(RTR("Arabic Letter Mark (ALM)"), MENU_INSERT_ALM);
- menu_ctl->add_item(RTR("Left-to-Right Isolate (LRI)"), MENU_INSERT_LRI);
- menu_ctl->add_item(RTR("Right-to-Left Isolate (RLI)"), MENU_INSERT_RLI);
- menu_ctl->add_item(RTR("First Strong Isolate (FSI)"), MENU_INSERT_FSI);
- menu_ctl->add_item(RTR("Pop Direction Isolate (PDI)"), MENU_INSERT_PDI);
- menu_ctl->add_separator();
- menu_ctl->add_item(RTR("Zero-Width Joiner (ZWJ)"), MENU_INSERT_ZWJ);
- menu_ctl->add_item(RTR("Zero-Width Non-Joiner (ZWNJ)"), MENU_INSERT_ZWNJ);
- menu_ctl->add_item(RTR("Word Joiner (WJ)"), MENU_INSERT_WJ);
- menu_ctl->add_item(RTR("Soft Hyphen (SHY)"), MENU_INSERT_SHY);
- menu->add_child(menu_ctl, false, INTERNAL_MODE_FRONT);
-
- menu->connect("id_pressed", callable_mp(this, &LineEdit::menu_option));
- menu->connect(SNAME("focus_entered"), callable_mp(this, &LineEdit::_validate_caret_can_draw));
- menu->connect(SNAME("focus_exited"), callable_mp(this, &LineEdit::_validate_caret_can_draw));
- menu_dir->connect("id_pressed", callable_mp(this, &LineEdit::menu_option));
- menu_ctl->connect("id_pressed", callable_mp(this, &LineEdit::menu_option));
- }
-
- // Reorganize context menu.
- menu->clear();
- if (editable) {
- menu->add_item(RTR("Cut"), MENU_CUT, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_cut") : Key::NONE);
- }
- menu->add_item(RTR("Copy"), MENU_COPY, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_copy") : Key::NONE);
- if (editable) {
- menu->add_item(RTR("Paste"), MENU_PASTE, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_paste") : Key::NONE);
- }
- menu->add_separator();
- if (is_selecting_enabled()) {
- menu->add_item(RTR("Select All"), MENU_SELECT_ALL, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_text_select_all") : Key::NONE);
- }
- if (editable) {
- menu->add_item(RTR("Clear"), MENU_CLEAR);
- menu->add_separator();
- menu->add_item(RTR("Undo"), MENU_UNDO, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_undo") : Key::NONE);
- menu->add_item(RTR("Redo"), MENU_REDO, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_redo") : Key::NONE);
- }
- menu->add_separator();
- menu->add_submenu_item(RTR("Text Writing Direction"), "DirMenu");
- menu->add_separator();
- menu->add_check_item(RTR("Display Control Characters"), MENU_DISPLAY_UCC);
- menu->set_item_checked(menu->get_item_index(MENU_DISPLAY_UCC), draw_control_chars);
- if (editable) {
- menu->add_submenu_item(RTR("Insert Control Character"), "CTLMenu");
- }
- 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);
-
- if (editable) {
- menu->set_item_disabled(menu->get_item_index(MENU_UNDO), !has_undo());
- menu->set_item_disabled(menu->get_item_index(MENU_REDO), !has_redo());
- }
-}
-
LineEdit::LineEdit(const String &p_placeholder) {
text_rid = TS->create_shaped_text();
_create_undo_state();
diff --git a/scene/gui/line_edit.h b/scene/gui/line_edit.h
index 5107845a5e..81c506069a 100644
--- a/scene/gui/line_edit.h
+++ b/scene/gui/line_edit.h
@@ -46,11 +46,13 @@ public:
MENU_SELECT_ALL,
MENU_UNDO,
MENU_REDO,
+ MENU_SUBMENU_TEXT_DIR,
MENU_DIR_INHERITED,
MENU_DIR_AUTO,
MENU_DIR_LTR,
MENU_DIR_RTL,
MENU_DISPLAY_UCC,
+ MENU_SUBMENU_INSERT_UCC,
MENU_INSERT_LRM,
MENU_INSERT_RLM,
MENU_INSERT_LRE,
@@ -207,6 +209,8 @@ private:
void _create_undo_state();
Key _get_menu_action_accelerator(const String &p_action);
+ void _generate_context_menu();
+ void _update_context_menu();
void _shape();
void _fit_to_width();
@@ -239,8 +243,6 @@ private:
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;
diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp
index a68a7ddfb8..71ee3c8d0d 100644
--- a/scene/gui/rich_text_label.cpp
+++ b/scene/gui/rich_text_label.cpp
@@ -2808,7 +2808,7 @@ void RichTextLabel::_process_line_caches() {
int ctrl_height = get_size().height;
int fi = main->first_invalid_line.load();
- int total_chars = (fi == 0) ? 0 : (main->lines[fi].char_offset + main->lines[fi].char_count);
+ int total_chars = main->lines[fi].char_offset;
float total_height = (fi == 0) ? 0 : _calculate_line_vertical_offset(main->lines[fi - 1]);
for (int i = fi; i < (int)main->lines.size(); i++) {
@@ -3435,6 +3435,8 @@ void RichTextLabel::push_customfx(Ref<RichTextEffect> p_custom_effect, Dictionar
item->custom_effect = p_custom_effect;
item->char_fx_transform->environment = p_environment;
_add_item(item, true);
+
+ set_process_internal(true);
}
void RichTextLabel::set_table_column_expand(int p_column, bool p_expand, int p_ratio) {
@@ -4552,7 +4554,6 @@ void RichTextLabel::append_text(const String &p_bbcode) {
push_customfx(effect, properties);
pos = brk_end + 1;
tag_stack.push_front(identifier);
- set_process_internal(true);
} else {
add_text("["); //ignore
pos = brk_pos + 1;
@@ -5346,6 +5347,7 @@ void RichTextLabel::_bind_methods() {
ClassDB::bind_method(D_METHOD("push_cell"), &RichTextLabel::push_cell);
ClassDB::bind_method(D_METHOD("push_fgcolor", "fgcolor"), &RichTextLabel::push_fgcolor);
ClassDB::bind_method(D_METHOD("push_bgcolor", "bgcolor"), &RichTextLabel::push_bgcolor);
+ ClassDB::bind_method(D_METHOD("push_customfx", "effect", "env"), &RichTextLabel::push_customfx);
ClassDB::bind_method(D_METHOD("pop"), &RichTextLabel::pop);
ClassDB::bind_method(D_METHOD("clear"), &RichTextLabel::clear);
diff --git a/scene/gui/spin_box.cpp b/scene/gui/spin_box.cpp
index dfc03c666b..f99b2edd54 100644
--- a/scene/gui/spin_box.cpp
+++ b/scene/gui/spin_box.cpp
@@ -368,7 +368,7 @@ void SpinBox::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "update_on_text_changed"), "set_update_on_text_changed", "get_update_on_text_changed");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "prefix"), "set_prefix", "get_prefix");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "suffix"), "set_suffix", "get_suffix");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "custom_arrow_step"), "set_custom_arrow_step", "get_custom_arrow_step");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "custom_arrow_step", PROPERTY_HINT_RANGE, "0,10000,0.0001,or_greater"), "set_custom_arrow_step", "get_custom_arrow_step");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "select_all_on_focus"), "set_select_all_on_focus", "is_select_all_on_focus");
}
diff --git a/scene/gui/subviewport_container.cpp b/scene/gui/subviewport_container.cpp
index 440597c24a..7c1d2f95a9 100644
--- a/scene/gui/subviewport_container.cpp
+++ b/scene/gui/subviewport_container.cpp
@@ -180,24 +180,51 @@ void SubViewportContainer::input(const Ref<InputEvent> &p_event) {
return;
}
- Transform2D xform = get_global_transform_with_canvas();
+ if (_is_propagated_in_gui_input(p_event)) {
+ return;
+ }
- if (stretch) {
- Transform2D scale_xf;
- scale_xf.scale(Vector2(shrink, shrink));
- xform *= scale_xf;
+ _send_event_to_viewports(p_event);
+}
+
+void SubViewportContainer::gui_input(const Ref<InputEvent> &p_event) {
+ ERR_FAIL_COND(p_event.is_null());
+
+ if (Engine::get_singleton()->is_editor_hint()) {
+ return;
}
- Ref<InputEvent> ev = p_event->xformed_by(xform.affine_inverse());
+ if (!_is_propagated_in_gui_input(p_event)) {
+ return;
+ }
+ if (stretch && shrink > 1) {
+ Transform2D xform;
+ xform.scale(Vector2(1, 1) / shrink);
+ _send_event_to_viewports(p_event->xformed_by(xform));
+ } else {
+ _send_event_to_viewports(p_event);
+ }
+}
+
+void SubViewportContainer::_send_event_to_viewports(const Ref<InputEvent> &p_event) {
for (int i = 0; i < get_child_count(); i++) {
SubViewport *c = Object::cast_to<SubViewport>(get_child(i));
if (!c || c->is_input_disabled()) {
continue;
}
- c->push_input(ev);
+ c->push_input(p_event);
+ }
+}
+
+bool SubViewportContainer::_is_propagated_in_gui_input(const Ref<InputEvent> &p_event) {
+ // Propagation of events with a position property happen in gui_input
+ // Propagation of other events happen in input
+ if (Object::cast_to<InputEventMouse>(*p_event) || Object::cast_to<InputEventScreenDrag>(*p_event) || Object::cast_to<InputEventScreenTouch>(*p_event) || Object::cast_to<InputEventGesture>(*p_event)) {
+ return true;
}
+ return false;
}
void SubViewportContainer::unhandled_input(const Ref<InputEvent> &p_event) {
diff --git a/scene/gui/subviewport_container.h b/scene/gui/subviewport_container.h
index d918c4a615..d3236b0c4e 100644
--- a/scene/gui/subviewport_container.h
+++ b/scene/gui/subviewport_container.h
@@ -39,6 +39,8 @@ class SubViewportContainer : public Container {
bool stretch = false;
int shrink = 1;
void _notify_viewports(int p_notification);
+ bool _is_propagated_in_gui_input(const Ref<InputEvent> &p_event);
+ void _send_event_to_viewports(const Ref<InputEvent> &p_event);
protected:
void _notification(int p_what);
@@ -52,6 +54,7 @@ public:
bool is_stretch_enabled() const;
virtual void input(const Ref<InputEvent> &p_event) override;
+ virtual void gui_input(const Ref<InputEvent> &p_event) override;
virtual void unhandled_input(const Ref<InputEvent> &p_event) override;
void set_stretch_shrink(int p_shrink);
int get_stretch_shrink() const;
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index 77d5dda4f2..d785280701 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -1861,7 +1861,7 @@ void TextEdit::gui_input(const Ref<InputEvent> &p_gui_input) {
}
if (context_menu_enabled) {
- _generate_context_menu();
+ _update_context_menu();
menu->set_position(get_screen_position() + mpos);
menu->reset_size();
menu->popup();
@@ -2141,7 +2141,7 @@ void TextEdit::gui_input(const Ref<InputEvent> &p_gui_input) {
// MISC.
if (k->is_action("ui_menu", true)) {
if (context_menu_enabled) {
- _generate_context_menu();
+ _update_context_menu();
adjust_viewport_to_caret();
menu->set_position(get_screen_position() + get_caret_draw_pos());
menu->reset_size();
@@ -3544,6 +3544,19 @@ void TextEdit::insert_text_at_caret(const String &p_text, int p_caret) {
adjust_carets_after_edit(i, new_line, new_column, from_line, from_col);
}
+
+ if (!ime_text.is_empty()) {
+ for (int i = 0; i < carets.size(); i++) {
+ String t;
+ if (get_caret_column(i) >= 0) {
+ t = text[get_caret_line(i)].substr(0, get_caret_column(i)) + ime_text + text[get_caret_line(i)].substr(get_caret_column(i), text[get_caret_line(i)].length());
+ } else {
+ t = ime_text;
+ }
+ text.invalidate_cache(get_caret_line(i), get_caret_column(i), true, t, structured_text_parser(st_parser, st_args, t));
+ }
+ }
+
end_complex_operation();
queue_redraw();
}
@@ -3713,7 +3726,9 @@ void TextEdit::paste_primary_clipboard(int p_caret) {
// Context menu.
PopupMenu *TextEdit::get_menu() const {
- const_cast<TextEdit *>(this)->_generate_context_menu();
+ if (!menu) {
+ const_cast<TextEdit *>(this)->_generate_context_menu();
+ }
return menu;
}
@@ -6062,11 +6077,13 @@ void TextEdit::_bind_methods() {
BIND_ENUM_CONSTANT(MENU_SELECT_ALL);
BIND_ENUM_CONSTANT(MENU_UNDO);
BIND_ENUM_CONSTANT(MENU_REDO);
+ BIND_ENUM_CONSTANT(MENU_SUBMENU_TEXT_DIR);
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);
+ BIND_ENUM_CONSTANT(MENU_SUBMENU_INSERT_UCC);
BIND_ENUM_CONSTANT(MENU_INSERT_LRM);
BIND_ENUM_CONSTANT(MENU_INSERT_RLM);
BIND_ENUM_CONSTANT(MENU_INSERT_LRE);
@@ -6717,87 +6734,7 @@ void TextEdit::_paste_primary_clipboard_internal(int p_caret) {
grab_focus();
}
-/* Text. */
// Context menu.
-void TextEdit::_generate_context_menu() {
- if (!menu) {
- menu = memnew(PopupMenu);
- add_child(menu, false, INTERNAL_MODE_FRONT);
-
- menu_dir = memnew(PopupMenu);
- menu_dir->set_name("DirMenu");
- menu_dir->add_radio_check_item(RTR("Same as Layout Direction"), MENU_DIR_INHERITED);
- menu_dir->add_radio_check_item(RTR("Auto-Detect Direction"), MENU_DIR_AUTO);
- menu_dir->add_radio_check_item(RTR("Left-to-Right"), MENU_DIR_LTR);
- menu_dir->add_radio_check_item(RTR("Right-to-Left"), MENU_DIR_RTL);
- menu->add_child(menu_dir, false, INTERNAL_MODE_FRONT);
-
- menu_ctl = memnew(PopupMenu);
- menu_ctl->set_name("CTLMenu");
- menu_ctl->add_item(RTR("Left-to-Right Mark (LRM)"), MENU_INSERT_LRM);
- menu_ctl->add_item(RTR("Right-to-Left Mark (RLM)"), MENU_INSERT_RLM);
- menu_ctl->add_item(RTR("Start of Left-to-Right Embedding (LRE)"), MENU_INSERT_LRE);
- menu_ctl->add_item(RTR("Start of Right-to-Left Embedding (RLE)"), MENU_INSERT_RLE);
- menu_ctl->add_item(RTR("Start of Left-to-Right Override (LRO)"), MENU_INSERT_LRO);
- menu_ctl->add_item(RTR("Start of Right-to-Left Override (RLO)"), MENU_INSERT_RLO);
- menu_ctl->add_item(RTR("Pop Direction Formatting (PDF)"), MENU_INSERT_PDF);
- menu_ctl->add_separator();
- menu_ctl->add_item(RTR("Arabic Letter Mark (ALM)"), MENU_INSERT_ALM);
- menu_ctl->add_item(RTR("Left-to-Right Isolate (LRI)"), MENU_INSERT_LRI);
- menu_ctl->add_item(RTR("Right-to-Left Isolate (RLI)"), MENU_INSERT_RLI);
- menu_ctl->add_item(RTR("First Strong Isolate (FSI)"), MENU_INSERT_FSI);
- menu_ctl->add_item(RTR("Pop Direction Isolate (PDI)"), MENU_INSERT_PDI);
- menu_ctl->add_separator();
- menu_ctl->add_item(RTR("Zero-Width Joiner (ZWJ)"), MENU_INSERT_ZWJ);
- menu_ctl->add_item(RTR("Zero-Width Non-Joiner (ZWNJ)"), MENU_INSERT_ZWNJ);
- menu_ctl->add_item(RTR("Word Joiner (WJ)"), MENU_INSERT_WJ);
- menu_ctl->add_item(RTR("Soft Hyphen (SHY)"), MENU_INSERT_SHY);
- menu->add_child(menu_ctl, false, INTERNAL_MODE_FRONT);
-
- menu->connect("id_pressed", callable_mp(this, &TextEdit::menu_option));
- menu_dir->connect("id_pressed", callable_mp(this, &TextEdit::menu_option));
- menu_ctl->connect("id_pressed", callable_mp(this, &TextEdit::menu_option));
- }
-
- // Reorganize context menu.
- menu->clear();
- if (editable) {
- menu->add_item(RTR("Cut"), MENU_CUT, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_cut") : Key::NONE);
- }
- menu->add_item(RTR("Copy"), MENU_COPY, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_copy") : Key::NONE);
- if (editable) {
- menu->add_item(RTR("Paste"), MENU_PASTE, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_paste") : Key::NONE);
- }
- if (selecting_enabled || editable) {
- menu->add_separator();
- }
- if (selecting_enabled) {
- menu->add_item(RTR("Select All"), MENU_SELECT_ALL, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_text_select_all") : Key::NONE);
- }
- if (editable) {
- menu->add_item(RTR("Clear"), MENU_CLEAR);
- menu->add_separator();
- menu->add_item(RTR("Undo"), MENU_UNDO, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_undo") : Key::NONE);
- menu->add_item(RTR("Redo"), MENU_REDO, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_redo") : Key::NONE);
- }
- menu->add_separator();
- menu->add_submenu_item(RTR("Text Writing Direction"), "DirMenu");
- menu->add_separator();
- menu->add_check_item(RTR("Display Control Characters"), MENU_DISPLAY_UCC);
- menu->set_item_checked(menu->get_item_index(MENU_DISPLAY_UCC), draw_control_chars);
- if (editable) {
- menu->add_submenu_item(RTR("Insert Control Character"), "CTLMenu");
- }
- 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);
-
- if (editable) {
- menu->set_item_disabled(menu->get_item_index(MENU_UNDO), !has_undo());
- menu->set_item_disabled(menu->get_item_index(MENU_REDO), !has_redo());
- }
-}
Key TextEdit::_get_menu_action_accelerator(const String &p_action) {
const List<Ref<InputEvent>> *events = InputMap::get_singleton()->action_get_events(p_action);
@@ -6824,6 +6761,112 @@ Key TextEdit::_get_menu_action_accelerator(const String &p_action) {
}
}
+void TextEdit::_generate_context_menu() {
+ menu = memnew(PopupMenu);
+ add_child(menu, false, INTERNAL_MODE_FRONT);
+
+ menu_dir = memnew(PopupMenu);
+ menu_dir->set_name("DirMenu");
+ menu_dir->add_radio_check_item(RTR("Same as Layout Direction"), MENU_DIR_INHERITED);
+ menu_dir->add_radio_check_item(RTR("Auto-Detect Direction"), MENU_DIR_AUTO);
+ menu_dir->add_radio_check_item(RTR("Left-to-Right"), MENU_DIR_LTR);
+ menu_dir->add_radio_check_item(RTR("Right-to-Left"), MENU_DIR_RTL);
+ menu->add_child(menu_dir, false, INTERNAL_MODE_FRONT);
+
+ menu_ctl = memnew(PopupMenu);
+ menu_ctl->set_name("CTLMenu");
+ menu_ctl->add_item(RTR("Left-to-Right Mark (LRM)"), MENU_INSERT_LRM);
+ menu_ctl->add_item(RTR("Right-to-Left Mark (RLM)"), MENU_INSERT_RLM);
+ menu_ctl->add_item(RTR("Start of Left-to-Right Embedding (LRE)"), MENU_INSERT_LRE);
+ menu_ctl->add_item(RTR("Start of Right-to-Left Embedding (RLE)"), MENU_INSERT_RLE);
+ menu_ctl->add_item(RTR("Start of Left-to-Right Override (LRO)"), MENU_INSERT_LRO);
+ menu_ctl->add_item(RTR("Start of Right-to-Left Override (RLO)"), MENU_INSERT_RLO);
+ menu_ctl->add_item(RTR("Pop Direction Formatting (PDF)"), MENU_INSERT_PDF);
+ menu_ctl->add_separator();
+ menu_ctl->add_item(RTR("Arabic Letter Mark (ALM)"), MENU_INSERT_ALM);
+ menu_ctl->add_item(RTR("Left-to-Right Isolate (LRI)"), MENU_INSERT_LRI);
+ menu_ctl->add_item(RTR("Right-to-Left Isolate (RLI)"), MENU_INSERT_RLI);
+ menu_ctl->add_item(RTR("First Strong Isolate (FSI)"), MENU_INSERT_FSI);
+ menu_ctl->add_item(RTR("Pop Direction Isolate (PDI)"), MENU_INSERT_PDI);
+ menu_ctl->add_separator();
+ menu_ctl->add_item(RTR("Zero-Width Joiner (ZWJ)"), MENU_INSERT_ZWJ);
+ menu_ctl->add_item(RTR("Zero-Width Non-Joiner (ZWNJ)"), MENU_INSERT_ZWNJ);
+ menu_ctl->add_item(RTR("Word Joiner (WJ)"), MENU_INSERT_WJ);
+ menu_ctl->add_item(RTR("Soft Hyphen (SHY)"), MENU_INSERT_SHY);
+ menu->add_child(menu_ctl, false, INTERNAL_MODE_FRONT);
+
+ menu->add_item(RTR("Cut"), MENU_CUT);
+ menu->add_item(RTR("Copy"), MENU_COPY);
+ menu->add_item(RTR("Paste"), MENU_PASTE);
+ menu->add_separator();
+ menu->add_item(RTR("Select All"), MENU_SELECT_ALL);
+ menu->add_item(RTR("Clear"), MENU_CLEAR);
+ menu->add_separator();
+ menu->add_item(RTR("Undo"), MENU_UNDO);
+ menu->add_item(RTR("Redo"), MENU_REDO);
+ menu->add_separator();
+ menu->add_submenu_item(RTR("Text Writing Direction"), "DirMenu", MENU_SUBMENU_TEXT_DIR);
+ menu->add_separator();
+ menu->add_check_item(RTR("Display Control Characters"), MENU_DISPLAY_UCC);
+ menu->add_submenu_item(RTR("Insert Control Character"), "CTLMenu", MENU_SUBMENU_INSERT_UCC);
+
+ menu->connect("id_pressed", callable_mp(this, &TextEdit::menu_option));
+ menu_dir->connect("id_pressed", callable_mp(this, &TextEdit::menu_option));
+ menu_ctl->connect("id_pressed", callable_mp(this, &TextEdit::menu_option));
+}
+
+void TextEdit::_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); \
+ }
+
+ 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
+}
+
/* Versioning */
void TextEdit::_push_current_op() {
if (pending_action_end) {
diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h
index 2ec2f39409..a084fa3833 100644
--- a/scene/gui/text_edit.h
+++ b/scene/gui/text_edit.h
@@ -87,11 +87,13 @@ public:
MENU_SELECT_ALL,
MENU_UNDO,
MENU_REDO,
+ MENU_SUBMENU_TEXT_DIR,
MENU_DIR_INHERITED,
MENU_DIR_AUTO,
MENU_DIR_LTR,
MENU_DIR_RTL,
MENU_DISPLAY_UCC,
+ MENU_SUBMENU_INSERT_UCC,
MENU_INSERT_LRM,
MENU_INSERT_RLM,
MENU_INSERT_LRE,
@@ -303,8 +305,9 @@ private:
PopupMenu *menu_dir = nullptr;
PopupMenu *menu_ctl = nullptr;
- void _generate_context_menu();
Key _get_menu_action_accelerator(const String &p_action);
+ void _generate_context_menu();
+ void _update_context_menu();
/* Versioning */
struct Caret;
diff --git a/scene/gui/view_panner.cpp b/scene/gui/view_panner.cpp
index e8d54e6937..145497fa61 100644
--- a/scene/gui/view_panner.cpp
+++ b/scene/gui/view_panner.cpp
@@ -43,36 +43,42 @@ bool ViewPanner::gui_input(const Ref<InputEvent> &p_event, Rect2 p_canvas_rect)
if (scroll_vec != Vector2() && mb->is_pressed()) {
if (control_scheme == SCROLL_PANS) {
if (mb->is_ctrl_pressed()) {
- scroll_vec.y *= mb->get_factor();
- callback_helper(zoom_callback, varray(scroll_vec, mb->get_position(), mb->is_alt_pressed()));
+ // Compute the zoom factor.
+ float zoom_factor = mb->get_factor() <= 0 ? 1.0 : mb->get_factor();
+ zoom_factor = ((scroll_zoom_factor - 1.0) * zoom_factor) + 1.0;
+ float zoom = (scroll_vec.x + scroll_vec.y) > 0 ? 1.0 / scroll_zoom_factor : scroll_zoom_factor;
+ callback_helper(zoom_callback, varray(zoom, mb->get_position(), p_event));
return true;
} else {
- Vector2 panning;
- if (mb->is_shift_pressed()) {
- panning.x += mb->get_factor() * scroll_vec.y;
- panning.y += mb->get_factor() * scroll_vec.x;
- } else {
- panning.y += mb->get_factor() * scroll_vec.y;
- panning.x += mb->get_factor() * scroll_vec.x;
+ Vector2 panning = scroll_vec * mb->get_factor();
+ if (pan_axis == PAN_AXIS_HORIZONTAL) {
+ panning = Vector2(panning.x + panning.y, 0);
+ } else if (pan_axis == PAN_AXIS_VERTICAL) {
+ panning = Vector2(0, panning.x + panning.y);
+ } else if (mb->is_shift_pressed()) {
+ panning = Vector2(panning.y, panning.x);
}
- callback_helper(scroll_callback, varray(panning, mb->is_alt_pressed()));
+ callback_helper(pan_callback, varray(-panning * scroll_speed, p_event));
return true;
}
} else {
if (mb->is_ctrl_pressed()) {
- Vector2 panning;
- if (mb->is_shift_pressed()) {
- panning.x += mb->get_factor() * scroll_vec.y;
- panning.y += mb->get_factor() * scroll_vec.x;
- } else {
- panning.y += mb->get_factor() * scroll_vec.y;
- panning.x += mb->get_factor() * scroll_vec.x;
+ Vector2 panning = scroll_vec * mb->get_factor();
+ if (pan_axis == PAN_AXIS_HORIZONTAL) {
+ panning = Vector2(panning.x + panning.y, 0);
+ } else if (pan_axis == PAN_AXIS_VERTICAL) {
+ panning = Vector2(0, panning.x + panning.y);
+ } else if (mb->is_shift_pressed()) {
+ panning = Vector2(panning.y, panning.x);
}
- callback_helper(scroll_callback, varray(panning, mb->is_alt_pressed()));
+ callback_helper(pan_callback, varray(-panning * scroll_speed, p_event));
return true;
} else if (!mb->is_shift_pressed()) {
- scroll_vec.y *= mb->get_factor();
- callback_helper(zoom_callback, varray(scroll_vec, mb->get_position(), mb->is_alt_pressed()));
+ // Compute the zoom factor.
+ float zoom_factor = mb->get_factor() <= 0 ? 1.0 : mb->get_factor();
+ zoom_factor = ((scroll_zoom_factor - 1.0) * zoom_factor) + 1.0;
+ float zoom = (scroll_vec.x + scroll_vec.y) > 0 ? 1.0 / scroll_zoom_factor : scroll_zoom_factor;
+ callback_helper(zoom_callback, varray(zoom, mb->get_position(), p_event));
return true;
}
}
@@ -102,14 +108,31 @@ bool ViewPanner::gui_input(const Ref<InputEvent> &p_event, Rect2 p_canvas_rect)
if (mm.is_valid()) {
if (is_dragging) {
if (p_canvas_rect != Rect2()) {
- callback_helper(pan_callback, varray(Input::get_singleton()->warp_mouse_motion(mm, p_canvas_rect)));
+ callback_helper(pan_callback, varray(Input::get_singleton()->warp_mouse_motion(mm, p_canvas_rect), p_event));
} else {
- callback_helper(pan_callback, varray(mm->get_relative()));
+ callback_helper(pan_callback, varray(mm->get_relative(), p_event));
}
return true;
}
}
+ Ref<InputEventMagnifyGesture> magnify_gesture = p_event;
+ if (magnify_gesture.is_valid()) {
+ // Zoom gesture
+ callback_helper(zoom_callback, varray(magnify_gesture->get_factor(), magnify_gesture->get_position(), p_event));
+ return true;
+ }
+
+ Ref<InputEventPanGesture> pan_gesture = p_event;
+ if (pan_gesture.is_valid()) {
+ callback_helper(pan_callback, varray(-pan_gesture->get_delta(), p_event));
+ }
+
+ Ref<InputEventScreenDrag> screen_drag = p_event;
+ if (screen_drag.is_valid()) {
+ callback_helper(pan_callback, varray(screen_drag->get_relative(), p_event));
+ }
+
Ref<InputEventKey> k = p_event;
if (k.is_valid()) {
if (pan_view_shortcut.is_valid() && pan_view_shortcut->matches_event(k)) {
@@ -140,8 +163,7 @@ void ViewPanner::callback_helper(Callable p_callback, Vector<Variant> p_args) {
p_callback.callp(argptr, p_args.size(), result, ce);
}
-void ViewPanner::set_callbacks(Callable p_scroll_callback, Callable p_pan_callback, Callable p_zoom_callback) {
- scroll_callback = p_scroll_callback;
+void ViewPanner::set_callbacks(Callable p_pan_callback, Callable p_zoom_callback) {
pan_callback = p_pan_callback;
zoom_callback = p_zoom_callback;
}
@@ -163,6 +185,20 @@ void ViewPanner::set_simple_panning_enabled(bool p_enabled) {
simple_panning_enabled = p_enabled;
}
+void ViewPanner::set_scroll_speed(int p_scroll_speed) {
+ ERR_FAIL_COND(p_scroll_speed <= 0);
+ scroll_speed = p_scroll_speed;
+}
+
+void ViewPanner::set_scroll_zoom_factor(float p_scroll_zoom_factor) {
+ ERR_FAIL_COND(p_scroll_zoom_factor <= 1.0);
+ scroll_zoom_factor = p_scroll_zoom_factor;
+}
+
+void ViewPanner::set_pan_axis(PanAxis p_pan_axis) {
+ pan_axis = p_pan_axis;
+}
+
void ViewPanner::setup(ControlScheme p_scheme, Ref<Shortcut> p_shortcut, bool p_simple_panning) {
set_control_scheme(p_scheme);
set_pan_shortcut(p_shortcut);
diff --git a/scene/gui/view_panner.h b/scene/gui/view_panner.h
index 861574a80c..60d36ca04c 100644
--- a/scene/gui/view_panner.h
+++ b/scene/gui/view_panner.h
@@ -45,7 +45,17 @@ public:
SCROLL_PANS,
};
+ enum PanAxis {
+ PAN_AXIS_BOTH,
+ PAN_AXIS_HORIZONTAL,
+ PAN_AXIS_VERTICAL,
+ };
+
private:
+ int scroll_speed = 32;
+ float scroll_zoom_factor = 1.1;
+ PanAxis pan_axis = PAN_AXIS_BOTH;
+
bool is_dragging = false;
bool pan_key_pressed = false;
bool force_drag = false;
@@ -55,7 +65,6 @@ private:
Ref<Shortcut> pan_view_shortcut;
- Callable scroll_callback;
Callable pan_callback;
Callable zoom_callback;
@@ -63,11 +72,14 @@ private:
ControlScheme control_scheme = SCROLL_ZOOMS;
public:
- void set_callbacks(Callable p_scroll_callback, Callable p_pan_callback, Callable p_zoom_callback);
+ void set_callbacks(Callable p_pan_callback, Callable p_zoom_callback);
void set_control_scheme(ControlScheme p_scheme);
void set_enable_rmb(bool p_enable);
void set_pan_shortcut(Ref<Shortcut> p_shortcut);
void set_simple_panning_enabled(bool p_enabled);
+ void set_scroll_speed(int p_scroll_speed);
+ void set_scroll_zoom_factor(float p_scroll_zoom_factor);
+ void set_pan_axis(PanAxis p_pan_axis);
void setup(ControlScheme p_scheme, Ref<Shortcut> p_shortcut, bool p_simple_panning);