diff --git a/src/lv_objx/lv_calendar.c b/src/lv_objx/lv_calendar.c index bef7f7b99..510974d21 100644 --- a/src/lv_objx/lv_calendar.c +++ b/src/lv_objx/lv_calendar.c @@ -487,6 +487,8 @@ static lv_res_t lv_calendar_signal(lv_obj_t * calendar, lv_signal_t sign, void * } ext->pressed_date.year = 0; + ext->pressed_date.month = 0; + ext->pressed_date.day = 0; } else if(calculate_touched_day(calendar, &p)) { if(ext->btn_pressing != 0) lv_obj_invalidate(calendar); ext->btn_pressing = 0; @@ -494,10 +496,11 @@ static lv_res_t lv_calendar_signal(lv_obj_t * calendar, lv_signal_t sign, void * if(ext->btn_pressing != 0) lv_obj_invalidate(calendar); ext->btn_pressing = 0; ext->pressed_date.year = 0; + ext->pressed_date.month = 0; + ext->pressed_date.day = 0; } } else if(sign == LV_SIGNAL_PRESS_LOST) { lv_calendar_ext_t * ext = lv_obj_get_ext_attr(calendar); - ext->pressed_date.year = 0; ext->btn_pressing = 0; lv_obj_invalidate(calendar); @@ -522,7 +525,6 @@ static lv_res_t lv_calendar_signal(lv_obj_t * calendar, lv_signal_t sign, void * if(res != LV_RES_OK) return res; } - ext->pressed_date.year = 0; ext->btn_pressing = 0; lv_obj_invalidate(calendar); } else if(sign == LV_SIGNAL_CONTROL) { diff --git a/src/lv_objx/lv_chart.c b/src/lv_objx/lv_chart.c index 92b4a0b8f..d12d8fef7 100644 --- a/src/lv_objx/lv_chart.c +++ b/src/lv_objx/lv_chart.c @@ -9,6 +9,7 @@ #include "lv_chart.h" #if LV_USE_CHART != 0 +#include "../lv_core/lv_refr.h" #include "../lv_draw/lv_draw.h" #include "../lv_themes/lv_theme.h" @@ -42,6 +43,9 @@ 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_areas(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 void lv_chart_inv_lines(lv_obj_t * chart, uint16_t i); +static void lv_chart_inv_points(lv_obj_t * chart, uint16_t i); +static void lv_chart_inv_cols(lv_obj_t * chart, uint16_t i); /********************** * STATIC VARIABLES @@ -79,15 +83,17 @@ lv_obj_t * lv_chart_create(lv_obj_t * par, const lv_obj_t * copy) if(ext == NULL) return NULL; lv_ll_init(&ext->series_ll, sizeof(lv_chart_series_t)); - ext->series.num = 0; - ext->ymin = LV_CHART_YMIN_DEF; - ext->ymax = LV_CHART_YMAX_DEF; - ext->hdiv_cnt = LV_CHART_HDIV_DEF; - ext->vdiv_cnt = LV_CHART_VDIV_DEF; - ext->point_cnt = LV_CHART_PNUM_DEF; - ext->type = LV_CHART_TYPE_LINE; - ext->series.opa = LV_OPA_COVER; - ext->series.dark = LV_OPA_50; + + ext->series.num = 0; + ext->ymin = LV_CHART_YMIN_DEF; + ext->ymax = LV_CHART_YMAX_DEF; + ext->hdiv_cnt = LV_CHART_HDIV_DEF; + ext->vdiv_cnt = LV_CHART_VDIV_DEF; + ext->point_cnt = LV_CHART_PNUM_DEF; + ext->type = LV_CHART_TYPE_LINE; + ext->update_mode = LV_CHART_UPDATE_MODE_SHIFT; + 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)); @@ -155,7 +161,6 @@ lv_chart_series_t * lv_chart_add_series(lv_obj_t * chart, lv_color_t color) if(ser == NULL) return NULL; ser->color = color; - ser->points = lv_mem_alloc(sizeof(lv_coord_t) * ext->point_cnt); lv_mem_assert(ser->points); if(ser->points == NULL) { @@ -392,13 +397,36 @@ void lv_chart_set_points(lv_obj_t * chart, lv_chart_series_t * ser, lv_coord_t y */ void lv_chart_set_next(lv_obj_t * chart, lv_chart_series_t * ser, lv_coord_t y) { - lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart); + lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart); + if(ext->update_mode == LV_CHART_UPDATE_MODE_SHIFT) { + ser->points[ser->start_point] = y; /*This was the place of the former left most value, after shifting it is the rightmost*/ + ser->start_point = (ser->start_point + 1) % ext->point_cnt; + lv_chart_refresh(chart); + } else if(ext->update_mode == LV_CHART_UPDATE_MODE_CIRCULAR) { + ser->points[ser->start_point] = y; - ser->points[ser->start_point] = - y; /*This was the place of the former left most value, after shifting it is the rightmost*/ - ser->start_point = (ser->start_point + 1) % ext->point_cnt; + if(ext->type & LV_CHART_TYPE_LINE) lv_chart_inv_lines(chart, ser->start_point); + if(ext->type & LV_CHART_TYPE_COLUMN) lv_chart_inv_cols(chart, ser->start_point); + if(ext->type & LV_CHART_TYPE_POINT) lv_chart_inv_points(chart, ser->start_point); + if(ext->type & LV_CHART_TYPE_VERTICAL_LINE) lv_chart_inv_lines(chart, ser->start_point); + if(ext->type & LV_CHART_TYPE_AREA) lv_chart_inv_lines(chart, ser->start_point); - lv_chart_refresh(chart); + ser->start_point = (ser->start_point + 1) % ext->point_cnt;/*update the x for next incoming y*/ + } +} + +/** + * Set update mode of the chart object. + * @param chart pointer to a chart object + * @param update mode + */ +void lv_chart_set_update_mode(lv_obj_t * chart, lv_chart_update_mode_t update_mode) +{ + lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart); + if(ext->update_mode == update_mode) return; + + ext->update_mode = update_mode; + lv_obj_invalidate(chart); } /** @@ -705,21 +733,24 @@ static void lv_chart_draw_lines(lv_obj_t * chart, const lv_area_t * mask) { style.line.color = ser->color; + lv_coord_t start_point = ext->update_mode == LV_CHART_UPDATE_MODE_SHIFT ? ser->start_point : 0; + p1.x = 0 + x_ofs; p2.x = 0 + x_ofs; - p_prev = ser->start_point; + p_prev = start_point; y_tmp = (int32_t)((int32_t)ser->points[p_prev] - ext->ymin) * h; y_tmp = y_tmp / (ext->ymax - ext->ymin); p2.y = h - y_tmp + y_ofs; + for(i = 1; i < ext->point_cnt; i++) { p1.x = p2.x; p1.y = p2.y; p2.x = ((w * i) / (ext->point_cnt - 1)) + x_ofs; - p_act = (ser->start_point + i) % ext->point_cnt; + p_act = (start_point + i) % ext->point_cnt; y_tmp = (int32_t)((int32_t)ser->points[p_act] - ext->ymin) * h; y_tmp = y_tmp / (ext->ymax - ext->ymin); @@ -762,8 +793,10 @@ static void lv_chart_draw_points(lv_obj_t * chart, const lv_area_t * mask) style_point.body.radius = ext->series.width; /*Go through all data lines*/ - LV_LL_READ_BACK(ext->series_ll, ser) - { + + LV_LL_READ_BACK(ext->series_ll, ser) { + lv_coord_t start_point = ext->update_mode == LV_CHART_UPDATE_MODE_SHIFT ? ser->start_point : 0; + style_point.body.main_color = ser->color; style_point.body.grad_color = lv_color_mix(LV_COLOR_BLACK, ser->color, ext->series.dark); @@ -771,9 +804,11 @@ static void lv_chart_draw_points(lv_obj_t * chart, const lv_area_t * mask) cir_a.x1 = ((w * i) / (ext->point_cnt - 1)) + x_ofs; cir_a.x2 = cir_a.x1 + style_point.body.radius; cir_a.x1 -= style_point.body.radius; - p_act = (ser->start_point + i) % ext->point_cnt; - y_tmp = (int32_t)((int32_t)ser->points[p_act] - ext->ymin) * h; - y_tmp = y_tmp / (ext->ymax - ext->ymin); + + p_act = (start_point + i) % ext->point_cnt; + y_tmp = (int32_t)((int32_t) ser->points[p_act] - ext->ymin) * h; + y_tmp = y_tmp / (ext->ymax - ext->ymin); + cir_a.y1 = h - y_tmp + y_ofs; cir_a.y2 = cir_a.y1 + style_point.body.radius; cir_a.y1 -= style_point.body.radius; @@ -822,18 +857,20 @@ static void lv_chart_draw_cols(lv_obj_t * chart, const lv_area_t * mask) x_act += chart->coords.x1 + x_ofs; /*Draw the current point of all data line*/ - LV_LL_READ_BACK(ext->series_ll, ser) - { + LV_LL_READ_BACK(ext->series_ll, ser) { + lv_coord_t start_point = ext->update_mode == LV_CHART_UPDATE_MODE_SHIFT ? ser->start_point : 0; + rects.body.main_color = ser->color; rects.body.grad_color = lv_color_mix(LV_COLOR_BLACK, ser->color, ext->series.dark); col_a.x1 = x_act; col_a.x2 = col_a.x1 + col_w; x_act += col_w; - lv_coord_t p_act = (ser->start_point + i) % ext->point_cnt; - y_tmp = (int32_t)((int32_t)ser->points[p_act] - ext->ymin) * h; - y_tmp = y_tmp / (ext->ymax - ext->ymin); - col_a.y1 = h - y_tmp + chart->coords.y1; + + lv_coord_t p_act = (start_point + i) % ext->point_cnt; + y_tmp = (int32_t)((int32_t) ser->points[p_act] - ext->ymin) * h; + y_tmp = y_tmp / (ext->ymax - ext->ymin); + col_a.y1 = h - y_tmp + chart->coords.y1; mask_ret = lv_area_intersect(&col_mask, mask, &col_a); if(mask_ret != false && ser->points[p_act] != LV_CHART_POINT_DEF) { @@ -861,7 +898,8 @@ static void lv_chart_draw_vertical_lines(lv_obj_t * chart, const lv_area_t * mas uint16_t i; lv_point_t p1; lv_point_t p2; - lv_coord_t h = lv_obj_get_height(chart); + lv_coord_t p_act; + lv_coord_t h = lv_obj_get_height(chart); lv_coord_t x_ofs = chart->coords.x1; lv_coord_t y_ofs = chart->coords.y1; int32_t y_tmp; @@ -873,8 +911,8 @@ static void lv_chart_draw_vertical_lines(lv_obj_t * chart, const lv_area_t * mas style.line.width = ext->series.width; /*Go through all data lines*/ - LV_LL_READ_BACK(ext->series_ll, ser) - { + LV_LL_READ_BACK(ext->series_ll, ser) { + lv_coord_t start_point = ext->update_mode == LV_CHART_UPDATE_MODE_SHIFT ? ser->start_point : 0; style.line.color = ser->color; p1.x = 0 + x_ofs; @@ -884,9 +922,11 @@ static void lv_chart_draw_vertical_lines(lv_obj_t * chart, const lv_area_t * mas p2.y = h - y_tmp + y_ofs; p1.y = p2.y; - for(i = 0; i < ext->point_cnt; i++) { + for(i = 0; i < ext->point_cnt; i++) + { + p_act = (start_point + i) % ext->point_cnt; - y_tmp = (int32_t)((int32_t)ser->points[i] - ext->ymin) * h; + y_tmp = (int32_t)((int32_t) ser->points[p_act] - ext->ymin) * h; y_tmp = y_tmp / (ext->ymax - ext->ymin); p2.y = h - y_tmp + y_ofs; @@ -894,11 +934,11 @@ static void lv_chart_draw_vertical_lines(lv_obj_t * chart, const lv_area_t * mas p2.x++; } - if(ser->points[i] != LV_CHART_POINT_DEF) { + if(ser->points[p_act] != LV_CHART_POINT_DEF) { lv_draw_line(&p1, &p2, mask, &style, opa_scale); } - p2.x = ((w * i) / (ext->point_cnt - 1)) + x_ofs; + p2.x = ((w * p_act) / (ext->point_cnt - 1)) + x_ofs; p1.x = p2.x; p1.y = p2.y; } @@ -929,8 +969,8 @@ static void lv_chart_draw_areas(lv_obj_t * chart, const lv_area_t * mask) lv_style_copy(&style, &lv_style_plain); /*Go through all data lines*/ - LV_LL_READ_BACK(ext->series_ll, ser) - { + LV_LL_READ_BACK(ext->series_ll, ser) { + lv_coord_t start_point = ext->update_mode == LV_CHART_UPDATE_MODE_SHIFT ? ser->start_point : 0; style.body.main_color = ser->color; p1.x = 0 + x_ofs; @@ -945,8 +985,8 @@ static void lv_chart_draw_areas(lv_obj_t * chart, const lv_area_t * mask) p1.x = p2.x; p1.y = p2.y; - p2.x = ((w * i) / (ext->point_cnt - 1)) + x_ofs; - p_act = (ser->start_point + i) % ext->point_cnt; + p_act = (start_point + i) % ext->point_cnt; + p2.x = ((w * p_act) / (ext->point_cnt - 1)) + x_ofs; y_tmp = (int32_t)((int32_t)ser->points[p_act] - ext->ymin) * h; y_tmp = y_tmp / (ext->ymax - ext->ymin); @@ -1199,4 +1239,80 @@ 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); } + +/** + * invalid area of the new line data lines on a chart + * @param obj pointer to chart object + */ +static void lv_chart_inv_lines(lv_obj_t * chart, uint16_t i) +{ + lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart); + + lv_coord_t w = lv_obj_get_width(chart); + lv_coord_t x_ofs = chart->coords.x1; + + if(i < ext->point_cnt) { + lv_area_t coords; + lv_obj_get_coords(chart, &coords); + if(i < ext->point_cnt - 1) { + coords.x1 = ((w * i) / (ext->point_cnt - 1)) + x_ofs - ext->series.width; + coords.x2 = ((w * (i + 1)) / (ext->point_cnt - 1)) + x_ofs + ext->series.width; + lv_inv_area(lv_obj_get_disp(chart), &coords); + } + + if(i > 0) { + coords.x1 = ((w * (i - 1)) / (ext->point_cnt - 1)) + x_ofs - ext->series.width; + coords.x2 = ((w * i) / (ext->point_cnt - 1)) + x_ofs + ext->series.width; + lv_inv_area(lv_obj_get_disp(chart), &coords); + } + } +} + +/** + * invalid area of the new point data lines on a chart + * @param chart pointer to chart object + * @param mask mask, inherited from the design function + */ +static void lv_chart_inv_points(lv_obj_t * chart, uint16_t i) +{ + lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart); + + lv_area_t cir_a; + lv_coord_t w = lv_obj_get_width(chart); + lv_coord_t x_ofs = chart->coords.x1; + + lv_obj_get_coords(chart, &cir_a); + cir_a.x1 = ((w * i) / (ext->point_cnt - 1)) + x_ofs; + cir_a.x2 = cir_a.x1 + ext->series.width; + cir_a.x1 -= ext->series.width; + + lv_inv_area(lv_obj_get_disp(chart), &cir_a); +} + +/** + * invalid area of the new column data lines on a chart + * @param chart pointer to chart object + * @param mask mask, inherited from the design function + */ +static void lv_chart_inv_cols(lv_obj_t * chart, uint16_t i) +{ + lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart); + + lv_area_t col_a; + lv_coord_t w = lv_obj_get_width(chart); + lv_coord_t col_w = w / ((ext->series.num + 1) * ext->point_cnt); /* Suppose + 1 series as separator*/ + lv_coord_t x_ofs = col_w / 2; /*Shift with a half col.*/ + + lv_coord_t x_act; + + x_act = (int32_t)((int32_t) w * i) / ext->point_cnt; + x_act += chart->coords.x1 + x_ofs; + + lv_obj_get_coords(chart, &col_a); + col_a.x1 = x_act; + col_a.x2 = col_a.x1 + col_w; + + lv_inv_area(lv_obj_get_disp(chart), &col_a); +} + #endif diff --git a/src/lv_objx/lv_chart.h b/src/lv_objx/lv_chart.h index 6c76c3c24..c88961ebb 100644 --- a/src/lv_objx/lv_chart.h +++ b/src/lv_objx/lv_chart.h @@ -44,6 +44,14 @@ enum { }; typedef uint8_t lv_chart_type_t; +/*Chart update mode*/ +enum +{ + LV_CHART_UPDATE_MODE_SHIFT, + LV_CHART_UPDATE_MODE_CIRCULAR, +}; +typedef uint8_t lv_chart_update_mode_t; + typedef struct { lv_coord_t * points; @@ -81,6 +89,7 @@ typedef struct lv_chart_axis_cfg_t y_axis; lv_chart_axis_cfg_t x_axis; uint16_t margin; + uint8_t update_mode: 1; struct { lv_coord_t width; /*Line width or point radius*/ @@ -201,6 +210,13 @@ void lv_chart_set_points(lv_obj_t * chart, lv_chart_series_t * ser, lv_coord_t * */ void lv_chart_set_next(lv_obj_t * chart, lv_chart_series_t * ser, lv_coord_t y); +/** + * Set update mode of the chart object. + * @param chart pointer to a chart object + * @param update mode + */ +void lv_chart_set_update_mode(lv_obj_t * chart, lv_chart_update_mode_t update_mode); + /** * Set the style of a chart * @param chart pointer to a chart object