1 #include "../../lv_examples.h"
2 
3 #if LV_USE_CHART && LV_DRAW_SW_COMPLEX && LV_BUILD_EXAMPLES
4 #include "../../../lvgl_private.h"
5 
6 static void hook_division_lines(lv_event_t * e);
7 static void add_faded_area(lv_event_t * e);
8 static void draw_event_cb(lv_event_t * e);
9 
10 /**
11  * Add a faded area effect to the line chart and make some division lines ticker
12  */
lv_example_chart_5(void)13 void lv_example_chart_5(void)
14 {
15     /*Create a chart*/
16     lv_obj_t * chart = lv_chart_create(lv_screen_active());
17     lv_chart_set_type(chart, LV_CHART_TYPE_LINE);   /*Show lines and points too*/
18     lv_obj_set_size(chart, 200, 150);
19     lv_obj_set_style_pad_all(chart, 0, 0);
20     lv_obj_set_style_radius(chart, 0, 0);
21     lv_obj_center(chart);
22 
23     lv_chart_set_div_line_count(chart, 5, 7);
24 
25     lv_obj_add_event_cb(chart, draw_event_cb, LV_EVENT_DRAW_TASK_ADDED, NULL);
26     lv_obj_add_flag(chart, LV_OBJ_FLAG_SEND_DRAW_TASK_EVENTS);
27 
28     lv_chart_series_t * ser = lv_chart_add_series(chart, lv_palette_main(LV_PALETTE_RED), LV_CHART_AXIS_PRIMARY_Y);
29 
30     uint32_t i;
31     for(i = 0; i < 10; i++) {
32         lv_chart_set_next_value(chart, ser, lv_rand(10, 80));
33     }
34 }
35 
draw_event_cb(lv_event_t * e)36 static void draw_event_cb(lv_event_t * e)
37 {
38     lv_draw_task_t * draw_task = lv_event_get_draw_task(e);
39     lv_draw_dsc_base_t * base_dsc = lv_draw_task_get_draw_dsc(draw_task);
40 
41     if(base_dsc->part == LV_PART_ITEMS && lv_draw_task_get_type(draw_task) == LV_DRAW_TASK_TYPE_LINE) {
42         add_faded_area(e);
43 
44     }
45     /*Hook the division lines too*/
46     if(base_dsc->part == LV_PART_MAIN && lv_draw_task_get_type(draw_task) == LV_DRAW_TASK_TYPE_LINE) {
47         hook_division_lines(e);
48     }
49 }
50 
add_faded_area(lv_event_t * e)51 static void add_faded_area(lv_event_t * e)
52 {
53     lv_obj_t * obj = lv_event_get_target(e);
54     lv_area_t coords;
55     lv_obj_get_coords(obj, &coords);
56 
57     lv_draw_task_t * draw_task = lv_event_get_draw_task(e);
58     lv_draw_dsc_base_t * base_dsc = lv_draw_task_get_draw_dsc(draw_task);
59 
60     const lv_chart_series_t * ser = lv_chart_get_series_next(obj, NULL);
61     lv_color_t ser_color = lv_chart_get_series_color(obj, ser);
62 
63     /*Draw a triangle below the line witch some opacity gradient*/
64     lv_draw_line_dsc_t * draw_line_dsc = lv_draw_task_get_draw_dsc(draw_task);
65     lv_draw_triangle_dsc_t tri_dsc;
66 
67     lv_draw_triangle_dsc_init(&tri_dsc);
68     tri_dsc.p[0].x = draw_line_dsc->p1.x;
69     tri_dsc.p[0].y = draw_line_dsc->p1.y;
70     tri_dsc.p[1].x = draw_line_dsc->p2.x;
71     tri_dsc.p[1].y = draw_line_dsc->p2.y;
72     tri_dsc.p[2].x = draw_line_dsc->p1.y < draw_line_dsc->p2.y ? draw_line_dsc->p1.x : draw_line_dsc->p2.x;
73     tri_dsc.p[2].y = LV_MAX(draw_line_dsc->p1.y, draw_line_dsc->p2.y);
74     tri_dsc.bg_grad.dir = LV_GRAD_DIR_VER;
75 
76     int32_t full_h = lv_obj_get_height(obj);
77     int32_t fract_uppter = (int32_t)(LV_MIN(draw_line_dsc->p1.y, draw_line_dsc->p2.y) - coords.y1) * 255 / full_h;
78     int32_t fract_lower = (int32_t)(LV_MAX(draw_line_dsc->p1.y, draw_line_dsc->p2.y) - coords.y1) * 255 / full_h;
79     tri_dsc.bg_grad.stops[0].color = ser_color;
80     tri_dsc.bg_grad.stops[0].opa = 255 - fract_uppter;
81     tri_dsc.bg_grad.stops[0].frac = 0;
82     tri_dsc.bg_grad.stops[1].color = ser_color;
83     tri_dsc.bg_grad.stops[1].opa = 255 - fract_lower;
84     tri_dsc.bg_grad.stops[1].frac = 255;
85 
86     lv_draw_triangle(base_dsc->layer, &tri_dsc);
87 
88     /*Draw rectangle below the triangle*/
89     lv_draw_rect_dsc_t rect_dsc;
90     lv_draw_rect_dsc_init(&rect_dsc);
91     rect_dsc.bg_grad.dir = LV_GRAD_DIR_VER;
92     rect_dsc.bg_grad.stops[0].color = ser_color;
93     rect_dsc.bg_grad.stops[0].frac = 0;
94     rect_dsc.bg_grad.stops[0].opa = 255 - fract_lower;
95     rect_dsc.bg_grad.stops[1].color = ser_color;
96     rect_dsc.bg_grad.stops[1].frac = 255;
97     rect_dsc.bg_grad.stops[1].opa = 0;
98 
99     lv_area_t rect_area;
100     rect_area.x1 = (int32_t)draw_line_dsc->p1.x;
101     rect_area.x2 = (int32_t)draw_line_dsc->p2.x - 1;
102     rect_area.y1 = (int32_t)LV_MAX(draw_line_dsc->p1.y, draw_line_dsc->p2.y) - 1;
103     rect_area.y2 = (int32_t)coords.y2;
104     lv_draw_rect(base_dsc->layer, &rect_dsc, &rect_area);
105 }
106 
hook_division_lines(lv_event_t * e)107 static void hook_division_lines(lv_event_t * e)
108 {
109     lv_draw_task_t * draw_task = lv_event_get_draw_task(e);
110     lv_draw_dsc_base_t * base_dsc = lv_draw_task_get_draw_dsc(draw_task);
111     lv_draw_line_dsc_t * line_dsc = lv_draw_task_get_draw_dsc(draw_task);
112 
113     /*Vertical line*/
114     if(line_dsc->p1.x == line_dsc->p2.x) {
115         line_dsc->color  = lv_palette_lighten(LV_PALETTE_GREY, 1);
116         if(base_dsc->id1 == 3) {
117             line_dsc->width = 2;
118             line_dsc->dash_gap = 0;
119             line_dsc->dash_width = 0;
120         }
121         else {
122             line_dsc->width = 1;
123             line_dsc->dash_gap = 6;
124             line_dsc->dash_width = 6;
125         }
126     }
127     /*Horizontal line*/
128     else {
129         if(base_dsc->id1 == 2) {
130             line_dsc->width  = 2;
131             line_dsc->dash_gap  = 0;
132             line_dsc->dash_width  = 0;
133         }
134         else {
135             line_dsc->width = 2;
136             line_dsc->dash_gap  = 6;
137             line_dsc->dash_width  = 6;
138         }
139 
140         if(base_dsc->id1 == 1  || base_dsc->id1 == 3) {
141             line_dsc->color  = lv_palette_main(LV_PALETTE_GREEN);
142         }
143         else {
144             line_dsc->color  = lv_palette_lighten(LV_PALETTE_GREY, 1);
145         }
146     }
147 }
148 
149 #endif
150