Files
trail-mate/modules/ui_shared/src/ui/components/info_card.cpp
T
2026-04-20 16:01:55 +08:00

214 lines
6.1 KiB
C++

#include "ui/components/info_card.h"
#include <algorithm>
#include "ui/components/two_pane_styles.h"
namespace ui::components::info_card
{
namespace
{
constexpr lv_coord_t kTDeckBodyRowMinHeight = 18;
bool s_inited = false;
lv_style_t s_item_base;
lv_style_t s_item_active;
lv_style_t s_header_row;
void init_once()
{
if (s_inited)
{
return;
}
s_inited = true;
lv_style_init(&s_item_base);
lv_style_set_bg_opa(&s_item_base, LV_OPA_COVER);
lv_style_set_bg_color(&s_item_base, lv_color_hex(::ui::components::two_pane_styles::kSidePanelBg));
lv_style_set_border_width(&s_item_base, 1);
lv_style_set_border_color(&s_item_base, lv_color_hex(::ui::components::two_pane_styles::kBorder));
lv_style_set_radius(&s_item_base, 10);
lv_style_init(&s_item_active);
lv_style_set_bg_opa(&s_item_active, LV_OPA_COVER);
lv_style_set_bg_color(&s_item_active, lv_color_hex(::ui::components::two_pane_styles::kMainPanelBg));
lv_style_set_border_width(&s_item_active, 2);
lv_style_set_border_color(&s_item_active, lv_color_hex(::ui::components::two_pane_styles::kAccent));
lv_style_init(&s_header_row);
lv_style_set_bg_opa(&s_header_row, LV_OPA_COVER);
lv_style_set_bg_color(&s_header_row, lv_color_hex(::ui::components::two_pane_styles::kAccent));
lv_style_set_border_width(&s_header_row, 0);
lv_style_set_radius(&s_header_row, 8);
lv_style_set_pad_left(&s_header_row, 8);
lv_style_set_pad_right(&s_header_row, 8);
lv_style_set_pad_top(&s_header_row, 2);
lv_style_set_pad_bottom(&s_header_row, 2);
}
void prepare_row(lv_obj_t* row, bool transparent_background)
{
if (!row)
{
return;
}
lv_obj_set_size(row, LV_PCT(100), LV_SIZE_CONTENT);
lv_obj_clear_flag(row, LV_OBJ_FLAG_SCROLLABLE);
lv_obj_clear_flag(
row,
static_cast<lv_obj_flag_t>(LV_OBJ_FLAG_CLICKABLE |
LV_OBJ_FLAG_CLICK_FOCUSABLE |
LV_OBJ_FLAG_SCROLL_ON_FOCUS));
lv_obj_add_flag(row, LV_OBJ_FLAG_EVENT_BUBBLE);
lv_obj_set_flex_flow(row, LV_FLEX_FLOW_ROW);
lv_obj_set_flex_align(row, LV_FLEX_ALIGN_SPACE_BETWEEN,
LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
if (transparent_background)
{
lv_obj_set_style_bg_opa(row, LV_OPA_TRANSP, LV_PART_MAIN);
lv_obj_set_style_border_width(row, 0, LV_PART_MAIN);
lv_obj_set_style_radius(row, 0, LV_PART_MAIN);
lv_obj_set_style_pad_all(row, 0, LV_PART_MAIN);
}
}
lv_obj_t* create_flex_label(lv_obj_t* parent, bool flex_grow, lv_text_align_t align)
{
lv_obj_t* label = lv_label_create(parent);
lv_obj_add_flag(label, LV_OBJ_FLAG_EVENT_BUBBLE);
lv_label_set_long_mode(label, LV_LABEL_LONG_DOT);
lv_obj_set_style_text_align(label, align, 0);
if (flex_grow)
{
lv_obj_set_width(label, 0);
lv_obj_set_flex_grow(label, 1);
}
else
{
lv_obj_set_width(label, LV_SIZE_CONTENT);
}
return label;
}
} // namespace
bool use_tdeck_layout()
{
#if defined(ARDUINO_T_DECK)
return true;
#else
return false;
#endif
}
lv_coord_t resolve_height(lv_coord_t base_height)
{
if (!use_tdeck_layout())
{
return base_height;
}
return std::max<lv_coord_t>(46, base_height + 10);
}
void configure_item(lv_obj_t* obj, lv_coord_t base_height)
{
if (!obj)
{
return;
}
lv_obj_set_size(obj, LV_PCT(100), resolve_height(base_height));
lv_obj_clear_flag(obj, LV_OBJ_FLAG_SCROLLABLE);
if (!use_tdeck_layout())
{
return;
}
lv_obj_set_style_pad_left(obj, 10, LV_PART_MAIN);
lv_obj_set_style_pad_right(obj, 10, LV_PART_MAIN);
lv_obj_set_style_pad_top(obj, 5, LV_PART_MAIN);
lv_obj_set_style_pad_bottom(obj, 5, LV_PART_MAIN);
lv_obj_set_style_pad_row(obj, 2, LV_PART_MAIN);
lv_obj_set_flex_flow(obj, LV_FLEX_FLOW_COLUMN);
lv_obj_set_flex_align(obj, LV_FLEX_ALIGN_START,
LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START);
}
void apply_item_style(lv_obj_t* obj)
{
if (!use_tdeck_layout() || !obj)
{
return;
}
init_once();
lv_obj_add_style(obj, &s_item_base, LV_PART_MAIN);
lv_obj_add_style(obj, &s_item_active, LV_PART_MAIN | LV_STATE_FOCUSED);
lv_obj_add_style(obj, &s_item_active, LV_PART_MAIN | LV_STATE_FOCUS_KEY);
lv_obj_add_style(obj, &s_item_active, LV_PART_MAIN | LV_STATE_CHECKED);
lv_obj_add_style(obj, &s_item_active, LV_PART_MAIN | LV_STATE_PRESSED);
}
void apply_single_line_label(lv_obj_t* label)
{
if (!label)
{
return;
}
lv_label_set_long_mode(label, LV_LABEL_LONG_DOT);
const lv_font_t* font = static_cast<const lv_font_t*>(
lv_obj_get_style_text_font(label, LV_PART_MAIN));
if (!font)
{
return;
}
const lv_coord_t line_height =
static_cast<lv_coord_t>(lv_font_get_line_height(font));
lv_obj_set_height(label, line_height);
lv_obj_set_style_max_height(label, line_height, 0);
}
ContentSlots create_content(lv_obj_t* parent, const ContentOptions& options)
{
ContentSlots slots{};
if (!parent)
{
return slots;
}
slots.header_row = lv_obj_create(parent);
prepare_row(slots.header_row, false);
init_once();
lv_obj_add_style(slots.header_row, &s_header_row, LV_PART_MAIN);
slots.header_main_label = create_flex_label(slots.header_row, true, LV_TEXT_ALIGN_LEFT);
if (options.header_meta)
{
slots.header_meta_label = create_flex_label(slots.header_row, false, LV_TEXT_ALIGN_RIGHT);
}
slots.body_row = lv_obj_create(parent);
prepare_row(slots.body_row, true);
if (use_tdeck_layout())
{
lv_obj_set_style_min_height(slots.body_row, kTDeckBodyRowMinHeight, LV_PART_MAIN);
lv_obj_set_style_pad_top(slots.body_row, 1, LV_PART_MAIN);
lv_obj_set_style_pad_bottom(slots.body_row, 1, LV_PART_MAIN);
}
slots.body_main_label = create_flex_label(slots.body_row, true, LV_TEXT_ALIGN_LEFT);
if (options.body_meta)
{
slots.body_meta_label = create_flex_label(slots.body_row, false, LV_TEXT_ALIGN_RIGHT);
}
return slots;
}
} // namespace ui::components::info_card