Merge branch 'main' into lvgl_9.1

This commit is contained in:
KlausMu 2024-05-09 08:03:35 +02:00
commit d69913c323
29 changed files with 977 additions and 450 deletions

View File

@ -4,8 +4,10 @@
Preferences preferences; Preferences preferences;
std::string currentScene; std::string activeScene;
std::string currentGUIname; std::string activeGUIname;
int activeGUIlist;
int lastActiveGUIlistIndex;
void init_preferences_HAL(void) { void init_preferences_HAL(void) {
// Restore settings from internal flash memory // Restore settings from internal flash memory
@ -17,10 +19,12 @@ void init_preferences_HAL(void) {
// from tft.h // from tft.h
set_backlightBrightness_HAL(preferences.getUChar("blBrightness")); set_backlightBrightness_HAL(preferences.getUChar("blBrightness"));
// from here // from here
currentScene = std::string(preferences.getString("currentScene").c_str()); activeScene = std::string(preferences.getString("currentScene").c_str());
currentGUIname = std::string(preferences.getString("currentGUIname").c_str()); activeGUIname = std::string(preferences.getString("currentGUIname").c_str());
activeGUIlist =(preferences.getInt("currentGUIlist"));
lastActiveGUIlistIndex = (preferences.getInt("lastActiveIndex"));
// Serial.printf("Preferences restored: brightness %d, GUI %s, scene %s\r\n", get_backlightBrightness_HAL(), get_currentGUIname().c_str(), get_currentScene().c_str()); // Serial.printf("Preferences restored: brightness %d, GUI %s, scene %s\r\n", get_backlightBrightness_HAL(), get_activeGUIname().c_str(), get_activeScene().c_str());
} else { } else {
// Serial.printf("No preferences to restore\r\n"); // Serial.printf("No preferences to restore\r\n");
} }
@ -35,23 +39,37 @@ void save_preferences_HAL(void) {
preferences.putUInt("slpTimeout", get_sleepTimeout_HAL()); preferences.putUInt("slpTimeout", get_sleepTimeout_HAL());
preferences.putUChar("blBrightness", get_backlightBrightness_HAL()); preferences.putUChar("blBrightness", get_backlightBrightness_HAL());
// from here // from here
preferences.putString("currentScene", currentScene.c_str()); preferences.putString("currentScene", activeScene.c_str());
preferences.putString("currentGUIname", currentGUIname.c_str()); preferences.putString("currentGUIname", activeGUIname.c_str());
preferences.putInt("currentGUIlist", activeGUIlist);
preferences.putInt("lastActiveIndex", lastActiveGUIlistIndex);
if (!preferences.getBool("alreadySetUp")) { if (!preferences.getBool("alreadySetUp")) {
preferences.putBool("alreadySetUp", true); preferences.putBool("alreadySetUp", true);
} }
preferences.end(); preferences.end();
} }
std::string get_currentScene_HAL() { std::string get_activeScene_HAL() {
return currentScene; return activeScene;
} }
void set_currentScene_HAL(std::string aCurrentScene) { void set_activeScene_HAL(std::string anActiveScene) {
currentScene = aCurrentScene; activeScene = anActiveScene;
} }
std::string get_currentGUIname_HAL(){ std::string get_activeGUIname_HAL(){
return currentGUIname; return activeGUIname;
} }
void set_currentGUIname_HAL(std::string aCurrentGUIname) { void set_activeGUIname_HAL(std::string anActiveGUIname) {
currentGUIname = aCurrentGUIname; activeGUIname = anActiveGUIname;
}
int get_activeGUIlist_HAL() {
return activeGUIlist;
}
void set_activeGUIlist_HAL(int anActiveGUIlist) {
activeGUIlist = anActiveGUIlist;
}
int get_lastActiveGUIlistIndex_HAL() {
return lastActiveGUIlistIndex;
}
void set_lastActiveGUIlistIndex_HAL(int aGUIlistIndex) {
lastActiveGUIlistIndex = aGUIlistIndex;
} }

View File

@ -5,7 +5,11 @@
void init_preferences_HAL(void); void init_preferences_HAL(void);
void save_preferences_HAL(void); void save_preferences_HAL(void);
std::string get_currentScene_HAL(); std::string get_activeScene_HAL();
void set_currentScene_HAL(std::string aCurrentScene); void set_activeScene_HAL(std::string anActiveScene);
std::string get_currentGUIname_HAL(); std::string get_activeGUIname_HAL();
void set_currentGUIname_HAL(std::string aCurrentGUIname); void set_activeGUIname_HAL(std::string anActiveGUIname);
int get_activeGUIlist_HAL();
void set_activeGUIlist_HAL(int anActiveGUIlist);
int get_lastActiveGUIlistIndex_HAL();
void set_lastActiveGUIlistIndex_HAL(int aGUIlistIndex);

View File

@ -1,31 +1,58 @@
#include <string> #include <string>
std::string currentScene; enum GUIlists {
std::string currentGUIname; // MAIN_GUI_LIST: we are in the main_gui_list (with the scene selector as first gui), either if a scene is active or not
// SCENE_GUI_LIST: a scene is active and we are not in the main_gui_list. In that case, we try to use the scene specific gui list, if the scene defined one.
MAIN_GUI_LIST,
SCENE_GUI_LIST
};
/*
Possible example:
main_gui_list : "Scene selection", "Smart Home", "Settings", "IR Receiver"};
"Off" :
"TV" : "Numpad"
"Fire TV" : "Numpad", "Settings"
"Chromecast" :
"Apple TV" : "Apple TV", "Settings", "IR Receiver"
*/
std::string activeScene;
std::string activeGUIname;
int activeGUIlist;
int lastActiveGUIlistIndex;
void init_preferences_HAL(void) { void init_preferences_HAL(void) {
// set some values for tests
activeScene = ""; // "Off", "TV", "Fire TV", "Chromecast", "Apple TV";
activeGUIname = ""; // "Scene selection", "Smart Home", "Settings", "IR Receiver" // "Numpad", "Apple TV"
activeGUIlist = MAIN_GUI_LIST; // MAIN_GUI_LIST, SCENE_GUI_LIST;
lastActiveGUIlistIndex = 0;
} }
void save_preferences_HAL(void) { void save_preferences_HAL(void) {
} }
std::string get_currentScene_HAL() { std::string get_activeScene_HAL() {
// if (currentScene == "") { return activeScene;
// // set here something if you need it for a test at startup
// return "Apple TV";
// } else
{return currentScene;}
} }
void set_currentScene_HAL(std::string aCurrentScene) { void set_activeScene_HAL(std::string anActiveScene) {
currentScene = aCurrentScene; activeScene = anActiveScene;
} }
std::string get_currentGUIname_HAL(){ std::string get_activeGUIname_HAL(){
// if (currentGUIname == "") { return activeGUIname;
// // set here something if you need it for a test at startup
// return "IR Receiver"; // "Numpad"; // "Apple TV";
// } else
{return currentGUIname;}
} }
void set_currentGUIname_HAL(std::string aCurrentGUIname) { void set_activeGUIname_HAL(std::string anActiveGUIname) {
currentGUIname = aCurrentGUIname; activeGUIname = anActiveGUIname;
}
int get_activeGUIlist_HAL() {
return activeGUIlist;
}
void set_activeGUIlist_HAL(int anActiveGUIlist) {
activeGUIlist = anActiveGUIlist;
}
int get_lastActiveGUIlistIndex_HAL() {
return lastActiveGUIlistIndex;
}
void set_lastActiveGUIlistIndex_HAL(int aGUIlistIndex) {
lastActiveGUIlistIndex = aGUIlistIndex;
} }

View File

@ -5,7 +5,11 @@
void init_preferences_HAL(void); void init_preferences_HAL(void);
void save_preferences_HAL(void); void save_preferences_HAL(void);
std::string get_currentScene_HAL(); std::string get_activeScene_HAL();
void set_currentScene_HAL(std::string aCurrentScene); void set_activeScene_HAL(std::string anActiveScene);
std::string get_currentGUIname_HAL(); std::string get_activeGUIname_HAL();
void set_currentGUIname_HAL(std::string aCurrentGUIname); void set_activeGUIname_HAL(std::string anActiveGUIname);
int get_activeGUIlist_HAL();
void set_activeGUIlist_HAL(int anActiveGUIlist);
int get_lastActiveGUIlistIndex_HAL();
void set_lastActiveGUIlistIndex_HAL(int aGUIlistIndex);

View File

