mirror of
https://github.com/vicliu624/trail-mate.git
synced 2026-10-23 13:33:03 +00:00
Add PSRAM-backed menu widgets and unify adaptive launchers
This commit is contained in:
1 parent
1bb42567a8
commit
83b0f93fb9
43 files changed
+1394
-493
No files matched your search
@@ -1,90 +1,31 @@
|
||||
#pragma once
|
||||
|
||||
#include "ui/menu/dashboard/dashboard_style.h"
|
||||
#include <string>
|
||||
#include "ui/menu/dashboard/dashboard_widget.h"
|
||||
#include <array>
|
||||
|
||||
namespace ui::menu::dashboard
|
||||
{
|
||||
|
||||
struct MeshWidgetUi
|
||||
{
|
||||
DashboardCardChrome chrome{};
|
||||
lv_obj_t* orbit_outer = nullptr;
|
||||
lv_obj_t* orbit_mid = nullptr;
|
||||
lv_obj_t* orbit_core = nullptr;
|
||||
lv_obj_t* hero_value = nullptr;
|
||||
lv_obj_t* hero_caption = nullptr;
|
||||
lv_obj_t* stat_tiles[3]{};
|
||||
lv_obj_t* stat_values[3]{};
|
||||
lv_obj_t* stat_captions[3]{};
|
||||
lv_obj_t* signal_bar_wrap = nullptr;
|
||||
lv_obj_t* signal_bars[12]{};
|
||||
lv_obj_t* footer_label = nullptr;
|
||||
};
|
||||
|
||||
struct GpsWidgetUi
|
||||
{
|
||||
DashboardCardChrome chrome{};
|
||||
lv_obj_t* radar = nullptr;
|
||||
lv_obj_t* radar_rings[3]{};
|
||||
lv_obj_t* radar_cross_h = nullptr;
|
||||
lv_obj_t* radar_cross_v = nullptr;
|
||||
lv_obj_t* sat_dots[8]{};
|
||||
lv_obj_t* sat_labels[8]{};
|
||||
lv_obj_t* sat_use_tags[8]{};
|
||||
lv_obj_t* stat_tiles[3]{};
|
||||
lv_obj_t* stat_values[3]{};
|
||||
lv_obj_t* stat_captions[3]{};
|
||||
lv_obj_t* footer_label = nullptr;
|
||||
};
|
||||
|
||||
struct RecentWidgetUi
|
||||
{
|
||||
DashboardCardChrome chrome{};
|
||||
lv_obj_t* rows[2]{};
|
||||
lv_obj_t* row_dots[2]{};
|
||||
lv_obj_t* row_names[2]{};
|
||||
lv_obj_t* row_previews[2]{};
|
||||
std::string row_name_text[2];
|
||||
std::string row_preview_text[2];
|
||||
lv_obj_t* row_badges[2]{};
|
||||
lv_obj_t* row_badge_labels[2]{};
|
||||
lv_obj_t* scan_track = nullptr;
|
||||
lv_obj_t* scan_runner = nullptr;
|
||||
lv_obj_t* footer_label = nullptr;
|
||||
};
|
||||
|
||||
struct CompassWidgetUi
|
||||
{
|
||||
DashboardCardChrome chrome{};
|
||||
lv_obj_t* dial = nullptr;
|
||||
lv_obj_t* dial_ring = nullptr;
|
||||
lv_obj_t* dial_inner_ring = nullptr;
|
||||
lv_obj_t* north_marker = nullptr;
|
||||
lv_obj_t* needle = nullptr;
|
||||
lv_point_precise_t needle_points[2]{};
|
||||
lv_obj_t* center_dot = nullptr;
|
||||
lv_obj_t* cardinal_labels[4]{};
|
||||
lv_obj_t* target_name = nullptr;
|
||||
lv_obj_t* distance_value = nullptr;
|
||||
lv_obj_t* bearing_value = nullptr;
|
||||
lv_obj_t* footer_label = nullptr;
|
||||
};
|
||||
|
||||
// Container state only. No child controls or service data belong here.
|
||||
// This owner is allocated in PSRAM; the registry retains one pointer.
|
||||
struct DashboardUi
|
||||
{
|
||||
lv_obj_t* panel = nullptr;
|
||||
lv_obj_t* grid = nullptr;
|
||||
lv_obj_t* menu_grid = nullptr;
|
||||
lv_obj_t* pager = nullptr;
|
||||
lv_timer_t* timer = nullptr;
|
||||
std::array<WidgetHandle, 4> widgets{};
|
||||
uint32_t tick = 0;
|
||||
bool dock_right = false;
|
||||
MeshWidgetUi mesh{};
|
||||
GpsWidgetUi gps{};
|
||||
RecentWidgetUi recent{};
|
||||
CompassWidgetUi compass{};
|
||||
bool feed_open = false;
|
||||
bool active = true;
|
||||
uint8_t page = 0;
|
||||
lv_indev_t* pointer = nullptr;
|
||||
lv_point_t start{};
|
||||
bool pressed = false;
|
||||
bool inside_dashboard = false;
|
||||
};
|
||||
|
||||
DashboardUi& dashboard_state();
|
||||
DashboardUi* dashboard_state();
|
||||
bool dashboard_create();
|
||||
void dashboard_reset();
|
||||
|
||||
} // namespace ui::menu::dashboard
|
||||
@@ -0,0 +1,76 @@
|
||||
#pragma once
|
||||
#include "lvgl.h"
|
||||
#include "platform/ui/psram_ui_lease.h"
|
||||
#include <cstdlib>
|
||||
#include <new>
|
||||
#if defined(ESP_PLATFORM)
|
||||
#include "esp_heap_caps.h"
|
||||
#endif
|
||||
|
||||
namespace ui::menu::dashboard
|
||||
{
|
||||
enum class WidgetKind : uint8_t
|
||||
{
|
||||
Mesh,
|
||||
Gps,
|
||||
Recent,
|
||||
Compass,
|
||||
Agenda,
|
||||
Count
|
||||
};
|
||||
struct WidgetHandle
|
||||
{
|
||||
lv_obj_t* root = nullptr;
|
||||
void* state = nullptr;
|
||||
void (*refresh)(void*) = nullptr;
|
||||
uint32_t period_ms = 1000;
|
||||
uint32_t next_refresh_ms = 0;
|
||||
};
|
||||
inline void* widget_allocate(std::size_t bytes)
|
||||
{
|
||||
#if defined(ESP_PLATFORM)
|
||||
return heap_caps_malloc(bytes, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
|
||||
#else
|
||||
return std::malloc(bytes);
|
||||
#endif
|
||||
}
|
||||
inline void widget_free(void* memory)
|
||||
{
|
||||
#if defined(ESP_PLATFORM)
|
||||
heap_caps_free(memory);
|
||||
#else
|
||||
std::free(memory);
|
||||
#endif
|
||||
}
|
||||
struct WidgetLifetime
|
||||
{
|
||||
platform::ui::PsramUiLease memory;
|
||||
};
|
||||
template <typename T>
|
||||
T* create_widget_state()
|
||||
{
|
||||
void* memory = widget_allocate(sizeof(T));
|
||||
return memory ? new (memory) T{} : nullptr;
|
||||
}
|
||||
template <typename T>
|
||||
void delete_widget_state(T* state)
|
||||
{
|
||||
if (!state) return;
|
||||
state->~T();
|
||||
widget_free(state);
|
||||
}
|
||||
template <typename T>
|
||||
WidgetHandle own_widget(lv_obj_t* root, T* state, void (*refresh)(void*), uint32_t period_ms = 1000)
|
||||
{
|
||||
lv_obj_set_user_data(root, state);
|
||||
lv_obj_add_event_cb(
|
||||
root, [](lv_event_t* event)
|
||||
{
|
||||
// Child controls can borrow arrays in this state (compass points).
|
||||
// They must finish DELETE before the backing PSRAM is released.
|
||||
lv_obj_clean(lv_event_get_target_obj(event));
|
||||
delete_widget_state(static_cast<T*>(lv_event_get_user_data(event))); },
|
||||
LV_EVENT_DELETE, state);
|
||||
return {root, state, refresh, period_ms, 0};
|
||||
}
|
||||
} // namespace ui::menu::dashboard
|
||||
@@ -1,20 +1,15 @@
|
||||
#pragma once
|
||||
#include "ui/menu/dashboard/dashboard_widget.h"
|
||||
|
||||
#include "lvgl.h"
|
||||
|
||||
namespace ui::agenda
|
||||
{
|
||||
class IAgendaSource;
|
||||
}
|
||||
namespace ui::menu::dashboard
|
||||
{
|
||||
|
||||
void create_mesh_widget(lv_obj_t* parent, lv_coord_t card_w, lv_coord_t card_h);
|
||||
void refresh_mesh_widget();
|
||||
|
||||
void create_gps_widget(lv_obj_t* parent, lv_coord_t card_w, lv_coord_t card_h);
|
||||
void refresh_gps_widget();
|
||||
|
||||
void create_recent_widget(lv_obj_t* parent, lv_coord_t card_w, lv_coord_t card_h);
|
||||
void refresh_recent_widget();
|
||||
|
||||
void create_compass_widget(lv_obj_t* parent, lv_coord_t card_w, lv_coord_t card_h);
|
||||
void refresh_compass_widget();
|
||||
|
||||
WidgetHandle create_mesh_widget(lv_obj_t* parent, lv_coord_t width, lv_coord_t height);
|
||||
WidgetHandle create_gps_widget(lv_obj_t* parent, lv_coord_t width, lv_coord_t height);
|
||||
WidgetHandle create_recent_widget(lv_obj_t* parent, lv_coord_t width, lv_coord_t height);
|
||||
WidgetHandle create_compass_widget(lv_obj_t* parent, lv_coord_t width, lv_coord_t height);
|
||||
WidgetHandle create_agenda_widget(lv_obj_t* parent, lv_coord_t width, lv_coord_t height, ui::agenda::IAgendaSource* source);
|
||||
} // namespace ui::menu::dashboard
|
||||
@@ -4,14 +4,24 @@
|
||||
|
||||
#include "ui/menu/menu_layout.h"
|
||||
|
||||
namespace ui::agenda
|
||||
{
|
||||
class IAgendaSource;
|
||||
}
|
||||
|
||||
namespace ui::menu::dashboard
|
||||
{
|
||||
|
||||
#if defined(TRAIL_MATE_ESP_BOARD_TAB5) || defined(TRAIL_MATE_ESP_BOARD_T_DISPLAY_P4)
|
||||
#if defined(TRAIL_MATE_ESP_BOARD_TAB5) || defined(TRAIL_MATE_ESP_BOARD_T_DISPLAY_P4) || defined(ARDUINO_T_DECK) || defined(ARDUINO_WIO_TRACKER_L2) || defined(ARDUINO_T_LORA_PAGER)
|
||||
void init(lv_obj_t* menu_panel, lv_obj_t* grid_panel, const ui::menu_layout::InitOptions& options);
|
||||
void bringToFront();
|
||||
void refresh_localized_text();
|
||||
void setActive(bool active);
|
||||
// Target-owned read port; its lifetime must exceed the menu's lifetime.
|
||||
void bindAgendaSource(ui::agenda::IAgendaSource* source);
|
||||
bool isFeedOpen();
|
||||
bool handleKey(uint32_t key, bool at_left_edge = false);
|
||||
bool handleEncoder(int delta);
|
||||
#else
|
||||
inline void init(lv_obj_t* menu_panel, lv_obj_t* grid_panel, const ui::menu_layout::InitOptions& options)
|
||||
{
|
||||
@@ -32,6 +42,10 @@ inline void setActive(bool active)
|
||||
{
|
||||
(void)active;
|
||||
}
|
||||
inline void bindAgendaSource(ui::agenda::IAgendaSource*) {}
|
||||
inline bool isFeedOpen() { return false; }
|
||||
inline bool handleKey(uint32_t, bool = false) { return false; }
|
||||
inline bool handleEncoder(int) { return false; }
|
||||
#endif
|
||||
|
||||
} // namespace ui::menu::dashboard
|
||||
Reference in new issue
Block a user