propigate key events around UI

use key events to add and remove sliders from settings as example
This commit is contained in:
MatthewColvin 2023-10-01 18:53:25 -05:00
parent a44e92ea5d
commit 3bd2b1a98a
13 changed files with 148 additions and 20 deletions

View file

@ -6,6 +6,12 @@ UIElement::UIElement(lv_obj_t *aLvglSelf, ID aId)
mLvglSelf->user_data = this; mLvglSelf->user_data = this;
} }
UIElement::~UIElement() {
if (lv_obj_is_valid(mLvglSelf)) {
lv_obj_del(mLvglSelf);
}
}
void UIElement::AddElement(UIElement *anUIElement) { void UIElement::AddElement(UIElement *anUIElement) {
lv_obj_set_parent(anUIElement->mLvglSelf, mLvglSelf); lv_obj_set_parent(anUIElement->mLvglSelf, mLvglSelf);
} }

View file

@ -1,7 +1,7 @@
#pragma once #pragma once
#include "UIElementIds.hpp" #include "UIElementIds.hpp"
#include "lvgl.h" #include <lvgl.h>
#include "KeyPressAbstract.hpp" #include "KeyPressAbstract.hpp"
@ -11,6 +11,7 @@ class UIElement {
public: public:
UIElement(lv_obj_t *aLvglSelf, const ID aId = ID()); UIElement(lv_obj_t *aLvglSelf, const ID aId = ID());
virtual ~UIElement();
virtual void SetBgColor(lv_color_t value, virtual void SetBgColor(lv_color_t value,
lv_style_selector_t selector = LV_PART_MAIN); lv_style_selector_t selector = LV_PART_MAIN);

View file

@ -1,5 +1,5 @@
#include "BackgroundScreen.hpp"
#include "PageBase.hpp" #include "PageBase.hpp"
#include "BackgroundScreen.hpp"
using namespace UI::Page; using namespace UI::Page;
@ -11,8 +11,37 @@ Base::Base(lv_obj_t *aLvglSelf, ID aID) : UIElement(aLvglSelf, aID) {
SetWidth(lv_pct(100)); SetWidth(lv_pct(100));
lv_obj_set_align(aLvglSelf, LV_ALIGN_CENTER); lv_obj_set_align(aLvglSelf, LV_ALIGN_CENTER);
} }
// Return non owning refrence to widget
void Base::AddWidget(Widget::Base::Ptr aWidget) { UI::Widget::Base *Base::AddWidget(Widget::Base::Ptr aWidget) {
AddElement(aWidget.get()); AddElement(aWidget.get());
mWidgets.push_back(std::move(aWidget)); mWidgets.push_back(std::move(aWidget));
return mWidgets[mWidgets.size() - 1].get();
} }
UI::Widget::Base::Ptr Base::RemoveWidget(Widget::Base *aWidgetRefrence) {
auto widgetToRemoveIter = std::find_if(
mWidgets.begin(), mWidgets.end(), [aWidgetRefrence](auto &aWidget) {
return aWidget.get() == aWidgetRefrence;
});
if (widgetToRemoveIter != mWidgets.end()) {
auto widget = std::move(*widgetToRemoveIter);
mWidgets.erase(widgetToRemoveIter);
return widget;
}
return nullptr;
}
bool Base::KeyEvent(KeyPressAbstract::KeyEvent aKeyEvent) {
if (OnKeyEvent(aKeyEvent)) {
return true;
}
for (auto &widget : mWidgets) {
auto used = widget->KeyEvent(aKeyEvent);
if (used) {
return true;
}
}
return false;
};
bool Base::OnKeyEvent(KeyPressAbstract::KeyEvent aKeyEvent) { return false; };

View file

