diff --git a/src/guiengine/event_handler.cpp b/src/guiengine/event_handler.cpp index fb09c6439..0939e506c 100644 --- a/src/guiengine/event_handler.cpp +++ b/src/guiengine/event_handler.cpp @@ -509,7 +509,7 @@ void EventHandler::navigate(const NavigationDirection nav, const int playerID) { ListWidget* list = (ListWidget*) closest_widget; assert(list != NULL); - list->setSelectionID(nav == NAV_UP ? list->getItemCount() - 1 : 0); + list->focusHeader(nav); } // Similar exception for vertical tabs, only apply when entering with down/up if (closest_widget->m_type == GUIEngine::WTYPE_RIBBON && (nav == NAV_UP || nav == NAV_DOWN)) diff --git a/src/guiengine/skin.cpp b/src/guiengine/skin.cpp index bb544b09c..ea7f48de7 100644 --- a/src/guiengine/skin.cpp +++ b/src/guiengine/skin.cpp @@ -1822,20 +1822,20 @@ void Skin::drawListHeader(const irr::core::rect< irr::s32 > &rect, Widget* widget) { #ifndef SERVER_ONLY + ListWidget* list = static_cast(widget->m_event_handler); bool isSelected = - (((ListWidget*)widget->m_event_handler)->m_selected_column == widget && - ((ListWidget*)widget->m_event_handler)->m_sort_default == false); + (list->m_selected_column == widget && list->m_choosing_header); drawBoxFromStretchableTexture(widget, rect, (isSelected ? SkinConfig::m_render_params["list_header::down"] : SkinConfig::m_render_params["list_header::neutral"]), false, NULL /* clip */); - if (isSelected) + if (list->m_selected_column == widget && !list->m_sort_default) { /** \brief img sets the icon for the column according to sort order **/ ITexture* img; - if (((ListWidget*)widget->m_event_handler)->m_sort_desc) + if (list->m_sort_desc) img = SkinConfig::m_render_params["list_sort_down::neutral"].getImage(); else diff --git a/src/guiengine/widgets/list_widget.cpp b/src/guiengine/widgets/list_widget.cpp index 33f652be5..ed148019e 100644 --- a/src/guiengine/widgets/list_widget.cpp +++ b/src/guiengine/widgets/list_widget.cpp @@ -47,6 +47,7 @@ ListWidget::ListWidget() : Widget(WTYPE_LIST) m_sort_col = 0; m_sortable = true; m_header_created = false; + m_choosing_header = false; } // ----------------------------------------------------------------------------- @@ -360,6 +361,9 @@ irr::core::stringw ListWidget::getSelectionLabel(const int cell) const void ListWidget::selectItemWithLabel(const irr::core::stringw& name) { + // Disable focusing header for choosing + m_choosing_header = false; + CGUISTKListBox* list = getIrrlichtElement(); assert(list != NULL); return list->setSelectedByCellText( name.c_str() ); @@ -393,6 +397,9 @@ void ListWidget::setSelectionID(const int index) // May only be called AFTER this widget has been add()ed assert(m_element != NULL); + // Disable focusing header for choosing + m_choosing_header = false; + CGUISTKListBox* irritem = getIrrlichtElement(); // auto-scroll to item when selecting something, don't auto-scroll when selecting nothing @@ -527,7 +534,7 @@ EventPropagation ListWidget::transmitEvent(Widget* w, m_sort_col = originator[(m_properties[PROP_ID] + "_column_").size()] - '0'; m_selected_column = m_header_elements.get(m_sort_col); - + m_choosing_header = true; /** \brief Allows sort icon to change depending on sort order **/ /* @@ -560,6 +567,57 @@ EventPropagation ListWidget::downPressed(const int playerID) return moveToNextItem(/*reverse*/ false); } // downPressed +// ----------------------------------------------------------------------------- + +EventPropagation ListWidget::leftPressed(const int playerID) +{ + if (m_deactivated || !m_choosing_header) + return EVENT_BLOCK; + + m_sort_col--; + repairSortCol(); + m_sort_default = true; + m_selected_column = m_header_elements.get(m_sort_col); + m_selected_column->setFocusForPlayer(0); + + return EVENT_LET; +} // upPressed + +// ----------------------------------------------------------------------------- + +EventPropagation ListWidget::rightPressed(const int playerID) +{ + if (m_deactivated || !m_choosing_header) + return EVENT_BLOCK; + + m_sort_col++; + repairSortCol(); + m_sort_default = true; + m_selected_column = m_header_elements.get(m_sort_col); + m_selected_column->setFocusForPlayer(0); + + return EVENT_LET; +} // downPressed + +// ----------------------------------------------------------------------------- + +void ListWidget::focusHeader(const NavigationDirection nav) +{ + if (m_header.empty() || getItemCount() == 0) + { + setSelectionID(nav == NAV_UP ? getItemCount() - 1 : 0); + } + else + { + repairSortCol(); + m_selected_column = m_header_elements.get(m_sort_col); + m_selected_column->setFocusForPlayer(0); + m_choosing_header = true; + } +} + +// ----------------------------------------------------------------------------- + EventPropagation ListWidget::moveToNextItem(const bool reverse) { // if widget is deactivated, do nothing @@ -570,6 +628,11 @@ EventPropagation ListWidget::moveToNextItem(const bool reverse) if (stay_within_list) { + if (m_choosing_header) + { + m_choosing_header = false; + setFocusForPlayer(0); + } if (reverse) setSelectionID(getSelectionID() - 1); else @@ -578,6 +641,17 @@ EventPropagation ListWidget::moveToNextItem(const bool reverse) } else { + if (reverse && !m_choosing_header && + m_sort_col < (int)m_header_elements.size()) + { + // Up pressed + repairSortCol(); + m_selected_column = m_header_elements.get(m_sort_col); + m_selected_column->setFocusForPlayer(0); + setSelectionID(-1); // select nothing + m_choosing_header = true; + return EVENT_LET; + } setSelectionID(-1); // select nothing } return EVENT_BLOCK; diff --git a/src/guiengine/widgets/list_widget.hpp b/src/guiengine/widgets/list_widget.hpp index 8ffb0a296..541c3ade1 100644 --- a/src/guiengine/widgets/list_widget.hpp +++ b/src/guiengine/widgets/list_widget.hpp @@ -68,7 +68,9 @@ namespace GUIEngine /** index of column*/ int m_sort_col; - + + bool m_choosing_header; + struct Column { irr::core::stringw m_text; @@ -96,6 +98,16 @@ namespace GUIEngine bool m_header_created; + void repairSortCol() + { + // Exclude scrollbar + int max_size = (int)m_header_elements.size() - 1; + if (m_sort_col < 0) + m_sort_col = max_size - 1; + else if (m_sort_col >= max_size) + m_sort_col = 0; + } + public: typedef irr::gui::CGUISTKListBox::ListItem ListItem; typedef ListItem::ListCell ListCell; @@ -266,6 +278,12 @@ namespace GUIEngine /** \brief implementing method from base class Widget */ virtual EventPropagation downPressed(const int playerID); + /** \brief implementing method from base class Widget */ + virtual EventPropagation leftPressed(const int playerID); + + /** \brief implementing method from base class Widget */ + virtual EventPropagation rightPressed(const int playerID); + /** \brief implement common core parts of upPressed and downPressed */ EventPropagation moveToNextItem(const bool down); @@ -282,6 +300,8 @@ namespace GUIEngine void addColumn(irr::video::ITexture* tex, int proportion=1) { m_header.push_back( Column(tex, proportion) ); } void setSortable(bool sortable) { m_sortable = sortable; } + void focusHeader(const NavigationDirection nav); + }; }