1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2005 by Kevin Ferrare
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
31 #include "screen_access.h"
33 #include "scrollbar.h"
34 #include "statusbar.h"
40 #ifdef HAVE_LCD_CHARCELLS
41 #define SCROLL_LIMIT 1
43 #define SCROLL_LIMIT (nb_lines<3?1:2)
46 /* The minimum number of pending button events in queue before starting
47 * to limit list drawing interval.
49 #define FRAMEDROP_TRIGGER 6
51 #ifdef HAVE_LCD_BITMAP
52 static int offset_step
= 16; /* pixels per screen scroll step */
53 /* should lines scroll out of the screen */
54 static bool offset_out_of_view
= false;
56 static struct gui_list
* last_list_displayed
[NB_SCREENS
];
58 #define SHOW_LIST_TITLE ((gui_list->title != NULL) && \
59 (gui_list->display->nb_lines > 2))
61 static void gui_list_select_at_offset(struct gui_list
* gui_list
, int offset
);
64 * Initializes a scrolling list
65 * - gui_list : the list structure to initialize
66 * - callback_get_item_name : pointer to a function that associates a label
67 * to a given item number
68 * - data : extra data passed to the list callback
72 static void gui_list_init(struct gui_list
* gui_list
,
73 list_get_name callback_get_item_name
,
79 gui_list
->callback_get_item_icon
= NULL
;
80 gui_list
->callback_get_item_name
= callback_get_item_name
;
81 gui_list
->display
= NULL
;
82 gui_list_set_nb_items(gui_list
, 0);
83 gui_list
->selected_item
= 0;
84 gui_list
->start_item
= 0;
85 gui_list
->limit_scroll
= false;
87 gui_list
->cursor_flash_state
=false;
88 #ifdef HAVE_LCD_BITMAP
89 gui_list
->offset_position
= 0;
91 gui_list
->scroll_all
=scroll_all
;
92 gui_list
->selected_size
=selected_size
;
93 gui_list
->title
= NULL
;
94 gui_list
->title_width
= 0;
95 gui_list
->title_icon
= Icon_NOICON
;
97 gui_list
->last_displayed_selected_item
= -1 ;
98 gui_list
->last_displayed_start_item
= -1 ;
99 gui_list
->show_selection_marker
= true;
101 #ifdef HAVE_LCD_COLOR
102 gui_list
->title_color
= -1;
103 gui_list
->callback_get_item_color
= NULL
;
107 /* this toggles the selection bar or cursor */
108 void gui_synclist_hide_selection_marker(struct gui_synclist
* lists
, bool hide
)
112 lists
->gui_list
[i
].show_selection_marker
= !hide
;
116 * Attach the scrolling list to a screen
117 * (The previous screen attachement is lost)
118 * - gui_list : the list structure
119 * - display : the screen to attach
121 static void gui_list_set_display(struct gui_list
* gui_list
, struct screen
* display
)
123 if(gui_list
->display
!= 0) /* we switched from a previous display */
124 gui_list
->display
->stop_scroll();
125 gui_list
->display
= display
;
126 #ifdef HAVE_LCD_CHARCELLS
127 display
->double_height(false);
129 gui_list_select_at_offset(gui_list
, 0);
133 * One call on 2, the selected lune will either blink the cursor or
134 * invert/display normal the selected line
135 * - gui_list : the list structure
137 static void gui_list_flash(struct gui_list
* gui_list
)
139 struct screen
* display
=gui_list
->display
;
140 gui_list
->cursor_flash_state
=!gui_list
->cursor_flash_state
;
141 int selected_line
=gui_list
->selected_item
-gui_list
->start_item
+SHOW_LIST_TITLE
;
142 #ifdef HAVE_LCD_BITMAP
143 int line_ypos
=display
->getymargin()+display
->char_height
*selected_line
;
144 if (global_settings
.cursor_style
)
146 int line_xpos
=display
->getxmargin();
147 display
->set_drawmode(DRMODE_COMPLEMENT
);
148 display
->fillrect(line_xpos
, line_ypos
, display
->width
,
149 display
->char_height
);
150 display
->set_drawmode(DRMODE_SOLID
);
151 display
->invertscroll(0, selected_line
);
155 int cursor_xpos
=(global_settings
.scrollbar
&&
156 display
->nb_lines
< gui_list
->nb_items
)?1:0;
157 screen_put_cursorxy(display
, cursor_xpos
, selected_line
,
158 gui_list
->cursor_flash_state
);
160 display
->update_rect(0, line_ypos
,display
->width
,
161 display
->char_height
);
163 screen_put_cursorxy(display
, 0, selected_line
,
164 gui_list
->cursor_flash_state
);
165 gui_textarea_update(display
);
170 #ifdef HAVE_LCD_BITMAP
171 static int gui_list_get_item_offset(struct gui_list
* gui_list
, int item_width
,
174 struct screen
* display
=gui_list
->display
;
177 if (offset_out_of_view
)
179 item_offset
= gui_list
->offset_position
;
183 /* if text is smaller then view */
184 if (item_width
<= display
->width
- text_pos
)
190 /* if text got out of view */
191 if (gui_list
->offset_position
>
192 item_width
- (display
->width
- text_pos
))
193 item_offset
= item_width
- (display
->width
- text_pos
);
195 item_offset
= gui_list
->offset_position
;
204 * Draws the list on the attached screen
205 * - gui_list : the list structure
207 static void gui_list_draw_smart(struct gui_list
*gui_list
)
209 struct screen
* display
=gui_list
->display
;
211 bool draw_icons
= (gui_list
->callback_get_item_icon
!= NULL
&& global_settings
.show_icons
);
215 static int last_lines
[NB_SCREENS
] = {0};
216 #ifdef HAVE_LCD_BITMAP
218 int old_margin
= display
->getxmargin();
221 bool partial_draw
= false;
223 #ifdef HAVE_LCD_BITMAP
224 display
->setfont(FONT_UI
);
225 gui_textarea_update_nblines(display
);
227 /* Speed up UI by drawing the changed contents only. */
228 if (gui_list
== last_list_displayed
[gui_list
->display
->screen_type
]
229 && gui_list
->last_displayed_start_item
== gui_list
->start_item
230 && gui_list
->selected_size
== 1)
235 lines
= display
->nb_lines
- SHOW_LIST_TITLE
;
236 if (last_lines
[display
->screen_type
] != lines
)
238 gui_list_select_at_offset(gui_list
, 0);
239 last_lines
[display
->screen_type
] = lines
;
244 end
= gui_list
->last_displayed_selected_item
- gui_list
->start_item
;
245 i
= gui_list
->selected_item
- gui_list
->start_item
;
259 gui_textarea_clear(display
);
261 end
= display
->nb_lines
;
262 gui_list
->last_displayed_start_item
= gui_list
->start_item
;
263 last_list_displayed
[gui_list
->display
->screen_type
] = gui_list
;
266 gui_list
->last_displayed_selected_item
= gui_list
->selected_item
;
268 /* position and draw the list title & icon */
269 if (SHOW_LIST_TITLE
&& !partial_draw
)
271 if (gui_list
->title_icon
!= NOICON
&& draw_icons
)
273 screen_put_icon(display
, 0, 0, gui_list
->title_icon
);
274 #ifdef HAVE_LCD_BITMAP
275 text_pos
= get_icon_width(display
->screen_type
)+2; /* pixels */
277 text_pos
= 1; /* chars */
285 #ifdef HAVE_LCD_BITMAP
286 int title_style
= STYLE_DEFAULT
;
287 #ifdef HAVE_LCD_COLOR
288 if (gui_list
->title_color
>= 0)
290 title_style
|= STYLE_COLORED
;
291 title_style
|= gui_list
->title_color
;
294 screen_set_xmargin(display
, text_pos
); /* margin for title */
295 item_offset
= gui_list_get_item_offset(gui_list
, gui_list
->title_width
,
297 if (item_offset
> gui_list
->title_width
- (display
->width
- text_pos
))
298 display
->puts_style_offset(0, 0, gui_list
->title
,
299 title_style
, item_offset
);
301 display
->puts_scroll_style_offset(0, 0, gui_list
->title
,
302 title_style
, item_offset
);
304 display
->puts_scroll(text_pos
, 0, gui_list
->title
);
308 /* Adjust the position of icon, cursor, text for the list */
309 #ifdef HAVE_LCD_BITMAP
310 gui_textarea_update_nblines(display
);
313 draw_scrollbar
= (global_settings
.scrollbar
&&
314 lines
< gui_list
->nb_items
);
316 draw_cursor
= !global_settings
.cursor_style
&&
317 gui_list
->show_selection_marker
;
318 text_pos
= 0; /* here it's in pixels */
319 if(draw_scrollbar
|| SHOW_LIST_TITLE
) /* indent if there's
322 text_pos
+= SCROLLBAR_WIDTH
;
325 text_pos
+= get_icon_width(display
->screen_type
) + 2;
328 text_pos
+= get_icon_width(display
->screen_type
) + 2;
332 text_pos
= 2; /* here it's in chars */
337 #ifdef HAVE_LCD_BITMAP
338 screen_set_xmargin(display
, text_pos
); /* margin for list */
344 if (end
< display
->nb_lines
)
348 for (i
= start
; i
< end
; i
++)
351 char entry_buffer
[MAX_PATH
];
352 unsigned char *entry_name
;
353 int current_item
= gui_list
->start_item
+
354 (SHOW_LIST_TITLE
? i
-1 : i
);
356 /* When there are less items to display than the
357 * current available space on the screen, we stop*/
358 if(current_item
>= gui_list
->nb_items
)
360 s
= gui_list
->callback_get_item_name(current_item
,
363 entry_name
= P2STR(s
);
365 #ifdef HAVE_LCD_BITMAP
366 int style
= STYLE_DEFAULT
;
367 /* position the string at the correct offset place */
369 display
->getstringsize(entry_name
, &item_width
, &h
);
370 item_offset
= gui_list_get_item_offset(gui_list
, item_width
, text_pos
);
373 #ifdef HAVE_LCD_COLOR
374 /* if the list has a color callback */
375 if (gui_list
->callback_get_item_color
)
377 int color
= gui_list
->callback_get_item_color(current_item
,
379 /* if color selected */
382 style
|= STYLE_COLORED
;
388 if(gui_list
->show_selection_marker
&&
389 current_item
>= gui_list
->selected_item
&&
390 current_item
< gui_list
->selected_item
+ gui_list
->selected_size
)
391 {/* The selected item must be displayed scrolling */
392 #ifdef HAVE_LCD_BITMAP
393 if (global_settings
.cursor_style
== 1
394 #ifdef HAVE_REMOTE_LCD
395 || display
->screen_type
== SCREEN_REMOTE
399 /* Display inverted-line-style */
400 style
|= STYLE_INVERT
;
402 #ifdef HAVE_LCD_COLOR
403 else if (global_settings
.cursor_style
== 2)
405 /* Display colour line selector */
406 style
|= STYLE_COLORBAR
;
408 else if (global_settings
.cursor_style
== 3)
410 /* Display gradient line selector */
411 style
= STYLE_GRADIENT
;
413 /* Make the lcd driver know how many lines the gradient should
414 cover and only draw it for the first selected item. */
415 if (current_item
== gui_list
->selected_item
)
416 style
|= gui_list
->selected_size
& STYLE_COLOR_MASK
;
419 else /* if (!global_settings.cursor_style) */
421 if (current_item
% gui_list
->selected_size
!= 0)
424 /* if the text is smaller than the viewport size */
425 if (item_offset
> item_width
- (display
->width
- text_pos
))
428 display
->puts_style_offset(0, i
, entry_name
,
433 display
->puts_scroll_style_offset(0, i
, entry_name
,
437 display
->puts_scroll(text_pos
, i
, entry_name
);
442 screen_put_icon_with_offset(display
, 0, i
,
443 (draw_scrollbar
|| SHOW_LIST_TITLE
)?
450 if(gui_list
->scroll_all
)
452 #ifdef HAVE_LCD_BITMAP
453 display
->puts_scroll_style_offset(0, i
, entry_name
,
456 display
->puts_scroll(text_pos
, i
, entry_name
);
461 #ifdef HAVE_LCD_BITMAP
462 display
->puts_style_offset(0, i
, entry_name
,
465 display
->puts(text_pos
, i
, entry_name
);
472 enum themable_icons icon
;
473 icon
= gui_list
->callback_get_item_icon(current_item
, gui_list
->data
);
474 if(icon
> Icon_NOICON
)
476 #ifdef HAVE_LCD_BITMAP
477 int x
= draw_cursor
?1:0;
478 int x_off
= (draw_scrollbar
|| SHOW_LIST_TITLE
) ? SCROLLBAR_WIDTH
: 0;
479 screen_put_icon_with_offset(display
, x
, i
,
482 screen_put_icon(display
, 1, i
, icon
);
488 #ifdef HAVE_LCD_BITMAP
489 /* Draw the scrollbar if needed*/
492 int y_start
= gui_textarea_get_ystart(display
);
494 y_start
+= display
->char_height
;
495 int scrollbar_y_end
= display
->char_height
*
497 gui_scrollbar_draw(display
, 0, y_start
, SCROLLBAR_WIDTH
-1,
498 scrollbar_y_end
- y_start
, gui_list
->nb_items
,
499 gui_list
->start_item
,
500 gui_list
->start_item
+ lines
, VERTICAL
);
503 screen_set_xmargin(display
, old_margin
);
506 gui_textarea_update(display
);
510 * Force a full screen update.
512 static void gui_list_draw(struct gui_list
*gui_list
)
514 last_list_displayed
[gui_list
->display
->screen_type
] = NULL
;
515 return gui_list_draw_smart(gui_list
);
519 * Selects an item in the list
520 * - gui_list : the list structure
521 * - item_number : the number of the item which will be selected
523 static void gui_list_select_item(struct gui_list
* gui_list
, int item_number
)
525 if( item_number
> gui_list
->nb_items
-1 || item_number
< 0 )
527 gui_list
->selected_item
= item_number
;
528 gui_list_select_at_offset(gui_list
, 0);
531 /* select an item above the current one */
532 static void gui_list_select_above(struct gui_list
* gui_list
,
533 int items
, int nb_lines
)
535 gui_list
->selected_item
-= items
;
537 /* in bottom "3rd" of the screen, so dont move the start item.
538 by 3rd I mean above SCROLL_LIMIT lines above the end of the screen */
539 if (items
&& gui_list
->start_item
+ SCROLL_LIMIT
< gui_list
->selected_item
)
541 if (gui_list
->show_selection_marker
== false)
543 gui_list
->start_item
-= items
;
544 if (gui_list
->start_item
< 0)
545 gui_list
->start_item
= 0;
549 if (gui_list
->selected_item
< 0)
551 if(gui_list
->limit_scroll
)
553 gui_list
->selected_item
= 0;
554 gui_list
->start_item
= 0;
558 gui_list
->selected_item
+= gui_list
->nb_items
;
559 if (global_settings
.scroll_paginated
)
561 gui_list
->start_item
= gui_list
->nb_items
- nb_lines
;
565 if (gui_list
->nb_items
> nb_lines
)
567 if (global_settings
.scroll_paginated
)
569 if (gui_list
->start_item
> gui_list
->selected_item
)
570 gui_list
->start_item
= MAX(0, gui_list
->start_item
- nb_lines
);
574 int top_of_screen
= gui_list
->selected_item
- SCROLL_LIMIT
;
575 int temp
= MIN(top_of_screen
, gui_list
->nb_items
- nb_lines
);
576 gui_list
->start_item
= MAX(0, temp
);
579 else gui_list
->start_item
= 0;
580 if (gui_list
->selected_size
> 1)
582 if (gui_list
->start_item
+ nb_lines
== gui_list
->selected_item
)
583 gui_list
->start_item
++;
586 /* select an item below the current one */
587 static void gui_list_select_below(struct gui_list
* gui_list
,
588 int items
, int nb_lines
)
592 gui_list
->selected_item
+= items
;
593 bottom
= gui_list
->nb_items
- nb_lines
;
595 /* always move the screen if selection isnt "visible" */
596 if (items
&& gui_list
->show_selection_marker
== false)
600 gui_list
->start_item
= MIN(bottom
, gui_list
->start_item
+
604 /* in top "3rd" of the screen, so dont move the start item */
606 (gui_list
->start_item
+ nb_lines
- SCROLL_LIMIT
> gui_list
->selected_item
)
607 && (gui_list
->selected_item
< gui_list
->nb_items
))
609 if (gui_list
->show_selection_marker
== false)
613 gui_list
->start_item
= MIN(bottom
,
614 gui_list
->start_item
+ items
);
619 if (gui_list
->selected_item
>= gui_list
->nb_items
)
621 if(gui_list
->limit_scroll
)
623 gui_list
->selected_item
= gui_list
->nb_items
-gui_list
->selected_size
;
624 gui_list
->start_item
= MAX(0,gui_list
->nb_items
- nb_lines
);
628 gui_list
->selected_item
= 0;
629 gui_list
->start_item
= 0;
634 if (gui_list
->nb_items
> nb_lines
)
636 if (global_settings
.scroll_paginated
)
638 if (gui_list
->start_item
+ nb_lines
<= gui_list
->selected_item
)
639 gui_list
->start_item
= MIN(bottom
, gui_list
->selected_item
);
643 int top_of_screen
= gui_list
->selected_item
+ SCROLL_LIMIT
- nb_lines
;
644 int temp
= MAX(0, top_of_screen
);
645 gui_list
->start_item
= MIN(bottom
, temp
);
648 else gui_list
->start_item
= 0;
651 static void gui_list_select_at_offset(struct gui_list
* gui_list
, int offset
)
653 /* do this here instead of in both select_above and select_below */
654 int nb_lines
= gui_list
->display
->nb_lines
;
658 if (gui_list
->selected_size
> 1)
660 offset
*= gui_list
->selected_size
;
661 /* always select the first item of multi-line lists */
662 offset
-= offset
%gui_list
->selected_size
;
664 if (offset
== 0 && global_settings
.scroll_paginated
&&
665 (gui_list
->nb_items
> nb_lines
))
667 int bottom
= gui_list
->nb_items
- nb_lines
;
668 gui_list
->start_item
= MIN(gui_list
->selected_item
, bottom
);
671 gui_list_select_above(gui_list
, -offset
, nb_lines
);
673 gui_list_select_below(gui_list
, offset
, nb_lines
);
677 * Adds an item to the list (the callback will be asked for one more item)
678 * - gui_list : the list structure
680 static void gui_list_add_item(struct gui_list
* gui_list
)
682 gui_list
->nb_items
++;
683 /* if only one item in the list, select it */
684 if(gui_list
->nb_items
== 1)
685 gui_list
->selected_item
= 0;
689 * Removes an item to the list (the callback will be asked for one less item)
690 * - gui_list : the list structure
692 static void gui_list_del_item(struct gui_list
* gui_list
)
694 if(gui_list
->nb_items
> 0)
696 gui_textarea_update_nblines(gui_list
->display
);
697 int nb_lines
= gui_list
->display
->nb_lines
;
699 int dist_selected_from_end
= gui_list
->nb_items
700 - gui_list
->selected_item
- 1;
701 int dist_start_from_end
= gui_list
->nb_items
702 - gui_list
->start_item
- 1;
703 if(dist_selected_from_end
== 0)
705 /* Oops we are removing the selected item,
706 select the previous one */
707 gui_list
->selected_item
--;
709 gui_list
->nb_items
--;
711 /* scroll the list if needed */
712 if( (dist_start_from_end
< nb_lines
) && (gui_list
->start_item
!= 0) )
713 gui_list
->start_item
--;
717 #ifdef HAVE_LCD_BITMAP
720 * Makes all the item in the list scroll by one step to the right.
721 * Should stop increasing the value when reaching the widest item value
724 static void gui_list_scroll_right(struct gui_list
* gui_list
)
726 /* FIXME: This is a fake right boundry limiter. there should be some
727 * callback function to find the longest item on the list in pixels,
728 * to stop the list from scrolling past that point */
729 gui_list
->offset_position
+=offset_step
;
730 if (gui_list
->offset_position
> 1000)
731 gui_list
->offset_position
= 1000;
735 * Makes all the item in the list scroll by one step to the left.
736 * stops at starting position.
738 static void gui_list_scroll_left(struct gui_list
* gui_list
)
740 gui_list
->offset_position
-=offset_step
;
741 if (gui_list
->offset_position
< 0)
742 gui_list
->offset_position
= 0;
744 void gui_list_screen_scroll_step(int ofs
)
749 void gui_list_screen_scroll_out_of_view(bool enable
)
752 offset_out_of_view
= true;
754 offset_out_of_view
= false;
756 #endif /* HAVE_LCD_BITMAP */
759 * Set the title and title icon of the list. Setting title to NULL disables
760 * both the title and icon. Use NOICON if there is no icon.
762 static void gui_list_set_title(struct gui_list
* gui_list
,
763 char * title
, enum themable_icons icon
)
765 gui_list
->title
= title
;
766 gui_list
->title_icon
= icon
;
768 #ifdef HAVE_LCD_BITMAP
769 gui_list
->display
->getstringsize(title
, &gui_list
->title_width
, NULL
);
771 gui_list
->title_width
= strlen(title
);
774 gui_list
->title_width
= 0;
779 * Synchronized lists stuffs
781 void gui_synclist_init(
782 struct gui_synclist
* lists
,
783 list_get_name callback_get_item_name
,
792 gui_list_init(&(lists
->gui_list
[i
]),
793 callback_get_item_name
,
794 data
, scroll_all
, selected_size
);
795 gui_list_set_display(&(lists
->gui_list
[i
]), &(screens
[i
]));
799 void gui_synclist_set_nb_items(struct gui_synclist
* lists
, int nb_items
)
804 gui_list_set_nb_items(&(lists
->gui_list
[i
]), nb_items
);
805 #ifdef HAVE_LCD_BITMAP
806 lists
->gui_list
[i
].offset_position
= 0;
810 int gui_synclist_get_nb_items(struct gui_synclist
* lists
)
812 return gui_list_get_nb_items(&((lists
)->gui_list
[0]));
814 int gui_synclist_get_sel_pos(struct gui_synclist
* lists
)
816 return gui_list_get_sel_pos(&((lists
)->gui_list
[0]));
818 void gui_synclist_set_icon_callback(struct gui_synclist
* lists
,
819 list_get_icon icon_callback
)
824 gui_list_set_icon_callback(&(lists
->gui_list
[i
]), icon_callback
);
828 void gui_synclist_draw(struct gui_synclist
* lists
)
832 gui_list_draw(&(lists
->gui_list
[i
]));
835 void gui_synclist_select_item(struct gui_synclist
* lists
, int item_number
)
839 gui_list_select_item(&(lists
->gui_list
[i
]), item_number
);
842 static void gui_synclist_select_next_page(struct gui_synclist
* lists
,
843 enum screen_type screen
)
847 gui_list_select_at_offset(&(lists
->gui_list
[i
]),
848 screens
[screen
].nb_lines
);
851 static void gui_synclist_select_previous_page(struct gui_synclist
* lists
,
852 enum screen_type screen
)
856 gui_list_select_at_offset(&(lists
->gui_list
[i
]),
857 -screens
[screen
].nb_lines
);
860 void gui_synclist_add_item(struct gui_synclist
* lists
)
864 gui_list_add_item(&(lists
->gui_list
[i
]));
867 void gui_synclist_del_item(struct gui_synclist
* lists
)
871 gui_list_del_item(&(lists
->gui_list
[i
]));
874 void gui_synclist_limit_scroll(struct gui_synclist
* lists
, bool scroll
)
878 gui_list_limit_scroll(&(lists
->gui_list
[i
]), scroll
);
881 void gui_synclist_set_title(struct gui_synclist
* lists
,
882 char * title
, enum themable_icons icon
)
886 gui_list_set_title(&(lists
->gui_list
[i
]), title
, icon
);
889 void gui_synclist_flash(struct gui_synclist
* lists
)
893 gui_list_flash(&(lists
->gui_list
[i
]));
896 #ifdef HAVE_LCD_BITMAP
897 static void gui_synclist_scroll_right(struct gui_synclist
* lists
)
901 gui_list_scroll_right(&(lists
->gui_list
[i
]));
904 static void gui_synclist_scroll_left(struct gui_synclist
* lists
)
908 gui_list_scroll_left(&(lists
->gui_list
[i
]));
910 #endif /* HAVE_LCD_BITMAP */
912 extern intptr_t get_action_data(void);
914 bool gui_synclist_do_button(struct gui_synclist
* lists
,
915 unsigned *actionptr
, enum list_wrap wrap
)
917 int action
= *actionptr
;
918 #ifdef HAVE_LCD_BITMAP
919 static bool scrolling_left
= false;
923 #ifdef HAVE_SCROLLWHEEL
924 int next_item_modifier
= button_apply_acceleration(get_action_data(),
925 WHEEL_ACCELERATION_FACTOR
);
927 static int next_item_modifier
= 1;
928 static int last_accel_tick
= 0;
930 if (global_settings
.list_accel_start_delay
)
932 int start_delay
= global_settings
.list_accel_start_delay
* (HZ
/2);
933 int accel_wait
= global_settings
.list_accel_wait
* HZ
/2;
935 if (get_action_statuscode(NULL
)&ACTION_REPEAT
)
937 if (!last_accel_tick
)
938 last_accel_tick
= current_tick
+ start_delay
;
939 else if (current_tick
>=
940 last_accel_tick
+ accel_wait
)
942 last_accel_tick
= current_tick
;
943 next_item_modifier
++;
946 else if (last_accel_tick
)
948 next_item_modifier
= 1;
957 gui_synclist_limit_scroll(lists
, false);
960 gui_synclist_limit_scroll(lists
, true);
962 case LIST_WRAP_UNLESS_HELD
:
963 if (action
== ACTION_STD_PREVREPEAT
||
964 action
== ACTION_STD_NEXTREPEAT
||
965 action
== ACTION_LISTTREE_PGUP
||
966 action
== ACTION_LISTTREE_PGDOWN
)
967 gui_synclist_limit_scroll(lists
, true);
968 else gui_synclist_limit_scroll(lists
, false);
974 #ifdef HAVE_VOLUME_IN_LIST
975 case ACTION_LIST_VOLUP
:
976 global_settings
.volume
+= 2;
977 /* up two because the falthrough brings it down one */
978 case ACTION_LIST_VOLDOWN
:
979 global_settings
.volume
--;
983 case ACTION_STD_PREV
:
984 case ACTION_STD_PREVREPEAT
:
986 gui_list_select_at_offset(&(lists
->gui_list
[i
]), -next_item_modifier
);
987 #ifndef HAVE_SCROLLWHEEL
988 if (queue_count(&button_queue
) < FRAMEDROP_TRIGGER
)
991 gui_synclist_draw(lists
);
994 *actionptr
= ACTION_STD_PREV
;
997 case ACTION_STD_NEXT
:
998 case ACTION_STD_NEXTREPEAT
:
1000 gui_list_select_at_offset(&(lists
->gui_list
[i
]), next_item_modifier
);
1001 #ifndef HAVE_SCROLLWHEEL
1002 if (queue_count(&button_queue
) < FRAMEDROP_TRIGGER
)
1005 gui_synclist_draw(lists
);
1008 *actionptr
= ACTION_STD_NEXT
;
1011 #ifdef HAVE_LCD_BITMAP
1012 case ACTION_TREE_PGRIGHT
:
1013 gui_synclist_scroll_right(lists
);
1014 gui_synclist_draw(lists
);
1016 case ACTION_TREE_ROOT_INIT
:
1017 /* After this button press ACTION_TREE_PGLEFT is allowed
1018 to skip to root. ACTION_TREE_ROOT_INIT must be defined in the
1019 keymaps as a repeated button press (the same as the repeated
1020 ACTION_TREE_PGLEFT) with the pre condition being the non-repeated
1022 if (lists
->gui_list
[0].offset_position
== 0)
1024 scrolling_left
= false;
1025 *actionptr
= ACTION_STD_CANCEL
;
1028 *actionptr
= ACTION_TREE_PGLEFT
;
1029 case ACTION_TREE_PGLEFT
:
1030 if(!scrolling_left
&& (lists
->gui_list
[0].offset_position
== 0))
1032 *actionptr
= ACTION_STD_CANCEL
;
1035 gui_synclist_scroll_left(lists
);
1036 gui_synclist_draw(lists
);
1037 scrolling_left
= true; /* stop ACTION_TREE_PAGE_LEFT
1042 /* for pgup / pgdown, we are obliged to have a different behaviour depending
1043 * on the screen for which the user pressed the key since for example, remote
1044 * and main screen doesn't have the same number of lines */
1045 case ACTION_LISTTREE_PGUP
:
1048 #ifdef HAVE_REMOTE_LCD
1049 get_action_statuscode(NULL
)&ACTION_REMOTE
?
1053 gui_synclist_select_previous_page(lists
, screen
);
1054 gui_synclist_draw(lists
);
1056 *actionptr
= ACTION_STD_NEXT
;
1060 case ACTION_LISTTREE_PGDOWN
:
1063 #ifdef HAVE_REMOTE_LCD
1064 get_action_statuscode(NULL
)&ACTION_REMOTE
?
1068 gui_synclist_select_next_page(lists
, screen
);
1069 gui_synclist_draw(lists
);
1071 *actionptr
= ACTION_STD_PREV
;