NetSurf
scrollbar.c
Go to the documentation of this file.
1/*
2 * Copyright 2004-2008 James Bursa <bursa@users.sourceforge.net>
3 * Copyright 2008 Michael Drake <tlsa@netsurf-browser.org>
4 * Copyright 2009 Paul Blokus <paul_pl@users.sourceforge.net>
5 *
6 * This file is part of NetSurf, http://www.netsurf-browser.org/
7 *
8 * NetSurf is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; version 2 of the License.
11 *
12 * NetSurf is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21/**
22 * \file
23 * implementation of scrollbar widget.
24 */
25
26#include <stdbool.h>
27#include <stdlib.h>
28
29#include "utils/log.h"
30#include "utils/messages.h"
31#include "utils/utils.h"
32#include "utils/nscolour.h"
33#include "utils/nsoption.h"
35#include "netsurf/mouse.h"
36#include "netsurf/plotters.h"
37
39#include "desktop/scrollbar.h"
40
41/**
42 * Scrollbar context
43 */
44struct scrollbar {
45 /** Horizontal scrollbar if true, else vertical */
47 /** Length of the scrollbar widget */
48 int length;
49
50 /** Length of the full scrollable area */
52 /** Length visible part of the scrollable area */
54
55 /** Current scroll offset to visible area */
56 int offset;
57
58 /** Position of the scrollbar */
60 /** Length of the scrollbar */
62
63 /** Callback receiving scrollbar events */
65 /** User data passed to the callback */
67
68 /** Flag indicating drag at progess */
70 /** Coordinate value at drag start */
72 /** Scrollbar offset or bar_pos at drag start */
74 /** Flag indicating that the drag corresponds to a dragged
75 * content area, rather than a dragged scrollbar.
76 */
78
79 /** Parpendicular scrollbar, or NULL */
80 struct scrollbar *pair;
81 /** Flag indicating that the current drag affects the
82 * perpendicular scrollbar too
83 */
85};
86
87
88
89/*
90 * Exported interface. Documented in desktop/scrollbar.h
91 */
94 int length,
95 int full_size,
96 int visible_size,
97 void *client_data,
99 struct scrollbar **s)
100{
101 struct scrollbar *scrollbar;
102 int well_length;
103
104 scrollbar = malloc(sizeof(struct scrollbar));
105 if (scrollbar == NULL) {
106 *s = NULL;
107 return NSERROR_NOMEM;
108 }
109
114 scrollbar->offset = 0;
115 scrollbar->bar_pos = 0;
116 scrollbar->pair = NULL;
117 scrollbar->pair_drag = false;
118
119 well_length = length - 2 * SCROLLBAR_WIDTH;
120 scrollbar->bar_len = (full_size == 0) ? 0 :
121 ((well_length * visible_size) / full_size);
122
125
126 scrollbar->dragging = false;
127 scrollbar->drag_content = false;
128
129 *s = scrollbar;
130
131 return NSERROR_OK;
132}
133
134
135/*
136 * Exported interface. Documented in scrollbar.h
137 */
139{
140 if (s->pair != NULL) {
141 s->pair->pair = NULL;
142 }
143 free(s);
144}
145
146
147/**
148 * Draw an outline rectangle common to several scrollbar elements.
149 *
150 * \param ctx current redraw context
151 * \param area the area of the scrollbar
152 * \param c base colour of the outline, the other colours are created by
153 * lightening or darkening this one
154 * \param inset true for inset outline, false for an outset one
155 * \return NSERROR_OK on success else error code
156 */
157static inline nserror
159 struct rect *area,
160 colour c,
161 bool inset)
162{
163 struct rect line;
164 nserror res;
165
166 static plot_style_t c0 = {
168 .stroke_width = plot_style_int_to_fixed(1),
169 };
170
171 static plot_style_t c1 = {
173 .stroke_width = plot_style_int_to_fixed(1),
174 };
175
176 static plot_style_t c2 = {
178 .stroke_width = plot_style_int_to_fixed(1),
179 };
180
181 if (inset) {
184 } else {
187 }
189
190 /* Plot the outline */
191
192 line.x0 = area->x0; line.y0 = area->y0;
193 line.x1 = area->x1; line.y1 = area->y0;
194 res = ctx->plot->line(ctx, &c0, &line);
195 if (res != NSERROR_OK) {
196 return res;
197 }
198
199 line.x0 = area->x1; line.y0 = area->y0;
200 line.x1 = area->x1; line.y1 = area->y1 + 1;
201 res = ctx->plot->line(ctx, &c1, &line);
202 if (res != NSERROR_OK) {
203 return res;
204 }
205
206 line.x0 = area->x1; line.y0 = area->y0;
207 line.x1 = area->x1; line.y1 = area->y0 + 1;
208 res = ctx->plot->line(ctx, &c2, &line);
209 if (res != NSERROR_OK) {
210 return res;
211 }
212
213 line.x0 = area->x1; line.y0 = area->y1;
214 line.x1 = area->x0; line.y1 = area->y1;
215 res = ctx->plot->line(ctx, &c1, &line);
216 if (res != NSERROR_OK) {
217 return res;
218 }
219
220 line.x0 = area->x0; line.y0 = area->y1;
221 line.x1 = area->x0; line.y1 = area->y0;
222 res = ctx->plot->line(ctx, &c0, &line);
223 if (res != NSERROR_OK) {
224 return res;
225 }
226
227 line.x0 = area->x0; line.y0 = area->y1;
228 line.x1 = area->x0; line.y1 = area->y1 + 1;
229 res = ctx->plot->line(ctx, &c2, &line);
230
231 return res;
232}
233
234
235/*
236 * Exported interface. Documented in scrollbar.h
237 */
240 int x, int y,
241 const struct rect *clip,
242 float scale,
243 const struct redraw_context *ctx)
244{
245 int w = SCROLLBAR_WIDTH;
246 int bar_pos, bar_c0, bar_c1;
247 int v[6]; /* array of triangle vertices */
248 struct rect area;
249 struct rect rect;
250 nserror res;
251
252 plot_style_t bg_fill_style = {
254 .fill_colour = nscolours[NSCOLOUR_SCROLL_WELL],
255 };
256 plot_style_t fg_fill_style = {
258 .fill_colour = nscolours[NSCOLOUR_BUTTON_BG],
259 };
260 plot_style_t arrow_fill_style = {
262 .fill_colour = nscolours[NSCOLOUR_BUTTON_FG],
263 };
264
265 area.x0 = x;
266 area.y0 = y;
267 area.x1 = x + (s->horizontal ? s->length : SCROLLBAR_WIDTH) - 1;
268 area.y1 = y + (s->horizontal ? SCROLLBAR_WIDTH : s->length) - 1;
269 bar_pos = s->bar_pos;
270 bar_c1 = (s->horizontal ? area.x0 : area.y0) + SCROLLBAR_WIDTH +
271 s->bar_pos + s->bar_len - 1;
272
273 if (scale != 1.0) {
274 w *= scale;
275 area.x0 *= scale;
276 area.y0 *= scale;
277 area.x1 *= scale;
278 area.y1 *= scale;
279 bar_pos *= scale;
280 bar_c1 *= scale;
281 }
282
283 bar_c0 = (s->horizontal ? area.x0 : area.y0) + w + bar_pos;
284
285 /* if scrollbar is outside the clipping rectangle, nothing to render */
286 if ((area.x1 < clip->x0) ||
287 (area.y1 < clip->y0) ||
288 (clip->x1 < area.x0) ||
289 (clip->y1 < area.y0)) {
290 return NSERROR_OK;
291 }
292
293 if (s->horizontal) {
294 /* scrollbar is horizontal */
295
296 /* scrollbar outline */
297 res = scrollbar_rectangle(ctx, &area,
298 bg_fill_style.fill_colour, true);
299 if (res != NSERROR_OK) {
300 return res;
301 }
302
303 /* left arrow icon border */
304 rect.x0 = area.x0 + 1;
305 rect.y0 = area.y0 + 1;
306 rect.x1 = area.x0 + w - 2;
307 rect.y1 = area.y1 - 1;
308 res = scrollbar_rectangle(ctx, &rect,
309 fg_fill_style.fill_colour, false);
310 if (res != NSERROR_OK) {
311 return res;
312 }
313
314 /* left arrow icon background */
315 rect.x0 = area.x0 + 2;
316 rect.y0 = area.y0 + 2;
317 rect.x1 = area.x0 + w - 2;
318 rect.y1 = area.y1 - 1;
319 res = ctx->plot->rectangle(ctx, &fg_fill_style, &rect);
320 if (res != NSERROR_OK) {
321 return res;
322 }
323
324 /* left arrow */
325 v[0] = area.x0 + w / 4;
326 v[1] = area.y0 + w / 2;
327 v[2] = area.x0 + w * 3 / 4;
328 v[3] = area.y0 + w / 4;
329 v[4] = area.x0 + w * 3 / 4;
330 v[5] = area.y0 + w * 3 / 4;
331 res = ctx->plot->polygon(ctx, &arrow_fill_style, v, 3);
332 if (res != NSERROR_OK) {
333 return res;
334 }
335
336 /* scrollbar well background */
337 rect.x0 = area.x0 + w - 1;
338 rect.y0 = area.y0 + 1;
339 rect.x1 = area.x1 - w + 2;
340 rect.y1 = area.y1;
341 res = ctx->plot->rectangle(ctx, &bg_fill_style, &rect);
342 if (res != NSERROR_OK) {
343 return res;
344 }
345
346 /* scrollbar position indicator bar */
347 rect.x0 = bar_c0;
348 rect.y0 = area.y0 + 1;
349 rect.x1 = bar_c1;
350 rect.y1 = area.y1 - 1;
351 res = scrollbar_rectangle(ctx, &rect,
352 fg_fill_style.fill_colour, false);
353 if (res != NSERROR_OK) {
354 return res;
355 }
356
357 rect.x0 = bar_c0 + 1;
358 rect.y0 = area.y0 + 2;
359 rect.x1 = bar_c1;
360 rect.y1 = area.y1 - 1;
361 res = ctx->plot->rectangle(ctx, &fg_fill_style, &rect);
362 if (res != NSERROR_OK) {
363 return res;
364 }
365
366 /* right arrow icon border */
367 rect.x0 = area.x1 - w + 2;
368 rect.y0 = area.y0 + 1;
369 rect.x1 = area.x1 - 1;
370 rect.y1 = area.y1 - 1;
371 res = scrollbar_rectangle(ctx, &rect,
372 fg_fill_style.fill_colour, false);
373 if (res != NSERROR_OK) {
374 return res;
375 }
376
377 /* right arrow icon background */
378 rect.x0 = area.x1 - w + 3;
379 rect.y0 = area.y0 + 2;
380 rect.x1 = area.x1 - 1;
381 rect.y1 = area.y1 - 1;
382 res = ctx->plot->rectangle(ctx, &fg_fill_style, &rect);
383 if (res != NSERROR_OK) {
384 return res;
385 }
386
387 /* right arrow */
388 v[0] = rect.x1 - w / 4 + 1;
389 v[1] = rect.y0 + w / 2;
390 v[2] = rect.x1 - w * 3 / 4 + 1;
391 v[3] = rect.y0 + w / 4;
392 v[4] = rect.x1 - w * 3 / 4 + 1;
393 v[5] = rect.y0 + w * 3 / 4;
394 res = ctx->plot->polygon(ctx, &arrow_fill_style, v, 3);
395 if (res != NSERROR_OK) {
396 return res;
397 }
398 } else {
399 /* scrollbar is vertical */
400
401 /* outline */
402 res = scrollbar_rectangle(ctx, &area,
403 bg_fill_style.fill_colour, true);
404 if (res != NSERROR_OK) {
405 return res;
406 }
407
408 /* top arrow border */
409 rect.x0 = area.x0 + 1;
410 rect.y0 = area.y0 + 1;
411 rect.x1 = area.x1 - 1;
412 rect.y1 = area.y0 + w - 2;
413 res = scrollbar_rectangle(ctx, &rect,
414 fg_fill_style.fill_colour, false);
415 if (res != NSERROR_OK) {
416 return res;
417 }
418
419 /* top arrow background */
420 rect.x0 = area.x0 + 2;
421 rect.y0 = area.y0 + 2;
422 rect.x1 = area.x1 - 1;
423 rect.y1 = area.y0 + w - 2;
424 res = ctx->plot->rectangle(ctx, &fg_fill_style, &rect);
425 if (res != NSERROR_OK) {
426 return res;
427 }
428
429 /* up arrow */
430 v[0] = area.x0 + w / 2;
431 v[1] = area.y0 + w / 4;
432 v[2] = area.x0 + w / 4;
433 v[3] = area.y0 + w * 3 / 4;
434 v[4] = area.x0 + w * 3 / 4;
435 v[5] = area.y0 + w * 3 / 4;
436 res = ctx->plot->polygon(ctx, &arrow_fill_style, v, 3);
437 if (res != NSERROR_OK) {
438 return res;
439 }
440
441 /* scrollbar well background */
442 rect.x0 = area.x0 + 1;
443 rect.y0 = area.y0 + w - 1;
444 rect.x1 = area.x1;
445 rect.y1 = area.y1 - w + 2;
446 res = ctx->plot->rectangle(ctx, &bg_fill_style, &rect);
447 if (res != NSERROR_OK) {
448 return res;
449 }
450
451 /* scrollbar position indicator bar */
452 rect.x0 = area.x0 + 1;
453 rect.y0 = bar_c0;
454 rect.x1 = area.x1 - 1;
455 rect.y1 = bar_c1;
456 res = scrollbar_rectangle(ctx, &rect,
457 fg_fill_style.fill_colour, false);
458 if (res != NSERROR_OK) {
459 return res;
460 }
461
462 rect.x0 = area.x0 + 2;
463 rect.y0 = bar_c0 + 1;
464 rect.x1 = area.x1 - 1;
465 rect.y1 = bar_c1;
466 res = ctx->plot->rectangle(ctx, &fg_fill_style, &rect);
467 if (res != NSERROR_OK) {
468 return res;
469 }
470
471 /* down arrow icon border */
472 rect.x0 = area.x0 + 1;
473 rect.y0 = area.y1 - w + 2;
474 rect.x1 = area.x1 - 1;
475 rect.y1 = area.y1 - 1;
476 res = scrollbar_rectangle(ctx, &rect,
477 fg_fill_style.fill_colour, false);
478 if (res != NSERROR_OK) {
479 return res;
480 }
481
482 /* down arrow icon background */
483 rect.x0 = area.x0 + 2;
484 rect.y0 = area.y1 - w + 3;
485 rect.x1 = area.x1 - 1;
486 rect.y1 = area.y1 - 1;
487 res = ctx->plot->rectangle(ctx, &fg_fill_style, &rect);
488 if (res != NSERROR_OK) {
489 return res;
490 }
491
492 /* down arrow */
493 v[0] = area.x0 + w / 2;
494 v[1] = area.y1 - w / 4 + 1;
495 v[2] = area.x0 + w / 4;
496 v[3] = area.y1 - w * 3 / 4 + 1;
497 v[4] = area.x0 + w * 3 / 4;
498 v[5] = area.y1 - w * 3 / 4 + 1;
499 res = ctx->plot->polygon(ctx, &arrow_fill_style, v, 3);
500 if (res != NSERROR_OK) {
501 return res;
502 }
503 }
504
505 return NSERROR_OK;
506}
507
508
509/*
510 * Exported interface. Documented in scrollbar.h
511 */
512void scrollbar_set(struct scrollbar *s, int value, bool bar_pos)
513{
514 int well_length;
515 int old_offset = s->offset;
516 struct scrollbar_msg_data msg;
517
518 if (value < 0) {
519 value = 0;
520 }
521
522 if (s->full_size == s->visible_size) {
523 return;
524 }
525
526 well_length = s->length - 2 * SCROLLBAR_WIDTH;
527 if (bar_pos) {
528 if (value > well_length - s->bar_len) {
529 s->bar_pos = well_length - s->bar_len;
530 } else {
531 s->bar_pos = value;
532 }
533
534 s->offset = ((well_length - s->bar_len) < 1) ? 0 :
535 (((s->full_size - s->visible_size) *
536 s->bar_pos) / (well_length - s->bar_len));
537
538 } else {
539 if (value > s->full_size - s->visible_size) {
540 s->offset = s->full_size - s->visible_size;
541 } else {
542 s->offset = value;
543 }
544
545 s->bar_pos = (s->full_size < 1) ? 0 :
546 ((well_length * s->offset) / s->full_size);
547 }
548
549 if (s->offset != old_offset) {
550 /* client callback if there was a chnage */
551 msg.scrollbar = s;
553 msg.scroll_offset = s->offset;
555 }
556}
557
558
559/*
560 * Exported interface. Documented in scrollbar.h
561 */
562bool scrollbar_scroll(struct scrollbar *s, int change)
563{
564 int well_length;
565 int old_offset;
566 struct scrollbar_msg_data msg;
567
568 if (s == NULL || change == 0 || s->full_size <= s->visible_size) {
569 /* scrollbar not present, zero scroll step, or unscrollable */
570 return false;
571 }
572
573 /* Convert named change values to appropriate pixel offset value */
574 switch (change) {
575 case SCROLL_TOP:
576 change = -s->full_size;
577 break;
578
579 case SCROLL_PAGE_UP:
580 change = -s->visible_size;
581 break;
582
583 case SCROLL_PAGE_DOWN:
584 change = s->visible_size;
585 break;
586
587 case SCROLL_BOTTOM:
588 change = s->full_size;
589 break;
590
591 default:
592 /* Change value is already a pixel offset */
593 break;
594 }
595
596 /* Get new offset */
597 old_offset = s->offset;
598 if (s->offset + change > s->full_size - s->visible_size) {
599 s->offset = s->full_size - s->visible_size;
600 } else if (s->offset + change < 0) {
601 s->offset = 0;
602 } else {
603 s->offset += change;
604 }
605
606 if (s->offset == old_offset) {
607 /* Nothing happened */
608 return false;
609 }
610
611 /* Update scrollbar */
612 well_length = s->length - 2 * SCROLLBAR_WIDTH;
613 s->bar_pos = (s->full_size < 1) ? 0 :
614 ((well_length * s->offset) / s->full_size);
615
616 msg.scrollbar = s;
618 msg.scroll_offset = s->offset;
620
621 return true;
622}
623
624
625/*
626 * Exported interface. Documented in scrollbar.h
627 */
629{
630 if (s == NULL) {
631 return 0;
632 }
633 return s->offset;
634}
635
636
637/*
638 * Exported interface. Documented in scrollbar.h
639 */
640void scrollbar_set_extents(struct scrollbar *s, int length,
641 int visible_size, int full_size)
642{
643 int cur_excess = s->full_size - s->visible_size;
644 int well_length;
645 struct scrollbar_msg_data msg;
646
647 if (length == s->length &&
648 visible_size == s->visible_size &&
649 full_size == s->full_size) {
650 /* Nothing's changed. */
651 return;
652 }
653
654 if (length != -1) {
655 s->length = length;
656 }
657 if (visible_size != -1) {
658 s->visible_size = visible_size;
659 }
660 if (full_size != -1) {
661 s->full_size = full_size;
662 }
663
664 if (s->full_size < s->visible_size) {
665 s->full_size = s->visible_size;
666 }
667
668 /* Update scroll offset (scaled in proportion with change in excess) */
669 if (cur_excess <= 0) {
670 s->offset = 0;
671 } else {
672 s->offset = (full_size - visible_size) * s->offset / cur_excess;
673 }
674
675 well_length = s->length - 2 * SCROLLBAR_WIDTH;
676
677 if (s->full_size < 1) {
678 s->bar_len = well_length;
679 s->bar_pos = 0;
680 } else {
681 s->bar_len = (well_length * s->visible_size) / s->full_size;
682 s->bar_pos = (well_length * s->offset) / s->full_size;
683 }
684
685 msg.scrollbar = s;
687 msg.scroll_offset = s->offset;
689}
690
691
692/*
693 * Exported interface. Documented in scrollbar.h
694 */
696{
697 return s->horizontal;
698}
699
700
701/**
702 * Internal procedure used for starting a drag scroll for a scrollbar.
703 *
704 * \param s the scrollbar to start the drag for
705 * \param x the X coordinate of the drag start
706 * \param y the Y coordinate of the drag start
707 * \param content_drag whether this should be a reverse drag (used when the
708 * user drags the content area, rather than the scrollbar)
709 * \param pair whether the drag is a '2D' scroll
710 */
711static void
713 int x, int y,
714 bool content_drag,
715 bool pair)
716{
717 struct scrollbar_msg_data msg;
718
719 s->drag_start_coord = s->horizontal ? x : y;
720 s->drag_start_pos = (content_drag) ? s->offset : s->bar_pos;
721
722 s->dragging = true;
723 s->drag_content = content_drag;
724
725 msg.scrollbar = s;
726
727 /** \todo some proper numbers please! */
728 if (s->horizontal) {
729 msg.x0 = -2048;
730 msg.x1 = 2048;
731 msg.y0 = 0;
732 msg.y1 = 0;
733 } else {
734 msg.x0 = 0;
735 msg.x1 = 0;
736 msg.y0 = -2048;
737 msg.y1 = 2048;
738 }
739
740 if (pair && s->pair != NULL) {
741 s->pair_drag = true;
742
744 s->pair->horizontal ? x : y;
745
746 s->pair->drag_start_pos = (content_drag) ? s->pair->offset :
747 s->pair->bar_pos;
748
749 s->pair->dragging = true;
750 s->pair->drag_content = content_drag;
751
752 if (s->pair->horizontal) {
753 msg.x0 = -2048;
754 msg.x1 = 2048;
755 } else {
756 msg.y0 = -2048;
757 msg.y1 = 2048;
758 }
759 }
762}
763
764
765/*
766 * Exported interface. Documented in scrollbar.h
767 */
771 int x, int y)
772{
773 int x0, y0, x1, y1;
774 int val;
776 bool h;
777
778 /* we want mouse presses and mouse drags that were not started at the
779 * scrollbar indication bar to be launching actions on the scroll area
780 */
781 bool but1 = ((mouse & BROWSER_MOUSE_PRESS_1) ||
782 ((mouse & BROWSER_MOUSE_HOLDING_1) &&
783 (mouse & BROWSER_MOUSE_DRAG_ON) &&
784 !s->dragging));
785 bool but2 = ((mouse & BROWSER_MOUSE_PRESS_2) ||
786 ((mouse & BROWSER_MOUSE_HOLDING_2) &&
787 (mouse & BROWSER_MOUSE_DRAG_ON) &&
788 !s->dragging));
789
790 h = s->horizontal;
791
792 x0 = 0;
793 y0 = 0;
794 x1 = h ? s->length : SCROLLBAR_WIDTH;
795 y1 = h ? SCROLLBAR_WIDTH : s->length;
796
797 if (!s->dragging && !(x >= x0 && x <= x1 && y >= y0 && y <= y1)) {
798 /* Not a drag and mouse outside scrollbar widget */
800 }
801
802
803 if (h) {
804 val = x;
805 } else {
806 val = y;
807 }
808
809 if (s->dragging) {
810 val -= s->drag_start_coord;
811 if (s->drag_content) {
812 val = -val;
813 }
814 if (val != 0) {
815 scrollbar_set(s, s->drag_start_pos + val,
816 !(s->drag_content));
817 }
818 if (s->pair_drag) {
819 scrollbar_mouse_action(s->pair, mouse, x, y);
820 status = SCROLLBAR_MOUSE_BOTH;
821 } else {
823 }
824 return status;
825 }
826
827 if (val < SCROLLBAR_WIDTH) {
828 /* left/up arrow */
829
831 if (but1) {
832 scrollbar_set(s, s->offset - SCROLLBAR_WIDTH, false);
833 } else if (but2) {
834 scrollbar_set(s, s->offset + SCROLLBAR_WIDTH, false);
835 }
836 } else if (val < SCROLLBAR_WIDTH + s->bar_pos) {
837 /* well between left/up arrow and bar */
838
840
841 if (but1) {
842 scrollbar_set(s, s->offset - s->length, false);
843 } else if (but2) {
844 scrollbar_set(s, s->offset + s->length, false);
845 }
846 } else if (val > s->length - SCROLLBAR_WIDTH) {
847 /* right/down arrow */
848
850
851 if (but1) {
852 scrollbar_set(s, s->offset + SCROLLBAR_WIDTH, false);
853 } else if (but2) {
854 scrollbar_set(s, s->offset - SCROLLBAR_WIDTH, false);
855 }
856 } else if (val > SCROLLBAR_WIDTH + s->bar_pos + s->bar_len) {
857 /* well between right/down arrow and bar */
858
860 if (but1) {
861 scrollbar_set(s, s->offset + s->length, false);
862 } else if (but2) {
863 scrollbar_set(s, s->offset - s->length, false);
864 }
865 } else {
866 /* scrollbar position indication bar */
867
869 }
870
871
873 (val >= SCROLLBAR_WIDTH + s->bar_pos
874 && val < SCROLLBAR_WIDTH + s->bar_pos +
875 s->bar_len)) {
876 /* The mouse event is a drag start on the scrollbar position
877 * indication bar. */
878 scrollbar_drag_start_internal(s, x, y, false,
879 (mouse & BROWSER_MOUSE_DRAG_2) ? true : false);
880 }
881
882 return status;
883}
884
885
886/*
887 * Exported interface. Documented in scrollbar.h
888 */
890{
891 switch ((unsigned int) status) {
894 return messages_get("ScrollUp");
897 return messages_get("ScrollPUp");
900 return messages_get("ScrollV");
903 return messages_get("ScrollPDown");
906 return messages_get("ScrollDown");
909 return messages_get("ScrollLeft");
912 return messages_get("ScrollPLeft");
915 return messages_get("ScrollH");
918 return messages_get("ScrollPRight");
921 return messages_get("ScrollRight");
922 default:
923 break;
924 }
925
926 return NULL;
927}
928
929
930/*
931 * Exported interface. Documented in scrollbar.h
932 */
934 browser_mouse_state mouse, int x, int y)
935{
936 struct scrollbar_msg_data msg;
937 int val, drag_start_pos;
938
939 assert(s->dragging);
940
941 drag_start_pos = s->drag_start_pos;
942 val = (s->horizontal ? x : y) - s->drag_start_coord;
943
944 if (s->drag_content) {
945 val = -val;
946 }
947 if (val != 0) {
948 scrollbar_set(s, drag_start_pos + val, !(s->drag_content));
949 }
950
951 s->dragging = false;
952 s->drag_content = false;
953
954 if (s->pair_drag) {
955 s->pair_drag = false;
956
957 drag_start_pos = s->pair->drag_start_pos;
958 val = (s->pair->horizontal ? x : y) - s->pair->drag_start_coord;
959
960 if (s->pair->drag_content) {
961 val = -val;
962 }
963 if (val != 0) {
964 scrollbar_set(s->pair, drag_start_pos + val,
965 !(s->pair->drag_content));
966 }
967
968 s->pair->dragging = false;
969 s->pair->drag_content = false;
970 }
971
972 msg.scrollbar = s;
975}
976
977
978/*
979 * Exported interface. Documented in scrollbar.h
980 */
981void scrollbar_start_content_drag(struct scrollbar *s, int x, int y)
982{
983 scrollbar_drag_start_internal(s, x, y, true, true);
984}
985
986
987/*
988 * Exported interface. Documented in scrollbar.h
989 */
990void scrollbar_make_pair(struct scrollbar *horizontal,
991 struct scrollbar *vertical)
992{
993 assert(horizontal->horizontal &&
994 !vertical->horizontal);
995
996 horizontal->pair = vertical;
997 vertical->pair = horizontal;
998}
999
1000
1001/*
1002 * Exported interface. Documented in scrollbar.h
1003 */
1005{
1006 return s->client_data;
1007}
#define SCROLL_BOTTOM
Definition: gui.c:173
#define SCROLL_PAGE_UP
Definition: gui.c:171
#define SCROLL_PAGE_DOWN
Definition: gui.c:172
#define SCROLL_TOP
Definition: gui.c:170
Browser window creation and manipulation interface.
nserror
Enumeration of error codes.
Definition: errors.h:29
@ NSERROR_NOMEM
Memory exhaustion.
Definition: errors.h:32
@ NSERROR_OK
No error.
Definition: errors.h:30
Core mouse and pointer states.
browser_mouse_state
Mouse state.
Definition: mouse.h:43
@ BROWSER_MOUSE_PRESS_1
button 1 pressed
Definition: mouse.h:50
@ BROWSER_MOUSE_PRESS_2
button 2 pressed
Definition: mouse.h:52
@ BROWSER_MOUSE_DRAG_1
start of button 1 drag
Definition: mouse.h:65
@ BROWSER_MOUSE_HOLDING_2
during button 2 drag
Definition: mouse.h:75
@ BROWSER_MOUSE_HOLDING_1
during button 1 drag
Definition: mouse.h:73
@ BROWSER_MOUSE_DRAG_ON
a drag operation was started and a mouse button is still pressed
Definition: mouse.h:70
@ BROWSER_MOUSE_DRAG_2
start of button 2 drag
Definition: mouse.h:67
Target independent plotting interface.
const char * messages_get(const char *key)
Fast lookup of a message by key from the standard Messages hash.
Definition: messages.c:241
Localised message support (interface).
colour nscolours[NSCOLOUR__COUNT]
NetSurf UI colour table.
Definition: nscolour.c:38
NetSurf UI colours (interface).
@ NSCOLOUR_BUTTON_BG
Definition: nscolour.h:57
@ NSCOLOUR_BUTTON_FG
Definition: nscolour.h:58
@ NSCOLOUR_SCROLL_WELL
Definition: nscolour.h:56
#define blend_colour(c0, c1)
Definition: plot_style.h:163
#define plot_style_int_to_fixed(v)
Definition: plot_style.h:51
#define lighten_colour(c1)
Definition: plot_style.h:150
#define darken_colour(c1)
Definition: plot_style.h:133
@ PLOT_OP_TYPE_SOLID
Solid colour.
Definition: plot_style.h:67
bool scrollbar_is_horizontal(struct scrollbar *s)
Check orientation of the scrollbar.
Definition: scrollbar.c:695
const char * scrollbar_mouse_status_to_message(scrollbar_mouse_status status)
Get a status bar message from a scrollbar mouse input status.
Definition: scrollbar.c:889
scrollbar_mouse_status scrollbar_mouse_action(struct scrollbar *s, browser_mouse_state mouse, int x, int y)
Handle mouse actions other then drag ends.
Definition: scrollbar.c:769
void scrollbar_make_pair(struct scrollbar *horizontal, struct scrollbar *vertical)
Connect a horizontal and a vertical scrollbar into a pair so that they co-operate during 2D drags.
Definition: scrollbar.c:990
static nserror scrollbar_rectangle(const struct redraw_context *ctx, struct rect *area, colour c, bool inset)
Draw an outline rectangle common to several scrollbar elements.
Definition: scrollbar.c:158
int scrollbar_get_offset(struct scrollbar *s)
Get the current scroll offset to the visible part of the full area.
Definition: scrollbar.c:628
static void scrollbar_drag_start_internal(struct scrollbar *s, int x, int y, bool content_drag, bool pair)
Internal procedure used for starting a drag scroll for a scrollbar.
Definition: scrollbar.c:712
nserror scrollbar_create(bool horizontal, int length, int full_size, int visible_size, void *client_data, scrollbar_client_callback client_callback, struct scrollbar **s)
Create a scrollbar.
Definition: scrollbar.c:93
nserror scrollbar_redraw(struct scrollbar *s, int x, int y, const struct rect *clip, float scale, const struct redraw_context *ctx)
Redraw a part of the scrollbar.
Definition: scrollbar.c:239
void * scrollbar_get_data(struct scrollbar *s)
Get the scrollbar's client data.
Definition: scrollbar.c:1004
bool scrollbar_scroll(struct scrollbar *s, int change)
Scroll the scrollbar by given amount.
Definition: scrollbar.c:562
void scrollbar_destroy(struct scrollbar *s)
Destroy a scrollbar.
Definition: scrollbar.c:138
void scrollbar_set(struct scrollbar *s, int value, bool bar_pos)
Set the scroll value of the scrollbar.
Definition: scrollbar.c:512
void scrollbar_start_content_drag(struct scrollbar *s, int x, int y)
Called when the content is being dragged to the scrollbars have to adjust.
Definition: scrollbar.c:981
void scrollbar_set_extents(struct scrollbar *s, int length, int visible_size, int full_size)
Set the length of the scrollbar widget, the size of the visible area, and the size of the full area.
Definition: scrollbar.c:640
void scrollbar_mouse_drag_end(struct scrollbar *s, browser_mouse_state mouse, int x, int y)
Handle end of mouse drags.
Definition: scrollbar.c:933
Scrollbar widget interface.
scrollbar_mouse_status
Scrollbar mouse input status flags.
Definition: scrollbar.h:70
@ SCROLLBAR_MOUSE_PLFT
Hover: scroll page left.
Definition: scrollbar.h:80
@ SCROLLBAR_MOUSE_UP
Hover: scroll up.
Definition: scrollbar.h:74
@ SCROLLBAR_MOUSE_PUP
Hover: scroll page up.
Definition: scrollbar.h:75
@ SCROLLBAR_MOUSE_RGT
Hover: scroll right.
Definition: scrollbar.h:83
@ SCROLLBAR_MOUSE_PDWN
Hover: scroll page down.
Definition: scrollbar.h:77
@ SCROLLBAR_MOUSE_DWN
Hover: scroll down.
Definition: scrollbar.h:78
@ SCROLLBAR_MOUSE_BOTH
Scrolling both bars.
Definition: scrollbar.h:73
@ SCROLLBAR_MOUSE_PRGT
Hover: scroll page right.
Definition: scrollbar.h:82
@ SCROLLBAR_MOUSE_NONE
Not relevant.
Definition: scrollbar.h:71
@ SCROLLBAR_MOUSE_LFT
Hover: scroll left.
Definition: scrollbar.h:79
@ SCROLLBAR_MOUSE_USED
Took action with input.
Definition: scrollbar.h:72
@ SCROLLBAR_MOUSE_HRZ
Hover: horiz.
Definition: scrollbar.h:81
@ SCROLLBAR_MOUSE_VRT
Hover: vert.
Definition: scrollbar.h:76
@ SCROLLBAR_MSG_MOVED
the scroll value has changed
Definition: scrollbar.h:47
@ SCROLLBAR_MSG_SCROLL_START
a scrollbar drag has started, all mouse events should be passed to the scrollbar regardless of the co...
Definition: scrollbar.h:48
@ SCROLLBAR_MSG_SCROLL_FINISHED
cancel a scrollbar drag
Definition: scrollbar.h:53
void(* scrollbar_client_callback)(void *client_data, struct scrollbar_msg_data *scrollbar_data)
Client callback for the scrollbar.
Definition: scrollbar.h:93
#define SCROLLBAR_WIDTH
Definition: scrollbar.h:32
Plot style for stroke/fill plotters.
Definition: plot_style.h:76
colour fill_colour
Colour of fill.
Definition: plot_style.h:81
plot_operation_type_t fill_type
Fill plot type.
Definition: plot_style.h:80
colour stroke_colour
Colour of stroke.
Definition: plot_style.h:79
plot_operation_type_t stroke_type
Stroke plot type.
Definition: plot_style.h:77
nserror(* line)(const struct redraw_context *ctx, const plot_style_t *pstyle, const struct rect *line)
Plots a line.
Definition: plotters.h:170
nserror(* polygon)(const struct redraw_context *ctx, const plot_style_t *pstyle, const int *p, unsigned int n)
Plot a polygon.
Definition: plotters.h:207
nserror(* rectangle)(const struct redraw_context *ctx, const plot_style_t *pstyle, const struct rect *rectangle)
Plots a rectangle.
Definition: plotters.h:188
Rectangle coordinates.
Definition: types.h:40
int x0
Definition: types.h:41
int y0
Top left.
Definition: types.h:41
int x1
Definition: types.h:42
int y1
Bottom right.
Definition: types.h:42
Redraw context.
Definition: plotters.h:51
const struct plotter_table * plot
Current plot operation table.
Definition: plotters.h:73
scrollbar message context data
Definition: scrollbar.h:59
scrollbar_msg msg
Definition: scrollbar.h:61
Scrollbar context.
Definition: scrollbar.c:44
int drag_start_coord
Coordinate value at drag start.
Definition: scrollbar.c:71
int bar_pos
Position of the scrollbar.
Definition: scrollbar.c:59
int full_size
Length of the full scrollable area.
Definition: scrollbar.c:51
struct scrollbar * pair
Parpendicular scrollbar, or NULL.
Definition: scrollbar.c:80
int visible_size
Length visible part of the scrollable area.
Definition: scrollbar.c:53
int offset
Current scroll offset to visible area.
Definition: scrollbar.c:56
bool horizontal
Horizontal scrollbar if true, else vertical.
Definition: scrollbar.c:46
scrollbar_client_callback client_callback
Callback receiving scrollbar events.
Definition: scrollbar.c:64
void * client_data
User data passed to the callback.
Definition: scrollbar.c:66
bool drag_content
Flag indicating that the drag corresponds to a dragged content area, rather than a dragged scrollbar.
Definition: scrollbar.c:77
bool pair_drag
Flag indicating that the current drag affects the perpendicular scrollbar too.
Definition: scrollbar.c:84
bool dragging
Flag indicating drag at progess.
Definition: scrollbar.c:69
int bar_len
Length of the scrollbar.
Definition: scrollbar.c:61
int length
Length of the scrollbar widget.
Definition: scrollbar.c:48
int drag_start_pos
Scrollbar offset or bar_pos at drag start.
Definition: scrollbar.c:73
Interface to system colour values.
uint32_t colour
Colour type: XBGR.
Definition: types.h:35
Option reading and saving interface.
Interface to a number of general purpose functionality.
static nserror line(const struct redraw_context *ctx, const plot_style_t *style, const struct rect *line)
Plots a line.
Definition: plot.c:579
static nserror clip(const struct redraw_context *ctx, const struct rect *clip)
Sets a clip rectangle for subsequent plot operations.
Definition: plot.c:357