diff options
Diffstat (limited to 'navit/gui/internal')
| -rw-r--r-- | navit/gui/internal/gui_internal.c | 59 | ||||
| -rw-r--r-- | navit/gui/internal/gui_internal.h | 5 | ||||
| -rw-r--r-- | navit/gui/internal/gui_internal_bookmark.c | 6 | ||||
| -rw-r--r-- | navit/gui/internal/gui_internal_command.c | 125 | ||||
| -rw-r--r-- | navit/gui/internal/gui_internal_html.c | 7 | ||||
| -rw-r--r-- | navit/gui/internal/gui_internal_keyboard.c | 147 | ||||
| -rw-r--r-- | navit/gui/internal/gui_internal_keyboard.h | 1 | ||||
| -rw-r--r-- | navit/gui/internal/gui_internal_menu.c | 61 | ||||
| -rw-r--r-- | navit/gui/internal/gui_internal_poi.c | 2 | ||||
| -rw-r--r-- | navit/gui/internal/gui_internal_search.c | 13 | ||||
| -rw-r--r-- | navit/gui/internal/gui_internal_widget.c | 41 |
11 files changed, 353 insertions, 114 deletions
diff --git a/navit/gui/internal/gui_internal.c b/navit/gui/internal/gui_internal.c index 3affd52e4..fd450b57c 100644 --- a/navit/gui/internal/gui_internal.c +++ b/navit/gui/internal/gui_internal.c @@ -88,6 +88,7 @@ #include "gui_internal_gesture.h" #include "gui_internal_poi.h" #include "gui_internal_command.h" +#include "gui_internal_keyboard.h" /** @@ -743,9 +744,7 @@ gui_internal_call_linked_on_finish(struct gui_priv *this, struct widget *wm, voi struct widget * gui_internal_keyboard(struct gui_priv *this, int mode); - - - +struct widget * gui_internal_keyboard_show_native(struct gui_priv *this, struct widget *w, int mode, char *lang); static void @@ -1674,9 +1673,15 @@ gui_internal_keypress_do(struct gui_priv *this, char *key) dbg(lvl_info,"wi->state=0x%x\n", wi->state); } text=g_strdup_printf("%s%s", wi->text ? wi->text : "", key); + + gui_internal_keyboard_to_lower_case(this); } g_free(wi->text); wi->text=text; + + if(!wi->text || !*wi->text) + gui_internal_keyboard_to_upper_case(this); + if (wi->func) { wi->reason=gui_internal_reason_keypress; wi->func(this, wi, wi->data); @@ -2668,6 +2673,12 @@ static void gui_internal_resize(void *data, int w, int h) this->root.h=h; changed=1; } + /* + * If we're drawing behind system bars on Android, watching for actual size changes will not catch + * fullscreen toggle events. As a workaround, always assume a size change if padding is supplied. + */ + if (!changed && this->gra && graphics_get_data(this->gra, "padding")) + changed = 1; dbg(lvl_debug,"w=%d h=%d children=%p\n", w, h, this->root.children); navit_handle_resize(this->nav, w, h); if (this->root.children) { @@ -2697,7 +2708,9 @@ gui_internal_keynav_point(struct widget *w, int dx, int dy, struct point *p) static struct widget* gui_internal_keynav_find_next_sensitive_child(struct widget *wi) { GList *l=wi->children; - if (wi && wi->state & STATE_SENSITIVE) + if (wi->state & STATE_OFFSCREEN) + return NULL; + if (wi->state & STATE_SENSITIVE) return wi; while (l) { struct widget* tmp = gui_internal_keynav_find_next_sensitive_child(l->data); @@ -2742,6 +2755,9 @@ gui_internal_keynav_find_prev(struct widget *wi, struct widget *current_highligh // Reached current widget; last widget found is the result. return RESULT_FOUND; } + // If widget is off-screen, do not recurse into it. + if (wi->state & STATE_OFFSCREEN) + return NO_RESULT_YET; if (wi->state & STATE_SENSITIVE) *result= wi; GList *l=wi->children; @@ -3102,12 +3118,14 @@ static struct gui_internal_widget_methods gui_internal_widget_methods = { gui_internal_set_default_background, }; - -/* - * @brief Displays Route information +/** + * @brief finds the intersection point of 2 lines + * + * @param coord a1, a2, b1, b2 : coords of the start and + * end of the first and the second line + * @param coord res, will become the coords of the intersection if found + * @return : TRUE if intersection found, otherwise FALSE */ -/* FIXME where is the implementation? */ - int line_intersection(struct coord* a1, struct coord *a2, struct coord * b1, struct coord *b2, struct coord *res) { @@ -3125,18 +3143,19 @@ line_intersection(struct coord* a1, struct coord *a2, struct coord * b1, struct b = -b; } if (a < 0 || b < 0) - return 0; + return FALSE; if (a > n || b > n) - return 0; + return FALSE; if (n == 0) { dbg(lvl_info,"a=%d b=%d n=%d\n", a, b, n); dbg(lvl_info,"a1=0x%x,0x%x ad %d,%d\n", a1->x, a1->y, adx, ady); dbg(lvl_info,"b1=0x%x,0x%x bd %d,%d\n", b1->x, b1->y, bdx, bdy); - dbg_assert(n != 0); + dbg(lvl_info,"No intersection found, lines assumed parallel ?\n"); + return FALSE; } res->x = a1->x + a * adx / n; res->y = a1->y + a * ady / n; - return 1; + return TRUE; } struct heightline * @@ -3166,18 +3185,6 @@ item_get_heightline(struct item *item) return ret; } - -/* - * @brief Displays Route Height Profile - * - * @li The name of the active vehicle - * @param wm The button that was pressed. - * @param v Unused - */ -/* FIXME where is the implementation? */ - - - /** * @brief Called when the route is updated. */ @@ -3445,5 +3452,5 @@ static struct gui_priv * gui_internal_new(struct navit *nav, struct gui_methods //############################################################################################################## void plugin_init(void) { - plugin_register_gui_type("internal", gui_internal_new); + plugin_register_category_gui("internal", gui_internal_new); } diff --git a/navit/gui/internal/gui_internal.h b/navit/gui/internal/gui_internal.h index cbe1e20df..ea5ab79ae 100644 --- a/navit/gui/internal/gui_internal.h +++ b/navit/gui/internal/gui_internal.h @@ -1,15 +1,14 @@ -struct widget; // defined in gui_internal.c +struct widget; struct graphics_image; struct gui_priv; -#define STATE_VISIBLE 1 -#define STATE_SELECTED 2 #define STATE_HIGHLIGHTED 4 #define STATE_SENSITIVE 8 #define STATE_EDIT 16 #define STATE_CLEAR 32 #define STATE_EDITABLE 64 #define STATE_SCROLLABLE 128 +#define STATE_OFFSCREEN 256 #define GESTURE_RINGSIZE 100 diff --git a/navit/gui/internal/gui_internal_bookmark.c b/navit/gui/internal/gui_internal_bookmark.c index 21102ba1a..eed0de123 100644 --- a/navit/gui/internal/gui_internal_bookmark.c +++ b/navit/gui/internal/gui_internal_bookmark.c @@ -104,6 +104,8 @@ gui_internal_cmd_add_bookmark2(struct gui_priv *this, struct widget *wm, void *d gui_internal_widget_append(w, wl); if (this->keyboard) gui_internal_widget_append(w, gui_internal_keyboard(this, VKBD_FLAG_2 | gui_internal_keyboard_init_mode(getenv("LANG")))); + else + gui_internal_keyboard_show_native(this, w, VKBD_FLAG_2 | gui_internal_keyboard_init_mode(getenv("LANG")), getenv("LANG")); gui_internal_menu_render(this); } @@ -132,6 +134,8 @@ gui_internal_cmd_add_bookmark_folder2(struct gui_priv *this, struct widget *wm, gui_internal_widget_append(w, wl); if (this->keyboard) gui_internal_widget_append(w, gui_internal_keyboard(this, VKBD_FLAG_2 | gui_internal_keyboard_init_mode(getenv("LANG")))); + else + gui_internal_keyboard_show_native(this, w, VKBD_FLAG_2 | gui_internal_keyboard_init_mode(getenv("LANG")), getenv("LANG")); gui_internal_menu_render(this); } @@ -161,6 +165,8 @@ gui_internal_cmd_rename_bookmark(struct gui_priv *this, struct widget *wm, void gui_internal_widget_append(w, wl); if (this->keyboard) gui_internal_widget_append(w, gui_internal_keyboard(this, VKBD_FLAG_2 | gui_internal_keyboard_init_mode(getenv("LANG")))); + else + gui_internal_keyboard_show_native(this, w, VKBD_FLAG_2 | gui_internal_keyboard_init_mode(getenv("LANG")), getenv("LANG")); gui_internal_menu_render(this); } diff --git a/navit/gui/internal/gui_internal_command.c b/navit/gui/internal/gui_internal_command.c index 98a736fb8..d26bd677d 100644 --- a/navit/gui/internal/gui_internal_command.c +++ b/navit/gui/internal/gui_internal_command.c @@ -294,6 +294,8 @@ gui_internal_cmd_enter_coord(struct gui_priv *this, char *function, struct attr if (this->keyboard) gui_internal_widget_append(w, gui_internal_keyboard(this, VKBD_DEGREE)); + else + gui_internal_keyboard_show_native(this, w, VKBD_DEGREE, NULL); gui_internal_menu_render(this); } @@ -444,13 +446,21 @@ gui_internal_cmd2_setting_layout(struct gui_priv *this, char *function, struct a navit_attr_iter_destroy(iter); gui_internal_menu_render(this); } + +/* + * @brief Displays Route Height Profile + * + * displays a heightprofile if a route is active and + * some heightinfo is provided by means of a map + * + * the name of the file providing the heightlines must + * comply with *.heightlines.bin + * + */ static void gui_internal_cmd2_route_height_profile(struct gui_priv *this, char *function, struct attr **in, struct attr ***out, int *valid) { - - struct widget * menu, *box; - struct map * map=NULL; struct map_rect * mr=NULL; struct route * route; @@ -458,17 +468,18 @@ gui_internal_cmd2_route_height_profile(struct gui_priv *this, char *function, st struct mapset *ms; struct mapset_handle *msh; int x,i,first=1,dist=0; + int diagram_points_count = 0; struct coord c,last,res; struct coord_rect rbbox,dbbox; struct map_selection sel; struct heightline *heightline,*heightlines=NULL; struct diagram_point *min,*diagram_point,*diagram_points=NULL; + struct point p[2]; sel.next=NULL; sel.order=18; sel.range.min=type_height_line_1; sel.range.max=type_height_line_3; - menu=gui_internal_menu(this,_("Height Profile")); box = gui_internal_box_new(this, gravity_left_top| orientation_vertical | flags_fill | flags_expand); gui_internal_widget_append(menu, box); @@ -489,11 +500,24 @@ gui_internal_cmd2_route_height_profile(struct gui_priv *this, char *function, st } } map_rect_destroy(mr); + mr = NULL; ms=navit_get_mapset(this->nav); if (!first && ms) { + int heightmap_installed = FALSE; msh=mapset_open(ms); while ((map=mapset_next(msh, 1))) { - mr=map_rect_new(map, &sel); + struct attr name_attr; + if (map_get_attr(map, attr_name, &name_attr, NULL)){ + dbg(lvl_debug,"map name = %s\n",name_attr.u.str); + if (strstr(name_attr.u.str,".heightlines.bin")){ + dbg(lvl_info,"reading heightlines from map %s\n",name_attr.u.str); + mr=map_rect_new(map, &sel); + heightmap_installed = TRUE; + } + else { + dbg(lvl_debug,"ignoring map %s\n",name_attr.u.str); + } + } if (mr) { while((item = map_rect_get_item(mr))) { if (item->type >= sel.range.min && item->type <= sel.range.max) { @@ -505,9 +529,20 @@ gui_internal_cmd2_route_height_profile(struct gui_priv *this, char *function, st } } map_rect_destroy(mr); + mr = NULL; } } mapset_close(msh); + if (!heightmap_installed){ + char *text; + struct widget *w; + text=g_strdup_printf("%s",_("please install a map *.heightlines.bin to provide elevationdata")); + gui_internal_widget_append(box, w=gui_internal_label_new(this, text)); + w->flags=gravity_bottom_center|orientation_horizontal|flags_fill; + g_free(text); + gui_internal_menu_render(this); + return; + } } } map=NULL; @@ -537,7 +572,8 @@ gui_internal_cmd2_route_height_profile(struct gui_priv *this, char *function, st diagram_point->c.y=heightline->height; diagram_point->next=diagram_points; diagram_points=diagram_point; - dbg(lvl_info,"%d %d\n", diagram_point->c.x, diagram_point->c.y); + diagram_points_count ++; + dbg(lvl_debug,"%d %d\n", diagram_point->c.x, diagram_point->c.y); } } } @@ -548,18 +584,30 @@ gui_internal_cmd2_route_height_profile(struct gui_priv *this, char *function, st } last=c; } - } } - + while (heightlines){ + heightline=heightlines; + heightlines=heightlines->next; + g_free(heightline); + } if(mr) map_rect_destroy(mr); - gui_internal_menu_render(this); - - if(!diagram_points) + if(diagram_points_count < 2){ + char *text; + struct widget *w; + text=g_strdup_printf("%s",_("The route must cross at least 2 heightlines")); + gui_internal_widget_append(box, w=gui_internal_label_new(this, text)); + w->flags=gravity_bottom_center|orientation_horizontal|flags_fill; + g_free(text); + gui_internal_menu_render(this); + if(diagram_points) + g_free(diagram_points); return; + } + gui_internal_menu_render(this); first=1; diagram_point=diagram_points; while (diagram_point) { @@ -571,38 +619,42 @@ gui_internal_cmd2_route_height_profile(struct gui_priv *this, char *function, st coord_rect_extend(&dbbox, &diagram_point->c); diagram_point=diagram_point->next; } - dbg(lvl_info,"%d %d %d %d\n", dbbox.lu.x, dbbox.lu.y, dbbox.rl.x, dbbox.rl.y); + dbg(lvl_debug,"%d %d %d %d\n", dbbox.lu.x, dbbox.lu.y, dbbox.rl.x, dbbox.rl.y); if (dbbox.rl.x > dbbox.lu.x && dbbox.lu.x*100/(dbbox.rl.x-dbbox.lu.x) <= 25) dbbox.lu.x=0; if (dbbox.lu.y > dbbox.rl.y && dbbox.rl.y*100/(dbbox.lu.y-dbbox.rl.y) <= 25) dbbox.rl.y=0; - dbg(lvl_info,"%d,%d %dx%d\n", box->p.x, box->p.y, box->w, box->h); + dbg(lvl_debug,"%d,%d %dx%d\n", box->p.x, box->p.y, box->w, box->h); x=dbbox.lu.x; first=1; - for (;;) { - struct point p[2]; - min=NULL; - diagram_point=diagram_points; - while (diagram_point) { - if (diagram_point->c.x >= x && (!min || min->c.x > diagram_point->c.x)) - min=diagram_point; - diagram_point=diagram_point->next; + if (diagram_points_count > 1 && dbbox.rl.x != dbbox.lu.x && dbbox.lu.y != dbbox.rl.y){ + for (;;) { + min=NULL; + diagram_point=diagram_points; + while (diagram_point) { + if (diagram_point->c.x >= x && (!min || min->c.x > diagram_point->c.x)) + min=diagram_point; + diagram_point=diagram_point->next; + } + if (! min) + break; + p[1].x=(min->c.x-dbbox.lu.x)*(box->w-10)/(dbbox.rl.x-dbbox.lu.x)+box->p.x+5; + p[1].y=(box->h)-5-(min->c.y-dbbox.rl.y)*(box->h-10)/(dbbox.lu.y-dbbox.rl.y)+box->p.y; + dbg(lvl_debug,"%d,%d=%d,%d\n",min->c.x, min->c.y, p[1].x,p[1].y); + graphics_draw_circle(this->gra, this->foreground, &p[1], 2); + if (first) + first=0; + else + graphics_draw_lines(this->gra, this->foreground, p, 2); + p[0]=p[1]; + x=min->c.x+1; } - if (! min) - break; - p[1].x=(min->c.x-dbbox.lu.x)*(box->w-10)/(dbbox.rl.x-dbbox.lu.x)+box->p.x+5; - p[1].y=(min->c.y-dbbox.rl.y)*(box->h-10)/(dbbox.lu.y-dbbox.rl.y)+box->p.y+5; - dbg(lvl_info,"%d,%d=%d,%d\n",min->c.x, min->c.y, p[1].x,p[1].y); - graphics_draw_circle(this->gra, this->foreground, &p[1], 2); - if (first) - first=0; - else - graphics_draw_lines(this->gra, this->foreground, p, 2); - p[0]=p[1]; - x=min->c.x+1; } - - + while (diagram_points){ + diagram_point=diagram_points; + diagram_points=diagram_points->next; + g_free(diagram_point); + } } static void @@ -860,6 +912,8 @@ gui_internal_cmd_log(struct gui_priv *this) gui_internal_widget_append(w, wl); if (this->keyboard) gui_internal_widget_append(w, gui_internal_keyboard(this, VKBD_FLAG_2 | gui_internal_keyboard_init_mode(getenv("LANG")))); + else + gui_internal_keyboard_show_native(this, w, VKBD_FLAG_2 | gui_internal_keyboard_init_mode(getenv("LANG")), getenv("LANG")); gui_internal_menu_render(this); gui_internal_leave(this); } @@ -1075,7 +1129,6 @@ error: return; } - static void gui_internal_cmd_img(struct gui_priv * this, char *function, struct attr **in, struct attr ***out, int *valid) { diff --git a/navit/gui/internal/gui_internal_html.c b/navit/gui/internal/gui_internal_html.c index 8350dbdcc..9b42fbdec 100644 --- a/navit/gui/internal/gui_internal_html.c +++ b/navit/gui/internal/gui_internal_html.c @@ -491,9 +491,12 @@ gui_internal_html_menu(struct gui_priv *this, const char *document, char *anchor callback_list_call_attr_2(this->cbl,attr_gui,anchor,&doc); gui_internal_html_parse_text(this, doc); g_free(doc); - if (this->keyboard_required && this->keyboard) { + if (this->keyboard_required) { this->html_container->flags=gravity_center|orientation_vertical|flags_expand|flags_fill; - gui_internal_widget_append(this->html_container, gui_internal_keyboard(this, VKBD_FLAG_2 | gui_internal_keyboard_init_mode(getenv("LANG")))); + if (this->keyboard) + gui_internal_widget_append(this->html_container, gui_internal_keyboard(this, VKBD_FLAG_2 | gui_internal_keyboard_init_mode(getenv("LANG")))); + else + gui_internal_keyboard_show_native(this, this->html_container, VKBD_FLAG_2 | gui_internal_keyboard_init_mode(getenv("LANG")), getenv("LANG")); } gui_internal_menu_render(this); graphics_draw_mode(this->gra, draw_mode_end); diff --git a/navit/gui/internal/gui_internal_keyboard.c b/navit/gui/internal/gui_internal_keyboard.c index ea71eb593..3dc6ae556 100644 --- a/navit/gui/internal/gui_internal_keyboard.c +++ b/navit/gui/internal/gui_internal_keyboard.c @@ -12,39 +12,61 @@ #include "gui_internal_menu.h" #include "gui_internal_keyboard.h" +/** + * @brief Switch keyboard mode to uppercase if it's in lowercase mode and {@code VKBD_MODE_2} is set. + * + * Called when there's no input left in the input field. + * + * @param this The internal GUI instance + */ void gui_internal_keyboard_to_upper_case(struct gui_priv *this) { struct menu_data *md; + + if (!this->keyboard) + return; + md=gui_internal_menu_data(this); - // Switch to lowercase after the first key is pressed - if (md->keyboard_mode == 10) // Latin - gui_internal_keyboard_do(this, md->keyboard, 2); - if (md->keyboard_mode == 34) // Umlaut - gui_internal_keyboard_do(this, md->keyboard, 26); - if (md->keyboard_mode == 50) // Russian/Ukrainian/Belorussian - gui_internal_keyboard_do(this, md->keyboard, 42); + + if (md->keyboard_mode == (VKBD_LATIN_LOWER | VKBD_FLAG_2)) + gui_internal_keyboard_do(this, md->keyboard, VKBD_LATIN_UPPER | VKBD_FLAG_2); + if (md->keyboard_mode == (VKBD_UMLAUT_LOWER | VKBD_FLAG_2)) + gui_internal_keyboard_do(this, md->keyboard, VKBD_UMLAUT_UPPER | VKBD_FLAG_2); + if (md->keyboard_mode == (VKBD_CYRILLIC_LOWER | VKBD_FLAG_2)) + gui_internal_keyboard_do(this, md->keyboard, VKBD_CYRILLIC_UPPER | VKBD_FLAG_2); } +/** + * @brief Switch keyboard mode to lowercase if it's in uppercase mode and {@code VKBD_MODE_2} is set. + * + * Called on each alphanumeric input. + * + * @param this The internal GUI instance + */ void gui_internal_keyboard_to_lower_case(struct gui_priv *this) { struct menu_data *md; + + if (!this->keyboard) + return; + md=gui_internal_menu_data(this); - // Switch to lowercase after the first key is pressed - if (md->keyboard_mode == (VKBD_LATIN_UPPER | VKBD_FLAG_2)) // Latin + + if (md->keyboard_mode == (VKBD_LATIN_UPPER | VKBD_FLAG_2)) gui_internal_keyboard_do(this, md->keyboard, VKBD_LATIN_LOWER | VKBD_FLAG_2); - if (md->keyboard_mode == (VKBD_UMLAUT_UPPER | VKBD_FLAG_2)) // Umlaut + if (md->keyboard_mode == (VKBD_UMLAUT_UPPER | VKBD_FLAG_2)) gui_internal_keyboard_do(this, md->keyboard, VKBD_UMLAUT_LOWER | VKBD_FLAG_2); - if (md->keyboard_mode == (VKBD_CYRILLIC_UPPER | VKBD_FLAG_2)) // Russian/Ukrainian/Belorussian + if (md->keyboard_mode == (VKBD_CYRILLIC_UPPER | VKBD_FLAG_2)) gui_internal_keyboard_do(this, md->keyboard, VKBD_CYRILLIC_LOWER | VKBD_FLAG_2); } /** * @brief Processes a key press on the internal GUI keyboard * - * If the keyboard is currently in uppercase mode and {@code VKBD_MODE_2} is set, it is then switched to - * the corresponding lowercase mode. + * If the keyboard is currently in uppercase mode and {@code VKBD_MODE_2} is set, it is tswitched to + * the corresponding lowercase mode in {@code gui_internal_keypress_do}. * * @param this The internal GUI instance * @param wm @@ -101,7 +123,7 @@ struct gui_internal_keyb_mode { /*16: VKBD_NUMERIC */ {"123", 2, VKBD_LATIN_UPPER, VKBD_UMLAUT_UPPER}, /*24: VKBD_UMLAUT_UPPER */ {"ÄÖÜ", 2, VKBD_UMLAUT_LOWER, VKBD_LATIN_UPPER}, /*32: VKBD_UMLAUT_LOWER */ {"äöü", 2, VKBD_UMLAUT_UPPER, VKBD_LATIN_LOWER}, - /*40: VKBD_CYRILLIC_UPPER*/ {"АБВ", 2, VKBD_CYRILLIC_UPPER, VKBD_LATIN_UPPER}, + /*40: VKBD_CYRILLIC_UPPER*/ {"АБВ", 2, VKBD_CYRILLIC_LOWER, VKBD_LATIN_UPPER}, /*48: VKBD_CYRILLIC_LOWER*/ {"абв", 2, VKBD_CYRILLIC_UPPER, VKBD_LATIN_LOWER}, /*56: VKBD_DEGREE */ {"DEG", 2, VKBD_FLAG_2, VKBD_FLAG_2} }; @@ -435,3 +457,100 @@ gui_internal_keyboard_init_mode(char *lang) g_free(lang); return ret; } + + +/** + * @brief Hides the platform's native on-screen keyboard or other input method + * + * This function is called as the {@code wfree} method of the placeholder widget for the platform's + * native on-screen keyboard. It is a wrapper around the corresponding method of the graphics plugin, + * which takes care of all platform-specific actions to hide the on-screen input method it previously + * displayed. + * + * A call to this function indicates that Navit no longer needs the input method and is about to destroy + * its placeholder widget. Navit will subsequently reclaim any screen real estate it may have previously + * reserved for the input method. + * + * This function will free the {@code struct graphics_keyboard} pointed to by {@code w->data} + * + * @param this The internal GUI instance + * @param w The placeholder widget + */ +void gui_internal_keyboard_hide_native(struct gui_priv *this_, struct widget *w) { + struct graphics_keyboard *kbd = (struct graphics_keyboard *) w->data; + + if (kbd) { + graphics_hide_native_keyboard(this_->gra, kbd); + g_free(kbd->lang); + g_free(kbd->gui_priv); + } else + dbg(lvl_warning, "no graphics_keyboard found, cleanup failed\n"); + g_free(w); +} + + +/** + * @brief Shows the platform's native on-screen keyboard or other input method + * + * This method is a wrapper around the corresponding method of the graphics plugin, which takes care of + * all platform-specific details. In particular, it is up to the graphics plugin to determine how to + * handle the request: it may show its on-screen keyboard or another input method (such as stroke + * recognition). It may choose to simply ignore the request, which will typically occur when a hardware + * keyboard (or other hardware input) is available. + * + * The platform's native input method may obstruct parts of Navit's UI. To prevent parts of the UI from + * becoming unreachable, this method will insert an empty box widget in the appropriate size at the + * appropriate position, provided the graphics plugin reports the correct values. Otherwise a zero-size + * widget is inserted. If the graphics driver decides not to display an on-screen input method, no + * widget will be created and the return value will be {@code NULL}. + * + * The widget's {@code wfree} function, to be called when the widget is destroyed, will be used to hide + * the platform keyboard when it is no longer needed. + * + * @param this The internal GUI instance + * @param w The parent of the widget requiring text input + * @param mode The requested keyboard mode + * @param lang The language for text input, used to select a keyboard layout + * + * @return The placeholder widget for the on-screen keyboard, may be {@code NULL} + */ +struct widget * gui_internal_keyboard_show_native(struct gui_priv *this, struct widget *w, int mode, char *lang) { + struct widget *ret = NULL; + struct menu_data *md = gui_internal_menu_data(this); + struct graphics_keyboard *kbd = g_new0(struct graphics_keyboard, 1); + int res; + + kbd->mode = mode; + if (lang) + kbd->lang = g_strdup(lang); + res = graphics_show_native_keyboard(this->gra, kbd); + + switch(res) { + case -1: + dbg(lvl_error, "graphics has no show_native_keyboard method, cannot display keyboard\n"); + /* no break */ + case 0: + g_free(kbd); + return NULL; + } + + ret = gui_internal_box_new(this, gravity_center|orientation_horizontal_vertical|flags_fill); + md->keyboard = ret; + md->keyboard_mode=mode; + ret->wfree = gui_internal_keyboard_hide_native; + if (kbd->h < 0) { + ret->h = w->h; + ret->hmin = w->hmin; + } else + ret->h = kbd->h; + if (kbd->w < 0) { + ret->w = w->w; + ret->wmin = w->wmin; + } else + ret->w = kbd->w; + dbg(lvl_error, "ret->w=%d, ret->h=%d\n", ret->w, ret->h); + ret->data = (void *) kbd; + gui_internal_widget_append(w, ret); + dbg(lvl_error, "return\n"); + return ret; +} diff --git a/navit/gui/internal/gui_internal_keyboard.h b/navit/gui/internal/gui_internal_keyboard.h index 336ba2c01..9b9039224 100644 --- a/navit/gui/internal/gui_internal_keyboard.h +++ b/navit/gui/internal/gui_internal_keyboard.h @@ -24,6 +24,7 @@ struct gui_priv; struct widget; struct widget *gui_internal_keyboard_do(struct gui_priv *this, struct widget *wkbdb, int mode); struct widget *gui_internal_keyboard(struct gui_priv *this, int mode); +struct widget *gui_internal_keyboard_show_native(struct gui_priv *this, struct widget *w, int mode, char *lang); int gui_internal_keyboard_init_mode(char *lang); void gui_internal_keyboard_to_upper_case(struct gui_priv *this); void gui_internal_keyboard_to_lower_case(struct gui_priv *this); diff --git a/navit/gui/internal/gui_internal_menu.c b/navit/gui/internal/gui_internal_menu.c index 7769953b9..33def9983 100644 --- a/navit/gui/internal/gui_internal_menu.c +++ b/navit/gui/internal/gui_internal_menu.c @@ -91,10 +91,31 @@ gui_internal_prune_menu_count(struct gui_priv *this, int count, int render) } } + +/** + * @brief Initializes a GUI screen + * + * This method initializes the internal GUI's screen on which all other elements (such as HTML menus, + * dialogs or others) are displayed. + * + * It sets up a view hierarchy, which includes a title bar and a client area to hold widgets defined by + * the caller. + * + * @param this The GUI instance + * @param label The label to display in the top bar + * + * @return The container for caller-defined widgets + */ struct widget * gui_internal_menu(struct gui_priv *this, const char *label) { struct widget *menu,*w,*w1,*topbox; + struct padding *padding = NULL; + + if (this->gra) { + padding = graphics_get_data(this->gra, "padding"); + } else + dbg(lvl_warning, "cannot get padding: this->gra is NULL\n"); gui_internal_search_idle_end(this); topbox=gui_internal_box_new_with_label(this, 0, label); @@ -102,8 +123,18 @@ gui_internal_menu(struct gui_priv *this, const char *label) topbox->h=this->root.h; gui_internal_widget_append(&this->root, topbox); menu=gui_internal_box_new(this, gravity_left_center|orientation_vertical); - menu->w=this->root.w; - menu->h=this->root.h; + + if (padding) { + menu->p.x = padding->left; + menu->p.y = padding->top; + menu->w = topbox->w - padding->left - padding->right; + menu->h = topbox->h - padding->top - padding->bottom; + } else { + menu->p.x = 0; + menu->p.y = 0; + menu->w = topbox->w; + menu->h = topbox->h; + } menu->background=this->background; gui_internal_apply_config(this); topbox->menu_data=g_new0(struct menu_data, 1); @@ -134,8 +165,17 @@ gui_internal_menu(struct gui_priv *this, const char *label) } if (this->flags & 192) { menu=gui_internal_box_new(this, gravity_left_center|orientation_vertical); - menu->w=this->root.w; - menu->h=this->root.h; + if (padding) { + menu->p.x = padding->left; + menu->p.y = padding->top; + menu->w = topbox->w - padding->left - padding->right; + menu->h = topbox->h - padding->top - padding->bottom; + } else { + menu->p.x = 0; + menu->p.y = 0; + menu->w = topbox->w; + menu->h = topbox->h; + } w1=gui_internal_time_help(this); gui_internal_widget_append(menu, w1); w1=gui_internal_box_new(this, gravity_center|orientation_horizontal_vertical|flags_expand|flags_fill); @@ -147,8 +187,17 @@ gui_internal_menu(struct gui_priv *this, const char *label) gui_internal_widget_reset_pack(this, topbox); topbox->w=this->root.w; topbox->h=this->root.h; - menu->w=this->root.w; - menu->h=this->root.h; + if (padding) { + menu->p.x = padding->left; + menu->p.y = padding->top; + menu->w = topbox->w - padding->left - padding->right; + menu->h = topbox->h - padding->top - padding->bottom; + } else { + menu->p.x = 0; + menu->p.y = 0; + menu->w = topbox->w; + menu->h = topbox->h; + } return w; } diff --git a/navit/gui/internal/gui_internal_poi.c b/navit/gui/internal/gui_internal_poi.c index c3eed5e60..d4ffea8b3 100644 --- a/navit/gui/internal/gui_internal_poi.c +++ b/navit/gui/internal/gui_internal_poi.c @@ -533,6 +533,8 @@ gui_internal_cmd_pois_filter(struct gui_priv *this, struct widget *wm, void *dat if (this->keyboard) gui_internal_widget_append(w, gui_internal_keyboard(this, keyboard_mode)); + else + gui_internal_keyboard_show_native(this, w, keyboard_mode, getenv("LANG")); gui_internal_menu_render(this); diff --git a/navit/gui/internal/gui_internal_search.c b/navit/gui/internal/gui_internal_search.c index a0d6a3b2e..e5e137e07 100644 --- a/navit/gui/internal/gui_internal_search.c +++ b/navit/gui/internal/gui_internal_search.c @@ -212,6 +212,9 @@ gui_internal_highlight_possible_keys(struct gui_priv *this, char *possible_keys) { struct menu_data *md; + if (!this->keyboard) + return; + md=gui_internal_menu_data(this); if (md && md->keyboard && !(this->flags & 2048)) { GList *lk=md->keyboard->children; @@ -225,9 +228,9 @@ gui_internal_highlight_possible_keys(struct gui_priv *this, char *possible_keys) if (child_->data && strcmp("\b", child_->data)) { // FIXME don't disable special keys if ( (strlen(possible_keys) == 0) || (g_strrstr(possible_keys, child_->data)!=NULL ) ) { - child_->state|= STATE_HIGHLIGHTED|STATE_VISIBLE|STATE_SENSITIVE|STATE_CLEAR ; + child_->state|= STATE_HIGHLIGHTED|STATE_SENSITIVE|STATE_CLEAR ; } else { - child_->state&= ~(STATE_HIGHLIGHTED|STATE_VISIBLE|STATE_SELECTED) ; + child_->state&= ~STATE_HIGHLIGHTED; } gui_internal_widget_render(this,child_); } @@ -431,13 +434,9 @@ gui_internal_search_changed(struct gui_priv *this, struct widget *wm, void *data search_attr.type=attr_house_number; search_attr.u.str=wm->text; search_list_search(this->sl, &search_attr, 1); - // Text is not necessarily entered via the on-screen keyboard, - // but we now switch it to lower case anyway. - gui_internal_keyboard_to_lower_case(this); gui_internal_search_idle_start(this, wm->name, search_list, param); } else { // If not enough content is entered, we highlight all keys. - gui_internal_keyboard_to_upper_case(this); gui_internal_highlight_possible_keys(this, ""); } l=g_list_last(this->root.children); @@ -570,6 +569,8 @@ gui_internal_search(struct gui_priv *this, const char *what, const char *type, i wk->name=g_strdup(type); if (this->keyboard) gui_internal_widget_append(w, gui_internal_keyboard(this, keyboard_mode)); + else + gui_internal_keyboard_show_native(this, w, keyboard_mode, getenv("LANG")); gui_internal_menu_render(this); } diff --git a/navit/gui/internal/gui_internal_widget.c b/navit/gui/internal/gui_internal_widget.c index e78abb3dd..1dd28837f 100644 --- a/navit/gui/internal/gui_internal_widget.c +++ b/navit/gui/internal/gui_internal_widget.c @@ -321,18 +321,18 @@ static void gui_internal_box_render(struct gui_priv *this, struct widget *w) gui_internal_background_render(this, w); if (w->foreground && w->border) { - struct point pnt[5]; - pnt[0]=w->p; - pnt[1].x=pnt[0].x+w->w; - pnt[1].y=pnt[0].y; - pnt[2].x=pnt[0].x+w->w; - pnt[2].y=pnt[0].y+w->h; - pnt[3].x=pnt[0].x; - pnt[3].y=pnt[0].y+w->h; - pnt[4]=pnt[0]; - graphics_gc_set_linewidth(w->foreground, w->border ? w->border : 1); - graphics_draw_lines(this->gra, w->foreground, pnt, 5); - graphics_gc_set_linewidth(w->foreground, 1); + struct point pnt[5]; + pnt[0]=w->p; + pnt[1].x=pnt[0].x+w->w; + pnt[1].y=pnt[0].y; + pnt[2].x=pnt[0].x+w->w; + pnt[2].y=pnt[0].y+w->h; + pnt[3].x=pnt[0].x; + pnt[3].y=pnt[0].y+w->h; + pnt[4]=pnt[0]; + graphics_gc_set_linewidth(w->foreground, w->border ? w->border : 1); + graphics_draw_lines(this->gra, w->foreground, pnt, 5); + graphics_gc_set_linewidth(w->foreground, 1); } l=w->children; @@ -1226,7 +1226,7 @@ gui_internal_table_render(struct gui_priv * this, struct widget * w) GList * current_desc=NULL; struct table_data * table_data = (struct table_data*)w->data; int drawing_space_left=1; - int is_first_page=1; + int is_first_page; struct table_column_desc * dim=NULL; dbg_assert(table_data); @@ -1238,16 +1238,17 @@ gui_internal_table_render(struct gui_priv * this, struct widget * w) /* * Skip rows that are on previous pages. */ - cur_row = w->children; if(table_data->top_row && table_data->top_row != w->children && !table_data->scroll_buttons.button_box_hide) { cur_row = table_data->top_row; is_first_page=0; } else { + cur_row = w->children; table_data->top_row=NULL; + is_first_page=1; } - /* First, let's deactivate all columns that are in rows which are *before* + /* First, let's mark all columns as off-screen that are in rows which are *before* * our current page. * */ GList *row = w->children; @@ -1263,7 +1264,7 @@ gui_internal_table_render(struct gui_priv * this, struct widget * w) cur_column=g_list_next(cur_column)) { struct widget * cur_widget = (struct widget*) cur_column->data; - cur_widget->state &= ~STATE_SENSITIVE; + cur_widget->state |= STATE_OFFSCREEN; } row = g_list_next(row); } @@ -1297,8 +1298,6 @@ gui_internal_table_render(struct gui_priv * this, struct widget * w) cur_column=g_list_next(cur_column)) { struct widget * cur_widget = (struct widget*) cur_column->data; - dim = (struct table_column_desc*)current_desc->data; - if (drawing_space_left) { cur_widget->p.x=x; cur_widget->w=dim->width; @@ -1309,7 +1308,7 @@ gui_internal_table_render(struct gui_priv * this, struct widget * w) /* We pack the widget before rendering to ensure that the x and y * coordinates get pushed down. */ - cur_widget->state |= STATE_SENSITIVE; + cur_widget->state &= ~STATE_OFFSCREEN; gui_internal_widget_pack(this,cur_widget); gui_internal_widget_render(this,cur_widget); @@ -1318,8 +1317,8 @@ gui_internal_table_render(struct gui_priv * this, struct widget * w) max_height = dim->height; } } else { - /* Deactivate contents that we don't have space for. */ - cur_widget->state &= ~STATE_SENSITIVE; + /* Mark contents that we don't have space for. */ + cur_widget->state |= STATE_OFFSCREEN; } } |
