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

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

Scrollbar buttons should not depress in text mode

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