From ea664e06476cb572bab2eadbb9c060902a95a34a Mon Sep 17 00:00:00 2001 From: Jonathan Gordon Date: Sat, 3 May 2008 12:30:40 +0000 Subject: Viewported quickscreen (take 2 :D) (FS#8553) - no customization support - no top item - much better use of the screen - deprecates 20 odd lang strings (the QS can now use the regular lang strings and user font) git-svn-id: svn://svn.rockbox.org/rockbox/trunk@17315 a1c6a512-1295-4272-9138-f99709370657 --- apps/gui/gwps.c | 1 + apps/gui/option_select.c | 104 +++++++------- apps/gui/option_select.h | 6 + apps/gui/quickscreen.c | 361 +++++++++++++++++++++++++++++++++-------------- apps/gui/quickscreen.h | 47 ++---- 5 files changed, 330 insertions(+), 189 deletions(-) (limited to 'apps/gui') diff --git a/apps/gui/gwps.c b/apps/gui/gwps.c index 0520357002..2e72813d73 100644 --- a/apps/gui/gwps.c +++ b/apps/gui/gwps.c @@ -57,6 +57,7 @@ #include "ata_idle_notify.h" #include "root_menu.h" #include "backdrop.h" +#include "quickscreen.h" /* currently only on wps_state is needed */ struct wps_state wps_state; diff --git a/apps/gui/option_select.c b/apps/gui/option_select.c index c6136ebf17..43b5fa6ea1 100644 --- a/apps/gui/option_select.c +++ b/apps/gui/option_select.c @@ -60,7 +60,7 @@ static const char *unit_strings[] = /* these two vars are needed so arbitrary values can be added to the TABLE_SETTING settings if the F_ALLOW_ARBITRARY_VALS flag is set */ static int table_setting_oldval = 0, table_setting_array_position = 0; -static char *option_get_valuestring(struct settings_list *setting, +char *option_get_valuestring(struct settings_list *setting, char *buffer, int buf_len, intptr_t temp_var) { @@ -210,56 +210,37 @@ static int option_talk(int selected_item, void * data) } return 0; } -#if 0 -int option_select_next_val(struct settings_list *setting, - intptr_t temp_var) -{ - int val = 0; - if ((setting->flags & F_BOOL_SETTING) == F_BOOL_SETTING) - { - val = (bool)temp_var ? 0 : 1; - } - else if ((setting->flags & F_INT_SETTING) == F_INT_SETTING) - { - struct int_setting *info = setting->int_setting; - val = (int)temp_var + info->step; - if (val > info->max) - val = info->min; - } - else if ((setting->flags & F_T_SOUND) == F_T_SOUND) - { - int setting_id = setting->sound_setting->setting; - int steps = sound_steps(setting_id); - int min = sound_min(setting_id); - int max = sound_max(setting_id); - val = (int)temp_var + steps; - if (val > max) - val = min; - } - else if ((setting->flags & F_CHOICE_SETTING) == F_CHOICE_SETTING) - { - struct choice_setting *info = setting->choice_setting; - val = (int)temp_var; - if (val > info->count) - val = 0; - } - return val; -} -int option_select_prev_val(struct settings_list *setting, - intptr_t temp_var) +#ifdef HAVE_QUICKSCREEN /* only the quickscreen uses this so far */ +void option_select_next_val(struct settings_list *setting, + bool previous, bool apply) { int val = 0; + int *value = setting->setting; if ((setting->flags & F_BOOL_SETTING) == F_BOOL_SETTING) { - val = (bool)temp_var ? 0 : 1; + *(bool*)value = !*(bool*)value; + if (apply && setting->bool_setting->option_callback) + setting->bool_setting->option_callback(*(bool*)value); + return; } else if ((setting->flags & F_INT_SETTING) == F_INT_SETTING) { - struct int_setting *info = setting->int_setting; - val = (int)temp_var - info->step; - if (val < info->min) - val = info->max; + struct int_setting *info = (struct int_setting *)setting->int_setting; + if (!previous) + { + val = *value + info->step; + if (val > info->max) + val = info->min; + } + else + { + val = *value - info->step; + if (val < info->min) + val = info->max; + } + if (apply && info->option_callback) + info->option_callback(*(int*)value); } else if ((setting->flags & F_T_SOUND) == F_T_SOUND) { @@ -267,18 +248,39 @@ int option_select_prev_val(struct settings_list *setting, int steps = sound_steps(setting_id); int min = sound_min(setting_id); int max = sound_max(setting_id); - val = (int)temp_var -+ steps; - if (val < min) - val = max; + if (!previous) + { + val = *value + steps; + if (val >= max) + val = min; + } + else + { + val = *value - steps; + if (val < min) + val = max; + } } else if ((setting->flags & F_CHOICE_SETTING) == F_CHOICE_SETTING) { - struct choice_setting *info = setting->choice_setting; - val = (int)temp_var; - if (val < 0) - val = info->count - 1; + struct choice_setting *info = (struct choice_setting *)setting->choice_setting; + val = *value + 1; + if (!previous) + { + val = *value + 1; + if (val >= info->count) + val = 0; + } + else + { + val = *value - 1; + if (val < 0) + val = info->count-1; + } + if (apply && info->option_callback) + info->option_callback(*(int*)value); } - return val; + *value = val; } #endif diff --git a/apps/gui/option_select.h b/apps/gui/option_select.h index bb609346a3..8b43af1e5a 100644 --- a/apps/gui/option_select.h +++ b/apps/gui/option_select.h @@ -69,4 +69,10 @@ extern void option_select_next(struct option_select * opt); extern void option_select_prev(struct option_select * opt); + +void option_select_next_val(struct settings_list *setting, + bool previous, bool apply); +char *option_get_valuestring(struct settings_list *setting, + char *buffer, int buf_len, + intptr_t temp_var); #endif /* _GUI_OPTION_SELECT_H_ */ diff --git a/apps/gui/quickscreen.c b/apps/gui/quickscreen.c index c2da5879fe..8668e9b085 100644 --- a/apps/gui/quickscreen.c +++ b/apps/gui/quickscreen.c @@ -7,7 +7,7 @@ * \/ \/ \/ \/ \/ * $Id$ * - * Copyright (C) 2005 by Kevin Ferrare + * Copyright (C) 2008 by Jonathan Gordon * * All files in this archive are subject to the GNU General Public License. * See the file COPYING in the source tree root for full license agreement. @@ -17,11 +17,9 @@ * ****************************************************************************/ -#include "quickscreen.h" - -#ifdef HAVE_QUICKSCREEN #include +#include "config.h" #include "system.h" #include "icons.h" #include "textarea.h" @@ -30,109 +28,199 @@ #include "misc.h" #include "statusbar.h" #include "action.h" +#include "settings_list.h" +#include "lang.h" +#include "playlist.h" +#include "dsp.h" +#include "viewport.h" +#include "audio.h" +#include "quickscreen.h" -void gui_quickscreen_init(struct gui_quickscreen * qs, - struct option_select *left_option, - struct option_select *bottom_option, - struct option_select *right_option, - quickscreen_callback callback) -{ - qs->left_option=left_option; - qs->bottom_option=bottom_option; - qs->right_option=right_option; - qs->callback=callback; -} +static struct viewport vps[NB_SCREENS][QUICKSCREEN_ITEM_COUNT]; +static struct viewport vp_icons[NB_SCREENS]; +/* vp_icons will be used like this: + the side icons will be aligned to the top of this vp and to their sides + the bottom icon wil be aligned center and at the bottom of this vp */ -/* - * Draws the quickscreen on a given screen - * - qs : the quickscreen - * - display : the screen to draw on - */ -static void gui_quickscreen_draw(struct gui_quickscreen * qs, struct screen * display) +#define MIN_LINES 4 +#define MAX_NEEDED_LINES 8 +#define CENTER_MARGIN 10 /* pixels between the 2 center items minimum */ +#define CENTER_ICONAREA_WIDTH (CENTER_MARGIN+8*2) + +static void quickscreen_fix_viewports(struct gui_quickscreen *qs, + struct screen *display, + struct viewport *parent) { - const unsigned char *option; - const unsigned char *title; - int w, font_h; - bool statusbar = global_settings.statusbar; -#ifdef HAS_BUTTONBAR - display->has_buttonbar=false; -#endif - gui_textarea_clear(display); - if (display->height / display->char_height < 7) /* we need at leats 7 lines */ + int char_height, i, screen = display->screen_type; + int left_width, right_width, bottom_lines = 3; + unsigned char *s; + int nb_lines = viewport_get_nb_lines(parent); + char_height = parent->height/nb_lines; + + vp_icons[screen] = *parent; + + vps[screen][QUICKSCREEN_BOTTOM] = *parent; + if (nb_lines <= MIN_LINES) /* make the bottom item use 1 line */ + bottom_lines = 1; + else + bottom_lines = 2; + vps[screen][QUICKSCREEN_BOTTOM].height = bottom_lines*char_height; + vps[screen][QUICKSCREEN_BOTTOM].y = parent->y + parent->height - bottom_lines*char_height; + if (nb_lines >= MAX_NEEDED_LINES) { - display->setfont(FONT_SYSFIXED); + vps[screen][QUICKSCREEN_BOTTOM].y -= char_height; } - display->getstringsize("A", NULL, &font_h); - - /* do these calculations once */ - const unsigned int puts_center = display->height/2/font_h; - const unsigned int puts_bottom = display->height/font_h; - const unsigned int putsxy_center = display->height/2; - const unsigned int putsxy_bottom = display->height; - - /* Displays the first line of text */ - option=(unsigned char *)option_select_get_text(qs->left_option); - title=(unsigned char *)qs->left_option->title; - display->puts_scroll(2, puts_center-4+!statusbar, title); - display->puts_scroll(2, puts_center-3+!statusbar, option); - display->mono_bitmap(bitmap_icons_7x8[Icon_FastBackward], 1, - putsxy_center-(font_h*3), 7, 8); - - /* Displays the second line of text */ - option=(unsigned char *)option_select_get_text(qs->right_option); - title=(unsigned char *)qs->right_option->title; - display->getstringsize(title, &w, NULL); - if(w > display->width - 8) + + /* adjust the left/right items widths to fit the screen nicely */ + s = P2STR(ID2P(qs->items[QUICKSCREEN_LEFT]->lang_id)); + left_width = display->getstringsize(s, NULL, NULL); + s = P2STR(ID2P(qs->items[QUICKSCREEN_RIGHT]->lang_id)); + right_width = display->getstringsize(s, NULL, NULL); + nb_lines -= bottom_lines; + + vps[screen][QUICKSCREEN_LEFT] = *parent; + vps[screen][QUICKSCREEN_RIGHT] = *parent; + vps[screen][QUICKSCREEN_LEFT].x = parent->x; + if (nb_lines <= MIN_LINES) + i = 0; + else + i = nb_lines/2; + vps[screen][QUICKSCREEN_LEFT].y = parent->y + (i*char_height); + vps[screen][QUICKSCREEN_RIGHT].y = parent->y + (i*char_height); + if (nb_lines >= 3) + i = 3*char_height; + else + i = nb_lines*char_height; + + vps[screen][QUICKSCREEN_LEFT].height = i; + vps[screen][QUICKSCREEN_RIGHT].height = i; + vp_icons[screen].y = vps[screen][QUICKSCREEN_LEFT].y + (char_height/2); + vp_icons[screen].height = vps[screen][QUICKSCREEN_BOTTOM].y - vp_icons[screen].y; + + if (left_width + right_width > display->width - CENTER_MARGIN) /* scrolling needed */ { - display->puts_scroll(2, puts_center-2+!statusbar, title); - display->mono_bitmap(bitmap_icons_7x8[Icon_FastForward], 1, - putsxy_center-font_h, 7, 8); + int width = (parent->width - CENTER_ICONAREA_WIDTH)/2; + vps[screen][QUICKSCREEN_LEFT].width = width; + vps[screen][QUICKSCREEN_RIGHT].width = width; + vps[screen][QUICKSCREEN_RIGHT].x = parent->x+parent->width - width; + vp_icons[screen].x = parent->x + width; + vp_icons[screen].width = CENTER_ICONAREA_WIDTH; } else { - display->putsxy(display->width - w - 12, putsxy_center-font_h, title); - display->mono_bitmap(bitmap_icons_7x8[Icon_FastForward], - display->width - 8, putsxy_center-font_h, 7, 8); + int width, pad = 0; + if (left_width > right_width) + width = left_width; + else + width = right_width; + width += CENTER_MARGIN; + if (width*2 < parent->width/2) + { + width += parent->width/6; + /* add some padding on the edges */ + pad = CENTER_MARGIN; + } + vps[screen][QUICKSCREEN_LEFT].width = width; + vps[screen][QUICKSCREEN_RIGHT].width = width; + vps[screen][QUICKSCREEN_RIGHT].x = parent->x + parent->width - width; + vp_icons[screen].x = parent->x + width; + if (pad) + { + vp_icons[screen].x += pad; + vps[screen][QUICKSCREEN_LEFT].x += pad; + vps[screen][QUICKSCREEN_RIGHT].x -= pad; + /* need to add the pad to the bottom to make it all centered nicely */ + vps[screen][QUICKSCREEN_BOTTOM].x += pad; + vps[screen][QUICKSCREEN_BOTTOM].width -= pad; + } + vp_icons[screen].width = vps[screen][QUICKSCREEN_RIGHT].x - width; + } - display->getstringsize(option, &w, NULL); - if(w > display->width) - display->puts_scroll(0, puts_center-1+!statusbar, option); - else - display->putsxy(display->width -w-12, putsxy_center, option); - - /* Displays the third line of text */ - option=(unsigned char *)option_select_get_text(qs->bottom_option); - title=(unsigned char *)qs->bottom_option->title; - - display->getstringsize(title, &w, NULL); - if(w > display->width) - display->puts_scroll(0, puts_bottom-4+!statusbar, title); - else - display->putsxy(display->width/2-w/2, putsxy_bottom-(font_h*3), title); +} - display->getstringsize(option, &w, NULL); - if(w > display->width) - display->puts_scroll(0, puts_bottom-3+!statusbar, option); +static void quickscreen_draw_text(char *s, int item, bool title, + struct screen *display, struct viewport *vp) +{ + int nb_lines = viewport_get_nb_lines(vp); + int w, h, line = 0, x=0; + display->getstringsize(s, &w, &h); + + if (nb_lines > 1 && !title) + line = 1; + switch (item) + { + case QUICKSCREEN_BOTTOM: + x = (vp->width - w)/2; + break; + case QUICKSCREEN_LEFT: + x = 0; + break; + case QUICKSCREEN_RIGHT: + x = vp->width - w; + break; + } + if (w>vp->width) + display->puts_scroll(0,line,s); else - display->putsxy(display->width/2-w/2, putsxy_bottom-(font_h*2), option); - display->mono_bitmap(bitmap_icons_7x8[Icon_DownArrow], display->width/2-4, - putsxy_bottom-font_h, 7, 8); - - gui_textarea_update(display); - display->setfont(FONT_UI); + display->putsxy(x, line*h, s); } -/* - * Draws the quickscreen on all available screens - * - qs : the quickscreen - */ -static void gui_syncquickscreen_draw(struct gui_quickscreen * qs) +static void gui_quickscreen_draw(struct gui_quickscreen *qs, + struct screen *display, + struct viewport *parent) { int i; - FOR_NB_SCREENS(i) - gui_quickscreen_draw(qs, &screens[i]); + char buf[MAX_PATH]; + unsigned char *title, *value; + void *setting; + int temp; + display->set_viewport(parent); + display->clear_viewport(); + for (i=0; iitems[i]) + continue; + display->set_viewport(&vps[display->screen_type][i]); + display->scroll_stop(&vps[display->screen_type][i]); + + title = P2STR(ID2P(qs->items[i]->lang_id)); + setting = qs->items[i]->setting; + if ((qs->items[i]->flags & F_BOOL_SETTING) == F_BOOL_SETTING) + temp = *(bool*)setting?1:0; + else + temp = *(int*)setting; + value = option_get_valuestring((struct settings_list*)qs->items[i], buf, MAX_PATH, temp); + + if (vps[display->screen_type][i].height < display->char_height*2) + { + char text[MAX_PATH]; + snprintf(text, MAX_PATH, "%s: %s", title, value); + quickscreen_draw_text(text, i, true, display, &vps[display->screen_type][i]); + } + else + { + quickscreen_draw_text(title, i, true, display, &vps[display->screen_type][i]); + quickscreen_draw_text(value, i, false, display, &vps[display->screen_type][i]); + } + display->update_viewport(); + } + /* draw the icons */ + display->set_viewport(&vp_icons[display->screen_type]); + display->mono_bitmap(bitmap_icons_7x8[Icon_FastForward], + vp_icons[display->screen_type].width - 8, 0, 7, 8); + display->mono_bitmap(bitmap_icons_7x8[Icon_FastBackward], 0, 0, 7, 8); + display->mono_bitmap(bitmap_icons_7x8[Icon_DownArrow], + (vp_icons[display->screen_type].width/2) - 4, + vp_icons[display->screen_type].height - 7, 7, 8); + display->update_viewport(); + + display->set_viewport(parent); + display->update_viewport(); + display->set_viewport(NULL); } + /* * Does the actions associated to the given button if any * - qs : the quickscreen @@ -141,48 +229,60 @@ static void gui_syncquickscreen_draw(struct gui_quickscreen * qs) */ static bool gui_quickscreen_do_button(struct gui_quickscreen * qs, int button) { - + int item; switch(button) { case ACTION_QS_LEFT: - option_select_next(qs->left_option); - return(true); + item = QUICKSCREEN_LEFT; + break; case ACTION_QS_DOWN: - option_select_next(qs->bottom_option); - return(true); + case ACTION_QS_DOWNINV: + item = QUICKSCREEN_BOTTOM; + break; case ACTION_QS_RIGHT: - option_select_next(qs->right_option); - return(true); + item = QUICKSCREEN_RIGHT; + break; - case ACTION_QS_DOWNINV: - option_select_prev(qs->bottom_option); - return(true); + default: + return false; } - return(false); + option_select_next_val((struct settings_list *)qs->items[item], false, true); + return true; } bool gui_syncquickscreen_run(struct gui_quickscreen * qs, int button_enter) { - int button; + int button, i; + struct viewport vp[NB_SCREENS]; + bool changed = false; /* To quit we need either : * - a second press on the button that made us enter * - an action taken while pressing the enter button, * then release the enter button*/ bool can_quit=false; - gui_syncquickscreen_draw(qs); gui_syncstatusbar_draw(&statusbars, true); + FOR_NB_SCREENS(i) + { + screens[i].set_viewport(NULL); + screens[i].stop_scroll(); + viewport_set_defaults(&vp[i], i); + quickscreen_fix_viewports(qs, &screens[i], &vp[i]); + gui_quickscreen_draw(qs, &screens[i], &vp[i]); + } while (true) { button = get_action(CONTEXT_QUICKSCREEN,TIMEOUT_BLOCK); if(default_event_handler(button) == SYS_USB_CONNECTED) return(true); if(gui_quickscreen_do_button(qs, button)) { + changed = true; can_quit=true; - if(qs->callback) + FOR_NB_SCREENS(i) + gui_quickscreen_draw(qs, &screens[i], &vp[i]); + if (qs->callback) qs->callback(qs); - gui_syncquickscreen_draw(qs); } else if(button==button_enter) can_quit=true; @@ -195,8 +295,57 @@ bool gui_syncquickscreen_run(struct gui_quickscreen * qs, int button_enter) gui_syncstatusbar_draw(&statusbars, false); } - return false; + return changed; +} + +bool quick_screen_quick(int button_enter) +{ + struct gui_quickscreen qs; + bool oldshuffle = global_settings.playlist_shuffle; + int oldrepeat = global_settings.repeat_mode; + qs.items[QUICKSCREEN_LEFT] = find_setting(&global_settings.playlist_shuffle, NULL); + qs.items[QUICKSCREEN_RIGHT] = find_setting(&global_settings.repeat_mode, NULL); + qs.items[QUICKSCREEN_BOTTOM] = find_setting(&global_settings.dirfilter, NULL); + qs.callback = NULL; + if (gui_syncquickscreen_run(&qs, button_enter)) + { + settings_save(); + settings_apply(false); + /* make sure repeat/shuffle/any other nasty ones get updated */ + if ( oldrepeat != global_settings.repeat_mode && + (audio_status() & AUDIO_STATUS_PLAY) ) + { + audio_flush_and_reload_tracks(); + } + if (oldshuffle != global_settings.playlist_shuffle + && audio_status() & AUDIO_STATUS_PLAY) + { +#if CONFIG_CODEC == SWCODEC + dsp_set_replaygain(); +#endif + if (global_settings.playlist_shuffle) + playlist_randomise(NULL, current_tick, true); + else + playlist_sort(NULL, true); + } + } + return(0); } -#endif /* HAVE_QUICKSCREEN */ +#ifdef BUTTON_F3 +bool quick_screen_f3(int button_enter) +{ + struct gui_quickscreen qs; + qs.items[QUICKSCREEN_LEFT] = find_setting(&global_settings.scrollbar, NULL); + qs.items[QUICKSCREEN_RIGHT] = find_setting(&global_settings.statusbar, NULL); + qs.items[QUICKSCREEN_BOTTOM] = find_setting(&global_settings.flip_display, NULL); + qs.callback = NULL; + if (gui_syncquickscreen_run(&qs, button_enter)) + { + settings_save(); + settings_apply(false); + } + return(0); +} +#endif /* BUTTON_F3 */ diff --git a/apps/gui/quickscreen.h b/apps/gui/quickscreen.h index 179d619883..47361bd472 100644 --- a/apps/gui/quickscreen.h +++ b/apps/gui/quickscreen.h @@ -27,45 +27,28 @@ #include "option_select.h" #include "screen_access.h" -struct gui_quickscreen; -/* - * Callback function called each time the quickscreen gets modified - * - qs : the quickscreen that did the modification - */ -typedef void (quickscreen_callback)(struct gui_quickscreen * qs); +enum QUICKSCREEN_ITEM { + QUICKSCREEN_LEFT = 0, + QUICKSCREEN_RIGHT, + QUICKSCREEN_BOTTOM, + QUICKSCREEN_ITEM_COUNT, +}; struct gui_quickscreen { - struct option_select *left_option; - struct option_select *bottom_option; - struct option_select *right_option; - quickscreen_callback *callback; + const struct settings_list *items[QUICKSCREEN_ITEM_COUNT]; + void (*callback)(struct gui_quickscreen * qs); /* called after a + item is changed */ }; -/* - * Initializes a quickscreen - * - qs : the quickscreen - * - left_option, bottom_option, right_option : a list of choices - * for each option - * - left_right_title : the 2nd line of the title - * on the left and on the right - * - callback : a callback function called each time the quickscreen - * gets modified - */ -void gui_quickscreen_init(struct gui_quickscreen * qs, - struct option_select *left_option, - struct option_select *bottom_option, - struct option_select *right_option, - quickscreen_callback *callback); +bool gui_syncquickscreen_run(struct gui_quickscreen * qs, int button_enter); + +#ifdef BUTTON_F3 +extern bool quick_screen_f3(int button_enter); +#endif +extern bool quick_screen_quick(int button_enter); -/* - * Runs the quickscreen on all available screens, if button_enter is released, quits - * - qs : the quickscreen - * - button_enter : button pressed at the same time the quickscreen is displayed - * returns : true if usb was connected, false otherwise - */ -bool gui_syncquickscreen_run(struct gui_quickscreen * qs, int button_enter); #endif /*_GUI_QUICK_SCREEN_H_*/ #endif /* HAVE_QUICKSCREEN */ -- cgit v1.2.3