Convert Lvgl resource manager to recursive mutex to allow re locking in thread.

This helps with creation and getting values and should be safe since it still keeps lvgl on  one thread at a time.

Add OnLvglEvent to UIElement that allows foreasy place for UI Elements  to respond to LVGL events .

Add button  class that can react to being presssed via a  callback function.

Add GetBottom() api to allow easy grabbing of bottom Y coordinate.

use some new stuff in the settings  page to sort test it all out.
This commit is contained in:
MatthewColvin 2023-10-06 22:11:15 -05:00
parent a11b78c540
commit 235d8e043f
8 changed files with 63 additions and 7 deletions

View file

@ -14,5 +14,5 @@ BasicUI::BasicUI(std::shared_ptr<HardwareAbstract> aHardware)
});
Screen::Manager::getInstance().pushScreen(
std::make_unique<Screen::HomeScreen>());
std::make_unique<Screen::HomeScreen>(aHardware));
}

View file

@ -16,7 +16,7 @@ public:
return mInstance;
}
[[nodiscard]] std::scoped_lock<std::mutex> scopeLock() {
[[nodiscard]] std::scoped_lock<std::recursive_mutex> scopeLock() {
return std::scoped_lock(mLvglMutex);
}
@ -45,5 +45,5 @@ protected:
}
std::queue<std::function<void()>> mLvglTasks;
std::mutex mLvglMutex;
std::recursive_mutex mLvglMutex;
};

View file

@ -6,6 +6,10 @@ UIElement::UIElement(lv_obj_t *aLvglSelf, ID aId)
: mLvglSelf(aLvglSelf), mId(aId) {
auto lock = LvglResourceManger::GetInstance().scopeLock();
mLvglSelf->user_data = this;
// Register Handler so that all object are able to override OnLvglEvent to
// handle events easilyOnLvEvent
lv_obj_add_event_cb(mLvglSelf, UIElement::LvglEventHandler, LV_EVENT_ALL,
this);
}
UIElement::~UIElement() {
@ -68,6 +72,8 @@ lv_coord_t UIElement::GetX() {
return lv_obj_get_x(mLvglSelf);
}
lv_coord_t UIElement::GetBottom() { return GetY() + GetHeight(); };
void UIElement::AlignTo(UIElement *anElementToAlignTo, lv_align_t anAlignment,
lv_coord_t aXoffset, lv_coord_t aYOffset) {
LvglResourceManger::GetInstance().AttemptNow([=] {
@ -114,4 +120,11 @@ bool UIElement::KeyEvent(KeyPressAbstract::KeyEvent aKeyEvent) {
return OnKeyEvent(aKeyEvent);
}
//////////////////// Statics //////////////////////////
void UIElement::LvglEventHandler(lv_event_t *anEvent) {
auto lock = LvglResourceManger::GetInstance().scopeLock();
reinterpret_cast<UIElement *>(anEvent->user_data)->OnLvglEvent(anEvent);
}
} // namespace UI

View file

@ -30,8 +30,9 @@ public:
lv_coord_t GetY();
lv_coord_t GetX();
lv_coord_t GetBottom();
void AlignTo(UIElement *anElementToAlignWith,lv_align_t anAlignment,
void AlignTo(UIElement *anElementToAlignWith, lv_align_t anAlignment,
lv_coord_t aXoffset = 0, lv_coord_t aYOffset = 0);
virtual void AddElement(UIElement *anElement);
@ -54,6 +55,9 @@ protected:
/// @brief Override in child class to run something after element is hidden
virtual void OnHide() = 0;
// Override in object to handle LVGL events for that object
virtual void OnLvglEvent(lv_event_t *anEvent){};
/// @brief Set KeyEvent to the UI element to see if it wants to handle it
virtual bool KeyEvent(KeyPressAbstract::KeyEvent aKeyEvent);
@ -63,6 +67,8 @@ protected:
virtual bool OnKeyEvent(KeyPressAbstract::KeyEvent aKeyEvent) = 0;
private:
static void LvglEventHandler(lv_event_t *anEvent);
lv_obj_t *mLvglSelf;
const ID mId;
};

View file

@ -1,11 +1,18 @@
#include "SettingsPage.hpp"
#include "BackgroundScreen.hpp"
#include "Button.hpp"
using namespace UI::Page;
SettingsPage::SettingsPage(std::shared_ptr<HardwareAbstract> aHardware)
: Base(ID::Pages::Settings), mHardware(aHardware) {
SetBgColor(lv_color_make(255, 0, 0));
auto button = std::make_unique<UI::Widget::Button>([this] { AddSlider(); });
button->SetY(0);
button->SetHeight(lv_pct(10));
button->SetWidth(lv_pct(10));
mButton = AddWidget(std::move(button));
}
void SettingsPage::OnShow() {}
@ -16,7 +23,7 @@ void SettingsPage::AddSlider() {
fakeSlider->SetHeight(lv_pct(10));
fakeSlider->SetWidth(GetWidth());
if (sliders.empty()) {
fakeSlider->SetY(0);
fakeSlider->SetY(mButton->GetBottom());
} else {
auto nextY = sliders.back()->GetY() + sliders.back()->GetHeight();
fakeSlider->SetY(nextY + 10);
@ -50,7 +57,7 @@ bool SettingsPage::OnKeyEvent(KeyPressAbstract::KeyEvent aKeyEvent) {
case id::Aux4:
break;
default:
used = false;
used = Page::Base::OnKeyEvent(aKeyEvent);
break;
}
return used;

View file

@ -14,6 +14,7 @@ protected:
void OnShow() override;
std::vector<Widget::Base *> sliders;
Widget::Base *mButton;
std::shared_ptr<HardwareAbstract> mHardware;
};
} // namespace UI::Page

View file

@ -0,0 +1,14 @@
#include "Button.hpp"
#include "BackgroundScreen.hpp"
using namespace UI::Widget;
Button::Button(std::function<void()> aOnPressHandler)
: Base(lv_btn_create(UI::Screen::BackgroundScreen::getLvInstance())),
mOnPress(aOnPressHandler) {}
void Button::OnLvglEvent(lv_event_t *anEvent) {
if (anEvent->code == LV_EVENT_PRESSED) {
mOnPress();
}
};

View file

@ -0,0 +1,15 @@
#pragma once
#include "WidgetBase.hpp"
namespace UI::Widget {
class Button : public Base {
public:
Button(std::function<void()> aOnPressHandler);
void OnLvglEvent(lv_event_t *anEvent) override;
private:
std::function<void()> mOnPress;
};
} // namespace UI::Widget