diff --git a/src/containermenudefinition.h b/src/containermenudefinition.h index 37c6e55..1d1562c 100644 --- a/src/containermenudefinition.h +++ b/src/containermenudefinition.h @@ -42,9 +42,12 @@ public: } template - void constructItem(Args&&... args) + T &constructItem(Args&&... args) { - emplaceItem(std::make_unique(std::forward(args)...)); + auto ptr = std::make_unique(std::forward(args)...); + T &ref = *ptr; + emplaceItem(std::move(ptr)); + return ref; } void emplaceItem(std::unique_ptr &&ptr) @@ -57,6 +60,16 @@ public: m_items.clear(); } + std::unique_ptr takeLast() + { + if (m_items.empty()) + throw "aua"; + + std::unique_ptr ptr = std::move(m_items.back()); + m_items.pop_back(); + return ptr; + } + private: std::vector> m_items; }; diff --git a/src/displays/menus/wifiscanmenu.h b/src/displays/menus/wifiscanmenu.h index 78a264d..e441c16 100644 --- a/src/displays/menus/wifiscanmenu.h +++ b/src/displays/menus/wifiscanmenu.h @@ -1,14 +1,12 @@ #pragma once -// system includes -#include - // Arduino includes #include #include // local includes #include "menudisplay.h" +#include "containermenudefinition.h" #include "utils.h" #include "actions/multiaction.h" #include "actions/switchscreenaction.h" @@ -23,7 +21,7 @@ class WifiSettingsMenu; } // namespace namespace { -class WifiScanMenu : public MenuDisplay, public BackActionInterface> +class WifiScanMenu : public MenuDisplay, public BackActionInterface>, public ContainerMenuDefinition { using Base = MenuDisplay; @@ -34,55 +32,15 @@ public: void update() override; void stop() override; - std::size_t size() const override { return 1 + vec.size(); } - - MenuItem& getMenuItem(std::size_t index) override - { - if (index < vec.size()) - return vec[index]; - - if (index == vec.size()) - return m_backItem; - - throw "aua"; - } - - const MenuItem& getMenuItem(std::size_t index) const override - { - if (index < vec.size()) - return vec[index]; - - if (index == vec.size()) - return m_backItem; - - throw "aua"; - } - - void runForEveryMenuItem(std::function &&callback) override - { - for (auto &item : vec) - callback(item); - callback(m_backItem); - } - - void runForEveryMenuItem(std::function &&callback) const override - { - for (auto &item : vec) - callback(item); - callback(m_backItem); - } - private: - makeComponent, SwitchScreenAction, StaticMenuItemIcon<&icons::back>> m_backItem; - - std::vector> vec; - millis_t m_lastScanComplete; + + std::vector>> m_reusableItems; }; String WifiScanMenu::text() const { - auto text = String{vec.size()} + " found"; + auto text = String{size()-1} + " found"; switch (WiFi.scanComplete()) { case WIFI_SCAN_RUNNING: text += " (scanning)"; break; @@ -93,6 +51,8 @@ String WifiScanMenu::text() const void WifiScanMenu::start() { + constructItem, SwitchScreenAction, StaticMenuItemIcon<&icons::back>>>(); + Base::start(); m_lastScanComplete = 0; @@ -105,26 +65,40 @@ void WifiScanMenu::update() const auto n = WiFi.scanComplete(); if (n >= 0) { - if (n != vec.size()) - { - while (n > vec.size()) - { - vec.emplace_back(); - vec.back().start(); - } - - while (n < vec.size()) - { - vec.back().stop(); - vec.pop_back(); - } - } - const auto now = millis(); if (!m_lastScanComplete) { - for (auto iter = std::begin(vec); iter != std::end(vec); iter++) - iter->setTitle(WiFi.SSID(std::distance(std::begin(vec), iter))); + auto backButton = takeLast(); + + for (std::size_t i = 0; i < n; i++) + { + const auto ssid = WiFi.SSID(i); + if (size() <= i) + { + if (m_reusableItems.empty()) + { + auto &item = constructItem>(); + item.setTitle(ssid); + } + else + { + std::unique_ptr> ptr = std::move(m_reusableItems.back()); + m_reusableItems.pop_back(); + ptr->setTitle(ssid); + emplaceItem(std::move(ptr)); + } + } + else + { + auto &item = *(makeComponent*)(&getMenuItem(i)); + item.setTitle(ssid); + } + } + + while (size() > n) + m_reusableItems.emplace_back((makeComponent*)takeLast().release()); + + emplaceItem(std::move(backButton)); m_lastScanComplete = now; }