diff options
Diffstat (limited to 'navit/gui/internal/gui_internal_widget.c')
-rw-r--r-- | navit/gui/internal/gui_internal_widget.c | 2439 |
1 files changed, 1256 insertions, 1183 deletions
diff --git a/navit/gui/internal/gui_internal_widget.c b/navit/gui/internal/gui_internal_widget.c index 3e1993025..3b979f011 100644 --- a/navit/gui/internal/gui_internal_widget.c +++ b/navit/gui/internal/gui_internal_widget.c @@ -12,135 +12,188 @@ #include "gui_internal_menu.h" static void gui_internal_scroll_buttons_init(struct gui_priv *this, struct widget *widget, struct scroll_buttons *sb); +void gui_internal_box_pack(struct gui_priv *this, struct widget *w); -static void -gui_internal_background_render(struct gui_priv *this, struct widget *w) -{ - struct point pnt=w->p; - if (w->state & STATE_HIGHLIGHTED) - graphics_draw_rectangle(this->gra, this->highlight_background, &pnt, w->w, w->h); - else { - if (w->background) - graphics_draw_rectangle(this->gra, w->background, &pnt, w->w, w->h); - } +/** + * @brief Transfer the content of one widget into another one (and optionally vice-versa) + * + * @param this The internal GUI instance + * @param[in,out] first The first widget + * @param[in,out] second The second widget + * @param move_only If non nul, transfer only the second widget into the first widget. The second widget is then deallocated and should be be used anymore (this is a move operation) + */ +static void gui_internal_widget_transfer_content(struct gui_priv *this, struct widget *first, struct widget *second, + int move_only) { + struct widget *temp; + + if (!first) { + dbg(lvl_error, "Refusing copy: first argument is NULL"); + return; + } + if (!second) { + dbg(lvl_error, "Refusing copy: second argument is NULL"); + return; + } + temp=g_new0(struct widget, 1); + memcpy(temp, first, sizeof(struct widget)); + memcpy(first, second, sizeof(struct widget)); + if (move_only) { + gui_internal_widget_destroy(this, temp); + /* gui_internal_widget_destroy() will do a g_free(temp), but will also deallocate all children widgets */ + /* Now, we also free the struct widget pointed to by second, so variable second should not be used anymore from this point */ + g_free(second); + } else { + memcpy(second, temp, sizeof(struct widget)); + g_free(temp); + } +} + +/** + * @brief Swap two widgets + * + * @param this The internal GUI instance + * @param[in,out] first The first widget + * @param[in,out] second The second widget + */ +void gui_internal_widget_swap(struct gui_priv *this, struct widget *first, struct widget *second) { + gui_internal_widget_transfer_content(this, first, second, 0); +} + +/** + * @brief Move the content of one widget into another one (the @p src widget is then deallocated and should be be used anymore) + * + * @param this The internal GUI instance + * @param[in,out] dst The destination widget + * @param[in,out] src The source widget + */ +void gui_internal_widget_move(struct gui_priv *this, struct widget *dst, struct widget *src) { + gui_internal_widget_transfer_content(this, dst, src, 1); +} + +static void gui_internal_background_render(struct gui_priv *this, struct widget *w) { + struct point pnt=w->p; + if (w->state & STATE_HIGHLIGHTED) + graphics_draw_rectangle(this->gra, this->highlight_background, &pnt, w->w, w->h); + else { + if (w->background) + graphics_draw_rectangle(this->gra, w->background, &pnt, w->w, w->h); + } } struct widget * -gui_internal_label_font_new(struct gui_priv *this, const char *text, int font) -{ - struct point p[4]; - int w=0; - int h=0; - - struct widget *widget=g_new0(struct widget, 1); - widget->type=widget_label; - widget->font_idx=font; - if (text) { - widget->text=g_strdup(text); - graphics_get_text_bbox(this->gra, this->fonts[font], widget->text, 0x10000, 0x0, p, 0); - w=p[2].x-p[0].x; - h=p[0].y-p[2].y; - } - widget->h=h+this->spacing; - widget->texth=h; - widget->w=w+this->spacing; - widget->textw=w; - widget->flags=gravity_center; - widget->foreground=this->text_foreground; - widget->text_background=this->text_background; - - return widget; +gui_internal_label_font_new(struct gui_priv *this, const char *text, int font) { + struct point p[4]; + int w=0; + int h=0; + + struct widget *widget=g_new0(struct widget, 1); + widget->type=widget_label; + widget->font_idx=font; + if (text) { + widget->text=g_strdup(text); + graphics_get_text_bbox(this->gra, this->fonts[font], widget->text, 0x10000, 0x0, p, 0); + w=p[2].x-p[0].x; + h=p[0].y-p[2].y; + } + widget->h=h+this->spacing; + widget->texth=h; + widget->w=w+this->spacing; + widget->textw=w; + widget->flags=gravity_center; + widget->foreground=this->text_foreground; + widget->text_background=this->text_background; + + return widget; } - + struct widget * -gui_internal_label_new(struct gui_priv *this, const char *text) -{ - return gui_internal_label_font_new(this, text, 0); +gui_internal_label_new(struct gui_priv *this, const char *text) { + return gui_internal_label_font_new(this, text, 0); } struct widget * -gui_internal_label_new_abbrev(struct gui_priv *this, const char *text, int maxwidth) -{ - struct widget *ret=NULL; - char *tmp=g_malloc(strlen(text)+3); - const char *p; - p=text+strlen(text); - while ((p=g_utf8_find_prev_char(text, p)) >= text) { - int i=p-text; - strcpy(tmp, text); - strcpy(tmp+i,".."); - ret=gui_internal_label_new(this, tmp); - if (ret->w < maxwidth) - break; - gui_internal_widget_destroy(this, ret); - ret=NULL; - } - if(!ret) - ret=gui_internal_label_new(this, ""); - g_free(tmp); - return ret; +gui_internal_label_new_abbrev(struct gui_priv *this, const char *text, int maxwidth) { + struct widget *ret=NULL; + char *tmp=g_malloc(strlen(text)+3); + const char *p; + p=text+strlen(text); + while ((p=g_utf8_find_prev_char(text, p)) >= text) { + int i=p-text; + strcpy(tmp, text); + strcpy(tmp+i,".."); + ret=gui_internal_label_new(this, tmp); + if (ret->w < maxwidth) + break; + gui_internal_widget_destroy(this, ret); + ret=NULL; + } + if(!ret) + ret=gui_internal_label_new(this, ""); + g_free(tmp); + return ret; } struct widget * -gui_internal_image_new(struct gui_priv *this, struct graphics_image *image) -{ - struct widget *widget=g_new0(struct widget, 1); - widget->type=widget_image; - widget->img=image; - if (image) { - widget->w=image->width; - widget->h=image->height; - } - return widget; +gui_internal_image_new(struct gui_priv *this, struct graphics_image *image) { + struct widget *widget=g_new0(struct widget, 1); + widget->type=widget_image; + widget->img=image; + if (image) { + widget->w=image->width; + widget->h=image->height; + } + return widget; } -static void -gui_internal_image_render(struct gui_priv *this, struct widget *w) -{ - struct point pnt; - - gui_internal_background_render(this, w); - if (w->img) { - pnt=w->p; - pnt.x+=w->w/2-w->img->hot.x; - pnt.y+=w->h/2-w->img->hot.y; - graphics_draw_image(this->gra, this->foreground, &pnt, w->img); - } +/** + * @brief Renders an image or icon, preparing it for drawing on the display + * + * @param this The internal GUI instance + * @param w The widget to render + */ +static void gui_internal_image_render(struct gui_priv *this, struct widget *w) { + struct point pnt; + + gui_internal_background_render(this, w); + if (w->img) { + pnt=w->p; + pnt.x+=w->w/2-w->img->hot.x; + pnt.y+=w->h/2-w->img->hot.y; + graphics_draw_image(this->gra, this->foreground, &pnt, w->img); + } } /** - * @brief Renders a label. + * @brief Renders a label, preparing it for drawing on the display * * @param this The internal GUI instance * @param w The widget to render */ -static void -gui_internal_label_render(struct gui_priv *this, struct widget *w) -{ - struct point pnt=w->p; - gui_internal_background_render(this, w); - if (w->state & STATE_EDIT) - graphics_draw_rectangle(this->gra, this->highlight_background, &pnt, w->w, w->h); - if (w->text) { - char *text; - char *startext=(char*)g_alloca(strlen(w->text)+1); - text=w->text; - if (w->flags2 & 1) { - int i; - for (i = 0 ; i < strlen(text); i++) - startext[i]='*'; - startext[i]='\0'; - text=startext; - } - if (w->flags & gravity_right) { - pnt.y+=w->h-this->spacing; - pnt.x+=w->w-w->textw-this->spacing; - graphics_draw_text(this->gra, w->foreground, w->text_background, this->fonts[w->font_idx], text, &pnt, 0x10000, 0x0); - } else { - pnt.y+=w->h-this->spacing; - graphics_draw_text(this->gra, w->foreground, w->text_background, this->fonts[w->font_idx], text, &pnt, 0x10000, 0x0); - } - } +static void gui_internal_label_render(struct gui_priv *this, struct widget *w) { + struct point pnt=w->p; + gui_internal_background_render(this, w); + if (w->state & STATE_EDIT) + graphics_draw_rectangle(this->gra, this->highlight_background, &pnt, w->w, w->h); + if (w->text) { + char *text; + char *startext=(char*)g_alloca(strlen(w->text)+1); + text=w->text; + if (w->flags2 & 1) { + int i; + for (i = 0 ; i < strlen(text); i++) + startext[i]='*'; + startext[i]='\0'; + text=startext; + } + if (w->flags & gravity_right) { + pnt.y+=w->h-this->spacing; + pnt.x+=w->w-w->textw-this->spacing; + graphics_draw_text(this->gra, w->foreground, w->text_background, this->fonts[w->font_idx], text, &pnt, 0x10000, 0x0); + } else { + pnt.y+=w->h-this->spacing; + graphics_draw_text(this->gra, w->foreground, w->text_background, this->fonts[w->font_idx], text, &pnt, 0x10000, 0x0); + } + } } /** @@ -155,487 +208,544 @@ gui_internal_label_render(struct gui_priv *this, struct widget *w) * @param flags */ struct widget * -gui_internal_text_font_new(struct gui_priv *this, const char *text, int font, enum flags flags) -{ - char *s=g_strdup(text),*s2,*tok; - struct widget *ret=gui_internal_box_new(this, flags); - s2=s; - while ((tok=strtok(s2,"\n"))) { - gui_internal_widget_append(ret, gui_internal_label_font_new(this, tok, font)); - s2=NULL; - } - gui_internal_widget_pack(this,ret); - g_free(s); - return ret; +gui_internal_text_font_new(struct gui_priv *this, const char *text, int font, enum flags flags) { + char *s=g_strdup(text),*s2,*tok; + struct widget *ret=gui_internal_box_new(this, flags); + s2=s; + while ((tok=strtok(s2,"\n"))) { + gui_internal_widget_append(ret, gui_internal_label_font_new(this, tok, font)); + s2=NULL; + } + gui_internal_widget_pack(this,ret); + g_free(s); + return ret; } struct widget * -gui_internal_text_new(struct gui_priv *this, const char *text, enum flags flags) -{ - return gui_internal_text_font_new(this, text, 0, flags); +gui_internal_text_new(struct gui_priv *this, const char *text, enum flags flags) { + return gui_internal_text_font_new(this, text, 0, flags); } struct widget * -gui_internal_button_font_new_with_callback(struct gui_priv *this, const char *text, int font, struct graphics_image *image, enum flags flags, void(*func)(struct gui_priv *priv, struct widget *widget, void *data), void *data) -{ - struct widget *ret=NULL; - ret=gui_internal_box_new(this, flags); - if (ret) { - if (image && !(flags & flags_swap)) - gui_internal_widget_append(ret, gui_internal_image_new(this, image)); - if (text) - gui_internal_widget_append(ret, gui_internal_text_font_new(this, text, font, gravity_center|orientation_vertical)); - if (image && (flags & flags_swap)) - gui_internal_widget_append(ret, gui_internal_image_new(this, image)); - ret->func=func; - ret->data=data; - if (func) { - ret->state |= STATE_SENSITIVE; - ret->speech=g_strdup(text); - } - } - return ret; +gui_internal_button_font_new_with_callback(struct gui_priv *this, const char *text, int font, + struct graphics_image *image, enum flags flags, void(*func)(struct gui_priv *priv, struct widget *widget, void *data), + void *data) { + struct widget *ret=NULL; + ret=gui_internal_box_new(this, flags); + if (ret) { + if (image && !(flags & flags_swap)) + gui_internal_widget_append(ret, gui_internal_image_new(this, image)); + if (text) + gui_internal_widget_append(ret, gui_internal_text_font_new(this, text, font, gravity_center|orientation_vertical)); + if (image && (flags & flags_swap)) + gui_internal_widget_append(ret, gui_internal_image_new(this, image)); + ret->func=func; + ret->data=data; + if (func) { + ret->state |= STATE_SENSITIVE; + ret->speech=g_strdup(text); + } + } + return ret; } struct widget * -gui_internal_button_new_with_callback(struct gui_priv *this, const char *text, struct graphics_image *image, enum flags flags, void(*func)(struct gui_priv *priv, struct widget *widget, void *data), void *data) -{ - return gui_internal_button_font_new_with_callback(this, text, 0, image, flags, func, data); +gui_internal_button_new_with_callback(struct gui_priv *this, const char *text, struct graphics_image *image, + enum flags flags, void(*func)(struct gui_priv *priv, struct widget *widget, void *data), void *data) { + return gui_internal_button_font_new_with_callback(this, text, 0, image, flags, func, data); } struct widget * -gui_internal_button_new(struct gui_priv *this, const char *text, struct graphics_image *image, enum flags flags) -{ - return gui_internal_button_new_with_callback(this, text, image, flags, NULL, NULL); +gui_internal_button_new(struct gui_priv *this, const char *text, struct graphics_image *image, enum flags flags) { + return gui_internal_button_new_with_callback(this, text, image, flags, NULL, NULL); } struct widget * -gui_internal_find_widget(struct widget *wi, struct point *p, int flags) -{ - struct widget *ret,*child; - GList *l=wi->children; - - if (p) { - if (wi->p.x > p->x ) - return NULL; - if (wi->p.y > p->y ) - return NULL; - if ( wi->p.x + wi->w < p->x) - return NULL; - if ( wi->p.y + wi->h < p->y) - return NULL; - } - if (wi->state & flags) - return wi; - while (l) { - child=l->data; - ret=gui_internal_find_widget(child, p, flags); - if (ret) { - return ret; - } - l=g_list_next(l); - } - return NULL; +gui_internal_find_widget(struct widget *wi, struct point *p, int flags) { + struct widget *ret,*child; + GList *l=wi->children; + + if (p) { + if (wi->p.x > p->x ) + return NULL; + if (wi->p.y > p->y ) + return NULL; + if ( wi->p.x + wi->w < p->x) + return NULL; + if ( wi->p.y + wi->h < p->y) + return NULL; + } + if (wi->state & flags) + return wi; + while (l) { + child=l->data; + ret=gui_internal_find_widget(child, p, flags); + if (ret) { + return ret; + } + l=g_list_next(l); + } + return NULL; } -void -gui_internal_highlight_do(struct gui_priv *this, struct widget *found) -{ - if (found == this->highlighted) - return; - - graphics_draw_mode(this->gra, draw_mode_begin); - if (this->highlighted) { - this->highlighted->state &= ~STATE_HIGHLIGHTED; - if (this->root.children && this->highlighted_menu == g_list_last(this->root.children)->data) - gui_internal_widget_render(this, this->highlighted); - this->highlighted=NULL; - this->highlighted_menu=NULL; - } - if (found) { - this->highlighted=found; - this->highlighted_menu=g_list_last(this->root.children)->data; - this->highlighted->state |= STATE_HIGHLIGHTED; - gui_internal_widget_render(this, this->highlighted); - dbg(lvl_debug,"%d,%d %dx%d\n", found->p.x, found->p.y, found->w, found->h); - } - graphics_draw_mode(this->gra, draw_mode_end); +void gui_internal_highlight_do(struct gui_priv *this, struct widget *found) { + if (found == this->highlighted) + return; + + graphics_draw_mode(this->gra, draw_mode_begin); + if (this->highlighted) { + this->highlighted->state &= ~STATE_HIGHLIGHTED; + if (this->root.children && this->highlighted_menu == g_list_last(this->root.children)->data) + gui_internal_widget_render(this, this->highlighted); + this->highlighted=NULL; + this->highlighted_menu=NULL; + } + if (found) { + this->highlighted=found; + this->highlighted_menu=g_list_last(this->root.children)->data; + this->highlighted->state |= STATE_HIGHLIGHTED; + gui_internal_widget_render(this, this->highlighted); + dbg(lvl_debug,"%d,%d %dx%d", found->p.x, found->p.y, found->w, found->h); + } + graphics_draw_mode(this->gra, draw_mode_end); } //############################################################################################################## //# Description: //# Comment: //# Authors: Martin Schaller (04/2008) //############################################################################################################## -void -gui_internal_highlight(struct gui_priv *this) -{ - struct widget *menu,*found=NULL; - if (this->current.x > -1 && this->current.y > -1) { - menu=g_list_last(this->root.children)->data; - found=gui_internal_find_widget(menu, &this->current, STATE_SENSITIVE); - if (!found) { - found=gui_internal_find_widget(menu, &this->current, STATE_EDITABLE); - if (found) { - if (this->editable && this->editable != found) { - this->editable->state &= ~ STATE_EDIT; - gui_internal_widget_render(this, this->editable); - } - found->state |= STATE_EDIT; - gui_internal_widget_render(this, found); - this->editable=found; - found=NULL; - } - } - } - gui_internal_highlight_do(this, found); - this->motion_timeout_event=NULL; +void gui_internal_highlight(struct gui_priv *this) { + struct widget *menu,*found=NULL; + if (this->current.x > -1 && this->current.y > -1) { + menu=g_list_last(this->root.children)->data; + found=gui_internal_find_widget(menu, &this->current, STATE_SENSITIVE); + if (!found) { + found=gui_internal_find_widget(menu, &this->current, STATE_EDITABLE); + if (found) { + if (this->editable && this->editable != found) { + this->editable->state &= ~ STATE_EDIT; + gui_internal_widget_render(this, this->editable); + } + found->state |= STATE_EDIT; + gui_internal_widget_render(this, found); + this->editable=found; + found=NULL; + } + } + } + gui_internal_highlight_do(this, found); + this->motion_timeout_event=NULL; } struct widget * -gui_internal_box_new_with_label(struct gui_priv *this, enum flags flags, const char *label) -{ - struct widget *widget=g_new0(struct widget, 1); - - if (label) - widget->text=g_strdup(label); - widget->type=widget_box; - widget->flags=flags; - return widget; +gui_internal_box_new_with_label(struct gui_priv *this, enum flags flags, const char *label) { + struct widget *widget=g_new0(struct widget, 1); + + if (label) + widget->text=g_strdup(label); + widget->type=widget_box; + widget->flags=flags; + widget->on_resize=gui_internal_box_resize; + return widget; } struct widget * -gui_internal_box_new(struct gui_priv *this, enum flags flags) -{ - return gui_internal_box_new_with_label(this, flags, NULL); +gui_internal_box_new(struct gui_priv *this, enum flags flags) { + return gui_internal_box_new_with_label(this, flags, NULL); } +/** + * @brief Renders a box widget, preparing it for drawing on the display + * + * @param this The internal GUI instance + * @param w The box widget to render + */ +static void gui_internal_box_render(struct gui_priv *this, struct widget *w) { + struct widget *wc; + GList *l; -static void gui_internal_box_render(struct gui_priv *this, struct widget *w) -{ - struct widget *wc; - GList *l; - - gui_internal_background_render(this, w); - if (w->foreground && w->border) { - struct point pnt[5]; - pnt[0]=w->p; - pnt[1].x=pnt[0].x+w->w; - pnt[1].y=pnt[0].y; - pnt[2].x=pnt[0].x+w->w; - pnt[2].y=pnt[0].y+w->h; - pnt[3].x=pnt[0].x; - pnt[3].y=pnt[0].y+w->h; - pnt[4]=pnt[0]; - graphics_gc_set_linewidth(w->foreground, w->border ? w->border : 1); - graphics_draw_lines(this->gra, w->foreground, pnt, 5); - graphics_gc_set_linewidth(w->foreground, 1); - } - - l=w->children; - while (l) { - wc=l->data; - gui_internal_widget_render(this, wc); - l=g_list_next(l); - } - if (w->scroll_buttons) - gui_internal_widget_render(this, w->scroll_buttons->button_box); -} + int visual_debug = 0; +#if defined(GUI_INTERNAL_VISUAL_DBG) + static struct graphics_gc *debug_gc=NULL; + static struct color gui_box_debug_color= {0xffff,0x0400,0x0400,0xffff}; /* Red */ + visual_debug = (debug_level_get("gui_internal_visual_layout") >= lvl_debug); +#endif + + if (visual_debug) + dbg(lvl_debug, "Internal layout visual debugging is enabled"); + +#if defined(GUI_INTERNAL_VISUAL_DBG) + if (visual_debug && !debug_gc) { + debug_gc = graphics_gc_new(this->gra); + graphics_gc_set_foreground(debug_gc, &gui_box_debug_color); + graphics_gc_set_linewidth(debug_gc, 1); + } +#endif + + gui_internal_background_render(this, w); + if ((w->foreground && w->border) || visual_debug) { + struct point pnt[5]; + pnt[0]=w->p; + pnt[1].x=pnt[0].x+w->w; + pnt[1].y=pnt[0].y; + pnt[2].x=pnt[0].x+w->w; + pnt[2].y=pnt[0].y+w->h; + pnt[3].x=pnt[0].x; + pnt[3].y=pnt[0].y+w->h; + pnt[4]=pnt[0]; + if (!visual_debug) { + graphics_gc_set_linewidth(w->foreground, w->border ? w->border : 1); + graphics_draw_lines(this->gra, w->foreground, pnt, 5); + graphics_gc_set_linewidth(w->foreground, 1); + } +#if defined(GUI_INTERNAL_VISUAL_DBG) + else + graphics_draw_lines(this->gra, debug_gc, pnt, 5); /* Force highlighting box borders in debug more */ +#endif + } + + l=w->children; + while (l) { + wc=l->data; + gui_internal_widget_render(this, wc); + l=g_list_next(l); + } + if (w->scroll_buttons) + gui_internal_widget_render(this, w->scroll_buttons->button_box); +} /** - * @brief Computes the size and location for the widget. + * @brief Computes the size and location for a box widget * * @param this The internal GUI instance - * @param w The widget to render + * @param w The widget to pack */ -static void gui_internal_box_pack(struct gui_priv *this, struct widget *w) -{ - struct widget *wc; - int x0,x=0,y=0,width=0,height=0,owidth=0,oheight=0,expand=0,expandd=1,count=0,rows=0,cols=w->cols ? w->cols : 0; - int hb=w->scroll_buttons?w->scroll_buttons->button_box->h:0; - GList *l; - int orientation=w->flags & 0xffff0000; - - if (!cols) - cols=this->cols; - if (!cols) { - if ( this->root.w > this->root.h ) - cols=3; - else - cols=2; - width=0; - height=0; - } - - - /* - * count the number of children - */ - l=w->children; - while (l) { - count++; - l=g_list_next(l); - } - if (orientation == orientation_horizontal_vertical && count <= cols) - orientation=orientation_horizontal; - switch (orientation) { - case orientation_horizontal: - /* - * For horizontal orientation: - * pack each child and find the largest height and - * compute the total width. x spacing (spx) is considered - * - * If any children want to be expanded - * we keep track of this - */ - l=w->children; - while (l) { - wc=l->data; - gui_internal_widget_pack(this, wc); - if (height < wc->h) - height=wc->h; - width+=wc->w; - if (wc->flags & flags_expand) - expand+=wc->w ? wc->w : 1; - l=g_list_next(l); - if (l) - width+=w->spx; - } - owidth=width; - if (expand && w->w) { - expandd=w->w-width+expand; - owidth=w->w; - } else - expandd=expand=1; - break; - case orientation_vertical: - /* - * For vertical layouts: - * We pack each child and compute the largest width and - * the total height. y spacing (spy) is considered - * - * If the expand flag is set then teh expansion amount - * is computed. - */ - l=w->children; - while (l) { - wc=l->data; - gui_internal_widget_pack(this, wc); - if (width < wc->w) - width=wc->w; - height+=wc->h; - if (wc->flags & flags_expand) - expand+=wc->h ? wc->h : 1; - l=g_list_next(l); - if (l) - height+=w->spy; - } - oheight=height; - if (expand && w->h) { - expandd=w->h-hb-height+expand; - oheight=w->h-hb; - } else - expandd=expand=1; - break; - case orientation_horizontal_vertical: - /* - * For horizontal_vertical orientation - * pack the children. - * Compute the largest height and largest width. - * Layout the widgets based on having the - * number of columns specified by (cols) - */ - count=0; - l=w->children; - while (l) { - wc=l->data; - gui_internal_widget_pack(this, wc); - if (height < wc->h) - height=wc->h; - if (width < wc->w) - width=wc->w; - l=g_list_next(l); - count++; - } - if (count < cols) - cols=count; - rows=(count+cols-1)/cols; - width*=cols; - height*=rows; - width+=w->spx*(cols-1); - height+=w->spy*(rows-1); - owidth=width; - oheight=height; - expandd=expand=1; - break; - default: - /* - * No orientation was specified. - * width and height are both 0. - * The width & height of this widget - * will be used. - */ - if(!w->w && !w->h) - dbg(lvl_error,"Warning width and height of a widget are 0"); - break; - } - if (! w->w && ! w->h) { - w->w=w->bl+w->br+width; - w->h=w->bt+w->bb+height+hb; - w->packed=1; - } +void gui_internal_box_pack(struct gui_priv *this, struct widget *w) { + struct widget *wc; + int x0,x=0,y=0,width=0,height=0,owidth=0,oheight=0,expand=0,expandd=1,count=0,rows=0,cols=w->cols ? w->cols : 0; + int hb=w->scroll_buttons?w->scroll_buttons->button_box->h:0; + GList *l; + int orientation=w->flags & 0xffff0000; + + if (!cols) + cols=this->cols; + if (!cols) { + if ( this->root.w > this->root.h ) + cols=3; + else + cols=2; + width=0; + height=0; + } + + + /* + * count the number of children + */ + l=w->children; + while (l) { + count++; + l=g_list_next(l); + } + if (orientation == orientation_horizontal_vertical && count <= cols) + orientation=orientation_horizontal; + switch (orientation) { + case orientation_horizontal: + /* + * For horizontal orientation: + * pack each child and find the largest height and + * compute the total width. x spacing (spx) is considered + * + * If any children want to be expanded + * we keep track of this + */ + l=w->children; + while (l) { + wc=l->data; + gui_internal_widget_pack(this, wc); + if (height < wc->h) + height=wc->h; + width+=wc->w; + if (wc->flags & flags_expand) + expand+=wc->w ? wc->w : 1; + l=g_list_next(l); + if (l) + width+=w->spx; + } + owidth=width; + if (expand && w->w) { + expandd=w->w-width+expand; + owidth=w->w; + } else + expandd=expand=1; + break; + case orientation_vertical: + /* + * For vertical layouts: + * We pack each child and compute the largest width and + * the total height. y spacing (spy) is considered + * + * If the expand flag is set then teh expansion amount + * is computed. + */ + l=w->children; + while (l) { + wc=l->data; + gui_internal_widget_pack(this, wc); + if (width < wc->w) + width=wc->w; + height+=wc->h; + if (wc->flags & flags_expand) + expand+=wc->h ? wc->h : 1; + l=g_list_next(l); + if (l) + height+=w->spy; + } + oheight=height; + if (expand && w->h) { + expandd=w->h-hb-height+expand; + oheight=w->h-hb; + } else + expandd=expand=1; + break; + case orientation_horizontal_vertical: + /* + * For horizontal_vertical orientation + * pack the children. + * Compute the largest height and largest width. + * Layout the widgets based on having the + * number of columns specified by (cols) + */ + count=0; + l=w->children; + while (l) { + wc=l->data; + gui_internal_widget_pack(this, wc); + if (height < wc->h) + height=wc->h; + if (width < wc->w) + width=wc->w; + l=g_list_next(l); + count++; + } + if (count < cols) + cols=count; + rows=(count+cols-1)/cols; + width*=cols; + height*=rows; + width+=w->spx*(cols-1); + height+=w->spy*(rows-1); + owidth=width; + oheight=height; + expandd=expand=1; + break; + default: + /* + * No orientation was specified. + * width and height are both 0. + * The width & height of this widget + * will be used. + */ + if(!w->w && !w->h) + dbg(lvl_error,"Warning width and height of a widget are 0"); + break; + } + if (! w->w && ! w->h) { + w->w=w->bl+w->br+width; + w->h=w->bt+w->bb+height+hb; + w->packed=1; + } #if 0 - if (expand < 100) - expand=100; + if (expand < 100) + expand=100; #endif - /* - * At this stage the width and height of this - * widget has been computed. - * We now make a second pass assigning heights, - * widths and coordinates to each child widget. - */ - - if (w->flags & gravity_left) - x=w->p.x+w->bl; - if (w->flags & gravity_xcenter) - x=w->p.x+w->w/2-owidth/2; - if (w->flags & gravity_right) - x=w->p.x+w->w-w->br-owidth; - if (w->flags & gravity_top) - y=w->p.y+w->bt; - if (w->flags & gravity_ycenter) - y=w->p.y+(w->h-hb)/2-oheight/2; - if (w->flags & gravity_bottom) - y=w->p.y+(w->h-hb)-w->bb-oheight; - l=w->children; - switch (orientation) { - case orientation_horizontal: - l=w->children; - while (l) { - wc=l->data; - wc->p.x=x; - if (wc->flags & flags_fill) - wc->h=w->h-hb; - if (wc->flags & flags_expand) { - if (! wc->w) - wc->w=1; - wc->w=wc->w*expandd/expand; - } - if (w->flags & gravity_top) - wc->p.y=y; - if (w->flags & gravity_ycenter) - wc->p.y=y-wc->h/2; - if (w->flags & gravity_bottom) - wc->p.y=y-wc->h; - x+=wc->w+w->spx; - l=g_list_next(l); - } - break; - case orientation_vertical: - l=w->children; - while (l) { - wc=l->data; - wc->p.y=y; - if (wc->flags & flags_fill) - wc->w=w->w; - if (wc->flags & flags_expand) { - if (! wc->h) - wc->h=1; - wc->h=wc->h*expandd/expand; - } - if (w->flags & gravity_left) - wc->p.x=x; - if (w->flags & gravity_xcenter) - wc->p.x=x-wc->w/2; - if (w->flags & gravity_right) - wc->p.x=x-wc->w; - y+=wc->h+w->spy; - l=g_list_next(l); - } - break; - case orientation_horizontal_vertical: - l=w->children; - x0=x; - count=0; - width/=cols; - height/=rows; - while (l) { - wc=l->data; - wc->p.x=x; - wc->p.y=y; - if (wc->flags & flags_fill) { - wc->w=width; - wc->h=height; - } - if (w->flags & gravity_left) - wc->p.x=x; - if (w->flags & gravity_xcenter) - wc->p.x=x+(width-wc->w)/2; - if (w->flags & gravity_right) - wc->p.x=x+width-wc->w; - if (w->flags & gravity_top) - wc->p.y=y; - if (w->flags & gravity_ycenter) - wc->p.y=y+(height-wc->h)/2; - if (w->flags & gravity_bottom) - wc->p.y=y-height-wc->h; - x+=width; - if (++count == cols) { - count=0; - x=x0; - y+=height; - } - l=g_list_next(l); - } - break; - default: - break; - } - if ((w->flags & flags_scrolly) && y > w->h+w->p.y && !w->scroll_buttons) { - w->scroll_buttons=g_new0(struct scroll_buttons, 1); - gui_internal_scroll_buttons_init(this, w, w->scroll_buttons); - w->scroll_buttons->button_box->w=w->w; - w->scroll_buttons->button_box->p.x=w->p.x; - w->scroll_buttons->button_box->p.y=w->p.y+w->h-w->scroll_buttons->button_box->h; - gui_internal_widget_pack(this, w->scroll_buttons->button_box); - dbg(lvl_debug,"needs buttons %d vs %d\n",y,w->h); - gui_internal_box_pack(this, w); - return; - } - /* - * Call pack again on each child, - * the child has now had its size and coordinates - * set so they can repack their children. - */ - l=w->children; - while (l) { - wc=l->data; - gui_internal_widget_pack(this, wc); - l=g_list_next(l); - } + /* + * At this stage the width and height of this + * widget has been computed. + * We now make a second pass assigning heights, + * widths and coordinates to each child widget. + */ + + if (w->flags & gravity_left) + x=w->p.x+w->bl; + if (w->flags & gravity_xcenter) + x=w->p.x+w->w/2-owidth/2; + if (w->flags & gravity_right) + x=w->p.x+w->w-w->br-owidth; + if (w->flags & gravity_top) + y=w->p.y+w->bt; + if (w->flags & gravity_ycenter) + y=w->p.y+(w->h-hb)/2-oheight/2; + if (w->flags & gravity_bottom) + y=w->p.y+(w->h-hb)-w->bb-oheight; + l=w->children; + switch (orientation) { + case orientation_horizontal: + l=w->children; + while (l) { + wc=l->data; + wc->p.x=x; + if (wc->flags & flags_fill) + wc->h=w->h-hb; + if (wc->flags & flags_expand) { + if (! wc->w) + wc->w=1; + wc->w=wc->w*expandd/expand; + } + if (w->flags & gravity_top) + wc->p.y=y; + if (w->flags & gravity_ycenter) + wc->p.y=y-wc->h/2; + if (w->flags & gravity_bottom) + wc->p.y=y-wc->h; + x+=wc->w+w->spx; + l=g_list_next(l); + } + break; + case orientation_vertical: + l=w->children; + while (l) { + wc=l->data; + wc->p.y=y; + if (wc->flags & flags_fill) + wc->w=w->w; + if (wc->flags & flags_expand) { + if (! wc->h) + wc->h=1; + wc->h=wc->h*expandd/expand; + } + if (w->flags & gravity_left) + wc->p.x=x; + if (w->flags & gravity_xcenter) + wc->p.x=x-wc->w/2; + if (w->flags & gravity_right) + wc->p.x=x-wc->w; + y+=wc->h+w->spy; + l=g_list_next(l); + } + break; + case orientation_horizontal_vertical: + l=w->children; + x0=x; + count=0; + width/=cols; + height/=rows; + while (l) { + wc=l->data; + wc->p.x=x; + wc->p.y=y; + if (wc->flags & flags_fill) { + wc->w=width; + wc->h=height; + } + if (w->flags & gravity_left) + wc->p.x=x; + if (w->flags & gravity_xcenter) + wc->p.x=x+(width-wc->w)/2; + if (w->flags & gravity_right) + wc->p.x=x+width-wc->w; + if (w->flags & gravity_top) + wc->p.y=y; + if (w->flags & gravity_ycenter) + wc->p.y=y+(height-wc->h)/2; + if (w->flags & gravity_bottom) + wc->p.y=y-height-wc->h; + x+=width; + if (++count == cols) { + count=0; + x=x0; + y+=height; + } + l=g_list_next(l); + } + break; + default: + break; + } + if ((w->flags & flags_scrolly) && y > w->h+w->p.y && !w->scroll_buttons) { + w->scroll_buttons=g_new0(struct scroll_buttons, 1); + gui_internal_scroll_buttons_init(this, w, w->scroll_buttons); + w->scroll_buttons->button_box->w=w->w; + w->scroll_buttons->button_box->p.x=w->p.x; + w->scroll_buttons->button_box->p.y=w->p.y+w->h-w->scroll_buttons->button_box->h; + gui_internal_widget_pack(this, w->scroll_buttons->button_box); + dbg(lvl_debug,"needs buttons %d vs %d",y,w->h); + gui_internal_box_pack(this, w); + return; + } + /* + * Call pack again on each child, + * the child has now had its size and coordinates + * set so they can repack their children. + */ + l=w->children; + while (l) { + wc=l->data; + gui_internal_widget_pack(this, wc); + l=g_list_next(l); + } } -void -gui_internal_widget_reset_pack(struct gui_priv *this, struct widget *w) -{ - struct widget *wc; - GList *l; - - l=w->children; - while (l) { - wc=l->data; - gui_internal_widget_reset_pack(this, wc); - l=g_list_next(l); - } - if (w->packed) { - w->w=0; - w->h=0; - } +/** + * @brief Resize a box widget. + * + * @param this The internal GUI instance + * @param w The widget to resize + * @param wnew The new width of the widget + * @param hnew THe new height of the widget + */ +void gui_internal_box_resize(struct gui_priv *this, struct widget *w, void *data, int wnew, int hnew) { + GList *l; + struct widget *wb; + + w->w = wnew; + w->h = hnew; + + l=w->children; + while (l) { + wb=l->data; + if (wb->on_resize) { + int orientation=w->flags & 0xffff0000; + switch(orientation) { + case orientation_horizontal: + case orientation_vertical: + case orientation_horizontal_vertical: + wb->h = 0; + wb->w = 0; + gui_internal_widget_pack(this, wb); + break; + default: + wb->w = w->w; + wb->h = w->h; + } + wb->on_resize(this, wb, NULL, wb->w, wb->h); + } + l=g_list_next(l); + } + + /* Note: this widget and its children have been resized, a call to gui_internal_box_render() needs to be done by the caller */ +} + +void gui_internal_widget_reset_pack(struct gui_priv *this, struct widget *w) { + struct widget *wc; + GList *l; + + l=w->children; + while (l) { + wc=l->data; + gui_internal_widget_reset_pack(this, wc); + l=g_list_next(l); + } + if (w->packed) { + w->w=0; + w->h=0; + } } /** @@ -644,15 +754,13 @@ gui_internal_widget_reset_pack(struct gui_priv *this, struct widget *w) * @param parent The parent widget * @param child The child widget */ -void -gui_internal_widget_append(struct widget *parent, struct widget *child) -{ - if (! child) - return; - if (! child->background) - child->background=parent->background; - parent->children=g_list_append(parent->children, child); - child->parent=parent; +void gui_internal_widget_append(struct widget *parent, struct widget *child) { + if (! child) + return; + if (! child->background) + child->background=parent->background; + parent->children=g_list_append(parent->children, child); + child->parent=parent; } /** @@ -661,13 +769,11 @@ gui_internal_widget_append(struct widget *parent, struct widget *child) * @param parent The parent widget * @param child The child widget */ -void -gui_internal_widget_prepend(struct widget *parent, struct widget *child) -{ - if (! child->background) - child->background=parent->background; - parent->children=g_list_prepend(parent->children, child); - child->parent=parent; +void gui_internal_widget_prepend(struct widget *parent, struct widget *child) { + if (! child->background) + child->background=parent->background; + parent->children=g_list_prepend(parent->children, child); + child->parent=parent; } /** @@ -679,14 +785,12 @@ gui_internal_widget_prepend(struct widget *parent, struct widget *child) * @param child The child widget * @param func The comparison function */ -void -gui_internal_widget_insert_sorted(struct widget *parent, struct widget *child, GCompareFunc func) -{ - if (! child->background) - child->background=parent->background; - - parent->children=g_list_insert_sorted(parent->children, child, func); - child->parent=parent; +void gui_internal_widget_insert_sorted(struct widget *parent, struct widget *child, GCompareFunc func) { + if (! child->background) + child->background=parent->background; + + parent->children=g_list_insert_sorted(parent->children, child, func); + child->parent=parent; } @@ -698,20 +802,18 @@ gui_internal_widget_insert_sorted(struct widget *parent, struct widget *child, G * @param this The internal GUI instance * @param w The widget whose children are to be destroyed */ -void -gui_internal_widget_children_destroy(struct gui_priv *this, struct widget *w) -{ - GList *l; - struct widget *wc; - - l=w->children; - while (l) { - wc=l->data; - gui_internal_widget_destroy(this, wc); - l=g_list_next(l); - } - g_list_free(w->children); - w->children=NULL; +void gui_internal_widget_children_destroy(struct gui_priv *this, struct widget *w) { + GList *l; + struct widget *wc; + + l=w->children; + while (l) { + wc=l->data; + gui_internal_widget_destroy(this, wc); + l=g_list_next(l); + } + g_list_free(w->children); + w->children=NULL; } @@ -724,113 +826,112 @@ gui_internal_widget_children_destroy(struct gui_priv *this, struct widget *w) * @param this The internal GUI instance * @param w The widget to destroy */ -void -gui_internal_widget_destroy(struct gui_priv *this, struct widget *w) -{ - gui_internal_widget_children_destroy(this, w); - g_free(w->command); - g_free(w->speech); - g_free(w->text); - if (w->img) - graphics_image_free(this->gra, w->img); - if (w->prefix) - g_free(w->prefix); - if (w->name) - g_free(w->name); - if (w->data_free) - w->data_free(w->data); - if (w->cb && w->remove_cb) - w->remove_cb(w->instance, w->cb); - if (w==this->highlighted) - this->highlighted=NULL; - if(w->wfree) - w->wfree(this,w); - else - g_free(w); +void gui_internal_widget_destroy(struct gui_priv *this, struct widget *w) { + gui_internal_widget_children_destroy(this, w); + g_free(w->command); + g_free(w->speech); + g_free(w->text); + if (w->img) + graphics_image_free(this->gra, w->img); + if (w->prefix) + g_free(w->prefix); + if (w->name) + g_free(w->name); + if (w->data_free) + w->data_free(w->data); + if (w->cb && w->remove_cb) + w->remove_cb(w->instance, w->cb); + if (w==this->highlighted) + this->highlighted=NULL; + if(w->wfree) + w->wfree(this,w); + else + g_free(w); } -void -gui_internal_widget_render(struct gui_priv *this, struct widget *w) -{ - if(w->p.x > this->root.w || w->p.y > this->root.h || w->state & STATE_INVISIBLE) - return; - - switch (w->type) { - case widget_box: - gui_internal_box_render(this, w); - break; - case widget_label: - gui_internal_label_render(this, w); - break; - case widget_image: - gui_internal_image_render(this, w); - break; - case widget_table: - gui_internal_table_render(this,w); - break; - default: - break; - } +/** + * @brief Renders widgets, preparing it for drawing on the display + * + * The appropriate render function will be called, depending on the type of widget + * + * @param this The internal GUI instance + * @param w The widget to render + */ +void gui_internal_widget_render(struct gui_priv *this, struct widget *w) { + if(w->p.x > this->root.w || w->p.y > this->root.h || w->state & STATE_INVISIBLE) + return; + + switch (w->type) { + case widget_box: + gui_internal_box_render(this, w); + break; + case widget_label: + gui_internal_label_render(this, w); + break; + case widget_image: + gui_internal_image_render(this, w); + break; + case widget_table: + gui_internal_table_render(this,w); + break; + default: + break; + } } -void -gui_internal_widget_pack(struct gui_priv *this, struct widget *w) -{ - switch (w->type) { - case widget_box: - gui_internal_box_pack(this, w); - break; - case widget_table: - gui_internal_table_pack(this,w); - default: - break; - } +void gui_internal_widget_pack(struct gui_priv *this, struct widget *w) { + switch (w->type) { + case widget_box: + gui_internal_box_pack(this, w); + break; + case widget_table: + gui_internal_table_pack(this,w); + default: + break; + } } struct widget * -gui_internal_button_label(struct gui_priv *this, const char *label, int mode) -{ - struct widget *wl,*wlb; - struct widget *wb=gui_internal_menu_data(this)->button_bar; - wlb=gui_internal_box_new(this, gravity_right_center|orientation_vertical); - wl=gui_internal_label_new(this, label); - wlb->border=1; - wlb->foreground=this->text_foreground; - wlb->bl=20; - wlb->br=20; - wlb->bb=6; - wlb->bt=6; - gui_internal_widget_append(wlb, wl); - if (mode == 1) - gui_internal_widget_prepend(wb, wlb); - if (mode == -1) - gui_internal_widget_append(wb, wlb); - - return wlb; +gui_internal_button_label(struct gui_priv *this, const char *label, int mode) { + struct widget *wl,*wlb; + struct widget *wb=gui_internal_menu_data(this)->button_bar; + wlb=gui_internal_box_new(this, gravity_right_center|orientation_vertical); + wl=gui_internal_label_new(this, label); + wlb->border=1; + wlb->foreground=this->text_foreground; + wlb->bl=20; + wlb->br=20; + wlb->bb=6; + wlb->bt=6; + gui_internal_widget_append(wlb, wl); + if (mode == 1) + gui_internal_widget_prepend(wb, wlb); + if (mode == -1) + gui_internal_widget_append(wb, wlb); + + return wlb; } -static void -gui_internal_scroll_buttons_init(struct gui_priv *this, struct widget *widget, struct scroll_buttons *sb) -{ - sb->next_button = gui_internal_button_new_with_callback(this, _("Next"), image_new_xs(this, "gui_arrow_right"), - gravity_center|orientation_horizontal|flags_swap, gui_internal_table_button_next, widget); - sb->prev_button = gui_internal_button_new_with_callback(this, _("Prev"), image_new_xs(this, "gui_arrow_left"), - gravity_center|orientation_horizontal, gui_internal_table_button_prev, widget); - - sb->button_box=gui_internal_box_new(this, gravity_center|orientation_horizontal); - sb->button_box->background=this->background; - if(this->hide_keys){ - sb->prev_button->state |= STATE_INVISIBLE; - sb->next_button->state |= STATE_INVISIBLE; - } - sb->prev_button->state &= ~STATE_SENSITIVE; - sb->next_button->state &= ~STATE_SENSITIVE; - gui_internal_widget_append(sb->button_box, sb->prev_button); - gui_internal_widget_append(sb->button_box, sb->next_button); - - sb->button_box->bl=this->spacing; - gui_internal_widget_pack(this,sb->button_box); +static void gui_internal_scroll_buttons_init(struct gui_priv *this, struct widget *widget, struct scroll_buttons *sb) { + sb->next_button = gui_internal_button_new_with_callback(this, _("Next"), image_new_xs(this, "gui_arrow_right"), + gravity_center|orientation_horizontal|flags_swap, gui_internal_table_button_next, widget); + sb->prev_button = gui_internal_button_new_with_callback(this, _("Prev"), image_new_xs(this, "gui_arrow_left"), + gravity_center|orientation_horizontal, gui_internal_table_button_prev, widget); + + sb->button_box=gui_internal_box_new(this, gravity_center|orientation_horizontal); + sb->button_box->background=this->background; + if(this->hide_keys) { + sb->prev_button->state |= STATE_INVISIBLE; + sb->next_button->state |= STATE_INVISIBLE; + } + sb->prev_button->state &= ~STATE_SENSITIVE; + sb->next_button->state &= ~STATE_SENSITIVE; + gui_internal_widget_append(sb->button_box, sb->prev_button); + gui_internal_widget_append(sb->button_box, sb->next_button); + + sb->button_box->bl=this->spacing; + gui_internal_widget_pack(this,sb->button_box); } /** @@ -843,29 +944,28 @@ gui_internal_scroll_buttons_init(struct gui_priv *this, struct widget *widget, s * @param flags widget sizing flags. * @return The newly created widget */ -struct widget * gui_internal_widget_table_new(struct gui_priv * this, enum flags flags, int buttons) -{ - struct widget * widget = g_new0(struct widget,1); - struct table_data * data = NULL; - widget->type=widget_table; - widget->flags=flags; - widget->state=STATE_SCROLLABLE; - widget->data=g_new0(struct table_data,1); - widget->data_free=gui_internal_table_data_free; - - // We have to set background here explicitly - // because it will be used by inner elements created later in this - // function (navigation buttons). Else that elements won't have - // any background. - widget->background=this->background; - data = (struct table_data*)widget->data; - - if (buttons) { - gui_internal_scroll_buttons_init(this, widget, &data->scroll_buttons); - gui_internal_widget_append(widget, data->scroll_buttons.button_box); - } - - return widget; +struct widget * gui_internal_widget_table_new(struct gui_priv * this, enum flags flags, int buttons) { + struct widget * widget = g_new0(struct widget,1); + struct table_data * data = NULL; + widget->type=widget_table; + widget->flags=flags; + widget->state=STATE_SCROLLABLE; + widget->data=g_new0(struct table_data,1); + widget->data_free=gui_internal_table_data_free; + + // We have to set background here explicitly + // because it will be used by inner elements created later in this + // function (navigation buttons). Else that elements won't have + // any background. + widget->background=this->background; + data = (struct table_data*)widget->data; + + if (buttons) { + gui_internal_scroll_buttons_init(this, widget, &data->scroll_buttons); + gui_internal_widget_append(widget, data->scroll_buttons.button_box); + } + + return widget; } @@ -878,30 +978,27 @@ struct widget * gui_internal_widget_table_new(struct gui_priv * this, enum flags * @param this The internal GUI instance * @param table The table widget */ -void gui_internal_widget_table_clear(struct gui_priv * this,struct widget * table) -{ - GList * iter; - struct table_data * table_data = (struct table_data* ) table->data; - - iter = table->children; - while(iter ) { - if(iter->data != table_data->scroll_buttons.button_box) { - struct widget * child = (struct widget*)iter->data; - gui_internal_widget_destroy(this,child); - if(table->children == iter) { - table->children = g_list_remove(iter,iter->data); - iter=table->children; - } - else - iter = g_list_remove(iter,iter->data); - } - else { - iter = g_list_next(iter); - } - - } - table_data->top_row=NULL; - table_data->bottom_row=NULL; +void gui_internal_widget_table_clear(struct gui_priv * this,struct widget * table) { + GList * iter; + struct table_data * table_data = (struct table_data* ) table->data; + + iter = table->children; + while(iter ) { + if(iter->data != table_data->scroll_buttons.button_box) { + struct widget * child = (struct widget*)iter->data; + gui_internal_widget_destroy(this,child); + if(table->children == iter) { + table->children = g_list_remove(iter,iter->data); + iter=table->children; + } else + iter = g_list_remove(iter,iter->data); + } else { + iter = g_list_next(iter); + } + + } + table_data->top_row=NULL; + table_data->bottom_row=NULL; } /** @@ -911,14 +1008,12 @@ void gui_internal_widget_table_clear(struct gui_priv * this,struct widget * tabl * * @return GList pointer to the next row in the children list, or NULL if there are no any rows left. */ -GList * -gui_internal_widget_table_next_row(GList * row) -{ - while((row=g_list_next(row))!=NULL) { - if(row->data && ((struct widget *)(row->data))->type == widget_table_row) - break; - } - return row; +GList *gui_internal_widget_table_next_row(GList * row) { + while((row=g_list_next(row))!=NULL) { + if(row->data && ((struct widget *)(row->data))->type == widget_table_row) + break; + } + return row; } /** @@ -928,14 +1023,12 @@ gui_internal_widget_table_next_row(GList * row) * * @return GList pointer to the previous row in the children list, or NULL if there are no any rows left. */ -GList * -gui_internal_widget_table_prev_row(GList * row) -{ - while((row=g_list_previous(row))!=NULL) { - if(row->data && ((struct widget *)(row->data))->type == widget_table_row) - break; - } - return row; +GList *gui_internal_widget_table_prev_row(GList * row) { + while((row=g_list_previous(row))!=NULL) { + if(row->data && ((struct widget *)(row->data))->type == widget_table_row) + break; + } + return row; } /** @@ -945,16 +1038,14 @@ gui_internal_widget_table_prev_row(GList * row) * * @return GList pointer to the first row in the children list, or NULL if table is empty. */ -GList * -gui_internal_widget_table_first_row(GList * row) -{ - if(!row) - return NULL; +GList *gui_internal_widget_table_first_row(GList * row) { + if(!row) + return NULL; - if(row->data && ((struct widget *)(row->data))->type == widget_table_row) - return row; + if(row->data && ((struct widget *)(row->data))->type == widget_table_row) + return row; - return gui_internal_widget_table_next_row(row); + return gui_internal_widget_table_next_row(row); } /** @@ -962,14 +1053,12 @@ gui_internal_widget_table_first_row(GList * row) * * @return GList pointer to the top row in the children list, or NULL. */ -GList * -gui_internal_widget_table_top_row(struct gui_priv *this, struct widget * table) -{ - if(table && table->type==widget_table) { - struct table_data *d=table->data; - return gui_internal_widget_table_first_row(d->top_row); - } - return NULL; +GList *gui_internal_widget_table_top_row(struct gui_priv *this, struct widget * table) { + if(table && table->type==widget_table) { + struct table_data *d=table->data; + return gui_internal_widget_table_first_row(d->top_row); + } + return NULL; } /** @@ -977,19 +1066,17 @@ gui_internal_widget_table_top_row(struct gui_priv *this, struct widget * table) * * @return GList pointer to the top row in the children list of the table. */ -GList * -gui_internal_widget_table_set_top_row(struct gui_priv *this, struct widget * table, struct widget *row) -{ - if(table && table->type==widget_table) { - struct table_data *d=table->data; - d->top_row=table->children; - while(d->top_row && d->top_row->data!=row) - d->top_row=g_list_next(d->top_row); - if(!d->top_row) - d->top_row=gui_internal_widget_table_first_row(table->children); - return d->top_row; - } - return NULL; +GList *gui_internal_widget_table_set_top_row(struct gui_priv *this, struct widget * table, struct widget *row) { + if(table && table->type==widget_table) { + struct table_data *d=table->data; + d->top_row=table->children; + while(d->top_row && d->top_row->data!=row) + d->top_row=g_list_next(d->top_row); + if(!d->top_row) + d->top_row=gui_internal_widget_table_first_row(table->children); + return d->top_row; + } + return NULL; } @@ -1002,12 +1089,11 @@ gui_internal_widget_table_set_top_row(struct gui_priv *this, struct widget * tab * @return The new table_row widget. */ struct widget * -gui_internal_widget_table_row_new(struct gui_priv * this, enum flags flags) -{ - struct widget * widget = g_new0(struct widget,1); - widget->type=widget_table_row; - widget->flags=flags; - return widget; +gui_internal_widget_table_row_new(struct gui_priv * this, enum flags flags) { + struct widget * widget = g_new0(struct widget,1); + widget->type=widget_table_row; + widget->flags=flags; + return widget; } @@ -1024,91 +1110,81 @@ gui_internal_widget_table_row_new(struct gui_priv * this, enum flags flags) * * The caller is responsible for freeing the returned list. */ -static GList * -gui_internal_compute_table_dimensions(struct gui_priv * this,struct widget * w) -{ - - GList * column_desc = NULL; - GList * current_desc=NULL; - GList * cur_row = w->children; - struct widget * cur_row_widget=NULL; - GList * cur_column=NULL; - struct widget * cell_w=NULL; - struct table_column_desc * current_cell=NULL; - struct table_data * table_data=NULL; - int height=0; - int width=0; - int total_width=0; - int column_count=0; - - /* - * Scroll through the the table and - * 1. Compute the maximum width + height of each column across all rows. - */ - table_data = (struct table_data*) w->data; - for(cur_row=w->children; cur_row ; cur_row = g_list_next(cur_row) ) - { - cur_row_widget = (struct widget*) cur_row->data; - current_desc = column_desc; - if(cur_row_widget == table_data->scroll_buttons.button_box) - { - continue; - } - column_count=0; - for(cur_column = cur_row_widget->children; cur_column; - cur_column=g_list_next(cur_column)) - { - cell_w = (struct widget*) cur_column->data; - gui_internal_widget_pack(this,cell_w); - if(current_desc == 0) - { - current_cell = g_new0(struct table_column_desc,1); - column_desc = g_list_append(column_desc,current_cell); - current_desc = g_list_last(column_desc); - current_cell->height=cell_w->h; - current_cell->width=cell_w->w; - total_width+=cell_w->w; - - } - else - { - current_cell = current_desc->data; - height = cell_w->h; - width = cell_w->w; - if(current_cell->height < height ) - { - current_cell->height = height; - } - if(current_cell->width < width) - { - total_width += (width-current_cell->width); - current_cell->width = width; - - - - } - current_desc = g_list_next(current_desc); - } - column_count++; - - }/* column loop */ - - } /*row loop */ - - - /* - * If the width of all columns is less than the width off - * the table expand each cell proportionally. - * - */ - if(total_width+(this->spacing*column_count) < w->w ) { - for(current_desc=column_desc; current_desc; current_desc=g_list_next(current_desc)) { - current_cell = (struct table_column_desc*) current_desc->data; - current_cell->width= ( (current_cell->width+this->spacing)/(float)total_width) * w->w ; - } - } - - return column_desc; +static GList *gui_internal_compute_table_dimensions(struct gui_priv * this,struct widget * w) { + + GList * column_desc = NULL; + GList * current_desc=NULL; + GList * cur_row = w->children; + struct widget * cur_row_widget=NULL; + GList * cur_column=NULL; + struct widget * cell_w=NULL; + struct table_column_desc * current_cell=NULL; + struct table_data * table_data=NULL; + int height=0; + int width=0; + int total_width=0; + int column_count=0; + + /* + * Scroll through the the table and + * 1. Compute the maximum width + height of each column across all rows. + */ + table_data = (struct table_data*) w->data; + for(cur_row=w->children; cur_row ; cur_row = g_list_next(cur_row) ) { + cur_row_widget = (struct widget*) cur_row->data; + current_desc = column_desc; + if(cur_row_widget == table_data->scroll_buttons.button_box) { + continue; + } + column_count=0; + for(cur_column = cur_row_widget->children; cur_column; + cur_column=g_list_next(cur_column)) { + cell_w = (struct widget*) cur_column->data; + gui_internal_widget_pack(this,cell_w); + if(current_desc == 0) { + current_cell = g_new0(struct table_column_desc,1); + column_desc = g_list_append(column_desc,current_cell); + current_desc = g_list_last(column_desc); + current_cell->height=cell_w->h; + current_cell->width=cell_w->w; + total_width+=cell_w->w; + + } else { + current_cell = current_desc->data; + height = cell_w->h; + width = cell_w->w; + if(current_cell->height < height ) { + current_cell->height = height; + } + if(current_cell->width < width) { + total_width += (width-current_cell->width); + current_cell->width = width; + + + + } + current_desc = g_list_next(current_desc); + } + column_count++; + + }/* column loop */ + + } /*row loop */ + + + /* + * If the width of all columns is less than the width off + * the table expand each cell proportionally. + * + */ + if(total_width+(this->spacing*column_count) < w->w ) { + for(current_desc=column_desc; current_desc; current_desc=g_list_next(current_desc)) { + current_cell = (struct table_column_desc*) current_desc->data; + current_cell->width= ( (current_cell->width+this->spacing)/(float)total_width) * w->w ; + } + } + + return column_desc; } @@ -1121,69 +1197,59 @@ gui_internal_compute_table_dimensions(struct gui_priv * this,struct widget * w) * @param this The graphics context * @param w The widget to pack. */ -void -gui_internal_table_pack(struct gui_priv * this, struct widget * w) -{ - - int height=0; - int width=0; - int count=0; - GList * column_data = gui_internal_compute_table_dimensions(this,w); - GList * current=0; - struct table_column_desc * cell_desc=0; - struct table_data * table_data = (struct table_data*)w->data; - - for(current = column_data; current; current=g_list_next(current)) - { - if(table_data->scroll_buttons.button_box == current->data ) - { - continue; - } - cell_desc = (struct table_column_desc *) current->data; - width = width + cell_desc->width + this->spacing; - if(height < cell_desc->height) - { - height = cell_desc->height ; - } - } - - - - for(current=w->children; current; current=g_list_next(current)) - { - if(current->data!= table_data->scroll_buttons.button_box) - { - count++; - } - } - - w->w = width; - if(w->w + w->c.x > this->root.w) - { - w->w = this->root.w - w->c.x; - } - - - if(w->h + w->c.y > this->root.h ) - { - /* - * Do not allow the widget to exceed the screen. - * - */ - w->h = this->root.h- w->c.y - height; - } - - if (table_data->scroll_buttons.button_box) - { - gui_internal_widget_pack(this,table_data->scroll_buttons.button_box); - } - - - /* - * Deallocate column descriptions. - */ - g_list_foreach(column_data,(GFunc)g_free,NULL); - g_list_free(column_data); +void gui_internal_table_pack(struct gui_priv * this, struct widget * w) { + + int height=0; + int width=0; + int count=0; + GList * column_data = gui_internal_compute_table_dimensions(this,w); + GList * current=0; + struct table_column_desc * cell_desc=0; + struct table_data * table_data = (struct table_data*)w->data; + + for(current = column_data; current; current=g_list_next(current)) { + if(table_data->scroll_buttons.button_box == current->data ) { + continue; + } + cell_desc = (struct table_column_desc *) current->data; + width = width + cell_desc->width + this->spacing; + if(height < cell_desc->height) { + height = cell_desc->height ; + } + } + + + + for(current=w->children; current; current=g_list_next(current)) { + if(current->data!= table_data->scroll_buttons.button_box) { + count++; + } + } + + w->w = width; + if(w->w + w->c.x > this->root.w) { + w->w = this->root.w - w->c.x; + } + + + if(w->h + w->c.y > this->root.h ) { + /* + * Do not allow the widget to exceed the screen. + * + */ + w->h = this->root.h- w->c.y - height; + } + + if (table_data->scroll_buttons.button_box) { + gui_internal_widget_pack(this,table_data->scroll_buttons.button_box); + } + + + /* + * Deallocate column descriptions. + */ + g_list_foreach(column_data,(GFunc)g_free,NULL); + g_list_free(column_data); } @@ -1194,210 +1260,225 @@ gui_internal_table_pack(struct gui_priv * this, struct widget * w) * * @param table_data Data from the table object. */ -void -gui_internal_table_hide_rows(struct table_data * table_data) -{ - GList*cur_row; - for(cur_row=table_data->top_row; cur_row ; cur_row = g_list_next(cur_row)) - { - struct widget * cur_row_widget = (struct widget*)cur_row->data; - if (cur_row_widget->type!=widget_table_row) - continue; - cur_row_widget->p.x=0; - cur_row_widget->p.y=0; - cur_row_widget->w=0; - cur_row_widget->h=0; - if(cur_row==table_data->bottom_row) - break; - } +void gui_internal_table_hide_rows(struct table_data * table_data) { + GList*cur_row; + for(cur_row=table_data->top_row; cur_row ; cur_row = g_list_next(cur_row)) { + struct widget * cur_row_widget = (struct widget*)cur_row->data; + if (cur_row_widget->type!=widget_table_row) + continue; + cur_row_widget->p.x=0; + cur_row_widget->p.y=0; + cur_row_widget->w=0; + cur_row_widget->h=0; + if(cur_row==table_data->bottom_row) + break; + } } /** - * @brief Renders a table widget. + * @brief Renders a table widget, preparing it for drawing on the display * - * @param this The graphics context - * @param w The table widget to render. + * @param this The internal GUI instance + * @param w The widget to render */ -void -gui_internal_table_render(struct gui_priv * this, struct widget * w) -{ - - int x; - int y; - GList * column_desc=NULL; - GList * cur_row = NULL; - GList * current_desc=NULL; - struct table_data * table_data = (struct table_data*)w->data; - int drawing_space_left=1; - int is_first_page; - struct table_column_desc * dim=NULL; - - dbg_assert(table_data); - column_desc = gui_internal_compute_table_dimensions(this,w); - if(!column_desc) - return; - y=w->p.y; - gui_internal_table_hide_rows(table_data); - /* - * Skip rows that are on previous pages. - */ - if(table_data->top_row && table_data->top_row != w->children && !table_data->scroll_buttons.button_box_hide) - { - cur_row = table_data->top_row; - is_first_page=0; - } else { - cur_row = w->children; - table_data->top_row=NULL; - is_first_page=1; - } - - /* First, let's mark all columns as off-screen that are in rows which are *before* - * our current page. - * */ - GList *row = w->children; - while (row != cur_row) { - struct widget * cur_row_widget = (struct widget*)row->data; - GList * cur_column=NULL; - if(cur_row_widget == table_data->scroll_buttons.button_box) - { - row = g_list_next(row); - continue; - } - for(cur_column = cur_row_widget->children; cur_column; - cur_column=g_list_next(cur_column)) - { - struct widget * cur_widget = (struct widget*) cur_column->data; - if(this->hide_keys){ - cur_widget->state |= STATE_INVISIBLE; - cur_widget->state &= ~STATE_SENSITIVE; - }else{ - cur_widget->state |= STATE_OFFSCREEN; - } - } - row = g_list_next(row); - } - - /* - * Loop through each row. Drawing each cell with the proper sizes, - * at the proper positions. - */ - for(table_data->top_row=cur_row; cur_row; cur_row = g_list_next(cur_row)) - { - int max_height=0, bbox_height=0; - struct widget * cur_row_widget; - GList * cur_column=NULL; - current_desc = column_desc; - cur_row_widget = (struct widget*)cur_row->data; - x =w->p.x+this->spacing; - if(cur_row_widget == table_data->scroll_buttons.button_box) - { - continue; - } - dim = (struct table_column_desc*)current_desc->data; - - if (table_data->scroll_buttons.button_box && !table_data->scroll_buttons.button_box_hide) - bbox_height=table_data->scroll_buttons.button_box->h; - - if( y + dim->height + bbox_height + this->spacing >= w->p.y + w->h ) - { - drawing_space_left=0; - } - for(cur_column = cur_row_widget->children; cur_column; - cur_column=g_list_next(cur_column)) - { - struct widget * cur_widget = (struct widget*) cur_column->data; - if (drawing_space_left) { - cur_widget->p.x=x; - cur_widget->w=dim->width; - cur_widget->p.y=y; - cur_widget->h=dim->height; - x=x+cur_widget->w; - max_height = dim->height; - /* We pack the widget before rendering to ensure that the x and y - * coordinates get pushed down. - */ - if(this->hide_keys){ - cur_widget->state &= ~STATE_INVISIBLE; - cur_widget->state |= STATE_SENSITIVE; - }else{ - cur_widget->state &= ~STATE_OFFSCREEN; - } - gui_internal_widget_pack(this,cur_widget); - gui_internal_widget_render(this,cur_widget); - - if(dim->height > max_height) - { - max_height = dim->height; - } - } else { - /* Deactivate contents that we don't have space for. */ - if(this->hide_keys){ - cur_widget->state |= STATE_INVISIBLE; - cur_widget->state &= ~STATE_SENSITIVE; - }else{ - cur_widget->state |= STATE_OFFSCREEN; - } - } - } - - if (drawing_space_left) { - /* Row object should have its coordinates in actual - * state to be able to pass mouse clicks to Column objects - */ - cur_row_widget->p.x=w->p.x; - cur_row_widget->w=w->w; - cur_row_widget->p.y=y; - cur_row_widget->h=max_height; - y = y + max_height; - table_data->bottom_row=cur_row; - current_desc = g_list_next(current_desc); - } - } - - /* By default, hide all scroll buttons. */ - if(this->hide_keys){ - table_data->scroll_buttons.next_button->state|= STATE_INVISIBLE; - table_data->scroll_buttons.prev_button->state|= STATE_INVISIBLE; - } - table_data->scroll_buttons.next_button->state&= ~STATE_SENSITIVE; - table_data->scroll_buttons.prev_button->state&= ~STATE_SENSITIVE; - - if(table_data->scroll_buttons.button_box && (!drawing_space_left || !is_first_page) && !table_data->scroll_buttons.button_box_hide ) - { - table_data->scroll_buttons.button_box->p.y =w->p.y+w->h-table_data->scroll_buttons.button_box->h - - this->spacing; - if(table_data->scroll_buttons.button_box->p.y < y ) - { - table_data->scroll_buttons.button_box->p.y=y; - } - table_data->scroll_buttons.button_box->p.x = w->p.x; - table_data->scroll_buttons.button_box->w = w->w; - gui_internal_widget_pack(this,table_data->scroll_buttons.button_box); - if(table_data->scroll_buttons.next_button->p.y > w->p.y + w->h + table_data->scroll_buttons.next_button->h) - { - table_data->scroll_buttons.button_box->p.y = w->p.y + w->h - - table_data->scroll_buttons.button_box->h; - } - if(!drawing_space_left) - { - table_data->scroll_buttons.next_button->state|= STATE_SENSITIVE; - table_data->scroll_buttons.next_button->state&= ~STATE_INVISIBLE; - } - - if(table_data->top_row != w->children) - { - table_data->scroll_buttons.prev_button->state|= STATE_SENSITIVE; - table_data->scroll_buttons.prev_button->state&= ~STATE_INVISIBLE; - } - gui_internal_widget_render(this,table_data->scroll_buttons.button_box); - } - - /* - * Deallocate column descriptions. - */ - g_list_foreach(column_desc,(GFunc)g_free,NULL); - g_list_free(column_desc); +void gui_internal_table_render(struct gui_priv * this, struct widget * w) { + + int x; + int y; + GList * column_desc=NULL; + GList * cur_row = NULL; + GList * current_desc=NULL; + struct table_data * table_data = (struct table_data*)w->data; + int drawing_space_left=1; + int is_first_page; + struct table_column_desc * dim=NULL; + + dbg_assert(table_data); + column_desc = gui_internal_compute_table_dimensions(this,w); + if(!column_desc) + return; + y=w->p.y; + gui_internal_table_hide_rows(table_data); + /* + * Skip rows that are on previous pages. + */ + if(table_data->top_row && table_data->top_row != w->children && !table_data->scroll_buttons.button_box_hide) { + cur_row = table_data->top_row; + is_first_page=0; + } else { + cur_row = w->children; + table_data->top_row=NULL; + is_first_page=1; + } + + /* First, let's mark all columns as off-screen that are in rows which are *before* + * our current page. + * */ + GList *row = w->children; + while (row != cur_row) { + struct widget * cur_row_widget = (struct widget*)row->data; + GList * cur_column=NULL; + if(cur_row_widget == table_data->scroll_buttons.button_box) { + row = g_list_next(row); + continue; + } + for(cur_column = cur_row_widget->children; cur_column; + cur_column=g_list_next(cur_column)) { + struct widget * cur_widget = (struct widget*) cur_column->data; + if(this->hide_keys) { + cur_widget->state |= STATE_INVISIBLE; + cur_widget->state &= ~STATE_SENSITIVE; + } else { + cur_widget->state |= STATE_OFFSCREEN; + } + } + row = g_list_next(row); + } + + /* + * Loop through each row. Drawing each cell with the proper sizes, + * at the proper positions. + */ + for(table_data->top_row=cur_row; cur_row; cur_row = g_list_next(cur_row)) { + int max_height=0, bbox_height=0; + struct widget * cur_row_widget; + GList * cur_column=NULL; + current_desc = column_desc; + cur_row_widget = (struct widget*)cur_row->data; + x =w->p.x+this->spacing; + if(cur_row_widget == table_data->scroll_buttons.button_box) { + continue; + } + dim = (struct table_column_desc*)current_desc->data; + + if (table_data->scroll_buttons.button_box && !table_data->scroll_buttons.button_box_hide) + bbox_height=table_data->scroll_buttons.button_box->h; + + if( y + dim->height + bbox_height + this->spacing >= w->p.y + w->h ) { + drawing_space_left=0; + } + for(cur_column = cur_row_widget->children; cur_column; + cur_column=g_list_next(cur_column)) { + struct widget * cur_widget = (struct widget*) cur_column->data; + if (drawing_space_left) { + cur_widget->p.x=x; + cur_widget->w=dim->width; + cur_widget->p.y=y; + cur_widget->h=dim->height; + x=x+cur_widget->w; + max_height = dim->height; + /* We pack the widget before rendering to ensure that the x and y + * coordinates get pushed down. + */ + if(this->hide_keys) { + cur_widget->state &= ~STATE_INVISIBLE; + cur_widget->state |= STATE_SENSITIVE; + } else { + cur_widget->state &= ~STATE_OFFSCREEN; + } + +#if defined(GUI_INTERNAL_VISUAL_DBG) + + static struct graphics_gc *debug_gc=NULL; + static struct color gui_table_debug_color= {0x0000,0xffff,0x0400,0xffff}; /* Green */ + int visual_debug = (debug_level_get("gui_internal_visual_layout") >= lvl_debug); + + if (visual_debug) + dbg(lvl_debug, "Internal layout visual debugging is enabled"); + + if (visual_debug && !debug_gc) { + debug_gc = graphics_gc_new(this->gra); + graphics_gc_set_foreground(debug_gc, &gui_table_debug_color); + graphics_gc_set_linewidth(debug_gc, 1); + } +#endif + + gui_internal_widget_pack(this,cur_widget); + gui_internal_widget_render(this,cur_widget); + +#if defined(GUI_INTERNAL_VISUAL_DBG) + if (visual_debug) { + struct point pnt[5]; + pnt[0]=cur_widget->p; + pnt[1].x=pnt[0].x+cur_widget->w; + pnt[1].y=pnt[0].y; + pnt[2].x=pnt[0].x+cur_widget->w; + pnt[2].y=pnt[0].y+cur_widget->h; + pnt[3].x=pnt[0].x; + pnt[3].y=pnt[0].y+cur_widget->h; + pnt[4]=pnt[0]; + graphics_draw_lines(this->gra, debug_gc, pnt, 5); /* Force highlighting table borders in debug more */ + } +#endif + + if(dim->height > max_height) { + max_height = dim->height; + } + } else { + /* Deactivate contents that we don't have space for. */ + if(this->hide_keys) { + cur_widget->state |= STATE_INVISIBLE; + cur_widget->state &= ~STATE_SENSITIVE; + } else { + cur_widget->state |= STATE_OFFSCREEN; + } + } + } + + if (drawing_space_left) { + /* Row object should have its coordinates in actual + * state to be able to pass mouse clicks to Column objects + */ + cur_row_widget->p.x=w->p.x; + cur_row_widget->w=w->w; + cur_row_widget->p.y=y; + cur_row_widget->h=max_height; + y = y + max_height; + table_data->bottom_row=cur_row; + current_desc = g_list_next(current_desc); + } + } + + /* By default, hide all scroll buttons. */ + if(this->hide_keys) { + table_data->scroll_buttons.next_button->state|= STATE_INVISIBLE; + table_data->scroll_buttons.prev_button->state|= STATE_INVISIBLE; + } + table_data->scroll_buttons.next_button->state&= ~STATE_SENSITIVE; + table_data->scroll_buttons.prev_button->state&= ~STATE_SENSITIVE; + + if(table_data->scroll_buttons.button_box && (!drawing_space_left || !is_first_page) + && !table_data->scroll_buttons.button_box_hide ) { + table_data->scroll_buttons.button_box->p.y =w->p.y+w->h-table_data->scroll_buttons.button_box->h - + this->spacing; + if(table_data->scroll_buttons.button_box->p.y < y ) { + table_data->scroll_buttons.button_box->p.y=y; + } + table_data->scroll_buttons.button_box->p.x = w->p.x; + table_data->scroll_buttons.button_box->w = w->w; + gui_internal_widget_pack(this,table_data->scroll_buttons.button_box); + if(table_data->scroll_buttons.next_button->p.y > w->p.y + w->h + table_data->scroll_buttons.next_button->h) { + table_data->scroll_buttons.button_box->p.y = w->p.y + w->h - + table_data->scroll_buttons.button_box->h; + } + if(!drawing_space_left) { + table_data->scroll_buttons.next_button->state|= STATE_SENSITIVE; + table_data->scroll_buttons.next_button->state&= ~STATE_INVISIBLE; + } + + if(table_data->top_row != w->children) { + table_data->scroll_buttons.prev_button->state|= STATE_SENSITIVE; + table_data->scroll_buttons.prev_button->state&= ~STATE_INVISIBLE; + } + gui_internal_widget_render(this,table_data->scroll_buttons.button_box); + } + + /* + * Deallocate column descriptions. + */ + g_list_foreach(column_desc,(GFunc)g_free,NULL); + g_list_free(column_desc); } /** @@ -1410,37 +1491,32 @@ gui_internal_table_render(struct gui_priv * this, struct widget * w) * @param wm The button widget that was pressed. * @param data */ -void -gui_internal_table_button_next(struct gui_priv * this, struct widget * wm, void *data) -{ - struct widget * table_widget=NULL; - struct table_data * table_data = NULL; - - if(wm) - table_widget = (struct widget * ) wm->data; - else - table_widget = data; - - if(table_widget && table_widget->type==widget_table) - table_data = (struct table_data*) table_widget->data; - - if(table_data) - { - GList *l=g_list_next(table_data->bottom_row); - if(l) { - gui_internal_table_hide_rows(table_data); - table_data->top_row=l; - } - } - - if(wm) - wm->state&= ~STATE_HIGHLIGHTED; - - gui_internal_menu_render(this); +void gui_internal_table_button_next(struct gui_priv * this, struct widget * wm, void *data) { + struct widget * table_widget=NULL; + struct table_data * table_data = NULL; + + if(wm) + table_widget = (struct widget * ) wm->data; + else + table_widget = data; + + if(table_widget && table_widget->type==widget_table) + table_data = (struct table_data*) table_widget->data; + + if(table_data) { + GList *l=g_list_next(table_data->bottom_row); + if(l) { + gui_internal_table_hide_rows(table_data); + table_data->top_row=l; + } + } + + if(wm) + wm->state&= ~STATE_HIGHLIGHTED; + + gui_internal_menu_render(this); } - - /** * @brief Handles the 'previous page' table event. * @@ -1450,36 +1526,34 @@ gui_internal_table_button_next(struct gui_priv * this, struct widget * wm, void * @param this The graphics context. * @param wm The button widget that was pressed. */ -void -gui_internal_table_button_prev(struct gui_priv * this, struct widget * wm, void *data) -{ - struct widget * table_widget = NULL; - struct table_data * table_data = NULL; - - if(wm) - table_widget=(struct widget * ) wm->data; - else - table_widget=(struct widget * ) data; - - if(table_widget && table_widget->type==widget_table) - table_data = (struct table_data*) table_widget->data; - - if(table_data) { - int bottomy=table_widget->p.y+table_widget->h; - int n; - GList *top=table_data->top_row; - struct widget *w=(struct widget*)top->data; - if(table_data->scroll_buttons.button_box->p.y!=0) { - bottomy=table_data->scroll_buttons.button_box->p.y; - } - n=(bottomy-w->p.y)/w->h; - while(n-- > 0 && (top=g_list_previous(top))!=NULL); - gui_internal_table_hide_rows(table_data); - table_data->top_row=top; - } - if(wm) - wm->state&= ~STATE_HIGHLIGHTED; - gui_internal_menu_render(this); +void gui_internal_table_button_prev(struct gui_priv * this, struct widget * wm, void *data) { + struct widget * table_widget = NULL; + struct table_data * table_data = NULL; + + if(wm) + table_widget=(struct widget * ) wm->data; + else + table_widget=(struct widget * ) data; + + if(table_widget && table_widget->type==widget_table) + table_data = (struct table_data*) table_widget->data; + + if(table_data) { + int bottomy=table_widget->p.y+table_widget->h; + int n; + GList *top=table_data->top_row; + struct widget *w=(struct widget*)top->data; + if(table_data->scroll_buttons.button_box->p.y!=0) { + bottomy=table_data->scroll_buttons.button_box->p.y; + } + n=(bottomy-w->p.y)/w->h; + while(n-- > 0 && (top=g_list_previous(top))!=NULL); + gui_internal_table_hide_rows(table_data); + table_data->top_row=top; + } + if(wm) + wm->state&= ~STATE_HIGHLIGHTED; + gui_internal_menu_render(this); } @@ -1491,7 +1565,6 @@ gui_internal_table_button_prev(struct gui_priv * this, struct widget * wm, void * * @param p The table_data structure */ -void gui_internal_table_data_free(void * p) -{ - g_free(p); +void gui_internal_table_data_free(void * p) { + g_free(p); } |