From b64646352c4d2b4eb77145fb3fcc184ca062a3d4 Mon Sep 17 00:00:00 2001 From: martin-s Date: Wed, 18 Nov 2009 17:09:51 +0000 Subject: [PATCH] Add:gui_internal:Further work on flexible menus git-svn-id: https://navit.svn.sourceforge.net/svnroot/navit/trunk@2760 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- navit/navit/command.c | 8 +- navit/navit/gui.c | 12 ++ navit/navit/gui.h | 1 + navit/navit/gui/internal/gui_internal.c | 319 ++++++++++++++++++++++++++------ navit/navit/gui/internal/gui_internal.h | 2 +- navit/navit/xmlconfig.c | 2 +- navit/navit/xmlconfig.h | 2 +- 7 files changed, 283 insertions(+), 63 deletions(-) diff --git a/navit/navit/command.c b/navit/navit/command.c index b1dcf7b..fc283fc 100644 --- a/navit/navit/command.c +++ b/navit/navit/command.c @@ -196,11 +196,8 @@ static void resolve(struct context *ctx, struct result *res, struct attr *parent) //FIXME What is that parent for? { resolve_object(ctx, res); - if (res->attr.type >= attr_type_object_begin && res->attr.type <= attr_type_object_end) { - if (res->attrn) - command_get_attr(ctx, res); - return; - } + if (res->attrn) + command_get_attr(ctx, res); } static double @@ -685,6 +682,7 @@ eval_list(struct context *ctx) attr_list_free(ret); return NULL; } + resolve(ctx, &tmp, NULL); ret=attr_generic_add_attr(ret, &tmp.attr); if (!get_op(ctx,0,",",NULL)) return ret; } diff --git a/navit/navit/gui.c b/navit/navit/gui.c index 3f4b931..f05a90d 100644 --- a/navit/navit/gui.c +++ b/navit/navit/gui.c @@ -31,6 +31,7 @@ struct gui { struct gui_methods meth; struct gui_priv *priv; struct attr **attrs; + struct attr parent; }; struct gui * @@ -54,12 +55,23 @@ gui_new(struct attr *parent, struct attr **attrs) cbl.u.callback_list=callback_list_new(); this_->attrs=attr_generic_add_attr(this_->attrs, &cbl); this_->priv=guitype_new(parent->u.navit, &this_->meth, this_->attrs); + this_->parent=*parent; return this_; } int gui_get_attr(struct gui *this_, enum attr_type type, struct attr *attr, struct attr_iter *iter) { + int ret; + if (this_->meth.get_attr) { + ret=this_->meth.get_attr(this_->priv, type, attr); + if (ret) + return ret; + } + if (type == this_->parent.type) { + *attr=this_->parent; + return 1; + } return attr_generic_get_attr(this_->attrs, NULL, type, attr, iter); } diff --git a/navit/navit/gui.h b/navit/navit/gui.h index 419582a..db1793b 100644 --- a/navit/navit/gui.h +++ b/navit/navit/gui.h @@ -37,6 +37,7 @@ struct gui_methods { struct datawindow_priv *(*datawindow_new)(struct gui_priv *priv, char *name, struct callback *click, struct callback *close, struct datawindow_methods *meth); int (*add_bookmark)(struct gui_priv *priv, struct pcoord *c, char *description); void (*disable_suspend)(struct gui_priv *priv); + int (*get_attr)(struct gui_priv *priv, enum attr_type type, struct attr *attr); }; diff --git a/navit/navit/gui/internal/gui_internal.c b/navit/navit/gui/internal/gui_internal.c index 0b26aad..b8ee764 100644 --- a/navit/navit/gui/internal/gui_internal.c +++ b/navit/navit/gui/internal/gui_internal.c @@ -71,6 +71,34 @@ #include "xmlconfig.h" #include "util.h" +const char *menu_html= + "" + "Main menu" +#ifdef NOTYET + ""_n("Actions")"" +#else + ""_n("Actions")"" +#endif +#if 0 + ""_n("Show
Map")"" +#endif + ""_n("Settings")"" + ""_n("Tools")"" + ""_n("Route")"" + "" +#ifdef NOTYET + "Actions" + ""_n("Bookmarks")"" + "" + "" + "Town" + "Quit" + "Stop\nNavigation" + "" +#endif + "" +; + struct menu_data { struct widget *search_list; struct widget *keyboard; @@ -234,6 +262,7 @@ struct gui_priv { struct widget *highlighted_menu; int clickp_valid, vehicle_valid; struct pcoord clickp, vehiclep; + struct coord_geo clickp_geo; struct search_list *sl; int ignore_button; int menu_on_map_click; @@ -263,8 +292,38 @@ struct gui_priv { struct attr osd_configuration; int pitch; /* html */ - char *html_tag,*html_command; - struct widget *html_container, *html_curr; + + int html_depth; + struct widget *html_container; + int html_skip; + char *html_anchor; + int html_anchor_found; + struct html { + int skip; + enum html_tag { + html_tag_none, + html_tag_a, + html_tag_h1, + html_tag_html, + html_tag_img, + html_tag_script, + } tag; + char *command; + char *name; + char *href; + struct widget *w; + } html[10]; +}; + +struct html_tag_map { + char *tag_name; + enum html_tag tag; +} html_tag_map[] = { + {"a",html_tag_a}, + {"h1",html_tag_h1}, + {"html",html_tag_html}, + {"img",html_tag_img}, + {"script",html_tag_script}, }; @@ -379,6 +438,7 @@ static struct widget *gui_internal_keyboard_do(struct gui_priv *this, struct wid static struct menu_data * gui_internal_menu_data(struct gui_priv *this); static int gui_internal_is_active_vehicle(struct gui_priv *this, struct vehicle *vehicle); +static void gui_internal_html_menu(struct gui_priv *this, const char *document, char *anchor); /* * * Display image scaled to specific size @@ -468,16 +528,12 @@ image_new_l(struct gui_priv *this, const char *name) } static char * -coordinates(struct pcoord *pc, char sep) +coordinates_geo(const struct coord_geo *gc, char sep) { char latc='N',lngc='E'; int lat_deg,lat_min,lat_sec; int lng_deg,lng_min,lng_sec; - struct coord_geo g; - struct coord c; - c.x=pc->x; - c.y=pc->y; - transform_to_geo(pc->pro, &c, &g); + struct coord_geo g=*gc; if (g.lat < 0) { g.lat=-g.lat; @@ -496,6 +552,18 @@ coordinates(struct pcoord *pc, char sep) 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); } +static char * +coordinates(struct pcoord *pc, char sep) +{ + struct coord_geo g; + struct coord c; + c.x=pc->x; + c.y=pc->y; + transform_to_geo(pc->pro, &c, &g); + return coordinates_geo(&g, sep); + +} + static void gui_internal_background_render(struct gui_priv *this, struct widget *w) { @@ -829,7 +897,7 @@ static void gui_internal_highlight(struct gui_priv *this) } static struct widget * -gui_internal_box_new_with_label(struct gui_priv *this, enum flags flags, char *label) +gui_internal_box_new_with_label(struct gui_priv *this, enum flags flags, const char *label) { struct widget *widget=g_new0(struct widget, 1); @@ -1594,7 +1662,7 @@ gui_internal_button_label(struct gui_priv *this, char *label, int mode) static struct widget * -gui_internal_menu(struct gui_priv *this, char *label) +gui_internal_menu(struct gui_priv *this, const char *label) { struct widget *menu,*w,*w1,*topbox; @@ -3517,73 +3585,179 @@ find_attr(const char **names, const char **values, const char *name) return NULL; } +static char * +find_attr_dup(const char **names, const char **values, const char *name) +{ + return g_strdup(find_attr(names, values, name)); +} + static void -gui_internal_html_command(struct gui_priv *this, struct widget *w, void *data) +gui_internal_evaluate(struct gui_priv *this, const char *command) { struct attr attr; /* FIXME */ - if (w->command && navit_get_attr(this->nav, attr_gui, &attr, NULL)) { - command_evaluate(&attr, w->command); + if (command && navit_get_attr(this->nav, attr_gui, &attr, NULL)) + command_evaluate(&attr, command); +} + + +static void +gui_internal_html_command(struct gui_priv *this, struct widget *w, void *data) +{ + gui_internal_evaluate(this,w->command); +} + +static void +gui_internal_html_href(struct gui_priv *this, struct widget *w, void *data) +{ + if (w->command && w->command[0] == '#') { + dbg(0,"href=%s\n",w->command); + gui_internal_html_menu(this, menu_html, w->command+1); } } + static void -gui_internal_html_start(void *dummy, const char *tag, const char **names, const char **values, void *data, void *error) +gui_internal_html_start(void *dummy, const char *tag_name, const char **names, const char **values, void *data, void *error) { struct gui_priv *this=data; - g_free(this->html_tag); - g_free(this->html_command); - this->html_tag=g_strdup(tag); - if (!strcasecmp(tag,"img")) { - const char *src=find_attr(names, values, "src"); - this->html_command=g_strdup(find_attr(names, values, "onclick")); - if (src) - this->html_curr=gui_internal_image_new(this, image_new_l(this, src)); + int i; + enum html_tag tag=html_tag_none; + struct html *html=&this->html[this->html_depth]; + const char *src; + html->command=NULL; + html->name=NULL; + html->href=NULL; + html->skip=0; + for (i=0 ; i < sizeof(html_tag_map)/sizeof(struct html_tag_map); i++) { + if (!strcasecmp(html_tag_map[i].tag_name, tag_name)) { + tag=html_tag_map[i].tag; + break; + } } + html->tag=tag; + if (!this->html_skip) { + switch (tag) { + case html_tag_a: + html->name=find_attr_dup(names, values, "name"); + if (html->name) { + if (this->html_anchor_found) + html->skip=1; + else + html->skip=this->html_anchor ? strcmp(html->name,this->html_anchor) : 0; + if (!html->skip) + this->html_anchor_found=1; + } + html->href=find_attr_dup(names, values, "href"); + break; + case html_tag_img: + html->command=find_attr_dup(names, values, "onclick"); + src=find_attr(names, values, "src"); + if (src) + html->w=gui_internal_image_new(this, image_new_l(this, src)); + break; + default: + break; + } + } + this->html_skip+=html->skip; + this->html_depth++; } static void -gui_internal_html_end(void *dummy, const char *tag, void *data, void *error) +gui_internal_html_end(void *dummy, const char *tag_name, void *data, void *error) { struct gui_priv *this=data; - if (this->html_command && this->html_curr) { - struct widget *w=this->html_curr; - w->state |= STATE_SENSITIVE; - w->command=this->html_command; - w->func=gui_internal_html_command; - this->html_command=NULL; - } - if (!strcasecmp(this->html_tag, "img")) { - gui_internal_widget_append(this->html_container, this->html_curr); + this->html_depth--; + struct html *html=&this->html[this->html_depth]; + struct html *parent=NULL; + + + if (this->html_depth > 0) + parent=&this->html[this->html_depth-1]; + + + if (!this->html_skip) { + if (html->command && html->w) { + html->w->state |= STATE_SENSITIVE; + html->w->command=html->command; + html->w->func=gui_internal_html_command; + html->command=NULL; + } + if (parent && parent->href) { + html->w->state |= STATE_SENSITIVE; + html->w->command=g_strdup(parent->href); + html->w->func=gui_internal_html_href; + } + switch (html->tag) { + case html_tag_img: + gui_internal_widget_append(this->html_container, html->w); + break; + default: + break; + } } - this->html_curr=NULL; + this->html_skip-=html->skip; + g_free(html->command); + g_free(html->name); + g_free(html->href); } static void gui_internal_html_text(void *dummy, const char *text, int len, void *data, void *error) { struct gui_priv *this=data; - if (!strcasecmp(this->html_tag, "h1")) { + struct widget *w; + int depth=this->html_depth-1; + struct html *html=&this->html[depth]; + struct attr attr; + + if (this->html_skip) + return; + if (html->tag == html_tag_html && depth > 2) { + if (this->html[depth-1].tag == html_tag_script) { + html=&this->html[depth-2]; + } + } + switch (html->tag) { + case html_tag_a: + if (html->name && len) { + this->html_container=gui_internal_menu(this, gettext(text)); + this->html_container->spx=this->spacing*10; + } + break; + case html_tag_h1: if (!this->html_container) { this->html_container=gui_internal_menu(this, gettext(text)); this->html_container->spx=this->spacing*10; } - } - if (!strcasecmp(this->html_tag, "img")) { - struct widget *w; - w=gui_internal_box_new(this, gravity_center|orientation_vertical); - gui_internal_widget_append(w, this->html_curr); - gui_internal_widget_append(w, gui_internal_text_new(this, gettext(text), gravity_center|orientation_vertical)); - this->html_curr=w; + break; + case html_tag_img: + if (len) { + w=gui_internal_box_new(this, gravity_center|orientation_vertical); + gui_internal_widget_append(w, html->w); + gui_internal_widget_append(w, gui_internal_text_new(this, gettext(text), gravity_center|orientation_vertical)); + html->w=w; + } + break; + case html_tag_script: + attr.type=attr_gui; + dbg(0,"execute %s\n",text); + gui_internal_evaluate(this,text); + break; + default: + break; } } static void -gui_internal_html_menu(struct gui_priv *this, char *document) +gui_internal_html_menu(struct gui_priv *this, const char *document, char *anchor) { graphics_draw_mode(this->gra, draw_mode_begin); this->html_container=NULL; - this->html_curr=NULL; + this->html_depth=0; + this->html_anchor=anchor; + this->html_anchor_found=0; xml_parse_text(document, this, gui_internal_html_start, gui_internal_html_end, gui_internal_html_text); gui_internal_menu_render(this); graphics_draw_mode(this->gra, draw_mode_end); @@ -3592,18 +3766,7 @@ gui_internal_html_menu(struct gui_priv *this, char *document) static void gui_internal_menu_root(struct gui_priv *this) { - gui_internal_html_menu(this, - "" - "

