Skip to content

Commit bdd3cb3

Browse files
committed
Merge pull request #103382 from dugramen/tree-shift-select
Add tree multiselect with shift up & down arrow keys
2 parents 7e647d7 + eb97301 commit bdd3cb3

File tree

2 files changed

+61
-4
lines changed

2 files changed

+61
-4
lines changed

scene/gui/tree.cpp

Lines changed: 59 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3557,6 +3557,47 @@ void Tree::_go_up() {
35573557
accept_event();
35583558
}
35593559

3560+
void Tree::_shift_select_range(TreeItem *new_item) {
3561+
if (!new_item) {
3562+
new_item = selected_item;
3563+
}
3564+
int s_col = selected_col;
3565+
bool in_range = false;
3566+
TreeItem *item = root;
3567+
3568+
if (!shift_anchor) {
3569+
shift_anchor = selected_item;
3570+
}
3571+
3572+
while (item) {
3573+
bool at_range_edge = item == shift_anchor || item == new_item;
3574+
if (at_range_edge) {
3575+
in_range = !in_range;
3576+
}
3577+
if (new_item == shift_anchor) {
3578+
in_range = false;
3579+
}
3580+
if (item->is_visible_in_tree()) {
3581+
if (in_range || at_range_edge) {
3582+
if (!item->is_selected(selected_col) && item->is_selectable(selected_col)) {
3583+
item->select(selected_col);
3584+
emit_signal(SNAME("multi_selected"), item, selected_col, true);
3585+
}
3586+
} else if (item->is_selected(selected_col)) {
3587+
item->deselect(selected_col);
3588+
emit_signal(SNAME("multi_selected"), item, selected_col, false);
3589+
}
3590+
}
3591+
item = item->get_next_in_tree(false);
3592+
}
3593+
3594+
selected_item = new_item;
3595+
selected_col = s_col;
3596+
ensure_cursor_is_visible();
3597+
queue_redraw();
3598+
accept_event();
3599+
}
3600+
35603601
void Tree::_go_down() {
35613602
TreeItem *next = nullptr;
35623603
if (!selected_item) {
@@ -3646,6 +3687,10 @@ void Tree::gui_input(const Ref<InputEvent> &p_event) {
36463687

36473688
Ref<InputEventKey> k = p_event;
36483689

3690+
if (k.is_valid() && k->get_keycode() == Key::SHIFT && !k->is_pressed()) {
3691+
shift_anchor = nullptr;
3692+
}
3693+
36493694
bool is_command = k.is_valid() && k->is_command_or_control_pressed();
36503695
if (p_event->is_action(cache.rtl ? "ui_left" : "ui_right") && p_event->is_pressed()) {
36513696
if (!cursor_can_exit_tree) {
@@ -3687,15 +3732,25 @@ void Tree::gui_input(const Ref<InputEvent> &p_event) {
36873732
if (!cursor_can_exit_tree) {
36883733
accept_event();
36893734
}
3690-
3691-
_go_up();
3735+
// Shift Up Selection.
3736+
if (k.is_valid() && k->is_shift_pressed() && selected_item && select_mode == SELECT_MULTI) {
3737+
TreeItem *new_item = selected_item->get_prev_visible(false);
3738+
_shift_select_range(new_item);
3739+
} else {
3740+
_go_up();
3741+
}
36923742

36933743
} else if (p_event->is_action("ui_down") && p_event->is_pressed() && !is_command) {
36943744
if (!cursor_can_exit_tree) {
36953745
accept_event();
36963746
}
3697-
3698-
_go_down();
3747+
// Shift Down Selection.
3748+
if (k.is_valid() && k->is_shift_pressed() && selected_item && select_mode == SELECT_MULTI) {
3749+
TreeItem *new_item = selected_item->get_next_visible(false);
3750+
_shift_select_range(new_item);
3751+
} else {
3752+
_go_down();
3753+
}
36993754
} else if (p_event->is_action("ui_menu") && p_event->is_pressed()) {
37003755
if (allow_rmb_select && selected_item) {
37013756
emit_signal(SNAME("item_mouse_selected"), get_item_rect(selected_item).position, MouseButton::RIGHT);

scene/gui/tree.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -464,6 +464,7 @@ class Tree : public Control {
464464
TreeItem *popup_edited_item = nullptr;
465465
TreeItem *selected_item = nullptr;
466466
TreeItem *edited_item = nullptr;
467+
TreeItem *shift_anchor = nullptr;
467468

468469
TreeItem *popup_pressing_edited_item = nullptr; // Candidate.
469470
int popup_pressing_edited_item_column = -1;
@@ -743,6 +744,7 @@ class Tree : public Control {
743744
void _go_right();
744745
void _go_down();
745746
void _go_up();
747+
void _shift_select_range(TreeItem *new_item);
746748

747749
bool _scroll(bool p_horizontal, float p_pages);
748750

0 commit comments

Comments
 (0)