diff --git a/src/gui/widgets/tree_view.cpp b/src/gui/widgets/tree_view.cpp index 1448338f088f..2a84894208b8 100644 --- a/src/gui/widgets/tree_view.cpp +++ b/src/gui/widgets/tree_view.cpp @@ -185,6 +185,56 @@ void ttree_view::signal_handler_left_button_down(const event::tevent event) get_window()->keyboard_capture(this); } +template +ttree_view_node* ttree_view::get_next_node() +{ + ttree_view_node* selected = selected_item(); + if(!selected) { + return NULL; + } + ttree_view_node* visible = selected->get_last_visible_parent_node(); + if(visible != selected) { + return visible; + } + return (selected->*func)(); +} + +template +bool ttree_view::handle_up_down_arrow() +{ + if(ttree_view_node* next = get_next_node()) + { + next->select_node(); + SDL_Rect visible = content_visible_area(); + SDL_Rect rect = next->get_grid().get_rectangle(); + visible.y = rect.y;// - content_grid()->get_y(); + visible.h = rect.h; + show_content_rect(visible); + return true; + } + return false; +} + +void ttree_view::handle_key_up_arrow(SDLMod modifier, bool& handled) +{ + if(handle_up_down_arrow<&ttree_view_node::get_selectable_node_above>()) { + handled = true; + } + else { + tscrollbar_container::handle_key_up_arrow(modifier, handled); + } +} + +void ttree_view::handle_key_down_arrow(SDLMod modifier, bool& handled) +{ + if(handle_up_down_arrow<&ttree_view_node::get_selectable_node_below>()) { + handled = true; + } + else { + tscrollbar_container::handle_key_down_arrow(modifier, handled); + } +} + void ttree_view::handle_key_left_arrow(SDLMod modifier, bool& handled) { @@ -201,7 +251,7 @@ void ttree_view::handle_key_right_arrow(SDLMod modifier, bool& handled) { ttree_view_node* selected = selected_item(); if(!selected || !selected->is_folded()) { - tscrollbar_container::handle_key_left_arrow(modifier, handled); + tscrollbar_container::handle_key_right_arrow(modifier, handled); return; } selected->unfold(); diff --git a/src/gui/widgets/tree_view.hpp b/src/gui/widgets/tree_view.hpp index e2d16ba7d9d1..454f93813b64 100644 --- a/src/gui/widgets/tree_view.hpp +++ b/src/gui/widgets/tree_view.hpp @@ -83,13 +83,12 @@ class ttree_view : public tscrollbar_container protected: /***** ***** ***** ***** keyboard functions ***** ***** ***** *****/ -#if 0 /** Inherited from tscrollbar_container. */ void handle_key_up_arrow(SDLMod modifier, bool& handled); /** Inherited from tscrollbar_container. */ void handle_key_down_arrow(SDLMod modifier, bool& handled); -#endif + /** Inherited from tscrollbar_container. */ void handle_key_left_arrow(SDLMod modifier, bool& handled); @@ -146,6 +145,12 @@ class ttree_view : public tscrollbar_container /***** ***** ***** signal handlers ***** ****** *****/ void signal_handler_left_button_down(const event::tevent event); + + template + ttree_view_node* get_next_node(); + + template + bool handle_up_down_arrow(); }; } // namespace gui2 diff --git a/src/gui/widgets/tree_view_node.cpp b/src/gui/widgets/tree_view_node.cpp index 846066dc67a5..f8f17ced60df 100644 --- a/src/gui/widgets/tree_view_node.cpp +++ b/src/gui/widgets/tree_view_node.cpp @@ -720,4 +720,92 @@ int ttree_view_node::calculate_ypos() } return res; } +ttree_view_node* ttree_view_node::get_last_visible_parent_node() +{ + if(!parent_node_) { + return this; + } + ttree_view_node* res = parent_node_->get_last_visible_parent_node(); + return res == parent_node_ && !res->is_folded() ? this : res; +} + +ttree_view_node* ttree_view_node::get_node_above() +{ + assert(!is_root_node()); + ttree_view_node* cur = NULL; + for(size_t i = 0; i < parent_node_->size(); ++i) { + if(&parent_node_->children_[i] == this) { + if(i == 0) { + return parent_node_->is_root_node() ? NULL : parent_node_; + } + else { + cur = &parent_node_->children_[i - 1]; + break; + } + } + } + while(!cur->is_folded() && cur->size() > 0) { + cur = &cur->get_child_at(cur->size() - 1); + } + return cur; +} + +ttree_view_node* ttree_view_node::get_node_below() +{ + assert(!is_root_node()); + if(!is_folded() && size() > 0) { + return &get_child_at(0); + } + ttree_view_node* cur = this; + while(cur->parent_node_ != NULL) { + ttree_view_node& parent = *cur->parent_node_; + + for(size_t i = 0; i < parent.size(); ++i) { + if(&parent.children_[i] == cur) { + if(i < parent.size() - 1) { + return &parent.children_[i + 1]; + } + else { + cur = &parent; + } + break; + } + } + } + return NULL; +} +ttree_view_node* ttree_view_node::get_selectable_node_above() +{ + ttree_view_node* above = this; + do { + above = above->get_node_above(); + } while(above != NULL && above->label_ == NULL); + return above; +} +ttree_view_node* ttree_view_node::get_selectable_node_below() +{ + ttree_view_node* below = this; + do { + below = below->get_node_below(); + } while(below != NULL && below->label_ == NULL); + return below; + +} +void ttree_view_node::select_node() +{ + if(!label_ || label_->get_value_bool()) { + return; + } + + if(tree_view().selected_item_ && tree_view().selected_item_->label_) { + tree_view().selected_item_->label_->set_value(false); + } + tree_view().selected_item_ = this; + + if(tree_view().selection_change_callback_) { + tree_view().selection_change_callback_(tree_view()); + } + label_->set_value_bool(true); +} + } // namespace gui2 diff --git a/src/gui/widgets/tree_view_node.hpp b/src/gui/widgets/tree_view_node.hpp index d817918e22f3..a1af6898dc7f 100644 --- a/src/gui/widgets/tree_view_node.hpp +++ b/src/gui/widgets/tree_view_node.hpp @@ -209,7 +209,13 @@ class ttree_view_node : public twidget break; } } - + ttree_view_node* get_last_visible_parent_node(); + ttree_view_node* get_node_above(); + ttree_view_node* get_node_below(); + ttree_view_node* get_selectable_node_above(); + ttree_view_node* get_selectable_node_below(); + void select_node(); + tgrid& get_grid() { return grid_; } private: int calculate_ypos();