From 079ad11896d68f16f23880f4de869bbb47617c19 Mon Sep 17 00:00:00 2001 From: Dave Chapman Date: Tue, 15 Aug 2006 08:14:46 +0000 Subject: Patch #5795 from Jonathan Gordon - change the settings display for enumerations and integers to use the list widget. Patch also adds an optional title to the list widget which is used in the settings. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@10576 a1c6a512-1295-4272-9138-f99709370657 --- apps/SOURCES | 1 - apps/gui/list.c | 68 ++++++++++++++--- apps/gui/list.h | 8 +- apps/settings.c | 212 ++++++++++++++++++++++++++++++--------------------- apps/settings_menu.c | 7 +- 5 files changed, 197 insertions(+), 99 deletions(-) (limited to 'apps') diff --git a/apps/SOURCES b/apps/SOURCES index 7580c5e3f6..3548980f28 100644 --- a/apps/SOURCES +++ b/apps/SOURCES @@ -39,7 +39,6 @@ gui/logo.c gui/option_select.c gui/quickscreen.c gui/scrollbar.c -gui/select.c gui/splash.c gui/statusbar.c gui/textarea.c diff --git a/apps/gui/list.c b/apps/gui/list.c index ebb915e0bc..98b0148c14 100644 --- a/apps/gui/list.c +++ b/apps/gui/list.c @@ -22,6 +22,7 @@ #include "font.h" #include "button.h" #include "sprintf.h" +#include "string.h" #include "settings.h" #include "kernel.h" @@ -66,6 +67,7 @@ void gui_list_init(struct gui_list * gui_list, #endif gui_list->scroll_all=scroll_all; gui_list->selected_size=selected_size; + gui_list->title = NULL; } void gui_list_set_display(struct gui_list * gui_list, struct screen * display) @@ -117,6 +119,8 @@ void gui_list_put_selection_in_screen(struct gui_list * gui_list, #endif gui_textarea_update_nblines(gui_list->display); int nb_lines=gui_list->display->nb_lines; + if (gui_list->title) + nb_lines--; if(put_from_end) { int list_end = gui_list->selected_item + SCROLL_LIMIT; @@ -147,13 +151,28 @@ void gui_list_draw(struct gui_list * gui_list) bool draw_icons = (gui_list->callback_get_item_icon != NULL ) ; bool draw_cursor; int i; + int lines; /* Adjust the position of icon, cursor, text */ + if (gui_list->title) + { + i = 1; + lines = display->nb_lines - 1; + } + else + { + i = 0; + lines = display->nb_lines; + } #ifdef HAVE_LCD_BITMAP display->setfont(FONT_UI); gui_textarea_update_nblines(display); - bool draw_scrollbar = (global_settings.scrollbar && - display->nb_lines < gui_list->nb_items); + bool draw_scrollbar; + + + draw_scrollbar = (global_settings.scrollbar && + lines < gui_list->nb_items); + draw_cursor = !global_settings.invert_cursor; text_pos = 0; /* here it's in pixels */ if(draw_scrollbar) @@ -182,11 +201,12 @@ void gui_list_draw(struct gui_list * gui_list) screen_set_xmargin(display, text_pos); #endif - for(i = 0;i < display->nb_lines;i++) + + while (i < display->nb_lines) { char entry_buffer[MAX_PATH]; unsigned char *entry_name; - int current_item = gui_list->start_item + i; + int current_item = gui_list->start_item + (gui_list->title?i-1:i); /* When there are less items to display than the * current available space on the screen, we stop*/ @@ -268,19 +288,31 @@ void gui_list_draw(struct gui_list * gui_list) if(icon) screen_put_iconxy(display, icon_pos, i, icon); } + i++; } -#ifdef HAVE_LCD_BITMAP + +#ifdef HAVE_LCD_BITMAP /* Draw the scrollbar if needed*/ if(draw_scrollbar) { int y_start = gui_textarea_get_ystart(display); + if (gui_list->title) + y_start += display->char_height; int scrollbar_y_end = display->char_height * - display->nb_lines + y_start; + lines + y_start; gui_scrollbar_draw(display, 0, y_start, SCROLLBAR_WIDTH-1, scrollbar_y_end - y_start, gui_list->nb_items, gui_list->start_item, gui_list->start_item + display->nb_lines, VERTICAL); } + if (gui_list->title) + { + int start = ((display->width/display->char_width) - strlen(gui_list->title))/2; + display->puts(start, 0, gui_list->title); + } +#else /* char cell display */ + if (gui_list->title) + display->puts(0, 0, gui_list->title); /* dont center title */ #endif gui_textarea_update(display); } @@ -307,9 +339,11 @@ void gui_list_select_next(struct gui_list * gui_list) { gui_list->selected_item+=gui_list->selected_size; int nb_lines = gui_list->display->nb_lines; + if (gui_list->title) + nb_lines--; int item_pos = gui_list->selected_item - gui_list->start_item; int end_item = gui_list->start_item + nb_lines; - + if (global_settings.scroll_paginated) { /* When we reach the bottom of the list @@ -336,7 +370,9 @@ void gui_list_select_previous(struct gui_list * gui_list) { if( gui_list->selected_item-gui_list->selected_size < 0 ) { - int nb_lines = gui_list->display->nb_lines; + int nb_lines = gui_list->display->nb_lines; + if (gui_list->title) + nb_lines--; if(gui_list->limit_scroll) return; /* we have aleady reached the top of the list */ @@ -384,6 +420,8 @@ void gui_list_select_next_page(struct gui_list * gui_list, int nb_lines) } else { + if (gui_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) @@ -402,6 +440,8 @@ void gui_list_select_previous_page(struct gui_list * gui_list, int nb_lines) } else { + if (gui_list->title) + nb_lines--; nb_lines-=nb_lines%gui_list->selected_size; gui_list->selected_item -= nb_lines; if(gui_list->selected_item < 0) @@ -473,7 +513,10 @@ void gui_list_screen_scroll_out_of_view(bool enable) offset_out_of_view = false; } #endif /* HAVE_LCD_BITMAP */ - +void gui_list_set_title(struct gui_list *gui_list , char* title) +{ + gui_list->title = title; +} /* * Synchronized lists stuffs */ @@ -590,6 +633,13 @@ void gui_synclist_limit_scroll(struct gui_synclist * lists, bool scroll) gui_list_limit_scroll(&(lists->gui_list[i]), scroll); } +void gui_synclist_set_title(struct gui_synclist * lists, char* title) +{ + int i; + FOR_NB_SCREENS(i) + gui_list_set_title(&(lists->gui_list[i]), title); +} + void gui_synclist_flash(struct gui_synclist * lists) { int i; diff --git a/apps/gui/list.h b/apps/gui/list.h index f0a6d3f32c..447e0d832d 100644 --- a/apps/gui/list.h +++ b/apps/gui/list.h @@ -168,6 +168,8 @@ struct gui_list int selected_size; /* The data that will be passed to the callback function YOU implement */ void * data; + /* The optional title, set to NULL for none */ + char *title; }; /* @@ -332,7 +334,10 @@ extern void gui_list_del_item(struct gui_list * gui_list); */ extern void gui_list_flash(struct gui_list * gui_list); - +/* + * Set the title of the list, setting to NULL disables the title + */ +extern void gui_list_set_title(struct gui_list *gui_list , char* title); /* * This part handles as many lists as there are connected screens * (the api is similar to the ones above) @@ -373,6 +378,7 @@ extern void gui_synclist_add_item(struct gui_synclist * lists); extern void gui_synclist_del_item(struct gui_synclist * lists); extern void gui_synclist_limit_scroll(struct gui_synclist * lists, bool scroll); extern void gui_synclist_flash(struct gui_synclist * lists); +extern void gui_synclist_set_title(struct gui_synclist * lists, char* title); void gui_synclist_scroll_right(struct gui_synclist * lists); void gui_synclist_scroll_left(struct gui_synclist * lists); diff --git a/apps/settings.c b/apps/settings.c index bb550ac929..1f8f15be1e 100644 --- a/apps/settings.c +++ b/apps/settings.c @@ -68,7 +68,6 @@ #include "sound.h" #include "rbunicode.h" #include "dircache.h" -#include "select.h" #include "statusbar.h" #include "splash.h" #include "list.h" @@ -1852,113 +1851,154 @@ void talk_unit(int unit, int value) } } -bool set_int(const unsigned char* string, - const char* unit, - int voice_unit, - int* variable, - void (*function)(int), - int step, - int min, - int max, - void (*formatter)(char*, int, int, const char*) ) +struct value_setting_data { + enum optiontype type; + /* used for "value" settings.. */ + int max; + int step; + int voice_unit; + const char * unit; + void (*formatter)(char* dest, int dest_length, + int variable, const char* unit); + /* used for BOOL and "choice" settings */ + struct opt_items* options; +}; + +char * value_setting_get_name_cb(int selected_item,void * data, char *buffer) { - int button; - int oldvalue=*variable; - struct gui_select select; - gui_select_init_numeric(&select, (char *)string, *variable, min, max, step, unit, - formatter); - gui_syncselect_draw(&select); - talk_unit(voice_unit, *variable); - while (!select.validated) + struct value_setting_data* cb_data = + (struct value_setting_data*)data; + if (cb_data->type == INT && !cb_data->options) { - button = button_get_w_tmo(HZ/2); - if(gui_syncselect_do_button(&select, button)) - { - *variable=select.options.option; - gui_syncselect_draw(&select); - talk_unit(voice_unit, *variable); - if ( function ) - function(*variable); - } - gui_syncstatusbar_draw(&statusbars, false); - if(select.canceled) - { - *variable=oldvalue; - if ( function ) - function(*variable); - return false; - } - if(default_event_handler(button) == SYS_USB_CONNECTED) - return true; + int item = cb_data->max -(selected_item*cb_data->step); + if (cb_data->formatter) + cb_data->formatter(buffer, MAX_PATH,item,cb_data->unit); + else + snprintf(buffer, MAX_PATH,"%d %s",item,cb_data->unit); } - return false; -} - -/* NOTE: the 'type' parameter specifies the actual type of the variable - that 'variable' points to. not the value within. Only variables with - type 'bool' should use parameter BOOL. - - The type separation is necessary since int and bool are fundamentally - different and bit-incompatible types and can not share the same access - code. */ - -#define set_type_fromint(type, dest, value) \ - if (type == INT) \ - *(int *)dest=value; \ - else \ - *(bool *)dest=value?true:false - + else strcpy(buffer,P2STR(cb_data->options[selected_item].string)); + return buffer; +} #define type_fromvoidptr(type, value) \ (type == INT)? \ (int)(*(int*)(value)) \ : \ (bool)(*(bool*)(value)) - -#define get_int_fromtype(type, var) \ - (type == INT)?*(int *)var:(*(bool *)var?1:0) - -bool set_option(const char* string, void* variable, enum optiontype type, - const struct opt_items* options, int numoptions, void (*function)(int)) +bool do_set_setting(const unsigned char* string, void *variable, + int nb_items,int selected, + struct value_setting_data *cb_data, + void (*function)(int)) { int button; + bool done = false; + struct gui_synclist lists; int oldvalue; - /* oldvalue=*variable; */ - oldvalue=get_int_fromtype(type, variable); - struct gui_select select; - gui_select_init_items(&select, string, oldvalue, options, numoptions); - gui_syncselect_draw(&select); + + if (cb_data->type == INT) + oldvalue = *(int*)variable; + else oldvalue = *(bool*)variable; + + gui_synclist_init(&lists,value_setting_get_name_cb,(void*)cb_data,false,1); + gui_synclist_set_title(&lists, (char*)string); + gui_synclist_set_icon_callback(&lists,NULL); + gui_synclist_set_nb_items(&lists,nb_items); + gui_synclist_limit_scroll(&lists,true); + gui_synclist_select_item(&lists, selected); + if (global_settings.talk_menu) - talk_id(options[select.options.option].voice_id, true); - - while ( !select.validated ) { - gui_syncstatusbar_draw(&statusbars, true); - button = button_get_w_tmo(HZ/2); - select.options.limit_loop = false; - if(gui_syncselect_do_button(&select, button)) + if (cb_data->type == INT && !cb_data->options) + talk_unit(cb_data->voice_unit, *(int*)variable); + else talk_id(cb_data->options[selected].voice_id, false); + } + + gui_synclist_draw(&lists); + while (!done) + { + + button = button_get(true); + if (button == BUTTON_NONE) + continue; + + if (gui_synclist_do_button(&lists,button)) { - /* *variable = gui_select_get_selected(&select) */ - set_type_fromint(type, variable, select.options.option); - gui_syncselect_draw(&select); if (global_settings.talk_menu) - talk_id(options[select.options.option].voice_id, false); - if ( function ) - function(type_fromvoidptr(type, variable)); + { + int value; + if (cb_data->type == INT && !cb_data->options) + { + value = cb_data->max - + gui_synclist_get_sel_pos(&lists)*cb_data->step; + talk_unit(cb_data->voice_unit, value); + } + else + { + value = gui_synclist_get_sel_pos(&lists); + talk_id(cb_data->options[value].voice_id, false); + } + } + if (cb_data->type == INT && !cb_data->options) + *(int*)variable = cb_data->max - + gui_synclist_get_sel_pos(&lists)*cb_data->step; + else if (cb_data->type == BOOL) + *(bool*)variable = gui_synclist_get_sel_pos(&lists) ? true : false; + else *(int*)variable = gui_synclist_get_sel_pos(&lists); + } + else if (button == SETTINGS_CANCEL) + { + gui_syncsplash(HZ/2,true,str(LANG_MENU_SETTING_CANCEL)); + if (cb_data->type == INT) + *(int*)variable = oldvalue; + else *(bool*)variable = (bool)oldvalue; + done = true; } - gui_syncstatusbar_draw(&statusbars, false); - if(select.canceled) + else if (button == SETTINGS_OK) { - /* *variable=oldvalue; */ - set_type_fromint(type, variable, oldvalue); - if ( function ) - function(type_fromvoidptr(type, variable)); - return false; + done = true; } - if(default_event_handler(button) == SYS_USB_CONNECTED) + else if(default_event_handler(button) == SYS_USB_CONNECTED) return true; + gui_syncstatusbar_draw(&statusbars, false); + if ( function ) + function(type_fromvoidptr(cb_data->type,variable)); } return false; } +bool set_int(const unsigned char* string, + const char* unit, + int voice_unit, + int* variable, + void (*function)(int), + int step, + int min, + int max, + void (*formatter)(char*, int, int, const char*) ) +{ + struct value_setting_data data = { + INT,max, step, voice_unit,unit,formatter,NULL }; + return do_set_setting(string,variable,(max-min)/step + 1, + (max-*variable)/step, &data,function); +} + +/* NOTE: the 'type' parameter specifies the actual type of the variable + that 'variable' points to. not the value within. Only variables with + type 'bool' should use parameter BOOL. + + The type separation is necessary since int and bool are fundamentally + different and bit-incompatible types and can not share the same access + code. */ +bool set_option(const char* string, void* variable, enum optiontype type, + const struct opt_items* options, int numoptions, void (*function)(int)) +{ + struct value_setting_data data = { + type,0, 0, 0,NULL,NULL,(struct opt_items*)options }; + int selected; + if (type == BOOL) + selected = *(bool*)variable ? 1 : 0; + else selected = *(int*)variable; + return do_set_setting(string,variable,numoptions, + selected, &data,function); +} #ifdef HAVE_RECORDING /* This array holds the record timer interval lengths, in seconds */ diff --git a/apps/settings_menu.c b/apps/settings_menu.c index 93c809d007..6a11e723b1 100644 --- a/apps/settings_menu.c +++ b/apps/settings_menu.c @@ -351,11 +351,14 @@ static bool flip_display(void) */ static bool invert_cursor(void) { - return set_bool_options(str(LANG_INVERT_CURSOR), - &global_settings.invert_cursor, + bool type = global_settings.invert_cursor; + bool rc = set_bool_options(str(LANG_INVERT_CURSOR), + &type, STR(LANG_INVERT_CURSOR_BAR), STR(LANG_INVERT_CURSOR_POINTER), NULL); + global_settings.invert_cursor = type; + return rc; } #ifdef HAVE_LCD_COLOR -- cgit v1.2.3