NetSurf
scroll.c
Go to the documentation of this file.
1/*
2 * Copyright 2010 Vincent Sanders <vince@simtec.co.uk>
3 *
4 * Framebuffer windowing toolkit scrollbar widgets
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#include <assert.h>
22
23#include <stdbool.h>
24
25#include <libnsfb.h>
26#include <libnsfb_plot.h>
27#include <libnsfb_event.h>
28#include <libnsfb_cursor.h>
29
30#include "utils/log.h"
32
33#include "framebuffer/gui.h"
34#include "framebuffer/fbtk.h"
36
37#include "widget.h"
38
39/* Vertical scroll widget */
40
41static int
43{
44 int vscroll;
45 int vpos;
46
47 nsfb_bbox_t bbox;
48 nsfb_bbox_t rect;
50
51 fbtk_get_bbox(widget, &bbox);
52
53 nsfb_claim(root->u.root.fb, &bbox);
54
55 rect = bbox;
56
57 /* background */
58 nsfb_plot_rectangle_fill(root->u.root.fb, &rect, widget->bg);
59
60 /* scroll well */
61 rect.x0 = bbox.x0 + 2;
62 rect.y0 = bbox.y0 + 1;
63 rect.x1 = bbox.x1 - 3;
64 rect.y1 = bbox.y1 - 2;
65
66 nsfb_plot_rectangle_fill(root->u.root.fb, &rect, widget->fg);
67 nsfb_plot_rectangle(root->u.root.fb, &rect, 1, 0xFF999999, false, false);
68
69 /* scroll bar */
70 if ((widget->u.scroll.maximum - widget->u.scroll.minimum) > 0) {
71 vscroll = ((widget->height - 4) * widget->u.scroll.thumb) /
72 (widget->u.scroll.maximum - widget->u.scroll.minimum) ;
73 vpos = ((widget->height - 4) * widget->u.scroll.position) /
74 (widget->u.scroll.maximum - widget->u.scroll.minimum) ;
75 } else {
76 vscroll = (widget->height - 4);
77 vpos = 0;
78 }
79
80 rect.x0 = bbox.x0 + 5;
81 rect.y0 = bbox.y0 + 3 + vpos;
82 rect.x1 = bbox.x0 + widget->width - 5;
83 rect.y1 = bbox.y0 + vscroll + vpos;
84
85 nsfb_plot_rectangle_fill(root->u.root.fb, &rect, widget->bg);
86
87 nsfb_update(root->u.root.fb, &bbox);
88
89 return 0;
90}
91
92static int
94{
95 int newpos;
96 fbtk_widget_t *scrollw = cbi->context;
97
98 newpos = ((widget->u.scroll.drag_position +
99 (cbi->y - widget->u.scroll.drag)) *
100 (widget->u.scroll.maximum - widget->u.scroll.minimum)) /
101 (widget->height - 4);
102
103 if (newpos < scrollw->u.scroll.minimum)
104 newpos = scrollw->u.scroll.minimum;
105
106 if (newpos > (scrollw->u.scroll.maximum - scrollw->u.scroll.thumb ))
107 newpos = (scrollw->u.scroll.maximum - scrollw->u.scroll.thumb);
108
109 if (newpos == scrollw->u.scroll.position)
110 return 0;
111
112 return fbtk_post_callback(widget, FBTK_CBT_SCROLLY, newpos);
113}
114
115static int
117{
118 int newpos;
119 fbtk_widget_t *scrollw = cbi->context;
120
121 if (cbi->event->type != NSFB_EVENT_KEY_DOWN)
122 return 0;
123
124 newpos = scrollw->u.scroll.position - scrollw->u.scroll.page;
125 if (newpos < scrollw->u.scroll.minimum)
126 newpos = scrollw->u.scroll.minimum;
127
128 if (newpos == scrollw->u.scroll.position)
129 return 0;
130
131 return fbtk_post_callback(scrollw, FBTK_CBT_SCROLLY, newpos);
132}
133
134static int
136{
137 int newpos;
138 fbtk_widget_t *scrollw = cbi->context;
139
140 if (cbi->event->type != NSFB_EVENT_KEY_DOWN)
141 return 0;
142
143 newpos = scrollw->u.scroll.position + scrollw->u.scroll.page;
144 if (newpos > (scrollw->u.scroll.maximum - scrollw->u.scroll.thumb ))
145 newpos = (scrollw->u.scroll.maximum - scrollw->u.scroll.thumb);
146
147 if (newpos == scrollw->u.scroll.position)
148 return 0;
149
150 return fbtk_post_callback(scrollw, FBTK_CBT_SCROLLY, newpos);
151}
152
153static int
155{
156 int vscroll;
157 int vpos;
158 int newpos;
159 int ret = 0;
160
161 if (cbi->event->type != NSFB_EVENT_KEY_DOWN) {
162 /* end all drags, just in case */
163 if (fbtk_set_handler(widget, FBTK_CBT_POINTERMOVE, NULL, NULL) != NULL)
164 fbtk_tgrab_pointer(widget);
165 return 0;
166 }
167
168 switch (cbi->event->value.keycode) {
169
170 case NSFB_KEY_MOUSE_4:
171 /* scroll up */
172 newpos = widget->u.scroll.position - widget->u.scroll.page;
173 if (newpos < widget->u.scroll.minimum)
174 newpos = widget->u.scroll.minimum;
175 ret = fbtk_post_callback(cbi->context, FBTK_CBT_SCROLLY, newpos);
176 break;
177
178 case NSFB_KEY_MOUSE_5:
179 /* scroll down */
180 newpos = widget->u.scroll.position + widget->u.scroll.page;
181 if (newpos > widget->u.scroll.maximum)
182 newpos = widget->u.scroll.maximum;
183 ret = fbtk_post_callback(cbi->context, FBTK_CBT_SCROLLY, newpos);
184 break;
185
186 default:
187
188 if ((widget->u.scroll.maximum - widget->u.scroll.minimum) > 0) {
189 vscroll = ((widget->height - 4) * widget->u.scroll.thumb) /
190 (widget->u.scroll.maximum - widget->u.scroll.minimum) ;
191 vpos = ((widget->height - 4) * widget->u.scroll.position) /
192 (widget->u.scroll.maximum - widget->u.scroll.minimum) ;
193 } else {
194 vscroll = (widget->height - 4);
195 vpos = 0;
196 }
197
198 if (cbi->y < vpos) {
199 /* above bar */
200 newpos = widget->u.scroll.position - widget->u.scroll.thumb;
201 if (newpos < widget->u.scroll.minimum)
202 newpos = widget->u.scroll.minimum;
203 ret = fbtk_post_callback(cbi->context, FBTK_CBT_SCROLLY, newpos);
204 } else if (cbi->y > (vpos + vscroll)) {
205 /* below bar */
206 newpos = widget->u.scroll.position + widget->u.scroll.thumb;
207 if (newpos > widget->u.scroll.maximum)
208 newpos = widget->u.scroll.maximum;
209 ret = fbtk_post_callback(cbi->context, FBTK_CBT_SCROLLY, newpos);
210 } else {
211 /* on bar - start drag */
212 widget->u.scroll.drag = cbi->y;
213 widget->u.scroll.drag_position = vpos;
215 fbtk_tgrab_pointer(widget);
216 }
217 }
218 return ret;
219}
220
221
222/* exported function documented in fbtk.h */
225 int x,
226 int y,
227 int width,
228 int height,
229 colour fg,
230 colour bg,
231 fbtk_callback callback,
232 void *context)
233{
234 fbtk_widget_t *neww;
235
236 neww = fbtk_widget_new(parent,
238 x,
239 y + scrollu.height,
240 width,
242
243 neww->fg = fg;
244 neww->bg = bg;
245 neww->mapped = true;
246
248
250
251 fbtk_set_handler(neww, FBTK_CBT_SCROLLY, callback, context);
252
254 x,
255 y,
256 width,
258 fg,
259 &scrollu,
261 neww);
262
264 x,
265 y + height - scrolld.height,
266 width,
268 fg,
269 &scrolld,
271 neww);
272
273
274 return neww;
275}
276
277
278/* exported function documented in fbtk.h */
279void
281 int x,
282 int y,
283 int width,
284 int height)
285{
286 assert(vscroll->type == FB_WIDGET_TYPE_VSCROLL);
287
288 fbtk_set_pos_and_size(vscroll, x, y + scrollu.height,
291 x, y, width, scrollu.height);
293 x, y + height - scrolld.height,
295}
296
297/* Horizontal scroll widget */
298
299static int
301{
302 int hscroll;
303 int hpos;
304 nsfb_bbox_t bbox;
305 nsfb_bbox_t rect;
307
308 fbtk_get_bbox(widget, &bbox);
309
310 nsfb_claim(root->u.root.fb, &bbox);
311
312 rect = bbox;
313
314 /* background */
315 nsfb_plot_rectangle_fill(root->u.root.fb, &rect, widget->bg);
316
317 /* scroll well */
318 rect.x0 = bbox.x0 + 1;
319 rect.y0 = bbox.y0 + 2;
320 rect.x1 = bbox.x1 - 2;
321 rect.y1 = bbox.y1 - 3;
322 nsfb_plot_rectangle_fill(root->u.root.fb, &rect, widget->fg);
323
324 /* scroll well outline */
325 nsfb_plot_rectangle(root->u.root.fb, &rect, 1, 0xFF999999, false, false);
326
327 if ((widget->u.scroll.maximum - widget->u.scroll.minimum) > 0) {
328 hscroll = ((widget->width - 4) * widget->u.scroll.thumb) /
329 (widget->u.scroll.maximum - widget->u.scroll.minimum) ;
330 hpos = ((widget->width - 4) * widget->u.scroll.position) /
331 (widget->u.scroll.maximum - widget->u.scroll.minimum) ;
332 } else {
333 hscroll = (widget->width - 4);
334 hpos = 0;
335 }
336
337 NSLOG(netsurf, INFO, "hscroll %d", hscroll);
338
339 rect.x0 = bbox.x0 + 3 + hpos;
340 rect.y0 = bbox.y0 + 5;
341 rect.x1 = bbox.x0 + hscroll + hpos;
342 rect.y1 = bbox.y0 + widget->height - 5;
343
344 nsfb_plot_rectangle_fill(root->u.root.fb, &rect, widget->bg);
345
346 nsfb_update(root->u.root.fb, &bbox);
347
348 return 0;
349}
350
351static int
353{
354 int newpos;
355 fbtk_widget_t *scrollw = cbi->context;
356
357 if (cbi->event->type != NSFB_EVENT_KEY_DOWN)
358 return 0;
359
360 newpos = scrollw->u.scroll.position - scrollw->u.scroll.page;
361 if (newpos < scrollw->u.scroll.minimum)
362 newpos = scrollw->u.scroll.minimum;
363
364 if (newpos == scrollw->u.scroll.position) {
365 NSLOG(netsurf, INFO, "horiz scroll was the same %d", newpos);
366 return 0;
367 }
368
369 return fbtk_post_callback(scrollw, FBTK_CBT_SCROLLX, newpos);
370}
371
372static int
374{
375 int newpos;
376 fbtk_widget_t *scrollw = cbi->context;
377
378 if (cbi->event->type != NSFB_EVENT_KEY_DOWN)
379 return 0;
380
381 newpos = scrollw->u.scroll.position + scrollw->u.scroll.page;
382 if (newpos > (scrollw->u.scroll.maximum - scrollw->u.scroll.thumb ))
383 newpos = (scrollw->u.scroll.maximum - scrollw->u.scroll.thumb);
384
385 if (newpos == scrollw->u.scroll.position)
386 return 0;
387
388 return fbtk_post_callback(scrollw, FBTK_CBT_SCROLLX, newpos);
389}
390
391static int
393{
394 int newpos;
395 fbtk_widget_t *scrollw = cbi->context;
396
397 newpos = ((widget->u.scroll.drag_position +
398 (cbi->x - widget->u.scroll.drag)) *
399 (widget->u.scroll.maximum - widget->u.scroll.minimum)) /
400 (widget->width - 4);
401
402 if (newpos < scrollw->u.scroll.minimum)
403 newpos = scrollw->u.scroll.minimum;
404
405 if (newpos > (scrollw->u.scroll.maximum - scrollw->u.scroll.thumb ))
406 newpos = (scrollw->u.scroll.maximum - scrollw->u.scroll.thumb);
407
408 if (newpos == scrollw->u.scroll.position)
409 return 0;
410
411 return fbtk_post_callback(widget, FBTK_CBT_SCROLLX, newpos);
412}
413
414static int
416{
417 int hscroll;
418 int hpos;
419 int newpos;
420 int ret = 0;
421
422 if (cbi->event->type != NSFB_EVENT_KEY_DOWN) {
423 /* end all drags, just in case */
424 if (fbtk_set_handler(widget, FBTK_CBT_POINTERMOVE, NULL, NULL) != NULL)
425 fbtk_tgrab_pointer(widget);
426 return 0;
427 }
428
429 if ((widget->u.scroll.maximum - widget->u.scroll.minimum) > 0) {
430 hscroll = ((widget->width - 4) * widget->u.scroll.thumb) /
431 (widget->u.scroll.maximum - widget->u.scroll.minimum) ;
432 hpos = ((widget->width - 4) * widget->u.scroll.position) /
433 (widget->u.scroll.maximum - widget->u.scroll.minimum) ;
434 } else {
435 hscroll = (widget->width - 4);
436 hpos = 0;
437 }
438
439 if (cbi->x < hpos) {
440 /* left of bar */
441 newpos = widget->u.scroll.position - widget->u.scroll.page;
442 if (newpos < widget->u.scroll.minimum)
443 newpos = widget->u.scroll.minimum;
444 ret = fbtk_post_callback(cbi->context, FBTK_CBT_SCROLLX, newpos);
445 } else if (cbi->x > (hpos + hscroll)) {
446 /* right of bar */
447 newpos = widget->u.scroll.position + widget->u.scroll.page;
448 if (newpos > widget->u.scroll.maximum)
449 newpos = widget->u.scroll.maximum;
450 ret = fbtk_post_callback(cbi->context, FBTK_CBT_SCROLLX, newpos);
451 } else {
452 /* on bar - start drag */
453 widget->u.scroll.drag = cbi->x;
454 widget->u.scroll.drag_position = hpos;
456 fbtk_tgrab_pointer(widget);
457 }
458 return ret;
459}
460
461/* exported function documented in fbtk.h */
464 int x,
465 int y,
466 int width,
467 int height,
468 colour fg,
469 colour bg,
470 fbtk_callback callback,
471 void *context)
472{
473 fbtk_widget_t *neww;
474
475 neww = fbtk_widget_new(parent,
477 x + scrolll.width,
478 y,
480 height);
481
482 neww->fg = fg;
483 neww->bg = bg;
484 neww->mapped = true;
485
488 fbtk_set_handler(neww, FBTK_CBT_SCROLLX, callback, context);
489
491 x,
492 y,
494 height,
495 fg,
496 &scrolll,
498 neww);
499
501 x + width - scrollr.width,
502 y,
504 height,
505 fg,
506 &scrollr,
508 neww);
509
510 return neww;
511}
512
513/* exported function documented in fbtk.h */
514void
516 int x,
517 int y,
518 int width,
519 int height)
520{
521 assert(scrollh->type == FB_WIDGET_TYPE_HSCROLL);
522
523 fbtk_set_pos_and_size(scrollh, x + scrolll.width, y,
526 x, y, scrolll.width, height);
528 x + width - scrollr.width, y,
530}
531
532
533/* exported function documented in fbtk.h */
534bool
536 int min,
537 int max,
538 int thumb,
539 int page)
540{
541 if (widget == NULL)
542 return false;
543
544 if ((widget->type != FB_WIDGET_TYPE_HSCROLL) &&
545 (widget->type != FB_WIDGET_TYPE_VSCROLL))
546 return false;
547
548 widget->u.scroll.minimum = min;
549 widget->u.scroll.maximum = max;
550 widget->u.scroll.thumb = thumb;
551 widget->u.scroll.page = page;
552
553 if (widget->u.scroll.position > max)
554 widget->u.scroll.position = max;
555 if (widget->u.scroll.position < min)
556 widget->u.scroll.position = min;
557
558 fbtk_request_redraw(widget);
559
560 return true;
561}
562
563/* exported function documented in fbtk.h */
564bool
566{
567 if (widget == NULL)
568 return false;
569
570 if ((widget->type != FB_WIDGET_TYPE_HSCROLL) &&
571 (widget->type != FB_WIDGET_TYPE_VSCROLL))
572 return false;
573
574 if ((position < widget->u.scroll.minimum) ||
575 (position > widget->u.scroll.maximum))
576 return false;
577
578 widget->u.scroll.position = position;
579
580 fbtk_request_redraw(widget);
581
582 return true;
583}
584
585/*
586 * Local Variables:
587 * c-basic-offset:8
588 * End:
589 */
Browser window creation and manipulation interface.
wimp_w parent
Definition: dialog.c:88
fbtk_widget_t * fbtk_widget_new(fbtk_widget_t *parent, enum fbtk_widgettype_e type, int x, int y, int width, int height)
creates a new widget and insert it into to hierachy.
Definition: fbtk.c:546
fbtk_widget_t * fbtk_get_root_widget(fbtk_widget_t *widget)
find the root widget from any widget in the toolkit hierarchy.
Definition: fbtk.c:412
fbtk_callback fbtk_set_handler(fbtk_widget_t *widget, fbtk_callback_type cbt, fbtk_callback cb, void *pw)
Set a callback handler.
Definition: fbtk.c:693
@ FBTK_CBT_POINTERMOVE
Definition: fbtk.h:41
@ FBTK_CBT_REDRAW
Definition: fbtk.h:44
@ FBTK_CBT_SCROLLY
Definition: fbtk.h:38
@ FBTK_CBT_SCROLLX
Definition: fbtk.h:37
@ FBTK_CBT_CLICK
Definition: fbtk.h:39
bool fbtk_set_pos_and_size(fbtk_widget_t *widget, int x, int y, int width, int height)
Change the widget's position and size.
Definition: fbtk.c:209
void fbtk_request_redraw(fbtk_widget_t *widget)
Indicate a widget should be redrawn.
Definition: fbtk.c:82
bool fbtk_tgrab_pointer(fbtk_widget_t *widget)
Toggle pointer grab.
Definition: event.c:95
int fbtk_post_callback(fbtk_widget_t *widget, fbtk_callback_type cbt,...)
Helper function to allow simple calling of callbacks with parameters.
Definition: fbtk.c:715
bool fbtk_get_bbox(fbtk_widget_t *widget, struct nsfb_bbox_s *bbox)
Get a widget's bounding box in absolute screen co-ordinates.
fbtk_widget_t * fbtk_create_button(fbtk_widget_t *window, int x, int y, int width, int height, colour c, struct fbtk_bitmap *image, fbtk_callback click, void *pw)
Create a button widget with an image.
Definition: bitmap.c:107
int(* fbtk_callback)(fbtk_widget_t *widget, fbtk_callback_info *cbi)
Definition: fbtk.h:83
static struct directory * root
Definition: filename.c:55
struct fbtk_bitmap scrolll
struct fbtk_bitmap scrollr
struct fbtk_bitmap scrolld
struct fbtk_bitmap scrollu
#define NSLOG(catname, level, logmsg, args...)
Definition: log.h:116
int width
Definition: gui.c:160
int height
Definition: gui.c:161
static int hscrollr_click(fbtk_widget_t *widget, fbtk_callback_info *cbi)
Definition: scroll.c:373
fbtk_widget_t * fbtk_create_vscroll(fbtk_widget_t *parent, int x, int y, int width, int height, colour fg, colour bg, fbtk_callback callback, void *context)
Create a vertical scroll widget.
Definition: scroll.c:224
static int hscrolll_click(fbtk_widget_t *widget, fbtk_callback_info *cbi)
Definition: scroll.c:352
static int hscroll_redraw(fbtk_widget_t *widget, fbtk_callback_info *cbi)
Definition: scroll.c:300
bool fbtk_set_scroll_position(fbtk_widget_t *widget, int position)
set scroll widget position.
Definition: scroll.c:565
static int vscrollu_click(fbtk_widget_t *widget, fbtk_callback_info *cbi)
Definition: scroll.c:116
static int vscrollarea_click(fbtk_widget_t *widget, fbtk_callback_info *cbi)
Definition: scroll.c:154
static int hscroll_drag(fbtk_widget_t *widget, fbtk_callback_info *cbi)
Definition: scroll.c:392
bool fbtk_set_scroll_parameters(fbtk_widget_t *widget, int min, int max, int thumb, int page)
Set scoll widget parameters.
Definition: scroll.c:535
void fbtk_reposition_hscroll(fbtk_widget_t *scrollh, int x, int y, int width, int height)
Move and/or resize a horizontal scroll widget.
Definition: scroll.c:515
static int vscroll_redraw(fbtk_widget_t *widget, fbtk_callback_info *cbi)
Definition: scroll.c:42
void fbtk_reposition_vscroll(fbtk_widget_t *vscroll, int x, int y, int width, int height)
Move and/or resize a vertical scroll widget.
Definition: scroll.c:280
static int vscroll_drag(fbtk_widget_t *widget, fbtk_callback_info *cbi)
Definition: scroll.c:93
static int hscrollarea_click(fbtk_widget_t *widget, fbtk_callback_info *cbi)
Definition: scroll.c:415
fbtk_widget_t * fbtk_create_hscroll(fbtk_widget_t *parent, int x, int y, int width, int height, colour fg, colour bg, fbtk_callback callback, void *context)
Create a horizontal scroll widget.
Definition: scroll.c:463
static int vscrolld_click(fbtk_widget_t *widget, fbtk_callback_info *cbi)
Definition: scroll.c:135
int height
Definition: fbtk.h:65
int width
Definition: fbtk.h:64
widget callback information
Definition: fbtk.h:52
nsfb_event_t * event
Definition: fbtk.h:55
void * context
Definition: fbtk.h:54
Widget description.
Definition: widget.h:120
enum fbtk_widgettype_e type
The type of the widget.
Definition: widget.h:154
bool mapped
The widget is mapped/visible .
Definition: widget.h:130
struct fbtk_widget_s * btnul
Definition: widget.h:205
struct fbtk_widget_s * btndr
Definition: widget.h:206
int position
Definition: widget.h:202
int maximum
Definition: widget.h:199
colour bg
Definition: widget.h:137
int drag_position
Definition: widget.h:204
int height
Definition: widget.h:136
int minimum
Definition: widget.h:198
struct fbtk_widget_s::@35::@40 scroll
union fbtk_widget_s::@35 u
colour fg
Definition: widget.h:138
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
uint32_t colour
Colour type: XBGR.
Definition: types.h:35
struct rect rect
Rectangle coordinates.
#define min(x, y)
Definition: utils.h:46
#define max(x, y)
Definition: utils.h:50
@ FB_WIDGET_TYPE_VSCROLL
Definition: widget.h:31
@ FB_WIDGET_TYPE_HSCROLL
Definition: widget.h:30