From a2af95b92d5007e3d5579633620d7013072f371b Mon Sep 17 00:00:00 2001 From: Ken Van Hoeylandt Date: Tue, 16 Sep 2025 23:12:07 +0200 Subject: [PATCH] Merge develop into main (#338) ### Cardputer: - Fix keyboard issue with up/down button conflict when selecting switch - Fix backlight flickering ### UI improvements - Removed a 3 pixel border that went around the entire desktop environment - Improved system layout (GuiService) - Statusbar: improved layout (mainly margin/padding) - Toolbar: fixed margin/padding of all buttons, fixed alignment of all content - Improved layout/UI of many apps ### Other - Update LVGL to 9.3.0 official release (was dev version) --- Boards/M5stackCardputer/Source/InitBoot.cpp | 2 +- .../Source/devices/CardputerKeyboard.cpp | 20 +- Buildscripts/release-sdk.sh | 2 +- CMakeLists.txt | 11 +- Documentation/ideas.md | 6 +- Drivers/ST7789/Source/St7789Display.cpp | 15 +- Libraries/lvgl | 2 +- Libraries/lvgl_conf/lv_conf_kconfig.h | 244 ------------------ Tactility/Include/Tactility/lvgl/Statusbar.h | 8 +- .../Private/Tactility/app/filebrowser/View.h | 2 +- Tactility/Source/app/boot/Boot.cpp | 9 +- .../app/crashdiagnostics/CrashDiagnostics.cpp | 18 +- .../Source/app/development/Development.cpp | 46 ++-- Tactility/Source/app/display/Display.cpp | 37 ++- .../Source/app/filebrowser/FileBrowser.cpp | 2 +- Tactility/Source/app/filebrowser/View.cpp | 4 +- Tactility/Source/app/gpio/Gpio.cpp | 24 +- Tactility/Source/app/launcher/Launcher.cpp | 7 + .../app/localesettings/LocaleSettings.cpp | 23 +- Tactility/Source/app/log/Log.cpp | 19 +- .../Source/app/systeminfo/SystemInfo.cpp | 39 ++- .../app/wifiapsettings/WifiApSettings.cpp | 8 +- Tactility/Source/app/wificonnect/View.cpp | 38 +-- Tactility/Source/app/wifimanage/View.cpp | 105 +++++--- Tactility/Source/lvgl/Statusbar.cpp | 11 +- Tactility/Source/lvgl/Toolbar.cpp | 125 ++++++--- Tactility/Source/lvgl/wrappers/button.cpp | 1 + Tactility/Source/lvgl/wrappers/obj.cpp | 6 +- Tactility/Source/service/gui/GuiService.cpp | 19 +- .../lv_conf_simulator.h => lv_conf.h | 4 + 30 files changed, 362 insertions(+), 495 deletions(-) delete mode 100644 Libraries/lvgl_conf/lv_conf_kconfig.h rename Libraries/lvgl_conf/lv_conf_simulator.h => lv_conf.h (99%) diff --git a/Boards/M5stackCardputer/Source/InitBoot.cpp b/Boards/M5stackCardputer/Source/InitBoot.cpp index 601446d2..6975e94d 100644 --- a/Boards/M5stackCardputer/Source/InitBoot.cpp +++ b/Boards/M5stackCardputer/Source/InitBoot.cpp @@ -6,5 +6,5 @@ constexpr auto* TAG = "Cardputer"; bool initBoot() { TT_LOG_I(TAG, "initBoot"); - return driver::pwmbacklight::init(GPIO_NUM_38, 256); + return driver::pwmbacklight::init(GPIO_NUM_38, 512); } \ No newline at end of file diff --git a/Boards/M5stackCardputer/Source/devices/CardputerKeyboard.cpp b/Boards/M5stackCardputer/Source/devices/CardputerKeyboard.cpp index 6490d259..1e2a0a32 100644 --- a/Boards/M5stackCardputer/Source/devices/CardputerKeyboard.cpp +++ b/Boards/M5stackCardputer/Source/devices/CardputerKeyboard.cpp @@ -62,11 +62,23 @@ void CardputerKeyboard::readCallback(lv_indev_t* indev, lv_indev_data_t* data) { } else { for (auto& i : self->keyboard.keysState().values) { if (i == ';') { // Up - data->key = LV_KEY_UP; - data->state = LV_INDEV_STATE_PRESSED; + /* + * WARNING: + * lv_switch picks up on this and toggles it, while the CardputerEncoder uses it for scrolling. + * We disable the keypress so the encoder can work properly. + */ + // TODO: Can we detect the active widget and ignore it in case it's a switch? + // data->key = LV_KEY_UP; + // data->state = LV_INDEV_STATE_PRESSED; } else if (i == '.') { // Down - data->key = LV_KEY_DOWN; - data->state = LV_INDEV_STATE_PRESSED; + /* + * WARNING: + * lv_switch picks up on this and toggles it, while the CardputerEncoder uses it for scrolling. + * We disable the keypress so the encoder can work properly. + */ + // TODO: Can we detect the active widget and ignore it in case it's a switch? + // data->key = LV_KEY_DOWN; + // data->state = LV_INDEV_STATE_PRESSED; } else if (i == ',') { // Left data->key = LV_KEY_LEFT; data->state = LV_INDEV_STATE_PRESSED; diff --git a/Buildscripts/release-sdk.sh b/Buildscripts/release-sdk.sh index 501f09c7..e48e538e 100755 --- a/Buildscripts/release-sdk.sh +++ b/Buildscripts/release-sdk.sh @@ -36,7 +36,7 @@ cd - cp Libraries/lvgl/lvgl.h $find_target_dir cp Libraries/lvgl/lv_version.h $find_target_dir cp Libraries/lvgl/LICENCE.txt $lvgl_library_path/LICENSE.txt -cp Libraries/lvgl_conf/lv_conf_kconfig.h $lvgl_library_path/Include/lv_conf.h +cp Libraries/lvgl/src/lv_conf_kconfig.h $lvgl_library_path/Include/lv_conf.h # elf_loader elf_loader_library_path=$library_path/elf_loader diff --git a/CMakeLists.txt b/CMakeLists.txt index 91f27fc3..59a74c62 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -49,11 +49,12 @@ if (DEFINED ENV{ESP_IDF_VERSION}) set(EXCLUDE_COMPONENTS "Simulator") # LVGL - get_filename_component( - LVGL_CONFIG_FULL_PATH Libraries/lvgl_conf ABSOLUTE - ) +# set(LV_CONF_PATH Libraries/lvgl/src/lv_conf_kconfig.h) +# get_filename_component( +# LV_CONF_PATH Libraries/lvgl/src/lv_conf_kconfig.h ABSOLUTE +# ) +# add_compile_definitions(LV_CONF_PATH="${LVGL_CONFIG_FULL_PATH}") - add_compile_definitions(LV_CONF_PATH="${LVGL_CONFIG_FULL_PATH}/lv_conf_kconfig.h") idf_build_set_property(LINK_OPTIONS "-Wl,--wrap=esp_panic_handler" APPEND) idf_build_set_property(LINK_OPTIONS "-Wl,--wrap=esp_log_write" APPEND) idf_build_set_property(LINK_OPTIONS "-Wl,--wrap=lv_button_create" APPEND) @@ -111,8 +112,6 @@ if (NOT DEFINED ENV{ESP_IDF_VERSION}) # LVGL add_subdirectory(Libraries/lvgl) # Added as idf component for ESP and as library for other targets - include_directories(lvgl PUBLIC ${PROJECT_SOURCE_DIR}/Libraries/lvgl_conf) - target_compile_definitions(lvgl PUBLIC "-DLV_CONF_PATH=\"${PROJECT_SOURCE_DIR}/Libraries/lvgl_conf/lv_conf_simulator.h\"") target_link_libraries(lvgl PRIVATE SDL2-static) endif () diff --git a/Documentation/ideas.md b/Documentation/ideas.md index 856bc531..6f674894 100644 --- a/Documentation/ideas.md +++ b/Documentation/ideas.md @@ -2,6 +2,7 @@ ## Higher Priority +- Show a warning in the web installer when flashing CYD 28R board regarding v1/v2/v3 - Fix Development service: when no SD card is present, the app fails to install. Consider installing to `/data` Note: Change app install to "transfer file" functionality. We can have a proper install when we have app packaging. Note: Consider installation path option in interface @@ -15,12 +16,10 @@ - CrowPanel Basic 3.5": check why GraphicsDemo fails - CrowPanel Basic 3.5": check why System Info doesn't show storage info - Update to LVGL v9.3 stable -- Files app: delete folder recursively - Create `app::getSettingsPath()` to get paths to properties files by first trying sd card and then trying `/data` ## Medium Priority -- Implement `uninstall` action in `tactility.py` - Improve EspLcdDisplay to contain all the standard configuration options, and implement a default init function. Add a configuration class. - Statusbar icon that shows low/critical memory warnings - Make WiFi setup app that starts an access point and hosts a webpage to set up the device. @@ -29,13 +28,12 @@ - Try out ILI9342 https://github.com/jbrilha/esp_lcd_ili9342 - All drivers (e.g. display, touch, etc.) should call stop() in their destructor, or at least assert that they should not be running. - Bug: Turn on WiFi (when testing it wasn't connected/connecting - just active). Open chat. Observe crash. -- Toolbar: when the title doesn't fit, scroll the text instead of splitting it onto a new line (try on Waveshare 1.47") -- UI: create UI size classification (e.g. "compact" for tiny screens without touch) - Bug: Crash handling app cannot be exited with an EncoderDevice. (current work-around is to manually reset the device) - I2C app should show error when I2C port is disabled when the scan button was manually pressed ## Lower Priority +- Rename `filebrowser` to `files` and `FileBrowser.cpp` to `Files.cpp` - Implement system suspend that turns off the screen - The boot button on some devices can be used as GPIO_NUM_0 at runtime - Localize all apps diff --git a/Drivers/ST7789/Source/St7789Display.cpp b/Drivers/ST7789/Source/St7789Display.cpp index e3420cf6..3d1925c4 100644 --- a/Drivers/ST7789/Source/St7789Display.cpp +++ b/Drivers/ST7789/Source/St7789Display.cpp @@ -77,6 +77,14 @@ bool St7789Display::createPanelHandle(esp_lcd_panel_io_handle_t ioHandle, esp_lc return false; } + // Warning: it looks like LVGL rotation is broken when "gap" is set and the screen is moved to a non-default orientation + int gap_x = configuration->swapXY ? configuration->gapY : configuration->gapX; + int gap_y = configuration->swapXY ? configuration->gapX : configuration->gapY; + if (esp_lcd_panel_set_gap(panelHandle, gap_x, gap_y) != ESP_OK) { + TT_LOG_E(TAG, "Failed to set panel gap"); + return false; + } + if (esp_lcd_panel_swap_xy(panelHandle, configuration->swapXY) != ESP_OK) { TT_LOG_E(TAG, "Failed to swap XY "); return false; @@ -92,13 +100,6 @@ bool St7789Display::createPanelHandle(esp_lcd_panel_io_handle_t ioHandle, esp_lc return false; } - int gap_x = configuration->swapXY ? configuration->gapY : configuration->gapX; - int gap_y = configuration->swapXY ? configuration->gapX : configuration->gapY; - if (esp_lcd_panel_set_gap(panelHandle, gap_x, gap_y) != ESP_OK) { - TT_LOG_E(TAG, "Failed to set panel gap"); - return false; - } - return true; } diff --git a/Libraries/lvgl b/Libraries/lvgl index 6decbb7f..c033a98a 160000 --- a/Libraries/lvgl +++ b/Libraries/lvgl @@ -1 +1 @@ -Subproject commit 6decbb7f7783f6e48d4591fcb9f7810c2fb08e61 +Subproject commit c033a98afddd65aaafeebea625382a94020fe4a7 diff --git a/Libraries/lvgl_conf/lv_conf_kconfig.h b/Libraries/lvgl_conf/lv_conf_kconfig.h deleted file mode 100644 index 91c17872..00000000 --- a/Libraries/lvgl_conf/lv_conf_kconfig.h +++ /dev/null @@ -1,244 +0,0 @@ -/** * @file lv_conf_kconfig.h * Configs that need special handling when LVGL is used with Kconfig */ - -#ifndef LV_CONF_KCONFIG_CUSTOM_H -#define LV_CONF_KCONFIG_CUSTOM_H - -#define LV_CONF_H - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef LV_CONF_KCONFIG_EXTERNAL_INCLUDE -# include LV_CONF_KCONFIG_EXTERNAL_INCLUDE -#else - -# ifdef ESP_PLATFORM -# include "sdkconfig.h" -# include "esp_attr.h" -# endif - -# ifdef __NuttX__ -# include -# elif defined(__RTTHREAD__) -# define LV_CONF_INCLUDE_SIMPLE -# include -# endif - -#endif /*LV_CONF_KCONFIG_EXTERNAL_INCLUDE*/ - -/******************* - * LV_USE_STDLIB_MALLOC - *******************/ - -#ifdef CONFIG_LV_USE_BUILTIN_MALLOC -# define CONFIG_LV_USE_STDLIB_MALLOC LV_STDLIB_BUILTIN -#elif defined(CONFIG_LV_USE_CLIB_MALLOC) -# define CONFIG_LV_USE_STDLIB_MALLOC LV_STDLIB_CLIB -#elif defined(CONFIG_LV_USE_MICROPYTHON_MALLOC) -# define CONFIG_LV_USE_STDLIB_MALLOC LV_STDLIB_MICROPYTHON -#elif defined(CONFIG_LV_USE_RTTHREAD_MALLOC) -# define CONFIG_LV_USE_STDLIB_MALLOC LV_STDLIB_RTTHREAD -#elif defined (CONFIG_LV_USE_CUSTOM_MALLOC) -# define CONFIG_LV_USE_STDLIB_MALLOC LV_STDLIB_CUSTOM -#endif - -/******************* - * LV_USE_STDLIB_STRING - *******************/ - -#ifdef CONFIG_LV_USE_BUILTIN_STRING -# define CONFIG_LV_USE_STDLIB_STRING LV_STDLIB_BUILTIN -#elif defined(CONFIG_LV_USE_CLIB_STRING) -# define CONFIG_LV_USE_STDLIB_STRING LV_STDLIB_CLIB -#elif defined(CONFIG_LV_USE_MICROPYTHON_STRING) -# define CONFIG_LV_USE_STDLIB_STRING LV_STDLIB_MICROPYTHON -#elif defined(CONFIG_LV_USE_RTTHREAD_STRING) -# define CONFIG_LV_USE_STDLIB_STRING LV_STDLIB_RTTHREAD -#elif defined (CONFIG_LV_USE_CUSTOM_STRING) -# define CONFIG_LV_USE_STDLIB_STRING LV_STDLIB_CUSTOM -#endif - -/******************* - * LV_USE_STDLIB_SPRINTF - *******************/ - -#ifdef CONFIG_LV_USE_BUILTIN_SPRINTF -# define CONFIG_LV_USE_STDLIB_SPRINTF LV_STDLIB_BUILTIN -#elif defined(CONFIG_LV_USE_CLIB_SPRINTF) -# define CONFIG_LV_USE_STDLIB_SPRINTF LV_STDLIB_CLIB -#elif defined(CONFIG_LV_USE_MICROPYTHON_SPRINTF) -# define CONFIG_LV_USE_STDLIB_SPRINTF LV_STDLIB_MICROPYTHON -#elif defined(CONFIG_LV_USE_RTTHREAD_SPRINTF) -# define CONFIG_LV_USE_STDLIB_SPRINTF LV_STDLIB_RTTHREAD -#elif defined (CONFIG_LV_USE_CUSTOM_SPRINTF) -# define CONFIG_LV_USE_STDLIB_SPRINTF LV_STDLIB_CUSTOM -#endif - -/******************* - * LV_MEM_SIZE - *******************/ - -#ifdef CONFIG_LV_MEM_SIZE_KILOBYTES -# if(CONFIG_LV_MEM_SIZE_KILOBYTES < 2) -# error "LV_MEM_SIZE >= 2kB is required" -# endif - -# define CONFIG_LV_MEM_SIZE (CONFIG_LV_MEM_SIZE_KILOBYTES * 1024U) -#endif - -#ifdef CONFIG_LV_MEM_POOL_EXPAND_SIZE_KILOBYTES -# define CONFIG_LV_MEM_POOL_EXPAND_SIZE (CONFIG_LV_MEM_POOL_EXPAND_SIZE_KILOBYTES * 1024U) -#endif - -/*------------------ - * MONITOR POSITION - *-----------------*/ - -#ifdef CONFIG_LV_PERF_MONITOR_ALIGN_TOP_LEFT -# define CONFIG_LV_USE_PERF_MONITOR_POS LV_ALIGN_TOP_LEFT -#elif defined(CONFIG_LV_USE_PERF_MONITOR_ALIGN_TOP_MID) -# define CONFIG_LV_USE_PERF_MONITOR_POS LV_ALIGN_TOP_MID -#elif defined(CONFIG_LV_PERF_MONITOR_ALIGN_TOP_RIGHT) -# define CONFIG_LV_USE_PERF_MONITOR_POS LV_ALIGN_TOP_RIGHT -#elif defined(CONFIG_LV_PERF_MONITOR_ALIGN_BOTTOM_LEFT) -# define CONFIG_LV_USE_PERF_MONITOR_POS LV_ALIGN_BOTTOM_LEFT -#elif defined(CONFIG_LV_PERF_MONITOR_ALIGN_BOTTOM_MID) -# define CONFIG_LV_USE_PERF_MONITOR_POS LV_ALIGN_BOTTOM_MID -#elif defined(CONFIG_LV_PERF_MONITOR_ALIGN_BOTTOM_RIGHT) -# define CONFIG_LV_USE_PERF_MONITOR_POS LV_ALIGN_BOTTOM_RIGHT -#elif defined(CONFIG_LV_PERF_MONITOR_ALIGN_LEFT_MID) -# define CONFIG_LV_USE_PERF_MONITOR_POS LV_ALIGN_LEFT_MID -#elif defined(CONFIG_LV_PERF_MONITOR_ALIGN_RIGHT_MID) -# define CONFIG_LV_USE_PERF_MONITOR_POS LV_ALIGN_RIGHT_MID -#elif defined(CONFIG_LV_PERF_MONITOR_ALIGN_CENTER) -# define CONFIG_LV_USE_PERF_MONITOR_POS LV_ALIGN_CENTER -#endif - -#ifdef CONFIG_LV_MEM_MONITOR_ALIGN_TOP_LEFT -# define CONFIG_LV_USE_MEM_MONITOR_POS LV_ALIGN_TOP_LEFT -#elif defined(CONFIG_LV_USE_MEM_MONITOR_ALIGN_TOP_MID) -# define CONFIG_LV_USE_MEM_MONITOR_POS LV_ALIGN_TOP_MID -#elif defined(CONFIG_LV_MEM_MONITOR_ALIGN_TOP_RIGHT) -# define CONFIG_LV_USE_MEM_MONITOR_POS LV_ALIGN_TOP_RIGHT -#elif defined(CONFIG_LV_MEM_MONITOR_ALIGN_BOTTOM_LEFT) -# define CONFIG_LV_USE_MEM_MONITOR_POS LV_ALIGN_BOTTOM_LEFT -#elif defined(CONFIG_LV_MEM_MONITOR_ALIGN_BOTTOM_MID) -# define CONFIG_LV_USE_MEM_MONITOR_POS LV_ALIGN_BOTTOM_MID -#elif defined(CONFIG_LV_MEM_MONITOR_ALIGN_BOTTOM_RIGHT) -# define CONFIG_LV_USE_MEM_MONITOR_POS LV_ALIGN_BOTTOM_RIGHT -#elif defined(CONFIG_LV_MEM_MONITOR_ALIGN_LEFT_MID) -# define CONFIG_LV_USE_MEM_MONITOR_POS LV_ALIGN_LEFT_MID -#elif defined(CONFIG_LV_MEM_MONITOR_ALIGN_RIGHT_MID) -# define CONFIG_LV_USE_MEM_MONITOR_POS LV_ALIGN_RIGHT_MID -#elif defined(CONFIG_LV_MEM_MONITOR_ALIGN_CENTER) -# define CONFIG_LV_USE_MEM_MONITOR_POS LV_ALIGN_CENTER -#endif - -/******************** - * FONT SELECTION - *******************/ - -/** - * NOTE: In Kconfig instead of `LV_DEFAULT_FONT` - * `CONFIG_LV_FONT_DEFAULT_` is defined - * hence the large selection with if-s - */ - -/*------------------ - * DEFAULT FONT - *-----------------*/ -#ifdef CONFIG_LV_FONT_DEFAULT_MONTSERRAT_8 -# define CONFIG_LV_FONT_DEFAULT &lv_font_montserrat_8 -#elif defined(CONFIG_LV_FONT_DEFAULT_MONTSERRAT_10) -# define CONFIG_LV_FONT_DEFAULT &lv_font_montserrat_10 -#elif defined(CONFIG_LV_FONT_DEFAULT_MONTSERRAT_12) -# define CONFIG_LV_FONT_DEFAULT &lv_font_montserrat_12 -#elif defined(CONFIG_LV_FONT_DEFAULT_MONTSERRAT_14) -# define CONFIG_LV_FONT_DEFAULT &lv_font_montserrat_14 -#elif defined(CONFIG_LV_FONT_DEFAULT_MONTSERRAT_16) -# define CONFIG_LV_FONT_DEFAULT &lv_font_montserrat_16 -#elif defined(CONFIG_LV_FONT_DEFAULT_MONTSERRAT_18) -# define CONFIG_LV_FONT_DEFAULT &lv_font_montserrat_18 -#elif defined(CONFIG_LV_FONT_DEFAULT_MONTSERRAT_20) -# define CONFIG_LV_FONT_DEFAULT &lv_font_montserrat_20 -#elif defined(CONFIG_LV_FONT_DEFAULT_MONTSERRAT_22) -# define CONFIG_LV_FONT_DEFAULT &lv_font_montserrat_22 -#elif defined(CONFIG_LV_FONT_DEFAULT_MONTSERRAT_24) -# define CONFIG_LV_FONT_DEFAULT &lv_font_montserrat_24 -#elif defined(CONFIG_LV_FONT_DEFAULT_MONTSERRAT_26) -# define CONFIG_LV_FONT_DEFAULT &lv_font_montserrat_26 -#elif defined(CONFIG_LV_FONT_DEFAULT_MONTSERRAT_28) -# define CONFIG_LV_FONT_DEFAULT &lv_font_montserrat_28 -#elif defined(CONFIG_LV_FONT_DEFAULT_MONTSERRAT_30) -# define CONFIG_LV_FONT_DEFAULT &lv_font_montserrat_30 -#elif defined(CONFIG_LV_FONT_DEFAULT_MONTSERRAT_32) -# define CONFIG_LV_FONT_DEFAULT &lv_font_montserrat_32 -#elif defined(CONFIG_LV_FONT_DEFAULT_MONTSERRAT_34) -# define CONFIG_LV_FONT_DEFAULT &lv_font_montserrat_34 -#elif defined(CONFIG_LV_FONT_DEFAULT_MONTSERRAT_36) -# define CONFIG_LV_FONT_DEFAULT &lv_font_montserrat_36 -#elif defined(CONFIG_LV_FONT_DEFAULT_MONTSERRAT_38) -# define CONFIG_LV_FONT_DEFAULT &lv_font_montserrat_38 -#elif defined(CONFIG_LV_FONT_DEFAULT_MONTSERRAT_40) -# define CONFIG_LV_FONT_DEFAULT &lv_font_montserrat_40 -#elif defined(CONFIG_LV_FONT_DEFAULT_MONTSERRAT_42) -# define CONFIG_LV_FONT_DEFAULT &lv_font_montserrat_42 -#elif defined(CONFIG_LV_FONT_DEFAULT_MONTSERRAT_44) -# define CONFIG_LV_FONT_DEFAULT &lv_font_montserrat_44 -#elif defined(CONFIG_LV_FONT_DEFAULT_MONTSERRAT_46) -# define CONFIG_LV_FONT_DEFAULT &lv_font_montserrat_46 -#elif defined(CONFIG_LV_FONT_DEFAULT_MONTSERRAT_48) -# define CONFIG_LV_FONT_DEFAULT &lv_font_montserrat_48 -#elif defined(CONFIG_LV_FONT_DEFAULT_MONTSERRAT_12_SUBPX) -# define CONFIG_LV_FONT_DEFAULT &lv_font_montserrat_12_subpx -#elif defined(CONFIG_LV_FONT_DEFAULT_MONTSERRAT_28_COMPRESSED) -# define CONFIG_LV_FONT_DEFAULT &lv_font_montserrat_28_compressed -#elif defined(CONFIG_LV_FONT_DEFAULT_DEJAVU_16_PERSIAN_HEBREW) -# define CONFIG_LV_FONT_DEFAULT &lv_font_dejavu_16_persian_hebrew -#elif defined(CONFIG_LV_FONT_DEFAULT_SIMSUN_16_CJK) -# define CONFIG_LV_FONT_DEFAULT &lv_font_simsun_16_cjk -#elif defined(CONFIG_LV_FONT_DEFAULT_UNSCII_8) -# define CONFIG_LV_FONT_DEFAULT &lv_font_unscii_8 -#elif defined(CONFIG_LV_FONT_DEFAULT_UNSCII_16) -# define CONFIG_LV_FONT_DEFAULT &lv_font_unscii_16 -#endif - -/*------------------ - * TEXT ENCODING - *-----------------*/ -#ifdef CONFIG_LV_TXT_ENC_UTF8 -# define CONFIG_LV_TXT_ENC LV_TXT_ENC_UTF8 -#elif defined(CONFIG_LV_TXT_ENC_ASCII) -# define CONFIG_LV_TXT_ENC LV_TXT_ENC_ASCII -#endif - -/*------------------ - * BIDI DIRECTION - *-----------------*/ - -#ifdef CONFIG_LV_BASE_DIR_LTR -# define CONFIG_LV_BIDI_BASE_DIR_DEF LV_BASE_DIR_LTR -#elif defined(CONFIG_LV_BASE_DIR_RTL) -# define CONFIG_LV_BIDI_BASE_DIR_DEF LV_BASE_DIR_RTL -#elif defined(CONFIG_LV_BASE_DIR_AUTO) -# define CONFIG_LV_BIDI_BASE_DIR_DEF LV_BASE_DIR_AUTO -#endif - -/*------------------ - * LINUX FBDEV - *-----------------*/ - -#ifdef CONFIG_LV_LINUX_FBDEV_RENDER_MODE_PARTIAL -# define CONFIG_LV_LINUX_FBDEV_RENDER_MODE LV_DISPLAY_RENDER_MODE_PARTIAL -#elif defined(CONFIG_LV_LINUX_FBDEV_RENDER_MODE_DIRECT) -# define CONFIG_LV_LINUX_FBDEV_RENDER_MODE LV_DISPLAY_RENDER_MODE_DIRECT -#elif defined(CONFIG_LV_LINUX_FBDEV_RENDER_MODE_FULL) -# define CONFIG_LV_LINUX_FBDEV_RENDER_MODE LV_DISPLAY_RENDER_MODE_FULL -#endif - -#ifdef __cplusplus -} /*extern "C"*/ -#endif - -#endif /*LV_CONF_KCONFIG_H*/ diff --git a/Tactility/Include/Tactility/lvgl/Statusbar.h b/Tactility/Include/Tactility/lvgl/Statusbar.h index 180571f5..63e88f49 100644 --- a/Tactility/Include/Tactility/lvgl/Statusbar.h +++ b/Tactility/Include/Tactility/lvgl/Statusbar.h @@ -1,14 +1,14 @@ #pragma once -#include "Tactility/app/AppContext.h" +#include #include namespace tt::lvgl { -#define STATUSBAR_ICON_LIMIT 8 -#define STATUSBAR_ICON_SIZE 20 -#define STATUSBAR_HEIGHT (STATUSBAR_ICON_SIZE + 4) // 4 extra pixels for border and outline +constexpr auto STATUSBAR_ICON_LIMIT = 8; +constexpr auto STATUSBAR_ICON_SIZE = 20; +constexpr auto STATUSBAR_HEIGHT = STATUSBAR_ICON_SIZE + 2; lv_obj_t* statusbar_create(lv_obj_t* parent); int8_t statusbar_icon_add(const std::string& image); diff --git a/Tactility/Private/Tactility/app/filebrowser/View.h b/Tactility/Private/Tactility/app/filebrowser/View.h index bd1320b2..18e7915b 100644 --- a/Tactility/Private/Tactility/app/filebrowser/View.h +++ b/Tactility/Private/Tactility/app/filebrowser/View.h @@ -30,7 +30,7 @@ public: explicit View(const std::shared_ptr& state) : state(state) {} - void init(lv_obj_t* parent); + void init(const AppContext& appContext, lv_obj_t* parent); void update(); void onNavigateUpPressed(); diff --git a/Tactility/Source/app/boot/Boot.cpp b/Tactility/Source/app/boot/Boot.cpp index 6a62e121..dcf1e164 100644 --- a/Tactility/Source/app/boot/Boot.cpp +++ b/Tactility/Source/app/boot/Boot.cpp @@ -145,16 +145,19 @@ public: } void onShow(TT_UNUSED AppContext& app, lv_obj_t* parent) override { + lvgl::obj_set_style_bg_blacken(parent); + lv_obj_set_style_border_width(parent, 0, LV_STATE_DEFAULT); + lv_obj_set_style_radius(parent, 0, LV_STATE_DEFAULT); + auto* image = lv_image_create(parent); - lv_obj_set_size(image, LV_PCT(100), LV_PCT(100)); + lv_obj_set_size(image, LV_SIZE_CONTENT, LV_SIZE_CONTENT); + lv_obj_align(image, LV_ALIGN_CENTER, 0, 0); const auto paths = app.getPaths(); const char* logo = hal::usb::isUsbBootMode() ? "logo_usb.png" : "logo.png"; const auto logo_path = paths->getSystemPathLvgl(logo); TT_LOG_I(TAG, "%s", logo_path.c_str()); lv_image_set_src(image, logo_path.c_str()); - - lvgl::obj_set_style_bg_blacken(parent); } }; diff --git a/Tactility/Source/app/crashdiagnostics/CrashDiagnostics.cpp b/Tactility/Source/app/crashdiagnostics/CrashDiagnostics.cpp index 56ab3fbd..ea5a65d6 100644 --- a/Tactility/Source/app/crashdiagnostics/CrashDiagnostics.cpp +++ b/Tactility/Source/app/crashdiagnostics/CrashDiagnostics.cpp @@ -1,21 +1,21 @@ #ifdef ESP_PLATFORM -#include "Tactility/app/crashdiagnostics/QrHelpers.h" -#include "Tactility/app/crashdiagnostics/QrUrl.h" -#include "Tactility/app/launcher/Launcher.h" -#include "Tactility/lvgl/Statusbar.h" -#include "Tactility/service/loader/Loader.h" +#include +#include +#include +#include +#include #include #include -#define TAG "crash_diagnostics" +#define TAG "CrashDiagnostics" namespace tt::app::crashdiagnostics { void onContinuePressed(TT_UNUSED lv_event_t* event) { - tt::service::loader::stopApp(); - tt::app::launcher::start(); + service::loader::stopApp(); + launcher::start(); } class CrashDiagnosticsApp : public App { @@ -24,7 +24,7 @@ public: void onShow(AppContext& app, lv_obj_t* parent) override { auto* display = lv_obj_get_display(parent); - int32_t parent_height = lv_display_get_vertical_resolution(display) - STATUSBAR_HEIGHT; + int32_t parent_height = lv_display_get_vertical_resolution(display) - lvgl::STATUSBAR_HEIGHT; lv_obj_add_event_cb(parent, onContinuePressed, LV_EVENT_SHORT_CLICKED, nullptr); auto* top_label = lv_label_create(parent); diff --git a/Tactility/Source/app/development/Development.cpp b/Tactility/Source/app/development/Development.cpp index afe78a53..ef7f9111 100644 --- a/Tactility/Source/app/development/Development.cpp +++ b/Tactility/Source/app/development/Development.cpp @@ -108,45 +108,45 @@ public: // Wrappers - lv_obj_t* secondary_flex = lv_obj_create(parent); - lv_obj_set_width(secondary_flex, LV_PCT(100)); - lv_obj_set_flex_grow(secondary_flex, 1); - lv_obj_set_flex_flow(secondary_flex, LV_FLEX_FLOW_COLUMN); - lv_obj_set_style_border_width(secondary_flex, 0, 0); - lv_obj_set_style_pad_all(secondary_flex, 0, 0); - lv_obj_set_style_pad_gap(secondary_flex, 0, 0); - lvgl::obj_set_style_bg_invisible(secondary_flex); - - // align() methods don't work on flex, so we need this extra wrapper - lv_obj_t* wrapper = lv_obj_create(secondary_flex); - lv_obj_set_size(wrapper, LV_PCT(100), LV_SIZE_CONTENT); - lvgl::obj_set_style_bg_invisible(wrapper); - lv_obj_set_style_border_width(wrapper, 0, 0); + lv_obj_t* content_wrapper = lv_obj_create(parent); + lv_obj_set_width(content_wrapper, LV_PCT(100)); + lv_obj_set_flex_grow(content_wrapper, 1); + lv_obj_set_flex_flow(content_wrapper, LV_FLEX_FLOW_COLUMN); + lv_obj_set_style_border_width(content_wrapper, 0, LV_STATE_DEFAULT); + lvgl::obj_set_style_bg_invisible(content_wrapper); // Enable on boot - lv_obj_t* enable_label = lv_label_create(wrapper); - lv_label_set_text(enable_label, "Enable on boot"); - lv_obj_align(enable_label, LV_ALIGN_TOP_LEFT, 0, 6); + lv_obj_t* enable_wrapper = lv_obj_create(content_wrapper); + lv_obj_set_size(enable_wrapper, LV_PCT(100), LV_SIZE_CONTENT); + lvgl::obj_set_style_bg_invisible(enable_wrapper); + lv_obj_set_style_border_width(enable_wrapper, 0, LV_STATE_DEFAULT); + lv_obj_set_style_pad_all(enable_wrapper, 0, LV_STATE_DEFAULT); - enableOnBootSwitch = lv_switch_create(wrapper); + lv_obj_t* enable_label = lv_label_create(enable_wrapper); + lv_label_set_text(enable_label, "Enable on boot"); + lv_obj_align(enable_label, LV_ALIGN_LEFT_MID, 0, 0); + + enableOnBootSwitch = lv_switch_create(enable_wrapper); lv_obj_add_event_cb(enableOnBootSwitch, onEnableOnBootSwitchChanged, LV_EVENT_VALUE_CHANGED, this); - lv_obj_align(enableOnBootSwitch, LV_ALIGN_TOP_RIGHT, 0, 0); + lv_obj_align(enableOnBootSwitch, LV_ALIGN_RIGHT_MID, 0, 0); if (service::development::shouldEnableOnBoot()) { lv_obj_add_state(enableOnBootSwitch, LV_STATE_CHECKED); } else { lv_obj_remove_state(enableOnBootSwitch, LV_STATE_CHECKED); } - statusLabel = lv_label_create(wrapper); - lv_obj_align(statusLabel, LV_ALIGN_TOP_LEFT, 0, 50); + // Status - auto warning_label = lv_label_create(wrapper); + statusLabel = lv_label_create(content_wrapper); + + // Warning + + auto warning_label = lv_label_create(content_wrapper); lv_label_set_text(warning_label, "This feature is experimental and uses an unsecured http connection."); lv_obj_set_width(warning_label, LV_PCT(100)); lv_label_set_long_mode(warning_label, LV_LABEL_LONG_WRAP); lv_obj_set_style_text_color(warning_label, lv_color_make(0xff, 0xff, 00), LV_STATE_DEFAULT); - lv_obj_align(warning_label, LV_ALIGN_TOP_LEFT, 0, 80); updateViewState(); diff --git a/Tactility/Source/app/display/Display.cpp b/Tactility/Source/app/display/Display.cpp index 7280eb83..2820d5ba 100644 --- a/Tactility/Source/app/display/Display.cpp +++ b/Tactility/Source/app/display/Display.cpp @@ -65,6 +65,7 @@ public: void onShow(AppContext& app, lv_obj_t* parent) override { displaySettings = settings::display::loadOrGetDefault(); + auto ui_scale = hal::getConfiguration()->uiScale; lv_obj_set_flex_flow(parent, LV_FLEX_FLOW_COLUMN); lv_obj_set_style_pad_row(parent, 0, LV_STATE_DEFAULT); @@ -79,39 +80,49 @@ public: lv_obj_set_width(main_wrapper, LV_PCT(100)); lv_obj_set_flex_grow(main_wrapper, 1); + // Backlight slider + if (hal_display->supportsBacklightDuty()) { auto* brightness_wrapper = lv_obj_create(main_wrapper); lv_obj_set_size(brightness_wrapper, LV_PCT(100), LV_SIZE_CONTENT); - lv_obj_set_style_pad_hor(brightness_wrapper, 0, 0); - lv_obj_set_style_pad_ver(brightness_wrapper, 6, 0); - lv_obj_set_style_border_width(brightness_wrapper, 0, 0); + lv_obj_set_style_pad_hor(brightness_wrapper, 0, LV_STATE_DEFAULT); + lv_obj_set_style_border_width(brightness_wrapper, 0, LV_STATE_DEFAULT); + if (ui_scale != hal::UiScale::Smallest) { + lv_obj_set_style_pad_ver(brightness_wrapper, 4, LV_STATE_DEFAULT); + } auto* brightness_label = lv_label_create(brightness_wrapper); lv_label_set_text(brightness_label, "Brightness"); + lv_obj_align(brightness_label, LV_ALIGN_LEFT_MID, 0, 0); auto* brightness_slider = lv_slider_create(brightness_wrapper); lv_obj_set_width(brightness_slider, LV_PCT(50)); - lv_obj_align(brightness_slider, LV_ALIGN_TOP_RIGHT, -8, 0); + lv_obj_align(brightness_slider, LV_ALIGN_RIGHT_MID, 0, 0); lv_slider_set_range(brightness_slider, 0, 255); lv_obj_add_event_cb(brightness_slider, onBacklightSliderEvent, LV_EVENT_VALUE_CHANGED, this); lv_slider_set_value(brightness_slider, displaySettings.backlightDuty, LV_ANIM_OFF); } + // Gamma slider + if (hal_display->getGammaCurveCount() > 0) { auto* gamma_wrapper = lv_obj_create(main_wrapper); lv_obj_set_size(gamma_wrapper, LV_PCT(100), LV_SIZE_CONTENT); - lv_obj_set_style_pad_hor(gamma_wrapper, 0, 0); - lv_obj_set_style_pad_ver(gamma_wrapper, 6, 0); - lv_obj_set_style_border_width(gamma_wrapper, 0, 0); + lv_obj_set_style_pad_hor(gamma_wrapper, 0, LV_STATE_DEFAULT); + lv_obj_set_style_border_width(gamma_wrapper, 0, LV_STATE_DEFAULT); + if (ui_scale != hal::UiScale::Smallest) { + lv_obj_set_style_pad_ver(gamma_wrapper, 4, LV_STATE_DEFAULT); + } auto* gamma_label = lv_label_create(gamma_wrapper); lv_label_set_text(gamma_label, "Gamma"); + lv_obj_align(gamma_label, LV_ALIGN_LEFT_MID, 0, 0); lv_obj_set_y(gamma_label, 0); auto* gamma_slider = lv_slider_create(gamma_wrapper); lv_obj_set_width(gamma_slider, LV_PCT(50)); - lv_obj_align(gamma_slider, LV_ALIGN_TOP_RIGHT, -8, 0); + lv_obj_align(gamma_slider, LV_ALIGN_RIGHT_MID, 0, 0); lv_slider_set_range(gamma_slider, 0, hal_display->getGammaCurveCount()); lv_obj_add_event_cb(gamma_slider, onGammaSliderEvent, LV_EVENT_VALUE_CHANGED, this); @@ -119,19 +130,21 @@ public: lv_slider_set_value(gamma_slider, curve_index, LV_ANIM_OFF); } + // Orientation + auto* orientation_wrapper = lv_obj_create(main_wrapper); lv_obj_set_size(orientation_wrapper, LV_PCT(100), LV_SIZE_CONTENT); - lv_obj_set_style_pad_all(orientation_wrapper, 0, 0); - lv_obj_set_style_border_width(orientation_wrapper, 0, 0); + lv_obj_set_style_pad_all(orientation_wrapper, 0, LV_STATE_DEFAULT); + lv_obj_set_style_border_width(orientation_wrapper, 0, LV_STATE_DEFAULT); auto* orientation_label = lv_label_create(orientation_wrapper); lv_label_set_text(orientation_label, "Orientation"); - lv_obj_align(orientation_label, LV_ALIGN_TOP_LEFT, 0, 8); + lv_obj_align(orientation_label, LV_ALIGN_LEFT_MID, 0, 0); auto* orientation_dropdown = lv_dropdown_create(orientation_wrapper); // Note: order correlates with settings::display::Orientation item order lv_dropdown_set_options(orientation_dropdown, "Landscape\nPortrait Right\nLandscape Flipped\nPortrait Left"); - lv_obj_align(orientation_dropdown, LV_ALIGN_TOP_RIGHT, 0, 0); + lv_obj_align(orientation_dropdown, LV_ALIGN_RIGHT_MID, 0, 0); lv_obj_set_style_border_color(orientation_dropdown, lv_color_hex(0xFAFAFA), LV_PART_MAIN); lv_obj_set_style_border_width(orientation_dropdown, 1, LV_PART_MAIN); lv_obj_add_event_cb(orientation_dropdown, onOrientationSet, LV_EVENT_VALUE_CHANGED, this); diff --git a/Tactility/Source/app/filebrowser/FileBrowser.cpp b/Tactility/Source/app/filebrowser/FileBrowser.cpp index e2e4c6f8..f74f7820 100644 --- a/Tactility/Source/app/filebrowser/FileBrowser.cpp +++ b/Tactility/Source/app/filebrowser/FileBrowser.cpp @@ -24,7 +24,7 @@ public: } void onShow(AppContext& appContext, lv_obj_t* parent) override { - view->init(parent); + view->init(appContext, parent); } void onResult(AppContext& appContext, TT_UNUSED LaunchId launchId, Result result, std::unique_ptr bundle) override { diff --git a/Tactility/Source/app/filebrowser/View.cpp b/Tactility/Source/app/filebrowser/View.cpp index 95983185..ddfdbb53 100644 --- a/Tactility/Source/app/filebrowser/View.cpp +++ b/Tactility/Source/app/filebrowser/View.cpp @@ -255,11 +255,11 @@ void View::update() { } } -void View::init(lv_obj_t* parent) { +void View::init(const AppContext& appContext, lv_obj_t* parent) { lv_obj_set_flex_flow(parent, LV_FLEX_FLOW_COLUMN); lv_obj_set_style_pad_row(parent, 0, LV_STATE_DEFAULT); - auto* toolbar = lvgl::toolbar_create(parent, "Files"); + auto* toolbar = lvgl::toolbar_create(parent, appContext); navigate_up_button = lvgl::toolbar_add_button_action(toolbar, LV_SYMBOL_UP, &onNavigateUpPressedCallback, this); auto* wrapper = lv_obj_create(parent); diff --git a/Tactility/Source/app/gpio/Gpio.cpp b/Tactility/Source/app/gpio/Gpio.cpp index f72cb270..14bc2d64 100644 --- a/Tactility/Source/app/gpio/Gpio.cpp +++ b/Tactility/Source/app/gpio/Gpio.cpp @@ -1,4 +1,4 @@ -#include "Tactility/service/loader/Loader.h" +#include #include #include #include "Tactility/lvgl/Toolbar.h" @@ -119,11 +119,17 @@ void GpioApp::onShow(AppContext& app, lv_obj_t* parent) { lv_obj_align(toolbar, LV_ALIGN_TOP_MID, 0, 0); // Main content wrapper, enables scrolling content without scrolling the toolbar - auto* wrapper = lv_obj_create(parent); - lv_obj_set_width(wrapper, LV_PCT(100)); - lv_obj_set_flex_grow(wrapper, 1); - lv_obj_set_style_border_width(wrapper, 0, LV_STATE_DEFAULT); - lv_obj_set_style_pad_all(wrapper, 0, LV_STATE_DEFAULT); + auto* expansion_wrapper = lv_obj_create(parent); + lv_obj_set_width(expansion_wrapper, LV_PCT(100)); + lv_obj_set_flex_grow(expansion_wrapper, 1); + lv_obj_set_style_border_width(expansion_wrapper, 0, LV_STATE_DEFAULT); + lv_obj_set_style_pad_all(expansion_wrapper, 0, LV_STATE_DEFAULT); + + auto* centering_wrapper = lv_obj_create(expansion_wrapper); + lv_obj_set_size(centering_wrapper, LV_SIZE_CONTENT, LV_SIZE_CONTENT); + lv_obj_set_align(centering_wrapper, LV_ALIGN_CENTER); + lv_obj_set_style_border_width(centering_wrapper, 0, LV_STATE_DEFAULT); + lv_obj_set_style_pad_all(centering_wrapper, 0, LV_STATE_DEFAULT); auto* display = lv_obj_get_display(parent); auto horizontal_px = lv_display_get_horizontal_resolution(display); @@ -134,14 +140,14 @@ void GpioApp::onShow(AppContext& app, lv_obj_t* parent) { const auto square_spacing = getSquareSpacing(ui_scale); int32_t x_spacing = block_width + square_spacing; uint8_t column = 0; - const uint8_t offset_from_left_label = 4; const uint8_t column_limit = is_landscape_display ? 10 : 5; - auto* row_wrapper = createGpioRowWrapper(wrapper); + auto* row_wrapper = createGpioRowWrapper(centering_wrapper); lv_obj_align(row_wrapper, LV_ALIGN_TOP_MID, 0, 0); mutex.lock(); for (int i = GPIO_NUM_MIN; i < GPIO_NUM_MAX; ++i) { + constexpr uint8_t offset_from_left_label = 4; // Add the GPIO number before the first item on a row if (column == 0) { @@ -165,7 +171,7 @@ void GpioApp::onShow(AppContext& app, lv_obj_t* parent) { lv_obj_set_pos(postfix, (column + 1) * x_spacing + offset_from_left_label, 0); // Add a new row wrapper underneath the last one - auto* new_row_wrapper = createGpioRowWrapper(wrapper); + auto* new_row_wrapper = createGpioRowWrapper(centering_wrapper); lv_obj_align_to(new_row_wrapper, row_wrapper, LV_ALIGN_BOTTOM_LEFT, 0, square_spacing); row_wrapper = new_row_wrapper; diff --git a/Tactility/Source/app/launcher/Launcher.cpp b/Tactility/Source/app/launcher/Launcher.cpp index 3189899a..c717b570 100644 --- a/Tactility/Source/app/launcher/Launcher.cpp +++ b/Tactility/Source/app/launcher/Launcher.cpp @@ -91,6 +91,13 @@ public: lv_obj_set_style_border_width(buttons_wrapper, 0, LV_STATE_DEFAULT); lv_obj_set_flex_grow(buttons_wrapper, 1); + // Fix for button selection (problem with UiScale::Small on Cardputer) + if (!hal::hasDevice(hal::Device::Type::Touch)) { + lv_obj_set_style_pad_all(buttons_wrapper, 6, LV_STATE_DEFAULT); + } else { + lv_obj_set_style_pad_all(buttons_wrapper, 0, LV_STATE_DEFAULT); + } + const auto* display = lv_obj_get_display(parent); const auto horizontal_px = lv_display_get_horizontal_resolution(display); const auto vertical_px = lv_display_get_vertical_resolution(display); diff --git a/Tactility/Source/app/localesettings/LocaleSettings.cpp b/Tactility/Source/app/localesettings/LocaleSettings.cpp index cd50b16c..9004f688 100644 --- a/Tactility/Source/app/localesettings/LocaleSettings.cpp +++ b/Tactility/Source/app/localesettings/LocaleSettings.cpp @@ -82,6 +82,8 @@ class LocaleSettingsApp : public App { public: void onShow(AppContext& app, lv_obj_t* parent) override { + auto ui_scale = hal::getConfiguration()->uiScale; + textResources.load(); lv_obj_set_flex_flow(parent, LV_FLEX_FLOW_COLUMN); @@ -94,6 +96,8 @@ public: lv_obj_set_width(main_wrapper, LV_PCT(100)); lv_obj_set_flex_grow(main_wrapper, 1); + // Region + auto* region_wrapper = lv_obj_create(main_wrapper); lv_obj_set_width(region_wrapper, LV_PCT(100)); lv_obj_set_height(region_wrapper, LV_SIZE_CONTENT); @@ -104,20 +108,23 @@ public: lv_label_set_text(regionLabel , textResources[i18n::Text::REGION].c_str()); lv_obj_align(regionLabel , LV_ALIGN_LEFT_MID, 0, 0); + auto* region_button = lv_button_create(region_wrapper); + lv_obj_align(region_button, LV_ALIGN_RIGHT_MID, 0, 0); + auto* region_button_image = lv_image_create(region_button); + lv_obj_add_event_cb(region_button, onConfigureTimeZonePressed, LV_EVENT_SHORT_CLICKED, nullptr); + lv_image_set_src(region_button_image, LV_SYMBOL_SETTINGS); + timeZoneLabel = lv_label_create(region_wrapper); std::string timeZoneName = settings::getTimeZoneName(); if (timeZoneName.empty()) { timeZoneName = "not set"; } - lv_label_set_text(timeZoneLabel, timeZoneName.c_str()); - // TODO: Find out why Y offset is needed - lv_obj_align_to(timeZoneLabel, regionLabel, LV_ALIGN_OUT_RIGHT_MID, 10, 8); - auto* region_button = lv_button_create(region_wrapper); - lv_obj_align(region_button, LV_ALIGN_TOP_RIGHT, 0, 0); - auto* region_button_image = lv_image_create(region_button); - lv_obj_add_event_cb(region_button, onConfigureTimeZonePressed, LV_EVENT_SHORT_CLICKED, nullptr); - lv_image_set_src(region_button_image, LV_SYMBOL_SETTINGS); + lv_label_set_text(timeZoneLabel, timeZoneName.c_str()); + const int offset = ui_scale == hal::UiScale::Smallest ? -2 : -10; + lv_obj_align_to(timeZoneLabel, region_button, LV_ALIGN_OUT_LEFT_MID, offset, 0); + + // Language auto* language_wrapper = lv_obj_create(main_wrapper); lv_obj_set_width(language_wrapper, LV_PCT(100)); diff --git a/Tactility/Source/app/log/Log.cpp b/Tactility/Source/app/log/Log.cpp index 6a957a3e..9aa33b4e 100644 --- a/Tactility/Source/app/log/Log.cpp +++ b/Tactility/Source/app/log/Log.cpp @@ -1,8 +1,8 @@ -#include "Tactility/app/selectiondialog/SelectionDialog.h" -#include "Tactility/lvgl/Style.h" -#include "Tactility/lvgl/Toolbar.h" -#include "Tactility/lvgl/LvglSync.h" -#include "Tactility/service/loader/Loader.h" +#include +#include +#include +#include +#include #include #include @@ -10,18 +10,16 @@ #include -#define TAG "text_viewer" - namespace tt::app::log { class LogApp : public App { -private: + static constexpr auto* TAG = "LogApp"; LogLevel filterLevel = LogLevel::Info; lv_obj_t* labelWidget = nullptr; - static inline bool shouldShowLog(LogLevel filterLevel, LogLevel logLevel) { + static bool shouldShowLog(LogLevel filterLevel, LogLevel logLevel) { return filterLevel >= logLevel; } @@ -67,7 +65,8 @@ private: "Warning", "Error", }; - app::selectiondialog::start("Log Level", items); + + selectiondialog::start("Log Level", items); } public: diff --git a/Tactility/Source/app/systeminfo/SystemInfo.cpp b/Tactility/Source/app/systeminfo/SystemInfo.cpp index 37da31ac..6c7546c4 100644 --- a/Tactility/Source/app/systeminfo/SystemInfo.cpp +++ b/Tactility/Source/app/systeminfo/SystemInfo.cpp @@ -1,5 +1,5 @@ -#include "Tactility/TactilityConfig.h" -#include "Tactility/lvgl/Toolbar.h" +#include +#include #include #include @@ -106,8 +106,8 @@ static void addMemoryBar(lv_obj_t* parent, const char* label, uint64_t free, uin uint64_t used = total - free; auto* container = lv_obj_create(parent); lv_obj_set_size(container, LV_PCT(100), LV_SIZE_CONTENT); - lv_obj_set_style_pad_all(container, 0, 0); - lv_obj_set_style_border_width(container, 0, 0); + lv_obj_set_style_pad_all(container, 0, LV_STATE_DEFAULT); + lv_obj_set_style_border_width(container, 0, LV_STATE_DEFAULT); lv_obj_set_flex_flow(container, LV_FLEX_FLOW_ROW); lv_obj_set_style_bg_opa(container, 0, LV_STATE_DEFAULT); @@ -203,7 +203,15 @@ static void addDevices(lv_obj_t* parent) { } } -class SystemInfoApp : public App { +static lv_obj_t* createTab(lv_obj_t* tabview, const char* name) { + auto* tab = lv_tabview_add_tab(tabview, name); + lv_obj_set_flex_flow(tab, LV_FLEX_FLOW_COLUMN); + lv_obj_set_style_pad_row(tab, 0, LV_STATE_DEFAULT); + lv_obj_set_style_border_width(tab, 0, LV_STATE_DEFAULT); + return tab; +} + +class SystemInfoApp final : public App { void onShow(AppContext& app, lv_obj_t* parent) override { lv_obj_set_flex_flow(parent, LV_FLEX_FLOW_COLUMN); @@ -212,7 +220,7 @@ class SystemInfoApp : public App { // This wrapper automatically has its children added vertically underneath eachother auto* wrapper = lv_obj_create(parent); - lv_obj_set_style_border_width(wrapper, 0, 0); + lv_obj_set_style_border_width(wrapper, 0, LV_STATE_DEFAULT); lv_obj_set_flex_flow(wrapper, LV_FLEX_FLOW_COLUMN); lv_obj_set_width(wrapper, LV_PCT(100)); lv_obj_set_flex_grow(wrapper, 1); @@ -224,20 +232,11 @@ class SystemInfoApp : public App { // Tabs - auto* memory_tab = lv_tabview_add_tab(tabview, "Memory"); - lv_obj_set_flex_flow(memory_tab, LV_FLEX_FLOW_COLUMN); - lv_obj_set_style_pad_row(memory_tab, 0, LV_STATE_DEFAULT); - auto* storage_tab = lv_tabview_add_tab(tabview, "Storage"); - lv_obj_set_flex_flow(storage_tab, LV_FLEX_FLOW_COLUMN); - lv_obj_set_style_pad_row(storage_tab, 0, LV_STATE_DEFAULT); - auto* tasks_tab = lv_tabview_add_tab(tabview, "Tasks"); - lv_obj_set_flex_flow(tasks_tab, LV_FLEX_FLOW_COLUMN); - lv_obj_set_style_pad_row(tasks_tab, 4, LV_STATE_DEFAULT); - auto* devices_tab = lv_tabview_add_tab(tabview, "Devices"); - lv_obj_set_flex_flow(devices_tab, LV_FLEX_FLOW_COLUMN); - lv_obj_set_style_pad_row(devices_tab, 4, LV_STATE_DEFAULT); - auto* about_tab = lv_tabview_add_tab(tabview, "About"); - lv_obj_set_flex_flow(about_tab, LV_FLEX_FLOW_COLUMN); + auto* memory_tab = createTab(tabview, "Memory"); + auto* storage_tab = createTab(tabview, "Storage"); + auto* tasks_tab = createTab(tabview, "Tasks"); + auto* devices_tab = createTab(tabview, "Devices"); + auto* about_tab = createTab(tabview, "About"); // Memory tab content diff --git a/Tactility/Source/app/wifiapsettings/WifiApSettings.cpp b/Tactility/Source/app/wifiapsettings/WifiApSettings.cpp index 1ea8e3bc..014c7d6a 100644 --- a/Tactility/Source/app/wifiapsettings/WifiApSettings.cpp +++ b/Tactility/Source/app/wifiapsettings/WifiApSettings.cpp @@ -80,16 +80,16 @@ class WifiApSettings : public App { auto* auto_connect_wrapper = lv_obj_create(wrapper); lv_obj_set_size(auto_connect_wrapper, LV_PCT(100), LV_SIZE_CONTENT); - lv_obj_set_style_pad_all(auto_connect_wrapper, 0, 0); - lv_obj_set_style_pad_gap(auto_connect_wrapper, 0, 0); - lv_obj_set_style_border_width(auto_connect_wrapper, 0, 0); + lv_obj_set_style_pad_all(auto_connect_wrapper, 0, LV_STATE_DEFAULT); + lv_obj_set_style_pad_gap(auto_connect_wrapper, 0, LV_STATE_DEFAULT); + lv_obj_set_style_border_width(auto_connect_wrapper, 0, LV_STATE_DEFAULT); auto* auto_connect_label = lv_label_create(auto_connect_wrapper); lv_label_set_text(auto_connect_label, "Auto-connect"); lv_obj_align(auto_connect_label, LV_ALIGN_TOP_LEFT, 0, 6); auto* auto_connect_switch = lv_switch_create(auto_connect_wrapper); - lv_obj_add_event_cb(auto_connect_switch, onToggleAutoConnect, LV_EVENT_VALUE_CHANGED, (void*)&paremeters); + lv_obj_add_event_cb(auto_connect_switch, onToggleAutoConnect, LV_EVENT_VALUE_CHANGED, &paremeters); lv_obj_align(auto_connect_switch, LV_ALIGN_TOP_RIGHT, 0, 0); auto* forget_button = lv_button_create(wrapper); diff --git a/Tactility/Source/app/wificonnect/View.cpp b/Tactility/Source/app/wificonnect/View.cpp index 5fd121bc..a9fef193 100644 --- a/Tactility/Source/app/wificonnect/View.cpp +++ b/Tactility/Source/app/wificonnect/View.cpp @@ -83,9 +83,9 @@ void View::createBottomButtons(lv_obj_t* parent) { auto* button_container = lv_obj_create(parent); lv_obj_set_width(button_container, LV_PCT(100)); lv_obj_set_height(button_container, LV_SIZE_CONTENT); - lv_obj_set_style_pad_all(button_container, 0, 0); - lv_obj_set_style_pad_gap(button_container, 0, 0); - lv_obj_set_style_border_width(button_container, 0, 0); + lv_obj_set_style_pad_all(button_container, 0, LV_STATE_DEFAULT); + lv_obj_set_style_pad_gap(button_container, 0, LV_STATE_DEFAULT); + lv_obj_set_style_border_width(button_container, 0, LV_STATE_DEFAULT); remember_switch = lv_switch_create(button_container); lv_obj_add_state(remember_switch, LV_STATE_CHECKED); @@ -124,17 +124,17 @@ void View::init(AppContext& app, lv_obj_t* parent) { auto* ssid_wrapper = lv_obj_create(wrapper); lv_obj_set_width(ssid_wrapper, LV_PCT(100)); lv_obj_set_height(ssid_wrapper, LV_SIZE_CONTENT); - lv_obj_set_style_pad_all(ssid_wrapper, 0, 0); - lv_obj_set_style_pad_gap(ssid_wrapper, 0, 0); - lv_obj_set_style_border_width(ssid_wrapper, 0, 0); + lv_obj_set_style_pad_all(ssid_wrapper, 0, LV_STATE_DEFAULT); + lv_obj_set_style_pad_gap(ssid_wrapper, 0, LV_STATE_DEFAULT); + lv_obj_set_style_border_width(ssid_wrapper, 0, LV_STATE_DEFAULT); auto* ssid_label_wrapper = lv_obj_create(ssid_wrapper); lv_obj_set_width(ssid_label_wrapper, LV_PCT(50)); lv_obj_set_height(ssid_label_wrapper, LV_SIZE_CONTENT); - lv_obj_align(ssid_label_wrapper, LV_ALIGN_LEFT_MID, 0, 0); - lv_obj_set_style_border_width(ssid_label_wrapper, 0, 0); - lv_obj_set_style_pad_left(ssid_label_wrapper, 0, 0); - lv_obj_set_style_pad_right(ssid_label_wrapper, 0, 0); + lv_obj_align(ssid_label_wrapper, LV_ALIGN_LEFT_MID, 0, LV_STATE_DEFAULT); + lv_obj_set_style_border_width(ssid_label_wrapper, 0, LV_STATE_DEFAULT); + lv_obj_set_style_pad_left(ssid_label_wrapper, 0, LV_STATE_DEFAULT); + lv_obj_set_style_pad_right(ssid_label_wrapper, 0, LV_STATE_DEFAULT); auto* ssid_label = lv_label_create(ssid_label_wrapper); lv_label_set_text(ssid_label, "Network:"); @@ -145,7 +145,7 @@ void View::init(AppContext& app, lv_obj_t* parent) { lv_obj_set_width(ssid_textarea, LV_PCT(50)); ssid_error = lv_label_create(wrapper); - lv_obj_set_style_text_color(ssid_error, lv_color_make(255, 50, 50), 0); + lv_obj_set_style_text_color(ssid_error, lv_color_make(255, 50, 50), LV_STATE_DEFAULT); lv_obj_add_flag(ssid_error, LV_OBJ_FLAG_HIDDEN); // Password @@ -153,17 +153,17 @@ void View::init(AppContext& app, lv_obj_t* parent) { auto* password_wrapper = lv_obj_create(wrapper); lv_obj_set_width(password_wrapper, LV_PCT(100)); lv_obj_set_height(password_wrapper, LV_SIZE_CONTENT); - lv_obj_set_style_pad_all(password_wrapper, 0, 0); - lv_obj_set_style_pad_gap(password_wrapper, 0, 0); - lv_obj_set_style_border_width(password_wrapper, 0, 0); + lv_obj_set_style_pad_all(password_wrapper, 0, LV_STATE_DEFAULT); + lv_obj_set_style_pad_gap(password_wrapper, 0, LV_STATE_DEFAULT); + lv_obj_set_style_border_width(password_wrapper, 0, LV_STATE_DEFAULT); auto* password_label_wrapper = lv_obj_create(password_wrapper); lv_obj_set_width(password_label_wrapper, LV_PCT(50)); lv_obj_set_height(password_label_wrapper, LV_SIZE_CONTENT); lv_obj_align_to(password_label_wrapper, password_wrapper, LV_ALIGN_LEFT_MID, 0, 0); - lv_obj_set_style_border_width(password_label_wrapper, 0, 0); - lv_obj_set_style_pad_left(password_label_wrapper, 0, 0); - lv_obj_set_style_pad_right(password_label_wrapper, 0, 0); + lv_obj_set_style_border_width(password_label_wrapper, 0, LV_STATE_DEFAULT); + lv_obj_set_style_pad_left(password_label_wrapper, 0, LV_STATE_DEFAULT); + lv_obj_set_style_pad_right(password_label_wrapper, 0, LV_STATE_DEFAULT); auto* password_label = lv_label_create(password_label_wrapper); lv_label_set_text(password_label, "Password:"); @@ -175,12 +175,12 @@ void View::init(AppContext& app, lv_obj_t* parent) { lv_obj_set_width(password_textarea, LV_PCT(50)); password_error = lv_label_create(wrapper); - lv_obj_set_style_text_color(password_error, lv_color_make(255, 50, 50), 0); + lv_obj_set_style_text_color(password_error, lv_color_make(255, 50, 50), LV_STATE_DEFAULT); lv_obj_add_flag(password_error, LV_OBJ_FLAG_HIDDEN); // Connection error connection_error = lv_label_create(wrapper); - lv_obj_set_style_text_color(connection_error, lv_color_make(255, 50, 50), 0); + lv_obj_set_style_text_color(connection_error, lv_color_make(255, 50, 50), LV_STATE_DEFAULT); lv_obj_add_flag(connection_error, LV_OBJ_FLAG_HIDDEN); // Bottom buttons diff --git a/Tactility/Source/app/wifimanage/View.cpp b/Tactility/Source/app/wifimanage/View.cpp index 14055218..6548437a 100644 --- a/Tactility/Source/app/wifimanage/View.cpp +++ b/Tactility/Source/app/wifimanage/View.cpp @@ -95,14 +95,16 @@ static void showDetails(lv_event_t* event) { } void View::createSsidListItem(const service::wifi::ApRecord& record, bool isConnecting) { + auto ui_scale = hal::getConfiguration()->uiScale; + auto* wrapper = lv_obj_create(networks_list); lv_obj_add_event_cb(wrapper, &connect, LV_EVENT_SHORT_CLICKED, bindings); lv_obj_set_user_data(wrapper, bindings); lv_obj_set_size(wrapper, LV_PCT(100), LV_SIZE_CONTENT); - lv_obj_set_style_pad_all(wrapper, 0, 0); - lv_obj_set_style_pad_gap(wrapper, 0, 0); - lv_obj_set_style_margin_all(wrapper, 0, 0); - lv_obj_set_style_border_width(wrapper, 0, 0); + lv_obj_set_style_pad_all(wrapper, 0, LV_STATE_DEFAULT); + lv_obj_set_style_pad_gap(wrapper, 0, LV_STATE_DEFAULT); + lv_obj_set_style_margin_all(wrapper, 0, LV_STATE_DEFAULT); + lv_obj_set_style_border_width(wrapper, 0, LV_STATE_DEFAULT); auto* label = lv_label_create(wrapper); lv_obj_align(label, LV_ALIGN_LEFT_MID, 0, 0); @@ -111,9 +113,17 @@ void View::createSsidListItem(const service::wifi::ApRecord& record, bool isConn lv_obj_set_width(label, LV_PCT(70)); auto* info_wrapper = lv_obj_create(wrapper); - lv_obj_set_style_pad_all(info_wrapper, 0, 0); - lv_obj_set_style_margin_all(info_wrapper, 0, 0); - lv_obj_set_size(info_wrapper, 36, 36); + lv_obj_set_style_margin_all(info_wrapper, 0, LV_STATE_DEFAULT); + lv_obj_set_align(info_wrapper, LV_ALIGN_RIGHT_MID); + + if (ui_scale == hal::UiScale::Smallest) { + lv_obj_set_size(info_wrapper, LV_SIZE_CONTENT, LV_SIZE_CONTENT); + lv_obj_set_style_pad_hor(info_wrapper, 4, LV_STATE_DEFAULT); + } else { + lv_obj_set_size(info_wrapper, 36, 36); + lv_obj_set_style_pad_all(info_wrapper, 0, LV_STATE_DEFAULT); + } + lv_obj_set_style_border_color(info_wrapper, lv_theme_get_color_primary(info_wrapper), 0); lv_obj_add_event_cb(info_wrapper, &showDetails, LV_EVENT_SHORT_CLICKED, bindings); lv_obj_align(info_wrapper, LV_ALIGN_RIGHT_MID, 0, 0); @@ -124,26 +134,28 @@ void View::createSsidListItem(const service::wifi::ApRecord& record, bool isConn auto* ssid_label = lv_label_create(info_wrapper); lv_label_set_text(ssid_label, record.ssid.c_str()); lv_obj_add_flag(ssid_label, LV_OBJ_FLAG_HIDDEN); - lv_obj_set_style_text_color(info_label, lv_theme_get_color_primary(info_wrapper), 0); + lv_obj_set_style_text_color(info_label, lv_theme_get_color_primary(info_wrapper), LV_STATE_DEFAULT); lv_obj_align(info_label, LV_ALIGN_CENTER, 0, 0); if (isConnecting) { - auto* connecting_spinner = tt::lvgl::spinner_create(wrapper); - lv_obj_align_to(connecting_spinner, info_wrapper, LV_ALIGN_OUT_LEFT_MID, -8, 0); + auto* connecting_spinner = lvgl::spinner_create(wrapper); + auto spinner_offset_x = (ui_scale == hal::UiScale::Smallest) ? -2 : -8; + lv_obj_align_to(connecting_spinner, info_wrapper, LV_ALIGN_OUT_LEFT_MID, spinner_offset_x, 0); } else { auto percentage = mapRssiToPercentage(record.rssi); std::string auth_info; if (record.auth_mode == WIFI_AUTH_OPEN) { - auth_info = "(open) "; + auth_info = "(open)"; } else { auth_info = ""; } - auto info = std::format("{}{}%", auth_info, percentage); - auto* open_label = lv_label_create(wrapper); - lv_label_set_text(open_label, info.c_str()); - lv_obj_align(open_label, LV_ALIGN_RIGHT_MID, -42, 0); + auto signal = std::format("{}{}%", auth_info, percentage); + auto* signal_label = lv_label_create(wrapper); + lv_label_set_text(signal_label, signal.c_str()); + auto info_label_offset = (ui_scale == hal::UiScale::Smallest) ? -4 : -16; + lv_obj_align_to(signal_label, info_wrapper, LV_ALIGN_OUT_LEFT_MID, info_label_offset, 0); } } @@ -178,7 +190,7 @@ void View::updateNetworkList() { state->withApRecords([this, &connection_target](const std::vector& apRecords){ bool is_connected = !connection_target.empty() && - state->getRadioState() == service::wifi::RadioState::ConnectionActive; + state->getRadioState() == ConnectionActive; bool added_connected = false; if (is_connected && !apRecords.empty()) { for (auto &record : apRecords) { @@ -198,7 +210,7 @@ void View::updateNetworkList() { if (used_ssids.find(record.ssid) == used_ssids.end()) { bool connection_target_match = (record.ssid == connection_target); bool is_connecting = connection_target_match - && state->getRadioState() == service::wifi::RadioState::ConnectionPending && + && state->getRadioState() == ConnectionPending && !connection_target.empty(); bool skip = connection_target_match && added_connected; if (!skip) { @@ -272,6 +284,8 @@ void View::updateEnableOnBootToggle() { // region Main void View::init(const AppContext& app, lv_obj_t* parent) { + auto ui_scale = hal::getConfiguration()->uiScale; + lv_obj_set_flex_flow(parent, LV_FLEX_FLOW_COLUMN); lv_obj_set_style_pad_row(parent, 0, LV_STATE_DEFAULT); @@ -290,45 +304,52 @@ void View::init(const AppContext& app, lv_obj_t* parent) { // Wrappers - lv_obj_t* secondary_flex = lv_obj_create(parent); - lv_obj_set_width(secondary_flex, LV_PCT(100)); - lv_obj_set_flex_grow(secondary_flex, 1); - lv_obj_set_flex_flow(secondary_flex, LV_FLEX_FLOW_COLUMN); - lv_obj_set_style_border_width(secondary_flex, 0, 0); - lv_obj_set_style_pad_all(secondary_flex, 0, 0); - lv_obj_set_style_pad_gap(secondary_flex, 0, 0); - lvgl::obj_set_style_bg_invisible(secondary_flex); + auto* flex_wrapper = lv_obj_create(parent); + lv_obj_set_width(flex_wrapper, LV_PCT(100)); + lv_obj_set_flex_grow(flex_wrapper, 1); + lv_obj_set_flex_flow(flex_wrapper, LV_FLEX_FLOW_COLUMN); + lv_obj_set_style_border_width(flex_wrapper, 0, LV_STATE_DEFAULT); + lv_obj_set_style_pad_all(flex_wrapper, 0, LV_STATE_DEFAULT); + lv_obj_set_style_pad_gap(flex_wrapper, 0, LV_STATE_DEFAULT); + lvgl::obj_set_style_bg_invisible(flex_wrapper); - // align() methods don't work on flex, so we need this extra wrapper - lv_obj_t* wrapper = lv_obj_create(secondary_flex); - lv_obj_set_size(wrapper, LV_PCT(100), LV_SIZE_CONTENT); - lvgl::obj_set_style_bg_invisible(wrapper); - lv_obj_set_style_border_width(wrapper, 0, 0); + // Fixed size content wrapper: align() methods don't work on flex, so we need this extra wrapper + + auto* content_wrapper = lv_obj_create(flex_wrapper); + lv_obj_set_size(content_wrapper, LV_PCT(100), LV_SIZE_CONTENT); + lvgl::obj_set_style_bg_invisible(content_wrapper); + lv_obj_set_style_border_width(content_wrapper, 0, LV_STATE_DEFAULT); // Enable on boot - lv_obj_t* enable_label = lv_label_create(wrapper); - lv_label_set_text(enable_label, "Enable on boot"); - lv_obj_align(enable_label, LV_ALIGN_TOP_LEFT, 0, 6); + auto* enable_on_boot_wrapper = lv_obj_create(content_wrapper); + lv_obj_set_size(enable_on_boot_wrapper, LV_PCT(100), LV_SIZE_CONTENT); + lv_obj_set_style_pad_all(enable_on_boot_wrapper, 0, LV_STATE_DEFAULT); + lv_obj_set_style_border_width(enable_on_boot_wrapper, 0, LV_STATE_DEFAULT); - enable_on_boot_switch = lv_switch_create(wrapper); + auto* enable_label = lv_label_create(enable_on_boot_wrapper); + lv_label_set_text(enable_label, "Enable on boot"); + lv_obj_align(enable_label, LV_ALIGN_LEFT_MID, 0, 0); + + enable_on_boot_switch = lv_switch_create(enable_on_boot_wrapper); lv_obj_add_event_cb(enable_on_boot_switch, on_enable_on_boot_switch_changed, LV_EVENT_VALUE_CHANGED, bindings); - lv_obj_align(enable_on_boot_switch, LV_ALIGN_TOP_RIGHT, 0, 0); + lv_obj_align(enable_on_boot_switch, LV_ALIGN_RIGHT_MID, 0, 0); // Networks - networks_list = lv_obj_create(wrapper); + networks_list = lv_obj_create(content_wrapper); lv_obj_set_flex_flow(networks_list, LV_FLEX_FLOW_COLUMN); lv_obj_set_width(networks_list, LV_PCT(100)); lv_obj_set_height(networks_list, LV_SIZE_CONTENT); - lv_obj_set_style_pad_top(networks_list, 0, 0); - lv_obj_set_style_pad_bottom(networks_list, 0, 0); - lv_obj_align(networks_list, LV_ALIGN_TOP_LEFT, 0, 44); + lv_obj_set_style_pad_top(networks_list, 0, LV_STATE_DEFAULT); + lv_obj_set_style_pad_bottom(networks_list, 0, LV_STATE_DEFAULT); + const int network_list_y_offset = ui_scale == hal::UiScale::Smallest ? 22 : 44; + lv_obj_align(networks_list, LV_ALIGN_TOP_LEFT, 0, network_list_y_offset); - connect_to_hidden = lv_button_create(secondary_flex); + connect_to_hidden = lv_button_create(flex_wrapper); lv_obj_set_width(connect_to_hidden, LV_PCT(100)); - lv_obj_set_style_margin_bottom(connect_to_hidden, 8, 0); - lv_obj_set_style_margin_hor(connect_to_hidden, 12, 0); + lv_obj_set_style_margin_bottom(connect_to_hidden, 8, LV_STATE_DEFAULT); + lv_obj_set_style_margin_hor(connect_to_hidden, 12, LV_STATE_DEFAULT); lv_obj_add_event_cb(connect_to_hidden, onConnectToHiddenClicked, LV_EVENT_SHORT_CLICKED, bindings); auto* connect_to_hidden_label = lv_label_create(connect_to_hidden); lv_label_set_text(connect_to_hidden_label, "Connect to hidden SSID"); diff --git a/Tactility/Source/lvgl/Statusbar.cpp b/Tactility/Source/lvgl/Statusbar.cpp index b90fa90d..061b85d7 100644 --- a/Tactility/Source/lvgl/Statusbar.cpp +++ b/Tactility/Source/lvgl/Statusbar.cpp @@ -13,6 +13,7 @@ #include #include +#include namespace tt::lvgl { @@ -167,15 +168,15 @@ lv_obj_t* statusbar_create(lv_obj_t* parent) { auto* statusbar = (Statusbar*)obj; lv_obj_set_width(obj, LV_PCT(100)); - lv_obj_set_height(obj, STATUSBAR_HEIGHT); - lv_obj_set_style_pad_all(obj, 0, 0); + lv_obj_set_style_pad_ver(obj, 0, LV_STATE_DEFAULT); + lv_obj_set_style_pad_hor(obj, 2, LV_STATE_DEFAULT); lv_obj_center(obj); lv_obj_set_flex_flow(obj, LV_FLEX_FLOW_ROW); lv_obj_set_flex_align(obj, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER); statusbar->time = lv_label_create(obj); - lv_obj_set_style_text_color(statusbar->time, lv_color_white(), 0); - lv_obj_set_style_margin_left(statusbar->time, 4, 0); + lv_obj_set_style_text_color(statusbar->time, lv_color_white(), LV_STATE_DEFAULT); + lv_obj_set_style_margin_left(statusbar->time, 4, LV_STATE_DEFAULT); update_time(statusbar); auto* left_spacer = lv_obj_create(obj); @@ -187,7 +188,7 @@ lv_obj_t* statusbar_create(lv_obj_t* parent) { for (int i = 0; i < STATUSBAR_ICON_LIMIT; ++i) { auto* image = lv_image_create(obj); lv_obj_set_size(image, STATUSBAR_ICON_SIZE, STATUSBAR_ICON_SIZE); - lv_obj_set_style_pad_all(image, 0, 0); + lv_obj_set_style_pad_all(image, 0, LV_STATE_DEFAULT); obj_set_style_bg_blacken(image); statusbar->icons[i] = image; diff --git a/Tactility/Source/lvgl/Toolbar.cpp b/Tactility/Source/lvgl/Toolbar.cpp index 2bfcedd9..db9e6967 100644 --- a/Tactility/Source/lvgl/Toolbar.cpp +++ b/Tactility/Source/lvgl/Toolbar.cpp @@ -1,29 +1,21 @@ #define LV_USE_PRIVATE_API 1 // For actual lv_obj_t declaration -#include "Tactility/lvgl/Toolbar.h" +#include -#include "Tactility/service/loader/Loader.h" -#include "Tactility/lvgl/Style.h" -#include "Tactility/lvgl/Spinner.h" +#include +#include +#include namespace tt::lvgl { static int getToolbarHeight(hal::UiScale uiScale) { if (uiScale == hal::UiScale::Smallest) { - return 20; + return 22; } else { return 40; } } -static int getToolbarFontHeight(hal::UiScale uiScale) { - if (uiScale == hal::UiScale::Smallest) { - return 14; - } else { - return 18; - } -} - static const _lv_font_t* getToolbarFont(hal::UiScale uiScale) { if (uiScale == hal::UiScale::Smallest) { return &lv_font_montserrat_14; @@ -32,6 +24,20 @@ static const _lv_font_t* getToolbarFont(hal::UiScale uiScale) { } } +/** + * Helps with button expansion and also with vertical alignment of content, + * as the parent flex doesn't allow for vertical alignment + */ +static lv_obj_t* create_action_wrapper(lv_obj_t* parent) { + auto* wrapper = lv_obj_create(parent); + lv_obj_set_size(wrapper, LV_SIZE_CONTENT, getToolbarHeight(hal::getConfiguration()->uiScale)); + lv_obj_set_style_pad_all(wrapper, 2, LV_STATE_DEFAULT); // For selection / click expansion + lv_obj_set_style_bg_opa(wrapper, 0, LV_STATE_DEFAULT); + lv_obj_set_style_border_width(wrapper, 0, LV_STATE_DEFAULT); + lv_obj_set_style_border_opa(wrapper, 0, LV_STATE_DEFAULT); + return wrapper; +} + typedef struct { lv_obj_t obj; lv_obj_t* title_label; @@ -43,7 +49,7 @@ typedef struct { static void toolbar_constructor(const lv_obj_class_t* class_p, lv_obj_t* obj); -static lv_obj_class_t toolbar_class = { +static const lv_obj_class_t toolbar_class = { .base_class = &lv_obj_class, .constructor_cb = &toolbar_constructor, .destructor_cb = nullptr, @@ -51,7 +57,7 @@ static lv_obj_class_t toolbar_class = { .user_data = nullptr, .name = nullptr, .width_def = LV_PCT(100), - .height_def = 40, + .height_def = LV_SIZE_CONTENT, .editable = false, .group_def = LV_OBJ_CLASS_GROUP_DEF_TRUE, .instance_size = sizeof(Toolbar), @@ -74,45 +80,63 @@ lv_obj_t* toolbar_create(lv_obj_t* parent, const std::string& title) { LV_LOG_INFO("begin"); auto ui_scale = hal::getConfiguration()->uiScale; auto toolbar_height = getToolbarHeight(ui_scale); - toolbar_class.height_def = toolbar_height; lv_obj_t* obj = lv_obj_class_create_obj(&toolbar_class, parent); lv_obj_class_init_obj(obj); + lv_obj_set_height(obj, toolbar_height); - auto* toolbar = (Toolbar*)obj; - + auto* toolbar = reinterpret_cast(obj); + lv_obj_set_width(obj, LV_PCT(100)); lv_obj_set_style_pad_all(obj, 0, LV_STATE_DEFAULT); - lv_obj_set_style_pad_gap(obj, 0, LV_STATE_DEFAULT); lv_obj_center(obj); lv_obj_set_flex_flow(obj, LV_FLEX_FLOW_ROW); - toolbar->close_button = lv_button_create(obj); + auto* close_button_wrapper = lv_obj_create(obj); + lv_obj_set_size(close_button_wrapper, LV_SIZE_CONTENT, toolbar_height); + lv_obj_set_style_pad_all(close_button_wrapper, 2, LV_STATE_DEFAULT); + lv_obj_set_style_border_width(close_button_wrapper, 0, LV_STATE_DEFAULT); + lv_obj_set_style_bg_opa(close_button_wrapper, 0, LV_STATE_DEFAULT); + + toolbar->close_button = lv_button_create(close_button_wrapper); + + if (ui_scale == hal::UiScale::Smallest) { + lv_obj_set_size(toolbar->close_button, toolbar_height - 8, toolbar_height - 8); + } else { + lv_obj_set_size(toolbar->close_button, toolbar_height - 6, toolbar_height - 6); + } - lv_obj_set_size(toolbar->close_button, toolbar_height - 4, toolbar_height - 4); lv_obj_set_style_pad_all(toolbar->close_button, 0, LV_STATE_DEFAULT); - lv_obj_set_style_pad_gap(toolbar->close_button, 0, LV_STATE_DEFAULT); + lv_obj_align(toolbar->close_button, LV_ALIGN_CENTER, 0, 0); toolbar->close_button_image = lv_image_create(toolbar->close_button); lv_obj_align(toolbar->close_button_image, LV_ALIGN_CENTER, 0, 0); - toolbar->title_label = lv_label_create(obj); + auto* title_wrapper = lv_obj_create(obj); + lv_obj_set_size(title_wrapper, LV_SIZE_CONTENT, LV_PCT(100)); + lv_obj_set_style_bg_opa(title_wrapper, 0, LV_STATE_DEFAULT); + lv_obj_set_style_pad_all(title_wrapper, 0, LV_STATE_DEFAULT); + lv_obj_set_style_border_width(title_wrapper, 0, LV_STATE_DEFAULT); + lv_obj_set_flex_grow(title_wrapper, 1); + + if (ui_scale == hal::UiScale::Smallest) { + lv_obj_set_style_pad_left(title_wrapper, 4, LV_STATE_DEFAULT); + } else { + lv_obj_set_style_pad_left(title_wrapper, 8, LV_STATE_DEFAULT); + } + + toolbar->title_label = lv_label_create(title_wrapper); lv_obj_set_style_text_font(toolbar->title_label, getToolbarFont(ui_scale), LV_STATE_DEFAULT); lv_label_set_text(toolbar->title_label, title.c_str()); lv_label_set_long_mode(toolbar->title_label, LV_LABEL_LONG_MODE_SCROLL); lv_obj_set_style_text_align(toolbar->title_label, LV_TEXT_ALIGN_LEFT, LV_STATE_DEFAULT); - lv_obj_set_flex_grow(toolbar->title_label, 1); - int32_t title_offset_x = (toolbar_height - getToolbarFontHeight(ui_scale) - 8) / 4 * 3; - // Margin top doesn't work - lv_obj_set_style_pad_top(toolbar->title_label, title_offset_x, LV_STATE_DEFAULT); - lv_obj_set_style_margin_left(toolbar->title_label, 8, LV_STATE_DEFAULT); - // Hack for margin bug where buttons in flex get rendered more narrowly - lv_obj_set_style_margin_right(toolbar->title_label, -8, LV_STATE_DEFAULT); + lv_obj_align(toolbar->title_label, LV_ALIGN_LEFT_MID, 0, 0); + lv_obj_set_width(toolbar->title_label, LV_PCT(100)); toolbar->action_container = lv_obj_create(obj); lv_obj_set_width(toolbar->action_container, LV_SIZE_CONTENT); lv_obj_set_flex_flow(toolbar->action_container, LV_FLEX_FLOW_ROW); lv_obj_set_style_pad_all(toolbar->action_container, 0, LV_STATE_DEFAULT); lv_obj_set_style_border_width(toolbar->action_container, 0, LV_STATE_DEFAULT); - lv_obj_set_flex_align(toolbar->action_container, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_START); + lv_obj_set_style_bg_opa(toolbar->action_container, 0, LV_STATE_DEFAULT); toolbar_set_nav_action(obj, LV_SYMBOL_CLOSE, &stop_app, nullptr); @@ -124,28 +148,35 @@ lv_obj_t* toolbar_create(lv_obj_t* parent, const app::AppContext& app) { } void toolbar_set_title(lv_obj_t* obj, const std::string& title) { - auto* toolbar = (Toolbar*)obj; + auto* toolbar = reinterpret_cast(obj); lv_label_set_text(toolbar->title_label, title.c_str()); } void toolbar_set_nav_action(lv_obj_t* obj, const char* icon, lv_event_cb_t callback, void* user_data) { - auto* toolbar = (Toolbar*)obj; + auto* toolbar = reinterpret_cast(obj); lv_obj_add_event_cb(toolbar->close_button, callback, LV_EVENT_SHORT_CLICKED, user_data); lv_image_set_src(toolbar->close_button_image, icon); // e.g. LV_SYMBOL_CLOSE } lv_obj_t* toolbar_add_button_action(lv_obj_t* obj, const char* icon, lv_event_cb_t callback, void* user_data) { - auto* toolbar = (Toolbar*)obj; + auto* toolbar = reinterpret_cast(obj); tt_check(toolbar->action_count < TOOLBAR_ACTION_LIMIT, "max actions reached"); toolbar->action_count++; auto ui_scale = hal::getConfiguration()->uiScale; auto toolbar_height = getToolbarHeight(ui_scale); - lv_obj_t* action_button = lv_button_create(toolbar->action_container); - lv_obj_set_size(action_button, toolbar_height - 4, toolbar_height - 4); + auto* wrapper = create_action_wrapper(toolbar->action_container); + + auto* action_button = lv_button_create(wrapper); + if (ui_scale == hal::UiScale::Smallest) { + lv_obj_set_size(action_button, toolbar_height - 8, toolbar_height - 8); + } else { + lv_obj_set_size(action_button, toolbar_height - 6, toolbar_height - 6); + } lv_obj_set_style_pad_all(action_button, 0, LV_STATE_DEFAULT); - lv_obj_set_style_pad_gap(action_button, 0, LV_STATE_DEFAULT); + lv_obj_align(action_button, LV_ALIGN_CENTER, 0, 0); + lv_obj_add_event_cb(action_button, callback, LV_EVENT_SHORT_CLICKED, user_data); lv_obj_t* action_button_image = lv_image_create(action_button); lv_image_set_src(action_button_image, icon); @@ -155,16 +186,24 @@ lv_obj_t* toolbar_add_button_action(lv_obj_t* obj, const char* icon, lv_event_cb } lv_obj_t* toolbar_add_switch_action(lv_obj_t* obj) { - auto* toolbar = (Toolbar*)obj; - lv_obj_t* widget = lv_switch_create(toolbar->action_container); - lv_obj_set_style_margin_top(widget, 4, LV_STATE_DEFAULT); // Because aligning doesn't work - lv_obj_set_style_margin_right(widget, 4, LV_STATE_DEFAULT); + auto* toolbar = reinterpret_cast(obj); + + auto* wrapper = create_action_wrapper(toolbar->action_container); + lv_obj_set_style_pad_hor(wrapper, 4, LV_STATE_DEFAULT); + + lv_obj_t* widget = lv_switch_create(wrapper); + lv_obj_set_align(widget, LV_ALIGN_CENTER); return widget; } lv_obj_t* toolbar_add_spinner_action(lv_obj_t* obj) { - auto* toolbar = (Toolbar*)obj; - return spinner_create(toolbar->action_container); + auto* toolbar = reinterpret_cast(obj); + + auto* wrapper = create_action_wrapper(toolbar->action_container); + + auto* spinner = spinner_create(wrapper); + lv_obj_set_align(spinner, LV_ALIGN_CENTER); + return spinner; } } // namespace diff --git a/Tactility/Source/lvgl/wrappers/button.cpp b/Tactility/Source/lvgl/wrappers/button.cpp index e35cd846..f4f9504d 100644 --- a/Tactility/Source/lvgl/wrappers/button.cpp +++ b/Tactility/Source/lvgl/wrappers/button.cpp @@ -13,6 +13,7 @@ lv_obj_t* __wrap_lv_button_create(lv_obj_t* parent) { if (tt::hal::getConfiguration()->uiScale == tt::hal::UiScale::Smallest) { lv_obj_set_style_pad_all(button, 2, LV_STATE_DEFAULT); + lv_obj_set_style_radius(button, 2, LV_STATE_DEFAULT); } return button; diff --git a/Tactility/Source/lvgl/wrappers/obj.cpp b/Tactility/Source/lvgl/wrappers/obj.cpp index c3a9f4a1..b82fa118 100644 --- a/Tactility/Source/lvgl/wrappers/obj.cpp +++ b/Tactility/Source/lvgl/wrappers/obj.cpp @@ -13,17 +13,15 @@ void __wrap_lv_obj_set_flex_flow(lv_obj_t* obj, lv_flex_flow_t flow) { __real_lv_obj_set_flex_flow(obj, flow); if (tt::hal::getConfiguration()->uiScale == tt::hal::UiScale::Smallest) { - lv_obj_set_style_pad_row(obj, 2, LV_STATE_DEFAULT); - lv_obj_set_style_pad_column(obj, 2, LV_STATE_DEFAULT); + lv_obj_set_style_pad_gap(obj, 2, LV_STATE_DEFAULT); } } lv_obj_t* __wrap_lv_obj_create(lv_obj_t* parent) { auto obj = __real_lv_obj_create(parent); if (tt::hal::getConfiguration()->uiScale == tt::hal::UiScale::Smallest) { - lv_obj_set_style_pad_row(obj, 2, LV_STATE_DEFAULT); - lv_obj_set_style_pad_column(obj, 2, LV_STATE_DEFAULT); lv_obj_set_style_pad_all(obj, 2, LV_STATE_DEFAULT); + lv_obj_set_style_pad_gap(obj, 2, LV_STATE_DEFAULT); lv_obj_set_style_radius(obj, 3, LV_STATE_DEFAULT); lv_obj_set_style_border_width(obj, 1, LV_STATE_DEFAULT); } diff --git a/Tactility/Source/service/gui/GuiService.cpp b/Tactility/Source/service/gui/GuiService.cpp index 8ce0be78..2268d7a4 100644 --- a/Tactility/Source/service/gui/GuiService.cpp +++ b/Tactility/Source/service/gui/GuiService.cpp @@ -56,8 +56,9 @@ int32_t GuiService::guiMain() { lv_obj_t* GuiService::createAppViews(lv_obj_t* parent) { lv_obj_send_event(statusbarWidget, LV_EVENT_DRAW_MAIN, nullptr); lv_obj_t* child_container = lv_obj_create(parent); - lv_obj_set_style_pad_all(child_container, 0, 0); + lv_obj_set_style_pad_all(child_container, 0, LV_STATE_DEFAULT); lv_obj_set_width(child_container, LV_PCT(100)); + lv_obj_set_style_border_width(child_container, 0, LV_STATE_DEFAULT); lv_obj_set_flex_grow(child_container, 1); if (softwareKeyboardIsEnabled()) { @@ -132,21 +133,23 @@ bool GuiService::onStart(TT_UNUSED ServiceContext& service) { lvgl::lock(portMAX_DELAY); keyboardGroup = lv_group_create(); - lvgl::obj_set_style_bg_blacken(screen_root); + lv_obj_set_style_border_width(screen_root, 0, LV_STATE_DEFAULT); + lv_obj_set_style_pad_all(screen_root, 0, LV_STATE_DEFAULT); lv_obj_t* vertical_container = lv_obj_create(screen_root); lv_obj_set_size(vertical_container, LV_PCT(100), LV_PCT(100)); lv_obj_set_flex_flow(vertical_container, LV_FLEX_FLOW_COLUMN); - lv_obj_set_style_pad_all(vertical_container, 0, 0); - lv_obj_set_style_pad_gap(vertical_container, 0, 0); - lvgl::obj_set_style_bg_blacken(vertical_container); + lv_obj_set_style_pad_all(vertical_container, 0, LV_STATE_DEFAULT); + lv_obj_set_style_pad_gap(vertical_container, 0, LV_STATE_DEFAULT); + lv_obj_set_style_bg_color(vertical_container, lv_color_black(), LV_STATE_DEFAULT); + lv_obj_set_style_border_width(vertical_container, 0, LV_STATE_DEFAULT); + lv_obj_set_style_radius(vertical_container, 0, LV_STATE_DEFAULT); statusbarWidget = lvgl::statusbar_create(vertical_container); auto* app_container = lv_obj_create(vertical_container); - lv_obj_set_style_pad_all(app_container, 0, 0); - lv_obj_set_style_border_width(app_container, 0, 0); - lvgl::obj_set_style_bg_blacken(app_container); + lv_obj_set_style_pad_all(app_container, 0, LV_STATE_DEFAULT); + lv_obj_set_style_border_width(app_container, 0, LV_STATE_DEFAULT); lv_obj_set_width(app_container, LV_PCT(100)); lv_obj_set_flex_grow(app_container, 1); lv_obj_set_flex_flow(app_container, LV_FLEX_FLOW_COLUMN); diff --git a/Libraries/lvgl_conf/lv_conf_simulator.h b/lv_conf.h similarity index 99% rename from Libraries/lvgl_conf/lv_conf_simulator.h rename to lv_conf.h index d68c471f..73bd3fe1 100644 --- a/Libraries/lvgl_conf/lv_conf_simulator.h +++ b/lv_conf.h @@ -1,3 +1,7 @@ +/** + * WARNING: This is only used by the simulator! + */ + /** * @file lv_conf.h * Configuration file for v9.0.0