diff options
Diffstat (limited to 'apps/gui/bitmap/list.c')
-rw-r--r-- | apps/gui/bitmap/list.c | 57 |
1 files changed, 31 insertions, 26 deletions
diff --git a/apps/gui/bitmap/list.c b/apps/gui/bitmap/list.c index db8e0504d7..ff0f5a29c1 100644 --- a/apps/gui/bitmap/list.c +++ b/apps/gui/bitmap/list.c | |||
@@ -50,7 +50,6 @@ | |||
50 | static struct viewport list_text[NB_SCREENS], title_text[NB_SCREENS]; | 50 | static struct viewport list_text[NB_SCREENS], title_text[NB_SCREENS]; |
51 | 51 | ||
52 | #ifdef HAVE_TOUCHSCREEN | 52 | #ifdef HAVE_TOUCHSCREEN |
53 | static int y_offset; | ||
54 | static bool hide_selection; | 53 | static bool hide_selection; |
55 | #endif | 54 | #endif |
56 | 55 | ||
@@ -170,12 +169,9 @@ void list_draw(struct screen *display, struct gui_synclist *list) | |||
170 | end = start + nb_lines; | 169 | end = start + nb_lines; |
171 | 170 | ||
172 | #ifdef HAVE_TOUCHSCREEN | 171 | #ifdef HAVE_TOUCHSCREEN |
173 | if (list->selected_item == 0 || (list->nb_items < nb_lines)) | 172 | int draw_offset = list_start_item * linedes.height - list->y_pos; |
174 | y_offset = 0; /* reset in case it's a new list */ | ||
175 | |||
176 | int draw_offset = y_offset; | ||
177 | /* draw some extra items to not have empty lines at the top and bottom */ | 173 | /* draw some extra items to not have empty lines at the top and bottom */ |
178 | if (y_offset > 0) | 174 | if (draw_offset > 0) |
179 | { | 175 | { |
180 | /* make it negative for more consistent apparence when switching | 176 | /* make it negative for more consistent apparence when switching |
181 | * directions */ | 177 | * directions */ |
@@ -183,7 +179,7 @@ void list_draw(struct screen *display, struct gui_synclist *list) | |||
183 | if (start > 0) | 179 | if (start > 0) |
184 | start--; | 180 | start--; |
185 | } | 181 | } |
186 | else if (y_offset < 0) | 182 | else if (draw_offset < 0) |
187 | end++; | 183 | end++; |
188 | #else | 184 | #else |
189 | #define draw_offset 0 | 185 | #define draw_offset 0 |
@@ -367,7 +363,6 @@ static int scrollbar_scroll(struct gui_synclist * gui_list, int y) | |||
367 | if (nb_lines < gui_list->nb_items) | 363 | if (nb_lines < gui_list->nb_items) |
368 | { | 364 | { |
369 | /* scrollbar scrolling is still line based */ | 365 | /* scrollbar scrolling is still line based */ |
370 | y_offset = 0; | ||
371 | int scrollbar_size = nb_lines * gui_list->line_height[screen]; | 366 | int scrollbar_size = nb_lines * gui_list->line_height[screen]; |
372 | int actual_y = y - list_text[screen].y; | 367 | int actual_y = y - list_text[screen].y; |
373 | int new_selection = (actual_y * gui_list->nb_items) / scrollbar_size; | 368 | int new_selection = (actual_y * gui_list->nb_items) / scrollbar_size; |
@@ -379,6 +374,7 @@ static int scrollbar_scroll(struct gui_synclist * gui_list, int y) | |||
379 | start_item = gui_list->nb_items - nb_lines; | 374 | start_item = gui_list->nb_items - nb_lines; |
380 | 375 | ||
381 | gui_list->start_item[screen] = start_item; | 376 | gui_list->start_item[screen] = start_item; |
377 | gui_list->y_pos = start_item * gui_list->line_height[screen]; | ||
382 | 378 | ||
383 | return ACTION_REDRAW; | 379 | return ACTION_REDRAW; |
384 | } | 380 | } |
@@ -468,9 +464,11 @@ static void kinetic_force_stop(void) | |||
468 | 464 | ||
469 | /* helper for gui/list.c to cancel scrolling if a normal button event comes | 465 | /* helper for gui/list.c to cancel scrolling if a normal button event comes |
470 | * through dpad or keyboard or whatever */ | 466 | * through dpad or keyboard or whatever */ |
471 | void _gui_synclist_stop_kinetic_scrolling(void) | 467 | void _gui_synclist_stop_kinetic_scrolling(struct gui_synclist * gui_list) |
472 | { | 468 | { |
473 | y_offset = 0; | 469 | const enum screen_type screen = screens[SCREEN_MAIN].screen_type; |
470 | gui_list->y_pos = gui_list->start_item[screen] * gui_list->line_height[screen]; | ||
471 | |||
474 | if (scroll_mode == SCROLL_KINETIC) | 472 | if (scroll_mode == SCROLL_KINETIC) |
475 | kinetic_force_stop(); | 473 | kinetic_force_stop(); |
476 | scroll_mode = SCROLL_NONE; | 474 | scroll_mode = SCROLL_NONE; |
@@ -512,22 +510,25 @@ static bool swipe_scroll(struct gui_synclist * gui_list, int difference) | |||
512 | int new_start_item = -1; | 510 | int new_start_item = -1; |
513 | int line_diff = 0; | 511 | int line_diff = 0; |
514 | 512 | ||
515 | /* don't scroll at the edges of the list */ | 513 | /* Track whether we hit the end of the list for sake of kinetic scroll */ |
516 | if ((old_start == 0 && difference > 0) | 514 | bool hit_end = true; |
517 | || (old_start == (gui_list->nb_items - nb_lines) && difference < 0)) | ||
518 | { | ||
519 | y_offset = 0; | ||
520 | gui_list->start_item[screen] = old_start; | ||
521 | return scroll_mode != SCROLL_KINETIC; /* stop kinetic at the edges */ | ||
522 | } | ||
523 | 515 | ||
524 | /* add up y_offset over time and translate to lines | 516 | /* Move the y position and clamp it (funny things happen otherwise...) */ |
525 | * if scrolled enough */ | 517 | gui_list->y_pos -= difference; |
526 | y_offset += difference; | 518 | if(gui_list->y_pos < 0) |
527 | if (abs(y_offset) > line_height) | 519 | gui_list->y_pos = 0; |
520 | else if(gui_list->y_pos > (gui_list->nb_items - nb_lines) * line_height) | ||
521 | gui_list->y_pos = (gui_list->nb_items - nb_lines) * line_height; | ||
522 | else | ||
523 | hit_end = false; | ||
524 | |||
525 | /* Get the list y position. When pos_y differs by a line height or more, | ||
526 | * we need to scroll the list by adjusting the start item accordingly */ | ||
527 | int cur_y = gui_list->start_item[screen] * line_height; | ||
528 | int diff_y = cur_y - gui_list->y_pos; | ||
529 | if (abs(diff_y) >= line_height) | ||
528 | { | 530 | { |
529 | line_diff = y_offset/line_height; | 531 | line_diff = diff_y/line_height; |
530 | y_offset -= line_diff * line_height; | ||
531 | } | 532 | } |
532 | 533 | ||
533 | if(line_diff != 0) | 534 | if(line_diff != 0) |
@@ -548,7 +549,10 @@ static bool swipe_scroll(struct gui_synclist * gui_list, int difference) | |||
548 | gui_list->selected_item -= (gui_list->selected_item % gui_list->selected_size); | 549 | gui_list->selected_item -= (gui_list->selected_item % gui_list->selected_size); |
549 | } | 550 | } |
550 | 551 | ||
551 | return true; | 552 | if(hit_end) |
553 | return scroll_mode != SCROLL_KINETIC; | ||
554 | else | ||
555 | return true; | ||
552 | } | 556 | } |
553 | 557 | ||
554 | static int kinetic_callback(struct timeout *tmo) | 558 | static int kinetic_callback(struct timeout *tmo) |
@@ -729,7 +733,8 @@ unsigned gui_synclist_do_touchscreen(struct gui_synclist * list) | |||
729 | if(!skinlist_get_item(&screens[screen], list, adj_x, adj_y, &line)) | 733 | if(!skinlist_get_item(&screens[screen], list, adj_x, adj_y, &line)) |
730 | { | 734 | { |
731 | /* selection needs to be corrected if items are only partially visible */ | 735 | /* selection needs to be corrected if items are only partially visible */ |
732 | line = (adj_y - y_offset) / line_height; | 736 | int cur_y = list->start_item[screen] * line_height; |
737 | line = (adj_y - (cur_y - list->y_pos)) / line_height; | ||
733 | if (list_display_title(list, screen)) | 738 | if (list_display_title(list, screen)) |
734 | line -= 1; /* adjust for the list title */ | 739 | line -= 1; /* adjust for the list title */ |
735 | } | 740 | } |