Add start stop event handling in UIElement

Add demo page to get play logic out of settings page.

Add a demo page and a Settings page to the home screen.
This commit is contained in:
Matthew Colvin 2023-10-12 15:20:38 -05:00
parent 0a397706af
commit 7d68cce6ad
10 changed files with 171 additions and 61 deletions

View file

@ -0,0 +1,54 @@
#include "Demo.hpp"
#include "Slider.hpp"
using namespace UI::Page;
Demo::Demo(std::shared_ptr<HardwareAbstract> aHardware): Base(ID::Pages::Demo), mHardware(aHardware){
}
void Demo::AddSlider() {
auto fakeSlider = std::make_unique<Widget::Slider>([](auto data){});
fakeSlider->SetHeight(lv_pct(10));
fakeSlider->SetWidth(GetContentWidth());
if (sliders.empty()) {
fakeSlider->AlignTo(this,LV_ALIGN_TOP_MID);
} else {
auto nextY = sliders.back()->GetY() + sliders.back()->GetHeight();
fakeSlider->SetY(nextY + 10);
}
sliders.push_back(AddElement(std::move(fakeSlider)));
}
bool Demo::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) {
RemoveElement(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 = Page::Base::OnKeyEvent(aKeyEvent);
break;
}
return used;
}

View file

@ -0,0 +1,22 @@
#pragma once
#include "PageBase.hpp"
#include "HardwareAbstract.hpp"
namespace UI::Page{
class Demo : public Base{
public:
Demo(std::shared_ptr<HardwareAbstract> aHardware);
void AddSlider();
void OnShow()override{};
void OnHide()override{};
bool OnKeyEvent(KeyPressAbstract::KeyEvent aKeyEvent);
private:
std::shared_ptr<HardwareAbstract> mHardware;
std::vector<UIElement *> sliders;
};
}

View file

