Move logic related to owning widgets into its own class to prepare for a widget type that can own other widgets.

This commit is contained in:
MatthewColvin 2023-10-10 15:43:36 -05:00 committed by Matthew Colvin
parent ddbfc13e55
commit 58787f5bf0
5 changed files with 101 additions and 77 deletions

View file

@ -0,0 +1,55 @@
#include "WidgetContainer.hpp"
using namespace UI;
WidgetContainer::WidgetContainer(lv_obj_t *aLvglSelf, ID aID)
: UIElement(aLvglSelf, aID) {}
UI::Widget::Base *WidgetContainer::AddWidget(Widget::Base::Ptr aWidget) {
AddElement(aWidget.get());
mWidgets.push_back(std::move(aWidget));
return mWidgets[mWidgets.size() - 1].get();
}
UI::Widget::Base::Ptr
WidgetContainer::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 WidgetContainer::KeyEvent(KeyPressAbstract::KeyEvent aKeyEvent) {
if (OnKeyEvent(aKeyEvent)) {
return true;
}
for (auto &widget : mWidgets) {
auto used = widget->KeyEvent(aKeyEvent);
if (used) {
return true;
}
}
return false;
};
void WidgetContainer::OnShow() {
for (auto &widget : mWidgets) {
if (widget->IsVisible()) {
widget->OnShow();
}
}
};
void WidgetContainer::OnHide() {
for (auto &widget : mWidgets) {
if (widget->IsVisible()) {
widget->OnHide();
}
}
};

View file

@ -0,0 +1,38 @@
#pragma once
#include "UIElement.hpp"
#include "WidgetBase.hpp"
namespace UI {
class WidgetContainer : public UIElement {
public:
WidgetContainer(lv_obj_t *aLvglSelf, ID aID);
template <class ElementTy> ElementTy *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(); }
protected:
/// @brief Forward To widgets that are visible
void OnShow() override;
/// @brief Forward To widgets that are visible
void OnHide() override;
/// @brief Pass Key Events to widgets until one is handled
/// TODO: consider an ability to have a selected widget be the first
/// one to get events.
bool KeyEvent(KeyPressAbstract::KeyEvent aKeyEvent) override;
private:
std::vector<Widget::Base::Ptr> mWidgets;
};
template <class ElementTy>
ElementTy *WidgetContainer::AddWidget(Widget::Base::Ptr aWidget) {
return static_cast<ElementTy *>(AddWidget(std::move(aWidget)));
}
} // namespace UI

View file

@ -6,58 +6,8 @@ using namespace UI::Page;
Base::Base(ID aID)
: Base(lv_obj_create(Screen::BackgroundScreen::getLvInstance()), aID) {}
Base::Base(lv_obj_t *aLvglSelf, ID aID) : UIElement(aLvglSelf, aID) {
Base::Base(lv_obj_t *aLvglSelf, ID aID) : WidgetContainer(aLvglSelf, aID) {
SetHeight(lv_pct(100));
SetWidth(lv_pct(100));
SetPadding(Padding()); // Set Padding to default
}
// Return non owning refrence to widget
UI::Widget::Base *Base::AddWidget(Widget::Base::Ptr aWidget) {
AddElement(aWidget.get());
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; };
void Base::OnShow() {
for (auto &widget : mWidgets) {
if (widget->IsVisible()) {
widget->OnShow();
}
}
};
void Base::OnHide() {
for (auto &widget : mWidgets) {
if (widget->IsVisible()) {
widget->OnHide();
}
}
};

View file

@ -1,6 +1,6 @@
#pragma once
#include "UIElement.hpp"
#include "WidgetBase.hpp"
#include "WidgetContainer.hpp"
#include <string>
#include <vector>
@ -10,7 +10,7 @@ class PopUpScreen;
namespace UI::Page {
class Tab;
class TabView;
class Base : public UIElement {
class Base : public WidgetContainer {
// Classes that Own Pages
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
@ -25,32 +25,13 @@ public:
Base(lv_obj_t *aLvglSelf, ID aID);
virtual ~Base() = default;
template <class ElementTy> ElementTy *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(); }
// Override to have a title associated with your page.
virtual std::string GetTitle() { return ""; };
protected:
/// @brief Forward To widgets that are visible
void OnShow() override;
/// @brief Forward To widgets that are visible
void OnHide() override;
bool KeyEvent(KeyPressAbstract::KeyEvent aKeyEvent) override;
bool OnKeyEvent(KeyPressAbstract::KeyEvent aKeyEvent) override;
bool OnKeyEvent(KeyPressAbstract::KeyEvent aKeyEvent) { return false; };
private:
std::vector<Widget::Base::Ptr> mWidgets;
};
template <class ElementTy>
ElementTy *Base::AddWidget(Widget::Base::Ptr aWidget) {
return static_cast<ElementTy *>(AddWidget(std::move(aWidget)));
}
} // namespace UI::Page

View file

@ -4,9 +4,9 @@
#include <memory>
namespace UI {
namespace Page {
class Base;
}
class WidgetContainer;
namespace Screen {
class PopUpScreen;
}
@ -16,7 +16,7 @@ namespace UI::Widget {
class Base : public UIElement {
// Classes that Own Widgets
friend class UI::Page::Base;
friend class UI::WidgetContainer;
friend class UI::Screen::PopUpScreen;
public: