convert Screen manager to use vector to allow popper of screen to use the Page.

Add ability to delay destruction of an object in LVGL after the core object has been destructed. This was added for animations to work .

make pop up Screen to allow for easy pushing of pages by wrapping it in a screen.

Use this all in the settings page to launch a fake display settings
This commit is contained in:
MatthewColvin 2023-10-08 12:32:59 -05:00
parent f9dd87fbe7
commit 7b7045f62b
8 changed files with 76 additions and 9 deletions

View file

@ -16,8 +16,8 @@ void Manager::pushScreen(Screen::Base::Ptr aScreen,
}
void Manager::pushScreen(Screen::Base::Ptr aScreen) {
mScreens.push(std::move(aScreen));
mScreens.top()->Show();
mScreens.push_back(std::move(aScreen));
mScreens.back()->Show();
}
void Manager::pushPopUp(Page::Base::Ptr aPopUpPage,
@ -26,7 +26,31 @@ void Manager::pushPopUp(Page::Base::Ptr aPopUpPage,
aPushAnimation);
}
UI::Screen::Base::Ptr Manager::popScreen(Screen::Base *aScreenToRemove) {
auto screenToPop = std::find_if(
mScreens.begin(), mScreens.end(), [aScreenToRemove](auto &screenInStack) {
return screenInStack.get() == aScreenToRemove;
});
bool isPopOffTopOfStack = mScreens.end() - 1 == screenToPop;
Screen::Base::Ptr retVal = nullptr;
if (screenToPop != mScreens.end()) {
retVal = std::move(*screenToPop);
mScreens.erase(screenToPop);
if (isPopOffTopOfStack) {
// Make sure to show correct top of stack
// since we popped the top screen off
mScreens.back()->Show();
}
}
// In order to make sure the Transition can complete
// flag the removed screen to stay alive in case it falls
// out of scope and gets deleted quickly after this.
retVal->SetKeepAliveTime(mScreens.back()->GetTransitionTime() + 500);
return retVal;
}
bool Manager::distributeKeyEvent(KeyPressAbstract::KeyEvent aKeyEvent) {
// Send Key Even to top Screen for handling
return mScreens.top()->KeyEvent(aKeyEvent);
return mScreens.back()->KeyEvent(aKeyEvent);
}

View file

@ -3,7 +3,7 @@
#include "PageBase.hpp"
#include "ScreenBase.hpp"
#include <memory>
#include <stack>
#include <vector>
namespace UI::Screen {
@ -19,13 +19,15 @@ public:
pushPopUp(UI::Page::Base::Ptr aPopUpPage,
lv_scr_load_anim_t aPushAnimation = LV_SCR_LOAD_ANIM_OVER_LEFT);
Screen::Base::Ptr popScreen(Screen::Base *aScreenToRemove);
bool distributeKeyEvent(KeyPressAbstract::KeyEvent aKeyEvent);
private:
Manager();
static Manager mManager;
std::stack<Screen::Base::Ptr> mScreens;
std::vector<Screen::Base::Ptr> mScreens;
};
} // namespace UI::Screen

View file

@ -14,8 +14,13 @@ UIElement::UIElement(lv_obj_t *aLvglSelf, ID aId)
UIElement::~UIElement() {
auto lock = LvglResourceManger::GetInstance().scopeLock();
if (lv_obj_is_valid(mLvglSelf)) {
lv_obj_del(mLvglSelf);
if (lv_obj_is_valid(LvglSelf())) {
if (mLvglKeepAliveTime > 0) {
lv_obj_del_delayed(LvglSelf(), mLvglKeepAliveTime);
} else {
lv_obj_del(LvglSelf());
}
lv_obj_remove_event_cb(mLvglSelf, UIElement::LvglEventHandler);
}
}

View file

@ -41,6 +41,15 @@ public:
template <class UIElemTy> static UIElemTy GetElement(lv_obj_t *aLvglObject);
/// @brief There are use cases in which objects
/// need to stay alive in LVGL but can die
/// in terms of our usage this is a helper for these
/// use Sparengly!!!
/// @param aTimeToKeepLvglObj
void SetKeepAliveTime(uint32_t aTimeToKeepLvglObj) {
mLvglKeepAliveTime = aTimeToKeepLvglObj;
}
protected:
/// @brief get Lvgl object refernce to use in LVGL APIs
/// @return lvgl object a
@ -71,6 +80,7 @@ private:
lv_obj_t *mLvglSelf;
const ID mId;
uint32_t mLvglKeepAliveTime = 0;
};
/**

View file

@ -1,12 +1,20 @@
#include "PopUpScreen.hpp"
#include "ScreenManager.hpp"
using namespace UI;
using namespace UI::Screen;
PopUpScreen::PopUpScreen(Page::Base::Ptr aPage)
: Screen::Base(UI::ID::Screens::PopUp), mContentPage(std::move(aPage)) {
: Screen::Base(UI::ID::Screens::PopUp), mContentPage(std::move(aPage)),
mExitButton(std::make_unique<Widget::Button>(
[this] { UI::Screen::Manager::getInstance().popScreen(this); })) {
mExitButton->SetWidth(30);
mExitButton->SetHeight(30);
mExitButton->SetBgColor(lv_color_make(255, 0, 0));
mExitButton->AlignTo(this, LV_ALIGN_TOP_RIGHT, -5, 5);
AddElement(mContentPage.get());
AddElement(mExitButton.get());
}
bool PopUpScreen::OnKeyEvent(KeyPressAbstract::KeyEvent aKeyEvent) {

View file

@ -1,6 +1,8 @@
#pragma once
#include "Button.hpp"
#include "PageBase.hpp"
#include "ScreenBase.hpp"
namespace UI::Screen {
/// @brief A Screen that allows easy display of a page that
@ -13,6 +15,7 @@ public:
private:
UI::Page::Base::Ptr mContentPage;
std::unique_ptr<Widget::Button> mExitButton;
};
} // namespace UI::Screen

View file

@ -5,7 +5,8 @@ using namespace UI::Screen;
Base::Base(ID aId) : UIElement(lv_obj_create(NULL), aId) {}
void Base::Show() {
lv_scr_load_anim(LvglSelf(), mPushAnimation, 1000, 1000, false);
lv_scr_load_anim(LvglSelf(), mPushAnimation, mTransitionAnimationTime,
mTransitionDelayTime, false);
UIElement::Show();
}
@ -13,4 +14,13 @@ void Base::SetPushAnimation(lv_scr_load_anim_t aShowAnimation) {
mPushAnimation = aShowAnimation;
}
uint32_t Base::GetTransitionTime() {
return mTransitionAnimationTime + mTransitionDelayTime;
}
void Base::SetTransitionTimes(uint32_t aAnimationTime, uint32_t aDelay) {
mTransitionAnimationTime = aAnimationTime;
mTransitionDelayTime = aDelay;
}
bool Base::OnKeyEvent(KeyPressAbstract::KeyEvent aKeyEvent) { return false; };

View file

@ -19,6 +19,9 @@ public:
void SetPushAnimation(lv_scr_load_anim_t aPushAnimation);
uint32_t GetTransitionTime();
void SetTransitionTimes(uint32_t aAnimationTime, uint32_t aDelay = 0);
protected:
void Show() override;
void OnShow() override{};
@ -27,6 +30,8 @@ protected:
private:
lv_scr_load_anim_t mPushAnimation = LV_SCR_LOAD_ANIM_NONE;
uint32_t mTransitionAnimationTime = 1000; // 1000 ms / 1 sec
uint32_t mTransitionDelayTime = 0;
};
} // namespace UI::Screen