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

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

Routine to fill rectangle with character

Use it to simplify scrollbar rendering.

  • Property mode set to 100644
File size: 27.7 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 * Pressing and holding down mouse button on up / down button or up / down
56 * through will auto-scroll (using clickmatic).
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/clickmatic.h>
68#include <ui/control.h>
69#include <ui/paint.h>
70#include <ui/pbutton.h>
71#include <ui/scrollbar.h>
72#include <ui/ui.h>
73#include <ui/window.h>
74#include "../private/pbutton.h"
75#include "../private/resource.h"
76#include "../private/scrollbar.h"
77
78enum {
79 /** Scrollbar button width */
80 ui_scrollbar_btn_len = 20,
81 /** Scrollbar button width in text mode */
82 ui_scrollbar_btn_len_text = 1,
83 /** Scrollbar thumb frame thickness */
84 ui_scrollbar_thumb_frame_thickness = 1,
85 /** Scrollbar thumb bevel width */
86 ui_scrollbar_thumb_bevel_width = 2,
87 /** Scrollbar default thumb length */
88 ui_scrollbar_def_thumb_len = 20,
89 /** Scrollbar default thumb length in text mode */
90 ui_scrollbar_def_thumb_len_text = 1,
91 /** Scrollbar minimum thumb length */
92 ui_scrollbar_min_thumb_len = 10,
93 /** Scrollbar minimum thumb length in text mode */
94 ui_scrollbar_min_thumb_len_text = 1,
95};
96
97static void ui_scrollbar_up_btn_down(ui_pbutton_t *, void *);
98static void ui_scrollbar_up_btn_up(ui_pbutton_t *, void *);
99static void ui_scrollbar_down_btn_down(ui_pbutton_t *, void *);
100static void ui_scrollbar_down_btn_up(ui_pbutton_t *, void *);
101static void ui_scrollbar_ctl_destroy(void *);
102static errno_t ui_scrollbar_ctl_paint(void *);
103static ui_evclaim_t ui_scrollbar_ctl_pos_event(void *, pos_event_t *);
104
105static ui_pbutton_cb_t ui_scrollbar_up_btn_cb = {
106 .down = ui_scrollbar_up_btn_down,
107 .up = ui_scrollbar_up_btn_up
108};
109
110static ui_pbutton_cb_t ui_scrollbar_down_btn_cb = {
111 .down = ui_scrollbar_down_btn_down,
112 .up = ui_scrollbar_down_btn_up
113};
114
115/** Scrollbar control ops */
116static ui_control_ops_t ui_scrollbar_ops = {
117 .destroy = ui_scrollbar_ctl_destroy,
118 .paint = ui_scrollbar_ctl_paint,
119 .pos_event = ui_scrollbar_ctl_pos_event
120};
121
122static void ui_scrollbar_cm_up(ui_clickmatic_t *, void *);
123static void ui_scrollbar_cm_down(ui_clickmatic_t *, void *);
124static void ui_scrollbar_cm_page_up(ui_clickmatic_t *, void *);
125static void ui_scrollbar_cm_page_down(ui_clickmatic_t *, void *);
126
127/** Scrollbar clickmatic up callbacks */
128ui_clickmatic_cb_t ui_scrollbar_clickmatic_up_cb = {
129 .clicked = ui_scrollbar_cm_up
130};
131
132/** Scrollbar clickmatic down callbacks */
133ui_clickmatic_cb_t ui_scrollbar_clickmatic_down_cb = {
134 .clicked = ui_scrollbar_cm_down
135};
136
137/** Scrollbar clickmatic page up callbacks */
138ui_clickmatic_cb_t ui_scrollbar_clickmatic_page_up_cb = {
139 .clicked = ui_scrollbar_cm_page_up
140};
141
142/** Scrollbar clickmatic page down callbacks */
143ui_clickmatic_cb_t ui_scrollbar_clickmatic_page_down_cb = {
144 .clicked = ui_scrollbar_cm_page_down
145};
146
147/** Create new scrollbar.
148 *
149 * @param ui UI
150 * @param window Window containing scrollbar
151 * @param dir Scrollbar direction
152 * @param rscrollbar Place to store pointer to new scrollbar
153 * @return EOK on success, ENOMEM if out of memory
154 */
155errno_t ui_scrollbar_create(ui_t *ui, ui_window_t *window,
156 ui_scrollbar_dir_t dir, ui_scrollbar_t **rscrollbar)
157{
158 ui_scrollbar_t *scrollbar;
159 ui_resource_t *resource;
160 const char *up_text;
161 const char *down_text;
162 errno_t rc;
163
164 resource = ui_window_get_res(window);
165
166 scrollbar = calloc(1, sizeof(ui_scrollbar_t));
167 if (scrollbar == NULL)
168 return ENOMEM;
169
170 rc = ui_control_new(&ui_scrollbar_ops, (void *) scrollbar,
171 &scrollbar->control);
172 if (rc != EOK) {
173 free(scrollbar);
174 return rc;
175 }
176
177 if (dir == ui_sbd_horiz) {
178 up_text = resource->textmode ? "\u25c4" : "<";
179 down_text = resource->textmode ? "\u25ba" : ">";
180 } else {
181 up_text = resource->textmode ? "\u25b2" : "^";
182 down_text = resource->textmode ? "\u25bc" : "v";
183 }
184
185 rc = ui_pbutton_create(resource, up_text, &scrollbar->up_btn);
186 if (rc != EOK)
187 goto error;
188
189 ui_pbutton_set_cb(scrollbar->up_btn, &ui_scrollbar_up_btn_cb,
190 (void *) scrollbar);
191
192 rc = ui_pbutton_create(resource, down_text, &scrollbar->down_btn);
193 if (rc != EOK)
194 goto error;
195
196 ui_pbutton_set_cb(scrollbar->down_btn, &ui_scrollbar_down_btn_cb,
197 (void *) scrollbar);
198
199 scrollbar->thumb_len = resource->textmode ?
200 ui_scrollbar_def_thumb_len_text :
201 ui_scrollbar_def_thumb_len;
202
203 scrollbar->ui = ui;
204 scrollbar->window = window;
205 scrollbar->dir = dir;
206 *rscrollbar = scrollbar;
207 return EOK;
208error:
209 ui_scrollbar_destroy(scrollbar);
210 return rc;
211}
212
213/** Destroy scrollbar.
214 *
215 * @param scrollbar Scrollbar or @c NULL
216 */
217void ui_scrollbar_destroy(ui_scrollbar_t *scrollbar)
218{
219 if (scrollbar == NULL)
220 return;
221
222 ui_pbutton_destroy(scrollbar->up_btn);
223 ui_pbutton_destroy(scrollbar->down_btn);
224 ui_control_delete(scrollbar->control);
225 free(scrollbar);
226}
227
228/** Get base control from scrollbar.
229 *
230 * @param scrollbar Scrollbar
231 * @return Control
232 */
233ui_control_t *ui_scrollbar_ctl(ui_scrollbar_t *scrollbar)
234{
235 return scrollbar->control;
236}
237
238/** Set scrollbar callbacks.
239 *
240 * @param scrollbar Scrollbar
241 * @param cb Scrollbar callbacks
242 * @param arg Callback argument
243 */
244void ui_scrollbar_set_cb(ui_scrollbar_t *scrollbar, ui_scrollbar_cb_t *cb, void *arg)
245{
246 scrollbar->cb = cb;
247 scrollbar->arg = arg;
248}
249
250/** Set scrollbar rectangle.
251 *
252 * @param scrollbar Scrollbar
253 * @param rect New scrollbar rectangle
254 */
255void ui_scrollbar_set_rect(ui_scrollbar_t *scrollbar, gfx_rect_t *rect)
256{
257 ui_scrollbar_geom_t geom;
258
259 scrollbar->rect = *rect;
260
261 ui_scrollbar_get_geom(scrollbar, &geom);
262 ui_pbutton_set_rect(scrollbar->up_btn, &geom.up_btn_rect);
263 ui_pbutton_set_rect(scrollbar->down_btn, &geom.down_btn_rect);
264}
265
266/** Paint outer thumb frame.
267 *
268 * @param scrollbar Scrollbar
269 * @return EOK on success or an error code
270 */
271static errno_t ui_scrollbar_paint_thumb_frame(ui_resource_t *res, gfx_rect_t *rect,
272 gfx_coord_t thickness, gfx_rect_t *inside)
273{
274 gfx_rect_t drect;
275 errno_t rc;
276
277 rc = gfx_set_color(res->gc, res->btn_frame_color);
278 if (rc != EOK)
279 goto error;
280
281 drect.p0.x = rect->p0.x + 1;
282 drect.p0.y = rect->p0.y;
283 drect.p1.x = rect->p1.x - 1;
284 drect.p1.y = rect->p0.y + thickness;
285 rc = gfx_fill_rect(res->gc, &drect);
286 if (rc != EOK)
287 goto error;
288
289 drect.p0.x = rect->p0.x + 1;
290 drect.p0.y = rect->p1.y - thickness;
291 drect.p1.x = rect->p1.x - 1;
292 drect.p1.y = rect->p1.y;
293 rc = gfx_fill_rect(res->gc, &drect);
294 if (rc != EOK)
295 goto error;
296
297 drect.p0.x = rect->p0.x;
298 drect.p0.y = rect->p0.y + 1;
299 drect.p1.x = rect->p0.x + thickness;
300 drect.p1.y = rect->p1.y - 1;
301 rc = gfx_fill_rect(res->gc, &drect);
302 if (rc != EOK)
303 goto error;
304
305 drect.p0.x = rect->p1.x - thickness;
306 drect.p0.y = rect->p0.y + 1;
307 drect.p1.x = rect->p1.x;
308 drect.p1.y = rect->p1.y - 1;
309 rc = gfx_fill_rect(res->gc, &drect);
310 if (rc != EOK)
311 goto error;
312
313 if (inside != NULL) {
314 inside->p0.x = rect->p0.x + thickness;
315 inside->p0.y = rect->p0.y + thickness;
316 inside->p1.x = rect->p1.x - thickness;
317 inside->p1.y = rect->p1.y - thickness;
318 }
319
320 return EOK;
321error:
322 return rc;
323}
324
325/** Paint outset scrollbar bevel.
326 *
327 * @param scrollbar Scrollbar
328 * @return EOK on success or an error code
329 */
330static errno_t ui_scrollbar_paint_outset(ui_scrollbar_t *scrollbar,
331 gfx_rect_t *rect, gfx_rect_t *inside)
332{
333 ui_resource_t *resource = ui_window_get_res(scrollbar->window);
334
335 return ui_paint_bevel(resource->gc, rect,
336 resource->btn_highlight_color,
337 resource->btn_shadow_color, ui_scrollbar_thumb_bevel_width, inside);
338}
339
340/** Determine scrollbar through length.
341 *
342 * Return the size of the space within which the thumb can move
343 * (without subtracting the length of the thumb).
344 *
345 * @param scrollbar Scrollbar
346 * @return Scrollbar through length in pixels
347 */
348gfx_coord_t ui_scrollbar_through_length(ui_scrollbar_t *scrollbar)
349{
350 ui_resource_t *resource;
351 gfx_coord2_t dims;
352 gfx_coord_t len;
353 gfx_coord_t sblen;
354
355 resource = ui_window_get_res(scrollbar->window);
356
357 gfx_rect_dims(&scrollbar->rect, &dims);
358 sblen = scrollbar->dir == ui_sbd_horiz ?
359 dims.x : dims.y;
360
361 len = resource->textmode ? ui_scrollbar_btn_len_text :
362 ui_scrollbar_btn_len;
363
364 return sblen - 2 * len;
365}
366
367/** Determine scrollbar move length.
368 *
369 * Return the maximum distance the thumb can move.
370 *
371 * @param scrollbar Scrollbar
372 * @return Scrollbar move length in pixels
373 */
374gfx_coord_t ui_scrollbar_move_length(ui_scrollbar_t *scrollbar)
375{
376 return ui_scrollbar_through_length(scrollbar) -
377 scrollbar->thumb_len;
378}
379
380/** Set scrollbar thumb length.
381 *
382 * @param scrollbar Scrollbar
383 * @param len Thumb length in pixels
384 */
385void ui_scrollbar_set_thumb_length(ui_scrollbar_t *scrollbar, gfx_coord_t len)
386{
387 ui_resource_t *resource;
388 gfx_coord_t min_len;
389 gfx_coord_t max_len;
390
391 resource = ui_window_get_res(scrollbar->window);
392
393 min_len = resource->textmode ?
394 ui_scrollbar_min_thumb_len_text :
395 ui_scrollbar_min_thumb_len;
396
397 max_len = ui_scrollbar_through_length(scrollbar);
398 if (len < min_len)
399 len = min_len;
400 if (len > max_len)
401 len = max_len;
402
403 if (len != scrollbar->thumb_len) {
404 scrollbar->thumb_len = len;
405 (void) ui_scrollbar_paint(scrollbar);
406 }
407}
408
409/** Get scrollbar thumb position.
410 *
411 * @param scrollbar Scrollbar
412 * @return Scrollbar thumb position in pixels
413 */
414gfx_coord_t ui_scrollbar_get_pos(ui_scrollbar_t *scrollbar)
415{
416 return scrollbar->pos;
417}
418
419/** Set scrollbar thumb position.
420 *
421 * The position is clipped to the allowed range.
422 *
423 * @param scrollbar Scrollbar
424 * @parap pos Scrollbar thumb position in pixels
425 */
426void ui_scrollbar_set_pos(ui_scrollbar_t *scrollbar, gfx_coord_t pos)
427{
428 gfx_coord_t length;
429
430 length = ui_scrollbar_move_length(scrollbar);
431 if (pos < 0)
432 pos = 0;
433 if (pos > length)
434 pos = length;
435
436 if (pos != scrollbar->pos) {
437 scrollbar->pos = pos;
438 (void) ui_scrollbar_paint(scrollbar);
439 ui_scrollbar_throughs_update(scrollbar,
440 &scrollbar->last_curs_pos);
441 ui_scrollbar_moved(scrollbar, pos);
442 }
443}
444
445/** Paint scrollbar in graphics mode.
446 *
447 * @param scrollbar Scrollbar
448 * @return EOK on success or an error code
449 */
450errno_t ui_scrollbar_paint_gfx(ui_scrollbar_t *scrollbar)
451{
452 ui_resource_t *resource;
453 ui_scrollbar_geom_t geom;
454 gfx_rect_t brect;
455 gfx_rect_t irect;
456 errno_t rc;
457
458 resource = ui_window_get_res(scrollbar->window);
459
460 ui_scrollbar_get_geom(scrollbar, &geom);
461
462 /* Paint scrollbar frame */
463
464 rc = ui_paint_inset_frame(resource, &scrollbar->rect, NULL);
465 if (rc != EOK)
466 goto error;
467
468 /* Paint scrollbar up through */
469 rc = gfx_set_color(resource->gc,
470 scrollbar->up_through_held && scrollbar->up_through_inside ?
471 resource->sbar_act_through_color :
472 resource->sbar_through_color);
473 if (rc != EOK)
474 goto error;
475
476 rc = gfx_fill_rect(resource->gc, &geom.up_through_rect);
477 if (rc != EOK)
478 goto error;
479
480 /* Paint scrollbar down through */
481
482 rc = gfx_set_color(resource->gc,
483 scrollbar->down_through_held && scrollbar->down_through_inside ?
484 resource->sbar_act_through_color :
485 resource->sbar_through_color);
486 if (rc != EOK)
487 goto error;
488
489 rc = gfx_fill_rect(resource->gc, &geom.down_through_rect);
490 if (rc != EOK)
491 goto error;
492
493 /* Paint scrollbar thumb */
494 rc = ui_scrollbar_paint_thumb_frame(resource, &geom.thumb_rect,
495 ui_scrollbar_thumb_frame_thickness, &brect);
496 if (rc != EOK)
497 goto error;
498
499 rc = ui_scrollbar_paint_outset(scrollbar, &brect, &irect);
500 if (rc != EOK)
501 goto error;
502
503 rc = gfx_set_color(resource->gc, resource->btn_face_color);
504 if (rc != EOK)
505 goto error;
506
507 rc = gfx_fill_rect(resource->gc, &irect);
508 if (rc != EOK)
509 goto error;
510
511 rc = ui_pbutton_paint(scrollbar->up_btn);
512 if (rc != EOK)
513 goto error;
514
515 rc = ui_pbutton_paint(scrollbar->down_btn);
516 if (rc != EOK)
517 goto error;
518
519 rc = gfx_update(resource->gc);
520 if (rc != EOK)
521 goto error;
522
523 return EOK;
524error:
525 return rc;
526}
527
528/** Paint scrollbar in text mode.
529 *
530 * @param scrollbar Scrollbar
531 * @return EOK on success or an error code
532 */
533errno_t ui_scrollbar_paint_text(ui_scrollbar_t *scrollbar)
534{
535 ui_resource_t *resource;
536 ui_scrollbar_geom_t geom;
537 errno_t rc;
538
539 resource = ui_window_get_res(scrollbar->window);
540 ui_scrollbar_get_geom(scrollbar, &geom);
541
542 /* Paint scrollbar through */
543
544 rc = ui_paint_text_rect(resource, &geom.through_rect,
545 resource->sbar_through_color, "\u2592");
546 if (rc != EOK)
547 goto error;
548
549 /* Paint scrollbar thumb */
550
551 rc = ui_paint_text_rect(resource, &geom.thumb_rect,
552 resource->sbar_through_color, "\u25a0");
553 if (rc != EOK)
554 goto error;
555
556 /* Paint buttons */
557
558 rc = ui_pbutton_paint(scrollbar->up_btn);
559 if (rc != EOK)
560 goto error;
561
562 rc = ui_pbutton_paint(scrollbar->down_btn);
563 if (rc != EOK)
564 goto error;
565
566 rc = gfx_update(resource->gc);
567 if (rc != EOK)
568 goto error;
569
570 return EOK;
571error:
572 return rc;
573}
574
575/** Paint scrollbar.
576 *
577 * @param scrollbar Scrollbar
578 * @return EOK on success or an error code
579 */
580errno_t ui_scrollbar_paint(ui_scrollbar_t *scrollbar)
581{
582 ui_resource_t *resource = ui_window_get_res(scrollbar->window);
583
584 if (resource->textmode) {
585 return ui_scrollbar_paint_text(scrollbar);
586 } else {
587 return ui_scrollbar_paint_gfx(scrollbar);
588 }
589}
590
591/** Get scrollbar geometry.
592 *
593 * @param scrollbar Scrollbar
594 * @param geom Structure to fill in with computed geometry
595 */
596void ui_scrollbar_get_geom(ui_scrollbar_t *scrollbar, ui_scrollbar_geom_t *geom)
597{
598 ui_resource_t *resource;
599 gfx_coord_t btn_len;
600 gfx_rect_t orect;
601 gfx_rect_t irect;
602
603 resource = ui_window_get_res(scrollbar->window);
604
605 if (resource->textmode) {
606 btn_len = ui_scrollbar_btn_len_text;
607 } else {
608 btn_len = ui_scrollbar_btn_len;
609 }
610
611 if (resource->textmode) {
612 irect = scrollbar->rect;
613 orect = scrollbar->rect;
614 } else {
615 ui_paint_get_inset_frame_inside(resource,
616 &scrollbar->rect, &irect);
617 ui_paint_get_bevel_inside(resource->gc,
618 &scrollbar->rect, 1, &orect);
619 }
620
621 if (scrollbar->dir == ui_sbd_horiz) {
622 /* Up button */
623 geom->up_btn_rect.p0.x = orect.p0.x;
624 geom->up_btn_rect.p0.y = orect.p0.y;
625 geom->up_btn_rect.p1.x = orect.p0.x + btn_len;
626 geom->up_btn_rect.p1.y = orect.p1.y;
627
628 /* Through */
629 geom->through_rect.p0.x = geom->up_btn_rect.p1.x;
630 geom->through_rect.p0.y = irect.p0.y;
631 geom->through_rect.p1.x = orect.p1.x - btn_len;
632 geom->through_rect.p1.y = irect.p1.y;
633
634 /* Thumb */
635 geom->thumb_rect.p0.x = geom->up_btn_rect.p1.x +
636 scrollbar->pos;
637 geom->thumb_rect.p0.y = orect.p0.y;
638 geom->thumb_rect.p1.x = geom->thumb_rect.p0.x +
639 scrollbar->thumb_len;
640 geom->thumb_rect.p1.y = orect.p1.y;
641
642 /* Up through */
643 geom->up_through_rect.p0 = geom->through_rect.p0;
644 geom->up_through_rect.p1.x = geom->thumb_rect.p0.x;
645 geom->up_through_rect.p1.y = geom->through_rect.p1.y;
646
647 /* Down through */
648 geom->down_through_rect.p0.x = geom->thumb_rect.p1.x;
649 geom->down_through_rect.p0.y = geom->through_rect.p0.y;
650 geom->down_through_rect.p1 = geom->through_rect.p1;
651
652 /* Down button */
653 geom->down_btn_rect.p0.x = geom->through_rect.p1.x;
654 geom->down_btn_rect.p0.y = orect.p0.y;
655 geom->down_btn_rect.p1.x = orect.p1.x;
656 geom->down_btn_rect.p1.y = orect.p1.y;
657 } else {
658 /* Up button */
659 geom->up_btn_rect.p0.x = orect.p0.x;
660 geom->up_btn_rect.p0.y = orect.p0.y;
661 geom->up_btn_rect.p1.x = orect.p1.x;
662 geom->up_btn_rect.p1.y = orect.p0.y + btn_len;
663
664 /* Through */
665 geom->through_rect.p0.x = irect.p0.x;
666 geom->through_rect.p0.y = geom->up_btn_rect.p1.y;
667 geom->through_rect.p1.x = irect.p1.x;
668 geom->through_rect.p1.y = orect.p1.y - btn_len;
669
670 /* Thumb */
671 geom->thumb_rect.p0.x = orect.p0.x;
672 geom->thumb_rect.p0.y = geom->up_btn_rect.p1.y +
673 scrollbar->pos;
674 geom->thumb_rect.p1.x = orect.p1.x;
675 geom->thumb_rect.p1.y = geom->thumb_rect.p0.y +
676 scrollbar->thumb_len;
677
678 /* Up through */
679 geom->up_through_rect.p0 = geom->through_rect.p0;
680 geom->up_through_rect.p1.x = geom->through_rect.p1.x;
681 geom->up_through_rect.p1.y = geom->thumb_rect.p0.y;
682
683 /* Down through */
684 geom->down_through_rect.p0.x = geom->through_rect.p0.x;
685 geom->down_through_rect.p0.y = geom->thumb_rect.p1.y;
686 geom->down_through_rect.p1 = geom->through_rect.p1;
687
688 /* Down button */
689 geom->down_btn_rect.p0.x = orect.p0.x;
690 geom->down_btn_rect.p0.y = geom->through_rect.p1.y;
691 geom->down_btn_rect.p1.x = orect.p1.x;
692 geom->down_btn_rect.p1.y = orect.p1.y;
693 }
694}
695
696/** Press down scrollbar thumb.
697 *
698 * @param scrollbar Scrollbar
699 * @param pos Pointer position
700 */
701void ui_scrollbar_thumb_press(ui_scrollbar_t *scrollbar, gfx_coord2_t *pos)
702{
703 if (scrollbar->thumb_held)
704 return;
705
706 scrollbar->thumb_held = true;
707 scrollbar->press_pos = *pos;
708 scrollbar->last_pos = scrollbar->pos;
709
710 (void) ui_scrollbar_paint(scrollbar);
711}
712
713/** Press down scrollbar up through.
714 *
715 * @param scrollbar Scrollbar
716 */
717void ui_scrollbar_up_through_press(ui_scrollbar_t *scrollbar)
718{
719 ui_clickmatic_t *clickmatic = ui_get_clickmatic(scrollbar->ui);
720
721 scrollbar->up_through_held = true;
722 scrollbar->up_through_inside = true;
723
724 ui_clickmatic_set_cb(clickmatic, &ui_scrollbar_clickmatic_page_up_cb,
725 (void *) scrollbar);
726 ui_clickmatic_press(clickmatic);
727}
728
729/** Press down scrollbar down through.
730 *
731 * @param scrollbar Scrollbar
732 */
733void ui_scrollbar_down_through_press(ui_scrollbar_t *scrollbar)
734{
735 ui_clickmatic_t *clickmatic = ui_get_clickmatic(scrollbar->ui);
736
737 scrollbar->down_through_held = true;
738 scrollbar->down_through_inside = true;
739
740 ui_clickmatic_set_cb(clickmatic, &ui_scrollbar_clickmatic_page_down_cb,
741 (void *) scrollbar);
742 ui_clickmatic_press(clickmatic);
743}
744
745/** Release scrollbar.
746 *
747 * @param scrollbar Scrollbar
748 * @param pos Pointer position
749 */
750void ui_scrollbar_release(ui_scrollbar_t *scrollbar, gfx_coord2_t *pos)
751{
752 ui_clickmatic_t *clickmatic;
753
754 if (scrollbar->thumb_held) {
755 ui_scrollbar_update(scrollbar, pos);
756 scrollbar->thumb_held = false;
757 }
758
759 if (scrollbar->up_through_held || scrollbar->down_through_held) {
760 clickmatic = ui_get_clickmatic(scrollbar->ui);
761 ui_clickmatic_release(clickmatic);
762 ui_clickmatic_set_cb(clickmatic, NULL, NULL);
763
764 scrollbar->up_through_held = false;
765 scrollbar->down_through_held = false;
766 (void) ui_scrollbar_paint(scrollbar);
767 }
768}
769
770/** Update state of scrollbar throuhgs.
771 *
772 * Update state of scrollbar throughs after mouse cursor or thumb has moved.
773 *
774 * @param scrollbar Scrollbar
775 * @param pos Mouse cursor position
776 */
777void ui_scrollbar_throughs_update(ui_scrollbar_t *scrollbar, gfx_coord2_t *pos)
778{
779 ui_scrollbar_geom_t geom;
780 bool inside_up;
781 bool inside_down;
782
783 ui_scrollbar_get_geom(scrollbar, &geom);
784
785 inside_up = gfx_pix_inside_rect(pos, &geom.up_through_rect);
786 inside_down = gfx_pix_inside_rect(pos, &geom.down_through_rect);
787
788 if (inside_up && !scrollbar->up_through_inside) {
789 scrollbar->up_through_inside = true;
790 (void) ui_scrollbar_paint(scrollbar);
791 } else if (!inside_up && scrollbar->up_through_inside) {
792 scrollbar->up_through_inside = false;
793 (void) ui_scrollbar_paint(scrollbar);
794 }
795
796 if (inside_down && !scrollbar->down_through_inside) {
797 scrollbar->down_through_inside = true;
798 (void) ui_scrollbar_paint(scrollbar);
799 } else if (!inside_down && scrollbar->down_through_inside) {
800 scrollbar->down_through_inside = false;
801 (void) ui_scrollbar_paint(scrollbar);
802 }
803}
804
805/** Scrollbar handler for pointer movement.
806 *
807 * @param scrollbar Scrollbar
808 * @param pos New pointer position
809 */
810void ui_scrollbar_update(ui_scrollbar_t *scrollbar, gfx_coord2_t *pos)
811{
812 gfx_coord_t spos;
813
814 if (scrollbar->thumb_held) {
815 if (scrollbar->dir == ui_sbd_horiz)
816 spos = scrollbar->last_pos + pos->x - scrollbar->press_pos.x;
817 else
818 spos = scrollbar->last_pos + pos->y - scrollbar->press_pos.y;
819
820 ui_scrollbar_set_pos(scrollbar, spos);
821 }
822
823 ui_scrollbar_throughs_update(scrollbar, pos);
824}
825
826/** Scrollbar up button was pressed.
827 *
828 * @param scrollbar Scrollbar
829 */
830void ui_scrollbar_up(ui_scrollbar_t *scrollbar)
831{
832 if (scrollbar->cb != NULL && scrollbar->cb->up != NULL)
833 scrollbar->cb->up(scrollbar, scrollbar->arg);
834}
835
836/** Scrollbar down button was pressed.
837 *
838 * @param scrollbar Scrollbar
839 */
840void ui_scrollbar_down(ui_scrollbar_t *scrollbar)
841{
842 if (scrollbar->cb != NULL && scrollbar->cb->down != NULL)
843 scrollbar->cb->down(scrollbar, scrollbar->arg);
844}
845
846/** Scrollbar up through was pressed.
847 *
848 * @param scrollbar Scrollbar
849 */
850void ui_scrollbar_page_up(ui_scrollbar_t *scrollbar)
851{
852 if (scrollbar->cb != NULL && scrollbar->cb->page_up != NULL)
853 scrollbar->cb->page_up(scrollbar, scrollbar->arg);
854}
855
856/** Scrollbar down through was pressed.
857 *
858 * @param scrollbar Scrollbar
859 */
860void ui_scrollbar_page_down(ui_scrollbar_t *scrollbar)
861{
862 if (scrollbar->cb != NULL && scrollbar->cb->page_down != NULL)
863 scrollbar->cb->page_down(scrollbar, scrollbar->arg);
864}
865
866/** Scrollbar was moved.
867 *
868 * @param scrollbar Scrollbar
869 */
870void ui_scrollbar_moved(ui_scrollbar_t *scrollbar, gfx_coord_t pos)
871{
872 if (scrollbar->cb != NULL && scrollbar->cb->moved != NULL)
873 scrollbar->cb->moved(scrollbar, scrollbar->arg, pos);
874}
875
876/** Handle scrollbar position event.
877 *
878 * @param scrollbar Scrollbar
879 * @param pos_event Position event
880 * @return @c ui_claimed iff the event is claimed
881 */
882ui_evclaim_t ui_scrollbar_pos_event(ui_scrollbar_t *scrollbar, pos_event_t *event)
883{
884 gfx_coord2_t pos;
885 ui_evclaim_t claimed;
886 ui_scrollbar_geom_t geom;
887
888 ui_scrollbar_get_geom(scrollbar, &geom);
889
890 pos.x = event->hpos;
891 pos.y = event->vpos;
892
893 claimed = ui_pbutton_pos_event(scrollbar->up_btn, event);
894 if (claimed == ui_claimed)
895 return ui_claimed;
896
897 claimed = ui_pbutton_pos_event(scrollbar->down_btn, event);
898 if (claimed == ui_claimed)
899 return ui_claimed;
900
901 switch (event->type) {
902 case POS_PRESS:
903 if (gfx_pix_inside_rect(&pos, &geom.thumb_rect)) {
904 ui_scrollbar_thumb_press(scrollbar, &pos);
905 return ui_claimed;
906 }
907 if (gfx_pix_inside_rect(&pos, &geom.up_through_rect)) {
908 ui_scrollbar_up_through_press(scrollbar);
909 return ui_claimed;
910 }
911 if (gfx_pix_inside_rect(&pos, &geom.down_through_rect)) {
912 ui_scrollbar_down_through_press(scrollbar);
913 return ui_claimed;
914 }
915 break;
916 case POS_RELEASE:
917 if (scrollbar->thumb_held || scrollbar->up_through_held ||
918 scrollbar->down_through_held) {
919 ui_scrollbar_release(scrollbar, &pos);
920 return ui_claimed;
921 }
922 break;
923 case POS_UPDATE:
924 ui_scrollbar_update(scrollbar, &pos);
925 scrollbar->last_curs_pos = pos;
926 break;
927 case POS_DCLICK:
928 break;
929 }
930
931 return ui_unclaimed;
932}
933
934/** Scrollbar up button pressed.
935 *
936 * @param pbutton Up button
937 * @param arg Argument (ui_scrollbar_t *)
938 */
939static void ui_scrollbar_up_btn_down(ui_pbutton_t *pbutton, void *arg)
940{
941 ui_scrollbar_t *scrollbar = (ui_scrollbar_t *)arg;
942 ui_clickmatic_t *clickmatic = ui_get_clickmatic(scrollbar->ui);
943
944 ui_clickmatic_set_cb(clickmatic, &ui_scrollbar_clickmatic_up_cb,
945 (void *) scrollbar);
946 ui_clickmatic_press(clickmatic);
947}
948
949/** Scrollbar up button released.
950 *
951 * @param pbutton Up button
952 * @param arg Argument (ui_scrollbar_t *)
953 */
954static void ui_scrollbar_up_btn_up(ui_pbutton_t *pbutton, void *arg)
955{
956 ui_scrollbar_t *scrollbar = (ui_scrollbar_t *)arg;
957 ui_clickmatic_t *clickmatic = ui_get_clickmatic(scrollbar->ui);
958
959 ui_clickmatic_release(clickmatic);
960 ui_clickmatic_set_cb(clickmatic, NULL, NULL);
961}
962
963/** Scrollbar down button pressed.
964 *
965 * @param pbutton Down button
966 * @param arg Argument (ui_scrollbar_t *)
967 */
968static void ui_scrollbar_down_btn_down(ui_pbutton_t *pbutton, void *arg)
969{
970 ui_scrollbar_t *scrollbar = (ui_scrollbar_t *)arg;
971 ui_clickmatic_t *clickmatic = ui_get_clickmatic(scrollbar->ui);
972
973 ui_clickmatic_set_cb(clickmatic, &ui_scrollbar_clickmatic_down_cb,
974 (void *) scrollbar);
975 ui_clickmatic_press(clickmatic);
976}
977
978/** Scrollbar down button released.
979 *
980 * @param pbutton Down button
981 * @param arg Argument (ui_scrollbar_t *)
982 */
983static void ui_scrollbar_down_btn_up(ui_pbutton_t *pbutton, void *arg)
984{
985 ui_scrollbar_t *scrollbar = (ui_scrollbar_t *)arg;
986 ui_clickmatic_t *clickmatic = ui_get_clickmatic(scrollbar->ui);
987
988 ui_clickmatic_release(clickmatic);
989 ui_clickmatic_set_cb(clickmatic, NULL, NULL);
990}
991
992/** Destroy scrollbar control.
993 *
994 * @param arg Argument (ui_scrollbar_t *)
995 */
996void ui_scrollbar_ctl_destroy(void *arg)
997{
998 ui_scrollbar_t *scrollbar = (ui_scrollbar_t *) arg;
999
1000 ui_scrollbar_destroy(scrollbar);
1001}
1002
1003/** Paint scrollbar control.
1004 *
1005 * @param arg Argument (ui_scrollbar_t *)
1006 * @return EOK on success or an error code
1007 */
1008errno_t ui_scrollbar_ctl_paint(void *arg)
1009{
1010 ui_scrollbar_t *scrollbar = (ui_scrollbar_t *) arg;
1011
1012 return ui_scrollbar_paint(scrollbar);
1013}
1014
1015/** Handle scrollbar control position event.
1016 *
1017 * @param arg Argument (ui_scrollbar_t *)
1018 * @param pos_event Position event
1019 * @return @c ui_claimed iff the event is claimed
1020 */
1021ui_evclaim_t ui_scrollbar_ctl_pos_event(void *arg, pos_event_t *event)
1022{
1023 ui_scrollbar_t *scrollbar = (ui_scrollbar_t *)arg;
1024
1025 return ui_scrollbar_pos_event(scrollbar, event);
1026}
1027
1028/** Scrollbar clickmatic up button click event.
1029 *
1030 * @param clickmatic Clickmatic
1031 * @param arg Argument (ui_scrollbar_t *)
1032 */
1033static void ui_scrollbar_cm_up(ui_clickmatic_t *clickmatic, void *arg)
1034{
1035 ui_scrollbar_t *scrollbar = (ui_scrollbar_t *)arg;
1036
1037 if (scrollbar->up_btn->inside)
1038 ui_scrollbar_up(scrollbar);
1039}
1040
1041/** Scrollbar clickmatic down button click event.
1042 *
1043 * @param clickmatic Clickmatic
1044 * @param arg Argument (ui_scrollbar_t *)
1045 */
1046static void ui_scrollbar_cm_down(ui_clickmatic_t *clickmatic, void *arg)
1047{
1048 ui_scrollbar_t *scrollbar = (ui_scrollbar_t *)arg;
1049
1050 if (scrollbar->down_btn->inside)
1051 ui_scrollbar_down(scrollbar);
1052}
1053
1054/** Scrollbar clickmatic up through click event.
1055 *
1056 * @param clickmatic Clickmatic
1057 * @param arg Argument (ui_scrollbar_t *)
1058 */
1059static void ui_scrollbar_cm_page_up(ui_clickmatic_t *clickmatic, void *arg)
1060{
1061 ui_scrollbar_t *scrollbar = (ui_scrollbar_t *)arg;
1062
1063 if (scrollbar->up_through_inside)
1064 ui_scrollbar_page_up(scrollbar);
1065}
1066
1067/** Scrollbar clickmatic down through click event.
1068 *
1069 * @param clickmatic Clickmatic
1070 * @param arg Argument (ui_scrollbar_t *)
1071 */
1072static void ui_scrollbar_cm_page_down(ui_clickmatic_t *clickmatic, void *arg)
1073{
1074 ui_scrollbar_t *scrollbar = (ui_scrollbar_t *)arg;
1075
1076 if (scrollbar->down_through_inside)
1077 ui_scrollbar_page_down(scrollbar);
1078}
1079
1080/** @}
1081 */
Note: See TracBrowser for help on using the repository browser.