Sdk/Canvas: Implement tab/shift-tab to switch to next/previous widget

This commit is contained in:
Jérôme Leclercq 2017-11-23 14:48:59 +01:00
parent 4116984f9f
commit 377dd992b9
6 changed files with 81 additions and 17 deletions

View File

@ -44,6 +44,8 @@ Nazara Development Kit:
- Add Entity::Disable method, which is a shortcut to Enable(false) - Add Entity::Disable method, which is a shortcut to Enable(false)
- Add BaseWidget::HasFocus - Add BaseWidget::HasFocus
- Fix TextAreaWidget cursor sometimes showing up in readonly mode - Fix TextAreaWidget cursor sometimes showing up in readonly mode
- ⚠️ BaseWidget::OnKeyPressed now returns a boolean to indicate if it should block default action (such as tab to switch to the previous/next widget)
- Pressing tab/shift-tab will now move to the next/previous widget able to be focused on
# 0.4: # 0.4:

View File

@ -88,9 +88,10 @@ namespace Ndk
virtual void Layout(); virtual void Layout();
void InvalidateNode() override; void InvalidateNode() override;
virtual bool IsFocusable() const;
virtual void OnFocusLost(); virtual void OnFocusLost();
virtual void OnFocusReceived(); virtual void OnFocusReceived();
virtual void OnKeyPressed(const Nz::WindowEvent::KeyEvent& key); virtual bool OnKeyPressed(const Nz::WindowEvent::KeyEvent& key);
virtual void OnKeyReleased(const Nz::WindowEvent::KeyEvent& key); virtual void OnKeyReleased(const Nz::WindowEvent::KeyEvent& key);
virtual void OnMouseEnter(); virtual void OnMouseEnter();
virtual void OnMouseMoved(int x, int y, int deltaX, int deltaY); virtual void OnMouseMoved(int x, int y, int deltaX, int deltaY);

View File

@ -76,7 +76,7 @@ namespace Ndk
bool IsFocusable() const override; bool IsFocusable() const override;
void OnFocusLost() override; void OnFocusLost() override;
void OnFocusReceived() override; void OnFocusReceived() override;
void OnKeyPressed(const Nz::WindowEvent::KeyEvent& key) override; bool OnKeyPressed(const Nz::WindowEvent::KeyEvent& key) override;
void OnKeyReleased(const Nz::WindowEvent::KeyEvent& key) override; void OnKeyReleased(const Nz::WindowEvent::KeyEvent& key) override;
void OnMouseButtonPress(int /*x*/, int /*y*/, Nz::Mouse::Button button) override; void OnMouseButtonPress(int /*x*/, int /*y*/, Nz::Mouse::Button button) override;
void OnTextEntered(char32_t character, bool repeated) override; void OnTextEntered(char32_t character, bool repeated) override;

View File

@ -189,6 +189,11 @@ namespace Ndk
m_canvas->NotifyWidgetBoxUpdate(m_canvasIndex); m_canvas->NotifyWidgetBoxUpdate(m_canvasIndex);
} }
bool BaseWidget::IsFocusable() const
{
return false;
}
void BaseWidget::OnFocusLost() void BaseWidget::OnFocusLost()
{ {
} }
@ -197,8 +202,9 @@ namespace Ndk
{ {
} }
void BaseWidget::OnKeyPressed(const Nz::WindowEvent::KeyEvent& /*key*/) bool BaseWidget::OnKeyPressed(const Nz::WindowEvent::KeyEvent& key)
{ {
return false;
} }
void BaseWidget::OnKeyReleased(const Nz::WindowEvent::KeyEvent& /*key*/) void BaseWidget::OnKeyReleased(const Nz::WindowEvent::KeyEvent& /*key*/)

View File

