2 * Navit, a modular navigation system.
3 * Copyright (C) 2005-2008 Navit Team
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * version 2 as published by the Free Software Foundation.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
20 //##############################################################################################################
22 //# File: gui_internal.c
23 //# Description: New "internal" GUI for use with any graphics library
24 //# Comment: Trying to make a touchscreen friendly GUI
25 //# Authors: Martin Schaller (04/2008), Stefan Klumpp (04/2008)
27 //##############################################################################################################
45 #include "transform.h"
61 #include "navit_nls.h"
63 #define STATE_VISIBLE 1
64 #define STATE_SELECTED 2
65 #define STATE_HIGHLIGHTED 4
66 #define STATE_SENSITIVE 8
68 #define STATE_CLEAR 32
87 gravity_left_top=gravity_left|gravity_top,
88 gravity_top_center=gravity_xcenter|gravity_top,
89 gravity_right_top=gravity_right|gravity_top,
90 gravity_left_center=gravity_left|gravity_ycenter,
91 gravity_center=gravity_xcenter|gravity_ycenter,
92 gravity_right_center=gravity_right|gravity_ycenter,
93 gravity_left_bottom=gravity_left|gravity_bottom,
94 gravity_bottom_center=gravity_xcenter|gravity_bottom,
95 gravity_right_bottom=gravity_right|gravity_bottom,
98 orientation_horizontal=0x10000,
99 orientation_vertical=0x20000,
100 orientation_horizontal_vertical=0x40000,
105 struct widget *search_list;
106 struct widget *keyboard;
110 //##############################################################################################################
113 //# Authors: Martin Schaller (04/2008)
114 //##############################################################################################################
116 enum widget_type type;
117 struct graphics_gc *background;
118 struct graphics_gc *foreground_frame;
120 struct graphics_image *img;
122 * A function to be invoked on actions.
123 * @li widget The widget that is receiving the button press.
126 void (*func)(struct gui_priv *priv, struct widget *widget);
130 void (*data_free)(void *data);
140 int bl,br,bt,bb,spx,spy;
144 int (*set_attr)(void *, struct attr *);
145 int (*get_attr)(void *, enum attr_type, struct attr *, struct attr_iter *);
146 void (*remove_cb)(void *, struct callback *cb);
153 struct menu_data *menu_data;
158 * @brief A structure to store configuration values.
160 * This structure stores configuration values for how gui elements in the internal GUI
163 struct gui_config_settings {
166 * The base size (in fractions of a point) to use for text.
170 * The size (in pixels) that xs style icons should be scaled to.
174 * The size (in pixels) that s style icons (small) should be scaled to
178 * The size (in pixels) that l style icons should be scaled to
182 * The default amount of spacing (in pixels) to place between GUI elements.
189 * Indexes into the config_profiles array.
191 const int LARGE_PROFILE=0;
192 const int MEDIUM_PROFILE=1;
193 const int SMALL_PROFILE=2;
196 * The default config profiles.
198 * [0] => LARGE_PROFILE (screens 640 in one dimension)
199 * [1] => MEDIUM PROFILE (screens larger than 320 in one dimension
200 * [2] => Small profile (default)
202 static struct gui_config_settings config_profiles[]={
208 //##############################################################################################################
211 //# Authors: Martin Schaller (04/2008)
212 //##############################################################################################################
216 struct graphics *gra;
217 struct graphics_gc *background;
218 struct graphics_gc *background2;
219 struct graphics_gc *highlight_background;
220 struct graphics_gc *foreground;
221 struct graphics_gc *text_foreground;
222 struct graphics_gc *text_background;
226 struct graphics_font *font;
227 int icon_xs, icon_s, icon_l;
229 struct widget *widgets;
233 struct widget *highlighted;
234 struct widget *highlighted_menu;
235 int clickp_valid, vehicle_valid;
236 struct pcoord clickp, vehiclep;
237 struct search_list *sl;
239 int menu_on_map_click;
244 * The setting information read from the configuration file.
245 * values of -1 indicate no value was specified in the config file.
247 struct gui_config_settings config;
248 struct event_idle *idle;
249 struct callback *motion_cb,*button_cb,*resize_cb,*keypress_cb,*idle_cb;
254 * @brief A structure to store information about a table.
256 * The table_data widget stores pointers to extra information needed by the
259 * The table_data structure needs to be freed with data_free along with the widget.
265 * A GList pointer into a widget->children list that indicates the row
266 * currently being rendered at the top of the table.
270 * A Glist pointer into a widget->children list that indicates the row
271 * currently being rendered at the bottom of the table.
276 * A list of table_row widgets that mark the
277 * top rows for each page of the table.
278 * This is needed for the 'previous page' function of the table.
280 GList * page_headers;
283 * A container box that is the child of the table widget that contains+groups
284 * the next and previous button.
286 struct widget * button_box;
289 * A button widget to handle 'next page' requests
291 struct widget * next_button;
293 * A button widget to handle 'previous page' requests.
295 struct widget * prev_button;
299 * a pointer to the gui context.
300 * This is needed by the free function to destory the buttons.
302 struct gui_priv * this;
306 * A data structure that holds information about a column that makes up a table.
310 struct table_column_desc
314 * The computed height of a cell in the table.
319 * The computed width of a cell in the table.
324 static void gui_internal_widget_render(struct gui_priv *this, struct widget *w);
325 static void gui_internal_widget_pack(struct gui_priv *this, struct widget *w);
326 static struct widget * gui_internal_box_new(struct gui_priv *this, enum flags flags);
327 static void gui_internal_widget_append(struct widget *parent, struct widget *child);
328 static void gui_internal_widget_destroy(struct gui_priv *this, struct widget *w);
329 static void gui_internal_apply_config(struct gui_priv *this);
331 static struct widget* gui_internal_widget_table_new(struct gui_priv * this, enum flags flags);
332 static void gui_internal_widget_table_add_row(struct widget * table, struct widget * row);
333 static void gui_internal_table_render(struct gui_priv * this, struct widget * w);
334 static void gui_internal_cmd_route(struct gui_priv * this, struct widget * w);
335 static void gui_internal_table_pack(struct gui_priv * this, struct widget * w);
336 static void gui_internal_table_button_next(struct gui_priv * this, struct widget * wm);
337 static void gui_internal_table_button_prev(struct gui_priv * this, struct widget * wm);
338 static void gui_internal_table_data_free(void * d);
340 static void gui_internal_search_idle_end(struct gui_priv *this);
341 static void gui_internal_search(struct gui_priv *this, char *what, char *type, int flags);
342 static void gui_internal_search_street(struct gui_priv *this, struct widget *widget);
343 static void gui_internal_search_street_in_town(struct gui_priv *this, struct widget *widget);
344 static void gui_internal_search_town(struct gui_priv *this, struct widget *wm);
345 static void gui_internal_search_town_in_country(struct gui_priv *this, struct widget *wm);
346 static void gui_internal_search_country(struct gui_priv *this, struct widget *widget);
348 static struct widget *gui_internal_keyboard_do(struct gui_priv *this, struct widget *wkbdb, int mode);
350 static struct graphics_image *
351 image_new_scaled(struct gui_priv *this, char *name, int w, int h)
353 struct graphics_image *ret=NULL;
354 char *full_name=NULL;
357 for (i = 1 ; i < 6 ; i++) {
361 full_name=g_strdup_printf("%s/xpm/%s.svg", getenv("NAVIT_SHAREDIR"), name);
364 full_name=g_strdup_printf("%s/xpm/%s.svgz", getenv("NAVIT_SHAREDIR"), name);
367 if (w != -1 && h != -1) {
368 full_name=g_strdup_printf("%s/xpm/%s_%d_%d.png", getenv("NAVIT_SHAREDIR"), name, w, h);
372 full_name=g_strdup_printf("%s/xpm/%s.png", getenv("NAVIT_SHAREDIR"), name);
375 full_name=g_strdup_printf("%s/xpm/%s.xpm", getenv("NAVIT_SHAREDIR"), name);
378 dbg(1,"trying '%s'\n", full_name);
381 if (!file_exists(full_name)) {
385 ret=graphics_image_new_scaled(this->gra, full_name, w, h);
386 dbg(1,"ret=%p\n", ret);
391 dbg(0,"failed to load %s with %d,%d\n", name, w, h);
396 static struct graphics_image *
397 image_new_o(struct gui_priv *this, char *name)
399 return image_new_scaled(this, name, -1, -1);
402 static struct graphics_image *
403 image_new_xs(struct gui_priv *this, char *name)
405 return image_new_scaled(this, name, this->icon_xs, this->icon_xs);
409 static struct graphics_image *
410 image_new_s(struct gui_priv *this, char *name)
412 return image_new_scaled(this, name, this->icon_s, this->icon_s);
415 static struct graphics_image *
416 image_new_l(struct gui_priv *this, char *name)
418 return image_new_scaled(this, name, this->icon_l, this->icon_l);
422 coordinates(struct pcoord *pc, char sep)
424 char latc='N',lngc='E';
425 int lat_deg,lat_min,lat_sec;
426 int lng_deg,lng_min,lng_sec;
431 transform_to_geo(pc->pro, &c, &g);
442 lat_min=fmod(g.lat*60,60);
443 lat_sec=fmod(g.lat*3600,60);
445 lng_min=fmod(g.lng*60,60);
446 lng_sec=fmod(g.lng*3600,60);
447 return g_strdup_printf("%d°%d'%d\" %c%c%d°%d'%d\" %c",lat_deg,lat_min,lat_sec,latc,sep,lng_deg,lng_min,lng_sec,lngc);
451 gui_internal_background_render(struct gui_priv *this, struct widget *w)
453 struct point pnt=w->p;
454 if (w->state & STATE_HIGHLIGHTED)
455 graphics_draw_rectangle(this->gra, this->highlight_background, &pnt, w->w, w->h);
458 graphics_draw_rectangle(this->gra, w->background, &pnt, w->w, w->h);
461 static struct widget *
462 gui_internal_label_new(struct gui_priv *this, char *text)
468 struct widget *widget=g_new0(struct widget, 1);
469 widget->type=widget_label;
471 widget->text=g_strdup(text);
472 graphics_get_text_bbox(this->gra, this->font, text, 0x10000, 0x0, p, 0);
476 widget->h=h+this->spacing;
477 widget->w=w+this->spacing;
478 widget->flags=gravity_center;
483 static struct widget *
484 gui_internal_label_new_abbrev(struct gui_priv *this, char *text, int maxwidth)
486 struct widget *ret=NULL;
487 char *tmp=g_malloc(strlen(text)+3);
494 ret=gui_internal_label_new(this, tmp);
495 if (ret->w < maxwidth)
497 gui_internal_widget_destroy(this, ret);
505 static struct widget *
506 gui_internal_image_new(struct gui_priv *this, struct graphics_image *image)
508 struct widget *widget=g_new0(struct widget, 1);
509 widget->type=widget_image;
512 widget->w=image->width;
513 widget->h=image->height;
519 gui_internal_image_render(struct gui_priv *this, struct widget *w)
523 gui_internal_background_render(this, w);
526 pnt.x+=w->w/2-w->img->hot.x;
527 pnt.y+=w->h/2-w->img->hot.y;
528 graphics_draw_image(this->gra, this->foreground, &pnt, w->img);
533 gui_internal_label_render(struct gui_priv *this, struct widget *w)
535 struct point pnt=w->p;
536 gui_internal_background_render(this, w);
538 pnt.y+=w->h-this->spacing;
539 graphics_draw_text(this->gra, this->text_foreground, this->text_background, this->font, w->text, &pnt, 0x10000, 0x0);
543 static struct widget *
544 gui_internal_text_new(struct gui_priv *this, char *text)
546 char *s=g_strdup(text),*s2,*tok;
547 struct widget *ret=gui_internal_box_new(this, gravity_center|orientation_vertical);
549 while ((tok=strtok(s2,"\n"))) {
550 gui_internal_widget_append(ret, gui_internal_label_new(this, tok));
557 static struct widget *
558 gui_internal_button_new_with_callback(struct gui_priv *this, char *text, struct graphics_image *image, enum flags flags, void(*func)(struct gui_priv *priv, struct widget *widget), void *data)
560 struct widget *ret=NULL;
561 ret=gui_internal_box_new(this, flags);
564 gui_internal_widget_append(ret, gui_internal_image_new(this, image));
566 gui_internal_widget_append(ret, gui_internal_text_new(this, text));
570 ret->state |= STATE_SENSITIVE;
571 ret->speech=g_strdup(text);
579 gui_internal_button_attr_update(struct gui_priv *this, struct widget *w)
586 if (w->get_attr(w->instance, w->on.type, &curr, NULL))
587 is_on=curr.u.data == w->on.u.data;
590 if (is_on != w->is_on) {
594 l=g_list_first(w->children);
598 graphics_image_free(this->gra, wi->img);
599 wi->img=image_new_xs(this, is_on ? "gui_active" : "gui_inactive");
601 if (w->is_on && w->off.type == attr_none)
602 w->state &= ~STATE_SENSITIVE;
604 w->state |= STATE_SENSITIVE;
611 gui_internal_button_attr_callback(struct gui_priv *this, struct widget *w)
613 if (gui_internal_button_attr_update(this, w))
614 gui_internal_widget_render(this, w);
617 gui_internal_button_attr_pressed(struct gui_priv *this, struct widget *w)
620 w->set_attr(w->instance, &w->off);
622 w->set_attr(w->instance, &w->on);
623 gui_internal_button_attr_update(this, w);
627 static struct widget *
628 gui_internal_button_navit_attr_new(struct gui_priv *this, char *text, enum flags flags, struct attr *on, struct attr *off)
630 struct graphics_image *image=image_new_xs(this, "gui_inactive");
632 ret=gui_internal_button_new_with_callback(this, text, image, flags, gui_internal_button_attr_pressed, NULL);
637 ret->get_attr=(int (*)(void *, enum attr_type, struct attr *, struct attr_iter *))navit_get_attr;
638 ret->set_attr=(int (*)(void *, struct attr *))navit_set_attr;
639 ret->remove_cb=(void (*)(void *, struct callback *))navit_remove_callback;
640 ret->instance=this->nav;
641 ret->cb=callback_new_attr_2(callback_cast(gui_internal_button_attr_callback), on->type, this, ret);
642 navit_add_callback(this->nav, ret->cb);
643 gui_internal_button_attr_update(this, ret);
647 static struct widget *
648 gui_internal_button_map_attr_new(struct gui_priv *this, char *text, enum flags flags, struct map *map, struct attr *on, struct attr *off, int deflt)
650 struct graphics_image *image=image_new_xs(this, "gui_inactive");
652 ret=gui_internal_button_new_with_callback(this, text, image, flags, gui_internal_button_attr_pressed, NULL);
658 ret->get_attr=(int (*)(void *, enum attr_type, struct attr *, struct attr_iter *))map_get_attr;
659 ret->set_attr=(int (*)(void *, struct attr *))map_set_attr;
660 ret->remove_cb=(void (*)(void *, struct callback *))map_remove_callback;
663 ret->cb=callback_new_attr_2(callback_cast(gui_internal_button_attr_callback), on->type, this, ret);
664 map_add_callback(map, ret->cb);
665 gui_internal_button_attr_update(this, ret);
669 static struct widget *
670 gui_internal_button_new(struct gui_priv *this, char *text, struct graphics_image *image, enum flags flags)
672 return gui_internal_button_new_with_callback(this, text, image, flags, NULL, NULL);
675 //##############################################################################################################
678 //# Authors: Martin Schaller (04/2008)
679 //##############################################################################################################
680 static void gui_internal_clear(struct gui_priv *this)
682 struct graphics *gra=this->gra;
686 graphics_draw_rectangle(gra, this->background, &pnt, this->root.w, this->root.h);
689 static struct widget *
690 gui_internal_find_widget(struct widget *wi, struct point *p, int flags)
692 struct widget *ret,*child;
693 GList *l=wi->children;
696 if (p && (wi->p.x > p->x || wi->p.y > p->y || wi->p.x + wi->w < p->x || wi->p.y + wi->h < p->y)) {
699 if (wi->state & flags)
703 ret=gui_internal_find_widget(child, p, flags);
714 gui_internal_highlight_do(struct gui_priv *this, struct widget *found)
716 if (found == this->highlighted)
718 if (this->highlighted) {
719 this->highlighted->state &= ~STATE_HIGHLIGHTED;
720 if (this->root.children && this->highlighted_menu == g_list_last(this->root.children)->data)
721 gui_internal_widget_render(this, this->highlighted);
722 this->highlighted=NULL;
723 this->highlighted_menu=NULL;
726 this->highlighted=found;
727 this->highlighted_menu=g_list_last(this->root.children)->data;
728 this->highlighted->state |= STATE_HIGHLIGHTED;
729 gui_internal_widget_render(this, this->highlighted);
730 dbg(1,"%d,%d %dx%d\n", found->p.x, found->p.y, found->w, found->h);
733 //##############################################################################################################
736 //# Authors: Martin Schaller (04/2008)
737 //##############################################################################################################
738 static void gui_internal_highlight(struct gui_priv *this, struct point *p)
740 struct widget *menu,*found=NULL;
743 menu=g_list_last(this->root.children)->data;
744 found=gui_internal_find_widget(menu, p, STATE_SENSITIVE);
746 gui_internal_highlight_do(this, found);
749 static struct widget *
750 gui_internal_box_new_with_label(struct gui_priv *this, enum flags flags, char *label)
752 struct widget *widget=g_new0(struct widget, 1);
755 widget->text=g_strdup(label);
756 widget->type=widget_box;
761 static struct widget *
762 gui_internal_box_new(struct gui_priv *this, enum flags flags)
764 return gui_internal_box_new_with_label(this, flags, NULL);
768 static void gui_internal_box_render(struct gui_priv *this, struct widget *w)
773 gui_internal_background_render(this, w);
777 pnt[1].x=pnt[0].x+w->w;
779 pnt[2].x=pnt[0].x+w->w;
780 pnt[2].y=pnt[0].y+w->h;
782 pnt[3].y=pnt[0].y+w->h;
784 graphics_draw_lines(this->gra, this->foreground, pnt, 5);
790 gui_internal_widget_render(this, wc);
795 static void gui_internal_box_pack(struct gui_priv *this, struct widget *w)
798 int x0,x=0,y=0,width=0,height=0,owidth=0,oheight=0,expand=0,count=0,rows=0,cols=w->cols ? w->cols : 3;
800 int orientation=w->flags & 0xffff0000;
808 if (orientation == orientation_horizontal_vertical && count <= cols)
809 orientation=orientation_horizontal;
810 switch (orientation) {
811 case orientation_horizontal:
815 gui_internal_widget_pack(this, wc);
819 if (wc->flags & flags_expand)
820 expand+=wc->w ? wc->w : 1;
826 if (expand && w->w) {
827 expand=100*(w->w-width+expand)/expand;
832 case orientation_vertical:
836 gui_internal_widget_pack(this, wc);
840 if (wc->flags & flags_expand)
841 expand+=wc->h ? wc->h : 1;
847 if (expand && w->h) {
848 expand=100*(w->h-height+expand)/expand;
853 case orientation_horizontal_vertical:
858 gui_internal_widget_pack(this, wc);
868 rows=(count+cols-1)/cols;
871 width+=w->spx*(cols-1);
872 height+=w->spy*(rows-1);
880 if (! w->w && ! w->h) {
881 w->w=w->bl+w->br+width;
882 w->h=w->bt+w->bb+height;
884 if (w->flags & gravity_left)
886 if (w->flags & gravity_xcenter)
887 x=w->p.x+w->w/2-owidth/2;
888 if (w->flags & gravity_right)
889 x=w->p.x+w->w-w->br-owidth;
890 if (w->flags & gravity_top)
892 if (w->flags & gravity_ycenter)
893 y=w->p.y+w->h/2-oheight/2;
894 if (w->flags & gravity_bottom)
895 y=w->p.y+w->h-w->bb-oheight;
897 switch (orientation) {
898 case orientation_horizontal:
903 if (wc->flags & flags_fill)
905 if (wc->flags & flags_expand) {
908 wc->w=wc->w*expand/100;
910 if (w->flags & gravity_top)
912 if (w->flags & gravity_ycenter)
914 if (w->flags & gravity_bottom)
920 case orientation_vertical:
925 if (wc->flags & flags_fill)
927 if (wc->flags & flags_expand) {
930 wc->h=wc->h*expand/100;
932 if (w->flags & gravity_left)
934 if (w->flags & gravity_xcenter)
936 if (w->flags & gravity_right)
942 case orientation_horizontal_vertical:
952 if (wc->flags & flags_fill) {
956 if (w->flags & gravity_left)
958 if (w->flags & gravity_xcenter)
959 wc->p.x=x+(width-wc->w)/2;
960 if (w->flags & gravity_right)
961 wc->p.x=x+width-wc->w;
962 if (w->flags & gravity_top)
964 if (w->flags & gravity_ycenter)
965 wc->p.y=y+(height-wc->h)/2;
966 if (w->flags & gravity_bottom)
967 wc->p.y=y-height-wc->h;
969 if (++count == cols) {
983 gui_internal_widget_pack(this, wc);
988 static void gui_internal_widget_append(struct widget *parent, struct widget *child)
990 if (! child->background)
991 child->background=parent->background;
992 parent->children=g_list_append(parent->children, child);
995 static void gui_internal_widget_children_destroy(struct gui_priv *this, struct widget *w)
1003 gui_internal_widget_destroy(this, wc);
1006 g_list_free(w->children);
1010 static void gui_internal_widget_destroy(struct gui_priv *this, struct widget *w)
1012 gui_internal_widget_children_destroy(this, w);
1016 graphics_image_free(this->gra, w->img);
1022 w->data_free(w->data);
1023 if (w->cb && w->remove_cb)
1024 w->remove_cb(w->instance, w->cb);
1030 gui_internal_widget_render(struct gui_priv *this, struct widget *w)
1034 gui_internal_box_render(this, w);
1037 gui_internal_label_render(this, w);
1040 gui_internal_image_render(this, w);
1043 gui_internal_table_render(this,w);
1051 gui_internal_widget_pack(struct gui_priv *this, struct widget *w)
1055 gui_internal_box_pack(this, w);
1058 gui_internal_table_pack(this,w);
1064 //##############################################################################################################
1067 //# Authors: Martin Schaller (04/2008)
1068 //##############################################################################################################
1069 static void gui_internal_call_highlighted(struct gui_priv *this)
1071 if (! this->highlighted || ! this->highlighted->func)
1073 this->highlighted->reason=1;
1074 this->highlighted->func(this, this->highlighted);
1078 gui_internal_say(struct gui_priv *this, struct widget *w, int questionmark)
1080 char *text=w->speech;
1088 text=g_strdup_printf("%s%c", text, questionmark ? '?':'\0');
1089 navit_say(this->nav, text);
1095 gui_internal_prune_menu(struct gui_priv *this, struct widget *w)
1098 gui_internal_search_idle_end(this);
1099 while ((l = g_list_last(this->root.children))) {
1101 gui_internal_say(this, w, 0);
1102 gui_internal_widget_render(this, w);
1105 gui_internal_widget_destroy(this, l->data);
1106 this->root.children=g_list_remove(this->root.children, l->data);
1111 gui_internal_prune_menu_count(struct gui_priv *this, int count, int render)
1114 gui_internal_search_idle_end(this);
1115 while ((l = g_list_last(this->root.children)) && count-- > 0) {
1116 gui_internal_widget_destroy(this, l->data);
1117 this->root.children=g_list_remove(this->root.children, l->data);
1120 gui_internal_say(this, l->data, 0);
1121 gui_internal_widget_render(this, l->data);
1126 gui_internal_back(struct gui_priv *this, struct widget *w)
1128 gui_internal_prune_menu_count(this, 1, 1);
1132 gui_internal_cmd_return(struct gui_priv *this, struct widget *wm)
1134 gui_internal_prune_menu(this, wm->data);
1138 gui_internal_cmd_main_menu(struct gui_priv *this, struct widget *wm)
1140 gui_internal_prune_menu(this, this->root.children->data);
1143 static struct widget *
1144 gui_internal_top_bar(struct gui_priv *this)
1146 struct widget *w,*wm,*wh,*wc,*wcn;
1147 int dots_len, sep_len;
1149 int width,width_used=0,use_sep,incomplete=0;
1151 w=gui_internal_box_new(this, gravity_left_center|orientation_horizontal|flags_fill);
1152 w->bl=this->spacing;
1153 w->spx=this->spacing;
1154 w->background=this->background2;
1155 wm=gui_internal_button_new_with_callback(this, NULL,
1156 image_new_s(this, "gui_map"), gravity_center|orientation_vertical,
1157 gui_internal_cmd_return, NULL);
1158 wm->speech=g_strdup(_("Back to map"));
1159 gui_internal_widget_pack(this, wm);
1160 wh=gui_internal_button_new_with_callback(this, NULL,
1161 image_new_s(this, "gui_home"), gravity_center|orientation_vertical,
1162 gui_internal_cmd_main_menu, NULL);
1163 wh->speech=g_strdup(_("Main Menu"));
1164 gui_internal_widget_pack(this, wh);
1165 gui_internal_widget_append(w, wm);
1166 gui_internal_widget_append(w, wh);
1167 width=this->root.w-w->bl-wm->w-w->spx-wh->w;
1168 l=g_list_last(this->root.children);
1169 wcn=gui_internal_label_new(this,".. »");
1171 gui_internal_widget_destroy(this, wcn);
1172 wcn=gui_internal_label_new(this,"»");
1174 gui_internal_widget_destroy(this, wcn);
1176 if (g_list_previous(l) || !g_list_next(l)) {
1178 wcn=gui_internal_label_new(this, wc->text);
1183 dbg(1,"%d (%s) + %d + %d + %d > %d\n", wcn->w, wc->text, width_used, w->spx, use_sep ? sep_len : 0, width);
1184 if (wcn->w + width_used + w->spx + (use_sep ? sep_len : 0) + (g_list_previous(l) ? dots_len : 0) > width) {
1186 gui_internal_widget_destroy(this, wcn);
1190 res=g_list_prepend(res, gui_internal_label_new(this, "»"));
1191 width_used+=sep_len+w->spx;
1194 wcn->func=gui_internal_cmd_return;
1196 wcn->state |= STATE_SENSITIVE;
1197 res=g_list_prepend(res, wcn);
1200 l=g_list_previous(l);
1204 wcn=gui_internal_label_new_abbrev(this, wc->text, width-width_used-w->spx-dots_len);
1205 wcn->func=gui_internal_cmd_return;
1207 wcn->state |= STATE_SENSITIVE;
1208 res=g_list_prepend(res, wcn);
1209 l=g_list_previous(l);
1212 wcn=gui_internal_label_new(this, ".. »");
1213 wcn->func=gui_internal_cmd_return;
1215 wcn->state |= STATE_SENSITIVE;
1216 res=g_list_prepend(res, wcn);
1220 gui_internal_widget_append(w, l->data);
1225 gui_internal_widget_destroy(this, dots);
1232 * Applys the configuration values to this based on the settings
1233 * specified in the configuration file (this->config) and
1234 * the most approriate default profile based on screen resolution.
1236 * This function should be run after this->root is setup and could
1237 * be rerun after the window is resized.
1239 * @authors Steve Singer <ssinger_pg@sympatico.ca> (09/2008)
1241 static void gui_internal_apply_config(struct gui_priv *this)
1243 struct gui_config_settings * current_config=0;
1246 * Select default values from profile based on the screen.
1248 if(this->root.w > 320 || this->root.h > 320)
1250 if(this->root.w > 640 || this->root.h > 640)
1252 current_config = &config_profiles[LARGE_PROFILE];
1256 current_config = &config_profiles[MEDIUM_PROFILE];
1261 current_config = &config_profiles[SMALL_PROFILE];
1265 * Apply override values from config file
1267 if(this->config.font_size == -1 )
1269 this->font_size = current_config->font_size;
1273 this->font_size = this->config.font_size;
1276 if(this->config.icon_xs == -1 )
1278 this->icon_xs = current_config->icon_xs;
1282 this->icon_xs = this->config.icon_xs;
1285 if(this->config.icon_s == -1 )
1287 this->icon_s = current_config->icon_s;
1291 this->icon_s = this->config.icon_s;
1293 if(this->config.icon_l == -1 )
1295 this->icon_l = current_config->icon_l;
1299 this->icon_l = this->config.icon_l;
1301 if(this->config.spacing == -1 )
1303 this->spacing = current_config->spacing;
1307 this->spacing = current_config->spacing;
1312 static struct widget *
1313 gui_internal_menu(struct gui_priv *this, char *label)
1315 struct widget *menu,*w;
1318 gui_internal_search_idle_end(this);
1319 menu=gui_internal_box_new_with_label(this, gravity_center|orientation_vertical, label);
1320 menu->w=this->root.w;
1321 menu->h=this->root.h;
1322 menu->background=this->background;
1323 gui_internal_apply_config(this);
1324 this->font=graphics_font_new(this->gra,this->font_size,1);
1325 menu->menu_data=g_new0(struct menu_data, 1);
1326 gui_internal_widget_append(&this->root, menu);
1327 w=gui_internal_top_bar(this);
1328 gui_internal_widget_append(menu, w);
1329 w=gui_internal_box_new(this, gravity_center|orientation_horizontal_vertical|flags_expand|flags_fill);
1330 w->spx=4*this->spacing;
1331 gui_internal_widget_append(menu, w);
1336 static struct menu_data *
1337 gui_internal_menu_data(struct gui_priv *this)
1340 struct widget *menu;
1342 l=g_list_last(this->root.children);
1344 return menu->menu_data;
1348 gui_internal_menu_render(struct gui_priv *this)
1351 struct widget *menu;
1353 l=g_list_last(this->root.children);
1355 gui_internal_say(this, menu, 0);
1356 gui_internal_widget_pack(this, menu);
1357 gui_internal_widget_render(this, menu);
1361 gui_internal_cmd_set_destination(struct gui_priv *this, struct widget *wm)
1363 struct widget *w=wm->data;
1364 dbg(0,"c=%d:0x%x,0x%x\n", w->c.pro, w->c.x, w->c.y);
1365 navit_set_destination(this->nav, &w->c, w->name);
1366 gui_internal_prune_menu(this, NULL);
1370 gui_internal_cmd_set_position(struct gui_priv *this, struct widget *wm)
1372 struct widget *w=wm->data;
1373 navit_set_position(this->nav, &w->c);
1374 gui_internal_prune_menu(this, NULL);
1378 gui_internal_cmd_add_bookmark_do(struct gui_priv *this, struct widget *widget)
1381 dbg(0,"text='%s'\n", widget->text);
1382 if (widget->text && strlen(widget->text))
1383 navit_add_bookmark(this->nav, &widget->c, widget->text);
1384 g_free(widget->text);
1386 l=g_list_previous(g_list_last(this->root.children));
1387 gui_internal_prune_menu(this, l->data);
1391 gui_internal_cmd_add_bookmark_clicked(struct gui_priv *this, struct widget *widget)
1393 gui_internal_cmd_add_bookmark_do(this, widget->data);
1397 gui_internal_cmd_add_bookmark_changed(struct gui_priv *this, struct widget *wm)
1402 len=strlen(wm->text);
1403 dbg(1,"len=%d\n", len);
1404 if (len && (wm->text[len-1] == '\n' || wm->text[len-1] == '\r')) {
1405 wm->text[len-1]='\0';
1406 gui_internal_cmd_add_bookmark_do(this, wm);
1412 static struct widget * gui_internal_keyboard(struct gui_priv *this, int mode);
1415 gui_internal_cmd_add_bookmark(struct gui_priv *this, struct widget *wm)
1417 struct widget *w,*wb,*wk,*wl,*we,*wnext,*wp=wm->data;
1418 wb=gui_internal_menu(this, "Add Bookmark");
1419 w=gui_internal_box_new(this, gravity_left_top|orientation_vertical|flags_expand|flags_fill);
1420 gui_internal_widget_append(wb, w);
1421 we=gui_internal_box_new(this, gravity_left_center|orientation_horizontal|flags_fill);
1422 gui_internal_widget_append(w, we);
1423 gui_internal_widget_append(we, wk=gui_internal_label_new(this, wp->name ? wp->name : wp->text));
1424 wk->state |= STATE_EDIT|STATE_CLEAR;
1425 wk->background=this->background;
1426 wk->flags |= flags_expand|flags_fill;
1427 wk->func = gui_internal_cmd_add_bookmark_changed;
1429 gui_internal_widget_append(we, wnext=gui_internal_image_new(this, image_new_xs(this, "gui_active")));
1430 wnext->state |= STATE_SENSITIVE;
1431 wnext->func = gui_internal_cmd_add_bookmark_clicked;
1433 wl=gui_internal_box_new(this, gravity_left_top|orientation_vertical|flags_expand|flags_fill);
1434 gui_internal_widget_append(w, wl);
1436 gui_internal_widget_append(w, gui_internal_keyboard(this,2));
1437 gui_internal_menu_render(this);
1442 get_direction(char *buffer, int angle, int mode)
1447 sprintf(buffer,"%d",angle);
1450 if (angle < 69 || angle > 291)
1452 if (angle > 111 && angle < 249)
1454 if (angle > 22 && angle < 158)
1456 if (angle > 202 && angle < 338)
1461 angle=(angle+15)/30;
1464 sprintf(buffer,"%d H", angle);
1472 enum item_type *types;
1474 {"bank","Bank",(enum item_type []){type_poi_bank,type_poi_bank,type_none}},
1475 {"fuel","Fuel",(enum item_type []){type_poi_fuel,type_poi_fuel,type_none}},
1476 {"hotel","Hotel",(enum item_type []) {
1477 type_poi_hotel,type_poi_camp_rv,
1478 type_poi_camping,type_poi_camping,
1479 type_poi_resort,type_poi_resort,
1481 {"restaurant","Restaurant",(enum item_type []) {
1482 type_poi_bar,type_poi_picnic,
1483 type_poi_burgerking,type_poi_fastfood,
1484 type_poi_restaurant,type_poi_restaurant,
1486 {"shopping","Shopping",(enum item_type []) {
1487 type_poi_mall,type_poi_mall,
1488 type_poi_shop_grocery,type_poi_shop_grocery,
1490 {"hospital","Service",(enum item_type []) {
1491 type_poi_marina,type_poi_marina,
1492 type_poi_hospital,type_poi_hospital,
1493 type_poi_public_utilities,type_poi_public_utilities,
1494 type_poi_police,type_poi_autoservice,
1495 type_poi_information,type_poi_information,
1496 type_poi_personal_service,type_poi_repair_service,
1497 type_poi_rest_room,type_poi_rest_room,
1498 type_poi_restroom,type_poi_restroom,
1500 {"parking","Parking",(enum item_type []){type_poi_car_parking,type_poi_car_parking,type_none}},
1501 {"peak","Land Features",(enum item_type []){
1502 type_poi_land_feature,type_poi_rock,
1503 type_poi_dam,type_poi_dam,
1505 {"unknown","Other",(enum item_type []){
1506 type_point_unspecified,type_poi_land_feature-1,
1507 type_poi_rock+1,type_poi_fuel-1,
1508 type_poi_marina+1,type_poi_car_parking-1,
1509 type_poi_car_parking+1,type_poi_bar-1,
1510 type_poi_bank+1,type_poi_dam-1,
1511 type_poi_dam+1,type_poi_information-1,
1512 type_poi_information+1,type_poi_mall-1,
1513 type_poi_mall+1,type_poi_personal_service-1,
1514 type_poi_restaurant+1,type_poi_restroom-1,
1515 type_poi_restroom+1,type_poi_shop_grocery-1,
1516 type_poi_shop_grocery+1,type_poi_wifi,
1520 static void gui_internal_cmd_pois(struct gui_priv *this, struct widget *wm);
1522 static struct widget *
1523 gui_internal_cmd_pois_selector(struct gui_priv *this, struct pcoord *c)
1525 struct widget *wl,*wb;
1527 wl=gui_internal_box_new(this, gravity_left_center|orientation_horizontal|flags_fill);
1528 for (i = 0 ; i < sizeof(selectors)/sizeof(struct selector) ; i++) {
1529 gui_internal_widget_append(wl, wb=gui_internal_button_new_with_callback(this, NULL,
1530 image_new_xs(this, selectors[i].icon), gravity_center|orientation_vertical,
1531 gui_internal_cmd_pois, &selectors[i]));
1537 static struct widget *
1538 gui_internal_cmd_pois_item(struct gui_priv *this, struct coord *center, struct item *item, struct coord *c, int dist)
1546 wl=gui_internal_box_new(this, gravity_left_center|orientation_horizontal|flags_fill);
1548 sprintf(distbuf,"%d", dist/1000);
1549 gui_internal_widget_append(wl, gui_internal_label_new(this, distbuf));
1550 get_direction(dirbuf, transform_get_angle_delta(center, c, 0), 1);
1551 gui_internal_widget_append(wl, gui_internal_label_new(this, dirbuf));
1552 type=item_to_name(item->type);
1553 gui_internal_widget_append(wl, gui_internal_label_new(this, type));
1554 if (item_attr_get(item, attr_label, &attr)) {
1555 wl->name=g_strdup_printf("%s %s",type,attr.u.str);
1558 wl->name=g_strdup(type);
1560 gui_internal_widget_append(wl, gui_internal_label_new(this, attr.u.str));
1566 gui_internal_cmd_pois_sort_num(gconstpointer a, gconstpointer b, gpointer user_data)
1568 const struct widget *wa=a;
1569 const struct widget *wb=b;
1570 struct widget *wac=wa->children->data;
1571 struct widget *wbc=wb->children->data;
1580 gui_internal_cmd_pois_item_selected(struct selector *sel, enum item_type type)
1582 enum item_type *types;
1583 if (type >= type_line)
1585 if (! sel || !sel->types)
1588 while (*types != type_none) {
1589 if (type >= types[0] && type <= types[1]) {
1597 static void gui_internal_cmd_position(struct gui_priv *this, struct widget *wm);
1600 gui_internal_cmd_pois(struct gui_priv *this, struct widget *wm)
1602 struct map_selection *sel,*selm;
1603 struct coord c,center;
1604 struct mapset_handle *h;
1606 struct map_rect *mr;
1608 int idist,dist=4000;
1609 struct widget *wi,*w,*w2,*wb;
1610 enum projection pro=wm->c.pro;
1611 struct selector *isel=wm->data;
1613 wb=gui_internal_menu(this, isel ? isel->name : _("POIs"));
1614 w=gui_internal_box_new(this, gravity_top_center|orientation_vertical|flags_expand|flags_fill);
1615 gui_internal_widget_append(wb, w);
1617 gui_internal_widget_append(w, gui_internal_cmd_pois_selector(this,&wm->c));
1618 w2=gui_internal_box_new(this, gravity_top_center|orientation_vertical|flags_expand|flags_fill);
1619 gui_internal_widget_append(w, w2);
1621 sel=map_selection_rect_new(&wm->c, dist, 18);
1624 h=mapset_open(navit_get_mapset(this->nav));
1625 while ((m=mapset_next(h, 1))) {
1626 selm=map_selection_dup_pro(sel, pro, map_projection(m));
1627 mr=map_rect_new(m, selm);
1628 dbg(2,"mr=%p\n", mr);
1630 while ((item=map_rect_get_item(mr))) {
1631 if (gui_internal_cmd_pois_item_selected(isel, item->type) &&
1632 item_coord_get_pro(item, &c, 1, pro) &&
1633 coord_rect_contains(&sel->u.c_rect, &c) &&
1634 (idist=transform_distance(pro, ¢er, &c)) < dist) {
1635 gui_internal_widget_append(w2, wi=gui_internal_cmd_pois_item(this, ¢er, item, &c, idist));
1636 wi->func=gui_internal_cmd_position;
1637 wi->state |= STATE_SENSITIVE;
1643 map_rect_destroy(mr);
1645 map_selection_destroy(selm);
1647 map_selection_destroy(sel);
1649 w2->children=g_list_sort_with_data(w2->children, gui_internal_cmd_pois_sort_num, (void *)1);
1650 gui_internal_menu_render(this);
1654 gui_internal_cmd_view_on_map(struct gui_priv *this, struct widget *wm)
1656 struct widget *w=wm->data;
1657 navit_set_center(this->nav, &w->c);
1658 gui_internal_prune_menu(this, NULL);
1663 gui_internal_cmd_view_attributes(struct gui_priv *this, struct widget *wm)
1665 struct widget *w,*wb;
1666 struct map_rect *mr;
1671 dbg(0,"item=%p 0x%x 0x%x\n", wm->item.map,wm->item.id_hi, wm->item.id_lo);
1672 wb=gui_internal_menu(this, "Attributes");
1673 w=gui_internal_box_new(this, gravity_top_center|orientation_vertical|flags_expand|flags_fill);
1674 gui_internal_widget_append(wb, w);
1675 mr=map_rect_new(wm->item.map, NULL);
1676 item = map_rect_get_item_byid(mr, wm->item.id_hi, wm->item.id_lo);
1677 dbg(0,"item=%p\n", item);
1679 while(item_attr_get(item, attr_any, &attr)) {
1680 text=g_strdup_printf("%s:%s", attr_to_name(attr.type), attr_to_text(&attr, wm->item.map, 1));
1681 gui_internal_widget_append(w,
1682 wb=gui_internal_button_new_with_callback(this, text,
1683 NULL, gravity_left_center|orientation_horizontal|flags_fill,
1684 gui_internal_cmd_view_attributes, NULL));
1688 map_rect_destroy(mr);
1689 gui_internal_menu_render(this);
1693 gui_internal_cmd_view_in_browser(struct gui_priv *this, struct widget *wm)
1695 struct map_rect *mr;
1700 dbg(0,"item=%p 0x%x 0x%x\n", wm->item.map,wm->item.id_hi, wm->item.id_lo);
1701 mr=map_rect_new(wm->item.map, NULL);
1702 item = map_rect_get_item_byid(mr, wm->item.id_hi, wm->item.id_lo);
1703 dbg(0,"item=%p\n", item);
1705 while(item_attr_get(item, attr_url_local, &attr)) {
1707 cmd=g_strdup_printf("navit-browser.sh '%s' &",attr.u.str);
1710 map_rect_destroy(mr);
1715 dbg(0,"calling external cmd '%s' is not supported\n",cmd);
1721 /* wm->data: 0 Nothing special
1729 gui_internal_cmd_position(struct gui_priv *this, struct widget *wm)
1731 struct widget *wb,*w,*wc,*wbc;
1735 int display_attributes=(wm->data == (void *)2);
1736 int display_view_on_map=(wm->data != (void *)1);
1737 int display_items=(wm->data == (void *)1);
1738 int display_streets=(wm->data == (void *)3);
1739 if (wm->data == (void *)4) {
1740 gui_internal_search_town_in_country(this, wm);
1744 switch ((int)wm->data) {
1749 dbg(0,"x=0x%x y=0x%x\n", c.x, c.y);
1750 transform_to_geo(wm->c.pro, &c, &g);
1761 name=wm->name ? wm->name : wm->text;
1762 wb=gui_internal_menu(this, name);
1763 w=gui_internal_box_new(this, gravity_top_center|orientation_vertical|flags_expand|flags_fill);
1764 gui_internal_widget_append(wb, w);
1765 coord=coordinates(&wm->c, ' ');
1766 gui_internal_widget_append(w, gui_internal_label_new(this, coord));
1768 if (display_streets) {
1769 gui_internal_widget_append(w,
1770 wc=gui_internal_button_new_with_callback(this, _("Streets"),
1771 image_new_xs(this, "gui_active"), gravity_left_center|orientation_horizontal|flags_fill,
1772 gui_internal_search_street_in_town, wm));
1775 if (display_attributes) {
1776 struct map_rect *mr;
1779 mr=map_rect_new(wm->item.map, NULL);
1780 item = map_rect_get_item_byid(mr, wm->item.id_hi, wm->item.id_lo);
1782 if (item_attr_get(item, attr_description, &attr))
1783 gui_internal_widget_append(w, gui_internal_label_new(this, attr.u.str));
1784 if (item_attr_get(item, attr_url_local, &attr)) {
1785 gui_internal_widget_append(w,
1786 wb=gui_internal_button_new_with_callback(this, _("View in Browser"),
1787 image_new_xs(this, "gui_active"), gravity_left_center|orientation_horizontal|flags_fill,
1788 gui_internal_cmd_view_in_browser, NULL));
1791 gui_internal_widget_append(w,
1792 wb=gui_internal_button_new_with_callback(this, _("View Attributes"),
1793 image_new_xs(this, "gui_active"), gravity_left_center|orientation_horizontal|flags_fill,
1794 gui_internal_cmd_view_attributes, NULL));
1797 map_rect_destroy(mr);
1799 gui_internal_widget_append(w,
1800 gui_internal_button_new_with_callback(this, _("Set as destination"),
1801 image_new_xs(this, "gui_active"), gravity_left_center|orientation_horizontal|flags_fill,
1802 gui_internal_cmd_set_destination, wm));
1803 gui_internal_widget_append(w,
1804 gui_internal_button_new_with_callback(this, _("Set as position"),
1805 image_new_xs(this, "gui_active"), gravity_left_center|orientation_horizontal|flags_fill,
1806 gui_internal_cmd_set_position, wm));
1807 gui_internal_widget_append(w,
1808 wbc=gui_internal_button_new_with_callback(this, _("Add as bookmark"),
1809 image_new_xs(this, "gui_active"), gravity_left_center|orientation_horizontal|flags_fill,
1810 gui_internal_cmd_add_bookmark, wm));
1812 gui_internal_widget_append(w,
1813 wbc=gui_internal_button_new_with_callback(this, _("POIs"),
1814 image_new_xs(this, "gui_active"), gravity_left_center|orientation_horizontal|flags_fill,
1815 gui_internal_cmd_pois, NULL));
1818 gui_internal_widget_append(w,
1819 gui_internal_button_new(this, "Add to tour",
1820 image_new_o(this, "gui_active"), gravity_left_center|orientation_horizontal|flags_fill));
1821 gui_internal_widget_append(w,
1822 gui_internal_button_new(this, "Add as bookmark",
1823 image_new_o(this, "gui_active"), gravity_left_center|orientation_horizontal|flags_fill));
1825 if (display_view_on_map) {
1826 gui_internal_widget_append(w,
1827 gui_internal_button_new_with_callback(this, _("View on map"),
1828 image_new_xs(this, "gui_active"), gravity_left_center|orientation_horizontal|flags_fill,
1829 gui_internal_cmd_view_on_map, wm));
1831 if (display_items) {
1834 struct mapset_handle *h;
1835 struct map_rect *mr;
1838 struct street_data *data;
1839 struct map_selection sel;
1840 struct transformation *trans;
1841 enum projection pro;
1845 trans=navit_get_trans(this->nav);
1846 pro=transform_get_projection(trans);
1847 transform_from_geo(pro, &g, &c);
1848 ms=navit_get_mapset(this->nav);
1850 sel.u.c_rect.lu.x=c.x-dist;
1851 sel.u.c_rect.lu.y=c.y+dist;
1852 sel.u.c_rect.rl.x=c.x+dist;
1853 sel.u.c_rect.rl.y=c.y-dist;
1855 sel.range=item_range_all;
1857 while ((m=mapset_next(h,1))) {
1858 mr=map_rect_new(m, &sel);
1861 while ((item=map_rect_get_item(mr))) {
1862 data=street_get_data(item);
1863 if (transform_within_dist_item(&c, item->type, data->c, data->count, dist)) {
1864 if (item_attr_get(item, attr_label, &attr)) {
1865 label=map_convert_string(m, attr.u.str);
1866 text=g_strdup_printf("%s %s", item_to_name(item->type), label);
1867 map_convert_free(label);
1869 text=g_strdup_printf("%s", item_to_name(item->type));
1870 gui_internal_widget_append(w,
1871 wc=gui_internal_button_new_with_callback(this, text,
1872 image_new_xs(this, "gui_active"), gravity_left_center|orientation_horizontal|flags_fill,
1873 gui_internal_cmd_position, (void *)2));
1874 wc->c.x=data->c[0].x;
1875 wc->c.y=data->c[0].y;
1877 wc->name=g_strdup(text);
1881 street_data_free(data);
1883 map_rect_destroy(mr);
1888 gui_internal_menu_render(this);
1892 gui_internal_cmd_bookmarks(struct gui_priv *this, struct widget *wm)
1894 struct attr attr,mattr;
1895 struct map_rect *mr=NULL;
1897 char *label_full,*l,*prefix,*pos;
1898 int len,plen,hassub;
1899 struct widget *wb,*w,*wbm;
1904 wb=gui_internal_menu(this, wm->text ? wm->text : _("Bookmarks"));
1905 w=gui_internal_box_new(this, gravity_top_center|orientation_vertical|flags_expand|flags_fill);
1906 w->spy=this->spacing*3;
1907 gui_internal_widget_append(wb, w);
1912 plen=strlen(prefix);
1914 if(navit_get_attr(this->nav, attr_bookmark_map, &mattr, NULL) && mattr.u.map && (mr=map_rect_new(mattr.u.map, NULL))) {
1915 hash=g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
1916 while ((item=map_rect_get_item(mr))) {
1917 if (item->type != type_bookmark) continue;
1918 if (!item_attr_get(item, attr_label, &attr)) continue;
1919 label_full=attr.u.str;
1920 if (!strncmp(label_full, prefix, plen)) {
1921 pos=strchr(label_full+plen, '/');
1927 len=strlen(label_full);
1929 l=g_malloc(len-plen+1);
1930 strncpy(l, label_full+plen, len-plen);
1932 if (!g_hash_table_lookup(hash, l)) {
1933 wbm=gui_internal_button_new_with_callback(this, l,
1934 image_new_xs(this, hassub ? "gui_inactive" : "gui_active" ), gravity_left_center|orientation_horizontal|flags_fill,
1935 hassub ? gui_internal_cmd_bookmarks : gui_internal_cmd_position, NULL);
1936 if (item_coord_get(item, &c, 1)) {
1939 wbm->c.pro=map_projection(mattr.u.map);
1940 wbm->name=g_strdup_printf(_("Bookmark %s"),label_full);
1941 wbm->text=g_strdup(l);
1942 gui_internal_widget_append(w, wbm);
1943 g_hash_table_insert(hash, g_strdup(l), (void *)1);
1944 wbm->prefix=g_malloc(len+2);
1945 strncpy(wbm->prefix, label_full, len+1);
1946 wbm->prefix[len+1]='\0';
1948 gui_internal_widget_destroy(this, wbm);
1955 g_hash_table_destroy(hash);
1957 gui_internal_menu_render(this);
1960 static void gui_internal_keypress_do(struct gui_priv *this, char *key)
1962 struct widget *wi,*menu;
1966 menu=g_list_last(this->root.children)->data;
1967 wi=gui_internal_find_widget(menu, NULL, STATE_EDIT);
1969 if (*key == NAVIT_KEY_BACKSPACE) {
1970 if (wi->text && wi->text[0]) {
1971 len=g_utf8_prev_char(wi->text+strlen(wi->text))-wi->text;
1973 text=g_strdup_printf("%s ", wi->text);
1976 if (wi->state & STATE_CLEAR) {
1977 dbg(0,"wi->state=0x%x\n", wi->state);
1980 wi->state &= ~STATE_CLEAR;
1981 dbg(0,"wi->state=0x%x\n", wi->state);
1983 text=g_strdup_printf("%s%s", wi->text ? wi->text : "", key);
1987 if (*key == NAVIT_KEY_BACKSPACE && wi->text) {
1988 gui_internal_widget_render(this, wi);
1995 gui_internal_widget_render(this, wi);
2001 gui_internal_cmd_keypress(struct gui_priv *this, struct widget *wm)
2003 struct menu_data *md=gui_internal_menu_data(this);
2004 gui_internal_keypress_do(this, (char *) wm->data);
2005 if (md->keyboard_mode == 2)
2006 gui_internal_keyboard_do(this, md->keyboard, 10);
2010 gui_internal_search_idle_end(struct gui_priv *this)
2013 event_remove_idle(this->idle);
2016 if (this->idle_cb) {
2017 callback_destroy(this->idle_cb);
2023 gui_internal_search_idle(struct gui_priv *this, char *wm_name, struct widget *search_list, void *param)
2025 char *text=NULL,*name=NULL;
2026 struct search_list_result *res;
2030 res=search_list_get_result(this->sl);
2032 gui_internal_search_idle_end(this);
2036 if (! strcmp(wm_name,"Country")) {
2037 name=res->country->name;
2038 text=g_strdup_printf("%s", res->country->name);
2040 if (! strcmp(wm_name,"Town")) {
2041 name=res->town->name;
2042 text=g_strdup(name);
2044 if (! strcmp(wm_name,"Street")) {
2045 name=res->street->name;
2046 text=g_strdup_printf("%s %s", res->town->name, res->street->name);
2049 dbg(0,"res=%s\n", res->town->name);
2051 gui_internal_widget_append(search_list,
2052 wc=gui_internal_button_new_with_callback(this, text,
2053 image_new_xs(this, res->country->flag), gravity_left_center|orientation_horizontal|flags_fill,
2054 gui_internal_cmd_position, param));
2056 wc->name=g_strdup(name);
2059 wc->item.id_lo=res->id;
2060 gui_internal_widget_pack(this, search_list);
2061 l=g_list_last(this->root.children);
2062 graphics_draw_mode(this->gra, draw_mode_begin);
2063 gui_internal_widget_render(this, l->data);
2064 graphics_draw_mode(this->gra, draw_mode_end);
2068 gui_internal_search_idle_start(struct gui_priv *this, char *wm_name, struct widget *search_list, void *param)
2070 this->idle_cb=callback_new_4(callback_cast(gui_internal_search_idle), this, wm_name, search_list, param);
2071 this->idle=event_add_idle(50,this->idle_cb);
2072 callback_call_0(this->idle_cb);
2077 gui_internal_search_changed(struct gui_priv *this, struct widget *wm)
2080 struct widget *search_list=gui_internal_menu_data(this)->search_list;
2081 gui_internal_widget_children_destroy(this, search_list);
2083 void *param=(void *)3;
2084 if (! strcmp(wm->name,"Country")) {
2088 dbg(0,"%s now '%s'\n", wm->name, wm->text);
2090 gui_internal_search_idle_end(this);
2091 if (wm->text && g_utf8_strlen(wm->text, -1) >= minlen) {
2092 struct attr search_attr;
2095 if (! strcmp(wm->name,"Country"))
2096 search_attr.type=attr_country_all;
2097 if (! strcmp(wm->name,"Town"))
2098 search_attr.type=attr_town_name;
2099 if (! strcmp(wm->name,"Street"))
2100 search_attr.type=attr_street_name;
2101 search_attr.u.str=wm->text;
2102 search_list_search(this->sl, &search_attr, 1);
2103 gui_internal_search_idle_start(this, wm->name, search_list, param);
2105 l=g_list_last(this->root.children);
2106 gui_internal_widget_render(this, l->data);
2109 static struct widget *
2110 gui_internal_keyboard_key_data(struct gui_priv *this, struct widget *wkbd, char *text, void(*func)(struct gui_priv *priv, struct widget *widget), void *data, void (*data_free)(void *data))
2114 gui_internal_widget_append(wkbd, wk=gui_internal_button_new_with_callback(this, text,
2115 NULL, gravity_center|orientation_vertical, func, data));
2116 wk->data_free=data_free;
2117 wk->background=this->background;
2125 static struct widget *
2126 gui_internal_keyboard_key(struct gui_priv *this, struct widget *wkbd, char *text, char *key)
2128 return gui_internal_keyboard_key_data(this, wkbd, text, gui_internal_cmd_keypress, g_strdup(key), g_free);
2131 static void gui_internal_keyboard_change(struct gui_priv *this, struct widget *key);
2133 static struct widget *
2134 gui_internal_keyboard_do(struct gui_priv *this, struct widget *wkbdb, int mode)
2136 struct widget *wkbd,*wk;
2137 struct menu_data *md=gui_internal_menu_data(this);
2142 gui_internal_highlight(this, NULL);
2144 gui_internal_widget_children_destroy(this, wkbdb);
2146 wkbdb=gui_internal_box_new(this, gravity_center|orientation_horizontal_vertical|flags_fill);
2148 md->keyboard_mode=mode;
2149 wkbd=gui_internal_box_new(this, gravity_center|orientation_horizontal_vertical|flags_fill);
2150 wkbd->background=this->background;
2154 if (mode >= 0 && mode < 8) {
2155 for (i = 0 ; i < 26 ; i++) {
2156 char text[]={'A'+i,'\0'};
2157 gui_internal_keyboard_key(this, wkbd, text, text);
2159 gui_internal_keyboard_key(this, wkbd, "_"," ");
2161 gui_internal_keyboard_key(this, wkbd, "-","-");
2162 gui_internal_keyboard_key(this, wkbd, "'","'");
2163 gui_internal_keyboard_key_data(this, wkbd, "", NULL, NULL, NULL);
2165 gui_internal_keyboard_key_data(this, wkbd, "", NULL, NULL, NULL);
2166 wk=gui_internal_keyboard_key_data(this, wkbd, "a", gui_internal_keyboard_change, wkbd, NULL);
2168 wk=gui_internal_keyboard_key_data(this, wkbd, "1", gui_internal_keyboard_change, wkbd, NULL);
2171 wk=gui_internal_keyboard_key_data(this, wkbd, "Ä",gui_internal_keyboard_change, wkbdb,NULL);
2173 gui_internal_keyboard_key(this, wkbd, "<-","\b");
2175 if (mode >= 8 && mode < 16) {
2176 for (i = 0 ; i < 26 ; i++) {
2177 char text[]={'a'+i,'\0'};
2178 gui_internal_keyboard_key(this, wkbd, text, text);
2180 gui_internal_keyboard_key(this, wkbd, "_"," ");
2182 gui_internal_keyboard_key(this, wkbd, "-","-");
2183 gui_internal_keyboard_key(this, wkbd, "'","'");
2184 gui_internal_keyboard_key_data(this, wkbd, "", NULL, NULL, NULL);
2186 gui_internal_keyboard_key_data(this, wkbd, "", NULL, NULL, NULL);
2187 wk=gui_internal_keyboard_key_data(this, wkbd, "A", gui_internal_keyboard_change, wkbd, NULL);
2189 wk=gui_internal_keyboard_key_data(this, wkbd, "1", gui_internal_keyboard_change, wkbd, NULL);
2192 wk=gui_internal_keyboard_key_data(this, wkbd, "ä",gui_internal_keyboard_change,wkbdb,NULL);
2194 gui_internal_keyboard_key(this, wkbd, "<-","\b");
2196 if (mode >= 16 && mode < 24) {
2197 for (i = 0 ; i < 10 ; i++) {
2198 char text[]={'0'+i,'\0'};
2199 gui_internal_keyboard_key(this, wkbd, text, text);
2201 gui_internal_keyboard_key(this, wkbd, ".",".");
2202 gui_internal_keyboard_key(this, wkbd, "°","°");
2203 gui_internal_keyboard_key(this, wkbd, "'","'");
2204 gui_internal_keyboard_key(this, wkbd, "\"","\"");
2205 gui_internal_keyboard_key(this, wkbd, "-","-");
2206 gui_internal_keyboard_key(this, wkbd, "+","+");
2207 gui_internal_keyboard_key(this, wkbd, "*","*");
2208 gui_internal_keyboard_key(this, wkbd, "/","/");
2209 gui_internal_keyboard_key(this, wkbd, "(","(");
2210 gui_internal_keyboard_key(this, wkbd, ")",")");
2211 gui_internal_keyboard_key(this, wkbd, "=","=");
2212 gui_internal_keyboard_key(this, wkbd, "?","?");
2213 for (i = 0 ; i < 5 ; i++) {
2214 gui_internal_keyboard_key_data(this, wkbd, "", NULL, NULL, NULL);
2217 gui_internal_keyboard_key(this, wkbd, "-","-");
2218 gui_internal_keyboard_key(this, wkbd, "'","'");
2219 gui_internal_keyboard_key_data(this, wkbd, "", NULL, NULL, NULL);
2221 gui_internal_keyboard_key_data(this, wkbd, "", NULL, NULL, NULL);
2222 wk=gui_internal_keyboard_key_data(this, wkbd, "A", gui_internal_keyboard_change, wkbd, NULL);
2224 wk=gui_internal_keyboard_key_data(this, wkbd, "a", gui_internal_keyboard_change, wkbd, NULL);
2227 wk=gui_internal_keyboard_key_data(this, wkbd, "Ä",gui_internal_keyboard_change,wkbdb,NULL);
2229 gui_internal_keyboard_key(this, wkbd, "<-","\b");
2231 if (mode >= 24 && mode < 32) {
2232 gui_internal_keyboard_key(this, wkbd, "Ä","Ä");
2233 gui_internal_keyboard_key(this, wkbd, "Ö","Ö");
2234 gui_internal_keyboard_key(this, wkbd, "Ü","Ü");
2235 for (i = 0 ; i < 27 ; i++) {
2236 gui_internal_keyboard_key_data(this, wkbd, "", NULL, NULL, NULL);
2238 wk=gui_internal_keyboard_key_data(this, wkbd, "A",gui_internal_keyboard_change,wkbdb,NULL);
2240 gui_internal_keyboard_key(this, wkbd, "<-","\b");
2242 if (mode >= 32 && mode < 40) {
2243 gui_internal_keyboard_key(this, wkbd, "ä","ä");
2244 gui_internal_keyboard_key(this, wkbd, "ö","ö");
2245 gui_internal_keyboard_key(this, wkbd, "ü","ü");
2246 for (i = 0 ; i < 27 ; i++) {
2247 gui_internal_keyboard_key_data(this, wkbd, "", NULL, NULL, NULL);
2249 wk=gui_internal_keyboard_key_data(this, wkbd, "a",gui_internal_keyboard_change,wkbdb,NULL);
2251 gui_internal_keyboard_key(this, wkbd, "<-","\b");
2253 gui_internal_widget_append(wkbdb, wkbd);
2255 gui_internal_widget_pack(this, wkbdb);
2256 gui_internal_widget_render(this, wkbdb);
2261 static struct widget *
2262 gui_internal_keyboard(struct gui_priv *this, int mode)
2264 return gui_internal_keyboard_do(this, NULL, mode);
2268 gui_internal_keyboard_change(struct gui_priv *this, struct widget *key)
2270 gui_internal_keyboard_do(this, key->data, key->datai);
2274 gui_internal_search_list_set_default_country(struct gui_priv *this)
2276 struct attr search_attr, country_name, country_iso2, *country_attr;
2278 struct country_search *cs;
2279 struct tracking *tracking;
2280 struct search_list_result *res;
2282 country_attr=country_default();
2283 tracking=navit_get_tracking(this->nav);
2284 if (tracking && tracking_get_current_attr(tracking, attr_country_id, &search_attr))
2285 country_attr=&search_attr;
2287 cs=country_search_new(country_attr, 0);
2288 item=country_search_get_item(cs);
2289 if (item && item_attr_get(item, attr_country_name, &country_name)) {
2290 search_attr.type=attr_country_all;
2291 dbg(0,"country %s\n", country_name.u.str);
2292 search_attr.u.str=country_name.u.str;
2293 search_list_search(this->sl, &search_attr, 0);
2294 while((res=search_list_get_result(this->sl)));
2295 g_free(this->country_iso2);
2296 if (item_attr_get(item, attr_country_iso2, &country_iso2))
2297 this->country_iso2=g_strdup(country_iso2.u.str);
2299 country_search_destroy(cs);
2301 dbg(0,"warning: no default country found\n");
2306 gui_internal_search_list_new(struct gui_priv *this)
2308 struct mapset *ms=navit_get_mapset(this->nav);
2310 this->sl=search_list_new(ms);
2311 gui_internal_search_list_set_default_country(this);
2316 gui_internal_search_list_destroy(struct gui_priv *this)
2319 search_list_destroy(this->sl);
2326 gui_internal_search(struct gui_priv *this, char *what, char *type, int flags)
2328 struct widget *wb,*wk,*w,*wr,*we,*wl,*wnext=NULL;
2330 gui_internal_search_list_new(this);
2331 wb=gui_internal_menu(this, what);
2332 w=gui_internal_box_new(this, gravity_center|orientation_vertical|flags_expand|flags_fill);
2333 gui_internal_widget_append(wb, w);
2334 wr=gui_internal_box_new(this, gravity_top_center|orientation_vertical|flags_expand|flags_fill);
2335 gui_internal_widget_append(w, wr);
2336 we=gui_internal_box_new(this, gravity_left_center|orientation_horizontal|flags_fill);
2337 gui_internal_widget_append(wr, we);
2339 if (!strcmp(type,"Country")) {
2340 wnext=gui_internal_image_new(this, image_new_xs(this, "gui_select_town"));
2341 wnext->func=gui_internal_search_town;
2342 } else if (!strcmp(type,"Town")) {
2343 if (this->country_iso2)
2344 country=g_strdup_printf("country_%s", this->country_iso2);
2346 country=strdup("gui_select_country");
2347 gui_internal_widget_append(we, wb=gui_internal_image_new(this, image_new_xs(this, country)));
2348 wb->state |= STATE_SENSITIVE;
2350 wb->func = gui_internal_search_country;
2352 wb->func = gui_internal_back;
2353 wnext=gui_internal_image_new(this, image_new_xs(this, "gui_select_street"));
2354 wnext->func=gui_internal_search_street;
2356 } else if (!strcmp(type,"Street")) {
2357 gui_internal_widget_append(we, wb=gui_internal_image_new(this, image_new_xs(this, "gui_select_town")));
2358 wb->state |= STATE_SENSITIVE;
2359 wb->func = gui_internal_back;
2361 gui_internal_widget_append(we, wk=gui_internal_label_new(this, NULL));
2363 gui_internal_widget_append(we, wnext);
2364 wnext->state |= STATE_SENSITIVE;
2366 wl=gui_internal_box_new(this, gravity_left_top|orientation_vertical|flags_expand|flags_fill);
2367 gui_internal_widget_append(wr, wl);
2368 gui_internal_menu_data(this)->search_list=wl;
2369 wk->state |= STATE_EDIT;
2370 wk->background=this->background;
2371 wk->flags |= flags_expand|flags_fill;
2372 wk->func = gui_internal_search_changed;
2373 wk->name=g_strdup(type);
2375 gui_internal_widget_append(w, gui_internal_keyboard(this,0));
2376 gui_internal_menu_render(this);
2380 gui_internal_search_street(struct gui_priv *this, struct widget *widget)
2382 search_list_select(this->sl, attr_town_name, 0, 0);
2383 gui_internal_search(this,_("Street"),"Street",0);
2387 gui_internal_search_street_in_town(struct gui_priv *this, struct widget *widget)
2389 dbg(0,"id %d\n", widget->item.id_lo);
2390 search_list_select(this->sl, attr_town_name, 0, 0);
2391 search_list_select(this->sl, attr_town_name, widget->item.id_lo, 1);
2392 gui_internal_search(this,_("Street"),"Street",0);
2396 gui_internal_search_town(struct gui_priv *this, struct widget *wm)
2399 search_list_select(this->sl, attr_country_all, 0, 0);
2400 g_free(this->country_iso2);
2401 this->country_iso2=NULL;
2402 gui_internal_search(this,_("Town"),"Town",0);
2406 gui_internal_search_town_in_country(struct gui_priv *this, struct widget *widget)
2408 struct search_list_common *slc;
2409 dbg(0,"id %d\n", widget->item.id_lo);
2410 search_list_select(this->sl, attr_country_all, 0, 0);
2411 slc=search_list_select(this->sl, attr_country_all, widget->item.id_lo, 1);
2413 g_free(this->country_iso2);
2414 this->country_iso2=((struct search_list_country *)slc)->iso2;
2416 gui_internal_search(this,widget->name,"Town",0);
2420 gui_internal_search_country(struct gui_priv *this, struct widget *widget)
2422 gui_internal_prune_menu_count(this, 1, 0);
2423 gui_internal_search(this,_("Country"),"Country",0);
2427 gui_internal_cmd_town(struct gui_priv *this, struct widget *wm)
2430 search_list_select(this->sl, attr_country_all, 0, 0);
2431 gui_internal_search(this,_("Town"),"Town",1);
2435 gui_internal_cmd_layout(struct gui_priv *this, struct widget *wm)
2438 struct widget *w,*wb,*wl;
2439 struct attr_iter *iter;
2442 wb=gui_internal_menu(this, _("Layout"));
2443 w=gui_internal_box_new(this, gravity_top_center|orientation_vertical|flags_expand|flags_fill);
2444 w->spy=this->spacing*3;
2445 gui_internal_widget_append(wb, w);
2446 iter=navit_attr_iter_new();
2447 while(navit_get_attr(this->nav, attr_layout, &attr, iter)) {
2448 wl=gui_internal_button_navit_attr_new(this, attr.u.layout->name, gravity_left_center|orientation_horizontal|flags_fill,
2450 gui_internal_widget_append(w, wl);
2452 navit_attr_iter_destroy(iter);
2453 gui_internal_menu_render(this);
2457 gui_internal_cmd_fullscreen(struct gui_priv *this, struct widget *wm)
2459 this->fullscreen=!this->fullscreen;
2460 this->win->fullscreen(this->win, this->fullscreen);
2465 gui_internal_cmd_display(struct gui_priv *this, struct widget *wm)
2469 w=gui_internal_menu(this, _("Display"));
2470 gui_internal_widget_append(w,
2471 gui_internal_button_new_with_callback(this, _("Layout"),
2472 image_new_l(this, "gui_display"), gravity_center|orientation_vertical,
2473 gui_internal_cmd_layout, NULL));
2474 if (this->fullscreen) {
2475 gui_internal_widget_append(w,
2476 gui_internal_button_new_with_callback(this, _("Window Mode"),
2477 image_new_l(this, "gui_leave_fullscreen"), gravity_center|orientation_vertical,
2478 gui_internal_cmd_fullscreen, NULL));
2480 gui_internal_widget_append(w,
2481 gui_internal_button_new_with_callback(this, _("Fullscreen"),
2482 image_new_l(this, "gui_fullscreen"), gravity_center|orientation_vertical,
2483 gui_internal_cmd_fullscreen, NULL));
2485 gui_internal_menu_render(this);
2489 gui_internal_cmd_quit(struct gui_priv *this, struct widget *wm)
2491 struct navit *nav=this->nav;
2493 main_remove_navit(nav);
2497 gui_internal_cmd_abort_navigation(struct gui_priv *this, struct widget *wm)
2499 navit_set_destination(this->nav, NULL, NULL);
2504 gui_internal_cmd_actions(struct gui_priv *this, struct widget *wm)
2506 struct widget *w,*wc;
2509 w=gui_internal_menu(this, _("Actions"));
2510 gui_internal_widget_append(w,
2511 gui_internal_button_new_with_callback(this, _("Bookmarks"),
2512 image_new_l(this, "gui_bookmark"), gravity_center|orientation_vertical,
2513 gui_internal_cmd_bookmarks, NULL));
2514 if (this->clickp_valid) {
2515 coord=coordinates(&this->clickp, '\n');
2516 gui_internal_widget_append(w,
2517 wc=gui_internal_button_new_with_callback(this, coord,
2518 image_new_l(this, "gui_map"), gravity_center|orientation_vertical,
2519 gui_internal_cmd_position, (void *)1));
2520 wc->name=g_strdup(_("Map Point"));
2524 if (this->vehicle_valid) {
2525 coord=coordinates(&this->vehiclep, '\n');
2526 gui_internal_widget_append(w,
2527 wc=gui_internal_button_new_with_callback(this, coord,
2528 image_new_l(this, "gui_rules"), gravity_center|orientation_vertical,
2529 gui_internal_cmd_position, NULL));
2530 wc->name=g_strdup(_("Vehicle Position"));
2531 wc->c=this->vehiclep;
2534 gui_internal_widget_append(w,
2535 gui_internal_button_new_with_callback(this, _("Town"),
2536 image_new_l(this, "gui_rules"), gravity_center|orientation_vertical,
2537 gui_internal_cmd_town, NULL));
2538 gui_internal_widget_append(w,
2539 gui_internal_button_new_with_callback(this, _("Quit"),
2540 image_new_l(this, "gui_quit"), gravity_center|orientation_vertical,
2541 gui_internal_cmd_quit, NULL));
2543 if (navit_check_route(this->nav)) {
2544 gui_internal_widget_append(w,
2545 gui_internal_button_new_with_callback(this, _("Stop\nNavigation"),
2546 image_new_l(this, "gui_stop"), gravity_center|orientation_vertical,
2547 gui_internal_cmd_abort_navigation, NULL));
2549 gui_internal_menu_render(this);
2553 gui_internal_cmd_maps(struct gui_priv *this, struct widget *wm)
2555 struct attr attr, on, off, description, type, data;
2556 struct widget *w,*wb,*wma;
2558 struct attr_iter *iter;
2561 wb=gui_internal_menu(this, _("Maps"));
2562 w=gui_internal_box_new(this, gravity_top_center|orientation_vertical|flags_expand|flags_fill);
2563 w->spy=this->spacing*3;
2564 gui_internal_widget_append(wb, w);
2565 iter=navit_attr_iter_new();
2566 on.type=off.type=attr_active;
2569 while(navit_get_attr(this->nav, attr_map, &attr, iter)) {
2570 if (map_get_attr(attr.u.map, attr_description, &description, NULL)) {
2571 label=g_strdup(description.u.str);
2573 if (!map_get_attr(attr.u.map, attr_type, &type, NULL))
2575 if (!map_get_attr(attr.u.map, attr_data, &data, NULL))
2577 label=g_strdup_printf("%s:%s", type.u.str, data.u.str);
2579 wma=gui_internal_button_map_attr_new(this, label, gravity_left_center|orientation_horizontal|flags_fill,
2580 attr.u.map, &on, &off, 1);
2581 gui_internal_widget_append(w, wma);
2584 navit_attr_iter_destroy(iter);
2585 gui_internal_menu_render(this);
2590 gui_internal_cmd_vehicle(struct gui_priv *this, struct widget *wm)
2592 struct attr attr,vattr;
2593 struct widget *w,*wb,*wl;
2594 struct attr_iter *iter;
2597 wb=gui_internal_menu(this, _("Vehicle"));
2598 w=gui_internal_box_new(this, gravity_top_center|orientation_vertical|flags_expand|flags_fill);
2599 w->spy=this->spacing*3;
2600 gui_internal_widget_append(wb, w);
2601 iter=navit_attr_iter_new();
2602 while(navit_get_attr(this->nav, attr_vehicle, &attr, iter)) {
2603 vehicle_get_attr(attr.u.vehicle, attr_name, &vattr, NULL);
2604 wl=gui_internal_button_navit_attr_new(this, vattr.u.str, gravity_left_center|orientation_horizontal|flags_fill,
2606 gui_internal_widget_append(w, wl);
2608 navit_attr_iter_destroy(iter);
2609 gui_internal_menu_render(this);
2614 gui_internal_cmd_rules(struct gui_priv *this, struct widget *wm)
2616 struct widget *wb,*w;
2618 wb=gui_internal_menu(this, _("Rules"));
2619 w=gui_internal_box_new(this, gravity_top_center|orientation_vertical|flags_expand|flags_fill);
2620 w->spy=this->spacing*3;
2621 gui_internal_widget_append(wb, w);
2624 on.type=off.type=attr_tracking;
2625 gui_internal_widget_append(w,
2626 gui_internal_button_navit_attr_new(this, _("Lock on road"), gravity_left_center|orientation_horizontal|flags_fill,
2630 on.type=off.type=attr_orientation;
2631 gui_internal_widget_append(w,
2632 gui_internal_button_navit_attr_new(this, _("Northing"), gravity_left_center|orientation_horizontal|flags_fill,
2636 on.type=off.type=attr_cursor;
2637 gui_internal_widget_append(w,
2638 gui_internal_button_navit_attr_new(this, _("Map follows Vehicle"), gravity_left_center|orientation_horizontal|flags_fill,
2640 gui_internal_menu_render(this);
2644 gui_internal_cmd_settings(struct gui_priv *this, struct widget *wm)
2648 w=gui_internal_menu(this, _("Settings"));
2649 gui_internal_widget_append(w,
2650 gui_internal_button_new_with_callback(this, _("Display"),
2651 image_new_l(this, "gui_display"), gravity_center|orientation_vertical,
2652 gui_internal_cmd_display, NULL));
2653 gui_internal_widget_append(w,
2654 gui_internal_button_new_with_callback(this, _("Maps"),
2655 image_new_l(this, "gui_maps"), gravity_center|orientation_vertical,
2656 gui_internal_cmd_maps, NULL));
2657 gui_internal_widget_append(w,
2658 gui_internal_button_new_with_callback(this, _("Vehicle"),
2659 image_new_l(this, "gui_sound"), gravity_center|orientation_vertical,
2660 gui_internal_cmd_vehicle, NULL));
2661 gui_internal_widget_append(w,
2662 gui_internal_button_new_with_callback(this, _("Rules"),
2663 image_new_l(this, "gui_rules"), gravity_center|orientation_vertical,
2664 gui_internal_cmd_rules, NULL));
2665 gui_internal_menu_render(this);
2668 //##############################################################################################################
2671 //# Authors: Martin Schaller (04/2008)
2672 //##############################################################################################################
2673 static void gui_internal_motion(void *data, struct point *p)
2675 struct gui_priv *this=data;
2676 if (!this->root.children) {
2677 navit_handle_motion(this->nav, p);
2682 graphics_draw_mode(this->gra, draw_mode_begin);
2683 gui_internal_highlight(this, p);
2684 graphics_draw_mode(this->gra, draw_mode_end);
2689 static void gui_internal_menu_root(struct gui_priv *this)
2693 graphics_draw_mode(this->gra, draw_mode_begin);
2694 w=gui_internal_menu(this, _("Main menu"));
2695 w->spx=this->spacing*10;
2696 gui_internal_widget_append(w, gui_internal_button_new_with_callback(this, _("Actions"),
2697 image_new_l(this, "gui_actions"), gravity_center|orientation_vertical,
2698 gui_internal_cmd_actions, NULL));
2699 gui_internal_widget_append(w, gui_internal_button_new_with_callback(this, _("Settings"),
2700 image_new_l(this, "gui_settings"), gravity_center|orientation_vertical,
2701 gui_internal_cmd_settings, NULL));
2702 gui_internal_widget_append(w, gui_internal_button_new(this, _("Tools"),
2703 image_new_l(this, "gui_tools"), gravity_center|orientation_vertical));
2705 gui_internal_widget_append(w, gui_internal_button_new_with_callback(this, "Table Test",
2706 image_new_l(this, "gui_settings"), gravity_center|orientation_vertical,
2707 gui_internal_cmd_route, NULL));
2710 gui_internal_menu_render(this);
2711 graphics_draw_mode(this->gra, draw_mode_end);
2715 gui_internal_cmd_menu(struct gui_priv *this, struct point *p, int ignore)
2717 struct graphics *gra=this->gra;
2718 struct transformation *trans;
2720 struct attr attr,attrp;
2722 this->ignore_button=ignore;
2723 this->clickp_valid=this->vehicle_valid=0;
2725 navit_block(this->nav, 1);
2726 graphics_overlay_disable(gra, 1);
2727 trans=navit_get_trans(this->nav);
2729 transform_reverse(trans, p, &c);
2730 dbg(0,"x=0x%x y=0x%x\n", c.x, c.y);
2731 this->clickp.pro=transform_get_projection(trans);
2734 this->clickp_valid=1;
2736 if (navit_get_attr(this->nav, attr_vehicle, &attr, NULL) && attr.u.vehicle
2737 && vehicle_get_attr(attr.u.vehicle, attr_position_coord_geo, &attrp, NULL)) {
2738 this->vehiclep.pro=transform_get_projection(trans);
2739 transform_from_geo(this->vehiclep.pro, attrp.u.coord_geo, &c);
2740 this->vehiclep.x=c.x;
2741 this->vehiclep.y=c.y;
2742 this->vehicle_valid=1;
2747 this->root.background=this->background;
2748 gui_internal_menu_root(this);
2752 gui_internal_check_exit(struct gui_priv *this)
2754 struct graphics *gra=this->gra;
2755 if (! this->root.children) {
2756 gui_internal_search_idle_end(this);
2757 gui_internal_search_list_destroy(this);
2758 graphics_overlay_disable(gra, 0);
2759 if (!navit_block(this->nav, 0)) {
2761 navit_draw(this->nav);
2763 navit_draw_displaylist(this->nav);
2768 //##############################################################################################################
2769 //# Description: Function to handle mouse clicks and scroll wheel movement
2771 //# Authors: Martin Schaller (04/2008), Stefan Klumpp (04/2008)
2772 //##############################################################################################################
2773 static void gui_internal_button(void *data, int pressed, int button, struct point *p)
2775 struct gui_priv *this=data;
2776 struct graphics *gra=this->gra;
2778 // if still on the map (not in the menu, yet):
2779 if (!this->root.children || this->ignore_button) {
2780 this->ignore_button=0;
2781 // check whether the position of the mouse changed during press/release OR if it is the scrollwheel
2782 if (!navit_handle_button(this->nav, pressed, button, p, NULL) || button >=4) // Maybe there's a better way to do this
2784 if (this->menu_on_map_click)
2785 gui_internal_cmd_menu(this, p, 0);
2789 // if already in the menu:
2792 graphics_draw_mode(gra, draw_mode_begin);
2793 gui_internal_highlight(this, p);
2794 graphics_draw_mode(gra, draw_mode_end);
2797 graphics_draw_mode(gra, draw_mode_begin);
2798 gui_internal_call_highlighted(this);
2799 gui_internal_highlight(this, NULL);
2800 graphics_draw_mode(gra, draw_mode_end);
2801 gui_internal_check_exit(this);
2805 //##############################################################################################################
2808 //# Authors: Martin Schaller (04/2008)
2809 //##############################################################################################################
2810 static void gui_internal_resize(void *data, int w, int h)
2812 struct gui_priv *this=data;
2815 dbg(1,"w=%d h=%d children=%p\n", w, h, this->root.children);
2816 navit_handle_resize(this->nav, w, h);
2817 if (this->root.children) {
2818 gui_internal_prune_menu(this, NULL);
2819 gui_internal_menu_root(this);
2824 gui_internal_keynav_point(struct widget *w, int dx, int dy, struct point *p)
2839 gui_internal_keynav_find_closest(struct widget *wi, struct point *p, int dx, int dy, int *distance, struct widget **result)
2841 GList *l=wi->children;
2842 if (wi->state & STATE_SENSITIVE) {
2845 gui_internal_keynav_point(wi, -dx, -dy, &wp);
2847 dist1=(wp.x-p->x)*dx;
2850 dist1=(wp.y-p->y)*dy;
2858 dbg(1,"checking %d,%d %d %d against %d,%d-%d,%d result %d,%d\n", p->x, p->y, dx, dy, wi->p.x, wi->p.y, wi->p.x+wi->w, wi->p.y+wi->h, dist1, dist2);
2864 if (dist1 < *distance) {
2871 struct widget *child=l->data;
2872 gui_internal_keynav_find_closest(child, p, dx, dy, distance, result);
2878 gui_internal_keynav_highlight_next(struct gui_priv *this, int dx, int dy)
2880 struct widget *result,*menu=g_list_last(this->root.children)->data;
2883 if (this->highlighted && this->highlighted_menu == g_list_last(this->root.children)->data)
2884 gui_internal_keynav_point(this->highlighted, dx, dy, &p);
2890 gui_internal_keynav_find_closest(menu, &p, 0, 0, &distance, &result);
2892 gui_internal_keynav_point(result, dx, dy, &p);
2893 dbg(1,"result origin=%p p=%d,%d\n", result, p.x, p.y);
2898 gui_internal_keynav_find_closest(menu, &p, dx, dy, &distance, &result);
2899 dbg(1,"result=%p\n", result);
2911 gui_internal_keynav_find_closest(menu, &p, dx, dy, &distance, &result);
2912 dbg(1,"wraparound result=%p\n", result);
2914 gui_internal_highlight_do(this, result);
2916 gui_internal_say(this, result, 1);
2919 //##############################################################################################################
2922 //# Authors: Martin Schaller (04/2008)
2923 //##############################################################################################################
2924 static void gui_internal_keypress(void *data, char *key)
2926 struct gui_priv *this=data;
2929 if (!this->root.children) {
2930 transform_get_size(navit_get_trans(this->nav), &w, &h);
2935 navit_set_center_screen(this->nav, &p);
2937 case NAVIT_KEY_DOWN:
2940 navit_set_center_screen(this->nav, &p);
2942 case NAVIT_KEY_LEFT:
2945 navit_set_center_screen(this->nav, &p);
2947 case NAVIT_KEY_RIGHT:
2950 navit_set_center_screen(this->nav, &p);
2952 case NAVIT_KEY_ZOOM_IN:
2953 navit_zoom_in(this->nav, 2, NULL);
2955 case NAVIT_KEY_ZOOM_OUT:
2956 navit_zoom_out(this->nav, 2, NULL);
2958 case NAVIT_KEY_RETURN:
2959 gui_internal_cmd_menu(this, NULL, 0);
2964 graphics_draw_mode(this->gra, draw_mode_begin);
2966 case NAVIT_KEY_LEFT:
2967 gui_internal_keynav_highlight_next(this,-1,0);
2969 case NAVIT_KEY_RIGHT:
2970 gui_internal_keynav_highlight_next(this,1,0);
2973 gui_internal_keynav_highlight_next(this,0,-1);
2975 case NAVIT_KEY_DOWN:
2976 gui_internal_keynav_highlight_next(this,0,1);
2978 case NAVIT_KEY_RETURN:
2979 if (this->highlighted && this->highlighted_menu == g_list_last(this->root.children)->data)
2980 gui_internal_call_highlighted(this);
2982 gui_internal_keypress_do(this, key);
2985 gui_internal_keypress_do(this, key);
2987 graphics_draw_mode(this->gra, draw_mode_end);
2988 gui_internal_check_exit(this);
2992 //##############################################################################################################
2995 //# Authors: Martin Schaller (04/2008)
2996 //##############################################################################################################
2997 static int gui_internal_set_graphics(struct gui_priv *this, struct graphics *gra)
3001 struct color cb={0x7fff,0x7fff,0x7fff,0xffff};
3003 struct color cb={0x0,0x0,0x0,0xffff};
3004 struct color cb2={0x4141,0x4141,0x4141,0xffff};
3005 struct color cbh={0x9fff,0x9fff,0x9fff,0xffff};
3006 struct color cf={0xbfff,0xbfff,0xbfff,0xffff};
3007 struct color cw={0xffff,0xffff,0xffff,0xffff};
3008 struct transformation *trans=navit_get_trans(this->nav);
3010 win=graphics_get_data(gra, "window");
3015 transform_get_size(trans, &this->root.w, &this->root.h);
3016 this->resize_cb=callback_new_attr_1(callback_cast(gui_internal_resize), attr_resize, this);
3017 graphics_add_callback(gra, this->resize_cb);
3018 this->button_cb=callback_new_attr_1(callback_cast(gui_internal_button), attr_button, this);
3019 graphics_add_callback(gra, this->button_cb);
3020 this->motion_cb=callback_new_attr_1(callback_cast(gui_internal_motion), attr_motion, this);
3021 graphics_add_callback(gra, this->motion_cb);
3022 this->keypress_cb=callback_new_attr_1(callback_cast(gui_internal_keypress), attr_keypress, this);
3023 graphics_add_callback(gra, this->keypress_cb);
3024 this->background=graphics_gc_new(gra);
3025 graphics_gc_set_foreground(this->background, &cb);
3026 this->background2=graphics_gc_new(gra);
3027 graphics_gc_set_foreground(this->background2, &cb2);
3028 this->highlight_background=graphics_gc_new(gra);
3029 graphics_gc_set_foreground(this->highlight_background, &cbh);
3030 this->foreground=graphics_gc_new(gra);
3031 graphics_gc_set_foreground(this->foreground, &cf);
3032 this->text_background=graphics_gc_new(gra);
3033 graphics_gc_set_foreground(this->text_background, &cb);
3034 this->text_foreground=graphics_gc_new(gra);
3035 graphics_gc_set_foreground(this->text_foreground, &cw);
3039 //##############################################################################################################
3042 //# Authors: Martin Schaller (04/2008)
3043 //##############################################################################################################
3044 struct gui_methods gui_internal_methods = {
3047 gui_internal_set_graphics,
3050 //##############################################################################################################
3053 //# Authors: Martin Schaller (04/2008)
3054 //##############################################################################################################
3055 static struct gui_priv * gui_internal_new(struct navit *nav, struct gui_methods *meth, struct attr **attrs)
3057 struct gui_priv *this;
3059 *meth=gui_internal_methods;
3060 navit_ignore_graphics_events(nav, 1);
3061 this=g_new0(struct gui_priv, 1);
3063 if ((attr=attr_search(attrs, NULL, attr_menu_on_map_click)))
3064 this->menu_on_map_click=attr->u.num;
3066 this->menu_on_map_click=1;
3067 navit_command_register(nav,"gui_internal_menu",callback_new_3(callback_cast(gui_internal_cmd_menu),this,NULL,(void *)1));
3068 navit_command_register(nav,"gui_internal_fullscreen",callback_new_2(callback_cast(gui_internal_cmd_fullscreen),this,NULL));
3070 if( (attr=attr_search(attrs,NULL,attr_font_size)))
3072 this->config.font_size=attr->u.num;
3076 this->config.font_size=-1;
3078 if( (attr=attr_search(attrs,NULL,attr_icon_xs)))
3080 this->config.icon_xs=attr->u.num;
3084 this->config.icon_xs=-1;
3086 if( (attr=attr_search(attrs,NULL,attr_icon_l)))
3088 this->config.icon_l=attr->u.num;
3092 this->config.icon_l=-1;
3094 if( (attr=attr_search(attrs,NULL,attr_icon_s)))
3096 this->config.icon_s=attr->u.num;
3100 this->config.icon_s=-1;
3102 if( (attr=attr_search(attrs,NULL,attr_spacing)))
3104 this->config.spacing=attr->u.num;
3108 this->config.spacing=-1;
3110 if( (attr=attr_search(attrs,NULL,attr_gui_speech)))
3112 this->speech=attr->u.num;
3114 if( (attr=attr_search(attrs,NULL,attr_keyboard)))
3115 this->keyboard=attr->u.num;
3123 //##############################################################################################################
3126 //# Authors: Martin Schaller (04/2008)
3127 //##############################################################################################################
3128 void plugin_init(void)
3130 plugin_register_gui_type("internal", gui_internal_new);
3134 * @brief Creates a new table widget.
3136 * Creates and returns a new table widget. This function will
3137 * setup next/previous buttons as children.
3139 * @param this The graphics context.
3140 * @param flags widget sizing flags.
3141 * @returns The newly created widget
3143 struct widget * gui_internal_widget_table_new(struct gui_priv * this, enum flags flags)
3145 struct widget * widget = g_new0(struct widget,1);
3146 struct table_data * data = NULL;
3147 widget->type=widget_table;
3148 widget->flags=flags;
3149 widget->data = g_new0(struct table_data,1);
3150 widget->data_free=gui_internal_table_data_free;
3151 data = (struct table_data*)widget->data;
3154 data->next_button = gui_internal_button_new_with_callback
3155 (this,"Next",image_new_xs(this, "gui_active") ,
3156 gravity_left_center |orientation_vertical,
3157 gui_internal_table_button_next,NULL);
3158 data->next_button->data=widget;
3161 data->prev_button = gui_internal_button_new_with_callback
3163 image_new_xs(this, "gui_active")
3164 ,gravity_right_center |orientation_vertical,
3165 gui_internal_table_button_prev,NULL);
3167 data->prev_button->data=widget;
3171 data->button_box=gui_internal_box_new(this,
3172 gravity_center|orientation_horizontal);
3173 data->button_box->children=g_list_append(data->button_box->children,
3175 data->button_box->children=g_list_append(data->button_box->children,
3177 data->button_box->background=this->background2;
3178 data->button_box->bl=this->spacing;
3179 widget->children=g_list_append(widget->children,data->button_box);
3180 gui_internal_widget_pack(this,data->button_box);
3188 * @brief Adds a row to a table_widget.
3190 * @param table The table to add the row to.
3191 * @param row A table_row widget that will be added to the table.
3193 void gui_internal_widget_table_add_row(struct widget * table, struct widget * row)
3195 table->children=g_list_append(table->children,row);
3200 * Creates a new table_row widget.
3201 * @param this The graphics context
3202 * @param flags Sizing flags for the row
3203 * @returns The new table_row widget.
3205 static struct widget * gui_internal_widget_table_row_new(struct gui_priv * this, enum flags flags)
3207 struct widget * widget = g_new0(struct widget,1);
3208 widget->type=widget_table_row;
3209 widget->flags=flags;
3216 * @brief Computes the column dimensions for the table.
3218 * @param w The table widget to compute dimensions for.
3220 * This function examines all of the rows and columns for the table w
3221 * and returns a list (GList) of table_column_desc elements that
3222 * describe each column of the table.
3224 * The caller is responsible for freeing the returned list.
3226 static GList * gui_internal_compute_table_dimensions(struct widget * w)
3229 GList * column_desc = NULL;
3230 GList * current_desc=NULL;
3231 GList * cur_row = w->children;
3232 struct widget * cur_row_widget=NULL;
3233 GList * cur_column=NULL;
3234 struct widget * cell_w=NULL;
3235 struct table_column_desc * current_cell=NULL;
3236 struct table_data * table_data=NULL;
3242 * Scroll through the the table and
3243 * 1. Compute the maximum width + height of each column across all rows.
3245 table_data = (struct table_data*) w->data;
3246 for(cur_row=w->children; cur_row ; cur_row = g_list_next(cur_row) )
3248 cur_row_widget = (struct widget*) cur_row->data;
3249 current_desc = column_desc;
3250 if(cur_row_widget == table_data->button_box)
3254 for(cur_column = cur_row_widget->children; cur_column;
3255 cur_column=g_list_next(cur_column))
3257 cell_w = (struct widget*) cur_column->data;
3258 if(current_desc == 0)
3260 current_cell = g_new0(struct table_column_desc,1);
3261 column_desc = g_list_append(column_desc,current_cell);
3262 current_desc = g_list_last(column_desc);
3263 current_cell->height=cell_w->h;
3264 current_cell->width=cell_w->w;
3269 current_cell = current_desc->data;
3272 if(current_cell->height < height )
3274 current_cell->height = height;
3276 if(current_cell->width < width)
3278 current_cell->width = width;
3280 current_desc = g_list_next(current_desc);
3291 * @brief Computes the height and width for the table.
3293 * The height and widht are computed to display all cells in the table
3294 * at the requested height/width.
3296 * @param this The graphics context
3297 * @param w The widget to pack.
3300 void gui_internal_table_pack(struct gui_priv * this, struct widget * w)
3306 GList * column_data = gui_internal_compute_table_dimensions(w);
3308 struct table_column_desc * cell_desc=0;
3309 struct table_data * table_data = (struct table_data*)w->data;
3311 for(current = column_data; current; current=g_list_next(current))
3313 if(table_data->button_box == current->data )
3317 cell_desc = (struct table_column_desc *) current->data;
3318 width = width + cell_desc->width + this->spacing;
3319 if(height < cell_desc->height)
3321 height = cell_desc->height ;
3325 for(current=w->children; current; current=g_list_next(current))
3327 if(current->data!= table_data->button_box)
3332 gui_internal_widget_pack(this,table_data->button_box);
3333 w->h = count * (height+this->spacing) + table_data->button_box + this->spacing;
3335 if(w->h + w->c.y > this->root.h )
3338 * Do not allow the widget to exceed the screen.
3341 w->h = this->root.h- w->c.y - height;
3346 * Deallocate column descriptions.
3348 current = column_data;
3349 while( (current = g_list_last(current)) )
3351 current = g_list_remove(current,current->data);
3359 * @brief Renders a table widget.
3361 * @param this The graphics context
3362 * @param w The table widget to render.
3364 void gui_internal_table_render(struct gui_priv * this, struct widget * w)
3369 GList * column_desc=NULL;
3370 GList * cur_row = NULL;
3371 GList * current_desc=NULL;
3372 struct table_data * table_data = (struct table_data*)w->data;
3374 struct table_column_desc * dim=NULL;
3376 column_desc = gui_internal_compute_table_dimensions(w);
3381 * Skip rows that are on previous pages.
3383 cur_row = w->children;
3384 if(table_data->top_row )
3386 cur_row = table_data->top_row;
3391 * Loop through each row. Drawing each cell with the proper sizes,
3392 * at the proper positions.
3394 for(table_data->top_row=cur_row; cur_row; cur_row = g_list_next(cur_row))
3396 GList * cur_column=NULL;
3397 current_desc = column_desc;
3398 struct widget * cur_row_widget = (struct widget*)cur_row->data;
3400 x =w->p.x+this->spacing;
3401 if(cur_row_widget == table_data->button_box )
3405 dim = (struct table_column_desc*)current_desc->data;
3407 if( y + dim->height + table_data->button_box->h + this->spacing >= w->p.y + w->h )
3410 * No more drawing space left.
3416 for(cur_column = cur_row_widget->children; cur_column;
3417 cur_column=g_list_next(cur_column))
3419 struct widget * cur_widget = (struct widget*) cur_column->data;
3420 dim = (struct table_column_desc*)current_desc->data;
3423 cur_widget->w=dim->width;
3425 cur_widget->h=dim->height;
3427 max_height = dim->height;
3428 gui_internal_widget_render(this,cur_widget);
3430 if(dim->height > max_height)
3432 max_height = dim->height;
3436 table_data->bottom_row=cur_row;
3437 current_desc = g_list_next(current_desc);
3439 if(table_data && table_data->button_box )
3441 table_data->button_box->p.y =w->p.y+w->h-table_data->button_box->h -
3443 if(table_data->button_box->p.y < y )
3445 table_data->button_box->p.y=y;
3447 table_data->button_box->p.x = w->p.x;
3448 table_data->button_box->w = w->w;
3449 // table_data->button_box->h = w->h - y;
3450 // table_data->next_button->h=table_data->button_box->h;
3451 // table_data->prev_button->h=table_data->button_box->h;
3452 // table_data->next_button->c.y=table_data->button_box->c.y;
3453 // table_data->prev_button->c.y=table_data->button_box->c.y;
3455 gui_internal_widget_pack(this,table_data->button_box);
3456 if(table_data->next_button->p.y > w->p.y + w->h + table_data->next_button->h)
3459 table_data->button_box->p.y = w->p.y + w->h -
3460 table_data->button_box->h;
3464 table_data->next_button->state|= STATE_SENSITIVE;
3468 table_data->next_button->state&= ~STATE_SENSITIVE;
3471 if(table_data->top_row != w->children)
3473 table_data->prev_button->state|= STATE_SENSITIVE;
3477 table_data->prev_button->state&= ~STATE_SENSITIVE;
3479 gui_internal_widget_render(this,table_data->button_box);
3485 * Deallocate column descriptions.
3487 current_desc = column_desc;
3488 while( (current_desc = g_list_last(current_desc)) )
3490 current_desc = g_list_remove(current_desc,current_desc->data);
3496 * TEST function for demonstrating table.
3498 void gui_internal_cmd_route(struct gui_priv * this, struct widget * wm)
3502 struct widget * menu;
3507 w = gui_internal_widget_table_new(this,gravity_center | orientation_vertical);
3509 for(idx=0; idx < 52; idx++)
3511 struct widget * row = gui_internal_widget_table_row_new
3512 (this,gravity_left_top);
3513 sprintf(buffer, "Test %d",idx);
3514 row->children = g_list_append(row->children,
3515 gui_internal_label_new(this,buffer));
3516 row->children= g_list_append(row->children,
3517 gui_internal_label_new(this,"column 2 4 6 8"));
3518 gui_internal_widget_table_add_row(w,row);
3520 menu=gui_internal_menu(this,"Route");
3521 gui_internal_widget_append(menu,w);
3522 gui_internal_menu_render(this);
3529 * @brief handles the 'next page' table event.
3530 * A callback function that is invoked when the 'next page' button is pressed
3531 * to advance the contents of a table widget.
3533 * @param this The graphics context.
3534 * @param wm The button widget that was pressed.
3536 static void gui_internal_table_button_next(struct gui_priv * this, struct widget * wm)
3538 struct widget * table_widget = (struct widget * ) wm->data;
3539 struct table_data * table_data = NULL;
3545 table_data = (struct table_data*) table_widget->data;
3551 * Before advancing to the next page we need to ensure
3552 * that the current top_row is in the list of previous top_rows
3553 * so previous page can work.
3556 for(iterator=table_data->page_headers; iterator != NULL;
3557 iterator = g_list_next(iterator) )
3559 if(iterator->data == table_data->top_row)
3568 table_data->page_headers=g_list_append(table_data->page_headers,
3569 table_data->top_row);
3572 table_data->top_row = g_list_next(table_data->bottom_row);
3574 wm->state&= ~STATE_HIGHLIGHTED;
3575 gui_internal_menu_render(this);
3581 * @brief handles the 'previous page' table event.
3582 * A callback function that is invoked when the 'previous page' button is pressed
3583 * to go back in the contents of a table widget.
3585 * @param this The graphics context.
3586 * @param wm The button widget that was pressed.
3588 static void gui_internal_table_button_prev(struct gui_priv * this, struct widget * wm)
3590 struct widget * table_widget = (struct widget * ) wm->data;
3591 struct table_data * table_data = NULL;
3592 GList * current_page_top=NULL;
3597 table_data = (struct table_data*) table_widget->data;
3598 current_page_top = table_data->top_row;
3601 for(iterator = table_data->page_headers; iterator != NULL;
3602 iterator = g_list_next(iterator))
3604 if(current_page_top == iterator->data)
3608 table_data->top_row = (GList*) iterator->data;
3612 wm->state&= ~STATE_HIGHLIGHTED;
3613 gui_internal_menu_render(this);
3618 * @brief deallocates a table_data structure.
3621 void gui_internal_table_data_free(void * p)
3626 * @note button_box and its children (next_button,prev_button)
3627 * have their memory managed by the table itself.
3629 struct table_data * table_data = (struct table_data*) p;
3630 g_list_free(table_data->page_headers);