-
-
Notifications
You must be signed in to change notification settings - Fork 21.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Focusable Tabs and TabContainer, tabs can be changed using keyboard and gamepad #49928
Changes from all commits
4c8405a
807af8e
02154f2
c9656e9
d0bc23e
874e954
d469dc7
3f7198e
96d392a
1421880
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -233,6 +233,63 @@ void Tabs::_gui_input(const Ref<InputEvent> &p_event) { | |
} | ||
} | ||
} | ||
if (!mm.is_valid() && !mb.is_valid()) { | ||
if (p_event->is_action_pressed("ui_right")) { | ||
int next_tab = get_current_tab() + 1; | ||
bool valid = true; | ||
while (valid) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Any reason why this needs to be a It seems to me like a for loop which acts as an offset from an origin is more appropriate and easier to read.
This might not cover all use cases or compile completely as I'm writing it mostly pseudo code, but something along those lines seems a bit easier to read to me. It also doesn't require checking for self as it will naturally wrap around with the use of modulo. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not really, I just found while loop being easiest way to implement searching for a valid tab and didn't thought of for loop. |
||
if (next_tab == get_current_tab()) { | ||
valid = false; | ||
break; | ||
} | ||
|
||
if (next_tab < get_tab_count()) { | ||
if (get_tab_disabled(next_tab)) { | ||
++next_tab; | ||
} else { | ||
break; | ||
} | ||
} else { | ||
if (rollover) { | ||
next_tab = 0; | ||
} else { | ||
valid = false; | ||
} | ||
} | ||
} | ||
if (valid) { | ||
set_current_tab(next_tab); | ||
accept_event(); | ||
} | ||
} else if (p_event->is_action_pressed("ui_left")) { | ||
int prev_tab = get_current_tab() - 1; | ||
bool valid = true; | ||
while (valid) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same as the last comment but inverse direction. Modulo won't work here, so you'll have to appropriately index wrap as you see fit. |
||
if (prev_tab == get_current_tab()) { | ||
valid = false; | ||
break; | ||
} | ||
|
||
if (prev_tab >= 0) { | ||
if (get_tab_disabled(prev_tab)) { | ||
--prev_tab; | ||
} else { | ||
break; | ||
} | ||
} else { | ||
if (rollover) { | ||
prev_tab = get_tab_count() - 1; | ||
} else { | ||
valid = false; | ||
} | ||
} | ||
} | ||
if (valid) { | ||
set_current_tab(prev_tab); | ||
accept_event(); | ||
} | ||
} | ||
} | ||
} | ||
|
||
void Tabs::_shape(int p_tab) { | ||
|
@@ -352,6 +409,11 @@ void Tabs::_notification(int p_what) { | |
} | ||
sb->draw(ci, sb_rect); | ||
|
||
if (i == current && has_focus()) { | ||
Ref<StyleBox> style2 = get_theme_stylebox("focus"); | ||
style2->draw(ci, sb_rect); | ||
} | ||
|
||
w += sb->get_margin(SIDE_LEFT); | ||
|
||
Size2i sb_ms = sb->get_minimum_size(); | ||
|
@@ -1106,6 +1168,14 @@ bool Tabs::get_select_with_rmb() const { | |
return select_with_rmb; | ||
} | ||
|
||
void Tabs::set_rollover(bool p_enabled) { | ||
rollover = p_enabled; | ||
} | ||
|
||
bool Tabs::get_rollover() const { | ||
return rollover; | ||
} | ||
|
||
void Tabs::_bind_methods() { | ||
ClassDB::bind_method(D_METHOD("_gui_input"), &Tabs::_gui_input); | ||
ClassDB::bind_method(D_METHOD("_update_hover"), &Tabs::_update_hover); | ||
|
@@ -1149,6 +1219,9 @@ void Tabs::_bind_methods() { | |
ClassDB::bind_method(D_METHOD("set_select_with_rmb", "enabled"), &Tabs::set_select_with_rmb); | ||
ClassDB::bind_method(D_METHOD("get_select_with_rmb"), &Tabs::get_select_with_rmb); | ||
|
||
ClassDB::bind_method(D_METHOD("set_rollover", "enabled"), &Tabs::set_rollover); | ||
ClassDB::bind_method(D_METHOD("get_rollover"), &Tabs::get_rollover); | ||
|
||
ADD_SIGNAL(MethodInfo("tab_changed", PropertyInfo(Variant::INT, "tab"))); | ||
ADD_SIGNAL(MethodInfo("right_button_pressed", PropertyInfo(Variant::INT, "tab"))); | ||
ADD_SIGNAL(MethodInfo("tab_closed", PropertyInfo(Variant::INT, "tab"))); | ||
|
@@ -1162,6 +1235,7 @@ void Tabs::_bind_methods() { | |
ADD_PROPERTY(PropertyInfo(Variant::INT, "tab_close_display_policy", PROPERTY_HINT_ENUM, "Show Never,Show Active Only,Show Always"), "set_tab_close_display_policy", "get_tab_close_display_policy"); | ||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "scrolling_enabled"), "set_scrolling_enabled", "get_scrolling_enabled"); | ||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "drag_to_rearrange_enabled"), "set_drag_to_rearrange_enabled", "get_drag_to_rearrange_enabled"); | ||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "rollover"), "set_rollover", "get_rollover"); | ||
|
||
BIND_ENUM_CONSTANT(ALIGN_LEFT); | ||
BIND_ENUM_CONSTANT(ALIGN_CENTER); | ||
|
@@ -1175,5 +1249,6 @@ void Tabs::_bind_methods() { | |
} | ||
|
||
Tabs::Tabs() { | ||
set_focus_mode(FOCUS_ALL); | ||
connect("mouse_exited", callable_mp(this, &Tabs::_on_mouse_exited)); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you don't mind, please try to cluster likewise functions together with a space between them. E.G: