From 3d0317a273a99f277d88c491181ba220db9dd2b0 Mon Sep 17 00:00:00 2001 From: Jonathan Gordon Date: Sun, 11 Sep 2011 10:44:17 +0000 Subject: Rework how the skin gets the list item text to save some ram. Also allow the %LI and %LT tags to take 2 optional parameters to get a different items text/icon: %LT(offset, nowrap) - get the text for the "being drawn"+offset item (offset being + or -). if the second param is "nowrap" (Without quotes) the text will be blank if the item would need to wrap. Same for the icon e.g: %LT(-1) %LT << %LT(1, nowrap) will display: Four Five << Six (or nothing if Five is the last item) git-svn-id: svn://svn.rockbox.org/rockbox/trunk@30502 a1c6a512-1295-4272-9138-f99709370657 --- apps/gui/bitmap/list-skinned.c | 57 ++++++++++++++++++++++++------------ apps/gui/list.h | 4 +-- apps/gui/skin_engine/skin_parser.c | 25 ++++++++++++++++ apps/gui/skin_engine/skin_tokens.c | 13 ++++++-- apps/gui/skin_engine/wps_internals.h | 5 ++++ 5 files changed, 80 insertions(+), 24 deletions(-) (limited to 'apps') diff --git a/apps/gui/bitmap/list-skinned.c b/apps/gui/bitmap/list-skinned.c index 2f3ca2bd2d..5f53784ccc 100644 --- a/apps/gui/bitmap/list-skinned.c +++ b/apps/gui/bitmap/list-skinned.c @@ -43,9 +43,8 @@ #include "appevents.h" static struct listitem_viewport_cfg *listcfg[NB_SCREENS] = {NULL}; -static const char *current_item_text_ptr; -static char current_item_text[MAX_PATH]; -static enum themable_icons current_item_icon; +struct gui_synclist *current_list; + void skinlist_set_cfg(enum screen_type screen, struct listitem_viewport_cfg *cfg) { @@ -54,7 +53,7 @@ void skinlist_set_cfg(enum screen_type screen, if (listcfg[screen]) screens[screen].scroll_stop(&listcfg[screen]->selected_item_vp.vp); listcfg[screen] = cfg; - current_item_text_ptr = ""; + current_list = NULL; } } @@ -64,15 +63,41 @@ static bool skinlist_is_configured(enum screen_type screen, return (listcfg[screen] != NULL) && (!list || (list && list->selected_size == 1)); } - -const char* skinlist_get_item_text(void) +static int current_drawing_line; +static int offset_to_item(int offset, bool wrap) +{ + int item = current_drawing_line + offset; + if (!current_list) + return -1; + if (item < 0) + { + if (!wrap) + return -1; + else + item = (item + current_list->nb_items) % current_list->nb_items; + } + else if (item >= current_list->nb_items && !wrap) + return -1; + else + item = item % current_list->nb_items; + return item; +} +const char* skinlist_get_item_text(int offset, bool wrap, char* buf, size_t buf_size) { - const char* ret = P2STR((unsigned char*)current_item_text_ptr); - return ret; + int item = offset_to_item(offset, wrap); + if (item < 0 || !current_list) + return NULL; + const char* ret = current_list->callback_get_item_name( + item, current_list->data, buf, buf_size); + return P2STR((unsigned char*)ret); } -enum themable_icons skinlist_get_item_icon(void) + +enum themable_icons skinlist_get_item_icon(int offset, bool wrap) { - return current_item_icon; + int item = offset_to_item(offset, wrap); + if (item < 0 || !current_list || current_list->callback_get_item_icon == NULL) + return Icon_NOICON; + return current_list->callback_get_item_icon(item, current_list->data); } static bool is_selected = false; @@ -130,6 +155,7 @@ bool skinlist_draw(struct screen *display, struct gui_synclist *list) struct gui_wps wps; if (!skinlist_is_configured(screen, list)) return false; + current_list = list; wps.display = display; wps.data = listcfg[screen]->data; display_lines = skinlist_get_line_count(screen, list); @@ -146,14 +172,9 @@ bool skinlist_draw(struct screen *display, struct gui_synclist *list) struct skin_viewport* skin_viewport; if (list_start_item+cur_line+1 > list->nb_items) break; + current_drawing_line = list_start_item+cur_line; is_selected = list->show_selection_marker && list_start_item+cur_line == list->selected_item; - current_item_text_ptr = list->callback_get_item_name( - list_start_item+cur_line, - list->data, current_item_text, MAX_PATH); - if (list->callback_get_item_icon != NULL) - current_item_icon = list->callback_get_item_icon( - list_start_item+cur_line, list->data); for (viewport = listcfg[screen]->data->tree; viewport; @@ -219,9 +240,7 @@ bool skinlist_draw(struct screen *display, struct gui_synclist *list) } display->set_viewport(parent); display->update_viewport(); - current_item_text_ptr = list->callback_get_item_name( - list->selected_item, - list->data, current_item_text, 2048); + current_drawing_line = list->selected_item; #if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP) /* Abuse the callback to force the sbs to update */ send_event(LCD_EVENT_ACTIVATION, NULL); diff --git a/apps/gui/list.h b/apps/gui/list.h index b54e7d7f5b..7c64987abb 100644 --- a/apps/gui/list.h +++ b/apps/gui/list.h @@ -189,8 +189,8 @@ bool skinlist_draw(struct screen *display, struct gui_synclist *list); bool skinlist_is_selected_item(void); void skinlist_set_cfg(enum screen_type screen, struct listitem_viewport_cfg *cfg); -const char* skinlist_get_item_text(void); -enum themable_icons skinlist_get_item_icon(void); +const char* skinlist_get_item_text(int offset, bool wrap, char* buf, size_t buf_size); +enum themable_icons skinlist_get_item_icon(int offset, bool wrap); bool skinlist_needs_scrollbar(enum screen_type screen); void skinlist_get_scrollbar(int* nb_item, int* first_shown, int* last_shown); int skinlist_get_line_count(enum screen_type screen, struct gui_synclist *list); diff --git a/apps/gui/skin_engine/skin_parser.c b/apps/gui/skin_engine/skin_parser.c index 0db19645bc..dd34d84e9f 100644 --- a/apps/gui/skin_engine/skin_parser.c +++ b/apps/gui/skin_engine/skin_parser.c @@ -485,6 +485,27 @@ static int parse_viewport_gradient_setup(struct skin_element *element, } #endif +static int parse_listitem(struct skin_element *element, + struct wps_token *token, + struct wps_data *wps_data) +{ + (void)wps_data; + struct listitem *li = (struct listitem *)skin_buffer_alloc(sizeof(struct listitem)); + if (!li) + return 1; + token->value.data = li; + if (element->params_count == 0) + li->offset = 0; + else + { + li->offset = element->params[0].data.number; + if (element->params_count > 1) + li->wrap = strcasecmp(element->params[1].data.text, "nowrap") != 0; + else + li->wrap = true; + } + return 0; +} static int parse_listitemviewport(struct skin_element *element, struct wps_token *token, @@ -1827,6 +1848,10 @@ static int skin_element_callback(struct skin_element* element, void* data) case SKIN_TOKEN_TRACK_ENDING: function = parse_timeout_tag; break; + case SKIN_TOKEN_LIST_ITEM_TEXT: + case SKIN_TOKEN_LIST_ITEM_ICON: + function = parse_listitem; + break; #ifdef HAVE_LCD_BITMAP case SKIN_TOKEN_DISABLE_THEME: case SKIN_TOKEN_ENABLE_THEME: diff --git a/apps/gui/skin_engine/skin_tokens.c b/apps/gui/skin_engine/skin_tokens.c index 371db46017..a4f0814945 100644 --- a/apps/gui/skin_engine/skin_tokens.c +++ b/apps/gui/skin_engine/skin_tokens.c @@ -922,14 +922,21 @@ const char *get_token_value(struct gui_wps *gwps, snprintf(buf, buf_size, "%d",sb_get_icon(gwps->display->screen_type)); return buf; case SKIN_TOKEN_LIST_ITEM_TEXT: - return skinlist_get_item_text(); + { + struct listitem *li = (struct listitem *)token->value.data; + return skinlist_get_item_text(li->offset, li->wrap, buf, buf_size); + } case SKIN_TOKEN_LIST_ITEM_IS_SELECTED: return skinlist_is_selected_item()?"s":""; case SKIN_TOKEN_LIST_ITEM_ICON: + { + struct listitem *li = (struct listitem *)token->value.data; + int icon = skinlist_get_item_icon(li->offset, li->wrap); if (intval) - *intval = skinlist_get_item_icon(); - snprintf(buf, buf_size, "%d",skinlist_get_item_icon()); + *intval = icon; + snprintf(buf, buf_size, "%d", icon); return buf; + } case SKIN_TOKEN_LIST_NEEDS_SCROLLBAR: return skinlist_needs_scrollbar(gwps->display->screen_type) ? "s" : ""; #endif diff --git a/apps/gui/skin_engine/wps_internals.h b/apps/gui/skin_engine/wps_internals.h index 7d7afe95b1..244d08595e 100644 --- a/apps/gui/skin_engine/wps_internals.h +++ b/apps/gui/skin_engine/wps_internals.h @@ -294,6 +294,11 @@ struct substring { struct wps_token *token; }; +struct listitem { + bool wrap; + short offset; +}; + #ifdef HAVE_SKIN_VARIABLES struct skin_var { const char *label; -- cgit v1.2.3