@ -232,6 +232,13 @@ void executeCommandWithData(uint16_t command, commandData commandData, std::stri
break; break;
} }
case GUI: {
// let the sceneHandler find and show the gui
Serial.printf("execute: will send gui command to the sceneHandler\r\n");
handleGUI(command, commandData, additionalPayload);
break;
}
case SPECIAL: { case SPECIAL: {
if (command == MY_SPECIAL_COMMAND) { if (command == MY_SPECIAL_COMMAND) {
// do your special command here // do your special command here

View File

@ -94,6 +94,7 @@ extern uint16_t KEYBOARD_VOLUME_DECREMENT;
enum commandHandlers { enum commandHandlers {
SPECIAL, SPECIAL,
SCENE, SCENE,
GUI,
IR, IR,
#if (ENABLE_WIFI_AND_MQTT == 1) #if (ENABLE_WIFI_AND_MQTT == 1)
MQTT, MQTT,

View File

@ -15,8 +15,6 @@ lv_obj_t* BluetoothLabel = NULL;
lv_obj_t* BattPercentageLabel = NULL; lv_obj_t* BattPercentageLabel = NULL;
lv_obj_t* BattIconLabel = NULL; lv_obj_t* BattIconLabel = NULL;
lv_obj_t* SceneLabel = NULL; lv_obj_t* SceneLabel = NULL;
uint32_t currentTabID = -1; // id of the current tab
uint32_t oldTabID = -1;
lv_obj_t* tabview = NULL; lv_obj_t* tabview = NULL;
// page indicator // page indicator
@ -30,8 +28,8 @@ lv_style_t panel_style;
lv_style_t style_red_border; lv_style_t style_red_border;
#endif #endif
void guis_doTabCreationAtStartup(); void guis_doTabCreationOnStartup();
void guis_doAfterSliding(int oldTabID, int newTabID, bool newGuiList); void guis_doTabCreationAfterSliding(int newTabID);
// Helper Functions ----------------------------------------------------------------------------------------------------------------------- // Helper Functions -----------------------------------------------------------------------------------------------------------------------
@ -89,28 +87,28 @@ void tabview_content_is_scrolling_event_cb(lv_event_t* e){
// ----------------------- // -----------------------
static bool waitBeforeActionAfterSlidingAnimationEnded = false; static bool waitBeforeActionAfterSlidingAnimationEnded = false;
static unsigned long waitBeforeActionAfterSlidingAnimationEnded_timerStart; static unsigned long waitBeforeActionAfterSlidingAnimationEnded_timerStart;
static int newTabID_forLateTabCreation;
// This is the callback when the animation of the tab sliding ended // This is the callback when the animation of the tab sliding ended
static void tabview_animation_ready_cb(lv_anim_t* a) { static void tabview_animation_ready_cb(lv_anim_t* a) {
// Unfortunately, the animation has not completely ended here. We cannot do the recreation of the tabs here. // Unfortunately, the animation has not completely ended here. We cannot do the recreation of the tabs here.
// We have to wait some more milliseconds or at least one cycle of lv_timer_handler(); // We have to wait some more milliseconds or at least one cycle of lv_timer_handler();
// calling lv_timer_handler(); here does not help // calling lv_timer_handler(); here does not help
// lv_timer_handler(); // lv_timer_handler();
// guis_doAfterSliding(oldTabID, currentTabID, false); // guis_doTabCreationAfterSliding(newTabID_forLateTabCreation);
waitBeforeActionAfterSlidingAnimationEnded = true; waitBeforeActionAfterSlidingAnimationEnded = true;
waitBeforeActionAfterSlidingAnimationEnded_timerStart = millis(); waitBeforeActionAfterSlidingAnimationEnded_timerStart = millis();
} }
// Update currentTabID when a new tab is selected // Update gui when a new tab is selected
// this is a callback if the tabview is changed (LV_EVENT_VALUE_CHANGED) // this is a callback if the tabview is changed (LV_EVENT_VALUE_CHANGED)
// Sent when a new tab is selected by sliding or clicking the tab button. lv_tabview_get_tab_act(tabview) returns the zero based index of the current tab. // Sent when a new tab is selected by sliding or clicking the tab button. lv_tabview_get_tab_act(tabview) returns the zero based index of the current tab.
void tabview_tab_changed_event_cb(lv_event_t* e) { void tabview_tab_changed_event_cb(lv_event_t* e) {
if (lv_event_get_code(e) == LV_EVENT_VALUE_CHANGED) { if (lv_event_get_code(e) == LV_EVENT_VALUE_CHANGED) {
oldTabID = currentTabID; int newTabID = lv_tabview_get_tab_active((lv_obj_t*)lv_event_get_target(e));
currentTabID = lv_tabview_get_tab_active((lv_obj_t*)lv_event_get_target(e));
// Wait until the animation ended, then call "guis_doAfterSliding(oldTabID, currentTabID, false);" // Wait until the animation ended, then call "guis_doTabCreationAfterSliding(newTabID);"
// https://forum.lvgl.io/t/delete-a-tab-after-the-tabview-scroll-animation-is-complete/3155/4 // https://forum.lvgl.io/t/delete-a-tab-after-the-tabview-scroll-animation-is-complete/3155/4
lv_obj_t* myTabview = (lv_obj_t*)lv_event_get_target(e); lv_obj_t* myTabview = (lv_obj_t*)lv_event_get_target(e);
lv_obj_t* tabContainer = lv_tabview_get_content(myTabview); lv_obj_t* tabContainer = lv_tabview_get_content(myTabview);
@ -118,11 +116,12 @@ void tabview_tab_changed_event_cb(lv_event_t* e) {
if(anim) { if(anim) {
// Swipe is not yet complete. User released the touch screen, an animation will bring it to the end. // Swipe is not yet complete. User released the touch screen, an animation will bring it to the end.
// That's the normal (and only?) case for the tft touchscreen // That's the normal (and only?) case for the tft touchscreen
newTabID_forLateTabCreation = newTabID;
lv_anim_set_completed_cb(anim, tabview_animation_ready_cb); lv_anim_set_completed_cb(anim, tabview_animation_ready_cb);
} else { } else {
// Swipe is complete, no additional animation is needed. Most likely only possible in simulator // Swipe is complete, no additional animation is needed. Most likely only possible in simulator
Serial.println("Change of tab detected, without animation at the end. Will directly do my job after sliding."); Serial.println("Change of tab detected, without animation at the end. Will directly do my job after sliding.");
guis_doAfterSliding(oldTabID, currentTabID, false); guis_doTabCreationAfterSliding(newTabID);
} }
} }
} }
@ -156,8 +155,8 @@ void init_gui(void) {
lv_obj_set_style_bg_color(lv_screen_active(), lv_color_black(), LV_PART_MAIN); lv_obj_set_style_bg_color(lv_screen_active(), lv_color_black(), LV_PART_MAIN);
// set default height and position of main widgets // set default height and position of main widgets
setMainWidgetsHeightAndPosition(); setMainWidgetsHeightAndPosition();
// At startup, set current GUI according to get_currentGUIname(), and create the content of that tab (and the previous and the next) for the first time // On startup, set current GUIname and GUIlist according to last state before going to sleep
guis_doTabCreationAtStartup(); guis_doTabCreationOnStartup();
// memoryUsage bar // memoryUsage bar
init_gui_memoryUsage_bar(); init_gui_memoryUsage_bar();
// status bar // status bar
@ -272,6 +271,7 @@ void init_gui_status_bar() {
lv_obj_align(SceneLabel, LV_ALIGN_TOP_MID, 0, labelsPositionTopStatusbar); lv_obj_align(SceneLabel, LV_ALIGN_TOP_MID, 0, labelsPositionTopStatusbar);
lv_obj_set_style_text_font(SceneLabel, &lv_font_montserrat_12, LV_PART_MAIN); lv_obj_set_style_text_font(SceneLabel, &lv_font_montserrat_12, LV_PART_MAIN);
lv_obj_add_flag(SceneLabel, LV_OBJ_FLAG_CLICKABLE); lv_obj_add_flag(SceneLabel, LV_OBJ_FLAG_CLICKABLE);
lv_obj_set_user_data(SceneLabel,(void *)(intptr_t)0);
lv_obj_add_event_cb(SceneLabel, sceneLabel_or_pageIndicator_event_cb, LV_EVENT_CLICKED, NULL); lv_obj_add_event_cb(SceneLabel, sceneLabel_or_pageIndicator_event_cb, LV_EVENT_CLICKED, NULL);
// Battery ---------------------------------------------------------------------- // Battery ----------------------------------------------------------------------
@ -294,12 +294,12 @@ void gui_loop(void) {
waitBeforeActionAfterSlidingAnimationEnded = false; waitBeforeActionAfterSlidingAnimationEnded = false;
} else if (waitOneLoop) { } else if (waitOneLoop) {
waitOneLoop = false; waitOneLoop = false;
guis_doAfterSliding(oldTabID, currentTabID, false); guis_doTabCreationAfterSliding(newTabID_forLateTabCreation);
}; };
// // as alternative, we could wait some milliseconds. But one cycle of gui_loop() works well. // // as alternative, we could wait some milliseconds. But one cycle of gui_loop() works well.
// if (waitBeforeActionAfterSlidingAnimationEnded) { // if (waitBeforeActionAfterSlidingAnimationEnded) {
// if (millis() - waitBeforeActionAfterSlidingAnimationEnded_timerStart >= 5) { // if (millis() - waitBeforeActionAfterSlidingAnimationEnded_timerStart >= 5) {
// guis_doAfterSliding(oldTabID, currentTabID, false); // guis_doTabCreationAfterSliding(newTabID_forLateTabCreation);
// waitBeforeActionAfterSlidingAnimationEnded = false; // waitBeforeActionAfterSlidingAnimationEnded = false;
// } // }
// } // }
@ -307,19 +307,35 @@ void gui_loop(void) {
lv_timer_handler(); lv_timer_handler();
} }
void guis_doTabCreationAtStartup() { // ------------------------------------------------------------------------------------------------------------
gui_memoryOptimizer_prepare_startup(); // There are several reasons why the tabs could get recreated. All are going through these functions in "guiBase.cpp", which are calling functions in "guiMemoryOptimizer.cpp"
// 1. tab creation on startup (called by init_gui())
guis_doAfterSliding(-1, -1, false); void guis_doTabCreationOnStartup() {
} gui_memoryOptimizer_onStartup(&tabview, &panel, &img1, &img2);
void guis_doAfterSliding(int oldTabID, int newTabID, bool newGuiList) {
// With parameter newGuiList it is signaled that we are changing from a scene specific list to the main list or vice versa
// In that case, we have to do special treatment because we are not simply sliding to the left or to the right, but we start newly with a different gui list.
gui_memoryOptimizer_doAfterSliding_deletionAndCreation(&tabview, oldTabID, newTabID, newGuiList, &panel, &img1, &img2);
doLogMemoryUsage(); doLogMemoryUsage();
} }
// 2. tab creation after sliding (called by tabview_tab_changed_event_cb())
void guis_doTabCreationAfterSliding(int newTabID) {
gui_memoryOptimizer_afterSliding(&tabview, &panel, &img1, &img2, newTabID);
doLogMemoryUsage();
}
// 3. after gui list has changed (called by handleScene()), when switching between main_gui_list and scene specific list. Will show first GUi in list
void guis_doTabCreationAfterGUIlistChanged(GUIlists newGUIlist) {
gui_memoryOptimizer_afterGUIlistChanged(&tabview, &panel, &img1, &img2, newGUIlist);
doLogMemoryUsage();
}
// 4. navigate to a specific GUI in gui_list
void guis_doTabCreationForSpecificGUI(GUIlists GUIlist, int gui_list_index) {
gui_memoryOptimizer_navigateToGUI(&tabview, &panel, &img1, &img2, GUIlist, gui_list_index);
doLogMemoryUsage();
}
// 5. navigate back to last active gui of previous gui_list
void guis_doTabCreationForNavigateToLastActiveGUIofPreviousGUIlist() {
gui_memoryOptimizer_navigateToLastActiveGUIofPreviousGUIlist(&tabview, &panel, &img1, &img2);
doLogMemoryUsage();
}
// ------------------------------------------------------------------------------------------------------------
void setActiveTab(uint32_t index, lv_anim_enable_t anim_en, bool send_tab_changed_event) { void setActiveTab(uint32_t index, lv_anim_enable_t anim_en, bool send_tab_changed_event) {
// unsigned long startTime = millis(); // unsigned long startTime = millis();

View File

@ -1,6 +1,7 @@
#pragma once #pragma once
#include <lvgl.h> #include <lvgl.h>
#include "applicationInternal/gui/guiMemoryOptimizer.h"
// used by memoryUsage.cpp // used by memoryUsage.cpp
extern lv_span_t* MemoryUsageSpanHeap; extern lv_span_t* MemoryUsageSpanHeap;
@ -17,7 +18,6 @@ extern lv_style_t panel_style;
extern int tabviewTop; extern int tabviewTop;
extern int tabviewHeight; extern int tabviewHeight;
extern int panelHeight; extern int panelHeight;
extern uint32_t currentTabID;
// used by almost all gui_*.cpp // used by almost all gui_*.cpp
extern lv_color_t color_primary; extern lv_color_t color_primary;
@ -26,18 +26,22 @@ extern lv_color_t color_primary;
extern lv_style_t style_red_border; extern lv_style_t style_red_border;
#endif #endif
// used by main.cpp and sceneHandler.cpp // used by main.cpp
void init_gui(void); void init_gui(void);
// used by main.cpp and sceneHandler.cpp
void gui_loop(void); void gui_loop(void);
// used by guiMemoryOptimizer.cpp // used by guiMemoryOptimizer.cpp
void tabview_content_is_scrolling_event_cb(lv_event_t* e); void tabview_content_is_scrolling_event_cb(lv_event_t* e);
void tabview_tab_changed_event_cb(lv_event_t* e); void tabview_tab_changed_event_cb(lv_event_t* e);
void sceneLabel_or_pageIndicator_event_cb(lv_event_t* e); void sceneLabel_or_pageIndicator_event_cb(lv_event_t* e);
void pageIndicator_navigate_event_cb(lv_event_t* e); void pageIndicator_navigate_event_cb(lv_event_t* e);
// used by sceneHandler.cpp
void guis_doTabCreationAfterGUIlistChanged(GUIlists newGUIlist);
void guis_doTabCreationForSpecificGUI(GUIlists GUIlist, int gui_list_index);
void guis_doTabCreationForNavigateToLastActiveGUIofPreviousGUIlist();
// used by guiMemoryOptimizer.cpp and sceneHandler.cpp
void setActiveTab(uint32_t index, lv_anim_enable_t anim_en, bool send_tab_changed_event = false); void setActiveTab(uint32_t index, lv_anim_enable_t anim_en, bool send_tab_changed_event = false);
// used by memoryUsage.cpp // used by memoryUsage.cpp
void showMemoryUsageBar(bool showBar); void showMemoryUsageBar(bool showBar);
// used by commandHandler to show WiFi status // used by commandHandler to show WiFi status
void showWiFiConnected(bool connected); void showWiFiConnected(bool connected);
void guis_doAfterSliding(int oldTabID, int newTabID, bool newGuiList);

View File

@ -1,47 +1,101 @@
#include <lvgl.h> #include <lvgl.h>
#include "applicationInternal/gui/guiBase.h" #include "applicationInternal/gui/guiBase.h"
#include "applicationInternal/gui/guiMemoryOptimizer.h"
#include "applicationInternal/gui/guiRegistry.h" #include "applicationInternal/gui/guiRegistry.h"
#include "applicationInternal/scenes/sceneRegistry.h"
#include "applicationInternal/hardware/hardwarePresenter.h" #include "applicationInternal/hardware/hardwarePresenter.h"
#include "applicationInternal/scenes/sceneRegistry.h"
struct tab_in_memory { struct t_gui_on_tab {
lv_obj_t* tab; lv_obj_t* tab;
int listIndex; std::string GUIname;
std::string guiName; int gui_list_index;
int gui_list_index_previous;
}; };
tab_in_memory tabs_in_memory[3] = {{NULL, -1, ""}, {NULL, -1, ""}, {NULL, -1, ""}}; struct t_gui_state {
// holds the ids of the tabs we had in memory before, so that we can determine the next or previous id // the next three and the last are saved in the preferenceStorage every time they change
int tabs_in_memory_previous_listIndex[3]= {-1 , -1, -1}; std::string activeScene_internalDontUse;
std::string activeGUIname_internalDontUse;
GUIlists activeGUIlist_internalDontUse;
// ---
int activeTabID = -1; // id of the active tab (one of 0,1,2)
int oldTabID = -1; // id of the tab before swiping (one of 0,1,2)
t_gui_on_tab gui_on_tab[3] = {{NULL, "", -1, -1}, {NULL, "", -1, -1}, {NULL, "", -1, -1}};
// the last active gui of scene. Will be stored to easily navigate back to it with guis_doTabCreationForNavigateToLastActiveGUIofPreviousGUIlist()
GUIlists last_active_gui_list = (GUIlists)-1;
int last_active_gui_list_index_internalDontUse = -1;
};
t_gui_state gui_state;
// Both the gui_state and the preferenceStorage should know at any time the current state (scene, GUIname, and GUIlist)
// preferenceStorage should know it because when going to sleep, it should persist the state in NVM.
// So whenever values change, it should be done through these functions.
// On startup, the gui_state is set by gui_memoryOptimizer_onStartup()
std::string gui_memoryOptimizer_getActiveSceneName() {
gui_state.activeScene_internalDontUse = get_activeScene();
return gui_state.activeScene_internalDontUse;
}
void gui_memoryOptimizer_setActiveSceneName(std::string aSceneName) {
gui_state.activeScene_internalDontUse = aSceneName;
set_activeScene(aSceneName);
}
std::string gui_memoryOptimizer_getActiveGUIname() {
gui_state.activeGUIname_internalDontUse = get_activeGUIname();
return gui_state.activeGUIname_internalDontUse;
}
void gui_memoryOptimizer_setActiveGUIname(std::string aGUIname) {
gui_state.activeGUIname_internalDontUse = aGUIname;
set_activeGUIname(aGUIname);
}
GUIlists gui_memoryOptimizer_getActiveGUIlist() {
gui_state.activeGUIlist_internalDontUse = (GUIlists)get_activeGUIlist();
return gui_state.activeGUIlist_internalDontUse;
}
void gui_memoryOptimizer_setActiveGUIlist(GUIlists aGUIlist) {
gui_state.activeGUIlist_internalDontUse = aGUIlist;
set_activeGUIlist(aGUIlist);
}
int gui_memoryOptimizer_getLastActiveGUIlistIndex() {
gui_state.last_active_gui_list_index_internalDontUse = get_lastActiveGUIlistIndex();
return gui_state.last_active_gui_list_index_internalDontUse;
}
void gui_memoryOptimizer_setLastActiveGUIlistIndex(int aGUIlistIndex) {
gui_state.last_active_gui_list_index_internalDontUse = aGUIlistIndex;
set_lastActiveGUIlistIndex(aGUIlistIndex);
}
int gui_memoryOptimizer_getActiveTabID() {
return gui_state.activeTabID;
}
bool gui_memoryOptimizer_isTabIDInMemory(int tabID) { bool gui_memoryOptimizer_isTabIDInMemory(int tabID) {
// range check // range check
if ((tabID < 0) || (tabID >= 3)) { if ((tabID < 0) || (tabID >= 3)) {
return false; return false;
} }
return (tabs_in_memory[tabID].listIndex != -1); return (gui_state.gui_on_tab[tabID].gui_list_index != -1);
} }
bool gui_memoryOptimizer_isGUInameInMemory(std::string guiName) { bool gui_memoryOptimizer_isGUInameInMemory(std::string GUIname) {
for (uint8_t index=0; index <= 2; index++) { for (uint8_t index=0; index <= 2; index++) {
if (tabs_in_memory[index].guiName == guiName) { if (gui_state.gui_on_tab[index].GUIname == GUIname) {
return true; return true;
} }
} }
return false; return false;
} }
void notify_active_tabs_before_delete() { void notify_active_tabs_before_delete(t_gui_state *gui_state) {
Serial.printf(" Will notify tabs about deletion\r\n"); Serial.printf(" Will notify tabs about deletion\r\n");
std::string nameOfTab; std::string nameOfTab;
for (int index=0; index <= 2; index++) { for (int index=0; index <= 2; index++) {
if (tabs_in_memory[index].listIndex == -1) { if (gui_state->gui_on_tab[index].gui_list_index == -1) {
Serial.printf(" Will not notify tab %d about deletion because it does not exist\r\n", index); Serial.printf(" Will not notify tab %d about deletion because it does not exist\r\n", index);
continue; continue;
} }
// For deletion, do not use the listIndex, but the name of the gui. // For deletion, do not use the gui_list_index, but the name of the gui.
// The gui_list might have changed (when switching from a scene specific list to the main list or vice versa), so index could have changed as well. // The gui_list might have changed (when switching from a scene specific list to the main list or vice versa), so index could have changed as well.
nameOfTab = tabs_in_memory[index].guiName; nameOfTab = gui_state->gui_on_tab[index].GUIname;
if (nameOfTab == "") { if (nameOfTab == "") {
Serial.printf(" Will not notify tab %d about deletion because it is not set\r\n", index); Serial.printf(" Will not notify tab %d about deletion because it is not set\r\n", index);
} else if (registered_guis_byName_map.count(nameOfTab) == 0) { } else if (registered_guis_byName_map.count(nameOfTab) == 0) {
@ -53,7 +107,7 @@ void notify_active_tabs_before_delete() {
} }
} }
void clear_tabview(lv_obj_t* tabview) { void clear_tabview(lv_obj_t* tabview, t_gui_state *gui_state) {
if (tabview != NULL) { if (tabview != NULL) {
// first remove events for the tabview // first remove events for the tabview
lv_obj_remove_event_cb(tabview, tabview_tab_changed_event_cb); lv_obj_remove_event_cb(tabview, tabview_tab_changed_event_cb);
@ -63,10 +117,10 @@ void clear_tabview(lv_obj_t* tabview) {
tabview = NULL; tabview = NULL;
} }
// set struct tabs_in_memory to NULL // the gui_list_index_previous is needed for setGUIlistIndicesToBeShown_afterSlide();
tabs_in_memory[0] = {NULL, -1, ""}; gui_state->gui_on_tab[0] = {NULL, "", -1, gui_state->gui_on_tab[0].gui_list_index};
tabs_in_memory[1] = {NULL, -1, ""}; gui_state->gui_on_tab[1] = {NULL, "", -1, gui_state->gui_on_tab[1].gui_list_index};
tabs_in_memory[2] = {NULL, -1, ""}; gui_state->gui_on_tab[2] = {NULL, "", -1, gui_state->gui_on_tab[2].gui_list_index};
} }
@ -116,162 +170,147 @@ lv_obj_t* create_panel() {
std::string get_name_of_gui_to_be_shown(int index) { std::string get_name_of_gui_to_be_shown(int index) {
if (index == -1) { if (index == -1) {
return ""; return "";
} else if (index <= get_gui_list(get_currentScene())->size() -1) { } else if (index <= get_gui_list_active_withFallback()->size() -1) {
return get_gui_list(get_currentScene())->at(index); return get_gui_list_active_withFallback()->at(index);
} else { } else {
return ""; return "";
} }
} }
void create_new_tab(lv_obj_t* tabview, uint32_t tabs_in_memory_index) { void create_new_tab(lv_obj_t* tabview, t_gui_on_tab *gui_on_tab) {
std::string nameOfTab = get_name_of_gui_to_be_shown(tabs_in_memory[tabs_in_memory_index].listIndex); std::string nameOfTab = get_name_of_gui_to_be_shown(gui_on_tab->gui_list_index);
if (nameOfTab == "") { if (nameOfTab == "") {
Serial.printf(" Will not create new tab at index %d because no name was provided\r\n", tabs_in_memory_index); Serial.printf(" Will not create new tab because no name was provided\r\n");
} else if (registered_guis_byName_map.count(nameOfTab) == 0) { } else if (registered_guis_byName_map.count(nameOfTab) == 0) {
Serial.printf(" Will not create new tab at index %d because name %s was not found in registry\r\n", tabs_in_memory_index, nameOfTab.c_str()); Serial.printf(" Will not create new tab because name %s was not found in registry\r\n", nameOfTab.c_str());
} else { } else {
Serial.printf(" Will create tab with name \"%s\" at index %d\r\n", nameOfTab.c_str(), tabs_in_memory_index); Serial.printf(" Will create tab with name \"%s\" \r\n", nameOfTab.c_str());
// save name of tab for deletion later // save name of tab for deletion later
tabs_in_memory[tabs_in_memory_index].guiName = nameOfTab; gui_on_tab->GUIname = nameOfTab;
// create tab and save pointer to tab in tabs_in_memory // create tab and save pointer to tab in gui_on_tab
tabs_in_memory[tabs_in_memory_index].tab = lv_tabview_add_tab(tabview, nameOfTab.c_str()); gui_on_tab->tab = lv_tabview_add_tab(tabview, nameOfTab.c_str());
// let the gui create it's content // let the gui create it's content
registered_guis_byName_map.at(nameOfTab).this_create_tab_content(tabs_in_memory[tabs_in_memory_index].tab); registered_guis_byName_map.at(nameOfTab).this_create_tab_content(gui_on_tab->tab);
} }
} }
void doTabCreation_strategyMax3(lv_obj_t* tabview, uint32_t oldTabID, uint32_t newTabID) { // create up to three tabs and the content of the tabs
// create up to three tabs and the content of the tabs /*
/* example: gui_list: 0 1 2 3 4
example: gui_list: 0 1 2 3 4 in memory active
in memory active 0 1 -1 0 <- first state, special case - also the initial state
0 1 -1 0 <- first state, special case - also the initial state 0 1 2 1
0 1 2 1 1 2 3 1
1 2 3 1 2 3 4 1
2 3 4 1 3 4 -1 1 <- last state, special case
3 4 -1 1 <- last state, special case */
*/ void setGUIlistIndicesToBeShown_forSpecificGUIlistIndex(int gui_list_index, t_gui_state *gui_state) {
// Set the gui_list_indeces to be shown for a specific gui_list_index
if (gui_list_index == 0) {
// first state
Serial.printf(" GUIlistIndices: will resume at specific index with \"first state\"\r\n");
gui_state->gui_on_tab[0] = {NULL, "", 0};
// take care if there is only one gui in list
gui_state->gui_on_tab[1] = {NULL, "", get_gui_list_active_withFallback()->size() >= 2 ? 1 : -1};
gui_state->gui_on_tab[2] = {NULL, "", -1};
gui_state->activeTabID = 0;
} else if (gui_list_index == get_gui_list_active_withFallback()->size() -1) {
// last state
Serial.printf(" GUIlistIndices: will resume at specific index with \"last state\"\r\n");
gui_state->gui_on_tab[0] = {NULL, "", gui_list_index -1};
gui_state->gui_on_tab[1] = {NULL, "", gui_list_index};
gui_state->gui_on_tab[2] = {NULL, "", -1};
gui_state->activeTabID = 1;
} else {
// any other state
Serial.printf(" GUIlistIndices: will resume at specific index with \"state between\"\r\n");
gui_state->gui_on_tab[0] = {NULL, "", gui_list_index -1};
gui_state->gui_on_tab[1] = {NULL, "", gui_list_index};
gui_state->gui_on_tab[2] = {NULL, "", gui_list_index +1};
gui_state->activeTabID = 1;
}
}
int tabToBeActivated = -1; void setGUIlistIndicesToBeShown_forFirstGUIinGUIlist(t_gui_state *gui_state) {
Serial.printf(" GUIlistIndices: will show the first gui from \"gui_list\" as initial state\r\n");
// take care if there is no gui in list
gui_state->gui_on_tab[0] = {NULL, "", get_gui_list_active_withFallback()->size() != 0 ? 0 : -1};
// take care if there is only one gui in list
gui_state->gui_on_tab[1] = {NULL, "", get_gui_list_active_withFallback()->size() >= 2 ? 1 : -1};
gui_state->gui_on_tab[2] = {NULL, "", -1};
gui_state->activeTabID = 0;
}
void setGUIlistIndicesToBeShown_afterSlide(t_gui_state *gui_state) {
int oldListIndex = -1; int oldListIndex = -1;
if ((oldTabID == -1) && (newTabID == -1)) { if (gui_state->oldTabID > gui_state->activeTabID) {
// This is the initialization after the ESP32 has booted.
if ((tabs_in_memory_previous_listIndex[0] < get_gui_list(get_currentScene())->size()) && (tabs_in_memory_previous_listIndex[0] != -1)) {
// In gui_memoryOptimizer_prepare_startup, the index of get_currentGUIname() in gui_list was saved, if found.
// We can resume at this old state.
oldListIndex = tabs_in_memory_previous_listIndex[0] ;
if (oldListIndex == 0) {
// first state
Serial.printf(" Startup: will resume where we went to sleep with \"first state\"\r\n");
tabs_in_memory[0] = {NULL, 0};
// take care if there is only one gui in list
tabs_in_memory[1] = {NULL, get_gui_list(get_currentScene())->size() >= 2 ? 1 : -1};
tabs_in_memory[2] = {NULL, -1};
tabToBeActivated = 0;
} else if (oldListIndex == get_gui_list(get_currentScene())->size() -1) {
// last state
Serial.printf(" Startup: will resume where we went to sleep with \"last state\"\r\n");
tabs_in_memory[0] = {NULL, oldListIndex -1};
tabs_in_memory[1] = {NULL, oldListIndex};
tabs_in_memory[2] = {NULL, -1};
tabToBeActivated = 1;
} else {
// any other state
Serial.printf(" Startup: will resume where we went to sleep with \"state between\"\r\n");
tabs_in_memory[0] = {NULL, oldListIndex -1};
tabs_in_memory[1] = {NULL, oldListIndex};
tabs_in_memory[2] = {NULL, oldListIndex +1};
tabToBeActivated = 1;
}
} else {
Serial.printf(" Startup: cannot resume old state, so we will show the first tabs from \"gui_list\" as initial state\r\n");
// take care if there is no gui in list
tabs_in_memory[0] = {NULL, get_gui_list(get_currentScene())->size() != 0 ? 0 : -1};
// take care if there is only one gui in list
tabs_in_memory[1] = {NULL, get_gui_list(get_currentScene())->size() >= 2 ? 1 : -1};
tabs_in_memory[2] = {NULL, -1};
tabToBeActivated = 0;
}
} else if (oldTabID > newTabID) {
// swipe to previous item in list // swipe to previous item in list
Serial.printf(" Will swipe to previous item in list\r\n"); Serial.printf(" Will swipe to previous item in list\r\n");
oldListIndex = tabs_in_memory_previous_listIndex[1]; oldListIndex = gui_state->gui_on_tab[1].gui_list_index_previous;
if ((oldListIndex == 1)) { if ((oldListIndex == 1)) {
// next state is the "first state" // next state is the "first state"
tabs_in_memory[0] = {NULL, 0}; gui_state->gui_on_tab[0] = {NULL, "", 0};
tabs_in_memory[1] = {NULL, 1}; gui_state->gui_on_tab[1] = {NULL, "", 1};
tabs_in_memory[2] = {NULL, -1}; gui_state->gui_on_tab[2] = {NULL, "", -1};
tabToBeActivated = 0; gui_state->activeTabID = 0;
} else { } else {
tabs_in_memory[0] = {NULL, oldListIndex -2}; gui_state->gui_on_tab[0] = {NULL, "", oldListIndex -2};
tabs_in_memory[1] = {NULL, oldListIndex -1}; gui_state->gui_on_tab[1] = {NULL, "", oldListIndex -1};
tabs_in_memory[2] = {NULL, oldListIndex}; gui_state->gui_on_tab[2] = {NULL, "", oldListIndex};
tabToBeActivated = 1; gui_state->activeTabID = 1;
} }
} else { } else {
// swipe to next item in list // swipe to next item in list
Serial.printf(" Will swipe to next item in list\r\n"); Serial.printf(" Will swipe to next item in list\r\n");
if (tabs_in_memory_previous_listIndex[2] == -1) { if (gui_state->gui_on_tab[2].gui_list_index_previous == -1) {
// last state was the first state // last state was the first state
oldListIndex = tabs_in_memory_previous_listIndex[0]; // is always 0 oldListIndex = gui_state->gui_on_tab[0].gui_list_index_previous; // is always 0
} else { } else {
oldListIndex = tabs_in_memory_previous_listIndex[1]; oldListIndex = gui_state->gui_on_tab[1].gui_list_index_previous;
} }
if (oldListIndex == get_gui_list(get_currentScene())->size() -2) { if (oldListIndex == get_gui_list_active_withFallback()->size() -2) {
// next state is the "last state" // next state is the "last state"
tabs_in_memory[0] = {NULL, oldListIndex}; gui_state->gui_on_tab[0] = {NULL, "", oldListIndex};
tabs_in_memory[1] = {NULL, oldListIndex +1}; gui_state->gui_on_tab[1] = {NULL, "", oldListIndex +1};
tabs_in_memory[2] = {NULL, -1}; gui_state->gui_on_tab[2] = {NULL, "", -1};
tabToBeActivated = 1; gui_state->activeTabID = 1;
} else { } else {
tabs_in_memory[0] = {NULL, oldListIndex}; gui_state->gui_on_tab[0] = {NULL, "", oldListIndex};
tabs_in_memory[1] = {NULL, oldListIndex +1}; gui_state->gui_on_tab[1] = {NULL, "", oldListIndex +1};
tabs_in_memory[2] = {NULL, oldListIndex +2}; gui_state->gui_on_tab[2] = {NULL, "", oldListIndex +2};
tabToBeActivated = 1; gui_state->activeTabID = 1;
} }
} }
}
void doTabCreation_strategyMax3(lv_obj_t* tabview, t_gui_state *gui_state) {
// create the tabs // create the tabs
Serial.printf(" Will create tabs. List indices of the three tabs are %d, %d, %d, tab nr %d will be activated\r\n", tabs_in_memory[0].listIndex, tabs_in_memory[1].listIndex, tabs_in_memory[2].listIndex, tabToBeActivated); Serial.printf(" Will create tabs. List indices of the three tabs are %d, %d, %d, tab nr %d will be activated\r\n", gui_state->gui_on_tab[0].gui_list_index, gui_state->gui_on_tab[1].gui_list_index, gui_state->gui_on_tab[2].gui_list_index, gui_state->activeTabID);
for (int i=0; i<3; i++) { for (int i=0; i<3; i++) {
create_new_tab(tabview, i); create_new_tab(tabview, &gui_state->gui_on_tab[i]);
} }
if (get_gui_list(get_currentScene())->size() > 0) { if (get_gui_list_active_withFallback()->size() > 0) {
std::string nameOfNewActiveTab = get_gui_list(get_currentScene())->at(tabs_in_memory[tabToBeActivated].listIndex); std::string nameOfNewActiveTab = get_gui_list_active_withFallback()->at(gui_state->gui_on_tab[gui_state->activeTabID].gui_list_index);
Serial.printf(" New visible tab is \"%s\"\r\n", nameOfNewActiveTab.c_str()); Serial.printf(" New visible tab is \"%s\"\r\n", nameOfNewActiveTab.c_str());
// set the tab we swiped to as active // set active tab
setActiveTab(tabToBeActivated, LV_ANIM_OFF); setActiveTab(gui_state->activeTabID, LV_ANIM_OFF);
set_currentGUIname(nameOfNewActiveTab); gui_memoryOptimizer_setActiveGUIname(nameOfNewActiveTab);
currentTabID = tabToBeActivated;
} }
} }
LV_IMAGE_DECLARE(gradientLeft); LV_IMAGE_DECLARE(gradientLeft);
LV_IMAGE_DECLARE(gradientRight); LV_IMAGE_DECLARE(gradientRight);
void getBreadcrumpPosition(uint8_t* breadcrumpPosition, std::string nameOfTab) { void fillPanelWithPageIndicator_strategyMax3(lv_obj_t* panel, lv_obj_t* img1, lv_obj_t* img2, t_gui_state *gui_state) {
*breadcrumpPosition = 0;
gui_list currentGUIlist = get_gui_list(get_currentScene());
uint8_t counter = 0;
for (std::vector<std::string>::iterator it = currentGUIlist->begin() ; it != currentGUIlist->end(); ++it) {
counter++;
if (*it == nameOfTab) {
*breadcrumpPosition = counter;
return;
}
}
}
void fillPanelWithPageIndicator_strategyMax3(lv_obj_t* panel, lv_obj_t* img1, lv_obj_t* img2) {
Serial.printf(" Will fill panel with page indicators\r\n"); Serial.printf(" Will fill panel with page indicators\r\n");
if (get_gui_list(get_currentScene())->size() == 0) { if (get_gui_list_active_withFallback()->size() == 0) {
Serial.printf(" no tab available, so no page indicators\r\n"); Serial.printf(" no tab available, so no page indicators\r\n");
// at least add the style // at least add the style
lv_obj_add_style(panel, &panel_style, 0); lv_obj_add_style(panel, &panel_style, 0);
@ -303,33 +342,52 @@ void fillPanelWithPageIndicator_strategyMax3(lv_obj_t* panel, lv_obj_t* img1, lv
btn = lv_button_create(panel); btn = lv_button_create(panel);
lv_obj_remove_flag(btn, LV_OBJ_FLAG_CLICKABLE); lv_obj_remove_flag(btn, LV_OBJ_FLAG_CLICKABLE);
lv_obj_set_size(btn, 150, lv_pct(100)); lv_obj_set_size(btn, 150, lv_pct(100));
if (tabs_in_memory[0].listIndex == 0) { if (gui_state->gui_on_tab[0].gui_list_index == 0) {
lv_obj_set_style_bg_color(btn, lv_color_black(), LV_PART_MAIN); lv_obj_set_style_bg_color(btn, lv_color_black(), LV_PART_MAIN);
} else { } else {
lv_obj_set_style_bg_color(btn, color_primary, LV_PART_MAIN); lv_obj_set_style_bg_color(btn, color_primary, LV_PART_MAIN);
} }
uint8_t breadcrumpLength = get_gui_list(get_currentScene())->size(); uint8_t breadcrumpDotSize = 8; // should be an even number
uint8_t breadcrumpDotSize = 8; // should be an even number
uint8_t breadcrumpDotDistance = 2; // should be an even number uint8_t breadcrumpDotDistance = 2; // should be an even number
int8_t breadcrumpStartPositionX = (-1) * (breadcrumpLength -1) * (breadcrumpDotSize + breadcrumpDotDistance) / 2; uint8_t breadcrumpMainGuiListLength = get_gui_list_withFallback(MAIN_GUI_LIST)->size();
int8_t breadcrumpMainGuiListStartPositionX = (-1) * (breadcrumpMainGuiListLength -1) * (breadcrumpDotSize + breadcrumpDotDistance) / 2;
uint8_t breadcrumpSceneGuiListLength = get_gui_list_withFallback(SCENE_GUI_LIST)->size();
int8_t breadcrumpSceneGuiListStartPositionX = (-1) * (breadcrumpSceneGuiListLength -1) * (breadcrumpDotSize + breadcrumpDotDistance) / 2;
#if (USE_SCENE_SPECIFIC_GUI_LIST != 0)
bool show_scene_gui_list = get_scene_has_gui_list(gui_memoryOptimizer_getActiveSceneName());
#else
bool show_scene_gui_list = false;
#endif
int8_t breadcrumpMainGuiList_yPos;
int8_t breadcrumpSceneGuiList_yPos;
int8_t nameOfGUI_yPos;
if (!show_scene_gui_list) {
breadcrumpMainGuiList_yPos = -6;
nameOfGUI_yPos = 6;
} else {
breadcrumpMainGuiList_yPos = -8;
breadcrumpSceneGuiList_yPos = -1;
nameOfGUI_yPos = 8;
}
// create the panel content for the three guis (or less) which are currently in memory // create the panel content for the three guis (or less) which are currently in memory
std::string nameOfTab; std::string nameOfGUI;
uint8_t breadcrumpPosition; uint8_t breadcrumpPosition;
for (int i=0; i<3; i++) { for (int i=0; i<3; i++) {
if (tabs_in_memory[i].listIndex != -1) { if (gui_state->gui_on_tab[i].gui_list_index != -1) {
nameOfTab = tabs_in_memory[i].guiName; nameOfGUI = gui_state->gui_on_tab[i].GUIname;
getBreadcrumpPosition(&breadcrumpPosition, nameOfTab); breadcrumpPosition = gui_state->gui_on_tab[i].gui_list_index +1;
// Create actual buttons for every tab // Create actual buttons for every tab
lv_obj_t* btn = lv_button_create(panel); lv_obj_t* btn = lv_button_create(panel);
// only if this is the button for the currently active tab, make it clickable to get to scene selection gui if (i == gui_state->activeTabID) {
if (nameOfTab == get_currentGUIname()) { // only if this is the button for the currently active tab, make it clickable to get to scene selection gui
lv_obj_add_flag(btn, LV_OBJ_FLAG_CLICKABLE); lv_obj_add_flag(btn, LV_OBJ_FLAG_CLICKABLE);
lv_obj_set_user_data(btn,(void *)(intptr_t)2);
lv_obj_add_event_cb(btn, sceneLabel_or_pageIndicator_event_cb, LV_EVENT_CLICKED, NULL); lv_obj_add_event_cb(btn, sceneLabel_or_pageIndicator_event_cb, LV_EVENT_CLICKED, NULL);
} else if ((i==0 || i==1) && (tabs_in_memory[i+1].listIndex != -1)) { } else if ((i==0 || i==1) && (gui_state->gui_on_tab[i+1].gui_list_index != -1)) {
// this is the button on the previous tab, which can be seen on the active tab // this is the button on the previous tab, which can be seen on the active tab
// activate click to prev tab // activate click to prev tab
lv_obj_add_flag(btn, LV_OBJ_FLAG_CLICKABLE); lv_obj_add_flag(btn, LV_OBJ_FLAG_CLICKABLE);
@ -349,28 +407,63 @@ void fillPanelWithPageIndicator_strategyMax3(lv_obj_t* panel, lv_obj_t* img1, lv
lv_obj_set_style_shadow_width(btn, 0, LV_PART_MAIN); lv_obj_set_style_shadow_width(btn, 0, LV_PART_MAIN);
lv_obj_set_style_bg_color(btn, color_primary, LV_PART_MAIN); lv_obj_set_style_bg_color(btn, color_primary, LV_PART_MAIN);
// create a breadcrump dot for each gui in the list // create a breadcrump dot for each gui in the main_gui_list
for (int j=0; j<breadcrumpLength; j++) { for (int j=0; j<breadcrumpMainGuiListLength; j++) {
lv_obj_t* dot = lv_obj_create(btn); lv_obj_t* dot = lv_obj_create(btn);
lv_obj_set_size(dot, breadcrumpDotSize, breadcrumpDotSize); lv_obj_set_size(dot, breadcrumpDotSize, breadcrumpDotSize);
lv_obj_set_style_radius(dot, LV_RADIUS_CIRCLE, LV_PART_MAIN); lv_obj_set_style_radius(dot, LV_RADIUS_CIRCLE, LV_PART_MAIN);
// hightlight dot if it is the one for the currently active tab // hightlight dot if it is the one for the currently active tab
if (j == (breadcrumpPosition-1)) { #if (USE_SCENE_SPECIFIC_GUI_LIST != 0)
lv_obj_set_style_bg_color(dot, lv_color_lighten(color_primary, 200), LV_PART_MAIN); if ( ((gui_memoryOptimizer_getActiveGUIlist() == MAIN_GUI_LIST) || !get_scene_has_gui_list(gui_memoryOptimizer_getActiveSceneName()))
#else
if ( true
#endif
&& (j == (breadcrumpPosition-1))) {
lv_obj_set_style_bg_color(dot, lv_color_lighten(color_primary, 255), LV_PART_MAIN);
} else if ((gui_memoryOptimizer_getActiveGUIlist() == SCENE_GUI_LIST) && get_scene_has_gui_list(gui_memoryOptimizer_getActiveSceneName()) && (j == gui_memoryOptimizer_getLastActiveGUIlistIndex())) {
// hightlight dot a little bit if it is at least the one which was last active in the other gui list
lv_obj_set_style_bg_color(dot, lv_color_lighten(color_primary, 140), LV_PART_MAIN);
} else { } else {
lv_obj_set_style_bg_color(dot, lv_color_lighten(color_primary, 100), LV_PART_MAIN); lv_obj_set_style_bg_color(dot, lv_color_lighten(color_primary, 30), LV_PART_MAIN);
} }
lv_obj_align(dot, LV_ALIGN_TOP_MID, breadcrumpStartPositionX +j*(breadcrumpDotSize + breadcrumpDotDistance), -6); lv_obj_align(dot, LV_ALIGN_TOP_MID, breadcrumpMainGuiListStartPositionX +j*(breadcrumpDotSize + breadcrumpDotDistance), breadcrumpMainGuiList_yPos);
// this dot needs to get clickable again // this dot needs to get clickable again
lv_obj_set_user_data(dot,(void *)(intptr_t)1);
lv_obj_add_flag(dot, LV_OBJ_FLAG_CLICKABLE); lv_obj_add_flag(dot, LV_OBJ_FLAG_CLICKABLE);
lv_obj_add_flag(dot, LV_OBJ_FLAG_EVENT_BUBBLE); lv_obj_add_flag(dot, LV_OBJ_FLAG_EVENT_BUBBLE);
} }
// create a breadcrump dot for each gui in the scene gui list, if there is one
if (show_scene_gui_list) {
for (int j=0; j<breadcrumpSceneGuiListLength; j++) {
lv_obj_t* dot = lv_obj_create(btn);
lv_obj_set_size(dot, breadcrumpDotSize, breadcrumpDotSize);
lv_obj_set_style_radius(dot, LV_RADIUS_CIRCLE, LV_PART_MAIN);
if ((gui_memoryOptimizer_getActiveGUIlist() == SCENE_GUI_LIST) && (j == (breadcrumpPosition-1))) {
// hightlight dot if it is the one for the currently active tab
lv_obj_set_style_bg_color(dot, lv_color_lighten(color_primary, 255), LV_PART_MAIN);
} else if ((gui_memoryOptimizer_getActiveGUIlist() == MAIN_GUI_LIST) && (j == gui_memoryOptimizer_getLastActiveGUIlistIndex())) {
// hightlight dot a little bit if it is at least the one which was last active in the other gui list
lv_obj_set_style_bg_color(dot, lv_color_lighten(color_primary, 140), LV_PART_MAIN);
} else {
lv_obj_set_style_bg_color(dot, lv_color_lighten(color_primary, 30), LV_PART_MAIN);
}
lv_obj_align(dot, LV_ALIGN_TOP_MID, breadcrumpSceneGuiListStartPositionX +j*(breadcrumpDotSize + breadcrumpDotDistance), breadcrumpSceneGuiList_yPos);
// this dot needs to get clickable again
lv_obj_set_user_data(dot,(void *)(intptr_t)1);
lv_obj_add_flag(dot, LV_OBJ_FLAG_CLICKABLE);
lv_obj_add_flag(dot, LV_OBJ_FLAG_EVENT_BUBBLE);
}
}
// create a label for nameOfGUI
lv_obj_t* label = lv_label_create(btn); lv_obj_t* label = lv_label_create(btn);
lv_obj_set_style_text_font(label, &lv_font_montserrat_10, LV_PART_MAIN); lv_obj_set_style_text_font(label, &lv_font_montserrat_10, LV_PART_MAIN);
lv_label_set_text_fmt(label, "%s", nameOfTab.c_str()); lv_label_set_text_fmt(label, "%s", nameOfGUI.c_str());
lv_obj_align(label, LV_ALIGN_BOTTOM_MID, 0, 6); lv_obj_align(label, LV_ALIGN_BOTTOM_MID, 0, nameOfGUI_yPos);
} }
} }
@ -379,8 +472,8 @@ void fillPanelWithPageIndicator_strategyMax3(lv_obj_t* panel, lv_obj_t* img1, lv
btn = lv_button_create(panel); btn = lv_button_create(panel);
lv_obj_remove_flag(btn, LV_OBJ_FLAG_CLICKABLE); lv_obj_remove_flag(btn, LV_OBJ_FLAG_CLICKABLE);
lv_obj_set_size(btn, 150, lv_pct(100)); lv_obj_set_size(btn, 150, lv_pct(100));
// 4 at last position 4 at middle position only one tab available overall // 4 at last position 4 at middle position only one tab available overall
if ((tabs_in_memory[2].listIndex == get_gui_list(get_currentScene())->size()-1) || (tabs_in_memory[1].listIndex == get_gui_list(get_currentScene())->size()-1) || (tabs_in_memory[1].listIndex == -1)) { if ((gui_state->gui_on_tab[2].gui_list_index == get_gui_list_active_withFallback()->size()-1) || (gui_state->gui_on_tab[1].gui_list_index == get_gui_list_active_withFallback()->size()-1) || (gui_state->gui_on_tab[1].gui_list_index == -1)) {
lv_obj_set_style_bg_color(btn, lv_color_black(), LV_PART_MAIN); lv_obj_set_style_bg_color(btn, lv_color_black(), LV_PART_MAIN);
} else { } else {
lv_obj_set_style_bg_color(btn, color_primary, LV_PART_MAIN); lv_obj_set_style_bg_color(btn, color_primary, LV_PART_MAIN);
@ -423,71 +516,81 @@ void fillPanelWithPageIndicator_strategyMax3(lv_obj_t* panel, lv_obj_t* img1, lv
} }
void gui_memoryOptimizer_prepare_startup() { void gui_memoryOptimizer_notifyAndClear(lv_obj_t** tabview, lv_obj_t** panel, lv_obj_t** img1, lv_obj_t** img2, t_gui_state *gui_state) {
// find index of get_currentGUIname() in gui_list
for (int i=0; i<get_gui_list(get_currentScene())->size(); i++) {
if (get_gui_list(get_currentScene())->at(i) == get_currentGUIname()) {
Serial.printf("Startup: found GUI with name \"%s\" in \"gui_list\" at position %d\r\n", get_currentGUIname().c_str(), i);
// save position so that "guis_doAfterSliding" can use it
tabs_in_memory[0].listIndex = i;
}
}
// if the gui was not found in main_gui_list, try to find it in scene specific list // 1. notify old guis that they will be deleted so that they can persist their state if needed
if (tabs_in_memory[0].listIndex == -1) { notify_active_tabs_before_delete(gui_state);
useSceneGUIlist = true; // 2. clear current tabview and save gui_list_index_previous (needed for swipe)
for (int i=0; i<get_gui_list(get_currentScene())->size(); i++) { clear_tabview(*tabview, gui_state);
if (get_gui_list(get_currentScene())->at(i) == get_currentGUIname()) { // 3. clear current panel for page indicator
Serial.printf("Startup: found GUI with name \"%s\" in scene specific \"gui_list\" at position %d\r\n", get_currentGUIname().c_str(), i); clear_panel(*panel, *img1, *img2);
// save position so that "guis_doAfterSliding" can use it
tabs_in_memory[0].listIndex = i;
}
}
}
// if the gui was still not found, reset useSceneGUIlist
if (tabs_in_memory[0].listIndex == -1) {
useSceneGUIlist = false;
}
} }
void gui_memoryOptimizer_doAfterSliding_deletionAndCreation(lv_obj_t** tabview, int oldTabID, int newTabID, bool newGuiList, lv_obj_t** panel, lv_obj_t** img1, lv_obj_t** img2) { void gui_memoryOptimizer_doContentCreation(lv_obj_t** tabview, lv_obj_t** panel, lv_obj_t** img1, lv_obj_t** img2, t_gui_state *gui_state);
// 1. tab creation on startup (called by init_gui())
// find the position of the current GUI in the gui list which was active last (both were automatically saved in the preferences)
void gui_memoryOptimizer_onStartup(lv_obj_t** tabview, lv_obj_t** panel, lv_obj_t** img1, lv_obj_t** img2) {
Serial.printf("Startup: try to resume at scene \"%s\" with GUI \"%s\"\r\n", gui_memoryOptimizer_getActiveSceneName().c_str(), gui_memoryOptimizer_getActiveGUIname().c_str());
// Get last state from preferences and save it in gui_state
// So it is ok to call them without using the return values.
gui_memoryOptimizer_getActiveSceneName();
gui_memoryOptimizer_getActiveGUIname();
gui_memoryOptimizer_getActiveGUIlist();
gui_memoryOptimizer_getLastActiveGUIlistIndex();
// 1. find last used gui
int gui_list_index = -1;
// find index of gui_memoryOptimizer_getActiveGUIname() in gui_list_active
for (int i=0; i<get_gui_list_active_withFallback()->size(); i++) {
if (get_gui_list_active_withFallback()->at(i) == gui_memoryOptimizer_getActiveGUIname()) {
Serial.printf("Startup: found GUI with name \"%s\" in \"gui_list_active\" at position %d\r\n", gui_memoryOptimizer_getActiveGUIname().c_str(), i);
gui_list_index = i;
break;
}
}
// 2. set gui_list_indices and the tab to be activated
if ((gui_list_index >= 0) && (gui_list_index < get_gui_list_active_withFallback()->size())) {
// gui was found
setGUIlistIndicesToBeShown_forSpecificGUIlistIndex(gui_list_index, &gui_state);
} else {
// gui was not found
Serial.printf("Startup: GUI with name \"%s\" was not found. Will start with first GUI of main_gui_list\r\n", gui_memoryOptimizer_getActiveGUIname().c_str());
gui_memoryOptimizer_setActiveGUIlist(MAIN_GUI_LIST);
setGUIlistIndicesToBeShown_forFirstGUIinGUIlist(&gui_state);
}
// 3. create content
gui_memoryOptimizer_doContentCreation(tabview, panel, img1, img2, &gui_state);
}
// 2. tab creation after sliding (called by tabview_tab_changed_event_cb())
void gui_memoryOptimizer_afterSliding(lv_obj_t** tabview, lv_obj_t** panel, lv_obj_t** img1, lv_obj_t** img2, int newTabID) {
// Here the magic for dynamic creation and deletion of lvgl objects happens to keep memory usage low. // Here the magic for dynamic creation and deletion of lvgl objects happens to keep memory usage low.
// The next and previous tab must always be available in the tabview, because they can already been seen during the animation. // The next and previous tab must always be available in the tabview, because they can already been seen during the animation.
// And you always need 3 tabs, otherwise you even could not slide to the next or previous tab. // And you always need 3 tabs, otherwise you even could not slide to the next or previous tab.
// So we always have 3 tabs. // So we always have 3 tabs.
// After the animation, the tabview and hence all tabs are deleted and recreated. // After the animation, the tabview and hence all tabs are deleted and recreated.
// With parameter newGuiList it is signaled that we are changing from a scene specific list to the main list or vice versa
// In that case, we have to do special treatment because we are not simply sliding to the left or to the right, but we start newly with a different gui list.
// only called by guis_doTabCreationAtStartup():
// oldTabID = -1, newTabID = -1, newGuiList = false
// called by handleScene()
// oldTabID = -1, newTabID = -1, newGuiList = true
Serial.printf("--- Start of tab deletion and creation\r\n"); Serial.printf("--- Start of tab deletion and creation\r\n");
bool isInitialization = ((oldTabID == -1) && (newTabID == -1)); gui_state.oldTabID = gui_state.activeTabID;
if (isInitialization) { gui_state.activeTabID = newTabID;
Serial.printf("Startup: will initially create the tabs to be shown\r\n");
} else {
Serial.printf("Changing from oldTabID %d \"%s\" to newTabID %d \"%s\"\r\n",
oldTabID, get_gui_list(get_currentScene())->at(tabs_in_memory[oldTabID].listIndex).c_str(),
newTabID, get_gui_list(get_currentScene())->at(tabs_in_memory[newTabID].listIndex).c_str());
}
// Save the ids of the tabs we had in memory before. This is only used by doTabCreation_strategyMax3() to know where we come from and where we have to go to. Serial.printf("Changing from oldTabID %d \"%s\" to newTabID %d \"%s\"\r\n",
for (int i=0; i<3; i++) { gui_state.oldTabID, gui_state.gui_on_tab[gui_state.oldTabID].GUIname.c_str(),
tabs_in_memory_previous_listIndex[i] = tabs_in_memory[i].listIndex; gui_state.activeTabID, gui_state.gui_on_tab[gui_state.activeTabID].GUIname.c_str());
}
// the old tabs need to be notified that they will be deleted so that they can persist their state if needed // 1. notify old guis and clear tabview and panel
notify_active_tabs_before_delete(); gui_memoryOptimizer_notifyAndClear(tabview, panel, img1, img2, &gui_state);
// clear current tabview
clear_tabview(*tabview);
// clear current panel for page indicator
clear_panel(*panel, *img1, *img2);
// only optional: delete and create the whole screen. Not necessary. // only optional: delete and create the whole screen. Not necessary.
// Only used for a test. init_gui_status_bar() would need to be called again at a suitable place, because the status bar would also be deleted. // Only used for a test. init_gui_status_bar() would need to be called again at a suitable place, because the status bar would also be deleted.
@ -498,25 +601,103 @@ void gui_memoryOptimizer_doAfterSliding_deletionAndCreation(lv_obj_t** tabview,
// lv_screen_load(newscr); // lv_screen_load(newscr);
// lv_obj_delete(oldscr); // lv_obj_delete(oldscr);
if (newGuiList) { // 2. set gui_list_indices and the tab to be activated
// If we are switching to a new gui list, then we need to set tabs_in_memory_previous_listIndex[0] = -1; setGUIlistIndicesToBeShown_afterSlide(&gui_state);
// Doing so, doTabCreation_strategyMax3() knows that we cannot resume an old state.
tabs_in_memory_previous_listIndex[0] = -1; // 3. create content
gui_memoryOptimizer_doContentCreation(tabview, panel, img1, img2, &gui_state);
}
// 3. after gui list has changed (called by handleScene()), when switching between main_gui_list and scene specific list. Will show first GUi in list
void gui_memoryOptimizer_afterGUIlistChanged(lv_obj_t** tabview, lv_obj_t** panel, lv_obj_t** img1, lv_obj_t** img2, GUIlists newGUIlist) {
Serial.printf("--- Will change to new gui_list\r\n");
if (gui_state.last_active_gui_list != newGUIlist) {
// we are changing the gui_list, so save the last_active_gui_list_index
gui_memoryOptimizer_setLastActiveGUIlistIndex(gui_state.gui_on_tab[gui_state.activeTabID].gui_list_index);
}
// 1. notify old guis and clear tabview and panel
gui_memoryOptimizer_notifyAndClear(tabview, panel, img1, img2, &gui_state);
// 2. set gui_list_indices and the tab to be activated
gui_memoryOptimizer_setActiveGUIlist(newGUIlist);
setGUIlistIndicesToBeShown_forFirstGUIinGUIlist(&gui_state);
// 3. create content
gui_memoryOptimizer_doContentCreation(tabview, panel, img1, img2, &gui_state);
}
// 4. navigate to a specific GUI in gui_list
void gui_memoryOptimizer_navigateToGUI(lv_obj_t** tabview, lv_obj_t** panel, lv_obj_t** img1, lv_obj_t** img2, GUIlists GUIlist, int gui_list_index) {
Serial.printf("--- Will navigate to specific GUI\r\n");
if ( !((gui_list_index >= 0) && (gui_list_index < get_gui_list_withFallback(GUIlist)->size()))) {
Serial.printf(" cannot navigate to GUI because gui_list_index \"%d\" is out of range\r\n", gui_list_index);
return;
}
if (gui_state.last_active_gui_list != GUIlist) {
// we are changing the gui_list, so save the last_active_gui_list_index
gui_memoryOptimizer_setLastActiveGUIlistIndex(gui_state.gui_on_tab[gui_state.activeTabID].gui_list_index);
} }
// 1. notify old guis and clear tabview and panel
gui_memoryOptimizer_notifyAndClear(tabview, panel, img1, img2, &gui_state);
// 2. set gui_list_indices and the tab to be activated
gui_memoryOptimizer_setActiveGUIlist(GUIlist);
setGUIlistIndicesToBeShown_forSpecificGUIlistIndex(gui_list_index, &gui_state);
// 3. create content
gui_memoryOptimizer_doContentCreation(tabview, panel, img1, img2, &gui_state);
}
// 5. navigate back to last gui in scene
void gui_memoryOptimizer_navigateToLastActiveGUIofPreviousGUIlist(lv_obj_t** tabview, lv_obj_t** panel, lv_obj_t** img1, lv_obj_t** img2) {
#if (USE_SCENE_SPECIFIC_GUI_LIST == 0)
Serial.printf("--- Cannot navigate to last GUI from scene, because scene specific gui lists are not enabled\r\n");
return;
#endif
if (gui_memoryOptimizer_getLastActiveGUIlistIndex() == -1) {
Serial.printf("--- Cannot navigate to last GUI from scene, because it is not set\r\n");
return;
} else {
Serial.printf("--- Will navigate to last GUI from scene\r\n");
}
// navigate to the other gui_list
if (gui_memoryOptimizer_getActiveGUIlist() == MAIN_GUI_LIST) {
gui_memoryOptimizer_navigateToGUI(tabview, panel, img1, img2, SCENE_GUI_LIST, gui_memoryOptimizer_getLastActiveGUIlistIndex());
} else {
gui_memoryOptimizer_navigateToGUI(tabview, panel, img1, img2, MAIN_GUI_LIST, gui_memoryOptimizer_getLastActiveGUIlistIndex());
}
}
void gui_memoryOptimizer_doContentCreation(lv_obj_t** tabview, lv_obj_t** panel, lv_obj_t** img1, lv_obj_t** img2, t_gui_state *gui_state) {
// recreate the tabview // recreate the tabview
lv_obj_t* newTabview = create_tabview(); lv_obj_t* newTabview = create_tabview();
*tabview = newTabview; *tabview = newTabview;
// Create the tabs. Use strategy "3 tabs at maximum" to keep memory usage low. // Create the tabs. Use strategy "3 tabs at maximum" to keep memory usage low.
// Set the tab we swiped to as active // Set the tab we swiped to as active
doTabCreation_strategyMax3(*tabview, oldTabID, newTabID); doTabCreation_strategyMax3(*tabview, gui_state);
// Create the panel for the page indicator. Panel itself takes about 2136 bytes for three tabs. // Create the panel for the page indicator. Panel itself takes about 2136 bytes for three tabs.
lv_obj_t* newPanel = create_panel(); lv_obj_t* newPanel = create_panel();
*panel = newPanel; *panel = newPanel;
*img1 = lv_image_create(lv_screen_active()); *img1 = lv_image_create(lv_screen_active());
*img2 = lv_image_create(lv_screen_active()); *img2 = lv_image_create(lv_screen_active());
fillPanelWithPageIndicator_strategyMax3(*panel, *img1, *img2); fillPanelWithPageIndicator_strategyMax3(*panel, *img1, *img2, gui_state);
// now, as the correct tab is active, register again the events for the tabview // now, as the correct tab is active, register again the events for the tabview
lv_obj_add_event_cb(*tabview, tabview_tab_changed_event_cb, LV_EVENT_VALUE_CHANGED, NULL); lv_obj_add_event_cb(*tabview, tabview_tab_changed_event_cb, LV_EVENT_VALUE_CHANGED, NULL);
@ -524,6 +705,11 @@ void gui_memoryOptimizer_doAfterSliding_deletionAndCreation(lv_obj_t** tabview,
// Initialize scroll position of the page indicator // Initialize scroll position of the page indicator
lv_obj_send_event(lv_tabview_get_content(*tabview), LV_EVENT_SCROLL, NULL); lv_obj_send_event(lv_tabview_get_content(*tabview), LV_EVENT_SCROLL, NULL);
// gui_memoryOptimizer_doContentCreation() is called as last step every time the 3 tabs are recreated.
// Save here the last_active_gui_list. If the used list changes in a future navigation, save the last_active_gui_list_index
// so that we can use SCENE_BACK_TO_PREVIOUS_GUI_LIST
gui_state->last_active_gui_list = gui_memoryOptimizer_getActiveGUIlist();
Serial.printf("------------ End of tab deletion and creation\r\n"); Serial.printf("------------ End of tab deletion and creation\r\n");
} }

View File

@ -1,6 +1,28 @@
#pragma once #pragma once
#include <string>
#include <lvgl.h>
void gui_memoryOptimizer_prepare_startup(); enum GUIlists {
void gui_memoryOptimizer_doAfterSliding_deletionAndCreation(lv_obj_t** tabview, int oldTabID, int newTabID, bool newGuiList, lv_obj_t** panel, lv_obj_t** img1, lv_obj_t** img2); // MAIN_GUI_LIST: we are in the main_gui_list (with the scene selector as first gui), either if a scene is active or not
// SCENE_GUI_LIST: a scene is active and we are not in the main_gui_list. In that case, we try to use the scene specific gui list, if the scene defined one.
MAIN_GUI_LIST,
SCENE_GUI_LIST
};
void gui_memoryOptimizer_onStartup(lv_obj_t** tabview, lv_obj_t** panel, lv_obj_t** img1, lv_obj_t** img2);
void gui_memoryOptimizer_afterSliding(lv_obj_t** tabview, lv_obj_t** panel, lv_obj_t** img1, lv_obj_t** img2, int newTabID);
void gui_memoryOptimizer_afterGUIlistChanged(lv_obj_t** tabview, lv_obj_t** panel, lv_obj_t** img1, lv_obj_t** img2, GUIlists newGUIlist);
void gui_memoryOptimizer_navigateToGUI(lv_obj_t** tabview, lv_obj_t** panel, lv_obj_t** img1, lv_obj_t** img2, GUIlists GUIlist, int gui_list_index);
void gui_memoryOptimizer_navigateToLastActiveGUIofPreviousGUIlist(lv_obj_t** tabview, lv_obj_t** panel, lv_obj_t** img1, lv_obj_t** img2);
int gui_memoryOptimizer_getActiveTabID();
bool gui_memoryOptimizer_isTabIDInMemory(int tabID); bool gui_memoryOptimizer_isTabIDInMemory(int tabID);
bool gui_memoryOptimizer_isGUInameInMemory(std::string guiName); bool gui_memoryOptimizer_isGUInameInMemory(std::string GUIname);
std::string gui_memoryOptimizer_getActiveSceneName();
void gui_memoryOptimizer_setActiveSceneName(std::string aSceneName);
std::string gui_memoryOptimizer_getActiveGUIname();
void gui_memoryOptimizer_setActiveGUIname(std::string aGUIname);
GUIlists gui_memoryOptimizer_getActiveGUIlist();
void gui_memoryOptimizer_setActiveGUIlist(GUIlists aGUIlist);

View File

@ -6,6 +6,7 @@
#include "guiRegistry.h" #include "guiRegistry.h"
#include "applicationInternal/gui/guiBase.h" #include "applicationInternal/gui/guiBase.h"
#include "applicationInternal/hardware/hardwarePresenter.h" #include "applicationInternal/hardware/hardwarePresenter.h"
#include "applicationInternal/scenes/sceneRegistry.h"
#include "scenes/scene__default.h" #include "scenes/scene__default.h"
// ------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------
@ -15,14 +16,30 @@ std::map<std::string, gui_definition> registered_guis_byName_map;
// ------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------
void register_gui(std::string a_name, create_tab_content a_create_tab_content, notify_tab_before_delete a_notify_tab_before_delete) { void register_gui(
std::string a_name,
create_tab_content a_create_tab_content,
notify_tab_before_delete a_notify_tab_before_delete,
gui_setKeys a_gui_setKeys,
key_repeatModes a_key_repeatModes,
key_commands_short a_key_commands_short,
key_commands_long a_key_commands_long
) {
if (registered_guis_byName_map.count(a_name) > 0) { if (registered_guis_byName_map.count(a_name) > 0) {
Serial.printf("ERROR!!!: you cannot register two guis having the same name '%s'\r\n", a_name.c_str()); Serial.printf("ERROR!!!: you cannot register two guis having the same name '%s'\r\n", a_name.c_str());
return; return;
} }
gui_definition new_gui_definition = gui_definition{a_name, a_create_tab_content, a_notify_tab_before_delete}; gui_definition new_gui_definition = gui_definition{
a_name,
a_create_tab_content,
a_notify_tab_before_delete,
a_gui_setKeys,
a_key_repeatModes,
a_key_commands_short,
a_key_commands_long
};
// put the gui_definition in a map that can be accessed by name // put the gui_definition in a map that can be accessed by name
registered_guis_byName_map[a_name] = new_gui_definition; registered_guis_byName_map[a_name] = new_gui_definition;
@ -31,4 +48,25 @@ void register_gui(std::string a_name, create_tab_content a_create_tab_content, n
// Can be overwritten by scenes to have their own gui_list. // Can be overwritten by scenes to have their own gui_list.
main_gui_list.insert(main_gui_list.end(), {std::string(a_name)}); main_gui_list.insert(main_gui_list.end(), {std::string(a_name)});
setKeysForAllRegisteredGUIsAndScenes();
}
void setKeysForAllRegisteredGUIsAndScenes() {
// Whenever a new gui or scene is registered, a new gui or scene command could have been defined in the gui or scene.
// But this new command could have already been used before in the key definition of another gui or scene. The command at this time was 0, which is undefined.
// So we have to set the keys again for all guis and scenes that have been registered before.
// 1. set again the defaultKeys
register_scene_defaultKeys();
// 2. loop over all registered scenes and call setKeys()
for (std::map<std::string, scene_definition>::iterator it = registered_scenes.begin(); it != registered_scenes.end(); ++it) {
it->second.this_scene_setKeys();
}
// 3. loop over all registered guis and call setKeys()
for (std::map<std::string, gui_definition>::iterator it = registered_guis_byName_map.begin(); it != registered_guis_byName_map.end(); ++it) {
if (it->second.this_gui_setKeys != NULL) {
it->second.this_gui_setKeys();
}
}
} }

View File

@ -22,19 +22,33 @@
#include <vector> #include <vector>
#include <map> #include <map>
#include <lvgl.h> #include <lvgl.h>
#include "applicationInternal/keys.h"
typedef void (*create_tab_content)(lv_obj_t* tab); typedef void (*create_tab_content)(lv_obj_t* tab);
typedef void (*notify_tab_before_delete)(void); typedef void (*notify_tab_before_delete)(void);
typedef void (*gui_setKeys)(void);
// https://stackoverflow.com/questions/840501/how-do-function-pointers-in-c-work // https://stackoverflow.com/questions/840501/how-do-function-pointers-in-c-work
struct gui_definition { struct gui_definition {
std::string this_name; std::string this_name;
create_tab_content this_create_tab_content; create_tab_content this_create_tab_content;
notify_tab_before_delete this_notify_tab_before_delete; notify_tab_before_delete this_notify_tab_before_delete;
uint32_t this_tabID; gui_setKeys this_gui_setKeys;
lv_obj_t* this_tab; key_repeatModes this_key_repeatModes;
key_commands_short this_key_commands_short;
key_commands_long this_key_commands_long;
}; };
extern std::map<std::string, gui_definition> registered_guis_byName_map; extern std::map<std::string, gui_definition> registered_guis_byName_map;
void register_gui(std::string a_name, create_tab_content a_create_tab_content, notify_tab_before_delete a_notify_tab_before_delete); void register_gui(
std::string a_name,
create_tab_content a_create_tab_content,
notify_tab_before_delete a_notify_tab_before_delete,
gui_setKeys a_gui_setKeys = NULL,
key_repeatModes a_key_repeatModes = NULL,
key_commands_short a_key_commands_short = NULL,
key_commands_long a_key_commands_long = NULL
);
void setKeysForAllRegisteredGUIsAndScenes();

View File

@ -26,17 +26,29 @@ void init_preferences(void) {
void save_preferences(void) { void save_preferences(void) {
save_preferences_HAL(); save_preferences_HAL();
}; };
std::string get_currentScene() { std::string get_activeScene() {
return get_currentScene_HAL(); return get_activeScene_HAL();
} }
void set_currentScene(std::string aCurrentScene) { void set_activeScene(std::string anActiveScene) {
set_currentScene_HAL(aCurrentScene); set_activeScene_HAL(anActiveScene);
} }
std::string get_currentGUIname() { std::string get_activeGUIname() {
return get_currentGUIname_HAL(); return get_activeGUIname_HAL();
} }
void set_currentGUIname(std::string aCurrentGUIname) { void set_activeGUIname(std::string anActiveGUIname) {
set_currentGUIname_HAL(aCurrentGUIname); set_activeGUIname_HAL(anActiveGUIname);
}
int get_activeGUIlist() {
return get_activeGUIlist_HAL();
}
void set_activeGUIlist(int anActiveGUIlist) {
set_activeGUIlist_HAL(anActiveGUIlist);
}
int get_lastActiveGUIlistIndex() {
return get_lastActiveGUIlistIndex_HAL();
}
void set_lastActiveGUIlistIndex(int aGUIlistIndex) {
set_lastActiveGUIlistIndex_HAL(aGUIlistIndex);
} }
// --- user led --------------------------------------------------------------- // --- user led ---------------------------------------------------------------

View File

@ -10,10 +10,14 @@ void init_hardware_general(void);
// --- preferences ------------------------------------------------------------ // --- preferences ------------------------------------------------------------
void init_preferences(void); void init_preferences(void);
void save_preferences(void); void save_preferences(void);
std::string get_currentScene(); std::string get_activeScene();
void set_currentScene(std::string aCurrentScene); void set_activeScene(std::string anActiveScene);
std::string get_currentGUIname(); std::string get_activeGUIname();
void set_currentGUIname(std::string aCurrentGUIname); void set_activeGUIname(std::string anActiveGUIname);
int get_activeGUIlist();
void set_activeGUIlist(int anActiveGUIlist);
int get_lastActiveGUIlistIndex();
void set_lastActiveGUIlistIndex(int aGUIlistIndex);
// --- user led --------------------------------------------------------------- // --- user led ---------------------------------------------------------------
void init_userled(void); void init_userled(void);

View File

@ -1,7 +1,8 @@
#include <string> #include <string>
#include "applicationInternal/gui/guiMemoryOptimizer.h"
#include "applicationInternal/hardware/hardwarePresenter.h"
#include "applicationInternal/scenes/sceneRegistry.h" #include "applicationInternal/scenes/sceneRegistry.h"
#include "applicationInternal/commandHandler.h" #include "applicationInternal/commandHandler.h"
#include "applicationInternal/hardware/hardwarePresenter.h"
const uint8_t ROWS = 5; //five rows const uint8_t ROWS = 5; //five rows
const uint8_t COLS = 5; //five columns const uint8_t COLS = 5; //five columns
@ -33,7 +34,7 @@ void doShortPress(char keyChar, int keyCode){
if ((currentMillis - lastTimeSent[keyCode/ROWS][keyCode%ROWS]) > repeatRate) { if ((currentMillis - lastTimeSent[keyCode/ROWS][keyCode%ROWS]) > repeatRate) {
lastTimeSent[keyCode/ROWS][keyCode%ROWS] = currentMillis; lastTimeSent[keyCode/ROWS][keyCode%ROWS] = currentMillis;
uint16_t command = get_command_short(get_currentScene(), keyChar); uint16_t command = get_command_short(gui_memoryOptimizer_getActiveSceneName(), keyChar);
if (command != COMMAND_UNKNOWN) { if (command != COMMAND_UNKNOWN) {
Serial.printf("key: key '%c', will use command '%u'\r\n", keyChar, command); Serial.printf("key: key '%c', will use command '%u'\r\n", keyChar, command);
executeCommand(command); executeCommand(command);
@ -44,7 +45,7 @@ void doShortPress(char keyChar, int keyCode){
} }
void doLongPress(char keyChar, int keyCode){ void doLongPress(char keyChar, int keyCode){
uint16_t command = get_command_long(get_currentScene(), keyChar); uint16_t command = get_command_long(gui_memoryOptimizer_getActiveSceneName(), keyChar);
if (command != COMMAND_UNKNOWN) { if (command != COMMAND_UNKNOWN) {
Serial.printf("key: key '%c' (long press), will use command '%u'\r\n", keyChar, command); Serial.printf("key: key '%c' (long press), will use command '%u'\r\n", keyChar, command);
executeCommand(command); executeCommand(command);
@ -70,11 +71,11 @@ void keypad_loop(void) {
if (keypad_keys[i].kstate == PRESSED) { if (keypad_keys[i].kstate == PRESSED) {
// Serial.println("pressed"); // Serial.println("pressed");
if ((get_key_repeatMode(get_currentScene(), keyChar) == SHORT) && (lastKeyState[keyCode/ROWS][keyCode%ROWS] != PRESSED)) { if ((get_key_repeatMode(gui_memoryOptimizer_getActiveSceneName(), keyChar) == SHORT) && (lastKeyState[keyCode/ROWS][keyCode%ROWS] != PRESSED)) {
// Serial.printf("key: PRESSED of SHORT key %c (%d)\r\n", keyChar, keyCode); // Serial.printf("key: PRESSED of SHORT key %c (%d)\r\n", keyChar, keyCode);
doShortPress(keyChar, keyCode); doShortPress(keyChar, keyCode);
} else if ((get_key_repeatMode(get_currentScene(), keyChar) == SHORT_REPEATED) && (lastKeyState[keyCode/ROWS][keyCode%ROWS] != PRESSED)) { // here do not repeat it too early, do the repeat only in HOLD } else if ((get_key_repeatMode(gui_memoryOptimizer_getActiveSceneName(), keyChar) == SHORT_REPEATED) && (lastKeyState[keyCode/ROWS][keyCode%ROWS] != PRESSED)) { // here do not repeat it too early, do the repeat only in HOLD
// Serial.printf("key: PRESSED of SHORT_REPEATED key %c (%d)\r\n", keyChar, keyCode); // Serial.printf("key: PRESSED of SHORT_REPEATED key %c (%d)\r\n", keyChar, keyCode);
doShortPress(keyChar, keyCode); doShortPress(keyChar, keyCode);
@ -84,13 +85,13 @@ void keypad_loop(void) {
} else if (keypad_keys[i].kstate == HOLD) { } else if (keypad_keys[i].kstate == HOLD) {
// Serial.println("hold"); // Serial.println("hold");
if ((get_key_repeatMode(get_currentScene(), keyChar) == SHORTorLONG) && (lastKeyState[keyCode/ROWS][keyCode%ROWS] != HOLD)) { if ((get_key_repeatMode(gui_memoryOptimizer_getActiveSceneName(), keyChar) == SHORTorLONG) && (lastKeyState[keyCode/ROWS][keyCode%ROWS] != HOLD)) {
// Serial.printf("key: HOLD of SHORTorLONG key %c (%d)\r\n", keyChar, keyCode); // Serial.printf("key: HOLD of SHORTorLONG key %c (%d)\r\n", keyChar, keyCode);
// Serial.printf("will set keyIsHold to TRUE for keycode %d\r\n", keyCode); // Serial.printf("will set keyIsHold to TRUE for keycode %d\r\n", keyCode);
keyIsHold[keyCode/ROWS][keyCode%ROWS] = true; keyIsHold[keyCode/ROWS][keyCode%ROWS] = true;
doLongPress(keyChar, keyCode); doLongPress(keyChar, keyCode);
} else if (get_key_repeatMode(get_currentScene(), keyChar) == SHORT_REPEATED) { // this is the only case where we do not check the lastKeyState, because here it is intended to repeat the action } else if (get_key_repeatMode(gui_memoryOptimizer_getActiveSceneName(), keyChar) == SHORT_REPEATED) { // this is the only case where we do not check the lastKeyState, because here it is intended to repeat the action
// Serial.printf("key: HOLD of SHORT_REPEATED key %c (%d)\r\n", keyChar, keyCode); // Serial.printf("key: HOLD of SHORT_REPEATED key %c (%d)\r\n", keyChar, keyCode);
doShortPress(keyChar, keyCode); doShortPress(keyChar, keyCode);
@ -99,7 +100,7 @@ void keypad_loop(void) {
} else if (keypad_keys[i].kstate == RELEASED) { } else if (keypad_keys[i].kstate == RELEASED) {
// Serial.println("released"); // Serial.println("released");
if ((get_key_repeatMode(get_currentScene(), keyChar) == SHORTorLONG) && !keyIsHold[keyCode/ROWS][keyCode%ROWS] && (lastKeyState[keyCode/ROWS][keyCode%ROWS] != RELEASED)) { if ((get_key_repeatMode(gui_memoryOptimizer_getActiveSceneName(), keyChar) == SHORTorLONG) && !keyIsHold[keyCode/ROWS][keyCode%ROWS] && (lastKeyState[keyCode/ROWS][keyCode%ROWS] != RELEASED)) {
// Serial.printf("value of keyIsHold for keycode %d is %d\r\n", keyCode, keyIsHold[keyCode/ROWS][keyCode%ROWS]); // Serial.printf("value of keyIsHold for keycode %d is %d\r\n", keyCode, keyIsHold[keyCode/ROWS][keyCode%ROWS]);
// Serial.printf("key: RELEASED of SHORTorLONG key %c (%d)\r\n", keyChar, keyCode); // Serial.printf("key: RELEASED of SHORTorLONG key %c (%d)\r\n", keyChar, keyCode);
doShortPress(keyChar, keyCode); doShortPress(keyChar, keyCode);

View File

@ -1,5 +1,8 @@
#pragma once #pragma once
#include <map>
#include <stdint.h>
enum repeatModes { enum repeatModes {
// only as fallback // only as fallback
REPEAT_MODE_UNKNOWN, REPEAT_MODE_UNKNOWN,
@ -15,4 +18,8 @@ enum repeatModes {
SHORTorLONG, SHORTorLONG,
}; };
typedef std::map<char, repeatModes> *key_repeatModes;
typedef std::map<char, uint16_t> *key_commands_short;
typedef std::map<char, uint16_t> *key_commands_long;
void keypad_loop(void); void keypad_loop(void);

View File

@ -5,17 +5,71 @@
#include "applicationInternal/scenes/sceneRegistry.h" #include "applicationInternal/scenes/sceneRegistry.h"
#include "applicationInternal/hardware/hardwarePresenter.h" #include "applicationInternal/hardware/hardwarePresenter.h"
#include "applicationInternal/commandHandler.h" #include "applicationInternal/commandHandler.h"
#include "guis/gui_sceneSelection.h"
#include "scenes/scene__default.h" #include "scenes/scene__default.h"
void setLabelActiveScene() {
if ((SceneLabel != NULL) && sceneExists(gui_memoryOptimizer_getActiveSceneName())) {
lv_label_set_text(SceneLabel, gui_memoryOptimizer_getActiveSceneName().c_str());
}
}
void showSpecificGUI(GUIlists GUIlist, std::string GUIname);
void handleScene(uint16_t command, commandData commandData, std::string additionalPayload = "") { void handleScene(uint16_t command, commandData commandData, std::string additionalPayload = "") {
auto current = commandData.commandPayloads.begin();
std::string scene_name = *current;
// --- do not switch scene, but show scene selection gui. From that on, we are in the main_gui_list. ----------------
if (scene_name == scene_name_selection) {
Serial.println("scene: will show scene selection gui");
showSpecificGUI(MAIN_GUI_LIST, tabName_sceneSelection);
return;
}
// --- do not switch scene, but navigate to the prev or next gui in the currently active list of guis ---------------
if ((scene_name == scene_gui_next) || (scene_name == scene_gui_prev)) {
if (scene_name == scene_gui_prev) {
if (gui_memoryOptimizer_getActiveTabID() == 0) {
Serial.println("scene: cannot navigate to prev gui, because there is none");
} else {
Serial.println("scene: will navigate to prev gui");
setActiveTab(gui_memoryOptimizer_getActiveTabID() -1, LV_ANIM_ON, true);
}
} else if (scene_name == scene_gui_next) {
if (!gui_memoryOptimizer_isTabIDInMemory(gui_memoryOptimizer_getActiveTabID() +1)) {
Serial.println("scene: cannot navigate to next gui, because there is none");
} else {
Serial.println("scene: will navigate to next gui");
setActiveTab(gui_memoryOptimizer_getActiveTabID() +1, LV_ANIM_ON, true);
}
}
return;
}
// --- do not switch scene. Switch to the other gui list ------------------------------------------------------------
if (scene_name == scene_back_to_previous_gui_list) {
if (get_scene_has_gui_list(gui_memoryOptimizer_getActiveSceneName())) {
Serial.println("scene: will navigate back to last active gui from previous gui list");
guis_doTabCreationForNavigateToLastActiveGUIofPreviousGUIlist();
} else {
Serial.println("scene: cannot navigate back to last active gui from previous gui list, because no scene specific gui list was defined");
}
return;
}
// --- This is the normal case. We navigate to a new scene ----------------------------------------------------------
// FORCE can be either as second payload in commandData // FORCE can be either as second payload in commandData
// e.g. register_command(&SCENE_TV_FORCE , makeCommandData(SCENE, {scene_name_TV, "FORCE"})); // e.g. register_command(&SCENE_TV_FORCE , makeCommandData(SCENE, {scene_name_TV, "FORCE"}));
// or as additionalPayload, used by gui_sceneSelection.cpp // or as additionalPayload, used by gui_sceneSelection.cpp
// e.g. executeCommand(activate_scene_command, "FORCE"); // e.g. executeCommand(activate_scene_command, "FORCE");
auto current = commandData.commandPayloads.begin();
std::string scene_name = *current;
// we can have a second payload // we can have a second payload
std::string isForcePayload = ""; std::string isForcePayload = "";
++current; ++current;
@ -23,49 +77,20 @@ void handleScene(uint16_t command, commandData commandData, std::string addition
isForcePayload = *current; isForcePayload = *current;
} }
// do not really switch scene, but show sceneSelection gui. From that on, we are in the main_gui_list.
if (scene_name == scene_name_selection) {
useSceneGUIlist = false;
guis_doAfterSliding(-1, -1, true);
return;
}
// do not switch scene, but navigate to the prev or next gui in the currently active list of guis
if ((scene_name == scene_gui_next) || (scene_name == scene_gui_prev)) {
if (scene_name == scene_gui_prev) {
if (currentTabID == 0) {
Serial.println("scene: cannot navigate to prev gui, because there is none");
} else {
Serial.println("scene: will navigate to prev gui");
setActiveTab(currentTabID -1, LV_ANIM_ON, true);
}
} else if (scene_name == scene_gui_next) {
if (!gui_memoryOptimizer_isTabIDInMemory(currentTabID +1)) {
Serial.println("scene: cannot navigate to next gui, because there is none");
} else {
Serial.println("scene: will navigate to next gui");
setActiveTab(currentTabID +1, LV_ANIM_ON, true);
}
}
return;
}
// check if we know the new scene // check if we know the new scene
if (!sceneExists(scene_name)) { if (!sceneExists(scene_name)) {
Serial.printf("scene: cannot start scene %s, because it is unknown\r\n", scene_name.c_str()); Serial.printf("scene: cannot start scene %s, because it is unknown\r\n", scene_name.c_str());
return; return;
} else { } else {
Serial.printf("scene: will switch from old scene %s to new scene %s\r\n", get_currentScene().c_str(), scene_name.c_str()); Serial.printf("scene: will switch from old scene %s to new scene %s\r\n", gui_memoryOptimizer_getActiveSceneName().c_str(), scene_name.c_str());
} }
// do not activate the same scene again, only when forced to do so (e.g. by long press on the gui or when selected by hardware key) // do not activate the same scene again, only when forced to do so (e.g. by long press on the gui or when selected by hardware key)
bool callEndAndStartSequences; bool callEndAndStartSequences;
if ((scene_name == get_currentScene()) && ((isForcePayload != "FORCE") && (additionalPayload != "FORCE"))) { if ((scene_name == gui_memoryOptimizer_getActiveSceneName()) && ((isForcePayload != "FORCE") && (additionalPayload != "FORCE"))) {
Serial.printf("scene: will not start scene again, because it is already active\r\n"); Serial.printf("scene: will not start scene again, because it is already active\r\n");
callEndAndStartSequences = false; callEndAndStartSequences = false;
} else if ((scene_name == get_currentScene()) && ((isForcePayload == "FORCE") || (additionalPayload == "FORCE"))) { } else if ((scene_name == gui_memoryOptimizer_getActiveSceneName()) && ((isForcePayload == "FORCE") || (additionalPayload == "FORCE"))) {
Serial.printf("scene: scene is already active, but FORCE was set, so start scene again\r\n"); Serial.printf("scene: scene is already active, but FORCE was set, so start scene again\r\n");
callEndAndStartSequences = true; callEndAndStartSequences = true;
} else { } else {
@ -78,13 +103,13 @@ void handleScene(uint16_t command, commandData commandData, std::string addition
if (callEndAndStartSequences) { if (callEndAndStartSequences) {
// end old scene // end old scene
if (!sceneExists(get_currentScene()) && (get_currentScene() != "")) { if (!sceneExists(gui_memoryOptimizer_getActiveSceneName()) && (gui_memoryOptimizer_getActiveSceneName() != "")) {
Serial.printf("scene: WARNING: cannot end scene %s, because it is unknown\r\n", get_currentScene().c_str()); Serial.printf("scene: WARNING: cannot end scene %s, because it is unknown\r\n", gui_memoryOptimizer_getActiveSceneName().c_str());
} else { } else {
if (get_currentScene() != "") { if (gui_memoryOptimizer_getActiveSceneName() != "") {
Serial.printf("scene: will call end sequence for scene %s\r\n", get_currentScene().c_str()); Serial.printf("scene: will call end sequence for scene %s\r\n", gui_memoryOptimizer_getActiveSceneName().c_str());
scene_end_sequence_from_registry(get_currentScene()); scene_end_sequence_from_registry(gui_memoryOptimizer_getActiveSceneName());
} }
} }
@ -94,19 +119,47 @@ void handleScene(uint16_t command, commandData commandData, std::string addition
scene_start_sequence_from_registry(scene_name); scene_start_sequence_from_registry(scene_name);
} }
set_currentScene(scene_name); gui_memoryOptimizer_setActiveSceneName(scene_name);
if (SceneLabel != NULL) {lv_label_set_text(SceneLabel, get_currentScene().c_str());} if (SceneLabel != NULL) {lv_label_set_text(SceneLabel, gui_memoryOptimizer_getActiveSceneName().c_str());}
Serial.printf("scene: scene handling finished, new scene %s is active\r\n", get_currentScene().c_str()); Serial.printf("scene: scene handling finished, new scene %s is active\r\n", gui_memoryOptimizer_getActiveSceneName().c_str());
useSceneGUIlist = true; guis_doTabCreationAfterGUIlistChanged(SCENE_GUI_LIST);
// recreate the gui based on the current scene
guis_doAfterSliding(-1, -1, true);
} }
void setLabelCurrentScene() { void showSpecificGUI(GUIlists GUIlist, std::string GUIname) {
if ((SceneLabel != NULL) && sceneExists(get_currentScene())) { gui_list gui_list_for_search = get_gui_list_withFallback(GUIlist);
lv_label_set_text(SceneLabel, get_currentScene().c_str());
// 1. search for gui in the gui list
int gui_list_index = -1;
for (int i=0; i < gui_list_for_search->size(); i++) {
if (gui_list_for_search->at(i) == GUIname) {
Serial.printf("showSpecificGUI: found GUI with name \"%s\" in %s at position %d\r\n", GUIname.c_str(), GUIlist == MAIN_GUI_LIST ? "\"main_gui_list\"" : "\"scene gui list\"", i);
gui_list_index = i;
break;
}
} }
// 2. call guiBase.cpp
if ((gui_list_index >= 0) && (gui_list_index < gui_list_for_search->size())) {
guis_doTabCreationForSpecificGUI(GUIlist, gui_list_index);
} else {
// gui was not found
Serial.printf("showSpecificGUI: GUI with name \"%s\" was not found in gui list %s. Cannot navigate to that GUI\r\n", GUIname.c_str(), GUIlist == MAIN_GUI_LIST ? "\"main_gui_list\"" : "\"scene gui list\"");
return;
}
}
void handleGUI(uint16_t command, commandData commandData, std::string additionalPayload = "") {
auto current = commandData.commandPayloads.begin();
GUIlists GUIlist = (GUIlists)std::stoi(*current);
current = std::next(current, 1);
std::string GUIname = *current;
showSpecificGUI(GUIlist, GUIname);
} }

View File

@ -3,5 +3,6 @@
#include <string> #include <string>
#include "applicationInternal/commandHandler.h" #include "applicationInternal/commandHandler.h"
void setLabelActiveScene();
void handleScene(uint16_t command, commandData commandData, std::string additionalPayload = ""); void handleScene(uint16_t command, commandData commandData, std::string additionalPayload = "");
void setLabelCurrentScene(); void handleGUI (uint16_t command, commandData commandData, std::string additionalPayload = "");

View File

@ -1,28 +1,13 @@
#include <map> #include <map>
#include <stdexcept> #include <stdexcept>
#include "applicationInternal/commandHandler.h" #include "applicationInternal/gui/guiMemoryOptimizer.h"
#include "applicationInternal/scenes/sceneRegistry.h" #include "applicationInternal/gui/guiRegistry.h"
#include "applicationInternal/hardware/hardwarePresenter.h" #include "applicationInternal/hardware/hardwarePresenter.h"
#include "applicationInternal/scenes/sceneRegistry.h"
#include "applicationInternal/commandHandler.h"
// scenes // scenes
#include "scenes/scene__default.h" #include "scenes/scene__default.h"
// If useSceneGUIlist == true, then a scene is active and we are not in the main_gui_list (with the scene selector as first gui).
// In that case, we try to use the scene specific gui list, if the scene defined one.
// If useSceneGUIlist == false, then we are in the main_gui_list, either if a scene is active or not.
bool useSceneGUIlist = false;
// https://stackoverflow.com/questions/840501/how-do-function-pointers-in-c-work
struct scene_definition {
scene_setKeys this_scene_setKeys;
scene_start_sequence this_scene_start_sequence;
scene_end_sequence this_scene_end_sequence;
key_repeatModes this_key_repeatModes;
key_commands_short this_key_commands_short;
key_commands_long this_key_commands_long;
gui_list this_gui_list;
uint16_t this_activate_scene_command;
};
std::map<std::string, scene_definition> registered_scenes; std::map<std::string, scene_definition> registered_scenes;
t_scene_list scenes_on_sceneSelectionGUI; t_scene_list scenes_on_sceneSelectionGUI;
@ -54,15 +39,7 @@ void register_scene(
// Can be overwritten in main.cpp // Can be overwritten in main.cpp
scenes_on_sceneSelectionGUI.insert(scenes_on_sceneSelectionGUI.end(), {std::string(a_scene_name)}); scenes_on_sceneSelectionGUI.insert(scenes_on_sceneSelectionGUI.end(), {std::string(a_scene_name)});
// Whenever a new scene is registered, normally a new scene command has been defined immediately before (e.g. see register_scene_TV()). setKeysForAllRegisteredGUIsAndScenes();
// But this new scene command could have been already been used before in the key definition of another scene. The command at this time was 0, which is undefined.
// So we have to set the keys again for all scenes that have been registered before.
// 1. set again the defaultKeys
register_scene_defaultKeys();
// 2. loop over all registered scenes and call setKeys()
for (std::map<std::string, scene_definition>::iterator it = registered_scenes.begin(); it != registered_scenes.end(); ++it) {
it->second.this_scene_setKeys();
}
} }
@ -90,8 +67,14 @@ void scene_end_sequence_from_registry(std::string sceneName) {
repeatModes get_key_repeatMode(std::string sceneName, char keyChar) { repeatModes get_key_repeatMode(std::string sceneName, char keyChar) {
try { try {
// look if the map of the current scene has a definition for it // look if the map of the active gui has a definition for it
if ((registered_scenes.count(sceneName) > 0) && (registered_scenes.at(sceneName).this_key_repeatModes->count(keyChar) > 0)) { std::string GUIname = gui_memoryOptimizer_getActiveGUIname();
if ((registered_guis_byName_map.count(GUIname) > 0) && (registered_guis_byName_map.at(GUIname).this_key_repeatModes != NULL) && (registered_guis_byName_map.at(GUIname).this_key_repeatModes->count(keyChar) > 0)) {
// Serial.printf("get_key_repeatMode: will use key from gui %s\r\n", GUIname.c_str());
return registered_guis_byName_map.at(GUIname).this_key_repeatModes->at(keyChar);
// look if the map of the active scene has a definition for it
} else if ((registered_scenes.count(sceneName) > 0) && (registered_scenes.at(sceneName).this_key_repeatModes->count(keyChar) > 0)) {
// Serial.printf("get_key_repeatMode: will use key from scene %s\r\n", sceneName.c_str()); // Serial.printf("get_key_repeatMode: will use key from scene %s\r\n", sceneName.c_str());
return registered_scenes.at(sceneName).this_key_repeatModes->at(keyChar); return registered_scenes.at(sceneName).this_key_repeatModes->at(keyChar);
@ -114,8 +97,14 @@ repeatModes get_key_repeatMode(std::string sceneName, char keyChar) {
uint16_t get_command_short(std::string sceneName, char keyChar) { uint16_t get_command_short(std::string sceneName, char keyChar) {
try { try {
// look if the map of the current scene has a definition for it // look if the map of the active gui has a definition for it
if ((registered_scenes.count(sceneName) > 0) && (registered_scenes.at(sceneName).this_key_commands_short->count(keyChar) > 0)) { std::string GUIname = gui_memoryOptimizer_getActiveGUIname();
if ((registered_guis_byName_map.count(GUIname) > 0) && (registered_guis_byName_map.at(GUIname).this_key_commands_short != NULL) && (registered_guis_byName_map.at(GUIname).this_key_commands_short->count(keyChar) > 0)) {
// Serial.printf("get_command_short: will use key from gui %s\r\n", GUIname.c_str());
return registered_guis_byName_map.at(GUIname).this_key_commands_short->at(keyChar);
// look if the map of the active scene has a definition for it
} else if ((registered_scenes.count(sceneName) > 0) && (registered_scenes.at(sceneName).this_key_commands_short->count(keyChar) > 0)) {
// Serial.printf("get_command_short: will use key from scene %s\r\n", sceneName.c_str()); // Serial.printf("get_command_short: will use key from scene %s\r\n", sceneName.c_str());
return registered_scenes.at(sceneName).this_key_commands_short->at(keyChar); return registered_scenes.at(sceneName).this_key_commands_short->at(keyChar);
@ -139,8 +128,14 @@ uint16_t get_command_short(std::string sceneName, char keyChar) {
uint16_t get_command_long(std::string sceneName, char keyChar) { uint16_t get_command_long(std::string sceneName, char keyChar) {
try { try {
// look if the map of the current scene has a definition for it // look if the map of the active gui has a definition for it
if ((registered_scenes.count(sceneName) > 0) && (registered_scenes.at(sceneName).this_key_commands_long->count(keyChar) > 0)) { std::string GUIname = gui_memoryOptimizer_getActiveGUIname();
if ((registered_guis_byName_map.count(GUIname) > 0) && (registered_guis_byName_map.at(GUIname).this_key_commands_long != NULL) && (registered_guis_byName_map.at(GUIname).this_key_commands_long->count(keyChar) > 0)) {
// Serial.printf("get_command_long: will use key from gui %s\r\n", GUIname.c_str());
return registered_guis_byName_map.at(GUIname).this_key_commands_long->at(keyChar);
// look if the map of the active scene has a definition for it
} else if ((registered_scenes.count(sceneName) > 0) && (registered_scenes.at(sceneName).this_key_commands_long->count(keyChar) > 0)) {
// Serial.printf("get_command_long: will use key from scene %s\r\n", sceneName.c_str()); // Serial.printf("get_command_long: will use key from scene %s\r\n", sceneName.c_str());
return registered_scenes.at(sceneName).this_key_commands_long->at(keyChar); return registered_scenes.at(sceneName).this_key_commands_long->at(keyChar);
@ -162,40 +157,58 @@ uint16_t get_command_long(std::string sceneName, char keyChar) {
} }
gui_list get_gui_list(std::string sceneName) { gui_list get_gui_list_withFallback(GUIlists gui_list) {
try { try {
// If useSceneGUIlist == true, then a scene is active and we are not in the main_gui_list (with the scene selector as first gui). // If gui_list == MAIN_GUI_LIST, then we want the main_gui_list, either if a scene is active or not.
// In that case, we try to use the scene specific gui list, if the scene defined one. // If gui_list == SCENE_GUI_LIST, then we want the scene gui list. If none is defined, return main_gui_list as fallback.
// If useSceneGUIlist == false, then we are in the main_gui_list, either if a scene is active or not.
#if (USE_SCENE_SPECIFIC_GUI_LIST != 0) if (gui_list == MAIN_GUI_LIST) {
// look if the current scene has a definition for a gui list
if (useSceneGUIlist &&
(registered_scenes.count(sceneName) > 0) && (registered_scenes.at(sceneName).this_gui_list != NULL)) {
// Serial.printf("get_gui_list: will use gui_list from scene %s\r\n", sceneName.c_str());
return registered_scenes.at(sceneName).this_gui_list;
// if there is no scene specific gui list, simply return the main_gui_list
} else {
// Serial.printf("get_gui_list: will use main_gui_list\r\n");
return &main_gui_list; return &main_gui_list;
} } else {
#else #if (USE_SCENE_SPECIFIC_GUI_LIST != 0)
// never use scene specific gui list // look if the active scene has a definition for a gui list
return &main_gui_list; if ((registered_scenes.count(gui_memoryOptimizer_getActiveSceneName()) > 0) && (registered_scenes.at(gui_memoryOptimizer_getActiveSceneName()).this_gui_list != NULL)) {
#endif // Serial.printf("get_gui_list: will use gui_list from scene %s\r\n", sceneName.c_str());
return registered_scenes.at(gui_memoryOptimizer_getActiveSceneName()).this_gui_list;
} else {
// no scene specific gui list was defined
return &main_gui_list;
}
#else
// never use scene specific gui list
return &main_gui_list;
#endif
}
} }
catch (const std::out_of_range& oor) { catch (const std::out_of_range& oor) {
Serial.printf("get_gui_list: internal error, sceneName not registered\r\n"); Serial.printf("get_gui_list: internal error, sceneName not registered\r\n");
return NULL; return NULL;
} }
}
gui_list get_gui_list_active_withFallback() {
return get_gui_list_withFallback(gui_memoryOptimizer_getActiveGUIlist());
}
bool get_scene_has_gui_list(std::string sceneName) {
try {
// look if the scene is known
if ((registered_scenes.count(sceneName) > 0)) {
return (registered_scenes.at(sceneName).this_gui_list != NULL);
} else {
return false;
}
}
catch (const std::out_of_range& oor) {
Serial.printf("get_scene_has_gui_list: internal error, sceneName not registered\r\n");
return false;
}
} }
uint16_t get_activate_scene_command(std::string sceneName) { uint16_t get_activate_scene_command(std::string sceneName) {
try { try {
// look if the current scene is known // look if the scene is known
if ((registered_scenes.count(sceneName) > 0)) { if ((registered_scenes.count(sceneName) > 0)) {
// Serial.printf("get_activate_scene_command: will use activate_scene_command from scene %s\r\n", sceneName.c_str()); // Serial.printf("get_activate_scene_command: will use activate_scene_command from scene %s\r\n", sceneName.c_str());
return registered_scenes.at(sceneName).this_activate_scene_command; return registered_scenes.at(sceneName).this_activate_scene_command;

View File

@ -1,12 +1,9 @@
#pragma once #pragma once
#include <string> #include <string>
#include <stdint.h>
#include <map>
#include <vector> #include <vector>
#include "applicationInternal/keys.h" #include "applicationInternal/keys.h"
#include "applicationInternal/gui/guiMemoryOptimizer.h"
extern bool useSceneGUIlist;
typedef std::vector<std::string> t_gui_list; typedef std::vector<std::string> t_gui_list;
typedef std::vector<std::string> t_scene_list; typedef std::vector<std::string> t_scene_list;
@ -14,12 +11,23 @@ typedef std::vector<std::string> t_scene_list;
typedef void (*scene_setKeys)(void); typedef void (*scene_setKeys)(void);
typedef void (*scene_start_sequence)(void); typedef void (*scene_start_sequence)(void);
typedef void (*scene_end_sequence)(void); typedef void (*scene_end_sequence)(void);
typedef std::map<char, repeatModes> *key_repeatModes;
typedef std::map<char, uint16_t> *key_commands_short;
typedef std::map<char, uint16_t> *key_commands_long;
typedef t_gui_list *gui_list; typedef t_gui_list *gui_list;
typedef t_scene_list *scene_list; typedef t_scene_list *scene_list;
// https://stackoverflow.com/questions/840501/how-do-function-pointers-in-c-work
struct scene_definition {
scene_setKeys this_scene_setKeys;
scene_start_sequence this_scene_start_sequence;
scene_end_sequence this_scene_end_sequence;
key_repeatModes this_key_repeatModes;
key_commands_short this_key_commands_short;
key_commands_long this_key_commands_long;
gui_list this_gui_list;
uint16_t this_activate_scene_command;
};
extern std::map<std::string, scene_definition> registered_scenes;
void register_scene( void register_scene(
std::string a_scene_name, std::string a_scene_name,
scene_setKeys a_scene_setKeys, scene_setKeys a_scene_setKeys,
@ -37,7 +45,9 @@ void scene_end_sequence_from_registry(std::string sceneName);
repeatModes get_key_repeatMode(std::string sceneName, char keyChar); repeatModes get_key_repeatMode(std::string sceneName, char keyChar);
uint16_t get_command_short(std::string sceneName, char keyChar); uint16_t get_command_short(std::string sceneName, char keyChar);
uint16_t get_command_long(std::string sceneName, char keyChar); uint16_t get_command_long(std::string sceneName, char keyChar);
gui_list get_gui_list(std::string sceneName); gui_list get_gui_list_withFallback(GUIlists gui_list);
gui_list get_gui_list_active_withFallback();
bool get_scene_has_gui_list(std::string sceneName);
uint16_t get_activate_scene_command(std::string sceneName); uint16_t get_activate_scene_command(std::string sceneName);
scene_list get_scenes_on_sceneSelectionGUI(); scene_list get_scenes_on_sceneSelectionGUI();
void set_scenes_on_sceneSelectionGUI(t_scene_list a_scene_list); void set_scenes_on_sceneSelectionGUI(t_scene_list a_scene_list);

View File

@ -0,0 +1,46 @@
#include <lvgl.h>
#include "applicationInternal/gui/guiBase.h"
#include "applicationInternal/gui/guiRegistry.h"
#include "applicationInternal/commandHandler.h"
#include "devices/AVreceiver/device_yamahaAmp/device_yamahaAmp.h"
#include "devices/AVreceiver/device_yamahaAmp/gui_yamahaAmp.h"
static void button_clicked_event_cb(lv_event_t* e) {
int user_data = (intptr_t)(e->user_data);
if (user_data == 0) {
executeCommand(YAMAHA_STANDARD);
}
}
void create_tab_content_yamahaAmp(lv_obj_t* tab) {
// Add content to the sceneSelection tab
lv_obj_set_layout(tab, LV_LAYOUT_FLEX);
lv_obj_set_flex_flow(tab, LV_FLEX_FLOW_COLUMN);
lv_obj_set_scrollbar_mode(tab, LV_SCROLLBAR_MODE_ACTIVE);
// -- create a button for "standard" ----------------------------------------
lv_obj_t* button = lv_btn_create(tab);
lv_obj_set_size(button, 80, 40);
lv_obj_set_style_radius(button, 10, LV_PART_MAIN);
lv_obj_set_style_bg_color(button, color_primary, LV_PART_MAIN);
lv_obj_add_event_cb(button, button_clicked_event_cb, LV_EVENT_CLICKED, (void *)(intptr_t) 0);
lv_obj_t* label = lv_label_create(button);
lv_label_set_text(label, "Standard");
lv_obj_center(label);
}
void notify_tab_before_delete_yamahaAmp(void) {
// remember to set all pointers to lvgl objects to NULL if they might be accessed from outside.
// They must check if object is NULL and must not use it if so
}
void register_gui_yamahaAmp(void){
register_gui(std::string(tabName_yamahaAmp), & create_tab_content_yamahaAmp, & notify_tab_before_delete_yamahaAmp);
}

View File

@ -0,0 +1,4 @@
#pragma once
const char * const tabName_yamahaAmp = "Yamaha Amp";
void register_gui_yamahaAmp(void);

View File

@ -1,11 +1,13 @@
#include <lvgl.h> #include <lvgl.h>
#include "applicationInternal/hardware/hardwarePresenter.h"
#include "applicationInternal/gui/guiBase.h" #include "applicationInternal/gui/guiBase.h"
#include "applicationInternal/gui/guiRegistry.h" #include "applicationInternal/gui/guiRegistry.h"
#include "devices/misc/device_smarthome/gui_smarthome.h" #include "applicationInternal/hardware/hardwarePresenter.h"
#include "applicationInternal/scenes/sceneRegistry.h"
#include "applicationInternal/commandHandler.h" #include "applicationInternal/commandHandler.h"
#include "applicationInternal/keys.h"
#include "devices/misc/device_smarthome/gui_smarthome.h"
#include "devices/misc/device_smarthome/device_smarthome.h" #include "devices/misc/device_smarthome/device_smarthome.h"
#include "scenes/scene__default.h"
// LVGL declarations // LVGL declarations
LV_IMAGE_DECLARE(lightbulb); LV_IMAGE_DECLARE(lightbulb);
@ -20,6 +22,12 @@ static bool lightToggleBstate = false;
static int32_t sliderAvalue = 0; static int32_t sliderAvalue = 0;
static int32_t sliderBvalue = 0; static int32_t sliderBvalue = 0;
uint16_t GUI_SMARTHOME_ACTIVATE;
std::map<char, repeatModes> key_repeatModes_smarthome = {};
std::map<char, uint16_t> key_commands_short_smarthome = {};
std::map<char, uint16_t> key_commands_long_smarthome = {};
// Smart Home Toggle Event handler // Smart Home Toggle Event handler
static void smartHomeToggle_event_cb(lv_event_t* e){ static void smartHomeToggle_event_cb(lv_event_t* e){
std::string payload; std::string payload;
@ -158,6 +166,23 @@ void notify_tab_before_delete_smarthome(void) {
sliderBvalue = lv_slider_get_value(sliderB); sliderBvalue = lv_slider_get_value(sliderB);
} }
void register_gui_smarthome(void){ void gui_setKeys_smarthome() {
register_gui(std::string(tabName_smarthome), & create_tab_content_smarthome, & notify_tab_before_delete_smarthome); key_commands_short_smarthome = {
{KEY_STOP, SCENE_SELECTION},
};
}
void register_gui_smarthome(void){
register_gui(
std::string(tabName_smarthome),
& create_tab_content_smarthome,
& notify_tab_before_delete_smarthome,
& gui_setKeys_smarthome,
& key_repeatModes_smarthome,
& key_commands_short_smarthome,
& key_commands_long_smarthome
);
register_command(&GUI_SMARTHOME_ACTIVATE, makeCommandData(GUI, {std::to_string(MAIN_GUI_LIST), std::string(tabName_smarthome)}));
} }

View File

@ -3,4 +3,5 @@
#include <lvgl.h> #include <lvgl.h>
const char * const tabName_smarthome = "Smart Home"; const char * const tabName_smarthome = "Smart Home";
extern uint16_t GUI_SMARTHOME_ACTIVATE;
void register_gui_smarthome(void); void register_gui_smarthome(void);

View File

@ -18,12 +18,12 @@ static void virtualKeypad_event_cb(lv_event_t* e) {
int user_data = (intptr_t)(target->user_data); int user_data = (intptr_t)(target->user_data);
// send corrensponding number // send corrensponding number
if (get_currentScene() == scene_name_TV) { if (gui_memoryOptimizer_getActiveSceneName() == scene_name_TV) {
uint16_t virtualKeyMapTVNumbers[10] = {SAMSUNG_NUM_1, SAMSUNG_NUM_2, SAMSUNG_NUM_3, SAMSUNG_NUM_4, SAMSUNG_NUM_5, SAMSUNG_NUM_6, SAMSUNG_NUM_7, SAMSUNG_NUM_8, SAMSUNG_NUM_9, SAMSUNG_NUM_0}; uint16_t virtualKeyMapTVNumbers[10] = {SAMSUNG_NUM_1, SAMSUNG_NUM_2, SAMSUNG_NUM_3, SAMSUNG_NUM_4, SAMSUNG_NUM_5, SAMSUNG_NUM_6, SAMSUNG_NUM_7, SAMSUNG_NUM_8, SAMSUNG_NUM_9, SAMSUNG_NUM_0};
uint16_t command = virtualKeyMapTVNumbers[user_data]; uint16_t command = virtualKeyMapTVNumbers[user_data];
executeCommand(command); executeCommand(command);
} else if (get_currentScene() == scene_name_fireTV) { } else if (gui_memoryOptimizer_getActiveSceneName() == scene_name_fireTV) {
int virtualKeyMapFireTVNumbers[10] = {0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x0}; int virtualKeyMapFireTVNumbers[10] = {0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x0};
int number = virtualKeyMapFireTVNumbers[user_data]; int number = virtualKeyMapFireTVNumbers[user_data];
std::string numberStr = std::to_string(number); std::string numberStr = std::to_string(number);

View File

@ -31,6 +31,7 @@
#include "guis/gui_irReceiver.h" #include "guis/gui_irReceiver.h"
#include "guis/gui_settings.h" #include "guis/gui_settings.h"
#include "guis/gui_numpad.h" #include "guis/gui_numpad.h"
#include "devices/AVreceiver/device_yamahaAmp/gui_yamahaAmp.h"
#include "devices/mediaPlayer/device_appleTV/gui_appleTV.h" #include "devices/mediaPlayer/device_appleTV/gui_appleTV.h"
#include "devices/misc/device_smarthome/gui_smarthome.h" #include "devices/misc/device_smarthome/gui_smarthome.h"
#include "applicationInternal/keys.h" #include "applicationInternal/keys.h"
@ -102,6 +103,19 @@ int main(int argc, char *argv[]) {
#endif #endif
register_keyboardCommands(); register_keyboardCommands();
// Register the GUIs. They will be displayed in the order they have been registered.
register_gui_sceneSelection();
register_gui_irReceiver();
register_gui_settings();
register_gui_appleTV();
register_gui_numpad();
register_gui_smarthome();
register_gui_yamahaAmp();
// Only show these GUIs in the main gui list. If you don't set this explicitely, by default all registered guis are shown.
#if (USE_SCENE_SPECIFIC_GUI_LIST != 0)
main_gui_list = {tabName_yamahaAmp, tabName_sceneSelection, tabName_smarthome, tabName_settings, tabName_irReceiver};
#endif
// register the scenes and their key_commands_* // register the scenes and their key_commands_*
register_scene_defaultKeys(); register_scene_defaultKeys();
register_scene_TV(); register_scene_TV();
@ -112,20 +126,9 @@ int main(int argc, char *argv[]) {
// Only show these scenes on the sceneSelection gui. If you don't set this explicitely, by default all registered scenes are shown. // Only show these scenes on the sceneSelection gui. If you don't set this explicitely, by default all registered scenes are shown.
set_scenes_on_sceneSelectionGUI({scene_name_TV, scene_name_fireTV, scene_name_chromecast, scene_name_appleTV}); set_scenes_on_sceneSelectionGUI({scene_name_TV, scene_name_fireTV, scene_name_chromecast, scene_name_appleTV});
// register the GUIs. They will be displayed in the order they have been registered.
register_gui_sceneSelection();
register_gui_irReceiver();
register_gui_settings();
register_gui_appleTV();
register_gui_numpad();
register_gui_smarthome();
// Only show these GUIs in the main gui list. If you don't set this explicitely, by default all registered guis are shown.
#if (USE_SCENE_SPECIFIC_GUI_LIST != 0)
main_gui_list = {tabName_sceneSelection, tabName_smarthome, tabName_settings, tabName_irReceiver};
#endif
// init GUI - will initialize tft, touch and lvgl // init GUI - will initialize tft, touch and lvgl
init_gui(); init_gui();
setLabelCurrentScene(); setLabelActiveScene();
gui_loop(); // Run the LVGL UI once before the loop takes over gui_loop(); // Run the LVGL UI once before the loop takes over
// setup the Inertial Measurement Unit (IMU) for motion detection. Has to be after init_gui(), otherwise I2C will not work // setup the Inertial Measurement Unit (IMU) for motion detection. Has to be after init_gui(), otherwise I2C will not work

View File

@ -33,7 +33,7 @@ void scene_setKeys_TV() {
key_commands_short_TV = { key_commands_short_TV = {
{KEY_STOP, SAMSUNG_REWIND }, {KEY_REWI, SAMSUNG_PAUSE }, {KEY_PLAY, SAMSUNG_PLAY }, {KEY_FORW, SAMSUNG_FASTFORWARD}, {KEY_STOP, SAMSUNG_PAUSE }, {KEY_REWI, SAMSUNG_REWIND }, {KEY_PLAY, SAMSUNG_PLAY }, {KEY_FORW, SAMSUNG_FASTFORWARD},
{KEY_CONF, SAMSUNG_GUIDE }, {KEY_INFO, SAMSUNG_MENU }, {KEY_CONF, SAMSUNG_GUIDE }, {KEY_INFO, SAMSUNG_MENU },
{KEY_UP, SAMSUNG_UP }, {KEY_UP, SAMSUNG_UP },
{KEY_LEFT, SAMSUNG_LEFT }, {KEY_OK, SAMSUNG_SELECT }, {KEY_RIGHT, SAMSUNG_RIGHT }, {KEY_LEFT, SAMSUNG_LEFT }, {KEY_OK, SAMSUNG_SELECT }, {KEY_RIGHT, SAMSUNG_RIGHT },

View File

@ -4,6 +4,7 @@
#include "applicationInternal/commandHandler.h" #include "applicationInternal/commandHandler.h"
// devices // devices
#include "devices/AVreceiver/device_yamahaAmp/device_yamahaAmp.h" #include "devices/AVreceiver/device_yamahaAmp/device_yamahaAmp.h"
#include "devices/misc/device_smarthome/gui_smarthome.h"
// scenes // scenes
#include "scene__default.h" #include "scene__default.h"
#include "scenes/scene_allOff.h" #include "scenes/scene_allOff.h"
@ -14,9 +15,11 @@
uint16_t SCENE_SELECTION; uint16_t SCENE_SELECTION;
std::string scene_name_selection = "sceneSelection"; std::string scene_name_selection = "sceneSelection";
uint16_t SCENE_BACK_TO_PREVIOUS_GUI_LIST;
std::string scene_back_to_previous_gui_list = "backToPreviousList";
uint16_t GUI_PREV; uint16_t GUI_PREV;
uint16_t GUI_NEXT;
std::string scene_gui_prev = "GUI_prev"; std::string scene_gui_prev = "GUI_prev";
uint16_t GUI_NEXT;
std::string scene_gui_next = "GUI_next"; std::string scene_gui_next = "GUI_next";
std::map<char, repeatModes> key_repeatModes_default; std::map<char, repeatModes> key_repeatModes_default;
@ -45,14 +48,14 @@ void register_scene_defaultKeys(void) {
key_commands_short_default = { key_commands_short_default = {
{KEY_OFF, SCENE_ALLOFF_FORCE}, {KEY_OFF, SCENE_ALLOFF_FORCE},
/*{KEY_STOP, COMMAND_UNKNOWN }, {KEY_REWI, COMMAND_UNKNOWN }, {KEY_PLAY, COMMAND_UNKNOWN }, {KEY_FORW, COMMAND_UNKNOWN },*/ {KEY_STOP, GUI_SMARTHOME_ACTIVATE},/*{KEY_REWI, COMMAND_UNKNOWN }, {KEY_PLAY, COMMAND_UNKNOWN }, {KEY_FORW, COMMAND_UNKNOWN },*/
/*{KEY_CONF, COMMAND_UNKNOWN }, {KEY_INFO, COMMAND_UNKNOWN },*/ /*{KEY_CONF, COMMAND_UNKNOWN }, {KEY_INFO, COMMAND_UNKNOWN },*/
/* {KEY_UP, COMMAND_UNKNOWN },*/ /* {KEY_UP, COMMAND_UNKNOWN },*/
{KEY_LEFT, GUI_PREV }, /* {KEY_OK, COMMAND_UNKNOWN },*/ {KEY_RIGHT, GUI_NEXT }, {KEY_LEFT, GUI_PREV }, /* {KEY_OK, COMMAND_UNKNOWN },*/ {KEY_RIGHT, GUI_NEXT },
/* {KEY_DOWN, COMMAND_UNKNOWN },*/ /* {KEY_DOWN, COMMAND_UNKNOWN },*/
{KEY_BACK, SCENE_SELECTION }, /*{KEY_SRC, COMMAND_UNKNOWN },*/ {KEY_BACK, SCENE_SELECTION }, /*{KEY_SRC, COMMAND_UNKNOWN },*/
{KEY_VOLUP, YAMAHA_VOL_PLUS }, {KEY_MUTE, YAMAHA_MUTE_TOGGLE}, /*{KEY_CHUP, COMMAND_UNKNOWN },*/ {KEY_VOLUP, YAMAHA_VOL_PLUS }, {KEY_MUTE, YAMAHA_MUTE_TOGGLE}, /*{KEY_CHUP, COMMAND_UNKNOWN },*/
{KEY_VOLDO, YAMAHA_VOL_MINUS }, /* {KEY_REC, COMMAND_UNKNOWN },*/ /*{KEY_CHDOW, COMMAND_UNKNOWN },*/ {KEY_VOLDO, YAMAHA_VOL_MINUS }, {KEY_REC, SCENE_BACK_TO_PREVIOUS_GUI_LIST }, /*{KEY_CHDOW, COMMAND_UNKNOWN },*/
{KEY_RED, SCENE_TV_FORCE }, {KEY_GREEN, SCENE_FIRETV_FORCE}, {KEY_YELLO, SCENE_CHROMECAST_FORCE},{KEY_BLUE, SCENE_APPLETV_FORCE}, {KEY_RED, SCENE_TV_FORCE }, {KEY_GREEN, SCENE_FIRETV_FORCE}, {KEY_YELLO, SCENE_CHROMECAST_FORCE},{KEY_BLUE, SCENE_APPLETV_FORCE},
}; };
@ -61,8 +64,9 @@ void register_scene_defaultKeys(void) {
}; };
register_command(&SCENE_SELECTION, makeCommandData(SCENE, {scene_name_selection})); register_command(&SCENE_SELECTION , makeCommandData(SCENE, {scene_name_selection}));
register_command(&GUI_PREV , makeCommandData(SCENE, {scene_gui_prev})); register_command(&SCENE_BACK_TO_PREVIOUS_GUI_LIST, makeCommandData(SCENE, {scene_back_to_previous_gui_list}));
register_command(&GUI_NEXT , makeCommandData(SCENE, {scene_gui_next})); register_command(&GUI_PREV , makeCommandData(SCENE, {scene_gui_prev}));
register_command(&GUI_NEXT , makeCommandData(SCENE, {scene_gui_next}));
} }

View File

@ -6,12 +6,14 @@
#include "applicationInternal/keys.h" #include "applicationInternal/keys.h"
#include "applicationInternal/scenes/sceneRegistry.h" #include "applicationInternal/scenes/sceneRegistry.h"
extern uint16_t SCENE_SELECTION; // command extern uint16_t SCENE_SELECTION; // command
extern std::string scene_name_selection; // payload: name of this fake default scene extern std::string scene_name_selection; // payload: name of this fake default scene
extern uint16_t GUI_PREV; // command extern uint16_t SCENE_BACK_TO_PREVIOUS_GUI_LIST; // command
extern uint16_t GUI_NEXT; // command extern std::string scene_back_to_previous_gui_list; // payload: name of this fake scene
extern std::string scene_gui_prev; // payload: name of this fake scene extern uint16_t GUI_PREV; // command
extern std::string scene_gui_next; // payload: name of this fake scene extern std::string scene_gui_prev; // payload: name of this fake scene
extern uint16_t GUI_NEXT; // command
extern std::string scene_gui_next; // payload: name of this fake scene
extern std::map<char, repeatModes> key_repeatModes_default; extern std::map<char, repeatModes> key_repeatModes_default;
extern std::map<char, uint16_t> key_commands_short_default; extern std::map<char, uint16_t> key_commands_short_default;