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"
67 struct widget *search_list;
68 struct widget *keyboard;
69 struct widget *button_bar;
71 void (*redisplay)(struct gui_priv *priv, struct widget *widget, void *data);
72 struct widget *redisplay_widget;
75 //##############################################################################################################
78 //# Authors: Martin Schaller (04/2008)
79 //##############################################################################################################
81 enum widget_type type;
82 struct graphics_gc *background,*text_background;
83 struct graphics_gc *foreground_frame;
84 struct graphics_gc *foreground;
86 struct graphics_image *img;
88 * A function to be invoked on actions.
89 * @li widget The widget that is receiving the button press.
92 void (*func)(struct gui_priv *priv, struct widget *widget, void *data);
96 void (*data_free)(void *data);
107 int bl,br,bt,bb,spx,spy;
112 int (*set_attr)(void *, struct attr *);
113 int (*get_attr)(void *, enum attr_type, struct attr *, struct attr_iter *);
114 void (*remove_cb)(void *, struct callback *cb);
121 struct menu_data *menu_data;
126 * @brief A structure to store configuration values.
128 * This structure stores configuration values for how gui elements in the internal GUI
131 struct gui_config_settings {
134 * The base size (in fractions of a point) to use for text.
138 * The size (in pixels) that xs style icons should be scaled to.
142 * The size (in pixels) that s style icons (small) should be scaled to
146 * The size (in pixels) that l style icons should be scaled to
150 * The default amount of spacing (in pixels) to place between GUI elements.
157 * Indexes into the config_profiles array.
159 const int LARGE_PROFILE=0;
160 const int MEDIUM_PROFILE=1;
161 const int SMALL_PROFILE=2;
164 * The default config profiles.
166 * [0] => LARGE_PROFILE (screens 640 in one dimension)
167 * [1] => MEDIUM PROFILE (screens larger than 320 in one dimension
168 * [2] => Small profile (default)
170 static struct gui_config_settings config_profiles[]={
176 //##############################################################################################################
179 //# Authors: Martin Schaller (04/2008)
180 //##############################################################################################################
184 struct graphics *gra;
185 struct graphics_gc *background;
186 struct graphics_gc *background2;
187 struct graphics_gc *highlight_background;
188 struct graphics_gc *foreground;
189 struct graphics_gc *text_foreground;
190 struct graphics_gc *text_background;
191 struct color background_color, background2_color, text_foreground_color, text_background_color;
195 struct graphics_font *font;
196 int icon_xs, icon_s, icon_l;
198 struct widget *widgets;
202 struct widget *highlighted;
203 struct widget *highlighted_menu;
204 int clickp_valid, vehicle_valid;
205 struct pcoord clickp, vehiclep;
206 struct search_list *sl;
208 int menu_on_map_click;
213 * The setting information read from the configuration file.
214 * values of -1 indicate no value was specified in the config file.
216 struct gui_config_settings config;
217 struct event_idle *idle;
218 struct callback *motion_cb,*button_cb,*resize_cb,*keypress_cb,*idle_cb, *motion_timeout_callback;
219 struct event_timeout *motion_timeout_event;
220 struct point current;
221 struct gui_internal_data data;
222 struct callback_list *cbl;
225 struct attr osd_configuration;
230 * @brief A structure to store information about a table.
232 * The table_data widget stores pointers to extra information needed by the
235 * The table_data structure needs to be freed with data_free along with the widget.
241 * A GList pointer into a widget->children list that indicates the row
242 * currently being rendered at the top of the table.
246 * A Glist pointer into a widget->children list that indicates the row
247 * currently being rendered at the bottom of the table.
252 * A list of table_row widgets that mark the
253 * top rows for each page of the table.
254 * This is needed for the 'previous page' function of the table.
256 GList * page_headers;
259 * A container box that is the child of the table widget that contains+groups
260 * the next and previous button.
262 struct widget * button_box;
265 * A button widget to handle 'next page' requests
267 struct widget * next_button;
269 * A button widget to handle 'previous page' requests.
271 struct widget * prev_button;
275 * a pointer to the gui context.
276 * This is needed by the free function to destory the buttons.
278 struct gui_priv * this;
282 * A data structure that holds information about a column that makes up a table.
286 struct table_column_desc
290 * The computed height of a cell in the table.
295 * The computed width of a cell in the table.
300 static void gui_internal_widget_render(struct gui_priv *this, struct widget *w);
301 static void gui_internal_widget_pack(struct gui_priv *this, struct widget *w);
302 static struct widget * gui_internal_box_new(struct gui_priv *this, enum flags flags);
303 static void gui_internal_widget_append(struct widget *parent, struct widget *child);
304 static void gui_internal_widget_destroy(struct gui_priv *this, struct widget *w);
305 static void gui_internal_apply_config(struct gui_priv *this);
307 static struct widget* gui_internal_widget_table_new(struct gui_priv * this, enum flags flags, int buttons);
308 static void gui_internal_widget_table_add_row(struct widget * table, struct widget * row);
309 static void gui_internal_table_render(struct gui_priv * this, struct widget * w);
310 static void gui_internal_cmd_route(struct gui_priv * this, struct widget * w);
311 static void gui_internal_table_pack(struct gui_priv * this, struct widget * w);
312 static void gui_internal_table_button_next(struct gui_priv * this, struct widget * wm, void *data);
313 static void gui_internal_table_button_prev(struct gui_priv * this, struct widget * wm, void *data);
314 static struct widget * gui_internal_widget_table_row_new(struct gui_priv * this, enum flags flags);
315 static void gui_internal_table_data_free(void * d);
317 static void gui_internal_search_idle_end(struct gui_priv *this);
318 static void gui_internal_search(struct gui_priv *this, char *what, char *type, int flags);
319 static void gui_internal_search_street(struct gui_priv *this, struct widget *widget, void *data);
320 static void gui_internal_search_street_in_town(struct gui_priv *this, struct widget *widget, void *data);
321 static void gui_internal_search_town(struct gui_priv *this, struct widget *wm, void *data);
322 static void gui_internal_search_town_in_country(struct gui_priv *this, struct widget *wm);
323 static void gui_internal_search_country(struct gui_priv *this, struct widget *widget, void *data);
325 static struct widget *gui_internal_keyboard_do(struct gui_priv *this, struct widget *wkbdb, int mode);
326 static struct menu_data * gui_internal_menu_data(struct gui_priv *this);
328 static struct graphics_image *
329 image_new_scaled(struct gui_priv *this, char *name, int w, int h)
331 struct graphics_image *ret=NULL;
332 char *full_name=NULL;
335 for (i = 1 ; i < 6 ; i++) {
339 full_name=g_strdup_printf("%s/xpm/%s.svg", getenv("NAVIT_SHAREDIR"), name);
342 full_name=g_strdup_printf("%s/xpm/%s.svgz", getenv("NAVIT_SHAREDIR"), name);
345 if (w != -1 && h != -1) {
346 full_name=g_strdup_printf("%s/xpm/%s_%d_%d.png", getenv("NAVIT_SHAREDIR"), name, w, h);
350 full_name=g_strdup_printf("%s/xpm/%s.png", getenv("NAVIT_SHAREDIR"), name);
353 full_name=g_strdup_printf("%s/xpm/%s.xpm", getenv("NAVIT_SHAREDIR"), name);
356 dbg(1,"trying '%s'\n", full_name);
359 if (!file_exists(full_name)) {
363 ret=graphics_image_new_scaled(this->gra, full_name, w, h);
364 dbg(1,"ret=%p\n", ret);
369 dbg(0,"failed to load %s with %d,%d\n", name, w, h);
374 static struct graphics_image *
375 image_new_o(struct gui_priv *this, char *name)
377 return image_new_scaled(this, name, -1, -1);
380 static struct graphics_image *
381 image_new_xs(struct gui_priv *this, char *name)
383 return image_new_scaled(this, name, this->icon_xs, this->icon_xs);
387 static struct graphics_image *
388 image_new_s(struct gui_priv *this, char *name)
390 return image_new_scaled(this, name, this->icon_s, this->icon_s);
393 static struct graphics_image *
394 image_new_l(struct gui_priv *this, char *name)
396 return image_new_scaled(this, name, this->icon_l, this->icon_l);
400 coordinates(struct pcoord *pc, char sep)
402 char latc='N',lngc='E';
403 int lat_deg,lat_min,lat_sec;
404 int lng_deg,lng_min,lng_sec;
409 transform_to_geo(pc->pro, &c, &g);
420 lat_min=fmod(g.lat*60,60);
421 lat_sec=fmod(g.lat*3600,60);
423 lng_min=fmod(g.lng*60,60);
424 lng_sec=fmod(g.lng*3600,60);
425 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);
429 gui_internal_background_render(struct gui_priv *this, struct widget *w)
431 struct point pnt=w->p;
432 if (w->state & STATE_HIGHLIGHTED)
433 graphics_draw_rectangle(this->gra, this->highlight_background, &pnt, w->w, w->h);
436 graphics_draw_rectangle(this->gra, w->background, &pnt, w->w, w->h);
439 static struct widget *
440 gui_internal_label_new(struct gui_priv *this, char *text)
446 struct widget *widget=g_new0(struct widget, 1);
447 widget->type=widget_label;
449 widget->text=g_strdup(text);
450 graphics_get_text_bbox(this->gra, this->font, text, 0x10000, 0x0, p, 0);
454 widget->h=h+this->spacing;
456 widget->w=w+this->spacing;
458 widget->flags=gravity_center;
459 widget->foreground=this->text_foreground;
460 widget->text_background=this->text_background;
465 static struct widget *
466 gui_internal_label_new_abbrev(struct gui_priv *this, char *text, int maxwidth)
468 struct widget *ret=NULL;
469 char *tmp=g_malloc(strlen(text)+3);
476 ret=gui_internal_label_new(this, tmp);
477 if (ret->w < maxwidth)
479 gui_internal_widget_destroy(this, ret);
487 static struct widget *
488 gui_internal_image_new(struct gui_priv *this, struct graphics_image *image)
490 struct widget *widget=g_new0(struct widget, 1);
491 widget->type=widget_image;
494 widget->w=image->width;
495 widget->h=image->height;
501 gui_internal_image_render(struct gui_priv *this, struct widget *w)
505 gui_internal_background_render(this, w);
508 pnt.x+=w->w/2-w->img->hot.x;
509 pnt.y+=w->h/2-w->img->hot.y;
510 graphics_draw_image(this->gra, this->foreground, &pnt, w->img);
515 gui_internal_label_render(struct gui_priv *this, struct widget *w)
517 struct point pnt=w->p;
518 gui_internal_background_render(this, w);
520 if (w->flags & gravity_right) {
521 pnt.y+=w->h-this->spacing;
522 pnt.x+=w->w-w->textw-this->spacing;
523 graphics_draw_text(this->gra, w->foreground, w->text_background, this->font, w->text, &pnt, 0x10000, 0x0);
525 pnt.y+=w->h-this->spacing;
526 graphics_draw_text(this->gra, w->foreground, w->text_background, this->font, w->text, &pnt, 0x10000, 0x0);
531 static struct widget *
532 gui_internal_text_new(struct gui_priv *this, char *text, enum flags flags)
534 char *s=g_strdup(text),*s2,*tok;
535 struct widget *ret=gui_internal_box_new(this, flags);
537 while ((tok=strtok(s2,"\n"))) {
538 gui_internal_widget_append(ret, gui_internal_label_new(this, tok));
545 static struct widget *
546 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)
548 struct widget *ret=NULL;
549 ret=gui_internal_box_new(this, flags);
552 gui_internal_widget_append(ret, gui_internal_image_new(this, image));
554 gui_internal_widget_append(ret, gui_internal_text_new(this, text, gravity_center|orientation_vertical));
558 ret->state |= STATE_SENSITIVE;
559 ret->speech=g_strdup(text);
567 gui_internal_button_attr_update(struct gui_priv *this, struct widget *w)
574 if (w->get_attr(w->instance, w->on.type, &curr, NULL))
575 is_on=curr.u.data == w->on.u.data;
578 if (is_on != w->is_on) {
582 l=g_list_first(w->children);
586 graphics_image_free(this->gra, wi->img);
587 wi->img=image_new_xs(this, is_on ? "gui_active" : "gui_inactive");
589 if (w->is_on && w->off.type == attr_none)
590 w->state &= ~STATE_SENSITIVE;
592 w->state |= STATE_SENSITIVE;
599 gui_internal_button_attr_callback(struct gui_priv *this, struct widget *w)
601 if (gui_internal_button_attr_update(this, w))
602 gui_internal_widget_render(this, w);
605 gui_internal_button_attr_pressed(struct gui_priv *this, struct widget *w, void *data)
608 w->set_attr(w->instance, &w->off);
610 w->set_attr(w->instance, &w->on);
611 gui_internal_button_attr_update(this, w);
615 static struct widget *
616 gui_internal_button_navit_attr_new(struct gui_priv *this, char *text, enum flags flags, struct attr *on, struct attr *off)
618 struct graphics_image *image=image_new_xs(this, "gui_inactive");
620 ret=gui_internal_button_new_with_callback(this, text, image, flags, gui_internal_button_attr_pressed, NULL);
625 ret->get_attr=(int (*)(void *, enum attr_type, struct attr *, struct attr_iter *))navit_get_attr;
626 ret->set_attr=(int (*)(void *, struct attr *))navit_set_attr;
627 ret->remove_cb=(void (*)(void *, struct callback *))navit_remove_callback;
628 ret->instance=this->nav;
629 ret->cb=callback_new_attr_2(callback_cast(gui_internal_button_attr_callback), on->type, this, ret);
630 navit_add_callback(this->nav, ret->cb);
631 gui_internal_button_attr_update(this, ret);
635 static struct widget *
636 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)
638 struct graphics_image *image=image_new_xs(this, "gui_inactive");
640 ret=gui_internal_button_new_with_callback(this, text, image, flags, gui_internal_button_attr_pressed, NULL);
646 ret->get_attr=(int (*)(void *, enum attr_type, struct attr *, struct attr_iter *))map_get_attr;
647 ret->set_attr=(int (*)(void *, struct attr *))map_set_attr;
648 ret->remove_cb=(void (*)(void *, struct callback *))map_remove_callback;
651 ret->cb=callback_new_attr_2(callback_cast(gui_internal_button_attr_callback), on->type, this, ret);
652 map_add_callback(map, ret->cb);
653 gui_internal_button_attr_update(this, ret);
657 static struct widget *
658 gui_internal_button_new(struct gui_priv *this, char *text, struct graphics_image *image, enum flags flags)
660 return gui_internal_button_new_with_callback(this, text, image, flags, NULL, NULL);
663 //##############################################################################################################
666 //# Authors: Martin Schaller (04/2008)
667 //##############################################################################################################
668 static void gui_internal_clear(struct gui_priv *this)
670 struct graphics *gra=this->gra;
674 graphics_draw_rectangle(gra, this->background, &pnt, this->root.w, this->root.h);
677 static struct widget *
678 gui_internal_find_widget(struct widget *wi, struct point *p, int flags)
680 struct widget *ret,*child;
681 GList *l=wi->children;
688 if ( wi->p.x + wi->w < p->x)
690 if ( wi->p.y + wi->h < p->y)
693 if (wi->state & flags)
697 ret=gui_internal_find_widget(child, p, flags);
708 gui_internal_highlight_do(struct gui_priv *this, struct widget *found)
710 if (found == this->highlighted)
713 graphics_draw_mode(this->gra, draw_mode_begin);
714 if (this->highlighted) {
715 this->highlighted->state &= ~STATE_HIGHLIGHTED;
716 if (this->root.children && this->highlighted_menu == g_list_last(this->root.children)->data)
717 gui_internal_widget_render(this, this->highlighted);
718 this->highlighted=NULL;
719 this->highlighted_menu=NULL;
722 this->highlighted=found;
723 this->highlighted_menu=g_list_last(this->root.children)->data;
724 this->highlighted->state |= STATE_HIGHLIGHTED;
725 gui_internal_widget_render(this, this->highlighted);
726 dbg(1,"%d,%d %dx%d\n", found->p.x, found->p.y, found->w, found->h);
728 graphics_draw_mode(this->gra, draw_mode_end);
730 //##############################################################################################################
733 //# Authors: Martin Schaller (04/2008)
734 //##############################################################################################################
735 static void gui_internal_highlight(struct gui_priv *this)
737 struct widget *menu,*found=NULL;
738 if (this->current.x > -1 && this->current.y > -1) {
739 menu=g_list_last(this->root.children)->data;
740 found=gui_internal_find_widget(menu, &this->current, STATE_SENSITIVE);
742 gui_internal_highlight_do(this, found);
743 this->motion_timeout_event=NULL;
746 static struct widget *
747 gui_internal_box_new_with_label(struct gui_priv *this, enum flags flags, char *label)
749 struct widget *widget=g_new0(struct widget, 1);
752 widget->text=g_strdup(label);
753 widget->type=widget_box;
758 static struct widget *
759 gui_internal_box_new(struct gui_priv *this, enum flags flags)
761 return gui_internal_box_new_with_label(this, flags, NULL);
765 static void gui_internal_box_render(struct gui_priv *this, struct widget *w)
770 gui_internal_background_render(this, w);
772 if (w->foreground && w->border) {
775 pnt[1].x=pnt[0].x+w->w;
777 pnt[2].x=pnt[0].x+w->w;
778 pnt[2].y=pnt[0].y+w->h;
780 pnt[3].y=pnt[0].y+w->h;
782 graphics_gc_set_linewidth(w->foreground, w->border ? w->border : 1);
783 graphics_draw_lines(this->gra, w->foreground, pnt, 5);
784 graphics_gc_set_linewidth(w->foreground, 1);
791 gui_internal_widget_render(this, wc);
796 static void gui_internal_box_pack(struct gui_priv *this, struct widget *w)
799 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;
801 int orientation=w->flags & 0xffff0000;
806 height=navit_get_height(this->nav);
807 width=navit_get_width(this->nav);
808 if ( (height/width) > 1.0 )
822 if (orientation == orientation_horizontal_vertical && count <= cols)
823 orientation=orientation_horizontal;
824 switch (orientation) {
825 case orientation_horizontal:
829 gui_internal_widget_pack(this, wc);
833 if (wc->flags & flags_expand)
834 expand+=wc->w ? wc->w : 1;
840 if (expand && w->w) {
841 expand=100*(w->w-width+expand)/expand;
846 case orientation_vertical:
850 gui_internal_widget_pack(this, wc);
854 if (wc->flags & flags_expand)
855 expand+=wc->h ? wc->h : 1;
861 if (expand && w->h) {
862 expand=100*(w->h-height+expand)/expand;
867 case orientation_horizontal_vertical:
872 gui_internal_widget_pack(this, wc);
882 rows=(count+cols-1)/cols;
885 width+=w->spx*(cols-1);
886 height+=w->spy*(rows-1);
894 if (! w->w && ! w->h) {
895 w->w=w->bl+w->br+width;
896 w->h=w->bt+w->bb+height;
898 if (w->flags & gravity_left)
900 if (w->flags & gravity_xcenter)
901 x=w->p.x+w->w/2-owidth/2;
902 if (w->flags & gravity_right)
903 x=w->p.x+w->w-w->br-owidth;
904 if (w->flags & gravity_top)
906 if (w->flags & gravity_ycenter)
907 y=w->p.y+w->h/2-oheight/2;
908 if (w->flags & gravity_bottom)
909 y=w->p.y+w->h-w->bb-oheight;
911 switch (orientation) {
912 case orientation_horizontal:
917 if (wc->flags & flags_fill)
919 if (wc->flags & flags_expand) {
922 wc->w=wc->w*expand/100;
924 if (w->flags & gravity_top)
926 if (w->flags & gravity_ycenter)
928 if (w->flags & gravity_bottom)
934 case orientation_vertical:
939 if (wc->flags & flags_fill)
941 if (wc->flags & flags_expand) {
944 wc->h=wc->h*expand/100;
946 if (w->flags & gravity_left)
948 if (w->flags & gravity_xcenter)
950 if (w->flags & gravity_right)
956 case orientation_horizontal_vertical:
966 if (wc->flags & flags_fill) {
970 if (w->flags & gravity_left)
972 if (w->flags & gravity_xcenter)
973 wc->p.x=x+(width-wc->w)/2;
974 if (w->flags & gravity_right)
975 wc->p.x=x+width-wc->w;
976 if (w->flags & gravity_top)
978 if (w->flags & gravity_ycenter)
979 wc->p.y=y+(height-wc->h)/2;
980 if (w->flags & gravity_bottom)
981 wc->p.y=y-height-wc->h;
983 if (++count == cols) {
997 gui_internal_widget_pack(this, wc);
1003 gui_internal_widget_append(struct widget *parent, struct widget *child)
1007 if (! child->background)
1008 child->background=parent->background;
1009 parent->children=g_list_append(parent->children, child);
1012 static void gui_internal_widget_prepend(struct widget *parent, struct widget *child)
1014 if (! child->background)
1015 child->background=parent->background;
1016 parent->children=g_list_prepend(parent->children, child);
1019 static void gui_internal_widget_children_destroy(struct gui_priv *this, struct widget *w)
1027 gui_internal_widget_destroy(this, wc);
1030 g_list_free(w->children);
1034 static void gui_internal_widget_destroy(struct gui_priv *this, struct widget *w)
1036 gui_internal_widget_children_destroy(this, w);
1040 graphics_image_free(this->gra, w->img);
1046 w->data_free(w->data);
1047 if (w->cb && w->remove_cb)
1048 w->remove_cb(w->instance, w->cb);
1054 gui_internal_widget_render(struct gui_priv *this, struct widget *w)
1056 if(w->p.x > navit_get_width(this->nav) || w->p.y > navit_get_height(this->nav))
1061 gui_internal_box_render(this, w);
1064 gui_internal_label_render(this, w);
1067 gui_internal_image_render(this, w);
1070 gui_internal_table_render(this,w);
1078 gui_internal_widget_pack(struct gui_priv *this, struct widget *w)
1082 gui_internal_box_pack(this, w);
1085 gui_internal_table_pack(this,w);
1091 //##############################################################################################################
1094 //# Authors: Martin Schaller (04/2008)
1095 //##############################################################################################################
1096 static void gui_internal_call_highlighted(struct gui_priv *this)
1098 if (! this->highlighted || ! this->highlighted->func)
1100 this->highlighted->reason=1;
1101 this->highlighted->func(this, this->highlighted, this->highlighted->data);
1105 gui_internal_say(struct gui_priv *this, struct widget *w, int questionmark)
1107 char *text=w->speech;
1115 text=g_strdup_printf("%s%c", text, questionmark ? '?':'\0');
1116 navit_say(this->nav, text);
1122 gui_internal_prune_menu(struct gui_priv *this, struct widget *w)
1126 gui_internal_search_idle_end(this);
1127 while ((l = g_list_last(this->root.children))) {
1129 void (*redisplay)(struct gui_priv *priv, struct widget *widget, void *data);
1130 gui_internal_say(this, w, 0);
1131 redisplay=w->menu_data->redisplay;
1132 wr=w->menu_data->redisplay_widget;
1133 if (!w->menu_data->redisplay) {
1134 gui_internal_widget_render(this, w);
1137 gui_internal_widget_destroy(this, l->data);
1138 this->root.children=g_list_remove(this->root.children, l->data);
1139 redisplay(this, wr, wr->data);
1142 gui_internal_widget_destroy(this, l->data);
1143 this->root.children=g_list_remove(this->root.children, l->data);
1148 gui_internal_prune_menu_count(struct gui_priv *this, int count, int render)
1151 gui_internal_search_idle_end(this);
1152 while ((l = g_list_last(this->root.children)) && count-- > 0) {
1153 gui_internal_widget_destroy(this, l->data);
1154 this->root.children=g_list_remove(this->root.children, l->data);
1157 gui_internal_say(this, l->data, 0);
1158 gui_internal_widget_render(this, l->data);
1163 gui_internal_back(struct gui_priv *this, struct widget *w, void *data)
1165 gui_internal_prune_menu_count(this, 1, 1);
1169 gui_internal_cmd_return(struct gui_priv *this, struct widget *wm, void *data)
1171 gui_internal_prune_menu(this, wm->data);
1175 gui_internal_cmd_main_menu(struct gui_priv *this, struct widget *wm, void *data)
1177 gui_internal_prune_menu(this, this->root.children->data);
1180 static struct widget *
1181 gui_internal_top_bar(struct gui_priv *this)
1183 struct widget *w,*wm,*wh,*wc,*wcn;
1184 int dots_len, sep_len;
1186 int width,width_used=0,use_sep=0,incomplete=0;
1187 struct graphics_gc *foreground=(this->flags & 256 ? this->background : this->text_foreground);
1189 1:Don't expand bar to screen width
1190 2:Don't show Map Icon
1191 4:Don't show Home Icon
1192 8:Show only current menu
1193 16:Don't use menu titles as button
1194 32:Show navit version
1197 256:Use background for menu headline
1198 512:Set osd_configuration and zoom to route when setting position
1201 w=gui_internal_box_new(this, gravity_left_center|orientation_horizontal|(this->flags & 1 ? 0:flags_fill));
1202 w->bl=this->spacing;
1203 w->spx=this->spacing;
1204 w->background=this->background2;
1205 if ((this->flags & 6) == 6) {
1211 width=this->root.w-w->bl;
1212 if (! (this->flags & 2)) {
1213 wm=gui_internal_button_new_with_callback(this, NULL,
1214 image_new_s(this, "gui_map"), gravity_center|orientation_vertical,
1215 gui_internal_cmd_return, NULL);
1216 wm->speech=g_strdup(_("Back to map"));
1217 gui_internal_widget_pack(this, wm);
1218 gui_internal_widget_append(w, wm);
1221 if (! (this->flags & 4)) {
1222 wh=gui_internal_button_new_with_callback(this, NULL,
1223 image_new_s(this, "gui_home"), gravity_center|orientation_vertical,
1224 gui_internal_cmd_main_menu, NULL);
1225 wh->speech=g_strdup(_("Main Menu"));
1226 gui_internal_widget_pack(this, wh);
1227 gui_internal_widget_append(w, wh);
1230 if (!(this->flags & 6))
1232 l=g_list_last(this->root.children);
1233 wcn=gui_internal_label_new(this,".. »");
1234 wcn->foreground=foreground;
1236 gui_internal_widget_destroy(this, wcn);
1237 wcn=gui_internal_label_new(this,"»");
1238 wcn->foreground=foreground;
1240 gui_internal_widget_destroy(this, wcn);
1242 if (g_list_previous(l) || !g_list_next(l)) {
1244 wcn=gui_internal_label_new(this, wc->text);
1245 wcn->foreground=foreground;
1250 dbg(1,"%d (%s) + %d + %d + %d > %d\n", wcn->w, wc->text, width_used, w->spx, use_sep ? sep_len : 0, width);
1251 if (wcn->w + width_used + w->spx + (use_sep ? sep_len : 0) + (g_list_previous(l) ? dots_len : 0) > width) {
1253 gui_internal_widget_destroy(this, wcn);
1257 struct widget *wct=gui_internal_label_new(this, "»");
1258 wct->foreground=foreground;
1259 res=g_list_prepend(res, wct);
1260 width_used+=sep_len+w->spx;
1263 if (!(this->flags & 16)) {
1264 wcn->func=gui_internal_cmd_return;
1266 wcn->state |= STATE_SENSITIVE;
1268 res=g_list_prepend(res, wcn);
1269 if (this->flags & 8)
1272 l=g_list_previous(l);
1276 wcn=gui_internal_label_new_abbrev(this, wc->text, width-width_used-w->spx-dots_len);
1277 wcn->foreground=foreground;
1278 wcn->func=gui_internal_cmd_return;
1280 wcn->state |= STATE_SENSITIVE;
1281 res=g_list_prepend(res, wcn);
1282 l=g_list_previous(l);
1285 wcn=gui_internal_label_new(this, ".. »");
1286 wcn->foreground=foreground;
1287 wcn->func=gui_internal_cmd_return;
1289 wcn->state |= STATE_SENSITIVE;
1290 res=g_list_prepend(res, wcn);
1294 gui_internal_widget_append(w, l->data);
1297 if (this->flags & 32) {
1298 extern char *version;
1299 char *version_text=g_strdup_printf("Navit %s",version);
1300 wcn=gui_internal_label_new(this, version_text);
1301 g_free(version_text);
1302 wcn->flags=gravity_right_center|flags_expand;
1303 gui_internal_widget_append(w, wcn);
1307 gui_internal_widget_destroy(this, dots);
1312 static struct widget *
1313 gui_internal_time_help(struct gui_priv *this)
1315 struct widget *w,*wm,*wh,*wc,*wcn;
1316 int dots_len, sep_len;
1318 int width,width_used=0,use_sep,incomplete=0;
1323 w=gui_internal_box_new(this, gravity_right_center|orientation_horizontal|flags_fill);
1324 w->bl=this->spacing;
1325 w->spx=this->spacing;
1331 if (this->flags & 64) {
1332 wc=gui_internal_box_new(this, gravity_right_top|orientation_vertical|flags_fill);
1338 tm=localtime(&timep);
1339 strftime(timestr, 64, "%H:%M %d.%m.%Y", tm);
1340 wcn=gui_internal_label_new(this, timestr);
1341 gui_internal_widget_append(wc, wcn);
1342 gui_internal_widget_append(w, wc);
1344 if (this->flags & 128) {
1345 wcn=gui_internal_button_new_with_callback(this, _("Help"), image_new_l(this, "gui_help"), gravity_center|orientation_vertical|flags_fill, NULL, NULL);
1346 gui_internal_widget_append(w, wcn);
1353 * Applys the configuration values to this based on the settings
1354 * specified in the configuration file (this->config) and
1355 * the most approriate default profile based on screen resolution.
1357 * This function should be run after this->root is setup and could
1358 * be rerun after the window is resized.
1360 * @authors Steve Singer <ssinger_pg@sympatico.ca> (09/2008)
1362 static void gui_internal_apply_config(struct gui_priv *this)
1364 struct gui_config_settings * current_config=0;
1366 dbg(0,"w=%d h=%d\n", this->root.w, this->root.h);
1368 * Select default values from profile based on the screen.
1370 if((this->root.w > 320 || this->root.h > 320) && this->root.w > 240 && this->root.h > 240)
1372 if((this->root.w > 640 || this->root.h > 640) && this->root.w > 480 && this->root.h > 480 )
1374 current_config = &config_profiles[LARGE_PROFILE];
1378 current_config = &config_profiles[MEDIUM_PROFILE];
1383 current_config = &config_profiles[SMALL_PROFILE];
1387 * Apply override values from config file
1389 if(this->config.font_size == -1 )
1391 this->font_size = current_config->font_size;
1395 this->font_size = this->config.font_size;
1398 if(this->config.icon_xs == -1 )
1400 this->icon_xs = current_config->icon_xs;
1404 this->icon_xs = this->config.icon_xs;
1407 if(this->config.icon_s == -1 )
1409 this->icon_s = current_config->icon_s;
1413 this->icon_s = this->config.icon_s;
1415 if(this->config.icon_l == -1 )
1417 this->icon_l = current_config->icon_l;
1421 this->icon_l = this->config.icon_l;
1423 if(this->config.spacing == -1 )
1425 this->spacing = current_config->spacing;
1429 this->spacing = current_config->spacing;
1434 static struct widget *
1435 gui_internal_button_label(struct gui_priv *this, char *label, int mode)
1437 struct widget *wl,*wlb;
1438 struct widget *wb=gui_internal_menu_data(this)->button_bar;
1439 wlb=gui_internal_box_new(this, gravity_right_center|orientation_vertical);
1440 wl=gui_internal_label_new(this, label);
1442 wlb->foreground=this->text_foreground;
1447 gui_internal_widget_append(wlb, wl);
1449 gui_internal_widget_prepend(wb, wlb);
1451 gui_internal_widget_append(wb, wlb);
1457 static struct widget *
1458 gui_internal_menu(struct gui_priv *this, char *label)
1460 struct widget *menu,*w,*w1,*topbox;
1462 gui_internal_search_idle_end(this);
1463 topbox=gui_internal_box_new_with_label(this, 0, label);
1464 topbox->w=this->root.w;
1465 topbox->h=this->root.h;
1466 gui_internal_widget_append(&this->root, topbox);
1467 menu=gui_internal_box_new(this, gravity_left_center|orientation_vertical);
1468 menu->w=this->root.w;
1469 menu->h=this->root.h;
1470 menu->background=this->background;
1471 gui_internal_apply_config(this);
1472 this->font=graphics_font_new(this->gra,this->font_size,1);
1473 topbox->menu_data=g_new0(struct menu_data, 1);
1474 gui_internal_widget_append(topbox, menu);
1475 w=gui_internal_top_bar(this);
1476 gui_internal_widget_append(menu, w);
1477 w=gui_internal_box_new(this, gravity_center|orientation_horizontal_vertical|flags_expand|flags_fill);
1478 w->spx=4*this->spacing;
1479 gui_internal_widget_append(menu, w);
1480 if (this->flags & 16) {
1481 struct widget *wl,*wlb,*wb,*wm=w;
1482 wm->flags=gravity_center|orientation_vertical|flags_expand|flags_fill;
1483 w=gui_internal_box_new(this, gravity_center|orientation_horizontal|flags_expand|flags_fill);
1484 dbg(0,"topbox->menu_data=%p\n", topbox->menu_data);
1485 gui_internal_widget_append(wm, w);
1486 wb=gui_internal_box_new(this, gravity_right_center|orientation_horizontal|flags_fill);
1492 topbox->menu_data->button_bar=wb;
1493 gui_internal_widget_append(wm, wb);
1494 wlb=gui_internal_button_label(this,_("Back"),1);
1495 wlb->func=gui_internal_back;
1496 wlb->state |= STATE_SENSITIVE;
1498 if (this->flags & 192) {
1499 menu=gui_internal_box_new(this, gravity_left_center|orientation_vertical);
1500 menu->w=this->root.w;
1501 menu->h=this->root.h;
1502 w1=gui_internal_time_help(this);
1503 gui_internal_widget_append(menu, w1);
1504 w1=gui_internal_box_new(this, gravity_center|orientation_horizontal_vertical|flags_expand|flags_fill);
1505 gui_internal_widget_append(menu, w1);
1506 gui_internal_widget_append(topbox, menu);
1507 menu->background=NULL;
1512 static struct menu_data *
1513 gui_internal_menu_data(struct gui_priv *this)
1516 struct widget *menu;
1518 l=g_list_last(this->root.children);
1520 return menu->menu_data;
1524 gui_internal_menu_render(struct gui_priv *this)
1527 struct widget *menu;
1529 l=g_list_last(this->root.children);
1531 gui_internal_say(this, menu, 0);
1532 gui_internal_widget_pack(this, menu);
1533 gui_internal_widget_render(this, menu);
1537 gui_internal_cmd_set_destination(struct gui_priv *this, struct widget *wm, void *data)
1539 struct widget *w=wm->data;
1540 dbg(0,"c=%d:0x%x,0x%x\n", w->c.pro, w->c.x, w->c.y);
1541 navit_set_destination(this->nav, &w->c, w->name);
1542 if (this->flags & 512) {
1543 navit_set_attr(this->nav, &this->osd_configuration);
1544 navit_zoom_to_route(this->nav);
1546 gui_internal_prune_menu(this, NULL);
1550 gui_internal_cmd_set_position(struct gui_priv *this, struct widget *wm, void *data)
1552 struct widget *w=wm->data;
1553 navit_set_position(this->nav, &w->c);
1554 gui_internal_prune_menu(this, NULL);
1558 gui_internal_cmd_add_bookmark_do(struct gui_priv *this, struct widget *widget)
1561 dbg(0,"text='%s'\n", widget->text);
1562 if (widget->text && strlen(widget->text))
1563 navit_add_bookmark(this->nav, &widget->c, widget->text);
1564 g_free(widget->text);
1566 l=g_list_previous(g_list_last(this->root.children));
1567 gui_internal_prune_menu(this, l->data);
1571 gui_internal_cmd_add_bookmark_clicked(struct gui_priv *this, struct widget *widget, void *data)
1573 gui_internal_cmd_add_bookmark_do(this, widget->data);
1577 gui_internal_cmd_add_bookmark_changed(struct gui_priv *this, struct widget *wm, void *data)
1582 len=strlen(wm->text);
1583 dbg(1,"len=%d\n", len);
1584 if (len && (wm->text[len-1] == '\n' || wm->text[len-1] == '\r')) {
1585 wm->text[len-1]='\0';
1586 gui_internal_cmd_add_bookmark_do(this, wm);
1592 static struct widget * gui_internal_keyboard(struct gui_priv *this, int mode);
1595 gui_internal_cmd_add_bookmark(struct gui_priv *this, struct widget *wm, void *data)
1597 struct widget *w,*wb,*wk,*wl,*we,*wnext,*wp=wm->data;
1598 wb=gui_internal_menu(this, "Add Bookmark");
1599 w=gui_internal_box_new(this, gravity_left_top|orientation_vertical|flags_expand|flags_fill);
1600 gui_internal_widget_append(wb, w);
1601 we=gui_internal_box_new(this, gravity_left_center|orientation_horizontal|flags_fill);
1602 gui_internal_widget_append(w, we);
1603 gui_internal_widget_append(we, wk=gui_internal_label_new(this, wp->name ? wp->name : wp->text));
1604 wk->state |= STATE_EDIT|STATE_CLEAR;
1605 wk->background=this->background;
1606 wk->flags |= flags_expand|flags_fill;
1607 wk->func = gui_internal_cmd_add_bookmark_changed;
1609 gui_internal_widget_append(we, wnext=gui_internal_image_new(this, image_new_xs(this, "gui_active")));
1610 wnext->state |= STATE_SENSITIVE;
1611 wnext->func = gui_internal_cmd_add_bookmark_clicked;
1613 wl=gui_internal_box_new(this, gravity_left_top|orientation_vertical|flags_expand|flags_fill);
1614 gui_internal_widget_append(w, wl);
1616 gui_internal_widget_append(w, gui_internal_keyboard(this,2));
1617 gui_internal_menu_render(this);
1622 get_direction(char *buffer, int angle, int mode)
1627 sprintf(buffer,"%d",angle);
1630 if (angle < 69 || angle > 291)
1632 if (angle > 111 && angle < 249)
1634 if (angle > 22 && angle < 158)
1636 if (angle > 202 && angle < 338)
1641 angle=(angle+15)/30;
1644 sprintf(buffer,"%d H", angle);
1652 enum item_type *types;
1654 {"bank","Bank",(enum item_type []){type_poi_bank,type_poi_bank,type_none}},
1655 {"fuel","Fuel",(enum item_type []){type_poi_fuel,type_poi_fuel,type_none}},
1656 {"hotel","Hotel",(enum item_type []) {
1657 type_poi_hotel,type_poi_camp_rv,
1658 type_poi_camping,type_poi_camping,
1659 type_poi_resort,type_poi_resort,
1661 {"restaurant","Restaurant",(enum item_type []) {
1662 type_poi_bar,type_poi_picnic,
1663 type_poi_burgerking,type_poi_fastfood,
1664 type_poi_restaurant,type_poi_restaurant,
1666 {"shopping","Shopping",(enum item_type []) {
1667 type_poi_mall,type_poi_mall,
1668 type_poi_shop_grocery,type_poi_shop_grocery,
1670 {"hospital","Service",(enum item_type []) {
1671 type_poi_marina,type_poi_marina,
1672 type_poi_hospital,type_poi_hospital,
1673 type_poi_public_utilities,type_poi_public_utilities,
1674 type_poi_police,type_poi_autoservice,
1675 type_poi_information,type_poi_information,
1676 type_poi_personal_service,type_poi_repair_service,
1677 type_poi_rest_room,type_poi_rest_room,
1678 type_poi_restroom,type_poi_restroom,
1680 {"parking","Parking",(enum item_type []){type_poi_car_parking,type_poi_car_parking,type_none}},
1681 {"peak","Land Features",(enum item_type []){
1682 type_poi_land_feature,type_poi_rock,
1683 type_poi_dam,type_poi_dam,
1685 {"unknown","Other",(enum item_type []){
1686 type_point_unspecified,type_poi_land_feature-1,
1687 type_poi_rock+1,type_poi_fuel-1,
1688 type_poi_marina+1,type_poi_car_parking-1,
1689 type_poi_car_parking+1,type_poi_bar-1,
1690 type_poi_bank+1,type_poi_dam-1,
1691 type_poi_dam+1,type_poi_information-1,
1692 type_poi_information+1,type_poi_mall-1,
1693 type_poi_mall+1,type_poi_personal_service-1,
1694 type_poi_restaurant+1,type_poi_restroom-1,
1695 type_poi_restroom+1,type_poi_shop_grocery-1,
1696 type_poi_shop_grocery+1,type_poi_wifi,
1700 static void gui_internal_cmd_pois(struct gui_priv *this, struct widget *wm, void *data);
1702 static struct widget *
1703 gui_internal_cmd_pois_selector(struct gui_priv *this, struct pcoord *c)
1705 struct widget *wl,*wb;
1707 wl=gui_internal_box_new(this, gravity_left_center|orientation_horizontal|flags_fill);
1708 for (i = 0 ; i < sizeof(selectors)/sizeof(struct selector) ; i++) {
1709 gui_internal_widget_append(wl, wb=gui_internal_button_new_with_callback(this, NULL,
1710 image_new_xs(this, selectors[i].icon), gravity_left_center|orientation_vertical,
1711 gui_internal_cmd_pois, &selectors[i]));
1718 static struct widget *
1719 gui_internal_cmd_pois_item(struct gui_priv *this, struct coord *center, struct item *item, struct coord *c, int dist)
1728 wl=gui_internal_box_new(this, gravity_left_center|orientation_horizontal|flags_fill);
1730 sprintf(distbuf,"%d", dist/1000);
1731 get_direction(dirbuf, transform_get_angle_delta(center, c, 0), 1);
1732 type=item_to_name(item->type);
1733 if (item_attr_get(item, attr_label, &attr)) {
1734 wl->name=g_strdup_printf("%s %s",type,attr.u.str);
1737 wl->name=g_strdup(type);
1739 text=g_strdup_printf("%s %s %s %s", distbuf, dirbuf, type, attr.u.str);
1740 gui_internal_widget_append(wl, gui_internal_label_new(this, text));
1747 gui_internal_cmd_pois_sort_num(gconstpointer a, gconstpointer b, gpointer user_data)
1749 const struct widget *wa=a;
1750 const struct widget *wb=b;
1751 struct widget *wac=wa->children->data;
1752 struct widget *wbc=wb->children->data;
1761 gui_internal_cmd_pois_item_selected(struct selector *sel, enum item_type type)
1763 enum item_type *types;
1764 if (type >= type_line)
1766 if (! sel || !sel->types)
1769 while (*types != type_none) {
1770 if (type >= types[0] && type <= types[1]) {
1778 static void gui_internal_cmd_position(struct gui_priv *this, struct widget *wm, void *data);
1781 gui_internal_cmd_pois(struct gui_priv *this, struct widget *wm, void *data)
1783 struct map_selection *sel,*selm;
1784 struct coord c,center;
1785 struct mapset_handle *h;
1787 struct map_rect *mr;
1789 int idist,dist=4000;
1790 struct widget *wi,*w,*w2,*wb;
1791 enum projection pro=wm->c.pro;
1792 struct selector *isel=wm->data;
1794 wb=gui_internal_menu(this, isel ? isel->name : _("POIs"));
1795 w=gui_internal_box_new(this, gravity_top_center|orientation_vertical|flags_expand|flags_fill);
1796 gui_internal_widget_append(wb, w);
1798 gui_internal_widget_append(w, gui_internal_cmd_pois_selector(this,&wm->c));
1799 w2=gui_internal_box_new(this, gravity_top_center|orientation_vertical|flags_expand|flags_fill);
1800 gui_internal_widget_append(w, w2);
1802 sel=map_selection_rect_new(&wm->c, dist, 18);
1805 h=mapset_open(navit_get_mapset(this->nav));
1806 while ((m=mapset_next(h, 1))) {
1807 selm=map_selection_dup_pro(sel, pro, map_projection(m));
1808 mr=map_rect_new(m, selm);
1809 dbg(2,"mr=%p\n", mr);
1811 while ((item=map_rect_get_item(mr))) {
1812 if (gui_internal_cmd_pois_item_selected(isel, item->type) &&
1813 item_coord_get_pro(item, &c, 1, pro) &&
1814 coord_rect_contains(&sel->u.c_rect, &c) &&
1815 (idist=transform_distance(pro, ¢er, &c)) < dist) {
1816 gui_internal_widget_append(w2, wi=gui_internal_cmd_pois_item(this, ¢er, item, &c, idist));
1817 wi->func=gui_internal_cmd_position;
1818 wi->state |= STATE_SENSITIVE;
1824 map_rect_destroy(mr);
1826 map_selection_destroy(selm);
1828 map_selection_destroy(sel);
1830 w2->children=g_list_sort_with_data(w2->children, gui_internal_cmd_pois_sort_num, (void *)1);
1831 gui_internal_menu_render(this);
1835 gui_internal_cmd_view_on_map(struct gui_priv *this, struct widget *wm, void *data)
1837 struct widget *w=wm->data;
1838 navit_set_center(this->nav, &w->c);
1839 gui_internal_prune_menu(this, NULL);
1844 gui_internal_cmd_view_attributes(struct gui_priv *this, struct widget *wm, void *data)
1846 struct widget *w,*wb;
1847 struct map_rect *mr;
1852 dbg(0,"item=%p 0x%x 0x%x\n", wm->item.map,wm->item.id_hi, wm->item.id_lo);
1853 wb=gui_internal_menu(this, "Attributes");
1854 w=gui_internal_box_new(this, gravity_top_center|orientation_vertical|flags_expand|flags_fill);
1855 gui_internal_widget_append(wb, w);
1856 mr=map_rect_new(wm->item.map, NULL);
1857 item = map_rect_get_item_byid(mr, wm->item.id_hi, wm->item.id_lo);
1858 dbg(0,"item=%p\n", item);
1860 while(item_attr_get(item, attr_any, &attr)) {
1861 text=g_strdup_printf("%s:%s", attr_to_name(attr.type), attr_to_text(&attr, wm->item.map, 1));
1862 gui_internal_widget_append(w,
1863 wb=gui_internal_button_new_with_callback(this, text,
1864 NULL, gravity_left_center|orientation_horizontal|flags_fill,
1865 gui_internal_cmd_view_attributes, NULL));
1869 map_rect_destroy(mr);
1870 gui_internal_menu_render(this);
1874 gui_internal_cmd_view_in_browser(struct gui_priv *this, struct widget *wm, void *data)
1876 struct map_rect *mr;
1881 dbg(0,"item=%p 0x%x 0x%x\n", wm->item.map,wm->item.id_hi, wm->item.id_lo);
1882 mr=map_rect_new(wm->item.map, NULL);
1883 item = map_rect_get_item_byid(mr, wm->item.id_hi, wm->item.id_lo);
1884 dbg(0,"item=%p\n", item);
1886 while(item_attr_get(item, attr_url_local, &attr)) {
1888 cmd=g_strdup_printf("navit-browser.sh '%s' &",attr.u.str);
1891 map_rect_destroy(mr);
1896 dbg(0,"calling external cmd '%s' is not supported\n",cmd);
1902 /* wm->data: 0 Nothing special
1910 gui_internal_cmd_position(struct gui_priv *this, struct widget *wm, void *data)
1912 struct widget *wb,*w,*wc,*wbc;
1916 int display_attributes=(wm->data == (void *)2);
1917 int display_view_on_map=(wm->data != (void *)1);
1918 int display_items=(wm->data == (void *)1);
1919 int display_streets=(wm->data == (void *)3);
1920 if (wm->data == (void *)4) {
1921 gui_internal_search_town_in_country(this, wm);
1925 switch ((int)wm->data) {
1930 dbg(0,"x=0x%x y=0x%x\n", c.x, c.y);
1931 transform_to_geo(wm->c.pro, &c, &g);
1942 name=wm->name ? wm->name : wm->text;
1943 wb=gui_internal_menu(this, name);
1944 w=gui_internal_box_new(this, gravity_top_center|orientation_vertical|flags_expand|flags_fill);
1945 gui_internal_widget_append(wb, w);
1946 coord=coordinates(&wm->c, ' ');
1947 gui_internal_widget_append(w, gui_internal_label_new(this, coord));
1949 if (display_streets) {
1950 gui_internal_widget_append(w,
1951 wc=gui_internal_button_new_with_callback(this, _("Streets"),
1952 image_new_xs(this, "gui_active"), gravity_left_center|orientation_horizontal|flags_fill,
1953 gui_internal_search_street_in_town, wm));
1956 if (display_attributes) {
1957 struct map_rect *mr;
1960 mr=map_rect_new(wm->item.map, NULL);
1961 item = map_rect_get_item_byid(mr, wm->item.id_hi, wm->item.id_lo);
1963 if (item_attr_get(item, attr_description, &attr))
1964 gui_internal_widget_append(w, gui_internal_label_new(this, attr.u.str));
1965 if (item_attr_get(item, attr_url_local, &attr)) {
1966 gui_internal_widget_append(w,
1967 wb=gui_internal_button_new_with_callback(this, _("View in Browser"),
1968 image_new_xs(this, "gui_active"), gravity_left_center|orientation_horizontal|flags_fill,
1969 gui_internal_cmd_view_in_browser, NULL));
1972 gui_internal_widget_append(w,
1973 wb=gui_internal_button_new_with_callback(this, _("View Attributes"),
1974 image_new_xs(this, "gui_active"), gravity_left_center|orientation_horizontal|flags_fill,
1975 gui_internal_cmd_view_attributes, NULL));
1978 map_rect_destroy(mr);
1980 gui_internal_widget_append(w,
1981 gui_internal_button_new_with_callback(this, _("Set as destination"),
1982 image_new_xs(this, "gui_active"), gravity_left_center|orientation_horizontal|flags_fill,
1983 gui_internal_cmd_set_destination, wm));
1984 gui_internal_widget_append(w,
1985 gui_internal_button_new_with_callback(this, _("Set as position"),
1986 image_new_xs(this, "gui_active"), gravity_left_center|orientation_horizontal|flags_fill,
1987 gui_internal_cmd_set_position, wm));
1988 gui_internal_widget_append(w,
1989 wbc=gui_internal_button_new_with_callback(this, _("Add as bookmark"),
1990 image_new_xs(this, "gui_active"), gravity_left_center|orientation_horizontal|flags_fill,
1991 gui_internal_cmd_add_bookmark, wm));
1993 gui_internal_widget_append(w,
1994 wbc=gui_internal_button_new_with_callback(this, _("POIs"),
1995 image_new_xs(this, "gui_active"), gravity_left_center|orientation_horizontal|flags_fill,
1996 gui_internal_cmd_pois, NULL));
1999 gui_internal_widget_append(w,
2000 gui_internal_button_new(this, "Add to tour",
2001 image_new_o(this, "gui_active"), gravity_left_center|orientation_horizontal|flags_fill));
2002 gui_internal_widget_append(w,
2003 gui_internal_button_new(this, "Add as bookmark",
2004 image_new_o(this, "gui_active"), gravity_left_center|orientation_horizontal|flags_fill));
2006 if (display_view_on_map) {
2007 gui_internal_widget_append(w,
2008 gui_internal_button_new_with_callback(this, _("View on map"),
2009 image_new_xs(this, "gui_active"), gravity_left_center|orientation_horizontal|flags_fill,
2010 gui_internal_cmd_view_on_map, wm));
2012 if (display_items) {
2015 struct mapset_handle *h;
2016 struct map_rect *mr;
2019 struct street_data *data;
2020 struct map_selection sel;
2021 struct transformation *trans;
2022 enum projection pro;
2026 trans=navit_get_trans(this->nav);
2027 pro=transform_get_projection(trans);
2028 transform_from_geo(pro, &g, &c);
2029 ms=navit_get_mapset(this->nav);
2031 sel.u.c_rect.lu.x=c.x-dist;
2032 sel.u.c_rect.lu.y=c.y+dist;
2033 sel.u.c_rect.rl.x=c.x+dist;
2034 sel.u.c_rect.rl.y=c.y-dist;
2036 sel.range=item_range_all;
2038 while ((m=mapset_next(h,1))) {
2039 mr=map_rect_new(m, &sel);
2042 while ((item=map_rect_get_item(mr))) {
2043 data=street_get_data(item);
2044 if (transform_within_dist_item(&c, item->type, data->c, data->count, dist)) {
2045 if (item_attr_get(item, attr_label, &attr)) {
2046 label=map_convert_string(m, attr.u.str);
2047 text=g_strdup_printf("%s %s", item_to_name(item->type), label);
2048 map_convert_free(label);
2050 text=g_strdup_printf("%s", item_to_name(item->type));
2051 gui_internal_widget_append(w,
2052 wc=gui_internal_button_new_with_callback(this, text,
2053 image_new_xs(this, "gui_active"), gravity_left_center|orientation_horizontal|flags_fill,
2054 gui_internal_cmd_position, (void *)2));
2055 wc->c.x=data->c[0].x;
2056 wc->c.y=data->c[0].y;
2058 wc->name=g_strdup(text);
2062 street_data_free(data);
2064 map_rect_destroy(mr);
2069 gui_internal_menu_render(this);
2073 gui_internal_cmd_bookmarks(struct gui_priv *this, struct widget *wm, void *data)
2075 struct attr attr,mattr;
2076 struct map_rect *mr=NULL;
2078 char *label_full,*l,*prefix,*pos;
2079 int len,plen,hassub;
2080 struct widget *wb,*w,*wbm;
2085 wb=gui_internal_menu(this, wm->text ? wm->text : _("Bookmarks"));
2086 w=gui_internal_box_new(this, gravity_top_center|orientation_vertical|flags_expand|flags_fill);
2087 w->spy=this->spacing*3;
2088 gui_internal_widget_append(wb, w);
2093 plen=strlen(prefix);
2095 if(navit_get_attr(this->nav, attr_bookmark_map, &mattr, NULL) && mattr.u.map && (mr=map_rect_new(mattr.u.map, NULL))) {
2096 hash=g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
2097 while ((item=map_rect_get_item(mr))) {
2098 if (item->type != type_bookmark) continue;
2099 if (!item_attr_get(item, attr_label, &attr)) continue;
2100 label_full=attr.u.str;
2101 if (!strncmp(label_full, prefix, plen)) {
2102 pos=strchr(label_full+plen, '/');
2108 len=strlen(label_full);
2110 l=g_malloc(len-plen+1);
2111 strncpy(l, label_full+plen, len-plen);
2113 if (!g_hash_table_lookup(hash, l)) {
2114 wbm=gui_internal_button_new_with_callback(this, l,
2115 image_new_xs(this, hassub ? "gui_inactive" : "gui_active" ), gravity_left_center|orientation_horizontal|flags_fill,
2116 hassub ? gui_internal_cmd_bookmarks : gui_internal_cmd_position, NULL);
2117 if (item_coord_get(item, &c, 1)) {
2120 wbm->c.pro=map_projection(mattr.u.map);
2121 wbm->name=g_strdup_printf(_("Bookmark %s"),label_full);
2122 wbm->text=g_strdup(l);
2123 gui_internal_widget_append(w, wbm);
2124 g_hash_table_insert(hash, g_strdup(l), (void *)1);
2125 wbm->prefix=g_malloc(len+2);
2126 strncpy(wbm->prefix, label_full, len+1);
2127 wbm->prefix[len+1]='\0';
2129 gui_internal_widget_destroy(this, wbm);
2136 g_hash_table_destroy(hash);
2138 gui_internal_menu_render(this);
2141 static void gui_internal_keypress_do(struct gui_priv *this, char *key)
2143 struct widget *wi,*menu;
2147 menu=g_list_last(this->root.children)->data;
2148 wi=gui_internal_find_widget(menu, NULL, STATE_EDIT);
2150 if (*key == NAVIT_KEY_BACKSPACE) {
2151 dbg(0,"backspace\n");
2152 if (wi->text && wi->text[0]) {
2153 len=g_utf8_prev_char(wi->text+strlen(wi->text))-wi->text;
2155 text=g_strdup_printf("%s ", wi->text);
2158 if (wi->state & STATE_CLEAR) {
2159 dbg(0,"wi->state=0x%x\n", wi->state);
2162 wi->state &= ~STATE_CLEAR;
2163 dbg(0,"wi->state=0x%x\n", wi->state);
2165 text=g_strdup_printf("%s%s", wi->text ? wi->text : "", key);
2169 if (*key == NAVIT_KEY_BACKSPACE && wi->text) {
2170 gui_internal_widget_render(this, wi);
2175 wi->func(this, wi, wi->data);
2177 gui_internal_widget_render(this, wi);
2183 gui_internal_cmd_keypress(struct gui_priv *this, struct widget *wm, void *data)
2185 struct menu_data *md=gui_internal_menu_data(this);
2186 gui_internal_keypress_do(this, (char *) wm->data);
2187 if (md->keyboard_mode == 2)
2188 gui_internal_keyboard_do(this, md->keyboard, 10);
2192 gui_internal_search_idle_end(struct gui_priv *this)
2195 event_remove_idle(this->idle);
2198 if (this->idle_cb) {
2199 callback_destroy(this->idle_cb);
2205 gui_internal_search_idle(struct gui_priv *this, char *wm_name, struct widget *search_list, void *param)
2207 char *text=NULL,*name=NULL;
2208 struct search_list_result *res;
2212 res=search_list_get_result(this->sl);
2214 gui_internal_search_idle_end(this);
2218 if (! strcmp(wm_name,"Country")) {
2219 name=res->country->name;
2220 text=g_strdup_printf("%s", res->country->name);
2222 if (! strcmp(wm_name,"Town")) {
2223 name=res->town->name;
2224 text=g_strdup(name);
2226 if (! strcmp(wm_name,"Street")) {
2227 name=res->street->name;
2228 text=g_strdup_printf("%s %s", res->town->name, res->street->name);
2231 dbg(0,"res=%s\n", res->town->name);
2233 gui_internal_widget_append(search_list,
2234 wc=gui_internal_button_new_with_callback(this, text,
2235 image_new_xs(this, res->country->flag), gravity_left_center|orientation_horizontal|flags_fill,
2236 gui_internal_cmd_position, param));
2238 wc->name=g_strdup(name);
2241 wc->item.id_lo=res->id;
2242 gui_internal_widget_pack(this, search_list);
2243 l=g_list_last(this->root.children);
2244 graphics_draw_mode(this->gra, draw_mode_begin);
2245 gui_internal_widget_render(this, l->data);
2246 graphics_draw_mode(this->gra, draw_mode_end);
2250 gui_internal_search_idle_start(struct gui_priv *this, char *wm_name, struct widget *search_list, void *param)
2252 this->idle_cb=callback_new_4(callback_cast(gui_internal_search_idle), this, wm_name, search_list, param);
2253 this->idle=event_add_idle(50,this->idle_cb);
2254 callback_call_0(this->idle_cb);
2259 gui_internal_search_changed(struct gui_priv *this, struct widget *wm, void *data)
2262 struct widget *search_list=gui_internal_menu_data(this)->search_list;
2263 gui_internal_widget_children_destroy(this, search_list);
2264 void *param=(void *)3;
2266 if (! strcmp(wm->name,"Country")) {
2270 dbg(0,"%s now '%s'\n", wm->name, wm->text);
2272 gui_internal_search_idle_end(this);
2273 if (wm->text && g_utf8_strlen(wm->text, -1) >= minlen) {
2274 struct attr search_attr;
2277 if (! strcmp(wm->name,"Country"))
2278 search_attr.type=attr_country_all;
2279 if (! strcmp(wm->name,"Town"))
2280 search_attr.type=attr_town_name;
2281 if (! strcmp(wm->name,"Street"))
2282 search_attr.type=attr_street_name;
2283 search_attr.u.str=wm->text;
2284 search_list_search(this->sl, &search_attr, 1);
2285 gui_internal_search_idle_start(this, wm->name, search_list, param);
2287 l=g_list_last(this->root.children);
2288 gui_internal_widget_render(this, l->data);
2291 static struct widget *
2292 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)
2295 gui_internal_widget_append(wkbd, wk=gui_internal_button_new_with_callback(this, text,
2296 NULL, gravity_center|orientation_vertical, func, data));
2297 wk->data_free=data_free;
2298 wk->background=this->background;
2306 static struct widget *
2307 gui_internal_keyboard_key(struct gui_priv *this, struct widget *wkbd, char *text, char *key, int w, int h)
2309 return gui_internal_keyboard_key_data(this, wkbd, text, gui_internal_cmd_keypress, g_strdup(key), g_free,w,h);
2312 static void gui_internal_keyboard_change(struct gui_priv *this, struct widget *key, void *data);
2314 static struct widget *
2315 gui_internal_keyboard_do(struct gui_priv *this, struct widget *wkbdb, int mode)
2317 struct widget *wkbd,*wk;
2318 struct menu_data *md=gui_internal_menu_data(this);
2319 int i, max_w=navit_get_width(this->nav), max_h=navit_get_height(this->nav);
2325 gui_internal_highlight(this);
2327 gui_internal_widget_children_destroy(this, wkbdb);
2329 wkbdb=gui_internal_box_new(this, gravity_center|orientation_horizontal_vertical|flags_fill);
2331 md->keyboard_mode=mode;
2332 wkbd=gui_internal_box_new(this, gravity_center|orientation_horizontal_vertical|flags_fill);
2333 wkbd->background=this->background;
2340 if (mode >= 0 && mode < 8) {
2341 for (i = 0 ; i < 26 ; i++) {
2342 char text[]={'A'+i,'\0'};
2343 gui_internal_keyboard_key(this, wkbd, text, text,max_w,max_h);
2345 gui_internal_keyboard_key(this, wkbd, "_"," ",max_w,max_h);
2347 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_data(this, wkbd, "", NULL, NULL, NULL,max_w,max_h);
2351 gui_internal_keyboard_key_data(this, wkbd, "", NULL, NULL, NULL,max_w,max_h);
2352 wk=gui_internal_keyboard_key_data(this, wkbd, "a", gui_internal_keyboard_change, wkbd, NULL,max_w,max_h);
2354 wk=gui_internal_keyboard_key_data(this, wkbd, "1", gui_internal_keyboard_change, wkbd, NULL,max_w,max_h);
2357 wk=gui_internal_keyboard_key_data(this, wkbd, "Ä",gui_internal_keyboard_change, wkbdb,NULL,max_w,max_h);
2359 gui_internal_keyboard_key(this, wkbd, "<-","\b",max_w,max_h);
2361 if (mode >= 8 && mode < 16) {
2362 for (i = 0 ; i < 26 ; i++) {
2363 char text[]={'a'+i,'\0'};
2364 gui_internal_keyboard_key(this, wkbd, text, text,max_w,max_h);
2366 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_data(this, wkbd, "", NULL, NULL, NULL,max_w,max_h);
2372 gui_internal_keyboard_key_data(this, wkbd, "", NULL, NULL, NULL,max_w,max_h);
2373 wk=gui_internal_keyboard_key_data(this, wkbd, "A", gui_internal_keyboard_change, wkbd, NULL,max_w,max_h);
2375 wk=gui_internal_keyboard_key_data(this, wkbd, "1", gui_internal_keyboard_change, wkbd, NULL,max_w,max_h);
2378 wk=gui_internal_keyboard_key_data(this, wkbd, "ä",gui_internal_keyboard_change,wkbdb,NULL,max_w,max_h);
2380 gui_internal_keyboard_key(this, wkbd, "<-","\b",max_w,max_h);
2382 if (mode >= 16 && mode < 24) {
2383 for (i = 0 ; i < 10 ; i++) {
2384 char text[]={'0'+i,'\0'};
2385 gui_internal_keyboard_key(this, wkbd, text, text,max_w,max_h);
2387 gui_internal_keyboard_key(this, wkbd, ".",".",max_w,max_h);
2388 gui_internal_keyboard_key(this, wkbd, "°","°",max_w,max_h);
2389 gui_internal_keyboard_key(this, wkbd, "'","'",max_w,max_h);
2390 gui_internal_keyboard_key(this, wkbd, "\"","\"",max_w,max_h);
2391 gui_internal_keyboard_key(this, wkbd, "-","-",max_w,max_h);
2392 gui_internal_keyboard_key(this, wkbd, "+","+",max_w,max_h);
2393 gui_internal_keyboard_key(this, wkbd, "*","*",max_w,max_h);
2394 gui_internal_keyboard_key(this, wkbd, "/","/",max_w,max_h);
2395 gui_internal_keyboard_key(this, wkbd, "(","(",max_w,max_h);
2396 gui_internal_keyboard_key(this, wkbd, ")",")",max_w,max_h);
2397 gui_internal_keyboard_key(this, wkbd, "=","=",max_w,max_h);
2398 gui_internal_keyboard_key(this, wkbd, "?","?",max_w,max_h);
2399 for (i = 0 ; i < 5 ; i++) {
2400 gui_internal_keyboard_key_data(this, wkbd, "", NULL, NULL, NULL,max_w,max_h);
2403 gui_internal_keyboard_key(this, wkbd, "-","-",max_w,max_h);
2404 gui_internal_keyboard_key(this, wkbd, "'","'",max_w,max_h);
2405 gui_internal_keyboard_key_data(this, wkbd, "", NULL, NULL, NULL,max_w,max_h);
2407 gui_internal_keyboard_key_data(this, wkbd, "", NULL, NULL, NULL,max_w,max_h);
2408 wk=gui_internal_keyboard_key_data(this, wkbd, "A", gui_internal_keyboard_change, wkbd, NULL,max_w,max_h);
2410 wk=gui_internal_keyboard_key_data(this, wkbd, "a", gui_internal_keyboard_change, wkbd, NULL,max_w,max_h);
2413 wk=gui_internal_keyboard_key_data(this, wkbd, "Ä",gui_internal_keyboard_change,wkbdb,NULL,max_w,max_h);
2415 gui_internal_keyboard_key(this, wkbd, "<-","\b",max_w,max_h);
2417 if (mode >= 24 && mode < 32) {
2418 gui_internal_keyboard_key(this, wkbd, "Ä","Ä",max_w,max_h);
2419 gui_internal_keyboard_key(this, wkbd, "Ö","Ö",max_w,max_h);
2420 gui_internal_keyboard_key(this, wkbd, "Ü","Ü",max_w,max_h);
2421 for (i = 0 ; i < 27 ; i++) {
2422 gui_internal_keyboard_key_data(this, wkbd, "", NULL, NULL, NULL,max_w,max_h);
2424 wk=gui_internal_keyboard_key_data(this, wkbd, "A",gui_internal_keyboard_change,wkbdb,NULL,max_w,max_h);
2426 gui_internal_keyboard_key(this, wkbd, "<-","\b",max_w,max_h);
2428 if (mode >= 32 && mode < 40) {
2429 gui_internal_keyboard_key(this, wkbd, "ä","ä",max_w,max_h);
2430 gui_internal_keyboard_key(this, wkbd, "ö","ö",max_w,max_h);
2431 gui_internal_keyboard_key(this, wkbd, "ü","ü",max_w,max_h);
2432 for (i = 0 ; i < 27 ; i++) {
2433 gui_internal_keyboard_key_data(this, wkbd, "", NULL, NULL, NULL,max_w,max_h);
2435 wk=gui_internal_keyboard_key_data(this, wkbd, "a",gui_internal_keyboard_change,wkbdb,NULL,max_w,max_h);
2437 gui_internal_keyboard_key(this, wkbd, "<-","\b",max_w,max_h);
2439 gui_internal_widget_append(wkbdb, wkbd);
2441 gui_internal_widget_pack(this, wkbdb);
2442 gui_internal_widget_render(this, wkbdb);
2447 static struct widget *
2448 gui_internal_keyboard(struct gui_priv *this, int mode)
2450 if (! this->keyboard)
2452 return gui_internal_keyboard_do(this, NULL, mode);
2456 gui_internal_keyboard_change(struct gui_priv *this, struct widget *key, void *data)
2458 gui_internal_keyboard_do(this, key->data, key->datai);
2462 gui_internal_search_list_set_default_country(struct gui_priv *this)
2464 struct attr search_attr, country_name, country_iso2, *country_attr;
2466 struct country_search *cs;
2467 struct tracking *tracking;
2468 struct search_list_result *res;
2470 country_attr=country_default();
2471 tracking=navit_get_tracking(this->nav);
2472 if (tracking && tracking_get_current_attr(tracking, attr_country_id, &search_attr))
2473 country_attr=&search_attr;
2475 cs=country_search_new(country_attr, 0);
2476 item=country_search_get_item(cs);
2477 if (item && item_attr_get(item, attr_country_name, &country_name)) {
2478 search_attr.type=attr_country_all;
2479 dbg(0,"country %s\n", country_name.u.str);
2480 search_attr.u.str=country_name.u.str;
2481 search_list_search(this->sl, &search_attr, 0);
2482 while((res=search_list_get_result(this->sl)));
2483 g_free(this->country_iso2);
2484 if (item_attr_get(item, attr_country_iso2, &country_iso2))
2485 this->country_iso2=g_strdup(country_iso2.u.str);
2487 country_search_destroy(cs);
2489 dbg(0,"warning: no default country found\n");
2494 gui_internal_search_list_new(struct gui_priv *this)
2496 struct mapset *ms=navit_get_mapset(this->nav);
2498 this->sl=search_list_new(ms);
2499 gui_internal_search_list_set_default_country(this);
2504 gui_internal_search_list_destroy(struct gui_priv *this)
2507 search_list_destroy(this->sl);
2514 gui_internal_search(struct gui_priv *this, char *what, char *type, int flags)
2516 struct widget *wb,*wk,*w,*wr,*we,*wl,*wnext=NULL;
2518 gui_internal_search_list_new(this);
2519 wb=gui_internal_menu(this, what);
2520 w=gui_internal_box_new(this, gravity_center|orientation_vertical|flags_expand|flags_fill);
2521 gui_internal_widget_append(wb, w);
2522 wr=gui_internal_box_new(this, gravity_top_center|orientation_vertical|flags_expand|flags_fill);
2523 gui_internal_widget_append(w, wr);
2524 we=gui_internal_box_new(this, gravity_left_center|orientation_horizontal|flags_fill);
2525 gui_internal_widget_append(wr, we);
2527 if (!strcmp(type,"Country")) {
2528 wnext=gui_internal_image_new(this, image_new_xs(this, "gui_select_town"));
2529 wnext->func=gui_internal_search_town;
2530 } else if (!strcmp(type,"Town")) {
2531 if (this->country_iso2)
2532 country=g_strdup_printf("country_%s", this->country_iso2);
2534 country=strdup("gui_select_country");
2535 gui_internal_widget_append(we, wb=gui_internal_image_new(this, image_new_xs(this, country)));
2536 wb->state |= STATE_SENSITIVE;
2538 wb->func = gui_internal_search_country;
2540 wb->func = gui_internal_back;
2541 wnext=gui_internal_image_new(this, image_new_xs(this, "gui_select_street"));
2542 wnext->func=gui_internal_search_street;
2544 } else if (!strcmp(type,"Street")) {
2545 gui_internal_widget_append(we, wb=gui_internal_image_new(this, image_new_xs(this, "gui_select_town")));
2546 wb->state |= STATE_SENSITIVE;
2547 wb->func = gui_internal_back;
2549 gui_internal_widget_append(we, wk=gui_internal_label_new(this, NULL));
2551 gui_internal_widget_append(we, wnext);
2552 wnext->state |= STATE_SENSITIVE;
2554 wl=gui_internal_box_new(this, gravity_left_top|orientation_vertical|flags_expand|flags_fill);
2555 gui_internal_widget_append(wr, wl);
2556 gui_internal_menu_data(this)->search_list=wl;
2557 wk->state |= STATE_EDIT;
2558 wk->background=this->background;
2559 wk->flags |= flags_expand|flags_fill;
2560 wk->func = gui_internal_search_changed;
2561 wk->name=g_strdup(type);
2563 gui_internal_widget_append(w, gui_internal_keyboard(this,0));
2564 gui_internal_menu_render(this);
2568 gui_internal_search_street(struct gui_priv *this, struct widget *widget, void *data)
2570 search_list_select(this->sl, attr_town_name, 0, 0);
2571 gui_internal_search(this,_("Street"),"Street",0);
2575 gui_internal_search_street_in_town(struct gui_priv *this, struct widget *widget, void *data)
2577 dbg(0,"id %d\n", widget->item.id_lo);
2578 search_list_select(this->sl, attr_town_name, 0, 0);
2579 search_list_select(this->sl, attr_town_name, widget->item.id_lo, 1);
2580 gui_internal_search(this,_("Street"),"Street",0);
2584 gui_internal_search_town(struct gui_priv *this, struct widget *wm, void *data)
2587 search_list_select(this->sl, attr_country_all, 0, 0);
2588 g_free(this->country_iso2);
2589 this->country_iso2=NULL;
2590 gui_internal_search(this,_("Town"),"Town",0);
2594 gui_internal_search_town_in_country(struct gui_priv *this, struct widget *widget)
2596 struct search_list_common *slc;
2597 dbg(0,"id %d\n", widget->item.id_lo);
2598 search_list_select(this->sl, attr_country_all, 0, 0);
2599 slc=search_list_select(this->sl, attr_country_all, widget->item.id_lo, 1);
2601 g_free(this->country_iso2);
2602 this->country_iso2=((struct search_list_country *)slc)->iso2;
2604 gui_internal_search(this,widget->name,"Town",0);
2608 gui_internal_search_country(struct gui_priv *this, struct widget *widget, void *data)
2610 gui_internal_prune_menu_count(this, 1, 0);
2611 gui_internal_search(this,_("Country"),"Country",0);
2615 gui_internal_cmd_town(struct gui_priv *this, struct widget *wm, void *data)
2618 search_list_select(this->sl, attr_country_all, 0, 0);
2619 gui_internal_search(this,_("Town"),"Town",1);
2623 gui_internal_cmd_layout(struct gui_priv *this, struct widget *wm, void *data)
2626 struct widget *w,*wb,*wl;
2627 struct attr_iter *iter;
2630 wb=gui_internal_menu(this, _("Layout"));
2631 w=gui_internal_box_new(this, gravity_top_center|orientation_vertical|flags_expand|flags_fill);
2632 w->spy=this->spacing*3;
2633 gui_internal_widget_append(wb, w);
2634 iter=navit_attr_iter_new();
2635 while(navit_get_attr(this->nav, attr_layout, &attr, iter)) {
2636 wl=gui_internal_button_navit_attr_new(this, attr.u.layout->name, gravity_left_center|orientation_horizontal|flags_fill,
2638 gui_internal_widget_append(w, wl);
2640 navit_attr_iter_destroy(iter);
2641 gui_internal_menu_render(this);
2645 gui_internal_cmd_fullscreen(struct gui_priv *this, struct widget *wm, void *data)
2647 this->fullscreen=!this->fullscreen;
2648 this->win->fullscreen(this->win, this->fullscreen);
2652 gui_internal_cmd_2d(struct gui_priv *this, struct widget *wm, void *data)
2654 struct transformation *trans=navit_get_trans(this->nav);
2655 transform_set_pitch(trans, 0);
2660 gui_internal_cmd_3d(struct gui_priv *this, struct widget *wm, void *data)
2662 struct transformation *trans=navit_get_trans(this->nav);
2663 transform_set_pitch(trans, 20);
2668 gui_internal_cmd_display(struct gui_priv *this, struct widget *wm, void *data)
2671 struct transformation *trans;
2673 w=gui_internal_menu(this, _("Display"));
2674 gui_internal_widget_append(w,
2675 gui_internal_button_new_with_callback(this, _("Layout"),
2676 image_new_l(this, "gui_display"), gravity_center|orientation_vertical,
2677 gui_internal_cmd_layout, NULL));
2678 if (this->fullscreen) {
2679 gui_internal_widget_append(w,
2680 gui_internal_button_new_with_callback(this, _("Window Mode"),
2681 image_new_l(this, "gui_leave_fullscreen"), gravity_center|orientation_vertical,
2682 gui_internal_cmd_fullscreen, NULL));
2684 gui_internal_widget_append(w,
2685 gui_internal_button_new_with_callback(this, _("Fullscreen"),
2686 image_new_l(this, "gui_fullscreen"), gravity_center|orientation_vertical,
2687 gui_internal_cmd_fullscreen, NULL));
2689 trans=navit_get_trans(this->nav);
2690 if (transform_get_pitch(trans)) {
2691 gui_internal_widget_append(w,
2692 gui_internal_button_new_with_callback(this, _("2D"),
2693 image_new_l(this, "gui_map"), gravity_center|orientation_vertical,
2694 gui_internal_cmd_2d, NULL));
2697 gui_internal_widget_append(w,
2698 gui_internal_button_new_with_callback(this, _("3D"),
2699 image_new_l(this, "gui_map"), gravity_center|orientation_vertical,
2700 gui_internal_cmd_3d, NULL));
2702 gui_internal_menu_render(this);
2706 gui_internal_cmd_quit(struct gui_priv *this, struct widget *wm, void *data)
2708 struct navit *nav=this->nav;
2710 main_remove_navit(nav);
2714 gui_internal_cmd_abort_navigation(struct gui_priv *this, struct widget *wm, void *data)
2716 navit_set_destination(this->nav, NULL, NULL);
2721 gui_internal_cmd_actions(struct gui_priv *this, struct widget *wm, void *data)
2723 struct widget *w,*wc;
2726 w=gui_internal_menu(this, _("Actions"));
2727 gui_internal_widget_append(w,
2728 gui_internal_button_new_with_callback(this, _("Bookmarks"),
2729 image_new_l(this, "gui_bookmark"), gravity_center|orientation_vertical,
2730 gui_internal_cmd_bookmarks, NULL));
2731 if (this->clickp_valid) {
2732 coord=coordinates(&this->clickp, '\n');
2733 gui_internal_widget_append(w,
2734 wc=gui_internal_button_new_with_callback(this, coord,
2735 image_new_l(this, "gui_map"), gravity_center|orientation_vertical,
2736 gui_internal_cmd_position, (void *)1));
2737 wc->name=g_strdup(_("Map Point"));
2741 if (this->vehicle_valid) {
2742 coord=coordinates(&this->vehiclep, '\n');
2743 gui_internal_widget_append(w,
2744 wc=gui_internal_button_new_with_callback(this, coord,
2745 image_new_l(this, "gui_vehicle"), gravity_center|orientation_vertical,
2746 gui_internal_cmd_position, NULL));
2747 wc->name=g_strdup(_("Vehicle Position"));
2748 wc->c=this->vehiclep;
2751 gui_internal_widget_append(w,
2752 gui_internal_button_new_with_callback(this, _("Town"),
2753 image_new_l(this, "gui_town"), gravity_center|orientation_vertical,
2754 gui_internal_cmd_town, NULL));
2755 gui_internal_widget_append(w,
2756 gui_internal_button_new_with_callback(this, _("Quit"),
2757 image_new_l(this, "gui_quit"), gravity_center|orientation_vertical,
2758 gui_internal_cmd_quit, NULL));
2760 if (navit_check_route(this->nav)) {
2761 gui_internal_widget_append(w,
2762 gui_internal_button_new_with_callback(this, _("Stop\nNavigation"),
2763 image_new_l(this, "gui_stop"), gravity_center|orientation_vertical,
2764 gui_internal_cmd_abort_navigation, NULL));
2766 gui_internal_menu_render(this);
2770 gui_internal_cmd_maps(struct gui_priv *this, struct widget *wm, void *wdata)
2772 struct attr attr, on, off, description, type, data;
2773 struct widget *w,*wb,*wma;
2775 struct attr_iter *iter;
2778 wb=gui_internal_menu(this, _("Maps"));
2779 w=gui_internal_box_new(this, gravity_top_center|orientation_vertical|flags_expand|flags_fill);
2780 w->spy=this->spacing*3;
2781 gui_internal_widget_append(wb, w);
2782 iter=navit_attr_iter_new();
2783 on.type=off.type=attr_active;
2786 while(navit_get_attr(this->nav, attr_map, &attr, iter)) {
2787 if (map_get_attr(attr.u.map, attr_description, &description, NULL)) {
2788 label=g_strdup(description.u.str);
2790 if (!map_get_attr(attr.u.map, attr_type, &type, NULL))
2792 if (!map_get_attr(attr.u.map, attr_data, &data, NULL))
2794 label=g_strdup_printf("%s:%s", type.u.str, data.u.str);
2796 wma=gui_internal_button_map_attr_new(this, label, gravity_left_center|orientation_horizontal|flags_fill,
2797 attr.u.map, &on, &off, 1);
2798 gui_internal_widget_append(w, wma);
2801 navit_attr_iter_destroy(iter);
2802 gui_internal_menu_render(this);
2806 gui_internal_cmd_set_active_vehicle(struct gui_priv *this, struct widget *wm, void *data)
2808 struct attr vehicle = {attr_vehicle,{wm->data}};
2809 navit_set_attr(this->nav, &vehicle);
2813 gui_internal_cmd_show_satellite_status(struct gui_priv *this, struct widget *wm, void *data)
2815 struct widget *w,*wb,*row;
2816 struct attr attr,sat_attr;
2817 struct vehicle *v=wm->data;
2820 enum attr_type types[]={attr_sat_prn, attr_sat_elevation, attr_sat_azimuth, attr_sat_snr};
2822 wb=gui_internal_menu(this, _("Show Satellite Status"));
2823 gui_internal_menu_data(this)->redisplay=gui_internal_cmd_show_satellite_status;
2824 gui_internal_menu_data(this)->redisplay_widget=wm;
2825 w=gui_internal_box_new(this, gravity_top_center|orientation_vertical|flags_expand|flags_fill);
2826 gui_internal_widget_append(wb, w);
2827 w = gui_internal_widget_table_new(this,gravity_center | orientation_vertical | flags_expand | flags_fill, 0);
2828 row = gui_internal_widget_table_row_new(this,gravity_left_top);
2829 gui_internal_widget_append(row, gui_internal_label_new(this, " PRN "));
2830 gui_internal_widget_append(row, gui_internal_label_new(this, " Elevation "));
2831 gui_internal_widget_append(row, gui_internal_label_new(this, " Azimuth "));
2832 gui_internal_widget_append(row, gui_internal_label_new(this, " SNR "));
2833 gui_internal_widget_append(w,row);
2834 while (vehicle_get_attr(v, attr_position_sat_item, &attr, NULL)) {
2835 row = gui_internal_widget_table_row_new(this,gravity_left_top);
2836 for (i = 0 ; i < sizeof(types)/sizeof(enum attr_type) ; i++) {
2837 if (item_attr_get(attr.u.item, types[i], &sat_attr))
2838 str=g_strdup_printf("%d", sat_attr.u.num);
2841 gui_internal_widget_append(row, gui_internal_label_new(this, str));
2844 gui_internal_widget_append(w,row);
2846 gui_internal_widget_append(wb, w);
2847 gui_internal_menu_render(this);
2851 gui_internal_cmd_show_nmea_data(struct gui_priv *this, struct widget *wm, void *data)
2853 struct widget *w,*wb;
2855 struct vehicle *v=wm->data;
2856 wb=gui_internal_menu(this, _("Show NMEA Data"));
2857 gui_internal_menu_data(this)->redisplay=gui_internal_cmd_show_nmea_data;
2858 gui_internal_menu_data(this)->redisplay_widget=wm;
2859 w=gui_internal_box_new(this, gravity_top_center|orientation_vertical|flags_expand|flags_fill);
2860 gui_internal_widget_append(wb, w);
2861 if (vehicle_get_attr(v, attr_position_nmea, &attr, NULL))
2862 gui_internal_widget_append(w, gui_internal_text_new(this, attr.u.str, gravity_left_center|orientation_vertical));
2863 gui_internal_menu_render(this);
2868 gui_internal_cmd_vehicle_settings(struct gui_priv *this, struct widget *wm, void *data)
2870 struct widget *w,*wb;
2871 struct attr attr,active_vehicle;
2872 struct vehicle *v=wm->data;
2873 wb=gui_internal_menu(this, wm->text);
2874 w=gui_internal_box_new(this, gravity_top_center|orientation_vertical|flags_expand|flags_fill);
2875 gui_internal_widget_append(wb, w);
2876 if (!navit_get_attr(this->nav, attr_vehicle, &active_vehicle, NULL))
2877 active_vehicle.u.vehicle=NULL;
2878 if (active_vehicle.u.vehicle != v) {
2879 gui_internal_widget_append(w,
2880 gui_internal_button_new_with_callback(this, _("Set as active"),
2881 image_new_xs(this, "gui_active"), gravity_left_center|orientation_horizontal|flags_fill,
2882 gui_internal_cmd_set_active_vehicle, wm->data));
2884 if (vehicle_get_attr(v, attr_position_sat_item, &attr, NULL)) {
2885 gui_internal_widget_append(w,
2886 gui_internal_button_new_with_callback(this, _("Show Satellite status"),
2887 image_new_xs(this, "gui_active"), gravity_left_center|orientation_horizontal|flags_fill,
2888 gui_internal_cmd_show_satellite_status, wm->data));
2890 if (vehicle_get_attr(v, attr_position_nmea, &attr, NULL)) {
2891 gui_internal_widget_append(w,
2892 gui_internal_button_new_with_callback(this, _("Show NMEA data"),
2893 image_new_xs(this, "gui_active"), gravity_left_center|orientation_horizontal|flags_fill,
2894 gui_internal_cmd_show_nmea_data, wm->data));
2896 callback_list_call_attr_2(this->cbl, attr_vehicle, w, wm->data);
2897 gui_internal_menu_render(this);
2901 gui_internal_cmd_vehicle(struct gui_priv *this, struct widget *wm, void *data)
2903 struct attr attr,vattr;
2904 struct widget *w,*wb,*wl;
2905 struct attr_iter *iter;
2906 struct attr active_vehicle;
2909 wb=gui_internal_menu(this, _("Vehicle"));
2910 w=gui_internal_box_new(this, gravity_top_center|orientation_vertical|flags_expand|flags_fill);
2911 w->spy=this->spacing*3;
2912 gui_internal_widget_append(wb, w);
2913 if (!navit_get_attr(this->nav, attr_vehicle, &active_vehicle, NULL))
2914 active_vehicle.u.vehicle=NULL;
2915 iter=navit_attr_iter_new();
2916 while(navit_get_attr(this->nav, attr_vehicle, &attr, iter)) {
2917 vehicle_get_attr(attr.u.vehicle, attr_name, &vattr, NULL);
2918 wl=gui_internal_button_new_with_callback(this, vattr.u.str,
2919 image_new_l(this, attr.u.vehicle == active_vehicle.u.vehicle ? "gui_active" : "gui_inactive"), gravity_left_center|orientation_horizontal|flags_fill,
2920 gui_internal_cmd_vehicle_settings, attr.u.vehicle);
2921 wl->text=g_strdup(vattr.u.str);
2922 gui_internal_widget_append(w, wl);
2924 navit_attr_iter_destroy(iter);
2925 gui_internal_menu_render(this);
2930 gui_internal_cmd_rules(struct gui_priv *this, struct widget *wm, void *data)
2932 struct widget *wb,*w;
2934 wb=gui_internal_menu(this, _("Rules"));
2935 w=gui_internal_box_new(this, gravity_top_center|orientation_vertical|flags_expand|flags_fill);
2936 w->spy=this->spacing*3;
2937 gui_internal_widget_append(wb, w);
2940 on.type=off.type=attr_tracking;
2941 gui_internal_widget_append(w,
2942 gui_internal_button_navit_attr_new(this, _("Lock on road"), gravity_left_center|orientation_horizontal|flags_fill,
2946 on.type=off.type=attr_orientation;
2947 gui_internal_widget_append(w,
2948 gui_internal_button_navit_attr_new(this, _("Northing"), gravity_left_center|orientation_horizontal|flags_fill,
2952 on.type=off.type=attr_cursor;
2953 gui_internal_widget_append(w,
2954 gui_internal_button_navit_attr_new(this, _("Map follows Vehicle"), gravity_left_center|orientation_horizontal|flags_fill,
2956 gui_internal_menu_render(this);
2960 gui_internal_cmd_settings(struct gui_priv *this, struct widget *wm, void *data)
2964 w=gui_internal_menu(this, _("Settings"));
2965 gui_internal_widget_append(w,
2966 gui_internal_button_new_with_callback(this, _("Display"),
2967 image_new_l(this, "gui_display"), gravity_center|orientation_vertical,
2968 gui_internal_cmd_display, NULL));
2969 gui_internal_widget_append(w,
2970 gui_internal_button_new_with_callback(this, _("Maps"),
2971 image_new_l(this, "gui_maps"), gravity_center|orientation_vertical,
2972 gui_internal_cmd_maps, NULL));
2973 gui_internal_widget_append(w,
2974 gui_internal_button_new_with_callback(this, _("Vehicle"),
2975 image_new_l(this, "gui_vehicle"), gravity_center|orientation_vertical,
2976 gui_internal_cmd_vehicle, NULL));
2977 gui_internal_widget_append(w,
2978 gui_internal_button_new_with_callback(this, _("Rules"),
2979 image_new_l(this, "gui_rules"), gravity_center|orientation_vertical,
2980 gui_internal_cmd_rules, NULL));
2981 gui_internal_menu_render(this);
2984 //##############################################################################################################
2987 //# Authors: Martin Schaller (04/2008)
2988 //##############################################################################################################
2989 static void gui_internal_motion(void *data, struct point *p)
2992 struct gui_priv *this=data;
2993 if (!this->root.children) {
2994 navit_handle_motion(this->nav, p);
3000 if(!this->motion_timeout_callback)
3001 this->motion_timeout_callback=callback_new_1(callback_cast(gui_internal_highlight), this);
3002 if(!this->motion_timeout_event)
3003 this->motion_timeout_event=event_add_timeout(100,0, this->motion_timeout_callback);
3007 static void gui_internal_menu_root(struct gui_priv *this)
3011 graphics_draw_mode(this->gra, draw_mode_begin);
3012 w=gui_internal_menu(this, _("Main menu"));
3013 w->spx=this->spacing*10;
3014 gui_internal_widget_append(w, gui_internal_button_new_with_callback(this, _("Actions"),
3015 image_new_l(this, "gui_actions"), gravity_center|orientation_vertical,
3016 gui_internal_cmd_actions, NULL));
3017 if (this->flags & 2) {
3018 gui_internal_widget_append(w, gui_internal_button_new_with_callback(this, _("Show\nMap"),
3019 image_new_l(this, "gui_map"), gravity_center|orientation_vertical,
3020 gui_internal_cmd_settings, NULL));
3022 gui_internal_widget_append(w, gui_internal_button_new_with_callback(this, _("Settings"),
3023 image_new_l(this, "gui_settings"), gravity_center|orientation_vertical,
3024 gui_internal_cmd_settings, NULL));
3025 gui_internal_widget_append(w, gui_internal_button_new(this, _("Tools"),
3026 image_new_l(this, "gui_tools"), gravity_center|orientation_vertical));
3028 gui_internal_widget_append(w, gui_internal_button_new_with_callback(this, "Table Test",
3029 image_new_l(this, "gui_settings"), gravity_center|orientation_vertical,
3030 gui_internal_cmd_route, NULL));
3033 callback_list_call_attr_1(this->cbl, attr_gui, w);
3035 gui_internal_menu_render(this);
3036 graphics_draw_mode(this->gra, draw_mode_end);
3040 gui_internal_cmd_menu(struct gui_priv *this, struct point *p, int ignore)
3042 struct graphics *gra=this->gra;
3043 struct transformation *trans;
3045 struct attr attr,attrp;
3047 this->ignore_button=ignore;
3048 this->clickp_valid=this->vehicle_valid=0;
3050 navit_block(this->nav, 1);
3051 graphics_overlay_disable(gra, 1);
3052 trans=navit_get_trans(this->nav);
3054 transform_reverse(trans, p, &c);
3055 dbg(0,"x=0x%x y=0x%x\n", c.x, c.y);
3056 this->clickp.pro=transform_get_projection(trans);
3059 this->clickp_valid=1;
3061 if (navit_get_attr(this->nav, attr_vehicle, &attr, NULL) && attr.u.vehicle
3062 && vehicle_get_attr(attr.u.vehicle, attr_position_coord_geo, &attrp, NULL)) {
3063 this->vehiclep.pro=transform_get_projection(trans);
3064 transform_from_geo(this->vehiclep.pro, attrp.u.coord_geo, &c);
3065 this->vehiclep.x=c.x;
3066 this->vehiclep.y=c.y;
3067 this->vehicle_valid=1;
3072 this->root.background=this->background;
3073 gui_internal_menu_root(this);
3077 gui_internal_cmd_menu2(struct gui_priv *this)
3079 gui_internal_cmd_menu(this, NULL, 1);
3083 gui_internal_check_exit(struct gui_priv *this)
3085 struct graphics *gra=this->gra;
3086 if (! this->root.children) {
3087 gui_internal_search_idle_end(this);
3088 gui_internal_search_list_destroy(this);
3089 graphics_overlay_disable(gra, 0);
3090 if (!navit_block(this->nav, 0)) {
3092 navit_draw(this->nav);
3094 navit_draw_displaylist(this->nav);
3099 //##############################################################################################################
3100 //# Description: Function to handle mouse clicks and scroll wheel movement
3102 //# Authors: Martin Schaller (04/2008), Stefan Klumpp (04/2008)
3103 //##############################################################################################################
3104 static void gui_internal_button(void *data, int pressed, int button, struct point *p)
3106 struct gui_priv *this=data;
3107 struct graphics *gra=this->gra;
3109 dbg(1,"enter %d %d\n", pressed, button);
3110 // if still on the map (not in the menu, yet):
3111 if (!this->root.children || this->ignore_button) {
3112 this->ignore_button=0;
3113 // check whether the position of the mouse changed during press/release OR if it is the scrollwheel
3114 if (!navit_handle_button(this->nav, pressed, button, p, NULL) || button >=4) // Maybe there's a better way to do this
3116 if (this->menu_on_map_click)
3117 gui_internal_cmd_menu(this, p, 0);
3122 // if already in the menu:
3126 gui_internal_highlight(this);
3131 graphics_draw_mode(gra, draw_mode_begin);
3132 gui_internal_call_highlighted(this);
3133 gui_internal_highlight(this);
3134 graphics_draw_mode(gra, draw_mode_end);
3135 gui_internal_check_exit(this);
3139 //##############################################################################################################
3142 //# Authors: Martin Schaller (04/2008)
3143 //##############################################################################################################
3144 static void gui_internal_resize(void *data, int w, int h)
3146 struct gui_priv *this=data;
3148 if( this->root.w==w && this->root.h==h)
3153 dbg(0,"w=%d h=%d children=%p\n", w, h, this->root.children);
3154 navit_handle_resize(this->nav, w, h);
3155 if (this->root.children) {
3156 gui_internal_prune_menu(this, NULL);
3157 gui_internal_menu_root(this);
3162 gui_internal_keynav_point(struct widget *w, int dx, int dy, struct point *p)
3177 gui_internal_keynav_find_closest(struct widget *wi, struct point *p, int dx, int dy, int *distance, struct widget **result)
3179 GList *l=wi->children;
3180 if (wi->state & STATE_SENSITIVE) {
3183 gui_internal_keynav_point(wi, -dx, -dy, &wp);
3185 dist1=(wp.x-p->x)*dx;
3188 dist1=(wp.y-p->y)*dy;
3196 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);
3202 if (dist1 < *distance) {
3209 struct widget *child=l->data;
3210 gui_internal_keynav_find_closest(child, p, dx, dy, distance, result);
3216 gui_internal_keynav_highlight_next(struct gui_priv *this, int dx, int dy)
3218 struct widget *result,*menu=g_list_last(this->root.children)->data;
3221 if (this->highlighted && this->highlighted_menu == g_list_last(this->root.children)->data)
3222 gui_internal_keynav_point(this->highlighted, dx, dy, &p);
3228 gui_internal_keynav_find_closest(menu, &p, 0, 0, &distance, &result);
3230 gui_internal_keynav_point(result, dx, dy, &p);
3231 dbg(1,"result origin=%p p=%d,%d\n", result, p.x, p.y);
3236 gui_internal_keynav_find_closest(menu, &p, dx, dy, &distance, &result);
3237 dbg(1,"result=%p\n", result);
3249 gui_internal_keynav_find_closest(menu, &p, dx, dy, &distance, &result);
3250 dbg(1,"wraparound result=%p\n", result);
3252 gui_internal_highlight_do(this, result);
3254 gui_internal_say(this, result, 1);
3257 //##############################################################################################################
3260 //# Authors: Martin Schaller (04/2008)
3261 //##############################################################################################################
3262 static void gui_internal_keypress(void *data, char *key)
3264 struct gui_priv *this=data;
3267 if (!this->root.children) {
3268 transform_get_size(navit_get_trans(this->nav), &w, &h);
3273 navit_set_center_screen(this->nav, &p);
3275 case NAVIT_KEY_DOWN:
3278 navit_set_center_screen(this->nav, &p);
3280 case NAVIT_KEY_LEFT:
3283 navit_set_center_screen(this->nav, &p);
3285 case NAVIT_KEY_RIGHT:
3288 navit_set_center_screen(this->nav, &p);
3290 case NAVIT_KEY_ZOOM_IN:
3291 navit_zoom_in(this->nav, 2, NULL);
3293 case NAVIT_KEY_ZOOM_OUT:
3294 navit_zoom_out(this->nav, 2, NULL);
3296 case NAVIT_KEY_RETURN:
3297 gui_internal_cmd_menu(this, NULL, 0);
3302 graphics_draw_mode(this->gra, draw_mode_begin);
3304 case NAVIT_KEY_LEFT:
3305 gui_internal_keynav_highlight_next(this,-1,0);
3307 case NAVIT_KEY_RIGHT:
3308 gui_internal_keynav_highlight_next(this,1,0);
3311 gui_internal_keynav_highlight_next(this,0,-1);
3313 case NAVIT_KEY_DOWN:
3314 gui_internal_keynav_highlight_next(this,0,1);
3316 case NAVIT_KEY_RETURN:
3317 if (this->highlighted && this->highlighted_menu == g_list_last(this->root.children)->data)
3318 gui_internal_call_highlighted(this);
3320 gui_internal_keypress_do(this, key);
3323 gui_internal_keypress_do(this, key);
3325 graphics_draw_mode(this->gra, draw_mode_end);
3326 gui_internal_check_exit(this);
3330 //##############################################################################################################
3333 //# Authors: Martin Schaller (04/2008)
3334 //##############################################################################################################
3335 static int gui_internal_set_graphics(struct gui_priv *this, struct graphics *gra)
3338 struct color cbh={0x9fff,0x9fff,0x9fff,0xffff};
3339 struct color cf={0xbfff,0xbfff,0xbfff,0xffff};
3340 struct color cw={0xffff,0xffff,0xffff,0xffff};
3341 struct color cbl={0x0000,0x0000,0x0000,0xffff};
3342 struct transformation *trans=navit_get_trans(this->nav);
3344 win=graphics_get_data(gra, "window");
3347 navit_ignore_graphics_events(this->nav, 1);
3350 navit_ignore_graphics_events(this->nav, 1);
3351 transform_get_size(trans, &this->root.w, &this->root.h);
3352 this->resize_cb=callback_new_attr_1(callback_cast(gui_internal_resize), attr_resize, this);
3353 graphics_add_callback(gra, this->resize_cb);
3354 this->button_cb=callback_new_attr_1(callback_cast(gui_internal_button), attr_button, this);
3355 graphics_add_callback(gra, this->button_cb);
3356 this->motion_cb=callback_new_attr_1(callback_cast(gui_internal_motion), attr_motion, this);
3357 graphics_add_callback(gra, this->motion_cb);
3358 this->keypress_cb=callback_new_attr_1(callback_cast(gui_internal_keypress), attr_keypress, this);
3359 graphics_add_callback(gra, this->keypress_cb);
3360 this->background=graphics_gc_new(gra);
3361 this->background2=graphics_gc_new(gra);
3362 this->highlight_background=graphics_gc_new(gra);
3363 graphics_gc_set_foreground(this->highlight_background, &cbh);
3364 this->foreground=graphics_gc_new(gra);
3365 graphics_gc_set_foreground(this->foreground, &cf);
3366 this->text_background=graphics_gc_new(gra);
3367 this->text_foreground=graphics_gc_new(gra);
3368 graphics_gc_set_foreground(this->background, &this->background_color);
3369 graphics_gc_set_foreground(this->background2, &this->background2_color);
3370 graphics_gc_set_foreground(this->text_background, &this->text_background_color);
3371 graphics_gc_set_foreground(this->text_foreground, &this->text_foreground_color);
3373 // set fullscreen if needed
3374 if (this->fullscreen)
3375 this->win->fullscreen(this->win, this->fullscreen);
3379 //##############################################################################################################
3382 //# Authors: Martin Schaller (04/2008)
3383 //##############################################################################################################
3384 struct gui_methods gui_internal_methods = {
3387 gui_internal_set_graphics,
3391 gui_internal_get_data(struct gui_priv *priv, char *command, struct attr **in, struct attr ***out)
3393 struct attr private_data = (struct attr) { attr_private_data, {(void *)&priv->data}};
3395 *out=attr_generic_add_attr(*out, &private_data);
3399 gui_internal_add_callback(struct gui_priv *priv, struct callback *cb)
3401 callback_list_add(priv->cbl, cb);
3405 gui_internal_remove_callback(struct gui_priv *priv, struct callback *cb)
3407 callback_list_remove(priv->cbl, cb);
3411 static struct gui_internal_methods gui_internal_methods_ext = {
3412 gui_internal_add_callback,
3413 gui_internal_remove_callback,
3414 gui_internal_menu_render,
3421 gui_internal_get_flags(struct widget *widget)
3423 return widget->flags;
3427 gui_internal_set_flags(struct widget *widget, enum flags flags)
3429 widget->flags=flags;
3433 gui_internal_get_state(struct widget *widget)
3435 return widget->state;
3439 gui_internal_set_state(struct widget *widget, int state)
3441 widget->state=state;
3445 gui_internal_set_func(struct widget *widget, void (*func)(struct gui_priv *priv, struct widget *widget, void *data))
3451 gui_internal_set_data(struct widget *widget, void *data)
3457 gui_internal_set_default_background(struct gui_priv *this, struct widget *widget)
3459 widget->background=this->background;
3462 static struct gui_internal_widget_methods gui_internal_widget_methods = {
3463 gui_internal_widget_append,
3464 gui_internal_button_new,
3465 gui_internal_button_new_with_callback,
3466 gui_internal_box_new,
3467 gui_internal_label_new,
3468 gui_internal_image_new,
3469 gui_internal_keyboard,
3471 gui_internal_get_flags,
3472 gui_internal_set_flags,
3473 gui_internal_get_state,
3474 gui_internal_set_state,
3475 gui_internal_set_func,
3476 gui_internal_set_data,
3477 gui_internal_set_default_background,
3480 static struct command_table commands[] = {
3481 {"menu",gui_internal_cmd_menu2},
3482 {"fullscreen",gui_internal_cmd_fullscreen},
3483 {"get_data",gui_internal_get_data},
3487 //##############################################################################################################
3490 //# Authors: Martin Schaller (04/2008)
3491 //##############################################################################################################
3492 static struct gui_priv * gui_internal_new(struct navit *nav, struct gui_methods *meth, struct attr **attrs)
3494 struct gui_priv *this;
3496 *meth=gui_internal_methods;
3497 this=g_new0(struct gui_priv, 1);
3499 if ((attr=attr_search(attrs, NULL, attr_menu_on_map_click)))
3500 this->menu_on_map_click=attr->u.num;
3502 this->menu_on_map_click=1;
3503 if ((attr=attr_search(attrs, NULL, attr_callback_list))) {
3504 dbg(0,"register\n");
3505 command_add_table(attr->u.callback_list, commands, sizeof(commands)/sizeof(struct command_table), this);
3508 if( (attr=attr_search(attrs,NULL,attr_font_size)))
3510 this->config.font_size=attr->u.num;
3514 this->config.font_size=-1;
3516 if( (attr=attr_search(attrs,NULL,attr_icon_xs)))
3518 this->config.icon_xs=attr->u.num;
3522 this->config.icon_xs=-1;
3524 if( (attr=attr_search(attrs,NULL,attr_icon_l)))
3526 this->config.icon_l=attr->u.num;
3530 this->config.icon_l=-1;
3532 if( (attr=attr_search(attrs,NULL,attr_icon_s)))
3534 this->config.icon_s=attr->u.num;
3538 this->config.icon_s=-1;
3540 if( (attr=attr_search(attrs,NULL,attr_spacing)))
3542 this->config.spacing=attr->u.num;
3546 this->config.spacing=-1;
3548 if( (attr=attr_search(attrs,NULL,attr_gui_speech)))
3550 this->speech=attr->u.num;
3552 if( (attr=attr_search(attrs,NULL,attr_keyboard)))
3553 this->keyboard=attr->u.num;
3557 if( (attr=attr_search(attrs,NULL,attr_fullscreen)))
3558 this->fullscreen=attr->u.num;
3560 if( (attr=attr_search(attrs,NULL,attr_flags)))
3561 this->flags=attr->u.num;
3562 if( (attr=attr_search(attrs,NULL,attr_background_color)))
3563 this->background_color=*attr->u.color;
3565 this->background_color=(struct color){0x0,0x0,0x0,0xffff};
3566 if( (attr=attr_search(attrs,NULL,attr_background_color2)))
3567 this->background2_color=*attr->u.color;
3569 this->background2_color=(struct color){0x4141,0x4141,0x4141,0xffff};
3570 if( (attr=attr_search(attrs,NULL,attr_text_color)))
3571 this->text_foreground_color=*attr->u.color;
3573 this->text_foreground_color=(struct color){0xffff,0xffff,0xffff,0xffff};
3574 if( (attr=attr_search(attrs,NULL,attr_columns)))
3575 this->cols=attr->u.num;
3576 if( (attr=attr_search(attrs,NULL,attr_osd_configuration)))
3577 this->osd_configuration=*attr;
3578 this->data.priv=this;
3579 this->data.gui=&gui_internal_methods_ext;
3580 this->data.widget=&gui_internal_widget_methods;
3581 this->cbl=callback_list_new();
3586 //##############################################################################################################
3589 //# Authors: Martin Schaller (04/2008)
3590 //##############################################################################################################
3591 void plugin_init(void)
3593 plugin_register_gui_type("internal", gui_internal_new);
3597 * @brief Creates a new table widget.
3599 * Creates and returns a new table widget. This function will
3600 * setup next/previous buttons as children.
3602 * @param this The graphics context.
3603 * @param flags widget sizing flags.
3604 * @returns The newly created widget
3606 struct widget * gui_internal_widget_table_new(struct gui_priv * this, enum flags flags, int buttons)
3608 struct widget * widget = g_new0(struct widget,1);
3609 struct table_data * data = NULL;
3610 widget->type=widget_table;
3611 widget->flags=flags;
3612 widget->data = g_new0(struct table_data,1);
3613 widget->data_free=gui_internal_table_data_free;
3614 data = (struct table_data*)widget->data;
3618 data->next_button = gui_internal_button_new_with_callback
3619 (this,"Next",image_new_xs(this, "gui_active") ,
3620 gravity_left_center |orientation_vertical,
3621 gui_internal_table_button_next,NULL);
3622 data->next_button->data=widget;
3625 data->prev_button = gui_internal_button_new_with_callback
3627 image_new_xs(this, "gui_active")
3628 ,gravity_right_center |orientation_vertical,
3629 gui_internal_table_button_prev,NULL);
3631 data->prev_button->data=widget;
3635 data->button_box=gui_internal_box_new(this,
3636 gravity_center|orientation_horizontal);
3637 data->button_box->children=g_list_append(data->button_box->children,
3639 data->button_box->children=g_list_append(data->button_box->children,
3641 data->button_box->background=this->background2;
3642 data->button_box->bl=this->spacing;
3643 widget->children=g_list_append(widget->children,data->button_box);
3644 gui_internal_widget_pack(this,data->button_box);
3652 * Creates a new table_row widget.
3653 * @param this The graphics context
3654 * @param flags Sizing flags for the row
3655 * @returns The new table_row widget.
3657 static struct widget * gui_internal_widget_table_row_new(struct gui_priv * this, enum flags flags)
3659 struct widget * widget = g_new0(struct widget,1);
3660 widget->type=widget_table_row;
3661 widget->flags=flags;
3668 * @brief Computes the column dimensions for the table.
3670 * @param w The table widget to compute dimensions for.
3672 * This function examines all of the rows and columns for the table w
3673 * and returns a list (GList) of table_column_desc elements that
3674 * describe each column of the table.
3676 * The caller is responsible for freeing the returned list.
3678 static GList * gui_internal_compute_table_dimensions(struct widget * w)
3681 GList * column_desc = NULL;
3682 GList * current_desc=NULL;
3683 GList * cur_row = w->children;
3684 struct widget * cur_row_widget=NULL;
3685 GList * cur_column=NULL;
3686 struct widget * cell_w=NULL;
3687 struct table_column_desc * current_cell=NULL;
3688 struct table_data * table_data=NULL;
3694 * Scroll through the the table and
3695 * 1. Compute the maximum width + height of each column across all rows.
3697 table_data = (struct table_data*) w->data;
3698 for(cur_row=w->children; cur_row ; cur_row = g_list_next(cur_row) )
3700 cur_row_widget = (struct widget*) cur_row->data;
3701 current_desc = column_desc;
3702 if(cur_row_widget == table_data->button_box)
3706 for(cur_column = cur_row_widget->children; cur_column;
3707 cur_column=g_list_next(cur_column))
3709 cell_w = (struct widget*) cur_column->data;
3710 if(current_desc == 0)
3712 current_cell = g_new0(struct table_column_desc,1);
3713 column_desc = g_list_append(column_desc,current_cell);
3714 current_desc = g_list_last(column_desc);
3715 current_cell->height=cell_w->h;
3716 current_cell->width=cell_w->w;
3721 current_cell = current_desc->data;
3724 if(current_cell->height < height )
3726 current_cell->height = height;
3728 if(current_cell->width < width)
3730 current_cell->width = width;
3732 current_desc = g_list_next(current_desc);
3743 * @brief Computes the height and width for the table.
3745 * The height and widht are computed to display all cells in the table
3746 * at the requested height/width.
3748 * @param this The graphics context
3749 * @param w The widget to pack.
3752 void gui_internal_table_pack(struct gui_priv * this, struct widget * w)
3758 GList * column_data = gui_internal_compute_table_dimensions(w);
3760 struct table_column_desc * cell_desc=0;
3761 struct table_data * table_data = (struct table_data*)w->data;
3763 for(current = column_data; current; current=g_list_next(current))
3765 if(table_data->button_box == current->data )
3769 cell_desc = (struct table_column_desc *) current->data;
3770 width = width + cell_desc->width + this->spacing;
3771 if(height < cell_desc->height)
3773 height = cell_desc->height ;
3777 for(current=w->children; current; current=g_list_next(current))
3779 if(current->data!= table_data->button_box)
3784 if (table_data->button_box)
3785 gui_internal_widget_pack(this,table_data->button_box);
3786 w->h = count * (height+this->spacing) + table_data->button_box + this->spacing;
3788 if(w->h + w->c.y > this->root.h )
3791 * Do not allow the widget to exceed the screen.
3794 w->h = this->root.h- w->c.y - height;
3799 * Deallocate column descriptions.
3801 current = column_data;
3802 while( (current = g_list_last(current)) )
3804 current = g_list_remove(current,current->data);
3812 * @brief Renders a table widget.
3814 * @param this The graphics context
3815 * @param w The table widget to render.
3817 void gui_internal_table_render(struct gui_priv * this, struct widget * w)
3822 GList * column_desc=NULL;
3823 GList * cur_row = NULL;
3824 GList * current_desc=NULL;
3825 struct table_data * table_data = (struct table_data*)w->data;
3827 struct table_column_desc * dim=NULL;
3829 column_desc = gui_internal_compute_table_dimensions(w);
3834 * Skip rows that are on previous pages.
3836 cur_row = w->children;
3837 if(table_data->top_row )
3839 cur_row = table_data->top_row;
3844 * Loop through each row. Drawing each cell with the proper sizes,
3845 * at the proper positions.
3847 for(table_data->top_row=cur_row; cur_row; cur_row = g_list_next(cur_row))
3849 GList * cur_column=NULL;
3850 current_desc = column_desc;
3851 struct widget * cur_row_widget = (struct widget*)cur_row->data;
3853 x =w->p.x+this->spacing;
3854 if(cur_row_widget == table_data->button_box )
3858 dim = (struct table_column_desc*)current_desc->data;
3860 if( y + dim->height + (table_data->button_box ? table_data->button_box->h : 0) + this->spacing >= w->p.y + w->h )
3863 * No more drawing space left.
3869 for(cur_column = cur_row_widget->children; cur_column;
3870 cur_column=g_list_next(cur_column))
3872 struct widget * cur_widget = (struct widget*) cur_column->data;
3873 dim = (struct table_column_desc*)current_desc->data;
3876 cur_widget->w=dim->width;
3878 cur_widget->h=dim->height;
3880 max_height = dim->height;
3881 gui_internal_widget_render(this,cur_widget);
3883 if(dim->height > max_height)
3885 max_height = dim->height;
3889 table_data->bottom_row=cur_row;
3890 current_desc = g_list_next(current_desc);
3892 if(table_data && table_data->button_box )
3894 table_data->button_box->p.y =w->p.y+w->h-table_data->button_box->h -
3896 if(table_data->button_box->p.y < y )
3898 table_data->button_box->p.y=y;
3900 table_data->button_box->p.x = w->p.x;
3901 table_data->button_box->w = w->w;
3902 // table_data->button_box->h = w->h - y;
3903 // table_data->next_button->h=table_data->button_box->h;
3904 // table_data->prev_button->h=table_data->button_box->h;
3905 // table_data->next_button->c.y=table_data->button_box->c.y;
3906 // table_data->prev_button->c.y=table_data->button_box->c.y;
3908 gui_internal_widget_pack(this,table_data->button_box);
3909 if(table_data->next_button->p.y > w->p.y + w->h + table_data->next_button->h)
3912 table_data->button_box->p.y = w->p.y + w->h -
3913 table_data->button_box->h;
3917 table_data->next_button->state|= STATE_SENSITIVE;
3921 table_data->next_button->state&= ~STATE_SENSITIVE;
3924 if(table_data->top_row != w->children)
3926 table_data->prev_button->state|= STATE_SENSITIVE;
3930 table_data->prev_button->state&= ~STATE_SENSITIVE;
3932 gui_internal_widget_render(this,table_data->button_box);
3938 * Deallocate column descriptions.
3940 current_desc = column_desc;
3941 while( (current_desc = g_list_last(current_desc)) )
3943 current_desc = g_list_remove(current_desc,current_desc->data);
3949 * TEST function for demonstrating table.
3951 void gui_internal_cmd_route(struct gui_priv * this, struct widget * wm)
3955 struct widget * menu;
3960 w = gui_internal_widget_table_new(this,gravity_center | orientation_vertical);
3962 for(idx=0; idx < 52; idx++)
3964 struct widget * row = gui_internal_widget_table_row_new
3965 (this,gravity_left_top);
3966 sprintf(buffer, "Test %d",idx);
3967 row->children = g_list_append(row->children,
3968 gui_internal_label_new(this,buffer));
3969 row->children= g_list_append(row->children,
3970 gui_internal_label_new(this,"column 2 4 6 8"));
3971 gui_internal_widget_table_add_row(w,row);
3973 menu=gui_internal_menu(this,"Route");
3974 gui_internal_widget_append(menu,w);
3975 gui_internal_menu_render(this);
3982 * @brief handles the 'next page' table event.
3983 * A callback function that is invoked when the 'next page' button is pressed
3984 * to advance the contents of a table widget.
3986 * @param this The graphics context.
3987 * @param wm The button widget that was pressed.
3989 static void gui_internal_table_button_next(struct gui_priv * this, struct widget * wm, void *data)
3991 struct widget * table_widget = (struct widget * ) wm->data;
3992 struct table_data * table_data = NULL;
3998 table_data = (struct table_data*) table_widget->data;
4004 * Before advancing to the next page we need to ensure
4005 * that the current top_row is in the list of previous top_rows
4006 * so previous page can work.
4009 for(iterator=table_data->page_headers; iterator != NULL;
4010 iterator = g_list_next(iterator) )
4012 if(iterator->data == table_data->top_row)
4021 table_data->page_headers=g_list_append(table_data->page_headers,
4022 table_data->top_row);
4025 table_data->top_row = g_list_next(table_data->bottom_row);
4027 wm->state&= ~STATE_HIGHLIGHTED;
4028 gui_internal_menu_render(this);
4034 * @brief handles the 'previous page' table event.
4035 * A callback function that is invoked when the 'previous page' button is pressed
4036 * to go back in the contents of a table widget.
4038 * @param this The graphics context.
4039 * @param wm The button widget that was pressed.
4041 static void gui_internal_table_button_prev(struct gui_priv * this, struct widget * wm, void *data)
4043 struct widget * table_widget = (struct widget * ) wm->data;
4044 struct table_data * table_data = NULL;
4045 GList * current_page_top=NULL;
4050 table_data = (struct table_data*) table_widget->data;
4051 current_page_top = table_data->top_row;
4054 for(iterator = table_data->page_headers; iterator != NULL;
4055 iterator = g_list_next(iterator))
4057 if(current_page_top == iterator->data)
4061 table_data->top_row = (GList*) iterator->data;
4065 wm->state&= ~STATE_HIGHLIGHTED;
4066 gui_internal_menu_render(this);
4071 * @brief deallocates a table_data structure.
4074 void gui_internal_table_data_free(void * p)
4079 * @note button_box and its children (next_button,prev_button)
4080 * have their memory managed by the table itself.
4082 struct table_data * table_data = (struct table_data*) p;
4083 g_list_free(table_data->page_headers);