source: mainline/uspace/lib/ui/test/checkbox.c@ 9c7dc8e

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

Print text as text in textmode UI. Make calculator smaller in text mode.

  • Property mode set to 100644
File size: 14.2 KB
Line 
1/*
2 * Copyright (c) 2020 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/checkbox.h>
36#include <ui/resource.h>
37#include "../private/checkbox.h"
38
39PCUT_INIT;
40
41PCUT_TEST_SUITE(checkbox);
42
43static errno_t testgc_set_color(void *, gfx_color_t *);
44static errno_t testgc_fill_rect(void *, gfx_rect_t *);
45static errno_t testgc_bitmap_create(void *, gfx_bitmap_params_t *,
46 gfx_bitmap_alloc_t *, void **);
47static errno_t testgc_bitmap_destroy(void *);
48static errno_t testgc_bitmap_render(void *, gfx_rect_t *, gfx_coord2_t *);
49static errno_t testgc_bitmap_get_alloc(void *, gfx_bitmap_alloc_t *);
50
51static gfx_context_ops_t ops = {
52 .set_color = testgc_set_color,
53 .fill_rect = testgc_fill_rect,
54 .bitmap_create = testgc_bitmap_create,
55 .bitmap_destroy = testgc_bitmap_destroy,
56 .bitmap_render = testgc_bitmap_render,
57 .bitmap_get_alloc = testgc_bitmap_get_alloc
58};
59
60static void test_checkbox_switched(ui_checkbox_t *, void *, bool);
61
62static ui_checkbox_cb_t test_checkbox_cb = {
63 .switched = test_checkbox_switched
64};
65
66static ui_checkbox_cb_t dummy_checkbox_cb = {
67};
68
69typedef struct {
70 bool bm_created;
71 bool bm_destroyed;
72 gfx_bitmap_params_t bm_params;
73 void *bm_pixels;
74 gfx_rect_t bm_srect;
75 gfx_coord2_t bm_offs;
76 bool bm_rendered;
77 bool bm_got_alloc;
78} test_gc_t;
79
80typedef struct {
81 test_gc_t *tgc;
82 gfx_bitmap_alloc_t alloc;
83 bool myalloc;
84} testgc_bitmap_t;
85
86typedef struct {
87 bool switched;
88} test_cb_resp_t;
89
90/** Create and destroy check box */
91PCUT_TEST(create_destroy)
92{
93 ui_checkbox_t *checkbox = NULL;
94 errno_t rc;
95
96 rc = ui_checkbox_create(NULL, "Hello", &checkbox);
97 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
98 PCUT_ASSERT_NOT_NULL(checkbox);
99
100 ui_checkbox_destroy(checkbox);
101}
102
103/** ui_checkbox_destroy() can take NULL argument (no-op) */
104PCUT_TEST(destroy_null)
105{
106 ui_checkbox_destroy(NULL);
107}
108
109/** ui_checkbox_ctl() returns control that has a working virtual destructor */
110PCUT_TEST(ctl)
111{
112 ui_checkbox_t *checkbox;
113 ui_control_t *control;
114 errno_t rc;
115
116 rc = ui_checkbox_create(NULL, "Hello", &checkbox);
117 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
118
119 control = ui_checkbox_ctl(checkbox);
120 PCUT_ASSERT_NOT_NULL(control);
121
122 ui_control_destroy(control);
123}
124
125/** Set check box rectangle sets internal field */
126PCUT_TEST(set_rect)
127{
128 ui_checkbox_t *checkbox;
129 gfx_rect_t rect;
130 errno_t rc;
131
132 rc = ui_checkbox_create(NULL, "Hello", &checkbox);
133 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
134
135 rect.p0.x = 1;
136 rect.p0.y = 2;
137 rect.p1.x = 3;
138 rect.p1.y = 4;
139
140 ui_checkbox_set_rect(checkbox, &rect);
141 PCUT_ASSERT_INT_EQUALS(rect.p0.x, checkbox->rect.p0.x);
142 PCUT_ASSERT_INT_EQUALS(rect.p0.y, checkbox->rect.p0.y);
143 PCUT_ASSERT_INT_EQUALS(rect.p1.x, checkbox->rect.p1.x);
144 PCUT_ASSERT_INT_EQUALS(rect.p1.y, checkbox->rect.p1.y);
145
146 ui_checkbox_destroy(checkbox);
147}
148
149/** Paint check box */
150PCUT_TEST(paint)
151{
152 errno_t rc;
153 gfx_context_t *gc = NULL;
154 test_gc_t tgc;
155 ui_resource_t *resource = NULL;
156 ui_checkbox_t *checkbox;
157
158 memset(&tgc, 0, sizeof(tgc));
159 rc = gfx_context_new(&ops, &tgc, &gc);
160 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
161
162 rc = ui_resource_create(gc, false, &resource);
163 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
164 PCUT_ASSERT_NOT_NULL(resource);
165
166 rc = ui_checkbox_create(resource, "Hello", &checkbox);
167 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
168
169 rc = ui_checkbox_paint(checkbox);
170 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
171
172 ui_checkbox_destroy(checkbox);
173 ui_resource_destroy(resource);
174
175 rc = gfx_context_delete(gc);
176 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
177}
178
179/** Test ui_checkbox_switched() */
180PCUT_TEST(switched)
181{
182 errno_t rc;
183 ui_checkbox_t *checkbox;
184 test_cb_resp_t resp;
185
186 rc = ui_checkbox_create(NULL, "Hello", &checkbox);
187 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
188
189 /* Switched with no callbacks set */
190 ui_checkbox_switched(checkbox);
191
192 /* Switched with callback not implementing switched */
193 ui_checkbox_set_cb(checkbox, &dummy_checkbox_cb, NULL);
194 ui_checkbox_switched(checkbox);
195
196 /* Switched with real callback set */
197 resp.switched = false;
198 ui_checkbox_set_cb(checkbox, &test_checkbox_cb, &resp);
199 ui_checkbox_switched(checkbox);
200 PCUT_ASSERT_TRUE(resp.switched);
201
202 ui_checkbox_destroy(checkbox);
203}
204
205/** Press and release check box */
206PCUT_TEST(press_release)
207{
208 errno_t rc;
209 gfx_context_t *gc = NULL;
210 test_gc_t tgc;
211 ui_resource_t *resource = NULL;
212 ui_checkbox_t *checkbox;
213 test_cb_resp_t resp;
214
215 memset(&tgc, 0, sizeof(tgc));
216 rc = gfx_context_new(&ops, &tgc, &gc);
217 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
218
219 rc = ui_resource_create(gc, false, &resource);
220 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
221 PCUT_ASSERT_NOT_NULL(resource);
222
223 rc = ui_checkbox_create(resource, "Hello", &checkbox);
224 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
225 PCUT_ASSERT_FALSE(checkbox->checked);
226
227 resp.switched = false;
228 ui_checkbox_set_cb(checkbox, &test_checkbox_cb, &resp);
229
230 PCUT_ASSERT_FALSE(checkbox->held);
231 PCUT_ASSERT_FALSE(checkbox->inside);
232
233 ui_checkbox_press(checkbox);
234 PCUT_ASSERT_TRUE(checkbox->held);
235 PCUT_ASSERT_TRUE(checkbox->inside);
236 PCUT_ASSERT_FALSE(resp.switched);
237 PCUT_ASSERT_FALSE(checkbox->checked);
238
239 ui_checkbox_release(checkbox);
240 PCUT_ASSERT_FALSE(checkbox->held);
241 PCUT_ASSERT_TRUE(checkbox->inside);
242 PCUT_ASSERT_TRUE(resp.switched);
243 PCUT_ASSERT_TRUE(checkbox->checked);
244
245 ui_checkbox_destroy(checkbox);
246 ui_resource_destroy(resource);
247
248 rc = gfx_context_delete(gc);
249 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
250}
251
252/** Press, leave and release check box */
253PCUT_TEST(press_leave_release)
254{
255 errno_t rc;
256 gfx_context_t *gc = NULL;
257 test_gc_t tgc;
258 ui_resource_t *resource = NULL;
259 ui_checkbox_t *checkbox;
260 test_cb_resp_t resp;
261
262 memset(&tgc, 0, sizeof(tgc));
263 rc = gfx_context_new(&ops, &tgc, &gc);
264 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
265
266 rc = ui_resource_create(gc, false, &resource);
267 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
268 PCUT_ASSERT_NOT_NULL(resource);
269
270 rc = ui_checkbox_create(resource, "Hello", &checkbox);
271 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
272
273 resp.switched = false;
274 ui_checkbox_set_cb(checkbox, &test_checkbox_cb, &resp);
275
276 PCUT_ASSERT_FALSE(checkbox->held);
277 PCUT_ASSERT_FALSE(checkbox->inside);
278
279 ui_checkbox_press(checkbox);
280 PCUT_ASSERT_TRUE(checkbox->held);
281 PCUT_ASSERT_TRUE(checkbox->inside);
282 PCUT_ASSERT_FALSE(resp.switched);
283 PCUT_ASSERT_FALSE(checkbox->checked);
284
285 ui_checkbox_leave(checkbox);
286 PCUT_ASSERT_TRUE(checkbox->held);
287 PCUT_ASSERT_FALSE(checkbox->inside);
288 PCUT_ASSERT_FALSE(resp.switched);
289 PCUT_ASSERT_FALSE(checkbox->checked);
290
291 ui_checkbox_release(checkbox);
292 PCUT_ASSERT_FALSE(checkbox->held);
293 PCUT_ASSERT_FALSE(checkbox->inside);
294 PCUT_ASSERT_FALSE(resp.switched);
295 PCUT_ASSERT_FALSE(checkbox->checked);
296
297 ui_checkbox_destroy(checkbox);
298 ui_resource_destroy(resource);
299
300 rc = gfx_context_delete(gc);
301 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
302}
303
304/** Press, leave, enter and release check box */
305PCUT_TEST(press_leave_enter_release)
306{
307 errno_t rc;
308 gfx_context_t *gc = NULL;
309 test_gc_t tgc;
310 ui_resource_t *resource = NULL;
311 ui_checkbox_t *checkbox;
312 test_cb_resp_t resp;
313
314 memset(&tgc, 0, sizeof(tgc));
315 rc = gfx_context_new(&ops, &tgc, &gc);
316 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
317
318 rc = ui_resource_create(gc, false, &resource);
319 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
320 PCUT_ASSERT_NOT_NULL(resource);
321
322 rc = ui_checkbox_create(resource, "Hello", &checkbox);
323 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
324 PCUT_ASSERT_FALSE(checkbox->checked);
325
326 resp.switched = false;
327 ui_checkbox_set_cb(checkbox, &test_checkbox_cb, &resp);
328
329 PCUT_ASSERT_FALSE(checkbox->held);
330 PCUT_ASSERT_FALSE(checkbox->inside);
331
332 ui_checkbox_press(checkbox);
333 PCUT_ASSERT_TRUE(checkbox->held);
334 PCUT_ASSERT_TRUE(checkbox->inside);
335 PCUT_ASSERT_FALSE(resp.switched);
336 PCUT_ASSERT_FALSE(checkbox->checked);
337
338 ui_checkbox_leave(checkbox);
339 PCUT_ASSERT_TRUE(checkbox->held);
340 PCUT_ASSERT_FALSE(checkbox->inside);
341 PCUT_ASSERT_FALSE(resp.switched);
342 PCUT_ASSERT_FALSE(checkbox->checked);
343
344 ui_checkbox_enter(checkbox);
345 PCUT_ASSERT_TRUE(checkbox->held);
346 PCUT_ASSERT_TRUE(checkbox->inside);
347 PCUT_ASSERT_FALSE(resp.switched);
348 PCUT_ASSERT_FALSE(checkbox->checked);
349
350 ui_checkbox_release(checkbox);
351 PCUT_ASSERT_FALSE(checkbox->held);
352 PCUT_ASSERT_TRUE(checkbox->inside);
353 PCUT_ASSERT_TRUE(resp.switched);
354 PCUT_ASSERT_TRUE(checkbox->checked);
355
356 ui_checkbox_destroy(checkbox);
357 ui_resource_destroy(resource);
358
359 rc = gfx_context_delete(gc);
360 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
361}
362
363/** ui_pos_event() correctly translates POS_PRESS/POS_RELEASE */
364PCUT_TEST(pos_event_press_release)
365{
366 errno_t rc;
367 gfx_context_t *gc = NULL;
368 test_gc_t tgc;
369 ui_resource_t *resource = NULL;
370 ui_checkbox_t *checkbox;
371 ui_evclaim_t claim;
372 pos_event_t event;
373 gfx_rect_t rect;
374
375 memset(&tgc, 0, sizeof(tgc));
376 rc = gfx_context_new(&ops, &tgc, &gc);
377 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
378
379 rc = ui_resource_create(gc, false, &resource);
380 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
381 PCUT_ASSERT_NOT_NULL(resource);
382
383 rc = ui_checkbox_create(resource, "Hello", &checkbox);
384 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
385
386 PCUT_ASSERT_FALSE(checkbox->held);
387
388 rect.p0.x = 10;
389 rect.p0.y = 20;
390 rect.p1.x = 30;
391 rect.p1.y = 40;
392 ui_checkbox_set_rect(checkbox, &rect);
393
394 /* Press outside is not claimed and does nothing */
395 event.type = POS_PRESS;
396 event.hpos = 9;
397 event.vpos = 20;
398 claim = ui_checkbox_pos_event(checkbox, &event);
399 PCUT_ASSERT_FALSE(checkbox->held);
400 PCUT_ASSERT_EQUALS(ui_unclaimed, claim);
401
402 /* Press inside is claimed and depresses check box */
403 event.type = POS_PRESS;
404 event.hpos = 10;
405 event.vpos = 20;
406 claim = ui_checkbox_pos_event(checkbox, &event);
407 PCUT_ASSERT_TRUE(checkbox->held);
408 PCUT_ASSERT_EQUALS(ui_claimed, claim);
409
410 /* Release outside (or anywhere) is claimed and relases check box */
411 event.type = POS_RELEASE;
412 event.hpos = 9;
413 event.vpos = 20;
414 claim = ui_checkbox_pos_event(checkbox, &event);
415 PCUT_ASSERT_FALSE(checkbox->held);
416 PCUT_ASSERT_EQUALS(ui_claimed, claim);
417
418 ui_checkbox_destroy(checkbox);
419 ui_resource_destroy(resource);
420
421 rc = gfx_context_delete(gc);
422 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
423}
424
425/** ui_pos_event() correctly translates POS_UPDATE to enter/leave */
426PCUT_TEST(pos_event_enter_leave)
427{
428 errno_t rc;
429 gfx_context_t *gc = NULL;
430 test_gc_t tgc;
431 ui_resource_t *resource = NULL;
432 ui_checkbox_t *checkbox;
433 pos_event_t event;
434 gfx_rect_t rect;
435
436 memset(&tgc, 0, sizeof(tgc));
437 rc = gfx_context_new(&ops, &tgc, &gc);
438 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
439
440 rc = ui_resource_create(gc, false, &resource);
441 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
442 PCUT_ASSERT_NOT_NULL(resource);
443
444 rc = ui_checkbox_create(resource, "Hello", &checkbox);
445 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
446
447 PCUT_ASSERT_FALSE(checkbox->inside);
448
449 rect.p0.x = 10;
450 rect.p0.y = 20;
451 rect.p1.x = 30;
452 rect.p1.y = 40;
453 ui_checkbox_set_rect(checkbox, &rect);
454
455 /* Moving outside does nothing */
456 event.type = POS_UPDATE;
457 event.hpos = 9;
458 event.vpos = 20;
459 ui_checkbox_pos_event(checkbox, &event);
460 PCUT_ASSERT_FALSE(checkbox->inside);
461
462 /* Moving inside sets inside flag */
463 event.type = POS_UPDATE;
464 event.hpos = 10;
465 event.vpos = 20;
466 ui_checkbox_pos_event(checkbox, &event);
467 PCUT_ASSERT_TRUE(checkbox->inside);
468
469 /* Moving outside clears inside flag */
470 event.type = POS_UPDATE;
471 event.hpos = 9;
472 event.vpos = 20;
473 ui_checkbox_pos_event(checkbox, &event);
474 PCUT_ASSERT_FALSE(checkbox->inside);
475
476 ui_checkbox_destroy(checkbox);
477 ui_resource_destroy(resource);
478
479 rc = gfx_context_delete(gc);
480 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
481}
482
483static errno_t testgc_set_color(void *arg, gfx_color_t *color)
484{
485 (void) arg;
486 (void) color;
487 return EOK;
488}
489
490static errno_t testgc_fill_rect(void *arg, gfx_rect_t *rect)
491{
492 (void) arg;
493 (void) rect;
494 return EOK;
495}
496
497static errno_t testgc_bitmap_create(void *arg, gfx_bitmap_params_t *params,
498 gfx_bitmap_alloc_t *alloc, void **rbm)
499{
500 test_gc_t *tgc = (test_gc_t *) arg;
501 testgc_bitmap_t *tbm;
502
503 tbm = calloc(1, sizeof(testgc_bitmap_t));
504 if (tbm == NULL)
505 return ENOMEM;
506
507 if (alloc == NULL) {
508 tbm->alloc.pitch = (params->rect.p1.x - params->rect.p0.x) *
509 sizeof(uint32_t);
510 tbm->alloc.off0 = 0;
511 tbm->alloc.pixels = calloc(sizeof(uint32_t),
512 (params->rect.p1.x - params->rect.p0.x) *
513 (params->rect.p1.y - params->rect.p0.y));
514 tbm->myalloc = true;
515 if (tbm->alloc.pixels == NULL) {
516 free(tbm);
517 return ENOMEM;
518 }
519 } else {
520 tbm->alloc = *alloc;
521 }
522
523 tbm->tgc = tgc;
524 tgc->bm_created = true;
525 tgc->bm_params = *params;
526 tgc->bm_pixels = tbm->alloc.pixels;
527 *rbm = (void *)tbm;
528 return EOK;
529}
530
531static errno_t testgc_bitmap_destroy(void *bm)
532{
533 testgc_bitmap_t *tbm = (testgc_bitmap_t *)bm;
534 if (tbm->myalloc)
535 free(tbm->alloc.pixels);
536 tbm->tgc->bm_destroyed = true;
537 free(tbm);
538 return EOK;
539}
540
541static errno_t testgc_bitmap_render(void *bm, gfx_rect_t *srect,
542 gfx_coord2_t *offs)
543{
544 testgc_bitmap_t *tbm = (testgc_bitmap_t *)bm;
545 tbm->tgc->bm_rendered = true;
546 tbm->tgc->bm_srect = *srect;
547 tbm->tgc->bm_offs = *offs;
548 return EOK;
549}
550
551static errno_t testgc_bitmap_get_alloc(void *bm, gfx_bitmap_alloc_t *alloc)
552{
553 testgc_bitmap_t *tbm = (testgc_bitmap_t *)bm;
554 *alloc = tbm->alloc;
555 tbm->tgc->bm_got_alloc = true;
556 return EOK;
557}
558
559static void test_checkbox_switched(ui_checkbox_t *checkbox, void *arg,
560 bool checked)
561{
562 test_cb_resp_t *resp = (test_cb_resp_t *) arg;
563
564 resp->switched = true;
565}
566
567PCUT_EXPORT(checkbox);
Note: See TracBrowser for help on using the repository browser.