@ -2,6 +2,7 @@
#include "BackgroundScreen.hpp" #include "BackgroundScreen.hpp"
#include "Button.hpp" #include "Button.hpp"
#include "Slider.hpp" #include "Slider.hpp"
#include "List.hpp"
#include "Colors.hpp" #include "Colors.hpp"
#include "DisplaySettings.hpp" #include "DisplaySettings.hpp"
#include "PopUpScreen.hpp" #include "PopUpScreen.hpp"
@ -11,66 +12,16 @@ using namespace UI::Page;
using namespace UI::Color; using namespace UI::Color;
SettingsPage::SettingsPage(std::shared_ptr<HardwareAbstract> aHardware) SettingsPage::SettingsPage(std::shared_ptr<HardwareAbstract> aHardware)
: Base(ID::Pages::Settings), mHardware(aHardware) { : Base(ID::Pages::Settings),
SetBgColor(RED); mSettingsList(AddElement<Widget::List>(std::make_unique<Widget::List>())),
auto button = mHardware(aHardware) {
std::make_unique<UI::Widget::Button>([this] { PushDisplaySettings(); });
button->SetBorder(button->GetBorder().Color(BLUE).Width(2));
button->SetY(0);
button->SetHeight(lv_pct(10));
button->SetWidth(lv_pct(10));
mButton = AddElement<Widget::Button>(std::move(button)); mSettingsList->AddItem("Display",LV_SYMBOL_EYE_OPEN,[this] { PushDisplaySettings(); });
mSettingsList->AddItem("Wifi",LV_SYMBOL_WIFI,[]{});
} }
void SettingsPage::OnShow() {}
void SettingsPage::PushDisplaySettings() { void SettingsPage::PushDisplaySettings() {
UI::Screen::Manager::getInstance().pushPopUp( UI::Screen::Manager::getInstance().pushPopUp(
std::make_unique<DisplaySettings>(mHardware->display())); std::make_unique<DisplaySettings>(mHardware->display()));
} }
void SettingsPage::AddSlider() {
auto fakeSlider = std::make_unique<Widget::Slider>([](auto data){});
fakeSlider->SetHeight(lv_pct(10));
fakeSlider->SetWidth(GetContentWidth());
if (sliders.empty()) {
fakeSlider->SetY(mButton->GetBottom());
} else {
auto nextY = sliders.back()->GetY() + sliders.back()->GetHeight();
fakeSlider->SetY(nextY + 10);
}
sliders.push_back(AddElement(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) {
RemoveElement(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 = Page::Base::OnKeyEvent(aKeyEvent);
break;
}
return used;
}

View file

@ -3,23 +3,23 @@
namespace UI::Widget{ namespace UI::Widget{
class Button; class Button;
class List;
} }
namespace UI::Page { namespace UI::Page {
class SettingsPage : public Base { class SettingsPage : public Base {
public: public:
SettingsPage(std::shared_ptr<HardwareAbstract> aHardware = nullptr); SettingsPage(std::shared_ptr<HardwareAbstract> aHardware = nullptr);
bool OnKeyEvent(KeyPressAbstract::KeyEvent aKeyEvent) override; bool OnKeyEvent(KeyPressAbstract::KeyEvent aKeyEvent) override{return false;};
void AddSlider();
void PushDisplaySettings(); void PushDisplaySettings();
protected: protected:
void OnShow() override; void OnShow() override{};
void OnHide() override{}; void OnHide() override{};
std::vector<UIElement *> sliders;
Widget::Button *mButton; Widget::Button *mButton;
Widget::List *mSettingsList;
std::shared_ptr<HardwareAbstract> mHardware; std::shared_ptr<HardwareAbstract> mHardware;
}; };
} // namespace UI::Page } // namespace UI::Page

View file

@ -1,6 +1,7 @@
#include "HomeScreen.hpp" #include "HomeScreen.hpp"
#include "Colors.hpp" #include "Colors.hpp"
#include "SettingsPage.hpp" #include "SettingsPage.hpp"
#include "Demo.hpp"
using namespace UI::Screen; using namespace UI::Screen;
@ -15,7 +16,7 @@ HomeScreen::HomeScreen(std::shared_ptr<HardwareAbstract> aHardware)
// Adds pages to the Tab view // Adds pages to the Tab view
mTabView->AddTab(std::make_unique<Page::SettingsPage>(aHardware)); mTabView->AddTab(std::make_unique<Page::SettingsPage>(aHardware));
mTabView->AddTab(std::make_unique<Page::SettingsPage>(aHardware)); mTabView->AddTab(std::make_unique<Page::Demo>(aHardware));
} }
void HomeScreen::SetBgColor(lv_color_t value, lv_style_selector_t selector) { void HomeScreen::SetBgColor(lv_color_t value, lv_style_selector_t selector) {

View file

@ -249,6 +249,19 @@ void UIElement::SetBgOpacity(lv_opa_t aOpacity, lv_style_selector_t aStyle) {
}); });
} }
void UIElement::StartLvglEventHandler(){
if(mIsHandlingLvglEvents){ return; }
lv_obj_add_event_cb(mLvglSelf, UIElement::LvglEventHandler, LV_EVENT_ALL,
this);
mIsHandlingLvglEvents = true;
}
void UIElement::StopLvglEventHandler(){
if(!mIsHandlingLvglEvents){return;}
lv_obj_remove_event_cb_with_user_data(mLvglSelf,UIElement::LvglEventHandler,
this);
mIsHandlingLvglEvents = false;
}
void UIElement::Show() { void UIElement::Show() {
if (IsVisible()) { if (IsVisible()) {
return; return;

View file

@ -81,12 +81,16 @@ public:
/// @brief There are use cases in which objects /// @brief There are use cases in which objects
/// need to stay alive in LVGL but can die /// need to stay alive in LVGL but can die
/// in terms of our usage this is a helper for these /// in terms of our usage this is a helper for these
/// use Sparengly!!! /// use Sparingly!!!
/// @param aTimeToKeepLvglObj /// @param aTimeToKeepLvglObj
void SetKeepAliveTime(uint32_t aTimeToKeepLvglObj) { void SetKeepAliveTime(uint32_t aTimeToKeepLvglObj) {
mLvglKeepAliveTime = aTimeToKeepLvglObj; mLvglKeepAliveTime = aTimeToKeepLvglObj;
} }
void StartLvglEventHandler();
void StopLvglEventHandler();
protected: protected:
/// @brief get Lvgl object refernce to use in LVGL APIs /// @brief get Lvgl object refernce to use in LVGL APIs
/// @return lvgl object a /// @return lvgl object a
@ -118,6 +122,7 @@ private:
lv_obj_t *mLvglSelf; lv_obj_t *mLvglSelf;
const ID mId; const ID mId;
uint32_t mLvglKeepAliveTime = 0; uint32_t mLvglKeepAliveTime = 0;
bool mIsHandlingLvglEvents = true;
/// @brief Elements that are currently in this element /// @brief Elements that are currently in this element
std::vector<UIElement::Ptr> mContainedElements; std::vector<UIElement::Ptr> mContainedElements;

View file

@ -17,6 +17,7 @@ public:
Slider = static_cast<int>(Screens::INVALID_SCREEN_ID) + 1, Slider = static_cast<int>(Screens::INVALID_SCREEN_ID) + 1,
Button, Button,
Label, Label,
List,
BrightnessSlider, BrightnessSlider,
INVALID_WIDGET_ID INVALID_WIDGET_ID
}; };
@ -24,6 +25,7 @@ public:
enum class Pages { enum class Pages {
Settings = static_cast<int>(Widgets::INVALID_WIDGET_ID) + 1, Settings = static_cast<int>(Widgets::INVALID_WIDGET_ID) + 1,
DisplaySettings, DisplaySettings,
Demo,
INVALID_PAGE_ID INVALID_PAGE_ID
}; };

View file

@ -0,0 +1,32 @@
#include "List.hpp"
#include "BackgroundScreen.hpp"
using namespace UI;
using namespace UI::Widget;
ListItem::ListItem(lv_obj_t *aListItem, std::function<void()> onItemSelected):
UIElement(aListItem,ID()),
mSelectedHandler(std::move(onItemSelected)){}
void ListItem::OnLvglEvent(lv_event_t* anEvent){
if(anEvent->code == LV_EVENT_CLICKED){
if(mSelectedHandler){
mSelectedHandler();
}
}
}
List::List():Base(lv_list_create(Screen::BackgroundScreen::getLvInstance()),ID::Widgets::List){
StopLvglEventHandler();
}
void List::AddItem(std::string aTitle, const char* aSymbol, std::function<void()> onItemSelected){
auto lvListItem = lv_list_add_btn(LvglSelf(),aSymbol,aTitle.c_str());
mListItems.push_back(std::make_unique<ListItem>(lvListItem, std::move(onItemSelected)));
mListItems.back()->SetHeight(lv_pct(20));
}
void List::OnLvglEvent(lv_event_t* anEvent){
if(anEvent->code == LV_EVENT_CLICKED){
auto tgt = anEvent->target;
}
}

View file

@ -0,0 +1,30 @@
#pragma once
#include "WidgetBase.hpp"
namespace UI::Widget{
class ListItem : public UIElement{
public:
ListItem(lv_obj_t* aListItem, std::function<void()> onItemSelected);
protected:
void OnLvglEvent(lv_event_t* anEvent) override;
bool OnKeyEvent(KeyPressAbstract::KeyEvent anEvent)override{return false;};
void OnShow()override{};
void OnHide()override{};
private:
std::function<void()> mSelectedHandler;
};
class List : public Base{
public:
List();
void AddItem(std::string aTitle, const char* aSymbol, std::function<void()> onItemSelected);
protected:
void OnLvglEvent(lv_event_t* anEvent)override;
private:
std::vector<UIElement::Ptr> mListItems;
};
}