summaryrefslogtreecommitdiff
path: root/navit/gui/internal
diff options
context:
space:
mode:
authorgreg <code@gregorkopf.de>2015-07-15 21:36:45 +0200
committerSebastian Leske <sebastian.leske@sleske.name>2015-12-17 23:56:32 +0100
commit8bdcd53d6b0b358d0a66fcb188e34ec2e974a66d (patch)
tree6ad49df3968bc73eeb841178e6bb534831bc559e /navit/gui/internal
parente0d189992ba2ab742004b62146c8eea3c4c6d558 (diff)
downloadnavit-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.c113
-rw-r--r--navit/gui/internal/gui_internal_widget.c96
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);
}