Files
ratdeck/src/ui/LvTabBar.cpp
T
DeFiDude 07025bfa23 v1.4.0: LVGL UI, async radio TX, live TCP management, input fixes
- Migrate all screens to LVGL v8.4 widget system
- Non-blocking radio TX (async endPacket via LoRaInterface)
- Live TCP server switching with transient node cleanup
- Fix UI freeze during radio transmit
- Trackball long-press delete, deferred click with debounce
- Pin microReticulum to 392363c, fix list_directory API
- Fix CI build: portable include path, remove hardcoded local path
2026-03-07 13:00:59 -07:00

82 lines
2.7 KiB
C++

#include "LvTabBar.h"
#include "Theme.h"
#include <cstdio>
constexpr const char* LvTabBar::TAB_NAMES[TAB_COUNT];
static void tab_click_cb(lv_event_t* e) {
LvTabBar* bar = (LvTabBar*)lv_event_get_user_data(e);
lv_obj_t* target = lv_event_get_target(e);
for (int i = 0; i < LvTabBar::TAB_COUNT; i++) {
lv_obj_t* parent = lv_obj_get_parent(target);
if (target == lv_obj_get_child(bar->obj(), i) ||
(parent && parent == lv_obj_get_child(bar->obj(), i))) {
bar->setActiveTab(i);
break;
}
}
}
void LvTabBar::create(lv_obj_t* parent) {
_bar = lv_obj_create(parent);
lv_obj_set_size(_bar, Theme::SCREEN_W, Theme::TAB_BAR_H);
lv_obj_align(_bar, LV_ALIGN_BOTTOM_LEFT, 0, 0);
lv_obj_set_style_bg_color(_bar, lv_color_hex(Theme::BG), 0);
lv_obj_set_style_bg_opa(_bar, LV_OPA_COVER, 0);
lv_obj_set_style_border_color(_bar, lv_color_hex(Theme::BORDER), 0);
lv_obj_set_style_border_width(_bar, 1, 0);
lv_obj_set_style_border_side(_bar, LV_BORDER_SIDE_TOP, 0);
lv_obj_set_style_pad_all(_bar, 0, 0);
lv_obj_set_style_radius(_bar, 0, 0);
lv_obj_clear_flag(_bar, LV_OBJ_FLAG_SCROLLABLE);
lv_obj_set_layout(_bar, LV_LAYOUT_FLEX);
lv_obj_set_flex_flow(_bar, LV_FLEX_FLOW_ROW);
lv_obj_set_flex_align(_bar, LV_FLEX_ALIGN_SPACE_EVENLY, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
const lv_font_t* font = &lv_font_montserrat_12;
for (int i = 0; i < TAB_COUNT; i++) {
_tabs[i] = lv_label_create(_bar);
lv_obj_set_style_text_font(_tabs[i], font, 0);
lv_label_set_text(_tabs[i], TAB_NAMES[i]);
lv_obj_add_flag(_tabs[i], LV_OBJ_FLAG_CLICKABLE);
lv_obj_add_event_cb(_tabs[i], tab_click_cb, LV_EVENT_CLICKED, this);
}
refreshTabs();
}
void LvTabBar::setActiveTab(int tab) {
if (tab < 0 || tab >= TAB_COUNT) return;
_activeTab = tab;
refreshTabs();
if (_tabCb) _tabCb(tab);
}
void LvTabBar::cycleTab(int direction) {
int next = (_activeTab + direction + TAB_COUNT) % TAB_COUNT;
setActiveTab(next);
}
void LvTabBar::setUnreadCount(int tab, int count) {
if (tab < 0 || tab >= TAB_COUNT) return;
_unread[tab] = count;
refreshTabs();
}
void LvTabBar::refreshTabs() {
for (int i = 0; i < TAB_COUNT; i++) {
bool active = (i == _activeTab);
lv_obj_set_style_text_color(_tabs[i],
lv_color_hex(active ? Theme::TAB_ACTIVE : Theme::TAB_INACTIVE), 0);
char buf[24];
if (_unread[i] > 0) {
snprintf(buf, sizeof(buf), "%s(%d)", TAB_NAMES[i], _unread[i]);
} else {
snprintf(buf, sizeof(buf), "%s", TAB_NAMES[i]);
}
lv_label_set_text(_tabs[i], buf);
}
}