From 267e39bf934d38b053dd58045b7cc744ec7d8e1a Mon Sep 17 00:00:00 2001 From: KlausMu Date: Mon, 22 Apr 2024 21:52:48 +0200 Subject: [PATCH] allow gui specific key bindings --- .../applicationInternal/gui/guiRegistry.cpp | 31 ++++++++++++++-- .../src/applicationInternal/gui/guiRegistry.h | 18 ++++++++-- Platformio/src/applicationInternal/keys.h | 7 ++++ .../scenes/sceneRegistry.cpp | 35 ++++++++++++++++--- .../scenes/sceneRegistry.h | 5 --- .../misc/device_smarthome/gui_smarthome.cpp | 29 ++++++++++++--- Platformio/src/main.cpp | 3 +- 7 files changed, 108 insertions(+), 20 deletions(-) diff --git a/Platformio/src/applicationInternal/gui/guiRegistry.cpp b/Platformio/src/applicationInternal/gui/guiRegistry.cpp index 29acd28..b2c30fd 100644 --- a/Platformio/src/applicationInternal/gui/guiRegistry.cpp +++ b/Platformio/src/applicationInternal/gui/guiRegistry.cpp @@ -6,6 +6,7 @@ #include "guiRegistry.h" #include "applicationInternal/gui/guiBase.h" #include "applicationInternal/hardware/hardwarePresenter.h" +#include "applicationInternal/scenes/sceneRegistry.h" #include "scenes/scene__default.h" // ------------------------------------------------------------------------------------ @@ -15,14 +16,30 @@ std::map 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) { Serial.printf("ERROR!!!: you cannot register two guis having the same name '%s'\r\n", a_name.c_str()); 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 registered_guis_byName_map[a_name] = new_gui_definition; @@ -31,4 +48,14 @@ 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. main_gui_list.insert(main_gui_list.end(), {std::string(a_name)}); + // Whenever a new gui is registered, a new gui command could have been defined. + // But this new gui command could have been already been used before in the key definition of another gui. The command at this time was 0, which is undefined. + // So we have to set the keys again for all guis that have been registered before. + // Loop over all registered guis and call setKeys() + for (std::map::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(); + } + } + } diff --git a/Platformio/src/applicationInternal/gui/guiRegistry.h b/Platformio/src/applicationInternal/gui/guiRegistry.h index cbe541f..c4a6296 100644 --- a/Platformio/src/applicationInternal/gui/guiRegistry.h +++ b/Platformio/src/applicationInternal/gui/guiRegistry.h @@ -22,19 +22,31 @@ #include #include #include +#include "applicationInternal/keys.h" typedef void (*create_tab_content)(lv_obj_t* tab); typedef void (*notify_tab_before_delete)(void); +typedef void (*gui_setKeys)(void); // https://stackoverflow.com/questions/840501/how-do-function-pointers-in-c-work struct gui_definition { std::string this_name; create_tab_content this_create_tab_content; notify_tab_before_delete this_notify_tab_before_delete; - uint32_t this_tabID; - lv_obj_t* this_tab; + gui_setKeys this_gui_setKeys; + key_repeatModes this_key_repeatModes; + key_commands_short this_key_commands_short; + key_commands_long this_key_commands_long; }; extern std::map 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 + ); diff --git a/Platformio/src/applicationInternal/keys.h b/Platformio/src/applicationInternal/keys.h index f38be73..f2004f5 100644 --- a/Platformio/src/applicationInternal/keys.h +++ b/Platformio/src/applicationInternal/keys.h @@ -1,5 +1,8 @@ #pragma once +#include +#include + enum repeatModes { // only as fallback REPEAT_MODE_UNKNOWN, @@ -15,4 +18,8 @@ enum repeatModes { SHORTorLONG, }; +typedef std::map *key_repeatModes; +typedef std::map *key_commands_short; +typedef std::map *key_commands_long; + void keypad_loop(void); diff --git a/Platformio/src/applicationInternal/scenes/sceneRegistry.cpp b/Platformio/src/applicationInternal/scenes/sceneRegistry.cpp index ceec140..53c8f5b 100644 --- a/Platformio/src/applicationInternal/scenes/sceneRegistry.cpp +++ b/Platformio/src/applicationInternal/scenes/sceneRegistry.cpp @@ -1,6 +1,7 @@ #include #include #include "applicationInternal/gui/guiMemoryOptimizer.h" +#include "applicationInternal/gui/guiRegistry.h" #include "applicationInternal/hardware/hardwarePresenter.h" #include "applicationInternal/scenes/sceneRegistry.h" #include "applicationInternal/commandHandler.h" @@ -51,14 +52,20 @@ void register_scene( 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()). - // 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. + // But this new scene command could have been already been used before in the key definition of another scene or a gui. The command at this time was 0, which is undefined. + // So we have to set the keys again for all scenes and guis 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::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::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(); + } + } } @@ -86,8 +93,14 @@ void scene_end_sequence_from_registry(std::string sceneName) { repeatModes get_key_repeatMode(std::string sceneName, char keyChar) { try { + // look if the map of the active gui has a definition for it + 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 - if ((registered_scenes.count(sceneName) > 0) && (registered_scenes.at(sceneName).this_key_repeatModes->count(keyChar) > 0)) { + } 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()); return registered_scenes.at(sceneName).this_key_repeatModes->at(keyChar); @@ -110,8 +123,14 @@ repeatModes get_key_repeatMode(std::string sceneName, char keyChar) { uint16_t get_command_short(std::string sceneName, char keyChar) { try { + // look if the map of the active gui has a definition for it + 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 - if ((registered_scenes.count(sceneName) > 0) && (registered_scenes.at(sceneName).this_key_commands_short->count(keyChar) > 0)) { + } 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()); return registered_scenes.at(sceneName).this_key_commands_short->at(keyChar); @@ -135,8 +154,14 @@ uint16_t get_command_short(std::string sceneName, char keyChar) { uint16_t get_command_long(std::string sceneName, char keyChar) { try { + // look if the map of the active gui has a definition for it + 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 - if ((registered_scenes.count(sceneName) > 0) && (registered_scenes.at(sceneName).this_key_commands_long->count(keyChar) > 0)) { + } 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()); return registered_scenes.at(sceneName).this_key_commands_long->at(keyChar); diff --git a/Platformio/src/applicationInternal/scenes/sceneRegistry.h b/Platformio/src/applicationInternal/scenes/sceneRegistry.h index 05ebfbf..06c3d64 100644 --- a/Platformio/src/applicationInternal/scenes/sceneRegistry.h +++ b/Platformio/src/applicationInternal/scenes/sceneRegistry.h @@ -1,8 +1,6 @@ #pragma once #include -#include -#include #include #include "applicationInternal/keys.h" #include "applicationInternal/gui/guiMemoryOptimizer.h" @@ -13,9 +11,6 @@ typedef std::vector t_scene_list; typedef void (*scene_setKeys)(void); typedef void (*scene_start_sequence)(void); typedef void (*scene_end_sequence)(void); -typedef std::map *key_repeatModes; -typedef std::map *key_commands_short; -typedef std::map *key_commands_long; typedef t_gui_list *gui_list; typedef t_scene_list *scene_list; diff --git a/Platformio/src/devices/misc/device_smarthome/gui_smarthome.cpp b/Platformio/src/devices/misc/device_smarthome/gui_smarthome.cpp index 4cc1e13..90a072d 100644 --- a/Platformio/src/devices/misc/device_smarthome/gui_smarthome.cpp +++ b/Platformio/src/devices/misc/device_smarthome/gui_smarthome.cpp @@ -1,11 +1,13 @@ #include -#include "applicationInternal/hardware/hardwarePresenter.h" #include "applicationInternal/gui/guiBase.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/keys.h" +#include "devices/misc/device_smarthome/gui_smarthome.h" #include "devices/misc/device_smarthome/device_smarthome.h" +#include "scenes/scene__default.h" // LVGL declarations LV_IMG_DECLARE(lightbulb); @@ -22,6 +24,10 @@ static int32_t sliderBvalue = 0; uint16_t GUI_SMARTHOME_ACTIVATE; +std::map key_repeatModes_smarthome = {}; +std::map key_commands_short_smarthome = {}; +std::map key_commands_long_smarthome = {}; + // Smart Home Toggle Event handler static void smartHomeToggle_event_cb(lv_event_t* e){ std::string payload; @@ -160,8 +166,23 @@ void notify_tab_before_delete_smarthome(void) { sliderBvalue = lv_slider_get_value(sliderB); } +void gui_setKeys_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); + + 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::string(tabName_smarthome)})); } diff --git a/Platformio/src/main.cpp b/Platformio/src/main.cpp index f6d9d41..0037358 100644 --- a/Platformio/src/main.cpp +++ b/Platformio/src/main.cpp @@ -102,7 +102,8 @@ int main(int argc, char *argv[]) { #endif register_keyboardCommands(); - // register the GUIs. They will be displayed in the order they have been registered. + // Register the GUIs. They will be displayed in the order they have been registered. + // GUIs must be registered before the scenes, because only the scenes re-register key bindings to commands which have been defined after the key binding (see register_scene()) register_gui_sceneSelection(); register_gui_irReceiver(); register_gui_settings();