source: mainline/uspace/lib/ui/src/scrollbar.c@ d4ea1f6

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

Scroll as soon as scroll button is pressed

  • Property mode set to 100644
File size: 22.0 KB
Line 
1/*
2 * Copyright (c) 2022 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 libui
30 * @{
31 */
32/**
33 * @file Scrollbar
34 *
35 * Anatomy of a horizontal scrollbar:
36 *
37 * Up Down
38 * through through
39 * +---+------+--------+---------+---+
40 * | < | | ||| | | > |
41 * +---+------+--------+---------+---+
42 * Up Thumb Down
43 * button button
44 *
45 * +-------- Through --------+
46 *
47 * Scrollbar uses the same terminology whether it is running in horizontal
48 * or vertical mode, in horizontal mode up means left, down means right
49 * (i.e. lower and higher coordinates, respectively).
50 *
51 * The thumb can be dragged to a specific position, resulting in a move
52 * event. The up/down buttons generate up/down events. Pressing a mouse
53 * button on the up/down through generates page up / page down events.
54 *
55 * TODO: Up/down buttons/throughs should be equipped with an autorepeat
56 * mechanism: after an initial delay, start repeating at a preset rate.
57 */
58
59#include <errno.h>
60#include <gfx/color.h>
61#include <gfx/context.h>
62#include <gfx/render.h>
63#include <gfx/text.h>
64#include <io/pos_event.h>
65#include <stdlib.h>
66#include <str.h>
67#include <ui/control.h>
68#include <ui/paint.h>
69#include <ui/pbutton.h>
70#include <ui/scrollbar.h>
71#include "../private/resource.h"
72#include "../private/scrollbar.h"
73
74enum {
75 /** Scrollbar button width */
76 ui_scrollbar_btn_len = 20,
77 /** Scrollbar button width in text mode */
78 ui_scrollbar_btn_len_text = 1,
79 /** Scrollbar thumb frame thickness */
80 ui_scrollbar_thumb_frame_thickness = 1,
81 /** Scrollbar thumb bevel width */
82 ui_scrollbar_thumb_bevel_width = 2,
83 /** Scrollbar default thumb length */
84 ui_scrollbar_def_thumb_len = 20,
85 /** Scrollbar default thumb length in text mode */
86 ui_scrollbar_def_thumb_len_text = 1,
87 /** Scrollbar minimum thumb length */
88 ui_scrollbar_min_thumb_len = 10,
89 /** Scrollbar minimum thumb length in text mode */
90 ui_scrollbar_min_thumb_len_text = 1,
91};
92
93static void ui_scrollbar_up_btn_down(ui_pbutton_t *, void *);
94static void ui_scrollbar_down_btn_down(ui_pbutton_t *, void *);
95static void ui_scrollbar_ctl_destroy(void *);
96static errno_t ui_scrollbar_ctl_paint(void *);
97static ui_evclaim_t ui_scrollbar_ctl_pos_event(void *, pos_event_t *);
98
99ui_pbutton_cb_t ui_scrollbar_up_btn_cb = {
100 .down = ui_scrollbar_up_btn_down
101};
102
103ui_pbutton_cb_t ui_scrollbar_down_btn_cb = {
104 .down = ui_scrollbar_down_btn_down
105};
106
107/** Scrollbar control ops */
108ui_control_ops_t ui_scrollbar_ops = {
109 .destroy = ui_scrollbar_ctl_destroy,
110 .paint = ui_scrollbar_ctl_paint,
111 .pos_event = ui_scrollbar_ctl_pos_event
112};
113
114/** Create new scrollbar.
115 *
116 * @param resource UI resource
117 * @param rscrollbar Place to store pointer to new scrollbar
118 * @return EOK on success, ENOMEM if out of memory
119 */
120errno_t ui_scrollbar_create(ui_resource_t *resource,
121 ui_scrollbar_t **rscrollbar)
122{
123 ui_scrollbar_t *scrollbar;
124 errno_t rc;
125
126 scrollbar = calloc(1, sizeof(ui_scrollbar_t));
127 if (scrollbar == NULL)
128 return ENOMEM;
129
130 rc = ui_control_new(&ui_scrollbar_ops, (void *) scrollbar,
131 &scrollbar->control);
132 if (rc != EOK) {
133 free(scrollbar);
134 return rc;
135 }
136
137 rc = ui_pbutton_create(resource, resource->textmode ? "\u25c4" : "<",
138 &scrollbar->up_btn);
139 if (rc != EOK)
140 goto error;
141
142 ui_pbutton_set_cb(scrollbar->up_btn, &ui_scrollbar_up_btn_cb,
143 (void *) scrollbar);
144
145 rc = ui_pbutton_create(resource, resource->textmode ? "\u25ba" : ">",
146 &scrollbar->down_btn);
147 if (rc != EOK)
148 goto error;
149
150 ui_pbutton_set_cb(scrollbar->down_btn, &ui_scrollbar_down_btn_cb,
151 (void *) scrollbar);
152
153 scrollbar->thumb_len = resource->textmode ?
154 ui_scrollbar_def_thumb_len_text :
155 ui_scrollbar_def_thumb_len;
156
157 scrollbar->res = resource;
158 *rscrollbar = scrollbar;
159 return EOK;
160error:
161 ui_scrollbar_destroy(scrollbar);
162 return rc;
163}
164
165/** Destroy scrollbar.
166 *
167 * @param scrollbar Scrollbar or @c NULL
168 */
169void ui_scrollbar_destroy(ui_scrollbar_t *scrollbar)
170{
171 if (scrollbar == NULL)
172 return;
173
174 ui_pbutton_destroy(scrollbar->up_btn);
175 ui_pbutton_destroy(scrollbar->down_btn);
176 ui_control_delete(scrollbar->control);
177 free(scrollbar);
178}
179
180/** Get base control from scrollbar.
181 *
182 * @param scrollbar Scrollbar
183 * @return Control
184 */
185ui_control_t *ui_scrollbar_ctl(ui_scrollbar_t *scrollbar)
186{
187 return scrollbar->control;
188}
189
190/** Set scrollbar callbacks.
191 *
192 * @param scrollbar Scrollbar
193 * @param cb Scrollbar callbacks
194 * @param arg Callback argument
195 */
196void ui_scrollbar_set_cb(ui_scrollbar_t *scrollbar, ui_scrollbar_cb_t *cb, void *arg)
197{
198 scrollbar->cb = cb;
199 scrollbar->arg = arg;
200}
201
202/** Set scrollbar rectangle.
203 *
204 * @param scrollbar Scrollbar
205 * @param rect New scrollbar rectangle
206 */
207void ui_scrollbar_set_rect(ui_scrollbar_t *scrollbar, gfx_rect_t *rect)
208{
209 ui_scrollbar_geom_t geom;
210
211 scrollbar->rect = *rect;
212
213 ui_scrollbar_get_geom(scrollbar, &geom);
214 ui_pbutton_set_rect(scrollbar->up_btn, &geom.up_btn_rect);
215 ui_pbutton_set_rect(scrollbar->down_btn, &geom.down_btn_rect);
216}
217
218/** Paint outer thumb frame.
219 *
220 * @param scrollbar Scrollbar
221 * @return EOK on success or an error code
222 */
223static errno_t ui_scrollbar_paint_thumb_frame(ui_resource_t *res, gfx_rect_t *rect,
224 gfx_coord_t thickness, gfx_rect_t *inside)
225{
226 gfx_rect_t drect;
227 errno_t rc;
228
229 rc = gfx_set_color(res->gc, res->btn_frame_color);
230 if (rc != EOK)
231 goto error;
232
233 drect.p0.x = rect->p0.x + 1;
234 drect.p0.y = rect->p0.y;
235 drect.p1.x = rect->p1.x - 1;
236 drect.p1.y = rect->p0.y + thickness;
237 rc = gfx_fill_rect(res->gc, &drect);
238 if (rc != EOK)
239 goto error;
240
241 drect.p0.x = rect->p0.x + 1;
242 drect.p0.y = rect->p1.y - thickness;
243 drect.p1.x = rect->p1.x - 1;
244 drect.p1.y = rect->p1.y;
245 rc = gfx_fill_rect(res->gc, &drect);
246 if (rc != EOK)
247 goto error;
248
249 drect.p0.x = rect->p0.x;
250 drect.p0.y = rect->p0.y + 1;
251 drect.p1.x = rect->p0.x + thickness;
252 drect.p1.y = rect->p1.y - 1;
253 rc = gfx_fill_rect(res->gc, &drect);
254 if (rc != EOK)
255 goto error;
256
257 drect.p0.x = rect->p1.x - thickness;
258 drect.p0.y = rect->p0.y + 1;
259 drect.p1.x = rect->p1.x;
260 drect.p1.y = rect->p1.y - 1;
261 rc = gfx_fill_rect(res->gc, &drect);
262 if (rc != EOK)
263 goto error;
264
265 if (inside != NULL) {
266 inside->p0.x = rect->p0.x + thickness;
267 inside->p0.y = rect->p0.y + thickness;
268 inside->p1.x = rect->p1.x - thickness;
269 inside->p1.y = rect->p1.y - thickness;
270 }
271
272 return EOK;
273error:
274 return rc;
275}
276
277/** Paint outset scrollbar bevel.
278 *
279 * @param scrollbar Scrollbar
280 * @return EOK on success or an error code
281 */
282static errno_t ui_scrollbar_paint_outset(ui_scrollbar_t *scrollbar,
283 gfx_rect_t *rect, gfx_rect_t *inside)
284{
285 return ui_paint_bevel(scrollbar->res->gc, rect,
286 scrollbar->res->btn_highlight_color,
287 scrollbar->res->btn_shadow_color, ui_scrollbar_thumb_bevel_width, inside);
288}
289
290/** Determine scrollbar thumb rectagle.
291 *
292 * @param scrollbar Scrollbar
293 */
294static void ui_scrollbar_thumb_rect(ui_scrollbar_t *scrollbar, gfx_rect_t *rect)
295{
296 ui_scrollbar_geom_t geom;
297
298 ui_scrollbar_get_geom(scrollbar, &geom);
299 *rect = geom.thumb_rect;
300}
301
302/** Determine scrollbar through length.
303 *
304 * Return the size of the space within which the thumb can move
305 * (without subtracting the length of the thumb).
306 *
307 * @param scrollbar Scrollbar
308 * @return Scrollbar through length in pixels
309 */
310gfx_coord_t ui_scrollbar_through_length(ui_scrollbar_t *scrollbar)
311{
312 gfx_coord2_t dims;
313 gfx_coord_t w;
314
315 gfx_rect_dims(&scrollbar->rect, &dims);
316 w = scrollbar->res->textmode ? ui_scrollbar_btn_len_text :
317 ui_scrollbar_btn_len;
318 return dims.x - 2 * w;
319}
320
321/** Determine scrollbar move length.
322 *
323 * Return the maximum distance the thumb can move.
324 *
325 * @param scrollbar Scrollbar
326 * @return Scrollbar move length in pixels
327 */
328gfx_coord_t ui_scrollbar_move_length(ui_scrollbar_t *scrollbar)
329{
330 return ui_scrollbar_through_length(scrollbar) -
331 scrollbar->thumb_len;
332}
333
334/** Set scrollbar thumb length.
335 *
336 * @param scrollbar Scrollbar
337 * @param len Thumb length in pixels
338 */
339void ui_scrollbar_set_thumb_length(ui_scrollbar_t *scrollbar, gfx_coord_t len)
340{
341 gfx_coord_t min_len;
342 gfx_coord_t max_len;
343
344 min_len = scrollbar->res->textmode ?
345 ui_scrollbar_min_thumb_len_text :
346 ui_scrollbar_min_thumb_len;
347
348 max_len = ui_scrollbar_through_length(scrollbar);
349 if (len < min_len)
350 len = min_len;
351 if (len > max_len)
352 len = max_len;
353
354 if (len != scrollbar->thumb_len) {
355 (void) ui_scrollbar_thumb_clear(scrollbar);
356 scrollbar->thumb_len = len;
357 (void) ui_scrollbar_paint(scrollbar);
358 }
359}
360
361/** Get scrollbar thumb position.
362 *
363 * @param scrollbar Scrollbar
364 * @return Scrollbar thumb position in pixels
365 */
366gfx_coord_t ui_scrollbar_get_pos(ui_scrollbar_t *scrollbar)
367{
368 return scrollbar->pos;
369}
370
371/** Set scrollbar thumb position.
372 *
373 * The position is clipped to the allowed range.
374 *
375 * @param scrollbar Scrollbar
376 * @parap pos Scrollbar thumb position in pixels
377 */
378void ui_scrollbar_set_pos(ui_scrollbar_t *scrollbar, gfx_coord_t pos)
379{
380 gfx_coord_t length;
381
382 length = ui_scrollbar_move_length(scrollbar);
383 if (pos < 0)
384 pos = 0;
385 if (pos > length)
386 pos = length;
387
388 if (pos != scrollbar->pos) {
389 (void) ui_scrollbar_thumb_clear(scrollbar);
390 scrollbar->pos = pos;
391 (void) ui_scrollbar_paint(scrollbar);
392 ui_scrollbar_moved(scrollbar, pos);
393 }
394}
395
396/** Paint scrollbar in graphics mode.
397 *
398 * @param scrollbar Scrollbar
399 * @return EOK on success or an error code
400 */
401errno_t ui_scrollbar_paint_gfx(ui_scrollbar_t *scrollbar)
402{
403 ui_scrollbar_geom_t geom;
404 gfx_rect_t brect;
405 gfx_rect_t irect;
406 errno_t rc;
407
408 ui_scrollbar_get_geom(scrollbar, &geom);
409
410 /* Paint scrollbar frame */
411
412 rc = ui_paint_inset_frame(scrollbar->res, &scrollbar->rect, NULL);
413 if (rc != EOK)
414 goto error;
415
416 /* Paint scrollbar up through */
417 rc = gfx_set_color(scrollbar->res->gc,
418 scrollbar->up_through_held ?
419 scrollbar->res->sbar_act_through_color :
420 scrollbar->res->sbar_through_color);
421 if (rc != EOK)
422 goto error;
423
424 rc = gfx_fill_rect(scrollbar->res->gc, &geom.up_through_rect);
425 if (rc != EOK)
426 goto error;
427
428 /* Paint scrollbar down through */
429
430 rc = gfx_set_color(scrollbar->res->gc,
431 scrollbar->down_through_held ?
432 scrollbar->res->sbar_act_through_color :
433 scrollbar->res->sbar_through_color);
434 if (rc != EOK)
435 goto error;
436
437 rc = gfx_fill_rect(scrollbar->res->gc, &geom.down_through_rect);
438 if (rc != EOK)
439 goto error;
440
441 /* Paint scrollbar thumb */
442
443 rc = ui_scrollbar_paint_thumb_frame(scrollbar->res, &geom.thumb_rect,
444 ui_scrollbar_thumb_frame_thickness, &brect);
445 if (rc != EOK)
446 goto error;
447
448 rc = ui_scrollbar_paint_outset(scrollbar, &brect, &irect);
449 if (rc != EOK)
450 goto error;
451
452 rc = gfx_set_color(scrollbar->res->gc, scrollbar->res->btn_face_color);
453 if (rc != EOK)
454 goto error;
455
456 rc = gfx_fill_rect(scrollbar->res->gc, &irect);
457 if (rc != EOK)
458 goto error;
459
460 rc = ui_pbutton_paint(scrollbar->up_btn);
461 if (rc != EOK)
462 goto error;
463
464 rc = ui_pbutton_paint(scrollbar->down_btn);
465 if (rc != EOK)
466 goto error;
467
468 rc = gfx_update(scrollbar->res->gc);
469 if (rc != EOK)
470 goto error;
471
472 return EOK;
473error:
474 return rc;
475}
476
477/** Paint scrollbar in text mode.
478 *
479 * @param scrollbar Scrollbar
480 * @return EOK on success or an error code
481 */
482errno_t ui_scrollbar_paint_text(ui_scrollbar_t *scrollbar)
483{
484 gfx_coord2_t pos;
485 gfx_text_fmt_t fmt;
486 gfx_coord_t w, i;
487 char *buf;
488 const char *gchar;
489 size_t gcharsz;
490 errno_t rc;
491
492 /* Paint scrollbar through */
493
494 pos = scrollbar->rect.p0;
495 pos.x += ui_scrollbar_btn_len_text;
496
497 gfx_text_fmt_init(&fmt);
498 fmt.font = scrollbar->res->font;
499 fmt.color = scrollbar->res->sbar_through_color;
500 fmt.halign = gfx_halign_left;
501 fmt.valign = gfx_valign_top;
502
503 w = scrollbar->rect.p1.x - scrollbar->rect.p0.x -
504 2 * ui_scrollbar_btn_len_text;
505 assert(w >= 0);
506 if (w < 0)
507 return EINVAL;
508
509 gchar = "\u2592";
510 gcharsz = str_size(gchar);
511
512 buf = malloc(w * gcharsz + 1);
513 if (buf == NULL)
514 return ENOMEM;
515
516 for (i = 0; i < w; i++)
517 str_cpy(buf + i * gcharsz, (w - i) * gcharsz + 1, gchar);
518 buf[w * gcharsz] = '\0';
519
520 rc = gfx_puttext(&pos, &fmt, buf);
521 free(buf);
522 if (rc != EOK)
523 goto error;
524
525 /* Paint scrollbar thumb */
526
527 pos.x += scrollbar->pos;
528
529 gchar = "\u25a0";
530 gcharsz = str_size(gchar);
531 w = scrollbar->thumb_len;
532
533 buf = malloc(w * gcharsz + 1);
534 if (buf == NULL)
535 return ENOMEM;
536
537 for (i = 0; i < w; i++)
538 str_cpy(buf + i * gcharsz, (w - i) * gcharsz + 1, gchar);
539 buf[w * gcharsz] = '\0';
540
541 rc = gfx_puttext(&pos, &fmt, buf);
542 free(buf);
543 if (rc != EOK)
544 goto error;
545
546 rc = ui_pbutton_paint(scrollbar->up_btn);
547 if (rc != EOK)
548 goto error;
549
550 rc = ui_pbutton_paint(scrollbar->down_btn);
551 if (rc != EOK)
552 goto error;
553
554 rc = gfx_update(scrollbar->res->gc);
555 if (rc != EOK)
556 goto error;
557
558 return EOK;
559error:
560 return rc;
561}
562
563/** Paint scrollbar.
564 *
565 * @param scrollbar Scrollbar
566 * @return EOK on success or an error code
567 */
568errno_t ui_scrollbar_paint(ui_scrollbar_t *scrollbar)
569{
570 if (scrollbar->res->textmode)
571 return ui_scrollbar_paint_text(scrollbar);
572 else
573 return ui_scrollbar_paint_gfx(scrollbar);
574}
575
576/** Get scrollbar geometry.
577 *
578 * @param scrollbar Scrollbar
579 * @param geom Structure to fill in with computed geometry
580 */
581void ui_scrollbar_get_geom(ui_scrollbar_t *scrollbar, ui_scrollbar_geom_t *geom)
582{
583 gfx_coord_t btn_len;
584 gfx_rect_t orect;
585 gfx_rect_t irect;
586
587 if (scrollbar->res->textmode) {
588 btn_len = ui_scrollbar_btn_len_text;
589 } else {
590 btn_len = ui_scrollbar_btn_len;
591 }
592
593 if (scrollbar->res->textmode) {
594 irect = scrollbar->rect;
595 orect = scrollbar->rect;
596 } else {
597 ui_paint_get_inset_frame_inside(scrollbar->res,
598 &scrollbar->rect, &irect);
599 ui_paint_get_bevel_inside(scrollbar->res->gc,
600 &scrollbar->rect, 1, &orect);
601 }
602
603 /* Up button */
604 geom->up_btn_rect.p0.x = orect.p0.x;
605 geom->up_btn_rect.p0.y = orect.p0.y;
606 geom->up_btn_rect.p1.x = orect.p0.x + btn_len;
607 geom->up_btn_rect.p1.y = orect.p1.y;
608
609 /* Through */
610 geom->through_rect.p0.x = geom->up_btn_rect.p1.x;
611 geom->through_rect.p0.y = irect.p0.y;
612 geom->through_rect.p1.x = orect.p1.x - btn_len;
613 geom->through_rect.p1.y = irect.p1.y;
614
615 /* Thumb */
616 geom->thumb_rect.p0.x = geom->up_btn_rect.p1.x + scrollbar->pos;
617 geom->thumb_rect.p0.y = orect.p0.y;
618 geom->thumb_rect.p1.x = geom->thumb_rect.p0.x + scrollbar->thumb_len;
619 geom->thumb_rect.p1.y = orect.p1.y;
620
621 /* Up through */
622 geom->up_through_rect.p0 = geom->through_rect.p0;
623 geom->up_through_rect.p1.x = geom->thumb_rect.p0.x;
624 geom->up_through_rect.p1.y = geom->through_rect.p1.y;
625
626 /* Down through */
627 geom->down_through_rect.p0.x = geom->thumb_rect.p1.x;
628 geom->down_through_rect.p0.y = geom->through_rect.p0.y;
629 geom->down_through_rect.p1 = geom->through_rect.p1;
630
631 /* Down button */
632 geom->down_btn_rect.p0.x = geom->through_rect.p1.x;
633 geom->down_btn_rect.p0.y = orect.p0.y;
634 geom->down_btn_rect.p1.x = orect.p1.x;
635 geom->down_btn_rect.p1.y = orect.p1.y;
636}
637
638/** Clear scrollbar thumb.
639 *
640 * @param scrollbar Scrollbar
641 * @return EOK on success or an error code
642 */
643errno_t ui_scrollbar_thumb_clear(ui_scrollbar_t *scrollbar)
644{
645 gfx_rect_t rect;
646 errno_t rc;
647
648 /* No need to clear thumb in text mode */
649 if (scrollbar->res->textmode)
650 return EOK;
651
652 ui_scrollbar_thumb_rect(scrollbar, &rect);
653
654 rc = gfx_set_color(scrollbar->res->gc, scrollbar->res->wnd_face_color);
655 if (rc != EOK)
656 goto error;
657
658 rc = gfx_fill_rect(scrollbar->res->gc, &rect);
659 if (rc != EOK)
660 goto error;
661
662 return EOK;
663error:
664 return rc;
665}
666
667/** Press down scrollbar thumb.
668 *
669 * @param scrollbar Scrollbar
670 * @param pos Pointer position
671 */
672void ui_scrollbar_thumb_press(ui_scrollbar_t *scrollbar, gfx_coord2_t *pos)
673{
674 if (scrollbar->thumb_held)
675 return;
676
677 scrollbar->thumb_held = true;
678 scrollbar->press_pos = *pos;
679 scrollbar->last_pos = scrollbar->pos;
680
681 (void) ui_scrollbar_paint(scrollbar);
682}
683
684/** Press down scrollbar up through.
685 *
686 * @param scrollbar Scrollbar
687 */
688void ui_scrollbar_up_through_press(ui_scrollbar_t *scrollbar)
689{
690 if (scrollbar->up_through_held)
691 return;
692
693 scrollbar->up_through_held = true;
694 (void) ui_scrollbar_paint(scrollbar);
695
696 ui_scrollbar_page_up(scrollbar);
697}
698
699/** Press down scrollbar down through.
700 *
701 * @param scrollbar Scrollbar
702 */
703void ui_scrollbar_down_through_press(ui_scrollbar_t *scrollbar)
704{
705 if (scrollbar->down_through_held)
706 return;
707
708 scrollbar->down_through_held = true;
709 (void) ui_scrollbar_paint(scrollbar);
710
711 ui_scrollbar_page_down(scrollbar);
712}
713
714/** Release scrollbar.
715 *
716 * @param scrollbar Scrollbar
717 * @param pos Pointer position
718 */
719void ui_scrollbar_release(ui_scrollbar_t *scrollbar, gfx_coord2_t *pos)
720{
721 if (scrollbar->thumb_held) {
722 ui_scrollbar_update(scrollbar, pos);
723 scrollbar->thumb_held = false;
724 }
725
726 if (scrollbar->up_through_held || scrollbar->down_through_held) {
727 scrollbar->up_through_held = false;
728 scrollbar->down_through_held = false;
729 (void) ui_scrollbar_paint(scrollbar);
730 }
731}
732
733/** Pointer moved.
734 *
735 * @param scrollbar Scrollbar
736 * @param pos New pointer position
737 */
738void ui_scrollbar_update(ui_scrollbar_t *scrollbar, gfx_coord2_t *pos)
739{
740 gfx_coord_t spos;
741
742 if (scrollbar->thumb_held) {
743 spos = scrollbar->last_pos + pos->x - scrollbar->press_pos.x;
744 ui_scrollbar_set_pos(scrollbar, spos);
745 }
746}
747
748/** Scrollbar up button was pressed.
749 *
750 * @param scrollbar Scrollbar
751 */
752void ui_scrollbar_up(ui_scrollbar_t *scrollbar)
753{
754 if (scrollbar->cb != NULL && scrollbar->cb->up != NULL)
755 scrollbar->cb->up(scrollbar, scrollbar->arg);
756}
757
758/** Scrollbar down button was pressed.
759 *
760 * @param scrollbar Scrollbar
761 */
762void ui_scrollbar_down(ui_scrollbar_t *scrollbar)
763{
764 if (scrollbar->cb != NULL && scrollbar->cb->down != NULL)
765 scrollbar->cb->down(scrollbar, scrollbar->arg);
766}
767
768/** Scrollbar up through was pressed.
769 *
770 * @param scrollbar Scrollbar
771 */
772void ui_scrollbar_page_up(ui_scrollbar_t *scrollbar)
773{
774 if (scrollbar->cb != NULL && scrollbar->cb->page_up != NULL)
775 scrollbar->cb->page_up(scrollbar, scrollbar->arg);
776}
777
778/** Scrollbar down through was pressed.
779 *
780 * @param scrollbar Scrollbar
781 */
782void ui_scrollbar_page_down(ui_scrollbar_t *scrollbar)
783{
784 if (scrollbar->cb != NULL && scrollbar->cb->page_down != NULL)
785 scrollbar->cb->page_down(scrollbar, scrollbar->arg);
786}
787
788/** Scrollbar was moved.
789 *
790 * @param scrollbar Scrollbar
791 */
792void ui_scrollbar_moved(ui_scrollbar_t *scrollbar, gfx_coord_t pos)
793{
794 if (scrollbar->cb != NULL && scrollbar->cb->moved != NULL)
795 scrollbar->cb->moved(scrollbar, scrollbar->arg, pos);
796}
797
798/** Handle scrollbar position event.
799 *
800 * @param scrollbar Scrollbar
801 * @param pos_event Position event
802 * @return @c ui_claimed iff the event is claimed
803 */
804ui_evclaim_t ui_scrollbar_pos_event(ui_scrollbar_t *scrollbar, pos_event_t *event)
805{
806 gfx_coord2_t pos;
807 ui_evclaim_t claimed;
808 ui_scrollbar_geom_t geom;
809
810 ui_scrollbar_get_geom(scrollbar, &geom);
811
812 pos.x = event->hpos;
813 pos.y = event->vpos;
814
815 claimed = ui_pbutton_pos_event(scrollbar->up_btn, event);
816 if (claimed == ui_claimed)
817 return ui_claimed;
818
819 claimed = ui_pbutton_pos_event(scrollbar->down_btn, event);
820 if (claimed == ui_claimed)
821 return ui_claimed;
822
823 switch (event->type) {
824 case POS_PRESS:
825 if (gfx_pix_inside_rect(&pos, &geom.thumb_rect)) {
826 ui_scrollbar_thumb_press(scrollbar, &pos);
827 return ui_claimed;
828 }
829 if (gfx_pix_inside_rect(&pos, &geom.up_through_rect)) {
830 ui_scrollbar_up_through_press(scrollbar);
831 return ui_claimed;
832 }
833 if (gfx_pix_inside_rect(&pos, &geom.down_through_rect)) {
834 ui_scrollbar_down_through_press(scrollbar);
835 return ui_claimed;
836 }
837 break;
838 case POS_RELEASE:
839 if (scrollbar->thumb_held || scrollbar->up_through_held ||
840 scrollbar->down_through_held) {
841 ui_scrollbar_release(scrollbar, &pos);
842 return ui_claimed;
843 }
844 break;
845 case POS_UPDATE:
846 ui_scrollbar_update(scrollbar, &pos);
847 break;
848 case POS_DCLICK:
849 break;
850 }
851
852 return ui_unclaimed;
853}
854
855/** Scrollbar up button pressed.
856 *
857 * @param pbutton Up button
858 * @param arg Argument (ui_scrollbar_t *)
859 */
860static void ui_scrollbar_up_btn_down(ui_pbutton_t *pbutton, void *arg)
861{
862 ui_scrollbar_t *scrollbar = (ui_scrollbar_t *)arg;
863
864 ui_scrollbar_up(scrollbar);
865}
866
867/** Scrollbar down button pressed.
868 *
869 * @param pbutton Down button
870 * @param arg Argument (ui_scrollbar_t *)
871 */
872static void ui_scrollbar_down_btn_down(ui_pbutton_t *pbutton, void *arg)
873{
874 ui_scrollbar_t *scrollbar = (ui_scrollbar_t *)arg;
875
876 ui_scrollbar_down(scrollbar);
877}
878
879/** Destroy scrollbar control.
880 *
881 * @param arg Argument (ui_scrollbar_t *)
882 */
883void ui_scrollbar_ctl_destroy(void *arg)
884{
885 ui_scrollbar_t *scrollbar = (ui_scrollbar_t *) arg;
886
887 ui_scrollbar_destroy(scrollbar);
888}
889
890/** Paint scrollbar control.
891 *
892 * @param arg Argument (ui_scrollbar_t *)
893 * @return EOK on success or an error code
894 */
895errno_t ui_scrollbar_ctl_paint(void *arg)
896{
897 ui_scrollbar_t *scrollbar = (ui_scrollbar_t *) arg;
898
899 return ui_scrollbar_paint(scrollbar);
900}
901
902/** Handle scrollbar control position event.
903 *
904 * @param arg Argument (ui_scrollbar_t *)
905 * @param pos_event Position event
906 * @return @c ui_claimed iff the event is claimed
907 */
908ui_evclaim_t ui_scrollbar_ctl_pos_event(void *arg, pos_event_t *event)
909{
910 ui_scrollbar_t *scrollbar = (ui_scrollbar_t *) arg;
911
912 return ui_scrollbar_pos_event(scrollbar, event);
913}
914
915/** @}
916 */
Note: See TracBrowser for help on using the repository browser.