/* * SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD * * SPDX-License-Identifier: MIT */ #include "view.h" #include #include #include #include #include #include using namespace view; using namespace uitk; using namespace uitk::lvgl_cpp; /* -------------------------------------------------------------------------- */ /* Dynamic backgroud color handle class */ /* -------------------------------------------------------------------------- */ class DynamicBgColor { public: std::function onBgColorChanged; void init(const std::vector& stepColors, int stepGap) { _step_colors = stepColors; _step_gap = stepGap; _bg_color.duration = 0.3; _bg_color.begin(); jumpTo(0); } void jumpTo(int index) { if (index < 0 || index >= _step_colors.size()) { return; } _bg_color.teleport(_step_colors[index]); _current_index = index; if (onBgColorChanged) { onBgColorChanged(_step_colors[index]); } } void update(int scrollValue) { _last_index = _current_index; // Update current index _current_index = (scrollValue + _step_gap / 2) / _step_gap; if (_current_index < 0) { _current_index = 0; } if (_current_index >= _step_colors.size()) { _current_index = _step_colors.size() - 1; } // If index changed if (_last_index != _current_index) { // mclog::tagInfo(_tag, "index changed from {} to {}", _last_index, _current_index); _bg_color = _step_colors[_current_index]; } // Update background color _bg_color.update(); if (!_bg_color.done()) { if (onBgColorChanged) { onBgColorChanged(_bg_color.toHex()); } } } private: std::vector _step_colors; int _current_index = 0; int _last_index = 0; int _step_gap = 0; color::AnimateRgb_t _bg_color; }; /* -------------------------------------------------------------------------- */ /* Page indicator */ /* -------------------------------------------------------------------------- */ class PageIndicator { public: const int dot_size = 8; const int dot_size_big = 14; const int dot_gap = 16; void init(int pageNum, int pageGap, lv_obj_t* parent, int posX, int posY) { _page_num = pageNum; _page_gap = pageGap; _panel = std::make_unique(parent); _panel->removeFlag(LV_OBJ_FLAG_SCROLLABLE); _panel->addFlag(LV_OBJ_FLAG_FLOATING); _panel->setAlign(LV_ALIGN_CENTER); _panel->setPadding(0, 0, 24, 24); _panel->setPos(posX, posY); _panel->setBorderWidth(0); _panel->setHeight(24); _panel->setWidth((pageNum * dot_size) + (pageNum - 1) * (dot_gap - dot_size) + 24 * 2); _panel->setBgOpa(0); for (int i = 0; i < pageNum; i++) { _dots.push_back(std::make_unique(_panel->get())); _dots.back()->setAlign(LV_ALIGN_CENTER); _dots.back()->setPos(i * dot_gap - (pageNum - 1) * dot_gap / 2, 0); _dots.back()->setBgColor(lv_color_hex(0xFFFFFF)); _dots.back()->removeFlag(LV_OBJ_FLAG_SCROLLABLE); _dots.back()->setRadius(LV_RADIUS_CIRCLE); _dots.back()->setSize(dot_size, dot_size); _dots.back()->setBorderWidth(0); } jumpTo(0); } void jumpTo(int index) { if (index < 0 || index >= _page_num) { return; } _current_index = index; _last_index = index; update_dots(); } void update(int scrollValue) { _last_index = _current_index; // Calculate absolute index int abs_index = (scrollValue + _page_gap / 2) / _page_gap; // Map to 0 ~ N-1 _current_index = abs_index % _page_num; if (_current_index < 0) { _current_index += _page_num; } if (_last_index != _current_index) { update_dots(); } } private: int _page_num = 0; int _page_gap = 0; int _current_index = 0; int _last_index = 0; std::unique_ptr _panel; std::vector> _dots; void update_dots() { for (int i = 0; i < _page_num; i++) { if (i == _current_index) { _dots[i]->setSize(dot_size_big, dot_size_big); _dots[i]->setOpa(255); } else { _dots[i]->setSize(dot_size, dot_size); _dots[i]->setOpa(128); } } } }; /* -------------------------------------------------------------------------- */ /* Dynamic icon label */ /* -------------------------------------------------------------------------- */ class DynamicIconLabel { public: const int show_range = 50; const int hidden_pos_y = -150; const int visible_pos_y = -99; const int transition_zone = 30; void init(const std::vector& iconLabelTexts, int iconGap, lv_obj_t* parent) { _icon_label_texts = iconLabelTexts; _icon_gap = iconGap; // Create floating label _label = std::make_unique