diff options
author | greg <code@gregorkopf.de> | 2015-07-15 21:36:45 +0200 |
---|---|---|
committer | Sebastian Leske <sebastian.leske@sleske.name> | 2015-12-17 23:56:32 +0100 |
commit | 8bdcd53d6b0b358d0a66fcb188e34ec2e974a66d (patch) | |
tree | 6ad49df3968bc73eeb841178e6bb534831bc559e /navit/gui/internal | |
parent | e0d189992ba2ab742004b62146c8eea3c4c6d558 (diff) | |
download | navit-8bdcd53d6b0b358d0a66fcb188e34ec2e974a66d.tar.gz |
Add:gui_internal:Navigating menus with rotary encoder
Allow navigating the menus of the internal GUI with only PgUp/PgDown
keys, instead of using arrow and Enter keys (which remains supported).
This allows to operate the menus with a rotary encoder, if its two
actions are mapped to PgUp/PgDown.
Diffstat (limited to 'navit/gui/internal')
-rw-r--r-- | navit/gui/internal/gui_internal.c | 113 | ||||
-rw-r--r-- | navit/gui/internal/gui_internal_widget.c | 96 |
2 files changed, 164 insertions, 45 deletions
diff --git a/navit/gui/internal/gui_internal.c b/navit/gui/internal/gui_internal.c index 2fd734f8f..a043b13b4 100644 --- a/navit/gui/internal/gui_internal.c +++ b/navit/gui/internal/gui_internal.c @@ -1621,7 +1621,16 @@ gui_internal_cmd_bookmarks(struct gui_priv *this, struct widget *wm, void *data) static void -gui_internal_keynav_highlight_next(struct gui_priv *this, int dx, int dy); +gui_internal_keynav_highlight_next(struct gui_priv *this, int dx, int dy, int rotary); + +int +gui_internal_keynav_find_next(struct widget *wi, struct widget *cur, struct widget **result); + +int +gui_internal_keynav_find_prev(struct widget *wi, struct widget *cur, struct widget **result, struct widget** last); + +struct widget* +gui_internal_keynav_find_next_sensitive_child(struct widget *wi); void gui_internal_keypress_do(struct gui_priv *this, char *key) @@ -2685,6 +2694,71 @@ gui_internal_keynav_point(struct widget *w, int dx, int dy, struct point *p) p->y=w->p.y+w->h; } +struct widget* +gui_internal_keynav_find_next_sensitive_child(struct widget *wi) { + GList *l=wi->children; + if (wi && wi->state & STATE_SENSITIVE) + return wi; + while (l) { + struct widget* tmp = gui_internal_keynav_find_next_sensitive_child(l->data); + if (tmp) + return tmp; + l=g_list_next(l); + } + return NULL; +} + +int +gui_internal_keynav_find_next(struct widget *wi, struct widget *cur, struct widget **result) { + GList *l=wi->children; + if (wi == cur) + return 1; + while (l) { + struct widget *child=l->data; + l=g_list_next(l); + if (gui_internal_keynav_find_next(child, cur, result)) { + while (l) { + struct widget *new = gui_internal_keynav_find_next_sensitive_child(l->data); + if (new) { + *result = new; + /* Found one! */ + return 0; + } + l=g_list_next(l); + } + /* Try parent */ + return 1; + } + } + return 0; +} + +int +gui_internal_keynav_find_prev(struct widget *wi, struct widget *cur, struct widget **result, struct widget** last) { + GList *l=wi->children; + struct widget* my_last = NULL; + if (last == NULL) + last = &my_last; + if (wi == cur) + return 1; + while (l) { + struct widget *child=l->data; + if (gui_internal_keynav_find_prev(child, cur, result, last)) { + *result = *last; + if (*last) + /* Done. */ + return 0; + else + /* Try parent. */ + return 1; + } + if (child->state & STATE_SENSITIVE) + *last = child; + l=g_list_next(l); + } + return 0; +} + static void gui_internal_keynav_find_closest(struct widget *wi, struct point *p, int dx, int dy, int *distance, struct widget **result) { @@ -2728,13 +2802,16 @@ gui_internal_keynav_find_closest(struct widget *wi, struct point *p, int dx, int } static void -gui_internal_keynav_highlight_next(struct gui_priv *this, int dx, int dy) +gui_internal_keynav_highlight_next(struct gui_priv *this, int dx, int dy, int rotary) { struct widget *result,*menu=g_list_last(this->root.children)->data; + struct widget *cur = NULL; struct point p; int distance; - if (this->highlighted && this->highlighted_menu == g_list_last(this->root.children)->data) + if (this->highlighted && this->highlighted_menu == g_list_last(this->root.children)->data) { gui_internal_keynav_point(this->highlighted, dx, dy, &p); + cur = this->highlighted; + } else { p.x=0; p.y=0; @@ -2744,17 +2821,27 @@ gui_internal_keynav_highlight_next(struct gui_priv *this, int dx, int dy) if (result) { gui_internal_keynav_point(result, dx, dy, &p); dbg(lvl_debug,"result origin=%p p=%d,%d\n", result, p.x, p.y); + cur = result; } } result=NULL; distance=INT_MAX; - gui_internal_keynav_find_closest(menu, &p, dx, dy, &distance, &result); + if (rotary && dx > 0) + gui_internal_keynav_find_next(menu, cur, &result); + else if (rotary && dx < 0) + gui_internal_keynav_find_prev(menu, cur, &result, NULL); + else + gui_internal_keynav_find_closest(menu, &p, dx, dy, &distance, &result); dbg(lvl_debug,"result=%p\n", result); if (! result) { - if (dx < 0) + if (dx < 0) { p.x=this->root.w; - if (dx > 0) + if (rotary) p.y = this->root.h; + } + if (dx > 0) { p.x=0; + if (rotary) p.y = 0; + } if (dy < 0) p.y=this->root.h; if (dy > 0) @@ -2818,17 +2905,23 @@ static void gui_internal_keypress(void *data, char *key) } graphics_draw_mode(this->gra, draw_mode_begin); switch (*key) { + case NAVIT_KEY_PAGE_DOWN: + gui_internal_keynav_highlight_next(this,1,0,1); + break; + case NAVIT_KEY_PAGE_UP: + gui_internal_keynav_highlight_next(this,-1,0,1); + break; case NAVIT_KEY_LEFT: - gui_internal_keynav_highlight_next(this,-1,0); + gui_internal_keynav_highlight_next(this,-1,0,0); break; case NAVIT_KEY_RIGHT: - gui_internal_keynav_highlight_next(this,1,0); + gui_internal_keynav_highlight_next(this,1,0,0); break; case NAVIT_KEY_UP: - gui_internal_keynav_highlight_next(this,0,-1); + gui_internal_keynav_highlight_next(this,0,-1,0); break; case NAVIT_KEY_DOWN: - gui_internal_keynav_highlight_next(this,0,1); + gui_internal_keynav_highlight_next(this,0,1,0); break; case NAVIT_KEY_BACK: if (g_list_length(this->root.children) > 1) diff --git a/navit/gui/internal/gui_internal_widget.c b/navit/gui/internal/gui_internal_widget.c index 7f22f6e24..ab4c51201 100644 --- a/navit/gui/internal/gui_internal_widget.c +++ b/navit/gui/internal/gui_internal_widget.c @@ -1261,6 +1261,28 @@ gui_internal_table_render(struct gui_priv * this, struct widget * w) } else { table_data->top_row=NULL; } + + /* First, let's deactivate all columns that are in rows which are *before* + * our current page. + * */ + GList *row = w->children; + while (row != cur_row) { + struct widget * cur_row_widget = (struct widget*)row->data; + GList * cur_column=NULL; + if(cur_row_widget == table_data->scroll_buttons.button_box) + { + row = g_list_next(row); + continue; + } + for(cur_column = cur_row_widget->children; cur_column; + cur_column=g_list_next(cur_column)) + { + struct widget * cur_widget = (struct widget*) cur_column->data; + cur_widget->state &= ~STATE_SENSITIVE; + } + row = g_list_next(row); + } + /* * Loop through each row. Drawing each cell with the proper sizes, * at the proper positions. @@ -1273,7 +1295,7 @@ gui_internal_table_render(struct gui_priv * this, struct widget * w) current_desc = column_desc; cur_row_widget = (struct widget*)cur_row->data; x =w->p.x+this->spacing; - if(cur_row_widget == table_data->scroll_buttons.button_box ) + if(cur_row_widget == table_data->scroll_buttons.button_box) { continue; } @@ -1288,7 +1310,6 @@ gui_internal_table_render(struct gui_priv * this, struct widget * w) * No more drawing space left. */ is_skipped=1; - break; } for(cur_column = cur_row_widget->children; cur_column; cur_column=g_list_next(cur_column)) @@ -1296,35 +1317,48 @@ gui_internal_table_render(struct gui_priv * this, struct widget * w) struct widget * cur_widget = (struct widget*) cur_column->data; dim = (struct table_column_desc*)current_desc->data; - cur_widget->p.x=x; - cur_widget->w=dim->width; - cur_widget->p.y=y; - cur_widget->h=dim->height; - x=x+cur_widget->w; - max_height = dim->height; - /* We pack the widget before rendering to ensure that the x and y - * coordinates get pushed down. - */ - gui_internal_widget_pack(this,cur_widget); - gui_internal_widget_render(this,cur_widget); - - if(dim->height > max_height) - { + if (!is_skipped) { + cur_widget->p.x=x; + cur_widget->w=dim->width; + cur_widget->p.y=y; + cur_widget->h=dim->height; + x=x+cur_widget->w; max_height = dim->height; + /* We pack the widget before rendering to ensure that the x and y + * coordinates get pushed down. + */ + cur_widget->state |= STATE_SENSITIVE; + gui_internal_widget_pack(this,cur_widget); + gui_internal_widget_render(this,cur_widget); + + if(dim->height > max_height) + { + max_height = dim->height; + } + } else { + /* Deactivate contents that we don't have space for. */ + cur_widget->state &= ~STATE_SENSITIVE; } } - - /* Row object should have its coordinates in actual - * state to be able to pass mouse clicks to Column objects - */ - cur_row_widget->p.x=w->p.x; - cur_row_widget->w=w->w; - cur_row_widget->p.y=y; - cur_row_widget->h=max_height; - y = y + max_height; - table_data->bottom_row=cur_row; - current_desc = g_list_next(current_desc); + + if (!is_skipped) { + /* Row object should have its coordinates in actual + * state to be able to pass mouse clicks to Column objects + */ + cur_row_widget->p.x=w->p.x; + cur_row_widget->w=w->w; + cur_row_widget->p.y=y; + cur_row_widget->h=max_height; + y = y + max_height; + table_data->bottom_row=cur_row; + current_desc = g_list_next(current_desc); + } } + + /* By default, hide all scroll buttons. */ + table_data->scroll_buttons.next_button->state&= ~STATE_SENSITIVE; + table_data->scroll_buttons.prev_button->state&= ~STATE_SENSITIVE; + if(table_data->scroll_buttons.button_box && (is_skipped || !is_first_page) && !table_data->scroll_buttons.button_box_hide ) { table_data->scroll_buttons.button_box->p.y =w->p.y+w->h-table_data->scroll_buttons.button_box->h - @@ -1350,19 +1384,11 @@ gui_internal_table_render(struct gui_priv * this, struct widget * w) { table_data->scroll_buttons.next_button->state|= STATE_SENSITIVE; } - else - { - table_data->scroll_buttons.next_button->state&= ~STATE_SENSITIVE; - } if(table_data->top_row != w->children) { table_data->scroll_buttons.prev_button->state|= STATE_SENSITIVE; } - else - { - table_data->scroll_buttons.prev_button->state&= ~STATE_SENSITIVE; - } gui_internal_widget_render(this,table_data->scroll_buttons.button_box); } |