summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSaracen <SaracenOne@gmail.com>2017-11-16 09:45:52 +0000
committerSaracen <SaracenOne@gmail.com>2017-11-16 09:45:52 +0000
commite4201734df8c835a12b39276692987d6e2f5c267 (patch)
tree6f9c1f9ff0c0dada16d8ce032595a7aa81d4f267
parent35e7f992993a69a1e25cc12109ef7cf885e18260 (diff)
Add manual overrides for focus_next and focus_previous on controls similar to what can already be done with focus neighbours.
-rw-r--r--doc/classes/Control.xml36
-rw-r--r--scene/gui/control.cpp68
-rw-r--r--scene/gui/control.h7
3 files changed, 108 insertions, 3 deletions
diff --git a/doc/classes/Control.xml b/doc/classes/Control.xml
index b5765ac948..c56b0a15ce 100644
--- a/doc/classes/Control.xml
+++ b/doc/classes/Control.xml
@@ -228,7 +228,14 @@
<argument index="0" name="margin" type="int" enum="Margin">
</argument>
<description>
- Return the forced neighbour for moving the input focus to. When pressing TAB or directional/joypad directions focus is moved to the next control in that direction. However, the neighbour to move to can be forced with this function.
+ Return the forced neighbour for moving the input focus to. When pressing directional/joypad directions, focus is moved to the next control in that direction. However, the neighbour to move to can be forced with this function.
+ </description>
+ </method>
+ <method name="get_focus_next" qualifiers="const">
+ <return type="NodePath">
+ </return>
+ <description>
+ Return the 'focus_next' for moving input focus to. When pressing TAB, focus is moved to the next control in the tree. However, the control to move to can be forced with this function.
</description>
</method>
<method name="get_focus_owner" qualifiers="const">
@@ -238,6 +245,13 @@
Return which control is owning the keyboard focus, or null if no one.
</description>
</method>
+ <method name="get_focus_previous" qualifiers="const">
+ <return type="NodePath">
+ </return>
+ <description>
+ Return the 'focus_previous' for moving input focus to. When pressing Shift+TAB focus is moved to the previous control in the tree. However, the control to move to can be forced with this function.
+ </description>
+ </method>
<method name="get_font" qualifiers="const">
<return type="Font">
</return>
@@ -676,7 +690,25 @@
<argument index="1" name="neighbour" type="NodePath">
</argument>
<description>
- Force a neighbour for moving the input focus to. When pressing TAB or directional/joypad directions focus is moved to the next control in that direction. However, the neighbour to move to can be forced with this function.
+ Force a neighbour for moving the input focus to. When pressing directional/joypad directions, focus is moved to the next control in that direction. However, the neighbour to move to can be forced with this function.
+ </description>
+ </method>
+ <method name="set_focus_next">
+ <return type="void">
+ </return>
+ <argument index="0" name="next" type="NodePath">
+ </argument>
+ <description>
+ Force the 'focus_next' for moving input focus to. When pressing TAB, focus is moved to the next control in the tree. However, the control to move to can be forced with this function.
+ </description>
+ </method>
+ <method name="set_focus_previous">
+ <return type="void">
+ </return>
+ <argument index="0" name="previous" type="NodePath">
+ </argument>
+ <description>
+ Force the 'focus_previous' for moving input focus to. When pressing Shift+TAB, focus is moved to the previous control in the tree. However, the control to move to can be forced with this function.
</description>
</method>
<method name="set_global_position">
diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp
index e73ada9f31..3976a2ad48 100644
--- a/scene/gui/control.cpp
+++ b/scene/gui/control.cpp
@@ -1847,6 +1847,25 @@ Control *Control::find_next_valid_focus() const {
while (true) {
+ // If the focus property is manually overwritten, attempt to use it.
+
+ if (!data.focus_next.is_empty()) {
+ Node *n = get_node(data.focus_next);
+ if (n) {
+ from = Object::cast_to<Control>(n);
+
+ if (!from) {
+
+ ERR_EXPLAIN("Next focus node is not a control: " + n->get_name());
+ ERR_FAIL_V(NULL);
+ }
+ } else {
+ return NULL;
+ }
+ if (from->is_visible() && from->get_focus_mode() != FOCUS_NONE)
+ return from;
+ }
+
// find next child
Control *next_child = NULL;
@@ -1926,6 +1945,25 @@ Control *Control::find_prev_valid_focus() const {
while (true) {
+ // If the focus property is manually overwritten, attempt to use it.
+
+ if (!data.focus_prev.is_empty()) {
+ Node *n = get_node(data.focus_prev);
+ if (n) {
+ from = Object::cast_to<Control>(n);
+
+ if (!from) {
+
+ ERR_EXPLAIN("Prev focus node is not a control: " + n->get_name());
+ ERR_FAIL_V(NULL);
+ }
+ } else {
+ return NULL;
+ }
+ if (from->is_visible() && from->get_focus_mode() != FOCUS_NONE)
+ return from;
+ }
+
// find prev child
Control *prev_child = NULL;
@@ -2157,6 +2195,26 @@ NodePath Control::get_focus_neighbour(Margin p_margin) const {
return data.focus_neighbour[p_margin];
}
+void Control::set_focus_next(const NodePath &p_next) {
+
+ data.focus_next = p_next;
+}
+
+NodePath Control::get_focus_next() const {
+
+ return data.focus_next;
+}
+
+void Control::set_focus_previous(const NodePath &p_prev) {
+
+ data.focus_prev = p_prev;
+}
+
+NodePath Control::get_focus_previous() const {
+
+ return data.focus_prev;
+}
+
#define MAX_NEIGHBOUR_SEARCH_COUNT 512
Control *Control::_get_focus_neighbour(Margin p_margin, int p_count) {
@@ -2172,7 +2230,7 @@ Control *Control::_get_focus_neighbour(Margin p_margin, int p_count) {
if (!c) {
- ERR_EXPLAIN("Next focus node is not a control: " + n->get_name());
+ ERR_EXPLAIN("Neighbour focus node is not a control: " + n->get_name());
ERR_FAIL_V(NULL);
}
} else {
@@ -2677,6 +2735,12 @@ void Control::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_focus_neighbour", "margin", "neighbour"), &Control::set_focus_neighbour);
ClassDB::bind_method(D_METHOD("get_focus_neighbour", "margin"), &Control::get_focus_neighbour);
+ ClassDB::bind_method(D_METHOD("set_focus_next", "next"), &Control::set_focus_next);
+ ClassDB::bind_method(D_METHOD("get_focus_next"), &Control::get_focus_next);
+
+ ClassDB::bind_method(D_METHOD("set_focus_previous", "previous"), &Control::set_focus_previous);
+ ClassDB::bind_method(D_METHOD("get_focus_previous"), &Control::get_focus_previous);
+
ClassDB::bind_method(D_METHOD("force_drag", "data", "preview"), &Control::force_drag);
ClassDB::bind_method(D_METHOD("set_mouse_filter", "filter"), &Control::set_mouse_filter);
@@ -2737,6 +2801,8 @@ void Control::_bind_methods() {
ADD_PROPERTYINZ(PropertyInfo(Variant::NODE_PATH, "focus_neighbour_top"), "set_focus_neighbour", "get_focus_neighbour", MARGIN_TOP);
ADD_PROPERTYINZ(PropertyInfo(Variant::NODE_PATH, "focus_neighbour_right"), "set_focus_neighbour", "get_focus_neighbour", MARGIN_RIGHT);
ADD_PROPERTYINZ(PropertyInfo(Variant::NODE_PATH, "focus_neighbour_bottom"), "set_focus_neighbour", "get_focus_neighbour", MARGIN_BOTTOM);
+ ADD_PROPERTYNZ(PropertyInfo(Variant::NODE_PATH, "focus_next"), "set_focus_next", "get_focus_next");
+ ADD_PROPERTYNZ(PropertyInfo(Variant::NODE_PATH, "focus_previous"), "set_focus_previous", "get_focus_previous");
ADD_GROUP("Mouse", "mouse_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "mouse_filter", PROPERTY_HINT_ENUM, "Stop,Pass,Ignore"), "set_mouse_filter", "get_mouse_filter");
diff --git a/scene/gui/control.h b/scene/gui/control.h
index 4d0e3934ad..94c484ca50 100644
--- a/scene/gui/control.h
+++ b/scene/gui/control.h
@@ -191,6 +191,8 @@ private:
ObjectID modal_prev_focus_owner;
NodePath focus_neighbour[4];
+ NodePath focus_next;
+ NodePath focus_prev;
HashMap<StringName, Ref<Texture>, StringNameHasher> icon_override;
HashMap<StringName, Ref<Shader>, StringNameHasher> shader_override;
@@ -374,6 +376,11 @@ public:
void set_focus_neighbour(Margin p_margin, const NodePath &p_neighbour);
NodePath get_focus_neighbour(Margin p_margin) const;
+ void set_focus_next(const NodePath &p_next);
+ NodePath get_focus_next() const;
+ void set_focus_previous(const NodePath &p_prev);
+ NodePath get_focus_previous() const;
+
Control *get_focus_owner() const;
void set_mouse_filter(MouseFilter p_filter);