1 #if LV_BUILD_TEST
2 #include "../lvgl.h"
3 #include "../../lvgl_private.h"
4 
5 #include "unity/unity.h"
6 #include "lv_test_indev.h"
7 
8 /* This function runs before each test */
9 void setUp(void);
10 
11 void test_arc_creation_successful(void);
12 void test_arc_should_truncate_to_max_range_when_new_value_exceeds_it(void);
13 void test_arc_should_truncate_to_min_range_when_new_value_is_inferior(void);
14 void test_arc_should_update_value_after_updating_range(void);
15 void test_arc_should_update_angles_when_changing_to_symmetrical_mode(void);
16 void test_arc_should_update_angles_when_changing_to_symmetrical_mode_value_more_than_middle_range(void);
17 void test_arc_angles_when_reversed(void);
18 
19 static lv_obj_t * active_screen = NULL;
20 static lv_obj_t * arc = NULL;
21 static lv_obj_t * arc2 = NULL;
22 static uint32_t event_cnt;
23 static uint32_t event_cnt2;
24 
25 static void dummy_event_cb(lv_event_t * e);
26 static void dummy_event_cb2(lv_event_t * e);
27 
setUp(void)28 void setUp(void)
29 {
30     active_screen = lv_screen_active();
31 }
32 
tearDown(void)33 void tearDown(void)
34 {
35     lv_obj_clean(active_screen);
36     lv_obj_set_style_layout(active_screen, LV_LAYOUT_NONE, 0);
37 }
38 
test_arc_creation_successful(void)39 void test_arc_creation_successful(void)
40 {
41     arc = lv_arc_create(active_screen);
42 
43     TEST_ASSERT_NOT_NULL(arc);
44 }
45 
test_arc_basic_render(void)46 void test_arc_basic_render(void)
47 {
48     arc = lv_arc_create(active_screen);
49     lv_obj_set_size(arc, 100, 100);
50     lv_obj_center(arc);
51     lv_arc_set_value(arc, 70);
52 
53     TEST_ASSERT_EQUAL_SCREENSHOT("widgets/arc_1.png");
54 }
55 
test_arc_rgb565a8_image(void)56 void test_arc_rgb565a8_image(void)
57 {
58 #if LV_BIN_DECODER_RAM_LOAD
59     /*RGB565A8 image rendering requires special handling*/
60     arc = lv_arc_create(active_screen);
61     lv_obj_set_size(arc, 100, 100);
62     lv_obj_center(arc);
63     lv_arc_set_value(arc, 70);
64     lv_obj_set_style_arc_width(arc, 30, 0);
65     lv_obj_set_style_arc_width(arc, 30, LV_PART_INDICATOR);
66     lv_obj_set_style_arc_image_src(arc, "A:src/test_files/binimages/cogwheel.RGB565A8.bin", LV_PART_INDICATOR);
67     lv_obj_set_style_arc_opa(arc, 150, LV_PART_INDICATOR);
68     lv_obj_set_style_bg_opa(arc, 0, LV_PART_KNOB);
69 
70     TEST_ASSERT_EQUAL_SCREENSHOT("widgets/arc_2.png");
71 #endif
72 }
73 
test_arc_should_truncate_to_max_range_when_new_value_exceeds_it(void)74 void test_arc_should_truncate_to_max_range_when_new_value_exceeds_it(void)
75 {
76     /* Default max range is 100 */
77     int16_t value_after_truncation = 100;
78 
79     arc = lv_arc_create(active_screen);
80 
81     lv_arc_set_value(arc, 200);
82 
83     TEST_ASSERT_EQUAL_INT16(value_after_truncation, lv_arc_get_value(arc));
84 }
85 
test_arc_should_truncate_to_min_range_when_new_value_is_inferior(void)86 void test_arc_should_truncate_to_min_range_when_new_value_is_inferior(void)
87 {
88     /* Default min range is 100 */
89     int16_t value_after_truncation = 0;
90 
91     arc = lv_arc_create(active_screen);
92 
93     lv_arc_set_value(arc, 0);
94 
95     TEST_ASSERT_EQUAL_INT16(value_after_truncation, lv_arc_get_value(arc));
96 }
97 
test_arc_should_update_value_after_updating_range(void)98 void test_arc_should_update_value_after_updating_range(void)
99 {
100     int16_t value_after_updating_max_range = 50;
101     int16_t value_after_updating_min_range = 30;
102 
103     arc = lv_arc_create(active_screen);
104 
105     lv_arc_set_value(arc, 80);
106     lv_arc_set_range(arc, 1, 50);
107 
108     TEST_ASSERT_EQUAL_INT16(value_after_updating_max_range, lv_arc_get_value(arc));
109 
110     lv_arc_set_value(arc, 10);
111     lv_arc_set_range(arc, 30, 50);
112 
113     TEST_ASSERT_EQUAL_INT16(value_after_updating_min_range, lv_arc_get_value(arc));
114 }
115 
test_arc_should_update_angles_when_changing_to_symmetrical_mode(void)116 void test_arc_should_update_angles_when_changing_to_symmetrical_mode(void)
117 {
118     int16_t expected_angle_start = 135;
119     int16_t expected_angle_end = 270;
120 
121     /* start angle is 135, end angle is 45 at creation */
122     arc = lv_arc_create(active_screen);
123     lv_arc_set_mode(arc, LV_ARC_MODE_SYMMETRICAL);
124 
125     TEST_ASSERT_EQUAL_INT16(expected_angle_start, lv_arc_get_angle_start(arc));
126     TEST_ASSERT_EQUAL_INT16(expected_angle_end, lv_arc_get_angle_end(arc));
127 }
128 
test_arc_should_update_angles_when_changing_to_symmetrical_mode_value_more_than_middle_range(void)129 void test_arc_should_update_angles_when_changing_to_symmetrical_mode_value_more_than_middle_range(void)
130 {
131     int16_t expected_angle_start = 270;
132     int16_t expected_angle_end = 45;
133 
134     /* start angle is 135, end angle is 45 at creation */
135     arc = lv_arc_create(active_screen);
136     lv_arc_set_value(arc, 100);
137     lv_arc_set_mode(arc, LV_ARC_MODE_SYMMETRICAL);
138 
139     TEST_ASSERT_EQUAL_INT16(expected_angle_start, lv_arc_get_angle_start(arc));
140     TEST_ASSERT_EQUAL_INT16(expected_angle_end, lv_arc_get_angle_end(arc));
141 }
142 
143 /* See #2522 for more information */
test_arc_angles_when_reversed(void)144 void test_arc_angles_when_reversed(void)
145 {
146     uint16_t expected_start_angle = 54;
147     uint16_t expected_end_angle = 90;
148     int16_t expected_value = 40;
149 
150     lv_obj_t * arcBlack;
151     arcBlack = lv_arc_create(lv_screen_active());
152 
153     lv_arc_set_mode(arcBlack, LV_ARC_MODE_REVERSE);
154 
155     lv_arc_set_bg_angles(arcBlack, 0, 90);
156 
157     lv_arc_set_value(arcBlack, expected_value);
158 
159     TEST_ASSERT_EQUAL_UINT16(expected_start_angle, lv_arc_get_angle_start(arcBlack));
160     TEST_ASSERT_EQUAL_UINT16(expected_end_angle, lv_arc_get_angle_end(arcBlack));
161     TEST_ASSERT_EQUAL_INT16(expected_value, lv_arc_get_value(arcBlack));
162 }
163 
test_arc_click_area_with_adv_hittest(void)164 void test_arc_click_area_with_adv_hittest(void)
165 {
166     arc = lv_arc_create(lv_screen_active());
167     lv_obj_set_size(arc, 100, 100);
168     lv_obj_set_style_arc_width(arc, 10, 0);
169     lv_obj_add_flag(arc, LV_OBJ_FLAG_ADV_HITTEST);
170     lv_obj_add_event_cb(arc, dummy_event_cb, LV_EVENT_PRESSED, NULL);
171     lv_obj_set_ext_click_area(arc, 5);
172 
173     /*No click detected at the middle*/
174     event_cnt = 0;
175     lv_test_mouse_click_at(50, 50);
176     TEST_ASSERT_EQUAL_UINT32(0, event_cnt);
177 
178     /*No click close to the radius - bg_arc - ext_click_area*/
179     event_cnt = 0;
180     lv_test_mouse_click_at(83, 50);
181     TEST_ASSERT_EQUAL_UINT32(0, event_cnt);
182 
183     /*Click on the radius - bg_arc - ext_click_area*/
184     event_cnt = 0;
185     lv_test_mouse_click_at(86, 50);
186     TEST_ASSERT_GREATER_THAN(0, event_cnt);
187 
188     /*Click on the radius + ext_click_area*/
189     event_cnt = 0;
190     lv_test_mouse_click_at(104, 50);
191     TEST_ASSERT_GREATER_THAN(0, event_cnt);
192 
193     /*No click beyond to the radius + ext_click_area*/
194     event_cnt = 0;
195     lv_test_mouse_click_at(106, 50);
196     TEST_ASSERT_EQUAL_UINT32(0, event_cnt);
197 }
198 
199 /* Check value doesn't go to max when clicking on the other side of the arc */
test_arc_click_sustained_from_start_to_end_does_not_set_value_to_max(void)200 void test_arc_click_sustained_from_start_to_end_does_not_set_value_to_max(void)
201 {
202     arc = lv_arc_create(lv_screen_active());
203     lv_arc_set_value(arc, 0);
204 
205     lv_obj_set_size(arc, 100, 100);
206     lv_obj_center(arc);
207     lv_obj_add_event_cb(arc, dummy_event_cb, LV_EVENT_PRESSED, NULL);
208     event_cnt = 0;
209 
210     /* Click close to start angle */
211     event_cnt = 0;
212     lv_test_mouse_release();
213     lv_test_indev_wait(50);
214     lv_test_mouse_move_to(376, 285);
215     lv_test_mouse_press();
216     lv_test_indev_wait(500);
217     lv_test_mouse_release();
218     lv_test_indev_wait(50);
219 
220     TEST_ASSERT_EQUAL_UINT32(1, event_cnt);
221     TEST_ASSERT_EQUAL_INT32(lv_arc_get_min_value(arc), lv_arc_get_value(arc));
222 
223     /* Click close to end angle */
224     event_cnt = 0;
225 
226     lv_test_mouse_release();
227     lv_test_indev_wait(50);
228     lv_test_mouse_move_to(376, 285);
229     lv_test_mouse_press();
230     lv_test_indev_wait(500);
231     lv_test_mouse_move_to(415, 281);
232     lv_test_indev_wait(500);
233     lv_test_mouse_release();
234     lv_test_indev_wait(50);
235 
236     TEST_ASSERT_EQUAL_UINT32(1, event_cnt);
237     TEST_ASSERT_EQUAL_INT32(lv_arc_get_min_value(arc), lv_arc_get_value(arc));
238 
239     TEST_ASSERT_EQUAL_SCREENSHOT("widgets/arc_3.png");
240 }
241 
test_two_overlapping_arcs_can_be_interacted_independently(void)242 void test_two_overlapping_arcs_can_be_interacted_independently(void)
243 {
244     arc = lv_arc_create(lv_screen_active());
245     arc2 = lv_arc_create(lv_screen_active());
246 
247     lv_arc_set_value(arc, 0);
248     lv_arc_set_value(arc2, 0);
249     lv_obj_set_size(arc, 100, 100);
250     lv_obj_set_size(arc2, 100, 100);
251     lv_arc_set_bg_angles(arc, 20, 160);
252     lv_arc_set_bg_angles(arc2, 200, 340);
253     lv_obj_add_flag(arc, LV_OBJ_FLAG_ADV_HITTEST);
254     lv_obj_add_flag(arc2, LV_OBJ_FLAG_ADV_HITTEST);
255     lv_arc_set_value(arc, 10);
256     lv_arc_set_value(arc2, 10);
257     lv_arc_set_rotation(arc, 355);
258     lv_arc_set_rotation(arc2, 355);
259     lv_obj_center(arc);
260     lv_obj_center(arc2);
261 
262     // Add event callback to both arcs
263     lv_obj_add_event_cb(arc, dummy_event_cb, LV_EVENT_PRESSED, NULL);
264     lv_obj_add_event_cb(arc2, dummy_event_cb2, LV_EVENT_PRESSED, NULL);
265 
266     // Reset event counters
267     event_cnt = 0;
268     event_cnt2 = 0;
269 
270     // Click on the position of the first arc (center)
271     lv_test_mouse_release();
272     lv_test_indev_wait(50);
273     lv_test_mouse_move_to(400, 195);
274     lv_test_mouse_press();
275     lv_test_indev_wait(500);
276     lv_test_mouse_release();
277     lv_test_indev_wait(50);
278 
279     // Verify that the event callback was called for the first arc
280     TEST_ASSERT_EQUAL_UINT32(0, event_cnt);
281     TEST_ASSERT_EQUAL_UINT32(1, event_cnt2);
282 
283     // click on the position of the second arc (center)
284     lv_test_mouse_release();
285     lv_test_indev_wait(50);
286     lv_test_mouse_move_to(400, 285);
287     lv_test_mouse_press();
288     lv_test_indev_wait(500);
289     lv_test_mouse_release();
290     lv_test_indev_wait(50);
291 
292     // Verify that the event callback was called for the second arc
293     TEST_ASSERT_EQUAL_UINT32(1, event_cnt);
294     TEST_ASSERT_EQUAL_UINT32(1, event_cnt2);
295 
296     // Verify that the screen remains as expected after the interactions
297     TEST_ASSERT_EQUAL_SCREENSHOT("widgets/overlapping_arcs_test.png");
298 }
299 
300 
dummy_event_cb(lv_event_t * e)301 static void dummy_event_cb(lv_event_t * e)
302 {
303     LV_UNUSED(e);
304     event_cnt++;
305 }
306 
dummy_event_cb2(lv_event_t * e)307 static void dummy_event_cb2(lv_event_t * e)
308 {
309     LV_UNUSED(e);
310     event_cnt2++;
311 }
312 
313 #endif
314