feat: 实现设置页面及其功能
This commit is contained in:
+6
-1
@@ -14,6 +14,9 @@ idf_component_register(SRCS
|
||||
"ui/screens/ui_Screen1.c"
|
||||
"ui/screens/ui_Screen2.c"
|
||||
"ui/screens/ui_Screen3.c"
|
||||
"ui/screens/ui_Settings.c"
|
||||
"ui/settings/settings_store.c"
|
||||
"ui/settings/settings_tabs.c"
|
||||
"ui/widgets/ui_comp_hook.c"
|
||||
PRIV_REQUIRES
|
||||
bt
|
||||
@@ -30,4 +33,6 @@ idf_component_register(SRCS
|
||||
"app"
|
||||
"bsp"
|
||||
"services"
|
||||
"ui")
|
||||
"ui"
|
||||
"ui/settings"
|
||||
)
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
#include "ui_handlers.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "ble_hid.h"
|
||||
#include "boot_button.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_system.h"
|
||||
#include "screens/ui_Settings.h"
|
||||
#include "settings/settings_store.h"
|
||||
#include "settings/settings_tabs.h"
|
||||
#include "ui_events.h"
|
||||
|
||||
static const char *TAG = "ui_handlers";
|
||||
@@ -37,6 +42,83 @@ void ui_handlers_init(void)
|
||||
boot_button_init(on_boot_press);
|
||||
}
|
||||
|
||||
void settings_on_tab_clicked(lv_event_t *e)
|
||||
{
|
||||
settings_tab_t tab = (settings_tab_t)(intptr_t)lv_event_get_user_data(e);
|
||||
ui_Settings_switch_tab(tab);
|
||||
}
|
||||
|
||||
void settings_on_save_clicked(lv_event_t *e)
|
||||
{
|
||||
(void)e;
|
||||
settings_data_t buf = *settings_store_get();
|
||||
settings_tabs_collect(ui_Settings_get_active_tab(), &buf);
|
||||
settings_store_update(&buf);
|
||||
esp_err_t err = settings_store_commit();
|
||||
if (err == ESP_OK) {
|
||||
settings_store_apply();
|
||||
ESP_LOGI(TAG, "Settings saved");
|
||||
} else {
|
||||
ESP_LOGW(TAG, "Settings save failed");
|
||||
}
|
||||
}
|
||||
|
||||
void settings_on_factory_reset(lv_event_t *e)
|
||||
{
|
||||
(void)e;
|
||||
ESP_LOGW(TAG, "Factory reset");
|
||||
settings_store_factory_reset();
|
||||
settings_store_apply();
|
||||
esp_restart();
|
||||
}
|
||||
|
||||
void settings_on_brightness_changed(lv_event_t *e)
|
||||
{
|
||||
lv_obj_t *slider = lv_event_get_target(e);
|
||||
uint8_t pct = (uint8_t)lv_slider_get_value(slider);
|
||||
|
||||
settings_data_t buf = *settings_store_get();
|
||||
buf.brightness_pct = pct;
|
||||
settings_store_update(&buf);
|
||||
settings_store_apply();
|
||||
|
||||
lv_obj_t *pct_label = lv_obj_get_user_data(slider);
|
||||
if (pct_label != NULL) {
|
||||
lv_label_set_text_fmt(pct_label, "%u%%", pct);
|
||||
}
|
||||
}
|
||||
|
||||
void settings_on_value_changed(lv_event_t *e)
|
||||
{
|
||||
settings_field_t field =
|
||||
(settings_field_t)(intptr_t)lv_event_get_user_data(e);
|
||||
lv_obj_t *target = lv_event_get_target(e);
|
||||
settings_data_t buf = *settings_store_get();
|
||||
|
||||
switch (field) {
|
||||
case SETTINGS_FIELD_NOTIFICATION:
|
||||
buf.notification_enabled = lv_obj_has_state(target, LV_STATE_CHECKED);
|
||||
break;
|
||||
case SETTINGS_FIELD_VOLUME:
|
||||
buf.volume_pct = (uint8_t)lv_slider_get_value(target);
|
||||
break;
|
||||
case SETTINGS_FIELD_MUTE:
|
||||
buf.mute = lv_obj_has_state(target, LV_STATE_CHECKED);
|
||||
break;
|
||||
default:
|
||||
LV_ASSERT_MSG(false, "unexpected settings_field_t");
|
||||
break;
|
||||
}
|
||||
|
||||
settings_store_update(&buf);
|
||||
}
|
||||
|
||||
void settings_on_network_scan_clicked(lv_event_t *e)
|
||||
{
|
||||
(void)e;
|
||||
ESP_LOGI(TAG, "Not available");
|
||||
}
|
||||
|
||||
void update_year_action(lv_event_t * e)
|
||||
{
|
||||
(void)e;
|
||||
|
||||
@@ -1,4 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include "lvgl.h"
|
||||
|
||||
/* UI event callbacks declared in ui_events.h are implemented in ui_handlers.c */
|
||||
void ui_handlers_init(void);
|
||||
|
||||
void settings_on_tab_clicked(lv_event_t *e);
|
||||
void settings_on_save_clicked(lv_event_t *e);
|
||||
void settings_on_factory_reset(lv_event_t *e);
|
||||
void settings_on_brightness_changed(lv_event_t *e);
|
||||
void settings_on_value_changed(lv_event_t *e);
|
||||
void settings_on_network_scan_clicked(lv_event_t *e);
|
||||
|
||||
@@ -9,6 +9,15 @@
|
||||
#define BOARD_LCD_PIXEL_CLOCK_HZ (20 * 1000 * 1000)
|
||||
#define BOARD_LCD_H_RES 170
|
||||
#define BOARD_LCD_V_RES 320
|
||||
|
||||
/* LVGL logical resolution after 90° rotation (landscape) */
|
||||
#define BOARD_LCD_LOGIC_H_RES 320
|
||||
#define BOARD_LCD_LOGIC_V_RES 170
|
||||
|
||||
/* Touch IC → physical panel alignment (not LVGL logical rotation) */
|
||||
#define BOARD_TOUCH_SWAP_XY 0
|
||||
#define BOARD_TOUCH_MIRROR_X 0
|
||||
#define BOARD_TOUCH_MIRROR_Y 0
|
||||
#define BOARD_LCD_PANEL_H_RES 240
|
||||
#define BOARD_LCD_GAP_X ((BOARD_LCD_PANEL_H_RES - BOARD_LCD_H_RES) / 2)
|
||||
#define BOARD_LCD_GAP_Y 0
|
||||
|
||||
+34
-6
@@ -2,6 +2,7 @@
|
||||
|
||||
#include "board_config.h"
|
||||
|
||||
#include "draw/sw/lv_draw_sw.h"
|
||||
#include "driver/spi_master.h"
|
||||
#include "esp_lcd_panel_ops.h"
|
||||
#include "esp_log.h"
|
||||
@@ -31,14 +32,40 @@ static bool notify_flush_ready(esp_lcd_panel_io_handle_t panel_io,
|
||||
static void flush_cb(lv_display_t *disp, const lv_area_t *area, uint8_t *px_map)
|
||||
{
|
||||
esp_lcd_panel_handle_t panel_handle = lv_display_get_user_data(disp);
|
||||
int offsetx1 = area->x1;
|
||||
int offsetx2 = area->x2;
|
||||
int offsety1 = area->y1;
|
||||
int offsety2 = area->y2;
|
||||
lv_draw_sw_rgb565_swap(px_map,
|
||||
const lv_area_t *draw_area = area;
|
||||
uint8_t *draw_buf = px_map;
|
||||
|
||||
static uint8_t rotated_buf[BOARD_LCD_H_RES * BOARD_LVGL_DRAW_BUF_LINES *
|
||||
sizeof(lv_color16_t)];
|
||||
|
||||
lv_display_rotation_t rotation = lv_display_get_rotation(disp);
|
||||
lv_area_t rotated_area;
|
||||
if (rotation != LV_DISPLAY_ROTATION_0) {
|
||||
lv_color_format_t cf = lv_display_get_color_format(disp);
|
||||
rotated_area = *area;
|
||||
lv_display_rotate_area(disp, &rotated_area);
|
||||
|
||||
int32_t src_w = lv_area_get_width(area);
|
||||
int32_t src_h = lv_area_get_height(area);
|
||||
uint32_t src_stride = lv_draw_buf_width_to_stride(src_w, cf);
|
||||
uint32_t dest_stride =
|
||||
lv_draw_buf_width_to_stride(lv_area_get_width(&rotated_area), cf);
|
||||
|
||||
lv_draw_sw_rotate(px_map, rotated_buf, src_w, src_h, src_stride,
|
||||
dest_stride, rotation, cf);
|
||||
|
||||
draw_area = &rotated_area;
|
||||
draw_buf = rotated_buf;
|
||||
}
|
||||
|
||||
int offsetx1 = draw_area->x1;
|
||||
int offsetx2 = draw_area->x2;
|
||||
int offsety1 = draw_area->y1;
|
||||
int offsety2 = draw_area->y2;
|
||||
lv_draw_sw_rgb565_swap(draw_buf,
|
||||
(offsetx2 + 1 - offsetx1) * (offsety2 + 1 - offsety1));
|
||||
esp_lcd_panel_draw_bitmap(panel_handle, offsetx1, offsety1, offsetx2 + 1,
|
||||
offsety2 + 1, px_map);
|
||||
offsety2 + 1, draw_buf);
|
||||
}
|
||||
|
||||
static void increase_lvgl_tick(void *arg)
|
||||
@@ -80,6 +107,7 @@ lv_display_t *lvgl_port_init(esp_lcd_panel_io_handle_t io_handle,
|
||||
|
||||
lv_display_t *display =
|
||||
lv_display_create(BOARD_LCD_H_RES, BOARD_LCD_V_RES);
|
||||
lv_display_set_rotation(display, LV_DISPLAY_ROTATION_270);
|
||||
|
||||
size_t draw_buffer_sz = BOARD_LCD_H_RES * BOARD_LVGL_DRAW_BUF_LINES *
|
||||
sizeof(lv_color16_t);
|
||||
|
||||
+3
-3
@@ -86,9 +86,9 @@ esp_err_t touch_init(lv_display_t *display)
|
||||
.interrupt = 0,
|
||||
},
|
||||
.flags = {
|
||||
.swap_xy = 0,
|
||||
.mirror_x = 0,
|
||||
.mirror_y = 0,
|
||||
.swap_xy = BOARD_TOUCH_SWAP_XY,
|
||||
.mirror_x = BOARD_TOUCH_MIRROR_X,
|
||||
.mirror_y = BOARD_TOUCH_MIRROR_Y,
|
||||
},
|
||||
.interrupt_callback = touch_isr_cb,
|
||||
};
|
||||
|
||||
@@ -0,0 +1,154 @@
|
||||
#include "ui_Settings.h"
|
||||
|
||||
#include "board_config.h"
|
||||
#include "settings/settings_store.h"
|
||||
#include "settings/settings_tabs.h"
|
||||
#include "ui_handlers.h"
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
lv_obj_t *ui_Settings;
|
||||
lv_obj_t *ui_Settings_sidebar;
|
||||
lv_obj_t *ui_Settings_content;
|
||||
|
||||
static settings_tab_t s_active_tab = SETTINGS_TAB_SYSTEM;
|
||||
static lv_obj_t *s_nav_buttons[4];
|
||||
|
||||
static lv_style_t s_style_sidebar_btn_active;
|
||||
static lv_style_t s_style_content_bg;
|
||||
static bool s_styles_inited;
|
||||
|
||||
static const char *s_tab_labels[] = {
|
||||
"System",
|
||||
"Display",
|
||||
"Audio",
|
||||
"Network",
|
||||
};
|
||||
|
||||
static void init_styles(void)
|
||||
{
|
||||
if (s_styles_inited) {
|
||||
return;
|
||||
}
|
||||
|
||||
lv_style_init(&s_style_sidebar_btn_active);
|
||||
lv_style_set_bg_color(&s_style_sidebar_btn_active,
|
||||
lv_palette_main(LV_PALETTE_BLUE));
|
||||
lv_style_set_bg_opa(&s_style_sidebar_btn_active, LV_OPA_COVER);
|
||||
|
||||
lv_style_init(&s_style_content_bg);
|
||||
lv_style_set_bg_color(&s_style_content_bg,
|
||||
lv_palette_lighten(LV_PALETTE_GREY, 2));
|
||||
lv_style_set_bg_opa(&s_style_content_bg, LV_OPA_COVER);
|
||||
|
||||
s_styles_inited = true;
|
||||
}
|
||||
|
||||
static void sidebar_update_highlight(settings_tab_t tab)
|
||||
{
|
||||
for (size_t i = 0; i < 4; i++) {
|
||||
if (s_nav_buttons[i] == NULL) {
|
||||
continue;
|
||||
}
|
||||
if ((settings_tab_t)i == tab) {
|
||||
lv_obj_add_style(s_nav_buttons[i], &s_style_sidebar_btn_active, 0);
|
||||
} else {
|
||||
lv_obj_remove_style(s_nav_buttons[i], &s_style_sidebar_btn_active, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
settings_tab_t ui_Settings_get_active_tab(void)
|
||||
{
|
||||
return s_active_tab;
|
||||
}
|
||||
|
||||
void ui_Settings_switch_tab(settings_tab_t tab)
|
||||
{
|
||||
settings_data_t buf = *settings_store_get();
|
||||
settings_tabs_collect(s_active_tab, &buf);
|
||||
settings_store_update(&buf);
|
||||
|
||||
s_active_tab = tab;
|
||||
sidebar_update_highlight(tab);
|
||||
|
||||
lv_obj_clean(ui_Settings_content);
|
||||
switch (tab) {
|
||||
case SETTINGS_TAB_SYSTEM:
|
||||
load_system_settings(ui_Settings_content, settings_store_get());
|
||||
break;
|
||||
case SETTINGS_TAB_DISPLAY:
|
||||
load_display_settings(ui_Settings_content, settings_store_get());
|
||||
break;
|
||||
case SETTINGS_TAB_AUDIO:
|
||||
load_audio_settings(ui_Settings_content, settings_store_get());
|
||||
break;
|
||||
case SETTINGS_TAB_NETWORK:
|
||||
load_network_settings(ui_Settings_content, settings_store_get());
|
||||
break;
|
||||
default:
|
||||
LV_ASSERT_MSG(false, "unexpected settings_tab_t");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ui_Settings_screen_init(void)
|
||||
{
|
||||
init_styles();
|
||||
|
||||
ui_Settings = lv_obj_create(NULL);
|
||||
lv_obj_set_size(ui_Settings, BOARD_LCD_LOGIC_H_RES, BOARD_LCD_LOGIC_V_RES);
|
||||
lv_obj_set_style_pad_all(ui_Settings, 2, 0);
|
||||
lv_obj_remove_flag(ui_Settings, LV_OBJ_FLAG_SCROLLABLE);
|
||||
|
||||
ui_Settings_sidebar = lv_list_create(ui_Settings);
|
||||
lv_obj_set_size(ui_Settings_sidebar, 90, 170);
|
||||
lv_obj_set_pos(ui_Settings_sidebar, 0, 0);
|
||||
lv_obj_set_style_pad_all(ui_Settings_sidebar, 2, 0);
|
||||
lv_obj_set_style_pad_row(ui_Settings_sidebar, 2, 0);
|
||||
lv_obj_remove_flag(ui_Settings_sidebar, LV_OBJ_FLAG_SCROLLABLE);
|
||||
|
||||
for (size_t i = 0; i < 4; i++) {
|
||||
s_nav_buttons[i] =
|
||||
lv_list_add_button(ui_Settings_sidebar, NULL, s_tab_labels[i]);
|
||||
lv_obj_set_size(s_nav_buttons[i], 86, 28);
|
||||
lv_obj_add_event_cb(s_nav_buttons[i], settings_on_tab_clicked,
|
||||
LV_EVENT_CLICKED, (void *)(intptr_t)i);
|
||||
}
|
||||
|
||||
lv_obj_t *save_btn = lv_button_create(ui_Settings);
|
||||
lv_obj_set_size(save_btn, 86, 28);
|
||||
lv_obj_set_pos(save_btn, 2, 138);
|
||||
lv_obj_t *save_label = lv_label_create(save_btn);
|
||||
lv_label_set_text(save_label, "Save");
|
||||
lv_obj_center(save_label);
|
||||
lv_obj_add_event_cb(save_btn, settings_on_save_clicked, LV_EVENT_CLICKED,
|
||||
NULL);
|
||||
|
||||
ui_Settings_content = lv_obj_create(ui_Settings);
|
||||
lv_obj_set_size(ui_Settings_content, 230, 170);
|
||||
lv_obj_set_pos(ui_Settings_content, 90, 0);
|
||||
lv_obj_set_style_pad_all(ui_Settings_content, 2, 0);
|
||||
lv_obj_add_style(ui_Settings_content, &s_style_content_bg, 0);
|
||||
lv_obj_remove_flag(ui_Settings_content, LV_OBJ_FLAG_SCROLLABLE);
|
||||
|
||||
settings_store_load();
|
||||
settings_store_apply();
|
||||
|
||||
s_active_tab = SETTINGS_TAB_SYSTEM;
|
||||
sidebar_update_highlight(s_active_tab);
|
||||
load_system_settings(ui_Settings_content, settings_store_get());
|
||||
}
|
||||
|
||||
void ui_Settings_screen_destroy(void)
|
||||
{
|
||||
if (ui_Settings != NULL) {
|
||||
lv_obj_del(ui_Settings);
|
||||
ui_Settings = NULL;
|
||||
ui_Settings_sidebar = NULL;
|
||||
ui_Settings_content = NULL;
|
||||
}
|
||||
for (size_t i = 0; i < 4; i++) {
|
||||
s_nav_buttons[i] = NULL;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include "lvgl.h"
|
||||
#include "settings_types.h"
|
||||
|
||||
extern lv_obj_t *ui_Settings;
|
||||
extern lv_obj_t *ui_Settings_sidebar;
|
||||
extern lv_obj_t *ui_Settings_content;
|
||||
|
||||
void ui_Settings_screen_init(void);
|
||||
void ui_Settings_screen_destroy(void);
|
||||
|
||||
void ui_Settings_switch_tab(settings_tab_t tab);
|
||||
settings_tab_t ui_Settings_get_active_tab(void);
|
||||
@@ -0,0 +1,121 @@
|
||||
#include "settings_store.h"
|
||||
|
||||
#include "display.h"
|
||||
|
||||
#include "esp_log.h"
|
||||
#include "nvs.h"
|
||||
#include "nvs_flash.h"
|
||||
|
||||
static const char *TAG = "settings_store";
|
||||
|
||||
static const char *SETTINGS_NAMESPACE = "settings";
|
||||
|
||||
static const settings_data_t SETTINGS_DEFAULTS = {
|
||||
.notification_enabled = false,
|
||||
.brightness_pct = 70,
|
||||
.volume_pct = 50,
|
||||
.mute = false,
|
||||
};
|
||||
|
||||
static settings_data_t s_data;
|
||||
|
||||
static void load_key_u8(nvs_handle_t handle, const char *key, uint8_t *out,
|
||||
uint8_t default_val)
|
||||
{
|
||||
uint8_t val = default_val;
|
||||
if (nvs_get_u8(handle, key, &val) != ESP_OK) {
|
||||
val = default_val;
|
||||
}
|
||||
*out = val;
|
||||
}
|
||||
|
||||
void settings_store_load(void)
|
||||
{
|
||||
s_data = SETTINGS_DEFAULTS;
|
||||
|
||||
nvs_handle_t handle;
|
||||
esp_err_t err = nvs_open(SETTINGS_NAMESPACE, NVS_READONLY, &handle);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGI(TAG, "No saved settings, using defaults");
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t val;
|
||||
load_key_u8(handle, "notif", &val, SETTINGS_DEFAULTS.notification_enabled);
|
||||
s_data.notification_enabled = val != 0;
|
||||
load_key_u8(handle, "bright", &s_data.brightness_pct,
|
||||
SETTINGS_DEFAULTS.brightness_pct);
|
||||
load_key_u8(handle, "vol", &s_data.volume_pct, SETTINGS_DEFAULTS.volume_pct);
|
||||
load_key_u8(handle, "mute", &val, SETTINGS_DEFAULTS.mute);
|
||||
s_data.mute = val != 0;
|
||||
|
||||
nvs_close(handle);
|
||||
ESP_LOGI(TAG, "Settings loaded (bright=%u vol=%u)", s_data.brightness_pct,
|
||||
s_data.volume_pct);
|
||||
}
|
||||
|
||||
const settings_data_t *settings_store_get(void)
|
||||
{
|
||||
return &s_data;
|
||||
}
|
||||
|
||||
void settings_store_update(const settings_data_t *data)
|
||||
{
|
||||
s_data = *data;
|
||||
}
|
||||
|
||||
esp_err_t settings_store_commit(void)
|
||||
{
|
||||
nvs_handle_t handle;
|
||||
esp_err_t err = nvs_open(SETTINGS_NAMESPACE, NVS_READWRITE, &handle);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "nvs_open failed: %s", esp_err_to_name(err));
|
||||
return err;
|
||||
}
|
||||
|
||||
err = nvs_set_u8(handle, "notif", s_data.notification_enabled ? 1 : 0);
|
||||
if (err == ESP_OK) {
|
||||
err = nvs_set_u8(handle, "bright", s_data.brightness_pct);
|
||||
}
|
||||
if (err == ESP_OK) {
|
||||
err = nvs_set_u8(handle, "vol", s_data.volume_pct);
|
||||
}
|
||||
if (err == ESP_OK) {
|
||||
err = nvs_set_u8(handle, "mute", s_data.mute ? 1 : 0);
|
||||
}
|
||||
if (err == ESP_OK) {
|
||||
err = nvs_commit(handle);
|
||||
}
|
||||
|
||||
nvs_close(handle);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "commit failed: %s", esp_err_to_name(err));
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
esp_err_t settings_store_factory_reset(void)
|
||||
{
|
||||
nvs_handle_t handle;
|
||||
esp_err_t err = nvs_open(SETTINGS_NAMESPACE, NVS_READWRITE, &handle);
|
||||
if (err == ESP_OK) {
|
||||
err = nvs_erase_all(handle);
|
||||
if (err == ESP_OK) {
|
||||
err = nvs_commit(handle);
|
||||
}
|
||||
nvs_close(handle);
|
||||
}
|
||||
|
||||
s_data = SETTINGS_DEFAULTS;
|
||||
esp_err_t commit_err = settings_store_commit();
|
||||
if (err != ESP_OK) {
|
||||
return err;
|
||||
}
|
||||
return commit_err;
|
||||
}
|
||||
|
||||
void settings_store_apply(void)
|
||||
{
|
||||
uint16_t duty = (uint16_t)((s_data.brightness_pct * 1023U) / 100U);
|
||||
display_backlight_set_brightness(duty);
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include "esp_err.h"
|
||||
#include "settings_types.h"
|
||||
|
||||
void settings_store_load(void);
|
||||
const settings_data_t *settings_store_get(void);
|
||||
void settings_store_update(const settings_data_t *data);
|
||||
esp_err_t settings_store_commit(void);
|
||||
esp_err_t settings_store_factory_reset(void);
|
||||
void settings_store_apply(void);
|
||||
@@ -0,0 +1,194 @@
|
||||
#include "settings_tabs.h"
|
||||
|
||||
#include "ui_handlers.h"
|
||||
|
||||
static lv_obj_t *s_notif_switch;
|
||||
static lv_obj_t *s_brightness_slider;
|
||||
static lv_obj_t *s_brightness_pct_label;
|
||||
static lv_obj_t *s_volume_slider;
|
||||
static lv_obj_t *s_mute_switch;
|
||||
|
||||
static lv_obj_t *create_status_bar(lv_obj_t *content, const char *title)
|
||||
{
|
||||
lv_obj_t *status_bar = lv_obj_create(content);
|
||||
lv_obj_set_size(status_bar, 230, 25);
|
||||
lv_obj_set_pos(status_bar, 0, 0);
|
||||
lv_obj_set_style_pad_all(status_bar, 2, 0);
|
||||
lv_obj_set_style_border_width(status_bar, 1, 0);
|
||||
lv_obj_set_style_border_side(status_bar, LV_BORDER_SIDE_BOTTOM, 0);
|
||||
lv_obj_remove_flag(status_bar, LV_OBJ_FLAG_SCROLLABLE);
|
||||
|
||||
lv_obj_t *title_label = lv_label_create(status_bar);
|
||||
lv_label_set_text(title_label, title);
|
||||
lv_obj_align(title_label, LV_ALIGN_LEFT_MID, 2, 0);
|
||||
|
||||
lv_obj_t *time_label = lv_label_create(status_bar);
|
||||
lv_label_set_text(time_label, "--:--");
|
||||
lv_obj_align(time_label, LV_ALIGN_RIGHT_MID, -2, 0);
|
||||
|
||||
return status_bar;
|
||||
}
|
||||
|
||||
static lv_obj_t *create_settings_body(lv_obj_t *content)
|
||||
{
|
||||
lv_obj_t *body = lv_obj_create(content);
|
||||
lv_obj_set_size(body, 230, 145);
|
||||
lv_obj_set_pos(body, 0, 25);
|
||||
lv_obj_set_style_pad_all(body, 2, 0);
|
||||
lv_obj_set_style_border_width(body, 0, 0);
|
||||
lv_obj_remove_flag(body, LV_OBJ_FLAG_SCROLLABLE);
|
||||
return body;
|
||||
}
|
||||
|
||||
void load_system_settings(lv_obj_t *content, const settings_data_t *data)
|
||||
{
|
||||
s_notif_switch = NULL;
|
||||
|
||||
create_status_bar(content, "System Settings");
|
||||
lv_obj_t *body = create_settings_body(content);
|
||||
|
||||
lv_obj_t *notif_label = lv_label_create(body);
|
||||
lv_label_set_text(notif_label, "Enable Notification");
|
||||
lv_obj_set_pos(notif_label, 4, 4);
|
||||
lv_obj_set_size(notif_label, 120, 28);
|
||||
|
||||
s_notif_switch = lv_switch_create(body);
|
||||
lv_obj_set_pos(s_notif_switch, 180, 4);
|
||||
lv_obj_set_size(s_notif_switch, 40, 28);
|
||||
if (data->notification_enabled) {
|
||||
lv_obj_add_state(s_notif_switch, LV_STATE_CHECKED);
|
||||
}
|
||||
lv_obj_add_event_cb(s_notif_switch, settings_on_value_changed,
|
||||
LV_EVENT_VALUE_CHANGED,
|
||||
(void *)(intptr_t)SETTINGS_FIELD_NOTIFICATION);
|
||||
|
||||
lv_obj_t *reset_btn = lv_button_create(body);
|
||||
lv_obj_set_pos(reset_btn, 4, 112);
|
||||
lv_obj_set_size(reset_btn, 100, 28);
|
||||
lv_obj_set_style_text_color(reset_btn, lv_palette_main(LV_PALETTE_RED), 0);
|
||||
lv_obj_t *reset_label = lv_label_create(reset_btn);
|
||||
lv_label_set_text(reset_label, "Factory Reset");
|
||||
lv_obj_center(reset_label);
|
||||
lv_obj_add_event_cb(reset_btn, settings_on_factory_reset, LV_EVENT_CLICKED,
|
||||
NULL);
|
||||
}
|
||||
|
||||
void load_display_settings(lv_obj_t *content, const settings_data_t *data)
|
||||
{
|
||||
s_brightness_slider = NULL;
|
||||
s_brightness_pct_label = NULL;
|
||||
|
||||
create_status_bar(content, "Display Settings");
|
||||
lv_obj_t *body = create_settings_body(content);
|
||||
|
||||
lv_obj_t *bright_label = lv_label_create(body);
|
||||
lv_label_set_text(bright_label, "Brightness");
|
||||
lv_obj_set_pos(bright_label, 4, 4);
|
||||
lv_obj_set_size(bright_label, 80, 28);
|
||||
|
||||
s_brightness_slider = lv_slider_create(body);
|
||||
lv_obj_set_pos(s_brightness_slider, 88, 8);
|
||||
lv_obj_set_size(s_brightness_slider, 100, 12);
|
||||
lv_slider_set_range(s_brightness_slider, 0, 100);
|
||||
lv_slider_set_value(s_brightness_slider, data->brightness_pct, LV_ANIM_OFF);
|
||||
|
||||
s_brightness_pct_label = lv_label_create(body);
|
||||
lv_label_set_text_fmt(s_brightness_pct_label, "%u%%", data->brightness_pct);
|
||||
lv_obj_set_pos(s_brightness_pct_label, 196, 4);
|
||||
lv_obj_set_size(s_brightness_pct_label, 30, 28);
|
||||
|
||||
lv_obj_set_user_data(s_brightness_slider, s_brightness_pct_label);
|
||||
lv_obj_add_event_cb(s_brightness_slider, settings_on_brightness_changed,
|
||||
LV_EVENT_VALUE_CHANGED, NULL);
|
||||
}
|
||||
|
||||
void load_audio_settings(lv_obj_t *content, const settings_data_t *data)
|
||||
{
|
||||
s_volume_slider = NULL;
|
||||
s_mute_switch = NULL;
|
||||
|
||||
create_status_bar(content, "Audio Settings");
|
||||
lv_obj_t *body = create_settings_body(content);
|
||||
|
||||
lv_obj_t *vol_label = lv_label_create(body);
|
||||
lv_label_set_text(vol_label, "Volume");
|
||||
lv_obj_set_pos(vol_label, 4, 4);
|
||||
lv_obj_set_size(vol_label, 80, 28);
|
||||
|
||||
s_volume_slider = lv_slider_create(body);
|
||||
lv_obj_set_pos(s_volume_slider, 88, 8);
|
||||
lv_obj_set_size(s_volume_slider, 100, 12);
|
||||
lv_slider_set_range(s_volume_slider, 0, 100);
|
||||
lv_slider_set_value(s_volume_slider, data->volume_pct, LV_ANIM_OFF);
|
||||
lv_obj_add_event_cb(s_volume_slider, settings_on_value_changed,
|
||||
LV_EVENT_VALUE_CHANGED,
|
||||
(void *)(intptr_t)SETTINGS_FIELD_VOLUME);
|
||||
|
||||
lv_obj_t *mute_label = lv_label_create(body);
|
||||
lv_label_set_text(mute_label, "Mute");
|
||||
lv_obj_set_pos(mute_label, 4, 40);
|
||||
lv_obj_set_size(mute_label, 80, 28);
|
||||
|
||||
s_mute_switch = lv_switch_create(body);
|
||||
lv_obj_set_pos(s_mute_switch, 180, 40);
|
||||
lv_obj_set_size(s_mute_switch, 40, 28);
|
||||
if (data->mute) {
|
||||
lv_obj_add_state(s_mute_switch, LV_STATE_CHECKED);
|
||||
}
|
||||
lv_obj_add_event_cb(s_mute_switch, settings_on_value_changed,
|
||||
LV_EVENT_VALUE_CHANGED,
|
||||
(void *)(intptr_t)SETTINGS_FIELD_MUTE);
|
||||
}
|
||||
|
||||
void load_network_settings(lv_obj_t *content, const settings_data_t *data)
|
||||
{
|
||||
(void)data;
|
||||
|
||||
create_status_bar(content, "Network Settings");
|
||||
lv_obj_t *body = create_settings_body(content);
|
||||
|
||||
lv_obj_t *wifi_label = lv_label_create(body);
|
||||
lv_label_set_text(wifi_label, "WiFi: Disabled");
|
||||
lv_obj_set_pos(wifi_label, 4, 4);
|
||||
lv_obj_set_size(wifi_label, 140, 28);
|
||||
|
||||
lv_obj_t *scan_btn = lv_button_create(body);
|
||||
lv_obj_set_pos(scan_btn, 4, 40);
|
||||
lv_obj_set_size(scan_btn, 80, 28);
|
||||
lv_obj_t *scan_label = lv_label_create(scan_btn);
|
||||
lv_label_set_text(scan_label, "Scan");
|
||||
lv_obj_center(scan_label);
|
||||
lv_obj_add_event_cb(scan_btn, settings_on_network_scan_clicked,
|
||||
LV_EVENT_CLICKED, NULL);
|
||||
}
|
||||
|
||||
void settings_tabs_collect(settings_tab_t tab, settings_data_t *out)
|
||||
{
|
||||
switch (tab) {
|
||||
case SETTINGS_TAB_SYSTEM:
|
||||
if (s_notif_switch != NULL) {
|
||||
out->notification_enabled =
|
||||
lv_obj_has_state(s_notif_switch, LV_STATE_CHECKED);
|
||||
}
|
||||
break;
|
||||
case SETTINGS_TAB_DISPLAY:
|
||||
if (s_brightness_slider != NULL) {
|
||||
out->brightness_pct =
|
||||
(uint8_t)lv_slider_get_value(s_brightness_slider);
|
||||
}
|
||||
break;
|
||||
case SETTINGS_TAB_AUDIO:
|
||||
if (s_volume_slider != NULL) {
|
||||
out->volume_pct = (uint8_t)lv_slider_get_value(s_volume_slider);
|
||||
}
|
||||
if (s_mute_switch != NULL) {
|
||||
out->mute = lv_obj_has_state(s_mute_switch, LV_STATE_CHECKED);
|
||||
}
|
||||
break;
|
||||
case SETTINGS_TAB_NETWORK:
|
||||
break;
|
||||
default:
|
||||
LV_ASSERT_MSG(false, "unexpected settings_tab_t");
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include "lvgl.h"
|
||||
#include "settings_types.h"
|
||||
|
||||
typedef enum {
|
||||
SETTINGS_FIELD_NOTIFICATION = 0,
|
||||
SETTINGS_FIELD_VOLUME,
|
||||
SETTINGS_FIELD_MUTE,
|
||||
} settings_field_t;
|
||||
|
||||
void load_system_settings(lv_obj_t *content, const settings_data_t *data);
|
||||
void load_display_settings(lv_obj_t *content, const settings_data_t *data);
|
||||
void load_audio_settings(lv_obj_t *content, const settings_data_t *data);
|
||||
void load_network_settings(lv_obj_t *content, const settings_data_t *data);
|
||||
|
||||
void settings_tabs_collect(settings_tab_t tab, settings_data_t *out);
|
||||
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
typedef enum {
|
||||
SETTINGS_TAB_SYSTEM = 0,
|
||||
SETTINGS_TAB_DISPLAY,
|
||||
SETTINGS_TAB_AUDIO,
|
||||
SETTINGS_TAB_NETWORK,
|
||||
} settings_tab_t;
|
||||
|
||||
typedef struct {
|
||||
bool notification_enabled;
|
||||
uint8_t brightness_pct;
|
||||
uint8_t volume_pct;
|
||||
bool mute;
|
||||
} settings_data_t;
|
||||
+3
-1
@@ -33,8 +33,9 @@ void ui_init(void)
|
||||
ui_Screen1_screen_init();
|
||||
ui_Screen2_screen_init();
|
||||
ui_Screen3_screen_init();
|
||||
ui_Settings_screen_init();
|
||||
ui____initial_actions0 = lv_obj_create(NULL);
|
||||
lv_disp_load_scr(ui_Screen3);
|
||||
lv_disp_load_scr(ui_Settings);
|
||||
}
|
||||
|
||||
void ui_destroy(void)
|
||||
@@ -42,4 +43,5 @@ void ui_destroy(void)
|
||||
ui_Screen1_screen_destroy();
|
||||
ui_Screen2_screen_destroy();
|
||||
ui_Screen3_screen_destroy();
|
||||
ui_Settings_screen_destroy();
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ extern "C" {
|
||||
#include "screens/ui_Screen1.h"
|
||||
#include "screens/ui_Screen2.h"
|
||||
#include "screens/ui_Screen3.h"
|
||||
#include "screens/ui_Settings.h"
|
||||
|
||||
///////////////////// VARIABLES ////////////////////
|
||||
|
||||
|
||||
Reference in New Issue
Block a user