/* exported function documented in fbtk.h */ fbtk_widget_t * fbtk_create_button(fbtk_widget_t *parent, int x, int y, int width, int height, colour c, struct fbtk_bitmap *image, fbtk_callback click, void *pw) { fbtk_widget_t *neww; neww = fbtk_widget_new(parent, FB_WIDGET_TYPE_BITMAP, x, y, width, height); neww->bg = c; neww->mapped = true; neww->u.bitmap.bitmap = image; fbtk_set_handler(neww, FBTK_CBT_REDRAW, fb_redraw_bitmap, NULL); fbtk_set_handler(neww, FBTK_CBT_CLICK, click, pw); fbtk_set_handler(neww, FBTK_CBT_POINTERENTER, fbtk_set_ptr, &null_image); return neww; }
/* exported function documented in fbtk.h */ fbtk_widget_t * fbtk_create_writable_text(fbtk_widget_t *parent, int x, int y, int width, int height, colour bg, colour fg, bool outline, fbtk_enter_t enter, void *pw) { fbtk_widget_t *neww; neww = fbtk_widget_new(parent, FB_WIDGET_TYPE_TEXT, x, y, width, height); neww->fg = fg; neww->bg = bg; neww->mapped = true; neww->u.text.outline = outline; neww->u.text.enter = enter; neww->u.text.pw = pw; fbtk_set_handler(neww, FBTK_CBT_REDRAW, fb_redraw_text, NULL); fbtk_set_handler(neww, FBTK_CBT_INPUT, text_input, neww); return neww; }
/* exported function documented in fbtk.h */ fbtk_widget_t * fbtk_create_text_button(fbtk_widget_t *parent, int x, int y, int width, int height, colour bg, colour fg, fbtk_callback click, void *pw) { fbtk_widget_t *neww; neww = fbtk_widget_new(parent, FB_WIDGET_TYPE_TEXT, x, y, width, height); neww->fg = fg; neww->bg = bg; neww->mapped = true; neww->u.text.outline = true; fbtk_set_handler(neww, FBTK_CBT_REDRAW, fb_redraw_text_button, NULL); fbtk_set_handler(neww, FBTK_CBT_CLICK, click, pw); fbtk_set_handler(neww, FBTK_CBT_POINTERENTER, fbtk_set_ptr, &hand_image); return neww; }
/* exported function documented in fbtk.h */ 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) { fbtk_widget_t *neww; neww = fbtk_widget_new(parent, FB_WIDGET_TYPE_VSCROLL, x, y + scrollu.height, width, height - scrollu.height - scrolld.height); neww->fg = fg; neww->bg = bg; neww->mapped = true; fbtk_set_handler(neww, FBTK_CBT_REDRAW, vscroll_redraw, NULL); fbtk_set_handler(neww, FBTK_CBT_CLICK, vscrollarea_click, neww); fbtk_set_handler(neww, FBTK_CBT_SCROLLY, callback, context); neww->u.scroll.btnul = fbtk_create_button(parent, x, y, width, scrollu.height, fg, load_bitmap("PROGDIR:Resources/Icons/scrollu.png"), vscrollu_click, neww); neww->u.scroll.btndr = fbtk_create_button(parent, x, y + height - scrolld.height, width, scrolld.height, fg, load_bitmap("PROGDIR:Resources/Icons/scrolld.png"), vscrolld_click, neww); return neww; }
/* exported function documented in fbtk.h */ void fbtk_writable_text(fbtk_widget_t *widget, fbtk_enter_t enter, void *pw) { widget->u.text.enter = enter; widget->u.text.pw = pw; fbtk_set_handler(widget, FBTK_CBT_INPUT, text_input, widget); }
static int hscrollarea_click(fbtk_widget_t *widget, fbtk_callback_info *cbi) { int hscroll; int hpos; int newpos; int ret = 0; if (cbi->event->type != NSFB_EVENT_KEY_DOWN) { /* end all drags, just in case */ if (fbtk_set_handler(widget, FBTK_CBT_POINTERMOVE, NULL, NULL) != NULL) fbtk_tgrab_pointer(widget); return 0; } if ((widget->u.scroll.maximum - widget->u.scroll.minimum) > 0) { hscroll = ((widget->width - 4) * widget->u.scroll.thumb) / (widget->u.scroll.maximum - widget->u.scroll.minimum) ; hpos = ((widget->width - 4) * widget->u.scroll.position) / (widget->u.scroll.maximum - widget->u.scroll.minimum) ; } else { hscroll = (widget->width - 4); hpos = 0; } if (cbi->x < hpos) { /* left of bar */ newpos = widget->u.scroll.position - widget->u.scroll.page; if (newpos < widget->u.scroll.minimum) newpos = widget->u.scroll.minimum; ret = fbtk_post_callback(cbi->context, FBTK_CBT_SCROLLX, newpos); } else if (cbi->x > (hpos + hscroll)) { /* right of bar */ newpos = widget->u.scroll.position + widget->u.scroll.page; if (newpos > widget->u.scroll.maximum) newpos = widget->u.scroll.maximum; ret = fbtk_post_callback(cbi->context, FBTK_CBT_SCROLLX, newpos); } else { /* on bar - start drag */ widget->u.scroll.drag = cbi->x; widget->u.scroll.drag_position = hpos; fbtk_set_handler(widget, FBTK_CBT_POINTERMOVE, hscroll_drag, widget); fbtk_tgrab_pointer(widget); } return ret; }
static void create_browser_widget(struct gui_window *gw, int toolbar_height, int furniture_width) { struct browser_widget_s *browser_widget; browser_widget = calloc(1, sizeof(struct browser_widget_s)); gw->browser = fbtk_create_user(gw->window, 0, toolbar_height, -furniture_width, -furniture_width, browser_widget); fbtk_set_handler(gw->browser, FBTK_CBT_REDRAW, fb_browser_window_redraw, gw); fbtk_set_handler(gw->browser, FBTK_CBT_INPUT, fb_browser_window_input, gw); fbtk_set_handler(gw->browser, FBTK_CBT_CLICK, fb_browser_window_click, gw); fbtk_set_handler(gw->browser, FBTK_CBT_STRIP_FOCUS, fb_browser_window_strip_focus, gw); fbtk_set_handler(gw->browser, FBTK_CBT_POINTERMOVE, fb_browser_window_move, gw); }
/* exported function documented in fbtk.h */ fbtk_widget_t * fbtk_create_fill(fbtk_widget_t *parent, int x, int y, int width, int height, colour c) { fbtk_widget_t *neww; neww = fbtk_widget_new(parent, FB_WIDGET_TYPE_FILL, x, y, width, height); neww->bg = c; neww->mapped = true; fbtk_set_handler(neww, FBTK_CBT_REDRAW, fb_redraw_fill, NULL); return neww; }
/* exported function documented in fbtk.h */ fbtk_widget_t * fbtk_create_bitmap(fbtk_widget_t *parent, int x, int y, int width, int height, colour c, struct fbtk_bitmap *image) { fbtk_widget_t *neww; neww = fbtk_widget_new(parent, FB_WIDGET_TYPE_BITMAP, x, y, width, height); neww->bg = c; neww->mapped = true; neww->u.bitmap.bitmap = image; fbtk_set_handler(neww, FBTK_CBT_REDRAW, fb_redraw_bitmap, NULL); return neww; }
/* exported function documented in fbtk.h */ fbtk_widget_t * fbtk_create_text(fbtk_widget_t *parent, int x, int y, int width, int height, colour bg, colour fg, bool outline) { fbtk_widget_t *neww; neww = fbtk_widget_new(parent, FB_WIDGET_TYPE_TEXT, x, y, width, height); neww->fg = fg; neww->bg = bg; neww->mapped = true; neww->u.text.outline = outline; fbtk_set_handler(neww, FBTK_CBT_REDRAW, fb_redraw_text, NULL); return neww; }
static int localhistory_redraw(fbtk_widget_t *widget, fbtk_callback_info *cbi) { struct gui_localhistory *glh = cbi->context; nsfb_bbox_t rbox; struct redraw_context ctx = { .interactive = true, .background_images = true, .plot = &fb_plotters }; rbox.x0 = fbtk_get_absx(widget); rbox.y0 = fbtk_get_absy(widget); rbox.x1 = rbox.x0 + fbtk_get_width(widget); rbox.y1 = rbox.y0 + fbtk_get_height(widget); nsfb_claim(fbtk_get_nsfb(widget), &rbox); nsfb_plot_rectangle_fill(fbtk_get_nsfb(widget), &rbox, 0xffffffff); history_redraw_rectangle(glh->bw->history, glh->scrollx, glh->scrolly, fbtk_get_width(widget) + glh->scrollx, fbtk_get_height(widget) + glh->scrolly, 0, 0, &ctx); nsfb_update(fbtk_get_nsfb(widget), &rbox); return 0; } static int localhistory_click(fbtk_widget_t *widget, fbtk_callback_info *cbi) { struct gui_localhistory *glh = cbi->context; if (cbi->event->type != NSFB_EVENT_KEY_UP) return 0; history_click(glh->bw, glh->bw->history, cbi->x, cbi->y, false); fbtk_set_mapping(glh->window, false); return 1; } struct gui_localhistory * fb_create_localhistory(struct browser_window *bw, fbtk_widget_t *parent, int furniture_width) { struct gui_localhistory *glh; glh = calloc(1, sizeof(struct gui_localhistory)); if (glh == NULL) return NULL; glh->bw = bw; /* container window */ glh->window = fbtk_create_window(parent, 0, 0, 0, 0, 0); glh->history = fbtk_create_user(glh->window, 0, 0, -furniture_width, -furniture_width, glh); fbtk_set_handler(glh->history, FBTK_CBT_REDRAW, localhistory_redraw, glh); fbtk_set_handler(glh->history, FBTK_CBT_CLICK, localhistory_click, glh); /* fbtk_set_handler(gw->localhistory, FBTK_CBT_INPUT, fb_browser_window_input, gw); fbtk_set_handler(gw->localhistory, FBTK_CBT_POINTERMOVE, fb_browser_window_move, bw); */ /* create horizontal scrollbar */ glh->hscroll = fbtk_create_hscroll(glh->window, 0, fbtk_get_height(glh->window) - furniture_width, fbtk_get_width(glh->window) - furniture_width, furniture_width, FB_SCROLL_COLOUR, FB_FRAME_COLOUR, NULL, NULL); glh->vscroll = fbtk_create_vscroll(glh->window, fbtk_get_width(glh->window) - furniture_width, 0, furniture_width, fbtk_get_height(glh->window) - furniture_width, FB_SCROLL_COLOUR, FB_FRAME_COLOUR, NULL, NULL); fbtk_create_fill(glh->window, fbtk_get_width(glh->window) - furniture_width, fbtk_get_height(glh->window) - furniture_width, furniture_width, furniture_width, FB_FRAME_COLOUR); return glh; } void fb_localhistory_map(struct gui_localhistory * glh) { fbtk_set_zorder(glh->window, INT_MIN); fbtk_set_mapping(glh->window, true); }
/* exported function documented fb/corewindow.h */ nserror fb_corewindow_init(fbtk_widget_t *parent, struct fb_corewindow *fb_cw) { int furniture_width; furniture_width = nsoption_int(fb_furniture_size); /* setup the core window callback table */ fb_cw->cb_table = &fb_cw_cb_table; fb_cw->drag_status = CORE_WINDOW_DRAG_NONE; /* container window */ fb_cw->wnd = fbtk_create_window(parent, 0, 0, 0, 0, 0); fb_cw->drawable = fbtk_create_user(fb_cw->wnd, 0, 0, -furniture_width, -furniture_width, fb_cw); fbtk_set_handler(fb_cw->drawable, FBTK_CBT_REDRAW, fb_cw_draw_event, fb_cw); fbtk_set_handler(fb_cw->drawable, FBTK_CBT_CLICK, fb_cw_mouse_press_event, fb_cw); /* fbtk_set_handler(fb_cw->drawable, FBTK_CBT_INPUT, fb_cw_input_event, fb_cw); fbtk_set_handler(fb_cw->drawable, FBTK_CBT_POINTERMOVE, fb_cw_move_event, fb_cw); */ /* create horizontal scrollbar */ fb_cw->hscroll = fbtk_create_hscroll(fb_cw->wnd, 0, fbtk_get_height(fb_cw->wnd) - furniture_width, fbtk_get_width(fb_cw->wnd) - furniture_width, furniture_width, FB_SCROLL_COLOUR, FB_FRAME_COLOUR, NULL, NULL); fb_cw->vscroll = fbtk_create_vscroll(fb_cw->wnd, fbtk_get_width(fb_cw->wnd) - furniture_width, 0, furniture_width, fbtk_get_height(fb_cw->wnd) - furniture_width, FB_SCROLL_COLOUR, FB_FRAME_COLOUR, NULL, NULL); fbtk_create_fill(fb_cw->wnd, fbtk_get_width(fb_cw->wnd) - furniture_width, fbtk_get_height(fb_cw->wnd) - furniture_width, furniture_width, furniture_width, FB_FRAME_COLOUR); return NSERROR_OK; }
static void create_normal_browser_window(struct gui_window *gw, int furniture_width) { fbtk_widget_t *widget; fbtk_widget_t *toolbar; int statusbar_width = 0; int toolbar_height = nsoption_int(fb_toolbar_size); LOG(("Normal window")); gw->window = fbtk_create_window(fbtk, 0, 0, 0, 0, 0); statusbar_width = nsoption_int(toolbar_status_size) * fbtk_get_width(gw->window) / 10000; /* toolbar */ toolbar = create_toolbar(gw, toolbar_height, 2, FB_FRAME_COLOUR, nsoption_charp(fb_toolbar_layout)); /* set the actually created toolbar height */ if (toolbar != NULL) { toolbar_height = fbtk_get_height(toolbar); } else { toolbar_height = 0; } /* status bar */ gw->status = fbtk_create_text(gw->window, 0, fbtk_get_height(gw->window) - furniture_width, statusbar_width, furniture_width, FB_FRAME_COLOUR, FB_COLOUR_BLACK, false); fbtk_set_handler(gw->status, FBTK_CBT_POINTERENTER, set_ptr_default_move, NULL); LOG(("status bar %p at %d,%d", gw->status, fbtk_get_absx(gw->status), fbtk_get_absy(gw->status))); /* create horizontal scrollbar */ gw->hscroll = fbtk_create_hscroll(gw->window, statusbar_width, fbtk_get_height(gw->window) - furniture_width, fbtk_get_width(gw->window) - statusbar_width - furniture_width, furniture_width, FB_SCROLL_COLOUR, FB_FRAME_COLOUR, fb_scroll_callback, gw); /* fill bottom right area */ if (nsoption_bool(fb_osk) == true) { widget = fbtk_create_text_button(gw->window, fbtk_get_width(gw->window) - furniture_width, fbtk_get_height(gw->window) - furniture_width, furniture_width, furniture_width, FB_FRAME_COLOUR, FB_COLOUR_BLACK, fb_osk_click, NULL); widget = fbtk_create_button(gw->window, fbtk_get_width(gw->window) - furniture_width, fbtk_get_height(gw->window) - furniture_width, furniture_width, furniture_width, FB_FRAME_COLOUR, &osk_image, fb_osk_click, NULL); } else { widget = fbtk_create_fill(gw->window, fbtk_get_width(gw->window) - furniture_width, fbtk_get_height(gw->window) - furniture_width, furniture_width, furniture_width, FB_FRAME_COLOUR); fbtk_set_handler(widget, FBTK_CBT_POINTERENTER, set_ptr_default_move, NULL); } /* create vertical scrollbar */ gw->vscroll = fbtk_create_vscroll(gw->window, fbtk_get_width(gw->window) - furniture_width, toolbar_height, furniture_width, fbtk_get_height(gw->window) - toolbar_height - furniture_width, FB_SCROLL_COLOUR, FB_FRAME_COLOUR, fb_scroll_callback, gw); /* browser widget */ create_browser_widget(gw, toolbar_height, nsoption_int(fb_furniture_size)); /* Give browser_window's user widget input focus */ fbtk_set_focus(gw->browser); }
/** Create a toolbar window and populate it with buttons. * * The toolbar layout uses a character to define buttons type and position: * b - back * l - local history * f - forward * s - stop * r - refresh * u - url bar expands to fit remaining space * t - throbber/activity indicator * c - close the current window * * The default layout is "blfsrut" there should be no more than a * single url bar entry or behaviour will be undefined. * * @param gw Parent window * @param toolbar_height The height in pixels of the toolbar * @param padding The padding in pixels round each element of the toolbar * @param frame_col Frame colour. * @param toolbar_layout A string defining which buttons and controls * should be added to the toolbar. May be empty * string to disable the bar.. * */ static fbtk_widget_t * create_toolbar(struct gui_window *gw, int toolbar_height, int padding, colour frame_col, const char *toolbar_layout) { fbtk_widget_t *toolbar; fbtk_widget_t *widget; int xpos; /* The position of the next widget. */ int xlhs = 0; /* extent of the left hand side widgets */ int xdir = 1; /* the direction of movement + or - 1 */ const char *itmtype; /* type of the next item */ if (toolbar_layout == NULL) { toolbar_layout = NSFB_TOOLBAR_DEFAULT_LAYOUT; } LOG(("Using toolbar layout %s", toolbar_layout)); itmtype = toolbar_layout; if (*itmtype == 0) { return NULL; } toolbar = fbtk_create_window(gw->window, 0, 0, 0, toolbar_height, frame_col); if (toolbar == NULL) { return NULL; } fbtk_set_handler(toolbar, FBTK_CBT_POINTERENTER, set_ptr_default_move, NULL); xpos = padding; /* loop proceeds creating widget on the left hand side until * it runs out of layout or encounters a url bar declaration * wherupon it works backwards from the end of the layout * untill the space left is for the url bar */ while ((itmtype >= toolbar_layout) && (*itmtype != 0) && (xdir !=0)) { LOG(("toolbar adding %c", *itmtype)); switch (*itmtype) { case 'b': /* back */ widget = fbtk_create_button(toolbar, (xdir == 1) ? xpos : xpos - left_arrow.width, padding, left_arrow.width, -padding, frame_col, &left_arrow, fb_leftarrow_click, gw); gw->back = widget; /* keep reference */ break; case 'l': /* local history */ widget = fbtk_create_button(toolbar, (xdir == 1) ? xpos : xpos - history_image.width, padding, history_image.width, -padding, frame_col, &history_image, fb_localhistory_btn_clik, gw); break; case 'f': /* forward */ widget = fbtk_create_button(toolbar, (xdir == 1)?xpos : xpos - right_arrow.width, padding, right_arrow.width, -padding, frame_col, &right_arrow, fb_rightarrow_click, gw); gw->forward = widget; break; case 'c': /* close the current window */ widget = fbtk_create_button(toolbar, (xdir == 1)?xpos : xpos - stop_image_g.width, padding, stop_image_g.width, -padding, frame_col, &stop_image_g, fb_close_click, gw->bw); break; case 's': /* stop */ widget = fbtk_create_button(toolbar, (xdir == 1)?xpos : xpos - stop_image.width, padding, stop_image.width, -padding, frame_col, &stop_image, fb_stop_click, gw->bw); break; case 'r': /* reload */ widget = fbtk_create_button(toolbar, (xdir == 1)?xpos : xpos - reload.width, padding, reload.width, -padding, frame_col, &reload, fb_reload_click, gw->bw); break; case 't': /* throbber/activity indicator */ widget = fbtk_create_bitmap(toolbar, (xdir == 1)?xpos : xpos - throbber0.width, padding, throbber0.width, -padding, frame_col, &throbber0); gw->throbber = widget; break; case 'u': /* url bar*/ if (xdir == -1) { /* met the u going backwards add url * now we know available extent */ widget = fbtk_create_writable_text(toolbar, xlhs, padding, xpos - xlhs, -padding, FB_COLOUR_WHITE, FB_COLOUR_BLACK, true, fb_url_enter, gw->bw); fbtk_set_handler(widget, FBTK_CBT_POINTERENTER, fb_url_move, gw->bw); gw->url = widget; /* keep reference */ /* toolbar is complete */ xdir = 0; break; } /* met url going forwards, note position and * reverse direction */ itmtype = toolbar_layout + strlen(toolbar_layout); xdir = -1; xlhs = xpos; xpos = (2 * fbtk_get_width(toolbar)); widget = toolbar; break; default: widget = NULL; xdir = 0; LOG(("Unknown element %c in toolbar layout", *itmtype)); break; } if (widget != NULL) { xpos += (xdir * (fbtk_get_width(widget) + padding)); } LOG(("xpos is %d",xpos)); itmtype += xdir; } fbtk_set_mapping(toolbar, true); return toolbar; }
static int vscrollarea_click(fbtk_widget_t *widget, fbtk_callback_info *cbi) { int vscroll; int vpos; int newpos; int ret = 0; if (cbi->event->type != NSFB_EVENT_KEY_DOWN) { /* end all drags, just in case */ if (fbtk_set_handler(widget, FBTK_CBT_POINTERMOVE, NULL, NULL) != NULL) fbtk_tgrab_pointer(widget); return 0; } switch (cbi->event->value.keycode) { case NSFB_KEY_MOUSE_4: /* scroll up */ newpos = widget->u.scroll.position - widget->u.scroll.page; if (newpos < widget->u.scroll.minimum) newpos = widget->u.scroll.minimum; ret = fbtk_post_callback(cbi->context, FBTK_CBT_SCROLLY, newpos); break; case NSFB_KEY_MOUSE_5: /* scroll down */ newpos = widget->u.scroll.position + widget->u.scroll.page; if (newpos > widget->u.scroll.maximum) newpos = widget->u.scroll.maximum; ret = fbtk_post_callback(cbi->context, FBTK_CBT_SCROLLY, newpos); break; default: if ((widget->u.scroll.maximum - widget->u.scroll.minimum) > 0) { vscroll = ((widget->height - 4) * widget->u.scroll.thumb) / (widget->u.scroll.maximum - widget->u.scroll.minimum) ; vpos = ((widget->height - 4) * widget->u.scroll.position) / (widget->u.scroll.maximum - widget->u.scroll.minimum) ; } else { vscroll = (widget->height - 4); vpos = 0; } if (cbi->y < vpos) { /* above bar */ newpos = widget->u.scroll.position - widget->u.scroll.thumb; if (newpos < widget->u.scroll.minimum) newpos = widget->u.scroll.minimum; ret = fbtk_post_callback(cbi->context, FBTK_CBT_SCROLLY, newpos); } else if (cbi->y > (vpos + vscroll)) { /* below bar */ newpos = widget->u.scroll.position + widget->u.scroll.thumb; if (newpos > widget->u.scroll.maximum) newpos = widget->u.scroll.maximum; ret = fbtk_post_callback(cbi->context, FBTK_CBT_SCROLLY, newpos); } else { /* on bar - start drag */ widget->u.scroll.drag = cbi->y; widget->u.scroll.drag_position = vpos; fbtk_set_handler(widget, FBTK_CBT_POINTERMOVE, vscroll_drag, widget); fbtk_tgrab_pointer(widget); } } return ret; }