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 //##############################################################################################################
46 #include "transform.h"
62 #include "navit_nls.h"
63 #include "gui_internal.h"
66 struct widget *search_list;
67 struct widget *keyboard;
68 struct widget *button_bar;
72 //##############################################################################################################
75 //# Authors: Martin Schaller (04/2008)
76 //##############################################################################################################
78 enum widget_type type;
79 struct graphics_gc *background,*text_background;
80 struct graphics_gc *foreground_frame;
81 struct graphics_gc *foreground;
83 struct graphics_image *img;
85 * A function to be invoked on actions.
86 * @li widget The widget that is receiving the button press.
89 void (*func)(struct gui_priv *priv, struct widget *widget, void *data);
93 void (*data_free)(void *data);
104 int bl,br,bt,bb,spx,spy;
109 int (*set_attr)(void *, struct attr *);
110 int (*get_attr)(void *, enum attr_type, struct attr *, struct attr_iter *);
111 void (*remove_cb)(void *, struct callback *cb);
118 struct menu_data *menu_data;
123 * @brief A structure to store configuration values.
125 * This structure stores configuration values for how gui elements in the internal GUI
128 struct gui_config_settings {
131 * The base size (in fractions of a point) to use for text.
135 * The size (in pixels) that xs style icons should be scaled to.
139 * The size (in pixels) that s style icons (small) should be scaled to
143 * The size (in pixels) that l style icons should be scaled to
147 * The default amount of spacing (in pixels) to place between GUI elements.
154 * Indexes into the config_profiles array.
156 const int LARGE_PROFILE=0;
157 const int MEDIUM_PROFILE=1;
158 const int SMALL_PROFILE=2;
161 * The default config profiles.
163 * [0] => LARGE_PROFILE (screens 640 in one dimension)
164 * [1] => MEDIUM PROFILE (screens larger than 320 in one dimension
165 * [2] => Small profile (default)
167 static struct gui_config_settings config_profiles[]={
173 //##############################################################################################################
176 //# Authors: Martin Schaller (04/2008)
177 //##############################################################################################################
181 struct graphics *gra;
182 struct graphics_gc *background;
183 struct graphics_gc *background2;
184 struct graphics_gc *highlight_background;
185 struct graphics_gc *foreground;
186 struct graphics_gc *text_foreground;
187 struct graphics_gc *text_background;
188 struct color background_color, background2_color, text_foreground_color, text_background_color;
192 struct graphics_font *font;
193 int icon_xs, icon_s, icon_l;
195 struct widget *widgets;
199 struct widget *highlighted;
200 struct widget *highlighted_menu;
201 int clickp_valid, vehicle_valid;
202 struct pcoord clickp, vehiclep;
203 struct search_list *sl;
205 int menu_on_map_click;
210 * The setting information read from the configuration file.
211 * values of -1 indicate no value was specified in the config file.
213 struct gui_config_settings config;
214 struct event_idle *idle;
215 struct callback *motion_cb,*button_cb,*resize_cb,*keypress_cb,*idle_cb, *motion_timeout_callback;
216 struct event_timeout *motion_timeout_event;
217 struct point current;
218 struct gui_internal_data data;
219 struct callback_list *cbl;
226 * @brief A structure to store information about a table.
228 * The table_data widget stores pointers to extra information needed by the
231 * The table_data structure needs to be freed with data_free along with the widget.
237 * A GList pointer into a widget->children list that indicates the row
238 * currently being rendered at the top of the table.
242 * A Glist pointer into a widget->children list that indicates the row
243 * currently being rendered at the bottom of the table.
248 * A list of table_row widgets that mark the
249 * top rows for each page of the table.
250 * This is needed for the 'previous page' function of the table.
252 GList * page_headers;
255 * A container box that is the child of the table widget that contains+groups
256 * the next and previous button.
258 struct widget * button_box;
261 * A button widget to handle 'next page' requests
263 struct widget * next_button;
265 * A button widget to handle 'previous page' requests.
267 struct widget * prev_button;
271 * a pointer to the gui context.
272 * This is needed by the free function to destory the buttons.
274 struct gui_priv * this;
278 * A data structure that holds information about a column that makes up a table.
282 struct table_column_desc
286 * The computed height of a cell in the table.
291 * The computed width of a cell in the table.
296 static void gui_internal_widget_render(struct gui_priv *this, struct widget *w);
297 static void gui_internal_widget_pack(struct gui_priv *this, struct widget *w);
298 static struct widget * gui_internal_box_new(struct gui_priv *this, enum flags flags);
299 static void gui_internal_widget_append(struct widget *parent, struct widget *child);
300 static void gui_internal_widget_destroy(struct gui_priv *this, struct widget *w);
301 static void gui_internal_apply_config(struct gui_priv *this);
303 static struct widget* gui_internal_widget_table_new(struct gui_priv * this, enum flags flags);
304 static void gui_internal_widget_table_add_row(struct widget * table, struct widget * row);
305 static void gui_internal_table_render(struct gui_priv * this, struct widget * w);
306 static void gui_internal_cmd_route(struct gui_priv * this, struct widget * w);
307 static void gui_internal_table_pack(struct gui_priv * this, struct widget * w);
308 static void gui_internal_table_button_next(struct gui_priv * this, struct widget * wm, void *data);
309 static void gui_internal_table_button_prev(struct gui_priv * this, struct widget * wm, void *data);
310 static void gui_internal_table_data_free(void * d);
312 static void gui_internal_search_idle_end(struct gui_priv *this);
313 static void gui_internal_search(struct gui_priv *this, char *what, char *type, int flags);
314 static void gui_internal_search_street(struct gui_priv *this, struct widget *widget, void *data);
315 static void gui_internal_search_street_in_town(struct gui_priv *this, struct widget *widget, void *data);
316 static void gui_internal_search_town(struct gui_priv *this, struct widget *wm, void *data);
317 static void gui_internal_search_town_in_country(struct gui_priv *this, struct widget *wm);
318 static void gui_internal_search_country(struct gui_priv *this, struct widget *widget, void *data);
320 static struct widget *gui_internal_keyboard_do(struct gui_priv *this, struct widget *wkbdb, int mode);
321 static struct menu_data * gui_internal_menu_data(struct gui_priv *this);
323 static struct graphics_image *
324 image_new_scaled(struct gui_priv *this, char *name, int w, int h)
326 struct graphics_image *ret=NULL;
327 char *full_name=NULL;
330 for (i = 1 ; i < 6 ; i++) {
334 full_name=g_strdup_printf("%s/xpm/%s.svg", getenv("NAVIT_SHAREDIR"), name);
337 full_name=g_strdup_printf("%s/xpm/%s.svgz", getenv("NAVIT_SHAREDIR"), name);
340 if (w != -1 && h != -1) {
341 full_name=g_strdup_printf("%s/xpm/%s_%d_%d.png", getenv("NAVIT_SHAREDIR"), name, w, h);
345 full_name=g_strdup_printf("%s/xpm/%s.png", getenv("NAVIT_SHAREDIR"), name);
348 full_name=g_strdup_printf("%s/xpm/%s.xpm", getenv("NAVIT_SHAREDIR"), name);
351 dbg(1,"trying '%s'\n", full_name);
354 if (!file_exists(full_name)) {
358 ret=graphics_image_new_scaled(this->gra, full_name, w, h);
359 dbg(1,"ret=%p\n", ret);
364 dbg(0,"failed to load %s with %d,%d\n", name, w, h);
369 static struct graphics_image *
370 image_new_o(struct gui_priv *this, char *name)
372 return image_new_scaled(this, name, -1, -1);
375 static struct graphics_image *
376 image_new_xs(struct gui_priv *this, char *name)
378 return image_new_scaled(this, name, this->icon_xs, this->icon_xs);
382 static struct graphics_image *
383 image_new_s(struct gui_priv *this, char *name)
385 return image_new_scaled(this, name, this->icon_s, this->icon_s);
388 static struct graphics_image *
389 image_new_l(struct gui_priv *this, char *name)
391 return image_new_scaled(this, name, this->icon_l, this->icon_l);
395 coordinates(struct pcoord *pc, char sep)
397 char latc='N',lngc='E';
398 int lat_deg,lat_min,lat_sec;
399 int lng_deg,lng_min,lng_sec;
404 transform_to_geo(pc->pro, &c, &g);
415 lat_min=fmod(g.lat*60,60);
416 lat_sec=fmod(g.lat*3600,60);
418 lng_min=fmod(g.lng*60,60);
419 lng_sec=fmod(g.lng*3600,60);
420 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);
424 gui_internal_background_render(struct gui_priv *this, struct widget *w)
426 struct point pnt=w->p;
427 if (w->state & STATE_HIGHLIGHTED)
428 graphics_draw_rectangle(this->gra, this->highlight_background, &pnt, w->w, w->h);
431 graphics_draw_rectangle(this->gra, w->background, &pnt, w->w, w->h);
434 static struct widget *
435 gui_internal_label_new(struct gui_priv *this, char *text)
441 struct widget *widget=g_new0(struct widget, 1);
442 widget->type=widget_label;
444 widget->text=g_strdup(text);
445 graphics_get_text_bbox(this->gra, this->font, text, 0x10000, 0x0, p, 0);
449 widget->h=h+this->spacing;
451 widget->w=w+this->spacing;
453 widget->flags=gravity_center;
454 widget->foreground=this->text_foreground;
455 widget->text_background=this->text_background;
460 static struct widget *
461 gui_internal_label_new_abbrev(struct gui_priv *this, char *text, int maxwidth)
463 struct widget *ret=NULL;
464 char *tmp=g_malloc(strlen(text)+3);
471 ret=gui_internal_label_new(this, tmp);
472 if (ret->w < maxwidth)
474 gui_internal_widget_destroy(this, ret);
482 static struct widget *
483 gui_internal_image_new(struct gui_priv *this, struct graphics_image *image)
485 struct widget *widget=g_new0(struct widget, 1);
486 widget->type=widget_image;
489 widget->w=image->width;
490 widget->h=image->height;
496 gui_internal_image_render(struct gui_priv *this, struct widget *w)
500 gui_internal_background_render(this, w);
503 pnt.x+=w->w/2-w->img->hot.x;
504 pnt.y+=w->h/2-w->img->hot.y;
505 graphics_draw_image(this->gra, this->foreground, &pnt, w->img);
510 gui_internal_label_render(struct gui_priv *this, struct widget *w)
512 struct point pnt=w->p;
513 gui_internal_background_render(this, w);
515 if (w->flags & gravity_right) {
516 pnt.y+=w->h-this->spacing;
517 pnt.x+=w->w-w->textw-this->spacing;
518 graphics_draw_text(this->gra, w->foreground, w->text_background, this->font, w->text, &pnt, 0x10000, 0x0);
520 pnt.y+=w->h-this->spacing;
521 graphics_draw_text(this->gra, w->foreground, w->text_background, this->font, w->text, &pnt, 0x10000, 0x0);
526 static struct widget *
527 gui_internal_text_new(struct gui_priv *this, char *text)
529 char *s=g_strdup(text),*s2,*tok;
530 struct widget *ret=gui_internal_box_new(this, gravity_center|orientation_vertical);
532 while ((tok=strtok(s2,"\n"))) {
533 gui_internal_widget_append(ret, gui_internal_label_new(this, tok));
540 static struct widget *
541 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), void *data)
543 struct widget *ret=NULL;
544 ret=gui_internal_box_new(this, flags);
547 gui_internal_widget_append(ret, gui_internal_image_new(this, image));
549 gui_internal_widget_append(ret, gui_internal_text_new(this, text));
553 ret->state |= STATE_SENSITIVE;
554 ret->speech=g_strdup(text);
562 gui_internal_button_attr_update(struct gui_priv *this, struct widget *w)
569 if (w->get_attr(w->instance, w->on.type, &curr, NULL))
570 is_on=curr.u.data == w->on.u.data;
573 if (is_on != w->is_on) {
577 l=g_list_first(w->children);
581 graphics_image_free(this->gra, wi->img);
582 wi->img=image_new_xs(this, is_on ? "gui_active" : "gui_inactive");
584 if (w->is_on && w->off.type == attr_none)
585 w->state &= ~STATE_SENSITIVE;
587 w->state |= STATE_SENSITIVE;
594 gui_internal_button_attr_callback(struct gui_priv *this, struct widget *w)
596 if (gui_internal_button_attr_update(this, w))
597 gui_internal_widget_render(this, w);
600 gui_internal_button_attr_pressed(struct gui_priv *this, struct widget *w, void *data)
603 w->set_attr(w->instance, &w->off);
605 w->set_attr(w->instance, &w->on);
606 gui_internal_button_attr_update(this, w);
610 static struct widget *
611 gui_internal_button_navit_attr_new(struct gui_priv *this, char *text, enum flags flags, struct attr *on, struct attr *off)
613 struct graphics_image *image=image_new_xs(this, "gui_inactive");
615 ret=gui_internal_button_new_with_callback(this, text, image, flags, gui_internal_button_attr_pressed, NULL);
620 ret->get_attr=(int (*)(void *, enum attr_type, struct attr *, struct attr_iter *))navit_get_attr;
621 ret->set_attr=(int (*)(void *, struct attr *))navit_set_attr;
622 ret->remove_cb=(void (*)(void *, struct callback *))navit_remove_callback;
623 ret->instance=this->nav;
624 ret->cb=callback_new_attr_2(callback_cast(gui_internal_button_attr_callback), on->type, this, ret);
625 navit_add_callback(this->nav, ret->cb);
626 gui_internal_button_attr_update(this, ret);
630 static struct widget *
631 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)
633 struct graphics_image *image=image_new_xs(this, "gui_inactive");
635 ret=gui_internal_button_new_with_callback(this, text, image, flags, gui_internal_button_attr_pressed, NULL);
641 ret->get_attr=(int (*)(void *, enum attr_type, struct attr *, struct attr_iter *))map_get_attr;
642 ret->set_attr=(int (*)(void *, struct attr *))map_set_attr;
643 ret->remove_cb=(void (*)(void *, struct callback *))map_remove_callback;
646 ret->cb=callback_new_attr_2(callback_cast(gui_internal_button_attr_callback), on->type, this, ret);
647 map_add_callback(map, ret->cb);
648 gui_internal_button_attr_update(this, ret);
652 static struct widget *
653 gui_internal_button_new(struct gui_priv *this, char *text, struct graphics_image *image, enum flags flags)
655 return gui_internal_button_new_with_callback(this, text, image, flags, NULL, NULL);
658 //##############################################################################################################
661 //# Authors: Martin Schaller (04/2008)
662 //##############################################################################################################
663 static void gui_internal_clear(struct gui_priv *this)
665 struct graphics *gra=this->gra;
669 graphics_draw_rectangle(gra, this->background, &pnt, this->root.w, this->root.h);
672 static struct widget *
673 gui_internal_find_widget(struct widget *wi, struct point *p, int flags)
675 struct widget *ret,*child;
676 GList *l=wi->children;
683 if ( wi->p.x + wi->w < p->x)
685 if ( wi->p.y + wi->h < p->y)
688 if (wi->state & flags)
692 ret=gui_internal_find_widget(child, p, flags);
703 gui_internal_highlight_do(struct gui_priv *this, struct widget *found)
705 if (found == this->highlighted)
708 graphics_draw_mode(this->gra, draw_mode_begin);
709 if (this->highlighted) {
710 this->highlighted->state &= ~STATE_HIGHLIGHTED;
711 if (this->root.children && this->highlighted_menu == g_list_last(this->root.children)->data)
712 gui_internal_widget_render(this, this->highlighted);
713 this->highlighted=NULL;
714 this->highlighted_menu=NULL;
717 this->highlighted=found;
718 this->highlighted_menu=g_list_last(this->root.children)->data;
719 this->highlighted->state |= STATE_HIGHLIGHTED;
720 gui_internal_widget_render(this, this->highlighted);
721 dbg(1,"%d,%d %dx%d\n", found->p.x, found->p.y, found->w, found->h);
723 graphics_draw_mode(this->gra, draw_mode_end);
725 //##############################################################################################################
728 //# Authors: Martin Schaller (04/2008)
729 //##############################################################################################################
730 static void gui_internal_highlight(struct gui_priv *this)
732 struct widget *menu,*found=NULL;
733 if (this->current.x > -1 && this->current.y > -1) {
734 menu=g_list_last(this->root.children)->data;
735 found=gui_internal_find_widget(menu, &this->current, STATE_SENSITIVE);
737 gui_internal_highlight_do(this, found);
738 this->motion_timeout_event=NULL;
741 static struct widget *
742 gui_internal_box_new_with_label(struct gui_priv *this, enum flags flags, char *label)
744 struct widget *widget=g_new0(struct widget, 1);
747 widget->text=g_strdup(label);
748 widget->type=widget_box;
753 static struct widget *
754 gui_internal_box_new(struct gui_priv *this, enum flags flags)
756 return gui_internal_box_new_with_label(this, flags, NULL);
760 static void gui_internal_box_render(struct gui_priv *this, struct widget *w)
765 gui_internal_background_render(this, w);
767 if (w->foreground && w->border) {
770 pnt[1].x=pnt[0].x+w->w;
772 pnt[2].x=pnt[0].x+w->w;
773 pnt[2].y=pnt[0].y+w->h;
775 pnt[3].y=pnt[0].y+w->h;
777 graphics_gc_set_linewidth(w->foreground, w->border ? w->border : 1);
778 graphics_draw_lines(this->gra, w->foreground, pnt, 5);
779 graphics_gc_set_linewidth(w->foreground, 1);
786 gui_internal_widget_render(this, wc);
791 static void gui_internal_box_pack(struct gui_priv *this, struct widget *w)
794 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 : 0;
796 int orientation=w->flags & 0xffff0000;
801 height=navit_get_height(this->nav);
802 width=navit_get_width(this->nav);
803 if ( (height/width) > 1.0 )
817 if (orientation == orientation_horizontal_vertical && count <= cols)
818 orientation=orientation_horizontal;
819 switch (orientation) {
820 case orientation_horizontal:
824 gui_internal_widget_pack(this, wc);
828 if (wc->flags & flags_expand)
829 expand+=wc->w ? wc->w : 1;
835 if (expand && w->w) {
836 expand=100*(w->w-width+expand)/expand;
841 case orientation_vertical:
845 gui_internal_widget_pack(this, wc);
849 if (wc->flags & flags_expand)
850 expand+=wc->h ? wc->h : 1;
856 if (expand && w->h) {
857 expand=100*(w->h-height+expand)/expand;
862 case orientation_horizontal_vertical:
867 gui_internal_widget_pack(this, wc);
877 rows=(count+cols-1)/cols;
880 width+=w->spx*(cols-1);
881 height+=w->spy*(rows-1);
889 if (! w->w && ! w->h) {
890 w->w=w->bl+w->br+width;
891 w->h=w->bt+w->bb+height;
893 if (w->flags & gravity_left)
895 if (w->flags & gravity_xcenter)
896 x=w->p.x+w->w/2-owidth/2;
897 if (w->flags & gravity_right)
898 x=w->p.x+w->w-w->br-owidth;
899 if (w->flags & gravity_top)
901 if (w->flags & gravity_ycenter)
902 y=w->p.y+w->h/2-oheight/2;
903 if (w->flags & gravity_bottom)
904 y=w->p.y+w->h-w->bb-oheight;
906 switch (orientation) {
907 case orientation_horizontal:
912 if (wc->flags & flags_fill)
914 if (wc->flags & flags_expand) {
917 wc->w=wc->w*expand/100;
919 if (w->flags & gravity_top)
921 if (w->flags & gravity_ycenter)
923 if (w->flags & gravity_bottom)
929 case orientation_vertical:
934 if (wc->flags & flags_fill)
936 if (wc->flags & flags_expand) {
939 wc->h=wc->h*expand/100;
941 if (w->flags & gravity_left)
943 if (w->flags & gravity_xcenter)
945 if (w->flags & gravity_right)
951 case orientation_horizontal_vertical:
961 if (wc->flags & flags_fill) {
965 if (w->flags & gravity_left)
967 if (w->flags & gravity_xcenter)
968 wc->p.x=x+(width-wc->w)/2;
969 if (w->flags & gravity_right)
970 wc->p.x=x+width-wc->w;
971 if (w->flags & gravity_top)
973 if (w->flags & gravity_ycenter)
974 wc->p.y=y+(height-wc->h)/2;
975 if (w->flags & gravity_bottom)
976 wc->p.y=y-height-wc->h;
978 if (++count == cols) {
992 gui_internal_widget_pack(this, wc);
998 gui_internal_widget_append(struct widget *parent, struct widget *child)
1002 if (! child->background)
1003 child->background=parent->background;
1004 parent->children=g_list_append(parent->children, child);
1007 static void gui_internal_widget_prepend(struct widget *parent, struct widget *child)
1009 if (! child->background)
1010 child->background=parent->background;
1011 parent->children=g_list_prepend(parent->children, child);
1014 static void gui_internal_widget_children_destroy(struct gui_priv *this, struct widget *w)
1022 gui_internal_widget_destroy(this, wc);
1025 g_list_free(w->children);
1029 static void gui_internal_widget_destroy(struct gui_priv *this, struct widget *w)
1031 gui_internal_widget_children_destroy(this, w);
1035 graphics_image_free(this->gra, w->img);
1041 w->data_free(w->data);
1042 if (w->cb && w->remove_cb)
1043 w->remove_cb(w->instance, w->cb);
1049 gui_internal_widget_render(struct gui_priv *this, struct widget *w)
1051 if(w->p.x > navit_get_width(this->nav) || w->p.y > navit_get_height(this->nav))
1056 gui_internal_box_render(this, w);
1059 gui_internal_label_render(this, w);
1062 gui_internal_image_render(this, w);
1065 gui_internal_table_render(this,w);
1073 gui_internal_widget_pack(struct gui_priv *this, struct widget *w)
1077 gui_internal_box_pack(this, w);
1080 gui_internal_table_pack(this,w);
1086 //##############################################################################################################
1089 //# Authors: Martin Schaller (04/2008)
1090 //##############################################################################################################
1091 static void gui_internal_call_highlighted(struct gui_priv *this)
1093 if (! this->highlighted || ! this->highlighted->func)
1095 this->highlighted->reason=1;
1096 this->highlighted->func(this, this->highlighted, this->highlighted->data);
1100 gui_internal_say(struct gui_priv *this, struct widget *w, int questionmark)
1102 char *text=w->speech;
1110 text=g_strdup_printf("%s%c", text, questionmark ? '?':'\0');
1111 navit_say(this->nav, text);
1117 gui_internal_prune_menu(struct gui_priv *this, struct widget *w)
1120 gui_internal_search_idle_end(this);
1121 while ((l = g_list_last(this->root.children))) {
1123 gui_internal_say(this, w, 0);
1124 gui_internal_widget_render(this, w);
1127 gui_internal_widget_destroy(this, l->data);
1128 this->root.children=g_list_remove(this->root.children, l->data);
1133 gui_internal_prune_menu_count(struct gui_priv *this, int count, int render)
1136 gui_internal_search_idle_end(this);
1137 while ((l = g_list_last(this->root.children)) && count-- > 0) {
1138 gui_internal_widget_destroy(this, l->data);
1139 this->root.children=g_list_remove(this->root.children, l->data);
1142 gui_internal_say(this, l->data, 0);
1143 gui_internal_widget_render(this, l->data);
1148 gui_internal_back(struct gui_priv *this, struct widget *w, void *data)
1150 gui_internal_prune_menu_count(this, 1, 1);
1154 gui_internal_cmd_return(struct gui_priv *this, struct widget *wm, void *data)
1156 gui_internal_prune_menu(this, wm->data);
1160 gui_internal_cmd_main_menu(struct gui_priv *this, struct widget *wm, void *data)
1162 gui_internal_prune_menu(this, this->root.children->data);
1165 static struct widget *
1166 gui_internal_top_bar(struct gui_priv *this)
1168 struct widget *w,*wm,*wh,*wc,*wcn;
1169 int dots_len, sep_len;
1171 int width,width_used=0,use_sep=0,incomplete=0;
1172 struct graphics_gc *foreground=(this->flags & 256 ? this->background : this->text_foreground);
1174 1:Don't expand bar to screen width
1175 2:Don't show Map Icon
1176 4:Don't show Home Icon
1177 8:Show only current menu
1178 16:Don't use menu titles as button
1179 32:Show navit version
1182 256:Use background for menu headline
1185 w=gui_internal_box_new(this, gravity_left_center|orientation_horizontal|(this->flags & 1 ? 0:flags_fill));
1186 w->bl=this->spacing;
1187 w->spx=this->spacing;
1188 w->background=this->background2;
1189 if ((this->flags & 6) == 6) {
1195 width=this->root.w-w->bl;
1196 if (! (this->flags & 2)) {
1197 wm=gui_internal_button_new_with_callback(this, NULL,
1198 image_new_s(this, "gui_map"), gravity_center|orientation_vertical,
1199 gui_internal_cmd_return, NULL);
1200 wm->speech=g_strdup(_("Back to map"));
1201 gui_internal_widget_pack(this, wm);
1202 gui_internal_widget_append(w, wm);
1205 if (! (this->flags & 4)) {
1206 wh=gui_internal_button_new_with_callback(this, NULL,
1207 image_new_s(this, "gui_home"), gravity_center|orientation_vertical,
1208 gui_internal_cmd_main_menu, NULL);
1209 wh->speech=g_strdup(_("Main Menu"));
1210 gui_internal_widget_pack(this, wh);
1211 gui_internal_widget_append(w, wh);
1214 if (!(this->flags & 6))
1216 l=g_list_last(this->root.children);
1217 wcn=gui_internal_label_new(this,".. »");
1218 wcn->foreground=foreground;
1220 gui_internal_widget_destroy(this, wcn);
1221 wcn=gui_internal_label_new(this,"»");
1222 wcn->foreground=foreground;
1224 gui_internal_widget_destroy(this, wcn);
1226 if (g_list_previous(l) || !g_list_next(l)) {
1228 wcn=gui_internal_label_new(this, wc->text);
1229 wcn->foreground=foreground;
1234 dbg(1,"%d (%s) + %d + %d + %d > %d\n", wcn->w, wc->text, width_used, w->spx, use_sep ? sep_len : 0, width);
1235 if (wcn->w + width_used + w->spx + (use_sep ? sep_len : 0) + (g_list_previous(l) ? dots_len : 0) > width) {
1237 gui_internal_widget_destroy(this, wcn);
1241 struct widget *wct=gui_internal_label_new(this, "»");
1242 wct->foreground=foreground;
1243 res=g_list_prepend(res, wct);
1244 width_used+=sep_len+w->spx;
1247 if (!(this->flags & 16)) {
1248 wcn->func=gui_internal_cmd_return;
1250 wcn->state |= STATE_SENSITIVE;
1252 res=g_list_prepend(res, wcn);
1253 if (this->flags & 8)
1256 l=g_list_previous(l);
1260 wcn=gui_internal_label_new_abbrev(this, wc->text, width-width_used-w->spx-dots_len);
1261 wcn->foreground=foreground;
1262 wcn->func=gui_internal_cmd_return;
1264 wcn->state |= STATE_SENSITIVE;
1265 res=g_list_prepend(res, wcn);
1266 l=g_list_previous(l);
1269 wcn=gui_internal_label_new(this, ".. »");
1270 wcn->foreground=foreground;
1271 wcn->func=gui_internal_cmd_return;
1273 wcn->state |= STATE_SENSITIVE;
1274 res=g_list_prepend(res, wcn);
1278 gui_internal_widget_append(w, l->data);
1281 if (this->flags & 32) {
1282 extern char *version;
1283 char *version_text=g_strdup_printf("Navit %s",version);
1284 wcn=gui_internal_label_new(this, version_text);
1285 g_free(version_text);
1286 wcn->flags=gravity_right_center|flags_expand;
1287 gui_internal_widget_append(w, wcn);
1291 gui_internal_widget_destroy(this, dots);
1296 static struct widget *
1297 gui_internal_time_help(struct gui_priv *this)
1299 struct widget *w,*wm,*wh,*wc,*wcn;
1300 int dots_len, sep_len;
1302 int width,width_used=0,use_sep,incomplete=0;
1307 w=gui_internal_box_new(this, gravity_right_center|orientation_horizontal|flags_fill);
1308 w->bl=this->spacing;
1309 w->spx=this->spacing;
1315 if (this->flags & 64) {
1316 wc=gui_internal_box_new(this, gravity_right_top|orientation_vertical|flags_fill);
1322 tm=localtime(&timep);
1323 strftime(timestr, 64, "%H:%M %d.%m.%Y", tm);
1324 wcn=gui_internal_label_new(this, timestr);
1325 gui_internal_widget_append(wc, wcn);
1326 gui_internal_widget_append(w, wc);
1328 if (this->flags & 128) {
1329 wcn=gui_internal_button_new_with_callback(this, _("Help"), image_new_l(this, "gui_help"), gravity_center|orientation_vertical|flags_fill, NULL, NULL);
1330 gui_internal_widget_append(w, wcn);
1337 * Applys the configuration values to this based on the settings
1338 * specified in the configuration file (this->config) and
1339 * the most approriate default profile based on screen resolution.
1341 * This function should be run after this->root is setup and could
1342 * be rerun after the window is resized.
1344 * @authors Steve Singer <ssinger_pg@sympatico.ca> (09/2008)
1346 static void gui_internal_apply_config(struct gui_priv *this)
1348 struct gui_config_settings * current_config=0;
1350 dbg(0,"w=%d h=%d\n", this->root.w, this->root.h);
1352 * Select default values from profile based on the screen.
1354 if((this->root.w > 320 || this->root.h > 320) && this->root.w > 240 && this->root.h > 240)
1356 if((this->root.w > 640 || this->root.h > 640) && this->root.w > 480 && this->root.h > 480 )
1358 current_config = &config_profiles[LARGE_PROFILE];
1362 current_config = &config_profiles[MEDIUM_PROFILE];
1367 current_config = &config_profiles[SMALL_PROFILE];
1371 * Apply override values from config file
1373 if(this->config.font_size == -1 )
1375 this->font_size = current_config->font_size;
1379 this->font_size = this->config.font_size;
1382 if(this->config.icon_xs == -1 )
1384 this->icon_xs = current_config->icon_xs;
1388 this->icon_xs = this->config.icon_xs;
1391 if(this->config.icon_s == -1 )
1393 this->icon_s = current_config->icon_s;
1397 this->icon_s = this->config.icon_s;
1399 if(this->config.icon_l == -1 )
1401 this->icon_l = current_config->icon_l;
1405 this->icon_l = this->config.icon_l;
1407 if(this->config.spacing == -1 )
1409 this->spacing = current_config->spacing;
1413 this->spacing = current_config->spacing;
1418 static struct widget *
1419 gui_internal_button_label(struct gui_priv *this, char *label, int mode)
1421 struct widget *wl,*wlb;
1422 struct widget *wb=gui_internal_menu_data(this)->button_bar;
1423 wlb=gui_internal_box_new(this, gravity_right_center|orientation_vertical);
1424 wl=gui_internal_label_new(this, label);
1426 wlb->foreground=this->text_foreground;
1431 gui_internal_widget_append(wlb, wl);
1433 gui_internal_widget_prepend(wb, wlb);
1435 gui_internal_widget_append(wb, wlb);
1441 static struct widget *
1442 gui_internal_menu(struct gui_priv *this, char *label)
1444 struct widget *menu,*w,*w1,*topbox;
1446 gui_internal_search_idle_end(this);
1447 topbox=gui_internal_box_new_with_label(this, 0, label);
1448 topbox->w=this->root.w;
1449 topbox->h=this->root.h;
1450 gui_internal_widget_append(&this->root, topbox);
1451 menu=gui_internal_box_new(this, gravity_left_center|orientation_vertical);
1452 menu->w=this->root.w;
1453 menu->h=this->root.h;
1454 menu->background=this->background;
1455 gui_internal_apply_config(this);
1456 this->font=graphics_font_new(this->gra,this->font_size,1);
1457 topbox->menu_data=g_new0(struct menu_data, 1);
1458 gui_internal_widget_append(topbox, menu);
1459 w=gui_internal_top_bar(this);
1460 gui_internal_widget_append(menu, w);
1461 w=gui_internal_box_new(this, gravity_center|orientation_horizontal_vertical|flags_expand|flags_fill);
1462 w->spx=4*this->spacing;
1463 gui_internal_widget_append(menu, w);
1464 if (this->flags & 16) {
1465 struct widget *wl,*wlb,*wb,*wm=w;
1466 wm->flags=gravity_center|orientation_vertical|flags_expand|flags_fill;
1467 w=gui_internal_box_new(this, gravity_center|orientation_horizontal|flags_expand|flags_fill);
1468 dbg(0,"topbox->menu_data=%p\n", topbox->menu_data);
1469 gui_internal_widget_append(wm, w);
1470 wb=gui_internal_box_new(this, gravity_right_center|orientation_horizontal|flags_fill);
1476 topbox->menu_data->button_bar=wb;
1477 gui_internal_widget_append(wm, wb);
1478 wlb=gui_internal_button_label(this,_("Back"),1);
1479 wlb->func=gui_internal_back;
1480 wlb->state |= STATE_SENSITIVE;
1482 if (this->flags & 192) {
1483 menu=gui_internal_box_new(this, gravity_left_center|orientation_vertical);
1484 menu->w=this->root.w;
1485 menu->h=this->root.h;
1486 w1=gui_internal_time_help(this);
1487 gui_internal_widget_append(menu, w1);
1488 w1=gui_internal_box_new(this, gravity_center|orientation_horizontal_vertical|flags_expand|flags_fill);
1489 gui_internal_widget_append(menu, w1);
1490 gui_internal_widget_append(topbox, menu);
1491 menu->background=NULL;
1496 static struct menu_data *
1497 gui_internal_menu_data(struct gui_priv *this)
1500 struct widget *menu;
1502 l=g_list_last(this->root.children);
1504 return menu->menu_data;
1508 gui_internal_menu_render(struct gui_priv *this)
1511 struct widget *menu;
1513 l=g_list_last(this->root.children);
1515 gui_internal_say(this, menu, 0);
1516 gui_internal_widget_pack(this, menu);
1517 gui_internal_widget_render(this, menu);
1521 gui_internal_cmd_set_destination(struct gui_priv *this, struct widget *wm, void *data)
1523 struct widget *w=wm->data;
1524 dbg(0,"c=%d:0x%x,0x%x\n", w->c.pro, w->c.x, w->c.y);
1525 navit_set_destination(this->nav, &w->c, w->name);
1526 gui_internal_prune_menu(this, NULL);
1530 gui_internal_cmd_set_position(struct gui_priv *this, struct widget *wm, void *data)
1532 struct widget *w=wm->data;
1533 navit_set_position(this->nav, &w->c);
1534 gui_internal_prune_menu(this, NULL);
1538 gui_internal_cmd_add_bookmark_do(struct gui_priv *this, struct widget *widget)
1541 dbg(0,"text='%s'\n", widget->text);
1542 if (widget->text && strlen(widget->text))
1543 navit_add_bookmark(this->nav, &widget->c, widget->text);
1544 g_free(widget->text);
1546 l=g_list_previous(g_list_last(this->root.children));
1547 gui_internal_prune_menu(this, l->data);
1551 gui_internal_cmd_add_bookmark_clicked(struct gui_priv *this, struct widget *widget, void *data)
1553 gui_internal_cmd_add_bookmark_do(this, widget->data);
1557 gui_internal_cmd_add_bookmark_changed(struct gui_priv *this, struct widget *wm, void *data)
1562 len=strlen(wm->text);
1563 dbg(1,"len=%d\n", len);
1564 if (len && (wm->text[len-1] == '\n' || wm->text[len-1] == '\r')) {
1565 wm->text[len-1]='\0';
1566 gui_internal_cmd_add_bookmark_do(this, wm);
1572 static struct widget * gui_internal_keyboard(struct gui_priv *this, int mode);
1575 gui_internal_cmd_add_bookmark(struct gui_priv *this, struct widget *wm, void *data)
1577 struct widget *w,*wb,*wk,*wl,*we,*wnext,*wp=wm->data;
1578 wb=gui_internal_menu(this, "Add Bookmark");
1579 w=gui_internal_box_new(this, gravity_left_top|orientation_vertical|flags_expand|flags_fill);
1580 gui_internal_widget_append(wb, w);
1581 we=gui_internal_box_new(this, gravity_left_center|orientation_horizontal|flags_fill);
1582 gui_internal_widget_append(w, we);
1583 gui_internal_widget_append(we, wk=gui_internal_label_new(this, wp->name ? wp->name : wp->text));
1584 wk->state |= STATE_EDIT|STATE_CLEAR;
1585 wk->background=this->background;
1586 wk->flags |= flags_expand|flags_fill;
1587 wk->func = gui_internal_cmd_add_bookmark_changed;
1589 gui_internal_widget_append(we, wnext=gui_internal_image_new(this, image_new_xs(this, "gui_active")));
1590 wnext->state |= STATE_SENSITIVE;
1591 wnext->func = gui_internal_cmd_add_bookmark_clicked;
1593 wl=gui_internal_box_new(this, gravity_left_top|orientation_vertical|flags_expand|flags_fill);
1594 gui_internal_widget_append(w, wl);
1596 gui_internal_widget_append(w, gui_internal_keyboard(this,2));
1597 gui_internal_menu_render(this);
1602 get_direction(char *buffer, int angle, int mode)
1607 sprintf(buffer,"%d",angle);
1610 if (angle < 69 || angle > 291)
1612 if (angle > 111 && angle < 249)
1614 if (angle > 22 && angle < 158)
1616 if (angle > 202 && angle < 338)
1621 angle=(angle+15)/30;
1624 sprintf(buffer,"%d H", angle);
1632 enum item_type *types;
1634 {"bank","Bank",(enum item_type []){type_poi_bank,type_poi_bank,type_none}},
1635 {"fuel","Fuel",(enum item_type []){type_poi_fuel,type_poi_fuel,type_none}},
1636 {"hotel","Hotel",(enum item_type []) {
1637 type_poi_hotel,type_poi_camp_rv,
1638 type_poi_camping,type_poi_camping,
1639 type_poi_resort,type_poi_resort,
1641 {"restaurant","Restaurant",(enum item_type []) {
1642 type_poi_bar,type_poi_picnic,
1643 type_poi_burgerking,type_poi_fastfood,
1644 type_poi_restaurant,type_poi_restaurant,
1646 {"shopping","Shopping",(enum item_type []) {
1647 type_poi_mall,type_poi_mall,
1648 type_poi_shop_grocery,type_poi_shop_grocery,
1650 {"hospital","Service",(enum item_type []) {
1651 type_poi_marina,type_poi_marina,
1652 type_poi_hospital,type_poi_hospital,
1653 type_poi_public_utilities,type_poi_public_utilities,
1654 type_poi_police,type_poi_autoservice,
1655 type_poi_information,type_poi_information,
1656 type_poi_personal_service,type_poi_repair_service,
1657 type_poi_rest_room,type_poi_rest_room,
1658 type_poi_restroom,type_poi_restroom,
1660 {"parking","Parking",(enum item_type []){type_poi_car_parking,type_poi_car_parking,type_none}},
1661 {"peak","Land Features",(enum item_type []){
1662 type_poi_land_feature,type_poi_rock,
1663 type_poi_dam,type_poi_dam,
1665 {"unknown","Other",(enum item_type []){
1666 type_point_unspecified,type_poi_land_feature-1,
1667 type_poi_rock+1,type_poi_fuel-1,
1668 type_poi_marina+1,type_poi_car_parking-1,
1669 type_poi_car_parking+1,type_poi_bar-1,
1670 type_poi_bank+1,type_poi_dam-1,
1671 type_poi_dam+1,type_poi_information-1,
1672 type_poi_information+1,type_poi_mall-1,
1673 type_poi_mall+1,type_poi_personal_service-1,
1674 type_poi_restaurant+1,type_poi_restroom-1,
1675 type_poi_restroom+1,type_poi_shop_grocery-1,
1676 type_poi_shop_grocery+1,type_poi_wifi,
1680 static void gui_internal_cmd_pois(struct gui_priv *this, struct widget *wm, void *data);
1682 static struct widget *
1683 gui_internal_cmd_pois_selector(struct gui_priv *this, struct pcoord *c)
1685 struct widget *wl,*wb;
1687 wl=gui_internal_box_new(this, gravity_left_center|orientation_horizontal|flags_fill);
1688 for (i = 0 ; i < sizeof(selectors)/sizeof(struct selector) ; i++) {
1689 gui_internal_widget_append(wl, wb=gui_internal_button_new_with_callback(this, NULL,
1690 image_new_xs(this, selectors[i].icon), gravity_left_center|orientation_vertical,
1691 gui_internal_cmd_pois, &selectors[i]));
1698 static struct widget *
1699 gui_internal_cmd_pois_item(struct gui_priv *this, struct coord *center, struct item *item, struct coord *c, int dist)
1708 wl=gui_internal_box_new(this, gravity_left_center|orientation_horizontal|flags_fill);
1710 sprintf(distbuf,"%d", dist/1000);
1711 get_direction(dirbuf, transform_get_angle_delta(center, c, 0), 1);
1712 type=item_to_name(item->type);
1713 if (item_attr_get(item, attr_label, &attr)) {
1714 wl->name=g_strdup_printf("%s %s",type,attr.u.str);
1717 wl->name=g_strdup(type);
1719 text=g_strdup_printf("%s %s %s %s", distbuf, dirbuf, type, attr.u.str);
1720 gui_internal_widget_append(wl, gui_internal_label_new(this, text));
1727 gui_internal_cmd_pois_sort_num(gconstpointer a, gconstpointer b, gpointer user_data)
1729 const struct widget *wa=a;
1730 const struct widget *wb=b;
1731 struct widget *wac=wa->children->data;
1732 struct widget *wbc=wb->children->data;
1741 gui_internal_cmd_pois_item_selected(struct selector *sel, enum item_type type)
1743 enum item_type *types;
1744 if (type >= type_line)
1746 if (! sel || !sel->types)
1749 while (*types != type_none) {
1750 if (type >= types[0] && type <= types[1]) {
1758 static void gui_internal_cmd_position(struct gui_priv *this, struct widget *wm, void *data);
1761 gui_internal_cmd_pois(struct gui_priv *this, struct widget *wm, void *data)
1763 struct map_selection *sel,*selm;
1764 struct coord c,center;
1765 struct mapset_handle *h;
1767 struct map_rect *mr;
1769 int idist,dist=4000;
1770 struct widget *wi,*w,*w2,*wb;
1771 enum projection pro=wm->c.pro;
1772 struct selector *isel=wm->data;
1774 wb=gui_internal_menu(this, isel ? isel->name : _("POIs"));
1775 w=gui_internal_box_new(this, gravity_top_center|orientation_vertical|flags_expand|flags_fill);
1776 gui_internal_widget_append(wb, w);
1778 gui_internal_widget_append(w, gui_internal_cmd_pois_selector(this,&wm->c));
1779 w2=gui_internal_box_new(this, gravity_top_center|orientation_vertical|flags_expand|flags_fill);
1780 gui_internal_widget_append(w, w2);
1782 sel=map_selection_rect_new(&wm->c, dist, 18);
1785 h=mapset_open(navit_get_mapset(this->nav));
1786 while ((m=mapset_next(h, 1))) {
1787 selm=map_selection_dup_pro(sel, pro, map_projection(m));
1788 mr=map_rect_new(m, selm);
1789 dbg(2,"mr=%p\n", mr);
1791 while ((item=map_rect_get_item(mr))) {
1792 if (gui_internal_cmd_pois_item_selected(isel, item->type) &&
1793 item_coord_get_pro(item, &c, 1, pro) &&
1794 coord_rect_contains(&sel->u.c_rect, &c) &&
1795 (idist=transform_distance(pro, ¢er, &c)) < dist) {
1796 gui_internal_widget_append(w2, wi=gui_internal_cmd_pois_item(this, ¢er, item, &c, idist));
1797 wi->func=gui_internal_cmd_position;
1798 wi->state |= STATE_SENSITIVE;
1804 map_rect_destroy(mr);
1806 map_selection_destroy(selm);
1808 map_selection_destroy(sel);
1810 w2->children=g_list_sort_with_data(w2->children, gui_internal_cmd_pois_sort_num, (void *)1);
1811 gui_internal_menu_render(this);
1815 gui_internal_cmd_view_on_map(struct gui_priv *this, struct widget *wm, void *data)
1817 struct widget *w=wm->data;
1818 navit_set_center(this->nav, &w->c);
1819 gui_internal_prune_menu(this, NULL);
1824 gui_internal_cmd_view_attributes(struct gui_priv *this, struct widget *wm, void *data)
1826 struct widget *w,*wb;
1827 struct map_rect *mr;
1832 dbg(0,"item=%p 0x%x 0x%x\n", wm->item.map,wm->item.id_hi, wm->item.id_lo);
1833 wb=gui_internal_menu(this, "Attributes");
1834 w=gui_internal_box_new(this, gravity_top_center|orientation_vertical|flags_expand|flags_fill);
1835 gui_internal_widget_append(wb, w);
1836 mr=map_rect_new(wm->item.map, NULL);
1837 item = map_rect_get_item_byid(mr, wm->item.id_hi, wm->item.id_lo);
1838 dbg(0,"item=%p\n", item);
1840 while(item_attr_get(item, attr_any, &attr)) {
1841 text=g_strdup_printf("%s:%s", attr_to_name(attr.type), attr_to_text(&attr, wm->item.map, 1));
1842 gui_internal_widget_append(w,
1843 wb=gui_internal_button_new_with_callback(this, text,
1844 NULL, gravity_left_center|orientation_horizontal|flags_fill,
1845 gui_internal_cmd_view_attributes, NULL));
1849 map_rect_destroy(mr);
1850 gui_internal_menu_render(this);
1854 gui_internal_cmd_view_in_browser(struct gui_priv *this, struct widget *wm, void *data)
1856 struct map_rect *mr;
1861 dbg(0,"item=%p 0x%x 0x%x\n", wm->item.map,wm->item.id_hi, wm->item.id_lo);
1862 mr=map_rect_new(wm->item.map, NULL);
1863 item = map_rect_get_item_byid(mr, wm->item.id_hi, wm->item.id_lo);
1864 dbg(0,"item=%p\n", item);
1866 while(item_attr_get(item, attr_url_local, &attr)) {
1868 cmd=g_strdup_printf("navit-browser.sh '%s' &",attr.u.str);
1871 map_rect_destroy(mr);
1876 dbg(0,"calling external cmd '%s' is not supported\n",cmd);
1882 /* wm->data: 0 Nothing special
1890 gui_internal_cmd_position(struct gui_priv *this, struct widget *wm, void *data)
1892 struct widget *wb,*w,*wc,*wbc;
1896 int display_attributes=(wm->data == (void *)2);
1897 int display_view_on_map=(wm->data != (void *)1);
1898 int display_items=(wm->data == (void *)1);
1899 int display_streets=(wm->data == (void *)3);
1900 if (wm->data == (void *)4) {
1901 gui_internal_search_town_in_country(this, wm);
1905 switch ((int)wm->data) {
1910 dbg(0,"x=0x%x y=0x%x\n", c.x, c.y);
1911 transform_to_geo(wm->c.pro, &c, &g);
1922 name=wm->name ? wm->name : wm->text;
1923 wb=gui_internal_menu(this, name);
1924 w=gui_internal_box_new(this, gravity_top_center|orientation_vertical|flags_expand|flags_fill);
1925 gui_internal_widget_append(wb, w);
1926 coord=coordinates(&wm->c, ' ');
1927 gui_internal_widget_append(w, gui_internal_label_new(this, coord));
1929 if (display_streets) {
1930 gui_internal_widget_append(w,
1931 wc=gui_internal_button_new_with_callback(this, _("Streets"),
1932 image_new_xs(this, "gui_active"), gravity_left_center|orientation_horizontal|flags_fill,
1933 gui_internal_search_street_in_town, wm));
1936 if (display_attributes) {
1937 struct map_rect *mr;
1940 mr=map_rect_new(wm->item.map, NULL);
1941 item = map_rect_get_item_byid(mr, wm->item.id_hi, wm->item.id_lo);
1943 if (item_attr_get(item, attr_description, &attr))
1944 gui_internal_widget_append(w, gui_internal_label_new(this, attr.u.str));
1945 if (item_attr_get(item, attr_url_local, &attr)) {
1946 gui_internal_widget_append(w,
1947 wb=gui_internal_button_new_with_callback(this, _("View in Browser"),
1948 image_new_xs(this, "gui_active"), gravity_left_center|orientation_horizontal|flags_fill,
1949 gui_internal_cmd_view_in_browser, NULL));
1952 gui_internal_widget_append(w,
1953 wb=gui_internal_button_new_with_callback(this, _("View Attributes"),
1954 image_new_xs(this, "gui_active"), gravity_left_center|orientation_horizontal|flags_fill,
1955 gui_internal_cmd_view_attributes, NULL));
1958 map_rect_destroy(mr);
1960 gui_internal_widget_append(w,
1961 gui_internal_button_new_with_callback(this, _("Set as destination"),
1962 image_new_xs(this, "gui_active"), gravity_left_center|orientation_horizontal|flags_fill,
1963 gui_internal_cmd_set_destination, wm));
1964 gui_internal_widget_append(w,
1965 gui_internal_button_new_with_callback(this, _("Set as position"),
1966 image_new_xs(this, "gui_active"), gravity_left_center|orientation_horizontal|flags_fill,
1967 gui_internal_cmd_set_position, wm));
1968 gui_internal_widget_append(w,
1969 wbc=gui_internal_button_new_with_callback(this, _("Add as bookmark"),
1970 image_new_xs(this, "gui_active"), gravity_left_center|orientation_horizontal|flags_fill,
1971 gui_internal_cmd_add_bookmark, wm));
1973 gui_internal_widget_append(w,
1974 wbc=gui_internal_button_new_with_callback(this, _("POIs"),
1975 image_new_xs(this, "gui_active"), gravity_left_center|orientation_horizontal|flags_fill,
1976 gui_internal_cmd_pois, NULL));
1979 gui_internal_widget_append(w,
1980 gui_internal_button_new(this, "Add to tour",
1981 image_new_o(this, "gui_active"), gravity_left_center|orientation_horizontal|flags_fill));
1982 gui_internal_widget_append(w,
1983 gui_internal_button_new(this, "Add as bookmark",
1984 image_new_o(this, "gui_active"), gravity_left_center|orientation_horizontal|flags_fill));
1986 if (display_view_on_map) {
1987 gui_internal_widget_append(w,
1988 gui_internal_button_new_with_callback(this, _("View on map"),
1989 image_new_xs(this, "gui_active"), gravity_left_center|orientation_horizontal|flags_fill,
1990 gui_internal_cmd_view_on_map, wm));
1992 if (display_items) {
1995 struct mapset_handle *h;
1996 struct map_rect *mr;
1999 struct street_data *data;
2000 struct map_selection sel;
2001 struct transformation *trans;
2002 enum projection pro;
2006 trans=navit_get_trans(this->nav);
2007 pro=transform_get_projection(trans);
2008 transform_from_geo(pro, &g, &c);
2009 ms=navit_get_mapset(this->nav);
2011 sel.u.c_rect.lu.x=c.x-dist;
2012 sel.u.c_rect.lu.y=c.y+dist;
2013 sel.u.c_rect.rl.x=c.x+dist;
2014 sel.u.c_rect.rl.y=c.y-dist;
2016 sel.range=item_range_all;
2018 while ((m=mapset_next(h,1))) {
2019 mr=map_rect_new(m, &sel);
2022 while ((item=map_rect_get_item(mr))) {
2023 data=street_get_data(item);
2024 if (transform_within_dist_item(&c, item->type, data->c, data->count, dist)) {
2025 if (item_attr_get(item, attr_label, &attr)) {
2026 label=map_convert_string(m, attr.u.str);
2027 text=g_strdup_printf("%s %s", item_to_name(item->type), label);
2028 map_convert_free(label);
2030 text=g_strdup_printf("%s", item_to_name(item->type));
2031 gui_internal_widget_append(w,
2032 wc=gui_internal_button_new_with_callback(this, text,
2033 image_new_xs(this, "gui_active"), gravity_left_center|orientation_horizontal|flags_fill,
2034 gui_internal_cmd_position, (void *)2));
2035 wc->c.x=data->c[0].x;
2036 wc->c.y=data->c[0].y;
2038 wc->name=g_strdup(text);
2042 street_data_free(data);
2044 map_rect_destroy(mr);
2049 gui_internal_menu_render(this);
2053 gui_internal_cmd_bookmarks(struct gui_priv *this, struct widget *wm, void *data)
2055 struct attr attr,mattr;
2056 struct map_rect *mr=NULL;
2058 char *label_full,*l,*prefix,*pos;
2059 int len,plen,hassub;
2060 struct widget *wb,*w,*wbm;
2065 wb=gui_internal_menu(this, wm->text ? wm->text : _("Bookmarks"));
2066 w=gui_internal_box_new(this, gravity_top_center|orientation_vertical|flags_expand|flags_fill);
2067 w->spy=this->spacing*3;
2068 gui_internal_widget_append(wb, w);
2073 plen=strlen(prefix);
2075 if(navit_get_attr(this->nav, attr_bookmark_map, &mattr, NULL) && mattr.u.map && (mr=map_rect_new(mattr.u.map, NULL))) {
2076 hash=g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
2077 while ((item=map_rect_get_item(mr))) {
2078 if (item->type != type_bookmark) continue;
2079 if (!item_attr_get(item, attr_label, &attr)) continue;
2080 label_full=attr.u.str;
2081 if (!strncmp(label_full, prefix, plen)) {
2082 pos=strchr(label_full+plen, '/');
2088 len=strlen(label_full);
2090 l=g_malloc(len-plen+1);
2091 strncpy(l, label_full+plen, len-plen);
2093 if (!g_hash_table_lookup(hash, l)) {
2094 wbm=gui_internal_button_new_with_callback(this, l,
2095 image_new_xs(this, hassub ? "gui_inactive" : "gui_active" ), gravity_left_center|orientation_horizontal|flags_fill,
2096 hassub ? gui_internal_cmd_bookmarks : gui_internal_cmd_position, NULL);
2097 if (item_coord_get(item, &c, 1)) {
2100 wbm->c.pro=map_projection(mattr.u.map);
2101 wbm->name=g_strdup_printf(_("Bookmark %s"),label_full);
2102 wbm->text=g_strdup(l);
2103 gui_internal_widget_append(w, wbm);
2104 g_hash_table_insert(hash, g_strdup(l), (void *)1);
2105 wbm->prefix=g_malloc(len+2);
2106 strncpy(wbm->prefix, label_full, len+1);
2107 wbm->prefix[len+1]='\0';
2109 gui_internal_widget_destroy(this, wbm);
2116 g_hash_table_destroy(hash);
2118 gui_internal_menu_render(this);
2121 static void gui_internal_keypress_do(struct gui_priv *this, char *key)
2123 struct widget *wi,*menu;
2127 menu=g_list_last(this->root.children)->data;
2128 wi=gui_internal_find_widget(menu, NULL, STATE_EDIT);
2130 if (*key == NAVIT_KEY_BACKSPACE) {
2131 dbg(0,"backspace\n");
2132 if (wi->text && wi->text[0]) {
2133 len=g_utf8_prev_char(wi->text+strlen(wi->text))-wi->text;
2135 text=g_strdup_printf("%s ", wi->text);
2138 if (wi->state & STATE_CLEAR) {
2139 dbg(0,"wi->state=0x%x\n", wi->state);
2142 wi->state &= ~STATE_CLEAR;
2143 dbg(0,"wi->state=0x%x\n", wi->state);
2145 text=g_strdup_printf("%s%s", wi->text ? wi->text : "", key);
2149 if (*key == NAVIT_KEY_BACKSPACE && wi->text) {
2150 gui_internal_widget_render(this, wi);
2155 wi->func(this, wi, wi->data);
2157 gui_internal_widget_render(this, wi);
2163 gui_internal_cmd_keypress(struct gui_priv *this, struct widget *wm, void *data)
2165 struct menu_data *md=gui_internal_menu_data(this);
2166 gui_internal_keypress_do(this, (char *) wm->data);
2167 if (md->keyboard_mode == 2)
2168 gui_internal_keyboard_do(this, md->keyboard, 10);
2172 gui_internal_search_idle_end(struct gui_priv *this)
2175 event_remove_idle(this->idle);
2178 if (this->idle_cb) {
2179 callback_destroy(this->idle_cb);
2185 gui_internal_search_idle(struct gui_priv *this, char *wm_name, struct widget *search_list, void *param)
2187 char *text=NULL,*name=NULL;
2188 struct search_list_result *res;
2192 res=search_list_get_result(this->sl);
2194 gui_internal_search_idle_end(this);
2198 if (! strcmp(wm_name,"Country")) {
2199 name=res->country->name;
2200 text=g_strdup_printf("%s", res->country->name);
2202 if (! strcmp(wm_name,"Town")) {
2203 name=res->town->name;
2204 text=g_strdup(name);
2206 if (! strcmp(wm_name,"Street")) {
2207 name=res->street->name;
2208 text=g_strdup_printf("%s %s", res->town->name, res->street->name);
2211 dbg(0,"res=%s\n", res->town->name);
2213 gui_internal_widget_append(search_list,
2214 wc=gui_internal_button_new_with_callback(this, text,
2215 image_new_xs(this, res->country->flag), gravity_left_center|orientation_horizontal|flags_fill,
2216 gui_internal_cmd_position, param));
2218 wc->name=g_strdup(name);
2221 wc->item.id_lo=res->id;
2222 gui_internal_widget_pack(this, search_list);
2223 l=g_list_last(this->root.children);
2224 graphics_draw_mode(this->gra, draw_mode_begin);
2225 gui_internal_widget_render(this, l->data);
2226 graphics_draw_mode(this->gra, draw_mode_end);
2230 gui_internal_search_idle_start(struct gui_priv *this, char *wm_name, struct widget *search_list, void *param)
2232 this->idle_cb=callback_new_4(callback_cast(gui_internal_search_idle), this, wm_name, search_list, param);
2233 this->idle=event_add_idle(50,this->idle_cb);
2234 callback_call_0(this->idle_cb);
2239 gui_internal_search_changed(struct gui_priv *this, struct widget *wm, void *data)
2242 struct widget *search_list=gui_internal_menu_data(this)->search_list;
2243 gui_internal_widget_children_destroy(this, search_list);
2244 void *param=(void *)3;
2246 if (! strcmp(wm->name,"Country")) {
2250 dbg(0,"%s now '%s'\n", wm->name, wm->text);
2252 gui_internal_search_idle_end(this);
2253 if (wm->text && g_utf8_strlen(wm->text, -1) >= minlen) {
2254 struct attr search_attr;
2257 if (! strcmp(wm->name,"Country"))
2258 search_attr.type=attr_country_all;
2259 if (! strcmp(wm->name,"Town"))
2260 search_attr.type=attr_town_name;
2261 if (! strcmp(wm->name,"Street"))
2262 search_attr.type=attr_street_name;
2263 search_attr.u.str=wm->text;
2264 search_list_search(this->sl, &search_attr, 1);
2265 gui_internal_search_idle_start(this, wm->name, search_list, param);
2267 l=g_list_last(this->root.children);
2268 gui_internal_widget_render(this, l->data);
2271 static struct widget *
2272 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, void (*data_free)(void *data), int w, int h)
2275 gui_internal_widget_append(wkbd, wk=gui_internal_button_new_with_callback(this, text,
2276 NULL, gravity_center|orientation_vertical, func, data));
2277 wk->data_free=data_free;
2278 wk->background=this->background;
2286 static struct widget *
2287 gui_internal_keyboard_key(struct gui_priv *this, struct widget *wkbd, char *text, char *key, int w, int h)
2289 return gui_internal_keyboard_key_data(this, wkbd, text, gui_internal_cmd_keypress, g_strdup(key), g_free,w,h);
2292 static void gui_internal_keyboard_change(struct gui_priv *this, struct widget *key, void *data);
2294 static struct widget *
2295 gui_internal_keyboard_do(struct gui_priv *this, struct widget *wkbdb, int mode)
2297 struct widget *wkbd,*wk;
2298 struct menu_data *md=gui_internal_menu_data(this);
2299 int i, max_w=navit_get_width(this->nav), max_h=navit_get_height(this->nav);
2305 gui_internal_highlight(this);
2307 gui_internal_widget_children_destroy(this, wkbdb);
2309 wkbdb=gui_internal_box_new(this, gravity_center|orientation_horizontal_vertical|flags_fill);
2311 md->keyboard_mode=mode;
2312 wkbd=gui_internal_box_new(this, gravity_center|orientation_horizontal_vertical|flags_fill);
2313 wkbd->background=this->background;
2320 if (mode >= 0 && mode < 8) {
2321 for (i = 0 ; i < 26 ; i++) {
2322 char text[]={'A'+i,'\0'};
2323 gui_internal_keyboard_key(this, wkbd, text, text,max_w,max_h);
2325 gui_internal_keyboard_key(this, wkbd, "_"," ",max_w,max_h);
2327 gui_internal_keyboard_key(this, wkbd, "-","-",max_w,max_h);
2328 gui_internal_keyboard_key(this, wkbd, "'","'",max_w,max_h);
2329 gui_internal_keyboard_key_data(this, wkbd, "", NULL, NULL, NULL,max_w,max_h);
2331 gui_internal_keyboard_key_data(this, wkbd, "", NULL, NULL, NULL,max_w,max_h);
2332 wk=gui_internal_keyboard_key_data(this, wkbd, "a", gui_internal_keyboard_change, wkbd, NULL,max_w,max_h);
2334 wk=gui_internal_keyboard_key_data(this, wkbd, "1", gui_internal_keyboard_change, wkbd, NULL,max_w,max_h);
2337 wk=gui_internal_keyboard_key_data(this, wkbd, "Ä",gui_internal_keyboard_change, wkbdb,NULL,max_w,max_h);
2339 gui_internal_keyboard_key(this, wkbd, "<-","\b",max_w,max_h);
2341 if (mode >= 8 && mode < 16) {
2342 for (i = 0 ; i < 26 ; i++) {
2343 char text[]={'a'+i,'\0'};
2344 gui_internal_keyboard_key(this, wkbd, text, text,max_w,max_h);
2346 gui_internal_keyboard_key(this, wkbd, "_"," ",max_w,max_h);
2348 gui_internal_keyboard_key(this, wkbd, "-","-",max_w,max_h);
2349 gui_internal_keyboard_key(this, wkbd, "'","'",max_w,max_h);
2350 gui_internal_keyboard_key_data(this, wkbd, "", NULL, NULL, NULL,max_w,max_h);
2352 gui_internal_keyboard_key_data(this, wkbd, "", NULL, NULL, NULL,max_w,max_h);
2353 wk=gui_internal_keyboard_key_data(this, wkbd, "A", gui_internal_keyboard_change, wkbd, NULL,max_w,max_h);
2355 wk=gui_internal_keyboard_key_data(this, wkbd, "1", gui_internal_keyboard_change, wkbd, NULL,max_w,max_h);
2358 wk=gui_internal_keyboard_key_data(this, wkbd, "ä",gui_internal_keyboard_change,wkbdb,NULL,max_w,max_h);
2360 gui_internal_keyboard_key(this, wkbd, "<-","\b",max_w,max_h);
2362 if (mode >= 16 && mode < 24) {
2363 for (i = 0 ; i < 10 ; i++) {
2364 char text[]={'0'+i,'\0'};
2365 gui_internal_keyboard_key(this, wkbd, text, text,max_w,max_h);
2367 gui_internal_keyboard_key(this, wkbd, ".",".",max_w,max_h);
2368 gui_internal_keyboard_key(this, wkbd, "°","°",max_w,max_h);
2369 gui_internal_keyboard_key(this, wkbd, "'","'",max_w,max_h);
2370 gui_internal_keyboard_key(this, wkbd, "\"","\"",max_w,max_h);
2371 gui_internal_keyboard_key(this, wkbd, "-","-",max_w,max_h);
2372 gui_internal_keyboard_key(this, wkbd, "+","+",max_w,max_h);
2373 gui_internal_keyboard_key(this, wkbd, "*","*",max_w,max_h);
2374 gui_internal_keyboard_key(this, wkbd, "/","/",max_w,max_h);
2375 gui_internal_keyboard_key(this, wkbd, "(","(",max_w,max_h);
2376 gui_internal_keyboard_key(this, wkbd, ")",")",max_w,max_h);
2377 gui_internal_keyboard_key(this, wkbd, "=","=",max_w,max_h);
2378 gui_internal_keyboard_key(this, wkbd, "?","?",max_w,max_h);
2379 for (i = 0 ; i < 5 ; i++) {
2380 gui_internal_keyboard_key_data(this, wkbd, "", NULL, NULL, NULL,max_w,max_h);
2383 gui_internal_keyboard_key(this, wkbd, "-","-",max_w,max_h);
2384 gui_internal_keyboard_key(this, wkbd, "'","'",max_w,max_h);
2385 gui_internal_keyboard_key_data(this, wkbd, "", NULL, NULL, NULL,max_w,max_h);
2387 gui_internal_keyboard_key_data(this, wkbd, "", NULL, NULL, NULL,max_w,max_h);
2388 wk=gui_internal_keyboard_key_data(this, wkbd, "A", gui_internal_keyboard_change, wkbd, NULL,max_w,max_h);
2390 wk=gui_internal_keyboard_key_data(this, wkbd, "a", gui_internal_keyboard_change, wkbd, NULL,max_w,max_h);
2393 wk=gui_internal_keyboard_key_data(this, wkbd, "Ä",gui_internal_keyboard_change,wkbdb,NULL,max_w,max_h);
2395 gui_internal_keyboard_key(this, wkbd, "<-","\b",max_w,max_h);
2397 if (mode >= 24 && mode < 32) {
2398 gui_internal_keyboard_key(this, wkbd, "Ä","Ä",max_w,max_h);
2399 gui_internal_keyboard_key(this, wkbd, "Ö","Ö",max_w,max_h);
2400 gui_internal_keyboard_key(this, wkbd, "Ü","Ü",max_w,max_h);
2401 for (i = 0 ; i < 27 ; i++) {
2402 gui_internal_keyboard_key_data(this, wkbd, "", NULL, NULL, NULL,max_w,max_h);
2404 wk=gui_internal_keyboard_key_data(this, wkbd, "A",gui_internal_keyboard_change,wkbdb,NULL,max_w,max_h);
2406 gui_internal_keyboard_key(this, wkbd, "<-","\b",max_w,max_h);
2408 if (mode >= 32 && mode < 40) {
2409 gui_internal_keyboard_key(this, wkbd, "ä","ä",max_w,max_h);
2410 gui_internal_keyboard_key(this, wkbd, "ö","ö",max_w,max_h);
2411 gui_internal_keyboard_key(this, wkbd, "ü","ü",max_w,max_h);
2412 for (i = 0 ; i < 27 ; i++) {
2413 gui_internal_keyboard_key_data(this, wkbd, "", NULL, NULL, NULL,max_w,max_h);
2415 wk=gui_internal_keyboard_key_data(this, wkbd, "a",gui_internal_keyboard_change,wkbdb,NULL,max_w,max_h);
2417 gui_internal_keyboard_key(this, wkbd, "<-","\b",max_w,max_h);
2419 gui_internal_widget_append(wkbdb, wkbd);
2421 gui_internal_widget_pack(this, wkbdb);
2422 gui_internal_widget_render(this, wkbdb);
2427 static struct widget *
2428 gui_internal_keyboard(struct gui_priv *this, int mode)
2430 if (! this->keyboard)
2432 return gui_internal_keyboard_do(this, NULL, mode);
2436 gui_internal_keyboard_change(struct gui_priv *this, struct widget *key, void *data)
2438 gui_internal_keyboard_do(this, key->data, key->datai);
2442 gui_internal_search_list_set_default_country(struct gui_priv *this)
2444 struct attr search_attr, country_name, country_iso2, *country_attr;
2446 struct country_search *cs;
2447 struct tracking *tracking;
2448 struct search_list_result *res;
2450 country_attr=country_default();
2451 tracking=navit_get_tracking(this->nav);
2452 if (tracking && tracking_get_current_attr(tracking, attr_country_id, &search_attr))
2453 country_attr=&search_attr;
2455 cs=country_search_new(country_attr, 0);
2456 item=country_search_get_item(cs);
2457 if (item && item_attr_get(item, attr_country_name, &country_name)) {
2458 search_attr.type=attr_country_all;
2459 dbg(0,"country %s\n", country_name.u.str);
2460 search_attr.u.str=country_name.u.str;
2461 search_list_search(this->sl, &search_attr, 0);
2462 while((res=search_list_get_result(this->sl)));
2463 g_free(this->country_iso2);
2464 if (item_attr_get(item, attr_country_iso2, &country_iso2))
2465 this->country_iso2=g_strdup(country_iso2.u.str);
2467 country_search_destroy(cs);
2469 dbg(0,"warning: no default country found\n");
2474 gui_internal_search_list_new(struct gui_priv *this)
2476 struct mapset *ms=navit_get_mapset(this->nav);
2478 this->sl=search_list_new(ms);
2479 gui_internal_search_list_set_default_country(this);
2484 gui_internal_search_list_destroy(struct gui_priv *this)
2487 search_list_destroy(this->sl);
2494 gui_internal_search(struct gui_priv *this, char *what, char *type, int flags)
2496 struct widget *wb,*wk,*w,*wr,*we,*wl,*wnext=NULL;
2498 gui_internal_search_list_new(this);
2499 wb=gui_internal_menu(this, what);
2500 w=gui_internal_box_new(this, gravity_center|orientation_vertical|flags_expand|flags_fill);
2501 gui_internal_widget_append(wb, w);
2502 wr=gui_internal_box_new(this, gravity_top_center|orientation_vertical|flags_expand|flags_fill);
2503 gui_internal_widget_append(w, wr);
2504 we=gui_internal_box_new(this, gravity_left_center|orientation_horizontal|flags_fill);
2505 gui_internal_widget_append(wr, we);
2507 if (!strcmp(type,"Country")) {
2508 wnext=gui_internal_image_new(this, image_new_xs(this, "gui_select_town"));
2509 wnext->func=gui_internal_search_town;
2510 } else if (!strcmp(type,"Town")) {
2511 if (this->country_iso2)
2512 country=g_strdup_printf("country_%s", this->country_iso2);
2514 country=strdup("gui_select_country");
2515 gui_internal_widget_append(we, wb=gui_internal_image_new(this, image_new_xs(this, country)));
2516 wb->state |= STATE_SENSITIVE;
2518 wb->func = gui_internal_search_country;
2520 wb->func = gui_internal_back;
2521 wnext=gui_internal_image_new(this, image_new_xs(this, "gui_select_street"));
2522 wnext->func=gui_internal_search_street;
2524 } else if (!strcmp(type,"Street")) {
2525 gui_internal_widget_append(we, wb=gui_internal_image_new(this, image_new_xs(this, "gui_select_town")));
2526 wb->state |= STATE_SENSITIVE;
2527 wb->func = gui_internal_back;
2529 gui_internal_widget_append(we, wk=gui_internal_label_new(this, NULL));
2531 gui_internal_widget_append(we, wnext);
2532 wnext->state |= STATE_SENSITIVE;
2534 wl=gui_internal_box_new(this, gravity_left_top|orientation_vertical|flags_expand|flags_fill);
2535 gui_internal_widget_append(wr, wl);
2536 gui_internal_menu_data(this)->search_list=wl;
2537 wk->state |= STATE_EDIT;
2538 wk->background=this->background;
2539 wk->flags |= flags_expand|flags_fill;
2540 wk->func = gui_internal_search_changed;
2541 wk->name=g_strdup(type);
2543 gui_internal_widget_append(w, gui_internal_keyboard(this,0));
2544 gui_internal_menu_render(this);
2548 gui_internal_search_street(struct gui_priv *this, struct widget *widget, void *data)
2550 search_list_select(this->sl, attr_town_name, 0, 0);
2551 gui_internal_search(this,_("Street"),"Street",0);
2555 gui_internal_search_street_in_town(struct gui_priv *this, struct widget *widget, void *data)
2557 dbg(0,"id %d\n", widget->item.id_lo);
2558 search_list_select(this->sl, attr_town_name, 0, 0);
2559 search_list_select(this->sl, attr_town_name, widget->item.id_lo, 1);
2560 gui_internal_search(this,_("Street"),"Street",0);
2564 gui_internal_search_town(struct gui_priv *this, struct widget *wm, void *data)
2567 search_list_select(this->sl, attr_country_all, 0, 0);
2568 g_free(this->country_iso2);
2569 this->country_iso2=NULL;
2570 gui_internal_search(this,_("Town"),"Town",0);
2574 gui_internal_search_town_in_country(struct gui_priv *this, struct widget *widget)
2576 struct search_list_common *slc;
2577 dbg(0,"id %d\n", widget->item.id_lo);
2578 search_list_select(this->sl, attr_country_all, 0, 0);
2579 slc=search_list_select(this->sl, attr_country_all, widget->item.id_lo, 1);
2581 g_free(this->country_iso2);
2582 this->country_iso2=((struct search_list_country *)slc)->iso2;
2584 gui_internal_search(this,widget->name,"Town",0);
2588 gui_internal_search_country(struct gui_priv *this, struct widget *widget, void *data)
2590 gui_internal_prune_menu_count(this, 1, 0);
2591 gui_internal_search(this,_("Country"),"Country",0);
2595 gui_internal_cmd_town(struct gui_priv *this, struct widget *wm, void *data)
2598 search_list_select(this->sl, attr_country_all, 0, 0);
2599 gui_internal_search(this,_("Town"),"Town",1);
2603 gui_internal_cmd_layout(struct gui_priv *this, struct widget *wm, void *data)
2606 struct widget *w,*wb,*wl;
2607 struct attr_iter *iter;
2610 wb=gui_internal_menu(this, _("Layout"));
2611 w=gui_internal_box_new(this, gravity_top_center|orientation_vertical|flags_expand|flags_fill);
2612 w->spy=this->spacing*3;
2613 gui_internal_widget_append(wb, w);
2614 iter=navit_attr_iter_new();
2615 while(navit_get_attr(this->nav, attr_layout, &attr, iter)) {
2616 wl=gui_internal_button_navit_attr_new(this, attr.u.layout->name, gravity_left_center|orientation_horizontal|flags_fill,
2618 gui_internal_widget_append(w, wl);
2620 navit_attr_iter_destroy(iter);
2621 gui_internal_menu_render(this);
2625 gui_internal_cmd_fullscreen(struct gui_priv *this, struct widget *wm, void *data)
2627 this->fullscreen=!this->fullscreen;
2628 this->win->fullscreen(this->win, this->fullscreen);
2632 gui_internal_cmd_2d(struct gui_priv *this, struct widget *wm, void *data)
2634 struct transformation *trans=navit_get_trans(this->nav);
2635 transform_set_pitch(trans, 0);
2640 gui_internal_cmd_3d(struct gui_priv *this, struct widget *wm, void *data)
2642 struct transformation *trans=navit_get_trans(this->nav);
2643 transform_set_pitch(trans, 20);
2648 gui_internal_cmd_display(struct gui_priv *this, struct widget *wm, void *data)
2651 struct transformation *trans;
2653 w=gui_internal_menu(this, _("Display"));
2654 gui_internal_widget_append(w,
2655 gui_internal_button_new_with_callback(this, _("Layout"),
2656 image_new_l(this, "gui_display"), gravity_center|orientation_vertical,
2657 gui_internal_cmd_layout, NULL));
2658 if (this->fullscreen) {
2659 gui_internal_widget_append(w,
2660 gui_internal_button_new_with_callback(this, _("Window Mode"),
2661 image_new_l(this, "gui_leave_fullscreen"), gravity_center|orientation_vertical,
2662 gui_internal_cmd_fullscreen, NULL));
2664 gui_internal_widget_append(w,
2665 gui_internal_button_new_with_callback(this, _("Fullscreen"),
2666 image_new_l(this, "gui_fullscreen"), gravity_center|orientation_vertical,
2667 gui_internal_cmd_fullscreen, NULL));
2669 trans=navit_get_trans(this->nav);
2670 if (transform_get_pitch(trans)) {
2671 gui_internal_widget_append(w,
2672 gui_internal_button_new_with_callback(this, _("2D"),
2673 image_new_l(this, "gui_map"), gravity_center|orientation_vertical,
2674 gui_internal_cmd_2d, NULL));
2677 gui_internal_widget_append(w,
2678 gui_internal_button_new_with_callback(this, _("3D"),
2679 image_new_l(this, "gui_map"), gravity_center|orientation_vertical,
2680 gui_internal_cmd_3d, NULL));
2682 gui_internal_menu_render(this);
2686 gui_internal_cmd_quit(struct gui_priv *this, struct widget *wm, void *data)
2688 struct navit *nav=this->nav;
2690 main_remove_navit(nav);
2694 gui_internal_cmd_abort_navigation(struct gui_priv *this, struct widget *wm, void *data)
2696 navit_set_destination(this->nav, NULL, NULL);
2701 gui_internal_cmd_actions(struct gui_priv *this, struct widget *wm, void *data)
2703 struct widget *w,*wc;
2706 w=gui_internal_menu(this, _("Actions"));
2707 gui_internal_widget_append(w,
2708 gui_internal_button_new_with_callback(this, _("Bookmarks"),
2709 image_new_l(this, "gui_bookmark"), gravity_center|orientation_vertical,
2710 gui_internal_cmd_bookmarks, NULL));
2711 if (this->clickp_valid) {
2712 coord=coordinates(&this->clickp, '\n');
2713 gui_internal_widget_append(w,
2714 wc=gui_internal_button_new_with_callback(this, coord,
2715 image_new_l(this, "gui_map"), gravity_center|orientation_vertical,
2716 gui_internal_cmd_position, (void *)1));
2717 wc->name=g_strdup(_("Map Point"));
2721 if (this->vehicle_valid) {
2722 coord=coordinates(&this->vehiclep, '\n');
2723 gui_internal_widget_append(w,
2724 wc=gui_internal_button_new_with_callback(this, coord,
2725 image_new_l(this, "gui_vehicle"), gravity_center|orientation_vertical,
2726 gui_internal_cmd_position, NULL));
2727 wc->name=g_strdup(_("Vehicle Position"));
2728 wc->c=this->vehiclep;
2731 gui_internal_widget_append(w,
2732 gui_internal_button_new_with_callback(this, _("Town"),
2733 image_new_l(this, "gui_town"), gravity_center|orientation_vertical,
2734 gui_internal_cmd_town, NULL));
2735 gui_internal_widget_append(w,
2736 gui_internal_button_new_with_callback(this, _("Quit"),
2737 image_new_l(this, "gui_quit"), gravity_center|orientation_vertical,
2738 gui_internal_cmd_quit, NULL));
2740 if (navit_check_route(this->nav)) {
2741 gui_internal_widget_append(w,
2742 gui_internal_button_new_with_callback(this, _("Stop\nNavigation"),
2743 image_new_l(this, "gui_stop"), gravity_center|orientation_vertical,
2744 gui_internal_cmd_abort_navigation, NULL));
2746 gui_internal_menu_render(this);
2750 gui_internal_cmd_maps(struct gui_priv *this, struct widget *wm, void *wdata)
2752 struct attr attr, on, off, description, type, data;
2753 struct widget *w,*wb,*wma;
2755 struct attr_iter *iter;
2758 wb=gui_internal_menu(this, _("Maps"));
2759 w=gui_internal_box_new(this, gravity_top_center|orientation_vertical|flags_expand|flags_fill);
2760 w->spy=this->spacing*3;
2761 gui_internal_widget_append(wb, w);
2762 iter=navit_attr_iter_new();
2763 on.type=off.type=attr_active;
2766 while(navit_get_attr(this->nav, attr_map, &attr, iter)) {
2767 if (map_get_attr(attr.u.map, attr_description, &description, NULL)) {
2768 label=g_strdup(description.u.str);
2770 if (!map_get_attr(attr.u.map, attr_type, &type, NULL))
2772 if (!map_get_attr(attr.u.map, attr_data, &data, NULL))
2774 label=g_strdup_printf("%s:%s", type.u.str, data.u.str);
2776 wma=gui_internal_button_map_attr_new(this, label, gravity_left_center|orientation_horizontal|flags_fill,
2777 attr.u.map, &on, &off, 1);
2778 gui_internal_widget_append(w, wma);
2781 navit_attr_iter_destroy(iter);
2782 gui_internal_menu_render(this);
2786 gui_internal_cmd_set_active_vehicle(struct gui_priv *this, struct widget *wm, void *data)
2788 struct attr vehicle = {attr_vehicle,{wm->data}};
2789 navit_set_attr(this->nav, &vehicle);
2793 gui_internal_cmd_vehicle_settings(struct gui_priv *this, struct widget *wm, void *data)
2795 struct widget *w,*wb;
2796 struct attr active_vehicle;
2797 wb=gui_internal_menu(this, wm->text);
2798 w=gui_internal_box_new(this, gravity_top_center|orientation_vertical|flags_expand|flags_fill);
2799 gui_internal_widget_append(wb, w);
2800 if (!navit_get_attr(this->nav, attr_vehicle, &active_vehicle, NULL))
2801 active_vehicle.u.vehicle=NULL;
2802 if (active_vehicle.u.vehicle != wm->data) {
2803 gui_internal_widget_append(w,
2804 gui_internal_button_new_with_callback(this, _("Set as active"),
2805 image_new_xs(this, "gui_active"), gravity_left_center|orientation_horizontal|flags_fill,
2806 gui_internal_cmd_set_active_vehicle, wm->data));
2808 callback_list_call_attr_2(this->cbl, attr_vehicle, w, wm->data);
2809 gui_internal_menu_render(this);
2813 gui_internal_cmd_vehicle(struct gui_priv *this, struct widget *wm, void *data)
2815 struct attr attr,vattr;
2816 struct widget *w,*wb,*wl;
2817 struct attr_iter *iter;
2818 struct attr active_vehicle;
2821 wb=gui_internal_menu(this, _("Vehicle"));
2822 w=gui_internal_box_new(this, gravity_top_center|orientation_vertical|flags_expand|flags_fill);
2823 w->spy=this->spacing*3;
2824 gui_internal_widget_append(wb, w);
2825 if (!navit_get_attr(this->nav, attr_vehicle, &active_vehicle, NULL))
2826 active_vehicle.u.vehicle=NULL;
2827 iter=navit_attr_iter_new();
2828 while(navit_get_attr(this->nav, attr_vehicle, &attr, iter)) {
2829 vehicle_get_attr(attr.u.vehicle, attr_name, &vattr, NULL);
2830 wl=gui_internal_button_new_with_callback(this, vattr.u.str,
2831 image_new_l(this, attr.u.vehicle == active_vehicle.u.vehicle ? "gui_active" : "gui_inactive"), gravity_left_center|orientation_horizontal|flags_fill,
2832 gui_internal_cmd_vehicle_settings, attr.u.vehicle);
2833 wl->text=g_strdup(vattr.u.str);
2834 gui_internal_widget_append(w, wl);
2836 navit_attr_iter_destroy(iter);
2837 gui_internal_menu_render(this);
2842 gui_internal_cmd_rules(struct gui_priv *this, struct widget *wm, void *data)
2844 struct widget *wb,*w;
2846 wb=gui_internal_menu(this, _("Rules"));
2847 w=gui_internal_box_new(this, gravity_top_center|orientation_vertical|flags_expand|flags_fill);
2848 w->spy=this->spacing*3;
2849 gui_internal_widget_append(wb, w);
2852 on.type=off.type=attr_tracking;
2853 gui_internal_widget_append(w,
2854 gui_internal_button_navit_attr_new(this, _("Lock on road"), gravity_left_center|orientation_horizontal|flags_fill,
2858 on.type=off.type=attr_orientation;
2859 gui_internal_widget_append(w,
2860 gui_internal_button_navit_attr_new(this, _("Northing"), gravity_left_center|orientation_horizontal|flags_fill,
2864 on.type=off.type=attr_cursor;
2865 gui_internal_widget_append(w,
2866 gui_internal_button_navit_attr_new(this, _("Map follows Vehicle"), gravity_left_center|orientation_horizontal|flags_fill,
2868 gui_internal_menu_render(this);
2872 gui_internal_cmd_settings(struct gui_priv *this, struct widget *wm, void *data)
2876 w=gui_internal_menu(this, _("Settings"));
2877 gui_internal_widget_append(w,
2878 gui_internal_button_new_with_callback(this, _("Display"),
2879 image_new_l(this, "gui_display"), gravity_center|orientation_vertical,
2880 gui_internal_cmd_display, NULL));
2881 gui_internal_widget_append(w,
2882 gui_internal_button_new_with_callback(this, _("Maps"),
2883 image_new_l(this, "gui_maps"), gravity_center|orientation_vertical,
2884 gui_internal_cmd_maps, NULL));
2885 gui_internal_widget_append(w,
2886 gui_internal_button_new_with_callback(this, _("Vehicle"),
2887 image_new_l(this, "gui_vehicle"), gravity_center|orientation_vertical,
2888 gui_internal_cmd_vehicle, NULL));
2889 gui_internal_widget_append(w,
2890 gui_internal_button_new_with_callback(this, _("Rules"),
2891 image_new_l(this, "gui_rules"), gravity_center|orientation_vertical,
2892 gui_internal_cmd_rules, NULL));
2893 gui_internal_menu_render(this);
2896 //##############################################################################################################
2899 //# Authors: Martin Schaller (04/2008)
2900 //##############################################################################################################
2901 static void gui_internal_motion(void *data, struct point *p)
2904 struct gui_priv *this=data;
2905 if (!this->root.children) {
2906 navit_handle_motion(this->nav, p);
2912 if(!this->motion_timeout_callback)
2913 this->motion_timeout_callback=callback_new_1(callback_cast(gui_internal_highlight), this);
2914 if(!this->motion_timeout_event)
2915 this->motion_timeout_event=event_add_timeout(100,0, this->motion_timeout_callback);
2919 static void gui_internal_menu_root(struct gui_priv *this)
2923 graphics_draw_mode(this->gra, draw_mode_begin);
2924 w=gui_internal_menu(this, _("Main menu"));
2925 w->spx=this->spacing*10;
2926 gui_internal_widget_append(w, gui_internal_button_new_with_callback(this, _("Actions"),
2927 image_new_l(this, "gui_actions"), gravity_center|orientation_vertical,
2928 gui_internal_cmd_actions, NULL));
2929 if (this->flags & 2) {
2930 gui_internal_widget_append(w, gui_internal_button_new_with_callback(this, _("Show\nMap"),
2931 image_new_l(this, "gui_map"), gravity_center|orientation_vertical,
2932 gui_internal_cmd_settings, NULL));
2934 gui_internal_widget_append(w, gui_internal_button_new_with_callback(this, _("Settings"),
2935 image_new_l(this, "gui_settings"), gravity_center|orientation_vertical,
2936 gui_internal_cmd_settings, NULL));
2937 gui_internal_widget_append(w, gui_internal_button_new(this, _("Tools"),
2938 image_new_l(this, "gui_tools"), gravity_center|orientation_vertical));
2940 gui_internal_widget_append(w, gui_internal_button_new_with_callback(this, "Table Test",
2941 image_new_l(this, "gui_settings"), gravity_center|orientation_vertical,
2942 gui_internal_cmd_route, NULL));
2945 callback_list_call_attr_1(this->cbl, attr_gui, w);
2947 gui_internal_menu_render(this);
2948 graphics_draw_mode(this->gra, draw_mode_end);
2952 gui_internal_cmd_menu(struct gui_priv *this, struct point *p, int ignore)
2954 struct graphics *gra=this->gra;
2955 struct transformation *trans;
2957 struct attr attr,attrp;
2959 this->ignore_button=ignore;
2960 this->clickp_valid=this->vehicle_valid=0;
2962 navit_block(this->nav, 1);
2963 graphics_overlay_disable(gra, 1);
2964 trans=navit_get_trans(this->nav);
2966 transform_reverse(trans, p, &c);
2967 dbg(0,"x=0x%x y=0x%x\n", c.x, c.y);
2968 this->clickp.pro=transform_get_projection(trans);
2971 this->clickp_valid=1;
2973 if (navit_get_attr(this->nav, attr_vehicle, &attr, NULL) && attr.u.vehicle
2974 && vehicle_get_attr(attr.u.vehicle, attr_position_coord_geo, &attrp, NULL)) {
2975 this->vehiclep.pro=transform_get_projection(trans);
2976 transform_from_geo(this->vehiclep.pro, attrp.u.coord_geo, &c);
2977 this->vehiclep.x=c.x;
2978 this->vehiclep.y=c.y;
2979 this->vehicle_valid=1;
2984 this->root.background=this->background;
2985 gui_internal_menu_root(this);
2989 gui_internal_check_exit(struct gui_priv *this)
2991 struct graphics *gra=this->gra;
2992 if (! this->root.children) {
2993 gui_internal_search_idle_end(this);
2994 gui_internal_search_list_destroy(this);
2995 graphics_overlay_disable(gra, 0);
2996 if (!navit_block(this->nav, 0)) {
2998 navit_draw(this->nav);
3000 navit_draw_displaylist(this->nav);
3005 //##############################################################################################################
3006 //# Description: Function to handle mouse clicks and scroll wheel movement
3008 //# Authors: Martin Schaller (04/2008), Stefan Klumpp (04/2008)
3009 //##############################################################################################################
3010 static void gui_internal_button(void *data, int pressed, int button, struct point *p)
3012 struct gui_priv *this=data;
3013 struct graphics *gra=this->gra;
3015 dbg(1,"enter %d %d\n", pressed, button);
3016 // if still on the map (not in the menu, yet):
3017 if (!this->root.children || this->ignore_button) {
3018 this->ignore_button=0;
3019 // check whether the position of the mouse changed during press/release OR if it is the scrollwheel
3020 if (!navit_handle_button(this->nav, pressed, button, p, NULL) || button >=4) // Maybe there's a better way to do this
3022 if (this->menu_on_map_click)
3023 gui_internal_cmd_menu(this, p, 0);
3028 // if already in the menu:
3032 gui_internal_highlight(this);
3037 graphics_draw_mode(gra, draw_mode_begin);
3038 gui_internal_call_highlighted(this);
3039 gui_internal_highlight(this);
3040 graphics_draw_mode(gra, draw_mode_end);
3041 gui_internal_check_exit(this);
3045 //##############################################################################################################
3048 //# Authors: Martin Schaller (04/2008)
3049 //##############################################################################################################
3050 static void gui_internal_resize(void *data, int w, int h)
3052 struct gui_priv *this=data;
3054 if( this->root.w==w && this->root.h==h)
3059 dbg(0,"w=%d h=%d children=%p\n", w, h, this->root.children);
3060 navit_handle_resize(this->nav, w, h);
3061 if (this->root.children) {
3062 gui_internal_prune_menu(this, NULL);
3063 gui_internal_menu_root(this);
3068 gui_internal_keynav_point(struct widget *w, int dx, int dy, struct point *p)
3083 gui_internal_keynav_find_closest(struct widget *wi, struct point *p, int dx, int dy, int *distance, struct widget **result)
3085 GList *l=wi->children;
3086 if (wi->state & STATE_SENSITIVE) {
3089 gui_internal_keynav_point(wi, -dx, -dy, &wp);
3091 dist1=(wp.x-p->x)*dx;
3094 dist1=(wp.y-p->y)*dy;
3102 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);
3108 if (dist1 < *distance) {
3115 struct widget *child=l->data;
3116 gui_internal_keynav_find_closest(child, p, dx, dy, distance, result);
3122 gui_internal_keynav_highlight_next(struct gui_priv *this, int dx, int dy)
3124 struct widget *result,*menu=g_list_last(this->root.children)->data;
3127 if (this->highlighted && this->highlighted_menu == g_list_last(this->root.children)->data)
3128 gui_internal_keynav_point(this->highlighted, dx, dy, &p);
3134 gui_internal_keynav_find_closest(menu, &p, 0, 0, &distance, &result);
3136 gui_internal_keynav_point(result, dx, dy, &p);
3137 dbg(1,"result origin=%p p=%d,%d\n", result, p.x, p.y);
3142 gui_internal_keynav_find_closest(menu, &p, dx, dy, &distance, &result);
3143 dbg(1,"result=%p\n", result);
3155 gui_internal_keynav_find_closest(menu, &p, dx, dy, &distance, &result);
3156 dbg(1,"wraparound result=%p\n", result);
3158 gui_internal_highlight_do(this, result);
3160 gui_internal_say(this, result, 1);
3163 //##############################################################################################################
3166 //# Authors: Martin Schaller (04/2008)
3167 //##############################################################################################################
3168 static void gui_internal_keypress(void *data, char *key)
3170 struct gui_priv *this=data;
3173 if (!this->root.children) {
3174 transform_get_size(navit_get_trans(this->nav), &w, &h);
3179 navit_set_center_screen(this->nav, &p);
3181 case NAVIT_KEY_DOWN:
3184 navit_set_center_screen(this->nav, &p);
3186 case NAVIT_KEY_LEFT:
3189 navit_set_center_screen(this->nav, &p);
3191 case NAVIT_KEY_RIGHT:
3194 navit_set_center_screen(this->nav, &p);
3196 case NAVIT_KEY_ZOOM_IN:
3197 navit_zoom_in(this->nav, 2, NULL);
3199 case NAVIT_KEY_ZOOM_OUT:
3200 navit_zoom_out(this->nav, 2, NULL);
3202 case NAVIT_KEY_RETURN:
3203 gui_internal_cmd_menu(this, NULL, 0);
3208 graphics_draw_mode(this->gra, draw_mode_begin);
3210 case NAVIT_KEY_LEFT:
3211 gui_internal_keynav_highlight_next(this,-1,0);
3213 case NAVIT_KEY_RIGHT:
3214 gui_internal_keynav_highlight_next(this,1,0);
3217 gui_internal_keynav_highlight_next(this,0,-1);
3219 case NAVIT_KEY_DOWN:
3220 gui_internal_keynav_highlight_next(this,0,1);
3222 case NAVIT_KEY_RETURN:
3223 if (this->highlighted && this->highlighted_menu == g_list_last(this->root.children)->data)
3224 gui_internal_call_highlighted(this);
3226 gui_internal_keypress_do(this, key);
3229 gui_internal_keypress_do(this, key);
3231 graphics_draw_mode(this->gra, draw_mode_end);
3232 gui_internal_check_exit(this);
3236 //##############################################################################################################
3239 //# Authors: Martin Schaller (04/2008)
3240 //##############################################################################################################
3241 static int gui_internal_set_graphics(struct gui_priv *this, struct graphics *gra)
3244 struct color cbh={0x9fff,0x9fff,0x9fff,0xffff};
3245 struct color cf={0xbfff,0xbfff,0xbfff,0xffff};
3246 struct color cw={0xffff,0xffff,0xffff,0xffff};
3247 struct color cbl={0x0000,0x0000,0x0000,0xffff};
3248 struct transformation *trans=navit_get_trans(this->nav);
3250 win=graphics_get_data(gra, "window");
3253 navit_ignore_graphics_events(this->nav, 1);
3256 navit_ignore_graphics_events(this->nav, 1);
3257 transform_get_size(trans, &this->root.w, &this->root.h);
3258 this->resize_cb=callback_new_attr_1(callback_cast(gui_internal_resize), attr_resize, this);
3259 graphics_add_callback(gra, this->resize_cb);
3260 this->button_cb=callback_new_attr_1(callback_cast(gui_internal_button), attr_button, this);
3261 graphics_add_callback(gra, this->button_cb);
3262 this->motion_cb=callback_new_attr_1(callback_cast(gui_internal_motion), attr_motion, this);
3263 graphics_add_callback(gra, this->motion_cb);
3264 this->keypress_cb=callback_new_attr_1(callback_cast(gui_internal_keypress), attr_keypress, this);
3265 graphics_add_callback(gra, this->keypress_cb);
3266 this->background=graphics_gc_new(gra);
3267 this->background2=graphics_gc_new(gra);
3268 this->highlight_background=graphics_gc_new(gra);
3269 graphics_gc_set_foreground(this->highlight_background, &cbh);
3270 this->foreground=graphics_gc_new(gra);
3271 graphics_gc_set_foreground(this->foreground, &cf);
3272 this->text_background=graphics_gc_new(gra);
3273 this->text_foreground=graphics_gc_new(gra);
3274 graphics_gc_set_foreground(this->background, &this->background_color);
3275 graphics_gc_set_foreground(this->background2, &this->background2_color);
3276 graphics_gc_set_foreground(this->text_background, &this->text_background_color);
3277 graphics_gc_set_foreground(this->text_foreground, &this->text_foreground_color);
3279 // set fullscreen if needed
3280 if (this->fullscreen)
3281 this->win->fullscreen(this->win, this->fullscreen);
3285 //##############################################################################################################
3288 //# Authors: Martin Schaller (04/2008)
3289 //##############################################################################################################
3290 struct gui_methods gui_internal_methods = {
3293 gui_internal_set_graphics,
3297 gui_internal_get_data(struct gui_priv *priv, char *command, struct attr **in, struct attr ***out)
3299 struct attr private_data = (struct attr) { attr_private_data, {(void *)&priv->data}};
3301 *out=attr_generic_add_attr(*out, &private_data);
3305 gui_internal_add_callback(struct gui_priv *priv, struct callback *cb)
3307 callback_list_add(priv->cbl, cb);
3311 gui_internal_remove_callback(struct gui_priv *priv, struct callback *cb)
3313 callback_list_remove(priv->cbl, cb);
3317 static struct gui_internal_methods gui_internal_methods_ext = {
3318 gui_internal_add_callback,
3319 gui_internal_remove_callback,
3320 gui_internal_menu_render,
3327 gui_internal_get_flags(struct widget *widget)
3329 return widget->flags;
3333 gui_internal_set_flags(struct widget *widget, enum flags flags)
3335 widget->flags=flags;
3339 gui_internal_get_state(struct widget *widget)
3341 return widget->state;
3345 gui_internal_set_state(struct widget *widget, int state)
3347 widget->state=state;
3351 gui_internal_set_func(struct widget *widget, void (*func)(struct gui_priv *priv, struct widget *widget, void *data))
3357 gui_internal_set_data(struct widget *widget, void *data)
3363 gui_internal_set_default_background(struct gui_priv *this, struct widget *widget)
3365 widget->background=this->background;
3368 static struct gui_internal_widget_methods gui_internal_widget_methods = {
3369 gui_internal_widget_append,
3370 gui_internal_button_new,
3371 gui_internal_button_new_with_callback,
3372 gui_internal_box_new,
3373 gui_internal_label_new,
3374 gui_internal_image_new,
3375 gui_internal_keyboard,
3377 gui_internal_get_flags,
3378 gui_internal_set_flags,
3379 gui_internal_get_state,
3380 gui_internal_set_state,
3381 gui_internal_set_func,
3382 gui_internal_set_data,
3383 gui_internal_set_default_background,
3387 //##############################################################################################################
3390 //# Authors: Martin Schaller (04/2008)
3391 //##############################################################################################################
3392 static struct gui_priv * gui_internal_new(struct navit *nav, struct gui_methods *meth, struct attr **attrs)
3394 struct gui_priv *this;
3396 *meth=gui_internal_methods;
3397 this=g_new0(struct gui_priv, 1);
3399 if ((attr=attr_search(attrs, NULL, attr_menu_on_map_click)))
3400 this->menu_on_map_click=attr->u.num;
3402 this->menu_on_map_click=1;
3403 navit_command_register(nav,"gui_internal_menu",callback_new_3(callback_cast(gui_internal_cmd_menu),this,NULL,(void *)1));
3404 navit_command_register(nav,"gui_internal_fullscreen",callback_new_2(callback_cast(gui_internal_cmd_fullscreen),this,NULL));
3405 dbg(0,"register\n");
3406 navit_command_register(nav,"gui_internal_get_data",callback_new_1(callback_cast(gui_internal_get_data),this));
3408 if( (attr=attr_search(attrs,NULL,attr_font_size)))
3410 this->config.font_size=attr->u.num;
3414 this->config.font_size=-1;
3416 if( (attr=attr_search(attrs,NULL,attr_icon_xs)))
3418 this->config.icon_xs=attr->u.num;
3422 this->config.icon_xs=-1;
3424 if( (attr=attr_search(attrs,NULL,attr_icon_l)))
3426 this->config.icon_l=attr->u.num;
3430 this->config.icon_l=-1;
3432 if( (attr=attr_search(attrs,NULL,attr_icon_s)))
3434 this->config.icon_s=attr->u.num;
3438 this->config.icon_s=-1;
3440 if( (attr=attr_search(attrs,NULL,attr_spacing)))
3442 this->config.spacing=attr->u.num;
3446 this->config.spacing=-1;
3448 if( (attr=attr_search(attrs,NULL,attr_gui_speech)))
3450 this->speech=attr->u.num;
3452 if( (attr=attr_search(attrs,NULL,attr_keyboard)))
3453 this->keyboard=attr->u.num;
3457 if( (attr=attr_search(attrs,NULL,attr_fullscreen)))
3458 this->fullscreen=attr->u.num;
3460 if( (attr=attr_search(attrs,NULL,attr_flags)))
3461 this->flags=attr->u.num;
3462 if( (attr=attr_search(attrs,NULL,attr_background_color)))
3463 this->background_color=*attr->u.color;
3465 this->background_color=(struct color){0x0,0x0,0x0,0xffff};
3466 if( (attr=attr_search(attrs,NULL,attr_background_color2)))
3467 this->background2_color=*attr->u.color;
3469 this->background2_color=(struct color){0x4141,0x4141,0x4141,0xffff};
3470 if( (attr=attr_search(attrs,NULL,attr_text_color)))
3471 this->text_foreground_color=*attr->u.color;
3473 this->text_foreground_color=(struct color){0xffff,0xffff,0xffff,0xffff};
3474 if( (attr=attr_search(attrs,NULL,attr_columns)))
3475 this->cols=attr->u.num;
3476 this->data.priv=this;
3477 this->data.gui=&gui_internal_methods_ext;
3478 this->data.widget=&gui_internal_widget_methods;
3479 this->cbl=callback_list_new();
3484 //##############################################################################################################
3487 //# Authors: Martin Schaller (04/2008)
3488 //##############################################################################################################
3489 void plugin_init(void)
3491 plugin_register_gui_type("internal", gui_internal_new);
3495 * @brief Creates a new table widget.
3497 * Creates and returns a new table widget. This function will
3498 * setup next/previous buttons as children.
3500 * @param this The graphics context.
3501 * @param flags widget sizing flags.
3502 * @returns The newly created widget
3504 struct widget * gui_internal_widget_table_new(struct gui_priv * this, enum flags flags)
3506 struct widget * widget = g_new0(struct widget,1);
3507 struct table_data * data = NULL;
3508 widget->type=widget_table;
3509 widget->flags=flags;
3510 widget->data = g_new0(struct table_data,1);
3511 widget->data_free=gui_internal_table_data_free;
3512 data = (struct table_data*)widget->data;
3515 data->next_button = gui_internal_button_new_with_callback
3516 (this,"Next",image_new_xs(this, "gui_active") ,
3517 gravity_left_center |orientation_vertical,
3518 gui_internal_table_button_next,NULL);
3519 data->next_button->data=widget;
3522 data->prev_button = gui_internal_button_new_with_callback
3524 image_new_xs(this, "gui_active")
3525 ,gravity_right_center |orientation_vertical,
3526 gui_internal_table_button_prev,NULL);
3528 data->prev_button->data=widget;
3532 data->button_box=gui_internal_box_new(this,
3533 gravity_center|orientation_horizontal);
3534 data->button_box->children=g_list_append(data->button_box->children,
3536 data->button_box->children=g_list_append(data->button_box->children,
3538 data->button_box->background=this->background2;
3539 data->button_box->bl=this->spacing;
3540 widget->children=g_list_append(widget->children,data->button_box);
3541 gui_internal_widget_pack(this,data->button_box);
3549 * @brief Adds a row to a table_widget.
3551 * @param table The table to add the row to.
3552 * @param row A table_row widget that will be added to the table.
3554 void gui_internal_widget_table_add_row(struct widget * table, struct widget * row)
3556 table->children=g_list_append(table->children,row);
3561 * Creates a new table_row widget.
3562 * @param this The graphics context
3563 * @param flags Sizing flags for the row
3564 * @returns The new table_row widget.
3566 static struct widget * gui_internal_widget_table_row_new(struct gui_priv * this, enum flags flags)
3568 struct widget * widget = g_new0(struct widget,1);
3569 widget->type=widget_table_row;
3570 widget->flags=flags;
3577 * @brief Computes the column dimensions for the table.
3579 * @param w The table widget to compute dimensions for.
3581 * This function examines all of the rows and columns for the table w
3582 * and returns a list (GList) of table_column_desc elements that
3583 * describe each column of the table.
3585 * The caller is responsible for freeing the returned list.
3587 static GList * gui_internal_compute_table_dimensions(struct widget * w)
3590 GList * column_desc = NULL;
3591 GList * current_desc=NULL;
3592 GList * cur_row = w->children;
3593 struct widget * cur_row_widget=NULL;
3594 GList * cur_column=NULL;
3595 struct widget * cell_w=NULL;
3596 struct table_column_desc * current_cell=NULL;
3597 struct table_data * table_data=NULL;
3603 * Scroll through the the table and
3604 * 1. Compute the maximum width + height of each column across all rows.
3606 table_data = (struct table_data*) w->data;
3607 for(cur_row=w->children; cur_row ; cur_row = g_list_next(cur_row) )
3609 cur_row_widget = (struct widget*) cur_row->data;
3610 current_desc = column_desc;
3611 if(cur_row_widget == table_data->button_box)
3615 for(cur_column = cur_row_widget->children; cur_column;
3616 cur_column=g_list_next(cur_column))
3618 cell_w = (struct widget*) cur_column->data;
3619 if(current_desc == 0)
3621 current_cell = g_new0(struct table_column_desc,1);
3622 column_desc = g_list_append(column_desc,current_cell);
3623 current_desc = g_list_last(column_desc);
3624 current_cell->height=cell_w->h;
3625 current_cell->width=cell_w->w;
3630 current_cell = current_desc->data;
3633 if(current_cell->height < height )
3635 current_cell->height = height;
3637 if(current_cell->width < width)
3639 current_cell->width = width;
3641 current_desc = g_list_next(current_desc);
3652 * @brief Computes the height and width for the table.
3654 * The height and widht are computed to display all cells in the table
3655 * at the requested height/width.
3657 * @param this The graphics context
3658 * @param w The widget to pack.
3661 void gui_internal_table_pack(struct gui_priv * this, struct widget * w)
3667 GList * column_data = gui_internal_compute_table_dimensions(w);
3669 struct table_column_desc * cell_desc=0;
3670 struct table_data * table_data = (struct table_data*)w->data;
3672 for(current = column_data; current; current=g_list_next(current))
3674 if(table_data->button_box == current->data )
3678 cell_desc = (struct table_column_desc *) current->data;
3679 width = width + cell_desc->width + this->spacing;
3680 if(height < cell_desc->height)
3682 height = cell_desc->height ;
3686 for(current=w->children; current; current=g_list_next(current))
3688 if(current->data!= table_data->button_box)
3693 gui_internal_widget_pack(this,table_data->button_box);
3694 w->h = count * (height+this->spacing) + table_data->button_box + this->spacing;
3696 if(w->h + w->c.y > this->root.h )
3699 * Do not allow the widget to exceed the screen.
3702 w->h = this->root.h- w->c.y - height;
3707 * Deallocate column descriptions.
3709 current = column_data;
3710 while( (current = g_list_last(current)) )
3712 current = g_list_remove(current,current->data);
3720 * @brief Renders a table widget.
3722 * @param this The graphics context
3723 * @param w The table widget to render.
3725 void gui_internal_table_render(struct gui_priv * this, struct widget * w)
3730 GList * column_desc=NULL;
3731 GList * cur_row = NULL;
3732 GList * current_desc=NULL;
3733 struct table_data * table_data = (struct table_data*)w->data;
3735 struct table_column_desc * dim=NULL;
3737 column_desc = gui_internal_compute_table_dimensions(w);
3742 * Skip rows that are on previous pages.
3744 cur_row = w->children;
3745 if(table_data->top_row )
3747 cur_row = table_data->top_row;
3752 * Loop through each row. Drawing each cell with the proper sizes,
3753 * at the proper positions.
3755 for(table_data->top_row=cur_row; cur_row; cur_row = g_list_next(cur_row))
3757 GList * cur_column=NULL;
3758 current_desc = column_desc;
3759 struct widget * cur_row_widget = (struct widget*)cur_row->data;
3761 x =w->p.x+this->spacing;
3762 if(cur_row_widget == table_data->button_box )
3766 dim = (struct table_column_desc*)current_desc->data;
3768 if( y + dim->height + table_data->button_box->h + this->spacing >= w->p.y + w->h )
3771 * No more drawing space left.
3777 for(cur_column = cur_row_widget->children; cur_column;
3778 cur_column=g_list_next(cur_column))
3780 struct widget * cur_widget = (struct widget*) cur_column->data;
3781 dim = (struct table_column_desc*)current_desc->data;
3784 cur_widget->w=dim->width;
3786 cur_widget->h=dim->height;
3788 max_height = dim->height;
3789 gui_internal_widget_render(this,cur_widget);
3791 if(dim->height > max_height)
3793 max_height = dim->height;
3797 table_data->bottom_row=cur_row;
3798 current_desc = g_list_next(current_desc);
3800 if(table_data && table_data->button_box )
3802 table_data->button_box->p.y =w->p.y+w->h-table_data->button_box->h -
3804 if(table_data->button_box->p.y < y )
3806 table_data->button_box->p.y=y;
3808 table_data->button_box->p.x = w->p.x;
3809 table_data->button_box->w = w->w;
3810 // table_data->button_box->h = w->h - y;
3811 // table_data->next_button->h=table_data->button_box->h;
3812 // table_data->prev_button->h=table_data->button_box->h;
3813 // table_data->next_button->c.y=table_data->button_box->c.y;
3814 // table_data->prev_button->c.y=table_data->button_box->c.y;
3816 gui_internal_widget_pack(this,table_data->button_box);
3817 if(table_data->next_button->p.y > w->p.y + w->h + table_data->next_button->h)
3820 table_data->button_box->p.y = w->p.y + w->h -
3821 table_data->button_box->h;
3825 table_data->next_button->state|= STATE_SENSITIVE;
3829 table_data->next_button->state&= ~STATE_SENSITIVE;
3832 if(table_data->top_row != w->children)
3834 table_data->prev_button->state|= STATE_SENSITIVE;
3838 table_data->prev_button->state&= ~STATE_SENSITIVE;
3840 gui_internal_widget_render(this,table_data->button_box);
3846 * Deallocate column descriptions.
3848 current_desc = column_desc;
3849 while( (current_desc = g_list_last(current_desc)) )
3851 current_desc = g_list_remove(current_desc,current_desc->data);
3857 * TEST function for demonstrating table.
3859 void gui_internal_cmd_route(struct gui_priv * this, struct widget * wm)
3863 struct widget * menu;
3868 w = gui_internal_widget_table_new(this,gravity_center | orientation_vertical);
3870 for(idx=0; idx < 52; idx++)
3872 struct widget * row = gui_internal_widget_table_row_new
3873 (this,gravity_left_top);
3874 sprintf(buffer, "Test %d",idx);
3875 row->children = g_list_append(row->children,
3876 gui_internal_label_new(this,buffer));
3877 row->children= g_list_append(row->children,
3878 gui_internal_label_new(this,"column 2 4 6 8"));
3879 gui_internal_widget_table_add_row(w,row);
3881 menu=gui_internal_menu(this,"Route");
3882 gui_internal_widget_append(menu,w);
3883 gui_internal_menu_render(this);
3890 * @brief handles the 'next page' table event.
3891 * A callback function that is invoked when the 'next page' button is pressed
3892 * to advance the contents of a table widget.
3894 * @param this The graphics context.
3895 * @param wm The button widget that was pressed.
3897 static void gui_internal_table_button_next(struct gui_priv * this, struct widget * wm, void *data)
3899 struct widget * table_widget = (struct widget * ) wm->data;
3900 struct table_data * table_data = NULL;
3906 table_data = (struct table_data*) table_widget->data;
3912 * Before advancing to the next page we need to ensure
3913 * that the current top_row is in the list of previous top_rows
3914 * so previous page can work.
3917 for(iterator=table_data->page_headers; iterator != NULL;
3918 iterator = g_list_next(iterator) )
3920 if(iterator->data == table_data->top_row)
3929 table_data->page_headers=g_list_append(table_data->page_headers,
3930 table_data->top_row);
3933 table_data->top_row = g_list_next(table_data->bottom_row);
3935 wm->state&= ~STATE_HIGHLIGHTED;
3936 gui_internal_menu_render(this);
3942 * @brief handles the 'previous page' table event.
3943 * A callback function that is invoked when the 'previous page' button is pressed
3944 * to go back in the contents of a table widget.
3946 * @param this The graphics context.
3947 * @param wm The button widget that was pressed.
3949 static void gui_internal_table_button_prev(struct gui_priv * this, struct widget * wm, void *data)
3951 struct widget * table_widget = (struct widget * ) wm->data;
3952 struct table_data * table_data = NULL;
3953 GList * current_page_top=NULL;
3958 table_data = (struct table_data*) table_widget->data;
3959 current_page_top = table_data->top_row;
3962 for(iterator = table_data->page_headers; iterator != NULL;
3963 iterator = g_list_next(iterator))
3965 if(current_page_top == iterator->data)
3969 table_data->top_row = (GList*) iterator->data;
3973 wm->state&= ~STATE_HIGHLIGHTED;
3974 gui_internal_menu_render(this);
3979 * @brief deallocates a table_data structure.
3982 void gui_internal_table_data_free(void * p)
3987 * @note button_box and its children (next_button,prev_button)
3988 * have their memory managed by the table itself.
3990 struct table_data * table_data = (struct table_data*) p;
3991 g_list_free(table_data->page_headers);