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

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

Scrollbar needs custom button decorations

Push button now allows setting a 'custom decoration' which means
instead of painting the button text a callback function is invoked
to paint the decoration.

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