code optimization
- lifecycle functions for widgets - persistence functions Signed-off-by: Peter Siegmund <developer@mars3142.org>
This commit is contained in:
@@ -22,23 +22,23 @@
|
|||||||
* must implement or can override. The class follows the template method pattern,
|
* must implement or can override. The class follows the template method pattern,
|
||||||
* allowing derived classes to customize behavior while maintaining a consistent
|
* allowing derived classes to customize behavior while maintaining a consistent
|
||||||
* interface for the UI system.
|
* interface for the UI system.
|
||||||
*
|
*
|
||||||
* @note All widgets should inherit from this class to ensure compatibility with
|
* @note All widgets should inherit from this class to ensure compatibility with
|
||||||
* the UI management system.
|
* the UI management system.
|
||||||
*
|
*
|
||||||
* @see u8g2_t
|
* @see u8g2_t
|
||||||
* @see ButtonType
|
* @see ButtonType
|
||||||
*/
|
*/
|
||||||
class Widget
|
class Widget
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* @brief Constructs a widget with the given u8g2 display context
|
* @brief Constructs a widget with the given u8g2 display context
|
||||||
* @param u8g2 Pointer to the u8g2 display context used for rendering operations
|
* @param u8g2 Pointer to the u8g2 display context used for rendering operations
|
||||||
*
|
*
|
||||||
* @pre u8g2 must not be nullptr
|
* @pre u8g2 must not be nullptr
|
||||||
* @post Widget is initialized with the provided display context
|
* @post Widget is initialized with the provided display context
|
||||||
*
|
*
|
||||||
* @note The widget does not take ownership of the u8g2 context and assumes
|
* @note The widget does not take ownership of the u8g2 context and assumes
|
||||||
* it remains valid for the lifetime of the widget.
|
* it remains valid for the lifetime of the widget.
|
||||||
*/
|
*/
|
||||||
@@ -51,15 +51,20 @@ public:
|
|||||||
*/
|
*/
|
||||||
virtual ~Widget() = default;
|
virtual ~Widget() = default;
|
||||||
|
|
||||||
|
virtual void enter();
|
||||||
|
virtual void pause();
|
||||||
|
virtual void resume();
|
||||||
|
virtual void exit();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Updates the widget's internal state based on elapsed time
|
* @brief Updates the widget's internal state based on elapsed time
|
||||||
* @param dt Delta time in milliseconds since the last update call
|
* @param dt Delta time in milliseconds since the last update call
|
||||||
*
|
*
|
||||||
* @details This method is called once per frame by the UI system to handle
|
* @details This method is called once per frame by the UI system to handle
|
||||||
* animations, timers, state transitions, or other time-dependent behavior.
|
* animations, timers, state transitions, or other time-dependent behavior.
|
||||||
* The base implementation is empty, allowing derived classes to override
|
* The base implementation is empty, allowing derived classes to override
|
||||||
* only if time-based updates are needed.
|
* only if time-based updates are needed.
|
||||||
*
|
*
|
||||||
* @note Override this method in derived classes to implement time-based behavior
|
* @note Override this method in derived classes to implement time-based behavior
|
||||||
* such as animations, blinking effects, or timeout handling.
|
* such as animations, blinking effects, or timeout handling.
|
||||||
*/
|
*/
|
||||||
@@ -71,10 +76,10 @@ public:
|
|||||||
* their specific rendering logic using the u8g2 display context.
|
* their specific rendering logic using the u8g2 display context.
|
||||||
* The base implementation is empty, requiring derived classes to
|
* The base implementation is empty, requiring derived classes to
|
||||||
* provide their own rendering code.
|
* provide their own rendering code.
|
||||||
*
|
*
|
||||||
* @pre u8g2 context must be initialized and ready for drawing operations
|
* @pre u8g2 context must be initialized and ready for drawing operations
|
||||||
* @post Widget's visual representation is drawn to the display buffer
|
* @post Widget's visual representation is drawn to the display buffer
|
||||||
*
|
*
|
||||||
* @note This method is called during the rendering phase of each frame.
|
* @note This method is called during the rendering phase of each frame.
|
||||||
* Derived classes should use the u8g2 member variable to perform
|
* Derived classes should use the u8g2 member variable to perform
|
||||||
* drawing operations.
|
* drawing operations.
|
||||||
@@ -84,29 +89,29 @@ public:
|
|||||||
/**
|
/**
|
||||||
* @brief Handles button press events
|
* @brief Handles button press events
|
||||||
* @param button The type of button that was pressed
|
* @param button The type of button that was pressed
|
||||||
*
|
*
|
||||||
* @details This method is called when a button press event occurs and allows
|
* @details This method is called when a button press event occurs and allows
|
||||||
* the widget to respond to user input. The base implementation is empty,
|
* the widget to respond to user input. The base implementation is empty,
|
||||||
* allowing derived classes to override only if input handling is needed.
|
* allowing derived classes to override only if input handling is needed.
|
||||||
*
|
*
|
||||||
* @note Override this method in derived classes to implement button-specific
|
* @note Override this method in derived classes to implement button-specific
|
||||||
* behavior such as navigation, selection, or state changes.
|
* behavior such as navigation, selection, or state changes.
|
||||||
*
|
*
|
||||||
* @see ButtonType for available button types
|
* @see ButtonType for available button types
|
||||||
*/
|
*/
|
||||||
virtual void onButtonClicked(ButtonType button);
|
virtual void onButtonClicked(ButtonType button);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/**
|
/**
|
||||||
* @brief Pointer to the u8g2 display context used for rendering operations
|
* @brief Pointer to the u8g2 display context used for rendering operations
|
||||||
* @details This member provides access to the u8g2 graphics library functions
|
* @details This member provides access to the u8g2 graphics library functions
|
||||||
* for drawing text, shapes, bitmaps, and other UI elements. It is
|
* for drawing text, shapes, bitmaps, and other UI elements. It is
|
||||||
* initialized during construction and remains valid for the widget's lifetime.
|
* initialized during construction and remains valid for the widget's lifetime.
|
||||||
*
|
*
|
||||||
* @note This member is protected to allow derived classes direct access while
|
* @note This member is protected to allow derived classes direct access while
|
||||||
* preventing external modification. Derived classes should use this
|
* preventing external modification. Derived classes should use this
|
||||||
* context for all rendering operations.
|
* context for all rendering operations.
|
||||||
*
|
*
|
||||||
* @warning Do not modify or delete this pointer. The widget does not own
|
* @warning Do not modify or delete this pointer. The widget does not own
|
||||||
* the u8g2 context and assumes it is managed externally.
|
* the u8g2 context and assumes it is managed externally.
|
||||||
*/
|
*/
|
||||||
|
@@ -4,6 +4,22 @@ Widget::Widget(u8g2_t *u8g2) : u8g2(u8g2)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Widget::enter()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Widget::pause()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Widget::resume()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Widget::exit()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
void Widget::update(uint64_t dt)
|
void Widget::update(uint64_t dt)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@@ -45,7 +45,7 @@ void LightMenu::onButtonPressed(const MenuItem &menuItem, const ButtonType butto
|
|||||||
if (m_options && m_options->persistence && m_options->persistence->save)
|
if (m_options && m_options->persistence && m_options->persistence->save)
|
||||||
{
|
{
|
||||||
const auto value = getItem(item.getId()).getValue();
|
const auto value = getItem(item.getId()).getValue();
|
||||||
m_options->persistence->save("light_activated", value.c_str());
|
m_options->persistence->save(VALUE_TYPE_STRING, "light_activated", value.c_str());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -57,8 +57,8 @@ void LightMenu::onButtonPressed(const MenuItem &menuItem, const ButtonType butto
|
|||||||
{
|
{
|
||||||
if (m_options && m_options->persistence && m_options->persistence->save)
|
if (m_options && m_options->persistence && m_options->persistence->save)
|
||||||
{
|
{
|
||||||
const auto value = std::to_string(getItem(item.getId()).getIndex());
|
const auto value = getItem(item.getId()).getIndex();
|
||||||
m_options->persistence->save("light_mode", value.c_str());
|
m_options->persistence->save(VALUE_TYPE_INT32, "light_mode", &value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@@ -37,6 +37,6 @@ void LightSettingsMenu::onButtonPressed(const MenuItem &menuItem, const ButtonTy
|
|||||||
{
|
{
|
||||||
const auto key = "section_" + std::to_string(menuItem.getId());
|
const auto key = "section_" + std::to_string(menuItem.getId());
|
||||||
const auto value = getItem(menuItem.getId()).getValue();
|
const auto value = getItem(menuItem.getId()).getValue();
|
||||||
m_options->persistence->save(key.c_str(), value.c_str());
|
m_options->persistence->save(VALUE_TYPE_STRING, key.c_str(), value.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -1,6 +1,6 @@
|
|||||||
if (DEFINED ENV{IDF_PATH})
|
if (DEFINED ENV{IDF_PATH})
|
||||||
idf_component_register(SRCS
|
idf_component_register(SRCS
|
||||||
persistence.c
|
espressif/persistence.c
|
||||||
INCLUDE_DIRS "include"
|
INCLUDE_DIRS "include"
|
||||||
PRIV_REQUIRES
|
PRIV_REQUIRES
|
||||||
nvs_flash
|
nvs_flash
|
||||||
|
116
components/ruth/espressif/persistence.c
Normal file
116
components/ruth/espressif/persistence.c
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
#include "persistence.h"
|
||||||
|
|
||||||
|
#include "esp_err.h"
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include "esp_mac.h"
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/semphr.h"
|
||||||
|
#include "nvs_flash.h"
|
||||||
|
|
||||||
|
static const char *TAG = "persistence";
|
||||||
|
|
||||||
|
static nvs_handle_t persistence_handle;
|
||||||
|
static SemaphoreHandle_t persistence_mutex;
|
||||||
|
|
||||||
|
void *persistence_init(const char *namespace_name)
|
||||||
|
{
|
||||||
|
esp_err_t ret = nvs_flash_init();
|
||||||
|
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND)
|
||||||
|
{
|
||||||
|
ESP_ERROR_CHECK(nvs_flash_erase());
|
||||||
|
ret = nvs_flash_init();
|
||||||
|
}
|
||||||
|
ESP_ERROR_CHECK(ret);
|
||||||
|
|
||||||
|
ESP_ERROR_CHECK(nvs_open(namespace_name, NVS_READWRITE, &persistence_handle));
|
||||||
|
|
||||||
|
persistence_mutex = xSemaphoreCreateMutex();
|
||||||
|
if (persistence_mutex == NULL)
|
||||||
|
{
|
||||||
|
ESP_LOGE(TAG, "Failed to create mutex");
|
||||||
|
}
|
||||||
|
return &persistence_handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
void persistence_save(persistence_value_t value_type, const char *key, const void *value)
|
||||||
|
{
|
||||||
|
if (persistence_mutex != NULL)
|
||||||
|
{
|
||||||
|
if (xSemaphoreTake(persistence_mutex, portMAX_DELAY) == pdTRUE)
|
||||||
|
{
|
||||||
|
esp_err_t err = ESP_ERR_INVALID_ARG;
|
||||||
|
|
||||||
|
switch (value_type)
|
||||||
|
{
|
||||||
|
case VALUE_TYPE_STRING:
|
||||||
|
err = nvs_set_str(persistence_handle, key, (char *)value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VALUE_TYPE_INT32:
|
||||||
|
err = nvs_set_i32(persistence_handle, key, *(int32_t *)value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
ESP_LOGE(TAG, "Unsupported value type");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (err == ESP_OK)
|
||||||
|
{
|
||||||
|
ESP_ERROR_CHECK(nvs_commit(persistence_handle));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ESP_LOGE(TAG, "Error saving key %s: %s", key, esp_err_to_name(err));
|
||||||
|
}
|
||||||
|
|
||||||
|
xSemaphoreGive(persistence_mutex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void *persistence_load(persistence_value_t value_type, const char *key, void *out)
|
||||||
|
{
|
||||||
|
if (persistence_mutex != NULL)
|
||||||
|
{
|
||||||
|
if (xSemaphoreTake(persistence_mutex, portMAX_DELAY) == pdTRUE)
|
||||||
|
{
|
||||||
|
esp_err_t err = ESP_ERR_INVALID_ARG;
|
||||||
|
|
||||||
|
switch (value_type)
|
||||||
|
{
|
||||||
|
case VALUE_TYPE_STRING:
|
||||||
|
err = nvs_get_str(persistence_handle, key, (char *)out, NULL);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VALUE_TYPE_INT32:
|
||||||
|
err = nvs_get_i32(persistence_handle, key, (int32_t *)out);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
ESP_LOGE(TAG, "Unsupported value type");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (err != ESP_OK)
|
||||||
|
{
|
||||||
|
ESP_LOGE(TAG, "Error loading key %s: %s", key, esp_err_to_name(err));
|
||||||
|
}
|
||||||
|
|
||||||
|
xSemaphoreGive(persistence_mutex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
void persistence_deinit()
|
||||||
|
{
|
||||||
|
if (persistence_mutex != NULL)
|
||||||
|
{
|
||||||
|
vSemaphoreDelete(persistence_mutex);
|
||||||
|
persistence_mutex = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
nvs_close(persistence_handle);
|
||||||
|
}
|
@@ -9,10 +9,17 @@ typedef enum
|
|||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
void *handle;
|
void *handle;
|
||||||
void (*save)(const char *key, const char *value);
|
void (*save)(persistence_value_t value_type, const char *key, const void *value);
|
||||||
} persistence_t;
|
} persistence_t;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif
|
||||||
void *persistence_init(const char *namespace_name);
|
void *persistence_init(const char *namespace_name);
|
||||||
void persistence_save(persistence_value_t value_type, const char *key, const void *value);
|
void persistence_save(persistence_value_t value_type, const char *key, const void *value);
|
||||||
void *persistence_load(persistence_value_t value_type, const char *key, void *out);
|
void *persistence_load(persistence_value_t value_type, const char *key, void *out);
|
||||||
void persistence_deinit();
|
void persistence_deinit();
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
@@ -1,13 +1,25 @@
|
|||||||
#include "persistence.h"
|
#include "persistence.h"
|
||||||
#include "stddef.h"
|
#include "stddef.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
void *persistence_init(const char *namespace_name)
|
void *persistence_init(const char *namespace_name)
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void persistence_save(persistence_value_t value_type, const char *key, const void *value)
|
void persistence_save(const persistence_value_t value_type, const char *key, const void *value)
|
||||||
{
|
{
|
||||||
|
printf("Key: %s - ", key);
|
||||||
|
switch (value_type)
|
||||||
|
{
|
||||||
|
case VALUE_TYPE_STRING:
|
||||||
|
printf("Value (s): %s\n", (char *)value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VALUE_TYPE_INT32:
|
||||||
|
printf("Value (i): %d\n", *(int32_t *)value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void *persistence_load(persistence_value_t value_type, const char *key, void *out)
|
void *persistence_load(persistence_value_t value_type, const char *key, void *out)
|
||||||
@@ -17,121 +29,4 @@ void *persistence_load(persistence_value_t value_type, const char *key, void *ou
|
|||||||
|
|
||||||
void persistence_deinit()
|
void persistence_deinit()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
#include "esp_err.h"
|
|
||||||
#include "esp_log.h"
|
|
||||||
#include "esp_mac.h"
|
|
||||||
#include "freertos/FreeRTOS.h"
|
|
||||||
#include "freertos/semphr.h"
|
|
||||||
#include "nvs_flash.h"
|
|
||||||
|
|
||||||
static const char *TAG = "persistence";
|
|
||||||
|
|
||||||
static nvs_handle_t persistence_handle;
|
|
||||||
static SemaphoreHandle_t persistence_mutex;
|
|
||||||
|
|
||||||
void *persistence_init(const char *namespace_name)
|
|
||||||
{
|
|
||||||
esp_err_t ret = nvs_flash_init();
|
|
||||||
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND)
|
|
||||||
{
|
|
||||||
ESP_ERROR_CHECK(nvs_flash_erase());
|
|
||||||
ret = nvs_flash_init();
|
|
||||||
}
|
|
||||||
ESP_ERROR_CHECK(ret);
|
|
||||||
|
|
||||||
ESP_ERROR_CHECK(nvs_open(namespace_name, NVS_READWRITE, &persistence_handle));
|
|
||||||
|
|
||||||
persistence_mutex = xSemaphoreCreateMutex();
|
|
||||||
if (persistence_mutex == NULL)
|
|
||||||
{
|
|
||||||
ESP_LOGE(TAG, "Failed to create mutex");
|
|
||||||
}
|
|
||||||
return &persistence_handle;
|
|
||||||
}
|
|
||||||
|
|
||||||
void persistence_save(persistence_value_t value_type, const char *key, const void *value)
|
|
||||||
{
|
|
||||||
if (persistence_mutex != NULL)
|
|
||||||
{
|
|
||||||
if (xSemaphoreTake(persistence_mutex, portMAX_DELAY) == pdTRUE)
|
|
||||||
{
|
|
||||||
esp_err_t err = ESP_ERR_INVALID_ARG;
|
|
||||||
|
|
||||||
switch (value_type)
|
|
||||||
{
|
|
||||||
case VALUE_TYPE_STRING:
|
|
||||||
err = nvs_set_str(persistence_handle, key, (char *)value);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case VALUE_TYPE_INT32:
|
|
||||||
err = nvs_set_i32(persistence_handle, key, *(int32_t *)value);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
ESP_LOGE(TAG, "Unsupported value type");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (err == ESP_OK)
|
|
||||||
{
|
|
||||||
ESP_ERROR_CHECK(nvs_commit(persistence_handle));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ESP_LOGE(TAG, "Error saving key %s: %s", key, esp_err_to_name(err));
|
|
||||||
}
|
|
||||||
|
|
||||||
xSemaphoreGive(persistence_mutex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void *persistence_load(persistence_value_t value_type, const char *key, void *out)
|
|
||||||
{
|
|
||||||
if (persistence_mutex != NULL)
|
|
||||||
{
|
|
||||||
if (xSemaphoreTake(persistence_mutex, portMAX_DELAY) == pdTRUE)
|
|
||||||
{
|
|
||||||
esp_err_t err = ESP_ERR_INVALID_ARG;
|
|
||||||
|
|
||||||
switch (value_type)
|
|
||||||
{
|
|
||||||
case VALUE_TYPE_STRING:
|
|
||||||
err = nvs_get_str(persistence_handle, key, (char *)out, NULL);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case VALUE_TYPE_INT32:
|
|
||||||
err = nvs_get_i32(persistence_handle, key, (int32_t *)out);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
ESP_LOGE(TAG, "Unsupported value type");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (err != ESP_OK)
|
|
||||||
{
|
|
||||||
ESP_LOGE(TAG, "Error loading key %s: %s", key, esp_err_to_name(err));
|
|
||||||
}
|
|
||||||
|
|
||||||
xSemaphoreGive(persistence_mutex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
void persistence_deinit()
|
|
||||||
{
|
|
||||||
if (persistence_mutex != NULL)
|
|
||||||
{
|
|
||||||
vSemaphoreDelete(persistence_mutex);
|
|
||||||
persistence_mutex = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
nvs_close(persistence_handle);
|
|
||||||
}
|
|
||||||
*/
|
|
@@ -59,6 +59,7 @@ void setScreen(const std::shared_ptr<Widget> &screen)
|
|||||||
m_widget = screen;
|
m_widget = screen;
|
||||||
m_history.clear();
|
m_history.clear();
|
||||||
m_history.emplace_back(m_widget);
|
m_history.emplace_back(m_widget);
|
||||||
|
m_widget->enter();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,7 +67,12 @@ void pushScreen(const std::shared_ptr<Widget> &screen)
|
|||||||
{
|
{
|
||||||
if (screen != nullptr)
|
if (screen != nullptr)
|
||||||
{
|
{
|
||||||
|
if (m_widget)
|
||||||
|
{
|
||||||
|
m_widget->pause();
|
||||||
|
}
|
||||||
m_widget = screen;
|
m_widget = screen;
|
||||||
|
m_widget->enter();
|
||||||
m_history.emplace_back(m_widget);
|
m_history.emplace_back(m_widget);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -76,7 +82,12 @@ void popScreen()
|
|||||||
if (m_history.size() >= 2)
|
if (m_history.size() >= 2)
|
||||||
{
|
{
|
||||||
m_history.pop_back();
|
m_history.pop_back();
|
||||||
|
if (m_widget)
|
||||||
|
{
|
||||||
|
m_widget->exit();
|
||||||
|
}
|
||||||
m_widget = m_history.back();
|
m_widget = m_history.back();
|
||||||
|
m_widget->resume();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -3,6 +3,7 @@
|
|||||||
#include <hal/u8g2_hal_sdl.h>
|
#include <hal/u8g2_hal_sdl.h>
|
||||||
#include <u8g2.h>
|
#include <u8g2.h>
|
||||||
|
|
||||||
|
#include "persistence.h"
|
||||||
#include "MenuOptions.h"
|
#include "MenuOptions.h"
|
||||||
#include "common/InactivityTracker.h"
|
#include "common/InactivityTracker.h"
|
||||||
#include "ui/ScreenSaver.h"
|
#include "ui/ScreenSaver.h"
|
||||||
@@ -55,11 +56,15 @@ Device::Device(void *appstate) : UIWidget(appstate)
|
|||||||
m_children.push_back(std::make_shared<Button>(
|
m_children.push_back(std::make_shared<Button>(
|
||||||
GetContext(), U8G2_SCREEN_WIDTH * U8G2_SCREEN_FACTOR + 3 * U8G2_SCREEN_PADDING + DPAD_WIDTH,
|
GetContext(), U8G2_SCREEN_WIDTH * U8G2_SCREEN_FACTOR + 3 * U8G2_SCREEN_PADDING + DPAD_WIDTH,
|
||||||
U8G2_SCREEN_HEIGHT * U8G2_SCREEN_FACTOR + U8G2_SCREEN_PADDING - BUTTON_WIDTH, BUTTON_WIDTH,
|
U8G2_SCREEN_HEIGHT * U8G2_SCREEN_FACTOR + U8G2_SCREEN_PADDING - BUTTON_WIDTH, BUTTON_WIDTH,
|
||||||
[]() { PushKey(SDLK_RETURN); }));
|
[]() {
|
||||||
|
PushKey(SDLK_RETURN);
|
||||||
|
}));
|
||||||
m_children.push_back(std::make_shared<Button>(
|
m_children.push_back(std::make_shared<Button>(
|
||||||
GetContext(), U8G2_SCREEN_WIDTH * U8G2_SCREEN_FACTOR + 4 * U8G2_SCREEN_PADDING + DPAD_WIDTH + BUTTON_WIDTH,
|
GetContext(), U8G2_SCREEN_WIDTH * U8G2_SCREEN_FACTOR + 4 * U8G2_SCREEN_PADDING + DPAD_WIDTH + BUTTON_WIDTH,
|
||||||
U8G2_SCREEN_HEIGHT * U8G2_SCREEN_FACTOR + U8G2_SCREEN_PADDING - 2 * BUTTON_WIDTH, BUTTON_WIDTH,
|
U8G2_SCREEN_HEIGHT * U8G2_SCREEN_FACTOR + U8G2_SCREEN_PADDING - 2 * BUTTON_WIDTH, BUTTON_WIDTH,
|
||||||
[]() { PushKey(SDLK_BACKSPACE); }));
|
[]() {
|
||||||
|
PushKey(SDLK_BACKSPACE);
|
||||||
|
}));
|
||||||
m_children.push_back(std::make_shared<D_Pad>(
|
m_children.push_back(std::make_shared<D_Pad>(
|
||||||
GetContext(), U8G2_SCREEN_WIDTH * U8G2_SCREEN_FACTOR + 2 * U8G2_SCREEN_PADDING,
|
GetContext(), U8G2_SCREEN_WIDTH * U8G2_SCREEN_FACTOR + 2 * U8G2_SCREEN_PADDING,
|
||||||
U8G2_SCREEN_HEIGHT * U8G2_SCREEN_FACTOR + U8G2_SCREEN_PADDING - DPAD_WIDTH, DPAD_WIDTH, dpad_callback));
|
U8G2_SCREEN_HEIGHT * U8G2_SCREEN_FACTOR + U8G2_SCREEN_PADDING - DPAD_WIDTH, DPAD_WIDTH, dpad_callback));
|
||||||
@@ -67,13 +72,19 @@ Device::Device(void *appstate) : UIWidget(appstate)
|
|||||||
u8g2_Setup_sh1106_128x64_noname_f(&u8g2, U8G2_R0, u8x8_byte_sdl_hw_spi, u8x8_gpio_and_delay_sdl);
|
u8g2_Setup_sh1106_128x64_noname_f(&u8g2, U8G2_R0, u8x8_byte_sdl_hw_spi, u8x8_gpio_and_delay_sdl);
|
||||||
u8x8_InitDisplay(u8g2_GetU8x8(&u8g2));
|
u8x8_InitDisplay(u8g2_GetU8x8(&u8g2));
|
||||||
|
|
||||||
m_persistence = {.save = savePersistence};
|
m_persistence.save = persistence_save;
|
||||||
|
|
||||||
options = {
|
options = {
|
||||||
.u8g2 = &u8g2,
|
.u8g2 = &u8g2,
|
||||||
.setScreen = [this](const std::shared_ptr<Widget> &screen) { this->SetScreen(screen); },
|
.setScreen = [this](const std::shared_ptr<Widget> &screen) {
|
||||||
.pushScreen = [this](const std::shared_ptr<Widget> &screen) { this->PushScreen(screen); },
|
this->SetScreen(screen);
|
||||||
.popScreen = [this]() { this->PopScreen(); },
|
},
|
||||||
|
.pushScreen = [this](const std::shared_ptr<Widget> &screen) {
|
||||||
|
this->PushScreen(screen);
|
||||||
|
},
|
||||||
|
.popScreen = [this]() {
|
||||||
|
this->PopScreen();
|
||||||
|
},
|
||||||
.persistence = &m_persistence,
|
.persistence = &m_persistence,
|
||||||
};
|
};
|
||||||
m_widget = std::make_shared<SplashScreen>(&options);
|
m_widget = std::make_shared<SplashScreen>(&options);
|
||||||
@@ -90,6 +101,7 @@ void Device::SetScreen(const std::shared_ptr<Widget> &screen)
|
|||||||
m_widget = screen;
|
m_widget = screen;
|
||||||
m_history.clear();
|
m_history.clear();
|
||||||
m_history.emplace_back(m_widget);
|
m_history.emplace_back(m_widget);
|
||||||
|
m_widget->enter();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,8 +109,13 @@ void Device::PushScreen(const std::shared_ptr<Widget> &screen)
|
|||||||
{
|
{
|
||||||
if (screen != nullptr)
|
if (screen != nullptr)
|
||||||
{
|
{
|
||||||
|
if (m_widget)
|
||||||
|
{
|
||||||
|
m_widget->pause();
|
||||||
|
}
|
||||||
m_widget = screen;
|
m_widget = screen;
|
||||||
m_history.emplace_back(m_widget);
|
m_history.emplace_back(m_widget);
|
||||||
|
m_widget->enter();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,8 +123,13 @@ void Device::PopScreen()
|
|||||||
{
|
{
|
||||||
if (m_history.size() >= 2)
|
if (m_history.size() >= 2)
|
||||||
{
|
{
|
||||||
|
if (m_widget)
|
||||||
|
{
|
||||||
|
m_widget->exit();
|
||||||
|
}
|
||||||
m_history.pop_back();
|
m_history.pop_back();
|
||||||
m_widget = m_history.back();
|
m_widget = m_history.back();
|
||||||
|
m_widget->resume();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,11 +141,6 @@ void Device::PushKey(const SDL_Keycode key)
|
|||||||
SDL_PushEvent(&ev);
|
SDL_PushEvent(&ev);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Device::savePersistence(const char *key, const char *value)
|
|
||||||
{
|
|
||||||
SDL_Log("Saving: %s = %s", key, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Device::RenderU8G2() const
|
void Device::RenderU8G2() const
|
||||||
{
|
{
|
||||||
SDL_Surface *u8g2_surface = nullptr;
|
SDL_Surface *u8g2_surface = nullptr;
|
||||||
|
@@ -44,8 +44,6 @@ private:
|
|||||||
|
|
||||||
static void PushKey(SDL_Keycode key);
|
static void PushKey(SDL_Keycode key);
|
||||||
|
|
||||||
static void savePersistence(const char *key, const char *value);
|
|
||||||
|
|
||||||
std::vector<std::shared_ptr<UIWidget>> m_children{};
|
std::vector<std::shared_ptr<UIWidget>> m_children{};
|
||||||
std::shared_ptr<Widget> m_widget;
|
std::shared_ptr<Widget> m_widget;
|
||||||
std::vector<std::shared_ptr<Widget>> m_history;
|
std::vector<std::shared_ptr<Widget>> m_history;
|
||||||
|
Reference in New Issue
Block a user