allow gui specific key bindings

This commit is contained in:
KlausMu 2024-04-22 21:52:48 +02:00 committed by Klaus Musch
parent d833827fab
commit 267e39bf93
7 changed files with 108 additions and 20 deletions

View file

@ -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<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) {
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<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,31 @@
#include <vector>
#include <map>
#include <lvgl.h>
#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<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
);

View file

@ -1,5 +1,8 @@
#pragma once
#include <map>
#include <stdint.h>
enum repeatModes {
// only as fallback
REPEAT_MODE_UNKNOWN,
@ -15,4 +18,8 @@ enum repeatModes {
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);

View file

@ -1,6 +1,7 @@
#include <map>
#include <stdexcept>
#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<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();
}
}
}
@ -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);

View file

@ -1,8 +1,6 @@
#pragma once
#include <string>
#include <stdint.h>
#include <map>
#include <vector>
#include "applicationInternal/keys.h"
#include "applicationInternal/gui/guiMemoryOptimizer.h"
@ -13,9 +11,6 @@ typedef std::vector<std::string> t_scene_list;
typedef void (*scene_setKeys)(void);
typedef void (*scene_start_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_scene_list *scene_list;

View file

@ -1,11 +1,13 @@
#include <lvgl.h>
#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<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
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)}));
}

View file

@ -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();