Improvements to incremental search
This commit is contained in:
parent
7112a45d99
commit
9de912caf5
|
@ -524,6 +524,9 @@
|
||||||
<member name="submenu_popup_delay" type="float" setter="set_submenu_popup_delay" getter="get_submenu_popup_delay">
|
<member name="submenu_popup_delay" type="float" setter="set_submenu_popup_delay" getter="get_submenu_popup_delay">
|
||||||
Sets the delay time for the submenu item to popup on mouse hovering. If the popup menu is added as a child of another (acting as a submenu), it will inherit the delay time of the parent menu item. Default value: [code]0.3[/code] seconds.
|
Sets the delay time for the submenu item to popup on mouse hovering. If the popup menu is added as a child of another (acting as a submenu), it will inherit the delay time of the parent menu item. Default value: [code]0.3[/code] seconds.
|
||||||
</member>
|
</member>
|
||||||
|
<member name="allow_search" type="bool" setter="set_allow_search" getter="get_allow_search">
|
||||||
|
If [code]true[/code], allows to navigate [PopupMenu] with letter keys. Default value: [code]false[/code].
|
||||||
|
</member>
|
||||||
</members>
|
</members>
|
||||||
<signals>
|
<signals>
|
||||||
<signal name="id_focused">
|
<signal name="id_focused">
|
||||||
|
|
|
@ -748,9 +748,21 @@ void ItemList::_gui_input(const Ref<InputEvent> &p_event) {
|
||||||
search_string = "";
|
search_string = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
search_string += String::chr(k->get_unicode());
|
if (String::chr(k->get_unicode()) != search_string)
|
||||||
for (int i = 0; i < items.size(); i++) {
|
search_string += String::chr(k->get_unicode());
|
||||||
if (items[i].text.begins_with(search_string)) {
|
|
||||||
|
for (int i = current + 1; i <= items.size(); i++) {
|
||||||
|
if (i == items.size()) {
|
||||||
|
if (current == 0)
|
||||||
|
break;
|
||||||
|
else
|
||||||
|
i = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == current)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (items[i].text.findn(search_string) == 0) {
|
||||||
set_current(i);
|
set_current(i);
|
||||||
ensure_current_is_visible();
|
ensure_current_is_visible();
|
||||||
if (select_mode == SELECT_SINGLE) {
|
if (select_mode == SELECT_SINGLE) {
|
||||||
|
|
|
@ -354,6 +354,7 @@ OptionButton::OptionButton() {
|
||||||
add_child(popup);
|
add_child(popup);
|
||||||
popup->set_pass_on_modal_close_click(false);
|
popup->set_pass_on_modal_close_click(false);
|
||||||
popup->set_notify_transform(true);
|
popup->set_notify_transform(true);
|
||||||
|
popup->set_allow_search(true);
|
||||||
popup->connect("id_pressed", this, "_selected");
|
popup->connect("id_pressed", this, "_selected");
|
||||||
popup->connect("id_focused", this, "_focused");
|
popup->connect("id_focused", this, "_focused");
|
||||||
popup->connect("popup_hide", this, "set_pressed", varray(false));
|
popup->connect("popup_hide", this, "set_pressed", varray(false));
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#include "popup_menu.h"
|
#include "popup_menu.h"
|
||||||
#include "core/os/input.h"
|
#include "core/os/input.h"
|
||||||
#include "core/os/keyboard.h"
|
#include "core/os/keyboard.h"
|
||||||
|
#include "core/os/os.h"
|
||||||
#include "core/print_string.h"
|
#include "core/print_string.h"
|
||||||
#include "core/translation.h"
|
#include "core/translation.h"
|
||||||
|
|
||||||
|
@ -380,6 +381,43 @@ void PopupMenu::_gui_input(const Ref<InputEvent> &p_event) {
|
||||||
_scroll(-pan_gesture->get_delta().y, pan_gesture->get_position());
|
_scroll(-pan_gesture->get_delta().y, pan_gesture->get_position());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ref<InputEventKey> k = p_event;
|
||||||
|
|
||||||
|
if (allow_search && k.is_valid() && k->get_unicode()) {
|
||||||
|
|
||||||
|
uint64_t now = OS::get_singleton()->get_ticks_msec();
|
||||||
|
uint64_t diff = now - search_time_msec;
|
||||||
|
uint64_t max_interval = uint64_t(GLOBAL_DEF("gui/timers/incremental_search_max_interval_msec", 2000));
|
||||||
|
search_time_msec = now;
|
||||||
|
|
||||||
|
if (diff > max_interval) {
|
||||||
|
search_string = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (String::chr(k->get_unicode()) != search_string)
|
||||||
|
search_string += String::chr(k->get_unicode());
|
||||||
|
|
||||||
|
for (int i = mouse_over + 1; i <= items.size(); i++) {
|
||||||
|
if (i == items.size()) {
|
||||||
|
if (mouse_over <= 0)
|
||||||
|
break;
|
||||||
|
else
|
||||||
|
i = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == mouse_over)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (items[i].text.findn(search_string) == 0) {
|
||||||
|
mouse_over = i;
|
||||||
|
emit_signal("id_focused", i);
|
||||||
|
update();
|
||||||
|
accept_event();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PopupMenu::has_point(const Point2 &p_point) const {
|
bool PopupMenu::has_point(const Point2 &p_point) const {
|
||||||
|
@ -1289,6 +1327,16 @@ float PopupMenu::get_submenu_popup_delay() const {
|
||||||
return submenu_timer->get_wait_time();
|
return submenu_timer->get_wait_time();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PopupMenu::set_allow_search(bool p_allow) {
|
||||||
|
|
||||||
|
allow_search = p_allow;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PopupMenu::get_allow_search() const {
|
||||||
|
|
||||||
|
return allow_search;
|
||||||
|
}
|
||||||
|
|
||||||
void PopupMenu::set_hide_on_window_lose_focus(bool p_enabled) {
|
void PopupMenu::set_hide_on_window_lose_focus(bool p_enabled) {
|
||||||
|
|
||||||
hide_on_window_lose_focus = p_enabled;
|
hide_on_window_lose_focus = p_enabled;
|
||||||
|
@ -1407,6 +1455,9 @@ void PopupMenu::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("set_hide_on_window_lose_focus", "enable"), &PopupMenu::set_hide_on_window_lose_focus);
|
ClassDB::bind_method(D_METHOD("set_hide_on_window_lose_focus", "enable"), &PopupMenu::set_hide_on_window_lose_focus);
|
||||||
ClassDB::bind_method(D_METHOD("is_hide_on_window_lose_focus"), &PopupMenu::is_hide_on_window_lose_focus);
|
ClassDB::bind_method(D_METHOD("is_hide_on_window_lose_focus"), &PopupMenu::is_hide_on_window_lose_focus);
|
||||||
|
|
||||||
|
ClassDB::bind_method(D_METHOD("set_allow_search", "allow"), &PopupMenu::set_allow_search);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_allow_search"), &PopupMenu::get_allow_search);
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("_submenu_timeout"), &PopupMenu::_submenu_timeout);
|
ClassDB::bind_method(D_METHOD("_submenu_timeout"), &PopupMenu::_submenu_timeout);
|
||||||
|
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "items", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_items", "_get_items");
|
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "items", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_items", "_get_items");
|
||||||
|
@ -1414,6 +1465,7 @@ void PopupMenu::_bind_methods() {
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hide_on_checkable_item_selection"), "set_hide_on_checkable_item_selection", "is_hide_on_checkable_item_selection");
|
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hide_on_checkable_item_selection"), "set_hide_on_checkable_item_selection", "is_hide_on_checkable_item_selection");
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hide_on_state_item_selection"), "set_hide_on_state_item_selection", "is_hide_on_state_item_selection");
|
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hide_on_state_item_selection"), "set_hide_on_state_item_selection", "is_hide_on_state_item_selection");
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "submenu_popup_delay"), "set_submenu_popup_delay", "get_submenu_popup_delay");
|
ADD_PROPERTY(PropertyInfo(Variant::REAL, "submenu_popup_delay"), "set_submenu_popup_delay", "get_submenu_popup_delay");
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "allow_search"), "set_allow_search", "get_allow_search");
|
||||||
|
|
||||||
ADD_SIGNAL(MethodInfo("id_pressed", PropertyInfo(Variant::INT, "id")));
|
ADD_SIGNAL(MethodInfo("id_pressed", PropertyInfo(Variant::INT, "id")));
|
||||||
ADD_SIGNAL(MethodInfo("id_focused", PropertyInfo(Variant::INT, "id")));
|
ADD_SIGNAL(MethodInfo("id_focused", PropertyInfo(Variant::INT, "id")));
|
||||||
|
@ -1435,6 +1487,10 @@ PopupMenu::PopupMenu() {
|
||||||
initial_button_mask = 0;
|
initial_button_mask = 0;
|
||||||
during_grabbed_click = false;
|
during_grabbed_click = false;
|
||||||
|
|
||||||
|
allow_search = false;
|
||||||
|
search_time_msec = 0;
|
||||||
|
search_string = "";
|
||||||
|
|
||||||
set_focus_mode(FOCUS_ALL);
|
set_focus_mode(FOCUS_ALL);
|
||||||
set_as_toplevel(true);
|
set_as_toplevel(true);
|
||||||
set_hide_on_item_selection(true);
|
set_hide_on_item_selection(true);
|
||||||
|
|
|
@ -112,6 +112,10 @@ class PopupMenu : public Popup {
|
||||||
void _ref_shortcut(Ref<ShortCut> p_sc);
|
void _ref_shortcut(Ref<ShortCut> p_sc);
|
||||||
void _unref_shortcut(Ref<ShortCut> p_sc);
|
void _unref_shortcut(Ref<ShortCut> p_sc);
|
||||||
|
|
||||||
|
bool allow_search;
|
||||||
|
uint64_t search_time_msec;
|
||||||
|
String search_string;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual bool has_point(const Point2 &p_point) const;
|
virtual bool has_point(const Point2 &p_point) const;
|
||||||
|
|
||||||
|
@ -206,6 +210,9 @@ public:
|
||||||
void set_submenu_popup_delay(float p_time);
|
void set_submenu_popup_delay(float p_time);
|
||||||
float get_submenu_popup_delay() const;
|
float get_submenu_popup_delay() const;
|
||||||
|
|
||||||
|
void set_allow_search(bool p_allow);
|
||||||
|
bool get_allow_search() const;
|
||||||
|
|
||||||
virtual void popup(const Rect2 &p_bounds = Rect2());
|
virtual void popup(const Rect2 &p_bounds = Rect2());
|
||||||
|
|
||||||
void set_hide_on_window_lose_focus(bool p_enabled);
|
void set_hide_on_window_lose_focus(bool p_enabled);
|
||||||
|
|
|
@ -389,7 +389,7 @@ TreeItem *TreeItem::get_children() {
|
||||||
return children;
|
return children;
|
||||||
}
|
}
|
||||||
|
|
||||||
TreeItem *TreeItem::get_prev_visible() {
|
TreeItem *TreeItem::get_prev_visible(bool p_wrap) {
|
||||||
|
|
||||||
TreeItem *current = this;
|
TreeItem *current = this;
|
||||||
|
|
||||||
|
@ -398,8 +398,20 @@ TreeItem *TreeItem::get_prev_visible() {
|
||||||
if (!prev) {
|
if (!prev) {
|
||||||
|
|
||||||
current = current->parent;
|
current = current->parent;
|
||||||
if (!current || (current == tree->root && tree->hide_root))
|
if (current == tree->root && tree->hide_root) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
} else if (!current) {
|
||||||
|
if (p_wrap) {
|
||||||
|
current = this;
|
||||||
|
TreeItem *temp = this->get_next_visible();
|
||||||
|
while (temp) {
|
||||||
|
current = temp;
|
||||||
|
temp = temp->get_next_visible();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
current = prev;
|
current = prev;
|
||||||
|
@ -415,7 +427,7 @@ TreeItem *TreeItem::get_prev_visible() {
|
||||||
return current;
|
return current;
|
||||||
}
|
}
|
||||||
|
|
||||||
TreeItem *TreeItem::get_next_visible() {
|
TreeItem *TreeItem::get_next_visible(bool p_wrap) {
|
||||||
|
|
||||||
TreeItem *current = this;
|
TreeItem *current = this;
|
||||||
|
|
||||||
|
@ -433,10 +445,14 @@ TreeItem *TreeItem::get_next_visible() {
|
||||||
current = current->parent;
|
current = current->parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (current == NULL)
|
if (!current) {
|
||||||
return NULL;
|
if (p_wrap)
|
||||||
else
|
return tree->root;
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
|
} else {
|
||||||
current = current->next;
|
current = current->next;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return current;
|
return current;
|
||||||
|
@ -740,8 +756,8 @@ void TreeItem::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("get_parent"), &TreeItem::get_parent);
|
ClassDB::bind_method(D_METHOD("get_parent"), &TreeItem::get_parent);
|
||||||
ClassDB::bind_method(D_METHOD("get_children"), &TreeItem::get_children);
|
ClassDB::bind_method(D_METHOD("get_children"), &TreeItem::get_children);
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("get_next_visible"), &TreeItem::get_next_visible);
|
ClassDB::bind_method(D_METHOD("get_next_visible", "wrap"), &TreeItem::get_next_visible, DEFVAL(false));
|
||||||
ClassDB::bind_method(D_METHOD("get_prev_visible"), &TreeItem::get_prev_visible);
|
ClassDB::bind_method(D_METHOD("get_prev_visible", "wrap"), &TreeItem::get_prev_visible, DEFVAL(false));
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("remove_child", "child"), &TreeItem::_remove_child);
|
ClassDB::bind_method(D_METHOD("remove_child", "child"), &TreeItem::_remove_child);
|
||||||
|
|
||||||
|
@ -3488,6 +3504,7 @@ void Tree::scroll_to_item(TreeItem *p_item) {
|
||||||
|
|
||||||
TreeItem *Tree::_search_item_text(TreeItem *p_at, const String &p_find, int *r_col, bool p_selectable, bool p_backwards) {
|
TreeItem *Tree::_search_item_text(TreeItem *p_at, const String &p_find, int *r_col, bool p_selectable, bool p_backwards) {
|
||||||
|
|
||||||
|
TreeItem *from = p_at;
|
||||||
while (p_at) {
|
while (p_at) {
|
||||||
|
|
||||||
for (int i = 0; i < columns.size(); i++) {
|
for (int i = 0; i < columns.size(); i++) {
|
||||||
|
@ -3499,9 +3516,12 @@ TreeItem *Tree::_search_item_text(TreeItem *p_at, const String &p_find, int *r_c
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p_backwards)
|
if (p_backwards)
|
||||||
p_at = p_at->get_prev_visible();
|
p_at = p_at->get_prev_visible(true);
|
||||||
else
|
else
|
||||||
p_at = p_at->get_next_visible();
|
p_at = p_at->get_next_visible(true);
|
||||||
|
|
||||||
|
if ((p_at) == from)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -3509,10 +3529,14 @@ TreeItem *Tree::_search_item_text(TreeItem *p_at, const String &p_find, int *r_c
|
||||||
|
|
||||||
TreeItem *Tree::search_item_text(const String &p_find, int *r_col, bool p_selectable) {
|
TreeItem *Tree::search_item_text(const String &p_find, int *r_col, bool p_selectable) {
|
||||||
|
|
||||||
|
TreeItem *from = get_selected()->get_next_visible();
|
||||||
|
|
||||||
if (!root)
|
if (!root)
|
||||||
|
from = root;
|
||||||
|
if (!from)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
return _search_item_text(root, p_find, r_col, p_selectable);
|
return _search_item_text(from, p_find, r_col, p_selectable);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Tree::_do_incr_search(const String &p_add) {
|
void Tree::_do_incr_search(const String &p_add) {
|
||||||
|
@ -3521,7 +3545,7 @@ void Tree::_do_incr_search(const String &p_add) {
|
||||||
uint64_t diff = time - last_keypress;
|
uint64_t diff = time - last_keypress;
|
||||||
if (diff > uint64_t(GLOBAL_DEF("gui/timers/incremental_search_max_interval_msec", 2000)))
|
if (diff > uint64_t(GLOBAL_DEF("gui/timers/incremental_search_max_interval_msec", 2000)))
|
||||||
incr_search = p_add;
|
incr_search = p_add;
|
||||||
else
|
else if (incr_search != p_add)
|
||||||
incr_search += p_add;
|
incr_search += p_add;
|
||||||
|
|
||||||
last_keypress = time;
|
last_keypress = time;
|
||||||
|
|
|
@ -238,8 +238,8 @@ public:
|
||||||
TreeItem *get_parent();
|
TreeItem *get_parent();
|
||||||
TreeItem *get_children();
|
TreeItem *get_children();
|
||||||
|
|
||||||
TreeItem *get_prev_visible();
|
TreeItem *get_prev_visible(bool p_wrap = false);
|
||||||
TreeItem *get_next_visible();
|
TreeItem *get_next_visible(bool p_wrap = false);
|
||||||
|
|
||||||
void remove_child(TreeItem *p_item);
|
void remove_child(TreeItem *p_item);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue