Implement UI scaling and more (#501)
**New Features** * Runtime font accessors and new symbol fonts for text, launcher, statusbar, and shared icons. * Added font height base setting to device.properties * Text fonts now have 3 sizes: small, default, large **Improvements** * Renamed `UiScale` to `UiDensity` * Statusbar, toolbar and many UI components now compute heights and spacing from fonts/density. * SSD1306 initialization sequence refined for more stable startup. * Multiple image assets replaced by symbol-font rendering. * Many layout improvements related to density, font scaling and icon scaling * Updated folder name capitalization for newer style
This commit is contained in:
committed by
GitHub
parent
72c9b2b113
commit
9a11e6f47b
@@ -1,12 +1,11 @@
|
||||
#include <Tactility/Tactility.h>
|
||||
|
||||
#include <Tactility/Logger.h>
|
||||
#include <Tactility/lvgl/Statusbar.h>
|
||||
#include <Tactility/service/ServiceContext.h>
|
||||
#include <Tactility/service/ServiceManifest.h>
|
||||
#include <Tactility/service/ServicePaths.h>
|
||||
#include <Tactility/service/memorychecker/MemoryCheckerService.h>
|
||||
|
||||
#include <tactility/lvgl_symbols_statusbar.h>
|
||||
|
||||
namespace tt::service::memorychecker {
|
||||
|
||||
static const auto LOGGER = Logger("MemoryChecker");
|
||||
@@ -55,8 +54,7 @@ bool MemoryCheckerService::onStart(ServiceContext& service) {
|
||||
auto lock = mutex.asScopedLock();
|
||||
lock.lock();
|
||||
|
||||
auto icon_path = std::string("A:") + service.getPaths()->getAssetsPath("memory_alert.png");
|
||||
statusbarIconId = lvgl::statusbar_icon_add(icon_path, false);
|
||||
statusbarIconId = lvgl::statusbar_icon_add(LVGL_SYMBOL_MEMORY, false);
|
||||
lvgl::statusbar_icon_set_visibility(statusbarIconId, false);
|
||||
|
||||
timer.setCallbackPriority(Thread::Priority::Lower);
|
||||
|
||||
@@ -14,60 +14,40 @@
|
||||
#include <Tactility/service/gps/GpsService.h>
|
||||
#include <Tactility/service/wifi/Wifi.h>
|
||||
|
||||
#include <tactility/lvgl_symbols_statusbar.h>
|
||||
|
||||
namespace tt::service::statusbar {
|
||||
|
||||
static const auto LOGGER = Logger("StatusbarService");
|
||||
|
||||
// SD card status
|
||||
constexpr auto* STATUSBAR_ICON_SDCARD = "sdcard.png";
|
||||
constexpr auto* STATUSBAR_ICON_SDCARD_ALERT = "sdcard_alert.png";
|
||||
|
||||
// Wifi status
|
||||
constexpr auto* STATUSBAR_ICON_WIFI_OFF_WHITE = "wifi_off_white.png";
|
||||
constexpr auto* STATUSBAR_ICON_WIFI_SCAN_WHITE = "wifi_scan_white.png";
|
||||
constexpr auto* STATUSBAR_ICON_WIFI_SIGNAL_WEAK_WHITE = "wifi_signal_weak_white.png";
|
||||
constexpr auto* STATUSBAR_ICON_WIFI_SIGNAL_MEDIUM_WHITE = "wifi_signal_medium_white.png";
|
||||
constexpr auto* STATUSBAR_ICON_WIFI_SIGNAL_STRONG_WHITE = "wifi_signal_strong_white.png";
|
||||
|
||||
// Power status
|
||||
constexpr auto* STATUSBAR_ICON_POWER_0 = "power_0.png";
|
||||
constexpr auto* STATUSBAR_ICON_POWER_10 = "power_10.png";
|
||||
constexpr auto* STATUSBAR_ICON_POWER_20 = "power_20.png";
|
||||
constexpr auto* STATUSBAR_ICON_POWER_30 = "power_30.png";
|
||||
constexpr auto* STATUSBAR_ICON_POWER_40 = "power_40.png";
|
||||
constexpr auto* STATUSBAR_ICON_POWER_50 = "power_50.png";
|
||||
constexpr auto* STATUSBAR_ICON_POWER_60 = "power_60.png";
|
||||
constexpr auto* STATUSBAR_ICON_POWER_70 = "power_70.png";
|
||||
constexpr auto* STATUSBAR_ICON_POWER_80 = "power_80.png";
|
||||
constexpr auto* STATUSBAR_ICON_POWER_90 = "power_90.png";
|
||||
constexpr auto* STATUSBAR_ICON_POWER_100 = "power_100.png";
|
||||
|
||||
// GPS
|
||||
constexpr auto* STATUSBAR_ICON_GPS = "location.png";
|
||||
|
||||
extern const ServiceManifest manifest;
|
||||
|
||||
const char* getWifiStatusIconForRssi(int rssi) {
|
||||
if (rssi >= -60) {
|
||||
return STATUSBAR_ICON_WIFI_SIGNAL_STRONG_WHITE;
|
||||
return LVGL_SYMBOL_SIGNAL_WIFI_4_BAR;
|
||||
} else if (rssi >= -70) {
|
||||
return STATUSBAR_ICON_WIFI_SIGNAL_MEDIUM_WHITE;
|
||||
return LVGL_SYMBOL_NETWORK_WIFI_3_BAR;
|
||||
} else if (rssi >= -80) {
|
||||
return LVGL_SYMBOL_NETWORK_WIFI_2_BAR;
|
||||
} else if (rssi >= -90) {
|
||||
return LVGL_SYMBOL_NETWORK_WIFI_1_BAR;
|
||||
} else {
|
||||
return STATUSBAR_ICON_WIFI_SIGNAL_WEAK_WHITE;
|
||||
return LVGL_SYMBOL_SIGNAL_WIFI_BAD;
|
||||
}
|
||||
}
|
||||
|
||||
static const char* getWifiStatusIcon(wifi::RadioState state, bool secure) {
|
||||
static const char* getWifiStatusIcon(wifi::RadioState state) {
|
||||
int rssi;
|
||||
switch (state) {
|
||||
using enum wifi::RadioState;
|
||||
case On:
|
||||
case OnPending:
|
||||
case ConnectionPending:
|
||||
return STATUSBAR_ICON_WIFI_SCAN_WHITE;
|
||||
return LVGL_SYMBOL_SIGNAL_WIFI_0_BAR;
|
||||
case OffPending:
|
||||
case Off:
|
||||
return STATUSBAR_ICON_WIFI_OFF_WHITE;
|
||||
return LVGL_SYMBOL_SIGNAL_WIFI_OFF;
|
||||
case ConnectionActive:
|
||||
rssi = wifi::getRssi();
|
||||
return getWifiStatusIconForRssi(rssi);
|
||||
@@ -80,11 +60,11 @@ static const char* getSdCardStatusIcon(hal::sdcard::SdCardDevice::State state) {
|
||||
switch (state) {
|
||||
using enum hal::sdcard::SdCardDevice::State;
|
||||
case Mounted:
|
||||
return STATUSBAR_ICON_SDCARD;
|
||||
return LVGL_SYMBOL_SD_CARD;
|
||||
case Error:
|
||||
case Unmounted:
|
||||
case Timeout:
|
||||
return STATUSBAR_ICON_SDCARD_ALERT;
|
||||
return LVGL_SYMBOL_SD_CARD_ALERT;
|
||||
default:
|
||||
check(false, "Unhandled SdCard state");
|
||||
}
|
||||
@@ -113,27 +93,19 @@ static const char* getPowerStatusIcon() {
|
||||
uint8_t charge = charge_level.valueAsUint8;
|
||||
|
||||
if (charge >= 95) {
|
||||
return STATUSBAR_ICON_POWER_100;
|
||||
} else if (charge >= 85) {
|
||||
return STATUSBAR_ICON_POWER_90;
|
||||
} else if (charge >= 75) {
|
||||
return STATUSBAR_ICON_POWER_80;
|
||||
} else if (charge >= 65) {
|
||||
return STATUSBAR_ICON_POWER_70;
|
||||
} else if (charge >= 55) {
|
||||
return STATUSBAR_ICON_POWER_60;
|
||||
} else if (charge >= 45) {
|
||||
return STATUSBAR_ICON_POWER_50;
|
||||
} else if (charge >= 35) {
|
||||
return STATUSBAR_ICON_POWER_40;
|
||||
} else if (charge >= 25) {
|
||||
return STATUSBAR_ICON_POWER_30;
|
||||
} else if (charge >= 15) {
|
||||
return STATUSBAR_ICON_POWER_20;
|
||||
} else if (charge >= 5) {
|
||||
return STATUSBAR_ICON_POWER_10;
|
||||
return LVGL_SYMBOL_BATTERY_ANDROID_FRAME_FULL;
|
||||
} else if (charge >= 80) {
|
||||
return LVGL_SYMBOL_BATTERY_ANDROID_FRAME_6;
|
||||
} else if (charge >= 64) {
|
||||
return LVGL_SYMBOL_BATTERY_ANDROID_FRAME_5;
|
||||
} else if (charge >= 48) {
|
||||
return LVGL_SYMBOL_BATTERY_ANDROID_FRAME_4;
|
||||
} else if (charge >= 32) {
|
||||
return LVGL_SYMBOL_BATTERY_ANDROID_FRAME_3;
|
||||
} else if (charge >= 16) {
|
||||
return LVGL_SYMBOL_BATTERY_ANDROID_FRAME_2;
|
||||
} else {
|
||||
return STATUSBAR_ICON_POWER_0;
|
||||
return LVGL_SYMBOL_BATTERY_ANDROID_FRAME_1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -150,8 +122,6 @@ class StatusbarService final : public Service {
|
||||
int8_t power_icon_id;
|
||||
const char* power_last_icon = nullptr;
|
||||
|
||||
std::unique_ptr<ServicePaths> paths;
|
||||
|
||||
void lock() const {
|
||||
mutex.lock();
|
||||
}
|
||||
@@ -165,8 +135,7 @@ class StatusbarService final : public Service {
|
||||
bool show_icon = (gps_state == gps::State::OnPending) || (gps_state == gps::State::On);
|
||||
if (gps_last_state != show_icon) {
|
||||
if (show_icon) {
|
||||
auto icon_path = "A:" + paths->getAssetsPath(STATUSBAR_ICON_GPS);
|
||||
lvgl::statusbar_icon_set_image(gps_icon_id, icon_path);
|
||||
lvgl::statusbar_icon_set_image(gps_icon_id, LVGL_SYMBOL_LOCATION_ON);
|
||||
lvgl::statusbar_icon_set_visibility(gps_icon_id, true);
|
||||
} else {
|
||||
lvgl::statusbar_icon_set_visibility(gps_icon_id, false);
|
||||
@@ -177,12 +146,10 @@ class StatusbarService final : public Service {
|
||||
|
||||
void updateWifiIcon() {
|
||||
wifi::RadioState radio_state = wifi::getRadioState();
|
||||
bool is_secure = wifi::isConnectionSecure();
|
||||
const char* desired_icon = getWifiStatusIcon(radio_state, is_secure);
|
||||
const char* desired_icon = getWifiStatusIcon(radio_state);
|
||||
if (wifi_last_icon != desired_icon) {
|
||||
if (desired_icon != nullptr) {
|
||||
auto icon_path = "A:" + paths->getAssetsPath(desired_icon);
|
||||
lvgl::statusbar_icon_set_image(wifi_icon_id, icon_path);
|
||||
lvgl::statusbar_icon_set_image(wifi_icon_id, desired_icon);
|
||||
lvgl::statusbar_icon_set_visibility(wifi_icon_id, true);
|
||||
} else {
|
||||
lvgl::statusbar_icon_set_visibility(wifi_icon_id, false);
|
||||
@@ -195,8 +162,7 @@ class StatusbarService final : public Service {
|
||||
const char* desired_icon = getPowerStatusIcon();
|
||||
if (power_last_icon != desired_icon) {
|
||||
if (desired_icon != nullptr) {
|
||||
auto icon_path = "A:" + paths->getAssetsPath(desired_icon);
|
||||
lvgl::statusbar_icon_set_image(power_icon_id, icon_path);
|
||||
lvgl::statusbar_icon_set_image(power_icon_id, desired_icon);
|
||||
lvgl::statusbar_icon_set_visibility(power_icon_id, true);
|
||||
} else {
|
||||
lvgl::statusbar_icon_set_visibility(power_icon_id, false);
|
||||
@@ -214,8 +180,7 @@ class StatusbarService final : public Service {
|
||||
if (state != hal::sdcard::SdCardDevice::State::Timeout) {
|
||||
auto* desired_icon = getSdCardStatusIcon(state);
|
||||
if (sdcard_last_icon != desired_icon) {
|
||||
auto icon_path = "A:" + paths->getAssetsPath(desired_icon);
|
||||
lvgl::statusbar_icon_set_image(sdcard_icon_id, icon_path);
|
||||
lvgl::statusbar_icon_set_image(sdcard_icon_id, desired_icon);
|
||||
lvgl::statusbar_icon_set_visibility(sdcard_icon_id, true);
|
||||
sdcard_last_icon = desired_icon;
|
||||
}
|
||||
@@ -258,8 +223,6 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
paths = serviceContext.getPaths();
|
||||
|
||||
// TODO: Make thread-safe for LVGL
|
||||
lvgl::statusbar_icon_set_visibility(wifi_icon_id, true);
|
||||
|
||||
|
||||
@@ -8,16 +8,15 @@
|
||||
#include <Tactility/MountPoints.h>
|
||||
#include <Tactility/file/File.h>
|
||||
#include <Tactility/Logger.h>
|
||||
#include <Tactility/kernel/SystemEvents.h>
|
||||
#include <Tactility/lvgl/Statusbar.h>
|
||||
#include <Tactility/Mutex.h>
|
||||
|
||||
#include <Tactility/Tactility.h>
|
||||
#include <Tactility/TactilityConfig.h>
|
||||
#include <tactility/hal/Device.h>
|
||||
#include <Tactility/app/AppRegistration.h>
|
||||
#include <Tactility/app/AppManifest.h>
|
||||
#include <Tactility/app/App.h>
|
||||
#include <Tactility/hal/sdcard/SdCardDevice.h>
|
||||
#include <Tactility/service/wifi/Wifi.h>
|
||||
#include <Tactility/network/HttpdReq.h>
|
||||
#include <Tactility/network/Url.h>
|
||||
@@ -32,23 +31,25 @@
|
||||
#include <lv_screenshot.h>
|
||||
#endif
|
||||
|
||||
#include <esp_system.h>
|
||||
#include <esp_heap_caps.h>
|
||||
#include <esp_chip_info.h>
|
||||
#include <esp_vfs_fat.h>
|
||||
#include <esp_flash.h>
|
||||
#include <esp_wifi.h>
|
||||
#include <esp_netif.h>
|
||||
#include <lwip/ip4_addr.h>
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/task.h>
|
||||
#include <sstream>
|
||||
#include <tactility/lvgl_symbols_statusbar.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <cctype>
|
||||
#include <cerrno>
|
||||
#include <cstring>
|
||||
#include <esp_chip_info.h>
|
||||
#include <esp_flash.h>
|
||||
#include <esp_heap_caps.h>
|
||||
#include <esp_netif.h>
|
||||
#include <esp_system.h>
|
||||
#include <esp_vfs_fat.h>
|
||||
#include <esp_wifi.h>
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/task.h>
|
||||
#include <iomanip>
|
||||
#include <cctype>
|
||||
#include <lwip/ip4_addr.h>
|
||||
#include <mbedtls/base64.h>
|
||||
#include <sstream>
|
||||
|
||||
namespace tt::service::webserver {
|
||||
|
||||
@@ -519,13 +520,9 @@ bool WebServerService::startServer() {
|
||||
LOGGER.info("HTTP server started successfully on port {}", settings.webServerPort);
|
||||
publish_event(this, WebServerEvent::WebServerStarted);
|
||||
|
||||
// Show statusbar icon (different icon for AP vs Station mode)
|
||||
// Show statusbar icon
|
||||
if (statusbarIconId >= 0) {
|
||||
const char* icon_name = (settings.wifiMode == settings::webserver::WiFiMode::AccessPoint)
|
||||
? "webserver_ap_white.png"
|
||||
: "webserver_station_white.png";
|
||||
auto icon_path = std::string("A:/system/service/Statusbar/assets/") + icon_name;
|
||||
lvgl::statusbar_icon_set_image(statusbarIconId, icon_path);
|
||||
lvgl::statusbar_icon_set_image(statusbarIconId, LVGL_SYMBOL_CLOUD);
|
||||
lvgl::statusbar_icon_set_visibility(statusbarIconId, true);
|
||||
LOGGER.info("WebServer statusbar icon shown ({} mode)",
|
||||
settings.wifiMode == settings::webserver::WiFiMode::AccessPoint ? "AP" : "Station");
|
||||
|
||||
Reference in New Issue
Block a user