@ -4,8 +4,10 @@
#include <vector> #include <vector>
namespace UI::Page { namespace UI::Page {
class Tab;
class TabView; class TabView;
class Base : public UIElement { class Base : public UIElement {
friend Tab; // Allow Tab to Forward all Key Events to its page
friend TabView; // Allow Tab view to call OnShow and OnHide Since it can show friend TabView; // Allow Tab view to call OnShow and OnHide Since it can show
// and Hide pages by swiping // and Hide pages by swiping
public: public:
@ -13,16 +15,18 @@ public:
Base(ID aID); Base(ID aID);
Base(lv_obj_t *aLvglSelf, ID aID); Base(lv_obj_t *aLvglSelf, ID aID);
virtual ~Base() = default;
void AddWidget(Widget::Base::Ptr aWidget); Widget::Base *AddWidget(Widget::Base::Ptr aWidget);
Widget::Base::Ptr RemoveWidget(Widget::Base *aWidgetRefrence);
size_t GetNumWidgets() { return mWidgets.size(); } size_t GetNumWidgets() { return mWidgets.size(); }
protected: protected:
void OnShow() override{}; void OnShow() override{};
void OnHide() override{}; void OnHide() override{};
bool OnKeyEvent(KeyPressAbstract::KeyEvent aKeyEvent) override {
return false; bool KeyEvent(KeyPressAbstract::KeyEvent aKeyEvent) override;
}; bool OnKeyEvent(KeyPressAbstract::KeyEvent aKeyEvent) override;
private: private:
std::vector<Widget::Base::Ptr> mWidgets; std::vector<Widget::Base::Ptr> mWidgets;

View file

@ -1,5 +1,5 @@
#include "BackgroundScreen.hpp"
#include "SettingsPage.hpp" #include "SettingsPage.hpp"
#include "BackgroundScreen.hpp"
using namespace UI::Page; using namespace UI::Page;
@ -7,7 +7,9 @@ SettingsPage::SettingsPage() : Base(ID::Pages::Settings) {
SetBgColor(lv_color_make(255, 0, 0)); SetBgColor(lv_color_make(255, 0, 0));
} }
void SettingsPage::OnShow() { void SettingsPage::OnShow() {}
void SettingsPage::AddSlider() {
auto fakeSlider = std::make_unique<UI::Widget::Base>( auto fakeSlider = std::make_unique<UI::Widget::Base>(
lv_slider_create(UI::Screen::BackgroundScreen::getLvInstance())); lv_slider_create(UI::Screen::BackgroundScreen::getLvInstance()));
fakeSlider->SetHeight(lv_pct(10)); fakeSlider->SetHeight(lv_pct(10));
@ -16,5 +18,36 @@ void SettingsPage::OnShow() {
auto sliderHeight = fakeSlider->GetHeight(); auto sliderHeight = fakeSlider->GetHeight();
fakeSlider->SetY(sliderHeight * GetNumWidgets()); fakeSlider->SetY(sliderHeight * GetNumWidgets());
AddWidget(std::move(fakeSlider)); sliders.push_back(AddWidget(std::move(fakeSlider)));
}
bool SettingsPage::OnKeyEvent(KeyPressAbstract::KeyEvent aKeyEvent) {
using id = KeyPressAbstract::KeyId;
using eventType = KeyPressAbstract::KeyEvent::Type;
bool used = true;
switch (aKeyEvent.mId) {
case id::Aux1:
if (aKeyEvent.mType == eventType::Press) {
AddSlider();
}
break;
case id::Aux2:
if (aKeyEvent.mType == eventType::Release) {
if (sliders.size() > 0) {
auto widget = RemoveWidget(sliders[0]);
sliders.erase(
sliders.begin()); // sliders is non owning so after removing delete
// it from non owning array
}
}
break;
case id::Aux3:
break;
case id::Aux4:
break;
default:
used = false;
break;
}
return used;
} }

View file

@ -5,7 +5,13 @@ class SettingsPage : public Base {
public: public:
SettingsPage(); SettingsPage();
bool OnKeyEvent(KeyPressAbstract::KeyEvent aKeyEvent) override;
void AddSlider();
protected: protected:
void OnShow() override; void OnShow() override;
std::vector<Widget::Base *> sliders;
}; };
} // namespace UI::Page } // namespace UI::Page

View file

@ -1,5 +1,5 @@
#include "BackgroundScreen.hpp"
#include "TabView.hpp" #include "TabView.hpp"
#include "BackgroundScreen.hpp"
#include <string> #include <string>
using namespace UI::Page; using namespace UI::Page;
@ -13,6 +13,16 @@ void Tab::GiveContent(Page::Base::Ptr aContent) {
Base::Ptr Tab::TakeContent() { return std::move(mContent); } Base::Ptr Tab::TakeContent() { return std::move(mContent); }
bool Tab::OnKeyEvent(KeyPressAbstract::KeyEvent aKeyEvent) {
return mContent->OnKeyEvent(aKeyEvent);
}
bool Tab::KeyEvent(KeyPressAbstract::KeyEvent aKeyEvent) {
return mContent->KeyEvent(aKeyEvent);
}
/////////////////////TabView/////////////////////////////////////
TabView::TabView(ID aId) TabView::TabView(ID aId)
: Base(lv_tabview_create(Screen::BackgroundScreen::getLvInstance(), : Base(lv_tabview_create(Screen::BackgroundScreen::getLvInstance(),
LV_DIR_TOP, 0), LV_DIR_TOP, 0),
@ -60,3 +70,10 @@ void TabView::HandleTabChangeImpl(lv_event_t *aTabChangeEvent) {
self->HandleTabChange(); self->HandleTabChange();
} }
} }
bool TabView::KeyEvent(KeyPressAbstract::KeyEvent aKeyEvent) {
if (OnKeyEvent(aKeyEvent)) {
return true;
}
return mTabs[GetCurrentTabIdx()]->KeyEvent(aKeyEvent);
};

View file

@ -2,8 +2,11 @@
#include <functional> #include <functional>
namespace UI::Page { namespace UI::Page {
class TabView;
class Tab : public Base { class Tab : public Base {
friend TabView;
public: public:
typedef std::unique_ptr<Tab> Ptr; typedef std::unique_ptr<Tab> Ptr;
@ -12,6 +15,9 @@ public:
void GiveContent(Page::Base::Ptr aContent); void GiveContent(Page::Base::Ptr aContent);
[[nodiscard]] Base::Ptr TakeContent(); [[nodiscard]] Base::Ptr TakeContent();
bool KeyEvent(KeyPressAbstract::KeyEvent aKeyEvent) override;
bool OnKeyEvent(KeyPressAbstract::KeyEvent aKeyEvent) override;
private: private:
Base::Ptr mContent; Base::Ptr mContent;
}; };
@ -25,6 +31,8 @@ public:
void SetCurrentTabIdx(uint16_t aTabToSetActive, void SetCurrentTabIdx(uint16_t aTabToSetActive,
lv_anim_enable_t aIsDoAnimation = LV_ANIM_ON); lv_anim_enable_t aIsDoAnimation = LV_ANIM_ON);
bool KeyEvent(KeyPressAbstract::KeyEvent aKeyEvent) override;
protected: protected:
void OnShow() {} void OnShow() {}
void OnHide() {} void OnHide() {}

View file

@ -19,3 +19,14 @@ void HomeScreen::SetBgColor(lv_color_t value, lv_style_selector_t selector) {
mTabView.SetBgColor(value, selector); mTabView.SetBgColor(value, selector);
UI::UIElement::SetBgColor(value, selector); UI::UIElement::SetBgColor(value, selector);
} }
bool HomeScreen::OnKeyEvent(KeyPressAbstract::KeyEvent aKeyEvent) {
return false;
};
bool HomeScreen::KeyEvent(KeyPressAbstract::KeyEvent aKeyEvent) {
if (OnKeyEvent(aKeyEvent)) {
return true;
}
return mTabView.KeyEvent(aKeyEvent);
};

View file

@ -12,6 +12,11 @@ public:
void SetBgColor(lv_color_t value, void SetBgColor(lv_color_t value,
lv_style_selector_t selector = LV_PART_MAIN) override; lv_style_selector_t selector = LV_PART_MAIN) override;
bool KeyEvent(KeyPressAbstract::KeyEvent aKeyEvent) override;
protected:
bool OnKeyEvent(KeyPressAbstract::KeyEvent aKeyEvent) override;
private: private:
Page::TabView mTabView; Page::TabView mTabView;
}; };

View file

@ -4,7 +4,6 @@ using namespace UI::Screen;
Base::Base(ID aId) : UIElement(lv_obj_create(NULL), aId) {} Base::Base(ID aId) : UIElement(lv_obj_create(NULL), aId) {}
void Base::Show() { void Base::Show() {
lv_scr_load_anim(LvglSelf(), mPushAnimation, 1000, 1000, false); lv_scr_load_anim(LvglSelf(), mPushAnimation, 1000, 1000, false);
UIElement::Show(); UIElement::Show();
@ -13,3 +12,5 @@ void Base::Show() {
void Base::SetPushAnimation(lv_scr_load_anim_t aShowAnimation) { void Base::SetPushAnimation(lv_scr_load_anim_t aShowAnimation) {
mPushAnimation = aShowAnimation; mPushAnimation = aShowAnimation;
} }
bool Base::OnKeyEvent(KeyPressAbstract::KeyEvent aKeyEvent) { return false; };

View file

@ -23,9 +23,7 @@ protected:
void Show() override; void Show() override;
void OnShow() override{}; void OnShow() override{};
void OnHide() override{}; void OnHide() override{};
bool OnKeyEvent(KeyPressAbstract::KeyEvent aKeyEvent) override { bool OnKeyEvent(KeyPressAbstract::KeyEvent aKeyEvent) override;
return false;
};
private: private:
lv_scr_load_anim_t mPushAnimation = LV_SCR_LOAD_ANIM_NONE; lv_scr_load_anim_t mPushAnimation = LV_SCR_LOAD_ANIM_NONE;

View file

@ -2,13 +2,22 @@
#include "UIElement.hpp" #include "UIElement.hpp"
#include <memory> #include <memory>
namespace UI::Page {
class Base;
}
namespace UI::Widget { namespace UI::Widget {
class Base : public UIElement { class Base : public UIElement {
friend class UI::Page::Base;
public: public:
typedef std::unique_ptr<Base> Ptr; typedef std::unique_ptr<Base> Ptr;
Base(lv_obj_t *aLvglSelf); Base(lv_obj_t *aLvglSelf);
virtual ~Base() override = default;
protected: protected:
void OnShow() override{}; void OnShow() override{};