summaryrefslogtreecommitdiff
path: root/scene/gui
diff options
context:
space:
mode:
Diffstat (limited to 'scene/gui')
-rw-r--r--scene/gui/code_edit.cpp20
-rw-r--r--scene/gui/control.cpp8
-rw-r--r--scene/gui/file_dialog.cpp7
-rw-r--r--scene/gui/gradient_edit.h1
-rw-r--r--scene/gui/graph_edit.cpp18
-rw-r--r--scene/gui/graph_edit.h5
-rw-r--r--scene/gui/popup_menu.cpp6
-rw-r--r--scene/gui/rich_text_label.cpp12
-rw-r--r--scene/gui/text_edit.cpp48
-rw-r--r--scene/gui/text_edit.h11
-rw-r--r--scene/gui/tree.cpp62
-rw-r--r--scene/gui/tree.h8
-rw-r--r--scene/gui/view_panner.cpp101
-rw-r--r--scene/gui/view_panner.h20
14 files changed, 221 insertions, 106 deletions
diff --git a/scene/gui/code_edit.cpp b/scene/gui/code_edit.cpp
index 040075150b..8da7264b02 100644
--- a/scene/gui/code_edit.cpp
+++ b/scene/gui/code_edit.cpp
@@ -1793,7 +1793,7 @@ void CodeEdit::request_code_completion(bool p_force) {
}
if (p_force) {
- emit_signal(SNAME("request_code_completion"));
+ emit_signal(SNAME("code_completion_requested"));
return;
}
@@ -1801,9 +1801,9 @@ void CodeEdit::request_code_completion(bool p_force) {
int ofs = CLAMP(get_caret_column(), 0, line.length());
if (ofs > 0 && (is_in_string(get_caret_line(), ofs) != -1 || _is_char(line[ofs - 1]) || code_completion_prefixes.has(line[ofs - 1]))) {
- emit_signal(SNAME("request_code_completion"));
+ emit_signal(SNAME("code_completion_requested"));
} else if (ofs > 1 && line[ofs - 1] == ' ' && code_completion_prefixes.has(line[ofs - 2])) {
- emit_signal(SNAME("request_code_completion"));
+ emit_signal(SNAME("code_completion_requested"));
}
}
@@ -2085,8 +2085,6 @@ void CodeEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_auto_brace_completion_close_key", "open_key"), &CodeEdit::get_auto_brace_completion_close_key);
/* Main Gutter */
- ClassDB::bind_method(D_METHOD("_main_gutter_draw_callback"), &CodeEdit::_main_gutter_draw_callback);
-
ClassDB::bind_method(D_METHOD("set_draw_breakpoints_gutter", "enable"), &CodeEdit::set_draw_breakpoints_gutter);
ClassDB::bind_method(D_METHOD("is_drawing_breakpoints_gutter"), &CodeEdit::is_drawing_breakpoints_gutter);
@@ -2115,16 +2113,12 @@ void CodeEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_executing_lines"), &CodeEdit::get_executing_lines);
/* Line numbers */
- ClassDB::bind_method(D_METHOD("_line_number_draw_callback"), &CodeEdit::_line_number_draw_callback);
-
ClassDB::bind_method(D_METHOD("set_draw_line_numbers", "enable"), &CodeEdit::set_draw_line_numbers);
ClassDB::bind_method(D_METHOD("is_draw_line_numbers_enabled"), &CodeEdit::is_draw_line_numbers_enabled);
ClassDB::bind_method(D_METHOD("set_line_numbers_zero_padded", "enable"), &CodeEdit::set_line_numbers_zero_padded);
ClassDB::bind_method(D_METHOD("is_line_numbers_zero_padded"), &CodeEdit::is_line_numbers_zero_padded);
/* Fold Gutter */
- ClassDB::bind_method(D_METHOD("_fold_gutter_draw_callback"), &CodeEdit::_fold_gutter_draw_callback);
-
ClassDB::bind_method(D_METHOD("set_draw_fold_gutter", "enable"), &CodeEdit::set_draw_fold_gutter);
ClassDB::bind_method(D_METHOD("is_drawing_fold_gutter"), &CodeEdit::is_drawing_fold_gutter);
@@ -2267,7 +2261,7 @@ void CodeEdit::_bind_methods() {
ADD_SIGNAL(MethodInfo("breakpoint_toggled", PropertyInfo(Variant::INT, "line")));
/* Code Completion */
- ADD_SIGNAL(MethodInfo("request_code_completion"));
+ ADD_SIGNAL(MethodInfo("code_completion_requested"));
/* Symbol lookup */
ADD_SIGNAL(MethodInfo("symbol_lookup", PropertyInfo(Variant::STRING, "symbol"), PropertyInfo(Variant::INT, "line"), PropertyInfo(Variant::INT, "column")));
@@ -3084,7 +3078,7 @@ CodeEdit::CodeEdit() {
set_gutter_draw(gutter_idx, false);
set_gutter_overwritable(gutter_idx, true);
set_gutter_type(gutter_idx, GUTTER_TYPE_CUSTOM);
- set_gutter_custom_draw(gutter_idx, this, "_main_gutter_draw_callback");
+ set_gutter_custom_draw(gutter_idx, callable_mp(this, &CodeEdit::_main_gutter_draw_callback));
gutter_idx++;
/* Line numbers */
@@ -3092,7 +3086,7 @@ CodeEdit::CodeEdit() {
set_gutter_name(gutter_idx, "line_numbers");
set_gutter_draw(gutter_idx, false);
set_gutter_type(gutter_idx, GUTTER_TYPE_CUSTOM);
- set_gutter_custom_draw(gutter_idx, this, "_line_number_draw_callback");
+ set_gutter_custom_draw(gutter_idx, callable_mp(this, &CodeEdit::_line_number_draw_callback));
gutter_idx++;
/* Fold Gutter */
@@ -3100,7 +3094,7 @@ CodeEdit::CodeEdit() {
set_gutter_name(gutter_idx, "fold_gutter");
set_gutter_draw(gutter_idx, false);
set_gutter_type(gutter_idx, GUTTER_TYPE_CUSTOM);
- set_gutter_custom_draw(gutter_idx, this, "_fold_gutter_draw_callback");
+ set_gutter_custom_draw(gutter_idx, callable_mp(this, &CodeEdit::_fold_gutter_draw_callback));
gutter_idx++;
connect("lines_edited_from", callable_mp(this, &CodeEdit::_lines_edited_from));
diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp
index 11d7946866..562ea8a8f7 100644
--- a/scene/gui/control.cpp
+++ b/scene/gui/control.cpp
@@ -240,7 +240,7 @@ bool Control::_set(const StringName &p_name, const Variant &p_value) {
return false;
}
- if (p_value.get_type() == Variant::NIL) {
+ if (p_value.get_type() == Variant::NIL || (p_value.get_type() == Variant::OBJECT && (Object *)p_value == nullptr)) {
if (name.begins_with("theme_override_icons/") || name.begins_with("custom_icons/")) {
String dname = name.get_slicec('/', 1);
if (data.icon_override.has(dname)) {
@@ -733,8 +733,10 @@ void Control::_notification(int p_notification) {
} break;
case NOTIFICATION_TRANSLATION_CHANGED:
case NOTIFICATION_LAYOUT_DIRECTION_CHANGED: {
- data.is_rtl_dirty = true;
- _size_changed();
+ if (is_inside_tree()) {
+ data.is_rtl_dirty = true;
+ _size_changed();
+ }
} break;
}
}
diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp
index 44ef641cb8..e5bd6f4882 100644
--- a/scene/gui/file_dialog.cpp
+++ b/scene/gui/file_dialog.cpp
@@ -110,6 +110,9 @@ void FileDialog::_notification(int p_what) {
show_hidden->set_icon(vbox->get_theme_icon(SNAME("toggle_hidden"), SNAME("FileDialog")));
_theme_changed();
}
+ if (p_what == NOTIFICATION_TRANSLATION_CHANGED) {
+ update_filters();
+ }
}
void FileDialog::unhandled_input(const Ref<InputEvent> &p_event) {
@@ -638,7 +641,7 @@ void FileDialog::update_filters() {
all_filters += ", ...";
}
- filter->add_item(String(TTRC("All Recognized")) + " (" + all_filters + ")");
+ filter->add_item(RTR("All Recognized") + " (" + all_filters + ")");
}
for (int i = 0; i < filters.size(); i++) {
String flt = filters[i].get_slice(";", 0).strip_edges();
@@ -650,7 +653,7 @@ void FileDialog::update_filters() {
}
}
- filter->add_item(TTRC("All Files (*)"));
+ filter->add_item(RTR("All Files") + " (*)");
}
void FileDialog::clear_filters() {
diff --git a/scene/gui/gradient_edit.h b/scene/gui/gradient_edit.h
index 407f61f7c1..67531d4f4a 100644
--- a/scene/gui/gradient_edit.h
+++ b/scene/gui/gradient_edit.h
@@ -33,7 +33,6 @@
#include "scene/gui/color_picker.h"
#include "scene/gui/popup.h"
-#include "scene/resources/default_theme/theme_data.h"
#include "scene/resources/gradient.h"
class GradientEdit : public Control {
diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp
index 79b73f7cc3..2d58733d8f 100644
--- a/scene/gui/graph_edit.cpp
+++ b/scene/gui/graph_edit.cpp
@@ -1070,7 +1070,9 @@ void GraphEdit::set_selected(Node *p_child) {
void GraphEdit::gui_input(const Ref<InputEvent> &p_ev) {
ERR_FAIL_COND(p_ev.is_null());
- panner->gui_input(p_ev);
+ if (panner->gui_input(p_ev, warped_panning ? get_global_rect() : Rect2())) {
+ return;
+ }
Ref<InputEventMouseMotion> mm = p_ev;
@@ -1272,7 +1274,7 @@ void GraphEdit::gui_input(const Ref<InputEvent> &p_ev) {
if (_filter_input(b->get_position())) {
return;
}
- if (Input::get_singleton()->is_key_pressed(Key::SPACE)) {
+ if (panner->is_panning()) {
return;
}
@@ -1367,7 +1369,7 @@ void GraphEdit::_pan_callback(Vector2 p_scroll_vec) {
v_scroll->set_value(v_scroll->get_value() - p_scroll_vec.y);
}
-void GraphEdit::_zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin) {
+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);
}
@@ -1678,6 +1680,14 @@ HBoxContainer *GraphEdit::get_zoom_hbox() {
return zoom_hb;
}
+Ref<ViewPanner> GraphEdit::get_panner() {
+ return panner;
+}
+
+void GraphEdit::set_warped_panning(bool p_warped) {
+ warped_panning = p_warped;
+}
+
int GraphEdit::_set_operations(SET_OPERATIONS p_operation, Set<StringName> &r_u, const Set<StringName> &r_v) {
switch (p_operation) {
case GraphEdit::IS_EQUAL: {
@@ -2305,7 +2315,6 @@ GraphEdit::GraphEdit() {
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_disable_rmb(true);
top_layer = memnew(GraphEditFilter(this));
add_child(top_layer, false, INTERNAL_MODE_BACK);
@@ -2313,6 +2322,7 @@ GraphEdit::GraphEdit() {
top_layer->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
top_layer->connect("draw", callable_mp(this, &GraphEdit::_top_layer_draw));
top_layer->connect("gui_input", callable_mp(this, &GraphEdit::_top_layer_input));
+ top_layer->connect("focus_exited", callable_mp(panner.ptr(), &ViewPanner::release_pan_key));
connections_layer = memnew(Control);
add_child(connections_layer, false, INTERNAL_MODE_FRONT);
diff --git a/scene/gui/graph_edit.h b/scene/gui/graph_edit.h
index 4e998d30a7..e0827a99a4 100644
--- a/scene/gui/graph_edit.h
+++ b/scene/gui/graph_edit.h
@@ -130,9 +130,10 @@ private:
float port_grab_distance_vertical;
Ref<ViewPanner> panner;
+ bool warped_panning = true;
void _scroll_callback(Vector2 p_scroll_vec);
void _pan_callback(Vector2 p_scroll_vec);
- void _zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin);
+ void _zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin, bool p_alt);
bool connecting = false;
String connecting_from;
@@ -348,6 +349,8 @@ public:
bool is_connection_lines_antialiased() const;
HBoxContainer *get_zoom_hbox();
+ Ref<ViewPanner> get_panner();
+ void set_warped_panning(bool p_warped);
void arrange_nodes();
diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp
index d7139d0140..c9fddc3e17 100644
--- a/scene/gui/popup_menu.cpp
+++ b/scene/gui/popup_menu.cpp
@@ -1403,12 +1403,12 @@ void PopupMenu::activate_item(int p_item) {
need_hide = false;
}
- emit_signal(SNAME("id_pressed"), id);
- emit_signal(SNAME("index_pressed"), p_item);
-
if (need_hide) {
hide();
}
+
+ emit_signal(SNAME("id_pressed"), id);
+ emit_signal(SNAME("index_pressed"), p_item);
}
void PopupMenu::remove_item(int p_idx) {
diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp
index 669bdab637..b50fad0e42 100644
--- a/scene/gui/rich_text_label.cpp
+++ b/scene/gui/rich_text_label.cpp
@@ -2197,10 +2197,6 @@ void RichTextLabel::_validate_line_caches(ItemFrame *p_frame) {
}
// Resize lines without reshaping.
- Size2 size = get_size();
- if (fixed_width != -1) {
- size.width = fixed_width;
- }
Rect2 text_rect = _get_text_rect();
Ref<Font> base_font = get_theme_font(SNAME("normal_font"));
@@ -2221,7 +2217,7 @@ void RichTextLabel::_validate_line_caches(ItemFrame *p_frame) {
vscroll->set_max(total_height);
vscroll->set_page(text_rect.size.height);
if (scroll_follow && scroll_following) {
- vscroll->set_value(total_height - size.height);
+ vscroll->set_value(total_height);
}
updating_scroll = false;
@@ -2232,10 +2228,6 @@ void RichTextLabel::_validate_line_caches(ItemFrame *p_frame) {
}
// Shape invalid lines.
- Size2 size = get_size();
- if (fixed_width != -1) {
- size.width = fixed_width;
- }
Rect2 text_rect = _get_text_rect();
Ref<Font> base_font = get_theme_font(SNAME("normal_font"));
@@ -2258,7 +2250,7 @@ void RichTextLabel::_validate_line_caches(ItemFrame *p_frame) {
vscroll->set_max(total_height);
vscroll->set_page(text_rect.size.height);
if (scroll_follow && scroll_following) {
- vscroll->set_value(total_height - size.height);
+ vscroll->set_value(total_height);
}
updating_scroll = false;
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index 671c2d951a..d6b449abd1 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -1008,15 +1008,17 @@ void TextEdit::_notification(int p_what) {
icon->draw_rect(ci, gutter_rect, false, get_line_gutter_item_color(line, g));
} break;
case GUTTER_TYPE_CUSTOM: {
- if (gutter.custom_draw_obj.is_valid()) {
- Object *cdo = ObjectDB::get_instance(gutter.custom_draw_obj);
- if (cdo) {
- Rect2i gutter_rect = Rect2i(Point2i(gutter_offset, ofs_y), Size2i(gutter.width, row_height));
- if (rtl) {
- gutter_rect.position.x = size.width - gutter_rect.position.x - gutter_rect.size.x;
- }
- cdo->call(gutter.custom_draw_callback, line, g, Rect2(gutter_rect));
+ if (gutter.custom_draw_callback.is_valid()) {
+ Rect2i gutter_rect = Rect2i(Point2i(gutter_offset, ofs_y), Size2i(gutter.width, row_height));
+ if (rtl) {
+ gutter_rect.position.x = size.width - gutter_rect.position.x - gutter_rect.size.x;
}
+
+ Variant args[3] = { line, g, Rect2(gutter_rect) };
+ const Variant *argp[] = { &args[0], &args[1], &args[2] };
+ Callable::CallError ce;
+ Variant ret;
+ gutter.custom_draw_callback.call(argp, 3, ret, ce);
}
} break;
}
@@ -2598,8 +2600,7 @@ Control::CursorShape TextEdit::get_cursor_shape(const Point2 &p_pos) const {
}
String TextEdit::get_tooltip(const Point2 &p_pos) const {
- Object *tooltip_obj = ObjectDB::get_instance(tooltip_obj_id);
- if (!tooltip_obj) {
+ if (!tooltip_callback.is_valid()) {
return Control::get_tooltip(p_pos);
}
Point2i pos = get_line_column_at_pos(p_pos);
@@ -2612,19 +2613,20 @@ String TextEdit::get_tooltip(const Point2 &p_pos) const {
}
int beg, end;
if (select_word(s, col, beg, end)) {
- String tt = tooltip_obj->call(tooltip_func, s.substr(beg, end - beg), tooltip_ud);
-
- return tt;
+ Variant args[1] = { s.substr(beg, end - beg) };
+ const Variant *argp[] = { &args[0] };
+ Callable::CallError ce;
+ Variant ret;
+ tooltip_callback.call(argp, 1, ret, ce);
+ ERR_FAIL_COND_V_MSG(ce.error != Callable::CallError::CALL_OK, "", "Failed to call custom tooltip.");
+ return ret;
}
return Control::get_tooltip(p_pos);
}
-void TextEdit::set_tooltip_request_func(Object *p_obj, const StringName &p_function, const Variant &p_udata) {
- ERR_FAIL_NULL(p_obj);
- tooltip_obj_id = p_obj->get_instance_id();
- tooltip_func = p_function;
- tooltip_ud = p_udata;
+void TextEdit::set_tooltip_request_func(const Callable &p_tooltip_callback) {
+ tooltip_callback = p_tooltip_callback;
}
/* Text */
@@ -4658,12 +4660,10 @@ void TextEdit::merge_gutters(int p_from_line, int p_to_line) {
update();
}
-void TextEdit::set_gutter_custom_draw(int p_gutter, Object *p_object, const StringName &p_callback) {
+void TextEdit::set_gutter_custom_draw(int p_gutter, const Callable &p_draw_callback) {
ERR_FAIL_INDEX(p_gutter, gutters.size());
- ERR_FAIL_NULL(p_object);
- gutters.write[p_gutter].custom_draw_obj = p_object->get_instance_id();
- gutters.write[p_gutter].custom_draw_callback = p_callback;
+ gutters.write[p_gutter].custom_draw_callback = p_draw_callback;
update();
}
@@ -4953,7 +4953,7 @@ void TextEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("search", "text", "flags", "from_line", "from_colum"), &TextEdit::search);
/* Tooltip */
- ClassDB::bind_method(D_METHOD("set_tooltip_request_func", "object", "callback", "data"), &TextEdit::set_tooltip_request_func);
+ ClassDB::bind_method(D_METHOD("set_tooltip_request_func", "callback"), &TextEdit::set_tooltip_request_func);
/* Mouse */
ClassDB::bind_method(D_METHOD("get_local_mouse_pos"), &TextEdit::get_local_mouse_pos);
@@ -5125,7 +5125,7 @@ void TextEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_gutter_overwritable", "gutter", "overwritable"), &TextEdit::set_gutter_overwritable);
ClassDB::bind_method(D_METHOD("is_gutter_overwritable", "gutter"), &TextEdit::is_gutter_overwritable);
ClassDB::bind_method(D_METHOD("merge_gutters", "from_line", "to_line"), &TextEdit::merge_gutters);
- ClassDB::bind_method(D_METHOD("set_gutter_custom_draw", "column", "object", "callback"), &TextEdit::set_gutter_custom_draw);
+ ClassDB::bind_method(D_METHOD("set_gutter_custom_draw", "column", "draw_callback"), &TextEdit::set_gutter_custom_draw);
ClassDB::bind_method(D_METHOD("get_total_gutter_width"), &TextEdit::get_total_gutter_width);
// Line gutters.
diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h
index 57b48b5f52..0d0f4f6dba 100644
--- a/scene/gui/text_edit.h
+++ b/scene/gui/text_edit.h
@@ -120,8 +120,7 @@ private:
bool clickable = false;
bool overwritable = false;
- ObjectID custom_draw_obj = ObjectID();
- StringName custom_draw_callback;
+ Callable custom_draw_callback;
};
class Text {
@@ -332,9 +331,7 @@ private:
int _get_column_pos_of_word(const String &p_key, const String &p_search, uint32_t p_search_flags, int p_from_column) const;
/* Tooltip. */
- ObjectID tooltip_obj_id;
- StringName tooltip_func;
- Variant tooltip_ud;
+ Callable tooltip_callback;
/* Mouse */
struct LineDrawingCache {
@@ -620,7 +617,7 @@ public:
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 String get_tooltip(const Point2 &p_pos) const override;
- void set_tooltip_request_func(Object *p_obj, const StringName &p_function, const Variant &p_udata);
+ void set_tooltip_request_func(const Callable &p_tooltip_callback);
/* Text */
// Text properties.
@@ -884,7 +881,7 @@ public:
void merge_gutters(int p_from_line, int p_to_line);
- void set_gutter_custom_draw(int p_gutter, Object *p_object, const StringName &p_callback);
+ void set_gutter_custom_draw(int p_gutter, const Callable &p_draw_callback);
// Line gutters.
void set_line_gutter_metadata(int p_line, int p_gutter, const Variant &p_metadata);
diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp
index e46de43f1e..e75d147134 100644
--- a/scene/gui/tree.cpp
+++ b/scene/gui/tree.cpp
@@ -198,6 +198,65 @@ bool TreeItem::is_indeterminate(int p_column) const {
return cells[p_column].indeterminate;
}
+void TreeItem::propagate_check(int p_column, bool p_emit_signal) {
+ bool ch = cells[p_column].checked;
+
+ if (p_emit_signal) {
+ tree->emit_signal("check_propagated_to_item", this, p_column);
+ }
+ _propagate_check_through_children(p_column, ch, p_emit_signal);
+ _propagate_check_through_parents(p_column, p_emit_signal);
+}
+
+void TreeItem::_propagate_check_through_children(int p_column, bool p_checked, bool p_emit_signal) {
+ TreeItem *current = get_first_child();
+ while (current) {
+ current->set_checked(p_column, p_checked);
+ if (p_emit_signal) {
+ current->tree->emit_signal("check_propagated_to_item", current, p_column);
+ }
+ current->_propagate_check_through_children(p_column, p_checked, p_emit_signal);
+ current = current->get_next();
+ }
+}
+
+void TreeItem::_propagate_check_through_parents(int p_column, bool p_emit_signal) {
+ TreeItem *current = get_parent();
+ if (!current) {
+ return;
+ }
+
+ bool all_unchecked_and_not_indeterminate = true;
+ bool any_unchecked_or_indeterminate = false;
+
+ TreeItem *child_item = current->get_first_child();
+ while (child_item) {
+ if (!child_item->is_checked(p_column)) {
+ any_unchecked_or_indeterminate = true;
+ if (child_item->is_indeterminate(p_column)) {
+ all_unchecked_and_not_indeterminate = false;
+ break;
+ }
+ } else {
+ all_unchecked_and_not_indeterminate = false;
+ }
+ child_item = child_item->get_next();
+ }
+
+ if (all_unchecked_and_not_indeterminate) {
+ current->set_checked(p_column, false);
+ } else if (any_unchecked_or_indeterminate) {
+ current->set_indeterminate(p_column, true);
+ } else {
+ current->set_checked(p_column, true);
+ }
+
+ if (p_emit_signal) {
+ current->tree->emit_signal("check_propagated_to_item", current, p_column);
+ }
+ current->_propagate_check_through_parents(p_column, p_emit_signal);
+}
+
void TreeItem::set_text(int p_column, String p_text) {
ERR_FAIL_INDEX(p_column, cells.size());
cells.write[p_column].text = p_text;
@@ -1141,6 +1200,8 @@ void TreeItem::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_checked", "column"), &TreeItem::is_checked);
ClassDB::bind_method(D_METHOD("is_indeterminate", "column"), &TreeItem::is_indeterminate);
+ ClassDB::bind_method(D_METHOD("propagate_check", "column", "emit_signal"), &TreeItem::propagate_check, DEFVAL(true));
+
ClassDB::bind_method(D_METHOD("set_text", "column", "text"), &TreeItem::set_text);
ClassDB::bind_method(D_METHOD("get_text", "column"), &TreeItem::get_text);
@@ -4847,6 +4908,7 @@ void Tree::_bind_methods() {
ADD_SIGNAL(MethodInfo("item_custom_button_pressed"));
ADD_SIGNAL(MethodInfo("item_double_clicked"));
ADD_SIGNAL(MethodInfo("item_collapsed", PropertyInfo(Variant::OBJECT, "item", PROPERTY_HINT_RESOURCE_TYPE, "TreeItem")));
+ ADD_SIGNAL(MethodInfo("check_propagated_to_item", PropertyInfo(Variant::OBJECT, "item", PROPERTY_HINT_RESOURCE_TYPE, "TreeItem"), PropertyInfo(Variant::INT, "column")));
//ADD_SIGNAL( MethodInfo("item_double_clicked" ) );
ADD_SIGNAL(MethodInfo("button_pressed", PropertyInfo(Variant::OBJECT, "item", PROPERTY_HINT_RESOURCE_TYPE, "TreeItem"), PropertyInfo(Variant::INT, "column"), PropertyInfo(Variant::INT, "id")));
ADD_SIGNAL(MethodInfo("custom_popup_edited", PropertyInfo(Variant::BOOL, "arrow_clicked")));
diff --git a/scene/gui/tree.h b/scene/gui/tree.h
index c60c87564e..33170cad35 100644
--- a/scene/gui/tree.h
+++ b/scene/gui/tree.h
@@ -212,6 +212,14 @@ public:
bool is_checked(int p_column) const;
bool is_indeterminate(int p_column) const;
+ void propagate_check(int p_column, bool p_emit_signal = true);
+
+private:
+ // Check helpers.
+ void _propagate_check_through_children(int p_column, bool p_checked, bool p_emit_signal);
+ void _propagate_check_through_parents(int p_column, bool p_emit_signal);
+
+public:
void set_text(int p_column, String p_text);
String get_text(int p_column) const;
diff --git a/scene/gui/view_panner.cpp b/scene/gui/view_panner.cpp
index ba5e8d4a17..0fbc4485ab 100644
--- a/scene/gui/view_panner.cpp
+++ b/scene/gui/view_panner.cpp
@@ -31,22 +31,18 @@
#include "view_panner.h"
#include "core/input/input.h"
+#include "core/input/shortcut.h"
#include "core/os/keyboard.h"
bool ViewPanner::gui_input(const Ref<InputEvent> &p_event, Rect2 p_canvas_rect) {
Ref<InputEventMouseButton> mb = p_event;
if (mb.is_valid()) {
- // Alt modifier is unused, so ignore such events.
- if (mb->is_alt_pressed()) {
- return false;
- }
-
Vector2i scroll_vec = Vector2((mb->get_button_index() == MouseButton::WHEEL_RIGHT) - (mb->get_button_index() == MouseButton::WHEEL_LEFT), (mb->get_button_index() == MouseButton::WHEEL_DOWN) - (mb->get_button_index() == MouseButton::WHEEL_UP));
if (scroll_vec != Vector2()) {
if (control_scheme == SCROLL_PANS) {
if (mb->is_ctrl_pressed()) {
scroll_vec.y *= mb->get_factor();
- callback_helper(zoom_callback, scroll_vec, mb->get_position());
+ callback_helper(zoom_callback, varray(scroll_vec, mb->get_position(), mb->is_alt_pressed()));
return true;
} else {
Vector2 panning;
@@ -57,7 +53,7 @@ bool ViewPanner::gui_input(const Ref<InputEvent> &p_event, Rect2 p_canvas_rect)
panning.y += mb->get_factor() * scroll_vec.y;
panning.x += mb->get_factor() * scroll_vec.x;
}
- callback_helper(scroll_callback, panning);
+ callback_helper(scroll_callback, varray(panning));
return true;
}
} else {
@@ -70,23 +66,28 @@ bool ViewPanner::gui_input(const Ref<InputEvent> &p_event, Rect2 p_canvas_rect)
panning.y += mb->get_factor() * scroll_vec.y;
panning.x += mb->get_factor() * scroll_vec.x;
}
- callback_helper(scroll_callback, panning);
+ callback_helper(scroll_callback, varray(panning));
return true;
} else if (!mb->is_shift_pressed()) {
scroll_vec.y *= mb->get_factor();
- callback_helper(zoom_callback, scroll_vec, mb->get_position());
+ callback_helper(zoom_callback, varray(scroll_vec, mb->get_position(), mb->is_alt_pressed()));
return true;
}
}
}
- if (mb->get_button_index() == MouseButton::MIDDLE || (mb->get_button_index() == MouseButton::RIGHT && !disable_rmb) || (mb->get_button_index() == MouseButton::LEFT && (Input::get_singleton()->is_key_pressed(Key::SPACE) || (is_dragging && !mb->is_pressed())))) {
+ // Use Alt only for scrolling.
+ if (mb->is_alt_pressed()) {
+ return false;
+ }
+
+ if (mb->get_button_index() == MouseButton::MIDDLE || (enable_rmb && mb->get_button_index() == MouseButton::RIGHT) || (!simple_panning_enabled && mb->get_button_index() == MouseButton::LEFT && is_panning())) {
if (mb->is_pressed()) {
is_dragging = true;
} else {
is_dragging = false;
}
- return true;
+ return mb->get_button_index() != MouseButton::LEFT || mb->is_pressed(); // Don't consume LMB release events (it fixes some selection problems).
}
}
@@ -94,9 +95,20 @@ 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, 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)));
} else {
- callback_helper(pan_callback, mm->get_relative());
+ callback_helper(pan_callback, varray(mm->get_relative()));
+ }
+ return true;
+ }
+ }
+
+ Ref<InputEventKey> k = p_event;
+ if (k.is_valid()) {
+ if (pan_view_shortcut.is_valid() && pan_view_shortcut->matches_event(k)) {
+ pan_key_pressed = k->is_pressed();
+ if (simple_panning_enabled || (Input::get_singleton()->get_mouse_button_mask() & MouseButton::LEFT) != MouseButton::NONE) {
+ is_dragging = pan_key_pressed;
}
return true;
}
@@ -105,26 +117,20 @@ bool ViewPanner::gui_input(const Ref<InputEvent> &p_event, Rect2 p_canvas_rect)
return false;
}
-void ViewPanner::callback_helper(Callable p_callback, Vector2 p_arg1, Vector2 p_arg2) {
- if (p_callback == zoom_callback) {
- const Variant **argptr = (const Variant **)alloca(sizeof(Variant *) * 2);
- Variant var1 = p_arg1;
- argptr[0] = &var1;
- Variant var2 = p_arg2;
- argptr[1] = &var2;
-
- Variant result;
- Callable::CallError ce;
- p_callback.call(argptr, 2, result, ce);
- } else {
- const Variant **argptr = (const Variant **)alloca(sizeof(Variant *));
- Variant var = p_arg1;
- argptr[0] = &var;
-
- Variant result;
- Callable::CallError ce;
- p_callback.call(argptr, 1, result, ce);
+void ViewPanner::release_pan_key() {
+ pan_key_pressed = false;
+ is_dragging = false;
+}
+
+void ViewPanner::callback_helper(Callable p_callback, Vector<Variant> p_args) {
+ const Variant **argptr = (const Variant **)alloca(sizeof(Variant *) * p_args.size());
+ for (int i = 0; i < p_args.size(); i++) {
+ argptr[i] = &p_args[i];
}
+
+ Variant result;
+ Callable::CallError ce;
+ p_callback.call(argptr, p_args.size(), result, ce);
}
void ViewPanner::set_callbacks(Callable p_scroll_callback, Callable p_pan_callback, Callable p_zoom_callback) {
@@ -137,6 +143,33 @@ void ViewPanner::set_control_scheme(ControlScheme p_scheme) {
control_scheme = p_scheme;
}
-void ViewPanner::set_disable_rmb(bool p_disable) {
- disable_rmb = p_disable;
+void ViewPanner::set_enable_rmb(bool p_enable) {
+ enable_rmb = p_enable;
+}
+
+void ViewPanner::set_pan_shortcut(Ref<Shortcut> p_shortcut) {
+ pan_view_shortcut = p_shortcut;
+ pan_key_pressed = false;
+}
+
+void ViewPanner::set_simple_panning_enabled(bool p_enabled) {
+ simple_panning_enabled = p_enabled;
+}
+
+void ViewPanner::setup(ControlScheme p_scheme, Ref<Shortcut> p_shortcut, bool p_simple_panning) {
+ set_control_scheme(p_scheme);
+ set_pan_shortcut(p_shortcut);
+ set_simple_panning_enabled(p_simple_panning);
+}
+
+bool ViewPanner::is_panning() const {
+ return is_dragging || pan_key_pressed;
+}
+
+ViewPanner::ViewPanner() {
+ Array inputs;
+ inputs.append(InputEventKey::create_reference(Key::SPACE));
+
+ pan_view_shortcut.instantiate();
+ pan_view_shortcut->set_events(inputs);
}
diff --git a/scene/gui/view_panner.h b/scene/gui/view_panner.h
index 0a92cb3dfd..8423c2a1c0 100644
--- a/scene/gui/view_panner.h
+++ b/scene/gui/view_panner.h
@@ -34,6 +34,7 @@
#include "core/object/ref_counted.h"
class InputEvent;
+class Shortcut;
class ViewPanner : public RefCounted {
GDCLASS(ViewPanner, RefCounted);
@@ -46,23 +47,34 @@ public:
private:
bool is_dragging = false;
- bool disable_rmb = false;
+ bool pan_key_pressed = false;
+ bool enable_rmb = false;
+ bool simple_panning_enabled = false;
+
+ Ref<Shortcut> pan_view_shortcut;
Callable scroll_callback;
Callable pan_callback;
Callable zoom_callback;
- void callback_helper(Callable p_callback, Vector2 p_arg1, Vector2 p_arg2 = Vector2());
+ void callback_helper(Callable p_callback, Vector<Variant> p_args);
ControlScheme control_scheme = SCROLL_ZOOMS;
public:
void set_callbacks(Callable p_scroll_callback, Callable p_pan_callback, Callable p_zoom_callback);
void set_control_scheme(ControlScheme p_scheme);
- void set_disable_rmb(bool p_disable);
+ void set_enable_rmb(bool p_enable);
+ void set_pan_shortcut(Ref<Shortcut> p_shortcut);
+ void set_simple_panning_enabled(bool p_enabled);
+
+ void setup(ControlScheme p_scheme, Ref<Shortcut> p_shortcut, bool p_simple_panning);
- bool is_panning() const { return is_dragging; }
+ bool is_panning() const;
bool gui_input(const Ref<InputEvent> &p_ev, Rect2 p_canvas_rect = Rect2());
+ void release_pan_key();
+
+ ViewPanner();
};
#endif // VIEW_PANNER_H