source: mainline/uspace/app/uidemo/uidemo.c@ 252d03c

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

Popping up a message, in text mode as well

  • Property mode set to 100644
File size: 16.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/** @addtogroup uidemo
30 * @{
31 */
32/** @file User interface demo
33 */
34
35#include <gfx/bitmap.h>
36#include <gfx/coord.h>
37#include <io/pixelmap.h>
38#include <stdio.h>
39#include <stdlib.h>
40#include <str.h>
41#include <ui/entry.h>
42#include <ui/fixed.h>
43#include <ui/image.h>
44#include <ui/label.h>
45#include <ui/menubar.h>
46#include <ui/menuentry.h>
47#include <ui/menu.h>
48#include <ui/msgdialog.h>
49#include <ui/pbutton.h>
50#include <ui/resource.h>
51#include <ui/ui.h>
52#include <ui/window.h>
53#include "uidemo.h"
54
55static errno_t bitmap_moire(gfx_bitmap_t *, gfx_coord_t, gfx_coord_t);
56
57static void wnd_close(ui_window_t *, void *);
58
59static ui_window_cb_t window_cb = {
60 .close = wnd_close
61};
62
63static void pb_clicked(ui_pbutton_t *, void *);
64
65static ui_pbutton_cb_t pbutton_cb = {
66 .clicked = pb_clicked
67};
68
69static void checkbox_switched(ui_checkbox_t *, void *, bool);
70
71static ui_checkbox_cb_t checkbox_cb = {
72 .switched = checkbox_switched
73};
74
75static void rb_selected(ui_rbutton_group_t *, void *, void *);
76
77static ui_rbutton_group_cb_t rbutton_group_cb = {
78 .selected = rb_selected
79};
80
81static void slider_moved(ui_slider_t *, void *, gfx_coord_t);
82
83static ui_slider_cb_t slider_cb = {
84 .moved = slider_moved
85};
86
87static void uidemo_file_message(ui_menu_entry_t *, void *);
88static void uidemo_file_exit(ui_menu_entry_t *, void *);
89
90static void msg_dialog_button(ui_msg_dialog_t *, void *, unsigned);
91static void msg_dialog_close(ui_msg_dialog_t *, void *);
92
93static ui_msg_dialog_cb_t msg_dialog_cb = {
94 .button = msg_dialog_button,
95 .close = msg_dialog_close
96};
97
98/** Window close button was clicked.
99 *
100 * @param window Window
101 * @param arg Argument (demo)
102 */
103static void wnd_close(ui_window_t *window, void *arg)
104{
105 ui_demo_t *demo = (ui_demo_t *) arg;
106
107 ui_quit(demo->ui);
108}
109
110/** Push button was clicked.
111 *
112 * @param pbutton Push button
113 * @param arg Argument (demo)
114 */
115static void pb_clicked(ui_pbutton_t *pbutton, void *arg)
116{
117 ui_demo_t *demo = (ui_demo_t *) arg;
118 errno_t rc;
119
120 if (pbutton == demo->pb1) {
121 rc = ui_entry_set_text(demo->entry, "OK pressed");
122 if (rc != EOK)
123 printf("Error changing entry text.\n");
124 (void) ui_entry_paint(demo->entry);
125 } else {
126 rc = ui_entry_set_text(demo->entry, "Cancel pressed");
127 if (rc != EOK)
128 printf("Error changing entry text.\n");
129 (void) ui_entry_paint(demo->entry);
130 }
131}
132
133/** Check box was switched.
134 *
135 * @param checkbox Check box
136 * @param arg Argument (demo)
137 */
138static void checkbox_switched(ui_checkbox_t *checkbox, void *arg, bool enable)
139{
140 ui_demo_t *demo = (ui_demo_t *) arg;
141 errno_t rc;
142
143 if (enable) {
144 rc = ui_entry_set_text(demo->entry, "Checked");
145 if (rc != EOK)
146 printf("Error changing entry text.\n");
147 (void) ui_entry_paint(demo->entry);
148 } else {
149 rc = ui_entry_set_text(demo->entry, "Unchecked");
150 if (rc != EOK)
151 printf("Error changing entry text.\n");
152 (void) ui_entry_paint(demo->entry);
153 }
154}
155
156/** Radio button was selected.
157 *
158 * @param rbgroup Radio button group
159 * @param garg Group argument (demo)
160 * @param barg Button argument
161 */
162static void rb_selected(ui_rbutton_group_t *rbgroup, void *garg, void *barg)
163{
164 ui_demo_t *demo = (ui_demo_t *) garg;
165 const char *text = (const char *) barg;
166 errno_t rc;
167
168 rc = ui_entry_set_text(demo->entry, text);
169 if (rc != EOK)
170 printf("Error changing entry text.\n");
171 (void) ui_entry_paint(demo->entry);
172}
173
174/** Slider was moved.
175 *
176 * @param slider Slider
177 * @param arg Argument (demo)
178 * @param pos Position
179 */
180static void slider_moved(ui_slider_t *slider, void *arg, gfx_coord_t pos)
181{
182 ui_demo_t *demo = (ui_demo_t *) arg;
183 char *str;
184 errno_t rc;
185 int rv;
186
187 rv = asprintf(&str, "Slider at %d of %d", (int) pos,
188 ui_slider_length(slider));
189 if (rv < 0) {
190 printf("Out of memory.\n");
191 return;
192 }
193
194 rc = ui_entry_set_text(demo->entry, str);
195 if (rc != EOK)
196 printf("Error changing entry text.\n");
197 (void) ui_entry_paint(demo->entry);
198
199 free(str);
200}
201
202/** File/message menu entry selected.
203 *
204 * @param mentry Menu entry
205 * @param arg Argument (demo)
206 */
207static void uidemo_file_message(ui_menu_entry_t *mentry, void *arg)
208{
209 ui_demo_t *demo = (ui_demo_t *) arg;
210 ui_msg_dialog_params_t mdparams;
211 ui_msg_dialog_t *dialog;
212 errno_t rc;
213
214 ui_msg_dialog_params_init(&mdparams);
215 mdparams.caption = "Message For You";
216 mdparams.text = "Hello, world!";
217
218 rc = ui_msg_dialog_create(demo->ui, &mdparams, &dialog);
219 if (rc != EOK) {
220 printf("Error creating message dialog.\n");
221 return;
222 }
223
224 ui_msg_dialog_set_cb(dialog, &msg_dialog_cb, &demo);
225
226}
227
228/** File/exit menu entry selected.
229 *
230 * @param mentry Menu entry
231 * @param arg Argument (demo)
232 */
233static void uidemo_file_exit(ui_menu_entry_t *mentry, void *arg)
234{
235 ui_demo_t *demo = (ui_demo_t *) arg;
236
237 ui_quit(demo->ui);
238}
239
240/** Message dialog button press.
241 *
242 * @param dialog Message dialog
243 * @param arg Argument (ui_demo_t *)
244 * @param bnum Button number
245 */
246static void msg_dialog_button(ui_msg_dialog_t *dialog, void *arg,
247 unsigned bnum)
248{
249 ui_demo_t *demo = (ui_demo_t *) arg;
250
251 (void) demo;
252 ui_msg_dialog_destroy(dialog);
253}
254
255/** Message dialog close request.
256 *
257 * @param dialog Message dialog
258 * @param arg Argument (ui_demo_t *)
259 */
260static void msg_dialog_close(ui_msg_dialog_t *dialog, void *arg)
261{
262 ui_demo_t *demo = (ui_demo_t *) arg;
263
264 (void) demo;
265 ui_msg_dialog_destroy(dialog);
266}
267
268/** Run UI demo on display server. */
269static errno_t ui_demo(const char *display_spec)
270{
271 ui_t *ui = NULL;
272 ui_wnd_params_t params;
273 ui_window_t *window = NULL;
274 ui_demo_t demo;
275 gfx_rect_t rect;
276 gfx_context_t *gc;
277 ui_resource_t *ui_res;
278 gfx_bitmap_params_t bparams;
279 gfx_bitmap_t *bitmap;
280 gfx_coord2_t off;
281 ui_menu_entry_t *mmsg;
282 ui_menu_entry_t *mfoo;
283 ui_menu_entry_t *mbar;
284 ui_menu_entry_t *mfoobar;
285 ui_menu_entry_t *mexit;
286 ui_menu_entry_t *mabout;
287 errno_t rc;
288
289 rc = ui_create(display_spec, &ui);
290 if (rc != EOK) {
291 printf("Error creating UI on display %s.\n", display_spec);
292 return rc;
293 }
294
295 memset((void *) &demo, 0, sizeof(demo));
296 demo.ui = ui;
297
298 ui_wnd_params_init(&params);
299 params.caption = "UI Demo";
300 params.style |= ui_wds_resizable;
301
302 /* FIXME: Auto layout */
303 if (ui_is_textmode(ui)) {
304 params.rect.p0.x = 0;
305 params.rect.p0.y = 0;
306 params.rect.p1.x = 80;
307 params.rect.p1.y = 25;
308 } else {
309 params.rect.p0.x = 0;
310 params.rect.p0.y = 0;
311 params.rect.p1.x = 220;
312 params.rect.p1.y = 350;
313 }
314
315 rc = ui_window_create(ui, &params, &window);
316 if (rc != EOK) {
317 printf("Error creating window.\n");
318 return rc;
319 }
320
321 ui_window_set_cb(window, &window_cb, (void *) &demo);
322 demo.window = window;
323
324 ui_res = ui_window_get_res(window);
325 gc = ui_window_get_gc(window);
326
327 rc = ui_fixed_create(&demo.fixed);
328 if (rc != EOK) {
329 printf("Error creating fixed layout.\n");
330 return rc;
331 }
332
333 rc = ui_menu_bar_create(ui_res, &demo.mbar);
334 if (rc != EOK) {
335 printf("Error creating menu bar.\n");
336 return rc;
337 }
338
339 rc = ui_menu_create(demo.mbar, "File", &demo.mfile);
340 if (rc != EOK) {
341 printf("Error creating menu.\n");
342 return rc;
343 }
344
345 rc = ui_menu_entry_create(demo.mfile, "Message", "", &mmsg);
346 if (rc != EOK) {
347 printf("Error creating menu.\n");
348 return rc;
349 }
350
351 ui_menu_entry_set_cb(mmsg, uidemo_file_message, (void *) &demo);
352
353 rc = ui_menu_entry_create(demo.mfile, "Foo", "Ctrl-Alt-Del", &mfoo);
354 if (rc != EOK) {
355 printf("Error creating menu.\n");
356 return rc;
357 }
358
359 rc = ui_menu_entry_create(demo.mfile, "Bar", "", &mbar);
360 if (rc != EOK) {
361 printf("Error creating menu.\n");
362 return rc;
363 }
364
365 rc = ui_menu_entry_create(demo.mfile, "Foobar", "", &mfoobar);
366 if (rc != EOK) {
367 printf("Error creating menu.\n");
368 return rc;
369 }
370
371 rc = ui_menu_entry_sep_create(demo.mfile, &mexit);
372 if (rc != EOK) {
373 printf("Error creating menu.\n");
374 return rc;
375 }
376
377 rc = ui_menu_entry_create(demo.mfile, "Exit", "Alt-F4", &mexit);
378 if (rc != EOK) {
379 printf("Error creating menu.\n");
380 return rc;
381 }
382
383 ui_menu_entry_set_cb(mexit, uidemo_file_exit, (void *) &demo);
384
385 rc = ui_menu_create(demo.mbar, "Edit", &demo.medit);
386 if (rc != EOK) {
387 printf("Error creating menu.\n");
388 return rc;
389 }
390
391 rc = ui_menu_create(demo.mbar, "Preferences", &demo.mpreferences);
392 if (rc != EOK) {
393 printf("Error creating menu.\n");
394 return rc;
395 }
396
397 rc = ui_menu_create(demo.mbar, "Help", &demo.mhelp);
398 if (rc != EOK) {
399 printf("Error creating menu.\n");
400 return rc;
401 }
402
403 rc = ui_menu_entry_create(demo.mhelp, "About", "Ctrl-H, F1", &mabout);
404 if (rc != EOK) {
405 printf("Error creating menu.\n");
406 return rc;
407 }
408
409 /* FIXME: Auto layout */
410 if (ui_is_textmode(ui)) {
411 rect.p0.x = 1;
412 rect.p0.y = 2;
413 rect.p1.x = 79;
414 rect.p1.y = 3;
415 } else {
416 rect.p0.x = 4;
417 rect.p0.y = 30;
418 rect.p1.x = 216;
419 rect.p1.y = 52;
420 }
421 ui_menu_bar_set_rect(demo.mbar, &rect);
422
423 rc = ui_fixed_add(demo.fixed, ui_menu_bar_ctl(demo.mbar));
424 if (rc != EOK) {
425 printf("Error adding control to layout.\n");
426 return rc;
427 }
428
429 rc = ui_entry_create(ui_res, "", &demo.entry);
430 if (rc != EOK) {
431 printf("Error creating entry.\n");
432 return rc;
433 }
434
435 rect.p0.x = 15;
436 rect.p0.y = 53;
437 rect.p1.x = 205;
438 rect.p1.y = 78;
439 ui_entry_set_rect(demo.entry, &rect);
440 ui_entry_set_halign(demo.entry, gfx_halign_center);
441
442 rc = ui_fixed_add(demo.fixed, ui_entry_ctl(demo.entry));
443 if (rc != EOK) {
444 printf("Error adding control to layout.\n");
445 return rc;
446 }
447
448 rc = ui_label_create(ui_res, "Text label", &demo.label);
449 if (rc != EOK) {
450 printf("Error creating label.\n");
451 return rc;
452 }
453
454 rect.p0.x = 60;
455 rect.p0.y = 88;
456 rect.p1.x = 160;
457 rect.p1.y = 101;
458 ui_label_set_rect(demo.label, &rect);
459 ui_label_set_halign(demo.label, gfx_halign_center);
460
461 rc = ui_fixed_add(demo.fixed, ui_label_ctl(demo.label));
462 if (rc != EOK) {
463 printf("Error adding control to layout.\n");
464 return rc;
465 }
466
467 rc = ui_pbutton_create(ui_res, "OK", &demo.pb1);
468 if (rc != EOK) {
469 printf("Error creating button.\n");
470 return rc;
471 }
472
473 ui_pbutton_set_cb(demo.pb1, &pbutton_cb, (void *) &demo);
474
475 rect.p0.x = 15;
476 rect.p0.y = 111;
477 rect.p1.x = 105;
478 rect.p1.y = 139;
479 ui_pbutton_set_rect(demo.pb1, &rect);
480
481 ui_pbutton_set_default(demo.pb1, true);
482
483 rc = ui_fixed_add(demo.fixed, ui_pbutton_ctl(demo.pb1));
484 if (rc != EOK) {
485 printf("Error adding control to layout.\n");
486 return rc;
487 }
488
489 rc = ui_pbutton_create(ui_res, "Cancel", &demo.pb2);
490 if (rc != EOK) {
491 printf("Error creating button.\n");
492 return rc;
493 }
494
495 ui_pbutton_set_cb(demo.pb2, &pbutton_cb, (void *) &demo);
496
497 rect.p0.x = 115;
498 rect.p0.y = 111;
499 rect.p1.x = 205;
500 rect.p1.y = 139;
501 ui_pbutton_set_rect(demo.pb2, &rect);
502
503 rc = ui_fixed_add(demo.fixed, ui_pbutton_ctl(demo.pb2));
504 if (rc != EOK) {
505 printf("Error adding control to layout.\n");
506 return rc;
507 }
508
509 gfx_bitmap_params_init(&bparams);
510 bparams.rect.p0.x = 0;
511 bparams.rect.p0.y = 0;
512 bparams.rect.p1.x = 188;
513 bparams.rect.p1.y = 24;
514
515 rc = gfx_bitmap_create(gc, &bparams, NULL, &bitmap);
516 if (rc != EOK)
517 return rc;
518
519 rc = bitmap_moire(bitmap, bparams.rect.p1.x, bparams.rect.p1.y);
520 if (rc != EOK)
521 return rc;
522
523 rc = ui_image_create(ui_res, bitmap, &params.rect, &demo.image);
524 if (rc != EOK) {
525 printf("Error creating label.\n");
526 return rc;
527 }
528
529 off.x = 15;
530 off.y = 155;
531 gfx_rect_translate(&off, &bparams.rect, &rect);
532
533 /* Adjust for frame width (2 x 1 pixel) */
534 rect.p1.x += 2;
535 rect.p1.y += 2;
536 ui_image_set_rect(demo.image, &rect);
537 ui_image_set_flags(demo.image, ui_imgf_frame);
538
539 rc = ui_fixed_add(demo.fixed, ui_image_ctl(demo.image));
540 if (rc != EOK) {
541 printf("Error adding control to layout.\n");
542 return rc;
543 }
544
545 rc = ui_checkbox_create(ui_res, "Check me", &demo.checkbox);
546 if (rc != EOK) {
547 printf("Error creating check box.\n");
548 return rc;
549 }
550
551 ui_checkbox_set_cb(demo.checkbox, &checkbox_cb, (void *) &demo);
552
553 rect.p0.x = 15;
554 rect.p0.y = 190;
555 rect.p1.x = 140;
556 rect.p1.y = 210;
557 ui_checkbox_set_rect(demo.checkbox, &rect);
558
559 rc = ui_fixed_add(demo.fixed, ui_checkbox_ctl(demo.checkbox));
560 if (rc != EOK) {
561 printf("Error adding control to layout.\n");
562 return rc;
563 }
564
565 rc = ui_rbutton_group_create(ui_res, &demo.rbgroup);
566 if (rc != EOK) {
567 printf("Error creating radio button group.\n");
568 return rc;
569 }
570
571 rc = ui_rbutton_create(demo.rbgroup, "Option 1", (void *) "First",
572 &demo.rb1);
573 if (rc != EOK) {
574 printf("Error creating radio button.\n");
575 return rc;
576 }
577
578 ui_rbutton_group_set_cb(demo.rbgroup, &rbutton_group_cb,
579 (void *) &demo);
580
581 rect.p0.x = 15;
582 rect.p0.y = 220;
583 rect.p1.x = 140;
584 rect.p1.y = 240;
585 ui_rbutton_set_rect(demo.rb1, &rect);
586
587 rc = ui_fixed_add(demo.fixed, ui_rbutton_ctl(demo.rb1));
588 if (rc != EOK) {
589 printf("Error adding control to layout.\n");
590 return rc;
591 }
592
593 rc = ui_rbutton_create(demo.rbgroup, "Option 2", (void *) "Second",
594 &demo.rb2);
595 if (rc != EOK) {
596 printf("Error creating radio button.\n");
597 return rc;
598 }
599
600 rect.p0.x = 15;
601 rect.p0.y = 250;
602 rect.p1.x = 140;
603 rect.p1.y = 270;
604 ui_rbutton_set_rect(demo.rb2, &rect);
605
606 rc = ui_fixed_add(demo.fixed, ui_rbutton_ctl(demo.rb2));
607 if (rc != EOK) {
608 printf("Error adding control to layout.\n");
609 return rc;
610 }
611
612 rc = ui_rbutton_create(demo.rbgroup, "Option 3", (void *) "Third",
613 &demo.rb3);
614 if (rc != EOK) {
615 printf("Error creating radio button.\n");
616 return rc;
617 }
618
619 rect.p0.x = 15;
620 rect.p0.y = 280;
621 rect.p1.x = 140;
622 rect.p1.y = 300;
623 ui_rbutton_set_rect(demo.rb3, &rect);
624
625 rc = ui_fixed_add(demo.fixed, ui_rbutton_ctl(demo.rb3));
626 if (rc != EOK) {
627 printf("Error adding control to layout.\n");
628 return rc;
629 }
630
631 rc = ui_slider_create(ui_res, "Slide!", &demo.slider);
632 if (rc != EOK) {
633 printf("Error creating button.\n");
634 return rc;
635 }
636
637 ui_slider_set_cb(demo.slider, &slider_cb, (void *) &demo);
638
639 rect.p0.x = 15;
640 rect.p0.y = 310;
641 rect.p1.x = 130;
642 rect.p1.y = 330;
643 ui_slider_set_rect(demo.slider, &rect);
644
645 rc = ui_fixed_add(demo.fixed, ui_slider_ctl(demo.slider));
646 if (rc != EOK) {
647 printf("Error adding control to layout.\n");
648 return rc;
649 }
650
651 ui_window_add(window, ui_fixed_ctl(demo.fixed));
652
653 rc = ui_window_paint(window);
654 if (rc != EOK) {
655 printf("Error painting window.\n");
656 return rc;
657 }
658
659 ui_run(ui);
660
661 ui_window_destroy(window);
662 ui_destroy(ui);
663
664 return EOK;
665}
666
667/** Fill bitmap with moire pattern.
668 *
669 * @param bitmap Bitmap
670 * @param w Bitmap width
671 * @param h Bitmap height
672 * @return EOK on success or an error code
673 */
674static errno_t bitmap_moire(gfx_bitmap_t *bitmap, gfx_coord_t w, gfx_coord_t h)
675{
676 int i, j;
677 int k;
678 pixelmap_t pixelmap;
679 gfx_bitmap_alloc_t alloc;
680 errno_t rc;
681
682 rc = gfx_bitmap_get_alloc(bitmap, &alloc);
683 if (rc != EOK)
684 return rc;
685
686 /* In absence of anything else, use pixelmap */
687 pixelmap.width = w;
688 pixelmap.height = h;
689 pixelmap.data = alloc.pixels;
690
691 for (i = 0; i < w; i++) {
692 for (j = 0; j < h; j++) {
693 k = i * i + j * j;
694 pixelmap_put_pixel(&pixelmap, i, j,
695 PIXEL(255, k, k, 255 - k));
696 }
697 }
698
699 return EOK;
700}
701
702static void print_syntax(void)
703{
704 printf("Syntax: uidemo [-d <display-spec>]\n");
705}
706
707int main(int argc, char *argv[])
708{
709 const char *display_spec = UI_DISPLAY_DEFAULT;
710 errno_t rc;
711 int i;
712
713 i = 1;
714 while (i < argc && argv[i][0] == '-') {
715 if (str_cmp(argv[i], "-d") == 0) {
716 ++i;
717 if (i >= argc) {
718 printf("Argument missing.\n");
719 print_syntax();
720 return 1;
721 }
722
723 display_spec = argv[i++];
724 } else {
725 printf("Invalid option '%s'.\n", argv[i]);
726 print_syntax();
727 return 1;
728 }
729 }
730
731 if (i < argc) {
732 print_syntax();
733 return 1;
734 }
735
736 rc = ui_demo(display_spec);
737 if (rc != EOK)
738 return 1;
739
740 return 0;
741}
742
743/** @}
744 */
Note: See TracBrowser for help on using the repository browser.