1 #if LV_BUILD_TEST
2 #include "../lvgl.h"
3 #include "../../lvgl_private.h"
4 
5 #include "unity/unity.h"
6 
7 #include "lv_test_indev.h"
8 
9 static lv_obj_t * g_active_screen = NULL;
10 static lv_obj_t * g_bar = NULL;
11 
setUp(void)12 void setUp(void)
13 {
14     g_active_screen = lv_screen_active();
15     g_bar = lv_bar_create(g_active_screen);
16 }
17 
tearDown(void)18 void tearDown(void)
19 {
20     lv_obj_clean(g_active_screen);
21 }
22 
test_bar_should_have_valid_default_attributes(void)23 void test_bar_should_have_valid_default_attributes(void)
24 {
25     TEST_ASSERT_EQUAL(0, lv_bar_get_min_value(g_bar));
26     TEST_ASSERT_EQUAL(100, lv_bar_get_max_value(g_bar));
27     TEST_ASSERT_EQUAL(LV_BAR_MODE_NORMAL, lv_bar_get_mode(g_bar));
28 }
29 
30 /*
31  * Bar has two parts, main and indicator, coordinates of the latter are
32  * calculated based on:
33  * - Bar size
34  * - Bar (main part) padding
35  * - Bar value
36  * - Bar coordinates
37  * - Bar base direction
38  * See Boxing model in docs for reference.
39  *
40  * Bar properties assumed:
41  * - mode: LV_BAR_MODE_NORMAL
42  * - min value: 0
43  * - max value: 100
44  * - base direction: LTR
45  */
test_bar_should_update_indicator_right_coordinate_based_on_bar_value(void)46 void test_bar_should_update_indicator_right_coordinate_based_on_bar_value(void)
47 {
48     lv_bar_t * bar_ptr = (lv_bar_t *) g_bar;
49 
50     static lv_style_t bar_style;
51 
52     const int32_t style_padding = 5u;
53     const int32_t bar_width = 200u;
54     const int32_t bar_height = 20u;
55     int32_t bar_value = 10u;
56 
57     lv_style_init(&bar_style);
58     lv_style_set_pad_all(&bar_style, style_padding);
59 
60     /* Setup new style */
61     lv_obj_remove_style_all(g_bar);
62     lv_obj_add_style(g_bar, &bar_style, LV_PART_MAIN);
63 
64     /* Set properties */
65     lv_obj_set_size(g_bar, bar_width, bar_height);
66     lv_bar_set_value(g_bar, bar_value, LV_ANIM_OFF);
67 
68     /* FIXME: Remove wait */
69     lv_test_indev_wait(50);
70 
71     int32_t actual_coord = lv_area_get_width(&bar_ptr->indic_area);
72 
73     /* Calculate bar indicator right coordinate, using rule of 3 */
74     int32_t bar_max_value = lv_bar_get_max_value(g_bar);
75     int32_t indicator_part_width = lv_obj_get_content_width(g_bar);
76 
77     int32_t expected_coord = (bar_value * indicator_part_width) / bar_max_value;
78     /* NOTE: Add 1 to calculation because the coordinates start at 0 */
79     expected_coord += 1;
80 
81     TEST_ASSERT_EQUAL_INT32(expected_coord, actual_coord);
82 }
83 
84 /*
85  * Bar has two parts, main and indicator, coordinates of the latter are
86  * calculated based on:
87  * - Bar size
88  * - Bar (main part) padding
89  * - Bar value
90  * - Bar coordinates
91  * - Bar base direction
92  * See Boxing model in docs for reference.
93  *
94  * Bar properties assumed:
95  * - mode: LV_BAR_MODE_NORMAL
96  * - min value: 0
97  * - max value: 100
98  */
test_bar_rtl_should_update_indicator_left_coordinate_based_on_bar_value(void)99 void test_bar_rtl_should_update_indicator_left_coordinate_based_on_bar_value(void)
100 {
101     lv_bar_t * bar_ptr = (lv_bar_t *) g_bar;
102 
103     static lv_style_t bar_style;
104 
105     const int32_t style_padding = 5u;
106     const int32_t bar_width = 200u;
107     const int32_t bar_height = 20u;
108     int32_t bar_value = 10u;
109 
110     lv_style_init(&bar_style);
111     lv_style_set_pad_all(&bar_style, style_padding);
112 
113     /* Setup new style */
114     lv_obj_remove_style_all(g_bar);
115     lv_obj_add_style(g_bar, &bar_style, LV_PART_MAIN);
116 
117     /* Set properties */
118     lv_obj_set_size(g_bar, bar_width, bar_height);
119     lv_bar_set_value(g_bar, bar_value, LV_ANIM_OFF);
120     lv_obj_set_style_base_dir(g_bar, LV_BASE_DIR_RTL, 0);
121 
122     /* FIXME: Remove wait */
123     lv_test_indev_wait(50);
124 
125     int32_t actual_coord = bar_ptr->indic_area.x1;
126 
127     /* Calculate current indicator width */
128     int32_t bar_max_value = lv_bar_get_max_value(g_bar);
129     int32_t indicator_part_width = lv_obj_get_content_width(g_bar);
130     int32_t right_padding = lv_obj_get_style_pad_right(g_bar, LV_PART_MAIN);
131     int32_t indicator_width = (bar_value * indicator_part_width) / bar_max_value;
132 
133     int32_t expected_coord = (bar_width - right_padding) - indicator_width;
134     expected_coord -= 1;
135 
136     TEST_ASSERT_EQUAL_INT32(expected_coord, actual_coord);
137 }
138 
test_bar_normal(void)139 void test_bar_normal(void)
140 {
141     int32_t w = 300;
142     int32_t h = 40;
143     int32_t h_gap = 20;
144     int32_t w_gap = 20;
145     int32_t y = h_gap;
146     int32_t x = w_gap;
147     lv_color_t bg_color = lv_color_black();
148     lv_color_t indic_color = lv_color_hex(0x0000FF);
149 
150     lv_obj_t * screen = lv_obj_create(lv_screen_active());
151     lv_obj_remove_style_all(screen);
152     lv_obj_set_size(screen, 800, 480);
153     lv_obj_center(screen);
154     lv_obj_set_style_bg_color(screen, lv_color_white(), 0);
155     lv_obj_set_style_bg_opa(screen, LV_OPA_100, 0);
156     lv_obj_set_style_pad_all(screen, 0, 0);
157 
158     lv_obj_t * test_bar = lv_bar_create(screen);
159     lv_obj_set_style_radius(test_bar, 100, 0);
160     lv_obj_set_style_radius(test_bar, 100, LV_PART_MAIN);
161     lv_obj_set_style_bg_opa(test_bar, LV_OPA_30, LV_PART_MAIN);
162     lv_obj_set_style_bg_color(test_bar, bg_color, LV_PART_MAIN);
163     lv_obj_set_style_bg_color(test_bar, indic_color, LV_PART_INDICATOR);
164     lv_bar_set_range(test_bar, 0, 100);
165     lv_bar_set_value(test_bar, 30, LV_ANIM_OFF);
166     lv_obj_set_size(test_bar, w, h);
167     lv_obj_align(test_bar, LV_ALIGN_TOP_LEFT, x, y);
168     y += h + h_gap;
169 
170     test_bar = lv_bar_create(screen);
171     lv_obj_set_style_radius(test_bar, 100, 0);
172     lv_obj_set_style_radius(test_bar, 100, LV_PART_MAIN);
173     lv_obj_set_style_bg_opa(test_bar, LV_OPA_30, LV_PART_MAIN);
174     lv_obj_set_style_bg_color(test_bar, bg_color, LV_PART_MAIN);
175     lv_obj_set_style_bg_color(test_bar, indic_color, LV_PART_INDICATOR);
176     lv_bar_set_range(test_bar, 0, 100);
177     lv_bar_set_value(test_bar, 30, LV_ANIM_OFF);
178     lv_obj_set_size(test_bar, w, h);
179     lv_obj_align(test_bar, LV_ALIGN_TOP_LEFT, x, y);
180     lv_obj_set_style_base_dir(test_bar, LV_BASE_DIR_RTL, 0);
181     y += h + h_gap;
182 
183     x = 150;
184     test_bar = lv_bar_create(screen);
185     lv_obj_set_style_radius(test_bar, 100, 0);
186     lv_obj_set_style_radius(test_bar, 100, LV_PART_MAIN);
187     lv_obj_set_style_bg_opa(test_bar, LV_OPA_30, LV_PART_MAIN);
188     lv_obj_set_style_bg_color(test_bar, bg_color, LV_PART_MAIN);
189     lv_obj_set_style_bg_color(test_bar, indic_color, LV_PART_INDICATOR);
190     lv_bar_set_range(test_bar, 0, 100);
191     lv_bar_set_value(test_bar, 30, LV_ANIM_OFF);
192     lv_obj_set_size(test_bar, h, w);
193     lv_obj_align(test_bar, LV_ALIGN_TOP_LEFT, x, y);
194     x += h + w_gap;
195 
196     test_bar = lv_bar_create(screen);
197     lv_obj_set_style_radius(test_bar, 100, 0);
198     lv_obj_set_style_radius(test_bar, 100, LV_PART_MAIN);
199     lv_obj_set_style_bg_opa(test_bar, LV_OPA_30, LV_PART_MAIN);
200     lv_obj_set_style_bg_color(test_bar, bg_color, LV_PART_MAIN);
201     lv_obj_set_style_bg_color(test_bar, indic_color, LV_PART_INDICATOR);
202     lv_bar_set_range(test_bar, 100, 0);
203     lv_bar_set_value(test_bar, 30, LV_ANIM_OFF);
204     lv_obj_set_size(test_bar, h, w);
205     lv_obj_align(test_bar, LV_ALIGN_TOP_LEFT, x, y);
206     TEST_ASSERT_EQUAL_SCREENSHOT("widgets/bar_1.png");
207 }
208 
test_bar_indicator_area_should_get_smaller_when_padding_is_increased(void)209 void test_bar_indicator_area_should_get_smaller_when_padding_is_increased(void)
210 {
211     lv_bar_t * bar_ptr = (lv_bar_t *) g_bar;
212 
213     const int32_t style_padding = 10u;
214     static lv_style_t bar_style;
215 
216     int32_t new_height = 0u;
217     int32_t new_width = 0u;
218     int32_t original_height = 0u;
219     int32_t original_width = 0u;
220 
221     lv_bar_set_value(g_bar, 50, LV_ANIM_OFF);
222     lv_test_indev_wait(50);
223 
224     original_width = lv_area_get_width(&bar_ptr->indic_area);
225     original_height = lv_area_get_height(&bar_ptr->indic_area);
226 
227     /* Setup new padding */
228     lv_style_init(&bar_style);
229     lv_style_set_pad_all(&bar_style, style_padding);
230     lv_obj_set_size(g_bar, 100, 50);
231 
232     /* Apply new style  */
233     lv_obj_remove_style_all(g_bar);
234     lv_obj_add_style(g_bar, &bar_style, LV_PART_MAIN);
235 
236     /* Notify LVGL of style change */
237     lv_obj_report_style_change(&bar_style);
238     lv_test_indev_wait(50);
239 
240     new_height = lv_area_get_height(&bar_ptr->indic_area);
241     new_width = lv_area_get_width(&bar_ptr->indic_area);
242 
243     TEST_ASSERT_LESS_THAN_INT32(original_height, new_height);
244     TEST_ASSERT_LESS_THAN_INT32(original_width, new_width);
245 }
246 
test_bar_start_value_should_only_change_when_in_range_mode(void)247 void test_bar_start_value_should_only_change_when_in_range_mode(void)
248 {
249     int32_t new_start_value = 20u;
250 
251     lv_bar_set_value(g_bar, 90, LV_ANIM_OFF);
252     lv_bar_set_start_value(g_bar, new_start_value, LV_ANIM_OFF);
253 
254     /* Start value shouldn't be updated when not in RANGE mode */
255     TEST_ASSERT_EQUAL_INT32(0u, lv_bar_get_start_value(g_bar));
256 
257     /* Set bar in RANGE mode so we can edit the start value */
258     lv_bar_set_mode(g_bar, LV_BAR_MODE_RANGE);
259     lv_bar_set_start_value(g_bar, new_start_value, LV_ANIM_OFF);
260 
261     TEST_ASSERT_EQUAL_INT32(new_start_value, lv_bar_get_start_value(g_bar));
262 }
263 
test_bar_start_value_should_be_smaller_than_current_value_in_range_mode(void)264 void test_bar_start_value_should_be_smaller_than_current_value_in_range_mode(void)
265 {
266     /* Set bar in RANGE mode so we can edit the start value */
267     lv_bar_set_mode(g_bar, LV_BAR_MODE_RANGE);
268     lv_bar_set_value(g_bar, 50, LV_ANIM_OFF);
269     lv_bar_set_start_value(g_bar, 100u, LV_ANIM_OFF);
270 
271     TEST_ASSERT_EQUAL_INT32(lv_bar_get_value(g_bar), lv_bar_get_start_value(g_bar));
272 }
273 
test_bar_current_value_should_be_truncated_to_max_value_when_exceeds_it(void)274 void test_bar_current_value_should_be_truncated_to_max_value_when_exceeds_it(void)
275 {
276     int32_t max_value = lv_bar_get_max_value(g_bar);
277     int32_t new_value = max_value + 1u;
278 
279     lv_bar_set_value(g_bar, new_value, LV_ANIM_OFF);
280     TEST_ASSERT_EQUAL_INT32(max_value, lv_bar_get_value(g_bar));
281 }
282 
test_bar_current_value_should_be_truncated_to_min_value_when_it_is_below_it(void)283 void test_bar_current_value_should_be_truncated_to_min_value_when_it_is_below_it(void)
284 {
285     int32_t min_value = lv_bar_get_min_value(g_bar);
286     int32_t new_value = min_value - 1u;
287 
288     lv_bar_set_value(g_bar, new_value, LV_ANIM_OFF);
289     TEST_ASSERT_EQUAL_INT32(min_value, lv_bar_get_value(g_bar));
290 }
291 
292 /** When in symmetrical mode, the bar indicator has to be drawn towards the min
293  * range value. Requires a negative min range value and a positive max range
294  * value.
295  *
296  * Bar properties assumed:
297  * - base direction: LTR
298  */
test_bar_indicator_should_be_drawn_towards_the_min_range_side_after_setting_a_more_negative_value(void)299 void test_bar_indicator_should_be_drawn_towards_the_min_range_side_after_setting_a_more_negative_value(void)
300 {
301     lv_bar_t * bar_ptr = (lv_bar_t *) g_bar;
302 
303     /* Setup bar properties */
304     lv_obj_set_size(g_bar, 100, 50);
305     lv_bar_set_mode(g_bar, LV_BAR_MODE_SYMMETRICAL);
306     lv_bar_set_range(g_bar, -100, 100);
307 
308     /* Set bar value to 1, so it gets drawn at the middle of the bar */
309     lv_bar_set_value(g_bar, 1, LV_ANIM_OFF);
310     lv_test_indev_wait(50);
311 
312     int32_t original_pos = bar_ptr->indic_area.x1;
313 
314     /* Set bar to a more negative value */
315     lv_bar_set_value(g_bar, -50, LV_ANIM_OFF);
316     lv_test_indev_wait(50);
317 
318     int32_t final_pos = bar_ptr->indic_area.x1;
319 
320     TEST_ASSERT_LESS_THAN(original_pos, final_pos);
321 }
322 
styled_bar_create(bool ver,int32_t start_value,int32_t end_value,lv_grad_dir_t grad_dir,int32_t bg_radius,int32_t indic_radius,int32_t bg_pad)323 static lv_obj_t * styled_bar_create(bool ver, int32_t start_value, int32_t end_value, lv_grad_dir_t grad_dir,
324                                     int32_t bg_radius, int32_t indic_radius, int32_t bg_pad)
325 {
326     lv_obj_t * bar = lv_bar_create(lv_screen_active());
327     if(ver) lv_obj_set_size(bar, 20, 100);
328     else lv_obj_set_size(bar, 100, 20);
329     lv_bar_set_range(bar, 0, 100);
330     lv_bar_set_mode(bar, LV_BAR_MODE_RANGE);
331     lv_bar_set_value(bar, end_value, LV_ANIM_OFF);
332     lv_bar_set_start_value(bar, start_value, LV_ANIM_OFF);
333 
334     lv_obj_set_style_bg_opa(bar, 255, LV_PART_MAIN);
335     lv_obj_set_style_bg_color(bar, lv_color_hex3(0x0ff), LV_PART_MAIN);
336     lv_obj_set_style_radius(bar, bg_radius, LV_PART_MAIN);
337     lv_obj_set_style_pad_all(bar, bg_pad, LV_PART_MAIN);
338 
339     lv_obj_set_style_bg_opa(bar, LV_OPA_70, LV_PART_INDICATOR);
340     lv_obj_set_style_bg_color(bar, lv_color_hex3(0xf0f), LV_PART_INDICATOR);
341     lv_obj_set_style_bg_grad_color(bar, lv_color_hex3(0x8f8), LV_PART_INDICATOR);
342     lv_obj_set_style_bg_grad_dir(bar, grad_dir, LV_PART_INDICATOR);
343 
344     lv_obj_set_style_border_width(bar, 2, LV_PART_INDICATOR);
345     lv_obj_set_style_border_color(bar, lv_color_hex3(0x0f0), LV_PART_INDICATOR);
346     lv_obj_set_style_border_opa(bar, LV_OPA_70, LV_PART_INDICATOR);
347     lv_obj_set_style_outline_width(bar, 2, LV_PART_INDICATOR);
348     lv_obj_set_style_outline_pad(bar, 4, LV_PART_INDICATOR);
349     lv_obj_set_style_outline_color(bar, lv_color_hex3(0xff0), LV_PART_INDICATOR);
350     lv_obj_set_style_outline_opa(bar, LV_OPA_70, LV_PART_INDICATOR);
351     lv_obj_set_style_shadow_width(bar, 20, LV_PART_INDICATOR);
352     lv_obj_set_style_shadow_spread(bar, 5, LV_PART_INDICATOR);
353     lv_obj_set_style_shadow_color(bar, lv_color_hex3(0xf00), LV_PART_INDICATOR);
354     lv_obj_set_style_shadow_opa(bar, LV_OPA_70, LV_PART_INDICATOR);
355     lv_obj_set_style_radius(bar, indic_radius, LV_PART_INDICATOR);
356 
357     return bar;
358 }
359 
render_test_screen_create(bool ver,lv_grad_dir_t grad_dir,const char * ref_img_path)360 static void render_test_screen_create(bool ver, lv_grad_dir_t grad_dir, const char * ref_img_path)
361 {
362     lv_obj_t * active_screen = lv_screen_active();
363     lv_obj_clean(active_screen);
364 
365     lv_obj_set_flex_flow(active_screen, ver ? LV_FLEX_FLOW_ROW_WRAP : LV_FLEX_FLOW_COLUMN_WRAP);
366     lv_obj_set_flex_align(active_screen, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_SPACE_EVENLY);
367     lv_obj_set_style_pad_row(active_screen, 17, 0);
368     lv_obj_set_style_pad_column(active_screen, 12, 0);
369     lv_obj_set_style_pad_all(active_screen, 15, 0);
370 
371     int32_t bar_values[6][2] = {{0, 5}, {0, 50}, {0, 95}, {5, 100}, {95, 100}, {20, 90}};
372     int32_t bg_radius[2] = {0, 15};
373     int32_t indic_radius[2] = {0, 15};
374     int32_t bg_pad[3] = {-5, 0, 5};
375 
376     uint32_t pad;
377     for(pad = 0; pad < 3; pad++) {
378         uint32_t indic_r;
379         for(indic_r = 0; indic_r < 2; indic_r++) {
380             uint32_t bg_r;
381             for(bg_r = 0; bg_r < 2; bg_r++) {
382                 uint32_t v;
383                 for(v = 0; v < 6; v++) {
384                     styled_bar_create(ver, bar_values[v][0], bar_values[v][1], grad_dir, bg_radius[bg_r], indic_radius[indic_r],
385                                       bg_pad[pad]);
386                 }
387             }
388         }
389     }
390 
391     TEST_ASSERT_EQUAL_SCREENSHOT(ref_img_path);
392 }
393 
test_bar_render_corner(void)394 void test_bar_render_corner(void)
395 {
396     render_test_screen_create(false, LV_GRAD_DIR_NONE, "widgets/bar_corner_1.png");
397     render_test_screen_create(false, LV_GRAD_DIR_HOR, "widgets/bar_corner_2.png");
398     render_test_screen_create(false, LV_GRAD_DIR_VER, "widgets/bar_corner_3.png");
399     render_test_screen_create(true, LV_GRAD_DIR_NONE, "widgets/bar_corner_4.png");
400     render_test_screen_create(true, LV_GRAD_DIR_HOR, "widgets/bar_corner_5.png");
401     render_test_screen_create(true, LV_GRAD_DIR_VER, "widgets/bar_corner_6.png");
402 }
403 
404 
bar_create_orientation(lv_bar_orientation_t orientation,int32_t w,int32_t h)405 static lv_obj_t * bar_create_orientation(lv_bar_orientation_t orientation, int32_t w, int32_t h)
406 {
407     lv_obj_t * bar = lv_bar_create(g_active_screen);
408     lv_bar_set_orientation(bar, orientation);
409     lv_obj_set_size(bar, w, h);
410     lv_bar_set_value(bar, 30, LV_ANIM_OFF);
411 
412     return bar;
413 
414 }
415 
test_bar_orientation(void)416 void test_bar_orientation(void)
417 {
418     lv_obj_clean(g_active_screen);
419 
420     lv_obj_set_flex_flow(g_active_screen, LV_FLEX_FLOW_ROW_WRAP);
421 
422     lv_obj_t * label;
423 
424     label = lv_label_create(g_active_screen);
425     lv_label_set_text(label, "Auto");
426     lv_obj_set_width(label, lv_pct(100));
427 
428     bar_create_orientation(LV_BAR_ORIENTATION_AUTO, 100, 20);
429     bar_create_orientation(LV_BAR_ORIENTATION_AUTO, 20, 100);
430     bar_create_orientation(LV_BAR_ORIENTATION_AUTO, 100, 100);
431 
432     label = lv_label_create(g_active_screen);
433     lv_label_set_text(label, "Vertical");
434     lv_obj_set_width(label, lv_pct(100));
435 
436     bar_create_orientation(LV_BAR_ORIENTATION_VERTICAL, 100, 20);
437     bar_create_orientation(LV_BAR_ORIENTATION_VERTICAL, 20, 100);
438     bar_create_orientation(LV_BAR_ORIENTATION_VERTICAL, 100, 100);
439 
440     label = lv_label_create(g_active_screen);
441     lv_label_set_text(label, "Horizontal");
442     lv_obj_set_width(label, lv_pct(100));
443 
444     bar_create_orientation(LV_BAR_ORIENTATION_HORIZONTAL, 100, 20);
445     bar_create_orientation(LV_BAR_ORIENTATION_HORIZONTAL, 20, 100);
446     bar_create_orientation(LV_BAR_ORIENTATION_HORIZONTAL, 100, 100);
447 
448     TEST_ASSERT_EQUAL_SCREENSHOT("widgets/bar_2.png");
449 }
450 
451 #endif
452