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 = s->offset;
566 struct scrollbar_msg_data msg;
567
568 if (change == 0 || s->full_size <= s->visible_size) {
569 /* 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 if (s->offset + change > s->full_size - s->visible_size) {
598 s->offset = s->full_size - s->visible_size;
599 } else if (s->offset + change < 0) {
600 s->offset = 0;
601 } else {
602 s->offset += change;
603 }
604
605 if (s->offset == old_offset) {
606 /* Nothing happened */
607 return false;
608 }
609
610 /* Update scrollbar */
611 well_length = s->length - 2 * SCROLLBAR_WIDTH;
612 s->bar_pos = (s->full_size < 1) ? 0 :
613 ((well_length * s->offset) / s->full_size);
614
615 msg.scrollbar = s;
617 msg.scroll_offset = s->offset;
619
620 return true;
621}
622
623
624/*
625 * Exported interface. Documented in scrollbar.h
626 */
628{
629 if (s == NULL) {
630 return 0;
631 }
632 return s->offset;
633}
634
635
636/*
637 * Exported interface. Documented in scrollbar.h
638 */
639void scrollbar_set_extents(struct scrollbar *s, int length,
640 int visible_size, int full_size)
641{
642 int cur_excess = s->full_size - s->visible_size;
643 int well_length;
644 struct scrollbar_msg_data msg;
645
646 if (length == s->length &&
647 visible_size == s->visible_size &&
648 full_size == s->full_size) {
649 /* Nothing's changed. */
650 return;
651 }
652
653 if (length != -1) {
654 s->length = length;
655 }
656 if (visible_size != -1) {
657 s->visible_size = visible_size;
658 }
659 if (full_size != -1) {
660 s->full_size = full_size;
661 }
662
663 if (s->full_size < s->visible_size) {
664 s->full_size = s->visible_size;
665 }
666
667 /* Update scroll offset (scaled in proportion with change in excess) */
668 if (cur_excess <= 0) {
669 s->offset = 0;
670 } else {
671 s->offset = (full_size - visible_size) * s->offset / cur_excess;
672 }
673
674 well_length = s->length - 2 * SCROLLBAR_WIDTH;
675
676 if (s->full_size < 1) {
677 s->bar_len = well_length;
678 s->bar_pos = 0;
679 } else {
680 s->bar_len = (well_length * s->visible_size) / s->full_size;
681 s->bar_pos = (well_length * s->offset) / s->full_size;
682 }
683
684 msg.scrollbar = s;
686 msg.scroll_offset = s->offset;
688}
689
690
691/*
692 * Exported interface. Documented in scrollbar.h
693 */
695{
696 return s->horizontal;
697}
698
699
700/**
701 * Internal procedure used for starting a drag scroll for a scrollbar.
702 *
703 * \param s the scrollbar to start the drag for
704 * \param x the X coordinate of the drag start
705 * \param y the Y coordinate of the drag start
706 * \param content_drag whether this should be a reverse drag (used when the
707 * user drags the content area, rather than the scrollbar)
708 * \param pair whether the drag is a '2D' scroll
709 */
710static void
712 int x, int y,
713 bool content_drag,
714 bool pair)
715{
716 struct scrollbar_msg_data msg;
717
718 s->drag_start_coord = s->horizontal ? x : y;
719 s->drag_start_pos = (content_drag) ? s->offset : s->bar_pos;
720
721 s->dragging = true;
722 s->drag_content = content_drag;
723
724 msg.scrollbar = s;
725
726 /** \todo some proper numbers please! */
727 if (s->horizontal) {
728 msg.x0 = -2048;
729 msg.x1 = 2048;
730 msg.y0 = 0;
731 msg.y1 = 0;
732 } else {
733 msg.x0 = 0;
734 msg.x1 = 0;
735 msg.y0 = -2048;
736 msg.y1 = 2048;
737 }
738
739 if (pair && s->pair != NULL) {
740 s->pair_drag = true;
741
743 s->pair->horizontal ? x : y;
744
745 s->pair->drag_start_pos = (content_drag) ? s->pair->offset :
746 s->pair->bar_pos;
747
748 s->pair->dragging = true;
749 s->pair->drag_content = content_drag;
750
751 if (s->pair->horizontal) {
752 msg.x0 = -2048;
753 msg.x1 = 2048;
754 } else {
755 msg.y0 = -2048;
756 msg.y1 = 2048;
757 }
758 }
761}
762
763
764/*
765 * Exported interface. Documented in scrollbar.h
766 */
770 int x, int y)
771{
772 int x0, y0, x1, y1;
773 int val;
775 bool h;
776
777 /* we want mouse presses and mouse drags that were not started at the
778 * scrollbar indication bar to be launching actions on the scroll area
779 */
780 bool but1 = ((mouse & BROWSER_MOUSE_PRESS_1) ||
781 ((mouse & BROWSER_MOUSE_HOLDING_1) &&
782 (mouse & BROWSER_MOUSE_DRAG_ON) &&
783 !s->dragging));
784 bool but2 = ((mouse & BROWSER_MOUSE_PRESS_2) ||
785 ((mouse & BROWSER_MOUSE_HOLDING_2) &&
786 (mouse & BROWSER_MOUSE_DRAG_ON) &&
787 !s->dragging));
788
789 h = s->horizontal;
790
791 x0 = 0;
792 y0 = 0;
793 x1 = h ? s->length : SCROLLBAR_WIDTH;
794 y1 = h ? SCROLLBAR_WIDTH : s->length;
795
796 if (!s->dragging && !(x >= x0 && x <= x1 && y >= y0 && y <= y1)) {
797 /* Not a drag and mouse outside scrollbar widget */
799 }
800
801
802 if (h) {
803 val = x;
804 } else {
805 val = y;
806 }
807
808 if (s->dragging) {
809 val -= s->drag_start_coord;
810 if (s->drag_content) {
811 val = -val;
812 }
813 if (val != 0) {
814 scrollbar_set(s, s->drag_start_pos + val,
815 !(s->drag_content));
816 }
817 if (s->pair_drag) {
818 scrollbar_mouse_action(s->pair, mouse, x, y);
819 status = SCROLLBAR_MOUSE_BOTH;
820 } else {
822 }
823 return status;
824 }
825
826 if (val < SCROLLBAR_WIDTH) {
827 /* left/up arrow */
828
830 if (but1) {
831 scrollbar_set(s, s->offset - SCROLLBAR_WIDTH, false);
832 } else if (but2) {
833 scrollbar_set(s, s->offset + SCROLLBAR_WIDTH, false);
834 }
835 } else if (val < SCROLLBAR_WIDTH + s->bar_pos) {
836 /* well between left/up arrow and bar */
837
839
840 if (but1) {
841 scrollbar_set(s, s->offset - s->length, false);
842 } else if (but2) {
843 scrollbar_set(s, s->offset + s->length, false);
844 }
845 } else if (val > s->length - SCROLLBAR_WIDTH) {
846 /* right/down arrow */
847
849
850 if (but1) {
851 scrollbar_set(s, s->offset + SCROLLBAR_WIDTH, false);
852 } else if (but2) {
853 scrollbar_set(s, s->offset - SCROLLBAR_WIDTH, false);
854 }
855 } else if (val > SCROLLBAR_WIDTH + s->bar_pos + s->bar_len) {
856 /* well between right/down arrow and bar */
857
859 if (but1) {
860 scrollbar_set(s, s->offset + s->length, false);
861 } else if (but2) {
862 scrollbar_set(s, s->offset - s->length, false);
863 }
864 } else {
865 /* scrollbar position indication bar */
866
868 }
869
870
872 (val >= SCROLLBAR_WIDTH + s->bar_pos
873 && val < SCROLLBAR_WIDTH + s->bar_pos +
874 s->bar_len)) {
875 /* The mouse event is a drag start on the scrollbar position
876 * indication bar. */
877 scrollbar_drag_start_internal(s, x, y, false,
878 (mouse & BROWSER_MOUSE_DRAG_2) ? true : false);
879 }
880
881 return status;
882}
883
884
885/*
886 * Exported interface. Documented in scrollbar.h
887 */
889{
890 switch ((unsigned int) status) {
893 return messages_get("ScrollUp");
896 return messages_get("ScrollPUp");
899 return messages_get("ScrollV");
902 return messages_get("ScrollPDown");
905 return messages_get("ScrollDown");
908 return messages_get("ScrollLeft");
911 return messages_get("ScrollPLeft");
914 return messages_get("ScrollH");
917 return messages_get("ScrollPRight");
920 return messages_get("ScrollRight");
921 default:
922 break;
923 }
924
925 return NULL;
926}
927
928
929/*
930 * Exported interface. Documented in scrollbar.h
931 */
933 browser_mouse_state mouse, int x, int y)
934{
935 struct scrollbar_msg_data msg;
936 int val, drag_start_pos;
937
938 assert(s->dragging);
939
940 drag_start_pos = s->drag_start_pos;
941 val = (s->horizontal ? x : y) - s->drag_start_coord;
942
943 if (s->drag_content) {
944 val = -val;
945 }
946 if (val != 0) {
947 scrollbar_set(s, drag_start_pos + val, !(s->drag_content));
948 }
949
950 s->dragging = false;
951 s->drag_content = false;
952
953 if (s->pair_drag) {
954 s->pair_drag = false;
955
956 drag_start_pos = s->pair->drag_start_pos;
957 val = (s->pair->horizontal ? x : y) - s->pair->drag_start_coord;
958
959 if (s->pair->drag_content) {
960 val = -val;
961 }
962 if (val != 0) {
963 scrollbar_set(s->pair, drag_start_pos + val,
964 !(s->pair->drag_content));
965 }
966
967 s->pair->dragging = false;
968 s->pair->drag_content = false;
969 }
970
971 msg.scrollbar = s;
974}
975
976
977/*
978 * Exported interface. Documented in scrollbar.h
979 */
980void scrollbar_start_content_drag(struct scrollbar *s, int x, int y)
981{
982 scrollbar_drag_start_internal(s, x, y, true, true);
983}
984
985
986/*
987 * Exported interface. Documented in scrollbar.h
988 */
989void scrollbar_make_pair(struct scrollbar *horizontal,
990 struct scrollbar *vertical)
991{
992 assert(horizontal->horizontal &&
993 !vertical->horizontal);
994
995 horizontal->pair = vertical;
996 vertical->pair = horizontal;
997}
998
999
1000/*
1001 * Exported interface. Documented in scrollbar.h
1002 */
1004{
1005 return s->client_data;
1006}
#define SCROLL_BOTTOM
Definition: gui.c:172
#define SCROLL_PAGE_UP
Definition: gui.c:170
#define SCROLL_PAGE_DOWN
Definition: gui.c:171
#define SCROLL_TOP
Definition: gui.c:169
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:694
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:888
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:768
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:989
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:627
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:711
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:1003
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:980
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:639
void scrollbar_mouse_drag_end(struct scrollbar *s, browser_mouse_state mouse, int x, int y)
Handle end of mouse drags.
Definition: scrollbar.c:932
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