From 8a4a1b1b38655f99762193d62e4f56fe13e3d7b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20B=C3=A1ny=C3=A1sz?= <36520141+banyaszg@users.noreply.github.com> Date: Wed, 12 Oct 2022 05:05:18 +0200 Subject: [PATCH] Speed up the initial menu filling (#77) * Preset menu line counter. Disable update position during the fill. * Code formating * Redesign attempt with addLines() functions. * . * Menu::addLines fix for icons. * Redesign to clean up * Selection fix. Choice implementation. * One more redesign. --- radio/src/thirdparty/libopenui/src/choice.cpp | 11 +++-- .../thirdparty/libopenui/src/filechoice.cpp | 3 +- radio/src/thirdparty/libopenui/src/menu.cpp | 48 +++++++++++++++---- radio/src/thirdparty/libopenui/src/menu.h | 21 ++++++-- 4 files changed, 66 insertions(+), 17 deletions(-) diff --git a/radio/src/thirdparty/libopenui/src/choice.cpp b/radio/src/thirdparty/libopenui/src/choice.cpp index 6c72a91b7..e5e24d317 100644 --- a/radio/src/thirdparty/libopenui/src/choice.cpp +++ b/radio/src/thirdparty/libopenui/src/choice.cpp @@ -210,19 +210,22 @@ void Choice::fillMenu(Menu *menu, const FilterFct& filter) auto value = _getValue(); int count = 0; + int selectedIx = -1; for (int i = vmin; i <= vmax; ++i) { if (filter && !filter(i)) continue; if (isValueAvailable && !isValueAvailable(i)) continue; if (textHandler) { - menu->addLine(textHandler(i), [=]() { setValue(i); }); + menu->addLineBuffered(textHandler(i), [=]() { setValue(i); }); } else if (unsigned(i - vmin) < values.size()) { - menu->addLine(values[i - vmin], [=]() { setValue(i); }); + menu->addLineBuffered(values[i - vmin], [=]() { setValue(i); }); } else { - menu->addLine(std::to_string(i), [=]() { setValue(i); }); + menu->addLineBuffered(std::to_string(i), [=]() { setValue(i); }); } - if (value == i) { menu->select(count); } + if (value == i) { selectedIx = count; } ++count; } + menu->updateLines(); + if (selectedIx >= 0) { menu->select(selectedIx); } } void Choice::openMenu() diff --git a/radio/src/thirdparty/libopenui/src/filechoice.cpp b/radio/src/thirdparty/libopenui/src/filechoice.cpp index ea5506bf5..223ea2614 100644 --- a/radio/src/thirdparty/libopenui/src/filechoice.cpp +++ b/radio/src/thirdparty/libopenui/src/filechoice.cpp @@ -101,7 +101,7 @@ bool FileChoice::openMenu() int current = -1; std::string value = getValue(); for (const auto &file : files) { - menu->addLine(file, [=]() { + menu->addLineBuffered(file, [=]() { setValue(file); lv_event_send(lvobj, LV_EVENT_VALUE_CHANGED, nullptr); }); @@ -113,6 +113,7 @@ bool FileChoice::openMenu() } ++count; } + menu->updateLines(); if (current >= 0) { menu->select(current); diff --git a/radio/src/thirdparty/libopenui/src/menu.cpp b/radio/src/thirdparty/libopenui/src/menu.cpp index 5e681357a..48ed53f8e 100644 --- a/radio/src/thirdparty/libopenui/src/menu.cpp +++ b/radio/src/thirdparty/libopenui/src/menu.cpp @@ -98,28 +98,41 @@ MenuBody::MenuBody(Window * parent, const rect_t & rect): } void MenuBody::addLine(const std::string &text, std::function onPress, - std::function isChecked) + std::function isChecked, bool update) { - lines.emplace_back(std::move(onPress), std::move(isChecked), nullptr); + lines.emplace_back(text, std::move(onPress), std::move(isChecked), nullptr); - auto idx = lines.size() - 1; - lv_table_set_cell_value(lvobj, idx, 0, text.c_str()); + if (update) { + auto idx = lines.size() - 1; + lv_table_set_cell_value(lvobj, idx, 0, text.c_str()); + } } void MenuBody::addLine(const uint8_t *icon_mask, const std::string &text, std::function onPress, - std::function isChecked) + std::function isChecked, + bool update) { lv_obj_t* canvas = lv_canvas_create(nullptr); - lines.emplace_back(std::move(onPress), std::move(isChecked), canvas); + lines.emplace_back(text, std::move(onPress), std::move(isChecked), canvas); lv_coord_t w = *((uint16_t *)icon_mask); lv_coord_t h = *(((uint16_t *)icon_mask)+1); void* buf = (void*)(icon_mask + 4); lv_canvas_set_buffer(canvas, buf, w, h, LV_IMG_CF_ALPHA_8BIT); - auto idx = lines.size() - 1; - lv_table_set_cell_value_fmt(lvobj, idx, 0, text.c_str()); + if (update) { + auto idx = lines.size() - 1; + lv_table_set_cell_value_fmt(lvobj, idx, 0, text.c_str()); + } +} + +void MenuBody::updateLines() +{ + setRowCount(lines.size()); + for(unsigned int idx = 0; idx < lines.size(); idx++) { + lv_table_set_cell_value_fmt(lvobj, idx, 0, lines[idx].text.c_str()); + } } void MenuBody::removeLines() @@ -327,6 +340,25 @@ void Menu::addLine(const uint8_t *icon_mask, const std::string &text, updatePosition(); } +void Menu::addLineBuffered(const std::string &text, std::function onPress, + std::function isChecked) +{ + content->body.addLine(text, std::move(onPress), std::move(isChecked), false); +} + +void Menu::addLineBuffered(const uint8_t *icon_mask, const std::string &text, + std::function onPress, + std::function isChecked) +{ + content->body.addLine(icon_mask, text, std::move(onPress), std::move(isChecked), false); +} + +void Menu::updateLines() +{ + content->body.updateLines(); + updatePosition(); +} + void Menu::removeLines() { content->body.removeLines(); diff --git a/radio/src/thirdparty/libopenui/src/menu.h b/radio/src/thirdparty/libopenui/src/menu.h index c724f54fe..13a4c784a 100644 --- a/radio/src/thirdparty/libopenui/src/menu.h +++ b/radio/src/thirdparty/libopenui/src/menu.h @@ -53,9 +53,9 @@ class MenuBody: public TableField friend class MenuBody; public: - MenuLine(std::function onPress, std::function isChecked, + MenuLine(const std::string& text, std::function onPress, std::function isChecked, lv_obj_t *icon) : - onPress(std::move(onPress)), isChecked(std::move(isChecked)), icon(icon) + text(text), onPress(std::move(onPress)), isChecked(std::move(isChecked)), icon(icon) { } @@ -65,6 +65,7 @@ class MenuBody: public TableField lv_obj_t* getIcon() { return icon.get(); } protected: + std::string text; std::function onPress; std::function isChecked; std::unique_ptr icon; @@ -96,11 +97,14 @@ class MenuBody: public TableField void onCancel() override; void addLine(const std::string &text, std::function onPress, - std::function isChecked); + std::function isChecked, bool update = true); void addLine(const uint8_t *icon_mask, const std::string &text, std::function onPress, - std::function isChecked); + std::function isChecked, + bool update = true); + + void updateLines(); void removeLines(); @@ -185,6 +189,15 @@ class Menu: public ModalWindow std::function onPress, std::function isChecked = nullptr); + void addLineBuffered(const std::string &text, std::function onPress, + std::function isChecked = nullptr); + + void addLineBuffered(const uint8_t *icon_mask, const std::string &text, + std::function onPress, + std::function isChecked = nullptr); + + void updateLines(); + void addSeparator(); void removeLines();