From 087ab979d6727fea653a3a1f3d1632bc1f00cec4 Mon Sep 17 00:00:00 2001 From: user-0 Date: Fri, 22 Mar 2019 17:24:40 +0200 Subject: [PATCH 1/7] Add support for chart axes ticks and value labels. Add support for chart axis X label. --- lv_objx/lv_chart.c | 309 +++++++++++++++++++++++++++++++++++++++++++++ lv_objx/lv_chart.h | 49 +++++++ 2 files changed, 358 insertions(+) diff --git a/lv_objx/lv_chart.c b/lv_objx/lv_chart.c index 0060c1499..fdb824ae4 100644 --- a/lv_objx/lv_chart.c +++ b/lv_objx/lv_chart.c @@ -20,6 +20,7 @@ #define LV_CHART_HDIV_DEF 3 #define LV_CHART_VDIV_DEF 5 #define LV_CHART_PNUM_DEF 10 +#define LV_CHART_AXIS_MARGIN 50 /********************** * TYPEDEFS @@ -35,6 +36,7 @@ static void lv_chart_draw_lines(lv_obj_t * chart, const lv_area_t * mask); static void lv_chart_draw_points(lv_obj_t * chart, const lv_area_t * mask); static void lv_chart_draw_cols(lv_obj_t * chart, const lv_area_t * mask); static void lv_chart_draw_vertical_lines(lv_obj_t * chart, const lv_area_t * mask); +static void lv_chart_draw_axes(lv_obj_t * chart, const lv_area_t * mask); /********************** * STATIC VARIABLES @@ -45,6 +47,7 @@ static lv_signal_func_t ancestor_signal; /********************** * MACROS **********************/ +#define strlens(s) (s==NULL?0:strlen(s)) /********************** * GLOBAL FUNCTIONS @@ -81,6 +84,8 @@ lv_obj_t * lv_chart_create(lv_obj_t * par, const lv_obj_t * copy) ext->series.opa = LV_OPA_COVER; ext->series.dark = LV_OPA_50; ext->series.width = 2; + memset(&ext->x_axis, 0, sizeof(ext->x_axis)); + memset(&ext->y_axis, 0, sizeof(ext->y_axis)); if(ancestor_design_f == NULL) ancestor_design_f = lv_obj_get_design_func(new_chart); if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_func(new_chart); @@ -109,6 +114,8 @@ lv_obj_t * lv_chart_create(lv_obj_t * par, const lv_obj_t * copy) ext->vdiv_cnt = ext_copy->vdiv_cnt; ext->point_cnt = ext_copy->point_cnt; ext->series.opa = ext_copy->series.opa; + ext->x_axis = ext_copy->x_axis; + ext->y_axis = ext_copy->y_axis; /*Refresh the style with new signal function*/ lv_obj_refresh_style(new_chart); @@ -387,6 +394,53 @@ void lv_chart_set_next(lv_obj_t * chart, lv_chart_series_t * ser, lv_coord_t y) lv_chart_refresh(chart); } +/** + * Set the x-axis label of a chart + * @param chart pointer to a chart object + * @param text pointer to the label text (not copied) + */ +void lv_chart_set_label(lv_obj_t* chart, const char* text) +{ + lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart); + ext->x_axis.label = text; + lv_obj_refresh_ext_size(chart); +} + +/** + * Set the x/y-axis ticks of a chart + * @param chart pointer to a chart object + * @param list_of_values list of string values, terminated with \n, except the last + * @param num_tick_marks if list_of_values is NULL: total number of ticks per axis + * else step in ticks between two value labels + * @param label label to show for this axis (only X) + * @param options extra options + */ +void lv_chart_set_x_ticks( lv_obj_t* chart, + const char* list_of_values, + uint8_t num_tick_marks, + const char* label, + lv_chart_axis_options_t options) +{ + lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart); + ext->x_axis.num_tick_marks = num_tick_marks; + ext->x_axis.list_of_values = list_of_values; + ext->x_axis.label = label; + ext->x_axis.options = options; +} + +void lv_chart_set_y_ticks( lv_obj_t* chart, + const char* list_of_values, + uint8_t num_tick_marks, + const char* label, + lv_chart_axis_options_t options) +{ + lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart); + ext->y_axis.num_tick_marks = num_tick_marks; + ext->y_axis.list_of_values = list_of_values; + ext->y_axis.label = label; + ext->y_axis.options = options; +} + /*===================== * Getter functions *====================*/ @@ -490,6 +544,7 @@ static bool lv_chart_design(lv_obj_t * chart, const lv_area_t * mask, lv_design_ if(ext->type & LV_CHART_TYPE_COLUMN) lv_chart_draw_cols(chart, mask); if(ext->type & LV_CHART_TYPE_POINT) lv_chart_draw_points(chart, mask); if(ext->type & LV_CHART_TYPE_VERTICAL_LINE) lv_chart_draw_vertical_lines(chart, mask); + lv_chart_draw_axes(chart, mask); } return true; } @@ -522,6 +577,16 @@ static lv_res_t lv_chart_signal(lv_obj_t * chart, lv_signal_t sign, void * param if(buf->type[i] == NULL) break; } buf->type[i] = "lv_chart"; + } else if(sign == LV_SIGNAL_REFR_EXT_SIZE) { + /*Provide extra px draw area around the chart if needed*/ + lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart); + + if( (ext->x_axis.list_of_values != NULL || ext->x_axis.num_tick_marks != 0) || + (ext->y_axis.list_of_values != NULL || ext->y_axis.num_tick_marks != 0) || + (ext->x_axis.label == NULL) ) + { /* Reserve some space for axis ticks and labels, predefined by the user */ + chart->ext_size += LV_CHART_AXIS_MARGIN; + } } return res; @@ -821,4 +886,248 @@ static void lv_chart_draw_vertical_lines(lv_obj_t * chart, const lv_area_t * mas } } } + +static void lv_chart_draw_y_ticks(lv_obj_t * chart, const lv_area_t * mask) +{ + lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart); + + if(ext->y_axis.list_of_values != NULL || ext->y_axis.num_tick_marks != 0) { + + const lv_style_t * style = lv_obj_get_style(chart); + lv_opa_t opa_scale = lv_obj_get_opa_scale(chart); + + uint8_t i,j; + uint8_t list_index; + uint8_t num_of_labels; + uint8_t num_scale_ticks; + uint8_t major_tick_len, minor_tick_len; + lv_point_t p1; + lv_point_t p2; + lv_coord_t x_ofs = chart->coords.x1; + lv_coord_t y_ofs = chart->coords.y1; + lv_coord_t h = lv_obj_get_height(chart); + lv_coord_t w = lv_obj_get_width(chart); + char buf[16+1]; /* up to 16 symbols per label + null terminator */ + + /* calculate the size of tick marks */ + major_tick_len = (int32_t)w / 15; + minor_tick_len = major_tick_len * 2/3; + + /* count the '\n'-s to determine the number of options */ + list_index = 0; + num_of_labels = 0; + if(ext->y_axis.list_of_values != NULL) + { + for(j = 0; ext->y_axis.list_of_values[j] != '\0'; j++) { + if(ext->y_axis.list_of_values[j] == '\n') + num_of_labels++; + } + + num_of_labels++; /* last option in the at row*/ + } + + /* we can't have string labels without ticks step, set to 1 if not specified */ + if(ext->y_axis.num_tick_marks == 0) + ext->y_axis.num_tick_marks = 1; + + /* calculate total number of ticks */ + if(num_of_labels < 2) + num_scale_ticks = ext->y_axis.num_tick_marks; + else + num_scale_ticks = (ext->y_axis.num_tick_marks * (num_of_labels - 1)); + + for(i = 0; i < (num_scale_ticks + 1); i++ ) { /* one extra loop - it may not exist in the list, empty label */ + /* first point of the tick */ + p1.x = 0 + x_ofs; + + /* second point of the tick */ + if( (num_of_labels != 0) && (i == 0 || i % ext->y_axis.num_tick_marks == 0) ) + p2.x = p1.x - major_tick_len; /* major tick */ + else + p2.x = p1.x - minor_tick_len; /* minor tick */ + + /* draw a line at moving y position */ + p2.y = p1.y = y_ofs + h - (int32_t)(((int32_t)h * i) / num_scale_ticks + 1) - __LV_CHART_AXIS_Y_TICK_OFFSET_FIX; + + if( i != num_scale_ticks ) + lv_draw_line(&p1, &p2, mask, style, opa_scale); + else + if( (ext->y_axis.options & LV_CHART_AXIS_DRAW_LAST_TICK) != 0 ) + lv_draw_line(&p1, &p2, mask, style, opa_scale); + + /* draw values if available */ + if (num_of_labels != 0) + { + /* add text only to major tick */ + if( i == 0 || i % ext->y_axis.num_tick_marks == 0 ) + { + /* search for tick string */ + j = 0; + while( ext->y_axis.list_of_values[list_index] != '\n' && + ext->y_axis.list_of_values[list_index] != '\0') + { + /* do not overflow the buffer, but move to the end of the current label */ + if(j < 16) + buf[j++] = ext->y_axis.list_of_values[list_index++]; + else + list_index++; + } + + /* this was a string, but not end of the list, so jump to the next string */ + if(ext->y_axis.list_of_values[list_index] == '\n') + list_index++; + + /* terminate the string */ + buf[j] = '\0'; + + /* reserve appropriate area */ + lv_point_t size; + lv_txt_get_size(&size, buf, style->text.font, style->text.letter_space, style->text.line_space, LV_COORD_MAX, LV_TXT_FLAG_CENTER); + + /* set the area at some distance of the major tick len left of the tick */ + lv_area_t a = {(p2.x - size.x - __LV_CHART_TO_LABEL_DISTANCE) , (p2.y - size.y/2), (p2.x - __LV_CHART_TO_LABEL_DISTANCE), (p2.y + size.y/2) }; + lv_draw_label(&a, mask, style, opa_scale, buf, LV_TXT_FLAG_CENTER, NULL); + } + } + } + } +} + +static void lv_chart_draw_x_ticks(lv_obj_t * chart, const lv_area_t * mask) +{ + + lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart); + + if(ext->x_axis.list_of_values != NULL || ext->x_axis.num_tick_marks != 0) { + + const lv_style_t * style = lv_obj_get_style(chart); + lv_opa_t opa_scale = lv_obj_get_opa_scale(chart); + + uint8_t i,j; + uint8_t list_index; + uint8_t num_of_labels; + uint8_t num_scale_ticks; + uint8_t major_tick_len, minor_tick_len; + lv_point_t p1; + lv_point_t p2; + lv_coord_t x_ofs = chart->coords.x1; + lv_coord_t y_ofs = chart->coords.y1; + lv_coord_t h = lv_obj_get_height(chart); + lv_coord_t w = lv_obj_get_width(chart); + char buf[16+1]; /* up to 16 symbols per label + null terminator */ + + /* calculate the size of tick marks */ + major_tick_len = (int32_t)w / 15; + minor_tick_len = major_tick_len * 2/3; + + /* count the '\n'-s to determine the number of options */ + list_index = 0; + num_of_labels = 0; + if(ext->x_axis.list_of_values != NULL) + { + for(j = 0; ext->x_axis.list_of_values[j] != '\0'; j++) { + if(ext->x_axis.list_of_values[j] == '\n') + num_of_labels++; + } + + num_of_labels++; /* last option in the at row*/ + } + + /* we can't have string labels without ticks step, set to 1 if not specified */ + if(ext->x_axis.num_tick_marks == 0) + ext->x_axis.num_tick_marks = 1; + + /* calculate total number of marks */ + if(num_of_labels < 2) + num_scale_ticks = ext->x_axis.num_tick_marks; + else + num_scale_ticks = (ext->x_axis.num_tick_marks * (num_of_labels - 1)); + + for(i = 0; i < (num_scale_ticks + 1); i++ ) { /* one extra loop - it may not exist in the list, empty label */ + /* first point of the tick */ + p1.y = h + y_ofs; + + /* second point of the tick */ + if( (num_of_labels != 0) && (i == 0 || i % ext->x_axis.num_tick_marks == 0) ) + p2.y = p1.y + major_tick_len; /* major tick */ + else + p2.y = p1.y + minor_tick_len; /* minor tick */ + + /* draw a line at moving x position */ + p2.x = p1.x = x_ofs + (int32_t)(((int32_t)w * i) / num_scale_ticks + 1) - __LV_CHART_AXIS_X_TICK_OFFSET_FIX; + + if( i != num_scale_ticks ) + lv_draw_line(&p1, &p2, mask, style, opa_scale); + else + if( (ext->x_axis.options & LV_CHART_AXIS_DRAW_LAST_TICK) != 0 ) + lv_draw_line(&p1, &p2, mask, style, opa_scale); + + /* draw values if available */ + if (num_of_labels != 0) + { + /* add text only to major tick */ + if( i == 0 || i % ext->x_axis.num_tick_marks == 0 ) + { + /* search for tick string */ + j = 0; + while( ext->x_axis.list_of_values[list_index] != '\n' && + ext->x_axis.list_of_values[list_index] != '\0') + { + /* do not overflow the buffer, but move to the end of the current label */ + if(j < 16) + buf[j++] = ext->x_axis.list_of_values[list_index++]; + else + list_index++; + } + + /* this was a string, but not end of the list, so jump to the next string */ + if(ext->x_axis.list_of_values[list_index] == '\n') + list_index++; + + /* terminate the string */ + buf[j] = '\0'; + + /* reserve appropriate area */ + lv_point_t size; + lv_txt_get_size(&size, buf, style->text.font, style->text.letter_space, style->text.line_space, LV_COORD_MAX, LV_TXT_FLAG_CENTER); + + /* set the area at some distance of the major tick len under of the tick */ + lv_area_t a = { (p2.x - size.x/2) , (p2.y + __LV_CHART_TO_LABEL_DISTANCE), (p2.x + size.x/2), (p2.y + size.y + __LV_CHART_TO_LABEL_DISTANCE) }; + lv_draw_label(&a, mask, style, opa_scale, buf, LV_TXT_FLAG_CENTER, NULL); + } + } + } + } +} + +static void lv_chart_draw_x_axis_label(lv_obj_t * chart, const lv_area_t * mask) +{ + + lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart); + + if (ext->x_axis.label != NULL) + { + const lv_style_t * style = lv_obj_get_style(chart); + lv_opa_t opa_scale = lv_obj_get_opa_scale(chart); + lv_coord_t w = lv_obj_get_width(chart); + + lv_point_t size; + lv_txt_get_size(&size, ext->x_axis.label, style->text.font, style->text.letter_space, style->text.line_space, LV_COORD_MAX, LV_TXT_FLAG_CENTER); + + lv_area_t label_area; + label_area.x1 = chart->coords.x1 + w/2 - size.x/2; + label_area.y1 = chart->coords.y1 - __LV_CHART_TO_LABEL_DISTANCE - size.y/2; + label_area.x2 = label_area.x1 + size.x; + label_area.y2 = label_area.y1 + size.y/2; + + lv_draw_label(&label_area, mask, style, opa_scale, ext->x_axis.label, LV_TXT_FLAG_CENTER, NULL); + } +} + +static void lv_chart_draw_axes(lv_obj_t * chart, const lv_area_t * mask) +{ + lv_chart_draw_y_ticks(chart, mask); + lv_chart_draw_x_ticks(chart, mask); + lv_chart_draw_x_axis_label(chart, mask); +} #endif diff --git a/lv_objx/lv_chart.h b/lv_objx/lv_chart.h index baea9d0f4..a97fc704e 100644 --- a/lv_objx/lv_chart.h +++ b/lv_objx/lv_chart.h @@ -39,6 +39,25 @@ typedef struct uint16_t start_point; } lv_chart_series_t; +/*Data of chart */ +#define __LV_CHART_TO_LABEL_DISTANCE 4 +#define __LV_CHART_AXIS_X_TICK_OFFSET_FIX 1 +#define __LV_CHART_AXIS_Y_TICK_OFFSET_FIX 0 + +enum +{ + LV_CHART_AXIS_DRAW_LAST_TICK = 0x01 /* draw the last tick */ +}; +typedef uint8_t lv_chart_axis_options_t; + +typedef struct +{ + const char* list_of_values; + uint8_t num_tick_marks; + const char* label; + lv_chart_axis_options_t options; +} lv_chart_axis_cfg_t; + /*Data of chart */ typedef struct { @@ -51,6 +70,8 @@ typedef struct uint8_t vdiv_cnt; /*Number of vertical division lines*/ uint16_t point_cnt; /*Point number in a data line*/ uint8_t type :4; /*Line, column or point chart (from 'lv_chart_type_t')*/ + lv_chart_axis_cfg_t y_axis; + lv_chart_axis_cfg_t x_axis; struct { lv_coord_t width; /*Line width or point radius*/ uint8_t num; /*Number of data lines in dl_ll*/ @@ -190,6 +211,34 @@ static inline void lv_chart_set_style(lv_obj_t *chart, lv_style_t *style) lv_obj_set_style(chart, style); } +/** + * Set the x-axis label of a chart + * @param chart pointer to a chart object + * @param text pointer to the label text (not copied) + */ +void lv_chart_set_label(lv_obj_t* chart, const char* text); + +/** + * Set the x/y-axis ticks of a chart + * @param chart pointer to a chart object + * @param list_of_values list of string values, terminated with \n, except the last + * @param num_tick_marks if list_of_values is NULL: total number of ticks per axis + * else step in ticks between two value labels + * @param label label to show for this axis (only X) + * @param options extra options + */ +void lv_chart_set_x_ticks( lv_obj_t* chart, + const char* list_of_values, + uint8_t num_tick_marks, + const char* label, + lv_chart_axis_options_t options); + +void lv_chart_set_y_ticks( lv_obj_t* chart, + const char* list_of_values, + uint8_t num_tick_marks, + const char* label, + lv_chart_axis_options_t options); + /*===================== * Getter functions *====================*/ From 46d5debc7a679de622201ed19db257f70d46cc1c Mon Sep 17 00:00:00 2001 From: user-0 Date: Fri, 22 Mar 2019 19:20:58 +0200 Subject: [PATCH 2/7] FIXED: Add support for chart axes ticks and value labels / chart label. --- lv_objx/lv_chart.c | 33 +++++++++++++++++++-------------- lv_objx/lv_chart.h | 6 +----- 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/lv_objx/lv_chart.c b/lv_objx/lv_chart.c index fdb824ae4..caa31135e 100644 --- a/lv_objx/lv_chart.c +++ b/lv_objx/lv_chart.c @@ -21,6 +21,12 @@ #define LV_CHART_VDIV_DEF 5 #define LV_CHART_PNUM_DEF 10 #define LV_CHART_AXIS_MARGIN 50 +#define LV_CHART_AXIS_TICK_LABEL_MAX_LEN 16 +#define LV_CHART_AXIS_TO_LABEL_DISTANCE 4 +#define LV_CHART_AXIS_MAJOR_TICK_LEN_COE 1/15 +#define LV_CHART_AXIS_MINOR_TICK_LEN_COE 2/3 +#define LV_CHART_AXIS_X_TICK_OFFSET_FIX 1 +#define LV_CHART_AXIS_Y_TICK_OFFSET_FIX 0 /********************** * TYPEDEFS @@ -47,7 +53,6 @@ static lv_signal_func_t ancestor_signal; /********************** * MACROS **********************/ -#define strlens(s) (s==NULL?0:strlen(s)) /********************** * GLOBAL FUNCTIONS @@ -907,11 +912,11 @@ static void lv_chart_draw_y_ticks(lv_obj_t * chart, const lv_area_t * mask) lv_coord_t y_ofs = chart->coords.y1; lv_coord_t h = lv_obj_get_height(chart); lv_coord_t w = lv_obj_get_width(chart); - char buf[16+1]; /* up to 16 symbols per label + null terminator */ + char buf[LV_CHART_AXIS_TICK_LABEL_MAX_LEN+1]; /* up to N symbols per label + null terminator */ /* calculate the size of tick marks */ - major_tick_len = (int32_t)w / 15; - minor_tick_len = major_tick_len * 2/3; + major_tick_len = (int32_t)w * LV_CHART_AXIS_MAJOR_TICK_LEN_COE; + minor_tick_len = major_tick_len * LV_CHART_AXIS_MINOR_TICK_LEN_COE; /* count the '\n'-s to determine the number of options */ list_index = 0; @@ -947,7 +952,7 @@ static void lv_chart_draw_y_ticks(lv_obj_t * chart, const lv_area_t * mask) p2.x = p1.x - minor_tick_len; /* minor tick */ /* draw a line at moving y position */ - p2.y = p1.y = y_ofs + h - (int32_t)(((int32_t)h * i) / num_scale_ticks + 1) - __LV_CHART_AXIS_Y_TICK_OFFSET_FIX; + p2.y = p1.y = y_ofs + h - (int32_t)(((int32_t)h * i) / num_scale_ticks + 1) - LV_CHART_AXIS_Y_TICK_OFFSET_FIX; if( i != num_scale_ticks ) lv_draw_line(&p1, &p2, mask, style, opa_scale); @@ -967,7 +972,7 @@ static void lv_chart_draw_y_ticks(lv_obj_t * chart, const lv_area_t * mask) ext->y_axis.list_of_values[list_index] != '\0') { /* do not overflow the buffer, but move to the end of the current label */ - if(j < 16) + if(j < LV_CHART_AXIS_TICK_LABEL_MAX_LEN) buf[j++] = ext->y_axis.list_of_values[list_index++]; else list_index++; @@ -985,7 +990,7 @@ static void lv_chart_draw_y_ticks(lv_obj_t * chart, const lv_area_t * mask) lv_txt_get_size(&size, buf, style->text.font, style->text.letter_space, style->text.line_space, LV_COORD_MAX, LV_TXT_FLAG_CENTER); /* set the area at some distance of the major tick len left of the tick */ - lv_area_t a = {(p2.x - size.x - __LV_CHART_TO_LABEL_DISTANCE) , (p2.y - size.y/2), (p2.x - __LV_CHART_TO_LABEL_DISTANCE), (p2.y + size.y/2) }; + lv_area_t a = {(p2.x - size.x - LV_CHART_AXIS_TO_LABEL_DISTANCE) , (p2.y - size.y/2), (p2.x - LV_CHART_AXIS_TO_LABEL_DISTANCE), (p2.y + size.y/2) }; lv_draw_label(&a, mask, style, opa_scale, buf, LV_TXT_FLAG_CENTER, NULL); } } @@ -1014,11 +1019,11 @@ static void lv_chart_draw_x_ticks(lv_obj_t * chart, const lv_area_t * mask) lv_coord_t y_ofs = chart->coords.y1; lv_coord_t h = lv_obj_get_height(chart); lv_coord_t w = lv_obj_get_width(chart); - char buf[16+1]; /* up to 16 symbols per label + null terminator */ + char buf[LV_CHART_AXIS_TICK_LABEL_MAX_LEN+1]; /* up to N symbols per label + null terminator */ /* calculate the size of tick marks */ - major_tick_len = (int32_t)w / 15; - minor_tick_len = major_tick_len * 2/3; + major_tick_len = (int32_t)w * LV_CHART_AXIS_MAJOR_TICK_LEN_COE; + minor_tick_len = major_tick_len * LV_CHART_AXIS_MINOR_TICK_LEN_COE; /* count the '\n'-s to determine the number of options */ list_index = 0; @@ -1054,7 +1059,7 @@ static void lv_chart_draw_x_ticks(lv_obj_t * chart, const lv_area_t * mask) p2.y = p1.y + minor_tick_len; /* minor tick */ /* draw a line at moving x position */ - p2.x = p1.x = x_ofs + (int32_t)(((int32_t)w * i) / num_scale_ticks + 1) - __LV_CHART_AXIS_X_TICK_OFFSET_FIX; + p2.x = p1.x = x_ofs + (int32_t)(((int32_t)w * i) / num_scale_ticks + 1) - LV_CHART_AXIS_X_TICK_OFFSET_FIX; if( i != num_scale_ticks ) lv_draw_line(&p1, &p2, mask, style, opa_scale); @@ -1074,7 +1079,7 @@ static void lv_chart_draw_x_ticks(lv_obj_t * chart, const lv_area_t * mask) ext->x_axis.list_of_values[list_index] != '\0') { /* do not overflow the buffer, but move to the end of the current label */ - if(j < 16) + if(j < LV_CHART_AXIS_TICK_LABEL_MAX_LEN) buf[j++] = ext->x_axis.list_of_values[list_index++]; else list_index++; @@ -1092,7 +1097,7 @@ static void lv_chart_draw_x_ticks(lv_obj_t * chart, const lv_area_t * mask) lv_txt_get_size(&size, buf, style->text.font, style->text.letter_space, style->text.line_space, LV_COORD_MAX, LV_TXT_FLAG_CENTER); /* set the area at some distance of the major tick len under of the tick */ - lv_area_t a = { (p2.x - size.x/2) , (p2.y + __LV_CHART_TO_LABEL_DISTANCE), (p2.x + size.x/2), (p2.y + size.y + __LV_CHART_TO_LABEL_DISTANCE) }; + lv_area_t a = { (p2.x - size.x/2) , (p2.y + LV_CHART_AXIS_TO_LABEL_DISTANCE), (p2.x + size.x/2), (p2.y + size.y + LV_CHART_AXIS_TO_LABEL_DISTANCE) }; lv_draw_label(&a, mask, style, opa_scale, buf, LV_TXT_FLAG_CENTER, NULL); } } @@ -1116,7 +1121,7 @@ static void lv_chart_draw_x_axis_label(lv_obj_t * chart, const lv_area_t * mask) lv_area_t label_area; label_area.x1 = chart->coords.x1 + w/2 - size.x/2; - label_area.y1 = chart->coords.y1 - __LV_CHART_TO_LABEL_DISTANCE - size.y/2; + label_area.y1 = chart->coords.y1 - LV_CHART_AXIS_TO_LABEL_DISTANCE - size.y/2; label_area.x2 = label_area.x1 + size.x; label_area.y2 = label_area.y1 + size.y/2; diff --git a/lv_objx/lv_chart.h b/lv_objx/lv_chart.h index a97fc704e..c6914247f 100644 --- a/lv_objx/lv_chart.h +++ b/lv_objx/lv_chart.h @@ -39,11 +39,7 @@ typedef struct uint16_t start_point; } lv_chart_series_t; -/*Data of chart */ -#define __LV_CHART_TO_LABEL_DISTANCE 4 -#define __LV_CHART_AXIS_X_TICK_OFFSET_FIX 1 -#define __LV_CHART_AXIS_Y_TICK_OFFSET_FIX 0 - +/*Data of axis */ enum { LV_CHART_AXIS_DRAW_LAST_TICK = 0x01 /* draw the last tick */ From 36b212d4dcb50f0abac24747fd6e671a4b166731 Mon Sep 17 00:00:00 2001 From: user-0 Date: Fri, 22 Mar 2019 22:49:09 +0200 Subject: [PATCH 3/7] TUNE: Add support for chart axes ticks and value labels / chart label. --- lv_objx/lv_chart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lv_objx/lv_chart.c b/lv_objx/lv_chart.c index caa31135e..182abeb21 100644 --- a/lv_objx/lv_chart.c +++ b/lv_objx/lv_chart.c @@ -1121,7 +1121,7 @@ static void lv_chart_draw_x_axis_label(lv_obj_t * chart, const lv_area_t * mask) lv_area_t label_area; label_area.x1 = chart->coords.x1 + w/2 - size.x/2; - label_area.y1 = chart->coords.y1 - LV_CHART_AXIS_TO_LABEL_DISTANCE - size.y/2; + label_area.y1 = chart->coords.y1 - LV_CHART_AXIS_TO_LABEL_DISTANCE - (style->text.font->h_px / 4) - size.y/2; label_area.x2 = label_area.x1 + size.x; label_area.y2 = label_area.y1 + size.y/2; From db4f4f0360509930209ba2b56e7ac3ad43937816 Mon Sep 17 00:00:00 2001 From: user-0 Date: Sat, 23 Mar 2019 22:21:02 +0200 Subject: [PATCH 4/7] FIXED/UPDATED: Add support for chart axes ticks and value labels / chart label. --- lv_conf_template.h | 1 + src/lv_objx/lv_chart.c | 107 ++++++++++++++++++----------------------- src/lv_objx/lv_chart.h | 20 +++++--- 3 files changed, 59 insertions(+), 69 deletions(-) diff --git a/lv_conf_template.h b/lv_conf_template.h index 8def85a49..8450b6ea8 100644 --- a/lv_conf_template.h +++ b/lv_conf_template.h @@ -257,6 +257,7 @@ typedef void * lv_obj_user_data_t; /*Declare the type of the user data /*Chart (dependencies: -)*/ #define LV_USE_CHART 1 +#define LV_CHART_AXIS_TICK_LABEL_MAX_LEN 16 /*Table (dependencies: lv_label)*/ #define LV_USE_TABLE 1 diff --git a/src/lv_objx/lv_chart.c b/src/lv_objx/lv_chart.c index 2f9a4d5d5..ac9b2fe1d 100644 --- a/src/lv_objx/lv_chart.c +++ b/src/lv_objx/lv_chart.c @@ -20,13 +20,11 @@ #define LV_CHART_HDIV_DEF 3 #define LV_CHART_VDIV_DEF 5 #define LV_CHART_PNUM_DEF 10 -#define LV_CHART_AXIS_MARGIN 50 -#define LV_CHART_AXIS_TICK_LABEL_MAX_LEN 16 -#define LV_CHART_AXIS_TO_LABEL_DISTANCE 4 -#define LV_CHART_AXIS_MAJOR_TICK_LEN_COE 1/15 -#define LV_CHART_AXIS_MINOR_TICK_LEN_COE 2/3 -#define LV_CHART_AXIS_X_TICK_OFFSET_FIX 1 -#define LV_CHART_AXIS_Y_TICK_OFFSET_FIX 0 +#define LV_CHART_AXIS_TO_LABEL_DISTANCE 4 +#define LV_CHART_AXIS_MAJOR_TICK_LEN_COE 1/15 +#define LV_CHART_AXIS_MINOR_TICK_LEN_COE 2/3 +#define LV_CHART_AXIS_X_TICK_OFFSET_FIX 1 +#define LV_CHART_AXIS_Y_TICK_OFFSET_FIX 0 /********************** * TYPEDEFS @@ -90,6 +88,7 @@ lv_obj_t * lv_chart_create(lv_obj_t * par, const lv_obj_t * copy) ext->series.opa = LV_OPA_COVER; ext->series.dark = LV_OPA_50; ext->series.width = 2; + ext->margin = 0; memset(&ext->x_axis, 0, sizeof(ext->x_axis)); memset(&ext->y_axis, 0, sizeof(ext->y_axis)); @@ -120,8 +119,9 @@ lv_obj_t * lv_chart_create(lv_obj_t * par, const lv_obj_t * copy) ext->vdiv_cnt = ext_copy->vdiv_cnt; ext->point_cnt = ext_copy->point_cnt; ext->series.opa = ext_copy->series.opa; - ext->x_axis = ext_copy->x_axis; - ext->y_axis = ext_copy->y_axis; + ext->margin = ext_copy->margin; + memcpy(&ext->x_axis, &ext_copy->x_axis, sizeof(lv_chart_axis_cfg_t)); + memcpy(&ext->y_axis, &ext_copy->y_axis, sizeof(lv_chart_axis_cfg_t)); /*Refresh the style with new signal function*/ lv_obj_refresh_style(new_chart); @@ -401,15 +401,14 @@ void lv_chart_set_next(lv_obj_t * chart, lv_chart_series_t * ser, lv_coord_t y) } /** - * Set the x-axis label of a chart - * @param chart pointer to a chart object - * @param text pointer to the label text (not copied) + * Set the margin around the chart, used for axes value and labels + * @param margin value of the margin */ -void lv_chart_set_label(lv_obj_t* chart, const char* text) +void lv_chart_set_margin(lv_obj_t* chart, uint16_t margin) { - lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart); - ext->x_axis.label = text; - lv_obj_refresh_ext_size(chart); + lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart); + ext->margin = margin; + lv_obj_refresh_ext_size(chart); } /** @@ -418,32 +417,37 @@ void lv_chart_set_label(lv_obj_t* chart, const char* text) * @param list_of_values list of string values, terminated with \n, except the last * @param num_tick_marks if list_of_values is NULL: total number of ticks per axis * else step in ticks between two value labels - * @param label label to show for this axis (only X) + * @param major_tick_len the length of the major tick, AUTO if 0 + * @param minor_tick_len the length of the minor tick, AUTO if 0 * @param options extra options */ void lv_chart_set_x_ticks( lv_obj_t* chart, const char* list_of_values, uint8_t num_tick_marks, - const char* label, + uint8_t major_tick_len, + uint8_t minor_tick_len, lv_chart_axis_options_t options) { lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart); ext->x_axis.num_tick_marks = num_tick_marks; ext->x_axis.list_of_values = list_of_values; - ext->x_axis.label = label; + ext->x_axis.major_tick_len = major_tick_len; + ext->x_axis.minor_tick_len = minor_tick_len; ext->x_axis.options = options; } void lv_chart_set_y_ticks( lv_obj_t* chart, const char* list_of_values, uint8_t num_tick_marks, - const char* label, + uint8_t major_tick_len, + uint8_t minor_tick_len, lv_chart_axis_options_t options) { lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart); ext->y_axis.num_tick_marks = num_tick_marks; ext->y_axis.list_of_values = list_of_values; - ext->y_axis.label = label; + ext->y_axis.major_tick_len = major_tick_len; + ext->y_axis.minor_tick_len = minor_tick_len; ext->y_axis.options = options; } @@ -565,6 +569,7 @@ static bool lv_chart_design(lv_obj_t * chart, const lv_area_t * mask, lv_design_ static lv_res_t lv_chart_signal(lv_obj_t * chart, lv_signal_t sign, void * param) { lv_res_t res; + lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart); /* Include the ancient signal function */ res = ancestor_signal(chart, sign, param); @@ -572,7 +577,6 @@ static lv_res_t lv_chart_signal(lv_obj_t * chart, lv_signal_t sign, void * param if(sign == LV_SIGNAL_CLEANUP) { lv_coord_t ** datal; - lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart); LV_LL_READ(ext->series_ll, datal) { lv_mem_free(*datal); } @@ -585,15 +589,8 @@ static lv_res_t lv_chart_signal(lv_obj_t * chart, lv_signal_t sign, void * param } buf->type[i] = "lv_chart"; } else if(sign == LV_SIGNAL_REFR_EXT_SIZE) { - /*Provide extra px draw area around the chart if needed*/ - lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart); - - if( (ext->x_axis.list_of_values != NULL || ext->x_axis.num_tick_marks != 0) || - (ext->y_axis.list_of_values != NULL || ext->y_axis.num_tick_marks != 0) || - (ext->x_axis.label == NULL) ) - { /* Reserve some space for axis ticks and labels, predefined by the user */ - chart->ext_size += LV_CHART_AXIS_MARGIN; - } + /*Provide extra px draw area around the chart*/ + chart->ext_size = ext->margin; } return res; @@ -977,8 +974,15 @@ static void lv_chart_draw_y_ticks(lv_obj_t * chart, const lv_area_t * mask) char buf[LV_CHART_AXIS_TICK_LABEL_MAX_LEN+1]; /* up to N symbols per label + null terminator */ /* calculate the size of tick marks */ - major_tick_len = (int32_t)w * LV_CHART_AXIS_MAJOR_TICK_LEN_COE; - minor_tick_len = major_tick_len * LV_CHART_AXIS_MINOR_TICK_LEN_COE; + if(ext->y_axis.major_tick_len == 0) + major_tick_len = (int32_t)w * LV_CHART_AXIS_MAJOR_TICK_LEN_COE; + else + major_tick_len = ext->y_axis.major_tick_len; + + if(ext->y_axis.minor_tick_len == 0) + minor_tick_len = major_tick_len * LV_CHART_AXIS_MINOR_TICK_LEN_COE; + else + minor_tick_len = ext->y_axis.minor_tick_len; /* count the '\n'-s to determine the number of options */ list_index = 0; @@ -1084,8 +1088,15 @@ static void lv_chart_draw_x_ticks(lv_obj_t * chart, const lv_area_t * mask) char buf[LV_CHART_AXIS_TICK_LABEL_MAX_LEN+1]; /* up to N symbols per label + null terminator */ /* calculate the size of tick marks */ - major_tick_len = (int32_t)w * LV_CHART_AXIS_MAJOR_TICK_LEN_COE; - minor_tick_len = major_tick_len * LV_CHART_AXIS_MINOR_TICK_LEN_COE; + if(ext->x_axis.major_tick_len == 0) + major_tick_len = (int32_t)w * LV_CHART_AXIS_MAJOR_TICK_LEN_COE; + else + major_tick_len = ext->x_axis.major_tick_len; + + if(ext->x_axis.minor_tick_len == 0) + minor_tick_len = major_tick_len * LV_CHART_AXIS_MINOR_TICK_LEN_COE; + else + minor_tick_len = ext->x_axis.minor_tick_len; /* count the '\n'-s to determine the number of options */ list_index = 0; @@ -1167,35 +1178,9 @@ static void lv_chart_draw_x_ticks(lv_obj_t * chart, const lv_area_t * mask) } } -static void lv_chart_draw_x_axis_label(lv_obj_t * chart, const lv_area_t * mask) -{ - - lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart); - - if (ext->x_axis.label != NULL) - { - const lv_style_t * style = lv_obj_get_style(chart); - lv_opa_t opa_scale = lv_obj_get_opa_scale(chart); - lv_coord_t w = lv_obj_get_width(chart); - - lv_point_t size; - lv_txt_get_size(&size, ext->x_axis.label, style->text.font, style->text.letter_space, style->text.line_space, LV_COORD_MAX, LV_TXT_FLAG_CENTER); - - lv_area_t label_area; - label_area.x1 = chart->coords.x1 + w/2 - size.x/2; - label_area.y1 = chart->coords.y1 - LV_CHART_AXIS_TO_LABEL_DISTANCE - (style->text.font->h_px / 4) - size.y/2; - label_area.x2 = label_area.x1 + size.x; - label_area.y2 = label_area.y1 + size.y/2; - - lv_draw_label(&label_area, mask, style, opa_scale, ext->x_axis.label, LV_TXT_FLAG_CENTER, NULL); - } -} - static void lv_chart_draw_axes(lv_obj_t * chart, const lv_area_t * mask) { lv_chart_draw_y_ticks(chart, mask); lv_chart_draw_x_ticks(chart, mask); - lv_chart_draw_x_axis_label(chart, mask); } - #endif diff --git a/src/lv_objx/lv_chart.h b/src/lv_objx/lv_chart.h index 9297f600c..49c4983bd 100644 --- a/src/lv_objx/lv_chart.h +++ b/src/lv_objx/lv_chart.h @@ -62,8 +62,9 @@ typedef struct { const char* list_of_values; uint8_t num_tick_marks; - const char* label; lv_chart_axis_options_t options; + uint8_t major_tick_len; + uint8_t minor_tick_len; } lv_chart_axis_cfg_t; /*Data of chart */ @@ -80,6 +81,7 @@ typedef struct lv_chart_type_t type; /*Line, column or point chart (from 'lv_chart_type_t')*/ lv_chart_axis_cfg_t y_axis; lv_chart_axis_cfg_t x_axis; + uint16_t margin; struct { lv_coord_t width; /*Line width or point radius*/ uint8_t num; /*Number of data lines in dl_ll*/ @@ -211,11 +213,10 @@ static inline void lv_chart_set_style(lv_obj_t *chart, lv_style_t *style) } /** - * Set the x-axis label of a chart - * @param chart pointer to a chart object - * @param text pointer to the label text (not copied) + * Set the margin around the chart, used for axes value and labels + * @param margin value of the margin */ -void lv_chart_set_label(lv_obj_t* chart, const char* text); +void lv_chart_set_margin(lv_obj_t* chart, uint16_t margin); /** * Set the x/y-axis ticks of a chart @@ -223,19 +224,22 @@ void lv_chart_set_label(lv_obj_t* chart, const char* text); * @param list_of_values list of string values, terminated with \n, except the last * @param num_tick_marks if list_of_values is NULL: total number of ticks per axis * else step in ticks between two value labels - * @param label label to show for this axis (only X) + * @param major_tick_len the length of the major tick, AUTO if 0 + * @param minor_tick_len the length of the minor tick, AUTO if 0 * @param options extra options */ void lv_chart_set_x_ticks( lv_obj_t* chart, const char* list_of_values, uint8_t num_tick_marks, - const char* label, + uint8_t major_tick_len, + uint8_t minor_tick_len, lv_chart_axis_options_t options); void lv_chart_set_y_ticks( lv_obj_t* chart, const char* list_of_values, uint8_t num_tick_marks, - const char* label, + uint8_t major_tick_len, + uint8_t minor_tick_len, lv_chart_axis_options_t options); /*===================== From 81696b85d06faed52c0b4a12d10bd4963f315de9 Mon Sep 17 00:00:00 2001 From: user-0 Date: Sat, 23 Mar 2019 23:59:12 +0200 Subject: [PATCH 5/7] FIXED: Add support for chart axes ticks and value labels / chart label. --- src/lv_objx/lv_chart.c | 11 +++++++++++ src/lv_objx/lv_chart.h | 8 ++++++++ 2 files changed, 19 insertions(+) diff --git a/src/lv_objx/lv_chart.c b/src/lv_objx/lv_chart.c index ac9b2fe1d..3a3f28343 100644 --- a/src/lv_objx/lv_chart.c +++ b/src/lv_objx/lv_chart.c @@ -523,6 +523,17 @@ void lv_chart_refresh(lv_obj_t * chart) lv_obj_invalidate(chart); } +/** + * Set the margin around the chart, used for axes value and labels + * @param chart pointer to an chart object + * @param return margin value of the margin + */ +uint16_t lv_chart_get_margin(lv_obj_t* chart) +{ + lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart); + return ext->margin; +} + /********************** * STATIC FUNCTIONS **********************/ diff --git a/src/lv_objx/lv_chart.h b/src/lv_objx/lv_chart.h index 49c4983bd..23e20daf2 100644 --- a/src/lv_objx/lv_chart.h +++ b/src/lv_objx/lv_chart.h @@ -214,6 +214,7 @@ static inline void lv_chart_set_style(lv_obj_t *chart, lv_style_t *style) /** * Set the margin around the chart, used for axes value and labels + * @param chart pointer to an chart object * @param margin value of the margin */ void lv_chart_set_margin(lv_obj_t* chart, uint16_t margin); @@ -291,6 +292,13 @@ static inline lv_style_t* lv_chart_get_style(const lv_obj_t *chart) return lv_obj_get_style(chart); } +/** + * Set the margin around the chart, used for axes value and labels + * @param chart pointer to an chart object + * @param return margin value of the margin + */ +uint16_t lv_chart_get_margin(lv_obj_t* chart); + /*===================== * Other functions *====================*/ From 36b47ba98d3e7ee770944279a8c6b601d4f3e7fb Mon Sep 17 00:00:00 2001 From: user-0 Date: Sun, 24 Mar 2019 00:07:16 +0200 Subject: [PATCH 6/7] FIX margin get function documentation --- src/lv_objx/lv_chart.c | 4 ++-- src/lv_objx/lv_chart.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/lv_objx/lv_chart.c b/src/lv_objx/lv_chart.c index 3a3f28343..43b7cf1d6 100644 --- a/src/lv_objx/lv_chart.c +++ b/src/lv_objx/lv_chart.c @@ -524,9 +524,9 @@ void lv_chart_refresh(lv_obj_t * chart) } /** - * Set the margin around the chart, used for axes value and labels + * Get the margin around the chart, used for axes value and labels * @param chart pointer to an chart object - * @param return margin value of the margin + * @param return value of the margin */ uint16_t lv_chart_get_margin(lv_obj_t* chart) { diff --git a/src/lv_objx/lv_chart.h b/src/lv_objx/lv_chart.h index 23e20daf2..3448c2c7f 100644 --- a/src/lv_objx/lv_chart.h +++ b/src/lv_objx/lv_chart.h @@ -293,9 +293,9 @@ static inline lv_style_t* lv_chart_get_style(const lv_obj_t *chart) } /** - * Set the margin around the chart, used for axes value and labels + * Get the margin around the chart, used for axes value and labels * @param chart pointer to an chart object - * @param return margin value of the margin + * @param return value of the margin */ uint16_t lv_chart_get_margin(lv_obj_t* chart); From a402f8258d64c223bd7ab825ca4f431a1c693cc2 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Sun, 24 Mar 2019 07:31:56 +0100 Subject: [PATCH 7/7] update lv_conf_checker.h --- scripts/lv_conf_checker.py | 2 +- src/lv_conf_checker.h | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/scripts/lv_conf_checker.py b/scripts/lv_conf_checker.py index 04fcb9f72..a16b36353 100644 --- a/scripts/lv_conf_checker.py +++ b/scripts/lv_conf_checker.py @@ -5,7 +5,7 @@ Generates a chechker file for lv_conf.h from lv_conf_templ.h define all the not import re -fin = open("../templates/lv_conf_templ.h", "r"); +fin = open("../lv_conf_template.h", "r"); fout = open("../src/lv_conf_checker.h", "w"); diff --git a/src/lv_conf_checker.h b/src/lv_conf_checker.h index 8fe96eb7f..e1de81219 100644 --- a/src/lv_conf_checker.h +++ b/src/lv_conf_checker.h @@ -439,6 +439,9 @@ #ifndef LV_USE_CHART #define LV_USE_CHART 1 #endif +#ifndef LV_CHART_AXIS_TICK_LABEL_MAX_LEN +#define LV_CHART_AXIS_TICK_LABEL_MAX_LEN 16 +#endif /*Table (dependencies: lv_label)*/ #ifndef LV_USE_TABLE