summaryrefslogtreecommitdiff
path: root/apps/gui
diff options
context:
space:
mode:
Diffstat (limited to 'apps/gui')
-rw-r--r--apps/gui/list.c91
-rw-r--r--apps/gui/list.h31
2 files changed, 118 insertions, 4 deletions
diff --git a/apps/gui/list.c b/apps/gui/list.c
index 52c1e4a3b9..d9725e451a 100644
--- a/apps/gui/list.c
+++ b/apps/gui/list.c
@@ -36,6 +36,7 @@
36#include "lang.h" 36#include "lang.h"
37#include "sound.h" 37#include "sound.h"
38#include "misc.h" 38#include "misc.h"
39#include "talk.h"
39 40
40#ifdef HAVE_LCD_CHARCELLS 41#ifdef HAVE_LCD_CHARCELLS
41#define SCROLL_LIMIT 1 42#define SCROLL_LIMIT 1
@@ -78,6 +79,7 @@ static void gui_list_init(struct gui_list * gui_list,
78{ 79{
79 gui_list->callback_get_item_icon = NULL; 80 gui_list->callback_get_item_icon = NULL;
80 gui_list->callback_get_item_name = callback_get_item_name; 81 gui_list->callback_get_item_name = callback_get_item_name;
82 gui_list->callback_speak_item = NULL;
81 gui_list->display = NULL; 83 gui_list->display = NULL;
82 gui_list_set_nb_items(gui_list, 0); 84 gui_list_set_nb_items(gui_list, 0);
83 gui_list->selected_item = 0; 85 gui_list->selected_item = 0;
@@ -95,6 +97,7 @@ static void gui_list_init(struct gui_list * gui_list,
95 97
96 gui_list->last_displayed_selected_item = -1 ; 98 gui_list->last_displayed_selected_item = -1 ;
97 gui_list->last_displayed_start_item = -1 ; 99 gui_list->last_displayed_start_item = -1 ;
100 gui_list->scheduled_talk_tick = gui_list->last_talked_tick = 0;
98 gui_list->show_selection_marker = true; 101 gui_list->show_selection_marker = true;
99 102
100#ifdef HAVE_LCD_COLOR 103#ifdef HAVE_LCD_COLOR
@@ -786,6 +789,12 @@ void gui_synclist_set_icon_callback(struct gui_synclist * lists,
786 } 789 }
787} 790}
788 791
792void gui_synclist_set_voice_callback(struct gui_synclist * lists,
793 list_speak_item voice_callback)
794{
795 gui_list_set_voice_callback(&(lists->gui_list[0]), voice_callback);
796}
797
789void gui_synclist_draw(struct gui_synclist * lists) 798void gui_synclist_draw(struct gui_synclist * lists)
790{ 799{
791 int i; 800 int i;
@@ -863,6 +872,43 @@ static void gui_synclist_scroll_left(struct gui_synclist * lists)
863} 872}
864#endif /* HAVE_LCD_BITMAP */ 873#endif /* HAVE_LCD_BITMAP */
865 874
875static void _gui_synclist_speak_item(struct gui_synclist *lists, bool repeating)
876{
877 struct gui_list *l = &lists->gui_list[0];
878 list_speak_item *cb = l->callback_speak_item;
879 if(cb && gui_synclist_get_nb_items(lists) != 0)
880 {
881 int sel = gui_synclist_get_sel_pos(lists);
882 talk_shutup();
883 /* If we got a repeating key action, or we have just very
884 recently started talking, then we want to stay silent for a
885 while until things settle. Likewise if we already had a
886 pending scheduled announcement not yet due: we need to
887 reschedule it. */
888 if(repeating
889 || (l->scheduled_talk_tick
890 && TIME_BEFORE(current_tick, l->scheduled_talk_tick))
891 || (l->last_talked_tick
892 && TIME_BEFORE(current_tick, l->last_talked_tick +HZ/4)))
893 {
894 l->scheduled_talk_tick = current_tick +HZ/4;
895 return;
896 } else {
897 l->scheduled_talk_tick = 0; /* work done */
898 cb(sel, l->data);
899 l->last_talked_tick = current_tick;
900 }
901 }
902}
903void gui_synclist_speak_item(struct gui_synclist * lists)
904/* The list user should call this to speak the first item on entering
905 the list, and whenever the list is updated. */
906{
907 if(gui_synclist_get_nb_items(lists) == 0 && global_settings.talk_menu)
908 talk_id(VOICE_EMPTY_LIST, true);
909 else _gui_synclist_speak_item(lists, false);
910}
911
866extern intptr_t get_action_data(void); 912extern intptr_t get_action_data(void);
867 913
868bool gui_synclist_do_button(struct gui_synclist * lists, 914bool gui_synclist_do_button(struct gui_synclist * lists,
@@ -941,9 +987,10 @@ bool gui_synclist_do_button(struct gui_synclist * lists,
941#ifndef HAVE_SCROLLWHEEL 987#ifndef HAVE_SCROLLWHEEL
942 if (queue_count(&button_queue) < FRAMEDROP_TRIGGER) 988 if (queue_count(&button_queue) < FRAMEDROP_TRIGGER)
943#endif 989#endif
944 {
945 gui_synclist_draw(lists); 990 gui_synclist_draw(lists);
946 } 991 _gui_synclist_speak_item(lists,
992 action == ACTION_STD_PREVREPEAT
993 || next_item_modifier >1);
947 yield(); 994 yield();
948 *actionptr = ACTION_STD_PREV; 995 *actionptr = ACTION_STD_PREV;
949 return true; 996 return true;
@@ -955,9 +1002,10 @@ bool gui_synclist_do_button(struct gui_synclist * lists,
955#ifndef HAVE_SCROLLWHEEL 1002#ifndef HAVE_SCROLLWHEEL
956 if (queue_count(&button_queue) < FRAMEDROP_TRIGGER) 1003 if (queue_count(&button_queue) < FRAMEDROP_TRIGGER)
957#endif 1004#endif
958 {
959 gui_synclist_draw(lists); 1005 gui_synclist_draw(lists);
960 } 1006 _gui_synclist_speak_item(lists,
1007 action == ACTION_STD_NEXTREPEAT
1008 || next_item_modifier >1);
961 yield(); 1009 yield();
962 *actionptr = ACTION_STD_NEXT; 1010 *actionptr = ACTION_STD_NEXT;
963 return true; 1011 return true;
@@ -1006,6 +1054,7 @@ bool gui_synclist_do_button(struct gui_synclist * lists,
1006 SCREEN_MAIN; 1054 SCREEN_MAIN;
1007 gui_synclist_select_previous_page(lists, screen); 1055 gui_synclist_select_previous_page(lists, screen);
1008 gui_synclist_draw(lists); 1056 gui_synclist_draw(lists);
1057 _gui_synclist_speak_item(lists, false);
1009 yield(); 1058 yield();
1010 *actionptr = ACTION_STD_NEXT; 1059 *actionptr = ACTION_STD_NEXT;
1011 } 1060 }
@@ -1021,14 +1070,48 @@ bool gui_synclist_do_button(struct gui_synclist * lists,
1021 SCREEN_MAIN; 1070 SCREEN_MAIN;
1022 gui_synclist_select_next_page(lists, screen); 1071 gui_synclist_select_next_page(lists, screen);
1023 gui_synclist_draw(lists); 1072 gui_synclist_draw(lists);
1073 _gui_synclist_speak_item(lists, false);
1024 yield(); 1074 yield();
1025 *actionptr = ACTION_STD_PREV; 1075 *actionptr = ACTION_STD_PREV;
1026 } 1076 }
1027 return true; 1077 return true;
1028 } 1078 }
1079 if(lists->gui_list[0].scheduled_talk_tick
1080 && TIME_AFTER(current_tick, lists->gui_list[0].scheduled_talk_tick))
1081 /* scheduled postponed item announcement is due */
1082 _gui_synclist_speak_item(lists, false);
1029 return false; 1083 return false;
1030} 1084}
1031 1085
1086int list_do_action_timeout(struct gui_synclist *lists, int timeout)
1087/* Returns the lowest of timeout or the delay until a postponed
1088 scheduled announcement is due (if any). */
1089{
1090 if(lists->gui_list[0].scheduled_talk_tick)
1091 {
1092 long delay = lists->gui_list[0].scheduled_talk_tick -current_tick +1;
1093 /* +1 because the trigger condition uses TIME_AFTER(), which
1094 is implemented as strictly greater than. */
1095 if(delay < 0)
1096 delay = 0;
1097 if(timeout > delay || timeout == TIMEOUT_BLOCK)
1098 timeout = delay;
1099 }
1100 return timeout;
1101}
1102
1103bool list_do_action(int context, int timeout,
1104 struct gui_synclist *lists, int *action,
1105 enum list_wrap wrap)
1106/* Combines the get_action() (with possibly overridden timeout) and
1107 gui_synclist_do_button() calls. Returns the list action from
1108 do_button, and places the action from get_action in *action. */
1109{
1110 timeout = list_do_action_timeout(lists, timeout);
1111 *action = get_action(context, timeout);
1112 return gui_synclist_do_button(lists, action, wrap);
1113}
1114
1032/* Simple use list implementation */ 1115/* Simple use list implementation */
1033static int simplelist_line_count = 0; 1116static int simplelist_line_count = 0;
1034static char simplelist_text[SIMPLELIST_MAX_LINES][SIMPLELIST_MAX_LINELENGTH]; 1117static char simplelist_text[SIMPLELIST_MAX_LINES][SIMPLELIST_MAX_LINELENGTH];
diff --git a/apps/gui/list.h b/apps/gui/list.h
index 2de67f5219..253dd9bdbf 100644
--- a/apps/gui/list.h
+++ b/apps/gui/list.h
@@ -62,6 +62,14 @@ typedef enum themable_icons list_get_icon(int selected_item, void * data);
62 * Returns a pointer to a string that contains the text to display 62 * Returns a pointer to a string that contains the text to display
63 */ 63 */
64typedef char * list_get_name(int selected_item, void * data, char * buffer); 64typedef char * list_get_name(int selected_item, void * data, char * buffer);
65/*
66 * Voice callback
67 * - selected_item : an integer that tells the number of the item to speak
68 * - data : a void pointer to the data you gave to the list when you
69 * initialized it
70 * Returns an integer, 0 means success, ignored really...
71 */
72typedef int list_speak_item(int selected_item, void * data);
65#ifdef HAVE_LCD_COLOR 73#ifdef HAVE_LCD_COLOR
66/* 74/*
67 * Color callback 75 * Color callback
@@ -97,9 +105,11 @@ struct gui_list
97#endif 105#endif
98 /* Cache the width of the title string in pixels/characters */ 106 /* Cache the width of the title string in pixels/characters */
99 int title_width; 107 int title_width;
108 long scheduled_talk_tick, last_talked_tick;
100 109
101 list_get_icon *callback_get_item_icon; 110 list_get_icon *callback_get_item_icon;
102 list_get_name *callback_get_item_name; 111 list_get_name *callback_get_item_name;
112 list_speak_item *callback_speak_item;
103 113
104 struct screen * display; 114 struct screen * display;
105 /* The data that will be passed to the callback function YOU implement */ 115 /* The data that will be passed to the callback function YOU implement */
@@ -140,6 +150,14 @@ struct gui_list
140#define gui_list_set_icon_callback(gui_list, _callback) \ 150#define gui_list_set_icon_callback(gui_list, _callback) \
141 (gui_list)->callback_get_item_icon=_callback 151 (gui_list)->callback_get_item_icon=_callback
142 152
153/*
154 * Sets the voice callback function
155 * - gui_list : the list structure
156 * - _callback : the callback function
157 */
158#define gui_list_set_voice_callback(gui_list, _callback) \
159 (gui_list)->callback_speak_item=_callback
160
143#ifdef HAVE_LCD_COLOR 161#ifdef HAVE_LCD_COLOR
144/* 162/*
145 * Sets the color callback function 163 * Sets the color callback function
@@ -200,6 +218,8 @@ extern void gui_synclist_init(
200 ); 218 );
201extern void gui_synclist_set_nb_items(struct gui_synclist * lists, int nb_items); 219extern void gui_synclist_set_nb_items(struct gui_synclist * lists, int nb_items);
202extern void gui_synclist_set_icon_callback(struct gui_synclist * lists, list_get_icon icon_callback); 220extern void gui_synclist_set_icon_callback(struct gui_synclist * lists, list_get_icon icon_callback);
221extern void gui_synclist_set_voice_callback(struct gui_synclist * lists, list_speak_item voice_callback);
222extern void gui_synclist_speak_item(struct gui_synclist * lists);
203extern int gui_synclist_get_nb_items(struct gui_synclist * lists); 223extern int gui_synclist_get_nb_items(struct gui_synclist * lists);
204 224
205extern int gui_synclist_get_sel_pos(struct gui_synclist * lists); 225extern int gui_synclist_get_sel_pos(struct gui_synclist * lists);
@@ -266,4 +286,15 @@ void simplelist_addline(int line_number, const char *fmt, ...);
266 before the list is dislplayed for the first time */ 286 before the list is dislplayed for the first time */
267bool simplelist_show_list(struct simplelist_info *info); 287bool simplelist_show_list(struct simplelist_info *info);
268 288
289/* If the list has a pending postponed scheduled announcement, that
290 may become due before the next get_action tmieout. This function
291 adjusts the get_action timeout appropriately. */
292extern int list_do_action_timeout(struct gui_synclist *lists, int timeout);
293/* This one combines a get_action call (with timeout overridden by
294 list_do_action_timeout) with the gui_synclist_do_button call, for
295 convenience. */
296extern bool list_do_action(int context, int timeout,
297 struct gui_synclist *lists, int *action,
298 enum list_wrap wrap);
299
269#endif /* _GUI_LIST_H_ */ 300#endif /* _GUI_LIST_H_ */