diff --git a/src/hasp/hasp_attribute.cpp b/src/hasp/hasp_attribute.cpp index 286d3b2d..766ab807 100644 --- a/src/hasp/hasp_attribute.cpp +++ b/src/hasp/hasp_attribute.cpp @@ -6,318 +6,11 @@ #endif #include "hasplib.h" +#include "hasp_attribute_helper.h" LV_FONT_DECLARE(unscii_8_icon); extern const char** btnmatrix_default_map; // memory pointer to lvgl default btnmatrix map -#if 0 -static bool attribute_lookup_lv_property(uint16_t hash, uint8_t * prop) -{ - struct prop_hash_map - { - uint16_t hash; - uint8_t prop; - }; - - /* in order of prevalence */ - prop_hash_map props[] = { - {ATTR_PAD_TOP, LV_STYLE_PAD_TOP & LV_STYLE_PROP_ALL}, - {ATTR_BORDER_WIDTH, LV_STYLE_BORDER_WIDTH & LV_STYLE_PROP_ALL}, - {ATTR_OUTLINE_WIDTH, LV_STYLE_OUTLINE_WIDTH & LV_STYLE_PROP_ALL}, - {ATTR_VALUE_LETTER_SPACE, LV_STYLE_VALUE_LETTER_SPACE & LV_STYLE_PROP_ALL}, - {ATTR_TEXT_LETTER_SPACE, LV_STYLE_TEXT_LETTER_SPACE & LV_STYLE_PROP_ALL}, - {ATTR_LINE_WIDTH, LV_STYLE_LINE_WIDTH & LV_STYLE_PROP_ALL}, - {ATTR_TRANSITION_TIME, LV_STYLE_TRANSITION_TIME & LV_STYLE_PROP_ALL}, - {ATTR_SCALE_WIDTH, LV_STYLE_SCALE_WIDTH & LV_STYLE_PROP_ALL}, - {ATTR_RADIUS, LV_STYLE_RADIUS & LV_STYLE_PROP_ALL}, - {ATTR_PAD_BOTTOM, LV_STYLE_PAD_BOTTOM & LV_STYLE_PROP_ALL}, - {ATTR_BG_MAIN_STOP, LV_STYLE_BG_MAIN_STOP & LV_STYLE_PROP_ALL}, - {ATTR_BORDER_SIDE, LV_STYLE_BORDER_SIDE & LV_STYLE_PROP_ALL}, - {ATTR_OUTLINE_PAD, LV_STYLE_OUTLINE_PAD & LV_STYLE_PROP_ALL}, - {ATTR_PATTERN_REPEAT, LV_STYLE_PATTERN_REPEAT & LV_STYLE_PROP_ALL}, - {ATTR_VALUE_LINE_SPACE, LV_STYLE_VALUE_LINE_SPACE & LV_STYLE_PROP_ALL}, - {ATTR_TEXT_LINE_SPACE, LV_STYLE_TEXT_LINE_SPACE & LV_STYLE_PROP_ALL}, - {ATTR_TRANSITION_DELAY, LV_STYLE_TRANSITION_DELAY & LV_STYLE_PROP_ALL}, - {ATTR_SCALE_BORDER_WIDTH, LV_STYLE_SCALE_BORDER_WIDTH & LV_STYLE_PROP_ALL}, - {ATTR_CLIP_CORNER, LV_STYLE_CLIP_CORNER & LV_STYLE_PROP_ALL}, - {ATTR_PAD_LEFT, LV_STYLE_PAD_LEFT & LV_STYLE_PROP_ALL}, - {ATTR_BG_GRAD_STOP, LV_STYLE_BG_GRAD_STOP & LV_STYLE_PROP_ALL}, - {ATTR_TEXT_DECOR, LV_STYLE_TEXT_DECOR & LV_STYLE_PROP_ALL}, - {ATTR_LINE_DASH_WIDTH, LV_STYLE_LINE_DASH_WIDTH & LV_STYLE_PROP_ALL}, - {ATTR_TRANSITION_PROP_1, LV_STYLE_TRANSITION_PROP_1 & LV_STYLE_PROP_ALL}, - {ATTR_SCALE_END_BORDER_WIDTH, LV_STYLE_SCALE_END_BORDER_WIDTH & LV_STYLE_PROP_ALL}, - {ATTR_SIZE, LV_STYLE_SIZE & LV_STYLE_PROP_ALL}, - {ATTR_PAD_RIGHT, LV_STYLE_PAD_RIGHT & LV_STYLE_PROP_ALL}, - {ATTR_BG_GRAD_DIR, LV_STYLE_BG_GRAD_DIR & LV_STYLE_PROP_ALL}, - {ATTR_BORDER_POST, LV_STYLE_BORDER_POST & LV_STYLE_PROP_ALL}, - {ATTR_VALUE_OFS_X, LV_STYLE_VALUE_OFS_X & LV_STYLE_PROP_ALL}, - {ATTR_LINE_DASH_GAP, LV_STYLE_LINE_DASH_GAP & LV_STYLE_PROP_ALL}, - {ATTR_TRANSITION_PROP_2, LV_STYLE_TRANSITION_PROP_2 & LV_STYLE_PROP_ALL}, - {ATTR_SCALE_END_LINE_WIDTH, LV_STYLE_SCALE_END_LINE_WIDTH & LV_STYLE_PROP_ALL}, - {ATTR_TRANSFORM_WIDTH, LV_STYLE_TRANSFORM_WIDTH & LV_STYLE_PROP_ALL}, - {ATTR_PAD_INNER, LV_STYLE_PAD_INNER & LV_STYLE_PROP_ALL}, - {ATTR_VALUE_OFS_Y, LV_STYLE_VALUE_OFS_Y & LV_STYLE_PROP_ALL}, - {ATTR_LINE_ROUNDED, LV_STYLE_LINE_ROUNDED & LV_STYLE_PROP_ALL}, - {ATTR_TRANSITION_PROP_3, LV_STYLE_TRANSITION_PROP_3 & LV_STYLE_PROP_ALL}, - {ATTR_TRANSFORM_HEIGHT, LV_STYLE_TRANSFORM_HEIGHT & LV_STYLE_PROP_ALL}, - // {ATTR_MARGIN_TOP, LV_STYLE_MARGIN_TOP & LV_STYLE_PROP_ALL}, - {ATTR_VALUE_ALIGN, LV_STYLE_VALUE_ALIGN & LV_STYLE_PROP_ALL}, - {ATTR_TRANSITION_PROP_4, LV_STYLE_TRANSITION_PROP_4 & LV_STYLE_PROP_ALL}, - // {ATTR_TRANSFORM_ANGLE, LV_STYLE_TRANSFORM_ANGLE & LV_STYLE_PROP_ALL}, - // {ATTR_MARGIN_BOTTOM, LV_STYLE_MARGIN_BOTTOM & LV_STYLE_PROP_ALL}, - {ATTR_TRANSITION_PROP_5, LV_STYLE_TRANSITION_PROP_5 & LV_STYLE_PROP_ALL}, - // {ATTR_TRANSFORM_ZOOM, LV_STYLE_TRANSFORM_ZOOM & LV_STYLE_PROP_ALL}, - // {ATTR_MARGIN_LEFT, LV_STYLE_MARGIN_LEFT & LV_STYLE_PROP_ALL}, - {ATTR_TRANSITION_PROP_6, LV_STYLE_TRANSITION_PROP_6 & LV_STYLE_PROP_ALL}, - // {ATTR_MARGIN_RIGHT, LV_STYLE_MARGIN_RIGHT & LV_STYLE_PROP_ALL}, - {ATTR_BG_COLOR, LV_STYLE_BG_COLOR & LV_STYLE_PROP_ALL}, - {ATTR_BORDER_COLOR, LV_STYLE_BORDER_COLOR & LV_STYLE_PROP_ALL}, - {ATTR_OUTLINE_COLOR, LV_STYLE_OUTLINE_COLOR & LV_STYLE_PROP_ALL}, - {ATTR_PATTERN_RECOLOR, LV_STYLE_PATTERN_RECOLOR & LV_STYLE_PROP_ALL}, - {ATTR_VALUE_COLOR, LV_STYLE_VALUE_COLOR & LV_STYLE_PROP_ALL}, - {ATTR_TEXT_COLOR, LV_STYLE_TEXT_COLOR & LV_STYLE_PROP_ALL}, - {ATTR_LINE_COLOR, LV_STYLE_LINE_COLOR & LV_STYLE_PROP_ALL}, - {ATTR_IMAGE_RECOLOR, LV_STYLE_IMAGE_RECOLOR & LV_STYLE_PROP_ALL}, - {ATTR_SCALE_GRAD_COLOR, LV_STYLE_SCALE_GRAD_COLOR & LV_STYLE_PROP_ALL}, - {ATTR_BG_GRAD_COLOR, LV_STYLE_BG_GRAD_COLOR & LV_STYLE_PROP_ALL}, - {ATTR_TEXT_SEL_COLOR, LV_STYLE_TEXT_SEL_COLOR & LV_STYLE_PROP_ALL}, - {ATTR_SCALE_END_COLOR, LV_STYLE_SCALE_END_COLOR & LV_STYLE_PROP_ALL}, - // {ATTR_TEXT_SEL_BG_COLOR, LV_STYLE_TEXT_SEL_BG_COLOR & LV_STYLE_PROP_ALL}, - {ATTR_OPA_SCALE, LV_STYLE_OPA_SCALE & LV_STYLE_PROP_ALL}, - {ATTR_BG_OPA, LV_STYLE_BG_OPA & LV_STYLE_PROP_ALL}, - {ATTR_BORDER_OPA, LV_STYLE_BORDER_OPA & LV_STYLE_PROP_ALL}, - {ATTR_OUTLINE_OPA, LV_STYLE_OUTLINE_OPA & LV_STYLE_PROP_ALL}, - {ATTR_PATTERN_OPA, LV_STYLE_PATTERN_OPA & LV_STYLE_PROP_ALL}, - {ATTR_VALUE_OPA, LV_STYLE_VALUE_OPA & LV_STYLE_PROP_ALL}, - {ATTR_TEXT_OPA, LV_STYLE_TEXT_OPA & LV_STYLE_PROP_ALL}, - {ATTR_LINE_OPA, LV_STYLE_LINE_OPA & LV_STYLE_PROP_ALL}, - {ATTR_IMAGE_OPA, LV_STYLE_IMAGE_OPA & LV_STYLE_PROP_ALL}, - {ATTR_PATTERN_RECOLOR_OPA, LV_STYLE_PATTERN_RECOLOR_OPA & LV_STYLE_PROP_ALL}, - {ATTR_IMAGE_RECOLOR_OPA, LV_STYLE_IMAGE_RECOLOR_OPA & LV_STYLE_PROP_ALL}, - {ATTR_PATTERN_IMAGE, LV_STYLE_PATTERN_IMAGE & LV_STYLE_PROP_ALL}, - {ATTR_VALUE_FONT, LV_STYLE_VALUE_FONT & LV_STYLE_PROP_ALL}, - {ATTR_TEXT_FONT, LV_STYLE_TEXT_FONT & LV_STYLE_PROP_ALL}, - {ATTR_TRANSITION_PATH, LV_STYLE_TRANSITION_PATH & LV_STYLE_PROP_ALL}, - {ATTR_VALUE_STR, LV_STYLE_VALUE_STR & LV_STYLE_PROP_ALL}, - -#if LV_USE_SHADOW - {ATTR_SHADOW_WIDTH, LV_STYLE_SHADOW_WIDTH & LV_STYLE_PROP_ALL}, - {ATTR_SHADOW_OFS_X, LV_STYLE_SHADOW_OFS_X & LV_STYLE_PROP_ALL}, - {ATTR_SHADOW_OFS_Y, LV_STYLE_SHADOW_OFS_Y & LV_STYLE_PROP_ALL}, - {ATTR_SHADOW_SPREAD, LV_STYLE_SHADOW_SPREAD & LV_STYLE_PROP_ALL}, - {ATTR_SHADOW_COLOR, LV_STYLE_SHADOW_COLOR & LV_STYLE_PROP_ALL}, - {ATTR_SHADOW_OPA, LV_STYLE_SHADOW_OPA & LV_STYLE_PROP_ALL}, -#endif - -#if LV_USE_BLEND_MODES && LV_USE_SHADOW - {ATTR_SHADOW_BLEND_MODE, LV_STYLE_SHADOW_BLEND_MODE & LV_STYLE_PROP_ALL}, -#endif - -#if LV_USE_BLEND_MODES - {ATTR_BG_BLEND_MODE, LV_STYLE_BG_BLEND_MODE & LV_STYLE_PROP_ALL}, - {ATTR_PATTERN_BLEND_MODE, LV_STYLE_PATTERN_BLEND_MODE & LV_STYLE_PROP_ALL}, - {ATTR_IMAGE_BLEND_MODE, LV_STYLE_IMAGE_BLEND_MODE & LV_STYLE_PROP_ALL}, - {ATTR_LINE_BLEND_MODE, LV_STYLE_LINE_BLEND_MODE & LV_STYLE_PROP_ALL}, - {ATTR_BORDER_BLEND_MODE, LV_STYLE_BORDER_BLEND_MODE & LV_STYLE_PROP_ALL}, - {ATTR_OUTLINE_BLEND_MODE, LV_STYLE_OUTLINE_BLEND_MODE & LV_STYLE_PROP_ALL}, - {ATTR_VALUE_BLEND_MODE, LV_STYLE_VALUE_BLEND_MODE & LV_STYLE_PROP_ALL}, - {ATTR_TEXT_BLEND_MODE, LV_STYLE_TEXT_BLEND_MODE & LV_STYLE_PROP_ALL}, -#endif - }; - - for(uint32_t i = 0; i < sizeof(props) / sizeof(props[0]); i++) { - if(props[i].hash == hash) { - *prop = props[1].prop; - LOG_WARNING(TAG_ATTR, F("%d found and has propery %d"), hash, props[i].prop); - return true; - } - } - LOG_ERROR(TAG_ATTR, F("%d has no property id"), hash); - return false; -} - -static bool attribute_get_lv_property() -{ - lv_res_t res _lv_style_get_int(const lv_style_t * style, lv_style_property_t prop, void * res); - return res == LV_RES_OK -} - -static bool attribute_set_lv_property() -{ - lv_res_t res _lv_style_get_int(const lv_style_t * style, lv_style_property_t prop, void * res); - return res == LV_RES_OK -} - -static bool attribute_update_lv_property(lv_obj_t * obj, const char * attr_p, uint16_t attr_hash, const char * payload, - bool update) -{ - uint8_t prop; - uint8_t prop_type; - - // convert sdbm hash to lv property number - if(!attribute_lookup_lv_property(attr_hash, &prop)) return false; - - // find the parameter type for this property - prop_type = prop & 0xF; - - if(prop_type < LV_STYLE_ID_COLOR) { - if(update) { - _lv_obj_set_style_local_int(obj, part, prop | (state << LV_STYLE_STATE_POS), atoi(payload)) - } else { - attr_out_str(obj, attr_p, lv_obj_get_style_value_str(obj, part)); - } - } else if(prop_type < LV_STYLE_ID_OPA) { - } else if(prop_type < LV_STYLE_ID_PTR) { - } else { - } -} -#endif - -const char* my_tabview_get_tab_name(const lv_obj_t* tabview, uint16_t id) -{ - if(id >= lv_tabview_get_tab_count(tabview)) return NULL; - - lv_tabview_ext_t* ext = (lv_tabview_ext_t*)lv_obj_get_ext_attr(tabview); - return ext->tab_name_ptr[id]; -} - -// OK - this function is missing in lvgl -static uint8_t my_roller_get_visible_row_count(lv_obj_t* roller) -{ - const lv_font_t* font = lv_obj_get_style_text_font(roller, LV_ROLLER_PART_BG); - lv_style_int_t line_space = lv_obj_get_style_text_line_space(roller, LV_ROLLER_PART_BG); - lv_coord_t h = lv_obj_get_height(roller); - - if((lv_font_get_line_height(font) + line_space) != 0) - return (uint8_t)(h / (lv_font_get_line_height(font) + line_space)); - else - return 0; -} - -// OK - this function is not const in lvgl and doesn't return 0 -static uint16_t my_msgbox_stop_auto_close(const lv_obj_t* obj) -{ - lv_msgbox_stop_auto_close((lv_obj_t*)obj); - return 0; -} - -// OK - this function is not const in lvgl -static bool my_arc_get_adjustable(const lv_obj_t* arc) -{ - return lv_arc_get_adjustable((lv_obj_t*)arc); -} - -// OK - we need to change the event handler too -static void my_arc_set_adjustable(lv_obj_t* arc, bool toggle) -{ - lv_arc_set_adjustable(arc, toggle); - lv_obj_set_event_cb(arc, toggle ? slider_event_handler : generic_event_handler); -} - -// OK - this function is missing in lvgl -static inline uint16_t my_arc_get_rotation(lv_obj_t* arc) -{ - lv_arc_ext_t* ext = (lv_arc_ext_t*)lv_obj_get_ext_attr(arc); - return ext->rotation_angle; -} - -// OK - this function is missing in lvgl -static inline int16_t my_chart_get_min_value(lv_obj_t* chart) -{ - lv_chart_ext_t* ext = (lv_chart_ext_t*)lv_obj_get_ext_attr(chart); - return ext->ymin[LV_CHART_AXIS_PRIMARY_Y]; -} - -// OK - this function is missing in lvgl -static inline int16_t my_chart_get_max_value(lv_obj_t* chart) -{ - lv_chart_ext_t* ext = (lv_chart_ext_t*)lv_obj_get_ext_attr(chart); - return ext->ymax[LV_CHART_AXIS_PRIMARY_Y]; -} - -lv_chart_series_t* my_chart_get_series(lv_obj_t* chart, uint8_t ser_num) -{ - lv_chart_ext_t* ext = (lv_chart_ext_t*)lv_obj_get_ext_attr(chart); - lv_chart_series_t* ser = (lv_chart_series_t*)_lv_ll_get_tail(&ext->series_ll); - while(ser_num > 0 && ser) { - ser = (lv_chart_series_t*)_lv_ll_get_prev(&ext->series_ll, ser); - ser_num--; - } - return ser; -} - -/** - * Set a new value_str for an object. Memory will be allocated to store the text by the object. - * @param obj pointer to a object - * @param text '\0' terminated character string. NULL to refresh with the current text. - */ -void my_obj_set_value_str_text(lv_obj_t* obj, uint8_t part, lv_state_t state, const char* text) -{ - // LOG_VERBOSE(TAG_ATTR, F("%s %d"), __FILE__, __LINE__); - - const void* value_str_p = lv_obj_get_style_value_str(obj, part); - lv_obj_invalidate(obj); - - if(text == NULL || text[0] == 0) { - // LOG_VERBOSE(TAG_ATTR, F("%s %d"), __FILE__, __LINE__); - lv_obj_set_style_local_value_str(obj, part, state, NULL); - lv_mem_free(value_str_p); - // LOG_VERBOSE(TAG_ATTR, F("%s %d"), __FILE__, __LINE__); - return; - } - - LV_ASSERT_STR(text); - - if(value_str_p == NULL) { - /*Get the size of the text*/ - size_t len = strlen(text) + 1; - - /*Allocate space for the new text*/ - // LOG_VERBOSE(TAG_ATTR, F("%s %d"), __FILE__, __LINE__); - value_str_p = (char*)lv_mem_alloc(len); - LV_ASSERT_MEM(value_str_p); - if(value_str_p == NULL) return; - - // LOG_VERBOSE(TAG_ATTR, F("%s %d"), __FILE__, __LINE__); - strncpy((char*)value_str_p, text, len); - lv_obj_set_style_local_value_str(obj, part, state, (char*)value_str_p); - // LOG_VERBOSE(TAG_ATTR, F("%s %d"), __FILE__, __LINE__); - return; - } - - // lv_obj_set_style_local_value_str(obj, part, state, str_p); - - if(value_str_p == text) { - /*If set its own text then reallocate it (maybe its size changed)*/ - LOG_DEBUG(TAG_ATTR, "%s %d", __FILE__, __LINE__); - return; // don't touch the data - - // value_str_p = lv_mem_realloc(value_str_p, strlen(text) + 1); - - // LV_ASSERT_MEM(value_str_p); - // if(value_str_p == NULL) return; - } else { - /*Free the old text*/ - if(value_str_p != NULL) { - // LOG_DEBUG(TAG_ATTR, F("%s %d"), __FILE__, __LINE__); - lv_mem_free(value_str_p); - value_str_p = NULL; - // LOG_DEBUG(TAG_ATTR, F("%s %d"), __FILE__, __LINE__); - } - - /*Get the size of the text*/ - size_t len = strlen(text) + 1; - - /*Allocate space for the new text*/ - value_str_p = lv_mem_alloc(len); - LV_ASSERT_MEM(value_str_p); - if(value_str_p != NULL) strcpy((char*)value_str_p, text); - lv_obj_set_style_local_value_str(obj, part, state, (char*)value_str_p); - } - - // LOG_VERBOSE(TAG_ATTR, F("%s %d"), __FILE__, __LINE__); -} - void my_btnmatrix_map_clear(lv_obj_t* obj) { lv_btnmatrix_ext_t* ext = (lv_btnmatrix_ext_t*)lv_obj_get_ext_attr(obj); @@ -349,76 +42,6 @@ void my_msgbox_map_clear(lv_obj_t* obj) if(ext && ext->btnm) my_btnmatrix_map_clear(ext->btnm); // Clear the button map if it exists yet } -/* -static void my_btnmatrix_map_create(lv_obj_t* obj, const char* payload) -{ - // const char** map_p = lv_btnmatrix_get_map_array(obj); - - // Create new map - // Reserve memory for JsonDocument - size_t maxsize = (128u * ((strlen(payload) / 128) + 1)) + 256; - DynamicJsonDocument map_doc(maxsize); - DeserializationError jsonError = deserializeJson(map_doc, payload); - - if(jsonError) { // Couldn't parse incoming JSON payload - dispatch_json_error(TAG_ATTR, jsonError); - return; - } - - JsonArray arr = map_doc.as(); // Parse payload - - size_t tot_len = sizeof(char*) * (arr.size() + 1); - const char** map_data_str = (const char**)lv_mem_alloc(tot_len); - if(map_data_str == NULL) { - LOG_ERROR(TAG_ATTR, F("Out of memory while creating button map")); - return; - } - memset(map_data_str, 0, tot_len); - - // Create buffer - tot_len = 0; - for(JsonVariant btn : arr) { - // tot_len += btn.as().length() + 1; - tot_len += strlen(btn.as()) + 1; - } - tot_len++; // trailing '\0' - LOG_VERBOSE(TAG_ATTR, F("Array Size = %d, Map Length = %d"), arr.size(), tot_len); - - char* buffer_addr = (char*)lv_mem_alloc(tot_len); - if(buffer_addr == NULL) { - lv_mem_free(map_data_str); - LOG_ERROR(TAG_ATTR, F("Out of memory while creating button map")); - return; - } - memset(buffer_addr, 0, tot_len); // Important, last index needs to be 0 => empty string "" - - // Point of no return, destroy & free the previous map / - LOG_VERBOSE(TAG_ATTR, F("%s %d map addr: %x"), __FILE__, __LINE__, map_data_str); - my_btnmatrix_map_clear(obj); // Free previous map - - // Fill buffer - size_t index = 0; - size_t pos = 0; - LOG_VERBOSE(TAG_ATTR, F("%s %d lbl addr: %x"), __FILE__, __LINE__, buffer_addr); - for(JsonVariant btn : arr) { - // size_t len = btn.as().length() + 1; - size_t len = strlen(btn.as()) + 1; - LOG_VERBOSE(TAG_ATTR, F(D_BULLET "Adding button: %s (%d bytes) %x"), btn.as(), len, - buffer_addr + pos); - // LOG_VERBOSE(TAG_ATTR, F(D_BULLET "Adding button: %s (%d bytes) %x"), btn.as().c_str(), len, - // buffer_addr + pos); - memccpy(buffer_addr + pos, btn.as(), 0, len); // Copy the label text into the buffer - // memccpy(buffer_addr + pos, btn.as().c_str(), 0, len); // Copy the label text into the buffer - map_data_str[index++] = buffer_addr + pos; // save pointer to the label in the array - pos += len; - } - map_data_str[index] = buffer_addr + pos; // save pointer to the last \0 byte - - LOG_VERBOSE(TAG_ATTR, F("%s %d"), __FILE__, __LINE__); - lv_btnmatrix_set_map(obj, map_data_str); - LOG_VERBOSE(TAG_ATTR, F("%s %d"), __FILE__, __LINE__); -}*/ - // Create new btnmatrix button map from json array const char** my_map_create(const char* payload) { @@ -559,16 +182,6 @@ static void line_set_points(lv_obj_t* obj, const char* payload) // TO DO : free & destroy previous pointlist! } -// OK -static inline lv_color_t haspLogColor(lv_color_t color) -{ - // uint8_t r = (LV_COLOR_GET_R(color) * 263 + 7) >> 5; - // uint8_t g = (LV_COLOR_GET_G(color) * 259 + 3) >> 6; - // uint8_t b = (LV_COLOR_GET_B(color) * 263 + 7) >> 5; - // LOG_VERBOSE(TAG_ATTR,F("Color: R%u G%u B%u"), r, g, b); - return color; -} - static lv_font_t* haspPayloadToFont(const char* payload) { uint8_t var = atoi(payload); @@ -613,26 +226,6 @@ static lv_font_t* haspPayloadToFont(const char* payload) } } -static void gauge_format_10(lv_obj_t* gauge, char* buf, int bufsize, int32_t value) -{ - snprintf(buf, bufsize, PSTR("%d"), value / 10); -} - -static void gauge_format_100(lv_obj_t* gauge, char* buf, int bufsize, int32_t value) -{ - snprintf(buf, bufsize, PSTR("%d"), value / 100); -} - -static void gauge_format_1k(lv_obj_t* gauge, char* buf, int bufsize, int32_t value) -{ - snprintf(buf, bufsize, PSTR("%d"), value / 1000); -} - -static void gauge_format_10k(lv_obj_t* gauge, char* buf, int bufsize, int32_t value) -{ - snprintf(buf, bufsize, PSTR("%d"), value / 10000); -} - static void hasp_process_label_long_mode(lv_obj_t* obj, const char* payload, bool update) { if(update) { @@ -660,93 +253,6 @@ static void hasp_process_label_long_mode(lv_obj_t* obj, const char* payload, boo } } -// OK -lv_obj_t* FindButtonLabel(lv_obj_t* btn) -{ - if(btn) { - lv_obj_t* label = lv_obj_get_child_back(btn, NULL); - if(label) { - if(obj_check_type(label, LV_HASP_LABEL)) { - return label; - } - - } else { - LOG_ERROR(TAG_ATTR, F("FindButtonLabel NULL Pointer encountered")); - } - } else { - LOG_WARNING(TAG_ATTR, F("Button not defined")); - } - return NULL; -} - -// OK -static inline void my_btn_set_text(lv_obj_t* obj, const char* value) -{ - lv_obj_t* label = FindButtonLabel(obj); - if(label) { - lv_label_set_text(label, value); - } -} - -// OK - lvgl does not return a const char * -static const char* my_label_get_text(const lv_obj_t* label) -{ - return lv_label_get_text(label); // library does not return const -} - -static void my_label_set_text(lv_obj_t* label, const char* text) -{ - if(text[0] == '%') { - uint16_t hash = Parser::get_sdbm(text); - size_t len = strlen(text); - const char* static_text; - - switch(hash) { - - case 10125: - static_text = haspDevice.get_hostname(); - break; - default: - lv_label_set_text(label, text); - return; - } - - lv_label_set_text_static(label, static_text); - } else { - lv_label_set_text(label, text); - } -} - -// OK -static const char* my_btn_get_text(const lv_obj_t* obj) -{ - if(!obj) { - LOG_WARNING(TAG_ATTR, F("Button not defined")); - return NULL; - } - - lv_obj_t* label = lv_obj_get_child_back(obj, NULL); - if(label) { -#if 1 - if(obj_check_type(label, LV_HASP_LABEL)) return lv_label_get_text(label); - -#else - lv_obj_type_t list; - lv_obj_get_type(label, &list); - - if(obj_check_type(list.type[0], LV_HASP_LABEL)) { - text = lv_label_get_text(label); - return true; - } -#endif - - } else { - LOG_WARNING(TAG_ATTR, F("my_btn_get_text NULL Pointer encountered")); - } - - return NULL; -} - static void hasp_attribute_get_part_state(lv_obj_t* obj, const char* attr_in, char* attr_out, uint8_t& part, uint8_t& state) { @@ -847,80 +353,12 @@ static void hasp_attribute_get_part_state(lv_obj_t* obj, const char* attr_in, ch return; } - // if(obj_check_type(obj, LV_HASP_LMETER)) { + // if(obj_check_type(obj, LV_HASP_LINEMETER)) { // state = LV_STATE_DEFAULT; // return; // } } -void my_tabview_set_text(lv_obj_t* obj, const char* payload) -{ - uint16_t id = lv_tabview_get_tab_act(obj); - - if(id < lv_tabview_get_tab_count(obj)) { - lv_tabview_set_tab_name(obj, id, (char*)payload); - } -} - -const char* my_tabview_get_text(const lv_obj_t* obj) -{ - uint16_t id = lv_tabview_get_tab_act(obj); - - if(id < lv_tabview_get_tab_count(obj)) { - return my_tabview_get_tab_name(obj, id); - } else { - return NULL; - } -} - -void my_tab_set_text(lv_obj_t* obj, const char* payload) -{ - lv_obj_t* content = lv_obj_get_parent(obj->parent); // 2 levels up - if(!content) return LOG_WARNING(TAG_ATTR, F("content not found")); - - lv_obj_t* tabview = lv_obj_get_parent(content); // 3rd level up - if(!tabview) return LOG_WARNING(TAG_ATTR, F("Tabview not found")); - - if(!obj_check_type(tabview, LV_HASP_TABVIEW)) - return LOG_WARNING(TAG_ATTR, F("LV_HASP_TABVIEW not found %d"), obj_get_type(tabview)); - - for(uint16_t id = 0; id < lv_tabview_get_tab_count(tabview); id++) { - if(obj == lv_tabview_get_tab(tabview, id)) { - lv_tabview_set_tab_name(tabview, id, (char*)payload); - return; - } - } - LOG_WARNING(TAG_ATTR, F("Tab not found")); -} - -const char* my_tab_get_text(const lv_obj_t* obj) -{ - lv_obj_t* content = lv_obj_get_parent(obj->parent); // 2 levels up - if(!content) { - LOG_WARNING(TAG_ATTR, F("content not found")); - return NULL; - } - - lv_obj_t* tabview = lv_obj_get_parent(content); // 3rd level up - if(!tabview) { - LOG_WARNING(TAG_ATTR, F("Tabview not found")); - return NULL; - } - - if(!obj_check_type(tabview, LV_HASP_TABVIEW)) { - LOG_WARNING(TAG_ATTR, F("LV_HASP_TABVIEW not found %d"), obj_get_type(tabview)); - return NULL; - } - - for(uint16_t id = 0; id < lv_tabview_get_tab_count(tabview); id++) { - if(obj == lv_tabview_get_tab(tabview, id)) { - return my_tabview_get_tab_name(tabview, id); - } - } - LOG_WARNING(TAG_ATTR, F("Tab not found")); - return NULL; -} - /** * Change or Retrieve the value of a local attribute of an object PART * @param obj lv_obj_t*: the object to get/set the attribute @@ -1302,96 +740,87 @@ static void hasp_local_style_attr(lv_obj_t* obj, const char* attr_p, uint16_t at result = false; } -static bool hasp_process_arc_attribute(lv_obj_t* obj, const char* attr, uint16_t attr_hash, const char* payload, - bool update) +static hasp_attribute_type_t hasp_process_arc_attribute(lv_obj_t* obj, uint16_t attr_hash, int32_t& val, bool update) { - uint16_t val = atoi(payload); - // We already know it's a arc object switch(attr_hash) { case ATTR_TYPE: - (update) ? lv_arc_set_type(obj, val % 3) : attr_out_int(obj, attr, lv_arc_get_type(obj)); - return true; + if(update) + lv_arc_set_type(obj, val % 3); + else + val = lv_arc_get_type(obj); + break; + + default: + return hasp_attribute_type_t::ATTR_NOT_FOUND; } - return false; + return hasp_attribute_type_t::ATTR_TYPE_INT; } -static bool hasp_process_lmeter_attribute(lv_obj_t* obj, const char* attr, uint16_t attr_hash, const char* payload, - bool update) +static hasp_attribute_type_t hasp_process_lmeter_attribute(lv_obj_t* obj, uint16_t attr_hash, int32_t& val, bool update) { - uint16_t val = atoi(payload); - // We already know it's a linemeter object uint16_t line_count = lv_linemeter_get_line_count(obj); uint16_t angle = lv_linemeter_get_scale_angle(obj); switch(attr_hash) { case ATTR_TYPE: - (update) ? lv_linemeter_set_mirror(obj, val != 0) : attr_out_int(obj, attr, lv_linemeter_get_mirror(obj)); - return true; - - case ATTR_ROTATION: - (update) ? lv_linemeter_set_angle_offset(obj, val) - : attr_out_int(obj, attr, lv_linemeter_get_angle_offset(obj)); - return true; + if(update) + lv_linemeter_set_mirror(obj, !!val); + else + val = lv_linemeter_get_mirror(obj); + break; case ATTR_LINE_COUNT: - (update) ? lv_linemeter_set_scale(obj, angle, val) : attr_out_int(obj, attr, line_count); - return true; + if(update) + lv_linemeter_set_scale(obj, angle, val); + else + val = line_count; + break; case ATTR_ANGLE: - (update) ? lv_linemeter_set_scale(obj, val, line_count) : attr_out_int(obj, attr, angle); - return true; + if(update) + lv_linemeter_set_scale(obj, val, line_count); + else + val = angle; + break; + + default: + return hasp_attribute_type_t::ATTR_NOT_FOUND; } - return false; + return hasp_attribute_type_t::ATTR_TYPE_INT; } -static bool hasp_process_dropdown_attribute(lv_obj_t* obj, const char* attr, uint16_t attr_hash, const char* payload, - bool update) +static hasp_attribute_type_t special_attribute_direction(lv_obj_t* obj, uint16_t attr_hash, int32_t& val, bool update) { - int16_t intval = atoi(payload); - uint16_t val = atoi(payload); + switch(obj_get_type(obj)) { - // We already know it's a gauge object - switch(attr_hash) { - case ATTR_DIRECTION: - (update) ? lv_dropdown_set_dir(obj, intval) : attr_out_int(obj, attr, lv_dropdown_get_dir(obj)); - return true; + case LV_HASP_DROPDOWN: + if(update) + lv_dropdown_set_dir(obj, (lv_dropdown_dir_t)val); + else + val = lv_dropdown_get_dir(obj); + break; - case ATTR_SYMBOL: - (update) ? lv_dropdown_set_symbol(obj, payload) : attr_out_str(obj, attr, lv_dropdown_get_symbol(obj)); - return true; + case LV_HASP_SPINNER: + if(update) + lv_spinner_set_dir(obj, (lv_spinner_dir_t)val); + else + val = lv_spinner_get_dir(obj); + break; - case ATTR_OPEN: - lv_dropdown_open(obj); - return true; - - case ATTR_CLOSE: - lv_dropdown_close(obj); - return true; - - case ATTR_MAX_HEIGHT: - (update) ? lv_dropdown_set_max_height(obj, intval) - : attr_out_int(obj, attr, lv_dropdown_get_max_height(obj)); - return true; - - case ATTR_SHOW_SELECTED: - (update) ? lv_dropdown_set_show_selected(obj, val) - : attr_out_int(obj, attr, lv_dropdown_get_show_selected(obj)); - return true; + default: + return hasp_attribute_type_t::ATTR_NOT_FOUND; } - return false; + return hasp_attribute_type_t::ATTR_TYPE_INT; } -static bool hasp_process_gauge_attribute(lv_obj_t* obj, const char* attr, uint16_t attr_hash, const char* payload, - bool update) +static hasp_attribute_type_t hasp_process_gauge_attribute(lv_obj_t* obj, uint16_t attr_hash, int32_t& val, bool update) { // We already know it's a gauge object - int16_t intval = atoi(payload); - uint16_t val = atoi(payload); uint8_t label_count = lv_gauge_get_label_count(obj); uint16_t line_count = lv_gauge_get_line_count(obj); @@ -1399,25 +828,32 @@ static bool hasp_process_gauge_attribute(lv_obj_t* obj, const char* attr, uint16 switch(attr_hash) { case ATTR_CRITICAL_VALUE: - (update) ? lv_gauge_set_critical_value(obj, intval) - : attr_out_int(obj, attr, lv_gauge_get_critical_value(obj)); - return true; // found + if(update) + lv_gauge_set_critical_value(obj, val); + else + val = lv_gauge_get_critical_value(obj); + break; case ATTR_ANGLE: - (update) ? lv_gauge_set_scale(obj, val, line_count, label_count) : attr_out_int(obj, attr, angle); - return true; // found + if(update) + lv_gauge_set_scale(obj, val, line_count, label_count); + else + val = angle; + break; case ATTR_LINE_COUNT: - (update) ? lv_gauge_set_scale(obj, angle, val, label_count) : attr_out_int(obj, attr, line_count); - return true; // found + if(update) + lv_gauge_set_scale(obj, angle, val, label_count); + else + val = line_count; + break; case ATTR_LABEL_COUNT: - (update) ? lv_gauge_set_scale(obj, angle, line_count, val) : attr_out_int(obj, attr, label_count); - return true; // found - - case ATTR_ROTATION: - (update) ? lv_gauge_set_angle_offset(obj, val) : attr_out_int(obj, attr, lv_gauge_get_angle_offset(obj)); - return true; // found + if(update) + lv_gauge_set_scale(obj, angle, line_count, val); + else + val = label_count; + break; case ATTR_FORMAT: if(update) { @@ -1439,36 +875,52 @@ static bool hasp_process_gauge_attribute(lv_obj_t* obj, const char* attr, uint16 lv_gauge_set_formatter_cb(obj, NULL); } } - return true; // found + break; + + default: + return hasp_attribute_type_t::ATTR_NOT_FOUND; } - return false; + return hasp_attribute_type_t::ATTR_TYPE_INT; } // ##################### Common Attributes ######################################################## -static bool hasp_process_page_attributes(lv_obj_t* obj, const char* attr_p, uint16_t attr_hash, uint8_t val, - bool update) +static hasp_attribute_type_t specific_page_attribute(lv_obj_t* obj, uint16_t attr_hash, int32_t& val, bool update) { + if(!obj_check_type(obj, LV_HASP_PAGE)) return hasp_attribute_type_t::ATTR_NOT_FOUND; + uint8_t pageid; if(haspPages.get_id(obj, &pageid)) { switch(attr_hash) { case ATTR_NEXT: - update ? haspPages.set_next(pageid, val) : attr_out_int(obj, attr_p, haspPages.get_next(pageid)); - return true; + if(update) + haspPages.set_next(pageid, (uint8_t)val); + else + val = haspPages.get_next(pageid); + break; case ATTR_PREV: - update ? haspPages.set_prev(pageid, val) : attr_out_int(obj, attr_p, haspPages.get_prev(pageid)); - return true; + if(update) + haspPages.set_prev(pageid, (uint8_t)val); + else + val = haspPages.get_prev(pageid); + break; + + case ATTR_BACK: + if(update) + haspPages.set_back(pageid, (uint8_t)val); + else + val = haspPages.get_back(pageid); + break; - // case ATTR_BACK: default: - update ? haspPages.set_back(pageid, val) : attr_out_int(obj, attr_p, haspPages.get_back(pageid)); - return true; + return hasp_attribute_type_t::ATTR_NOT_FOUND; } } - return false; + + return hasp_attribute_type_t::ATTR_TYPE_INT; } template @@ -1490,11 +942,105 @@ static inline bool do_attribute(T& list, lv_obj_t* obj, uint16_t attr_hash, int3 return false; } -static bool hasp_process_obj_attribute_text(lv_obj_t* obj, const char* attr, const char* payload, bool update) +static hasp_attribute_type_t special_attribute_src(lv_obj_t* obj, const char* payload, char** text, bool update) +{ + if(!obj_check_type(obj, LV_HASP_IMAGE)) return ATTR_NOT_FOUND; + + if(update) { + lv_img_cache_invalidate_src(lv_img_get_src(obj)); + lv_img_set_src(obj, payload); + } else { + switch(lv_img_src_get_type(obj)) { + case LV_IMG_SRC_FILE: + *text = (char*)lv_img_get_file_name(obj); + case LV_IMG_SRC_SYMBOL: + *text = (char*)lv_img_get_src(obj); + } + } + return ATTR_TYPE_STR; +} + +static hasp_attribute_type_t attribute_common_align(lv_obj_t* obj, const char* attr, const char* payload, char** text, + bool update) +{ + lv_label_align_t val; + + if(update) { + if(!strcasecmp_P(payload, PSTR("left"))) { + val = LV_LABEL_ALIGN_LEFT; + } else if(!strcasecmp_P(payload, PSTR("right"))) { + val = LV_LABEL_ALIGN_RIGHT; + } else if(!strcasecmp_P(payload, PSTR("center"))) { + val = LV_LABEL_ALIGN_CENTER; + } else if(!strcasecmp_P(payload, PSTR("auto"))) { + val = LV_LABEL_ALIGN_AUTO; + } else { + return ATTR_TYPE_ALIGN_INVALID; + } + } + + switch(obj_get_type(obj)) { + case LV_HASP_BUTTON: { + lv_obj_t* label = FindButtonLabel(obj); + if(label) { + if(update) + lv_label_set_align(label, val); + else + val = lv_label_get_align(label); + } else { + return ATTR_NOT_FOUND; // not found + } + break; + } + case LV_HASP_BTNMATRIX: + if(update) + lv_btnmatrix_set_align(obj, val); + else + val = lv_btnmatrix_get_align(obj); + break; + + case LV_HASP_LABEL: + if(update) + lv_label_set_align(obj, val); + else + val = lv_label_get_align(obj); + break; + + case LV_HASP_ROLLER: + if(update) + lv_roller_set_align(obj, val); + else + val = lv_roller_get_align(obj); + break; + + default: + return ATTR_NOT_FOUND; // not found + } + + // return values + switch(val) { + case LV_LABEL_ALIGN_AUTO: + strcpy_P(*text, PSTR("auto")); + break; + case LV_LABEL_ALIGN_CENTER: + strcpy_P(*text, PSTR("center")); + break; + case LV_LABEL_ALIGN_RIGHT: + strcpy_P(*text, PSTR("right")); + break; + default: + strcpy_P(*text, PSTR("left")); + } + + return ATTR_TYPE_STR; +} + +static hasp_attribute_type_t attribute_common_text(lv_obj_t* obj, const char* attr, const char* payload, char** text, + bool update) { uint8_t obj_type = obj_get_type(obj); - hasp_attr_update_char_const_t text[] = { + hasp_attr_update_char_const_t list[] = { {LV_HASP_BUTTON, ATTR_TEXT, my_btn_set_text, my_btn_get_text}, {LV_HASP_LABEL, ATTR_TEXT, my_label_set_text, my_label_get_text}, {LV_HASP_CHECKBOX, ATTR_TEXT, lv_checkbox_set_text, lv_checkbox_get_text}, @@ -1506,14 +1052,14 @@ static bool hasp_process_obj_attribute_text(lv_obj_t* obj, const char* attr, con {LV_HASP_MSGBOX, ATTR_TEXT, lv_msgbox_set_text, lv_msgbox_get_text} }; - for(int i = 0; i < sizeof(text) / sizeof(text[0]); i++) { - if(obj_type == text[i].obj_type) { - if(update) { - text[i].set(obj, payload); - } else { - attr_out_str(obj, attr, text[i].get(obj)); - } - return true; + for(int i = 0; i < sizeof(list) / sizeof(list[0]); i++) { + if(obj_type == list[i].obj_type) { + if(update) + list[i].set(obj, payload); + else + *text = (char*)list[i].get(obj); + + return hasp_attribute_type_t::ATTR_TYPE_STR; } } @@ -1522,39 +1068,60 @@ static bool hasp_process_obj_attribute_text(lv_obj_t* obj, const char* attr, con // {LV_HASP_ROLLER, set_text_not_implemented, my_roller_get_text}, switch(obj_get_type(obj)) { case LV_HASP_DROPDOWN: { - char buffer[128]; - lv_dropdown_get_selected_str(obj, buffer, sizeof(buffer)); - attr_out_str(obj, attr, buffer); - return true; - } - case LV_HASP_ROLLER: { - char buffer[128]; - lv_roller_get_selected_str(obj, buffer, sizeof(buffer)); - attr_out_str(obj, attr, buffer); - return true; - } - default: + lv_dropdown_get_selected_str(obj, *text, 128); + if(update) return hasp_attribute_type_t::ATTR_TYPE_STR_READONLY; break; + } + + case LV_HASP_ROLLER: { + lv_roller_get_selected_str(obj, *text, 128); + if(update) return hasp_attribute_type_t::ATTR_TYPE_STR_READONLY; + break; + } + + default: + return hasp_attribute_type_t::ATTR_NOT_FOUND; } - return false; + + return hasp_attribute_type_t::ATTR_TYPE_STR; } -static bool generic_bool_attribute(lv_obj_t* obj, uint16_t attr_hash, int32_t& val, bool update) +static hasp_attribute_type_t specific_bool_attribute(lv_obj_t* obj, uint16_t attr_hash, int32_t& val, bool update) { { // bool hasp_attr_update_bool_const_t list[] = { {LV_HASP_ARC, ATTR_ADJUSTABLE, my_arc_set_adjustable, my_arc_get_adjustable}, {LV_HASP_BTNMATRIX, ATTR_ONE_CHECK, lv_btnmatrix_set_one_check, lv_btnmatrix_get_one_check}, {LV_HASP_IMAGE, ATTR_AUTO_SIZE, lv_img_set_auto_size, lv_img_get_auto_size}}; - if(do_attribute(list, obj, attr_hash, val, update)) return true; + if(do_attribute(list, obj, attr_hash, val, update)) return ATTR_TYPE_BOOL; } - return false; + + { // bool + hasp_attr_update_bool_t list[] = { + {LV_HASP_DROPDOWN, ATTR_SHOW_SELECTED, lv_dropdown_set_show_selected, lv_dropdown_get_show_selected}}; + if(do_attribute(list, obj, attr_hash, val, update)) return ATTR_TYPE_BOOL; + } + + return ATTR_NOT_FOUND; } -static bool generic_int_attribute(lv_obj_t* obj, uint16_t attr_hash, int32_t& val, bool update) +static hasp_attribute_type_t specific_coord_attribute(lv_obj_t* obj, uint16_t attr_hash, int32_t& val, bool update) { - { // unint16_t - hasp_attr_update16_const_t list[] = { + { // lv_coord_t + hasp_attr_update_lv_coord_t list[] = { + {LV_HASP_IMAGE, ATTR_OFFSET_X, lv_img_set_offset_x, lv_img_get_offset_x}, + {LV_HASP_IMAGE, ATTR_OFFSET_Y, lv_img_set_offset_y, lv_img_get_offset_y}, + {LV_HASP_DROPDOWN, ATTR_MAX_HEIGHT, lv_dropdown_set_max_height, my_dropdown_get_max_height}}; + if(do_attribute(list, obj, attr_hash, val, update)) return ATTR_TYPE_INT; + } + + return ATTR_NOT_FOUND; +} + +static hasp_attribute_type_t specific_int_attribute(lv_obj_t* obj, uint16_t attr_hash, int32_t& val, bool update) +{ + { // uint16_t + hasp_attr_update_uint16_const_t list[] = { {LV_HASP_MSGBOX, ATTR_AUTO_CLOSE, lv_msgbox_start_auto_close, my_msgbox_stop_auto_close}, {LV_HASP_SPINNER, ATTR_SPEED, lv_spinner_set_spin_time, lv_spinner_get_spin_time}, {LV_HASP_BAR, ATTR_ANIM_TIME, lv_bar_set_anim_time, lv_bar_get_anim_time}, @@ -1566,35 +1133,64 @@ static bool generic_int_attribute(lv_obj_t* obj, uint16_t attr_hash, int32_t& va {LV_HASP_TABVIEW, ATTR_ANIM_TIME, lv_tabview_set_anim_time, lv_tabview_get_anim_time}, {LV_HASP_WINDOW, ATTR_ANIM_TIME, lv_win_set_anim_time, lv_win_get_anim_time}, {LV_HASP_LABEL, ATTR_ANIM_SPEED, lv_label_set_anim_speed, lv_label_get_anim_speed}}; - if(do_attribute(list, obj, attr_hash, val, update)) return true; + if(do_attribute(list, obj, attr_hash, val, update)) return ATTR_TYPE_INT; } - { // lv_anim_value_t - hasp_attr_update_lv_anim_value_const_t list[] = { - {LV_HASP_SPINNER, ATTR_ANGLE, lv_spinner_set_arc_length, lv_spinner_get_arc_length}}; - if(do_attribute(list, obj, attr_hash, val, update)) return true; - } - - // {LV_HASP_SPINNER, ATTR_THICKNESS, lv_spinner_set_arc_length, lv_spinner_get_arc_length} - - // { // uint8_t - // hasp_attr_update8_const_t list[] = {{LV_HASP_SPINNER, ATTR_DIRECTION, lv_spinner_set_dir, - // lv_spinner_get_dir}}; if(do_attribute(list, obj, attr_hash, val, update)) return true; - // } - - { // unint16_t, but getter is not const - hasp_attr_update16_t list[] = { + { // uint16_t, but getter is not const + hasp_attr_update_uint16_t list[] = { {LV_HASP_ARC, ATTR_ROTATION, lv_arc_set_rotation, my_arc_get_rotation}, {LV_HASP_ARC, ATTR_START_ANGLE, lv_arc_set_bg_start_angle, lv_arc_get_bg_angle_start}, {LV_HASP_ARC, ATTR_END_ANGLE, lv_arc_set_bg_end_angle, lv_arc_get_bg_angle_end}, {LV_HASP_ARC, ATTR_START_ANGLE1, lv_arc_set_start_angle, lv_arc_get_angle_start}, {LV_HASP_ARC, ATTR_END_ANGLE1, lv_arc_set_end_angle, lv_arc_get_angle_end}, + {LV_HASP_LINEMETER, ATTR_ROTATION, lv_linemeter_set_angle_offset, lv_linemeter_get_angle_offset}, + {LV_HASP_GAUGE, ATTR_ROTATION, lv_gauge_set_angle_offset, lv_gauge_get_angle_offset}, {LV_HASP_SLIDER, ATTR_ANIM_TIME, lv_slider_set_anim_time, lv_slider_get_anim_time}, + {LV_HASP_TABLE, ATTR_COLS, lv_table_set_col_cnt, lv_table_get_col_cnt}, + {LV_HASP_TABLE, ATTR_ROWS, lv_table_set_row_cnt, lv_table_get_row_cnt}, {LV_HASP_TILEVIEW, ATTR_ANIM_TIME, lv_tileview_set_anim_time, lv_tileview_get_anim_time}}; - if(do_attribute(list, obj, attr_hash, val, update)) return true; + if(do_attribute(list, obj, attr_hash, val, update)) return ATTR_TYPE_INT; } - return false; + { // lv_anim_value_t + hasp_attr_update_lv_anim_value_const_t list[] = { + {LV_HASP_SPINNER, ATTR_ANGLE, lv_spinner_set_arc_length, lv_spinner_get_arc_length}}; + if(do_attribute(list, obj, attr_hash, val, update)) return ATTR_TYPE_INT; + } + + { // int16_t + hasp_attr_update_int16_const_t list[] = { + {LV_HASP_BAR, ATTR_START_VALUE, my_bar_set_start_value, lv_bar_get_start_value}, + {LV_HASP_SLIDER, ATTR_START_VALUE, my_slider_set_left_value, lv_slider_get_left_value}}; + if(do_attribute(list, obj, attr_hash, val, update)) return ATTR_TYPE_INT; + } + + { // uint8_t + hasp_attr_update_uint8_const_t list[] = { + {LV_HASP_ROLLER, ATTR_ROWS, lv_roller_set_visible_row_count, my_roller_get_visible_row_count}}; + if(do_attribute(list, obj, attr_hash, val, update)) return ATTR_TYPE_INT; + } + + if(obj_check_type(obj, LV_HASP_TABVIEW)) { + switch(attr_hash) { + case ATTR_COUNT: + val = lv_tabview_get_tab_count(obj); + if(update) + return ATTR_TYPE_INT_READONLY; + else + return ATTR_TYPE_INT; + + case ATTR_BTN_POS: + if(update) { + lv_tabview_set_btns_pos(obj, val); + } else { + val = lv_tabview_get_btns_pos(obj); + } + return ATTR_TYPE_INT; + } + } + + return ATTR_NOT_FOUND; } static bool my_obj_get_range(lv_obj_t* obj, int32_t& min, int32_t& max) @@ -1617,7 +1213,7 @@ static bool my_obj_get_range(lv_obj_t* obj, int32_t& min, int32_t& max) max = 255; break; - case LV_HASP_LMETER: + case LV_HASP_LINEMETER: min = lv_linemeter_get_min_value(obj); max = lv_linemeter_get_max_value(obj); break; @@ -1663,16 +1259,87 @@ static bool my_obj_get_range(lv_obj_t* obj, int32_t& min, int32_t& max) return true; } +static hasp_attribute_type_t attribute_common_val(lv_obj_t* obj, int32_t& val, bool update) +{ + if(obj_check_type(obj, LV_HASP_BUTTON)) { + if(lv_btn_get_checkable(obj)) { + if(update) { + if(val) + lv_obj_add_state(obj, LV_STATE_CHECKED); + else + lv_obj_clear_state(obj, LV_STATE_CHECKED); + } else { + val = lv_obj_get_state(obj, LV_BTN_PART_MAIN) & LV_STATE_CHECKED; + } + } else { + return hasp_attribute_type_t::ATTR_NOT_FOUND; // not checkable + } + } else if(obj_check_type(obj, LV_HASP_CHECKBOX)) { + if(update) + lv_checkbox_set_checked(obj, !!val); + else + val = lv_checkbox_is_checked(obj); + } else if(obj_check_type(obj, LV_HASP_SWITCH)) { + if(update) + !val ? lv_switch_off(obj, LV_ANIM_ON) : lv_switch_on(obj, LV_ANIM_ON); + else + val = lv_switch_get_state(obj); + } else if(obj_check_type(obj, LV_HASP_DROPDOWN)) { + lv_dropdown_set_selected(obj, (uint16_t)val); + } else if(obj_check_type(obj, LV_HASP_LINEMETER)) { + if(update) + lv_linemeter_set_value(obj, val); + else + val = lv_linemeter_get_value(obj); + } else if(obj_check_type(obj, LV_HASP_SLIDER)) { + if(update) + lv_slider_set_value(obj, val, LV_ANIM_ON); + else + val = lv_slider_get_value(obj); + } else if(obj_check_type(obj, LV_HASP_LED)) { + if(update) + lv_led_set_bright(obj, (uint8_t)val); + else + val = lv_led_get_bright(obj); + } else if(obj_check_type(obj, LV_HASP_ARC)) { + if(update) + lv_arc_set_value(obj, val); + else + val = lv_arc_get_value(obj); + } else if(obj_check_type(obj, LV_HASP_GAUGE)) { + if(update) + lv_gauge_set_value(obj, 0, val); + else + val = lv_gauge_get_value(obj, 0); + } else if(obj_check_type(obj, LV_HASP_ROLLER)) { + lv_roller_set_selected(obj, (uint16_t)val, LV_ANIM_ON); + } else if(obj_check_type(obj, LV_HASP_BAR)) { + if(update) + lv_bar_set_value(obj, val, LV_ANIM_ON); + else + val = lv_bar_get_value(obj); + } else if(obj_check_type(obj, LV_HASP_TABVIEW)) { + if(update) + lv_tabview_set_tab_act(obj, val, LV_ANIM_ON); + else + val = lv_tabview_get_tab_act(obj); + } else { + return hasp_attribute_type_t::ATTR_NOT_FOUND; // not found + } + + return hasp_attribute_type_t::ATTR_TYPE_INT; // found +} + bool attribute_set_normalized_value(lv_obj_t* obj, hasp_update_value_t& value) { if(value.min == value.max) return false; // would cause divide by zero error + int32_t val; int32_t min; int32_t max; if(!my_obj_get_range(obj, min, max)) return false; // range could not be determined // Limit the value between min and max, adjust if power = 0 - int16_t val; if(value.power == 0 || value.val <= value.min) { val = value.min; } else if(value.val >= value.max) { @@ -1687,110 +1354,317 @@ bool attribute_set_normalized_value(lv_obj_t* obj, hasp_update_value_t& value) val = map(val, value.min, value.max, min, max); } - hasp_process_obj_attribute_val(obj, NULL, val, !!val, true); + attribute_common_val(obj, val, true); return true; } -bool hasp_process_obj_attribute_val(lv_obj_t* obj, const char* attr, int16_t intval, bool boolval, bool update) +static hasp_attribute_type_t attribute_common_range(lv_obj_t* obj, int32_t& val, bool update, bool set_min, + bool set_max) { - if(obj_check_type(obj, LV_HASP_BUTTON)) { - if(lv_btn_get_checkable(obj)) { - if(update) { - if(intval) - lv_obj_add_state(obj, LV_STATE_CHECKED); - else - lv_obj_clear_state(obj, LV_STATE_CHECKED); - } else { - attr_out_int(obj, attr, lv_obj_get_state(obj, LV_BTN_PART_MAIN) & LV_STATE_CHECKED); - } - } else { - return false; // not checkable - } - } else if(obj_check_type(obj, LV_HASP_CHECKBOX)) { - update ? lv_checkbox_set_checked(obj, boolval) : attr_out_int(obj, attr, lv_checkbox_is_checked(obj)); - } else if(obj_check_type(obj, LV_HASP_SWITCH)) { - if(update) - boolval ? lv_switch_on(obj, LV_ANIM_ON) : lv_switch_off(obj, LV_ANIM_ON); - else - attr_out_int(obj, attr, lv_switch_get_state(obj)); - } else if(obj_check_type(obj, LV_HASP_DROPDOWN)) { - lv_dropdown_set_selected(obj, (uint16_t)intval); - } else if(obj_check_type(obj, LV_HASP_LMETER)) { - update ? lv_linemeter_set_value(obj, intval) : attr_out_int(obj, attr, lv_linemeter_get_value(obj)); - } else if(obj_check_type(obj, LV_HASP_SLIDER)) { - update ? lv_slider_set_value(obj, intval, LV_ANIM_ON) : attr_out_int(obj, attr, lv_slider_get_value(obj)); - } else if(obj_check_type(obj, LV_HASP_LED)) { - update ? lv_led_set_bright(obj, (uint8_t)intval) : attr_out_int(obj, attr, lv_led_get_bright(obj)); - } else if(obj_check_type(obj, LV_HASP_ARC)) { - update ? lv_arc_set_value(obj, intval) : attr_out_int(obj, attr, lv_arc_get_value(obj)); - } else if(obj_check_type(obj, LV_HASP_GAUGE)) { - update ? lv_gauge_set_value(obj, 0, intval) : attr_out_int(obj, attr, lv_gauge_get_value(obj, 0)); - } else if(obj_check_type(obj, LV_HASP_ROLLER)) { - lv_roller_set_selected(obj, (uint16_t)intval, LV_ANIM_ON); - } else if(obj_check_type(obj, LV_HASP_BAR)) { - update ? lv_bar_set_value(obj, intval, LV_ANIM_ON) : attr_out_int(obj, attr, lv_bar_get_value(obj)); - } else if(obj_check_type(obj, LV_HASP_TABVIEW)) { - update ? lv_tabview_set_tab_act(obj, intval, LV_ANIM_ON) : attr_out_int(obj, attr, lv_tabview_get_tab_act(obj)); - } else { - return false; - } - - return true; -} - -static bool hasp_process_obj_attribute_range(lv_obj_t* obj, const char* attr, const char* payload, bool update, - bool set_min, bool set_max) -{ - int16_t val = atoi(payload); - int32_t val32 = strtol(payload, nullptr, DEC); - int32_t min; int32_t max; - if(!my_obj_get_range(obj, min, max)) return false; + if(!my_obj_get_range(obj, min, max)) return hasp_attribute_type_t::ATTR_RANGE_ERROR; - if(obj_check_type(obj, LV_HASP_SLIDER)) { - if(update && (set_min ? val : min) == (set_max ? val : max)) return false; // prevent setting min=max - update ? lv_slider_set_range(obj, set_min ? val : min, set_max ? val : max) - : attr_out_int(obj, attr, set_min ? min : max); - return true; + switch(obj_get_type(obj)) { + case LV_HASP_SLIDER: + if(update && (set_min ? val : min) == (set_max ? val : max)) + return hasp_attribute_type_t::ATTR_RANGE_ERROR; // prevent setting min=max + if(update) + lv_slider_set_range(obj, set_min ? val : min, set_max ? val : max); + else + val = set_min ? min : max; + break; + + case LV_HASP_GAUGE: + if(update && (set_min ? val : min) == (set_max ? val : max)) + return hasp_attribute_type_t::ATTR_RANGE_ERROR; // prevent setting min=max + if(update) + lv_gauge_set_range(obj, set_min ? val : min, set_max ? val : max); + else + val = set_min ? min : max; + break; + + case LV_HASP_ARC: + if(update && (set_min ? val : min) == (set_max ? val : max)) + return hasp_attribute_type_t::ATTR_RANGE_ERROR; // prevent setting min=max + if(update) + lv_arc_set_range(obj, set_min ? val : min, set_max ? val : max); + else + val = set_min ? min : max; + break; + + case LV_HASP_BAR: + if(update && (set_min ? val : min) == (set_max ? val : max)) + return hasp_attribute_type_t::ATTR_RANGE_ERROR; // prevent setting min=max + if(update) + lv_bar_set_range(obj, set_min ? val : min, set_max ? val : max); + else + val = set_min ? min : max; + break; + + case LV_HASP_LINEMETER: + if(update && (set_min ? val : min) == (set_max ? val : max)) + return hasp_attribute_type_t::ATTR_RANGE_ERROR; // prevent setting min=max + if(update) + lv_linemeter_set_range(obj, set_min ? val : min, set_max ? val : max); + else + val = set_min ? min : max; + break; + + case LV_HASP_CHART: + if(update && (set_min ? val : min) == (set_max ? val : max)) + return hasp_attribute_type_t::ATTR_RANGE_ERROR; // prevent setting min=max + if(update) + lv_chart_set_range(obj, set_min ? val : min, set_max ? val : max); + else + val = set_min ? min : max; + break; + + default: + return hasp_attribute_type_t::ATTR_NOT_FOUND; } - if(obj_check_type(obj, LV_HASP_GAUGE)) { - if(update && (set_min ? val32 : min) == (set_max ? val32 : max)) return false; // prevent setting min=max - update ? lv_gauge_set_range(obj, set_min ? val32 : min, set_max ? val32 : max) - : attr_out_int(obj, attr, set_min ? min : max); - return true; + return hasp_attribute_type_t::ATTR_TYPE_INT; +} + +// ##################### Default Attributes ######################################################## + +/** + * Execute the method of an object + * @param obj lv_obj_t*: the object to get/set the attribute + * @param attr_hash uint16_t: the hashed attribute value + * @param attr char*: the attribute name (without leading ".") + * @param payload char*: the parameters for the method + * @note setting a value won't return anything, getting will dispatch the value + */ +static hasp_attribute_type_t attribute_common_method(lv_obj_t* obj, uint16_t attr_hash, const char* attr, + const char* payload) +{ + switch(attr_hash) { + case ATTR_DELETE: + if(!lv_obj_get_parent(obj)) return hasp_attribute_type_t::ATTR_TYPE_METHOD_INVALID_FOR_PAGE; + lv_obj_del_async(obj); + break; + + case ATTR_CLEAR: + lv_obj_clean(obj); + break; + + case ATTR_TO_FRONT: + if(!lv_obj_get_parent(obj)) return hasp_attribute_type_t::ATTR_TYPE_METHOD_INVALID_FOR_PAGE; + lv_obj_move_foreground(obj); + break; + + case ATTR_TO_BACK: + if(!lv_obj_get_parent(obj)) return hasp_attribute_type_t::ATTR_TYPE_METHOD_INVALID_FOR_PAGE; + lv_obj_move_background(obj); + break; + + case ATTR_OPEN: + case ATTR_CLOSE: + if(!obj_check_type(obj, LV_HASP_DROPDOWN)) return hasp_attribute_type_t::ATTR_NOT_FOUND; + if(attr_hash == ATTR_OPEN) + lv_dropdown_open(obj); + else + lv_dropdown_open(obj); + break; + + default: + return hasp_attribute_type_t::ATTR_NOT_FOUND; // attribute_not found } - if(obj_check_type(obj, LV_HASP_ARC)) { - if(update && (set_min ? val : min) == (set_max ? val : max)) return false; // prevent setting min=max - update ? lv_arc_set_range(obj, set_min ? val : min, set_max ? val : max) - : attr_out_int(obj, attr, set_min ? min : max); - return true; + return hasp_attribute_type_t::ATTR_TYPE_METHOD_OK; +} + +/** + * Change or Retrieve the value of the attribute of an object + * @param obj lv_obj_t*: the object to get/set the attribute + * @param attr_hash uint16_t: the hashed attribute to get/set + * @param val uint32_t: the new value of the attribute + * @param update bool: change/set the value if true, dispatch/get value if false + * @note setting a value won't return anything, getting will dispatch the value + */ +static hasp_attribute_type_t attribute_common_int(lv_obj_t* obj, uint16_t attr_hash, int32_t& val, bool update) +{ + switch(attr_hash) { + case ATTR_ID: + if(update) + obj->user_data.id = (uint8_t)val; + else + val = obj->user_data.id; + break; // attribute_found + + case ATTR_GROUPID: + if(update) + obj->user_data.groupid = (uint8_t)val; + else + 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_OBJID: + val = obj->user_data.objid; + if(update && val != obj->user_data.objid) hasp_attribute_type_t::ATTR_TYPE_INT_READONLY; + break; // attribute_found + + case ATTR_X: + if(update) + lv_obj_set_x(obj, val); + else + val = lv_obj_get_x(obj); + break; // attribute_found + + case ATTR_Y: + if(update) + lv_obj_set_y(obj, val); + else + val = lv_obj_get_y(obj); + break; // attribute_found + + case ATTR_W: + if(update) { + lv_obj_set_width(obj, val); + if(obj_check_type(obj, LV_HASP_CPICKER)) { +#if LVGL_VERSION_MAJOR == 7 + lv_cpicker_set_type(obj, lv_obj_get_width(obj) == lv_obj_get_height(obj) ? LV_CPICKER_TYPE_DISC + : LV_CPICKER_TYPE_RECT); +#endif + } + } else { + val = lv_obj_get_width(obj); + } + break; // attribute_found + + case ATTR_H: + if(update) { + lv_obj_set_height(obj, val); + if(obj_check_type(obj, LV_HASP_CPICKER)) { +#if LVGL_VERSION_MAJOR == 7 + lv_cpicker_set_type(obj, lv_obj_get_width(obj) == lv_obj_get_height(obj) ? LV_CPICKER_TYPE_DISC + : LV_CPICKER_TYPE_RECT); +#endif + } + } else { + val = lv_obj_get_height(obj); + } + break; // attribute_found + + case ATTR_OPACITY: + if(update) + lv_obj_set_style_local_opa_scale(obj, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, val); + else + val = lv_obj_get_style_opa_scale(obj, LV_OBJ_PART_MAIN); + break; // attribute_found + + case ATTR_EXT_CLICK_H: + if(update) + lv_obj_set_ext_click_area(obj, val, val, lv_obj_get_ext_click_pad_top(obj), + lv_obj_get_ext_click_pad_bottom(obj)); + else + val = lv_obj_get_ext_click_pad_left(obj); + break; // attribute_found + + case ATTR_EXT_CLICK_V: + if(update) + lv_obj_set_ext_click_area(obj, lv_obj_get_ext_click_pad_left(obj), lv_obj_get_ext_click_pad_right(obj), + val, val); + else + val = lv_obj_get_ext_click_pad_top(obj); + break; // attribute_found + + default: + return hasp_attribute_type_t::ATTR_NOT_FOUND; // attribute_not found } - if(obj_check_type(obj, LV_HASP_BAR)) { - if(update && (set_min ? val : min) == (set_max ? val : max)) return false; // prevent setting min=max - update ? lv_bar_set_range(obj, set_min ? val : min, set_max ? val : max) - : attr_out_int(obj, attr, set_min ? min : max); - return true; + return hasp_attribute_type_t::ATTR_TYPE_INT; +} + +/** + * Change or Retrieve the value of the attribute of an object + * @param obj lv_obj_t*: the object to get/set the attribute + * @param attr_hash uint16_t: the hashed attribute to get/set + * @param val uint32_t: the new value of the attribute + * @param update bool: change/set the value if true, dispatch/get value if false + * @note setting a value won't return anything, getting will dispatch the value + */ +static hasp_attribute_type_t attribute_common_bool(lv_obj_t* obj, uint16_t attr_hash, int32_t& val, bool update) +{ + switch(attr_hash) { + case ATTR_VIS: + if(update) + lv_obj_set_hidden(obj, !val); + else + val = !lv_obj_get_hidden(obj); + break; // attribute_found + + case ATTR_HIDDEN: + if(update) + lv_obj_set_hidden(obj, !!val); + else + val = lv_obj_get_hidden(obj); + break; // attribute_found + + case ATTR_CLICK: + if(update) + lv_obj_set_click(obj, !!val); + else + val = lv_obj_get_click(obj); + break; // attribute_found + + case ATTR_ENABLED: + if(update) + if(!!val) + lv_obj_clear_state(obj, LV_STATE_DISABLED); + else + lv_obj_add_state(obj, LV_STATE_DISABLED); + else + 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_TOGGLE: + switch(obj_get_type(obj)) { + case LV_HASP_BUTTON: + if(update) { + lv_btn_set_checkable(obj, !!val); + lv_obj_set_event_cb(obj, !!val ? toggle_event_handler : generic_event_handler); + } else { + val = lv_btn_get_checkable(obj); + } + break; // attribute_found + case LV_HASP_BTNMATRIX: + if(update) { + if(val) { + lv_btnmatrix_set_btn_ctrl_all(obj, LV_BTNMATRIX_CTRL_CHECKABLE); + } else { + lv_btnmatrix_clear_btn_ctrl_all(obj, LV_BTNMATRIX_CTRL_CHECKABLE); + lv_btnmatrix_clear_btn_ctrl_all(obj, LV_BTNMATRIX_CTRL_CHECK_STATE); + } + } else { + val = lv_btn_get_checkable(obj); + } + break; // attribute_found + default: + return hasp_attribute_type_t::ATTR_NOT_FOUND; // attribute_not found + } + + default: + return hasp_attribute_type_t::ATTR_NOT_FOUND; // attribute_not found } - if(obj_check_type(obj, LV_HASP_LMETER)) { - if(update && (set_min ? val32 : min) == (set_max ? val32 : max)) return false; // prevent setting min=max - update ? lv_linemeter_set_range(obj, set_min ? val32 : min, set_max ? val32 : max) - : attr_out_int(obj, attr, set_min ? min : max); - return true; - } - - if(obj_check_type(obj, LV_HASP_CHART)) { - if(update && (set_min ? val : min) == (set_max ? val : max)) return false; // prevent setting min=max - update ? lv_chart_set_range(obj, set_min ? val : min, set_max ? val : max) - : attr_out_int(obj, attr, set_min ? min : max); - return true; - } - - return false; + return hasp_attribute_type_t::ATTR_TYPE_BOOL; } // ##################### Default Attributes ######################################################## @@ -1803,195 +1677,12 @@ static bool hasp_process_obj_attribute_range(lv_obj_t* obj, const char* attr, co * @param update bool: change/set the value if true, dispatch/get value if false * @note setting a value won't return anything, getting will dispatch the value */ -void hasp_process_obj_attribute(lv_obj_t* obj, const char* attr_p, const char* payload, bool update) +void old_process_obj_attribute(lv_obj_t* obj, const char* attr_p, const char* payload, bool update) { - // unsigned long start = millis(); - if(!obj) { - LOG_WARNING(TAG_ATTR, F(D_OBJECT_UNKNOWN)); - return; - } - - char* attr = (char*)attr_p; - // if(*attr == '.') attr++; // strip leading '.' - - uint16_t attr_hash = Parser::get_sdbm(attr); - int32_t val = atoi(payload); + uint16_t attr_hash; /* 16-bit Hash Lookup Table */ switch(attr_hash) { - case ATTR_ID: - update ? (void)(obj->user_data.id = (uint8_t)val) : attr_out_int(obj, attr, obj->user_data.id); - return; // attribute_found - - case ATTR_GROUPID: - update ? (void)(obj->user_data.groupid = (uint8_t)val) : attr_out_int(obj, attr, obj->user_data.groupid); - return; // attribute_found - - case ATTR_ACTION: - update ? (void)(obj->user_data.actionid = Parser::get_action_id(payload)) - : attr_out_int(obj, attr, obj->user_data.actionid); - return; // attribute_found - - case ATTR_TRANSITION: - update ? (void)(obj->user_data.transitionid = (uint8_t)val) - : attr_out_int(obj, attr, obj->user_data.transitionid); - return; // attribute_found - - case ATTR_OBJ: - if(update) LOG_WARNING(TAG_ATTR, F(D_ATTRIBUTE_READ_ONLY), attr_p); - attr_out_str(obj, attr, obj_get_type_name(obj)); - return; // attribute_found - - case ATTR_OBJID: - if(update && val != obj->user_data.objid) LOG_WARNING(TAG_ATTR, F(D_ATTRIBUTE_READ_ONLY), attr_p); - attr_out_int(obj, attr, obj->user_data.objid); - return; // attribute_found - - case ATTR_X: - update ? lv_obj_set_x(obj, val) : attr_out_int(obj, attr, lv_obj_get_x(obj)); - return; // attribute_found - - case ATTR_Y: - update ? lv_obj_set_y(obj, val) : attr_out_int(obj, attr, lv_obj_get_y(obj)); - return; // attribute_found - - case ATTR_W: - if(update) { - lv_obj_set_width(obj, val); - if(obj_check_type(obj, LV_HASP_CPICKER)) { -#if LVGL_VERSION_MAJOR == 7 - lv_cpicker_set_type(obj, lv_obj_get_width(obj) == lv_obj_get_height(obj) ? LV_CPICKER_TYPE_DISC - : LV_CPICKER_TYPE_RECT); -#endif - } - } else { - attr_out_int(obj, attr, lv_obj_get_width(obj)); - } - return; // attribute_found - - case ATTR_H: - if(update) { - lv_obj_set_height(obj, val); - if(obj_check_type(obj, LV_HASP_CPICKER)) { -#if LVGL_VERSION_MAJOR == 7 - lv_cpicker_set_type(obj, lv_obj_get_width(obj) == lv_obj_get_height(obj) ? LV_CPICKER_TYPE_DISC - : LV_CPICKER_TYPE_RECT); -#endif - } - } else { - attr_out_int(obj, attr, lv_obj_get_height(obj)); - } - return; // attribute_found - - case ATTR_VIS: - update ? lv_obj_set_hidden(obj, !Parser::is_true(payload)) - : attr_out_int(obj, attr, !lv_obj_get_hidden(obj)); - return; // attribute_found - - case ATTR_HIDDEN: - update ? lv_obj_set_hidden(obj, Parser::is_true(payload)) : attr_out_int(obj, attr, lv_obj_get_hidden(obj)); - return; // attribute_found - - case ATTR_TXT: // TODO: remove - LOG_WARNING(TAG_HASP, F("txt property is obsolete, use text instead")); - case ATTR_TEXT: - hasp_process_obj_attribute_text(obj, attr, payload, update); - return; // attribute_found - - case ATTR_VAL: - if(hasp_process_obj_attribute_val(obj, attr, atoi(payload), Parser::is_true(payload), update)) - return; // attribute_found - break; // not found - - case ATTR_MIN: - if(hasp_process_obj_attribute_range(obj, attr, payload, update, true, false)) return; // attribute_found - break; - - case ATTR_MAX: - if(hasp_process_obj_attribute_range(obj, attr, payload, update, false, true)) return; // attribute_found - break; - - case ATTR_OPACITY: - update ? lv_obj_set_style_local_opa_scale(obj, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, val) - : attr_out_int(obj, attr, lv_obj_get_style_opa_scale(obj, LV_OBJ_PART_MAIN)); - return; // attribute_found - - case ATTR_CLICK: - update ? lv_obj_set_click(obj, Parser::is_true(payload)) : attr_out_int(obj, attr, lv_obj_get_click(obj)); - return; // attribute_found - - case ATTR_EXT_CLICK_H: - update ? lv_obj_set_ext_click_area(obj, val, val, lv_obj_get_ext_click_pad_top(obj), - lv_obj_get_ext_click_pad_bottom(obj)) - : attr_out_int(obj, attr, lv_obj_get_ext_click_pad_left(obj)); - return; - - case ATTR_EXT_CLICK_V: - update ? lv_obj_set_ext_click_area(obj, lv_obj_get_ext_click_pad_left(obj), - lv_obj_get_ext_click_pad_right(obj), val, val) - : attr_out_int(obj, attr, lv_obj_get_ext_click_pad_top(obj)); - return; - - case ATTR_ENABLED: - if(update) - if(Parser::is_true(payload)) - lv_obj_clear_state(obj, LV_STATE_DISABLED); - else - lv_obj_add_state(obj, LV_STATE_DISABLED); - else - attr_out_int(obj, attr, !(lv_obj_get_state(obj, LV_BTN_PART_MAIN) & LV_STATE_DISABLED)); - break; // attribute_found - - case ATTR_SWIPE: - update ? (void)(obj->user_data.swipeid = Parser::is_true(payload) % 16) - : attr_out_int(obj, attr, obj->user_data.swipeid); - return; // attribute_found - - case ATTR_ROWS: - switch(obj_get_type(obj)) { - case LV_HASP_ROLLER: - update ? lv_roller_set_visible_row_count(obj, (uint8_t)val) - : attr_out_int(obj, attr, my_roller_get_visible_row_count(obj)); - return; // attribute_found - case LV_HASP_TABLE: - update ? lv_table_set_row_cnt(obj, (uint8_t)val) - : attr_out_int(obj, attr, lv_table_get_row_cnt(obj)); - return; // attribute_found - default: - break; // not found - } - break; // not found - - case ATTR_COLS: - if(obj_check_type(obj, LV_HASP_TABLE)) { - update ? lv_table_set_col_cnt(obj, (uint8_t)val) : attr_out_int(obj, attr, lv_table_get_col_cnt(obj)); - return; // attribute_found - } - break; // not found - - case ATTR_ALIGN: - switch(obj_get_type(obj)) { - case LV_HASP_BUTTON: { - lv_obj_t* label = FindButtonLabel(obj); - if(label) { - update ? lv_label_set_align(label, val) : attr_out_int(obj, attr, lv_label_get_align(label)); - return; // attribute_found - } - break; // not found - } - case LV_HASP_BTNMATRIX: - update ? lv_btnmatrix_set_align(obj, val) : attr_out_int(obj, attr, lv_btnmatrix_get_align(obj)); - return; // attribute_found - case LV_HASP_LABEL: - update ? lv_label_set_align(obj, val) : attr_out_int(obj, attr, lv_label_get_align(obj)); - return; // attribute_found - case LV_HASP_ROLLER: - update ? lv_roller_set_align(obj, val) : attr_out_int(obj, attr, lv_roller_get_align(obj)); - return; // attribute_found - default: - break; // not found - } - break; // not found case ATTR_MODE: switch(obj_get_type(obj)) { @@ -2012,36 +1703,7 @@ void hasp_process_obj_attribute(lv_obj_t* obj, const char* attr_p, const char* p (lv_roller_mode_t)Parser::is_true(payload)); } else { lv_roller_ext_t* ext = (lv_roller_ext_t*)lv_obj_get_ext_attr(obj); - attr_out_int(obj, attr, ext->mode); - } - return; // attribute_found - default: - break; // not found - } - break; // not found - - case ATTR_TOGGLE: - switch(obj_get_type(obj)) { - case LV_HASP_BUTTON: - if(update) { - bool toggle = Parser::is_true(payload); - lv_btn_set_checkable(obj, toggle); - lv_obj_set_event_cb(obj, toggle ? toggle_event_handler : generic_event_handler); - } else { - attr_out_int(obj, attr, lv_btn_get_checkable(obj)); - } - return; // attribute_found - case LV_HASP_BTNMATRIX: - if(update) { - bool toggle = Parser::is_true(payload); - if(toggle) { - lv_btnmatrix_set_btn_ctrl_all(obj, LV_BTNMATRIX_CTRL_CHECKABLE); - } else { - lv_btnmatrix_clear_btn_ctrl_all(obj, LV_BTNMATRIX_CTRL_CHECKABLE); - lv_btnmatrix_clear_btn_ctrl_all(obj, LV_BTNMATRIX_CTRL_CHECK_STATE); - } - } else { - attr_out_int(obj, attr, lv_btn_get_checkable(obj)); + attr_out_int(obj, attr_p, ext->mode); } return; // attribute_found default: @@ -2055,7 +1717,7 @@ void hasp_process_obj_attribute(lv_obj_t* obj, const char* attr_p, const char* p if(update) { lv_dropdown_set_options(obj, payload); } else { - attr_out_str(obj, attr, lv_dropdown_get_options(obj)); + attr_out_str(obj, attr_p, lv_dropdown_get_options(obj)); } return; // attribute_found case LV_HASP_ROLLER: @@ -2063,7 +1725,7 @@ void hasp_process_obj_attribute(lv_obj_t* obj, const char* attr_p, const char* p lv_roller_ext_t* ext = (lv_roller_ext_t*)lv_obj_get_ext_attr(obj); lv_roller_set_options(obj, payload, ext->mode); } else { - attr_out_str(obj, attr, lv_roller_get_options(obj)); + attr_out_str(obj, attr_p, lv_roller_get_options(obj)); } return; // attribute_found case LV_HASP_BTNMATRIX: @@ -2085,152 +1747,7 @@ void hasp_process_obj_attribute(lv_obj_t* obj, const char* attr_p, const char* p } break; // not found - case ATTR_BTN_POS: - if(obj_check_type(obj, LV_HASP_TABVIEW)) { - if(update) { - lv_tabview_set_btns_pos(obj, val); - } else { - attr_out_int(obj, attr_p, lv_tabview_get_btns_pos(obj)); - } - return; // attribute_found - } - break; // not found - - case ATTR_COUNT: - if(obj_check_type(obj, LV_HASP_TABVIEW)) { - if(update) LOG_WARNING(TAG_ATTR, F(D_ATTRIBUTE_READ_ONLY), attr_p); - attr_out_int(obj, attr_p, lv_tabview_get_tab_count(obj)); - return; // attribute_found - } - break; // not found - // case ATTR_MODAL: - - case ATTR_RED: // TODO: remove temp RED - if(obj_check_type(obj, LV_HASP_BTNMATRIX)) { - my_btnmatrix_map_clear(obj); // TODO : remove this test property - return; // attribute_found - } - break; // not found - - /* ***** Methods ***** */ - case ATTR_DELETE: - if(!lv_obj_get_parent(obj)) { - LOG_ERROR(TAG_ATTR, F(D_ATTRIBUTE_PAGE_METHOD_INVALID), attr_p); - } else { - lv_obj_del_async(obj); - } - return; // attribute_found - - case ATTR_CLEAR: - lv_obj_clean(obj); - return; // attribute_found - - case ATTR_TO_FRONT: - if(!lv_obj_get_parent(obj)) { - LOG_ERROR(TAG_ATTR, F(D_ATTRIBUTE_PAGE_METHOD_INVALID), attr_p); - } else { - lv_obj_move_foreground(obj); - } - return; // attribute_found - - case ATTR_TO_BACK: - if(!lv_obj_get_parent(obj)) { - LOG_ERROR(TAG_ATTR, F(D_ATTRIBUTE_PAGE_METHOD_INVALID), attr_p); - } else { - lv_obj_move_background(obj); - } - return; // attribute_found - } - - // Properties by object type - switch(obj_get_type(obj)) { - case LV_HASP_IMAGE: - switch(attr_hash) { - case ATTR_OFFSET_X: - update ? lv_img_set_offset_x(obj, val) : attr_out_int(obj, attr, lv_img_get_offset_x(obj)); - return; - case ATTR_OFFSET_Y: - update ? lv_img_set_offset_y(obj, val) : attr_out_int(obj, attr, lv_img_get_offset_y(obj)); - return; - case ATTR_SRC: - if(update) { - lv_img_cache_invalidate_src(lv_img_get_src(obj)); - lv_img_set_src(obj, payload); - } else { - switch(lv_img_src_get_type(obj)) { - case LV_IMG_SRC_FILE: - return attr_out_str(obj, attr, lv_img_get_file_name(obj)); - case LV_IMG_SRC_SYMBOL: - return attr_out_str(obj, attr, (char*)lv_img_get_src(obj)); - } - } - return; // attribute_found - } - break; // not found - - case LV_HASP_PAGE: - if(hasp_process_page_attributes(obj, attr_p, attr_hash, val, update)) { - return; // attribute_found - } - break; // not found - - case LV_HASP_DROPDOWN: - if(hasp_process_dropdown_attribute(obj, attr_p, attr_hash, payload, update)) { - return; // attribute_found - } - break; // not found - - case LV_HASP_ARC: - if(hasp_process_arc_attribute(obj, attr_p, attr_hash, payload, update)) { - return; // attribute_found - } - break; // not found - - case LV_HASP_GAUGE: - if(hasp_process_gauge_attribute(obj, attr_p, attr_hash, payload, update)) { - return; // attribute_found - } - break; // not found - - case LV_HASP_LMETER: - if(hasp_process_lmeter_attribute(obj, attr_p, attr_hash, payload, update)) { - return; // attribute_found - } - break; // not found - - case LV_HASP_CPICKER: - if(attr_hash == ATTR_COLOR) { - if(update) { - lv_color32_t c; - if(Parser::haspPayloadToColor(payload, c)) - lv_cpicker_set_color(obj, lv_color_make(c.ch.red, c.ch.green, c.ch.blue)); - } else { - attr_out_color(obj, attr, lv_cpicker_get_color(obj)); - } - return; // attribute_found - } - break; // not found - - default: - break; - } - - if(generic_int_attribute(obj, attr_hash, val, update)) { - if(update) attr_out_int(obj, attr, val); - return; // attribute_found - } - - if(generic_bool_attribute(obj, attr_hash, val, update)) { - bool toggle = Parser::is_true(payload); - if(update) attr_out_int(obj, attr, toggle); - return; // attribute_found - } - - { - bool result; - hasp_local_style_attr(obj, attr, attr_hash, payload, update, result); - if(result) return; // attribute_found } LOG_WARNING(TAG_ATTR, F(D_ATTRIBUTE_UNKNOWN " (%d)"), attr_p, attr_hash); @@ -2249,15 +1766,9 @@ void attr_out_str(lv_obj_t* obj, const char* attribute, const char* data) else doc[attribute].set(nullptr); - // size_t size = measureJson(doc); // strlen(data) + strlen(attribute); - // if(size < MQTT_MAX_PACKET_SIZE) { char payload[MQTT_MAX_PACKET_SIZE]; serializeJson(doc, payload, MQTT_MAX_PACKET_SIZE); object_dispatch_state(pageid, objid, payload); - - // } else { - // LOG_ERROR(TAG_ATTR, F(D_MQTT_PAYLOAD_TOO_LONG), (uint32_t)size); - // } } void attr_out_int(lv_obj_t* obj, const char* attribute, int32_t val) @@ -2265,14 +1776,28 @@ void attr_out_int(lv_obj_t* obj, const char* attribute, int32_t val) uint8_t pageid; uint8_t objid; - if(hasp_find_id_from_obj(obj, &pageid, &objid)) { - if(!attribute) return; + if(!attribute || !hasp_find_id_from_obj(obj, &pageid, &objid)) return; - char payload[64 + strlen(attribute)]; - snprintf_P(payload, sizeof(payload), PSTR("{\"%s\":%d}"), attribute, val); + char payload[64 + strlen(attribute)]; + snprintf_P(payload, sizeof(payload), PSTR("{\"%s\":%d}"), attribute, val); - object_dispatch_state(pageid, objid, payload); - } + object_dispatch_state(pageid, objid, payload); +} + +void attr_out_bool(lv_obj_t* obj, const char* attribute, bool val) +{ + uint8_t pageid; + uint8_t objid; + + if(!attribute || !hasp_find_id_from_obj(obj, &pageid, &objid)) return; + + char payload[16 + strlen(attribute)]; + if(val) + snprintf_P(payload, sizeof(payload), PSTR("{\"%s\":true}"), attribute); + else + snprintf_P(payload, sizeof(payload), PSTR("{\"%s\":false}"), attribute); + + object_dispatch_state(pageid, objid, payload); } void attr_out_color(lv_obj_t* obj, const char* attribute, lv_color_t color) @@ -2280,15 +1805,269 @@ void attr_out_color(lv_obj_t* obj, const char* attribute, lv_color_t color) uint8_t pageid; uint8_t objid; - if(hasp_find_id_from_obj(obj, &pageid, &objid)) { - if(!attribute) return; + if(!attribute || !hasp_find_id_from_obj(obj, &pageid, &objid)) return; - char payload[64 + strlen(attribute)]; - lv_color32_t c32; - c32.full = lv_color_to32(color); + char payload[64 + strlen(attribute)]; + lv_color32_t c32; + c32.full = lv_color_to32(color); - snprintf_P(payload, sizeof(payload), PSTR("{\"%s\":\"#%02x%02x%02x\",\"r\":%d,\"g\":%d,\"b\":%d}"), attribute, - c32.ch.red, c32.ch.green, c32.ch.blue, c32.ch.red, c32.ch.green, c32.ch.blue); - object_dispatch_state(pageid, objid, payload); + snprintf_P(payload, sizeof(payload), PSTR("{\"%s\":\"#%02x%02x%02x\",\"r\":%d,\"g\":%d,\"b\":%d}"), attribute, + c32.ch.red, c32.ch.green, c32.ch.blue, c32.ch.red, c32.ch.green, c32.ch.blue); + object_dispatch_state(pageid, objid, payload); +} + +/** + * Change or Retrieve the value of the attribute of an object + * @param obj lv_obj_t*: the object to get/set the attribute + * @param attribute char*: the attribute name (with or without leading ".") + * @param payload char*: the new value of the attribute + * @param update bool: change/set the value if true, dispatch/get value if false + * @note setting a value won't return anything, getting will dispatch the value + */ +void hasp_process_obj_attribute(lv_obj_t* obj, const char* attribute, const char* payload, bool update) +{ + // unsigned long start = millis(); + if(!obj) return; + + lv_color_t color; + int32_t val; + char temp_buffer[128] = ""; // buffer to hold return strings + char* text = &temp_buffer[0]; // pointer to temp_buffer + hasp_attribute_type_t ret; // the return code determines the attribute return value type + uint16_t attr_hash = Parser::get_sdbm(attribute); + + switch(attr_hash) { + case ATTR_GROUPID: + case ATTR_ID: + case ATTR_TRANSITION: + case ATTR_OBJID: + case ATTR_X: + case ATTR_Y: + case ATTR_H: + case ATTR_W: + case ATTR_OPACITY: + case ATTR_EXT_CLICK_H: + case ATTR_EXT_CLICK_V: + val = strtol(payload, nullptr, DEC); + ret = attribute_common_int(obj, attr_hash, val, update); + break; + + case ATTR_VIS: + case ATTR_HIDDEN: + case ATTR_TOGGLE: + case ATTR_CLICK: + case ATTR_SWIPE: + case ATTR_ENABLED: + val = Parser::is_true(payload); + ret = attribute_common_bool(obj, attr_hash, val, update); + break; + + case ATTR_MIN: + val = strtol(payload, nullptr, DEC); + ret = attribute_common_range(obj, val, update, true, false); + break; + + case ATTR_MAX: + val = strtol(payload, nullptr, DEC); + ret = attribute_common_range(obj, val, update, false, true); + break; + + case ATTR_VAL: + val = strtol(payload, nullptr, DEC); + ret = attribute_common_val(obj, val, update); + break; + + case ATTR_TXT: // TODO: remove + LOG_WARNING(TAG_HASP, F("txt property is obsolete, use text instead")); + case ATTR_TEXT: + ret = attribute_common_text(obj, attribute, payload, &text, update); + break; + + case ATTR_ALIGN: + ret = attribute_common_align(obj, attribute, payload, &text, update); + break; + + case ATTR_OBJ: + text = (char*)obj_get_type_name(obj); + if(update) + ret = ATTR_TYPE_STR_READONLY; + else + ret = ATTR_TYPE_STR; + break; + + // case ATTR_MODE: + // case ATTR_OPTIONS: + // case ATTR_BTN_POS: + + case ATTR_ACTION: + if(update) + obj->user_data.actionid = Parser::get_action_id(payload); + else + val = obj->user_data.actionid; + ret = ATTR_TYPE_INT; + break; + + // case ATTR_SYMBOL: + // (update) ? lv_dropdown_set_symbol(obj, payload) : attr_out_str(obj, attr, + // lv_dropdown_get_symbol(obj)); return true; + + case ATTR_DELETE: + case ATTR_CLEAR: + case ATTR_TO_FRONT: + case ATTR_TO_BACK: + case ATTR_OPEN: + case ATTR_CLOSE: + ret = attribute_common_method(obj, attr_hash, attribute, payload); + break; + + case ATTR_COLS: + case ATTR_ROWS: + case ATTR_AUTO_CLOSE: + case ATTR_SPEED: + case ATTR_ANIM_TIME: + case ATTR_ANIM_SPEED: + case ATTR_ANGLE: + case ATTR_ROTATION: + case ATTR_START_VALUE: + case ATTR_START_ANGLE: + case ATTR_END_ANGLE: + case ATTR_START_ANGLE1: + case ATTR_END_ANGLE1: + case ATTR_COUNT: + case ATTR_BTN_POS: + val = strtol(payload, nullptr, DEC); + ret = specific_int_attribute(obj, attr_hash, val, update); + break; + + case ATTR_OFFSET_X: + case ATTR_OFFSET_Y: + case ATTR_MAX_HEIGHT: + val = strtol(payload, nullptr, DEC); + ret = specific_coord_attribute(obj, attr_hash, val, update); + break; + + case ATTR_ADJUSTABLE: + case ATTR_ONE_CHECK: + case ATTR_AUTO_SIZE: + case ATTR_SHOW_SELECTED: + val = Parser::is_true(payload); + ret = specific_bool_attribute(obj, attr_hash, val, update); + break; + + case ATTR_NEXT: + case ATTR_PREV: + case ATTR_BACK: + val = strtol(payload, nullptr, DEC); + ret = specific_page_attribute(obj, attr_hash, val, update); + break; + + case ATTR_DIRECTION: + val = strtol(payload, nullptr, DEC); + ret = special_attribute_direction(obj, attr_hash, val, update); + break; + + case ATTR_SRC: + ret = special_attribute_src(obj, payload, &text, update); + break; + + default: { + bool result; + hasp_local_style_attr(obj, attribute, attr_hash, payload, update, result); + if(result) { + ret = ATTR_TYPE_METHOD_OK; + } else { + ret = ATTR_NOT_FOUND; + } + } } -} \ No newline at end of file + + if(ret == ATTR_NOT_FOUND) { + switch(obj_get_type(obj)) { // Properties by object type + + case LV_HASP_ARC: + val = strtol(payload, nullptr, DEC); + ret = hasp_process_arc_attribute(obj, attr_hash, val, update); + break; + + case LV_HASP_GAUGE: + val = strtol(payload, nullptr, DEC); + ret = hasp_process_gauge_attribute(obj, attr_hash, val, update); + break; + + case LV_HASP_LINEMETER: + val = strtol(payload, nullptr, DEC); + ret = hasp_process_lmeter_attribute(obj, attr_hash, val, update); + break; + + case LV_HASP_CPICKER: + if(attr_hash == ATTR_COLOR) { + if(update) { + lv_color32_t c; + if(Parser::haspPayloadToColor(payload, c)) + lv_cpicker_set_color(obj, lv_color_make(c.ch.red, c.ch.green, c.ch.blue)); + } else { + color = lv_cpicker_get_color(obj); + } + ret = ATTR_TYPE_COLOR; + } + break; + + default: + break; // not found + } + } + + // Positive return codes have returned a value, negative are warnings + if(update && ret > 0) return; // done + + // Output the returned value or warning + switch(ret) { + case ATTR_NOT_FOUND: + LOG_WARNING(TAG_ATTR, F(D_ATTRIBUTE_UNKNOWN " (%d)"), attribute, attr_hash); + break; + + case ATTR_TYPE_INT_READONLY: + LOG_WARNING(TAG_ATTR, F(D_ATTRIBUTE_READ_ONLY), attribute); + case ATTR_TYPE_INT: + attr_out_int(obj, attribute, val); + break; + + case ATTR_TYPE_BOOL_READONLY: + LOG_WARNING(TAG_ATTR, F(D_ATTRIBUTE_READ_ONLY), attribute); + case ATTR_TYPE_BOOL: + attr_out_bool(obj, attribute, val); + break; + + case ATTR_TYPE_STR_READONLY: + LOG_WARNING(TAG_ATTR, F(D_ATTRIBUTE_READ_ONLY), attribute); + case ATTR_TYPE_STR: + attr_out_str(obj, attribute, text); + break; + + case ATTR_TYPE_COLOR_INVALID: + LOG_WARNING(TAG_ATTR, F(D_ATTRIBUTE_ALIGN_INVALID), payload); + break; + + case ATTR_TYPE_COLOR: + attr_out_color(obj, attribute, color); + break; + + case ATTR_TYPE_ALIGN_INVALID: + LOG_WARNING(TAG_ATTR, F(D_ATTRIBUTE_ALIGN_INVALID), payload); + break; + + case ATTR_TYPE_ALIGN: + case ATTR_TYPE_DIRECTION_CLOCK: + case ATTR_TYPE_DIRECTION_XY: + attr_out_int(obj, attribute, val); + break; + + case ATTR_TYPE_METHOD_INVALID_FOR_PAGE: + LOG_ERROR(TAG_ATTR, F(D_ATTRIBUTE_PAGE_METHOD_INVALID), attribute); + case ATTR_TYPE_METHOD_OK: + break; + + default: + LOG_ERROR(TAG_ATTR, F(D_ERROR_UNKNOWN " (%d)"), ret); + } +} diff --git a/src/hasp/hasp_attribute.h b/src/hasp/hasp_attribute.h index 5b6f6e3b..0e8db12a 100644 --- a/src/hasp/hasp_attribute.h +++ b/src/hasp/hasp_attribute.h @@ -18,7 +18,6 @@ void my_msgbox_map_clear(lv_obj_t* obj); void line_clear_points(lv_obj_t* obj); void hasp_process_obj_attribute(lv_obj_t* obj, const char* attr_p, const char* payload, bool update); -bool hasp_process_obj_attribute_val(lv_obj_t* obj, const char* attr, int16_t intval, bool booval, bool update); bool attribute_set_normalized_value(lv_obj_t* obj, hasp_update_value_t& value); @@ -30,6 +29,26 @@ void attr_out_color(lv_obj_t* obj, const char* attribute, lv_color_t color); } /* extern "C" */ #endif +typedef enum { + ATTR_RANGE_ERROR = -9, + ATTR_TYPE_METHOD_INVALID_FOR_PAGE = -8, + ATTR_TYPE_ALIGN_INVALID = -5, + ATTR_TYPE_COLOR_INVALID = -4, + ATTR_TYPE_STR_READONLY = -3, + ATTR_TYPE_BOOL_READONLY = -2, + ATTR_TYPE_INT_READONLY = -1, + ATTR_NOT_FOUND = 0, + ATTR_TYPE_INT, + ATTR_TYPE_BOOL, + ATTR_TYPE_STR, + ATTR_TYPE_COLOR, + ATTR_TYPE_ALIGN, + ATTR_TYPE_DIRECTION_XY, + ATTR_TYPE_DIRECTION_CLOCK, + ATTR_TYPE_METHOD_OK, + +} hasp_attribute_type_t; + struct hasp_attr_update_bool_const_t { lv_hasp_obj_type_t obj_type; @@ -38,7 +57,7 @@ struct hasp_attr_update_bool_const_t bool (*get)(const lv_obj_t*); }; -struct hasp_attr_update16_const_t +struct hasp_attr_update_uint16_const_t { lv_hasp_obj_type_t obj_type; uint16_t hash; @@ -54,6 +73,22 @@ struct hasp_attr_update_lv_anim_value_const_t lv_anim_value_t (*get)(const lv_obj_t*); }; +struct hasp_attr_update_int16_const_t +{ + lv_hasp_obj_type_t obj_type; + uint16_t hash; + void (*set)(lv_obj_t*, int16_t); + int16_t (*get)(const lv_obj_t*); +}; + +struct hasp_attr_update_uint8_const_t +{ + lv_hasp_obj_type_t obj_type; + uint16_t hash; + void (*set)(lv_obj_t*, uint8_t); + uint8_t (*get)(const lv_obj_t*); +}; + struct hasp_attr_update8_const_t { lv_hasp_obj_type_t obj_type; @@ -62,7 +97,7 @@ struct hasp_attr_update8_const_t uint8_t (*get)(const lv_obj_t*); }; -struct hasp_attr_update16_t +struct hasp_attr_update_uint16_t { lv_hasp_obj_type_t obj_type; uint16_t hash; @@ -70,6 +105,22 @@ struct hasp_attr_update16_t uint16_t (*get)(lv_obj_t*); }; +struct hasp_attr_update_bool_t +{ + lv_hasp_obj_type_t obj_type; + uint16_t hash; + void (*set)(lv_obj_t*, bool); + bool (*get)(lv_obj_t*); +}; + +struct hasp_attr_update_lv_coord_t +{ + lv_hasp_obj_type_t obj_type; + uint16_t hash; + void (*set)(lv_obj_t*, lv_coord_t); + lv_coord_t (*get)(lv_obj_t*); +}; + struct hasp_attr_update_char_const_t { lv_hasp_obj_type_t obj_type; @@ -339,6 +390,7 @@ _HASP_ATTRIBUTE(SCALE_END_LINE_WIDTH, scale_end_line_width, lv_style_int_t) #define ATTR_EXT_CLICK_V 46657 #define ATTR_ANIM_TIME 59451 #define ATTR_ANIM_SPEED 281 +#define ATTR_START_VALUE 11828 // methods #define ATTR_DELETE 50027 diff --git a/src/hasp/hasp_attribute_helper.h b/src/hasp/hasp_attribute_helper.h new file mode 100644 index 00000000..15379023 --- /dev/null +++ b/src/hasp/hasp_attribute_helper.h @@ -0,0 +1,512 @@ +/* MIT License - Copyright (c) 2019-2021 Francis Van Roie + For full license information read the LICENSE file in the project folder */ + +#include "hasplib.h" + +const char* my_tabview_get_tab_name(const lv_obj_t* tabview, uint16_t id) +{ + if(id >= lv_tabview_get_tab_count(tabview)) return NULL; + + lv_tabview_ext_t* ext = (lv_tabview_ext_t*)lv_obj_get_ext_attr(tabview); + return ext->tab_name_ptr[id]; +} + +// OK - this function is missing in lvgl +static uint8_t my_roller_get_visible_row_count(const lv_obj_t* roller) +{ + const lv_font_t* font = lv_obj_get_style_text_font(roller, LV_ROLLER_PART_BG); + lv_style_int_t line_space = lv_obj_get_style_text_line_space(roller, LV_ROLLER_PART_BG); + lv_coord_t h = lv_obj_get_height(roller); + + if((lv_font_get_line_height(font) + line_space) != 0) + return (uint8_t)(h / (lv_font_get_line_height(font) + line_space)); + else + return 0; +} + +// OK - this function is not const in lvgl and doesn't return 0 +static uint16_t my_msgbox_stop_auto_close(const lv_obj_t* obj) +{ + lv_msgbox_stop_auto_close((lv_obj_t*)obj); + return 0; +} + +// OK - this function is not const in lvgl +static bool my_arc_get_adjustable(const lv_obj_t* arc) +{ + return lv_arc_get_adjustable((lv_obj_t*)arc); +} + +// OK - we need to change the event handler too +static void my_arc_set_adjustable(lv_obj_t* arc, bool toggle) +{ + lv_arc_set_adjustable(arc, toggle); + lv_obj_set_event_cb(arc, toggle ? slider_event_handler : generic_event_handler); +} + +// OK - this function is missing in lvgl +static inline uint16_t my_arc_get_rotation(lv_obj_t* arc) +{ + lv_arc_ext_t* ext = (lv_arc_ext_t*)lv_obj_get_ext_attr(arc); + return ext->rotation_angle; +} + +// OK - this function is missing in lvgl +static inline int16_t my_chart_get_min_value(lv_obj_t* chart) +{ + lv_chart_ext_t* ext = (lv_chart_ext_t*)lv_obj_get_ext_attr(chart); + return ext->ymin[LV_CHART_AXIS_PRIMARY_Y]; +} + +// OK - this function is missing in lvgl +static inline int16_t my_chart_get_max_value(lv_obj_t* chart) +{ + lv_chart_ext_t* ext = (lv_chart_ext_t*)lv_obj_get_ext_attr(chart); + return ext->ymax[LV_CHART_AXIS_PRIMARY_Y]; +} + +lv_chart_series_t* my_chart_get_series(lv_obj_t* chart, uint8_t ser_num) +{ + lv_chart_ext_t* ext = (lv_chart_ext_t*)lv_obj_get_ext_attr(chart); + lv_chart_series_t* ser = (lv_chart_series_t*)_lv_ll_get_tail(&ext->series_ll); + while(ser_num > 0 && ser) { + ser = (lv_chart_series_t*)_lv_ll_get_prev(&ext->series_ll, ser); + ser_num--; + } + return ser; +} + +// OK +static inline lv_color_t haspLogColor(lv_color_t color) +{ + // uint8_t r = (LV_COLOR_GET_R(color) * 263 + 7) >> 5; + // uint8_t g = (LV_COLOR_GET_G(color) * 259 + 3) >> 6; + // uint8_t b = (LV_COLOR_GET_B(color) * 263 + 7) >> 5; + // LOG_VERBOSE(TAG_ATTR,F("Color: R%u G%u B%u"), r, g, b); + return color; +} + +void my_bar_set_start_value(lv_obj_t* bar, int16_t start_value) +{ + lv_bar_set_start_value(bar, start_value, true); +} + +void my_slider_set_left_value(lv_obj_t* bar, int16_t start_value) +{ + lv_slider_set_left_value(bar, start_value, true); +} + +lv_coord_t my_dropdown_get_max_height(lv_obj_t* obj) +{ + return lv_dropdown_get_max_height(obj); +} + +// OK +lv_obj_t* FindButtonLabel(lv_obj_t* btn) +{ + if(btn) { + lv_obj_t* label = lv_obj_get_child_back(btn, NULL); + if(label) { + if(obj_check_type(label, LV_HASP_LABEL)) { + return label; + } + + } else { + LOG_ERROR(TAG_ATTR, F("FindButtonLabel NULL Pointer encountered")); + } + } else { + LOG_WARNING(TAG_ATTR, F("Button not defined")); + } + return NULL; +} + +// OK +static inline void my_btn_set_text(lv_obj_t* obj, const char* value) +{ + lv_obj_t* label = FindButtonLabel(obj); + if(label) { + lv_label_set_text(label, value); + } +} + +// OK - lvgl does not return a const char * +static const char* my_label_get_text(const lv_obj_t* label) +{ + return lv_label_get_text(label); // library does not return const +} + +static void my_label_set_text(lv_obj_t* label, const char* text) +{ + if(text[0] == '%') { + uint16_t hash = Parser::get_sdbm(text); + size_t len = strlen(text); + const char* static_text; + + switch(hash) { + + case 10125: + static_text = haspDevice.get_hostname(); + break; + default: + lv_label_set_text(label, text); + return; + } + + lv_label_set_text_static(label, static_text); + } else { + lv_label_set_text(label, text); + } +} + +// OK +static const char* my_btn_get_text(const lv_obj_t* obj) +{ + if(!obj) { + LOG_WARNING(TAG_ATTR, F("Button not defined")); + return NULL; + } + + lv_obj_t* label = lv_obj_get_child_back(obj, NULL); + if(label) { +#if 1 + if(obj_check_type(label, LV_HASP_LABEL)) return lv_label_get_text(label); + +#else + lv_obj_type_t list; + lv_obj_get_type(label, &list); + + if(obj_check_type(list.type[0], LV_HASP_LABEL)) { + text = lv_label_get_text(label); + return true; + } +#endif + + } else { + LOG_WARNING(TAG_ATTR, F("my_btn_get_text NULL Pointer encountered")); + } + + return NULL; +} + +/** + * Set a new value_str for an object. Memory will be allocated to store the text by the object. + * @param obj pointer to a object + * @param text '\0' terminated character string. NULL to refresh with the current text. + */ +void my_obj_set_value_str_text(lv_obj_t* obj, uint8_t part, lv_state_t state, const char* text) +{ + // LOG_VERBOSE(TAG_ATTR, F("%s %d"), __FILE__, __LINE__); + + const void* value_str_p = lv_obj_get_style_value_str(obj, part); + lv_obj_invalidate(obj); + + if(text == NULL || text[0] == 0) { + // LOG_VERBOSE(TAG_ATTR, F("%s %d"), __FILE__, __LINE__); + lv_obj_set_style_local_value_str(obj, part, state, NULL); + lv_mem_free(value_str_p); + // LOG_VERBOSE(TAG_ATTR, F("%s %d"), __FILE__, __LINE__); + return; + } + + LV_ASSERT_STR(text); + + if(value_str_p == NULL) { + /*Get the size of the text*/ + size_t len = strlen(text) + 1; + + /*Allocate space for the new text*/ + // LOG_VERBOSE(TAG_ATTR, F("%s %d"), __FILE__, __LINE__); + value_str_p = (char*)lv_mem_alloc(len); + LV_ASSERT_MEM(value_str_p); + if(value_str_p == NULL) return; + + // LOG_VERBOSE(TAG_ATTR, F("%s %d"), __FILE__, __LINE__); + strncpy((char*)value_str_p, text, len); + lv_obj_set_style_local_value_str(obj, part, state, (char*)value_str_p); + // LOG_VERBOSE(TAG_ATTR, F("%s %d"), __FILE__, __LINE__); + return; + } + + // lv_obj_set_style_local_value_str(obj, part, state, str_p); + + if(value_str_p == text) { + /*If set its own text then reallocate it (maybe its size changed)*/ + LOG_DEBUG(TAG_ATTR, "%s %d", __FILE__, __LINE__); + return; // don't touch the data + + // value_str_p = lv_mem_realloc(value_str_p, strlen(text) + 1); + + // LV_ASSERT_MEM(value_str_p); + // if(value_str_p == NULL) return; + } else { + /*Free the old text*/ + if(value_str_p != NULL) { + // LOG_DEBUG(TAG_ATTR, F("%s %d"), __FILE__, __LINE__); + lv_mem_free(value_str_p); + value_str_p = NULL; + // LOG_DEBUG(TAG_ATTR, F("%s %d"), __FILE__, __LINE__); + } + + /*Get the size of the text*/ + size_t len = strlen(text) + 1; + + /*Allocate space for the new text*/ + value_str_p = lv_mem_alloc(len); + LV_ASSERT_MEM(value_str_p); + if(value_str_p != NULL) strcpy((char*)value_str_p, text); + lv_obj_set_style_local_value_str(obj, part, state, (char*)value_str_p); + } + + // LOG_VERBOSE(TAG_ATTR, F("%s %d"), __FILE__, __LINE__); +} + +void my_tabview_set_text(lv_obj_t* obj, const char* payload) +{ + uint16_t id = lv_tabview_get_tab_act(obj); + + if(id < lv_tabview_get_tab_count(obj)) { + lv_tabview_set_tab_name(obj, id, (char*)payload); + } +} + +const char* my_tabview_get_text(const lv_obj_t* obj) +{ + uint16_t id = lv_tabview_get_tab_act(obj); + + if(id < lv_tabview_get_tab_count(obj)) { + return my_tabview_get_tab_name(obj, id); + } else { + return NULL; + } +} + +void my_tab_set_text(lv_obj_t* obj, const char* payload) +{ + lv_obj_t* content = lv_obj_get_parent(obj->parent); // 2 levels up + if(!content) return LOG_WARNING(TAG_ATTR, F("content not found")); + + lv_obj_t* tabview = lv_obj_get_parent(content); // 3rd level up + if(!tabview) return LOG_WARNING(TAG_ATTR, F("Tabview not found")); + + if(!obj_check_type(tabview, LV_HASP_TABVIEW)) + return LOG_WARNING(TAG_ATTR, F("LV_HASP_TABVIEW not found %d"), obj_get_type(tabview)); + + for(uint16_t id = 0; id < lv_tabview_get_tab_count(tabview); id++) { + if(obj == lv_tabview_get_tab(tabview, id)) { + lv_tabview_set_tab_name(tabview, id, (char*)payload); + return; + } + } + LOG_WARNING(TAG_ATTR, F("Tab not found")); +} + +const char* my_tab_get_text(const lv_obj_t* obj) +{ + lv_obj_t* content = lv_obj_get_parent(obj->parent); // 2 levels up + if(!content) { + LOG_WARNING(TAG_ATTR, F("content not found")); + return NULL; + } + + lv_obj_t* tabview = lv_obj_get_parent(content); // 3rd level up + if(!tabview) { + LOG_WARNING(TAG_ATTR, F("Tabview not found")); + return NULL; + } + + if(!obj_check_type(tabview, LV_HASP_TABVIEW)) { + LOG_WARNING(TAG_ATTR, F("LV_HASP_TABVIEW not found %d"), obj_get_type(tabview)); + return NULL; + } + + for(uint16_t id = 0; id < lv_tabview_get_tab_count(tabview); id++) { + if(obj == lv_tabview_get_tab(tabview, id)) { + return my_tabview_get_tab_name(tabview, id); + } + } + LOG_WARNING(TAG_ATTR, F("Tab not found")); + return NULL; +} + +static void gauge_format_10(lv_obj_t* gauge, char* buf, int bufsize, int32_t value) +{ + snprintf(buf, bufsize, PSTR("%d"), value / 10); +} + +static void gauge_format_100(lv_obj_t* gauge, char* buf, int bufsize, int32_t value) +{ + snprintf(buf, bufsize, PSTR("%d"), value / 100); +} + +static void gauge_format_1k(lv_obj_t* gauge, char* buf, int bufsize, int32_t value) +{ + snprintf(buf, bufsize, PSTR("%d"), value / 1000); +} + +static void gauge_format_10k(lv_obj_t* gauge, char* buf, int bufsize, int32_t value) +{ + snprintf(buf, bufsize, PSTR("%d"), value / 10000); +} + +#if 0 +static bool attribute_lookup_lv_property(uint16_t hash, uint8_t * prop) +{ + struct prop_hash_map + { + uint16_t hash; + uint8_t prop; + }; + + /* in order of prevalence */ + prop_hash_map props[] = { + {ATTR_PAD_TOP, LV_STYLE_PAD_TOP & LV_STYLE_PROP_ALL}, + {ATTR_BORDER_WIDTH, LV_STYLE_BORDER_WIDTH & LV_STYLE_PROP_ALL}, + {ATTR_OUTLINE_WIDTH, LV_STYLE_OUTLINE_WIDTH & LV_STYLE_PROP_ALL}, + {ATTR_VALUE_LETTER_SPACE, LV_STYLE_VALUE_LETTER_SPACE & LV_STYLE_PROP_ALL}, + {ATTR_TEXT_LETTER_SPACE, LV_STYLE_TEXT_LETTER_SPACE & LV_STYLE_PROP_ALL}, + {ATTR_LINE_WIDTH, LV_STYLE_LINE_WIDTH & LV_STYLE_PROP_ALL}, + {ATTR_TRANSITION_TIME, LV_STYLE_TRANSITION_TIME & LV_STYLE_PROP_ALL}, + {ATTR_SCALE_WIDTH, LV_STYLE_SCALE_WIDTH & LV_STYLE_PROP_ALL}, + {ATTR_RADIUS, LV_STYLE_RADIUS & LV_STYLE_PROP_ALL}, + {ATTR_PAD_BOTTOM, LV_STYLE_PAD_BOTTOM & LV_STYLE_PROP_ALL}, + {ATTR_BG_MAIN_STOP, LV_STYLE_BG_MAIN_STOP & LV_STYLE_PROP_ALL}, + {ATTR_BORDER_SIDE, LV_STYLE_BORDER_SIDE & LV_STYLE_PROP_ALL}, + {ATTR_OUTLINE_PAD, LV_STYLE_OUTLINE_PAD & LV_STYLE_PROP_ALL}, + {ATTR_PATTERN_REPEAT, LV_STYLE_PATTERN_REPEAT & LV_STYLE_PROP_ALL}, + {ATTR_VALUE_LINE_SPACE, LV_STYLE_VALUE_LINE_SPACE & LV_STYLE_PROP_ALL}, + {ATTR_TEXT_LINE_SPACE, LV_STYLE_TEXT_LINE_SPACE & LV_STYLE_PROP_ALL}, + {ATTR_TRANSITION_DELAY, LV_STYLE_TRANSITION_DELAY & LV_STYLE_PROP_ALL}, + {ATTR_SCALE_BORDER_WIDTH, LV_STYLE_SCALE_BORDER_WIDTH & LV_STYLE_PROP_ALL}, + {ATTR_CLIP_CORNER, LV_STYLE_CLIP_CORNER & LV_STYLE_PROP_ALL}, + {ATTR_PAD_LEFT, LV_STYLE_PAD_LEFT & LV_STYLE_PROP_ALL}, + {ATTR_BG_GRAD_STOP, LV_STYLE_BG_GRAD_STOP & LV_STYLE_PROP_ALL}, + {ATTR_TEXT_DECOR, LV_STYLE_TEXT_DECOR & LV_STYLE_PROP_ALL}, + {ATTR_LINE_DASH_WIDTH, LV_STYLE_LINE_DASH_WIDTH & LV_STYLE_PROP_ALL}, + {ATTR_TRANSITION_PROP_1, LV_STYLE_TRANSITION_PROP_1 & LV_STYLE_PROP_ALL}, + {ATTR_SCALE_END_BORDER_WIDTH, LV_STYLE_SCALE_END_BORDER_WIDTH & LV_STYLE_PROP_ALL}, + {ATTR_SIZE, LV_STYLE_SIZE & LV_STYLE_PROP_ALL}, + {ATTR_PAD_RIGHT, LV_STYLE_PAD_RIGHT & LV_STYLE_PROP_ALL}, + {ATTR_BG_GRAD_DIR, LV_STYLE_BG_GRAD_DIR & LV_STYLE_PROP_ALL}, + {ATTR_BORDER_POST, LV_STYLE_BORDER_POST & LV_STYLE_PROP_ALL}, + {ATTR_VALUE_OFS_X, LV_STYLE_VALUE_OFS_X & LV_STYLE_PROP_ALL}, + {ATTR_LINE_DASH_GAP, LV_STYLE_LINE_DASH_GAP & LV_STYLE_PROP_ALL}, + {ATTR_TRANSITION_PROP_2, LV_STYLE_TRANSITION_PROP_2 & LV_STYLE_PROP_ALL}, + {ATTR_SCALE_END_LINE_WIDTH, LV_STYLE_SCALE_END_LINE_WIDTH & LV_STYLE_PROP_ALL}, + {ATTR_TRANSFORM_WIDTH, LV_STYLE_TRANSFORM_WIDTH & LV_STYLE_PROP_ALL}, + {ATTR_PAD_INNER, LV_STYLE_PAD_INNER & LV_STYLE_PROP_ALL}, + {ATTR_VALUE_OFS_Y, LV_STYLE_VALUE_OFS_Y & LV_STYLE_PROP_ALL}, + {ATTR_LINE_ROUNDED, LV_STYLE_LINE_ROUNDED & LV_STYLE_PROP_ALL}, + {ATTR_TRANSITION_PROP_3, LV_STYLE_TRANSITION_PROP_3 & LV_STYLE_PROP_ALL}, + {ATTR_TRANSFORM_HEIGHT, LV_STYLE_TRANSFORM_HEIGHT & LV_STYLE_PROP_ALL}, + // {ATTR_MARGIN_TOP, LV_STYLE_MARGIN_TOP & LV_STYLE_PROP_ALL}, + {ATTR_VALUE_ALIGN, LV_STYLE_VALUE_ALIGN & LV_STYLE_PROP_ALL}, + {ATTR_TRANSITION_PROP_4, LV_STYLE_TRANSITION_PROP_4 & LV_STYLE_PROP_ALL}, + // {ATTR_TRANSFORM_ANGLE, LV_STYLE_TRANSFORM_ANGLE & LV_STYLE_PROP_ALL}, + // {ATTR_MARGIN_BOTTOM, LV_STYLE_MARGIN_BOTTOM & LV_STYLE_PROP_ALL}, + {ATTR_TRANSITION_PROP_5, LV_STYLE_TRANSITION_PROP_5 & LV_STYLE_PROP_ALL}, + // {ATTR_TRANSFORM_ZOOM, LV_STYLE_TRANSFORM_ZOOM & LV_STYLE_PROP_ALL}, + // {ATTR_MARGIN_LEFT, LV_STYLE_MARGIN_LEFT & LV_STYLE_PROP_ALL}, + {ATTR_TRANSITION_PROP_6, LV_STYLE_TRANSITION_PROP_6 & LV_STYLE_PROP_ALL}, + // {ATTR_MARGIN_RIGHT, LV_STYLE_MARGIN_RIGHT & LV_STYLE_PROP_ALL}, + {ATTR_BG_COLOR, LV_STYLE_BG_COLOR & LV_STYLE_PROP_ALL}, + {ATTR_BORDER_COLOR, LV_STYLE_BORDER_COLOR & LV_STYLE_PROP_ALL}, + {ATTR_OUTLINE_COLOR, LV_STYLE_OUTLINE_COLOR & LV_STYLE_PROP_ALL}, + {ATTR_PATTERN_RECOLOR, LV_STYLE_PATTERN_RECOLOR & LV_STYLE_PROP_ALL}, + {ATTR_VALUE_COLOR, LV_STYLE_VALUE_COLOR & LV_STYLE_PROP_ALL}, + {ATTR_TEXT_COLOR, LV_STYLE_TEXT_COLOR & LV_STYLE_PROP_ALL}, + {ATTR_LINE_COLOR, LV_STYLE_LINE_COLOR & LV_STYLE_PROP_ALL}, + {ATTR_IMAGE_RECOLOR, LV_STYLE_IMAGE_RECOLOR & LV_STYLE_PROP_ALL}, + {ATTR_SCALE_GRAD_COLOR, LV_STYLE_SCALE_GRAD_COLOR & LV_STYLE_PROP_ALL}, + {ATTR_BG_GRAD_COLOR, LV_STYLE_BG_GRAD_COLOR & LV_STYLE_PROP_ALL}, + {ATTR_TEXT_SEL_COLOR, LV_STYLE_TEXT_SEL_COLOR & LV_STYLE_PROP_ALL}, + {ATTR_SCALE_END_COLOR, LV_STYLE_SCALE_END_COLOR & LV_STYLE_PROP_ALL}, + // {ATTR_TEXT_SEL_BG_COLOR, LV_STYLE_TEXT_SEL_BG_COLOR & LV_STYLE_PROP_ALL}, + {ATTR_OPA_SCALE, LV_STYLE_OPA_SCALE & LV_STYLE_PROP_ALL}, + {ATTR_BG_OPA, LV_STYLE_BG_OPA & LV_STYLE_PROP_ALL}, + {ATTR_BORDER_OPA, LV_STYLE_BORDER_OPA & LV_STYLE_PROP_ALL}, + {ATTR_OUTLINE_OPA, LV_STYLE_OUTLINE_OPA & LV_STYLE_PROP_ALL}, + {ATTR_PATTERN_OPA, LV_STYLE_PATTERN_OPA & LV_STYLE_PROP_ALL}, + {ATTR_VALUE_OPA, LV_STYLE_VALUE_OPA & LV_STYLE_PROP_ALL}, + {ATTR_TEXT_OPA, LV_STYLE_TEXT_OPA & LV_STYLE_PROP_ALL}, + {ATTR_LINE_OPA, LV_STYLE_LINE_OPA & LV_STYLE_PROP_ALL}, + {ATTR_IMAGE_OPA, LV_STYLE_IMAGE_OPA & LV_STYLE_PROP_ALL}, + {ATTR_PATTERN_RECOLOR_OPA, LV_STYLE_PATTERN_RECOLOR_OPA & LV_STYLE_PROP_ALL}, + {ATTR_IMAGE_RECOLOR_OPA, LV_STYLE_IMAGE_RECOLOR_OPA & LV_STYLE_PROP_ALL}, + {ATTR_PATTERN_IMAGE, LV_STYLE_PATTERN_IMAGE & LV_STYLE_PROP_ALL}, + {ATTR_VALUE_FONT, LV_STYLE_VALUE_FONT & LV_STYLE_PROP_ALL}, + {ATTR_TEXT_FONT, LV_STYLE_TEXT_FONT & LV_STYLE_PROP_ALL}, + {ATTR_TRANSITION_PATH, LV_STYLE_TRANSITION_PATH & LV_STYLE_PROP_ALL}, + {ATTR_VALUE_STR, LV_STYLE_VALUE_STR & LV_STYLE_PROP_ALL}, + +#if LV_USE_SHADOW + {ATTR_SHADOW_WIDTH, LV_STYLE_SHADOW_WIDTH & LV_STYLE_PROP_ALL}, + {ATTR_SHADOW_OFS_X, LV_STYLE_SHADOW_OFS_X & LV_STYLE_PROP_ALL}, + {ATTR_SHADOW_OFS_Y, LV_STYLE_SHADOW_OFS_Y & LV_STYLE_PROP_ALL}, + {ATTR_SHADOW_SPREAD, LV_STYLE_SHADOW_SPREAD & LV_STYLE_PROP_ALL}, + {ATTR_SHADOW_COLOR, LV_STYLE_SHADOW_COLOR & LV_STYLE_PROP_ALL}, + {ATTR_SHADOW_OPA, LV_STYLE_SHADOW_OPA & LV_STYLE_PROP_ALL}, +#endif + +#if LV_USE_BLEND_MODES && LV_USE_SHADOW + {ATTR_SHADOW_BLEND_MODE, LV_STYLE_SHADOW_BLEND_MODE & LV_STYLE_PROP_ALL}, +#endif + +#if LV_USE_BLEND_MODES + {ATTR_BG_BLEND_MODE, LV_STYLE_BG_BLEND_MODE & LV_STYLE_PROP_ALL}, + {ATTR_PATTERN_BLEND_MODE, LV_STYLE_PATTERN_BLEND_MODE & LV_STYLE_PROP_ALL}, + {ATTR_IMAGE_BLEND_MODE, LV_STYLE_IMAGE_BLEND_MODE & LV_STYLE_PROP_ALL}, + {ATTR_LINE_BLEND_MODE, LV_STYLE_LINE_BLEND_MODE & LV_STYLE_PROP_ALL}, + {ATTR_BORDER_BLEND_MODE, LV_STYLE_BORDER_BLEND_MODE & LV_STYLE_PROP_ALL}, + {ATTR_OUTLINE_BLEND_MODE, LV_STYLE_OUTLINE_BLEND_MODE & LV_STYLE_PROP_ALL}, + {ATTR_VALUE_BLEND_MODE, LV_STYLE_VALUE_BLEND_MODE & LV_STYLE_PROP_ALL}, + {ATTR_TEXT_BLEND_MODE, LV_STYLE_TEXT_BLEND_MODE & LV_STYLE_PROP_ALL}, +#endif + }; + + for(uint32_t i = 0; i < sizeof(props) / sizeof(props[0]); i++) { + if(props[i].hash == hash) { + *prop = props[1].prop; + LOG_WARNING(TAG_ATTR, F("%d found and has propery %d"), hash, props[i].prop); + return true; + } + } + LOG_ERROR(TAG_ATTR, F("%d has no property id"), hash); + return false; +} + +static bool attribute_get_lv_property() +{ + lv_res_t res _lv_style_get_int(const lv_style_t * style, lv_style_property_t prop, void * res); + return res == LV_RES_OK +} + +static bool attribute_set_lv_property() +{ + lv_res_t res _lv_style_get_int(const lv_style_t * style, lv_style_property_t prop, void * res); + return res == LV_RES_OK +} + +static bool attribute_update_lv_property(lv_obj_t * obj, const char * attr_p, uint16_t attr_hash, const char * payload, + bool update) +{ + uint8_t prop; + uint8_t prop_type; + + // convert sdbm hash to lv property number + if(!attribute_lookup_lv_property(attr_hash, &prop)) return false; + + // find the parameter type for this property + prop_type = prop & 0xF; + + if(prop_type < LV_STYLE_ID_COLOR) { + if(update) { + _lv_obj_set_style_local_int(obj, part, prop | (state << LV_STYLE_STATE_POS), atoi(payload)) + } else { + attr_out_str(obj, attr_p, lv_obj_get_style_value_str(obj, part)); + } + } else if(prop_type < LV_STYLE_ID_OPA) { + } else if(prop_type < LV_STYLE_ID_PTR) { + } else { + } +} +#endif