1 #if LV_BUILD_TEST
2 #include "../lvgl.h"
3 
4 #include "unity/unity.h"
5 
6 #include "lv_test_indev.h"
7 
8 static lv_obj_t * active_screen = NULL;
9 static lv_obj_t * bar = NULL;
10 
setUp(void)11 void setUp(void)
12 {
13     active_screen = lv_scr_act();
14     bar = lv_bar_create(active_screen);
15 }
16 
tearDown(void)17 void tearDown(void)
18 {
19 }
20 
test_bar_should_have_valid_default_attributes(void)21 void test_bar_should_have_valid_default_attributes(void)
22 {
23     TEST_ASSERT_EQUAL(0, lv_bar_get_min_value(bar));
24     TEST_ASSERT_EQUAL(100, lv_bar_get_max_value(bar));
25     TEST_ASSERT_EQUAL(LV_BAR_MODE_NORMAL, lv_bar_get_mode(bar));
26 }
27 
28 /*
29  * Bar has two parts, main and indicator, coordinates of the latter are
30  * calculated based on:
31  * - Bar size
32  * - Bar (main part) padding
33  * - Bar value
34  * - Bar coordinates
35  * - Bar base direction
36  * See Boxing model in docs for reference.
37  *
38  * Bar properties assumed:
39  * - mode: LV_BAR_MODE_NORMAL
40  * - min value: 0
41  * - max value: 100
42  * - base direction: LTR
43  */
test_bar_should_update_indicator_right_coordinate_based_on_bar_value(void)44 void test_bar_should_update_indicator_right_coordinate_based_on_bar_value(void)
45 {
46     lv_bar_t * bar_ptr = (lv_bar_t *) bar;
47 
48     static lv_style_t bar_style;
49 
50     const lv_coord_t style_padding = 5u;
51     const lv_coord_t bar_width = 200u;
52     const lv_coord_t bar_height = 20u;
53     int32_t bar_value = 10u;
54 
55     lv_style_init(&bar_style);
56     lv_style_set_pad_all(&bar_style, style_padding);
57 
58     /* Setup new style */
59     lv_obj_remove_style_all(bar);
60     lv_obj_add_style(bar, &bar_style, LV_PART_MAIN);
61 
62     /* Set properties */
63     lv_obj_set_size(bar, bar_width, bar_height);
64     lv_bar_set_value(bar, bar_value, LV_ANIM_OFF);
65 
66     /* FIXME: Remove wait */
67     lv_test_indev_wait(50);
68 
69     int32_t actual_coord = lv_area_get_width(&bar_ptr->indic_area);
70 
71     /* Calculate bar indicator right coordinate, using rule of 3 */
72     lv_coord_t bar_max_value = lv_bar_get_max_value(bar);
73     lv_coord_t indicator_part_width = lv_obj_get_content_width(bar);
74     lv_coord_t sides_padding = lv_obj_get_style_pad_left(bar, LV_PART_MAIN);
75     sides_padding += lv_obj_get_style_pad_right(bar, LV_PART_MAIN);
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 *) bar;
102 
103     static lv_style_t bar_style;
104 
105     const lv_coord_t style_padding = 5u;
106     const lv_coord_t bar_width = 200u;
107     const lv_coord_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(bar);
115     lv_obj_add_style(bar, &bar_style, LV_PART_MAIN);
116 
117     /* Set properties */
118     lv_obj_set_size(bar, bar_width, bar_height);
119     lv_bar_set_value(bar, bar_value, LV_ANIM_OFF);
120     lv_obj_set_style_base_dir(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     lv_coord_t bar_max_value = lv_bar_get_max_value(bar);
129     lv_coord_t indicator_part_width = lv_obj_get_content_width(bar);
130     lv_coord_t right_padding = lv_obj_get_style_pad_right(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_indicator_area_should_get_smaller_when_padding_is_increased(void)139 void test_bar_indicator_area_should_get_smaller_when_padding_is_increased(void)
140 {
141     lv_bar_t * bar_ptr = (lv_bar_t *) bar;
142 
143     const lv_coord_t style_padding = 10u;
144     static lv_style_t bar_style;
145 
146     int32_t new_height = 0u;
147     int32_t new_width = 0u;
148     int32_t original_height = 0u;
149     int32_t original_width = 0u;
150 
151     lv_bar_set_value(bar, 50, LV_ANIM_OFF);
152     lv_test_indev_wait(50);
153 
154     original_width = lv_area_get_width(&bar_ptr->indic_area);
155     original_height = lv_area_get_height(&bar_ptr->indic_area);
156 
157     /* Setup new padding */
158     lv_style_init(&bar_style);
159     lv_style_set_pad_all(&bar_style, style_padding);
160     lv_obj_set_size(bar, 100, 50);
161 
162     /* Apply new style  */
163     lv_obj_remove_style_all(bar);
164     lv_obj_add_style(bar, &bar_style, LV_PART_MAIN);
165 
166     /* Notify LVGL of style change */
167     lv_obj_report_style_change(&bar_style);
168     lv_test_indev_wait(50);
169 
170     new_height = lv_area_get_height(&bar_ptr->indic_area);
171     new_width = lv_area_get_width(&bar_ptr->indic_area);
172 
173     TEST_ASSERT_LESS_THAN_INT32(original_height, new_height);
174     TEST_ASSERT_LESS_THAN_INT32(original_width, new_width);
175 }
176 
test_bar_start_value_should_only_change_when_in_range_mode(void)177 void test_bar_start_value_should_only_change_when_in_range_mode(void)
178 {
179     int32_t new_start_value = 20u;
180 
181     lv_bar_set_value(bar, 90, LV_ANIM_OFF);
182     lv_bar_set_start_value(bar, new_start_value, LV_ANIM_OFF);
183 
184     /* Start value shouldn't be updated when not in RANGE mode */
185     TEST_ASSERT_EQUAL_INT32(0u, lv_bar_get_start_value(bar));
186 
187     /* Set bar in RANGE mode so we can edit the start value */
188     lv_bar_set_mode(bar, LV_BAR_MODE_RANGE);
189     lv_bar_set_start_value(bar, new_start_value, LV_ANIM_OFF);
190 
191     TEST_ASSERT_EQUAL_INT32(new_start_value, lv_bar_get_start_value(bar));
192 }
193 
test_bar_start_value_should_be_smaller_than_current_value_in_range_mode(void)194 void test_bar_start_value_should_be_smaller_than_current_value_in_range_mode(void)
195 {
196     /* Set bar in RANGE mode so we can edit the start value */
197     lv_bar_set_mode(bar, LV_BAR_MODE_RANGE);
198     lv_bar_set_value(bar, 50, LV_ANIM_OFF);
199     lv_bar_set_start_value(bar, 100u, LV_ANIM_OFF);
200 
201     TEST_ASSERT_EQUAL_INT32(lv_bar_get_value(bar), lv_bar_get_start_value(bar));
202 }
203 
test_bar_current_value_should_be_truncated_to_max_value_when_exceeds_it(void)204 void test_bar_current_value_should_be_truncated_to_max_value_when_exceeds_it(void)
205 {
206     int32_t max_value = lv_bar_get_max_value(bar);
207     int32_t new_value = max_value + 1u;
208 
209     lv_bar_set_value(bar, new_value, LV_ANIM_OFF);
210     TEST_ASSERT_EQUAL_INT32(max_value, lv_bar_get_value(bar));
211 }
212 
test_bar_current_value_should_be_truncated_to_min_value_when_it_is_below_it(void)213 void test_bar_current_value_should_be_truncated_to_min_value_when_it_is_below_it(void)
214 {
215     int32_t min_value = lv_bar_get_min_value(bar);
216     int32_t new_value = min_value - 1u;
217 
218     lv_bar_set_value(bar, new_value, LV_ANIM_OFF);
219     TEST_ASSERT_EQUAL_INT32(min_value, lv_bar_get_value(bar));
220 }
221 
222 /** When in symmetrical mode, the bar indicator has to be drawn towards the min
223  * range value. Requires a negative min range value and a positive max range
224  * value.
225  *
226  * Bar properties assumed:
227  * - base direction: LTR
228  */
test_bar_indicator_should_be_drawn_towards_the_min_range_side_after_setting_a_more_negative_value(void)229 void test_bar_indicator_should_be_drawn_towards_the_min_range_side_after_setting_a_more_negative_value(void)
230 {
231     lv_bar_t * bar_ptr = (lv_bar_t *) bar;
232 
233     /* Setup bar properties */
234     lv_obj_set_size(bar, 100, 50);
235     lv_bar_set_mode(bar, LV_BAR_MODE_SYMMETRICAL);
236     lv_bar_set_range(bar, -100, 100);
237 
238     /* Set bar value to 1, so it gets drawn at the middle of the bar */
239     lv_bar_set_value(bar, 1, LV_ANIM_OFF);
240     lv_test_indev_wait(50);
241 
242     lv_coord_t original_pos = bar_ptr->indic_area.x1;
243 
244     /* Set bar to a more negative value */
245     lv_bar_set_value(bar, -50, LV_ANIM_OFF);
246     lv_test_indev_wait(50);
247 
248     lv_coord_t final_pos = bar_ptr->indic_area.x1;
249 
250     TEST_ASSERT_LESS_THAN(original_pos, final_pos);
251 }
252 
253 #endif
254