Improved spinner (#3374)

* Add spinner arrow focus with keyboard

* Improve keyboard navigation for spinners

* Only display active arrow if spinner is focused
This commit is contained in:
Alayan-stk-2 2018-08-13 00:00:42 +02:00 committed by auriamg
parent 64595a7b18
commit 41a3a1056e
4 changed files with 95 additions and 36 deletions

View File

@ -30,6 +30,7 @@
#include "guiengine/widget.hpp"
#include "guiengine/widgets/list_widget.hpp"
#include "guiengine/widgets/ribbon_widget.hpp"
#include "guiengine/widgets/spinner_widget.hpp"
#include "input/input_manager.hpp"
#include "modes/demo_world.hpp"
#include "modes/world.hpp"
@ -488,6 +489,16 @@ void EventHandler::navigate(const NavigationDirection nav, const int playerID)
sendEventToUser(ribbon, ribbon->m_properties[PROP_ID], playerID);
}
}
// For spinners, select the most intuitive button
// based on where the navigation came from
// Right if coming from right by a left press
// Left for all other directions
if (closest_widget->getType() == WTYPE_SPINNER)
{
SpinnerWidget* spinner = dynamic_cast<SpinnerWidget*>(closest_widget);
spinner->setSelectedButton(nav == NAV_LEFT);
}
}
return;
@ -724,6 +735,7 @@ EventPropagation EventHandler::onWidgetActivated(GUIEngine::Widget* w, const int
Widget* parent = w->m_event_handler;
//FIXME : sendEventToUser do the same screen keyboard and modal dialog checks, so they are done twice
if (ScreenKeyboard::isActive())
{
if (ScreenKeyboard::getCurrent()->processEvent(w->m_properties[PROP_ID]) == EVENT_BLOCK)
@ -743,6 +755,13 @@ EventPropagation EventHandler::onWidgetActivated(GUIEngine::Widget* w, const int
//Log::info("EventHandler", "Widget activated: %s", w->m_properties[PROP_ID].c_str());
// For spinners, also trigger activation
if (w->getType() == WTYPE_SPINNER)
{
SpinnerWidget* spinner = dynamic_cast<SpinnerWidget*>(w);
spinner->activateSelectedButton();
}
if (w->m_event_handler != NULL)
{
/* Find all parents. Stop looping if a widget event handler's is itself, to not fall

View File

@ -1410,20 +1410,29 @@ void Skin::drawSpinnerBody(const core::recti &rect, Widget* widget,
void Skin::drawSpinnerChild(const core::recti &rect, Widget* widget,
const bool pressed, bool focused)
{
if (!widget->isVisible()) return;
if (!widget->isVisible() || widget->m_deactivated) return;
if (!widget->m_deactivated && pressed)
int areas = 0;
bool right;
if (widget->m_properties[PROP_ID] == "left")
{
Widget* spinner = widget->m_event_handler;
int areas = 0;
areas = BoxRenderParams::LEFT;
right = false;
}
else if (widget->m_properties[PROP_ID] == "right")
{
areas = BoxRenderParams::RIGHT;
right = true;
}
else
return;
if (widget->m_properties[PROP_ID] == "left")
areas = BoxRenderParams::LEFT;
else if (widget->m_properties[PROP_ID] == "right")
areas = BoxRenderParams::RIGHT;
else
return;
SpinnerWidget* spinner = dynamic_cast<SpinnerWidget*>(widget->m_event_handler);
bool spinner_focused = spinner->isFocusedForPlayer(PLAYER_ID_GAME_MASTER);
if (pressed || (spinner->isRightButtonSelected() == right && spinner_focused))
{
core::recti rect2(spinner->m_x, spinner->m_y,
spinner->m_x + spinner->m_w,
spinner->m_y + spinner->m_h );
@ -1434,7 +1443,7 @@ void Skin::drawSpinnerChild(const core::recti &rect, Widget* widget,
widget->m_deactivated);
}
}
} // drawSpinnerChild
// ----------------------------------------------------------------------------
/**

View File

@ -49,6 +49,7 @@ SpinnerWidget::SpinnerWidget(const bool gauge) : Widget(WTYPE_SPINNER)
m_spinner_widget_player_id=-1;
m_min = 0;
m_max = 999;
m_right_selected = false;
}
// -----------------------------------------------------------------------------
@ -230,45 +231,65 @@ void SpinnerWidget::move(const int x, const int y, const int w, const int h)
EventPropagation SpinnerWidget::rightPressed(const int playerID)
{
//Log::info("SpinnerWidget", "Right pressed");
// if widget is deactivated, do nothing
if (m_deactivated) return EVENT_BLOCK;
//Log::info("SpinnerWidget", "Right pressed");
if (m_value+1 <= m_max)
{
setValue(m_value+1);
}
else if (m_wrap_around)
{
setValue(m_min);
}
//GUIEngine::transmitEvent( this, m_properties[PROP_ID], playerID );
// if right arrow is selected, let event handler move to next widget
if (m_right_selected)
return EVENT_BLOCK;
else
setSelectedButton(/* right*/ true);
return EVENT_LET;
}
} // rightPressed
// -----------------------------------------------------------------------------
EventPropagation SpinnerWidget::leftPressed(const int playerID)
{
//Log::info("SpinnerWidget", "Left pressed");
// if widget is deactivated, do nothing
if (m_deactivated) return EVENT_BLOCK;
//Log::info("SpinnerWidget", "Left pressed");
if (m_value-1 >= m_min)
{
setValue(m_value-1);
}
else if (m_wrap_around)
{
setValue(m_max);
}
//GUIEngine::transmitEvent( this, m_properties[PROP_ID], playerID );
// if right arrow is selected, select left arrow
if (m_right_selected)
setSelectedButton(/* right*/ false);
// if left arrow is selected, let navigation move to next widget
else
return EVENT_BLOCK;
return EVENT_LET;
}
} // leftPressed
void SpinnerWidget::activateSelectedButton()
{
if (m_right_selected)
{
if (m_value+1 <= m_max)
{
setValue(m_value+1);
}
else if (m_wrap_around)
{
setValue(m_min);
}
}
else // left button active
{
if (m_value-1 >= m_min)
{
setValue(m_value-1);
}
else if (m_wrap_around)
{
setValue(m_max);
}
}
} // activateSelectedButton
// -----------------------------------------------------------------------------
@ -283,11 +304,13 @@ EventPropagation SpinnerWidget::transmitEvent(Widget* w,
if (originator == "left")
{
leftPressed(playerID);
m_right_selected = false;
activateSelectedButton();
}
else if (originator == "right")
{
rightPressed(playerID);
m_right_selected = true;
activateSelectedButton();
}
else if (originator == "spinnerbody" || originator == m_properties[PROP_ID])
{

View File

@ -76,6 +76,9 @@ namespace GUIEngine
/** \brief Whether to wrap back to the first value when going "beyond" the last value */
bool m_wrap_around;
/** \brief Whether the right or left arrow is the currently selected one */
bool m_right_selected;
/** \brief Keeps track of the custom text in spinner (a text which isn't related to a value)
* to remember it and set it back (example : when we deactivate the widget)
*/
@ -124,6 +127,11 @@ namespace GUIEngine
int getSpinnerWidgetPlayerID() {return m_spinner_widget_player_id; }
void unsetUseBackgroundColor() {m_use_background_color=false; }
void activateSelectedButton();
void setSelectedButton(bool right) {m_right_selected = right; }
bool isRightButtonSelected() {return m_right_selected; }
void setListener(ISpinnerConfirmListener* listener) { m_listener = listener; }