From 6a712ab2b1369d100c8f8dfde1eb51a0cb9d96be Mon Sep 17 00:00:00 2001 From: martin-s Date: Mon, 4 Jan 2010 09:13:07 +0000 Subject: [PATCH] Add:gui_internal:More html functionality git-svn-id: https://navit.svn.sourceforge.net/svnroot/navit/trunk/navit@2895 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- navit/attr.c | 28 ++-- navit/attr.h | 1 + navit/attr_def.h | 3 + navit/command.c | 12 +- navit/gui/internal/gui_internal.c | 290 ++++++++++++++++++++++++++++++++----- navit/gui/internal/gui_internal.h | 1 + navit/navit.c | 2 + 7 files changed, 290 insertions(+), 47 deletions(-) diff --git a/navit/attr.c b/navit/attr.c index ad9013d..79458e9 100644 --- a/navit/attr.c +++ b/navit/attr.c @@ -504,23 +504,29 @@ attr_free(struct attr *attr) g_free(attr); } -struct attr * -attr_dup(struct attr *attr) +void +attr_dup_content(struct attr *src, struct attr *dst) { int size; - struct attr *ret=g_new0(struct attr, 1); - ret->type=attr->type; - if (attr->type >= attr_type_int_begin && attr->type <= attr_type_int_end) - ret->u.num=attr->u.num; - else if (attr->type >= attr_type_object_begin && attr->type <= attr_type_object_end) - ret->u.data=attr->u.data; + dst->type=src->type; + if (src->type >= attr_type_int_begin && src->type <= attr_type_int_end) + dst->u.num=src->u.num; + else if (src->type >= attr_type_object_begin && src->type <= attr_type_object_end) + dst->u.data=src->u.data; else { - size=attr_data_size(attr); + size=attr_data_size(src); if (size) { - ret->u.data=g_malloc(size); - memcpy(ret->u.data, attr->u.data, size); + dst->u.data=g_malloc(size); + memcpy(dst->u.data, src->u.data, size); } } +} + +struct attr * +attr_dup(struct attr *attr) +{ + struct attr *ret=g_new0(struct attr, 1); + attr_dup_content(attr, ret); return ret; } diff --git a/navit/attr.h b/navit/attr.h index b6db5a7..5c2ec81 100644 --- a/navit/attr.h +++ b/navit/attr.h @@ -156,6 +156,7 @@ void *attr_data_get(struct attr *attr); void attr_data_set(struct attr *attr, void *data); void attr_data_set_le(struct attr *attr, void *data); void attr_free(struct attr *attr); +void attr_dup_content(struct attr *src, struct attr *dst); struct attr *attr_dup(struct attr *attr); void attr_list_free(struct attr **attrs); struct attr **attr_list_dup(struct attr **attrs); diff --git a/navit/attr_def.h b/navit/attr_def.h index 461c0a1..9403042 100644 --- a/navit/attr_def.h +++ b/navit/attr_def.h @@ -276,6 +276,9 @@ ATTR(daylayout) ATTR(nightlayout) ATTR(xml_text) ATTR(layout_name) +ATTR(user_name) +ATTR(user_pass) +ATTR(status_text) ATTR2(0x0003ffff,type_string_end) ATTR2(0x00040000,type_special_begin) ATTR(order) diff --git a/navit/command.c b/navit/command.c index a9e13fd..4d83082 100644 --- a/navit/command.c +++ b/navit/command.c @@ -396,10 +396,16 @@ command_call_function(struct context *ctx, struct result *res) } else { if (command_object_get_attr(ctx, &res->attr, attr_callback_list, &cbl)) { int valid; + struct attr **out=NULL; dbg(1,"function call %s from %s\n",function, attr_to_name(res->attr.type)); - callback_list_call_attr_4(cbl.u.callback_list, attr_command, function, list, NULL, &valid); - } - res->attr.type=attr_none; + callback_list_call_attr_4(cbl.u.callback_list, attr_command, function, list, &out, &valid); + if (out && out[0]) { + attr_dup_content(out[0], &res->attr); + attr_list_free(out); + } else + res->attr.type=attr_none; + } else + res->attr.type=attr_none; } res->var=NULL; res->varlen=0; diff --git a/navit/gui/internal/gui_internal.c b/navit/gui/internal/gui_internal.c index adc5a6c..653298c 100644 --- a/navit/gui/internal/gui_internal.c +++ b/navit/gui/internal/gui_internal.c @@ -71,6 +71,10 @@ #include "xmlconfig.h" #include "util.h" +struct form { + char *onsubmit; +}; + struct menu_data { struct widget *search_list; struct widget *keyboard; @@ -136,6 +140,7 @@ struct widget { */ int cols; enum flags flags; + int flags2; void *instance; int (*set_attr)(void *, struct attr *); int (*get_attr)(void *, enum attr_type, struct attr *, struct attr_iter *); @@ -147,6 +152,7 @@ struct widget { int is_on; int redraw; struct menu_data *menu_data; + struct form *form; GList *children; }; @@ -234,7 +240,7 @@ struct gui_priv { int widgets_count; int redraw; struct widget root; - struct widget *highlighted; + struct widget *highlighted,*editable; struct widget *highlighted_menu; int clickp_valid, vehicle_valid; struct pcoord clickp, vehiclep; @@ -246,6 +252,7 @@ struct gui_priv { char *country_iso2; int speech; int keyboard; + int keyboard_required; /** * The setting information read from the configuration file. * values of -1 indicate no value was specified in the config file. @@ -276,6 +283,7 @@ struct gui_priv { int html_skip; char *html_anchor; int html_anchor_found; + struct form *form; struct html { int skip; enum html_tag { @@ -285,11 +293,15 @@ struct gui_priv { html_tag_html, html_tag_img, html_tag_script, + html_tag_form, + html_tag_input, + html_tag_div, } tag; char *command; char *name; char *href; struct widget *w; + struct widget *container; } html[10]; }; @@ -302,6 +314,9 @@ struct html_tag_map { {"html",html_tag_html}, {"img",html_tag_img}, {"script",html_tag_script}, + {"form",html_tag_form}, + {"input",html_tag_input}, + {"div",html_tag_div}, }; @@ -639,14 +654,25 @@ gui_internal_label_render(struct gui_priv *this, struct widget *w) { struct point pnt=w->p; gui_internal_background_render(this, w); + if (w->state & STATE_EDIT) + graphics_draw_rectangle(this->gra, this->highlight_background, &pnt, w->w, w->h); if (w->text) { + char *text,startext[strlen(w->text)+1]; + text=w->text; + if (w->flags2 & 1) { + int i; + for (i = 0 ; i < strlen(text); i++) + startext[i]='*'; + startext[i]='\0'; + text=startext; + } if (w->flags & gravity_right) { pnt.y+=w->h-this->spacing; pnt.x+=w->w-w->textw-this->spacing; - graphics_draw_text(this->gra, w->foreground, w->text_background, this->fonts[w->font_idx], w->text, &pnt, 0x10000, 0x0); + graphics_draw_text(this->gra, w->foreground, w->text_background, this->fonts[w->font_idx], text, &pnt, 0x10000, 0x0); } else { pnt.y+=w->h-this->spacing; - graphics_draw_text(this->gra, w->foreground, w->text_background, this->fonts[w->font_idx], w->text, &pnt, 0x10000, 0x0); + graphics_draw_text(this->gra, w->foreground, w->text_background, this->fonts[w->font_idx], text, &pnt, 0x10000, 0x0); } } } @@ -887,6 +913,19 @@ static void gui_internal_highlight(struct gui_priv *this) if (this->current.x > -1 && this->current.y > -1) { menu=g_list_last(this->root.children)->data; found=gui_internal_find_widget(menu, &this->current, STATE_SENSITIVE); + if (!found) { + found=gui_internal_find_widget(menu, &this->current, STATE_EDITABLE); + if (found) { + if (this->editable && this->editable != found) { + this->editable->state &= ~ STATE_EDIT; + gui_internal_widget_render(this, this->editable); + } + found->state |= STATE_EDIT; + gui_internal_widget_render(this, found); + this->editable=found; + found=NULL; + } + } } gui_internal_highlight_do(this, found); this->motion_timeout_event=NULL; @@ -1872,7 +1911,7 @@ gui_internal_cmd_add_bookmark2(struct gui_priv *this, struct widget *wm, void *d we=gui_internal_box_new(this, gravity_left_center|orientation_horizontal|flags_fill); gui_internal_widget_append(w, we); gui_internal_widget_append(we, wk=gui_internal_label_new(this, name)); - wk->state |= STATE_EDIT|STATE_CLEAR; + wk->state |= STATE_EDIT|STATE_EDITABLE|STATE_CLEAR; wk->background=this->background; wk->flags |= flags_expand|flags_fill; wk->func = gui_internal_cmd_add_bookmark_changed; @@ -3242,7 +3281,7 @@ gui_internal_search(struct gui_priv *this, char *what, char *type, int flags) wl=gui_internal_box_new(this, gravity_left_top|orientation_vertical|flags_expand|flags_fill); gui_internal_widget_append(wr, wl); gui_internal_menu_data(this)->search_list=wl; - wk->state |= STATE_EDIT; + wk->state |= STATE_EDIT|STATE_EDITABLE; wk->background=this->background; wk->flags |= flags_expand|flags_fill; wk->func = gui_internal_search_changed; @@ -3581,9 +3620,9 @@ gui_internal_add_vehicle_profile(struct gui_priv *this, struct widget name = attr->u.str; // Determine whether the profile is the active one - vehicle_get_attr(v, attr_profilename, &profile_attr, NULL); - active_profile = profile_attr.u.str; - active = strcmp(name, active_profile) == 0; + if (vehicle_get_attr(v, attr_profilename, &profile_attr, NULL)) + active_profile = profile_attr.u.str; + active = active_profile != NULL && !strcmp(name, active_profile); dbg(0, "Adding vehicle profile %s, active=%s/%i\n", name, active_profile, active); @@ -3771,14 +3810,134 @@ gui_internal_html_command(struct gui_priv *this, struct widget *w, void *data) } static void +gui_internal_html_submit_set(struct gui_priv *this, struct widget *w, struct form *form) +{ + GList *l; + if (w->form == form && w->name) { + struct attr *attr=attr_new_from_text(w->name, w->text?w->text:""); + if (attr) + gui_set_attr(this->self.u.gui, attr); + attr_free(attr); + } + l=w->children; + while (l) { + w=l->data; + gui_internal_html_submit_set(this, w, form); + l=g_list_next(l); + } + +} + +static void +gui_internal_html_submit(struct gui_priv *this, struct widget *w, void *data) +{ + struct widget *menu; + GList *l; + + dbg(1,"enter form %p %s\n",w->form,w->form->onsubmit); + l=g_list_last(this->root.children); + menu=l->data; + graphics_draw_mode(this->gra, draw_mode_begin); + gui_internal_highlight_do(this, NULL); + gui_internal_menu_render(this); + graphics_draw_mode(this->gra, draw_mode_end); + gui_internal_html_submit_set(this, menu, w->form); + gui_internal_evaluate(this,w->form->onsubmit); +} + +static void +gui_internal_html_load_href(struct gui_priv *this, char *href, int replace) +{ + if (replace) + gui_internal_prune_menu_count(this, 1, 0); + if (href && href[0] == '#') { + dbg(1,"href=%s\n",href); + gui_internal_html_menu(this, this->html_text, href+1); + } +} + +static void gui_internal_html_href(struct gui_priv *this, struct widget *w, void *data) { - if (w->command && w->command[0] == '#') { - dbg(1,"href=%s\n",w->command); - gui_internal_html_menu(this, this->html_text, w->command+1); + gui_internal_html_load_href(this, w->command, 0); +} + +struct div_flags_map { + char *attr; + char *val; + enum flags flags; +} div_flags_map[] = { + {"gravity","none",gravity_none}, + {"gravity","left",gravity_left}, + {"gravity","xcenter",gravity_xcenter}, + {"gravity","right",gravity_right}, + {"gravity","top",gravity_top}, + {"gravity","ycenter",gravity_ycenter}, + {"gravity","bottom",gravity_bottom}, + {"gravity","left_top",gravity_left_top}, + {"gravity","top_center",gravity_top_center}, + {"gravity","right_top",gravity_right_top}, + {"gravity","left_center",gravity_left_center}, + {"gravity","center",gravity_center}, + {"gravity","right_center",gravity_right_center}, + {"gravity","left_bottom",gravity_left_bottom}, + {"gravity","bottom_center",gravity_bottom_center}, + {"gravity","right_bottom",gravity_right_bottom}, + {"expand","1",flags_expand}, + {"fill","1",flags_fill}, + {"orientation","horizontal",orientation_horizontal}, + {"orientation","vertical",orientation_vertical}, + {"orientation","horizontal_vertical",orientation_horizontal_vertical}, +}; + +static enum flags +div_flag(const char **names, const char **values, char *name) +{ + int i; + enum flags ret=0; + const char *value=find_attr(names, values, name); + if (!value) + return ret; + for (i = 0 ; i < sizeof(div_flags_map)/sizeof(struct div_flags_map); i++) { + if (!strcmp(div_flags_map[i].attr,name) && !strcmp(div_flags_map[i].val,value)) + ret|=div_flags_map[i].flags; } + return ret; } +static enum flags +div_flags(const char **names, const char **values) +{ + enum flags flags; + flags = div_flag(names, values, "gravity"); + flags |= div_flag(names, values, "orientation"); + flags |= div_flag(names, values, "expand"); + flags |= div_flag(names, values, "fill"); + return flags; +} + +static struct widget * +html_image(struct gui_priv *this, const char **names, const char **values) +{ + const char *src, *size; + struct graphics_image *img=NULL; + + src=find_attr(names, values, "src"); + if (!src) + return NULL; + size=find_attr(names, values, "size"); + if (!size) + size="l"; + if (!strcmp(size,"l")) + img=image_new_l(this, src); + else if (!strcmp(size,"s")) + img=image_new_s(this, src); + else if (!strcmp(size,"xs")) + img=image_new_xs(this, src); + if (!img) + return NULL; + return gui_internal_image_new(this, img); +} static void gui_internal_html_start(void *dummy, const char *tag_name, const char **names, const char **values, void *data, void *error) @@ -3787,7 +3946,7 @@ gui_internal_html_start(void *dummy, const char *tag_name, const char **names, c int i; enum html_tag tag=html_tag_none; struct html *html=&this->html[this->html_depth]; - const char *src, *cond; + const char *cond, *type; if (!strcasecmp(tag_name,"text")) return; @@ -3822,9 +3981,45 @@ gui_internal_html_start(void *dummy, const char *tag_name, const char **names, c 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)); + html->w=html_image(this, names, values); + break; + case html_tag_form: + this->form=g_new0(struct form, 1); + this->form->onsubmit=find_attr_dup(names, values, "onsubmit"); + break; + case html_tag_input: + type=find_attr_dup(names, values, "type"); + if (!type) + break; + if (!strcmp(type,"image")) { + html->w=html_image(this, names, values); + if (html->w) { + html->w->state|=STATE_SENSITIVE; + html->w->func=gui_internal_html_submit; + } + } + if (!strcmp(type,"text") || !strcmp(type,"password")) { + html->w=gui_internal_label_new(this, NULL); + html->w->background=this->background; + html->w->flags |= div_flags(names, values); + html->w->state|=STATE_EDITABLE; + if (!this->editable) { + this->editable=html->w; + html->w->state|=STATE_EDIT; + } + this->keyboard_required=1; + if (!strcmp(type,"password")) + html->w->flags2 |= 1; + } + if (html->w) { + html->w->form=this->form; + html->w->name=find_attr_dup(names, values, "name"); + } + break; + case html_tag_div: + html->w=gui_internal_box_new(this, div_flags(names, values)); + html->container=this->html_container; + this->html_container=html->w; break; default: break; @@ -3862,9 +4057,15 @@ gui_internal_html_end(void *dummy, const char *tag_name, void *data, void *error html->w->func=gui_internal_html_href; } switch (html->tag) { + case html_tag_div: + this->html_container=html->container; case html_tag_img: + case html_tag_input: gui_internal_widget_append(this->html_container, html->w); break; + case html_tag_form: + this->form=NULL; + break; default: break; } @@ -3903,13 +4104,15 @@ gui_internal_html_text(void *dummy, const char *text, int len, void *data, void switch (html->tag) { case html_tag_a: if (html->name && len) { - this->html_container=gui_internal_menu(this, gettext(text_stripped)); + this->html_container=gui_internal_box_new(this, gravity_center|orientation_horizontal_vertical|flags_expand|flags_fill); + gui_internal_widget_append(gui_internal_menu(this, gettext(text_stripped)), this->html_container); 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_stripped)); + this->html_container=gui_internal_box_new(this, gravity_center|orientation_horizontal_vertical|flags_expand|flags_fill); + gui_internal_widget_append(gui_internal_menu(this, gettext(text_stripped)), this->html_container); this->html_container->spx=this->spacing*10; } break; @@ -3921,6 +4124,11 @@ gui_internal_html_text(void *dummy, const char *text, int len, void *data, void html->w=w; } break; + case html_tag_div: + if (len) { + gui_internal_widget_append(html->w, gui_internal_text_new(this, gettext(text_stripped), gravity_center|orientation_vertical)); + } + break; case html_tag_script: dbg(1,"execute %s\n",text_stripped); gui_internal_evaluate(this,text_stripped); @@ -3933,22 +4141,27 @@ gui_internal_html_text(void *dummy, const char *text, int len, void *data, void static void gui_internal_html_menu(struct gui_priv *this, const char *document, char *anchor) { + char *doc=g_strdup(document); graphics_draw_mode(this->gra, draw_mode_begin); this->html_container=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); + this->form=NULL; + this->keyboard_required=0; + this->editable=NULL; + callback_list_call_attr_2(this->cbl,attr_gui,anchor,&doc); + xml_parse_text(doc, this, gui_internal_html_start, gui_internal_html_end, gui_internal_html_text); + g_free(doc); + if (this->keyboard_required && this->keyboard) { + this->html_container->flags=gravity_center|orientation_vertical|flags_expand|flags_fill; + gui_internal_widget_append(this->html_container, gui_internal_keyboard(this,2)); + } gui_internal_menu_render(this); graphics_draw_mode(this->gra, draw_mode_end); } -static void gui_internal_menu_root(struct gui_priv *this) -{ - gui_internal_html_menu(this, this->html_text, "Main Menu"); -} - static void gui_internal_enter(struct gui_priv *this, int ignore) { @@ -3970,7 +4183,7 @@ gui_internal_leave(struct gui_priv *this) } static void -gui_internal_cmd_menu(struct gui_priv *this, struct point *p, int ignore) +gui_internal_cmd_menu(struct gui_priv *this, struct point *p, int ignore, char *href) { struct transformation *trans; struct coord c; @@ -4005,15 +4218,26 @@ gui_internal_cmd_menu(struct gui_priv *this, struct point *p, int ignore) this->vehicle_valid=1; } // draw menu - gui_internal_menu_root(this); + gui_internal_html_load_href(this, href?href:"#Main Menu", 0); } static void -gui_internal_cmd_menu2(struct gui_priv *this) +gui_internal_cmd_menu2(struct gui_priv *this, char *function, struct attr **in, struct attr ***out, int *valid) { - if (this->root.children) + char *href=NULL; + int replace=0; + if (in && in[0] && ATTR_IS_STRING(in[0]->type)) { + href=in[0]->u.str; + if (in[1] && ATTR_IS_INT(in[1]->type)) + replace=in[1]->u.num; + } + if (this->root.children) { + if (!href) + return; + gui_internal_html_load_href(this, href, replace); return; - gui_internal_cmd_menu(this, NULL, 0); + } + gui_internal_cmd_menu(this, NULL, 0, href); } @@ -4059,7 +4283,7 @@ gui_internal_cmd_log(struct gui_priv *this) we=gui_internal_box_new(this, gravity_left_center|orientation_horizontal|flags_fill); gui_internal_widget_append(w, we); gui_internal_widget_append(we, wk=gui_internal_label_new(this, _("Message"))); - wk->state |= STATE_EDIT|STATE_CLEAR; + wk->state |= STATE_EDIT|STATE_EDITABLE|STATE_CLEAR; wk->background=this->background; wk->flags |= flags_expand|flags_fill; wk->func = gui_internal_cmd_log_changed; @@ -4146,7 +4370,7 @@ gui_internal_set_attr(struct gui_priv *this, struct attr *attr) return 1; default: dbg(0,"%s\n",attr_to_name(attr->type)); - return 0; + return 1; } } @@ -4206,7 +4430,7 @@ static void gui_internal_button(void *data, int pressed, int button, struct poin if (button != 1) return; if (this->menu_on_map_click) { - gui_internal_cmd_menu(this, p, 0); + gui_internal_cmd_menu(this, p, 0, NULL); return; } if (this->signal_on_map_click) { @@ -4279,7 +4503,7 @@ static void gui_internal_resize(void *data, int w, int h) if (this->root.children) { if (changed) { gui_internal_prune_menu(this, NULL); - gui_internal_menu_root(this); + gui_internal_html_load_href(this, "#Main Menu", 0); } else { gui_internal_menu_render(this); } @@ -4423,7 +4647,7 @@ static void gui_internal_keypress(void *data, char *key) break; case NAVIT_KEY_RETURN: case NAVIT_KEY_MENU: - gui_internal_cmd_menu(this, NULL, 0); + gui_internal_cmd_menu(this, NULL, 0, NULL); break; } return; diff --git a/navit/gui/internal/gui_internal.h b/navit/gui/internal/gui_internal.h index 80f57f8..9363275 100644 --- a/navit/gui/internal/gui_internal.h +++ b/navit/gui/internal/gui_internal.h @@ -7,6 +7,7 @@ struct graphics_image; #define STATE_SENSITIVE 8 #define STATE_EDIT 16 #define STATE_CLEAR 32 +#define STATE_EDITABLE 64 enum widget_type { widget_box=1, diff --git a/navit/navit.c b/navit/navit.c index f06bc67..eb92e8b 100644 --- a/navit/navit.c +++ b/navit/navit.c @@ -2327,6 +2327,8 @@ navit_layout_switch(struct navit *n) if (navit_get_attr(n,attr_layout,&layout_attr,NULL)!=1) { return; //No layout - nothing to switch } + if (!n->vehicle) + return; l=layout_attr.u.layout; if (l->dayname || l->nightname) { -- 1.7.9.5