diff --git a/Platformio/OmoteUI/UIs/BasicRefactored/page/WifiSettings.cpp b/Platformio/OmoteUI/UIs/BasicRefactored/page/WifiSettings.cpp index 6018bf0..0295276 100644 --- a/Platformio/OmoteUI/UIs/BasicRefactored/page/WifiSettings.cpp +++ b/Platformio/OmoteUI/UIs/BasicRefactored/page/WifiSettings.cpp @@ -1,8 +1,8 @@ #include "WifiSettings.hpp" +#include "Keyboard.hpp" #include "Label.hpp" #include "List.hpp" #include "LvglResourceManager.hpp" -//#include using namespace UI; using namespace UI::Page; @@ -12,22 +12,36 @@ WifiSettings::WifiSettings(std::shared_ptr aWifi) mScanCompleteHandler(mWifi->ScanCompleteNotification()), mScanningText(AddElement( std::make_unique("Scanning..."))), - mWifiNetworks( - AddElement(std::make_unique())) { - + mWifiNetworks(AddElement(std::make_unique())), + mPasswordGetter(nullptr) { + // Set Handler for when the wifi scan is done mScanCompleteHandler = [this](auto aWifiInfos) { - // Serial.println("populating UI"); mScanningText->SetText("Networks Found"); + // Create List of wifi infos for (WifiInfo wifiInfo : aWifiInfos) { - mWifiNetworks->AddItem(wifiInfo.ssid, LV_SYMBOL_WIFI, [] {}); + mWifiNetworks->AddItem(wifiInfo.ssid, LV_SYMBOL_WIFI, [this, wifiInfo] { + if (!mPasswordGetter) { + // Launch a Keyboard if we dont already have one when user selects + // list item + auto keyboard = std::make_unique( + [this, wifiInfo](auto aUserEnteredPassword) { + // Attempt Connection when user finishes up with keyboard input + mWifi->connect(wifiInfo.ssid, aUserEnteredPassword); + mPasswordGetter->AnimateOut(); + }); + keyboard->OnKeyboardAnimatedOut([this] { + // Once keyboard is done animating out remove it and null the ref to + // it. + RemoveElement(mPasswordGetter); + mPasswordGetter = nullptr; + }); + mPasswordGetter = AddElement(std::move(keyboard)); + } + }); } }; mWifi->scan(); - - // mWifi->onScanDone([this](auto aWifiInfos) { - // - // }); } void WifiSettings::SetHeight(lv_coord_t aHeight) { diff --git a/Platformio/OmoteUI/UIs/BasicRefactored/page/WifiSettings.hpp b/Platformio/OmoteUI/UIs/BasicRefactored/page/WifiSettings.hpp index 521c68e..3a1e2dc 100644 --- a/Platformio/OmoteUI/UIs/BasicRefactored/page/WifiSettings.hpp +++ b/Platformio/OmoteUI/UIs/BasicRefactored/page/WifiSettings.hpp @@ -5,6 +5,7 @@ namespace UI::Widget { class List; class Label; +class Keyboard; } // namespace UI::Widget namespace UI::Page { @@ -22,6 +23,7 @@ private: UI::Widget::Label *mScanningText; UI::Widget::List *mWifiNetworks; + UI::Widget::Keyboard *mPasswordGetter; }; } // namespace UI::Page \ No newline at end of file diff --git a/Platformio/OmoteUI/core/Animation.cpp b/Platformio/OmoteUI/core/Animation.cpp index 101b966..03a1b87 100644 --- a/Platformio/OmoteUI/core/Animation.cpp +++ b/Platformio/OmoteUI/core/Animation.cpp @@ -4,21 +4,37 @@ using namespace UI; Animation::Animation(std::function aAnimator, int32_t aAnimationTime, int32_t aStart, int32_t aEnd) - : mAnimator(aAnimator) { + : mAnimator(aAnimator), mStart(aStart), mEnd(aEnd) { lv_anim_init(&mAnimation); mAnimation.user_data = this; lv_anim_set_custom_exec_cb(&mAnimation, AnimatorImpl); - lv_anim_set_values(&mAnimation, aStart, aEnd); lv_anim_set_time(&mAnimation, aAnimationTime); } Animation::~Animation() { lv_anim_custom_del(&mAnimation, AnimatorImpl); } -void Animation::Start() { lv_anim_start(&mAnimation); } +void Animation::HandleAnimationComplete( + std::function onAnimationComplete) { + mOnComplete = onAnimationComplete; +} + +void Animation::Start() { + lv_anim_set_values(&mAnimation, mStart, mEnd); + lv_anim_start(&mAnimation); +} + +void Animation::Reverse() { + std::swap(mStart, mEnd); + Start(); +} //////////////////////// Statics ///////////////////////////////////////// void Animation::AnimatorImpl(lv_anim_t *aSelf, int32_t aNextValue) { auto self = reinterpret_cast(aSelf->user_data); self->mAnimator(aNextValue); + // TODO This probably will not support Overshoot animations. + if (self->mOnComplete && aNextValue == self->mEnd) { + self->mOnComplete(); + } } \ No newline at end of file diff --git a/Platformio/OmoteUI/core/Animation.hpp b/Platformio/OmoteUI/core/Animation.hpp index 1671f48..1bfa9cb 100644 --- a/Platformio/OmoteUI/core/Animation.hpp +++ b/Platformio/OmoteUI/core/Animation.hpp @@ -11,11 +11,19 @@ public: virtual ~Animation(); + void HandleAnimationComplete(std::function onAnimationComplete); + void Start(); + void Reverse(); private: lv_anim_t mAnimation; std::function mAnimator = nullptr; + std::function mOnComplete = nullptr; + bool onCompleteCalled = false; + + int32_t mStart = 0; + int32_t mEnd = 0; static void AnimatorImpl(lv_anim_t *aSelf, int32_t aNextValue); }; diff --git a/Platformio/OmoteUI/core/UIElementIds.hpp b/Platformio/OmoteUI/core/UIElementIds.hpp index acf8bef..914a20e 100644 --- a/Platformio/OmoteUI/core/UIElementIds.hpp +++ b/Platformio/OmoteUI/core/UIElementIds.hpp @@ -19,6 +19,7 @@ public: Label, List, DropDown, + Keyboard, BrightnessSlider, INVALID_WIDGET_ID }; diff --git a/Platformio/OmoteUI/core/widget/Keyboard.cpp b/Platformio/OmoteUI/core/widget/Keyboard.cpp new file mode 100644 index 0000000..35e059a --- /dev/null +++ b/Platformio/OmoteUI/core/widget/Keyboard.cpp @@ -0,0 +1,53 @@ +#include "Keyboard.hpp" +#include "BackgroundScreen.hpp" +#include + +using namespace UI; +using namespace UI::Widget; + +Keyboard::Keyboard(std::function aOnUserCompletedTextEntry) + : Base(ID::Widgets::Keyboard), + mKeyboard(AddElement(std::make_unique( + lv_keyboard_create(LvglSelf()), ID::Widgets::INVALID_WIDGET_ID))), + mTextArea(AddElement(std::make_unique( + lv_textarea_create(LvglSelf()), ID::Widgets::INVALID_WIDGET_ID))), + mOnUserCompleteTextEntry(aOnUserCompletedTextEntry) { + lv_keyboard_set_textarea(mKeyboard->LvglSelf(), mTextArea->LvglSelf()); + + mKeyboard->HandleLvglEvent([this](auto aEvent) { + if (aEvent->code == LV_EVENT_READY) { + std::string userEnteredText = + std::string(lv_textarea_get_text(mTextArea->LvglSelf())); + mOnUserCompleteTextEntry(userEnteredText); + } + }); +} + +void Keyboard::OnAdded(UIElement *aNewParent) { + auto selfHeight = ceil(aNewParent->GetContentHeight() * 0.60f); + // Align to final position and get Y for end of animation + SetHeight(selfHeight); + AlignTo(aNewParent, LV_ALIGN_BOTTOM_MID); + auto endAnimationY = GetY(); + auto startAnimationY = aNewParent->GetBottom(); + + mAnimateIn = std::make_unique([this](auto aY) { SetY(aY); }, 500, + startAnimationY, endAnimationY); + mAnimateIn->Start(); +} + +void Keyboard::AnimateOut() { + if (mOnKeyboardAnimatedOut) { + mAnimateIn->HandleAnimationComplete(mOnKeyboardAnimatedOut); + } + mAnimateIn->Reverse(); +}; + +void Keyboard::SetHeight(lv_coord_t aHeight) { + Base::SetHeight(aHeight); + auto txtAreaHight = 33; + mTextArea->SetHeight(txtAreaHight); + mKeyboard->SetHeight(GetContentHeight() - txtAreaHight); + mTextArea->AlignTo(this, LV_ALIGN_TOP_MID); + mKeyboard->AlignTo(mTextArea, LV_ALIGN_OUT_BOTTOM_MID); +} diff --git a/Platformio/OmoteUI/core/widget/Keyboard.hpp b/Platformio/OmoteUI/core/widget/Keyboard.hpp new file mode 100644 index 0000000..2296901 --- /dev/null +++ b/Platformio/OmoteUI/core/widget/Keyboard.hpp @@ -0,0 +1,31 @@ +#pragma once +#include "Animation.hpp" +#include "WidgetBase.hpp" +#include +#include + +namespace UI::Widget { + +class Keyboard : public Base { +public: + Keyboard(std::function aOnUserCompletedTextEntry); + + void OnAdded(UIElement *aNewParent) override; + + void SetHeight(lv_coord_t aHeight) override; + + void AnimateOut(); + void OnKeyboardAnimatedOut(std::function aOnKeyboardAnimatedOut) { + mOnKeyboardAnimatedOut = aOnKeyboardAnimatedOut; + } + +private: + std::function mOnKeyboardAnimatedOut; + std::function mOnUserCompleteTextEntry; + std::unique_ptr mAnimateIn; + + Base *mKeyboard; + Base *mTextArea; +}; + +} // namespace UI::Widget \ No newline at end of file