diff --git a/apps/gui/list.c b/apps/gui/list.c index bad318eee6..466ab2904b 100644 --- a/apps/gui/list.c +++ b/apps/gui/list.c @@ -38,7 +38,7 @@ #ifdef HAVE_LCD_CHARCELLS #define SCROLL_LIMIT 1 #else -#define SCROLL_LIMIT 2 +#define SCROLL_LIMIT ((nb_lines/4)<2?2:nb_lines/4) #endif /* The minimum number of pending button events in queue before starting @@ -499,166 +499,70 @@ static void gui_list_select_item(struct gui_list * gui_list, int item_number) gui_list_put_selection_in_screen(gui_list, false); } -static void scroll_down(struct gui_list *gui_list, bool paginate) +static void gui_list_select_at_offset(struct gui_list * gui_list, int offset) { int nb_lines = gui_list->display->nb_lines; if (SHOW_LIST_TITLE) nb_lines--; - int item_pos = gui_list->selected_item - gui_list->start_item; - int end_item = gui_list->start_item + nb_lines; + offset *= gui_list->selected_size; + gui_list->selected_item += offset; - if (paginate) + if (offset < 0) /* moving up the list */ { - /* When we reach the bottom of the list - * we jump to a new page if there are more items*/ - if ((item_pos > nb_lines-gui_list->selected_size) && - (end_item < gui_list->nb_items) ) + if (gui_list->selected_item < 0) { - gui_list->start_item = gui_list->selected_item; - if ( gui_list->start_item > gui_list->nb_items-nb_lines ) - gui_list->start_item = gui_list->nb_items-nb_lines; + if(gui_list->limit_scroll) + { + gui_list->selected_item = 0; + gui_list->start_item = 0; + } + else + { + gui_list->selected_item = gui_list->nb_items - 1; + if (gui_list->nb_items >= nb_lines ) + gui_list->start_item = gui_list->selected_item - nb_lines + 1; + } + return; } - } - else - { - /* we start scrolling vertically when reaching the line - * (nb_lines-SCROLL_LIMIT) - * and when we are not in the last part of the list*/ - if( (item_pos > nb_lines-SCROLL_LIMIT) && - (end_item < gui_list->nb_items) ) + if (global_settings.scroll_paginated) { - gui_list->start_item+=gui_list->selected_size; + if (gui_list->selected_item < gui_list->start_item) + { + gui_list->start_item -= nb_lines; + if (gui_list->start_item < 0) + gui_list->start_item = 0; + } } + else if (gui_list->selected_item - gui_list->start_item <= SCROLL_LIMIT) + gui_list_put_selection_in_screen(gui_list, false); } -} - -static void scroll_up(struct gui_list *gui_list, bool paginate) -{ - int item_pos = gui_list->selected_item - gui_list->start_item; - int nb_lines = gui_list->display->nb_lines; - if (SHOW_LIST_TITLE) - nb_lines--; - - if (paginate) + else /* moving down */ { - /* When we reach the top of the list - * we jump to a new page if there are more items*/ - if( item_pos < 0) - gui_list->start_item = gui_list->selected_item - nb_lines + - gui_list->selected_size; - } - else - { - /* we start scrolling vertically when reaching the line - * (nb_lines-SCROLL_LIMIT) - * and when we are not in the last part of the list*/ - if( item_pos < SCROLL_LIMIT-1) - gui_list->start_item-=gui_list->selected_size; - } - if( gui_list->start_item < 0 ) - gui_list->start_item = 0; -} - -/* - * Selects the next item in the list - * (Item 0 gets selected if the end of the list is reached) - * - gui_list : the list structure - */ -static void gui_list_select_next(struct gui_list * gui_list) -{ - if( gui_list->selected_item+gui_list->selected_size >= gui_list->nb_items ) - { - if(gui_list->limit_scroll) + if (gui_list->selected_item >= gui_list->nb_items) + { + if(gui_list->limit_scroll) + { + if (gui_list->nb_items >= nb_lines) + gui_list->start_item = gui_list->nb_items - nb_lines; + gui_list->selected_item = gui_list->nb_items - 1; + } + else + { + gui_list->selected_item = 0; + gui_list->start_item = 0; + } return; - /* we have already reached the bottom of the list */ - gui_list->selected_item = 0; - gui_list->start_item = 0; + } + if (global_settings.scroll_paginated) + { + if (gui_list->selected_item - gui_list->start_item >= nb_lines) + { + gui_list->start_item = gui_list->selected_item; + } + } + else if (nb_lines - (gui_list->selected_item - gui_list->start_item) <= SCROLL_LIMIT) + gui_list_put_selection_in_screen(gui_list, true); } - else - { - gui_list->selected_item+=gui_list->selected_size; - scroll_down(gui_list, global_settings.scroll_paginated); - } -} - -/* - * Selects the previous item in the list - * (Last item in the list gets selected if the list beginning is reached) - * - gui_list : the list structure - */ -static void gui_list_select_previous(struct gui_list * gui_list) -{ - int nb_lines = gui_list->display->nb_lines; - if (SHOW_LIST_TITLE) - nb_lines--; - if( gui_list->selected_item-gui_list->selected_size < 0 ) - { - if(gui_list->limit_scroll) - return; - /* we have aleady reached the top of the list */ - int start; - gui_list->selected_item = gui_list->nb_items-gui_list->selected_size; - start = gui_list->nb_items-nb_lines; - if( start < 0 ) - gui_list->start_item = 0; - else - gui_list->start_item = start; - } - else - { - gui_list->selected_item -= gui_list->selected_size; - scroll_up(gui_list, global_settings.scroll_paginated); - } -} - -/* - * Go to next page if any, else selects the last item in the list - * - gui_list : the list structure - * - nb_lines : the number of lines to try to move the cursor - */ -static void gui_list_select_next_page(struct gui_list * gui_list, int nb_lines) -{ - if(gui_list->selected_item == gui_list->nb_items-gui_list->selected_size) - { - if(gui_list->limit_scroll) - return; - gui_list->selected_item = 0; - } - else - { - if (SHOW_LIST_TITLE) - nb_lines--; - nb_lines-=nb_lines%gui_list->selected_size; - gui_list->selected_item += nb_lines; - if(gui_list->selected_item > gui_list->nb_items-1) - gui_list->selected_item = gui_list->nb_items-1; - } - gui_list_put_selection_in_screen(gui_list, true); -} - -/* - * Go to previous page if any, else selects the first item in the list - * - gui_list : the list structure - * - nb_lines : the number of lines to try to move the cursor - */ -static void gui_list_select_previous_page(struct gui_list * gui_list, int nb_lines) -{ - if(gui_list->selected_item == 0) - { - if(gui_list->limit_scroll) - return; - gui_list->selected_item = gui_list->nb_items - gui_list->selected_size; - } - else - { - if (SHOW_LIST_TITLE) - nb_lines--; - nb_lines-=nb_lines%gui_list->selected_size; - gui_list->selected_item -= nb_lines; - if(gui_list->selected_item < 0) - gui_list->selected_item = 0; - } - gui_list_put_selection_in_screen(gui_list, false); } /* @@ -827,26 +731,12 @@ void gui_synclist_select_item(struct gui_synclist * lists, int item_number) gui_list_select_item(&(lists->gui_list[i]), item_number); } -static void gui_synclist_select_next(struct gui_synclist * lists) -{ - int i; - FOR_NB_SCREENS(i) - gui_list_select_next(&(lists->gui_list[i])); -} - -static void gui_synclist_select_previous(struct gui_synclist * lists) -{ - int i; - FOR_NB_SCREENS(i) - gui_list_select_previous(&(lists->gui_list[i])); -} - static void gui_synclist_select_next_page(struct gui_synclist * lists, enum screen_type screen) { int i; FOR_NB_SCREENS(i) - gui_list_select_next_page(&(lists->gui_list[i]), + gui_list_select_at_offset(&(lists->gui_list[i]), screens[screen].nb_lines); } @@ -855,8 +745,8 @@ static void gui_synclist_select_previous_page(struct gui_synclist * lists, { int i; FOR_NB_SCREENS(i) - gui_list_select_previous_page(&(lists->gui_list[i]), - screens[screen].nb_lines); + gui_list_select_at_offset(&(lists->gui_list[i]), + -screens[screen].nb_lines); } void gui_synclist_add_item(struct gui_synclist * lists) @@ -917,6 +807,32 @@ unsigned gui_synclist_do_button(struct gui_synclist * lists, #ifdef HAVE_LCD_BITMAP static bool scrolling_left = false; #endif + static int next_item_modifier = 1; + static int last_accel_tick = 0; + int i; + + if (global_settings.list_accel_start_delay) + { + int start_delay = global_settings.list_accel_start_delay * (HZ/2); + int accel_wait = global_settings.list_accel_wait * HZ/2; + + if (get_action_statuscode(NULL)&ACTION_REPEAT) + { + if (!last_accel_tick) + last_accel_tick = current_tick + start_delay; + else if (current_tick >= + last_accel_tick + accel_wait) + { + last_accel_tick = current_tick; + next_item_modifier++; + } + } + else if (last_accel_tick) + { + next_item_modifier = 1; + last_accel_tick = 0; + } + } switch (wrap) { @@ -928,7 +844,9 @@ unsigned gui_synclist_do_button(struct gui_synclist * lists, break; case LIST_WRAP_UNLESS_HELD: if (button == ACTION_STD_PREVREPEAT || - button == ACTION_STD_NEXTREPEAT) + button == ACTION_STD_NEXTREPEAT || + button == ACTION_LISTTREE_PGUP || + button == ACTION_LISTTREE_PGDOWN) gui_synclist_limit_scroll(lists, true); else gui_synclist_limit_scroll(lists, false); break; @@ -953,7 +871,8 @@ unsigned gui_synclist_do_button(struct gui_synclist * lists, #endif case ACTION_STD_PREV: case ACTION_STD_PREVREPEAT: - gui_synclist_select_previous(lists); + FOR_NB_SCREENS(i) + gui_list_select_at_offset(&(lists->gui_list[i]), -next_item_modifier); if (queue_count(&button_queue) < FRAMEDROP_TRIGGER) gui_synclist_draw(lists); yield(); @@ -961,7 +880,8 @@ unsigned gui_synclist_do_button(struct gui_synclist * lists, case ACTION_STD_NEXT: case ACTION_STD_NEXTREPEAT: - gui_synclist_select_next(lists); + FOR_NB_SCREENS(i) + gui_list_select_at_offset(&(lists->gui_list[i]), next_item_modifier); if (queue_count(&button_queue) < FRAMEDROP_TRIGGER) gui_synclist_draw(lists); yield(); diff --git a/apps/lang/english.lang b/apps/lang/english.lang index ecfa2be042..d48d917cba 100644 --- a/apps/lang/english.lang +++ b/apps/lang/english.lang @@ -10952,3 +10952,31 @@ *: "Time" + + id: LANG_LISTACCEL_START_DELAY + desc: Delay before list starts accelerating + user: + + *: "List Acceleration Start Delay" + + + *: "List Acceleration Start Delay" + + + *: "List Acceleration Start Delay" + + + + id: LANG_LISTACCEL_ACCEL_SPEED + desc: list acceleration speed + user: + + *: "List Acceleration Speed" + + + *: "List Acceleration Speed" + + + *: "List Acceleration Speed" + + diff --git a/apps/menus/display_menu.c b/apps/menus/display_menu.c index 3f5c6b3b54..60b06d7f4f 100644 --- a/apps/menus/display_menu.c +++ b/apps/menus/display_menu.c @@ -303,6 +303,7 @@ MENUITEM_SETTING(remote_scroll_delay, &global_settings.remote_scroll_delay, NULL MENUITEM_SETTING_W_TEXT(remote_scroll_step, &global_settings.remote_scroll_step, ID2P(LANG_SCROLL_STEP_EXAMPLE), NULL); MENUITEM_SETTING(remote_bidir_limit, &global_settings.remote_bidir_limit, NULL); + MAKE_MENU(remote_scroll_sets, ID2P(LANG_REMOTE_SCROLL_SETS), 0, Icon_NOICON, &remote_scroll_speed, &remote_scroll_delay, &remote_scroll_step, &remote_bidir_limit); @@ -311,6 +312,10 @@ MAKE_MENU(remote_scroll_sets, ID2P(LANG_REMOTE_SCROLL_SETS), 0, Icon_NOICON, MENUITEM_SETTING(jump_scroll, &global_settings.jump_scroll, NULL); MENUITEM_SETTING(jump_scroll_delay, &global_settings.jump_scroll_delay, NULL); #endif +/* list acceleration */ +MENUITEM_SETTING(list_accel_start_delay, + &global_settings.list_accel_start_delay, NULL); +MENUITEM_SETTING(list_accel_wait, &global_settings.list_accel_wait, NULL); #ifdef HAVE_LCD_BITMAP int screenscroll_callback(int action,const struct menu_item_ex *this_item) { @@ -344,7 +349,8 @@ MAKE_MENU(scroll_settings_menu, ID2P(LANG_SCROLL_MENU), 0, Icon_NOICON, #ifdef HAVE_LCD_BITMAP &offset_out_of_view, &screen_scroll_step, #endif - &scroll_paginated + &scroll_paginated, + &list_accel_start_delay, &list_accel_wait ); /* SCROLL MENU */ /***********************************/ diff --git a/apps/settings.h b/apps/settings.h index 5e9da84bae..f60e4bacc7 100644 --- a/apps/settings.h +++ b/apps/settings.h @@ -723,6 +723,8 @@ struct user_settings #ifdef HAVE_BUTTONLIGHT_BRIGHTNESS int buttonlight_brightness; #endif + int list_accel_start_delay; /* ms before we start increaseing step size */ + int list_accel_wait; /* ms between increases */ }; /** global variables **/ diff --git a/apps/settings_list.c b/apps/settings_list.c index c6adfe884a..efac40c7b5 100644 --- a/apps/settings_list.c +++ b/apps/settings_list.c @@ -177,6 +177,22 @@ static void poweroff_idle_timer_formatter(char *buffer, int buffer_size, snprintf(buffer, buffer_size, "%dm", poweroff_idle_timer_times[val]); } +static long listaccel_getlang(int value) +{ + if (value == 0) + return LANG_OFF; + return TALK_ID((HZ/2)*value, UNIT_MS); +} +static void listaccel_formatter(char *buffer, int buffer_size, + int val, const char *unit) +{ + (void)unit; + if (val == 0) + strcpy(buffer, str(LANG_OFF)); + else + snprintf(buffer, buffer_size, "%d ms", 5*HZ*val); +} + #define NVRAM(bytes) (bytes<