@ -144,7 +144,57 @@ namespace Ndk
void Canvas::OnEventKeyPressed(const Nz::EventHandler* /*eventHandler*/, const Nz::WindowEvent::KeyEvent& event) void Canvas::OnEventKeyPressed(const Nz::EventHandler* /*eventHandler*/, const Nz::WindowEvent::KeyEvent& event)
{ {
if (m_keyboardOwner != InvalidCanvasIndex) if (m_keyboardOwner != InvalidCanvasIndex)
m_widgetEntries[m_keyboardOwner].widget->OnKeyPressed(event); {
if (m_widgetEntries[m_keyboardOwner].widget->OnKeyPressed(event))
return;
if (event.code == Nz::Keyboard::Tab)
{
if (!event.shift)
{
// Forward
for (std::size_t i = m_keyboardOwner + 1; i < m_widgetEntries.size(); ++i)
{
if (m_widgetEntries[i].widget->IsFocusable())
{
SetKeyboardOwner(i);
return;
}
}
for (std::size_t i = 0; i < m_keyboardOwner; ++i)
{
if (m_widgetEntries[i].widget->IsFocusable())
{
SetKeyboardOwner(i);
return;
}
}
}
else
{
// Backward
for (decltype(m_widgetEntries)::reverse_iterator rit{ m_widgetEntries.begin() + m_keyboardOwner }; rit != m_widgetEntries.rend(); ++rit)
{
if (rit->widget->IsFocusable())
{
SetKeyboardOwner(std::distance(m_widgetEntries.begin(), rit.base()) - 1);
return;
}
}
decltype(m_widgetEntries)::reverse_iterator rend { m_widgetEntries.begin() + m_keyboardOwner };
for (auto rit = m_widgetEntries.rbegin(); rit != rend; ++rit)
{
if (rit->widget->IsFocusable())
{
SetKeyboardOwner(std::distance(m_widgetEntries.begin(), rit.base()) - 1);
return;
}
}
}
}
}
} }
void Canvas::OnEventKeyReleased(const Nz::EventHandler* /*eventHandler*/, const Nz::WindowEvent::KeyEvent& event) void Canvas::OnEventKeyReleased(const Nz::EventHandler* /*eventHandler*/, const Nz::WindowEvent::KeyEvent& event)

View File

@ -134,9 +134,14 @@ namespace Ndk
RefreshCursor(); RefreshCursor();
} }
bool TextAreaWidget::IsFocusable() const
{
return !m_readOnly;
}
void TextAreaWidget::OnFocusLost() void TextAreaWidget::OnFocusLost()
{ {
m_cursorEntity->Enable(false); m_cursorEntity->Disable();
} }
void TextAreaWidget::OnFocusReceived() void TextAreaWidget::OnFocusReceived()
@ -145,7 +150,7 @@ namespace Ndk
m_cursorEntity->Enable(true); m_cursorEntity->Enable(true);
} }
void TextAreaWidget::OnKeyPressed(const Nz::WindowEvent::KeyEvent& key) bool TextAreaWidget::OnKeyPressed(const Nz::WindowEvent::KeyEvent& key)
{ {
switch (key.code) switch (key.code)
{ {
@ -155,7 +160,7 @@ namespace Ndk
std::size_t textLength = m_text.GetLength(); std::size_t textLength = m_text.GetLength();
if (cursorGlyph > textLength) if (cursorGlyph > textLength)
break; return true;
Nz::String newText; Nz::String newText;
if (cursorGlyph > 0) if (cursorGlyph > 0)
@ -165,7 +170,7 @@ namespace Ndk
newText.Append(m_text.SubString(m_text.GetCharacterPosition(cursorGlyph + 1))); newText.Append(m_text.SubString(m_text.GetCharacterPosition(cursorGlyph + 1)));
SetText(newText); SetText(newText);
break; return true;
} }
case Nz::Keyboard::Down: case Nz::Keyboard::Down:
@ -174,10 +179,10 @@ namespace Ndk
OnTextAreaKeyDown(this, &ignoreDefaultAction); OnTextAreaKeyDown(this, &ignoreDefaultAction);
if (ignoreDefaultAction) if (ignoreDefaultAction)
break; return true;
MoveCursor({0, 1}); MoveCursor({0, 1});
break; return true;
} }
case Nz::Keyboard::Left: case Nz::Keyboard::Left:
@ -186,10 +191,10 @@ namespace Ndk
OnTextAreaKeyLeft(this, &ignoreDefaultAction); OnTextAreaKeyLeft(this, &ignoreDefaultAction);
if (ignoreDefaultAction) if (ignoreDefaultAction)
break; return true;
MoveCursor(-1); MoveCursor(-1);
break; return true;
} }
case Nz::Keyboard::Right: case Nz::Keyboard::Right:
@ -198,10 +203,10 @@ namespace Ndk
OnTextAreaKeyRight(this, &ignoreDefaultAction); OnTextAreaKeyRight(this, &ignoreDefaultAction);
if (ignoreDefaultAction) if (ignoreDefaultAction)
break; return true;
MoveCursor(1); MoveCursor(1);
break; return true;
} }
case Nz::Keyboard::Up: case Nz::Keyboard::Up:
@ -210,14 +215,14 @@ namespace Ndk
OnTextAreaKeyUp(this, &ignoreDefaultAction); OnTextAreaKeyUp(this, &ignoreDefaultAction);
if (ignoreDefaultAction) if (ignoreDefaultAction)
break; return true;
MoveCursor({0, -1}); MoveCursor({0, -1});
break; return true;
} }
default: default:
break; return false;
} }
} }