"_n("Main menu")"

" - ""_n("Actions")"" -#if 0 - ""_n("Show
Map")"" -#endif - ""_n("Settings")"" - ""_n("Tools")"" - ""_n("Route")"" - "" - ); + gui_internal_html_menu(this, menu_html, "Main Menu"); } static void @@ -3642,6 +3805,7 @@ gui_internal_cmd_menu(struct gui_priv *this, struct point *p, int ignore) this->clickp.pro=transform_get_projection(trans); this->clickp.x=c.x; this->clickp.y=c.y; + transform_to_geo(this->clickp.pro, &c, &this->clickp_geo); this->clickp_valid=1; } if (navit_get_attr(this->nav, attr_vehicle, &attr, NULL) && attr.u.vehicle @@ -3738,6 +3902,27 @@ gui_internal_check_exit(struct gui_priv *this) } } +static int +gui_internal_get_attr(struct gui_priv *this, enum attr_type type, struct attr *attr) +{ + switch (type) { + case attr_active: + attr->u.num=this->root.children != NULL; + break; + case attr_position_coord_geo: + if (!this->clickp_valid) + return 0; + attr->u.coord_geo=&this->clickp_geo; + break; + default: + dbg(0,"%s\n",attr_to_name(type)); + return 0; + } + attr->type=type; + return 1; +} + + //############################################################################################################## //# Description: Function to handle mouse clicks and scroll wheel movement //# Comment: @@ -4057,6 +4242,7 @@ struct gui_methods gui_internal_methods = { NULL, NULL, gui_internal_disable_suspend, + gui_internal_get_attr, }; static void @@ -4149,6 +4335,28 @@ static struct gui_internal_widget_methods gui_internal_widget_methods = { gui_internal_set_default_background, }; +static void +gui_internal_cmd_write(struct gui_priv * this, char *function, struct attr **in, struct attr ***out, int *valid) +{ + char *str=NULL,*str2=NULL; + dbg(0,"enter %s %p %p %p\n",function,in,out,valid); + if (!in || !in[0]) + return; + dbg(0,"%s\n",attr_to_name(in[0]->type)); + if (in[0]->type >= attr_type_string_begin && in[0]->type <= attr_type_string_end) { + str=in[0]->u.str; + } + if (in[0]->type >= attr_type_coord_geo_begin && in[0]->type <= attr_type_coord_geo_end) { + str=str2=coordinates_geo(in[0]->u.coord_geo, '\n'); + } + if (str) { + str=g_strdup_printf("%s\n",str); + xml_parse_text(str, this, gui_internal_html_start, gui_internal_html_end, gui_internal_html_text); + } + g_free(str); + g_free(str2); +} + static struct command_table commands[] = { {"actions",command_cast(gui_internal_cmd_actions)}, {"fullscreen",command_cast(gui_internal_cmd_fullscreen)}, @@ -4158,6 +4366,7 @@ static struct command_table commands[] = { {"route",command_cast(gui_internal_cmd_route)}, {"settings",command_cast(gui_internal_cmd_settings)}, {"tools",command_cast(gui_internal_cmd_tools)}, + {"write",command_cast(gui_internal_cmd_write)}, }; diff --git a/navit/navit/gui/internal/gui_internal.h b/navit/navit/gui/internal/gui_internal.h index f8dd244..80f57f8 100644 --- a/navit/navit/gui/internal/gui_internal.h +++ b/navit/navit/gui/internal/gui_internal.h @@ -58,7 +58,7 @@ struct gui_internal_widget_methods { struct widget * (*label_new)(struct gui_priv *this, char *text); struct widget * (*image_new)(struct gui_priv *this, struct graphics_image *image); struct widget * (*keyboard)(struct gui_priv *this, int mode); - struct widget * (*menu)(struct gui_priv *this, char *label); + struct widget * (*menu)(struct gui_priv *this, const char *label); enum flags (*get_flags)(struct widget *widget); void (*set_flags)(struct widget *widget, enum flags flags); int (*get_state)(struct widget *widget); diff --git a/navit/navit/xmlconfig.c b/navit/navit/xmlconfig.c index 027c344..ec02022 100644 --- a/navit/navit/xmlconfig.c +++ b/navit/navit/xmlconfig.c @@ -828,7 +828,7 @@ parse_node_text(ezxml_t node, void *data, void (*start)(void *, const char *, co #endif void -xml_parse_text(char *document, void *data, void (*start)(void *, const char *, const char **, const char **, void *, void *), +xml_parse_text(const char *document, void *data, void (*start)(void *, const char *, const char **, const char **, void *, void *), void (*end)(void *, const char *, void *, void *), void (*text)(void *, const char *, int, void *, void *)) { diff --git a/navit/navit/xmlconfig.h b/navit/navit/xmlconfig.h index f28041a..8ae89e9 100644 --- a/navit/navit/xmlconfig.h +++ b/navit/navit/xmlconfig.h @@ -40,7 +40,7 @@ extern const int xml_attr_distance; /* prototypes */ enum attr_type; struct object_func *object_func_lookup(enum attr_type type); -void xml_parse_text(char *document, void *data, void (*start)(void *, const char *, const char **, const char **, void *, void *), void (*end)(void *, const char *, void *, void *), void (*text)(void *, const char *, int, void *, void *)); +void xml_parse_text(const char *document, void *data, void (*start)(void *, const char *, const char **, const char **, void *, void *), void (*end)(void *, const char *, void *, void *), void (*text)(void *, const char *, int, void *, void *)); gboolean config_load(const char *filename, xmlerror **error); /* end of prototypes */ #endif -- 2.7.4