From 46e9e97132f6983360ed2a89c4e5c6dd8e1d761c Mon Sep 17 00:00:00 2001 From: fvanroie Date: Thu, 16 Feb 2023 04:27:48 +0100 Subject: [PATCH] Allow any command in the swipe attribute (like action) --- include/lv_conf_v7.h | 10 +- src/hasp/hasp_attribute.cpp | 41 +++++--- src/hasp/hasp_attribute.h | 3 + src/hasp/hasp_attribute_helper.h | 159 ++++++++++++++++++++++++++++--- src/hasp/hasp_event.cpp | 81 ++++++---------- src/hasp/hasp_object.h | 7 ++ 6 files changed, 217 insertions(+), 84 deletions(-) diff --git a/include/lv_conf_v7.h b/include/lv_conf_v7.h index faa665e1..0c7945f6 100644 --- a/include/lv_conf_v7.h +++ b/include/lv_conf_v7.h @@ -851,12 +851,12 @@ typedef void* lv_font_user_data_t; typedef struct { uint8_t id:8; uint8_t objid:6; - uint8_t transitionid:4; - uint8_t actionid:4; + //uint8_t transitionid:4; + //uint8_t actionid:4; uint8_t groupid:4; - uint8_t swipeid:4; - void* tag; - char* action; + // uint8_t swipeid:4; + void* ext; + // char* action; } lv_obj_user_data_t; /*1: enable `lv_obj_realaign()` based on `lv_obj_align()` parameters*/ diff --git a/src/hasp/hasp_attribute.cpp b/src/hasp/hasp_attribute.cpp index 992cffbe..77fd2f59 100644 --- a/src/hasp/hasp_attribute.cpp +++ b/src/hasp/hasp_attribute.cpp @@ -1637,6 +1637,18 @@ static hasp_attribute_type_t attribute_common_tag(lv_obj_t* obj, uint16_t attr_h } break; // attribute_found + case ATTR_SWIPE: + if(update) { + my_obj_set_swipe(obj, payload); + } else { + if(my_obj_get_swipe(obj)) { + *text = (char*)my_obj_get_swipe(obj); + } else { + strcpy_P(*text, "null"); // TODO : Literal String + } + } + break; // attribute_found + default: return HASP_ATTR_TYPE_NOT_FOUND; } @@ -2324,12 +2336,12 @@ static hasp_attribute_type_t attribute_common_int(lv_obj_t* obj, uint16_t attr_h val = obj->user_data.groupid; break; // attribute_found - case ATTR_TRANSITION: - if(update) - obj->user_data.transitionid = (uint8_t)val; - else - val = obj->user_data.transitionid; - break; // attribute_found + // case ATTR_TRANSITION: + // if(update) + // obj->user_data.transitionid = (uint8_t)val; + // else + // val = obj->user_data.transitionid; + // break; // attribute_found case ATTR_OBJID: if(update && val != obj->user_data.objid) return HASP_ATTR_TYPE_INT_READONLY; @@ -2450,12 +2462,12 @@ static hasp_attribute_type_t attribute_common_bool(lv_obj_t* obj, uint16_t attr_ val = !(lv_obj_get_state(obj, LV_BTN_PART_MAIN) & LV_STATE_DISABLED); break; // attribute_found - case ATTR_SWIPE: - if(update) - obj->user_data.swipeid = (!!val) % 16; - else - val = obj->user_data.swipeid; - break; // attribute_found + // case ATTR_SWIPE: + // if(update) + // obj->user_data.swipeid = (!!val) % 16; + // else + // val = obj->user_data.swipeid; + // break; // attribute_found case ATTR_TOGGLE: switch(obj_get_type(obj)) { @@ -2594,7 +2606,7 @@ void hasp_process_obj_attribute(lv_obj_t* obj, const char* attribute, const char switch(attr_hash) { case ATTR_GROUPID: case ATTR_ID: - case ATTR_TRANSITION: + // case ATTR_TRANSITION: case ATTR_OBJID: case ATTR_X: case ATTR_Y: @@ -2611,7 +2623,7 @@ void hasp_process_obj_attribute(lv_obj_t* obj, const char* attribute, const char case ATTR_HIDDEN: case ATTR_TOGGLE: case ATTR_CLICK: - case ATTR_SWIPE: + // case ATTR_SWIPE: case ATTR_ENABLED: val = Parser::is_true(payload); ret = attribute_common_bool(obj, attr_hash, val, update); @@ -2644,6 +2656,7 @@ void hasp_process_obj_attribute(lv_obj_t* obj, const char* attribute, const char break; case ATTR_TAG: case ATTR_ACTION: + case ATTR_SWIPE: ret = attribute_common_tag(obj, attr_hash, payload, &text, update); break; case ATTR_JSONL: diff --git a/src/hasp/hasp_attribute.h b/src/hasp/hasp_attribute.h index 9a1e24d9..adb098cd 100644 --- a/src/hasp/hasp_attribute.h +++ b/src/hasp/hasp_attribute.h @@ -17,7 +17,10 @@ lv_chart_series_t* my_chart_get_series(lv_obj_t* chart, uint8_t ser_num); void my_obj_set_value_str_text(lv_obj_t* obj, uint8_t part, lv_state_t state, const char* text); void my_obj_set_tag(lv_obj_t* obj, const char* tag); void my_obj_set_action(lv_obj_t* obj, const char* tag); +void my_obj_set_swipe(lv_obj_t* obj, const char* tag); const char* my_obj_get_tag(lv_obj_t* obj); +const char* my_obj_get_action(lv_obj_t* obj); +const char* my_obj_get_swipe(lv_obj_t* obj); void my_btnmatrix_map_clear(lv_obj_t* obj); void my_msgbox_map_clear(lv_obj_t* obj); void my_line_clear_points(lv_obj_t* obj); diff --git a/src/hasp/hasp_attribute_helper.h b/src/hasp/hasp_attribute_helper.h index 929df661..cad7951f 100644 --- a/src/hasp/hasp_attribute_helper.h +++ b/src/hasp/hasp_attribute_helper.h @@ -58,8 +58,67 @@ void my_obj_set_template(lv_obj_t* obj, const char* text) LOG_WARNING(TAG_ATTR, "Failed to allocate memory!"); } +static hasp_ext_user_data_t* my_create_ext_tag(lv_obj_t* obj) +{ + void* ext = hasp_calloc(1, sizeof(hasp_ext_user_data_t)); + obj->user_data.ext = ext; + return (hasp_ext_user_data_t*)ext; +} + +void my_obj_set_tag(lv_obj_t* obj, const char* payload) +{ + hasp_ext_user_data_t* ext = (hasp_ext_user_data_t*)obj->user_data.ext; + + // extended tag exists, free old tag + if(ext && ext->tag) { + hasp_free(ext->tag); + ext->tag = NULL; + } + + // new tag is blank + if(payload == NULL || payload[0] == '\0') { + // my_prune_ext_tag(obj); // delete extended data if all extended properties are NULL + return; + } + + // create new extended tags + if(!ext) { + ext = my_create_ext_tag(obj); + } + + // create new tag + if(ext) { + StaticJsonDocument<512> doc; + size_t len = payload ? strlen(payload) : 0; + + // check if it is a proper JSON object + DeserializationError error = deserializeJson(doc, payload, len); + if(error != DeserializationError::Ok) doc.set(payload); // use tag as-is + + const size_t size = measureJson(doc) + 1; + if(char* str = (char*)hasp_malloc(size)) { + len = serializeJson(doc, str, size); // tidy-up the json object + ext->tag = str; + LOG_VERBOSE(TAG_ATTR, "new json: %s", str); + return; + } + } + + // ext or str was NULL + LOG_WARNING(TAG_ATTR, D_ERROR_OUT_OF_MEMORY); +} + // the tag data is stored as SERIALIZED JSON data -void my_obj_set_tag(lv_obj_t* obj, const char* tag) +const char* my_obj_get_tag(lv_obj_t* obj) +{ + hasp_ext_user_data_t* ext = (hasp_ext_user_data_t*)obj->user_data.ext; + if(!ext) return NULL; + return ext->tag; +} + +/* +// the tag data is stored as SERIALIZED JSON data +void my_obj_set_tag2(lv_obj_t* obj, const char* tag) { size_t len = tag ? strlen(tag) : 0; @@ -90,45 +149,115 @@ void my_obj_set_tag(lv_obj_t* obj, const char* tag) } // the tag data is stored as SERIALIZED JSON data -const char* my_obj_get_tag(lv_obj_t* obj) +const char* my_obj_get_tag2(lv_obj_t* obj) { return (char*)obj->user_data.tag; } +*/ // the action data is stored as SERIALIZED JSON data -void my_obj_set_action(lv_obj_t* obj, const char* action) +void my_obj_set_action(lv_obj_t* obj, const char* payload) { - // release old action - if(obj->user_data.action) { - hasp_free(obj->user_data.action); - obj->user_data.action = NULL; + hasp_ext_user_data_t* ext = (hasp_ext_user_data_t*)obj->user_data.ext; + + // extended tag exists, free old tag + if(ext && ext->action) { + hasp_free(ext->action); + ext->action = NULL; } - // new action is blank - if(action == NULL || action[0] == '\0') return; + // new tag is blank + if(payload == NULL || payload[0] == '\0') { + // my_prune_ext_tag(obj); // delete extended data if all extended properties are NULL + return; + } + + // create new extended tags + if(!ext) { + ext = my_create_ext_tag(obj); + } // create new action { StaticJsonDocument<512> doc; - // size_t len = action ? strlen(action) : 0; + size_t len = payload ? strlen(payload) : 0; // check if it is a proper JSON object - DeserializationError error = deserializeJson(doc, action /*, len*/); - if(error != DeserializationError::Ok) doc.set(action); // use tag as-is + DeserializationError error = deserializeJson(doc, payload, len); + if(error != DeserializationError::Ok) doc.set(payload); // use tag as-is const size_t size = measureJson(doc) + 1; if(char* str = (char*)hasp_malloc(size)) { - size_t len = serializeJson(doc, str, size); // tidy-up the json object - obj->user_data.action = str; + size_t len = serializeJson(doc, str, size); // tidy-up the json object + ext->action = str; LOG_VERBOSE(TAG_ATTR, "new json: %s", str); + return; } } + + // ext or str was NULL + LOG_WARNING(TAG_ATTR, D_ERROR_OUT_OF_MEMORY); } // the tag data is stored as SERIALIZED JSON data const char* my_obj_get_action(lv_obj_t* obj) { - return obj->user_data.action; + hasp_ext_user_data_t* ext = (hasp_ext_user_data_t*)obj->user_data.ext; + if(!ext) return NULL; + return ext->action; +} + + +// the swipe data is stored as SERIALIZED JSON data +void my_obj_set_swipe(lv_obj_t* obj, const char* payload) +{ + hasp_ext_user_data_t* ext = (hasp_ext_user_data_t*)obj->user_data.ext; + + // extended tag exists, free old tag + if(ext && ext->swipe) { + hasp_free(ext->swipe); + ext->swipe = NULL; + } + + // new tag is blank + if(payload == NULL || payload[0] == '\0') { + // my_prune_ext_tag(obj); // delete extended data if all extended properties are NULL + return; + } + + // create new extended tags + if(!ext) { + ext = my_create_ext_tag(obj); + } + + // create new action + { + StaticJsonDocument<512> doc; + size_t len = payload ? strlen(payload) : 0; + + // check if it is a proper JSON object + DeserializationError error = deserializeJson(doc, payload, len); + if(error != DeserializationError::Ok) doc.set(payload); // use tag as-is + + const size_t size = measureJson(doc) + 1; + if(char* str = (char*)hasp_malloc(size)) { + size_t len = serializeJson(doc, str, size); // tidy-up the json object + ext->swipe = str; + LOG_VERBOSE(TAG_ATTR, "new json: %s", str); + return; + } + } + + // ext or str was NULL + LOG_WARNING(TAG_ATTR, D_ERROR_OUT_OF_MEMORY); +} + +// the tag data is stored as SERIALIZED JSON data +const char* my_obj_get_swipe(lv_obj_t* obj) +{ + hasp_ext_user_data_t* ext = (hasp_ext_user_data_t*)obj->user_data.ext; + if(!ext) return NULL; + return ext->swipe; } lv_label_align_t my_textarea_get_text_align(lv_obj_t* ta) diff --git a/src/hasp/hasp_event.cpp b/src/hasp/hasp_event.cpp index 3a2f8602..6a41129f 100644 --- a/src/hasp/hasp_event.cpp +++ b/src/hasp/hasp_event.cpp @@ -42,6 +42,25 @@ void event_reset_last_value_sent() last_value_sent = INT16_MIN; } +void script_event_handler(const char* eventname, const char* json) +{ + StaticJsonDocument<256> doc; + StaticJsonDocument<64> filter; + + filter[eventname] = true; + DeserializationError jsonError = deserializeJson(doc, json, DeserializationOption::Filter(filter)); + + if(!jsonError) { + JsonVariant json = doc[eventname].as(); + uint8_t savedPage = haspPages.get(); + if(!dispatch_json_variant(json, savedPage, TAG_EVENT)) { + LOG_WARNING(TAG_EVENT, F(D_DISPATCH_COMMAND_NOT_FOUND), eventname); + } + } else { + dispatch_json_error(TAG_EVENT, jsonError); + } +} + /** * Clean-up allocated memory before an object is deleted * @param obj pointer to an object to clean-up @@ -87,6 +106,7 @@ void delete_event_handler(lv_obj_t* obj, lv_event_t event) } my_obj_set_tag(obj, (char*)NULL); my_obj_set_action(obj, (char*)NULL); + my_obj_set_swipe(obj, (char*)NULL); } /* ============================== Timer Event ============================ */ @@ -239,7 +259,7 @@ static void event_send_object_data(lv_obj_t* obj, const char* data) if(!data) return; object_dispatch_state(pageid, objid, data); } else { - LOG_ERROR(TAG_MSGR, F(D_OBJECT_UNKNOWN)); + LOG_ERROR(TAG_EVENT, F(D_OBJECT_UNKNOWN)); } } @@ -370,22 +390,22 @@ void first_touch_event_handler(lv_obj_t* obj, lv_event_t event) void swipe_event_handler(lv_obj_t* obj, lv_event_t event) { - if(!obj || obj->user_data.swipeid == 0) return; + if(event != LV_EVENT_GESTURE || !obj || !obj->user_data.ext) return; - if(event == LV_EVENT_GESTURE) { + if(const char* swipe = my_obj_get_swipe(obj)) { lv_gesture_dir_t dir = lv_indev_get_gesture_dir(lv_indev_get_act()); switch(dir) { case LV_GESTURE_DIR_LEFT: - haspPages.next(LV_SCR_LOAD_ANIM_NONE, 500, 0); + script_event_handler("left", swipe); break; case LV_GESTURE_DIR_RIGHT: - haspPages.prev(LV_SCR_LOAD_ANIM_NONE, 500, 0); + script_event_handler("right", swipe); break; case LV_GESTURE_DIR_BOTTOM: - haspPages.back(LV_SCR_LOAD_ANIM_NONE, 500, 0); + script_event_handler("down", swipe); break; default: - dispatch_current_page(); + script_event_handler("up", swipe); } } } @@ -492,49 +512,10 @@ void generic_event_handler(lv_obj_t* obj, lv_event_t event) if(last_value_sent == HASP_EVENT_LOST) return; - if(obj->user_data.action) { - // if(last_value_sent == HASP_EVENT_UP || last_value_sent == HASP_EVENT_RELEASE) { - // dispatch_text_line(obj->user_data.action, TAG_EVENT); - - StaticJsonDocument<256> doc; - StaticJsonDocument<64> filter; - char eventname[8]; - - Parser::get_event_name(last_value_sent, eventname, sizeof(eventname)); - filter[eventname] = true; - DeserializationError jsonError = - deserializeJson(doc, (const char*)obj->user_data.action, DeserializationOption::Filter(filter)); - - if(!jsonError) { - JsonVariant json = doc[eventname].as(); - uint8_t savedPage = haspPages.get(); - if(!dispatch_json_variant(json, savedPage, TAG_EVENT)) { - LOG_WARNING(TAG_MSGR, F(D_DISPATCH_COMMAND_NOT_FOUND), eventname); - // dispatch_simple_text_command(payload, source); - } - } - // } - - } else if(obj->user_data.actionid) { - /* If an actionid is attached, perform that action on UP event only */ - if(last_value_sent == HASP_EVENT_UP || last_value_sent == HASP_EVENT_RELEASE) { - lv_scr_load_anim_t transitionid = (lv_scr_load_anim_t)obj->user_data.transitionid; - switch(obj->user_data.actionid) { - case HASP_NUM_PAGE_PREV: - haspPages.prev(transitionid, 500, 0); - break; - case HASP_NUM_PAGE_BACK: - haspPages.back(transitionid, 500, 0); - break; - case HASP_NUM_PAGE_NEXT: - haspPages.next(transitionid, 500, 0); - break; - default: - haspPages.set(obj->user_data.actionid, transitionid, 500, 0); - } - dispatch_current_page(); - } - + if(const char* action = my_obj_get_action(obj)) { + char eventname[8]; + Parser::get_event_name(last_value_sent, eventname, sizeof(eventname)); + script_event_handler(eventname, action); } else { char data[512]; { diff --git a/src/hasp/hasp_object.h b/src/hasp/hasp_object.h index f8284b1b..79f9edad 100644 --- a/src/hasp/hasp_object.h +++ b/src/hasp/hasp_object.h @@ -14,6 +14,13 @@ const char FP_OBJID[] PROGMEM = "objid"; const char FP_PARENTID[] PROGMEM = "parentid"; const char FP_GROUPID[] PROGMEM = "groupid"; +typedef struct +{ + char* action; + char* swipe; + char* tag; +} hasp_ext_user_data_t; + typedef struct { lv_obj_t* obj;