2010-07-29 12:37:48 +00:00
|
|
|
/***************************************************************************
|
|
|
|
* __________ __ ___.
|
|
|
|
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
|
|
|
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
|
|
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
|
|
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
|
|
|
* \/ \/ \/ \/ \/
|
|
|
|
* $Id: skin_parser.c 26752 2010-06-10 21:22:16Z bieber $
|
|
|
|
*
|
|
|
|
* Copyright (C) 2010 Jonathan Gordon
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
|
|
|
* KIND, either express or implied.
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdbool.h>
|
|
|
|
#include <ctype.h>
|
|
|
|
#include "strlcat.h"
|
|
|
|
|
|
|
|
#include "config.h"
|
2011-11-15 14:11:08 +00:00
|
|
|
#include "core_alloc.h"
|
2010-07-29 12:37:48 +00:00
|
|
|
#include "kernel.h"
|
2012-03-20 10:27:33 +00:00
|
|
|
#include "appevents.h"
|
2010-07-29 12:37:48 +00:00
|
|
|
#ifdef HAVE_ALBUMART
|
|
|
|
#include "albumart.h"
|
|
|
|
#endif
|
2011-09-24 13:19:34 +00:00
|
|
|
#include "settings.h"
|
2010-07-29 12:37:48 +00:00
|
|
|
#include "skin_display.h"
|
|
|
|
#include "skin_engine.h"
|
|
|
|
#include "skin_parser.h"
|
|
|
|
#include "tag_table.h"
|
|
|
|
#include "skin_scan.h"
|
|
|
|
#if CONFIG_TUNER
|
|
|
|
#include "radio.h"
|
|
|
|
#endif
|
2010-08-14 15:17:59 +00:00
|
|
|
#include "viewport.h"
|
|
|
|
#include "cuesheet.h"
|
2010-07-29 12:37:48 +00:00
|
|
|
#include "language.h"
|
|
|
|
#include "playback.h"
|
2010-08-14 15:17:59 +00:00
|
|
|
#include "playlist.h"
|
2010-08-14 15:23:07 +00:00
|
|
|
#include "root_menu.h"
|
2010-08-14 15:17:59 +00:00
|
|
|
#include "misc.h"
|
Lists can now be completly draw using the skin engine!
due to lack of user feedback the actual tags may change, hopefully not though.
The way it works is the skin specifies a rectangle and a viewport label. For each item in the list that is being displayed all viewports with the specified label are drawn. However, instead of the viewport x/y position being offset from the top left corner like normal they are offset from the rectangle position in the list (so think of them as child-viewports of the rectangle which moves).
Normally the rectangle will move down the screen to show a normal list, this can be changed to move across the screen in a grid pattern.
The UI viewport is used to bound the items (i.e %Vi() )
Scrolling is completly disabled in all items except the currently selected item.
This works well in combination with the %cs tag to show differently styled lists based on the current screen :)
New tags:
%LT - Get the current items text
%LI - Get the current items icon number
%Lc - Use as a conditional to determine if the current item is the selected item
%LB - BAR TAG to show the scroll bar, params/options like other bar types. It still needs a bit of work though. Use as a conditional to find out if the bar is actually needed
%Lb(viewport, width, height [,tile]) - specify the viewport label to draw for each item and the size of each item. if the last param is 'tile' it will form a grid instead of a list
example.sbs:
%?cs<%Lb(a,100,20)|>
%V(0,0,10,-,1)%Vf(aabbcc)
%?LB<%LB(0,0,10,185, invert)>
%Vi(-,10,0,-,-35,1)
%Vl(a,5,5,160,12,1)
%s%?Lc<%Vg(00ffaa, ff0000, 000000)%Vs(gradient)%>%>%>%ac>zzzzzzz %LT zzzzz%s%?Lc<%ar%<%<%<>
%V(0,185,-,-,1)
%s%LT
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@30461 a1c6a512-1295-4272-9138-f99709370657
2011-09-06 13:49:41 +00:00
|
|
|
#include "list.h"
|
2022-10-02 20:05:32 +00:00
|
|
|
#include "wps.h"
|
2010-07-29 12:37:48 +00:00
|
|
|
|
|
|
|
|
|
|
|
#define MAX_LINE 1024
|
|
|
|
|
|
|
|
struct skin_draw_info {
|
|
|
|
struct gui_wps *gwps;
|
|
|
|
struct skin_viewport *skin_vp;
|
|
|
|
int line_number;
|
|
|
|
unsigned long refresh_type;
|
2013-12-20 22:34:28 +00:00
|
|
|
struct line_desc line_desc;
|
2020-10-26 16:38:22 +00:00
|
|
|
|
2010-07-29 12:37:48 +00:00
|
|
|
char* cur_align_start;
|
|
|
|
struct align_pos align;
|
|
|
|
bool no_line_break;
|
|
|
|
bool line_scrolls;
|
|
|
|
bool force_redraw;
|
2020-10-26 16:38:22 +00:00
|
|
|
|
2010-07-29 12:37:48 +00:00
|
|
|
char *buf;
|
|
|
|
size_t buf_size;
|
2020-10-26 16:38:22 +00:00
|
|
|
|
2010-08-14 15:17:59 +00:00
|
|
|
int offset; /* used by the playlist viewer */
|
2010-07-29 12:37:48 +00:00
|
|
|
};
|
|
|
|
|
2022-10-02 17:02:27 +00:00
|
|
|
extern void sb_set_info_vp(enum screen_type screen, OFFSETTYPE(char*) label);
|
|
|
|
|
2010-07-29 12:37:48 +00:00
|
|
|
typedef bool (*skin_render_func)(struct skin_element* alternator, struct skin_draw_info *info);
|
|
|
|
bool skin_render_alternator(struct skin_element* alternator, struct skin_draw_info *info);
|
|
|
|
|
2010-08-14 15:17:59 +00:00
|
|
|
static void skin_render_playlistviewer(struct playlistviewer* viewer,
|
|
|
|
struct gui_wps *gwps,
|
|
|
|
struct skin_viewport* skin_viewport,
|
|
|
|
unsigned long refresh_type);
|
2010-07-29 12:37:48 +00:00
|
|
|
|
2011-11-15 14:11:08 +00:00
|
|
|
static char* skin_buffer;
|
|
|
|
|
|
|
|
static inline struct skin_element*
|
|
|
|
get_child(OFFSETTYPE(struct skin_element**) children, int child)
|
|
|
|
{
|
|
|
|
OFFSETTYPE(struct skin_element*) *kids = SKINOFFSETTOPTR(skin_buffer, children);
|
|
|
|
return SKINOFFSETTOPTR(skin_buffer, kids[child]);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-10-10 13:21:49 +00:00
|
|
|
static bool do_non_text_tags(struct gui_wps *gwps, struct skin_draw_info *info,
|
2022-10-04 13:35:16 +00:00
|
|
|
struct skin_element *element)
|
2010-07-29 12:37:48 +00:00
|
|
|
{
|
2011-11-15 14:11:08 +00:00
|
|
|
struct wps_token *token = (struct wps_token *)SKINOFFSETTOPTR(skin_buffer, element->data);
|
2020-10-27 15:14:23 +00:00
|
|
|
if (!token) return false;
|
2022-10-04 13:35:16 +00:00
|
|
|
struct skin_viewport *skin_vp = info->skin_vp;
|
2010-07-29 12:37:48 +00:00
|
|
|
struct wps_data *data = gwps->data;
|
|
|
|
bool do_refresh = (element->tag->flags & info->refresh_type) > 0;
|
2020-07-17 14:31:31 +00:00
|
|
|
|
2010-07-29 12:37:48 +00:00
|
|
|
switch (token->type)
|
2020-10-26 16:38:22 +00:00
|
|
|
{
|
2010-07-29 12:37:48 +00:00
|
|
|
#if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1))
|
|
|
|
case SKIN_TOKEN_VIEWPORT_FGCOLOUR:
|
|
|
|
{
|
2011-11-15 14:11:08 +00:00
|
|
|
struct viewport_colour *col = SKINOFFSETTOPTR(skin_buffer, token->value.data);
|
2020-10-27 15:14:23 +00:00
|
|
|
if (!col) return false;
|
2022-10-04 13:10:43 +00:00
|
|
|
skin_vp->vp.fg_pattern = col->colour;
|
2014-01-10 20:50:37 +00:00
|
|
|
skin_vp->fgbg_changed = true;
|
2010-07-29 12:37:48 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case SKIN_TOKEN_VIEWPORT_BGCOLOUR:
|
|
|
|
{
|
2011-11-15 14:11:08 +00:00
|
|
|
struct viewport_colour *col = SKINOFFSETTOPTR(skin_buffer, token->value.data);
|
2020-10-27 15:14:23 +00:00
|
|
|
if (!col) return false;
|
2022-10-04 13:10:43 +00:00
|
|
|
skin_vp->vp.bg_pattern = col->colour;
|
2014-01-10 20:50:37 +00:00
|
|
|
skin_vp->fgbg_changed = true;
|
2010-07-29 12:37:48 +00:00
|
|
|
}
|
|
|
|
break;
|
2011-08-14 13:50:07 +00:00
|
|
|
case SKIN_TOKEN_VIEWPORT_TEXTSTYLE:
|
2013-12-20 22:34:28 +00:00
|
|
|
{
|
|
|
|
struct line_desc *data = SKINOFFSETTOPTR(skin_buffer, token->value.data);
|
2014-01-07 21:46:45 +00:00
|
|
|
struct line_desc *linedes = &info->line_desc;
|
2020-10-27 15:14:23 +00:00
|
|
|
if (!data || !linedes) return false;
|
2013-12-20 22:34:28 +00:00
|
|
|
/* gradient colors are handled with a separate tag
|
|
|
|
* (SKIN_TOKEN_VIEWPORT_GRADIENT_SETUP, see below). since it may
|
|
|
|
* come before the text style tag color fields need to be preserved */
|
|
|
|
if (data->style & STYLE_GRADIENT)
|
|
|
|
{
|
2014-06-18 05:15:00 +00:00
|
|
|
unsigned tc = linedes->text_color,
|
|
|
|
lc = linedes->line_color,
|
|
|
|
lec = linedes->line_end_color;
|
2013-12-20 22:34:28 +00:00
|
|
|
*linedes = *data;
|
|
|
|
linedes->text_color = tc;
|
|
|
|
linedes->line_color = lc;
|
|
|
|
linedes->line_end_color = lec;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
*linedes = *data;
|
|
|
|
}
|
|
|
|
break;
|
2011-08-14 13:50:07 +00:00
|
|
|
#endif
|
|
|
|
#ifdef HAVE_LCD_COLOR
|
|
|
|
case SKIN_TOKEN_VIEWPORT_GRADIENT_SETUP:
|
|
|
|
{
|
2011-11-15 14:11:08 +00:00
|
|
|
struct gradient_config *cfg = SKINOFFSETTOPTR(skin_buffer, token->value.data);
|
2014-01-07 21:41:00 +00:00
|
|
|
struct line_desc *linedes = &info->line_desc;
|
2020-10-27 15:14:23 +00:00
|
|
|
if (!cfg || !linedes) return false;
|
2013-12-20 22:34:28 +00:00
|
|
|
linedes->text_color = cfg->text;
|
|
|
|
linedes->line_color = cfg->start;
|
|
|
|
linedes->line_end_color = cfg->end;
|
2011-08-14 13:50:07 +00:00
|
|
|
}
|
|
|
|
break;
|
2010-07-29 12:37:48 +00:00
|
|
|
#endif
|
|
|
|
case SKIN_TOKEN_VIEWPORT_ENABLE:
|
|
|
|
{
|
2011-11-15 14:11:08 +00:00
|
|
|
char *label = SKINOFFSETTOPTR(skin_buffer, token->value.data);
|
2010-07-29 12:37:48 +00:00
|
|
|
char temp = VP_DRAW_HIDEABLE;
|
2011-11-15 14:11:08 +00:00
|
|
|
struct skin_element *viewport = SKINOFFSETTOPTR(skin_buffer, gwps->data->tree);
|
2010-07-29 12:37:48 +00:00
|
|
|
while (viewport)
|
|
|
|
{
|
2011-11-15 14:11:08 +00:00
|
|
|
struct skin_viewport *skinvp = SKINOFFSETTOPTR(skin_buffer, viewport->data);
|
2020-10-26 16:38:22 +00:00
|
|
|
|
2020-10-27 15:14:23 +00:00
|
|
|
if (skinvp) {
|
|
|
|
char *vplabel = SKINOFFSETTOPTR(skin_buffer, skinvp->label);
|
|
|
|
if (skinvp->label == VP_DEFAULT_LABEL)
|
|
|
|
vplabel = VP_DEFAULT_LABEL_STRING;
|
|
|
|
if (vplabel && !skinvp->is_infovp &&
|
|
|
|
!strcmp(vplabel, label))
|
2010-07-29 12:37:48 +00:00
|
|
|
{
|
2020-10-27 15:14:23 +00:00
|
|
|
if (skinvp->hidden_flags&VP_DRAW_HIDDEN)
|
|
|
|
{
|
|
|
|
temp |= VP_DRAW_WASHIDDEN;
|
|
|
|
}
|
|
|
|
skinvp->hidden_flags = temp;
|
2020-10-26 16:38:22 +00:00
|
|
|
}
|
2010-07-29 12:37:48 +00:00
|
|
|
}
|
2011-11-15 14:11:08 +00:00
|
|
|
viewport = SKINOFFSETTOPTR(skin_buffer, viewport->next);
|
2010-07-29 12:37:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
Lists can now be completly draw using the skin engine!
due to lack of user feedback the actual tags may change, hopefully not though.
The way it works is the skin specifies a rectangle and a viewport label. For each item in the list that is being displayed all viewports with the specified label are drawn. However, instead of the viewport x/y position being offset from the top left corner like normal they are offset from the rectangle position in the list (so think of them as child-viewports of the rectangle which moves).
Normally the rectangle will move down the screen to show a normal list, this can be changed to move across the screen in a grid pattern.
The UI viewport is used to bound the items (i.e %Vi() )
Scrolling is completly disabled in all items except the currently selected item.
This works well in combination with the %cs tag to show differently styled lists based on the current screen :)
New tags:
%LT - Get the current items text
%LI - Get the current items icon number
%Lc - Use as a conditional to determine if the current item is the selected item
%LB - BAR TAG to show the scroll bar, params/options like other bar types. It still needs a bit of work though. Use as a conditional to find out if the bar is actually needed
%Lb(viewport, width, height [,tile]) - specify the viewport label to draw for each item and the size of each item. if the last param is 'tile' it will form a grid instead of a list
example.sbs:
%?cs<%Lb(a,100,20)|>
%V(0,0,10,-,1)%Vf(aabbcc)
%?LB<%LB(0,0,10,185, invert)>
%Vi(-,10,0,-,-35,1)
%Vl(a,5,5,160,12,1)
%s%?Lc<%Vg(00ffaa, ff0000, 000000)%Vs(gradient)%>%>%>%ac>zzzzzzz %LT zzzzz%s%?Lc<%ar%<%<%<>
%V(0,185,-,-,1)
%s%LT
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@30461 a1c6a512-1295-4272-9138-f99709370657
2011-09-06 13:49:41 +00:00
|
|
|
case SKIN_TOKEN_LIST_ITEM_CFG:
|
2012-02-21 13:59:52 +00:00
|
|
|
skinlist_set_cfg(gwps->display->screen_type,
|
|
|
|
SKINOFFSETTOPTR(skin_buffer, token->value.data));
|
Lists can now be completly draw using the skin engine!
due to lack of user feedback the actual tags may change, hopefully not though.
The way it works is the skin specifies a rectangle and a viewport label. For each item in the list that is being displayed all viewports with the specified label are drawn. However, instead of the viewport x/y position being offset from the top left corner like normal they are offset from the rectangle position in the list (so think of them as child-viewports of the rectangle which moves).
Normally the rectangle will move down the screen to show a normal list, this can be changed to move across the screen in a grid pattern.
The UI viewport is used to bound the items (i.e %Vi() )
Scrolling is completly disabled in all items except the currently selected item.
This works well in combination with the %cs tag to show differently styled lists based on the current screen :)
New tags:
%LT - Get the current items text
%LI - Get the current items icon number
%Lc - Use as a conditional to determine if the current item is the selected item
%LB - BAR TAG to show the scroll bar, params/options like other bar types. It still needs a bit of work though. Use as a conditional to find out if the bar is actually needed
%Lb(viewport, width, height [,tile]) - specify the viewport label to draw for each item and the size of each item. if the last param is 'tile' it will form a grid instead of a list
example.sbs:
%?cs<%Lb(a,100,20)|>
%V(0,0,10,-,1)%Vf(aabbcc)
%?LB<%LB(0,0,10,185, invert)>
%Vi(-,10,0,-,-35,1)
%Vl(a,5,5,160,12,1)
%s%?Lc<%Vg(00ffaa, ff0000, 000000)%Vs(gradient)%>%>%>%ac>zzzzzzz %LT zzzzz%s%?Lc<%ar%<%<%<>
%V(0,185,-,-,1)
%s%LT
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@30461 a1c6a512-1295-4272-9138-f99709370657
2011-09-06 13:49:41 +00:00
|
|
|
break;
|
2010-07-29 12:37:48 +00:00
|
|
|
case SKIN_TOKEN_UIVIEWPORT_ENABLE:
|
2011-11-15 14:11:08 +00:00
|
|
|
sb_set_info_vp(gwps->display->screen_type, token->value.data);
|
2010-07-29 12:37:48 +00:00
|
|
|
break;
|
|
|
|
case SKIN_TOKEN_PEAKMETER:
|
|
|
|
data->peak_meter_enabled = true;
|
|
|
|
if (do_refresh)
|
2022-10-04 13:35:16 +00:00
|
|
|
draw_peakmeters(gwps, info->line_number, &skin_vp->vp);
|
2010-07-29 12:37:48 +00:00
|
|
|
break;
|
2012-03-15 11:50:17 +00:00
|
|
|
case SKIN_TOKEN_DRAWRECTANGLE:
|
|
|
|
if (do_refresh)
|
|
|
|
{
|
|
|
|
struct draw_rectangle *rect =
|
|
|
|
SKINOFFSETTOPTR(skin_buffer, token->value.data);
|
2020-10-27 15:14:23 +00:00
|
|
|
if (!rect) break;
|
2012-03-15 11:50:17 +00:00
|
|
|
#ifdef HAVE_LCD_COLOR
|
|
|
|
if (rect->start_colour != rect->end_colour &&
|
2020-10-27 15:14:23 +00:00
|
|
|
gwps->display->screen_type == SCREEN_MAIN)
|
2012-03-15 11:50:17 +00:00
|
|
|
{
|
|
|
|
gwps->display->gradient_fillrect(rect->x, rect->y, rect->width,
|
2020-10-27 15:14:23 +00:00
|
|
|
rect->height, rect->start_colour, rect->end_colour);
|
2012-03-15 11:50:17 +00:00
|
|
|
}
|
|
|
|
else
|
2011-01-13 06:48:39 +00:00
|
|
|
#endif
|
2012-03-15 11:50:17 +00:00
|
|
|
{
|
2012-03-15 12:03:33 +00:00
|
|
|
#if LCD_DEPTH > 1
|
2022-10-04 13:35:16 +00:00
|
|
|
unsigned backup = skin_vp->vp.fg_pattern;
|
|
|
|
skin_vp->vp.fg_pattern = rect->start_colour;
|
2012-03-15 12:03:33 +00:00
|
|
|
#endif
|
2012-03-15 11:50:17 +00:00
|
|
|
gwps->display->fillrect(rect->x, rect->y, rect->width,
|
2020-10-27 15:14:23 +00:00
|
|
|
rect->height);
|
2012-03-15 12:03:33 +00:00
|
|
|
#if LCD_DEPTH > 1
|
2022-10-04 13:35:16 +00:00
|
|
|
skin_vp->vp.fg_pattern = backup;
|
2012-03-15 12:03:33 +00:00
|
|
|
#endif
|
2012-03-15 11:50:17 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2011-01-13 06:48:39 +00:00
|
|
|
case SKIN_TOKEN_PEAKMETER_LEFTBAR:
|
|
|
|
case SKIN_TOKEN_PEAKMETER_RIGHTBAR:
|
|
|
|
data->peak_meter_enabled = true;
|
|
|
|
/* fall through to the progressbar code */
|
2010-07-29 12:37:48 +00:00
|
|
|
case SKIN_TOKEN_VOLUMEBAR:
|
|
|
|
case SKIN_TOKEN_BATTERY_PERCENTBAR:
|
2012-07-05 12:44:13 +00:00
|
|
|
case SKIN_TOKEN_SETTINGBAR:
|
2010-07-29 12:37:48 +00:00
|
|
|
case SKIN_TOKEN_PROGRESSBAR:
|
2010-11-18 11:47:42 +00:00
|
|
|
case SKIN_TOKEN_TUNER_RSSI_BAR:
|
Lists can now be completly draw using the skin engine!
due to lack of user feedback the actual tags may change, hopefully not though.
The way it works is the skin specifies a rectangle and a viewport label. For each item in the list that is being displayed all viewports with the specified label are drawn. However, instead of the viewport x/y position being offset from the top left corner like normal they are offset from the rectangle position in the list (so think of them as child-viewports of the rectangle which moves).
Normally the rectangle will move down the screen to show a normal list, this can be changed to move across the screen in a grid pattern.
The UI viewport is used to bound the items (i.e %Vi() )
Scrolling is completly disabled in all items except the currently selected item.
This works well in combination with the %cs tag to show differently styled lists based on the current screen :)
New tags:
%LT - Get the current items text
%LI - Get the current items icon number
%Lc - Use as a conditional to determine if the current item is the selected item
%LB - BAR TAG to show the scroll bar, params/options like other bar types. It still needs a bit of work though. Use as a conditional to find out if the bar is actually needed
%Lb(viewport, width, height [,tile]) - specify the viewport label to draw for each item and the size of each item. if the last param is 'tile' it will form a grid instead of a list
example.sbs:
%?cs<%Lb(a,100,20)|>
%V(0,0,10,-,1)%Vf(aabbcc)
%?LB<%LB(0,0,10,185, invert)>
%Vi(-,10,0,-,-35,1)
%Vl(a,5,5,160,12,1)
%s%?Lc<%Vg(00ffaa, ff0000, 000000)%Vs(gradient)%>%>%>%ac>zzzzzzz %LT zzzzz%s%?Lc<%ar%<%<%<>
%V(0,185,-,-,1)
%s%LT
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@30461 a1c6a512-1295-4272-9138-f99709370657
2011-09-06 13:49:41 +00:00
|
|
|
case SKIN_TOKEN_LIST_SCROLLBAR:
|
2010-07-29 12:37:48 +00:00
|
|
|
{
|
2011-11-15 14:11:08 +00:00
|
|
|
struct progressbar *bar = (struct progressbar*)SKINOFFSETTOPTR(skin_buffer, token->value.data);
|
2010-07-29 12:37:48 +00:00
|
|
|
if (do_refresh)
|
2022-10-04 13:08:24 +00:00
|
|
|
draw_progressbar(gwps, info->skin_vp, info->line_number, bar);
|
2010-07-29 12:37:48 +00:00
|
|
|
}
|
|
|
|
break;
|
2012-02-28 11:05:28 +00:00
|
|
|
case SKIN_TOKEN_IMAGE_DISPLAY:
|
|
|
|
{
|
|
|
|
struct gui_img *img = SKINOFFSETTOPTR(skin_buffer, token->value.data);
|
|
|
|
if (img && img->loaded && do_refresh)
|
|
|
|
img->display = 0;
|
|
|
|
}
|
|
|
|
break;
|
2010-08-12 13:27:10 +00:00
|
|
|
case SKIN_TOKEN_IMAGE_DISPLAY_LISTICON:
|
2010-07-29 12:37:48 +00:00
|
|
|
case SKIN_TOKEN_IMAGE_PRELOAD_DISPLAY:
|
2012-12-03 09:43:58 +00:00
|
|
|
case SKIN_TOKEN_IMAGE_DISPLAY_9SEGMENT:
|
2010-07-29 12:37:48 +00:00
|
|
|
{
|
2011-11-15 14:11:08 +00:00
|
|
|
struct image_display *id = SKINOFFSETTOPTR(skin_buffer, token->value.data);
|
2020-10-27 15:14:23 +00:00
|
|
|
if (!id) break;
|
2011-11-15 14:11:08 +00:00
|
|
|
const char* label = SKINOFFSETTOPTR(skin_buffer, id->label);
|
2011-03-07 12:45:45 +00:00
|
|
|
struct gui_img *img = skin_find_item(label,SKIN_FIND_IMAGE, data);
|
2010-07-29 12:37:48 +00:00
|
|
|
if (img && img->loaded)
|
2010-08-05 11:28:48 +00:00
|
|
|
{
|
2011-11-15 14:11:08 +00:00
|
|
|
if (SKINOFFSETTOPTR(skin_buffer, id->token) == NULL)
|
2010-08-05 11:28:48 +00:00
|
|
|
{
|
|
|
|
img->display = id->subimage;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
char buf[16];
|
|
|
|
const char *out;
|
2010-08-12 10:01:46 +00:00
|
|
|
int a = img->num_subimages;
|
2011-11-15 14:11:08 +00:00
|
|
|
out = get_token_value(gwps, SKINOFFSETTOPTR(skin_buffer, id->token),
|
|
|
|
info->offset, buf, sizeof(buf), &a);
|
2010-08-12 10:01:46 +00:00
|
|
|
|
2010-08-05 11:28:48 +00:00
|
|
|
/* NOTE: get_token_value() returns values starting at 1! */
|
|
|
|
if (a == -1)
|
|
|
|
a = (out && *out) ? 1 : 2;
|
2010-08-12 13:27:10 +00:00
|
|
|
if (token->type == SKIN_TOKEN_IMAGE_DISPLAY_LISTICON)
|
|
|
|
a -= 2; /* 2 is added in statusbar-skinned.c! */
|
|
|
|
else
|
|
|
|
a--;
|
2010-08-05 11:28:48 +00:00
|
|
|
a += id->offset;
|
2010-08-12 10:01:46 +00:00
|
|
|
|
|
|
|
/* Clear the image, as in conditionals */
|
|
|
|
clear_image_pos(gwps, img);
|
|
|
|
|
2010-08-05 11:28:48 +00:00
|
|
|
/* If the token returned a value which is higher than
|
2010-08-12 10:01:46 +00:00
|
|
|
* the amount of subimages, don't draw it. */
|
|
|
|
if (a >= 0 && a < img->num_subimages)
|
2010-08-05 11:28:48 +00:00
|
|
|
{
|
|
|
|
img->display = a;
|
2010-08-12 10:01:46 +00:00
|
|
|
}
|
2010-08-05 11:28:48 +00:00
|
|
|
}
|
|
|
|
}
|
2010-07-29 12:37:48 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
#ifdef HAVE_ALBUMART
|
|
|
|
case SKIN_TOKEN_ALBUMART_DISPLAY:
|
2011-11-15 14:11:08 +00:00
|
|
|
{
|
|
|
|
struct skin_albumart *aa = SKINOFFSETTOPTR(skin_buffer, data->albumart);
|
2010-07-29 12:37:48 +00:00
|
|
|
/* now draw the AA */
|
2011-11-15 14:11:08 +00:00
|
|
|
if (do_refresh && aa)
|
2010-07-29 12:37:48 +00:00
|
|
|
{
|
|
|
|
int handle = playback_current_aa_hid(data->playback_aa_slot);
|
2013-12-23 11:35:52 +00:00
|
|
|
#if CONFIG_TUNER
|
2010-07-29 12:37:48 +00:00
|
|
|
if (in_radio_screen() || (get_radio_status() != FMRADIO_OFF))
|
|
|
|
{
|
2011-11-15 14:11:08 +00:00
|
|
|
struct dim dim = {aa->width, aa->height};
|
2010-07-29 12:37:48 +00:00
|
|
|
handle = radio_get_art_hid(&dim);
|
|
|
|
}
|
2013-12-23 11:35:52 +00:00
|
|
|
#endif
|
2011-11-15 14:11:08 +00:00
|
|
|
aa->draw_handle = handle;
|
2010-07-29 12:37:48 +00:00
|
|
|
}
|
|
|
|
break;
|
2011-11-15 14:11:08 +00:00
|
|
|
}
|
2010-07-29 12:37:48 +00:00
|
|
|
#endif
|
|
|
|
case SKIN_TOKEN_DRAW_INBUILTBAR:
|
|
|
|
gui_statusbar_draw(&(statusbars.statusbars[gwps->display->screen_type]),
|
|
|
|
info->refresh_type == SKIN_REFRESH_ALL,
|
2011-11-15 14:11:08 +00:00
|
|
|
SKINOFFSETTOPTR(skin_buffer, token->value.data));
|
2010-07-29 12:37:48 +00:00
|
|
|
break;
|
|
|
|
case SKIN_TOKEN_VIEWPORT_CUSTOMLIST:
|
|
|
|
if (do_refresh)
|
2011-11-15 14:11:08 +00:00
|
|
|
skin_render_playlistviewer(SKINOFFSETTOPTR(skin_buffer, token->value.data), gwps,
|
2010-08-14 15:17:59 +00:00
|
|
|
info->skin_vp, info->refresh_type);
|
2010-07-29 12:37:48 +00:00
|
|
|
break;
|
2011-03-27 08:01:58 +00:00
|
|
|
#ifdef HAVE_SKIN_VARIABLES
|
|
|
|
case SKIN_TOKEN_VAR_SET:
|
|
|
|
{
|
2011-11-15 14:11:08 +00:00
|
|
|
struct skin_var_changer *data = SKINOFFSETTOPTR(skin_buffer, token->value.data);
|
|
|
|
struct skin_var *var = SKINOFFSETTOPTR(skin_buffer, data->var);
|
2011-03-27 08:01:58 +00:00
|
|
|
if (data->direct)
|
2011-11-15 14:11:08 +00:00
|
|
|
var->value = data->newval;
|
2011-03-27 08:01:58 +00:00
|
|
|
else
|
|
|
|
{
|
2011-11-15 14:11:08 +00:00
|
|
|
var->value += data->newval;
|
2011-03-27 08:01:58 +00:00
|
|
|
if (data->max)
|
|
|
|
{
|
2011-11-15 14:11:08 +00:00
|
|
|
if (var->value > data->max)
|
|
|
|
var->value = 1;
|
|
|
|
else if (var->value < 1)
|
|
|
|
var->value = data->max;
|
2011-03-27 08:01:58 +00:00
|
|
|
}
|
|
|
|
}
|
2011-11-15 14:11:08 +00:00
|
|
|
if (var->value < 1)
|
|
|
|
var->value = 1;
|
|
|
|
var->last_changed = current_tick;
|
2011-03-27 08:01:58 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
#endif
|
2010-07-29 12:37:48 +00:00
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2010-10-10 13:21:49 +00:00
|
|
|
static void do_tags_in_hidden_conditional(struct skin_element* branch,
|
2010-07-29 12:37:48 +00:00
|
|
|
struct skin_draw_info *info)
|
|
|
|
{
|
|
|
|
struct gui_wps *gwps = info->gwps;
|
|
|
|
struct wps_data *data = gwps->data;
|
2020-10-07 06:01:35 +00:00
|
|
|
|
2020-10-26 16:38:22 +00:00
|
|
|
/* Tags here are ones which need to be "turned off" or cleared
|
2010-07-29 12:37:48 +00:00
|
|
|
* if they are in a conditional branch which isnt being used */
|
|
|
|
if (branch->type == LINE_ALTERNATOR)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
for (i=0; i<branch->children_count; i++)
|
|
|
|
{
|
2011-11-15 14:11:08 +00:00
|
|
|
do_tags_in_hidden_conditional(get_child(branch->children, i), info);
|
2010-07-29 12:37:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (branch->type == LINE && branch->children_count)
|
|
|
|
{
|
2011-11-15 14:11:08 +00:00
|
|
|
struct skin_element *child = get_child(branch->children, 0);
|
2010-07-29 12:37:48 +00:00
|
|
|
struct wps_token *token;
|
|
|
|
while (child)
|
|
|
|
{
|
|
|
|
if (child->type == CONDITIONAL)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
for (i=0; i<child->children_count; i++)
|
|
|
|
{
|
2011-11-15 14:11:08 +00:00
|
|
|
do_tags_in_hidden_conditional(get_child(child->children, i), info);
|
2010-07-29 12:37:48 +00:00
|
|
|
}
|
2020-10-27 15:14:23 +00:00
|
|
|
goto skip;
|
2010-07-29 12:37:48 +00:00
|
|
|
}
|
2011-11-15 14:11:08 +00:00
|
|
|
else if (child->type != TAG || !SKINOFFSETTOPTR(skin_buffer, child->data))
|
2010-07-29 12:37:48 +00:00
|
|
|
{
|
2020-10-27 15:14:23 +00:00
|
|
|
goto skip;
|
2010-07-29 12:37:48 +00:00
|
|
|
}
|
2020-10-27 15:14:23 +00:00
|
|
|
|
2011-11-15 14:11:08 +00:00
|
|
|
token = (struct wps_token *)SKINOFFSETTOPTR(skin_buffer, child->data);
|
2020-10-27 15:14:23 +00:00
|
|
|
|
2010-07-29 12:37:48 +00:00
|
|
|
/* clear all pictures in the conditional and nested ones */
|
|
|
|
if (token->type == SKIN_TOKEN_IMAGE_PRELOAD_DISPLAY)
|
|
|
|
{
|
2011-11-15 14:11:08 +00:00
|
|
|
struct image_display *id = SKINOFFSETTOPTR(skin_buffer, token->value.data);
|
2020-10-27 15:14:23 +00:00
|
|
|
if (!id) goto skip;
|
|
|
|
|
2020-10-26 16:38:22 +00:00
|
|
|
struct gui_img *img = skin_find_item(SKINOFFSETTOPTR(skin_buffer, id->label),
|
2011-03-07 12:45:45 +00:00
|
|
|
SKIN_FIND_IMAGE, data);
|
2010-07-29 12:37:48 +00:00
|
|
|
clear_image_pos(gwps, img);
|
|
|
|
}
|
|
|
|
else if (token->type == SKIN_TOKEN_PEAKMETER)
|
|
|
|
{
|
|
|
|
data->peak_meter_enabled = false;
|
|
|
|
}
|
|
|
|
else if (token->type == SKIN_TOKEN_VIEWPORT_ENABLE)
|
|
|
|
{
|
2011-11-15 14:11:08 +00:00
|
|
|
char *label = SKINOFFSETTOPTR(skin_buffer, token->value.data);
|
2010-07-29 12:37:48 +00:00
|
|
|
struct skin_element *viewport;
|
2011-11-15 14:11:08 +00:00
|
|
|
for (viewport = SKINOFFSETTOPTR(skin_buffer, data->tree);
|
2010-07-29 12:37:48 +00:00
|
|
|
viewport;
|
2011-11-15 14:11:08 +00:00
|
|
|
viewport = SKINOFFSETTOPTR(skin_buffer, viewport->next))
|
2010-07-29 12:37:48 +00:00
|
|
|
{
|
2011-11-15 14:11:08 +00:00
|
|
|
struct skin_viewport *skin_viewport = SKINOFFSETTOPTR(skin_buffer, viewport->data);
|
2020-10-27 15:14:23 +00:00
|
|
|
if (!skin_viewport) continue;
|
2011-11-15 14:11:08 +00:00
|
|
|
char *vplabel = SKINOFFSETTOPTR(skin_buffer, skin_viewport->label);
|
|
|
|
if (skin_viewport->label == VP_DEFAULT_LABEL)
|
|
|
|
vplabel = VP_DEFAULT_LABEL_STRING;
|
|
|
|
if (vplabel && strcmp(vplabel, label))
|
2010-07-29 12:37:48 +00:00
|
|
|
continue;
|
|
|
|
if (skin_viewport->hidden_flags&VP_NEVER_VISIBLE)
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (skin_viewport->hidden_flags&VP_DRAW_HIDEABLE)
|
|
|
|
{
|
|
|
|
if (skin_viewport->hidden_flags&VP_DRAW_HIDDEN)
|
|
|
|
skin_viewport->hidden_flags |= VP_DRAW_WASHIDDEN;
|
|
|
|
else
|
|
|
|
{
|
2012-02-28 12:16:06 +00:00
|
|
|
#if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1))
|
2012-02-28 11:26:32 +00:00
|
|
|
if (skin_viewport->output_to_backdrop_buffer)
|
|
|
|
{
|
2020-10-07 06:01:35 +00:00
|
|
|
skin_backdrop_set_buffer(data->backdrop_id, skin_viewport);
|
2012-02-28 11:26:32 +00:00
|
|
|
skin_backdrop_show(-1);
|
2020-11-01 17:25:39 +00:00
|
|
|
gwps->display->set_viewport_ex(&skin_viewport->vp, VP_FLAG_VP_SET_CLEAN);
|
2020-10-28 14:32:17 +00:00
|
|
|
gwps->display->clear_viewport();
|
2020-11-01 17:25:39 +00:00
|
|
|
gwps->display->set_viewport_ex(&info->skin_vp->vp, VP_FLAG_VP_SET_CLEAN);
|
2020-10-28 14:32:17 +00:00
|
|
|
skin_backdrop_set_buffer(-1, skin_viewport);
|
|
|
|
skin_backdrop_show(data->backdrop_id);
|
2012-02-28 11:26:32 +00:00
|
|
|
}
|
2020-10-28 14:32:17 +00:00
|
|
|
else
|
2012-02-28 12:16:06 +00:00
|
|
|
#endif
|
2012-02-28 11:26:32 +00:00
|
|
|
{
|
2020-11-01 17:25:39 +00:00
|
|
|
gwps->display->set_viewport_ex(&skin_viewport->vp, VP_FLAG_VP_SET_CLEAN);
|
2020-10-28 14:32:17 +00:00
|
|
|
gwps->display->clear_viewport();
|
2020-11-01 17:25:39 +00:00
|
|
|
gwps->display->set_viewport_ex(&info->skin_vp->vp, VP_FLAG_VP_SET_CLEAN);
|
2012-02-28 11:26:32 +00:00
|
|
|
}
|
2020-10-28 14:32:17 +00:00
|
|
|
skin_viewport->hidden_flags |= VP_DRAW_HIDDEN;
|
2010-07-29 12:37:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#ifdef HAVE_ALBUMART
|
|
|
|
else if (data->albumart && token->type == SKIN_TOKEN_ALBUMART_DISPLAY)
|
|
|
|
{
|
|
|
|
draw_album_art(gwps,
|
|
|
|
playback_current_aa_hid(data->playback_aa_slot), true);
|
|
|
|
}
|
|
|
|
#endif
|
2020-10-27 15:14:23 +00:00
|
|
|
skip:
|
2011-11-15 14:11:08 +00:00
|
|
|
child = SKINOFFSETTOPTR(skin_buffer, child->next);
|
2010-07-29 12:37:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-10-26 16:38:22 +00:00
|
|
|
|
2010-10-10 13:21:49 +00:00
|
|
|
static void fix_line_alignment(struct skin_draw_info *info, struct skin_element *element)
|
2010-07-29 12:37:48 +00:00
|
|
|
{
|
|
|
|
struct align_pos *align = &info->align;
|
|
|
|
char *cur_pos = info->cur_align_start + strlen(info->cur_align_start);
|
2020-10-29 01:34:40 +00:00
|
|
|
char *next_pos = cur_pos + 1;
|
2010-07-29 12:37:48 +00:00
|
|
|
switch (element->tag->type)
|
|
|
|
{
|
|
|
|
case SKIN_TOKEN_ALIGN_LEFT:
|
2020-10-29 01:34:40 +00:00
|
|
|
align->left = next_pos;
|
|
|
|
info->cur_align_start = next_pos;
|
2010-07-29 12:37:48 +00:00
|
|
|
break;
|
|
|
|
case SKIN_TOKEN_ALIGN_LEFT_RTL:
|
2020-10-29 01:34:40 +00:00
|
|
|
if (UNLIKELY(lang_is_rtl()))
|
|
|
|
align->right = next_pos;
|
2010-07-29 12:37:48 +00:00
|
|
|
else
|
2020-10-29 01:34:40 +00:00
|
|
|
align->left = next_pos;
|
|
|
|
info->cur_align_start = next_pos;
|
2010-07-29 12:37:48 +00:00
|
|
|
break;
|
|
|
|
case SKIN_TOKEN_ALIGN_CENTER:
|
2020-10-29 01:34:40 +00:00
|
|
|
align->center = next_pos;
|
|
|
|
info->cur_align_start = next_pos;
|
2010-07-29 12:37:48 +00:00
|
|
|
break;
|
|
|
|
case SKIN_TOKEN_ALIGN_RIGHT:
|
2020-10-29 01:34:40 +00:00
|
|
|
align->right = next_pos;
|
|
|
|
info->cur_align_start = next_pos;
|
2010-07-29 12:37:48 +00:00
|
|
|
break;
|
|
|
|
case SKIN_TOKEN_ALIGN_RIGHT_RTL:
|
2020-10-29 01:34:40 +00:00
|
|
|
if (UNLIKELY(lang_is_rtl()))
|
|
|
|
align->left = next_pos;
|
2010-07-29 12:37:48 +00:00
|
|
|
else
|
2020-10-29 01:34:40 +00:00
|
|
|
align->right = next_pos;
|
|
|
|
info->cur_align_start = next_pos;
|
2010-07-29 12:37:48 +00:00
|
|
|
break;
|
|
|
|
default:
|
2020-10-29 01:34:40 +00:00
|
|
|
return;
|
2010-07-29 12:37:48 +00:00
|
|
|
}
|
2020-10-29 01:34:40 +00:00
|
|
|
*cur_pos = '\0';
|
|
|
|
*next_pos = '\0';
|
2010-07-29 12:37:48 +00:00
|
|
|
}
|
2020-10-26 16:38:22 +00:00
|
|
|
|
2010-07-29 12:37:48 +00:00
|
|
|
/* Draw a LINE element onto the display */
|
2010-10-10 13:21:49 +00:00
|
|
|
static bool skin_render_line(struct skin_element* line, struct skin_draw_info *info)
|
2010-07-29 12:37:48 +00:00
|
|
|
{
|
|
|
|
bool needs_update = false;
|
2020-11-01 17:25:39 +00:00
|
|
|
|
2010-07-29 12:37:48 +00:00
|
|
|
int last_value, value;
|
2020-10-26 16:38:22 +00:00
|
|
|
|
2010-07-29 12:37:48 +00:00
|
|
|
if (line->children_count == 0)
|
|
|
|
return false; /* empty line, do nothing */
|
2020-10-26 16:38:22 +00:00
|
|
|
|
2011-11-15 14:11:08 +00:00
|
|
|
struct skin_element *child = get_child(line->children, 0);
|
2010-07-29 12:37:48 +00:00
|
|
|
struct conditional *conditional;
|
|
|
|
skin_render_func func = skin_render_line;
|
|
|
|
int old_refresh_mode = info->refresh_type;
|
|
|
|
while (child)
|
|
|
|
{
|
|
|
|
switch (child->type)
|
|
|
|
{
|
|
|
|
case CONDITIONAL:
|
2011-11-15 14:11:08 +00:00
|
|
|
conditional = SKINOFFSETTOPTR(skin_buffer, child->data);
|
2020-10-27 15:14:23 +00:00
|
|
|
if (!conditional) break;
|
2010-07-29 12:37:48 +00:00
|
|
|
last_value = conditional->last_value;
|
2020-10-26 16:38:22 +00:00
|
|
|
value = evaluate_conditional(info->gwps, info->offset,
|
2010-08-14 15:17:59 +00:00
|
|
|
conditional, child->children_count);
|
2010-09-02 11:43:33 +00:00
|
|
|
conditional->last_value = value;
|
2010-07-29 12:37:48 +00:00
|
|
|
if (child->children_count == 1)
|
|
|
|
{
|
2020-10-26 16:38:22 +00:00
|
|
|
/* special handling so
|
2010-07-29 12:37:48 +00:00
|
|
|
* %?aa<true> and %?<true|false> need special handlng here */
|
2020-10-26 16:38:22 +00:00
|
|
|
|
2010-09-02 11:43:33 +00:00
|
|
|
if (value == -1) /* tag is false */
|
2010-07-29 12:37:48 +00:00
|
|
|
{
|
|
|
|
/* we are in a false branch of a %?aa<true> conditional */
|
|
|
|
if (last_value == 0)
|
2011-11-15 14:11:08 +00:00
|
|
|
do_tags_in_hidden_conditional(get_child(child->children, 0), info);
|
2010-07-29 12:37:48 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (last_value >= 0 && value != last_value && last_value < child->children_count)
|
2011-11-15 14:11:08 +00:00
|
|
|
do_tags_in_hidden_conditional(get_child(child->children, last_value), info);
|
2010-07-29 12:37:48 +00:00
|
|
|
}
|
2011-11-15 14:11:08 +00:00
|
|
|
if (get_child(child->children, value)->type == LINE_ALTERNATOR)
|
2010-07-29 12:37:48 +00:00
|
|
|
{
|
|
|
|
func = skin_render_alternator;
|
|
|
|
}
|
2011-11-15 14:11:08 +00:00
|
|
|
else if (get_child(child->children, value)->type == LINE)
|
2010-07-29 12:37:48 +00:00
|
|
|
func = skin_render_line;
|
2020-10-26 16:38:22 +00:00
|
|
|
|
2010-07-29 12:37:48 +00:00
|
|
|
if (value != last_value)
|
|
|
|
{
|
|
|
|
info->refresh_type = SKIN_REFRESH_ALL;
|
|
|
|
info->force_redraw = true;
|
|
|
|
}
|
2020-10-26 16:38:22 +00:00
|
|
|
|
2011-11-15 14:11:08 +00:00
|
|
|
if (func(get_child(child->children, value), info))
|
2010-07-29 12:37:48 +00:00
|
|
|
needs_update = true;
|
|
|
|
else
|
|
|
|
needs_update = needs_update || (last_value != value);
|
2020-10-26 16:38:22 +00:00
|
|
|
|
2010-07-29 12:37:48 +00:00
|
|
|
info->refresh_type = old_refresh_mode;
|
|
|
|
break;
|
|
|
|
case TAG:
|
2020-11-01 17:25:39 +00:00
|
|
|
|
2010-07-29 12:37:48 +00:00
|
|
|
if (child->tag->flags & NOBREAK)
|
|
|
|
info->no_line_break = true;
|
|
|
|
if (child->tag->type == SKIN_TOKEN_SUBLINE_SCROLL)
|
|
|
|
info->line_scrolls = true;
|
2020-10-26 16:38:22 +00:00
|
|
|
|
2010-07-29 12:37:48 +00:00
|
|
|
fix_line_alignment(info, child);
|
2020-10-26 16:38:22 +00:00
|
|
|
|
2011-11-15 14:11:08 +00:00
|
|
|
if (!SKINOFFSETTOPTR(skin_buffer, child->data))
|
2010-07-29 12:37:48 +00:00
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
2022-10-04 13:35:16 +00:00
|
|
|
if (!do_non_text_tags(info->gwps, info, child))
|
2010-07-29 12:37:48 +00:00
|
|
|
{
|
2010-09-26 06:43:33 +00:00
|
|
|
static char tempbuf[128];
|
2011-11-15 14:11:08 +00:00
|
|
|
const char *valuestr = get_token_value(info->gwps, SKINOFFSETTOPTR(skin_buffer, child->data),
|
2010-08-14 15:17:59 +00:00
|
|
|
info->offset, tempbuf,
|
|
|
|
sizeof(tempbuf), NULL);
|
Lists can now be completly draw using the skin engine!
due to lack of user feedback the actual tags may change, hopefully not though.
The way it works is the skin specifies a rectangle and a viewport label. For each item in the list that is being displayed all viewports with the specified label are drawn. However, instead of the viewport x/y position being offset from the top left corner like normal they are offset from the rectangle position in the list (so think of them as child-viewports of the rectangle which moves).
Normally the rectangle will move down the screen to show a normal list, this can be changed to move across the screen in a grid pattern.
The UI viewport is used to bound the items (i.e %Vi() )
Scrolling is completly disabled in all items except the currently selected item.
This works well in combination with the %cs tag to show differently styled lists based on the current screen :)
New tags:
%LT - Get the current items text
%LI - Get the current items icon number
%Lc - Use as a conditional to determine if the current item is the selected item
%LB - BAR TAG to show the scroll bar, params/options like other bar types. It still needs a bit of work though. Use as a conditional to find out if the bar is actually needed
%Lb(viewport, width, height [,tile]) - specify the viewport label to draw for each item and the size of each item. if the last param is 'tile' it will form a grid instead of a list
example.sbs:
%?cs<%Lb(a,100,20)|>
%V(0,0,10,-,1)%Vf(aabbcc)
%?LB<%LB(0,0,10,185, invert)>
%Vi(-,10,0,-,-35,1)
%Vl(a,5,5,160,12,1)
%s%?Lc<%Vg(00ffaa, ff0000, 000000)%Vs(gradient)%>%>%>%ac>zzzzzzz %LT zzzzz%s%?Lc<%ar%<%<%<>
%V(0,185,-,-,1)
%s%LT
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@30461 a1c6a512-1295-4272-9138-f99709370657
2011-09-06 13:49:41 +00:00
|
|
|
if (valuestr)
|
2010-07-29 12:37:48 +00:00
|
|
|
{
|
2010-08-15 14:35:34 +00:00
|
|
|
#if CONFIG_RTC
|
|
|
|
if (child->tag->flags&SKIN_RTC_REFRESH)
|
|
|
|
needs_update = needs_update || info->refresh_type&SKIN_REFRESH_DYNAMIC;
|
|
|
|
#endif
|
2020-10-26 16:38:22 +00:00
|
|
|
needs_update = needs_update ||
|
2010-07-29 12:37:48 +00:00
|
|
|
((child->tag->flags&info->refresh_type)!=0);
|
2020-10-26 16:38:22 +00:00
|
|
|
strlcat(info->cur_align_start, valuestr,
|
2010-07-29 12:37:48 +00:00
|
|
|
info->buf_size - (info->cur_align_start-info->buf));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case TEXT:
|
2020-10-26 16:38:22 +00:00
|
|
|
strlcat(info->cur_align_start, SKINOFFSETTOPTR(skin_buffer, child->data),
|
2010-07-29 12:37:48 +00:00
|
|
|
info->buf_size - (info->cur_align_start-info->buf));
|
2020-10-26 16:38:22 +00:00
|
|
|
needs_update = needs_update ||
|
2010-07-29 12:37:48 +00:00
|
|
|
(info->refresh_type&SKIN_REFRESH_STATIC) != 0;
|
|
|
|
break;
|
|
|
|
case COMMENT:
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2011-11-15 14:11:08 +00:00
|
|
|
child = SKINOFFSETTOPTR(skin_buffer, child->next);
|
2010-07-29 12:37:48 +00:00
|
|
|
}
|
|
|
|
return needs_update;
|
|
|
|
}
|
|
|
|
|
2010-10-10 13:21:49 +00:00
|
|
|
static int get_subline_timeout(struct gui_wps *gwps, struct skin_element* line)
|
2010-09-02 11:43:33 +00:00
|
|
|
{
|
|
|
|
struct skin_element *element=line;
|
|
|
|
struct wps_token *token;
|
2010-10-10 06:47:52 +00:00
|
|
|
int retval = DEFAULT_SUBLINE_TIME_MULTIPLIER*TIMEOUT_UNIT;
|
2010-09-02 11:43:33 +00:00
|
|
|
if (element->type == LINE)
|
2010-10-10 06:47:52 +00:00
|
|
|
{
|
|
|
|
if (element->children_count == 0)
|
|
|
|
return retval; /* empty line, so force redraw */
|
2011-11-15 14:11:08 +00:00
|
|
|
element = get_child(element->children, 0);
|
2010-10-10 06:47:52 +00:00
|
|
|
}
|
2010-09-02 11:43:33 +00:00
|
|
|
while (element)
|
|
|
|
{
|
|
|
|
if (element->type == TAG &&
|
|
|
|
element->tag->type == SKIN_TOKEN_SUBLINE_TIMEOUT )
|
|
|
|
{
|
2011-11-15 14:11:08 +00:00
|
|
|
token = SKINOFFSETTOPTR(skin_buffer, element->data);
|
2020-10-27 15:14:23 +00:00
|
|
|
if (token)
|
|
|
|
return token->value.i;
|
2010-09-02 11:43:33 +00:00
|
|
|
}
|
|
|
|
else if (element->type == CONDITIONAL)
|
|
|
|
{
|
2011-11-15 14:11:08 +00:00
|
|
|
struct conditional *conditional = SKINOFFSETTOPTR(skin_buffer, element->data);
|
2010-09-02 11:43:33 +00:00
|
|
|
int val = evaluate_conditional(gwps, 0, conditional,
|
|
|
|
element->children_count);
|
|
|
|
if (val >= 0)
|
|
|
|
{
|
2011-11-15 14:11:08 +00:00
|
|
|
retval = get_subline_timeout(gwps, get_child(element->children, val));
|
2010-09-02 11:43:33 +00:00
|
|
|
if (retval >= 0)
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
}
|
2011-11-15 14:11:08 +00:00
|
|
|
element = SKINOFFSETTOPTR(skin_buffer, element->next);
|
2010-09-02 11:43:33 +00:00
|
|
|
}
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
2010-10-10 13:21:49 +00:00
|
|
|
bool skin_render_alternator(struct skin_element* element, struct skin_draw_info *info)
|
2010-07-29 12:37:48 +00:00
|
|
|
{
|
|
|
|
bool changed_lines = false;
|
2011-11-15 14:11:08 +00:00
|
|
|
struct line_alternator *alternator = SKINOFFSETTOPTR(skin_buffer, element->data);
|
2010-07-29 12:37:48 +00:00
|
|
|
unsigned old_refresh = info->refresh_type;
|
|
|
|
if (info->refresh_type == SKIN_REFRESH_ALL)
|
|
|
|
{
|
2010-10-10 06:47:52 +00:00
|
|
|
alternator->current_line = element->children_count-1;
|
2010-07-29 12:37:48 +00:00
|
|
|
changed_lines = true;
|
|
|
|
}
|
2010-10-10 06:47:52 +00:00
|
|
|
else if (TIME_AFTER(current_tick, alternator->next_change_tick))
|
2010-07-29 12:37:48 +00:00
|
|
|
{
|
2010-10-10 06:47:52 +00:00
|
|
|
changed_lines = true;
|
2010-07-29 12:37:48 +00:00
|
|
|
}
|
2010-10-10 06:47:52 +00:00
|
|
|
|
2010-07-29 12:37:48 +00:00
|
|
|
if (changed_lines)
|
|
|
|
{
|
2011-06-12 22:17:45 +00:00
|
|
|
struct skin_element *current_line;
|
2010-09-02 11:43:33 +00:00
|
|
|
int start = alternator->current_line;
|
|
|
|
int try_line = start;
|
|
|
|
bool suitable = false;
|
2010-10-10 06:47:52 +00:00
|
|
|
int rettimeout = DEFAULT_SUBLINE_TIME_MULTIPLIER*TIMEOUT_UNIT;
|
2020-10-26 16:38:22 +00:00
|
|
|
|
2010-09-02 11:43:33 +00:00
|
|
|
/* find a subline which has at least one token in it,
|
|
|
|
* and that line doesnt have a timeout set to 0 through conditionals */
|
|
|
|
do {
|
|
|
|
try_line++;
|
|
|
|
if (try_line >= element->children_count)
|
|
|
|
try_line = 0;
|
2011-11-15 14:11:08 +00:00
|
|
|
if (get_child(element->children, try_line)->children_count != 0)
|
2010-09-02 11:43:33 +00:00
|
|
|
{
|
2011-11-15 14:11:08 +00:00
|
|
|
current_line = get_child(element->children, try_line);
|
2020-10-26 16:38:22 +00:00
|
|
|
rettimeout = get_subline_timeout(info->gwps,
|
2011-11-15 14:11:08 +00:00
|
|
|
get_child(current_line->children, 0));
|
2010-10-10 06:47:52 +00:00
|
|
|
if (rettimeout > 0)
|
2010-09-02 11:43:33 +00:00
|
|
|
{
|
|
|
|
suitable = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
while (try_line != start && !suitable);
|
2020-10-26 16:38:22 +00:00
|
|
|
|
2010-09-02 11:43:33 +00:00
|
|
|
if (suitable)
|
2010-10-10 06:47:52 +00:00
|
|
|
{
|
2010-09-02 11:43:33 +00:00
|
|
|
alternator->current_line = try_line;
|
2010-10-10 06:47:52 +00:00
|
|
|
alternator->next_change_tick = current_tick + rettimeout;
|
|
|
|
}
|
2010-09-02 11:43:33 +00:00
|
|
|
|
2010-07-29 12:37:48 +00:00
|
|
|
info->refresh_type = SKIN_REFRESH_ALL;
|
|
|
|
info->force_redraw = true;
|
|
|
|
}
|
2011-11-15 14:11:08 +00:00
|
|
|
bool ret = skin_render_line(get_child(element->children, alternator->current_line), info);
|
2010-07-29 12:37:48 +00:00
|
|
|
info->refresh_type = old_refresh;
|
|
|
|
return changed_lines || ret;
|
|
|
|
}
|
|
|
|
|
Lists can now be completly draw using the skin engine!
due to lack of user feedback the actual tags may change, hopefully not though.
The way it works is the skin specifies a rectangle and a viewport label. For each item in the list that is being displayed all viewports with the specified label are drawn. However, instead of the viewport x/y position being offset from the top left corner like normal they are offset from the rectangle position in the list (so think of them as child-viewports of the rectangle which moves).
Normally the rectangle will move down the screen to show a normal list, this can be changed to move across the screen in a grid pattern.
The UI viewport is used to bound the items (i.e %Vi() )
Scrolling is completly disabled in all items except the currently selected item.
This works well in combination with the %cs tag to show differently styled lists based on the current screen :)
New tags:
%LT - Get the current items text
%LI - Get the current items icon number
%Lc - Use as a conditional to determine if the current item is the selected item
%LB - BAR TAG to show the scroll bar, params/options like other bar types. It still needs a bit of work though. Use as a conditional to find out if the bar is actually needed
%Lb(viewport, width, height [,tile]) - specify the viewport label to draw for each item and the size of each item. if the last param is 'tile' it will form a grid instead of a list
example.sbs:
%?cs<%Lb(a,100,20)|>
%V(0,0,10,-,1)%Vf(aabbcc)
%?LB<%LB(0,0,10,185, invert)>
%Vi(-,10,0,-,-35,1)
%Vl(a,5,5,160,12,1)
%s%?Lc<%Vg(00ffaa, ff0000, 000000)%Vs(gradient)%>%>%>%ac>zzzzzzz %LT zzzzz%s%?Lc<%ar%<%<%<>
%V(0,185,-,-,1)
%s%LT
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@30461 a1c6a512-1295-4272-9138-f99709370657
2011-09-06 13:49:41 +00:00
|
|
|
void skin_render_viewport(struct skin_element* viewport, struct gui_wps *gwps,
|
|
|
|
struct skin_viewport* skin_viewport, unsigned long refresh_type)
|
2010-07-29 12:37:48 +00:00
|
|
|
{
|
|
|
|
struct screen *display = gwps->display;
|
|
|
|
char linebuf[MAX_LINE];
|
|
|
|
skin_render_func func = skin_render_line;
|
|
|
|
struct skin_element* line = viewport;
|
|
|
|
struct skin_draw_info info = {
|
|
|
|
.gwps = gwps,
|
|
|
|
.buf = linebuf,
|
|
|
|
.buf_size = sizeof(linebuf),
|
|
|
|
.line_number = 0,
|
|
|
|
.no_line_break = false,
|
|
|
|
.line_scrolls = false,
|
|
|
|
.refresh_type = refresh_type,
|
2010-08-14 15:17:59 +00:00
|
|
|
.skin_vp = skin_viewport,
|
2011-08-14 13:50:07 +00:00
|
|
|
.offset = 0,
|
2013-12-20 22:34:28 +00:00
|
|
|
.line_desc = LINE_DESC_DEFINIT,
|
2010-07-29 12:37:48 +00:00
|
|
|
};
|
2020-07-17 14:31:31 +00:00
|
|
|
|
2010-07-29 12:37:48 +00:00
|
|
|
struct align_pos * align = &info.align;
|
2014-01-10 20:50:37 +00:00
|
|
|
bool needs_update, update_all = false;
|
2011-11-15 14:11:08 +00:00
|
|
|
skin_buffer = get_skin_buffer(gwps->data);
|
2010-07-29 12:37:48 +00:00
|
|
|
/* Set images to not to be displayed */
|
2011-11-15 14:11:08 +00:00
|
|
|
struct skin_token_list *imglist = SKINOFFSETTOPTR(skin_buffer, gwps->data->images);
|
2010-07-29 12:37:48 +00:00
|
|
|
while (imglist)
|
|
|
|
{
|
2011-11-15 14:11:08 +00:00
|
|
|
struct wps_token *token = SKINOFFSETTOPTR(skin_buffer, imglist->token);
|
2020-10-27 15:14:23 +00:00
|
|
|
if (token) {
|
|
|
|
struct gui_img *img = (struct gui_img *)SKINOFFSETTOPTR(skin_buffer, token->value.data);
|
2020-10-28 14:32:17 +00:00
|
|
|
if (img)
|
2020-10-27 15:14:23 +00:00
|
|
|
img->display = -1;
|
|
|
|
}
|
2011-11-15 14:11:08 +00:00
|
|
|
imglist = SKINOFFSETTOPTR(skin_buffer, imglist->next);
|
2010-07-29 12:37:48 +00:00
|
|
|
}
|
2011-09-24 13:19:34 +00:00
|
|
|
|
|
|
|
/* fix font ID's */
|
|
|
|
if (skin_viewport->parsed_fontid == 1)
|
2011-11-08 10:09:33 +00:00
|
|
|
skin_viewport->vp.font = display->getuifont();
|
2014-01-10 20:50:37 +00:00
|
|
|
|
2010-07-29 12:37:48 +00:00
|
|
|
while (line)
|
|
|
|
{
|
|
|
|
linebuf[0] = '\0';
|
|
|
|
info.no_line_break = false;
|
|
|
|
info.line_scrolls = false;
|
|
|
|
info.force_redraw = false;
|
2014-01-10 20:50:37 +00:00
|
|
|
#if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1))
|
|
|
|
skin_viewport->fgbg_changed = false;
|
2011-08-14 13:50:07 +00:00
|
|
|
#ifdef HAVE_LCD_COLOR
|
2013-12-20 22:34:28 +00:00
|
|
|
if (info.line_desc.style&STYLE_GRADIENT)
|
2011-08-14 13:50:07 +00:00
|
|
|
{
|
2013-12-20 22:34:28 +00:00
|
|
|
if (++info.line_desc.line > info.line_desc.nlines)
|
|
|
|
info.line_desc.style = STYLE_DEFAULT;
|
2011-08-14 13:50:07 +00:00
|
|
|
}
|
2020-10-26 16:38:22 +00:00
|
|
|
#endif
|
2014-01-10 20:50:37 +00:00
|
|
|
#endif
|
2010-07-29 12:37:48 +00:00
|
|
|
info.cur_align_start = info.buf;
|
|
|
|
align->left = info.buf;
|
|
|
|
align->center = NULL;
|
|
|
|
align->right = NULL;
|
2020-10-26 16:38:22 +00:00
|
|
|
|
2010-07-29 12:37:48 +00:00
|
|
|
if (line->type == LINE_ALTERNATOR)
|
|
|
|
func = skin_render_alternator;
|
|
|
|
else if (line->type == LINE)
|
|
|
|
func = skin_render_line;
|
2014-01-10 20:50:37 +00:00
|
|
|
|
2010-07-29 12:37:48 +00:00
|
|
|
needs_update = func(line, &info);
|
2010-10-13 09:46:01 +00:00
|
|
|
#if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1))
|
2014-01-10 20:50:37 +00:00
|
|
|
if (skin_viewport->fgbg_changed)
|
2010-10-13 09:46:01 +00:00
|
|
|
{
|
2014-01-10 20:50:37 +00:00
|
|
|
/* if fg/bg changed due to a conditional tag the colors
|
|
|
|
* need to be set (2bit displays requires set_{fore,back}ground
|
|
|
|
* for this. the rest of the viewport needs to be redrawn
|
|
|
|
* to get the new colors */
|
|
|
|
display->set_foreground(skin_viewport->vp.fg_pattern);
|
|
|
|
display->set_background(skin_viewport->vp.bg_pattern);
|
|
|
|
if (needs_update)
|
|
|
|
update_all = true;
|
2010-10-13 09:46:01 +00:00
|
|
|
}
|
|
|
|
#endif
|
2010-07-29 12:37:48 +00:00
|
|
|
/* only update if the line needs to be, and there is something to write */
|
2014-01-10 20:50:37 +00:00
|
|
|
if (refresh_type && (needs_update || update_all))
|
2010-07-29 12:37:48 +00:00
|
|
|
{
|
2012-03-26 11:24:43 +00:00
|
|
|
if (info.force_redraw)
|
2013-01-31 06:24:19 +00:00
|
|
|
display->scroll_stop_viewport_rect(&skin_viewport->vp,
|
|
|
|
0, info.line_number*display->getcharheight(),
|
|
|
|
skin_viewport->vp.width, display->getcharheight());
|
2011-12-14 12:53:19 +00:00
|
|
|
write_line(display, align, info.line_number,
|
2013-12-20 22:34:28 +00:00
|
|
|
info.line_scrolls, &info.line_desc);
|
2010-07-29 12:37:48 +00:00
|
|
|
}
|
|
|
|
if (!info.no_line_break)
|
|
|
|
info.line_number++;
|
2011-11-15 14:11:08 +00:00
|
|
|
line = SKINOFFSETTOPTR(skin_buffer, line->next);
|
2010-07-29 12:37:48 +00:00
|
|
|
}
|
|
|
|
wps_display_images(gwps, &skin_viewport->vp);
|
|
|
|
}
|
|
|
|
|
|
|
|
void skin_render(struct gui_wps *gwps, unsigned refresh_mode)
|
|
|
|
{
|
2020-10-07 06:01:35 +00:00
|
|
|
const int vp_is_appearing = (VP_DRAW_WASHIDDEN|VP_DRAW_HIDEABLE);
|
2010-07-29 12:37:48 +00:00
|
|
|
struct wps_data *data = gwps->data;
|
|
|
|
struct screen *display = gwps->display;
|
2020-10-26 16:38:22 +00:00
|
|
|
|
2011-06-12 22:17:45 +00:00
|
|
|
struct skin_element* viewport;
|
2010-07-29 12:37:48 +00:00
|
|
|
struct skin_viewport* skin_viewport;
|
2011-11-15 14:11:08 +00:00
|
|
|
char *label;
|
2020-10-26 16:38:22 +00:00
|
|
|
|
2010-07-29 12:37:48 +00:00
|
|
|
int old_refresh_mode = refresh_mode;
|
2011-11-15 14:11:08 +00:00
|
|
|
skin_buffer = get_skin_buffer(gwps->data);
|
2020-10-07 06:01:35 +00:00
|
|
|
|
|
|
|
/* Framebuffer is likely dirty */
|
|
|
|
if ((refresh_mode&SKIN_REFRESH_ALL) == SKIN_REFRESH_ALL)
|
|
|
|
{
|
2020-10-28 14:32:17 +00:00
|
|
|
/* should already be the default buffer */
|
|
|
|
struct viewport * first_vp = display->set_viewport_ex(NULL, 0);
|
2020-10-07 06:01:35 +00:00
|
|
|
if ((first_vp->flags & VP_FLAG_VP_SET_CLEAN) == VP_FLAG_VP_DIRTY &&
|
|
|
|
get_current_activity() == ACTIVITY_WPS) /* only clear if in WPS */
|
|
|
|
{
|
|
|
|
display->clear_viewport();
|
|
|
|
}
|
|
|
|
}
|
2020-10-28 14:32:17 +00:00
|
|
|
|
2011-11-15 14:11:08 +00:00
|
|
|
viewport = SKINOFFSETTOPTR(skin_buffer, data->tree);
|
2020-10-27 15:14:23 +00:00
|
|
|
if (!viewport) return;
|
2011-11-15 14:11:08 +00:00
|
|
|
skin_viewport = SKINOFFSETTOPTR(skin_buffer, viewport->data);
|
2020-10-27 15:14:23 +00:00
|
|
|
if (!skin_viewport) return;
|
2011-11-15 14:11:08 +00:00
|
|
|
label = SKINOFFSETTOPTR(skin_buffer, skin_viewport->label);
|
|
|
|
if (skin_viewport->label == VP_DEFAULT_LABEL)
|
|
|
|
label = VP_DEFAULT_LABEL_STRING;
|
|
|
|
if (label && SKINOFFSETTOPTR(skin_buffer, viewport->next) &&
|
|
|
|
!strcmp(label,VP_DEFAULT_LABEL_STRING))
|
2010-07-29 12:37:48 +00:00
|
|
|
refresh_mode = 0;
|
2020-10-26 16:38:22 +00:00
|
|
|
|
2011-11-15 14:11:08 +00:00
|
|
|
for (viewport = SKINOFFSETTOPTR(skin_buffer, data->tree);
|
2010-07-29 12:37:48 +00:00
|
|
|
viewport;
|
2011-11-15 14:11:08 +00:00
|
|
|
viewport = SKINOFFSETTOPTR(skin_buffer, viewport->next))
|
2010-07-29 12:37:48 +00:00
|
|
|
{
|
2020-10-27 15:14:23 +00:00
|
|
|
|
2010-07-29 12:37:48 +00:00
|
|
|
/* SETUP */
|
2011-11-15 14:11:08 +00:00
|
|
|
skin_viewport = SKINOFFSETTOPTR(skin_buffer, viewport->data);
|
2020-10-27 15:14:23 +00:00
|
|
|
if (!skin_viewport) continue;
|
2010-07-29 12:37:48 +00:00
|
|
|
unsigned vp_refresh_mode = refresh_mode;
|
|
|
|
#if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1)
|
2012-02-28 11:26:32 +00:00
|
|
|
if (skin_viewport->output_to_backdrop_buffer)
|
|
|
|
{
|
2020-10-07 06:01:35 +00:00
|
|
|
skin_backdrop_set_buffer(data->backdrop_id, skin_viewport);
|
2012-02-28 11:26:32 +00:00
|
|
|
skin_backdrop_show(-1);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-10-07 06:01:35 +00:00
|
|
|
skin_backdrop_set_buffer(-1, skin_viewport);
|
2012-02-28 11:26:32 +00:00
|
|
|
skin_backdrop_show(data->backdrop_id);
|
|
|
|
}
|
2010-07-29 12:37:48 +00:00
|
|
|
#endif
|
2020-10-26 16:38:22 +00:00
|
|
|
|
2010-07-29 12:37:48 +00:00
|
|
|
/* dont redraw the viewport if its disabled */
|
|
|
|
if (skin_viewport->hidden_flags&VP_NEVER_VISIBLE)
|
|
|
|
{ /* don't draw anything into this one */
|
|
|
|
vp_refresh_mode = 0;
|
|
|
|
}
|
|
|
|
else if ((skin_viewport->hidden_flags&VP_DRAW_HIDDEN))
|
|
|
|
{
|
|
|
|
skin_viewport->hidden_flags |= VP_DRAW_WASHIDDEN;
|
|
|
|
continue;
|
|
|
|
}
|
2020-10-07 06:01:35 +00:00
|
|
|
else if ((skin_viewport->hidden_flags & vp_is_appearing) == vp_is_appearing)
|
2010-07-29 12:37:48 +00:00
|
|
|
{
|
|
|
|
vp_refresh_mode = SKIN_REFRESH_ALL;
|
|
|
|
skin_viewport->hidden_flags = VP_DRAW_HIDEABLE;
|
|
|
|
}
|
2020-10-26 16:38:22 +00:00
|
|
|
|
2020-10-07 06:01:35 +00:00
|
|
|
display->set_viewport_ex(&skin_viewport->vp, VP_FLAG_VP_SET_CLEAN);
|
|
|
|
|
2010-07-29 12:37:48 +00:00
|
|
|
if ((vp_refresh_mode&SKIN_REFRESH_ALL) == SKIN_REFRESH_ALL)
|
|
|
|
{
|
|
|
|
display->clear_viewport();
|
|
|
|
}
|
|
|
|
/* render */
|
2010-10-12 09:36:59 +00:00
|
|
|
if (viewport->children_count)
|
2011-11-15 14:11:08 +00:00
|
|
|
skin_render_viewport(get_child(viewport->children, 0), gwps,
|
2010-10-12 09:36:59 +00:00
|
|
|
skin_viewport, vp_refresh_mode);
|
2010-07-29 12:37:48 +00:00
|
|
|
refresh_mode = old_refresh_mode;
|
|
|
|
}
|
2012-02-28 12:16:06 +00:00
|
|
|
#if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1))
|
2020-10-28 14:32:17 +00:00
|
|
|
skin_backdrop_set_buffer(-1, skin_viewport);
|
2012-02-28 11:26:32 +00:00
|
|
|
skin_backdrop_show(data->backdrop_id);
|
|
|
|
#endif
|
2012-03-20 10:27:33 +00:00
|
|
|
|
|
|
|
if (((refresh_mode&SKIN_REFRESH_ALL) == SKIN_REFRESH_ALL))
|
|
|
|
{
|
|
|
|
/* If this is the UI viewport then let the UI know
|
|
|
|
* to redraw itself */
|
|
|
|
send_event(GUI_EVENT_NEED_UI_UPDATE, NULL);
|
|
|
|
}
|
2020-10-28 14:32:17 +00:00
|
|
|
/* Restore the default viewport */
|
|
|
|
display->set_viewport_ex(NULL, VP_FLAG_VP_SET_CLEAN);
|
2010-07-29 12:37:48 +00:00
|
|
|
display->update();
|
|
|
|
}
|
2010-08-14 15:17:59 +00:00
|
|
|
|
2020-07-17 14:31:31 +00:00
|
|
|
static __attribute__((noinline))
|
Lists can now be completly draw using the skin engine!
due to lack of user feedback the actual tags may change, hopefully not though.
The way it works is the skin specifies a rectangle and a viewport label. For each item in the list that is being displayed all viewports with the specified label are drawn. However, instead of the viewport x/y position being offset from the top left corner like normal they are offset from the rectangle position in the list (so think of them as child-viewports of the rectangle which moves).
Normally the rectangle will move down the screen to show a normal list, this can be changed to move across the screen in a grid pattern.
The UI viewport is used to bound the items (i.e %Vi() )
Scrolling is completly disabled in all items except the currently selected item.
This works well in combination with the %cs tag to show differently styled lists based on the current screen :)
New tags:
%LT - Get the current items text
%LI - Get the current items icon number
%Lc - Use as a conditional to determine if the current item is the selected item
%LB - BAR TAG to show the scroll bar, params/options like other bar types. It still needs a bit of work though. Use as a conditional to find out if the bar is actually needed
%Lb(viewport, width, height [,tile]) - specify the viewport label to draw for each item and the size of each item. if the last param is 'tile' it will form a grid instead of a list
example.sbs:
%?cs<%Lb(a,100,20)|>
%V(0,0,10,-,1)%Vf(aabbcc)
%?LB<%LB(0,0,10,185, invert)>
%Vi(-,10,0,-,-35,1)
%Vl(a,5,5,160,12,1)
%s%?Lc<%Vg(00ffaa, ff0000, 000000)%Vs(gradient)%>%>%>%ac>zzzzzzz %LT zzzzz%s%?Lc<%ar%<%<%<>
%V(0,185,-,-,1)
%s%LT
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@30461 a1c6a512-1295-4272-9138-f99709370657
2011-09-06 13:49:41 +00:00
|
|
|
void skin_render_playlistviewer(struct playlistviewer* viewer,
|
|
|
|
struct gui_wps *gwps,
|
|
|
|
struct skin_viewport* skin_viewport,
|
|
|
|
unsigned long refresh_type)
|
2010-08-14 15:17:59 +00:00
|
|
|
{
|
|
|
|
struct screen *display = gwps->display;
|
|
|
|
char linebuf[MAX_LINE];
|
|
|
|
skin_render_func func = skin_render_line;
|
|
|
|
struct skin_element* line;
|
|
|
|
struct skin_draw_info info = {
|
|
|
|
.gwps = gwps,
|
|
|
|
.buf = linebuf,
|
|
|
|
.buf_size = sizeof(linebuf),
|
|
|
|
.line_number = 0,
|
|
|
|
.no_line_break = false,
|
|
|
|
.line_scrolls = false,
|
|
|
|
.refresh_type = refresh_type,
|
|
|
|
.skin_vp = skin_viewport,
|
2011-08-14 13:50:07 +00:00
|
|
|
.offset = viewer->start_offset,
|
2013-12-20 22:34:28 +00:00
|
|
|
.line_desc = LINE_DESC_DEFINIT,
|
2010-08-14 15:17:59 +00:00
|
|
|
};
|
2020-07-17 14:31:31 +00:00
|
|
|
|
2010-08-14 15:17:59 +00:00
|
|
|
struct align_pos * align = &info.align;
|
|
|
|
bool needs_update;
|
|
|
|
int cur_pos, start_item, max;
|
2022-10-04 13:02:44 +00:00
|
|
|
int nb_lines = viewport_get_nb_lines(&skin_viewport->vp);
|
2010-08-14 15:17:59 +00:00
|
|
|
#if CONFIG_TUNER
|
2011-06-01 14:41:49 +00:00
|
|
|
if (get_current_activity() == ACTIVITY_FM)
|
2010-08-14 15:17:59 +00:00
|
|
|
{
|
|
|
|
cur_pos = radio_current_preset();
|
|
|
|
start_item = cur_pos + viewer->start_offset;
|
|
|
|
max = start_item+radio_preset_count();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
{
|
2022-10-02 20:05:32 +00:00
|
|
|
struct wps_state *state = get_wps_state();
|
|
|
|
struct cuesheet *cue = state->id3 ? state->id3->cuesheet : NULL;
|
2010-08-14 15:17:59 +00:00
|
|
|
cur_pos = playlist_get_display_index();
|
|
|
|
max = playlist_amount()+1;
|
|
|
|
if (cue)
|
|
|
|
max += cue->track_count;
|
2020-10-26 16:38:22 +00:00
|
|
|
start_item = MAX(0, cur_pos + viewer->start_offset);
|
2010-08-14 15:17:59 +00:00
|
|
|
}
|
|
|
|
if (max-start_item > nb_lines)
|
|
|
|
max = start_item + nb_lines;
|
2020-10-26 16:38:22 +00:00
|
|
|
|
2011-11-15 14:11:08 +00:00
|
|
|
line = SKINOFFSETTOPTR(skin_buffer, viewer->line);
|
2010-08-14 15:17:59 +00:00
|
|
|
while (start_item < max)
|
|
|
|
{
|
|
|
|
linebuf[0] = '\0';
|
|
|
|
info.no_line_break = false;
|
|
|
|
info.line_scrolls = false;
|
|
|
|
info.force_redraw = false;
|
2020-10-26 16:38:22 +00:00
|
|
|
|
2010-08-14 15:17:59 +00:00
|
|
|
info.cur_align_start = info.buf;
|
|
|
|
align->left = info.buf;
|
|
|
|
align->center = NULL;
|
|
|
|
align->right = NULL;
|
2020-10-26 16:38:22 +00:00
|
|
|
|
|
|
|
|
2010-08-14 15:17:59 +00:00
|
|
|
if (line->type == LINE_ALTERNATOR)
|
|
|
|
func = skin_render_alternator;
|
|
|
|
else if (line->type == LINE)
|
|
|
|
func = skin_render_line;
|
2020-10-26 16:38:22 +00:00
|
|
|
|
2010-08-14 15:17:59 +00:00
|
|
|
needs_update = func(line, &info);
|
2020-10-26 16:38:22 +00:00
|
|
|
|
2010-08-14 15:17:59 +00:00
|
|
|
/* only update if the line needs to be, and there is something to write */
|
|
|
|
if (refresh_type && needs_update)
|
|
|
|
{
|
2022-10-04 13:02:44 +00:00
|
|
|
struct viewport *vp = &skin_viewport->vp;
|
2011-12-14 12:53:19 +00:00
|
|
|
if (!info.force_redraw)
|
2013-01-31 06:24:19 +00:00
|
|
|
display->scroll_stop_viewport_rect(vp,
|
|
|
|
0, info.line_number*display->getcharheight(),
|
|
|
|
vp->width, display->getcharheight());
|
2011-12-14 12:53:19 +00:00
|
|
|
write_line(display, align, info.line_number,
|
2013-12-20 22:34:28 +00:00
|
|
|
info.line_scrolls, &info.line_desc);
|
2010-08-14 15:17:59 +00:00
|
|
|
}
|
|
|
|
info.line_number++;
|
|
|
|
info.offset++;
|
|
|
|
start_item++;
|
|
|
|
}
|
|
|
|
}
|