Allow any command in the swipe attribute (like action)

This commit is contained in:
fvanroie 2023-02-16 04:27:48 +01:00
parent c296a5e568
commit 46e9e97132
6 changed files with 217 additions and 84 deletions

View File

@ -851,12 +851,12 @@ typedef void* lv_font_user_data_t;
typedef struct { typedef struct {
uint8_t id:8; uint8_t id:8;
uint8_t objid:6; uint8_t objid:6;
uint8_t transitionid:4; //uint8_t transitionid:4;
uint8_t actionid:4; //uint8_t actionid:4;
uint8_t groupid:4; uint8_t groupid:4;
uint8_t swipeid:4; // uint8_t swipeid:4;
void* tag; void* ext;
char* action; // char* action;
} lv_obj_user_data_t; } lv_obj_user_data_t;
/*1: enable `lv_obj_realaign()` based on `lv_obj_align()` parameters*/ /*1: enable `lv_obj_realaign()` based on `lv_obj_align()` parameters*/

View File

@ -1637,6 +1637,18 @@ static hasp_attribute_type_t attribute_common_tag(lv_obj_t* obj, uint16_t attr_h
} }
break; // attribute_found 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: default:
return HASP_ATTR_TYPE_NOT_FOUND; 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; val = obj->user_data.groupid;
break; // attribute_found break; // attribute_found
case ATTR_TRANSITION: // case ATTR_TRANSITION:
if(update) // if(update)
obj->user_data.transitionid = (uint8_t)val; // obj->user_data.transitionid = (uint8_t)val;
else // else
val = obj->user_data.transitionid; // val = obj->user_data.transitionid;
break; // attribute_found // break; // attribute_found
case ATTR_OBJID: case ATTR_OBJID:
if(update && val != obj->user_data.objid) return HASP_ATTR_TYPE_INT_READONLY; 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); val = !(lv_obj_get_state(obj, LV_BTN_PART_MAIN) & LV_STATE_DISABLED);
break; // attribute_found break; // attribute_found
case ATTR_SWIPE: // case ATTR_SWIPE:
if(update) // if(update)
obj->user_data.swipeid = (!!val) % 16; // obj->user_data.swipeid = (!!val) % 16;
else // else
val = obj->user_data.swipeid; // val = obj->user_data.swipeid;
break; // attribute_found // break; // attribute_found
case ATTR_TOGGLE: case ATTR_TOGGLE:
switch(obj_get_type(obj)) { 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) { switch(attr_hash) {
case ATTR_GROUPID: case ATTR_GROUPID:
case ATTR_ID: case ATTR_ID:
case ATTR_TRANSITION: // case ATTR_TRANSITION:
case ATTR_OBJID: case ATTR_OBJID:
case ATTR_X: case ATTR_X:
case ATTR_Y: 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_HIDDEN:
case ATTR_TOGGLE: case ATTR_TOGGLE:
case ATTR_CLICK: case ATTR_CLICK:
case ATTR_SWIPE: // case ATTR_SWIPE:
case ATTR_ENABLED: case ATTR_ENABLED:
val = Parser::is_true(payload); val = Parser::is_true(payload);
ret = attribute_common_bool(obj, attr_hash, val, update); 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; break;
case ATTR_TAG: case ATTR_TAG:
case ATTR_ACTION: case ATTR_ACTION:
case ATTR_SWIPE:
ret = attribute_common_tag(obj, attr_hash, payload, &text, update); ret = attribute_common_tag(obj, attr_hash, payload, &text, update);
break; break;
case ATTR_JSONL: case ATTR_JSONL:

View File

@ -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_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_tag(lv_obj_t* obj, const char* tag);
void my_obj_set_action(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_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_btnmatrix_map_clear(lv_obj_t* obj);
void my_msgbox_map_clear(lv_obj_t* obj); void my_msgbox_map_clear(lv_obj_t* obj);
void my_line_clear_points(lv_obj_t* obj); void my_line_clear_points(lv_obj_t* obj);

View File

@ -58,8 +58,67 @@ void my_obj_set_template(lv_obj_t* obj, const char* text)
LOG_WARNING(TAG_ATTR, "Failed to allocate memory!"); 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 // 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; 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 // 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; return (char*)obj->user_data.tag;
} }
*/
// the action data is stored as SERIALIZED JSON data // 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 hasp_ext_user_data_t* ext = (hasp_ext_user_data_t*)obj->user_data.ext;
if(obj->user_data.action) {
hasp_free(obj->user_data.action); // extended tag exists, free old tag
obj->user_data.action = NULL; if(ext && ext->action) {
hasp_free(ext->action);
ext->action = NULL;
} }
// new action is blank // new tag is blank
if(action == NULL || action[0] == '\0') return; 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 // create new action
{ {
StaticJsonDocument<512> doc; 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 // check if it is a proper JSON object
DeserializationError error = deserializeJson(doc, action /*, len*/); DeserializationError error = deserializeJson(doc, payload, len);
if(error != DeserializationError::Ok) doc.set(action); // use tag as-is if(error != DeserializationError::Ok) doc.set(payload); // use tag as-is
const size_t size = measureJson(doc) + 1; const size_t size = measureJson(doc) + 1;
if(char* str = (char*)hasp_malloc(size)) { if(char* str = (char*)hasp_malloc(size)) {
size_t len = serializeJson(doc, str, size); // tidy-up the json object size_t len = serializeJson(doc, str, size); // tidy-up the json object
obj->user_data.action = str; ext->action = str;
LOG_VERBOSE(TAG_ATTR, "new json: %s", 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 // the tag data is stored as SERIALIZED JSON data
const char* my_obj_get_action(lv_obj_t* obj) 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) lv_label_align_t my_textarea_get_text_align(lv_obj_t* ta)

View File

@ -42,6 +42,25 @@ void event_reset_last_value_sent()
last_value_sent = INT16_MIN; 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<JsonVariant>();
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 * Clean-up allocated memory before an object is deleted
* @param obj pointer to an object to clean-up * @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_tag(obj, (char*)NULL);
my_obj_set_action(obj, (char*)NULL); my_obj_set_action(obj, (char*)NULL);
my_obj_set_swipe(obj, (char*)NULL);
} }
/* ============================== Timer Event ============================ */ /* ============================== Timer Event ============================ */
@ -239,7 +259,7 @@ static void event_send_object_data(lv_obj_t* obj, const char* data)
if(!data) return; if(!data) return;
object_dispatch_state(pageid, objid, data); object_dispatch_state(pageid, objid, data);
} else { } 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) 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()); lv_gesture_dir_t dir = lv_indev_get_gesture_dir(lv_indev_get_act());
switch(dir) { switch(dir) {
case LV_GESTURE_DIR_LEFT: case LV_GESTURE_DIR_LEFT:
haspPages.next(LV_SCR_LOAD_ANIM_NONE, 500, 0); script_event_handler("left", swipe);
break; break;
case LV_GESTURE_DIR_RIGHT: case LV_GESTURE_DIR_RIGHT:
haspPages.prev(LV_SCR_LOAD_ANIM_NONE, 500, 0); script_event_handler("right", swipe);
break; break;
case LV_GESTURE_DIR_BOTTOM: case LV_GESTURE_DIR_BOTTOM:
haspPages.back(LV_SCR_LOAD_ANIM_NONE, 500, 0); script_event_handler("down", swipe);
break; break;
default: 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(last_value_sent == HASP_EVENT_LOST) return;
if(obj->user_data.action) { if(const char* action = my_obj_get_action(obj)) {
// if(last_value_sent == HASP_EVENT_UP || last_value_sent == HASP_EVENT_RELEASE) { char eventname[8];
// dispatch_text_line(obj->user_data.action, TAG_EVENT); Parser::get_event_name(last_value_sent, eventname, sizeof(eventname));
script_event_handler(eventname, action);
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<JsonVariant>();
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();
}
} else { } else {
char data[512]; char data[512];
{ {

View File

@ -14,6 +14,13 @@ const char FP_OBJID[] PROGMEM = "objid";
const char FP_PARENTID[] PROGMEM = "parentid"; const char FP_PARENTID[] PROGMEM = "parentid";
const char FP_GROUPID[] PROGMEM = "groupid"; const char FP_GROUPID[] PROGMEM = "groupid";
typedef struct
{
char* action;
char* swipe;
char* tag;
} hasp_ext_user_data_t;
typedef struct typedef struct
{ {
lv_obj_t* obj; lv_obj_t* obj;