Index: apps/gui/newlist.c =================================================================== --- apps/gui/newlist.c (revision 0) +++ apps/gui/newlist.c (revision 0) @@ -0,0 +1,315 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id: list.c 15948 2007-12-17 04:23:34Z jdgordon $ + * + * Copyright (C) 2007 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. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#include "config.h" +#include "lcd.h" +#include "font.h" +#include "button.h" +#include "sprintf.h" +#include "string.h" +#include "settings.h" +#include "kernel.h" +#include "system.h" + +#include "action.h" +#include "screen_access.h" +#include "newlist.h" +#include "scrollbar.h" +#include "statusbar.h" +#include "textarea.h" +#include "lang.h" +#include "sound.h" +#include "misc.h" +#include "talk.h" + +#define SCROLLBAR_WIDTH 6 +#define ICON_PADDING 1 + +#define HAVE_RTL_DRAWING 0 + +/* globals */ +struct viewport title_text, title_icons, list_text, list_icons/*, list_scrollbar */; + +/* TODO list: + callbacks: + text + icon + text color + talk + scrolling: + horizontal: usual + screen move by offset + verticle: line based, screen based + completly independant drawing and movement + framedropping if too many events + */ + +/* should probably be moved somewhere else */ +int viewport_get_nb_lines(struct viewport *vp) +{ + return vp->height/font_get(vp->font)->height; +} +bool list_display_title(struct gui_synclist *list, struct viewport *vp) +{ + return list->title != NULL && viewport_get_nb_lines(vp)>2; +} +/* Draw the list... + internal screen layout: + ----------------- + |TI| title | TI is title icon + ----------------- + | | | | + |S|I| | S - scrollbar + | | | items | I - icons + | | | | + ----------------- + icons/scrollbar can be put on either side of the items if HAVE_RTL_DRAWING == 1 +*/ +bool draw_title(struct screen *display, struct viewport *parent, struct gui_synclist *list) +{ +#if HAVE_RTL_DRAWING + bool icons_on_left = false; +#endif + if (!list_display_title(list, parent)) + return false; + title_text = *parent; + title_text.height = font_get(title_text.font)->height; + if (list->title_icon != Icon_NOICON) + { + title_icons = title_text; + title_icons.width = get_icon_width(display->screen_type) + ICON_PADDING*2; + title_text.width -= title_icons.width; +#if HAVE_RTL_DRAWING + if (icons_on_left) + { +#endif + title_icons.x += ICON_PADDING; + title_text.width -= title_icons.width; + title_text.x += title_icons.width; + +#if HAVE_RTL_DRAWING + } + else + { + title_icons.x = parent->x + parent->width - title_icons.width; + title_text.width -= title_icons.width; + } +#endif + display->set_viewport(&title_icons); + screen_put_icon(display, 0, 0, list->title_icon); + } + display->set_viewport(&title_text); +#ifdef HAVE_LCD_BITMAP + title_text.drawmode = STYLE_DEFAULT; +#ifdef HAVE_LCD_COLOR + if (list->title_color >= 0) + { + title_text.drawmode |= STYLE_COLORED; + title_text.drawmode |= list->title_color; + } +#endif + display->puts_scroll_style_offset(0, 0, list->title, + title_text.drawmode, /*item_offset*/0); +#else + display->puts_scroll(text_pos, 0, gui_list->title); +#endif + return true; +} + +void list_draw(struct screen *display, struct viewport *parent, struct gui_synclist *list) +{ +#if HAVE_RTL_DRAWING + bool icons_on_left = false; +#endif + int start, end, line_height, i; + int icon_width = get_icon_width(display->screen_type) + ICON_PADDING*2; + bool show_cursor = !global_settings.cursor_style && list->show_selection_marker; +#ifdef HAVE_LCD_COLOR + unsigned char cur_line = 0; +#endif + line_height = font_get(parent->font)->height; + display->set_viewport(parent); + display->clear_viewport(); + list_text = *parent; + if (draw_title(display, parent, list)) + { + list_text.y += line_height; + list_text.height -= line_height; + /* shift everything right a bit... */ + list_text.width -= SCROLLBAR_WIDTH; + list_text.x += SCROLLBAR_WIDTH; + } + + start = list->start_item[display->screen_type]; + end = start + viewport_get_nb_lines(&list_text); + + /* draw the scrollbar if its needed */ + if (viewport_get_nb_lines(&list_text) < list->nb_items) + { + struct viewport vp; + vp = list_text; + vp.width = SCROLLBAR_WIDTH; + list_text.width -= SCROLLBAR_WIDTH; + +#if HAVE_RTL_DRAWING + if (icons_on_left) + { + vp.x = parent->x; + } + else + vp.x = parent->x+parent->width - SCROLLBAR_WIDTH; +#else + vp.x = parent->x; +#endif + display->set_viewport(&vp); + gui_scrollbar_draw(display, 0, 0, SCROLLBAR_WIDTH-1, + vp.height, list->nb_items, + list->start_item[display->screen_type], + list->start_item[display->screen_type] + end-start, VERTICAL); + } + /* setup icon placement */ + list_icons = list_text; + if (list->callback_get_item_icon != NULL || show_cursor) + { + if (list->callback_get_item_icon != NULL && show_cursor) + list_icons.width = icon_width*2; + else + list_icons.width = icon_width; + list_text.width -= list_icons.width; +#if HAVE_RTL_DRAWING + if (icons_on_left) +#endif + list_text.x += list_icons.width; + } + + for (i=start; inb_items; i++) + { + /* do the text */ + unsigned char *s; + char entry_buffer[MAX_PATH]; + unsigned char *entry_name; + s = list->callback_get_item_name(i, list->data, entry_buffer); + entry_name = P2STR(s); + display->set_viewport(&list_text); +#ifdef HAVE_LCD_BITMAP + list_text.drawmode = STYLE_DEFAULT; + /* position the string at the correct offset place + int item_width,h; + display->getstringsize(entry_name, &item_width, &h); + item_offset = gui_list_get_item_offset(gui_list, item_width, + text_pos, display); + */ +#endif + +#ifdef HAVE_LCD_COLOR + /* if the list has a color callback */ + if (list->callback_get_item_color) + { + int color = list->callback_get_item_color(i, list->data); + /* if color selected */ + if (color >= 0) + { + list_text.drawmode |= STYLE_COLORED|color; + } + } +#endif + + if(list->show_selection_marker && + i >= list->selected_item && + i < list->selected_item + list->selected_size) + {/* The selected item must be displayed scrolling */ +#ifdef HAVE_LCD_BITMAP + if (global_settings.cursor_style == 1 +#ifdef HAVE_REMOTE_LCD + || display->screen_type == SCREEN_REMOTE +#endif + ) + { + /* Display inverted-line-style */ + list_text.drawmode |= STYLE_INVERT; + } +#ifdef HAVE_LCD_COLOR + else if (global_settings.cursor_style == 2) + { + /* Display colour line selector */ + list_text.drawmode |= STYLE_COLORBAR; + } + else if (global_settings.cursor_style == 3) + { + /* Display gradient line selector */ + list_text.drawmode = STYLE_GRADIENT; + + /* Make the lcd driver know how many lines the gradient should + cover and current line number */ + /* number of selected lines */ + list_text.drawmode |= NUMLN_PACK(list->selected_size); + /* current line number, zero based */ + list_text.drawmode |= CURLN_PACK(cur_line); + cur_line++; + } +#endif +#if 0 + /* if the text is smaller than the viewport size */ + if (item_offset > item_width - (display->width - text_pos)) + { + /* don't scroll */ + display->puts_style_offset(0, i-start, entry_name, + style, item_offset); + } + else + { + display->puts_scroll_style_offset(0, i-start, entry_name, + style, item_offset); + } +#endif + + display->puts_scroll_style_offset(0, i-start, entry_name, + list_text.drawmode, 0); + } + else + display->puts_style_offset(0, i-start, entry_name, + list_text.drawmode, 0); +#else + display->puts_scroll(0, i-start, entry_name); +#endif + /* do the icon */ + if (list->callback_get_item_icon) + { + display->set_viewport(&list_icons); + screen_put_icon(display, show_cursor?1:0/*FIXME when RTL drawing is added */, (i-start), + list->callback_get_item_icon(i, list->data)); + if (show_cursor && i >= list->selected_item && + i < list->selected_item + list->selected_size) + { + screen_put_icon(display, 0, line_height*(i-start), Icon_Cursor); + } + } + else if (show_cursor && i >= list->selected_item && + i < list->selected_item + list->selected_size) + { + display->set_viewport(&list_icons); + screen_put_icon(display, 0, (i-start), Icon_Cursor); + } + } + + display->set_viewport(parent); + display->update_viewport(); + display->set_viewport(NULL); +} + + Index: apps/gui/newlist.h =================================================================== --- apps/gui/newlist.h (revision 0) +++ apps/gui/newlist.h (revision 0) @@ -0,0 +1,303 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id: list.h 15947 2007-12-17 02:37:21Z jdgordon $ + * + * Copyright (C) 2005 by Kevin Ferrare + * + * 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. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#ifndef _GUI_LIST_H_ +#define _GUI_LIST_H_ + +#include "config.h" +#include "icon.h" +#include "screen_access.h" + +enum list_wrap { + LIST_WRAP_ON = 0, + LIST_WRAP_OFF, + LIST_WRAP_UNLESS_HELD, +}; + +/* + * The gui_list is based on callback functions, if you want the list + * to display something you have to provide it a function that + * tells it what to display. + * There are three callback function : + * one to get the text, one to get the icon and one to get the color + */ + +/* + * Icon callback + * - selected_item : an integer that tells the number of the item to display + * - data : a void pointer to the data you gave to the list when you + * initialized it + * Returns a pointer to the icon, the value inside it is used to display the + * icon after the function returns. + * Note : we use the ICON type because the real type depends of the plateform + */ +typedef enum themable_icons list_get_icon(int selected_item, void * data); +/* + * Text callback + * - selected_item : an integer that tells the number of the item to display + * - data : a void pointer to the data you gave to the list when you + * initialized it + * - buffer : a buffer to put the resulting text on it + * (The content of the buffer may not be used by the list, we use + * the return value of the function in all cases to avoid filling + * a buffer when it's not necessary) + * Returns a pointer to a string that contains the text to display + */ +typedef char * list_get_name(int selected_item, void * data, char * buffer); +/* + * Voice callback + * - selected_item : an integer that tells the number of the item to speak + * - data : a void pointer to the data you gave to the list when you + * initialized it + * Returns an integer, 0 means success, ignored really... + */ +typedef int list_speak_item(int selected_item, void * data); +#ifdef HAVE_LCD_COLOR +/* + * Color callback + * - selected_item : an integer that tells the number of the item to display + * - data : a void pointer to the data you gave to the list when you + * initialized it + * Returns an int with the lower 16 bits representing the color to display the + * selected item, negative value for default coloring. + */ +typedef int list_get_color(int selected_item, void * data); +#endif + +struct gui_synclist +{ + /* defines wether the list should stop when reaching the top/bottom + * or should continue (by going to bottom/top) */ + bool limit_scroll; + /* wether the text of the whole items of the list have to be + * scrolled or only for the selected item */ + bool scroll_all; + + int nb_items; + int selected_item; + int start_item[NB_SCREENS]; /* the item that is displayed at the top of the screen */ + /* the number of lines that are selected at the same time */ + int selected_size; + /* These are used to calculate how much of the screen content we need + to redraw. */ + int last_displayed_selected_item; + int last_displayed_start_item[NB_SCREENS]; +#ifdef HAVE_LCD_BITMAP + int offset_position[NB_SCREENS]; /* the list's screen scroll placement in pixels */ +#endif + /* Cache the width of the title string in pixels/characters */ + int title_width; + long scheduled_talk_tick, last_talked_tick; + + list_get_icon *callback_get_item_icon; + list_get_name *callback_get_item_name; + list_speak_item *callback_speak_item; + + /* The data that will be passed to the callback function YOU implement */ + void * data; + /* The optional title, set to NULL for none */ + char * title; + /* Optional title icon */ + enum themable_icons title_icon; + bool show_selection_marker; /* set to true by default */ + +#ifdef HAVE_LCD_COLOR + int title_color; + list_get_color *callback_get_item_color; +#endif +}; + +/* + * Sets the numbers of items the list can currently display + * note that the list's context like the currently pointed item is resetted + * - gui_list : the list structure + * - nb_items : the numbers of items you want + */ +#define gui_list_set_nb_items(gui_list, nb) \ + (gui_list)->nb_items = nb + +/* + * Returns the numbers of items currently in the list + * - gui_list : the list structure + */ +#define gui_list_get_nb_items(gui_list) \ + (gui_list)->nb_items + +/* + * Sets the icon callback function + * - gui_list : the list structure + * - _callback : the callback function + */ +#define gui_list_set_icon_callback(gui_list, _callback) \ + (gui_list)->callback_get_item_icon=_callback + +/* + * Sets the voice callback function + * - gui_list : the list structure + * - _callback : the callback function + */ +#define gui_list_set_voice_callback(gui_list, _callback) \ + (gui_list)->callback_speak_item=_callback + +#ifdef HAVE_LCD_COLOR +/* + * Sets the color callback function + * - gui_list : the list structure + * - _callback : the callback function + */ +#define gui_list_set_color_callback(gui_list, _callback) \ + (gui_list)->callback_get_item_color=_callback +#endif + +/* + * Gives the position of the selected item + * - gui_list : the list structure + * Returns the position + */ +#define gui_list_get_sel_pos(gui_list) \ + (gui_list)->selected_item + + +#ifdef HAVE_LCD_BITMAP +/* parse global setting to static int */ +extern void gui_list_screen_scroll_step(int ofs); + +/* parse global setting to static bool */ +extern void gui_list_screen_scroll_out_of_view(bool enable); +#endif /* HAVE_LCD_BITMAP */ +/* + * Tells the list wether it should stop when reaching the top/bottom + * or should continue (by going to bottom/top) + * - gui_list : the list structure + * - scroll : + * - true : stops when reaching top/bottom + * - false : continues to go to bottom/top when reaching top/bottom + */ +#define gui_list_limit_scroll(gui_list, scroll) \ + (gui_list)->limit_scroll=scroll + + +extern void gui_synclist_init( + struct gui_synclist * lists, + list_get_name callback_get_item_name, + void * data, + bool scroll_all, + int selected_size + ); +extern void gui_synclist_set_nb_items(struct gui_synclist * lists, int nb_items); +extern void gui_synclist_set_icon_callback(struct gui_synclist * lists, list_get_icon icon_callback); +extern void gui_synclist_set_voice_callback(struct gui_synclist * lists, list_speak_item voice_callback); +extern void gui_synclist_speak_item(struct gui_synclist * lists); +extern int gui_synclist_get_nb_items(struct gui_synclist * lists); + +extern int gui_synclist_get_sel_pos(struct gui_synclist * lists); + +extern void gui_synclist_draw(struct gui_synclist * lists); +extern void gui_synclist_select_item(struct gui_synclist * lists, + int item_number); +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, + int icon); +extern void gui_synclist_hide_selection_marker(struct gui_synclist *lists, + bool hide); +/* + * Do the action implied by the given button, + * returns true if the action was handled. + * NOTE: *action may be changed regardless of return value + */ +extern bool gui_synclist_do_button(struct gui_synclist * lists, + unsigned *action, + enum list_wrap); + +/* If the list has a pending postponed scheduled announcement, that + may become due before the next get_action tmieout. This function + adjusts the get_action timeout appropriately. */ +extern int list_do_action_timeout(struct gui_synclist *lists, int timeout); +/* This one combines a get_action call (with timeout overridden by + list_do_action_timeout) with the gui_synclist_do_button call, for + convenience. */ +extern bool list_do_action(int context, int timeout, + struct gui_synclist *lists, int *action, + enum list_wrap wrap); + + +/** Simplelist implementation. + USe this if you dont need to reimplement the list code, + and just need to show a list + **/ + +struct simplelist_info { + char *title; /* title to show on the list */ + int count; /* number of items in the list, each item is selection_size high */ + char selection_size; /* list selection size, usually 1 */ + bool hide_selection; + bool scroll_all; + int timeout; + int start_selection; /* the item to select when the list is first displayed */ + int (*action_callback)(int action, struct gui_synclist *lists); /* can be NULL */ + /* action_callback notes: + action == the action pressed by the user + _after_ gui_synclist_do_button returns. + lists == the lists sturct so the callack can get selection and count etc. */ + list_get_icon *get_icon; /* can be NULL */ + list_get_name *get_name; /* NULL if you're using simplelist_addline() */ + list_speak_item *get_talk; /* can be NULL to not speak */ + void *callback_data; /* data for callbacks */ +}; + +#define SIMPLELIST_MAX_LINES 32 +#define SIMPLELIST_MAX_LINELENGTH 32 + +/** The next three functions are used if the text is mostly static. + These should be called in the action callback for the list. + **/ +/* set the amount of lines shown in the list + Only needed if simplelist_info.get_name == NULL */ +void simplelist_set_line_count(int lines); +/* get the current amount of lines shown */ +int simplelist_get_line_count(void); +/* add/edit a line in the list. + if line_number > number of lines shown it adds the line, else it edits the line */ +#define SIMPLELIST_ADD_LINE (SIMPLELIST_MAX_LINES+1) +void simplelist_addline(int line_number, const char *fmt, ...); + +/* setup the info struct. members not setup in this function need to be assigned manually + members set in this function: + info.selection_size = 1; + info.hide_selection = false; + info.scroll_all = false; + info.action_callback = NULL; + info.get_icon = NULL; + info.get_name = NULL; + info.get_voice = NULL; + info.timeout = HZ/10; + info.start_selection = 0; +*/ +void simplelist_info_init(struct simplelist_info *info, char* title, + int count, void* data); + +/* show a list. + if list->action_callback != NULL it is called with the action ACTION_REDRAW + before the list is dislplayed for the first time */ +bool simplelist_show_list(struct simplelist_info *info); + +#endif /* _GUI_LIST_H_ */ Index: apps/gui/list.c =================================================================== --- apps/gui/list.c (revision 16043) +++ apps/gui/list.c (working copy) @@ -56,11 +56,28 @@ #endif static struct gui_synclist* last_list_displayed; -#define SHOW_LIST_TITLE ((gui_list->title != NULL) && \ - (display->nb_lines > 2)) +/*#define SHOW_LIST_TITLE ((gui_list->title != NULL) && \ + (display->nb_lines > 2)) */ static void gui_list_select_at_offset(struct gui_synclist * gui_list, int offset); +static struct viewport parent = +{ + .x = 10, + .y = 10, + .width = LCD_WIDTH-10, + .height = (LCD_HEIGHT-8)/4-10, + .font = FONT_UI, + .drawmode = DRMODE_SOLID, + .xmargin = 0, + .ymargin = 0, + .fg_pattern = LCD_DEFAULT_BG, + .bg_pattern = LCD_DEFAULT_FG, + .lss_pattern = LCD_DEFAULT_BG, + .lse_pattern = LCD_DEFAULT_BG, + .lst_pattern = LCD_DEFAULT_BG, +}; +void list_draw(struct screen *display, struct viewport *parent, struct gui_synclist *list); /* * Initializes a scrolling list @@ -91,6 +108,7 @@ #ifdef HAVE_LCD_BITMAP gui_list->offset_position[i] = 0; #endif + gui_list->parent[i] = &parent; /* fix properly! */ } gui_list->limit_scroll = false; gui_list->data=data; @@ -148,7 +166,7 @@ return item_offset; } #endif - +#if 0 /* * Draws the list on the attached screen * - gui_list : the list structure @@ -460,29 +478,33 @@ gui_textarea_update(display); } - +#endif /* * Force a full screen update. */ + void gui_synclist_draw(struct gui_synclist *gui_list) { int i; FOR_NB_SCREENS(i) { last_list_displayed = NULL; - gui_list_draw_smart(gui_list, &screens[i]); + list_draw(&screens[i], &parent, gui_list); + //gui_list_draw_smart(gui_list, &screens[i]); } } +int viewport_get_nb_lines(struct viewport *vp); +bool list_display_title(struct gui_synclist *list, struct viewport *vp); - /* sets up the list so the selection is shown correctly on the screen */ static void gui_list_put_selection_on_screen(struct gui_synclist * gui_list, enum screen_type screen) { - struct screen *display = &screens[screen]; - int nb_lines = display->nb_lines - SHOW_LIST_TITLE; + int nb_lines = viewport_get_nb_lines(gui_list->parent[screen]); int difference = gui_list->selected_item - gui_list->start_item[screen]; + if (list_display_title(gui_list, gui_list->parent[screen])) + nb_lines--; /* edge case,, selected last item */ if (gui_list->selected_item == gui_list->nb_items -1) @@ -579,8 +601,9 @@ int i, nb_lines, screen_top; FOR_NB_SCREENS(i) { - struct screen *display = &screens[i]; - nb_lines = display->nb_lines - SHOW_LIST_TITLE; + nb_lines = viewport_get_nb_lines(gui_list->parent[i]); + if (list_display_title(gui_list, gui_list->parent[i])) + nb_lines--; if (offset > 0) { screen_top = gui_list->nb_items-nb_lines; Index: apps/gui/list.h =================================================================== --- apps/gui/list.h (revision 16043) +++ apps/gui/list.h (working copy) @@ -123,6 +123,7 @@ int title_color; list_get_color *callback_get_item_color; #endif + struct viewport *parent[NB_SCREENS]; }; /* Index: apps/SOURCES =================================================================== --- apps/SOURCES (revision 16043) +++ apps/SOURCES (working copy) @@ -53,6 +53,7 @@ gui/icon.c #endif gui/list.c +gui/newlist.c gui/option_select.c gui/quickscreen.c gui/scrollbar.c