From 377dd992b924c82066c1c6f776c5fbafb71011f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Thu, 23 Nov 2017 14:48:59 +0100 Subject: [PATCH] Sdk/Canvas: Implement tab/shift-tab to switch to next/previous widget --- ChangeLog.md | 2 + SDK/include/NDK/BaseWidget.hpp | 3 +- SDK/include/NDK/Widgets/TextAreaWidget.hpp | 2 +- SDK/src/NDK/BaseWidget.cpp | 8 +++- SDK/src/NDK/Canvas.cpp | 52 +++++++++++++++++++++- SDK/src/NDK/Widgets/TextAreaWidget.cpp | 31 +++++++------ 6 files changed, 81 insertions(+), 17 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index 9d2e4b739..3e4eccbc0 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -44,6 +44,8 @@ Nazara Development Kit: - Add Entity::Disable method, which is a shortcut to Enable(false) - Add BaseWidget::HasFocus - 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: diff --git a/SDK/include/NDK/BaseWidget.hpp b/SDK/include/NDK/BaseWidget.hpp index cff9b1a9e..175a1d71d 100644 --- a/SDK/include/NDK/BaseWidget.hpp +++ b/SDK/include/NDK/BaseWidget.hpp @@ -88,9 +88,10 @@ namespace Ndk virtual void Layout(); void InvalidateNode() override; + virtual bool IsFocusable() const; virtual void OnFocusLost(); 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 OnMouseEnter(); virtual void OnMouseMoved(int x, int y, int deltaX, int deltaY); diff --git a/SDK/include/NDK/Widgets/TextAreaWidget.hpp b/SDK/include/NDK/Widgets/TextAreaWidget.hpp index 270df9547..300cc2196 100644 --- a/SDK/include/NDK/Widgets/TextAreaWidget.hpp +++ b/SDK/include/NDK/Widgets/TextAreaWidget.hpp @@ -76,7 +76,7 @@ namespace Ndk bool IsFocusable() const override; void OnFocusLost() 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 OnMouseButtonPress(int /*x*/, int /*y*/, Nz::Mouse::Button button) override; void OnTextEntered(char32_t character, bool repeated) override; diff --git a/SDK/src/NDK/BaseWidget.cpp b/SDK/src/NDK/BaseWidget.cpp index 61bc9b13c..ff38e6f34 100644 --- a/SDK/src/NDK/BaseWidget.cpp +++ b/SDK/src/NDK/BaseWidget.cpp @@ -189,6 +189,11 @@ namespace Ndk m_canvas->NotifyWidgetBoxUpdate(m_canvasIndex); } + bool BaseWidget::IsFocusable() const + { + return false; + } + 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*/) diff --git a/SDK/src/NDK/Canvas.cpp b/SDK/src/NDK/Canvas.cpp index 757ad46a3..32f02d5c5 100644 --- a/SDK/src/NDK/Canvas.cpp +++ b/SDK/src/NDK/Canvas.cpp @@ -144,7 +144,57 @@ namespace Ndk void Canvas::OnEventKeyPressed(const Nz::EventHandler* /*eventHandler*/, const Nz::WindowEvent::KeyEvent& event) { 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) diff --git a/SDK/src/NDK/Widgets/TextAreaWidget.cpp b/SDK/src/NDK/Widgets/TextAreaWidget.cpp index 52a879b14..586de7456 100644 --- a/SDK/src/NDK/Widgets/TextAreaWidget.cpp +++ b/SDK/src/NDK/Widgets/TextAreaWidget.cpp @@ -134,9 +134,14 @@ namespace Ndk RefreshCursor(); } + bool TextAreaWidget::IsFocusable() const + { + return !m_readOnly; + } + void TextAreaWidget::OnFocusLost() { - m_cursorEntity->Enable(false); + m_cursorEntity->Disable(); } void TextAreaWidget::OnFocusReceived() @@ -145,7 +150,7 @@ namespace Ndk m_cursorEntity->Enable(true); } - void TextAreaWidget::OnKeyPressed(const Nz::WindowEvent::KeyEvent& key) + bool TextAreaWidget::OnKeyPressed(const Nz::WindowEvent::KeyEvent& key) { switch (key.code) { @@ -155,7 +160,7 @@ namespace Ndk std::size_t textLength = m_text.GetLength(); if (cursorGlyph > textLength) - break; + return true; Nz::String newText; if (cursorGlyph > 0) @@ -165,7 +170,7 @@ namespace Ndk newText.Append(m_text.SubString(m_text.GetCharacterPosition(cursorGlyph + 1))); SetText(newText); - break; + return true; } case Nz::Keyboard::Down: @@ -174,10 +179,10 @@ namespace Ndk OnTextAreaKeyDown(this, &ignoreDefaultAction); if (ignoreDefaultAction) - break; + return true; MoveCursor({0, 1}); - break; + return true; } case Nz::Keyboard::Left: @@ -186,10 +191,10 @@ namespace Ndk OnTextAreaKeyLeft(this, &ignoreDefaultAction); if (ignoreDefaultAction) - break; + return true; MoveCursor(-1); - break; + return true; } case Nz::Keyboard::Right: @@ -198,10 +203,10 @@ namespace Ndk OnTextAreaKeyRight(this, &ignoreDefaultAction); if (ignoreDefaultAction) - break; + return true; MoveCursor(1); - break; + return true; } case Nz::Keyboard::Up: @@ -210,14 +215,14 @@ namespace Ndk OnTextAreaKeyUp(this, &ignoreDefaultAction); if (ignoreDefaultAction) - break; + return true; MoveCursor({0, -1}); - break; + return true; } default: - break; + return false; } }