Implement keyboard sorting list widget

This commit is contained in:
Benau 2019-11-04 16:41:23 +08:00
parent 5f32b81ab8
commit 1d384961dd
4 changed files with 101 additions and 7 deletions

View File

@ -509,7 +509,7 @@ void EventHandler::navigate(const NavigationDirection nav, const int playerID)
{ {
ListWidget* list = (ListWidget*) closest_widget; ListWidget* list = (ListWidget*) closest_widget;
assert(list != NULL); 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 // 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)) if (closest_widget->m_type == GUIEngine::WTYPE_RIBBON && (nav == NAV_UP || nav == NAV_DOWN))

View File

@ -1822,20 +1822,20 @@ void Skin::drawListHeader(const irr::core::rect< irr::s32 > &rect,
Widget* widget) Widget* widget)
{ {
#ifndef SERVER_ONLY #ifndef SERVER_ONLY
ListWidget* list = static_cast<ListWidget*>(widget->m_event_handler);
bool isSelected = bool isSelected =
(((ListWidget*)widget->m_event_handler)->m_selected_column == widget && (list->m_selected_column == widget && list->m_choosing_header);
((ListWidget*)widget->m_event_handler)->m_sort_default == false);
drawBoxFromStretchableTexture(widget, rect, drawBoxFromStretchableTexture(widget, rect,
(isSelected ? SkinConfig::m_render_params["list_header::down"] (isSelected ? SkinConfig::m_render_params["list_header::down"]
: SkinConfig::m_render_params["list_header::neutral"]), : SkinConfig::m_render_params["list_header::neutral"]),
false, NULL /* clip */); 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 **/ /** \brief img sets the icon for the column according to sort order **/
ITexture* img; ITexture* img;
if (((ListWidget*)widget->m_event_handler)->m_sort_desc) if (list->m_sort_desc)
img = img =
SkinConfig::m_render_params["list_sort_down::neutral"].getImage(); SkinConfig::m_render_params["list_sort_down::neutral"].getImage();
else else

View File

@ -47,6 +47,7 @@ ListWidget::ListWidget() : Widget(WTYPE_LIST)
m_sort_col = 0; m_sort_col = 0;
m_sortable = true; m_sortable = true;
m_header_created = false; 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) void ListWidget::selectItemWithLabel(const irr::core::stringw& name)
{ {
// Disable focusing header for choosing
m_choosing_header = false;
CGUISTKListBox* list = getIrrlichtElement<CGUISTKListBox>(); CGUISTKListBox* list = getIrrlichtElement<CGUISTKListBox>();
assert(list != NULL); assert(list != NULL);
return list->setSelectedByCellText( name.c_str() ); 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 // May only be called AFTER this widget has been add()ed
assert(m_element != NULL); assert(m_element != NULL);
// Disable focusing header for choosing
m_choosing_header = false;
CGUISTKListBox* irritem = getIrrlichtElement<CGUISTKListBox>(); CGUISTKListBox* irritem = getIrrlichtElement<CGUISTKListBox>();
// auto-scroll to item when selecting something, don't auto-scroll when selecting nothing // 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_sort_col = originator[(m_properties[PROP_ID] + "_column_").size()] - '0';
m_selected_column = m_header_elements.get(m_sort_col); m_selected_column = m_header_elements.get(m_sort_col);
m_choosing_header = true;
/** \brief Allows sort icon to change depending on sort order **/ /** \brief Allows sort icon to change depending on sort order **/
/* /*
@ -560,6 +567,57 @@ EventPropagation ListWidget::downPressed(const int playerID)
return moveToNextItem(/*reverse*/ false); return moveToNextItem(/*reverse*/ false);
} // downPressed } // 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) EventPropagation ListWidget::moveToNextItem(const bool reverse)
{ {
// if widget is deactivated, do nothing // if widget is deactivated, do nothing
@ -570,6 +628,11 @@ EventPropagation ListWidget::moveToNextItem(const bool reverse)
if (stay_within_list) if (stay_within_list)
{ {
if (m_choosing_header)
{
m_choosing_header = false;
setFocusForPlayer(0);
}
if (reverse) if (reverse)
setSelectionID(getSelectionID() - 1); setSelectionID(getSelectionID() - 1);
else else
@ -578,6 +641,17 @@ EventPropagation ListWidget::moveToNextItem(const bool reverse)
} }
else 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 setSelectionID(-1); // select nothing
} }
return EVENT_BLOCK; return EVENT_BLOCK;

View File

@ -68,7 +68,9 @@ namespace GUIEngine
/** index of column*/ /** index of column*/
int m_sort_col; int m_sort_col;
bool m_choosing_header;
struct Column struct Column
{ {
irr::core::stringw m_text; irr::core::stringw m_text;
@ -96,6 +98,16 @@ namespace GUIEngine
bool m_header_created; 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: public:
typedef irr::gui::CGUISTKListBox::ListItem ListItem; typedef irr::gui::CGUISTKListBox::ListItem ListItem;
typedef ListItem::ListCell ListCell; typedef ListItem::ListCell ListCell;
@ -266,6 +278,12 @@ namespace GUIEngine
/** \brief implementing method from base class Widget */ /** \brief implementing method from base class Widget */
virtual EventPropagation downPressed(const int playerID); 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 */ /** \brief implement common core parts of upPressed and downPressed */
EventPropagation moveToNextItem(const bool down); 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 addColumn(irr::video::ITexture* tex, int proportion=1) { m_header.push_back( Column(tex, proportion) ); }
void setSortable(bool sortable) { m_sortable = sortable; } void setSortable(bool sortable) { m_sortable = sortable; }
void focusHeader(const NavigationDirection nav);
}; };
} }