forked from len0rd/rockbox
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
This commit is contained in:
parent
edf3bcf15b
commit
079ad11896
5 changed files with 197 additions and 99 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
212
apps/settings.c
212
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,6 +1851,119 @@ void talk_unit(int unit, int value)
|
|||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
struct value_setting_data* cb_data =
|
||||
(struct value_setting_data*)data;
|
||||
if (cb_data->type == INT && !cb_data->options)
|
||||
{
|
||||
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);
|
||||
}
|
||||
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))
|
||||
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;
|
||||
|
||||
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)
|
||||
{
|
||||
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))
|
||||
{
|
||||
if (global_settings.talk_menu)
|
||||
{
|
||||
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;
|
||||
}
|
||||
else if (button == SETTINGS_OK)
|
||||
{
|
||||
done = true;
|
||||
}
|
||||
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,
|
||||
|
|
@ -1862,36 +1974,10 @@ bool set_int(const unsigned char* string,
|
|||
int max,
|
||||
void (*formatter)(char*, int, int, const char*) )
|
||||
{
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
return false;
|
||||
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
|
||||
|
|
@ -1900,64 +1986,18 @@ bool set_int(const unsigned char* string,
|
|||
|
||||
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
|
||||
|
||||
#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)
|
||||
|
||||
code. */
|
||||
bool set_option(const char* string, void* variable, enum optiontype type,
|
||||
const struct opt_items* options, int numoptions, void (*function)(int))
|
||||
{
|
||||
int button;
|
||||
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 (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))
|
||||
{
|
||||
/* *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));
|
||||
}
|
||||
gui_syncstatusbar_draw(&statusbars, false);
|
||||
if(select.canceled)
|
||||
{
|
||||
/* *variable=oldvalue; */
|
||||
set_type_fromint(type, variable, oldvalue);
|
||||
if ( function )
|
||||
function(type_fromvoidptr(type, variable));
|
||||
return false;
|
||||
}
|
||||
if(default_event_handler(button) == SYS_USB_CONNECTED)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue