source: mainline/uspace/lib/ui/test/slider.c@ c68c18b9

serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since c68c18b9 was 7470d97, checked in by Jiri Svoboda <jiri@…>, 4 years ago

Add GC operation to set clipping rectangle

The number of changed files is due to the proliferation of GC
implementations, mostly these are just dummies in unit tests.
Definitely need to tame those in the future.

  • Property mode set to 100644
File size: 12.4 KB
Line 
1/*
2 * Copyright (c) 2021 Jiri Svoboda
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <gfx/context.h>
30#include <gfx/coord.h>
31#include <mem.h>
32#include <pcut/pcut.h>
33#include <stdbool.h>
34#include <ui/control.h>
35#include <ui/slider.h>
36#include <ui/resource.h>
37#include "../private/slider.h"
38
39PCUT_INIT;
40
41PCUT_TEST_SUITE(slider);
42
43static errno_t testgc_set_clip_rect(void *, gfx_rect_t *);
44static errno_t testgc_set_color(void *, gfx_color_t *);
45static errno_t testgc_fill_rect(void *, gfx_rect_t *);
46static errno_t testgc_update(void *);
47static errno_t testgc_bitmap_create(void *, gfx_bitmap_params_t *,
48 gfx_bitmap_alloc_t *, void **);
49static errno_t testgc_bitmap_destroy(void *);
50static errno_t testgc_bitmap_render(void *, gfx_rect_t *, gfx_coord2_t *);
51static errno_t testgc_bitmap_get_alloc(void *, gfx_bitmap_alloc_t *);
52
53static gfx_context_ops_t ops = {
54 .set_clip_rect = testgc_set_clip_rect,
55 .set_color = testgc_set_color,
56 .fill_rect = testgc_fill_rect,
57 .update = testgc_update,
58 .bitmap_create = testgc_bitmap_create,
59 .bitmap_destroy = testgc_bitmap_destroy,
60 .bitmap_render = testgc_bitmap_render,
61 .bitmap_get_alloc = testgc_bitmap_get_alloc
62};
63
64static void test_slider_moved(ui_slider_t *, void *, gfx_coord_t);
65
66static ui_slider_cb_t test_slider_cb = {
67 .moved = test_slider_moved
68};
69
70static ui_slider_cb_t dummy_slider_cb = {
71};
72
73typedef struct {
74 bool bm_created;
75 bool bm_destroyed;
76 gfx_bitmap_params_t bm_params;
77 void *bm_pixels;
78 gfx_rect_t bm_srect;
79 gfx_coord2_t bm_offs;
80 bool bm_rendered;
81 bool bm_got_alloc;
82} test_gc_t;
83
84typedef struct {
85 test_gc_t *tgc;
86 gfx_bitmap_alloc_t alloc;
87 bool myalloc;
88} testgc_bitmap_t;
89
90typedef struct {
91 bool moved;
92 gfx_coord_t pos;
93} test_cb_resp_t;
94
95/** Create and destroy slider */
96PCUT_TEST(create_destroy)
97{
98 ui_slider_t *slider = NULL;
99 errno_t rc;
100
101 rc = ui_slider_create(NULL, "Hello", &slider);
102 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
103 PCUT_ASSERT_NOT_NULL(slider);
104
105 ui_slider_destroy(slider);
106}
107
108/** ui_slider_destroy() can take NULL argument (no-op) */
109PCUT_TEST(destroy_null)
110{
111 ui_slider_destroy(NULL);
112}
113
114/** ui_slider_ctl() returns control that has a working virtual destructor */
115PCUT_TEST(ctl)
116{
117 ui_slider_t *slider;
118 ui_control_t *control;
119 errno_t rc;
120
121 rc = ui_slider_create(NULL, "Hello", &slider);
122 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
123
124 control = ui_slider_ctl(slider);
125 PCUT_ASSERT_NOT_NULL(control);
126
127 ui_control_destroy(control);
128}
129
130/** Set slider rectangle sets internal field */
131PCUT_TEST(set_rect)
132{
133 ui_slider_t *slider;
134 gfx_rect_t rect;
135 errno_t rc;
136
137 rc = ui_slider_create(NULL, "Hello", &slider);
138 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
139
140 rect.p0.x = 1;
141 rect.p0.y = 2;
142 rect.p1.x = 3;
143 rect.p1.y = 4;
144
145 ui_slider_set_rect(slider, &rect);
146 PCUT_ASSERT_INT_EQUALS(rect.p0.x, slider->rect.p0.x);
147 PCUT_ASSERT_INT_EQUALS(rect.p0.y, slider->rect.p0.y);
148 PCUT_ASSERT_INT_EQUALS(rect.p1.x, slider->rect.p1.x);
149 PCUT_ASSERT_INT_EQUALS(rect.p1.y, slider->rect.p1.y);
150
151 ui_slider_destroy(slider);
152}
153
154/** Paint slider */
155PCUT_TEST(paint)
156{
157 errno_t rc;
158 gfx_context_t *gc = NULL;
159 test_gc_t tgc;
160 ui_resource_t *resource = NULL;
161 ui_slider_t *slider;
162
163 memset(&tgc, 0, sizeof(tgc));
164 rc = gfx_context_new(&ops, &tgc, &gc);
165 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
166
167 rc = ui_resource_create(gc, false, &resource);
168 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
169 PCUT_ASSERT_NOT_NULL(resource);
170
171 rc = ui_slider_create(resource, "Hello", &slider);
172 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
173
174 rc = ui_slider_paint(slider);
175 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
176
177 ui_slider_destroy(slider);
178 ui_resource_destroy(resource);
179
180 rc = gfx_context_delete(gc);
181 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
182}
183
184/** Test ui_slider_moved() */
185PCUT_TEST(moved)
186{
187 errno_t rc;
188 ui_slider_t *slider;
189 test_cb_resp_t resp;
190
191 rc = ui_slider_create(NULL, "Hello", &slider);
192 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
193
194 /* Moved with no callbacks set */
195 ui_slider_moved(slider, 42);
196
197 /* Moved with callback not implementing clicked */
198 ui_slider_set_cb(slider, &dummy_slider_cb, NULL);
199 ui_slider_moved(slider, 42);
200
201 /* Moved with real callback set */
202 resp.moved = false;
203 resp.pos = 0;
204 ui_slider_set_cb(slider, &test_slider_cb, &resp);
205 ui_slider_moved(slider, 42);
206 PCUT_ASSERT_TRUE(resp.moved);
207 PCUT_ASSERT_INT_EQUALS(42, resp.pos);
208
209 ui_slider_destroy(slider);
210}
211
212/** Press and release slider */
213PCUT_TEST(press_release)
214{
215 errno_t rc;
216 gfx_context_t *gc = NULL;
217 test_gc_t tgc;
218 ui_resource_t *resource = NULL;
219 gfx_coord2_t pos;
220 gfx_rect_t rect;
221 ui_slider_t *slider;
222 test_cb_resp_t resp;
223
224 memset(&tgc, 0, sizeof(tgc));
225 rc = gfx_context_new(&ops, &tgc, &gc);
226 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
227
228 rc = ui_resource_create(gc, false, &resource);
229 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
230 PCUT_ASSERT_NOT_NULL(resource);
231
232 rc = ui_slider_create(resource, "Hello", &slider);
233 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
234
235 rect.p0.x = 10;
236 rect.p0.y = 20;
237 rect.p1.x = 110;
238 rect.p1.y = 120;
239 ui_slider_set_rect(slider, &rect);
240
241 resp.moved = false;
242 ui_slider_set_cb(slider, &test_slider_cb, &resp);
243
244 PCUT_ASSERT_FALSE(slider->held);
245
246 pos.x = 11;
247 pos.y = 22;
248
249 ui_slider_press(slider, &pos);
250 PCUT_ASSERT_TRUE(slider->held);
251 PCUT_ASSERT_FALSE(resp.moved);
252
253 pos.x = 21;
254 pos.y = 32;
255
256 ui_slider_release(slider, &pos);
257 PCUT_ASSERT_FALSE(slider->held);
258 PCUT_ASSERT_TRUE(resp.moved);
259 PCUT_ASSERT_INT_EQUALS(10, slider->pos);
260
261 ui_slider_destroy(slider);
262 ui_resource_destroy(resource);
263
264 rc = gfx_context_delete(gc);
265 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
266}
267
268/** Press, update and release slider */
269PCUT_TEST(press_uodate_release)
270{
271 errno_t rc;
272 gfx_context_t *gc = NULL;
273 test_gc_t tgc;
274 ui_resource_t *resource = NULL;
275 gfx_coord2_t pos;
276 gfx_rect_t rect;
277 ui_slider_t *slider;
278 test_cb_resp_t resp;
279
280 memset(&tgc, 0, sizeof(tgc));
281 rc = gfx_context_new(&ops, &tgc, &gc);
282 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
283
284 rc = ui_resource_create(gc, false, &resource);
285 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
286 PCUT_ASSERT_NOT_NULL(resource);
287
288 rc = ui_slider_create(resource, "Hello", &slider);
289 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
290
291 rect.p0.x = 10;
292 rect.p0.y = 20;
293 rect.p1.x = 110;
294 rect.p1.y = 120;
295 ui_slider_set_rect(slider, &rect);
296
297 resp.moved = false;
298 ui_slider_set_cb(slider, &test_slider_cb, &resp);
299
300 PCUT_ASSERT_FALSE(slider->held);
301
302 pos.x = 11;
303 pos.y = 22;
304
305 ui_slider_press(slider, &pos);
306 PCUT_ASSERT_TRUE(slider->held);
307 PCUT_ASSERT_FALSE(resp.moved);
308
309 pos.x = 21;
310 pos.y = 32;
311
312 ui_slider_update(slider, &pos);
313 PCUT_ASSERT_TRUE(slider->held);
314 PCUT_ASSERT_TRUE(resp.moved);
315 PCUT_ASSERT_INT_EQUALS(10, slider->pos);
316
317 pos.x = 31;
318 pos.y = 42;
319
320 ui_slider_release(slider, &pos);
321 PCUT_ASSERT_FALSE(slider->held);
322 PCUT_ASSERT_TRUE(resp.moved);
323 PCUT_ASSERT_INT_EQUALS(20, slider->pos);
324
325 ui_slider_destroy(slider);
326 ui_resource_destroy(resource);
327
328 rc = gfx_context_delete(gc);
329 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
330}
331
332/** ui_pos_event() correctly translates POS_PRESS/POS_RELEASE */
333PCUT_TEST(pos_event_press_release)
334{
335 errno_t rc;
336 gfx_context_t *gc = NULL;
337 test_gc_t tgc;
338 ui_resource_t *resource = NULL;
339 ui_slider_t *slider;
340 ui_evclaim_t claim;
341 pos_event_t event;
342 gfx_rect_t rect;
343
344 memset(&tgc, 0, sizeof(tgc));
345 rc = gfx_context_new(&ops, &tgc, &gc);
346 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
347
348 rc = ui_resource_create(gc, false, &resource);
349 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
350 PCUT_ASSERT_NOT_NULL(resource);
351
352 rc = ui_slider_create(resource, "Hello", &slider);
353 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
354
355 PCUT_ASSERT_FALSE(slider->held);
356
357 rect.p0.x = 10;
358 rect.p0.y = 20;
359 rect.p1.x = 30;
360 rect.p1.y = 40;
361 ui_slider_set_rect(slider, &rect);
362
363 /* Press outside is not claimed and does nothing */
364 event.type = POS_PRESS;
365 event.hpos = 1;
366 event.vpos = 2;
367 claim = ui_slider_pos_event(slider, &event);
368 PCUT_ASSERT_FALSE(slider->held);
369 PCUT_ASSERT_EQUALS(ui_unclaimed, claim);
370
371 /* Press inside is claimed and depresses slider */
372 event.type = POS_PRESS;
373 event.hpos = 11;
374 event.vpos = 22;
375 claim = ui_slider_pos_event(slider, &event);
376 PCUT_ASSERT_TRUE(slider->held);
377 PCUT_ASSERT_EQUALS(ui_claimed, claim);
378
379 /* Release outside (or anywhere) is claimed and relases slider */
380 event.type = POS_RELEASE;
381 event.hpos = 41;
382 event.vpos = 32;
383 claim = ui_slider_pos_event(slider, &event);
384 PCUT_ASSERT_FALSE(slider->held);
385 PCUT_ASSERT_EQUALS(ui_claimed, claim);
386
387 ui_slider_destroy(slider);
388 ui_resource_destroy(resource);
389
390 rc = gfx_context_delete(gc);
391 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
392}
393
394/** ui_slider_length() correctly determines slider length */
395PCUT_TEST(length)
396{
397 errno_t rc;
398 gfx_context_t *gc = NULL;
399 test_gc_t tgc;
400 ui_resource_t *resource = NULL;
401 ui_slider_t *slider;
402 gfx_coord_t length;
403 gfx_rect_t rect;
404
405 memset(&tgc, 0, sizeof(tgc));
406 rc = gfx_context_new(&ops, &tgc, &gc);
407 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
408
409 rc = ui_resource_create(gc, false, &resource);
410 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
411 PCUT_ASSERT_NOT_NULL(resource);
412
413 rc = ui_slider_create(resource, "Hello", &slider);
414 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
415
416 PCUT_ASSERT_FALSE(slider->held);
417
418 rect.p0.x = 10;
419 rect.p0.y = 20;
420 rect.p1.x = 110;
421 rect.p1.y = 120;
422 ui_slider_set_rect(slider, &rect);
423
424 length = ui_slider_length(slider);
425 PCUT_ASSERT_INT_EQUALS(110 - 10 - 15, length);
426
427 ui_slider_destroy(slider);
428 ui_resource_destroy(resource);
429
430 rc = gfx_context_delete(gc);
431 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
432}
433
434static errno_t testgc_set_clip_rect(void *arg, gfx_rect_t *rect)
435{
436 (void) arg;
437 (void) rect;
438 return EOK;
439}
440
441static errno_t testgc_set_color(void *arg, gfx_color_t *color)
442{
443 (void) arg;
444 (void) color;
445 return EOK;
446}
447
448static errno_t testgc_fill_rect(void *arg, gfx_rect_t *rect)
449{
450 (void) arg;
451 (void) rect;
452 return EOK;
453}
454
455static errno_t testgc_update(void *arg)
456{
457 (void) arg;
458 return EOK;
459}
460
461static errno_t testgc_bitmap_create(void *arg, gfx_bitmap_params_t *params,
462 gfx_bitmap_alloc_t *alloc, void **rbm)
463{
464 test_gc_t *tgc = (test_gc_t *) arg;
465 testgc_bitmap_t *tbm;
466
467 tbm = calloc(1, sizeof(testgc_bitmap_t));
468 if (tbm == NULL)
469 return ENOMEM;
470
471 if (alloc == NULL) {
472 tbm->alloc.pitch = (params->rect.p1.x - params->rect.p0.x) *
473 sizeof(uint32_t);
474 tbm->alloc.off0 = 0;
475 tbm->alloc.pixels = calloc(sizeof(uint32_t),
476 (params->rect.p1.x - params->rect.p0.x) *
477 (params->rect.p1.y - params->rect.p0.y));
478 tbm->myalloc = true;
479 if (tbm->alloc.pixels == NULL) {
480 free(tbm);
481 return ENOMEM;
482 }
483 } else {
484 tbm->alloc = *alloc;
485 }
486
487 tbm->tgc = tgc;
488 tgc->bm_created = true;
489 tgc->bm_params = *params;
490 tgc->bm_pixels = tbm->alloc.pixels;
491 *rbm = (void *)tbm;
492 return EOK;
493}
494
495static errno_t testgc_bitmap_destroy(void *bm)
496{
497 testgc_bitmap_t *tbm = (testgc_bitmap_t *)bm;
498 if (tbm->myalloc)
499 free(tbm->alloc.pixels);
500 tbm->tgc->bm_destroyed = true;
501 free(tbm);
502 return EOK;
503}
504
505static errno_t testgc_bitmap_render(void *bm, gfx_rect_t *srect,
506 gfx_coord2_t *offs)
507{
508 testgc_bitmap_t *tbm = (testgc_bitmap_t *)bm;
509 tbm->tgc->bm_rendered = true;
510 tbm->tgc->bm_srect = *srect;
511 tbm->tgc->bm_offs = *offs;
512 return EOK;
513}
514
515static errno_t testgc_bitmap_get_alloc(void *bm, gfx_bitmap_alloc_t *alloc)
516{
517 testgc_bitmap_t *tbm = (testgc_bitmap_t *)bm;
518 *alloc = tbm->alloc;
519 tbm->tgc->bm_got_alloc = true;
520 return EOK;
521}
522
523static void test_slider_moved(ui_slider_t *slider, void *arg, gfx_coord_t pos)
524{
525 test_cb_resp_t *resp = (test_cb_resp_t *) arg;
526
527 resp->moved = true;
528 resp->pos = pos;
529}
530
531PCUT_EXPORT(slider);
Note: See TracBrowser for help on using the repository browser.