summaryrefslogtreecommitdiff
path: root/apps/gui
diff options
context:
space:
mode:
authorJonathan Gordon <rockbox@jdgordon.info>2007-06-05 02:57:43 +0000
committerJonathan Gordon <rockbox@jdgordon.info>2007-06-05 02:57:43 +0000
commitfea88888f0bc271b57a6d6dfab387fddc1cbd20d (patch)
tree08c963e189012878f76071a5c26f953b151c81bd /apps/gui
parent71577e0d874e9c8e000261066761ded5ba6d5a01 (diff)
downloadrockbox-fea88888f0bc271b57a6d6dfab387fddc1cbd20d.tar.gz
rockbox-fea88888f0bc271b57a6d6dfab387fddc1cbd20d.zip
Fix most (all) known list wierdness bugs, hopefully simplifies the code a bit, plenty of room for optimizing, but wanted to get it working first. (fixes FS#7255 and possibly others)
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@13556 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/gui')
-rw-r--r--apps/gui/list.c197
1 files changed, 91 insertions, 106 deletions
diff --git a/apps/gui/list.c b/apps/gui/list.c
index 23939469c5..43bbbe27cb 100644
--- a/apps/gui/list.c
+++ b/apps/gui/list.c
@@ -25,6 +25,7 @@
25#include "string.h" 25#include "string.h"
26#include "settings.h" 26#include "settings.h"
27#include "kernel.h" 27#include "kernel.h"
28#include "system.h"
28 29
29#include "action.h" 30#include "action.h"
30#include "screen_access.h" 31#include "screen_access.h"
@@ -39,7 +40,7 @@
39#ifdef HAVE_LCD_CHARCELLS 40#ifdef HAVE_LCD_CHARCELLS
40#define SCROLL_LIMIT 1 41#define SCROLL_LIMIT 1
41#else 42#else
42#define SCROLL_LIMIT ((nb_lines/4)<2?2:nb_lines/4) 43#define SCROLL_LIMIT (nb_lines<3?1:2)
43#endif 44#endif
44 45
45/* The minimum number of pending button events in queue before starting 46/* The minimum number of pending button events in queue before starting
@@ -57,9 +58,7 @@ static struct gui_list* last_list_displayed[NB_SCREENS];
57#define SHOW_LIST_TITLE ((gui_list->title != NULL) && \ 58#define SHOW_LIST_TITLE ((gui_list->title != NULL) && \
58 (gui_list->display->nb_lines > 2)) 59 (gui_list->display->nb_lines > 2))
59 60
60static void gui_list_put_selection_in_screen(struct gui_list * gui_list, 61static void gui_list_select_at_offset(struct gui_list * gui_list, int offset);
61 bool put_from_end);
62
63 62
64/* 63/*
65 * Initializes a scrolling list 64 * Initializes a scrolling list
@@ -113,7 +112,7 @@ static void gui_list_set_display(struct gui_list * gui_list, struct screen * dis
113#ifdef HAVE_LCD_CHARCELLS 112#ifdef HAVE_LCD_CHARCELLS
114 display->double_height(false); 113 display->double_height(false);
115#endif 114#endif
116 gui_list_put_selection_in_screen(gui_list, false); 115 gui_list_select_at_offset(gui_list, 0);
117} 116}
118 117
119/* 118/*
@@ -153,51 +152,6 @@ static void gui_list_flash(struct gui_list * gui_list)
153#endif 152#endif
154} 153}
155 154
156/*
157 * Puts the selection in the screen
158 * - gui_list : the list structure
159 * - put_from_end : if true, selection will be put as close from
160 * the end of the list as possible, else, it's
161 * from the beginning
162 */
163static void gui_list_put_selection_in_screen(struct gui_list * gui_list,
164 bool put_from_end)
165{
166#ifdef HAVE_LCD_BITMAP
167 gui_list->display->setfont(FONT_UI);
168#endif
169 gui_textarea_update_nblines(gui_list->display);
170 int nb_lines=gui_list->display->nb_lines;
171 if (SHOW_LIST_TITLE)
172 nb_lines--;
173 if (gui_list->nb_items < nb_lines)
174 {
175 gui_list->start_item = 0;
176 }
177 else if (global_settings.scroll_paginated &&
178 gui_list->nb_items - gui_list->selected_item < nb_lines)
179 {
180 gui_list->start_item = gui_list->nb_items - nb_lines;
181 }
182 else if(put_from_end)
183 {
184 int list_end = gui_list->selected_item + SCROLL_LIMIT;
185 if(list_end >= gui_list->nb_items)
186 list_end = gui_list->nb_items;
187 gui_list->start_item = list_end - nb_lines;
188 }
189 else if (gui_list->nb_items-gui_list->selected_item < nb_lines)
190 {
191 gui_list->start_item = gui_list->nb_items - nb_lines;
192 }
193 else
194 {
195 int list_start = gui_list->selected_item - SCROLL_LIMIT - 1;
196 gui_list->start_item = list_start;
197 if(gui_list->start_item < 0)
198 gui_list->start_item = 0;
199 }
200}
201 155
202#ifdef HAVE_LCD_BITMAP 156#ifdef HAVE_LCD_BITMAP
203static int gui_list_get_item_offset(struct gui_list * gui_list, int item_width, 157static int gui_list_get_item_offset(struct gui_list * gui_list, int item_width,
@@ -505,85 +459,116 @@ static void gui_list_select_item(struct gui_list * gui_list, int item_number)
505 if( item_number > gui_list->nb_items-1 || item_number < 0 ) 459 if( item_number > gui_list->nb_items-1 || item_number < 0 )
506 return; 460 return;
507 gui_list->selected_item = item_number; 461 gui_list->selected_item = item_number;
508 gui_list_put_selection_in_screen(gui_list, false); 462 gui_list_select_at_offset(gui_list, 0);
509} 463}
510 464
511static void gui_list_select_at_offset(struct gui_list * gui_list, int offset) 465/* select an item above the current one */
466static void gui_list_select_above(struct gui_list * gui_list, int items)
512{ 467{
513 int nb_lines = gui_list->display->nb_lines; 468 int nb_lines = gui_list->display->nb_lines;
514 if (SHOW_LIST_TITLE) 469 if (SHOW_LIST_TITLE)
515 nb_lines--; 470 nb_lines--;
516 471
517 472 gui_list->selected_item -= items;
518 if (gui_list->selected_size > 1) 473 /* in bottom "3rd" of the screen, so dont move the start item.
519 { 474 by 3rd I mean above SCROLL_LIMIT lines above the end of the screen */
520 offset *= gui_list->selected_size; 475 if (items && gui_list->start_item + SCROLL_LIMIT < gui_list->selected_item)
521 /* always select the first item of multi-line lists */ 476 return;
522 offset -= offset%gui_list->selected_size; 477 if (gui_list->selected_item < 0)
523 }
524 gui_list->selected_item += offset;
525
526 if (offset < 0) /* moving up the list */
527 { 478 {
528 if (gui_list->selected_item < 0) 479 if(gui_list->limit_scroll)
529 { 480 {
530 if(gui_list->limit_scroll) 481 gui_list->selected_item = 0;
531 { 482 gui_list->start_item = 0;
532 gui_list->selected_item = 0; 483 }
533 gui_list->start_item = 0; 484 else
534 } 485 {
535 else 486 gui_list->selected_item += gui_list->nb_items;
487 if (global_settings.scroll_paginated)
536 { 488 {
537 gui_list->selected_item = gui_list->nb_items - 489 gui_list->start_item = gui_list->nb_items - nb_lines;
538 gui_list->selected_size;
539 if (gui_list->nb_items >= nb_lines )
540 gui_list->start_item = gui_list->selected_item -
541 nb_lines + gui_list->selected_size;
542 } 490 }
543 return;
544 } 491 }
492 }
493 if (gui_list->nb_items > nb_lines)
494 {
545 if (global_settings.scroll_paginated) 495 if (global_settings.scroll_paginated)
546 { 496 {
547 if (gui_list->selected_item < gui_list->start_item) 497 if (gui_list->start_item > gui_list->selected_item)
548 { 498 gui_list->start_item = MAX(0, gui_list->start_item - nb_lines);
549 gui_list->start_item -= nb_lines; 499 }
550 if (gui_list->start_item < 0) 500 else
551 gui_list->start_item = 0; 501 {
552 } 502 int top_of_screen = gui_list->selected_item - SCROLL_LIMIT;
503 int temp = MIN(top_of_screen, gui_list->nb_items - nb_lines);
504 gui_list->start_item = MAX(0, temp);
553 } 505 }
554 else if (gui_list->selected_item - gui_list->start_item <= SCROLL_LIMIT)
555 gui_list_put_selection_in_screen(gui_list, false);
556 } 506 }
557 else /* moving down */ 507 else gui_list->start_item = 0;
508 if (gui_list->selected_size > 1)
558 { 509 {
559 if (gui_list->selected_item >= gui_list->nb_items) 510 if (gui_list->start_item + nb_lines == gui_list->selected_item)
511 gui_list->start_item++;
512 }
513}
514/* select an item below the current one */
515static void gui_list_select_below(struct gui_list * gui_list, int items)
516{
517 int nb_lines = gui_list->display->nb_lines;
518 if (SHOW_LIST_TITLE)
519 nb_lines--;
520
521 gui_list->selected_item += items;
522 /* in top "3rd" of the screen, so dont move the start item */
523 if (items &&
524 (gui_list->start_item + nb_lines - SCROLL_LIMIT > gui_list->selected_item)
525 && (gui_list->selected_item < gui_list->nb_items))
526 return;
527
528 if (gui_list->selected_item >= gui_list->nb_items)
529 {
530 if(gui_list->limit_scroll)
560 { 531 {
561 if(gui_list->limit_scroll) 532 gui_list->selected_item = gui_list->nb_items-gui_list->selected_size;
562 { 533 gui_list->start_item = MAX(0,gui_list->nb_items - nb_lines);
563 if (gui_list->nb_items >= nb_lines) 534 }
564 gui_list->start_item = gui_list->nb_items - nb_lines; 535 else
565 gui_list->selected_item = gui_list->nb_items - 536 {
566 gui_list->selected_size; 537 gui_list->selected_item = 0;
567 } 538 gui_list->start_item = 0;
568 else
569 {
570 gui_list->selected_item = 0;
571 gui_list->start_item = 0;
572 }
573 return;
574 } 539 }
540 return;
541 }
542 int bottom = gui_list->nb_items - nb_lines;
543 if (gui_list->nb_items > nb_lines)
544 {
575 if (global_settings.scroll_paginated) 545 if (global_settings.scroll_paginated)
576 { 546 {
577 if (gui_list->selected_item - gui_list->start_item >= nb_lines) 547 if (gui_list->start_item + nb_lines <= gui_list->selected_item)
578 { 548 gui_list->start_item = MIN(bottom, gui_list->selected_item);
579 gui_list->start_item = gui_list->selected_item; 549 }
580 if (gui_list->nb_items - gui_list->start_item < nb_lines) 550 else
581 gui_list->start_item = gui_list->nb_items - nb_lines; 551 {
582 } 552 int top_of_screen = gui_list->selected_item + SCROLL_LIMIT - nb_lines;
553 int temp = MAX(0, top_of_screen);
554 gui_list->start_item = MIN(bottom, temp);
583 } 555 }
584 else if (nb_lines - (gui_list->selected_item - gui_list->start_item) <= SCROLL_LIMIT)
585 gui_list_put_selection_in_screen(gui_list, true);
586 } 556 }
557 else gui_list->start_item = 0;
558}
559
560static void gui_list_select_at_offset(struct gui_list * gui_list, int offset)
561{
562 if (gui_list->selected_size > 1)
563 {
564 offset *= gui_list->selected_size;
565 /* always select the first item of multi-line lists */
566 offset -= offset%gui_list->selected_size;
567 }
568 if (offset < 0)
569 gui_list_select_above(gui_list, -offset);
570 else
571 gui_list_select_below(gui_list, offset);
587} 572}
588 573
589/* 574/*